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
---
[email protected]
[email protected]
[email protected] "unsafe"
[email protected] " "
[email protected]
[email protected] "{"
[email protected] " "
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected] "foo"
[email protected]
[email protected] "("
[email protected] ")"
[email protected] " "
[email protected] "}"
[email protected] "\n\n"
[email protected]
[email protected] "unsafe"
[email protected] " "
[email protected]
[email protected] "{"
[email protected] "\n"
[email protected] " "
[email protected]
[email protected] "let"
[email protected] " "
[email protected]
[email protected]
[email protected]
[email protected] "a"
[email protected] " "
[email protected] "="
[email protected] " "
[email protected]
[email protected]
[email protected] "42"
[email protected] "\n"
[email protected] " "
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected] "std"
[email protected] "::"
[email protected]
[email protected] "evm"
[email protected] "::"
[email protected]
[email protected] "mstore"
[email protected]
[email protected] "("
[email protected]
[email protected] "offset"
[email protected] ":"
[email protected] " "
[email protected]
[email protected]
[email protected] "0"
[email protected] ","
[email protected] " "
[email protected]
[email protected] "value"
[email protected] ":"
[email protected] " "
[email protected]
[email protected]
[email protected]
[email protected] "a"
[email protected] ")"
[email protected] "\n"
[email protected] " "
[email protected]
[email protected] "return"
[email protected] "\n"
[email protected] "}"
[email protected] "\n\n"
[email protected]
[email protected] "unsafe"
[email protected] " "
[email protected]
[email protected]
[email protected]
[email protected] "1"
[email protected] " "
[email protected] "+"
[email protected] " "
[email protected]
[email protected]
[email protected] "1"
[email protected] "\n\n"
[email protected]
[email protected] "unsafe"
[email protected] " "
[email protected]
[email protected]
[email protected]
[email protected]
[email protected] "bar"
[email protected]
[email protected] "("
[email protected] ")"
[email protected] "\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
[email protected]
[email protected] "let"
[email protected] " "
Expand Down Expand Up @@ -298,4 +298,26 @@ [email protected]
[email protected] "0"
[email protected] "\n"
[email protected] "}"
[email protected] "\n\n"
[email protected]
[email protected] "let"
[email protected] " "
[email protected]
[email protected]
[email protected]
[email protected] "x"
[email protected] " "
[email protected] "="
[email protected] " "
[email protected]
[email protected] "unsafe"
[email protected] " "
[email protected]
[email protected]
[email protected]
[email protected]
[email protected] "bar"
[email protected]
[email protected] "("
[email protected] ")"

Loading