1use crate::ast::*;
57use std::collections::HashMap;
58
59struct RegAlloc {
62 map: HashMap<String, u8>,
63 next: u8,
64}
65
66impl RegAlloc {
67 fn new() -> Self { Self { map: HashMap::new(), next: 2 } } fn alloc(&mut self, name: &str) -> u8 {
69 if let Some(&r) = self.map.get(name) { return r; }
70 let r = self.next;
71 self.next += 1;
72 self.map.insert(name.to_string(), r);
73 r
74 }
75 fn get(&self, name: &str) -> u8 {
76 *self.map.get(name).unwrap_or(&1) }
78 fn scratch(&mut self) -> u8 {
79 let r = self.next;
80 self.next += 1;
81 r
82 }
83 fn snapshot(&self) -> HashMap<String, u8> {
84 self.map.clone()
85 }
86 fn restore(&mut self, snap: HashMap<String, u8>, next: u8) {
87 self.map = snap;
88 self.next = next;
89 }
90}
91
92fn reg(n: u8) -> String {
93 match n {
94 0 => "zero".to_string(),
95 1 => "t1".to_string(),
96 _ => format!("t{}", n),
97 }
98}
99
100pub struct TernAsmEmitter {
103 out: Vec<String>,
104 label_counter: usize,
105}
106
107impl TernAsmEmitter {
108 pub fn new() -> Self {
109 Self { out: Vec::new(), label_counter: 0 }
110 }
111
112 fn emit(&mut self, line: &str) {
113 self.out.push(format!(" {}", line));
114 }
115
116 fn emit_label(&mut self, label: &str) {
117 self.out.push(format!("{}:", label));
118 }
119
120 fn fresh_label(&mut self, prefix: &str) -> String {
121 let l = format!(".L_{}_{}", prefix, self.label_counter);
122 self.label_counter += 1;
123 l
124 }
125
126 pub fn emit_program(&mut self, program: &Program) -> String {
128 self.out.push("; Generated by ternlang TERN-ASM emitter — RFI-IRFOS".to_string());
129 self.out.push("; TERN assembly (RISC-V-inspired balanced ternary)".to_string());
130 self.out.push("; Spec compatible with: Tern Systems TERN / BTMC".to_string());
131 self.out.push("".to_string());
132 self.out.push(".section .text".to_string());
133 self.out.push(".global main".to_string());
134 self.out.push("".to_string());
135
136 for func in &program.functions {
138 let mut ra = RegAlloc::new();
139 self.emit_function(func, &mut ra);
140 self.out.push("".to_string());
141 }
142
143 for agent in &program.agents {
145 for method in &agent.methods {
146 let label = format!("{}__{}", agent.name, method.name);
147 let mut ra = RegAlloc::new();
148 self.emit_function_with_label(&label, method, &mut ra);
149 self.out.push("".to_string());
150 }
151 }
152
153 self.out.join("\n")
154 }
155
156 fn emit_function(&mut self, func: &Function, ra: &mut RegAlloc) {
157 self.emit_function_with_label(&func.name, func, ra);
158 }
159
160 fn emit_function_with_label(&mut self, label: &str, func: &Function, ra: &mut RegAlloc) {
161 self.emit_label(label);
162
163 for (param_name, _) in &func.params {
165 ra.alloc(param_name);
166 }
167
168 for stmt in &func.body {
169 self.emit_stmt(stmt, ra);
170 }
171
172 let has_return = func.body.last().map(|s| matches!(s, Stmt::Return(_))).unwrap_or(false);
174 if !has_return {
175 self.emit("ret");
176 }
177 }
178
179 fn emit_stmt(&mut self, stmt: &Stmt, ra: &mut RegAlloc) {
180 match stmt {
181 Stmt::Let { name, value, .. } => {
182 if let Expr::StructLiteral { fields, .. } = value {
183 for (f_name, f_val) in fields {
184 let f_dest = ra.alloc(&format!("{}.{}", name, f_name));
185 let f_src = self.emit_expr(f_val, ra);
186 if f_src != f_dest {
187 self.emit(&format!("tadd {}, {}, zero ; struct field init", reg(f_dest), reg(f_src)));
188 }
189 }
190 let dest = ra.alloc(name);
192 self.emit(&format!("tldi {}, 0 ; struct root dummy", reg(dest)));
193 } else {
194 let dest = ra.alloc(name);
195 let src = self.emit_expr(value, ra);
196 if src != dest {
197 self.emit(&format!("tadd {}, {}, zero ; {} = {}", reg(dest), reg(src), name, name));
198 }
199 }
200 }
202
203 Stmt::Set { name, value } => {
204 let dest = ra.get(name);
205 let src = self.emit_expr(value, ra);
206 if src != dest {
207 self.emit(&format!("tadd {}, {}, zero ; {} = expr", reg(dest), reg(src), name));
208 }
209 }
210
211 Stmt::Return(expr) => {
212 let src = self.emit_expr(expr, ra);
213 if src != 2 {
215 self.emit(&format!("tadd t2, {}, zero ; return value", reg(src)));
216 }
217 self.emit("ret");
218 }
219
220 Stmt::Expr(expr) => {
221 self.emit_expr(expr, ra);
222 }
223
224 Stmt::Block(stmts) => {
225 let snap = ra.snapshot();
226 let next = ra.next;
227 for s in stmts { self.emit_stmt(s, ra); }
228 ra.restore(snap, next);
229 }
230
231 Stmt::IfTernary { condition, on_pos, on_zero, on_neg } => {
232 let cond_reg = self.emit_expr(condition, ra);
233 let lbl_pos = self.fresh_label("pos");
234 let lbl_zero = self.fresh_label("zero");
235 let lbl_neg = self.fresh_label("neg");
236 let lbl_end = self.fresh_label("end");
237
238 self.emit(&format!("bpos {}, {}", reg(cond_reg), lbl_pos));
239 self.emit(&format!("bzero {}, {}", reg(cond_reg), lbl_zero));
240 self.emit(&format!("j {}", lbl_neg));
241
242 self.emit_label(&lbl_pos);
243 self.emit_stmt(on_pos, ra);
244 self.emit(&format!("j {}", lbl_end));
245
246 self.emit_label(&lbl_zero);
247 self.emit_stmt(on_zero, ra);
248 self.emit(&format!("j {}", lbl_end));
249
250 self.emit_label(&lbl_neg);
251 self.emit_stmt(on_neg, ra);
252
253 self.emit_label(&lbl_end);
254 }
255
256 Stmt::Match { condition, arms } => {
257 let cond_reg = self.emit_expr(condition, ra);
258 let lbl_end = self.fresh_label("match_end");
259 let mut arm_labels: Vec<(i64, String)> = Vec::new();
260
261 let mut wildcard_lbl: Option<String> = None;
262 for (pattern, _) in arms.iter() {
263 match pattern {
264 Pattern::Wildcard => {
265 wildcard_lbl = Some(self.fresh_label("arm_wildcard"));
266 }
267 Pattern::Int(v) => arm_labels.push((*v, self.fresh_label(&format!("arm_{}", v)))),
268 Pattern::Trit(t) => arm_labels.push((*t as i64, self.fresh_label(&format!("arm_{}", t)))),
269 Pattern::Float(f) => arm_labels.push((*f as i64, self.fresh_label(&format!("arm_f{}", *f as i64)))),
270 }
271 }
272
273 let mut label_iter = arm_labels.iter();
275 for (pattern, _) in arms.iter() {
276 if matches!(pattern, Pattern::Wildcard) { continue; }
277 if let Some((val, lbl)) = label_iter.next() {
278 let tmp = ra.scratch();
279 self.emit(&format!("tlii {}, {}", reg(tmp), val));
280 let cmp = ra.scratch();
281 self.emit(&format!("teq {}, {}, {}", reg(cmp), reg(cond_reg), reg(tmp)));
282 self.emit(&format!("bpos {}, {}", reg(cmp), lbl));
283 }
284 }
285 if let Some(ref wlbl) = wildcard_lbl {
287 self.emit(&format!("j {}", wlbl));
288 } else {
289 self.emit(&format!("j {}", lbl_end));
290 }
291
292 let mut label_iter = arm_labels.iter();
293 let mut w_emitted = false;
294 for (pattern, body_stmt) in arms.iter() {
295 match pattern {
296 Pattern::Wildcard => {
297 if let Some(ref wlbl) = wildcard_lbl {
298 if !w_emitted {
299 self.emit_label(wlbl);
300 w_emitted = true;
301 }
302 }
303 self.emit_stmt(body_stmt, ra);
304 self.emit(&format!("j {}", lbl_end));
305 }
306 _ => {
307 if let Some((_, lbl)) = label_iter.next() {
308 self.emit_label(lbl);
309 self.emit_stmt(body_stmt, ra);
310 self.emit(&format!("j {}", lbl_end));
311 }
312 }
313 }
314 }
315
316 self.emit_label(&lbl_end);
317 }
318
319 Stmt::WhileTernary { condition, on_pos, on_zero, on_neg } => {
320 let lbl_loop = self.fresh_label("while");
321 let lbl_pos = self.fresh_label("wpos");
322 let lbl_zero = self.fresh_label("wzero");
323 let lbl_neg = self.fresh_label("wneg");
324 let lbl_end = self.fresh_label("wend");
325
326 self.emit_label(&lbl_loop);
327 let cond_reg = self.emit_expr(condition, ra);
328
329 self.emit(&format!("bpos {}, {}", reg(cond_reg), lbl_pos));
330 self.emit(&format!("bzero {}, {}", reg(cond_reg), lbl_zero));
331 self.emit(&format!("j {}", lbl_neg));
332
333 self.emit_label(&lbl_pos);
334 self.emit_stmt(on_pos, ra);
335 self.emit(&format!("j {}", lbl_loop));
336
337 self.emit_label(&lbl_zero);
338 self.emit_stmt(on_zero, ra);
339 self.emit(&format!("j {}", lbl_loop));
340
341 self.emit_label(&lbl_neg);
342 self.emit_stmt(on_neg, ra);
343 self.emit_label(&lbl_end);
346 }
347
348 Stmt::Loop { body } => {
349 let lbl_loop = self.fresh_label("loop");
350 let lbl_end = self.fresh_label("loop_end");
351
352 self.emit_label(&lbl_loop);
353 self.emit_stmt(body, ra);
354 self.emit(&format!("j {}", lbl_loop));
355 self.emit_label(&lbl_end);
356 }
357
358 Stmt::ForIn { var, iter, body } => {
359 let iter_reg = self.emit_expr(iter, ra);
361 let var_reg = ra.alloc(var);
362 let idx_reg = ra.scratch();
363 let lbl_loop = self.fresh_label("forin");
364 let lbl_end = self.fresh_label("forin_end");
365
366 self.emit(&format!("tlii {}, 0 ; for-in idx = 0", reg(idx_reg)));
367 self.emit_label(&lbl_loop);
368 self.emit(&format!("tld {}, 0({}) ; load row iter[idx]", reg(var_reg), reg(iter_reg)));
370 self.emit_stmt(body, ra);
371 self.emit(&format!("tadd {0}, {0}, t1 ; idx++", reg(idx_reg)));
372 self.emit(&format!("j {}", lbl_loop));
373 self.emit_label(&lbl_end);
374 }
375
376 Stmt::Break => { self.emit("j .L_break_arch_def ; break"); }
377 Stmt::Continue => { self.emit("j .L_continue_arch_def ; continue"); }
378
379 Stmt::Send { target, message } => {
380 let t = self.emit_expr(target, ra);
381 let m = self.emit_expr(message, ra);
382 self.emit(&format!("tsend {}, {} ; send msg to agent", reg(t), reg(m)));
383 }
384
385 Stmt::FieldSet { object, field: _, value } => {
386 let obj_reg = ra.get(object);
387 let val_reg = self.emit_expr(value, ra);
388 self.emit(&format!("tst {}, 0({}) ; field store", reg(val_reg), reg(obj_reg)));
389 }
390
391 Stmt::IndexSet { object, row, col: _, value } => {
392 let obj_reg = ra.get(object);
393 let row_reg = self.emit_expr(row, ra);
394 let val_reg = self.emit_expr(value, ra);
395 let addr = ra.scratch();
396 self.emit(&format!("tadd {}, {}, {} ; tensor index addr", reg(addr), reg(obj_reg), reg(row_reg)));
397 self.emit(&format!("tst {}, 0({}) ; tensor store", reg(val_reg), reg(addr)));
398 }
399
400 Stmt::Decorated { stmt, .. } => self.emit_stmt(stmt, ra),
401 Stmt::Use { .. } => {}
402 Stmt::FromImport { .. } => {}
403 }
404 }
405
406 fn emit_expr(&mut self, expr: &Expr, ra: &mut RegAlloc) -> u8 {
408 match expr {
409 Expr::TritLiteral(v) => {
410 let r = ra.scratch();
411 self.emit(&format!("tldi {}, {} ; trit literal", reg(r), v));
412 r
413 }
414
415 Expr::IntLiteral(v) => {
416 let r = ra.scratch();
417 self.emit(&format!("tlii {}, {} ; int literal", reg(r), v));
418 r
419 }
420
421 Expr::FloatLiteral(v) => {
422 let r = ra.scratch();
423 self.emit(&format!("tlii {}, {} ; float (truncated to int)", reg(r), *v as i64));
424 r
425 }
426
427 Expr::StringLiteral(_) => {
428 let r = ra.scratch();
429 self.emit(&format!("tlii {}, 0 ; string (addr architecture defined)", reg(r)));
430 r
431 }
432
433 Expr::Ident(name) => {
434 ra.get(name)
435 }
436
437 Expr::BinaryOp { op, lhs, rhs } => {
438 let lreg = self.emit_expr(lhs, ra);
439 let rreg = self.emit_expr(rhs, ra);
440 let dest = ra.scratch();
441 let mnemonic = match op {
442 BinOp::Add => "tadd",
443 BinOp::Sub => "tsub",
444 BinOp::Mul => "tmul",
445 BinOp::Div => "tdiv",
446 BinOp::Mod => "tmod",
447 BinOp::Equal => "teq",
448 BinOp::NotEqual => "tne",
449 BinOp::Less => "tlt",
450 BinOp::Greater => "tgt",
451 BinOp::LessEqual => "tle",
452 BinOp::GreaterEqual => "tge",
453 BinOp::And => "tcons",
454 BinOp::Or => "tmax",
455 };
456 self.emit(&format!("{:<6}{}, {}, {}", mnemonic, reg(dest), reg(lreg), reg(rreg)));
457 dest
458 }
459
460 Expr::UnaryOp { op: UnOp::Neg, expr } => {
461 let src = self.emit_expr(expr, ra);
462 let dest = ra.scratch();
463 self.emit(&format!("tnot {}, {}", reg(dest), reg(src)));
464 dest
465 }
466
467 Expr::Call { callee, args } => {
468 for (i, arg) in args.iter().enumerate() {
470 let r = self.emit_expr(arg, ra);
471 let arg_reg = 10 + i as u8;
473 if r != arg_reg {
474 self.emit(&format!("tadd t{}, {}, zero ; arg {}", arg_reg, reg(r), i));
475 }
476 }
477 match callee.as_str() {
479 "print" | "debug_print" => {
480 if !args.is_empty() {
481 let r = self.emit_expr(&args[0], ra);
482 self.emit(&format!("tprint {}", reg(r)));
483 }
484 return 0; }
486 "opent" => { if args.len() == 2 {
488 let r_path = self.emit_expr(&args[0], ra);
489 let r_mode = self.emit_expr(&args[1], ra);
490 self.emit(&format!("tpush {}", reg(r_path)));
491 self.emit(&format!("tpush {}", reg(r_mode)));
492 self.emit("topent");
493 self.emit("tpop t2"); }
495 return 2;
496 }
497 "readt" => { if !args.is_empty() {
499 let r_handle = self.emit_expr(&args[0], ra);
500 self.emit(&format!("tpush {}", reg(r_handle)));
501 self.emit("treadt");
502 self.emit("tpop t2");
503 }
504 return 2;
505 }
506 "writet" => { if args.len() == 2 {
508 let r_handle = self.emit_expr(&args[0], ra);
509 let r_trit = self.emit_expr(&args[1], ra);
510 self.emit(&format!("tpush {}", reg(r_handle)));
511 self.emit(&format!("tpush {}", reg(r_trit)));
512 self.emit("twritet");
513 }
514 return 0;
515 }
516 _ => {}
517 }
518 self.emit(&format!("call {}", callee));
519 2 }
521
522 Expr::Cast { expr, .. } => {
523 self.emit_expr(expr, ra) }
525
526 Expr::FieldAccess { object, field: _ } => {
527 let obj_reg = self.emit_expr(object, ra);
528 let dest = ra.scratch();
529 self.emit(&format!("tld {}, 0({}) ; field load", reg(dest), reg(obj_reg)));
530 dest
531 }
532
533 Expr::Index { object, row, col: _ } => {
534 let obj_reg = self.emit_expr(object, ra);
535 let row_reg = self.emit_expr(row, ra);
536 let addr = ra.scratch();
537 let dest = ra.scratch();
538 self.emit(&format!("tadd {}, {}, {} ; tensor index", reg(addr), reg(obj_reg), reg(row_reg)));
539 self.emit(&format!("tld {}, 0({}) ; tensor load", reg(dest), reg(addr)));
540 dest
541 }
542
543 Expr::TritTensorLiteral(vals) => {
544 let base = ra.scratch();
545 self.emit(&format!("tlii {}, 0 ; tensor literal (addr)", reg(base)));
546 for (i, v) in vals.iter().enumerate() {
547 let tmp = ra.scratch();
548 self.emit(&format!("tldi {}, {}", reg(tmp), v));
549 self.emit(&format!("tst {}, {}({}) ; tensor[{}]", reg(tmp), i, reg(base), i));
550 }
551 base
552 }
553
554 Expr::Spawn { agent_name, .. } => {
555 let r = ra.scratch();
556 self.emit(&format!("tspawn {}, {} ; spawn agent", reg(r), agent_name));
557 r
558 }
559
560 Expr::Await { target } => {
561 let t = self.emit_expr(target, ra);
562 let r = ra.scratch();
563 self.emit(&format!("tawait {}, {} ; await agent", reg(r), reg(t)));
564 r
565 }
566
567 Expr::Slice { object, start, end, stride } => {
568 let obj = self.emit_expr(object, ra);
569 let st = self.emit_expr(start, ra);
570 let en = self.emit_expr(end, ra);
571 let sd = self.emit_expr(stride, ra);
572 let r = ra.scratch();
573 self.emit(&format!("tview {}, {}, {}, {}, {} ; create view", reg(r), reg(obj), reg(st), reg(en), reg(sd)));
574 r
575 }
576
577 Expr::Propagate { expr } => {
578 let src = self.emit_expr(expr, ra);
579 let lbl = self.fresh_label("prop_ok");
580 self.emit(&format!("bneg {}, .L_prop_ret_{}", reg(src), self.label_counter));
582 self.emit(&format!("j {}", lbl));
583 self.emit_label(&format!(".L_prop_ret_{}", self.label_counter - 1));
584 self.emit("tldi t2, -1 ; propagate reject");
585 self.emit("ret");
586 self.emit_label(&lbl);
587 src
588 }
589
590 Expr::NodeId => {
591 let r = ra.scratch();
592 self.emit(&format!("tnodeid {}", reg(r)));
593 r
594 }
595
596 Expr::StructLiteral { .. } => {
597 let r = ra.scratch();
598 self.emit(&format!("tldi {}, 0 ; struct literal (dummy)", reg(r)));
599 r
600 }
601 }
602 }
603}
604
605pub fn emit_tern_asm(program: &Program) -> String {
609 TernAsmEmitter::new().emit_program(program)
610}