#include "cvm_core.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <stdint.h>

/* 值系统构造函数已移至 cvm_core.h (static inline) */

int val_truthy(Value v) {
    switch (v.type) {
        case VAL_NUM:  return v.as.num != 0.0;
        case VAL_BOOL: return v.as.boolean;
        case VAL_STR:  return v.as.str && v.as.str[0] != '\0';
        case VAL_NIL:  return 0;
        case VAL_MODULE: return v.as.mod != NULL;
        case VAL_FUNC: return 1;
        case VAL_ARRAY: return arr_len((const Arr *)v.as.arr) > 0;
        case VAL_CLOSURE: return 1;
        case VAL_PTR:    return v.as.ptr != NULL;
        case VAL_INT:    return v.as.i != 0;
    }
    return 0;
}

const char *val_type_name(Value v) {
    switch (v.type) {
        case VAL_NUM:  return "number";
        case VAL_STR:  return "string";
        case VAL_BOOL: return "bool";
        case VAL_NIL:  return "nil";
        case VAL_MODULE: return "module";
        case VAL_FUNC: return "func";
        case VAL_ARRAY:  return "array";
        case VAL_CLOSURE: return "closure";
        case VAL_PTR:    return "ptr";
        case VAL_INT:    return "int";
    }
    return "?";
}

static char *arr_to_str(Arena *a, const Arr *arr, int depth) {
    if (depth > 32) return arena_strdup(a, "[...]");   /* 防御自引用环 */
    char *out = arena_strdup(a, "[");
    size_t len = 1;
    for (int i = 0; i < arr_len(arr); ++i) {
        ArrEntry *e = arr_at(arr, i);
        if (i) {
            char *sep = arena_strdup(a, ", ");
            char *buf = (char *)arena_alloc(a, len + strlen(sep) + 1);
            memcpy(buf, out, len); strcpy(buf + len, sep);
            out = buf; len += strlen(sep);
        }
        char *kb = NULL;
        if (e->is_str) {
            size_t n = strlen(e->skey);
            kb = (char *)arena_alloc(a, n + 3);
            kb[0] = '"'; memcpy(kb + 1, e->skey, n); kb[n + 1] = '"'; kb[n + 2] = '\0';
        } else {
            char tmp[32]; snprintf(tmp, sizeof(tmp), "%lld", (long long)e->ikey);
            kb = arena_strdup(a, tmp);
        }
        char *vs = val_to_str(a, e->value);
        size_t kl = strlen(kb), vl = strlen(vs);
        char *buf = (char *)arena_alloc(a, len + kl + vl + 3);
        memcpy(buf, out, len);
        memcpy(buf + len, kb, kl); buf[len + kl] = ':';
        memcpy(buf + len + kl + 1, vs, vl); buf[len + kl + 1 + vl] = '\0';
        out = buf; len += kl + 1 + vl;
    }
    char *tail = arena_strdup(a, "]");
    char *buf = (char *)arena_alloc(a, len + 2);
    memcpy(buf, out, len); strcpy(buf + len, tail);
    return buf;
}

char *val_to_str(Arena *a, Value v) {
    switch (v.type) {
        case VAL_NUM: {
            char buf[64];
            snprintf(buf, sizeof(buf), "%.12g", v.as.num);
            return arena_strdup(a, buf);
        }
        case VAL_INT: {
            char buf[32];
            snprintf(buf, sizeof(buf), "%lld", (long long)v.as.i);
            return arena_strdup(a, buf);
        }
        case VAL_STR:  return v.as.str ? v.as.str : "";
        case VAL_BOOL: return arena_strdup(a, v.as.boolean ? "true" : "false");
        case VAL_NIL:  return arena_strdup(a, "nil");
        case VAL_MODULE: return arena_strdup(a, "<module>");
        case VAL_FUNC: {
            char buf[128];
            snprintf(buf, sizeof(buf), "<func %s>", v.as.funcname ? v.as.funcname : "?");
            return arena_strdup(a, buf);
        }
        case VAL_ARRAY: return arr_to_str(a, (const Arr *)v.as.arr, 0);
        case VAL_CLOSURE: {
            Closure *cl = (Closure *)v.as.closure;
            if (cl && cl->fn && cl->fn->u.func.name) {
                char buf[128];
                snprintf(buf, sizeof(buf), "<closure %s>", cl->fn->u.func.name);
                return arena_strdup(a, buf);
            }
            return arena_strdup(a, "<closure>");
        }
        case VAL_PTR: {
            char buf[64];
            snprintf(buf, sizeof(buf), "<ptr %p>", v.as.ptr);
            return arena_strdup(a, buf);
        }
    }
    return arena_strdup(a, "?");
}

int value_equal(Value a, Value b, int depth) {
    if (depth > 64) return 1;   /* 环形数组: 保守地视为相等, 避免栈溢出 */
    if (a.type == b.type) {
        switch (a.type) {
            case VAL_NUM:  return a.as.num == b.as.num;
            case VAL_INT:  return a.as.i == b.as.i;
            case VAL_BOOL: return a.as.boolean == b.as.boolean;
            case VAL_NIL:  return 1;
            case VAL_STR:  return strcmp(a.as.str, b.as.str) == 0;
            case VAL_ARRAY: {
                Arr *x = (Arr *)a.as.arr, *y = (Arr *)b.as.arr;
                if (arr_len(x) != arr_len(y)) return 0;
                for (int i = 0; i < arr_len(x); ++i) {
                    ArrEntry *xe = arr_at(x, i);
                    ArrEntry *ye = arr_find(xe->is_str, xe->skey, xe->ikey, y);
                    if (!ye) return 0;
                    if (!value_equal(xe->value, ye->value, depth + 1)) return 0;
                }
                return 1;
            }
            default:
                if (a.type == VAL_CLOSURE) return a.as.closure == b.as.closure;
                if (a.type == VAL_PTR) return a.as.ptr == b.as.ptr;
                return 0;
        }
    }
    /* 跨类型数值相等: int 与 num 按数值比较 (脚本语义, 同 JS/Python) */
    if ((a.type == VAL_INT && b.type == VAL_NUM) ||
        (a.type == VAL_NUM && b.type == VAL_INT)) {
        int64_t iv = (a.type == VAL_INT) ? a.as.i : b.as.i;
        double  fv = (a.type == VAL_NUM) ? a.as.num : b.as.num;
        return (double)iv == fv;
    }
    return 0;
}
static int val_equal(Value a, Value b) { return value_equal(a, b, 0); }

/* ===================== 自由变量收集 (编译期) ===================== */

typedef struct {
    char **names;
    int    count;
    int    cap;
} FVSet;

static void fvset_init(FVSet *s) {
    s->names = NULL; s->count = 0; s->cap = 0;
}
static void fvset_add(FVSet *s, const char *name) {
    for (int i = 0; i < s->count; ++i)
        if (strcmp(s->names[i], name) == 0) return;
    if (s->count >= s->cap) {
        int ncap = s->cap ? s->cap * 2 : 32;
        s->names = (char **)realloc(s->names, (size_t)ncap * sizeof(char *));
        if (!s->names) abort();
        s->cap = ncap;
    }
    s->names[s->count++] = (char *)name;
}
static int fvset_has(FVSet *s, const char *name) {
    for (int i = 0; i < s->count; ++i)
        if (strcmp(s->names[i], name) == 0) return 1;
    return 0;
}
static void fvset_free(FVSet *s) { free(s->names); s->names = NULL; s->count = s->cap = 0; }

static void fv_collect_expr(FVSet *used, Expr *e);
static void fv_collect_stmt(FVSet *used, FVSet *locals, Stmt *s);

static void fv_collect_expr(FVSet *used, Expr *e) {
    if (!e) return;
    switch (e->kind) {
        case EXPR_VAR:      fvset_add(used, e->u.name); break;
        case EXPR_ASSIGN:   fvset_add(used, e->u.assign.name); break;
        case EXPR_UNARY:    fv_collect_expr(used, e->u.unary.inner); break;
        case EXPR_BINARY:
            fv_collect_expr(used, e->u.binary.left);
            fv_collect_expr(used, e->u.binary.right);
            break;
        case EXPR_CALL:
            fv_collect_expr(used, e->u.call.callee);
            for (int i = 0; i < e->u.call.argc; ++i)
                fv_collect_expr(used, e->u.call.args[i]);
            break;
        case EXPR_MEMBER:
            fv_collect_expr(used, e->u.member.obj);
            break;
        case EXPR_INDEX:
            fv_collect_expr(used, e->u.idx.obj);
            fv_collect_expr(used, e->u.idx.index);
            break;
        case EXPR_INDEX_ASSIGN:
            fv_collect_expr(used, e->u.index_assign.target);
            fv_collect_expr(used, e->u.index_assign.value);
            break;
        case EXPR_ARRAY:
            for (int i = 0; i < e->u.array.count; ++i) {
                fv_collect_expr(used, e->u.array.keys[i]);
                fv_collect_expr(used, e->u.array.vals[i]);
            }
            break;
        case EXPR_LAMBDA:
            /* Lambda body 属于新作用域, 不合并名字到本层 */
            break;
        default: break;
    }
}

static void fv_collect_stmt(FVSet *used, FVSet *locals, Stmt *s) {
    if (!s) return;
    switch (s->kind) {
        case STMT_LET:
            fvset_add(locals, s->u.let.name);
            if (s->u.let.init) fv_collect_expr(used, s->u.let.init);
            break;
        case STMT_ASSIGN:
            fvset_add(used, s->u.assign.name);
            fv_collect_expr(used, s->u.assign.value);
            break;
        case STMT_IF:
            fv_collect_expr(used, s->u.ifs.cond);
            fv_collect_stmt(used, locals, s->u.ifs.then_b);
            if (s->u.ifs.else_b) fv_collect_stmt(used, locals, s->u.ifs.else_b);
            break;
        case STMT_WHILE:
            fv_collect_expr(used, s->u.whiles.cond);
            fv_collect_stmt(used, locals, s->u.whiles.body);
            break;
        case STMT_FOR:
            if (s->u.fors.init) fv_collect_stmt(used, locals, s->u.fors.init);
            if (s->u.fors.cond) fv_collect_expr(used, s->u.fors.cond);
            if (s->u.fors.step) fv_collect_expr(used, s->u.fors.step);
            fv_collect_stmt(used, locals, s->u.fors.body);
            break;
        case STMT_RETURN:
            if (s->u.returns.value) fv_collect_expr(used, s->u.returns.value);
            break;
        case STMT_BLOCK:
            for (int i = 0; i < s->u.block.count; ++i)
                fv_collect_stmt(used, locals, s->u.block.stmts[i]);
            break;
        case STMT_FUNC:
            /* 内嵌函数名字对当前作用域是局部变量 */
            if (s->u.func.name) fvset_add(locals, s->u.func.name);
            /* body 在新作用域, 不合并到本层 */
            break;
        case STMT_EXPR:
            if (s->u.expr) fv_collect_expr(used, s->u.expr);
            break;
        case STMT_TRY:
            fv_collect_stmt(used, locals, s->u.trys.body);
            if (s->u.trys.catchvar) fvset_add(locals, s->u.trys.catchvar);
            if (s->u.trys.catchbody) fv_collect_stmt(used, locals, s->u.trys.catchbody);
            if (s->u.trys.finallybody) fv_collect_stmt(used, locals, s->u.trys.finallybody);
            break;
        case STMT_THROW:
            if (s->u.throws.value) fv_collect_expr(used, s->u.throws.value);
            break;
    }
}

/* 为单个函数节点填充 freevars/freecount */
static void collect_freevars_one(Arena *a, Stmt *func) {
    if (!func || func->kind != STMT_FUNC) return;

    FVSet used, locals, params;
    fvset_init(&used); fvset_init(&locals); fvset_init(&params);

    for (int i = 0; i < func->u.func.pcount; ++i)
        fvset_add(&params, func->u.func.params[i]);

    fv_collect_stmt(&used, &locals, func->u.func.body);

    int freecount = 0;
    for (int i = 0; i < used.count; ++i)
        if (!fvset_has(&locals, used.names[i]) && !fvset_has(&params, used.names[i]))
            freecount++;

    if (freecount == 0) {
        func->u.func.freevars = NULL;
        func->u.func.freecount = 0;
    } else {
        char **fv = (char **)arena_alloc(a, (size_t)freecount * sizeof(char *));
        int idx = 0;
        for (int i = 0; i < used.count; ++i)
            if (!fvset_has(&locals, used.names[i]) && !fvset_has(&params, used.names[i]))
                fv[idx++] = used.names[i];
        func->u.func.freevars = fv;
        func->u.func.freecount = freecount;
    }

    fvset_free(&used); fvset_free(&locals); fvset_free(&params);
}

/* 递归遍历表达式, 找到嵌套的 lambda 并收集自由变量 */
static void collect_freevars_deep_expr(Arena *a, Expr *e);

/* 递归遍历所有嵌套函数 */
static void collect_freevars_deep(Arena *a, Stmt *s) {
    if (!s) return;
    if (s->kind == STMT_FUNC) {
        if (s->u.func.body) collect_freevars_deep(a, s->u.func.body);
        collect_freevars_one(a, s);
        return;
    }
    switch (s->kind) {
        case STMT_BLOCK:
            for (int i = 0; i < s->u.block.count; ++i)
                collect_freevars_deep(a, s->u.block.stmts[i]);
            break;
        case STMT_IF:
            collect_freevars_deep(a, s->u.ifs.then_b);
            collect_freevars_deep(a, s->u.ifs.else_b);
            break;
        case STMT_WHILE:
            collect_freevars_deep(a, s->u.whiles.body);
            break;
        case STMT_FOR:
            collect_freevars_deep(a, s->u.fors.init);
            collect_freevars_deep(a, s->u.fors.body);
            break;
        case STMT_LET:
            collect_freevars_deep_expr(a, s->u.let.init);
            break;
        case STMT_ASSIGN:
            collect_freevars_deep_expr(a, s->u.assign.value);
            break;
        case STMT_EXPR:
            collect_freevars_deep_expr(a, s->u.expr);
            break;
        case STMT_RETURN:
            collect_freevars_deep_expr(a, s->u.returns.value);
            break;
        case STMT_TRY:
            collect_freevars_deep(a, s->u.trys.body);
            collect_freevars_deep(a, s->u.trys.catchbody);
            collect_freevars_deep(a, s->u.trys.finallybody);
            break;
        default: break;
    }
}

static void collect_freevars_deep_expr(Arena *a, Expr *e) {
    if (!e) return;
    switch (e->kind) {
        case EXPR_LAMBDA: {
            /* 递归处理 lambda 体中的嵌套函数/闭包 */
            Stmt *func = e->u.lambda;
            if (func->u.func.body)
                collect_freevars_deep(a, func->u.func.body);
            collect_freevars_one(a, func);
            return;
        }
        case EXPR_UNARY:
            collect_freevars_deep_expr(a, e->u.unary.inner);
            break;
        case EXPR_BINARY:
            collect_freevars_deep_expr(a, e->u.binary.left);
            collect_freevars_deep_expr(a, e->u.binary.right);
            break;
        case EXPR_CALL:
            collect_freevars_deep_expr(a, e->u.call.callee);
            for (int i = 0; i < e->u.call.argc; ++i)
                collect_freevars_deep_expr(a, e->u.call.args[i]);
            break;
        case EXPR_ASSIGN:
            collect_freevars_deep_expr(a, e->u.assign.value);
            break;
        case EXPR_MEMBER:
            collect_freevars_deep_expr(a, e->u.member.obj);
            break;
        case EXPR_INDEX:
            collect_freevars_deep_expr(a, e->u.idx.obj);
            collect_freevars_deep_expr(a, e->u.idx.index);
            break;
        case EXPR_INDEX_ASSIGN:
            collect_freevars_deep_expr(a, e->u.index_assign.target);
            collect_freevars_deep_expr(a, e->u.index_assign.value);
            break;
        case EXPR_ARRAY:
            for (int i = 0; i < e->u.array.count; ++i) {
                collect_freevars_deep_expr(a, e->u.array.keys[i]);
                collect_freevars_deep_expr(a, e->u.array.vals[i]);
            }
            break;
        default: break;
    }
}

/* 为 Program 中所有函数(含嵌套)收集自由变量, 必须在执行前调用 */
void cvm_collect_freevars(Arena *a, Program *p) {
    for (int i = 0; i < p->count; ++i)
        collect_freevars_deep(a, p->stmts[i]);
}

/* --------------------------- 运行时生命周期 --------------------------- */
Runtime *rt_new(void) {
    Runtime *rt = (Runtime *)malloc(sizeof(Runtime));
    if (!rt) abort();
    arena_init(&rt->arena);
    rt->global = env_new(NULL, &rt->arena);
    map_init(&rt->funcs);
    map_init(&rt->builtins);
    map_init(&rt->modules);
    map_init(&rt->ffi_syms);
    map_init(&rt->ffi_sigs);
    map_init(&rt->ffi_allow);
    map_init(&rt->ffi_allow_sym);
    rt->ffi_count = 0;
    rt->ffi_enabled = 0;
    rt->timer_count = 0;
    rt->timer_epoch = 0;  /* 首次 rt_now_ms 调用时置为当前时间 */
    rt->return_flag = 0;
    rt->return_value = val_nil();
    rt->break_flag = 0;
    rt->continue_flag = 0;
    rt->call_depth = 0;
    rt->has_error = 0;
    rt->has_throw = 0;
    rt->thrown = val_nil();
    rt->errbuf[0] = '\0';
    rt->current_file[0] = '\0';
    rt->loading_n = 0;
    host_register_all(rt);
    return rt;
}

void rt_free(Runtime *rt) {
    if (!rt) return;
    map_destroy(&rt->builtins);
    map_destroy(&rt->funcs);
    map_destroy(&rt->modules);   /* 缓存的导出 Map* 随进程退出释放, 此处不深入释放 */
    map_destroy(&rt->ffi_syms);
    env_free(rt->global);
    for (int i = 0; i < rt->ffi_count; ++i) ffi_close(rt->ffi_libs[i].lib);
    arena_destroy(&rt->arena);
    free(rt);
}

void rt_register_builtin(Runtime *rt, const char *name, BuiltinFunc f) {
    map_set(&rt->builtins, name, (void *)f);
}

/* ------------------------------ 求值器 ------------------------------- */
static void interp_err(Runtime *rt, int line, const char *fmt, ...) {
    va_list ap; va_start(ap, fmt);
    int n = snprintf(rt->errbuf, sizeof(rt->errbuf), "运行错误 行 %d: ", line);
    vsnprintf(rt->errbuf + n, sizeof(rt->errbuf) - (size_t)n, fmt, ap);
    va_end(ap);
    rt->has_error = 1;
}

static Value call_function(Runtime *rt, Env *env, const char *name,
                           Expr **args, int argc, int line);
static void exec_stmt(Runtime *rt, Env *env, Stmt *s);
static Closure *make_closure(Runtime *rt, Env *env, Stmt *fn);

static Value eval_expr(Runtime *rt, Env *env, Expr *e) {
    if (rt->has_error || rt->has_throw) return val_nil();
    switch (e->kind) {
        case EXPR_NUM:
            if (e->u.numlit.is_int) return val_int(e->u.numlit.ival);
            return val_num(e->u.numlit.fval);
        case EXPR_STR:  return val_str(e->u.str);
        case EXPR_BOOL: return val_bool(e->u.boolean);
        case EXPR_NIL:  return val_nil();

        case EXPR_ARRAY: {
            Arr *arr = (Arr *)arena_alloc(&rt->arena, sizeof(Arr));
            arr_init(&rt->arena, arr);
            for (int i = 0; i < e->u.array.count; ++i) {
                Expr *ve = e->u.array.vals[i];
                Value v = ve ? eval_expr(rt, env, ve) : val_nil();
                if (rt->has_error || rt->has_throw) return val_nil();
                if (e->u.array.haskey[i]) {
                    Value k = eval_expr(rt, env, e->u.array.keys[i]);
                    if (rt->has_error || rt->has_throw) return val_nil();
                    arr_set_from_key(rt, arr, k, v);
                } else {
                    arr_append(&rt->arena, arr, v);
                }
            }
            return val_array(arr);
        }

        case EXPR_LAMBDA: {
            Closure *cl = make_closure(rt, env, e->u.lambda);
            return val_closure(cl);
        }

        case EXPR_VAR: {
            Value *v = env_get(env, e->u.name);
            if (!v) { interp_err(rt, e->line, "未定义的变量 '%s'", e->u.name); return val_nil(); }
            return *v;
        }

        case EXPR_UNARY: {
            Value inner = eval_expr(rt, env, e->u.unary.inner);
            if (rt->has_error || rt->has_throw) return val_nil();
            if (e->u.unary.op == TK_MINUS) {
                if (inner.type == VAL_INT) return val_int(-inner.as.i);
                if (inner.type == VAL_NUM) return val_num(-inner.as.num);
                interp_err(rt, e->line, "一元'-'需要数字或整数"); return val_nil();
            } else { /* NOT */
                return val_bool(!val_truthy(inner));
            }
        }

        case EXPR_BINARY: {
            int op = e->u.binary.op;
            /* 短路逻辑 */
            if (op == TK_AND || op == TK_OR) {
                Value l = eval_expr(rt, env, e->u.binary.left);
                if (rt->has_error || rt->has_throw) return val_nil();
                if (op == TK_AND) {
                    if (!val_truthy(l)) return l;
                    return eval_expr(rt, env, e->u.binary.right);
                } else {
                    if (val_truthy(l)) return l;
                    return eval_expr(rt, env, e->u.binary.right);
                }
            }
            Value l = eval_expr(rt, env, e->u.binary.left);
            if (rt->has_error || rt->has_throw) return val_nil();
            Value r = eval_expr(rt, env, e->u.binary.right);
            if (rt->has_error || rt->has_throw) return val_nil();

            switch (op) {
                case TK_PLUS: {
                    if (l.type == VAL_STR && r.type == VAL_STR) {
                        size_t nl = strlen(l.as.str), nr = strlen(r.as.str);
                        char *buf = (char *)arena_alloc(&rt->arena, nl + nr + 1);
                        memcpy(buf, l.as.str, nl); memcpy(buf + nl, r.as.str, nr); buf[nl + nr] = '\0';
                        return val_str(buf);
                    }
                    if (l.type == VAL_INT && r.type == VAL_INT) return val_int(l.as.i + r.as.i);
                    if (l.type == VAL_NUM && r.type == VAL_NUM) return val_num(l.as.num + r.as.num);
                    if ((l.type == VAL_INT || l.type == VAL_NUM) &&
                        (r.type == VAL_INT || r.type == VAL_NUM)) {
                        double a = (l.type == VAL_INT) ? (double)l.as.i : l.as.num;
                        double b = (r.type == VAL_INT) ? (double)r.as.i : r.as.num;
                        return val_num(a + b);
                    }
                    interp_err(rt, e->line, "'+' 需要两个数字/整数或两个字符串"); return val_nil();
                }
                case TK_MINUS:
                case TK_STAR:
                case TK_SLASH:
                case TK_PERCENT: {
                    /* 整数 × 整数 -> 整数 (精确, 无浮点误差) */
                    if (l.type == VAL_INT && r.type == VAL_INT) {
                        if (op == TK_MINUS) return val_int(l.as.i - r.as.i);
                        if (op == TK_STAR)   return val_int(l.as.i * r.as.i);
                        if (op == TK_SLASH) {
                            if (r.as.i == 0) { interp_err(rt, e->line, "除以零"); return val_nil(); }
                            return val_int(l.as.i / r.as.i);   /* 整数除法 */
                        }
                        if (op == TK_PERCENT) {
                            if (r.as.i == 0) { interp_err(rt, e->line, "取模零"); return val_nil(); }
                            return val_int(l.as.i % r.as.i);   /* 整数取模 */
                        }
                        break;
                    }
                    if (l.type == VAL_NUM && r.type == VAL_NUM) {
                        if (op == TK_MINUS) return val_num(l.as.num - r.as.num);
                        if (op == TK_STAR)   return val_num(l.as.num * r.as.num);
                        if (op == TK_SLASH) {
                            if (r.as.num == 0.0) { interp_err(rt, e->line, "除以零"); return val_nil(); }
                            return val_num(l.as.num / r.as.num);
                        }
                        if (op == TK_PERCENT) {
                            if (r.as.num == 0.0) { interp_err(rt, e->line, "取模零"); return val_nil(); }
                            return val_num(fmod(l.as.num, r.as.num));
                        }
                        break;
                    }
                    /* 混合 int/float -> 提升为 double */
                    if ((l.type == VAL_INT || l.type == VAL_NUM) &&
                        (r.type == VAL_INT || r.type == VAL_NUM)) {
                        double a = (l.type == VAL_INT) ? (double)l.as.i : l.as.num;
                        double b = (r.type == VAL_INT) ? (double)r.as.i : r.as.num;
                        if (op == TK_MINUS) return val_num(a - b);
                        if (op == TK_STAR)   return val_num(a * b);
                        if (op == TK_SLASH) {
                            if (b == 0.0) { interp_err(rt, e->line, "除以零"); return val_nil(); }
                            return val_num(a / b);
                        }
                        if (op == TK_PERCENT) {
                            if (b == 0.0) { interp_err(rt, e->line, "取模零"); return val_nil(); }
                            return val_num(fmod(a, b));
                        }
                        break;
                    }
                    interp_err(rt, e->line, "算术运算需要数字或整数"); return val_nil();
                }
                case TK_EQEQ:  return val_bool(val_equal(l, r));
                case TK_NOTEQ: return val_bool(!val_equal(l, r));
                case TK_LT: case TK_GT: case TK_LE: case TK_GE: {
                    if (l.type == VAL_INT && r.type == VAL_INT) {
                        int64_t a = l.as.i, b = r.as.i;
                        if (op == TK_LT) return val_bool(a < b);
                        if (op == TK_GT) return val_bool(a > b);
                        if (op == TK_LE) return val_bool(a <= b);
                        return val_bool(a >= b);
                    }
                    if (l.type == VAL_NUM && r.type == VAL_NUM) {
                        double a = l.as.num, b = r.as.num;
                        if (op == TK_LT) return val_bool(a < b);
                        if (op == TK_GT) return val_bool(a > b);
                        if (op == TK_LE) return val_bool(a <= b);
                        return val_bool(a >= b);
                    }
                    if (l.type == VAL_STR && r.type == VAL_STR) {
                        int c = strcmp(l.as.str, r.as.str);
                        if (op == TK_LT) return val_bool(c < 0);
                        if (op == TK_GT) return val_bool(c > 0);
                        if (op == TK_LE) return val_bool(c <= 0);
                        return val_bool(c >= 0);
                    }
                    if ((l.type == VAL_INT || l.type == VAL_NUM) &&
                        (r.type == VAL_INT || r.type == VAL_NUM)) {
                        double a = (l.type == VAL_INT) ? (double)l.as.i : l.as.num;
                        double b = (r.type == VAL_INT) ? (double)r.as.i : r.as.num;
                        if (op == TK_LT) return val_bool(a < b);
                        if (op == TK_GT) return val_bool(a > b);
                        if (op == TK_LE) return val_bool(a <= b);
                        return val_bool(a >= b);
                    }
                    interp_err(rt, e->line, "比较需要同类型数字或字符串"); return val_nil();
                }
                default: break;
            }
            interp_err(rt, e->line, "未知运算符"); return val_nil();
        }

        case EXPR_CALL: {
            Expr *callee = e->u.call.callee;
            /* 闭包值优先: env 中找到了 VAL_CLOSURE */
            if (callee->kind == EXPR_VAR) {
                Value *cv = env_get(env, callee->u.name);
                if (cv && cv->type == VAL_CLOSURE) {
                    Closure *cl = (Closure *)cv->as.closure;
                    Stmt *fn = cl->fn;
                    if (rt->call_depth >= CVM_MAX_CALL_DEPTH) {
                        interp_err(rt, e->line, "递归深度超过上限 (%d)", CVM_MAX_CALL_DEPTH);
                        return val_nil();
                    }
                    rt->call_depth++;
                    if (e->u.call.argc != fn->u.func.pcount) {
                        interp_err(rt, e->line, "函数期望 %d 个参数, 收到 %d",
                                   fn->u.func.pcount, e->u.call.argc);
                        rt->call_depth--;
                        return val_nil();
                    }
                    Env *fen = env_new(cl->capenv, &rt->arena);
                    for (int i = 0; i < e->u.call.argc; ++i)
                        env_define(fen, fn->u.func.params[i],
                                   eval_expr(rt, env, e->u.call.args[i]), &rt->arena);
                    if (rt->has_error || rt->has_throw) { env_free(fen); rt->call_depth--; return val_nil(); }
                    rt->return_flag = 0;
                    exec_stmt(rt, fen, fn->u.func.body);
                    Value r = rt->return_flag ? rt->return_value : val_nil();
                    rt->return_flag = 0;
                    env_free(fen);
                    rt->call_depth--;
                    return r;
                }
            }

            const char *fname = NULL;
            if (callee->kind == EXPR_VAR) {
                fname = callee->u.name;
            } else if (callee->kind == EXPR_MEMBER) {
                Value obj = eval_expr(rt, env, callee->u.member.obj);
                if (rt->has_error || rt->has_throw) return val_nil();
                if (obj.type != VAL_MODULE) {
                    interp_err(rt, e->line, "只有模块才能用 '.' 访问成员");
                    return val_nil();
                }
                Value *mem = (Value *)map_get((Map *)obj.as.mod, callee->u.member.name);
                if (!mem) {
                    interp_err(rt, e->line, "模块未导出成员 '%s'", callee->u.member.name);
                    return val_nil();
                }
                if (mem->type != VAL_FUNC) {
                    interp_err(rt, e->line, "成员 '%s' 不是可调用函数", callee->u.member.name);
                    return val_nil();
                }
                fname = mem->as.funcname;
            } else {
                interp_err(rt, e->line, "不支持的调用目标");
                return val_nil();
            }
            return call_function(rt, env, fname, e->u.call.args, e->u.call.argc, e->line);
        }

        case EXPR_MEMBER: {
            Value obj = eval_expr(rt, env, e->u.member.obj);
            if (rt->has_error || rt->has_throw) return val_nil();
            if (obj.type != VAL_MODULE) {
                interp_err(rt, e->line, "只有模块才能用 '.' 访问成员");
                return val_nil();
            }
            Value *mem = (Value *)map_get((Map *)obj.as.mod, e->u.member.name);
            if (!mem) {
                interp_err(rt, e->line, "模块未导出成员 '%s'", e->u.member.name);
                return val_nil();
            }
            return *mem;
        }

        case EXPR_INDEX: {
            Value obj = eval_expr(rt, env, e->u.idx.obj);
            if (rt->has_error || rt->has_throw) return val_nil();
            if (obj.type == VAL_STR) {
                Value key = eval_expr(rt, env, e->u.idx.index);
                if (rt->has_error || rt->has_throw) return val_nil();
                long idx;
                if (key.type == VAL_INT) idx = (long)key.as.i;
                else if (key.type == VAL_NUM) idx = (long)key.as.num;
                else { interp_err(rt, e->line, "字符串索引需要整数"); return val_nil(); }
                int clen;
                const char *p = utf8_char_at_ptr(obj.as.str, idx, &clen);
                if (!p) { interp_err(rt, e->line, "字符串索引越界"); return val_nil(); }
                char *o = (char *)arena_alloc(&rt->arena, (size_t)clen + 1);
                memcpy(o, p, (size_t)clen); o[clen] = '\0';
                return val_str(o);
            }
            if (obj.type != VAL_ARRAY) { interp_err(rt, e->line, "下标操作需要数组或字符串"); return val_nil(); }
            Value key = eval_expr(rt, env, e->u.idx.index);
            if (rt->has_error || rt->has_throw) return val_nil();
            ArrEntry *ent = arr_lookup(rt, (Arr *)obj.as.arr, key);
            if (!ent) return val_nil();
            return ent->value;
        }

        case EXPR_INDEX_ASSIGN: {
            Expr *t = e->u.index_assign.target;   /* 目标必为 EXPR_INDEX */
            Value obj = eval_expr(rt, env, t->u.idx.obj);
            if (rt->has_error || rt->has_throw) return val_nil();
            if (obj.type == VAL_STR) {
                /* v1.1+: 字符串下标赋值 — 创建新串替换指定码点 */
                Value key = eval_expr(rt, env, t->u.idx.index);
                if (rt->has_error || rt->has_throw) return val_nil();
                Value v = eval_expr(rt, env, e->u.index_assign.value);
                if (rt->has_error || rt->has_throw) return val_nil();
                /* 转换下标 */
                long idx;
                if (key.type == VAL_INT) idx = (long)key.as.i;
                else if (key.type == VAL_NUM) idx = (long)key.as.num;
                else { interp_err(rt, e->line, "字符串下标需要整数"); return val_nil(); }
                if (idx < 0) { interp_err(rt, e->line, "字符串下标不能为负"); return val_nil(); }
                /* 转换新值为码点 */
                int64_t new_cp;
                if (v.type == VAL_STR) {
                    new_cp = utf8_codepoint_at(v.as.str, 0);
                    if (new_cp < 0 || v.as.str[0] == '\0')
                        { interp_err(rt, e->line, "字符串下标赋值需要非空字符"); return val_nil(); }
                } else if (v.type == VAL_INT) {
                    new_cp = v.as.i;
                } else if (v.type == VAL_NUM) {
                    new_cp = (int64_t)v.as.num;
                } else {
                    interp_err(rt, e->line, "字符串下标赋值需要字符、整数或码点值");
                    return val_nil();
                }
                /* 定位旧码点 */
                int old_clen;
                const char *old_p = utf8_char_at_ptr(obj.as.str, idx, &old_clen);
                if (!old_p) { interp_err(rt, e->line, "字符串索引越界"); return val_nil(); }
                /* 构造新串 (prefix + 新编码码点 + suffix) */
                size_t prefix_len = (size_t)(old_p - obj.as.str);
                size_t suffix_start = prefix_len + (size_t)old_clen;
                size_t suffix_len   = strlen(obj.as.str + suffix_start);
                char enc[4];
                int enclen = utf8_encode(new_cp, enc);
                size_t new_len = prefix_len + (size_t)enclen + suffix_len;
                char *new_s = (char *)arena_alloc(&rt->arena, new_len + 1);
                if (prefix_len) memcpy(new_s, obj.as.str, prefix_len);
                memcpy(new_s + prefix_len, enc, (size_t)enclen);
                if (suffix_len) memcpy(new_s + prefix_len + enclen, obj.as.str + suffix_start, suffix_len);
                new_s[new_len] = '\0';
                Value result = val_str(new_s);
                /* 若目标来自变量, 更新该变量指向新串 */
                if (t->u.idx.obj->kind == EXPR_VAR)
                    env_assign(env, t->u.idx.obj->u.name, result, &rt->arena);
                return result;
            }
            if (obj.type != VAL_ARRAY) { interp_err(rt, e->line, "下标赋值需要数组"); return val_nil(); }
            Value key = eval_expr(rt, env, t->u.idx.index);
            if (rt->has_error || rt->has_throw) return val_nil();
            Value v = eval_expr(rt, env, e->u.index_assign.value);
            if (rt->has_error || rt->has_throw) return val_nil();
            arr_set_from_key(rt, (Arr *)obj.as.arr, key, v);
            return v;
        }

        case EXPR_ASSIGN: {
            Value v = eval_expr(rt, env, e->u.assign.value);
            if (rt->has_error || rt->has_throw) return val_nil();
            env_assign(env, e->u.assign.name, v, &rt->arena);
            return v;
        }
    }
    interp_err(rt, e->line, "未知表达式节点"); return val_nil();
}

/* ===================== 闭包创建辅助 ===================== */
static Closure *make_closure(Runtime *rt, Env *env, Stmt *fn) {
    Env *def_env = env;
    Env *root_env = env_root(def_env);
    Env *capenv = env_new(root_env, &rt->arena);
    /* 捕获自由变量: 仅抄"非 root 外层局部"的 Value* 槽 */
    for (int i = 0; i < fn->u.func.freecount; ++i) {
        const char *fv = fn->u.func.freevars[i];
        Value *slot = NULL;
        Env *owner = env_get_owner(def_env, fv, &slot);
        if (owner && owner != root_env && slot)
            env_link(capenv, fv, slot);
    }
    Closure *cl = (Closure *)arena_alloc(&rt->arena, sizeof(Closure));
    cl->fn = fn;
    cl->capenv = capenv;
    return cl;
}

/* ------------------------------ 语句执行 ----------------------------- */

static void exec_block(Runtime *rt, Env *env, Stmt *s) {
    Env *be = env_new(env, &rt->arena);
    for (int i = 0; i < s->u.block.count; ++i) {
        exec_stmt(rt, be, s->u.block.stmts[i]);
        if (rt->has_error || rt->has_throw || rt->return_flag || rt->break_flag || rt->continue_flag) break;
    }
    env_free(be);
}

static void exec_stmt(Runtime *rt, Env *env, Stmt *s) {
    if (rt->has_error || rt->has_throw) return;
    switch (s->kind) {
        case STMT_LET: {
            Value v = s->u.let.init ? eval_expr(rt, env, s->u.let.init) : val_nil();
            if (rt->has_error || rt->has_throw) return;
            env_define(env, s->u.let.name, v, &rt->arena);
            return;
        }
        case STMT_ASSIGN: {
            Value v = eval_expr(rt, env, s->u.assign.value);
            if (rt->has_error || rt->has_throw) return;
            env_assign(env, s->u.assign.name, v, &rt->arena);
            return;
        }
        case STMT_IF: {
            Value c = eval_expr(rt, env, s->u.ifs.cond);
            if (rt->has_error || rt->has_throw) return;
            if (val_truthy(c)) exec_stmt(rt, env, s->u.ifs.then_b);
            else if (s->u.ifs.else_b) exec_stmt(rt, env, s->u.ifs.else_b);
            return;
        }
        case STMT_WHILE: {
            /* quickening: 检测 `while(var < const)` 并走快速路径 */
            int fast = 0; const char *cv=NULL; int64_t cc=0; int co=0;
            if (s->u.whiles.cond && s->u.whiles.cond->kind == EXPR_BINARY) {
                Expr *ce = s->u.whiles.cond; int op = ce->u.binary.op;
                if ((op==TK_LT||op==TK_GT||op==TK_LE||op==TK_GE) &&
                    ce->u.binary.left && ce->u.binary.left->kind==EXPR_VAR &&
                    ce->u.binary.right && ce->u.binary.right->kind==EXPR_NUM &&
                    ce->u.binary.right->u.numlit.is_int) {
                    fast=1; cv=ce->u.binary.left->u.name;
                    cc=ce->u.binary.right->u.numlit.ival; co=op;
                }
            }
            while (1) {
                if (rt->break_flag) break;
                rt->continue_flag = 0;
                if (fast) {
                    Value *vp = env_get(env_root(env), cv);
                    int64_t v = (vp && vp->type == VAL_INT) ? vp->as.i : (vp ? (int64_t)vp->as.num : 0);
                    int ok; switch(co){case TK_LT:ok=v<cc;break;case TK_GT:ok=v>cc;break;case TK_LE:ok=v<=cc;break;case TK_GE:ok=v>=cc;break;default:ok=0;break;}
                    if (!ok) break;
                } else {
                    Value c = eval_expr(rt, env, s->u.whiles.cond);
                    if (rt->has_error || rt->has_throw) return;
                    if (!val_truthy(c)) break;
                }
                exec_stmt(rt, env, s->u.whiles.body);
                if (rt->has_error || rt->has_throw || rt->return_flag || rt->break_flag) break;
            }
            rt->break_flag = 0; rt->continue_flag = 0;
            return;
        }
        case STMT_FOR: {
            if (s->u.fors.init) { exec_stmt(rt, env, s->u.fors.init); if (rt->has_error || rt->has_throw || rt->return_flag || rt->break_flag) return; }
            while (1) {
                if (rt->break_flag) break;
                rt->continue_flag = 0;
                if (s->u.fors.cond) {
                    Value c = eval_expr(rt, env, s->u.fors.cond);
                    if (rt->has_error || rt->has_throw) return;
                    if (!val_truthy(c)) break;
                }
                exec_stmt(rt, env, s->u.fors.body);
                if (rt->has_error || rt->has_throw || rt->return_flag || rt->break_flag) break;
                if (s->u.fors.step) { eval_expr(rt, env, s->u.fors.step); if (rt->has_error || rt->has_throw) return; }
            }
            rt->break_flag = 0; rt->continue_flag = 0;
            return;
        }
        case STMT_FOR_IN: {
            Value it = eval_expr(rt, env, s->u.for_in.iterable);
            if (rt->has_error || rt->has_throw) { rt->break_flag = 0; rt->continue_flag = 0; return; }
            if (it.type == VAL_ARRAY) {
                Arr *arr = (Arr *)it.as.arr;
                int n = arr_len(arr);
                for (int i = 0; i < n; ++i) {
                    if (rt->break_flag) break;
                    rt->continue_flag = 0;
                    ArrEntry *e = arr_at(arr, i);
                    Value elem = e ? e->value : val_nil();
                    env_define(env, s->u.for_in.iter_var, elem, &rt->arena);
                    exec_stmt(rt, env, s->u.for_in.body);
                    if (rt->has_error || rt->has_throw || rt->return_flag || rt->break_flag) break;
                }
            } else if (it.type == VAL_STR) {
                const char *str = it.as.str ? it.as.str : "";
                int n = (int)strlen(str);
                for (int i = 0; i < n; ++i) {
                    if (rt->break_flag) break;
                    rt->continue_flag = 0;
                    char buf[2] = { str[i], '\0' };
                    Value elem = val_str(arena_strdup(&rt->arena, buf));
                    env_define(env, s->u.for_in.iter_var, elem, &rt->arena);
                    exec_stmt(rt, env, s->u.for_in.body);
                    if (rt->has_error || rt->has_throw || rt->return_flag || rt->break_flag) break;
                }
            } else {
                interp_err(rt, s->line, "for-in 暂不支持该类型");
                rt->break_flag = 0; rt->continue_flag = 0;
                return;
            }
            rt->break_flag = 0; rt->continue_flag = 0;
            return;
        }
        case STMT_RETURN: {
            if (s->u.returns.value) {
                rt->return_value = eval_expr(rt, env, s->u.returns.value);
                if (rt->has_error || rt->has_throw) return;
            } else {
                rt->return_value = val_nil();
            }
            rt->return_flag = 1;
            return;
        }
        case STMT_BREAK:
            rt->break_flag = 1;
            return;
        case STMT_CONTINUE:
            rt->continue_flag = 1;
            return;
        case STMT_BLOCK:
            exec_block(rt, env, s);
            return;
        case STMT_FUNC: {
            Stmt *fn = s;
            Closure *cl = make_closure(rt, env, fn);
            if (fn->u.func.name) {
                map_set(&rt->funcs, fn->u.func.name, cl);
                env_define(env, fn->u.func.name, val_closure(cl), &rt->arena);
            }
            return;
        }
        case STMT_EXPR: {
            if (s->u.expr) { eval_expr(rt, env, s->u.expr); }
            return;
        }
        case STMT_THROW: {
            if (rt->has_error || rt->has_throw) return; /* 已有未决异常(含嵌套 throw 表达式内已抛), 直接冒泡 */
            Value v = s->u.throws.value ? eval_expr(rt, env, s->u.throws.value) : val_nil();
            if (rt->has_error || rt->has_throw) return; /* 求值过程中内层异常已置位, 保留其 thrown 值 */
            rt->thrown = v;
            rt->has_throw = 1;
            return;
        }
        case STMT_TRY: {
            exec_stmt(rt, env, s->u.trys.body);
            if (rt->has_throw) {
                if (s->u.trys.catchvar && s->u.trys.catchbody) {
                    Env *ce = env_new(env, &rt->arena);
                    env_define(ce, s->u.trys.catchvar, rt->thrown, &rt->arena);
                    rt->has_throw = 0;
                    exec_stmt(rt, ce, s->u.trys.catchbody);
                    env_free(ce);
                }
                /* 无 catch: 保留 has_throw 继续向外冒泡 */
            }
            if (s->u.trys.finallybody) {
                /* finally 必跑: 暂存异常标志(不清 errbuf, 其仍保留原错误文本), 跑完后再视情况恢复 */
                int pend_throw = rt->has_throw;
                int pend_err = rt->has_error;
                rt->has_throw = 0; rt->has_error = 0;
                exec_stmt(rt, env, s->u.trys.finallybody);
                if (!rt->has_error && !rt->has_throw) {       /* finally 干净才恢复原状态 */
                    if (pend_err) rt->has_error = 1;          /* errbuf 仍保留原错误文本 */
                    if (pend_throw) rt->has_throw = 1;
                }
                /* finally 自身出错/再抛: 以 finally 的为准, 不恢复 */
            }
            return;
        }
    }
}

/* ===================== FFI 类型化封送 ===================== */
/* 值 -> C 参数联合 (按真实类型承载, 不再经 double 往返指针, 消除 UB) */
typedef union { double d; int64_t i; void *p; } CArg;

/* 按类型码把 CVM Value 转为 C 参数. 类型码: d=double i=int s=char* p=void* */
static CArg ffi_val_to_c(Runtime *rt, int line, Value v, char code) {
    CArg out; out.i = 0;
    switch (code) {
        case 'd':
            if (v.type == VAL_INT) { out.d = (double)v.as.i; break; }
            if (v.type == VAL_NUM) { out.d = v.as.num; break; }
            interp_err(rt, line, "FFI 参数需要数字 (类型 'd')"); return out;
        case 'i':
            if (v.type == VAL_INT) { out.i = v.as.i; break; }
            if (v.type == VAL_NUM) { out.i = (int64_t)(int)v.as.num; break; }
            interp_err(rt, line, "FFI 参数需要数字 (类型 'i')"); return out;
        case 's':
            if (v.type != VAL_STR) { interp_err(rt, line, "FFI 参数需要字符串 (类型 's')"); return out; }
            out.p = v.as.str; break;
        case 'p':
            if (v.type != VAL_PTR) { interp_err(rt, line, "FFI 参数需要指针 (类型 'p')"); return out; }
            out.p = v.as.ptr; break;
        case 'q':   /* int64 (FFI 与 VAL_INT 对接) */
            if (v.type == VAL_INT) { out.i = v.as.i; break; }
            if (v.type == VAL_NUM) { out.i = (int64_t)v.as.num; break; }
            interp_err(rt, line, "FFI 参数需要 int64 (类型 'q')"); return out;
        default:
            interp_err(rt, line, "FFI 不支持的参数类型码: '%c'", code); break;
    }
    return out;
}

/* 原生返回值 -> CVM Value. 返回类型码: d/i/p/v */
static Value ffi_c_to_val(Runtime *rt, int line, char rc, intptr_t r) {
    switch (rc) {
        case 'd': return val_num((double)r);   /* double 返回 (经 union) */
        case 'i': return val_num((double)(int)r);
        case 'q': return val_int((int64_t)r);
        case 'p': return val_ptr((void *)r);
        case 's': { /* char* 返回 -> 拷入 arena */
            const char *cs = (const char *)(intptr_t)r;
            if (!cs) return val_str(arena_strdup(&rt->arena, ""));
            return val_str(arena_strdup(&rt->arena, cs));
        }
        case 'v': return val_nil();
        default:  interp_err(rt, line, "FFI 不支持的返回类型码: '%c'", rc); return val_nil();
    }
}

/* 按类型化签名调用函数指针. 仅支持: 参数全整型类(i/s/p) 或 全浮点类(d);
 * 返回 d/i/p/v. 混合整型/浮点参数在 v1 中拒绝 (ABI 不确定, 避免 UB).
 * 每个分支把 fp 内联转换成"精确元数"的函数指针类型再调用, 避免类型不匹配告警。 */
static Value ffi_invoke(Runtime *rt, int line, void *fp, const char *sig, int nparams, CArg *a) {
    const char *rp = strchr(sig, ')');
    char rc = rp ? rp[1] : sig[0];
    int pbase = rp ? 0 : 1;   /* 参数类型码起始偏移: ')'前 或 返回类型后 */
    int all_sse = 1, all_int = 1;
    for (int i = 0; i < nparams; ++i) {
        char c = sig[pbase + i];
        if (c == 'd') all_int = 0;
        else if (c == 'i' || c == 's' || c == 'p' || c == 'q') all_sse = 0;
        else { interp_err(rt, line, "FFI 不支持的参数类型码: '%c'", c); return val_nil(); }
    }
    if (!all_sse && !all_int) {
        interp_err(rt, line, "FFI 暂不支持整型/浮点混合参数 (v1)");
        return val_nil();
    }
    int n = nparams < 6 ? nparams : 6;
    if (all_sse) {
        double d[6]; for (int i = 0; i < nparams; ++i) d[i] = a[i].d;
        if (rc == 'd') {
            double r;
            switch (n) {
                case 0: r = ((double(*)(void))fp)(); break;
                case 1: r = ((double(*)(double))fp)(d[0]); break;
                case 2: r = ((double(*)(double,double))fp)(d[0], d[1]); break;
                case 3: r = ((double(*)(double,double,double))fp)(d[0], d[1], d[2]); break;
                case 4: r = ((double(*)(double,double,double,double))fp)(d[0], d[1], d[2], d[3]); break;
                case 5: r = ((double(*)(double,double,double,double,double))fp)(d[0], d[1], d[2], d[3], d[4]); break;
                default: r = ((double(*)(double,double,double,double,double,double))fp)(d[0], d[1], d[2], d[3], d[4], d[5]); break;
            }
            return val_num(r);
        } else {
            intptr_t r;
            switch (n) {
                case 0: r = ((intptr_t(*)(void))fp)(); break;
                case 1: r = ((intptr_t(*)(double))fp)(d[0]); break;
                case 2: r = ((intptr_t(*)(double,double))fp)(d[0], d[1]); break;
                case 3: r = ((intptr_t(*)(double,double,double))fp)(d[0], d[1], d[2]); break;
                case 4: r = ((intptr_t(*)(double,double,double,double))fp)(d[0], d[1], d[2], d[3]); break;
                case 5: r = ((intptr_t(*)(double,double,double,double,double))fp)(d[0], d[1], d[2], d[3], d[4]); break;
                default: r = ((intptr_t(*)(double,double,double,double,double,double))fp)(d[0], d[1], d[2], d[3], d[4], d[5]); break;
            }
            return ffi_c_to_val(rt, line, rc, r);
        }
    } else {
        intptr_t d[6]; for (int i = 0; i < nparams; ++i) d[i] = a[i].i;
        if (rc == 'd') {
            double r;
            switch (n) {
                case 0: r = ((double(*)(void))fp)(); break;
                case 1: r = ((double(*)(intptr_t))fp)(d[0]); break;
                case 2: r = ((double(*)(intptr_t,intptr_t))fp)(d[0], d[1]); break;
                case 3: r = ((double(*)(intptr_t,intptr_t,intptr_t))fp)(d[0], d[1], d[2]); break;
                case 4: r = ((double(*)(intptr_t,intptr_t,intptr_t,intptr_t))fp)(d[0], d[1], d[2], d[3]); break;
                case 5: r = ((double(*)(intptr_t,intptr_t,intptr_t,intptr_t,intptr_t))fp)(d[0], d[1], d[2], d[3], d[4]); break;
                default: r = ((double(*)(intptr_t,intptr_t,intptr_t,intptr_t,intptr_t,intptr_t))fp)(d[0], d[1], d[2], d[3], d[4], d[5]); break;
            }
            return val_num(r);
        } else {
            intptr_t r;
            switch (n) {
                case 0: r = ((intptr_t(*)(void))fp)(); break;
                case 1: r = ((intptr_t(*)(intptr_t))fp)(d[0]); break;
                case 2: r = ((intptr_t(*)(intptr_t,intptr_t))fp)(d[0], d[1]); break;
                case 3: r = ((intptr_t(*)(intptr_t,intptr_t,intptr_t))fp)(d[0], d[1], d[2]); break;
                case 4: r = ((intptr_t(*)(intptr_t,intptr_t,intptr_t,intptr_t))fp)(d[0], d[1], d[2], d[3]); break;
                case 5: r = ((intptr_t(*)(intptr_t,intptr_t,intptr_t,intptr_t,intptr_t))fp)(d[0], d[1], d[2], d[3], d[4]); break;
                default: r = ((intptr_t(*)(intptr_t,intptr_t,intptr_t,intptr_t,intptr_t,intptr_t))fp)(d[0], d[1], d[2], d[3], d[4], d[5]); break;
            }
            return ffi_c_to_val(rt, line, rc, r);
        }
    }
}

/* ------------------------------ 函数调用 ----------------------------- */
static Value call_function(Runtime *rt, Env *env, const char *name,
                           Expr **args, int argc, int line) {
    /* 1) 宿主内置 */
    BuiltinFunc bf = (BuiltinFunc)map_get(&rt->builtins, name);
    if (bf) {
        Value *av = (Value *)malloc((size_t)(argc > 0 ? argc : 1) * sizeof(Value));
        for (int i = 0; i < argc; ++i) av[i] = eval_expr(rt, env, args[i]);
        if (rt->has_error || rt->has_throw) { free(av); return val_nil(); }
        Value r = bf(rt, argc, av);
        free(av);
        return r;
    }

    /* 2) 用户函数 (闭包) */
    Closure *cl = (Closure *)map_get(&rt->funcs, name);
    if (cl) {
        /* 递归深度守卫 */
        if (rt->call_depth >= CVM_MAX_CALL_DEPTH) {
            interp_err(rt, line, "递归深度超过上限 (%d)", CVM_MAX_CALL_DEPTH);
            return val_nil();
        }
        rt->call_depth++;
        Stmt *fn = cl->fn;
        if (argc != fn->u.func.pcount) {
            interp_err(rt, line, "函数 '%s' 期望 %d 个参数, 收到 %d",
                       name, fn->u.func.pcount, argc);
            rt->call_depth--;
            return val_nil();
        }
        Env *fen = env_new(cl->capenv, &rt->arena);  /* 关键: 父链 = 闭包捕获环境 */
        for (int i = 0; i < argc; ++i)
            env_define(fen, fn->u.func.params[i], eval_expr(rt, env, args[i]), &rt->arena);
        if (rt->has_error || rt->has_throw) { env_free(fen); rt->call_depth--; return val_nil(); }
        rt->return_flag = 0;
        exec_stmt(rt, fen, fn->u.func.body);
        Value r = rt->return_flag ? rt->return_value : val_nil();
        rt->return_flag = 0;
        env_free(fen);
        rt->call_depth--;
        return r;
    }

    /* 3) FFI 外部函数 (默认拒绝 + 类型化签名封送) */
    const char *sig = (const char *)map_get(&rt->ffi_sigs, name);
    void *fp = ffi_resolve_allowed(rt, name);  /* v1.1: 先校验 operator 白名单 */
    if (rt->has_error) return val_nil();       /* ffi_resolve_allowed 已设 errbuf (未授权/未启用) */
    if (fp) {
        if (!rt->ffi_enabled) {
            interp_err(rt, line, "FFI 已禁用 (ffi_enabled=0)");
            return val_nil();
        }
        if (!sig || sig[0] == '\0') {
            interp_err(rt, line, "FFI 符号未声明签名: %s", name);
            return val_nil();
        }
        /* 解析签名 (兼容两种写法, 消除文档歧义):
         *   "s)i"  -> 参数 s, 返回 i   (params)return 形式, 例见 strlen)
         *   "is"   -> 返回 i, 参数 s   (首字符=返回, 其后=参数; spec 正文描述)
         * 二者等价, 引擎自动按是否含 ')' 判定。 */
        const char *rp = strchr(sig, ')');
        int nparams, pbase;
        if (rp) {
            nparams = (int)(rp - sig);
            if (rp[1] == '\0') {
                interp_err(rt, line, "FFI 签名无效 (')' 后缺返回类型): %s", name);
                return val_nil();
            }
            pbase = 0;
        } else {
            if (sig[0] == '\0') {
                interp_err(rt, line, "FFI 签名无效 (空签名): %s", name);
                return val_nil();
            }
            pbase = 1;
            nparams = (int)strlen(sig) - 1;
        }
        if (nparams < 0) nparams = 0;
        if (nparams > 6) {
            interp_err(rt, line, "FFI 暂不支持超过 6 个参数: %s", name);
            return val_nil();
        }
        if (argc != nparams) {
            interp_err(rt, line, "FFI 函数 '%s' 签名期望 %d 个参数, 收到 %d",
                       name, nparams, argc);
            return val_nil();
        }
        CArg a[6];
        for (int i = 0; i < argc; ++i) {
            Value v = eval_expr(rt, env, args[i]);
            if (rt->has_error || rt->has_throw) return val_nil();
            a[i] = ffi_val_to_c(rt, line, v, sig[pbase + i]);
            if (rt->has_error || rt->has_throw) return val_nil();
        }
        return ffi_invoke(rt, line, fp, sig, nparams, a);
    }

    interp_err(rt, line, "未定义的函数 '%s'", name);
    return val_nil();
}

/* --------------------------- 编译/执行辅助 --------------------------- */
Program cvm_compile(Runtime *rt, const char *source, const char *name) {
    Program p; p.stmts = NULL; p.count = 0; p.cap = 0; p.has_error = 0;
    char lerr[256]; lerr[0] = '\0';
    TokenList tl = lex(&rt->arena, source, lerr, sizeof(lerr));
    if (lerr[0]) {
        snprintf(rt->errbuf, sizeof(rt->errbuf), "词法错误(%s): %s", name ? name : "?", lerr);
        rt->has_error = 1; p.has_error = 1; return p;
    }
    p = parse(&rt->arena, &tl);
    if (p.has_error) {
        snprintf(rt->errbuf, sizeof(rt->errbuf), "语法错误(%s): %s", name ? name : "?", p.err);
        rt->has_error = 1;
    }
    if (!p.has_error) cvm_collect_freevars(&rt->arena, &p);
    return p;
}

void cvm_exec_program(Runtime *rt, Program *p, Env *env) {
    for (int i = 0; i < p->count; ++i) {
        exec_stmt(rt, env, p->stmts[i]);
        if (rt->has_error) return;
        if (rt->has_throw) {
            snprintf(rt->errbuf, sizeof(rt->errbuf), "未捕获异常: %s", val_to_str(&rt->arena, rt->thrown));
            rt->has_error = 1;
            return;
        }
        if (rt->return_flag) rt->return_flag = 0;
    }
}

/* ------------------------------ 运行入口 ----------------------------- */
int rt_run(Runtime *rt, const char *source, const char *name) {
    rt->has_error = 0;
    rt->has_throw = 0;
    rt->thrown = val_nil();
    rt->errbuf[0] = '\0';
    rt->return_flag = 0;

    char lerr[256]; lerr[0] = '\0';
    TokenList tl = lex(&rt->arena, source, lerr, sizeof(lerr));
    if (lerr[0]) {
        snprintf(rt->errbuf, sizeof(rt->errbuf), "词法错误: %s", lerr);
        rt->has_error = 1;
        return -1;
    }
    Program prog = parse(&rt->arena, &tl);
    if (prog.has_error) {
        snprintf(rt->errbuf, sizeof(rt->errbuf), "语法错误: %s", prog.err);
        rt->has_error = 1;
        return -1;
    }

    /* 若程序全由字节码 VM 支持, 走寄存器解释器 (computed goto) 加速 */
    const char *force_bc = getenv("CVM_USE_BC");
    int use_bc = cvm_bc_supported(&prog);
    if (force_bc && (force_bc[0] == '1' || force_bc[0] == 'y' || force_bc[0] == 'Y')) use_bc = 1;
    if (force_bc && (force_bc[0] == '0' || force_bc[0] == 'n' || force_bc[0] == 'N')) use_bc = 0;
    if (use_bc) {
        int nbfs = 0;
        ByteFunc *bfs = cvm_bc_compile_all(rt, &prog, &nbfs);
        if (bfs && !bfs[0].unsupported) {
            cvm_bc_run(rt, &bfs[0], bfs, nbfs);
            cvm_bc_free(bfs, nbfs);
            if (rt->has_error) return -1;
            return 0;
        }
        if (bfs) cvm_bc_free(bfs, nbfs);
        /* 编译失败回退到树遍历解释器 */
        rt->has_error = 0;
        rt->has_throw = 0;
        rt->thrown = val_nil();
        rt->errbuf[0] = '\0';
    }

    cvm_collect_freevars(&rt->arena, &prog);
    /* 预注册顶层函数: 创建闭包, 支持前向引用 */
    for (int i = 0; i < prog.count; ++i)
        if (prog.stmts[i]->kind == STMT_FUNC) {
            Stmt *fn = prog.stmts[i];
            Closure *cl = (Closure *)arena_alloc(&rt->arena, sizeof(Closure));
            cl->fn = fn;
            cl->capenv = env_new(rt->global, &rt->arena);
            map_set(&rt->funcs, fn->u.func.name, cl);
        }

    Env *env = rt->global;
    for (int i = 0; i < prog.count; ++i) {
        exec_stmt(rt, env, prog.stmts[i]);
        if (rt->has_error) return -1;
        if (rt->has_throw) {
            snprintf(rt->errbuf, sizeof(rt->errbuf), "未捕获异常: %s", val_to_str(&rt->arena, rt->thrown));
            rt->has_error = 1;
            return -1;
        }
        if (rt->return_flag) rt->return_flag = 0; /* 顶层 return 忽略 */
    }
    return 0;
}

int rt_run_file(Runtime *rt, const char *path) {
    FILE *f = fopen(path, "rb");
    if (!f) { snprintf(rt->errbuf, sizeof(rt->errbuf), "无法打开文件: %s", path); rt->has_error = 1; return -1; }
    fseek(f, 0, SEEK_END); long sz = ftell(f); fseek(f, 0, SEEK_SET);
    char *buf = (char *)malloc((size_t)sz + 1);
    if (!buf) { fclose(f); abort(); }
    size_t rd = fread(buf, 1, (size_t)sz, f);
    buf[rd] = '\0';
    fclose(f);
    char saved[512];
    snprintf(saved, sizeof(saved), "%s", rt->current_file);
    snprintf(rt->current_file, sizeof(rt->current_file), "%s", path);
    int r = rt_run(rt, buf, path);
    snprintf(rt->current_file, sizeof(rt->current_file), "%s", saved);
    free(buf);
    return r;
}

/* ===================== v1.1+ 事件循环 / 定时器 ===================== */

#ifdef _WIN32
#  include <windows.h>
int64_t rt_now_ms(Runtime *rt) {
    (void)rt;
    return (int64_t)GetTickCount64();
}
#else
#  include <sys/time.h>
int64_t rt_now_ms(Runtime *rt) {
    (void)rt;
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
#endif

int rt_timer_add(Runtime *rt, const char *func_name, int delay_ms, int repeat_ms) {
    if (rt->timer_count >= 64) return -1;
    if (!rt->timer_epoch) rt->timer_epoch = rt_now_ms(rt);
    int i = rt->timer_count++;
    snprintf(rt->timers[i].name, sizeof(rt->timers[i].name), "%s", func_name);
    rt->timers[i].deadline_ms = rt_now_ms(rt) - rt->timer_epoch + delay_ms;
    rt->timers[i].repeat_ms  = repeat_ms;
    rt->timers[i].active     = 1;
    return 0;
}

int rt_process_timers(Runtime *rt) {
    if (rt->timer_count == 0) return 0;
    if (!rt->timer_epoch) return 0;
    int64_t now = rt_now_ms(rt) - rt->timer_epoch;
    int fired = 0;
    for (int i = 0; i < rt->timer_count; ++i) {
        if (!rt->timers[i].active) continue;
        if (rt->timers[i].deadline_ms > now) continue;
        /* 触发回调: 构建 func_name(argc=0) 调用串并执行 */
        char call_str[320];
        snprintf(call_str, sizeof(call_str), "%s();", rt->timers[i].name);
        rt_run(rt, call_str, "timer");
        rt->has_error = 0;  /* 定时器回调报错不应破坏事件循环 */
        fired++;
        if (rt->timers[i].repeat_ms > 0) {
            /* 重复定时器: 重设 deadline */
            rt->timers[i].deadline_ms = now + rt->timers[i].repeat_ms;
        } else {
            rt->timers[i].active = 0;
        }
    }
    return fired;
}