// streamline.ce — run the full compile + optimize pipeline // // Usage: // pit streamline Full optimized IR as JSON (default) // pit streamline --stats Summary stats per function // pit streamline --ir Human-readable IR // pit streamline --check 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] ") $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 : "
" 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 : `` 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()