From 2c9ac8f7b62c0e8f6c4fb249db81acb6ea9a04ad Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sat, 7 Feb 2026 16:29:04 -0600 Subject: [PATCH] no json roundtrip for mcode --- source/cell.c | 51 ++++++++++++++++++++++-------------------------- source/quickjs.c | 30 +++++++++++++++++++--------- source/quickjs.h | 14 +++++++++---- 3 files changed, 54 insertions(+), 41 deletions(-) diff --git a/source/cell.c b/source/cell.c index 58bde784..9dcc422d 100644 --- a/source/cell.c +++ b/source/cell.c @@ -497,36 +497,32 @@ int cell_init(int argc, char **argv) script = (char *)script_or_file; } - char *ast_json = JS_AST(script, strlen(script), filename); - if (!ast_json) { + cJSON *ast = JS_ASTTree(script, strlen(script), filename); + if (!ast) { printf("Failed to parse AST\n"); free(allocated_script); return 1; } - if (print_json_errors(ast_json)) { - free(ast_json); + if (print_tree_errors(ast)) { + cJSON_Delete(ast); free(allocated_script); return 1; } - char *mcode_json = JS_Mcode(ast_json); - free(ast_json); + cJSON *mcode = JS_McodeTree(ast); + cJSON_Delete(ast); - if (!mcode_json) { + if (!mcode) { printf("Failed to generate MCODE\n"); free(allocated_script); return 1; } - cJSON *root = cJSON_Parse(mcode_json); - free(mcode_json); - if (root) { - char *pretty = cJSON_Print(root); - cJSON_Delete(root); - printf("%s\n", pretty); - free(pretty); - } + char *pretty = cJSON_Print(mcode); + cJSON_Delete(mcode); + printf("%s\n", pretty); + free(pretty); free(allocated_script); return 0; @@ -554,40 +550,39 @@ int cell_init(int argc, char **argv) script = (char *)script_or_file; } - char *ast_json = JS_AST(script, strlen(script), filename); - if (!ast_json) { + cJSON *ast = JS_ASTTree(script, strlen(script), filename); + if (!ast) { printf("Failed to parse AST\n"); free(allocated_script); return 1; } - if (print_json_errors(ast_json)) { - free(ast_json); free(allocated_script); + if (print_tree_errors(ast)) { + cJSON_Delete(ast); free(allocated_script); return 1; } - char *mcode_json = JS_Mcode(ast_json); - free(ast_json); + cJSON *mcode = JS_McodeTree(ast); + cJSON_Delete(ast); - if (!mcode_json) { + if (!mcode) { printf("Failed to generate MCODE\n"); free(allocated_script); return 1; } - if (print_json_errors(mcode_json)) { - free(mcode_json); free(allocated_script); + if (print_tree_errors(mcode)) { + cJSON_Delete(mcode); free(allocated_script); return 1; } /* Use a larger heap context for execution */ JSRuntime *rt = JS_NewRuntime(); - if (!rt) { printf("Failed to create JS runtime\n"); free(mcode_json); free(allocated_script); return 1; } + if (!rt) { printf("Failed to create JS runtime\n"); cJSON_Delete(mcode); free(allocated_script); return 1; } JSContext *ctx = JS_NewContextWithHeapSize(rt, 64 * 1024); - if (!ctx) { printf("Failed to create execution context\n"); free(mcode_json); JS_FreeRuntime(rt); free(allocated_script); return 1; } + if (!ctx) { printf("Failed to create execution context\n"); cJSON_Delete(mcode); JS_FreeRuntime(rt); free(allocated_script); return 1; } - JSValue result = JS_CallMcode(ctx, mcode_json); - free(mcode_json); + JSValue result = JS_CallMcodeTree(ctx, mcode); /* takes ownership of mcode */ if (JS_IsException(result)) { JSValue exc = JS_GetException(ctx); diff --git a/source/quickjs.c b/source/quickjs.c index c04f43e2..9f9e7db1 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -35720,8 +35720,7 @@ static cJSON *mach_gen_program (MachGenState *s, cJSON *ast) { return result; } -char *JS_Mcode (const char *ast_json) { - cJSON *ast = cJSON_Parse (ast_json); +cJSON *JS_McodeTree (cJSON *ast) { if (!ast) return NULL; MachGenState s = {0}; @@ -35730,7 +35729,6 @@ char *JS_Mcode (const char *ast_json) { s.has_error = 0; cJSON *mach = mach_gen_program (&s, ast); - cJSON_Delete (ast); for (int i = 0; i < s.var_count; i++) sys_free (s.vars[i].name); if (s.vars) sys_free (s.vars); @@ -35743,6 +35741,15 @@ char *JS_Mcode (const char *ast_json) { if (s.errors) cJSON_AddItemToObject (mach, "errors", s.errors); + return mach; +} + +char *JS_Mcode (const char *ast_json) { + cJSON *ast = cJSON_Parse (ast_json); + if (!ast) return NULL; + cJSON *mach = JS_McodeTree (ast); + cJSON_Delete (ast); + if (!mach) return NULL; char *json = cJSON_PrintUnformatted (mach); cJSON_Delete (mach); return json; @@ -37471,15 +37478,14 @@ cJSON *JS_GetStack(JSContext *ctx) { return arr; } -/* Public API: parse MCODE JSON and execute */ -JSValue JS_CallMcode(JSContext *ctx, const char *mcode_json) { - cJSON *root = cJSON_Parse(mcode_json); - if (!root) return JS_ThrowSyntaxError(ctx, "invalid MCODE JSON"); +/* Execute MCODE from cJSON tree. Takes ownership of root (freed internally). */ +JSValue JS_CallMcodeTree(JSContext *ctx, cJSON *root) { + if (!root) return JS_ThrowSyntaxError(ctx, "invalid MCODE tree"); cJSON *main_obj = cJSON_GetObjectItem(root, "main"); if (!main_obj) { cJSON_Delete(root); - return JS_ThrowSyntaxError(ctx, "MCODE JSON missing 'main' section"); + return JS_ThrowSyntaxError(ctx, "MCODE tree missing 'main' section"); } cJSON *functions = cJSON_GetObjectItem(root, "functions"); @@ -37490,7 +37496,7 @@ JSValue JS_CallMcode(JSContext *ctx, const char *mcode_json) { cJSON_Delete(root); return JS_ThrowInternalError(ctx, "failed to parse MCODE"); } - code->json_root = root; /* Keep JSON alive — instrs point into it */ + code->json_root = root; /* Keep tree alive — instrs point into it */ /* Execute with global_obj as this */ JSValue result = mcode_exec(ctx, code, ctx->global_obj, 0, NULL, JS_NULL); @@ -37501,6 +37507,12 @@ JSValue JS_CallMcode(JSContext *ctx, const char *mcode_json) { return result; } +JSValue JS_CallMcode(JSContext *ctx, const char *mcode_json) { + cJSON *root = cJSON_Parse(mcode_json); + if (!root) return JS_ThrowSyntaxError(ctx, "invalid MCODE JSON"); + return JS_CallMcodeTree(ctx, root); +} + /* ============================================================ MACH Public API ============================================================ */ diff --git a/source/quickjs.h b/source/quickjs.h index 4f9b8d4c..81fa71c2 100644 --- a/source/quickjs.h +++ b/source/quickjs.h @@ -1257,12 +1257,18 @@ JSValue JS_RunMachTree (JSContext *ctx, struct cJSON *ast, JSValue env); /* Compile and execute MACH bytecode from AST JSON string. */ JSValue JS_RunMach (JSContext *ctx, const char *ast_json, JSValue env); -/* Compile AST JSON to MCODE JSON (string-based IR). - Returns malloc'd JSON string, or NULL on error. Caller must free. - No JSContext needed — pure string transformation. */ +/* Compile AST cJSON tree to MCODE cJSON tree. + Caller must call cJSON_Delete() on result. */ +struct cJSON *JS_McodeTree (struct cJSON *ast); + +/* Compile AST JSON string to MCODE JSON string. + Returns malloc'd JSON string, or NULL on error. Caller must free. */ char *JS_Mcode (const char *ast_json); -/* Parse and execute MCODE JSON directly via the MCODE interpreter. +/* Execute MCODE from cJSON tree. Takes ownership of root. */ +JSValue JS_CallMcodeTree (JSContext *ctx, struct cJSON *root); + +/* Parse and execute MCODE JSON string. Returns result of execution, or JS_EXCEPTION on error. */ JSValue JS_CallMcode (JSContext *ctx, const char *mcode_json);