Merge branch 'mach' into mcode2

This commit is contained in:
2026-02-07 00:10:01 -06:00
2 changed files with 3694 additions and 21 deletions

View File

@@ -560,6 +560,9 @@ typedef enum MachOpcode {
MACH_THROW, /* disrupt — trigger disruption */
MACH_PUSH, /* push R(B) onto array R(A) */
MACH_POP, /* R(A) = pop last element from array R(B) */
MACH_NOP,
MACH_OP_COUNT
@@ -615,6 +618,8 @@ static const char *mach_opcode_names[MACH_OP_COUNT] = {
[MACH_NEWARRAY] = "newarray",
[MACH_CLOSURE] = "closure",
[MACH_THROW] = "throw",
[MACH_PUSH] = "push",
[MACH_POP] = "pop",
[MACH_NOP] = "nop",
};
@@ -29932,6 +29937,18 @@ static void ast_sem_check_assign_target (ASTSemState *st, ASTSemScope *scope, cJ
} else {
cJSON_AddNumberToObject (left, "level", -1);
}
} else if (strcmp (kind, ".") == 0 || strcmp (kind, "[") == 0 ||
strcmp (kind, "?.") == 0 || strcmp (kind, "?.[") == 0) {
/* Property access as assignment target: resolve the object expression */
cJSON *obj_expr = cJSON_GetObjectItem (left, "expression");
if (!obj_expr) obj_expr = cJSON_GetObjectItem (left, "left");
ast_sem_check_expr (st, scope, obj_expr);
/* Also resolve the index expression for computed access */
cJSON *idx_expr = cJSON_GetObjectItem (left, "index");
if (!idx_expr && strcmp (kind, "[") == 0)
idx_expr = cJSON_GetObjectItem (left, "right");
if (idx_expr && cJSON_IsObject (idx_expr))
ast_sem_check_expr (st, scope, idx_expr);
}
}
@@ -30024,7 +30041,9 @@ static void ast_sem_check_expr (ASTSemState *st, ASTSemScope *scope, cJSON *expr
/* Unary ops */
if (strcmp (kind, "!") == 0 || strcmp (kind, "~") == 0 ||
strcmp (kind, "delete") == 0 || strcmp (kind, "neg") == 0 ||
strcmp (kind, "pos") == 0 || strcmp (kind, "spread") == 0) {
strcmp (kind, "pos") == 0 || strcmp (kind, "spread") == 0 ||
strcmp (kind, "-unary") == 0 || strcmp (kind, "+unary") == 0 ||
strcmp (kind, "unary_-") == 0) {
ast_sem_check_expr (st, scope, cJSON_GetObjectItem (expr, "expression"));
return;
}
@@ -30039,10 +30058,12 @@ static void ast_sem_check_expr (ASTSemState *st, ASTSemScope *scope, cJSON *expr
}
/* Object literal */
if (strcmp (kind, "object") == 0) {
if (strcmp (kind, "object") == 0 || strcmp (kind, "record") == 0) {
cJSON *prop;
cJSON_ArrayForEach (prop, cJSON_GetObjectItem (expr, "list")) {
ast_sem_check_expr (st, scope, cJSON_GetObjectItem (prop, "value"));
cJSON *val = cJSON_GetObjectItem (prop, "value");
if (!val) val = cJSON_GetObjectItem (prop, "right");
ast_sem_check_expr (st, scope, val);
}
return;
}
@@ -31075,7 +31096,7 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
mach_free_reg_to(cs, save);
return dest;
}
if (strcmp(kind, "unary_-") == 0 || (strcmp(kind, "-") == 0 && !cJSON_GetObjectItem(node, "left"))) {
if (strcmp(kind, "unary_-") == 0 || strcmp(kind, "-unary") == 0 || (strcmp(kind, "-") == 0 && !cJSON_GetObjectItem(node, "left"))) {
if (dest < 0) dest = mach_reserve_reg(cs);
cJSON *operand = cJSON_GetObjectItem(node, "expression");
if (!operand) operand = cJSON_GetObjectItem(node, "right");
@@ -31086,10 +31107,160 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
return dest;
}
/* Unary plus: identity for numbers */
if (strcmp(kind, "+unary") == 0 || strcmp(kind, "pos") == 0) {
cJSON *operand = cJSON_GetObjectItem(node, "expression");
return mach_compile_expr(cs, operand, dest);
}
/* Comma operator: compile left for side effects, return right */
if (strcmp(kind, ",") == 0) {
cJSON *left = cJSON_GetObjectItem(node, "left");
cJSON *right = cJSON_GetObjectItem(node, "right");
int save = cs->freereg;
mach_compile_expr(cs, left, -1);
mach_free_reg_to(cs, save);
return mach_compile_expr(cs, right, dest);
}
/* Increment/Decrement as expression */
if (strcmp(kind, "++") == 0 || strcmp(kind, "--") == 0) {
if (dest < 0) dest = mach_reserve_reg(cs);
MachOpcode inc_op = (kind[0] == '+') ? MACH_INC : MACH_DEC;
cJSON *operand = cJSON_GetObjectItem(node, "expression");
cJSON *postfix_node = cJSON_GetObjectItem(node, "postfix");
int is_postfix = postfix_node && cJSON_IsTrue(postfix_node);
const char *op_kind = cJSON_GetStringValue(cJSON_GetObjectItem(operand, "kind"));
if (op_kind && strcmp(op_kind, "name") == 0) {
const char *name = cJSON_GetStringValue(cJSON_GetObjectItem(operand, "name"));
cJSON *level_node = cJSON_GetObjectItem(operand, "level");
int level = level_node ? (int)cJSON_GetNumberValue(level_node) : -1;
if (level == 0 && name) {
int slot = mach_find_var(cs, name);
if (slot >= 0) {
if (is_postfix) {
/* Return old value, then increment */
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, slot, 0));
mach_emit(cs, MACH_ABC(inc_op, slot, slot, 0));
} else {
/* Increment, then return new value */
mach_emit(cs, MACH_ABC(inc_op, slot, slot, 0));
if (dest != slot)
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, slot, 0));
}
return dest;
}
}
}
/* Fallback: just compile operand */
return mach_compile_expr(cs, operand, dest);
}
/* Compound assignment operators */
if (strcmp(kind, "+=") == 0 || strcmp(kind, "-=") == 0 ||
strcmp(kind, "*=") == 0 || strcmp(kind, "/=") == 0 ||
strcmp(kind, "%=") == 0 || strcmp(kind, "**=") == 0 ||
strcmp(kind, "&=") == 0 || strcmp(kind, "|=") == 0 ||
strcmp(kind, "^=") == 0 || strcmp(kind, "<<=") == 0 ||
strcmp(kind, ">>=") == 0 || strcmp(kind, ">>>=") == 0) {
if (dest < 0) dest = mach_reserve_reg(cs);
cJSON *left = cJSON_GetObjectItem(node, "left");
cJSON *right = cJSON_GetObjectItem(node, "right");
/* Map compound op to binary op */
MachOpcode binop;
if (strcmp(kind, "+=") == 0) binop = MACH_ADD;
else if (strcmp(kind, "-=") == 0) binop = MACH_SUB;
else if (strcmp(kind, "*=") == 0) binop = MACH_MUL;
else if (strcmp(kind, "/=") == 0) binop = MACH_DIV;
else if (strcmp(kind, "%=") == 0) binop = MACH_MOD;
else if (strcmp(kind, "**=") == 0) binop = MACH_POW;
else if (strcmp(kind, "&=") == 0) binop = MACH_BAND;
else if (strcmp(kind, "|=") == 0) binop = MACH_BOR;
else if (strcmp(kind, "^=") == 0) binop = MACH_BXOR;
else if (strcmp(kind, "<<=") == 0) binop = MACH_SHL;
else if (strcmp(kind, ">>=") == 0) binop = MACH_SHR;
else binop = MACH_USHR; /* >>>= */
const char *lk = cJSON_GetStringValue(cJSON_GetObjectItem(left, "kind"));
if (lk && strcmp(lk, "name") == 0) {
const char *name = cJSON_GetStringValue(cJSON_GetObjectItem(left, "name"));
cJSON *level_node = cJSON_GetObjectItem(left, "level");
int level = level_node ? (int)cJSON_GetNumberValue(level_node) : -1;
if (level == 0 && name) {
int slot = mach_find_var(cs, name);
if (slot >= 0) {
int save = cs->freereg;
int rr = mach_compile_expr(cs, right, -1);
mach_emit(cs, MACH_ABC(binop, slot, slot, rr));
mach_free_reg_to(cs, save);
if (dest != slot)
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, slot, 0));
return dest;
}
}
}
/* Fallback: load null */
mach_emit(cs, MACH_ABx(MACH_LOADNULL, dest, 0));
return dest;
}
/* In operator */
if (strcmp(kind, "in") == 0) {
if (dest < 0) dest = mach_reserve_reg(cs);
cJSON *left = cJSON_GetObjectItem(node, "left");
cJSON *right = cJSON_GetObjectItem(node, "right");
int save = cs->freereg;
int lr = mach_compile_expr(cs, left, -1);
int rr = mach_compile_expr(cs, right, -1);
/* Use MACH_ABC with a new opcode or use GETINDEX + check null.
For now, emit a HAS instruction (MACH_GETINDEX) and check if result is non-null.
Actually, we need a proper HAS check. Let's use a call to a runtime helper. */
/* We'll emit GETFIELD/GETINDEX then JMPNULL to check existence.
But "in" checks presence, not value. For string keys, use GETFIELD and check non-null.
This is an approximation that works for most cases. */
mach_emit(cs, MACH_ABC(MACH_GETINDEX, dest, rr, lr));
/* Check if result is null — if null, property doesn't exist → false
But this is wrong because a property CAN be set to null.
We need a proper HASPROP opcode. For now let's use JMPNULL. */
int jmpnull_pc = mach_current_pc(cs);
mach_emit(cs, MACH_AsBx(MACH_JMPNULL, dest, 0));
mach_emit(cs, MACH_ABx(MACH_LOADTRUE, dest, 0));
int jmpend_pc = mach_current_pc(cs);
mach_emit(cs, MACH_sJ(MACH_JMP, 0));
/* Patch jmpnull to false */
int offset = mach_current_pc(cs) - (jmpnull_pc + 1);
cs->code[jmpnull_pc] = MACH_AsBx(MACH_JMPNULL, dest, (int16_t)offset);
mach_emit(cs, MACH_ABx(MACH_LOADFALSE, dest, 0));
/* Patch jmpend */
offset = mach_current_pc(cs) - (jmpend_pc + 1);
cs->code[jmpend_pc] = MACH_sJ(MACH_JMP, offset);
mach_free_reg_to(cs, save);
return dest;
}
/* Assignment */
if (strcmp(kind, "assign") == 0) {
cJSON *left = cJSON_GetObjectItem(node, "left");
cJSON *right = cJSON_GetObjectItem(node, "right");
/* Push: arr[] = val */
cJSON *push_node = cJSON_GetObjectItem(node, "push");
if (push_node && cJSON_IsTrue(push_node)) {
if (dest < 0) dest = mach_reserve_reg(cs);
int save = cs->freereg;
cJSON *arr_expr = cJSON_GetObjectItem(left, "left");
if (!arr_expr) arr_expr = cJSON_GetObjectItem(left, "expression");
int arr_r = mach_compile_expr(cs, arr_expr, -1);
int val_r = mach_compile_expr(cs, right, -1);
mach_emit(cs, MACH_ABC(MACH_PUSH, arr_r, val_r, 0));
if (dest >= 0)
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, val_r, 0));
mach_free_reg_to(cs, save);
return dest;
}
const char *lk = cJSON_GetStringValue(cJSON_GetObjectItem(left, "kind"));
if (lk && strcmp(lk, "name") == 0) {
@@ -31131,10 +31302,14 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
if (dest < 0) dest = mach_reserve_reg(cs);
int save = cs->freereg;
cJSON *obj_expr = cJSON_GetObjectItem(left, "expression");
if (!obj_expr) obj_expr = cJSON_GetObjectItem(left, "left");
cJSON *prop = cJSON_GetObjectItem(left, "name");
if (!prop) prop = cJSON_GetObjectItem(left, "right");
const char *prop_name = NULL;
if (cJSON_IsString(prop)) prop_name = cJSON_GetStringValue(prop);
else prop_name = cJSON_GetStringValue(cJSON_GetObjectItem(left, "value"));
else if (prop) prop_name = cJSON_GetStringValue(cJSON_GetObjectItem(prop, "value"));
if (!prop_name && prop) prop_name = cJSON_GetStringValue(cJSON_GetObjectItem(prop, "name"));
if (!prop_name) prop_name = cJSON_GetStringValue(cJSON_GetObjectItem(left, "value"));
int obj_r = mach_compile_expr(cs, obj_expr, -1);
int val_r = mach_compile_expr(cs, right, dest);
@@ -31151,6 +31326,7 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
if (dest < 0) dest = mach_reserve_reg(cs);
int save = cs->freereg;
cJSON *obj_expr = cJSON_GetObjectItem(left, "expression");
if (!obj_expr) obj_expr = cJSON_GetObjectItem(left, "left");
cJSON *idx_expr = cJSON_GetObjectItem(left, "index");
if (!idx_expr) idx_expr = cJSON_GetObjectItem(left, "right");
@@ -31173,10 +31349,14 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
if (dest < 0) dest = mach_reserve_reg(cs);
int save = cs->freereg;
cJSON *obj_expr = cJSON_GetObjectItem(node, "expression");
if (!obj_expr) obj_expr = cJSON_GetObjectItem(node, "left");
cJSON *prop = cJSON_GetObjectItem(node, "name");
if (!prop) prop = cJSON_GetObjectItem(node, "right");
const char *prop_name = NULL;
if (cJSON_IsString(prop)) prop_name = cJSON_GetStringValue(prop);
else prop_name = cJSON_GetStringValue(cJSON_GetObjectItem(node, "value"));
else if (prop) prop_name = cJSON_GetStringValue(cJSON_GetObjectItem(prop, "value"));
if (!prop_name && prop) prop_name = cJSON_GetStringValue(cJSON_GetObjectItem(prop, "name"));
if (!prop_name) prop_name = cJSON_GetStringValue(cJSON_GetObjectItem(node, "value"));
int obj_r = mach_compile_expr(cs, obj_expr, -1);
if (prop_name) {
@@ -31192,6 +31372,7 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
if (dest < 0) dest = mach_reserve_reg(cs);
int save = cs->freereg;
cJSON *obj_expr = cJSON_GetObjectItem(node, "expression");
if (!obj_expr) obj_expr = cJSON_GetObjectItem(node, "left");
cJSON *idx_expr = cJSON_GetObjectItem(node, "index");
if (!idx_expr) idx_expr = cJSON_GetObjectItem(node, "right");
@@ -31202,8 +31383,8 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
return dest;
}
/* Object literal: kind="object" */
if (strcmp(kind, "object") == 0) {
/* Object literal: kind="object" or "record" */
if (strcmp(kind, "object") == 0 || strcmp(kind, "record") == 0) {
if (dest < 0) dest = mach_reserve_reg(cs);
mach_emit(cs, MACH_ABC(MACH_NEWOBJECT, dest, 0, 0));
cJSON *props = cJSON_GetObjectItem(node, "list");
@@ -31212,11 +31393,13 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
for (int i = 0; i < count; i++) {
cJSON *prop = cJSON_GetArrayItem(props, i);
cJSON *key_node = cJSON_GetObjectItem(prop, "key");
if (!key_node) key_node = cJSON_GetObjectItem(prop, "left");
cJSON *val_node = cJSON_GetObjectItem(prop, "value");
if (!val_node) val_node = cJSON_GetObjectItem(prop, "right");
if (!val_node) val_node = cJSON_GetObjectItem(prop, "expression");
const char *key = cJSON_GetStringValue(key_node);
if (!key) key = cJSON_GetStringValue(cJSON_GetObjectItem(key_node, "value"));
if (!key) key = cJSON_GetStringValue(cJSON_GetObjectItem(key_node, "name"));
if (!key && key_node) key = cJSON_GetStringValue(cJSON_GetObjectItem(key_node, "value"));
if (!key && key_node) key = cJSON_GetStringValue(cJSON_GetObjectItem(key_node, "name"));
if (key && val_node) {
int save = cs->freereg;
int vr = mach_compile_expr(cs, val_node, -1);
@@ -31237,7 +31420,7 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
/* Reserve consecutive regs for elements starting at dest+1 */
int save = cs->freereg;
if (cs->freereg <= dest) cs->freereg = dest + 1;
cs->freereg = dest + 1;
for (int i = 0; i < count; i++) {
int er = mach_reserve_reg(cs);
cJSON *elem = cJSON_GetArrayItem(elems, i);
@@ -31249,8 +31432,8 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
return dest;
}
/* Ternary: kind="?" */
if (strcmp(kind, "?") == 0) {
/* Ternary: kind="?" or "then" */
if (strcmp(kind, "?") == 0 || strcmp(kind, "then") == 0) {
if (dest < 0) dest = mach_reserve_reg(cs);
cJSON *cond = cJSON_GetObjectItem(node, "expression");
if (!cond) cond = cJSON_GetObjectItem(node, "condition");
@@ -31405,6 +31588,17 @@ static void mach_compile_stmt(MachCompState *cs, cJSON *stmt) {
slot = mach_reserve_reg(cs);
mach_add_var(cs, name, slot, strcmp(kind, "def") == 0);
}
/* Pop: var x = arr[] */
cJSON *pop_node = cJSON_GetObjectItem(stmt, "pop");
if (pop_node && cJSON_IsTrue(pop_node) && right) {
cJSON *arr_expr = cJSON_GetObjectItem(right, "left");
if (!arr_expr) arr_expr = cJSON_GetObjectItem(right, "expression");
int save = cs->freereg;
int arr_r = mach_compile_expr(cs, arr_expr, -1);
mach_emit(cs, MACH_ABC(MACH_POP, slot, arr_r, 0));
mach_free_reg_to(cs, save);
return;
}
if (right) {
int r = mach_compile_expr(cs, right, slot);
if (r != slot)
@@ -31413,6 +31607,17 @@ static void mach_compile_stmt(MachCompState *cs, cJSON *stmt) {
return;
}
/* var_list: multiple declarations in one statement */
if (strcmp(kind, "var_list") == 0) {
cJSON *list = cJSON_GetObjectItem(stmt, "list");
if (list && cJSON_IsArray(list)) {
int count = cJSON_GetArraySize(list);
for (int i = 0; i < count; i++)
mach_compile_stmt(cs, cJSON_GetArrayItem(list, i));
}
return;
}
/* Function declaration statement */
if (strcmp(kind, "function") == 0) {
const char *name = cJSON_GetStringValue(cJSON_GetObjectItem(stmt, "name"));
@@ -32045,6 +32250,39 @@ static JSValue reg_vm_binop(JSContext *ctx, int op, JSValue a, JSValue b) {
default: break;
}
}
/* String comparisons */
if (JS_IsText(a) && JS_IsText(b)) {
int cmp = js_string_compare_value(ctx, a, b, FALSE);
switch (op) {
case MACH_EQ: return JS_NewBool(ctx, cmp == 0);
case MACH_NEQ: return JS_NewBool(ctx, cmp != 0);
case MACH_LT: return JS_NewBool(ctx, cmp < 0);
case MACH_LE: return JS_NewBool(ctx, cmp <= 0);
case MACH_GT: return JS_NewBool(ctx, cmp > 0);
case MACH_GE: return JS_NewBool(ctx, cmp >= 0);
default: break;
}
}
/* Null comparisons */
if (JS_IsNull(a) && JS_IsNull(b)) {
if (op == MACH_EQ || op == MACH_LE || op == MACH_GE)
return JS_TRUE;
return JS_FALSE;
}
/* Boolean comparisons */
if (JS_IsBool(a) && JS_IsBool(b)) {
int ba = JS_VALUE_GET_BOOL(a);
int bb = JS_VALUE_GET_BOOL(b);
switch (op) {
case MACH_EQ: return JS_NewBool(ctx, ba == bb);
case MACH_NEQ: return JS_NewBool(ctx, ba != bb);
case MACH_LT: return JS_NewBool(ctx, ba < bb);
case MACH_LE: return JS_NewBool(ctx, ba <= bb);
case MACH_GT: return JS_NewBool(ctx, ba > bb);
case MACH_GE: return JS_NewBool(ctx, ba >= bb);
default: break;
}
}
/* Different types: EQ→false, NEQ→true, others→false */
if (op == MACH_NEQ) return JS_NewBool(ctx, 1);
return JS_NewBool(ctx, 0);
@@ -32056,12 +32294,38 @@ static JSValue reg_vm_binop(JSContext *ctx, int op, JSValue a, JSValue b) {
JS_ToFloat64(ctx, &da, a);
JS_ToFloat64(ctx, &db, b);
switch (op) {
case MACH_ADD: return JS_NewFloat64(ctx, da + db);
case MACH_SUB: return JS_NewFloat64(ctx, da - db);
case MACH_MUL: return JS_NewFloat64(ctx, da * db);
case MACH_DIV: return JS_NewFloat64(ctx, da / db);
case MACH_MOD: return JS_NewFloat64(ctx, fmod(da, db));
case MACH_POW: return JS_NewFloat64(ctx, pow(da, db));
case MACH_ADD: {
double r = da + db;
if (!isfinite(r)) return JS_NULL;
return JS_NewFloat64(ctx, r);
}
case MACH_SUB: {
double r = da - db;
if (!isfinite(r)) return JS_NULL;
return JS_NewFloat64(ctx, r);
}
case MACH_MUL: {
double r = da * db;
if (!isfinite(r)) return JS_NULL;
return JS_NewFloat64(ctx, r);
}
case MACH_DIV: {
if (db == 0.0) return JS_NULL;
double r = da / db;
if (!isfinite(r)) return JS_NULL;
return JS_NewFloat64(ctx, r);
}
case MACH_MOD: {
if (db == 0.0) return JS_NULL;
double r = fmod(da, db);
if (!isfinite(r)) return JS_NULL;
return JS_NewFloat64(ctx, r);
}
case MACH_POW: {
double r = pow(da, db);
if (!isfinite(r) && isfinite(da) && isfinite(db)) return JS_NULL;
return JS_NewFloat64(ctx, r);
}
case MACH_BAND: case MACH_BOR: case MACH_BXOR:
case MACH_SHL: case MACH_SHR: case MACH_USHR: {
int32_t ia = (int32_t)da;
@@ -32571,11 +32835,12 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
JSValue arr = JS_NewArray(ctx);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (JS_IsException(arr)) { goto disrupt; }
/* Store array in dest immediately so GC can track it */
frame->slots[a] = arr;
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(ctx, arr, i, frame->slots[a + 1 + i]);
JS_SetPropertyUint32(ctx, frame->slots[a], i, frame->slots[a + 1 + i]);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
}
frame->slots[a] = arr;
break;
}
@@ -32592,6 +32857,30 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
break;
}
case MACH_PUSH: {
/* push R(B) onto array R(A) */
JSValue arr = frame->slots[a];
JSValue val = frame->slots[b];
if (!JS_IsArray(arr)) goto disrupt;
JSValue arr_ref = arr;
int rc = JS_ArrayPush(ctx, &arr_ref, val);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (rc < 0) goto disrupt;
if (arr_ref != arr) frame->slots[a] = arr_ref;
break;
}
case MACH_POP: {
/* R(A) = pop last element from array R(B) */
JSValue arr = frame->slots[b];
if (!JS_IsArray(arr)) goto disrupt;
JSValue val = JS_ArrayPop(ctx, arr);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (JS_IsException(val)) goto disrupt;
frame->slots[a] = val;
break;
}
case MACH_THROW:
goto disrupt;
@@ -35771,6 +36060,14 @@ static void dump_register_code(JSContext *ctx, JSCodeRegister *code, int indent)
printf("r%d, %d", a, b);
break;
/* Push/Pop */
case MACH_PUSH:
printf("r%d, r%d", a, b);
break;
case MACH_POP:
printf("r%d, r%d", a, b);
break;
/* Closure */
case MACH_CLOSURE: {
int bx = MACH_GET_Bx(instr);

3376
vm_suite.ce Normal file

File diff suppressed because it is too large Load Diff