Skip to main content

lutra_bin/ir/
mod.rs

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::bool(value)),
33            ty: Ty::new(TyPrimitive::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<EnumEq> for ExprKind {
68    fn from(eq: EnumEq) -> Self {
69        ExprKind::EnumEq(boxed::Box::new(eq))
70    }
71}
72
73impl PartialEq for Ty {
74    fn eq(&self, other: &Self) -> bool {
75        self.kind == other.kind
76    }
77}
78
79impl Eq for Ty {}
80
81impl Ty {
82    pub fn new(kind: impl Into<TyKind>) -> Self {
83        Ty {
84            kind: kind.into(),
85            layout: None,
86            name: None,
87            variants_recursive: vec![],
88        }
89    }
90    pub fn new_unit() -> Self {
91        Ty {
92            kind: TyKind::Tuple(vec![]),
93            layout: Some(TyLayout {
94                head_size: 0,
95                body_ptrs: vec![],
96            }),
97            name: None,
98            variants_recursive: vec![],
99        }
100    }
101    pub fn is_unit(&self) -> bool {
102        self.kind.is_unit()
103    }
104}
105
106impl TyKind {
107    pub fn is_unit(&self) -> bool {
108        self.as_tuple().is_some_and(|f| f.is_empty())
109    }
110
111    pub fn as_option(&self) -> Option<&Ty> {
112        self.as_enum()
113            .filter(|v| v.len() == 2 && v[0].ty.is_unit() && !v[1].ty.is_unit())
114            .map(|v| &v[1].ty)
115    }
116}
117
118impl From<TyPrimitive> for TyKind {
119    fn from(value: TyPrimitive) -> Self {
120        TyKind::Primitive(value)
121    }
122}
123impl From<vec::Vec<TyTupleField>> for TyKind {
124    fn from(value: vec::Vec<TyTupleField>) -> Self {
125        TyKind::Tuple(value)
126    }
127}
128impl From<TyFunction> for TyKind {
129    fn from(value: TyFunction) -> Self {
130        TyKind::Function(boxed::Box::new(value))
131    }
132}
133impl From<Path> for TyKind {
134    fn from(value: Path) -> Self {
135        TyKind::Ident(value)
136    }
137}
138
139impl Module {
140    pub fn insert(&mut self, path: &[string::String], decl: Decl) {
141        if path.is_empty() {
142            panic!();
143        }
144
145        if path.len() == 1 {
146            self.decls.retain(|d| d.name != path[0]);
147            self.decls.push(ModuledeclsItems {
148                name: path[0].clone(),
149                decl,
150            });
151        } else {
152            let exists = self.decls.iter().any(|d| d.name == path[0]);
153            if !exists {
154                self.decls.push(ModuledeclsItems {
155                    name: path[0].clone(),
156                    decl: Decl::Module(boxed::Box::new(Module {
157                        decls: vec::Vec::new(),
158                    })),
159                });
160            }
161
162            let sub_module = self.decls.iter_mut().find(|d| d.name == path[0]);
163            let Decl::Module(sub_module) = &mut sub_module.unwrap().decl else {
164                panic!()
165            };
166            sub_module.insert(&path[1..], decl)
167        }
168    }
169
170    pub fn iter_defs_re(&self) -> impl Iterator<Item = (Path, &Decl)> {
171        self.decls.iter().flat_map(|item| match &item.decl {
172            Decl::Module(sub_module) => sub_module
173                .iter_defs_re()
174                .map(|(mut p, d)| {
175                    p.0.insert(0, item.name.clone());
176                    (p, d)
177                })
178                .collect::<vec::Vec<_>>(),
179            _ => {
180                vec![(Path(vec![item.name.clone()]), &item.decl)]
181            }
182        })
183    }
184
185    pub fn iter_types_re(&self) -> impl Iterator<Item = (Path, &Ty)> {
186        self.iter_defs_re().filter_map(|(p, d)| {
187            if let Decl::Type(ty) = d {
188                Some((p, ty))
189            } else {
190                None
191            }
192        })
193    }
194}