Merge branch 'mach' into mqbe

This commit is contained in:
2026-02-09 22:22:15 -06:00
3 changed files with 365 additions and 0 deletions

View File

@@ -10424,6 +10424,117 @@ static JSValue js_mach_eval_ast (JSContext *ctx, JSValue this_val, int argc, JSV
return result;
}
/* mach_compile(name, source) - parse and compile to binary blob */
static JSValue js_mach_compile (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 2 || !JS_IsText (argv[0]) || !JS_IsText (argv[1]))
return JS_ThrowTypeError (ctx, "mach_compile requires (name, source) text arguments");
const char *name = JS_ToCString (ctx, argv[0]);
if (!name) return JS_EXCEPTION;
const char *source = JS_ToCString (ctx, argv[1]);
if (!source) {
JS_FreeCString (ctx, name);
return JS_EXCEPTION;
}
cJSON *ast = JS_ASTTree (source, strlen (source), name);
JS_FreeCString (ctx, source);
if (!ast) {
JS_FreeCString (ctx, name);
return JS_ThrowSyntaxError (ctx, "mach_compile: failed to parse source");
}
MachCode *mc = JS_CompileMachTree (ast);
cJSON_Delete (ast);
JS_FreeCString (ctx, name);
if (!mc)
return JS_ThrowSyntaxError (ctx, "mach_compile: failed to compile AST");
size_t blob_size;
uint8_t *buf = JS_SerializeMachCode (mc, &blob_size);
JS_FreeMachCode (mc);
if (!buf)
return JS_ThrowInternalError (ctx, "mach_compile: serialization failed");
JSValue result = js_new_blob_stoned_copy (ctx, buf, blob_size);
sys_free (buf);
return result;
}
/* mach_compile_ast(name, ast_json) - compile pre-parsed AST to binary blob */
static JSValue js_mach_compile_ast (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 2 || !JS_IsText (argv[0]) || !JS_IsText (argv[1]))
return JS_ThrowTypeError (ctx, "mach_compile_ast requires (name, ast_json) text arguments");
const char *name = JS_ToCString (ctx, argv[0]);
if (!name) return JS_EXCEPTION;
const char *json_str = JS_ToCString (ctx, argv[1]);
if (!json_str) {
JS_FreeCString (ctx, name);
return JS_EXCEPTION;
}
cJSON *ast = cJSON_Parse (json_str);
JS_FreeCString (ctx, json_str);
if (!ast) {
JS_FreeCString (ctx, name);
return JS_ThrowSyntaxError (ctx, "mach_compile_ast: failed to parse AST JSON");
}
cJSON_DeleteItemFromObjectCaseSensitive (ast, "filename");
cJSON_AddStringToObject (ast, "filename", name);
MachCode *mc = JS_CompileMachTree (ast);
cJSON_Delete (ast);
JS_FreeCString (ctx, name);
if (!mc)
return JS_ThrowSyntaxError (ctx, "mach_compile_ast: failed to compile AST");
size_t blob_size;
uint8_t *buf = JS_SerializeMachCode (mc, &blob_size);
JS_FreeMachCode (mc);
if (!buf)
return JS_ThrowInternalError (ctx, "mach_compile_ast: serialization failed");
JSValue result = js_new_blob_stoned_copy (ctx, buf, blob_size);
sys_free (buf);
return result;
}
/* mach_load(blob, env?) - deserialize and execute binary blob */
static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 1)
return JS_ThrowTypeError (ctx, "mach_load requires a blob argument");
size_t data_size;
void *data = js_get_blob_data (ctx, &data_size, argv[0]);
if (!data) return JS_EXCEPTION;
MachCode *mc = JS_DeserializeMachCode ((const uint8_t *)data, data_size);
if (!mc)
return JS_ThrowSyntaxError (ctx, "mach_load: failed to deserialize bytecode");
JSValue env = (argc >= 2 && JS_IsObject (argv[1])) ? argv[1] : JS_NULL;
JSGCRef env_ref;
JS_PushGCRef (ctx, &env_ref);
env_ref.val = env;
JSCodeRegister *code = JS_LoadMachCode (ctx, mc, env_ref.val);
JS_FreeMachCode (mc);
JSValue result = JS_CallRegisterVM (ctx, code, ctx->global_obj, 0, NULL, env_ref.val, JS_NULL);
JS_PopGCRef (ctx, &env_ref);
return result;
}
/* mcode_run(name, mcode_json, env?) - run pre-compiled mcode JSON */
static JSValue js_mcode_run (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
if (argc < 2 || !JS_IsText (argv[0]) || !JS_IsText (argv[1]))
@@ -11546,6 +11657,9 @@ static void JS_AddIntrinsicBaseObjects (JSContext *ctx) {
/* Core functions - using GC-safe helper */
js_set_global_cfunc(ctx, "mach_eval_ast", js_mach_eval_ast, 3);
js_set_global_cfunc(ctx, "mcode_run", js_mcode_run, 3);
js_set_global_cfunc(ctx, "mach_compile", js_mach_compile, 2);
js_set_global_cfunc(ctx, "mach_compile_ast", js_mach_compile_ast, 2);
js_set_global_cfunc(ctx, "mach_load", js_mach_load, 2);
js_set_global_cfunc(ctx, "stone", js_cell_stone, 1);
js_set_global_cfunc(ctx, "length", js_cell_length, 1);
js_set_global_cfunc(ctx, "call", js_cell_call, 3);