spade_types/
lib.rs

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