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',
|
'miniz.c',
|
||||||
'runtime.c',
|
'runtime.c',
|
||||||
'mach.c',
|
'mach.c',
|
||||||
'mcode.c',
|
|
||||||
'libregexp.c', 'libunicode.c', 'cutils.c', 'dtoa.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 errors = []
|
||||||
var error_count = 0
|
var error_count = 0
|
||||||
var function_nr = 1
|
var fn_counter = 1
|
||||||
|
|
||||||
var ast_node = function(kind, token) {
|
var ast_node = function(kind, token) {
|
||||||
return {
|
return {
|
||||||
@@ -422,8 +422,8 @@ var parse = function(tokens, src, filename, tokenizer) {
|
|||||||
_control_depth = meth_old_cd
|
_control_depth = meth_old_cd
|
||||||
_control_type = meth_old_ct
|
_control_type = meth_old_ct
|
||||||
_expecting_body = meth_old_eb
|
_expecting_body = meth_old_eb
|
||||||
fn.function_nr = function_nr
|
fn.function_nr = fn_counter
|
||||||
function_nr = function_nr + 1
|
fn_counter = fn_counter + 1
|
||||||
ast_node_end(fn)
|
ast_node_end(fn)
|
||||||
pair.right = fn
|
pair.right = fn
|
||||||
} else if (is_ident && (tok.kind == "," || tok.kind == "}")) {
|
} else if (is_ident && (tok.kind == "," || tok.kind == "}")) {
|
||||||
@@ -918,8 +918,8 @@ var parse = function(tokens, src, filename, tokenizer) {
|
|||||||
_control_depth = old_cd
|
_control_depth = old_cd
|
||||||
_control_type = old_ct
|
_control_type = old_ct
|
||||||
_expecting_body = old_eb
|
_expecting_body = old_eb
|
||||||
node.function_nr = function_nr
|
node.function_nr = fn_counter
|
||||||
function_nr = function_nr + 1
|
fn_counter = fn_counter + 1
|
||||||
ast_node_end(node)
|
ast_node_end(node)
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
@@ -1008,8 +1008,8 @@ var parse = function(tokens, src, filename, tokenizer) {
|
|||||||
_control_depth = old_cd
|
_control_depth = old_cd
|
||||||
_control_type = old_ct
|
_control_type = old_ct
|
||||||
_expecting_body = old_eb
|
_expecting_body = old_eb
|
||||||
node.function_nr = function_nr
|
node.function_nr = fn_counter
|
||||||
function_nr = function_nr + 1
|
fn_counter = fn_counter + 1
|
||||||
ast_node_end(node)
|
ast_node_end(node)
|
||||||
return 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 tokenize = use("tokenize")
|
||||||
var parse = use("parse")
|
var parse = use("parse")
|
||||||
var fold = use("fold")
|
var fold = use("fold")
|
||||||
|
var mcode = use("mcode")
|
||||||
|
var streamline = use("streamline")
|
||||||
|
|
||||||
var files = [
|
var files = [
|
||||||
{src: "tokenize.cm", name: "tokenize", out: "tokenize.mach"},
|
{src: "tokenize.cm", name: "tokenize", out: "tokenize.mach"},
|
||||||
@@ -25,21 +27,49 @@ var src = null
|
|||||||
var tok_result = null
|
var tok_result = null
|
||||||
var ast = null
|
var ast = null
|
||||||
var folded = null
|
var folded = null
|
||||||
var ast_json = null
|
var compiled = null
|
||||||
|
var optimized = null
|
||||||
|
var mcode_json = null
|
||||||
var bytecode = null
|
var bytecode = null
|
||||||
var f = null
|
var f = null
|
||||||
|
var errs = null
|
||||||
|
var ei = 0
|
||||||
|
var e = null
|
||||||
|
var had_errors = false
|
||||||
|
|
||||||
while (i < length(files)) {
|
while (i < length(files)) {
|
||||||
entry = files[i]
|
entry = files[i]
|
||||||
src = text(fd.slurp(entry.src))
|
src = text(fd.slurp(entry.src))
|
||||||
tok_result = tokenize(src, entry.src)
|
tok_result = tokenize(src, entry.src)
|
||||||
ast = parse(tok_result.tokens, src, entry.src, tokenize)
|
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)
|
folded = fold(ast)
|
||||||
ast_json = json.encode(folded)
|
compiled = mcode(folded)
|
||||||
bytecode = mach_compile_ast(entry.name, ast_json)
|
optimized = streamline(compiled)
|
||||||
|
mcode_json = json.encode(optimized)
|
||||||
|
bytecode = mach_compile_mcode_bin(entry.name, mcode_json)
|
||||||
f = fd.open(entry.out, "w")
|
f = fd.open(entry.out, "w")
|
||||||
fd.write(f, bytecode)
|
fd.write(f, bytecode)
|
||||||
fd.close(f)
|
fd.close(f)
|
||||||
print(`wrote ${entry.out}`)
|
print(`wrote ${entry.out}`)
|
||||||
i = i + 1
|
i = i + 1
|
||||||
}
|
}
|
||||||
|
if (had_errors) {
|
||||||
|
print("regen aborted: fix errors above")
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
|
|
||||||
#define BOOTSTRAP_MACH "internal/bootstrap.mach"
|
#define BOOTSTRAP_MACH "internal/bootstrap.mach"
|
||||||
#define BOOTSTRAP_AST "internal/bootstrap.ast.json"
|
|
||||||
#define BOOTSTRAP_SRC "internal/bootstrap.cm"
|
#define BOOTSTRAP_SRC "internal/bootstrap.cm"
|
||||||
#define CELL_SHOP_DIR ".cell"
|
#define CELL_SHOP_DIR ".cell"
|
||||||
#define CELL_CORE_DIR "packages/core"
|
#define CELL_CORE_DIR "packages/core"
|
||||||
@@ -179,14 +178,9 @@ void script_startup(cell_rt *prt)
|
|||||||
cell_rt *crt = JS_GetContextOpaque(js);
|
cell_rt *crt = JS_GetContextOpaque(js);
|
||||||
JS_FreeValue(js, js_blob_use(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;
|
size_t boot_size;
|
||||||
int boot_is_bin = 1;
|
|
||||||
char *boot_data = load_core_file(BOOTSTRAP_MACH, &boot_size);
|
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) {
|
if (!boot_data) {
|
||||||
printf("ERROR: Could not load bootstrap from %s!\n", core_path);
|
printf("ERROR: Could not load bootstrap from %s!\n", core_path);
|
||||||
return;
|
return;
|
||||||
@@ -225,17 +219,8 @@ void script_startup(cell_rt *prt)
|
|||||||
|
|
||||||
// Run through MACH VM
|
// Run through MACH VM
|
||||||
crt->state = ACTOR_RUNNING;
|
crt->state = ACTOR_RUNNING;
|
||||||
JSValue v;
|
JSValue v = JS_RunMachBin(js, (const uint8_t *)boot_data, boot_size, hidden_env);
|
||||||
if (boot_is_bin) {
|
|
||||||
v = JS_RunMachBin(js, (const uint8_t *)boot_data, boot_size, hidden_env);
|
|
||||||
free(boot_data);
|
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);
|
|
||||||
}
|
|
||||||
uncaught_exception(js, v);
|
uncaught_exception(js, v);
|
||||||
crt->state = ACTOR_IDLE;
|
crt->state = ACTOR_IDLE;
|
||||||
set_actor_state(crt);
|
set_actor_state(crt);
|
||||||
@@ -359,12 +344,7 @@ int cell_init(int argc, char **argv)
|
|||||||
actor_initialize();
|
actor_initialize();
|
||||||
|
|
||||||
size_t boot_size;
|
size_t boot_size;
|
||||||
int boot_is_bin = 1;
|
|
||||||
char *boot_data = load_core_file(BOOTSTRAP_MACH, &boot_size);
|
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) {
|
if (!boot_data) {
|
||||||
printf("ERROR: Could not load bootstrap from %s\n", core_path);
|
printf("ERROR: Could not load bootstrap from %s\n", core_path);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -433,17 +413,8 @@ int cell_init(int argc, char **argv)
|
|||||||
JS_SetPropertyStr(ctx, hidden_env, "args", args_arr);
|
JS_SetPropertyStr(ctx, hidden_env, "args", args_arr);
|
||||||
hidden_env = JS_Stone(ctx, hidden_env);
|
hidden_env = JS_Stone(ctx, hidden_env);
|
||||||
|
|
||||||
JSValue result;
|
JSValue result = JS_RunMachBin(ctx, (const uint8_t *)boot_data, boot_size, hidden_env);
|
||||||
if (boot_is_bin) {
|
|
||||||
result = JS_RunMachBin(ctx, (const uint8_t *)boot_data, boot_size, hidden_env);
|
|
||||||
free(boot_data);
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
int exit_code = 0;
|
int exit_code = 0;
|
||||||
if (JS_IsException(result)) {
|
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) */
|
uint16_t disruption_pc; /* start of disruption handler (0 = none) */
|
||||||
} JSCodeRegister;
|
} 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
|
/* Frame for closures - used by link-time relocation model where closures
|
||||||
reference outer frames via (depth, slot) addressing.
|
reference outer frames via (depth, slot) addressing.
|
||||||
@@ -1306,7 +1284,6 @@ typedef enum {
|
|||||||
JS_FUNC_KIND_BYTECODE,
|
JS_FUNC_KIND_BYTECODE,
|
||||||
JS_FUNC_KIND_C_DATA,
|
JS_FUNC_KIND_C_DATA,
|
||||||
JS_FUNC_KIND_REGISTER, /* register-based VM function */
|
JS_FUNC_KIND_REGISTER, /* register-based VM function */
|
||||||
JS_FUNC_KIND_MCODE, /* MCODE JSON interpreter */
|
|
||||||
} JSFunctionKind;
|
} JSFunctionKind;
|
||||||
|
|
||||||
typedef struct JSFunction {
|
typedef struct JSFunction {
|
||||||
@@ -1330,11 +1307,6 @@ typedef struct JSFunction {
|
|||||||
JSValue env_record; /* stone record, module environment */
|
JSValue env_record; /* stone record, module environment */
|
||||||
JSValue outer_frame; /* JSFrame JSValue, for closures */
|
JSValue outer_frame; /* JSFrame JSValue, for closures */
|
||||||
} reg;
|
} 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;
|
} u;
|
||||||
} JSFunction;
|
} 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_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_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 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);
|
int JS_DeleteProperty (JSContext *ctx, JSValue obj, JSValue prop);
|
||||||
JSValue __attribute__ ((format (printf, 2, 3)))
|
JSValue __attribute__ ((format (printf, 2, 3)))
|
||||||
JS_ThrowInternalError (JSContext *ctx, const char *fmt, ...);
|
JS_ThrowInternalError (JSContext *ctx, const char *fmt, ...);
|
||||||
@@ -1860,13 +1830,6 @@ typedef struct {
|
|||||||
} GetLineColCache;
|
} 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) === */
|
/* === PPretext (parser pretext, system-malloc, used by cell_js.c parser) === */
|
||||||
typedef struct PPretext {
|
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);
|
cJSON *mach_find_scope_record(cJSON *scopes, int function_nr);
|
||||||
int reg_vm_check_interrupt(JSContext *ctx);
|
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 */
|
#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. */
|
/* Load compiled MachCode into a JSContext, materializing JSValues. */
|
||||||
struct JSCodeRegister *JS_LoadMachCode(JSContext *ctx, MachCode *mc, JSValue env);
|
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. */
|
/* Deserialize and execute pre-compiled MACH binary bytecode. */
|
||||||
JSValue JS_RunMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue env);
|
JSValue JS_RunMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue env);
|
||||||
|
|
||||||
/* Compile mcode JSON IR to MachCode binary. */
|
/* Compile mcode JSON IR to MachCode binary. */
|
||||||
MachCode *mach_compile_mcode(struct cJSON *mcode_json);
|
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.
|
/* Get stack trace as cJSON array of frame objects.
|
||||||
Returns NULL if no register VM frame is active.
|
Returns NULL if no register VM frame is active.
|
||||||
Caller must call cJSON_Delete() on the result. */
|
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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4630,8 +4626,6 @@ JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj,
|
|||||||
case JS_FUNC_KIND_REGISTER:
|
case JS_FUNC_KIND_REGISTER:
|
||||||
return JS_CallRegisterVM (ctx, f->u.reg.code, this_obj, argc, argv,
|
return JS_CallRegisterVM (ctx, f->u.reg.code, this_obj, argc, argv,
|
||||||
f->u.reg.env_record, f->u.reg.outer_frame);
|
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:
|
default:
|
||||||
return JS_ThrowTypeError (ctx, "not a function");
|
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:
|
case JS_FUNC_KIND_REGISTER:
|
||||||
return JS_CallRegisterVM (ctx, f->u.reg.code, this_obj, argc, argv,
|
return JS_CallRegisterVM (ctx, f->u.reg.code, this_obj, argc, argv,
|
||||||
f->u.reg.env_record, f->u.reg.outer_frame);
|
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:
|
default:
|
||||||
return JS_ThrowTypeError (ctx, "not a function");
|
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 */
|
/* mach_load(blob, env?) - deserialize and execute binary blob */
|
||||||
static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||||
if (argc < 1)
|
if (argc < 1)
|
||||||
@@ -10207,6 +10122,11 @@ static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue
|
|||||||
if (!mc)
|
if (!mc)
|
||||||
return JS_ThrowSyntaxError (ctx, "mach_load: failed to deserialize bytecode");
|
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;
|
JSValue env = (argc >= 2 && JS_IsObject (argv[1])) ? argv[1] : JS_NULL;
|
||||||
|
|
||||||
JSGCRef env_ref;
|
JSGCRef env_ref;
|
||||||
@@ -10220,35 +10140,6 @@ static JSValue js_mach_load (JSContext *ctx, JSValue this_val, int argc, JSValue
|
|||||||
return result;
|
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 */
|
/* 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) {
|
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]))
|
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;
|
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
|
* stone() function - deep freeze with blob support
|
||||||
* ============================================================================
|
* ============================================================================
|
||||||
@@ -11398,11 +11344,9 @@ static void JS_AddIntrinsicBaseObjects (JSContext *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Core functions - using GC-safe helper */
|
/* 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_load", js_mach_load, 2);
|
||||||
js_set_global_cfunc(ctx, "mach_eval_mcode", js_mach_eval_mcode, 3);
|
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, "stone", js_cell_stone, 1);
|
||||||
js_set_global_cfunc(ctx, "length", js_cell_length, 1);
|
js_set_global_cfunc(ctx, "length", js_cell_length, 1);
|
||||||
js_set_global_cfunc(ctx, "call", js_cell_call, 3);
|
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;
|
line = code->line_table[pc].line;
|
||||||
col = code->line_table[pc].col;
|
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();
|
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