1use std::{
4 collections::{BTreeMap, HashSet, VecDeque},
5 sync::Arc,
6 vec,
7};
8
9use rexlang_ast::expr::{
10 ClassDecl, ClassMethodSig, Decl, DeclareFnDecl, Expr, FnDecl, ImportClause, ImportDecl,
11 ImportItem, ImportPath, InstanceDecl, InstanceMethodImpl, NameRef, Pattern, Program, Scope,
12 Symbol, TypeConstraint, TypeDecl, TypeExpr, TypeVariant, Var, intern,
13};
14use rexlang_lexer::{
15 Token, Tokens,
16 span::{Position, Span, Spanned},
17};
18
19use crate::{error::ParserErr, op::Operator};
20use rexlang_util::GasMeter;
21
22pub struct Parser {
23 token_cursor: usize,
24 tokens: Vec<Token>,
25 eof: Span,
26 errors: Vec<ParserErr>,
27 limits: ParserLimits,
28 nesting_depth: usize,
29}
30
31#[derive(Clone, Copy, Debug)]
32pub struct ParserLimits {
33 pub max_nesting: Option<usize>,
34}
35
36impl ParserLimits {
37 pub fn unlimited() -> Self {
38 Self { max_nesting: None }
39 }
40
41 pub fn safe_defaults() -> Self {
42 Self {
43 max_nesting: Some(512),
44 }
45 }
46}
47
48impl Default for ParserLimits {
49 fn default() -> Self {
50 Self::unlimited()
51 }
52}
53
54impl Parser {
55 fn operator_token_name(token: &Token) -> Option<(&'static str, Span)> {
56 match token {
57 Token::Add(span, ..) => Some(("+", *span)),
58 Token::And(span, ..) => Some(("&&", *span)),
59 Token::Concat(span, ..) => Some(("++", *span)),
60 Token::Div(span, ..) => Some(("/", *span)),
61 Token::Eq(span, ..) => Some(("==", *span)),
62 Token::Ne(span, ..) => Some(("!=", *span)),
63 Token::Ge(span, ..) => Some((">=", *span)),
64 Token::Gt(span, ..) => Some((">", *span)),
65 Token::Le(span, ..) => Some(("<=", *span)),
66 Token::Lt(span, ..) => Some(("<", *span)),
67 Token::Mod(span, ..) => Some(("%", *span)),
68 Token::Mul(span, ..) => Some(("*", *span)),
69 Token::Or(span, ..) => Some(("||", *span)),
70 Token::Sub(span, ..) => Some(("-", *span)),
71 _ => None,
72 }
73 }
74
75 fn parse_value_name(&mut self) -> Result<(Symbol, Span), ParserErr> {
76 match self.current_token() {
77 Token::Ident(name, span, ..) => {
78 self.next_token();
79 Ok((intern(&name), span))
80 }
81 token => {
82 if let Some((name, span)) = Self::operator_token_name(&token) {
83 self.next_token();
84 Ok((intern(name), span))
85 } else {
86 Err(ParserErr::new(
87 *token.span(),
88 format!("expected identifier or operator name got {}", token),
89 ))
90 }
91 }
92 }
93 }
94
95 pub fn new(tokens: Tokens) -> Parser {
96 let mut parser = Parser {
97 token_cursor: 0,
98 tokens: tokens
99 .items
100 .into_iter()
101 .filter_map(|token| match token {
102 Token::Whitespace(..) => None,
103 token => Some(token),
104 })
105 .collect(),
106 eof: tokens.eof,
107 errors: Vec::new(),
108 limits: ParserLimits::default(),
109 nesting_depth: 0,
110 };
111 parser.strip_comments();
113 parser
114 }
115
116 pub fn set_limits(&mut self, limits: ParserLimits) {
117 self.limits = limits;
118 }
119
120 fn with_nesting<T>(
121 &mut self,
122 span: Span,
123 f: impl FnOnce(&mut Self) -> Result<T, ParserErr>,
124 ) -> Result<T, ParserErr> {
125 if let Some(max) = self.limits.max_nesting
126 && self.nesting_depth >= max
127 {
128 return Err(ParserErr::new(
129 span,
130 format!("maximum nesting depth exceeded (max {max})"),
131 ));
132 }
133 self.nesting_depth += 1;
134 let res = f(self);
135 self.nesting_depth = self.nesting_depth.saturating_sub(1);
136 res
137 }
138
139 fn skip_newlines(&mut self) {
140 while self.token_cursor < self.tokens.len() {
141 if matches!(self.tokens[self.token_cursor], Token::WhitespaceNewline(..)) {
142 self.token_cursor += 1;
143 continue;
144 }
145 break;
146 }
147 }
148
149 fn current_token(&mut self) -> Token {
150 self.skip_newlines();
151 if self.token_cursor < self.tokens.len() {
152 return self.tokens[self.token_cursor].clone();
153 }
154 Token::Eof(self.eof)
155 }
156
157 fn peek_token(&mut self, n: usize) -> Token {
158 self.skip_newlines();
159 let mut cursor = self.token_cursor;
160 let mut seen = 0usize;
161 while cursor < self.tokens.len() {
162 if matches!(self.tokens[cursor], Token::WhitespaceNewline(..)) {
163 cursor += 1;
164 continue;
165 }
166 if seen == n {
167 return self.tokens[cursor].clone();
168 }
169 seen += 1;
170 cursor += 1;
171 }
172 Token::Eof(self.eof)
173 }
174
175 fn next_token(&mut self) {
176 self.token_cursor += 1;
177 self.skip_newlines();
178 }
179
180 fn expect_colon(&mut self) -> Result<(), ParserErr> {
181 let token = self.current_token();
182 match token {
183 Token::Colon(..) => {
184 self.next_token();
185 Ok(())
186 }
187 token => Err(ParserErr::new(
188 *token.span(),
189 format!("expected `:` got {}", token),
190 )),
191 }
192 }
193
194 fn expect_assign(&mut self) -> Result<(), ParserErr> {
195 let token = self.current_token();
196 match token {
197 Token::Assign(..) => {
198 self.next_token();
199 Ok(())
200 }
201 token => Err(ParserErr::new(
202 *token.span(),
203 format!("expected `=` got {}", token),
204 )),
205 }
206 }
207
208 fn expect_paren_r(&mut self) -> Result<Span, ParserErr> {
209 let token = self.current_token();
210 match token {
211 Token::ParenR(span, ..) => {
212 self.next_token();
213 Ok(span)
214 }
215 token => Err(ParserErr::new(
216 *token.span(),
217 format!("expected `)` got {}", token),
218 )),
219 }
220 }
221
222 fn expect_ident(&mut self, what: &str) -> Result<(String, Span), ParserErr> {
223 match self.current_token() {
224 Token::Ident(name, span, ..) => {
225 self.next_token();
226 Ok((name, span))
227 }
228 token => Err(ParserErr::new(
229 *token.span(),
230 format!("expected {what} got {}", token),
231 )),
232 }
233 }
234
235 fn is_value_name_token(token: &Token) -> bool {
236 matches!(token, Token::Ident(..)) || Self::operator_token_name(token).is_some()
237 }
238
239 fn parse_layout_block<T>(
240 &mut self,
241 has_block: bool,
242 block_indent: Option<usize>,
243 mut parse_item: impl FnMut(&mut Self) -> Result<T, ParserErr>,
244 ) -> Result<Vec<T>, ParserErr> {
245 if !has_block {
246 return Ok(Vec::new());
247 }
248
249 let mut items = Vec::new();
250 loop {
251 let token = self.current_token();
252 if !Self::is_value_name_token(&token) {
253 break;
254 }
255 let span = *token.span();
256 if let Some(indent) = block_indent
257 && span.begin.column != indent
258 {
259 break;
260 }
261 items.push(parse_item(self)?);
262 }
263 Ok(items)
264 }
265
266 fn find_token_at_depth0(
267 &self,
268 start: usize,
269 end: usize,
270 mut matches: impl FnMut(&Token) -> bool,
271 ) -> Option<usize> {
272 let mut depth = 0usize;
273 let end = end.min(self.tokens.len());
274 for i in start..end {
275 match &self.tokens[i] {
276 Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..) => depth += 1,
277 Token::ParenR(..) | Token::BracketR(..) | Token::BraceR(..) => {
278 depth = depth.saturating_sub(1)
279 }
280 _ => {}
281 }
282 if depth == 0 && matches(&self.tokens[i]) {
283 return Some(i);
284 }
285 }
286 None
287 }
288
289 fn find_same_line_end(&self, start_idx: usize) -> Result<usize, ParserErr> {
290 let start_line = self
291 .tokens
292 .get(start_idx)
293 .ok_or_else(|| ParserErr::new(self.eof, "unexpected EOF".to_string()))?
294 .span()
295 .begin
296 .line;
297
298 let mut depth = 0usize;
299 let mut end_idx = start_idx;
300 for i in start_idx..self.tokens.len() {
301 let tok = &self.tokens[i];
302 if depth == 0 && tok.span().begin.line > start_line {
303 break;
304 }
305 match tok {
306 Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..) => depth += 1,
307 Token::ParenR(..) | Token::BracketR(..) | Token::BraceR(..) => {
308 depth = depth.saturating_sub(1)
309 }
310 _ => {}
311 }
312 end_idx = i + 1;
313 }
314 Ok(end_idx)
315 }
316
317 fn find_dedent_end(&self, start_idx: usize, base_indent: usize) -> Result<usize, ParserErr> {
318 let mut depth = 0usize;
319 let mut end_idx = start_idx;
320 for i in start_idx..self.tokens.len() {
321 let tok = &self.tokens[i];
322 match tok {
323 Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..) => depth += 1,
324 Token::ParenR(..) | Token::BracketR(..) | Token::BraceR(..) => {
325 depth = depth.saturating_sub(1)
326 }
327 Token::WhitespaceNewline(..) if depth == 0 => {
328 let mut j = i + 1;
329 while j < self.tokens.len()
330 && matches!(self.tokens[j], Token::WhitespaceNewline(..))
331 {
332 j += 1;
333 }
334 if j >= self.tokens.len() {
335 return Ok(i);
336 }
337 if self.tokens[j].span().begin.column <= base_indent {
338 return Ok(i);
339 }
340 }
341 _ => {}
342 }
343 end_idx = i + 1;
344 }
345 Ok(end_idx)
346 }
347
348 fn paren_group_has_top_level_comma(&self, paren_start: usize) -> bool {
349 let mut depth = 0usize;
350 for i in (paren_start + 1)..self.tokens.len() {
351 match self.tokens[i] {
352 Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..) => depth += 1,
353 Token::ParenR(..) | Token::BracketR(..) | Token::BraceR(..) => {
354 if depth == 0 {
355 break;
356 }
357 depth = depth.saturating_sub(1)
358 }
359 Token::Comma(..) if depth == 0 => return true,
360 _ => {}
361 }
362 }
363 false
364 }
365
366 fn paren_group_has_top_level_colon(&self, paren_start: usize) -> bool {
367 let mut depth = 0usize;
368 for i in (paren_start + 1)..self.tokens.len() {
369 match self.tokens[i] {
370 Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..) => depth += 1,
371 Token::ParenR(..) | Token::BracketR(..) | Token::BraceR(..) => {
372 if depth == 0 {
373 break;
374 }
375 depth = depth.saturating_sub(1)
376 }
377 Token::Colon(..) if depth == 0 => return true,
378 _ => {}
379 }
380 }
381 false
382 }
383
384 fn parse_legacy_param_group(&mut self) -> Result<Vec<(Var, TypeExpr)>, ParserErr> {
385 match self.current_token() {
386 Token::ParenL(..) => self.next_token(),
387 token => {
388 return Err(ParserErr::new(
389 *token.span(),
390 format!("expected `(` got {}", token),
391 ));
392 }
393 }
394
395 let mut params = Vec::new();
396 if matches!(self.current_token(), Token::ParenR(..)) {
397 self.next_token();
398 return Ok(params);
399 }
400
401 loop {
402 let (param_name, param_span) = self.expect_ident("parameter name")?;
403 self.expect_colon()?;
404
405 let ty_start = self.token_cursor;
406 let ty_end = self
407 .find_token_at_depth0(ty_start, self.tokens.len(), |t| {
408 matches!(t, Token::Comma(..) | Token::ParenR(..))
409 })
410 .ok_or_else(|| {
411 ParserErr::new(
412 self.eof,
413 "expected `,` or `)` after parameter type".to_string(),
414 )
415 })?;
416 let ann = self.parse_type_expr_slice(&self.tokens[ty_start..ty_end])?;
417 self.token_cursor = ty_end;
418 params.push((Var::with_span(param_span, param_name), ann));
419
420 match self.current_token() {
421 Token::Comma(..) => {
422 self.next_token();
423 continue;
424 }
425 Token::ParenR(..) => {
426 self.next_token();
427 break;
428 }
429 token => {
430 return Err(ParserErr::new(
431 *token.span(),
432 format!("expected `,` or `)` got {}", token),
433 ));
434 }
435 }
436 }
437
438 Ok(params)
439 }
440
441 fn next_token_raw(&mut self) {
448 self.token_cursor += 1;
449 }
450
451 fn strip_comments(&mut self) {
452 let mut cursor = 0;
453
454 while cursor < self.tokens.len() {
455 match self.tokens[cursor] {
456 Token::CommentL(..) => {
457 self.tokens.remove(cursor);
458 while cursor < self.tokens.len() {
459 if let Token::CommentR(..) = self.tokens[cursor] {
460 self.tokens.remove(cursor);
461 break;
462 }
463 self.tokens.remove(cursor);
464 }
465 }
466 _ => {
467 cursor += 1;
468 continue;
469 }
470 }
471 }
472 }
473
474 fn record_error(&mut self, e: ParserErr) {
475 self.errors.push(e);
476 }
477
478 fn parse_program_core(&mut self) -> Result<Program, Vec<ParserErr>> {
479 let mut decls = Vec::new();
480 loop {
481 let mut is_pub = false;
482 if let Token::Pub(..) = self.current_token() {
483 is_pub = true;
484 self.next_token();
485 }
486
487 match self.current_token() {
488 Token::Type(..) => match self.parse_type_decl(is_pub) {
489 Ok(decl) => decls.push(Decl::Type(decl)),
490 Err(e) => {
491 self.record_error(e);
492 break;
493 }
494 },
495 Token::Fn(..) => match self.parse_fn_decl(is_pub) {
496 Ok(decl) => decls.push(Decl::Fn(decl)),
497 Err(e) => {
498 self.record_error(e);
499 break;
500 }
501 },
502 Token::Declare(..) => match self.parse_declare_fn_decl_toplevel(is_pub) {
503 Ok(decl) => decls.push(Decl::DeclareFn(decl)),
504 Err(e) => {
505 self.record_error(e);
506 break;
507 }
508 },
509 Token::Import(..) => match self.parse_import_decl(is_pub) {
510 Ok(decl) => decls.push(Decl::Import(decl)),
511 Err(e) => {
512 self.record_error(e);
513 break;
514 }
515 },
516 Token::Class(..) => match self.parse_class_decl(is_pub) {
517 Ok(decl) => decls.push(Decl::Class(decl)),
518 Err(e) => {
519 self.record_error(e);
520 break;
521 }
522 },
523 Token::Instance(..) => match self.parse_instance_decl(is_pub) {
524 Ok(decl) => decls.push(Decl::Instance(decl)),
525 Err(e) => {
526 self.record_error(e);
527 break;
528 }
529 },
530 _ => break,
531 }
532 }
533
534 let expr = if matches!(self.current_token(), Token::Eof(..)) {
535 Expr::Tuple(self.eof, vec![])
538 } else {
539 match self.parse_expr() {
540 Ok(expr) => expr,
541 Err(e) => {
542 self.record_error(e);
543 return Err(self.errors.clone());
544 }
545 }
546 };
547
548 match self.current_token() {
551 Token::Eof(..) => {}
552 token => self.record_error(ParserErr::new(
553 *token.span(),
554 format!("unexpected {}", token),
555 )),
556 }
557
558 if !self.errors.is_empty() {
559 Err(self.errors.clone())
560 } else {
561 Ok(Program {
562 decls,
563 expr: Arc::new(expr),
564 })
565 }
566 }
567
568 pub fn parse_program(&mut self, gas: &mut GasMeter) -> Result<Program, Vec<ParserErr>> {
569 let token_cost = gas
570 .costs
571 .parse_token
572 .saturating_mul(self.tokens.len() as u64);
573 if let Err(e) = gas.charge(token_cost) {
574 return Err(vec![ParserErr::new(Span::default(), e.to_string())]);
575 }
576
577 let program = self.parse_program_core()?;
578 let expr_nodes = count_expr_nodes(program.expr.as_ref());
579 let decl_nodes = program.decls.len() as u64;
580 let node_cost = gas
581 .costs
582 .parse_node
583 .saturating_mul(expr_nodes.saturating_add(decl_nodes));
584 if let Err(e) = gas.charge(node_cost) {
585 return Err(vec![ParserErr::new(Span::default(), e.to_string())]);
586 }
587 Ok(program)
588 }
589
590 fn parse_expr(&mut self) -> Result<Expr, ParserErr> {
591 let span = *self.current_token().span();
592 self.with_nesting(span, |this| {
593 let lhs_expr = this.parse_unary_expr()?;
594 this.parse_binary_expr(lhs_expr)
595 })
596 }
597
598 fn parse_binary_expr(&mut self, lhs_expr: Expr) -> Result<Expr, ParserErr> {
599 let span = *lhs_expr.span();
600 self.with_nesting(span, move |this| {
601 let lhs_expr_span = lhs_expr.span();
602
603 let token = match this.current_token() {
605 Token::Eof(..) => return Ok(lhs_expr),
608 token => token,
609 };
610 let prec = token.precedence();
611
612 let operator = match token {
614 Token::Add(..) => Operator::Add,
615 Token::And(..) => Operator::And,
616 Token::Concat(..) => Operator::Concat,
617 Token::ColonColon(..) => {
618 let operator_span = token.span();
619 this.next_token();
620
621 let rhs_expr = this.parse_unary_expr()?;
622 let rhs_expr_span = *rhs_expr.span();
623
624 let next_binary_expr_takes_precedence = match this.current_token() {
625 Token::Eof(..) => false,
626 token if prec > token.precedence() => false,
627 token if prec == token.precedence() => !matches!(
628 token,
629 Token::Add(..)
630 | Token::And(..)
631 | Token::Concat(..)
632 | Token::Div(..)
633 | Token::Mul(..)
634 | Token::Mod(..)
635 | Token::Or(..)
636 | Token::Sub(..)
637 ),
638 _ => true,
639 };
640
641 let rhs_expr = if next_binary_expr_takes_precedence {
642 this.parse_binary_expr(rhs_expr)?
643 } else {
644 rhs_expr
645 };
646
647 let cons_span = Span::from_begin_end(lhs_expr_span.begin, operator_span.end);
648 let outer_span = Span::from_begin_end(lhs_expr_span.begin, rhs_expr_span.end);
649 return this.parse_binary_expr(Expr::App(
650 outer_span,
651 Arc::new(Expr::App(
652 cons_span,
653 Arc::new(Expr::Var(Var::with_span(*operator_span, "Cons"))),
654 Arc::new(lhs_expr),
655 )),
656 Arc::new(rhs_expr),
657 ));
658 }
659 Token::Div(..) => Operator::Div,
660 Token::Eq(..) => Operator::Eq,
661 Token::Ne(..) => Operator::Ne,
662 Token::Ge(..) => Operator::Ge,
663 Token::Gt(..) => Operator::Gt,
664 Token::Le(..) => Operator::Le,
665 Token::Lt(..) => Operator::Lt,
666 Token::Mod(..) => Operator::Mod,
667 Token::Mul(..) => Operator::Mul,
668 Token::Or(..) => Operator::Or,
669 Token::Sub(..) => Operator::Sub,
670 _ => {
671 return Ok(lhs_expr);
672 }
673 };
674 let operator_span = token.span();
675
676 this.next_token();
678
679 let rhs_expr = this.parse_unary_expr()?;
681 let rhs_expr_span = *rhs_expr.span();
682
683 let next_binary_expr_takes_precedence = match this.current_token() {
684 Token::Eof(..) => false,
686 token if prec > token.precedence() => false,
688 token if prec == token.precedence() => {
690 !matches!(
692 token,
693 Token::Add(..)
694 | Token::And(..)
695 | Token::Concat(..)
696 | Token::Div(..)
697 | Token::Mul(..)
698 | Token::Mod(..)
699 | Token::Or(..)
700 | Token::Sub(..)
701 )
702 }
703 _ => true,
705 };
706
707 let rhs_expr = if next_binary_expr_takes_precedence {
708 this.parse_binary_expr(rhs_expr)?
709 } else {
710 rhs_expr
711 };
712
713 let inner_span = Span::from_begin_end(lhs_expr_span.begin, operator_span.end);
714 let outer_span = Span::from_begin_end(lhs_expr_span.begin, rhs_expr_span.end);
715
716 this.parse_binary_expr(Expr::App(
717 outer_span,
718 Arc::new(Expr::App(
719 inner_span,
720 Arc::new(Expr::Var(Var::with_span(
721 *operator_span,
722 operator.to_string(),
723 ))),
724 Arc::new(lhs_expr),
725 )),
726 Arc::new(rhs_expr),
727 ))
728 })
729 }
730
731 fn parse_unary_expr(&mut self) -> Result<Expr, ParserErr> {
732 let mut call_base_expr = self.parse_postfix_expr()?;
734 let call_base_expr_span = *call_base_expr.span();
735
736 let mut call_arg_exprs = VecDeque::new();
737 loop {
738 let call_arg_expr = match self.current_token() {
739 Token::ParenL(..)
740 | Token::BracketL(..)
741 | Token::BraceL(..)
742 | Token::Bool(..)
743 | Token::Float(..)
744 | Token::Int(..)
745 | Token::String(..)
746 | Token::Question(..)
747 | Token::Ident(..)
748 | Token::BackSlash(..)
749 | Token::Let(..)
750 | Token::If(..)
751 | Token::Match(..) => self.parse_postfix_expr(),
752 _ => break,
753 }?;
754 call_arg_exprs.push_back(call_arg_expr);
755 }
756
757 while let Some(call_arg_expr) = call_arg_exprs.pop_front() {
758 let call_arg_expr_span_end = call_arg_expr.span().end;
759 call_base_expr = Expr::App(
760 Span::from_begin_end(call_base_expr_span.begin, call_arg_expr_span_end),
761 Arc::new(call_base_expr),
762 Arc::new(call_arg_expr),
763 );
764 }
765 while let Token::Is(..) = self.current_token() {
766 self.next_token();
767 let ann = self.parse_type_expr()?;
768 let span = Span::from_begin_end(call_base_expr.span().begin, ann.span().end);
769 call_base_expr = Expr::Ann(span, Arc::new(call_base_expr), ann);
770 }
771 Ok(call_base_expr)
772 }
773
774 fn parse_postfix_expr(&mut self) -> Result<Expr, ParserErr> {
775 let mut base = self.parse_atom_expr()?;
776 while let Token::Dot(..) = self.current_token() {
777 self.next_token();
778
779 let (field, end) = match self.current_token() {
780 Token::Ident(name, span, ..) => {
781 let name = intern(&name);
782 let end = span.end;
783 self.next_token();
784 (name, end)
785 }
786 Token::Int(value, span) => {
787 let name = intern(&value.to_string());
788 let end = span.end;
789 self.next_token();
790 (name, end)
791 }
792 token => {
793 return Err(ParserErr::new(
794 *token.span(),
795 "expected field name after `.`",
796 ));
797 }
798 };
799
800 let span = Span::from_begin_end(base.span().begin, end);
801 base = Expr::Project(span, Arc::new(base), field);
802 }
803 Ok(base)
804 }
805
806 fn parse_atom_expr(&mut self) -> Result<Expr, ParserErr> {
807 match self.current_token() {
808 Token::ParenL(..) => self.parse_paren_expr(),
809 Token::BracketL(..) => self.parse_bracket_expr(),
810 Token::BraceL(..) => self.parse_brace_expr(),
811 Token::Bool(..) => self.parse_literal_bool_expr(),
812 Token::Float(..) => self.parse_literal_float_expr(),
813 Token::Int(..) => self.parse_literal_int_expr(),
814 Token::String(..) => self.parse_literal_str_expr(),
815 Token::Question(..) => self.parse_hole_expr(),
816 Token::Ident(..) => self.parse_ident_expr(),
817 Token::BackSlash(..) => self.parse_lambda_expr(),
818 Token::Let(..) => self.parse_let_expr(),
819 Token::If(..) => self.parse_if_expr(),
820 Token::Match(..) => self.parse_match_expr(),
821 Token::Sub(..) => self.parse_neg_expr(),
822 Token::Eof(span) => Err(ParserErr::new(span, "unexpected EOF".to_string())),
823 token => Err(ParserErr::new(
824 *token.span(),
825 format!("unexpected {}", token),
826 )),
827 }
828 }
829
830 fn parse_paren_expr(&mut self) -> Result<Expr, ParserErr> {
831 let span_begin = match self.current_token() {
833 Token::ParenL(span, ..) => {
834 self.next_token();
835 span
836 }
837 token => {
838 return Err(ParserErr::new(
839 *token.span(),
840 format!("expected `(` got {}", token),
841 ));
842 }
843 };
844
845 self.with_nesting(span_begin, |this| {
846 let expr = match this.current_token() {
848 Token::ParenR(span, ..) => {
849 this.next_token();
850 return Ok(Expr::Tuple(
852 Span::from_begin_end(span_begin.begin, span.end),
853 vec![],
854 ));
855 }
856 Token::Add(span, ..) => {
857 this.next_token();
858 Expr::Var(Var::with_span(span, "+"))
859 }
860 Token::And(span, ..) => {
861 this.next_token();
862 Expr::Var(Var::with_span(span, "&&"))
863 }
864 Token::Concat(span, ..) => {
865 this.next_token();
866 Expr::Var(Var::with_span(span, "++"))
867 }
868 Token::Div(span, ..) => {
869 this.next_token();
870 Expr::Var(Var::with_span(span, "/"))
871 }
872 Token::Eq(span, ..) => {
873 this.next_token();
874 Expr::Var(Var::with_span(span, "=="))
875 }
876 Token::Ge(span, ..) => {
877 this.next_token();
878 Expr::Var(Var::with_span(span, ">="))
879 }
880 Token::Gt(span, ..) => {
881 this.next_token();
882 Expr::Var(Var::with_span(span, ">"))
883 }
884 Token::Le(span, ..) => {
885 this.next_token();
886 Expr::Var(Var::with_span(span, "<="))
887 }
888 Token::Lt(span, ..) => {
889 this.next_token();
890 Expr::Var(Var::with_span(span, "<"))
891 }
892 Token::Mod(span, ..) => {
893 this.next_token();
894 Expr::Var(Var::with_span(span, "%"))
895 }
896 Token::Mul(span, ..) => {
897 this.next_token();
898 Expr::Var(Var::with_span(span, "*"))
899 }
900 Token::Or(span, ..) => {
901 this.next_token();
902 Expr::Var(Var::with_span(span, "||"))
903 }
904 Token::Sub(span, ..) => {
905 if let Token::ParenR(..) = this.peek_token(1) {
906 this.next_token();
917 Expr::Var(Var::with_span(span, "-"))
918 } else {
919 this.parse_expr()?
920 }
921 }
922 _ => this.parse_expr()?,
923 };
924
925 let span_end = match this.current_token() {
927 Token::ParenR(span, ..) => {
928 this.next_token();
929 span
930 }
931 Token::Comma(..) => {
932 return this.parse_tuple(span_begin, expr);
934 }
935 token => {
936 this.record_error(ParserErr::new(*token.span(), "expected `)`"));
937 return Ok(expr);
938 }
939 };
940
941 let expr = expr.with_span_begin_end(span_begin.begin, span_end.end);
942 Ok(expr)
943 })
944 }
945
946 fn parse_tuple(&mut self, span_begin: Span, first_item: Expr) -> Result<Expr, ParserErr> {
947 let mut items = vec![Arc::new(first_item)];
948 loop {
949 match self.current_token() {
951 Token::Comma(..) => self.next_token(),
952 Token::ParenR(end_span) => {
953 self.next_token();
954 return Ok(Expr::Tuple(
955 Span::from_begin_end(span_begin.begin, end_span.end),
956 items,
957 ));
958 }
959 _ => items.push(Arc::new(self.parse_expr()?)),
960 }
961 }
962 }
963
964 fn parse_bracket_expr(&mut self) -> Result<Expr, ParserErr> {
965 let span_begin = match self.current_token() {
967 Token::BracketL(span, ..) => {
968 self.next_token();
969 span
970 }
971 token => {
972 return Err(ParserErr::new(
973 *token.span(),
974 format!("expected `[` got {}", token),
975 ));
976 }
977 };
978
979 self.with_nesting(span_begin, |this| {
980 let mut exprs = Vec::new();
981 loop {
982 if let Token::BracketR(..) = this.current_token() {
983 break;
984 }
985
986 exprs.push(Arc::new(this.parse_expr()?));
988 match this.current_token() {
990 Token::Comma(..) => this.next_token(),
991 Token::Eof(span) => {
992 this.record_error(ParserErr::new(span, "expected `,` or `]`"));
993 break;
994 }
995 _ => {
996 break;
997 }
998 };
999 }
1000
1001 let span_end = match this.current_token() {
1003 Token::BracketR(span, ..) => {
1004 this.next_token();
1005 span.end
1006 }
1007 token => {
1008 this.record_error(ParserErr::new(
1009 *token.span(),
1010 format!("expected `]` got {}", token),
1011 ));
1012
1013 return Ok(Expr::List(
1014 Span::from_begin_end(span_begin.begin, token.span().end),
1015 exprs,
1016 ));
1017 }
1018 };
1019
1020 Ok(Expr::List(
1021 Span::from_begin_end(span_begin.begin, span_end),
1022 exprs,
1023 ))
1024 })
1025 }
1026
1027 fn parse_brace_expr(&mut self) -> Result<Expr, ParserErr> {
1028 let span_begin = match self.current_token() {
1030 Token::BraceL(span, ..) => {
1031 self.next_token();
1032 span
1033 }
1034 token => {
1035 return Err(ParserErr::new(
1036 *token.span(),
1037 format!("expected `{{` got {}", token),
1038 ));
1039 }
1040 };
1041
1042 self.with_nesting(span_begin, |this| {
1043 let span_begin_pos = span_begin.begin;
1044
1045 if let Token::BraceR(span, ..) = this.current_token() {
1047 this.next_token();
1048 return Ok(Expr::Dict(
1049 Span::from_begin_end(span_begin_pos, span.end),
1050 BTreeMap::new(),
1051 ));
1052 }
1053
1054 let looks_like_dict_literal = matches!(this.current_token(), Token::Ident(..))
1058 && matches!(this.peek_token(1), Token::Assign(..));
1059
1060 if looks_like_dict_literal {
1061 return this.parse_dict_expr_after_lbrace(span_begin_pos);
1062 }
1063
1064 let base = match this.parse_expr() {
1065 Ok(expr) => expr,
1066 Err(err) => {
1067 this.record_error(err);
1068 while !matches!(this.current_token(), Token::BraceR(..) | Token::Eof(..)) {
1069 this.next_token();
1070 }
1071 if let Token::BraceR(..) = this.current_token() {
1072 this.next_token();
1073 }
1074 return Ok(Expr::Dict(
1075 Span::from_begin_end(span_begin_pos, Position::new(0, 0)),
1076 BTreeMap::new(),
1077 ));
1078 }
1079 };
1080
1081 match this.current_token() {
1082 Token::With(..) => this.next_token(),
1083 token => {
1084 this.record_error(ParserErr::new(*token.span(), "expected `with`"));
1085 while !matches!(this.current_token(), Token::BraceR(..) | Token::Eof(..)) {
1086 this.next_token();
1087 }
1088 if let Token::BraceR(..) = this.current_token() {
1089 this.next_token();
1090 }
1091 return Ok(base);
1092 }
1093 };
1094
1095 let updates = match this.parse_dict_expr() {
1096 Ok(Expr::Dict(_, kvs)) => kvs,
1097 Ok(other) => {
1098 this.record_error(ParserErr::new(*other.span(), "expected `{...}`"));
1099 BTreeMap::new()
1100 }
1101 Err(err) => {
1102 this.record_error(err);
1103 BTreeMap::new()
1104 }
1105 };
1106
1107 let span_end = match this.current_token() {
1109 Token::BraceR(span, ..) => {
1110 this.next_token();
1111 span.end
1112 }
1113 token => {
1114 this.record_error(ParserErr::new(
1115 *token.span(),
1116 format!("expected `}}` got {}", token),
1117 ));
1118 Position::new(0, 0)
1119 }
1120 };
1121
1122 Ok(Expr::RecordUpdate(
1123 Span::from_begin_end(span_begin_pos, span_end),
1124 Arc::new(base),
1125 updates,
1126 ))
1127 })
1128 }
1129
1130 fn parse_dict_expr(&mut self) -> Result<Expr, ParserErr> {
1131 let span_begin = match self.current_token() {
1133 Token::BraceL(span, ..) => {
1134 self.next_token();
1135 span.begin
1136 }
1137 token => {
1138 return Err(ParserErr::new(
1139 *token.span(),
1140 format!("expected `{{` got {}", token),
1141 ));
1142 }
1143 };
1144
1145 self.with_nesting(Span::from_begin_end(span_begin, span_begin), |this| {
1146 this.parse_dict_expr_after_lbrace(span_begin)
1147 })
1148 }
1149
1150 fn parse_dict_expr_after_lbrace(&mut self, span_begin: Position) -> Result<Expr, ParserErr> {
1151 let mut kvs = Vec::new();
1152 loop {
1153 if let Token::BraceR(..) = self.current_token() {
1154 break;
1155 }
1156
1157 let var = match self.parse_ident_expr()? {
1159 Expr::Var(var) => var,
1160 _ => unreachable!(),
1161 };
1162 match self.current_token() {
1164 Token::Assign(..) => self.next_token(),
1165 token => {
1166 self.record_error(ParserErr::new(*token.span(), "expected `=`"));
1167 break;
1168 }
1169 };
1170 kvs.push((var.name, Arc::new(self.parse_expr()?)));
1172 match self.current_token() {
1174 Token::Comma(..) => self.next_token(),
1175 Token::Eof(span) => {
1176 self.record_error(ParserErr::new(span, "expected `,` or `}`"));
1177 break;
1178 }
1179 _ => {
1180 break;
1181 }
1182 };
1183 }
1184
1185 let span_end = match self.current_token() {
1187 Token::BraceR(span, ..) => {
1188 self.next_token();
1189 span.end
1190 }
1191 token => {
1192 self.record_error(ParserErr::new(
1193 *token.span(),
1194 format!("expected `}}` got {}", token),
1195 ));
1196
1197 return Ok(Expr::Dict(
1198 Span::from_begin_end(span_begin, Position::new(0, 0)),
1199 kvs.into_iter().collect(),
1200 ));
1201 }
1202 };
1203
1204 Ok(Expr::Dict(
1205 Span::from_begin_end(span_begin, span_end),
1206 kvs.into_iter().collect(),
1207 ))
1208 }
1209
1210 fn parse_neg_expr(&mut self) -> Result<Expr, ParserErr> {
1211 let span_token = match self.current_token() {
1213 Token::Sub(span, ..) => {
1214 self.next_token();
1215 span
1216 }
1217 token => {
1218 return Err(ParserErr::new(
1219 *token.span(),
1220 format!("expected `-` got {}", token),
1221 ));
1222 }
1223 };
1224
1225 let expr = self.parse_expr()?;
1227 let expr_span_end = expr.span().end;
1228
1229 Ok(Expr::App(
1231 Span::from_begin_end(span_token.begin, expr_span_end),
1232 Arc::new(Expr::Var(Var::with_span(span_token, "negate"))),
1233 Arc::new(expr),
1234 ))
1235 }
1236
1237 fn parse_lambda_expr(&mut self) -> Result<Expr, ParserErr> {
1239 let span_begin = match self.current_token() {
1241 Token::BackSlash(span, ..) => {
1242 self.next_token();
1243 span.begin
1244 }
1245 token => {
1246 return Err(ParserErr::new(
1247 *token.span(),
1248 format!("expected `\\` got {}", token),
1249 ));
1250 }
1251 };
1252
1253 let mut params = VecDeque::new();
1255 while let Token::Ident(..) | Token::ParenL(..) = self.current_token() {
1256 let (var, ann, span) = self.parse_lambda_param()?;
1257 params.push_back((span, var, ann));
1258 }
1259
1260 let mut constraints = Vec::new();
1261 if matches!(self.current_token(), Token::Where(..)) {
1262 self.next_token();
1263 constraints = self.parse_type_constraints()?;
1264 }
1265
1266 let _span_arrow = match self.current_token() {
1268 Token::ArrowR(span, ..) => {
1269 self.next_token();
1270 span
1271 }
1272 token => {
1273 return Err(ParserErr::new(
1274 *token.span(),
1275 format!("expected `->` got {}", token),
1276 ));
1277 }
1278 };
1279
1280 let mut body = self.parse_expr()?;
1282 let mut body_span_end = body.span().end;
1283 while let Some((param_span, param, ann)) = params.pop_back() {
1284 let lam_constraints = if params.is_empty() {
1285 std::mem::take(&mut constraints)
1286 } else {
1287 Vec::new()
1288 };
1289 body = Expr::Lam(
1290 Span::from_begin_end(param_span.begin, body_span_end),
1291 Scope::new_sync(),
1292 param,
1293 ann,
1294 lam_constraints,
1295 Arc::new(body),
1296 );
1297 body_span_end = body.span().end;
1298 }
1299 let body = body.with_span_begin(span_begin);
1301
1302 Ok(body)
1303 }
1304
1305 fn parse_lambda_param(&mut self) -> Result<(Var, Option<TypeExpr>, Span), ParserErr> {
1306 match self.current_token() {
1307 Token::Ident(name, span, ..) => {
1308 self.next_token();
1309 let mut ann = None;
1310 let mut param_span = span;
1311 if let Token::Colon(..) = self.current_token() {
1312 self.next_token();
1313 let ann_expr = self.parse_type_expr()?;
1314 param_span = Span::from_begin_end(span.begin, ann_expr.span().end);
1315 ann = Some(ann_expr);
1316 }
1317 Ok((Var::with_span(span, name), ann, param_span))
1318 }
1319 Token::ParenL(span_begin, ..) => {
1320 self.next_token();
1321 let (name, name_span) = self.expect_ident("parameter name")?;
1322 self.expect_colon()?;
1323 let ann = self.parse_type_expr()?;
1324 let span_end = self.expect_paren_r()?.end;
1325 Ok((
1326 Var::with_span(name_span, name),
1327 Some(ann),
1328 Span::from_begin_end(span_begin.begin, span_end),
1329 ))
1330 }
1331 token => Err(ParserErr::new(
1332 *token.span(),
1333 format!("expected lambda param got {}", token),
1334 )),
1335 }
1336 }
1337
1338 fn parse_type_constraints(&mut self) -> Result<Vec<TypeConstraint>, ParserErr> {
1339 let mut constraints = Vec::new();
1340 loop {
1341 let (class, _) = self.parse_name_ref_with_span("expected type class name")?;
1342
1343 let typ = self.parse_type_app()?;
1344 constraints.push(TypeConstraint::new(class, typ));
1345
1346 match self.current_token() {
1347 Token::Comma(..) => {
1348 self.next_token();
1349 continue;
1350 }
1351 _ => break,
1352 }
1353 }
1354 Ok(constraints)
1355 }
1356
1357 fn parse_let_expr(&mut self) -> Result<Expr, ParserErr> {
1359 let span_begin = match self.current_token() {
1361 Token::Let(span, ..) => {
1362 self.next_token();
1363 span.begin
1364 }
1365 token => {
1366 return Err(ParserErr::new(
1367 *token.span(),
1368 format!("expected `let` got {}", token),
1369 ));
1370 }
1371 };
1372
1373 let is_rec = if matches!(self.current_token(), Token::Rec(..)) {
1374 self.next_token();
1375 true
1376 } else {
1377 false
1378 };
1379
1380 if is_rec {
1381 let mut bindings = Vec::new();
1382 loop {
1383 let (pat, ann) = match (self.current_token(), self.peek_token(1)) {
1384 (Token::Ident(val, span, ..), Token::Colon(..)) => {
1385 self.next_token();
1386 self.next_token();
1387 let var = Var::with_span(span, val);
1388 let ann = Some(self.parse_type_expr()?);
1389 (Pattern::Var(var), ann)
1390 }
1391 _ => {
1392 let pat = self.parse_pattern()?;
1393 let mut ann = None;
1394 if let Token::Colon(..) = self.current_token() {
1395 self.next_token();
1396 ann = Some(self.parse_type_expr()?);
1397 }
1398 (pat, ann)
1399 }
1400 };
1401
1402 let var = match pat {
1403 Pattern::Var(var) => var,
1404 other => {
1405 return Err(ParserErr::new(
1406 *other.span(),
1407 "let rec only supports variable bindings".to_string(),
1408 ));
1409 }
1410 };
1411
1412 self.expect_assign()?;
1413 let def = Arc::new(self.parse_expr()?);
1414 bindings.push((var, ann, def));
1415
1416 match self.current_token() {
1417 Token::Comma(..) => {
1418 self.next_token();
1419 }
1420 Token::In(..) => break,
1421 token => {
1422 return Err(ParserErr::new(
1423 *token.span(),
1424 format!("expected `,` or `in` got {}", token),
1425 ));
1426 }
1427 }
1428 }
1429
1430 match self.current_token() {
1431 Token::In(..) => self.next_token(),
1432 token => {
1433 return Err(ParserErr::new(
1434 *token.span(),
1435 format!("expected `in` got {}", token),
1436 ));
1437 }
1438 };
1439
1440 let body = Arc::new(self.parse_expr()?);
1441 let span = Span::from_begin_end(span_begin, body.span().end);
1442 Ok(Expr::LetRec(span, bindings, body))
1443 } else {
1444 let mut decls = VecDeque::new();
1446 let is_pattern_start = |token: Token| {
1447 matches!(
1448 token,
1449 Token::Ident(..) | Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..)
1450 )
1451 };
1452 while is_pattern_start(self.current_token()) {
1453 let (pat, ann) = match (self.current_token(), self.peek_token(1)) {
1454 (Token::Ident(val, span, ..), Token::Colon(..)) => {
1455 self.next_token();
1456 self.next_token();
1457 let var = Var::with_span(span, val);
1458 let ann = Some(self.parse_type_expr()?);
1459 (Pattern::Var(var), ann)
1460 }
1461 _ => {
1462 let pat = self.parse_pattern()?;
1463 let mut ann = None;
1464 if let Token::Colon(..) = self.current_token() {
1465 self.next_token();
1466 ann = Some(self.parse_type_expr()?);
1467 }
1468 (pat, ann)
1469 }
1470 };
1471
1472 self.expect_assign()?;
1474 decls.push_back((pat, ann, self.parse_expr()?));
1476 match self.current_token() {
1478 Token::Comma(_span, ..) => {
1479 self.next_token();
1480 continue;
1481 }
1482 Token::In(..) => break,
1483 token => {
1484 return Err(ParserErr::new(
1485 *token.span(),
1486 format!("expected `,` or `in` got {}", token),
1487 ));
1488 }
1489 }
1490 }
1491
1492 let _span_arrow = match self.current_token() {
1494 Token::In(span, ..) => {
1495 self.next_token();
1496 span
1497 }
1498 token => {
1499 return Err(ParserErr::new(
1500 *token.span(),
1501 format!("expected `in` got {}", token),
1502 ));
1503 }
1504 };
1505
1506 let mut body = self.parse_expr()?;
1508 let mut body_span_end = body.span().end;
1509 while let Some((pat, ann, def)) = decls.pop_back() {
1510 match pat {
1511 Pattern::Var(var) => {
1512 body = Expr::Let(
1513 Span::from_begin_end(var.span.begin, body_span_end),
1514 var,
1515 ann,
1516 Arc::new(def),
1517 Arc::new(body),
1518 );
1519 }
1520 pat => {
1521 let def_expr = match ann {
1522 Some(ann) => {
1523 let span = Span::from_begin_end(def.span().begin, ann.span().end);
1524 Expr::Ann(span, Arc::new(def), ann)
1525 }
1526 None => def,
1527 };
1528 body = Expr::Match(
1529 Span::from_begin_end(pat.span().begin, body_span_end),
1530 Arc::new(def_expr),
1531 vec![(pat, Arc::new(body))],
1532 );
1533 }
1534 }
1535 body_span_end = body.span().end;
1536 }
1537 let body = body.with_span_begin(span_begin);
1540
1541 Ok(body)
1542 }
1543 }
1544
1545 fn parse_if_expr(&mut self) -> Result<Expr, ParserErr> {
1547 let span_begin = match self.current_token() {
1549 Token::If(span, ..) => {
1550 self.next_token();
1551 span.begin
1552 }
1553 token => {
1554 return Err(ParserErr::new(
1555 *token.span(),
1556 format!("expected `if` got {}", token),
1557 ));
1558 }
1559 };
1560
1561 let cond = self.parse_expr()?;
1563
1564 let _span_arrow = match self.current_token() {
1566 Token::Then(span, ..) => {
1567 self.next_token();
1568 span
1569 }
1570 token => {
1571 return Err(ParserErr::new(
1572 *token.span(),
1573 format!("expected `then` got {}", token),
1574 ));
1575 }
1576 };
1577
1578 let then = self.parse_expr()?;
1580
1581 let _span_arrow = match self.current_token() {
1583 Token::Else(span, ..) => {
1584 self.next_token();
1585 span
1586 }
1587 token => {
1588 return Err(ParserErr::new(
1589 *token.span(),
1590 format!("expected `else` got {}", token),
1591 ));
1592 }
1593 };
1594
1595 let r#else = self.parse_expr()?;
1597 let else_span_end = r#else.span().end;
1598
1599 Ok(Expr::Ite(
1600 Span::from_begin_end(span_begin, else_span_end),
1601 Arc::new(cond),
1602 Arc::new(then),
1603 Arc::new(r#else),
1604 ))
1605 }
1606
1607 fn parse_match_expr(&mut self) -> Result<Expr, ParserErr> {
1608 let span_begin = match self.current_token() {
1610 Token::Match(span, ..) => {
1611 self.next_token();
1612 span.begin
1613 }
1614 token => {
1615 return Err(ParserErr::new(
1616 *token.span(),
1617 format!("expected `match` got {}", token),
1618 ));
1619 }
1620 };
1621
1622 let scrutinee = self.parse_atom_expr()?;
1623 let mut arms = Vec::new();
1624 loop {
1625 match self.current_token() {
1626 Token::When(..) => {
1627 self.next_token();
1628 }
1629 token => {
1630 return Err(ParserErr::new(
1631 *token.span(),
1632 format!("expected `when` got {}", token),
1633 ));
1634 }
1635 }
1636
1637 let pattern = self.parse_pattern()?;
1638
1639 match self.current_token() {
1640 Token::ArrowR(..) => self.next_token(),
1641 token => {
1642 return Err(ParserErr::new(
1643 *token.span(),
1644 format!("expected `->` got {}", token),
1645 ));
1646 }
1647 }
1648
1649 let expr = self.parse_expr()?;
1650 arms.push((pattern, Arc::new(expr)));
1651
1652 match self.current_token() {
1653 Token::When(..) => continue,
1654 _ => break,
1655 }
1656 }
1657
1658 let span_end = arms
1659 .last()
1660 .map(|(_, expr)| expr.span().end)
1661 .unwrap_or_else(|| scrutinee.span().end);
1662
1663 Ok(Expr::Match(
1664 Span::from_begin_end(span_begin, span_end),
1665 Arc::new(scrutinee),
1666 arms,
1667 ))
1668 }
1669
1670 fn eof_for_slice(&self, slice: &[Token]) -> Span {
1671 slice.last().map(|t| *t.span()).unwrap_or(self.eof)
1672 }
1673
1674 fn parse_type_expr_slice(&self, slice: &[Token]) -> Result<TypeExpr, ParserErr> {
1675 if slice.is_empty() {
1676 return Err(ParserErr::new(self.eof, "expected type".to_string()));
1677 }
1678 let eof = self.eof_for_slice(slice);
1679 let tokens = Tokens {
1680 items: slice.to_vec(),
1681 eof,
1682 };
1683 let mut parser = Parser::new(tokens);
1684 let expr = parser.parse_type_expr()?;
1685 match parser.current_token() {
1686 Token::Eof(..) => Ok(expr),
1687 token => Err(ParserErr::new(
1688 *token.span(),
1689 format!("unexpected {} in type", token),
1690 )),
1691 }
1692 }
1693
1694 fn parse_type_app_slice(&self, slice: &[Token]) -> Result<TypeExpr, ParserErr> {
1695 if slice.is_empty() {
1696 return Err(ParserErr::new(self.eof, "expected type".to_string()));
1697 }
1698 let eof = self.eof_for_slice(slice);
1699 let tokens = Tokens {
1700 items: slice.to_vec(),
1701 eof,
1702 };
1703 let mut parser = Parser::new(tokens);
1704 let expr = parser.parse_type_app()?;
1705 match parser.current_token() {
1706 Token::Eof(..) => Ok(expr),
1707 token => Err(ParserErr::new(
1708 *token.span(),
1709 format!("unexpected {} in type", token),
1710 )),
1711 }
1712 }
1713
1714 fn parse_type_constraints_slice(
1715 &self,
1716 slice: &[Token],
1717 ) -> Result<Vec<TypeConstraint>, ParserErr> {
1718 if slice.is_empty() {
1719 return Err(ParserErr::new(
1720 self.eof,
1721 "expected type constraint".to_string(),
1722 ));
1723 }
1724 let eof = self.eof_for_slice(slice);
1725 let tokens = Tokens {
1726 items: slice.to_vec(),
1727 eof,
1728 };
1729 let mut parser = Parser::new(tokens);
1730 let constraints = parser.parse_type_constraints()?;
1731 match parser.current_token() {
1732 Token::Eof(..) => Ok(constraints),
1733 token => Err(ParserErr::new(
1734 *token.span(),
1735 format!("unexpected {} in type constraints", token),
1736 )),
1737 }
1738 }
1739
1740 fn parse_expr_slice(&self, slice: &[Token]) -> Result<Expr, ParserErr> {
1741 if slice.is_empty() {
1742 return Err(ParserErr::new(self.eof, "expected expression".to_string()));
1743 }
1744 let eof = self.eof_for_slice(slice);
1745 let tokens = Tokens {
1746 items: slice.to_vec(),
1747 eof,
1748 };
1749 let mut parser = Parser::new(tokens);
1750 let expr = parser.parse_expr()?;
1751 match parser.current_token() {
1752 Token::Eof(..) => Ok(expr),
1753 token => Err(ParserErr::new(
1754 *token.span(),
1755 format!("unexpected {} in expression", token),
1756 )),
1757 }
1758 }
1759
1760 fn parse_class_decl(&mut self, is_pub: bool) -> Result<ClassDecl, ParserErr> {
1761 let span_begin = match self.current_token() {
1762 Token::Class(span, ..) => {
1763 self.next_token();
1764 span.begin
1765 }
1766 token => {
1767 return Err(ParserErr::new(
1768 *token.span(),
1769 format!("expected `class` got {}", token),
1770 ));
1771 }
1772 };
1773
1774 let (name, name_span) = match self.current_token() {
1775 Token::Ident(name, span, ..) => {
1776 self.next_token_raw();
1777 (intern(&name), span)
1778 }
1779 token => {
1780 return Err(ParserErr::new(
1781 *token.span(),
1782 format!("expected class name got {}", token),
1783 ));
1784 }
1785 };
1786
1787 let class_indent = span_begin.column;
1788 let header_line = name_span.begin.line;
1789 let mut header_end = name_span.end;
1790
1791 let mut params = Vec::new();
1792 while let Some(Token::Ident(p, span, ..)) = self.tokens.get(self.token_cursor).cloned() {
1793 if span.begin.line != header_line {
1797 break;
1798 }
1799 header_end = header_end.max(span.end);
1800 params.push(intern(&p));
1801 self.next_token_raw();
1802 }
1803
1804 let mut supers = Vec::new();
1805 if let Some(Token::Le(span, ..)) = self.tokens.get(self.token_cursor).cloned() {
1806 if span.begin.line == header_line {
1807 self.next_token_raw();
1808 let start_idx = self.token_cursor;
1809 let end_idx = find_layout_header_clause_end(&self.tokens, start_idx, |t| {
1810 matches!(t, Token::Where(..))
1811 });
1812 supers = self.parse_type_constraints_slice(&self.tokens[start_idx..end_idx])?;
1813 self.token_cursor = end_idx;
1814 }
1815 if let Some(last) = supers.last() {
1816 header_end = header_end.max(last.typ.span().end);
1817 }
1818 }
1819
1820 let mut saw_where = false;
1829 let where_span = match self.current_token() {
1830 Token::Where(span, ..) => {
1831 self.next_token();
1832 header_end = header_end.max(span.end);
1833 saw_where = true;
1834 span
1835 }
1836 _ => Span::default(),
1837 };
1838
1839 let implicit_method_start = if saw_where {
1843 false
1844 } else {
1845 let token = self.current_token();
1846 let token_span = *token.span();
1847 let next = self.peek_token(1);
1848 token_span.begin.column > class_indent
1849 && matches!(next, Token::Colon(..))
1850 && Self::is_value_name_token(&token)
1851 };
1852 let has_method_block = saw_where || implicit_method_start;
1853 let block_indent = if has_method_block {
1854 match self.current_token() {
1855 Token::Ident(_, span, ..) => Some(span.begin.column),
1856 token => Self::operator_token_name(&token).map(|(_, span)| span.begin.column),
1857 }
1858 } else {
1859 None
1860 };
1861
1862 let methods = self.parse_layout_block(has_method_block, block_indent, |parser| {
1863 let (m_name, _name_span) = parser.parse_value_name()?;
1864 parser.expect_colon()?;
1865
1866 let start_idx = parser.token_cursor;
1867 let end_idx =
1868 find_layout_expr_end(&parser.tokens, start_idx, block_indent, |t, next| {
1869 matches!(next, Token::Colon(..)) && Self::is_value_name_token(t)
1870 });
1871 let typ = parser.parse_type_expr_slice(&parser.tokens[start_idx..end_idx])?;
1872 parser.token_cursor = end_idx;
1873 parser.skip_newlines();
1874 Ok(ClassMethodSig { name: m_name, typ })
1875 })?;
1876
1877 let span_end = methods
1878 .last()
1879 .map(|m| m.typ.span().end)
1880 .or_else(|| supers.last().map(|s| s.typ.span().end))
1881 .unwrap_or(header_end.max(where_span.end));
1882
1883 Ok(ClassDecl {
1884 span: Span::from_begin_end(span_begin, span_end),
1885 is_pub,
1886 name,
1887 params,
1888 supers,
1889 methods,
1890 })
1891 }
1892
1893 fn parse_instance_decl(&mut self, is_pub: bool) -> Result<InstanceDecl, ParserErr> {
1894 let span_begin = match self.current_token() {
1895 Token::Instance(span, ..) => {
1896 self.next_token();
1897 span.begin
1898 }
1899 token => {
1900 return Err(ParserErr::new(
1901 *token.span(),
1902 format!("expected `instance` got {}", token),
1903 ));
1904 }
1905 };
1906
1907 let (class_ref, class_span) = self.parse_name_ref_with_span("expected class name")?;
1908 let class = class_ref.to_dotted_symbol();
1909
1910 let instance_indent = span_begin.column;
1911 let header_line = class_span.begin.line;
1912
1913 let start_idx = self.token_cursor;
1914 let end_idx = find_layout_header_clause_end(&self.tokens, start_idx, |t| {
1915 matches!(t, Token::Le(..) | Token::Where(..))
1916 });
1917 if end_idx == start_idx {
1918 let span = self
1919 .tokens
1920 .get(start_idx)
1921 .map(|t| *t.span())
1922 .unwrap_or(self.eof);
1923 return Err(ParserErr::new(span, "expected type".to_string()));
1924 }
1925 let head = self.parse_type_app_slice(&self.tokens[start_idx..end_idx])?;
1926 self.token_cursor = end_idx;
1927 let mut header_end = head.span().end;
1928
1929 let mut context = Vec::new();
1930 if let Some(Token::Le(span, ..)) = self.tokens.get(self.token_cursor).cloned()
1931 && span.begin.line == header_line
1932 {
1933 self.next_token_raw();
1934 let start_idx = self.token_cursor;
1935 let end_idx = find_layout_header_clause_end(&self.tokens, start_idx, |t| {
1936 matches!(t, Token::Where(..))
1937 });
1938 context = self.parse_type_constraints_slice(&self.tokens[start_idx..end_idx])?;
1939 self.token_cursor = end_idx;
1940 if let Some(last) = context.last() {
1941 header_end = header_end.max(last.typ.span().end);
1942 }
1943 }
1944
1945 let mut saw_where = false;
1951 let where_span = match self.current_token() {
1952 Token::Where(span, ..) => {
1953 self.next_token();
1954 header_end = header_end.max(span.end);
1955 saw_where = true;
1956 span
1957 }
1958 _ => Span::default(),
1959 };
1960
1961 let has_method_block = if saw_where {
1964 true
1965 } else {
1966 let token = self.current_token();
1967 let token_span = *token.span();
1968 let next = self.peek_token(1);
1969 token_span.begin.column > instance_indent
1970 && matches!(next, Token::Assign(..))
1971 && Self::is_value_name_token(&token)
1972 };
1973
1974 let block_indent = if has_method_block {
1975 match self.current_token() {
1976 Token::Ident(_, span, ..) => Some(span.begin.column),
1977 token => Self::operator_token_name(&token).map(|(_, span)| span.begin.column),
1978 }
1979 } else {
1980 None
1981 };
1982
1983 let methods = self.parse_layout_block(has_method_block, block_indent, |parser| {
1984 let (name, _name_span) = parser.parse_value_name()?;
1985 parser.expect_assign()?;
1986
1987 let start_idx = parser.token_cursor;
1988 let end_idx =
1989 find_layout_expr_end(&parser.tokens, start_idx, block_indent, |t, next| {
1990 matches!(next, Token::Assign(..)) && Self::is_value_name_token(t)
1991 });
1992 let body = parser.parse_expr_slice(&parser.tokens[start_idx..end_idx])?;
1993 parser.token_cursor = end_idx;
1994 parser.skip_newlines();
1995
1996 Ok(InstanceMethodImpl {
1997 name,
1998 body: Arc::new(body),
1999 })
2000 })?;
2001
2002 let span_end = methods
2003 .last()
2004 .map(|m| m.body.span().end)
2005 .or_else(|| context.last().map(|c| c.typ.span().end))
2006 .unwrap_or(header_end.max(where_span.end));
2007
2008 Ok(InstanceDecl {
2009 span: Span::from_begin_end(span_begin, span_end),
2010 is_pub,
2011 class,
2012 head,
2013 context,
2014 methods,
2015 })
2016 }
2017
2018 fn parse_fn_decl(&mut self, is_pub: bool) -> Result<FnDecl, ParserErr> {
2019 let span_begin = match self.current_token() {
2020 Token::Fn(span, ..) => {
2021 self.next_token();
2022 span.begin
2023 }
2024 token => {
2025 return Err(ParserErr::new(
2026 *token.span(),
2027 format!("expected `fn` got {}", token),
2028 ));
2029 }
2030 };
2031
2032 let (name, name_span) = match self.current_token() {
2033 Token::Ident(name, span, ..) => {
2034 self.next_token();
2035 (name, span)
2036 }
2037 token => {
2038 return Err(ParserErr::new(
2039 *token.span(),
2040 format!("expected function name got {}", token),
2041 ));
2042 }
2043 };
2044
2045 let name_var = Var::with_span(name_span, name);
2046 let mut params: Vec<(Var, TypeExpr)> = Vec::new();
2047
2048 if matches!(self.current_token(), Token::Colon(..)) {
2056 self.next_token();
2057
2058 let sig_start = self.token_cursor;
2060 let sig_end = self
2061 .find_token_at_depth0(sig_start, self.tokens.len(), |t| {
2062 matches!(t, Token::Where(..) | Token::Assign(..))
2063 })
2064 .ok_or_else(|| ParserErr::new(self.eof, "expected `=`".to_string()))?;
2065 let sig = self.parse_type_expr_slice(&self.tokens[sig_start..sig_end])?;
2066 self.token_cursor = sig_end;
2067
2068 let mut constraints = Vec::new();
2069 if matches!(self.current_token(), Token::Where(..)) {
2070 self.next_token();
2071 constraints = self.parse_type_constraints()?;
2072 }
2073
2074 self.expect_assign()?;
2076
2077 let body_start = self.token_cursor;
2079 let body_end = self.find_dedent_end(body_start, span_begin.column)?;
2080 let body_expr = self.parse_expr_slice(&self.tokens[body_start..body_end])?;
2081 self.token_cursor = body_end;
2082 let body = Arc::new(body_expr);
2083 let span_end = body.span().end;
2084
2085 let mut param_tys = Vec::new();
2088 let mut cur = sig;
2089 let ret = loop {
2090 match cur {
2091 TypeExpr::Fun(_, arg, next_ret) => {
2092 param_tys.push(*arg);
2093 cur = *next_ret;
2094 }
2095 other => break other,
2096 }
2097 };
2098 if param_tys.is_empty() {
2099 return Err(ParserErr::new(
2100 *ret.span(),
2101 "expected function type after `:`; use `let` for values".to_string(),
2102 ));
2103 }
2104
2105 let arity = param_tys.len();
2106 let mut body_constraints = Vec::new();
2107 let (params, body) = if matches!(body.as_ref(), Expr::Lam(..)) {
2108 let mut lam_params: Vec<Var> = Vec::new();
2109 let mut cur = body.clone();
2110 while matches!(cur.as_ref(), Expr::Lam(..)) {
2111 let Expr::Lam(_span, _scope, param, _ann, lam_constraints, next) = cur.as_ref()
2112 else {
2113 break;
2114 };
2115 if !lam_constraints.is_empty() {
2116 body_constraints.extend(lam_constraints.iter().cloned());
2117 }
2118 lam_params.push(param.clone());
2119 cur = next.clone();
2120 }
2121
2122 if lam_params.len() != arity {
2123 return Err(ParserErr::new(
2124 *body.span(),
2125 format!(
2126 "lambda has {} parameter(s) but signature expects {}",
2127 lam_params.len(),
2128 arity
2129 ),
2130 ));
2131 }
2132
2133 let params: Vec<(Var, TypeExpr)> = lam_params.into_iter().zip(param_tys).collect();
2134 (params, cur)
2135 } else {
2136 let var_span = *body.span();
2138 let vars: Vec<Var> = (0..arity)
2139 .map(|i| Var::with_span(var_span, format!("_arg{i}")))
2140 .collect();
2141
2142 let mut applied = body.clone();
2143 for v in &vars {
2144 applied = Arc::new(Expr::App(
2145 Span::from_begin_end(applied.span().begin, applied.span().end),
2146 applied,
2147 Arc::new(Expr::Var(v.clone())),
2148 ));
2149 }
2150
2151 let params: Vec<(Var, TypeExpr)> = vars.into_iter().zip(param_tys).collect();
2152 (params, applied)
2153 };
2154
2155 constraints.extend(body_constraints);
2156
2157 return Ok(FnDecl {
2158 span: Span::from_begin_end(span_begin, span_end),
2159 is_pub,
2160 name: name_var,
2161 params,
2162 ret,
2163 constraints,
2164 body,
2165 });
2166 }
2167
2168 let is_named_param_head = |token: &Token, next: &Token| {
2169 matches!(token, Token::Ident(..)) && matches!(next, Token::Colon(..))
2170 };
2171 let is_paren_param_head = |token: &Token, next: &Token, next2: &Token| {
2172 matches!(token, Token::ParenL(..))
2173 && matches!(next, Token::Ident(..))
2174 && matches!(next2, Token::Colon(..))
2175 };
2176
2177 if matches!(self.current_token(), Token::ParenL(..)) {
2186 if self.paren_group_has_top_level_comma(self.token_cursor)
2188 || matches!(self.peek_token(1), Token::ParenR(..))
2189 {
2190 params = self.parse_legacy_param_group()?;
2191
2192 match self.current_token() {
2194 Token::ArrowR(..) => self.next_token(),
2195 token => {
2196 return Err(ParserErr::new(
2197 *token.span(),
2198 format!("expected `->` got {}", token),
2199 ));
2200 }
2201 }
2202 }
2203 }
2204
2205 if params.is_empty() {
2208 loop {
2209 let tok = self.current_token();
2210 let next = self.peek_token(1);
2211 let next2 = self.peek_token(2);
2212 if is_paren_param_head(&tok, &next, &next2) {
2213 self.next_token(); let (param_name, param_span) = self.expect_ident("parameter name")?;
2216 self.expect_colon()?;
2217
2218 let ty_start = self.token_cursor;
2220 let rparen_idx = self
2221 .find_token_at_depth0(ty_start, self.tokens.len(), |t| {
2222 matches!(t, Token::ParenR(..))
2223 })
2224 .ok_or_else(|| ParserErr::new(self.eof, "expected `)`".to_string()))?;
2225 let ann = self.parse_type_expr_slice(&self.tokens[ty_start..rparen_idx])?;
2226 self.token_cursor = rparen_idx;
2227
2228 let _ = self.expect_paren_r()?;
2229
2230 params.push((Var::with_span(param_span, param_name), ann));
2231 } else if is_named_param_head(&tok, &next) {
2232 let (param_name, param_span) = self.expect_ident("parameter name")?;
2234
2235 self.expect_colon()?;
2236
2237 let ty_start = self.token_cursor;
2241 let mut depth = 0usize;
2242 let mut arrow_idx = None;
2243 let mut stop_span = None;
2244 for i in ty_start..self.tokens.len() {
2245 match self.tokens[i] {
2246 Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..) => {
2247 depth += 1
2248 }
2249 Token::ParenR(..) | Token::BracketR(..) | Token::BraceR(..) => {
2250 depth = depth.saturating_sub(1)
2251 }
2252 Token::ArrowR(..) if depth == 0 => {
2253 arrow_idx = Some(i);
2254 break;
2255 }
2256 Token::Assign(span, ..) | Token::Where(span, ..) if depth == 0 => {
2257 stop_span = Some(span);
2258 break;
2259 }
2260 _ => {}
2261 }
2262 }
2263 let Some(arrow_idx) = arrow_idx else {
2264 let span = stop_span.unwrap_or(self.eof);
2265 return Err(ParserErr::new(
2266 span,
2267 "expected `->` after parameter type".to_string(),
2268 ));
2269 };
2270 let ann = self.parse_type_expr_slice(&self.tokens[ty_start..arrow_idx])?;
2271 self.token_cursor = arrow_idx;
2272 params.push((Var::with_span(param_span, param_name), ann));
2273 } else {
2274 return Err(ParserErr::new(
2275 *tok.span(),
2276 format!("expected `(` or parameter name got {}", tok),
2277 ));
2278 }
2279
2280 match self.current_token() {
2282 Token::ArrowR(..) => self.next_token(),
2283 token => {
2284 return Err(ParserErr::new(
2285 *token.span(),
2286 format!("expected `->` got {}", token),
2287 ));
2288 }
2289 }
2290
2291 let tok = self.current_token();
2293 let next = self.peek_token(1);
2294 let next2 = self.peek_token(2);
2295 if is_paren_param_head(&tok, &next, &next2) || is_named_param_head(&tok, &next) {
2296 continue;
2297 }
2298 break;
2299 }
2300 }
2301
2302 let ret_start = self.token_cursor;
2304 let assign_idx = self
2305 .find_token_at_depth0(ret_start, self.tokens.len(), |t| {
2306 matches!(t, Token::Assign(..))
2307 })
2308 .ok_or_else(|| {
2309 ParserErr::new(self.eof, "expected `=` in function declaration".to_string())
2310 })?;
2311
2312 let ret_end = self
2313 .find_token_at_depth0(ret_start, assign_idx, |t| matches!(t, Token::Where(..)))
2314 .unwrap_or(assign_idx);
2315 let ret = self.parse_type_expr_slice(&self.tokens[ret_start..ret_end])?;
2316 self.token_cursor = ret_end;
2317
2318 let mut constraints = Vec::new();
2319 if matches!(self.current_token(), Token::Where(..)) {
2320 self.next_token();
2321 constraints = self.parse_type_constraints()?;
2322 }
2323
2324 self.expect_assign()?;
2326
2327 let body_start = self.token_cursor;
2329 let body_end = self.find_same_line_end(body_start)?;
2330 let body = self.parse_expr_slice(&self.tokens[body_start..body_end])?;
2331 self.token_cursor = body_end;
2332 let span_end = body.span().end;
2333
2334 Ok(FnDecl {
2335 span: Span::from_begin_end(span_begin, span_end),
2336 is_pub,
2337 name: name_var,
2338 params,
2339 ret,
2340 constraints,
2341 body: Arc::new(body),
2342 })
2343 }
2344
2345 fn parse_declare_fn_decl_toplevel(&mut self, is_pub: bool) -> Result<DeclareFnDecl, ParserErr> {
2346 let start_idx = self.token_cursor;
2347 let end_idx = self.find_same_line_end(start_idx)?;
2349
2350 let eof = self
2351 .tokens
2352 .get(end_idx.saturating_sub(1))
2353 .map(|t| *t.span())
2354 .unwrap_or(self.eof);
2355 let tokens = Tokens {
2356 items: self.tokens[start_idx..end_idx].to_vec(),
2357 eof,
2358 };
2359 let mut parser = Parser::new(tokens);
2360 let decl = parser.parse_declare_fn_decl(is_pub)?;
2361 match parser.current_token() {
2362 Token::Eof(..) => {}
2363 token => {
2364 return Err(ParserErr::new(
2365 *token.span(),
2366 format!("unexpected {} in declaration", token),
2367 ));
2368 }
2369 }
2370
2371 self.token_cursor = end_idx;
2372 self.skip_newlines();
2373 Ok(decl)
2374 }
2375
2376 fn parse_declare_fn_decl(&mut self, is_pub: bool) -> Result<DeclareFnDecl, ParserErr> {
2377 let span_begin = match self.current_token() {
2378 Token::Declare(span, ..) => {
2379 self.next_token();
2380 span.begin
2381 }
2382 token => {
2383 return Err(ParserErr::new(
2384 *token.span(),
2385 format!("expected `declare` got {}", token),
2386 ));
2387 }
2388 };
2389
2390 match self.current_token() {
2391 Token::Fn(..) => self.next_token(),
2392 token => {
2393 return Err(ParserErr::new(
2394 *token.span(),
2395 format!("expected `fn` got {}", token),
2396 ));
2397 }
2398 }
2399
2400 let (name, name_span) = match self.current_token() {
2401 Token::Ident(name, span, ..) => {
2402 self.next_token();
2403 (name, span)
2404 }
2405 token => {
2406 return Err(ParserErr::new(
2407 *token.span(),
2408 format!("expected function name got {}", token),
2409 ));
2410 }
2411 };
2412
2413 let name_var = Var::with_span(name_span, name);
2414 let mut params: Vec<(Var, TypeExpr)> = Vec::new();
2415
2416 if matches!(self.current_token(), Token::Colon(..)) {
2419 self.next_token();
2420 }
2421
2422 let is_named_param_head = |token: &Token, next: &Token| {
2423 matches!(token, Token::Ident(..)) && matches!(next, Token::Colon(..))
2424 };
2425 let is_paren_param_head = |token: &Token, next: &Token, next2: &Token| {
2426 matches!(token, Token::ParenL(..))
2427 && matches!(next, Token::Ident(..))
2428 && matches!(next2, Token::Colon(..))
2429 };
2430
2431 let tok = self.current_token();
2435 let next = self.peek_token(1);
2436 let next2 = self.peek_token(2);
2437 let mut use_named_params =
2438 is_named_param_head(&tok, &next) || is_paren_param_head(&tok, &next, &next2);
2439
2440 if !use_named_params && matches!(tok, Token::ParenL(..)) {
2441 if matches!(next, Token::ParenR(..)) {
2443 use_named_params = true;
2444 } else {
2445 if self.paren_group_has_top_level_colon(self.token_cursor) {
2447 use_named_params = true;
2448 }
2449 }
2450 }
2451
2452 if !use_named_params {
2453 let sig_start = self.token_cursor;
2455 let stop_idx = self.find_token_at_depth0(sig_start, self.tokens.len(), |t| {
2456 matches!(t, Token::Where(..) | Token::Assign(..))
2457 });
2458 let sig_end = match stop_idx {
2459 Some(i) => match self.tokens[i] {
2460 Token::Where(..) => i,
2461 Token::Assign(span, ..) => {
2462 return Err(ParserErr::new(
2463 span,
2464 "declare fn cannot have a body; use `fn`".to_string(),
2465 ));
2466 }
2467 _ => i,
2468 },
2469 None => self.tokens.len(),
2470 };
2471 let sig = self.parse_type_expr_slice(&self.tokens[sig_start..sig_end])?;
2472 self.token_cursor = sig_end;
2473
2474 let mut constraints = Vec::new();
2475 if matches!(self.current_token(), Token::Where(..)) {
2476 self.next_token();
2477 constraints = self.parse_type_constraints()?;
2478 }
2479
2480 let mut param_tys = Vec::new();
2483 let mut cur = sig;
2484 let ret = loop {
2485 match cur {
2486 TypeExpr::Fun(_, arg, next_ret) => {
2487 param_tys.push(*arg);
2488 cur = *next_ret;
2489 }
2490 other => break other,
2491 }
2492 };
2493 params = param_tys
2494 .into_iter()
2495 .enumerate()
2496 .map(|(i, ann)| (Var::with_span(*ann.span(), format!("_arg{i}")), ann))
2497 .collect();
2498
2499 let span_end = constraints
2500 .last()
2501 .map(|c| c.typ.span().end)
2502 .unwrap_or(ret.span().end);
2503 return Ok(DeclareFnDecl {
2504 span: Span::from_begin_end(span_begin, span_end),
2505 is_pub,
2506 name: name_var,
2507 params,
2508 ret,
2509 constraints,
2510 });
2511 }
2512
2513 if matches!(self.current_token(), Token::ParenL(..)) {
2520 if self.paren_group_has_top_level_comma(self.token_cursor)
2522 || matches!(self.peek_token(1), Token::ParenR(..))
2523 {
2524 params = self.parse_legacy_param_group()?;
2525
2526 match self.current_token() {
2528 Token::ArrowR(..) => self.next_token(),
2529 token => {
2530 return Err(ParserErr::new(
2531 *token.span(),
2532 format!("expected `->` got {}", token),
2533 ));
2534 }
2535 }
2536 }
2537 }
2538
2539 if params.is_empty() {
2542 loop {
2543 let tok = self.current_token();
2544 let next = self.peek_token(1);
2545 let next2 = self.peek_token(2);
2546 if is_paren_param_head(&tok, &next, &next2) {
2547 self.next_token(); let (param_name, param_span) = self.expect_ident("parameter name")?;
2550 self.expect_colon()?;
2551
2552 let ty_start = self.token_cursor;
2554 let rparen_idx = self
2555 .find_token_at_depth0(ty_start, self.tokens.len(), |t| {
2556 matches!(t, Token::ParenR(..))
2557 })
2558 .ok_or_else(|| ParserErr::new(self.eof, "expected `)`".to_string()))?;
2559 let ann = self.parse_type_expr_slice(&self.tokens[ty_start..rparen_idx])?;
2560 self.token_cursor = rparen_idx;
2561
2562 let _ = self.expect_paren_r()?;
2563
2564 params.push((Var::with_span(param_span, param_name), ann));
2565 } else if is_named_param_head(&tok, &next) {
2566 let (param_name, param_span) = self.expect_ident("parameter name")?;
2568 self.expect_colon()?;
2569
2570 let ty_start = self.token_cursor;
2574 let mut depth = 0usize;
2575 let mut arrow_idx = None;
2576 let mut stop_span = None;
2577 for i in ty_start..self.tokens.len() {
2578 match self.tokens[i] {
2579 Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..) => {
2580 depth += 1
2581 }
2582 Token::ParenR(..) | Token::BracketR(..) | Token::BraceR(..) => {
2583 depth = depth.saturating_sub(1)
2584 }
2585 Token::ArrowR(..) if depth == 0 => {
2586 arrow_idx = Some(i);
2587 break;
2588 }
2589 Token::Where(span, ..) if depth == 0 => {
2590 stop_span = Some(span);
2591 break;
2592 }
2593 _ => {}
2594 }
2595 }
2596 let Some(arrow_idx) = arrow_idx else {
2597 let span = stop_span.unwrap_or(self.eof);
2598 return Err(ParserErr::new(
2599 span,
2600 "expected `->` after parameter type".to_string(),
2601 ));
2602 };
2603 let ann = self.parse_type_expr_slice(&self.tokens[ty_start..arrow_idx])?;
2604 self.token_cursor = arrow_idx;
2605 params.push((Var::with_span(param_span, param_name), ann));
2606 } else {
2607 return Err(ParserErr::new(
2608 *tok.span(),
2609 format!("expected `(` or parameter name got {}", tok),
2610 ));
2611 }
2612
2613 match self.current_token() {
2615 Token::ArrowR(..) => self.next_token(),
2616 token => {
2617 return Err(ParserErr::new(
2618 *token.span(),
2619 format!("expected `->` got {}", token),
2620 ));
2621 }
2622 }
2623
2624 let tok = self.current_token();
2626 let next = self.peek_token(1);
2627 let next2 = self.peek_token(2);
2628 if is_paren_param_head(&tok, &next, &next2) || is_named_param_head(&tok, &next) {
2629 continue;
2630 }
2631 break;
2632 }
2633 }
2634
2635 let ret_start = self.token_cursor;
2637 let stop_idx = self.find_token_at_depth0(ret_start, self.tokens.len(), |t| {
2638 matches!(t, Token::Where(..) | Token::Assign(..))
2639 });
2640 let ret_end = match stop_idx {
2641 Some(i) => match self.tokens[i] {
2642 Token::Where(..) => i,
2643 Token::Assign(span, ..) => {
2644 return Err(ParserErr::new(
2645 span,
2646 "declare fn cannot have a body; use `fn`".to_string(),
2647 ));
2648 }
2649 _ => i,
2650 },
2651 None => self.tokens.len(),
2652 };
2653 let ret = self.parse_type_expr_slice(&self.tokens[ret_start..ret_end])?;
2654 self.token_cursor = ret_end;
2655
2656 let mut constraints = Vec::new();
2657 if matches!(self.current_token(), Token::Where(..)) {
2658 self.next_token();
2659 constraints = self.parse_type_constraints()?;
2660 }
2661
2662 let span_end = constraints
2663 .last()
2664 .map(|c| c.typ.span().end)
2665 .unwrap_or(ret.span().end);
2666 Ok(DeclareFnDecl {
2667 span: Span::from_begin_end(span_begin, span_end),
2668 is_pub,
2669 name: name_var,
2670 params,
2671 ret,
2672 constraints,
2673 })
2674 }
2675
2676 fn parse_import_decl(&mut self, is_pub: bool) -> Result<ImportDecl, ParserErr> {
2677 let span_begin = match self.current_token() {
2678 Token::Import(span, ..) => {
2679 self.next_token();
2680 span.begin
2681 }
2682 token => {
2683 return Err(ParserErr::new(
2684 *token.span(),
2685 format!("expected `import` got {}", token),
2686 ));
2687 }
2688 };
2689
2690 let (path, mut span_end, default_alias) = match self.current_token() {
2691 Token::HttpsUrl(url, span, ..) => {
2692 let url = url.clone();
2693 self.next_token();
2694 let (base_url, sha) = match url.split_once('#') {
2695 Some((a, b)) if !b.is_empty() => (a.to_string(), Some(b.to_string())),
2696 _ => (url, None),
2697 };
2698 let alias = base_url
2699 .rsplit('/')
2700 .next()
2701 .unwrap_or("")
2702 .trim_end_matches(".rex")
2703 .to_string();
2704 (
2705 ImportPath::Remote { url: base_url, sha },
2706 span.end,
2707 if alias.is_empty() {
2708 None
2709 } else {
2710 Some(intern(&alias))
2711 },
2712 )
2713 }
2714 Token::Dot(..) | Token::DotDot(..) => {
2715 let (mut segs, end) = self.parse_relative_import_segments()?;
2716
2717 let sha = if matches!(self.current_token(), Token::HashTag(..)) {
2718 self.next_token();
2719 match self.current_token() {
2720 Token::Ident(s, span, ..) => {
2721 self.next_token();
2722 Some((s.clone(), span.end))
2723 }
2724 Token::Int(n, span, ..) => {
2725 self.next_token();
2726 Some((n.to_string(), span.end))
2727 }
2728 token => {
2729 return Err(ParserErr::new(
2730 *token.span(),
2731 format!("expected sha token got {}", token),
2732 ));
2733 }
2734 }
2735 } else {
2736 None
2737 };
2738 let mut end = end;
2739 let sha = sha.map(|(sha, sha_end)| {
2740 end = end.max(sha_end);
2741 sha
2742 });
2743 let default_alias = segs.last().cloned();
2744 if segs.is_empty() {
2745 return Err(ParserErr::new(
2746 *self.current_token().span(),
2747 "relative import must include a module path",
2748 ));
2749 }
2750 (
2751 ImportPath::Local {
2752 segments: std::mem::take(&mut segs),
2753 sha,
2754 },
2755 end,
2756 default_alias,
2757 )
2758 }
2759 Token::Ident(..) => {
2760 let mut segs: Vec<Symbol> = Vec::new();
2761 let (first, first_span) = match self.current_token() {
2762 Token::Ident(name, span, ..) => (intern(&name), span),
2763 token => {
2764 return Err(ParserErr::new(
2765 *token.span(),
2766 format!("expected module path segment got {}", token),
2767 ));
2768 }
2769 };
2770 let mut end = first_span.end;
2771 segs.push(first);
2772 self.next_token();
2773
2774 while matches!(self.current_token(), Token::Dot(..)) {
2775 self.next_token();
2776 let (seg, seg_span) = match self.current_token() {
2777 Token::Ident(name, span, ..) => (intern(&name), span),
2778 token => {
2779 return Err(ParserErr::new(
2780 *token.span(),
2781 format!("expected module path segment got {}", token),
2782 ));
2783 }
2784 };
2785 segs.push(seg);
2786 end = seg_span.end;
2787 self.next_token();
2788 }
2789
2790 let sha = if matches!(self.current_token(), Token::HashTag(..)) {
2791 self.next_token();
2792 match self.current_token() {
2793 Token::Ident(s, span, ..) => {
2794 self.next_token();
2795 end = end.max(span.end);
2796 Some(s.clone())
2797 }
2798 Token::Int(n, span, ..) => {
2799 self.next_token();
2800 end = end.max(span.end);
2801 Some(n.to_string())
2802 }
2803 token => {
2804 return Err(ParserErr::new(
2805 *token.span(),
2806 format!("expected sha token got {}", token),
2807 ));
2808 }
2809 }
2810 } else {
2811 None
2812 };
2813 let default_alias = segs.last().cloned();
2814 (
2815 ImportPath::Local {
2816 segments: segs,
2817 sha,
2818 },
2819 end,
2820 default_alias,
2821 )
2822 }
2823 token => {
2824 return Err(ParserErr::new(
2825 *token.span(),
2826 format!("expected module path got {}", token),
2827 ));
2828 }
2829 };
2830
2831 let clause = if matches!(self.current_token(), Token::ParenL(..)) {
2832 self.next_token();
2833 if matches!(self.current_token(), Token::Mul(..)) {
2834 self.next_token();
2835 let end = match self.current_token() {
2836 Token::ParenR(span, ..) => {
2837 self.next_token();
2838 span.end
2839 }
2840 token => {
2841 return Err(ParserErr::new(
2842 *token.span(),
2843 format!("expected `)` got {}", token),
2844 ));
2845 }
2846 };
2847 span_end = span_end.max(end);
2848 Some(ImportClause::All)
2849 } else {
2850 let mut items: Vec<ImportItem> = Vec::new();
2851 let mut local_names: HashSet<Symbol> = HashSet::new();
2852 loop {
2853 let (name, item_span) = self.parse_value_name()?;
2854 let mut item_end = item_span.end;
2855 let alias = if matches!(self.current_token(), Token::As(..)) {
2856 self.next_token();
2857 match self.current_token() {
2858 Token::Ident(alias, alias_span, ..) => {
2859 self.next_token();
2860 item_end = alias_span.end;
2861 Some(intern(&alias))
2862 }
2863 token => {
2864 return Err(ParserErr::new(
2865 *token.span(),
2866 format!("expected alias name got {}", token),
2867 ));
2868 }
2869 }
2870 } else {
2871 None
2872 };
2873
2874 let local_name = alias.clone().unwrap_or_else(|| name.clone());
2875 if local_names.contains(&local_name) {
2876 return Err(ParserErr::new(
2877 Span::from_begin_end(item_span.begin, item_end),
2878 format!("duplicate imported name `{local_name}`"),
2879 ));
2880 }
2881 local_names.insert(local_name);
2882 items.push(ImportItem { name, alias });
2883
2884 match self.current_token() {
2885 Token::Comma(..) => {
2886 self.next_token();
2887 }
2888 Token::ParenR(span, ..) => {
2889 self.next_token();
2890 span_end = span_end.max(span.end.max(item_end));
2891 break;
2892 }
2893 token => {
2894 return Err(ParserErr::new(
2895 *token.span(),
2896 format!("expected `,` or `)` got {}", token),
2897 ));
2898 }
2899 }
2900 }
2901 Some(ImportClause::Items(items))
2902 }
2903 } else {
2904 None
2905 };
2906
2907 let alias = if matches!(self.current_token(), Token::As(..)) {
2908 if clause.is_some() {
2909 let span = *self.current_token().span();
2910 return Err(ParserErr::new(
2911 span,
2912 "cannot combine `as <alias>` with import clause `(...)`".to_string(),
2913 ));
2914 }
2915 self.next_token();
2916 match self.current_token() {
2917 Token::Ident(name, span, ..) => {
2918 self.next_token();
2919 span_end = span_end.max(span.end);
2920 intern(&name)
2921 }
2922 token => {
2923 return Err(ParserErr::new(
2924 *token.span(),
2925 format!("expected alias name got {}", token),
2926 ));
2927 }
2928 }
2929 } else {
2930 default_alias
2931 .or_else(|| clause.as_ref().map(|_| intern("_")))
2932 .ok_or_else(|| {
2933 ParserErr::new(
2934 Span::from_begin_end(span_begin, span_end),
2935 "import requires `as <alias>`".to_string(),
2936 )
2937 })?
2938 };
2939
2940 self.skip_newlines();
2941 Ok(ImportDecl {
2942 span: Span::from_begin_end(span_begin, span_end),
2943 is_pub,
2944 path,
2945 alias,
2946 clause,
2947 })
2948 }
2949
2950 fn parse_relative_import_segments(&mut self) -> Result<(Vec<Symbol>, Position), ParserErr> {
2951 let mut segments: Vec<Symbol> = Vec::new();
2952
2953 loop {
2954 if matches!(self.current_token(), Token::DotDot(..)) {
2955 self.next_token();
2956 segments.push(intern("super"));
2957 } else {
2958 match self.current_token() {
2959 Token::Dot(..) => self.next_token(),
2960 token => {
2961 return Err(ParserErr::new(
2962 *token.span(),
2963 "expected `.` or `..` in relative import path",
2964 ));
2965 }
2966 }
2967 }
2968
2969 match self.current_token() {
2970 Token::Div(..) => self.next_token(),
2971 token => {
2972 return Err(ParserErr::new(
2973 *token.span(),
2974 "expected `/` in relative import path",
2975 ));
2976 }
2977 }
2978
2979 if !matches!(self.current_token(), Token::Dot(..) | Token::DotDot(..)) {
2980 break;
2981 }
2982 }
2983
2984 let (first, first_span) = match self.current_token() {
2985 Token::Ident(name, span, ..) => (intern(&name), span),
2986 token => {
2987 return Err(ParserErr::new(
2988 *token.span(),
2989 format!("expected module path segment got {}", token),
2990 ));
2991 }
2992 };
2993 segments.push(first);
2994 let mut end = first_span.end;
2995 self.next_token();
2996
2997 loop {
2998 if !matches!(self.current_token(), Token::Dot(..) | Token::Div(..)) {
2999 break;
3000 }
3001 self.next_token();
3002 let (seg, seg_span) = match self.current_token() {
3003 Token::Ident(name, span, ..) => (intern(&name), span),
3004 token => {
3005 return Err(ParserErr::new(
3006 *token.span(),
3007 format!("expected module path segment got {}", token),
3008 ));
3009 }
3010 };
3011 segments.push(seg);
3012 end = seg_span.end;
3013 self.next_token();
3014 }
3015
3016 Ok((segments, end))
3017 }
3018
3019 fn parse_type_decl(&mut self, is_pub: bool) -> Result<TypeDecl, ParserErr> {
3020 let span_begin = match self.current_token() {
3021 Token::Type(span, ..) => {
3022 self.next_token();
3023 span.begin
3024 }
3025 token => {
3026 return Err(ParserErr::new(
3027 *token.span(),
3028 format!("expected `type` got {}", token),
3029 ));
3030 }
3031 };
3032
3033 let (name, _name_span) = match self.current_token() {
3034 Token::Ident(name, span, ..) => {
3035 let name = intern(&name);
3036 self.next_token();
3037 (name, span)
3038 }
3039 token => {
3040 return Err(ParserErr::new(
3041 *token.span(),
3042 format!("expected type name got {}", token),
3043 ));
3044 }
3045 };
3046
3047 let mut params = Vec::new();
3048 while let Token::Ident(_param, ..) = self.current_token() {
3049 let name = match self.current_token() {
3050 Token::Ident(param, ..) => intern(¶m),
3051 _ => unreachable!(),
3052 };
3053 self.next_token();
3054 params.push(name);
3055 }
3056
3057 match self.current_token() {
3058 Token::Assign(..) => self.next_token(),
3059 token => {
3060 return Err(ParserErr::new(
3061 *token.span(),
3062 format!("expected `=` got {}", token),
3063 ));
3064 }
3065 }
3066
3067 let (first, first_span) = self.parse_type_variant()?;
3068 let mut variants = vec![first];
3069 let mut span_end = first_span.end;
3070 while let Token::Pipe(..) = self.current_token() {
3071 self.next_token();
3072 let (variant, vspan) = self.parse_type_variant()?;
3073 span_end = vspan.end;
3074 variants.push(variant);
3075 }
3076
3077 Ok(TypeDecl {
3078 span: Span::from_begin_end(span_begin, span_end),
3079 is_pub,
3080 name,
3081 params,
3082 variants,
3083 })
3084 }
3085
3086 fn parse_type_variant(&mut self) -> Result<(TypeVariant, Span), ParserErr> {
3087 let (name, name_span) = match self.current_token() {
3088 Token::Ident(name, span, ..) => {
3089 let name = intern(&name);
3090 self.next_token();
3091 (name, span)
3092 }
3093 token => {
3094 return Err(ParserErr::new(
3095 *token.span(),
3096 format!("expected constructor name got {}", token),
3097 ));
3098 }
3099 };
3100
3101 let mut args = Vec::new();
3102 let mut span_end = name_span.end;
3103 while let Token::Ident(..) | Token::ParenL(..) | Token::BraceL(..) = self.current_token() {
3104 let arg = self.parse_type_atom()?;
3105 span_end = arg.span().end;
3106 args.push(arg);
3107 }
3108
3109 Ok((
3110 TypeVariant { name, args },
3111 Span::from_begin_end(name_span.begin, span_end),
3112 ))
3113 }
3114
3115 fn parse_type_expr(&mut self) -> Result<TypeExpr, ParserErr> {
3116 self.parse_type_fun()
3117 }
3118
3119 fn parse_type_fun(&mut self) -> Result<TypeExpr, ParserErr> {
3120 let span = *self.current_token().span();
3121 self.with_nesting(span, |this| {
3122 let lhs = this.parse_type_app()?;
3123 match this.current_token() {
3124 Token::ArrowR(..) => {
3125 this.next_token();
3126 let rhs = this.parse_type_fun()?;
3127 let span = Span::from_begin_end(lhs.span().begin, rhs.span().end);
3128 Ok(TypeExpr::Fun(span, Box::new(lhs), Box::new(rhs)))
3129 }
3130 _ => Ok(lhs),
3131 }
3132 })
3133 }
3134
3135 fn parse_type_app(&mut self) -> Result<TypeExpr, ParserErr> {
3136 let mut lhs = self.parse_type_atom()?;
3137 while let Token::Ident(..) | Token::ParenL(..) | Token::BraceL(..) = self.current_token() {
3138 let rhs = self.parse_type_atom()?;
3139 let span = Span::from_begin_end(lhs.span().begin, rhs.span().end);
3140 lhs = TypeExpr::App(span, Box::new(lhs), Box::new(rhs));
3141 }
3142 Ok(lhs)
3143 }
3144
3145 fn parse_type_atom(&mut self) -> Result<TypeExpr, ParserErr> {
3146 match self.current_token() {
3147 Token::Ident(..) => {
3148 let (name, span) = self.parse_name_ref_with_span("expected type identifier")?;
3149 Ok(TypeExpr::Name(span, name))
3150 }
3151 Token::ParenL(..) => self.parse_type_paren(),
3152 Token::BraceL(..) => self.parse_type_record(),
3153 token => Err(ParserErr::new(
3154 *token.span(),
3155 format!("unexpected {} in type", token),
3156 )),
3157 }
3158 }
3159
3160 fn parse_type_paren(&mut self) -> Result<TypeExpr, ParserErr> {
3161 let span_begin = match self.current_token() {
3162 Token::ParenL(span, ..) => {
3163 self.next_token();
3164 span.begin
3165 }
3166 token => {
3167 return Err(ParserErr::new(
3168 *token.span(),
3169 format!("expected `(` got {}", token),
3170 ));
3171 }
3172 };
3173
3174 self.with_nesting(Span::from_begin_end(span_begin, span_begin), |this| {
3175 if let Token::ParenR(span, ..) = this.current_token() {
3177 this.next_token();
3178 return Ok(TypeExpr::Tuple(
3179 Span::from_begin_end(span_begin, span.end),
3180 Vec::new(),
3181 ));
3182 }
3183
3184 let first = this.parse_type_expr()?;
3185 let mut elems = Vec::new();
3186 let span_end = match this.current_token() {
3187 Token::Comma(..) => {
3188 this.next_token();
3189 elems.push(first);
3190 loop {
3191 elems.push(this.parse_type_expr()?);
3192 match this.current_token() {
3193 Token::Comma(..) => {
3194 this.next_token();
3195 continue;
3196 }
3197 Token::ParenR(span, ..) => {
3198 this.next_token();
3199 break span.end;
3200 }
3201 token => {
3202 return Err(ParserErr::new(
3203 *token.span(),
3204 format!("expected `)` got {}", token),
3205 ));
3206 }
3207 }
3208 }
3209 }
3210 Token::ParenR(_span, ..) => {
3211 this.next_token();
3212 return Ok(first);
3213 }
3214 token => {
3215 return Err(ParserErr::new(
3216 *token.span(),
3217 format!("expected `)` or `,` got {}", token),
3218 ));
3219 }
3220 };
3221
3222 Ok(TypeExpr::Tuple(
3223 Span::from_begin_end(span_begin, span_end),
3224 elems,
3225 ))
3226 })
3227 }
3228
3229 fn parse_type_record(&mut self) -> Result<TypeExpr, ParserErr> {
3230 let span_begin = match self.current_token() {
3231 Token::BraceL(span, ..) => {
3232 self.next_token();
3233 span.begin
3234 }
3235 token => {
3236 return Err(ParserErr::new(
3237 *token.span(),
3238 format!("expected `{{` got {}", token),
3239 ));
3240 }
3241 };
3242
3243 self.with_nesting(Span::from_begin_end(span_begin, span_begin), |this| {
3244 let mut fields = Vec::new();
3245 if let Token::BraceR(span, ..) = this.current_token() {
3246 this.next_token();
3247 return Ok(TypeExpr::Record(
3248 Span::from_begin_end(span_begin, span.end),
3249 fields,
3250 ));
3251 }
3252
3253 let span_end = loop {
3254 let (name, _span) = match this.current_token() {
3255 Token::Ident(name, span, ..) => {
3256 let name = intern(&name);
3257 this.next_token();
3258 (name, span)
3259 }
3260 token => {
3261 return Err(ParserErr::new(
3262 *token.span(),
3263 format!("expected field name got {}", token),
3264 ));
3265 }
3266 };
3267
3268 match this.current_token() {
3269 Token::Colon(..) => this.next_token(),
3270 token => {
3271 return Err(ParserErr::new(
3272 *token.span(),
3273 format!("expected `:` got {}", token),
3274 ));
3275 }
3276 }
3277
3278 let ty = this.parse_type_expr()?;
3279 fields.push((name, ty));
3280
3281 match this.current_token() {
3282 Token::Comma(..) => {
3283 this.next_token();
3284 }
3285 Token::BraceR(span, ..) => {
3286 this.next_token();
3287 break span.end;
3288 }
3289 token => {
3290 return Err(ParserErr::new(
3291 *token.span(),
3292 format!("expected `}}` got {}", token),
3293 ));
3294 }
3295 }
3296 };
3297
3298 Ok(TypeExpr::Record(
3299 Span::from_begin_end(span_begin, span_end),
3300 fields,
3301 ))
3302 })
3303 }
3304
3305 fn parse_pattern(&mut self) -> Result<Pattern, ParserErr> {
3306 self.parse_pattern_cons()
3307 }
3308
3309 fn parse_pattern_cons(&mut self) -> Result<Pattern, ParserErr> {
3310 let span = *self.current_token().span();
3311 self.with_nesting(span, |this| {
3312 let mut lhs = this.parse_pattern_app()?;
3313 while let Token::ColonColon(..) = this.current_token() {
3314 this.next_token();
3315 let rhs = this.parse_pattern_cons()?;
3316 let span = Span::from_begin_end(lhs.span().begin, rhs.span().end);
3317 lhs = Pattern::Cons(span, Box::new(lhs), Box::new(rhs));
3318 }
3319 Ok(lhs)
3320 })
3321 }
3322
3323 fn parse_pattern_app(&mut self) -> Result<Pattern, ParserErr> {
3324 let mut head = self.parse_pattern_atom()?;
3325 if let Pattern::Var(var) = &head
3326 && matches!(self.current_token(), Token::Dot(..))
3327 {
3328 let mut segments = vec![var.name.clone()];
3329 let mut end = var.span.end;
3330 while matches!(self.current_token(), Token::Dot(..)) {
3331 self.next_token();
3332 match self.current_token() {
3333 Token::Ident(name, seg_span, ..) => {
3334 segments.push(intern(&name));
3335 end = seg_span.end;
3336 self.next_token();
3337 }
3338 token => {
3339 return Err(ParserErr::new(
3340 *token.span(),
3341 "expected identifier after `.` in constructor pattern",
3342 ));
3343 }
3344 }
3345 }
3346 head = Pattern::Named(
3347 Span::from_begin_end(var.span.begin, end),
3348 NameRef::from_segments(segments),
3349 vec![],
3350 );
3351 }
3352
3353 let mut args = Vec::new();
3354 while let Token::Ident(..) | Token::BracketL(..) | Token::BraceL(..) | Token::ParenL(..) =
3355 self.current_token()
3356 {
3357 let arg = self.parse_pattern_atom()?;
3358 args.push(arg);
3359 }
3360
3361 if args.is_empty() {
3362 if let Pattern::Var(var) = &head {
3363 let is_constructor = var
3364 .name
3365 .chars()
3366 .next()
3367 .map(|c| c.is_uppercase())
3368 .unwrap_or(false);
3369 if is_constructor {
3370 return Ok(Pattern::Named(
3371 var.span,
3372 NameRef::Unqualified(var.name.clone()),
3373 vec![],
3374 ));
3375 }
3376 }
3377 return Ok(head);
3378 }
3379
3380 match head {
3382 Pattern::Var(var) => {
3383 let begin = var.span.begin;
3384 let end = args.last().map(|p| p.span().end).unwrap_or(begin);
3385 Ok(Pattern::Named(
3386 Span::from_begin_end(begin, end),
3387 NameRef::Unqualified(var.name),
3388 args,
3389 ))
3390 }
3391 Pattern::Named(span, name, mut existing_args) => {
3392 existing_args.extend(args);
3393 let end = existing_args
3394 .last()
3395 .map(|p| p.span().end)
3396 .unwrap_or(span.end);
3397 Ok(Pattern::Named(
3398 Span::from_begin_end(span.begin, end),
3399 name,
3400 existing_args,
3401 ))
3402 }
3403 _ => {
3404 let span = args
3405 .first()
3406 .map(|p| *p.span())
3407 .unwrap_or_else(|| *self.current_token().span());
3408 Err(ParserErr::new(
3409 span,
3410 "constructor patterns must start with an identifier",
3411 ))
3412 }
3413 }
3414 }
3415
3416 fn parse_name_ref_with_span(
3417 &mut self,
3418 expected_message: &str,
3419 ) -> Result<(NameRef, Span), ParserErr> {
3420 let mut segments: Vec<Symbol> = Vec::new();
3421 let start = self.current_token().span().begin;
3422 let mut end = match self.current_token() {
3423 Token::Ident(name, span, ..) => {
3424 segments.push(intern(&name));
3425 self.next_token();
3426 span.end
3427 }
3428 token => return Err(ParserErr::new(*token.span(), expected_message)),
3429 };
3430
3431 while matches!(self.current_token(), Token::Dot(..)) {
3432 self.next_token();
3433 match self.current_token() {
3434 Token::Ident(name, span, ..) => {
3435 segments.push(intern(&name));
3436 end = span.end;
3437 self.next_token();
3438 }
3439 token => {
3440 return Err(ParserErr::new(
3441 *token.span(),
3442 "expected identifier after `.`",
3443 ));
3444 }
3445 }
3446 }
3447
3448 Ok((
3449 NameRef::from_segments(segments),
3450 Span::from_begin_end(start, end),
3451 ))
3452 }
3453
3454 fn parse_pattern_atom(&mut self) -> Result<Pattern, ParserErr> {
3455 match self.current_token() {
3456 Token::Ident(name, span, ..) if name == "_" => {
3457 self.next_token();
3458 Ok(Pattern::Wildcard(span))
3459 }
3460 Token::Ident(name, span, ..) => {
3461 self.next_token();
3462 Ok(Pattern::Var(Var::with_span(span, name)))
3463 }
3464 Token::BracketL(..) => self.parse_list_pattern(),
3465 Token::BraceL(..) => self.parse_dict_pattern(),
3466 Token::ParenL(..) => self.parse_paren_pattern(),
3467 token => Err(ParserErr::new(
3468 *token.span(),
3469 format!("unexpected {} in pattern", token),
3470 )),
3471 }
3472 }
3473
3474 fn parse_list_pattern(&mut self) -> Result<Pattern, ParserErr> {
3475 let span_begin = match self.current_token() {
3476 Token::BracketL(span, ..) => {
3477 self.next_token();
3478 span.begin
3479 }
3480 token => {
3481 return Err(ParserErr::new(
3482 *token.span(),
3483 format!("expected `[` got {}", token),
3484 ));
3485 }
3486 };
3487
3488 self.with_nesting(Span::from_begin_end(span_begin, span_begin), |this| {
3489 if let Token::BracketR(span, ..) = this.current_token() {
3490 this.next_token();
3491 return Ok(Pattern::List(
3492 Span::from_begin_end(span_begin, span.end),
3493 Vec::new(),
3494 ));
3495 }
3496
3497 let mut patterns = Vec::new();
3498 let span_end = loop {
3499 patterns.push(this.parse_pattern()?);
3500
3501 match this.current_token() {
3502 Token::Comma(..) => {
3503 this.next_token();
3504 }
3505 Token::BracketR(span, ..) => {
3506 this.next_token();
3507 break span.end;
3508 }
3509 token => {
3510 return Err(ParserErr::new(
3511 *token.span(),
3512 format!("expected `,` or `]` got {}", token),
3513 ));
3514 }
3515 }
3516 };
3517
3518 Ok(Pattern::List(
3519 Span::from_begin_end(span_begin, span_end),
3520 patterns,
3521 ))
3522 })
3523 }
3524
3525 fn parse_dict_pattern(&mut self) -> Result<Pattern, ParserErr> {
3526 let span_begin = match self.current_token() {
3527 Token::BraceL(span, ..) => {
3528 self.next_token();
3529 span.begin
3530 }
3531 token => {
3532 return Err(ParserErr::new(
3533 *token.span(),
3534 format!("expected `{{` got {}", token),
3535 ));
3536 }
3537 };
3538
3539 self.with_nesting(Span::from_begin_end(span_begin, span_begin), |this| {
3540 if let Token::BraceR(span, ..) = this.current_token() {
3541 this.next_token();
3542 return Ok(Pattern::Dict(
3543 Span::from_begin_end(span_begin, span.end),
3544 Vec::new(),
3545 ));
3546 }
3547
3548 let mut fields = Vec::new();
3549 let span_end = loop {
3550 match this.current_token() {
3551 Token::Ident(name, key_span, ..) => {
3552 let key_name = name;
3553 let key = intern(&key_name);
3554 this.next_token();
3555
3556 let pat = if matches!(this.current_token(), Token::Colon(..)) {
3557 this.next_token();
3558 this.parse_pattern()?
3559 } else {
3560 Pattern::Var(Var::with_span(key_span, key_name))
3561 };
3562 fields.push((key, pat));
3563
3564 match this.current_token() {
3565 Token::Comma(..) => {
3566 this.next_token();
3567 }
3568 Token::BraceR(span, ..) => {
3569 this.next_token();
3570 break span.end;
3571 }
3572 token => {
3573 return Err(ParserErr::new(
3574 *token.span(),
3575 format!("expected `,` or `}}` got {}", token),
3576 ));
3577 }
3578 }
3579 }
3580 token => {
3581 return Err(ParserErr::new(
3582 *token.span(),
3583 format!("expected identifier in dict pattern got {}", token),
3584 ));
3585 }
3586 }
3587 };
3588
3589 Ok(Pattern::Dict(
3590 Span::from_begin_end(span_begin, span_end),
3591 fields,
3592 ))
3593 })
3594 }
3595
3596 fn parse_paren_pattern(&mut self) -> Result<Pattern, ParserErr> {
3597 let span_begin = match self.current_token() {
3598 Token::ParenL(span, ..) => {
3599 self.next_token();
3600 span.begin
3601 }
3602 token => {
3603 return Err(ParserErr::new(
3604 *token.span(),
3605 format!("expected `(` got {}", token),
3606 ));
3607 }
3608 };
3609
3610 self.with_nesting(Span::from_begin_end(span_begin, span_begin), |this| {
3611 if let Token::ParenR(span, ..) = this.current_token() {
3613 this.next_token();
3614 return Ok(Pattern::Tuple(
3615 Span::from_begin_end(span_begin, span.end),
3616 Vec::new(),
3617 ));
3618 }
3619
3620 let first = this.parse_pattern()?;
3621 let mut elems = Vec::new();
3622 let span_end = match this.current_token() {
3623 Token::Comma(..) => {
3624 this.next_token();
3625 elems.push(first);
3626 loop {
3627 elems.push(this.parse_pattern()?);
3628 match this.current_token() {
3629 Token::Comma(..) => {
3630 this.next_token();
3631 }
3632 Token::ParenR(span, ..) => {
3633 this.next_token();
3634 break span.end;
3635 }
3636 token => {
3637 return Err(ParserErr::new(
3638 *token.span(),
3639 format!("expected `)` got {}", token),
3640 ));
3641 }
3642 }
3643 }
3644 }
3645 Token::ParenR(span, ..) => {
3646 this.next_token();
3647 return Ok(first.with_span(Span::from_begin_end(span_begin, span.end)));
3648 }
3649 token => {
3650 return Err(ParserErr::new(
3651 *token.span(),
3652 format!("expected `)` or `,` got {}", token),
3653 ));
3654 }
3655 };
3656
3657 Ok(Pattern::Tuple(
3658 Span::from_begin_end(span_begin, span_end),
3659 elems,
3660 ))
3661 })
3662 }
3663
3664 fn parse_literal_bool_expr(&mut self) -> Result<Expr, ParserErr> {
3666 let token = self.current_token();
3667 self.next_token();
3668 match token {
3669 Token::Bool(val, span, ..) => Ok(Expr::Bool(span, val)),
3670 token => Err(ParserErr::new(
3671 *token.span(),
3672 format!("expected `bool` got {}", token),
3673 )),
3674 }
3675 }
3676
3677 fn parse_literal_float_expr(&mut self) -> Result<Expr, ParserErr> {
3679 let token = self.current_token();
3680 self.next_token();
3681 match token {
3682 Token::Float(val, span, ..) => Ok(Expr::Float(span, val)),
3683 token => Err(ParserErr::new(
3684 *token.span(),
3685 format!("expected `float` got {}", token),
3686 )),
3687 }
3688 }
3689
3690 fn parse_literal_int_expr(&mut self) -> Result<Expr, ParserErr> {
3692 let token = self.current_token();
3693 self.next_token();
3694 match token {
3695 Token::Int(val, span, ..) => Ok(Expr::Uint(span, val)),
3696 token => Err(ParserErr::new(
3697 *token.span(),
3698 format!("expected `int` got {}", token),
3699 )),
3700 }
3701 }
3702
3703 fn parse_literal_str_expr(&mut self) -> Result<Expr, ParserErr> {
3705 let token = self.current_token();
3706 self.next_token();
3707 match token {
3708 Token::String(val, span, ..) => Ok(Expr::String(span, val)),
3709 token => Err(ParserErr::new(
3710 *token.span(),
3711 format!("expected `str` got {}", token),
3712 )),
3713 }
3714 }
3715
3716 fn parse_ident_expr(&mut self) -> Result<Expr, ParserErr> {
3718 let token = self.current_token();
3719 self.next_token();
3720 match token {
3721 Token::Ident(name, span, ..) => Ok(Expr::Var(Var::with_span(span, name))),
3722 token => Err(ParserErr::new(
3723 *token.span(),
3724 format!("expected `ident` got {}", token),
3725 )),
3726 }
3727 }
3728
3729 fn parse_hole_expr(&mut self) -> Result<Expr, ParserErr> {
3730 let token = self.current_token();
3731 self.next_token();
3732 match token {
3733 Token::Question(span, ..) => Ok(Expr::Hole(span)),
3734 token => Err(ParserErr::new(
3735 *token.span(),
3736 format!("expected `?` got {}", token),
3737 )),
3738 }
3739 }
3740}
3741
3742fn find_layout_expr_end(
3743 tokens: &[Token],
3744 start_idx: usize,
3745 block_indent: Option<usize>,
3746 is_stmt_head: impl Fn(&Token, &Token) -> bool,
3747) -> usize {
3748 let mut depth = 0usize;
3752 let mut idx = start_idx;
3753 while idx < tokens.len() {
3754 match &tokens[idx] {
3755 Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..) => depth += 1,
3756 Token::ParenR(..) | Token::BracketR(..) | Token::BraceR(..) => {
3757 depth = depth.saturating_sub(1)
3758 }
3759 Token::WhitespaceNewline(nl_span, ..) if depth == 0 => {
3760 let mut j = idx + 1;
3761 while j < tokens.len() && matches!(tokens[j], Token::WhitespaceNewline(..)) {
3762 j += 1;
3763 }
3764 if j >= tokens.len() {
3765 return idx;
3766 }
3767 if let Some(indent) = block_indent {
3768 let next_span = tokens[j].span();
3769 if next_span.begin.column < indent {
3770 return idx;
3771 }
3772 if next_span.begin.column == indent {
3773 let mut k = j + 1;
3775 while k < tokens.len() && matches!(tokens[k], Token::WhitespaceNewline(..))
3776 {
3777 k += 1;
3778 }
3779 if k < tokens.len() && is_stmt_head(&tokens[j], &tokens[k]) {
3780 return idx;
3781 }
3782 }
3783 } else {
3784 let _ = nl_span;
3785 }
3786 }
3787 _ => {}
3788 }
3789 idx += 1;
3790 }
3791 tokens.len()
3792}
3793
3794fn find_layout_header_clause_end(
3795 tokens: &[Token],
3796 start_idx: usize,
3797 is_terminator: impl Fn(&Token) -> bool,
3798) -> usize {
3799 let mut depth = 0usize;
3808 let mut idx = start_idx;
3809 while idx < tokens.len() {
3810 match &tokens[idx] {
3811 Token::ParenL(..) | Token::BracketL(..) | Token::BraceL(..) => depth += 1,
3812 Token::ParenR(..) | Token::BracketR(..) | Token::BraceR(..) => {
3813 depth = depth.saturating_sub(1)
3814 }
3815 Token::WhitespaceNewline(..) if depth == 0 => return idx,
3816 token if depth == 0 && is_terminator(token) => return idx,
3817 _ => {}
3818 }
3819 idx += 1;
3820 }
3821 tokens.len()
3822}
3823
3824fn count_expr_nodes(expr: &Expr) -> u64 {
3825 match expr {
3826 Expr::Bool(..)
3827 | Expr::Uint(..)
3828 | Expr::Int(..)
3829 | Expr::Float(..)
3830 | Expr::String(..)
3831 | Expr::Uuid(..)
3832 | Expr::DateTime(..)
3833 | Expr::Hole(..)
3834 | Expr::Var(..) => 1,
3835 Expr::Tuple(_, xs) | Expr::List(_, xs) => {
3836 1 + xs.iter().map(|e| count_expr_nodes(e)).sum::<u64>()
3837 }
3838 Expr::Dict(_, kvs) => 1 + kvs.values().map(|e| count_expr_nodes(e)).sum::<u64>(),
3839 Expr::RecordUpdate(_, base, updates) => {
3840 1 + count_expr_nodes(base) + updates.values().map(|e| count_expr_nodes(e)).sum::<u64>()
3841 }
3842 Expr::App(_, f, x) => 1 + count_expr_nodes(f) + count_expr_nodes(x),
3843 Expr::Project(_, e, _) => 1 + count_expr_nodes(e),
3844 Expr::Lam(_, _, _, ann, constraints, body) => {
3845 let ann_nodes = ann.as_ref().map(count_type_expr_nodes).unwrap_or(0);
3846 let constraint_nodes = constraints
3847 .iter()
3848 .map(count_type_constraint_nodes)
3849 .sum::<u64>();
3850 1 + ann_nodes + constraint_nodes + count_expr_nodes(body)
3851 }
3852 Expr::Let(_, _, ann, def, body) => {
3853 let ann_nodes = ann.as_ref().map(count_type_expr_nodes).unwrap_or(0);
3854 1 + ann_nodes + count_expr_nodes(def) + count_expr_nodes(body)
3855 }
3856 Expr::LetRec(_, bindings, body) => {
3857 let binding_nodes = bindings
3858 .iter()
3859 .map(|(_, ann, def)| {
3860 ann.as_ref().map(count_type_expr_nodes).unwrap_or(0) + count_expr_nodes(def)
3861 })
3862 .sum::<u64>();
3863 1 + binding_nodes + count_expr_nodes(body)
3864 }
3865 Expr::Ite(_, a, b, c) => {
3866 1 + count_expr_nodes(a) + count_expr_nodes(b) + count_expr_nodes(c)
3867 }
3868 Expr::Match(_, scrutinee, arms) => {
3869 1 + count_expr_nodes(scrutinee)
3870 + arms
3871 .iter()
3872 .map(|(pat, e)| count_pattern_nodes(pat) + count_expr_nodes(e))
3873 .sum::<u64>()
3874 }
3875 Expr::Ann(_, e, ty) => 1 + count_expr_nodes(e) + count_type_expr_nodes(ty),
3876 }
3877}
3878
3879fn count_pattern_nodes(pat: &Pattern) -> u64 {
3880 match pat {
3881 Pattern::Wildcard(..) | Pattern::Var(..) => 1,
3882 Pattern::Named(_, _, ps) | Pattern::Tuple(_, ps) | Pattern::List(_, ps) => {
3883 1 + ps.iter().map(count_pattern_nodes).sum::<u64>()
3884 }
3885 Pattern::Cons(_, a, b) => 1 + count_pattern_nodes(a) + count_pattern_nodes(b),
3886 Pattern::Dict(_, fields) => {
3887 1 + fields
3888 .iter()
3889 .map(|(_, p)| count_pattern_nodes(p))
3890 .sum::<u64>()
3891 }
3892 }
3893}
3894
3895fn count_type_constraint_nodes(c: &TypeConstraint) -> u64 {
3896 1 + count_type_expr_nodes(&c.typ)
3897}
3898
3899fn count_type_expr_nodes(ty: &TypeExpr) -> u64 {
3900 match ty {
3901 TypeExpr::Name(..) => 1,
3902 TypeExpr::App(_, a, b) | TypeExpr::Fun(_, a, b) => {
3903 1 + count_type_expr_nodes(a) + count_type_expr_nodes(b)
3904 }
3905 TypeExpr::Tuple(_, elems) => 1 + elems.iter().map(count_type_expr_nodes).sum::<u64>(),
3906 TypeExpr::Record(_, fields) => {
3907 1 + fields
3908 .iter()
3909 .map(|(_, t)| count_type_expr_nodes(t))
3910 .sum::<u64>()
3911 }
3912 }
3913}
3914
3915#[cfg(test)]
3916mod tests {
3917 use std::sync::Arc;
3918
3919 use crate::error::ParserErr;
3920 use rexlang_ast::{
3921 app, assert_expr_eq, b, d,
3922 expr::{Decl, Expr, Pattern, Scope, TypeExpr, Var},
3923 f, l, s, tup, u, v,
3924 };
3925 use rexlang_lexer::{Token, span, span::Span};
3926
3927 use super::*;
3928
3929 fn parse(code: &str) -> Arc<Expr> {
3930 let mut parser = Parser::new(Token::tokenize(code).unwrap());
3931 parser.parse_program(&mut GasMeter::default()).unwrap().expr
3932 }
3933
3934 fn lam(param: &str, body: Arc<Expr>) -> Arc<Expr> {
3935 Arc::new(Expr::Lam(
3936 Span::default(),
3937 Scope::new_sync(),
3938 Var::new(param),
3939 None,
3940 Vec::new(),
3941 body,
3942 ))
3943 }
3944
3945 #[test]
3946 fn test_parse_comment() {
3947 let mut parser = Parser::new(Token::tokenize("true {- this is a boolean -}").unwrap());
3948 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
3949 assert_expr_eq!(expr, b!(span!(1:1 - 1:5); true));
3950
3951 let mut parser = Parser::new(Token::tokenize("{- this is a boolean -} false").unwrap());
3952 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
3953 assert_expr_eq!(expr, b!(span!(1:25 - 1:30); false));
3954
3955 let mut parser = Parser::new(Token::tokenize("(3.54 {- this is a float -}, {- this is an int -} 42, false {- this is a boolean -})").unwrap());
3956 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
3957 assert_expr_eq!(
3958 expr,
3959 tup!(
3960 span!(1:1 - 1:85);
3961 f!(span!(1:2 - 1:6); 3.54),
3962 u!(span!(1:51 - 1:53); 42),
3963 b!(span!(1:55 - 1:60); false),
3964 )
3965 );
3966 }
3967
3968 #[test]
3969 fn test_max_nesting_depth_is_enforced_during_parse() {
3970 let code = format!("{}0{}", "(".repeat(6), ")".repeat(6));
3971 let mut parser = Parser::new(Token::tokenize(&code).unwrap());
3972 parser.set_limits(ParserLimits {
3973 max_nesting: Some(5),
3974 });
3975
3976 let errs = parser.parse_program(&mut GasMeter::default()).unwrap_err();
3977 assert!(
3978 errs.iter()
3979 .any(|e| e.to_string().contains("maximum nesting depth exceeded")),
3980 "expected a max-nesting parse error, got: {errs:?}"
3981 );
3982 }
3983
3984 #[test]
3985 fn test_max_nesting_binary_chain() {
3986 let code = std::iter::repeat_n("1", 12).collect::<Vec<_>>().join(" + ");
3987 let mut parser = Parser::new(Token::tokenize(&code).unwrap());
3988 parser.set_limits(ParserLimits {
3989 max_nesting: Some(5),
3990 });
3991
3992 let errs = parser.parse_program(&mut GasMeter::default()).unwrap_err();
3993 assert!(
3994 errs.iter()
3995 .any(|e| e.to_string().contains("maximum nesting depth exceeded")),
3996 "expected a max-nesting parse error, got: {errs:?}"
3997 );
3998 }
3999
4000 #[test]
4001 fn test_max_nesting_type_fun_chain() {
4002 let ty_chain = std::iter::repeat_n("a", 12)
4003 .collect::<Vec<_>>()
4004 .join(" -> ");
4005 let code = format!("let t: {ty_chain} = x in t");
4006 let mut parser = Parser::new(Token::tokenize(&code).unwrap());
4007 parser.set_limits(ParserLimits {
4008 max_nesting: Some(5),
4009 });
4010
4011 let errs = parser.parse_program(&mut GasMeter::default()).unwrap_err();
4012 assert!(
4013 errs.iter()
4014 .any(|e| e.to_string().contains("maximum nesting depth exceeded")),
4015 "expected a max-nesting parse error, got: {errs:?}"
4016 );
4017 }
4018
4019 #[test]
4020 fn test_max_nesting_cons_pattern_chain() {
4021 let pattern = (1..=12)
4022 .map(|i| format!("x{i}"))
4023 .collect::<Vec<_>>()
4024 .join(" :: ");
4025 let code = format!("match xs when {pattern} -> xs");
4026 let mut parser = Parser::new(Token::tokenize(&code).unwrap());
4027 parser.set_limits(ParserLimits {
4028 max_nesting: Some(5),
4029 });
4030
4031 let errs = parser.parse_program(&mut GasMeter::default()).unwrap_err();
4032 assert!(
4033 errs.iter()
4034 .any(|e| e.to_string().contains("maximum nesting depth exceeded")),
4035 "expected a max-nesting parse error, got: {errs:?}"
4036 );
4037 }
4038
4039 #[test]
4040 fn test_add() {
4041 let mut parser = Parser::new(Token::tokenize("1 + 2").unwrap());
4042 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
4043 assert_expr_eq!(
4044 expr,
4045 app!(
4046 span!(1:1 - 1:6);
4047 app!(
4048 span!(1:1 - 1:4);
4049 v!(span!(1:3 - 1:4); "+"),
4050 u!(span!(1:1 - 1:2); 1)
4051 ),
4052 u!(span!(1:5 - 1:6); 2)
4053 )
4054 );
4055
4056 let mut parser = Parser::new(Token::tokenize("(6.9 + 3.17)").unwrap());
4057 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
4058 assert_expr_eq!(
4059 expr,
4060 app!(
4061 span!(1:1 - 1:13);
4062 app!(
4063 span!(1:2 - 1:7);
4064 v!(span!(1:6 - 1:7); "+"),
4065 f!(span!(1:2 - 1:5); 6.9)
4066 ),
4067 f!(span!(1:8 - 1:12); 3.17)
4068 )
4069 );
4070
4071 let mut parser = Parser::new(Token::tokenize("(+) 420").unwrap());
4072 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
4073 assert_expr_eq!(
4074 expr,
4075 app!(
4076 span!(1:1 - 1:8);
4077 v!(span!(1:1 - 1:4); "+"),
4078 u!(span!(1:5 - 1:8); 420)
4079 )
4080 );
4081 }
4082
4083 #[test]
4084 fn test_parse_type_decl() {
4085 let code = r#"
4086 type MyADT a b c = MyCtor1 | MyCtor2 a b | MyCtor3 { field1: c }
4087 42
4088 "#;
4089 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4090 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4091 assert_eq!(program.decls.len(), 1);
4092 match &program.decls[0] {
4093 Decl::Type(decl) => {
4094 assert_eq!(decl.name, intern("MyADT"));
4095 assert_eq!(decl.params, vec![intern("a"), intern("b"), intern("c")]);
4096 assert_eq!(decl.variants.len(), 3);
4097 assert_eq!(decl.variants[0].name, intern("MyCtor1"));
4098 assert!(decl.variants[0].args.is_empty());
4099 assert_eq!(decl.variants[1].name, intern("MyCtor2"));
4100 assert_eq!(decl.variants[1].args.len(), 2);
4101 assert_eq!(decl.variants[2].name, intern("MyCtor3"));
4102 match &decl.variants[2].args[0] {
4103 TypeExpr::Record(_, fields) => {
4104 assert_eq!(fields.len(), 1);
4105 assert_eq!(fields[0].0, intern("field1"));
4106 assert!(matches!(
4107 fields[0].1,
4108 TypeExpr::Name(_, ref n) if n.as_ref() == "c"
4109 ));
4110 }
4111 other => panic!("expected record type, got {other:?}"),
4112 }
4113 }
4114 other => panic!("expected type decl, got {other:?}"),
4115 }
4116 assert_expr_eq!(program.expr, u!(span!(3:9 - 3:11); 42));
4117 }
4118
4119 #[test]
4120 fn test_parse_fn_decl_simple() {
4121 let code = r#"
4122 fn add x: i32 -> y: i32 -> i32 = x + y
4123 add 1 2
4124 "#;
4125 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4126 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4127 assert_eq!(program.decls.len(), 1);
4128 match &program.decls[0] {
4129 Decl::Fn(fd) => {
4130 assert_eq!(fd.name.name, intern("add"));
4131 assert_eq!(fd.params.len(), 2);
4132 assert_eq!(fd.params[0].0.name, intern("x"));
4133 assert!(matches!(
4134 fd.params[0].1,
4135 TypeExpr::Name(_, ref n) if n.as_ref() == "i32"
4136 ));
4137 assert_eq!(fd.params[1].0.name, intern("y"));
4138 assert!(matches!(
4139 fd.params[1].1,
4140 TypeExpr::Name(_, ref n) if n.as_ref() == "i32"
4141 ));
4142 assert!(matches!(fd.ret, TypeExpr::Name(_, ref n) if n.as_ref() == "i32"));
4143 assert!(fd.constraints.is_empty());
4144 }
4145 other => panic!("expected fn decl, got {other:?}"),
4146 }
4147 }
4148
4149 #[test]
4150 fn test_parse_fn_decl_signature_form_with_lambda_body() {
4151 let code = r#"
4152 fn add : i32 -> i32 -> i32 = \x y -> x + y
4153 add 1 2
4154 "#;
4155 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4156 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4157 assert_eq!(program.decls.len(), 1);
4158 match &program.decls[0] {
4159 Decl::Fn(fd) => {
4160 assert_eq!(fd.name.name, intern("add"));
4161 assert_eq!(fd.params.len(), 2);
4162 assert_eq!(fd.params[0].0.name, intern("x"));
4163 assert!(matches!(
4164 fd.params[0].1,
4165 TypeExpr::Name(_, ref n) if n.as_ref() == "i32"
4166 ));
4167 assert_eq!(fd.params[1].0.name, intern("y"));
4168 assert!(matches!(
4169 fd.params[1].1,
4170 TypeExpr::Name(_, ref n) if n.as_ref() == "i32"
4171 ));
4172 assert!(matches!(fd.ret, TypeExpr::Name(_, ref n) if n.as_ref() == "i32"));
4173 assert!(fd.constraints.is_empty());
4174 assert!(!matches!(fd.body.as_ref(), Expr::Lam(..)));
4175 }
4176 other => panic!("expected fn decl, got {other:?}"),
4177 }
4178 }
4179
4180 #[test]
4181 fn test_parse_fn_sig_multiline_lambda() {
4182 let code = r#"
4183 fn f : i32 -> i32 = \x ->
4184 x + 1
4185 f 1
4186 "#;
4187 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4188 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4189 assert_eq!(program.decls.len(), 1);
4190 match &program.decls[0] {
4191 Decl::Fn(fd) => {
4192 assert_eq!(fd.name.name, intern("f"));
4193 assert_eq!(fd.params.len(), 1);
4194 assert_eq!(fd.params[0].0.name, intern("x"));
4195 assert!(matches!(
4196 fd.params[0].1,
4197 TypeExpr::Name(_, ref n) if n.as_ref() == "i32"
4198 ));
4199 assert!(matches!(fd.ret, TypeExpr::Name(_, ref n) if n.as_ref() == "i32"));
4200 }
4201 other => panic!("expected fn decl, got {other:?}"),
4202 }
4203 }
4204
4205 #[test]
4206 fn test_parse_fn_decl_signature_form_eta_expands_non_lambda_body() {
4207 let code = r#"
4208 fn inc : i32 -> i32 = add 1
4209 inc
4210 "#;
4211 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4212 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4213 assert_eq!(program.decls.len(), 1);
4214 match &program.decls[0] {
4215 Decl::Fn(fd) => {
4216 assert_eq!(fd.name.name, intern("inc"));
4217 assert_eq!(fd.params.len(), 1);
4218 assert_eq!(fd.params[0].0.name, intern("_arg0"));
4219 assert!(matches!(
4220 fd.params[0].1,
4221 TypeExpr::Name(_, ref n) if n.as_ref() == "i32"
4222 ));
4223 assert!(matches!(fd.ret, TypeExpr::Name(_, ref n) if n.as_ref() == "i32"));
4224 }
4225 other => panic!("expected fn decl, got {other:?}"),
4226 }
4227 }
4228
4229 #[test]
4230 fn test_parse_fn_decl_signature_form_where_constraints() {
4231 let code = r#"
4232 fn my_fun : a -> b -> c where Iterable (a, b) = \x y -> x
4233 my_fun
4234 "#;
4235 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4236 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4237 assert_eq!(program.decls.len(), 1);
4238 match &program.decls[0] {
4239 Decl::Fn(fd) => {
4240 assert_eq!(fd.name.name, intern("my_fun"));
4241 assert_eq!(fd.params.len(), 2);
4242 assert!(matches!(
4243 fd.constraints[0].class,
4244 ref n if n.as_ref() == "Iterable"
4245 ));
4246 }
4247 other => panic!("expected fn decl, got {other:?}"),
4248 }
4249 }
4250
4251 #[test]
4252 fn test_parse_fn_decl_signature_form_rejects_mismatched_lambda_arity() {
4253 let code = r#"
4254 fn add : i32 -> i32 -> i32 = \x -> x
4255 add
4256 "#;
4257 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4258 assert!(parser.parse_program(&mut GasMeter::default()).is_err());
4259 }
4260
4261 #[test]
4262 fn test_parse_fn_decl_where_constraints() {
4263 let code = r#"
4264 fn my_fun x: a -> y: b -> c where Iterable (a, b) = x
4265 my_fun
4266 "#;
4267 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4268 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4269 assert_eq!(program.decls.len(), 1);
4270 match &program.decls[0] {
4271 Decl::Fn(fd) => {
4272 assert_eq!(fd.name.name, intern("my_fun"));
4273 assert_eq!(fd.params.len(), 2);
4274 assert!(matches!(
4275 fd.constraints[0].class,
4276 ref n if n.as_ref() == "Iterable"
4277 ));
4278 match &fd.constraints[0].typ {
4279 TypeExpr::Tuple(_, elems) => {
4280 assert_eq!(elems.len(), 2);
4281 assert!(matches!(elems[0], TypeExpr::Name(_, ref n) if n.as_ref() == "a"));
4282 assert!(matches!(elems[1], TypeExpr::Name(_, ref n) if n.as_ref() == "b"));
4283 }
4284 other => panic!("expected tuple constraint type, got {other:?}"),
4285 }
4286 }
4287 other => panic!("expected fn decl, got {other:?}"),
4288 }
4289 }
4290
4291 #[test]
4292 fn test_parse_declare_fn_decl_where_constraints() {
4293 let code = r#"
4294 declare fn my_fun x: a -> y: b -> c where Iterable (a, b)
4295 42
4296 "#;
4297 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4298 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4299 assert_eq!(program.decls.len(), 1);
4300 match &program.decls[0] {
4301 Decl::DeclareFn(fd) => {
4302 assert_eq!(fd.name.name, intern("my_fun"));
4303 assert_eq!(fd.params.len(), 2);
4304 assert!(matches!(
4305 fd.constraints[0].class,
4306 ref n if n.as_ref() == "Iterable"
4307 ));
4308 match &fd.constraints[0].typ {
4309 TypeExpr::Tuple(_, elems) => {
4310 assert_eq!(elems.len(), 2);
4311 assert!(matches!(elems[0], TypeExpr::Name(_, ref n) if n.as_ref() == "a"));
4312 assert!(matches!(elems[1], TypeExpr::Name(_, ref n) if n.as_ref() == "b"));
4313 }
4314 other => panic!("expected tuple constraint type, got {other:?}"),
4315 }
4316 }
4317 other => panic!("expected declare fn decl, got {other:?}"),
4318 }
4319 assert_expr_eq!(program.expr, u!(span!(3:9 - 3:11); 42));
4320 }
4321
4322 #[test]
4323 fn test_parse_declare_fn_decl_bare_signature() {
4324 let code = r#"
4325 declare fn info a -> string where Show a
4326 0
4327 "#;
4328 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4329 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4330 assert_eq!(program.decls.len(), 1);
4331 match &program.decls[0] {
4332 Decl::DeclareFn(fd) => {
4333 assert_eq!(fd.name.name, intern("info"));
4334 assert_eq!(fd.params.len(), 1);
4335 assert!(matches!(
4336 fd.params[0].1,
4337 TypeExpr::Name(_, ref n) if n.as_ref() == "a"
4338 ));
4339 assert!(matches!(
4340 fd.ret,
4341 TypeExpr::Name(_, ref n) if n.as_ref() == "string"
4342 ));
4343 assert_eq!(fd.constraints.len(), 1);
4344 assert!(matches!(
4345 fd.constraints[0].class,
4346 ref n if n.as_ref() == "Show"
4347 ));
4348 }
4349 other => panic!("expected declare fn decl, got {other:?}"),
4350 }
4351 }
4352
4353 #[test]
4354 fn test_parse_declare_fn_decl_bare_signature_with_colon() {
4355 let code = r#"
4356 declare fn info : a -> string where Show a
4357 0
4358 "#;
4359 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4360 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4361 assert_eq!(program.decls.len(), 1);
4362 match &program.decls[0] {
4363 Decl::DeclareFn(fd) => {
4364 assert_eq!(fd.name.name, intern("info"));
4365 assert_eq!(fd.params.len(), 1);
4366 assert!(matches!(
4367 fd.params[0].1,
4368 TypeExpr::Name(_, ref n) if n.as_ref() == "a"
4369 ));
4370 assert!(matches!(
4371 fd.ret,
4372 TypeExpr::Name(_, ref n) if n.as_ref() == "string"
4373 ));
4374 assert_eq!(fd.constraints.len(), 1);
4375 assert!(matches!(
4376 fd.constraints[0].class,
4377 ref n if n.as_ref() == "Show"
4378 ));
4379 }
4380 other => panic!("expected declare fn decl, got {other:?}"),
4381 }
4382 }
4383
4384 #[test]
4385 fn test_parse_declare_fn_decl_rejects_body() {
4386 let code = r#"
4387 declare fn my_fun x: a -> a = x
4388 0
4389 "#;
4390 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4391 assert!(parser.parse_program(&mut GasMeter::default()).is_err());
4392 }
4393
4394 #[test]
4395 fn test_parse_fn_decl_param_fun_type_requires_parens() {
4396 let code = r#"
4397 fn apply x: (a -> c) -> y: a -> c = x y
4398 apply
4399 "#;
4400 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4401 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4402 assert_eq!(program.decls.len(), 1);
4403 match &program.decls[0] {
4404 Decl::Fn(fd) => {
4405 assert_eq!(fd.name.name, intern("apply"));
4406 assert_eq!(fd.params.len(), 2);
4407 assert_eq!(fd.params[0].0.name, intern("x"));
4408 assert!(matches!(fd.params[0].1, TypeExpr::Fun(_, _, _)));
4409 assert_eq!(fd.params[1].0.name, intern("y"));
4410 assert!(matches!(
4411 fd.params[1].1,
4412 TypeExpr::Name(_, ref n) if n.as_ref() == "a"
4413 ));
4414 assert!(matches!(fd.ret, TypeExpr::Name(_, ref n) if n.as_ref() == "c"));
4415 }
4416 other => panic!("expected fn decl, got {other:?}"),
4417 }
4418 }
4419
4420 #[test]
4421 fn test_parse_fn_decl_parenthesized_params_allow_fun_types() {
4422 let code = r#"
4423 fn reduce (f: a -> a -> a) -> (x: t a) -> a = x
4424 reduce
4425 "#;
4426 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4427 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4428 assert_eq!(program.decls.len(), 1);
4429 match &program.decls[0] {
4430 Decl::Fn(fd) => {
4431 assert_eq!(fd.name.name, intern("reduce"));
4432 assert_eq!(fd.params.len(), 2);
4433 assert_eq!(fd.params[0].0.name, intern("f"));
4434 assert!(matches!(fd.params[0].1, TypeExpr::Fun(..)));
4435 assert_eq!(fd.params[1].0.name, intern("x"));
4436 assert!(matches!(fd.params[1].1, TypeExpr::App(..)));
4437 assert!(matches!(fd.ret, TypeExpr::Name(_, ref n) if n.as_ref() == "a"));
4438 }
4439 other => panic!("expected fn decl, got {other:?}"),
4440 }
4441 }
4442
4443 #[test]
4444 fn test_parse_fn_decl_parenthesized_params_require_arrow_delimiter() {
4445 let code = r#"
4446 fn reduce (f: a -> a -> a) (x: t a) -> a = x
4447 reduce
4448 "#;
4449 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4450 assert!(parser.parse_program(&mut GasMeter::default()).is_err());
4451 }
4452
4453 #[test]
4454 fn test_parse_unit_type() {
4455 let code = r#"
4456 fn unit_id x: () -> () = x
4457 unit_id ()
4458 "#;
4459 let mut parser = Parser::new(Token::tokenize(code).unwrap());
4460 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
4461 assert_eq!(program.decls.len(), 1);
4462 match &program.decls[0] {
4463 Decl::Fn(fd) => {
4464 assert_eq!(fd.name.name, intern("unit_id"));
4465 assert_eq!(fd.params.len(), 1);
4466 assert!(matches!(fd.params[0].1, TypeExpr::Tuple(_, ref xs) if xs.is_empty()));
4467 assert!(matches!(fd.ret, TypeExpr::Tuple(_, ref xs) if xs.is_empty()));
4468 }
4469 other => panic!("expected fn decl, got {other:?}"),
4470 }
4471 }
4472
4473 #[test]
4474 fn test_sub() {
4475 let mut parser = Parser::new(Token::tokenize("1 - 2").unwrap());
4476 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
4477 assert_expr_eq!(
4478 expr,
4479 app!(
4480 span!(1:1 - 1:6);
4481 app!(
4482 span!(1:1 - 1:4);
4483 v!(span!(1:3 - 1:4); "-"),
4484 u!(span!(1:1 - 1:2); 1)
4485 ),
4486 u!(span!(1:5 - 1:6); 2)
4487 )
4488 );
4489
4490 let mut parser = Parser::new(Token::tokenize("(6.9 - 3.17)").unwrap());
4491 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
4492 assert_expr_eq!(
4493 expr,
4494 app!(
4495 span!(1:1 - 1:13);
4496 app!(
4497 span!(1:2 - 1:7);
4498 v!(span!(1:6 - 1:7); "-"),
4499 f!(span!(1:2 - 1:5); 6.9)
4500 ),
4501 f!(span!(1:8 - 1:12); 3.17)
4502 )
4503 );
4504
4505 let mut parser = Parser::new(Token::tokenize("(-) 4.20").unwrap());
4506 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
4507 assert_expr_eq!(
4508 expr,
4509 app!(
4510 span!(1:1 - 1:9);
4511 v!(span!(1:1 - 1:4); "-"),
4512 f!(span!(1:5 - 1:9); 4.20)
4513 )
4514 );
4515 }
4516
4517 #[test]
4518 fn test_negate() {
4519 let mut parser = Parser::new(Token::tokenize("-1").unwrap());
4520 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
4521 assert_expr_eq!(
4522 expr,
4523 app!(
4524 span!(1:1 - 1:3);
4525 v!(span!(1:1 - 1:2); "negate"),
4526 u!(span!(1:2 - 1:3); 1)
4527 )
4528 );
4529
4530 let mut parser = Parser::new(Token::tokenize("(-1)").unwrap());
4531 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
4532 assert_expr_eq!(
4533 expr,
4534 app!(
4535 span!(1:1 - 1:5);
4536 v!(span!(1:2 - 1:3); "negate"),
4537 u!(span!(1:3 - 1:4); 1)
4538 )
4539 );
4540
4541 let mut parser = Parser::new(Token::tokenize("(- 6.9)").unwrap());
4542 let expr = parser.parse_program(&mut GasMeter::default()).unwrap().expr;
4543 assert_expr_eq!(
4544 expr,
4545 app!(
4546 span!(1:1 - 1:8);
4547 v!(span!(1:2 - 1:3); "negate"),
4548 f!(span!(1:4 - 1:7); 6.9)
4549 )
4550 );
4551 }
4552
4553 #[test]
4554 fn test_application_associativity() {
4555 let expr = parse("f x y z");
4556 let expected = app!(app!(app!(v!("f"), v!("x")), v!("y")), v!("z"));
4557
4558 assert_expr_eq!(expr, expected; ignore span);
4559 }
4560
4561 #[test]
4562 fn test_projection_expr() {
4563 let expr = parse("x.field");
4564 let expected = Arc::new(Expr::Project(Span::default(), v!("x"), intern("field")));
4565
4566 assert_expr_eq!(expr, expected; ignore span);
4567 }
4568
4569 #[test]
4570 fn test_projection_tuple_index_expr() {
4571 let expr = parse("x.0");
4572 let expected = Arc::new(Expr::Project(Span::default(), v!("x"), intern("0")));
4573
4574 assert_expr_eq!(expr, expected; ignore span);
4575 }
4576
4577 #[test]
4578 fn test_projection_expr_colon_rejected() {
4579 let mut parser = Parser::new(Token::tokenize("x:field").unwrap());
4580 assert!(parser.parse_program(&mut GasMeter::default()).is_err());
4581 }
4582
4583 #[test]
4584 fn test_projection_binds_tighter_than_application() {
4585 let expr = parse("show p.x");
4586 let expected = app!(
4587 v!("show"),
4588 Arc::new(Expr::Project(Span::default(), v!("p"), intern("x")))
4589 );
4590 assert_expr_eq!(expr, expected; ignore span);
4591 }
4592
4593 #[test]
4594 fn test_projection_can_be_applied_without_parens() {
4595 let expr = parse("x.field y");
4596 let expected = app!(
4597 Arc::new(Expr::Project(Span::default(), v!("x"), intern("field"))),
4598 v!("y")
4599 );
4600 assert_expr_eq!(expr, expected; ignore span);
4601 }
4602
4603 #[test]
4604 fn test_list_cons_expr() {
4605 let expr = parse("x::xs");
4606 let expected = app!(app!(v!("Cons"), v!("x")), v!("xs"));
4607 assert_expr_eq!(expr, expected; ignore span);
4608 }
4609
4610 #[test]
4611 fn test_list_cons_expr_right_associative() {
4612 let expr = parse("x::y::zs");
4613 let expected = app!(
4614 app!(v!("Cons"), v!("x")),
4615 app!(app!(v!("Cons"), v!("y")), v!("zs"))
4616 );
4617 assert_expr_eq!(expr, expected; ignore span);
4618 }
4619
4620 #[test]
4621 fn test_list_cons_constructor_call_expr() {
4622 let expr = parse("Cons x xs");
4623 let expected = app!(app!(v!("Cons"), v!("x")), v!("xs"));
4624 assert_expr_eq!(expr, expected; ignore span);
4625 }
4626
4627 #[test]
4628 fn test_operator_precedence() {
4629 let expr = parse("1 + 2 * 3 - 4");
4630 let expected = app!(
4631 app!(v!("+"), u!(1)),
4632 app!(app!(v!("-"), app!(app!(v!("*"), u!(2)), u!(3))), u!(4))
4633 );
4634
4635 assert_expr_eq!(expr, expected; ignore span);
4636 }
4637
4638 #[test]
4639 fn test_collections_and_tuples() {
4640 let expr = parse("([1, 2], { foo = \"bar\", baz = false }, (true, 9))");
4641 let expected = tup!(
4642 l!(u!(1), u!(2)),
4643 d!(foo = s!("bar"), baz = b!(false)),
4644 tup!(b!(true), u!(9))
4645 );
4646
4647 assert_expr_eq!(expr, expected; ignore span);
4648 }
4649
4650 #[test]
4651 fn test_record_update_expr() {
4652 let expr = parse("{ foo with { x = 1, y = 2 } }");
4653 match expr.as_ref() {
4654 Expr::RecordUpdate(_, base, updates) => {
4655 assert_expr_eq!(base.clone(), v!("foo"); ignore span);
4656 assert_expr_eq!(updates.get(&intern("x")).unwrap().clone(), u!(1); ignore span);
4657 assert_expr_eq!(updates.get(&intern("y")).unwrap().clone(), u!(2); ignore span);
4658 }
4659 other => panic!("expected record update, got {other:?}"),
4660 }
4661 }
4662
4663 #[test]
4664 fn test_brace_expr_prefers_dict_literal() {
4665 let expr = parse("{ foo = 1 }");
4666 match expr.as_ref() {
4667 Expr::Dict(_, kvs) => {
4668 assert_eq!(kvs.len(), 1);
4669 assert_expr_eq!(kvs.get(&intern("foo")).unwrap().clone(), u!(1); ignore span);
4670 }
4671 other => panic!("expected dict literal, got {other:?}"),
4672 }
4673 }
4674
4675 #[test]
4676 fn test_record_update_empty_updates() {
4677 let expr = parse("{ foo with { } }");
4678 match expr.as_ref() {
4679 Expr::RecordUpdate(_, base, updates) => {
4680 assert_expr_eq!(base.clone(), v!("foo"); ignore span);
4681 assert!(updates.is_empty());
4682 }
4683 other => panic!("expected record update, got {other:?}"),
4684 }
4685 }
4686
4687 #[test]
4688 fn test_lambda_and_let_chain() {
4689 let expr = parse("let inc = \\x -> x + 1, dbl = \\x -> x * 2 in \\y -> inc (dbl y)");
4690
4691 let inc = lam("x", app!(app!(v!("+"), v!("x")), u!(1)));
4692 let dbl = lam("x", app!(app!(v!("*"), v!("x")), u!(2)));
4693 let body = lam("y", app!(v!("inc"), app!(v!("dbl"), v!("y"))));
4694
4695 let expected = Arc::new(Expr::Let(
4696 Span::default(),
4697 Var::new("inc"),
4698 None,
4699 inc,
4700 Arc::new(Expr::Let(Span::default(), Var::new("dbl"), None, dbl, body)),
4701 ));
4702
4703 assert_expr_eq!(expr, expected; ignore span);
4704 }
4705
4706 #[test]
4707 fn test_let_rec_single_binding() {
4708 let expr = parse("let rec fact = \\n -> if n == 0 then 1 else n * fact (n - 1) in fact 5");
4709 match expr.as_ref() {
4710 Expr::LetRec(_, bindings, body) => {
4711 assert_eq!(bindings.len(), 1);
4712 let (name, ann, def) = &bindings[0];
4713 assert_eq!(name.name.as_ref(), "fact");
4714 assert!(ann.is_none());
4715 assert!(matches!(def.as_ref(), Expr::Lam(..)));
4716 assert_expr_eq!(body.clone(), app!(v!("fact"), u!(5)); ignore span);
4717 }
4718 other => panic!("expected let rec, got {other:?}"),
4719 }
4720 }
4721
4722 #[test]
4723 fn test_let_rec_mutual_bindings() {
4724 let expr = parse("let rec even = \\n -> odd n, odd = \\n -> even n in (even 0, odd 1)");
4725 match expr.as_ref() {
4726 Expr::LetRec(_, bindings, body) => {
4727 assert_eq!(bindings.len(), 2);
4728 assert_eq!(bindings[0].0.name.as_ref(), "even");
4729 assert_eq!(bindings[1].0.name.as_ref(), "odd");
4730 assert!(matches!(bindings[0].2.as_ref(), Expr::Lam(..)));
4731 assert!(matches!(bindings[1].2.as_ref(), Expr::Lam(..)));
4732 assert!(matches!(body.as_ref(), Expr::Tuple(..)));
4733 }
4734 other => panic!("expected let rec, got {other:?}"),
4735 }
4736 }
4737
4738 #[test]
4739 fn test_and_is_ident() {
4740 let expr = parse("let and = 1 in and");
4741 match expr.as_ref() {
4742 Expr::Let(_, var, _, def, body) => {
4743 assert_eq!(var.name.as_ref(), "and");
4744 assert_expr_eq!(def.clone(), u!(1); ignore span);
4745 assert_expr_eq!(body.clone(), v!("and"); ignore span);
4746 }
4747 other => panic!("expected let, got {other:?}"),
4748 }
4749 }
4750
4751 #[test]
4752 fn test_let_tuple_destructuring() {
4753 let expr = parse("let (x, y) = (1, 2) in x");
4754
4755 let pat = Pattern::Tuple(
4756 Span::default(),
4757 vec![Pattern::Var(Var::new("x")), Pattern::Var(Var::new("y"))],
4758 );
4759 let expected = Arc::new(Expr::Match(
4760 Span::default(),
4761 tup!(u!(1), u!(2)),
4762 vec![(pat, v!("x"))],
4763 ));
4764
4765 assert_expr_eq!(expr, expected; ignore span);
4766 }
4767
4768 #[test]
4769 fn test_type_annotations() {
4770 let expr = parse("let x: u8 = foo in x");
4771 match expr.as_ref() {
4772 Expr::Let(_, var, Some(TypeExpr::Name(_, name)), _def, _body) => {
4773 assert_eq!(var.name.as_ref(), "x");
4774 assert_eq!(name.as_ref(), "u8");
4775 }
4776 other => panic!("expected typed let, got {other:?}"),
4777 }
4778
4779 let expr = parse("foo bar is u8");
4780 match expr.as_ref() {
4781 Expr::Ann(_, inner, TypeExpr::Name(_, name)) => {
4782 assert_eq!(name.as_ref(), "u8");
4783 assert!(matches!(inner.as_ref(), Expr::App(..)));
4784 }
4785 other => panic!("expected type assertion, got {other:?}"),
4786 }
4787
4788 let expr = parse("foo is Sample.Correctness");
4789 match expr.as_ref() {
4790 Expr::Ann(_, inner, TypeExpr::Name(_, name)) => {
4791 assert_eq!(name.as_ref(), "Sample.Correctness");
4792 assert!(matches!(inner.as_ref(), Expr::Var(_)));
4793 }
4794 other => panic!("expected qualified type assertion, got {other:?}"),
4795 }
4796
4797 let expr = parse("\\ (a : f32) -> a");
4798 match expr.as_ref() {
4799 Expr::Lam(_, _scope, param, Some(TypeExpr::Name(_, name)), constraints, body) => {
4800 assert_eq!(param.name.as_ref(), "a");
4801 assert_eq!(name.as_ref(), "f32");
4802 assert!(constraints.is_empty());
4803 assert!(matches!(body.as_ref(), Expr::Var(_)));
4804 }
4805 other => panic!("expected typed lambda, got {other:?}"),
4806 }
4807
4808 let expr = parse("let t: f32 -> str -> Result bool str = x in t");
4809 match expr.as_ref() {
4810 Expr::Let(_, _var, Some(ann), _def, _body) => {
4811 fn is_name(expr: &TypeExpr, expected: &str) -> bool {
4812 matches!(expr, TypeExpr::Name(_, name) if name.as_ref() == expected)
4813 }
4814
4815 match ann {
4816 TypeExpr::Fun(_, arg, ret) => {
4817 assert!(is_name(arg, "f32"));
4818 match ret.as_ref() {
4819 TypeExpr::Fun(_, arg2, ret2) => {
4820 assert!(is_name(arg2, "str"));
4821 match ret2.as_ref() {
4822 TypeExpr::App(_, fun, arg3) => {
4823 match fun.as_ref() {
4824 TypeExpr::App(_, fun2, arg2) => {
4825 assert!(is_name(fun2, "Result"));
4826 assert!(is_name(arg2, "bool"));
4827 }
4828 _ => panic!("expected Result bool str"),
4829 }
4830 assert!(is_name(arg3, "str"));
4831 }
4832 _ => panic!("expected Result bool str"),
4833 }
4834 }
4835 _ => panic!("expected f32 -> str -> Result bool str"),
4836 }
4837 }
4838 _ => panic!("expected function type annotation"),
4839 }
4840 }
4841 other => panic!("expected typed let, got {other:?}"),
4842 }
4843 }
4844
4845 #[test]
4846 fn test_match_named_patterns() {
4847 let expr = parse("match named when Ok x -> x when Err e -> e when _ -> default");
4848 let expected = Arc::new(Expr::Match(
4849 Span::default(),
4850 v!("named"),
4851 vec![
4852 (
4853 Pattern::Named(
4854 Span::default(),
4855 "Ok".into(),
4856 vec![Pattern::Var(Var::new("x"))],
4857 ),
4858 v!("x"),
4859 ),
4860 (
4861 Pattern::Named(
4862 Span::default(),
4863 "Err".into(),
4864 vec![Pattern::Var(Var::new("e"))],
4865 ),
4866 v!("e"),
4867 ),
4868 (Pattern::Wildcard(Span::default()), v!("default")),
4869 ],
4870 ));
4871
4872 assert_expr_eq!(expr, expected; ignore span);
4873 }
4874
4875 #[test]
4876 fn test_match_list_patterns() {
4877 let expr = parse(
4878 "match list when [] -> empty when [x] -> x when [x, y, z] -> z when x::xs -> xs when _ -> fallback",
4879 );
4880 let expected = Arc::new(Expr::Match(
4881 Span::default(),
4882 v!("list"),
4883 vec![
4884 (Pattern::List(Span::default(), vec![]), v!("empty")),
4885 (
4886 Pattern::List(Span::default(), vec![Pattern::Var(Var::new("x"))]),
4887 v!("x"),
4888 ),
4889 (
4890 Pattern::List(
4891 Span::default(),
4892 vec![
4893 Pattern::Var(Var::new("x")),
4894 Pattern::Var(Var::new("y")),
4895 Pattern::Var(Var::new("z")),
4896 ],
4897 ),
4898 v!("z"),
4899 ),
4900 (
4901 Pattern::Cons(
4902 Span::default(),
4903 Box::new(Pattern::Var(Var::new("x"))),
4904 Box::new(Pattern::Var(Var::new("xs"))),
4905 ),
4906 v!("xs"),
4907 ),
4908 (Pattern::Wildcard(Span::default()), v!("fallback")),
4909 ],
4910 ));
4911
4912 assert_expr_eq!(expr, expected; ignore span);
4913 }
4914
4915 #[test]
4916 fn test_match_nested_patterns() {
4917 let expr = parse("match t when Cons x (Cons _ xs) -> xs when Pair (Just a) (Just b) -> a");
4918 let expected = Arc::new(Expr::Match(
4919 Span::default(),
4920 v!("t"),
4921 vec![
4922 (
4923 Pattern::Named(
4924 Span::default(),
4925 "Cons".into(),
4926 vec![
4927 Pattern::Var(Var::new("x")),
4928 Pattern::Named(
4929 Span::default(),
4930 "Cons".into(),
4931 vec![
4932 Pattern::Wildcard(Span::default()),
4933 Pattern::Var(Var::new("xs")),
4934 ],
4935 ),
4936 ],
4937 ),
4938 v!("xs"),
4939 ),
4940 (
4941 Pattern::Named(
4942 Span::default(),
4943 "Pair".into(),
4944 vec![
4945 Pattern::Named(
4946 Span::default(),
4947 "Just".into(),
4948 vec![Pattern::Var(Var::new("a"))],
4949 ),
4950 Pattern::Named(
4951 Span::default(),
4952 "Just".into(),
4953 vec![Pattern::Var(Var::new("b"))],
4954 ),
4955 ],
4956 ),
4957 v!("a"),
4958 ),
4959 ],
4960 ));
4961
4962 assert_expr_eq!(expr, expected; ignore span);
4963 }
4964
4965 #[test]
4966 fn test_match_dict_pattern() {
4967 let expr = parse("match obj when {foo, bar} -> foo bar");
4968 let expected = Arc::new(Expr::Match(
4969 Span::default(),
4970 v!("obj"),
4971 vec![(
4972 Pattern::Dict(
4973 Span::default(),
4974 vec![
4975 ("foo".into(), Pattern::Var(Var::new("foo"))),
4976 ("bar".into(), Pattern::Var(Var::new("bar"))),
4977 ],
4978 ),
4979 app!(v!("foo"), v!("bar")),
4980 )],
4981 ));
4982
4983 assert_expr_eq!(expr, expected; ignore span);
4984 }
4985
4986 #[test]
4987 fn test_match_cons_associativity() {
4988 let expr = parse("match xs when h::t::u -> u");
4989 let expected = Arc::new(Expr::Match(
4990 Span::default(),
4991 v!("xs"),
4992 vec![(
4993 Pattern::Cons(
4994 Span::default(),
4995 Box::new(Pattern::Var(Var::new("h"))),
4996 Box::new(Pattern::Cons(
4997 Span::default(),
4998 Box::new(Pattern::Var(Var::new("t"))),
4999 Box::new(Pattern::Var(Var::new("u"))),
5000 )),
5001 ),
5002 v!("u"),
5003 )],
5004 ));
5005
5006 assert_expr_eq!(expr, expected; ignore span);
5007 }
5008
5009 #[test]
5010 fn test_match_wildcard_cons() {
5011 let expr = parse("match xs when (_::_) -> xs");
5012 let expected = Arc::new(Expr::Match(
5013 Span::default(),
5014 v!("xs"),
5015 vec![(
5016 Pattern::Cons(
5017 Span::default(),
5018 Box::new(Pattern::Wildcard(Span::default())),
5019 Box::new(Pattern::Wildcard(Span::default())),
5020 ),
5021 v!("xs"),
5022 )],
5023 ));
5024
5025 assert_expr_eq!(expr, expected; ignore span);
5026 }
5027
5028 #[test]
5029 fn test_match_empty_dict_pattern() {
5030 let expr = parse("match obj when {} -> obj");
5031 let expected = Arc::new(Expr::Match(
5032 Span::default(),
5033 v!("obj"),
5034 vec![(Pattern::Dict(Span::default(), vec![]), v!("obj"))],
5035 ));
5036
5037 assert_expr_eq!(expr, expected; ignore span);
5038 }
5039
5040 #[test]
5041 fn test_import_clause_all() {
5042 let code = "import foo.bar (*)\n()";
5043 let mut parser = Parser::new(Token::tokenize(code).unwrap());
5044 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
5045 let Decl::Import(import) = &program.decls[0] else {
5046 panic!("expected import decl");
5047 };
5048 assert_eq!(import.alias, intern("bar"));
5049 assert!(matches!(import.clause, Some(ImportClause::All)));
5050 }
5051
5052 #[test]
5053 fn test_import_clause_items_with_alias() {
5054 let code = "import foo.bar (x, y as z)\n()";
5055 let mut parser = Parser::new(Token::tokenize(code).unwrap());
5056 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
5057 let Decl::Import(import) = &program.decls[0] else {
5058 panic!("expected import decl");
5059 };
5060 assert_eq!(import.alias, intern("bar"));
5061 let Some(ImportClause::Items(items)) = &import.clause else {
5062 panic!("expected import items");
5063 };
5064 assert_eq!(items.len(), 2);
5065 assert_eq!(items[0].name, intern("x"));
5066 assert_eq!(items[0].alias, None);
5067 assert_eq!(items[1].name, intern("y"));
5068 assert_eq!(items[1].alias, Some(intern("z")));
5069 }
5070
5071 #[test]
5072 fn test_import_clause_rejects_module_alias_combo() {
5073 let code = "import foo.bar (x) as Bar\n()";
5074 let mut parser = Parser::new(Token::tokenize(code).unwrap());
5075 let err = parser.parse_program(&mut GasMeter::default()).unwrap_err();
5076 assert!(
5077 err[0]
5078 .message
5079 .contains("cannot combine `as <alias>` with import clause")
5080 );
5081 }
5082
5083 #[test]
5084 fn test_import_clause_rejects_duplicate_local_names() {
5085 let code = "import foo.bar (x, y as x)\n()";
5086 let mut parser = Parser::new(Token::tokenize(code).unwrap());
5087 let err = parser.parse_program(&mut GasMeter::default()).unwrap_err();
5088 assert!(err[0].message.contains("duplicate imported name `x`"));
5089 }
5090
5091 #[test]
5092 fn test_import_relative_current_dir_path() {
5093 let code = "import ./foo/bar (x)\n()";
5094 let mut parser = Parser::new(Token::tokenize(code).unwrap());
5095 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
5096 let Decl::Import(import) = &program.decls[0] else {
5097 panic!("expected import decl");
5098 };
5099 match &import.path {
5100 ImportPath::Local { segments, sha } => {
5101 assert_eq!(segments, &vec![intern("foo"), intern("bar")]);
5102 assert_eq!(sha, &None);
5103 }
5104 other => panic!("expected local import path, got {other:?}"),
5105 }
5106 assert_eq!(import.alias, intern("bar"));
5107 }
5108
5109 #[test]
5110 fn test_import_relative_parent_dir_path() {
5111 let code = "import ../../foo/bar as FB\n()";
5112 let mut parser = Parser::new(Token::tokenize(code).unwrap());
5113 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
5114 let Decl::Import(import) = &program.decls[0] else {
5115 panic!("expected import decl");
5116 };
5117 match &import.path {
5118 ImportPath::Local { segments, sha } => {
5119 assert_eq!(
5120 segments,
5121 &vec![
5122 intern("super"),
5123 intern("super"),
5124 intern("foo"),
5125 intern("bar")
5126 ]
5127 );
5128 assert_eq!(sha, &None);
5129 }
5130 other => panic!("expected local import path, got {other:?}"),
5131 }
5132 assert_eq!(import.alias, intern("FB"));
5133 }
5134
5135 #[test]
5136 fn test_errors() {
5137 let mut parser = Parser::new(Token::tokenize("1 + 2 + in + 3").unwrap());
5138 let res = parser.parse_program(&mut GasMeter::default());
5139 assert_eq!(
5140 res,
5141 Err(vec![ParserErr::new(
5142 Span::new(1, 9, 1, 11),
5143 "unexpected in"
5144 )])
5145 );
5146
5147 let mut parser = Parser::new(Token::tokenize("1 + 2 in + 3").unwrap());
5148 let res = parser.parse_program(&mut GasMeter::default());
5149 assert_eq!(
5150 res,
5151 Err(vec![ParserErr::new(Span::new(1, 7, 1, 9), "unexpected in")])
5152 );
5153
5154 let mut parser = Parser::new(Token::tokenize("get 0 [ ").unwrap());
5155 let res = parser.parse_program(&mut GasMeter::default());
5156 assert_eq!(
5157 res,
5158 Err(vec![ParserErr::new(
5159 Span::new(1, 12, 1, 12),
5160 "unexpected EOF"
5161 )])
5162 );
5163
5164 let mut parser = Parser::new(Token::tokenize("elem0 ( ").unwrap());
5165 let res = parser.parse_program(&mut GasMeter::default());
5166 assert_eq!(
5167 res,
5168 Err(vec![ParserErr::new(
5169 Span::new(1, 10, 1, 10),
5170 "unexpected EOF"
5171 )])
5172 );
5173
5174 let mut parser = Parser::new(
5175 Token::tokenize(
5176 "
5177 { a = 1, b }
5178 { a = 1, b = 2, c }
5179 { a = 1, b = 3, c = 3, d }
5180 ",
5181 )
5182 .unwrap(),
5183 );
5184 let res = parser.parse_program(&mut GasMeter::default());
5185 assert_eq!(
5186 res,
5187 Err(vec![
5188 ParserErr::new(Span::new(2, 24, 2, 25), "expected `=`"),
5189 ParserErr::new(Span::new(3, 31, 3, 32), "expected `=`"),
5190 ParserErr::new(Span::new(4, 38, 4, 39), "expected `=`")
5191 ])
5192 );
5193 }
5194
5195 #[test]
5196 fn test_typeclass_where_is_optional() {
5197 let code = r#"
5198class Default a
5199 default : a
5200
5201instance Default i32
5202 default = 0
5203
5204default
5205"#;
5206
5207 let mut parser = Parser::new(Token::tokenize(code).unwrap());
5208 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
5209 assert_eq!(program.decls.len(), 2);
5210
5211 match &program.decls[0] {
5212 Decl::Class(decl) => {
5213 assert_eq!(decl.name, intern("Default"));
5214 assert_eq!(decl.methods.len(), 1);
5215 assert_eq!(decl.methods[0].name, intern("default"));
5216 }
5217 other => panic!("expected class decl, got {other:?}"),
5218 }
5219
5220 match &program.decls[1] {
5221 Decl::Instance(decl) => {
5222 assert_eq!(decl.class, intern("Default"));
5223 assert_eq!(decl.methods.len(), 1);
5224 assert_eq!(decl.methods[0].name, intern("default"));
5225 }
5226 other => panic!("expected instance decl, got {other:?}"),
5227 }
5228 }
5229
5230 #[test]
5231 fn test_typeclass_where_optional_does_not_force_method_block() {
5232 let code = r#"
5235class Marker a
5236
5237instance Marker i32
5238
5239 true
5240"#;
5241
5242 let mut parser = Parser::new(Token::tokenize(code).unwrap());
5243 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
5244 assert_eq!(program.decls.len(), 2);
5245 assert!(matches!(program.expr.as_ref(), Expr::Bool(..)));
5246 }
5247
5248 #[test]
5249 fn test_parse_instance_with_qualified_class_name() {
5250 let code = r#"
5251instance Sample.Default i32
5252 default = 0
5253
5254default
5255"#;
5256
5257 let mut parser = Parser::new(Token::tokenize(code).unwrap());
5258 let program = parser.parse_program(&mut GasMeter::default()).unwrap();
5259 assert_eq!(program.decls.len(), 1);
5260
5261 let Decl::Instance(decl) = &program.decls[0] else {
5262 panic!("expected instance decl");
5263 };
5264 assert_eq!(decl.class, intern("Sample.Default"));
5265 assert_eq!(decl.methods.len(), 1);
5266 assert_eq!(decl.methods[0].name, intern("default"));
5267 }
5268
5269 #[test]
5270 fn test_parse_top_level_hole_expr() {
5271 let expr = parse("?");
5272 assert!(matches!(expr.as_ref(), Expr::Hole(..)), "expr={expr:#?}");
5273 }
5274
5275 #[test]
5276 fn test_parse_hole_in_let_with_annotation() {
5277 let expr = parse("let x : i32 = ? in x");
5278 match expr.as_ref() {
5279 Expr::Let(_, _var, ann, def, body) => {
5280 assert!(ann.is_some(), "expected annotation");
5281 assert!(matches!(def.as_ref(), Expr::Hole(..)), "def={def:#?}");
5282 assert!(matches!(body.as_ref(), Expr::Var(..)), "body={body:#?}");
5283 }
5284 other => panic!("expected let expr, got {other:#?}"),
5285 }
5286 }
5287
5288 #[test]
5289 fn test_parse_hole_in_nested_expression_positions() {
5290 let expr = parse("(\\f -> f ?) (\\x -> x)");
5291 match expr.as_ref() {
5292 Expr::App(_, lhs, rhs) => {
5293 assert!(matches!(rhs.as_ref(), Expr::Lam(..)), "rhs={rhs:#?}");
5294 match lhs.as_ref() {
5295 Expr::Lam(_, _, _param, _ann, _constraints, body) => match body.as_ref() {
5296 Expr::App(_, f, arg) => {
5297 assert!(matches!(f.as_ref(), Expr::Var(..)), "f={f:#?}");
5298 assert!(matches!(arg.as_ref(), Expr::Hole(..)), "arg={arg:#?}");
5299 }
5300 other => panic!("expected app in lambda body, got {other:#?}"),
5301 },
5302 other => panic!("expected lambda lhs, got {other:#?}"),
5303 }
5304 }
5305 other => panic!("expected top-level app, got {other:#?}"),
5306 }
5307 }
5308
5309 #[test]
5310 fn test_parse_hole_not_allowed_in_type_annotation_failure_case() {
5311 let mut parser = Parser::new(Token::tokenize("let x : ? = 1 in x").unwrap());
5312 let errs = parser.parse_program(&mut GasMeter::default()).unwrap_err();
5313 assert!(
5314 errs.iter()
5315 .any(|e| e.message.contains("expected type") || e.message.contains("unexpected")),
5316 "errs={errs:#?}"
5317 );
5318 }
5319}