From 6df7f672d01fb8a8b2b93908c7d6eb2382fe692f Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 08:32:29 +0200 Subject: [PATCH 01/11] Simple semantic analysis structure --- Cargo.lock | 5 +++++ Cargo.toml | 1 + semantic/src/lib.rs | 15 ++------------- semantic/src/top_level.rs | 18 ++++++++++++++++++ 4 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 semantic/src/top_level.rs diff --git a/Cargo.lock b/Cargo.lock index b134b8e..53b22b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,7 @@ name = "mist" version = "0.1.0" dependencies = [ "parser", + "semantic", "serde", "serde_json", ] @@ -154,6 +155,10 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "semantic" +version = "0.1.0" + [[package]] name = "serde" version = "1.0.228" diff --git a/Cargo.toml b/Cargo.toml index 9afc151..2a9e8f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ edition = "2024" serde = { version = "1.0.228", features = ["serde_derive"] } serde_json = "1.0.149" parser = { path = "./parser" } +semantic = { path = "./semantic" } diff --git a/semantic/src/lib.rs b/semantic/src/lib.rs index b93cf3f..b4ef974 100644 --- a/semantic/src/lib.rs +++ b/semantic/src/lib.rs @@ -1,14 +1,3 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right -} +pub mod top_level; -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +pub struct Scope {} diff --git a/semantic/src/top_level.rs b/semantic/src/top_level.rs new file mode 100644 index 0000000..5de1c84 --- /dev/null +++ b/semantic/src/top_level.rs @@ -0,0 +1,18 @@ +use std::collections::HashMap; + +pub struct TypeSymbol { + export: bool, + name: String, +} + +pub struct FunctionSymbol { + export: bool, + name: String, + params: HashMap, +} + +pub struct StructSymbol { + export: bool, + name: String, + fields: HashMap, +} From 19629363b012f2352674febd1728deedc5048c96 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 08:40:28 +0200 Subject: [PATCH 02/11] Top level scope --- semantic/src/lib.rs | 3 +-- semantic/src/scope.rs | 21 +++++++++++++++++++++ semantic/src/top_level.rs | 18 ++++++++++-------- 3 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 semantic/src/scope.rs diff --git a/semantic/src/lib.rs b/semantic/src/lib.rs index b4ef974..1e8d15e 100644 --- a/semantic/src/lib.rs +++ b/semantic/src/lib.rs @@ -1,3 +1,2 @@ +pub mod scope; pub mod top_level; - -pub struct Scope {} diff --git a/semantic/src/scope.rs b/semantic/src/scope.rs new file mode 100644 index 0000000..ea4398f --- /dev/null +++ b/semantic/src/scope.rs @@ -0,0 +1,21 @@ +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, +}; + +use crate::top_level; + +pub enum Symbol { + Function(top_level::FunctionSymbol), + TypeSymbol(top_level::TypeSymbol), + StructSymbol(top_level::StructSymbol), +} + +pub struct Scope { + pub parent: Option>, + pub variables: Mutex>, +} + +impl Scope { + pub fn from_top_level() {} +} diff --git a/semantic/src/top_level.rs b/semantic/src/top_level.rs index 5de1c84..904ea45 100644 --- a/semantic/src/top_level.rs +++ b/semantic/src/top_level.rs @@ -1,18 +1,20 @@ use std::collections::HashMap; pub struct TypeSymbol { - export: bool, - name: String, + pub export: bool, + pub name: String, } pub struct FunctionSymbol { - export: bool, - name: String, - params: HashMap, + pub export: bool, + pub name: String, + pub params: HashMap, } pub struct StructSymbol { - export: bool, - name: String, - fields: HashMap, + pub export: bool, + pub name: String, + pub fields: HashMap, + pub methods: HashMap, } + From 6717be038f3836bcaf86e1ecaf5722c5a5accb6e Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 09:16:26 +0200 Subject: [PATCH 03/11] Top level scope --- Cargo.lock | 3 ++ parser/src/ast.rs | 8 +++ semantic/Cargo.toml | 1 + semantic/src/scope.rs | 22 +++----- semantic/src/top_level.rs | 111 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 126 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53b22b8..d1e4cb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,6 +158,9 @@ dependencies = [ [[package]] name = "semantic" version = "0.1.0" +dependencies = [ + "parser", +] [[package]] name = "serde" diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 63d7e24..4d9f0c7 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use serde::Serialize; #[derive(Debug, Clone, Serialize)] @@ -123,3 +125,9 @@ pub enum VarKind { Const, Var, } + +impl ParamList { + pub fn to_hashmap(&self, f: impl Fn(&String, &TypeExpr) -> T) -> HashMap { + self.0.iter().map(|(k, v)| (k.clone(), f(k, v))).collect() + } +} diff --git a/semantic/Cargo.toml b/semantic/Cargo.toml index c290a2c..69caf32 100644 --- a/semantic/Cargo.toml +++ b/semantic/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2024" [dependencies] +parser = { path = "../parser" } diff --git a/semantic/src/scope.rs b/semantic/src/scope.rs index ea4398f..b395e5c 100644 --- a/semantic/src/scope.rs +++ b/semantic/src/scope.rs @@ -1,21 +1,13 @@ -use std::{ - collections::HashMap, - sync::{Arc, Mutex}, -}; +use std::sync::Arc; -use crate::top_level; +use crate::top_level::TopLevelScope; -pub enum Symbol { - Function(top_level::FunctionSymbol), - TypeSymbol(top_level::TypeSymbol), - StructSymbol(top_level::StructSymbol), -} - -pub struct Scope { - pub parent: Option>, - pub variables: Mutex>, +pub enum Scope { + TopLevel(TopLevelScope), } impl Scope { - pub fn from_top_level() {} + pub fn from_top(top_level: &Vec) -> Arc { + Arc::new(Self::TopLevel(TopLevelScope::from(top_level))) + } } diff --git a/semantic/src/top_level.rs b/semantic/src/top_level.rs index 904ea45..1817dc7 100644 --- a/semantic/src/top_level.rs +++ b/semantic/src/top_level.rs @@ -1,20 +1,123 @@ use std::collections::HashMap; -pub struct TypeSymbol { - pub export: bool, +use parser::ast::TopLevel; + +use parser::ast::{ParamList, TypeExpr}; + +pub struct TypeSymbol(pub String); + +pub struct VarSymbol { + pub var_type: TypeSymbol, pub name: String, } pub struct FunctionSymbol { pub export: bool, pub name: String, - pub params: HashMap, + pub params: HashMap, + pub return_type: Option, } pub struct StructSymbol { pub export: bool, pub name: String, - pub fields: HashMap, + pub fields: HashMap, pub methods: HashMap, } +impl TypeSymbol { + pub fn from_ast(expr: TypeExpr) -> Self { + TypeSymbol(match expr { + TypeExpr::Identifier(i) => i.to_string(), + }) + } +} + +impl FunctionSymbol { + pub fn from_ast( + export: bool, + name: String, + params: ParamList, + return_type: Option, + ) -> Self { + Self { + export: export, + name: name.clone(), + params: params.to_hashmap(|name, v| VarSymbol { + name: name.clone(), + var_type: TypeSymbol(match v { + TypeExpr::Identifier(i) => i.to_string(), + }), + }), + return_type: return_type.map(TypeSymbol::from_ast), + } + } +} + +impl StructSymbol { + pub fn from_ast(export: bool, name: String, fields: ParamList) -> Self { + Self { + export, + name, + fields: fields.to_hashmap(|name, v| VarSymbol { + name: name.clone(), + var_type: TypeSymbol(match v { + TypeExpr::Identifier(i) => i.to_string(), + }), + }), + // TODO - parse struct methods + methods: HashMap::new(), + } + } +} + +pub struct TopLevelScope { + pub structs: HashMap, + pub functions: HashMap, +} + +impl TopLevelScope { + pub fn from(top_level: &Vec) -> Self { + let mut scope = TopLevelScope { + structs: HashMap::new(), + functions: HashMap::new(), + }; + + for top in top_level { + match top { + TopLevel::Import(_) => unimplemented!(), + + TopLevel::FunctionDecl { + export, + name, + params, + return_type, + .. + } => { + scope.functions.insert( + name.clone(), + FunctionSymbol::from_ast( + *export, + name.clone(), + params.clone(), + return_type.clone(), + ), + ); + } + + TopLevel::StructDecl { + export, + name, + fields, + } => { + scope.structs.insert( + name.clone(), + StructSymbol::from_ast(*export, name.clone(), fields.clone()), + ); + } + } + } + + scope + } +} From deeb9350b4944b66d918fa0c4df8f762c941b457 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 09:18:56 +0200 Subject: [PATCH 04/11] Semantics in check --- semantic/src/scope.rs | 1 + semantic/src/top_level.rs | 5 +++++ src/main.rs | 6 ++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/semantic/src/scope.rs b/semantic/src/scope.rs index b395e5c..f4b70e7 100644 --- a/semantic/src/scope.rs +++ b/semantic/src/scope.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use crate::top_level::TopLevelScope; +#[derive(Clone, Debug)] pub enum Scope { TopLevel(TopLevelScope), } diff --git a/semantic/src/top_level.rs b/semantic/src/top_level.rs index 1817dc7..a0caf07 100644 --- a/semantic/src/top_level.rs +++ b/semantic/src/top_level.rs @@ -4,13 +4,16 @@ use parser::ast::TopLevel; use parser::ast::{ParamList, TypeExpr}; +#[derive(Clone, Debug)] pub struct TypeSymbol(pub String); +#[derive(Clone, Debug)] pub struct VarSymbol { pub var_type: TypeSymbol, pub name: String, } +#[derive(Clone, Debug)] pub struct FunctionSymbol { pub export: bool, pub name: String, @@ -18,6 +21,7 @@ pub struct FunctionSymbol { pub return_type: Option, } +#[derive(Clone, Debug)] pub struct StructSymbol { pub export: bool, pub name: String, @@ -71,6 +75,7 @@ impl StructSymbol { } } +#[derive(Clone, Debug)] pub struct TopLevelScope { pub structs: HashMap, pub functions: HashMap, diff --git a/src/main.rs b/src/main.rs index ad40e2b..bff6a1f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,8 +53,10 @@ pub fn cmd_build() { fn cmd_check(path: &str) { let source = read_ms_file(path); match parser::parse(&source) { - Ok(_) => { - println!("ok"); + Ok(ast) => { + println!("parse: ok"); + + println!("{:#?}", semantic::scope::Scope::from_top(&ast)) } Err(e) => { eprintln!("parse error:\n{}", e); From 4907533441d54aafb5c64cd357b1f49d27212d1c Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 10:51:55 +0200 Subject: [PATCH 05/11] HIR --- semantic/src/hir.rs | 148 ++++++++++++++++++++++++++++++++++++++ semantic/src/lib.rs | 1 + semantic/src/scope.rs | 7 +- semantic/src/top_level.rs | 6 +- 4 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 semantic/src/hir.rs diff --git a/semantic/src/hir.rs b/semantic/src/hir.rs new file mode 100644 index 0000000..e1b2a7c --- /dev/null +++ b/semantic/src/hir.rs @@ -0,0 +1,148 @@ +use std::{collections::HashMap, sync::Arc}; + +use crate::top_level::{FunctionSymbol, StructSymbol, TopLevelSymbolScope, TypeSymbol, VarSymbol}; + +#[derive(Clone, Debug)] +pub enum TypeRef { + Struct(StructRef), +} + +#[derive(Clone, Debug)] +pub struct VarRef { + pub var_type: Arc, + pub name: String, +} + +#[derive(Clone, Debug)] +pub struct FunctionRef { + pub export: bool, + pub name: String, + pub params: HashMap>, + pub return_type: Option>, +} + +#[derive(Clone, Debug)] +pub struct StructRef { + pub export: bool, + pub name: String, + pub fields: HashMap>, + pub methods: HashMap, +} + +#[derive(Clone, Debug)] +pub struct TopLevelHirScope { + pub types: HashMap>, + pub functions: HashMap>, +} + +impl TopLevelHirScope { + pub fn from_tlss(tlss: &TopLevelSymbolScope) -> Self { + let mut scope = Self { + types: HashMap::new(), + functions: HashMap::new(), + }; + + for (_, symbol) in &tlss.functions { + scope.function_ref(tlss, symbol); + } + + for (_, symbol) in &tlss.structs { + scope.struct_ref(tlss, symbol); + } + + scope + } + + pub fn function_ref( + &mut self, + tlss: &TopLevelSymbolScope, + symbol: &FunctionSymbol, + ) -> Arc { + if let Some(rf) = self.functions.get(&symbol.name) { + rf.clone() + } else { + if let Some(tlss_rf) = tlss.functions.get(&symbol.name) { + let rf = Arc::new(FunctionRef { + export: symbol.export, + name: symbol.name.clone(), + params: symbol + .params + .iter() + .map(|(name, v)| (name.clone(), self.var_ref(tlss, v))) + .collect(), + return_type: symbol + .return_type + .clone() + .map(|rt| self.type_ref(tlss, &rt)), + }); + + self.functions.insert(symbol.name.clone(), rf.clone()); + + rf + } else { + unimplemented!() + } + } + } + + pub fn struct_ref( + &mut self, + tlss: &TopLevelSymbolScope, + symbol: &StructSymbol, + ) -> Arc { + let rf = Arc::new(TypeRef::Struct(StructRef { + export: symbol.export, + name: symbol.name.clone(), + fields: symbol + .fields + .iter() + .map(|(name, v)| (name.clone(), self.var_ref(tlss, v))) + .collect(), + methods: HashMap::new(), + })); + + self.types.insert(symbol.name.clone(), rf.clone()); + + rf + } + + pub fn var_ref(&mut self, tlss: &TopLevelSymbolScope, symbol: &VarSymbol) -> Arc { + Arc::new(VarRef { + var_type: self.type_ref(tlss, &symbol.var_type), + name: symbol.name.clone(), + }) + } + + pub fn type_ref(&mut self, tlss: &TopLevelSymbolScope, symbol: &TypeSymbol) -> Arc { + if let Some(rf) = self.types.get(&symbol.0) { + rf.clone() + } else { + if let Some(tlss_rf) = tlss.structs.get(&symbol.0) { + let rf = Arc::new(TypeRef::Struct(StructRef { + export: tlss_rf.export, + name: tlss_rf.name.clone(), + fields: tlss_rf + .fields + .iter() + .map(|(name, v)| { + ( + name.clone(), + Arc::new(VarRef { + name: name.clone(), + var_type: self.type_ref(tlss, &v.var_type), + }), + ) + }) + .collect(), + methods: HashMap::new(), + })); + + self.types.insert(symbol.0.clone(), rf.clone()); + + rf + } else { + unimplemented!() + } + } + } +} diff --git a/semantic/src/lib.rs b/semantic/src/lib.rs index 1e8d15e..b601db3 100644 --- a/semantic/src/lib.rs +++ b/semantic/src/lib.rs @@ -1,2 +1,3 @@ +pub mod hir; pub mod scope; pub mod top_level; diff --git a/semantic/src/scope.rs b/semantic/src/scope.rs index f4b70e7..da087e6 100644 --- a/semantic/src/scope.rs +++ b/semantic/src/scope.rs @@ -1,14 +1,15 @@ use std::sync::Arc; -use crate::top_level::TopLevelScope; +use crate::{hir::TopLevelHirScope, top_level::TopLevelSymbolScope}; #[derive(Clone, Debug)] pub enum Scope { - TopLevel(TopLevelScope), + TopLevel(TopLevelHirScope), } impl Scope { pub fn from_top(top_level: &Vec) -> Arc { - Arc::new(Self::TopLevel(TopLevelScope::from(top_level))) + let tl = TopLevelSymbolScope::from(top_level); + Arc::new(Self::TopLevel(TopLevelHirScope::from_tlss(&tl))) } } diff --git a/semantic/src/top_level.rs b/semantic/src/top_level.rs index a0caf07..ffcd52d 100644 --- a/semantic/src/top_level.rs +++ b/semantic/src/top_level.rs @@ -76,14 +76,14 @@ impl StructSymbol { } #[derive(Clone, Debug)] -pub struct TopLevelScope { +pub struct TopLevelSymbolScope { pub structs: HashMap, pub functions: HashMap, } -impl TopLevelScope { +impl TopLevelSymbolScope { pub fn from(top_level: &Vec) -> Self { - let mut scope = TopLevelScope { + let mut scope = TopLevelSymbolScope { structs: HashMap::new(), functions: HashMap::new(), }; From 7ce90478f0045d3a2af97527f0962c6b808842a8 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 10:56:39 +0200 Subject: [PATCH 06/11] working hir --- semantic/src/hir.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/semantic/src/hir.rs b/semantic/src/hir.rs index e1b2a7c..f22e58c 100644 --- a/semantic/src/hir.rs +++ b/semantic/src/hir.rs @@ -5,6 +5,7 @@ use crate::top_level::{FunctionSymbol, StructSymbol, TopLevelSymbolScope, TypeSy #[derive(Clone, Debug)] pub enum TypeRef { Struct(StructRef), + Int, } #[derive(Clone, Debug)] @@ -61,7 +62,7 @@ impl TopLevelHirScope { if let Some(rf) = self.functions.get(&symbol.name) { rf.clone() } else { - if let Some(tlss_rf) = tlss.functions.get(&symbol.name) { + if let Some(_) = tlss.functions.get(&symbol.name) { let rf = Arc::new(FunctionRef { export: symbol.export, name: symbol.name.clone(), @@ -141,7 +142,19 @@ impl TopLevelHirScope { rf } else { - unimplemented!() + match symbol.0.as_str() { + "int" => { + let rf = Arc::new(TypeRef::Int); + + self.types.insert(symbol.0.clone(), rf.clone()); + + rf + } + + _ => { + unimplemented!("{:?}", symbol) + } + } } } } From cb03653e88e23e2149335482616b462c65cde3c0 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 11:18:20 +0200 Subject: [PATCH 07/11] Refrencing and LocalScope --- semantic/src/hir.rs | 15 ++++++++++++++- semantic/src/scope.rs | 37 +++++++++++++++++++++++++++++++++++-- test/src/main.ms | 23 ++++------------------- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/semantic/src/hir.rs b/semantic/src/hir.rs index f22e58c..d1f94fe 100644 --- a/semantic/src/hir.rs +++ b/semantic/src/hir.rs @@ -1,6 +1,9 @@ use std::{collections::HashMap, sync::Arc}; -use crate::top_level::{FunctionSymbol, StructSymbol, TopLevelSymbolScope, TypeSymbol, VarSymbol}; +use crate::{ + scope::Refrence, + top_level::{FunctionSymbol, StructSymbol, TopLevelSymbolScope, TypeSymbol, VarSymbol}, +}; #[derive(Clone, Debug)] pub enum TypeRef { @@ -158,4 +161,14 @@ impl TopLevelHirScope { } } } + + pub fn get_refrence(&self, name: &String) -> Option { + if let Some(r) = self.functions.get(name) { + Some(Refrence::Func(r.clone())) + } else if let Some(r) = self.types.get(name) { + Some(Refrence::Type(r.clone())) + } else { + None + } + } } diff --git a/semantic/src/scope.rs b/semantic/src/scope.rs index da087e6..6e00430 100644 --- a/semantic/src/scope.rs +++ b/semantic/src/scope.rs @@ -1,10 +1,21 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; -use crate::{hir::TopLevelHirScope, top_level::TopLevelSymbolScope}; +use crate::{ + hir::{FunctionRef, TopLevelHirScope, TypeRef, VarRef}, + top_level::TopLevelSymbolScope, +}; + +#[derive(Clone, Debug)] +pub enum Refrence { + Type(Arc), + Var(Arc), + Func(Arc), +} #[derive(Clone, Debug)] pub enum Scope { TopLevel(TopLevelHirScope), + Local(LocalScope), } impl Scope { @@ -12,4 +23,26 @@ impl Scope { let tl = TopLevelSymbolScope::from(top_level); Arc::new(Self::TopLevel(TopLevelHirScope::from_tlss(&tl))) } + + pub fn get_refrence(&self, name: &String) -> Option { + match self { + Scope::TopLevel(tl) => tl.get_refrence(name), + Scope::Local(l) => l.variables.get(name).cloned().map(Refrence::Var), + } + } +} + +#[derive(Clone, Debug)] +pub struct LocalScope { + pub parent: Arc, + pub variables: HashMap>, +} + +impl LocalScope { + pub fn from_block(parent: Arc) -> Arc { + Arc::new(LocalScope { + parent, + variables: HashMap::new(), + }) + } } diff --git a/test/src/main.ms b/test/src/main.ms index eaed9a5..bede08a 100644 --- a/test/src/main.ms +++ b/test/src/main.ms @@ -1,21 +1,6 @@ -function add(a: int, b: int): int { - let sum = 0; - - for (let i = 0; i < 10; i = i + 1) { - if (i == 5) { - continue; - } - - sum = sum + i; - } - - if (sum > 20) { - return sum; - } else { - return 0; - } +struct AddParams { + x: int, + y: int, } -function main() { - add(10, 10); -} +function add(p: AddParams) {} From 0d63528d10fe5b81094e46b726025d037464b66e Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 11:47:36 +0200 Subject: [PATCH 08/11] Walking ast --- semantic/src/hir.rs | 2 +- semantic/src/scope.rs | 63 ++++++++++++++++++++++++++++++++++++++----- src/main.rs | 8 ++++-- 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/semantic/src/hir.rs b/semantic/src/hir.rs index d1f94fe..bf6da89 100644 --- a/semantic/src/hir.rs +++ b/semantic/src/hir.rs @@ -33,7 +33,7 @@ pub struct StructRef { pub methods: HashMap, } -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct TopLevelHirScope { pub types: HashMap>, pub functions: HashMap>, diff --git a/semantic/src/scope.rs b/semantic/src/scope.rs index 6e00430..7c5e8cb 100644 --- a/semantic/src/scope.rs +++ b/semantic/src/scope.rs @@ -1,4 +1,9 @@ -use std::{collections::HashMap, sync::Arc}; +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, +}; + +use parser::ast::Statement; use crate::{ hir::{FunctionRef, TopLevelHirScope, TypeRef, VarRef}, @@ -12,7 +17,7 @@ pub enum Refrence { Func(Arc), } -#[derive(Clone, Debug)] +#[derive(Debug)] pub enum Scope { TopLevel(TopLevelHirScope), Local(LocalScope), @@ -27,22 +32,66 @@ impl Scope { pub fn get_refrence(&self, name: &String) -> Option { match self { Scope::TopLevel(tl) => tl.get_refrence(name), - Scope::Local(l) => l.variables.get(name).cloned().map(Refrence::Var), + Scope::Local(l) => l + .variables + .lock() + .unwrap() + .get(name) + .cloned() + .map(Refrence::Var), } } } -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct LocalScope { pub parent: Arc, - pub variables: HashMap>, + pub variables: Mutex>>, } impl LocalScope { - pub fn from_block(parent: Arc) -> Arc { + pub fn new(parent: Arc) -> Arc { Arc::new(LocalScope { parent, - variables: HashMap::new(), + variables: Mutex::new(HashMap::new()), }) } + + pub fn with_block(self: &Arc, block: &mut parser::ast::Block) { + for statement in &mut block.0 { + match statement { + Statement::Block(b) => self.clone().with_block(b), + _ => {} + } + } + } +} + +pub fn walk_ast(top_scope: Arc, tl: &mut Vec) { + for tl in tl { + match tl { + parser::ast::TopLevel::Import(_) => unimplemented!(), + + parser::ast::TopLevel::FunctionDecl { + export, + name, + params, + return_type, + body, + } => { + let scope = LocalScope::new(top_scope.clone()); + scope.with_block(body); + + println!("{:?}", scope); + } + + parser::ast::TopLevel::StructDecl { + export, + name, + fields, + } => { + + } + } + } } diff --git a/src/main.rs b/src/main.rs index bff6a1f..fc20c5b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,8 @@ use std::fs; use std::path::PathBuf; use std::process; +use semantic::scope::walk_ast; + fn main() { let args: Vec = std::env::args().collect(); @@ -53,10 +55,12 @@ pub fn cmd_build() { fn cmd_check(path: &str) { let source = read_ms_file(path); match parser::parse(&source) { - Ok(ast) => { + Ok(mut ast) => { println!("parse: ok"); - println!("{:#?}", semantic::scope::Scope::from_top(&ast)) + walk_ast(semantic::scope::Scope::from_top(&ast), &mut ast); + + println!("{:#?}", ast) } Err(e) => { eprintln!("parse error:\n{}", e); From 88bf07b91379e0f1344f797f649f2a0f3c277d90 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 11:57:45 +0200 Subject: [PATCH 09/11] function params --- semantic/src/scope.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/semantic/src/scope.rs b/semantic/src/scope.rs index 7c5e8cb..34ce4b1 100644 --- a/semantic/src/scope.rs +++ b/semantic/src/scope.rs @@ -3,7 +3,7 @@ use std::{ sync::{Arc, Mutex}, }; -use parser::ast::Statement; +use parser::ast::{ParamList, Statement}; use crate::{ hir::{FunctionRef, TopLevelHirScope, TypeRef, VarRef}, @@ -65,6 +65,25 @@ impl LocalScope { } } } + + pub fn with_params(self: &Arc, param_list: &ParamList) { + for (param_name, type_expr) in ¶m_list.0 { + match type_expr { + parser::ast::TypeExpr::Identifier(id) => match self.parent.get_refrence(id) { + Some(Refrence::Type(type_ref)) => { + self.variables.lock().unwrap().insert( + param_name.clone(), + Arc::new(VarRef { + var_type: type_ref, + name: param_name.clone(), + }), + ); + } + _ => unimplemented!(), + }, + } + } + } } pub fn walk_ast(top_scope: Arc, tl: &mut Vec) { @@ -80,6 +99,9 @@ pub fn walk_ast(top_scope: Arc, tl: &mut Vec) { body, } => { let scope = LocalScope::new(top_scope.clone()); + + scope.with_params(params); + scope.with_block(body); println!("{:?}", scope); @@ -89,9 +111,7 @@ pub fn walk_ast(top_scope: Arc, tl: &mut Vec) { export, name, fields, - } => { - - } + } => {} } } } From 04087abbdf55eaa541657514ca6756f311cc1c59 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 12:18:40 +0200 Subject: [PATCH 10/11] small refactor --- semantic/src/lib.rs | 34 ++++++++++++++++++++++++++++++++++ semantic/src/scope.rs | 31 +------------------------------ src/main.rs | 2 +- test/src/main.ms | 9 +++------ 4 files changed, 39 insertions(+), 37 deletions(-) diff --git a/semantic/src/lib.rs b/semantic/src/lib.rs index b601db3..8dd6f97 100644 --- a/semantic/src/lib.rs +++ b/semantic/src/lib.rs @@ -1,3 +1,37 @@ +use std::sync::Arc; + +use crate::scope::{LocalScope, Scope}; + pub mod hir; pub mod scope; pub mod top_level; + +pub fn walk_ast(top_scope: Arc, tl: &mut Vec) { + for tl in tl { + match tl { + parser::ast::TopLevel::Import(_) => unimplemented!(), + + parser::ast::TopLevel::FunctionDecl { + export, + name, + params, + return_type, + body, + } => { + let scope = LocalScope::new(top_scope.clone()); + + scope.with_params(params); + + scope.with_block(body); + + println!("{:?}", scope); + } + + parser::ast::TopLevel::StructDecl { + export, + name, + fields, + } => {} + } + } +} diff --git a/semantic/src/scope.rs b/semantic/src/scope.rs index 34ce4b1..7dd42c8 100644 --- a/semantic/src/scope.rs +++ b/semantic/src/scope.rs @@ -61,6 +61,7 @@ impl LocalScope { for statement in &mut block.0 { match statement { Statement::Block(b) => self.clone().with_block(b), + Statement::VarDecl { kind, name, init } => unimplemented!(), _ => {} } } @@ -85,33 +86,3 @@ impl LocalScope { } } } - -pub fn walk_ast(top_scope: Arc, tl: &mut Vec) { - for tl in tl { - match tl { - parser::ast::TopLevel::Import(_) => unimplemented!(), - - parser::ast::TopLevel::FunctionDecl { - export, - name, - params, - return_type, - body, - } => { - let scope = LocalScope::new(top_scope.clone()); - - scope.with_params(params); - - scope.with_block(body); - - println!("{:?}", scope); - } - - parser::ast::TopLevel::StructDecl { - export, - name, - fields, - } => {} - } - } -} diff --git a/src/main.rs b/src/main.rs index fc20c5b..dec07c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use std::fs; use std::path::PathBuf; use std::process; -use semantic::scope::walk_ast; +use semantic::walk_ast; fn main() { let args: Vec = std::env::args().collect(); diff --git a/test/src/main.ms b/test/src/main.ms index bede08a..350881d 100644 --- a/test/src/main.ms +++ b/test/src/main.ms @@ -1,6 +1,3 @@ -struct AddParams { - x: int, - y: int, -} - -function add(p: AddParams) {} +function add(a: int, b: int) { + let a = 10; +} \ No newline at end of file From 09c7f07c957db320fc7e4194dd38a5bf4f555a5b Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Wed, 15 Apr 2026 12:36:42 +0200 Subject: [PATCH 11/11] Variable decleration --- semantic/src/scope.rs | 29 +++++++++++++++++++++++++++-- test/src/main.ms | 2 +- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/semantic/src/scope.rs b/semantic/src/scope.rs index 7dd42c8..5755912 100644 --- a/semantic/src/scope.rs +++ b/semantic/src/scope.rs @@ -3,7 +3,7 @@ use std::{ sync::{Arc, Mutex}, }; -use parser::ast::{ParamList, Statement}; +use parser::ast::{self, ParamList, Statement}; use crate::{ hir::{FunctionRef, TopLevelHirScope, TypeRef, VarRef}, @@ -61,12 +61,37 @@ impl LocalScope { for statement in &mut block.0 { match statement { Statement::Block(b) => self.clone().with_block(b), - Statement::VarDecl { kind, name, init } => unimplemented!(), + Statement::VarDecl { kind, name, init } => { + if let Some(init) = init { + self.variables.lock().unwrap().insert( + name.clone(), + Arc::new(VarRef { + name: name.to_string(), + var_type: self.get_type_from_expr(init).unwrap(), + }), + ); + } + } _ => {} } } } + pub fn get_type_from_expr(self: &Arc, expr: &ast::Expression) -> Option> { + match expr { + ast::Expression::IntLiteral(_) => { + self.parent.get_refrence(&"int".to_string()).map(|r| { + if let Refrence::Type(tr) = &r { + tr.clone() + } else { + unimplemented!() + } + }) + } + _ => unimplemented!(), + } + } + pub fn with_params(self: &Arc, param_list: &ParamList) { for (param_name, type_expr) in ¶m_list.0 { match type_expr { diff --git a/test/src/main.ms b/test/src/main.ms index 350881d..e3ccd76 100644 --- a/test/src/main.ms +++ b/test/src/main.ms @@ -1,3 +1,3 @@ function add(a: int, b: int) { - let a = 10; + let myVar = 10; } \ No newline at end of file