bitsy_lang/
types.rs

1use super::Context;
2use super::Expr;
3use super::Path;
4
5use std::sync::Arc;
6
7pub use crate::ast::WordLit; // re-export
8
9/// The bitwidth of a [`Type::Word`].
10pub type Width = u64;
11
12/// The length of a [`Type::Vec`].
13pub type Length = u64;
14
15/// A type classifier for [`crate::sim::Value`]s.
16#[derive(Clone, PartialEq)]
17pub enum Type {
18    /// An n-bit two's complement integer. Nominally unsigned. Written `Word<n>`.
19    Word(Width),
20    /// A n-element vector. Written `Vec<T, n>`.
21    Vec(Box<Type>, Length),
22    /// An optional value. Written `Valid<T>`.
23    Valid(Box<Type>),
24    /// A user-defined `enum`.
25    Enum(Arc<EnumTypeDef>),
26    /// A user-defined `struct`.
27    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/// A user-defined `enum` type.
65#[derive(Debug, Clone, PartialEq)]
66pub struct EnumTypeDef {
67    pub name: String,
68    pub values: Vec<(String, WordLit)>,
69}
70
71/// A user-defined `struct` type.
72#[derive(Debug, Clone, PartialEq)]
73pub struct StructTypeDef {
74    pub name: String,
75    pub fields: Vec<(String, Type)>,
76}
77
78/// A user-defined `fn` function.
79#[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        // TODO
120        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        // TODO
131        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}