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 in_sparseskip: bool,
22}
23
24impl BytecodeEmitter {
25 pub fn new() -> Self {
26 Self {
27 code: Vec::new(),
28 symbols: std::collections::HashMap::new(),
29 func_addrs: std::collections::HashMap::new(),
30 function_patches: std::collections::HashMap::new(),
31 break_patches: Vec::new(),
32 continue_patches: Vec::new(),
33 next_reg: 0,
34 struct_layouts: std::collections::HashMap::new(),
35 agent_type_ids: std::collections::HashMap::new(),
36 agent_handlers: Vec::new(),
37 function_symbols: std::collections::HashMap::new(),
38 in_sparseskip: false,
39 }
40 }
41
42 pub fn get_symbols(&self) -> &std::collections::HashMap<String, u8> {
44 &self.symbols
45 }
46
47 pub fn get_function_symbols(&self, name: &str) -> Option<&std::collections::HashMap<String, u8>> {
50 self.function_symbols.get(name)
51 }
52
53 pub fn register_agents(&self, vm: &mut crate::vm::BetVm) {
54 for &(type_id, addr) in &self.agent_handlers {
55 vm.register_agent_type(type_id, addr as usize);
56 }
57 }
58
59 pub fn emit_agent_def(&mut self, agent: &crate::AgentDef) {
62 let type_id = self.agent_type_ids.len() as u16;
63 self.agent_type_ids.insert(agent.name.clone(), type_id);
64 let mut handler_addr: Option<u16> = None;
65 for method in &agent.methods {
66 let addr = self.code.len() as u16;
67 if handler_addr.is_none() {
68 handler_addr = Some(addr);
69 }
70 self.emit_function(method);
71 self.func_addrs.insert(format!("{}::{}", agent.name, method.name), addr);
72 }
73 if let Some(addr) = handler_addr {
74 self.agent_handlers.push((type_id, addr));
75 }
76 }
77
78 pub fn emit_header_jump(&mut self) -> usize {
79 let patch_pos = self.code.len() + 1;
80 self.code.push(0x0b); self.code.extend_from_slice(&[0u8, 0u8]);
82 patch_pos
83 }
84
85 pub fn patch_header_jump(&mut self, patch_pos: usize) {
86 let addr = self.code.len() as u16;
87 self.patch_u16(patch_pos, addr);
88 }
89
90 pub fn emit_program(&mut self, program: &Program) {
91 let parent_next_reg = self.next_reg;
92 for s in &program.structs {
93 let names: Vec<String> = s.fields.iter().map(|(n, _)| n.clone()).collect();
94 self.struct_layouts.insert(s.name.clone(), names);
95 }
96 for (idx, agent) in program.agents.iter().enumerate() {
97 self.agent_type_ids.insert(agent.name.clone(), idx as u16);
98 }
99
100 let real_code = std::mem::take(&mut self.code);
102 let real_func_addrs = std::mem::take(&mut self.func_addrs);
103 let real_agent_handlers = std::mem::take(&mut self.agent_handlers);
104 let base_addr = real_code.len() as u16;
105
106 for agent in &program.agents {
107 let type_id = self.agent_type_ids[&agent.name];
108 let mut handler_addr = None;
109 for method in &agent.methods {
110 let addr = base_addr + self.code.len() as u16;
111 if handler_addr.is_none() { handler_addr = Some(addr); }
112 self.emit_function(method);
113 self.func_addrs.insert(format!("{}::{}", agent.name, method.name), addr);
115 }
116 if let Some(addr) = handler_addr { self.agent_handlers.push((type_id, addr)); }
117 }
118 for func in &program.functions {
119 let addr = base_addr + self.code.len() as u16;
120 self.func_addrs.insert(func.name.clone(), addr);
121 self.emit_function(func);
123 self.func_addrs.insert(func.name.clone(), addr);
127 }
128
129 let final_func_addrs = std::mem::replace(&mut self.func_addrs, real_func_addrs);
130 let final_agent_handlers = std::mem::replace(&mut self.agent_handlers, real_agent_handlers);
131 self.code = real_code;
132 self.func_addrs = final_func_addrs;
133 self.agent_handlers = final_agent_handlers;
134 self.next_reg = parent_next_reg;
135
136 for agent in &program.agents {
138 for method in &agent.methods { self.emit_function(method); }
139 }
140 for func in &program.functions { self.emit_function(func); }
141 }
142
143 pub fn emit_function(&mut self, func: &Function) {
144 let func_addr = self.code.len() as u16;
145 self.func_addrs.insert(func.name.clone(), func_addr);
146 if let Some(patches) = self.function_patches.remove(&func.name) {
147 for p in patches {
148 self.code[p..p + 2].copy_from_slice(&func_addr.to_le_bytes());
149 }
150 }
151 let parent_symbols = self.symbols.clone();
152 let parent_next_reg = self.next_reg;
153 let parent_in_sparseskip = self.in_sparseskip;
154 self.next_reg = 0;
155 self.in_sparseskip = func.directive.as_deref() == Some("sparseskip");
156
157 for (name, ty) in func.params.iter().rev() {
158 if let Type::Named(s_name) = ty {
159 if let Some(fields) = self.struct_layouts.get(s_name).cloned() {
160 let root_reg = self.alloc_reg();
165 self.symbols.insert(name.clone(), root_reg);
166 self.code.push(0x08); self.code.push(root_reg);
167
168 for f_name in fields.iter().rev() {
170 let f_reg = self.alloc_reg();
171 let key = format!("{}.{}", name, f_name);
172 self.symbols.insert(key, f_reg);
173 self.code.push(0x08); self.code.push(f_reg);
174 }
175 continue;
176 }
177 }
178 let reg = self.alloc_reg();
179 self.symbols.insert(name.clone(), reg);
180 self.code.push(0x08); self.code.push(reg);
181 }
182 for stmt in &func.body { self.emit_stmt(stmt); }
183 self.function_symbols.insert(func.name.clone(), self.symbols.clone());
185 self.symbols = parent_symbols;
186 self.next_reg = parent_next_reg;
187 self.in_sparseskip = parent_in_sparseskip;
188 self.code.push(0x11); }
190
191 pub fn emit_stmt(&mut self, stmt: &Stmt) {
192 match stmt {
193 Stmt::Let { name, ty, value } => {
194 let mut handled = false;
195 match ty {
196 Type::TritTensor { dims } => {
197 let is_zero_init = matches!(value, Expr::TritLiteral(0) | Expr::IntLiteral(0));
199 if !dims.is_empty() && !dims.contains(&0) && is_zero_init {
200 let rows = dims[0];
201 let cols = if dims.len() > 1 { dims[1] } else { 1 };
202 self.code.push(0x0f); self.code.extend_from_slice(&(rows as u32).to_le_bytes());
204 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
205 handled = true;
206 }
207 }
208 Type::PackedTritTensor { dims } => {
209 let is_zero_init = matches!(value, Expr::TritLiteral(0) | Expr::IntLiteral(0));
210 if !dims.is_empty() && !dims.contains(&0) && is_zero_init {
211 let rows = dims[0];
212 let cols = if dims.len() > 1 { dims[1] } else { 1 };
213 self.code.push(0x56); self.code.extend_from_slice(&(rows as u32).to_le_bytes());
215 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
216 handled = true;
217 }
218 }
219 Type::IntTensor { dims } => {
220 let is_zero_init = matches!(value, Expr::TritLiteral(0) | Expr::IntLiteral(0));
221 if !dims.is_empty() && !dims.contains(&0) && is_zero_init {
222 let rows = dims[0];
223 let cols = if dims.len() > 1 { dims[1] } else { 1 };
224 self.code.push(0x3c); self.code.extend_from_slice(&(rows as u32).to_le_bytes());
226 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
227 handled = true;
228 }
229 }
230 Type::FloatTensor { dims } => {
231 let is_zero_init = matches!(value, Expr::TritLiteral(0) | Expr::IntLiteral(0));
232 if !dims.is_empty() && !dims.contains(&0) && is_zero_init {
233 let rows = dims[0];
234 let cols = if dims.len() > 1 { dims[1] } else { 1 };
235 self.code.push(0x3d); self.code.extend_from_slice(&(rows as u32).to_le_bytes());
237 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
238 handled = true;
239 }
240 }
241 Type::Named(_) => {
242 if let Expr::StructLiteral { fields, .. } = value {
243 for (f_name, f_val) in fields {
245 self.emit_expr(f_val);
246 let reg = self.alloc_reg();
247 let key = format!("{}.{}", name, f_name);
248 self.symbols.insert(key, reg);
249 self.code.push(0x08); self.code.push(reg);
250 }
251 }
253 }
254 _ => {}
255 }
256 if !handled {
257 self.emit_expr(value);
258 }
259 let reg = self.alloc_reg();
260 self.symbols.insert(name.clone(), reg);
261 self.code.push(0x08); self.code.push(reg); }
263 Stmt::Set { name, value } => {
264 self.emit_expr(value);
265 if let Some(®) = self.symbols.get(name) {
266 self.code.push(0x08); self.code.push(reg);
267 }
268 }
269 Stmt::FieldSet { object, field, value } => {
270 let key = format!("{}.{}", object, field);
271 self.emit_expr(value);
272 if let Some(®) = self.symbols.get(&key) {
273 self.code.push(0x08); self.code.push(reg);
274 }
275 }
276 Stmt::IndexSet { object, row, col, value } => {
277 if let Some(®) = self.symbols.get(object) {
278 self.code.push(0x09); self.code.push(reg);
279 self.emit_expr(row);
280 self.emit_expr(col);
281 self.emit_expr(value);
282 self.code.push(0x23);
283 }
284 }
285 Stmt::IfTernary { condition, on_pos, on_zero, on_neg } => {
286 let pre_reg = self.next_reg;
287 self.emit_expr(condition);
288 let cond_reg = self.alloc_reg();
289 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;
296 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]); let zero_patch = self.code.len() + 1;
300 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.emit_stmt(on_neg);
305 let exit_patch = self.code.len() + 1;
306 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let pos_addr = self.code.len() as u16;
310 self.patch_u16(pos_patch, pos_addr);
311 self.code.push(0x0c); self.emit_stmt(on_pos);
313 let exit_pos = self.code.len() + 1;
314 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
315
316 let zero_addr = self.code.len() as u16;
318 self.patch_u16(zero_patch, zero_addr);
319 self.code.push(0x0c); self.emit_stmt(on_zero);
321
322 let end = self.code.len() as u16;
323 self.patch_u16(exit_patch, end);
324 self.patch_u16(exit_pos, end);
325 self.next_reg = pre_reg;
326 }
327 Stmt::Match { condition, arms } => {
328 let pre_reg = self.next_reg;
329 self.emit_expr(condition);
330 let cond_reg = self.alloc_reg();
331 self.code.push(0x08); self.code.push(cond_reg); let mut end_patches = Vec::new();
334 let mut next_arm_patch = None;
335
336 for (pattern, stmt) in arms {
337 if let Some(p) = next_arm_patch {
338 let addr = self.code.len() as u16;
339 self.patch_u16(p, addr);
340 }
341
342 self.code.push(0x09); self.code.push(cond_reg); let match_patch;
346 match pattern {
347 Pattern::Trit(1) | Pattern::Int(1) => {
348 self.code.push(0x05); match_patch = self.code.len();
350 self.code.extend_from_slice(&[0, 0]);
351 }
352 Pattern::Trit(0) | Pattern::Int(0) => {
353 self.code.push(0x06); match_patch = self.code.len();
355 self.code.extend_from_slice(&[0, 0]);
356 }
357 Pattern::Trit(-1) | Pattern::Int(-1) => {
358 self.code.push(0x07); match_patch = self.code.len();
360 self.code.extend_from_slice(&[0, 0]);
361 }
362 Pattern::Int(v) => {
363 self.code.push(0x25); self.code.extend_from_slice(&v.to_le_bytes());
365 match_patch = self.code.len();
366 self.code.extend_from_slice(&[0, 0]);
367 }
368 Pattern::Trit(v) => {
369 self.code.push(0x25); self.code.extend_from_slice(&(*v as i64).to_le_bytes());
371 match_patch = self.code.len();
372 self.code.extend_from_slice(&[0, 0]);
373 }
374 Pattern::Float(v) => {
375 self.code.push(0x2a); self.code.extend_from_slice(&v.to_le_bytes());
377 match_patch = self.code.len();
378 self.code.extend_from_slice(&[0, 0]);
379 }
380 Pattern::Wildcard => {
381 match_patch = self.code.len() + 1;
385 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); }
387 }
388
389 self.code.push(0x0c); let skip_patch = self.code.len() + 1;
395 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
396 next_arm_patch = Some(skip_patch);
397
398 let body_addr = self.code.len() as u16;
400 self.patch_u16(match_patch, body_addr);
401
402 self.code.push(0x0c); self.emit_stmt(stmt);
405
406 let end_patch = self.code.len() + 1;
408 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
409 end_patches.push(end_patch);
410 }
411
412 if let Some(p) = next_arm_patch {
413 let addr = self.code.len() as u16;
414 self.patch_u16(p, addr);
415 }
416
417 if !arms.is_empty() {
418 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
424 }
425
426 let end_addr = self.code.len() as u16;
427 for p in end_patches { self.patch_u16(p, end_addr); }
428 self.next_reg = pre_reg;
429 }
430 Stmt::ForIn { var, iter, body } => {
431 let pre_loop_reg = self.next_reg;
435
436 self.emit_expr(iter);
437 let it_reg = self.alloc_reg();
438 self.code.push(0x08); self.code.push(it_reg);
439 self.code.push(0x09); self.code.push(it_reg);
440 self.code.push(0x24); self.code.push(0x0c); let r_reg = self.alloc_reg();
443 self.code.push(0x08); self.code.push(r_reg); let i_reg = self.alloc_reg();
445 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
446 self.code.push(0x08); self.code.push(i_reg);
447
448 let cmp_reg = self.alloc_reg();
452
453 let top = self.code.len() as u16;
454 let pre_break = self.break_patches.len();
455 let pre_cont = self.continue_patches.len();
456
457 self.code.push(0x09); self.code.push(i_reg);
459 self.code.push(0x09); self.code.push(r_reg);
460 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;
466 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;
472 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.code.push(0x09); self.code.push(it_reg);
477 self.code.push(0x09); self.code.push(i_reg);
478 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
479 self.code.push(0x22);
480 let v_reg = self.alloc_reg();
481 self.symbols.insert(var.clone(), v_reg);
482 self.code.push(0x08); self.code.push(v_reg);
483 self.emit_stmt(body);
484
485 let cont_addr = self.code.len() as u16;
486 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
487 for p in cs { self.patch_u16(p, cont_addr); }
488
489 self.code.push(0x09); self.code.push(i_reg);
490 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
491 self.code.push(0x18);
492 self.code.push(0x08); self.code.push(i_reg);
493 let back = self.code.len() + 1;
494 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
495 self.patch_u16(back, top);
496
497 let neg_exit_addr = self.code.len() as u16;
500 self.patch_u16(neg, neg_exit_addr);
501 self.code.push(0x0c); let neg_to_end = self.code.len() + 1;
503 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
504
505 let zero_exit_addr = self.code.len() as u16;
506 self.patch_u16(zero, zero_exit_addr);
507 self.code.push(0x0c); let zero_to_end = self.code.len() + 1;
509 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
510
511 let end = self.code.len() as u16;
512 self.patch_u16(neg_to_end, end);
513 self.patch_u16(zero_to_end, end);
514 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
515 for p in bs { self.patch_u16(p, end); }
516
517 self.symbols.remove(var);
520 self.next_reg = pre_loop_reg;
521 }
522 Stmt::WhileTernary { condition, on_pos, on_zero, on_neg } => {
523 let pre_reg = self.next_reg;
524 let cond_reg = self.alloc_reg();
525 let top = self.code.len() as u16;
526 let pre_break = self.break_patches.len();
527 let pre_cont = self.continue_patches.len();
528
529 self.emit_expr(condition);
530 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;
537 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]); let zero_patch = self.code.len() + 1;
541 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.emit_stmt(on_neg);
546 let exit_neg = self.code.len() + 1;
547 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let pos_addr = self.code.len() as u16;
551 self.patch_u16(pos_patch, pos_addr);
552 self.code.push(0x0c); self.emit_stmt(on_pos);
554 let back_pos = self.code.len() + 1;
555 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
556 self.patch_u16(back_pos, top);
557
558 let zero_addr = self.code.len() as u16;
560 self.patch_u16(zero_patch, zero_addr);
561 self.code.push(0x0c); self.emit_stmt(on_zero);
563
564 let end = self.code.len() as u16;
565 self.patch_u16(exit_neg, end);
566
567 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
568 for p in cs { self.patch_u16(p, top); }
569 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
570 for p in bs { self.patch_u16(p, end); }
571 self.next_reg = pre_reg;
572 }
573 Stmt::Loop { body } => {
574 let top = self.code.len() as u16;
575 let pre_break = self.break_patches.len();
576 let pre_cont = self.continue_patches.len();
577 self.emit_stmt(body);
578 let back = self.code.len() + 1;
579 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
580 self.patch_u16(back, top);
581 let end = self.code.len() as u16;
582 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
583 for p in cs { self.patch_u16(p, top); }
584 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
585 for p in bs { self.patch_u16(p, end); }
586 }
587 Stmt::Break => {
588 let p = self.code.len() + 1;
589 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
590 self.break_patches.push(p);
591 }
592 Stmt::Continue => {
593 let p = self.code.len() + 1;
594 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
595 self.continue_patches.push(p);
596 }
597 Stmt::Send { target, message } => {
598 self.emit_expr(target);
599 self.emit_expr(message);
600 self.code.push(0x31); }
602 Stmt::Return(e) => { self.emit_expr(e); self.code.push(0x11); }
603 Stmt::Block(ss) => { for s in ss { self.emit_stmt(s); } }
604 Stmt::Expr(e) => { self.emit_expr(e); self.code.push(0x0c); }
605 Stmt::Decorated { directive: _, stmt } => { self.emit_stmt(stmt); }
606 _ => {}
607 }
608 }
609
610 fn emit_expr(&mut self, expr: &Expr) {
611 match expr {
612 Expr::TritLiteral(v) => {
613 self.code.push(0x01);
614 self.code.extend(pack_trits(&[Trit::from(*v)]));
615 }
616 Expr::IntLiteral(v) => {
617 self.code.push(0x17);
618 self.code.extend_from_slice(&v.to_le_bytes());
619 }
620 Expr::FloatLiteral(val) => {
621 self.code.push(0x19);
622 self.code.extend_from_slice(&val.to_le_bytes());
623 }
624 Expr::StringLiteral(val) => {
625 self.code.push(0x21); let bytes = val.as_bytes();
627 self.code.extend_from_slice(&(bytes.len() as u16).to_le_bytes());
628 self.code.extend_from_slice(bytes);
629 }
630 Expr::Ident(name) => {
631 match name.as_str() {
635 "true" => {
636 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
638 }
639 "false" => {
640 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
642 }
643 "affirm" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Affirm])); }
645 "hold" | "tend" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
646 "reject" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Reject])); }
647 _ => {
648 if let Some(&r) = self.symbols.get(name) {
649 self.code.push(0x09); self.code.push(r);
650 }
651 }
652 }
653 }
654 Expr::BinaryOp { op, lhs, rhs } => {
655 self.emit_expr(lhs); self.emit_expr(rhs);
656 match op {
657 BinOp::Add => self.code.push(0x02),
658 BinOp::Mul => self.code.push(0x03),
659 BinOp::Div => self.code.push(0x1e),
660 BinOp::Mod => self.code.push(0x1f),
661 BinOp::Sub => { self.code.push(0x04); self.code.push(0x02); }
662 BinOp::Equal => self.code.push(0x16),
663 BinOp::NotEqual => { self.code.push(0x16); self.code.push(0x04); }
664 BinOp::And => self.code.push(0x28), BinOp::Or => self.code.push(0x29), BinOp::Less => self.code.push(0x14),
667 BinOp::Greater => self.code.push(0x15),
668 BinOp::LessEqual => self.code.push(0x26),
669 BinOp::GreaterEqual => self.code.push(0x27),
670 }
671 }
672 Expr::UnaryOp { op, expr } => {
673 self.emit_expr(expr);
674 match op { UnOp::Neg => self.code.push(0x04) }
675 }
676 Expr::Call { callee, args } => {
677 match callee.as_str() {
678 "println" | "print" => {
680 if args.is_empty() {
681 } else {
683 for a in args {
684 self.emit_expr(a);
685 self.code.push(0x20); }
687 }
688 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
690 "opent" => {
691 if args.len() == 2 {
692 for a in args { self.emit_expr(a); }
693 self.code.push(0x33); } else {
695 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
697 }
698 }
699 "readt" => {
700 if args.len() == 1 {
701 self.emit_expr(&args[0]);
702 self.code.push(0x34); } else {
704 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
705 }
706 }
707 "writet" => {
708 if args.len() == 2 {
709 for a in args { self.emit_expr(a); }
710 self.code.push(0x35); }
712 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
714 "consensus" => {
715
716 for a in args { self.emit_expr(a); }
717 if args.len() == 2 { self.code.push(0x0e); }
718 }
719 "length" => {
720 if args.len() == 1 {
721 self.emit_expr(&args[0]);
722 self.code.push(0x24); self.code.push(0x0c); }
725 }
726 "invert" => {
728 if args.len() == 1 {
729 self.emit_expr(&args[0]);
730 self.code.push(0x04); }
732 }
733 "len" => {
735 if args.len() == 1 {
736 self.emit_expr(&args[0]);
737 self.code.push(0x24); self.code.push(0x0c); }
740 }
741 "abs" => {
743 if args.len() == 1 {
744 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;
751 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
752 self.code.push(0x0c); let end_patch = self.code.len() + 1;
755 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
756 let neg_addr = self.code.len() as u16;
758 self.patch_u16(neg_patch, neg_addr);
759 self.code.push(0x0c); self.code.push(0x04); let end_addr = self.code.len() as u16;
762 self.patch_u16(end_patch, end_addr);
763 }
764 }
765 "min" => {
767 if args.len() == 2 {
768 let a_reg = self.alloc_reg();
769 let b_reg = self.alloc_reg();
770 self.emit_expr(&args[0]);
771 self.code.push(0x08); self.code.push(a_reg); self.emit_expr(&args[1]);
773 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;
779 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
780 self.code.push(0x0c); self.code.push(0x09); self.code.push(b_reg); let end_patch = self.code.len() + 1;
784 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
785 let a_smaller_addr = self.code.len() as u16;
787 self.patch_u16(a_smaller_patch, a_smaller_addr);
788 self.code.push(0x0c); self.code.push(0x09); self.code.push(a_reg); let end_addr = self.code.len() as u16;
791 self.patch_u16(end_patch, end_addr);
792 }
793 }
794 "max" => {
796 if args.len() == 2 {
797 let a_reg = self.alloc_reg();
798 let b_reg = self.alloc_reg();
799 self.emit_expr(&args[0]);
800 self.code.push(0x08); self.code.push(a_reg); self.emit_expr(&args[1]);
802 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;
808 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
809 self.code.push(0x0c); self.code.push(0x09); self.code.push(b_reg); let end_patch = self.code.len() + 1;
813 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
814 let a_larger_addr = self.code.len() as u16;
816 self.patch_u16(a_larger_patch, a_larger_addr);
817 self.code.push(0x0c); self.code.push(0x09); self.code.push(a_reg); let end_addr = self.code.len() as u16;
820 self.patch_u16(end_patch, end_addr);
821 }
822 }
823 "pow" => {
825 if args.len() == 2 {
826 let b_reg = self.alloc_reg(); let e_reg = self.alloc_reg(); let r_reg = self.alloc_reg(); self.emit_expr(&args[0]);
831 self.code.push(0x08); self.code.push(b_reg);
832 self.emit_expr(&args[1]);
834 self.code.push(0x08); self.code.push(e_reg);
835 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
837 self.code.push(0x08); self.code.push(r_reg);
838 let loop_start = self.code.len() as u16;
840 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;
845 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
846 self.code.push(0x0c);
848 let end_patch = self.code.len() + 1;
849 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
850 let body_addr = self.code.len() as u16;
852 self.patch_u16(body_patch, body_addr);
853 self.code.push(0x0c); self.code.push(0x09); self.code.push(r_reg);
856 self.code.push(0x09); self.code.push(b_reg);
857 self.code.push(0x03); self.code.push(0x08); self.code.push(r_reg);
859 self.code.push(0x09); self.code.push(e_reg);
861 self.code.push(0x17); self.code.extend_from_slice(&(-1i64).to_le_bytes());
862 self.code.push(0x18); self.code.push(0x08); self.code.push(e_reg);
864 self.code.push(0x0b); self.code.extend_from_slice(&loop_start.to_le_bytes());
866 let end_addr = self.code.len() as u16;
868 self.patch_u16(end_patch, end_addr);
869 self.code.push(0x09); self.code.push(r_reg);
871 }
872 }
873 "push" => {
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 "pop" => {
882 for a in args { self.emit_expr(a); self.code.push(0x0c); } self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
885 "pack" => {
886 for a in args { self.emit_expr(a); }
887 if args.len() == 5 { self.code.push(0x50); }
888 }
889 "unpack" => {
890 if args.len() == 1 { self.emit_expr(&args[0]); self.code.push(0x51); }
891 }
892 "v_add" => {
893 if args.len() == 2 { for a in args { self.emit_expr(a); } self.code.push(0x52); }
894 }
895 "v_neg" => {
896 if args.len() == 1 { self.emit_expr(&args[0]); self.code.push(0x53); }
897 }
898 "v_con" => {
899 if args.len() == 2 { for a in args { self.emit_expr(a); } self.code.push(0x54); }
900 }
901 "bind" => {
902 if args.len() == 2 {
903 if let Expr::Ident(name) = &args[0] {
904 if let Some(®) = self.symbols.get(name) {
905 self.emit_expr(&args[1]);
906 self.code.push(0x42); self.code.push(reg);
908 }
909 }
910 }
911 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
912 }
913 "mul" => {
914 for a in args { self.emit_expr(a); }
915 if args.len() == 2 { self.code.push(0x03); }
916 }
917 "truth" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Affirm])); }
918 "hold" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
919 "conflict" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Reject])); }
920 "matmul" => {
924 if args.len() == 2 {
925 for a in args { self.emit_expr(a); }
926 if self.in_sparseskip {
927 self.code.push(0x38); self.code.push(0x00); self.code.push(0x00); self.code.push(0x00); } else {
932 self.code.push(0x10); if let Some(&addr) = self.func_addrs.get("matmul") {
934 self.code.extend_from_slice(&addr.to_le_bytes());
935 } else {
936 let patch = self.code.len();
937 self.code.extend_from_slice(&[0, 0]);
938 self.function_patches.entry("matmul".to_string()).or_default().push(patch);
939 }
940 }
941 } else {
942 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
943 }
944 }
945 "explain" => {
949 if args.len() == 2 {
950 for a in args { self.emit_expr(a); }
951 self.code.push(0x60); }
953 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
954 }
955 _ => {
956 for a in args {
957 let mut pushed_as_struct = false;
959 if let Expr::Ident(name) = a {
960 let mut fields_found = Vec::new();
965 for (_s_name, s_fields) in &self.struct_layouts {
966 let mut all_present = true;
967 let mut current_regs = Vec::new();
968 for f in s_fields {
969 let key = format!("{}.{}", name, f);
970 if let Some(&r) = self.symbols.get(&key) {
971 current_regs.push(r);
972 } else {
973 all_present = false;
974 break;
975 }
976 }
977 if all_present && !s_fields.is_empty() {
978 fields_found = current_regs;
979 break;
980 }
981 }
982
983 if !fields_found.is_empty() {
984 for reg in fields_found {
985 self.code.push(0x09); self.code.push(reg); }
987 if let Some(®) = self.symbols.get(name) {
989 self.code.push(0x09); self.code.push(reg); }
991 pushed_as_struct = true;
992 }
993 }
994
995 if !pushed_as_struct {
996 self.emit_expr(a);
997 }
998 }
999 self.code.push(0x10); if let Some(&addr) = self.func_addrs.get(callee) {
1001 self.code.extend_from_slice(&addr.to_le_bytes());
1002 } else {
1003 let patch = self.code.len();
1004 self.code.extend_from_slice(&[0, 0]);
1005 self.function_patches.entry(callee.to_string()).or_default().push(patch);
1006 }
1007 }
1008 }
1009 }
1010 Expr::Spawn { agent_name, .. } => {
1011 if let Some(&type_id) = self.agent_type_ids.get(agent_name) {
1012 self.code.push(0x30); self.code.extend_from_slice(&type_id.to_le_bytes());
1014 } else {
1015 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
1016 }
1017 }
1018 Expr::Await { target } => {
1019 self.emit_expr(target);
1020 self.code.push(0x32); }
1022 Expr::Slice { object, start, end, stride } => {
1023 self.emit_expr(object);
1024 self.emit_expr(start);
1025 self.emit_expr(end);
1027 self.emit_expr(start);
1028 self.code.push(0x04); self.code.push(0x02); self.emit_expr(stride);
1030 self.code.push(0x55); }
1032 Expr::TritTensorLiteral(vs) => {
1033 let rows = vs.len();
1034 let cols = 1;
1035 self.code.push(0x0f);
1036 self.code.extend_from_slice(&(rows as u32).to_le_bytes());
1037 self.code.extend_from_slice(&(cols as u32).to_le_bytes());
1038 let tr = self.next_reg; self.next_reg += 1;
1039 self.code.push(0x08); self.code.push(tr.try_into().unwrap());
1040 for (idx, &v) in vs.iter().enumerate() {
1041 self.code.push(0x09); self.code.push(tr.try_into().unwrap());
1042 self.code.push(0x17); self.code.extend_from_slice(&(idx as i64).to_le_bytes());
1043 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
1044 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::from(v)]));
1045 self.code.push(0x23);
1046 }
1047 self.code.push(0x09); self.code.push(tr.try_into().unwrap());
1048 }
1049 Expr::StructLiteral { fields, .. } => {
1050 for (_, f_val) in fields {
1051 self.emit_expr(f_val);
1052 }
1053 self.code.push(0x40); self.code.push(fields.len() as u8);
1055 for (f_name, _) in fields.iter().rev() {
1057 self.code.push(f_name.len() as u8);
1058 self.code.extend_from_slice(f_name.as_bytes());
1059 }
1060 }
1061 Expr::Propagate { expr } => {
1062 self.emit_expr(expr);
1063 self.code.push(0x0a); let patch = self.code.len() + 1;
1065 self.code.push(0x07); self.code.extend_from_slice(&[0, 0]); let skip = self.code.len() + 1;
1067 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let early_ret = self.code.len() as u16;
1069 self.patch_u16(patch, early_ret);
1070 self.code.push(0x11); let next = self.code.len() as u16;
1072 self.patch_u16(skip, next);
1073 }
1074 Expr::Index { object, row, col } => {
1075 self.emit_expr(object); self.emit_expr(row); self.emit_expr(col);
1076 self.code.push(0x22);
1077 }
1078 Expr::FieldAccess { object, field } => {
1079 if let Expr::Ident(obj_name) = object.as_ref() {
1080 let key = format!("{}.{}", obj_name, field);
1081 if let Some(&r) = self.symbols.get(&key) {
1082 self.code.push(0x09); self.code.push(r); } else if let Some(&r) = self.symbols.get(obj_name) {
1085 self.code.push(0x09); self.code.push(r); self.code.push(0x41); self.code.push(field.len() as u8);
1090 self.code.extend_from_slice(field.as_bytes());
1091 }
1092 }
1093 }
1094 Expr::Cast { expr, ty } => {
1095 self.emit_expr(expr);
1096 match ty {
1097 crate::ast::Type::Int => { self.code.push(0x57); } crate::ast::Type::Float => { self.code.push(0x58); } _ => {} }
1101 }
1102 Expr::NodeId => {
1103 self.code.push(0x36); }
1110 }
1111 }
1112
1113 pub fn emit_entry_call(&mut self, name: &str) {
1114 if let Some(&addr) = self.func_addrs.get(name) {
1115 self.code.push(0x10); self.code.extend_from_slice(&addr.to_le_bytes());
1116 }
1117 }
1118
1119 fn alloc_reg(&mut self) -> u8 {
1123 let r = self.next_reg;
1124 self.next_reg += 1;
1125 if r > 255 {
1126 eprintln!(
1127 "[CODEGEN] Warning: register #{r} exceeds u8 range — \
1128 this function has too many local variables (max 255). \
1129 Split the function or reduce scope depth."
1130 );
1131 }
1132 r as u8
1133 }
1134
1135 pub fn get_agent_handlers(&self) -> Vec<(u16, usize)> {
1136 self.agent_handlers.iter().map(|&(id, addr)| (id, addr as usize)).collect()
1137 }
1138
1139 pub fn finalize(&mut self) -> Vec<u8> { std::mem::take(&mut self.code) }
1140
1141 fn patch_u16(&mut self, pos: usize, val: u16) {
1142 let b = val.to_le_bytes();
1143 self.code[pos] = b[0]; self.code[pos + 1] = b[1];
1144 }
1145}