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

static const char *token_name(int t) {
    switch (t) {
        case TK_EOF:    return "EOF";
        case TK_NUM:    return "数字";
        case TK_STR:    return "字符串";
        case TK_IDENT:  return "标识符";
        case TK_LET:    return "let";
        case TK_IF:     return "if";
        case TK_ELSE:   return "else";
        case TK_WHILE:  return "while";
        case TK_FOR:    return "for";
        case TK_FUNC:   return "func";
    case TK_RETURN: return "return";
    case TK_BREAK:   return "break";
    case TK_CONTINUE:return "continue";
    case TK_TRUE:   return "true";
        case TK_FALSE:  return "false";
        case TK_NIL:    return "nil";
        case TK_AND:    return "and";
        case TK_OR:     return "or";
        case TK_NOT:    return "not";
        case TK_EQEQ:   return "==";
        case TK_NOTEQ:  return "!=";
        case TK_LE:     return "<=";
        case TK_GE:     return ">=";
        case TK_LT:     return "<";
        case TK_GT:     return ">";
        case TK_ASSIGN: return "=";
        case TK_PLUS:   return "+";
        case TK_MINUS:  return "-";
        case TK_STAR:   return "*";
        case TK_SLASH:  return "/";
        case TK_PERCENT:return "%";
        case TK_LPAREN: return "(";
        case TK_RPAREN: return ")";
        case TK_LBRACE: return "{";
        case TK_RBRACE: return "}";
        case TK_SEMI:   return ";";
        case TK_COMMA:  return ",";
        case TK_LBRACKET: return "[";
        case TK_RBRACKET: return "]";
        case TK_COLON:  return ":";
    case TK_DOT:    return ".";
    case TK_IN:     return "in";
    default:        return "?";
    }
}

/* --------------------------- AST 构造器 ------------------------------ */
Expr *expr_num(Arena *a, int is_int, int64_t ival, double fval, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_NUM; e->line = line;
    e->u.numlit.is_int = is_int;
    if (is_int) e->u.numlit.ival = ival;
    else        e->u.numlit.fval = fval;
    return e;
}
Expr *expr_str(Arena *a, char *s, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_STR; e->line = line; e->u.str = s; return e;
}
Expr *expr_bool(Arena *a, int b, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_BOOL; e->line = line; e->u.boolean = b; return e;
}
Expr *expr_nil(Arena *a, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_NIL; e->line = line; return e;
}
Expr *expr_var(Arena *a, char *name, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_VAR; e->line = line; e->u.name = name; return e;
}
Expr *expr_unary(Arena *a, int op, Expr *inner, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_UNARY; e->line = line; e->u.unary.op = op; e->u.unary.inner = inner; return e;
}
Expr *expr_binary(Arena *a, int op, Expr *l, Expr *r, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_BINARY; e->line = line;
    e->u.binary.op = op; e->u.binary.left = l; e->u.binary.right = r; return e;
}
Expr *expr_call(Arena *a, Expr *callee, Expr **args, int argc, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_CALL; e->line = line;
    e->u.call.callee = callee; e->u.call.args = args; e->u.call.argc = argc; return e;
}
Expr *expr_member(Arena *a, Expr *obj, char *name, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_MEMBER; e->line = line;
    e->u.member.obj = obj; e->u.member.name = name; return e;
}
Expr *expr_assign(Arena *a, char *name, Expr *value, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_ASSIGN; e->line = line;
    e->u.assign.name = name; e->u.assign.value = value; return e;
}
Expr *expr_index(Arena *a, Expr *obj, Expr *index, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_INDEX; e->line = line;
    e->u.idx.obj = obj; e->u.idx.index = index; return e;
}
Expr *expr_index_assign(Arena *a, Expr *target, Expr *value, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_INDEX_ASSIGN; e->line = line;
    e->u.index_assign.target = target; e->u.index_assign.value = value; return e;
}
Expr *expr_array(Arena *a, Expr **keys, Expr **vals, int *haskey, int count, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_ARRAY; e->line = line;
    e->u.array.keys = keys; e->u.array.vals = vals;
    e->u.array.haskey = haskey; e->u.array.count = count; return e;
}
Expr *expr_lambda(Arena *a, Stmt *funcDef, int line) {
    Expr *e = (Expr *)arena_alloc(a, sizeof(Expr));
    e->kind = EXPR_LAMBDA; e->line = line; e->u.lambda = funcDef; return e;
}
Stmt *stmt_let(Arena *a, char *name, Expr *init, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_LET; s->line = line; s->u.let.name = name; s->u.let.init = init; return s;
}
Stmt *stmt_assign(Arena *a, char *name, Expr *value, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_ASSIGN; s->line = line; s->u.assign.name = name; s->u.assign.value = value; return s;
}
Stmt *stmt_if(Arena *a, Expr *cond, Stmt *thenb, Stmt *elseb, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_IF; s->line = line;
    s->u.ifs.cond = cond; s->u.ifs.then_b = thenb; s->u.ifs.else_b = elseb; return s;
}
Stmt *stmt_while(Arena *a, Expr *cond, Stmt *body, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_WHILE; s->line = line; s->u.whiles.cond = cond; s->u.whiles.body = body; return s;
}
Stmt *stmt_for(Arena *a, Stmt *init, Expr *cond, Expr *step, Stmt *body, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_FOR; s->line = line;
    s->u.fors.init = init; s->u.fors.cond = cond; s->u.fors.step = step; s->u.fors.body = body; return s;
}
Stmt *stmt_for_in(Arena *a, char *var, Expr *iterable, Stmt *body, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_FOR_IN; s->line = line;
    s->u.for_in.iter_var = var; s->u.for_in.iterable = iterable; s->u.for_in.body = body; return s;
}
Stmt *stmt_break(Arena *a, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_BREAK; s->line = line; return s;
}
Stmt *stmt_continue(Arena *a, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_CONTINUE; s->line = line; return s;
}
Stmt *stmt_return(Arena *a, Expr *value, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_RETURN; s->line = line; s->u.returns.value = value; return s;
}
Stmt *stmt_block(Arena *a, Stmt **stmts, int count, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_BLOCK; s->line = line; s->u.block.stmts = stmts; s->u.block.count = count; return s;
}
Stmt *stmt_func(Arena *a, char *name, char **params, int pcount, Stmt *body, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_FUNC; s->line = line;
    s->u.func.name = name; s->u.func.params = params; s->u.func.pcount = pcount; s->u.func.body = body; return s;
}
Stmt *stmt_expr(Arena *a, Expr *e, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_EXPR; s->line = line; s->u.expr = e; return s;
}
Stmt *stmt_try(Arena *a, Stmt *body, char *catchvar, Stmt *catchbody, Stmt *finallybody, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_TRY; s->line = line;
    s->u.trys.body = body; s->u.trys.catchvar = catchvar;
    s->u.trys.catchbody = catchbody; s->u.trys.finallybody = finallybody; return s;
}
Stmt *stmt_throw(Arena *a, Expr *value, int line) {
    Stmt *s = (Stmt *)arena_alloc(a, sizeof(Stmt));
    s->kind = STMT_THROW; s->line = line; s->u.throws.value = value; return s;
}
/* 错误占位用的空语句 */
Stmt *stmt_nil(Arena *a, int line) {
    return stmt_block(a, NULL, 0, line);
}

/* ------------------------------ 解析器 ------------------------------- */
typedef struct {
    TokenList *tl;
    int        pos;
    Arena     *a;
    Program   prog;
} Parser;

static Token *peek(Parser *p) { return &p->tl->tokens[p->pos]; }
static Token *adv(Parser *p) { return &p->tl->tokens[p->pos++]; }
static int   check(Parser *p, int t) { return peek(p)->type == t; }
static int   match(Parser *p, int t) { if (check(p, t)) { adv(p); return 1; } return 0; }

static void perr(Parser *p, const char *fmt, ...) {
    va_list ap; va_start(ap, fmt);
    vsnprintf(p->prog.err, sizeof(p->prog.err), fmt, ap);
    va_end(ap);
    p->prog.has_error = 1;
}
static void expect(Parser *p, int t, const char *what) {
    if (!check(p, t)) {
        if (peek(p)->type == TK_EOF)
            perr(p, "incomplete: 期望 %s", what);
        else
            perr(p, "行 %d: 期望 %s, 但遇到 '%s'", peek(p)->line, what,
                 peek(p)->text ? peek(p)->text : token_name(peek(p)->type));
        return;
    }
    adv(p);
}

/* 顺序数组增长 */
static void stmt_push(Arena *a, Stmt ***arr, int *count, int *cap, Stmt *s) {
    if (*count == *cap) {
        int ncap = *cap ? *cap * 2 : 8;
        Stmt **na = (Stmt **)arena_alloc(a, (size_t)ncap * sizeof(Stmt *));
        if (*count) memcpy(na, *arr, (size_t)(*count) * sizeof(Stmt *));
        *arr = na; *cap = ncap;
    }
    (*arr)[(*count)++] = s;
}
static void expr_push(Arena *a, Expr ***arr, int *count, int *cap, Expr *e) {
    if (*count == *cap) {
        int ncap = *cap ? *cap * 2 : 8;
        Expr **na = (Expr **)arena_alloc(a, (size_t)ncap * sizeof(Expr *));
        if (*count) memcpy(na, *arr, (size_t)(*count) * sizeof(Expr *));
        *arr = na; *cap = ncap;
    }
    (*arr)[(*count)++] = e;
}
static void param_push(Arena *a, char ***arr, int *count, int *cap, char *s) {
    if (*count == *cap) {
        int ncap = *cap ? *cap * 2 : 4;
        char **na = (char **)arena_alloc(a, (size_t)ncap * sizeof(char *));
        if (*count) memcpy(na, *arr, (size_t)(*count) * sizeof(char *));
        *arr = na; *cap = ncap;
    }
    (*arr)[(*count)++] = s;
}

/* 前向声明 */
static Stmt *parse_statement(Parser *p);
static Expr *parse_expression(Parser *p);
static Stmt *parse_block(Parser *p);
static Stmt *parse_for_in(Parser *p);

static Expr *parse_postfix(Parser *p, Expr *e, int line) {
    while (1) {
        if (match(p, TK_LBRACKET)) {                 /* 下标 a[i] */
            Expr *idx = parse_expression(p);
            expect(p, TK_RBRACKET, "']'");
            e = expr_index(p->a, e, idx, line);
        } else if (match(p, TK_DOT)) {               /* 成员 .name (仅模块, 调用由下方统一处理) */
            if (!check(p, TK_IDENT)) { perr(p, "行 %d: '.' 后期望成员名", peek(p)->line); return e; }
            char *m = adv(p)->text;
            e = expr_member(p->a, e, m, line);
        } else if (match(p, TK_LPAREN)) {            /* 调用 f(...) / m.g(...) / a[i](...) */
            Expr **args = NULL; int argc = 0, cap = 0;
            if (!check(p, TK_RPAREN)) {
                expr_push(p->a, &args, &argc, &cap, parse_expression(p));
                while (match(p, TK_COMMA)) expr_push(p->a, &args, &argc, &cap, parse_expression(p));
            }
            expect(p, TK_RPAREN, "')'");
            e = expr_call(p->a, e, args, argc, line);
        } else {
            break;
        }
    }
    return e;
}

static Expr *parse_array_literal(Parser *p, int line) {
    /* 当前 token 已是 '[' (已 match) */
    int cap = 8;
    Expr **keys = (Expr **)arena_alloc(p->a, (size_t)cap * sizeof(Expr *));
    Expr **vals = (Expr **)arena_alloc(p->a, (size_t)cap * sizeof(Expr *));
    int  *haskey = (int *)arena_alloc(p->a, (size_t)cap * sizeof(int));
    int count = 0;
    if (!check(p, TK_RBRACKET)) {
        do {
            if (count == cap) {
                int ncap = cap * 2;
                Expr **nk = (Expr **)arena_alloc(p->a, (size_t)ncap * sizeof(Expr *));
                Expr **nv = (Expr **)arena_alloc(p->a, (size_t)ncap * sizeof(Expr *));
                int  *nh = (int *)arena_alloc(p->a, (size_t)ncap * sizeof(int));
                memcpy(nk, keys, (size_t)count * sizeof(Expr *));
                memcpy(nv, vals, (size_t)count * sizeof(Expr *));
                memcpy(nh, haskey, (size_t)count * sizeof(int));
                keys = nk; vals = nv; haskey = nh; cap = ncap;
            }
            /* 前瞻: 先解析一个表达式, 若其后紧跟 ':' 则是 "键: 值" 形式 */
            Expr *first = parse_expression(p);
            if (match(p, TK_COLON)) {
                keys[count] = first; haskey[count] = 1;
                vals[count] = parse_expression(p);
            } else {
                keys[count] = NULL;  haskey[count] = 0;
                vals[count] = first;
            }
            count++;
        } while (match(p, TK_COMMA));
    }
    expect(p, TK_RBRACKET, "']'");
    return expr_array(p->a, keys, vals, haskey, count, line);
}

static Stmt *parse_block(Parser *p);
static Expr *parse_lambda(Parser *p, int line);

static Expr *parse_primary(Parser *p) {
    Token *t = peek(p);
    if (match(p, TK_NUM)) {
        if (t->is_int) return expr_num(p->a, 1, t->inum, 0.0, t->line);
        return expr_num(p->a, 0, 0, t->num, t->line);
    }
    if (match(p, TK_STR)) return expr_str(p->a, t->text, t->line);
    if (match(p, TK_TRUE)) return expr_bool(p->a, 1, t->line);
    if (match(p, TK_FALSE)) return expr_bool(p->a, 0, t->line);
    if (match(p, TK_NIL)) return expr_nil(p->a, t->line);
    if (match(p, TK_LBRACKET)) return parse_array_literal(p, t->line);
    if (check(p, TK_FUNC)) { int line = adv(p)->line; return parse_lambda(p, line); }
    if (match(p, TK_IDENT)) {
        char *name = t->text;
        Expr *e = expr_var(p->a, name, t->line);
        return parse_postfix(p, e, t->line);
    }
    if (match(p, TK_LPAREN)) {
        Expr *e = parse_expression(p);
        expect(p, TK_RPAREN, "')'");
        return e;
    }
    perr(p, "行 %d: 意外的符号 '%s'", t->line, t->text ? t->text : token_name(t->type));
    return expr_nil(p->a, t->line);
}

static Expr *parse_unary(Parser *p) {
    Token *t = peek(p);
    if (t->type == TK_NOT || t->type == TK_MINUS) {
        adv(p);
        Expr *inner = parse_unary(p);
        return expr_unary(p->a, t->type, inner, t->line);
    }
    return parse_primary(p);
}

static Expr *parse_factor(Parser *p) {
    Expr *left = parse_unary(p);
    while (check(p, TK_STAR) || check(p, TK_SLASH) || check(p, TK_PERCENT)) {
        int op = adv(p)->type;
        Expr *right = parse_unary(p);
        left = expr_binary(p->a, op, left, right, left->line);
    }
    return left;
}
static Expr *parse_term(Parser *p) {
    Expr *left = parse_factor(p);
    while (check(p, TK_PLUS) || check(p, TK_MINUS)) {
        int op = adv(p)->type;
        Expr *right = parse_factor(p);
        left = expr_binary(p->a, op, left, right, left->line);
    }
    return left;
}
static Expr *parse_comparison(Parser *p) {
    Expr *left = parse_term(p);
    while (check(p, TK_LT) || check(p, TK_GT) || check(p, TK_LE) || check(p, TK_GE)) {
        int op = adv(p)->type;
        Expr *right = parse_term(p);
        left = expr_binary(p->a, op, left, right, left->line);
    }
    return left;
}
static Expr *parse_equality(Parser *p) {
    Expr *left = parse_comparison(p);
    while (check(p, TK_EQEQ) || check(p, TK_NOTEQ)) {
        int op = adv(p)->type;
        Expr *right = parse_comparison(p);
        left = expr_binary(p->a, op, left, right, left->line);
    }
    return left;
}
static Expr *parse_and(Parser *p) {
    Expr *left = parse_equality(p);
    while (match(p, TK_AND)) {
        Expr *right = parse_equality(p);
        left = expr_binary(p->a, TK_AND, left, right, left->line);
    }
    return left;
}
static Expr *parse_or(Parser *p) {
    Expr *left = parse_and(p);
    while (match(p, TK_OR)) {
        Expr *right = parse_and(p);
        left = expr_binary(p->a, TK_OR, left, right, left->line);
    }
    return left;
}
static Expr *parse_assignment(Parser *p) {
    Expr *left = parse_or(p);
    if (match(p, TK_ASSIGN)) {
        Expr *right = parse_assignment(p);
        if (left->kind == EXPR_VAR)
            return expr_assign(p->a, left->u.name, right, left->line);
        if (left->kind == EXPR_INDEX)
            return expr_index_assign(p->a, left, right, left->line);
        perr(p, "行 %d: 赋值目标必须是变量或数组下标", left->line);
        return left;
    }
    return left;
}
static Expr *parse_expression(Parser *p) { return parse_assignment(p); }

static Stmt *parse_let(Parser *p) {
    int line = adv(p)->line; /* LET */
    if (!check(p, TK_IDENT)) { perr(p, "行 %d: let 后期望变量名", line); return stmt_nil(p->a, line); }
    char *name = adv(p)->text;
    Expr *init = NULL;
    if (match(p, TK_ASSIGN)) init = parse_expression(p);
    expect(p, TK_SEMI, "';'");
    return stmt_let(p->a, name, init, line);
}
static Stmt *parse_assign(Parser *p) {
    int line = peek(p)->line;
    char *name = adv(p)->text; /* IDENT */
    adv(p); /* ASSIGN */
    Expr *value = parse_expression(p);
    expect(p, TK_SEMI, "';'");
    return stmt_assign(p->a, name, value, line);
}
static Stmt *parse_if(Parser *p) {
    int line = adv(p)->line; /* IF */
    expect(p, TK_LPAREN, "'('");
    Expr *cond = parse_expression(p);
    expect(p, TK_RPAREN, "')'");
    Stmt *thenb = parse_statement(p);
    Stmt *elseb = NULL;
    if (match(p, TK_ELSE)) {
        if (check(p, TK_IF)) elseb = parse_if(p);
        else elseb = parse_statement(p);
    }
    return stmt_if(p->a, cond, thenb, elseb, line);
}
static Stmt *parse_while(Parser *p) {
    int line = adv(p)->line; /* WHILE */
    expect(p, TK_LPAREN, "'('");
    Expr *cond = parse_expression(p);
    expect(p, TK_RPAREN, "')'");
    Stmt *body = parse_statement(p);
    return stmt_while(p->a, cond, body, line);
}
static Stmt *parse_for(Parser *p) {
    int line = adv(p)->line; /* FOR */
    /* 判断: for(...) 是 C-style, for IDENT in ... 是 for-in */
    if (!check(p, TK_LPAREN)) return parse_for_in(p);
    expect(p, TK_LPAREN, "'('");
    Stmt *init = NULL; Expr *cond = NULL; Expr *step = NULL;
    if (match(p, TK_LET)) {
        char *name = adv(p)->text;
        Expr *v = NULL;
        if (match(p, TK_ASSIGN)) v = parse_expression(p);
        init = stmt_let(p->a, name, v, line);
        expect(p, TK_SEMI, "';'");
    } else if (!match(p, TK_SEMI)) {
        Expr *e = parse_expression(p);
        init = stmt_expr(p->a, e, line);
        expect(p, TK_SEMI, "';'");
    }
    if (!match(p, TK_SEMI)) { cond = parse_expression(p); expect(p, TK_SEMI, "';'"); }
    if (!match(p, TK_RPAREN)) { step = parse_expression(p); expect(p, TK_RPAREN, "')'"); }
    Stmt *body = parse_statement(p);
    return stmt_for(p->a, init, cond, step, body, line);
}
static Stmt *parse_return(Parser *p) {
    int line = adv(p)->line; /* RETURN */
    Expr *v = NULL;
    if (!match(p, TK_SEMI)) { v = parse_expression(p); expect(p, TK_SEMI, "';'"); }
    return stmt_return(p->a, v, line);
}
static Stmt *parse_break(Parser *p) {
    int line = adv(p)->line;
    expect(p, TK_SEMI, "';' after break");
    return stmt_break(p->a, line);
}
static Stmt *parse_continue(Parser *p) {
    int line = adv(p)->line;
    expect(p, TK_SEMI, "';' after continue");
    return stmt_continue(p->a, line);
}
static Stmt *parse_for_in(Parser *p) {
    /* FOR 已由 parse_for 消费; 此处光标位于迭代变量名 */
    int line = peek(p)->line;
    /* for-in: for IDENT in expr statement (无括号) */
    if (!check(p, TK_IDENT)) { perr(p, "行 %d: for-in 后期望变量名", line); return stmt_nil(p->a, line); }
    char *var = adv(p)->text;
    if (!match(p, TK_IN)) { perr(p, "行 %d: for-in 期望 'in'", peek(p)->line); return stmt_nil(p->a, line); }
    Expr *iterable = parse_expression(p);
    Stmt *body = parse_statement(p);
    return stmt_for_in(p->a, var, iterable, body, line);
}
static Expr *parse_lambda(Parser *p, int line) {
    expect(p, TK_LPAREN, "'('");
    char **params = NULL; int pcount = 0, pcap = 0;
    if (!check(p, TK_RPAREN)) {
        if (!check(p, TK_IDENT)) { perr(p, "行 %d: 参数应为标识符", line); }
        else {
            param_push(p->a, &params, &pcount, &pcap, adv(p)->text);
            while (match(p, TK_COMMA)) param_push(p->a, &params, &pcount, &pcap, adv(p)->text);
        }
    }
    expect(p, TK_RPAREN, "')'");
    Stmt *body = parse_block(p);
    Stmt *func = stmt_func(p->a, NULL, params, pcount, body, line);
    return expr_lambda(p->a, func, line);
}

static Stmt *parse_func(Parser *p) {
    int line = adv(p)->line; /* FUNC */
    if (!check(p, TK_IDENT)) { perr(p, "行 %d: func 后期望函数名", line); return stmt_nil(p->a, line); }
    char *name = adv(p)->text;
    expect(p, TK_LPAREN, "'('");
    char **params = NULL; int pcount = 0, pcap = 0;
    if (!check(p, TK_RPAREN)) {
        if (!check(p, TK_IDENT)) { perr(p, "行 %d: 参数应为标识符", line); }
        else {
            param_push(p->a, &params, &pcount, &pcap, adv(p)->text);
            while (match(p, TK_COMMA)) param_push(p->a, &params, &pcount, &pcap, adv(p)->text);
        }
    }
    expect(p, TK_RPAREN, "')'");
    Stmt *body = parse_block(p);
    return stmt_func(p->a, name, params, pcount, body, line);
}
static Stmt *parse_block(Parser *p) {
    int line = adv(p)->line; /* LBRACE */
    Stmt **stmts = NULL; int count = 0, cap = 0;
    while (!check(p, TK_RBRACE) && !check(p, TK_EOF)) {
        stmt_push(p->a, &stmts, &count, &cap, parse_statement(p));
        if (p->prog.has_error) break;
    }
    expect(p, TK_RBRACE, "'}'");
    return stmt_block(p->a, stmts, count, line);
}

static Stmt *parse_try(Parser *p) {
    int line = adv(p)->line; /* TRY */
    if (!check(p, TK_LBRACE)) { perr(p, "行 %d: try 后期望 '{'", line); return stmt_nil(p->a, line); }
    Stmt *body = parse_block(p);
    char *catchvar = NULL;
    Stmt *catchbody = NULL;
    Stmt *finallybody = NULL;
    if (check(p, TK_CATCH)) {
        adv(p); /* CATCH */
        if (match(p, TK_LPAREN)) {
            if (!check(p, TK_IDENT)) { perr(p, "行 %d: catch 后期望变量名", peek(p)->line); }
            else catchvar = adv(p)->text;
            expect(p, TK_RPAREN, "')'");
        }
        if (!check(p, TK_LBRACE)) { perr(p, "行 %d: catch 后期望 '{'", peek(p)->line); return stmt_nil(p->a, line); }
        catchbody = parse_block(p);
    }
    if (check(p, TK_FINALLY)) {
        adv(p); /* FINALLY */
        if (!check(p, TK_LBRACE)) { perr(p, "行 %d: finally 后期望 '{'", peek(p)->line); return stmt_nil(p->a, line); }
        finallybody = parse_block(p);
    }
    if (!catchbody && !finallybody) {
        perr(p, "行 %d: try 需要 catch 或 finally", line);
        return stmt_nil(p->a, line);
    }
    return stmt_try(p->a, body, catchvar, catchbody, finallybody, line);
}
static Stmt *parse_throw(Parser *p) {
    int line = adv(p)->line; /* THROW */
    Expr *v = NULL;
    if (!check(p, TK_SEMI)) { v = parse_expression(p); expect(p, TK_SEMI, "';' after throw 表达式"); }
    return stmt_throw(p->a, v, line);
}
static Stmt *parse_statement(Parser *p) {
    if (p->prog.has_error) return stmt_nil(p->a, peek(p)->line);
    if (check(p, TK_LET))   return parse_let(p);
    if (check(p, TK_IF))    return parse_if(p);
    if (check(p, TK_WHILE)) return parse_while(p);
    if (check(p, TK_FOR))   return parse_for(p);
    if (check(p, TK_RETURN))return parse_return(p);
    if (check(p, TK_BREAK))  return parse_break(p);
    if (check(p, TK_CONTINUE)) return parse_continue(p);
    if (check(p, TK_FUNC))  return parse_func(p);
    if (check(p, TK_TRY))   return parse_try(p);
    if (check(p, TK_THROW)) return parse_throw(p);
    if (check(p, TK_LBRACE))return parse_block(p);
    /* 赋值语句: IDENT = ... */
    if (check(p, TK_IDENT) && p->pos + 1 < p->tl->count &&
        p->tl->tokens[p->pos + 1].type == TK_ASSIGN) return parse_assign(p);
    /* 表达式语句 */
    Expr *e = parse_expression(p);
    expect(p, TK_SEMI, "';'");
    return stmt_expr(p->a, e, peek(p)->line);
}

Program parse(Arena *a, TokenList *tl) {
    Parser p; p.tl = tl; p.pos = 0; p.a = a;
    p.prog.stmts = NULL; p.prog.count = 0; p.prog.cap = 0; p.prog.has_error = 0;
    while (!check(&p, TK_EOF)) {
        stmt_push(a, &p.prog.stmts, &p.prog.count, &p.prog.cap, parse_statement(&p));
        if (p.prog.has_error) break;
    }
    return p.prog;
}