Merge pull request #47 from mist-go/closures-and-bodies

Closures and fix statement bodies
This commit is contained in:
2026-05-24 14:47:32 +02:00
committed by GitHub
10 changed files with 167 additions and 59 deletions
+31 -13
View File
@@ -85,7 +85,7 @@ impl GenRust for Expression {
prefixes, prefixes,
postfixes, postfixes,
} => { } => {
cg.add(&prefixes.get_rust()); prefixes.gen_rust(ctx, cg);
initial.gen_rust(ctx, cg); initial.gen_rust(ctx, cg);
cg.add(&Some(prefixes).get_rust()); cg.add(&Some(prefixes).get_rust());
for postfix in postfixes { for postfix in postfixes {
@@ -110,23 +110,41 @@ impl GenRust for Expression {
} }
} }
impl GetRust for Prefix { impl GenRust for Prefix {
fn get_rust(&self) -> String { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
match self { match self {
Self::Deref => "*", Self::Deref => cg.add("*"),
Self::Ref => "&", Self::Ref => cg.add("&"),
Self::RefMut => "&mut ", Self::RefMut => cg.add("&mut "),
Self::Not => "!", Self::Not => cg.add("!"),
Self::New(_) => "", Self::New(_) => cg.add(""),
Self::Neg => "-", 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<Prefix> { impl GenRust for Vec<Prefix> {
fn get_rust(&self) -> String { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
self.into_iter().map(Prefix::get_rust).collect() for prefix in self {
prefix.gen_rust(ctx, cg);
}
} }
} }
+11
View File
@@ -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 { impl GenRust for Attribute {
+18 -6
View File
@@ -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 { impl GenRust for Statement {
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
match self { match self {
@@ -76,18 +88,18 @@ impl GenRust for Statement {
cg.add("if "); cg.add("if ");
initial.condition.gen_rust(ctx, cg); initial.condition.gen_rust(ctx, cg);
cg.add(" "); cg.add(" ");
cg.ensure_brackets_expr(ctx, &initial.body); cg.ensure_brackets_body(ctx, &initial.body);
for else_if_branch in else_if { for else_if_branch in else_if {
cg.add("else if"); cg.add("else if");
else_if_branch.condition.gen_rust(ctx, cg); else_if_branch.condition.gen_rust(ctx, cg);
cg.add(" "); 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 { if let Some(else_br) = else_branch {
cg.add(" else "); 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 "); cg.add("while ");
condition.gen_rust(ctx, cg); condition.gen_rust(ctx, cg);
cg.add(" "); cg.add(" ");
cg.ensure_brackets_expr(ctx, body); cg.ensure_brackets_body(ctx, body);
} }
Statement::Loop(body) => { Statement::Loop(body) => {
cg.add("loop "); cg.add("loop ");
cg.ensure_brackets_expr(ctx, body); cg.ensure_brackets_body(ctx, body);
} }
Statement::CStyleFor { Statement::CStyleFor {
@@ -156,7 +168,7 @@ impl GenRust for Statement {
pattern.gen_rust(ctx, cg); pattern.gen_rust(ctx, cg);
cg.add(" in "); cg.add(" in ");
iterator.gen_rust(ctx, cg); iterator.gen_rust(ctx, cg);
cg.ensure_brackets_expr(ctx, body); cg.ensure_brackets_body(ctx, body);
} }
Statement::Return(expr) => { Statement::Return(expr) => {
+1
View File
@@ -62,6 +62,7 @@ pub enum Prefix {
New(Option<Generics>), New(Option<Generics>),
Not, Not,
Neg, Neg,
Closure(Option<TypeExpr>, Vec<VarDecl>),
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
+26 -20
View File
@@ -8,27 +8,33 @@ pub struct Block(
pub Option<Spanned<Expression>>, pub Option<Spanned<Expression>>,
); );
#[derive(Debug, Clone, Serialize)]
pub enum StatementBody {
Statement(Expression),
Expression(Expression),
}
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub enum Statement { pub enum Statement {
Block(Block), Block(Block),
If { If {
initial: StatementBranch, initial: StatementBranch,
else_if: Vec<StatementBranch>, else_if: Vec<StatementBranch>,
else_branch: Option<Box<Expression>>, else_branch: Option<StatementBody>,
}, },
Loop(Expression), Loop(StatementBody),
While(StatementBranch), While(StatementBranch),
CStyleFor { CStyleFor {
init: Expression, init: Expression,
condition: Expression, condition: Expression,
update: Expression, update: Expression,
body: Expression, body: StatementBody,
}, },
For { For {
mutable: bool, mutable: bool,
pattern: Pattern, pattern: Pattern,
iterator: Expression, iterator: Expression,
body: Box<Expression>, body: StatementBody,
}, },
Match(Expression, Vec<(Vec<Pattern>, Expression)>), Match(Expression, Vec<(Vec<Pattern>, Expression)>),
@@ -54,28 +60,28 @@ pub struct VarDeclStmt {
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct StatementBranch { pub struct StatementBranch {
pub condition: Expression, pub condition: Expression,
pub body: Box<Expression>, pub body: Box<StatementBody>,
} }
impl Statement { impl Statement {
pub fn is_block(&self) -> bool { pub fn is_block(&self) -> bool {
match self { match self {
Self::Block(_) => true, Self::Block(_)
Self::If { | Self::Match(_, _)
initial, | Self::While(_)
else_if, | Self::For { .. }
else_branch, | Self::Loop(..)
} => { | Self::CStyleFor { .. }
else_branch | Self::If { .. } => true,
.as_ref() _ => false,
.map(|v| v.is_block())
.unwrap_or_default()
|| else_if
.last()
.map(|b| b.body.is_block())
.unwrap_or_default()
|| initial.body.is_block()
} }
}
}
impl StatementBody {
pub fn is_soft_return(&self) -> bool {
match self {
Self::Expression(_) => true,
_ => false, _ => false,
} }
} }
+18 -7
View File
@@ -91,7 +91,7 @@ generics = { "<" ~ (generic ~ ("," ~ generic)*)? ~ ">" }
// ====================================================== // ======================================================
tuple_type = { tuple_type = {
"(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" "[" ~ (type_expr ~ ("," ~ type_expr)*)? ~ "]"
} }
path_type = { path_type = {
@@ -343,6 +343,10 @@ statement = _{
| (expr ~ semicolon) | (expr ~ semicolon)
} }
statement_wrapper = { statement }
statement_body = { statement_wrapper | expr }
// ------------------------------------------------------ // ------------------------------------------------------
// BASIC STATEMENTS // BASIC STATEMENTS
// ------------------------------------------------------ // ------------------------------------------------------
@@ -384,7 +388,7 @@ control_flow = {
| block | block
} }
statement_branch = { "(" ~ expr ~ ")" ~ statement } statement_branch = { "(" ~ expr ~ ")" ~ statement_body }
else_if = { else_if = {
"else" ~ "if" ~ statement_branch "else" ~ "if" ~ statement_branch
@@ -395,7 +399,7 @@ else_if_list = {
} }
if_stmt = { 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 = { c_for_stmt = {
"for" ~ "(" ~ statement ~ statement ~ expr ~ ")" ~ statement "for" ~ "(" ~ statement ~ statement ~ expr ~ ")" ~ statement_body
} }
for_stmt = { for_stmt = {
"for" ~ "(" ~ mutable? ~ pattern ~ ":" ~ expr ~ ")" ~ statement "for" ~ "(" ~ mutable? ~ pattern ~ ":" ~ expr ~ ")" ~ statement_body
} }
loop_stmt = { loop_stmt = {
"loop" ~ statement "loop" ~ statement_body
} }
// ------------------------------------------------------ // ------------------------------------------------------
@@ -436,6 +440,12 @@ match_stmt = {
// EXPRESSIONS // EXPRESSIONS
// ====================================================== // ======================================================
// ------------------------------------------------------
// CLOSURES
// ------------------------------------------------------
closure = { type_expr? ~ "|" ~ param_list ~ "|" }
// ------------------------------------------------------ // ------------------------------------------------------
// TUPLES & ARRAYS // TUPLES & ARRAYS
// ------------------------------------------------------ // ------------------------------------------------------
@@ -549,7 +559,8 @@ not_px = { "!" }
neg_px = { "-" } neg_px = { "-" }
prefix = { prefix = {
deref_px closure
| deref_px
| mut_ref_px | mut_ref_px
| ref_px | ref_px
| new_px | new_px
+21 -1
View File
@@ -3,6 +3,7 @@ use crate::{
ast::*, ast::*,
ast_ensure, ast_expr, ast_ensure, ast_expr,
error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map}, error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map},
parser::consume_rule,
}; };
use pest::pratt_parser::PrattParser; use pest::pratt_parser::PrattParser;
use std::sync::OnceLock; use std::sync::OnceLock;
@@ -12,7 +13,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
let rule = pair.as_rule(); let rule = pair.as_rule();
let inner = pair.clone().into_inner(); let mut inner = pair.clone().into_inner();
match rule { match rule {
Rule::expr => { Rule::expr => {
@@ -78,6 +79,15 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
Rule::static_path => ast_expr!(Expression::Path(pair.try_into())), Rule::static_path => ast_expr!(Expression::Path(pair.try_into())),
Rule::literal => ast_expr!(Expression::Literal(pair.try_into())), Rule::literal => ast_expr!(Expression::Literal(pair.try_into())),
Rule::expr_path => ast_expr!(Expression::Path(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!( Rule::statement | Rule::basic_stmt | Rule::control_flow => ast_expr!(
Expression::Statement(pair.try_into().get_map(Box::new).map(Box::new)) Expression::Statement(pair.try_into().get_map(Box::new).map(Box::new))
), ),
@@ -104,6 +114,16 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Prefix {
), ),
Rule::not_px => Self::Not, Rule::not_px => Self::Not,
Rule::neg_px => Self::Neg, 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), _ => return AstError::bug_unimplemented(pair),
}) })
+20 -7
View File
@@ -18,6 +18,24 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Block {
} }
} }
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBody {
type Error = AstError<'a, Self>;
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
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<pest::iterators::Pair<'a, Rule>> for StatementBranch { impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBranch {
type Error = AstError<'a, Self>; type Error = AstError<'a, Self>;
@@ -63,12 +81,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
ast_expr!(Statement::If { ast_expr!(Statement::If {
initial: inner.next().unwrap().try_into(), initial: inner.next().unwrap().try_into(),
else_if: collect_recovered(inner.next().unwrap().into_inner()), else_if: collect_recovered(inner.next().unwrap().into_inner()),
else_branch: inner else_branch: inner.next().map(StatementBody::try_from).transpose(),
.next()
.map(Expression::try_from)
.transpose()
.map(|v| v.map(Box::new))
.get_map(|v| { Some(Box::new(v)) }),
}) })
} }
@@ -87,7 +100,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>, mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>,
pattern: inner.next().unwrap().try_into(), pattern: inner.next().unwrap().try_into(),
iterator: 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( Rule::match_stmt => ast_expr!(Statement::Match(
+3 -3
View File
@@ -1,7 +1,7 @@
pub enum Event { pub enum Event {
Startup, Startup,
Shutdown, Shutdown,
TaskExecuted(String), TaskExecuted[String],
PluginLoaded(String), PluginLoaded[String],
Error(String), Error[String],
} }
+16
View File
@@ -10,3 +10,19 @@ void main() {
app_instance.boot(); app_instance.boot();
app_instance.run(); app_instance.run();
} }
void do_stuff() {
vec!(1, 2, 3).into_iter().map(Option<i32> |var v| {Some(v)}).collect::<Vec<_>>();
if (43==69) testing1();
}
i32 testing1() {
i32 v = if (0 == 0) {
0
} else {
1
};
v
}