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