From 3f6846126050cd39932709abece80655d6e5af9b Mon Sep 17 00:00:00 2001 From: Lennart Van Hirtum Date: Sun, 23 Jun 2024 20:58:27 +0200 Subject: [PATCH] Can now concretize templates --- src/dev_aid/lsp/hover_info.rs | 2 +- src/dev_aid/lsp/tree_walk.rs | 18 +++---- src/errors.rs | 2 +- src/flattening/mod.rs | 38 ++++++++------ src/flattening/parse.rs | 91 +++++++++++++++++----------------- src/flattening/typechecking.rs | 8 +-- src/instantiation/execute.rs | 31 ++++++++++-- src/instantiation/mod.rs | 17 +++++-- src/linker/resolver.rs | 53 +++----------------- tinyTestFile.sus | 2 +- 10 files changed, 131 insertions(+), 131 deletions(-) diff --git a/src/dev_aid/lsp/hover_info.rs b/src/dev_aid/lsp/hover_info.rs index ac6f3fc..4392009 100644 --- a/src/dev_aid/lsp/hover_info.rs +++ b/src/dev_aid/lsp/hover_info.rs @@ -100,7 +100,7 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec { - let submodule = &linker.modules[submod.module_uuid]; + let submodule = &linker.modules[submod.module_ref.id]; // Declaration's documentation hover.documentation(&submod.documentation); diff --git a/src/dev_aid/lsp/tree_walk.rs b/src/dev_aid/lsp/tree_walk.rs index dd6e7ca..dce0de3 100644 --- a/src/dev_aid/lsp/tree_walk.rs +++ b/src/dev_aid/lsp/tree_walk.rs @@ -60,8 +60,8 @@ impl<'linker> From> for RefersTo { result.global = Some(name_elem); } LocationInfo::Port(sm, md, p_id) => { - result.local = Some((sm.module_uuid, md.ports[p_id].declaration_instruction)); - result.port = Some((sm.module_uuid, p_id)) + result.local = Some((sm.module_ref.id, md.ports[p_id].declaration_instruction)); + result.port = Some((sm.module_ref.id, p_id)) } LocationInfo::Interface(md_id, _md, i_id, _interface) => { result.interface = Some((md_id, i_id)) @@ -77,7 +77,7 @@ impl RefersTo { LocationInfo::InModule(md_id, _, obj, _) => self.local == Some((md_id, obj)), LocationInfo::Type(_) => false, LocationInfo::Global(ne) => self.global == Some(ne), - LocationInfo::Port(sm, _, p_id) => self.port == Some((sm.module_uuid, p_id)), + LocationInfo::Port(sm, _, p_id) => self.port == Some((sm.module_ref.id, p_id)), LocationInfo::Interface(md_id, _, i_id, _) => self.interface == Some((md_id, i_id)) } } @@ -159,7 +159,7 @@ impl<'linker, Visitor : FnMut(Span, LocationInfo<'linker>), Pruner : Fn(Span) -> WireReferenceRoot::SubModulePort(port) => { if let Some(span) = port.port_name_span { let sm_instruction = md.instructions[port.submodule_decl].unwrap_submodule(); - let submodule = &self.linker.modules[sm_instruction.module_uuid]; + let submodule = &self.linker.modules[sm_instruction.module_ref.id]; self.visit(span, LocationInfo::Port(sm_instruction, submodule, port.port)); // port_name_span being enabled means submodule_name_span is for sure @@ -177,8 +177,8 @@ impl<'linker, Visitor : FnMut(Span, LocationInfo<'linker>), Pruner : Fn(Span) -> (self.visitor)(typ_expr_span, LocationInfo::Type(typ_expr)); match typ_expr { WrittenType::Error(_) => {} - WrittenType::Named(span, name_id) => { - self.visit(*span, LocationInfo::Global(NameElem::Type(*name_id))); + WrittenType::Named(named_type) => { + self.visit(named_type.span, LocationInfo::Global(NameElem::Type(named_type.id))); } WrittenType::Array(_, arr_box) => { let (arr_content_typ, _size_id, _br_span) = arr_box.deref(); @@ -195,9 +195,9 @@ impl<'linker, Visitor : FnMut(Span, LocationInfo<'linker>), Pruner : Fn(Span) -> let submodule = md.instructions[submodule_instruction].unwrap_submodule(); self.visit(submod_name_span, LocationInfo::InModule(md_id, md, submodule_instruction, InModule::NamedSubmodule(submodule))); if iref.interface_span != submod_name_span { - let submod_md = &self.linker.modules[submodule.module_uuid]; + let submod_md = &self.linker.modules[submodule.module_ref.id]; let interface = &submod_md.interfaces[iref.submodule_interface]; - self.visit(iref.interface_span, LocationInfo::Interface(submodule.module_uuid, submod_md, iref.submodule_interface, interface)); + self.visit(iref.interface_span, LocationInfo::Interface(submodule.module_ref.id, submod_md, iref.submodule_interface, interface)); } } } @@ -217,7 +217,7 @@ impl<'linker, Visitor : FnMut(Span, LocationInfo<'linker>), Pruner : Fn(Span) -> for (id, inst) in &md.instructions { match inst { Instruction::SubModule(sm) => { - self.visit(sm.module_name_span, LocationInfo::Global(NameElem::Module(sm.module_uuid))); + self.visit(sm.module_ref.span, LocationInfo::Global(NameElem::Module(sm.module_ref.id))); if let Some((_sm_name, sm_name_span)) = &sm.name { self.visit(*sm_name_span, LocationInfo::InModule(md_id, md, id, InModule::NamedSubmodule(sm))); } diff --git a/src/errors.rs b/src/errors.rs index f5e4497..1060199 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -191,7 +191,7 @@ impl ErrorInfoObject for SubModuleInstance { if let Some((name, span)) = &self.name { (*span, format!("{name} declared here")) } else { - (self.module_name_span, "Used here".to_owned()) + (self.module_ref.span, "Used here".to_owned()) } } } diff --git a/src/flattening/mod.rs b/src/flattening/mod.rs index 60250ec..808bb04 100644 --- a/src/flattening/mod.rs +++ b/src/flattening/mod.rs @@ -179,7 +179,7 @@ impl Module { pub fn get_instruction_span(&self, instr_id : FlatID) -> Span { match &self.instructions[instr_id] { - Instruction::SubModule(sm) => sm.module_name_span, + Instruction::SubModule(sm) => sm.module_ref.span, Instruction::FuncCall(fc) => fc.whole_func_span, Instruction::Declaration(decl) => decl.decl_span, Instruction::Wire(w) => w.span, @@ -413,24 +413,32 @@ impl WireSource { } } -#[derive(Debug, Clone)] +#[derive(Debug)] +pub struct GlobalReference { + pub span: Span, + pub id: ID, + pub template_args: FlatAlloc, TemplateIDMarker>, + pub template_span: Option +} + +#[derive(Debug)] pub enum WrittenType { Error(Span), - Named(Span, TypeUUID), + Named(GlobalReference), Array(Span, Box<(WrittenType, FlatID, BracketSpan)>) } impl WrittenType { pub fn get_span(&self) -> Span { match self { - WrittenType::Error(span) | WrittenType::Named(span, _) | WrittenType::Array(span, _) => *span + WrittenType::Error(span) | WrittenType::Named(GlobalReference { span, ..}) | WrittenType::Array(span, _) => *span } } pub fn to_type(&self) -> AbstractType { match self { WrittenType::Error(_) => AbstractType::Error, - WrittenType::Named(_, id) => AbstractType::Named(*id), + WrittenType::Named(named_type) => AbstractType::Named(named_type.id), WrittenType::Array(_, arr_box) => { let (elem_typ, _arr_idx, _br_span) = arr_box.deref(); AbstractType::Array(Box::new(elem_typ.to_type())) @@ -440,7 +448,7 @@ impl WrittenType { pub fn for_each_generative_input(&self, mut f : F) { match self { - WrittenType::Error(_) | WrittenType::Named(_, _) => {} + WrittenType::Error(_) | WrittenType::Named(_) => {} WrittenType::Array(_span, arr_box) => { f(arr_box.deref().1) } @@ -452,8 +460,8 @@ impl WrittenType { WrittenType::Error(_) => { "{error}".to_owned() } - WrittenType::Named(_, id) => { - linker_types[*id].get_full_name() + WrittenType::Named(named_type) => { + linker_types[named_type.id].get_full_name() } WrittenType::Array(_, sub) => sub.deref().0.to_string(linker_types) + "[]", } @@ -522,13 +530,16 @@ pub enum TemplateInputKind { Generative{decl_span : Span, declaration_instruction : FlatID} } + +#[derive(Debug)] pub struct TemplateArg { pub name_specification : Option, pub whole_span : Span, - pub typ : TemplateArgType + pub kind : TemplateArgKind } -pub enum TemplateArgType { +#[derive(Debug)] +pub enum TemplateArgKind { Type(WrittenType), Value(FlatID) } @@ -536,8 +547,7 @@ pub enum TemplateArgType { #[derive(Debug)] pub struct SubModuleInstance { - pub module_uuid : ModuleUUID, - pub module_name_span : Span, + pub module_ref : GlobalReference, /// Name is not always present in source code. Such as in inline function call syntax: my_mod(a, b, c) pub name : Option<(String, Span)>, pub declaration_runtime_depth : usize, @@ -641,8 +651,8 @@ impl Instruction { } -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum ModuleOrWrittenType { WrittenType(WrittenType), - Module(Span, ModuleUUID) + Module(GlobalReference) } diff --git a/src/flattening/parse.rs b/src/flattening/parse.rs index 1d116cc..70b9a11 100644 --- a/src/flattening/parse.rs +++ b/src/flattening/parse.rs @@ -5,15 +5,15 @@ use std::{ops::{Deref, DerefMut}, str::FromStr}; use num::BigInt; use sus_proc_macro::{field, kind, kw}; use crate::{ - arena_alloc::{UUIDRange, UUIDRangeIter, UUID}, debug::SpanDebugger, errors::ErrorCollector, file_position::{BracketSpan, Span}, linker::{with_module_editing_context, ConstantUUIDMarker, Linker, ModuleUUID, ModuleUUIDMarker, NameElem, NameResolver, NamedConstant, NamedType, ResolvedName, Resolver, TypeUUIDMarker, WorkingOnResolver}, parser::Cursor, value::Value + arena_alloc::{UUIDRange, UUIDRangeIter, UUID}, debug::SpanDebugger, errors::ErrorCollector, file_position::{BracketSpan, Span}, linker::{with_module_editing_context, ConstantUUIDMarker, Linker, ModuleUUID, ModuleUUIDMarker, NameElem, NameResolver, NamedConstant, NamedType, Resolver, TypeUUIDMarker, WorkingOnResolver}, parser::Cursor, value::Value }; use super::name_context::LocalVariableContext; use super::*; -enum LocalOrGlobal<'l> { +enum LocalOrGlobal { Local(FlatID), - Global(ResolvedName<'l>, FlatAlloc, TemplateIDMarker>, Option), + Global(NameElem, Span, FlatAlloc, TemplateIDMarker>, Option), // Error is already handled NotFound(Span) } @@ -23,7 +23,7 @@ enum PartialWireReference { /// Means the error has already been reported Error, /// A module that is implicitly declared in a function call. - GlobalModuleName(ModuleUUID, Span), + GlobalModuleName(GlobalReference), /// Partial result, waiting for a port to be grabbed ModuleButNoPort(FlatID, Span), /// A module with an interface specified @@ -37,21 +37,21 @@ impl PartialWireReference { match self { PartialWireReference::Error => None, // Error already reported PartialWireReference::ModuleButNoPort(submod_decl, span) => { - let md_uuid = ctx.working_on.instructions[submod_decl].unwrap_submodule().module_uuid; + let md_uuid = ctx.working_on.instructions[submod_decl].unwrap_submodule().module_ref.id; ctx.errors .error(span, "cannot operate on modules directly. Should use ports instead") .info_obj(&ctx.modules[md_uuid]); None }, - PartialWireReference::GlobalModuleName(md_uuid, span) => { - let md = &ctx.modules[md_uuid]; + PartialWireReference::GlobalModuleName(md_ref) => { + let md = &ctx.modules[md_ref.id]; ctx.errors - .error(span, format!("Expected a Wire Reference, but found module '{}' instead", md.link_info.name)) + .error(md_ref.span, format!("Expected a Wire Reference, but found module '{}' instead", md.link_info.name)) .info_obj(md); None } PartialWireReference::ModuleWithInterface { submodule_decl: submod_decl, submodule_name_span:_, interface, interface_name_span } => { - let md_uuid = ctx.working_on.instructions[submod_decl].unwrap_submodule().module_uuid; + let md_uuid = ctx.working_on.instructions[submod_decl].unwrap_submodule().module_ref.id; let md = &ctx.modules[md_uuid]; let interf = &md.interfaces[interface]; ctx.errors @@ -192,7 +192,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { let name_specification = cursor.optional_field_span(field!("name"), kind!("identifier")); cursor.field(field!("arg")); let typ = self.flatten_type(cursor); - TemplateArg{name_specification, whole_span, typ : TemplateArgType::Type(typ)} + TemplateArg{name_specification, whole_span, kind : TemplateArgKind::Type(typ)} }) } kind!("template_value_param") => { @@ -200,7 +200,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { let name_specification = cursor.optional_field_span(field!("name"), kind!("identifier")); cursor.field(field!("arg")); let expr = self.flatten_expr(cursor); - TemplateArg{name_specification, whole_span, typ : TemplateArgType::Value(expr)} + TemplateArg{name_specification, whole_span, kind : TemplateArgKind::Value(expr)} }) } _ => cursor.could_not_match() @@ -208,10 +208,10 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { }) } - fn collect_template_args(&self, global : &ResolvedName, template_argument_list : Vec) -> FlatAlloc, TemplateIDMarker> { + fn collect_template_args(&self, name_elem : NameElem, template_argument_list : Vec) -> FlatAlloc, TemplateIDMarker> { let empty_template : FlatAlloc = FlatAlloc::new(); - let template_info = match global.name_elem { + let template_info = match name_elem { NameElem::Module(md_id) => { &self.modules[md_id].link_info.template_arguments }, @@ -229,7 +229,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { let target_name = &self.name_resolver.file_text[name_span]; let Some(named_index) = template_info.find(|_, template_input| template_input.name == target_name) else { - let info = global.get_linking_error_location(); + let info = self.name_resolver.get_linking_error_location(name_elem); let err_ref = self.errors.error(name_span, format!("No template argument of name '{target_name}' on '{}'", info.full_name)); if let Some(pos) = info.location { err_ref.info(pos, format!("'{}' declared here", info.full_name)); @@ -239,7 +239,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { named_index } else { let Some(index) = index_iter.next() else { - let info = global.get_linking_error_location(); + let info = self.name_resolver.get_linking_error_location(name_elem); let err_ref = self.errors.error(given_arg.whole_span, format!("Too many template arguments! '{}' only requires {} template arguments", info.full_name, template_info.len())); if let Some(pos) = info.location { err_ref.info(pos, format!("'{}' declared here", info.full_name)); @@ -303,10 +303,10 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { // Global identifier let [name_span] = name_path.as_slice() else {todo!("Namespaces")}; - if let Some(found_global) = self.name_resolver.resolve_global(*name_span) { - let template_arg_map = self.collect_template_args(&found_global, template_args); + if let Some((found_global, found_global_span)) = self.name_resolver.resolve_global(*name_span) { + let template_arg_map = self.collect_template_args(found_global, template_args); - LocalOrGlobal::Global(found_global, template_arg_map, template_args_whole_span) + LocalOrGlobal::Global(found_global, found_global_span, template_arg_map, template_args_whole_span) } else { LocalOrGlobal::NotFound(*name_span) } @@ -330,11 +330,12 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { if kind == kind!("template_global") { match self.flatten_local_or_template_global(true, cursor) { LocalOrGlobal::Local(_) => unreachable!(), - LocalOrGlobal::Global(resolved_global, template_args, template_span) => { - if let Some(typ_id) = resolved_global.expect_type() { - WrittenType::Named(resolved_global.span, typ_id) + LocalOrGlobal::Global(resolved_global, resolved_global_span, template_args, template_span) => { + if let NameElem::Type(typ_id) = resolved_global { + WrittenType::Named(GlobalReference { span: resolved_global_span, id: typ_id, template_args, template_span}) } else { - WrittenType::Error(resolved_global.span) + self.name_resolver.not_expected_global_error(resolved_global, resolved_global_span, "Type"); + WrittenType::Error(resolved_global_span) } } LocalOrGlobal::NotFound(name_span) => WrittenType::Error(name_span) // Already covered @@ -350,14 +351,14 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { if kind == kind!("template_global") { match self.flatten_local_or_template_global(true, cursor) { LocalOrGlobal::Local(_) => unreachable!(), - LocalOrGlobal::Global(resolved_global, template_args, template_span) => { - match &resolved_global.name_elem { - NameElem::Type(typ_id) => ModuleOrWrittenType::WrittenType(WrittenType::Named(resolved_global.span, *typ_id)), - NameElem::Module(md) if ALLOW_MODULES => ModuleOrWrittenType::Module(resolved_global.span, *md), + LocalOrGlobal::Global(resolved_global, resolved_global_span, template_args, template_span) => { + match &resolved_global { + NameElem::Type(typ_id) => ModuleOrWrittenType::WrittenType(WrittenType::Named(GlobalReference { span: resolved_global_span, id: *typ_id, template_args, template_span })), + NameElem::Module(md_id) if ALLOW_MODULES => ModuleOrWrittenType::Module(GlobalReference { span: resolved_global_span, id: *md_id, template_args, template_span }), _ => { let accepted_text = if ALLOW_MODULES {"Type or Module"} else {"Type"}; - resolved_global.not_expected_global_error(accepted_text); - ModuleOrWrittenType::WrittenType(WrittenType::Error(resolved_global.span)) + self.name_resolver.not_expected_global_error(resolved_global, resolved_global_span, accepted_text); + ModuleOrWrittenType::WrittenType(WrittenType::Error(resolved_global_span)) } } } @@ -476,7 +477,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { ModuleOrWrittenType::WrittenType(typ) => { typ } - ModuleOrWrittenType::Module(span, module_uuid) => { + ModuleOrWrittenType::Module(module_ref) => { assert!(ALLOW_MODULES); if let Some((_, span)) = span_latency_specifier { self.errors.error(span, "Cannot add latency specifier to module instances"); @@ -484,8 +485,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { let name = &self.name_resolver.file_text[name_span]; return self.alloc_declaration(name, whole_declaration_span, Instruction::SubModule(SubModuleInstance{ name : Some((name.to_owned(), name_span)), - module_uuid, - module_name_span: span, + module_ref, declaration_runtime_depth : DECL_DEPTH_LATER, local_interface_domains : FlatAlloc::new(), documentation @@ -521,7 +521,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { DeclarationPortInfo::GenerativeInput => { let this_template_id = self.template_inputs_to_visit.next().unwrap(); - let TemplateInputKind::Generative { decl_span, declaration_instruction } = &mut self.working_on.link_info.template_arguments[this_template_id].kind else {unreachable!()}; + let TemplateInputKind::Generative { decl_span:_, declaration_instruction } = &mut self.working_on.link_info.template_arguments[this_template_id].kind else {unreachable!()}; *declaration_instruction = decl_id; } @@ -603,12 +603,12 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { let outer_span = cursor.span(); match self.flatten_wire_reference(cursor) { PartialWireReference::Error => None, - PartialWireReference::GlobalModuleName(module_uuid, module_name_span) => { + PartialWireReference::GlobalModuleName(module_ref) => { let documentation = cursor.extract_gathered_comments(); + let interface_span = module_ref.span; let submodule_decl = self.working_on.instructions.alloc(Instruction::SubModule(SubModuleInstance{ name : None, - module_uuid, - module_name_span, + module_ref, declaration_runtime_depth : DECL_DEPTH_LATER, local_interface_domains : FlatAlloc::new(), documentation @@ -617,7 +617,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { submodule_decl, submodule_interface : Module::MAIN_INTERFACE_ID, name_span : None, - interface_span : module_name_span + interface_span }) } PartialWireReference::ModuleButNoPort(submodule_decl, name_span) => { @@ -646,7 +646,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { fn get_interface_reference(&self, interface_reference : &ModuleInterfaceReference) -> (&Module, &Interface) { let submodule = self.working_on.instructions[interface_reference.submodule_decl].unwrap_submodule(); - let md = &self.modules[submodule.module_uuid]; + let md = &self.modules[submodule.module_ref.id]; let interface = &md.interfaces[interface_reference.submodule_interface]; (md, interface) } @@ -738,17 +738,17 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { Instruction::Wire(_) | Instruction::Write(_) | Instruction::IfStatement(_) | Instruction::ForStatement(_) | Instruction::FuncCall(_) => unreachable!() } } - LocalOrGlobal::Global(global, template_args, template_args_span) => { - match global.name_elem { + LocalOrGlobal::Global(name_elem, span, template_args, template_span) => { + match name_elem { NameElem::Constant(cst) => { let root = WireReferenceRoot::NamedConstant(cst, expr_span); PartialWireReference::WireReference(WireReference{root, path : Vec::new()}) } NameElem::Module(md_id) => { - PartialWireReference::GlobalModuleName(md_id, expr_span) + PartialWireReference::GlobalModuleName(GlobalReference { span, id: md_id, template_args, template_span }) } NameElem::Type(_) => { - global.not_expected_global_error("named wire: local or constant"); + self.name_resolver.not_expected_global_error(name_elem, span, "named wire: local or constant"); PartialWireReference::Error }, } @@ -767,8 +767,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { // only unpack the subexpr after flattening the idx, so we catch all errors match &mut flattened_arr_expr { - PartialWireReference::ModuleButNoPort(_, sp) | PartialWireReference::GlobalModuleName(_, sp) | PartialWireReference::ModuleWithInterface { submodule_decl:_, submodule_name_span:_, interface:_, interface_name_span:sp }=> { - sp.debug(); + PartialWireReference::ModuleButNoPort(_, _) | PartialWireReference::GlobalModuleName(_) | PartialWireReference::ModuleWithInterface { submodule_decl:_, submodule_name_span:_, interface:_, interface_name_span:_ }=> { todo!("Module Arrays") } PartialWireReference::Error => {} @@ -788,8 +787,8 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { match flattened_arr_expr { PartialWireReference::Error => PartialWireReference::Error, - PartialWireReference::GlobalModuleName(_md_id, span) => { - self.errors.error(span, "Ports or interfaces can only be accessed on modules that have been explicitly declared. Declare this submodule on its own line"); + PartialWireReference::GlobalModuleName(md_ref) => { + self.errors.error(md_ref.span, "Ports or interfaces can only be accessed on modules that have been explicitly declared. Declare this submodule on its own line"); PartialWireReference::Error } PartialWireReference::ModuleWithInterface { submodule_decl:_, submodule_name_span, interface:_, interface_name_span } => { @@ -801,7 +800,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { PartialWireReference::ModuleButNoPort(submodule_decl, submodule_name_span) => { let submodule = self.working_on.instructions[submodule_decl].unwrap_submodule(); - let submod = &self.modules[submodule.module_uuid]; + let submod = &self.modules[submodule.module_ref.id]; match submod.get_port_or_interface_by_name(port_name_span, &self.name_resolver.file_text, self.errors) { Some(PortOrInterface::Port(port)) => { diff --git a/src/flattening/typechecking.rs b/src/flattening/typechecking.rs index b9bda6f..35348e0 100644 --- a/src/flattening/typechecking.rs +++ b/src/flattening/typechecking.rs @@ -62,7 +62,7 @@ impl<'l, 'errs> DerefMut for TypeCheckingContext<'l, 'errs> { impl<'l, 'errs> TypeCheckingContext<'l, 'errs> { fn get_decl_of_module_port<'s>(&'s self, port : PortID, submodule_instr : FlatID) -> (&'s Declaration, FileUUID) { - let submodule_id = self.working_on.instructions[submodule_instr].unwrap_submodule().module_uuid; + let submodule_id = self.working_on.instructions[submodule_instr].unwrap_submodule().module_ref.id; let module = &self.modules[submodule_id]; let decl = module.get_port_decl(port); (decl, module.link_info.file) @@ -71,7 +71,7 @@ impl<'l, 'errs> TypeCheckingContext<'l, 'errs> { fn get_type_of_port(&self, port : PortID, submodule_instr : FlatID) -> FullType { let (decl, _file) = self.get_decl_of_module_port(port, submodule_instr); let submodule_inst = self.working_on.instructions[submodule_instr].unwrap_submodule(); - let submodule_module = &self.modules[submodule_inst.module_uuid]; + let submodule_module = &self.modules[submodule_inst.module_ref.id]; let port_interface = submodule_module.ports[port].interface; let port_local_domain = submodule_inst.local_interface_domains[port_interface]; FullType { @@ -216,7 +216,7 @@ impl<'l, 'errs> TypeCheckingContext<'l, 'errs> { fn typecheck_visit_instruction(&mut self, instr_id : FlatID) { match &self.working_on.instructions[instr_id] { Instruction::SubModule(sm) => { - let md = &self.modules[sm.module_uuid]; + let md = &self.modules[sm.module_ref.id]; let local_interface_domains = md.interfaces.iter().map(|_| self.type_checker.new_unknown_domain_id()).collect(); let Instruction::SubModule(sm) = &mut self.working_on.instructions[instr_id] else {unreachable!()}; @@ -349,7 +349,7 @@ impl<'l, 'errs> TypeCheckingContext<'l, 'errs> { BestName::ExistingInterface => self.modules.working_on.interfaces[id].name.clone(), BestName::SubModule(sm_instr, sm_interface) => { let sm = self.working_on.instructions[sm_instr].unwrap_submodule(); - let md = &self.modules[sm.module_uuid]; + let md = &self.modules[sm.module_ref.id]; format!("{}_{}", sm.get_name(&md), md.interfaces[sm_interface].name) } BestName::NamedWire(decl_id) => self.working_on.instructions[decl_id].unwrap_wire_declaration().name.clone(), diff --git a/src/instantiation/execute.rs b/src/instantiation/execute.rs index e061912..f0e6e86 100644 --- a/src/instantiation/execute.rs +++ b/src/instantiation/execute.rs @@ -9,7 +9,7 @@ use std::ops::{Deref, Index, IndexMut}; use num::BigInt; use crate::{ - abstract_type::DomainType, arena_alloc::UUIDRange, concrete_type::{ConcreteType, BOOL_CONCRETE_TYPE, INT_CONCRETE_TYPE}, file_position::Span, flattening::{BinaryOperator, Declaration, FlatID, FlatIDRange, IdentifierType, Instruction, UnaryOperator, WireInstance, WireReference, WireReferencePathElement, WireReferenceRoot, WireSource, WriteModifiers, WrittenType}, linker::NamedConstant, util::add_to_small_set, value::{compute_binary_op, compute_unary_op, TypedValue, Value} + abstract_type::DomainType, arena_alloc::UUIDRange, concrete_type::{ConcreteType, BOOL_CONCRETE_TYPE, INT_CONCRETE_TYPE}, file_position::Span, flattening::{BinaryOperator, Declaration, FlatID, FlatIDRange, IdentifierType, Instruction, TemplateArgKind, UnaryOperator, WireInstance, WireReference, WireReferencePathElement, WireReferenceRoot, WireSource, WriteModifiers, WrittenType}, linker::NamedConstant, util::add_to_small_set, value::{compute_binary_op, compute_unary_op, TypedValue, Value} }; use super::*; @@ -100,8 +100,8 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { fn concretize_type(&self, typ : &WrittenType) -> ExecutionResult { Ok(match typ { WrittenType::Error(_) => caught_by_typecheck!("Error Type"), - WrittenType::Named(_, id) => { - ConcreteType::Named(*id) + WrittenType::Named(named_type) => { + ConcreteType::Named(named_type.id) } WrittenType::Array(_, arr_box) => { let (arr_content_typ, arr_size_wire, _bracket_span) = arr_box.deref(); @@ -424,7 +424,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { self.md.get_instruction_span(original_instruction); let instance_to_add : SubModuleOrWire = match instr { Instruction::SubModule(submodule) => { - let sub_module = &self.linker.modules[submodule.module_uuid]; + let sub_module = &self.linker.modules[submodule.module_ref.id]; let name = if let Some((name, _span)) = &submodule.name { name.clone() @@ -433,7 +433,28 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { }; let port_map = FlatAlloc::new_nones(sub_module.ports.len()); let interface_call_sites = sub_module.interfaces.iter().map(|_| Vec::new()).collect(); - SubModuleOrWire::SubModule(self.submodules.alloc(SubModule { original_instruction, instance : None, port_map, interface_call_sites, name, module_uuid : submodule.module_uuid})) + let mut template_args = FlatAlloc::with_capacity(submodule.module_ref.template_args.len()); + + for (_id, v) in &submodule.module_ref.template_args { + template_args.alloc(match v { + Some(arg) => { + match &arg.kind { + TemplateArgKind::Type(typ) => ConcreteTemplateArg::Type(self.concretize_type(typ)?), + TemplateArgKind::Value(v) => ConcreteTemplateArg::Value(self.generation_state.get_generation_value(*v)?.clone()), + } + } + None => ConcreteTemplateArg::NotProvided + }); + } + SubModuleOrWire::SubModule(self.submodules.alloc(SubModule { + original_instruction, + instance : None, + port_map, + interface_call_sites, + name, + module_uuid : submodule.module_ref.id, + template_args + })) } Instruction::Declaration(wire_decl) => { self.instantiate_declaration(wire_decl, original_instruction)? diff --git a/src/instantiation/mod.rs b/src/instantiation/mod.rs index 5879043..c13f6b8 100644 --- a/src/instantiation/mod.rs +++ b/src/instantiation/mod.rs @@ -8,7 +8,7 @@ mod latency_count; use std::{cell::RefCell, ops::Deref, rc::Rc}; use crate::{ - arena_alloc::{FlatAlloc, UUIDMarker, UUID}, concrete_type::ConcreteType, config, errors::{CompileError, ErrorCollector, ErrorStore}, file_position::{BracketSpan, Span}, flattening::{BinaryOperator, DomainID, DomainIDMarker, FlatID, FlatIDMarker, Module, PortID, PortIDMarker, UnaryOperator}, linker::{Linker, ModuleUUID}, value::{TypedValue, Value} + arena_alloc::{FlatAlloc, UUIDMarker, UUID}, concrete_type::ConcreteType, config, errors::{CompileError, ErrorCollector, ErrorStore}, file_position::{BracketSpan, Span}, flattening::{BinaryOperator, DomainID, DomainIDMarker, FlatID, FlatIDMarker, Module, PortID, PortIDMarker, TemplateIDMarker, UnaryOperator}, linker::{Linker, ModuleUUID}, value::{TypedValue, Value} }; use self::latency_algorithm::SpecifiedLatency; @@ -88,6 +88,14 @@ pub struct UsedPort { pub name_refs : Vec } +#[derive(Debug)] +pub enum ConcreteTemplateArg { + Type(ConcreteType), + Value(TypedValue), + NotProvided, + Errored +} + #[derive(Debug)] pub struct SubModule { pub original_instruction : FlatID, @@ -95,7 +103,8 @@ pub struct SubModule { pub port_map : FlatAlloc, PortIDMarker>, pub interface_call_sites : FlatAlloc, DomainIDMarker>, pub name : String, - pub module_uuid : ModuleUUID + pub module_uuid : ModuleUUID, + pub template_args : FlatAlloc } #[derive(Debug)] @@ -273,7 +282,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { (Some(_concrete_port), None) => { // Port is enabled, but not used let source_code_port = &sub_module.ports[port_id]; - self.errors.warn(submod_obj.module_name_span, format!("Unused port '{}'", source_code_port.name)) + self.errors.warn(submod_obj.module_ref.span, format!("Unused port '{}'", source_code_port.name)) .info_obj_different_file(source_code_port, sub_module.link_info.file) .info_obj_same_file(submod_obj); } @@ -309,7 +318,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { } sm.instance = Some(instance); } else { - self.errors.error(submod_obj.module_name_span, "Error instantiating submodule"); + self.errors.error(submod_obj.module_ref.span, "Error instantiating submodule"); success = false; }; } diff --git a/src/linker/resolver.rs b/src/linker/resolver.rs index 8138973..a6e0b22 100644 --- a/src/linker/resolver.rs +++ b/src/linker/resolver.rs @@ -72,7 +72,7 @@ pub struct NameResolver<'linker, 'err_and_globals> { impl<'linker, 'err_and_globals> NameResolver<'linker, 'err_and_globals> { /// SAFETY: Files are never touched, and as long as this object is managed properly linker will also exist long enough. - pub fn resolve_global<'slf>(&'slf self, name_span : Span) -> Option> { + pub fn resolve_global<'slf>(&'slf self, name_span : Span) -> Option<(NameElem, Span)> { let name = &self.file_text[name_span]; let linker = unsafe{&*self.linker}; @@ -80,7 +80,7 @@ impl<'linker, 'err_and_globals> NameResolver<'linker, 'err_and_globals> { match linker.global_namespace.get(name) { Some(NamespaceElement::Global(found)) => { resolved_globals.referenced_globals.push(*found); - Some(ResolvedName{name_elem: *found, linker : self.linker, errors: &self.errors, span: name_span}) + Some((*found, name_span)) } Some(NamespaceElement::Colission(coll)) => { resolved_globals.all_resolved = false; @@ -108,62 +108,23 @@ impl<'linker, 'err_and_globals> NameResolver<'linker, 'err_and_globals> { } } } -} - -pub struct ResolvedName<'err_and_globals> { - pub name_elem : NameElem, - pub span : Span, - pub errors : &'err_and_globals ErrorCollector<'err_and_globals>, - linker : *const Linker -} -impl<'err_and_globals> ResolvedName<'err_and_globals> { - pub fn get_linking_error_location(&self) -> LinkingErrorLocation { - unsafe{&*self.linker}.get_linking_error_location(self.name_elem) + pub fn get_linking_error_location(&self, name_elem : NameElem) -> LinkingErrorLocation { + unsafe{&*self.linker}.get_linking_error_location(name_elem) } - pub fn not_expected_global_error(&self, expected : &str) { + pub fn not_expected_global_error(&self, name_elem : NameElem, span : Span, expected : &str) { // SAFETY: The allocated linker objects aren't going to change. - let info = self.get_linking_error_location(); + let info = self.get_linking_error_location(name_elem); let name = &info.full_name; let global_type = info.named_type; - let err_ref = self.errors.error(self.span, format!("{name} is not a {expected}, it is a {global_type} instead!")); + let err_ref = self.errors.error(span, format!("{name} is not a {expected}, it is a {global_type} instead!")); if let Some(span_file) = info.location { err_ref.info(span_file, "Defined here"); } } - - #[allow(dead_code)] - pub fn expect_constant(&self) -> Option { - if let NameElem::Constant(id) = self.name_elem { - Some(id) - } else { - self.not_expected_global_error("Constant"); - None - } - } - - pub fn expect_type(&self) -> Option { - if let NameElem::Type(id) = self.name_elem { - Some(id) - } else { - self.not_expected_global_error("Type"); - None - } - } - - #[allow(dead_code)] - pub fn expect_module(&self) -> Option { - if let NameElem::Module(id) = self.name_elem { - Some(id) - } else { - self.not_expected_global_error("Module"); - None - } - } } - /// pub struct ModuleEditContext<'linker, 'err_and_globals> { /// pub modules : InternalResolver<'linker, 'err_and_globals, ModuleUUIDMarker, Module>, /// pub types : Resolver<'linker, 'err_and_globals, TypeUUIDMarker, NamedType>, diff --git a/tinyTestFile.sus b/tinyTestFile.sus index 4d103df..9e3f983 100644 --- a/tinyTestFile.sus +++ b/tinyTestFile.sus @@ -12,7 +12,7 @@ module test : ::int:: 3; BEEP = int::<;>> ab { } module use_test { - test:: test_mod + test::<3;> test_mod }