stage1 修复错误 提供类型检查
This commit is contained in:
@@ -185,6 +185,9 @@ void emit_patch_call_fixups(spl_emit_t *e, spl_prog_t *prog) {
|
||||
if (fe->func_idx >= 0 && fe->func_idx < (int)vec_size(prog->funcs)) {
|
||||
spl_val_t addr = vec_at(prog->funcs, fe->func_idx).address;
|
||||
vec_at(prog->insns, fe->insn_idx).imm = addr;
|
||||
} else {
|
||||
fprintf(stderr, "WARN: fixup func_idx=%d out of bounds [0,%zu), insn_idx=%zu\n",
|
||||
fe->func_idx, vec_size(prog->funcs), fe->insn_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,24 +609,107 @@ static int parse_call_args(spl_comp_t *ctx) {
|
||||
return nargs;
|
||||
}
|
||||
|
||||
static int types_equal(spl_type_ctx_t *tctx, int a, int b) {
|
||||
if (a < 0 || b < 0)
|
||||
return 0;
|
||||
a = spl_type_resolve_underlying(tctx, a);
|
||||
b = spl_type_resolve_underlying(tctx, b);
|
||||
if (a == b)
|
||||
return 1;
|
||||
|
||||
spl_type_kind_t ak = spl_type_kind(tctx, a);
|
||||
spl_type_kind_t bk = spl_type_kind(tctx, b);
|
||||
if (ak != bk)
|
||||
return 0;
|
||||
|
||||
switch (ak) {
|
||||
case TYPE_VOID:
|
||||
return 1;
|
||||
case TYPE_BASIC:
|
||||
return spl_type_basic_type(tctx, a) == spl_type_basic_type(tctx, b);
|
||||
case TYPE_PTR:
|
||||
return types_equal(tctx, spl_type_elem_type(tctx, a), spl_type_elem_type(tctx, b));
|
||||
case TYPE_ARRAY:
|
||||
return spl_type_array_len(tctx, a) == spl_type_array_len(tctx, b) &&
|
||||
types_equal(tctx, spl_type_elem_type(tctx, a), spl_type_elem_type(tctx, b));
|
||||
case TYPE_SLICE:
|
||||
return types_equal(tctx, spl_type_elem_type(tctx, a), spl_type_elem_type(tctx, b));
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
case TYPE_ENUM: {
|
||||
const char *an = spl_type_name(tctx, a);
|
||||
const char *bn = spl_type_name(tctx, b);
|
||||
return an && bn && strcmp(an, bn) == 0;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void spl_check_arg_type(spl_comp_t *ctx, const char *fname, int arg_type_idx,
|
||||
int param_type_idx, int arg_idx) {
|
||||
if (arg_type_idx < 0 || param_type_idx < 0)
|
||||
return;
|
||||
if (spl_type_kind(&ctx->tctx, param_type_idx) == TYPE_PTR &&
|
||||
spl_type_elem_type(&ctx->tctx, param_type_idx) >= 0 &&
|
||||
spl_type_kind(&ctx->tctx, arg_type_idx) != TYPE_PTR &&
|
||||
spl_type_name(&ctx->tctx, arg_type_idx) &&
|
||||
spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx)) &&
|
||||
strcmp(spl_type_name(&ctx->tctx, arg_type_idx),
|
||||
spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx))) == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: warning: argument %d of '%s' expects '%s*', "
|
||||
"got '%s' (missing '&'?)\n",
|
||||
ctx->fname, arg_idx + 1, fname,
|
||||
spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx)),
|
||||
spl_type_name(&ctx->tctx, arg_type_idx));
|
||||
|
||||
/* Level 1: structurally equal types */
|
||||
if (types_equal(&ctx->tctx, arg_type_idx, param_type_idx))
|
||||
return;
|
||||
|
||||
int arg_u = spl_type_resolve_underlying(&ctx->tctx, arg_type_idx);
|
||||
int param_u = spl_type_resolve_underlying(&ctx->tctx, param_type_idx);
|
||||
|
||||
/* Level 1b: void pointer (*_) accepts any pointer */
|
||||
if (spl_type_kind(&ctx->tctx, param_u) == TYPE_PTR) {
|
||||
int param_elem = spl_type_elem_type(&ctx->tctx, param_u);
|
||||
int param_elem_u = spl_type_resolve_underlying(&ctx->tctx, param_elem);
|
||||
if (param_elem_u >= 0 && spl_type_kind(&ctx->tctx, param_elem_u) == TYPE_BASIC &&
|
||||
spl_type_basic_type(&ctx->tctx, param_elem_u) == SPL_VOID &&
|
||||
spl_type_kind(&ctx->tctx, arg_u) == TYPE_PTR) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Level 2: pointer indirection mismatch with same inner type */
|
||||
if (spl_type_kind(&ctx->tctx, param_u) == TYPE_PTR) {
|
||||
int param_elem = spl_type_elem_type(&ctx->tctx, param_u);
|
||||
if (param_elem < 0)
|
||||
goto type_mismatch;
|
||||
|
||||
/* 2a: param = *T, arg = T (missing '&') */
|
||||
if (spl_type_kind(&ctx->tctx, arg_u) != TYPE_PTR) {
|
||||
if (types_equal(&ctx->tctx, arg_type_idx, param_elem)) {
|
||||
const char *is = spl_type_str(&ctx->tctx, param_elem);
|
||||
fprintf(stderr,
|
||||
"%s: warning: argument %d of '%s' expects '%s*', "
|
||||
"got '%s' (missing '&'?)\n",
|
||||
ctx->fname, arg_idx + 1, fname, is, is);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2b: param = *T, arg = **T (extra '&') */
|
||||
if (spl_type_kind(&ctx->tctx, arg_u) == TYPE_PTR) {
|
||||
int arg_elem = spl_type_elem_type(&ctx->tctx, arg_u);
|
||||
int arg_elem_u = spl_type_resolve_underlying(&ctx->tctx, arg_elem);
|
||||
if (spl_type_kind(&ctx->tctx, arg_elem_u) == TYPE_PTR) {
|
||||
if (types_equal(&ctx->tctx, spl_type_elem_type(&ctx->tctx, arg_elem), param_elem)) {
|
||||
const char *is = spl_type_str(&ctx->tctx, param_elem);
|
||||
fprintf(stderr,
|
||||
"%s: warning: argument %d of '%s' expects '%s*', "
|
||||
"got '%s**' (extra '&'?)\n",
|
||||
ctx->fname, arg_idx + 1, fname, is, is);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Level 3: general type mismatch → error */
|
||||
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);
|
||||
}
|
||||
|
||||
static int parse_call_args_checked(spl_comp_t *ctx, const char *fname, int *param_type_indices,
|
||||
@@ -975,6 +1058,10 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
|
||||
}
|
||||
expect(ctx, TOK_R_PAREN);
|
||||
|
||||
if (func->func_idx < 0) {
|
||||
fprintf(stderr, "WARN: method call '%s.' with invalid func_idx=%d\n",
|
||||
func->name, func->func_idx);
|
||||
}
|
||||
emit_call_with_fixup(&ctx->emit, nargs, func->func_idx);
|
||||
|
||||
left = (spl_expr_result_t){func->ret_type_idx, 0};
|
||||
|
||||
@@ -90,8 +90,14 @@ static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx,
|
||||
if ((usize)ctx->emit.frame.peak_bytes < min_bytes)
|
||||
ctx->emit.frame.peak_bytes = (int)min_bytes;
|
||||
}
|
||||
emit_patch(&ctx->emit, alloc_addr,
|
||||
ctx->emit.frame.peak_bytes / (int)sizeof(spl_val_t) - total_phys_slots);
|
||||
int alloc_slots = ctx->emit.frame.peak_bytes / (int)sizeof(spl_val_t) - total_phys_slots;
|
||||
if (alloc_slots < 0 || alloc_slots > 65536) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"WARN: parse_fn_body: suspicious alloc_slots=%d (peak_bytes=%d, phys_slots=%d)\n",
|
||||
alloc_slots, ctx->emit.frame.peak_bytes, total_phys_slots);
|
||||
}
|
||||
emit_patch(&ctx->emit, alloc_addr, alloc_slots);
|
||||
expect(ctx, TOK_R_BRACE);
|
||||
}
|
||||
|
||||
|
||||
@@ -575,7 +575,14 @@ spl_type_t spl_type_emit_type(spl_type_ctx_t *tctx, int type_idx) {
|
||||
return SPL_PTR;
|
||||
}
|
||||
|
||||
#define TYPE_STR_BUF_COUNT 8
|
||||
#define TYPE_STR_BUF_SIZE 64
|
||||
|
||||
const char *spl_type_str(spl_type_ctx_t *tctx, int type_idx) {
|
||||
static char b[TYPE_STR_BUF_COUNT][TYPE_STR_BUF_SIZE];
|
||||
static int bi = 0;
|
||||
int my = (bi++) % TYPE_STR_BUF_COUNT;
|
||||
|
||||
if (type_idx < 0)
|
||||
return "<null>";
|
||||
spl_type_info_t *t = &vec_at(tctx->types, type_idx);
|
||||
@@ -616,22 +623,18 @@ const char *spl_type_str(spl_type_ctx_t *tctx, int type_idx) {
|
||||
return "<basic>";
|
||||
}
|
||||
}
|
||||
case TYPE_PTR: {
|
||||
static char buf[64];
|
||||
snprintf(buf, sizeof(buf), "*%s", spl_type_str(tctx, spl_type_elem_type(tctx, type_idx)));
|
||||
return buf;
|
||||
}
|
||||
case TYPE_ARRAY: {
|
||||
static char buf[64];
|
||||
snprintf(buf, sizeof(buf), "[%zu]%s", spl_type_array_len(tctx, type_idx),
|
||||
case TYPE_PTR:
|
||||
snprintf(b[my], TYPE_STR_BUF_SIZE, "*%s",
|
||||
spl_type_str(tctx, spl_type_elem_type(tctx, type_idx)));
|
||||
return buf;
|
||||
}
|
||||
case TYPE_SLICE: {
|
||||
static char buf[64];
|
||||
snprintf(buf, sizeof(buf), "[]%s", spl_type_str(tctx, spl_type_elem_type(tctx, type_idx)));
|
||||
return buf;
|
||||
}
|
||||
return b[my];
|
||||
case TYPE_ARRAY:
|
||||
snprintf(b[my], TYPE_STR_BUF_SIZE, "[%zu]%s", spl_type_array_len(tctx, type_idx),
|
||||
spl_type_str(tctx, spl_type_elem_type(tctx, type_idx)));
|
||||
return b[my];
|
||||
case TYPE_SLICE:
|
||||
snprintf(b[my], TYPE_STR_BUF_SIZE, "[]%s",
|
||||
spl_type_str(tctx, spl_type_elem_type(tctx, type_idx)));
|
||||
return b[my];
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
case TYPE_ENUM:
|
||||
|
||||
Reference in New Issue
Block a user