From 87bc8a0d697399362d7b3946def1a957ae8b780e Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 11:29:01 +0200 Subject: [PATCH 01/11] Rewriting codegen' --- Cargo.lock | 8 +++++ Cargo.toml | 1 + codegen/Cargo.toml | 12 ++++++++ codegen/src/expr.rs | 0 codegen/src/lib.rs | 63 ++++++++++++++++++++++++++++++++++++++++ codegen/src/statement.rs | 0 codegen/src/top_level.rs | 0 7 files changed, 84 insertions(+) create mode 100644 codegen/Cargo.toml create mode 100644 codegen/src/expr.rs create mode 100644 codegen/src/lib.rs create mode 100644 codegen/src/statement.rs create mode 100644 codegen/src/top_level.rs diff --git a/Cargo.lock b/Cargo.lock index 339cb0f..01f0dd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -449,12 +449,20 @@ dependencies = [ "tower-lsp", ] +[[package]] +name = "mist-codegen" +version = "0.1.0" +dependencies = [ + "mist-parser", +] + [[package]] name = "mist-lang" version = "0.0.3-alpha4" dependencies = [ "cargo_metadata", "mist-analyzer", + "mist-codegen", "mist-parser", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index e4e5dc5..f129aae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ serde = { version = "1.0.228", features = ["serde_derive"] } serde_json = "1.0.149" mist-parser = { path = "./parser", version = "0.1.4"} mist-analyzer = { path = "./analyzer", version = "0.0.1"} +mist-codegen = { path = "./codegen", version = "0.1.0"} cargo_metadata = "0.23.1" [[bin]] diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml new file mode 100644 index 0000000..cf2c632 --- /dev/null +++ b/codegen/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "mist-codegen" +version = "0.1.0" +edition = "2024" +description = "The Mist programming language Rust code generator" +license = "Apache-2.0" +repository = "https://github.com/mist-go/mist" +keywords = ["compiler", "language", "mist"] +categories = ["compilers"] + +[dependencies] +mist-parser = { path = "../parser", version = "0.1.4"} diff --git a/codegen/src/expr.rs b/codegen/src/expr.rs new file mode 100644 index 0000000..e69de29 diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs new file mode 100644 index 0000000..71e7ff9 --- /dev/null +++ b/codegen/src/lib.rs @@ -0,0 +1,63 @@ +pub mod expr; +pub mod statement; +pub mod top_level; + +use mist_parser::ast::*; + +pub trait GenRust { + fn get_rust(&self, cg: &mut RustCodegen); +} + +#[derive(Default)] +pub struct RustCodegen { + output: String, + indent: usize, +} + +impl RustCodegen { + pub fn new() -> Self { + Self { + output: String::new(), + indent: 0, + } + } + + fn indent_str(&self) -> String { + " ".repeat(self.indent) + } + + fn add(&mut self, s: &str) { + self.output.push_str(s); + } + + fn addln(&mut self, s: &str) { + self.add(s); + self.add("\n"); + } + + fn add_indentedln(&mut self, s: &str) { + let line = format!("{}{}\n", self.indent_str(), s); + self.add(&line); + } + + pub fn generate(&mut self, toplevels: Vec) -> String { + for tl in toplevels { + tl.to_rust(self); + } + + self.output.clone() + } + + pub fn ensure_brackets(&mut self, stmt: Box) { + match *stmt { + Statement::Block(_) => stmt.to_rust(self), + _ => { + self.add_indentedln("{"); + self.indent += 1; + stmt.to_rust(self); + self.indent -= 1; + self.add_indentedln("}"); + } + } + } +} diff --git a/codegen/src/statement.rs b/codegen/src/statement.rs new file mode 100644 index 0000000..e69de29 diff --git a/codegen/src/top_level.rs b/codegen/src/top_level.rs new file mode 100644 index 0000000..e69de29 From 827b674be2c0fc965d2f8a999a038e86b723263c Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 12:25:06 +0200 Subject: [PATCH 02/11] Expression --- codegen/src/expr.rs | 205 +++++++++++++++++++++++++++++++++++ codegen/src/lib.rs | 149 ++++++++++++++++++++++--- src/codegen.rs | 257 -------------------------------------------- 3 files changed, 338 insertions(+), 273 deletions(-) diff --git a/codegen/src/expr.rs b/codegen/src/expr.rs index e69de29..6a23e14 100644 --- a/codegen/src/expr.rs +++ b/codegen/src/expr.rs @@ -0,0 +1,205 @@ +use mist_parser::ast::*; + +use crate::Context; + +use crate::{GenRust, GetRust, RustCodegen}; + +impl GenRust for Literal { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + match self { + Self::Int(n) => cg.add(&n.to_string()), + Self::Float(n) => cg.add(&format!("{n:?}")), + Self::Bool(b) => cg.add(&b.to_string()), + Self::String(s) => cg.add(&format!("\"{s}\"")), + + Self::Tuple(values) => { + cg.add("("); + + for val in values { + val.gen_rust(ctx, cg); + } + + cg.add(")"); + } + + Self::Array(values) => { + cg.add("["); + + for val in values { + val.gen_rust(ctx, cg); + } + + cg.add("]"); + } + + Self::ArrayRepeat(value, repeat) => { + cg.add("["); + value.gen_rust(ctx, cg); + cg.add("; "); + repeat.gen_rust(ctx, cg); + cg.add("]"); + } + } + } +} + +impl GenRust for Expression { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + match self { + Expression::Path(path) => unimplemented!(), + Expression::Literal(literal) => unimplemented!(), + Expression::Statement(stmt) => stmt.gen_rust(ctx, cg), + Expression::Fix { + initial, + prefixes, + postfixes, + } => { + cg.add(&prefixes.get_rust()); + initial.gen_rust(ctx, cg); + for postfix in postfixes { + postfix.gen_rust(ctx, cg); + } + } + // Safely integrated to handle the tree structure built by the Pratt Parser + Expression::Binary { lhs, op, rhs } => { + lhs.gen_rust(ctx, cg); + cg.add(op); + rhs.gen_rust(ctx, cg); + } + } + } +} + +impl GetRust for Prefix { + fn get_rust(&self) -> String { + match self { + Self::Deref => "*", + Self::Ref => "&", + Self::RefMut => "&mut ", + Self::Not => "!", + Self::New(_) => "", + Self::Neg => "-", + } + .to_string() + } +} + +impl GetRust for Vec { + fn get_rust(&self) -> String { + self.into_iter().map(Prefix::get_rust).collect() + } +} + +impl GetRust for Option> { + fn get_rust(&self) -> String { + if let Some(prefixes) = self { + prefixes + .into_iter() + .last() + .map(|p| match p { + Prefix::New(generics) => format!( + "::new{}", + generics + .clone() + .map(|v| format!("::{}", v.get_rust())) + .unwrap_or_default(), + ), + _ => String::new(), + }) + .unwrap_or_default() + .to_string() + } else { + String::new() + } + } +} + +impl GenRust for Postfix { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + match self { + Postfix::FieldAccess(field, generics) => cg.add(&format!( + ".{}{}", + field.get_rust(), + generics + .iter() + .map(|v| format!("::{}", v.get_rust())) + .collect::() + )), + + Postfix::Call(args) => { + cg.add("("); + + for arg in args { + arg.gen_rust(ctx, cg); + cg.add(", "); + } + + cg.add(")"); + } + + Postfix::MacroCall(inner) => { + cg.add("!("); + cg.add(inner); + cg.add(")"); + } + + Postfix::StructCall(fields) => { + cg.add("{"); + + for (name, expr) in fields { + cg.add(&name.get_rust()); + cg.add(": "); + expr.gen_rust(ctx, cg); + cg.add(","); + } + } + + Postfix::Index(idx) => { + cg.add("["); + idx.gen_rust(ctx, cg); + cg.add("]"); + } + + Postfix::As(ty) => { + cg.add(" as "); + cg.add(&ty.get_rust()); + } + + Postfix::Try => cg.add("?"), + + Postfix::Assign(cmp, expr) => { + cg.add(" "); + cg.add(cmp); + expr.gen_rust(ctx, cg); + } + Postfix::Increment => cg.add("+=1"), + Postfix::Decrement => cg.add("-=1"), + } + } +} + +impl GetRust for Generics { + fn get_rust(&self) -> String { + if self.0.len() == 0 { + String::new() + } else { + format!( + "<{}>", + self.0 + .iter() + .map(Generic::get_rust) + .collect::>() + .join(", ") + ) + } + } +} + +impl GetRust for Generic { + fn get_rust(&self) -> String { + match self { + Self::Lifetime(name) => format!("'{}", name.get_rust()), + Self::Type(ty) => ty.get_rust(), + } + } +} diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 71e7ff9..42b76a0 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -4,8 +4,16 @@ pub mod top_level; use mist_parser::ast::*; +pub struct Context { + pub expr_ensure_semicolon: bool, +} + pub trait GenRust { - fn get_rust(&self, cg: &mut RustCodegen); + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen); +} + +pub trait GetRust { + fn get_rust(&self) -> String; } #[derive(Default)] @@ -40,24 +48,133 @@ impl RustCodegen { self.add(&line); } - pub fn generate(&mut self, toplevels: Vec) -> String { - for tl in toplevels { - tl.to_rust(self); - } + // pub fn generate(&mut self, toplevels: Vec) -> String { + // for tl in toplevels { + // tl.gen_rust(self); + // } - self.output.clone() + // self.output.clone() + // } + + // pub fn ensure_brackets(&mut self, stmt: Box) { + // match *stmt { + // Statement::Block(_) => stmt.gen_rust(self), + // _ => { + // self.add_indentedln("{"); + // self.indent += 1; + // stmt.gen_rust(self); + // self.indent -= 1; + // self.add_indentedln("}"); + // } + // } + // } +} + +impl GetRust for Spanned { + fn get_rust(&self) -> String { + format!( + "/* {}:{} */ {}", + self.line, + self.column, + self.item.get_rust() + ) } +} - pub fn ensure_brackets(&mut self, stmt: Box) { - 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 GenRust for Spanned { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + cg.add_indentedln(&format!("/* {}:{} */", self.line, self.column)); + self.item.gen_rust(ctx, cg); + } +} + +impl GetRust for Path { + fn get_rust(&self) -> String { + self.0 + .iter() + .map(Identifier::get_rust) + .collect::>() + .join("::") + } +} + +impl GetRust for TypePostfix { + fn get_rust(&self) -> String { + match self { + TypePostfix::Ref => format!("&"), + TypePostfix::RefMut => format!("&mut "), + TypePostfix::RefLifetime(lifetime) => format!("&'{} ", lifetime.get_rust()), + TypePostfix::RefMutLifetime(lifetime) => format!("&'{} mut ", lifetime.get_rust()), + TypePostfix::Dyn => format!("dyn "), } } } + +impl GetRust for Visibility { + fn get_rust(&self) -> String { + match self { + Visibility::Public => "pub ".to_string(), + Visibility::PublicTarget(path) => format!("pub({}) ", path.get_rust()), + Visibility::Private => "".to_string(), + } + } +} + +impl GetRust for Identifier { + fn get_rust(&self) -> String { + self.0.clone() + } +} + +impl GetRust for TypeExpr { + fn get_rust(&self) -> String { + self.1 + .iter() + .map(TypePostfix::get_rust) + .rev() + .collect::() + + &self.0.get_rust() + } +} + +pub fn get_static_type_path(path: &Path) -> String { + let rust_path = path.get_rust(); + + if rust_path == "void" { + format!("()") + } else { + rust_path + } +} + +impl GetRust for TypeExprKind { + fn get_rust(&self) -> String { + match self { + TypeExprKind::Path(path) => get_static_type_path(path), + TypeExprKind::Lifetime(name) => format!("'{}", name.get_rust()), + TypeExprKind::PathParams(path, params) => { + format!( + "{}<{}>", + get_static_type_path(path), + params + .into_iter() + .map(|t| t.get_rust()) + .collect::>() + .join(", ") + ) + } + TypeExprKind::Tuple(types) => format!( + "({})", + types + .into_iter() + .map(|t| t.get_rust()) + .collect::>() + .join(", ") + ), + } + } +} + +pub fn get_mutable(mutable: bool) -> String { + if mutable { "mut " } else { "" }.to_string() +} diff --git a/src/codegen.rs b/src/codegen.rs index cc22d83..d449efd 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -133,37 +133,6 @@ impl GetRust for TypeExprKind { } } -impl GetRust for Literal { - fn get_rust(self) -> String { - match self { - Self::Int(n) => n.to_string(), - Self::Float(n) => format!("{n:?}"), - Self::Bool(b) => b.to_string(), - Self::String(s) => format!("\"{s}\""), - Self::Tuple(t) => { - format!( - "({})", - t.into_iter() - .map(Expression::get_rust) - .collect::>() - .join(", ") - ) - } - Self::Array(values) => format!( - "[{}]", - values - .into_iter() - .map(Expression::get_rust) - .collect::>() - .join(", ") - ), - Self::ArrayRepeat(value, repeat) => { - format!("[{}; {}]", value.get_rust(), repeat.get_rust()) - } - } - } -} - impl GetRust for Expression { fn get_rust(self) -> String { match self { @@ -371,232 +340,6 @@ impl GetRust for Attribute { } } -impl ToRust for TopLevelKind { - fn to_rust(self, cg: &mut RustCodegen) { - match self { - Self::ModAttribute => {} - Self::Import(vis, path) => { - cg.addln(&format!("{}use {};", vis.get_rust(), path.get_rust())) - } - Self::Mod(vis, id) => cg.addln(&format!("{}mod {};", vis.get_rust(), id.get_rust())), - Self::FunctionDecl(decl) => decl.to_rust(cg), - Self::ImplDecl(impl_) => impl_.to_rust(cg), - Self::StructDecl { - visibility, - name, - generics, - fields, - } => { - cg.addln(&format!( - "{}struct {}{} {{", - visibility.get_rust(), - name.get_rust(), - generics.get_rust() - )); - cg.indent += 1; - - for field in fields { - cg.add_indentedln(&field.get_rust()); - } - - cg.indent -= 1; - cg.addln("}\n"); - } - Self::EnumDecl { - visibility, - name, - generics, - fields, - } => { - cg.addln(&format!( - "{}enum {}{} {{", - visibility.get_rust(), - name.get_rust(), - generics.get_rust() - )); - cg.indent += 1; - - for field in fields { - cg.add_indentedln(&(field.get_rust() + ",")); - } - - cg.indent -= 1; - cg.addln("}\n"); - } - Self::TraitDecl { - visibility, - name, - generics, - requirements, - items, - } => { - cg.addln(&format!( - "{}trait {}{}{} {{", - visibility.get_rust(), - name.get_rust(), - generics.get_rust(), - if requirements.len() != 0 { - String::from(": ") - + &requirements - .into_iter() - .map(TypeExpr::get_rust) - .collect::>() - .join("+") - } else { - String::new() - }, - )); - cg.indent += 1; - - for item in items { - item.to_rust(cg); - } - - cg.indent -= 1; - cg.addln("}\n"); - } - Self::ClassDecl { - visibility, - name, - generics, - fields, - constructor, - items, - } => { - // Struct decl - cg.addln(&format!( - "{}struct {}{} {{", - visibility.get_rust(), - name.clone().get_rust(), - generics.clone().get_rust() - )); - cg.indent += 1; - - for field in fields.clone() { - cg.add_indentedln(&field.get_comment()); - cg.add_indentedln(&field.item.decl.get_rust()); - } - - cg.indent -= 1; - cg.addln("}\n"); - - // Constructor - cg.addln(&format!( - "impl{} {}{} {{", - generics.clone().get_rust(), - name.clone().get_rust(), - format!( - "<{}>", - generics - .clone() - .0 - .into_iter() - .map(|v| Generic::from(v).get_rust()) - .collect::>() - .join(", ") - ) - )); - cg.indent += 1; - - let constructor_comment = constructor.get_comment(); - - let constructor = constructor.item; - - let params_str = constructor - .params - .0 - .clone() - .into_iter() - .map(VarDecl::get_rust) - .collect::>() - .join(", "); - - cg.add_indentedln("#[allow(invalid_value)]"); - cg.add_indentedln(&constructor_comment); - cg.add_indentedln(&format!( - "{}fn new{}({}) -> Self {{", - constructor.visibility.clone().get_rust(), - constructor.generics.clone().get_rust(), - params_str - )); - cg.indent += 1; - - cg.add_indentedln("let mut this: Self = unsafe { std::mem::MaybeUninit::::zeroed().assume_init() };"); - - for field in fields { - let comment = field.get_comment(); - - if let Some(init) = field.item.init { - cg.add_indentedln(&comment); - - cg.add_indentedln(&format!( - "this.{} = {};", - field.item.decl.name.get_rust(), - init.get_rust() - )); - } - } - - cg.add_indentedln(&format!( - "this.construct_class({});", - constructor - .params - .0 - .into_iter() - .map(|e| e.name.get_rust()) - .collect::>() - .join(", ") - )); - - cg.add_indentedln("this"); - - cg.indent -= 1; - cg.add_indentedln("}\n"); - - // Constructor function - cg.add_indentedln(&constructor_comment); - cg.add_indentedln(&format!( - "{}fn construct_class{}(&mut self, {}) {{", - constructor.visibility.get_rust(), - constructor.generics.get_rust(), - params_str - )); - cg.indent += 1; - - constructor.body.to_rust(cg); - - cg.indent -= 1; - cg.add_indentedln("}\n"); - - for item in items.clone() { - match item { - ClassItem::ImplDecl(_) => {} - ClassItem::Method(method) => method.to_rust(cg), - } - } - - cg.indent -= 1; - cg.addln("}\n"); - - for item in items { - match item { - ClassItem::ImplDecl(impl_) => { - let mut impl_ = impl_.clone(); - - impl_.item.trait_ = Some(impl_.item.target); - impl_.item.target = - TypeExpr(TypeExprKind::Path(Path(vec![name.clone()])), Vec::new()); - - impl_.to_rust(cg); - } - ClassItem::Method(_) => {} - } - } - } - } - } -} - impl ToRust for Statement { fn to_rust(self, cg: &mut RustCodegen) { match self { From 7af64169211f6cb9ddab724136783718aa9d5a7b Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 13:03:46 +0200 Subject: [PATCH 03/11] Statements --- codegen/src/lib.rs | 72 +++++++++++++---- codegen/src/statement.rs | 169 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 14 deletions(-) diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 42b76a0..103e281 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -4,6 +4,10 @@ pub mod top_level; use mist_parser::ast::*; +pub fn get_mutable(mutable: bool) -> String { + if mutable { "mut " } else { "" }.to_string() +} + pub struct Context { pub expr_ensure_semicolon: bool, } @@ -43,6 +47,11 @@ impl RustCodegen { self.add("\n"); } + fn add_indented(&mut self, s: &str) { + let line = format!("{}{}", self.indent_str(), s); + self.add(&line); + } + fn add_indentedln(&mut self, s: &str) { let line = format!("{}{}\n", self.indent_str(), s); self.add(&line); @@ -56,18 +65,18 @@ impl RustCodegen { // self.output.clone() // } - // pub fn ensure_brackets(&mut self, stmt: Box) { - // match *stmt { - // Statement::Block(_) => stmt.gen_rust(self), - // _ => { - // self.add_indentedln("{"); - // self.indent += 1; - // stmt.gen_rust(self); - // self.indent -= 1; - // self.add_indentedln("}"); - // } - // } - // } + pub fn ensure_brackets(&mut self, ctx: &mut Context, stmt: &Box) { + match &**stmt { + Statement::Block(_) => stmt.gen_rust(ctx, self), + _ => { + self.add("{"); + self.indent += 1; + stmt.gen_rust(ctx, self); + self.indent -= 1; + self.add("}"); + } + } + } } impl GetRust for Spanned { @@ -175,6 +184,41 @@ impl GetRust for TypeExprKind { } } -pub fn get_mutable(mutable: bool) -> String { - if mutable { "mut " } else { "" }.to_string() +impl GenRust for Pattern { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + match self { + Self::Id(id) => cg.add(&id.get_rust()), + Self::Path(path) => cg.add(&path.get_rust()), + Self::Literal(lit) => lit.gen_rust(ctx, cg), + + Self::Struct(path, ids) => { + cg.add(&path.get_rust()); + cg.add(" {"); + for id in ids { + cg.add(&id.get_rust()); + cg.add(","); + } + cg.add("}"); + } + + Self::NamedTuple(path, ids) => { + cg.add(&path.get_rust()); + cg.add(" ("); + for id in ids { + cg.add(&id.get_rust()); + cg.add(","); + } + cg.add(")"); + } + + Self::Tuple(ids) => { + cg.add("("); + for id in ids { + cg.add(&id.get_rust()); + cg.add(","); + } + cg.add(")"); + } + } + } } diff --git a/codegen/src/statement.rs b/codegen/src/statement.rs index e69de29..4178c08 100644 --- a/codegen/src/statement.rs +++ b/codegen/src/statement.rs @@ -0,0 +1,169 @@ +use mist_parser::ast::*; + +use crate::{Context, get_mutable}; + +use crate::{GenRust, GetRust, RustCodegen}; + +impl GenRust for Block { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + for stmt in &self.0 { + cg.add_indented(""); + stmt.gen_rust(ctx, cg); + } + + if let Some(soft_return) = &self.1 { + ctx.expr_ensure_semicolon = false; + soft_return.gen_rust(ctx, cg); + ctx.expr_ensure_semicolon = true; + } + } +} + +impl GenRust for Statement { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + match self { + Statement::Block(block) => { + cg.add_indentedln("{"); + cg.indent += 1; + block.gen_rust(ctx, cg); + cg.indent -= 1; + cg.add_indentedln("}"); + } + + Statement::VarDecl(VarDeclStmt { decl, init }) => { + cg.add("let "); + decl.gen_rust(ctx, cg); + + if let Some(init) = init { + cg.add(" = "); + init.gen_rust(ctx, cg); + } + } + + Statement::Match(expr, match_items) => { + cg.add("match "); + expr.gen_rust(ctx, cg); + cg.add(" {"); + cg.indent += 1; + + for (pat, body) in match_items { + for (i, p) in pat.iter().enumerate() { + if i > 0 { + cg.add(" | "); + } + + p.gen_rust(ctx, cg); + } + + cg.add("=> {"); + cg.indent += 1; + + body.gen_rust(ctx, cg); + + cg.indent -= 1; + cg.add_indentedln("}"); + } + + cg.indent -= 1; + cg.add_indentedln("}"); + } + + Statement::If { + initial, + else_if, + else_branch, + } => { + cg.add("if "); + initial.condition.gen_rust(ctx, cg); + cg.ensure_brackets(ctx, &initial.body); + + for else_if_branch in else_if { + cg.add("else if"); + else_if_branch.condition.gen_rust(ctx, cg); + cg.ensure_brackets(ctx, &else_if_branch.body); + } + + if let Some(else_br) = else_branch { + cg.add("else"); + cg.ensure_brackets(ctx, else_br); + } + } + + Statement::While(StatementBranch { condition, body }) => { + cg.add("while "); + condition.gen_rust(ctx, cg); + cg.ensure_brackets(ctx, body); + } + + Statement::CStyleFor { + init, + condition, + update, + body, + } => { + cg.add_indentedln("{"); + cg.indent += 1; + + init.gen_rust(ctx, cg); + + cg.add("while "); + + condition.gen_rust(ctx, cg); + + cg.add("{"); + + cg.indent += 1; + + cg.ensure_brackets(ctx, body); + + update.gen_rust(ctx, cg); + + cg.indent -= 1; + cg.add_indentedln("}"); + + cg.indent -= 1; + cg.add_indentedln("}"); + } + + Statement::For { + mutable, + pattern, + iterator, + body, + } => { + cg.add("for "); + cg.add(&get_mutable(*mutable)); + pattern.gen_rust(ctx, cg); + cg.add(" in "); + iterator.gen_rust(ctx, cg); + cg.ensure_brackets(ctx, body); + } + + Statement::Return(expr) => { + cg.add("return "); + if let Some(expr) = expr { + expr.gen_rust(ctx, cg); + } + } + + Statement::Break => cg.add_indentedln("break"), + Statement::Continue => cg.add_indentedln("continue"), + } + } +} + +impl GenRust for VarDecl { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + cg.add(&get_mutable(self.mutable)); + + self.name.gen_rust(ctx, cg); + + cg.add( + &self + .type_ + .as_ref() + .map(|t| format!(": {}", t.get_rust())) + .unwrap_or_default(), + ); + } +} From 357a25a859f9f8ed220c8879b95f015e47a4eac7 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 13:14:48 +0200 Subject: [PATCH 04/11] base top level --- codegen/src/top_level.rs | 104 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/codegen/src/top_level.rs b/codegen/src/top_level.rs index e69de29..9213687 100644 --- a/codegen/src/top_level.rs +++ b/codegen/src/top_level.rs @@ -0,0 +1,104 @@ +use mist_parser::ast::*; + +use crate::Context; + +use crate::{GenRust, GetRust, RustCodegen}; + +impl GetRust for GenericsDecl { + fn get_rust(&self) -> String { + if self.0.len() == 0 { + String::new() + } else { + format!( + "<{}>", + self.0 + .iter() + .map(|v| v.get_rust()) + .collect::>() + .join(", ") + ) + } + } +} + +impl GetRust for GenericDecl { + fn get_rust(&self) -> String { + match self { + GenericDecl::Lifetime(name) => format!("'{}", name.get_rust()), + GenericDecl::Type(name, requirements) => { + name.get_rust() + + &(if requirements.len() != 0 { + format!( + ": {}", + requirements + .into_iter() + .map(TypeExpr::get_rust) + .collect::>() + .join("+") + ) + } else { + String::new() + }) + } + } + } +} + +impl GenRust for ImplDecl { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + if let Some(trait_) = &self.trait_ { + cg.add_indentedln(&format!( + "impl{} {} for {} {{", + self.generics.get_rust(), + trait_.get_rust(), + self.target.get_rust() + )); + } else { + cg.add_indentedln(&format!( + "impl{} {} {{", + self.generics.get_rust(), + self.target.get_rust() + )); + } + cg.indent += 1; + + for method in &self.methods { + method.gen_rust(ctx, cg); + } + + cg.indent -= 1; + cg.add_indentedln("}"); + } +} + +impl GenRust for FunctionDecl { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + cg.add_indentedln(&format!( + "{}fn {}{}(", + self.visibility.get_rust(), + self.name.get_rust(), + self.generics.get_rust(), + )); + + for (i, param) in self.params.0.iter().enumerate() { + if i > 0 { + cg.add(","); + } + + param.gen_rust(ctx, cg); + } + + cg.add(") -> "); + cg.add(&self.return_type.get_rust()); + + if let Some(body) = &self.body { + cg.add_indentedln("{\n"); + cg.indent += 1; + body.gen_rust(ctx, cg); + cg.indent -= 1; + cg.add_indentedln("}\n"); + } else { + cg.add(";"); + } + } +} From 7b94969379036aa176a1b1bceee42b5ebb2c0a52 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 13:36:38 +0200 Subject: [PATCH 05/11] Top level --- codegen/src/top_level.rs | 272 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) diff --git a/codegen/src/top_level.rs b/codegen/src/top_level.rs index 9213687..7ceb09e 100644 --- a/codegen/src/top_level.rs +++ b/codegen/src/top_level.rs @@ -102,3 +102,275 @@ impl GenRust for FunctionDecl { } } } + +impl GetRust for FieldDecl { + fn get_rust(&self) -> String { + format!( + "{}{}: {},", + self.visibility.get_rust(), + self.name.get_rust(), + self.type_.get_rust() + ) + } +} + +impl GetRust for EnumItem { + fn get_rust(&self) -> String { + match self { + Self::Named(id) => id.get_rust(), + Self::Struct(id, s) => format!( + "{} {{{}}}", + id.get_rust(), + s.into_iter() + .map(|field| format!("{}: {}", field.name.get_rust(), field.type_.get_rust())) + .collect::>() + .join(", ") + ), + Self::Tuple(id, t) => format!( + "{} ({})", + id.get_rust(), + t.into_iter() + .map(TypeExpr::get_rust) + .collect::>() + .join(", ") + ), + } + } +} + +impl GenRust for ParamList { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + for (i, param) in self.0.iter().enumerate() { + if i > 0 { + cg.add(", "); + } + + param.gen_rust(ctx, cg); + } + } +} + +impl GenRust for (&Vec>, &ClassConstructor) { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + cg.add_indentedln(&format!( + "{}fn new{}(", + self.1.visibility.get_rust(), + self.1.generics.get_rust() + )); + + self.1.params.gen_rust(ctx, cg); + + cg.add(") -> Self {"); + cg.indent += 1; + + cg.add_indentedln("let mut this: Self = unsafe { std::mem::MaybeUninit::::zeroed().assume_init() };"); + + for field in self.0 { + let comment = field.get_comment(); + + if let Some(init) = &field.item.init { + cg.add_indentedln(&comment); + + cg.add_indentedln(&format!("this.{} = ", field.item.decl.name.get_rust())); + + init.gen_rust(ctx, cg); + } + } + + cg.add_indentedln(&format!("this.construct_class(")); + + for (i, param) in self.1.params.0.iter().enumerate() { + if i > 0 { + cg.add(", "); + } + + param.name.gen_rust(ctx, cg); + } + + cg.add(")"); + + cg.add_indentedln("this"); + + cg.indent -= 1; + cg.add_indentedln("}\n"); + + FunctionDecl { + visibility: self.1.visibility.clone(), + name: Identifier(String::from("constructor")), + generics: self.1.generics.clone(), + params: self.1.params.clone(), + return_type: TypeExpr( + TypeExprKind::Path(Path(vec![Identifier(String::from("Self"))])), + Vec::new(), + ), + body: Some(self.1.body.clone()), + } + .gen_rust(ctx, cg); + } +} + +impl GenRust for TopLevelKind { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + match self { + Self::ModAttribute => {} + Self::Import(vis, path) => { + cg.addln(&format!("{}use {};", vis.get_rust(), path.get_rust())) + } + Self::Mod(vis, id) => cg.addln(&format!("{}mod {};", vis.get_rust(), id.get_rust())), + Self::FunctionDecl(decl) => decl.gen_rust(ctx, cg), + Self::ImplDecl(impl_) => impl_.gen_rust(ctx, cg), + Self::StructDecl { + visibility, + name, + generics, + fields, + } => { + cg.addln(&format!( + "{}struct {}{} {{", + visibility.get_rust(), + name.get_rust(), + generics.get_rust() + )); + cg.indent += 1; + + for field in fields { + cg.add_indentedln(&field.get_rust()); + } + + cg.indent -= 1; + cg.addln("}\n"); + } + Self::EnumDecl { + visibility, + name, + generics, + fields, + } => { + cg.addln(&format!( + "{}enum {}{} {{", + visibility.get_rust(), + name.get_rust(), + generics.get_rust() + )); + cg.indent += 1; + + for field in fields { + cg.add_indentedln(&(field.get_rust() + ",")); + } + + cg.indent -= 1; + cg.addln("}\n"); + } + Self::TraitDecl { + visibility, + name, + generics, + requirements, + items, + } => { + cg.addln(&format!( + "{}trait {}{}{} {{", + visibility.get_rust(), + name.get_rust(), + generics.get_rust(), + if requirements.len() != 0 { + String::from(": ") + + &requirements + .into_iter() + .map(TypeExpr::get_rust) + .collect::>() + .join("+") + } else { + String::new() + }, + )); + cg.indent += 1; + + for item in items { + item.gen_rust(ctx, cg); + } + + cg.indent -= 1; + cg.addln("}\n"); + } + Self::ClassDecl { + visibility, + name, + generics, + fields, + constructor, + items, + } => { + // Struct decl + cg.addln(&format!( + "{}struct {}{} {{", + visibility.get_rust(), + name.clone().get_rust(), + generics.clone().get_rust() + )); + cg.indent += 1; + + for field in fields.clone() { + cg.add_indentedln(&field.get_comment()); + cg.add_indentedln(&field.item.decl.get_rust()); + } + + cg.indent -= 1; + cg.addln("}\n"); + + // Constructor + cg.addln(&format!( + "impl{} {}{} {{", + generics.clone().get_rust(), + name.clone().get_rust(), + format!( + "<{}>", + generics + .clone() + .0 + .into_iter() + .map(|v| Generic::from(v).get_rust()) + .collect::>() + .join(", ") + ) + )); + cg.indent += 1; + + let constructor_comment = constructor.get_comment(); + + cg.add_indentedln("#[allow(invalid_value)]"); + cg.add_indentedln(&constructor_comment); + + (fields, &constructor.item).gen_rust(ctx, cg); + + cg.indent -= 1; + cg.add_indentedln("}\n"); + + for item in items.clone() { + match item { + ClassItem::ImplDecl(_) => {} + ClassItem::Method(method) => method.gen_rust(ctx, cg), + } + } + + cg.indent -= 1; + cg.addln("}\n"); + + for item in items { + match item { + ClassItem::ImplDecl(impl_) => { + let mut impl_ = impl_.clone(); + + impl_.item.trait_ = Some(impl_.item.target); + impl_.item.target = + TypeExpr(TypeExprKind::Path(Path(vec![name.clone()])), Vec::new()); + + impl_.gen_rust(ctx, cg); + } + ClassItem::Method(_) => {} + } + } + } + } + } +} From 70a1fa332ba984acf4874cd1844f69cb262325d0 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 13:43:42 +0200 Subject: [PATCH 06/11] Top level --- codegen/src/lib.rs | 38 ++++++++++++++++++++++++++++++++------ codegen/src/top_level.rs | 20 ++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 103e281..c406d09 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -57,13 +57,17 @@ impl RustCodegen { self.add(&line); } - // pub fn generate(&mut self, toplevels: Vec) -> String { - // for tl in toplevels { - // tl.gen_rust(self); - // } + pub fn generate(&mut self, toplevels: Vec) -> String { + let mut ctx = Context { + expr_ensure_semicolon: true, + }; - // self.output.clone() - // } + for tl in toplevels { + tl.gen_rust(&mut ctx, self); + } + + self.output.clone() + } pub fn ensure_brackets(&mut self, ctx: &mut Context, stmt: &Box) { match &**stmt { @@ -79,6 +83,28 @@ impl RustCodegen { } } +impl GenRust for Attribute { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + match self { + Self::Path(path) => cg.add(&path.get_rust()), + Self::NameValue { path, value } => { + cg.add(&format!("{} =", path.get_rust())); + value.gen_rust(ctx, cg); + } + Self::List { path, items } => { + cg.add(&path.get_rust()); + for (i, item) in items.iter().enumerate() { + if i > 0 { + cg.add(", "); + } + + item.gen_rust(ctx, cg); + } + } + } + } +} + impl GetRust for Spanned { fn get_rust(&self) -> String { format!( diff --git a/codegen/src/top_level.rs b/codegen/src/top_level.rs index 7ceb09e..54bb444 100644 --- a/codegen/src/top_level.rs +++ b/codegen/src/top_level.rs @@ -150,6 +150,26 @@ impl GenRust for ParamList { } } +impl GenRust for TopLevel { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + if let TopLevelKind::ModAttribute = self.0.item { + for attr in &self.1 { + cg.add("#!["); + attr.gen_rust(ctx, cg); + cg.addln("]"); + } + } else { + for attr in &self.1 { + cg.add("#["); + attr.gen_rust(ctx, cg); + cg.addln("]"); + } + } + + self.0.gen_rust(ctx, cg); + } +} + impl GenRust for (&Vec>, &ClassConstructor) { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { cg.add_indentedln(&format!( From 8703ac42543f771292ede50b5f770b16e48bd8f7 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 13:48:09 +0200 Subject: [PATCH 07/11] Finished expr, and removed old codegen --- analyzer/src/lib.rs | 2 +- codegen/src/expr.rs | 27 +- src/_header.rs | 1 - src/codegen.rs | 730 -------------------------------------------- src/main.mist | 1 - src/transpiler.rs | 2 +- 6 files changed, 27 insertions(+), 736 deletions(-) delete mode 100644 src/codegen.rs diff --git a/analyzer/src/lib.rs b/analyzer/src/lib.rs index eb3e52c..cb1f168 100644 --- a/analyzer/src/lib.rs +++ b/analyzer/src/lib.rs @@ -31,7 +31,7 @@ impl LanguageServer for Backend { .await; } - async fn completion(&self, params: CompletionParams) -> Result> { + async fn completion(&self, _params: CompletionParams) -> Result> { self.client .log_message(MessageType::INFO, "getting completion") .await; diff --git a/codegen/src/expr.rs b/codegen/src/expr.rs index 6a23e14..a0e2b10 100644 --- a/codegen/src/expr.rs +++ b/codegen/src/expr.rs @@ -4,6 +4,29 @@ use crate::Context; use crate::{GenRust, GetRust, RustCodegen}; +impl GetRust for ExprPath { + fn get_rust(&self) -> String { + self.0 + .iter() + .map(ExprPathSegment::get_rust) + .collect::>() + .join("::") + } +} + +impl GetRust for ExprPathSegment { + fn get_rust(&self) -> String { + format!( + "{}{}", + self.ident.get_rust(), + self.generics + .as_ref() + .map(|v| format!("::{}", v.get_rust())) + .unwrap_or_default() + ) + } +} + impl GenRust for Literal { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { match self { @@ -46,8 +69,8 @@ impl GenRust for Literal { impl GenRust for Expression { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { match self { - Expression::Path(path) => unimplemented!(), - Expression::Literal(literal) => unimplemented!(), + Expression::Path(path) => cg.add(&path.get_rust()), + Expression::Literal(literal) => literal.gen_rust(ctx, cg), Expression::Statement(stmt) => stmt.gen_rust(ctx, cg), Expression::Fix { initial, diff --git a/src/_header.rs b/src/_header.rs index c8b912b..749d126 100644 --- a/src/_header.rs +++ b/src/_header.rs @@ -1,5 +1,4 @@ pub mod builder; -pub mod codegen; pub mod transpiler; fn main() {} diff --git a/src/codegen.rs b/src/codegen.rs deleted file mode 100644 index d449efd..0000000 --- a/src/codegen.rs +++ /dev/null @@ -1,730 +0,0 @@ -use mist_parser::ast::{ - Attribute, Block, ClassItem, EnumItem, ExprPath, ExprPathSegment, Expression, FieldDecl, - FunctionDecl, Generic, GenericDecl, Generics, GenericsDecl, Identifier, ImplDecl, Literal, - Path, Pattern, Postfix, Prefix, Spanned, Statement, StatementBranch, TopLevel, TopLevelKind, - TypeExpr, TypeExprKind, TypePostfix, VarDecl, VarDeclStmt, Visibility, -}; - -// --------------------------------------------------------------------------- -// Traits -// --------------------------------------------------------------------------- - -/// Implemented by nodes that *write* into the codegen output buffer. -/// Requires `&mut RustCodegen` because it calls `add` / `addln` / indentation helpers. -pub trait ToRust { - fn to_rust(self, cg: &mut RustCodegen); -} - -/// Implemented by nodes that *produce* a `String` without mutating the codegen. -/// Only needs `&RustCodegen` (e.g. for indent level or helper access). -pub trait GetRust { - fn get_rust(self) -> String; -} - -// --------------------------------------------------------------------------- -// Codegen struct -// --------------------------------------------------------------------------- - -pub struct RustCodegen { - output: String, - indent: usize, -} - -impl RustCodegen { - pub fn new() -> Self { - Self { - output: String::new(), - indent: 0, - } - } - - fn indent_str(&self) -> String { - " ".repeat(self.indent) - } - - fn add(&mut self, s: &str) { - self.output.push_str(s); - } - - fn addln(&mut self, s: &str) { - self.add(s); - self.add("\n"); - } - - fn add_indentedln(&mut self, s: &str) { - let line = format!("{}{}\n", self.indent_str(), s); - self.add(&line); - } - - pub fn generate(&mut self, toplevels: Vec) -> String { - for tl in toplevels { - tl.to_rust(self); - } - - self.output.clone() - } - - pub fn ensure_brackets(&mut self, stmt: Box) { - 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 { - fn default() -> Self { - Self::new() - } -} - -// --------------------------------------------------------------------------- -// GetRust — pure string production (expressions, types) -// --------------------------------------------------------------------------- - -impl GetRust for Spanned { - fn get_rust(self) -> String { - format!( - "/* {}:{} */ {}", - self.line, - self.column, - self.item.get_rust() - ) - } -} - -impl GetRust for TypeExpr { - fn get_rust(self) -> String { - get_type_postfixes(self.1) + &self.0.get_rust() - } -} - -impl GetRust for TypeExprKind { - fn get_rust(self) -> String { - match self { - TypeExprKind::Path(path) => get_static_type_path(path), - TypeExprKind::Lifetime(name) => format!("'{}", name.get_rust()), - TypeExprKind::PathParams(path, params) => { - format!( - "{}<{}>", - get_static_type_path(path), - params - .into_iter() - .map(|t| t.get_rust()) - .collect::>() - .join(", ") - ) - } - TypeExprKind::Tuple(types) => format!( - "({})", - types - .into_iter() - .map(|t| t.get_rust()) - .collect::>() - .join(", ") - ), - } - } -} - -impl GetRust for Expression { - fn get_rust(self) -> String { - match self { - Expression::Path(path) => path.get_rust(), - Expression::Literal(literal) => literal.get_rust(), - Expression::Statement(stmt) => { - let mut cg = RustCodegen::new(); - cg.indent += 1; - stmt.to_rust(&mut cg); - cg.output - } - Expression::Fix { - initial, - prefixes, - postfixes, - } => { - prefixes.clone().get_rust() - + &initial.get_rust() - + &Some(prefixes).get_rust() - + &postfixes.get_rust() - } - // Safely integrated to handle the tree structure built by the Pratt Parser - Expression::Binary { lhs, op, rhs } => { - format!("{} {} {}", lhs.get_rust(), op, rhs.get_rust()) - } - } - } -} - -impl GetRust for Prefix { - fn get_rust(self) -> String { - match self { - Self::Deref => "*", - Self::Ref => "&", - Self::RefMut => "&mut ", - Self::Not => "!", - Self::New(_) => "", - Self::Neg => "-", - } - .to_string() - } -} - -impl GetRust for Vec { - fn get_rust(self) -> String { - self.into_iter().map(Prefix::get_rust).collect() - } -} - -impl GetRust for ExprPath { - fn get_rust(self) -> String { - self.0 - .into_iter() - .map(ExprPathSegment::get_rust) - .collect::>() - .join("::") - } -} - -impl GetRust for ExprPathSegment { - fn get_rust(self) -> String { - format!( - "{}{}", - self.ident.get_rust(), - self.generics - .map(|v| format!("::{}", v.get_rust())) - .unwrap_or_default() - ) - } -} - -impl GetRust for Option> { - fn get_rust(self) -> String { - self.map(|prefixes| { - prefixes - .into_iter() - .last() - .map(|p| match p { - Prefix::New(generics) => format!( - "::new{}", - generics - .map(|v| format!("::{}", v.get_rust())) - .unwrap_or_default(), - ), - _ => String::new(), - }) - .unwrap_or_default() - .to_string() - }) - .unwrap_or_default() - } -} - -impl GetRust for Postfix { - fn get_rust(self) -> String { - match self { - Postfix::FieldAccess(field, generics) => format!( - ".{}{}", - field.get_rust(), - generics - .map(|v| format!("::{}", v.get_rust())) - .unwrap_or_default() - ), - - Postfix::Call(args) => { - let args = args - .into_iter() - .map(|a| a.get_rust()) - .collect::>() - .join(", "); - format!("({})", args) - } - - Postfix::MacroCall(inner) => { - format!("!({})", inner) - } - - Postfix::StructCall(fields) => { - let fields = fields - .into_iter() - .map(|(k, v)| format!("{}: {}", k.get_rust(), v.get_rust())) - .collect::>() - .join(", "); - format!("{{ {} }}", fields) - } - - Postfix::Index(idx) => { - format!("[{}]", idx.get_rust()) - } - - Postfix::As(ty) => format!(" as {}", ty.get_rust()), - - Postfix::Try => String::from("?"), - - Postfix::Assign(cmp, expr) => format!("{cmp} {}", expr.get_rust()), - Postfix::Increment => "+=1".to_string(), - Postfix::Decrement => "-=1".to_string(), - } - } -} - -impl GetRust for Vec { - fn get_rust(self) -> String { - self.into_iter().map(Postfix::get_rust).collect() - } -} -// --------------------------------------------------------------------------- -// ToRust — output-writing (top-level, statements, blocks) -// --------------------------------------------------------------------------- - -impl ToRust for Spanned { - fn to_rust(self, cg: &mut RustCodegen) { - cg.add_indentedln(&format!("/* {}:{} */", self.line, self.column)); - self.item.to_rust(cg); - } -} - -impl ToRust for Block { - fn to_rust(self, cg: &mut RustCodegen) { - for stmt in self.0 { - cg.add_indentedln(&(stmt.get_rust() + ";")); - } - - if let Some(soft_return) = self.1 { - cg.add_indentedln(&soft_return.get_rust()); - } - } -} - -impl ToRust for TopLevel { - fn to_rust(self, cg: &mut RustCodegen) { - if let TopLevelKind::ModAttribute = self.0.item { - for attr in self.1 { - cg.addln(&format!("#![{}]", attr.get_rust())); - } - } else { - for attr in self.1 { - cg.addln(&format!("#[{}]", attr.get_rust())); - } - } - - self.0.to_rust(cg); - } -} - -impl GetRust for Attribute { - fn get_rust(self) -> String { - match self { - Self::Path(path) => path.get_rust(), - Self::NameValue { path, value } => { - format!("{} = {}", path.get_rust(), value.get_rust()) - } - Self::List { path, items } => { - format!( - "{}({})", - path.get_rust(), - items - .into_iter() - .map(Attribute::get_rust) - .collect::>() - .join(", ") - ) - } - } - } -} - -impl ToRust for Statement { - fn to_rust(self, cg: &mut RustCodegen) { - match self { - Statement::Block(block) => { - cg.add_indentedln("{"); - cg.indent += 1; - block.to_rust(cg); - cg.indent -= 1; - cg.add_indentedln("}"); - } - - Statement::VarDecl(VarDeclStmt { decl, init }) => { - let init = init - .map(|e| format!(" = {}", e.get_rust())) - .unwrap_or_default(); - - cg.add_indentedln(&format!("let {}{}", decl.get_rust(), init)); - } - - Statement::Match(expr, match_items) => { - cg.add_indentedln(&format!("match {} {{", expr.get_rust())); - cg.indent += 1; - - for itm in match_items { - cg.add_indentedln(&format!( - "{} =>", - itm.0 - .into_iter() - .map(Pattern::get_rust) - .collect::>() - .join(" | ") - )); - cg.add_indentedln("{"); - cg.indent += 1; - itm.1.to_rust(cg); - cg.indent -= 1; - cg.add_indentedln("}"); - } - - cg.indent -= 1; - cg.add_indentedln("}"); - } - - Statement::If { - initial, - else_if, - else_branch, - } => { - 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.ensure_brackets(else_br); - } - } - - 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; - - 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 { - mutable, - pattern, - iterator, - body, - } => { - cg.add_indentedln(&format!( - "for {}{} in {}", - get_mutable(mutable), - pattern.get_rust(), - iterator.get_rust() - )); - cg.ensure_brackets(body); - } - - Statement::Return(expr) => { - let val = expr.map(|e| e.get_rust()).unwrap_or_default(); - cg.add_indentedln(&format!("return {}", val)); - } - - Statement::Break => cg.add_indentedln("break"), - Statement::Continue => cg.add_indentedln("continue"), - } - } -} - -impl ToRust for FunctionDecl { - fn to_rust(self, cg: &mut RustCodegen) { - let params_str = self - .params - .0 - .into_iter() - .map(VarDecl::get_rust) - .collect::>() - .join(", "); - - cg.add_indentedln(&format!( - "{}fn {}{}({}) -> {}", - self.visibility.get_rust(), - self.name.get_rust(), - self.generics.get_rust(), - params_str, - self.return_type.get_rust() - )); - if let Some(body) = self.body { - cg.add_indentedln("{\n"); - cg.indent += 1; - body.to_rust(cg); - cg.indent -= 1; - cg.add_indentedln("}\n"); - } else { - cg.add(";"); - } - } -} - -impl ToRust for ImplDecl { - fn to_rust(self, cg: &mut RustCodegen) { - if let Some(trait_) = self.trait_ { - cg.add_indentedln(&format!( - "impl{} {} for {} {{", - self.generics.get_rust(), - trait_.get_rust(), - self.target.get_rust() - )); - } else { - cg.add_indentedln(&format!( - "impl{} {} {{", - self.generics.get_rust(), - self.target.get_rust() - )); - } - cg.indent += 1; - - for method in self.methods { - method.to_rust(cg); - } - - cg.indent -= 1; - cg.add_indentedln("}"); - } -} - -impl GetRust for VarDecl { - fn get_rust(self) -> String { - let ty = self - .type_ - .map(|t| format!(": {}", t.get_rust())) - .unwrap_or_default(); - - format!( - "{}{}{}", - get_mutable(self.mutable), - self.name.get_rust(), - ty - ) - } -} - -impl GetRust for Path { - fn get_rust(self) -> String { - self.0 - .into_iter() - .map(Identifier::get_rust) - .collect::>() - .join("::") - } -} - -impl GetRust for TypePostfix { - fn get_rust(self) -> String { - match self { - TypePostfix::Ref => format!("&"), - TypePostfix::RefMut => format!("&mut "), - TypePostfix::RefLifetime(lifetime) => format!("&'{} ", lifetime.get_rust()), - TypePostfix::RefMutLifetime(lifetime) => format!("&'{} mut ", lifetime.get_rust()), - TypePostfix::Dyn => format!("dyn "), - } - } -} - -impl GetRust for Visibility { - fn get_rust(self) -> String { - match self { - Visibility::Public => "pub ".to_string(), - Visibility::PublicTarget(path) => format!("pub({}) ", path.get_rust()), - Visibility::Private => "".to_string(), - } - } -} - -impl GetRust for Identifier { - fn get_rust(self) -> String { - self.0.clone() - } -} - -impl GetRust for EnumItem { - fn get_rust(self) -> String { - match self { - Self::Named(id) => id.get_rust(), - Self::Struct(id, s) => format!( - "{} {{{}}}", - id.get_rust(), - s.into_iter() - .map(|field| format!("{}: {}", field.name.get_rust(), field.type_.get_rust())) - .collect::>() - .join(", ") - ), - Self::Tuple(id, t) => format!( - "{} ({})", - id.get_rust(), - t.into_iter() - .map(TypeExpr::get_rust) - .collect::>() - .join(", ") - ), - } - } -} - -impl GetRust for Pattern { - fn get_rust(self) -> String { - match self { - Self::Id(id) => id.get_rust(), - Self::Path(path) => path.get_rust(), - Self::Literal(lit) => lit.get_rust(), - Self::Struct(path, ids) => format!( - "{} {{{}}}", - path.get_rust(), - ids.into_iter() - .map(Identifier::get_rust) - .collect::>() - .join(", ") - ), - Self::Tuple(ids) => format!( - "({})", - ids.into_iter() - .map(Identifier::get_rust) - .collect::>() - .join(", ") - ), - Self::NamedTuple(path, ids) => { - format!( - "{} ({})", - path.get_rust(), - ids.into_iter() - .map(Identifier::get_rust) - .collect::>() - .join(", ") - ) - } - } - } -} - -impl GetRust for GenericsDecl { - fn get_rust(self) -> String { - if self.0.len() == 0 { - String::new() - } else { - format!( - "<{}>", - self.0 - .into_iter() - .map(|v| v.get_rust()) - .collect::>() - .join(", ") - ) - } - } -} - -impl GetRust for GenericDecl { - fn get_rust(self) -> String { - match self { - GenericDecl::Lifetime(name) => format!("'{}", name.get_rust()), - GenericDecl::Type(name, requirements) => { - name.get_rust() - + &(if requirements.len() != 0 { - format!( - ": {}", - requirements - .into_iter() - .map(TypeExpr::get_rust) - .collect::>() - .join("+") - ) - } else { - String::new() - }) - } - } - } -} - -impl GetRust for Generics { - fn get_rust(self) -> String { - if self.0.len() == 0 { - String::new() - } else { - format!( - "<{}>", - self.0 - .into_iter() - .map(Generic::get_rust) - .collect::>() - .join(", ") - ) - } - } -} - -impl GetRust for Generic { - fn get_rust(self) -> String { - match self { - Self::Lifetime(name) => format!("'{}", name.get_rust()), - Self::Type(ty) => ty.get_rust(), - } - } -} - -impl GetRust for FieldDecl { - fn get_rust(self) -> String { - format!( - "{}{}: {},", - self.visibility.get_rust(), - self.name.get_rust(), - self.type_.get_rust() - ) - } -} - -pub fn get_static_type_path(path: Path) -> String { - let rust_path = path.get_rust(); - - if rust_path == "void" { - format!("()") - } else { - rust_path - } -} - -pub fn get_type_postfixes(postfixes: Vec) -> String { - postfixes - .into_iter() - .map(TypePostfix::get_rust) - .rev() - .collect() -} - -pub fn get_mutable(mutable: bool) -> String { - if mutable { "mut " } else { "" }.to_string() -} diff --git a/src/main.mist b/src/main.mist index a86389b..59c2d3b 100644 --- a/src/main.mist +++ b/src/main.mist @@ -3,7 +3,6 @@ use ; use ; pub mod builder; -pub mod codegen; pub mod transpiler; void main() { diff --git a/src/transpiler.rs b/src/transpiler.rs index 349b7c4..77b2522 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -141,7 +141,7 @@ fn build_dir(root: &Path, base_src: &Path, current_dir: &Path, out_dir: &Path) { // semantic::walk_ast(semantic::scope::Scope::from_top(root, &ast), &mut ast); - let mut gc = crate::codegen::RustCodegen::new(); + let mut gc = mist_codegen::RustCodegen::new(); let output = gc.generate(ast); if let Err(e) = fs::write(&output_path, output) { From f2257a4e816c182b367f378f15f1ede2bb202a1c Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 14:04:12 +0200 Subject: [PATCH 08/11] Fixed some bugs --- codegen/src/expr.rs | 15 +++++++++++++++ codegen/src/top_level.rs | 5 +---- mist-test/src/task.mist | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/codegen/src/expr.rs b/codegen/src/expr.rs index a0e2b10..ec21e89 100644 --- a/codegen/src/expr.rs +++ b/codegen/src/expr.rs @@ -68,6 +68,14 @@ impl GenRust for Literal { impl GenRust for Expression { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + let ensure_semicolon = if ctx.expr_ensure_semicolon { + ctx.expr_ensure_semicolon = false; + + true + } else { + false + }; + match self { Expression::Path(path) => cg.add(&path.get_rust()), Expression::Literal(literal) => literal.gen_rust(ctx, cg), @@ -90,6 +98,11 @@ impl GenRust for Expression { rhs.gen_rust(ctx, cg); } } + + if ensure_semicolon { + ctx.expr_ensure_semicolon = true; + cg.add(";"); + } } } @@ -175,6 +188,8 @@ impl GenRust for Postfix { expr.gen_rust(ctx, cg); cg.add(","); } + + cg.add("}"); } Postfix::Index(idx) => { diff --git a/codegen/src/top_level.rs b/codegen/src/top_level.rs index 54bb444..af80bbc 100644 --- a/codegen/src/top_level.rs +++ b/codegen/src/top_level.rs @@ -92,7 +92,7 @@ impl GenRust for FunctionDecl { cg.add(&self.return_type.get_rust()); if let Some(body) = &self.body { - cg.add_indentedln("{\n"); + cg.add_indentedln(" {\n"); cg.indent += 1; body.gen_rust(ctx, cg); cg.indent -= 1; @@ -363,9 +363,6 @@ impl GenRust for TopLevelKind { (fields, &constructor.item).gen_rust(ctx, cg); - cg.indent -= 1; - cg.add_indentedln("}\n"); - for item in items.clone() { match item { ClassItem::ImplDecl(_) => {} diff --git a/mist-test/src/task.mist b/mist-test/src/task.mist index d902258..a90f9e3 100644 --- a/mist-test/src/task.mist +++ b/mist-test/src/task.mist @@ -12,9 +12,9 @@ pub struct Task { } pub Task create_task(str* name) { - return Task { + Task { name: name.to_string(), state: TaskState::Pending, executions: 0, - }; + } } \ No newline at end of file From 80ff10503a4e03a43512c4388f4d2ad0d15f3f24 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 14:19:32 +0200 Subject: [PATCH 09/11] Working constructor and statements --- codegen/src/expr.rs | 3 ++- codegen/src/statement.rs | 2 +- codegen/src/top_level.rs | 22 +++++++++++++++------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/codegen/src/expr.rs b/codegen/src/expr.rs index ec21e89..1729525 100644 --- a/codegen/src/expr.rs +++ b/codegen/src/expr.rs @@ -87,6 +87,7 @@ impl GenRust for Expression { } => { cg.add(&prefixes.get_rust()); initial.gen_rust(ctx, cg); + cg.add(&Some(prefixes).get_rust()); for postfix in postfixes { postfix.gen_rust(ctx, cg); } @@ -126,7 +127,7 @@ impl GetRust for Vec { } } -impl GetRust for Option> { +impl GetRust for Option<&Vec> { fn get_rust(&self) -> String { if let Some(prefixes) = self { prefixes diff --git a/codegen/src/statement.rs b/codegen/src/statement.rs index 4178c08..e2a1ecb 100644 --- a/codegen/src/statement.rs +++ b/codegen/src/statement.rs @@ -7,6 +7,7 @@ use crate::{GenRust, GetRust, RustCodegen}; impl GenRust for Block { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { for stmt in &self.0 { + ctx.expr_ensure_semicolon = true; cg.add_indented(""); stmt.gen_rust(ctx, cg); } @@ -14,7 +15,6 @@ impl GenRust for Block { if let Some(soft_return) = &self.1 { ctx.expr_ensure_semicolon = false; soft_return.gen_rust(ctx, cg); - ctx.expr_ensure_semicolon = true; } } } diff --git a/codegen/src/top_level.rs b/codegen/src/top_level.rs index af80bbc..a5c54a9 100644 --- a/codegen/src/top_level.rs +++ b/codegen/src/top_level.rs @@ -197,7 +197,7 @@ impl GenRust for (&Vec>, &ClassConstructor) { } } - cg.add_indentedln(&format!("this.construct_class(")); + cg.add_indentedln(&format!("this.constructor(")); for (i, param) in self.1.params.0.iter().enumerate() { if i > 0 { @@ -207,22 +207,30 @@ impl GenRust for (&Vec>, &ClassConstructor) { param.name.gen_rust(ctx, cg); } - cg.add(")"); + cg.add(");"); cg.add_indentedln("this"); cg.indent -= 1; cg.add_indentedln("}\n"); + let mut constructor_params = vec![VarDecl { + mutable: false, + name: Pattern::Id(Identifier(String::from("self"))), + type_: Some(TypeExpr( + TypeExprKind::Path(Path(vec![Identifier(String::from("Self"))])), + vec![TypePostfix::RefMut], + )), + }]; + + constructor_params.append(&mut self.1.params.0.clone()); + FunctionDecl { visibility: self.1.visibility.clone(), name: Identifier(String::from("constructor")), generics: self.1.generics.clone(), - params: self.1.params.clone(), - return_type: TypeExpr( - TypeExprKind::Path(Path(vec![Identifier(String::from("Self"))])), - Vec::new(), - ), + params: ParamList(constructor_params), + return_type: TypeExpr::no_px(TypeExprKind::Tuple(Vec::new())), body: Some(self.1.body.clone()), } .gen_rust(ctx, cg); From 4112dcac3b30312b7f96dfcc9d43eee1a640d6d4 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 14:38:37 +0200 Subject: [PATCH 10/11] Improved match statements --- mist-test/src/logger.mist | 15 +++++---------- parser/src/ast/statement.rs | 2 +- parser/src/grammar.pest | 2 +- parser/src/parser/common/statement.rs | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index ab194cd..ca23341 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -13,18 +13,13 @@ pub enum LogLevel { impl fmt::Display for LogLevel { fmt::Result fmt(self*, Formatter<'_> mut* f) { - match (self) { - LogLevel::Info => { - return write!(f, "[INFO]"); - } + return match (self) { + LogLevel::Info => write!(f, "[INFO]"); - LogLevel::Warning => { - return write!(f, "[WARN]"); - } + LogLevel::Warning => write!(f, "[WARN]"); - LogLevel::Error => { - return write!(f, "[ERROR]"); - } + LogLevel::Error => write!(f, "[ERROR]"); + } } } diff --git a/parser/src/ast/statement.rs b/parser/src/ast/statement.rs index 89a2d44..a95429c 100644 --- a/parser/src/ast/statement.rs +++ b/parser/src/ast/statement.rs @@ -30,7 +30,7 @@ pub enum Statement { iterator: Expression, body: Box, }, - Match(Expression, Vec<(Vec, Block)>), + Match(Expression, Vec<(Vec, Expression)>), Return(Option), Break, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 3b08ce8..8e03ebc 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -419,7 +419,7 @@ for_stmt = { pattern_list = { pattern ~ ("|" ~ pattern)* } match_item = { - pattern_list ~ "=>" ~ block + pattern_list ~ "=>" ~ statement } match_stmt = { diff --git a/parser/src/parser/common/statement.rs b/parser/src/parser/common/statement.rs index 516d32d..6c8bfa2 100644 --- a/parser/src/parser/common/statement.rs +++ b/parser/src/parser/common/statement.rs @@ -95,7 +95,7 @@ impl<'a> TryFrom> for Statement { let mut match_inner = match_itms.into_inner(); Ok(( collect_recovered(match_inner.next().unwrap().into_inner()).get()?, - Block::try_from(match_inner.next().unwrap()).get()?, + Expression::try_from(match_inner.next().unwrap()).get()?, )) }) .collect::>>(), From 119f93cf7953174f0c51dfce49a4d546364a1112 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 21 May 2026 15:14:51 +0200 Subject: [PATCH 11/11] Prettier codegen output --- codegen/src/lib.rs | 1 + codegen/src/statement.rs | 20 +++++++++------- codegen/src/top_level.rs | 49 ++++++++++++++++++++------------------- mist-test/src/logger.mist | 1 - 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index c406d09..a2513fc 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -119,6 +119,7 @@ impl GetRust for Spanned { impl GenRust for Spanned { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { cg.add_indentedln(&format!("/* {}:{} */", self.line, self.column)); + cg.add_indented(""); self.item.gen_rust(ctx, cg); } } diff --git a/codegen/src/statement.rs b/codegen/src/statement.rs index e2a1ecb..2274f5c 100644 --- a/codegen/src/statement.rs +++ b/codegen/src/statement.rs @@ -6,29 +6,29 @@ use crate::{GenRust, GetRust, RustCodegen}; impl GenRust for Block { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + cg.addln("{"); + cg.indent += 1; + for stmt in &self.0 { ctx.expr_ensure_semicolon = true; - cg.add_indented(""); stmt.gen_rust(ctx, cg); + cg.addln(""); } if let Some(soft_return) = &self.1 { ctx.expr_ensure_semicolon = false; soft_return.gen_rust(ctx, cg); } + + cg.indent -= 1; + cg.add_indentedln("}"); } } impl GenRust for Statement { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { match self { - Statement::Block(block) => { - cg.add_indentedln("{"); - cg.indent += 1; - block.gen_rust(ctx, cg); - cg.indent -= 1; - cg.add_indentedln("}"); - } + Statement::Block(block) => block.gen_rust(ctx, cg), Statement::VarDecl(VarDeclStmt { decl, init }) => { cg.add("let "); @@ -48,6 +48,8 @@ impl GenRust for Statement { for (pat, body) in match_items { for (i, p) in pat.iter().enumerate() { + cg.addln(""); + cg.add_indented(""); if i > 0 { cg.add(" | "); } @@ -55,7 +57,7 @@ impl GenRust for Statement { p.gen_rust(ctx, cg); } - cg.add("=> {"); + cg.add(" => {"); cg.indent += 1; body.gen_rust(ctx, cg); diff --git a/codegen/src/top_level.rs b/codegen/src/top_level.rs index a5c54a9..34bd69f 100644 --- a/codegen/src/top_level.rs +++ b/codegen/src/top_level.rs @@ -73,7 +73,7 @@ impl GenRust for ImplDecl { impl GenRust for FunctionDecl { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { - cg.add_indentedln(&format!( + cg.add(&format!( "{}fn {}{}(", self.visibility.get_rust(), self.name.get_rust(), @@ -82,7 +82,7 @@ impl GenRust for FunctionDecl { for (i, param) in self.params.0.iter().enumerate() { if i > 0 { - cg.add(","); + cg.add(", "); } param.gen_rust(ctx, cg); @@ -92,11 +92,8 @@ impl GenRust for FunctionDecl { cg.add(&self.return_type.get_rust()); if let Some(body) = &self.body { - cg.add_indentedln(" {\n"); - cg.indent += 1; + cg.add(" "); body.gen_rust(ctx, cg); - cg.indent -= 1; - cg.add_indentedln("}\n"); } else { cg.add(";"); } @@ -170,17 +167,17 @@ impl GenRust for TopLevel { } } -impl GenRust for (&Vec>, &ClassConstructor) { +impl GenRust for (&Vec>, &Spanned) { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { - cg.add_indentedln(&format!( + cg.add_indented(&format!( "{}fn new{}(", - self.1.visibility.get_rust(), - self.1.generics.get_rust() + self.1.item.visibility.get_rust(), + self.1.item.generics.get_rust() )); - self.1.params.gen_rust(ctx, cg); + self.1.item.params.gen_rust(ctx, cg); - cg.add(") -> Self {"); + cg.addln(") -> Self {"); cg.indent += 1; cg.add_indentedln("let mut this: Self = unsafe { std::mem::MaybeUninit::::zeroed().assume_init() };"); @@ -197,9 +194,9 @@ impl GenRust for (&Vec>, &ClassConstructor) { } } - cg.add_indentedln(&format!("this.constructor(")); + cg.add_indented(&format!("this.constructor(")); - for (i, param) in self.1.params.0.iter().enumerate() { + for (i, param) in self.1.item.params.0.iter().enumerate() { if i > 0 { cg.add(", "); } @@ -207,7 +204,7 @@ impl GenRust for (&Vec>, &ClassConstructor) { param.name.gen_rust(ctx, cg); } - cg.add(");"); + cg.addln(");"); cg.add_indentedln("this"); @@ -223,15 +220,19 @@ impl GenRust for (&Vec>, &ClassConstructor) { )), }]; - constructor_params.append(&mut self.1.params.0.clone()); + constructor_params.append(&mut self.1.item.params.0.clone()); - FunctionDecl { - visibility: self.1.visibility.clone(), - name: Identifier(String::from("constructor")), - generics: self.1.generics.clone(), - params: ParamList(constructor_params), - return_type: TypeExpr::no_px(TypeExprKind::Tuple(Vec::new())), - body: Some(self.1.body.clone()), + Spanned { + line: self.1.line, + column: self.1.column, + item: FunctionDecl { + visibility: self.1.item.visibility.clone(), + name: Identifier(String::from("constructor")), + generics: self.1.item.generics.clone(), + params: ParamList(constructor_params), + return_type: TypeExpr::no_px(TypeExprKind::Tuple(Vec::new())), + body: Some(self.1.item.body.clone()), + }, } .gen_rust(ctx, cg); } @@ -369,7 +370,7 @@ impl GenRust for TopLevelKind { cg.add_indentedln("#[allow(invalid_value)]"); cg.add_indentedln(&constructor_comment); - (fields, &constructor.item).gen_rust(ctx, cg); + (fields, constructor).gen_rust(ctx, cg); for item in items.clone() { match item { diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index ca23341..e8ee98a 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -19,7 +19,6 @@ impl fmt::Display for LogLevel { LogLevel::Warning => write!(f, "[WARN]"); LogLevel::Error => write!(f, "[ERROR]"); - } } }