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;
|
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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-9
@@ -15,7 +15,9 @@ 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
@@ -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
|
||||||
|
|||||||
+64
-23
@@ -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 {
|
||||||
@@ -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
@@ -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}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user