diff --git a/internal/engine.cm b/internal/engine.cm index b338acf5..11244d90 100644 --- a/internal/engine.cm +++ b/internal/engine.cm @@ -73,7 +73,21 @@ function ensure_build_dir() { return dir } -// Load a pipeline module from cache, with boot/ seed fallback +// Load a boot seed module (for compiling pipeline modules on cache miss) +function boot_load(name) { + var mcode_path = core_path + '/boot/' + name + '.cm.mcode' + var mcode_blob = null + var mach_blob = null + if (!fd.is_file(mcode_path)) { + print("error: missing boot seed: " + name + "\n") + disrupt + } + mcode_blob = fd.slurp(mcode_path) + mach_blob = mach_compile_mcode_bin(name, text(mcode_blob)) + return mach_load(mach_blob, {use: use_embed}) +} + +// Load a pipeline module from cache; on miss compile from source via boot chain function load_pipeline_module(name, env) { var source_path = core_path + '/' + name + '.cm' var source_blob = null @@ -82,14 +96,48 @@ function load_pipeline_module(name, env) { var mcode_path = null var mcode_blob = null var mach_blob = null + var src = null + var boot_tok = null + var boot_par = null + var boot_fld = null + var boot_mc = null + var tok_result = null + var ast = null + var compiled = null + var mcode_json = null if (fd.is_file(source_path)) { source_blob = fd.slurp(source_path) hash = content_hash(source_blob) cached = cache_path(hash) if (cached && fd.is_file(cached)) return mach_load(fd.slurp(cached), env) + + // Cache miss: compile from source using boot seed pipeline + mcode_path = core_path + '/boot/' + name + '.cm.mcode' + if (fd.is_file(mcode_path)) { + boot_tok = boot_load("tokenize") + boot_par = boot_load("parse") + boot_fld = boot_load("fold") + boot_mc = boot_load("mcode") + src = text(source_blob) + tok_result = boot_tok(src, source_path) + ast = boot_par(tok_result.tokens, src, source_path, boot_tok) + if (ast.errors != null && length(ast.errors) > 0) { + print("error: failed to compile pipeline module: " + name + "\n") + disrupt + } + ast = boot_fld(ast) + compiled = boot_mc(ast) + mcode_json = json.encode(compiled) + mach_blob = mach_compile_mcode_bin(name, mcode_json) + if (cached) { + ensure_build_dir() + fd.slurpwrite(cached, mach_blob) + } + return mach_load(mach_blob, env) + } } - // Boot seed fallback + // Last resort: boot seed as runtime (no source file found) mcode_path = core_path + '/boot/' + name + '.cm.mcode' if (fd.is_file(mcode_path)) { mcode_blob = fd.slurp(mcode_path) diff --git a/parse.cm b/parse.cm index dc52a372..07c7f185 100644 --- a/parse.cm +++ b/parse.cm @@ -437,7 +437,14 @@ var parse = function(tokens, src, filename, tokenizer) { } push(list, pair) if (tok.kind == ",") advance() - else break + else if (tok.kind == "{") { + if (right && right.kind == "(") { + parse_error(tok, "unexpected '{' after property value; use method shorthand `name(args) { ... }` or `name: function(args) { ... }`") + } else { + parse_error(tok, "expected ',' or '}' in object literal") + } + break + } else break } ast_node_end(node) if (tok.kind == "}") advance()