/* cvm_vm.c — V8 Ignition 风格寄存器 VM (v2)
 * 32位指令: op(8)|A(8)|B(8)|C(8)
 * 支持:多函数、调用栈、内置函数、用户函数调用/返回
 */
#define _POSIX_C_SOURCE 200809L
#include "cvm_core.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

/* ---- 指令集 ---- */
enum {
    R_NOP, R_CONST, R_INT, R_TRUE, R_FALSE, R_NIL,
    R_LOAD, R_STORE,
    R_MOV, R_ADD, R_SUB, R_MUL, R_DIV, R_MOD,
    R_EQ, R_LT, R_LE, R_INV,
    R_JMP, R_JT, R_JF,
    R_CALL, R_RET, R_HALT,
    R_LOAD_FUNC,   /* reg=name_idx, 把函数名字符串加载到寄存器 */
    R_CALL_IDX,    /* 直接函数索引调用: op|result|first_arg|argc, 跳过运行时名字查找 */
    R_ADD_IMM,     /* 即数加: op|dst|src|unused, imm32; 学习 V8 AddSmi */
    R_SUB_IMM,     /* 即数减: op|dst|src|unused, imm32 */
    R_LT_IMM,      /* 即数小于: op|dst|src|unused, imm32; 学习 V8 TestLessThan */
    R_LE_IMM       /* 即数小于等于 */
};

/* ---- 编译器 ---- */
typedef struct {
    int32_t *code; int clen, ccap;
    Value *pool; int plen, pcap;
    char **names; int nlen, ncap;
    int nregs, nvars, nargs, max_args;
    int unsupported;
    /* 变量→寄存器映射 */
    struct { const char *name; int reg; } vars[64]; int nvar;
    /* 函数名→索引映射 (编译期解析, 支持直接调用) */
    struct { const char *name; int index; } funcs[64]; int nfunc;
} Rc;

static void re(int32_t v, Rc *c) {
    if (c->clen >= c->ccap) { c->ccap = c->ccap < 256 ? 256 : c->ccap * 2; c->code = realloc(c->code, c->ccap * 4); }
    c->code[c->clen++] = v;
}
#define E(v) re(v, c)

static int addc(Value v, Rc *c) {
    for (int i = 0; i < c->plen; i++) if (value_equal(c->pool[i], v, 0)) return i;
    if (c->plen >= c->pcap) { c->pcap = c->pcap < 64 ? 64 : c->pcap * 2; c->pool = realloc(c->pool, c->pcap * sizeof(Value)); }
    c->pool[c->plen] = v; return c->plen++;
}
static int addn(const char *s, Rc *c) {
    for (int i = 0; i < c->nlen; i++) if (!strcmp(c->names[i], s)) return i;
    if (c->nlen >= c->ncap) { c->ncap = c->ncap < 64 ? 64 : c->ncap * 2; c->names = realloc(c->names, c->ncap * sizeof(char *)); }
    c->names[c->nlen] = strdup(s); return c->nlen++;
}
static int vfind(const char *nm, Rc *c) {
    for (int i = 0; i < c->nvar; i++) if (!strcmp(c->vars[i].name, nm)) return c->vars[i].reg;
    return -1;
}
static int vreg(const char *nm, Rc *c) {
    int r = vfind(nm, c);
    if (r >= 0) return r;
    r = c->nregs++;
    if (c->nvar < 64) { c->vars[c->nvar].name = nm; c->vars[c->nvar].reg = r; c->nvar++; }
    return r;
}
static int vname(const char *nm, Rc *c) { return addn(nm, c); }

static int func_index(const char *nm, Rc *c) {
    for (int i = 0; i < c->nfunc; i++) if (!strcmp(c->funcs[i].name, nm)) return c->funcs[i].index;
    return -1;
}

static int comp_expr(Expr*, Rc*);
static void comp_stmt(Stmt*, Rc*);

static int comp_expr(Expr *e, Rc *c) {
    if (!e) { int r = c->nregs++; E(R_NIL | (r << 8)); return r; }
    switch (e->kind) {
    case EXPR_NIL: { int r = c->nregs++; E(R_NIL | (r << 8)); return r; }
    case EXPR_BOOL: { int r = c->nregs++; E(e->u.boolean ? R_TRUE | (r << 8) : R_FALSE | (r << 8)); return r; }
    case EXPR_NUM: {
        int r = c->nregs++;
        if (e->u.numlit.is_int) { int ci = addc(val_int(e->u.numlit.ival), c); E(R_INT | (r << 8)); E(ci); }
        else { int ci = addc(val_num(e->u.numlit.fval), c); E(R_CONST | (r << 8)); E(ci); }
        return r;
    }
    case EXPR_STR: { int r = c->nregs++; int ci = addc(val_str(e->u.str), c); E(R_CONST | (r << 8)); E(ci); return r; }
    case EXPR_VAR: {
        int r = vfind(e->u.name, c);
        if (r < 0) { c->unsupported = 1; r = c->nregs++; E(R_NIL | (r << 8)); }
        return r;
    }
    case EXPR_UNARY: {
        int a = comp_expr(e->u.unary.inner, c), r = c->nregs++;
        if (e->u.unary.op == TK_MINUS) { int z = c->nregs++; E(R_INT | (z << 8)); E(addc(val_int(0), c)); E(R_SUB | (r << 8) | (z << 16) | (a << 24)); }
        else { E(R_INV | (r << 8) | (a << 16)); }
        return r;
    }
    case EXPR_BINARY: {
        int a = comp_expr(e->u.binary.left, c);
        int op = e->u.binary.op;
        /* V8 风格: 右操作数为整数常量时使用即数指令, 省寄存器和常量池 */
        if (e->u.binary.right && e->u.binary.right->kind == EXPR_NUM && e->u.binary.right->u.numlit.is_int &&
            (op == TK_PLUS || op == TK_MINUS || op == TK_LT || op == TK_LE)) {
            int r = c->nregs++;
            int32_t imm = (int32_t)e->u.binary.right->u.numlit.ival;
            if (op == TK_PLUS) E(R_ADD_IMM | (r << 8) | (a << 16));
            else if (op == TK_MINUS) E(R_SUB_IMM | (r << 8) | (a << 16));
            else if (op == TK_LT) E(R_LT_IMM | (r << 8) | (a << 16));
            else E(R_LE_IMM | (r << 8) | (a << 16));
            E(imm);
            return r;
        }
        int b = comp_expr(e->u.binary.right, c), r = c->nregs++;
        if (op == TK_PLUS) E(R_ADD | (r << 8) | (a << 16) | (b << 24));
        else if (op == TK_MINUS) E(R_SUB | (r << 8) | (a << 16) | (b << 24));
        else if (op == TK_STAR) E(R_MUL | (r << 8) | (a << 16) | (b << 24));
        else if (op == TK_SLASH) E(R_DIV | (r << 8) | (a << 16) | (b << 24));
        else if (op == TK_PERCENT) E(R_MOD | (r << 8) | (a << 16) | (b << 24));
        else if (op == TK_EQEQ) E(R_EQ | (r << 8) | (a << 16) | (b << 24));
        else if (op == TK_LT) E(R_LT | (r << 8) | (a << 16) | (b << 24));
        else if (op == TK_LE) E(R_LE | (r << 8) | (a << 16) | (b << 24));
        else if (op == TK_GT) { E(R_LE | (r << 8) | (b << 16) | (a << 24)); E(R_INV | (r << 8) | (r << 16)); }
        else if (op == TK_GE) { E(R_LT | (r << 8) | (b << 16) | (a << 24)); E(R_INV | (r << 8) | (r << 16)); }
        else if (op == TK_NOTEQ) { E(R_EQ | (r << 8) | (a << 16) | (b << 24)); E(R_INV | (r << 8) | (r << 16)); }
        else { E(R_MOV | (r << 8) | (a << 16)); }
        return r;
    }
    case EXPR_ASSIGN: {
        int v = comp_expr(e->u.assign.value, c);
        int t = vreg(e->u.assign.name, c);
        E(R_MOV | (t << 8) | (v << 16));
        return v;
    }
    case EXPR_CALL: {
        /* 参数依次求值,占用连续寄存器 */
        int argc = e->u.call.argc;
        int first_arg = c->nregs;
        if (argc > 0) {
            for (int i = 0; i < argc; i++) {
                /* 强制从目标参数槽开始分配,防止变量参数不增量 nregs 导致后续常量覆盖 */
                c->nregs = first_arg + i;
                int rr = comp_expr(e->u.call.args[i], c);
                if (rr != first_arg + i) { int dst = first_arg + i; E(R_MOV | (dst << 8) | (rr << 16)); }
            }
            c->nregs = first_arg + argc;
        }
        /* FFI 相关调用在字节码 VM 中不支持, 回退到树遍历解释器 */
        if (e->u.call.callee->kind == EXPR_VAR) {
            const char *callee_name = e->u.call.callee->u.name;
            if (!strcmp(callee_name, "ffi_decl") || !strcmp(callee_name, "import") ||
                !strcmp(callee_name, "ffi_enable")) {
                c->unsupported = 1;
            }
        }
        /* 编译期已知函数? 用直接索引调用 (V8 风格: 避免运行时名字查找) */
        if (e->u.call.callee->kind == EXPR_VAR) {
            const char *callee_name = e->u.call.callee->u.name;
            int fidx = func_index(callee_name, c);
            if (fidx >= 0) {
                int result_reg = c->nregs++;
                E(R_CALL_IDX | (result_reg << 8) | (first_arg << 16) | (argc << 24));
                E(fidx);
                if (argc + 1 > c->max_args) c->max_args = argc + 1;
                return result_reg;
            }
        }
        /* 回退: 运行时名字查找调用 */
        int callee_reg = c->nregs++;
        if (e->u.call.callee->kind == EXPR_VAR) {
            int ni = vname(e->u.call.callee->u.name, c);
            E(R_LOAD_FUNC | (callee_reg << 8) | (ni << 16));
        } else {
            c->unsupported = 1; int r = c->nregs++; E(R_NIL | (r << 8)); return r;
        }
        int result_reg = c->nregs++;
        E(R_CALL | (result_reg << 8) | (callee_reg << 16) | (argc << 24));
        if (argc + 1 > c->max_args) c->max_args = argc + 1;
        return result_reg;
    }
    default: { c->unsupported = 1; int r = c->nregs++; E(R_NIL | (r << 8)); return r; }
    }
}

static void comp_stmt(Stmt *s, Rc *c) {
    if (!s) return;
    switch (s->kind) {
    case STMT_EXPR: { comp_expr(s->u.expr, c); break; }
    case STMT_LET: {
        if (s->u.let.init) { int r = comp_expr(s->u.let.init, c); int t = vreg(s->u.let.name, c); E(R_MOV | (t << 8) | (r << 16)); }
        else { vreg(s->u.let.name, c); }
        break;
    }
    case STMT_ASSIGN: {
        int v = comp_expr(s->u.assign.value, c);
        int t = vreg(s->u.assign.name, c);
        E(R_MOV | (t << 8) | (v << 16));
        break;
    }
    case STMT_RETURN: {
        int r = 0; if (s->u.returns.value) r = comp_expr(s->u.returns.value, c);
        E(R_RET | (r << 8)); break;
    }
    case STMT_BLOCK: for (int i = 0; i < s->u.block.count; i++) comp_stmt(s->u.block.stmts[i], c); break;
    case STMT_IF: {
        int cond = comp_expr(s->u.ifs.cond, c);
        E(R_JF | (cond << 8)); int jf_pc = c->clen; E(0);
        comp_stmt(s->u.ifs.then_b, c);
        if (s->u.ifs.else_b) {
            E(R_JMP); int jmp_pc = c->clen; E(0);
            c->code[jf_pc] = (c->clen - jf_pc - 1);
            comp_stmt(s->u.ifs.else_b, c);
            c->code[jmp_pc] = (c->clen - jmp_pc - 1);
        } else {
            c->code[jf_pc] = (c->clen - jf_pc - 1);
        }
        break;
    }
    case STMT_WHILE: {
        int loop_pc = c->clen;
        int cond = comp_expr(s->u.whiles.cond, c);
        E(R_JF | (cond << 8)); int exit_pc = c->clen; E(0);
        comp_stmt(s->u.whiles.body, c);
        E(R_JMP); int jmp_pc = c->clen; E(0);
        c->code[jmp_pc] = loop_pc - (c->clen);
        c->code[exit_pc] = c->clen - exit_pc - 1;
        break;
    }
    default: c->unsupported = 1; break;
    }
}

static ByteFunc finish_rc(Rc *c, const char *name, int nargs) {
    ByteFunc bf; memset(&bf, 0, sizeof(bf));
    bf.code = c->code; bf.clen = c->clen;
    bf.consts = c->pool; bf.nconsts = c->plen;
    bf.names = c->names; bf.nnames = c->nlen;
    bf.nlocals = c->nregs; bf.nargs = nargs; bf.max_args = c->max_args;
    bf.unsupported = c->unsupported;
    bf.name = name ? strdup(name) : strdup("<anon>");
    return bf;
}

static void reset_rc(Rc *c) {
    int nfunc = c->nfunc;
    struct { const char *name; int index; } funcs[64];
    memcpy(funcs, c->funcs, sizeof(funcs));
    memset(c, 0, sizeof(*c));
    memcpy(c->funcs, funcs, sizeof(funcs));
    c->nfunc = nfunc;
}

static ByteFunc compile_func(Stmt *fn, Rc *c) {
    reset_rc(c);
    c->nargs = fn->u.func.pcount;
    c->nregs = c->nargs; /* 参数占用 0..nargs-1 */
    for (int i = 0; i < fn->u.func.pcount; i++) {
        if (c->nvar < 64) { c->vars[c->nvar].name = fn->u.func.params[i]; c->vars[c->nvar].reg = i; c->nvar++; }
    }
    comp_stmt(fn->u.func.body, c);
    E(R_RET | (0 << 8)); /* 无显式 return 返回 nil */
    return finish_rc(c, fn->u.func.name, fn->u.func.pcount);
}

ByteFunc *cvm_bc_compile_all(Runtime *rt, Program *prog, int *out_count) {
    (void)rt;
    int func_count = 0;
    for (int i = 0; i < prog->count; i++) if (prog->stmts[i]->kind == STMT_FUNC) func_count++;
    int total = func_count + 1; /* + main */
    ByteFunc *bfs = (ByteFunc *)calloc((size_t)total, sizeof(ByteFunc));
    if (!bfs) return NULL;
    Rc c; memset(&c, 0, sizeof(c));

    /* 预构建函数名->索引映射: main=0, 用户函数=1..n */
    for (int i = 0, idx = 1; i < prog->count; i++) {
        if (prog->stmts[i]->kind == STMT_FUNC) {
            const char *name = prog->stmts[i]->u.func.name;
            if (c.nfunc < 64 && name) {
                c.funcs[c.nfunc].name = name;
                c.funcs[c.nfunc].index = idx++;
                c.nfunc++;
            }
        }
    }

    int idx = 0;
    /* 先编译顶层 main */
    reset_rc(&c);
    for (int i = 0; i < prog->count; i++) {
        if (prog->stmts[i]->kind == STMT_FUNC) continue; /* 跳过函数定义 */
        comp_stmt(prog->stmts[i], &c);
    }
    re(R_HALT, &c);
    bfs[idx++] = finish_rc(&c, "<main>", 0);

    /* 编译函数 */
    for (int i = 0; i < prog->count; i++) {
        if (prog->stmts[i]->kind == STMT_FUNC) {
            bfs[idx++] = compile_func(prog->stmts[i], &c);
        }
    }
    *out_count = idx;
    return bfs;
}

int cvm_bc_supported(Program *prog) {
    Rc c; memset(&c, 0, sizeof(c));
    for (int i = 0; i < prog->count && !c.unsupported; i++) {
        if (prog->stmts[i]->kind == STMT_FUNC) {
            Rc fc; memset(&fc, 0, sizeof(fc));
            fc.nargs = prog->stmts[i]->u.func.pcount;
            fc.nregs = fc.nargs;
            for (int j = 0; j < prog->stmts[i]->u.func.pcount; j++) {
                if (fc.nvar < 64) { fc.vars[fc.nvar].name = prog->stmts[i]->u.func.params[j]; fc.vars[fc.nvar].reg = j; fc.nvar++; }
            }
            comp_stmt(prog->stmts[i]->u.func.body, &fc);
            if (fc.unsupported) c.unsupported = 1;
        } else {
            comp_stmt(prog->stmts[i], &c);
        }
    }
    return !c.unsupported;
}

void cvm_bc_free(ByteFunc *bfs, int n) {
    if (!bfs) return;
    for (int i = 0; i < n; i++) {
        free(bfs[i].code);
        free(bfs[i].consts);
        for (int j = 0; j < bfs[i].nnames; j++) free(bfs[i].names[j]);
        free(bfs[i].names);
        free(bfs[i].name);
    }
    free(bfs);
}

/* ---- VM 执行器 (computed goto + 调用栈) ---- */
#define REGS 256
#define MAX_FRAMES 512

typedef struct {
    ByteFunc *bf;
    int32_t *ip;
    int result_reg;  /* 调用者期望的返回值寄存器 */
    Value regs[REGS];
} CallFrame;

static ByteFunc *find_func(Runtime *rt, const char *name, ByteFunc *bfs, int nbfs) {
    /* 优先用户函数 */
    for (int i = 0; i < nbfs; i++) if (bfs[i].name && !strcmp(bfs[i].name, name)) return &bfs[i];
    /* 内置函数以 VAL_FUNC 形式存在?这里只返回 NULL,由调用处处理 */
    return NULL;
}

int cvm_bc_run(Runtime *rt, ByteFunc *main_bf, ByteFunc *bfs, int nbfs) {
    if (!main_bf || !main_bf->code || main_bf->clen == 0) return -1;
    CallFrame frames[MAX_FRAMES];
    int fp = 0;
    frames[0].bf = main_bf;
    frames[0].ip = main_bf->code;
    memset(frames[0].regs, 0, sizeof(frames[0].regs));

    #define I() (*cf->ip++)
    #define A(v) ((v >> 8) & 0xFF)
    #define B(v) ((v >> 16) & 0xFF)
    #define C(v) ((v >> 24) & 0xFF)

    static const void *dt[] = {
        &&L_NOP, &&L_CONST, &&L_INT, &&L_TRUE, &&L_FALSE, &&L_NIL,
        &&L_LOAD, &&L_STORE,
        &&L_MOV, &&L_ADD, &&L_SUB, &&L_MUL, &&L_DIV, &&L_MOD,
        &&L_EQ, &&L_LT, &&L_LE, &&L_INV,
        &&L_JMP, &&L_JT, &&L_JF,
        &&L_CALL, &&L_RET, &&L_HALT,
        &&L_LOAD_FUNC, &&L_CALL_IDX,
        &&L_ADD_IMM, &&L_SUB_IMM, &&L_LT_IMM, &&L_LE_IMM
    };

    CallFrame *cf = &frames[0];
    uint32_t ins;
    #define DISP { if (cf->ip >= cf->bf->code + cf->bf->clen || rt->has_error) goto L_EXIT; ins = I(); goto *dt[ins & 0xFF]; }
    DISP;

L_NOP: DISP;
L_CONST: { int r = A(ins); int ci = I(); cf->regs[r] = cf->bf->consts[ci]; DISP; }
L_INT:   { int r = A(ins); int ci = I(); cf->regs[r] = cf->bf->consts[ci]; DISP; }
L_TRUE:  { cf->regs[A(ins)] = val_bool(1); DISP; }
L_FALSE: { cf->regs[A(ins)] = val_bool(0); DISP; }
L_NIL:   { cf->regs[A(ins)] = val_nil(); DISP; }
L_LOAD:  { int r = A(ins), ni = (ins >> 16) & 0xFF;
    Value *vp = env_get(rt->global, cf->bf->names[ni]);
    cf->regs[r] = vp ? *vp : val_nil(); DISP; }
L_STORE: { int v = B(ins), ni = (ins >> 24) & 0xFF;
    env_assign(rt->global, cf->bf->names[ni], cf->regs[v], &rt->arena); DISP; }
L_MOV:   { cf->regs[A(ins)] = cf->regs[B(ins)]; DISP; }

L_ADD: L_SUB: L_MUL: L_DIV: L_MOD: L_EQ: L_LT: L_LE:
{ int op = ins & 0xFF, d = A(ins), x = B(ins), y = C(ins);
    Value a = cf->regs[x], b = cf->regs[y];
    if (op == R_EQ) { cf->regs[d] = val_bool(value_equal(a, b, 0)); DISP; }
    if (a.type == VAL_STR && b.type == VAL_STR) {
        int c = strcmp(a.as.str, b.as.str);
        if (op == R_LT) cf->regs[d] = val_bool(c < 0);
        else if (op == R_LE) cf->regs[d] = val_bool(c <= 0);
        else { snprintf(rt->errbuf, sizeof(rt->errbuf), "字符串不支持该运算"); rt->has_error = 1; goto L_EXIT; }
        DISP;
    }
    if (a.type == VAL_INT && b.type == VAL_INT) {
        int64_t ai = a.as.i, bi = b.as.i;
        switch (op) {
        case R_ADD: cf->regs[d] = val_int(ai + bi); break;
        case R_SUB: cf->regs[d] = val_int(ai - bi); break;
        case R_MUL: cf->regs[d] = val_int(ai * bi); break;
        case R_DIV: if (bi == 0) { snprintf(rt->errbuf, sizeof(rt->errbuf), "div0"); rt->has_error = 1; goto L_EXIT; } cf->regs[d] = val_int(ai / bi); break;
        case R_MOD: if (bi == 0) { snprintf(rt->errbuf, sizeof(rt->errbuf), "mod0"); rt->has_error = 1; goto L_EXIT; } cf->regs[d] = val_int(ai % bi); break;
        case R_LT:  cf->regs[d] = val_bool(ai < bi); break;
        case R_LE:  cf->regs[d] = val_bool(ai <= bi); break;
        default: { snprintf(rt->errbuf, sizeof(rt->errbuf), "整数不支持该运算"); rt->has_error = 1; goto L_EXIT; }
        } DISP;
    }
    double da = (a.type == VAL_INT) ? (double)a.as.i : a.as.num;
    double db = (b.type == VAL_INT) ? (double)b.as.i : b.as.num;
    switch (op) {
    case R_ADD: cf->regs[d] = val_num(da + db); break;
    case R_SUB: cf->regs[d] = val_num(da - db); break;
    case R_MUL: cf->regs[d] = val_num(da * db); break;
    case R_DIV: if (db == 0) { snprintf(rt->errbuf, sizeof(rt->errbuf), "div0"); rt->has_error = 1; goto L_EXIT; } cf->regs[d] = val_num(da / db); break;
    case R_MOD: if (db == 0) { snprintf(rt->errbuf, sizeof(rt->errbuf), "mod0"); rt->has_error = 1; goto L_EXIT; } cf->regs[d] = val_num(da - (int64_t)(da / db) * db); break;
    case R_LT:  cf->regs[d] = val_bool(da < db); break;
    case R_LE:  cf->regs[d] = val_bool(da <= db); break;
    default: { snprintf(rt->errbuf, sizeof(rt->errbuf), "数字不支持该运算"); rt->has_error = 1; goto L_EXIT; }
    } DISP;
}

L_ADD_IMM: { int d = A(ins), x = B(ins); int32_t imm = I();
    Value a = cf->regs[x];
    if (a.type == VAL_INT) cf->regs[d] = val_int(a.as.i + (int64_t)imm);
    else cf->regs[d] = val_num(((a.type == VAL_INT) ? (double)a.as.i : a.as.num) + (double)imm);
    DISP; }
L_SUB_IMM: { int d = A(ins), x = B(ins); int32_t imm = I();
    Value a = cf->regs[x];
    if (a.type == VAL_INT) cf->regs[d] = val_int(a.as.i - (int64_t)imm);
    else cf->regs[d] = val_num(((a.type == VAL_INT) ? (double)a.as.i : a.as.num) - (double)imm);
    DISP; }
L_LT_IMM: { int d = A(ins), x = B(ins); int32_t imm = I();
    Value a = cf->regs[x];
    if (a.type == VAL_INT) cf->regs[d] = val_bool(a.as.i < (int64_t)imm);
    else cf->regs[d] = val_bool(((a.type == VAL_INT) ? (double)a.as.i : a.as.num) < (double)imm);
    DISP; }
L_LE_IMM: { int d = A(ins), x = B(ins); int32_t imm = I();
    Value a = cf->regs[x];
    if (a.type == VAL_INT) cf->regs[d] = val_bool(a.as.i <= (int64_t)imm);
    else cf->regs[d] = val_bool(((a.type == VAL_INT) ? (double)a.as.i : a.as.num) <= (double)imm);
    DISP; }

L_INV: { cf->regs[A(ins)] = val_bool(!val_truthy(cf->regs[B(ins)])); DISP; }
L_JMP: { int32_t off = I(); cf->ip += off; DISP; }
L_JT: { int cr = A(ins); int32_t off = I(); if (val_truthy(cf->regs[cr])) cf->ip += off; DISP; }
L_JF: { int cr = A(ins); int32_t off = I(); if (!val_truthy(cf->regs[cr])) cf->ip += off; DISP; }

L_LOAD_FUNC: { cf->regs[A(ins)] = val_str(cf->bf->names[(ins >> 16) & 0xFF]); DISP; }

L_CALL: {
    int result_reg = A(ins); int callee_reg = B(ins); int argc = C(ins);
    Value callee = cf->regs[callee_reg];
    if (callee.type != VAL_STR) { cf->regs[result_reg] = val_nil(); DISP; }
    const char *name = callee.as.str;
    /* 检查是否为用户函数 */
    ByteFunc *target = find_func(rt, name, bfs, nbfs);
    if (target) {
        if (argc != target->nargs) { snprintf(rt->errbuf, sizeof(rt->errbuf), "函数 '%s' 期望 %d 个参数, 收到 %d", name, target->nargs, argc); rt->has_error = 1; goto L_EXIT; }
        if (fp + 1 >= MAX_FRAMES) { snprintf(rt->errbuf, sizeof(rt->errbuf), "递归深度超过上限 (%d)", MAX_FRAMES); rt->has_error = 1; goto L_EXIT; }
        CallFrame *next = &frames[++fp];
        next->bf = target;
        next->ip = target->code;
        next->result_reg = result_reg;
        int to_zero = target->nlocals - argc;
        if (to_zero > 0) memset(next->regs + argc, 0, (size_t)to_zero * sizeof(Value));
        for (int i = 0; i < argc; i++) next->regs[i] = cf->regs[callee_reg - argc + i];
        cf = next;
        DISP;
    }
    /* 内置函数 */
    BuiltinFunc fn = (BuiltinFunc)map_get(&rt->builtins, name);
    if (fn) {
        Value args[8]; for (int i = 0; i < argc && i < 8; i++) args[i] = cf->regs[callee_reg - argc + i];
        cf->regs[result_reg] = fn(rt, argc, args);
        if (rt->has_error) goto L_EXIT;
        DISP;
    }
    cf->regs[result_reg] = val_nil();
    DISP;
}

L_CALL_IDX: {
    int result_reg = A(ins); int first_arg = B(ins); int argc = C(ins);
    int32_t fidx = I();
    if (fidx < 0 || fidx >= nbfs) {
        snprintf(rt->errbuf, sizeof(rt->errbuf), "R_CALL_IDX 函数索引越界: %d", (int)fidx); rt->has_error = 1; goto L_EXIT;
    }
    ByteFunc *target = &bfs[fidx];
    if (argc != target->nargs) {
        snprintf(rt->errbuf, sizeof(rt->errbuf), "函数 '%s' 期望 %d 个参数, 收到 %d", target->name ? target->name : "?", target->nargs, argc); rt->has_error = 1; goto L_EXIT;
    }
    if (fp + 1 >= MAX_FRAMES) { snprintf(rt->errbuf, sizeof(rt->errbuf), "递归深度超过上限 (%d)", MAX_FRAMES); rt->has_error = 1; goto L_EXIT; }
    CallFrame *next = &frames[++fp];
    next->bf = target; next->ip = target->code; next->result_reg = result_reg;
    int to_zero = target->nlocals - argc;
    if (to_zero > 0) memset(next->regs + argc, 0, (size_t)to_zero * sizeof(Value));
    for (int i = 0; i < argc; i++) next->regs[i] = cf->regs[first_arg + i];
    cf = next;
    DISP;
}

L_RET: {
    int r = A(ins);
    Value ret = cf->regs[r];
    if (fp == 0) { /* 顶层 return */ cf->regs[0] = ret; goto L_EXIT; }
    CallFrame *prev = &frames[--fp];
    prev->regs[cf->result_reg] = ret;
    cf = prev;
    DISP;
}

L_HALT:
L_EXIT:
    return 0;
#undef I
#undef A
#undef B
#undef C
}