Merge pull request #10 from mist-go/decl-export

Declration export
This commit is contained in:
2026-04-17 13:06:39 +02:00
committed by GitHub
9 changed files with 160 additions and 87 deletions
+1 -12
View File
@@ -3,13 +3,12 @@ use std::collections::HashMap;
use serde::Serialize; use serde::Serialize;
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct ParamList(pub Vec<(String, TypeExpr)>); pub struct ParamList(pub HashMap<String, (bool, TypeExpr)>);
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct Block(pub Vec<Statement>); pub struct Block(pub Vec<Statement>);
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum TypeExpr { pub enum TypeExpr {
Identifier(String), Identifier(String),
} }
@@ -30,7 +29,6 @@ pub enum BinaryOp {
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum TopLevel { pub enum TopLevel {
Import(String), Import(String),
StructDecl { StructDecl {
@@ -48,7 +46,6 @@ pub enum TopLevel {
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum Postfix { pub enum Postfix {
FieldAccess(String), FieldAccess(String),
Call(Vec<Expression>), Call(Vec<Expression>),
@@ -57,7 +54,6 @@ pub enum Postfix {
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum Statement { pub enum Statement {
// expr; // expr;
Expression(Expression), Expression(Expression),
@@ -106,7 +102,6 @@ pub enum Statement {
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum Expression { pub enum Expression {
Identifier(String), Identifier(String),
IntLiteral(i64), IntLiteral(i64),
@@ -125,9 +120,3 @@ 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()
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ export = { "export" }
import = { "import" ~ string_lit ~ ";" } import = { "import" ~ string_lit ~ ";" }
param_list = { param ~ ("," ~ param)* ~ ","? } param_list = { param ~ ("," ~ param)* ~ ","? }
param = { identifier ~ ":" ~ type_expr } param = { export? ~ identifier ~ ":" ~ type_expr }
struct_decl = { struct_decl = {
export? ~ "struct" ~ identifier ~ "{" ~ param_list? ~ "}" export? ~ "struct" ~ identifier ~ "{" ~ param_list? ~ "}"
+14 -7
View File
@@ -1,3 +1,5 @@
use std::collections::HashMap;
use pest::Parser; use pest::Parser;
use pest_derive::Parser; use pest_derive::Parser;
@@ -39,14 +41,21 @@ impl TypeExpr {
} }
impl ParamList { impl ParamList {
pub fn from_pair(pair: pest::iterators::Pair<Rule>) -> Self { pub fn from_pair(export_allowed: bool, pair: pest::iterators::Pair<Rule>) -> Self {
let params = pair let params = pair
.into_inner() .into_inner()
.map(|p| { .map(|p| {
let mut param_inner = p.into_inner(); 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 param_name = param_inner.next().unwrap().as_str().to_string(); let param_name = param_inner.next().unwrap().as_str().to_string();
let param_type = TypeExpr::from_pair(param_inner.next().unwrap()); let param_type = TypeExpr::from_pair(param_inner.next().unwrap());
(param_name, param_type) (param_name, (export, param_type))
}) })
.collect(); .collect();
@@ -76,9 +85,9 @@ impl TopLevel {
}; };
let name = inner.next().unwrap().as_str().to_string(); let name = inner.next().unwrap().as_str().to_string();
let params = if inner.peek().unwrap().as_rule() == Rule::param_list { let params = if inner.peek().unwrap().as_rule() == Rule::param_list {
ParamList::from_pair(inner.next().unwrap()) ParamList::from_pair(false, inner.next().unwrap())
} else { } else {
ParamList(vec![]) ParamList(HashMap::new())
}; };
let return_type = if let Some(next) = inner.peek() { let return_type = if let Some(next) = inner.peek() {
if next.as_rule() == Rule::type_expr { if next.as_rule() == Rule::type_expr {
@@ -115,7 +124,7 @@ impl TopLevel {
}; };
let name = inner.next().unwrap().as_str().to_string(); let name = inner.next().unwrap().as_str().to_string();
let fields_pair = inner.next().unwrap(); let fields_pair = inner.next().unwrap();
let fields = ParamList::from_pair(fields_pair); let fields = ParamList::from_pair(true, fields_pair);
Some(TopLevel::StructDecl { Some(TopLevel::StructDecl {
export, export,
@@ -167,8 +176,6 @@ impl Statement {
let kind_pair = inner.next().unwrap(); // let/const/var let kind_pair = inner.next().unwrap(); // let/const/var
let name_pair = inner.next().unwrap(); // identifier let name_pair = inner.next().unwrap(); // identifier
println!("{:#?}", inner);
let init = inner.next().map(Expression::from_pair); let init = inner.next().map(Expression::from_pair);
let kind = match kind_pair.as_str() { let kind = match kind_pair.as_str() {
+22 -11
View File
@@ -17,6 +17,7 @@ pub enum TypeRef {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct VarRef { pub struct VarRef {
pub export: bool,
pub var_type: Arc<TypeRef>, pub var_type: Arc<TypeRef>,
pub name: String, pub name: String,
} }
@@ -82,6 +83,7 @@ impl TopLevelHirScope {
self.variables.insert( self.variables.insert(
symbol.name.clone(), symbol.name.clone(),
Arc::new(VarRef { Arc::new(VarRef {
export: false,
name: name.clone(), name: name.clone(),
var_type: Arc::new(TypeRef::Function(rf)), var_type: Arc::new(TypeRef::Function(rf)),
}), }),
@@ -97,6 +99,9 @@ impl TopLevelHirScope {
tlss: &TopLevelSymbolScope, tlss: &TopLevelSymbolScope,
symbol: &StructSymbol, symbol: &StructSymbol,
) -> Arc<TypeRef> { ) -> Arc<TypeRef> {
if let Some(rf) = self.variables.get(&symbol.name) {
rf.var_type.clone()
} else {
let name = self.get_name(symbol.export); let name = self.get_name(symbol.export);
let rf = Arc::new(TypeRef::Struct(StructRef { let rf = Arc::new(TypeRef::Struct(StructRef {
@@ -112,6 +117,7 @@ impl TopLevelHirScope {
self.variables.insert( self.variables.insert(
symbol.name.clone(), symbol.name.clone(),
Arc::new(VarRef { Arc::new(VarRef {
export: symbol.export,
name: name.clone(), name: name.clone(),
var_type: rf.clone(), var_type: rf.clone(),
}), }),
@@ -119,11 +125,13 @@ impl TopLevelHirScope {
rf rf
} }
}
pub fn var_ref(&mut self, tlss: &TopLevelSymbolScope, symbol: &VarSymbol) -> Arc<VarRef> { pub fn var_ref(&mut self, tlss: &TopLevelSymbolScope, symbol: &VarSymbol) -> Arc<VarRef> {
Arc::new(VarRef { Arc::new(VarRef {
export: symbol.export,
var_type: self.type_ref(tlss, &symbol.var_type), var_type: self.type_ref(tlss, &symbol.var_type),
name: symbol.name.clone(), name: self.get_name(symbol.export),
}) })
} }
@@ -132,19 +140,12 @@ impl TopLevelHirScope {
var_ref.var_type.clone() var_ref.var_type.clone()
} else { } else {
if let Some(tlss_rf) = tlss.structs.get(&symbol.0) { if let Some(tlss_rf) = tlss.structs.get(&symbol.0) {
let struct_ref = self.struct_ref(tlss, tlss_rf); self.struct_ref(tlss, tlss_rf)
let var_ref = Arc::new(VarRef {
name: symbol.0.clone(),
var_type: struct_ref,
});
self.variables.insert(symbol.0.clone(), var_ref.clone());
var_ref.var_type.clone()
} else { } else {
match symbol.0.as_str() { match symbol.0.as_str() {
"int" => { "int" => {
let var_ref = Arc::new(VarRef { let var_ref = Arc::new(VarRef {
export: false,
name: symbol.0.clone(), name: symbol.0.clone(),
var_type: Arc::new(TypeRef::Int), var_type: Arc::new(TypeRef::Int),
}); });
@@ -167,10 +168,20 @@ impl TopLevelHirScope {
} }
pub fn next_var_idx(&self) -> usize { pub fn next_var_idx(&self) -> usize {
self.var_idx.fetch_add(1, Ordering::Relaxed) + 1 self.var_idx.fetch_add(1, Ordering::Relaxed)
} }
pub fn get_name(&self, export: bool) -> String { pub fn get_name(&self, export: bool) -> String {
format!("{}{}", if export { 'V' } else { 'v' }, self.next_var_idx()) format!("{}{}", if export { 'V' } else { 'v' }, self.next_var_idx())
} }
} }
impl TypeRef {
pub fn get_name(&self) -> String {
match self {
TypeRef::Function(f) => f.name.clone(),
TypeRef::Struct(s) => s.name.clone(),
TypeRef::Int => "int".to_string(),
}
}
}
+42 -4
View File
@@ -1,6 +1,11 @@
use std::sync::Arc; use std::{collections::HashMap, sync::Arc};
use crate::scope::{LocalScope, Scope}; use parser::ast::{ParamList, TypeExpr};
use crate::{
hir::VarRef,
scope::{LocalScope, Scope},
};
pub mod hir; pub mod hir;
pub mod scope; pub mod scope;
@@ -11,7 +16,17 @@ pub fn walk_ast(top_scope: Arc<Scope>, tl: &mut Vec<parser::ast::TopLevel>) {
match tl { match tl {
parser::ast::TopLevel::Import(_) => unimplemented!(), parser::ast::TopLevel::Import(_) => unimplemented!(),
parser::ast::TopLevel::FunctionDecl { params, body, .. } => { parser::ast::TopLevel::FunctionDecl {
params, body, name, ..
} => {
let rf = top_scope.get_reference(name).unwrap();
*name = rf.name.clone();
match &*rf.var_type {
hir::TypeRef::Function(f) => walk_param_list(&f.params, params),
_ => unimplemented!(),
}
let scope = LocalScope::new(top_scope.clone()); let scope = LocalScope::new(top_scope.clone());
scope.with_params(params); scope.with_params(params);
@@ -19,7 +34,30 @@ pub fn walk_ast(top_scope: Arc<Scope>, tl: &mut Vec<parser::ast::TopLevel>) {
scope.with_block(body); scope.with_block(body);
} }
parser::ast::TopLevel::StructDecl { .. } => {} parser::ast::TopLevel::StructDecl { name, fields, .. } => {
let rf = top_scope.get_reference(name).unwrap();
*name = rf.name.clone();
match &*rf.var_type {
hir::TypeRef::Struct(s) => walk_param_list(&s.fields, fields),
_ => unimplemented!(),
} }
} }
} }
}
}
pub fn walk_param_list(fields: &HashMap<String, Arc<VarRef>>, param_list: &mut ParamList) {
let old_param_list = param_list.clone();
param_list.0.clear();
for (name, param) in fields {
param_list.0.insert(
param.name.clone(),
(
old_param_list.0.get(name).map(|a| a.0).unwrap_or_default(),
TypeExpr::Identifier(param.var_type.get_name()),
),
);
}
}
+17 -6
View File
@@ -71,6 +71,7 @@ impl LocalScope {
self.variables.lock().unwrap().insert( self.variables.lock().unwrap().insert(
name.clone(), name.clone(),
Arc::new(VarRef { Arc::new(VarRef {
export: false,
name: name.to_string(), name: name.to_string(),
var_type, var_type,
}), }),
@@ -84,8 +85,8 @@ impl LocalScope {
pub fn walk_postfixes( pub fn walk_postfixes(
self: &Arc<Self>, self: &Arc<Self>,
initial: &Box<ast::Expression>, initial: &mut Box<ast::Expression>,
postfixes: &Vec<Postfix>, postfixes: &mut Vec<Postfix>,
) -> Option<Arc<TypeRef>> { ) -> Option<Arc<TypeRef>> {
let mut current_type = self.get_type_from_expr(initial)?; let mut current_type = self.get_type_from_expr(initial)?;
@@ -93,7 +94,9 @@ impl LocalScope {
match postfix { match postfix {
Postfix::FieldAccess(id) => match &*current_type { Postfix::FieldAccess(id) => match &*current_type {
TypeRef::Struct(s) => { TypeRef::Struct(s) => {
current_type = s.fields.get(id)?.var_type.clone(); let field = s.fields.get(id)?;
*id = field.name.clone();
current_type = field.var_type.clone();
} }
_ => unimplemented!(), _ => unimplemented!(),
}, },
@@ -111,7 +114,10 @@ impl LocalScope {
Some(current_type) Some(current_type)
} }
pub fn get_type_from_expr(self: &Arc<Self>, expr: &ast::Expression) -> Option<Arc<TypeRef>> { pub fn get_type_from_expr(
self: &Arc<Self>,
expr: &mut ast::Expression,
) -> Option<Arc<TypeRef>> {
match expr { match expr {
ast::Expression::IntLiteral(_) => self ast::Expression::IntLiteral(_) => self
.parent .parent
@@ -133,7 +139,11 @@ impl LocalScope {
.get_reference(&"string".to_string()) .get_reference(&"string".to_string())
.map(|r| r.var_type.clone()), .map(|r| r.var_type.clone()),
ast::Expression::Identifier(id) => self.get_reference(id).map(|r| r.var_type.clone()), ast::Expression::Identifier(id) => {
let rf = self.get_reference(id)?;
*id = rf.name.clone();
Some(rf.var_type.clone())
}
ast::Expression::Postfix { initial, postfixes } => { ast::Expression::Postfix { initial, postfixes } => {
self.walk_postfixes(initial, postfixes) self.walk_postfixes(initial, postfixes)
@@ -142,7 +152,7 @@ impl LocalScope {
} }
pub fn with_params(self: &Arc<Self>, param_list: &ParamList) { pub fn with_params(self: &Arc<Self>, param_list: &ParamList) {
for (param_name, type_expr) in &param_list.0 { for (param_name, (export, type_expr)) in &param_list.0 {
match type_expr { match type_expr {
parser::ast::TypeExpr::Identifier(id) => { parser::ast::TypeExpr::Identifier(id) => {
if let Some(var_type) = if let Some(var_type) =
@@ -151,6 +161,7 @@ impl LocalScope {
self.variables.lock().unwrap().insert( self.variables.lock().unwrap().insert(
param_name.clone(), param_name.clone(),
Arc::new(VarRef { Arc::new(VarRef {
export: *export,
var_type, var_type,
name: param_name.clone(), name: param_name.clone(),
}), }),
+25 -4
View File
@@ -9,6 +9,7 @@ pub struct TypeSymbol(pub String);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct VarSymbol { pub struct VarSymbol {
pub export: bool,
pub var_type: TypeSymbol, pub var_type: TypeSymbol,
pub name: String, pub name: String,
} }
@@ -47,12 +48,22 @@ impl FunctionSymbol {
Self { Self {
export: export, export: export,
name: name.clone(), name: name.clone(),
params: params.to_hashmap(|name, v| VarSymbol { params: params
.0
.iter()
.map(|(name, (export, v))| {
(
name.clone(),
VarSymbol {
export: *export,
name: name.clone(), name: name.clone(),
var_type: TypeSymbol(match v { var_type: TypeSymbol(match v {
TypeExpr::Identifier(i) => i.to_string(), TypeExpr::Identifier(i) => i.to_string(),
}), }),
}), },
)
})
.collect(),
return_type: return_type.map(TypeSymbol::from_ast), return_type: return_type.map(TypeSymbol::from_ast),
} }
} }
@@ -63,12 +74,22 @@ impl StructSymbol {
Self { Self {
export, export,
name, name,
fields: fields.to_hashmap(|name, v| VarSymbol { fields: fields
.0
.iter()
.map(|(name, (export, v))| {
(
name.clone(),
VarSymbol {
export: *export,
name: name.clone(), name: name.clone(),
var_type: TypeSymbol(match v { var_type: TypeSymbol(match v {
TypeExpr::Identifier(i) => i.to_string(), TypeExpr::Identifier(i) => i.to_string(),
}), }),
}), },
)
})
.collect(),
// TODO - parse struct methods // TODO - parse struct methods
methods: HashMap::new(), methods: HashMap::new(),
} }
+7 -7
View File
@@ -72,15 +72,15 @@ fn cmd_check(path: &str) {
fn cmd_parse(path: &str) { fn cmd_parse(path: &str) {
let source = read_ms_file(path); let source = read_ms_file(path);
match parser::parse(&source) { match parser::parse(&source) {
Ok(output) => { Ok(mut ast) => {
fs::write( walk_ast(semantic::scope::Scope::from_top(&ast), &mut ast);
"output.json",
serde_json::to_string_pretty(&output).unwrap(), fs::write("output.json", serde_json::to_string_pretty(&ast).unwrap()).unwrap_or_else(
) |e| {
.unwrap_or_else(|e| {
eprintln!("error: could not write output.json: {}", e); eprintln!("error: could not write output.json: {}", e);
process::exit(1); process::exit(1);
}); },
);
} }
Err(e) => { Err(e) => {
eprintln!("parse error:\n{}", e); eprintln!("parse error:\n{}", e);
+3 -7
View File
@@ -1,9 +1,5 @@
struct Test { export struct MyType {
x: int export x: int,
} }
function add() { export function test(a: MyType) { }
let output = test();
}
function test(): int { }