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/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/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..1729525 --- /dev/null +++ b/codegen/src/expr.rs @@ -0,0 +1,244 @@ +use mist_parser::ast::*; + +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 { + 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) { + 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), + Expression::Statement(stmt) => stmt.gen_rust(ctx, cg), + Expression::Fix { + initial, + prefixes, + postfixes, + } => { + 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); + } + } + // 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); + } + } + + if ensure_semicolon { + ctx.expr_ensure_semicolon = true; + cg.add(";"); + } + } +} + +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<&Vec> { + 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(","); + } + + 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 new file mode 100644 index 0000000..a2513fc --- /dev/null +++ b/codegen/src/lib.rs @@ -0,0 +1,251 @@ +pub mod expr; +pub mod statement; +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, +} + +pub trait GenRust { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen); +} + +pub trait GetRust { + fn get_rust(&self) -> String; +} + +#[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_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); + } + + pub fn generate(&mut self, toplevels: Vec) -> String { + let mut ctx = Context { + expr_ensure_semicolon: true, + }; + + 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 { + Statement::Block(_) => stmt.gen_rust(ctx, self), + _ => { + self.add("{"); + self.indent += 1; + stmt.gen_rust(ctx, self); + self.indent -= 1; + self.add("}"); + } + } + } +} + +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!( + "/* {}:{} */ {}", + self.line, + self.column, + self.item.get_rust() + ) + } +} + +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); + } +} + +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(", ") + ), + } + } +} + +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 new file mode 100644 index 0000000..2274f5c --- /dev/null +++ b/codegen/src/statement.rs @@ -0,0 +1,171 @@ +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) { + cg.addln("{"); + cg.indent += 1; + + for stmt in &self.0 { + ctx.expr_ensure_semicolon = true; + 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) => block.gen_rust(ctx, cg), + + 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() { + cg.addln(""); + cg.add_indented(""); + 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(), + ); + } +} diff --git a/codegen/src/top_level.rs b/codegen/src/top_level.rs new file mode 100644 index 0000000..34bd69f --- /dev/null +++ b/codegen/src/top_level.rs @@ -0,0 +1,402 @@ +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(&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(" "); + body.gen_rust(ctx, cg); + } else { + cg.add(";"); + } + } +} + +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 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>, &Spanned) { + fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { + cg.add_indented(&format!( + "{}fn new{}(", + self.1.item.visibility.get_rust(), + self.1.item.generics.get_rust() + )); + + self.1.item.params.gen_rust(ctx, cg); + + cg.addln(") -> 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_indented(&format!("this.constructor(")); + + for (i, param) in self.1.item.params.0.iter().enumerate() { + if i > 0 { + cg.add(", "); + } + + param.name.gen_rust(ctx, cg); + } + + cg.addln(");"); + + 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.item.params.0.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); + } +} + +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).gen_rust(ctx, cg); + + 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(_) => {} + } + } + } + } + } +} diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index ab194cd..e8ee98a 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -13,18 +13,12 @@ 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/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 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::>>(), 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 cc22d83..0000000 --- a/src/codegen.rs +++ /dev/null @@ -1,987 +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 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 { - 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 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 { - 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) {