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 pub 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_agent_def(&mut self, agent: &crate::AgentDef) {
58 let type_id = self.agent_type_ids.len() as u16;
59 self.agent_type_ids.insert(agent.name.clone(), type_id);
60 let mut handler_addr: Option<u16> = None;
61 for method in &agent.methods {
62 let addr = self.code.len() as u16;
63 if handler_addr.is_none() {
64 handler_addr = Some(addr);
65 }
66 self.emit_function(method);
67 self.func_addrs.insert(format!("{}::{}", agent.name, method.name), addr);
68 }
69 if let Some(addr) = handler_addr {
70 self.agent_handlers.push((type_id, addr));
71 }
72 }
73
74 pub fn emit_header_jump(&mut self) -> usize {
75 let patch_pos = self.code.len() + 1;
76 self.code.push(0x0b); self.code.extend_from_slice(&[0u8, 0u8]);
78 patch_pos
79 }
80
81 pub fn patch_header_jump(&mut self, patch_pos: usize) {
82 let addr = self.code.len() as u16;
83 self.patch_u16(patch_pos, addr);
84 }
85
86 pub fn emit_program(&mut self, program: &Program) {
87 let parent_next_reg = self.next_reg;
88 for s in &program.structs {
89 let names: Vec<String> = s.fields.iter().map(|(n, _)| n.clone()).collect();
90 self.struct_layouts.insert(s.name.clone(), names);
91 }
92 for (idx, agent) in program.agents.iter().enumerate() {
93 self.agent_type_ids.insert(agent.name.clone(), idx as u16);
94 }
95
96 let real_code = std::mem::take(&mut self.code);
98 let real_func_addrs = std::mem::take(&mut self.func_addrs);
99 let real_agent_handlers = std::mem::take(&mut self.agent_handlers);
100 let base_addr = real_code.len() as u16;
101
102 for agent in &program.agents {
103 let type_id = self.agent_type_ids[&agent.name];
104 let mut handler_addr = None;
105 for method in &agent.methods {
106 let addr = base_addr + self.code.len() as u16;
107 if handler_addr.is_none() { handler_addr = Some(addr); }
108 self.emit_function(method);
109 self.func_addrs.insert(format!("{}::{}", agent.name, method.name), addr);
111 }
112 if let Some(addr) = handler_addr { self.agent_handlers.push((type_id, addr)); }
113 }
114 for func in &program.functions {
115 let addr = base_addr + self.code.len() as u16;
116 self.func_addrs.insert(func.name.clone(), addr);
117 self.emit_function(func);
119 self.func_addrs.insert(func.name.clone(), addr);
123 }
124
125 let final_func_addrs = std::mem::replace(&mut self.func_addrs, real_func_addrs);
126 let final_agent_handlers = std::mem::replace(&mut self.agent_handlers, real_agent_handlers);
127 self.code = real_code;
128 self.func_addrs = final_func_addrs;
129 self.agent_handlers = final_agent_handlers;
130 self.next_reg = parent_next_reg;
131
132 for agent in &program.agents {
134 for method in &agent.methods { self.emit_function(method); }
135 }
136 for func in &program.functions { self.emit_function(func); }
137 }
138
139 pub fn emit_function(&mut self, func: &Function) {
140 let func_addr = self.code.len() as u16;
141 self.func_addrs.insert(func.name.clone(), func_addr);
142 if let Some(patches) = self.function_patches.remove(&func.name) {
143 for p in patches {
144 self.code[p..p + 2].copy_from_slice(&func_addr.to_le_bytes());
145 }
146 }
147 let parent_symbols = self.symbols.clone();
148 let parent_next_reg = self.next_reg;
149 self.next_reg = 0;
150
151 for (name, ty) in func.params.iter().rev() {
155 if let Type::Named(s_name) = ty {
156 if let Some(fields) = self.struct_layouts.get(s_name).cloned() {
157 let root_reg = self.alloc_reg();
162 self.symbols.insert(name.clone(), root_reg);
163 self.code.push(0x08); self.code.push(root_reg);
164
165 for f_name in fields.iter().rev() {
167 let f_reg = self.alloc_reg();
168 let key = format!("{}.{}", name, f_name);
169 self.symbols.insert(key, f_reg);
170 self.code.push(0x08); self.code.push(f_reg);
171 }
172 continue;
173 }
174 }
175 let reg = self.alloc_reg();
176 self.symbols.insert(name.clone(), reg);
177 self.code.push(0x08); self.code.push(reg);
178 }
179 for stmt in &func.body { self.emit_stmt(stmt); }
180 self.function_symbols.insert(func.name.clone(), self.symbols.clone());
182 self.symbols = parent_symbols;
183 self.next_reg = parent_next_reg;
184 self.code.push(0x11); }
186
187 pub fn emit_stmt(&mut self, stmt: &Stmt) {
188 match stmt {
189 Stmt::Let { name, ty, value } => {
190 let mut handled = false;
191 match ty {
192 Type::TritTensor { dims } => {
193 let is_zero_init = matches!(value, Expr::TritLiteral(0) | Expr::IntLiteral(0));
195 if !dims.is_empty() && !dims.contains(&0) && is_zero_init {
196 let rows = dims[0];
197 let cols = if dims.len() > 1 { dims[1] } else { 1 };
198 self.code.push(0x0f); self.code.extend_from_slice(&(rows as u32).to_le_bytes());
200 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
201 handled = true;
202 }
203 }
204 Type::PackedTritTensor { dims } => {
205 let is_zero_init = matches!(value, Expr::TritLiteral(0) | Expr::IntLiteral(0));
206 if !dims.is_empty() && !dims.contains(&0) && is_zero_init {
207 let rows = dims[0];
208 let cols = if dims.len() > 1 { dims[1] } else { 1 };
209 self.code.push(0x56); self.code.extend_from_slice(&(rows as u32).to_le_bytes());
211 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
212 handled = true;
213 }
214 }
215 Type::IntTensor { dims } => {
216 let is_zero_init = matches!(value, Expr::TritLiteral(0) | Expr::IntLiteral(0));
217 if !dims.is_empty() && !dims.contains(&0) && is_zero_init {
218 let rows = dims[0];
219 let cols = if dims.len() > 1 { dims[1] } else { 1 };
220 self.code.push(0x3c); self.code.extend_from_slice(&(rows as u32).to_le_bytes());
222 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
223 handled = true;
224 }
225 }
226 Type::FloatTensor { dims } => {
227 let is_zero_init = matches!(value, Expr::TritLiteral(0) | Expr::IntLiteral(0));
228 if !dims.is_empty() && !dims.contains(&0) && is_zero_init {
229 let rows = dims[0];
230 let cols = if dims.len() > 1 { dims[1] } else { 1 };
231 self.code.push(0x3d); self.code.extend_from_slice(&(rows as u32).to_le_bytes());
233 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
234 handled = true;
235 }
236 }
237 Type::Named(_) => {
238 if let Expr::StructLiteral { fields, .. } = value {
239 for (f_name, f_val) in fields {
241 self.emit_expr(f_val);
242 let reg = self.alloc_reg();
243 let key = format!("{}.{}", name, f_name);
244 self.symbols.insert(key, reg);
245 self.code.push(0x08); self.code.push(reg);
246 }
247 }
249 }
250 _ => {}
251 }
252 if !handled {
253 self.emit_expr(value);
254 }
255 let reg = self.alloc_reg();
256 self.symbols.insert(name.clone(), reg);
257 self.code.push(0x08); self.code.push(reg); }
259 Stmt::Set { name, value } => {
260 self.emit_expr(value);
261 if let Some(®) = self.symbols.get(name) {
262 self.code.push(0x08); self.code.push(reg);
263 }
264 }
265 Stmt::FieldSet { object, field, value } => {
266 let key = format!("{}.{}", object, field);
267 self.emit_expr(value);
268 if let Some(®) = self.symbols.get(&key) {
269 self.code.push(0x08); self.code.push(reg);
270 }
271 }
272 Stmt::IndexSet { object, row, col, value } => {
273 if let Some(®) = self.symbols.get(object) {
274 self.code.push(0x09); self.code.push(reg);
275 self.emit_expr(row);
276 self.emit_expr(col);
277 self.emit_expr(value);
278 self.code.push(0x23);
279 }
280 }
281 Stmt::IfTernary { condition, on_pos, on_zero, on_neg } => {
282 let pre_reg = self.next_reg;
283 self.emit_expr(condition);
284 let cond_reg = self.alloc_reg();
285 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;
292 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]); let zero_patch = self.code.len() + 1;
296 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.emit_stmt(on_neg);
301 let exit_patch = self.code.len() + 1;
302 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let pos_addr = self.code.len() as u16;
306 self.patch_u16(pos_patch, pos_addr);
307 self.code.push(0x0c); self.emit_stmt(on_pos);
309 let exit_pos = self.code.len() + 1;
310 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
311
312 let zero_addr = self.code.len() as u16;
314 self.patch_u16(zero_patch, zero_addr);
315 self.code.push(0x0c); self.emit_stmt(on_zero);
317
318 let end = self.code.len() as u16;
319 self.patch_u16(exit_patch, end);
320 self.patch_u16(exit_pos, end);
321 self.next_reg = pre_reg;
322 }
323 Stmt::Match { condition, arms } => {
324 let pre_reg = self.next_reg;
325 self.emit_expr(condition);
326 let cond_reg = self.alloc_reg();
327 self.code.push(0x08); self.code.push(cond_reg); let mut end_patches = Vec::new();
330 let mut next_arm_patch = None;
331
332 for (pattern, stmt) in arms {
333 if let Some(p) = next_arm_patch {
334 let addr = self.code.len() as u16;
335 self.patch_u16(p, addr);
336 }
337
338 self.code.push(0x09); self.code.push(cond_reg); let match_patch;
342 match pattern {
343 Pattern::Trit(1) | Pattern::Int(1) => {
344 self.code.push(0x05); match_patch = self.code.len();
346 self.code.extend_from_slice(&[0, 0]);
347 }
348 Pattern::Trit(0) | Pattern::Int(0) => {
349 self.code.push(0x06); match_patch = self.code.len();
351 self.code.extend_from_slice(&[0, 0]);
352 }
353 Pattern::Trit(-1) | Pattern::Int(-1) => {
354 self.code.push(0x07); match_patch = self.code.len();
356 self.code.extend_from_slice(&[0, 0]);
357 }
358 Pattern::Int(v) => {
359 self.code.push(0x25); self.code.extend_from_slice(&v.to_le_bytes());
361 match_patch = self.code.len();
362 self.code.extend_from_slice(&[0, 0]);
363 }
364 Pattern::Trit(v) => {
365 self.code.push(0x25); self.code.extend_from_slice(&(*v as i64).to_le_bytes());
367 match_patch = self.code.len();
368 self.code.extend_from_slice(&[0, 0]);
369 }
370 Pattern::Float(v) => {
371 self.code.push(0x2a); self.code.extend_from_slice(&v.to_le_bytes());
373 match_patch = self.code.len();
374 self.code.extend_from_slice(&[0, 0]);
375 }
376 Pattern::Wildcard => {
377 match_patch = self.code.len() + 1;
381 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); }
383 }
384
385 self.code.push(0x0c); let skip_patch = self.code.len() + 1;
391 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
392 next_arm_patch = Some(skip_patch);
393
394 let body_addr = self.code.len() as u16;
396 self.patch_u16(match_patch, body_addr);
397
398 self.code.push(0x0c); self.emit_stmt(stmt);
401
402 let end_patch = self.code.len() + 1;
404 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
405 end_patches.push(end_patch);
406 }
407
408 if let Some(p) = next_arm_patch {
409 let addr = self.code.len() as u16;
410 self.patch_u16(p, addr);
411 }
412
413 if !arms.is_empty() {
414 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
420 }
421
422 let end_addr = self.code.len() as u16;
423 for p in end_patches { self.patch_u16(p, end_addr); }
424 self.next_reg = pre_reg;
425 }
426 Stmt::ForIn { var, iter, body } => {
427 let pre_loop_reg = self.next_reg;
431
432 self.emit_expr(iter);
433 let it_reg = self.alloc_reg();
434 self.code.push(0x08); self.code.push(it_reg);
435 self.code.push(0x09); self.code.push(it_reg);
436 self.code.push(0x24); self.code.push(0x0c); let r_reg = self.alloc_reg();
439 self.code.push(0x08); self.code.push(r_reg); let i_reg = self.alloc_reg();
441 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
442 self.code.push(0x08); self.code.push(i_reg);
443
444 let cmp_reg = self.alloc_reg();
448
449 let top = self.code.len() as u16;
450 let pre_break = self.break_patches.len();
451 let pre_cont = self.continue_patches.len();
452
453 self.code.push(0x09); self.code.push(i_reg);
455 self.code.push(0x09); self.code.push(r_reg);
456 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;
462 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;
468 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.code.push(0x09); self.code.push(it_reg);
473 self.code.push(0x09); self.code.push(i_reg);
474 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
475 self.code.push(0x22);
476 let v_reg = self.alloc_reg();
477 self.symbols.insert(var.clone(), v_reg);
478 self.code.push(0x08); self.code.push(v_reg);
479 self.emit_stmt(body);
480
481 let cont_addr = self.code.len() as u16;
482 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
483 for p in cs { self.patch_u16(p, cont_addr); }
484
485 self.code.push(0x09); self.code.push(i_reg);
486 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
487 self.code.push(0x18);
488 self.code.push(0x08); self.code.push(i_reg);
489 let back = self.code.len() + 1;
490 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
491 self.patch_u16(back, top);
492
493 let neg_exit_addr = self.code.len() as u16;
496 self.patch_u16(neg, neg_exit_addr);
497 self.code.push(0x0c); let neg_to_end = self.code.len() + 1;
499 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
500
501 let zero_exit_addr = self.code.len() as u16;
502 self.patch_u16(zero, zero_exit_addr);
503 self.code.push(0x0c); let zero_to_end = self.code.len() + 1;
505 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
506
507 let end = self.code.len() as u16;
508 self.patch_u16(neg_to_end, end);
509 self.patch_u16(zero_to_end, end);
510 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
511 for p in bs { self.patch_u16(p, end); }
512
513 self.symbols.remove(var);
516 self.next_reg = pre_loop_reg;
517 }
518 Stmt::WhileTernary { condition, on_pos, on_zero, on_neg } => {
519 let pre_reg = self.next_reg;
520 let cond_reg = self.alloc_reg();
521 let top = self.code.len() as u16;
522 let pre_break = self.break_patches.len();
523 let pre_cont = self.continue_patches.len();
524
525 self.emit_expr(condition);
526 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;
533 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]); let zero_patch = self.code.len() + 1;
537 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.emit_stmt(on_neg);
542 let exit_neg = self.code.len() + 1;
543 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let pos_addr = self.code.len() as u16;
547 self.patch_u16(pos_patch, pos_addr);
548 self.code.push(0x0c); self.emit_stmt(on_pos);
550 let back_pos = self.code.len() + 1;
551 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
552 self.patch_u16(back_pos, top);
553
554 let zero_addr = self.code.len() as u16;
556 self.patch_u16(zero_patch, zero_addr);
557 self.code.push(0x0c); self.emit_stmt(on_zero);
559
560 let end = self.code.len() as u16;
561 self.patch_u16(exit_neg, end);
562
563 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
564 for p in cs { self.patch_u16(p, top); }
565 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
566 for p in bs { self.patch_u16(p, end); }
567 self.next_reg = pre_reg;
568 }
569 Stmt::Loop { body } => {
570 let top = self.code.len() as u16;
571 let pre_break = self.break_patches.len();
572 let pre_cont = self.continue_patches.len();
573 self.emit_stmt(body);
574 let back = self.code.len() + 1;
575 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
576 self.patch_u16(back, top);
577 let end = self.code.len() as u16;
578 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
579 for p in cs { self.patch_u16(p, top); }
580 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
581 for p in bs { self.patch_u16(p, end); }
582 }
583 Stmt::Break => {
584 let p = self.code.len() + 1;
585 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
586 self.break_patches.push(p);
587 }
588 Stmt::Continue => {
589 let p = self.code.len() + 1;
590 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
591 self.continue_patches.push(p);
592 }
593 Stmt::Send { target, message } => {
594 self.emit_expr(target);
595 self.emit_expr(message);
596 self.code.push(0x31); }
598 Stmt::Return(e) => { self.emit_expr(e); self.code.push(0x11); }
599 Stmt::Block(ss) => { for s in ss { self.emit_stmt(s); } }
600 Stmt::Expr(e) => { self.emit_expr(e); self.code.push(0x0c); }
601 Stmt::Decorated { directive: _, stmt } => { self.emit_stmt(stmt); }
602 _ => {}
603 }
604 }
605
606 fn emit_expr(&mut self, expr: &Expr) {
607 match expr {
608 Expr::TritLiteral(v) => {
609 self.code.push(0x01);
610 self.code.extend(pack_trits(&[Trit::from(*v)]));
611 }
612 Expr::IntLiteral(v) => {
613 self.code.push(0x17);
614 self.code.extend_from_slice(&v.to_le_bytes());
615 }
616 Expr::FloatLiteral(val) => {
617 self.code.push(0x19);
618 self.code.extend_from_slice(&val.to_le_bytes());
619 }
620 Expr::StringLiteral(val) => {
621 self.code.push(0x21); let bytes = val.as_bytes();
623 self.code.extend_from_slice(&(bytes.len() as u16).to_le_bytes());
624 self.code.extend_from_slice(bytes);
625 }
626 Expr::Ident(name) => {
627 match name.as_str() {
631 "true" => {
632 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
634 }
635 "false" => {
636 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
638 }
639 "affirm" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Affirm])); }
641 "hold" | "tend" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
642 "reject" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Reject])); }
643 _ => {
644 if let Some(&r) = self.symbols.get(name) {
645 self.code.push(0x09); self.code.push(r);
646 }
647 }
648 }
649 }
650 Expr::BinaryOp { op, lhs, rhs } => {
651 self.emit_expr(lhs); self.emit_expr(rhs);
652 match op {
653 BinOp::Add => self.code.push(0x02),
654 BinOp::Mul => self.code.push(0x03),
655 BinOp::Div => self.code.push(0x1e),
656 BinOp::Mod => self.code.push(0x1f),
657 BinOp::Sub => { self.code.push(0x04); self.code.push(0x02); }
658 BinOp::Equal => self.code.push(0x16),
659 BinOp::NotEqual => { self.code.push(0x16); self.code.push(0x04); }
660 BinOp::And => self.code.push(0x28), BinOp::Or => self.code.push(0x29), BinOp::Less => self.code.push(0x14),
663 BinOp::Greater => self.code.push(0x15),
664 BinOp::LessEqual => self.code.push(0x26),
665 BinOp::GreaterEqual => self.code.push(0x27),
666 }
667 }
668 Expr::UnaryOp { op, expr } => {
669 self.emit_expr(expr);
670 match op { UnOp::Neg => self.code.push(0x04) }
671 }
672 Expr::Call { callee, args } => {
673 match callee.as_str() {
674 "println" | "print" => {
676 if args.is_empty() {
677 } else {
679 for a in args {
680 self.emit_expr(a);
681 self.code.push(0x20); }
683 }
684 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
686 "opent" => {
687 if args.len() == 2 {
688 for a in args { self.emit_expr(a); }
689 self.code.push(0x33); } else {
691 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
693 }
694 }
695 "readt" => {
696 if args.len() == 1 {
697 self.emit_expr(&args[0]);
698 self.code.push(0x34); } else {
700 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
701 }
702 }
703 "writet" => {
704 if args.len() == 2 {
705 for a in args { self.emit_expr(a); }
706 self.code.push(0x35); }
708 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
710 "consensus" => {
711
712 for a in args { self.emit_expr(a); }
713 if args.len() == 2 { self.code.push(0x0e); }
714 }
715 "length" => {
716 if args.len() == 1 {
717 self.emit_expr(&args[0]);
718 self.code.push(0x24); self.code.push(0x0c); }
721 }
722 "invert" => {
724 if args.len() == 1 {
725 self.emit_expr(&args[0]);
726 self.code.push(0x04); }
728 }
729 "len" => {
731 if args.len() == 1 {
732 self.emit_expr(&args[0]);
733 self.code.push(0x24); self.code.push(0x0c); }
736 }
737 "abs" => {
739 if args.len() == 1 {
740 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;
747 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
748 self.code.push(0x0c); let end_patch = self.code.len() + 1;
751 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
752 let neg_addr = self.code.len() as u16;
754 self.patch_u16(neg_patch, neg_addr);
755 self.code.push(0x0c); self.code.push(0x04); let end_addr = self.code.len() as u16;
758 self.patch_u16(end_patch, end_addr);
759 }
760 }
761 "min" => {
763 if args.len() == 2 {
764 let a_reg = self.alloc_reg();
765 let b_reg = self.alloc_reg();
766 self.emit_expr(&args[0]);
767 self.code.push(0x08); self.code.push(a_reg); self.emit_expr(&args[1]);
769 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;
775 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
776 self.code.push(0x0c); self.code.push(0x09); self.code.push(b_reg); let end_patch = self.code.len() + 1;
780 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
781 let a_smaller_addr = self.code.len() as u16;
783 self.patch_u16(a_smaller_patch, a_smaller_addr);
784 self.code.push(0x0c); self.code.push(0x09); self.code.push(a_reg); let end_addr = self.code.len() as u16;
787 self.patch_u16(end_patch, end_addr);
788 }
789 }
790 "max" => {
792 if args.len() == 2 {
793 let a_reg = self.alloc_reg();
794 let b_reg = self.alloc_reg();
795 self.emit_expr(&args[0]);
796 self.code.push(0x08); self.code.push(a_reg); self.emit_expr(&args[1]);
798 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;
804 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
805 self.code.push(0x0c); self.code.push(0x09); self.code.push(b_reg); let end_patch = self.code.len() + 1;
809 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
810 let a_larger_addr = self.code.len() as u16;
812 self.patch_u16(a_larger_patch, a_larger_addr);
813 self.code.push(0x0c); self.code.push(0x09); self.code.push(a_reg); let end_addr = self.code.len() as u16;
816 self.patch_u16(end_patch, end_addr);
817 }
818 }
819 "pow" => {
821 if args.len() == 2 {
822 let b_reg = self.alloc_reg(); let e_reg = self.alloc_reg(); let r_reg = self.alloc_reg(); self.emit_expr(&args[0]);
827 self.code.push(0x08); self.code.push(b_reg);
828 self.emit_expr(&args[1]);
830 self.code.push(0x08); self.code.push(e_reg);
831 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
833 self.code.push(0x08); self.code.push(r_reg);
834 let loop_start = self.code.len() as u16;
836 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;
841 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
842 self.code.push(0x0c);
844 let end_patch = self.code.len() + 1;
845 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
846 let body_addr = self.code.len() as u16;
848 self.patch_u16(body_patch, body_addr);
849 self.code.push(0x0c); self.code.push(0x09); self.code.push(r_reg);
852 self.code.push(0x09); self.code.push(b_reg);
853 self.code.push(0x03); self.code.push(0x08); self.code.push(r_reg);
855 self.code.push(0x09); self.code.push(e_reg);
857 self.code.push(0x17); self.code.extend_from_slice(&(-1i64).to_le_bytes());
858 self.code.push(0x18); self.code.push(0x08); self.code.push(e_reg);
860 self.code.push(0x0b); self.code.extend_from_slice(&loop_start.to_le_bytes());
862 let end_addr = self.code.len() as u16;
864 self.patch_u16(end_patch, end_addr);
865 self.code.push(0x09); self.code.push(r_reg);
867 }
868 }
869 "push" => {
874 for a in args { self.emit_expr(a); self.code.push(0x0c); } self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
877 "pop" => {
878 for a in args { self.emit_expr(a); self.code.push(0x0c); } self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
881 "pack" => {
882 for a in args { self.emit_expr(a); }
883 if args.len() == 5 { self.code.push(0x50); }
884 }
885 "unpack" => {
886 if args.len() == 1 { self.emit_expr(&args[0]); self.code.push(0x51); }
887 }
888 "v_add" => {
889 if args.len() == 2 { for a in args { self.emit_expr(a); } self.code.push(0x52); }
890 }
891 "v_neg" => {
892 if args.len() == 1 { self.emit_expr(&args[0]); self.code.push(0x53); }
893 }
894 "v_con" => {
895 if args.len() == 2 { for a in args { self.emit_expr(a); } self.code.push(0x54); }
896 }
897 "bind" => {
898 if args.len() == 2 {
899 if let Expr::Ident(name) = &args[0] {
900 if let Some(®) = self.symbols.get(name) {
901 self.emit_expr(&args[1]);
902 self.code.push(0x42); self.code.push(reg);
904 }
905 }
906 }
907 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
908 }
909 "mul" => {
910 for a in args { self.emit_expr(a); }
911 if args.len() == 2 { self.code.push(0x03); }
912 }
913 "truth" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Affirm])); }
914 "hold" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
915 "conflict" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Reject])); }
916 _ => {
917 for a in args {
918 let mut pushed_as_struct = false;
920 if let Expr::Ident(name) = a {
921 let mut fields_found = Vec::new();
926 for (_s_name, s_fields) in &self.struct_layouts {
927 let mut all_present = true;
928 let mut current_regs = Vec::new();
929 for f in s_fields {
930 let key = format!("{}.{}", name, f);
931 if let Some(&r) = self.symbols.get(&key) {
932 current_regs.push(r);
933 } else {
934 all_present = false;
935 break;
936 }
937 }
938 if all_present && !s_fields.is_empty() {
939 fields_found = current_regs;
940 break;
941 }
942 }
943
944 if !fields_found.is_empty() {
945 for reg in fields_found {
946 self.code.push(0x09); self.code.push(reg); }
948 if let Some(®) = self.symbols.get(name) {
950 self.code.push(0x09); self.code.push(reg); }
952 pushed_as_struct = true;
953 }
954 }
955
956 if !pushed_as_struct {
957 self.emit_expr(a);
958 }
959 }
960 self.code.push(0x10); if let Some(&addr) = self.func_addrs.get(callee) {
962 self.code.extend_from_slice(&addr.to_le_bytes());
963 } else {
964 let patch = self.code.len();
965 self.code.extend_from_slice(&[0, 0]);
966 self.function_patches.entry(callee.to_string()).or_default().push(patch);
967 }
968 }
969 }
970 }
971 Expr::Spawn { agent_name, .. } => {
972 if let Some(&type_id) = self.agent_type_ids.get(agent_name) {
973 self.code.push(0x30); self.code.extend_from_slice(&type_id.to_le_bytes());
975 } else {
976 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
977 }
978 }
979 Expr::Await { target } => {
980 self.emit_expr(target);
981 self.code.push(0x32); }
983 Expr::Slice { object, start, end, stride } => {
984 self.emit_expr(object);
985 self.emit_expr(start);
986 self.emit_expr(end);
988 self.emit_expr(start);
989 self.code.push(0x04); self.code.push(0x02); self.emit_expr(stride);
991 self.code.push(0x55); }
993 Expr::TritTensorLiteral(vs) => {
994 let rows = vs.len();
995 let cols = 1;
996 self.code.push(0x0f);
997 self.code.extend_from_slice(&(rows as u32).to_le_bytes());
998 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
999 let tr = self.next_reg; self.next_reg += 1;
1000 self.code.push(0x08); self.code.push(tr.try_into().unwrap());
1001 for (idx, &v) in vs.iter().enumerate() {
1002 self.code.push(0x09); self.code.push(tr.try_into().unwrap());
1003 self.code.push(0x17); self.code.extend_from_slice(&(idx as i64).to_le_bytes());
1004 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
1005 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::from(v)]));
1006 self.code.push(0x23);
1007 }
1008 self.code.push(0x09); self.code.push(tr.try_into().unwrap());
1009 }
1010 Expr::StructLiteral { fields, .. } => {
1011 for (_, f_val) in fields {
1012 self.emit_expr(f_val);
1013 }
1014 self.code.push(0x40); self.code.push(fields.len() as u8);
1016 for (f_name, _) in fields.iter().rev() {
1018 self.code.push(f_name.len() as u8);
1019 self.code.extend_from_slice(f_name.as_bytes());
1020 }
1021 }
1022 Expr::Propagate { expr } => {
1023 self.emit_expr(expr);
1024 self.code.push(0x0a); let patch = self.code.len() + 1;
1026 self.code.push(0x07); self.code.extend_from_slice(&[0, 0]); let skip = self.code.len() + 1;
1028 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let early_ret = self.code.len() as u16;
1030 self.patch_u16(patch, early_ret);
1031 self.code.push(0x11); let next = self.code.len() as u16;
1033 self.patch_u16(skip, next);
1034 }
1035 Expr::Index { object, row, col } => {
1036 self.emit_expr(object); self.emit_expr(row); self.emit_expr(col);
1037 self.code.push(0x22);
1038 }
1039 Expr::FieldAccess { object, field } => {
1040 if let Expr::Ident(obj_name) = object.as_ref() {
1041 let key = format!("{}.{}", obj_name, field);
1042 if let Some(&r) = self.symbols.get(&key) {
1043 self.code.push(0x09); self.code.push(r); }
1045 }
1046 }
1047 Expr::Cast { expr, .. } => {
1048 self.emit_expr(expr);
1050 }
1051 Expr::NodeId => {
1052 self.code.push(0x36); }
1059 }
1060 }
1061
1062 pub fn emit_entry_call(&mut self, name: &str) {
1063 if let Some(&addr) = self.func_addrs.get(name) {
1064 self.code.push(0x10); self.code.extend_from_slice(&addr.to_le_bytes());
1065 }
1066 }
1067
1068 fn alloc_reg(&mut self) -> u8 {
1072 let r = self.next_reg;
1073 self.next_reg += 1;
1074 if r > 255 {
1075 eprintln!(
1076 "[CODEGEN] Warning: register #{r} exceeds u8 range — \
1077 this function has too many local variables (max 255). \
1078 Split the function or reduce scope depth."
1079 );
1080 }
1081 r as u8
1082 }
1083
1084 pub fn get_agent_handlers(&self) -> Vec<(u16, usize)> {
1085 self.agent_handlers.iter().map(|&(id, addr)| (id, addr as usize)).collect()
1086 }
1087
1088 pub fn finalize(&mut self) -> Vec<u8> { std::mem::take(&mut self.code) }
1089
1090 fn patch_u16(&mut self, pos: usize, val: u16) {
1091 let b = val.to_le_bytes();
1092 self.code[pos] = b[0]; self.code[pos + 1] = b[1];
1093 }
1094}