Skip to content

Commit

Permalink
unsafe block
Browse files Browse the repository at this point in the history
  • Loading branch information
Grant Wuerker committed Mar 9, 2024
1 parent 65f3804 commit 5e2cf56
Show file tree
Hide file tree
Showing 15 changed files with 281 additions and 11 deletions.
2 changes: 1 addition & 1 deletion crates/hir-analysis/src/name_resolution/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> {
expr: ExprId,
expr_data: &Expr,
) {
if matches!(expr_data, Expr::Block(_)) {
if matches!(expr_data, Expr::Block { .. }) {
walk_expr(self, ctxt, expr)
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/hir/src/hir_def/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl<'db> Visitor for BlockOrderCalculator<'db> {
expr: ExprId,
expr_data: &Expr,
) {
if ctxt.body() == self.body && matches!(expr_data, Expr::Block(..)) {
if ctxt.body() == self.body && matches!(expr_data, Expr::Block { .. }) {
self.order.insert(expr, self.fresh_number);
self.fresh_number += 1;
}
Expand Down
5 changes: 4 additions & 1 deletion crates/hir/src/hir_def/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use super::{Body, GenericArgListId, IdentId, IntegerId, LitKind, Partial, PatId,
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Expr {
Lit(LitKind),
Block(Vec<StmtId>),
Block {
stmts: Vec<StmtId>,
is_unsafe: bool,
},
/// The first `ExprId` is the lhs, the second is the rhs.
///
/// and a `BinOp`.
Expand Down
8 changes: 7 additions & 1 deletion crates/hir/src/lower/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ impl Expr {
let stmt = Stmt::push_to_body(ctxt, stmt);
stmts.push(stmt);
}
let expr_id = ctxt.push_expr(Self::Block(stmts), HirOrigin::raw(&ast));
let expr_id = ctxt.push_expr(
Self::Block {
stmts,
is_unsafe: block.unsafe_kw().is_some(),
},
HirOrigin::raw(&ast),
);

for item in block.items() {
ItemKind::lower_ast(ctxt.f_ctxt, item);
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!(
LazyBlockExprSpan,
ast::BlockExpr,
@token {
(unsafe_kw, unsafe_kw),
}
);

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

Expr::Block(stmts) => {
Expr::Block { stmts, .. } => {
let s_graph = ctxt.top_mod().scope_graph(ctxt.db);
let scope = ctxt.scope();
for item in s_graph.child_items(scope) {
Expand Down Expand Up @@ -1987,7 +1987,7 @@ where
/// `scope` is the scope that encloses the expression.
pub fn with_expr(db: &'db dyn HirDb, scope: ScopeId, body: Body, expr: ExprId) -> Self {
let scope_id = match expr.data(db, body) {
Partial::Present(Expr::Block(_)) => ScopeId::Block(body, expr),
Partial::Present(Expr::Block { .. }) => ScopeId::Block(body, expr),
_ => scope,
};

Expand Down
4 changes: 4 additions & 0 deletions crates/parser2/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ impl BlockExpr {
pub fn items(&self) -> impl Iterator<Item = super::Item> {
support::children(self.syntax())
}

pub fn unsafe_kw(&self) -> Option<SyntaxToken> {
support::token(self.syntax(), SK::UnsafeKw)
}
}

ast_node! {
Expand Down
14 changes: 14 additions & 0 deletions crates/parser2/src/parser/expr_atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub(super) fn parse_expr_atom<S: TokenStream>(
match parser.current_kind() {
Some(IfKw) => parser.parse(IfExprScope::default(), None),
Some(MatchKw) => parser.parse(MatchExprScope::default(), None),
Some(UnsafeKw) => parser.parse(BlockExprScope::default(), None),
Some(LBrace) => parser.parse(BlockExprScope::default(), None),
Some(LParen) => parser.parse(ParenScope::default(), None),
Some(LBracket) => parser.parse(ArrayScope::default(), None),
Expand Down Expand Up @@ -53,6 +54,10 @@ define_scope! {
}
impl super::Parse for BlockExprScope {
fn parse<S: TokenStream>(&mut self, parser: &mut Parser<S>) {
if parser.current_kind() == Some(SyntaxKind::UnsafeKw) {
parser.bump_expected(SyntaxKind::UnsafeKw);
}

parser.bump_expected(SyntaxKind::LBrace);

loop {
Expand All @@ -62,6 +67,15 @@ impl super::Parse for BlockExprScope {
break;
}

if let (Some(kind_0), Some(kind_1), Some(kind_2)) = parser.peek_three() {
if kind_0 == SyntaxKind::UnsafeKw
&& (kind_1 == SyntaxKind::LBrace || kind_2 == SyntaxKind::LBrace)
{
parser.parse(BlockExprScope::default(), None);
continue;
}
}

if parser
.current_kind()
.map(SyntaxKind::is_item_head)
Expand Down
7 changes: 7 additions & 0 deletions crates/parser2/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ impl super::Parse for ItemScope {
fn parse<S: TokenStream>(&mut self, parser: &mut Parser<S>) {
use crate::SyntaxKind::*;

// if parser.peek_two() == (Some(UnsafeKw), Some(LBrace)) {
// parser.parse(BlockExprScope::default(), None);
// return;
// } else {
// println!("{:?}", parser.peek_two(),)
// }

let mut checkpoint = attr::parse_attr_list(parser);
let modifier_scope = ItemModifierScope::default();
let modifier = match parser.current_kind() {
Expand Down
7 changes: 7 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,7 @@
unsafe { foo() }

unsafe {
let a = 42
std::evm::mstore(offset: 0, value: a)
return
}
84 changes: 84 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,84 @@
---
source: crates/parser2/tests/syntax_node.rs
expression: node
input_file: crates/parser2/test_files/syntax_node/exprs/unsafe.fe
---
Root@0..97
BlockExpr@0..16
UnsafeKw@0..6 "unsafe"
WhiteSpace@6..7 " "
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"
BlockExpr@18..96
UnsafeKw@18..24 "unsafe"
WhiteSpace@24..25 " "
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..97 "\n"

23 changes: 22 additions & 1 deletion crates/parser2/test_files/syntax_node/items/func.fe
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,25 @@ fn generics1<T: Trait, U>(t: T, u: Option<U>) -> T
t
}

fn decl<T, U>(t: MyStruct<T, U>) -> Result<T, Err> {}
fn decl<T, U>(t: MyStruct<T, U>) -> Result<T, Err> {}

fn foo() {
unsafe {
bar()
}
}

fn foo2() {
unsafe {
bar2()
}
}

// fails due to newlines
// fn foo3() {
// unsafe

// {
// bar3()
// }
// }
90 changes: 87 additions & 3 deletions crates/parser2/test_files/syntax_node/items/func.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ source: crates/parser2/tests/syntax_node.rs
expression: node
input_file: crates/parser2/test_files/syntax_node/items/func.fe
---
Root@0..361
ItemList@0..361
Root@0..561
ItemList@0..462
Item@0..32
Func@0..30
ItemModifier@0..3
Expand Down Expand Up @@ -282,7 +282,7 @@ Root@0..361
Newline@304..305 "\n"
RBrace@305..306 "}"
Newline@306..308 "\n\n"
Item@308..361
Item@308..363
Func@308..361
FnKw@308..310 "fn"
WhiteSpace@310..311 " "
Expand Down Expand Up @@ -348,4 +348,88 @@ Root@0..361
BlockExpr@359..361
LBrace@359..360 "{"
RBrace@360..361 "}"
Newline@361..363 "\n\n"
Item@363..410
Func@363..408
FnKw@363..365 "fn"
WhiteSpace@365..366 " "
Ident@366..369 "foo"
FuncParamList@369..371
LParen@369..370 "("
RParen@370..371 ")"
WhiteSpace@371..372 " "
BlockExpr@372..408
LBrace@372..373 "{"
Newline@373..374 "\n"
WhiteSpace@374..378 " "
BlockExpr@378..406
UnsafeKw@378..384 "unsafe"
WhiteSpace@384..385 " "
LBrace@385..386 "{"
Newline@386..387 "\n"
WhiteSpace@387..395 " "
ExprStmt@395..400
CallExpr@395..400
PathExpr@395..398
Path@395..398
PathSegment@395..398
Ident@395..398 "bar"
CallArgList@398..400
LParen@398..399 "("
RParen@399..400 ")"
Newline@400..401 "\n"
WhiteSpace@401..405 " "
RBrace@405..406 "}"
Newline@406..407 "\n"
RBrace@407..408 "}"
Newline@408..410 "\n\n"
Item@410..462
Func@410..460
FnKw@410..412 "fn"
WhiteSpace@412..413 " "
Ident@413..417 "foo2"
FuncParamList@417..419
LParen@417..418 "("
RParen@418..419 ")"
WhiteSpace@419..420 " "
BlockExpr@420..460
LBrace@420..421 "{"
Newline@421..422 "\n"
WhiteSpace@422..426 " "
BlockExpr@426..458
UnsafeKw@426..432 "unsafe"
WhiteSpace@432..436 " "
LBrace@436..437 "{"
Newline@437..438 "\n"
WhiteSpace@438..446 " "
ExprStmt@446..452
CallExpr@446..452
PathExpr@446..450
Path@446..450
PathSegment@446..450
Ident@446..450 "bar2"
CallArgList@450..452
LParen@450..451 "("
RParen@451..452 ")"
Newline@452..453 "\n"
WhiteSpace@453..457 " "
RBrace@457..458 "}"
Newline@458..459 "\n"
RBrace@459..460 "}"
Newline@460..462 "\n\n"
Comment@462..486 "// fails due to newlines"
Newline@486..487 "\n"
Comment@487..501 "// fn foo3() {"
Newline@501..502 "\n"
Comment@502..515 "// unsafe"
Newline@515..516 "\n"
WhiteSpace@516..520 " "
Newline@520..521 "\n"
Comment@521..529 "// {"
Newline@529..530 "\n"
Comment@530..547 "// bar3()"
Newline@547..548 "\n"
Comment@548..556 "// }"
Newline@556..557 "\n"
Comment@557..561 "// }"

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

let z = unsafe {
foo()
}
Loading

0 comments on commit 5e2cf56

Please sign in to comment.