stage1 完成11-13测试

This commit is contained in:
zzy
2026-07-06 13:00:55 +08:00
parent 0182b8ed5c
commit ad473f245c
6 changed files with 363 additions and 69 deletions

View File

@@ -3,9 +3,9 @@
#include "spl_comp.h"
#include <string.h>
static spl_tok_t *peek(spl_comp_t *ctx) { return &vec_at(ctx->toks, ctx->tok_idx); }
spl_tok_t *peek(spl_comp_t *ctx) { return &vec_at(ctx->toks, ctx->tok_idx); }
static spl_tok_t *advance(spl_comp_t *ctx) {
spl_tok_t *advance(spl_comp_t *ctx) {
spl_tok_t *t = &vec_at(ctx->toks, ctx->tok_idx);
if (t->type != TOK_EOF)
ctx->tok_idx++;
@@ -173,31 +173,55 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
}
/* ============================================================
* Parse type declaration
* type Name = struct/enum { ... };
* type Name = ExistingType;
* Parse struct/union body (shared for struct and union containers)
*
* Body supports:
* var name: type; — field declarations
* name: type, — field declarations (old-style)
* type Name = ...; — nested type declarations
* fn name(...) type { } — methods (skipped)
* ============================================================ */
void parse_type_decl(spl_comp_t *ctx) {
advance(ctx); /* type */
spl_tok_t *name_tok = advance(ctx);
char tname[256];
usize tnl = name_tok->len < 255 ? name_tok->len : 255;
memcpy(tname, name_tok->lexeme, tnl);
tname[tnl] = '\0';
static void parse_struct_body(spl_comp_t *ctx, spl_type_info_t *st) {
if (peek(ctx)->type != TOK_L_BRACE)
return;
advance(ctx); /* { */
skip_nl(ctx);
expect(ctx, TOK_ASSIGN);
skip_nl(ctx);
/* === Pass 1: Parse all nested type declarations first ===
* This allows field declarations to reference types defined later in the body. */
{
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_TYPE && depth == 1) {
parse_type_decl(ctx);
} else {
advance(ctx);
}
}
/* Reset to start of body for second pass */
ctx->tok_idx = saved;
}
if (peek(ctx)->type == KW_STRUCT) {
advance(ctx);
spl_type_info_t *st = spl_type_struct(tname);
skip_nl(ctx);
if (peek(ctx)->type == TOK_L_BRACE) {
advance(ctx); /* { */
/* === Pass 2: Parse fields and methods === */
{
int depth = 1;
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
skip_nl(ctx);
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
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) { advance(ctx); break; } advance(ctx); }
else if (tt == KW_TYPE && depth == 1) {
/* Nested type — already parsed in pass 1, skip by re-parsing */
parse_type_decl(ctx);
}
else if (tt == KW_VAR && depth == 1) {
/* var name: type; */
advance(ctx); /* var */
skip_nl(ctx);
spl_tok_t *ftok = advance(ctx);
skip_nl(ctx);
if (peek(ctx)->type == TOK_COLON) {
@@ -211,24 +235,103 @@ void parse_type_decl(spl_comp_t *ctx) {
spl_type_add_field(st, fname, ftype);
}
skip_nl(ctx);
if (peek(ctx)->type == TOK_COMMA) {
if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_COMMA)
advance(ctx);
}
else if (tt == TOK_IDENT && depth == 1) {
/* 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);
char fname[256];
usize fnl = ftok->len < 255 ? ftok->len : 255;
memcpy(fname, ftok->lexeme, fnl);
fname[fnl] = '\0';
spl_type_add_field(st, 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) {
/* Method — skip over fn name(params) rettype { body } */
advance(ctx); /* fn */
while (ctx->tok_idx < vec_size(ctx->toks)) {
spl_tok_type_t mt = peek(ctx)->type;
if (mt == TOK_SEMICOLON) { advance(ctx); break; }
if (mt == TOK_L_BRACE) {
/* Skip function body counting braces */
advance(ctx);
int bd = 1;
while (bd > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
if (peek(ctx)->type == TOK_L_BRACE) bd++;
else if (peek(ctx)->type == TOK_R_BRACE) bd--;
advance(ctx);
}
break;
}
advance(ctx);
}
}
if (peek(ctx)->type == TOK_R_BRACE)
else {
advance(ctx);
}
}
spl_type_compute_layout(st);
map_put(ctx->type_defs, strdup(tname), st);
} else if (peek(ctx)->type == KW_ENUM) {
advance(ctx);
spl_type_info_t *et = spl_type_enum(tname);
skip_nl(ctx);
if (peek(ctx)->type == TOK_L_BRACE) {
advance(ctx); /* { */
}
spl_type_compute_layout(st);
}
/* ============================================================
* Parse enum body
*
* Body supports:
* Name — simple variant
* Name: Type — variant with data
* var name: type; — field-style variant
* type Name = ...; — nested type declarations
* fn name(...) type { } — methods (skipped)
* ============================================================ */
static void parse_enum_body(spl_comp_t *ctx, spl_type_info_t *et) {
if (peek(ctx)->type != TOK_L_BRACE)
return;
advance(ctx); /* { */
/* === Pass 1: Parse all nested type declarations first === */
{
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_TYPE && depth == 1) {
parse_type_decl(ctx);
} else {
advance(ctx);
}
}
ctx->tok_idx = saved;
}
/* === Pass 2: Parse variants and methods === */
{
int depth = 1;
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
skip_nl(ctx);
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
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) { advance(ctx); break; } advance(ctx); }
else if (tt == KW_TYPE && depth == 1) {
/* Already parsed in pass 1, re-parse to skip */
parse_type_decl(ctx);
}
else if (tt == TOK_IDENT && depth == 1) {
/* Variant: Name or Name: Type */
spl_tok_t *vtok = advance(ctx);
skip_nl(ctx);
if (peek(ctx)->type == TOK_COLON) {
@@ -248,16 +351,77 @@ void parse_type_decl(spl_comp_t *ctx) {
spl_type_add_variant(et, vname, NULL);
}
skip_nl(ctx);
if (peek(ctx)->type == TOK_COMMA) {
if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_COMMA)
advance(ctx);
}
else if (tt == KW_FN && depth == 1) {
/* Method — skip */
advance(ctx); /* fn */
while (ctx->tok_idx < vec_size(ctx->toks)) {
spl_tok_type_t mt = peek(ctx)->type;
if (mt == TOK_SEMICOLON) { advance(ctx); break; }
if (mt == TOK_L_BRACE) {
advance(ctx);
int bd = 1;
while (bd > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
if (peek(ctx)->type == TOK_L_BRACE) bd++;
else if (peek(ctx)->type == TOK_R_BRACE) bd--;
advance(ctx);
}
break;
}
advance(ctx);
skip_nl(ctx);
}
}
if (peek(ctx)->type == TOK_R_BRACE)
else {
advance(ctx);
}
}
spl_type_compute_layout(et);
}
spl_type_compute_layout(et);
}
/* ============================================================
* Parse type declaration
* type Name = struct { ... };
* type Name = union { ... };
* type Name = enum { ... };
* type Name = ExistingType;
* ============================================================ */
void parse_type_decl(spl_comp_t *ctx) {
advance(ctx); /* type */
spl_tok_t *name_tok = advance(ctx);
char tname[256];
usize tnl = name_tok->len < 255 ? name_tok->len : 255;
memcpy(tname, name_tok->lexeme, tnl);
tname[tnl] = '\0';
skip_nl(ctx);
expect(ctx, TOK_ASSIGN);
skip_nl(ctx);
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);
skip_nl(ctx);
parse_struct_body(ctx, st);
} 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);
skip_nl(ctx);
parse_struct_body(ctx, ut);
} 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);
skip_nl(ctx);
parse_enum_body(ctx, et);
} 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);