diff --git a/src/abstract_type.rs b/src/abstract_type.rs index 474536c..3ee3fb2 100644 --- a/src/abstract_type.rs +++ b/src/abstract_type.rs @@ -56,13 +56,6 @@ impl DomainType { pub fn new_unset() -> DomainType { DomainType::Physical(DomainID::PLACEHOLDER) } - pub fn physical_to_string(physical_id : DomainID, interfaces : &FlatAlloc) -> String { - if let Some(interf) = interfaces.get(physical_id) { - format!("{{{}}}", interf.name) - } else { - format!("{{unnamed domain {}}}", physical_id.get_hidden_value()) - } - } } #[derive(Debug, Clone)] diff --git a/src/codegen_fallback.rs b/src/codegen_fallback.rs index a3e35e2..0c81a98 100644 --- a/src/codegen_fallback.rs +++ b/src/codegen_fallback.rs @@ -136,7 +136,7 @@ impl<'g, 'out, Stream : std::fmt::Write> CodeGenerationContext<'g, 'out, Stream> if let Instruction::Declaration(wire_decl) = &self.md.instructions[w.original_instruction] { // Don't print named inputs and outputs, already did that in interface - if let DeclarationPortInfo::RegularPort { is_input: _ } = wire_decl.is_port { + if let DeclarationPortInfo::RegularPort { is_input: _, port_id:_ } = wire_decl.is_port { continue; } } diff --git a/src/dev_aid/lsp/hover_info.rs b/src/dev_aid/lsp/hover_info.rs index bdca0f7..ddcb7f0 100644 --- a/src/dev_aid/lsp/hover_info.rs +++ b/src/dev_aid/lsp/hover_info.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use lsp_types::{LanguageString, MarkedString}; use crate::{ - abstract_type::DomainType, flattening::{DeclarationPortInfo, FlatID, IdentifierType, InterfaceToDomainMap, Module}, instantiation::{SubModuleOrWire, CALCULATE_LATENCY_LATER}, linker::{FileData, LinkInfo, Linker, NameElem}, parser::Documentation, to_string::map_to_type_names + abstract_type::DomainType, flattening::{DeclarationPortInfo, FlatID, IdentifierType, InterfaceToDomainMap, Module}, instantiation::{SubModuleOrWire, CALCULATE_LATENCY_LATER}, linker::{FileData, LinkInfo, Linker, NameElem}, parser::Documentation, template::TemplateInputKind }; use super::tree_walk::{InModule, LocationInfo}; @@ -78,7 +78,7 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec details_vec.push(if is_input {"input"} else {"output"}), + DeclarationPortInfo::RegularPort { is_input, port_id:_ } => details_vec.push(if is_input {"input"} else {"output"}), DeclarationPortInfo::NotPort => {}, DeclarationPortInfo::GenerativeInput(_) => details_vec.push("input") // "gen" in "input gen" is covered by decl.identifier_type } @@ -89,7 +89,7 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec {details_vec.push("gen")} } - let typ_str = decl.typ.typ.to_string(&linker.types, &map_to_type_names(&md.link_info.template_arguments)); + let typ_str = decl.typ.typ.to_string(&linker.types, &md.link_info.template_arguments); details_vec.push(&typ_str); details_vec.push(&decl.name); @@ -126,12 +126,30 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec { - hover.sus_code(typ.to_type().to_string(&linker.types, &map_to_type_names(&link_info.template_arguments))); + hover.sus_code(typ.to_type().to_string(&linker.types, &link_info.template_arguments)); + } + LocationInfo::TemplateInput(in_obj, link_info, _template_id, template_arg) => { + match &template_arg.kind { + TemplateInputKind::Type { default_value } => { + if let Some(default_typ) = default_value { + hover.monospace(format!("type param '{}' = {}", template_arg.name, default_typ.to_string(&linker.types, &link_info.template_arguments))); + } else { + hover.monospace(format!("type param '{}'", template_arg.name)); + } + } + TemplateInputKind::Generative { decl_span:_, declaration_instruction } => { + let NameElem::Module(md_id) = in_obj else {todo!("Non-module template args")}; + let md = &linker.modules[md_id]; + let decl = md.instructions[*declaration_instruction].unwrap_wire_declaration(); + hover.sus_code(format!("input gen {} {}", template_arg.name, decl.typ_expr.to_string(&linker.types, &link_info.template_arguments))); + hover.gather_hover_infos(md, *declaration_instruction, true); + } + } } LocationInfo::Global(global) => { if let Some(link_info) = linker.get_link_info(global) { diff --git a/src/dev_aid/lsp/mod.rs b/src/dev_aid/lsp/mod.rs index f7c7e28..c7c5329 100644 --- a/src/dev_aid/lsp/mod.rs +++ b/src/dev_aid/lsp/mod.rs @@ -293,6 +293,9 @@ fn handle_request(method : &str, params : serde_json::Value, file_cache : &mut L } LocationInfo::InModule(_, _, _, InModule::Temporary(_)) => {} LocationInfo::Type(_, _) => {} + LocationInfo::TemplateInput(_, link_info, _, template_arg) => { + goto_definition_list.push((template_arg.name_span, link_info.file)) + } LocationInfo::Global(id) => { if let Some(link_info) = file_cache.linker.get_link_info(id) { goto_definition_list.push((link_info.name_span, link_info.file)); diff --git a/src/dev_aid/lsp/semantic_tokens.rs b/src/dev_aid/lsp/semantic_tokens.rs index 42e69af..87cca43 100644 --- a/src/dev_aid/lsp/semantic_tokens.rs +++ b/src/dev_aid/lsp/semantic_tokens.rs @@ -1,7 +1,7 @@ use lsp_types::{Position, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokensFullOptions, SemanticTokensLegend, SemanticTokensOptions, SemanticTokensServerCapabilities, WorkDoneProgressOptions}; -use crate::{abstract_type::DomainType, dev_aid::lsp::to_position, file_position::Span, flattening::{DomainID, IdentifierType}, linker::{FileData, FileUUID, Linker, NameElem}}; +use crate::{abstract_type::DomainType, dev_aid::lsp::to_position, file_position::Span, flattening::{DomainID, IdentifierType}, linker::{FileData, FileUUID, Linker, NameElem}, template::TemplateInputKind}; use super::tree_walk::{self, InModule, LocationInfo}; @@ -128,6 +128,12 @@ fn walk_name_color(file : &FileData, linker : &Linker) -> Vec<(Span, IDEIdentifi } LocationInfo::InModule(_md_id, _, _, InModule::Temporary(_)) => {return} LocationInfo::Type(_, _) => {return} + LocationInfo::TemplateInput(_id, _link_info, _, template_arg) => { + match &template_arg.kind { + TemplateInputKind::Type { .. } => IDEIdentifierType::Type, + TemplateInputKind::Generative { .. } => IDEIdentifierType::Generative, + } + } LocationInfo::Global(g) => { match g { NameElem::Module(_) => IDEIdentifierType::Interface, diff --git a/src/dev_aid/lsp/tree_walk.rs b/src/dev_aid/lsp/tree_walk.rs index 2f27e51..02e57d7 100644 --- a/src/dev_aid/lsp/tree_walk.rs +++ b/src/dev_aid/lsp/tree_walk.rs @@ -2,19 +2,20 @@ use std::ops::Deref; use crate::{ - file_position::Span, flattening::{Declaration, DomainID, FlatID, Instruction, Interface, Module, ModuleInterfaceReference, PortID, SubModuleInstance, WireInstance, WireReference, WireReferenceRoot, WireSource, WrittenType}, linker::{FileData, FileUUID, LinkInfo, Linker, ModuleUUID, NameElem} + file_position::Span, flattening::{Declaration, DeclarationPortInfo, DomainID, FlatID, Instruction, Interface, Module, ModuleInterfaceReference, PortID, SubModuleInstance, WireInstance, WireReference, WireReferenceRoot, WireSource, WrittenType}, linker::{FileData, FileUUID, LinkInfo, Linker, ModuleUUID, NameElem}, template::{GlobalReference, TemplateArgKind, TemplateID, TemplateInput, TemplateInputKind} }; #[derive(Clone, Copy, Debug)] pub enum InModule<'linker> { NamedLocal(&'linker Declaration), NamedSubmodule(&'linker SubModuleInstance), - Temporary(&'linker WireInstance), + Temporary(&'linker WireInstance) } #[derive(Clone, Copy, Debug)] pub enum LocationInfo<'linker> { InModule(ModuleUUID, &'linker Module, FlatID, InModule<'linker>), + TemplateInput(NameElem, &'linker LinkInfo, TemplateID, &'linker TemplateInput), Type(&'linker WrittenType, &'linker LinkInfo), Global(NameElem), /// The contained module only refers to the module on which the port is defined @@ -29,7 +30,8 @@ pub struct RefersTo { pub local : Option<(ModuleUUID, FlatID)>, pub global : Option, pub port : Option<(ModuleUUID, PortID)>, - pub interface : Option<(ModuleUUID, DomainID)> + pub interface : Option<(ModuleUUID, DomainID)>, + pub template_input : Option<(NameElem, TemplateID)> } impl<'linker> From> for RefersTo { @@ -39,13 +41,21 @@ impl<'linker> From> for RefersTo { global: None, port: None, interface : None, + template_input : None }; match info { LocationInfo::InModule(md_id, md, flat_id, flat_obj) => { match flat_obj { InModule::NamedLocal(_) => { - if let Some(port_id) = md.ports.find(|_, port| port.declaration_instruction == flat_id) { - result.port = Some((md_id, port_id)); + let decl = md.instructions[flat_id].unwrap_wire_declaration(); + match decl.is_port { + DeclarationPortInfo::NotPort => {} + DeclarationPortInfo::RegularPort { is_input:_, port_id } => { + result.port = Some((md_id, port_id)); + } + DeclarationPortInfo::GenerativeInput(template_id) => { + result.template_input = Some((NameElem::Module(md_id), template_id)) + } } result.local = Some((md_id, flat_id)); }, @@ -56,6 +66,16 @@ impl<'linker> From> for RefersTo { } } LocationInfo::Type(_, _) => {} + LocationInfo::TemplateInput(obj, _link_info, template_id, template_arg) => { + match &template_arg.kind { + TemplateInputKind::Type { default_value:_ } => {} + TemplateInputKind::Generative { decl_span:_, declaration_instruction } => { + let NameElem::Module(md_id) = obj else {unreachable!()}; // TODO, local names in types? + result.local = Some((md_id, *declaration_instruction)); + } + } + result.template_input = Some((obj, template_id)) + } LocationInfo::Global(name_elem) => { result.global = Some(name_elem); } @@ -75,6 +95,7 @@ impl RefersTo { pub fn refers_to_same_as(&self, info : LocationInfo) -> bool { match info { LocationInfo::InModule(md_id, _, obj, _) => self.local == Some((md_id, obj)), + LocationInfo::TemplateInput(parent, _, template_id, _) => self.template_input == Some((parent, template_id)), LocationInfo::Type(_, _) => false, LocationInfo::Global(ne) => self.global == Some(ne), LocationInfo::Port(sm, _, p_id) => self.port == Some((sm.module_ref.id, p_id)), @@ -82,7 +103,7 @@ impl RefersTo { } } pub fn is_global(&self) -> bool { - self.global.is_some() | self.port.is_some() | self.interface.is_some() + self.global.is_some() | self.port.is_some() | self.interface.is_some() | self.template_input.is_some() } } @@ -148,6 +169,23 @@ impl<'linker, Visitor : FnMut(Span, LocationInfo<'linker>), Pruner : Fn(Span) -> } } + fn walk_global_reference(&mut self, parent : NameElem, link_info : &'linker LinkInfo, global : &'linker GlobalReference) where NameElem : From { + let target_name_elem = NameElem::from(global.id); + self.visit(global.span, LocationInfo::Global(target_name_elem)); + for (id, template_arg) in global.template_args.iter_valids() { + if let Some(name_span) = template_arg.name_specification { + let target_link_info = self.linker.get_link_info(target_name_elem).unwrap(); + self.visit(name_span, LocationInfo::TemplateInput(target_name_elem, target_link_info, id, &target_link_info.template_arguments[id])); + } + match &template_arg.kind { + TemplateArgKind::Type(typ_expr) => { + self.walk_type(parent, link_info, typ_expr); + } + TemplateArgKind::Value(_) => {} // Covered by FlatIDs + } + } + } + fn walk_wire_ref(&mut self, md_id : ModuleUUID, md : &'linker Module, wire_ref : &'linker WireReference) { match &wire_ref.root { WireReferenceRoot::LocalDecl(decl_id, span) => { @@ -171,22 +209,22 @@ impl<'linker, Visitor : FnMut(Span, LocationInfo<'linker>), Pruner : Fn(Span) -> } } - fn walk_type(&mut self, typ_expr : &'linker WrittenType, link_info : &'linker LinkInfo) { + fn walk_type(&mut self, parent : NameElem, link_info : &'linker LinkInfo, typ_expr : &'linker WrittenType) { let typ_expr_span = typ_expr.get_span(); if !(self.should_prune)(typ_expr_span) { (self.visitor)(typ_expr_span, LocationInfo::Type(typ_expr, link_info)); match typ_expr { WrittenType::Error(_) => {} - WrittenType::Template(span, link_info) => { - // TODO + WrittenType::Template(span, template_id) => { + self.visit(*span, LocationInfo::TemplateInput(parent, link_info, *template_id, &link_info.template_arguments[*template_id])); } WrittenType::Named(named_type) => { - self.visit(named_type.span, LocationInfo::Global(NameElem::Type(named_type.id))); + self.walk_global_reference(parent, link_info, named_type); } WrittenType::Array(_, arr_box) => { let (arr_content_typ, _size_id, _br_span) = arr_box.deref(); - self.walk_type(arr_content_typ, link_info) + self.walk_type(parent, link_info, arr_content_typ); } } } @@ -210,6 +248,16 @@ impl<'linker, Visitor : FnMut(Span, LocationInfo<'linker>), Pruner : Fn(Span) -> if !(self.should_prune)(md.link_info.span) { self.visit(md.link_info.name_span, LocationInfo::Global(NameElem::Module(md_id))); + for (template_id, template_arg) in &md.link_info.template_arguments { + if let TemplateInputKind::Type{default_value} = &template_arg.kind { + self.visit(template_arg.name_span, LocationInfo::TemplateInput(NameElem::Module(md_id), &md.link_info, template_id, template_arg)); + + if let Some(default_val) = default_value { + self.walk_type(NameElem::Module(md_id), &md.link_info, default_val) + } + } + } + let mut interface_iter = md.interfaces.iter(); // Skip main interface interface_iter.next(); @@ -220,13 +268,13 @@ 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_ref.span, LocationInfo::Global(NameElem::Module(sm.module_ref.id))); + self.walk_global_reference(NameElem::Module(md_id), &md.link_info, &sm.module_ref); if let Some((_sm_name, sm_name_span)) = &sm.name { self.visit(*sm_name_span, LocationInfo::InModule(md_id, md, id, InModule::NamedSubmodule(sm))); } } Instruction::Declaration(decl) => { - self.walk_type(&decl.typ_expr, &md.link_info); + self.walk_type(NameElem::Module(md_id), &md.link_info, &decl.typ_expr); if decl.declaration_itself_is_not_written_to { self.visit(decl.name_span, LocationInfo::InModule(md_id, md, id, InModule::NamedLocal(decl))); } diff --git a/src/flattening/mod.rs b/src/flattening/mod.rs index 9b42410..be1dcd0 100644 --- a/src/flattening/mod.rs +++ b/src/flattening/mod.rs @@ -11,7 +11,7 @@ pub use initialization::gather_initial_file_data; pub use typechecking::typecheck_all_modules; use crate::{ - abstract_type::{AbstractType, FullType}, arena_alloc::{FlatAlloc, UUIDMarker, UUIDRange, UUID}, errors::ErrorCollector, file_position::{BracketSpan, FileText, Span}, instantiation::InstantiationList, linker::{ConstantUUID, LinkInfo, ModuleUUID, TypeUUID}, parser::Documentation, pretty_print_many_spans, template::{GlobalReference, TemplateID, TemplateInputKind}, value::Value + abstract_type::{AbstractType, FullType}, arena_alloc::{FlatAlloc, UUIDMarker, UUIDRange, UUID}, errors::ErrorCollector, file_position::{BracketSpan, FileText, Span}, instantiation::InstantiationList, linker::{ConstantUUID, LinkInfo, ModuleUUID, TypeUUID}, parser::Documentation, template::{GlobalReference, TemplateID, TemplateInputKind}, value::Value }; @@ -82,75 +82,6 @@ impl Module { self.instructions[flat_port].unwrap_wire_declaration() } - pub fn make_port_info_fmt(&self, port_id : PortID, file_text : &FileText, result : &mut String) { - use std::fmt::Write; - let port = &self.ports[port_id]; - let port_direction = if port.is_input {"input"} else {"output"}; - writeln!(result, "{port_direction} {}", &file_text[port.decl_span]).unwrap() - } - pub fn make_port_info_string(&self, port_id : PortID, file_text : &FileText) -> String { - let mut r = String::new(); self.make_port_info_fmt(port_id, file_text, &mut r); r - } - - pub fn make_interface_info_fmt(&self, interface_id : DomainID, file_text : &FileText, result : &mut String) { - for (port_id, port) in &self.ports { - if port.interface == interface_id { - self.make_port_info_fmt(port_id, file_text, result); - } - } - } - pub fn make_interface_info_string(&self, interface_id : DomainID, file_text : &FileText) -> String { - let mut r = String::new(); self.make_interface_info_fmt(interface_id, file_text, &mut r); r - } - - pub fn make_all_ports_info_string(&self, file_text : &FileText, local_domains : Option) -> String { - use std::fmt::Write; - - let mut interface_iter = self.interfaces.iter(); - if !self.main_interface_used { - interface_iter.next(); - } - - let mut type_args : Vec<&str> = Vec::new(); - let mut temporary_gen_input_builder = String::new(); - for (_id, t) in &self.link_info.template_arguments { - match &t.kind { - TemplateInputKind::Type { default_value:_ } => type_args.push(&t.name), - TemplateInputKind::Generative { decl_span, declaration_instruction:_ } => writeln!(temporary_gen_input_builder, "input gen {}", &file_text[*decl_span]).unwrap(), - } - } - - let mut result = format!("module {}<{}>:\n", self.link_info.get_full_name(), type_args.join(", ")); - result.push_str(&temporary_gen_input_builder); - - for (interface_id, interface) in interface_iter { - if let Some(domain_map) = &local_domains { - writeln!(result, "{}: {{{}}}", &interface.name, domain_map.get_submodule_interface_domain(interface_id).name).unwrap(); - } else { - writeln!(result, "{}:", &interface.name).unwrap(); - } - self.make_interface_info_fmt(interface_id, file_text, &mut result); - } - - result - } - - pub fn print_flattened_module(&self, file_text : &FileText) { - println!("[[{}]]:", self.link_info.name); - println!("Interface:"); - for (port_id, port) in &self.ports { - println!(" {} -> {:?}", self.make_port_info_string(port_id, file_text), port); - } - println!("Instructions:"); - let mut spans_print = Vec::new(); - for (id, inst) in &self.instructions { - println!(" {id:?}: {inst:?}"); - let span = self.get_instruction_span(id); - spans_print.push((format!("{id:?}"), span.into_range())); - } - pretty_print_many_spans(file_text.file_text.clone(), &spans_print); - } - /// Get a port by the given name. Reports non existing ports errors /// /// Prefer interfaces over ports in name conflicts @@ -451,13 +382,13 @@ const DECL_DEPTH_LATER : usize = usize::MAX; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DeclarationPortInfo { NotPort, - RegularPort{is_input : bool}, + RegularPort{is_input : bool, port_id : PortID}, GenerativeInput(TemplateID) } impl DeclarationPortInfo { pub fn as_regular_port(&self) -> Option { - if let DeclarationPortInfo::RegularPort{is_input} = self { + if let DeclarationPortInfo::RegularPort{is_input, port_id:_} = self { Some(*is_input) } else { None @@ -466,7 +397,7 @@ impl DeclarationPortInfo { pub fn implies_read_only(&self) -> bool { match self { DeclarationPortInfo::NotPort => false, - DeclarationPortInfo::RegularPort { is_input } => *is_input, + DeclarationPortInfo::RegularPort { is_input, port_id:_ } => *is_input, DeclarationPortInfo::GenerativeInput(_) => true, } } diff --git a/src/flattening/parse.rs b/src/flattening/parse.rs index 4cc0ab2..769e58a 100644 --- a/src/flattening/parse.rs +++ b/src/flattening/parse.rs @@ -405,7 +405,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { if let Some((_, io_span)) = io_kw { self.errors.error(io_span, "Cannot redeclare 'input' or 'output' on functional syntax IO"); } - DeclarationPortInfo::RegularPort { is_input: declaration_context == DeclarationContext::Input } + DeclarationPortInfo::RegularPort { is_input: declaration_context == DeclarationContext::Input, port_id:UUID::PLACEHOLDER } } DeclarationContext::ForLoopGenerative => { if let Some((_, io_span)) = io_kw { @@ -415,7 +415,7 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { } DeclarationContext::PlainWire => { match io_kw { - Some((is_input, _)) => DeclarationPortInfo::RegularPort { is_input }, + Some((is_input, _)) => DeclarationPortInfo::RegularPort { is_input, port_id:UUID::PLACEHOLDER }, None => DeclarationPortInfo::NotPort, } } @@ -437,12 +437,11 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { Some((kw!("gen"), modifier_span)) => { match is_port { DeclarationPortInfo::NotPort => {} - DeclarationPortInfo::RegularPort { is_input : true } => { - let this_template_id = self.template_inputs_to_visit.next().unwrap(); + DeclarationPortInfo::RegularPort { is_input : true, port_id : _ } => { // AHA! Generative input - is_port = DeclarationPortInfo::GenerativeInput(this_template_id) + is_port = DeclarationPortInfo::GenerativeInput(UUID::PLACEHOLDER) } - DeclarationPortInfo::RegularPort { is_input : false } => { + DeclarationPortInfo::RegularPort { is_input : false, port_id : _ } => { self.errors.error(modifier_span, "Cannot make generative outputs. This is because it could interfere with inference of generic types and generative inputs"); } DeclarationPortInfo::GenerativeInput(_) => unreachable!("Can't have been GenerativeInput here already, because it only gets converted to that here"), @@ -463,6 +462,12 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { } }; + match &mut is_port { + DeclarationPortInfo::NotPort => {} + DeclarationPortInfo::RegularPort { is_input:_, port_id } => {*port_id = self.ports_to_visit.next().unwrap();} + DeclarationPortInfo::GenerativeInput(template_id) => {*template_id = self.template_inputs_to_visit.next().unwrap();} + } + cursor.field(field!("type")); let decl_span = Span::new_overarching(cursor.span(), whole_declaration_span.empty_span_at_end()); let typ_or_module_expr = self.flatten_module_or_type::(cursor); @@ -523,9 +528,8 @@ impl<'l, 'errs> FlatteningContext<'l, 'errs> { match is_port { DeclarationPortInfo::NotPort => {}, - DeclarationPortInfo::RegularPort { is_input:_ } => { - let this_port_id = self.ports_to_visit.next().unwrap(); - let port = &mut self.working_on.ports[this_port_id]; + DeclarationPortInfo::RegularPort { is_input:_, port_id } => { + let port = &mut self.working_on.ports[port_id]; assert_eq!(port.name_span, name_span); port.declaration_instruction = decl_id; } diff --git a/src/to_string.rs b/src/to_string.rs index e2db9ff..b3e95ba 100644 --- a/src/to_string.rs +++ b/src/to_string.rs @@ -1,4 +1,4 @@ -use crate::{abstract_type::AbstractType, arena_alloc::FlatAlloc, concrete_type::ConcreteType, flattening::WrittenType, linker::{LinkInfo, Linker, NamedType, TypeUUID}, template::{ConcreteTemplateArg, ConcreteTemplateArgs, TemplateIDMarker, TemplateInputs}, value::Value}; +use crate::{abstract_type::{AbstractType, DomainType}, arena_alloc::FlatAlloc, concrete_type::ConcreteType, file_position::FileText, flattening::{DomainID, DomainIDMarker, Interface, InterfaceToDomainMap, Module, PortID, WrittenType}, linker::{LinkInfo, Linker, NamedType, TypeUUID}, pretty_print_many_spans, template::{ConcreteTemplateArg, ConcreteTemplateArgs, TemplateID, TemplateIDMarker, TemplateInputKind, TemplateInputs}, value::Value}; use std::{fmt::{Display, Formatter}, ops::Index}; @@ -10,14 +10,29 @@ pub fn map_to_type_names(template_inputs : &TemplateInputs) -> FlatAlloc &str; +} + +impl TemplateNameGetter for FlatAlloc { + fn get_template_name(&self, id : TemplateID) -> &str { + &self[id] + } +} +impl TemplateNameGetter for TemplateInputs { + fn get_template_name(&self, id : TemplateID) -> &str { + &self[id].name + } +} + impl WrittenType { - pub fn to_string>(&self, linker_types : &TypVec, template_names : &FlatAlloc) -> String { + pub fn to_string, TemplateVec : TemplateNameGetter>(&self, linker_types : &TypVec, template_names : &TemplateVec) -> String { match self { WrittenType::Error(_) => { "{error}".to_owned() } WrittenType::Template(_, id) => { - template_names[*id].clone() + template_names.get_template_name(*id).to_owned() } WrittenType::Named(named_type) => { linker_types[named_type.id].get_full_name() @@ -28,7 +43,7 @@ impl WrittenType { } impl AbstractType { - pub fn to_string>(&self, linker_types : &TypVec, template_names : &FlatAlloc) -> String { + pub fn to_string, TemplateVec : TemplateNameGetter>(&self, linker_types : &TypVec, template_names : &TemplateVec) -> String { match self { AbstractType::Error => { "{error}".to_owned() @@ -37,7 +52,7 @@ impl AbstractType { "{unknown}".to_owned() } AbstractType::Template(id) => { - template_names[*id].clone() + template_names.get_template_name(*id).to_owned() } AbstractType::Named(id) => { linker_types[*id].get_full_name() @@ -106,6 +121,89 @@ impl Value { } } +impl DomainType { + pub fn physical_to_string(physical_id : DomainID, interfaces : &FlatAlloc) -> String { + if let Some(interf) = interfaces.get(physical_id) { + format!("{{{}}}", interf.name) + } else { + format!("{{unnamed domain {}}}", physical_id.get_hidden_value()) + } + } +} + +impl Module { + + + pub fn make_port_info_fmt(&self, port_id : PortID, file_text : &FileText, result : &mut String) { + use std::fmt::Write; + let port = &self.ports[port_id]; + let port_direction = if port.is_input {"input"} else {"output"}; + writeln!(result, "{port_direction} {}", &file_text[port.decl_span]).unwrap() + } + pub fn make_port_info_string(&self, port_id : PortID, file_text : &FileText) -> String { + let mut r = String::new(); self.make_port_info_fmt(port_id, file_text, &mut r); r + } + + pub fn make_interface_info_fmt(&self, interface_id : DomainID, file_text : &FileText, result : &mut String) { + for (port_id, port) in &self.ports { + if port.interface == interface_id { + self.make_port_info_fmt(port_id, file_text, result); + } + } + } + pub fn make_interface_info_string(&self, interface_id : DomainID, file_text : &FileText) -> String { + let mut r = String::new(); self.make_interface_info_fmt(interface_id, file_text, &mut r); r + } + + pub fn make_all_ports_info_string(&self, file_text : &FileText, local_domains : Option) -> String { + use std::fmt::Write; + + let mut interface_iter = self.interfaces.iter(); + if !self.main_interface_used { + interface_iter.next(); + } + + let mut type_args : Vec<&str> = Vec::new(); + let mut temporary_gen_input_builder = String::new(); + for (_id, t) in &self.link_info.template_arguments { + match &t.kind { + TemplateInputKind::Type { default_value:_ } => type_args.push(&t.name), + TemplateInputKind::Generative { decl_span, declaration_instruction:_ } => writeln!(temporary_gen_input_builder, "input gen {}", &file_text[*decl_span]).unwrap(), + } + } + + let mut result = format!("module {}<{}>:\n", self.link_info.get_full_name(), type_args.join(", ")); + result.push_str(&temporary_gen_input_builder); + + for (interface_id, interface) in interface_iter { + if let Some(domain_map) = &local_domains { + writeln!(result, "{}: {{{}}}", &interface.name, domain_map.get_submodule_interface_domain(interface_id).name).unwrap(); + } else { + writeln!(result, "{}:", &interface.name).unwrap(); + } + self.make_interface_info_fmt(interface_id, file_text, &mut result); + } + + result + } + + pub fn print_flattened_module(&self, file_text : &FileText) { + println!("[[{}]]:", self.link_info.name); + println!("Interface:"); + for (port_id, port) in &self.ports { + println!(" {} -> {:?}", self.make_port_info_string(port_id, file_text), port); + } + println!("Instructions:"); + let mut spans_print = Vec::new(); + for (id, inst) in &self.instructions { + println!(" {id:?}: {inst:?}"); + let span = self.get_instruction_span(id); + spans_print.push((format!("{id:?}"), span.into_range())); + } + pretty_print_many_spans(file_text.file_text.clone(), &spans_print); + } +} + pub fn pretty_print_concrete_instance(linker : &Linker, link_info : &LinkInfo, template_args : &ConcreteTemplateArgs) -> String { assert!(link_info.template_arguments.len() == template_args.len()); diff --git a/sus_compiler b/sus_compiler new file mode 100755 index 0000000..7f3856c Binary files /dev/null and b/sus_compiler differ diff --git a/tinyTestFile.sus b/tinyTestFile.sus index 85c9d4c..4fafe62 100644 --- a/tinyTestFile.sus +++ b/tinyTestFile.sus @@ -140,3 +140,39 @@ module use_replicate { replicate:: a replicate:: b } + +module permute_t { + input gen int SIZE + + input gen int[SIZE] SOURCES + + interface permute : T[SIZE] d_in -> T[SIZE] d_out + + for int i in 0..SIZE { + d_out[i] = d_in[SOURCES[i]] + } +} +/* +module use_permute { + gen int[8] indices + + indices[0] = 3 + indices[1] = 2 + indices[2] = 4 + indices[3] = 5 + indices[4] = 1 + indices[5] = 2 + indices[6] = 7 + indices[7] = 6 + + + gen int[2] inArr + + inArr[0] = 2387 + inArr[1] = 786823 + + permute_t:: permut + + int[8] beep = permut.permute(inArr) +} +*/ \ No newline at end of file