1mod literal;
2mod printer;
3
4pub use crate::generated::ir::*;
5#[cfg(feature = "std")]
6pub use printer::{print, print_no_color, print_ty};
7
8use crate::{boxed, string, vec};
9
10impl Program {
11 pub fn get_output_ty(&self) -> &Ty {
12 let main_ty = self.main.ty.kind.as_function().unwrap();
13 &main_ty.body
14 }
15
16 pub fn get_input_ty(&self) -> &Ty {
17 let main_ty = self.main.ty.kind.as_function().unwrap();
18 assert_eq!(main_ty.params.len(), 1);
19 &main_ty.params[0]
20 }
21}
22
23impl Expr {
24 pub fn new(kind: impl Into<ExprKind>, ty: Ty) -> Expr {
25 Expr {
26 kind: kind.into(),
27 ty,
28 }
29 }
30 pub fn new_lit_bool(value: bool) -> Self {
31 Expr {
32 kind: ExprKind::Literal(Literal::Prim8(value as u8)),
33 ty: Ty::bool(),
34 }
35 }
36}
37impl From<ParameterPtr> for ExprKind {
38 fn from(ptr: ParameterPtr) -> Self {
39 ExprKind::Pointer(Pointer::Parameter(ptr))
40 }
41}
42impl From<ExternalPtr> for ExprKind {
43 fn from(ptr: ExternalPtr) -> Self {
44 ExprKind::Pointer(Pointer::External(ptr))
45 }
46}
47impl From<TupleLookup> for ExprKind {
48 fn from(v: TupleLookup) -> Self {
49 ExprKind::TupleLookup(boxed::Box::new(v))
50 }
51}
52impl From<Binding> for ExprKind {
53 fn from(v: Binding) -> Self {
54 ExprKind::Binding(boxed::Box::new(v))
55 }
56}
57impl From<Call> for ExprKind {
58 fn from(v: Call) -> Self {
59 ExprKind::Call(boxed::Box::new(v))
60 }
61}
62impl From<Function> for ExprKind {
63 fn from(v: Function) -> Self {
64 ExprKind::Function(boxed::Box::new(v))
65 }
66}
67impl From<EnumTag> for ExprKind {
68 fn from(v: EnumTag) -> Self {
69 ExprKind::EnumTag(boxed::Box::new(v))
70 }
71}
72impl From<EnumUnwrap> for ExprKind {
73 fn from(value: EnumUnwrap) -> Self {
74 ExprKind::EnumUnwrap(boxed::Box::new(value))
75 }
76}
77
78impl PartialEq for Ty {
79 fn eq(&self, other: &Self) -> bool {
80 self.kind == other.kind
81 }
82}
83
84impl Eq for Ty {}
85
86impl Ty {
87 pub fn new(kind: impl Into<TyKind>) -> Self {
88 Ty {
89 kind: kind.into(),
90 layout: None,
91 name: None,
92 variants_recursive: vec![],
93 }
94 }
95 pub fn new_ident(path: &[&str]) -> Self {
96 use string::ToString;
97 Ty::new(Path(path.iter().map(|n| n.to_string()).collect()))
98 }
99 pub fn bool() -> Self {
100 Ty::new_ident(&["std", "Bool"])
101 }
102 pub fn text() -> Self {
103 Ty::new_ident(&["std", "Text"])
104 }
105 pub fn new_unit() -> Self {
106 Ty {
107 kind: TyKind::Tuple(vec![]),
108 layout: Some(TyLayout {
109 head_size: 0,
110 body_ptrs: vec![],
111 }),
112 name: None,
113 variants_recursive: vec![],
114 }
115 }
116 pub fn is_unit(&self) -> bool {
117 self.kind.is_unit()
118 }
119}
120
121impl TyKind {
122 pub fn is_unit(&self) -> bool {
123 self.as_tuple().is_some_and(|f| f.is_empty())
124 }
125
126 pub fn as_option(&self) -> Option<&Ty> {
127 self.as_enum()
128 .filter(|v| v.len() == 2 && v[0].ty.is_unit() && !v[1].ty.is_unit())
129 .map(|v| &v[1].ty)
130 }
131
132 pub fn as_std(&self) -> Option<TyStd> {
133 self.as_ident().and_then(TyStd::try_new)
134 }
135}
136
137impl From<TyPrimitive> for TyKind {
138 fn from(value: TyPrimitive) -> Self {
139 TyKind::Primitive(value)
140 }
141}
142impl From<vec::Vec<TyTupleField>> for TyKind {
143 fn from(value: vec::Vec<TyTupleField>) -> Self {
144 TyKind::Tuple(value)
145 }
146}
147impl From<TyFunction> for TyKind {
148 fn from(value: TyFunction) -> Self {
149 TyKind::Function(boxed::Box::new(value))
150 }
151}
152impl From<Path> for TyKind {
153 fn from(value: Path) -> Self {
154 TyKind::Ident(value)
155 }
156}
157
158impl Module {
159 pub fn insert(&mut self, path: &[string::String], decl: Decl) {
160 if path.is_empty() {
161 panic!();
162 }
163
164 if path.len() == 1 {
165 self.decls.retain(|d| d.name != path[0]);
166 self.decls.push(ModuledeclsItems {
167 name: path[0].clone(),
168 decl,
169 });
170 } else {
171 let exists = self.decls.iter().any(|d| d.name == path[0]);
172 if !exists {
173 self.decls.push(ModuledeclsItems {
174 name: path[0].clone(),
175 decl: Decl::Mod(boxed::Box::new(Module {
176 decls: vec::Vec::new(),
177 })),
178 });
179 }
180
181 let sub_module = self.decls.iter_mut().find(|d| d.name == path[0]);
182 let Decl::Mod(sub_module) = &mut sub_module.unwrap().decl else {
183 panic!()
184 };
185 sub_module.insert(&path[1..], decl)
186 }
187 }
188
189 pub fn iter_defs_re(&self) -> impl Iterator<Item = (Path, &Decl)> {
190 self.decls.iter().flat_map(|item| match &item.decl {
191 Decl::Mod(sub_module) => sub_module
192 .iter_defs_re()
193 .map(|(mut p, d)| {
194 p.0.insert(0, item.name.clone());
195 (p, d)
196 })
197 .collect::<vec::Vec<_>>(),
198 _ => {
199 vec![(Path(vec![item.name.clone()]), &item.decl)]
200 }
201 })
202 }
203
204 pub fn iter_types_re(&self) -> impl Iterator<Item = (Path, &Ty)> {
205 self.iter_defs_re().filter_map(|(p, d)| {
206 if let Decl::Ty(ty) = d {
207 Some((p, ty))
208 } else {
209 None
210 }
211 })
212 }
213}
214
215impl Path {
216 pub fn is(&self, name: &[&str]) -> bool {
217 self.0.len() == name.len() && core::iter::zip(&self.0, name).all(|(a, b)| a == b)
218 }
219}
220
221impl Literal {
222 pub fn new_int16(value: i16) -> Self {
223 Self::Prim16(value.to_le() as u16)
224 }
225 pub fn new_int32(value: i32) -> Self {
226 Self::Prim32(value.to_le() as u32)
227 }
228 pub fn new_int64(value: i64) -> Self {
229 Self::Prim64(value.to_le() as u64)
230 }
231}
232
233impl TupleLookup {
234 pub fn new(base: Expr, position: u16) -> Self {
235 Self { base, position }
236 }
237}
238
239impl TyPrimitive {
240 pub fn name(self) -> &'static str {
241 match self {
242 Self::Prim8 => "Prim8",
243 Self::Prim16 => "Prim16",
244 Self::Prim32 => "Prim32",
245 Self::Prim64 => "Prim64",
246 }
247 }
248}
249
250#[derive(Clone, Copy, Debug, Eq, PartialEq)]
252pub enum TyStd {
253 Bool,
254 Int8,
255 Int16,
256 Int32,
257 Int64,
258 UInt8,
259 UInt16,
260 UInt32,
261 UInt64,
262 Float32,
263 Float64,
264 Text,
265 Date,
266 Time,
267 Timestamp,
268 Decimal,
269}
270
271impl TyStd {
272 pub fn try_new(ident: &Path) -> Option<Self> {
273 Self::try_from_steps(&ident.0)
274 }
275
276 pub fn try_from_steps(steps: &[string::String]) -> Option<Self> {
277 if steps.len() != 2 && steps.first().unwrap() != "std" {
278 return None;
279 }
280 Some(match steps[1].as_str() {
281 "Bool" => Self::Bool,
282 "Int8" => Self::Int8,
283 "Int16" => Self::Int16,
284 "Int32" => Self::Int32,
285 "Int64" => Self::Int64,
286 "Uint8" => Self::UInt8,
287 "Uint16" => Self::UInt16,
288 "Uint32" => Self::UInt32,
289 "Uint64" => Self::UInt64,
290 "Float32" => Self::Float32,
291 "Float64" => Self::Float64,
292 "Text" => Self::Text,
293 "Date" => Self::Date,
294 "Time" => Self::Time,
295 "Timestamp" => Self::Timestamp,
296 "Decimal" => Self::Decimal,
297 _ => return None,
298 })
299 }
300
301 pub fn is_int(self) -> bool {
302 use TyStd::*;
303 matches!(
304 self,
305 Int8 | Int16 | Int32 | Int64 | UInt8 | UInt16 | UInt32 | UInt64
306 )
307 }
308
309 pub fn is_signed_int(self) -> bool {
310 matches!(
311 self,
312 TyStd::Int8 | TyStd::Int16 | TyStd::Int32 | TyStd::Int64
313 )
314 }
315
316 pub fn is_float(self) -> bool {
317 matches!(self, TyStd::Float32 | TyStd::Float64)
318 }
319
320 pub fn is_number(self) -> bool {
321 self.is_int() || self.is_float() || self == Self::Decimal
322 }
323
324 pub fn bits(self) -> u32 {
325 match self {
326 TyStd::Int8 | TyStd::UInt8 => 8,
327 TyStd::Int16 | TyStd::UInt16 => 16,
328 TyStd::Int32 | TyStd::UInt32 | TyStd::Float32 => 32,
329 TyStd::Int64 | TyStd::UInt64 | TyStd::Float64 => 64,
330 _ => 0,
331 }
332 }
333}