Skip to content

Commit

Permalink
unsafe expr parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Grant Wuerker committed Apr 19, 2024
1 parent 57335f1 commit 1645bf6
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 5 deletions.
2 changes: 2 additions & 0 deletions crates/hir/src/hir_def/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub enum Expr {
/// The first `ExprId` is the scrutinee, the second is the arms.
Match(ExprId, Partial<Vec<MatchArm>>),

Unsafe(ExprId),

/// The `Assign` Expression. The first `ExprId` is the destination of the assignment,
/// and the second `ExprId` is the rhs value of the binding.
Assign(ExprId, ExprId),
Expand Down
5 changes: 5 additions & 0 deletions crates/hir/src/lower/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ impl Expr {
Self::Match(scrutinee, arm)
}

ast::ExprKind::Unsafe(unsafe_expr) => {
let inner = Self::push_to_body_opt(ctxt, unsafe_expr.inner_expr());
Self::Unsafe(inner)
}

ast::ExprKind::Paren(paren) => {
return Self::push_to_body_opt(ctxt, paren.expr());
}
Expand Down
8 changes: 8 additions & 0 deletions crates/hir/src/span/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,14 @@ define_lazy_span_node!(

define_lazy_span_node!(LazyMatchArmSpan);

define_lazy_span_node!(
LazyUnsafeExprSpan,
ast::UnsafeExpr,
@token {
(unsafe_kw, unsafe_kw),
}
);

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub(crate) struct ExprRoot {
expr: ExprId,
Expand Down
4 changes: 4 additions & 0 deletions crates/hir/src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,10 @@ where
}
}

Expr::Unsafe(expr_id) => {
visit_node_in_body!(visitor, ctxt, expr_id, expr);
}

Expr::Assign(left_expr_id, right_expr_id) => {
visit_node_in_body!(visitor, ctxt, left_expr_id, expr);
visit_node_in_body!(visitor, ctxt, right_expr_id, expr);
Expand Down
18 changes: 18 additions & 0 deletions crates/parser2/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ ast_node! {
| SK::LitExpr
| SK::IfExpr
| SK::MatchExpr
| SK::UnsafeExpr
| SK::ParenExpr
| SK::AssignExpr
| SK::AugAssignExpr,
Expand Down Expand Up @@ -50,6 +51,7 @@ impl Expr {
SK::LitExpr => ExprKind::Lit(AstNode::cast(self.syntax().clone()).unwrap()),
SK::IfExpr => ExprKind::If(AstNode::cast(self.syntax().clone()).unwrap()),
SK::MatchExpr => ExprKind::Match(AstNode::cast(self.syntax().clone()).unwrap()),
SK::UnsafeExpr => ExprKind::Unsafe(AstNode::cast(self.syntax().clone()).unwrap()),
SK::ParenExpr => ExprKind::Paren(AstNode::cast(self.syntax().clone()).unwrap()),
SK::AssignExpr => ExprKind::Assign(AstNode::cast(self.syntax().clone()).unwrap()),
SK::AugAssignExpr => ExprKind::AugAssign(AstNode::cast(self.syntax().clone()).unwrap()),
Expand Down Expand Up @@ -326,6 +328,21 @@ impl MatchExpr {
}
}

ast_node! {
/// `unsafe expr`
pub struct UnsafeExpr,
SK::UnsafeExpr
}
impl UnsafeExpr {
pub fn unsafe_kw(&self) -> Option<SyntaxToken> {
support::token(self.syntax(), SK::UnsafeKw)
}

pub fn inner_expr(&self) -> Option<Expr> {
support::child(self.syntax())
}
}

ast_node! {
/// `(expr)`
pub struct ParenExpr,
Expand Down Expand Up @@ -398,6 +415,7 @@ pub enum ExprKind {
ArrayRep(ArrayRepExpr),
If(IfExpr),
Match(MatchExpr),
Unsafe(UnsafeExpr),
Paren(ParenExpr),
Assign(AssignExpr),
AugAssign(AugAssignExpr),
Expand Down
32 changes: 29 additions & 3 deletions crates/parser2/src/parser/expr_atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use super::{
pub(super) fn is_expr_atom_head(kind: SyntaxKind) -> bool {
use SyntaxKind::*;
match kind {
IfKw | MatchKw | LBrace | LParen | LBracket => true,
IfKw | MatchKw | LBrace | LParen | LBracket | UnsafeKw => true,
kind if lit::is_lit(kind) => true,
kind if path::is_path_segment(kind) => true,
_ => false,
Expand All @@ -38,6 +38,7 @@ pub(super) fn parse_expr_atom<S: TokenStream>(
match parser.current_kind() {
Some(IfKw) => parser.parse_cp(IfExprScope::default(), None),
Some(MatchKw) => parser.parse_cp(MatchExprScope::default(), None),
Some(UnsafeKw) => parser.parse_cp(UnsafeExprScope::default(), None),
Some(LBrace) => parser.parse_cp(BlockExprScope::default(), None),
Some(LParen) => parser.parse_cp(ParenScope::default(), None),
Some(LBracket) => parser.parse_cp(ArrayScope::default(), None),
Expand Down Expand Up @@ -83,8 +84,22 @@ impl super::Parse for BlockExprScope {
.map(SyntaxKind::is_item_head)
.unwrap_or_default()
{
parser.parse(ItemScope::default())?;
continue;
let is_item = if parser.current_kind() == Some(SyntaxKind::UnsafeKw) {
parser.dry_run(|parser| {
parser.bump();
parser
.current_kind()
.map(SyntaxKind::is_item_head)
.unwrap_or_default()
})
} else {
true
};

if is_item {
parser.parse(ItemScope::default())?;
continue;
}
}

parse_stmt(parser)?;
Expand Down Expand Up @@ -131,6 +146,17 @@ impl super::Parse for IfExprScope {
}
}

define_scope! { UnsafeExprScope, UnsafeExpr }
impl super::Parse for UnsafeExprScope {
type Error = Recovery<ErrProof>;

fn parse<S: TokenStream>(&mut self, parser: &mut Parser<S>) -> Result<(), Self::Error> {
parser.bump_expected(SyntaxKind::UnsafeKw);

parse_expr(parser)
}
}

define_scope! { MatchExprScope, MatchExpr }
impl super::Parse for MatchExprScope {
type Error = Recovery<ErrProof>;
Expand Down
3 changes: 3 additions & 0 deletions crates/parser2/src/syntax_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ pub enum SyntaxKind {
LitExpr,
/// `if x { 1 } else { 2 }`
IfExpr,
/// `unsafe foo(x)`
UnsafeExpr,
/// `match x { pat => { .. } }`
MatchExpr,
/// `(1 + 2)`
Expand Down Expand Up @@ -632,6 +634,7 @@ impl SyntaxKind {
SyntaxKind::ArrayRepExpr => "array expression",
SyntaxKind::LitExpr => "literal expression",
SyntaxKind::IfExpr => "`if` expression",
SyntaxKind::UnsafeExpr => "`unsafe` expression",
SyntaxKind::MatchExpr => "`match` expression",
SyntaxKind::ParenExpr => "parenthesized expression",
SyntaxKind::AssignExpr => "assignment expression",
Expand Down
11 changes: 11 additions & 0 deletions crates/parser2/test_files/syntax_node/exprs/unsafe.fe
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
unsafe { foo() }

unsafe {
let a = 42
std::evm::mstore(offset: 0, value: a)
return
}

unsafe 1 + 1

unsafe bar()
112 changes: 112 additions & 0 deletions crates/parser2/test_files/syntax_node/exprs/unsafe.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
source: crates/parser2/tests/syntax_node.rs
expression: node
input_file: crates/parser2/test_files/syntax_node/exprs/unsafe.fe
---
Root@0..125
UnsafeExpr@0..16
UnsafeKw@0..6 "unsafe"
WhiteSpace@6..7 " "
BlockExpr@7..16
LBrace@7..8 "{"
WhiteSpace@8..9 " "
ExprStmt@9..14
CallExpr@9..14
PathExpr@9..12
Path@9..12
PathSegment@9..12
Ident@9..12 "foo"
CallArgList@12..14
LParen@12..13 "("
RParen@13..14 ")"
WhiteSpace@14..15 " "
RBrace@15..16 "}"
Newline@16..18 "\n\n"
UnsafeExpr@18..96
UnsafeKw@18..24 "unsafe"
WhiteSpace@24..25 " "
BlockExpr@25..96
LBrace@25..26 "{"
Newline@26..27 "\n"
WhiteSpace@27..31 " "
LetStmt@31..41
LetKw@31..34 "let"
WhiteSpace@34..35 " "
PathPat@35..36
Path@35..36
PathSegment@35..36
Ident@35..36 "a"
WhiteSpace@36..37 " "
Eq@37..38 "="
WhiteSpace@38..39 " "
LitExpr@39..41
Lit@39..41
Int@39..41 "42"
Newline@41..42 "\n"
WhiteSpace@42..46 " "
ExprStmt@46..83
CallExpr@46..83
PathExpr@46..62
Path@46..62
PathSegment@46..49
Ident@46..49 "std"
Colon2@49..51 "::"
PathSegment@51..54
Ident@51..54 "evm"
Colon2@54..56 "::"
PathSegment@56..62
Ident@56..62 "mstore"
CallArgList@62..83
LParen@62..63 "("
CallArg@63..72
Ident@63..69 "offset"
Colon@69..70 ":"
WhiteSpace@70..71 " "
LitExpr@71..72
Lit@71..72
Int@71..72 "0"
Comma@72..73 ","
WhiteSpace@73..74 " "
CallArg@74..82
Ident@74..79 "value"
Colon@79..80 ":"
WhiteSpace@80..81 " "
PathExpr@81..82
Path@81..82
PathSegment@81..82
Ident@81..82 "a"
RParen@82..83 ")"
Newline@83..84 "\n"
WhiteSpace@84..88 " "
ReturnStmt@88..94
ReturnKw@88..94 "return"
Newline@94..95 "\n"
RBrace@95..96 "}"
Newline@96..98 "\n\n"
UnsafeExpr@98..110
UnsafeKw@98..104 "unsafe"
WhiteSpace@104..105 " "
BinExpr@105..110
LitExpr@105..106
Lit@105..106
Int@105..106 "1"
WhiteSpace@106..107 " "
Plus@107..108 "+"
WhiteSpace@108..109 " "
LitExpr@109..110
Lit@109..110
Int@109..110 "1"
Newline@110..112 "\n\n"
UnsafeExpr@112..124
UnsafeKw@112..118 "unsafe"
WhiteSpace@118..119 " "
CallExpr@119..124
PathExpr@119..122
Path@119..122
PathSegment@119..122
Ident@119..122 "bar"
CallArgList@122..124
LParen@122..123 "("
RParen@123..124 ")"
Newline@124..125 "\n"

4 changes: 3 additions & 1 deletion crates/parser2/test_files/syntax_node/stmts/let.fe
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ let x = if b {
let x = match b {
MyEnum::A(x) | MyEnum::B(x) => x
_ => 0
}
}

let x = unsafe bar()
24 changes: 23 additions & 1 deletion crates/parser2/test_files/syntax_node/stmts/let.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ source: crates/parser2/tests/syntax_node.rs
expression: node
input_file: crates/parser2/test_files/syntax_node/stmts/let.fe
---
Root@0..231
Root@0..253
LetStmt@0..5
LetKw@0..3 "let"
WhiteSpace@3..4 " "
Expand Down Expand Up @@ -298,4 +298,26 @@ [email protected]
Int@228..229 "0"
Newline@229..230 "\n"
RBrace@230..231 "}"
Newline@231..233 "\n\n"
LetStmt@233..253
LetKw@233..236 "let"
WhiteSpace@236..237 " "
PathPat@237..238
Path@237..238
PathSegment@237..238
Ident@237..238 "x"
WhiteSpace@238..239 " "
Eq@239..240 "="
WhiteSpace@240..241 " "
UnsafeExpr@241..253
UnsafeKw@241..247 "unsafe"
WhiteSpace@247..248 " "
CallExpr@248..253
PathExpr@248..251
Path@248..251
PathSegment@248..251
Ident@248..251 "bar"
CallArgList@251..253
LParen@251..252 "("
RParen@252..253 ")"

0 comments on commit 1645bf6

Please sign in to comment.