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

@@ -14,6 +14,16 @@ static int parse_params_decl(spl_comp_t *ctx, char pnames[][256], int ptypes[])
int nparams = 0;
skip_nl(ctx);
if (peek(ctx)->type != TOK_R_PAREN) {
{
usize saved = ctx->tok_idx;
spl_tok_t *ptok = advance(ctx);
skip_nl(ctx);
if (ptok->type == KW_VOID && peek(ctx)->type == TOK_R_PAREN) {
expect(ctx, TOK_R_PAREN);
return 0;
}
ctx->tok_idx = saved;
}
while (1) {
spl_tok_t *pname = advance(ctx);
spl_tok_copy_name(pname, pnames[nparams], 256);
@@ -45,6 +55,7 @@ static int parse_params_decl(spl_comp_t *ctx, char pnames[][256], int ptypes[])
static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx, int nparams,
char pnames[][256], int ptypes[], int is_pub) {
snprintf(ctx->parse_context, sizeof(ctx->parse_context), "function '%s'", fn_name);
int fi = spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 0, is_pub);
{
@@ -75,11 +86,35 @@ static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx,
spl_val_t alloc_addr = vec_size(ctx->prog.insns);
emit_alloc(&ctx->emit, 0);
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) {
spl_parse_stmt(ctx);
skip_nl(ctx);
}
/* Error recovery: skip to matching } if has_error caused early exit */
if (ctx->has_error) {
int depth = 1;
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
spl_tok_type_t tt = peek(ctx)->type;
if (tt == TOK_L_BRACE)
depth++;
else if (tt == TOK_R_BRACE) {
depth--;
if (depth == 0)
break;
} else if (tt == TOK_EOF)
break;
advance(ctx);
}
if (peek(ctx)->type == TOK_R_BRACE)
advance(ctx);
else
return 0;
} else {
if (!expect(ctx, TOK_R_BRACE))
return 0;
}
int total_phys_slots = 0;
for (int i = 0; i < nparams; i++) {
usize psz = spl_type_size(&ctx->tctx, ptypes[i]);
@@ -98,7 +133,6 @@ static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx,
alloc_slots, ctx->emit.frame.peak_bytes, total_phys_slots);
}
emit_patch(&ctx->emit, alloc_addr, alloc_slots);
expect(ctx, TOK_R_BRACE);
}
spl_emit_defer_epilogue(ctx, ctx->scope_depth);
@@ -122,7 +156,8 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
char fn_name[256];
spl_tok_copy_name(fname_tok, fn_name, sizeof(fn_name));
skip_nl(ctx);
expect(ctx, TOK_L_PAREN);
if (!expect(ctx, TOK_L_PAREN))
return;
char pnames[MAX_PARAMS][256];
int ptypes[MAX_PARAMS];
@@ -176,7 +211,8 @@ static void parse_method_decl(spl_comp_t *ctx, int container_type_idx) {
snprintf(qualified, sizeof(qualified), "%s.%s", cname ? cname : "anon", mname);
skip_nl(ctx);
expect(ctx, TOK_L_PAREN);
if (!expect(ctx, TOK_L_PAREN))
return;
char pnames[MAX_PARAMS][256];
int ptypes[MAX_PARAMS];
@@ -200,42 +236,6 @@ static void parse_method_decl(spl_comp_t *ctx, int container_type_idx) {
* Parse type container body (shared for struct, union, enum)
* ============================================================ */
static void skip_type_decl(spl_comp_t *ctx) {
advance(ctx); /* type */
advance(ctx); /* name */
skip_nl(ctx);
expect(ctx, TOK_ASSIGN);
skip_nl(ctx);
spl_tok_type_t tt = peek(ctx)->type;
if (tt == KW_STRUCT || tt == KW_UNION || tt == KW_ENUM) {
advance(ctx);
skip_nl(ctx);
}
if (peek(ctx)->type == TOK_L_BRACE) {
int bd = 1;
advance(ctx);
while (bd > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
spl_tok_type_t tt = peek(ctx)->type;
if (tt == TOK_L_BRACE)
bd++;
else if (tt == TOK_R_BRACE)
bd--;
else if (tt == TOK_EOF)
break;
advance(ctx);
}
} else {
while (peek(ctx)->type != TOK_SEMICOLON && peek(ctx)->type != TOK_EOF)
advance(ctx);
}
skip_nl(ctx);
if (peek(ctx)->type == TOK_SEMICOLON)
advance(ctx);
}
static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum) {
if (peek(ctx)->type != TOK_L_BRACE)
return;
@@ -248,7 +248,7 @@ static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum
{
usize saved = ctx->tok_idx;
int depth = 1;
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
while (!ctx->has_error && depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
spl_tok_type_t tt = peek(ctx)->type;
if (tt == TOK_L_BRACE) {
depth++;
@@ -275,7 +275,7 @@ static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum
if (cname) {
usize saved = ctx->tok_idx;
int depth = 1;
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
while (!ctx->has_error && depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
spl_tok_type_t tt = peek(ctx)->type;
if (tt == TOK_L_BRACE) {
depth++;
@@ -331,7 +331,7 @@ static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum
/* === Pass 2: Parse fields/variants and methods === */
{
int depth = 1;
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
while (!ctx->has_error && depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
skip_nl(ctx);
spl_tok_type_t tt = peek(ctx)->type;
if (tt == TOK_L_BRACE) {
@@ -345,7 +345,7 @@ static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum
}
advance(ctx);
} else if (tt == KW_TYPE && depth == 1) {
skip_type_decl(ctx);
parse_type_decl(ctx);
} else if (tt == KW_VAR && depth == 1 && !is_enum) {
advance(ctx); /* var */
skip_nl(ctx);
@@ -358,7 +358,7 @@ static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum
char fname[256];
spl_tok_copy_name(ftok, fname, sizeof(fname));
if (ftype >= 0)
spl_type_add_field(&ctx->tctx, container_type_idx, fname, ftype);
spl_type_add_var(&ctx->tctx, container_type_idx, fname, ftype);
}
skip_nl(ctx);
if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_COMMA)
@@ -420,31 +420,48 @@ void parse_type_decl(spl_comp_t *ctx) {
spl_tok_t *name_tok = advance(ctx);
char tname[256];
spl_tok_copy_name(name_tok, tname, sizeof(tname));
snprintf(ctx->parse_context, sizeof(ctx->parse_context), "type '%s'", tname);
skip_nl(ctx);
expect(ctx, TOK_ASSIGN);
if (!expect(ctx, TOK_ASSIGN))
return;
skip_nl(ctx);
int parent_type_idx = ctx->tctx.current_type_idx;
/* Check if already pre-registered in Pass 0 */
int existing = spl_type_resolve(&ctx->tctx, tname);
if (peek(ctx)->type == KW_STRUCT) {
advance(ctx);
int ti = spl_type_struct(&ctx->tctx, tname);
if (parent_type_idx >= 0)
int ti;
if (existing >= 0)
ti = existing;
else
ti = spl_type_struct(&ctx->tctx, tname);
if (parent_type_idx >= 0 && existing < 0)
spl_type_add_nested(&ctx->tctx, parent_type_idx, tname, ti);
skip_nl(ctx);
parse_type_body(ctx, ti, 0);
} else if (peek(ctx)->type == KW_UNION) {
advance(ctx);
int ti = spl_type_union(&ctx->tctx, tname);
if (parent_type_idx >= 0)
int ti;
if (existing >= 0)
ti = existing;
else
ti = spl_type_union(&ctx->tctx, tname);
if (parent_type_idx >= 0 && existing < 0)
spl_type_add_nested(&ctx->tctx, parent_type_idx, tname, ti);
skip_nl(ctx);
parse_type_body(ctx, ti, 1);
} else if (peek(ctx)->type == KW_ENUM) {
advance(ctx);
int ti = spl_type_enum(&ctx->tctx, tname);
if (parent_type_idx >= 0)
int ti;
if (existing >= 0)
ti = existing;
else
ti = spl_type_enum(&ctx->tctx, tname);
if (parent_type_idx >= 0 && existing < 0)
spl_type_add_nested(&ctx->tctx, parent_type_idx, tname, ti);
skip_nl(ctx);
parse_type_body(ctx, ti, 1);
@@ -461,12 +478,213 @@ void parse_type_decl(spl_comp_t *ctx) {
advance(ctx);
}
/* ============================================================
* Pre-registration pass: register all names before filling bodies
* ============================================================ */
/* Skip a { ... } function body */
static void skip_fn_body(spl_comp_t *ctx) {
int depth = 1;
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
spl_tok_type_t tt = peek(ctx)->type;
if (tt == TOK_L_BRACE)
depth++;
else if (tt == TOK_R_BRACE) {
depth--;
if (depth == 0)
break;
} else if (tt == TOK_EOF)
break;
advance(ctx);
}
if (peek(ctx)->type == TOK_R_BRACE)
advance(ctx);
}
/* Pre-register a type name (and nested type names), skip the body */
static void pre_register_type_decl(spl_comp_t *ctx) {
advance(ctx); /* type */
spl_tok_t *name_tok = advance(ctx);
char tname[256];
spl_tok_copy_name(name_tok, tname, sizeof(tname));
skip_nl(ctx);
if (!expect(ctx, TOK_ASSIGN))
return;
skip_nl(ctx);
int parent_type_idx = ctx->tctx.current_type_idx;
int ti = -1;
if (peek(ctx)->type == KW_STRUCT) {
advance(ctx);
ti = spl_type_struct(&ctx->tctx, tname);
} else if (peek(ctx)->type == KW_ENUM) {
advance(ctx);
ti = spl_type_enum(&ctx->tctx, tname);
} else if (peek(ctx)->type == KW_UNION) {
advance(ctx);
ti = spl_type_union(&ctx->tctx, tname);
}
if (ti >= 0) {
if (parent_type_idx >= 0)
spl_type_add_nested(&ctx->tctx, parent_type_idx, tname, ti);
/* Register nested type names inside the body */
if (peek(ctx)->type == TOK_L_BRACE) {
int saved_current = ctx->tctx.current_type_idx;
ctx->tctx.current_type_idx = ti;
int depth = 1;
advance(ctx); /* { */
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
spl_tok_type_t tt = peek(ctx)->type;
if (tt == TOK_L_BRACE) {
depth++;
advance(ctx);
} else if (tt == TOK_R_BRACE) {
depth--;
if (depth == 0)
break;
advance(ctx);
} else if (tt == KW_TYPE && depth == 1) {
pre_register_type_decl(ctx);
} else if (tt == TOK_EOF) {
break;
} else {
advance(ctx);
}
}
if (peek(ctx)->type == TOK_R_BRACE)
advance(ctx);
ctx->tctx.current_type_idx = saved_current;
}
}
skip_nl(ctx);
if (peek(ctx)->type == TOK_SEMICOLON)
advance(ctx);
}
/* Pre-register a function name and signature, skip the body */
static void pre_register_fn_decl(spl_comp_t *ctx, int is_extern) {
advance(ctx);
skip_nl(ctx);
spl_tok_t *fname_tok = advance(ctx);
char fn_name[256];
spl_tok_copy_name(fname_tok, fn_name, sizeof(fn_name));
skip_nl(ctx);
if (!expect(ctx, TOK_L_PAREN))
return;
char pnames[MAX_PARAMS][256];
int ptypes[MAX_PARAMS];
int nparams = parse_params_decl(ctx, pnames, ptypes);
skip_nl(ctx);
int ret_type_idx = spl_type_basic(&ctx->tctx, SPL_VOID);
if (peek(ctx)->type != TOK_SEMICOLON && peek(ctx)->type != TOK_L_BRACE) {
ret_type_idx = spl_type_parse(&ctx->tctx, ctx);
if (ret_type_idx < 0)
ret_type_idx = spl_type_basic(&ctx->tctx, SPL_VOID);
skip_nl(ctx);
}
if (is_extern) {
spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 1, 0);
spl_ensure_native(ctx, fn_name);
if (peek(ctx)->type == TOK_SEMICOLON)
advance(ctx);
return;
}
if (peek(ctx)->type == TOK_SEMICOLON) {
advance(ctx);
return;
}
skip_nl(ctx);
if (peek(ctx)->type == TOK_L_BRACE) {
skip_fn_body(ctx);
}
skip_nl(ctx);
if (peek(ctx)->type == TOK_SEMICOLON)
advance(ctx);
}
/* ============================================================
* Parse top-level program
* ============================================================ */
void spl_parse_prog(spl_comp_t *ctx) {
while (peek(ctx)->type != TOK_EOF) {
/* Pass 0: Pre-register all type names, function signatures, and variables */
{
usize saved = ctx->tok_idx;
while (!ctx->has_error && peek(ctx)->type != TOK_EOF) {
skip_nl(ctx);
if (peek(ctx)->type == TOK_EOF)
break;
switch (peek(ctx)->type) {
case KW_TYPE:
pre_register_type_decl(ctx);
break;
case KW_FN:
pre_register_fn_decl(ctx, 0);
break;
case KW_PUB: {
advance(ctx);
skip_nl(ctx);
if (peek(ctx)->type == KW_FN)
pre_register_fn_decl(ctx, 0);
else if (peek(ctx)->type == KW_TYPE)
pre_register_type_decl(ctx);
break;
}
case TOK_AT:
case TOK_SHARP: {
int tt = peek(ctx)->type;
advance(ctx);
skip_nl(ctx);
if (tt == TOK_AT) {
if (peek(ctx)->type == KW_EXTERN) {
advance(ctx);
skip_nl(ctx);
if (peek(ctx)->type == TOK_L_PAREN) {
advance(ctx);
skip_nl(ctx);
advance(ctx);
skip_nl(ctx);
if (peek(ctx)->type == TOK_R_PAREN)
advance(ctx);
}
}
} else {
if (peek(ctx)->type == TOK_L_BRACKET) {
advance(ctx);
while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF)
advance(ctx);
if (peek(ctx)->type == TOK_R_BRACKET)
advance(ctx);
}
}
skip_nl(ctx);
if (peek(ctx)->type == KW_FN)
pre_register_fn_decl(ctx, 1);
break;
}
default:
/* Skip unrecognized tokens (stmts, etc.) */
advance(ctx);
break;
}
}
ctx->tok_idx = saved;
}
/* Pass 1: Fill all bodies */
while (!ctx->has_error && peek(ctx)->type != TOK_EOF) {
skip_nl(ctx);
if (peek(ctx)->type == TOK_EOF)
break;
@@ -493,7 +711,6 @@ void spl_parse_prog(spl_comp_t *ctx) {
advance(ctx); /* @ or # */
skip_nl(ctx);
if (tt == TOK_AT) {
/* @extern(vm) fn ... */
if (peek(ctx)->type == KW_EXTERN) {
advance(ctx); /* extern */
skip_nl(ctx);
@@ -507,9 +724,8 @@ void spl_parse_prog(spl_comp_t *ctx) {
}
}
} else {
/* #[extern("vm")] fn ... (legacy) */
if (peek(ctx)->type == TOK_L_BRACKET) {
advance(ctx); /* [ */
advance(ctx);
while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF)
advance(ctx);
if (peek(ctx)->type == TOK_R_BRACKET)