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 {