diff --git a/compiler/qsc_frontend/src/parse/expr.rs b/compiler/qsc_frontend/src/parse/expr.rs index 0e0aed86c7..203d3864eb 100644 --- a/compiler/qsc_frontend/src/parse/expr.rs +++ b/compiler/qsc_frontend/src/parse/expr.rs @@ -123,7 +123,7 @@ fn expr_base(s: &mut Scanner) -> Result { let body = stmt::block(s)?; Ok(ExprKind::For(vars, Box::new(iter), body)) } else if keyword(s, Keyword::If).is_ok() { - if_kind(s) + expr_if(s) } else if keyword(s, Keyword::Repeat).is_ok() { let body = stmt::block(s)?; keyword(s, Keyword::Until)?; @@ -137,10 +137,7 @@ fn expr_base(s: &mut Scanner) -> Result { } else if keyword(s, Keyword::Return).is_ok() { Ok(ExprKind::Return(Box::new(expr(s)?))) } else if keyword(s, Keyword::Set).is_ok() { - let lhs = expr(s)?; - token(s, TokenKind::Eq)?; - let rhs = expr(s)?; - Ok(ExprKind::Assign(Box::new(lhs), Box::new(rhs))) + expr_set(s) } else if keyword(s, Keyword::While).is_ok() { Ok(ExprKind::While(Box::new(expr(s)?), stmt::block(s)?)) } else if keyword(s, Keyword::Within).is_ok() { @@ -165,13 +162,13 @@ fn expr_base(s: &mut Scanner) -> Result { }) } -fn if_kind(s: &mut Scanner) -> Result { +fn expr_if(s: &mut Scanner) -> Result { let cond = expr(s)?; let body = stmt::block(s)?; - let lo = s.peek().span.lo; + let otherwise = if keyword(s, Keyword::Elif).is_ok() { - Some(if_kind(s)?) + Some(expr_if(s)?) } else if keyword(s, Keyword::Else).is_ok() { Some(ExprKind::Block(stmt::block(s)?)) } else { @@ -188,6 +185,33 @@ fn if_kind(s: &mut Scanner) -> Result { Ok(ExprKind::If(Box::new(cond), body, otherwise)) } +fn expr_set(s: &mut Scanner) -> Result { + let lhs = expr(s)?; + if token(s, TokenKind::Eq).is_ok() { + let rhs = expr(s)?; + Ok(ExprKind::Assign(Box::new(lhs), Box::new(rhs))) + } else if token(s, TokenKind::WSlashEq).is_ok() { + let index = expr(s)?; + token(s, TokenKind::LArrow)?; + let rhs = expr(s)?; + Ok(ExprKind::AssignUpdate( + Box::new(lhs), + Box::new(index), + Box::new(rhs), + )) + } else if let TokenKind::BinOpEq(op) = s.peek().kind { + s.advance(); + let rhs = expr(s)?; + Ok(ExprKind::AssignOp( + closed_bin_op(op), + Box::new(lhs), + Box::new(rhs), + )) + } else { + Err(s.error(ErrorKind::Rule("assignment operator"))) + } +} + fn lit(s: &mut Scanner) -> Result { let lexeme = s.read(); if token(s, TokenKind::BigInt).is_ok() { @@ -276,11 +300,11 @@ fn mixfix_op(name: OpName) -> Option { precedence: 1, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::Or)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::OrL, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::Or), Assoc::Left), precedence: 2, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::And)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::AndL, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::And), Assoc::Left), precedence: 3, }), OpName::Token(TokenKind::EqEq) => Some(MixfixOp { @@ -308,47 +332,47 @@ fn mixfix_op(name: OpName) -> Option { precedence: 4, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::BarBarBar)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::OrB, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::BarBarBar), Assoc::Left), precedence: 5, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::CaretCaretCaret)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::XorB, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::CaretCaretCaret), Assoc::Left), precedence: 6, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::AmpAmpAmp)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::AndB, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::AmpAmpAmp), Assoc::Left), precedence: 7, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::LtLtLt)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::Shl, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::LtLtLt), Assoc::Left), precedence: 8, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::GtGtGt)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::Shr, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::GtGtGt), Assoc::Left), precedence: 8, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::Plus)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::Add, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::Plus), Assoc::Left), precedence: 9, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::Minus)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::Sub, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::Minus), Assoc::Left), precedence: 9, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::Star)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::Mul, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::Star), Assoc::Left), precedence: 10, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::Slash)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::Div, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::Slash), Assoc::Left), precedence: 10, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::Percent)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::Mod, Assoc::Left), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::Percent), Assoc::Left), precedence: 10, }), OpName::Token(TokenKind::ClosedBinOp(ClosedBinOp::Caret)) => Some(MixfixOp { - kind: OpKind::Binary(BinOp::Exp, Assoc::Right), + kind: OpKind::Binary(closed_bin_op(ClosedBinOp::Caret), Assoc::Right), precedence: 12, }), OpName::Token(TokenKind::Open(Delim::Paren)) => Some(MixfixOp { @@ -371,6 +395,24 @@ fn mixfix_op(name: OpName) -> Option { } } +fn closed_bin_op(op: ClosedBinOp) -> BinOp { + match op { + ClosedBinOp::AmpAmpAmp => BinOp::AndB, + ClosedBinOp::And => BinOp::AndL, + ClosedBinOp::BarBarBar => BinOp::OrB, + ClosedBinOp::Caret => BinOp::Exp, + ClosedBinOp::CaretCaretCaret => BinOp::XorB, + ClosedBinOp::GtGtGt => BinOp::Shr, + ClosedBinOp::LtLtLt => BinOp::Shl, + ClosedBinOp::Minus => BinOp::Sub, + ClosedBinOp::Or => BinOp::OrL, + ClosedBinOp::Percent => BinOp::Mod, + ClosedBinOp::Plus => BinOp::Add, + ClosedBinOp::Slash => BinOp::Div, + ClosedBinOp::Star => BinOp::Mul, + } +} + fn field_op(s: &mut Scanner, lhs: Expr) -> Result { Ok(ExprKind::Field(Box::new(lhs), ident(s)?)) } diff --git a/compiler/qsc_frontend/src/parse/expr/tests.rs b/compiler/qsc_frontend/src/parse/expr/tests.rs index afd9481a16..c2ffe2d9fd 100644 --- a/compiler/qsc_frontend/src/parse/expr/tests.rs +++ b/compiler/qsc_frontend/src/parse/expr/tests.rs @@ -2047,6 +2047,1240 @@ fn set() { ); } +#[test] +fn set_bitwise_and() { + check( + expr, + "set x &&&= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 12, + }, + kind: AssignOp( + AndB, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_logical_and() { + check( + expr, + "set x and= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 12, + }, + kind: AssignOp( + AndL, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_bitwise_or() { + check( + expr, + "set x |||= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 12, + }, + kind: AssignOp( + OrB, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_exp() { + check( + expr, + "set x ^= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 10, + }, + kind: AssignOp( + Exp, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_bitwise_xor() { + check( + expr, + "set x ^^^= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 12, + }, + kind: AssignOp( + XorB, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_shr() { + check( + expr, + "set x >>>= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 12, + }, + kind: AssignOp( + Shr, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_shl() { + check( + expr, + "set x <<<= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 12, + }, + kind: AssignOp( + Shl, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 11, + hi: 12, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_sub() { + check( + expr, + "set x -= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 10, + }, + kind: AssignOp( + Sub, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_logical_or() { + check( + expr, + "set x or= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 11, + }, + kind: AssignOp( + OrL, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 10, + hi: 11, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 10, + hi: 11, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 10, + hi: 11, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_mod() { + check( + expr, + "set x %= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 10, + }, + kind: AssignOp( + Mod, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_add() { + check( + expr, + "set x += y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 10, + }, + kind: AssignOp( + Add, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_div() { + check( + expr, + "set x /= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 10, + }, + kind: AssignOp( + Div, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_mul() { + check( + expr, + "set x *= y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 10, + }, + kind: AssignOp( + Mul, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 9, + hi: 10, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + +#[test] +fn set_with_update() { + check( + expr, + "set x w/= i <- y", + &expect![[r#" + Ok( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 0, + hi: 16, + }, + kind: AssignUpdate( + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 4, + hi: 5, + }, + name: "x", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 10, + hi: 11, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 10, + hi: 11, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 10, + hi: 11, + }, + name: "i", + }, + }, + ), + }, + Expr { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 15, + hi: 16, + }, + kind: Path( + Path { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 15, + hi: 16, + }, + namespace: None, + name: Ident { + id: NodeId( + 4294967295, + ), + span: Span { + lo: 15, + hi: 16, + }, + name: "y", + }, + }, + ), + }, + ), + }, + ) + "#]], + ); +} + #[test] fn while_expr() { check(