Files
cell/streamline.ce
2026-02-17 13:37:17 -06:00

172 lines
4.3 KiB
Plaintext

// streamline.ce — run the full compile + optimize pipeline
//
// Usage:
// pit streamline <file> Full optimized IR as JSON (default)
// pit streamline --stats <file> Summary stats per function
// pit streamline --ir <file> Human-readable IR
// pit streamline --check <file> Warnings only (e.g. high slot count)
var fd = use("fd")
var json = use("json")
var tokenize = use("tokenize")
var parse = use("parse")
var fold = use("fold")
var mcode = use("mcode")
var streamline = use("streamline")
var show_stats = false
var show_ir = false
var show_check = false
var filename = null
var i = 0
for (i = 0; i < length(args); i++) {
if (args[i] == '--stats') {
show_stats = true
} else if (args[i] == '--ir') {
show_ir = true
} else if (args[i] == '--check') {
show_check = true
} else if (!starts_with(args[i], '-')) {
filename = args[i]
}
}
if (!filename) {
print("usage: pit streamline [--stats] [--ir] [--check] <file>")
$stop()
}
var src = text(fd.slurp(filename))
var result = tokenize(src, filename)
var ast = parse(result.tokens, src, filename, tokenize)
var folded = fold(ast)
var compiled = mcode(folded)
// Deep copy for before snapshot (needed by --stats)
var before = null
if (show_stats) {
before = json.decode(json.encode(compiled))
}
var optimized = streamline(compiled)
// If no flags, default to full JSON output
if (!show_stats && !show_ir && !show_check) {
print(json.encode(optimized, true))
$stop()
}
// --- Helpers ---
var ir_stats = use("ir_stats")
var pad_right = function(s, w) {
var r = s
while (length(r) < w) {
r = r + " "
}
return r
}
var count_nops = function(func) {
var instrs = func.instructions
var nops = 0
var i = 0
if (instrs == null) return 0
while (i < length(instrs)) {
if (is_text(instrs[i]) && starts_with(instrs[i], "_nop_")) {
nops = nops + 1
}
i = i + 1
}
return nops
}
var print_func_stats = function(func, before_func, name) {
var nr_args = func.nr_args != null ? func.nr_args : 0
var nr_slots = func.nr_slots != null ? func.nr_slots : 0
var nr_close = func.nr_close_slots != null ? func.nr_close_slots : 0
var stats = ir_stats.detailed_stats(func)
var nops = count_nops(func)
var before_stats = before_func ? ir_stats.detailed_stats(before_func) : null
var before_total = before_stats ? before_stats.instr : stats.instr
print(` ${name}`)
print(` args=${text(nr_args)} slots=${text(nr_slots)} close_slots=${text(nr_close)}`)
print(` instructions: ${text(stats.instr)} total, ${text(nops)} nops eliminated`)
if (before_stats) {
print(` before: ${text(before_total)} after: ${text(stats.instr - nops)}`)
}
print(` load=${text(stats.load)} store=${text(stats.store)} branch=${text(stats.branch)} call=${text(stats.call)}`)
print(` guard=${text(stats.guard)} arith=${text(stats.arith)} move=${text(stats.move)} const=${text(stats.const)}`)
if (nr_slots > 200) {
print(` WARNING: nr_slots=${text(nr_slots)} approaching 255 limit`)
}
}
var print_func_ir = function(func, name) {
var ir_text = ir_stats.canonical_ir(func, name, {show_nops: true})
print(ir_text)
}
var check_func = function(func, name) {
var nr_slots = func.nr_slots != null ? func.nr_slots : 0
if (nr_slots > 200) {
print(`WARNING: ${name} has ${text(nr_slots)} slots (approaching 255 limit)`)
}
}
// --- Process functions ---
var main_name = optimized.name != null ? optimized.name : "<main>"
var fi = 0
var func = null
var bfunc = null
var fname = null
if (show_stats) {
print(`\n--- Stats for ${filename} ---`)
}
// Main function
if (optimized.main != null) {
if (show_stats) {
print_func_stats(optimized.main, before ? before.main : null, main_name)
}
if (show_ir) {
print_func_ir(optimized.main, main_name)
}
if (show_check) {
check_func(optimized.main, main_name)
}
}
// Sub-functions
if (optimized.functions != null) {
fi = 0
while (fi < length(optimized.functions)) {
func = optimized.functions[fi]
bfunc = before ? before.functions[fi] : null
fname = func.name != null ? func.name : `<func_${text(fi)}>`
if (show_stats) {
print_func_stats(func, bfunc, fname)
}
if (show_ir) {
print_func_ir(func, fname)
}
if (show_check) {
check_func(func, fname)
}
fi = fi + 1
}
}
if (show_stats) {
print('---')
}
$stop()