123 lines
2.8 KiB
Plaintext
123 lines
2.8 KiB
Plaintext
// mcode.ce — compile to mcode IR
|
|
//
|
|
// Usage:
|
|
// cell mcode <file> Full mcode IR as JSON (default)
|
|
// cell mcode --pretty <file> Pretty-printed human-readable IR
|
|
|
|
var fd = use("fd")
|
|
var json = use("json")
|
|
var shop = use("internal/shop")
|
|
|
|
var show_pretty = false
|
|
var filename = null
|
|
var i = 0
|
|
|
|
for (i = 0; i < length(args); i++) {
|
|
if (args[i] == '--pretty') {
|
|
show_pretty = true
|
|
} else if (args[i] == '--help' || args[i] == '-h') {
|
|
log.console("Usage: cell mcode [--pretty] <file>")
|
|
$stop()
|
|
} else if (!starts_with(args[i], '-')) {
|
|
filename = args[i]
|
|
}
|
|
}
|
|
|
|
if (!filename) {
|
|
log.console("usage: cell mcode [--pretty] <file>")
|
|
$stop()
|
|
}
|
|
|
|
var compiled = shop.mcode_file(filename)
|
|
|
|
if (!show_pretty) {
|
|
print(json.encode(compiled))
|
|
$stop()
|
|
}
|
|
|
|
// Pretty-print helpers (from dump_mcode.cm)
|
|
var pad_right = function(s, w) {
|
|
var r = s
|
|
while (length(r) < w) {
|
|
r = r + " "
|
|
}
|
|
return r
|
|
}
|
|
|
|
var fmt_val = function(v) {
|
|
if (is_null(v)) return "null"
|
|
if (is_number(v)) return text(v)
|
|
if (is_text(v)) return `"${v}"`
|
|
if (is_object(v)) return json.encode(v)
|
|
if (is_logical(v)) return v ? "true" : "false"
|
|
return text(v)
|
|
}
|
|
|
|
var dump_function = function(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 instrs = func.instructions
|
|
var i = 0
|
|
var pc = 0
|
|
var instr = null
|
|
var op = null
|
|
var n = 0
|
|
var parts = null
|
|
var j = 0
|
|
var operands = null
|
|
var pc_str = null
|
|
var op_str = null
|
|
print(`\n=== ${name} (args=${text(nr_args)}, slots=${text(nr_slots)}, closures=${text(nr_close)}) ===`)
|
|
if (instrs == null || length(instrs) == 0) {
|
|
print(" (empty)")
|
|
return null
|
|
}
|
|
while (i < length(instrs)) {
|
|
instr = instrs[i]
|
|
if (is_text(instr)) {
|
|
if (!starts_with(instr, "_nop_")) {
|
|
print(`${instr}:`)
|
|
}
|
|
} else if (is_array(instr)) {
|
|
op = instr[0]
|
|
n = length(instr)
|
|
parts = []
|
|
j = 1
|
|
while (j < n - 2) {
|
|
push(parts, fmt_val(instr[j]))
|
|
j = j + 1
|
|
}
|
|
operands = text(parts, ", ")
|
|
pc_str = pad_right(text(pc), 5)
|
|
op_str = pad_right(op, 14)
|
|
print(` ${pc_str} ${op_str} ${operands}`)
|
|
pc = pc + 1
|
|
}
|
|
i = i + 1
|
|
}
|
|
return null
|
|
}
|
|
|
|
var main_name = null
|
|
var fi = 0
|
|
var func = null
|
|
var fname = null
|
|
|
|
if (compiled.main != null) {
|
|
main_name = compiled.name != null ? compiled.name : "<main>"
|
|
dump_function(compiled.main, main_name)
|
|
}
|
|
|
|
if (compiled.functions != null) {
|
|
fi = 0
|
|
while (fi < length(compiled.functions)) {
|
|
func = compiled.functions[fi]
|
|
fname = func.name != null ? func.name : `<func_${text(fi)}>`
|
|
dump_function(func, `[${text(fi)}] ${fname}`)
|
|
fi = fi + 1
|
|
}
|
|
}
|
|
|
|
$stop()
|