Merge pull request #21 from mist-go/improved-statements
Improved statements
This commit is contained in:
+20
-23
@@ -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>,
|
||||
}
|
||||
|
||||
|
||||
+28
-12
@@ -12,10 +12,12 @@ string_lit = { "\"" ~ inner_str ~ "\"" }
|
||||
inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* }
|
||||
static_path = { identifier ~ ("::" ~ identifier)* }
|
||||
|
||||
export = { "public" }
|
||||
mutable = { "mut" }
|
||||
sharp = _{ "#" }
|
||||
var_decl = { type_expr ~ mutable? ~ identifier }
|
||||
export = { "public" }
|
||||
mutable = { "mut" }
|
||||
sharp = _{ "#" }
|
||||
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
@@ -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
@@ -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
@@ -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}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user