spade_types/
lib.rs

1pub mod meta_types;
2
3use num::BigInt;
4use serde::{Deserialize, Serialize};
5use spade_common::{
6    location_info::WithLocation,
7    name::{Identifier, NameID},
8    num_ext::InfallibleToBigInt,
9};
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12pub enum PrimitiveType {
13    Int,
14    Uint,
15    Clock,
16    Bool,
17    Bit,
18    Memory,
19    InOut,
20}
21
22impl std::fmt::Display for PrimitiveType {
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        let str = match self {
25            PrimitiveType::Int => "int",
26            PrimitiveType::Uint => "uint",
27            PrimitiveType::Clock => "clk",
28            PrimitiveType::Bool => "bool",
29            PrimitiveType::Bit => "bit",
30            PrimitiveType::Memory => "Memory",
31            PrimitiveType::InOut => "inout",
32        };
33        write!(f, "{str}")
34    }
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38pub enum ConcreteType {
39    Tuple(Vec<ConcreteType>),
40    Struct {
41        name: NameID,
42        is_port: bool,
43        members: Vec<(Identifier, ConcreteType)>,
44    },
45    Array {
46        inner: Box<ConcreteType>,
47        size: BigInt,
48    },
49    Enum {
50        options: Vec<(NameID, Vec<(Identifier, ConcreteType)>)>,
51    },
52    Single {
53        base: PrimitiveType,
54        params: Vec<ConcreteType>,
55    },
56    Integer(BigInt),
57    Bool(bool),
58    Backward(Box<ConcreteType>),
59    Wire(Box<ConcreteType>),
60}
61
62impl ConcreteType {
63    pub fn assume_struct(&self) -> (&NameID, &Vec<(Identifier, ConcreteType)>) {
64        match self {
65            ConcreteType::Struct {
66                name,
67                is_port: _,
68                members,
69            } => (name, members),
70            t => unreachable!("Assumed {} was a struct", t),
71        }
72    }
73
74    pub fn is_port(&self) -> bool {
75        match self {
76            ConcreteType::Tuple(inner) => inner.iter().any(Self::is_port),
77            ConcreteType::Struct {
78                name: _,
79                is_port,
80                members: _,
81            } => *is_port,
82            ConcreteType::Array { inner, size: _ } => inner.is_port(),
83            // Enums cannot be ports
84            ConcreteType::Enum { .. } => false,
85            ConcreteType::Single {
86                base: PrimitiveType::Memory,
87                ..
88            } => true,
89            ConcreteType::Single {
90                base: PrimitiveType::Clock,
91                ..
92            } => true,
93            ConcreteType::Single { .. } => false,
94            ConcreteType::Integer(_) | ConcreteType::Bool(_) => false,
95            ConcreteType::Backward(_) => true,
96            ConcreteType::Wire(_) => true,
97        }
98    }
99}
100
101impl std::fmt::Display for ConcreteType {
102    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103        let str = match self {
104            ConcreteType::Tuple(inner) => {
105                format!(
106                    "({})",
107                    inner
108                        .iter()
109                        .map(|p| format!("{}", p))
110                        .collect::<Vec<_>>()
111                        .join(", ")
112                )
113            }
114            ConcreteType::Struct {
115                name,
116                is_port,
117                members,
118            } => {
119                let port = if *is_port { "port " } else { "" };
120                format!(
121                    "struct {port}{name} {{{}}}",
122                    members
123                        .iter()
124                        .map(|(name, t)| format!("{}: {}", name, t))
125                        .collect::<Vec<_>>()
126                        .join(", ")
127                )
128            }
129            ConcreteType::Array { inner, size } => {
130                format!("[{}; {}]", inner, size)
131            }
132            ConcreteType::Enum { options } => {
133                let inner = options
134                    .iter()
135                    .map(|o| {
136                        let param_list =
137                            o.1.iter()
138                                .map(|t| format!("{}", t.1))
139                                .collect::<Vec<_>>()
140                                .join(",");
141                        format!("{} ( {} )", o.0 .0, param_list)
142                    })
143                    .collect::<Vec<_>>()
144                    .join(",");
145                format!("enum {{{}}}", inner)
146            }
147            ConcreteType::Single { base, params } => {
148                let params_str = if params.is_empty() {
149                    String::new()
150                } else {
151                    params
152                        .iter()
153                        .map(|p| format!("{}", p))
154                        .collect::<Vec<_>>()
155                        .join(", ")
156                };
157
158                format!("{}{}", base, params_str)
159            }
160            ConcreteType::Integer(size) => {
161                format!("{}", size)
162            }
163            ConcreteType::Bool(val) => {
164                format!("{}", val)
165            }
166            ConcreteType::Backward(inner) => {
167                format!("inv &{}", inner)
168            }
169            ConcreteType::Wire(inner) => {
170                format!("&{}", inner)
171            }
172        };
173
174        write!(f, "{str}")
175    }
176}
177
178#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
179pub enum KnownType {
180    Named(NameID),
181    Integer(BigInt),
182    Bool(bool),
183    Tuple,
184    Array,
185    Wire,
186    Inverted,
187}
188
189impl WithLocation for KnownType {}
190
191impl KnownType {
192    pub fn integer(val: u64) -> Self {
193        Self::Integer(val.to_bigint())
194    }
195}