diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs index ac776c5..257448d 100644 --- a/parser/src/ast/expr.rs +++ b/parser/src/ast/expr.rs @@ -92,3 +92,12 @@ pub struct ExprPathSegment { #[derive(Debug, Clone, Serialize)] pub struct ExprPath(pub Vec); + +#[derive(Debug, Clone, Serialize)] +pub struct Generics(pub Vec); + +#[derive(Debug, Clone, Serialize)] +pub enum Generic { + Lifetime(Identifier), + Type(TypeExpr), +} diff --git a/parser/src/ast/mod.rs b/parser/src/ast/mod.rs index 1dd636d..ad0b287 100644 --- a/parser/src/ast/mod.rs +++ b/parser/src/ast/mod.rs @@ -41,3 +41,14 @@ impl TypeExpr { Self(kind, Vec::new()) } } + +impl From for Generic { + fn from(value: GenericDecl) -> Self { + match value { + GenericDecl::Lifetime(life) => Generic::Lifetime(life), + GenericDecl::Type(ty, _) => { + Generic::Type(TypeExpr(TypeExprKind::Path(Path(vec![ty])), Vec::new())) + } + } + } +} diff --git a/parser/src/ast/top_level.rs b/parser/src/ast/top_level.rs index 30021ea..04644ca 100644 --- a/parser/src/ast/top_level.rs +++ b/parser/src/ast/top_level.rs @@ -33,27 +33,27 @@ pub enum TopLevelKind { TraitDecl { visibility: Visibility, name: Identifier, - generics: Generics, + generics: GenericsDecl, requirements: Vec, items: Vec, }, EnumDecl { visibility: Visibility, name: Identifier, - generics: Generics, + generics: GenericsDecl, fields: Vec, }, StructDecl { visibility: Visibility, name: Identifier, - generics: Generics, + generics: GenericsDecl, fields: Vec, }, FunctionDecl(FunctionDecl), ClassDecl { visibility: Visibility, name: Identifier, - generics: Generics, + generics: GenericsDecl, fields: Vec, constructor: ClassConstructor, items: Vec, @@ -67,13 +67,14 @@ pub enum ClassItem { } #[derive(Debug, Clone, Serialize, Default)] -pub struct Generics(pub Vec); +pub struct GenericsDecl(pub Vec); #[derive(Debug, Clone, Serialize)] -pub enum Generic { +pub enum GenericDecl { Lifetime(Identifier), Type(Identifier, Vec), } + #[derive(Debug, Clone, Serialize)] pub enum EnumItem { Named(Identifier), @@ -84,7 +85,7 @@ pub enum EnumItem { #[derive(Debug, Clone, Serialize)] pub struct ClassConstructor { pub visibility: Visibility, - pub generics: Generics, + pub generics: GenericsDecl, pub params: ParamList, pub body: Block, } @@ -93,7 +94,7 @@ pub struct ClassConstructor { pub struct FunctionDecl { pub visibility: Visibility, pub name: Identifier, - pub generics: Generics, + pub generics: GenericsDecl, pub params: ParamList, pub return_type: TypeExpr, pub body: Option, @@ -101,7 +102,7 @@ pub struct FunctionDecl { #[derive(Debug, Clone, Serialize)] pub struct ImplDecl { - pub generics: Generics, + pub generics: GenericsDecl, pub target: TypeExpr, pub trait_: Option, pub methods: Vec, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index b843c39..5553193 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -63,7 +63,10 @@ unexpected_statement = { // ====================================================== // GENERICS // ====================================================== -generic = { lifetime | (identifier ~ (":" ~ type_expr_param ~ ("+" ~ type_expr_param)*)?) } +generic_decl = { lifetime | (identifier ~ (":" ~ type_expr_param ~ ("+" ~ type_expr_param)*)?) } +generics_decl = { "<" ~ (generic_decl ~ ("," ~ generic_decl)*)? ~ ">" } + +generic = { lifetime | type_expr_param } generics = { "<" ~ (generic ~ ("," ~ generic)*)? ~ ">" } // ====================================================== @@ -190,7 +193,7 @@ mod_package = { // ====================================================== struct_decl = { - visibility? ~ "struct" ~ identifier ~ generics? ~ "{" ~ field_list? ~ "}" + visibility? ~ "struct" ~ identifier ~ generics_decl? ~ "{" ~ field_list? ~ "}" } // ====================================================== @@ -220,7 +223,7 @@ enum_fields = _{ } enum_decl = { - visibility? ~ "enum" ~ identifier ~ generics? ~ "{" ~ enum_fields ~ "}" + visibility? ~ "enum" ~ identifier ~ generics_decl? ~ "{" ~ enum_fields ~ "}" } // ====================================================== @@ -228,7 +231,7 @@ enum_decl = { // ====================================================== class_constructor = { - visibility? ~ "constructor" ~ generics? ~ "(" ~ param_list? ~ ")" ~ block + visibility? ~ "constructor" ~ generics_decl? ~ "(" ~ param_list? ~ ")" ~ block } class_fields = { @@ -244,7 +247,7 @@ self_param = { } method = { - visibility? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ block + visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ block } class_item = _{ @@ -253,18 +256,18 @@ class_item = _{ } class_decl = { - visibility? ~ "class" ~ identifier ~ generics? ~ "{" ~ class_fields ~ class_constructor ~ class_item* ~ "}" + visibility? ~ "class" ~ identifier ~ generics_decl? ~ "{" ~ class_fields ~ class_constructor ~ class_item* ~ "}" } // ====================================================== // IMPL // ====================================================== impl_for_decl = { - "impl" ~ generics? ~ type_expr ~ "for" ~ type_expr ~ "{" ~ method* ~ "}" + "impl" ~ generics_decl? ~ type_expr ~ "for" ~ type_expr ~ "{" ~ method* ~ "}" } impl_decl = { - "impl" ~ generics? ~ type_expr ~ "{" ~ method* ~ "}" + "impl" ~ generics_decl? ~ type_expr ~ "{" ~ method* ~ "}" } // ====================================================== @@ -273,7 +276,7 @@ impl_decl = { trait_requirements = { ":" ~ type_expr_param ~ ("+" ~ type_expr_param)* } method_no_body = { - visibility? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ semicolon + visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ semicolon } trait_item = _{ @@ -282,7 +285,7 @@ trait_item = _{ } trait_decl = { - visibility? ~ "trait" ~ identifier ~ generics? ~ trait_requirements? ~ "{" ~ trait_item* ~ "}" + visibility? ~ "trait" ~ identifier ~ generics_decl? ~ trait_requirements? ~ "{" ~ trait_item* ~ "}" } // ====================================================== diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 245fd9f..867c2ef 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -34,8 +34,8 @@ pub fn parse<'a>(source: &'a str) -> Result, ParseError<'a, Vec $body:block) => { - if $pair.as_rule() == $rule + ($pair:expr, $rule:expr $(, $rules:expr)* => $body:block) => { + if $pair.as_rule() == $rule $(|| $pair.as_rule() == $rules)* $body else { Err(AstError { diff --git a/parser/src/parser/common/types.rs b/parser/src/parser/common/types.rs index 7e64d1c..840ae4d 100644 --- a/parser/src/parser/common/types.rs +++ b/parser/src/parser/common/types.rs @@ -1,7 +1,7 @@ use crate::{ Rule, ast::*, - ast_expr, + ast_ensure, ast_expr, error::{AstError, GetLength, IntoErr, collect_recovered}, parser::{consume_rule, listen_rule}, }; @@ -87,17 +87,48 @@ impl<'a> TryFrom> for TypeExpr { } } +impl<'a> TryFrom> for GenericsDecl { + type Error = AstError<'a, Self>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let inner = pair.clone().into_inner(); + + ast_ensure!(pair, Rule::generics_decl => { + ast_expr!(GenericsDecl(collect_recovered(inner))) + }) + } +} + +impl<'a> TryFrom> for GenericDecl { + type Error = AstError<'a, Self>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let mut inner = pair.clone().into_inner(); + + ast_ensure!(pair, Rule::generic_decl => { + if let Some(pair) = consume_rule(&mut inner, Rule::lifetime) { + ast_expr!(GenericDecl::Lifetime( + pair.into_inner().next().unwrap().try_into(), + )) + } else { + ast_expr!(GenericDecl::Type( + inner.next().unwrap().try_into(), + collect_recovered(inner), + )) + } + }) + } +} + impl<'a> TryFrom> for Generics { type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let rule = pair.as_rule(); let inner = pair.clone().into_inner(); - match rule { - Rule::generics => ast_expr!(Generics(collect_recovered(inner))), - _ => AstError::bug_unimplemented(pair), - } + ast_ensure!(pair, Rule::generics => { + ast_expr!(Generics(collect_recovered(inner))) + }) } } @@ -107,15 +138,16 @@ impl<'a> TryFrom> for Generic { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.clone().into_inner(); - if let Some(pair) = consume_rule(&mut inner, Rule::lifetime) { - ast_expr!(Generic::Lifetime( - pair.into_inner().next().unwrap().try_into(), - )) - } else { - ast_expr!(Generic::Type( - inner.next().unwrap().try_into(), - collect_recovered(inner), - )) - } + ast_ensure!(pair, Rule::generic => { + if let Some(pair) = consume_rule(&mut inner, Rule::lifetime) { + ast_expr!(Generic::Lifetime( + pair.into_inner().next().unwrap().try_into(), + )) + } else { + ast_expr!(Generic::Type( + inner.next().unwrap().try_into() + )) + } + }) } } diff --git a/parser/src/parser/items/class.rs b/parser/src/parser/items/class.rs index 86eef27..4512d59 100644 --- a/parser/src/parser/items/class.rs +++ b/parser/src/parser/items/class.rs @@ -14,8 +14,8 @@ impl<'a> TryFrom> for ClassConstructor { Ok(Self { visibility: Visibility::try_from(&mut inner).get()?, - generics: consume_rule(&mut inner, Rule::generics) - .map(Generics::try_from) + generics: consume_rule(&mut inner, Rule::generics_decl) + .map(GenericsDecl::try_from) .transpose() .get()? .unwrap_or_default(), diff --git a/parser/src/parser/items/function.rs b/parser/src/parser/items/function.rs index c9500e7..766de4c 100644 --- a/parser/src/parser/items/function.rs +++ b/parser/src/parser/items/function.rs @@ -1,7 +1,7 @@ use crate::{ Rule, ast::*, - ast_expr, + ast_ensure, ast_expr, error::{AstError, AstResult, IntoErr, collect_recovered}, parser::{consume_rule, listen_rule}, }; @@ -10,64 +10,66 @@ impl<'a> TryFrom> for FunctionDecl { type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + ast_ensure!(pair, Rule::function_decl, Rule::method, Rule::method_no_body => { let mut inner = pair.into_inner(); - let visibility = Visibility::try_from(&mut inner); - let return_type = TypeExpr::try_from(inner.next().unwrap()); - let name = Identifier::try_from(inner.next().unwrap()); + let visibility = Visibility::try_from(&mut inner); + let return_type = TypeExpr::try_from(inner.next().unwrap()); + let name = Identifier::try_from(inner.next().unwrap()); - let generics = consume_rule(&mut inner, Rule::generics) - .map(Generics::try_from) - .transpose() - .map(|v| v.unwrap_or_default()); + let generics = consume_rule(&mut inner, Rule::generics_decl) + .map(GenericsDecl::try_from) + .transpose() + .map(|v| v.unwrap_or_default()); - let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { - let mut param_inner = param.into_inner(); - let name = Pattern::Id(Identifier(String::from("self"))); + let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { + let mut param_inner = param.into_inner(); + let name = Pattern::Id(Identifier(String::from("self"))); - let mutable = listen_rule(&mut param_inner, Rule::mutable); + let mutable = listen_rule(&mut param_inner, Rule::mutable); - let is_ref = listen_rule(&mut param_inner, Rule::deref_px); + let is_ref = listen_rule(&mut param_inner, Rule::deref_px); - VarDecl { - mutable: mutable && !is_ref, - name: name.clone(), - type_: Some(TypeExpr( - TypeExprKind::Path(Path(vec![Identifier("Self".to_string())])), - if is_ref { - vec![if mutable { - TypePostfix::RefMut + VarDecl { + mutable: mutable && !is_ref, + name: name.clone(), + type_: Some(TypeExpr( + TypeExprKind::Path(Path(vec![Identifier("Self".to_string())])), + if is_ref { + vec![if mutable { + TypePostfix::RefMut + } else { + TypePostfix::Ref + }] } else { - TypePostfix::Ref - }] - } else { - Vec::new() - }, - )), - } - }); - - let params = consume_rule(&mut inner, Rule::param_list) - .map({ - let self_param = self_param.clone(); - |params_pair| -> AstResult<'a, ParamList> { - let mut params = ParamList::try_from(params_pair)?; - if let Some(x) = self_param { - params.0.insert(0, x); - } - Ok(params) + Vec::new() + }, + )), } + }); + + let params = consume_rule(&mut inner, Rule::param_list) + .map({ + let self_param = self_param.clone(); + |params_pair| -> AstResult<'a, ParamList> { + let mut params = ParamList::try_from(params_pair)?; + if let Some(x) = self_param { + params.0.insert(0, x); + } + Ok(params) + } + }) + .unwrap_or_else(|| Ok(ParamList(self_param.into_iter().collect()))); + + let body = inner.next().map(Block::try_from).transpose(); + + ast_expr!(Self { + visibility: visibility, + return_type: return_type, + name: name, + generics: generics, + params: params, + body: body, }) - .unwrap_or_else(|| Ok(ParamList(self_param.into_iter().collect()))); - - let body = inner.next().map(Block::try_from).transpose(); - - ast_expr!(Self { - visibility: visibility, - return_type: return_type, - name: name, - generics: generics, - params: params, - body: body, }) } } diff --git a/parser/src/parser/items/impl_decl.rs b/parser/src/parser/items/impl_decl.rs index 6ad4ca4..5e8203a 100644 --- a/parser/src/parser/items/impl_decl.rs +++ b/parser/src/parser/items/impl_decl.rs @@ -14,8 +14,8 @@ impl<'a> TryFrom> for ImplDecl { match rule { Rule::impl_for_decl => Ok(ImplDecl { - generics: consume_rule(&mut inner, Rule::generics) - .map(Generics::try_from) + generics: consume_rule(&mut inner, Rule::generics_decl) + .map(GenericsDecl::try_from) .transpose() .get()? .unwrap_or_default(), @@ -25,8 +25,8 @@ impl<'a> TryFrom> for ImplDecl { }), Rule::impl_decl => Ok(ImplDecl { - generics: consume_rule(&mut inner, Rule::generics) - .map(Generics::try_from) + generics: consume_rule(&mut inner, Rule::generics_decl) + .map(GenericsDecl::try_from) .transpose() .get()? .unwrap_or_default(), diff --git a/parser/src/parser/items/mod.rs b/parser/src/parser/items/mod.rs index 5cbcaab..229ea88 100644 --- a/parser/src/parser/items/mod.rs +++ b/parser/src/parser/items/mod.rs @@ -8,7 +8,7 @@ use crate::{ Rule, ast::*, ast_expr, - error::{AstError, IntoErr, collect_recovered}, + error::{AstError, AstResult, IntoErr, collect_recovered}, parser::consume_rule, }; @@ -50,8 +50,8 @@ impl<'a> TryFrom> for TopLevelKind { name: inner.next().unwrap().try_into(), - generics: consume_rule(&mut inner, Rule::generics) - .map(Generics::try_from) + generics: consume_rule(&mut inner, Rule::generics_decl) + .map(GenericsDecl::try_from) .transpose() .map(|v| v.unwrap_or_default()), @@ -67,8 +67,8 @@ impl<'a> TryFrom> for TopLevelKind { name: inner.next().unwrap().try_into(), - generics: consume_rule(&mut inner, Rule::generics) - .map(Generics::try_from) + generics: consume_rule(&mut inner, Rule::generics_decl) + .map(GenericsDecl::try_from) .transpose() .map(|v| v.unwrap_or_default()), @@ -84,8 +84,8 @@ impl<'a> TryFrom> for TopLevelKind { name: inner.next().unwrap().try_into(), - generics: consume_rule(&mut inner, Rule::generics) - .map(Generics::try_from) + generics: consume_rule(&mut inner, Rule::generics_decl) + .map(GenericsDecl::try_from) .transpose() .map(|v| v.unwrap_or_default()), @@ -106,17 +106,17 @@ impl<'a> TryFrom> for TopLevelKind { name: inner.next().unwrap().try_into(), - generics: consume_rule(&mut inner, Rule::generics) - .map(Generics::try_from) + generics: consume_rule(&mut inner, Rule::generics_decl) + .map(GenericsDecl::try_from) .transpose() .map(|v| v.unwrap_or_default()), requirements: consume_rule(&mut inner, Rule::trait_requirements) - .map(|pair| collect_recovered::(pair.into_inner())) + .map(|pair| collect_recovered(pair.into_inner())) .transpose() .map(|v| v.unwrap_or_default()), - items: collect_recovered(inner), + items: Ok(Vec::new()) as AstResult<'_, Vec<_>>, }), _ => AstError::bug_unimplemented(pair), diff --git a/src/codegen.rs b/src/codegen.rs index 9b18cea..2b44796 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,8 +1,8 @@ use mist_parser::ast::{ Attribute, BinaryOp, Block, ClassItem, EnumItem, ExprPath, ExprPathSegment, Expression, - FieldDecl, FunctionDecl, Generic, Generics, Identifier, ImplDecl, Literal, Path, Pattern, - Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, - TypePostfix, VarDecl, VarDeclStmt, Visibility, + FieldDecl, FunctionDecl, Generic, GenericDecl, Generics, GenericsDecl, Identifier, ImplDecl, + Literal, Path, Pattern, Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, + TypeExpr, TypeExprKind, TypePostfix, VarDecl, VarDeclStmt, Visibility, }; // --------------------------------------------------------------------------- @@ -12,13 +12,13 @@ use mist_parser::ast::{ /// 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); + 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; + fn get_rust(self) -> String; } // --------------------------------------------------------------------------- @@ -56,15 +56,16 @@ impl RustCodegen { self.add(&line); } - pub fn generate(&mut self, toplevels: &[TopLevel]) -> String { + 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: &Statement) { - match stmt { + pub fn ensure_brackets(&mut self, stmt: Box) { + match *stmt { Statement::Block(_) => stmt.to_rust(self), _ => { self.add_indentedln("{"); @@ -88,13 +89,13 @@ impl Default for RustCodegen { // --------------------------------------------------------------------------- impl GetRust for TypeExpr { - fn get_rust(&self) -> String { - get_type_postfixes(&self.1) + &self.0.get_rust() + fn get_rust(self) -> String { + get_type_postfixes(self.1) + &self.0.get_rust() } } impl GetRust for TypeExprKind { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { TypeExprKind::Path(path) => get_static_type_path(path), TypeExprKind::Lifetime(name) => format!("'{}", name.get_rust()), @@ -103,7 +104,7 @@ impl GetRust for TypeExprKind { "{}<{}>", get_static_type_path(path), params - .iter() + .into_iter() .map(|t| t.get_rust()) .collect::>() .join(", ") @@ -112,7 +113,7 @@ impl GetRust for TypeExprKind { TypeExprKind::Tuple(types) => format!( "({})", types - .iter() + .into_iter() .map(|t| t.get_rust()) .collect::>() .join(", ") @@ -122,7 +123,7 @@ impl GetRust for TypeExprKind { } impl GetRust for Literal { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { Self::Int(n) => n.to_string(), Self::Float(n) => format!("{n:?}"), @@ -131,7 +132,7 @@ impl GetRust for Literal { Self::Tuple(t) => { format!( "({})", - t.iter() + t.into_iter() .map(Expression::get_rust) .collect::>() .join(", ") @@ -140,7 +141,7 @@ impl GetRust for Literal { Self::Array(values) => format!( "[{}]", values - .iter() + .into_iter() .map(Expression::get_rust) .collect::>() .join(", ") @@ -153,7 +154,7 @@ impl GetRust for Literal { } impl GetRust for Expression { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { Expression::Path(path) => path.get_rust(), Expression::Literal(literal) => literal.get_rust(), @@ -162,7 +163,7 @@ impl GetRust for Expression { prefixes, postfixes, } => { - prefixes.get_rust() + prefixes.clone().get_rust() + &initial.get_rust() + &Some(prefixes).get_rust() + &postfixes.get_rust() @@ -198,7 +199,7 @@ impl GetRust for Expression { } impl GetRust for Prefix { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { Self::Deref => "*", Self::Ref => "&", @@ -211,16 +212,16 @@ impl GetRust for Prefix { } } -impl GetRust for [Prefix] { - fn get_rust(&self) -> String { - self.iter().map(Prefix::get_rust).collect() +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 { + fn get_rust(self) -> String { self.0 - .iter() + .into_iter() .map(ExprPathSegment::get_rust) .collect::>() .join("::") @@ -228,29 +229,27 @@ impl GetRust for ExprPath { } impl GetRust for ExprPathSegment { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { format!( "{}{}", self.ident.get_rust(), self.generics - .as_ref() .map(|v| format!("::{}", v.get_rust())) .unwrap_or_default() ) } } -impl GetRust for Option<&Vec> { - fn get_rust(&self) -> String { +impl GetRust for Option> { + fn get_rust(self) -> String { self.map(|prefixes| { prefixes - .iter() + .into_iter() .last() .map(|p| match p { Prefix::New(generics) => format!( "::new{}", generics - .as_ref() .map(|v| format!("::{}", v.get_rust())) .unwrap_or_default(), ), @@ -264,20 +263,19 @@ impl GetRust for Option<&Vec> { } impl GetRust for Postfix { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { Postfix::FieldAccess(field, generics) => format!( ".{}{}", field.get_rust(), generics - .as_ref() .map(|v| format!("::{}", v.get_rust())) .unwrap_or_default() ), Postfix::Call(args) => { let args = args - .iter() + .into_iter() .map(|a| a.get_rust()) .collect::>() .join(", "); @@ -290,7 +288,7 @@ impl GetRust for Postfix { Postfix::StructCall(fields) => { let fields = fields - .iter() + .into_iter() .map(|(k, v)| format!("{}: {}", k.get_rust(), v.get_rust())) .collect::>() .join(", "); @@ -308,9 +306,9 @@ impl GetRust for Postfix { } } -impl GetRust for [Postfix] { - fn get_rust(&self) -> String { - self.iter().map(Postfix::get_rust).collect() +impl GetRust for Vec { + fn get_rust(self) -> String { + self.into_iter().map(Postfix::get_rust).collect() } } // --------------------------------------------------------------------------- @@ -318,23 +316,23 @@ impl GetRust for [Postfix] { // --------------------------------------------------------------------------- impl ToRust for Block { - fn to_rust(&self, cg: &mut RustCodegen) { - for stmt in &self.0 { + fn to_rust(self, cg: &mut RustCodegen) { + for stmt in self.0 { stmt.to_rust(cg); } } } impl ToRust for TopLevel { - fn to_rust(&self, cg: &mut RustCodegen) { - match &self.0 { + fn to_rust(self, cg: &mut RustCodegen) { + match self.0 { TopLevelKind::ModAttribute => { - for attr in &self.1 { + for attr in self.1 { cg.addln(&format!("#![{}]", attr.get_rust())); } } _ => { - for attr in &self.1 { + for attr in self.1 { cg.addln(&format!("#[{}]", attr.get_rust())); } } @@ -345,7 +343,7 @@ impl ToRust for TopLevel { } impl GetRust for Attribute { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { Self::Path(path) => path.get_rust(), Self::NameValue { path, value } => { @@ -356,7 +354,7 @@ impl GetRust for Attribute { "{}({})", path.get_rust(), items - .iter() + .into_iter() .map(Attribute::get_rust) .collect::>() .join(", ") @@ -367,7 +365,7 @@ impl GetRust for Attribute { } impl ToRust for TopLevelKind { - fn to_rust(&self, cg: &mut RustCodegen) { + fn to_rust(self, cg: &mut RustCodegen) { match self { Self::ModAttribute => {} Self::Import(vis, path) => { @@ -433,7 +431,7 @@ impl ToRust for TopLevelKind { if requirements.len() != 0 { String::from(": ") + &requirements - .iter() + .into_iter() .map(TypeExpr::get_rust) .collect::>() .join("+") @@ -462,12 +460,12 @@ impl ToRust for TopLevelKind { cg.addln(&format!( "{}struct {}{} {{", visibility.get_rust(), - name.get_rust(), - generics.get_rust() + name.clone().get_rust(), + generics.clone().get_rust() )); cg.indent += 1; - for field in fields { + for field in fields.clone() { cg.add_indentedln(&field.decl.get_rust()); } @@ -477,14 +475,15 @@ impl ToRust for TopLevelKind { // Constructor cg.addln(&format!( "impl{} {}{} {{", - generics.get_rust(), - name.get_rust(), + generics.clone().get_rust(), + name.clone().get_rust(), format!( "<{}>", generics + .clone() .0 - .iter() - .map(|v| (false, v).get_rust()) + .into_iter() + .map(|v| Generic::from(v).get_rust()) .collect::>() .join(", ") ) @@ -494,7 +493,8 @@ impl ToRust for TopLevelKind { let params_str = constructor .params .0 - .iter() + .clone() + .into_iter() .map(VarDecl::get_rust) .collect::>() .join(", "); @@ -502,8 +502,8 @@ impl ToRust for TopLevelKind { cg.add_indentedln("#[allow(invalid_value)]"); cg.add_indentedln(&format!( "{}fn new{}({}) -> Self {{", - constructor.visibility.get_rust(), - constructor.generics.get_rust(), + constructor.visibility.clone().get_rust(), + constructor.generics.clone().get_rust(), params_str )); cg.indent += 1; @@ -511,7 +511,7 @@ impl ToRust for TopLevelKind { cg.add_indentedln("let mut this: Self = unsafe { std::mem::MaybeUninit::::zeroed().assume_init() };"); for field in fields { - if let Some(init) = &field.init { + if let Some(init) = field.init { cg.add_indentedln(&format!( "this.{} = {};", field.decl.name.get_rust(), @@ -525,7 +525,7 @@ impl ToRust for TopLevelKind { constructor .params .0 - .iter() + .into_iter() .map(|e| e.name.get_rust()) .collect::>() .join(", ") @@ -550,7 +550,7 @@ impl ToRust for TopLevelKind { cg.indent -= 1; cg.add_indentedln("}\n"); - for item in items { + for item in items.clone() { match item { ClassItem::ImplDecl(_) => {} ClassItem::Method(method) => method.to_rust(cg), @@ -580,7 +580,7 @@ impl ToRust for TopLevelKind { } impl ToRust for Statement { - fn to_rust(&self, cg: &mut RustCodegen) { + fn to_rust(self, cg: &mut RustCodegen) { match self { Statement::Expression(expr) => { cg.add_indentedln(&format!("{};", expr.get_rust())); @@ -596,7 +596,6 @@ impl ToRust for Statement { Statement::VarDecl(VarDeclStmt { decl, init }) => { let init = init - .as_ref() .map(|e| format!(" = {}", e.get_rust())) .unwrap_or_default(); @@ -639,11 +638,11 @@ impl ToRust for Statement { else_branch, } => { cg.add_indentedln(&format!("if {}", initial.condition.get_rust())); - cg.ensure_brackets(&initial.body); + 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); + cg.ensure_brackets(else_if_branch.body); } if let Some(else_br) = else_branch { @@ -692,7 +691,7 @@ impl ToRust for Statement { } => { cg.add_indentedln(&format!( "for {}{} in {}", - get_mutable(*mutable), + get_mutable(mutable), pattern.get_rust(), iterator.get_rust() )); @@ -700,7 +699,7 @@ impl ToRust for Statement { } Statement::Return(expr) => { - let val = expr.as_ref().map(|e| e.get_rust()).unwrap_or_default(); + let val = expr.map(|e| e.get_rust()).unwrap_or_default(); cg.add_indentedln(&format!("return {};", val)); } @@ -714,11 +713,11 @@ impl ToRust for Statement { } impl ToRust for FunctionDecl { - fn to_rust(&self, cg: &mut RustCodegen) { + fn to_rust(self, cg: &mut RustCodegen) { let params_str = self .params .0 - .iter() + .into_iter() .map(VarDecl::get_rust) .collect::>() .join(", "); @@ -731,7 +730,7 @@ impl ToRust for FunctionDecl { params_str, self.return_type.get_rust() )); - if let Some(body) = &self.body { + if let Some(body) = self.body { cg.add_indentedln("{\n"); cg.indent += 1; body.to_rust(cg); @@ -744,8 +743,8 @@ impl ToRust for FunctionDecl { } impl ToRust for ImplDecl { - fn to_rust(&self, cg: &mut RustCodegen) { - if let Some(trait_) = &self.trait_ { + fn to_rust(self, cg: &mut RustCodegen) { + if let Some(trait_) = self.trait_ { cg.add_indentedln(&format!( "impl{} {} for {} {{", self.generics.get_rust(), @@ -761,7 +760,7 @@ impl ToRust for ImplDecl { } cg.indent += 1; - for method in &self.methods { + for method in self.methods { method.to_rust(cg); } @@ -771,10 +770,9 @@ impl ToRust for ImplDecl { } impl GetRust for VarDecl { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { let ty = self .type_ - .as_ref() .map(|t| format!(": {}", t.get_rust())) .unwrap_or_default(); @@ -788,9 +786,9 @@ impl GetRust for VarDecl { } impl GetRust for Path { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { self.0 - .iter() + .into_iter() .map(Identifier::get_rust) .collect::>() .join("::") @@ -798,7 +796,7 @@ impl GetRust for Path { } impl GetRust for TypePostfix { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { TypePostfix::Ref => format!("&"), TypePostfix::RefMut => format!("&mut "), @@ -809,7 +807,7 @@ impl GetRust for TypePostfix { } impl GetRust for Visibility { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { Visibility::Public => "pub ".to_string(), Visibility::PublicTarget(path) => format!("pub({}) ", path.get_rust()), @@ -819,19 +817,19 @@ impl GetRust for Visibility { } impl GetRust for Identifier { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { self.0.clone() } } impl GetRust for EnumItem { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { Self::Named(id) => id.get_rust(), Self::Struct(id, s) => format!( "{} {{{}}}", id.get_rust(), - s.iter() + s.into_iter() .map(|field| format!("{}: {}", field.name.get_rust(), field.type_.get_rust())) .collect::>() .join(", ") @@ -839,7 +837,7 @@ impl GetRust for EnumItem { Self::Tuple(id, t) => format!( "{} ({})", id.get_rust(), - t.iter() + t.into_iter() .map(TypeExpr::get_rust) .collect::>() .join(", ") @@ -849,7 +847,7 @@ impl GetRust for EnumItem { } impl GetRust for Pattern { - fn get_rust(&self) -> String { + fn get_rust(self) -> String { match self { Self::Id(id) => id.get_rust(), Self::Path(path) => path.get_rust(), @@ -857,14 +855,14 @@ impl GetRust for Pattern { Self::Struct(path, ids) => format!( "{} {{{}}}", path.get_rust(), - ids.iter() + ids.into_iter() .map(Identifier::get_rust) .collect::>() .join(", ") ), Self::Tuple(ids) => format!( "({})", - ids.iter() + ids.into_iter() .map(Identifier::get_rust) .collect::>() .join(", ") @@ -873,7 +871,7 @@ impl GetRust for Pattern { format!( "{} ({})", path.get_rust(), - ids.iter() + ids.into_iter() .map(Identifier::get_rust) .collect::>() .join(", ") @@ -883,16 +881,16 @@ impl GetRust for Pattern { } } -impl GetRust for Generics { - fn get_rust(&self) -> String { +impl GetRust for GenericsDecl { + fn get_rust(self) -> String { if self.0.len() == 0 { String::new() } else { format!( "<{}>", self.0 - .iter() - .map(|v| (false, v).get_rust()) + .into_iter() + .map(|v| v.get_rust()) .collect::>() .join(", ") ) @@ -900,17 +898,17 @@ impl GetRust for Generics { } } -impl GetRust for (bool, &Generic) { - fn get_rust(&self) -> String { - match &self.1 { - Generic::Lifetime(name) => format!("'{}", name.get_rust()), - Generic::Type(name, requirements) => { +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 self.0 && requirements.len() != 0 { + + &(if requirements.len() != 0 { format!( ": {}", requirements - .iter() + .into_iter() .map(TypeExpr::get_rust) .collect::>() .join("+") @@ -923,8 +921,34 @@ impl GetRust for (bool, &Generic) { } } +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 { + fn get_rust(self) -> String { format!( "{}{}: {},", self.visibility.get_rust(), @@ -934,7 +958,7 @@ impl GetRust for FieldDecl { } } -pub fn get_static_type_path(path: &Path) -> String { +pub fn get_static_type_path(path: Path) -> String { let rust_path = path.get_rust(); if rust_path == "void" { @@ -944,8 +968,12 @@ pub fn get_static_type_path(path: &Path) -> String { } } -pub fn get_type_postfixes(postfixes: &[TypePostfix]) -> String { - postfixes.iter().map(TypePostfix::get_rust).collect() +pub fn get_type_postfixes(postfixes: Vec) -> String { + postfixes + .into_iter() + .map(TypePostfix::get_rust) + .rev() + .collect() } pub fn get_mutable(mutable: bool) -> String { diff --git a/src/compiler.rs b/src/compiler.rs index 1510f7a..e1dd733 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -69,13 +69,13 @@ fn build_dir(root: &Path, base_src: &Path, current_dir: &Path, out_dir: &Path) { continue; } - // skip non-mist files + let relative = path.strip_prefix(base_src).unwrap(); + if path.extension().and_then(|e| e.to_str()) != Some("mist") { + fs::copy(&path, out_dir.join(relative)).expect("Failed to copy non-mist file"); continue; } - let relative = path.strip_prefix(base_src).unwrap(); - let output_path = out_dir.join(relative).with_extension("rs"); // create parent directories @@ -133,7 +133,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 output = gc.generate(&ast); + let output = gc.generate(ast); if let Err(e) = fs::write(&output_path, output) { eprintln!(