diff --git a/README.md b/README.md index ac446b4..19331d0 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,8 @@ In this example, we create a memory block with a read port and a write port. Thi - [x] Generative Code - [x] Generative Parameters - [x] Type Templates +- [ ] Full Template Inference +- [ ] Actions, Triggers and Queries ### Language Features - [x] Basic Tokenizer @@ -230,7 +232,7 @@ In this example, we create a memory block with a read port and a write port. Thi - [x] Latency cuts - [x] Latency Offset - [ ] Latency Cuts & Latency Counting for "disjoint Input-Output blocks" -- [ ] Split Latencies +- [ ] ~~Split Latencies~~ ### LSP - [x] Basic LSP for VSCode integration diff --git a/src/alloc.rs b/src/alloc.rs index c207ef5..c151275 100644 --- a/src/alloc.rs +++ b/src/alloc.rs @@ -285,6 +285,9 @@ impl ArenaAllocator { self.data.clear(); self.free_slots.clear(); } + pub fn is_empty(&self) -> bool { + self.data.len() == self.free_slots.len() + } pub fn iter<'a>(&'a self) -> FlatOptionIterator<'a, T, IndexMarker> { self.into_iter() } diff --git a/src/compiler_top.rs b/src/compiler_top.rs index 4487bc2..119b0e1 100644 --- a/src/compiler_top.rs +++ b/src/compiler_top.rs @@ -3,8 +3,9 @@ use std::path::PathBuf; use std::str::FromStr; use crate::config::EarlyExitUpTo; -use crate::linker::AFTER_INITIAL_PARSE_CP; +use crate::linker::{get_builtin_constant, get_builtin_type, AFTER_INITIAL_PARSE_CP}; use crate::prelude::*; +use crate::value::{TypedValue, Value}; use tree_sitter::Parser; @@ -33,9 +34,20 @@ impl LinkerExtraFileInfoManager for () {} impl Linker { pub fn add_standard_library(&mut self, info_mngr : &mut ExtraInfoManager) { + assert!(self.modules.is_empty()); + assert!(self.types.is_empty()); + assert!(self.constants.is_empty()); println!("Standard Library Directory: {STD_LIB_PATH}"); let stl_path = PathBuf::from_str(STD_LIB_PATH).expect("Standard library directory is not a valid path?"); self.add_all_files_in_directory(&stl_path, info_mngr); + + assert_eq!(self.types[get_builtin_type("int")].link_info.name, "int"); + assert_eq!(self.types[get_builtin_type("bool")].link_info.name, "bool"); + + assert_eq!(self.constants[get_builtin_constant("true")].link_info.name, "true"); + assert_eq!(self.constants[get_builtin_constant("false")].link_info.name, "false"); + self.constants[get_builtin_constant("true")].val = TypedValue::from_value(Value::Bool(true)); + self.constants[get_builtin_constant("false")].val = TypedValue::from_value(Value::Bool(false)); } pub fn add_all_files_in_directory(&mut self, directory : &PathBuf, info_mngr : &mut ExtraInfoManager) { @@ -128,6 +140,9 @@ impl Linker { for (_, typ) in &mut self.types { typ.link_info.reset_to(AFTER_INITIAL_PARSE_CP); } + for (_, cst) in &mut self.constants { + cst.link_info.reset_to(AFTER_INITIAL_PARSE_CP); + } if config().early_exit == EarlyExitUpTo::Initialize {return} flatten_all_modules(self); diff --git a/src/dev_aid/lsp/hover_info.rs b/src/dev_aid/lsp/hover_info.rs index a80cb74..46a2ba8 100644 --- a/src/dev_aid/lsp/hover_info.rs +++ b/src/dev_aid/lsp/hover_info.rs @@ -202,9 +202,8 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec { - if let Some(link_info) = linker.get_link_info(global) { - hover.documentation_link_info(link_info); - } + let link_info = linker.get_link_info(global); + hover.documentation_link_info(link_info); hover.sus_code(format!("{}", linker.get_full_name(global))); match global { NameElem::Module(md_uuid) => { diff --git a/src/dev_aid/lsp/mod.rs b/src/dev_aid/lsp/mod.rs index 15550b7..8069464 100644 --- a/src/dev_aid/lsp/mod.rs +++ b/src/dev_aid/lsp/mod.rs @@ -219,7 +219,6 @@ fn initialize_all_files(init_params: &InitializeParams) -> (Linker, LSPFileManag fn gather_completions(linker: &Linker, file_id: FileUUID, position: usize) -> Vec { let mut result = Vec::new(); - use crate::linker::Linkable; for (_, m) in &linker.modules { result.push(CompletionItem { label: m.link_info.name.to_string(), @@ -241,14 +240,14 @@ fn gather_completions(linker: &Linker, file_id: FileUUID, position: usize) -> Ve } for (_, c) in &linker.constants { result.push(CompletionItem { - label: c.get_name().to_string(), + label: c.link_info.name.to_string(), kind: Some(CompletionItemKind::CONSTANT), ..Default::default() }); } for (_, t) in &linker.types { result.push(CompletionItem { - label: t.get_name().to_string(), + label: t.link_info.name.to_string(), kind: Some(CompletionItemKind::STRUCT), ..Default::default() }); @@ -397,9 +396,8 @@ fn handle_request( goto_definition_list.push((template_arg.name_span, link_info.file)) } LocationInfo::Global(id) => { - if let Some(link_info) = linker.get_link_info(id) { - goto_definition_list.push((link_info.name_span, link_info.file)); - } + let link_info = linker.get_link_info(id); + goto_definition_list.push((link_info.name_span, link_info.file)); } LocationInfo::Port(_sm, md, port_id) => { goto_definition_list.push((md.ports[port_id].name_span, md.link_info.file)); diff --git a/src/dev_aid/lsp/tree_walk.rs b/src/dev_aid/lsp/tree_walk.rs index 478024f..b22051d 100644 --- a/src/dev_aid/lsp/tree_walk.rs +++ b/src/dev_aid/lsp/tree_walk.rs @@ -216,7 +216,7 @@ impl<'linker, Visitor: FnMut(Span, LocationInfo<'linker>), Pruner: Fn(Span) -> b let target_name_elem = NameElem::from(global.id); self.visit(global.total_span, LocationInfo::Global(target_name_elem)); for (id, template_arg) in global.template_args.iter_valids() { - let target_link_info = self.linker.get_link_info(target_name_elem).unwrap(); + let target_link_info = self.linker.get_link_info(target_name_elem); self.visit( template_arg.name_span, LocationInfo::TemplateInput( @@ -442,6 +442,15 @@ impl<'linker, Visitor: FnMut(Span, LocationInfo<'linker>), Pruner: Fn(Span) -> b } } + fn walk_constant(&mut self, cst_id: ConstantUUID) { + let cst = &self.linker.constants[cst_id]; + if !(self.should_prune)(cst.link_info.span) { + self.walk_name_and_template_arguments(NameElem::Constant(cst_id), &cst.link_info); + + println!("TODO constant instructions") + } + } + fn walk_file(&mut self, file: &'linker FileData) { for global in &file.associated_values { match *global { @@ -451,8 +460,8 @@ impl<'linker, Visitor: FnMut(Span, LocationInfo<'linker>), Pruner: Fn(Span) -> b NameElem::Type(typ_id) => { self.walk_struct(typ_id); } - NameElem::Constant(_) => { - todo!() + NameElem::Constant(cst_id) => { + self.walk_constant(cst_id); } } } diff --git a/src/flattening/flatten.rs b/src/flattening/flatten.rs index 2560d92..0238c12 100644 --- a/src/flattening/flatten.rs +++ b/src/flattening/flatten.rs @@ -189,10 +189,16 @@ impl core::fmt::Display for BinaryOperator { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum GenerativeKind { + PlainGenerative, + ForLoopGenerative +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum DeclarationContext { IO{is_input : bool}, - ForLoopGenerative, + Generative(GenerativeKind), TemplateGenerative(TemplateID), PlainWire, StructField @@ -235,7 +241,7 @@ struct FlatteningContext<'l, 'errs> { default_declaration_context: DeclarationContext } -impl<'l, 'errs : 'l> FlatteningContext<'l, 'errs> { +impl<'l, 'errs> FlatteningContext<'l, 'errs> { fn flatten_template_inputs(&mut self, cursor: &mut Cursor) { let mut template_inputs_to_visit = self.working_on_link_info.template_arguments.id_range().into_iter(); if cursor.optional_field(field!("template_declaration_arguments")) { @@ -583,9 +589,9 @@ impl<'l, 'errs : 'l> FlatteningContext<'l, 'errs> { } DeclarationPortInfo::RegularPort { is_input, port_id: PortID::PLACEHOLDER } } - DeclarationContext::ForLoopGenerative => { + DeclarationContext::Generative(_) => { if let Some((_, io_span)) = io_kw { - self.errors.error(io_span, "Cannot declare 'input' or 'output' to the iterator of a for loop"); + self.errors.error(io_span, "Cannot declare 'input' or 'output' to declarations in a generative context"); } DeclarationPortInfo::NotPort } @@ -635,7 +641,7 @@ impl<'l, 'errs : 'l> FlatteningContext<'l, 'errs> { } } } - DeclarationContext::ForLoopGenerative | DeclarationContext::TemplateGenerative(_) => { + DeclarationContext::Generative(_) | DeclarationContext::TemplateGenerative(_) => { if let Some((_, modifier_span)) = declaration_modifiers { self.errors.error(modifier_span, "Cannot add modifiers to implicitly generative declarations"); } @@ -1282,7 +1288,7 @@ impl<'l, 'errs : 'l> FlatteningContext<'l, 'errs> { cursor.go_down_no_check(|cursor| { let loop_var_decl_frame = self.local_variable_context.new_frame(); cursor.field(field!("for_decl")); - let loop_var_decl = self.flatten_declaration::(DeclarationContext::ForLoopGenerative, true, true, cursor); + let loop_var_decl = self.flatten_declaration::(DeclarationContext::Generative(GenerativeKind::ForLoopGenerative), true, true, cursor); cursor.field(field!("from")); let (start, start_is_generative) = self.flatten_expr(cursor); @@ -1467,14 +1473,38 @@ impl<'l, 'errs : 'l> FlatteningContext<'l, 'errs> { let _ = cursor.optional_field(field!("extern_marker")); // Skip because we know this from initialization. cursor.field(field!("object_type")); + + // We parse this one a bit strangely. Just because visually it looks nicer to have the template arguments after + // const int[SIZE] range #(int SIZE) {} + let const_type_cursor = (cursor.kind() == kind!("const_and_type")).then(|| cursor.clone()); let name_span = cursor.field_span(field!("name"), kind!("identifier")); self.flatten_template_inputs(cursor); let module_name = &self.globals.file_data.file_text[name_span]; println!("TREE SITTER module! {module_name}"); - // Interface is allocated in self - if cursor.optional_field(field!("interface_ports")) { - self.flatten_interface_ports(cursor); + + if let Some(mut const_type_cursor) = const_type_cursor { + let decl_span = const_type_cursor.span(); + const_type_cursor.go_down(kind!("const_and_type"), |const_type_cursor| { + const_type_cursor.field(field!("const_type")); + let typ_expr = self.flatten_type(const_type_cursor); + let module_output_decl = self.instructions.alloc(Instruction::Declaration(Declaration{ + typ_expr, + typ: self.type_alloc.alloc_unset_type(DomainAllocOption::Generative), + decl_span, + name_span, + name: module_name.to_string(), + declaration_runtime_depth: OnceCell::new(), + read_only: false, + declaration_itself_is_not_written_to: true, + is_port: DeclarationPortInfo::NotPort, + identifier_type: IdentifierType::Generative, + latency_specifier: None, + documentation: const_type_cursor.extract_gathered_comments(), + })); + + self.alloc_local_name(name_span, NamedLocal::Declaration(module_output_decl)); + }); } cursor.field(field!("block")); @@ -1511,7 +1541,7 @@ pub fn flatten_all_modules(linker: &mut Linker) { (UUIDRange::empty().into_iter(), typ.fields.id_range().into_iter(), DeclarationContext::StructField) } NameElem::Constant(const_uuid) => { - todo!("TODO Constant flattening") + (UUIDRange::empty().into_iter(), UUIDRange::empty().into_iter(), DeclarationContext::Generative(GenerativeKind::PlainGenerative)) } }; @@ -1521,7 +1551,7 @@ pub fn flatten_all_modules(linker: &mut Linker) { fields_to_visit, default_declaration_context, errors: &globals.errors, - working_on_link_info: linker.get_link_info(global_obj).unwrap(), + working_on_link_info: linker.get_link_info(global_obj), instructions: FlatAlloc::new(), type_alloc: TypingAllocator { type_variable_alloc: UUIDAllocator::new(), domain_variable_alloc: UUIDAllocator::new() }, named_domain_alloc: UUIDAllocator::new(), @@ -1600,7 +1630,15 @@ pub fn flatten_all_modules(linker: &mut Linker) { &mut typ.link_info } NameElem::Constant(const_uuid) => { - todo!("TODO Constant flattening") + let cst = &mut linker.constants[const_uuid]; + + cst.output_decl = instructions.iter().find(|(_decl_id, instr)| { + if let Instruction::Declaration(decl) = instr { + decl.name_span == cst.link_info.name_span + } else {false} + }).unwrap().0; + + &mut cst.link_info } }; diff --git a/src/flattening/initialization.rs b/src/flattening/initialization.rs index aa79b01..ad3d3d0 100644 --- a/src/flattening/initialization.rs +++ b/src/flattening/initialization.rs @@ -2,10 +2,11 @@ use arrayvec::ArrayVec; use sus_proc_macro::{field, kind, kw}; use crate::errors::ErrorStore; -use crate::linker::{IsExtern, AFTER_INITIAL_PARSE_CP}; +use crate::linker::{IsExtern, NamedConstant, AFTER_INITIAL_PARSE_CP}; use crate::prelude::*; use crate::linker::{FileBuilder, LinkInfo, ResolvedGlobals}; +use crate::value::TypedValue; use crate::{file_position::FileText, flattening::Module, instantiation::InstantiationList}; use crate::typing::template::{ @@ -278,8 +279,8 @@ fn initialize_global_object(builder: &mut FileBuilder, parsing_errors: ErrorColl kw!("module") => { GlobalObjectKind::Module } - kw!("function") => { - GlobalObjectKind::Function + kind!("const_and_type") => { + GlobalObjectKind::Const } kw!("struct") => { GlobalObjectKind::Struct @@ -315,8 +316,8 @@ fn initialize_global_object(builder: &mut FileBuilder, parsing_errors: ErrorColl link_info.reabsorb_errors_globals((parsing_errors, ResolvedGlobals::empty()), AFTER_INITIAL_PARSE_CP); match global_obj_kind { - GlobalObjectKind::Module | GlobalObjectKind::Function => { - let md = Module { + GlobalObjectKind::Module => { + builder.add_module(Module { link_info, instructions: FlatAlloc::new(), ports: ctx.ports, @@ -324,18 +325,22 @@ fn initialize_global_object(builder: &mut FileBuilder, parsing_errors: ErrorColl domains: FlatAlloc::new(), interfaces: ctx.interfaces, instantiations: InstantiationList::new(), - }; - - builder.add_module(md); + }); } GlobalObjectKind::Struct => { - let typ = StructType { + builder.add_type(StructType { link_info, fields: ctx.fields, instructions: FlatAlloc::new() - }; - - builder.add_type(typ); + }); + } + GlobalObjectKind::Const => { + builder.add_const(NamedConstant { + link_info, + instructions: FlatAlloc::new(), + output_decl: FlatID::PLACEHOLDER, + val: TypedValue::make_placeholder(), + }); } } } diff --git a/src/flattening/mod.rs b/src/flattening/mod.rs index 610a62b..4d63639 100644 --- a/src/flattening/mod.rs +++ b/src/flattening/mod.rs @@ -30,7 +30,7 @@ use crate::typing::{ #[derive(Debug)] pub enum GlobalObjectKind { Module, - Function, + Const, Struct } diff --git a/src/flattening/parser.rs b/src/flattening/parser.rs index 5fdb229..f53334c 100644 --- a/src/flattening/parser.rs +++ b/src/flattening/parser.rs @@ -31,6 +31,7 @@ fn print_current_node_indented<'ft>(file_text: &'ft FileText, cursor: &TreeCurso node_name } +#[derive(Clone)] pub struct Cursor<'t> { cursor: TreeCursor<'t>, file_text: &'t FileText, diff --git a/src/flattening/typechecking.rs b/src/flattening/typechecking.rs index ca09afb..41be48f 100644 --- a/src/flattening/typechecking.rs +++ b/src/flattening/typechecking.rs @@ -6,7 +6,7 @@ use crate::typing::type_inference::{FailedUnification, HindleyMilner}; use crate::debug::SpanDebugger; use crate::linker::{ - GlobalResolver, Linkable, NameElem, AFTER_TYPECHECK_CP + GlobalResolver, NameElem, AFTER_TYPECHECK_CP }; use crate::typing::{ @@ -112,19 +112,19 @@ impl<'l, 'errs> TypeCheckingContext<'l, 'errs> { fn get_wire_ref_declaration_point( &self, wire_ref_root: &WireReferenceRoot, - ) -> Option { + ) -> SpanFile { match wire_ref_root { WireReferenceRoot::LocalDecl(id, _) => { let decl_root = self.working_on.instructions[*id].unwrap_wire_declaration(); - Some((decl_root.decl_span, self.errors.file)) + (decl_root.decl_span, self.errors.file) } WireReferenceRoot::NamedConstant(cst, _) => { let linker_cst = &self.globals[*cst]; - linker_cst.get_span_file() + linker_cst.link_info.get_span_file() } WireReferenceRoot::SubModulePort(port) => { let (decl, file) = self.get_decl_of_module_port(port.port, port.submodule_decl); - Some((decl.decl_span, file)) + (decl.decl_span, file) } } } diff --git a/src/instantiation/execute.rs b/src/instantiation/execute.rs index 0835cc9..6fbe9df 100644 --- a/src/instantiation/execute.rs +++ b/src/instantiation/execute.rs @@ -12,7 +12,7 @@ use num::BigInt; use crate::flattening::*; use crate::value::{compute_binary_op, compute_unary_op, TypedValue, Value}; -use crate::{linker::NamedConstant, util::add_to_small_set}; +use crate::util::add_to_small_set; use crate::typing::{ abstract_type::DomainType, @@ -203,9 +203,9 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { SubModuleOrWire::SubModule(_) => unreachable!(), SubModuleOrWire::Unnasigned => unreachable!(), }, - WireReferenceRoot::NamedConstant(cst, _) => { - let NamedConstant::Builtin { name: _, val } = &self.linker.constants[*cst]; - RealWireRefRoot::Constant(val.clone()) + WireReferenceRoot::NamedConstant(cst_id, _) => { + let cst = &self.linker.constants[*cst_id]; + RealWireRefRoot::Constant(cst.val.clone()) } WireReferenceRoot::SubModulePort(port) => { return self.instantiate_port_wire_ref_root( diff --git a/src/linker/mod.rs b/src/linker/mod.rs index 7b246b2..106dad6 100644 --- a/src/linker/mod.rs +++ b/src/linker/mod.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use crate::{flattening::Instruction, prelude::*}; pub mod checkpoint; mod resolver; @@ -45,7 +45,6 @@ pub const fn get_builtin_type(name: &'static str) -> TypeUUID { } } -#[allow(dead_code)] pub const fn get_builtin_constant(name: &'static str) -> ConstantUUID { if let Some(is_constant) = const_str_position_in_tuples(name, &BUILTIN_CONSTANTS) { ConstantUUID::from_hidden_value(is_constant) @@ -118,38 +117,27 @@ impl LinkInfo { format!("::{}", self.name) } pub fn get_span_file(&self) -> SpanFile { - (self.span, self.file) + (self.name_span, self.file) } } pub struct LinkingErrorLocation { pub named_type: &'static str, pub full_name: String, - pub location: Option, -} - -pub trait Linkable { - fn get_name(&self) -> &str; - fn get_full_name(&self) -> String { - format!("::{}", self.get_name()) - } - fn get_linking_error_location(&self) -> LinkingErrorLocation; - fn get_link_info(&self) -> Option<&LinkInfo>; - fn get_span_file(&self) -> Option { - self.get_link_info().map(|l| (l.span, l.file)) - } + pub location: SpanFile, } #[derive(Debug)] -pub enum NamedConstant { - Builtin { name: &'static str, val: TypedValue }, +pub struct NamedConstant { + pub link_info: LinkInfo, + pub instructions: FlatAlloc, + pub output_decl: FlatID, + pub val: TypedValue } impl NamedConstant { pub fn get_concrete_type(&self) -> &ConcreteType { - match self { - NamedConstant::Builtin { name: _, val } => &val.typ, - } + &self.val.typ } pub fn get_full_type(&self) -> FullType { FullType { @@ -158,45 +146,7 @@ impl NamedConstant { } } pub fn get_value(&self) -> &TypedValue { - match self { - NamedConstant::Builtin { name: _, val } => &val, - } - } -} - -impl Linkable for NamedConstant { - fn get_name(&self) -> &'static str { - match self { - NamedConstant::Builtin { name, val: _ } => name, - } - } - fn get_linking_error_location(&self) -> LinkingErrorLocation { - LinkingErrorLocation { - named_type: "Builtin Constant", - full_name: self.get_full_name(), - location: None, - } - } - fn get_link_info(&self) -> Option<&LinkInfo> { - match self { - NamedConstant::Builtin { name: _, val: _ } => None, - } - } -} - -impl Linkable for StructType { - fn get_name(&self) -> &str { - &self.link_info.name - } - fn get_linking_error_location(&self) -> LinkingErrorLocation { - LinkingErrorLocation { - named_type: "Struct", - full_name: self.link_info.get_full_name(), - location: Some((self.link_info.name_span, self.link_info.file)), - } - } - fn get_link_info(&self) -> Option<&LinkInfo> { - Some(&self.link_info) + &self.val } } @@ -250,105 +200,71 @@ pub struct Linker { impl Linker { pub fn new() -> Linker { - let mut result = Linker { + Linker { types: ArenaAllocator::new(), modules: ArenaAllocator::new(), constants: ArenaAllocator::new(), files: ArenaAllocator::new(), global_namespace: HashMap::new(), - }; - - fn add_known_unique_name(result: &mut Linker, name: String, new_obj_id: NameElem) { - let already_exisits = result - .global_namespace - .insert(name.into(), NamespaceElement::Global(new_obj_id)); - assert!(already_exisits.is_none()); - } - - for (name, val) in BUILTIN_CONSTANTS { - let id = result.constants.alloc(NamedConstant::Builtin { - name, - val: TypedValue::from_value(val), - }); - add_known_unique_name(&mut result, name.into(), NameElem::Constant(id)); } - - result } - pub fn get_link_info(&self, global: NameElem) -> Option<&LinkInfo> { + pub fn get_link_info(&self, global: NameElem) -> &LinkInfo { match global { - NameElem::Module(md_id) => Some(&self.modules[md_id].link_info), - NameElem::Type(typ_id) => Some(&self.types[typ_id].link_info), - NameElem::Constant(_) => { - None // Can't define constants yet - } + NameElem::Module(md_id) => &self.modules[md_id].link_info, + NameElem::Type(typ_id) => &self.types[typ_id].link_info, + NameElem::Constant(cst_id) => &self.constants[cst_id].link_info } } pub fn get_link_info_mut<'l>( modules: &'l mut ArenaAllocator, types: &'l mut ArenaAllocator, + constants: &'l mut ArenaAllocator, global: NameElem - ) -> Option<&'l mut LinkInfo> { + ) -> &'l mut LinkInfo { match global { - NameElem::Module(md_id) => Some(&mut modules[md_id].link_info), - NameElem::Type(typ_id) => Some(&mut types[typ_id].link_info), - NameElem::Constant(_) => { - None // Can't define constants yet - } + NameElem::Module(md_id) => &mut modules[md_id].link_info, + NameElem::Type(typ_id) => &mut types[typ_id].link_info, + NameElem::Constant(cst_id) => &mut constants[cst_id].link_info } } pub fn get_full_name(&self, global: NameElem) -> String { match global { NameElem::Module(id) => self.modules[id].link_info.get_full_name(), - NameElem::Type(id) => self.types[id].get_full_name(), - NameElem::Constant(id) => self.constants[id].get_full_name(), + NameElem::Type(id) => self.types[id].link_info.get_full_name(), + NameElem::Constant(id) => self.constants[id].link_info.get_full_name(), } } fn get_linking_error_location(&self, global: NameElem) -> LinkingErrorLocation { - match global { - NameElem::Module(id) => { - let md = &self.modules[id]; - LinkingErrorLocation { - named_type: "Module", - full_name: md.link_info.get_full_name(), - location: Some((md.link_info.name_span, md.link_info.file)), - } - } - NameElem::Type(id) => self.types[id].get_linking_error_location(), - NameElem::Constant(id) => self.constants[id].get_linking_error_location(), + let named_type = match global { + NameElem::Module(_) => "Module", + NameElem::Type(_) => "Struct", + NameElem::Constant(_) => "Constant" + }; + let link_info = self.get_link_info(global); + LinkingErrorLocation { + named_type, + full_name: link_info.get_full_name(), + location: link_info.get_span_file(), } } - fn for_all_duplicate_declaration_errors( - &self, - file_uuid: FileUUID, - f: &mut F, - ) { + fn for_all_duplicate_declaration_errors(&self, file_uuid: FileUUID, f: &mut F) { // Conflicting Declarations for item in &self.global_namespace { let NamespaceElement::Colission(colission) = &item.1 else { continue; }; - let infos: Vec> = + let infos: Vec<&LinkInfo> = colission.iter().map(|id| self.get_link_info(*id)).collect(); for (idx, info) in infos.iter().enumerate() { - let Some(info) = info else { continue }; // Is not a builtin - if info.file != file_uuid { - continue; - } // Not for this file + if info.file != file_uuid {continue} let mut conflict_infos = Vec::new(); - let mut builtin_conflict = false; for (idx_2, conflicts_with) in infos.iter().enumerate() { if idx_2 == idx { continue; } - if let Some(conflicts_with) = conflicts_with { - conflict_infos.push(conflicts_with); - } else { - assert!(!builtin_conflict); - builtin_conflict = true; - } + conflict_infos.push(conflicts_with); } let this_object_name = &info.name; let infos = conflict_infos @@ -359,11 +275,9 @@ impl Linker { info: "Conflicts with".to_owned(), }) .collect(); - let reason = if builtin_conflict { - format!("Cannot redeclare the builtin '{this_object_name}'") - } else { - format!("'{this_object_name}' conflicts with other declarations:") - }; + + let reason = format!("'{this_object_name}' conflicts with other declarations:"); + f(&CompileError { position: info.name_span, reason, @@ -481,9 +395,7 @@ pub struct FileBuilder<'linker> { associated_values: &'linker mut Vec, global_namespace: &'linker mut HashMap, modules: &'linker mut ArenaAllocator, - #[allow(dead_code)] types: &'linker mut ArenaAllocator, - #[allow(dead_code)] constants: &'linker mut ArenaAllocator, } @@ -521,4 +433,11 @@ impl<'linker> FileBuilder<'linker> { self.associated_values.push(new_type_uuid); self.add_name(type_name, new_type_uuid); } + + pub fn add_const(&mut self, cst: NamedConstant) { + let const_name = cst.link_info.name.clone(); + let new_const_uuid = NameElem::Constant(self.constants.alloc(cst)); + self.associated_values.push(new_const_uuid); + self.add_name(const_name, new_const_uuid); + } } diff --git a/src/linker/resolver.rs b/src/linker/resolver.rs index 4d5b3a3..5926c18 100644 --- a/src/linker/resolver.rs +++ b/src/linker/resolver.rs @@ -47,7 +47,7 @@ pub struct GlobalResolver<'linker> { impl<'linker> GlobalResolver<'linker> { pub fn take_errors_globals(linker: &mut Linker, global_obj: NameElem) -> (ErrorStore, ResolvedGlobals) { - let obj_link_info = Linker::get_link_info_mut(&mut linker.modules, &mut linker.types, global_obj).unwrap(); + let obj_link_info = Linker::get_link_info_mut(&mut linker.modules, &mut linker.types, &mut linker.constants, global_obj); let errors = obj_link_info.errors.take(); let resolved_globals = obj_link_info.resolved_globals.take(); @@ -55,7 +55,7 @@ impl<'linker> GlobalResolver<'linker> { (errors, resolved_globals) } pub fn new(linker: &'linker Linker, global_obj: NameElem, errors_globals: (ErrorStore, ResolvedGlobals)) -> Self { - let obj_link_info = linker.get_link_info(global_obj).unwrap(); + let obj_link_info = linker.get_link_info(global_obj); let file_data = &linker.files[obj_link_info.file]; @@ -91,18 +91,10 @@ impl<'linker> GlobalResolver<'linker> { for collider_global in coll.iter() { let err_loc = self.linker.get_linking_error_location(*collider_global); - if let Some(span_file) = err_loc.location { - err_ref.info( - span_file, - format!("{} {} declared here", err_loc.named_type, err_loc.full_name), - ); - } else { - // Kinda hacky, point the 'builtin' back to the declaration location because builtins don't have a location - err_ref.info_same_file( - name_span, - format!("{} {}", err_loc.named_type, err_loc.full_name), - ); - } + err_ref.info( + err_loc.location, + format!("{} {} declared here", err_loc.named_type, err_loc.full_name), + ); } None @@ -134,9 +126,7 @@ impl<'linker> GlobalResolver<'linker> { global_ref.total_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"); - } + err_ref.info(info.location, "Defined here"); } } diff --git a/src/to_string.rs b/src/to_string.rs index 6fbfab6..bab88c0 100644 --- a/src/to_string.rs +++ b/src/to_string.rs @@ -18,7 +18,6 @@ use std::{ ops::Index, }; -use crate::linker::Linkable; use std::fmt::Write; use std::ops::Deref; @@ -53,7 +52,7 @@ impl WrittenType { match self { WrittenType::Error(_) => "{error}".to_owned(), WrittenType::TemplateVariable(_, id) => template_names.get_template_name(*id).to_owned(), - WrittenType::Named(named_type) => linker_types[named_type.id].get_full_name(), + WrittenType::Named(named_type) => linker_types[named_type.id].link_info.get_full_name(), WrittenType::Array(_, sub) => { sub.deref().0.to_string(linker_types, template_names) + "[]" } @@ -74,7 +73,7 @@ impl AbstractType { AbstractType::Error => "{error}".to_owned(), AbstractType::Unknown(id) => format!("{id:?}"), AbstractType::Template(id) => template_names.get_template_name(*id).to_owned(), - AbstractType::Named(id) => linker_types[*id].get_full_name(), + AbstractType::Named(id) => linker_types[*id].link_info.get_full_name(), AbstractType::Array(sub) => sub.deref().to_string(linker_types, template_names) + "[]", } } @@ -86,7 +85,7 @@ impl ConcreteType { linker_types: &TypVec, ) -> String { match self { - ConcreteType::Named(name) => linker_types[*name].get_full_name(), + ConcreteType::Named(name) => linker_types[*name].link_info.get_full_name(), ConcreteType::Array(arr_box) => { let (elem_typ, arr_size) = arr_box.deref(); format!( diff --git a/src/value.rs b/src/value.rs index fcd4b95..bc0aca6 100644 --- a/src/value.rs +++ b/src/value.rs @@ -178,6 +178,12 @@ impl TypedValue { value: Value::Integer(i), } } + pub fn make_placeholder() -> Self { + Self { + typ: ConcreteType::Error, + value: Value::Error + } + } /// panics if the value can't be typed. pub fn from_value(value: Value) -> Self { Self { diff --git a/stl/core.sus b/stl/core.sus index b108484..3d4b3e1 100644 --- a/stl/core.sus +++ b/stl/core.sus @@ -19,10 +19,15 @@ __builtin__ module BitsToInt { interface IntToBits : bool[32] bits'0 -> int value'0 } -// For now these two must be in this order, because they're constants in the code. +// For now these builtin declarations must be in this order, because they're constants in the code. +// We'll get a better system for this at some point +// The decider of truth and falsity __builtin__ struct bool {} - +// An integer of variable size. Right now it's not implemented yet, so this is just a 32-bit int. __builtin__ struct int {} - +// True, as in '1' +__builtin__ const bool true {} +// False, as in '0' +__builtin__ const bool false {} diff --git a/test.sus b/test.sus index 646a51c..0e6105e 100644 --- a/test.sus +++ b/test.sus @@ -933,3 +933,7 @@ module useModuleWithBadInterface { xyz[3] = true } + +module check_qzdqzz { + gen bool b = false +} diff --git a/test.sus_output.txt b/test.sus_output.txt index b097da2..1d90d1f 100644 --- a/test.sus_output.txt +++ b/test.sus_output.txt @@ -20,6 +20,8 @@ TREE SITTER module! IntToBits TREE SITTER module! BitsToInt TREE SITTER module! bool TREE SITTER module! int +TREE SITTER module! true +TREE SITTER module! false TREE SITTER module! example_md TREE SITTER module! multiply_add TREE SITTER module! test_pow17 diff --git a/tree-sitter-sus b/tree-sitter-sus index 63f2a4e..3fb461d 160000 --- a/tree-sitter-sus +++ b/tree-sitter-sus @@ -1 +1 @@ -Subproject commit 63f2a4ef1c2e51abe8a6a18df74b120898bf4d24 +Subproject commit 3fb461dbaf2f90d0dae8bbbfbffa876eba04070e