ludic/selfhost/emit_math.ludic
Orkuncakilkaya df6955e609 Phase 7g: the compiler builds its IR with interpolation, not +
Answering your readability point directly: the compiler's own string-building —
left uglier by the 7c `+` migration, e.g. `emit_bind(("load i32, ptr " + ip))` —
now reads as interpolation:

  emit_bind(("load i32, ptr " + ip))            -> emit_bind(`load i32, ptr {ip}`)
  emit_bind(("icmp eq i32 " + (kv + (", " + itoa(ak)))))
                                                -> emit_bind(`icmp eq i32 {kv}, {itoa(ak)}`)
  perr(("assign to unknown " + t.s))            -> perr(`assign to unknown {t.s}`)

164 concat chains across selfhost converted by a tool that flattens the `+` tree,
keeps call/index parens (only grouping parens are rewritten), and converts only
**brace-free** literals — LLVM IR structure strings full of `{`/`}` stay as `+`
rather than becoming awkward `{{`/`}}`. No new language surface; interpolation
already desugars to the same concat.

Reseeded (22565 lines); C-free fixpoint holds byte-for-byte (the strongest proof
the reconstruction is exact); goldens identical; 18/18.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-28 01:30:37 +03:00

29 lines
1.3 KiB
Text

# emit_math.ludic — the math builtins that lower to inline IR rather than a
# runtime call: min, max, abs, clamp. Everything else named like a builtin
# (clear, fill_rect, reg, ...) is resolved to its rt_ function by emit_call.
fn is_math_builtin(name: ptr) -> bool {
return (name == "min") or (name == "max") or (name == "abs") or (name == "clamp")
}
fn emit_math_builtin(name: ptr, e: Node) -> Val {
if (name == "abs") {
let a = emit_expr(e.kids[0])
let c = emit_bind(`icmp slt i32 {a.code}, 0`)
let n = emit_bind(`sub i32 0, {a.code}`)
return val(emit_bind(`select i1 {c}, i32 {n}, i32 {a.code}`), "int")
}
if (name == "min") or (name == "max") {
let a = emit_expr(e.kids[0]); let b = emit_expr(e.kids[1])
var op = "slt"
if (name == "max") { op = "sgt" }
let c = emit_bind(`icmp {op} i32 {a.code}, {b.code}`)
return val(emit_bind(`select i1 {c}, i32 {a.code}, i32 {b.code}`), "int")
}
# clamp(v, lo, hi) = max(lo, min(v, hi))
let v = emit_expr(e.kids[0]); let lo = emit_expr(e.kids[1]); let hi = emit_expr(e.kids[2])
let c1 = emit_bind(`icmp slt i32 {v.code}, {hi.code}`)
let t = emit_bind(`select i1 {c1}, i32 {v.code}, i32 {hi.code}`)
let c2 = emit_bind(`icmp sgt i32 {lo.code}, {t}`)
return val(emit_bind(`select i1 {c2}, i32 {lo.code}, i32 {t}`), "int")
}