spade_parser/
expression.rs

1use num::ToPrimitive;
2use spade_ast::{
3    ArgumentList, BinaryOperator, Block, CallKind, Expression, IntLiteral, UnaryOperator,
4};
5use spade_common::location_info::{Loc, WithLocation};
6use spade_diagnostics::diag_list::ResultExt;
7use spade_diagnostics::Diagnostic;
8use spade_macros::trace_parser;
9
10use crate::error::{CSErrorTransformations, ExpectedArgumentList, Result, UnexpectedToken};
11use crate::item_type::UnitKindLocal;
12use crate::{lexer::TokenKind, ParseStackEntry, Parser};
13
14#[derive(PartialEq, PartialOrd, Eq, Ord)]
15enum OpBindingPower {
16    None,
17    LogicalOr,
18    LogicalAnd,
19    LogicalXor,
20    Equality,
21    RelationalCmp,
22    BitwiseOr,
23    BitwiseXor,
24    BitwiseAnd,
25    Shift,
26    AddLike,
27    MulLike,
28    // Unary operator appearing before the expression it applies to such as
29    // - and !
30    PrefixUnary,
31}
32
33fn binop_binding_power(op: &BinaryOperator) -> OpBindingPower {
34    match op {
35        BinaryOperator::Add => OpBindingPower::AddLike,
36        BinaryOperator::Sub => OpBindingPower::AddLike,
37        BinaryOperator::Mul => OpBindingPower::MulLike,
38        BinaryOperator::Div => OpBindingPower::MulLike,
39        BinaryOperator::Mod => OpBindingPower::MulLike,
40        BinaryOperator::Equals => OpBindingPower::Equality,
41        BinaryOperator::NotEquals => OpBindingPower::Equality,
42        BinaryOperator::Lt => OpBindingPower::RelationalCmp,
43        BinaryOperator::Gt => OpBindingPower::RelationalCmp,
44        BinaryOperator::Le => OpBindingPower::RelationalCmp,
45        BinaryOperator::Ge => OpBindingPower::RelationalCmp,
46        BinaryOperator::LogicalAnd => OpBindingPower::LogicalAnd,
47        BinaryOperator::LogicalOr => OpBindingPower::LogicalOr,
48        BinaryOperator::LogicalXor => OpBindingPower::LogicalXor,
49        BinaryOperator::LeftShift => OpBindingPower::Shift,
50        BinaryOperator::RightShift => OpBindingPower::Shift,
51        BinaryOperator::ArithmeticRightShift => OpBindingPower::Shift,
52        BinaryOperator::BitwiseAnd => OpBindingPower::BitwiseAnd,
53        BinaryOperator::BitwiseOr => OpBindingPower::BitwiseOr,
54        BinaryOperator::BitwiseXor => OpBindingPower::BitwiseXor,
55    }
56}
57
58fn unop_binding_power(op: &UnaryOperator) -> OpBindingPower {
59    match op {
60        UnaryOperator::Sub => OpBindingPower::PrefixUnary,
61        UnaryOperator::Not => OpBindingPower::PrefixUnary,
62        UnaryOperator::BitwiseNot => OpBindingPower::PrefixUnary,
63        UnaryOperator::Dereference => OpBindingPower::PrefixUnary,
64        UnaryOperator::Reference => OpBindingPower::PrefixUnary,
65    }
66}
67
68impl<'a> Parser<'a> {
69    fn binop_from_kind(kind: &TokenKind) -> Option<BinaryOperator> {
70        match kind {
71            TokenKind::Plus => Some(BinaryOperator::Add),
72            TokenKind::Minus => Some(BinaryOperator::Sub),
73            TokenKind::Asterisk => Some(BinaryOperator::Mul),
74            TokenKind::Slash => Some(BinaryOperator::Div),
75            TokenKind::Percentage => Some(BinaryOperator::Mod),
76            TokenKind::Equals => Some(BinaryOperator::Equals),
77            TokenKind::NotEquals => Some(BinaryOperator::NotEquals),
78            // We have to handle left and right shifts separately because otherwise
79            // their parsing interferes with generic arguments
80            TokenKind::Lt => Some(BinaryOperator::Lt),
81            TokenKind::Gt => Some(BinaryOperator::Gt),
82            TokenKind::Le => Some(BinaryOperator::Le),
83            TokenKind::Ge => Some(BinaryOperator::Ge),
84            TokenKind::RightShift => Some(BinaryOperator::RightShift),
85            TokenKind::ArithmeticRightShift => Some(BinaryOperator::ArithmeticRightShift),
86            TokenKind::LeftShift => Some(BinaryOperator::LeftShift),
87            TokenKind::DoublePipe => Some(BinaryOperator::LogicalOr),
88            TokenKind::LogicalAnd => Some(BinaryOperator::LogicalAnd),
89            TokenKind::LogicalXor => Some(BinaryOperator::LogicalXor),
90            TokenKind::Ampersand => Some(BinaryOperator::BitwiseAnd),
91            TokenKind::Pipe => Some(BinaryOperator::BitwiseOr),
92            TokenKind::BitwiseXor => Some(BinaryOperator::BitwiseXor),
93            _ => None,
94        }
95    }
96
97    fn unop_from_kind(kind: &TokenKind) -> Option<UnaryOperator> {
98        match kind {
99            TokenKind::Minus => Some(UnaryOperator::Sub),
100            TokenKind::Not => Some(UnaryOperator::Not),
101            TokenKind::Tilde => Some(UnaryOperator::BitwiseNot),
102            TokenKind::Ampersand => Some(UnaryOperator::Reference),
103            TokenKind::Asterisk => Some(UnaryOperator::Dereference),
104            _ => None,
105        }
106    }
107
108    #[tracing::instrument(skip(self))]
109    pub fn expression(&mut self) -> Result<Loc<Expression>> {
110        self.non_comptime_expression()
111    }
112
113    /// We need a function like this in order to not run into parser conflicts when
114    /// parsing blocks, since both statements and expressions can start with $if.
115    #[tracing::instrument(skip(self))]
116    pub fn non_comptime_expression(&mut self) -> Result<Loc<Expression>> {
117        self.custom_infix_operator()
118    }
119
120    fn custom_infix_operator(&mut self) -> Result<Loc<Expression>> {
121        let lhs_val = self.expr_bp(OpBindingPower::None)?;
122
123        if self.peek_kind(&TokenKind::InfixOperatorSeparator)? {
124            let (Some((callee, turbofish)), _) = self.surrounded(
125                &TokenKind::InfixOperatorSeparator,
126                Self::path_with_turbofish,
127                &TokenKind::InfixOperatorSeparator,
128            )?
129            else {
130                return Err(Diagnostic::from(UnexpectedToken {
131                    got: self.peek()?,
132                    expected: vec!["Identifier"],
133                }));
134            };
135
136            let rhs_val = self.custom_infix_operator()?;
137
138            Ok(Expression::Call {
139                kind: CallKind::Function,
140                callee,
141                args: ArgumentList::Positional(vec![lhs_val.clone(), rhs_val.clone()]).between(
142                    self.file_id,
143                    &lhs_val,
144                    &rhs_val,
145                ),
146                turbofish,
147            }
148            .between(self.file_id, &lhs_val, &rhs_val))
149        } else {
150            Ok(lhs_val)
151        }
152    }
153
154    /// If `op` is a subtraction, and `rhs` is an integer literal, construct a negative integer literal instead.
155    fn inline_negative_literal(
156        &self,
157        op: Loc<UnaryOperator>,
158        rhs: Loc<Expression>,
159    ) -> Result<Loc<Expression>> {
160        let (op, op_loc) = op.split_loc();
161        let (rhs, rhs_loc) = rhs.split_loc();
162        let expr_loc = ().between_locs(&op_loc, &rhs_loc);
163        let expr: Result<Expression> = match (op, rhs) {
164            (UnaryOperator::Sub, Expression::IntLiteral(int)) => {
165                let int_literal = match &int.inner {
166                    IntLiteral::Unsized(val) => Ok(IntLiteral::Unsized(-val)),
167                    IntLiteral::Signed { val, size } => Ok(IntLiteral::Signed {
168                        val: -val,
169                        size: size.clone(),
170                    }),
171                    IntLiteral::Unsigned { val, size } => Err(Diagnostic::error(
172                        expr_loc,
173                        "Cannot apply unary minus to unsigned integer literal",
174                    )
175                    .help("Only signed integers can have negative values")
176                    .span_suggest_replace(
177                        "Try making the integer signed",
178                        expr_loc,
179                        format!("-{val}i{size}"),
180                    )),
181                }?;
182                Ok(Expression::IntLiteral(int_literal.at_loc(&int)))
183            }
184            (op, rhs) => Ok(Expression::UnaryOperator(
185                op.at_loc(&op_loc),
186                Box::new(rhs.at_loc(&rhs_loc)),
187            )),
188        };
189        Ok(expr?.at_loc(&expr_loc))
190    }
191
192    // Based on matklads blog post on pratt parsing:
193    // https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
194    fn expr_bp(&mut self, min_power: OpBindingPower) -> Result<Loc<Expression>> {
195        let next_tok = self.peek()?;
196        let mut lhs = if let Some((tok, op)) =
197            Self::unop_from_kind(&next_tok.kind).map(|op| (next_tok, op))
198        {
199            self.eat_unconditional()?;
200            let op_power = unop_binding_power(&op);
201            let rhs = self.expr_bp(op_power)?;
202            self.inline_negative_literal(op.at_loc(&tok.loc()), rhs)?
203        } else {
204            self.base_expression()?
205        };
206
207        while let Some(op) = Self::binop_from_kind(&self.peek()?.kind) {
208            let op_power = binop_binding_power(&op);
209
210            if op_power <= min_power {
211                break;
212            }
213
214            let op_tok = self.eat_unconditional()?;
215
216            let rhs = self.expr_bp(op_power)?;
217            lhs = Expression::BinaryOperator(
218                Box::new(lhs.clone()),
219                op.at(self.file_id, &op_tok),
220                Box::new(rhs.clone()),
221            )
222            .between(self.file_id, &lhs, &rhs)
223        }
224
225        Ok(lhs)
226    }
227
228    // Expression parsing
229
230    #[trace_parser]
231    fn base_expression(&mut self) -> Result<Loc<Expression>> {
232        let expr = if let Some(tuple) = self.tuple_literal()? {
233            Ok(tuple)
234        } else if let Some(lambda) = self.lambda()? {
235            Ok(lambda)
236        } else if let Some(array) = self.array_literal()? {
237            Ok(array)
238        } else if let Some(instance) = self.entity_instance()? {
239            Ok(instance)
240        } else if let Some(val) = self.bool_literal()? {
241            Ok(Expression::BoolLiteral(val).at_loc(&val))
242        } else if let Some(val) = self.str_literal()? {
243            Ok(Expression::StrLiteral(val.clone()).at_loc(&val))
244        } else if let Some(val) = self.tri_literal()? {
245            Ok(Expression::TriLiteral(val.clone()).at_loc(&val))
246        } else if let Some(val) = self.int_literal()? {
247            Ok(Expression::IntLiteral(val.clone()).at_loc(&val))
248        } else if let Some(block) = self.block(false)? {
249            Ok(block.map(Box::new).map(Expression::Block))
250        } else if let Some(if_expr) = self.if_expression(false)? {
251            Ok(if_expr)
252        } else if let Some(if_expr) = self.type_level_if()? {
253            Ok(if_expr)
254        } else if let Some(match_expr) = self.match_expression()? {
255            Ok(match_expr)
256        } else if let Some(stageref) = self.pipeline_reference()? {
257            Ok(stageref)
258        } else if let Some(unsafe_expr) = self.unsafe_block()? {
259            Ok(unsafe_expr)
260        } else if let Some(create_ports) = self.peek_and_eat(&TokenKind::Port)? {
261            Ok(Expression::CreatePorts.at(self.file_id, &create_ports))
262        } else if let Some((path, turbofish)) = self.path_with_turbofish()? {
263            let span = path.span;
264            match (turbofish, self.argument_list()?) {
265                (None, None) => Ok(Expression::Identifier(path).at(self.file_id, &span)),
266                (Some(tf), None) => {
267                    return Err(Diagnostic::error(self.peek()?, "Expected argument list")
268                        .primary_label("Expected argument list")
269                        .secondary_label(
270                            tf,
271                            "Type parameters can only be specified on function calls",
272                        ))
273                }
274                (tf, Some(args)) => {
275                    // Doing this avoids cloning result and args
276                    let span = ().between(self.file_id, &path, &args);
277
278                    Ok(Expression::Call {
279                        kind: CallKind::Function,
280                        callee: path,
281                        args,
282                        turbofish: tf,
283                    }
284                    .at_loc(&span))
285                }
286            }
287        } else {
288            let got = self.peek()?;
289            Err(Diagnostic::error(
290                got.loc(),
291                format!("Unexpected `{}`, expected expression", got.kind.as_str()),
292            )
293            .primary_label("expected expression here"))
294        }?;
295
296        self.expression_suffix(expr)
297    }
298
299    #[trace_parser]
300    fn lambda(&mut self) -> Result<Option<Loc<Expression>>> {
301        let start_token = self.peek()?;
302        let Some(unit_kind) = self.unit_kind(&start_token)? else {
303            return Ok(None);
304        };
305
306        let (args, args_loc) = match self.peek_and_eat(&TokenKind::DoublePipe)? {
307            Some(thing) => (vec![], thing.loc()),
308            None => self.surrounded(
309                &TokenKind::Pipe,
310                |s| {
311                    let args = s
312                        .comma_separated(|s| s.pattern(), &TokenKind::Pipe)
313                        .no_context()?;
314
315                    Ok(args)
316                },
317                &TokenKind::Pipe,
318            )?,
319        };
320
321        let args = args.at_loc(&args_loc);
322
323        let body = if self.peek_kind(&TokenKind::OpenBrace)? {
324            // It is safe to unwrap the value, as it can only be `None` if
325            // there is no opening brace but it is guaranteed by the `if`
326            // condition.
327            self.block(unit_kind.is_pipeline())?.unwrap()
328        } else {
329            let expr = self.expression().map_err(|diag| {
330                diag.primary_label("expected lambda body here")
331                    .span_suggest_insert_after(
332                        "you might have meant to place the body there",
333                        args_loc,
334                        "{ /* ... */ }",
335                    )
336            })?;
337
338            let loc = expr.loc();
339
340            let block = Block {
341                statements: vec![],
342                result: Some(expr),
343            };
344
345            block.at_loc(&loc)
346        };
347
348        let loc = ().between(self.file_id, &start_token, &body);
349
350        Ok(Some(
351            Expression::Lambda {
352                unit_kind,
353                args,
354                body: Box::new(body),
355            }
356            .at_loc(&loc),
357        ))
358    }
359
360    #[trace_parser]
361    fn expression_suffix(&mut self, expr: Loc<Expression>) -> Result<Loc<Expression>> {
362        let base = if let Some(hash) = self.peek_and_eat(&TokenKind::Hash)? {
363            if let Some(index) = self.int_literal()? {
364                let index = index
365                    .try_map_ref(|idx| -> Result<u128> {
366                        let as_u128 = idx
367                            .clone()
368                            .as_unsigned()
369                            .ok_or_else(|| {
370                                Diagnostic::error(&index, "Tuple indices must be non-negative")
371                                    .primary_label("Negative tuple index")
372                            })?
373                            .to_u128()
374                            .ok_or_else(|| {
375                                Diagnostic::bug(&index, "Tuple index too large")
376                                    .primary_label("Tuple index too large")
377                                    .note(format!("Tuple index can be at most {}", u128::MAX))
378                            })?;
379
380                        Ok(as_u128)
381                    })?
382                    .between(self.file_id, &hash, &index);
383                Ok(
384                    Expression::TupleIndex(Box::new(expr.clone()), *index).between(
385                        self.file_id,
386                        &expr,
387                        &index,
388                    ),
389                )
390            } else {
391                Err(
392                    Diagnostic::error(self.peek()?.loc(), "expected an index after #")
393                        .primary_label("expected index here"),
394                )
395            }
396        } else if self.peek_and_eat(&TokenKind::Dot)?.is_some() {
397            let inst = self.peek_and_eat(&TokenKind::Instance)?;
398
399            if let Some(inst) = &inst {
400                self.unit_context
401                    .allows_inst(().at(self.file_id, inst))
402                    .handle_in(&mut self.diags);
403            }
404
405            // Check if this is a pipeline or not
406            let pipeline_depth = if inst.is_some() {
407                if self.peek_kind(&TokenKind::OpenParen)? {
408                    Some(self.surrounded(
409                        &TokenKind::OpenParen,
410                        |s| s.type_expression(),
411                        &TokenKind::CloseParen,
412                    )?)
413                } else {
414                    None
415                }
416            } else {
417                None
418            };
419
420            let field = self.identifier()?;
421
422            let turbofish = self.turbofish()?;
423
424            if let Some(args) = self.argument_list()? {
425                Ok(Expression::MethodCall {
426                    target: Box::new(expr.clone()),
427                    name: field.clone(),
428                    args: args.clone(),
429                    kind: pipeline_depth
430                        .map(|(depth, _)| {
431                            CallKind::Pipeline(().at(self.file_id, &inst.clone().unwrap()), depth)
432                        })
433                        .or_else(|| inst.map(|i| CallKind::Entity(().at(self.file_id, &i))))
434                        .unwrap_or(CallKind::Function),
435                    turbofish,
436                }
437                .between(self.file_id, &expr, &args))
438            } else if let Some(inst_keyword) = inst {
439                let base_loc = ().between(self.file_id, &inst_keyword, &field);
440                let base_expr = if let Some(turbofish) = turbofish {
441                    ().between_locs(&base_loc, &turbofish)
442                } else {
443                    base_loc
444                };
445                Err(ExpectedArgumentList {
446                    next_token: self.peek()?,
447                    base_expr,
448                }
449                .with_suggestions())
450            } else if let Some(turbofish) = turbofish {
451                Err(ExpectedArgumentList {
452                    next_token: self.peek()?,
453                    base_expr: ().between(self.file_id, &turbofish, &field),
454                }
455                .with_suggestions())
456            } else {
457                Ok(
458                    Expression::FieldAccess(Box::new(expr.clone()), field.clone()).between(
459                        self.file_id,
460                        &expr,
461                        &field,
462                    ),
463                )
464            }
465        } else if self.peek_kind(&TokenKind::OpenBracket)? {
466            let (inner_expr, loc) = self.surrounded(
467                &TokenKind::OpenBracket,
468                |s| {
469                    // `start` is parsed as an expression since at this point we are parsing either
470                    //
471                    // - an array index (`a[2]`) which allows an expression (`a[2+offset]`)
472                    // - a range index (`a[1..2]`) which does not allow an expression
473                    let start = s.expression()?;
474
475                    if let Some(_) = s.peek_and_eat(&TokenKind::DotDot)? {
476                        // double dot => range index: `[1..2]`
477                        let end = s.expression()?;
478                        Ok(Expression::RangeIndex {
479                            target: Box::new(expr.clone()),
480                            start: Box::new(start),
481                            end: Box::new(end),
482                        })
483                    } else {
484                        Ok(Expression::Index(Box::new(expr.clone()), Box::new(start)))
485                    }
486                },
487                &TokenKind::CloseBracket,
488            )?;
489
490            Ok(inner_expr.between_locs(&expr, &loc))
491        } else {
492            return Ok(expr);
493        }?;
494
495        self.expression_suffix(base)
496    }
497}
498
499#[cfg(test)]
500mod test {
501    use spade_ast::testutil::{ast_ident, ast_path};
502    use spade_ast::*;
503
504    use super::*;
505    use crate::lexer::TokenKind;
506    use crate::{check_parse, format_parse_stack};
507
508    use colored::Colorize;
509    use logos::Logos;
510
511    use spade_common::location_info::WithLocation;
512
513    #[test]
514    fn addition_operatoins_are_expressions() {
515        let expected_value = Expression::BinaryOperator(
516            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
517            BinaryOperator::Add.nowhere(),
518            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
519        )
520        .nowhere();
521
522        check_parse!("a + b", expression, Ok(expected_value));
523    }
524
525    #[test]
526    fn unary_suptraction_works() {
527        let expected_value = Expression::UnaryOperator(
528            UnaryOperator::Sub.nowhere(),
529            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
530        )
531        .nowhere();
532
533        check_parse!("- b", expression, Ok(expected_value));
534    }
535
536    #[test]
537    fn not_operator_works() {
538        let expected_value = Expression::UnaryOperator(
539            UnaryOperator::Not.nowhere(),
540            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
541        )
542        .nowhere();
543
544        check_parse!("!b", expression, Ok(expected_value));
545    }
546
547    #[test]
548    fn bitwise_and_operatoins_are_expressions() {
549        let expected_value = Expression::BinaryOperator(
550            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
551            BinaryOperator::BitwiseAnd.nowhere(),
552            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
553        )
554        .nowhere();
555
556        check_parse!("a & b", expression, Ok(expected_value));
557    }
558
559    #[test]
560    fn bitwise_or_operatoins_are_expressions() {
561        let expected_value = Expression::BinaryOperator(
562            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
563            BinaryOperator::BitwiseOr.nowhere(),
564            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
565        )
566        .nowhere();
567
568        check_parse!("a | b", expression, Ok(expected_value));
569    }
570
571    #[test]
572    fn multiplications_are_expressions() {
573        let expected_value = Expression::BinaryOperator(
574            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
575            BinaryOperator::Mul.nowhere(),
576            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
577        )
578        .nowhere();
579
580        check_parse!("a * b", expression, Ok(expected_value));
581    }
582
583    #[test]
584    fn multiplication_before_addition() {
585        let expected_value = Expression::BinaryOperator(
586            Box::new(
587                Expression::BinaryOperator(
588                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
589                    BinaryOperator::Mul.nowhere(),
590                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
591                )
592                .nowhere(),
593            ),
594            BinaryOperator::Add.nowhere(),
595            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
596        )
597        .nowhere();
598
599        check_parse!("a*b + c", expression, Ok(expected_value));
600    }
601
602    #[test]
603    fn equals_after_addition() {
604        let expected_value = Expression::BinaryOperator(
605            Box::new(
606                Expression::BinaryOperator(
607                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
608                    BinaryOperator::Add.nowhere(),
609                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
610                )
611                .nowhere(),
612            ),
613            BinaryOperator::Equals.nowhere(),
614            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
615        )
616        .nowhere();
617
618        check_parse!("a+b == c", expression, Ok(expected_value));
619    }
620
621    #[test]
622    fn and_after_equals() {
623        {
624            let expected_value = Expression::BinaryOperator(
625                Box::new(
626                    Expression::BinaryOperator(
627                        Box::new(Expression::Identifier(ast_path("a")).nowhere()),
628                        BinaryOperator::Equals.nowhere(),
629                        Box::new(Expression::Identifier(ast_path("b")).nowhere()),
630                    )
631                    .nowhere(),
632                ),
633                BinaryOperator::LogicalAnd.nowhere(),
634                Box::new(Expression::Identifier(ast_path("c")).nowhere()),
635            )
636            .nowhere();
637
638            check_parse!("a == b && c", expression, Ok(expected_value));
639        }
640        {
641            let expected_value = Expression::BinaryOperator(
642                Box::new(Expression::Identifier(ast_path("a")).nowhere()),
643                BinaryOperator::LogicalAnd.nowhere(),
644                Box::new(
645                    Expression::BinaryOperator(
646                        Box::new(Expression::Identifier(ast_path("b")).nowhere()),
647                        BinaryOperator::Equals.nowhere(),
648                        Box::new(Expression::Identifier(ast_path("c")).nowhere()),
649                    )
650                    .nowhere(),
651                ),
652            )
653            .nowhere();
654
655            check_parse!("a && b == c", expression, Ok(expected_value));
656        }
657    }
658
659    #[test]
660    fn bracketed_expressions_are_expressions() {
661        let expected_value = Expression::BinaryOperator(
662            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
663            BinaryOperator::Add.nowhere(),
664            Box::new(
665                Expression::Parenthesized(Box::new(
666                    Expression::BinaryOperator(
667                        Box::new(Expression::Identifier(ast_path("b")).nowhere()),
668                        BinaryOperator::Add.nowhere(),
669                        Box::new(Expression::Identifier(ast_path("c")).nowhere()),
670                    )
671                    .nowhere(),
672                ))
673                .nowhere(),
674            ),
675        )
676        .nowhere();
677
678        check_parse!("a + (b + c)", expression, Ok(expected_value));
679    }
680
681    #[test]
682    fn repeated_bracketed_expressions_work() {
683        let expected_value = Expression::Parenthesized(Box::new(
684            Expression::BinaryOperator(
685                Box::new(
686                    Expression::Parenthesized(Box::new(
687                        Expression::BinaryOperator(
688                            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
689                            BinaryOperator::Add.nowhere(),
690                            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
691                        )
692                        .nowhere(),
693                    ))
694                    .nowhere(),
695                ),
696                BinaryOperator::Add.nowhere(),
697                Box::new(Expression::Identifier(ast_path("a")).nowhere()),
698            )
699            .nowhere(),
700        ))
701        .nowhere();
702
703        check_parse!("((b + c) + a)", expression, Ok(expected_value));
704    }
705
706    #[test]
707    fn functions_work() {
708        let code = "test(1, 2)";
709
710        let expected = Expression::Call {
711            kind: CallKind::Function,
712            callee: ast_path("test"),
713            args: ArgumentList::Positional(vec![
714                Expression::int_literal_signed(1).nowhere(),
715                Expression::int_literal_signed(2).nowhere(),
716            ])
717            .nowhere(),
718            turbofish: None,
719        }
720        .nowhere();
721
722        check_parse!(code, expression, Ok(expected));
723    }
724
725    #[test]
726    fn functions_with_named_arguments_work() {
727        let code = "test$(a, b)";
728
729        let expected = Expression::Call {
730            kind: CallKind::Function,
731            callee: ast_path("test"),
732            args: ArgumentList::Named(vec![
733                NamedArgument::Short(ast_ident("a")),
734                NamedArgument::Short(ast_ident("b")),
735            ])
736            .nowhere(),
737            turbofish: None,
738        }
739        .nowhere();
740
741        check_parse!(code, expression, Ok(expected));
742    }
743
744    #[test]
745    fn tuple_literals_parse() {
746        let code = "(1, true)";
747
748        let expected = Expression::TupleLiteral(vec![
749            Expression::int_literal_signed(1).nowhere(),
750            Expression::bool_literal(true).nowhere(),
751        ])
752        .nowhere();
753
754        check_parse!(code, expression, Ok(expected));
755    }
756
757    #[test]
758    fn array_literals_parse() {
759        let code = "[1, 2, 3]";
760
761        let expected = Expression::ArrayLiteral(vec![
762            Expression::int_literal_signed(1).nowhere(),
763            Expression::int_literal_signed(2).nowhere(),
764            Expression::int_literal_signed(3).nowhere(),
765        ])
766        .nowhere();
767
768        check_parse!(code, expression, Ok(expected));
769    }
770
771    #[test]
772    fn array_indexing_works() {
773        let code = "a[0]";
774
775        let expected = Expression::Index(
776            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
777            Box::new(Expression::int_literal_signed(0).nowhere()),
778        )
779        .nowhere();
780
781        check_parse!(code, expression, Ok(expected));
782    }
783
784    #[test]
785    fn tuple_indexing_parsese() {
786        let code = "a#0";
787
788        let expected = Expression::TupleIndex(
789            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
790            Loc::new(0, ().nowhere().span, 0),
791        )
792        .nowhere();
793
794        check_parse!(code, expression, Ok(expected));
795    }
796
797    #[test]
798    fn field_access_parses() {
799        let code = "a.b";
800        let expected = Expression::FieldAccess(
801            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
802            ast_ident("b"),
803        )
804        .nowhere();
805
806        check_parse!(code, expression, Ok(expected));
807    }
808
809    #[test]
810    fn method_call_parses() {
811        let code = "a.b(x)";
812
813        let expected = Expression::MethodCall {
814            target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
815            name: ast_ident("b"),
816            args: ArgumentList::Positional(vec![Expression::Identifier(ast_path("x")).nowhere()])
817                .nowhere(),
818            kind: CallKind::Function,
819            turbofish: None,
820        }
821        .nowhere();
822
823        check_parse!(code, expression, Ok(expected));
824    }
825
826    #[test]
827    fn inst_method_call_parses() {
828        let code = "a.inst b(x)";
829
830        let expected = Expression::MethodCall {
831            target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
832            name: ast_ident("b"),
833            args: ArgumentList::Positional(vec![Expression::Identifier(ast_path("x")).nowhere()])
834                .nowhere(),
835            kind: CallKind::Entity(().nowhere()),
836            turbofish: None,
837        }
838        .nowhere();
839
840        check_parse!(code, expression, Ok(expected));
841    }
842
843    #[test]
844    fn method_call_with_named_args_works() {
845        let code = "a.b$(x: y)";
846
847        let expected = Expression::MethodCall {
848            target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
849            name: ast_ident("b"),
850            args: ArgumentList::Named(vec![NamedArgument::Full(
851                ast_ident("x"),
852                Expression::Identifier(ast_path("y")).nowhere(),
853            )])
854            .nowhere(),
855            kind: CallKind::Function,
856            turbofish: None,
857        }
858        .nowhere();
859
860        check_parse!(code, expression, Ok(expected));
861    }
862
863    #[test]
864    fn if_expressions_work() {
865        let code = r#"
866        if a {b} else {c}
867        "#;
868
869        let expected = Expression::If(
870            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
871            Box::new(
872                Expression::Block(Box::new(Block {
873                    statements: vec![],
874                    result: Some(Expression::Identifier(ast_path("b")).nowhere()),
875                }))
876                .nowhere(),
877            ),
878            Box::new(
879                Expression::Block(Box::new(Block {
880                    statements: vec![],
881                    result: Some(Expression::Identifier(ast_path("c")).nowhere()),
882                }))
883                .nowhere(),
884            ),
885        )
886        .nowhere();
887
888        check_parse!(code, expression, Ok(expected));
889    }
890
891    #[test]
892    fn match_expressions_work() {
893        let code = r#"
894        match x {
895            (0, y) => y,
896            (x, y) => x,
897        }
898        "#;
899
900        let expected = Expression::Match(
901            Box::new(Expression::Identifier(ast_path("x")).nowhere()),
902            vec![
903                (
904                    Pattern::Tuple(vec![Pattern::integer(0).nowhere(), Pattern::name("y")])
905                        .nowhere(),
906                    Expression::Identifier(ast_path("y")).nowhere(),
907                ),
908                (
909                    Pattern::Tuple(vec![Pattern::name("x"), Pattern::name("y")]).nowhere(),
910                    Expression::Identifier(ast_path("x")).nowhere(),
911                ),
912            ]
913            .nowhere(),
914        )
915        .nowhere();
916
917        check_parse!(code, expression, Ok(expected));
918    }
919
920    #[test]
921    fn blocks_work() {
922        let code = r#"
923            {
924                let a = 0;
925                1
926            }
927            "#;
928
929        let expected = Block {
930            statements: vec![Statement::binding(
931                Pattern::name("a"),
932                None,
933                Expression::int_literal_signed(0).nowhere(),
934            )
935            .nowhere()],
936            result: Some(Expression::int_literal_signed(1).nowhere()),
937        }
938        .nowhere();
939
940        check_parse!(code, block(false), Ok(Some(expected)));
941    }
942
943    #[test]
944    fn blocks_are_expressions() {
945        let code = r#"
946            {
947                let a = 0;
948                1
949            }
950            "#;
951
952        let expected = Expression::Block(Box::new(Block {
953            statements: vec![Statement::binding(
954                Pattern::name("a"),
955                None,
956                Expression::int_literal_signed(0).nowhere(),
957            )
958            .nowhere()],
959            result: Some(Expression::int_literal_signed(1).nowhere()),
960        }))
961        .nowhere();
962
963        check_parse!(code, expression, Ok(expected));
964    }
965
966    #[test]
967    fn infix_operators_work() {
968        let code = r#"
969            1 `infix` 2
970            "#;
971
972        let expected = Expression::Call {
973            kind: CallKind::Function,
974            callee: ast_path("infix"),
975            args: ArgumentList::Positional(vec![
976                Expression::int_literal_signed(1).nowhere(),
977                Expression::int_literal_signed(2).nowhere(),
978            ])
979            .nowhere(),
980            turbofish: None,
981        }
982        .nowhere();
983
984        check_parse!(code, expression, Ok(expected));
985    }
986
987    #[test]
988    fn infix_operator_precedence_is_unchanged() {
989        // NOTE: the exact ordering here is somewhat unimportant, in general one
990        // should probably put parentheses around infix operators anyway. The main
991        // purpose of this test is to prevent accidental changes to the order in the future
992        let code = r#"
993            0 || 1 `infix` 2 `infix` 3
994            "#;
995
996        let expected = Expression::Call {
997            kind: CallKind::Function,
998            callee: ast_path("infix"),
999            args: ArgumentList::Positional(vec![
1000                Expression::BinaryOperator(
1001                    Box::new(Expression::int_literal_signed(0).nowhere()),
1002                    BinaryOperator::LogicalOr.nowhere(),
1003                    Box::new(Expression::int_literal_signed(1).nowhere()),
1004                )
1005                .nowhere(),
1006                Expression::Call {
1007                    kind: CallKind::Function,
1008                    callee: ast_path("infix"),
1009                    args: ArgumentList::Positional(vec![
1010                        Expression::int_literal_signed(2).nowhere(),
1011                        Expression::int_literal_signed(3).nowhere(),
1012                    ])
1013                    .nowhere(),
1014                    turbofish: None,
1015                }
1016                .nowhere(),
1017            ])
1018            .nowhere(),
1019            turbofish: None,
1020        }
1021        .nowhere();
1022
1023        check_parse!(code, expression, Ok(expected));
1024    }
1025
1026    #[test]
1027    fn field_access_operator_does_not_require_parens() {
1028        let code = r#"x.y.z"#;
1029
1030        let expected = Expression::FieldAccess(
1031            Box::new(
1032                Expression::FieldAccess(
1033                    Box::new(Expression::Identifier(ast_path("x")).nowhere()),
1034                    ast_ident("y"),
1035                )
1036                .nowhere(),
1037            ),
1038            ast_ident("z"),
1039        )
1040        .nowhere();
1041
1042        check_parse!(code, expression, Ok(expected));
1043    }
1044
1045    #[test]
1046    fn array_index_operator_precedence_is_correct() {
1047        let code = r#"x && y[z]"#;
1048
1049        let expected = Expression::BinaryOperator(
1050            Box::new(Expression::Identifier(ast_path("x")).nowhere()),
1051            BinaryOperator::LogicalAnd.nowhere(),
1052            Box::new(
1053                Expression::Index(
1054                    Box::new(Expression::Identifier(ast_path("y")).nowhere()),
1055                    Box::new(Expression::Identifier(ast_path("z")).nowhere()),
1056                )
1057                .nowhere(),
1058            ),
1059        )
1060        .nowhere();
1061
1062        check_parse!(code, expression, Ok(expected));
1063    }
1064
1065    #[test]
1066    fn tuple_index_operator_precedence_is_correct() {
1067        let code = r#"y#1#2"#;
1068
1069        let expected = Expression::TupleIndex(
1070            Box::new(
1071                Expression::TupleIndex(
1072                    Box::new(Expression::Identifier(ast_path("y")).nowhere()),
1073                    1u128.nowhere(),
1074                )
1075                .nowhere(),
1076            ),
1077            2.nowhere(),
1078        )
1079        .nowhere();
1080
1081        check_parse!(code, expression, Ok(expected));
1082    }
1083
1084    // Precedence related tests
1085    #[test]
1086    fn subtraction_occurs_in_correct_order() {
1087        let expected_value = Expression::BinaryOperator(
1088            Box::new(
1089                Expression::BinaryOperator(
1090                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1091                    BinaryOperator::Sub.nowhere(),
1092                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1093                )
1094                .nowhere(),
1095            ),
1096            BinaryOperator::Sub.nowhere(),
1097            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
1098        )
1099        .nowhere();
1100
1101        check_parse!("a - b - c", expression, Ok(expected_value));
1102    }
1103
1104    #[test]
1105    fn not_function_call_does_not_invert_function() {
1106        let expected_value = Expression::UnaryOperator(
1107            UnaryOperator::Not.nowhere(),
1108            Box::new(
1109                Expression::Call {
1110                    kind: CallKind::Function,
1111                    callee: ast_path("a"),
1112                    args: ArgumentList::Positional(vec![]).nowhere(),
1113                    turbofish: None,
1114                }
1115                .nowhere(),
1116            ),
1117        )
1118        .nowhere();
1119
1120        check_parse!("!a()", expression, Ok(expected_value));
1121    }
1122
1123    #[test]
1124    fn chained_array_indexing_is_left_to_right() {
1125        let expected_value = Expression::Index(
1126            Box::new(
1127                Expression::Index(
1128                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1129                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1130                )
1131                .nowhere(),
1132            ),
1133            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
1134        )
1135        .nowhere();
1136
1137        check_parse!("a[b][c]", expression, Ok(expected_value));
1138    }
1139
1140    #[test]
1141    fn not_index_result_inverts_whole_result() {
1142        let expected_value = Expression::UnaryOperator(
1143            UnaryOperator::Not.nowhere(),
1144            Box::new(
1145                Expression::Index(
1146                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1147                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1148                )
1149                .nowhere(),
1150            ),
1151        )
1152        .nowhere();
1153
1154        check_parse!("!a[b]", expression, Ok(expected_value));
1155    }
1156
1157    #[test]
1158    fn unary_sub_binds_correctly() {
1159        let expected_value = Expression::BinaryOperator(
1160            Box::new(
1161                Expression::UnaryOperator(
1162                    UnaryOperator::Sub.nowhere(),
1163                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1164                )
1165                .nowhere(),
1166            ),
1167            BinaryOperator::Add.nowhere(),
1168            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1169        )
1170        .nowhere();
1171
1172        check_parse!("-a + b", expression, Ok(expected_value));
1173    }
1174
1175    #[test]
1176    fn unary_sub_binds_correctly_without_spaces() {
1177        let expected_value = Expression::BinaryOperator(
1178            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1179            BinaryOperator::Add.nowhere(),
1180            Box::new(
1181                Expression::UnaryOperator(
1182                    UnaryOperator::Sub.nowhere(),
1183                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1184                )
1185                .nowhere(),
1186            ),
1187        )
1188        .nowhere();
1189
1190        check_parse!("b+-a", expression, Ok(expected_value));
1191    }
1192
1193    #[test]
1194    fn binary_sub_binds_correctly_without_spaces() {
1195        let expected_value = Expression::BinaryOperator(
1196            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1197            BinaryOperator::Sub.nowhere(),
1198            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1199        )
1200        .nowhere();
1201
1202        check_parse!("b-a", expression, Ok(expected_value));
1203    }
1204
1205    #[test]
1206    fn deref_operator_works() {
1207        let expected = Expression::UnaryOperator(
1208            UnaryOperator::Dereference.nowhere(),
1209            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1210        )
1211        .nowhere();
1212
1213        check_parse!("*a", expression, Ok(expected));
1214    }
1215
1216    #[test]
1217    fn deref_operator_precedence() {
1218        let expected = Expression::BinaryOperator(
1219            Box::new(
1220                Expression::UnaryOperator(
1221                    UnaryOperator::Dereference.nowhere(),
1222                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1223                )
1224                .nowhere(),
1225            ),
1226            BinaryOperator::Add.nowhere(),
1227            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1228        )
1229        .nowhere();
1230
1231        check_parse!("*a + b", expression, Ok(expected));
1232    }
1233
1234    #[test]
1235    fn ref_operator_works() {
1236        let expected = Expression::UnaryOperator(
1237            UnaryOperator::Reference.nowhere(),
1238            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1239        )
1240        .nowhere();
1241
1242        check_parse!("&a", expression, Ok(expected));
1243    }
1244}