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 { name: Pattern::Path(false, Path(vec![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, inherits, fields, constructor, items, } => { // Struct decl cg.addln(&format!( "{}struct {}{} {{", visibility.get_rust(), name.clone().get_rust(), generics.clone().get_rust() )); cg.indent += 1; if let Some(inherits) = inherits { cg.add_indented("pub _super: "); cg.add(&inherits.get_rust()); cg.addln(","); } 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(_) => {} } } if let Some(inherits) = inherits { cg.add("impl std::ops::Deref for "); cg.add(&name.get_rust()); cg.addln(" {"); cg.indent += 1; cg.add_indented("type Target = "); cg.add(&inherits.get_rust()); cg.addln(";"); cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}"); cg.indent -= 1; cg.addln("}"); // Mut cg.add("impl std::ops::DerefMut for "); cg.add(&name.get_rust()); cg.addln(" {"); cg.indent += 1; cg.add_indentedln( "fn deref_mut(&mut self) -> &mut Self::Target {&mut self._super}", ); cg.indent -= 1; cg.addln("}"); } } } } }