Merge pull request #21 from mist-go/improved-statements

Improved statements
This commit is contained in:
2026-05-05 18:14:18 +02:00
committed by GitHub
5 changed files with 163 additions and 88 deletions
+20 -23
View File
@@ -1,9 +1,7 @@
use std::collections::HashMap;
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
pub struct FieldList(pub HashMap<String, (bool, TypeExpr)>);
pub struct FieldList(pub Vec<(String, bool, TypeExpr)>);
#[derive(Debug, Clone, Serialize)]
pub struct ParamList(pub Vec<VarDecl>);
@@ -83,7 +81,7 @@ pub enum Postfix {
FieldAccess(String),
Call(Vec<Expression>),
MacroCall(String),
StructCall(HashMap<String, Expression>),
StructCall(Vec<(String, Expression)>),
Index(Expression),
Binary(BinaryOp, Expression),
}
@@ -102,9 +100,23 @@ pub enum Statement {
VarDecl(VarDeclStmt),
VarAssign(VarAssignStmt),
If(IfStmt),
While(WhileStmt),
For(ForStmt),
If {
initial: StatementBranch,
else_if: Vec<StatementBranch>,
else_branch: Option<Box<Statement>>,
},
While(StatementBranch),
CStyleFor {
init: Box<Statement>,
condition: Expression,
update: Box<Statement>,
body: Box<Statement>,
},
For {
pattern: String,
iterator: Expression,
body: Box<Statement>,
},
Return(Option<Expression>),
Break,
@@ -131,23 +143,8 @@ pub struct VarAssignStmt {
}
#[derive(Debug, Clone, Serialize)]
pub struct IfStmt {
pub struct StatementBranch {
pub condition: Expression,
pub then_branch: Box<Statement>,
pub else_branch: Option<Box<Statement>>,
}
#[derive(Debug, Clone, Serialize)]
pub struct WhileStmt {
pub condition: Expression,
pub body: Box<Statement>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ForStmt {
pub init: (bool, String, Option<Expression>),
pub condition: Option<Expression>,
pub update: Option<Box<Statement>>,
pub body: Box<Statement>,
}
+25 -9
View File
@@ -15,7 +15,9 @@ static_path = { identifier ~ ("::" ~ identifier)* }
export = { "public" }
mutable = { "mut" }
sharp = _{ "#" }
var_decl = { type_expr ~ mutable? ~ identifier }
var = { "var" }
var_decl = { (var | type_expr) ~ mutable? ~ identifier }
semicolon = _{ ";" }
// ================= TOP LEVEL =================
@@ -66,6 +68,8 @@ statement = _{
| assign_statement
| if_stmt
| while_stmt
| c_for_stmt
| for_stmt
| return_stmt
| break_stmt
| continue_stmt
@@ -74,26 +78,38 @@ statement = _{
// --- basic statements ---
expr_stmt = { expr ~ ";" }
expr_stmt = { expr ~ semicolon }
return_stmt = { "return" ~ expr? ~ ";" }
return_stmt = { "return" ~ expr? ~ semicolon }
break_stmt = { "break" ~ ";" }
break_stmt = { "break" ~ semicolon }
continue_stmt = { "continue" ~ ";" }
continue_stmt = { "continue" ~ semicolon }
var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ ";" }
var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ semicolon }
assign_statement = { expr ~ "=" ~ expr ~ ";" }
assign_statement = { expr ~ "=" ~ expr ~ semicolon }
else_if = { "else" ~ "if" ~ "(" ~ expr ~ ")" ~ statement }
else_if_list = { else_if* }
if_stmt = {
"if" ~ "(" ~ expr ~ ")" ~ statement ~ ("else" ~ statement)?
"if" ~ "(" ~ expr ~ ")" ~ statement ~ else_if_list ~ ("else" ~ statement)?
}
while_stmt = {
"while" ~ "(" ~ expr ~ ")" ~ statement
}
c_for_stmt = {
"for" ~ "(" ~ statement ~ expr ~ semicolon ~ statement ~ ")" ~ statement
}
for_stmt = {
"for" ~ "(" ~ identifier ~ "in" ~ expr ~ ")" ~ statement
}
// ================= EXPRESSIONS =================
tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" }
path_type = { static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? }
@@ -131,7 +147,7 @@ macro_call_px = { "!" ~ "(" ~ macro_inner_v* ~ ")" }
struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" }
index_px = { "[" ~ expr ~ "]" }
binary_px = { bin_op ~ expr }
bin_op = { "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | ">" | "<=" | ">=" }
bin_op = { "<=" | ">=" | "==" | "!=" | "+" | "-" | "*" | "/" | "%" | "<" | ">" }
struct_field_decl = { identifier ~ ":" ~ expr }
prefix = {
+46 -19
View File
@@ -104,7 +104,7 @@ impl From<pest::iterators::Pair<'_, Rule>> for FieldList {
};
let param_type = TypeExpr::from(param_inner.next().unwrap());
let param_name = param_inner.next().unwrap().as_str().to_string();
(param_name, (export, param_type))
(param_name, export, param_type)
})
.collect();
@@ -196,6 +196,20 @@ impl From<pest::iterators::Pair<'_, Rule>> for TopLevel {
}
}
impl From<pest::iterators::Pair<'_, Rule>> for StatementBranch {
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
let mut inner = pair.into_inner();
let condition = Expression::from(inner.next().unwrap());
let body = Statement::from(inner.next().unwrap());
StatementBranch {
condition,
body: Box::new(body),
}
}
}
impl From<pest::iterators::Pair<'_, Rule>> for TopLevelKind {
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
let rule = pair.as_rule();
@@ -303,27 +317,34 @@ impl From<pest::iterators::Pair<'_, Rule>> for Statement {
Rule::continue_stmt => Statement::Continue,
Rule::if_stmt => {
let condition = Expression::from(inner.next().unwrap());
let then_branch = Statement::from(inner.next().unwrap());
let mut inner = inner.skip(2);
let else_branch = inner.next().map(Statement::from);
Statement::If(IfStmt {
condition,
then_branch: Box::new(then_branch),
else_branch: else_branch.map(Box::new),
})
Statement::If {
initial: pair.into(),
else_if: inner
.next()
.unwrap()
.into_inner()
.map(StatementBranch::from)
.collect(),
else_branch: inner.next().map(Statement::from).map(Box::new),
}
}
Rule::while_stmt => {
let condition = Expression::from(inner.next().unwrap());
let body = Statement::from(inner.next().unwrap());
Rule::while_stmt => Statement::While(pair.into()),
Statement::While(WhileStmt {
condition,
body: Box::new(body),
})
}
Rule::c_for_stmt => Statement::CStyleFor {
init: Box::new(Statement::from(inner.next().unwrap())),
condition: inner.next().unwrap().into(),
update: Box::new(Statement::from(inner.next().unwrap())),
body: Box::new(Statement::from(inner.next().unwrap())),
},
Rule::for_stmt => Statement::For {
pattern: inner.next().unwrap().as_str().to_string(),
iterator: inner.next().unwrap().into(),
body: Box::new(Statement::from(inner.next().unwrap())),
},
Rule::assign_statement => Statement::VarAssign(VarAssignStmt {
target: Expression::from(inner.next().unwrap()),
@@ -495,7 +516,13 @@ impl From<pest::iterators::Pair<'_, Rule>> for VarDecl {
Rule::var_decl => {
let mut inner = pair.into_inner();
let type_ = Some(inner.next().map(TypeExpr::from).unwrap());
let type_ = inner.next().and_then(|pair| {
if pair.as_str().trim() == "var" {
None
} else {
Some(TypeExpr::from(pair))
}
});
let mutable = if inner.peek().unwrap().as_rule() == Rule::mutable {
inner.next();
true
+65 -24
View File
@@ -1,7 +1,7 @@
use parser::ast::{
Attribute, BinaryOp, Block, Expression, IfStmt, Literal, Path, Postfix, Prefix, Statement,
TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl,
VarDeclStmt, WhileStmt,
Attribute, BinaryOp, Block, Expression, Literal, Path, Postfix, Prefix, Statement,
StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt,
VarDecl, VarDeclStmt,
};
// ---------------------------------------------------------------------------
@@ -61,6 +61,19 @@ impl RustCodegen {
}
self.output.clone()
}
pub fn ensure_brackets(&mut self, stmt: &Statement) {
match stmt {
Statement::Block(_) => stmt.to_rust(self),
_ => {
self.add_indentedln("{");
self.indent += 1;
stmt.to_rust(self);
self.indent -= 1;
self.add_indentedln("}");
}
}
}
}
impl Default for RustCodegen {
@@ -202,7 +215,7 @@ impl GetRust for Postfix {
BinaryOp::LessThanOrEqual => "<=",
BinaryOp::GreaterThanOrEqual => ">=",
};
format!("{} {}", op_str, rhs.get_rust())
format!(" {} {}", op_str, rhs.get_rust())
}
}
}
@@ -284,7 +297,7 @@ impl ToRust for TopLevelKind {
cg.addln(&format!("{}struct {} {{", vis, name));
cg.indent += 1;
for (field_name, (_, ty)) in &fields.0 {
for (field_name, _, ty) in &fields.0 {
let ty = ty.get_rust();
cg.add_indentedln(&format!("pub {}: {},", field_name, ty));
}
@@ -353,36 +366,64 @@ impl ToRust for Statement {
cg.add_indentedln(&format!("{} = {};", target.get_rust(), value.get_rust(),));
}
Statement::If(IfStmt {
condition,
then_branch,
Statement::If {
initial,
else_if,
else_branch,
}) => {
cg.add_indentedln(&format!("if {} {{", condition.get_rust()));
cg.indent += 1;
then_branch.to_rust(cg);
cg.indent -= 1;
cg.add_indentedln("}");
} => {
cg.add_indentedln(&format!("if {}", initial.condition.get_rust()));
cg.ensure_brackets(&initial.body);
for else_if_branch in else_if {
cg.add_indentedln(&format!("else if {}", else_if_branch.condition.get_rust()));
cg.ensure_brackets(&else_if_branch.body);
}
if let Some(else_br) = else_branch {
cg.add_indentedln("else {");
cg.indent += 1;
else_br.to_rust(cg);
cg.indent -= 1;
cg.add_indentedln("}");
cg.add_indentedln("else");
cg.ensure_brackets(else_br);
}
}
Statement::While(WhileStmt { condition, body }) => {
cg.add_indentedln(&format!("while {} {{", condition.get_rust()));
Statement::While(StatementBranch { condition, body }) => {
cg.add_indentedln(&format!("while {}", condition.get_rust()));
cg.ensure_brackets(body);
}
Statement::CStyleFor {
init,
condition,
update,
body,
} => {
cg.add_indentedln("{");
cg.indent += 1;
body.to_rust(cg);
init.to_rust(cg);
cg.add_indentedln(&format!("while {}", condition.get_rust()));
cg.add_indentedln("{");
cg.indent += 1;
cg.ensure_brackets(body);
update.to_rust(cg);
cg.indent -= 1;
cg.add_indentedln("}");
cg.indent -= 1;
cg.add_indentedln("}");
}
Statement::For { .. } => {
cg.add_indentedln("// TODO: transform into iterator-based loop");
Statement::For {
pattern,
iterator,
body,
} => {
cg.add_indentedln(&format!("for {} in {}", pattern, iterator.get_rust()));
cg.ensure_brackets(body);
}
Statement::Return(expr) => {
+4 -10
View File
@@ -1,13 +1,7 @@
#![allow(unused_mut)]
#[derive(Debug)]
public struct ApiCall {
i32 x,
i32 y,
}
void main() {
ApiCall call = ApiCall { x: 10, y: 12 };
var iter = vec!(1, 2, 3, 4, 5);
println!("{call:?}");
for (i in iter) {
println!("{i}");
}
}