From d4edea0e62f5352ae58e01175ea8ea226d1e8412 Mon Sep 17 00:00:00 2001 From: shadow cat Date: Fri, 25 Apr 2025 00:37:42 -0400 Subject: [PATCH] had a conversation w the code --- data/test.lang | 5 +- src/ir/lower/program.rs | 12 ++-- src/ir/upper/kind.rs | 46 ++++++++++----- src/ir/upper/maps.rs | 109 +++++++++++++++++++++++++++++++++++ src/ir/upper/mod.rs | 3 + src/ir/upper/program.rs | 102 +++++++------------------------- src/ir/upper/validate.rs | 21 ++++--- src/parser/v3/lower/def.rs | 9 +-- src/parser/v3/lower/expr.rs | 6 +- src/parser/v3/lower/func.rs | 21 +------ src/parser/v3/lower/struc.rs | 16 ++--- src/parser/v3/lower/ty.rs | 9 ++- 12 files changed, 205 insertions(+), 154 deletions(-) create mode 100644 src/ir/upper/maps.rs diff --git a/data/test.lang b/data/test.lang index 7ad59ca..e91466a 100644 --- a/data/test.lang +++ b/data/test.lang @@ -75,20 +75,23 @@ fn structer(test: Test) { println(""); } -struct GTest { +struct GTest { a: T, b: U, + c: V, } fn generic() { let gt = GTest { a: 39, b: "hello", + c: 40, }; print("generic: "); print_dec(gt.a); print(", "); print(gt.b); + print_dec(gt.c); println(""); } diff --git a/src/ir/lower/program.rs b/src/ir/lower/program.rs index faaf802..cc429b9 100644 --- a/src/ir/lower/program.rs +++ b/src/ir/lower/program.rs @@ -17,7 +17,7 @@ impl LProgram { pub fn create(p: &UProgram) -> Result { let start = p .names - .lookup::("start") + .id::("start") .ok_or("no start method found")?; let mut ssbuilder = SymbolSpaceBuilder::with_entries(&[start]); let entry = ssbuilder.func(&start); @@ -31,7 +31,7 @@ impl LProgram { fbuilder.instrs.push(LInstruction::Ret { src: None }); } let res = fbuilder.finish(f); - ssbuilder.write_fn(sym, res, Some(p.names.get(i).to_string())); + ssbuilder.write_fn(sym, res, Some(p.names.name(i).to_string())); } let sym_space = ssbuilder.finish().expect("we failed the mission"); Ok(Self { sym_space, entry }) @@ -101,7 +101,7 @@ impl<'a> LFunctionBuilder<'a> { }; self.map_subvar(i); let var = self.data.var_offset(self.program, i).expect("var offset"); - if let None = self.stack.get(&var.id) { + if !self.stack.contains_key(&var.id) { let size = self .data .size_of_var(self.program, var.id) @@ -142,7 +142,7 @@ impl<'a> LFunctionBuilder<'a> { let sym = self.data.builder.ro_data( src, &data.content, - Some(self.program.names.get(dest.id).to_string()), + Some(self.program.names.name(dest.id).to_string()), ); self.instrs.push(LInstruction::LoadData { dest: dest.id, @@ -163,7 +163,7 @@ impl<'a> LFunctionBuilder<'a> { let sym = self.data.builder.ro_data( src, &data.content, - Some(self.program.names.get(dest.id).to_string()), + Some(self.program.names.name(dest.id).to_string()), ); self.instrs.push(LInstruction::LoadAddr { dest: dest.id, @@ -193,7 +193,7 @@ impl<'a> LFunctionBuilder<'a> { UInstruction::Call { dest, f, args } => { self.alloc_stack(dest.id); self.makes_call = true; - let fid = &self.program.fn_map[&f.id]; + let fid = &self.program.fn_var.fun(f.id).expect("a"); let sym = self.builder.func(fid); let ret_size = self .data diff --git a/src/ir/upper/kind.rs b/src/ir/upper/kind.rs index d62dcd7..ab10c41 100644 --- a/src/ir/upper/kind.rs +++ b/src/ir/upper/kind.rs @@ -1,15 +1,13 @@ +use super::{Type, UInstrInst, UInstruction, UProgram}; use crate::{ common::FileSpan, ir::{Len, Named, ID}, }; - -use super::{Type, UInstrInst, UInstruction, UProgram}; use std::{collections::HashMap, fmt::Debug}; pub struct UFunc { pub args: Vec, pub ret: Type, - pub origin: Origin, pub instructions: Vec, } @@ -22,7 +20,6 @@ pub struct StructField { pub struct UStruct { pub fields: HashMap, pub generics: Vec, - pub origin: Origin, } #[derive(Clone)] @@ -32,7 +29,6 @@ pub struct UGeneric {} pub struct UVar { pub parent: Option, pub ty: Type, - pub origin: Origin, } #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] @@ -50,7 +46,6 @@ pub struct FieldRef { #[derive(Clone)] pub struct UData { pub ty: Type, - pub origin: Origin, pub content: Vec, } @@ -101,7 +96,14 @@ impl<'a> Iterator for InstrIter<'a> { } macro_rules! impl_kind { + // TRUST THIS IS SANE!!! KEEP THE CODE DRY AND SAFE!!!!!! ($struc:ty, $idx:expr, $field:ident, $name:expr) => { + impl_kind!($struc, $idx, $field, $name, nofin); + impl Finish for $struc { + fn finish(_: &mut UProgram, _: ID) {} + } + }; + ($struc:ty, $idx:expr, $field:ident, $name:expr, nofin) => { impl Kind for $struc { const INDEX: usize = $idx; fn from_program_mut(program: &mut UProgram) -> &mut Vec> { @@ -117,7 +119,7 @@ macro_rules! impl_kind { }; } -impl_kind!(UFunc, 0, fns, "func"); +impl_kind!(UFunc, 0, fns, "func", nofin); impl_kind!(UVar, 1, vars, "var"); impl_kind!(UStruct, 2, structs, "struct"); impl_kind!(UGeneric, 3, types, "type"); @@ -130,12 +132,26 @@ pub type StructID = ID; pub type DataID = ID; pub type GenericID = ID; -pub trait Kind { - const INDEX: usize; - fn from_program_mut(program: &mut UProgram) -> &mut Vec> - where - Self: Sized; - fn from_program(program: &UProgram) -> &Vec> - where - Self: Sized; +impl Finish for UFunc { + fn finish(p: &mut UProgram, id: ID) { + let var = p.def_searchable( + p.names.name(id).to_string(), + Some(UVar { + parent: None, + ty: Type::Placeholder, + }), + p.origins.get(id), + ); + p.fn_var.insert(id, var); + } +} + +pub trait Kind: Sized { + const INDEX: usize; + fn from_program_mut(program: &mut UProgram) -> &mut Vec>; + fn from_program(program: &UProgram) -> &Vec>; +} + +pub trait Finish: Sized { + fn finish(program: &mut UProgram, id: ID); } diff --git a/src/ir/upper/maps.rs b/src/ir/upper/maps.rs new file mode 100644 index 0000000..22a407a --- /dev/null +++ b/src/ir/upper/maps.rs @@ -0,0 +1,109 @@ +use super::{FnID, Kind, Origin, VarID, NAMED_KINDS}; +use crate::ir::ID; +use std::collections::HashMap; + +pub struct OriginMap { + origins: [Vec; NAMED_KINDS], +} + +impl OriginMap { + pub fn new() -> Self { + Self { + origins: core::array::from_fn(|_| Vec::new()), + } + } + pub fn get(&self, id: ID) -> Origin { + self.origins[K::INDEX][id.0] + } + pub fn push(&mut self, origin: Origin) { + self.origins[K::INDEX].push(origin); + } +} + +pub struct NameMap { + names: [Vec; NAMED_KINDS], + inv_names: [HashMap; NAMED_KINDS], +} + +impl NameMap { + pub fn new() -> Self { + Self { + names: core::array::from_fn(|_| Vec::new()), + inv_names: core::array::from_fn(|_| HashMap::new()), + } + } + pub fn name(&self, id: ID) -> &str { + &self.names[K::INDEX][id.0] + } + pub fn id(&self, name: &str) -> Option> { + Some(ID::new(*self.inv_names[K::INDEX].get(name)?)) + } + pub fn push(&mut self, name: String) { + self.inv_names[K::INDEX].insert(name.clone(), self.names[K::INDEX].len()); + self.names[K::INDEX].push(name); + } +} + +pub struct FnVarMap { + vtf: HashMap, + ftv: Vec, +} + +impl FnVarMap { + pub fn new() -> Self { + Self { + vtf: HashMap::new(), + ftv: Vec::new(), + } + } + pub fn insert(&mut self, f: FnID, v: VarID) { + self.vtf.insert(v, f); + self.ftv.push(v); + } + pub fn var(&self, f: FnID) -> VarID { + self.ftv[f.0] + } + pub fn fun(&self, v: VarID) -> Option { + self.vtf.get(&v).copied() + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Ident { + id: usize, + kind: usize, +} + +impl From> for Ident { + fn from(id: ID) -> Self { + Self { + id: id.0, + kind: K::INDEX, + } + } +} + +// this isn't really a map... but also keeps track of "side data" +#[derive(Debug, Clone, Copy)] +pub struct Idents { + pub latest: Ident, + pub kinds: [Option; NAMED_KINDS], +} + +impl Idents { + pub fn new(latest: Ident) -> Self { + let mut s = Self { + latest, + kinds: [None; NAMED_KINDS], + }; + s.insert(latest); + s + } + pub fn insert(&mut self, i: Ident) { + self.latest = i; + self.kinds[i.kind] = Some(i.id); + } + pub fn get(&self) -> Option> { + self.kinds[K::INDEX].map(|i| i.into()) + } +} diff --git a/src/ir/upper/mod.rs b/src/ir/upper/mod.rs index 3ca1b7d..5bed81a 100644 --- a/src/ir/upper/mod.rs +++ b/src/ir/upper/mod.rs @@ -5,8 +5,11 @@ mod program; mod validate; mod error; mod inst; +mod maps; use super::*; +use maps::*; +pub use maps::Idents; pub use kind::*; pub use instr::*; pub use ty::*; diff --git a/src/ir/upper/program.rs b/src/ir/upper/program.rs index 73420a0..a14a46f 100644 --- a/src/ir/upper/program.rs +++ b/src/ir/upper/program.rs @@ -1,6 +1,5 @@ -use std::{collections::HashMap, fmt::Debug}; - -use super::{inst::VarInst, *}; +use super::*; +use std::collections::HashMap; pub struct UProgram { pub fns: Vec>, @@ -8,39 +7,14 @@ pub struct UProgram { pub structs: Vec>, pub types: Vec>, pub data: Vec>, - pub start: Option, pub names: NameMap, + pub origins: OriginMap, // todo: these feel weird raw - pub fn_map: HashMap, - pub inv_fn_map: Vec, + pub fn_var: FnVarMap, pub temp: usize, pub name_stack: Vec>, } -pub struct NameMap { - names: [Vec; NAMED_KINDS], - inv_names: [HashMap; NAMED_KINDS], -} - -impl NameMap { - pub fn new() -> Self { - Self { - names: core::array::from_fn(|_| Vec::new()), - inv_names: core::array::from_fn(|_| HashMap::new()), - } - } - pub fn get(&self, id: ID) -> &str { - &self.names[K::INDEX][id.0] - } - pub fn lookup(&self, name: &str) -> Option> { - Some(ID::new(*self.inv_names[K::INDEX].get(name)?)) - } - pub fn push(&mut self, name: String) { - self.inv_names[K::INDEX].insert(name.clone(), self.names[K::INDEX].len()); - self.names[K::INDEX].push(name); - } -} - impl UProgram { pub fn new() -> Self { Self { @@ -49,10 +23,9 @@ impl UProgram { structs: Vec::new(), types: Vec::new(), data: Vec::new(), - start: None, names: NameMap::new(), - fn_map: HashMap::new(), - inv_fn_map: Vec::new(), + origins: OriginMap::new(), + fn_var: FnVarMap::new(), temp: 0, name_stack: vec![HashMap::new()], } @@ -87,7 +60,7 @@ impl UProgram { .unwrap_or_else(|| panic!("{id:?} not defined yet!")) } pub fn get_fn_var(&self, id: VarID) -> Option<&UFunc> { - self.fns[self.fn_map.get(&id)?.0].as_ref() + self.fns[self.fn_var.fun(id)?.0].as_ref() } pub fn temp_subvar(&mut self, origin: Origin, ty: Type, parent: FieldRef) -> VarInst { self.temp_var_inner(origin, ty, Some(parent)) @@ -99,7 +72,8 @@ impl UProgram { fn temp_var_inner(&mut self, origin: Origin, ty: Type, parent: Option) -> VarInst { let v = self.def( format!("temp{}", self.temp), - Some(UVar { parent, origin, ty }), + Some(UVar { parent, ty }), + origin, ); self.temp += 1; VarInst { @@ -112,16 +86,23 @@ impl UProgram { K::from_program_mut(self)[id.0] = Some(k); } - pub fn def(&mut self, name: String, k: Option) -> ID { + pub fn def(&mut self, name: String, k: Option, origin: Origin) -> ID { self.names.push::(name); + self.origins.push::(origin); let vec = K::from_program_mut(self); let id = ID::new(vec.len()); vec.push(k); + K::finish(self, id); id } - pub fn def_searchable(&mut self, name: String, k: Option) -> ID { - let id = self.def(name.clone(), k); + pub fn def_searchable( + &mut self, + name: String, + k: Option, + origin: Origin, + ) -> ID { + let id = self.def(name.clone(), k, origin); self.name_on_stack(id, name); id } @@ -135,7 +116,7 @@ impl UProgram { if let Type::Generic { id } = field.ty { for (i, g) in struc.generics.iter().enumerate() { if *g == id { - return Some(&args[i]) + return Some(&args[i]); } } } @@ -146,7 +127,7 @@ impl UProgram { let mut str = String::new(); match ty { Type::Struct { id: base, args } => { - str += self.names.get(*base); + str += self.names.name(*base); if let Some(arg) = args.first() { str = str + "<" + &self.type_name(arg); } @@ -173,7 +154,7 @@ impl UProgram { } Type::Error => str += "{error}", Type::Infer => str += "{inferred}", - Type::Generic { id } => str += self.names.get(*id), + Type::Generic { id } => str += self.names.name(*id), Type::Bits(size) => str += &format!("b{}", size), Type::Array(t, len) => str += &format!("[{}; {len}]", self.type_name(t)), Type::Unit => str += "()", @@ -206,42 +187,3 @@ impl UProgram { .map(|(i, x)| (ID::new(i), x)) } } - -#[derive(Debug, Clone, Copy)] -pub struct Ident { - id: usize, - kind: usize, -} - -impl From> for Ident { - fn from(id: ID) -> Self { - Self { - id: id.0, - kind: K::INDEX, - } - } -} - -#[derive(Debug, Clone, Copy)] -pub struct Idents { - pub latest: Ident, - pub kinds: [Option; NAMED_KINDS], -} - -impl Idents { - fn new(latest: Ident) -> Self { - let mut s = Self { - latest, - kinds: [None; NAMED_KINDS], - }; - s.insert(latest); - s - } - fn insert(&mut self, i: Ident) { - self.latest = i; - self.kinds[i.kind] = Some(i.id); - } - pub fn get(&self) -> Option> { - self.kinds[K::INDEX].map(|i| i.into()) - } -} diff --git a/src/ir/upper/validate.rs b/src/ir/upper/validate.rs index a4c2994..c4ff695 100644 --- a/src/ir/upper/validate.rs +++ b/src/ir/upper/validate.rs @@ -5,36 +5,43 @@ use crate::common::{CompilerMsg, CompilerOutput, FileSpan}; impl UProgram { pub fn validate(&self) -> CompilerOutput { let mut output = CompilerOutput::new(); - for f in self.fns.iter().flatten() { - self.validate_fn(&f.instructions, f.origin, &f.ret, &mut output, true, false); + for (id, f) in self.iter_fns() { + self.validate_fn( + &f.instructions, + self.origins.get(id), + &f.ret, + &mut output, + true, + false, + ); } for (id, var) in self.iter_vars() { if var.ty == Type::Error { output.err(CompilerMsg { msg: format!("Var {:?} is error type!", id), - spans: vec![var.origin], + spans: vec![self.origins.get(id)], }); } if var.ty == Type::Infer { output.err(CompilerMsg { msg: format!("Var {:?} cannot be inferred", id), - spans: vec![var.origin], + spans: vec![self.origins.get(id)], }); } if var.ty == Type::Placeholder { output.err(CompilerMsg { msg: format!("Var {:?} still placeholder!", id), - spans: vec![var.origin], + spans: vec![self.origins.get(id)], }); } if let Some(parent) = &var.parent { let pty = &self.get(parent.var).unwrap().ty; if let Some(ft) = self.field_type(pty, &parent.field) { - output.check_assign(self, &var.ty, ft, var.origin); + output.check_assign(self, &var.ty, ft, self.origins.get(id)); } else { output.err(CompilerMsg { msg: format!("invalid parent!"), - spans: vec![var.origin], + spans: vec![self.origins.get(id)], }); } } diff --git a/src/parser/v3/lower/def.rs b/src/parser/v3/lower/def.rs index 3d68735..c1af82b 100644 --- a/src/parser/v3/lower/def.rs +++ b/src/parser/v3/lower/def.rs @@ -15,14 +15,7 @@ impl Node { None => Type::Infer, }; Some(VarInst { - id: program.def_searchable( - name, - Some(UVar { - ty, - parent: None, - origin: self.span, - }), - ), + id: program.def_searchable(name, Some(UVar { ty, parent: None }), self.span), span: self.span, }) } diff --git a/src/parser/v3/lower/expr.rs b/src/parser/v3/lower/expr.rs index e7f6ab5..a083fa2 100644 --- a/src/parser/v3/lower/expr.rs +++ b/src/parser/v3/lower/expr.rs @@ -16,9 +16,9 @@ impl FnLowerable for PExpr { format!("string \"{}\"", s.replace("\n", "\\n")), Some(UData { ty: Type::Bits(8).arr(data.len() as u32), - origin: l.span, content: data, }), + l.span, ); ctx.push(UInstruction::LoadSlice { dest, src }); dest @@ -30,9 +30,9 @@ impl FnLowerable for PExpr { format!("char '{c}'"), Some(UData { ty, - origin: l.span, content: c.to_string().as_bytes().to_vec(), }), + l.span, ); ctx.push(UInstruction::LoadData { dest, src }); dest @@ -45,9 +45,9 @@ impl FnLowerable for PExpr { format!("num {n:?}"), Some(UData { ty, - origin: l.span, content: n.whole.parse::().unwrap().to_le_bytes().to_vec(), }), + l.span ); ctx.push(UInstruction::LoadData { dest, src }); dest diff --git a/src/parser/v3/lower/func.rs b/src/parser/v3/lower/func.rs index 4d72d57..4018644 100644 --- a/src/parser/v3/lower/func.rs +++ b/src/parser/v3/lower/func.rs @@ -1,9 +1,6 @@ use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Node, PFunction}; use crate::{ - ir::{ - FieldRef, FnID, Idents, InstrIter, Type, UFunc, UInstrInst, UInstruction, UProgram, UVar, - VarInst, - }, + ir::{FieldRef, FnID, Idents, Type, UFunc, UInstrInst, UInstruction, UProgram, UVar, VarInst}, parser, }; @@ -22,17 +19,7 @@ impl PFunction { pub fn lower_name(&self, p: &mut UProgram) -> Option { let header = self.header.as_ref()?; let name = header.name.as_ref()?; - let id = p.def_searchable(name.to_string(), None); - let var = p.def_searchable( - name.to_string(), - Some(UVar { - parent: None, - ty: Type::Placeholder, - origin: self.header.span, - }), - ); - p.fn_map.insert(var, id); - p.inv_fn_map.push(var); + let id = p.def_searchable(name.to_string(), None, self.header.span); Some(id) } pub fn lower(&self, id: FnID, p: &mut UProgram, output: &mut CompilerOutput) { @@ -63,15 +50,13 @@ impl PFunction { span: src.span, }); } - let origin = self.header.span; let instructions = ctx.instructions; let f = UFunc { - origin, args, ret, instructions, }; - p.expect_mut(p.inv_fn_map[id.0]).ty = f.ty(p); + p.expect_mut(p.fn_var.var(id)).ty = f.ty(p); p.write(id, f) } } diff --git a/src/parser/v3/lower/struc.rs b/src/parser/v3/lower/struc.rs index b52bfef..420f8bc 100644 --- a/src/parser/v3/lower/struc.rs +++ b/src/parser/v3/lower/struc.rs @@ -49,7 +49,7 @@ impl PStruct { let generics = self .generics .iter() - .flat_map(|a| a.as_ref()?.lower(p)) + .flat_map(|a| a.lower(p)) .collect(); let fields = match &self.fields { PStructFields::Named(nodes) => nodes @@ -75,14 +75,7 @@ impl PStruct { .into_iter() .map(|(name, ty)| (name, StructField { ty })) .collect(); - p.write( - id, - UStruct { - origin: span, - generics, - fields, - }, - ); + p.write(id, UStruct { generics, fields }); p.pop(); Some(()) } @@ -90,8 +83,9 @@ impl PStruct { impl Node { pub fn lower_name(&self, p: &mut UProgram) -> Option { - let name = self.as_ref()?.name.as_ref()?.to_string(); - let id = p.def_searchable(name.to_string(), None); + let s = self.as_ref()?; + let name = s.name.as_ref()?.to_string(); + let id = p.def_searchable(name.to_string(), None, s.name.span); Some(id) } pub fn lower(&self, id: StructID, p: &mut UProgram, output: &mut CompilerOutput) { diff --git a/src/parser/v3/lower/ty.rs b/src/parser/v3/lower/ty.rs index 0242531..bb38c9b 100644 --- a/src/parser/v3/lower/ty.rs +++ b/src/parser/v3/lower/ty.rs @@ -43,11 +43,10 @@ impl PType { } } -impl PGenericDef { +impl Node { pub fn lower(&self, p: &mut UProgram) -> Option { - let Some(name) = self.name.as_ref() else { - return None; - }; - Some(p.def_searchable(name.to_string(), Some(UGeneric {}))) + let s = self.as_ref()?; + let name = s.name.as_ref()?; + Some(p.def_searchable(name.to_string(), Some(UGeneric {}), self.span)) } }