stage1 重构代码

This commit is contained in:
zzy
2026-07-20 12:10:55 +08:00
parent ab63c8ed90
commit 21f35b30fa
14 changed files with 1963 additions and 1539 deletions

View File

@@ -15,18 +15,11 @@ spl_tok_t *advance(spl_comp_t *ctx) {
/* ============================================================
* Parse function definition
* fn name(params) ret-type { body }
* or fn name(params) ret-type; (forward decl, not used for stage1)
* ============================================================ */
/* Shared helper: register a function, declare params, parse body, end function.
* Used by both top-level fn decl and methods inside type bodies. */
/* Shared helper: parse function/method parameter list: (name: type, name: type, ...)
* Returns number of params parsed. Stores names in pnames and types in ptypes
* (both must be MAX_PARAMS-sized arrays). */
enum { MAX_PARAMS = 64 };
static int parse_params_decl(spl_comp_t *ctx, char pnames[][256], spl_type_info_t *ptypes[]) {
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) {
@@ -35,11 +28,11 @@ static int parse_params_decl(spl_comp_t *ctx, char pnames[][256], spl_type_info_
spl_tok_copy_name(pname, pnames[nparams], 256);
skip_nl(ctx);
if (peek(ctx)->type == TOK_COLON) {
advance(ctx); /* : */
advance(ctx);
skip_nl(ctx);
ptypes[nparams] = spl_parse_type(ctx);
ptypes[nparams] = spl_type_parse(&ctx->tctx, ctx);
} else {
ptypes[nparams] = spl_type_basic(SPL_I32);
ptypes[nparams] = spl_type_basic(&ctx->tctx, SPL_I32);
}
nparams++;
skip_nl(ctx);
@@ -59,13 +52,12 @@ static int parse_params_decl(spl_comp_t *ctx, char pnames[][256], spl_type_info_
return nparams;
}
static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, spl_type_info_t *ret_type,
int nparams, char pnames[][256], spl_type_info_t *ptypes[], int is_pub) {
int fi = spl_declare_func(ctx, fn_name, ret_type, nparams, 0, is_pub);
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) {
int fi = spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 0, is_pub);
ctx->current_func_idx = fi;
ctx->current_ret_type = ret_type;
ctx->current_local_bytes = 0;
ctx->peak_local_bytes = 0;
ctx->current_ret_type_idx = ret_type_idx;
fa_init(&ctx->emit.frame);
spl_push_scope(ctx);
@@ -75,63 +67,50 @@ static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, spl_type_info_t *
skip_nl(ctx);
if (peek(ctx)->type == TOK_L_BRACE) {
advance(ctx); /* { */
advance(ctx);
skip_nl(ctx);
spl_val_t alloc_addr = vec_size(ctx->prog.insns);
spl_emit(ctx, SPL_ALLOC, SPL_VOID, 0);
emit_alloc(&ctx->emit, 0);
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
spl_parse_stmt(ctx);
skip_nl(ctx);
}
/* Compute physical param slot count (1 slot = 8 bytes).
* Multi-slot struct params occupy ceil(size/8) slots; scalar params occupy 1 each. */
int total_phys_slots = 0;
for (int i = 0; i < nparams; i++) {
usize psz = spl_type_size(ptypes[i]);
usize psz = spl_type_size(&ctx->tctx, ptypes[i]);
total_phys_slots += (int)((psz + sizeof(spl_val_t) - 1) / sizeof(spl_val_t));
}
/* Ensure ALLOC provides enough space for multi-slot return value
* pre-placed at fp[0..nslots-1] (above saved_sp). */
if (ret_type && !spl_type_is_scalar(ret_type) &&
spl_type_size(ret_type) > sizeof(spl_val_t)) {
usize min_bytes = spl_type_slot_count(ret_type) * sizeof(spl_val_t);
if ((usize)ctx->peak_local_bytes < min_bytes)
ctx->peak_local_bytes = (int)min_bytes;
if (spl_type_needs_multi_slot(&ctx->tctx, ret_type_idx)) {
usize min_bytes =
spl_type_slot_count(&ctx->tctx, ret_type_idx) * sizeof(spl_val_t);
if ((usize)ctx->emit.frame.peak_bytes < min_bytes)
ctx->emit.frame.peak_bytes = (int)min_bytes;
}
spl_patch(ctx, alloc_addr,
ctx->peak_local_bytes / (int)sizeof(spl_val_t) - total_phys_slots);
emit_patch(&ctx->emit, alloc_addr,
ctx->emit.frame.peak_bytes / (int)sizeof(spl_val_t) - total_phys_slots);
expect(ctx, TOK_R_BRACE);
}
spl_emit_defer_epilogue(ctx, ctx->scope_depth);
spl_pop_scope(ctx);
/* Store param_types for call-site type checking and multi-slot expansion */
{
spl_func_info_t *f = &vec_at(ctx->funcs, fi);
f->param_types = calloc(nparams, sizeof(spl_type_info_t *));
f->param_type_indices = calloc(nparams, sizeof(int));
f->param_names = calloc(nparams, sizeof(char *));
for (int i = 0; i < nparams; i++) {
f->param_types[i] = ptypes[i];
f->param_type_indices[i] = ptypes[i];
f->param_names[i] = strdup(pnames[i]);
}
}
/* Epilogue return: for multi-slot returns, return address of fp[1]
* (fp[0] is a gap slot that absorbs the RET PUSH, data at fp[1..nslots]). */
if (ctx->current_ret_type && !spl_type_is_scalar(ctx->current_ret_type) &&
spl_type_size(ctx->current_ret_type) > sizeof(spl_val_t)) {
spl_emit(ctx, SPL_LADDR, SPL_PTR, (int)sizeof(spl_val_t));
spl_emit(ctx, SPL_RET, SPL_PTR, 0);
} else {
spl_emit(ctx, SPL_RET, SPL_VOID, 0);
}
emit_return(&ctx->emit, &ctx->tctx, ctx->current_ret_type_idx);
spl_prog_end_func(&ctx->prog, fi);
ctx->current_func_idx = -1;
ctx->current_ret_type = NULL;
ctx->current_ret_type_idx = -1;
return fi;
}
@@ -145,31 +124,27 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
skip_nl(ctx);
expect(ctx, TOK_L_PAREN);
/* Parse parameters — collect names and types */
char pnames[MAX_PARAMS][256];
spl_type_info_t *ptypes[MAX_PARAMS];
int ptypes[MAX_PARAMS];
int nparams = parse_params_decl(ctx, pnames, ptypes);
skip_nl(ctx);
/* Return type (default: void) */
spl_type_info_t *ret_type = spl_type_basic(SPL_VOID);
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 = spl_parse_type(ctx);
if (!ret_type)
ret_type = spl_type_basic(SPL_VOID);
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);
}
/* Extern function: register as native, no body */
if (is_extern) {
spl_declare_func(ctx, fn_name, ret_type, nparams, 1, is_pub);
spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 1, is_pub);
spl_ensure_native(ctx, fn_name);
if (peek(ctx)->type == TOK_SEMICOLON)
advance(ctx);
return;
}
/* Check for forward declaration (just semicolon, skip) */
if (peek(ctx)->type == TOK_SEMICOLON) {
advance(ctx);
return;
@@ -177,66 +152,48 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
skip_nl(ctx);
/* Use shared helper for function body parsing */
parse_fn_body(ctx, fn_name, ret_type, nparams, pnames, ptypes, is_pub);
parse_fn_body(ctx, fn_name, ret_type_idx, nparams, pnames, ptypes, is_pub);
}
/* ============================================================
* Shared helper: parse a method declaration inside a type body.
* Used by both struct_body and enum_body parsers.
* fn name(params) ret-type { body }
* Parse method declaration inside a type body
* ============================================================ */
static void parse_method_decl(spl_comp_t *ctx, spl_type_info_t *container) {
static void parse_method_decl(spl_comp_t *ctx, int container_type_idx) {
advance(ctx); /* fn */
skip_nl(ctx);
spl_tok_t *mname_tok = advance(ctx);
char mname[256];
spl_tok_copy_name(mname_tok, mname, sizeof(mname));
/* Build qualified name: TypeName.method_name */
const char *cname = spl_type_name(&ctx->tctx, container_type_idx);
char qualified[512];
snprintf(qualified, sizeof(qualified), "%s.%s", container->name ? container->name : "anon",
mname);
snprintf(qualified, sizeof(qualified), "%s.%s", cname ? cname : "anon", mname);
skip_nl(ctx);
expect(ctx, TOK_L_PAREN);
/* Parse parameters using shared helper */
char pnames[MAX_PARAMS][256];
spl_type_info_t *ptypes[MAX_PARAMS];
int ptypes[MAX_PARAMS];
int nparams = parse_params_decl(ctx, pnames, ptypes);
skip_nl(ctx);
/* Return type (default: void) */
spl_type_info_t *ret_type = spl_type_basic(SPL_VOID);
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 = spl_parse_type(ctx);
if (!ret_type)
ret_type = spl_type_basic(SPL_VOID);
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);
}
int fi = parse_fn_body(ctx, qualified, ret_type, nparams, pnames, ptypes, 0);
int fi = parse_fn_body(ctx, qualified, ret_type_idx, nparams, pnames, ptypes, 0);
spl_type_add_method(container, mname, fi);
spl_type_add_method(&ctx->tctx, container_type_idx, mname, fi);
}
/* ============================================================
* Parse type container body (shared for struct, union, enum)
*
* For struct/union: fields are added for identifiers
* For enum: variants are added for identifiers
*
* Body supports:
* var name: type; — field declarations (struct/union only)
* name: type, — field/variant declarations
* name: Type, — enum variant with data
* name, — simple enum variant
* type Name = ...; — nested type declarations
* fn name(...) type { } — methods
* ============================================================ */
/* Skip past a nested type declaration in pass 2 without re-parsing */
static void skip_type_decl(spl_comp_t *ctx) {
advance(ctx); /* type */
advance(ctx); /* name */
@@ -270,16 +227,15 @@ static void skip_type_decl(spl_comp_t *ctx) {
advance(ctx);
}
static void parse_type_body(spl_comp_t *ctx, spl_type_info_t *container, int is_enum) {
static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum) {
if (peek(ctx)->type != TOK_L_BRACE)
return;
advance(ctx); /* { */
/* Push type onto namespace chain for short-name resolution inside body */
spl_ns_push(ctx, container);
int saved_current = ctx->tctx.current_type_idx;
ctx->tctx.current_type_idx = container_type_idx;
/* === Pass 1: Parse all nested type declarations first ===
* This allows fields/variants to reference types defined later. */
/* === Pass 1: Parse all nested type declarations first === */
{
usize saved = ctx->tok_idx;
int depth = 1;
@@ -303,35 +259,37 @@ static void parse_type_body(spl_comp_t *ctx, spl_type_info_t *container, int is_
}
/* === Pre-register method names for forward references === */
if (container->name) {
usize saved = ctx->tok_idx;
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++;
advance(ctx);
} else if (tt == TOK_R_BRACE) {
depth--;
if (depth == 0)
break;
advance(ctx);
} else if (tt == KW_FN && depth == 1) {
advance(ctx); /* fn */
skip_nl(ctx);
spl_tok_t *name_tok = advance(ctx);
char mname[256];
spl_tok_copy_name(name_tok, mname, sizeof(mname));
char qualified[512];
snprintf(qualified, sizeof(qualified), "%s.%s", container->name, mname);
int fi = spl_declare_func(ctx, qualified, NULL, 0, 0, 0);
/* Register in type->methods immediately so ns_chain lookup works */
spl_type_add_method(container, mname, fi);
} else {
advance(ctx);
{
const char *cname = spl_type_name(&ctx->tctx, container_type_idx);
if (cname) {
usize saved = ctx->tok_idx;
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++;
advance(ctx);
} else if (tt == TOK_R_BRACE) {
depth--;
if (depth == 0)
break;
advance(ctx);
} else if (tt == KW_FN && depth == 1) {
advance(ctx); /* fn */
skip_nl(ctx);
spl_tok_t *name_tok = advance(ctx);
char mname[256];
spl_tok_copy_name(name_tok, mname, sizeof(mname));
char qualified[512];
snprintf(qualified, sizeof(qualified), "%s.%s", cname, mname);
int fi = spl_declare_func(ctx, qualified, -1, 0, 0, 0);
spl_type_add_method(&ctx->tctx, container_type_idx, mname, fi);
} else {
advance(ctx);
}
}
ctx->tok_idx = saved;
}
ctx->tok_idx = saved;
}
/* === Pass 2: Parse fields/variants and methods === */
@@ -353,7 +311,6 @@ static void parse_type_body(spl_comp_t *ctx, spl_type_info_t *container, int is_
} else if (tt == KW_TYPE && depth == 1) {
skip_type_decl(ctx);
} else if (tt == KW_VAR && depth == 1 && !is_enum) {
/* var name: type; (struct/union only) */
advance(ctx); /* var */
skip_nl(ctx);
spl_tok_t *ftok = advance(ctx);
@@ -361,68 +318,63 @@ static void parse_type_body(spl_comp_t *ctx, spl_type_info_t *container, int is_
if (peek(ctx)->type == TOK_COLON) {
advance(ctx); /* : */
skip_nl(ctx);
spl_type_info_t *ftype = spl_parse_type(ctx);
int ftype = spl_type_parse(&ctx->tctx, ctx);
char fname[256];
spl_tok_copy_name(ftok, fname, sizeof(fname));
spl_type_add_field(container, fname, ftype);
if (ftype >= 0)
spl_type_add_field(&ctx->tctx, container_type_idx, fname, ftype);
}
skip_nl(ctx);
if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_COMMA)
advance(ctx);
} else if (tt == TOK_IDENT && depth == 1) {
if (is_enum) {
/* Variant: Name or Name: Type */
spl_tok_t *vtok = advance(ctx);
skip_nl(ctx);
if (peek(ctx)->type == TOK_COLON) {
advance(ctx); /* : */
skip_nl(ctx);
spl_type_info_t *dtype = spl_parse_type(ctx);
int dtype = spl_type_parse(&ctx->tctx, ctx);
char vname[256];
spl_tok_copy_name(vtok, vname, sizeof(vname));
spl_type_add_variant(container, vname, dtype);
spl_type_add_variant(&ctx->tctx, container_type_idx, vname,
dtype >= 0 ? dtype : -1);
} else {
char vname[256];
spl_tok_copy_name(vtok, vname, sizeof(vname));
spl_type_add_variant(container, vname, NULL);
spl_type_add_variant(&ctx->tctx, container_type_idx, vname, -1);
}
} else {
/* Old-style field: name: type, */
spl_tok_t *ftok = advance(ctx);
skip_nl(ctx);
if (peek(ctx)->type == TOK_COLON) {
advance(ctx); /* : */
skip_nl(ctx);
spl_type_info_t *ftype = spl_parse_type(ctx);
int ftype = spl_type_parse(&ctx->tctx, ctx);
char fname[256];
spl_tok_copy_name(ftok, fname, sizeof(fname));
spl_type_add_field(container, fname, ftype);
if (ftype >= 0)
spl_type_add_field(&ctx->tctx, container_type_idx, fname, ftype);
}
}
skip_nl(ctx);
if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_COMMA)
advance(ctx);
} else if (tt == KW_FN && depth == 1) {
/* Compute layout before compiling methods so
* field offsets are correct during codegen */
spl_type_compute_layout(container);
parse_method_decl(ctx, container);
spl_type_compute_layout(&ctx->tctx, container_type_idx);
parse_method_decl(ctx, container_type_idx);
} else {
advance(ctx);
}
}
}
spl_ns_pop(ctx);
spl_type_compute_layout(container);
ctx->tctx.current_type_idx = saved_current;
spl_type_compute_layout(&ctx->tctx, container_type_idx);
}
/* ============================================================
* Parse type declaration
* type Name = struct { ... };
* type Name = union { ... };
* type Name = enum { ... };
* type Name = ExistingType;
* ============================================================ */
void parse_type_decl(spl_comp_t *ctx) {
@@ -435,44 +387,34 @@ void parse_type_decl(spl_comp_t *ctx) {
expect(ctx, TOK_ASSIGN);
skip_nl(ctx);
/* Determine parent type if inside a type body (for nested type registration) */
spl_type_info_t *parent =
vec_size(ctx->ns_chain) > 0 ? vec_at(ctx->ns_chain, vec_size(ctx->ns_chain) - 1) : NULL;
int parent_type_idx = ctx->tctx.current_type_idx;
if (peek(ctx)->type == KW_STRUCT) {
advance(ctx);
spl_type_info_t *st = spl_type_struct(tname);
/* Register type early to allow self-referential fields */
map_put(ctx->type_defs, strdup(tname), st);
if (parent)
map_put(parent->children, strdup(tname), st);
int ti = spl_type_struct(&ctx->tctx, tname);
if (parent_type_idx >= 0)
spl_type_add_nested(&ctx->tctx, parent_type_idx, tname, ti);
skip_nl(ctx);
parse_type_body(ctx, st, 0);
parse_type_body(ctx, ti, 0);
} else if (peek(ctx)->type == KW_UNION) {
advance(ctx);
spl_type_info_t *ut = spl_type_union(tname);
map_put(ctx->type_defs, strdup(tname), ut);
if (parent)
map_put(parent->children, strdup(tname), ut);
int ti = spl_type_union(&ctx->tctx, tname);
if (parent_type_idx >= 0)
spl_type_add_nested(&ctx->tctx, parent_type_idx, tname, ti);
skip_nl(ctx);
parse_type_body(ctx, ut, 0);
parse_type_body(ctx, ti, 1);
} else if (peek(ctx)->type == KW_ENUM) {
advance(ctx);
spl_type_info_t *et = spl_type_enum(tname);
/* Register type early to allow self-referential variants */
map_put(ctx->type_defs, strdup(tname), et);
if (parent)
map_put(parent->children, strdup(tname), et);
int ti = spl_type_enum(&ctx->tctx, tname);
if (parent_type_idx >= 0)
spl_type_add_nested(&ctx->tctx, parent_type_idx, tname, ti);
skip_nl(ctx);
parse_type_body(ctx, et, 1);
parse_type_body(ctx, ti, 1);
} else if (peek(ctx)->type == TOK_IDENT ||
(peek(ctx)->type >= KW_AS && peek(ctx)->type <= KW_ANY)) {
spl_type_info_t *base = spl_parse_type(ctx);
if (base) {
spl_type_info_t *alias = spl_type_clone(base);
alias->name = strdup(tname);
alias->kind = TYPE_NAME;
map_put(ctx->type_defs, strdup(tname), alias);
int base = spl_type_parse(&ctx->tctx, ctx);
if (base >= 0) {
spl_type_alias(&ctx->tctx, tname, base);
}
}
@@ -508,7 +450,6 @@ void spl_parse_prog(spl_comp_t *ctx) {
break;
}
case TOK_SHARP:
/* #[extern("vm")] fn ... */
advance(ctx); /* # */
if (peek(ctx)->type == TOK_L_BRACKET) {
advance(ctx); /* [ */
@@ -522,10 +463,8 @@ void spl_parse_prog(spl_comp_t *ctx) {
parse_fn_decl(ctx, 1, 0);
break;
default: {
int prev = ctx->tok_idx; /* Safety: prevent infinite loop */
/* Try to parse as a statement */
int prev = ctx->tok_idx;
spl_parse_stmt(ctx);
/* Safety: prevent infinite loop on unrecognized tokens */
if (ctx->tok_idx == prev)
advance(ctx);
break;