Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unsafe expr parsing #991

Open
wants to merge 1 commit into
base: fe-v2
Choose a base branch
from
Open
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: 2 additions & 0 deletions crates/hir/src/hir_def/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,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 @@ -171,6 +171,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 @@ -201,6 +201,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 @@ -1086,6 +1086,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 @@ -21,7 +21,7 @@ use crate::{
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 @@ -37,6 +37,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 @@ -82,8 +83,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)
g-r-a-n-t marked this conversation as resolved.
Show resolved Hide resolved
.unwrap_or_default()
})
} else {
true
};

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

parse_stmt(parser)?;
Expand Down Expand Up @@ -130,6 +145,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 @@ -634,6 +636,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 ")"

Loading