/// Alias for &TypeStruct to reduce repetition /// and make futura migration to interning /// easier pub type Type<'ty> = &'ty TypeStruct<'ty>; pub struct TypeStruct<'ty> { kind: TypeKind<'ty>, } enum TypeKind<'ty> { /// Elaboration-time types ElabType(ElabKind), /// Signal/Wire of generic width Logic(ElabData<'ty>), /// UInt of generic width UInt(ElabData<'ty>), /// Callable Callable, } struct ElabData<'ty> { typ: Type<'ty>, value: ElabValue<'ty>, } enum ElabValue<'ty> { /// the value is not given and has to be inferred Infer, /// the value is given as some byte representation Concrete(ElabValueData<'ty>), } enum ElabValueData<'ty> { U32(u32), Bytes(&'ty [u8]), } /// Types that are only valid during Elaboration enum ElabKind { /// general, unsized number type Num, } /// Helper functions to create primitive types impl<'ty> TypeStruct<'ty> { /// a logic signal with inferred width pub fn logic_infer() -> Self { Self { kind: TypeKind::Logic(ElabData { typ: &TypeStruct { kind: TypeKind::ElabType(ElabKind::Num), }, value: ElabValue::Infer, }), } } /// a logic signal with known width pub fn logic_width(width: u32) -> Self { Self { kind: TypeKind::Logic(ElabData::from_u32(width)), } } /// return an elaboration number type pub fn elab_num() -> Self { Self { kind: TypeKind::ElabType(ElabKind::Num), } } pub fn bit_width(&self) -> Option { match &self.kind { // elab types are not representable in hardware TypeKind::ElabType(_) => None, TypeKind::Logic(data) => data.try_u32(), TypeKind::UInt(_) => todo!(), // callables are not representable in hardware TypeKind::Callable => None, } } pub fn genparam_count(&self) -> u32 { match self.kind { TypeKind::ElabType(_) => todo!(), TypeKind::Logic(_) => 1, TypeKind::UInt(_) => 1, TypeKind::Callable => todo!(), } } } /// Helper functions to create primitive elaboration values impl<'ty> ElabData<'ty> { /// an integer pub fn from_u32(val: u32) -> Self { Self { typ: &TypeStruct { kind: TypeKind::ElabType(ElabKind::Num), }, value: ElabValue::Concrete(ElabValueData::U32(val)), } } /// return Some(u32) if this is a number pub fn try_u32(&self) -> Option { // TODO: assert this is actually a number match self.value { ElabValue::Infer => None, ElabValue::Concrete(_) => todo!(), } } } pub fn make_primitives() -> Vec<(String, TypeStruct<'static>)> { vec![("Logic".to_string(), TypeStruct::logic_infer())] }