diff --git a/crates/codegen/src/expr.rs b/crates/codegen/src/expr.rs index 2b51f26..c6fa873 100644 --- a/crates/codegen/src/expr.rs +++ b/crates/codegen/src/expr.rs @@ -85,7 +85,7 @@ impl GenRust for Expression { prefixes, postfixes, } => { - cg.add(&prefixes.get_rust()); + prefixes.gen_rust(ctx, cg); initial.gen_rust(ctx, cg); cg.add(&Some(prefixes).get_rust()); for postfix in postfixes { @@ -110,23 +110,41 @@ impl GenRust for Expression { } } -impl GetRust for Prefix { - fn get_rust(&self) -> String { +impl GenRust for Prefix { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { match self { - Self::Deref => "*", - Self::Ref => "&", - Self::RefMut => "&mut ", - Self::Not => "!", - Self::New(_) => "", - Self::Neg => "-", + Self::Deref => cg.add("*"), + Self::Ref => cg.add("&"), + Self::RefMut => cg.add("&mut "), + Self::Not => cg.add("!"), + Self::New(_) => cg.add(""), + Self::Neg => cg.add("-"), + Self::Closure(ty, args) => { + cg.add("|"); + for (i, arg) in args.iter().enumerate() { + if i > 0 { + cg.add(", "); + } + + arg.gen_rust(ctx, cg); + } + cg.add("| "); + + if let Some(ty) = ty { + cg.add("-> "); + cg.add(&ty.get_rust()); + cg.add(" "); + } + } } - .to_string() } } -impl GetRust for Vec { - fn get_rust(&self) -> String { - self.into_iter().map(Prefix::get_rust).collect() +impl GenRust for Vec { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + for prefix in self { + prefix.gen_rust(ctx, cg); + } } } diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 220cde2..ff34768 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -94,6 +94,17 @@ impl RustCodegen { } } } + + pub fn ensure_brackets_body(&mut self, ctx: &mut Context, body: &StatementBody) { + match body { + StatementBody::Expression(expr) => self.ensure_brackets_expr(ctx, expr), + + StatementBody::Statement(expr) => { + ctx.expr_ensure_semicolon = true; + self.ensure_brackets_expr(ctx, expr); + } + } + } } impl GenRust for Attribute { diff --git a/crates/codegen/src/statement.rs b/crates/codegen/src/statement.rs index 8f16fcb..e55bf4c 100644 --- a/crates/codegen/src/statement.rs +++ b/crates/codegen/src/statement.rs @@ -26,6 +26,18 @@ impl GenRust for Block { } } +impl GenRust for StatementBody { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + match self { + Self::Expression(expr) => expr.gen_rust(ctx, cg), + Self::Statement(stmt) => { + ctx.expr_ensure_semicolon = true; + stmt.gen_rust(ctx, cg); + } + } + } +} + impl GenRust for Statement { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { match self { @@ -76,18 +88,18 @@ impl GenRust for Statement { cg.add("if "); initial.condition.gen_rust(ctx, cg); cg.add(" "); - cg.ensure_brackets_expr(ctx, &initial.body); + cg.ensure_brackets_body(ctx, &initial.body); for else_if_branch in else_if { cg.add("else if"); else_if_branch.condition.gen_rust(ctx, cg); cg.add(" "); - cg.ensure_brackets_expr(ctx, &else_if_branch.body); + cg.ensure_brackets_body(ctx, &else_if_branch.body); } if let Some(else_br) = else_branch { cg.add(" else "); - cg.ensure_brackets_expr(ctx, else_br); + cg.ensure_brackets_body(ctx, else_br); } } @@ -95,12 +107,12 @@ impl GenRust for Statement { cg.add("while "); condition.gen_rust(ctx, cg); cg.add(" "); - cg.ensure_brackets_expr(ctx, body); + cg.ensure_brackets_body(ctx, body); } Statement::Loop(body) => { cg.add("loop "); - cg.ensure_brackets_expr(ctx, body); + cg.ensure_brackets_body(ctx, body); } Statement::CStyleFor { @@ -156,7 +168,7 @@ impl GenRust for Statement { pattern.gen_rust(ctx, cg); cg.add(" in "); iterator.gen_rust(ctx, cg); - cg.ensure_brackets_expr(ctx, body); + cg.ensure_brackets_body(ctx, body); } Statement::Return(expr) => { diff --git a/crates/parser/src/ast/expr.rs b/crates/parser/src/ast/expr.rs index 75583e0..1c6eb6b 100644 --- a/crates/parser/src/ast/expr.rs +++ b/crates/parser/src/ast/expr.rs @@ -62,6 +62,7 @@ pub enum Prefix { New(Option), Not, Neg, + Closure(Option, Vec), } #[derive(Debug, Clone, Serialize)] diff --git a/crates/parser/src/ast/statement.rs b/crates/parser/src/ast/statement.rs index f0682c5..d4102ea 100644 --- a/crates/parser/src/ast/statement.rs +++ b/crates/parser/src/ast/statement.rs @@ -8,27 +8,33 @@ pub struct Block( pub Option>, ); +#[derive(Debug, Clone, Serialize)] +pub enum StatementBody { + Statement(Expression), + Expression(Expression), +} + #[derive(Debug, Clone, Serialize)] pub enum Statement { Block(Block), If { initial: StatementBranch, else_if: Vec, - else_branch: Option>, + else_branch: Option, }, - Loop(Expression), + Loop(StatementBody), While(StatementBranch), CStyleFor { init: Expression, condition: Expression, update: Expression, - body: Expression, + body: StatementBody, }, For { mutable: bool, pattern: Pattern, iterator: Expression, - body: Box, + body: StatementBody, }, Match(Expression, Vec<(Vec, Expression)>), @@ -54,28 +60,28 @@ pub struct VarDeclStmt { #[derive(Debug, Clone, Serialize)] pub struct StatementBranch { pub condition: Expression, - pub body: Box, + pub body: Box, } impl Statement { pub fn is_block(&self) -> bool { match self { - Self::Block(_) => true, - Self::If { - initial, - else_if, - else_branch, - } => { - else_branch - .as_ref() - .map(|v| v.is_block()) - .unwrap_or_default() - || else_if - .last() - .map(|b| b.body.is_block()) - .unwrap_or_default() - || initial.body.is_block() - } + Self::Block(_) + | Self::Match(_, _) + | Self::While(_) + | Self::For { .. } + | Self::Loop(..) + | Self::CStyleFor { .. } + | Self::If { .. } => true, + _ => false, + } + } +} + +impl StatementBody { + pub fn is_soft_return(&self) -> bool { + match self { + Self::Expression(_) => true, _ => false, } } diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 5a87ca1..6651ae5 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -91,7 +91,7 @@ generics = { "<" ~ (generic ~ ("," ~ generic)*)? ~ ">" } // ====================================================== tuple_type = { - "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" + "[" ~ (type_expr ~ ("," ~ type_expr)*)? ~ "]" } path_type = { @@ -343,6 +343,10 @@ statement = _{ | (expr ~ semicolon) } +statement_wrapper = { statement } + +statement_body = { statement_wrapper | expr } + // ------------------------------------------------------ // BASIC STATEMENTS // ------------------------------------------------------ @@ -384,7 +388,7 @@ control_flow = { | block } -statement_branch = { "(" ~ expr ~ ")" ~ statement } +statement_branch = { "(" ~ expr ~ ")" ~ statement_body } else_if = { "else" ~ "if" ~ statement_branch @@ -395,7 +399,7 @@ else_if_list = { } if_stmt = { - "if" ~ statement_branch ~ else_if_list ~ ("else" ~ statement)? + "if" ~ statement_branch ~ else_if_list ~ ("else" ~ statement_body)? } // ------------------------------------------------------ @@ -407,15 +411,15 @@ while_stmt = { } c_for_stmt = { - "for" ~ "(" ~ statement ~ statement ~ expr ~ ")" ~ statement + "for" ~ "(" ~ statement ~ statement ~ expr ~ ")" ~ statement_body } for_stmt = { - "for" ~ "(" ~ mutable? ~ pattern ~ ":" ~ expr ~ ")" ~ statement + "for" ~ "(" ~ mutable? ~ pattern ~ ":" ~ expr ~ ")" ~ statement_body } loop_stmt = { - "loop" ~ statement + "loop" ~ statement_body } // ------------------------------------------------------ @@ -436,6 +440,12 @@ match_stmt = { // EXPRESSIONS // ====================================================== +// ------------------------------------------------------ +// CLOSURES +// ------------------------------------------------------ + +closure = { type_expr? ~ "|" ~ param_list ~ "|" } + // ------------------------------------------------------ // TUPLES & ARRAYS // ------------------------------------------------------ @@ -549,7 +559,8 @@ not_px = { "!" } neg_px = { "-" } prefix = { - deref_px + closure + | deref_px | mut_ref_px | ref_px | new_px diff --git a/crates/parser/src/parser/common/expr.rs b/crates/parser/src/parser/common/expr.rs index de33878..2bd9c67 100644 --- a/crates/parser/src/parser/common/expr.rs +++ b/crates/parser/src/parser/common/expr.rs @@ -3,6 +3,7 @@ use crate::{ ast::*, ast_ensure, ast_expr, error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map}, + parser::consume_rule, }; use pest::pratt_parser::PrattParser; use std::sync::OnceLock; @@ -12,7 +13,7 @@ impl<'a> TryFrom> for Expression { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); - let inner = pair.clone().into_inner(); + let mut inner = pair.clone().into_inner(); match rule { Rule::expr => { @@ -78,6 +79,15 @@ impl<'a> TryFrom> for Expression { Rule::static_path => ast_expr!(Expression::Path(pair.try_into())), Rule::literal => ast_expr!(Expression::Literal(pair.try_into())), Rule::expr_path => ast_expr!(Expression::Path(pair.try_into())), + Rule::statement_wrapper => { + let i = inner.next().unwrap(); + match i.as_rule() { + Rule::expr => i.try_into(), + _ => ast_expr!(Expression::Statement( + i.try_into().get_map(Box::new).map(Box::new) + )), + } + } Rule::statement | Rule::basic_stmt | Rule::control_flow => ast_expr!( Expression::Statement(pair.try_into().get_map(Box::new).map(Box::new)) ), @@ -104,6 +114,16 @@ impl<'a> TryFrom> for Prefix { ), Rule::not_px => Self::Not, Rule::neg_px => Self::Neg, + Rule::closure => { + let mut inner = pair.into_inner(); + + return ast_expr!(Self::Closure( + consume_rule(&mut inner, Rule::type_expr) + .map(TypeExpr::try_from) + .transpose(), + collect_recovered(inner.next().unwrap().into_inner()) + )); + } _ => return AstError::bug_unimplemented(pair), }) diff --git a/crates/parser/src/parser/common/statement.rs b/crates/parser/src/parser/common/statement.rs index 7ed8227..3f2db09 100644 --- a/crates/parser/src/parser/common/statement.rs +++ b/crates/parser/src/parser/common/statement.rs @@ -18,6 +18,24 @@ impl<'a> TryFrom> for Block { } } +impl<'a> TryFrom> for StatementBody { + type Error = AstError<'a, Self>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let mut inner = pair.clone().into_inner(); + + ast_ensure!(pair, Rule::statement_body => { + let i = inner.next().unwrap(); + + match i.as_rule() { + Rule::expr => ast_expr!(StatementBody::Expression(i.try_into())), + Rule::statement_wrapper => ast_expr!(StatementBody::Statement(i.try_into())), + _ => AstError::bug_unimplemented(i), + } + }) + } +} + impl<'a> TryFrom> for StatementBranch { type Error = AstError<'a, Self>; @@ -63,12 +81,7 @@ impl<'a> TryFrom> for Statement { ast_expr!(Statement::If { initial: inner.next().unwrap().try_into(), else_if: collect_recovered(inner.next().unwrap().into_inner()), - else_branch: inner - .next() - .map(Expression::try_from) - .transpose() - .map(|v| v.map(Box::new)) - .get_map(|v| { Some(Box::new(v)) }), + else_branch: inner.next().map(StatementBody::try_from).transpose(), }) } @@ -87,7 +100,7 @@ impl<'a> TryFrom> for Statement { mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>, pattern: inner.next().unwrap().try_into(), iterator: inner.next().unwrap().try_into(), - body: inner.next().unwrap().try_into().map(Box::new), + body: inner.next().unwrap().try_into(), }), Rule::match_stmt => ast_expr!(Statement::Match( diff --git a/mist-test/src/event.mist b/mist-test/src/event.mist index 6340bf4..61a1292 100644 --- a/mist-test/src/event.mist +++ b/mist-test/src/event.mist @@ -1,7 +1,7 @@ pub enum Event { Startup, Shutdown, - TaskExecuted(String), - PluginLoaded(String), - Error(String), + TaskExecuted[String], + PluginLoaded[String], + Error[String], } \ No newline at end of file diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 3729e97..59ecadb 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -9,4 +9,20 @@ void main() { app_instance.boot(); app_instance.run(); -} \ No newline at end of file +} + +void do_stuff() { + vec!(1, 2, 3).into_iter().map(Option |var v| {Some(v)}).collect::>(); + + if (43==69) testing1(); +} + +i32 testing1() { + + i32 v = if (0 == 0) { + 0 + } else { + 1 + }; + v +}