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(val) = self.ascii_char_literal()? {
249            Ok(Expression::IntLiteral(val.clone()).at_loc(&val))
250        } else if let Some(val) = self.ascii_string_literal()? {
251            Ok(val)
252        } else if let Some(block) = self.block(false)? {
253            Ok(block.map(Box::new).map(Expression::Block))
254        } else if let Some(if_expr) = self.if_expression(false)? {
255            Ok(if_expr)
256        } else if let Some(if_expr) = self.type_level_if()? {
257            Ok(if_expr)
258        } else if let Some(match_expr) = self.match_expression()? {
259            Ok(match_expr)
260        } else if let Some(stageref) = self.pipeline_reference()? {
261            Ok(stageref)
262        } else if let Some(label_access) = self.label_access()? {
263            Ok(label_access)
264        } else if let Some(unsafe_expr) = self.unsafe_block()? {
265            Ok(unsafe_expr)
266        } else if let Some(create_ports) = self.peek_and_eat(&TokenKind::Port)? {
267            Ok(Expression::CreatePorts.at(self.file_id, &create_ports))
268        } else if let Some((path, turbofish)) = self.path_with_turbofish()? {
269            let span = path.span;
270            match (turbofish, self.argument_list()?) {
271                (None, None) => Ok(Expression::Identifier(path).at(self.file_id, &span)),
272                (Some(tf), None) => {
273                    return Err(Diagnostic::error(self.peek()?, "Expected argument list")
274                        .primary_label("Expected argument list")
275                        .secondary_label(
276                            tf,
277                            "Type parameters can only be specified on function calls",
278                        ))
279                }
280                (tf, Some(args)) => {
281                    // Doing this avoids cloning result and args
282                    let span = ().between(self.file_id, &path, &args);
283
284                    Ok(Expression::Call {
285                        kind: CallKind::Function,
286                        callee: path,
287                        args,
288                        turbofish: tf,
289                    }
290                    .at_loc(&span))
291                }
292            }
293        } else {
294            let got = self.peek()?;
295            Err(Diagnostic::error(
296                got.loc(),
297                format!("Unexpected `{}`, expected expression", got.kind.as_str()),
298            )
299            .primary_label("expected expression here"))
300        }?;
301
302        self.expression_suffix(expr)
303    }
304
305    #[trace_parser]
306    fn lambda(&mut self) -> Result<Option<Loc<Expression>>> {
307        let start_token = self.peek()?;
308        let Some(unit_kind) = self.unit_kind(&start_token)? else {
309            return Ok(None);
310        };
311
312        let (args, args_loc) = match self.peek_and_eat(&TokenKind::DoublePipe)? {
313            Some(thing) => (vec![], thing.loc()),
314            None => self.surrounded(
315                &TokenKind::Pipe,
316                |s| {
317                    let args = s
318                        .comma_separated(|s| s.pattern(), &TokenKind::Pipe)
319                        .no_context()?;
320
321                    Ok(args)
322                },
323                &TokenKind::Pipe,
324            )?,
325        };
326
327        let args = args.at_loc(&args_loc);
328
329        let body = if self.peek_kind(&TokenKind::OpenBrace)? {
330            // It is safe to unwrap the value, as it can only be `None` if
331            // there is no opening brace but it is guaranteed by the `if`
332            // condition.
333            self.block(unit_kind.is_pipeline())?.unwrap()
334        } else {
335            let expr = self.expression().map_err(|diag| {
336                diag.primary_label("expected lambda body here")
337                    .span_suggest_insert_after(
338                        "you might have meant to place the body there",
339                        args_loc,
340                        "{ /* ... */ }",
341                    )
342            })?;
343
344            let loc = expr.loc();
345
346            let block = Block {
347                statements: vec![],
348                result: Some(expr),
349            };
350
351            block.at_loc(&loc)
352        };
353
354        let loc = ().between(self.file_id, &start_token, &body);
355
356        Ok(Some(
357            Expression::Lambda {
358                unit_kind,
359                args,
360                body: Box::new(body),
361            }
362            .at_loc(&loc),
363        ))
364    }
365
366    #[trace_parser]
367    fn expression_suffix(&mut self, expr: Loc<Expression>) -> Result<Loc<Expression>> {
368        let base = if let Some(hash) = self.peek_and_eat(&TokenKind::Hash)? {
369            if let Some(index) = self.int_literal()? {
370                let index = index
371                    .try_map_ref(|idx| -> Result<u128> {
372                        let as_u128 = idx
373                            .clone()
374                            .as_unsigned()
375                            .ok_or_else(|| {
376                                Diagnostic::error(&index, "Tuple indices must be non-negative")
377                                    .primary_label("Negative tuple index")
378                            })?
379                            .to_u128()
380                            .ok_or_else(|| {
381                                Diagnostic::bug(&index, "Tuple index too large")
382                                    .primary_label("Tuple index too large")
383                                    .note(format!("Tuple index can be at most {}", u128::MAX))
384                            })?;
385
386                        Ok(as_u128)
387                    })?
388                    .between(self.file_id, &hash, &index);
389                Ok(Expression::TupleIndex {
390                    target: Box::new(expr.clone()),
391                    index: *index,
392                    deprecated_syntax: true,
393                }
394                .between(self.file_id, &expr, &index))
395            } else {
396                Err(
397                    Diagnostic::error(self.peek()?.loc(), "expected an index after #")
398                        .primary_label("expected index here"),
399                )
400            }
401        } else if let Some(dot) = self.peek_and_eat(&TokenKind::Dot)? {
402            if let Some(index) = self.int_literal()? {
403                let index = index
404                    .try_map_ref(|idx| -> Result<u128> {
405                        let as_u128 = idx
406                            .clone()
407                            .as_unsigned()
408                            .ok_or_else(|| {
409                                Diagnostic::error(&index, "Tuple indices must be non-negative")
410                                    .primary_label("Negative tuple index")
411                            })?
412                            .to_u128()
413                            .ok_or_else(|| {
414                                Diagnostic::bug(&index, "Tuple index too large")
415                                    .primary_label("Tuple index too large")
416                                    .note(format!("Tuple index can be at most {}", u128::MAX))
417                            })?;
418
419                        Ok(as_u128)
420                    })?
421                    .between(self.file_id, &dot, &index);
422                Ok(Expression::TupleIndex {
423                    target: Box::new(expr.clone()),
424                    index: *index,
425                    deprecated_syntax: false,
426                }
427                .between(self.file_id, &expr, &index))
428            } else {
429                let inst = self.peek_and_eat(&TokenKind::Instance)?;
430
431                if let Some(inst) = &inst {
432                    self.unit_context
433                        .allows_inst(().at(self.file_id, inst))
434                        .handle_in(&mut self.diags);
435                }
436
437                // Check if this is a pipeline or not
438                let pipeline_depth = if inst.is_some() {
439                    if self.peek_kind(&TokenKind::OpenParen)? {
440                        Some(self.surrounded(
441                            &TokenKind::OpenParen,
442                            |s| s.type_expression(),
443                            &TokenKind::CloseParen,
444                        )?)
445                    } else {
446                        None
447                    }
448                } else {
449                    None
450                };
451
452                let field = self.identifier()?;
453
454                let turbofish = self.turbofish()?;
455
456                if let Some(args) = self.argument_list()? {
457                    Ok(Expression::MethodCall {
458                        target: Box::new(expr.clone()),
459                        name: field.clone(),
460                        args: args.clone(),
461                        kind: pipeline_depth
462                            .map(|(depth, _)| {
463                                CallKind::Pipeline(
464                                    ().at(self.file_id, &inst.clone().unwrap()),
465                                    depth,
466                                )
467                            })
468                            .or_else(|| inst.map(|i| CallKind::Entity(().at(self.file_id, &i))))
469                            .unwrap_or(CallKind::Function),
470                        turbofish,
471                    }
472                    .between(self.file_id, &expr, &args))
473                } else if let Some(inst_keyword) = inst {
474                    let base_loc = ().between(self.file_id, &inst_keyword, &field);
475                    let base_expr = if let Some(turbofish) = turbofish {
476                        ().between_locs(&base_loc, &turbofish)
477                    } else {
478                        base_loc
479                    };
480                    Err(ExpectedArgumentList {
481                        next_token: self.peek()?,
482                        base_expr,
483                    }
484                    .with_suggestions())
485                } else if let Some(turbofish) = turbofish {
486                    Err(ExpectedArgumentList {
487                        next_token: self.peek()?,
488                        base_expr: ().between(self.file_id, &turbofish, &field),
489                    }
490                    .with_suggestions())
491                } else {
492                    Ok(
493                        Expression::FieldAccess(Box::new(expr.clone()), field.clone()).between(
494                            self.file_id,
495                            &expr,
496                            &field,
497                        ),
498                    )
499                }
500            }
501        } else if self.peek_kind(&TokenKind::OpenBracket)? {
502            let (inner_expr, loc) = self.surrounded(
503                &TokenKind::OpenBracket,
504                |s| {
505                    // `start` is parsed as an expression since at this point we are parsing either
506                    //
507                    // - an array index (`a[2]`) which allows an expression (`a[2+offset]`)
508                    // - a range index (`a[1..2]`) which does not allow an expression
509                    let start = s.expression()?;
510
511                    if let Some(_) = s.peek_and_eat(&TokenKind::DotDot)? {
512                        // double dot => range index: `[1..2]`
513                        let end = s.expression()?;
514                        Ok(Expression::RangeIndex {
515                            target: Box::new(expr.clone()),
516                            start: Box::new(start),
517                            end: Box::new(end),
518                        })
519                    } else {
520                        Ok(Expression::Index(Box::new(expr.clone()), Box::new(start)))
521                    }
522                },
523                &TokenKind::CloseBracket,
524            )?;
525
526            Ok(inner_expr.between_locs(&expr, &loc))
527        } else {
528            return Ok(expr);
529        }?;
530
531        self.expression_suffix(base)
532    }
533}
534
535#[cfg(test)]
536mod test {
537    use spade_ast::testutil::{ast_ident, ast_path};
538    use spade_ast::*;
539
540    use super::*;
541    use crate::lexer::TokenKind;
542    use crate::{check_parse, format_parse_stack};
543
544    use colored::Colorize;
545    use logos::Logos;
546
547    use spade_common::location_info::WithLocation;
548
549    #[test]
550    fn addition_operatoins_are_expressions() {
551        let expected_value = Expression::BinaryOperator(
552            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
553            BinaryOperator::Add.nowhere(),
554            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
555        )
556        .nowhere();
557
558        check_parse!("a + b", expression, Ok(expected_value));
559    }
560
561    #[test]
562    fn unary_suptraction_works() {
563        let expected_value = Expression::UnaryOperator(
564            UnaryOperator::Sub.nowhere(),
565            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
566        )
567        .nowhere();
568
569        check_parse!("- b", expression, Ok(expected_value));
570    }
571
572    #[test]
573    fn not_operator_works() {
574        let expected_value = Expression::UnaryOperator(
575            UnaryOperator::Not.nowhere(),
576            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
577        )
578        .nowhere();
579
580        check_parse!("!b", expression, Ok(expected_value));
581    }
582
583    #[test]
584    fn bitwise_and_operatoins_are_expressions() {
585        let expected_value = Expression::BinaryOperator(
586            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
587            BinaryOperator::BitwiseAnd.nowhere(),
588            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
589        )
590        .nowhere();
591
592        check_parse!("a & b", expression, Ok(expected_value));
593    }
594
595    #[test]
596    fn bitwise_or_operatoins_are_expressions() {
597        let expected_value = Expression::BinaryOperator(
598            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
599            BinaryOperator::BitwiseOr.nowhere(),
600            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
601        )
602        .nowhere();
603
604        check_parse!("a | b", expression, Ok(expected_value));
605    }
606
607    #[test]
608    fn multiplications_are_expressions() {
609        let expected_value = Expression::BinaryOperator(
610            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
611            BinaryOperator::Mul.nowhere(),
612            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
613        )
614        .nowhere();
615
616        check_parse!("a * b", expression, Ok(expected_value));
617    }
618
619    #[test]
620    fn multiplication_before_addition() {
621        let expected_value = Expression::BinaryOperator(
622            Box::new(
623                Expression::BinaryOperator(
624                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
625                    BinaryOperator::Mul.nowhere(),
626                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
627                )
628                .nowhere(),
629            ),
630            BinaryOperator::Add.nowhere(),
631            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
632        )
633        .nowhere();
634
635        check_parse!("a*b + c", expression, Ok(expected_value));
636    }
637
638    #[test]
639    fn equals_after_addition() {
640        let expected_value = Expression::BinaryOperator(
641            Box::new(
642                Expression::BinaryOperator(
643                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
644                    BinaryOperator::Add.nowhere(),
645                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
646                )
647                .nowhere(),
648            ),
649            BinaryOperator::Equals.nowhere(),
650            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
651        )
652        .nowhere();
653
654        check_parse!("a+b == c", expression, Ok(expected_value));
655    }
656
657    #[test]
658    fn and_after_equals() {
659        {
660            let expected_value = Expression::BinaryOperator(
661                Box::new(
662                    Expression::BinaryOperator(
663                        Box::new(Expression::Identifier(ast_path("a")).nowhere()),
664                        BinaryOperator::Equals.nowhere(),
665                        Box::new(Expression::Identifier(ast_path("b")).nowhere()),
666                    )
667                    .nowhere(),
668                ),
669                BinaryOperator::LogicalAnd.nowhere(),
670                Box::new(Expression::Identifier(ast_path("c")).nowhere()),
671            )
672            .nowhere();
673
674            check_parse!("a == b && c", expression, Ok(expected_value));
675        }
676        {
677            let expected_value = Expression::BinaryOperator(
678                Box::new(Expression::Identifier(ast_path("a")).nowhere()),
679                BinaryOperator::LogicalAnd.nowhere(),
680                Box::new(
681                    Expression::BinaryOperator(
682                        Box::new(Expression::Identifier(ast_path("b")).nowhere()),
683                        BinaryOperator::Equals.nowhere(),
684                        Box::new(Expression::Identifier(ast_path("c")).nowhere()),
685                    )
686                    .nowhere(),
687                ),
688            )
689            .nowhere();
690
691            check_parse!("a && b == c", expression, Ok(expected_value));
692        }
693    }
694
695    #[test]
696    fn bracketed_expressions_are_expressions() {
697        let expected_value = Expression::BinaryOperator(
698            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
699            BinaryOperator::Add.nowhere(),
700            Box::new(
701                Expression::Parenthesized(Box::new(
702                    Expression::BinaryOperator(
703                        Box::new(Expression::Identifier(ast_path("b")).nowhere()),
704                        BinaryOperator::Add.nowhere(),
705                        Box::new(Expression::Identifier(ast_path("c")).nowhere()),
706                    )
707                    .nowhere(),
708                ))
709                .nowhere(),
710            ),
711        )
712        .nowhere();
713
714        check_parse!("a + (b + c)", expression, Ok(expected_value));
715    }
716
717    #[test]
718    fn repeated_bracketed_expressions_work() {
719        let expected_value = Expression::Parenthesized(Box::new(
720            Expression::BinaryOperator(
721                Box::new(
722                    Expression::Parenthesized(Box::new(
723                        Expression::BinaryOperator(
724                            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
725                            BinaryOperator::Add.nowhere(),
726                            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
727                        )
728                        .nowhere(),
729                    ))
730                    .nowhere(),
731                ),
732                BinaryOperator::Add.nowhere(),
733                Box::new(Expression::Identifier(ast_path("a")).nowhere()),
734            )
735            .nowhere(),
736        ))
737        .nowhere();
738
739        check_parse!("((b + c) + a)", expression, Ok(expected_value));
740    }
741
742    #[test]
743    fn functions_work() {
744        let code = "test(1, 2)";
745
746        let expected = Expression::Call {
747            kind: CallKind::Function,
748            callee: ast_path("test"),
749            args: ArgumentList::Positional(vec![
750                Expression::int_literal_signed(1).nowhere(),
751                Expression::int_literal_signed(2).nowhere(),
752            ])
753            .nowhere(),
754            turbofish: None,
755        }
756        .nowhere();
757
758        check_parse!(code, expression, Ok(expected));
759    }
760
761    #[test]
762    fn functions_with_named_arguments_work() {
763        let code = "test$(a, b)";
764
765        let expected = Expression::Call {
766            kind: CallKind::Function,
767            callee: ast_path("test"),
768            args: ArgumentList::Named(vec![
769                NamedArgument::Short(ast_ident("a")),
770                NamedArgument::Short(ast_ident("b")),
771            ])
772            .nowhere(),
773            turbofish: None,
774        }
775        .nowhere();
776
777        check_parse!(code, expression, Ok(expected));
778    }
779
780    #[test]
781    fn tuple_literals_parse() {
782        let code = "(1, true)";
783
784        let expected = Expression::TupleLiteral(vec![
785            Expression::int_literal_signed(1).nowhere(),
786            Expression::bool_literal(true).nowhere(),
787        ])
788        .nowhere();
789
790        check_parse!(code, expression, Ok(expected));
791    }
792
793    #[test]
794    fn array_indexing_works() {
795        let code = "a[0]";
796
797        let expected = Expression::Index(
798            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
799            Box::new(Expression::int_literal_signed(0).nowhere()),
800        )
801        .nowhere();
802
803        check_parse!(code, expression, Ok(expected));
804    }
805
806    #[test]
807    fn tuple_indexing_parsese() {
808        let code = "a.0";
809
810        let expected = Expression::TupleIndex {
811            target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
812            index: Loc::new(0, ().nowhere().span, 0),
813            deprecated_syntax: false,
814        }
815        .nowhere();
816
817        check_parse!(code, expression, Ok(expected));
818    }
819
820    #[test]
821    fn field_access_parses() {
822        let code = "a.b";
823        let expected = Expression::FieldAccess(
824            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
825            ast_ident("b"),
826        )
827        .nowhere();
828
829        check_parse!(code, expression, Ok(expected));
830    }
831
832    #[test]
833    fn method_call_parses() {
834        let code = "a.b(x)";
835
836        let expected = Expression::MethodCall {
837            target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
838            name: ast_ident("b"),
839            args: ArgumentList::Positional(vec![Expression::Identifier(ast_path("x")).nowhere()])
840                .nowhere(),
841            kind: CallKind::Function,
842            turbofish: None,
843        }
844        .nowhere();
845
846        check_parse!(code, expression, Ok(expected));
847    }
848
849    #[test]
850    fn inst_method_call_parses() {
851        let code = "a.inst b(x)";
852
853        let expected = Expression::MethodCall {
854            target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
855            name: ast_ident("b"),
856            args: ArgumentList::Positional(vec![Expression::Identifier(ast_path("x")).nowhere()])
857                .nowhere(),
858            kind: CallKind::Entity(().nowhere()),
859            turbofish: None,
860        }
861        .nowhere();
862
863        check_parse!(code, expression, Ok(expected));
864    }
865
866    #[test]
867    fn method_call_with_named_args_works() {
868        let code = "a.b$(x: y)";
869
870        let expected = Expression::MethodCall {
871            target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
872            name: ast_ident("b"),
873            args: ArgumentList::Named(vec![NamedArgument::Full(
874                ast_ident("x"),
875                Expression::Identifier(ast_path("y")).nowhere(),
876            )])
877            .nowhere(),
878            kind: CallKind::Function,
879            turbofish: None,
880        }
881        .nowhere();
882
883        check_parse!(code, expression, Ok(expected));
884    }
885
886    #[test]
887    fn if_expressions_work() {
888        let code = r#"
889        if a {b} else {c}
890        "#;
891
892        let expected = Expression::If(
893            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
894            Box::new(
895                Expression::Block(Box::new(Block {
896                    statements: vec![],
897                    result: Some(Expression::Identifier(ast_path("b")).nowhere()),
898                }))
899                .nowhere(),
900            ),
901            Box::new(
902                Expression::Block(Box::new(Block {
903                    statements: vec![],
904                    result: Some(Expression::Identifier(ast_path("c")).nowhere()),
905                }))
906                .nowhere(),
907            ),
908        )
909        .nowhere();
910
911        check_parse!(code, expression, Ok(expected));
912    }
913
914    #[test]
915    fn match_expressions_work() {
916        let code = r#"
917        match x {
918            (0, y) => y,
919            (x, y) => x,
920        }
921        "#;
922
923        let expected = Expression::Match(
924            Box::new(Expression::Identifier(ast_path("x")).nowhere()),
925            vec![
926                (
927                    Pattern::Tuple(vec![Pattern::integer(0).nowhere(), Pattern::name("y")])
928                        .nowhere(),
929                    None,
930                    Expression::Identifier(ast_path("y")).nowhere(),
931                ),
932                (
933                    Pattern::Tuple(vec![Pattern::name("x"), Pattern::name("y")]).nowhere(),
934                    None,
935                    Expression::Identifier(ast_path("x")).nowhere(),
936                ),
937            ]
938            .nowhere(),
939        )
940        .nowhere();
941
942        check_parse!(code, expression, Ok(expected));
943    }
944
945    #[test]
946    fn blocks_work() {
947        let code = r#"
948            {
949                let a = 0;
950                1
951            }
952            "#;
953
954        let expected = Block {
955            statements: vec![Statement::binding(
956                Pattern::name("a"),
957                None,
958                Expression::int_literal_signed(0).nowhere(),
959            )
960            .nowhere()],
961            result: Some(Expression::int_literal_signed(1).nowhere()),
962        }
963        .nowhere();
964
965        check_parse!(code, block(false), Ok(Some(expected)));
966    }
967
968    #[test]
969    fn blocks_are_expressions() {
970        let code = r#"
971            {
972                let a = 0;
973                1
974            }
975            "#;
976
977        let expected = Expression::Block(Box::new(Block {
978            statements: vec![Statement::binding(
979                Pattern::name("a"),
980                None,
981                Expression::int_literal_signed(0).nowhere(),
982            )
983            .nowhere()],
984            result: Some(Expression::int_literal_signed(1).nowhere()),
985        }))
986        .nowhere();
987
988        check_parse!(code, expression, Ok(expected));
989    }
990
991    #[test]
992    fn infix_operators_work() {
993        let code = r#"
994            1 `infix` 2
995            "#;
996
997        let expected = Expression::Call {
998            kind: CallKind::Function,
999            callee: ast_path("infix"),
1000            args: ArgumentList::Positional(vec![
1001                Expression::int_literal_signed(1).nowhere(),
1002                Expression::int_literal_signed(2).nowhere(),
1003            ])
1004            .nowhere(),
1005            turbofish: None,
1006        }
1007        .nowhere();
1008
1009        check_parse!(code, expression, Ok(expected));
1010    }
1011
1012    #[test]
1013    fn infix_operator_precedence_is_unchanged() {
1014        // NOTE: the exact ordering here is somewhat unimportant, in general one
1015        // should probably put parentheses around infix operators anyway. The main
1016        // purpose of this test is to prevent accidental changes to the order in the future
1017        let code = r#"
1018            0 || 1 `infix` 2 `infix` 3
1019            "#;
1020
1021        let expected = Expression::Call {
1022            kind: CallKind::Function,
1023            callee: ast_path("infix"),
1024            args: ArgumentList::Positional(vec![
1025                Expression::BinaryOperator(
1026                    Box::new(Expression::int_literal_signed(0).nowhere()),
1027                    BinaryOperator::LogicalOr.nowhere(),
1028                    Box::new(Expression::int_literal_signed(1).nowhere()),
1029                )
1030                .nowhere(),
1031                Expression::Call {
1032                    kind: CallKind::Function,
1033                    callee: ast_path("infix"),
1034                    args: ArgumentList::Positional(vec![
1035                        Expression::int_literal_signed(2).nowhere(),
1036                        Expression::int_literal_signed(3).nowhere(),
1037                    ])
1038                    .nowhere(),
1039                    turbofish: None,
1040                }
1041                .nowhere(),
1042            ])
1043            .nowhere(),
1044            turbofish: None,
1045        }
1046        .nowhere();
1047
1048        check_parse!(code, expression, Ok(expected));
1049    }
1050
1051    #[test]
1052    fn field_access_operator_does_not_require_parens() {
1053        let code = r#"x.y.z"#;
1054
1055        let expected = Expression::FieldAccess(
1056            Box::new(
1057                Expression::FieldAccess(
1058                    Box::new(Expression::Identifier(ast_path("x")).nowhere()),
1059                    ast_ident("y"),
1060                )
1061                .nowhere(),
1062            ),
1063            ast_ident("z"),
1064        )
1065        .nowhere();
1066
1067        check_parse!(code, expression, Ok(expected));
1068    }
1069
1070    #[test]
1071    fn array_index_operator_precedence_is_correct() {
1072        let code = r#"x && y[z]"#;
1073
1074        let expected = Expression::BinaryOperator(
1075            Box::new(Expression::Identifier(ast_path("x")).nowhere()),
1076            BinaryOperator::LogicalAnd.nowhere(),
1077            Box::new(
1078                Expression::Index(
1079                    Box::new(Expression::Identifier(ast_path("y")).nowhere()),
1080                    Box::new(Expression::Identifier(ast_path("z")).nowhere()),
1081                )
1082                .nowhere(),
1083            ),
1084        )
1085        .nowhere();
1086
1087        check_parse!(code, expression, Ok(expected));
1088    }
1089
1090    #[test]
1091    fn tuple_index_operator_precedence_is_correct() {
1092        let code = r#"y.1.2"#;
1093
1094        let expected = Expression::TupleIndex {
1095            target: Box::new(
1096                Expression::TupleIndex {
1097                    target: Box::new(Expression::Identifier(ast_path("y")).nowhere()),
1098                    index: 1u128.nowhere(),
1099                    deprecated_syntax: false,
1100                }
1101                .nowhere(),
1102            ),
1103            index: 2.nowhere(),
1104            deprecated_syntax: false,
1105        }
1106        .nowhere();
1107
1108        check_parse!(code, expression, Ok(expected));
1109    }
1110
1111    // Precedence related tests
1112    #[test]
1113    fn subtraction_occurs_in_correct_order() {
1114        let expected_value = Expression::BinaryOperator(
1115            Box::new(
1116                Expression::BinaryOperator(
1117                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1118                    BinaryOperator::Sub.nowhere(),
1119                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1120                )
1121                .nowhere(),
1122            ),
1123            BinaryOperator::Sub.nowhere(),
1124            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
1125        )
1126        .nowhere();
1127
1128        check_parse!("a - b - c", expression, Ok(expected_value));
1129    }
1130
1131    #[test]
1132    fn not_function_call_does_not_invert_function() {
1133        let expected_value = Expression::UnaryOperator(
1134            UnaryOperator::Not.nowhere(),
1135            Box::new(
1136                Expression::Call {
1137                    kind: CallKind::Function,
1138                    callee: ast_path("a"),
1139                    args: ArgumentList::Positional(vec![]).nowhere(),
1140                    turbofish: None,
1141                }
1142                .nowhere(),
1143            ),
1144        )
1145        .nowhere();
1146
1147        check_parse!("!a()", expression, Ok(expected_value));
1148    }
1149
1150    #[test]
1151    fn chained_array_indexing_is_left_to_right() {
1152        let expected_value = Expression::Index(
1153            Box::new(
1154                Expression::Index(
1155                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1156                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1157                )
1158                .nowhere(),
1159            ),
1160            Box::new(Expression::Identifier(ast_path("c")).nowhere()),
1161        )
1162        .nowhere();
1163
1164        check_parse!("a[b][c]", expression, Ok(expected_value));
1165    }
1166
1167    #[test]
1168    fn not_index_result_inverts_whole_result() {
1169        let expected_value = Expression::UnaryOperator(
1170            UnaryOperator::Not.nowhere(),
1171            Box::new(
1172                Expression::Index(
1173                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1174                    Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1175                )
1176                .nowhere(),
1177            ),
1178        )
1179        .nowhere();
1180
1181        check_parse!("!a[b]", expression, Ok(expected_value));
1182    }
1183
1184    #[test]
1185    fn unary_sub_binds_correctly() {
1186        let expected_value = Expression::BinaryOperator(
1187            Box::new(
1188                Expression::UnaryOperator(
1189                    UnaryOperator::Sub.nowhere(),
1190                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1191                )
1192                .nowhere(),
1193            ),
1194            BinaryOperator::Add.nowhere(),
1195            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1196        )
1197        .nowhere();
1198
1199        check_parse!("-a + b", expression, Ok(expected_value));
1200    }
1201
1202    #[test]
1203    fn unary_sub_binds_correctly_without_spaces() {
1204        let expected_value = Expression::BinaryOperator(
1205            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1206            BinaryOperator::Add.nowhere(),
1207            Box::new(
1208                Expression::UnaryOperator(
1209                    UnaryOperator::Sub.nowhere(),
1210                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1211                )
1212                .nowhere(),
1213            ),
1214        )
1215        .nowhere();
1216
1217        check_parse!("b+-a", expression, Ok(expected_value));
1218    }
1219
1220    #[test]
1221    fn binary_sub_binds_correctly_without_spaces() {
1222        let expected_value = Expression::BinaryOperator(
1223            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1224            BinaryOperator::Sub.nowhere(),
1225            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1226        )
1227        .nowhere();
1228
1229        check_parse!("b-a", expression, Ok(expected_value));
1230    }
1231
1232    #[test]
1233    fn deref_operator_works() {
1234        let expected = Expression::UnaryOperator(
1235            UnaryOperator::Dereference.nowhere(),
1236            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1237        )
1238        .nowhere();
1239
1240        check_parse!("*a", expression, Ok(expected));
1241    }
1242
1243    #[test]
1244    fn deref_operator_precedence() {
1245        let expected = Expression::BinaryOperator(
1246            Box::new(
1247                Expression::UnaryOperator(
1248                    UnaryOperator::Dereference.nowhere(),
1249                    Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1250                )
1251                .nowhere(),
1252            ),
1253            BinaryOperator::Add.nowhere(),
1254            Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1255        )
1256        .nowhere();
1257
1258        check_parse!("*a + b", expression, Ok(expected));
1259    }
1260
1261    #[test]
1262    fn ref_operator_works() {
1263        let expected = Expression::UnaryOperator(
1264            UnaryOperator::Reference.nowhere(),
1265            Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1266        )
1267        .nowhere();
1268
1269        check_parse!("&a", expression, Ok(expected));
1270    }
1271}