1use crate::ast::{
7 AnonStructField, ArgMode, ArrayLitExpr, AssignStatement, AssignTarget, AssocFnCallExpr, Ast,
8 BinaryExpr, BinaryOp, BlockExpr, BoolLit, BreakExpr, CallArg, CallExpr, CheckedBlockExpr,
9 ComptimeBlockExpr, ComptimeUnrollForExpr, ConstDecl, ContinueExpr, DestructureBinding,
10 DestructureField, Directive, DirectiveArg, Directives, DropFn, EnumDecl, EnumStructLitExpr,
11 EnumVariant, Expr, FieldDecl, FieldExpr, FieldInit, FloatLit, ForExpr, Function, Ident, IfExpr,
12 IndexExpr, IntLit, IntrinsicArg, IntrinsicCallExpr, Item, LetPattern, LetStatement, LoopExpr,
13 MatchArm, MatchExpr, Method, MethodCallExpr, NegIntLit, Param, ParamMode, ParenExpr, PathExpr,
14 PathPattern, Pattern, PatternBinding, PatternFieldBinding, ReturnExpr, SelfExpr, SelfParam,
15 Statement, StringLit, StructDecl, StructLitExpr, TypeExpr, TypeLitExpr, UnaryExpr, UnaryOp,
16 UnitLit, Visibility, WhileExpr,
17};
18use chumsky::input::{Input as ChumskyInput, MapExtra, Stream, ValueInput};
19use chumsky::prelude::*;
20use chumsky::recovery::via_parser;
21use chumsky::recursive::Direct;
22use gruel_error::{CompileError, CompileErrors, ErrorKind, MultiErrorResult};
23use gruel_lexer::TokenKind;
24use gruel_span::{FileId, Span};
25use lasso::{Spur, ThreadedRodeo};
26use std::borrow::Cow;
27
28use chumsky::extra::SimpleState;
29
30#[derive(Clone, Copy)]
33pub struct PrimitiveTypeSpurs {
34 pub i8: Spur,
35 pub i16: Spur,
36 pub i32: Spur,
37 pub i64: Spur,
38 pub isize: Spur,
39 pub u8: Spur,
40 pub u16: Spur,
41 pub u32: Spur,
42 pub u64: Spur,
43 pub usize: Spur,
44 pub f16: Spur,
45 pub f32: Spur,
46 pub f64: Spur,
47 pub bool: Spur,
48 pub self_type: Spur,
50}
51
52impl PrimitiveTypeSpurs {
53 pub fn new(interner: &mut ThreadedRodeo) -> Self {
55 Self {
56 i8: interner.get_or_intern("i8"),
57 i16: interner.get_or_intern("i16"),
58 i32: interner.get_or_intern("i32"),
59 i64: interner.get_or_intern("i64"),
60 isize: interner.get_or_intern("isize"),
61 u8: interner.get_or_intern("u8"),
62 u16: interner.get_or_intern("u16"),
63 u32: interner.get_or_intern("u32"),
64 u64: interner.get_or_intern("u64"),
65 usize: interner.get_or_intern("usize"),
66 f16: interner.get_or_intern("f16"),
67 f32: interner.get_or_intern("f32"),
68 f64: interner.get_or_intern("f64"),
69 bool: interner.get_or_intern("bool"),
70 self_type: interner.get_or_intern("Self"),
71 }
72 }
73}
74
75#[derive(Clone, Copy)]
81pub struct ParserState {
82 pub syms: PrimitiveTypeSpurs,
84 pub file_id: FileId,
86}
87
88impl ParserState {
89 pub fn new(syms: PrimitiveTypeSpurs, file_id: FileId) -> Self {
91 Self { syms, file_id }
92 }
93}
94
95type ParserExtras<'src> = extra::Full<Rich<'src, TokenKind>, SimpleState<ParserState>, ()>;
98
99type GruelParser<'src, I, O> = Boxed<'src, 'src, I, O, ParserExtras<'src>>;
102
103#[inline]
110fn offset_to_u32(offset: usize) -> u32 {
111 debug_assert!(
112 offset <= u32::MAX as usize,
113 "offset {} exceeds u32::MAX (source file too large)",
114 offset
115 );
116 offset as u32
117}
118
119fn to_gruel_span_with_file(span: SimpleSpan, file_id: FileId) -> Span {
126 Span::with_file(file_id, offset_to_u32(span.start), offset_to_u32(span.end))
127}
128
129fn to_gruel_span(span: SimpleSpan) -> Span {
132 Span::new(offset_to_u32(span.start), offset_to_u32(span.end))
133}
134
135#[inline]
138fn span_from_extra<'src, I>(e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>) -> Span
139where
140 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
141{
142 let file_id = e.state().0.file_id;
143 to_gruel_span_with_file(e.span(), file_id)
144}
145
146fn ident_parser<'src, I>() -> GruelParser<'src, I, Ident>
148where
149 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
150{
151 select! {
152 TokenKind::Ident(name) = e => Ident {
153 name,
154 span: span_from_extra(e),
155 },
156 }
157 .boxed()
158}
159
160fn primitive_type_parser<'src, I>() -> GruelParser<'src, I, TypeExpr>
163where
164 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
165{
166 let i8_parser =
170 just(TokenKind::I8).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
171 let syms = e.state().0.syms;
172 TypeExpr::Named(Ident {
173 name: syms.i8,
174 span: span_from_extra(e),
175 })
176 });
177 let i16_parser =
178 just(TokenKind::I16).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
179 let syms = e.state().0.syms;
180 TypeExpr::Named(Ident {
181 name: syms.i16,
182 span: span_from_extra(e),
183 })
184 });
185 let i32_parser =
186 just(TokenKind::I32).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
187 let syms = e.state().0.syms;
188 TypeExpr::Named(Ident {
189 name: syms.i32,
190 span: span_from_extra(e),
191 })
192 });
193 let i64_parser =
194 just(TokenKind::I64).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
195 let syms = e.state().0.syms;
196 TypeExpr::Named(Ident {
197 name: syms.i64,
198 span: span_from_extra(e),
199 })
200 });
201 let u8_parser =
202 just(TokenKind::U8).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
203 let syms = e.state().0.syms;
204 TypeExpr::Named(Ident {
205 name: syms.u8,
206 span: span_from_extra(e),
207 })
208 });
209 let u16_parser =
210 just(TokenKind::U16).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
211 let syms = e.state().0.syms;
212 TypeExpr::Named(Ident {
213 name: syms.u16,
214 span: span_from_extra(e),
215 })
216 });
217 let u32_parser =
218 just(TokenKind::U32).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
219 let syms = e.state().0.syms;
220 TypeExpr::Named(Ident {
221 name: syms.u32,
222 span: span_from_extra(e),
223 })
224 });
225 let u64_parser =
226 just(TokenKind::U64).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
227 let syms = e.state().0.syms;
228 TypeExpr::Named(Ident {
229 name: syms.u64,
230 span: span_from_extra(e),
231 })
232 });
233 let isize_parser =
234 just(TokenKind::Isize).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
235 let syms = e.state().0.syms;
236 TypeExpr::Named(Ident {
237 name: syms.isize,
238 span: span_from_extra(e),
239 })
240 });
241 let usize_parser =
242 just(TokenKind::Usize).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
243 let syms = e.state().0.syms;
244 TypeExpr::Named(Ident {
245 name: syms.usize,
246 span: span_from_extra(e),
247 })
248 });
249 let f16_parser =
250 just(TokenKind::F16).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
251 let syms = e.state().0.syms;
252 TypeExpr::Named(Ident {
253 name: syms.f16,
254 span: span_from_extra(e),
255 })
256 });
257 let f32_parser =
258 just(TokenKind::F32).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
259 let syms = e.state().0.syms;
260 TypeExpr::Named(Ident {
261 name: syms.f32,
262 span: span_from_extra(e),
263 })
264 });
265 let f64_parser =
266 just(TokenKind::F64).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
267 let syms = e.state().0.syms;
268 TypeExpr::Named(Ident {
269 name: syms.f64,
270 span: span_from_extra(e),
271 })
272 });
273 let bool_parser =
274 just(TokenKind::Bool).map_with(|_, e: &mut MapExtra<'src, '_, I, ParserExtras<'src>>| {
275 let syms = e.state().0.syms;
276 TypeExpr::Named(Ident {
277 name: syms.bool,
278 span: span_from_extra(e),
279 })
280 });
281
282 choice((
283 i8_parser.boxed(),
284 i16_parser.boxed(),
285 i32_parser.boxed(),
286 i64_parser.boxed(),
287 isize_parser.boxed(),
288 u8_parser.boxed(),
289 u16_parser.boxed(),
290 u32_parser.boxed(),
291 u64_parser.boxed(),
292 usize_parser.boxed(),
293 f16_parser.boxed(),
294 f32_parser.boxed(),
295 f64_parser.boxed(),
296 bool_parser.boxed(),
297 ))
298 .boxed()
299}
300
301fn type_parser<'src, I>() -> GruelParser<'src, I, TypeExpr>
303where
304 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
305{
306 recursive(
307 move |ty: Recursive<Direct<'src, 'src, I, TypeExpr, ParserExtras<'src>>>| {
308 let unit_type = just(TokenKind::LParen)
310 .then(just(TokenKind::RParen))
311 .map_with(|_, e| TypeExpr::Unit(span_from_extra(e)));
312
313 let never_type =
315 just(TokenKind::Bang).map_with(|_, e| TypeExpr::Never(span_from_extra(e)));
316
317 let array_type = just(TokenKind::LBracket)
319 .ignore_then(ty.clone())
320 .then_ignore(just(TokenKind::Semi))
321 .then(select! {
322 TokenKind::Int(n) => n,
323 })
324 .then_ignore(just(TokenKind::RBracket))
325 .map_with(|(element, length), e| TypeExpr::Array {
326 element: Box::new(element),
327 length,
328 span: span_from_extra(e),
329 });
330
331 let anon_struct_field: GruelParser<'src, I, AnonStructField> = ident_parser()
334 .then_ignore(just(TokenKind::Colon))
335 .then(ty.clone())
336 .map_with(|(name, field_ty), e| AnonStructField {
337 name,
338 ty: field_ty,
339 span: span_from_extra(e),
340 })
341 .boxed();
342
343 let anon_struct_fields: GruelParser<'src, I, Vec<AnonStructField>> = anon_struct_field
344 .separated_by(just(TokenKind::Comma))
345 .allow_trailing()
346 .collect::<Vec<_>>()
347 .boxed();
348
349 let anon_struct_type = just(TokenKind::Struct)
350 .ignore_then(just(TokenKind::LBrace))
351 .ignore_then(anon_struct_fields)
352 .then_ignore(just(TokenKind::RBrace))
353 .map_with(|fields, e| TypeExpr::AnonymousStruct {
354 fields,
355 methods: vec![],
356 span: span_from_extra(e),
357 });
358
359 let ptr_const_type = just(TokenKind::Ptr)
361 .ignore_then(just(TokenKind::Const))
362 .ignore_then(ty.clone())
363 .map_with(|pointee, e| TypeExpr::PointerConst {
364 pointee: Box::new(pointee),
365 span: span_from_extra(e),
366 });
367
368 let ptr_mut_type = just(TokenKind::Ptr)
369 .ignore_then(just(TokenKind::Mut))
370 .ignore_then(ty.clone())
371 .map_with(|pointee, e| TypeExpr::PointerMut {
372 pointee: Box::new(pointee),
373 span: span_from_extra(e),
374 });
375
376 let named_type = ident_parser().map(TypeExpr::Named);
378
379 let self_type = just(TokenKind::SelfType).map_with(|_, e| {
381 let span = span_from_extra(e);
382 TypeExpr::Named(Ident {
383 name: e.state().syms.self_type,
384 span,
385 })
386 });
387
388 let types_a: GruelParser<'src, I, TypeExpr> = choice((
391 unit_type.boxed(),
392 never_type.boxed(),
393 array_type.boxed(),
394 anon_struct_type.boxed(),
395 ptr_const_type.boxed(),
396 ))
397 .boxed();
398 let types_b: GruelParser<'src, I, TypeExpr> = choice((
399 ptr_mut_type.boxed(),
400 primitive_type_parser().boxed(),
401 self_type.boxed(),
402 named_type.boxed(),
403 ))
404 .boxed();
405 choice((types_a, types_b)).boxed()
406 },
407 )
408 .boxed()
409}
410
411fn param_mode_parser<'src, I>() -> GruelParser<'src, I, ParamMode>
413where
414 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
415{
416 choice((
417 just(TokenKind::Inout).to(ParamMode::Inout).boxed(),
418 just(TokenKind::Borrow).to(ParamMode::Borrow).boxed(),
419 just(TokenKind::Comptime).to(ParamMode::Comptime).boxed(),
420 ))
421 .boxed()
422}
423
424fn param_parser<'src, I>() -> GruelParser<'src, I, Param>
426where
427 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
428{
429 just(TokenKind::Comptime)
430 .or_not()
431 .then(param_mode_parser().or_not())
432 .then(ident_parser())
433 .then_ignore(just(TokenKind::Colon))
434 .then(type_parser())
435 .map_with(|(((is_comptime, mode), name), ty), e| Param {
436 is_comptime: is_comptime.is_some(),
437 mode: mode.unwrap_or(ParamMode::Normal),
438 name,
439 ty,
440 span: span_from_extra(e),
441 })
442 .boxed()
443}
444
445fn field_decl_parser<'src, I>() -> GruelParser<'src, I, FieldDecl>
447where
448 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
449{
450 ident_parser()
451 .then_ignore(just(TokenKind::Colon))
452 .then(type_parser())
453 .map_with(|(name, ty), e| FieldDecl {
454 name,
455 ty,
456 span: span_from_extra(e),
457 })
458 .boxed()
459}
460
461fn field_decls_parser<'src, I>() -> GruelParser<'src, I, Vec<FieldDecl>>
463where
464 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
465{
466 field_decl_parser()
467 .separated_by(just(TokenKind::Comma))
468 .allow_trailing()
469 .collect::<Vec<_>>()
470 .boxed()
471}
472
473fn params_parser<'src, I>() -> GruelParser<'src, I, Vec<Param>>
475where
476 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
477{
478 param_parser()
479 .separated_by(just(TokenKind::Comma))
480 .collect::<Vec<_>>()
481 .boxed()
482}
483
484fn directive_parser<'src, I>() -> GruelParser<'src, I, Directive>
486where
487 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
488{
489 just(TokenKind::At)
490 .ignore_then(ident_parser())
491 .then(
492 ident_parser()
493 .map(DirectiveArg::Ident)
494 .separated_by(just(TokenKind::Comma))
495 .allow_trailing()
496 .collect::<Vec<_>>()
497 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen))
498 .or_not(),
499 )
500 .map_with(|(name, args), e| Directive {
501 name,
502 args: args.unwrap_or_default(),
503 span: span_from_extra(e),
504 })
505 .boxed()
506}
507
508fn directives_parser<'src, I>() -> GruelParser<'src, I, Directives>
510where
511 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
512{
513 directive_parser()
517 .repeated()
518 .collect::<Vec<_>>()
519 .map(|v| v.into_iter().collect())
520 .boxed()
521}
522
523fn arg_mode_parser<'src, I>() -> GruelParser<'src, I, ArgMode>
525where
526 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
527{
528 choice((
529 just(TokenKind::Inout).to(ArgMode::Inout).boxed(),
530 just(TokenKind::Borrow).to(ArgMode::Borrow).boxed(),
531 ))
532 .boxed()
533}
534
535fn call_arg_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, CallArg>
537where
538 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
539{
540 arg_mode_parser()
541 .or_not()
542 .then(expr)
543 .map_with(|(mode, expr), e| CallArg {
544 mode: mode.unwrap_or(ArgMode::Normal),
545 expr,
546 span: span_from_extra(e),
547 })
548 .boxed()
549}
550
551fn call_args_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, Vec<CallArg>>
553where
554 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
555{
556 call_arg_parser(expr)
557 .separated_by(just(TokenKind::Comma))
558 .collect::<Vec<_>>()
559 .boxed()
560}
561
562fn args_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, Vec<Expr>>
564where
565 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
566{
567 expr.separated_by(just(TokenKind::Comma))
568 .collect::<Vec<_>>()
569 .boxed()
570}
571
572fn field_init_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, FieldInit>
574where
575 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
576{
577 let explicit = ident_parser()
579 .then_ignore(just(TokenKind::Colon))
580 .then(expr)
581 .map_with(|(name, value), e| FieldInit {
582 name,
583 value: Box::new(value),
584 span: span_from_extra(e),
585 });
586
587 let shorthand = ident_parser().map_with(|name, e| FieldInit {
589 value: Box::new(Expr::Ident(name)),
590 name,
591 span: span_from_extra(e),
592 });
593
594 choice((explicit, shorthand)).boxed()
595}
596
597fn field_inits_parser<'src, I>(
599 expr: GruelParser<'src, I, Expr>,
600) -> GruelParser<'src, I, Vec<FieldInit>>
601where
602 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
603{
604 field_init_parser(expr)
605 .separated_by(just(TokenKind::Comma))
606 .allow_trailing()
607 .collect::<Vec<_>>()
608 .boxed()
609}
610
611fn make_binary(left: Expr, op: BinaryOp, right: Expr) -> Expr {
613 let span = Span::new(left.span().start, right.span().end);
614 Expr::Binary(BinaryExpr {
615 left: Box::new(left),
616 op,
617 right: Box::new(right),
618 span,
619 })
620}
621
622fn make_unary(op: UnaryOp, operand: Expr, op_span: SimpleSpan) -> Expr {
624 let span = Span::new(offset_to_u32(op_span.start), operand.span().end);
625 Expr::Unary(UnaryExpr {
626 op,
627 operand: Box::new(operand),
628 span,
629 })
630}
631
632fn expr_parser<'src, I>() -> GruelParser<'src, I, Expr>
650where
651 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
652{
653 recursive(
654 |expr: Recursive<Direct<'src, 'src, I, Expr, ParserExtras<'src>>>| {
655 let atom: GruelParser<I, Expr> = atom_parser(expr.clone().boxed());
657
658 let unary: GruelParser<I, Expr> = {
660 let prefix_op: GruelParser<I, (UnaryOp, SimpleSpan)> = choice((
661 just(TokenKind::Minus)
662 .map_with(|_, e| (UnaryOp::Neg, e.span()))
663 .boxed(),
664 just(TokenKind::Bang)
665 .map_with(|_, e| (UnaryOp::Not, e.span()))
666 .boxed(),
667 just(TokenKind::Tilde)
668 .map_with(|_, e| (UnaryOp::BitNot, e.span()))
669 .boxed(),
670 ))
671 .boxed();
672 prefix_op
673 .repeated()
674 .collect::<Vec<_>>()
675 .then(atom.clone())
676 .map(|(mut ops, mut rhs)| {
677 ops.reverse();
679 for (op, span) in ops {
680 rhs = make_unary(op, rhs, span);
681 }
682 rhs
683 })
684 .boxed()
685 };
686
687 macro_rules! left_binary {
690 ($prev:expr, $op_parser:expr) => {{
691 let prev: GruelParser<I, Expr> = $prev;
692 let op: GruelParser<I, BinaryOp> = $op_parser;
693 prev.clone()
694 .foldl(op.then(prev).repeated(), |l, (op, r)| make_binary(l, op, r))
695 .boxed()
696 }};
697 }
698
699 let multiplicative: GruelParser<I, Expr> = left_binary!(
701 unary,
702 choice((
703 just(TokenKind::Star).to(BinaryOp::Mul).boxed(),
704 just(TokenKind::Slash).to(BinaryOp::Div).boxed(),
705 just(TokenKind::Percent).to(BinaryOp::Mod).boxed(),
706 ))
707 .boxed()
708 );
709
710 let additive: GruelParser<I, Expr> = left_binary!(
712 multiplicative,
713 choice((
714 just(TokenKind::Plus).to(BinaryOp::Add).boxed(),
715 just(TokenKind::Minus).to(BinaryOp::Sub).boxed(),
716 ))
717 .boxed()
718 );
719
720 let shift: GruelParser<I, Expr> = left_binary!(
722 additive,
723 choice((
724 just(TokenKind::LtLt).to(BinaryOp::Shl).boxed(),
725 just(TokenKind::GtGt).to(BinaryOp::Shr).boxed(),
726 ))
727 .boxed()
728 );
729
730 let comparison: GruelParser<I, Expr> = left_binary!(
732 shift,
733 choice((
734 just(TokenKind::EqEq).to(BinaryOp::Eq).boxed(),
735 just(TokenKind::BangEq).to(BinaryOp::Ne).boxed(),
736 just(TokenKind::Lt).to(BinaryOp::Lt).boxed(),
737 just(TokenKind::Gt).to(BinaryOp::Gt).boxed(),
738 just(TokenKind::LtEq).to(BinaryOp::Le).boxed(),
739 just(TokenKind::GtEq).to(BinaryOp::Ge).boxed(),
740 ))
741 .boxed()
742 );
743
744 let bitwise_and: GruelParser<I, Expr> = left_binary!(
746 comparison,
747 just(TokenKind::Amp).to(BinaryOp::BitAnd).boxed()
748 );
749
750 let bitwise_xor: GruelParser<I, Expr> = left_binary!(
752 bitwise_and,
753 just(TokenKind::Caret).to(BinaryOp::BitXor).boxed()
754 );
755
756 let bitwise_or: GruelParser<I, Expr> = left_binary!(
758 bitwise_xor,
759 just(TokenKind::Pipe).to(BinaryOp::BitOr).boxed()
760 );
761
762 let logical_and: GruelParser<I, Expr> = left_binary!(
764 bitwise_or,
765 just(TokenKind::AmpAmp).to(BinaryOp::And).boxed()
766 );
767
768 let logical_or: GruelParser<I, Expr> = left_binary!(
770 logical_and,
771 just(TokenKind::PipePipe).to(BinaryOp::Or).boxed()
772 );
773
774 logical_or
775 },
776 )
777 .boxed()
778}
779
780fn pattern_parser<'src, I>() -> GruelParser<'src, I, Pattern>
782where
783 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
784{
785 let wildcard =
787 just(TokenKind::Underscore).map_with(|_, e| Pattern::Wildcard(span_from_extra(e)));
788
789 let int_pat = select! {
791 TokenKind::Int(n) = e => Pattern::Int(IntLit {
792 value: n,
793 span: span_from_extra(e),
794 }),
795 };
796
797 let neg_int_pat = just(TokenKind::Minus)
799 .then(select! { TokenKind::Int(n) => n })
800 .map_with(|(_, n), e| {
801 Pattern::NegInt(NegIntLit {
802 value: n,
803 span: span_from_extra(e),
804 })
805 });
806
807 let bool_true = select! {
809 TokenKind::True = e => Pattern::Bool(BoolLit {
810 value: true,
811 span: span_from_extra(e),
812 }),
813 };
814
815 let bool_false = select! {
816 TokenKind::False = e => Pattern::Bool(BoolLit {
817 value: false,
818 span: span_from_extra(e),
819 }),
820 };
821
822 let pattern_binding = choice((
824 just(TokenKind::Underscore).map_with(|_, e| PatternBinding::Wildcard(span_from_extra(e))),
825 just(TokenKind::Mut)
826 .ignore_then(ident_parser())
827 .map(|name| PatternBinding::Ident { is_mut: true, name }),
828 ident_parser().map(|name| PatternBinding::Ident {
829 is_mut: false,
830 name,
831 }),
832 ));
833
834 let bindings_suffix = pattern_binding
836 .clone()
837 .separated_by(just(TokenKind::Comma))
838 .allow_trailing()
839 .collect::<Vec<_>>()
840 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen));
841
842 let pattern_field_binding = {
845 let explicit = ident_parser()
846 .then_ignore(just(TokenKind::Colon))
847 .then(pattern_binding.clone())
848 .map(|(field_name, binding)| PatternFieldBinding {
849 field_name,
850 binding,
851 });
852 let shorthand = ident_parser().map(|name| PatternFieldBinding {
853 field_name: name,
854 binding: PatternBinding::Ident {
855 is_mut: false,
856 name,
857 },
858 });
859 choice((explicit, shorthand))
860 };
861
862 let struct_bindings_suffix = pattern_field_binding
864 .separated_by(just(TokenKind::Comma))
865 .allow_trailing()
866 .collect::<Vec<_>>()
867 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace));
868
869 #[derive(Debug, Clone)]
871 enum PatternSuffix {
872 Tuple(Vec<PatternBinding>),
873 Struct(Vec<PatternFieldBinding>),
874 }
875
876 let pattern_suffix = choice((
877 bindings_suffix.clone().map(PatternSuffix::Tuple),
878 struct_bindings_suffix.clone().map(PatternSuffix::Struct),
879 ));
880
881 let self_path_pat = just(TokenKind::SelfType)
884 .ignore_then(just(TokenKind::ColonColon))
885 .ignore_then(ident_parser())
886 .then(pattern_suffix.clone().or_not())
887 .map_with(|(variant, suffix_opt), e| {
888 let span = span_from_extra(e);
889 let type_name = Ident {
890 name: e.state().syms.self_type,
891 span,
892 };
893 match suffix_opt {
894 Some(PatternSuffix::Tuple(bindings)) => Pattern::DataVariant {
895 base: None,
896 type_name,
897 variant,
898 bindings,
899 span,
900 },
901 Some(PatternSuffix::Struct(fields)) => Pattern::StructVariant {
902 base: None,
903 type_name,
904 variant,
905 fields,
906 span,
907 },
908 None => Pattern::Path(PathPattern {
909 base: None,
910 type_name,
911 variant,
912 span,
913 }),
914 }
915 });
916
917 let simple_path_pat = ident_parser()
919 .then_ignore(just(TokenKind::ColonColon))
920 .then(ident_parser())
921 .then(pattern_suffix.clone().or_not())
922 .map_with(|((type_name, variant), suffix_opt), e| match suffix_opt {
923 Some(PatternSuffix::Tuple(bindings)) => Pattern::DataVariant {
924 base: None,
925 type_name,
926 variant,
927 bindings,
928 span: span_from_extra(e),
929 },
930 Some(PatternSuffix::Struct(fields)) => Pattern::StructVariant {
931 base: None,
932 type_name,
933 variant,
934 fields,
935 span: span_from_extra(e),
936 },
937 None => Pattern::Path(PathPattern {
938 base: None,
939 type_name,
940 variant,
941 span: span_from_extra(e),
942 }),
943 });
944
945 let qualified_path_pat = ident_parser()
949 .then(
950 just(TokenKind::Dot)
951 .ignore_then(ident_parser())
952 .repeated()
953 .at_least(1)
954 .collect::<Vec<_>>(),
955 )
956 .then_ignore(just(TokenKind::ColonColon))
957 .then(ident_parser())
958 .then(pattern_suffix.or_not())
959 .map_with(|(((first, mut rest), variant), suffix_opt), e| {
960 let type_name = rest.pop().expect("at_least(1) guarantees non-empty");
964
965 let base_expr = if rest.is_empty() {
967 Expr::Ident(first)
969 } else {
970 let mut base = Expr::Ident(first);
972 for field in rest {
973 let span = base.span().extend_to(field.span.end);
974 base = Expr::Field(FieldExpr {
975 base: Box::new(base),
976 field,
977 span,
978 });
979 }
980 base
981 };
982
983 match suffix_opt {
984 Some(PatternSuffix::Tuple(bindings)) => Pattern::DataVariant {
985 base: Some(Box::new(base_expr)),
986 type_name,
987 variant,
988 bindings,
989 span: span_from_extra(e),
990 },
991 Some(PatternSuffix::Struct(fields)) => Pattern::StructVariant {
992 base: Some(Box::new(base_expr)),
993 type_name,
994 variant,
995 fields,
996 span: span_from_extra(e),
997 },
998 None => Pattern::Path(PathPattern {
999 base: Some(Box::new(base_expr)),
1000 type_name,
1001 variant,
1002 span: span_from_extra(e),
1003 }),
1004 }
1005 });
1006
1007 choice((
1008 wildcard.boxed(),
1009 neg_int_pat.boxed(),
1010 int_pat.boxed(),
1011 bool_true.boxed(),
1012 bool_false.boxed(),
1013 qualified_path_pat.boxed(),
1015 self_path_pat.boxed(),
1016 simple_path_pat.boxed(),
1017 ))
1018 .boxed()
1019}
1020
1021fn match_arm_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, MatchArm>
1023where
1024 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
1025{
1026 pattern_parser()
1027 .then_ignore(just(TokenKind::FatArrow))
1028 .then(expr)
1029 .map_with(|(pattern, body), e| MatchArm {
1030 pattern,
1031 body: Box::new(body),
1032 span: span_from_extra(e),
1033 })
1034 .boxed()
1035}
1036
1037fn literal_parser<'src, I>() -> GruelParser<'src, I, Expr>
1039where
1040 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
1041{
1042 let int_lit = select! {
1044 TokenKind::Int(n) = e => Expr::Int(IntLit {
1045 value: n,
1046 span: span_from_extra(e),
1047 }),
1048 };
1049
1050 let float_lit = select! {
1052 TokenKind::Float(bits) = e => Expr::Float(FloatLit {
1053 bits,
1054 span: span_from_extra(e),
1055 }),
1056 };
1057
1058 let string_lit = select! {
1060 TokenKind::String(s) = e => Expr::String(StringLit {
1061 value: s,
1062 span: span_from_extra(e),
1063 }),
1064 };
1065
1066 let bool_true = select! {
1068 TokenKind::True = e => Expr::Bool(BoolLit {
1069 value: true,
1070 span: span_from_extra(e),
1071 }),
1072 };
1073
1074 let bool_false = select! {
1075 TokenKind::False = e => Expr::Bool(BoolLit {
1076 value: false,
1077 span: span_from_extra(e),
1078 }),
1079 };
1080
1081 let unit_lit = just(TokenKind::LParen)
1083 .then(just(TokenKind::RParen))
1084 .map_with(|_, e| {
1085 Expr::Unit(UnitLit {
1086 span: span_from_extra(e),
1087 })
1088 });
1089
1090 choice((
1091 int_lit.boxed(),
1092 float_lit.boxed(),
1093 string_lit.boxed(),
1094 bool_true.boxed(),
1095 bool_false.boxed(),
1096 unit_lit.boxed(),
1097 ))
1098 .boxed()
1099}
1100
1101fn control_flow_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, Expr>
1103where
1104 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
1105{
1106 let break_expr = select! {
1108 TokenKind::Break = e => Expr::Break(BreakExpr { span: span_from_extra(e) }),
1109 };
1110
1111 let continue_expr = select! {
1113 TokenKind::Continue = e => Expr::Continue(ContinueExpr { span: span_from_extra(e) }),
1114 };
1115
1116 let return_expr = just(TokenKind::Return)
1118 .ignore_then(expr.clone().or_not())
1119 .map_with(|value, e| {
1120 Expr::Return(ReturnExpr {
1121 value: value.map(Box::new),
1122 span: span_from_extra(e),
1123 })
1124 });
1125
1126 let if_expr: GruelParser<'src, I, Expr> = recursive(
1128 |if_expr_rec: Recursive<Direct<'src, 'src, I, Expr, ParserExtras<'src>>>| {
1129 just(TokenKind::If)
1130 .ignore_then(expr.clone())
1131 .then(maybe_unit_block_parser(expr.clone()))
1132 .then(
1133 just(TokenKind::Else)
1134 .ignore_then(choice((
1135 if_expr_rec
1137 .map_with(|nested_if, e| {
1138 let span = span_from_extra(e);
1139 BlockExpr {
1140 statements: Vec::new(),
1141 expr: Box::new(nested_if),
1142 span,
1143 }
1144 })
1145 .boxed(),
1146 maybe_unit_block_parser(expr.clone()),
1148 )))
1149 .or_not(),
1150 )
1151 .map_with(|((cond, then_block), else_block), e| {
1152 Expr::If(IfExpr {
1153 cond: Box::new(cond),
1154 then_block,
1155 else_block,
1156 span: span_from_extra(e),
1157 })
1158 })
1159 .boxed()
1160 },
1161 )
1162 .boxed();
1163
1164 let while_expr: GruelParser<'src, I, Expr> = just(TokenKind::While)
1166 .ignore_then(expr.clone())
1167 .then(maybe_unit_block_parser(expr.clone()))
1168 .map_with(|(cond, body), e| {
1169 Expr::While(WhileExpr {
1170 cond: Box::new(cond),
1171 body,
1172 span: span_from_extra(e),
1173 })
1174 })
1175 .boxed();
1176
1177 let for_expr: GruelParser<'src, I, Expr> = just(TokenKind::For)
1179 .ignore_then(just(TokenKind::Mut).or_not())
1180 .then(ident_parser())
1181 .then_ignore(just(TokenKind::In))
1182 .then(expr.clone())
1183 .then(maybe_unit_block_parser(expr.clone()))
1184 .map_with(|(((is_mut, binding), iterable), body), e| {
1185 Expr::For(ForExpr {
1186 binding,
1187 is_mut: is_mut.is_some(),
1188 iterable: Box::new(iterable),
1189 body,
1190 span: span_from_extra(e),
1191 })
1192 })
1193 .boxed();
1194
1195 let loop_expr: GruelParser<'src, I, Expr> = just(TokenKind::Loop)
1197 .ignore_then(maybe_unit_block_parser(expr.clone()))
1198 .map_with(|body, e| {
1199 Expr::Loop(LoopExpr {
1200 body,
1201 span: span_from_extra(e),
1202 })
1203 })
1204 .boxed();
1205
1206 let match_expr: GruelParser<'src, I, Expr> = just(TokenKind::Match)
1208 .ignore_then(expr.clone())
1209 .then(
1210 match_arm_parser(expr.clone())
1211 .separated_by(just(TokenKind::Comma))
1212 .allow_trailing()
1213 .collect::<Vec<_>>()
1214 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)),
1215 )
1216 .map_with(|(scrutinee, arms), e| {
1217 Expr::Match(MatchExpr {
1218 scrutinee: Box::new(scrutinee),
1219 arms,
1220 span: span_from_extra(e),
1221 })
1222 })
1223 .boxed();
1224
1225 let comptime_unroll_for_expr: GruelParser<'src, I, Expr> = just(TokenKind::ComptimeUnroll)
1227 .ignore_then(just(TokenKind::For))
1228 .ignore_then(ident_parser())
1229 .then_ignore(just(TokenKind::In))
1230 .then(expr.clone())
1231 .then(maybe_unit_block_parser(expr.clone()))
1232 .map_with(|((binding, iterable), body), e| {
1233 Expr::ComptimeUnrollFor(ComptimeUnrollForExpr {
1234 binding,
1235 iterable: Box::new(iterable),
1236 body,
1237 span: span_from_extra(e),
1238 })
1239 })
1240 .boxed();
1241
1242 choice((
1243 break_expr.boxed(),
1244 continue_expr.boxed(),
1245 return_expr.boxed(),
1246 if_expr,
1247 while_expr,
1248 for_expr,
1249 comptime_unroll_for_expr,
1250 loop_expr,
1251 match_expr,
1252 ))
1253 .boxed()
1254}
1255
1256#[derive(Clone)]
1258enum IdentSuffix {
1259 Call(Vec<CallArg>),
1260 StructLit(Vec<FieldInit>),
1261 Path(Ident), PathCall(Ident, Vec<CallArg>), PathStructLit(Ident, Vec<FieldInit>), None,
1265}
1266
1267fn call_and_access_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, Expr>
1269where
1270 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
1271{
1272 ident_parser()
1273 .then(
1274 choice((
1275 call_args_parser(expr.clone())
1277 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen))
1278 .map(IdentSuffix::Call)
1279 .boxed(),
1280 just(TokenKind::LBrace)
1284 .then(
1285 choice((
1286 just(TokenKind::RBrace).ignored(),
1287 select! { TokenKind::Ident(_) => () }
1288 .then_ignore(just(TokenKind::Colon))
1289 .ignored(),
1290 select! { TokenKind::Ident(_) => () }
1291 .then_ignore(just(TokenKind::Comma))
1292 .ignored(),
1293 ))
1294 .rewind(),
1295 )
1296 .rewind()
1297 .ignore_then(
1298 field_inits_parser(expr.clone())
1299 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)),
1300 )
1301 .map(IdentSuffix::StructLit)
1302 .boxed(),
1303 just(TokenKind::ColonColon)
1305 .ignore_then(ident_parser())
1306 .then(
1307 call_args_parser(expr.clone())
1308 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen)),
1309 )
1310 .map(|(func, args)| IdentSuffix::PathCall(func, args))
1311 .boxed(),
1312 just(TokenKind::ColonColon)
1314 .ignore_then(ident_parser())
1315 .then(
1316 field_inits_parser(expr.clone())
1317 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)),
1318 )
1319 .map(|(variant, fields)| IdentSuffix::PathStructLit(variant, fields))
1320 .boxed(),
1321 just(TokenKind::ColonColon)
1323 .ignore_then(ident_parser())
1324 .map(IdentSuffix::Path)
1325 .boxed(),
1326 ))
1327 .or_not()
1328 .map(|opt| opt.unwrap_or(IdentSuffix::None)),
1329 )
1330 .map_with(|(name, suffix), e| match suffix {
1331 IdentSuffix::Call(args) => Expr::Call(CallExpr {
1332 name,
1333 args,
1334 span: span_from_extra(e),
1335 }),
1336 IdentSuffix::StructLit(fields) => Expr::StructLit(StructLitExpr {
1337 base: None, name,
1339 fields,
1340 span: span_from_extra(e),
1341 }),
1342 IdentSuffix::PathCall(function, args) => Expr::AssocFnCall(AssocFnCallExpr {
1343 base: None, type_name: name,
1345 function,
1346 args,
1347 span: span_from_extra(e),
1348 }),
1349 IdentSuffix::PathStructLit(variant, fields) => Expr::EnumStructLit(EnumStructLitExpr {
1350 base: None,
1351 type_name: name,
1352 variant,
1353 fields,
1354 span: span_from_extra(e),
1355 }),
1356 IdentSuffix::Path(variant) => Expr::Path(PathExpr {
1357 base: None, type_name: name,
1359 variant,
1360 span: span_from_extra(e),
1361 }),
1362 IdentSuffix::None => Expr::Ident(name),
1363 })
1364 .boxed()
1365}
1366
1367#[derive(Clone)]
1370enum Suffix {
1371 Field(Ident),
1373 MethodCall(Ident, Vec<CallArg>, u32),
1375 Index(Expr, u32),
1377 QualifiedStructLit(Ident, Vec<FieldInit>, u32),
1380 QualifiedPath(Ident, Ident, u32),
1382 QualifiedAssocFnCall(Ident, Ident, Vec<CallArg>, u32),
1384 QualifiedEnumStructLit(Ident, Ident, Vec<FieldInit>, u32),
1386}
1387
1388fn with_suffix_parser<'src, I>(
1390 primary: impl Parser<'src, I, Expr, ParserExtras<'src>> + Clone + 'src,
1391 expr: GruelParser<'src, I, Expr>,
1392) -> GruelParser<'src, I, Expr>
1393where
1394 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
1395{
1396 let method_call_suffix = just(TokenKind::Dot)
1398 .ignore_then(ident_parser())
1399 .then(
1400 call_args_parser(expr.clone())
1401 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen)),
1402 )
1403 .map_with(|(method, args), e| {
1404 Suffix::MethodCall(method, args, offset_to_u32(e.span().end))
1405 });
1406
1407 let struct_lit_lookahead = just(TokenKind::LBrace)
1419 .then(
1420 choice((
1421 just(TokenKind::RBrace).ignored(),
1423 select! { TokenKind::Ident(_) => () }
1425 .then_ignore(just(TokenKind::Colon))
1426 .ignored(),
1427 ))
1428 .rewind(),
1430 )
1431 .rewind();
1432
1433 let struct_lit_lookahead: GruelParser<'src, I, _> = struct_lit_lookahead.boxed();
1436
1437 let struct_lit_name: GruelParser<'src, I, Ident> = just(TokenKind::Dot)
1441 .ignore_then(ident_parser())
1442 .then_ignore(struct_lit_lookahead)
1443 .boxed();
1444 let qualified_struct_lit_suffix = struct_lit_name
1445 .then(
1446 field_inits_parser(expr.clone())
1447 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)),
1448 )
1449 .map_with(|(name, fields), e| {
1450 Suffix::QualifiedStructLit(name, fields, offset_to_u32(e.span().end))
1451 })
1452 .boxed();
1453
1454 let type_and_member: GruelParser<'src, I, (Ident, Ident)> = just(TokenKind::Dot)
1457 .ignore_then(ident_parser())
1458 .then_ignore(just(TokenKind::ColonColon))
1459 .then(ident_parser())
1460 .boxed();
1461
1462 let qualified_assoc_fn_suffix = type_and_member
1464 .clone()
1465 .then(
1466 call_args_parser(expr.clone())
1467 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen)),
1468 )
1469 .map_with(|((type_name, function), args), e| {
1470 Suffix::QualifiedAssocFnCall(type_name, function, args, offset_to_u32(e.span().end))
1471 });
1472
1473 let qualified_enum_struct_lit_suffix = type_and_member
1475 .clone()
1476 .then(
1477 field_inits_parser(expr.clone())
1478 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)),
1479 )
1480 .map_with(|((type_name, variant), fields), e| {
1481 Suffix::QualifiedEnumStructLit(type_name, variant, fields, offset_to_u32(e.span().end))
1482 });
1483
1484 let qualified_path_suffix = type_and_member
1487 .map(|(type_name, variant): (Ident, Ident)| {
1488 let end = variant.span.end;
1489 (type_name, variant, end)
1490 })
1491 .then_ignore(none_of([TokenKind::LParen, TokenKind::LBrace]).rewind())
1492 .map(|(type_name, variant, end)| Suffix::QualifiedPath(type_name, variant, end));
1493
1494 let field_suffix = just(TokenKind::Dot)
1498 .ignore_then(ident_parser())
1499 .then_ignore(none_of([TokenKind::LParen, TokenKind::ColonColon]).rewind())
1500 .map(Suffix::Field);
1501
1502 let index_suffix = expr
1503 .delimited_by(just(TokenKind::LBracket), just(TokenKind::RBracket))
1504 .map_with(|index, e| Suffix::Index(index, offset_to_u32(e.span().end)));
1505
1506 primary
1516 .foldl(
1517 choice((
1518 method_call_suffix.boxed(),
1519 qualified_assoc_fn_suffix.boxed(),
1520 qualified_enum_struct_lit_suffix.boxed(),
1521 qualified_struct_lit_suffix,
1522 qualified_path_suffix.boxed(),
1523 field_suffix.boxed(),
1524 index_suffix.boxed(),
1525 ))
1526 .boxed()
1527 .repeated(),
1528 |base, suffix| match suffix {
1529 Suffix::Field(field) => {
1530 let span = base.span().extend_to(field.span.end);
1532 Expr::Field(FieldExpr {
1533 base: Box::new(base),
1534 field,
1535 span,
1536 })
1537 }
1538 Suffix::MethodCall(method, args, end) => {
1539 let span = base.span().extend_to(end);
1541 Expr::MethodCall(MethodCallExpr {
1542 receiver: Box::new(base),
1543 method,
1544 args,
1545 span,
1546 })
1547 }
1548 Suffix::Index(index, end) => {
1549 let span = base.span().extend_to(end);
1551 Expr::Index(IndexExpr {
1552 base: Box::new(base),
1553 index: Box::new(index),
1554 span,
1555 })
1556 }
1557 Suffix::QualifiedStructLit(name, fields, end) => {
1558 let span = base.span().extend_to(end);
1560 Expr::StructLit(StructLitExpr {
1561 base: Some(Box::new(base)),
1562 name,
1563 fields,
1564 span,
1565 })
1566 }
1567 Suffix::QualifiedPath(type_name, variant, end) => {
1568 let span = base.span().extend_to(end);
1570 Expr::Path(PathExpr {
1571 base: Some(Box::new(base)),
1572 type_name,
1573 variant,
1574 span,
1575 })
1576 }
1577 Suffix::QualifiedEnumStructLit(type_name, variant, fields, end) => {
1578 let span = base.span().extend_to(end);
1580 Expr::EnumStructLit(EnumStructLitExpr {
1581 base: Some(Box::new(base)),
1582 type_name,
1583 variant,
1584 fields,
1585 span,
1586 })
1587 }
1588 Suffix::QualifiedAssocFnCall(type_name, function, args, end) => {
1589 let span = base.span().extend_to(end);
1591 Expr::AssocFnCall(AssocFnCallExpr {
1592 base: Some(Box::new(base)),
1593 type_name,
1594 function,
1595 args,
1596 span,
1597 })
1598 }
1599 },
1600 )
1601 .boxed()
1602}
1603
1604fn atom_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, Expr>
1606where
1607 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
1608{
1609 let self_expr = select! {
1611 TokenKind::SelfValue = e => Expr::SelfExpr(SelfExpr { span: span_from_extra(e) }),
1612 };
1613
1614 let paren_expr = expr
1616 .clone()
1617 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen))
1618 .map_with(|inner, e| {
1619 Expr::Paren(ParenExpr {
1620 inner: Box::new(inner),
1621 span: span_from_extra(e),
1622 })
1623 });
1624
1625 let block_expr = block_parser(expr.clone());
1627
1628 let comptime_expr = just(TokenKind::Comptime)
1630 .ignore_then(block_parser(expr.clone()))
1631 .map_with(|inner_expr, e| {
1632 Expr::Comptime(ComptimeBlockExpr {
1633 expr: Box::new(inner_expr),
1634 span: span_from_extra(e),
1635 })
1636 });
1637
1638 let checked_expr = just(TokenKind::Checked)
1641 .ignore_then(block_parser(expr.clone()))
1642 .map_with(|inner_expr, e| {
1643 Expr::Checked(CheckedBlockExpr {
1644 expr: Box::new(inner_expr),
1645 span: span_from_extra(e),
1646 })
1647 });
1648
1649 let unambiguous_type = {
1653 let unit_type = just(TokenKind::LParen)
1655 .then(just(TokenKind::RParen))
1656 .map_with(|_, e| IntrinsicArg::Type(TypeExpr::Unit(span_from_extra(e))));
1657
1658 let never_type = just(TokenKind::Bang)
1660 .map_with(|_, e| IntrinsicArg::Type(TypeExpr::Never(span_from_extra(e))));
1661
1662 let array_type = just(TokenKind::LBracket)
1664 .ignore_then(type_parser())
1665 .then_ignore(just(TokenKind::Semi))
1666 .then(select! {
1667 TokenKind::Int(n) => n,
1668 })
1669 .then_ignore(just(TokenKind::RBracket))
1670 .map_with(|(element, length), e| {
1671 IntrinsicArg::Type(TypeExpr::Array {
1672 element: Box::new(element),
1673 length,
1674 span: span_from_extra(e),
1675 })
1676 });
1677
1678 let primitive_type = primitive_type_parser().map(IntrinsicArg::Type);
1680
1681 choice((
1682 unit_type.boxed(),
1683 never_type.boxed(),
1684 array_type.boxed(),
1685 primitive_type.boxed(),
1686 ))
1687 .boxed()
1688 };
1689
1690 let intrinsic_arg: GruelParser<I, IntrinsicArg> = choice((
1693 unambiguous_type,
1694 expr.clone().map(IntrinsicArg::Expr).boxed(),
1695 ))
1696 .boxed();
1697
1698 let intrinsic_args: GruelParser<I, Vec<IntrinsicArg>> = intrinsic_arg
1700 .separated_by(just(TokenKind::Comma))
1701 .allow_trailing()
1702 .collect::<Vec<_>>()
1703 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen))
1704 .boxed();
1705
1706 let intrinsic_call: GruelParser<I, Expr> = just(TokenKind::At)
1708 .ignore_then(ident_parser())
1709 .then(intrinsic_args.clone())
1710 .map_with(|(name, args), e| {
1711 Expr::IntrinsicCall(IntrinsicCallExpr {
1712 name,
1713 args,
1714 span: span_from_extra(e),
1715 })
1716 })
1717 .boxed();
1718
1719 let import_call: GruelParser<I, Expr> = select! {
1721 TokenKind::AtImport(import_spur) = e => (import_spur, span_from_extra(e)),
1722 }
1723 .then(intrinsic_args)
1724 .map_with(|((import_spur, import_span), args), e| {
1725 Expr::IntrinsicCall(IntrinsicCallExpr {
1726 name: Ident {
1727 name: import_spur,
1728 span: import_span,
1729 },
1730 args,
1731 span: span_from_extra(e),
1732 })
1733 })
1734 .boxed();
1735
1736 let any_intrinsic_call: GruelParser<I, Expr> = choice((import_call, intrinsic_call)).boxed();
1738
1739 let array_lit = args_parser(expr.clone())
1741 .delimited_by(just(TokenKind::LBracket), just(TokenKind::RBracket))
1742 .map_with(|elements, e| {
1743 Expr::ArrayLit(ArrayLitExpr {
1744 elements,
1745 span: span_from_extra(e),
1746 })
1747 });
1748
1749 let type_lit_expr = primitive_type_parser().map_with(|type_expr, e| {
1752 Expr::TypeLit(TypeLitExpr {
1753 type_expr,
1754 span: span_from_extra(e),
1755 })
1756 });
1757
1758 let anon_struct_field: GruelParser<'src, I, AnonStructField> = ident_parser()
1764 .then_ignore(just(TokenKind::Colon))
1765 .then(type_parser())
1766 .map_with(|(name, field_ty), e| AnonStructField {
1767 name,
1768 ty: field_ty,
1769 span: span_from_extra(e),
1770 })
1771 .boxed();
1772
1773 let anon_struct_fields: GruelParser<'src, I, Vec<AnonStructField>> = anon_struct_field
1774 .separated_by(just(TokenKind::Comma))
1775 .allow_trailing()
1776 .collect::<Vec<_>>()
1777 .boxed();
1778
1779 let anon_struct_method = anon_struct_method_parser(expr.clone());
1782
1783 let anon_struct_header: GruelParser<'src, I, (Vec<AnonStructField>, Vec<Method>)> =
1784 just(TokenKind::Struct)
1785 .ignore_then(just(TokenKind::LBrace))
1786 .ignore_then(anon_struct_fields)
1787 .then(
1788 anon_struct_method.repeated().collect::<Vec<_>>(),
1790 )
1791 .boxed();
1792
1793 let anon_struct_type_expr = anon_struct_header
1794 .then_ignore(just(TokenKind::RBrace))
1795 .map_with(|(fields, methods), e| {
1796 let span = span_from_extra(e);
1797 Expr::TypeLit(TypeLitExpr {
1798 type_expr: TypeExpr::AnonymousStruct {
1799 fields,
1800 methods,
1801 span,
1802 },
1803 span,
1804 })
1805 });
1806
1807 let anon_enum_method = anon_struct_method_parser(expr.clone());
1811
1812 let anon_enum_type_expr = just(TokenKind::Enum)
1813 .ignore_then(just(TokenKind::LBrace))
1814 .ignore_then(enum_variants_parser())
1815 .then(
1816 anon_enum_method.repeated().collect::<Vec<_>>(),
1818 )
1819 .then_ignore(just(TokenKind::RBrace))
1820 .map_with(|(variants, methods), e| {
1821 let span = span_from_extra(e);
1822 Expr::TypeLit(TypeLitExpr {
1823 type_expr: TypeExpr::AnonymousEnum {
1824 variants,
1825 methods,
1826 span,
1827 },
1828 span,
1829 })
1830 });
1831
1832 let self_type_expr = just(TokenKind::SelfType)
1835 .ignore_then(
1836 field_inits_parser(expr.clone())
1837 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)),
1838 )
1839 .map_with(|fields, e| {
1840 let span = span_from_extra(e);
1841 Expr::StructLit(StructLitExpr {
1842 base: None,
1843 name: Ident {
1844 name: e.state().syms.self_type,
1845 span,
1846 },
1847 fields,
1848 span,
1849 })
1850 });
1851
1852 let self_assoc_fn_call = just(TokenKind::SelfType)
1854 .ignore_then(just(TokenKind::ColonColon))
1855 .ignore_then(ident_parser())
1856 .then(
1857 call_args_parser(expr.clone())
1858 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen)),
1859 )
1860 .map_with(|(function, args), e| {
1861 let span = span_from_extra(e);
1862 Expr::AssocFnCall(AssocFnCallExpr {
1863 base: None,
1864 type_name: Ident {
1865 name: e.state().syms.self_type,
1866 span,
1867 },
1868 function,
1869 args,
1870 span,
1871 })
1872 });
1873
1874 let self_enum_struct_lit = just(TokenKind::SelfType)
1876 .ignore_then(just(TokenKind::ColonColon))
1877 .ignore_then(ident_parser())
1878 .then(
1879 field_inits_parser(expr.clone())
1880 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)),
1881 )
1882 .map_with(|(variant, fields), e| {
1883 let span = span_from_extra(e);
1884 Expr::EnumStructLit(EnumStructLitExpr {
1885 base: None,
1886 type_name: Ident {
1887 name: e.state().syms.self_type,
1888 span,
1889 },
1890 variant,
1891 fields,
1892 span,
1893 })
1894 });
1895
1896 let self_enum_variant = just(TokenKind::SelfType)
1898 .ignore_then(just(TokenKind::ColonColon))
1899 .ignore_then(ident_parser())
1900 .then_ignore(none_of([TokenKind::LParen, TokenKind::LBrace]).rewind())
1901 .map_with(|variant, e| {
1902 let span = span_from_extra(e);
1903 Expr::Path(PathExpr {
1904 base: None,
1905 type_name: Ident {
1906 name: e.state().syms.self_type,
1907 span,
1908 },
1909 variant,
1910 span,
1911 })
1912 });
1913
1914 let primary_a: GruelParser<'src, I, Expr> = choice((
1926 literal_parser(),
1927 control_flow_parser(expr.clone()),
1928 self_expr.boxed(),
1929 self_assoc_fn_call.boxed(),
1930 self_enum_struct_lit.boxed(),
1931 self_enum_variant.boxed(),
1932 self_type_expr.boxed(),
1933 any_intrinsic_call.boxed(),
1934 ))
1935 .boxed();
1936 let primary_b: GruelParser<'src, I, Expr> = choice((
1937 array_lit.boxed(),
1938 anon_struct_type_expr.boxed(),
1939 anon_enum_type_expr.boxed(),
1940 type_lit_expr.boxed(),
1941 call_and_access_parser(expr.clone()),
1942 paren_expr.boxed(),
1943 ))
1944 .boxed();
1945 let primary_c: GruelParser<'src, I, Expr> = choice((
1946 comptime_expr.boxed(),
1947 checked_expr.boxed(),
1948 block_expr.boxed(),
1949 ))
1950 .boxed();
1951 let primary: GruelParser<'src, I, Expr> = choice((primary_a, primary_b, primary_c)).boxed();
1952
1953 with_suffix_parser(primary, expr)
1955}
1956
1957#[derive(Debug, Clone)]
1959enum BlockItem {
1960 Statement(Statement),
1961 Expr(Expr),
1962}
1963
1964#[derive(Debug, Clone, Copy)]
1966enum ExprFollower {
1967 Semi,
1969 RBrace,
1971 Other,
1973 End,
1975}
1976
1977fn let_pattern_parser<'src, I>() -> GruelParser<'src, I, LetPattern>
1979where
1980 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
1981{
1982 let wildcard =
1983 just(TokenKind::Underscore).map_with(|_, e| LetPattern::Wildcard(span_from_extra(e)));
1984
1985 let destructure_field = just(TokenKind::Mut)
1987 .or_not()
1988 .then(ident_parser())
1989 .then(
1990 just(TokenKind::Colon)
1991 .ignore_then(choice((
1992 just(TokenKind::Underscore)
1993 .map_with(|_, e| DestructureBinding::Wildcard(span_from_extra(e))),
1994 ident_parser().map(DestructureBinding::Renamed),
1995 )))
1996 .or_not(),
1997 )
1998 .map(|((is_mut, field_name), binding)| DestructureField {
1999 field_name,
2000 binding: binding.unwrap_or(DestructureBinding::Shorthand),
2001 is_mut: is_mut.is_some(),
2002 });
2003
2004 let struct_destructure = ident_parser()
2006 .then(
2007 destructure_field
2008 .separated_by(just(TokenKind::Comma))
2009 .allow_trailing()
2010 .collect::<Vec<_>>()
2011 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)),
2012 )
2013 .map_with(|(type_name, fields), e| LetPattern::Struct {
2014 type_name,
2015 fields,
2016 span: span_from_extra(e),
2017 });
2018
2019 let ident = ident_parser().map(LetPattern::Ident);
2020
2021 struct_destructure.or(ident).or(wildcard).boxed()
2023}
2024
2025fn let_statement_parser<'src, I>(
2027 expr: GruelParser<'src, I, Expr>,
2028) -> GruelParser<'src, I, Statement>
2029where
2030 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2031{
2032 let let_head: GruelParser<I, (Directives, bool, LetPattern)> = directives_parser()
2034 .then(just(TokenKind::Let).ignore_then(just(TokenKind::Mut).or_not().map(|m| m.is_some())))
2035 .then(let_pattern_parser())
2036 .map(|((d, m), p)| (d, m, p))
2037 .boxed();
2038
2039 let let_tail: GruelParser<I, (Option<TypeExpr>, Expr)> = just(TokenKind::Colon)
2040 .ignore_then(type_parser())
2041 .or_not()
2042 .then(just(TokenKind::Eq).ignore_then(expr))
2043 .then_ignore(just(TokenKind::Semi))
2044 .boxed();
2045
2046 let_head
2047 .then(let_tail)
2048 .map_with(|((directives, is_mut, pattern), (ty, init)), e| {
2049 Statement::Let(LetStatement {
2050 directives,
2051 is_mut,
2052 pattern,
2053 ty,
2054 init: Box::new(init),
2055 span: span_from_extra(e),
2056 })
2057 })
2058 .boxed()
2059}
2060
2061#[derive(Clone)]
2063enum AssignSuffix {
2064 Field(Ident),
2065 Index(Expr),
2066}
2067
2068fn assign_target_parser<'src, I>(
2071 expr: GruelParser<'src, I, Expr>,
2072) -> GruelParser<'src, I, AssignTarget>
2073where
2074 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2075{
2076 let field_suffix = just(TokenKind::Dot)
2077 .ignore_then(ident_parser())
2078 .map(AssignSuffix::Field);
2079
2080 let index_suffix = expr
2081 .delimited_by(just(TokenKind::LBracket), just(TokenKind::RBracket))
2082 .map(AssignSuffix::Index);
2083
2084 ident_parser()
2085 .then(
2086 choice((field_suffix.boxed(), index_suffix.boxed()))
2087 .repeated()
2088 .collect::<Vec<_>>(),
2089 )
2090 .map(|(base_ident, suffixes)| {
2091 if suffixes.is_empty() {
2092 AssignTarget::Var(base_ident)
2094 } else {
2095 let mut base_expr = Expr::Ident(base_ident);
2098 let mut suffixes = suffixes.into_iter().peekable();
2099 while let Some(suffix) = suffixes.next() {
2100 let is_last = suffixes.peek().is_none();
2101 if is_last {
2102 return match suffix {
2104 AssignSuffix::Field(field) => {
2105 let span = Span::new(base_expr.span().start, field.span.end);
2106 AssignTarget::Field(FieldExpr {
2107 base: Box::new(base_expr),
2108 field,
2109 span,
2110 })
2111 }
2112 AssignSuffix::Index(index) => {
2113 let span = Span::new(base_expr.span().start, index.span().end);
2114 AssignTarget::Index(IndexExpr {
2115 base: Box::new(base_expr),
2116 index: Box::new(index),
2117 span,
2118 })
2119 }
2120 };
2121 }
2122 match suffix {
2124 AssignSuffix::Field(field) => {
2125 let span = Span::new(base_expr.span().start, field.span.end);
2126 base_expr = Expr::Field(FieldExpr {
2127 base: Box::new(base_expr),
2128 field,
2129 span,
2130 });
2131 }
2132 AssignSuffix::Index(index) => {
2133 let span = Span::new(base_expr.span().start, index.span().end);
2134 base_expr = Expr::Index(IndexExpr {
2135 base: Box::new(base_expr),
2136 index: Box::new(index),
2137 span,
2138 });
2139 }
2140 }
2141 }
2142 unreachable!()
2144 }
2145 })
2146 .boxed()
2147}
2148
2149fn assign_statement_parser<'src, I>(
2152 expr: GruelParser<'src, I, Expr>,
2153) -> GruelParser<'src, I, Statement>
2154where
2155 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2156{
2157 assign_target_parser(expr.clone())
2158 .then_ignore(just(TokenKind::Eq))
2159 .then(expr)
2160 .then_ignore(just(TokenKind::Semi))
2161 .map_with(|(target, value), e| {
2162 Statement::Assign(AssignStatement {
2163 target,
2164 value: Box::new(value),
2165 span: span_from_extra(e),
2166 })
2167 })
2168 .boxed()
2169}
2170
2171fn is_control_flow_expr(e: &Expr) -> bool {
2181 matches!(
2182 e,
2183 Expr::If(_)
2184 | Expr::Match(_)
2185 | Expr::While(_)
2186 | Expr::For(_)
2187 | Expr::ComptimeUnrollFor(_)
2188 | Expr::Loop(_)
2189 | Expr::Break(_)
2190 | Expr::Continue(_)
2191 | Expr::Return(_)
2192 | Expr::Block(_)
2193 )
2194}
2195
2196fn is_diverging_expr(e: &Expr) -> bool {
2200 matches!(
2201 e,
2202 Expr::Break(_) | Expr::Continue(_) | Expr::Return(_) | Expr::Loop(_)
2203 )
2204}
2205
2206fn block_item_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, BlockItem>
2256where
2257 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2258{
2259 let let_stmt = let_statement_parser(expr.clone()).map(BlockItem::Statement);
2262
2263 let assign_stmt = assign_statement_parser(expr.clone()).map(BlockItem::Statement);
2267
2268 let expr_item = expr
2276 .then(
2277 choice((
2278 just(TokenKind::Semi).to(ExprFollower::Semi).boxed(),
2279 just(TokenKind::RBrace)
2280 .rewind()
2281 .to(ExprFollower::RBrace)
2282 .boxed(),
2283 any().rewind().to(ExprFollower::Other).boxed(),
2284 ))
2285 .or(end().to(ExprFollower::End)),
2286 )
2287 .try_map(|(e, follower), span| match follower {
2288 ExprFollower::Semi => {
2289 Ok(BlockItem::Statement(Statement::Expr(e)))
2291 }
2292 ExprFollower::RBrace => {
2293 Ok(BlockItem::Expr(e))
2295 }
2296 ExprFollower::Other | ExprFollower::End => {
2297 if is_control_flow_expr(&e) {
2300 Ok(BlockItem::Statement(Statement::Expr(e)))
2301 } else {
2302 Err(Rich::custom(span, "expected semicolon after expression"))
2303 }
2304 }
2305 });
2306
2307 choice((let_stmt.boxed(), assign_stmt.boxed(), expr_item.boxed())).boxed()
2312}
2313
2314fn process_block_items(items: Vec<BlockItem>, block_span: Span) -> (Vec<Statement>, Expr) {
2316 let mut statements = Vec::new();
2317 let mut final_expr = None;
2318
2319 for item in items {
2320 match item {
2321 BlockItem::Statement(stmt) => {
2322 if let Some(e) = final_expr.take() {
2325 statements.push(Statement::Expr(e));
2326 }
2327 statements.push(stmt);
2328 }
2329 BlockItem::Expr(e) => {
2330 if let Some(prev) = final_expr.take() {
2331 statements.push(Statement::Expr(prev));
2334 }
2335 final_expr = Some(e);
2336 }
2337 }
2338 }
2339
2340 let expr = final_expr.unwrap_or_else(|| {
2341 if let Some(Statement::Expr(e)) = statements.last()
2345 && is_diverging_expr(e)
2346 {
2347 let Statement::Expr(e) = statements.pop().unwrap() else {
2349 unreachable!()
2350 };
2351 return e;
2352 }
2353 Expr::Unit(UnitLit {
2355 span: Span::new(block_span.end, block_span.end),
2356 })
2357 });
2358
2359 (statements, expr)
2360}
2361
2362fn maybe_unit_block_parser<'src, I>(
2364 expr: GruelParser<'src, I, Expr>,
2365) -> GruelParser<'src, I, BlockExpr>
2366where
2367 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2368{
2369 block_item_parser(expr)
2370 .repeated()
2371 .collect::<Vec<_>>()
2372 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace))
2373 .map_with(|items, e| {
2374 let span = span_from_extra(e);
2375 let (statements, final_expr) = process_block_items(items, span);
2376 BlockExpr {
2377 statements,
2378 expr: Box::new(final_expr),
2379 span,
2380 }
2381 })
2382 .boxed()
2383}
2384
2385fn block_parser<'src, I>(expr: GruelParser<'src, I, Expr>) -> GruelParser<'src, I, Expr>
2387where
2388 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2389{
2390 block_item_parser(expr)
2391 .repeated()
2392 .collect::<Vec<_>>()
2393 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace))
2394 .map_with(|items, e| {
2395 let span = span_from_extra(e);
2396 let (statements, final_expr) = process_block_items(items, span);
2397 Expr::Block(BlockExpr {
2398 statements,
2399 expr: Box::new(final_expr),
2400 span,
2401 })
2402 })
2403 .boxed()
2404}
2405
2406fn function_parser<'src, I>() -> GruelParser<'src, I, Function>
2408where
2409 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2410{
2411 let expr = expr_parser();
2412
2413 let visibility = just(TokenKind::Pub).or_not().map(|opt| {
2415 if opt.is_some() {
2416 Visibility::Public
2417 } else {
2418 Visibility::Private
2419 }
2420 });
2421
2422 let fn_head: GruelParser<I, (Directives, Visibility, bool)> = directives_parser()
2424 .then(visibility)
2425 .then(just(TokenKind::Unchecked).or_not())
2426 .map(|((d, v), u)| (d, v, u.is_some()))
2427 .boxed();
2428
2429 let fn_sig: GruelParser<I, (Ident, Vec<Param>)> = just(TokenKind::Fn)
2430 .ignore_then(ident_parser())
2431 .then(params_parser().delimited_by(just(TokenKind::LParen), just(TokenKind::RParen)))
2432 .boxed();
2433
2434 fn_head
2435 .then(fn_sig)
2436 .then(just(TokenKind::Arrow).ignore_then(type_parser()).or_not())
2437 .then(block_parser(expr))
2438 .map_with(
2439 |((((directives, visibility, is_unchecked), (name, params)), return_type), body), e| {
2440 Function {
2441 directives,
2442 visibility,
2443 is_unchecked,
2444 name,
2445 params,
2446 return_type,
2447 body,
2448 span: span_from_extra(e),
2449 }
2450 },
2451 )
2452 .boxed()
2453}
2454
2455fn struct_parser<'src, I>() -> GruelParser<'src, I, StructDecl>
2460where
2461 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2462{
2463 let visibility = just(TokenKind::Pub).or_not().map(|opt| {
2465 if opt.is_some() {
2466 Visibility::Public
2467 } else {
2468 Visibility::Private
2469 }
2470 });
2471
2472 let struct_head: GruelParser<I, (Directives, Visibility, bool, Ident)> = directives_parser()
2474 .then(visibility)
2475 .then(just(TokenKind::Linear).or_not())
2476 .then(just(TokenKind::Struct).ignore_then(ident_parser()))
2477 .map(|(((d, v), l), name)| (d, v, l.is_some(), name))
2478 .boxed();
2479
2480 let struct_body: GruelParser<I, (Vec<FieldDecl>, Vec<Method>)> = field_decls_parser()
2482 .then(method_parser().repeated().collect::<Vec<_>>())
2483 .boxed();
2484
2485 struct_head
2486 .then(struct_body.delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)))
2487 .map_with(
2488 |((directives, visibility, is_linear, name), (fields, methods)), e| StructDecl {
2489 directives,
2490 visibility,
2491 is_linear,
2492 name,
2493 fields,
2494 methods,
2495 span: span_from_extra(e),
2496 },
2497 )
2498 .boxed()
2499}
2500
2501fn enum_variant_parser<'src, I>() -> GruelParser<'src, I, EnumVariant>
2503where
2504 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2505{
2506 use crate::ast::{EnumVariantField, EnumVariantKind};
2507
2508 let tuple_fields = type_parser()
2510 .separated_by(just(TokenKind::Comma))
2511 .allow_trailing()
2512 .collect::<Vec<_>>()
2513 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen));
2514
2515 let struct_field = ident_parser()
2517 .then_ignore(just(TokenKind::Colon))
2518 .then(type_parser())
2519 .map_with(|(name, ty), e| EnumVariantField {
2520 name,
2521 ty,
2522 span: span_from_extra(e),
2523 });
2524 let struct_fields = struct_field
2525 .separated_by(just(TokenKind::Comma))
2526 .allow_trailing()
2527 .collect::<Vec<_>>()
2528 .delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace));
2529
2530 let variant_kind = choice((
2532 tuple_fields.map(EnumVariantKind::Tuple),
2533 struct_fields.map(EnumVariantKind::Struct),
2534 ))
2535 .or_not()
2536 .map(|opt| opt.unwrap_or(EnumVariantKind::Unit));
2537
2538 ident_parser()
2539 .then(variant_kind)
2540 .map_with(|(name, kind), e| EnumVariant {
2541 name,
2542 kind,
2543 span: span_from_extra(e),
2544 })
2545 .boxed()
2546}
2547
2548fn enum_variants_parser<'src, I>() -> GruelParser<'src, I, Vec<EnumVariant>>
2550where
2551 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2552{
2553 enum_variant_parser()
2554 .separated_by(just(TokenKind::Comma))
2555 .allow_trailing()
2556 .collect::<Vec<_>>()
2557 .boxed()
2558}
2559
2560fn enum_parser<'src, I>() -> GruelParser<'src, I, EnumDecl>
2562where
2563 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2564{
2565 let visibility = just(TokenKind::Pub).or_not().map(|opt| {
2567 if opt.is_some() {
2568 Visibility::Public
2569 } else {
2570 Visibility::Private
2571 }
2572 });
2573
2574 visibility
2575 .then(just(TokenKind::Enum).ignore_then(ident_parser()))
2576 .then(enum_variants_parser().delimited_by(just(TokenKind::LBrace), just(TokenKind::RBrace)))
2577 .map_with(|((visibility, name), variants), e| EnumDecl {
2578 visibility,
2579 name,
2580 variants,
2581 span: span_from_extra(e),
2582 })
2583 .boxed()
2584}
2585
2586fn method_parser<'src, I>() -> GruelParser<'src, I, Method>
2589where
2590 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2591{
2592 let expr = expr_parser();
2593 method_parser_with_expr(expr)
2594}
2595
2596fn anon_struct_method_parser<'src, I>(
2599 expr: GruelParser<'src, I, Expr>,
2600) -> GruelParser<'src, I, Method>
2601where
2602 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2603{
2604 method_parser_with_expr(expr)
2605}
2606
2607fn method_parser_with_expr<'src, I>(
2610 expr: GruelParser<'src, I, Expr>,
2611) -> GruelParser<'src, I, Method>
2612where
2613 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2614{
2615 let self_param = just(TokenKind::SelfValue).map_with(|_, e| SelfParam {
2617 span: span_from_extra(e),
2618 });
2619
2620 let self_then_params = self_param
2622 .then(
2623 just(TokenKind::Comma)
2624 .ignore_then(params_parser())
2625 .or_not()
2626 .map(|opt| opt.unwrap_or_default()),
2627 )
2628 .map(|(self_param, params)| (Some(self_param), params));
2629
2630 let just_params = params_parser().map(|params| (None, params));
2632
2633 let params_with_optional_self: GruelParser<I, (Option<SelfParam>, Vec<Param>)> =
2635 choice((self_then_params.boxed(), just_params.boxed())).boxed();
2636
2637 let method_head: GruelParser<I, (Directives, Ident)> = directives_parser()
2639 .then(just(TokenKind::Fn).ignore_then(ident_parser()))
2640 .boxed();
2641
2642 let method_params: GruelParser<I, (Option<SelfParam>, Vec<Param>)> = params_with_optional_self
2643 .delimited_by(just(TokenKind::LParen), just(TokenKind::RParen))
2644 .boxed();
2645
2646 let method_return: GruelParser<I, Option<TypeExpr>> = just(TokenKind::Arrow)
2647 .ignore_then(type_parser())
2648 .or_not()
2649 .boxed();
2650
2651 method_head
2652 .then(method_params)
2653 .then(method_return)
2654 .then(block_parser(expr))
2655 .map_with(
2656 |((((directives, name), (receiver, params)), return_type), body), e| Method {
2657 directives,
2658 name,
2659 receiver,
2660 params,
2661 return_type,
2662 body,
2663 span: span_from_extra(e),
2664 },
2665 )
2666 .boxed()
2667}
2668
2669fn drop_fn_parser<'src, I>() -> GruelParser<'src, I, DropFn>
2671where
2672 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2673{
2674 let expr = expr_parser();
2675
2676 let self_param = just(TokenKind::SelfValue).map_with(|_, e| SelfParam {
2678 span: span_from_extra(e),
2679 });
2680
2681 let drop_fn_sig: GruelParser<'src, I, (Ident, SelfParam)> = just(TokenKind::Drop)
2683 .ignore_then(just(TokenKind::Fn))
2684 .ignore_then(ident_parser())
2685 .then(self_param.delimited_by(just(TokenKind::LParen), just(TokenKind::RParen)))
2686 .boxed();
2687
2688 drop_fn_sig
2689 .then(block_parser(expr))
2690 .map_with(|((type_name, self_param), body), e| DropFn {
2691 type_name,
2692 self_param,
2693 body,
2694 span: span_from_extra(e),
2695 })
2696 .boxed()
2697}
2698
2699fn const_parser<'src, I>() -> GruelParser<'src, I, ConstDecl>
2707where
2708 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2709{
2710 let expr = expr_parser();
2711
2712 let visibility = just(TokenKind::Pub).or_not().map(|opt| {
2714 if opt.is_some() {
2715 Visibility::Public
2716 } else {
2717 Visibility::Private
2718 }
2719 });
2720
2721 let const_head: GruelParser<I, (Directives, Visibility, Ident)> = directives_parser()
2723 .then(visibility)
2724 .then(just(TokenKind::Const).ignore_then(ident_parser()))
2725 .map(|((d, v), n)| (d, v, n))
2726 .boxed();
2727
2728 let const_tail: GruelParser<I, (Option<TypeExpr>, Expr)> = just(TokenKind::Colon)
2729 .ignore_then(type_parser())
2730 .or_not()
2731 .then(just(TokenKind::Eq).ignore_then(expr))
2732 .then_ignore(just(TokenKind::Semi))
2733 .boxed();
2734
2735 const_head
2736 .then(const_tail)
2737 .map_with(
2738 |((directives, visibility, name), (ty, init)), e| ConstDecl {
2739 directives,
2740 visibility,
2741 name,
2742 ty,
2743 init: Box::new(init),
2744 span: span_from_extra(e),
2745 },
2746 )
2747 .boxed()
2748}
2749
2750fn item_parser<'src, I>() -> GruelParser<'src, I, Item>
2752where
2753 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2754{
2755 choice((
2756 function_parser().map(Item::Function).boxed(),
2757 struct_parser().map(Item::Struct).boxed(),
2758 enum_parser().map(Item::Enum).boxed(),
2759 drop_fn_parser().map(Item::DropFn).boxed(),
2760 const_parser().map(Item::Const).boxed(),
2761 ))
2762 .boxed()
2763}
2764
2765fn item_start<'src, I>() -> GruelParser<'src, I, ()>
2768where
2769 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2770{
2771 let item_start_a: GruelParser<'src, I, ()> = choice((
2774 just(TokenKind::Fn).ignored().boxed(),
2775 just(TokenKind::Struct).ignored().boxed(),
2776 just(TokenKind::Enum).ignored().boxed(),
2777 just(TokenKind::Drop).ignored().boxed(),
2778 just(TokenKind::Const).ignored().boxed(),
2779 ))
2780 .boxed();
2781 let item_start_b: GruelParser<'src, I, ()> = choice((
2782 just(TokenKind::Pub).ignored().boxed(),
2783 just(TokenKind::Linear).ignored().boxed(),
2784 just(TokenKind::Unchecked).ignored().boxed(),
2785 just(TokenKind::At).ignored().boxed(), ))
2787 .boxed();
2788 choice((item_start_a, item_start_b))
2789 .rewind() .boxed()
2791}
2792
2793fn error_recovery<'src, I>() -> GruelParser<'src, I, Item>
2797where
2798 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2799{
2800 any()
2802 .map_with(|_, extra| extra.span())
2803 .then(
2805 any()
2806 .and_is(item_start().not())
2807 .repeated()
2808 .collect::<Vec<_>>(),
2809 )
2810 .map(|(start_span, _): (SimpleSpan, Vec<TokenKind>)| {
2811 Item::Error(to_gruel_span(start_span))
2813 })
2814 .boxed()
2815}
2816
2817fn item_with_recovery<'src, I>() -> GruelParser<'src, I, Item>
2821where
2822 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2823{
2824 item_parser()
2825 .recover_with(via_parser(error_recovery()))
2826 .boxed()
2827}
2828
2829fn ast_parser<'src, I>() -> GruelParser<'src, I, Ast>
2831where
2832 I: ValueInput<'src, Token = TokenKind, Span = SimpleSpan>,
2833{
2834 item_with_recovery()
2835 .repeated()
2836 .collect::<Vec<_>>()
2837 .then_ignore(end())
2838 .map(|items| Ast { items })
2839 .boxed()
2840}
2841
2842fn format_pattern(pattern: &chumsky::error::RichPattern<'_, TokenKind>) -> String {
2844 use chumsky::error::RichPattern;
2845 match pattern {
2846 RichPattern::Token(tok) => tok.name().to_string(),
2847 RichPattern::Label(label) => label.to_string(),
2848 RichPattern::Identifier(ident) => format!("'{}'", ident),
2849 RichPattern::Any => "any token".to_string(),
2850 RichPattern::SomethingElse => "something else".to_string(),
2851 RichPattern::EndOfInput => "end of input".to_string(),
2852 }
2853}
2854
2855fn convert_error(err: Rich<'_, TokenKind>) -> CompileError {
2857 let span = to_gruel_span(*err.span());
2858
2859 let mut error = match err.reason() {
2861 chumsky::error::RichReason::ExpectedFound { expected, found } => {
2862 let expected_str: Cow<'static, str> = if expected.is_empty() {
2863 Cow::Borrowed("something")
2864 } else {
2865 Cow::Owned(
2866 expected
2867 .iter()
2868 .take(3) .map(format_pattern)
2870 .collect::<Vec<_>>()
2871 .join(" or "),
2872 )
2873 };
2874
2875 let found_str: Cow<'static, str> = match found.as_ref() {
2876 Some(t) => Cow::Owned(t.name().to_string()),
2877 None => Cow::Borrowed("end of file"),
2878 };
2879
2880 CompileError::new(
2881 ErrorKind::UnexpectedToken {
2882 expected: expected_str,
2883 found: found_str,
2884 },
2885 span,
2886 )
2887 }
2888 chumsky::error::RichReason::Custom(msg) => {
2889 CompileError::new(ErrorKind::ParseError(msg.clone()), span)
2891 }
2892 };
2893
2894 for (pattern, ctx_span) in err.contexts() {
2896 let label_msg = format!("while parsing {}", format_pattern(pattern));
2897 let label_span = to_gruel_span(*ctx_span);
2898 error = error.with_label(label_msg, label_span);
2899 }
2900
2901 error
2902}
2903
2904pub struct ChumskyParser {
2906 tokens: Vec<(TokenKind, SimpleSpan)>,
2907 source_len: usize,
2908 interner: ThreadedRodeo,
2909 file_id: FileId,
2911}
2912
2913impl ChumskyParser {
2914 pub fn new(tokens: Vec<gruel_lexer::Token>, interner: ThreadedRodeo) -> Self {
2916 let source_len = tokens.last().map(|t| t.span.end as usize).unwrap_or(0);
2917 let file_id = tokens
2919 .first()
2920 .map(|t| t.span.file_id)
2921 .unwrap_or(FileId::DEFAULT);
2922
2923 let spanned_tokens: Vec<(TokenKind, SimpleSpan)> = tokens
2924 .into_iter()
2925 .filter(|t| t.kind != TokenKind::Eof) .map(|t| {
2927 (
2928 t.kind,
2929 SimpleSpan::new(t.span.start as usize, t.span.end as usize),
2930 )
2931 })
2932 .collect();
2933 Self {
2934 tokens: spanned_tokens,
2935 source_len,
2936 interner,
2937 file_id,
2938 }
2939 }
2940
2941 pub fn parse(mut self) -> MultiErrorResult<(Ast, ThreadedRodeo)> {
2945 let syms = PrimitiveTypeSpurs::new(&mut self.interner);
2947 let parser_state = ParserState::new(syms, self.file_id);
2948 let mut state = SimpleState(parser_state);
2949
2950 let token_iter = self.tokens.iter().cloned();
2952 let stream = Stream::from_iter(token_iter);
2953
2954 let eoi: SimpleSpan = (self.source_len..self.source_len).into();
2956 let mapped = stream.map(eoi, |(tok, span)| (tok, span));
2957
2958 let result = ast_parser()
2959 .parse_with_state(mapped, &mut state)
2960 .into_result()
2961 .map_err(|errs| {
2962 let errors: Vec<CompileError> = errs.into_iter().map(convert_error).collect();
2963 CompileErrors::from(errors)
2964 });
2965
2966 result.map(|ast| (ast, self.interner))
2967 }
2968}
2969
2970#[cfg(test)]
2971mod tests {
2972 use super::*;
2973 use gruel_lexer::Lexer;
2974
2975 #[derive(Debug)]
2978 struct ParseResult {
2979 ast: Ast,
2980 interner: ThreadedRodeo,
2981 }
2982
2983 impl ParseResult {
2984 fn get(&self, sym: Spur) -> &str {
2986 self.interner.resolve(&sym)
2987 }
2988 }
2989
2990 #[derive(Debug)]
2992 struct ExprResult {
2993 expr: Expr,
2994 interner: ThreadedRodeo,
2995 }
2996
2997 impl ExprResult {
2998 fn get(&self, sym: Spur) -> &str {
3000 self.interner.resolve(&sym)
3001 }
3002 }
3003
3004 fn parse(source: &str) -> MultiErrorResult<ParseResult> {
3005 let lexer = Lexer::new(source);
3006 let (tokens, interner) = lexer.tokenize().map_err(CompileErrors::from)?;
3007 let parser = ChumskyParser::new(tokens, interner);
3008 let (ast, interner) = parser.parse()?;
3009 Ok(ParseResult { ast, interner })
3010 }
3011
3012 fn parse_expr(source: &str) -> MultiErrorResult<ExprResult> {
3013 let result = parse(&format!("fn main() -> i32 {{ {} }}", source))?;
3014 let interner = result.interner;
3015 let expr = match result.ast.items.into_iter().next().unwrap() {
3016 Item::Function(f) => match f.body {
3017 Expr::Block(block) => *block.expr,
3018 other => other,
3019 },
3020 Item::Struct(_) => panic!("parse_expr helper should only be used with functions"),
3021 Item::Enum(_) => panic!("parse_expr helper should only be used with functions"),
3022 Item::DropFn(_) => panic!("parse_expr helper should only be used with functions"),
3023 Item::Const(_) => panic!("parse_expr helper should only be used with functions"),
3024 Item::Error(_) => panic!("parse_expr helper should only be used with functions"),
3025 };
3026 Ok(ExprResult { expr, interner })
3027 }
3028
3029 #[test]
3030 fn test_chumsky_parse_main() {
3031 let result = parse("fn main() -> i32 { 42 }").unwrap();
3032
3033 assert_eq!(result.ast.items.len(), 1);
3034 match &result.ast.items[0] {
3035 Item::Function(f) => {
3036 assert_eq!(result.get(f.name.name), "main");
3037 match f.return_type.as_ref().unwrap() {
3038 TypeExpr::Named(ident) => assert_eq!(result.get(ident.name), "i32"),
3039 _ => panic!("expected Named type"),
3040 }
3041 match &f.body {
3042 Expr::Block(block) => match block.expr.as_ref() {
3043 Expr::Int(lit) => assert_eq!(lit.value, 42),
3044 _ => panic!("expected Int"),
3045 },
3046 _ => panic!("expected Block"),
3047 }
3048 }
3049 Item::Struct(_) => panic!("expected Function"),
3050 Item::Enum(_) => panic!("expected Function"),
3051 Item::DropFn(_) => panic!("expected Function"),
3052 Item::Const(_) => panic!("expected Function"),
3053 Item::Error(_) => panic!("expected Function"),
3054 }
3055 }
3056
3057 #[test]
3058 fn test_chumsky_parse_addition() {
3059 let result = parse_expr("1 + 2").unwrap();
3060 match result.expr {
3061 Expr::Binary(bin) => {
3062 assert!(matches!(bin.op, BinaryOp::Add));
3063 match (*bin.left, *bin.right) {
3064 (Expr::Int(l), Expr::Int(r)) => {
3065 assert_eq!(l.value, 1);
3066 assert_eq!(r.value, 2);
3067 }
3068 _ => panic!("expected Int operands"),
3069 }
3070 }
3071 _ => panic!("expected Binary"),
3072 }
3073 }
3074
3075 #[test]
3076 fn test_chumsky_parse_precedence() {
3077 let result = parse_expr("1 + 2 * 3").unwrap();
3079 match result.expr {
3080 Expr::Binary(bin) => {
3081 assert!(matches!(bin.op, BinaryOp::Add));
3082 match *bin.left {
3083 Expr::Int(l) => assert_eq!(l.value, 1),
3084 _ => panic!("expected Int"),
3085 }
3086 match *bin.right {
3087 Expr::Binary(inner) => {
3088 assert!(matches!(inner.op, BinaryOp::Mul));
3089 }
3090 _ => panic!("expected Binary"),
3091 }
3092 }
3093 _ => panic!("expected Binary"),
3094 }
3095 }
3096
3097 #[test]
3098 fn test_chumsky_parse_let_binding() {
3099 let result = parse("fn main() -> i32 { let x = 42; x }").unwrap();
3100 match &result.ast.items[0] {
3101 Item::Function(f) => match &f.body {
3102 Expr::Block(block) => {
3103 assert_eq!(block.statements.len(), 1);
3104 match &block.statements[0] {
3105 Statement::Let(let_stmt) => {
3106 assert!(!let_stmt.is_mut);
3107 match &let_stmt.pattern {
3108 LetPattern::Ident(ident) => {
3109 assert_eq!(result.get(ident.name), "x")
3110 }
3111 LetPattern::Wildcard(_) => panic!("expected Ident, got Wildcard"),
3112 LetPattern::Struct { .. } => panic!("expected Ident, got Struct"),
3113 }
3114 }
3115 _ => panic!("expected Let"),
3116 }
3117 }
3118 _ => panic!("expected Block"),
3119 },
3120 Item::Struct(_) => panic!("expected Function"),
3121 Item::Enum(_) => panic!("expected Function"),
3122 Item::DropFn(_) => panic!("expected Function"),
3123 Item::Const(_) => panic!("expected Function"),
3124 Item::Error(_) => panic!("expected Function"),
3125 }
3126 }
3127
3128 #[test]
3129 fn test_while_simple() {
3130 let result = parse("fn main() -> i32 { while true { } 0 }").unwrap();
3132 assert_eq!(result.ast.items.len(), 1);
3133 }
3134
3135 #[test]
3136 fn test_while_with_statement() {
3137 let result = parse("fn main() -> i32 { while true { x = 1; } 0 }").unwrap();
3139 assert_eq!(result.ast.items.len(), 1);
3140 }
3141
3142 #[test]
3143 fn test_function_calls() {
3144 let result =
3145 parse("fn add(a: i32, b: i32) -> i32 { a + b } fn main() -> i32 { add(1, 2) }")
3146 .unwrap();
3147 assert_eq!(result.ast.items.len(), 2);
3148 }
3149
3150 #[test]
3151 fn test_if_else() {
3152 let result = parse("fn main() -> i32 { if true { 1 } else { 0 } }").unwrap();
3153 assert_eq!(result.ast.items.len(), 1);
3154 }
3155
3156 #[test]
3157 fn test_nested_control_flow() {
3158 let result =
3159 parse("fn main() -> i32 { let mut x = 0; while x < 10 { x = x + 1; } x }").unwrap();
3160 assert_eq!(result.ast.items.len(), 1);
3161 }
3162
3163 #[test]
3166 fn test_struct_with_single_method() {
3167 let result = parse("struct Point { x: i32, fn get_x(self) -> i32 { self.x } }").unwrap();
3168 assert_eq!(result.ast.items.len(), 1);
3169 match &result.ast.items[0] {
3170 Item::Struct(struct_decl) => {
3171 assert_eq!(result.get(struct_decl.name.name), "Point");
3172 assert_eq!(struct_decl.methods.len(), 1);
3173 let method = &struct_decl.methods[0];
3174 assert_eq!(result.get(method.name.name), "get_x");
3175 assert!(method.receiver.is_some()); assert!(method.params.is_empty()); }
3178 _ => panic!("expected Struct"),
3179 }
3180 }
3181
3182 #[test]
3183 fn test_struct_method_with_params() {
3184 let result =
3185 parse("struct Point { x: i32, fn add(self, n: i32) -> i32 { self.x + n } }").unwrap();
3186 assert_eq!(result.ast.items.len(), 1);
3187 match &result.ast.items[0] {
3188 Item::Struct(struct_decl) => {
3189 let method = &struct_decl.methods[0];
3190 assert_eq!(result.get(method.name.name), "add");
3191 assert!(method.receiver.is_some());
3192 assert_eq!(method.params.len(), 1);
3193 assert_eq!(result.get(method.params[0].name.name), "n");
3194 }
3195 _ => panic!("expected Struct"),
3196 }
3197 }
3198
3199 #[test]
3200 fn test_struct_associated_function() {
3201 let result = parse(
3203 "struct Point { x: i32, y: i32, fn new(x: i32, y: i32) -> Point { Point { x: x, y: y } } }",
3204 )
3205 .unwrap();
3206 assert_eq!(result.ast.items.len(), 1);
3207 match &result.ast.items[0] {
3208 Item::Struct(struct_decl) => {
3209 let method = &struct_decl.methods[0];
3210 assert_eq!(result.get(method.name.name), "new");
3211 assert!(method.receiver.is_none()); assert_eq!(method.params.len(), 2);
3213 }
3214 _ => panic!("expected Struct"),
3215 }
3216 }
3217
3218 #[test]
3219 fn test_struct_multiple_methods() {
3220 let result = parse(
3221 "struct Counter {
3222 value: i32,
3223 fn new() -> Counter { Counter { value: 0 } }
3224 fn get(self) -> i32 { self.value }
3225 fn increment(self) -> i32 { self.value + 1 }
3226 }",
3227 )
3228 .unwrap();
3229 assert_eq!(result.ast.items.len(), 1);
3230 match &result.ast.items[0] {
3231 Item::Struct(struct_decl) => {
3232 assert_eq!(struct_decl.methods.len(), 3);
3233 assert!(struct_decl.methods[0].receiver.is_none());
3235 assert_eq!(result.get(struct_decl.methods[0].name.name), "new");
3236 assert!(struct_decl.methods[1].receiver.is_some());
3238 assert_eq!(result.get(struct_decl.methods[1].name.name), "get");
3239 assert!(struct_decl.methods[2].receiver.is_some());
3241 assert_eq!(result.get(struct_decl.methods[2].name.name), "increment");
3242 }
3243 _ => panic!("expected Struct"),
3244 }
3245 }
3246
3247 #[test]
3248 fn test_struct_method_with_directive() {
3249 let result = parse("struct Foo { @inline fn bar(self) -> i32 { 42 } }").unwrap();
3250 match &result.ast.items[0] {
3251 Item::Struct(struct_decl) => {
3252 let method = &struct_decl.methods[0];
3253 assert_eq!(method.directives.len(), 1);
3254 assert_eq!(result.get(method.directives[0].name.name), "inline");
3255 }
3256 _ => panic!("expected Struct"),
3257 }
3258 }
3259
3260 #[test]
3263 fn test_method_call_simple() {
3264 let result = parse_expr("x.foo()").unwrap();
3265 match &result.expr {
3266 Expr::MethodCall(call) => {
3267 assert_eq!(result.get(call.method.name), "foo");
3268 assert!(call.args.is_empty());
3269 match call.receiver.as_ref() {
3270 Expr::Ident(ident) => assert_eq!(result.get(ident.name), "x"),
3271 _ => panic!("expected Ident receiver"),
3272 }
3273 }
3274 _ => panic!("expected MethodCall, got {:?}", result.expr),
3275 }
3276 }
3277
3278 #[test]
3279 fn test_method_call_with_args() {
3280 let result = parse_expr("point.add(5, 10)").unwrap();
3281 match &result.expr {
3282 Expr::MethodCall(call) => {
3283 assert_eq!(result.get(call.method.name), "add");
3284 assert_eq!(call.args.len(), 2);
3285 }
3286 _ => panic!("expected MethodCall"),
3287 }
3288 }
3289
3290 #[test]
3291 fn test_method_call_chained() {
3292 let result = parse_expr("x.foo().bar()").unwrap();
3293 match &result.expr {
3294 Expr::MethodCall(outer) => {
3295 assert_eq!(result.get(outer.method.name), "bar");
3296 match outer.receiver.as_ref() {
3297 Expr::MethodCall(inner) => {
3298 assert_eq!(result.get(inner.method.name), "foo");
3299 }
3300 _ => panic!("expected inner MethodCall"),
3301 }
3302 }
3303 _ => panic!("expected outer MethodCall"),
3304 }
3305 }
3306
3307 #[test]
3308 fn test_method_call_on_field_access() {
3309 let result = parse_expr("obj.field.method()").unwrap();
3310 match &result.expr {
3311 Expr::MethodCall(call) => {
3312 assert_eq!(result.get(call.method.name), "method");
3313 match call.receiver.as_ref() {
3314 Expr::Field(field) => {
3315 assert_eq!(result.get(field.field.name), "field");
3316 }
3317 _ => panic!("expected Field receiver"),
3318 }
3319 }
3320 _ => panic!("expected MethodCall"),
3321 }
3322 }
3323
3324 #[test]
3325 fn test_field_access_not_method_call() {
3326 let result = parse_expr("x.field").unwrap();
3328 match &result.expr {
3329 Expr::Field(field) => {
3330 assert_eq!(result.get(field.field.name), "field");
3331 }
3332 _ => panic!("expected Field, got {:?}", result.expr),
3333 }
3334 }
3335
3336 #[test]
3337 fn test_method_call_on_struct_literal() {
3338 let result =
3339 parse("struct Point { x: i32 } fn main() -> i32 { Point { x: 1 }.get() }").unwrap();
3340 match &result.ast.items[1] {
3341 Item::Function(f) => match &f.body {
3342 Expr::Block(block) => match block.expr.as_ref() {
3343 Expr::MethodCall(call) => {
3344 assert_eq!(result.get(call.method.name), "get");
3345 match call.receiver.as_ref() {
3346 Expr::StructLit(lit) => {
3347 assert_eq!(result.get(lit.name.name), "Point")
3348 }
3349 _ => panic!("expected StructLit receiver"),
3350 }
3351 }
3352 _ => panic!("expected MethodCall"),
3353 },
3354 _ => panic!("expected Block"),
3355 },
3356 _ => panic!("expected Function"),
3357 }
3358 }
3359
3360 #[test]
3361 fn test_method_call_on_paren_expr() {
3362 let result = parse_expr("(x).method()").unwrap();
3363 match &result.expr {
3364 Expr::MethodCall(call) => {
3365 assert_eq!(result.get(call.method.name), "method");
3366 match call.receiver.as_ref() {
3367 Expr::Paren(_) => {}
3368 _ => panic!("expected Paren receiver"),
3369 }
3370 }
3371 _ => panic!("expected MethodCall"),
3372 }
3373 }
3374
3375 #[test]
3376 fn test_method_call_mixed_with_index() {
3377 let result = parse_expr("arr[0].get().value").unwrap();
3379 match &result.expr {
3380 Expr::Field(field) => {
3381 assert_eq!(result.get(field.field.name), "value");
3382 match field.base.as_ref() {
3383 Expr::MethodCall(call) => {
3384 assert_eq!(result.get(call.method.name), "get");
3385 match call.receiver.as_ref() {
3386 Expr::Index(_) => {}
3387 _ => panic!("expected Index receiver"),
3388 }
3389 }
3390 _ => panic!("expected MethodCall"),
3391 }
3392 }
3393 _ => panic!("expected Field"),
3394 }
3395 }
3396
3397 #[test]
3398 fn test_associated_function_call() {
3399 let result = parse_expr("Point::new(1, 2)").unwrap();
3401 match &result.expr {
3402 Expr::AssocFnCall(call) => {
3403 assert_eq!(result.get(call.type_name.name), "Point");
3404 assert_eq!(result.get(call.function.name), "new");
3405 assert_eq!(call.args.len(), 2);
3406 }
3407 _ => panic!("expected AssocFnCall, got {:?}", result.expr),
3408 }
3409 }
3410
3411 #[test]
3414 fn test_borrow_param_simple() {
3415 let result = parse("fn read(borrow x: i32) -> i32 { x }").unwrap();
3417 match &result.ast.items[0] {
3418 Item::Function(f) => {
3419 assert_eq!(f.params.len(), 1);
3420 assert_eq!(f.params[0].mode, ParamMode::Borrow);
3421 assert_eq!(result.get(f.params[0].name.name), "x");
3422 }
3423 _ => panic!("expected Function"),
3424 }
3425 }
3426
3427 #[test]
3428 fn test_borrow_param_with_struct_type() {
3429 let result =
3431 parse("struct Point { x: i32 } fn read(borrow p: Point) -> i32 { p.x }").unwrap();
3432 match &result.ast.items[1] {
3433 Item::Function(f) => {
3434 assert_eq!(f.params.len(), 1);
3435 assert_eq!(f.params[0].mode, ParamMode::Borrow);
3436 assert_eq!(result.get(f.params[0].name.name), "p");
3437 match &f.params[0].ty {
3438 TypeExpr::Named(ident) => assert_eq!(result.get(ident.name), "Point"),
3439 _ => panic!("expected Named type"),
3440 }
3441 }
3442 _ => panic!("expected Function"),
3443 }
3444 }
3445
3446 #[test]
3447 fn test_borrow_param_mixed_with_normal() {
3448 let result = parse("fn add(borrow a: i32, b: i32) -> i32 { a + b }").unwrap();
3450 match &result.ast.items[0] {
3451 Item::Function(f) => {
3452 assert_eq!(f.params.len(), 2);
3453 assert_eq!(f.params[0].mode, ParamMode::Borrow);
3454 assert_eq!(result.get(f.params[0].name.name), "a");
3455 assert_eq!(f.params[1].mode, ParamMode::Normal);
3456 assert_eq!(result.get(f.params[1].name.name), "b");
3457 }
3458 _ => panic!("expected Function"),
3459 }
3460 }
3461
3462 #[test]
3463 fn test_borrow_param_mixed_with_inout() {
3464 let result = parse("fn modify(borrow a: i32, inout b: i32) { b = a; }").unwrap();
3466 match &result.ast.items[0] {
3467 Item::Function(f) => {
3468 assert_eq!(f.params.len(), 2);
3469 assert_eq!(f.params[0].mode, ParamMode::Borrow);
3470 assert_eq!(result.get(f.params[0].name.name), "a");
3471 assert_eq!(f.params[1].mode, ParamMode::Inout);
3472 assert_eq!(result.get(f.params[1].name.name), "b");
3473 }
3474 _ => panic!("expected Function"),
3475 }
3476 }
3477
3478 #[test]
3479 fn test_borrow_param_with_array_type() {
3480 let result = parse("fn first(borrow arr: [i32; 3]) -> i32 { arr[0] }").unwrap();
3482 match &result.ast.items[0] {
3483 Item::Function(f) => {
3484 assert_eq!(f.params.len(), 1);
3485 assert_eq!(f.params[0].mode, ParamMode::Borrow);
3486 match &f.params[0].ty {
3487 TypeExpr::Array { length, .. } => assert_eq!(*length, 3),
3488 _ => panic!("expected Array type"),
3489 }
3490 }
3491 _ => panic!("expected Function"),
3492 }
3493 }
3494
3495 #[test]
3496 fn test_borrow_param_multiple() {
3497 let result = parse("fn sum(borrow a: i32, borrow b: i32) -> i32 { a + b }").unwrap();
3499 match &result.ast.items[0] {
3500 Item::Function(f) => {
3501 assert_eq!(f.params.len(), 2);
3502 assert_eq!(f.params[0].mode, ParamMode::Borrow);
3503 assert_eq!(f.params[1].mode, ParamMode::Borrow);
3504 }
3505 _ => panic!("expected Function"),
3506 }
3507 }
3508
3509 #[test]
3512 fn test_borrow_arg_simple() {
3513 let result = parse_expr("read(borrow x)").unwrap();
3515 match &result.expr {
3516 Expr::Call(call) => {
3517 assert_eq!(result.get(call.name.name), "read");
3518 assert_eq!(call.args.len(), 1);
3519 assert_eq!(call.args[0].mode, ArgMode::Borrow);
3520 match &call.args[0].expr {
3521 Expr::Ident(ident) => assert_eq!(result.get(ident.name), "x"),
3522 _ => panic!("expected Ident argument"),
3523 }
3524 }
3525 _ => panic!("expected Call, got {:?}", result.expr),
3526 }
3527 }
3528
3529 #[test]
3530 fn test_borrow_arg_mixed_with_normal() {
3531 let result = parse_expr("foo(borrow a, b)").unwrap();
3533 match &result.expr {
3534 Expr::Call(call) => {
3535 assert_eq!(call.args.len(), 2);
3536 assert_eq!(call.args[0].mode, ArgMode::Borrow);
3537 assert_eq!(call.args[1].mode, ArgMode::Normal);
3538 }
3539 _ => panic!("expected Call"),
3540 }
3541 }
3542
3543 #[test]
3544 fn test_borrow_arg_mixed_with_inout() {
3545 let result = parse_expr("modify(borrow a, inout b)").unwrap();
3547 match &result.expr {
3548 Expr::Call(call) => {
3549 assert_eq!(call.args.len(), 2);
3550 assert_eq!(call.args[0].mode, ArgMode::Borrow);
3551 assert_eq!(call.args[1].mode, ArgMode::Inout);
3552 }
3553 _ => panic!("expected Call"),
3554 }
3555 }
3556
3557 #[test]
3558 fn test_borrow_arg_multiple() {
3559 let result = parse_expr("sum(borrow x, borrow y)").unwrap();
3561 match &result.expr {
3562 Expr::Call(call) => {
3563 assert_eq!(call.args.len(), 2);
3564 assert_eq!(call.args[0].mode, ArgMode::Borrow);
3565 assert_eq!(call.args[1].mode, ArgMode::Borrow);
3566 }
3567 _ => panic!("expected Call"),
3568 }
3569 }
3570
3571 #[test]
3572 fn test_borrow_arg_with_field_access() {
3573 let result = parse_expr("read(borrow point.x)").unwrap();
3575 match &result.expr {
3576 Expr::Call(call) => {
3577 assert_eq!(call.args.len(), 1);
3578 assert_eq!(call.args[0].mode, ArgMode::Borrow);
3579 match &call.args[0].expr {
3580 Expr::Field(field) => assert_eq!(result.get(field.field.name), "x"),
3581 _ => panic!("expected Field expression"),
3582 }
3583 }
3584 _ => panic!("expected Call"),
3585 }
3586 }
3587
3588 #[test]
3589 fn test_borrow_arg_in_method_call() {
3590 let result = parse_expr("obj.method(borrow x)").unwrap();
3592 match &result.expr {
3593 Expr::MethodCall(call) => {
3594 assert_eq!(call.args.len(), 1);
3595 assert_eq!(call.args[0].mode, ArgMode::Borrow);
3596 }
3597 _ => panic!("expected MethodCall"),
3598 }
3599 }
3600
3601 #[test]
3602 fn test_borrow_arg_in_associated_function() {
3603 let result = parse_expr("Foo::bar(borrow x)").unwrap();
3605 match &result.expr {
3606 Expr::AssocFnCall(call) => {
3607 assert_eq!(call.args.len(), 1);
3608 assert_eq!(call.args[0].mode, ArgMode::Borrow);
3609 }
3610 _ => panic!("expected AssocFnCall"),
3611 }
3612 }
3613
3614 #[test]
3615 fn test_borrow_helper_methods() {
3616 let result = parse_expr("foo(borrow x, inout y, z)").unwrap();
3618 match &result.expr {
3619 Expr::Call(call) => {
3620 assert!(call.args[0].is_borrow());
3621 assert!(!call.args[0].is_inout());
3622 assert!(call.args[1].is_inout());
3623 assert!(!call.args[1].is_borrow());
3624 assert!(!call.args[2].is_borrow());
3625 assert!(!call.args[2].is_inout());
3626 }
3627 _ => panic!("expected Call"),
3628 }
3629 }
3630
3631 #[test]
3634 fn test_block_statement_followed_by_identifier() {
3635 let result = parse(
3638 "fn main() -> i32 {
3639 let a = 1;
3640 {
3641 let b = 2;
3642 }
3643 a
3644 }",
3645 )
3646 .unwrap();
3647 match &result.ast.items[0] {
3648 Item::Function(f) => match &f.body {
3649 Expr::Block(block) => {
3650 assert_eq!(block.statements.len(), 2);
3652 assert!(matches!(&block.statements[0], Statement::Let(_)));
3654 match &block.statements[1] {
3656 Statement::Expr(Expr::Block(_)) => {}
3657 _ => panic!("expected Expr(Block), got {:?}", block.statements[1]),
3658 }
3659 match block.expr.as_ref() {
3661 Expr::Ident(ident) => assert_eq!(result.get(ident.name), "a"),
3662 _ => panic!("expected Ident expression, got {:?}", block.expr),
3663 }
3664 }
3665 _ => panic!("expected Block"),
3666 },
3667 _ => panic!("expected Function"),
3668 }
3669 }
3670
3671 #[test]
3674 fn test_error_preserves_span() {
3675 let result = parse("fn main() -> i32 { let = 42; }");
3677 assert!(result.is_err());
3678 let errors = result.unwrap_err();
3679 let error = errors.first().expect("should have at least one error");
3681 assert!(error.has_span());
3682 assert!(error.span().is_some());
3683 }
3684
3685 #[test]
3686 fn test_error_expected_found() {
3687 let result = parse("fn main() -> i32 { let x = ; }");
3689 assert!(result.is_err());
3690 let errors = result.unwrap_err();
3691 let error = errors.first().expect("should have at least one error");
3692 let msg = error.to_string();
3694 assert!(
3695 msg.contains("expected") || msg.contains("found"),
3696 "error message: {}",
3697 msg
3698 );
3699 }
3700
3701 #[test]
3702 fn test_error_unexpected_eof() {
3703 let result = parse("fn main() -> i32 {");
3705 assert!(result.is_err());
3706 let errors = result.unwrap_err();
3707 let error = errors.first().expect("should have at least one error");
3708 let msg = error.to_string();
3709 assert!(
3711 msg.contains("end of file") || msg.contains("expected"),
3712 "error message: {}",
3713 msg
3714 );
3715 }
3716
3717 #[test]
3718 fn test_format_pattern_token() {
3719 use chumsky::error::RichPattern;
3720 use chumsky::util::MaybeRef;
3721
3722 let pattern = RichPattern::Token(MaybeRef::Val(TokenKind::Plus));
3723 let formatted = format_pattern(&pattern);
3724 assert_eq!(formatted, "'+'");
3726 }
3727
3728 #[test]
3729 fn test_format_pattern_label() {
3730 use chumsky::error::RichPattern;
3731
3732 let pattern: RichPattern<'_, TokenKind> = RichPattern::Label(Cow::Borrowed("expression"));
3733 let formatted = format_pattern(&pattern);
3734 assert_eq!(formatted, "expression");
3735 }
3736
3737 #[test]
3738 fn test_format_pattern_identifier() {
3739 use chumsky::error::RichPattern;
3740
3741 let pattern: RichPattern<'_, TokenKind> = RichPattern::Identifier("while".to_string());
3742 let formatted = format_pattern(&pattern);
3743 assert_eq!(formatted, "'while'");
3744 }
3745
3746 #[test]
3747 fn test_format_pattern_any() {
3748 use chumsky::error::RichPattern;
3749
3750 let pattern: RichPattern<'_, TokenKind> = RichPattern::Any;
3751 let formatted = format_pattern(&pattern);
3752 assert_eq!(formatted, "any token");
3753 }
3754
3755 #[test]
3756 fn test_format_pattern_end_of_input() {
3757 use chumsky::error::RichPattern;
3758
3759 let pattern: RichPattern<'_, TokenKind> = RichPattern::EndOfInput;
3760 let formatted = format_pattern(&pattern);
3761 assert_eq!(formatted, "end of input");
3762 }
3763
3764 #[test]
3765 fn test_parse_error_no_empty_found_clause() {
3766 let result = parse("fn main() -> i32 { let x = ; }");
3769 assert!(result.is_err());
3770 let errors = result.unwrap_err();
3771 let error = errors.first().expect("should have at least one error");
3772 let msg = error.to_string();
3773 assert!(
3775 !msg.ends_with("found "),
3776 "error message should not have trailing empty 'found': {}",
3777 msg
3778 );
3779 }
3780
3781 #[test]
3782 fn test_parse_error_variant_display() {
3783 let error = CompileError::new(
3785 ErrorKind::ParseError("expected semicolon after expression".to_string()),
3786 gruel_span::Span::new(0, 10),
3787 );
3788 assert_eq!(error.to_string(), "expected semicolon after expression");
3789 }
3790
3791 #[test]
3792 fn test_offset_to_u32_normal() {
3793 assert_eq!(offset_to_u32(0), 0);
3795 assert_eq!(offset_to_u32(42), 42);
3796 assert_eq!(offset_to_u32(1000000), 1000000);
3797 assert_eq!(offset_to_u32(u32::MAX as usize), u32::MAX);
3798 }
3799
3800 #[test]
3801 #[should_panic(expected = "offset 4294967296 exceeds u32::MAX")]
3802 #[cfg(debug_assertions)]
3803 fn test_offset_to_u32_overflow_panics_in_debug() {
3804 let _ = offset_to_u32((u32::MAX as usize) + 1);
3806 }
3807
3808 #[test]
3809 fn test_to_gruel_span_normal() {
3810 let simple = SimpleSpan::new(10, 20);
3812 let gruel = to_gruel_span(simple);
3813 assert_eq!(gruel.start, 10);
3814 assert_eq!(gruel.end, 20);
3815 }
3816
3817 #[test]
3818 fn test_parse_returns_multiple_errors() {
3819 let source = "fn main() { let }"; let result = parse(source);
3826 assert!(result.is_err(), "Expected parsing to fail");
3827
3828 let errors = result.unwrap_err();
3830 assert!(
3831 !errors.is_empty(),
3832 "Expected at least one error but got none"
3833 );
3834
3835 let error_count = errors.len();
3837 assert!(
3838 error_count >= 1,
3839 "Expected at least 1 error, got {}",
3840 error_count
3841 );
3842 }
3843
3844 #[test]
3845 fn test_parse_error_collection_preserves_all() {
3846 let errors = vec![
3849 CompileError::without_span(ErrorKind::UnexpectedToken {
3850 expected: std::borrow::Cow::Borrowed("ident"),
3851 found: std::borrow::Cow::Borrowed("let"),
3852 }),
3853 CompileError::without_span(ErrorKind::UnexpectedToken {
3854 expected: std::borrow::Cow::Borrowed("expr"),
3855 found: std::borrow::Cow::Borrowed("rbrace"),
3856 }),
3857 ];
3858
3859 let compile_errors = CompileErrors::from(errors);
3860 assert_eq!(compile_errors.len(), 2, "Expected 2 errors to be preserved");
3861 }
3862
3863 #[test]
3866 fn test_qualified_struct_literal() {
3867 let result = parse_expr("mod.Point { x: 1, y: 2 }").unwrap();
3869 match &result.expr {
3870 Expr::StructLit(lit) => {
3871 assert!(
3873 lit.base.is_some(),
3874 "qualified struct literal should have a base"
3875 );
3876 match lit.base.as_ref().unwrap().as_ref() {
3877 Expr::Ident(ident) => assert_eq!(result.get(ident.name), "mod"),
3878 _ => panic!("base should be Ident, got {:?}", lit.base),
3879 }
3880 assert_eq!(result.get(lit.name.name), "Point");
3882 assert_eq!(lit.fields.len(), 2);
3884 assert_eq!(result.get(lit.fields[0].name.name), "x");
3885 assert_eq!(result.get(lit.fields[1].name.name), "y");
3886 }
3887 _ => panic!("expected StructLit, got {:?}", result.expr),
3888 }
3889 }
3890
3891 #[test]
3892 fn test_qualified_struct_literal_empty() {
3893 let result = parse_expr("mod.Empty {}").unwrap();
3895 match &result.expr {
3896 Expr::StructLit(lit) => {
3897 assert!(
3898 lit.base.is_some(),
3899 "qualified struct literal should have a base"
3900 );
3901 assert_eq!(result.get(lit.name.name), "Empty");
3902 assert_eq!(lit.fields.len(), 0);
3903 }
3904 _ => panic!("expected StructLit, got {:?}", result.expr),
3905 }
3906 }
3907
3908 #[test]
3909 fn test_field_access_then_block() {
3910 let result = parse("fn main() -> i32 { x.field; { 1 } }").unwrap();
3914 match &result.ast.items[0] {
3915 Item::Function(f) => match &f.body {
3916 Expr::Block(block) => {
3917 assert_eq!(block.statements.len(), 1);
3920 match &block.statements[0] {
3921 Statement::Expr(Expr::Field(field)) => {
3922 assert_eq!(result.get(field.field.name), "field");
3923 }
3924 _ => panic!("expected Field statement, got {:?}", block.statements[0]),
3925 }
3926 match block.expr.as_ref() {
3927 Expr::Block(inner) => match inner.expr.as_ref() {
3928 Expr::Int(lit) => assert_eq!(lit.value, 1),
3929 _ => panic!("expected Int, got {:?}", inner.expr),
3930 },
3931 _ => panic!("expected Block, got {:?}", block.expr),
3932 }
3933 }
3934 _ => panic!("expected Block"),
3935 },
3936 _ => panic!("expected Function"),
3937 }
3938 }
3939
3940 #[test]
3941 fn test_field_access_block_without_semicolon_is_error() {
3942 let result = parse("fn main() -> i32 { x.field { 1 } }");
3945 assert!(
3946 result.is_err(),
3947 "field + block without semicolon should be syntax error"
3948 );
3949 }
3950
3951 #[test]
3952 fn test_chained_qualified_struct_literal() {
3953 let result = parse_expr("a.b.Point { x: 1 }").unwrap();
3955 match &result.expr {
3956 Expr::StructLit(lit) => {
3957 assert!(lit.base.is_some());
3959 match lit.base.as_ref().unwrap().as_ref() {
3960 Expr::Field(field) => {
3961 assert_eq!(result.get(field.field.name), "b");
3962 match field.base.as_ref() {
3963 Expr::Ident(ident) => assert_eq!(result.get(ident.name), "a"),
3964 _ => panic!("inner base should be Ident"),
3965 }
3966 }
3967 _ => panic!("base should be Field, got {:?}", lit.base),
3968 }
3969 assert_eq!(result.get(lit.name.name), "Point");
3970 }
3971 _ => panic!("expected StructLit, got {:?}", result.expr),
3972 }
3973 }
3974
3975 #[test]
3978 fn test_anon_struct_with_fields_only() {
3979 let result = parse("fn make_type() -> type { struct { x: i32, y: i32 } }").unwrap();
3981 match &result.ast.items[0] {
3982 Item::Function(f) => {
3983 assert_eq!(result.get(f.name.name), "make_type");
3984 match &f.body {
3985 Expr::Block(block) => match block.expr.as_ref() {
3986 Expr::TypeLit(type_lit) => match &type_lit.type_expr {
3987 TypeExpr::AnonymousStruct {
3988 fields, methods, ..
3989 } => {
3990 assert_eq!(fields.len(), 2);
3991 assert_eq!(result.get(fields[0].name.name), "x");
3992 assert_eq!(result.get(fields[1].name.name), "y");
3993 assert!(methods.is_empty());
3994 }
3995 _ => panic!("expected AnonymousStruct"),
3996 },
3997 _ => panic!("expected TypeLit"),
3998 },
3999 _ => panic!("expected Block"),
4000 }
4001 }
4002 _ => panic!("expected Function"),
4003 }
4004 }
4005
4006 #[test]
4007 fn test_anon_struct_with_method() {
4008 let result =
4010 parse("fn make_type() -> type { struct { x: i32, fn get_x(self) -> i32 { self.x } } }")
4011 .unwrap();
4012 match &result.ast.items[0] {
4013 Item::Function(f) => match &f.body {
4014 Expr::Block(block) => match block.expr.as_ref() {
4015 Expr::TypeLit(type_lit) => match &type_lit.type_expr {
4016 TypeExpr::AnonymousStruct {
4017 fields, methods, ..
4018 } => {
4019 assert_eq!(fields.len(), 1);
4020 assert_eq!(result.get(fields[0].name.name), "x");
4021 assert_eq!(methods.len(), 1);
4022 assert_eq!(result.get(methods[0].name.name), "get_x");
4023 assert!(
4024 methods[0].receiver.is_some(),
4025 "method should have self receiver"
4026 );
4027 }
4028 _ => panic!("expected AnonymousStruct"),
4029 },
4030 _ => panic!("expected TypeLit"),
4031 },
4032 _ => panic!("expected Block"),
4033 },
4034 _ => panic!("expected Function"),
4035 }
4036 }
4037
4038 #[test]
4039 fn test_anon_struct_with_associated_function() {
4040 let result = parse(
4042 "fn make_type() -> type { struct { x: i32, fn new() -> Self { Self { x: 0 } } } }",
4043 )
4044 .unwrap();
4045 match &result.ast.items[0] {
4046 Item::Function(f) => match &f.body {
4047 Expr::Block(block) => match block.expr.as_ref() {
4048 Expr::TypeLit(type_lit) => match &type_lit.type_expr {
4049 TypeExpr::AnonymousStruct {
4050 fields, methods, ..
4051 } => {
4052 assert_eq!(fields.len(), 1);
4053 assert_eq!(methods.len(), 1);
4054 assert_eq!(result.get(methods[0].name.name), "new");
4055 assert!(
4056 methods[0].receiver.is_none(),
4057 "associated function should not have self"
4058 );
4059 match &methods[0].return_type {
4061 Some(TypeExpr::Named(ident)) => {
4062 assert_eq!(result.get(ident.name), "Self");
4063 }
4064 _ => panic!("expected Self return type"),
4065 }
4066 }
4067 _ => panic!("expected AnonymousStruct"),
4068 },
4069 _ => panic!("expected TypeLit"),
4070 },
4071 _ => panic!("expected Block"),
4072 },
4073 _ => panic!("expected Function"),
4074 }
4075 }
4076
4077 #[test]
4078 fn test_anon_struct_with_multiple_methods() {
4079 let result = parse(
4081 r#"
4082 fn make_type() -> type {
4083 struct {
4084 value: i32,
4085 fn get(self) -> i32 { self.value }
4086 fn set(self, v: i32) -> Self { Self { value: v } }
4087 }
4088 }
4089 "#,
4090 )
4091 .unwrap();
4092 match &result.ast.items[0] {
4093 Item::Function(f) => match &f.body {
4094 Expr::Block(block) => match block.expr.as_ref() {
4095 Expr::TypeLit(type_lit) => match &type_lit.type_expr {
4096 TypeExpr::AnonymousStruct {
4097 fields, methods, ..
4098 } => {
4099 assert_eq!(fields.len(), 1);
4100 assert_eq!(result.get(fields[0].name.name), "value");
4101 assert_eq!(methods.len(), 2);
4102 assert_eq!(result.get(methods[0].name.name), "get");
4103 assert_eq!(result.get(methods[1].name.name), "set");
4104 assert_eq!(methods[1].params.len(), 1);
4106 assert_eq!(result.get(methods[1].params[0].name.name), "v");
4107 }
4108 _ => panic!("expected AnonymousStruct"),
4109 },
4110 _ => panic!("expected TypeLit"),
4111 },
4112 _ => panic!("expected Block"),
4113 },
4114 _ => panic!("expected Function"),
4115 }
4116 }
4117
4118 #[test]
4119 fn test_anon_struct_methods_only() {
4120 let result =
4122 parse("fn make_type() -> type { struct { fn new() -> Self { Self { } } } }").unwrap();
4123 match &result.ast.items[0] {
4124 Item::Function(f) => match &f.body {
4125 Expr::Block(block) => match block.expr.as_ref() {
4126 Expr::TypeLit(type_lit) => match &type_lit.type_expr {
4127 TypeExpr::AnonymousStruct {
4128 fields, methods, ..
4129 } => {
4130 assert!(fields.is_empty());
4131 assert_eq!(methods.len(), 1);
4132 assert_eq!(result.get(methods[0].name.name), "new");
4133 }
4134 _ => panic!("expected AnonymousStruct"),
4135 },
4136 _ => panic!("expected TypeLit"),
4137 },
4138 _ => panic!("expected Block"),
4139 },
4140 _ => panic!("expected Function"),
4141 }
4142 }
4143
4144 #[test]
4145 fn test_self_type_in_return() {
4146 let result =
4148 parse("fn make_type() -> type { struct { x: i32, fn clone(self) -> Self { self } } }")
4149 .unwrap();
4150 match &result.ast.items[0] {
4151 Item::Function(f) => match &f.body {
4152 Expr::Block(block) => match block.expr.as_ref() {
4153 Expr::TypeLit(type_lit) => match &type_lit.type_expr {
4154 TypeExpr::AnonymousStruct { methods, .. } => {
4155 match &methods[0].return_type {
4156 Some(TypeExpr::Named(ident)) => {
4157 assert_eq!(result.get(ident.name), "Self");
4158 }
4159 _ => panic!("expected Self return type"),
4160 }
4161 }
4162 _ => panic!("expected AnonymousStruct"),
4163 },
4164 _ => panic!("expected TypeLit"),
4165 },
4166 _ => panic!("expected Block"),
4167 },
4168 _ => panic!("expected Function"),
4169 }
4170 }
4171
4172 #[test]
4173 fn test_self_type_in_param() {
4174 let result = parse(
4176 "fn make_type() -> type { struct { fn combine(self, other: Self) -> Self { self } } }",
4177 )
4178 .unwrap();
4179 match &result.ast.items[0] {
4180 Item::Function(f) => match &f.body {
4181 Expr::Block(block) => match block.expr.as_ref() {
4182 Expr::TypeLit(type_lit) => match &type_lit.type_expr {
4183 TypeExpr::AnonymousStruct { methods, .. } => {
4184 let param = &methods[0].params[0];
4186 match ¶m.ty {
4187 TypeExpr::Named(ident) => {
4188 assert_eq!(result.get(ident.name), "Self");
4189 }
4190 _ => panic!("expected Self param type"),
4191 }
4192 }
4193 _ => panic!("expected AnonymousStruct"),
4194 },
4195 _ => panic!("expected TypeLit"),
4196 },
4197 _ => panic!("expected Block"),
4198 },
4199 _ => panic!("expected Function"),
4200 }
4201 }
4202
4203 #[test]
4204 fn test_self_type_standalone() {
4205 let result = parse("struct Foo { x: i32, fn clone(self) -> Self { self } }").unwrap();
4208 match &result.ast.items[0] {
4209 Item::Struct(struct_decl) => {
4210 let method = &struct_decl.methods[0];
4211 match &method.return_type {
4212 Some(TypeExpr::Named(ident)) => {
4213 assert_eq!(result.get(ident.name), "Self");
4214 }
4215 _ => panic!("expected Self return type"),
4216 }
4217 }
4218 _ => panic!("expected Struct"),
4219 }
4220 }
4221}