From a4c1f787ff76743f87e62267935ce8ce17f09923 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 06:59:31 +0200 Subject: [PATCH 01/17] Refactoring variable definition parsing --- parser/src/ast.rs | 16 +++++-- parser/src/lib.rs | 103 ++++++++++++++++++++++++++++----------------- src/codegen.rs | 24 ++++++----- test/src/main.mist | 2 +- 4 files changed, 92 insertions(+), 53 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 5256592..83637e7 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -3,7 +3,10 @@ use std::collections::HashMap; use serde::Serialize; #[derive(Debug, Clone, Serialize)] -pub struct ParamList(pub HashMap); +pub struct FieldList(pub HashMap); + +#[derive(Debug, Clone, Serialize)] +pub struct ParamList(pub Vec); #[derive(Debug, Clone, Serialize)] pub struct Block(pub Vec); @@ -34,7 +37,7 @@ pub enum TopLevel { StructDecl { export: bool, name: String, - fields: ParamList, + fields: FieldList, }, FunctionDecl { export: bool, @@ -71,13 +74,18 @@ pub enum Statement { } #[derive(Debug, Clone, Serialize)] -pub struct VarDeclStmt { +pub struct VarDecl { pub mutable: bool, pub name: String, - pub init: Option, pub type_: Option, } +#[derive(Debug, Clone, Serialize)] +pub struct VarDeclStmt { + pub decl: VarDecl, + pub init: Option, +} + #[derive(Debug, Clone, Serialize)] pub struct VarAssignStmt { pub target: Expression, diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 3ab17af..4a61fbb 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use pest::Parser; use pest_derive::Parser; @@ -17,8 +15,6 @@ pub type ParseError = pest::error::Error; pub fn parse(source: &str) -> Result, ParseError> { let mut pairs = MistParser::parse(Rule::program, source)?; - println!("{pairs:#?}"); - let mut statements = vec![]; for pair in pairs.next().unwrap().into_inner() { @@ -49,25 +45,32 @@ impl TryFrom> for TypeExpr { } } -impl From<(bool, pest::iterators::Pair<'_, Rule>)> for ParamList { - fn from((export_allowed, pair): (bool, pest::iterators::Pair)) -> Self { +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 export = - if export_allowed && param_inner.peek().unwrap().as_rule() == Rule::export { - param_inner.next().unwrap(); - true - } else { - false - }; + let export = if param_inner.peek().unwrap().as_rule() == Rule::export { + param_inner.next().unwrap(); + true + } else { + false + }; let param_type = TypeExpr::try_from(param_inner.next().unwrap()).unwrap(); let param_name = param_inner.next().unwrap().as_str().to_string(); (param_name, (export, param_type)) }) .collect(); + FieldList(params) + } +} + +impl From> for ParamList { + fn from(pair: pest::iterators::Pair) -> Self { + let params = pair.into_inner().map(VarDecl::from).collect(); + ParamList(params) } } @@ -106,9 +109,9 @@ impl TryFrom> for TopLevel { let name = inner.next().unwrap().as_str().to_string(); let params = if inner.peek().unwrap().as_rule() == Rule::param_list { - ParamList::from((false, inner.next().unwrap())) + ParamList::from(inner.next().unwrap()) } else { - ParamList(HashMap::new()) + ParamList(Vec::new()) }; let body = Block::from(inner.next().unwrap()); @@ -136,7 +139,7 @@ impl TryFrom> for TopLevel { }; let name = inner.next().unwrap().as_str().to_string(); let fields_pair = inner.next().unwrap(); - let fields = ParamList::from((true, fields_pair)); + let fields = FieldList::from(fields_pair); Ok(TopLevel::StructDecl { export, @@ -182,28 +185,7 @@ impl From> for Statement { Rule::block => Statement::Block(Block::from(pair.into_inner().next().unwrap())), - Rule::var_decl_statement => { - let mut inner = pair.into_inner(); - - let mut var_decl = inner.next().unwrap().into_inner(); - - let type_ = var_decl.next().map(TypeExpr::try_from).unwrap().ok(); - let mutable = if var_decl.peek().unwrap().as_rule() == Rule::mutable { - var_decl.next(); - true - } else { - false - }; - let name = var_decl.next().unwrap().as_str().to_string(); - let init = inner.next().map(Expression::from); - - Statement::VarDecl(VarDeclStmt { - mutable, - name: name.as_str().to_string(), - init, - type_, - }) - } + Rule::var_decl_statement => Statement::VarDecl(VarDeclStmt::from(pair)), Rule::return_stmt => { let mut inner = pair.into_inner(); @@ -348,3 +330,48 @@ impl From> for Postfix { } } } + +impl From> for VarDeclStmt { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { + Rule::var_decl_statement => { + let mut inner = pair.into_inner(); + + let decl = VarDecl::from(inner.next().unwrap()); + + let init = inner.next().map(Expression::from); + + VarDeclStmt { decl, init } + } + + _ => unimplemented!(), + } + } +} + +impl From> for VarDecl { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { + Rule::var_decl => { + let mut inner = pair.into_inner(); + + let type_ = inner.next().map(TypeExpr::try_from).unwrap().ok(); + let mutable = if inner.peek().unwrap().as_rule() == Rule::mutable { + inner.next(); + true + } else { + false + }; + let name = inner.next().unwrap().as_str().to_string(); + + VarDecl { + mutable, + name: name.as_str().to_string(), + type_, + } + } + + _ => unimplemented!("{:?}", pair.as_rule()), + } + } +} diff --git a/src/codegen.rs b/src/codegen.rs index 7c8330f..9ad548c 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -78,7 +78,15 @@ impl RustCodegen { let params_str = params .0 .iter() - .map(|(n, (_, t))| format!("{}: {}", n, self.translate_type(t))) + .map(|v| { + format!( + "{name}{}", + v.type_ + .as_ref() + .map(|t| format!(": {}", self.translate_type(t))) + .unwrap_or_default() + ) + }) .collect::>() .join(", "); @@ -131,15 +139,11 @@ impl RustCodegen { self.add_indentedln("}"); } - Statement::VarDecl(VarDeclStmt { - mutable, - name, - init, - type_, - }) => { - let mutability = if *mutable { "mut " } else { "" }; + Statement::VarDecl(VarDeclStmt { decl, init }) => { + let mutability = if decl.mutable { "mut " } else { "" }; - let ty = type_ + let ty = decl + .type_ .as_ref() .map(|t| format!(": {}", self.translate_type(t))) .unwrap_or_default(); @@ -149,7 +153,7 @@ impl RustCodegen { .map(|e| format!(" = {}", self.generate_expression(e))) .unwrap_or_default(); - self.add_indentedln(&format!("let {}{}{}{};", mutability, name, ty, init)); + self.add_indentedln(&format!("let {}{}{}{};", mutability, decl.name, ty, init)); } Statement::VarAssign(VarAssignStmt { target, value }) => { diff --git a/test/src/main.mist b/test/src/main.mist index a4ec76f..1aa1923 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1,3 @@ -int test() { +int test(int mut b) { int mut a = 10; } From 257877319e02a90c9c8bf4d719b27b8a1901f7f7 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 07:12:05 +0200 Subject: [PATCH 02/17] Refactoring codegen --- src/codegen.rs | 347 +++++++++++++++++++++++++++---------------------- 1 file changed, 190 insertions(+), 157 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 9ad548c..7b54381 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -3,6 +3,26 @@ use parser::ast::{ VarDeclStmt, WhileStmt, }; +// --------------------------------------------------------------------------- +// Traits +// --------------------------------------------------------------------------- + +/// 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); +} + +/// 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, cg: &RustCodegen) -> String; +} + +// --------------------------------------------------------------------------- +// Codegen struct +// --------------------------------------------------------------------------- + pub struct RustCodegen { output: String, indent: usize, @@ -30,21 +50,136 @@ impl RustCodegen { } fn add_indentedln(&mut self, s: &str) { - self.add(&format!("{}{}\n", self.indent_str(), s)); + let line = format!("{}{}\n", self.indent_str(), s); + self.add(&line); } pub fn generate(&mut self, toplevels: &[TopLevel]) -> String { for tl in toplevels { - self.generate_toplevel(tl); + tl.to_rust(self); } self.output.clone() } +} - fn generate_toplevel(&mut self, tl: &TopLevel) { - match tl { +impl Default for RustCodegen { + fn default() -> Self { + Self::new() + } +} + +// --------------------------------------------------------------------------- +// GetRust — pure string production (expressions, types) +// --------------------------------------------------------------------------- + +impl GetRust for TypeExpr { + fn get_rust(&self, _cg: &RustCodegen) -> String { + match self { + TypeExpr::Identifier(name) => match name.as_str() { + "int" => "i32".into(), + "float" | "float64" => "f64".into(), + "float32" => "f32".into(), + "bool" => "bool".into(), + "string" => "String".into(), + _ => name.clone(), + }, + } + } +} + +impl GetRust for Expression { + fn get_rust(&self, cg: &RustCodegen) -> String { + match self { + Expression::Identifier(name) => name.clone(), + Expression::IntLiteral(n) => n.to_string(), + Expression::FloatLiteral(n) => n.to_string(), + Expression::BoolLiteral(b) => b.to_string(), + Expression::StringLiteral(s) => format!("\"{}\".to_string()", s), + + Expression::Postfix { initial, postfixes } => { + let base = initial.get_rust(cg); + postfixes.get_rust_with_base(cg, &base) + } + } + } +} + +/// Helper — applies a slice of postfixes onto an already-rendered base string. +trait PostfixChain { + fn get_rust_with_base(&self, cg: &RustCodegen, base: &str) -> String; +} + +impl PostfixChain for [Postfix] { + fn get_rust_with_base(&self, cg: &RustCodegen, base: &str) -> String { + let mut result = base.to_string(); + + for postfix in self { + result = match postfix { + Postfix::FieldAccess(field) => format!("{}.{}", result, field), + + Postfix::Call(args) => { + let args = args + .iter() + .map(|a| a.get_rust(cg)) + .collect::>() + .join(", "); + format!("{}({})", result, args) + } + + Postfix::StructCall(fields) => { + let fields = fields + .iter() + .map(|(k, v)| format!("{}: {}", k, v.get_rust(cg))) + .collect::>() + .join(", "); + format!("{} {{ {} }}", result, fields) + } + + Postfix::Index(idx) => { + format!("{}[{}]", result, idx.get_rust(cg)) + } + + Postfix::Binary(op, rhs) => { + let op_str = match op { + BinaryOp::Plus => "+", + BinaryOp::Minus => "-", + BinaryOp::Multiply => "*", + BinaryOp::Divide => "/", + BinaryOp::Modulo => "%", + BinaryOp::Equal => "==", + BinaryOp::NotEqual => "!=", + BinaryOp::LessThan => "<", + BinaryOp::GreaterThan => ">", + BinaryOp::LessThanOrEqual => "<=", + BinaryOp::GreaterThanOrEqual => ">=", + }; + format!("{} {} {}", result, op_str, rhs.get_rust(cg)) + } + }; + } + + result + } +} + +// --------------------------------------------------------------------------- +// ToRust — output-writing (top-level, statements, blocks) +// --------------------------------------------------------------------------- + +impl ToRust for Block { + 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 { TopLevel::Import(path) => { - let path = path.replace("\"", ""); - self.addln(&format!("use {};", path)); + let path = path.replace('"', ""); + cg.addln(&format!("use {};", path)); } TopLevel::StructDecl { @@ -53,17 +188,16 @@ impl RustCodegen { fields, } => { let vis = if *export { "pub " } else { "" }; - - self.addln(&format!("{}struct {} {{", vis, name)); - self.indent += 1; + cg.addln(&format!("{}struct {} {{", vis, name)); + cg.indent += 1; for (field_name, (_, ty)) in &fields.0 { - let ty = self.translate_type(ty); - self.add_indentedln(&format!("pub {}: {},", field_name, ty)); + let ty = ty.get_rust(cg); + cg.add_indentedln(&format!("pub {}: {},", field_name, ty)); } - self.indent -= 1; - self.addln("}\n"); + cg.indent -= 1; + cg.addln("}\n"); } TopLevel::FunctionDecl { @@ -83,7 +217,7 @@ impl RustCodegen { "{name}{}", v.type_ .as_ref() - .map(|t| format!(": {}", self.translate_type(t))) + .map(|t| format!(": {}", t.get_rust(cg))) .unwrap_or_default() ) }) @@ -92,51 +226,32 @@ impl RustCodegen { let ret = return_type .as_ref() - .map(|t| format!(" -> {}", self.translate_type(t))) + .map(|t| format!(" -> {}", t.get_rust(cg))) .unwrap_or_default(); - self.addln(&format!("{}fn {}({}){} {{", vis, name, params_str, ret)); - - self.indent += 1; - self.generate_block(body); - self.indent -= 1; - - self.addln("}\n"); + cg.addln(&format!("{}fn {}({}){} {{", vis, name, params_str, ret)); + cg.indent += 1; + body.to_rust(cg); + cg.indent -= 1; + cg.addln("}\n"); } } } +} - fn translate_type(&self, ty: &TypeExpr) -> String { - match ty { - TypeExpr::Identifier(name) => match name.as_str() { - "int" => "i32".into(), - "float" | "float64" => "f64".into(), - "float32" => "f32".into(), - "bool" => "bool".into(), - "string" => "String".into(), - _ => name.clone(), - }, - } - } - - fn generate_block(&mut self, block: &Block) { - for stmt in &block.0 { - self.generate_statement(stmt); - } - } - - fn generate_statement(&mut self, stmt: &Statement) { - match stmt { +impl ToRust for Statement { + fn to_rust(&self, cg: &mut RustCodegen) { + match self { Statement::Expression(expr) => { - self.add_indentedln(&format!("{};", self.generate_expression(expr))); + cg.add_indentedln(&format!("{};", expr.get_rust(cg))); } Statement::Block(block) => { - self.add_indentedln("{"); - self.indent += 1; - self.generate_block(block); - self.indent -= 1; - self.add_indentedln("}"); + cg.add_indentedln("{"); + cg.indent += 1; + block.to_rust(cg); + cg.indent -= 1; + cg.add_indentedln("}"); } Statement::VarDecl(VarDeclStmt { decl, init }) => { @@ -145,22 +260,22 @@ impl RustCodegen { let ty = decl .type_ .as_ref() - .map(|t| format!(": {}", self.translate_type(t))) + .map(|t| format!(": {}", t.get_rust(cg))) .unwrap_or_default(); let init = init .as_ref() - .map(|e| format!(" = {}", self.generate_expression(e))) + .map(|e| format!(" = {}", e.get_rust(cg))) .unwrap_or_default(); - self.add_indentedln(&format!("let {}{}{}{};", mutability, decl.name, ty, init)); + cg.add_indentedln(&format!("let {}{}{}{};", mutability, decl.name, ty, init)); } Statement::VarAssign(VarAssignStmt { target, value }) => { - self.add_indentedln(&format!( + cg.add_indentedln(&format!( "{} = {};", - self.generate_expression(target), - self.generate_expression(value) + target.get_rust(cg), + value.get_rust(cg), )); } @@ -169,122 +284,40 @@ impl RustCodegen { then_branch, else_branch, }) => { - self.add_indentedln(&format!("if {} {{", self.generate_expression(condition))); - - self.indent += 1; - self.generate_statement(then_branch); - self.indent -= 1; - - self.add_indentedln("}"); + cg.add_indentedln(&format!("if {} {{", condition.get_rust(cg))); + cg.indent += 1; + then_branch.to_rust(cg); + cg.indent -= 1; + cg.add_indentedln("}"); if let Some(else_br) = else_branch { - self.add_indentedln("else {"); - self.indent += 1; - self.generate_statement(else_br); - self.indent -= 1; - self.add_indentedln("}"); + cg.add_indentedln("else {"); + cg.indent += 1; + else_br.to_rust(cg); + cg.indent -= 1; + cg.add_indentedln("}"); } } Statement::While(WhileStmt { condition, body }) => { - self.add_indentedln(&format!("while {} {{", self.generate_expression(condition))); - - self.indent += 1; - self.generate_statement(body); - self.indent -= 1; - - self.add_indentedln("}"); + cg.add_indentedln(&format!("while {} {{", condition.get_rust(cg))); + cg.indent += 1; + body.to_rust(cg); + cg.indent -= 1; + cg.add_indentedln("}"); } Statement::For { .. } => { - // Rust doesn't support C-style for loops - self.add_indentedln("// TODO: transform into iterator-based loop"); + cg.add_indentedln("// TODO: transform into iterator-based loop"); } Statement::Return(expr) => { - let val = expr - .as_ref() - .map(|e| self.generate_expression(e)) - .unwrap_or_default(); - - self.add_indentedln(&format!("return {};", val)); + let val = expr.as_ref().map(|e| e.get_rust(cg)).unwrap_or_default(); + cg.add_indentedln(&format!("return {};", val)); } - Statement::Break => self.add_indentedln("break;"), - Statement::Continue => self.add_indentedln("continue;"), + Statement::Break => cg.add_indentedln("break;"), + Statement::Continue => cg.add_indentedln("continue;"), } } - - fn generate_expression(&self, expr: &Expression) -> String { - match expr { - Expression::Identifier(name) => name.clone(), - Expression::IntLiteral(n) => n.to_string(), - Expression::FloatLiteral(n) => n.to_string(), - Expression::BoolLiteral(b) => b.to_string(), - Expression::StringLiteral(s) => format!("\"{}\".to_string()", s), - - Expression::Postfix { initial, postfixes } => { - let base = self.generate_expression(initial); - self.apply_postfixes(&base, postfixes) - } - } - } - - fn apply_postfixes(&self, base: &str, postfixes: &[Postfix]) -> String { - let mut result = base.to_string(); - - for postfix in postfixes { - result = match postfix { - Postfix::FieldAccess(field) => format!("{}.{}", result, field), - - Postfix::Call(args) => { - let args = args - .iter() - .map(|a| self.generate_expression(a)) - .collect::>() - .join(", "); - format!("{}({})", result, args) - } - - Postfix::StructCall(fields) => { - let fields = fields - .iter() - .map(|(k, v)| format!("{}: {}", k, self.generate_expression(v))) - .collect::>() - .join(", "); - format!("{} {{ {} }}", result, fields) - } - - Postfix::Index(idx) => { - format!("{}[{}]", result, self.generate_expression(idx)) - } - - Postfix::Binary(op, rhs) => { - let op = match op { - BinaryOp::Plus => "+", - BinaryOp::Minus => "-", - BinaryOp::Multiply => "*", - BinaryOp::Divide => "/", - BinaryOp::Modulo => "%", - BinaryOp::Equal => "==", - BinaryOp::NotEqual => "!=", - BinaryOp::LessThan => "<", - BinaryOp::GreaterThan => ">", - BinaryOp::LessThanOrEqual => "<=", - BinaryOp::GreaterThanOrEqual => ">=", - }; - - format!("{} {} {}", result, op, self.generate_expression(rhs)) - } - }; - } - - result - } -} - -impl Default for RustCodegen { - fn default() -> Self { - Self::new() - } } From 77c6138965a39884a1611fe65dbf4f9d9e197335 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 07:21:04 +0200 Subject: [PATCH 03/17] Refactored codegen --- parser/src/lib.rs | 2 +- src/codegen.rs | 78 ++++++++++++++++++++++------------------------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 4a61fbb..3ef52ed 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -366,7 +366,7 @@ impl From> for VarDecl { VarDecl { mutable, - name: name.as_str().to_string(), + name, type_, } } diff --git a/src/codegen.rs b/src/codegen.rs index 7b54381..6a1e0b6 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,6 +1,6 @@ use parser::ast::{ BinaryOp, Block, Expression, IfStmt, Postfix, Statement, TopLevel, TypeExpr, VarAssignStmt, - VarDeclStmt, WhileStmt, + VarDecl, VarDeclStmt, WhileStmt, }; // --------------------------------------------------------------------------- @@ -16,7 +16,7 @@ pub trait ToRust { /// 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, cg: &RustCodegen) -> String; + fn get_rust(&self) -> String; } // --------------------------------------------------------------------------- @@ -73,7 +73,7 @@ impl Default for RustCodegen { // --------------------------------------------------------------------------- impl GetRust for TypeExpr { - fn get_rust(&self, _cg: &RustCodegen) -> String { + fn get_rust(&self) -> String { match self { TypeExpr::Identifier(name) => match name.as_str() { "int" => "i32".into(), @@ -88,7 +88,7 @@ impl GetRust for TypeExpr { } impl GetRust for Expression { - fn get_rust(&self, cg: &RustCodegen) -> String { + fn get_rust(&self) -> String { match self { Expression::Identifier(name) => name.clone(), Expression::IntLiteral(n) => n.to_string(), @@ -97,8 +97,8 @@ impl GetRust for Expression { Expression::StringLiteral(s) => format!("\"{}\".to_string()", s), Expression::Postfix { initial, postfixes } => { - let base = initial.get_rust(cg); - postfixes.get_rust_with_base(cg, &base) + let base = initial.get_rust(); + postfixes.get_rust_with_base(&base) } } } @@ -106,11 +106,11 @@ impl GetRust for Expression { /// Helper — applies a slice of postfixes onto an already-rendered base string. trait PostfixChain { - fn get_rust_with_base(&self, cg: &RustCodegen, base: &str) -> String; + fn get_rust_with_base(&self, base: &str) -> String; } impl PostfixChain for [Postfix] { - fn get_rust_with_base(&self, cg: &RustCodegen, base: &str) -> String { + fn get_rust_with_base(&self, base: &str) -> String { let mut result = base.to_string(); for postfix in self { @@ -120,7 +120,7 @@ impl PostfixChain for [Postfix] { Postfix::Call(args) => { let args = args .iter() - .map(|a| a.get_rust(cg)) + .map(|a| a.get_rust()) .collect::>() .join(", "); format!("{}({})", result, args) @@ -129,14 +129,14 @@ impl PostfixChain for [Postfix] { Postfix::StructCall(fields) => { let fields = fields .iter() - .map(|(k, v)| format!("{}: {}", k, v.get_rust(cg))) + .map(|(k, v)| format!("{}: {}", k, v.get_rust())) .collect::>() .join(", "); format!("{} {{ {} }}", result, fields) } Postfix::Index(idx) => { - format!("{}[{}]", result, idx.get_rust(cg)) + format!("{}[{}]", result, idx.get_rust()) } Postfix::Binary(op, rhs) => { @@ -153,7 +153,7 @@ impl PostfixChain for [Postfix] { BinaryOp::LessThanOrEqual => "<=", BinaryOp::GreaterThanOrEqual => ">=", }; - format!("{} {} {}", result, op_str, rhs.get_rust(cg)) + format!("{} {} {}", result, op_str, rhs.get_rust()) } }; } @@ -192,7 +192,7 @@ impl ToRust for TopLevel { cg.indent += 1; for (field_name, (_, ty)) in &fields.0 { - let ty = ty.get_rust(cg); + let ty = ty.get_rust(); cg.add_indentedln(&format!("pub {}: {},", field_name, ty)); } @@ -212,21 +212,13 @@ impl ToRust for TopLevel { let params_str = params .0 .iter() - .map(|v| { - format!( - "{name}{}", - v.type_ - .as_ref() - .map(|t| format!(": {}", t.get_rust(cg))) - .unwrap_or_default() - ) - }) + .map(VarDecl::get_rust) .collect::>() .join(", "); let ret = return_type .as_ref() - .map(|t| format!(" -> {}", t.get_rust(cg))) + .map(|t| format!(" -> {}", t.get_rust())) .unwrap_or_default(); cg.addln(&format!("{}fn {}({}){} {{", vis, name, params_str, ret)); @@ -243,7 +235,7 @@ impl ToRust for Statement { fn to_rust(&self, cg: &mut RustCodegen) { match self { Statement::Expression(expr) => { - cg.add_indentedln(&format!("{};", expr.get_rust(cg))); + cg.add_indentedln(&format!("{};", expr.get_rust())); } Statement::Block(block) => { @@ -255,28 +247,16 @@ impl ToRust for Statement { } Statement::VarDecl(VarDeclStmt { decl, init }) => { - let mutability = if decl.mutable { "mut " } else { "" }; - - let ty = decl - .type_ - .as_ref() - .map(|t| format!(": {}", t.get_rust(cg))) - .unwrap_or_default(); - let init = init .as_ref() - .map(|e| format!(" = {}", e.get_rust(cg))) + .map(|e| format!(" = {}", e.get_rust())) .unwrap_or_default(); - cg.add_indentedln(&format!("let {}{}{}{};", mutability, decl.name, ty, init)); + cg.add_indentedln(&format!("let {}{};", decl.get_rust(), init)); } Statement::VarAssign(VarAssignStmt { target, value }) => { - cg.add_indentedln(&format!( - "{} = {};", - target.get_rust(cg), - value.get_rust(cg), - )); + cg.add_indentedln(&format!("{} = {};", target.get_rust(), value.get_rust(),)); } Statement::If(IfStmt { @@ -284,7 +264,7 @@ impl ToRust for Statement { then_branch, else_branch, }) => { - cg.add_indentedln(&format!("if {} {{", condition.get_rust(cg))); + cg.add_indentedln(&format!("if {} {{", condition.get_rust())); cg.indent += 1; then_branch.to_rust(cg); cg.indent -= 1; @@ -300,7 +280,7 @@ impl ToRust for Statement { } Statement::While(WhileStmt { condition, body }) => { - cg.add_indentedln(&format!("while {} {{", condition.get_rust(cg))); + cg.add_indentedln(&format!("while {} {{", condition.get_rust())); cg.indent += 1; body.to_rust(cg); cg.indent -= 1; @@ -312,7 +292,7 @@ impl ToRust for Statement { } Statement::Return(expr) => { - let val = expr.as_ref().map(|e| e.get_rust(cg)).unwrap_or_default(); + let val = expr.as_ref().map(|e| e.get_rust()).unwrap_or_default(); cg.add_indentedln(&format!("return {};", val)); } @@ -321,3 +301,17 @@ impl ToRust for Statement { } } } + +impl GetRust for VarDecl { + fn get_rust(&self) -> String { + let mutability = if self.mutable { "mut " } else { "" }; + + let ty = self + .type_ + .as_ref() + .map(|t| format!(": {}", t.get_rust())) + .unwrap_or_default(); + + format!("{}{}{}", mutability, self.name, ty) + } +} From 8faf6635898cdba95257bdd993e08e4ca11bcce5 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 16:39:55 +0200 Subject: [PATCH 04/17] Implementing static path --- parser/src/ast.rs | 3 +++ parser/src/grammar.pest | 17 +++++++++-------- parser/src/lib.rs | 17 +++++++++++++++++ test/src/main.mist | 4 +--- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 83637e7..53fc170 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -16,6 +16,9 @@ pub enum TypeExpr { Identifier(String), } +#[derive(Debug, Clone, Serialize)] +pub struct StaticPath(pub Vec); + #[derive(Debug, Clone, Serialize)] pub enum BinaryOp { Plus, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index c08f422..84191f6 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -4,12 +4,13 @@ COMMENT = _{ "//" ~ (!"\n" ~ ANY)* } program = { SOI ~ top_level* ~ EOI } // primitives -identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* } -integer = @{ ASCII_DIGIT+ } -float = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ } -boolean = { "true" | "false" } -string_lit = { "\"" ~ inner_str ~ "\"" } -inner_str = @{ (!"\"" ~ ANY)* } +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)* } export = { "public" } mutable = { "mut" } @@ -72,14 +73,14 @@ while_stmt = { } // ================= EXPRESSIONS ================= -type_expr = { identifier } +type_expr = { static_path } primary = { integer | float | boolean | string_lit - | identifier + | static_path } postfix = { diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 3ef52ed..d260193 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -45,6 +45,23 @@ impl TryFrom> for TypeExpr { } } +impl TryFrom> for StaticPath { + type Error = (); + + fn try_from(pair: pest::iterators::Pair<'_, Rule>) -> Result { + if pair.as_str() == "void" { + return Err(()); + } + + Ok(match pair.as_rule() { + Rule::static_path => { + StaticPath(pair.into_inner().map(|i| i.as_str().to_string()).collect()) + } + _ => unimplemented!("{pair:#?}"), + }) + } +} + impl From> for FieldList { fn from(pair: pest::iterators::Pair) -> Self { let params = pair diff --git a/test/src/main.mist b/test/src/main.mist index 1aa1923..42f1d16 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1 @@ -int test(int mut b) { - int mut a = 10; -} +int test() {} From 8506170d3446c34ddb0d1b7f7f4ed725af01336e Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 16:42:59 +0200 Subject: [PATCH 05/17] Static path parsing --- parser/src/ast.rs | 2 +- parser/src/lib.rs | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 53fc170..0dc7f6a 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -13,7 +13,7 @@ pub struct Block(pub Vec); #[derive(Debug, Clone, Serialize)] pub enum TypeExpr { - Identifier(String), + Path(StaticPath), } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/lib.rs b/parser/src/lib.rs index d260193..cc0eb69 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -39,26 +39,20 @@ impl TryFrom> for TypeExpr { let inner = pair.into_inner().next().unwrap(); TypeExpr::try_from(inner)? } - Rule::identifier => TypeExpr::Identifier(pair.as_str().to_string()), + Rule::static_path => TypeExpr::Path(StaticPath::from(pair)), _ => unimplemented!("{pair:#?}"), }) } } -impl TryFrom> for StaticPath { - type Error = (); - - fn try_from(pair: pest::iterators::Pair<'_, Rule>) -> Result { - if pair.as_str() == "void" { - return Err(()); - } - - Ok(match pair.as_rule() { +impl From> for StaticPath { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { Rule::static_path => { StaticPath(pair.into_inner().map(|i| i.as_str().to_string()).collect()) } _ => unimplemented!("{pair:#?}"), - }) + } } } From eba35995204ea655e01b666382933dd9a5ebd748 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 16:45:53 +0200 Subject: [PATCH 06/17] Static path codegen --- src/codegen.rs | 19 +++++++++---------- test/src/main.mist | 4 +++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 6a1e0b6..f04413d 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,6 +1,6 @@ use parser::ast::{ - BinaryOp, Block, Expression, IfStmt, Postfix, Statement, TopLevel, TypeExpr, VarAssignStmt, - VarDecl, VarDeclStmt, WhileStmt, + BinaryOp, Block, Expression, IfStmt, Postfix, Statement, StaticPath, TopLevel, TypeExpr, + VarAssignStmt, VarDecl, VarDeclStmt, WhileStmt, }; // --------------------------------------------------------------------------- @@ -75,14 +75,7 @@ impl Default for RustCodegen { impl GetRust for TypeExpr { fn get_rust(&self) -> String { match self { - TypeExpr::Identifier(name) => match name.as_str() { - "int" => "i32".into(), - "float" | "float64" => "f64".into(), - "float32" => "f32".into(), - "bool" => "bool".into(), - "string" => "String".into(), - _ => name.clone(), - }, + TypeExpr::Path(path) => path.get_rust(), } } } @@ -315,3 +308,9 @@ impl GetRust for VarDecl { format!("{}{}{}", mutability, self.name, ty) } } + +impl GetRust for StaticPath { + fn get_rust(&self) -> String { + self.0.join("::") + } +} diff --git a/test/src/main.mist b/test/src/main.mist index 42f1d16..5ff9964 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1 +1,3 @@ -int test() {} +i32 test() { + +} From c4bdc20276593e4b679e886dd6f59a32093cd718 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 16:49:41 +0200 Subject: [PATCH 07/17] Static path expr --- parser/src/ast.rs | 2 +- parser/src/lib.rs | 2 +- src/codegen.rs | 2 +- test/src/main.mist | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 0dc7f6a..e98f654 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -118,7 +118,7 @@ pub struct ForStmt { #[derive(Debug, Clone, Serialize)] pub enum Expression { - Identifier(String), + Path(StaticPath), IntLiteral(i64), FloatLiteral(f64), BoolLiteral(bool), diff --git a/parser/src/lib.rs b/parser/src/lib.rs index cc0eb69..2969baa 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -262,7 +262,7 @@ impl From> for Expression { } } Rule::primary => Expression::from(pair.into_inner().next().unwrap()), - Rule::identifier => Expression::Identifier(pair.as_str().to_string()), + Rule::static_path => Expression::Path(StaticPath::from(pair)), Rule::integer => { let value = pair.as_str().parse::().unwrap(); Expression::IntLiteral(value) diff --git a/src/codegen.rs b/src/codegen.rs index f04413d..3396d17 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -83,7 +83,7 @@ impl GetRust for TypeExpr { impl GetRust for Expression { fn get_rust(&self) -> String { match self { - Expression::Identifier(name) => name.clone(), + Expression::Path(path) => path.get_rust(), Expression::IntLiteral(n) => n.to_string(), Expression::FloatLiteral(n) => n.to_string(), Expression::BoolLiteral(b) => b.to_string(), diff --git a/test/src/main.mist b/test/src/main.mist index 5ff9964..3ed2575 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1,3 @@ i32 test() { - + std::fs::write(); } From 0d9af81955b1946262ff49d2bba9d66015fe44d1 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 16:56:55 +0200 Subject: [PATCH 08/17] void type --- src/codegen.rs | 12 +++++++++++- test/src/main.mist | 6 +++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 3396d17..dd69279 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -75,7 +75,7 @@ impl Default for RustCodegen { impl GetRust for TypeExpr { fn get_rust(&self) -> String { match self { - TypeExpr::Path(path) => path.get_rust(), + TypeExpr::Path(path) => get_static_type_path(path), } } } @@ -314,3 +314,13 @@ impl GetRust for StaticPath { self.0.join("::") } } + +pub fn get_static_type_path(path: &StaticPath) -> String { + let rust_path = path.get_rust(); + + if rust_path == "void" { + format!("()") + } else { + rust_path + } +} diff --git a/test/src/main.mist b/test/src/main.mist index 3ed2575..af940c0 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1,3 @@ -i32 test() { - std::fs::write(); -} +void main() { + +} \ No newline at end of file From 416830b0950f0b32c0cb0526283c1d82d67d898f Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 16:59:10 +0200 Subject: [PATCH 09/17] tuple codegen --- parser/src/ast.rs | 1 + src/codegen.rs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index e98f654..0fb43d7 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -14,6 +14,7 @@ pub struct Block(pub Vec); #[derive(Debug, Clone, Serialize)] pub enum TypeExpr { Path(StaticPath), + Tuple(Vec), } #[derive(Debug, Clone, Serialize)] diff --git a/src/codegen.rs b/src/codegen.rs index dd69279..dca4fb5 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -76,6 +76,14 @@ impl GetRust for TypeExpr { fn get_rust(&self) -> String { match self { TypeExpr::Path(path) => get_static_type_path(path), + TypeExpr::Tuple(types) => format!( + "({})", + types + .iter() + .map(|t| t.get_rust()) + .collect::>() + .join(", ") + ), } } } From 32a08d3e7f223f35a2a1c7d3fc5e7e8175163b65 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 17:11:56 +0200 Subject: [PATCH 10/17] tuple type parsing --- parser/src/grammar.pest | 3 ++- parser/src/lib.rs | 34 +++++++++------------------------- test/src/main.mist | 2 +- 3 files changed, 12 insertions(+), 27 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 84191f6..a8e5d0a 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -73,7 +73,8 @@ while_stmt = { } // ================= EXPRESSIONS ================= -type_expr = { static_path } +tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } +type_expr = { (static_path ~ ("<" ~ type_expr ~ ">")?) | tuple_type } primary = { integer diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 2969baa..d7431da 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -26,22 +26,14 @@ pub fn parse(source: &str) -> Result, ParseError> { Ok(statements) } -impl TryFrom> for TypeExpr { - type Error = (); - - fn try_from(pair: pest::iterators::Pair<'_, Rule>) -> Result { - if pair.as_str() == "void" { - return Err(()); - } - - Ok(match pair.as_rule() { - Rule::type_expr => { - let inner = pair.into_inner().next().unwrap(); - TypeExpr::try_from(inner)? - } +impl From> for TypeExpr { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { + Rule::type_expr => TypeExpr::from(pair.into_inner().next().unwrap()), Rule::static_path => TypeExpr::Path(StaticPath::from(pair)), + Rule::tuple_type => TypeExpr::Tuple(pair.into_inner().map(TypeExpr::from).collect()), _ => unimplemented!("{pair:#?}"), - }) + } } } @@ -68,7 +60,7 @@ impl From> for FieldList { } else { false }; - let param_type = TypeExpr::try_from(param_inner.next().unwrap()).unwrap(); + let param_type = TypeExpr::from(param_inner.next().unwrap()); let param_name = param_inner.next().unwrap().as_str().to_string(); (param_name, (export, param_type)) }) @@ -108,15 +100,7 @@ impl TryFrom> for TopLevel { false }; - let return_type = if let Some(next) = inner.peek() { - if next.as_rule() == Rule::type_expr { - TypeExpr::try_from(inner.next().unwrap()).ok() - } else { - None - } - } else { - None - }; + let return_type = Some(TypeExpr::from(inner.next().unwrap())); let name = inner.next().unwrap().as_str().to_string(); let params = if inner.peek().unwrap().as_rule() == Rule::param_list { @@ -366,7 +350,7 @@ impl From> for VarDecl { Rule::var_decl => { let mut inner = pair.into_inner(); - let type_ = inner.next().map(TypeExpr::try_from).unwrap().ok(); + let type_ = Some(inner.next().map(TypeExpr::from).unwrap()); let mutable = if inner.peek().unwrap().as_rule() == Rule::mutable { inner.next(); true diff --git a/test/src/main.mist b/test/src/main.mist index af940c0..46e4b04 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1,3 @@ -void main() { +(i32, i32) main() { } \ No newline at end of file From 7b1d2e3d913ac2b31428b1a1d8754bf6de722cd3 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 17:14:17 +0200 Subject: [PATCH 11/17] Removed unnecessary option return type --- parser/src/ast.rs | 2 +- parser/src/lib.rs | 2 +- src/codegen.rs | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 0fb43d7..deec78a 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -47,7 +47,7 @@ pub enum TopLevel { export: bool, name: String, params: ParamList, - return_type: Option, + return_type: TypeExpr, body: Block, }, } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index d7431da..8666c30 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -100,7 +100,7 @@ impl TryFrom> for TopLevel { false }; - let return_type = Some(TypeExpr::from(inner.next().unwrap())); + let return_type = TypeExpr::from(inner.next().unwrap()); let name = inner.next().unwrap().as_str().to_string(); let params = if inner.peek().unwrap().as_rule() == Rule::param_list { diff --git a/src/codegen.rs b/src/codegen.rs index dca4fb5..b16ffda 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -217,12 +217,13 @@ impl ToRust for TopLevel { .collect::>() .join(", "); - let ret = return_type - .as_ref() - .map(|t| format!(" -> {}", t.get_rust())) - .unwrap_or_default(); - - cg.addln(&format!("{}fn {}({}){} {{", vis, name, params_str, ret)); + cg.addln(&format!( + "{}fn {}({}) -> {} {{", + vis, + name, + params_str, + return_type.get_rust() + )); cg.indent += 1; body.to_rust(cg); cg.indent -= 1; From c3844726fee372a14837a932d9eef18516f4a3f9 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 17:22:24 +0200 Subject: [PATCH 12/17] Type params parsing --- parser/src/ast.rs | 2 +- parser/src/grammar.pest | 3 ++- parser/src/lib.rs | 6 +++++- test/src/main.mist | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index deec78a..4909378 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -13,7 +13,7 @@ pub struct Block(pub Vec); #[derive(Debug, Clone, Serialize)] pub enum TypeExpr { - Path(StaticPath), + Path(StaticPath, Vec), Tuple(Vec), } diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index a8e5d0a..2b1384b 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -74,7 +74,8 @@ while_stmt = { // ================= EXPRESSIONS ================= tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } -type_expr = { (static_path ~ ("<" ~ type_expr ~ ">")?) | tuple_type } +path_type = { static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? } +type_expr = { path_type | tuple_type } primary = { integer diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 8666c30..27b25ab 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -30,8 +30,12 @@ impl From> for TypeExpr { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { match pair.as_rule() { Rule::type_expr => TypeExpr::from(pair.into_inner().next().unwrap()), - Rule::static_path => TypeExpr::Path(StaticPath::from(pair)), Rule::tuple_type => TypeExpr::Tuple(pair.into_inner().map(TypeExpr::from).collect()), + Rule::path_type => { + let mut inner = pair.into_inner(); + + TypeExpr::Path(StaticPath::from(inner.next().unwrap()), inner.map(TypeExpr::from).collect()) + } _ => unimplemented!("{pair:#?}"), } } diff --git a/test/src/main.mist b/test/src/main.mist index 46e4b04..b81268b 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1,3 @@ -(i32, i32) main() { +Result main() { } \ No newline at end of file From 0192844d27e5c112ff69499692bcca887d71c750 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 17:25:53 +0200 Subject: [PATCH 13/17] Type params gen --- parser/src/ast.rs | 3 ++- parser/src/lib.rs | 8 +++++++- src/codegen.rs | 11 +++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 4909378..826ac95 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -13,7 +13,8 @@ pub struct Block(pub Vec); #[derive(Debug, Clone, Serialize)] pub enum TypeExpr { - Path(StaticPath, Vec), + Path(StaticPath), + PathParams(StaticPath, Vec), Tuple(Vec), } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 27b25ab..72cea59 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -33,8 +33,14 @@ impl From> for TypeExpr { Rule::tuple_type => TypeExpr::Tuple(pair.into_inner().map(TypeExpr::from).collect()), Rule::path_type => { let mut inner = pair.into_inner(); + let path = StaticPath::from(inner.next().unwrap()); + let params = inner.map(TypeExpr::from).collect::>(); - TypeExpr::Path(StaticPath::from(inner.next().unwrap()), inner.map(TypeExpr::from).collect()) + if params.len() == 0 { + TypeExpr::Path(path) + } else { + TypeExpr::PathParams(path, params) + } } _ => unimplemented!("{pair:#?}"), } diff --git a/src/codegen.rs b/src/codegen.rs index b16ffda..1ede7e7 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -76,6 +76,17 @@ impl GetRust for TypeExpr { fn get_rust(&self) -> String { match self { TypeExpr::Path(path) => get_static_type_path(path), + TypeExpr::PathParams(path, params) => { + format!( + "{}<{}>", + get_static_type_path(path), + params + .iter() + .map(|t| t.get_rust()) + .collect::>() + .join(", ") + ) + } TypeExpr::Tuple(types) => format!( "({})", types From d263f1a41f085c5285b6dc8af1143f7be3ba71c0 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 17:36:25 +0200 Subject: [PATCH 14/17] Type postix gen --- parser/src/ast.rs | 11 ++++++++--- parser/src/grammar.pest | 3 ++- src/codegen.rs | 28 ++++++++++++++++++++++------ test/src/main.mist | 4 +--- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 826ac95..90f4375 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -11,11 +11,16 @@ pub struct ParamList(pub Vec); #[derive(Debug, Clone, Serialize)] pub struct Block(pub Vec); +#[derive(Debug, Clone, Serialize)] +pub enum TypePostfix { + Ref, +} + #[derive(Debug, Clone, Serialize)] pub enum TypeExpr { - Path(StaticPath), - PathParams(StaticPath, Vec), - Tuple(Vec), + Path(StaticPath, Vec), + PathParams(StaticPath, Vec, Vec), + Tuple(Vec, Vec), } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 2b1384b..035791b 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -75,7 +75,8 @@ while_stmt = { // ================= EXPRESSIONS ================= tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } path_type = { static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? } -type_expr = { path_type | tuple_type } +ref_type = { "*" } +type_expr = { (path_type | tuple_type) ~ ref_type* } primary = { integer diff --git a/src/codegen.rs b/src/codegen.rs index 1ede7e7..4e37482 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,6 +1,6 @@ use parser::ast::{ BinaryOp, Block, Expression, IfStmt, Postfix, Statement, StaticPath, TopLevel, TypeExpr, - VarAssignStmt, VarDecl, VarDeclStmt, WhileStmt, + TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, WhileStmt, }; // --------------------------------------------------------------------------- @@ -75,10 +75,13 @@ impl Default for RustCodegen { impl GetRust for TypeExpr { fn get_rust(&self) -> String { match self { - TypeExpr::Path(path) => get_static_type_path(path), - TypeExpr::PathParams(path, params) => { + TypeExpr::Path(path, postix) => { + get_type_postfixes(postix) + &get_static_type_path(path) + } + TypeExpr::PathParams(path, params, postfix) => { format!( - "{}<{}>", + "{}{}<{}>", + get_type_postfixes(postix), get_static_type_path(path), params .iter() @@ -87,8 +90,9 @@ impl GetRust for TypeExpr { .join(", ") ) } - TypeExpr::Tuple(types) => format!( - "({})", + TypeExpr::Tuple(types, postfix) => format!( + "{}({})", + get_type_postfixes(postix), types .iter() .map(|t| t.get_rust()) @@ -335,6 +339,14 @@ impl GetRust for StaticPath { } } +impl GetRust for TypePostfix { + fn get_rust(&self) -> String { + match self { + TypePostfix::Ref => format!("&"), + } + } +} + pub fn get_static_type_path(path: &StaticPath) -> String { let rust_path = path.get_rust(); @@ -344,3 +356,7 @@ pub fn get_static_type_path(path: &StaticPath) -> String { rust_path } } + +pub fn get_type_postfixes(postfixes: &[TypePostfix]) -> String { + postfixes.iter().map(TypePostfix::get_rust).collect() +} diff --git a/test/src/main.mist b/test/src/main.mist index b81268b..9f2489e 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1 @@ -Result main() { - -} \ No newline at end of file +i32 add(i32* a, i32* b) {} \ No newline at end of file From 0e84e1ca3d4b2a190468838559bbec1c2c5c864b Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 17:45:23 +0200 Subject: [PATCH 15/17] Type expr parse refactor --- parser/src/ast.rs | 11 +++++++---- parser/src/lib.rs | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 90f4375..fabb675 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -17,12 +17,15 @@ pub enum TypePostfix { } #[derive(Debug, Clone, Serialize)] -pub enum TypeExpr { - Path(StaticPath, Vec), - PathParams(StaticPath, Vec, Vec), - Tuple(Vec, Vec), +pub enum TypeExprKind { + Path(StaticPath), + PathParams(StaticPath, Vec), + Tuple(Vec), } +#[derive(Debug, Clone, Serialize)] +pub struct TypeExpr(pub TypeExprKind, pub Vec); + #[derive(Debug, Clone, Serialize)] pub struct StaticPath(pub Vec); diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 72cea59..aa07769 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -29,17 +29,44 @@ pub fn parse(source: &str) -> Result, ParseError> { impl From> for TypeExpr { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { match pair.as_rule() { - Rule::type_expr => TypeExpr::from(pair.into_inner().next().unwrap()), - Rule::tuple_type => TypeExpr::Tuple(pair.into_inner().map(TypeExpr::from).collect()), + Rule::type_expr => { + let mut inner = pair.into_inner(); + TypeExpr( + TypeExprKind::from(inner.next().unwrap()), + inner.map(TypePostfix::from).collect(), + ) + } + _ => unimplemented!("{pair:#?}"), + } + } +} + +impl From> for TypePostfix { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { + Rule::ref_type => match pair.as_str().trim() { + _ => Self::Ref, + }, + _ => unimplemented!("{pair:#?}"), + } + } +} + +impl From> for TypeExprKind { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { + Rule::tuple_type => { + TypeExprKind::Tuple(pair.into_inner().map(TypeExpr::from).collect()) + } Rule::path_type => { let mut inner = pair.into_inner(); let path = StaticPath::from(inner.next().unwrap()); let params = inner.map(TypeExpr::from).collect::>(); if params.len() == 0 { - TypeExpr::Path(path) + TypeExprKind::Path(path) } else { - TypeExpr::PathParams(path, params) + TypeExprKind::PathParams(path, params) } } _ => unimplemented!("{pair:#?}"), From a057c50a53e2c0d6109bcfef79bb65e6b63518f1 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 17:47:04 +0200 Subject: [PATCH 16/17] Type expr refrence --- src/codegen.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 4e37482..63bbdf1 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,6 +1,6 @@ use parser::ast::{ BinaryOp, Block, Expression, IfStmt, Postfix, Statement, StaticPath, TopLevel, TypeExpr, - TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, WhileStmt, + TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, WhileStmt, }; // --------------------------------------------------------------------------- @@ -73,15 +73,18 @@ impl Default for RustCodegen { // --------------------------------------------------------------------------- impl GetRust for TypeExpr { + fn get_rust(&self) -> String { + get_type_postfixes(&self.1) + &self.0.get_rust() + } +} + +impl GetRust for TypeExprKind { fn get_rust(&self) -> String { match self { - TypeExpr::Path(path, postix) => { - get_type_postfixes(postix) + &get_static_type_path(path) - } - TypeExpr::PathParams(path, params, postfix) => { + TypeExprKind::Path(path) => get_static_type_path(path), + TypeExprKind::PathParams(path, params) => { format!( - "{}{}<{}>", - get_type_postfixes(postix), + "{}<{}>", get_static_type_path(path), params .iter() @@ -90,9 +93,8 @@ impl GetRust for TypeExpr { .join(", ") ) } - TypeExpr::Tuple(types, postfix) => format!( - "{}({})", - get_type_postfixes(postix), + TypeExprKind::Tuple(types) => format!( + "({})", types .iter() .map(|t| t.get_rust()) From 860f51ea0667cad82b983a653db7516c6e63cf69 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 18:00:50 +0200 Subject: [PATCH 17/17] Mutable ref --- parser/src/ast.rs | 1 + parser/src/grammar.pest | 2 +- parser/src/lib.rs | 10 +++++++--- src/codegen.rs | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index fabb675..8ba217a 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -14,6 +14,7 @@ pub struct Block(pub Vec); #[derive(Debug, Clone, Serialize)] pub enum TypePostfix { Ref, + RefMut, } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 035791b..e60b11b 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -75,7 +75,7 @@ while_stmt = { // ================= EXPRESSIONS ================= tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } path_type = { static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? } -ref_type = { "*" } +ref_type = { mutable? ~ "*" } type_expr = { (path_type | tuple_type) ~ ref_type* } primary = { diff --git a/parser/src/lib.rs b/parser/src/lib.rs index aa07769..584c832 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -44,9 +44,13 @@ impl From> for TypeExpr { impl From> for TypePostfix { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { match pair.as_rule() { - Rule::ref_type => match pair.as_str().trim() { - _ => Self::Ref, - }, + Rule::ref_type => { + if pair.into_inner().peek().is_some() { + TypePostfix::RefMut + } else { + TypePostfix::Ref + } + } _ => unimplemented!("{pair:#?}"), } } diff --git a/src/codegen.rs b/src/codegen.rs index 63bbdf1..0830a5f 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -345,6 +345,7 @@ impl GetRust for TypePostfix { fn get_rust(&self) -> String { match self { TypePostfix::Ref => format!("&"), + TypePostfix::RefMut => format!("&mut "), } } }