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: u8,
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);
91 }
92 if let Some(addr) = handler_addr { self.agent_handlers.push((type_id, addr)); }
93 }
94 for func in &program.functions {
95 let addr = base_addr + self.code.len() as u16;
96 self.func_addrs.insert(func.name.clone(), addr);
97 self.emit_function(func);
99 }
100
101 let final_func_addrs = std::mem::replace(&mut self.func_addrs, real_func_addrs);
102 let final_agent_handlers = std::mem::replace(&mut self.agent_handlers, real_agent_handlers);
103 self.code = real_code;
104 self.func_addrs = final_func_addrs;
105 self.agent_handlers = final_agent_handlers;
106 self.next_reg = parent_next_reg;
107
108 for agent in &program.agents {
110 for method in &agent.methods { self.emit_function(method); }
111 }
112 for func in &program.functions { self.emit_function(func); }
113 }
114
115 pub fn emit_function(&mut self, func: &Function) {
116 let func_addr = self.code.len() as u16;
117 self.func_addrs.insert(func.name.clone(), func_addr);
118 if let Some(patches) = self.function_patches.remove(&func.name) {
119 for p in patches {
120 self.code[p..p + 2].copy_from_slice(&func_addr.to_le_bytes());
121 }
122 }
123 let parent_symbols = self.symbols.clone();
124 let parent_next_reg = self.next_reg;
125 self.next_reg = 0;
126
127 for (name, ty) in func.params.iter().rev() {
131 if let Type::Named(s_name) = ty {
132 if let Some(fields) = self.struct_layouts.get(s_name).cloned() {
133 let root_reg = self.next_reg;
138 self.symbols.insert(name.clone(), root_reg);
139 self.next_reg += 1;
140 self.code.push(0x08); self.code.push(root_reg);
141
142 for f_name in fields.iter().rev() {
144 let f_reg = self.next_reg;
145 let key = format!("{}.{}", name, f_name);
146 self.symbols.insert(key, f_reg);
147 self.next_reg += 1;
148 self.code.push(0x08); self.code.push(f_reg);
149 }
150 continue;
151 }
152 }
153 let reg = self.next_reg;
154 self.symbols.insert(name.clone(), reg);
155 self.next_reg += 1;
156 self.code.push(0x08); self.code.push(reg);
157 }
158 for stmt in &func.body { self.emit_stmt(stmt); }
159 self.function_symbols.insert(func.name.clone(), self.symbols.clone());
161 self.symbols = parent_symbols;
162 self.next_reg = parent_next_reg;
163 self.code.push(0x11); }
165
166 pub fn emit_stmt(&mut self, stmt: &Stmt) {
167 match stmt {
168 Stmt::Let { name, ty, value } => {
169 let mut handled = false;
170 if let Type::TritTensor { dims } = ty {
171 if !dims.is_empty() && !dims.contains(&0) && !matches!(value, Expr::TritTensorLiteral(_)) {
173 let rows = dims[0];
174 let cols = if dims.len() > 1 { dims[1] } else { 1 };
175 self.code.push(0x0f);
176 self.code.extend_from_slice(&(rows as u16).to_le_bytes());
177 self.code.extend_from_slice(&(cols as u16).to_le_bytes());
178 handled = true;
179 }
180 } else if let Type::Named(_) = ty {
181 if let Expr::StructLiteral { fields, .. } = value {
182 for (f_name, f_val) in fields {
184 self.emit_expr(f_val);
185 let reg = self.next_reg;
186 let key = format!("{}.{}", name, f_name);
187 self.symbols.insert(key, reg);
188 self.next_reg += 1;
189 self.code.push(0x08); self.code.push(reg);
190 }
191 }
193 }
194 if !handled {
195 self.emit_expr(value);
196 }
197 let reg = self.next_reg;
198 self.symbols.insert(name.clone(), reg);
199 self.next_reg += 1;
200 self.code.push(0x08); self.code.push(reg); }
202 Stmt::Set { name, value } => {
203 self.emit_expr(value);
204 if let Some(®) = self.symbols.get(name) {
205 self.code.push(0x08); self.code.push(reg);
206 }
207 }
208 Stmt::FieldSet { object, field, value } => {
209 let key = format!("{}.{}", object, field);
210 self.emit_expr(value);
211 if let Some(®) = self.symbols.get(&key) {
212 self.code.push(0x08); self.code.push(reg);
213 }
214 }
215 Stmt::IndexSet { object, row, col, value } => {
216 if let Some(®) = self.symbols.get(object) {
217 self.code.push(0x09); self.code.push(reg);
218 self.emit_expr(row);
219 self.emit_expr(col);
220 self.emit_expr(value);
221 self.code.push(0x23);
222 }
223 }
224 Stmt::IfTernary { condition, on_pos, on_zero, on_neg } => {
225 self.emit_expr(condition);
226 self.code.push(0x0a);
227 let pos_patch = self.code.len() + 1;
228 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]);
229 self.code.push(0x0a);
230 let zero_patch = self.code.len() + 1;
231 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]);
232 self.code.push(0x0c);
233 self.emit_stmt(on_neg);
234 let exit_patch = self.code.len() + 1;
235 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
236 let pos_addr = self.code.len() as u16;
237 self.patch_u16(pos_patch, pos_addr);
238 self.code.push(0x0c);
239 self.emit_stmt(on_pos);
240 let exit_pos = self.code.len() + 1;
241 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
242 let zero_addr = self.code.len() as u16;
243 self.patch_u16(zero_patch, zero_addr);
244 self.code.push(0x0c);
245 self.emit_stmt(on_zero);
246 let end = self.code.len() as u16;
247 self.patch_u16(exit_patch, end);
248 self.patch_u16(exit_pos, end);
249 }
250 Stmt::Match { condition, arms } => {
251 self.emit_expr(condition);
252 let cond_reg = self.next_reg; self.next_reg += 1;
253 self.code.push(0x08); self.code.push(cond_reg); let mut end_patches = Vec::new();
256 let mut next_arm_patch = None;
257
258 for (val, stmt) in arms {
259 if let Some(p) = next_arm_patch {
260 let addr = self.code.len() as u16;
261 self.patch_u16(p, addr);
262 }
263
264 self.code.push(0x09); self.code.push(cond_reg); let match_patch;
268 match val {
269 1 => {
270 self.code.push(0x05); match_patch = self.code.len();
272 self.code.extend_from_slice(&[0, 0]);
273 }
274 0 => {
275 self.code.push(0x06); match_patch = self.code.len();
277 self.code.extend_from_slice(&[0, 0]);
278 }
279 -1 => {
280 self.code.push(0x07); match_patch = self.code.len();
282 self.code.extend_from_slice(&[0, 0]);
283 }
284 v => {
285 self.code.push(0x25); self.code.extend_from_slice(&v.to_le_bytes());
287 match_patch = self.code.len();
288 self.code.extend_from_slice(&[0, 0]);
289 }
290 }
291
292 let skip_patch = self.code.len() + 1;
294 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
295 next_arm_patch = Some(skip_patch);
296
297 let body_addr = self.code.len() as u16;
299 self.patch_u16(match_patch, body_addr);
300
301 self.code.push(0x0c); self.emit_stmt(stmt);
304
305 let end_patch = self.code.len() + 1;
307 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
308 end_patches.push(end_patch);
309 }
310
311 if let Some(p) = next_arm_patch {
312 let addr = self.code.len() as u16;
313 self.patch_u16(p, addr);
314 }
315
316 if !arms.is_empty() {
319 self.code.push(0x0c); }
321
322 let end_addr = self.code.len() as u16;
323 for p in end_patches { self.patch_u16(p, end_addr); }
324 self.next_reg -= 1;
325 }
326 Stmt::ForIn { var, iter, body } => {
327 self.emit_expr(iter);
328 let it_reg = self.next_reg; self.next_reg += 1;
329 self.code.push(0x08); self.code.push(it_reg);
330 self.code.push(0x09); self.code.push(it_reg);
331 self.code.push(0x24); self.code.push(0x0c); let r_reg = self.next_reg; self.next_reg += 1;
334 self.code.push(0x08); self.code.push(r_reg); let i_reg = self.next_reg; self.next_reg += 1;
336 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
337 self.code.push(0x08); self.code.push(i_reg);
338
339 let top = self.code.len() as u16;
340 let pre_break = self.break_patches.len();
341 let pre_cont = self.continue_patches.len();
342
343 self.code.push(0x09); self.code.push(i_reg);
344 self.code.push(0x09); self.code.push(r_reg);
345 self.code.push(0x14);
346 self.code.push(0x0a);
347 let neg = self.code.len() + 1;
348 self.code.push(0x07); self.code.extend_from_slice(&[0, 0]);
349 self.code.push(0x0a);
350 let zero = self.code.len() + 1;
351 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]);
352 self.code.push(0x0c);
353 self.code.push(0x09); self.code.push(it_reg);
354 self.code.push(0x09); self.code.push(i_reg);
355 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
356 self.code.push(0x22);
357 let v_reg = self.next_reg; self.next_reg += 1;
358 self.symbols.insert(var.clone(), v_reg);
359 self.code.push(0x08); self.code.push(v_reg);
360 self.emit_stmt(body);
361
362 let cont_addr = self.code.len() as u16;
363 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
364 for p in cs { self.patch_u16(p, cont_addr); }
365
366 self.code.push(0x09); self.code.push(i_reg);
367 self.code.push(0x17); self.code.extend_from_slice(&1i64.to_le_bytes());
368 self.code.push(0x18);
369 self.code.push(0x08); self.code.push(i_reg);
370 let back = self.code.len() + 1;
371 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
372 self.patch_u16(back, top);
373 let end = self.code.len() as u16;
374 self.patch_u16(neg, end); self.patch_u16(zero, end);
375 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
376 for p in bs { self.patch_u16(p, end); }
377 }
378 Stmt::WhileTernary { condition, on_pos, on_zero, on_neg } => {
379 let top = self.code.len() as u16;
380 let pre_break = self.break_patches.len();
381 let pre_cont = self.continue_patches.len();
382
383 self.emit_expr(condition);
384 self.code.push(0x0a); let pos_patch = self.code.len() + 1;
386 self.code.push(0x05); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0a); let zero_patch = self.code.len() + 1;
389 self.code.push(0x06); self.code.extend_from_slice(&[0, 0]); self.code.push(0x0c); self.emit_stmt(on_neg);
394 let exit_neg = self.code.len() + 1;
395 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let pos_addr = self.code.len() as u16;
399 self.patch_u16(pos_patch, pos_addr);
400 self.code.push(0x0c); self.emit_stmt(on_pos);
402 let back_pos = self.code.len() + 1;
403 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
404 self.patch_u16(back_pos, top);
405
406 let zero_addr = self.code.len() as u16;
408 self.patch_u16(zero_patch, zero_addr);
409 self.code.push(0x0c); self.emit_stmt(on_zero);
411
412 let end = self.code.len() as u16;
413 self.patch_u16(exit_neg, end);
414
415 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
416 for p in cs { self.patch_u16(p, top); }
417 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
418 for p in bs { self.patch_u16(p, end); }
419 }
420 Stmt::Loop { body } => {
421 let top = self.code.len() as u16;
422 let pre_break = self.break_patches.len();
423 let pre_cont = self.continue_patches.len();
424 self.emit_stmt(body);
425 let back = self.code.len() + 1;
426 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
427 self.patch_u16(back, top);
428 let end = self.code.len() as u16;
429 let cs: Vec<usize> = self.continue_patches.drain(pre_cont..).collect();
430 for p in cs { self.patch_u16(p, top); }
431 let bs: Vec<usize> = self.break_patches.drain(pre_break..).collect();
432 for p in bs { self.patch_u16(p, end); }
433 }
434 Stmt::Break => {
435 let p = self.code.len() + 1;
436 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
437 self.break_patches.push(p);
438 }
439 Stmt::Continue => {
440 let p = self.code.len() + 1;
441 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]);
442 self.continue_patches.push(p);
443 }
444 Stmt::Send { target, message } => {
445 self.emit_expr(target);
446 self.emit_expr(message);
447 self.code.push(0x31); }
449 Stmt::Return(e) => { self.emit_expr(e); self.code.push(0x11); }
450 Stmt::Block(ss) => { for s in ss { self.emit_stmt(s); } }
451 Stmt::Expr(e) => { self.emit_expr(e); self.code.push(0x0c); }
452 Stmt::Decorated { directive: _, stmt } => { self.emit_stmt(stmt); }
453 _ => {}
454 }
455 }
456
457 fn emit_expr(&mut self, expr: &Expr) {
458 match expr {
459 Expr::TritLiteral(v) => {
460 self.code.push(0x01);
461 self.code.extend(pack_trits(&[Trit::from(*v)]));
462 }
463 Expr::IntLiteral(v) => {
464 self.code.push(0x17);
465 self.code.extend_from_slice(&v.to_le_bytes());
466 }
467 Expr::FloatLiteral(val) => {
468 self.code.push(0x19);
469 self.code.extend_from_slice(&val.to_le_bytes());
470 }
471 Expr::StringLiteral(val) => {
472 self.code.push(0x21); let bytes = val.as_bytes();
474 self.code.extend_from_slice(&(bytes.len() as u16).to_le_bytes());
475 self.code.extend_from_slice(bytes);
476 }
477 Expr::Ident(name) => {
478 if let Some(&r) = self.symbols.get(name) {
479 self.code.push(0x09); self.code.push(r);
480 }
481 }
482 Expr::BinaryOp { op, lhs, rhs } => {
483 self.emit_expr(lhs); self.emit_expr(rhs);
484 match op {
485 BinOp::Add => self.code.push(0x02),
486 BinOp::Mul => self.code.push(0x03),
487 BinOp::Div => self.code.push(0x1e),
488 BinOp::Mod => self.code.push(0x1f),
489 BinOp::Sub => { self.code.push(0x04); self.code.push(0x02); }
490 BinOp::Equal => self.code.push(0x16),
491 BinOp::NotEqual => { self.code.push(0x16); self.code.push(0x04); }
492 BinOp::And => self.code.push(0x28), BinOp::Or => self.code.push(0x29), BinOp::Less => self.code.push(0x14),
495 BinOp::Greater => self.code.push(0x15),
496 BinOp::LessEqual => self.code.push(0x26),
497 BinOp::GreaterEqual => self.code.push(0x27),
498 }
499 }
500 Expr::UnaryOp { op, expr } => {
501 self.emit_expr(expr);
502 match op { UnOp::Neg => self.code.push(0x04) }
503 }
504 Expr::Call { callee, args } => {
505 match callee.as_str() {
506 "print" | "println" => {
507 for a in args {
508 self.emit_expr(a);
509 self.code.push(0x20); }
511 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
513 "consensus" => {
514 for a in args { self.emit_expr(a); }
515 if args.len() == 2 { self.code.push(0x0e); }
516 }
517 "length" => {
518 if args.len() == 1 {
519 self.emit_expr(&args[0]);
520 self.code.push(0x24); self.code.push(0x0c); }
523 }
524 "mul" => {
525 for a in args { self.emit_expr(a); }
526 if args.len() == 2 { self.code.push(0x03); }
527 }
528 "truth" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Affirm])); }
529 "hold" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend])); }
530 "conflict" => { self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Reject])); }
531 _ => {
532 for a in args {
533 let mut pushed_as_struct = false;
535 if let Expr::Ident(name) = a {
536 let mut fields_found = Vec::new();
541 for (_s_name, s_fields) in &self.struct_layouts {
542 let mut all_present = true;
543 let mut current_regs = Vec::new();
544 for f in s_fields {
545 let key = format!("{}.{}", name, f);
546 if let Some(&r) = self.symbols.get(&key) {
547 current_regs.push(r);
548 } else {
549 all_present = false;
550 break;
551 }
552 }
553 if all_present && !s_fields.is_empty() {
554 fields_found = current_regs;
555 break;
556 }
557 }
558
559 if !fields_found.is_empty() {
560 for reg in fields_found {
561 self.code.push(0x09); self.code.push(reg); }
563 if let Some(®) = self.symbols.get(name) {
565 self.code.push(0x09); self.code.push(reg); }
567 pushed_as_struct = true;
568 }
569 }
570
571 if !pushed_as_struct {
572 self.emit_expr(a);
573 }
574 }
575 self.code.push(0x10); if let Some(&addr) = self.func_addrs.get(callee) {
577 self.code.extend_from_slice(&addr.to_le_bytes());
578 } else {
579 let patch = self.code.len();
580 self.code.extend_from_slice(&[0, 0]);
581 self.function_patches.entry(callee.to_string()).or_default().push(patch);
582 }
583 }
584 }
585 }
586 Expr::Spawn { agent_name, .. } => {
587 if let Some(&type_id) = self.agent_type_ids.get(agent_name) {
588 self.code.push(0x30); self.code.extend_from_slice(&type_id.to_le_bytes());
590 } else {
591 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
592 }
593 }
594 Expr::Await { target } => {
595 self.emit_expr(target);
596 self.code.push(0x32); }
598 Expr::TritTensorLiteral(vs) => {
599 let rows = vs.len();
600 let cols = 1;
601 self.code.push(0x0f);
602 self.code.extend_from_slice(&(rows as u16).to_le_bytes());
603 self.code.extend_from_slice(&(cols as u16).to_le_bytes());
604 let tr = self.next_reg; self.next_reg += 1;
605 self.code.push(0x08); self.code.push(tr);
606 for (idx, &v) in vs.iter().enumerate() {
607 self.code.push(0x09); self.code.push(tr);
608 self.code.push(0x17); self.code.extend_from_slice(&(idx as i64).to_le_bytes());
609 self.code.push(0x17); self.code.extend_from_slice(&0i64.to_le_bytes());
610 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::from(v)]));
611 self.code.push(0x23);
612 }
613 self.code.push(0x09); self.code.push(tr);
614 }
615 Expr::StructLiteral { .. } => {
616 self.code.push(0x01); self.code.extend(pack_trits(&[Trit::Tend]));
619 }
620 Expr::Propagate { expr } => {
621 self.emit_expr(expr);
622 self.code.push(0x0a); let patch = self.code.len() + 1;
624 self.code.push(0x07); self.code.extend_from_slice(&[0, 0]); let skip = self.code.len() + 1;
626 self.code.push(0x0b); self.code.extend_from_slice(&[0, 0]); let early_ret = self.code.len() as u16;
628 self.patch_u16(patch, early_ret);
629 self.code.push(0x11); let next = self.code.len() as u16;
631 self.patch_u16(skip, next);
632 }
633 Expr::Index { object, row, col } => {
634 self.emit_expr(object); self.emit_expr(row); self.emit_expr(col);
635 self.code.push(0x22);
636 }
637 Expr::FieldAccess { object, field } => {
638 if let Expr::Ident(obj_name) = object.as_ref() {
639 let key = format!("{}.{}", obj_name, field);
640 if let Some(&r) = self.symbols.get(&key) {
641 self.code.push(0x09); self.code.push(r); }
643 }
644 }
645 Expr::Cast { expr, .. } => {
646 self.emit_expr(expr);
648 }
649 Expr::NodeId => {
650 let bytes = b"127.0.0.1:7373";
651 self.code.push(0x21);
652 self.code.extend_from_slice(&(bytes.len() as u16).to_le_bytes());
653 self.code.extend_from_slice(bytes);
654 }
655 }
656 }
657
658 pub fn emit_entry_call(&mut self, name: &str) {
659 if let Some(&addr) = self.func_addrs.get(name) {
660 self.code.push(0x10); self.code.extend_from_slice(&addr.to_le_bytes());
661 }
662 }
663
664 pub fn get_agent_handlers(&self) -> Vec<(u16, usize)> {
665 self.agent_handlers.iter().map(|&(id, addr)| (id, addr as usize)).collect()
666 }
667
668 pub fn finalize(&mut self) -> Vec<u8> { std::mem::take(&mut self.code) }
669
670 fn patch_u16(&mut self, pos: usize, val: u16) {
671 let b = val.to_le_bytes();
672 self.code[pos] = b[0]; self.code[pos + 1] = b[1];
673 }
674}