From 43b691be2cc8c07767663a3ddfd25c7387ac167d Mon Sep 17 00:00:00 2001 From: Lennart Van Hirtum Date: Tue, 19 Dec 2023 13:03:10 +0100 Subject: [PATCH] Removed UUID::INVALID --- src/arena_alloc.rs | 27 ++++----------------------- src/flattening.rs | 30 ++++++++++++++---------------- src/linker.rs | 2 +- src/typing.rs | 6 +++--- 4 files changed, 22 insertions(+), 43 deletions(-) diff --git a/src/arena_alloc.rs b/src/arena_alloc.rs index a0c78d7..98b53f0 100644 --- a/src/arena_alloc.rs +++ b/src/arena_alloc.rs @@ -2,6 +2,9 @@ use std::{ops::{IndexMut, Index}, marker::PhantomData, iter::Enumerate, fmt}; use crate::block_vector::{BlockVec, BlockVecIterMut, BlockVecIter}; + +// TODO add custom niche for more efficient Options, wait until custom niches are stabilized (https://internals.rust-lang.org/t/nonmaxusize-and-niche-value-optimisation/19661) +// Maybe use NonZeroUsize (https://doc.rust-lang.org/std/num/struct.NonZeroUsize.html) #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct UUID(usize, PhantomData); @@ -12,25 +15,11 @@ pub trait UUIDMarker { impl fmt::Debug for UUID { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(IndexMarker::DISPLAY_NAME)?; - if self.0 == Self::INVALID.0 { - f.write_str("INV") - } else { - self.0.fmt(f) - } - } -} - -impl Default for UUID { - fn default() -> Self { - Self::INVALID + self.0.fmt(f) } } -const INVALID_UUID_VALUE : usize = usize::MAX; - impl UUID { - pub const INVALID : Self = UUID(INVALID_UUID_VALUE, PhantomData); - pub const fn from_hidden_value(v : usize) -> Self { UUID(v, PhantomData) } @@ -97,7 +86,6 @@ impl Index> for ArenaAllocator) -> &Self::Output { - assert!(uuid != INVALID_UUID_VALUE, "Invalid UUID passed to index"); assert!(self.data[uuid].is_some()); self.data[uuid].as_ref().unwrap() } @@ -105,7 +93,6 @@ impl Index> for ArenaAllocator IndexMut> for ArenaAllocator { fn index_mut(&mut self, UUID(uuid, _): UUID) -> &mut Self::Output { - assert!(uuid != INVALID_UUID_VALUE, "Invalid UUID passed to index_mut"); assert!(self.data[uuid].is_some()); self.data[uuid].as_mut().unwrap() } @@ -208,14 +195,12 @@ impl Index> for ArenaVector) -> &Self::Output { - assert!(uuid != INVALID_UUID_VALUE, "Invalid UUID passed to index"); self.data[uuid].as_ref().unwrap() } } impl IndexMut> for ArenaVector { fn index_mut(&mut self, UUID(uuid, _): UUID) -> &mut Self::Output { - assert!(uuid != INVALID_UUID_VALUE, "Invalid UUID passed to index_mut"); self.data[uuid].as_mut().unwrap() } } @@ -269,14 +254,12 @@ impl Index> for ListAllocator) -> &Self::Output { - assert!(uuid != INVALID_UUID_VALUE, "Invalid UUID passed to index"); &self.data[uuid] } } impl IndexMut> for ListAllocator { fn index_mut(&mut self, UUID(uuid, _): UUID) -> &mut Self::Output { - assert!(uuid != INVALID_UUID_VALUE, "Invalid UUID passed to index_mut"); &mut self.data[uuid] } } @@ -383,14 +366,12 @@ impl Index> for FlatAlloc) -> &Self::Output { - assert!(uuid != INVALID_UUID_VALUE, "Invalid UUID passed to index"); &self.data[uuid] } } impl IndexMut> for FlatAlloc { fn index_mut(&mut self, UUID(uuid, _): UUID) -> &mut Self::Output { - assert!(uuid != INVALID_UUID_VALUE, "Invalid UUID passed to index_mut"); &mut self.data[uuid] } } diff --git a/src/flattening.rs b/src/flattening.rs index 9642621..01ce05e 100644 --- a/src/flattening.rs +++ b/src/flattening.rs @@ -81,7 +81,7 @@ impl Instantiation { } struct FlatteningContext<'l, 'm, 'fl> { - decl_to_flat_map : FlatAlloc, + decl_to_flat_map : FlatAlloc, DeclIDMarker>, instantiations : &'fl ListAllocator, errors : &'fl ErrorCollector, @@ -153,7 +153,7 @@ impl<'l, 'm, 'fl> FlatteningContext<'l, 'm, 'fl> { let (name_expr, name_expr_span) = &func_and_args[0]; // Function name is always there let func_instantiation_id = match name_expr { Expression::Named(LocalOrGlobal::Local(l)) => { - self.decl_to_flat_map[*l] + self.decl_to_flat_map[*l].unwrap() } Expression::Named(LocalOrGlobal::Global(g)) => { let module_ref = self.module.link_info.global_references[*g]; @@ -205,8 +205,7 @@ impl<'l, 'm, 'fl> FlatteningContext<'l, 'm, 'fl> { fn flatten_single_expr(&self, (expr, expr_span) : &SpanExpression, condition : Option) -> Option { let single_connection_side = match expr { Expression::Named(LocalOrGlobal::Local(l)) => { - assert!(self.decl_to_flat_map[*l] != UUID::INVALID); - self.decl_to_flat_map[*l] + self.decl_to_flat_map[*l].unwrap() } Expression::Named(LocalOrGlobal::Global(g)) => { let r = self.module.link_info.global_references[*g]; @@ -260,7 +259,7 @@ impl<'l, 'm, 'fl> FlatteningContext<'l, 'm, 'fl> { fn flatten_assignable_expr(&self, (expr, span) : &SpanAssignableExpression, condition : Option) -> Option { Some(match expr { AssignableExpression::Named{local_idx} => { - let root = self.decl_to_flat_map[*local_idx]; + let root = self.decl_to_flat_map[*local_idx].unwrap(); let WireSource::NamedWire { read_only, identifier_type : _, decl_id : _ } = &self.instantiations[root].extract_wire().inst else { unreachable!("Attempting to assign to a Instantiation::PlainWire") }; @@ -300,14 +299,11 @@ impl<'l, 'm, 'fl> FlatteningContext<'l, 'm, 'fl> { Statement::Declaration(decl_id) => { let decl = &self.module.declarations[*decl_id]; - let typ = self.map_to_type(&decl.typ.0, &self.module.link_info.global_references) else {continue;}; + let typ = self.map_to_type(&decl.typ.0, &self.module.link_info.global_references); let typ_span = decl.typ.1; - let decl_typ_root_reference = typ.get_root(); - let inst = if decl_typ_root_reference == UUID::INVALID { - Instantiation::Error // Error's covered by linker - } else { - match &self.linker.links.globals[decl_typ_root_reference] { + let inst = if let Some(root_ref) = typ.get_root() { + match &self.linker.links.globals[root_ref] { Named::Constant(c) => { self.errors.error_basic(typ_span, format!("This should be the type of a declaration, but it refers to the constant '{}'", c.get_full_name())); Instantiation::Error @@ -326,10 +322,12 @@ impl<'l, 'm, 'fl> FlatteningContext<'l, 'm, 'fl> { Instantiation::Wire(WireInstance{typ, span : typ_span, inst : WireSource::NamedWire{read_only : false, identifier_type : decl.identifier_type, decl_id : Some(*decl_id)}}) } } + } else { + Instantiation::Error // Error's covered by linker }; let wire_id = self.instantiations.alloc(inst); - self.decl_to_flat_map[*decl_id] = wire_id; + self.decl_to_flat_map[*decl_id] = Some(wire_id); } Statement::If{condition : condition_expr, then, els} => { let Some(if_statement_condition) = self.flatten_single_expr(condition_expr, condition) else {continue;}; @@ -444,7 +442,7 @@ impl FlattenedModule { Produces an initial FlattenedModule, in which the interface types have already been resolved. Must be further processed by flatten, but this requires all modules to have been Initial Flattened for dependency resolution */ - pub fn initialize_interfaces(linker : &Linker, module : &Module) -> (FlattenedInterface, FlattenedModule, FlatAlloc) { + pub fn initialize_interfaces(linker : &Linker, module : &Module) -> (FlattenedInterface, FlattenedModule, FlatAlloc, DeclIDMarker>) { let mut interface = FlattenedInterface::new(); let flat_mod = FlattenedModule { @@ -453,7 +451,7 @@ impl FlattenedModule { }; let mut context = FlatteningContext{ - decl_to_flat_map: module.declarations.iter().map(|_| UUID::INVALID).collect(), + decl_to_flat_map: module.declarations.iter().map(|_| None).collect(), instantiations: &flat_mod.instantiations, errors: &flat_mod.errors, linker, @@ -471,7 +469,7 @@ impl FlattenedModule { let wire_id = context.instantiations.alloc(Instantiation::Wire(WireInstance{typ : typ.clone(), span : decl.typ.1, inst : WireSource::NamedWire{read_only: is_input, identifier_type : decl.identifier_type, decl_id : Some(decl_id)}})); interface.interface_wires.push(FlattenedInterfacePort { wire_id, is_input, typ, port_name: decl.name.clone(), span: decl.span }); - context.decl_to_flat_map[decl_id] = wire_id; + context.decl_to_flat_map[decl_id] = Some(wire_id); } let decl_to_flat_map = context.decl_to_flat_map; @@ -484,7 +482,7 @@ impl FlattenedModule { The Generating Structure of the code is not yet executed. It is template-preserving */ - pub fn flatten(&self, module : &Module, linker : &Linker, decl_to_flat_map : FlatAlloc) { + pub fn flatten(&self, module : &Module, linker : &Linker, decl_to_flat_map : FlatAlloc, DeclIDMarker>) { let mut context = FlatteningContext { decl_to_flat_map : decl_to_flat_map, instantiations : &self.instantiations, diff --git a/src/linker.rs b/src/linker.rs index 5b10d21..275b0c2 100644 --- a/src/linker.rs +++ b/src/linker.rs @@ -515,7 +515,7 @@ impl Linker { // First create initial flattening for everything, to produce the necessary interfaces let mut interface_vec : Vec<(NamedUUID, FlattenedInterface, FlattenedModule)> = Vec::new(); - let mut initial_flat_vec : Vec<(NamedUUID, FlatAlloc)> = Vec::new(); + let mut initial_flat_vec : Vec<(NamedUUID, FlatAlloc, DeclIDMarker>)> = Vec::new(); for (id, named_object) in &self.links.globals { println!("Initializing Interface for {}", named_object.get_name()); if let Named::Module(md) = named_object { diff --git a/src/typing.rs b/src/typing.rs index 5fcf2de..af04f1c 100644 --- a/src/typing.rs +++ b/src/typing.rs @@ -39,10 +39,10 @@ impl Type { Type::Array(sub) => sub.deref().0.to_string(linker) + "[]", } } - pub fn get_root(&self) -> NamedUUID { + pub fn get_root(&self) -> Option { match self { - Type::Invalid => {unreachable!()} - Type::Named(name) => *name, + Type::Invalid => {None} + Type::Named(name) => Some(*name), Type::Array(sub) => sub.0.get_root(), } }