Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/cairo-lang-formatter/src/node_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl<'a> SyntaxNodeFormat for SyntaxNode<'a> {
{
true
}
SyntaxKind::TokenMinus | SyntaxKind::TokenMul => {
SyntaxKind::TokenMinus | SyntaxKind::TokenMul | SyntaxKind::TokenAnd => {
matches!(self.grandparent_kind(db), Some(SyntaxKind::ExprUnary))
}
SyntaxKind::TokenPlus
Expand Down
1 change: 1 addition & 0 deletions crates/cairo-lang-parser/src/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use cairo_lang_syntax::node::kind::SyntaxKind;
pub fn get_unary_operator_precedence(kind: SyntaxKind) -> Option<usize> {
match kind {
SyntaxKind::TerminalAt
| SyntaxKind::TerminalAnd
| SyntaxKind::TerminalNot
| SyntaxKind::TerminalBitNot
| SyntaxKind::TerminalMul
Expand Down
6 changes: 6 additions & 0 deletions crates/cairo-lang-parser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,7 @@ impl<'a, 'mt> Parser<'a, 'mt> {
fn expect_unary_operator(&mut self) -> UnaryOperatorGreen<'a> {
match self.peek().kind {
SyntaxKind::TerminalAt => self.take::<TerminalAt<'_>>().into(),
SyntaxKind::TerminalAnd => self.take::<TerminalAnd<'_>>().into(),
SyntaxKind::TerminalNot => self.take::<TerminalNot<'_>>().into(),
SyntaxKind::TerminalBitNot => self.take::<TerminalBitNot<'_>>().into(),
SyntaxKind::TerminalMinus => self.take::<TerminalMinus<'_>>().into(),
Expand Down Expand Up @@ -1706,6 +1707,11 @@ impl<'a, 'mt> Parser<'a, 'mt> {
let expr = self.parse_type_expr();
Ok(ExprUnary::new_green(self.db, op, expr).into())
}
SyntaxKind::TerminalAnd => {
let op = self.take::<TerminalAnd<'_>>().into();
let expr = self.parse_type_expr();
Ok(ExprUnary::new_green(self.db, op, expr).into())
}
SyntaxKind::TerminalIdentifier | SyntaxKind::TerminalDollar => {
Ok(self.parse_type_path().into())
}
Expand Down
1 change: 1 addition & 0 deletions crates/cairo-lang-parser/src/parser_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ cairo_lang_test_utils::test_file_test!(
while_: "while",
for_: "for",
range: "range",
reference: "reference",
use_: "use",
type_alias: "type_alias",
macro_declaration: "macro_declaration",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! > Test binary expression.
//! > Test logical AND and OR

//! > test_runner_name
test_partial_parser_tree(expect_diagnostics: false)
Expand Down Expand Up @@ -42,3 +42,38 @@ ExprBinary
└── segments (kind: ExprPathInner)
└── item #0 (kind: PathSegmentSimple)
└── ident (kind: TokenIdentifier): 'd'

//! > ==========================================================================

//! > Test reference type param with bitwise AND expression

//! > test_runner_name
test_partial_parser_tree(expect_diagnostics: false)

//! > cairo_code
fn foo(a: &u32, b: u32) {
a & &b
}

//! > top_level_kind
ExprBinary

//! > ignored_kinds

//! > expected_diagnostics

//! > expected_tree
└── Top level kind: ExprBinary
├── lhs (kind: ExprPath)
│ ├── dollar (kind: OptionTerminalDollarEmpty) []
│ └── segments (kind: ExprPathInner)
│ └── item #0 (kind: PathSegmentSimple)
│ └── ident (kind: TokenIdentifier): 'a'
├── op (kind: TokenAnd): '&'
└── rhs (kind: ExprUnary)
├── op (kind: TokenAnd): '&'
└── expr (kind: ExprPath)
├── dollar (kind: OptionTerminalDollarEmpty) []
└── segments (kind: ExprPathInner)
└── item #0 (kind: PathSegmentSimple)
└── ident (kind: TokenIdentifier): 'b'
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//! > Test basic reference type

//! > test_runner_name
test_partial_parser_tree(expect_diagnostics: false)

//! > cairo_code
fn f(x: &u32) {}

//! > top_level_kind
ExprUnary

//! > ignored_kinds

//! > expected_diagnostics

//! > expected_tree
└── Top level kind: ExprUnary
├── op (kind: TokenAnd): '&'
└── expr (kind: ExprPath)
├── dollar (kind: OptionTerminalDollarEmpty) []
└── segments (kind: ExprPathInner)
└── item #0 (kind: PathSegmentSimple)
└── ident (kind: TokenIdentifier): 'u32'

//! > ==========================================================================

//! > Test reference of snapshot vs snapshot of reference

//! > test_runner_name
test_partial_parser_tree(expect_diagnostics: false)

//! > cairo_code
fn f(x: &@u32, y: @ &u32) {}

//! > top_level_kind
ParamList

//! > ignored_kinds

//! > expected_diagnostics

//! > expected_tree
└── Top level kind: ParamList
├── item #0 (kind: Param)
│ ├── modifiers (kind: ModifierList) []
│ ├── name (kind: TokenIdentifier): 'x'
│ └── type_clause (kind: TypeClause)
│ ├── colon (kind: TokenColon): ':'
│ └── ty (kind: ExprUnary)
│ ├── op (kind: TokenAnd): '&'
│ └── expr (kind: ExprUnary)
│ ├── op (kind: TokenAt): '@'
│ └── expr (kind: ExprPath)
│ ├── dollar (kind: OptionTerminalDollarEmpty) []
│ └── segments (kind: ExprPathInner)
│ └── item #0 (kind: PathSegmentSimple)
│ └── ident (kind: TokenIdentifier): 'u32'
├── separator #0 (kind: TokenComma): ','
└── item #1 (kind: Param)
├── modifiers (kind: ModifierList) []
├── name (kind: TokenIdentifier): 'y'
└── type_clause (kind: TypeClause)
├── colon (kind: TokenColon): ':'
└── ty (kind: ExprUnary)
├── op (kind: TokenAt): '@'
└── expr (kind: ExprUnary)
├── op (kind: TokenAnd): '&'
└── expr (kind: ExprPath)
├── dollar (kind: OptionTerminalDollarEmpty) []
└── segments (kind: ExprPathInner)
└── item #0 (kind: PathSegmentSimple)
└── ident (kind: TokenIdentifier): 'u32'

//! > ==========================================================================

//! > Test reference inside generics

//! > test_runner_name
test_partial_parser_tree(expect_diagnostics: false)

//! > cairo_code
fn f() -> Option< &u64> {}

//! > top_level_kind
ExprUnary

//! > ignored_kinds

//! > expected_diagnostics

//! > expected_tree
└── Top level kind: ExprUnary
├── op (kind: TokenAnd): '&'
└── expr (kind: ExprPath)
├── dollar (kind: OptionTerminalDollarEmpty) []
└── segments (kind: ExprPathInner)
└── item #0 (kind: PathSegmentSimple)
└── ident (kind: TokenIdentifier): 'u64'
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ test_partial_parser_tree_with_trivia(expect_diagnostics: true)
//! > cairo_code
fn foo() {
#[aaa]
&
/
}

//! > top_level_kind
Expand All @@ -1002,7 +1002,7 @@ error: Missing tokens. Expected a statement after attributes.

error: Skipped tokens. Expected: statement.
--> dummy_file.cairo:3:5
&
/
^

//! > expected_tree
Expand All @@ -1028,7 +1028,7 @@ error: Skipped tokens. Expected: statement.
│ │ ├── arguments (kind: OptionArgListParenthesizedEmpty) []
│ │ └── rbrack (kind: TerminalRBrack) <ignored>
│ ├── child #1 (kind: TokenWhitespace).
│ ├── child #2 (kind: TokenSkipped): '&'
│ ├── child #2 (kind: TokenSkipped): '/'
│ └── child #3 (kind: TokenNewline).
├── token (kind: TokenRBrace): '}'
└── trailing_trivia (kind: Trivia) []
Expand All @@ -1042,7 +1042,7 @@ test_partial_parser_tree_with_trivia(expect_diagnostics: true)

//! > cairo_code
fn foo() {
&
/
#[aaa]
}

Expand All @@ -1061,7 +1061,7 @@ TerminalSemicolon
//! > expected_diagnostics
error: Skipped tokens. Expected: statement.
--> dummy_file.cairo:2:5
&
/
^

error: Missing tokens. Expected a statement after attributes.
Expand All @@ -1082,7 +1082,7 @@ error: Missing tokens. Expected a statement after attributes.
│ ├── hash (kind: TerminalHash)
│ │ ├── leading_trivia (kind: Trivia)
│ │ │ ├── child #0 (kind: TokenWhitespace).
│ │ │ ├── child #1 (kind: TokenSkipped): '&'
│ │ │ ├── child #1 (kind: TokenSkipped): '/'
│ │ │ ├── child #2 (kind: TokenNewline).
│ │ │ └── child #3 (kind: TokenWhitespace).
│ │ ├── token (kind: TokenHash): '#'
Expand Down Expand Up @@ -1111,7 +1111,7 @@ test_partial_parser_tree_with_trivia(expect_diagnostics: true)
//! > cairo_code
fn foo() {
#[aaa]
&
/
#[bbb]
}

Expand All @@ -1135,7 +1135,7 @@ error: Missing tokens. Expected a statement after attributes.

error: Skipped tokens. Expected: statement.
--> dummy_file.cairo:3:5
&
/
^

error: Missing tokens. Expected a statement after attributes.
Expand Down Expand Up @@ -1176,7 +1176,7 @@ error: Missing tokens. Expected a statement after attributes.
│ │ │ │ ├── arguments (kind: OptionArgListParenthesizedEmpty) []
│ │ │ │ └── rbrack (kind: TerminalRBrack) <ignored>
│ │ │ ├── child #1 (kind: TokenWhitespace).
│ │ │ ├── child #2 (kind: TokenSkipped): '&'
│ │ │ ├── child #2 (kind: TokenSkipped): '/'
│ │ │ ├── child #3 (kind: TokenNewline).
│ │ │ └── child #4 (kind: TokenWhitespace).
│ │ ├── token (kind: TokenHash): '#'
Expand Down
1 change: 1 addition & 0 deletions crates/cairo-lang-semantic/src/corelib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@ pub fn core_unary_operator<'db>(
UnaryOperator::BitNot(_) => (info.bitnot_trt, info.bitnot_fn),
UnaryOperator::At(_) => unreachable!("@ is not an unary operator."),
UnaryOperator::Desnap(_) => unreachable!("* is not an unary operator."),
UnaryOperator::Reference(_) => unreachable!("& is handled before reaching here."),
};
Ok(Ok(get_core_trait_function_infer(db, inference, trait_id, trait_fn, stable_ptr)))
}
Expand Down
1 change: 1 addition & 0 deletions crates/cairo-lang-syntax-codegen/src/cairo_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ pub fn get_spec() -> Vec<Node> {
.node_with_explicit_kind("Minus", "TerminalMinus")
.node_with_explicit_kind("At", "TerminalAt")
.node_with_explicit_kind("Desnap", "TerminalMul")
.node_with_explicit_kind("Reference", "TerminalAnd")
)
.add_struct(StructBuilder::new("ExprBinary")
.node("lhs", "Expr")
Expand Down
19 changes: 19 additions & 0 deletions crates/cairo-lang-syntax/src/node/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2706,6 +2706,7 @@ pub enum UnaryOperator<'db> {
Minus(TerminalMinus<'db>),
At(TerminalAt<'db>),
Desnap(TerminalMul<'db>),
Reference(TerminalAnd<'db>),
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, salsa::Update)]
pub struct UnaryOperatorPtr<'db>(pub SyntaxStablePtrId<'db>);
Expand Down Expand Up @@ -2748,6 +2749,11 @@ impl<'db> From<TerminalMulPtr<'db>> for UnaryOperatorPtr<'db> {
Self(value.0)
}
}
impl<'db> From<TerminalAndPtr<'db>> for UnaryOperatorPtr<'db> {
fn from(value: TerminalAndPtr<'db>) -> Self {
Self(value.0)
}
}
impl<'db> From<TerminalNotGreen<'db>> for UnaryOperatorGreen<'db> {
fn from(value: TerminalNotGreen<'db>) -> Self {
Self(value.0)
Expand All @@ -2773,6 +2779,11 @@ impl<'db> From<TerminalMulGreen<'db>> for UnaryOperatorGreen<'db> {
Self(value.0)
}
}
impl<'db> From<TerminalAndGreen<'db>> for UnaryOperatorGreen<'db> {
fn from(value: TerminalAndGreen<'db>) -> Self {
Self(value.0)
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, salsa::Update)]
pub struct UnaryOperatorGreen<'db>(pub GreenId<'db>);
impl<'db> TypedSyntaxNode<'db> for UnaryOperator<'db> {
Expand All @@ -2796,6 +2807,9 @@ impl<'db> TypedSyntaxNode<'db> for UnaryOperator<'db> {
SyntaxKind::TerminalMul => {
UnaryOperator::Desnap(TerminalMul::from_syntax_node(db, node))
}
SyntaxKind::TerminalAnd => {
UnaryOperator::Reference(TerminalAnd::from_syntax_node(db, node))
}
_ => panic!("Unexpected syntax kind {:?} when constructing {}.", kind, "UnaryOperator"),
}
}
Expand All @@ -2817,6 +2831,9 @@ impl<'db> TypedSyntaxNode<'db> for UnaryOperator<'db> {
SyntaxKind::TerminalMul => {
Some(UnaryOperator::Desnap(TerminalMul::from_syntax_node(db, node)))
}
SyntaxKind::TerminalAnd => {
Some(UnaryOperator::Reference(TerminalAnd::from_syntax_node(db, node)))
}
_ => None,
}
}
Expand All @@ -2827,6 +2844,7 @@ impl<'db> TypedSyntaxNode<'db> for UnaryOperator<'db> {
UnaryOperator::Minus(x) => x.as_syntax_node(),
UnaryOperator::At(x) => x.as_syntax_node(),
UnaryOperator::Desnap(x) => x.as_syntax_node(),
UnaryOperator::Reference(x) => x.as_syntax_node(),
}
}
fn stable_ptr(&self, db: &'db dyn Database) -> Self::StablePtr {
Expand All @@ -2843,6 +2861,7 @@ impl<'db> UnaryOperator<'db> {
| SyntaxKind::TerminalMinus
| SyntaxKind::TerminalAt
| SyntaxKind::TerminalMul
| SyntaxKind::TerminalAnd
)
}
}
Expand Down
Loading