stage1 修复错误 提供类型检查

This commit is contained in:
zzy
2026-07-25 22:48:35 +08:00
parent 02095524b1
commit 89d4bae8db
6 changed files with 219 additions and 17 deletions

View File

@@ -465,7 +465,7 @@ static void parse_one_field_init(spl_comp_t *ctx, spl_type_item_vec_t *items, in
}
}
if (!found) {
spl_comp_error(ctx, "unknown field '%s' in struct literal", fname);
spl_comp_err_tok(ctx, ftok, "unknown field '%s' in struct literal", fname);
}
}
@@ -794,6 +794,16 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
if (peek(ctx)->type == TOK_L_PAREN) {
int fi = spl_lookup_func(ctx, name);
if (fi < 0) {
/* Not a known function — check if it's a function pointer variable */
spl_var_info_t *v = spl_lookup_var(ctx, name);
if (v && v->type_idx >= 0 && spl_type_kind(&ctx->tctx, v->type_idx) == TYPE_FN) {
/* Load function pointer value, let postfix handle the call */
int vt_idx = v->type_idx;
emit_laddr(&ctx->emit, v->offset);
emit_load_ptr(&ctx->emit);
spl_expr_result_t r = {vt_idx, 0};
return r;
}
spl_comp_err_tok(ctx, t, "unknown function '%s'", name);
spl_expr_result_t r = {-1, 0};
return r;
@@ -802,7 +812,16 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
advance(ctx);
int nargs = parse_call_args_checked(ctx, f->name, f->param_type_indices, f->nparams);
if (!expect(ctx, TOK_R_PAREN)) {
if (!ctx->has_error && nargs < f->nparams) {
spl_comp_err_tok(ctx, peek(ctx), "too few arguments to '%s': expected %d, got %d",
f->name, f->nparams, nargs);
}
if (!ctx->has_error) {
if (!expect(ctx, TOK_R_PAREN)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
} else {
spl_expr_result_t _r = {-1, 0};
return _r;
}
@@ -854,6 +873,21 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
return r;
}
/* Function reference (not a call): get function address */
{
int fi = spl_lookup_func(ctx, name);
if (fi >= 0) {
spl_func_info_t *f = &vec_at(ctx->funcs, fi);
if (!f->is_extern) {
emit_push_u64(&ctx->emit, f->func_idx);
int fn_ptr_type =
spl_type_fn(&ctx->tctx, spl_type_basic(&ctx->tctx, SPL_USIZE), f->ret_type_idx);
spl_expr_result_t r = {fn_ptr_type, 1};
return r;
}
}
}
int ttype_idx = spl_type_resolve(&ctx->tctx, name);
if (ttype_idx >= 0) {
if (peek(ctx)->type == TOK_L_BRACE &&
@@ -873,8 +907,10 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
static spl_expr_result_t parse_group(spl_comp_t *ctx) {
advance(ctx);
spl_expr_result_t r = spl_parse_expr(ctx, PREC_MIN);
if (!expect(ctx, TOK_R_PAREN))
return r;
if (!ctx->has_error) {
if (!expect(ctx, TOK_R_PAREN))
return r;
}
return r;
}
@@ -910,6 +946,9 @@ static spl_expr_result_t parse_prefix_op(spl_comp_t *ctx) {
emit_binop(&ctx->emit, SPL_NOT, spl_type_emit_type(&ctx->tctx, right.type_idx));
break;
case TOK_AND:
if (right.type_idx >= 0 && spl_type_kind(&ctx->tctx, right.type_idx) == TYPE_FN) {
return right;
}
if (!right.is_lvalue) {
spl_comp_err_tok(ctx, peek(ctx), "cannot take address of rvalue");
spl_expr_result_t _r = {-1, 0};
@@ -995,7 +1034,12 @@ static spl_expr_result_t parse_primary_expr(spl_comp_t *ctx) {
if (peek(ctx)->type == TOK_L_PAREN) {
advance(ctx);
int nargs = parse_call_args(ctx);
if (!expect(ctx, TOK_R_PAREN)) {
if (!ctx->has_error) {
if (!expect(ctx, TOK_R_PAREN)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
} else {
spl_expr_result_t _r = {-1, 0};
return _r;
}
@@ -1015,7 +1059,12 @@ static spl_expr_result_t parse_primary_expr(spl_comp_t *ctx) {
return _r;
}
int ti = spl_type_parse(&ctx->tctx, ctx);
if (!expect(ctx, TOK_R_PAREN)) {
if (!ctx->has_error) {
if (!expect(ctx, TOK_R_PAREN)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
} else {
spl_expr_result_t _r = {-1, 0};
return _r;
}
@@ -1112,11 +1161,26 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
}
{
int *cp = func->param_type_indices;
int cn = func->nparams;
nargs += parse_call_args_checked(ctx, func->name, cp, cn);
int full_np = func->nparams;
nargs += parse_call_args_checked(ctx, func->name,
func->param_type_indices, full_np);
if (is_instance && !ctx->has_error) {
int ok =
(nargs >= full_np) || (nargs == full_np - 1 && full_np == 1);
if (!ok) {
spl_comp_err_tok(
ctx, peek(ctx),
"too few arguments to '%s': expected %d, got %d",
func->name, full_np, nargs);
}
}
}
if (!expect(ctx, TOK_R_PAREN)) {
if (!ctx->has_error) {
if (!expect(ctx, TOK_R_PAREN)) {
spl_expr_result_t _r = left;
return _r;
}
} else {
spl_expr_result_t _r = left;
return _r;
}
@@ -1142,6 +1206,48 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
}
if (found_method)
continue;
/* Indirect call through function pointer: fn_ptr(args) */
if (left.type_idx >= 0 && peek(ctx)->type == TOK_L_PAREN &&
spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_FN) {
advance(ctx); /* ( */
int nargs = parse_call_args(ctx);
if (!ctx->has_error) {
if (!expect(ctx, TOK_R_PAREN)) {
spl_expr_result_t _r = left;
return _r;
}
} else {
spl_expr_result_t _r = left;
return _r;
}
/* If left is lvalue, load the function address value first */
if (left.is_lvalue) {
emit_load_ptr(&ctx->emit);
}
/* Stack currently: [args..., func_addr].
* CALLI expects: POP addr, POP nargs, call(addr, nargs).
* After all args are on stack: push nargs, push func_addr.
* But func_addr is already below args? No — we need:
* Stack: [..., func_addr, arg0, ..., argN-1]
* CALLI: POP addr, POP nargs, call(addr, nargs)
* Actually CALLI pops: TOS=addr, TOS-1=nargs.
* So we need: [args..., nargs, addr]
* But currently: [args..., addr] (addr is on TOS, loaded above)
* Push nargs ABOVE addr, then CALLI pops addr, then nargs:
* Stack: [args..., nargs, addr]
* TOS=addr → POP returns addr, then POP returns nargs. ✓ */
emit_push_u64(&ctx->emit, nargs);
emit_raw(&ctx->emit, SPL_CALLI, SPL_VOID, 0);
/* For now, result type is void — we don't know the return type from fn ptr */
left = (spl_expr_result_t){spl_type_basic(&ctx->tctx, SPL_VOID), 0};
continue;
}
}
if (left.type_idx >= 0 && spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_STRUCT) {