Generated
+8
@@ -79,6 +79,7 @@ name = "mist"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parser",
|
"parser",
|
||||||
|
"semantic",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
@@ -154,6 +155,13 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semantic"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"parser",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ edition = "2024"
|
|||||||
serde = { version = "1.0.228", features = ["serde_derive"] }
|
serde = { version = "1.0.228", features = ["serde_derive"] }
|
||||||
serde_json = "1.0.149"
|
serde_json = "1.0.149"
|
||||||
parser = { path = "./parser" }
|
parser = { path = "./parser" }
|
||||||
|
semantic = { path = "./semantic" }
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
@@ -123,3 +125,9 @@ pub enum VarKind {
|
|||||||
Const,
|
Const,
|
||||||
Var,
|
Var,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParamList {
|
||||||
|
pub fn to_hashmap<T>(&self, f: impl Fn(&String, &TypeExpr) -> T) -> HashMap<String, T> {
|
||||||
|
self.0.iter().map(|(k, v)| (k.clone(), f(k, v))).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
parser = { path = "../parser" }
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
scope::Refrence,
|
||||||
|
top_level::{FunctionSymbol, StructSymbol, TopLevelSymbolScope, TypeSymbol, VarSymbol},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum TypeRef {
|
||||||
|
Struct(StructRef),
|
||||||
|
Int,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct VarRef {
|
||||||
|
pub var_type: Arc<TypeRef>,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct FunctionRef {
|
||||||
|
pub export: bool,
|
||||||
|
pub name: String,
|
||||||
|
pub params: HashMap<String, Arc<VarRef>>,
|
||||||
|
pub return_type: Option<Arc<TypeRef>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct StructRef {
|
||||||
|
pub export: bool,
|
||||||
|
pub name: String,
|
||||||
|
pub fields: HashMap<String, Arc<VarRef>>,
|
||||||
|
pub methods: HashMap<String, FunctionRef>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TopLevelHirScope {
|
||||||
|
pub types: HashMap<String, Arc<TypeRef>>,
|
||||||
|
pub functions: HashMap<String, Arc<FunctionRef>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<FunctionRef> {
|
||||||
|
if let Some(rf) = self.functions.get(&symbol.name) {
|
||||||
|
rf.clone()
|
||||||
|
} else {
|
||||||
|
if let Some(_) = 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<TypeRef> {
|
||||||
|
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<VarRef> {
|
||||||
|
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<TypeRef> {
|
||||||
|
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 {
|
||||||
|
match symbol.0.as_str() {
|
||||||
|
"int" => {
|
||||||
|
let rf = Arc::new(TypeRef::Int);
|
||||||
|
|
||||||
|
self.types.insert(symbol.0.clone(), rf.clone());
|
||||||
|
|
||||||
|
rf
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
unimplemented!("{:?}", symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_refrence(&self, name: &String) -> Option<Refrence> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
-10
@@ -1,14 +1,37 @@
|
|||||||
pub fn add(left: u64, right: u64) -> u64 {
|
use std::sync::Arc;
|
||||||
left + right
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
use crate::scope::{LocalScope, Scope};
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
pub mod hir;
|
||||||
fn it_works() {
|
pub mod scope;
|
||||||
let result = add(2, 2);
|
pub mod top_level;
|
||||||
assert_eq!(result, 4);
|
|
||||||
|
pub fn walk_ast(top_scope: Arc<Scope>, tl: &mut Vec<parser::ast::TopLevel>) {
|
||||||
|
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,
|
||||||
|
} => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
use parser::ast::{self, ParamList, Statement};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
hir::{FunctionRef, TopLevelHirScope, TypeRef, VarRef},
|
||||||
|
top_level::TopLevelSymbolScope,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Refrence {
|
||||||
|
Type(Arc<TypeRef>),
|
||||||
|
Var(Arc<VarRef>),
|
||||||
|
Func(Arc<FunctionRef>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Scope {
|
||||||
|
TopLevel(TopLevelHirScope),
|
||||||
|
Local(LocalScope),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scope {
|
||||||
|
pub fn from_top(top_level: &Vec<parser::ast::TopLevel>) -> Arc<Self> {
|
||||||
|
let tl = TopLevelSymbolScope::from(top_level);
|
||||||
|
Arc::new(Self::TopLevel(TopLevelHirScope::from_tlss(&tl)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_refrence(&self, name: &String) -> Option<Refrence> {
|
||||||
|
match self {
|
||||||
|
Scope::TopLevel(tl) => tl.get_refrence(name),
|
||||||
|
Scope::Local(l) => l
|
||||||
|
.variables
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.get(name)
|
||||||
|
.cloned()
|
||||||
|
.map(Refrence::Var),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LocalScope {
|
||||||
|
pub parent: Arc<Scope>,
|
||||||
|
pub variables: Mutex<HashMap<String, Arc<VarRef>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LocalScope {
|
||||||
|
pub fn new(parent: Arc<Scope>) -> Arc<Self> {
|
||||||
|
Arc::new(LocalScope {
|
||||||
|
parent,
|
||||||
|
variables: Mutex::new(HashMap::new()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_block(self: &Arc<Self>, block: &mut parser::ast::Block) {
|
||||||
|
for statement in &mut block.0 {
|
||||||
|
match statement {
|
||||||
|
Statement::Block(b) => self.clone().with_block(b),
|
||||||
|
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<Self>, expr: &ast::Expression) -> Option<Arc<TypeRef>> {
|
||||||
|
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<Self>, 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!(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
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,
|
||||||
|
pub params: HashMap<String, VarSymbol>,
|
||||||
|
pub return_type: Option<TypeSymbol>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct StructSymbol {
|
||||||
|
pub export: bool,
|
||||||
|
pub name: String,
|
||||||
|
pub fields: HashMap<String, VarSymbol>,
|
||||||
|
pub methods: HashMap<String, FunctionSymbol>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<TypeExpr>,
|
||||||
|
) -> 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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct TopLevelSymbolScope {
|
||||||
|
pub structs: HashMap<String, StructSymbol>,
|
||||||
|
pub functions: HashMap<String, FunctionSymbol>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TopLevelSymbolScope {
|
||||||
|
pub fn from(top_level: &Vec<TopLevel>) -> Self {
|
||||||
|
let mut scope = TopLevelSymbolScope {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-2
@@ -2,6 +2,8 @@ use std::fs;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
|
use semantic::walk_ast;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
|
||||||
@@ -53,8 +55,12 @@ pub fn cmd_build() {
|
|||||||
fn cmd_check(path: &str) {
|
fn cmd_check(path: &str) {
|
||||||
let source = read_ms_file(path);
|
let source = read_ms_file(path);
|
||||||
match parser::parse(&source) {
|
match parser::parse(&source) {
|
||||||
Ok(_) => {
|
Ok(mut ast) => {
|
||||||
println!("ok");
|
println!("parse: ok");
|
||||||
|
|
||||||
|
walk_ast(semantic::scope::Scope::from_top(&ast), &mut ast);
|
||||||
|
|
||||||
|
println!("{:#?}", ast)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("parse error:\n{}", e);
|
eprintln!("parse error:\n{}", e);
|
||||||
|
|||||||
+2
-20
@@ -1,21 +1,3 @@
|
|||||||
function add(a: int, b: int): int {
|
function add(a: int, b: int) {
|
||||||
let sum = 0;
|
let myVar = 10;
|
||||||
|
|
||||||
for (let i = 0; i < 10; i = i + 1) {
|
|
||||||
if (i == 5) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sum = sum + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum > 20) {
|
|
||||||
return sum;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
add(10, 10);
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user