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