diff --git a/src/ir/lower/program.rs b/src/ir/lower/program.rs index 1dba694..2035bf2 100644 --- a/src/ir/lower/program.rs +++ b/src/ir/lower/program.rs @@ -1,9 +1,9 @@ use std::collections::HashMap; -use crate::ir::{AsmBlockArgType, Size, StructTy, SymbolSpace, UFunc, UInstrInst, VarOffset}; +use crate::ir::{AsmBlockArgType, Size, StructTy, SymbolSpace, Type, UFunc, UInstrInst, VarOffset}; use super::{ - IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, Type, UInstruction, UProgram, VarID, + IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, UInstruction, UProgram, VarID, }; pub struct LProgram { @@ -17,7 +17,7 @@ impl LProgram { pub fn create(p: &UProgram) -> Result { let start = p .names - .id::(&["crate".to_string()]) + .id::(&[], "crate") .ok_or("no start method found")?; let mut ssbuilder = SymbolSpaceBuilder::with_entries(&[start]); let entry = ssbuilder.func(&start); @@ -356,17 +356,22 @@ impl<'a> LFunctionBuilder<'a> { } impl LFunctionBuilderData<'_> { - pub fn var_offset(&mut self, p: &UProgram, var: VarID) -> Option { - let mut current = VarOffset { id: var, offset: 0 }; - while let Type::Member(parent) = &p.get(current.id)?.ty { - current.id = parent.parent; - // ... should it be set to 0 if not? what does that even mean?? - // "the field of this struct is a reference to another variable" ???? - if let Type::Struct(sty) = &p.get(parent.parent)?.ty { - current.offset += self.field_offset(p, sty, &parent.name)?; - } + pub fn var_offset(&mut self, p: &UProgram, mut var: VarID) -> Option { + let mut path = Vec::new(); + while let Type::Field(parent) = &p.get(var)?.ty { + var = parent.parent; + path.push(&parent.name); } - Some(current) + let mut ty = &p.get(var)?.ty; + let mut offset = 0; + while let Type::Struct(sty) = ty { + let Some(name) = path.pop() else { + break; + }; + offset += self.field_offset(p, sty, &name)?; + ty = p.struct_field_type(sty, name).expect("bad field"); + } + Some(VarOffset { id: var, offset }) } pub fn addr_size(&self) -> Size { 64 @@ -425,7 +430,7 @@ impl LFunctionBuilderData<'_> { pub fn size_of_type(&mut self, p: &UProgram, ty: &Type) -> Option { // TODO: target matters - Some(match ty { + Some(match p.follow_type(ty)? { Type::Bits(b) => *b, Type::Struct(ty) => self.struct_inst(p, ty).size, Type::Generic { id } => return None, @@ -433,22 +438,8 @@ impl LFunctionBuilderData<'_> { Type::Ref(_) => self.addr_size(), Type::Array(ty, len) => self.size_of_type(p, ty)? * len, Type::Slice(_) => self.addr_size() * 2, - Type::Infer => return None, - Type::Error => return None, Type::Unit => 0, - Type::Placeholder => return None, - Type::Module(_) => return None, - Type::Member(m) => { - let pty = &p.expect(m.parent).ty; - let ty = match pty { - Type::Struct(ty) => self.struct_inst(p, ty).ty(&m.name)?, - Type::Module(path) => p.path_ty(path)?, - Type::Member(_) => return self.size_of_type(p, pty), - _ => return None, - } - .clone(); - self.size_of_type(p, &ty)? - } + _ => return None, }) } diff --git a/src/ir/upper/assoc.rs b/src/ir/upper/assoc.rs index b50e02c..30ac780 100644 --- a/src/ir/upper/assoc.rs +++ b/src/ir/upper/assoc.rs @@ -38,10 +38,9 @@ impl NameTree { let first = path.first()?; self.children.get(first)?.get(&path[1..]) } - pub fn id(&self, path: &[String]) -> Option> { - let last = path.last()?; - self.get(&path[..path.len() - 1])?.ids[K::INDEX] - .get(last) + pub fn id(&self, path: &[String], name: &str) -> Option> { + self.get(&path)?.ids[K::INDEX] + .get(name) .copied() .map(ID::new) } @@ -82,8 +81,8 @@ impl NameMap { } path } - pub fn id(&self, path: &[String]) -> Option> { - Some(self.tree.id(path)?) + pub fn id(&self, path: &[String], name: &str) -> Option> { + Some(self.tree.id(path, name)?) } pub fn push(&mut self, path: &[String]) { let id = self.names[K::INDEX].len(); diff --git a/src/ir/upper/error.rs b/src/ir/upper/error.rs index cedd404..fb4be1e 100644 --- a/src/ir/upper/error.rs +++ b/src/ir/upper/error.rs @@ -1,12 +1,12 @@ use crate::common::{CompilerMsg, CompilerOutput, FileSpan}; -use super::{Type, UProgram}; +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_real() || !dest.is_real() { + if !src.is_resolved() || !dest.is_resolved() { return; } self.err(CompilerMsg { diff --git a/src/ir/upper/inst.rs b/src/ir/upper/inst.rs index e6d9987..2cf51dc 100644 --- a/src/ir/upper/inst.rs +++ b/src/ir/upper/inst.rs @@ -9,6 +9,7 @@ pub struct VarInst { pub span: FileSpan, } +#[derive(Clone)] pub struct UInstrInst { pub i: UInstruction, pub span: FileSpan, diff --git a/src/ir/upper/instr.rs b/src/ir/upper/instr.rs index a27197c..263d017 100644 --- a/src/ir/upper/instr.rs +++ b/src/ir/upper/instr.rs @@ -3,6 +3,7 @@ use std::{collections::HashMap, fmt::Write}; use super::{arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, UFunc, UInstrInst}; use crate::{compiler::arch::riscv::Reg, util::Padder}; +#[derive(Clone)] pub enum UInstruction { Mv { dest: VarInst, @@ -51,14 +52,14 @@ pub enum UInstruction { Continue, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AsmBlockArg { pub var: VarInst, pub reg: Reg, pub ty: AsmBlockArgType, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum AsmBlockArgType { In, Out, diff --git a/src/ir/upper/kind.rs b/src/ir/upper/kind.rs index 2d8494b..11dd75a 100644 --- a/src/ir/upper/kind.rs +++ b/src/ir/upper/kind.rs @@ -5,6 +5,7 @@ use crate::{ }; use std::{collections::HashMap, fmt::Debug}; +#[derive(Clone)] pub struct UFunc { pub args: Vec, pub ret: Type, @@ -128,7 +129,7 @@ pub type GenericID = ID; impl Finish for UFunc { fn finish(p: &mut UProgram, id: ID, name: &str) { let var = p.def_searchable( - name.to_string(), + name, Some(UVar { ty: Type::Placeholder, }), diff --git a/src/ir/upper/program.rs b/src/ir/upper/program.rs index 298dca2..2c96699 100644 --- a/src/ir/upper/program.rs +++ b/src/ir/upper/program.rs @@ -12,6 +12,7 @@ pub struct UProgram { pub names: NameMap, pub origins: OriginMap, pub fn_var: FnVarMap, + // utils for creation pub path: Vec, pub name_stack: Vec>, pub temp: usize, @@ -29,10 +30,14 @@ impl UProgram { origins: OriginMap::new(), fn_var: FnVarMap::new(), path: Vec::new(), - name_stack: vec![HashMap::new()], + name_stack: Vec::new(), temp: 0, } } + pub fn set_module(&mut self, path: Vec) { + self.path = path; + self.name_stack = vec![HashMap::new()]; + } pub fn push(&mut self) { self.name_stack.push(HashMap::new()); } @@ -72,12 +77,16 @@ impl UProgram { self.fns[self.fn_var.fun(id)?.0].as_ref() } - pub fn temp_var(&mut self, origin: Origin, ty: Type) -> VarInst { + pub fn temp_var(&mut self, origin: Origin, ty: impl Into) -> VarInst { self.temp_var_inner(origin, ty) } - fn temp_var_inner(&mut self, origin: Origin, ty: Type) -> VarInst { - let v = self.def(&format!("temp{}", self.temp), Some(UVar { ty }), origin); + fn temp_var_inner(&mut self, origin: Origin, ty: impl Into) -> VarInst { + let v = self.def( + &format!("temp{}", self.temp), + Some(UVar { ty: ty.into() }), + origin, + ); self.temp += 1; VarInst { id: v, @@ -110,48 +119,86 @@ impl UProgram { pub fn def_searchable( &mut self, - name: String, + name: &str, k: Option, origin: Origin, ) -> ID { let id = self.def(&name, k, origin); - self.name_on_stack(id, name); + self.name_on_stack(id, name.to_string()); id } - pub fn ref_ty<'a>(&'a self, mem: &MemberRef) -> Option<&'a Type> { - self.follow_ref(mem).and_then(|r| Some(&self.get(r)?.ty)) - } - - pub fn follow_ref<'a>(&'a self, mem: &MemberRef) -> Option { - let parent = self.get(mem.parent)?; - if let Type::Member(mem) = &parent.ty { - self.follow_ref(mem) - } else { - Some(mem.parent) - } - } - - pub fn field_type<'a>(&'a self, sty: &'a Type, field: &str) -> Option<&'a Type> { - if let Type::Struct(st) = sty { - let struc = self.get(st.id)?; - let field = struc.fields.get(field)?; - if let Type::Generic { id } = field.ty { - for (i, g) in struc.generics.iter().enumerate() { - if *g == id { - return Some(&st.args[i]); - } + pub fn struct_field_type<'a>(&'a self, sty: &'a StructTy, field: &str) -> Option<&'a Type> { + let struc = self.get(sty.id)?; + let field = struc.fields.get(field)?; + if let Type::Generic { id } = field.ty { + for (i, g) in struc.generics.iter().enumerate() { + if *g == id { + return Some(&sty.args[i]); } } - Some(&field.ty) - } else if let Type::Module(path) = sty { - let id = self.names.id::(path)?; + } + Some(&field.ty) + } + + pub fn field_type<'a>(&'a self, ty: &'a Type, field: &str) -> Option<&'a Type> { + if let Type::Struct(sty) = ty { + self.struct_field_type(sty, field) + } else if let Type::Module(path) = ty { + let id = self.names.id::(path, field)?; Some(&self.get(id)?.ty) } else { None } } + pub fn follow_ref(&self, m: &FieldRef) -> Option<&Type> { + let parent = self.get(m.parent)?; + self.field_type(self.follow_type(&parent.ty)?, &m.name) + } + + pub fn get_type<'a>(&'a self, v: VarID) -> Option<&'a Type> { + self.follow_type(&self.get(v)?.ty) + } + + pub fn set_type(&mut self, mut var: VarID, set: Type) -> Option<()> { + let mut path = Vec::new(); + while let Type::Field(parent) = &self.get(var)?.ty { + var = parent.parent; + path.push(parent.name.clone()); + } + let mut ty = &mut self.vars[var.0].as_mut()?.ty; + 'outer: while let Type::Struct(sty) = ty { + let Some(name) = path.pop() else { + break; + }; + let struc = &self.structs[sty.id.0].as_ref()?; + let field = struc.fields.get(&name)?; + let Type::Generic { id } = field.ty else { + return None; + }; + for (i, g) in struc.generics.iter().enumerate() { + if *g == id { + ty = &mut sty.args[i]; + continue 'outer; + } + } + return None; + } + *ty = set; + Some(()) + } + + pub fn follow_type<'a>(&'a self, ty: &'a Type) -> Option<&'a Type> { + match ty { + Type::Field(m) => { + let parent = self.get(m.parent)?; + self.field_type(self.follow_type(&parent.ty)?, &m.name) + } + ty => Some(ty), + } + } + pub fn type_name(&self, ty: &Type) -> String { let mut str = String::new(); match ty { @@ -183,29 +230,29 @@ impl UProgram { Type::Ref(t) => { str = str + "&" + &self.type_name(t); } - Type::Error => str += "{error}", - Type::Infer => str += "{inferred}", 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 += "()", Type::Slice(t) => str += &format!("&[{}]", self.type_name(t)), + Type::Error => str += "{error}", + Type::Infer => str += "{inferred}", Type::Placeholder => str += "{placeholder}", Type::Module(path) => str += &path.join("::"), - Type::Member(m) => { + Type::Field(m) => { str += &self - .ref_ty(m) + .follow_ref(m) .map(|t| self.type_name(t)) .unwrap_or("{error}".to_string()) } } str } - pub fn path_var(&self, path: &NamePath) -> Option { - self.names.id(path) + pub fn path_var(&self, path: &NamePath, name: &str) -> Option { + self.names.id(path, name) } - pub fn path_ty(&self, path: &NamePath) -> Option<&Type> { - Some(&self.get(self.path_var(path)?)?.ty) + pub fn path_ty(&self, path: &NamePath, name: &str) -> Option<&Type> { + Some(&self.get(self.path_var(path, name)?)?.ty) } fn name_on_stack(&mut self, id: ID, name: String) { let idx = self.name_stack.len() - 1; @@ -230,4 +277,11 @@ impl UProgram { .enumerate() .map(|(i, x)| (ID::new(i), x)) } + pub fn cloned_fns(&self) -> impl Iterator + use<'_> { + self.fns + .iter() + .flatten() + .enumerate() + .map(|(i, x)| (ID::new(i), x.clone())) + } } diff --git a/src/ir/upper/ty.rs b/src/ir/upper/ty.rs index f0016f8..6ebf1c4 100644 --- a/src/ir/upper/ty.rs +++ b/src/ir/upper/ty.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use super::{assoc::NamePath, GenericID, Len, StructID, UInstruction, UProgram, UVar, VarID}; #[derive(Debug, Clone, Hash, Eq, PartialEq)] -pub struct MemberRef { +pub struct FieldRef { pub parent: VarID, pub name: String, } @@ -18,54 +18,55 @@ pub struct StructTy { pub enum Type { Bits(u32), Struct(StructTy), + // is this real? I don't know, it's kind of like infer Generic { id: GenericID }, Fn { args: Vec, ret: Box }, Ref(Box), Slice(Box), Array(Box, Len), - Member(MemberRef), + Unit, + // fake types + Field(FieldRef), Module(NamePath), Infer, Error, Placeholder, - Unit, } impl Type { + pub fn is_resolved(&self) -> bool { + !matches!(self, Self::Error | Self::Placeholder | Self::Infer) + } pub fn rf(self) -> Self { - Self::Ref(Box::new(self)) + Type::Ref(Box::new(self)) } pub fn arr(self, len: Len) -> Self { - Self::Array(Box::new(self), len) + Type::Array(Box::new(self), len) } pub fn slice(self) -> Self { - Self::Slice(Box::new(self)) - } - pub fn is_real(&self) -> bool { - !matches!(self, Self::Error | Self::Placeholder | Self::Infer) + Type::Slice(Box::new(self)) } } impl UProgram { pub fn resolve_types(&mut self) { - // I LOVE RUST - let mut vars = self.vars.clone(); - // set type of vars referring to functions - for (i, f) in self.iter_fns() { - let vi = self.fn_var.var(i); - vars[vi.0].as_mut().expect("bruh").ty = f.ty(self); + // PARTIAL BORROWING :SOB: + let fns: Vec<_> = self.cloned_fns().collect(); + for (i, f) in &fns { + let vi = self.fn_var.var(*i); + self.expect_mut(vi).ty = f.ty(self); } - for (i, f) in self.iter_fns() { + for (i, f) in &fns { let mut redo_iter = Vec::new(); let mut redo_new = Vec::new(); for i in f.flat_iter() { - if self.resolve_instr_types(&mut vars, &i.i).is_none() { + if self.resolve_instr_types(&i.i).is_none() { redo_iter.push(i); } } while !redo_iter.is_empty() { for &i in &redo_iter { - if self.resolve_instr_types(&mut vars, &i.i).is_none() { + if self.resolve_instr_types(&i.i).is_none() { redo_new.push(i); } } @@ -73,19 +74,19 @@ impl UProgram { redo_new.clear(); } } - self.vars = vars; } - pub fn resolve_instr_types(&self, vars: &mut [Option], i: &UInstruction) -> Option<()> { + pub fn resolve_instr_types(&mut self, i: &UInstruction) -> Option<()> { 'outer: { match &i { UInstruction::Call { dest, f, args } => { let fun = self.get_fn_var(f.id).expect("bruh"); - vars[dest.id.0].as_mut().expect("bruh").ty = fun.ret.clone(); + self.expect_mut(dest.id).ty = fun.ret.clone(); for (src, &dest) in args.iter().zip(&fun.args) { - let dest_ty = get(vars, dest)?; - let src_ty = get(vars, src.id)?; + let dest_ty = self.get_type(dest)?; + let src_ty = self.get_type(src.id)?; if let Some(ty) = self.match_types(dest_ty, src_ty) { + self.expect_mut(dest).ty = ty.clone(); set(vars, dest, ty.clone()); set(vars, src.id, ty); } @@ -166,13 +167,16 @@ impl UProgram { Some(()) } - pub fn match_types(&self, dest: &Type, src: &Type) -> Option { + pub fn match_types<'a>(&'a self, mut dest: &'a Type, mut src: &'a Type) -> Option { + dest = self.follow_type(dest)?; + src = self.follow_type(src)?; if dest == src { return None; } match (dest, src) { (Type::Error, _) | (_, Type::Error) => None, (Type::Placeholder, _) | (_, Type::Placeholder) => None, + (Type::Infer, Type::Infer) => None, (Type::Infer, x) | (x, Type::Infer) => Some(x.clone()), // TODO: handle constraints? (Type::Generic { id }, x) | (x, Type::Generic { id }) => Some(x.clone()), @@ -223,33 +227,3 @@ impl UProgram { } } } - -pub fn get(vars: &[Option], id: VarID) -> Option<&Type> { - let mut var = vars[id.0] - .as_ref() - .expect("PARTIAL BORROWING WOULD BE REALLY COOL"); - if var.ty == Type::Placeholder { - return None; - } - while let Type::Member(m) = &var.ty { - var = vars[m.parent.0].as_ref().expect("xd"); - } - // x.y().z == a.b.c() - // 0 ------- member(1, z) - // 1 ----- call(2) - // 2 --- member(3, y) - // 3 - x - // - // 0 ------- call(1) - // 1 ----- member(c, 2) - // 2 --- member(b, 3) - // 3 - a - Some(&var.ty) -} - -pub fn set(vars: &mut [Option], id: VarID, ty: Type) { - vars[id.0] - .as_mut() - .expect("PARTIAL BORROWING WOULD BE REALLY COOL") - .ty = ty; -} diff --git a/src/ir/upper/validate.rs b/src/ir/upper/validate.rs index 80e4017..97c9292 100644 --- a/src/ir/upper/validate.rs +++ b/src/ir/upper/validate.rs @@ -1,4 +1,3 @@ -// TODO: move this into ir, not parser use super::{Type, UInstrInst, UInstruction, UProgram}; use crate::common::{CompilerMsg, CompilerOutput, FileSpan}; @@ -33,17 +32,6 @@ impl UProgram { 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, self.origins.get(id)); - } else { - output.err(CompilerMsg { - msg: "invalid parent!".to_string(), - spans: vec![self.origins.get(id)], - }); - } - } } } @@ -108,6 +96,7 @@ impl UProgram { UInstruction::AsmBlock { instructions, args } => { for arg in args { // TODO: validate size with enabled targets + // maybe should happen in lowering? but I think it could happen here // if let Some(size) = self.size_of_var(arg.var.id) // && size != 64 // { @@ -125,8 +114,8 @@ impl UProgram { } UInstruction::Construct { dest, fields } => { let dest_def = self.expect(dest.id); - let (tyid, args) = match &dest_def.ty { - Type::Struct { id, args } => (*id, args), + let sty = match &dest_def.ty { + Type::Struct(sty) => sty, _ => { output.err(CompilerMsg { msg: format!( @@ -138,19 +127,19 @@ impl UProgram { continue; } }; - let def = self.expect(tyid); + let def = self.expect(sty.id); for (name, field) in &def.fields { if let Some(var) = fields.get(name) { - let mut sty = &field.ty; - if let Type::Generic { id } = sty { - for (g, a) in def.generics.iter().zip(args) { + let mut fty = &field.ty; + if let Type::Generic { id } = fty { + for (g, a) in def.generics.iter().zip(&sty.args) { if *g == *id { - sty = a; + fty = a; } } } let ety = &self.expect(var.id).ty; - output.check_assign(self, ety, sty, var.span); + output.check_assign(self, ety, fty, var.span); } else { output.err(CompilerMsg { msg: format!("field '{}' missing from struct", name), diff --git a/src/main.rs b/src/main.rs index 903b524..18d3a0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,29 +46,30 @@ impl UProgram { let mut output = CompilerOutput::new(); let mut imports = Imports::new(); - imports.insert(Import( - path.file_name() - .expect("bruh") - .to_str() - .expect("bruh") - .to_string(), - )); + imports.insert(Import(vec![path + .file_name() + .expect("bruh") + .to_str() + .expect("bruh") + .to_string()])); let mut imported = HashSet::new(); let mut fid = 0; while !imports.is_empty() { let iter = std::mem::take(&mut imports); for i in iter { - let name = &i.0; + let import_path = &i.0; if imported.contains(&i) { continue; } - let path = parent.join(name).with_extension(FILE_EXT); - let text = std::fs::read_to_string(&path).expect("failed to read file"); + let mut file_path = parent.to_path_buf(); + file_path.extend(import_path); + file_path.set_extension(FILE_EXT); + let text = std::fs::read_to_string(&file_path).expect("failed to read file"); output.file_map.insert( fid, SrcFile { - path, + path: file_path, text: text.clone(), }, ); @@ -77,7 +78,7 @@ impl UProgram { let res = PModule::parse(&mut ctx); // println!("Parsed:"); // println!("{:#?}", res.node); - res.lower(name.clone(), &mut program, &mut imports, &mut output); + res.lower(import_path.clone(), &mut program, &mut imports, &mut output); imported.insert(i); } } diff --git a/src/parser/v3/lower/asm.rs b/src/parser/v3/lower/asm.rs index ebe3c2f..eb6f081 100644 --- a/src/parser/v3/lower/asm.rs +++ b/src/parser/v3/lower/asm.rs @@ -1,7 +1,7 @@ use crate::{ compiler::arch::riscv::Reg, ir::{ - arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, UInstruction, Type, VarInst, + arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, Type, UInstruction, VarInst }, parser::PAsmBlockArg, }; diff --git a/src/parser/v3/lower/block.rs b/src/parser/v3/lower/block.rs index e33080e..bb3f469 100644 --- a/src/parser/v3/lower/block.rs +++ b/src/parser/v3/lower/block.rs @@ -27,27 +27,24 @@ impl FnLowerable for PBlock { }, } } + ctx.program.push(); // then lower imports for i_n in &import_nodes { if let Some(i) = i_n.as_ref() { let name = &i.0; - let import = Import(ctx.program.path_for(name)); - ctx - .imports - .entry(import) - .or_insert(ctx.program.def(name, None, i_n.origin)); - // I could prevent this if someone imports something twice, - // but that doesn't seem worth it at all - ctx.program.def_searchable::( - name.clone(), - Some(UVar { - ty: Type::Module, - }), - i_n.origin, - ); + let path = ctx.program.path_for(name); + let import = Import(path.clone()); + if ctx.imports.insert(import) { + ctx.program.def_searchable::( + name, + Some(UVar { + ty: Type::Module(path), + }), + i_n.origin, + ); + } } } - ctx.program.push(); // then lower const things let mut structs = Vec::new(); for s in &struct_nodes { diff --git a/src/parser/v3/lower/def.rs b/src/parser/v3/lower/def.rs index c508443..6023b0d 100644 --- a/src/parser/v3/lower/def.rs +++ b/src/parser/v3/lower/def.rs @@ -8,8 +8,7 @@ impl Node { let name = s .name .as_ref() - .map(|n| n.to_string()) - .unwrap_or("{error}".to_string()); + .map_or("{error}", |v| v); let ty = match &s.ty { Some(ty) => ty.lower(program, output), None => Type::Infer, diff --git a/src/parser/v3/lower/expr.rs b/src/parser/v3/lower/expr.rs index 7bebed5..236f85a 100644 --- a/src/parser/v3/lower/expr.rs +++ b/src/parser/v3/lower/expr.rs @@ -1,6 +1,6 @@ use super::{func::FnLowerCtx, FnLowerable, PExpr, UnaryOp}; use crate::{ - ir::{MemberRef, Type, UData, UInstruction, VarInst}, + ir::{FieldRef, Type, UData, UInstruction, VarInst}, parser::PInfixOp, }; @@ -40,7 +40,7 @@ impl FnLowerable for PExpr { super::PLiteral::Number(n) => { // TODO: temp let ty = Type::Bits(64); - let dest = ctx.program.temp_var(l.origin, Type::Bits(64)); + let dest = ctx.program.temp_var(l.origin, ty.clone()); let src = ctx.program.def( &format!("num {n:?}"), Some(UData { @@ -69,7 +69,7 @@ impl FnLowerable for PExpr { return None; }; let fname = ident.as_ref()?.0.clone(); - ctx.temp(Type::Member(MemberRef { + ctx.temp(Type::Field(FieldRef { parent: res1.id, name: fname, })) diff --git a/src/parser/v3/lower/func.rs b/src/parser/v3/lower/func.rs index 78611e6..f1703fc 100644 --- a/src/parser/v3/lower/func.rs +++ b/src/parser/v3/lower/func.rs @@ -1,6 +1,6 @@ -use super::{Imports, CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Node, PFunction}; +use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, PFunction}; use crate::{ - ir::{MemberRef, FnID, Idents, Type, UFunc, UInstrInst, UInstruction, UProgram, UVar, VarInst}, + ir::{FnID, Idents, Type, UFunc, UInstrInst, UInstruction, UProgram, UVar, VarInst}, parser, }; @@ -25,7 +25,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, self.header.origin); + let id = p.def_searchable(name, None, self.header.origin); Some(id) } pub fn lower( @@ -112,7 +112,7 @@ impl FnLowerCtx<'_> { pub fn err_at(&mut self, span: FileSpan, msg: String) { self.output.err(CompilerMsg::from_span(span, msg)) } - pub fn temp(&mut self, ty: Type) -> VarInst { + pub fn temp(&mut self, ty: impl Into) -> VarInst { self.program.temp_var(self.origin, ty) } pub fn push(&mut self, i: UInstruction) { diff --git a/src/parser/v3/lower/mod.rs b/src/parser/v3/lower/mod.rs index 44d0368..c815991 100644 --- a/src/parser/v3/lower/mod.rs +++ b/src/parser/v3/lower/mod.rs @@ -13,12 +13,14 @@ use crate::ir::{Type, UFunc, UProgram}; impl PModule { pub fn lower( &self, - name: String, + path: Vec, p: &mut UProgram, imports: &mut Imports, output: &mut CompilerOutput, ) { - let fid = p.def_searchable(name.clone(), None, self.block.origin); + let name = path.last().unwrap().clone(); + p.set_module(path); + let fid = p.def_searchable(&name, None, self.block.origin); p.push_name(&name); let mut fctx = FnLowerCtx { program: p, diff --git a/src/parser/v3/lower/struc.rs b/src/parser/v3/lower/struc.rs index 724f41b..62de84d 100644 --- a/src/parser/v3/lower/struc.rs +++ b/src/parser/v3/lower/struc.rs @@ -46,11 +46,7 @@ impl PStruct { span: FileSpan, ) -> Option<()> { p.push(); - let generics = self - .generics - .iter() - .flat_map(|a| a.lower(p)) - .collect(); + let generics = self.generics.iter().flat_map(|a| a.lower(p)).collect(); let fields = match &self.fields { PStructFields::Named(nodes) => nodes .iter() @@ -84,8 +80,8 @@ impl PStruct { impl Node { pub fn lower_name(&self, p: &mut UProgram) -> Option { let s = self.as_ref()?; - let name = s.name.as_ref()?.to_string(); - let id = p.def_searchable(name.to_string(), None, s.name.origin); + let name = s.name.as_ref()?; + let id = p.def_searchable(name, None, s.name.origin); 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 c8a8b1b..024a3d1 100644 --- a/src/parser/v3/lower/ty.rs +++ b/src/parser/v3/lower/ty.rs @@ -47,6 +47,6 @@ impl Node { pub fn lower(&self, p: &mut UProgram) -> Option { let s = self.as_ref()?; let name = s.name.as_ref()?; - Some(p.def_searchable(name.to_string(), Some(UGeneric {}), self.origin)) + Some(p.def_searchable(name, Some(UGeneric {}), self.origin)) } }