ir
Intermediate representation - node constructors for every AST type (program, function, definition, return, if, while, call, id, number, string, list, object, lambda, binary op, dot access, index), an identity from_ast pass, constant-folding and dead-code-elimination optimisation passes, program validation, bytecode lowering, and pretty-print dump.
Load with: use ir
What this module does
ir bridges the parser's AST and the bytecode backend. Because the
ilusm AST is already structurally IR-compatible, ir.from_ast is
an identity pass. The interesting work happens in the optimisation passes:
- Constant folding (
ir.opt) - evaluates binary operations on literal numbers at compile time, e.g.2 + 3becomes5in the IR. - Dead-code elimination (
ir.dce) - truncates any statements that follow aretnode in a block.
ir.validate checks that a program node is structurally sound before
lowering, and ir.to_bc delegates to the compiler to produce bytecode.
Quick example
use ir
use prs
src = fs.rd("src/app.ilu")
ast = prs.parse(src)
# Convert to IR (identity pass here, but stable API)
prog = ir.from_ast(ast)
# Optimise
prog = ir.opt(prog) # constant folding
prog = ir.dce(prog) # dead code elimination
# Validate
r = ir.validate(prog)
if !r.ok: err(r.er)
# Dump human-readable
prn(ir.dump(prog))
# Lower to bytecode
bc = ir.to_bc(prog)
Functions
Node constructors
ir.prog(stmts)Creates a program node {t:"prg", st:stmts}.
ir.fn(name, params, body)Function definition node {t:"fun", n, pa, bd}.
ir.defn(name, val)Variable definition node {t:"def", n, v}.
ir.rtn(val)Return node {t:"ret", v}.
ir.ifs(cond, yes, no)If-else node {t:"ifs", cd, th, el}.
ir.whl(cond, body)While loop node {t:"whl", cd, bd}.
ir.call(fn_expr, args)Function call node {t:"ca", fn, ar}.
ir.id(name)Identifier node {t:"id", n}.
ir.num(v)Numeric literal node {t:"nm", v}.
ir.str(v)String literal node {t:"st", v}.
ir.list(items)List literal node {t:"ls", el}.
ir.obj(pairs)Object literal node {t:"ob", ps}.
ir.lam(params, body)Lambda node {t:"lm", pa, bd}.
ir.bin(op, l, r)Binary operation node {t:"bn", op, l, r}.
ir.dot(obj, field)Dot access node {t:"dt", ob, f}.
ir.idx(obj, key)Index access node {t:"ix", ob, k}.
Passes
ir.from_ast(prog)
Identity pass - returns the program unchanged. Exists as a stable hook for future transformations.
ir.opt(prog)
Constant-folding pass. Recursively evaluates binary operations on numeric literals (+, -, *, /, %). Returns an optimised program node.
ir.dce(prog)
Dead-code elimination pass. Truncates any statements after the first ret node in each block.
Validation, lowering, and dump
ir.validate(prog)
Checks structural validity: must have type "prg" and a non-nil st field. Returns {ok: tru, er: nil} or {ok: fls, er: message}.
ir.to_bc(prog)
Lowers the IR program to bytecode by delegating to cmppr (the compiler's program-compile function).
ir.dump(prog)
Returns a human-readable indented text representation of the IR using ast.pp.
Notes
- Requires
trlandast.