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