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_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.as_tuple().is_some_and(|f| f.is_empty())
103    }
104}
105
106impl From<TyPrimitive> for TyKind {
107    fn from(value: TyPrimitive) -> Self {
108        TyKind::Primitive(value)
109    }
110}
111impl From<vec::Vec<TyTupleField>> for TyKind {
112    fn from(value: vec::Vec<TyTupleField>) -> Self {
113        TyKind::Tuple(value)
114    }
115}
116impl From<TyFunction> for TyKind {
117    fn from(value: TyFunction) -> Self {
118        TyKind::Function(boxed::Box::new(value))
119    }
120}
121impl From<Path> for TyKind {
122    fn from(value: Path) -> Self {
123        TyKind::Ident(value)
124    }
125}
126
127impl Module {
128    pub fn insert(&mut self, path: &[string::String], decl: Decl) {
129        if path.is_empty() {
130            panic!();
131        }
132
133        if path.len() == 1 {
134            self.decls.retain(|d| d.name != path[0]);
135            self.decls.push(ModuledeclsItems {
136                name: path[0].clone(),
137                decl,
138            });
139        } else {
140            let exists = self.decls.iter().any(|d| d.name == path[0]);
141            if !exists {
142                self.decls.push(ModuledeclsItems {
143                    name: path[0].clone(),
144                    decl: Decl::Module(boxed::Box::new(Module {
145                        decls: vec::Vec::new(),
146                    })),
147                });
148            }
149
150            let sub_module = self.decls.iter_mut().find(|d| d.name == path[0]);
151            let Decl::Module(sub_module) = &mut sub_module.unwrap().decl else {
152                panic!()
153            };
154            sub_module.insert(&path[1..], decl)
155        }
156    }
157
158    pub fn iter_defs_re(&self) -> impl Iterator<Item = (Path, &Decl)> {
159        self.decls.iter().flat_map(|item| match &item.decl {
160            Decl::Module(sub_module) => sub_module
161                .iter_defs_re()
162                .map(|(mut p, d)| {
163                    p.0.insert(0, item.name.clone());
164                    (p, d)
165                })
166                .collect::<vec::Vec<_>>(),
167            _ => {
168                vec![(Path(vec![item.name.clone()]), &item.decl)]
169            }
170        })
171    }
172
173    pub fn iter_types_re(&self) -> impl Iterator<Item = (Path, &Ty)> {
174        self.iter_defs_re().filter_map(|(p, d)| {
175            if let Decl::Type(ty) = d {
176                Some((p, ty))
177            } else {
178                None
179            }
180        })
181    }
182}