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