From af2d296f40ad74d6bd842306e36d1d62aa060051 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Fri, 6 Feb 2026 12:45:25 -0600 Subject: [PATCH] use new parser info --- source/quickjs.c | 237 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 168 insertions(+), 69 deletions(-) diff --git a/source/quickjs.c b/source/quickjs.c index 5b433fb7..5a6dedd4 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -30727,7 +30727,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; /* ---- Compiler state ---- */ @@ -30871,6 +30872,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 */ @@ -32466,13 +32468,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) { @@ -32493,6 +32529,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 */ @@ -32545,6 +32582,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)); } } } @@ -32745,11 +32784,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); @@ -32758,11 +32797,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); @@ -32771,19 +32810,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); @@ -32815,7 +32854,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) { @@ -32837,10 +32876,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); @@ -32848,11 +32887,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); @@ -32879,7 +32918,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) { @@ -32900,13 +32939,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; @@ -32914,36 +32953,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; } @@ -32967,7 +33006,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")); @@ -32981,7 +33022,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; @@ -32991,8 +33032,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; @@ -33005,7 +33046,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")); @@ -33013,10 +33054,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); @@ -33026,28 +33067,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 */ @@ -33095,7 +33136,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); @@ -33105,8 +33146,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); @@ -33124,7 +33165,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)); @@ -33134,8 +33175,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); @@ -33150,14 +33191,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); @@ -33172,7 +33213,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); @@ -33202,7 +33243,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")); @@ -33211,7 +33252,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); } } @@ -33261,8 +33302,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); @@ -33283,7 +33324,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); } @@ -33308,7 +33349,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); } @@ -33335,7 +33376,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; @@ -33363,17 +33404,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; @@ -33387,7 +33428,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"); @@ -33405,17 +33446,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); @@ -33424,7 +33465,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; } @@ -33444,7 +33485,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; @@ -33457,7 +33498,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); @@ -33541,11 +33582,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) { @@ -33600,12 +33641,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) { @@ -33664,12 +33734,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; @@ -33679,7 +33778,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); @@ -33692,7 +33791,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);