Files
cell/regen.ce
2026-02-15 11:44:33 -06:00

126 lines
3.8 KiB
Plaintext

// regen.ce — regenerate .mcode bytecode files and pre-warm .mach cache
var fd = use("fd")
var json = use("json")
var crypto = use("crypto")
var tokenize = use("tokenize")
var parse = use("parse")
var fold = use("fold")
var mcode = use("mcode")
var streamline = use("streamline")
// Pipeline files (tokenize/parse/fold/mcode/streamline) are only regenerated
// with --all flag since they require a self-consistent compiler to bootstrap.
var pipeline_files = [
{src: "tokenize.cm", name: "tokenize", out: "boot/tokenize.cm.mcode"},
{src: "parse.cm", name: "parse", out: "boot/parse.cm.mcode"},
{src: "fold.cm", name: "fold", out: "boot/fold.cm.mcode"},
{src: "mcode.cm", name: "mcode", out: "boot/mcode.cm.mcode"},
{src: "streamline.cm", name: "streamline", out: "boot/streamline.cm.mcode"}
]
var files = [
{src: "qbe.cm", name: "qbe", out: "boot/qbe.cm.mcode"},
{src: "qbe_emit.cm", name: "qbe_emit", out: "boot/qbe_emit.cm.mcode"},
{src: "verify_ir.cm", name: "verify_ir", out: "boot/verify_ir.cm.mcode"},
{src: "internal/bootstrap.cm", name: "bootstrap", out: "boot/bootstrap.cm.mcode"},
{src: "internal/engine.cm", name: "engine", out: "boot/engine.cm.mcode"},
{src: "boot/seed_bootstrap.cm", name: "seed_bootstrap", out: "boot/seed_bootstrap.cm.mcode"},
{src: "fd.cm", name: "fd", out: "boot/fd.cm.mcode"},
{src: "time.cm", name: "time", out: "boot/time.cm.mcode"},
{src: "pronto.cm", name: "pronto", out: "boot/pronto.cm.mcode"},
{src: "toml.cm", name: "toml", out: "boot/toml.cm.mcode"},
{src: "link.cm", name: "link", out: "boot/link.cm.mcode"},
{src: "toolchains.cm", name: "toolchains", out: "boot/toolchains.cm.mcode"},
{src: "package.cm", name: "package", out: "boot/package.cm.mcode"},
{src: "internal/shop.cm", name: "internal_shop", out: "boot/internal_shop.cm.mcode"}
]
// Include pipeline files with --all flag
var os = use('os')
var regen_all = args != null && length(args) > 0 && args[0] == "--all"
if (regen_all) {
files = array(pipeline_files, files)
}
// Resolve shop_path for cache writes
var shop = os.getenv('CELL_SHOP')
var home = null
var cache_dir = null
if (!shop) {
home = os.getenv('HOME')
if (home) {
shop = home + '/.cell'
}
}
if (shop) {
cache_dir = shop + '/build'
if (!fd.is_dir(cache_dir)) {
fd.mkdir(cache_dir)
}
}
var i = 0
var entry = null
var src = null
var tok_result = null
var ast = null
var folded = null
var mcode_blob = null
var hash = null
var mach_blob = null
var compiled = null
var optimized = null
var mcode_text = null
var f = null
var errs = null
var ei = 0
var e = null
var had_errors = false
var compact_mcode = null
while (i < length(files)) {
entry = files[i]
src = text(fd.slurp(entry.src))
tok_result = tokenize(src, entry.src)
ast = parse(tok_result.tokens, src, entry.src, tokenize)
// Check for parse/semantic errors
errs = ast.errors
if (errs != null && length(errs) > 0) {
ei = 0
while (ei < length(errs)) {
e = errs[ei]
if (e.line != null) {
print(`${entry.src}:${text(e.line)}:${text(e.column)}: error: ${e.message}`)
} else {
print(`${entry.src}: error: ${e.message}`)
}
ei = ei + 1
}
had_errors = true
i = i + 1
continue
}
folded = fold(ast)
compiled = mcode(folded)
optimized = streamline(compiled)
mcode_text = json.encode(optimized)
f = fd.open(entry.out, "w")
fd.write(f, mcode_text)
fd.close(f)
print(`wrote ${entry.out}`)
// Pre-warm .mach cache
if (cache_dir) {
mcode_blob = stone(blob(mcode_text))
hash = text(crypto.blake2(mcode_blob), 'h')
compact_mcode = json.encode(optimized)
mach_blob = mach_compile_mcode_bin(entry.name, compact_mcode)
fd.slurpwrite(cache_dir + '/' + hash, mach_blob)
print(` cached ${hash}`)
}
i = i + 1
}
if (had_errors) {
print("regen aborted: fix errors above")
}