1use super::Context;
2use super::Expr;
3use super::Path;
4
5use std::sync::Arc;
6
7pub use crate::ast::WordLit; pub type Width = u64;
11
12pub type Length = u64;
14
15#[derive(Clone, PartialEq)]
17pub enum Type {
18 Word(Width),
20 Vec(Box<Type>, Length),
22 Valid(Box<Type>),
24 Enum(Arc<EnumTypeDef>),
26 Struct(Arc<StructTypeDef>),
28}
29
30impl Type {
31 pub fn name(&self) -> &str {
32 match self {
33 Type::Word(_width) => "Word",
34 Type::Vec(_typ, _length) => "Vec",
35 Type::Valid(_typ) => "Valid",
36 Type::Enum(typedef) => &typedef.name,
37 Type::Struct(typedef) => &typedef.name,
38 }
39 }
40
41 pub fn word(w: Width) -> Type {
42 Type::Word(w)
43 }
44
45 pub fn vec(typ: Type, n: Length) -> Type {
46 Type::Vec(Box::new(typ), n)
47 }
48
49 pub fn valid(typ: Type) -> Type {
50 Type::Valid(Box::new(typ))
51 }
52
53 pub fn bitwidth(&self) -> Width {
54 match self {
55 Type::Word(n) => *n,
56 Type::Valid(typ) => typ.bitwidth() + 1,
57 Type::Vec(typ, n) => typ.bitwidth() * n,
58 Type::Enum(typedef) => typedef.bitwidth(),
59 Type::Struct(typedef) => typedef.bitwidth(),
60 }
61 }
62}
63
64#[derive(Debug, Clone, PartialEq)]
66pub struct EnumTypeDef {
67 pub name: String,
68 pub values: Vec<(String, WordLit)>,
69}
70
71#[derive(Debug, Clone, PartialEq)]
73pub struct StructTypeDef {
74 pub name: String,
75 pub fields: Vec<(String, Type)>,
76}
77
78#[derive(Debug, Clone)]
80pub struct FnDef {
81 pub name: String,
82 pub args: Vec<(String, Type)>,
83 pub ret: Type,
84 pub body: Arc<Expr>,
85}
86
87impl FnDef {
88 pub fn context(&self) -> Context<Path, Type> {
89 Context::from(self.args.iter().map(|(arg_name, arg_type)| (arg_name.to_string().into(), arg_type.clone())).collect::<Vec<_>>())
90 }
91}
92
93impl StructTypeDef {
94 pub fn bitwidth(&self) -> Width {
95 self.fields.iter().map(|(_name, typ)| typ.bitwidth()).sum()
96 }
97
98 pub fn type_of_field(&self, fieldname: &str) -> Option<Type> {
99 for (name, typ) in &self.fields {
100 if name == fieldname {
101 return Some(typ.clone())
102 }
103 }
104 None
105 }
106}
107
108impl EnumTypeDef {
109 pub fn value_of(&self, name: &str) -> Option<u64> {
110 for (other_name, WordLit(_w, value)) in &self.values {
111 if name == other_name {
112 return Some(*value);
113 }
114 }
115 None
116 }
117
118 pub fn bitwidth(&self) -> Width {
119 let mut max_width = None;
121 for (_name, value) in &self.values {
122 if let WordLit(Some(w), _n) = value {
123 if let Some(max_w) = max_width {
124 assert_eq!(*w, max_w);
125 } else {
126 max_width = Some(*w);
127 }
128 }
129 }
130 max_width.unwrap()
132 }
133}
134
135impl std::fmt::Debug for Type {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
137 match self {
138 Type::Word(n) => write!(f, "Word<{n}>"),
139 Type::Valid(typ) => write!(f, "Valid<{typ:?}>"),
140 Type::Vec(typ, n) => write!(f, "Vec<{typ:?}, {n}>"),
141 Type::Struct(typedef) => write!(f, "{}", typedef.name),
142 Type::Enum(typedef) => write!(f, "{}", typedef.name),
143 }
144 }
145}