diff --git a/src/ir/lower/program.rs b/src/ir/lower/program.rs index b0e3b76..b9a73c2 100644 --- a/src/ir/lower/program.rs +++ b/src/ir/lower/program.rs @@ -1,6 +1,8 @@ use std::collections::HashMap; -use crate::ir::{AsmBlockArgType, Size, StructTy, SymbolSpace, Type, UFunc, UInstrInst, VarOffset}; +use crate::ir::{ + AsmBlockArgType, FnID, Size, GenericTy, SymbolSpace, Type, UFunc, UInstrInst, VarOffset, +}; use super::{ IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, UInstruction, UProgram, VarID, @@ -14,15 +16,11 @@ pub struct LProgram { // NOTE: there are THREE places here where I specify size (8) impl LProgram { - pub fn create(p: &UProgram) -> Result { - let start = p - .names - .id::(&[], "crate") - .ok_or("no start method found")?; + pub fn create(p: &UProgram, start: FnID) -> Result { let mut ssbuilder = SymbolSpaceBuilder::with_entries(&[start]); let entry = ssbuilder.func(&start); while let Some((sym, i)) = ssbuilder.pop_fn() { - let f = p.fns[i.0].as_ref().unwrap(); + let f = &p.fns[i]; let mut fbuilder = LFunctionBuilder::new(p, &mut ssbuilder); for i in &f.instructions { fbuilder.insert_instr(i); @@ -31,7 +29,7 @@ impl LProgram { fbuilder.instrs.push(LInstruction::Ret { src: None }); } let res = fbuilder.finish(f); - ssbuilder.write_fn(sym, res, Some(p.names.path(i).to_string())); + ssbuilder.write_fn(sym, res, Some(f.name.clone())); } let sym_space = ssbuilder.finish().expect("we failed the mission"); Ok(Self { sym_space, entry }) @@ -376,7 +374,7 @@ impl LFunctionBuilderData<'_> { pub fn addr_size(&self) -> Size { 64 } - pub fn struct_inst(&mut self, p: &UProgram, ty: &StructTy) -> &StructInst { + pub fn struct_inst(&mut self, p: &UProgram, ty: &GenericTy) -> &StructInst { // normally I'd let Some(..) here and return, but polonius does not exist :grief: if self.struct_insts.get(ty).is_none() { let StructInst { id, args } = ty; diff --git a/src/ir/upper/error.rs b/src/ir/upper/error.rs deleted file mode 100644 index fb4be1e..0000000 --- a/src/ir/upper/error.rs +++ /dev/null @@ -1,22 +0,0 @@ -use crate::common::{CompilerMsg, CompilerOutput, FileSpan}; - -use super::{UProgram, Type}; - -impl CompilerOutput { - pub fn check_assign(&mut self, p: &UProgram, src: &Type, dest: &Type, span: FileSpan) { - // TODO: spans - if src != dest { - if !src.is_resolved() || !dest.is_resolved() { - return; - } - self.err(CompilerMsg { - msg: format!( - "Cannot assign type '{}' to '{}'", - p.type_name(src), - p.type_name(dest) - ), - spans: vec![span], - }); - } - } -} diff --git a/src/ir/upper/inst.rs b/src/ir/upper/inst.rs index 147a10d..cc977a8 100644 --- a/src/ir/upper/inst.rs +++ b/src/ir/upper/inst.rs @@ -1,26 +1,33 @@ use crate::ir::VarID; use std::fmt::Debug; -use super::{Origin, UInstruction}; +use super::{MemberID, ModPath, Origin, UInstruction}; -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct VarInst { - pub id: VarID, + pub status: VarStatus, pub origin: Origin, } +#[derive(Clone)] +pub enum VarStatus { + Res(VarID), + Unres { mid: ModPath, fields: Vec }, + Partial { v: VarID, fields: Vec }, +} + +#[derive(Clone)] +pub struct VarParent { + id: VarID, + path: Vec, +} + #[derive(Clone)] pub struct UInstrInst { pub i: UInstruction, pub origin: Origin, } -impl Debug for VarInst { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self.id) - } -} - impl Debug for UInstrInst { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", self.i) diff --git a/src/ir/upper/instr.rs b/src/ir/upper/instr.rs index f369996..6546a07 100644 --- a/src/ir/upper/instr.rs +++ b/src/ir/upper/instr.rs @@ -73,7 +73,8 @@ impl std::fmt::Debug for UInstruction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Mv { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?, - Self::Ref { dst: dest, src } => write!(f, "{dest:?} <- &{src:?}")?, + Self::Ref { dst: dest, src } => write!(f, "{dest:?} <- {src:?}&")?, + Self::Deref { dst: dest, src } => write!(f, "{dest:?} <- {src:?}^")?, Self::LoadData { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?, Self::LoadFn { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?, Self::LoadSlice { dst: dest, src } => write!(f, "{dest:?} <- &[{src:?}]")?, diff --git a/src/ir/upper/kind.rs b/src/ir/upper/kind.rs index 8197a52..b4748a6 100644 --- a/src/ir/upper/kind.rs +++ b/src/ir/upper/kind.rs @@ -1,4 +1,4 @@ -use super::{Type, UInstrInst, UInstruction, UProgram}; +use super::{Type, UInstrInst, UInstruction}; use crate::{ common::FileSpan, ir::{Len, ID}, @@ -12,7 +12,7 @@ pub struct UFunc { pub name: String, pub origin: Origin, pub args: Vec, - pub argtys: Vec, + pub gargs: Vec, pub ret: TypeID, pub instructions: Vec, } @@ -41,13 +41,8 @@ pub struct UVar { pub name: String, pub origin: Origin, pub ty: TypeID, - pub res: UVarTy, -} - -#[derive(Clone)] -pub struct VarParent { - id: VarID, - path: Vec, + pub parent: Option, + pub children: Vec, } #[derive(Clone, PartialEq, Eq, Hash)] @@ -62,25 +57,6 @@ pub struct ModPath { pub path: Vec, } -#[derive(Clone)] -pub enum UVarTy { - Ptr(VarID), - /// fully resolved & typed - Res { - parent: Option, - }, - /// module doesn't exist yet - Unres { - path: ModPath, - fields: Vec, - }, - /// parent var exists but not typed enough for this field path - Partial { - v: VarID, - fields: Vec, - }, -} - #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] pub struct VarOffset { pub id: VarID, @@ -117,12 +93,6 @@ pub enum Member { pub type Origin = FileSpan; impl UFunc { - pub fn ty(&self, program: &UProgram) -> Type { - Type::Fn { - args: self.argtys.clone(), - ret: Box::new(self.ret.clone()), - } - } pub fn flat_iter(&self) -> impl Iterator { InstrIter::new(self.instructions.iter()) } diff --git a/src/ir/upper/mod.rs b/src/ir/upper/mod.rs index f407590..34277d0 100644 --- a/src/ir/upper/mod.rs +++ b/src/ir/upper/mod.rs @@ -1,5 +1,4 @@ mod assoc; -mod error; mod inst; mod instr; mod kind; @@ -11,7 +10,6 @@ mod resolve; use super::*; use assoc::*; -pub use assoc::Idents; pub use inst::*; pub use instr::*; pub use kind::*; diff --git a/src/ir/upper/program.rs b/src/ir/upper/program.rs index bd7cbe1..feafad3 100644 --- a/src/ir/upper/program.rs +++ b/src/ir/upper/program.rs @@ -12,6 +12,11 @@ pub struct UProgram { pub generics: Vec, pub vars: Vec, pub types: Vec, + + pub unres_vars: Vec, + pub unres_tys: Vec, + pub unit: TypeID, + pub error: TypeID, } pub struct UModuleBuilder<'a> { @@ -22,6 +27,9 @@ pub struct UModuleBuilder<'a> { impl UProgram { pub fn new() -> Self { + let mut types = Vec::new(); + let unit = Self::push_id(&mut types, Type::Unit); + let error = Self::push_id(&mut types, Type::Error); Self { fns: Vec::new(), vars: Vec::new(), @@ -30,24 +38,36 @@ impl UProgram { generics: Vec::new(), data: Vec::new(), modules: Vec::new(), + unres_vars: Vec::new(), + unres_tys: Vec::new(), + error, + unit, } } - pub fn instantiate_type(&mut self, ty: Type) { - self.def_ty(match ty { - Type::Ref(node) => Type::Ref(node.lower()), - Type::Generic(node, nodes) => todo!(), - Type::Ident(node) => todo!(), - }); + pub fn inst_type(&mut self, ty: TypeID, gs: Vec) -> TypeID { + let ty = match &self.types[ty] { + Type::Ref(id) => Type::Ref(self.inst_type(*id, gs)), + Type::Generic(id) => return gs[id.0], + Type::Bits(b) => Type::Bits(*b), + Type::Struct(struct_ty) => Type::Struct(struct_ty.clone()), + Type::Fn() => todo!(), + Type::Deref(id) => todo!(), + Type::Slice(id) => todo!(), + Type::Array(id, _) => todo!(), + Type::Unit => todo!(), + Type::Unres(mod_path) => todo!(), + Type::Infer => todo!(), + Type::Error => todo!(), + }; + self.def_ty(ty) } pub fn infer(&mut self) -> TypeID { self.def_ty(Type::Infer) } - pub fn error(&mut self) -> TypeID { - self.def_ty(Type::Error) - } + pub fn set_type(id: TypeID, ty: Type) {} pub fn def_var(&mut self, v: UVar) -> VarID { Self::push_id(&mut self.vars, v) diff --git a/src/ir/upper/resolve.rs b/src/ir/upper/resolve.rs index 7054b96..101841e 100644 --- a/src/ir/upper/resolve.rs +++ b/src/ir/upper/resolve.rs @@ -1,4 +1,4 @@ -use super::{Origin, StructTy, Type, TypeID, TypeIDed, UInstruction, UProgram, UStruct, UVar}; +use super::{Origin, GenericTy, Type, TypeID, TypeIDed, UInstruction, UProgram, UStruct, UVar}; use crate::common::{CompilerMsg, CompilerOutput}; use std::{collections::HashMap, ops::BitOrAssign}; @@ -65,10 +65,6 @@ impl UProgram { format!("Type of {:?} cannot be inferred", var.name), var.origin, )), - Type::Placeholder => output.err(CompilerMsg::new( - format!("Var {:?} still placeholder!", var.name), - var.origin, - )), Type::Unres(_) => output.err(CompilerMsg::new( format!("Var {:?} type still unresolved!", var.name), var.origin, @@ -91,11 +87,12 @@ pub fn resolve_instr(data: &mut ResData, i: &UInstruction) -> InstrRes { let mut uf = InstrRes::Finished; match &i { UInstruction::Call { dst, f, args } => { - let fty = data.vars[f.id].ty; - let Type::Fn { args: fargs, ret } = &data.types[fty] else { + let ftyid = data.vars[f.id].ty; + let fty = &data.types[ftyid]; + let Type::Fn { args: fargs, ret } = fty else { data.errs.push(ResErr::NotCallable { origin: f.origin, - ty: fty, + ty: ftyid, }); return InstrRes::Finished; }; @@ -131,7 +128,7 @@ pub fn resolve_instr(data: &mut ResData, i: &UInstruction) -> InstrRes { let dest_ty = get(vars, dst.id)?; let Type::Struct(sty) = dest_ty else {}; let id = sty.id; - let Some(struc) = self.get(id) else {}; + let Some(struc) = get(id) else {}; let mut new = HashMap::new(); for (name, field) in &struc.fields { let Some(src) = fields.get(name) else { @@ -155,7 +152,7 @@ pub fn resolve_instr(data: &mut ResData, i: &UInstruction) -> InstrRes { args[i] = ty; } } - set(vars, dst.id, Type::Struct(StructTy { id, args })); + set(vars, dst.id, Type::Struct(GenericTy { id, args })); } UInstruction::If { cond, body } => { for i in body { diff --git a/src/ir/upper/ty.rs b/src/ir/upper/ty.rs index 771b680..0b7c288 100644 --- a/src/ir/upper/ty.rs +++ b/src/ir/upper/ty.rs @@ -1,4 +1,5 @@ -use super::{FnID, GenericID, Len, ModPath, StructID, TypeID, UVar, VarID, VarInst}; +use super::{GenericID, Len, ModPath, TypeID, UFunc, UProgram, UStruct, UVar, VarID, VarInst}; +use crate::ir::ID; #[derive(Debug, Clone, Hash, Eq, PartialEq)] pub struct FieldRef { @@ -7,16 +8,16 @@ pub struct FieldRef { } #[derive(Clone, Eq, PartialEq, Hash)] -pub struct StructTy { - pub id: StructID, +pub struct GenericTy { + pub id: ID, pub args: Vec, } #[derive(Clone)] pub enum Type { Bits(u32), - Struct(StructTy), - Fn(FnID), + Struct(GenericTy), + Fn(GenericTy), Ref(TypeID), Deref(TypeID), Slice(TypeID), @@ -27,7 +28,21 @@ pub enum Type { Generic(GenericID), Infer, Error, - Placeholder, +} + +impl Type { + pub fn rf(self, p: &mut UProgram) -> Self { + p.def_ty(self).rf() + } + pub fn derf(self, p: &mut UProgram) -> Self { + p.def_ty(self).derf() + } + pub fn arr(self, p: &mut UProgram, len: Len) -> Self { + p.def_ty(self).arr(len) + } + pub fn slice(self, p: &mut UProgram) -> Self { + p.def_ty(self).slice() + } } impl TypeID { @@ -46,9 +61,6 @@ impl TypeID { } impl Type { - pub fn is_resolved(&self) -> bool { - !matches!(self, Self::Error | Self::Placeholder | Self::Infer) - } pub fn bx(self) -> Box { Box::new(self) } diff --git a/src/parser/v3/lower/arch/riscv64.rs b/src/parser/v3/lower/arch/riscv64.rs index 1a34796..1390164 100644 --- a/src/parser/v3/lower/arch/riscv64.rs +++ b/src/parser/v3/lower/arch/riscv64.rs @@ -174,7 +174,7 @@ pub fn arg_to_var(node: &Node, ctx: &mut FnLowerCtx) -> Option ); return None; }; - ctx.get_var(node) + ctx.var(node) } impl RegRef { @@ -184,7 +184,7 @@ impl RegRef { let reg = Reg::from_ident(node, ctx)?; Self::Reg(reg) } - PAsmArg::Ref(node) => Self::Var(ctx.get_var(node)?), + PAsmArg::Ref(node) => Self::Var(ctx.var(node)?), }) } } diff --git a/src/parser/v3/lower/def.rs b/src/parser/v3/lower/def.rs index bcb8f23..9be5731 100644 --- a/src/parser/v3/lower/def.rs +++ b/src/parser/v3/lower/def.rs @@ -1,9 +1,9 @@ -use crate::ir::{UProgram, UVar, VarInst}; +use crate::ir::{UProgram, UVar, VarID, VarInst}; use super::{CompilerOutput, Node, PVarDef}; impl Node { - pub fn lower(&self, program: &mut UProgram, output: &mut CompilerOutput) -> Option { + pub fn lower(&self, program: &mut UProgram, output: &mut CompilerOutput) -> Option { let s = self.as_ref()?; let name = s.name.as_ref().map_or("{error}", |v| v); let ty = match &s.ty { diff --git a/src/parser/v3/lower/expr.rs b/src/parser/v3/lower/expr.rs index aef350a..5e6f928 100644 --- a/src/parser/v3/lower/expr.rs +++ b/src/parser/v3/lower/expr.rs @@ -20,11 +20,11 @@ impl FnLowerable for PExpr { Some(match e { PExpr::Lit(l) => match l { super::PLiteral::String(s) => { - let dest = ctx.b.temp_var(ctx.origin, Type::Bits(8).slice()); + let dest = ctx.b.temp_var(ctx.origin, Type::Bits(8).slice(ctx.b.p)); let data = s.as_bytes().to_vec(); let src = ctx.b.def_data(UData { name: format!("string \"{}\"", s.replace("\n", "\\n")), - ty: Type::Bits(8).arr(data.len() as u32), + ty: Type::Bits(8).arr(ctx.b.p, data.len() as u32), content: data, }); ctx.push(UInstruction::LoadSlice { dst: dest, src }); @@ -55,7 +55,7 @@ impl FnLowerable for PExpr { } super::PLiteral::Unit => ctx.b.temp_var(ctx.origin, Type::Unit), }, - PExpr::Ident(i) => ctx.get_var(i), + PExpr::Ident(i) => ctx.var(i), PExpr::BinaryOp(op, e1, e2) => match op { InfixOp::Add => todo!(), InfixOp::Sub => todo!(), @@ -77,13 +77,13 @@ impl FnLowerable for PExpr { let res = e.lower(ctx)?; match op { PostfixOp::Ref => { - let ty = ctx.b.vars[res.id].ty.rf(); + let ty = Type::Ref(ctx.b.infer()); let dest = ctx.temp(ty); ctx.push(UInstruction::Ref { dst: dest, src: res }); dest } PostfixOp::Deref => { - let ty = ctx.b.vars[res.id].ty.derf(); + let ty = Type::Deref(ctx.b.infer()); let dest = ctx.temp(ty); ctx.push(UInstruction::Deref { dst: dest, src: res }); dest @@ -100,9 +100,9 @@ impl FnLowerable for PExpr { let arg = arg.lower(ctx)?; nargs.push(arg); } - let dest = ctx.temp(Type::Placeholder); + let dest = ctx.temp(Type::Infer); ctx.push(UInstruction::Call { - dst: dest, + dst: VarInst { status: , origin: () }, f: fe, args: nargs, }); diff --git a/src/parser/v3/lower/func.rs b/src/parser/v3/lower/func.rs index cedc690..d4e1bc5 100644 --- a/src/parser/v3/lower/func.rs +++ b/src/parser/v3/lower/func.rs @@ -3,120 +3,111 @@ use std::collections::HashMap; use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, PFunction}; use crate::{ ir::{ - FnID, Idents, Typable, Type, UFunc, UInstrInst, UInstruction, UModuleBuilder, UProgram, - UVar, VarID, VarInst, + FnID, Origin, Typable, Type, UFunc, UInstrInst, UInstruction, UModuleBuilder, UVar, VarID, + VarInst, VarStatus, }, - parser, + parser, util::NameStack, }; impl Node { - pub fn lower_name(&self, p: &mut UProgram) -> Option { - self.as_ref()?.lower_name(p) - } pub fn lower( &self, - id: FnID, - p: &mut UProgram, + b: &mut UModuleBuilder, imports: &mut Imports, output: &mut CompilerOutput, - ) { - if let Some(s) = self.as_ref() { - s.lower(id, p, imports, output) - } + ) -> Option { + self.as_ref() + .map(|s| s.lower(b, imports, output, self.origin)) + .flatten() } } 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, None, self.header.origin); - Some(id) - } pub fn lower( &self, - id: FnID, - p: &mut UProgram, + b: &mut UModuleBuilder, imports: &mut Imports, output: &mut CompilerOutput, - ) { - let name = p.names.name(id).to_string(); - p.push_name(&name); - let (args, ret) = if let Some(header) = self.header.as_ref() { + origin: Origin, + ) -> Option { + let header = self.header.as_ref()?; + let name = header.name.as_ref()?.0.clone(); + let (generic_args, args, ret) = if let Some(header) = self.header.as_ref() { ( + header + .gargs + .iter() + .map(|a| Some(a.lower(b, output))) + .collect(), header .args .iter() - .flat_map(|a| Some(a.lower(p, output)?.id)) + .flat_map(|a| Some(a.lower(b, output)?)) .collect(), match &header.ret { - Some(ty) => ty.lower(p, output), - None => Type::Unit, + Some(ty) => ty.lower(b, output), + None => b.def_ty(Type::Unit), }, ) } else { - (Vec::new(), Type::Error) + (Vec::new(), Vec::new(), b.error) }; - let mut ctx = FnLowerCtx { - instructions: Vec::new(), - b: p, - output, - origin: self.body.origin, - imports, + let instructions = { + let mut var_stack = Vec::new(); + let mut ctx = FnLowerCtx { + instructions: Vec::new(), + var_stack: &mut var_stack, + b, + output, + origin: self.body.origin, + imports, + }; + if let Some(src) = self.body.lower(&mut ctx) { + ctx.instructions.push(UInstrInst { + origin: src.origin, + i: UInstruction::Ret { src }, + }); + } + ctx.instructions }; - if let Some(src) = self.body.lower(&mut ctx) { - ctx.instructions.push(UInstrInst { - i: UInstruction::Ret { src }, - origin: src.origin, - }); - } - let instructions = ctx.instructions; + let gargs = args.iter().map(|a| b.vars[a].ty).collect(); let f = UFunc { + origin, + gargs, + name, args, ret, instructions, }; - p.pop_name(); - p.write(id, f) + Some(b.def_fn(f)) } } -pub struct FnLowerCtx<'a> { - pub b: &'a mut UModuleBuilder<'a>, +pub struct FnLowerCtx<'a, 'b> { + pub b: &'a mut UModuleBuilder<'b>, pub instructions: Vec, pub output: &'a mut CompilerOutput, pub origin: FileSpan, pub imports: &'a mut Imports, - pub var_stack: Vec>, + pub var_stack: &'a mut NameStack, } -impl FnLowerCtx<'_> { - pub fn get_idents(&mut self, node: &Node) -> Option { - let name = node.inner.as_ref()?; - let res = self.b.get_idents(name); - if res.is_none() { - self.err_at(node.origin, format!("Identifier '{}' not found", name)); +impl<'a, 'b> FnLowerCtx<'a, 'b> { + pub fn var(&mut self, node: &Node) -> VarInst { + if let Some(n) = node.as_ref() { + if let Some(&var) = self.var_stack.search(&n.0) { + return VarInst { + status: VarStatus::Res(var), + origin: node.origin, + } + } } - res - } - pub fn get_var(&mut self, node: &Node) -> VarInst { - let ids = self.get_idents(node)?; - if ids.get::().is_none() { - self.err_at( - node.origin, - format!("Variable '{}' not found", node.inner.as_ref()?), - ); - } - ids.get::().map(|id| VarInst { - id, - origin: node.origin, - }) } pub fn err(&mut self, msg: String) { - self.output.err(CompilerMsg::new(self.origin, msg)) + self.output.err(CompilerMsg::new(msg, self.origin)) } pub fn err_at(&mut self, span: FileSpan, msg: String) { - self.output.err(CompilerMsg::new(span, msg)) + self.output.err(CompilerMsg::new(msg, span)) } pub fn temp(&mut self, ty: Type) -> VarInst { self.b.temp_var(self.origin, ty) @@ -125,27 +116,13 @@ impl FnLowerCtx<'_> { self.push_at(i, self.origin); } pub fn push_at(&mut self, i: UInstruction, span: FileSpan) { - match i { - UInstruction::Mv { dst: dest, src } => todo!(), - UInstruction::Ref { dst: dest, src } => todo!(), - UInstruction::LoadData { dst: dest, src } => todo!(), - UInstruction::LoadSlice { dst: dest, src } => todo!(), - UInstruction::LoadFn { dst: dest, src } => todo!(), - UInstruction::Call { dst: dest, f, args } => todo!(), - UInstruction::AsmBlock { instructions, args } => todo!(), - UInstruction::Ret { src } => todo!(), - UInstruction::Construct { dst: dest, fields } => todo!(), - UInstruction::If { cond, body } => todo!(), - UInstruction::Loop { body } => todo!(), - UInstruction::Break => todo!(), - UInstruction::Continue => todo!(), - } self.instructions.push(UInstrInst { i, origin: span }); } - pub fn branch<'a>(&'a mut self) -> FnLowerCtx<'a> { + pub fn branch(&'a mut self) -> FnLowerCtx<'a, 'b> { FnLowerCtx { b: self.b, instructions: Vec::new(), + var_stack: self.var_stack, output: self.output, origin: self.origin, imports: self.imports, diff --git a/src/parser/v3/lower/mod.rs b/src/parser/v3/lower/mod.rs index 8eca6c8..b7b4b23 100644 --- a/src/parser/v3/lower/mod.rs +++ b/src/parser/v3/lower/mod.rs @@ -8,13 +8,13 @@ mod struc; mod ty; use super::*; -use crate::ir::{Type, UFunc, UProgram}; +use crate::ir::{Type, UFunc, UModuleBuilder}; impl PModule { pub fn lower( &self, path: Vec, - p: &mut UProgram, + p: &mut UModuleBuilder, imports: &mut Imports, output: &mut CompilerOutput, ) { diff --git a/src/parser/v3/lower/ty.rs b/src/parser/v3/lower/ty.rs index d7d362f..4c330e8 100644 --- a/src/parser/v3/lower/ty.rs +++ b/src/parser/v3/lower/ty.rs @@ -9,14 +9,14 @@ impl Node> { pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID { self.as_ref() .map(|t| t.lower(p, output, self.origin)) - .unwrap_or(p.error()) + .unwrap_or(p.error) } } impl Node { pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID { self.as_ref() .map(|t| t.lower(p, output, self.origin)) - .unwrap_or(p.error()) + .unwrap_or(p.error) } } @@ -34,7 +34,7 @@ impl PType { while let PType::Member(node, ident) = ty { ty = if let Some(t) = node.as_ref() { let Some(name) = ident.as_ref() else { - return p.error(); + return p.error; }; origin = node.origin; path.push(MemberID { @@ -43,18 +43,19 @@ impl PType { }); &**t } else { - return p.error(); + return p.error; }; } if !path.is_empty() { let PType::Ident(id) = ty else { - return p.error(); + return p.error; }; path.push(MemberID { name: id.0.clone(), origin, }); - return p.def_ty(Type::Unres(ModPath { m: p.module, path })); + let ty = Type::Unres(ModPath { m: p.module, path }); + return p.def_ty(ty); } let ty = match ty { PType::Member(_, _) => unreachable!(), @@ -70,31 +71,6 @@ impl PType { PType::Generic(node, nodes) => todo!(), }; p.def_ty(ty) - // let Some(name) = self.name.as_ref() else { - // return p.error(); - // }; - // let ids = p.get_idents(name); - // // TODO: should generics always take precedence? - // if let Some(id) = ids.and_then(|ids| ids.get::()) { - // Type::Generic { id } - // } else if let Some(id) = ids.and_then(|ids| ids.get::()) { - // let args = self.args.iter().map(|n| n.lower(p, output)).collect(); - // Type::Struct(StructInst { id, args }) - // } else if let Ok(num) = name.parse::() { - // Type::Bits(num) - // } else { - // match name.as_str() { - // "slice" => { - // let inner = self.args[0].lower(p, output); - // Type::Slice(Box::new(inner)) - // } - // "_" => Type::Infer, - // _ => { - // output.err(CompilerMsg::from_span(span, "Type not found".to_string())); - // Type::Error - // } - // } - // } } } diff --git a/src/parser/v3/nodes/func.rs b/src/parser/v3/nodes/func.rs index a5e8985..3870edd 100644 --- a/src/parser/v3/nodes/func.rs +++ b/src/parser/v3/nodes/func.rs @@ -1,12 +1,13 @@ use super::{ - util::parse_list, PBlock, PIdent, Node, Parsable, ParseResult, ParserCtx, - Symbol, PType, PVarDef, + util::parse_list, Node, PBlock, PIdent, PType, PVarDef, Parsable, ParseResult, ParserCtx, + Symbol, }; use std::fmt::Debug; pub struct PFunctionHeader { pub name: Node, pub args: Vec>, + pub gargs: Vec>, pub ret: Option>, } @@ -18,6 +19,12 @@ pub struct PFunction { impl Parsable for PFunctionHeader { fn parse(ctx: &mut ParserCtx) -> ParseResult { let name = ctx.parse()?; + let generic_args = if ctx.expect_peek()?.is_symbol(Symbol::OpenAngle) { + ctx.next(); + parse_list(ctx, Symbol::CloseAngle)? + } else { + Vec::new() + }; ctx.expect_sym(Symbol::OpenParen)?; // let sel = ctx.maybe_parse(); // if sel.is_some() { @@ -39,6 +46,7 @@ impl Parsable for PFunctionHeader { ParseResult::Ok(Self { name, args, + gargs: generic_args, ret, }) } diff --git a/src/parser/v3/nodes/ty.rs b/src/parser/v3/nodes/ty.rs index 78a4f63..ab086c1 100644 --- a/src/parser/v3/nodes/ty.rs +++ b/src/parser/v3/nodes/ty.rs @@ -40,7 +40,7 @@ impl Parsable for PType { } break; } - ParseResult::Wrap(cur) + ParseResult::Node(cur) } } diff --git a/src/util/mod.rs b/src/util/mod.rs index 52ba79e..4e563a5 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,7 +1,9 @@ mod padder; mod bits; mod label; +mod name_stack; pub use padder::*; pub use bits::*; pub use label::*; +pub use name_stack::*; diff --git a/src/util/name_stack.rs b/src/util/name_stack.rs new file mode 100644 index 0000000..da44d8e --- /dev/null +++ b/src/util/name_stack.rs @@ -0,0 +1,17 @@ +use std::collections::HashMap; + +pub struct NameStack(Vec>); + +impl NameStack { + pub fn new() -> Self { + Self(Vec::new()) + } + pub fn search(&self, name: &str) -> Option<&T> { + for level in self.0.iter().rev() { + if let Some(v) = level.get(name) { + return Some(v); + } + } + None + } +}