1use num::ToPrimitive;
2use spade_ast::token::TokenKind;
3use spade_ast::{
4 ArgumentList, BinaryOperator, Block, CallKind, Expression, IncompleteExpression, IntLiteral,
5 UnaryOperator,
6};
7use spade_common::location_info::{Loc, WithLocation};
8use spade_diagnostics::Diagnostic;
9use spade_diagnostics::diag_list::ResultExt;
10use spade_macros::trace_parser;
11
12use crate::error::{CSErrorTransformations, ExpectedArgumentList, Result, UnexpectedToken};
13use crate::item_type::UnitKindLocal;
14use crate::{ParseStackEntry, Parser};
15
16#[derive(PartialEq, PartialOrd, Eq, Ord)]
17enum OpBindingPower {
18 None,
19 LogicalOr,
20 LogicalAnd,
21 LogicalXor,
22 Equality,
23 RelationalCmp,
24 BitwiseOr,
25 BitwiseXor,
26 BitwiseAnd,
27 Shift,
28 AddLike,
29 MulLike,
30 PrefixUnary,
33}
34
35fn binop_binding_power(op: &BinaryOperator) -> OpBindingPower {
36 match op {
37 BinaryOperator::Add => OpBindingPower::AddLike,
38 BinaryOperator::Sub => OpBindingPower::AddLike,
39 BinaryOperator::Mul => OpBindingPower::MulLike,
40 BinaryOperator::Div => OpBindingPower::MulLike,
41 BinaryOperator::Mod => OpBindingPower::MulLike,
42 BinaryOperator::Eq => OpBindingPower::Equality,
43 BinaryOperator::Neq => OpBindingPower::Equality,
44 BinaryOperator::Lt => OpBindingPower::RelationalCmp,
45 BinaryOperator::Gt => OpBindingPower::RelationalCmp,
46 BinaryOperator::Le => OpBindingPower::RelationalCmp,
47 BinaryOperator::Ge => OpBindingPower::RelationalCmp,
48 BinaryOperator::LogicalAnd => OpBindingPower::LogicalAnd,
49 BinaryOperator::LogicalOr => OpBindingPower::LogicalOr,
50 BinaryOperator::LogicalXor => OpBindingPower::LogicalXor,
51 BinaryOperator::LeftShift => OpBindingPower::Shift,
52 BinaryOperator::RightShift => OpBindingPower::Shift,
53 BinaryOperator::ArithmeticRightShift => OpBindingPower::Shift,
54 BinaryOperator::BitwiseAnd => OpBindingPower::BitwiseAnd,
55 BinaryOperator::BitwiseOr => OpBindingPower::BitwiseOr,
56 BinaryOperator::BitwiseXor => OpBindingPower::BitwiseXor,
57 BinaryOperator::WrappingAdd => OpBindingPower::AddLike,
58 BinaryOperator::WrappingSub => OpBindingPower::AddLike,
59 BinaryOperator::WrappingMul => OpBindingPower::MulLike,
60 BinaryOperator::WrappingLeftShift => OpBindingPower::Shift,
61 BinaryOperator::WrappingRightShift => OpBindingPower::Shift,
62 }
63}
64
65fn unop_binding_power(op: &UnaryOperator) -> OpBindingPower {
66 match op {
67 UnaryOperator::Sub => OpBindingPower::PrefixUnary,
68 UnaryOperator::Not => OpBindingPower::PrefixUnary,
69 UnaryOperator::BitwiseNot => OpBindingPower::PrefixUnary,
70 UnaryOperator::WrappingSub => OpBindingPower::PrefixUnary,
71 UnaryOperator::Dereference => OpBindingPower::PrefixUnary,
72 UnaryOperator::Reference => OpBindingPower::PrefixUnary,
73 }
74}
75
76impl<'a> Parser<'a> {
77 fn binop_from_kind(kind: &TokenKind) -> Option<BinaryOperator> {
78 match kind {
79 TokenKind::Plus => Some(BinaryOperator::Add),
80 TokenKind::Minus => Some(BinaryOperator::Sub),
81 TokenKind::Asterisk => Some(BinaryOperator::Mul),
82 TokenKind::Slash => Some(BinaryOperator::Div),
83 TokenKind::Percentage => Some(BinaryOperator::Mod),
84 TokenKind::Equals => Some(BinaryOperator::Eq),
85 TokenKind::NotEquals => Some(BinaryOperator::Neq),
86 TokenKind::Lt => Some(BinaryOperator::Lt),
89 TokenKind::Gt => Some(BinaryOperator::Gt),
90 TokenKind::Le => Some(BinaryOperator::Le),
91 TokenKind::Ge => Some(BinaryOperator::Ge),
92 TokenKind::RightShift => Some(BinaryOperator::RightShift),
93 TokenKind::ArithmeticRightShift => Some(BinaryOperator::ArithmeticRightShift),
94 TokenKind::LeftShift => Some(BinaryOperator::LeftShift),
95 TokenKind::PlusDot => Some(BinaryOperator::WrappingAdd),
96 TokenKind::MinusDot => Some(BinaryOperator::WrappingSub),
97 TokenKind::AsteriskDot => Some(BinaryOperator::WrappingMul),
98 TokenKind::RightShiftDot => Some(BinaryOperator::WrappingRightShift),
99 TokenKind::LeftShiftDot => Some(BinaryOperator::WrappingLeftShift),
100 TokenKind::DoublePipe => Some(BinaryOperator::LogicalOr),
101 TokenKind::LogicalAnd => Some(BinaryOperator::LogicalAnd),
102 TokenKind::LogicalXor => Some(BinaryOperator::LogicalXor),
103 TokenKind::Ampersand => Some(BinaryOperator::BitwiseAnd),
104 TokenKind::Pipe => Some(BinaryOperator::BitwiseOr),
105 TokenKind::BitwiseXor => Some(BinaryOperator::BitwiseXor),
106 _ => None,
107 }
108 }
109
110 fn unop_from_kind(kind: &TokenKind) -> Option<UnaryOperator> {
111 match kind {
112 TokenKind::Minus => Some(UnaryOperator::Sub),
113 TokenKind::MinusDot => Some(UnaryOperator::WrappingSub),
114 TokenKind::Not => Some(UnaryOperator::Not),
115 TokenKind::Tilde => Some(UnaryOperator::BitwiseNot),
116 TokenKind::Ampersand => Some(UnaryOperator::Reference),
117 TokenKind::Asterisk => Some(UnaryOperator::Dereference),
118 _ => None,
119 }
120 }
121
122 #[tracing::instrument(skip(self))]
123 pub fn expression(&mut self) -> Result<Loc<Expression>> {
124 self.non_comptime_expression()
125 }
126
127 #[tracing::instrument(skip(self))]
130 pub fn non_comptime_expression(&mut self) -> Result<Loc<Expression>> {
131 self.custom_infix_operator()
132 }
133
134 fn custom_infix_operator(&mut self) -> Result<Loc<Expression>> {
135 let lhs_val = self.expr_bp(OpBindingPower::None)?;
136
137 if self.peek_kind(&TokenKind::InfixOperatorSeparator)? {
138 let (Some((callee, _, turbofish)), _) = self.surrounded(
139 &TokenKind::InfixOperatorSeparator,
140 Self::path_with_turbofish,
141 &TokenKind::InfixOperatorSeparator,
142 )?
143 else {
144 return Err(Diagnostic::from(UnexpectedToken {
145 got: self.peek()?,
146 expected: vec!["Identifier"],
147 }));
148 };
149
150 let rhs_val = self.custom_infix_operator()?;
151
152 Ok(Expression::Call {
153 kind: CallKind::Function,
154 callee,
155 args: ArgumentList::Positional(vec![lhs_val.clone(), rhs_val.clone()]).between(
156 self.file_id(),
157 &lhs_val,
158 &rhs_val,
159 ),
160 turbofish,
161 }
162 .between(self.file_id(), &lhs_val, &rhs_val))
163 } else {
164 Ok(lhs_val)
165 }
166 }
167
168 fn inline_negative_literal(
170 &self,
171 op: Loc<UnaryOperator>,
172 rhs: Loc<Expression>,
173 ) -> Result<Loc<Expression>> {
174 let (op, op_loc) = op.split_loc();
175 let (rhs, rhs_loc) = rhs.split_loc();
176 let expr_loc = ().between_locs(&op_loc, &rhs_loc);
177 let expr: Result<Expression> = match (op, rhs) {
178 (UnaryOperator::Sub, Expression::IntLiteral(int)) => {
179 let int_literal = match &int.inner {
180 IntLiteral::Unsized(val) => Ok(IntLiteral::Unsized(-val)),
181 IntLiteral::Signed { val, size } => Ok(IntLiteral::Signed {
182 val: -val,
183 size: size.clone(),
184 }),
185 IntLiteral::Unsigned { val, size } => Err(Diagnostic::error(
186 expr_loc,
187 "Cannot apply unary minus to unsigned integer literal",
188 )
189 .help("Only signed integers can have negative values")
190 .span_suggest_replace(
191 "Try making the integer signed",
192 expr_loc,
193 format!(
194 "-{val}i{}",
195 if let Some(sz) = size {
196 format!("{sz}")
197 } else {
198 String::new()
199 }
200 ),
201 )),
202 }?;
203 Ok(Expression::IntLiteral(int_literal.at_loc(&int)))
204 }
205 (op, rhs) => Ok(Expression::UnaryOperator(
206 op.at_loc(&op_loc),
207 Box::new(rhs.at_loc(&rhs_loc)),
208 )),
209 };
210 Ok(expr?.at_loc(&expr_loc))
211 }
212
213 fn expr_bp(&mut self, min_power: OpBindingPower) -> Result<Loc<Expression>> {
216 let next_tok = self.peek()?;
217 let mut lhs = if let Some((tok, op)) =
218 Self::unop_from_kind(&next_tok.kind).map(|op| (next_tok, op))
219 {
220 self.eat_unconditional()?;
221 let op_power = unop_binding_power(&op);
222 let rhs = self.expr_bp(op_power)?;
223 self.inline_negative_literal(op.at_loc(&tok.loc()), rhs)?
224 } else {
225 self.base_expression()?
226 };
227
228 while let Some(op) = Self::binop_from_kind(&self.peek()?.kind) {
229 let op_power = binop_binding_power(&op);
230
231 if op_power <= min_power {
232 break;
233 }
234
235 let op_tok = self.eat_unconditional()?;
236
237 let rhs = self.expr_bp(op_power)?;
238 lhs = Expression::BinaryOperator(
239 Box::new(lhs.clone()),
240 op.at(self.file_id(), &op_tok),
241 Box::new(rhs.clone()),
242 )
243 .between(self.file_id(), &lhs, &rhs)
244 }
245
246 Ok(lhs)
247 }
248
249 #[trace_parser]
252 fn base_expression(&mut self) -> Result<Loc<Expression>> {
253 let expr = if let Some(tuple) = self.tuple_literal()? {
254 Ok(tuple)
255 } else if let Some(lambda) = self.lambda()? {
256 Ok(lambda)
257 } else if let Some(array) = self.array_literal()? {
258 Ok(array)
259 } else if let Some(instance) = self.entity_instance()? {
260 Ok(instance)
261 } else if let Some(val) = self.bool_literal()? {
262 Ok(Expression::BoolLiteral(val).at_loc(&val))
263 } else if let Some(val) = self.str_literal()? {
264 Ok(Expression::StrLiteral(val.clone()).at_loc(&val))
265 } else if let Some(val) = self.tri_literal()? {
266 Ok(Expression::TriLiteral(val.clone()).at_loc(&val))
267 } else if let Some(val) = self.int_literal()? {
268 Ok(Expression::IntLiteral(val.clone()).at_loc(&val))
269 } else if let Some(val) = self.ascii_char_literal()? {
270 Ok(Expression::IntLiteral(val.clone()).at_loc(&val))
271 } else if let Some(val) = self.ascii_string_literal()? {
272 Ok(val)
273 } else if let Some(block) = self.block(false)? {
274 Ok(block.map(Box::new).map(Expression::Block))
275 } else if let Some(if_expr) = self.if_expression(false, true, false)? {
276 Ok(if_expr)
277 } else if let Some(if_expr) = self.type_level_if()? {
278 Ok(if_expr)
279 } else if let Some(match_expr) = self.match_expression()? {
280 Ok(match_expr)
281 } else if let Some(stageref) = self.pipeline_reference()? {
282 Ok(stageref)
283 } else if let Some(label_access) = self.label_access()? {
284 Ok(label_access)
285 } else if let Some(unsafe_expr) = self.unsafe_block()? {
286 Ok(unsafe_expr)
287 } else if let Some((path, is_macro, turbofish)) = self.path_with_turbofish()? {
288 if is_macro {
289 let opening_token = self.peek()?;
290 let closing_delimiter = match opening_token.kind {
291 TokenKind::OpenBrace => TokenKind::CloseBrace,
292 TokenKind::OpenBracket => TokenKind::CloseBracket,
293 TokenKind::OpenParen => TokenKind::CloseParen,
294 _ => {
295 return Err(Diagnostic::from(UnexpectedToken {
296 got: opening_token,
297 expected: vec![
298 TokenKind::CloseParen.as_str(),
299 TokenKind::CloseBracket.as_str(),
300 TokenKind::CloseBrace.as_str(),
301 ],
302 }));
303 }
304 };
305
306 let tokens = self.enclosed_token_stream(&opening_token.kind, &closing_delimiter)?;
307 let end_loc = tokens.loc();
308
309 Ok(Expression::MacroCall {
310 callee: path.clone(),
311 tokens: tokens.inner,
312 parse_ctx: self.parse_ctx.clone(),
313 }
314 .between(self.file_id(), &path, &end_loc))
315 } else {
316 let span = path.span;
317 match (turbofish, self.argument_list()?) {
318 (None, None) => Ok(Expression::Identifier(path).at(self.file_id(), &span)),
319 (Some(tf), None) => {
320 return Err(Diagnostic::error(self.peek()?, "Expected argument list")
321 .primary_label("Expected argument list")
322 .secondary_label(
323 tf,
324 "Type parameters can only be specified on function calls",
325 ));
326 }
327 (tf, Some(args)) => {
328 let span = ().between(self.file_id(), &path, &args);
330
331 Ok(Expression::Call {
332 kind: CallKind::Function,
333 callee: path,
334 args,
335 turbofish: tf,
336 }
337 .at_loc(&span))
338 }
339 }
340 }
341 } else {
342 let got = self.peek()?;
343 Err(Diagnostic::error(
344 got.loc(),
345 format!("Unexpected `{}`, expected expression", got.kind.as_str()),
346 )
347 .primary_label("expected expression here"))
348 }?;
349
350 self.expression_suffix(expr)
351 }
352
353 #[trace_parser]
354 fn lambda(&mut self) -> Result<Option<Loc<Expression>>> {
355 let start_token = self.peek()?;
356 let Some(unit_kind) = self.unit_kind(&start_token)? else {
357 return Ok(None);
358 };
359
360 let (args, args_loc) = match self.peek_and_eat(&TokenKind::DoublePipe)? {
361 Some(thing) => (vec![], thing.loc()),
362 None => self.surrounded(
363 &TokenKind::Pipe,
364 |s| {
365 let args = s
366 .comma_separated(|s| s.pattern(), &TokenKind::Pipe)
367 .no_context()?;
368
369 Ok(args)
370 },
371 &TokenKind::Pipe,
372 )?,
373 };
374
375 let args = args.at_loc(&args_loc);
376
377 let body = if self.peek_kind(&TokenKind::OpenBrace)? {
378 self.block(unit_kind.is_pipeline())?.unwrap()
382 } else {
383 let expr = self.expression().map_err(|diag| {
384 diag.primary_label("expected lambda body here")
385 .span_suggest_insert_after(
386 "you might have meant to place the body there",
387 args_loc,
388 "{ /* ... */ }",
389 )
390 })?;
391
392 let loc = expr.loc();
393
394 let block = Block {
395 statements: vec![],
396 result: Some(expr),
397 };
398
399 block.at_loc(&loc)
400 };
401
402 let loc = ().between(self.file_id(), &start_token, &body);
403
404 Ok(Some(
405 Expression::Lambda {
406 unit_kind,
407 args,
408 body: Box::new(body),
409 }
410 .at_loc(&loc),
411 ))
412 }
413
414 #[trace_parser]
415 fn expression_suffix(&mut self, expr: Loc<Expression>) -> Result<Loc<Expression>> {
416 let base = if let Some(hash) = self.peek_and_eat(&TokenKind::Hash)? {
417 if let Some(index) = self.int_literal()? {
418 let index = index
419 .try_map_ref(|idx| -> Result<u128> {
420 let as_u128 = idx
421 .clone()
422 .as_unsigned()
423 .ok_or_else(|| {
424 Diagnostic::error(&index, "Tuple indices must be non-negative")
425 .primary_label("Negative tuple index")
426 })?
427 .to_u128()
428 .ok_or_else(|| {
429 Diagnostic::bug(&index, "Tuple index too large")
430 .primary_label("Tuple index too large")
431 .note(format!("Tuple index can be at most {}", u128::MAX))
432 })?;
433
434 Ok(as_u128)
435 })?
436 .between(self.file_id(), &hash, &index);
437 Ok(Expression::TupleIndex {
438 target: Box::new(expr.clone()),
439 index: *index,
440 deprecated_syntax: true,
441 }
442 .between(self.file_id(), &expr, &index))
443 } else {
444 Err(
445 Diagnostic::error(self.peek()?.loc(), "expected an index after #")
446 .primary_label("expected index here"),
447 )
448 }
449 } else if let Some(dot) = self.peek_and_eat(&TokenKind::Dot)? {
450 if let Some(index) = self.int_literal()? {
451 let index = index
452 .try_map_ref(|idx| -> Result<u128> {
453 let as_u128 = idx
454 .clone()
455 .as_unsigned()
456 .ok_or_else(|| {
457 Diagnostic::error(&index, "Tuple indices must be non-negative")
458 .primary_label("Negative tuple index")
459 })?
460 .to_u128()
461 .ok_or_else(|| {
462 Diagnostic::bug(&index, "Tuple index too large")
463 .primary_label("Tuple index too large")
464 .note(format!("Tuple index can be at most {}", u128::MAX))
465 })?;
466
467 Ok(as_u128)
468 })?
469 .between(self.file_id(), &dot, &index);
470 Ok(Expression::TupleIndex {
471 target: Box::new(expr.clone()),
472 index: *index,
473 deprecated_syntax: false,
474 }
475 .between(self.file_id(), &expr, &index))
476 } else {
477 let inst = self.peek_and_eat(&TokenKind::Instance)?;
478
479 let pipeline_depth = if inst.is_some() {
481 if self.peek_kind(&TokenKind::OpenParen)? {
482 Some(self.surrounded(
483 &TokenKind::OpenParen,
484 |s| s.type_expression(),
485 &TokenKind::CloseParen,
486 )?)
487 } else {
488 None
489 }
490 } else {
491 None
492 };
493
494 if !self.peek_cond(|tok| matches!(tok, TokenKind::Identifier(_)), "Identifier")? {
495 let next = self.peek()?;
496 let loc = ().at(self.file_id(), &next);
497 return Ok(Expression::Incomplete(
498 Diagnostic::error(next, "Expected an identifier after `.`")
499 .primary_label("Expected identifier")
500 .secondary_label(dot, "To complete this `.`"),
501 IncompleteExpression::IncompleteDot {
502 has_inst: inst.is_some(),
503 has_depth: pipeline_depth.is_some(),
504 base: Box::new(expr.clone()),
505 },
506 )
507 .between_locs(&expr, &loc));
508 }
509 let field = self.identifier()?;
510
511 let turbofish = self.turbofish()?;
512
513 if let Some(inst) = &inst {
514 self.unit_context
515 .allows_inst(().at(self.file_id(), inst))
516 .handle_in(&mut self.diags);
517 }
518
519 if let Some(args) = self.argument_list()? {
520 Ok(Expression::MethodCall {
521 target: Box::new(expr.clone()),
522 name: field.clone(),
523 args: args.clone(),
524 kind: pipeline_depth
525 .map(|(depth, _)| {
526 CallKind::Pipeline(
527 ().at(self.file_id(), &inst.clone().unwrap()),
528 depth,
529 )
530 })
531 .or_else(|| inst.map(|i| CallKind::Entity(().at(self.file_id(), &i))))
532 .unwrap_or(CallKind::Function),
533 turbofish,
534 }
535 .between(self.file_id(), &expr, &args))
536 } else if let Some(inst_keyword) = inst {
537 let base_loc = ().between(self.file_id(), &inst_keyword, &field);
538 let base_expr = if let Some(turbofish) = turbofish {
539 ().between_locs(&base_loc, &turbofish)
540 } else {
541 base_loc
542 };
543 Err(ExpectedArgumentList {
544 next_token: self.peek()?,
545 base_expr,
546 }
547 .with_suggestions())
548 } else if let Some(turbofish) = turbofish {
549 Err(ExpectedArgumentList {
550 next_token: self.peek()?,
551 base_expr: ().between(self.file_id(), &turbofish, &field),
552 }
553 .with_suggestions())
554 } else {
555 Ok(
556 Expression::FieldAccess(Box::new(expr.clone()), field.clone()).between(
557 self.file_id(),
558 &expr,
559 &field,
560 ),
561 )
562 }
563 }
564 } else if self.peek_kind(&TokenKind::OpenBracket)? {
565 let (inner_expr, loc) = self.surrounded(
566 &TokenKind::OpenBracket,
567 |s| {
568 if let Some(_) = s.peek_and_eat(&TokenKind::DotDot)? {
569 let end = if s.peek_kind(&TokenKind::CloseBracket)? {
570 None
571 } else {
572 Some(s.expression()?)
573 };
574
575 Ok(Expression::RangeIndex {
576 target: Box::new(expr.clone()),
577 start: None,
578 end: end.map(Box::new),
579 })
580 } else {
581 let start = s.expression()?;
587
588 if let Some(_) = s.peek_and_eat(&TokenKind::DotDot)? {
589 let end = if s.peek_kind(&TokenKind::CloseBracket)? {
590 None
591 } else {
592 Some(s.expression()?)
593 };
594
595 Ok(Expression::RangeIndex {
596 target: Box::new(expr.clone()),
597 start: Some(Box::new(start)),
598 end: end.map(Box::new),
599 })
600 } else {
601 Ok(Expression::Index(Box::new(expr.clone()), Box::new(start)))
602 }
603 }
604 },
605 &TokenKind::CloseBracket,
606 )?;
607
608 Ok(inner_expr.between_locs(&expr, &loc))
609 } else if self.peek_and_eat(&TokenKind::As)?.is_some() {
610 let expr_loc = expr.loc();
611 let ty = self.type_expression()?;
612 let ty_loc = ty.loc();
613 return Ok(Expression::TypeCast(Box::new(expr), ty).between_locs(&expr_loc, &ty_loc));
614 } else {
615 return Ok(expr);
616 }?;
617
618 self.expression_suffix(base)
619 }
620}
621
622#[cfg(test)]
623mod test {
624 use spade_ast::testutil::{ast_ident, ast_path};
625 use spade_ast::*;
626
627 use super::*;
628 use crate::{check_parse, format_parse_stack};
629
630 use colored::Colorize;
631
632 use spade_common::location_info::WithLocation;
633
634 #[test]
635 fn addition_operatoins_are_expressions() {
636 let expected_value = Expression::BinaryOperator(
637 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
638 BinaryOperator::Add.nowhere(),
639 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
640 )
641 .nowhere();
642
643 check_parse!("a + b", expression, Ok(expected_value));
644 }
645
646 #[test]
647 fn unary_suptraction_works() {
648 let expected_value = Expression::UnaryOperator(
649 UnaryOperator::Sub.nowhere(),
650 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
651 )
652 .nowhere();
653
654 check_parse!("- b", expression, Ok(expected_value));
655 }
656
657 #[test]
658 fn not_operator_works() {
659 let expected_value = Expression::UnaryOperator(
660 UnaryOperator::Not.nowhere(),
661 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
662 )
663 .nowhere();
664
665 check_parse!("!b", expression, Ok(expected_value));
666 }
667
668 #[test]
669 fn bitwise_and_operatoins_are_expressions() {
670 let expected_value = Expression::BinaryOperator(
671 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
672 BinaryOperator::BitwiseAnd.nowhere(),
673 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
674 )
675 .nowhere();
676
677 check_parse!("a & b", expression, Ok(expected_value));
678 }
679
680 #[test]
681 fn bitwise_or_operatoins_are_expressions() {
682 let expected_value = Expression::BinaryOperator(
683 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
684 BinaryOperator::BitwiseOr.nowhere(),
685 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
686 )
687 .nowhere();
688
689 check_parse!("a | b", expression, Ok(expected_value));
690 }
691
692 #[test]
693 fn multiplications_are_expressions() {
694 let expected_value = Expression::BinaryOperator(
695 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
696 BinaryOperator::Mul.nowhere(),
697 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
698 )
699 .nowhere();
700
701 check_parse!("a * b", expression, Ok(expected_value));
702 }
703
704 #[test]
705 fn multiplication_before_addition() {
706 let expected_value = Expression::BinaryOperator(
707 Box::new(
708 Expression::BinaryOperator(
709 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
710 BinaryOperator::Mul.nowhere(),
711 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
712 )
713 .nowhere(),
714 ),
715 BinaryOperator::Add.nowhere(),
716 Box::new(Expression::Identifier(ast_path("c")).nowhere()),
717 )
718 .nowhere();
719
720 check_parse!("a*b + c", expression, Ok(expected_value));
721 }
722
723 #[test]
724 fn equals_after_addition() {
725 let expected_value = Expression::BinaryOperator(
726 Box::new(
727 Expression::BinaryOperator(
728 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
729 BinaryOperator::Add.nowhere(),
730 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
731 )
732 .nowhere(),
733 ),
734 BinaryOperator::Eq.nowhere(),
735 Box::new(Expression::Identifier(ast_path("c")).nowhere()),
736 )
737 .nowhere();
738
739 check_parse!("a+b == c", expression, Ok(expected_value));
740 }
741
742 #[test]
743 fn and_after_equals() {
744 {
745 let expected_value = Expression::BinaryOperator(
746 Box::new(
747 Expression::BinaryOperator(
748 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
749 BinaryOperator::Eq.nowhere(),
750 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
751 )
752 .nowhere(),
753 ),
754 BinaryOperator::LogicalAnd.nowhere(),
755 Box::new(Expression::Identifier(ast_path("c")).nowhere()),
756 )
757 .nowhere();
758
759 check_parse!("a == b && c", expression, Ok(expected_value));
760 }
761 {
762 let expected_value = Expression::BinaryOperator(
763 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
764 BinaryOperator::LogicalAnd.nowhere(),
765 Box::new(
766 Expression::BinaryOperator(
767 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
768 BinaryOperator::Eq.nowhere(),
769 Box::new(Expression::Identifier(ast_path("c")).nowhere()),
770 )
771 .nowhere(),
772 ),
773 )
774 .nowhere();
775
776 check_parse!("a && b == c", expression, Ok(expected_value));
777 }
778 }
779
780 #[test]
781 fn bracketed_expressions_are_expressions() {
782 let expected_value = Expression::BinaryOperator(
783 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
784 BinaryOperator::Add.nowhere(),
785 Box::new(
786 Expression::Parenthesized(Box::new(
787 Expression::BinaryOperator(
788 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
789 BinaryOperator::Add.nowhere(),
790 Box::new(Expression::Identifier(ast_path("c")).nowhere()),
791 )
792 .nowhere(),
793 ))
794 .nowhere(),
795 ),
796 )
797 .nowhere();
798
799 check_parse!("a + (b + c)", expression, Ok(expected_value));
800 }
801
802 #[test]
803 fn repeated_bracketed_expressions_work() {
804 let expected_value = Expression::Parenthesized(Box::new(
805 Expression::BinaryOperator(
806 Box::new(
807 Expression::Parenthesized(Box::new(
808 Expression::BinaryOperator(
809 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
810 BinaryOperator::Add.nowhere(),
811 Box::new(Expression::Identifier(ast_path("c")).nowhere()),
812 )
813 .nowhere(),
814 ))
815 .nowhere(),
816 ),
817 BinaryOperator::Add.nowhere(),
818 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
819 )
820 .nowhere(),
821 ))
822 .nowhere();
823
824 check_parse!("((b + c) + a)", expression, Ok(expected_value));
825 }
826
827 #[test]
828 fn functions_work() {
829 let code = "test(1, 2)";
830
831 let expected = Expression::Call {
832 kind: CallKind::Function,
833 callee: ast_path("test"),
834 args: ArgumentList::Positional(vec![
835 Expression::int_literal_signed(1).nowhere(),
836 Expression::int_literal_signed(2).nowhere(),
837 ])
838 .nowhere(),
839 turbofish: None,
840 }
841 .nowhere();
842
843 check_parse!(code, expression, Ok(expected));
844 }
845
846 #[test]
847 fn functions_with_named_arguments_work() {
848 let code = "test$(a, b)";
849
850 let expected = Expression::Call {
851 kind: CallKind::Function,
852 callee: ast_path("test"),
853 args: ArgumentList::Named(vec![
854 NamedArgument::Short(ast_ident("a")),
855 NamedArgument::Short(ast_ident("b")),
856 ])
857 .nowhere(),
858 turbofish: None,
859 }
860 .nowhere();
861
862 check_parse!(code, expression, Ok(expected));
863 }
864
865 #[test]
866 fn tuple_literals_parse() {
867 let code = "(1, true)";
868
869 let expected = Expression::TupleLiteral(vec![
870 Expression::int_literal_signed(1).nowhere(),
871 Expression::bool_literal(true).nowhere(),
872 ])
873 .nowhere();
874
875 check_parse!(code, expression, Ok(expected));
876 }
877
878 #[test]
879 fn array_indexing_works() {
880 let code = "a[0]";
881
882 let expected = Expression::Index(
883 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
884 Box::new(Expression::int_literal_signed(0).nowhere()),
885 )
886 .nowhere();
887
888 check_parse!(code, expression, Ok(expected));
889 }
890
891 #[test]
892 fn tuple_indexing_parsese() {
893 let code = "a.0";
894
895 let expected = Expression::TupleIndex {
896 target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
897 index: Loc::new(0, ().nowhere().span, 0),
898 deprecated_syntax: false,
899 }
900 .nowhere();
901
902 check_parse!(code, expression, Ok(expected));
903 }
904
905 #[test]
906 fn field_access_parses() {
907 let code = "a.b";
908 let expected = Expression::FieldAccess(
909 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
910 ast_ident("b"),
911 )
912 .nowhere();
913
914 check_parse!(code, expression, Ok(expected));
915 }
916
917 #[test]
918 fn method_call_parses() {
919 let code = "a.b(x)";
920
921 let expected = Expression::MethodCall {
922 target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
923 name: ast_ident("b"),
924 args: ArgumentList::Positional(vec![Expression::Identifier(ast_path("x")).nowhere()])
925 .nowhere(),
926 kind: CallKind::Function,
927 turbofish: None,
928 }
929 .nowhere();
930
931 check_parse!(code, expression, Ok(expected));
932 }
933
934 #[test]
935 fn inst_method_call_parses() {
936 let code = "a.inst b(x)";
937
938 let expected = Expression::MethodCall {
939 target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
940 name: ast_ident("b"),
941 args: ArgumentList::Positional(vec![Expression::Identifier(ast_path("x")).nowhere()])
942 .nowhere(),
943 kind: CallKind::Entity(().nowhere()),
944 turbofish: None,
945 }
946 .nowhere();
947
948 check_parse!(code, expression, Ok(expected));
949 }
950
951 #[test]
952 fn method_call_with_named_args_works() {
953 let code = "a.b$(x: y)";
954
955 let expected = Expression::MethodCall {
956 target: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
957 name: ast_ident("b"),
958 args: ArgumentList::Named(vec![NamedArgument::Full(
959 ast_ident("x"),
960 Expression::Identifier(ast_path("y")).nowhere(),
961 )])
962 .nowhere(),
963 kind: CallKind::Function,
964 turbofish: None,
965 }
966 .nowhere();
967
968 check_parse!(code, expression, Ok(expected));
969 }
970
971 #[test]
972 fn if_expressions_work() {
973 let code = r#"
974 if a {b} else {c}
975 "#;
976
977 let expected = Expression::If {
978 cond: Box::new(Expression::Identifier(ast_path("a")).nowhere()),
979 on_true: Box::new(
980 Expression::Block(Box::new(Block {
981 statements: vec![],
982 result: Some(Expression::Identifier(ast_path("b")).nowhere()),
983 }))
984 .nowhere(),
985 ),
986 on_false: Box::new(
987 Expression::Block(Box::new(Block {
988 statements: vec![],
989 result: Some(Expression::Identifier(ast_path("c")).nowhere()),
990 }))
991 .nowhere(),
992 ),
993 }
994 .nowhere();
995
996 check_parse!(code, expression, Ok(expected));
997 }
998
999 #[test]
1000 fn match_expressions_work() {
1001 let code = r#"
1002 match x {
1003 (0, y) => y,
1004 (x, y) => x,
1005 }
1006 "#;
1007
1008 let expected = Expression::Match {
1009 expression: Box::new(Expression::Identifier(ast_path("x")).nowhere()),
1010 branches: vec![
1011 (
1012 Pattern::Tuple(vec![Pattern::integer(0).nowhere(), Pattern::name("y")])
1013 .nowhere(),
1014 None,
1015 Expression::Identifier(ast_path("y")).nowhere(),
1016 ),
1017 (
1018 Pattern::Tuple(vec![Pattern::name("x"), Pattern::name("y")]).nowhere(),
1019 None,
1020 Expression::Identifier(ast_path("x")).nowhere(),
1021 ),
1022 ]
1023 .nowhere(),
1024 if_let: false,
1025 }
1026 .nowhere();
1027
1028 check_parse!(code, expression, Ok(expected));
1029 }
1030
1031 #[test]
1032 fn if_let_expressions_work() {
1033 let code = r#"
1034 if let (0, y) = x {
1035 y
1036 } else {
1037 x
1038 }
1039 "#;
1040
1041 let expected = Expression::Match {
1042 expression: Box::new(Expression::Identifier(ast_path("x")).nowhere()),
1043 branches: vec![
1044 (
1045 Pattern::Tuple(vec![Pattern::integer(0).nowhere(), Pattern::name("y")])
1046 .nowhere(),
1047 None,
1048 Expression::Block(Box::new(Block {
1049 statements: vec![],
1050 result: Some(Expression::Identifier(ast_path("y")).nowhere()),
1051 }))
1052 .nowhere(),
1053 ),
1054 (
1055 Pattern::Path {
1056 wire: None,
1057 path: ast_path("_"),
1058 }
1059 .nowhere(),
1060 None,
1061 Expression::Block(Box::new(Block {
1062 statements: vec![],
1063 result: Some(Expression::Identifier(ast_path("x")).nowhere()),
1064 }))
1065 .nowhere(),
1066 ),
1067 ]
1068 .nowhere(),
1069 if_let: true,
1070 }
1071 .nowhere();
1072
1073 check_parse!(code, expression, Ok(expected));
1074 }
1075
1076 #[test]
1077 fn blocks_work() {
1078 let code = r#"
1079 {
1080 let a = 0;
1081 1
1082 }
1083 "#;
1084
1085 let expected = Block {
1086 statements: vec![
1087 Statement::binding(
1088 Pattern::name("a"),
1089 None,
1090 Expression::int_literal_signed(0).nowhere(),
1091 )
1092 .nowhere(),
1093 ],
1094 result: Some(Expression::int_literal_signed(1).nowhere()),
1095 }
1096 .nowhere();
1097
1098 check_parse!(code, block(false), Ok(Some(expected)));
1099 }
1100
1101 #[test]
1102 fn blocks_are_expressions() {
1103 let code = r#"
1104 {
1105 let a = 0;
1106 1
1107 }
1108 "#;
1109
1110 let expected = Expression::Block(Box::new(Block {
1111 statements: vec![
1112 Statement::binding(
1113 Pattern::name("a"),
1114 None,
1115 Expression::int_literal_signed(0).nowhere(),
1116 )
1117 .nowhere(),
1118 ],
1119 result: Some(Expression::int_literal_signed(1).nowhere()),
1120 }))
1121 .nowhere();
1122
1123 check_parse!(code, expression, Ok(expected));
1124 }
1125
1126 #[test]
1127 fn infix_operators_work() {
1128 let code = r#"
1129 1 `infix` 2
1130 "#;
1131
1132 let expected = Expression::Call {
1133 kind: CallKind::Function,
1134 callee: ast_path("infix"),
1135 args: ArgumentList::Positional(vec![
1136 Expression::int_literal_signed(1).nowhere(),
1137 Expression::int_literal_signed(2).nowhere(),
1138 ])
1139 .nowhere(),
1140 turbofish: None,
1141 }
1142 .nowhere();
1143
1144 check_parse!(code, expression, Ok(expected));
1145 }
1146
1147 #[test]
1148 fn infix_operator_precedence_is_unchanged() {
1149 let code = r#"
1153 0 || 1 `infix` 2 `infix` 3
1154 "#;
1155
1156 let expected = Expression::Call {
1157 kind: CallKind::Function,
1158 callee: ast_path("infix"),
1159 args: ArgumentList::Positional(vec![
1160 Expression::BinaryOperator(
1161 Box::new(Expression::int_literal_signed(0).nowhere()),
1162 BinaryOperator::LogicalOr.nowhere(),
1163 Box::new(Expression::int_literal_signed(1).nowhere()),
1164 )
1165 .nowhere(),
1166 Expression::Call {
1167 kind: CallKind::Function,
1168 callee: ast_path("infix"),
1169 args: ArgumentList::Positional(vec![
1170 Expression::int_literal_signed(2).nowhere(),
1171 Expression::int_literal_signed(3).nowhere(),
1172 ])
1173 .nowhere(),
1174 turbofish: None,
1175 }
1176 .nowhere(),
1177 ])
1178 .nowhere(),
1179 turbofish: None,
1180 }
1181 .nowhere();
1182
1183 check_parse!(code, expression, Ok(expected));
1184 }
1185
1186 #[test]
1187 fn field_access_operator_does_not_require_parens() {
1188 let code = r#"x.y.z"#;
1189
1190 let expected = Expression::FieldAccess(
1191 Box::new(
1192 Expression::FieldAccess(
1193 Box::new(Expression::Identifier(ast_path("x")).nowhere()),
1194 ast_ident("y"),
1195 )
1196 .nowhere(),
1197 ),
1198 ast_ident("z"),
1199 )
1200 .nowhere();
1201
1202 check_parse!(code, expression, Ok(expected));
1203 }
1204
1205 #[test]
1206 fn array_index_operator_precedence_is_correct() {
1207 let code = r#"x && y[z]"#;
1208
1209 let expected = Expression::BinaryOperator(
1210 Box::new(Expression::Identifier(ast_path("x")).nowhere()),
1211 BinaryOperator::LogicalAnd.nowhere(),
1212 Box::new(
1213 Expression::Index(
1214 Box::new(Expression::Identifier(ast_path("y")).nowhere()),
1215 Box::new(Expression::Identifier(ast_path("z")).nowhere()),
1216 )
1217 .nowhere(),
1218 ),
1219 )
1220 .nowhere();
1221
1222 check_parse!(code, expression, Ok(expected));
1223 }
1224
1225 #[test]
1226 fn tuple_index_operator_precedence_is_correct() {
1227 let code = r#"y.1.2"#;
1228
1229 let expected = Expression::TupleIndex {
1230 target: Box::new(
1231 Expression::TupleIndex {
1232 target: Box::new(Expression::Identifier(ast_path("y")).nowhere()),
1233 index: 1u128.nowhere(),
1234 deprecated_syntax: false,
1235 }
1236 .nowhere(),
1237 ),
1238 index: 2.nowhere(),
1239 deprecated_syntax: false,
1240 }
1241 .nowhere();
1242
1243 check_parse!(code, expression, Ok(expected));
1244 }
1245
1246 #[test]
1248 fn subtraction_occurs_in_correct_order() {
1249 let expected_value = Expression::BinaryOperator(
1250 Box::new(
1251 Expression::BinaryOperator(
1252 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1253 BinaryOperator::Sub.nowhere(),
1254 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1255 )
1256 .nowhere(),
1257 ),
1258 BinaryOperator::Sub.nowhere(),
1259 Box::new(Expression::Identifier(ast_path("c")).nowhere()),
1260 )
1261 .nowhere();
1262
1263 check_parse!("a - b - c", expression, Ok(expected_value));
1264 }
1265
1266 #[test]
1267 fn not_function_call_does_not_invert_function() {
1268 let expected_value = Expression::UnaryOperator(
1269 UnaryOperator::Not.nowhere(),
1270 Box::new(
1271 Expression::Call {
1272 kind: CallKind::Function,
1273 callee: ast_path("a"),
1274 args: ArgumentList::Positional(vec![]).nowhere(),
1275 turbofish: None,
1276 }
1277 .nowhere(),
1278 ),
1279 )
1280 .nowhere();
1281
1282 check_parse!("!a()", expression, Ok(expected_value));
1283 }
1284
1285 #[test]
1286 fn chained_array_indexing_is_left_to_right() {
1287 let expected_value = Expression::Index(
1288 Box::new(
1289 Expression::Index(
1290 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1291 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1292 )
1293 .nowhere(),
1294 ),
1295 Box::new(Expression::Identifier(ast_path("c")).nowhere()),
1296 )
1297 .nowhere();
1298
1299 check_parse!("a[b][c]", expression, Ok(expected_value));
1300 }
1301
1302 #[test]
1303 fn not_index_result_inverts_whole_result() {
1304 let expected_value = Expression::UnaryOperator(
1305 UnaryOperator::Not.nowhere(),
1306 Box::new(
1307 Expression::Index(
1308 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1309 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1310 )
1311 .nowhere(),
1312 ),
1313 )
1314 .nowhere();
1315
1316 check_parse!("!a[b]", expression, Ok(expected_value));
1317 }
1318
1319 #[test]
1320 fn unary_sub_binds_correctly() {
1321 let expected_value = Expression::BinaryOperator(
1322 Box::new(
1323 Expression::UnaryOperator(
1324 UnaryOperator::Sub.nowhere(),
1325 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1326 )
1327 .nowhere(),
1328 ),
1329 BinaryOperator::Add.nowhere(),
1330 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1331 )
1332 .nowhere();
1333
1334 check_parse!("-a + b", expression, Ok(expected_value));
1335 }
1336
1337 #[test]
1338 fn unary_sub_binds_correctly_without_spaces() {
1339 let expected_value = Expression::BinaryOperator(
1340 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1341 BinaryOperator::Add.nowhere(),
1342 Box::new(
1343 Expression::UnaryOperator(
1344 UnaryOperator::Sub.nowhere(),
1345 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1346 )
1347 .nowhere(),
1348 ),
1349 )
1350 .nowhere();
1351
1352 check_parse!("b+-a", expression, Ok(expected_value));
1353 }
1354
1355 #[test]
1356 fn binary_sub_binds_correctly_without_spaces() {
1357 let expected_value = Expression::BinaryOperator(
1358 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1359 BinaryOperator::Sub.nowhere(),
1360 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1361 )
1362 .nowhere();
1363
1364 check_parse!("b-a", expression, Ok(expected_value));
1365 }
1366
1367 #[test]
1368 fn deref_operator_works() {
1369 let expected = Expression::UnaryOperator(
1370 UnaryOperator::Dereference.nowhere(),
1371 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1372 )
1373 .nowhere();
1374
1375 check_parse!("*a", expression, Ok(expected));
1376 }
1377
1378 #[test]
1379 fn deref_operator_precedence() {
1380 let expected = Expression::BinaryOperator(
1381 Box::new(
1382 Expression::UnaryOperator(
1383 UnaryOperator::Dereference.nowhere(),
1384 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1385 )
1386 .nowhere(),
1387 ),
1388 BinaryOperator::Add.nowhere(),
1389 Box::new(Expression::Identifier(ast_path("b")).nowhere()),
1390 )
1391 .nowhere();
1392
1393 check_parse!("*a + b", expression, Ok(expected));
1394 }
1395
1396 #[test]
1397 fn ref_operator_works() {
1398 let expected = Expression::UnaryOperator(
1399 UnaryOperator::Reference.nowhere(),
1400 Box::new(Expression::Identifier(ast_path("a")).nowhere()),
1401 )
1402 .nowhere();
1403
1404 check_parse!("&a", expression, Ok(expected));
1405 }
1406}