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; use serde::Serialize;
#[derive(Debug, Clone, 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)] #[derive(Debug, Clone, Serialize)]
pub struct ParamList(pub Vec<VarDecl>); pub struct ParamList(pub Vec<VarDecl>);
@@ -83,7 +81,7 @@ pub enum Postfix {
FieldAccess(String), FieldAccess(String),
Call(Vec<Expression>), Call(Vec<Expression>),
MacroCall(String), MacroCall(String),
StructCall(HashMap<String, Expression>), StructCall(Vec<(String, Expression)>),
Index(Expression), Index(Expression),
Binary(BinaryOp, Expression), Binary(BinaryOp, Expression),
} }
@@ -102,9 +100,23 @@ pub enum Statement {
VarDecl(VarDeclStmt), VarDecl(VarDeclStmt),
VarAssign(VarAssignStmt), VarAssign(VarAssignStmt),
If(IfStmt), If {
While(WhileStmt), initial: StatementBranch,
For(ForStmt), 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>), Return(Option<Expression>),
Break, Break,
@@ -131,23 +143,8 @@ pub struct VarAssignStmt {
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct IfStmt { pub struct StatementBranch {
pub condition: Expression, 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>, pub body: Box<Statement>,
} }
+28 -12
View File
@@ -12,10 +12,12 @@ string_lit = { "\"" ~ inner_str ~ "\"" }
inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* } inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* }
static_path = { identifier ~ ("::" ~ identifier)* } static_path = { identifier ~ ("::" ~ identifier)* }
export = { "public" } export = { "public" }
mutable = { "mut" } mutable = { "mut" }
sharp = _{ "#" } sharp = _{ "#" }
var_decl = { type_expr ~ mutable? ~ identifier } var = { "var" }
var_decl = { (var | type_expr) ~ mutable? ~ identifier }
semicolon = _{ ";" }
// ================= TOP LEVEL ================= // ================= TOP LEVEL =================
@@ -66,6 +68,8 @@ statement = _{
| assign_statement | assign_statement
| if_stmt | if_stmt
| while_stmt | while_stmt
| c_for_stmt
| for_stmt
| return_stmt | return_stmt
| break_stmt | break_stmt
| continue_stmt | continue_stmt
@@ -74,26 +78,38 @@ statement = _{
// --- basic statements --- // --- 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_stmt = {
"if" ~ "(" ~ expr ~ ")" ~ statement ~ ("else" ~ statement)? "if" ~ "(" ~ expr ~ ")" ~ statement ~ else_if_list ~ ("else" ~ statement)?
} }
while_stmt = { while_stmt = {
"while" ~ "(" ~ expr ~ ")" ~ statement "while" ~ "(" ~ expr ~ ")" ~ statement
} }
c_for_stmt = {
"for" ~ "(" ~ statement ~ expr ~ semicolon ~ statement ~ ")" ~ statement
}
for_stmt = {
"for" ~ "(" ~ identifier ~ "in" ~ expr ~ ")" ~ statement
}
// ================= EXPRESSIONS ================= // ================= EXPRESSIONS =================
tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" }
path_type = { static_path ~ ("<" ~ (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)*)? ~ ","? ~ "}" } struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" }
index_px = { "[" ~ expr ~ "]" } index_px = { "[" ~ expr ~ "]" }
binary_px = { bin_op ~ expr } binary_px = { bin_op ~ expr }
bin_op = { "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | ">" | "<=" | ">=" } bin_op = { "<=" | ">=" | "==" | "!=" | "+" | "-" | "*" | "/" | "%" | "<" | ">" }
struct_field_decl = { identifier ~ ":" ~ expr } struct_field_decl = { identifier ~ ":" ~ expr }
prefix = { 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_type = TypeExpr::from(param_inner.next().unwrap());
let param_name = param_inner.next().unwrap().as_str().to_string(); let param_name = param_inner.next().unwrap().as_str().to_string();
(param_name, (export, param_type)) (param_name, export, param_type)
}) })
.collect(); .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 { impl From<pest::iterators::Pair<'_, Rule>> for TopLevelKind {
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
let rule = pair.as_rule(); let rule = pair.as_rule();
@@ -303,27 +317,34 @@ impl From<pest::iterators::Pair<'_, Rule>> for Statement {
Rule::continue_stmt => Statement::Continue, Rule::continue_stmt => Statement::Continue,
Rule::if_stmt => { Rule::if_stmt => {
let condition = Expression::from(inner.next().unwrap()); let mut inner = inner.skip(2);
let then_branch = Statement::from(inner.next().unwrap());
let else_branch = inner.next().map(Statement::from); Statement::If {
initial: pair.into(),
Statement::If(IfStmt { else_if: inner
condition, .next()
then_branch: Box::new(then_branch), .unwrap()
else_branch: else_branch.map(Box::new), .into_inner()
}) .map(StatementBranch::from)
.collect(),
else_branch: inner.next().map(Statement::from).map(Box::new),
}
} }
Rule::while_stmt => { Rule::while_stmt => Statement::While(pair.into()),
let condition = Expression::from(inner.next().unwrap());
let body = Statement::from(inner.next().unwrap());
Statement::While(WhileStmt { Rule::c_for_stmt => Statement::CStyleFor {
condition, init: Box::new(Statement::from(inner.next().unwrap())),
body: Box::new(body), 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 { Rule::assign_statement => Statement::VarAssign(VarAssignStmt {
target: Expression::from(inner.next().unwrap()), target: Expression::from(inner.next().unwrap()),
@@ -495,7 +516,13 @@ impl From<pest::iterators::Pair<'_, Rule>> for VarDecl {
Rule::var_decl => { Rule::var_decl => {
let mut inner = pair.into_inner(); 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 { let mutable = if inner.peek().unwrap().as_rule() == Rule::mutable {
inner.next(); inner.next();
true true
+65 -24
View File
@@ -1,7 +1,7 @@
use parser::ast::{ use parser::ast::{
Attribute, BinaryOp, Block, Expression, IfStmt, Literal, Path, Postfix, Prefix, Statement, Attribute, BinaryOp, Block, Expression, Literal, Path, Postfix, Prefix, Statement,
TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt,
VarDeclStmt, WhileStmt, VarDecl, VarDeclStmt,
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -61,6 +61,19 @@ impl RustCodegen {
} }
self.output.clone() 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 { impl Default for RustCodegen {
@@ -202,7 +215,7 @@ impl GetRust for Postfix {
BinaryOp::LessThanOrEqual => "<=", BinaryOp::LessThanOrEqual => "<=",
BinaryOp::GreaterThanOrEqual => ">=", 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.addln(&format!("{}struct {} {{", vis, name));
cg.indent += 1; cg.indent += 1;
for (field_name, (_, ty)) in &fields.0 { for (field_name, _, ty) in &fields.0 {
let ty = ty.get_rust(); let ty = ty.get_rust();
cg.add_indentedln(&format!("pub {}: {},", field_name, ty)); 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(),)); cg.add_indentedln(&format!("{} = {};", target.get_rust(), value.get_rust(),));
} }
Statement::If(IfStmt { Statement::If {
condition, initial,
then_branch, else_if,
else_branch, else_branch,
}) => { } => {
cg.add_indentedln(&format!("if {} {{", condition.get_rust())); cg.add_indentedln(&format!("if {}", initial.condition.get_rust()));
cg.indent += 1; cg.ensure_brackets(&initial.body);
then_branch.to_rust(cg);
cg.indent -= 1; for else_if_branch in else_if {
cg.add_indentedln("}"); 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 { if let Some(else_br) = else_branch {
cg.add_indentedln("else {"); cg.add_indentedln("else");
cg.indent += 1; cg.ensure_brackets(else_br);
else_br.to_rust(cg);
cg.indent -= 1;
cg.add_indentedln("}");
} }
} }
Statement::While(WhileStmt { condition, body }) => { Statement::While(StatementBranch { condition, body }) => {
cg.add_indentedln(&format!("while {} {{", condition.get_rust())); cg.add_indentedln(&format!("while {}", condition.get_rust()));
cg.ensure_brackets(body);
}
Statement::CStyleFor {
init,
condition,
update,
body,
} => {
cg.add_indentedln("{");
cg.indent += 1; 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.indent -= 1;
cg.add_indentedln("}"); cg.add_indentedln("}");
} }
Statement::For { .. } => { Statement::For {
cg.add_indentedln("// TODO: transform into iterator-based loop"); pattern,
iterator,
body,
} => {
cg.add_indentedln(&format!("for {} in {}", pattern, iterator.get_rust()));
cg.ensure_brackets(body);
} }
Statement::Return(expr) => { 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() { 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}");
}
} }