stage1 修复错误 提供类型检查

This commit is contained in:
zzy
2026-07-25 10:28:24 +08:00
parent da9dae734c
commit 02095524b1
10 changed files with 640 additions and 153 deletions

View File

@@ -93,7 +93,12 @@ static int spl_resolve_type_member(spl_comp_t *ctx, int type_idx, const char *fi
continue;
if (strcmp(it->name, field) == 0) {
emit_push_i32(&ctx->emit, it->enum_field.value);
*result = (spl_expr_result_t){type_idx, 0};
int data_type = it->enum_field.type_idx;
if (data_type >= 0) {
*result = (spl_expr_result_t){data_type, 0};
} else {
*result = (spl_expr_result_t){type_idx, 0};
}
return 1;
}
}
@@ -278,14 +283,17 @@ static spl_expr_result_t parse_array_literal(spl_comp_t *ctx) {
int len_val;
if (!spl_parse_int_literal(ctx, &len_val)) {
spl_comp_error(ctx, "expected array length");
spl_comp_err_tok(ctx, peek(ctx), "expected array length");
spl_expr_result_t r = {-1, 0};
return r;
}
usize len = (usize)len_val;
skip_nl(ctx);
expect(ctx, TOK_R_BRACKET);
if (!expect(ctx, TOK_R_BRACKET)) {
spl_expr_result_t r = {-1, 0};
return r;
}
skip_nl(ctx);
int elem_type_idx = spl_type_parse(&ctx->tctx, ctx);
@@ -295,7 +303,10 @@ static spl_expr_result_t parse_array_literal(spl_comp_t *ctx) {
}
skip_nl(ctx);
expect(ctx, TOK_L_BRACE);
if (!expect(ctx, TOK_L_BRACE)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
skip_nl(ctx);
for (usize i = 0; i < len; i++) {
@@ -311,7 +322,10 @@ static spl_expr_result_t parse_array_literal(spl_comp_t *ctx) {
advance(ctx);
skip_nl(ctx);
expect(ctx, TOK_R_BRACE);
if (!expect(ctx, TOK_R_BRACE)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
int arr_type_idx = spl_type_array(&ctx->tctx, elem_type_idx, len);
return (spl_expr_result_t){arr_type_idx, 0};
@@ -320,7 +334,8 @@ static spl_expr_result_t parse_array_literal(spl_comp_t *ctx) {
static void parse_slice_inline(spl_comp_t *ctx) {
advance(ctx);
skip_nl(ctx);
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
skip_nl(ctx);
while (!ctx->has_error && peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
if (peek(ctx)->type == TOK_COMMA) {
advance(ctx);
skip_nl(ctx);
@@ -347,7 +362,8 @@ static void parse_slice_inline(spl_comp_t *ctx) {
}
skip_nl(ctx);
}
expect(ctx, TOK_R_BRACE);
if (!expect(ctx, TOK_R_BRACE))
return;
emit_drop(&ctx->emit);
}
@@ -363,11 +379,13 @@ static void parse_one_field_init(spl_comp_t *ctx, spl_type_item_vec_t *items, in
advance(ctx);
skip_nl(ctx);
int found = 0;
vec_for(*items, fi) {
spl_type_item_t *it = &vec_at(*items, fi);
if (it->item_kind != ITEM_FIELD)
continue;
if (strcmp(it->name, fname) == 0) {
found = 1;
emit_laddr(&ctx->emit, base_offset);
usize byte_off = extra_offset + it->aggregate_field.offset;
emit_ptr_add(&ctx->emit, byte_off);
@@ -381,16 +399,17 @@ static void parse_one_field_init(spl_comp_t *ctx, spl_type_item_vec_t *items, in
skip_nl(ctx);
int len_val;
if (!spl_parse_int_literal(ctx, &len_val)) {
spl_comp_error(ctx, "expected array length");
spl_comp_err_tok(ctx, peek(ctx), "expected array length");
return;
}
usize arr_len = (usize)len_val;
skip_nl(ctx);
expect(ctx, TOK_R_BRACKET);
if (!expect(ctx, TOK_R_BRACKET))
return;
skip_nl(ctx);
int elem_type_idx = spl_type_parse(&ctx->tctx, ctx);
skip_nl(ctx);
expect(ctx, TOK_L_BRACE);
int elem_type_idx = spl_type_elem_type(&ctx->tctx, ft_idx);
if (!expect(ctx, TOK_L_BRACE))
return;
skip_nl(ctx);
usize stride = spl_type_elem_stride(&ctx->tctx, elem_type_idx);
spl_type_t st = spl_type_emit_type(&ctx->tctx, elem_type_idx);
@@ -417,7 +436,8 @@ static void parse_one_field_init(spl_comp_t *ctx, spl_type_item_vec_t *items, in
if (peek(ctx)->type == TOK_COMMA)
advance(ctx);
skip_nl(ctx);
expect(ctx, TOK_R_BRACE);
if (!expect(ctx, TOK_R_BRACE))
return;
emit_drop(&ctx->emit);
} else if (ft_idx >= 0 &&
(spl_type_kind(&ctx->tctx, ft_idx) == TYPE_STRUCT ||
@@ -444,6 +464,9 @@ static void parse_one_field_init(spl_comp_t *ctx, spl_type_item_vec_t *items, in
break;
}
}
if (!found) {
spl_comp_error(ctx, "unknown field '%s' in struct literal", fname);
}
}
spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx) {
@@ -454,7 +477,7 @@ spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx) {
skip_nl(ctx);
if (spl_type_kind(&ctx->tctx, type_idx) == TYPE_STRUCT) {
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
while (!ctx->has_error && peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
if (peek(ctx)->type == TOK_COMMA) {
advance(ctx);
skip_nl(ctx);
@@ -470,14 +493,8 @@ spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx) {
skip_nl(ctx);
}
} else if (spl_type_kind(&ctx->tctx, type_idx) == TYPE_SLICE) {
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
if (peek(ctx)->type == TOK_COMMA) {
advance(ctx);
skip_nl(ctx);
continue;
}
if (peek(ctx)->type == TOK_DOT)
advance(ctx);
while (!ctx->has_error && peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
advance(ctx);
spl_tok_t *ftok = advance(ctx);
char fname[256];
spl_tok_copy_name(ftok, fname, sizeof(fname));
@@ -535,7 +552,8 @@ spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx) {
peek(ctx)->type == TOK_L_BRACE) {
advance(ctx);
skip_nl(ctx);
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
while (!ctx->has_error && peek(ctx)->type != TOK_R_BRACE &&
peek(ctx)->type != TOK_EOF) {
if (peek(ctx)->type == TOK_COMMA) {
advance(ctx);
skip_nl(ctx);
@@ -547,7 +565,10 @@ spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx) {
base_offset, DATA_OFFSET);
skip_nl(ctx);
}
expect(ctx, TOK_R_BRACE);
if (!expect(ctx, TOK_R_BRACE)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
} else if (dt_idx >= 0 &&
(spl_type_kind(&ctx->tctx, dt_idx) == TYPE_STRUCT ||
spl_type_kind(&ctx->tctx, dt_idx) == TYPE_ENUM) &&
@@ -577,11 +598,14 @@ spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx) {
}
}
if (!found)
spl_comp_error(ctx, "unknown enum variant '%s'", vname);
spl_comp_err_tok(ctx, vtok, "unknown enum variant '%s'", vname);
}
skip_nl(ctx);
expect(ctx, TOK_R_BRACE);
if (!expect(ctx, TOK_R_BRACE)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
if (sz <= sizeof(spl_val_t)) {
emit_laddr(&ctx->emit, base_offset);
@@ -596,7 +620,7 @@ spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, int type_idx) {
static int parse_call_args(spl_comp_t *ctx) {
int nargs = 0;
if (peek(ctx)->type != TOK_R_PAREN) {
for (;;) {
while (!ctx->has_error) {
spl_parse_expr(ctx, PREC_MIN);
nargs++;
if (peek(ctx)->type == TOK_COMMA) {
@@ -708,8 +732,8 @@ static void spl_check_arg_type(spl_comp_t *ctx, const char *fname, int arg_type_
type_mismatch:;
const char *as = spl_type_str(&ctx->tctx, arg_type_idx);
const char *ps = spl_type_str(&ctx->tctx, param_type_idx);
spl_comp_error(ctx, "argument %d of '%s' type mismatch: expected '%s', got '%s'", arg_idx + 1,
fname, ps, as);
spl_comp_err_tok(ctx, peek(ctx), "argument %d of '%s' type mismatch: expected '%s', got '%s'",
arg_idx + 1, fname, ps, as);
}
static int parse_call_args_checked(spl_comp_t *ctx, const char *fname, int *param_type_indices,
@@ -717,11 +741,20 @@ static int parse_call_args_checked(spl_comp_t *ctx, const char *fname, int *para
int nargs = 0;
int nlogical = 0;
if (peek(ctx)->type != TOK_R_PAREN) {
for (;;) {
while (!ctx->has_error) {
spl_expr_result_t arg = spl_parse_expr(ctx, PREC_MIN);
if (param_type_indices && nlogical < nparams && param_type_indices[nlogical] >= 0)
if (param_type_indices && nlogical < nparams && param_type_indices[nlogical] >= 0) {
int param_u = spl_type_resolve_underlying(&ctx->tctx, param_type_indices[nlogical]);
int arg_u = spl_type_resolve_underlying(&ctx->tctx, arg.type_idx);
if (arg.type_idx >= 0 && spl_type_kind(&ctx->tctx, param_u) == TYPE_BASIC &&
spl_type_is_integer(spl_type_basic_type(&ctx->tctx, param_u)) &&
spl_type_kind(&ctx->tctx, arg_u) == TYPE_BASIC &&
spl_type_is_integer(spl_type_basic_type(&ctx->tctx, arg_u))) {
arg.type_idx = param_type_indices[nlogical];
}
spl_check_arg_type(ctx, fname, arg.type_idx, param_type_indices[nlogical],
nlogical);
}
int arg_slots = 1;
if (param_type_indices && nlogical < nparams && param_type_indices[nlogical] >= 0 &&
@@ -761,7 +794,7 @@ 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) {
spl_comp_error(ctx, "unknown function '%s'", name);
spl_comp_err_tok(ctx, t, "unknown function '%s'", name);
spl_expr_result_t r = {-1, 0};
return r;
}
@@ -769,12 +802,19 @@ 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);
expect(ctx, TOK_R_PAREN);
if (!expect(ctx, TOK_R_PAREN)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
if (f->is_extern) {
int nidx = spl_ensure_native(ctx, f->name);
emit_push_i32(&ctx->emit, nidx);
emit_ncall(&ctx->emit, nargs);
if (spl_type_kind(&ctx->tctx, f->ret_type_idx) == TYPE_BASIC &&
spl_type_basic_type(&ctx->tctx, f->ret_type_idx) == SPL_VOID) {
emit_drop(&ctx->emit);
}
} else {
emit_call_with_fixup(&ctx->emit, nargs, f->func_idx);
}
@@ -805,7 +845,12 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
emit_laddr(&ctx->emit, v->offset);
spl_expr_result_t r;
emit_load_or_addr_type(ctx, &r, vt_idx);
spl_tok_type_t next_type = peek(ctx)->type;
if (next_type == TOK_DOT) {
r = (spl_expr_result_t){vt_idx, 1};
} else {
emit_load_or_addr_type(ctx, &r, vt_idx);
}
return r;
}
@@ -820,7 +865,7 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
return r;
}
spl_comp_error(ctx, "undefined variable '%s'", name);
spl_comp_err_tok(ctx, t, "undefined variable '%s'", name);
spl_expr_result_t r = {-1, 0};
return r;
}
@@ -828,7 +873,8 @@ 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);
expect(ctx, TOK_R_PAREN);
if (!expect(ctx, TOK_R_PAREN))
return r;
return r;
}
@@ -865,7 +911,9 @@ static spl_expr_result_t parse_prefix_op(spl_comp_t *ctx) {
break;
case TOK_AND:
if (!right.is_lvalue) {
spl_comp_error(ctx, "cannot take address of rvalue");
spl_comp_err_tok(ctx, peek(ctx), "cannot take address of rvalue");
spl_expr_result_t _r = {-1, 0};
return _r;
}
right.type_idx = spl_type_ptr(&ctx->tctx, right.type_idx);
break;
@@ -935,7 +983,7 @@ static spl_expr_result_t parse_primary_expr(spl_comp_t *ctx) {
skip_nl(ctx);
tok = peek(ctx);
if (!tok || tok->type != TOK_IDENT) {
spl_comp_error(ctx, "expected builtin name after '@'");
spl_comp_err_tok(ctx, tok, "expected builtin name after '@'");
spl_expr_result_t r = {-1, 0};
return r;
}
@@ -947,7 +995,10 @@ 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);
expect(ctx, TOK_R_PAREN);
if (!expect(ctx, TOK_R_PAREN)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
for (int i = 0; i < nargs; i++) {
emit_dbg_usize(&ctx->emit);
emit_drop(&ctx->emit);
@@ -959,11 +1010,17 @@ static spl_expr_result_t parse_primary_expr(spl_comp_t *ctx) {
}
return (spl_expr_result_t){spl_type_basic(&ctx->tctx, SPL_VOID), 0};
} else if (strcmp(bname, "sizeof") == 0) {
expect(ctx, TOK_L_PAREN);
if (!expect(ctx, TOK_L_PAREN)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
int ti = spl_type_parse(&ctx->tctx, ctx);
expect(ctx, TOK_R_PAREN);
if (!expect(ctx, TOK_R_PAREN)) {
spl_expr_result_t _r = {-1, 0};
return _r;
}
if (ti < 0) {
spl_comp_error(ctx, "@sizeof: invalid type");
spl_comp_err_tok(ctx, peek(ctx), "@sizeof: invalid type");
spl_expr_result_t r = {-1, 0};
return r;
}
@@ -971,13 +1028,13 @@ static spl_expr_result_t parse_primary_expr(spl_comp_t *ctx) {
emit_push_usize(&ctx->emit, sz);
return (spl_expr_result_t){spl_type_basic(&ctx->tctx, SPL_USIZE), 0};
} else {
spl_comp_error(ctx, "unknown builtin '@%s'", bname);
spl_comp_err_tok(ctx, peek(ctx), "unknown builtin '@%s'", bname);
spl_expr_result_t r = {-1, 0};
return r;
}
}
default:
if (peek(ctx)->type >= KW_AS && peek(ctx)->type <= KW_ANY) {
if (peek(ctx)->type > KW_AS && peek(ctx)->type <= KW_ANY) {
return parse_ident(ctx);
}
spl_expr_result_t r = {-1, 0};
@@ -990,6 +1047,8 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
return left;
for (;;) {
if (ctx->has_error)
break;
skip_nl(ctx);
spl_tok_type_t opt = peek(ctx)->type;
@@ -1044,8 +1103,9 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
if (is_instance) {
if (!left.is_lvalue && !is_ptr_self) {
spl_comp_error(ctx, "cannot call instance method '%s' on type",
fname);
spl_comp_err_tok(ctx, field,
"cannot call instance method '%s' on type", fname);
return left;
}
emit_drop(&ctx->emit);
nargs = 0;
@@ -1056,7 +1116,10 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
int cn = func->nparams;
nargs += parse_call_args_checked(ctx, func->name, cp, cn);
}
expect(ctx, TOK_R_PAREN);
if (!expect(ctx, TOK_R_PAREN)) {
spl_expr_result_t _r = left;
return _r;
}
if (func->func_idx < 0) {
fprintf(stderr, "WARN: method call '%s.' with invalid func_idx=%d\n",
@@ -1083,6 +1146,7 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
if (left.type_idx >= 0 && spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_STRUCT) {
spl_type_item_vec_t *f_items = spl_type_items(&ctx->tctx, left.type_idx);
int found = 0;
vec_for(*f_items, fi) {
spl_type_item_t *fit = &vec_at(*f_items, fi);
if (fit->item_kind != ITEM_FIELD)
@@ -1090,10 +1154,12 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
if (strcmp(fit->name, fname) == 0) {
emit_ptr_add(&ctx->emit, fit->aggregate_field.offset);
emit_load_or_addr_type(ctx, &left, fit->aggregate_field.type_idx);
found = 1;
break;
}
}
continue;
if (found)
continue;
}
if (left.type_idx >= 0 && spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_PTR) {
@@ -1103,6 +1169,7 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
emit_load_ptr(&ctx->emit);
}
spl_type_item_vec_t *st_items = spl_type_items(&ctx->tctx, elem_idx);
int found = 0;
vec_for(*st_items, si) {
spl_type_item_t *sit = &vec_at(*st_items, si);
if (sit->item_kind != ITEM_FIELD)
@@ -1110,10 +1177,12 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
if (strcmp(sit->name, fname) == 0) {
emit_ptr_add(&ctx->emit, sit->aggregate_field.offset);
emit_load_or_addr_type(ctx, &left, sit->aggregate_field.type_idx);
found = 1;
break;
}
}
continue;
if (found)
continue;
}
}
@@ -1159,7 +1228,7 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
continue;
}
spl_comp_error(ctx, "unknown field '%s'", fname);
spl_comp_err_tok(ctx, field, "unknown field '%s'", fname);
continue;
}
@@ -1186,7 +1255,8 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
ctx->addr_of_mode = saved_aom;
}
(void)end_expr;
expect(ctx, TOK_R_BRACKET);
if (!expect(ctx, TOK_R_BRACKET))
return left;
if (!has_explicit_end) {
if (left.type_idx >= 0 &&
@@ -1235,7 +1305,8 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
continue;
}
expect(ctx, TOK_R_BRACKET);
if (!expect(ctx, TOK_R_BRACKET))
break;
if (left.type_idx >= 0 && (spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_ARRAY ||
spl_type_kind(&ctx->tctx, left.type_idx) == TYPE_PTR ||
@@ -1304,8 +1375,7 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
spl_expr_result_t left = parse_primary_expr(ctx);
if (left.type_idx < 0)
return left;
while (1) {
while (!ctx->has_error) {
left = parse_postfix_expr(ctx, left);
skip_nl(ctx);
@@ -1378,8 +1448,8 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp
spl_parse_expr(ctx, next_prec);
if ((op == TOK_EQ || op == TOK_NEQ) && left.type_idx >= 0 &&
!spl_type_is_scalar(&ctx->tctx, left.type_idx)) {
spl_comp_error(ctx, "type '%s' does not support comparison",
spl_type_str(&ctx->tctx, left.type_idx));
spl_comp_err_tok(ctx, peek(ctx), "type '%s' does not support comparison",
spl_type_str(&ctx->tctx, left.type_idx));
}
spl_type_t bt = spl_type_emit_type(&ctx->tctx, left.type_idx);
int sop = binop_to_sir(op, bt);
@@ -1394,29 +1464,27 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp
int spl_emit_match_enum_cmp(spl_comp_t *ctx, int enum_type_idx, int val_offset, int by_value) {
char vname[256];
spl_tok_t *vtok = NULL;
if (peek(ctx)->type == TOK_DOT) {
advance(ctx);
vtok = advance(ctx);
spl_tok_copy_name(vtok, vname, sizeof(vname));
} else {
spl_tok_t *tok = advance(ctx);
spl_tok_copy_name(tok, vname, sizeof(vname));
vtok = advance(ctx);
spl_tok_copy_name(vtok, vname, sizeof(vname));
while (peek(ctx)->type == TOK_DOT) {
int qt_idx = spl_type_resolve(&ctx->tctx, vname);
(void)qt_idx;
advance(ctx);
tok = advance(ctx);
spl_tok_copy_name(tok, vname, sizeof(vname));
vtok = advance(ctx);
spl_tok_copy_name(vtok, vname, sizeof(vname));
}
goto lookup;
}
{
spl_tok_t *vtok = advance(ctx);
spl_tok_copy_name(vtok, vname, sizeof(vname));
}
lookup: {
spl_type_item_vec_t *e_items = spl_type_items(&ctx->tctx, enum_type_idx);
vec_for(*e_items, vi) {
@@ -1438,7 +1506,7 @@ lookup: {
}
}
}
spl_comp_error(ctx, "unknown variant '%s' in match", vname);
spl_comp_err_tok(ctx, vtok, "unknown variant '%s' in match", vname);
return -1;
}