diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index 94c4b4a..788c7bb 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -1,9 +1,33 @@ +use ; + +public trait TestLogging: fmt::Display { + String get(); +} + public enum LogLevel { Info, Warning, Error, } +impl fmt::Display for LogLevel { + std::fmt::Result fmt(self*, std::fmt::Formatter<'_> mut* f) { + match (self) { + LogLevel::Info => { + return write!(f, "[INFO]"); + } + + LogLevel::Warning => { + return write!(f, "[WARN]"); + } + + LogLevel::Error => { + return write!(f, "[ERROR]"); + } + } + } +} + public class Logger { String prefix; @@ -26,16 +50,22 @@ public class Logger { void log(self*, LogLevel level, str* message) { match(level) { LogLevel::Info => { - println!("[INFO] {} {}", self.prefix, message); + println!("{level} {} {}", self.prefix, message); } LogLevel::Warning => { - println!("[WARN] {} {}", self.prefix, message); + println!("{level} {} {}", self.prefix, message); } LogLevel::Error => { - println!("[ERROR] {} {}", self.prefix, message); + println!("{level} {} {}", self.prefix, message); } } } + + impl fmt::Display { + std::fmt::Result fmt(self*, std::fmt::Formatter<'_> mut* f) { + return write!(f, "logger ({})", self.prefix); + } + } } diff --git a/parser/src/ast.rs b/parser/src/ast.rs index db081d9..ed75ba1 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -3,9 +3,6 @@ use serde::Serialize; #[derive(Debug, Clone, Serialize)] pub struct Identifier(pub String); -#[derive(Debug, Clone, Serialize, Default)] -pub struct FieldList(pub Vec<(Identifier, Visibility, TypeExpr)>); - #[derive(Debug, Clone, Serialize, Default)] pub struct ParamList(pub Vec); @@ -77,6 +74,14 @@ pub enum TopLevelKind { ModAttribute, Import(Path), Mod(Identifier), + ImplDecl(ImplDecl), + TraitDecl { + visibility: Visibility, + name: Identifier, + generics: Generics, + requirements: Vec, + items: Vec, + }, EnumDecl { visibility: Visibility, name: Identifier, @@ -85,21 +90,27 @@ pub enum TopLevelKind { }, StructDecl { visibility: Visibility, - generics: Generics, name: Identifier, - fields: FieldList, + generics: Generics, + fields: Vec, }, FunctionDecl(FunctionDecl), ClassDecl { visibility: Visibility, name: Identifier, generics: Generics, - fields: Vec, + fields: Vec, constructor: ClassConstructor, - methods: Vec, + items: Vec, }, } +#[derive(Debug, Clone, Serialize)] +pub enum ClassItem { + Method(FunctionDecl), + ImplDecl(ImplDecl), +} + #[derive(Debug, Clone, Serialize, Default)] pub struct Generics(pub Vec); @@ -123,7 +134,7 @@ pub enum Pattern { pub enum EnumItem { Named(Identifier), Tuple(Identifier, Vec), - Struct(Identifier, FieldList), + Struct(Identifier, Vec), } #[derive(Debug, Clone, Serialize)] @@ -141,7 +152,7 @@ pub struct FunctionDecl { pub generics: Generics, pub params: ParamList, pub return_type: TypeExpr, - pub body: Block, + pub body: Option, } #[derive(Debug, Clone, Serialize)] @@ -195,6 +206,14 @@ pub enum Statement { Continue, } +#[derive(Debug, Clone, Serialize)] +pub struct ImplDecl { + pub generics: Generics, + pub target: TypeExpr, + pub trait_: Option, + pub methods: Vec, +} + #[derive(Debug, Clone, Serialize)] pub struct VarDecl { pub mutable: bool, @@ -208,6 +227,19 @@ pub struct VarDeclStmt { pub init: Option, } +#[derive(Debug, Clone, Serialize)] +pub struct FieldDecl { + pub visibility: Visibility, + pub type_: TypeExpr, + pub name: Identifier, +} + +#[derive(Debug, Clone, Serialize)] +pub struct FieldDeclStmt { + pub decl: FieldDecl, + pub init: Option, +} + #[derive(Debug, Clone, Serialize)] pub struct VarAssignStmt { pub target: Expression, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 5c6e8f7..9c0aca9 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -149,7 +149,6 @@ attributes = { // ====================================================== // DECLARATION HELPERS // ====================================================== - var_decl = { (var | type_expr) ~ mutable? ~ pattern } @@ -225,7 +224,11 @@ class_constructor = { } class_fields = { - var_decl_statement* + class_field* +} + +class_field = { + field ~ ("=" ~ expr)? ~ semicolon } self_param = { @@ -236,8 +239,42 @@ method = { export? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ block } +class_item = _{ + impl_decl + | method +} + class_decl = { - export? ~ "class" ~ identifier ~ generics? ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}" + export? ~ "class" ~ identifier ~ generics? ~ "{" ~ class_fields ~ class_constructor ~ class_item* ~ "}" +} + +// ====================================================== +// IMPL +// ====================================================== +impl_for_decl = { + "impl" ~ generics? ~ type_expr ~ "for" ~ type_expr ~ "{" ~ method* ~ "}" +} + +impl_decl = { + "impl" ~ generics? ~ type_expr ~ "{" ~ method* ~ "}" +} + +// ====================================================== +// Traits +// ====================================================== +trait_requirements = { ":" ~ type_expr_param ~ ("+" ~ type_expr_param)* } + +method_no_body = { + export? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ semicolon +} + +trait_item = _{ + method + | method_no_body +} + +trait_decl = { + export? ~ "trait" ~ identifier ~ generics? ~ trait_requirements? ~ "{" ~ trait_item* ~ "}" } // ====================================================== @@ -253,7 +290,7 @@ function_decl = { // ====================================================== top_level = { - (attributes ~ (import | function_decl | struct_decl | enum_decl | class_decl | mod_package)) + (attributes ~ (import | impl_for_decl | impl_decl | trait_decl | struct_decl | enum_decl | class_decl | mod_package | function_decl)) | mod_attribute } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index e17057c..ba4193b 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -107,23 +107,6 @@ impl From> for Path { } } -impl From> for FieldList { - fn from(pair: pest::iterators::Pair) -> Self { - let params = pair - .into_inner() - .map(|p| { - let mut param_inner = p.into_inner(); - let visibility = Visibility::from(&mut param_inner); - let param_type = TypeExpr::from(param_inner.next().unwrap()); - let param_name = Identifier::from(param_inner.next().unwrap()); - (param_name, visibility, param_type) - }) - .collect(); - - FieldList(params) - } -} - impl From> for ParamList { fn from(pair: pest::iterators::Pair) -> Self { ParamList(pair.into_inner().map(VarDecl::from).collect()) @@ -287,7 +270,10 @@ impl From> for TopLevelKind { generics: consume_rule(&mut inner, Rule::generics) .map(Generics::from) .unwrap_or_default(), - fields: inner.next().map(FieldList::from).unwrap_or_default(), + fields: inner + .next() + .map(|pair| pair.into_inner().map(FieldDecl::from).collect()) + .unwrap_or_default(), }, Rule::class_decl => TopLevelKind::ClassDecl { @@ -300,10 +286,10 @@ impl From> for TopLevelKind { .next() .unwrap() .into_inner() - .map(VarDeclStmt::from) + .map(FieldDeclStmt::from) .collect(), constructor: ClassConstructor::from(inner.next().unwrap()), - methods: inner.into_iter().map(FunctionDecl::from).collect(), + items: inner.into_iter().map(ClassItem::from).collect(), }, Rule::enum_decl => TopLevelKind::EnumDecl { @@ -317,6 +303,63 @@ impl From> for TopLevelKind { Rule::mod_package => TopLevelKind::Mod(Identifier::from(inner.next().unwrap())), + Rule::impl_for_decl | Rule::impl_decl => TopLevelKind::ImplDecl(ImplDecl::from(pair)), + + Rule::trait_decl => TopLevelKind::TraitDecl { + visibility: Visibility::from(&mut inner), + name: Identifier::from(inner.next().unwrap()), + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or_default(), + requirements: consume_rule(&mut inner, Rule::trait_requirements) + .map(|pair| pair.into_inner().map(TypeExpr::from).collect()) + .unwrap_or_default(), + items: inner.map(FunctionDecl::from).collect(), + }, + + _ => unimplemented!("{rule:#?}"), + } + } +} + +impl From> for ClassItem { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let rule = pair.as_rule(); + + match rule { + Rule::impl_decl | Rule::impl_for_decl => ClassItem::ImplDecl(ImplDecl::from(pair)), + + Rule::method => ClassItem::Method(FunctionDecl::from(pair)), + + _ => unimplemented!("{rule:#?}"), + } + } +} + +impl From> for ImplDecl { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let rule = pair.as_rule(); + let mut inner = pair.clone().into_inner(); + + match rule { + Rule::impl_for_decl => ImplDecl { + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or_default(), + trait_: Some(TypeExpr::from(inner.next().unwrap())), + target: TypeExpr::from(inner.next().unwrap()), + methods: inner.map(FunctionDecl::from).collect(), + }, + + Rule::impl_decl => ImplDecl { + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or_default(), + trait_: None, + target: TypeExpr::from(inner.next().unwrap()), + methods: inner.map(FunctionDecl::from).collect(), + }, + _ => unimplemented!("{rule:#?}"), } } @@ -342,7 +385,10 @@ impl From> for EnumItem { Rule::enum_struct => EnumItem::Struct( Identifier::from(inner.next().unwrap()), - FieldList::from(inner.next().unwrap()), + inner + .next() + .map(|pair| pair.into_inner().map(FieldDecl::from).collect()) + .unwrap_or_default(), ), _ => unimplemented!("{rule:#?}"), @@ -583,6 +629,24 @@ impl From> for VarDeclStmt { } } +impl From> for FieldDeclStmt { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { + Rule::class_field => { + let mut inner = pair.into_inner(); + + let decl = FieldDecl::from(inner.next().unwrap()); + + let init = inner.next().map(Expression::from); + + FieldDeclStmt { decl, init } + } + + _ => unimplemented!(), + } + } +} + impl From> for Pattern { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let rule = pair.as_rule(); @@ -641,6 +705,28 @@ impl From> for VarDecl { } } +impl From> for FieldDecl { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { + Rule::field => { + let mut inner = pair.into_inner(); + + let visibility = Visibility::from(&mut inner); + let type_ = TypeExpr::from(inner.next().unwrap()); + let name = Identifier::from(inner.next().unwrap()); + + FieldDecl { + visibility, + type_, + name, + } + } + + _ => unimplemented!("{:?}", pair.as_rule()), + } + } +} + impl From> for FunctionDecl { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let mut inner = pair.into_inner(); @@ -690,7 +776,7 @@ impl From> for FunctionDecl { }) .unwrap_or_else(|| ParamList(self_param.into_iter().collect())); - let body = Block::from(inner.next().unwrap()); + let body = inner.next().map(Block::from); Self { visibility, diff --git a/src/codegen.rs b/src/codegen.rs index 437a99f..5ed33b0 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,7 +1,8 @@ use parser::ast::{ - Attribute, BinaryOp, Block, EnumItem, Expression, FunctionDecl, Generic, Generics, Identifier, - Literal, Path, Pattern, Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, - TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, Visibility, + Attribute, BinaryOp, Block, ClassItem, EnumItem, Expression, FieldDecl, FunctionDecl, Generic, + Generics, Identifier, ImplDecl, Literal, Path, Pattern, Postfix, Prefix, Statement, + StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, + VarDecl, VarDeclStmt, Visibility, }; // --------------------------------------------------------------------------- @@ -314,6 +315,7 @@ impl ToRust for TopLevelKind { Self::Import(path) => cg.addln(&format!("use {};", path.get_rust())), Self::Mod(id) => cg.addln(&format!("mod {};", id.get_rust())), Self::FunctionDecl(decl) => decl.to_rust(cg), + Self::ImplDecl(impl_) => impl_.to_rust(cg), Self::StructDecl { visibility, name, @@ -328,9 +330,8 @@ impl ToRust for TopLevelKind { )); cg.indent += 1; - for (field_name, _, ty) in &fields.0 { - let ty = ty.get_rust(); - cg.add_indentedln(&format!("pub {}: {},", field_name.get_rust(), ty)); + for field in fields { + cg.add_indentedln(&field.get_rust()); } cg.indent -= 1; @@ -357,13 +358,45 @@ impl ToRust for TopLevelKind { 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 + .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, - methods, + items, } => { // Struct decl cg.addln(&format!( @@ -375,8 +408,7 @@ impl ToRust for TopLevelKind { cg.indent += 1; for field in fields { - let ty = field.decl.type_.clone().unwrap().get_rust(); - cg.add_indentedln(&format!("pub {}: {},", field.decl.name.get_rust(), ty)); + cg.add_indentedln(&field.decl.get_rust()); } cg.indent -= 1; @@ -458,12 +490,30 @@ impl ToRust for TopLevelKind { cg.indent -= 1; cg.add_indentedln("}\n"); - for method in methods { - method.to_rust(cg); + for item in items { + 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_.trait_ = Some(impl_.target); + impl_.target = + TypeExpr(TypeExprKind::Path(Path(vec![name.clone()])), Vec::new()); + + impl_.to_rust(cg); + } + ClassItem::Method(_) => {} + } + } } } } @@ -602,17 +652,49 @@ impl ToRust for FunctionDecl { .join(", "); cg.add_indentedln(&format!( - "{}fn {}{}({}) -> {} {{", + "{}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; - self.body.to_rust(cg); + + for method in &self.methods { + method.to_rust(cg); + } + cg.indent -= 1; - cg.add_indentedln("}\n"); + cg.add_indentedln("}"); } } @@ -677,8 +759,8 @@ impl GetRust for EnumItem { Self::Struct(id, s) => format!( "{} {{{}}}", id.get_rust(), - s.0.iter() - .map(|(id, _, ty)| format!("{}: {}", id.get_rust(), ty.get_rust())) + s.iter() + .map(|field| format!("{}: {}", field.name.get_rust(), field.type_.get_rust())) .collect::>() .join(", ") ), @@ -769,6 +851,17 @@ impl GetRust for (bool, &Generic) { } } +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();