1use crate::ast::*;
2use crate::vm::bet::pack_trits;
3use crate::trit::Trit;
4
5pub struct BytecodeEmitter {
6 code: Vec<u8>,
7 symbols: std::collections::HashMap<String, u8>,
8 func_addrs: std::collections::HashMap<String, u16>,
9 function_patches: std::collections::HashMap<String, Vec<usize>>,
10 break_patches: Vec<usize>,
11 continue_patches: Vec<usize>,
12 next_reg: usize,
13 struct_layouts: std::collections::HashMap<String, Vec<String>>,
14 agent_type_ids: std::collections::HashMap<String, u16>,
15 agent_handlers: Vec<(u16, u16)>,
16 function_symbols: std::collections::HashMap<String, std::collections::HashMap<String, u8>>,
19}
20
21impl BytecodeEmitter {
22 pub fn new() -> Self {
23 Self {
24 code: Vec::new(),
25 symbols: std::collections::HashMap::new(),
26 func_addrs: std::collections::HashMap::new(),
27 function_patches: std::collections::HashMap::new(),
28 break_patches: Vec::new(),
29 continue_patches: Vec::new(),
30 next_reg: 0,
31 struct_layouts: std::collections::HashMap::new(),
32 agent_type_ids: std::collections::HashMap::new(),
33 agent_handlers: Vec::new(),
34 function_symbols: std::collections::HashMap::new(),
35 }
36 }
37
38 pub fn get_symbols(&self) -> &std::collections::HashMap<String, u8> {
40 &self.symbols
41 }
42
43 pub fn get_function_symbols(&self, name: &str) -> Option<&std::collections::HashMap<String, u8>> {
46 self.function_symbols.get(name)
47 }
48
49 pub fn register_agents(&self, vm: &mut crate::vm::BetVm) {
50 for &(type_id, addr) in &self.agent_handlers {
51 vm.register_agent_type(type_id, addr as usize);
52 }
53 }
54
55 pub fn emit_header_jump(&mut self) -> usize {
56 let patch_pos = self.code.len() + 1;
57 self.code.push(0x0b); self.code.extend_from_slice(&[0u8, 0u8]);
59 patch_pos
60 }
61
62 pub fn patch_header_jump(&mut self, patch_pos: usize) {
63 let addr = self.code.len() as u16;
64 self.patch_u16(patch_pos, addr);
65 }
66
67 pub fn emit_program(&mut self, program: &Program) {
68 let parent_next_reg = self.next_reg;
69 for s in &program.structs {
70 let names: Vec<String> = s.fields.iter().map(|(n, _)| n.clone()).collect();
71 self.struct_layouts.insert(s.name.clone(), names);
72 }
73 for (idx, agent) in program.agents.iter().enumerate() {
74 self.agent_type_ids.insert(agent.name.clone(), idx as u16);
75 }
76
77 let real_code = std::mem::take(&mut self.code);
79 let real_func_addrs = std::mem::take(&mut self.func_addrs);
80 let real_agent_handlers = std::mem::take(&mut self.agent_handlers);
81 let base_addr = real_code.len() as u16;
82
83 for agent in &program.agents {
84 let type_id = self.agent_type_ids[&agent.name];
85 let mut handler_addr = None;
86 for method in &agent.methods {
87 let addr = base_addr + self.code.len() as u16;
88 if handler_addr.is_none() { handler_addr = Some(addr); }
89 self.emit_function(method);
90 self.func_addrs.insert(format!("{}::{}", agent.name, method.name), addr);
92 }
93 if let Some(addr) = handler_addr { self.agent_handlers.push((type_id, addr)); }
94 }
95 for func in &program.functions {
96 let addr = base_addr + self.code.len() as u16;
97 self.func_addrs.insert(func.name.clone(), addr);
98 self.emit_function(func);
100 self.func_addrs.insert(func.name.clone(), addr);
104 }
105
106 let final_func_addrs = std::mem::replace(&mut self.func_addrs, real_func_addrs);
107 let final_agent_handlers = std::mem::replace(&mut self.agent_handlers, real_agent_handlers);
108 self.code = real_code;
109 self.func_addrs = final_func_addrs;
110 self.agent_handlers = final_agent_handlers;
111 self.next_reg = parent_next_reg;
112
113 for agent in &program.agents {
115 for method in &agent.methods { self.emit_function(method); }
116 }
117 for func in &program.functions { self.emit_function(func); }
118 }
119
120 pub fn emit_function(&mut self, func: &Function) {
121 let func_addr = self.code.len() as u16;
122 self.func_addrs.insert(func.name.clone(), func_addr);
123 if let Some(patches) = self.function_patches.remove(&func.name) {
124 for p in patches {
125 self.code[p..p + 2].copy_from_slice(&func_addr.to_le_bytes());
126 }
127 }
128 let parent_symbols = self.symbols.clone();
129 let parent_next_reg = self.next_reg;
130 self.next_reg = 0;
131
132 for (name, ty) in func.params.iter().rev() {
136 if let Type::Named(s_name) = ty {
137 if let Some(fields) = self.struct_layouts.get(s_name).cloned() {
138 let root_reg = self.alloc_reg();
143 self.symbols.insert(name.clone(), root_reg);
144 self.code.push(0x08); self.code.push(root_reg);
145
146 for f_name in fields.iter().rev() {
148 let f_reg = self.alloc_reg();
149 let key = format!("{}.{}", name, f_name);
150 self.symbols.insert(key, f_reg);
151 self.code.push(0x08); self.code.push(f_reg);
152 }
153 continue;
154 }
155 }
156 let reg = self.alloc_reg();
157 self.symbols.insert(name.clone(), reg);
158 self.code.push(0x08); self.code.push(reg);
159 }
160 for stmt in &func.body { self.emit_stmt(stmt); }
161 self.function_symbols.insert(func.name.clone(), self.symbols.clone());
163 self.symbols = parent_symbols;
164 self.next_reg = parent_next_reg;
165 self.code.push(0x11); }
167
168 pub fn emit_stmt(&mut self, stmt: &Stmt) {
169 match stmt {
170 Stmt::Let { name, ty, value } => {
171 let mut handled = false;
172 match ty {
173 Type::TritTensor { dims } | Type::IntTensor { dims } | Type::FloatTensor { dims } => {
174 if !dims.is_empty() && !dims.contains(&0) && matches!(value, Expr::TritLiteral(0)) {
176 let rows = dims[0];
177 let cols = if dims.len() > 1 { dims[1] } else { 1 };
178 self.code.push(0x0f);
179 self.code.extend_from_slice(&(rows as u16).to_le_bytes());
180 self.code.extend_from_slice(&(cols as u16).to_le_bytes());
181 handled = true;
182 }
183 }
184 Type::Named(_) => {
185 if let Expr::StructLiteral { fields, .. } = value {
186 for (f_name, f_val) in fields {
188 self.emit_expr(f_val);
189 let reg = self.alloc_reg();
190 let key = format!("{}.{}", name, f_name);
191 self.symbols.insert(key, reg);
192 self.code.push(0x08); self.code.push(reg);
193 }
194 }
196 }
197 _ => {}
198 }
199 if !handled {
200 self.emit_expr(value);
201 }
202 let reg = self.alloc_reg();
203 self.symbols.insert(name.clone(), reg);
204 self.code.push(0x08); self.code.push(reg); }
206 Stmt::Set { name, value } => {
207 self.emit_expr(value);
208 if let Some(®) = self.symbols.get(name) {
209 self.code.push(0x08); self.code.push(reg);
210 }
211 }
212 Stmt::FieldSet { object, field, value } => {
213 let key = format!("{}.{}", object, field);
214 self.emit_expr(value);
215 if let Some(®) = self.symbols.get(&key) {
216 self.code.push(0x08); self.code.push(reg);
217 }
218 }
219 Stmt::IndexSet { object, row, col, value } => {
220 if let Some(®) = self.symbols.get(object) {
221 self.code.push(0x09); self.code.push(reg);
222 self.emit_expr(row);
223 self.emit_expr(col);
224 self.emit_expr(value);
225 self.code.push(0x23);
226 }
227 }
228 Stmt::IfTernary { condition, on_pos, on_zero, on_neg } => {
229 let pre_reg = self.next_reg;
230 self.emit_expr(condition);
231 let cond_reg = self.alloc_reg();
232 self.code.push(0x08); self.code.push(cond_reg); self.code.push(0x09); self.code.push(cond_reg); let pos_patch = self.code.len() + 1;
239 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]); let zero_patch = self.code.len() + 1;
243 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.emit_stmt(on_neg);
248 let exit_patch = self.code.len() + 1;
249 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let pos_addr = self.code.len() as u16;
253 self.patch_u16(pos_patch, pos_addr);
254 self.code.push(0x0c); self.emit_stmt(on_pos);
256 let exit_pos = self.code.len() + 1;
257 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
258
259 let zero_addr = self.code.len() as u16;
261 self.patch_u16(zero_patch, zero_addr);
262 self.code.push(0x0c); self.emit_stmt(on_zero);
264
265 let end = self.code.len() as u16;
266 self.patch_u16(exit_patch, end);
267 self.patch_u16(exit_pos, end);
268 self.next_reg = pre_reg;
269 }
270 Stmt::Match { condition, arms } => {
271 let pre_reg = self.next_reg;
272 self.emit_expr(condition);
273 let cond_reg = self.alloc_reg();
274 self.code.push(0x08); self.code.push(cond_reg); let mut end_patches = Vec::new();
277 let mut next_arm_patch = None;
278
279 for (pattern, stmt) in arms {
280 if let Some(p) = next_arm_patch {
281 let addr = self.code.len() as u16;
282 self.patch_u16(p, addr);
283 }
284
285 self.code.push(0x09); self.code.push(cond_reg); let match_patch;
289 match pattern {
290 Pattern::Trit(1) | Pattern::Int(1) => {
291 self.code.push(0x05); match_patch = self.code.len();
293 self.code.extend_from_slice(&[0, 0]);
294 }
295 Pattern::Trit(0) | Pattern::Int(0) => {
296 self.code.push(0x06); match_patch = self.code.len();
298 self.code.extend_from_slice(&[0, 0]);
299 }
300 Pattern::Trit(-1) | Pattern::Int(-1) => {
301 self.code.push(0x07); match_patch = self.code.len();
303 self.code.extend_from_slice(&[0, 0]);
304 }
305 Pattern::Int(v) => {
306 self.code.push(0x25); self.code.extend_from_slice(&v.to_le_bytes());
308 match_patch = self.code.len();
309 self.code.extend_from_slice(&[0, 0]);
310 }
311 Pattern::Trit(v) => {
312 self.code.push(0x25); self.code.extend_from_slice(&(*v as i64).to_le_bytes());
314 match_patch = self.code.len();
315 self.code.extend_from_slice(&[0, 0]);
316 }
317 Pattern::Float(v) => {
318 self.code.push(0x2a); self.code.extend_from_slice(&v.to_le_bytes());
320 match_patch = self.code.len();
321 self.code.extend_from_slice(&[0, 0]);
322 }
323 }
324
325 self.code.push(0x0c); let skip_patch = self.code.len() + 1;
330 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
331 next_arm_patch = Some(skip_patch);
332
333 let body_addr = self.code.len() as u16;
335 self.patch_u16(match_patch, body_addr);
336
337 self.code.push(0x0c); self.emit_stmt(stmt);
340
341 let end_patch = self.code.len() + 1;
343 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
344 end_patches.push(end_patch);
345 }
346
347 if let Some(p) = next_arm_patch {
348 let addr = self.code.len() as u16;
349 self.patch_u16(p, addr);
350 }
351
352 if !arms.is_empty() {
353 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
359 }
360
361 let end_addr = self.code.len() as u16;
362 for p in end_patches { self.patch_u16(p, end_addr); }
363 self.next_reg = pre_reg;
364 }
365 Stmt::ForIn { var, iter, body } => {
366 let pre_loop_reg = self.next_reg;
370
371 self.emit_expr(iter);
372 let it_reg = self.alloc_reg();
373 self.code.push(0x08); self.code.push(it_reg);
374 self.code.push(0x09); self.code.push(it_reg);
375 self.code.push(0x24); self.code.push(0x0c); let r_reg = self.alloc_reg();
378 self.code.push(0x08); self.code.push(r_reg); let i_reg = self.alloc_reg();
380 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
381 self.code.push(0x08); self.code.push(i_reg);
382
383 let cmp_reg = self.alloc_reg();
387
388 let top = self.code.len() as u16;
389 let pre_break = self.break_patches.len();
390 let pre_cont = self.continue_patches.len();
391
392 self.code.push(0x09); self.code.push(i_reg);
394 self.code.push(0x09); self.code.push(r_reg);
395 self.code.push(0x14); self.code.push(0x08); self.code.push(cmp_reg); self.code.push(0x09); self.code.push(cmp_reg); let neg = self.code.len() + 1;
401 self.code.push(0x07); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.code.push(0x09); self.code.push(cmp_reg); let zero = self.code.len() + 1;
407 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.code.push(0x09); self.code.push(it_reg);
412 self.code.push(0x09); self.code.push(i_reg);
413 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
414 self.code.push(0x22);
415 let v_reg = self.alloc_reg();
416 self.symbols.insert(var.clone(), v_reg);
417 self.code.push(0x08); self.code.push(v_reg);
418 self.emit_stmt(body);
419
420 let cont_addr = self.code.len() as u16;
421 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
422 for p in cs { self.patch_u16(p, cont_addr); }
423
424 self.code.push(0x09); self.code.push(i_reg);
425 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
426 self.code.push(0x18);
427 self.code.push(0x08); self.code.push(i_reg);
428 let back = self.code.len() + 1;
429 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
430 self.patch_u16(back, top);
431
432 let neg_exit_addr = self.code.len() as u16;
435 self.patch_u16(neg, neg_exit_addr);
436 self.code.push(0x0c); let neg_to_end = self.code.len() + 1;
438 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
439
440 let zero_exit_addr = self.code.len() as u16;
441 self.patch_u16(zero, zero_exit_addr);
442 self.code.push(0x0c); let zero_to_end = self.code.len() + 1;
444 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
445
446 let end = self.code.len() as u16;
447 self.patch_u16(neg_to_end, end);
448 self.patch_u16(zero_to_end, end);
449 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
450 for p in bs { self.patch_u16(p, end); }
451
452 self.symbols.remove(var);
455 self.next_reg = pre_loop_reg;
456 }
457 Stmt::WhileTernary { condition, on_pos, on_zero, on_neg } => {
458 let pre_reg = self.next_reg;
459 let cond_reg = self.alloc_reg();
460 let top = self.code.len() as u16;
461 let pre_break = self.break_patches.len();
462 let pre_cont = self.continue_patches.len();
463
464 self.emit_expr(condition);
465 self.code.push(0x08); self.code.push(cond_reg); self.code.push(0x09); self.code.push(cond_reg); let pos_patch = self.code.len() + 1;
472 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]); let zero_patch = self.code.len() + 1;
476 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.emit_stmt(on_neg);
481 let exit_neg = self.code.len() + 1;
482 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let pos_addr = self.code.len() as u16;
486 self.patch_u16(pos_patch, pos_addr);
487 self.code.push(0x0c); self.emit_stmt(on_pos);
489 let back_pos = self.code.len() + 1;
490 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
491 self.patch_u16(back_pos, top);
492
493 let zero_addr = self.code.len() as u16;
495 self.patch_u16(zero_patch, zero_addr);
496 self.code.push(0x0c); self.emit_stmt(on_zero);
498
499 let end = self.code.len() as u16;
500 self.patch_u16(exit_neg, end);
501
502 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
503 for p in cs { self.patch_u16(p, top); }
504 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
505 for p in bs { self.patch_u16(p, end); }
506 self.next_reg = pre_reg;
507 }
508 Stmt::Loop { body } => {
509 let top = self.code.len() as u16;
510 let pre_break = self.break_patches.len();
511 let pre_cont = self.continue_patches.len();
512 self.emit_stmt(body);
513 let back = self.code.len() + 1;
514 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
515 self.patch_u16(back, top);
516 let end = self.code.len() as u16;
517 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
518 for p in cs { self.patch_u16(p, top); }
519 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
520 for p in bs { self.patch_u16(p, end); }
521 }
522 Stmt::Break => {
523 let p = self.code.len() + 1;
524 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
525 self.break_patches.push(p);
526 }
527 Stmt::Continue => {
528 let p = self.code.len() + 1;
529 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
530 self.continue_patches.push(p);
531 }
532 Stmt::Send { target, message } => {
533 self.emit_expr(target);
534 self.emit_expr(message);
535 self.code.push(0x31); }
537 Stmt::Return(e) => { self.emit_expr(e); self.code.push(0x11); }
538 Stmt::Block(ss) => { for s in ss { self.emit_stmt(s); } }
539 Stmt::Expr(e) => { self.emit_expr(e); self.code.push(0x0c); }
540 Stmt::Decorated { directive: _, stmt } => { self.emit_stmt(stmt); }
541 _ => {}
542 }
543 }
544
545 fn emit_expr(&mut self, expr: &Expr) {
546 match expr {
547 Expr::TritLiteral(v) => {
548 self.code.push(0x01);
549 self.code.extend(pack_trits(&[Trit::from(*v)]));
550 }
551 Expr::IntLiteral(v) => {
552 self.code.push(0x17);
553 self.code.extend_from_slice(&v.to_le_bytes());
554 }
555 Expr::FloatLiteral(val) => {
556 self.code.push(0x19);
557 self.code.extend_from_slice(&val.to_le_bytes());
558 }
559 Expr::StringLiteral(val) => {
560 self.code.push(0x21); let bytes = val.as_bytes();
562 self.code.extend_from_slice(&(bytes.len() as u16).to_le_bytes());
563 self.code.extend_from_slice(bytes);
564 }
565 Expr::Ident(name) => {
566 match name.as_str() {
570 "true" => {
571 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
573 }
574 "false" => {
575 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
577 }
578 _ => {
579 if let Some(&r) = self.symbols.get(name) {
580 self.code.push(0x09); self.code.push(r);
581 }
582 }
583 }
584 }
585 Expr::BinaryOp { op, lhs, rhs } => {
586 self.emit_expr(lhs); self.emit_expr(rhs);
587 match op {
588 BinOp::Add => self.code.push(0x02),
589 BinOp::Mul => self.code.push(0x03),
590 BinOp::Div => self.code.push(0x1e),
591 BinOp::Mod => self.code.push(0x1f),
592 BinOp::Sub => { self.code.push(0x04); self.code.push(0x02); }
593 BinOp::Equal => self.code.push(0x16),
594 BinOp::NotEqual => { self.code.push(0x16); self.code.push(0x04); }
595 BinOp::And => self.code.push(0x28), BinOp::Or => self.code.push(0x29), BinOp::Less => self.code.push(0x14),
598 BinOp::Greater => self.code.push(0x15),
599 BinOp::LessEqual => self.code.push(0x26),
600 BinOp::GreaterEqual => self.code.push(0x27),
601 }
602 }
603 Expr::UnaryOp { op, expr } => {
604 self.emit_expr(expr);
605 match op { UnOp::Neg => self.code.push(0x04) }
606 }
607 Expr::Call { callee, args } => {
608 match callee.as_str() {
609 "println" | "print" => {
611 if args.is_empty() {
612 } else {
614 for a in args {
615 self.emit_expr(a);
616 self.code.push(0x20); }
618 }
619 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
621 "opent" => {
622 if args.len() == 2 {
623 for a in args { self.emit_expr(a); }
624 self.code.push(0x33); } else {
626 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
628 }
629 }
630 "readt" => {
631 if args.len() == 1 {
632 self.emit_expr(&args[0]);
633 self.code.push(0x34); } else {
635 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
636 }
637 }
638 "writet" => {
639 if args.len() == 2 {
640 for a in args { self.emit_expr(a); }
641 self.code.push(0x35); }
643 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
645 "consensus" => {
646
647 for a in args { self.emit_expr(a); }
648 if args.len() == 2 { self.code.push(0x0e); }
649 }
650 "length" => {
651 if args.len() == 1 {
652 self.emit_expr(&args[0]);
653 self.code.push(0x24); self.code.push(0x0c); }
656 }
657 "invert" => {
659 if args.len() == 1 {
660 self.emit_expr(&args[0]);
661 self.code.push(0x04); }
663 }
664 "len" => {
666 if args.len() == 1 {
667 self.emit_expr(&args[0]);
668 self.code.push(0x24); self.code.push(0x0c); }
671 }
672 "abs" => {
674 if args.len() == 1 {
675 self.emit_expr(&args[0]); self.code.push(0x0a); self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes()); self.code.push(0x14); let neg_patch = self.code.len() + 1;
682 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
683 self.code.push(0x0c); let end_patch = self.code.len() + 1;
686 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
687 let neg_addr = self.code.len() as u16;
689 self.patch_u16(neg_patch, neg_addr);
690 self.code.push(0x0c); self.code.push(0x04); let end_addr = self.code.len() as u16;
693 self.patch_u16(end_patch, end_addr);
694 }
695 }
696 "min" => {
698 if args.len() == 2 {
699 let a_reg = self.alloc_reg();
700 let b_reg = self.alloc_reg();
701 self.emit_expr(&args[0]);
702 self.code.push(0x08); self.code.push(a_reg); self.emit_expr(&args[1]);
704 self.code.push(0x08); self.code.push(b_reg); self.code.push(0x09); self.code.push(a_reg); self.code.push(0x09); self.code.push(b_reg); self.code.push(0x14); let a_smaller_patch = self.code.len() + 1;
710 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
711 self.code.push(0x0c); self.code.push(0x09); self.code.push(b_reg); let end_patch = self.code.len() + 1;
715 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
716 let a_smaller_addr = self.code.len() as u16;
718 self.patch_u16(a_smaller_patch, a_smaller_addr);
719 self.code.push(0x0c); self.code.push(0x09); self.code.push(a_reg); let end_addr = self.code.len() as u16;
722 self.patch_u16(end_patch, end_addr);
723 }
724 }
725 "max" => {
727 if args.len() == 2 {
728 let a_reg = self.alloc_reg();
729 let b_reg = self.alloc_reg();
730 self.emit_expr(&args[0]);
731 self.code.push(0x08); self.code.push(a_reg); self.emit_expr(&args[1]);
733 self.code.push(0x08); self.code.push(b_reg); self.code.push(0x09); self.code.push(b_reg); self.code.push(0x09); self.code.push(a_reg); self.code.push(0x14); let a_larger_patch = self.code.len() + 1;
739 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
740 self.code.push(0x0c); self.code.push(0x09); self.code.push(b_reg); let end_patch = self.code.len() + 1;
744 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
745 let a_larger_addr = self.code.len() as u16;
747 self.patch_u16(a_larger_patch, a_larger_addr);
748 self.code.push(0x0c); self.code.push(0x09); self.code.push(a_reg); let end_addr = self.code.len() as u16;
751 self.patch_u16(end_patch, end_addr);
752 }
753 }
754 "pow" => {
756 if args.len() == 2 {
757 let b_reg = self.alloc_reg(); let e_reg = self.alloc_reg(); let r_reg = self.alloc_reg(); self.emit_expr(&args[0]);
762 self.code.push(0x08); self.code.push(b_reg);
763 self.emit_expr(&args[1]);
765 self.code.push(0x08); self.code.push(e_reg);
766 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
768 self.code.push(0x08); self.code.push(r_reg);
769 let loop_start = self.code.len() as u16;
771 self.code.push(0x09); self.code.push(e_reg); self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes()); self.code.push(0x15); let body_patch = self.code.len() + 1;
776 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
777 self.code.push(0x0c);
779 let end_patch = self.code.len() + 1;
780 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
781 let body_addr = self.code.len() as u16;
783 self.patch_u16(body_patch, body_addr);
784 self.code.push(0x0c); self.code.push(0x09); self.code.push(r_reg);
787 self.code.push(0x09); self.code.push(b_reg);
788 self.code.push(0x03); self.code.push(0x08); self.code.push(r_reg);
790 self.code.push(0x09); self.code.push(e_reg);
792 self.code.push(0x17); self.code.extend_from_slice(&(-1i64).to_le_bytes());
793 self.code.push(0x18); self.code.push(0x08); self.code.push(e_reg);
795 self.code.push(0x0b); self.code.extend_from_slice(&loop_start.to_le_bytes());
797 let end_addr = self.code.len() as u16;
799 self.patch_u16(end_patch, end_addr);
800 self.code.push(0x09); self.code.push(r_reg);
802 }
803 }
804 "push" => {
809 for a in args { self.emit_expr(a); self.code.push(0x0c); } self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
812 "pop" => {
813 for a in args { self.emit_expr(a); self.code.push(0x0c); } self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
816 "mul" => {
817 for a in args { self.emit_expr(a); }
818 if args.len() == 2 { self.code.push(0x03); }
819 }
820 "truth" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Affirm])); }
821 "hold" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
822 "conflict" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Reject])); }
823 _ => {
824 for a in args {
825 let mut pushed_as_struct = false;
827 if let Expr::Ident(name) = a {
828 let mut fields_found = Vec::new();
833 for (_s_name, s_fields) in &self.struct_layouts {
834 let mut all_present = true;
835 let mut current_regs = Vec::new();
836 for f in s_fields {
837 let key = format!("{}.{}", name, f);
838 if let Some(&r) = self.symbols.get(&key) {
839 current_regs.push(r);
840 } else {
841 all_present = false;
842 break;
843 }
844 }
845 if all_present && !s_fields.is_empty() {
846 fields_found = current_regs;
847 break;
848 }
849 }
850
851 if !fields_found.is_empty() {
852 for reg in fields_found {
853 self.code.push(0x09); self.code.push(reg); }
855 if let Some(®) = self.symbols.get(name) {
857 self.code.push(0x09); self.code.push(reg); }
859 pushed_as_struct = true;
860 }
861 }
862
863 if !pushed_as_struct {
864 self.emit_expr(a);
865 }
866 }
867 self.code.push(0x10); if let Some(&addr) = self.func_addrs.get(callee) {
869 self.code.extend_from_slice(&addr.to_le_bytes());
870 } else {
871 let patch = self.code.len();
872 self.code.extend_from_slice(&[0, 0]);
873 self.function_patches.entry(callee.to_string()).or_default().push(patch);
874 }
875 }
876 }
877 }
878 Expr::Spawn { agent_name, .. } => {
879 if let Some(&type_id) = self.agent_type_ids.get(agent_name) {
880 self.code.push(0x30); self.code.extend_from_slice(&type_id.to_le_bytes());
882 } else {
883 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
884 }
885 }
886 Expr::Await { target } => {
887 self.emit_expr(target);
888 self.code.push(0x32); }
890 Expr::TritTensorLiteral(vs) => {
891 let rows = vs.len();
892 let cols = 1;
893 self.code.push(0x0f);
894 self.code.extend_from_slice(&(rows as u16).to_le_bytes());
895 self.code.extend_from_slice(&(cols as u16).to_le_bytes());
896 let tr = self.next_reg; self.next_reg += 1;
897 self.code.push(0x08); self.code.push(tr.try_into().unwrap());
898 for (idx, &v) in vs.iter().enumerate() {
899 self.code.push(0x09); self.code.push(tr.try_into().unwrap());
900 self.code.push(0x17); self.code.extend_from_slice(&(idx as i64).to_le_bytes());
901 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
902 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::from(v)]));
903 self.code.push(0x23);
904 }
905 self.code.push(0x09); self.code.push(tr.try_into().unwrap());
906 }
907 Expr::StructLiteral { .. } => {
908 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
911 }
912 Expr::Propagate { expr } => {
913 self.emit_expr(expr);
914 self.code.push(0x0a); let patch = self.code.len() + 1;
916 self.code.push(0x07); self.code.extend_from_slice(&[0, 0]); let skip = self.code.len() + 1;
918 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let early_ret = self.code.len() as u16;
920 self.patch_u16(patch, early_ret);
921 self.code.push(0x11); let next = self.code.len() as u16;
923 self.patch_u16(skip, next);
924 }
925 Expr::Index { object, row, col } => {
926 self.emit_expr(object); self.emit_expr(row); self.emit_expr(col);
927 self.code.push(0x22);
928 }
929 Expr::FieldAccess { object, field } => {
930 if let Expr::Ident(obj_name) = object.as_ref() {
931 let key = format!("{}.{}", obj_name, field);
932 if let Some(&r) = self.symbols.get(&key) {
933 self.code.push(0x09); self.code.push(r); }
935 }
936 }
937 Expr::Cast { expr, .. } => {
938 self.emit_expr(expr);
940 }
941 Expr::NodeId => {
942 self.code.push(0x36); }
949 }
950 }
951
952 pub fn emit_entry_call(&mut self, name: &str) {
953 if let Some(&addr) = self.func_addrs.get(name) {
954 self.code.push(0x10); self.code.extend_from_slice(&addr.to_le_bytes());
955 }
956 }
957
958 fn alloc_reg(&mut self) -> u8 {
962 let r = self.next_reg;
963 self.next_reg += 1;
964 if r > 255 {
965 eprintln!(
966 "[CODEGEN] Warning: register #{r} exceeds u8 range — \
967 this function has too many local variables (max 255). \
968 Split the function or reduce scope depth."
969 );
970 }
971 r as u8
972 }
973
974 pub fn get_agent_handlers(&self) -> Vec<(u16, usize)> {
975 self.agent_handlers.iter().map(|&(id, addr)| (id, addr as usize)).collect()
976 }
977
978 pub fn finalize(&mut self) -> Vec<u8> { std::mem::take(&mut self.code) }
979
980 fn patch_u16(&mut self, pos: usize, val: u16) {
981 let b = val.to_le_bytes();
982 self.code[pos] = b[0]; self.code[pos + 1] = b[1];
983 }
984}