From 39b15d42071c5f0e73bb1fcd810253b0d1d0564f Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 15:43:57 +0200 Subject: [PATCH 1/7] More binary op --- parser/src/ast.rs | 2 ++ parser/src/grammar.pest | 2 +- parser/src/lib.rs | 2 ++ src/codegen.rs | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 7ff1df8..dc77c0e 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -62,6 +62,8 @@ pub enum BinaryOp { GreaterThan, LessThanOrEqual, GreaterThanOrEqual, + And, + Or, } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 7c207f5..d4b35ad 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -192,7 +192,7 @@ macro_call_px = { "!" ~ "(" ~ macro_inner_v* ~ ")" } struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" } index_px = { "[" ~ expr ~ "]" } binary_px = { bin_op ~ expr } -bin_op = { "<=" | ">=" | "==" | "!=" | "+" | "-" | "*" | "/" | "%" | "<" | ">" } +bin_op = { "<=" | ">=" | "==" | "!=" | "&&" | "||" | "+" | "-" | "*" | "/" | "%" | "<" | ">" } struct_field_decl = { identifier ~ ":" ~ expr } prefix = { diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 636223a..2128993 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -498,6 +498,8 @@ impl From> for Postfix { ">" => BinaryOp::GreaterThan, "<=" => BinaryOp::LessThanOrEqual, ">=" => BinaryOp::GreaterThanOrEqual, + "&&" => BinaryOp::And, + "||" => BinaryOp::Or, _ => { unimplemented!("Binary operator not implemented yet: {}", op_pair.as_str()) diff --git a/src/codegen.rs b/src/codegen.rs index 6558d35..96e5bd7 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -238,6 +238,8 @@ impl GetRust for Postfix { BinaryOp::GreaterThan => ">", BinaryOp::LessThanOrEqual => "<=", BinaryOp::GreaterThanOrEqual => ">=", + BinaryOp::And => "&&", + BinaryOp::Or => "||", }; format!(" {} {}", op_str, rhs.get_rust()) } From 630528a8433f2a8330ad7bc76e5bd60244597785 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 15:55:09 +0200 Subject: [PATCH 2/7] Organized grammar --- parser/src/grammar.pest | 426 ++++++++++++++++++++++++++++++++-------- 1 file changed, 344 insertions(+), 82 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index d4b35ad..3b7eb05 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -1,59 +1,115 @@ +// ====================================================== +// LEXICAL +// ====================================================== + WHITESPACE = _{ " " | "\t" | "\r" | "\n" } COMMENT = _{ "//" ~ (!"\n" ~ ANY)* } -program = { SOI ~ top_level* ~ EOI } +// ------------------------------------------------------ +// PRIMITIVES +// ------------------------------------------------------ -// primitives -identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* } -integer = @{ ASCII_DIGIT+ } -float = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ } -boolean = { "true" | "false" } -string_lit = { "\"" ~ inner_str ~ "\"" } -inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* } -static_path = { identifier ~ ("::" ~ identifier)* } +identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* } -// pattern -tuple_pattern = { "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" } -named_tuple_pattern = { static_path ~ "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" } -struct_pattern = { static_path ~ "{" ~ (identifier ~ ("," ~ identifier)*)? ~ "}" } -pattern = _{ named_tuple_pattern | tuple_pattern | struct_pattern | literal | static_path } +integer = @{ ASCII_DIGIT+ } + +float = @{ + ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ +} + +boolean = { + "true" + | "false" +} + +string_lit = { + "\"" ~ inner_str ~ "\"" +} + +inner_str = @{ + (!"\"" ~ ("\\\"" | ANY))* +} -export = { "public" } -mutable = { "mut" } -var = { "var" } -var_decl = { (var | type_expr) ~ mutable? ~ pattern } semicolon = _{ ";" } -// ================= CLASS ================= -class_constructor = { - export? ~ "constructor" ~ "(" ~ param_list? ~ ")" ~ block +static_path = { + identifier ~ ("::" ~ identifier)* } -class_fields = { var_decl_statement* } +// ====================================================== +// PROGRAM +// ====================================================== -self_param = { "self" ~ mutable? ~ deref_px? } - -method = { - export? ~ type_expr ~ identifier ~ "(" ~ self_param? ~ param_list? ~ ")" ~ block +program = { + SOI ~ top_level* ~ EOI } -class_decl = { - export? ~ "class" ~ identifier ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}" +// ====================================================== +// MODIFIERS +// ====================================================== + +export = { "public" } +mutable = { "mut" } +var = { "var" } + +// ====================================================== +// TYPES +// ====================================================== + +tuple_type = { + "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } -// ================= TOP LEVEL ================= +path_type = { + static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? +} -enum_named = { identifier } -enum_tuple = { identifier ~ tuple_type } -enum_struct = { identifier ~ "{" ~ field_list ~ "}" } +ref_type = { + mutable? ~ "*" +} -enum_field = _{ enum_tuple | enum_struct | enum_named } +type_expr = { + (path_type | tuple_type) ~ ref_type* +} -enum_fields = _{ enum_field ~ ("," ~ enum_field)* ~ ","? } +// ====================================================== +// LITERALS +// ====================================================== -enum_decl = { export? ~ "enum" ~ identifier ~ "{" ~ enum_fields ~ "}" } +literal = { + float + | integer + | boolean + | string_lit +} -top_level = { (attributes ~ (import | function_decl | struct_decl | enum_decl | class_decl | mod_package)) | mod_attribute } +// ====================================================== +// PATTERNS +// ====================================================== + +tuple_pattern = { + "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" +} + +named_tuple_pattern = { + static_path ~ "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" +} + +struct_pattern = { + static_path ~ "{" ~ (identifier ~ ("," ~ identifier)*)? ~ "}" +} + +pattern = _{ + named_tuple_pattern + | tuple_pattern + | struct_pattern + | literal + | static_path +} + +// ====================================================== +// ATTRIBUTES / META +// ====================================================== attribute = { "#" ~ "[" ~ meta ~ "]" @@ -71,30 +127,132 @@ meta_list = { meta ~ ("," ~ meta)* ~ ","? } -attributes = { attribute* } +attributes = { + attribute* +} -import = { "use" ~ "<" ~ static_path ~ ">" ~ semicolon } +// ====================================================== +// DECLARATION HELPERS +// ====================================================== -mod_package = { "mod" ~ identifier ~ semicolon } +var_decl = { + (var | type_expr) ~ mutable? ~ pattern +} -field_list = { field ~ ("," ~ field)* ~ ","? } -field = { export? ~ type_expr ~ identifier } +field = { + export? ~ type_expr ~ identifier +} -param_list = { var_decl ~ ("," ~ var_decl)* ~ ","? } +field_list = { + field ~ ("," ~ field)* ~ ","? +} + +param_list = { + var_decl ~ ("," ~ var_decl)* ~ ","? +} + +// ====================================================== +// IMPORTS / MODULES +// ====================================================== + +import = { + "use" ~ "<" ~ static_path ~ ">" ~ semicolon +} + +mod_package = { + "mod" ~ identifier ~ semicolon +} + +// ====================================================== +// STRUCTS +// ====================================================== struct_decl = { export? ~ "struct" ~ identifier ~ "{" ~ field_list? ~ "}" } +// ====================================================== +// ENUMS +// ====================================================== + +enum_named = { + identifier +} + +enum_tuple = { + identifier ~ tuple_type +} + +enum_struct = { + identifier ~ "{" ~ field_list ~ "}" +} + +enum_field = _{ + enum_tuple + | enum_struct + | enum_named +} + +enum_fields = _{ + enum_field ~ ("," ~ enum_field)* ~ ","? +} + +enum_decl = { + export? ~ "enum" ~ identifier ~ "{" ~ enum_fields ~ "}" +} + +// ====================================================== +// CLASSES +// ====================================================== + +class_constructor = { + export? ~ "constructor" ~ "(" ~ param_list? ~ ")" ~ block +} + +class_fields = { + var_decl_statement* +} + +self_param = { + "self" ~ mutable? ~ deref_px? +} + +method = { + export? ~ type_expr ~ identifier ~ "(" ~ self_param? ~ param_list? ~ ")" ~ block +} + +class_decl = { + export? ~ "class" ~ identifier ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}" +} + +// ====================================================== +// FUNCTIONS +// ====================================================== + function_decl = { export? ~ type_expr ~ identifier ~ "(" ~ param_list? ~ ")" ~ block } -// ================= STATEMENTS ================= +// ====================================================== +// TOP LEVEL +// ====================================================== -block = { "{" ~ statement_list ~ "}" } +top_level = { + (attributes ~ (import | function_decl | struct_decl | enum_decl | class_decl | mod_package)) + | mod_attribute +} -statement_list = { statement* } +// ====================================================== +// STATEMENTS +// ====================================================== + +block = { + "{" ~ statement_list ~ "}" +} + +statement_list = { + statement* +} statement = _{ expr_stmt @@ -111,28 +269,54 @@ statement = _{ | block } -// --- basic statements --- +// ------------------------------------------------------ +// BASIC STATEMENTS +// ------------------------------------------------------ -expr_stmt = { expr ~ semicolon } +expr_stmt = { + expr ~ semicolon +} -return_stmt = { "return" ~ expr? ~ semicolon } +return_stmt = { + "return" ~ expr? ~ semicolon +} -break_stmt = { "break" ~ semicolon } +break_stmt = { + "break" ~ semicolon +} -continue_stmt = { "continue" ~ semicolon } +continue_stmt = { + "continue" ~ semicolon +} -var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ semicolon } +var_decl_statement = { + var_decl ~ ("=" ~ expr)? ~ semicolon +} -assign_statement = { expr ~ "=" ~ expr ~ semicolon } +assign_statement = { + expr ~ "=" ~ expr ~ semicolon +} -else_if = { "else" ~ "if" ~ "(" ~ expr ~ ")" ~ statement } +// ------------------------------------------------------ +// CONDITIONALS +// ------------------------------------------------------ -else_if_list = { else_if* } +else_if = { + "else" ~ "if" ~ "(" ~ expr ~ ")" ~ statement +} + +else_if_list = { + else_if* +} if_stmt = { "if" ~ "(" ~ expr ~ ")" ~ statement ~ else_if_list ~ ("else" ~ statement)? } +// ------------------------------------------------------ +// LOOPS +// ------------------------------------------------------ + while_stmt = { "while" ~ "(" ~ expr ~ ")" ~ statement } @@ -145,31 +329,42 @@ for_stmt = { "for" ~ "(" ~ mutable? ~ pattern ~ "in" ~ expr ~ ")" ~ statement } -match_item = { pattern ~ "=>" ~ block } +// ------------------------------------------------------ +// MATCH +// ------------------------------------------------------ + +match_item = { + pattern ~ "=>" ~ block +} match_stmt = { "match" ~ "(" ~ expr ~ ")" ~ "{" ~ match_item* ~ "}" } -// ================= EXPRESSIONS ================= -tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } -path_type = { static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? } -ref_type = { mutable? ~ "*" } -type_expr = { (path_type | tuple_type) ~ ref_type* } +// ====================================================== +// EXPRESSIONS +// ====================================================== + +// ------------------------------------------------------ +// TUPLES +// ------------------------------------------------------ + +tuple = { + "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" +} + +// ------------------------------------------------------ +// MACROS +// ------------------------------------------------------ macro_inner_v = { "(" ~ macro_inner_v* ~ ")" | (!("(" | ")") ~ ANY) } -tuple = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } - -literal = { - float - | integer - | boolean - | string_lit -} +// ------------------------------------------------------ +// PRIMARY EXPRESSIONS +// ------------------------------------------------------ primary = { literal @@ -177,6 +372,38 @@ primary = { | tuple } +// ------------------------------------------------------ +// POSTFIX EXPRESSIONS +// ------------------------------------------------------ + +field_px = { + "." ~ identifier +} + +call_px = { + "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" +} + +macro_call_px = { + "!" ~ "(" ~ macro_inner_v* ~ ")" +} + +struct_field_decl = { + identifier ~ ":" ~ expr +} + +struct_px = { + "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" +} + +index_px = { + "[" ~ expr ~ "]" +} + +binary_px = { + bin_op ~ expr +} + postfix = { field_px | call_px @@ -186,14 +413,29 @@ postfix = { | binary_px } -field_px = { "." ~ identifier } -call_px = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } -macro_call_px = { "!" ~ "(" ~ macro_inner_v* ~ ")" } -struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" } -index_px = { "[" ~ expr ~ "]" } -binary_px = { bin_op ~ expr } -bin_op = { "<=" | ">=" | "==" | "!=" | "&&" | "||" | "+" | "-" | "*" | "/" | "%" | "<" | ">" } -struct_field_decl = { identifier ~ ":" ~ expr } +// ------------------------------------------------------ +// PREFIX EXPRESSIONS +// ------------------------------------------------------ + +deref_px = { + "*" +} + +mut_ref_px = { + "&" ~ mutable +} + +ref_px = { + "&" +} + +new_px = { + "new" +} + +not_px = { + "!" +} prefix = { deref_px @@ -203,13 +445,33 @@ prefix = { | not_px } -deref_px = { "*" } -mut_ref_px = { "&" ~ mutable } -ref_px = { "&" } -new_px = { "new" } -not_px = { "!" } +prefix_list = { + prefix* +} -prefix_list = { prefix* } +// ------------------------------------------------------ +// OPERATORS +// ------------------------------------------------------ + +bin_op = { + "<=" + | ">=" + | "==" + | "!=" + | "&&" + | "||" + | "+" + | "-" + | "*" + | "/" + | "%" + | "<" + | ">" +} + +// ------------------------------------------------------ +// EXPRESSIONS +// ------------------------------------------------------ expr = { prefix_list ~ primary ~ postfix* From 205e2d9fd34ac1d6870978848ff6692ff00e9c26 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 16:48:31 +0200 Subject: [PATCH 3/7] generics parsing and AST --- parser/src/ast.rs | 4 ++++ parser/src/grammar.pest | 8 +++++++- parser/src/lib.rs | 42 +++++++++++++++++++++++++++++------------ 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index dc77c0e..8b29051 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -81,6 +81,7 @@ pub enum TopLevelKind { }, StructDecl { visibility: Visibility, + generics: Generics, name: Identifier, fields: FieldList, }, @@ -94,6 +95,9 @@ pub enum TopLevelKind { }, } +#[derive(Debug, Clone, Serialize)] +pub struct Generics(pub Vec<(Identifier, Vec)>); + #[derive(Debug, Clone, Serialize)] pub enum Pattern { NamedTuple(Path, Vec), diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 3b7eb05..5d8b892 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -52,6 +52,12 @@ export = { "public" } mutable = { "mut" } var = { "var" } +// ====================================================== +// GENERICS +// ====================================================== +generic = { identifier ~ (":" ~ static_path ~ ("+" ~ static_path)*)? } +generics = { "<" ~ (generic ~ ("," ~ generic)*)? ~ ">" } + // ====================================================== // TYPES // ====================================================== @@ -168,7 +174,7 @@ mod_package = { // ====================================================== struct_decl = { - export? ~ "struct" ~ identifier ~ "{" ~ field_list? ~ "}" + export? ~ "struct" ~ identifier ~ generics? ~ "{" ~ field_list? ~ "}" } // ====================================================== diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 2128993..79886ac 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -223,6 +223,28 @@ impl From> for ClassConstructor { } } +impl From> for Generics { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let rule = pair.as_rule(); + let inner = pair.clone().into_inner(); + + match rule { + Rule::generics => Generics( + inner + .map(|pair| { + let mut inner = pair.into_inner(); + ( + Identifier::from(inner.next().unwrap()), + inner.map(Path::from).collect(), + ) + }) + .collect(), + ), + _ => unimplemented!("{rule:#?}"), + } + } +} + impl From> for TopLevelKind { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let rule = pair.as_rule(); @@ -233,18 +255,14 @@ impl From> for TopLevelKind { Rule::function_decl => TopLevelKind::FunctionDecl(FunctionDecl::from(pair)), - Rule::struct_decl => { - let visibility = Visibility::from(&mut inner); - let name = Identifier::from(inner.next().unwrap()); - let fields_pair = inner.next().unwrap(); - let fields = FieldList::from(fields_pair); - - TopLevelKind::StructDecl { - visibility, - name, - fields, - } - } + Rule::struct_decl => TopLevelKind::StructDecl { + visibility: Visibility::from(&mut inner), + name: Identifier::from(inner.next().unwrap()), + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or(Generics(Vec::new())), + fields: FieldList::from(inner.next().unwrap()), + }, Rule::class_decl => TopLevelKind::ClassDecl { visibility: Visibility::from(&mut inner), From 0e6c73e85c8bdcb65fc079fcf616f2226061f972 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 16:54:11 +0200 Subject: [PATCH 4/7] generics codege --- src/codegen.rs | 40 ++++++++++++++++++++++++++++++++++++---- test/src/main.mist | 2 ++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 96e5bd7..c4ebdc3 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,6 +1,6 @@ use parser::ast::{ - Attribute, BinaryOp, Block, EnumItem, Expression, FunctionDecl, Identifier, Literal, Path, - Pattern, Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, + Attribute, BinaryOp, Block, EnumItem, Expression, FunctionDecl, Generics, Identifier, Literal, + Path, Pattern, Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, Visibility, }; @@ -316,12 +316,14 @@ impl ToRust for TopLevelKind { Self::StructDecl { visibility, name, + generics, fields, } => { cg.addln(&format!( - "{}struct {} {{", + "{}struct {}{} {{", visibility.get_rust(), - name.get_rust() + name.get_rust(), + generics.get_rust() )); cg.indent += 1; @@ -703,6 +705,36 @@ impl GetRust for Pattern { } } +impl GetRust for Generics { + fn get_rust(&self) -> String { + if self.0.len() == 0 { + String::new() + } else { + format!( + "<{}>", + self.0 + .iter() + .map(|generic| generic.0.get_rust() + + &(if generic.1.len() == 0 { + String::new() + } else { + format!( + ": {}", + generic + .1 + .iter() + .map(Path::get_rust) + .collect::>() + .join("+") + ) + })) + .collect::>() + .join(", ") + ) + } + } +} + pub fn get_static_type_path(path: &Path) -> String { let rust_path = path.get_rust(); diff --git a/test/src/main.mist b/test/src/main.mist index 602dd59..6996a76 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -2,6 +2,8 @@ mod my_class; use ; use ; +struct Test {} + void main() { var my_class = new MyClass("World"); my_class.greet(); From ed4a505a6a5455bd468ed9d642fcd62da111d52e Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 17:00:03 +0200 Subject: [PATCH 5/7] fix generics --- parser/src/ast.rs | 8 ++++---- parser/src/lib.rs | 4 ++-- test/src/main.mist | 2 -- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 8b29051..b82abc8 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -3,13 +3,13 @@ use serde::Serialize; #[derive(Debug, Clone, Serialize)] pub struct Identifier(pub String); -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Default)] pub struct FieldList(pub Vec<(Identifier, Visibility, TypeExpr)>); -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Default)] pub struct ParamList(pub Vec); -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Default)] pub struct Block(pub Vec); #[derive(Debug, Clone, Serialize)] @@ -95,7 +95,7 @@ pub enum TopLevelKind { }, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Default)] pub struct Generics(pub Vec<(Identifier, Vec)>); #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 79886ac..062f0af 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -260,8 +260,8 @@ impl From> for TopLevelKind { name: Identifier::from(inner.next().unwrap()), generics: consume_rule(&mut inner, Rule::generics) .map(Generics::from) - .unwrap_or(Generics(Vec::new())), - fields: FieldList::from(inner.next().unwrap()), + .unwrap_or_default(), + fields: inner.next().map(FieldList::from).unwrap_or_default(), }, Rule::class_decl => TopLevelKind::ClassDecl { diff --git a/test/src/main.mist b/test/src/main.mist index 6996a76..602dd59 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -2,8 +2,6 @@ mod my_class; use ; use ; -struct Test {} - void main() { var my_class = new MyClass("World"); my_class.greet(); From bbcc6393318771c25df5f960afb2f2a99da96b69 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 17:09:01 +0200 Subject: [PATCH 6/7] More generics --- parser/src/ast.rs | 3 +++ parser/src/grammar.pest | 6 +++--- parser/src/lib.rs | 14 +++++++++++--- src/codegen.rs | 15 ++++++++++----- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index b82abc8..16a0968 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -77,6 +77,7 @@ pub enum TopLevelKind { EnumDecl { visibility: Visibility, name: Identifier, + generics: Generics, fields: Vec, }, StructDecl { @@ -89,6 +90,7 @@ pub enum TopLevelKind { ClassDecl { visibility: Visibility, name: Identifier, + generics: Generics, fields: Vec, constructor: ClassConstructor, methods: Vec, @@ -126,6 +128,7 @@ pub struct ClassConstructor { pub struct FunctionDecl { pub visibility: Visibility, pub name: Identifier, + pub generics: Generics, pub params: ParamList, pub return_type: TypeExpr, pub body: Block, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 5d8b892..8ff673b 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -204,7 +204,7 @@ enum_fields = _{ } enum_decl = { - export? ~ "enum" ~ identifier ~ "{" ~ enum_fields ~ "}" + export? ~ "enum" ~ identifier ~ generics? ~ "{" ~ enum_fields ~ "}" } // ====================================================== @@ -224,11 +224,11 @@ self_param = { } method = { - export? ~ type_expr ~ identifier ~ "(" ~ self_param? ~ param_list? ~ ")" ~ block + export? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ param_list? ~ ")" ~ block } class_decl = { - export? ~ "class" ~ identifier ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}" + export? ~ "class" ~ identifier ~ generics? ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}" } // ====================================================== diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 062f0af..13113b1 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -267,6 +267,9 @@ impl From> for TopLevelKind { Rule::class_decl => TopLevelKind::ClassDecl { visibility: Visibility::from(&mut inner), name: Identifier::from(inner.next().unwrap()), + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or_default(), fields: inner .next() .unwrap() @@ -280,6 +283,9 @@ impl From> for TopLevelKind { Rule::enum_decl => TopLevelKind::EnumDecl { visibility: Visibility::from(&mut inner), name: Identifier::from(inner.next().unwrap()), + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or_default(), fields: inner.map(EnumItem::from).collect(), }, @@ -612,12 +618,13 @@ impl From> for VarDecl { impl From> for FunctionDecl { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let mut inner = pair.into_inner(); - let visibility = Visibility::from(&mut inner); - let return_type = TypeExpr::from(inner.next().unwrap()); - let name = Identifier::from(inner.next().unwrap()); + let generics = consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .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"))); @@ -662,6 +669,7 @@ impl From> for FunctionDecl { Self { visibility, name, + generics, params, return_type, body, diff --git a/src/codegen.rs b/src/codegen.rs index c4ebdc3..b8caf83 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -338,12 +338,14 @@ impl ToRust for TopLevelKind { Self::EnumDecl { visibility, name, + generics, fields, } => { cg.addln(&format!( - "{}enum {} {{", + "{}enum {}{} {{", visibility.get_rust(), - name.get_rust() + name.get_rust(), + generics.get_rust() )); cg.indent += 1; @@ -357,15 +359,17 @@ impl ToRust for TopLevelKind { Self::ClassDecl { visibility, name, + generics, fields, constructor, methods, } => { // Struct decl cg.addln(&format!( - "{}struct {} {{", + "{}struct {}{} {{", visibility.get_rust(), - name.get_rust() + name.get_rust(), + generics.get_rust() )); cg.indent += 1; @@ -581,9 +585,10 @@ 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() )); From 65f4c5278d8abb2795649877e4c6fe1707d63ab5 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 17:14:39 +0200 Subject: [PATCH 7/7] Constructor generics --- parser/src/ast.rs | 1 + parser/src/grammar.pest | 2 +- parser/src/lib.rs | 5 +++++ src/codegen.rs | 6 ++++-- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 16a0968..ac6b1f0 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -120,6 +120,7 @@ pub enum EnumItem { #[derive(Debug, Clone, Serialize)] pub struct ClassConstructor { pub visibility: Visibility, + pub generics: Generics, pub params: ParamList, pub body: Block, } diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 8ff673b..c557e5d 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -212,7 +212,7 @@ enum_decl = { // ====================================================== class_constructor = { - export? ~ "constructor" ~ "(" ~ param_list? ~ ")" ~ block + export? ~ "constructor" ~ generics? ~ "(" ~ param_list? ~ ")" ~ block } class_fields = { diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 13113b1..fa01570 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -211,12 +211,17 @@ impl From> for ClassConstructor { let visibility = Visibility::from(&mut inner); + let generics = consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or_default(); + let params = consume_rule(&mut inner, Rule::param_list) .map(ParamList::from) .unwrap_or_else(|| ParamList(Vec::new())); Self { visibility, + generics, params, body: Block::from(inner.next().unwrap()), } diff --git a/src/codegen.rs b/src/codegen.rs index b8caf83..78299c7 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -394,8 +394,9 @@ impl ToRust for TopLevelKind { .join(", "); cg.add_indentedln(&format!( - "{}fn new({}) -> Self {{", + "{}fn new{}({}) -> Self {{", constructor.visibility.get_rust(), + constructor.generics.get_rust(), params_str )); cg.indent += 1; @@ -430,8 +431,9 @@ impl ToRust for TopLevelKind { // Constructor function cg.add_indentedln(&format!( - "{}fn construct_class(&mut self, {}) {{", + "{}fn construct_class{}(&mut self, {}) {{", constructor.visibility.get_rust(), + constructor.generics.get_rust(), params_str )); cg.indent += 1;