Merge branch 'mcode2' into mach
This commit is contained in:
237
source/quickjs.c
237
source/quickjs.c
@@ -30728,7 +30728,8 @@ typedef enum MachVarResolution {
|
||||
typedef struct MachVarInfo {
|
||||
char *name;
|
||||
int slot;
|
||||
int is_const; /* 1 for def, function args; 0 for var */
|
||||
int is_const; /* 1 for def, function args; 0 for var */
|
||||
int is_closure; /* 1 if captured by a nested function */
|
||||
} MachVarInfo;
|
||||
|
||||
/* ---- Compile-time constant pool entry ---- */
|
||||
@@ -30922,6 +30923,7 @@ static void mach_add_var(MachCompState *cs, const char *name, int slot, int is_c
|
||||
strcpy(v->name, name);
|
||||
v->slot = slot;
|
||||
v->is_const = is_const;
|
||||
v->is_closure = 0;
|
||||
}
|
||||
|
||||
/* Find a variable in the current scope */
|
||||
@@ -32562,13 +32564,47 @@ typedef struct MachGenState {
|
||||
int function_nr;
|
||||
cJSON *scopes;
|
||||
|
||||
/* Intrinsic (global) name cache */
|
||||
struct { const char *name; int slot; } intrinsic_cache[64];
|
||||
int intrinsic_count;
|
||||
|
||||
/* Error tracking */
|
||||
cJSON *errors;
|
||||
int has_error;
|
||||
} MachGenState;
|
||||
|
||||
static int mach_gen_expr (MachGenState *s, cJSON *expr);
|
||||
static int mach_gen_expr (MachGenState *s, cJSON *expr, int target);
|
||||
static void mach_gen_statement (MachGenState *s, cJSON *stmt);
|
||||
static int mach_gen_alloc_slot (MachGenState *s);
|
||||
|
||||
/* Look up an intrinsic in the cache, return slot or -1 */
|
||||
static int mach_gen_find_intrinsic (MachGenState *s, const char *name) {
|
||||
for (int i = 0; i < s->intrinsic_count; i++) {
|
||||
if (strcmp (s->intrinsic_cache[i].name, name) == 0)
|
||||
return s->intrinsic_cache[i].slot;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pre-load intrinsics from the AST intrinsics array */
|
||||
static void mach_gen_load_intrinsics (MachGenState *s, cJSON *intrinsics) {
|
||||
if (!intrinsics) return;
|
||||
cJSON *item;
|
||||
cJSON_ArrayForEach (item, intrinsics) {
|
||||
const char *name = cJSON_GetStringValue (item);
|
||||
if (!name || s->intrinsic_count >= 64) continue;
|
||||
if (mach_gen_find_intrinsic (s, name) >= 0) continue;
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
cJSON *instr = cJSON_CreateArray ();
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateString ("cap_name"));
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateNumber (slot));
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateString (name));
|
||||
cJSON_AddItemToArray (s->instructions, instr);
|
||||
s->intrinsic_cache[s->intrinsic_count].name = name;
|
||||
s->intrinsic_cache[s->intrinsic_count].slot = slot;
|
||||
s->intrinsic_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a temporary slot */
|
||||
static int mach_gen_alloc_slot (MachGenState *s) {
|
||||
@@ -32589,6 +32625,7 @@ static void mach_gen_add_var (MachGenState *s, const char *name, int slot, int i
|
||||
strcpy (v->name, name);
|
||||
v->slot = slot;
|
||||
v->is_const = is_const;
|
||||
v->is_closure = 0;
|
||||
}
|
||||
|
||||
/* Find a variable in the current scope only */
|
||||
@@ -32641,6 +32678,8 @@ static void mach_gen_scan_scope (MachGenState *s) {
|
||||
int is_const = (strcmp (make, "def") == 0 || strcmp (make, "function") == 0);
|
||||
int slot = 1 + s->nr_args + s->nr_local_slots++;
|
||||
mach_gen_add_var (s, name, slot, is_const);
|
||||
cJSON *closure_flag = cJSON_GetObjectItem (v, "closure");
|
||||
s->vars[s->var_count - 1].is_closure = (closure_flag && cJSON_IsTrue (closure_flag));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32841,11 +32880,11 @@ static int mach_gen_binary (MachGenState *s, cJSON *node) {
|
||||
|
||||
if (strcmp (kind, "&&") == 0) {
|
||||
char *end_label = mach_gen_label (s, "and_end");
|
||||
int left_slot = mach_gen_expr (s, left);
|
||||
int left_slot = mach_gen_expr (s, left, -1);
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_2 (s, "move", dest, left_slot);
|
||||
mach_gen_emit_jump_cond (s, "jump_false", dest, end_label);
|
||||
int right_slot = mach_gen_expr (s, right);
|
||||
int right_slot = mach_gen_expr (s, right, -1);
|
||||
mach_gen_emit_2 (s, "move", dest, right_slot);
|
||||
mach_gen_emit_label (s, end_label);
|
||||
sys_free (end_label);
|
||||
@@ -32854,11 +32893,11 @@ static int mach_gen_binary (MachGenState *s, cJSON *node) {
|
||||
|
||||
if (strcmp (kind, "||") == 0) {
|
||||
char *end_label = mach_gen_label (s, "or_end");
|
||||
int left_slot = mach_gen_expr (s, left);
|
||||
int left_slot = mach_gen_expr (s, left, -1);
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_2 (s, "move", dest, left_slot);
|
||||
mach_gen_emit_jump_cond (s, "jump_true", dest, end_label);
|
||||
int right_slot = mach_gen_expr (s, right);
|
||||
int right_slot = mach_gen_expr (s, right, -1);
|
||||
mach_gen_emit_2 (s, "move", dest, right_slot);
|
||||
mach_gen_emit_label (s, end_label);
|
||||
sys_free (end_label);
|
||||
@@ -32867,19 +32906,19 @@ static int mach_gen_binary (MachGenState *s, cJSON *node) {
|
||||
|
||||
if (strcmp (kind, "??") == 0) {
|
||||
char *end_label = mach_gen_label (s, "nullish_end");
|
||||
int left_slot = mach_gen_expr (s, left);
|
||||
int left_slot = mach_gen_expr (s, left, -1);
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_2 (s, "move", dest, left_slot);
|
||||
mach_gen_emit_jump_cond (s, "jump_not_null", dest, end_label);
|
||||
int right_slot = mach_gen_expr (s, right);
|
||||
int right_slot = mach_gen_expr (s, right, -1);
|
||||
mach_gen_emit_2 (s, "move", dest, right_slot);
|
||||
mach_gen_emit_label (s, end_label);
|
||||
sys_free (end_label);
|
||||
return dest;
|
||||
}
|
||||
|
||||
int left_slot = mach_gen_expr (s, left);
|
||||
int right_slot = mach_gen_expr (s, right);
|
||||
int left_slot = mach_gen_expr (s, left, -1);
|
||||
int right_slot = mach_gen_expr (s, right, -1);
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
const char *op = mach_gen_binop_to_string (kind);
|
||||
mach_gen_emit_3 (s, op, dest, left_slot, right_slot);
|
||||
@@ -32911,7 +32950,7 @@ static int mach_gen_compound_assign (MachGenState *s, cJSON *node, const char *o
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateString (name));
|
||||
cJSON_AddItemToArray (s->instructions, instr);
|
||||
}
|
||||
int right_slot = mach_gen_expr (s, right);
|
||||
int right_slot = mach_gen_expr (s, right, -1);
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_3 (s, op, dest, left_slot, right_slot);
|
||||
if (level == 0) {
|
||||
@@ -32933,10 +32972,10 @@ static int mach_gen_compound_assign (MachGenState *s, cJSON *node, const char *o
|
||||
} else if (strcmp (left_kind, ".") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (left, "left");
|
||||
const char *prop = cJSON_GetStringValue (cJSON_GetObjectItem (left, "right"));
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
int old_val = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_get_prop (s, old_val, obj_slot, prop);
|
||||
int right_slot = mach_gen_expr (s, right);
|
||||
int right_slot = mach_gen_expr (s, right, -1);
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_3 (s, op, dest, old_val, right_slot);
|
||||
mach_gen_emit_set_prop (s, obj_slot, prop, dest);
|
||||
@@ -32944,11 +32983,11 @@ static int mach_gen_compound_assign (MachGenState *s, cJSON *node, const char *o
|
||||
} else if (strcmp (left_kind, "[") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (left, "left");
|
||||
cJSON *idx_expr = cJSON_GetObjectItem (left, "right");
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int idx_slot = mach_gen_expr (s, idx_expr);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
int idx_slot = mach_gen_expr (s, idx_expr, -1);
|
||||
int old_val = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_get_elem (s, old_val, obj_slot, idx_slot);
|
||||
int right_slot = mach_gen_expr (s, right);
|
||||
int right_slot = mach_gen_expr (s, right, -1);
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_3 (s, op, dest, old_val, right_slot);
|
||||
mach_gen_emit_set_elem (s, obj_slot, idx_slot, dest);
|
||||
@@ -32975,7 +33014,7 @@ static int mach_gen_assign (MachGenState *s, cJSON *node) {
|
||||
if (strcmp (kind, ">>=") == 0) return mach_gen_compound_assign (s, node, "shr");
|
||||
if (strcmp (kind, ">>>=") == 0) return mach_gen_compound_assign (s, node, "ushr");
|
||||
|
||||
int val_slot = mach_gen_expr (s, right);
|
||||
int val_slot = mach_gen_expr (s, right, -1);
|
||||
const char *left_kind = cJSON_GetStringValue (cJSON_GetObjectItem (left, "kind"));
|
||||
|
||||
if (strcmp (left_kind, "name") == 0) {
|
||||
@@ -32996,13 +33035,13 @@ static int mach_gen_assign (MachGenState *s, cJSON *node) {
|
||||
} else if (strcmp (left_kind, ".") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (left, "left");
|
||||
const char *prop = cJSON_GetStringValue (cJSON_GetObjectItem (left, "right"));
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
mach_gen_emit_set_prop (s, obj_slot, prop, val_slot);
|
||||
} else if (strcmp (left_kind, "[") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (left, "left");
|
||||
cJSON *idx_expr = cJSON_GetObjectItem (left, "right");
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int idx_slot = mach_gen_expr (s, idx_expr);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
int idx_slot = mach_gen_expr (s, idx_expr, -1);
|
||||
mach_gen_emit_set_elem (s, obj_slot, idx_slot, val_slot);
|
||||
}
|
||||
return val_slot;
|
||||
@@ -33010,36 +33049,36 @@ static int mach_gen_assign (MachGenState *s, cJSON *node) {
|
||||
|
||||
static cJSON *mach_gen_function (MachGenState *parent, cJSON *func_node);
|
||||
|
||||
static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
static int mach_gen_expr (MachGenState *s, cJSON *expr, int target) {
|
||||
if (!expr) return -1;
|
||||
const char *kind = cJSON_GetStringValue (cJSON_GetObjectItem (expr, "kind"));
|
||||
if (!kind) return -1;
|
||||
|
||||
/* Literals */
|
||||
/* Literals — use target slot if provided */
|
||||
if (strcmp (kind, "number") == 0) {
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
int slot = target >= 0 ? target : mach_gen_alloc_slot (s);
|
||||
double val = cJSON_GetNumberValue (cJSON_GetObjectItem (expr, "number"));
|
||||
mach_gen_emit_const_num (s, slot, val);
|
||||
return slot;
|
||||
}
|
||||
if (strcmp (kind, "text") == 0) {
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
int slot = target >= 0 ? target : mach_gen_alloc_slot (s);
|
||||
const char *val = cJSON_GetStringValue (cJSON_GetObjectItem (expr, "value"));
|
||||
mach_gen_emit_const_str (s, slot, val ? val : "");
|
||||
return slot;
|
||||
}
|
||||
if (strcmp (kind, "true") == 0) {
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
int slot = target >= 0 ? target : mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_const_bool (s, slot, 1);
|
||||
return slot;
|
||||
}
|
||||
if (strcmp (kind, "false") == 0) {
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
int slot = target >= 0 ? target : mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_const_bool (s, slot, 0);
|
||||
return slot;
|
||||
}
|
||||
if (strcmp (kind, "null") == 0) {
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
int slot = target >= 0 ? target : mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_const_null (s, slot);
|
||||
return slot;
|
||||
}
|
||||
@@ -33063,7 +33102,9 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
mach_gen_emit_3 (s, "get", dest, parent_slot, level);
|
||||
return dest;
|
||||
}
|
||||
/* Unbound — emit cap_name */
|
||||
/* Unbound — check intrinsic cache first, then emit cap_name */
|
||||
int cached = mach_gen_find_intrinsic (s, name);
|
||||
if (cached >= 0) return cached;
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
cJSON *instr = cJSON_CreateArray ();
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateString ("cap_name"));
|
||||
@@ -33077,7 +33118,7 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
if (strcmp (kind, ".") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (expr, "left");
|
||||
const char *prop = cJSON_GetStringValue (cJSON_GetObjectItem (expr, "right"));
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_get_prop (s, slot, obj_slot, prop);
|
||||
return slot;
|
||||
@@ -33087,8 +33128,8 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
if (strcmp (kind, "[") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (expr, "left");
|
||||
cJSON *idx = cJSON_GetObjectItem (expr, "right");
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int idx_slot = mach_gen_expr (s, idx);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
int idx_slot = mach_gen_expr (s, idx, -1);
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_get_elem (s, slot, obj_slot, idx_slot);
|
||||
return slot;
|
||||
@@ -33101,7 +33142,7 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
cJSON *arg_slots = cJSON_CreateArray ();
|
||||
cJSON *arg;
|
||||
cJSON_ArrayForEach (arg, args_list) {
|
||||
int arg_slot = mach_gen_expr (s, arg);
|
||||
int arg_slot = mach_gen_expr (s, arg, -1);
|
||||
cJSON_AddItemToArray (arg_slots, cJSON_CreateNumber (arg_slot));
|
||||
}
|
||||
const char *callee_kind = cJSON_GetStringValue (cJSON_GetObjectItem (callee, "kind"));
|
||||
@@ -33109,10 +33150,10 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
if (strcmp (callee_kind, ".") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (callee, "left");
|
||||
const char *prop = cJSON_GetStringValue (cJSON_GetObjectItem (callee, "right"));
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
mach_gen_emit_call_method (s, dest, obj_slot, prop, arg_slots);
|
||||
} else {
|
||||
int func_slot = mach_gen_expr (s, callee);
|
||||
int func_slot = mach_gen_expr (s, callee, -1);
|
||||
mach_gen_emit_call (s, dest, func_slot, arg_slots);
|
||||
}
|
||||
cJSON_Delete (arg_slots);
|
||||
@@ -33122,28 +33163,28 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
/* Unary operators */
|
||||
if (strcmp (kind, "!") == 0) {
|
||||
cJSON *operand = cJSON_GetObjectItem (expr, "expression");
|
||||
int operand_slot = mach_gen_expr (s, operand);
|
||||
int operand_slot = mach_gen_expr (s, operand, -1);
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_2 (s, "not", slot, operand_slot);
|
||||
return slot;
|
||||
}
|
||||
if (strcmp (kind, "~") == 0) {
|
||||
cJSON *operand = cJSON_GetObjectItem (expr, "expression");
|
||||
int operand_slot = mach_gen_expr (s, operand);
|
||||
int operand_slot = mach_gen_expr (s, operand, -1);
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_2 (s, "bitnot", slot, operand_slot);
|
||||
return slot;
|
||||
}
|
||||
if (strcmp (kind, "-unary") == 0) {
|
||||
cJSON *operand = cJSON_GetObjectItem (expr, "expression");
|
||||
int operand_slot = mach_gen_expr (s, operand);
|
||||
int operand_slot = mach_gen_expr (s, operand, -1);
|
||||
int slot = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_2 (s, "neg", slot, operand_slot);
|
||||
return slot;
|
||||
}
|
||||
if (strcmp (kind, "+unary") == 0) {
|
||||
cJSON *operand = cJSON_GetObjectItem (expr, "expression");
|
||||
return mach_gen_expr (s, operand);
|
||||
return mach_gen_expr (s, operand, -1);
|
||||
}
|
||||
|
||||
/* Increment/Decrement */
|
||||
@@ -33191,7 +33232,7 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
} else if (strcmp (operand_kind, ".") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (operand, "left");
|
||||
const char *prop = cJSON_GetStringValue (cJSON_GetObjectItem (operand, "right"));
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
int old_slot = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_get_prop (s, old_slot, obj_slot, prop);
|
||||
int new_slot = mach_gen_alloc_slot (s);
|
||||
@@ -33201,8 +33242,8 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
} else if (strcmp (operand_kind, "[") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (operand, "left");
|
||||
cJSON *idx_expr = cJSON_GetObjectItem (operand, "right");
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int idx_slot = mach_gen_expr (s, idx_expr);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
int idx_slot = mach_gen_expr (s, idx_expr, -1);
|
||||
int old_slot = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_get_elem (s, old_slot, obj_slot, idx_slot);
|
||||
int new_slot = mach_gen_alloc_slot (s);
|
||||
@@ -33220,7 +33261,7 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
if (strcmp (operand_kind, ".") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (operand, "left");
|
||||
const char *prop = cJSON_GetStringValue (cJSON_GetObjectItem (operand, "right"));
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
cJSON *instr = cJSON_CreateArray ();
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateString ("delete_prop"));
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateNumber (slot));
|
||||
@@ -33230,8 +33271,8 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
} else if (strcmp (operand_kind, "[") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItem (operand, "left");
|
||||
cJSON *idx = cJSON_GetObjectItem (operand, "right");
|
||||
int obj_slot = mach_gen_expr (s, obj);
|
||||
int idx_slot = mach_gen_expr (s, idx);
|
||||
int obj_slot = mach_gen_expr (s, obj, -1);
|
||||
int idx_slot = mach_gen_expr (s, idx, -1);
|
||||
mach_gen_emit_3 (s, "delete_idx", slot, obj_slot, idx_slot);
|
||||
} else {
|
||||
mach_gen_emit_const_bool (s, slot, 1);
|
||||
@@ -33246,14 +33287,14 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
cJSON *else_expr = cJSON_GetObjectItem (expr, "else");
|
||||
char *else_label = mach_gen_label (s, "tern_else");
|
||||
char *end_label = mach_gen_label (s, "tern_end");
|
||||
int cond_slot = mach_gen_expr (s, cond);
|
||||
int cond_slot = mach_gen_expr (s, cond, -1);
|
||||
mach_gen_emit_jump_cond (s, "jump_false", cond_slot, else_label);
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
int then_slot = mach_gen_expr (s, then_expr);
|
||||
int then_slot = mach_gen_expr (s, then_expr, -1);
|
||||
mach_gen_emit_2 (s, "move", dest, then_slot);
|
||||
mach_gen_emit_jump (s, end_label);
|
||||
mach_gen_emit_label (s, else_label);
|
||||
int else_slot = mach_gen_expr (s, else_expr);
|
||||
int else_slot = mach_gen_expr (s, else_expr, -1);
|
||||
mach_gen_emit_2 (s, "move", dest, else_slot);
|
||||
mach_gen_emit_label (s, end_label);
|
||||
sys_free (else_label);
|
||||
@@ -33268,7 +33309,7 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
cJSON *elem_slots = cJSON_CreateArray ();
|
||||
cJSON *elem;
|
||||
cJSON_ArrayForEach (elem, list) {
|
||||
int slot = mach_gen_expr (s, elem);
|
||||
int slot = mach_gen_expr (s, elem, -1);
|
||||
cJSON_AddItemToArray (elem_slots, cJSON_CreateNumber (slot));
|
||||
}
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
@@ -33298,7 +33339,7 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
cJSON_ArrayForEach (pair, list) {
|
||||
cJSON *key = cJSON_GetObjectItem (pair, "left");
|
||||
cJSON *val = cJSON_GetObjectItem (pair, "right");
|
||||
int val_slot = mach_gen_expr (s, val);
|
||||
int val_slot = mach_gen_expr (s, val, -1);
|
||||
const char *key_kind = cJSON_GetStringValue (cJSON_GetObjectItem (key, "kind"));
|
||||
if (key_kind && strcmp (key_kind, "name") == 0) {
|
||||
const char *name = cJSON_GetStringValue (cJSON_GetObjectItem (key, "name"));
|
||||
@@ -33307,7 +33348,7 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) {
|
||||
const char *name = cJSON_GetStringValue (cJSON_GetObjectItem (key, "value"));
|
||||
mach_gen_emit_set_prop (s, dest, name ? name : "", val_slot);
|
||||
} else {
|
||||
int key_slot = mach_gen_expr (s, key);
|
||||
int key_slot = mach_gen_expr (s, key, -1);
|
||||
mach_gen_emit_set_elem (s, dest, key_slot, val_slot);
|
||||
}
|
||||
}
|
||||
@@ -33357,8 +33398,8 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
const char *name = cJSON_GetStringValue (cJSON_GetObjectItem (left, "name"));
|
||||
int local_slot = mach_gen_find_var (s, name);
|
||||
if (right) {
|
||||
int val_slot = mach_gen_expr (s, right);
|
||||
if (local_slot >= 0)
|
||||
int val_slot = mach_gen_expr (s, right, local_slot);
|
||||
if (local_slot >= 0 && val_slot != local_slot)
|
||||
mach_gen_emit_2 (s, "move", local_slot, val_slot);
|
||||
} else if (local_slot >= 0) {
|
||||
mach_gen_emit_const_null (s, local_slot);
|
||||
@@ -33379,7 +33420,7 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
cJSON *else_stmts = cJSON_GetObjectItem (stmt, "else");
|
||||
char *else_label = mach_gen_label (s, "if_else");
|
||||
char *end_label = mach_gen_label (s, "if_end");
|
||||
int cond_slot = mach_gen_expr (s, cond);
|
||||
int cond_slot = mach_gen_expr (s, cond, -1);
|
||||
mach_gen_emit_jump_cond (s, "jump_false", cond_slot, else_label);
|
||||
cJSON *child;
|
||||
cJSON_ArrayForEach (child, then_stmts) { mach_gen_statement (s, child); }
|
||||
@@ -33404,7 +33445,7 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
s->loop_break = end_label;
|
||||
s->loop_continue = start_label;
|
||||
mach_gen_emit_label (s, start_label);
|
||||
int cond_slot = mach_gen_expr (s, cond);
|
||||
int cond_slot = mach_gen_expr (s, cond, -1);
|
||||
mach_gen_emit_jump_cond (s, "jump_false", cond_slot, end_label);
|
||||
cJSON *child;
|
||||
cJSON_ArrayForEach (child, stmts) { mach_gen_statement (s, child); }
|
||||
@@ -33431,7 +33472,7 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
cJSON *child;
|
||||
cJSON_ArrayForEach (child, stmts) { mach_gen_statement (s, child); }
|
||||
mach_gen_emit_label (s, cond_label);
|
||||
int cond_slot = mach_gen_expr (s, cond);
|
||||
int cond_slot = mach_gen_expr (s, cond, -1);
|
||||
mach_gen_emit_jump_cond (s, "jump_true", cond_slot, start_label);
|
||||
mach_gen_emit_label (s, end_label);
|
||||
s->loop_break = old_break;
|
||||
@@ -33459,17 +33500,17 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
if (init_kind && (strcmp (init_kind, "var") == 0 || strcmp (init_kind, "def") == 0))
|
||||
mach_gen_statement (s, init);
|
||||
else
|
||||
mach_gen_expr (s, init);
|
||||
mach_gen_expr (s, init, -1);
|
||||
}
|
||||
mach_gen_emit_label (s, start_label);
|
||||
if (test) {
|
||||
int test_slot = mach_gen_expr (s, test);
|
||||
int test_slot = mach_gen_expr (s, test, -1);
|
||||
mach_gen_emit_jump_cond (s, "jump_false", test_slot, end_label);
|
||||
}
|
||||
cJSON *child;
|
||||
cJSON_ArrayForEach (child, stmts) { mach_gen_statement (s, child); }
|
||||
mach_gen_emit_label (s, update_label);
|
||||
if (update) mach_gen_expr (s, update);
|
||||
if (update) mach_gen_expr (s, update, -1);
|
||||
mach_gen_emit_jump (s, start_label);
|
||||
mach_gen_emit_label (s, end_label);
|
||||
s->loop_break = old_break;
|
||||
@@ -33483,7 +33524,7 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
if (strcmp (kind, "return") == 0) {
|
||||
cJSON *expr = cJSON_GetObjectItem (stmt, "expression");
|
||||
if (expr) {
|
||||
int slot = mach_gen_expr (s, expr);
|
||||
int slot = mach_gen_expr (s, expr, -1);
|
||||
mach_gen_emit_1 (s, "return", slot);
|
||||
} else {
|
||||
mach_gen_emit_0 (s, "return_undef");
|
||||
@@ -33501,17 +33542,17 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
cJSON *arg_slots = cJSON_CreateArray ();
|
||||
cJSON *arg;
|
||||
cJSON_ArrayForEach (arg, args_list) {
|
||||
int arg_slot = mach_gen_expr (s, arg);
|
||||
int arg_slot = mach_gen_expr (s, arg, -1);
|
||||
cJSON_AddItemToArray (arg_slots, cJSON_CreateNumber (arg_slot));
|
||||
}
|
||||
const char *callee_kind = cJSON_GetStringValue (cJSON_GetObjectItem (callee, "kind"));
|
||||
if (callee_kind && strcmp (callee_kind, ".") == 0) {
|
||||
cJSON *obj_node = cJSON_GetObjectItem (callee, "left");
|
||||
const char *prop = cJSON_GetStringValue (cJSON_GetObjectItem (callee, "right"));
|
||||
int obj_slot = mach_gen_expr (s, obj_node);
|
||||
int obj_slot = mach_gen_expr (s, obj_node, -1);
|
||||
mach_gen_emit_go_call_method (s, obj_slot, prop, arg_slots);
|
||||
} else {
|
||||
int func_slot = mach_gen_expr (s, callee);
|
||||
int func_slot = mach_gen_expr (s, callee, -1);
|
||||
mach_gen_emit_go_call (s, func_slot, arg_slots);
|
||||
}
|
||||
cJSON_Delete (arg_slots);
|
||||
@@ -33520,7 +33561,7 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
|
||||
if (strcmp (kind, "throw") == 0) {
|
||||
cJSON *expr = cJSON_GetObjectItem (stmt, "expression");
|
||||
int slot = mach_gen_expr (s, expr);
|
||||
int slot = mach_gen_expr (s, expr, -1);
|
||||
mach_gen_emit_1 (s, "throw", slot);
|
||||
return;
|
||||
}
|
||||
@@ -33540,7 +33581,7 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
if (strcmp (kind, "switch") == 0) {
|
||||
cJSON *expr = cJSON_GetObjectItem (stmt, "expression");
|
||||
cJSON *cases = cJSON_GetObjectItem (stmt, "cases");
|
||||
int switch_val = mach_gen_expr (s, expr);
|
||||
int switch_val = mach_gen_expr (s, expr, -1);
|
||||
char *end_label = mach_gen_label (s, "switch_end");
|
||||
char *default_label = NULL;
|
||||
const char *old_break = s->loop_break;
|
||||
@@ -33553,7 +33594,7 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
} else {
|
||||
char *case_label = mach_gen_label (s, "switch_case");
|
||||
cJSON *case_expr = cJSON_GetObjectItem (case_node, "expression");
|
||||
int case_val = mach_gen_expr (s, case_expr);
|
||||
int case_val = mach_gen_expr (s, case_expr, -1);
|
||||
int cmp_slot = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_3 (s, "eq", cmp_slot, switch_val, case_val);
|
||||
mach_gen_emit_jump_cond (s, "jump_true", cmp_slot, case_label);
|
||||
@@ -33637,11 +33678,11 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
||||
|
||||
if (strcmp (kind, "call") == 0) {
|
||||
cJSON *expr = cJSON_GetObjectItem (stmt, "expression");
|
||||
mach_gen_expr (s, expr);
|
||||
mach_gen_expr (s, expr, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
mach_gen_expr (s, stmt);
|
||||
mach_gen_expr (s, stmt, -1);
|
||||
}
|
||||
|
||||
static cJSON *mach_gen_function (MachGenState *parent, cJSON *func_node) {
|
||||
@@ -33695,12 +33736,41 @@ static cJSON *mach_gen_function (MachGenState *parent, cJSON *func_node) {
|
||||
|
||||
cJSON_AddNumberToObject (result, "nr_args", s.nr_args);
|
||||
|
||||
/* Use nr_slots from AST to pre-allocate var capacity */
|
||||
cJSON *ns = cJSON_GetObjectItem (func_node, "nr_slots");
|
||||
int ast_nr_slots = ns ? (int)cJSON_GetNumberValue (ns) : 0;
|
||||
if (ast_nr_slots > 0) {
|
||||
s.var_capacity = ast_nr_slots;
|
||||
s.vars = sys_malloc (s.var_capacity * sizeof(MachVarInfo));
|
||||
}
|
||||
|
||||
/* Scan scope record for variable declarations */
|
||||
mach_gen_scan_scope (&s);
|
||||
|
||||
s.next_temp_slot = 1 + s.nr_args + s.nr_local_slots;
|
||||
if (s.next_temp_slot > s.max_slot) s.max_slot = s.next_temp_slot;
|
||||
|
||||
/* Pre-load intrinsics (global names) */
|
||||
mach_gen_load_intrinsics (&s, cJSON_GetObjectItem (func_node, "intrinsics"));
|
||||
|
||||
/* Compile hoisted function declarations from func_node["functions"] */
|
||||
cJSON *hoisted = cJSON_GetObjectItem (func_node, "functions");
|
||||
if (hoisted) {
|
||||
cJSON *fn;
|
||||
cJSON_ArrayForEach (fn, hoisted) {
|
||||
const char *fname = cJSON_GetStringValue (cJSON_GetObjectItem (fn, "name"));
|
||||
if (fname) {
|
||||
int func_id = s.func_counter++;
|
||||
cJSON *compiled = mach_gen_function (&s, fn);
|
||||
cJSON_AddItemToArray (s.functions, compiled);
|
||||
int local_slot = mach_gen_find_var (&s, fname);
|
||||
int dest = mach_gen_alloc_slot (&s);
|
||||
mach_gen_emit_2 (&s, "mkfunc", dest, func_id);
|
||||
if (local_slot >= 0) mach_gen_emit_2 (&s, "move", local_slot, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compile body */
|
||||
cJSON *stmts = cJSON_GetObjectItem (func_node, "statements");
|
||||
if (!stmts) {
|
||||
@@ -33759,12 +33829,41 @@ static cJSON *mach_gen_program (MachGenState *s, cJSON *ast) {
|
||||
s->next_temp_slot = 1;
|
||||
s->max_slot = 1;
|
||||
|
||||
/* Use nr_slots from AST to pre-allocate var capacity */
|
||||
cJSON *ns = cJSON_GetObjectItem (ast, "nr_slots");
|
||||
int ast_nr_slots = ns ? (int)cJSON_GetNumberValue (ns) : 0;
|
||||
if (ast_nr_slots > 0) {
|
||||
s->var_capacity = ast_nr_slots;
|
||||
s->vars = sys_malloc (s->var_capacity * sizeof(MachVarInfo));
|
||||
}
|
||||
|
||||
/* Scan scope record for variable declarations */
|
||||
mach_gen_scan_scope (s);
|
||||
|
||||
s->next_temp_slot = 1 + s->nr_local_slots;
|
||||
if (s->next_temp_slot > s->max_slot) s->max_slot = s->next_temp_slot;
|
||||
|
||||
/* Pre-load intrinsics (global names) */
|
||||
mach_gen_load_intrinsics (s, cJSON_GetObjectItem (ast, "intrinsics"));
|
||||
|
||||
/* Compile hoisted function declarations from ast["functions"] */
|
||||
cJSON *hoisted = cJSON_GetObjectItem (ast, "functions");
|
||||
if (hoisted) {
|
||||
cJSON *fn;
|
||||
cJSON_ArrayForEach (fn, hoisted) {
|
||||
const char *name = cJSON_GetStringValue (cJSON_GetObjectItem (fn, "name"));
|
||||
if (name) {
|
||||
int func_id = s->func_counter++;
|
||||
cJSON *compiled = mach_gen_function (s, fn);
|
||||
cJSON_AddItemToArray (s->functions, compiled);
|
||||
int local_slot = mach_gen_find_var (s, name);
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_2 (s, "mkfunc", dest, func_id);
|
||||
if (local_slot >= 0) mach_gen_emit_2 (s, "move", local_slot, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate main code */
|
||||
cJSON *statements = cJSON_GetObjectItem (ast, "statements");
|
||||
int last_expr_slot = -1;
|
||||
@@ -33774,7 +33873,7 @@ static cJSON *mach_gen_program (MachGenState *s, cJSON *ast) {
|
||||
if (kind) {
|
||||
if (strcmp (kind, "call") == 0) {
|
||||
cJSON *expr = cJSON_GetObjectItem (stmt, "expression");
|
||||
last_expr_slot = mach_gen_expr (s, expr);
|
||||
last_expr_slot = mach_gen_expr (s, expr, -1);
|
||||
} else if (strcmp (kind, "return") == 0 || strcmp (kind, "throw") == 0 ||
|
||||
strcmp (kind, "break") == 0 || strcmp (kind, "continue") == 0) {
|
||||
mach_gen_statement (s, stmt);
|
||||
@@ -33787,7 +33886,7 @@ static cJSON *mach_gen_program (MachGenState *s, cJSON *ast) {
|
||||
mach_gen_statement (s, stmt);
|
||||
last_expr_slot = -1;
|
||||
} else {
|
||||
last_expr_slot = mach_gen_expr (s, stmt);
|
||||
last_expr_slot = mach_gen_expr (s, stmt, -1);
|
||||
}
|
||||
} else {
|
||||
mach_gen_statement (s, stmt);
|
||||
|
||||
Reference in New Issue
Block a user