diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 9909b77..38a30f9 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -112,7 +112,66 @@ pub fn class_decl( { let body = method.item.body; - method.item.body = Some(Block(Vec::new(), None)); + method.item.body = Some(Block { + is_unsafe: false, + statements: Vec::new(), + soft_return: Some(Spanned { + line: 1, + column: 1, + item: Expression::Statement(Box::new(Statement::Block(Block { + is_unsafe: true, + statements: vec![Spanned { + line: 1, + column: 1, + item: Expression::Statement(Box::new(Statement::VarDecl( + VarDeclStmt { + decl: VarDecl { + name: Pattern::Path( + false, + Path(vec![Identifier(String::from("func_ptr"))]), + ), + type_: None, + }, + init: Some(Expression::Fix { + initial: Box::new(Expression::Path(ExprPath(vec![ + ExprPathSegment { + ident: Identifier(String::from("self")), + generics: None, + }, + ]))), + prefixes: vec![Prefix::Deref], + postfixes: vec![ + Postfix::FieldAccess( + Identifier(String::from("_m_oop")), + None, + ), + Postfix::TupleFieldAccess(0, None), + Postfix::FieldAccess( + Identifier(String::from("add")), + None, + ), + Postfix::Call(vec![Expression::Path(ExprPath(vec![ + ExprPathSegment { + ident: Identifier(String::from("Self")), + generics: None, + }, + ExprPathSegment { + ident: Identifier(format!( + "__FN_{}", + method.item.name.0.to_uppercase() + )), + generics: None, + }, + ]))]), + ], + }), + }, + ))), + }], + soft_return: None, + }))), + }), + }); method.gen_rust(ctx, cg); method.item.body = body; diff --git a/crates/codegen/src/statement.rs b/crates/codegen/src/statement.rs index fb2d3aa..601b20b 100644 --- a/crates/codegen/src/statement.rs +++ b/crates/codegen/src/statement.rs @@ -6,16 +6,20 @@ use crate::{GenRust, GetRust, RustCodegen}; impl GenRust for Block { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + if self.is_unsafe { + cg.add("unsafe "); + } + cg.addln("{"); cg.indent += 1; - for stmt in &self.0 { + for stmt in &self.statements { ctx.expr_ensure_semicolon = true; stmt.gen_rust(ctx, cg); cg.addln(""); } - if let Some(soft_return) = &self.1 { + if let Some(soft_return) = &self.soft_return { ctx.expr_ensure_semicolon = false; soft_return.gen_rust(ctx, cg); cg.addln(""); diff --git a/crates/parser/src/ast/statement.rs b/crates/parser/src/ast/statement.rs index 412e2f0..e9b41a8 100644 --- a/crates/parser/src/ast/statement.rs +++ b/crates/parser/src/ast/statement.rs @@ -3,10 +3,12 @@ use serde::Serialize; use super::*; #[derive(Debug, Clone, Serialize, Default)] -pub struct Block( - pub Vec>, - pub Option>, -); +pub struct Block { + pub is_unsafe: bool, + + pub statements: Vec>, + pub soft_return: Option>, +} #[derive(Debug, Clone, Serialize)] pub enum StatementBody { diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index e4f33fb..e62dc58 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -63,6 +63,8 @@ static_path = { identifier ~ ("::" ~ identifier)* } +unsafe_kw = { "unsafe" } + // ====================================================== // PROGRAM // ====================================================== @@ -340,7 +342,7 @@ top_level = { // ====================================================== block = { - "{" ~ statement_list ~ expr? ~ "}" + unsafe_kw? ~ "{" ~ statement_list ~ expr? ~ "}" } statement_list = { diff --git a/crates/parser/src/parser/common/statement.rs b/crates/parser/src/parser/common/statement.rs index 5ca288e..1947928 100644 --- a/crates/parser/src/parser/common/statement.rs +++ b/crates/parser/src/parser/common/statement.rs @@ -2,7 +2,8 @@ use crate::{ Rule, ast::*, ast_ensure, ast_expr, - error::{AstError, IntoErr, collect_recovered}, + error::{AstError, AstResult, IntoErr, collect_recovered}, + parser::listen_rule, }; impl<'a> TryFrom> for Block { @@ -12,7 +13,11 @@ impl<'a> TryFrom> for Block { let mut inner = pair.clone().into_inner(); ast_ensure!(pair, Rule::block => { - ast_expr!(Block(collect_recovered(inner.next().unwrap().into_inner()), inner.next().map(Spanned::try_from).transpose())) + ast_expr!(Block { + is_unsafe: Ok(listen_rule(&mut inner, Rule::unsafe_kw)) as AstResult, + statements: collect_recovered(inner.next().unwrap().into_inner()), + soft_return: inner.next().map(Spanned::try_from).transpose(), + }) }) } }