From c717a57f99f947a0cb6aa803425a8d96e6762566 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 19:29:10 +0200 Subject: [PATCH 01/11] Importing --- parser/src/ast.rs | 2 +- parser/src/grammar.pest | 9 +++++---- parser/src/lib.rs | 8 ++++---- src/codegen.rs | 5 ++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 8ba217a..d33557a 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -47,7 +47,7 @@ pub enum BinaryOp { #[derive(Debug, Clone, Serialize)] pub enum TopLevel { - Import(String), + Include(StaticPath), StructDecl { export: bool, name: String, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index e60b11b..fc0110c 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -12,15 +12,16 @@ string_lit = { "\"" ~ inner_str ~ "\"" } inner_str = @{ (!"\"" ~ ANY)* } static_path = { identifier ~ ("::" ~ identifier)* } -export = { "public" } -mutable = { "mut" } -var_decl = { type_expr ~ mutable? ~ identifier } +export = { "public" } +mutable = { "mut" } +sharp = _{ "#" } +var_decl = { type_expr ~ mutable? ~ identifier } // ================= TOP LEVEL ================= top_level = _{ import | function_decl | struct_decl } -import = { "import" ~ string_lit ~ ";" } +import = { sharp ~ "include" ~ "<" ~ static_path ~ ">" } field_list = { field ~ ("," ~ field)* ~ ","? } field = { export? ~ type_expr ~ identifier } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 584c832..e8d2340 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -123,10 +123,10 @@ impl TryFrom> for TopLevel { type Error = (); fn try_from(pair: pest::iterators::Pair) -> Result { match pair.as_rule() { - Rule::import => { - let path = pair.into_inner().next().unwrap().as_str().to_string(); - Ok(TopLevel::Import(path)) - } + Rule::import => Ok(TopLevel::Include(StaticPath::from( + pair.into_inner().next().unwrap(), + ))), + Rule::function_decl => { let mut inner = pair.into_inner(); diff --git a/src/codegen.rs b/src/codegen.rs index 0830a5f..34b9571 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -195,9 +195,8 @@ impl ToRust for Block { impl ToRust for TopLevel { fn to_rust(&self, cg: &mut RustCodegen) { match self { - TopLevel::Import(path) => { - let path = path.replace('"', ""); - cg.addln(&format!("use {};", path)); + TopLevel::Include(path) => { + cg.addln(&format!("use {};", path.get_rust())); } TopLevel::StructDecl { From c083a547d79a677e89d2207db441c45bfb894063 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 19:43:49 +0200 Subject: [PATCH 02/11] Macro calls --- parser/src/ast.rs | 1 + parser/src/grammar.pest | 7 +++++++ parser/src/lib.rs | 2 ++ src/codegen.rs | 4 ++++ test/src/main.mist | 4 +++- 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index d33557a..2dd6699 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -66,6 +66,7 @@ pub enum TopLevel { pub enum Postfix { FieldAccess(String), Call(Vec), + MacroCall(String), StructCall(HashMap), Index(Expression), Binary(BinaryOp, Expression), diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index fc0110c..ef05032 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -79,6 +79,11 @@ path_type = { static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? } ref_type = { mutable? ~ "*" } type_expr = { (path_type | tuple_type) ~ ref_type* } +macro_inner_v = { + "(" ~ macro_inner_v* ~ ")" + | (!("(" | ")") ~ ANY) +} + primary = { integer | float @@ -90,6 +95,7 @@ primary = { postfix = { field_px | call_px + | macro_call_px | struct_px | index_px | binary_px @@ -97,6 +103,7 @@ postfix = { 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 } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index e8d2340..204dbb7 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -362,6 +362,8 @@ impl From> for Postfix { Postfix::Binary(op, Expression::from(inner.next().unwrap())) } + Rule::macro_call_px => Postfix::MacroCall(pair.into_inner().as_str().to_string()), + _ => unimplemented!("Postfix parsing not implemented yet {:?}", pair.as_rule()), } } diff --git a/src/codegen.rs b/src/codegen.rs index 34b9571..64ade01 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -144,6 +144,10 @@ impl PostfixChain for [Postfix] { format!("{}({})", result, args) } + Postfix::MacroCall(inner) => { + format!("{}!({})", result, inner) + } + Postfix::StructCall(fields) => { let fields = fields .iter() diff --git a/test/src/main.mist b/test/src/main.mist index 9f2489e..aa71749 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1 +1,3 @@ -i32 add(i32* a, i32* b) {} \ No newline at end of file +void main() { + println!("Hello, World!"); +} \ No newline at end of file From ba24db481caa2a17ac4a749225279e53098ed682 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 19:58:34 +0200 Subject: [PATCH 03/11] Prefix parsing --- parser/src/ast.rs | 10 +++++++++- parser/src/grammar.pest | 12 +++++++++++- parser/src/lib.rs | 27 ++++++++++++++++++++++++++- src/codegen.rs | 2 +- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 2dd6699..5a8fe83 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -72,6 +72,13 @@ pub enum Postfix { Binary(BinaryOp, Expression), } +#[derive(Debug, Clone, Serialize)] +pub enum PreFix { + Ref, + RefMut, + Deref, +} + #[derive(Debug, Clone, Serialize)] pub enum Statement { Expression(Expression), @@ -135,8 +142,9 @@ pub enum Expression { FloatLiteral(f64), BoolLiteral(bool), StringLiteral(String), - Postfix { + Fix { initial: Box, + prefixes: Vec, postfixes: Vec, }, } diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index ef05032..b0522c4 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -110,6 +110,16 @@ binary_px = { bin_op ~ expr } bin_op = { "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | ">" | "<=" | ">=" } struct_field_decl = { identifier ~ ":" ~ expr } +prefix = { + deref_px + | mut_ref_px + | ref_px +} + +deref_px = { "*" } +mut_ref_px = { "&" ~ mutable } +ref_px = { "&" } + expr = { - primary ~ postfix* + prefix* ~ primary ~ postfix* } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 204dbb7..df12de8 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -275,11 +275,24 @@ impl From> for Expression { match pair.as_rule() { Rule::expr => { let mut inner = pair.into_inner(); + let mut prefixes = Vec::new(); + + while inner + .peek() + .map(|v| v.as_rule() == Rule::prefix) + .unwrap_or_default() + { + prefixes.push(PreFix::from(inner.next().unwrap())); + } + + println!("{:#?}", prefixes); + let exp = Expression::from(inner.next().unwrap()); if inner.len() > 0 { - Expression::Postfix { + Expression::Fix { initial: Box::new(exp), + prefixes, postfixes: inner.map(|p| Postfix::from(p)).collect(), } } else { @@ -313,6 +326,18 @@ impl From> for Expression { } } +impl From> for PreFix { + fn from(pair: pest::iterators::Pair) -> Self { + match pair.as_rule() { + Rule::prefix => Self::from(pair.into_inner().next().unwrap()), + Rule::deref_px => Self::Deref, + Rule::mut_ref_px => Self::RefMut, + Rule::ref_px => Self::Ref, + _ => unimplemented!("{pair:#?}"), + } + } +} + impl From> for Postfix { fn from(pair: pest::iterators::Pair) -> Self { match pair.as_rule() { diff --git a/src/codegen.rs b/src/codegen.rs index 64ade01..825b90d 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -114,7 +114,7 @@ impl GetRust for Expression { Expression::BoolLiteral(b) => b.to_string(), Expression::StringLiteral(s) => format!("\"{}\".to_string()", s), - Expression::Postfix { initial, postfixes } => { + Expression::Fix { initial, postfixes } => { let base = initial.get_rust(); postfixes.get_rust_with_base(&base) } From e79b594ab8156aeeb5013072b23897ae2c8621af Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 20:04:09 +0200 Subject: [PATCH 04/11] Postfix refactor in codegen --- src/codegen.rs | 120 ++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 62 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 825b90d..9978ebb 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -114,73 +114,69 @@ impl GetRust for Expression { Expression::BoolLiteral(b) => b.to_string(), Expression::StringLiteral(s) => format!("\"{}\".to_string()", s), - Expression::Fix { initial, postfixes } => { - let base = initial.get_rust(); - postfixes.get_rust_with_base(&base) + Expression::Fix { + initial, + prefixes, + postfixes, + } => initial.get_rust() + &postfixes.get_rust(), + } + } +} + +impl GetRust for Postfix { + fn get_rust(&self) -> String { + match self { + Postfix::FieldAccess(field) => format!(".{}", field), + + Postfix::Call(args) => { + let args = args + .iter() + .map(|a| a.get_rust()) + .collect::>() + .join(", "); + format!("({})", args) + } + + Postfix::MacroCall(inner) => { + format!("!({})", inner) + } + + Postfix::StructCall(fields) => { + let fields = fields + .iter() + .map(|(k, v)| format!("{}: {}", k, v.get_rust())) + .collect::>() + .join(", "); + format!("{{ {} }}", fields) + } + + Postfix::Index(idx) => { + format!("[{}]", idx.get_rust()) + } + + 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!("{} {}", op_str, rhs.get_rust()) } } } } -/// Helper — applies a slice of postfixes onto an already-rendered base string. -trait PostfixChain { - fn get_rust_with_base(&self, base: &str) -> String; -} - -impl PostfixChain for [Postfix] { - fn get_rust_with_base(&self, 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()) - .collect::>() - .join(", "); - format!("{}({})", result, args) - } - - Postfix::MacroCall(inner) => { - format!("{}!({})", result, inner) - } - - Postfix::StructCall(fields) => { - let fields = fields - .iter() - .map(|(k, v)| format!("{}: {}", k, v.get_rust())) - .collect::>() - .join(", "); - format!("{} {{ {} }}", result, fields) - } - - Postfix::Index(idx) => { - format!("{}[{}]", result, idx.get_rust()) - } - - 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()) - } - }; - } - - result +impl GetRust for [Postfix] { + fn get_rust(&self) -> String { + self.iter().map(Postfix::get_rust).collect() } } From 5364f51fc1d055868dc133927446cddaa093fc66 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 20:07:20 +0200 Subject: [PATCH 05/11] Prefix --- parser/src/ast.rs | 4 ++-- parser/src/lib.rs | 4 ++-- src/codegen.rs | 23 ++++++++++++++++++++--- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 5a8fe83..2a58fed 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -73,7 +73,7 @@ pub enum Postfix { } #[derive(Debug, Clone, Serialize)] -pub enum PreFix { +pub enum Prefix { Ref, RefMut, Deref, @@ -144,7 +144,7 @@ pub enum Expression { StringLiteral(String), Fix { initial: Box, - prefixes: Vec, + prefixes: Vec, postfixes: Vec, }, } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index df12de8..22d0183 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -282,7 +282,7 @@ impl From> for Expression { .map(|v| v.as_rule() == Rule::prefix) .unwrap_or_default() { - prefixes.push(PreFix::from(inner.next().unwrap())); + prefixes.push(Prefix::from(inner.next().unwrap())); } println!("{:#?}", prefixes); @@ -326,7 +326,7 @@ impl From> for Expression { } } -impl From> for PreFix { +impl From> for Prefix { fn from(pair: pest::iterators::Pair) -> Self { match pair.as_rule() { Rule::prefix => Self::from(pair.into_inner().next().unwrap()), diff --git a/src/codegen.rs b/src/codegen.rs index 9978ebb..7463650 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, - TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, WhileStmt, + BinaryOp, Block, Expression, IfStmt, Postfix, Prefix, Statement, StaticPath, TopLevel, + TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, WhileStmt, }; // --------------------------------------------------------------------------- @@ -118,11 +118,28 @@ impl GetRust for Expression { initial, prefixes, postfixes, - } => initial.get_rust() + &postfixes.get_rust(), + } => prefixes.get_rust() + &initial.get_rust() + &postfixes.get_rust(), } } } +impl GetRust for Prefix { + fn get_rust(&self) -> String { + match self { + Self::Deref => "*", + Self::Ref => "&", + Self::RefMut => "&mut ", + } + .to_string() + } +} + +impl GetRust for [Prefix] { + fn get_rust(&self) -> String { + self.iter().map(Prefix::get_rust).collect() + } +} + impl GetRust for Postfix { fn get_rust(&self) -> String { match self { From 44c8a792cfc26a6a5f20aa3f35b6637d047dc252 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 20:12:06 +0200 Subject: [PATCH 06/11] Working prefix --- parser/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 22d0183..5d1907c 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -285,11 +285,9 @@ impl From> for Expression { prefixes.push(Prefix::from(inner.next().unwrap())); } - println!("{:#?}", prefixes); - let exp = Expression::from(inner.next().unwrap()); - if inner.len() > 0 { + if inner.len() > 0 || prefixes.len() > 0 { Expression::Fix { initial: Box::new(exp), prefixes, From 73e2680ca055973971d55a342e13750dd93d596b Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 20:19:34 +0200 Subject: [PATCH 07/11] Assign --- parser/src/grammar.pest | 3 +++ parser/src/lib.rs | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index b0522c4..dc508e2 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -45,6 +45,7 @@ statement_list = { statement* } statement = _{ expr_stmt | var_decl_statement + | assign_statement | if_stmt | while_stmt | return_stmt @@ -65,6 +66,8 @@ continue_stmt = { "continue" ~ ";" } var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ ";" } +assign_statement = { expr ~ "=" ~ expr ~ ";" } + if_stmt = { "if" ~ "(" ~ expr ~ ")" ~ statement ~ ("else" ~ statement)? } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 5d1907c..2b5bbbc 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -262,6 +262,15 @@ impl From> for Statement { }) } + Rule::assign_statement => { + let mut inner = pair.into_inner(); + + Statement::VarAssign(VarAssignStmt { + target: Expression::from(inner.next().unwrap()), + value: Expression::from(inner.next().unwrap()), + }) + } + _ => unimplemented!( "Statement parsing not implemented yet: {:?}", pair.as_rule() From 8f95b69e215a6cda90209952285443cbc3e1b2a3 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 20:33:06 +0200 Subject: [PATCH 08/11] Refactored parser --- parser/src/lib.rs | 130 ++++++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 73 deletions(-) diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 2b5bbbc..778faa2 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -28,42 +28,45 @@ 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 => { - let mut inner = pair.into_inner(); - TypeExpr( - TypeExprKind::from(inner.next().unwrap()), - inner.map(TypePostfix::from).collect(), - ) - } - _ => unimplemented!("{pair:#?}"), + let rule = pair.as_rule(); + let mut inner = pair.into_inner(); + + match rule { + Rule::type_expr => TypeExpr( + TypeExprKind::from(inner.next().unwrap()), + inner.map(TypePostfix::from).collect(), + ), + _ => unimplemented!("{rule:#?}"), } } } impl From> for TypePostfix { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { - match pair.as_rule() { + let rule = pair.as_rule(); + let inner = pair.into_inner(); + + match rule { Rule::ref_type => { - if pair.into_inner().peek().is_some() { + if inner.peek().is_some() { TypePostfix::RefMut } else { TypePostfix::Ref } } - _ => unimplemented!("{pair:#?}"), + _ => unimplemented!("{rule:#?}"), } } } 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()) - } + let rule = pair.as_rule(); + let mut inner = pair.into_inner(); + + match rule { + Rule::tuple_type => TypeExprKind::Tuple(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::>(); @@ -73,7 +76,7 @@ impl From> for TypeExprKind { TypeExprKind::PathParams(path, params) } } - _ => unimplemented!("{pair:#?}"), + _ => unimplemented!("{rule:#?}"), } } } @@ -113,23 +116,20 @@ impl From> for FieldList { impl From> for ParamList { fn from(pair: pest::iterators::Pair) -> Self { - let params = pair.into_inner().map(VarDecl::from).collect(); - - ParamList(params) + ParamList(pair.into_inner().map(VarDecl::from).collect()) } } impl TryFrom> for TopLevel { type Error = (); fn try_from(pair: pest::iterators::Pair) -> Result { - match pair.as_rule() { - Rule::import => Ok(TopLevel::Include(StaticPath::from( - pair.into_inner().next().unwrap(), - ))), + let rule = pair.as_rule(); + let mut inner = pair.into_inner(); + + match rule { + Rule::import => Ok(TopLevel::Include(StaticPath::from(inner.next().unwrap()))), Rule::function_decl => { - let mut inner = pair.into_inner(); - let export = if let Some(first) = inner.peek() { if first.as_rule() == Rule::export { inner.next(); @@ -162,7 +162,6 @@ impl TryFrom> for TopLevel { } Rule::struct_decl => { - let mut inner = pair.into_inner(); let export = if let Some(first) = inner.peek() { if first.as_rule() == Rule::export { inner.next(); @@ -185,7 +184,7 @@ impl TryFrom> for TopLevel { } Rule::EOI => Err(()), - _ => unimplemented!("TopLevel parsing not implemented yet {:?}", pair.as_rule()), + _ => unimplemented!("{rule:#?}"), } } } @@ -208,24 +207,19 @@ impl From> for Block { impl From> for Statement { fn from(pair: pest::iterators::Pair) -> Self { - match pair.as_rule() { - Rule::statement => { - let inner = pair.into_inner().next().unwrap(); - Statement::from(inner) - } + let rule = pair.as_rule(); + let mut inner = pair.clone().into_inner(); - Rule::expr_stmt => { - let expr_pair = pair.into_inner().next().unwrap(); - Statement::Expression(Expression::from(expr_pair)) - } + match rule { + Rule::statement => Statement::from(inner.next().unwrap()), - Rule::block => Statement::Block(Block::from(pair.into_inner().next().unwrap())), + Rule::expr_stmt => Statement::Expression(Expression::from(inner.next().unwrap())), + + Rule::block => Statement::Block(Block::from(inner.next().unwrap())), Rule::var_decl_statement => Statement::VarDecl(VarDeclStmt::from(pair)), Rule::return_stmt => { - let mut inner = pair.into_inner(); - let expr = inner.next().map(Expression::from); Statement::Return(expr) @@ -236,8 +230,6 @@ impl From> for Statement { Rule::continue_stmt => Statement::Continue, Rule::if_stmt => { - let mut inner = pair.into_inner(); - let condition = Expression::from(inner.next().unwrap()); let then_branch = Statement::from(inner.next().unwrap()); @@ -251,8 +243,6 @@ impl From> for Statement { } Rule::while_stmt => { - let mut inner = pair.into_inner(); - let condition = Expression::from(inner.next().unwrap()); let body = Statement::from(inner.next().unwrap()); @@ -262,28 +252,23 @@ impl From> for Statement { }) } - Rule::assign_statement => { - let mut inner = pair.into_inner(); + Rule::assign_statement => Statement::VarAssign(VarAssignStmt { + target: Expression::from(inner.next().unwrap()), + value: Expression::from(inner.next().unwrap()), + }), - Statement::VarAssign(VarAssignStmt { - target: Expression::from(inner.next().unwrap()), - value: Expression::from(inner.next().unwrap()), - }) - } - - _ => unimplemented!( - "Statement parsing not implemented yet: {:?}", - pair.as_rule() - ), + _ => unimplemented!("{rule:#?}"), } } } impl From> for Expression { fn from(pair: pest::iterators::Pair) -> Self { - match pair.as_rule() { + let rule = pair.as_rule(); + let mut inner = pair.clone().into_inner(); + + match rule { Rule::expr => { - let mut inner = pair.into_inner(); let mut prefixes = Vec::new(); while inner @@ -306,7 +291,7 @@ impl From> for Expression { exp } } - Rule::primary => Expression::from(pair.into_inner().next().unwrap()), + Rule::primary => Expression::from(inner.next().unwrap()), Rule::static_path => Expression::Path(StaticPath::from(pair)), Rule::integer => { let value = pair.as_str().parse::().unwrap(); @@ -325,10 +310,7 @@ impl From> for Expression { Expression::StringLiteral(inner_str.to_string()) } - _ => unimplemented!( - "Expression parsing not implemented yet {:?}", - pair.as_rule() - ), + _ => unimplemented!("{rule:#?}"), } } } @@ -347,18 +329,21 @@ impl From> for Prefix { impl From> for Postfix { fn from(pair: pest::iterators::Pair) -> Self { - match pair.as_rule() { - Rule::postfix => Postfix::from(pair.into_inner().next().unwrap()), + let rule = pair.as_rule(); + let mut inner = pair.into_inner(); + + match rule { + Rule::postfix => Postfix::from(inner.next().unwrap()), Rule::field_px => { - let field_name = pair.into_inner().next().unwrap().as_str().to_string(); + let field_name = inner.next().unwrap().as_str().to_string(); Postfix::FieldAccess(field_name) } - Rule::call_px => Postfix::Call(pair.into_inner().map(Expression::from).collect()), + Rule::call_px => Postfix::Call(inner.map(Expression::from).collect()), Rule::struct_px => Postfix::StructCall( - pair.into_inner() + inner .map(|p| { let mut pi = p.into_inner(); ( @@ -369,10 +354,9 @@ impl From> for Postfix { .collect(), ), - Rule::index_px => Postfix::Index(Expression::from(pair.into_inner().next().unwrap())), + Rule::index_px => Postfix::Index(Expression::from(inner.next().unwrap())), Rule::binary_px => { - let mut inner = pair.into_inner(); let op_pair = inner.next().unwrap(); let op = match op_pair.as_str() { "+" => BinaryOp::Plus, @@ -394,9 +378,9 @@ impl From> for Postfix { Postfix::Binary(op, Expression::from(inner.next().unwrap())) } - Rule::macro_call_px => Postfix::MacroCall(pair.into_inner().as_str().to_string()), + Rule::macro_call_px => Postfix::MacroCall(inner.as_str().to_string()), - _ => unimplemented!("Postfix parsing not implemented yet {:?}", pair.as_rule()), + _ => unimplemented!("{rule:#?}"), } } } From 341000b98ecfd98204d0e1e48528ae9bde3d0ad3 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 20:40:38 +0200 Subject: [PATCH 09/11] Tuple literals --- parser/src/ast.rs | 1 + parser/src/grammar.pest | 3 +++ parser/src/lib.rs | 2 +- src/codegen.rs | 10 +++++++++- test/src/main.mist | 2 +- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 2a58fed..5051a1d 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -142,6 +142,7 @@ pub enum Expression { FloatLiteral(f64), BoolLiteral(bool), StringLiteral(String), + TupleLiteral(Vec), Fix { initial: Box, prefixes: Vec, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index dc508e2..c6ee1b8 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -87,12 +87,15 @@ macro_inner_v = { | (!("(" | ")") ~ ANY) } +tuple = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } + primary = { integer | float | boolean | string_lit | static_path + | tuple } postfix = { diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 778faa2..a5fda42 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -309,7 +309,7 @@ impl From> for Expression { let inner_str = pair.into_inner().next().unwrap().as_str(); Expression::StringLiteral(inner_str.to_string()) } - + Rule::tuple => Expression::TupleLiteral(inner.map(Expression::from).collect()), _ => unimplemented!("{rule:#?}"), } } diff --git a/src/codegen.rs b/src/codegen.rs index 7463650..a288066 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -113,7 +113,15 @@ impl GetRust for Expression { Expression::FloatLiteral(n) => n.to_string(), Expression::BoolLiteral(b) => b.to_string(), Expression::StringLiteral(s) => format!("\"{}\".to_string()", s), - + Expression::TupleLiteral(t) => { + format!( + "({})", + t.iter() + .map(Expression::get_rust) + .collect::>() + .join(", ") + ) + } Expression::Fix { initial, prefixes, diff --git a/test/src/main.mist b/test/src/main.mist index aa71749..6ae3431 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1,3 @@ void main() { - println!("Hello, World!"); + (i32, i32) = (10, 20); } \ No newline at end of file From a6411624d3c78de31b32b2036fbbeedba3f49340 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 20:44:56 +0200 Subject: [PATCH 10/11] Small refactors --- parser/src/lib.rs | 20 ++++---------------- src/codegen.rs | 2 +- test/src/main.mist | 2 +- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/parser/src/lib.rs b/parser/src/lib.rs index a5fda42..036e8cc 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -293,22 +293,10 @@ impl From> for Expression { } Rule::primary => Expression::from(inner.next().unwrap()), Rule::static_path => Expression::Path(StaticPath::from(pair)), - Rule::integer => { - let value = pair.as_str().parse::().unwrap(); - Expression::IntLiteral(value) - } - Rule::float => { - let value = pair.as_str().parse::().unwrap(); - Expression::FloatLiteral(value) - } - Rule::boolean => { - let value = pair.as_str().parse::().unwrap(); - Expression::BoolLiteral(value) - } - Rule::string_lit => { - let inner_str = pair.into_inner().next().unwrap().as_str(); - Expression::StringLiteral(inner_str.to_string()) - } + Rule::integer => Expression::IntLiteral(pair.as_str().parse::().unwrap()), + Rule::float => Expression::FloatLiteral(pair.as_str().parse::().unwrap()), + Rule::boolean => Expression::BoolLiteral(pair.as_str().parse::().unwrap()), + Rule::string_lit => Expression::StringLiteral(inner.as_str().to_string()), Rule::tuple => Expression::TupleLiteral(inner.map(Expression::from).collect()), _ => unimplemented!("{rule:#?}"), } diff --git a/src/codegen.rs b/src/codegen.rs index a288066..db79b79 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -112,7 +112,7 @@ impl GetRust for Expression { 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::StringLiteral(s) => format!("\"{s}\""), Expression::TupleLiteral(t) => { format!( "({})", diff --git a/test/src/main.mist b/test/src/main.mist index 6ae3431..f5c3828 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1,3 @@ void main() { - (i32, i32) = (10, 20); + (i32, i32, str*) my_tuple = (10, 20, "hello, world"); } \ No newline at end of file From 538de499fe9e623db18848785c6b445e4e4eb8aa Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Mon, 4 May 2026 20:47:27 +0200 Subject: [PATCH 11/11] Fixed string literal escape --- parser/src/grammar.pest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index c6ee1b8..406001c 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -9,7 +9,7 @@ integer = @{ ASCII_DIGIT+ } float = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ } boolean = { "true" | "false" } string_lit = { "\"" ~ inner_str ~ "\"" } -inner_str = @{ (!"\"" ~ ANY)* } +inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* } static_path = { identifier ~ ("::" ~ identifier)* } export = { "public" }