mcode->mach
This commit is contained in:
BIN
fold_new.mach
Normal file
BIN
fold_new.mach
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mcode.mach
BIN
mcode.mach
Binary file not shown.
@@ -46,7 +46,6 @@ src += [ # core
|
||||
'miniz.c',
|
||||
'runtime.c',
|
||||
'mach.c',
|
||||
'mcode.c',
|
||||
'libregexp.c', 'libunicode.c', 'cutils.c', 'dtoa.c'
|
||||
]
|
||||
|
||||
|
||||
14
parse.cm
14
parse.cm
@@ -65,7 +65,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
|
||||
var errors = []
|
||||
var error_count = 0
|
||||
var function_nr = 1
|
||||
var fn_counter = 1
|
||||
|
||||
var ast_node = function(kind, token) {
|
||||
return {
|
||||
@@ -422,8 +422,8 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
_control_depth = meth_old_cd
|
||||
_control_type = meth_old_ct
|
||||
_expecting_body = meth_old_eb
|
||||
fn.function_nr = function_nr
|
||||
function_nr = function_nr + 1
|
||||
fn.function_nr = fn_counter
|
||||
fn_counter = fn_counter + 1
|
||||
ast_node_end(fn)
|
||||
pair.right = fn
|
||||
} else if (is_ident && (tok.kind == "," || tok.kind == "}")) {
|
||||
@@ -918,8 +918,8 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
_control_depth = old_cd
|
||||
_control_type = old_ct
|
||||
_expecting_body = old_eb
|
||||
node.function_nr = function_nr
|
||||
function_nr = function_nr + 1
|
||||
node.function_nr = fn_counter
|
||||
fn_counter = fn_counter + 1
|
||||
ast_node_end(node)
|
||||
return node
|
||||
}
|
||||
@@ -1008,8 +1008,8 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
_control_depth = old_cd
|
||||
_control_type = old_ct
|
||||
_expecting_body = old_eb
|
||||
node.function_nr = function_nr
|
||||
function_nr = function_nr + 1
|
||||
node.function_nr = fn_counter
|
||||
fn_counter = fn_counter + 1
|
||||
ast_node_end(node)
|
||||
return node
|
||||
}
|
||||
|
||||
BIN
parse.mach
BIN
parse.mach
Binary file not shown.
BIN
qbe_emit.mach
BIN
qbe_emit.mach
Binary file not shown.
36
regen.cm
36
regen.cm
@@ -6,6 +6,8 @@ var json = use("json")
|
||||
var tokenize = use("tokenize")
|
||||
var parse = use("parse")
|
||||
var fold = use("fold")
|
||||
var mcode = use("mcode")
|
||||
var streamline = use("streamline")
|
||||
|
||||
var files = [
|
||||
{src: "tokenize.cm", name: "tokenize", out: "tokenize.mach"},
|
||||
@@ -25,21 +27,49 @@ var src = null
|
||||
var tok_result = null
|
||||
var ast = null
|
||||
var folded = null
|
||||
var ast_json = null
|
||||
var compiled = null
|
||||
var optimized = null
|
||||
var mcode_json = null
|
||||
var bytecode = null
|
||||
var f = null
|
||||
var errs = null
|
||||
var ei = 0
|
||||
var e = null
|
||||
var had_errors = false
|
||||
|
||||
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)
|
||||
ast_json = json.encode(folded)
|
||||
bytecode = mach_compile_ast(entry.name, ast_json)
|
||||
compiled = mcode(folded)
|
||||
optimized = streamline(compiled)
|
||||
mcode_json = json.encode(optimized)
|
||||
bytecode = mach_compile_mcode_bin(entry.name, mcode_json)
|
||||
f = fd.open(entry.out, "w")
|
||||
fd.write(f, bytecode)
|
||||
fd.close(f)
|
||||
print(`wrote ${entry.out}`)
|
||||
i = i + 1
|
||||
}
|
||||
if (had_errors) {
|
||||
print("regen aborted: fix errors above")
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "cJSON.h"
|
||||
|
||||
#define BOOTSTRAP_MACH "internal/bootstrap.mach"
|
||||
#define BOOTSTRAP_AST "internal/bootstrap.ast.json"
|
||||
#define BOOTSTRAP_SRC "internal/bootstrap.cm"
|
||||
#define CELL_SHOP_DIR ".cell"
|
||||
#define CELL_CORE_DIR "packages/core"
|
||||
@@ -179,14 +178,9 @@ void script_startup(cell_rt *prt)
|
||||
cell_rt *crt = JS_GetContextOpaque(js);
|
||||
JS_FreeValue(js, js_blob_use(js));
|
||||
|
||||
// Load pre-compiled bootstrap bytecode (.mach), fall back to AST JSON
|
||||
// Load pre-compiled bootstrap bytecode (.mach)
|
||||
size_t boot_size;
|
||||
int boot_is_bin = 1;
|
||||
char *boot_data = load_core_file(BOOTSTRAP_MACH, &boot_size);
|
||||
if (!boot_data) {
|
||||
boot_is_bin = 0;
|
||||
boot_data = load_core_file(BOOTSTRAP_AST, &boot_size);
|
||||
}
|
||||
if (!boot_data) {
|
||||
printf("ERROR: Could not load bootstrap from %s!\n", core_path);
|
||||
return;
|
||||
@@ -225,17 +219,8 @@ void script_startup(cell_rt *prt)
|
||||
|
||||
// Run through MACH VM
|
||||
crt->state = ACTOR_RUNNING;
|
||||
JSValue v;
|
||||
if (boot_is_bin) {
|
||||
v = JS_RunMachBin(js, (const uint8_t *)boot_data, boot_size, hidden_env);
|
||||
free(boot_data);
|
||||
} else {
|
||||
cJSON *ast = cJSON_Parse(boot_data);
|
||||
free(boot_data);
|
||||
if (!ast) { printf("ERROR: Failed to parse bootstrap AST\n"); return; }
|
||||
v = JS_RunMachTree(js, ast, hidden_env);
|
||||
cJSON_Delete(ast);
|
||||
}
|
||||
JSValue v = JS_RunMachBin(js, (const uint8_t *)boot_data, boot_size, hidden_env);
|
||||
free(boot_data);
|
||||
uncaught_exception(js, v);
|
||||
crt->state = ACTOR_IDLE;
|
||||
set_actor_state(crt);
|
||||
@@ -359,12 +344,7 @@ int cell_init(int argc, char **argv)
|
||||
actor_initialize();
|
||||
|
||||
size_t boot_size;
|
||||
int boot_is_bin = 1;
|
||||
char *boot_data = load_core_file(BOOTSTRAP_MACH, &boot_size);
|
||||
if (!boot_data) {
|
||||
boot_is_bin = 0;
|
||||
boot_data = load_core_file(BOOTSTRAP_AST, &boot_size);
|
||||
}
|
||||
if (!boot_data) {
|
||||
printf("ERROR: Could not load bootstrap from %s\n", core_path);
|
||||
return 1;
|
||||
@@ -433,17 +413,8 @@ int cell_init(int argc, char **argv)
|
||||
JS_SetPropertyStr(ctx, hidden_env, "args", args_arr);
|
||||
hidden_env = JS_Stone(ctx, hidden_env);
|
||||
|
||||
JSValue result;
|
||||
if (boot_is_bin) {
|
||||
result = JS_RunMachBin(ctx, (const uint8_t *)boot_data, boot_size, hidden_env);
|
||||
free(boot_data);
|
||||
} else {
|
||||
cJSON *ast = cJSON_Parse(boot_data);
|
||||
free(boot_data);
|
||||
if (!ast) { printf("Failed to parse bootstrap AST\n"); JS_FreeContext(ctx); JS_FreeRuntime(g_runtime); return 1; }
|
||||
result = JS_RunMachTree(ctx, ast, hidden_env);
|
||||
cJSON_Delete(ast);
|
||||
}
|
||||
JSValue result = JS_RunMachBin(ctx, (const uint8_t *)boot_data, boot_size, hidden_env);
|
||||
free(boot_data);
|
||||
|
||||
int exit_code = 0;
|
||||
if (JS_IsException(result)) {
|
||||
|
||||
2576
source/mach.c
2576
source/mach.c
File diff suppressed because it is too large
Load Diff
2038
source/mcode.c
2038
source/mcode.c
File diff suppressed because it is too large
Load Diff
@@ -812,28 +812,6 @@ typedef struct JSCodeRegister {
|
||||
uint16_t disruption_pc; /* start of disruption handler (0 = none) */
|
||||
} JSCodeRegister;
|
||||
|
||||
/* Pre-parsed MCODE for a single function (off-heap, never GC'd).
|
||||
Created by jsmcode_parse from cJSON MCODE output.
|
||||
Instructions remain as cJSON pointers for string-based dispatch. */
|
||||
typedef struct JSMCode {
|
||||
uint16_t nr_args;
|
||||
uint16_t nr_slots;
|
||||
/* Pre-flattened instruction array (cJSON array items → C array for O(1) access) */
|
||||
cJSON **instrs;
|
||||
uint32_t instr_count;
|
||||
/* Label map: label string → instruction index */
|
||||
struct { const char *name; uint32_t index; } *labels;
|
||||
uint32_t label_count;
|
||||
/* Nested function definitions (indexes into top-level functions array) */
|
||||
struct JSMCode **functions;
|
||||
uint32_t func_count;
|
||||
/* Keep root cJSON alive (owns all the cJSON nodes instrs[] point into) */
|
||||
cJSON *json_root;
|
||||
MachLineEntry *line_table; /* [instr_count], parallel to instrs[] */
|
||||
const char *name; /* function name (points into cJSON tree) */
|
||||
const char *filename; /* source filename (points into cJSON tree) */
|
||||
uint16_t disruption_pc; /* start of disruption handler (0 = none) */
|
||||
} JSMCode;
|
||||
|
||||
/* Frame for closures - used by link-time relocation model where closures
|
||||
reference outer frames via (depth, slot) addressing.
|
||||
@@ -1306,7 +1284,6 @@ typedef enum {
|
||||
JS_FUNC_KIND_BYTECODE,
|
||||
JS_FUNC_KIND_C_DATA,
|
||||
JS_FUNC_KIND_REGISTER, /* register-based VM function */
|
||||
JS_FUNC_KIND_MCODE, /* MCODE JSON interpreter */
|
||||
} JSFunctionKind;
|
||||
|
||||
typedef struct JSFunction {
|
||||
@@ -1330,11 +1307,6 @@ typedef struct JSFunction {
|
||||
JSValue env_record; /* stone record, module environment */
|
||||
JSValue outer_frame; /* JSFrame JSValue, for closures */
|
||||
} reg;
|
||||
struct {
|
||||
JSMCode *code; /* pre-parsed MCODE (off-heap) */
|
||||
JSValue outer_frame; /* lexical parent frame for closures */
|
||||
JSValue env_record; /* module env or JS_NULL */
|
||||
} mcode;
|
||||
} u;
|
||||
} JSFunction;
|
||||
|
||||
@@ -1527,8 +1499,6 @@ JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue this_obj,
|
||||
JSValue js_call_bound_function (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv);
|
||||
JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv, int flags);
|
||||
JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, JSValue this_obj, int argc, JSValue *argv, JSValue env, JSValue outer_frame);
|
||||
JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
int argc, JSValue *argv, JSValue outer_frame);
|
||||
int JS_DeleteProperty (JSContext *ctx, JSValue obj, JSValue prop);
|
||||
JSValue __attribute__ ((format (printf, 2, 3)))
|
||||
JS_ThrowInternalError (JSContext *ctx, const char *fmt, ...);
|
||||
@@ -1860,13 +1830,6 @@ typedef struct {
|
||||
} GetLineColCache;
|
||||
|
||||
|
||||
/* === MachVarInfo (shared by mach.c and mcode.c) === */
|
||||
typedef struct MachVarInfo {
|
||||
char *name;
|
||||
int slot;
|
||||
int is_const; /* 1 for def, function args; 0 for var */
|
||||
int is_closure; /* 1 if captured by a nested function */
|
||||
} MachVarInfo;
|
||||
|
||||
/* === PPretext (parser pretext, system-malloc, used by cell_js.c parser) === */
|
||||
typedef struct PPretext {
|
||||
@@ -2057,8 +2020,5 @@ JSFrameRegister *alloc_frame_register(JSContext *ctx, int slot_count);
|
||||
cJSON *mach_find_scope_record(cJSON *scopes, int function_nr);
|
||||
int reg_vm_check_interrupt(JSContext *ctx);
|
||||
|
||||
/* mcode.c exports */
|
||||
JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj, int argc, JSValue *argv, JSValue outer_frame);
|
||||
|
||||
|
||||
#endif /* QUICKJS_INTERNAL_H */
|
||||
|
||||
@@ -1091,34 +1091,12 @@ MachCode *JS_DeserializeMachCode(const uint8_t *data, size_t size);
|
||||
/* Load compiled MachCode into a JSContext, materializing JSValues. */
|
||||
struct JSCodeRegister *JS_LoadMachCode(JSContext *ctx, MachCode *mc, JSValue env);
|
||||
|
||||
/* Dump MACH bytecode to stdout. Takes AST cJSON tree. */
|
||||
void JS_DumpMachTree (JSContext *ctx, struct cJSON *ast, JSValue env);
|
||||
|
||||
/* Dump MACH bytecode to stdout. Takes AST JSON string. */
|
||||
void JS_DumpMach (JSContext *ctx, const char *ast_json, JSValue env);
|
||||
|
||||
/* Compile and execute MACH bytecode from AST cJSON tree. */
|
||||
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);
|
||||
|
||||
/* Deserialize and execute pre-compiled MACH binary bytecode. */
|
||||
JSValue JS_RunMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue env);
|
||||
|
||||
/* Compile mcode JSON IR to MachCode binary. */
|
||||
MachCode *mach_compile_mcode(struct cJSON *mcode_json);
|
||||
|
||||
/* Execute MCODE from cJSON tree. Takes ownership of root. */
|
||||
JSValue JS_CallMcodeTree (JSContext *ctx, struct cJSON *root);
|
||||
|
||||
/* Execute MCODE from cJSON tree with hidden env. Takes ownership of root. */
|
||||
JSValue JS_CallMcodeTreeEnv (JSContext *ctx, struct cJSON *root, JSValue env);
|
||||
|
||||
/* Parse and execute MCODE JSON string.
|
||||
Returns result of execution, or JS_EXCEPTION on error. */
|
||||
JSValue JS_CallMcode (JSContext *ctx, const char *mcode_json);
|
||||
|
||||
/* Get stack trace as cJSON array of frame objects.
|
||||
Returns NULL if no register VM frame is active.
|
||||
Caller must call cJSON_Delete() on the result. */
|
||||
|
||||
189
source/runtime.c
189
source/runtime.c
@@ -1139,10 +1139,6 @@ void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *from_base, uint8_t *fro
|
||||
nested->name = gc_copy_value (ctx, nested->name, from_base, from_end, to_base, to_free, to_end);
|
||||
}
|
||||
}
|
||||
} else if (fn->kind == JS_FUNC_KIND_MCODE) {
|
||||
/* MCODE function - scan outer_frame and env_record */
|
||||
fn->u.mcode.outer_frame = gc_copy_value (ctx, fn->u.mcode.outer_frame, from_base, from_end, to_base, to_free, to_end);
|
||||
fn->u.mcode.env_record = gc_copy_value (ctx, fn->u.mcode.env_record, from_base, from_end, to_base, to_free, to_end);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -4630,8 +4626,6 @@ JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj,
|
||||
case JS_FUNC_KIND_REGISTER:
|
||||
return JS_CallRegisterVM (ctx, f->u.reg.code, this_obj, argc, argv,
|
||||
f->u.reg.env_record, f->u.reg.outer_frame);
|
||||
case JS_FUNC_KIND_MCODE:
|
||||
return mcode_exec (ctx, f->u.mcode.code, this_obj, argc, argv, f->u.mcode.outer_frame);
|
||||
default:
|
||||
return JS_ThrowTypeError (ctx, "not a function");
|
||||
}
|
||||
@@ -4653,8 +4647,6 @@ JSValue JS_Call (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, J
|
||||
case JS_FUNC_KIND_REGISTER:
|
||||
return JS_CallRegisterVM (ctx, f->u.reg.code, this_obj, argc, argv,
|
||||
f->u.reg.env_record, f->u.reg.outer_frame);
|
||||
case JS_FUNC_KIND_MCODE:
|
||||
return mcode_exec (ctx, f->u.mcode.code, this_obj, argc, argv, f->u.mcode.outer_frame);
|
||||
default:
|
||||
return JS_ThrowTypeError (ctx, "not a function");
|
||||
}
|
||||
@@ -10117,83 +10109,6 @@ int js_is_blob (JSContext *js, JSValue v) {
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/* mach_eval_ast(name, ast_json, env?) - compile pre-parsed AST and run */
|
||||
static JSValue js_mach_eval_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_eval_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_eval_ast: failed to parse AST JSON");
|
||||
}
|
||||
|
||||
/* Set the filename on the AST root */
|
||||
cJSON_DeleteItemFromObjectCaseSensitive (ast, "filename");
|
||||
cJSON_AddStringToObject (ast, "filename", name);
|
||||
|
||||
JSValue env = (argc >= 3 && JS_IsObject (argv[2])) ? argv[2] : JS_NULL;
|
||||
JSValue result = JS_RunMachTree (ctx, ast, env);
|
||||
cJSON_Delete (ast);
|
||||
JS_FreeCString (ctx, name);
|
||||
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)
|
||||
@@ -10207,6 +10122,11 @@ static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue
|
||||
if (!mc)
|
||||
return JS_ThrowSyntaxError (ctx, "mach_load: failed to deserialize bytecode");
|
||||
|
||||
{
|
||||
extern void verify_getup(MachCode *mc, const char *path);
|
||||
verify_getup(mc, "MACH_LOAD");
|
||||
}
|
||||
|
||||
JSValue env = (argc >= 2 && JS_IsObject (argv[1])) ? argv[1] : JS_NULL;
|
||||
|
||||
JSGCRef env_ref;
|
||||
@@ -10220,35 +10140,6 @@ static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue
|
||||
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]))
|
||||
return JS_ThrowTypeError (ctx, "mcode_run requires (name, mcode_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 *mcode = cJSON_Parse (json_str);
|
||||
JS_FreeCString (ctx, json_str);
|
||||
|
||||
if (!mcode) {
|
||||
JS_FreeCString (ctx, name);
|
||||
return JS_ThrowSyntaxError (ctx, "mcode_run: failed to parse mcode JSON");
|
||||
}
|
||||
|
||||
JSValue env = (argc >= 3 && JS_IsObject (argv[2])) ? argv[2] : JS_NULL;
|
||||
JSValue result = JS_CallMcodeTreeEnv (ctx, mcode, env);
|
||||
/* mcode tree ownership transferred to JS_CallMcodeTreeEnv — do not free */
|
||||
JS_FreeCString (ctx, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* mach_eval_mcode(name, mcode_json, env?) - compile mcode IR and run via register VM */
|
||||
static JSValue js_mach_eval_mcode (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
if (argc < 2 || !JS_IsText (argv[0]) || !JS_IsText (argv[1]))
|
||||
@@ -10298,6 +10189,61 @@ static JSValue js_mach_eval_mcode (JSContext *ctx, JSValue this_val, int argc, J
|
||||
return result;
|
||||
}
|
||||
|
||||
/* mach_compile_mcode_bin(name, mcode_json) - compile mcode IR to serialized binary blob */
|
||||
static JSValue js_mach_compile_mcode_bin (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_mcode_bin requires (name, mcode_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 *mcode = cJSON_Parse (json_str);
|
||||
JS_FreeCString (ctx, json_str);
|
||||
|
||||
if (!mcode) {
|
||||
JS_FreeCString (ctx, name);
|
||||
return JS_ThrowSyntaxError (ctx, "mach_compile_mcode_bin: failed to parse mcode JSON");
|
||||
}
|
||||
|
||||
if (!cJSON_GetObjectItemCaseSensitive (mcode, "filename"))
|
||||
cJSON_AddStringToObject (mcode, "filename", name);
|
||||
|
||||
MachCode *mc = mach_compile_mcode (mcode);
|
||||
cJSON_Delete (mcode);
|
||||
JS_FreeCString (ctx, name);
|
||||
|
||||
if (!mc)
|
||||
return JS_ThrowInternalError (ctx, "mach_compile_mcode_bin: compilation failed");
|
||||
|
||||
size_t size = 0;
|
||||
uint8_t *data = JS_SerializeMachCode (mc, &size);
|
||||
|
||||
/* DEBUG: verify round-trip */
|
||||
{
|
||||
MachCode *mc2 = JS_DeserializeMachCode (data, size);
|
||||
if (mc2) {
|
||||
extern void verify_getup(MachCode *mc, const char *path);
|
||||
verify_getup(mc2, "ROUNDTRIP");
|
||||
JS_FreeMachCode (mc2);
|
||||
}
|
||||
}
|
||||
|
||||
JS_FreeMachCode (mc);
|
||||
|
||||
if (!data)
|
||||
return JS_ThrowInternalError (ctx, "mach_compile_mcode_bin: serialization failed");
|
||||
|
||||
JSValue blob = js_new_blob_stoned_copy (ctx, data, size);
|
||||
sys_free (data);
|
||||
return blob;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* stone() function - deep freeze with blob support
|
||||
* ============================================================================
|
||||
@@ -11398,11 +11344,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_ast", js_mach_compile_ast, 2);
|
||||
js_set_global_cfunc(ctx, "mach_load", js_mach_load, 2);
|
||||
js_set_global_cfunc(ctx, "mach_eval_mcode", js_mach_eval_mcode, 3);
|
||||
js_set_global_cfunc(ctx, "mach_compile_mcode_bin", js_mach_compile_mcode_bin, 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);
|
||||
@@ -13150,17 +13094,6 @@ cJSON *JS_GetStack(JSContext *ctx) {
|
||||
line = code->line_table[pc].line;
|
||||
col = code->line_table[pc].col;
|
||||
}
|
||||
} else if (fn->kind == JS_FUNC_KIND_MCODE && fn->u.mcode.code) {
|
||||
JSMCode *code = fn->u.mcode.code;
|
||||
file = code->filename;
|
||||
func_name = code->name;
|
||||
if (!is_first) {
|
||||
pc = (uint32_t)(JS_VALUE_GET_INT(frame->address) >> 16);
|
||||
}
|
||||
if (code->line_table && pc < code->instr_count) {
|
||||
line = code->line_table[pc].line;
|
||||
col = code->line_table[pc].col;
|
||||
}
|
||||
}
|
||||
|
||||
cJSON *entry = cJSON_CreateObject();
|
||||
|
||||
BIN
streamline.mach
BIN
streamline.mach
Binary file not shown.
BIN
tokenize.mach
BIN
tokenize.mach
Binary file not shown.
Reference in New Issue
Block a user