1use glyph_types::Value;
10use std::collections::HashMap;
11
12#[derive(Debug, Clone)]
14pub struct IRModule {
15 pub program: IRProgram,
17 pub functions: HashMap<String, IRFunction>,
19 pub entry_point: Option<String>,
21}
22
23#[derive(Debug, Clone)]
25pub struct IRProgram {
26 pub name: String,
27 pub version: String,
28 pub requires: Vec<String>,
29}
30
31#[derive(Debug, Clone)]
33pub struct IRFunction {
34 pub name: String,
36 pub params: Vec<String>,
38 pub locals_count: usize,
40 pub blocks: Vec<IRBlock>,
42 pub is_async: bool,
44}
45
46#[derive(Debug, Clone)]
48pub struct IRBlock {
49 pub label: String,
51 pub instructions: Vec<IRInstruction>,
53 pub terminator: IRTerminator,
55}
56
57#[derive(Debug, Clone)]
59pub enum IRInstruction {
60 LoadConst(Value),
62 LoadVar(String),
64 StoreVar(String),
66 BinaryOp(BinaryOp),
68 UnaryOp(UnaryOp),
70 Call { func: String, args_count: usize },
72 CallIntrinsic { name: String, args_count: usize },
74 MakeList(usize),
76 MakeDict(usize),
78 GetAttr(String),
80 GetItem,
82 CallMethod { name: String, argc: usize },
84 Await,
86 Dup,
88 Pop,
90}
91
92#[derive(Debug, Clone)]
94pub enum IRTerminator {
95 Return,
97 Jump(String),
99 JumpIf {
101 then_block: String,
102 else_block: String,
103 },
104 Match {
106 cases: Vec<(IRPattern, String)>,
107 default: Option<String>,
108 },
109}
110
111#[derive(Debug, Clone)]
113pub enum IRPattern {
114 Literal(Value),
116 Variable(String),
118 Constructor { name: String, args: Vec<IRPattern> },
120 Wildcard,
122}
123
124#[derive(Debug, Clone, Copy)]
126pub enum BinaryOp {
127 Add,
129 Sub,
130 Mul,
131 Div,
132 Mod,
133 Pow,
134 Eq,
136 Ne,
137 Lt,
138 Le,
139 Gt,
140 Ge,
141 And,
143 Or,
144}
145
146#[derive(Debug, Clone, Copy)]
148pub enum UnaryOp {
149 Neg,
150 Not,
151}
152
153pub struct IRBuilder {
155 pub module: IRModule,
157 current_function: Option<String>,
159 current_block: Option<String>,
161 var_counter: usize,
163 block_counter: usize,
165 block_terminated: bool,
167}
168
169impl IRBuilder {
170 pub fn new(name: String, version: String, requires: Vec<String>) -> Self {
171 Self {
172 module: IRModule {
173 program: IRProgram {
174 name,
175 version,
176 requires,
177 },
178 functions: HashMap::new(),
179 entry_point: None,
180 },
181 current_function: None,
182 current_block: None,
183 var_counter: 0,
184 block_counter: 0,
185 block_terminated: false,
186 }
187 }
188
189 pub fn fresh_var(&mut self) -> String {
191 let var = format!("_t{}", self.var_counter);
192 self.var_counter += 1;
193 var
194 }
195
196 pub fn fresh_label(&mut self) -> String {
198 let label = format!("L{}", self.block_counter);
199 self.block_counter += 1;
200 label
201 }
202
203 pub fn start_function(&mut self, name: String, params: Vec<String>, is_async: bool) {
205 let entry_label = self.fresh_label();
206 let func = IRFunction {
207 name: name.clone(),
208 params,
209 locals_count: 0,
210 blocks: vec![IRBlock {
211 label: entry_label.clone(),
212 instructions: vec![],
213 terminator: IRTerminator::Return,
214 }],
215 is_async,
216 };
217 self.module.functions.insert(name.clone(), func);
218 self.current_function = Some(name);
219 self.current_block = Some(entry_label);
220 self.block_terminated = false;
221 }
222
223 pub fn emit(&mut self, inst: IRInstruction) {
225 if let (Some(func_name), Some(block_label)) = (&self.current_function, &self.current_block)
226 {
227 if let Some(func) = self.module.functions.get_mut(func_name) {
228 if let Some(block) = func.blocks.iter_mut().find(|b| b.label == *block_label) {
229 block.instructions.push(inst);
230 }
231 }
232 }
233 }
234
235 pub fn terminate(&mut self, term: IRTerminator) {
237 if let (Some(func_name), Some(block_label)) = (&self.current_function, &self.current_block)
238 {
239 if let Some(func) = self.module.functions.get_mut(func_name) {
240 if let Some(block) = func.blocks.iter_mut().find(|b| b.label == *block_label) {
241 block.terminator = term;
242 self.block_terminated = true;
243 }
244 }
245 }
246 }
247
248 pub fn new_block(&mut self, label: String) {
250 if let Some(func_name) = &self.current_function {
251 if let Some(func) = self.module.functions.get_mut(func_name) {
252 func.blocks.push(IRBlock {
253 label: label.clone(),
254 instructions: vec![],
255 terminator: IRTerminator::Return,
256 });
257 self.current_block = Some(label);
258 self.block_terminated = false; }
260 }
261 }
262
263 pub fn is_terminated(&self) -> bool {
265 self.block_terminated
266 }
267
268 pub fn finish(mut self) -> IRModule {
270 if self.module.functions.contains_key("main") {
272 self.module.entry_point = Some("main".to_string());
273 }
274 self.module
275 }
276}