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

@@ -21,6 +21,7 @@ typedef enum {
TYPE_ARRAY,
TYPE_SLICE,
TYPE_STRUCT,
TYPE_UNION,
TYPE_ENUM,
TYPE_ENUM_VARIANT, /* enum variant with data */
TYPE_NAME, /* named alias */
@@ -66,6 +67,7 @@ spl_type_info_t *spl_type_ptr(spl_type_info_t *elem);
spl_type_info_t *spl_type_array(spl_type_info_t *elem, usize len);
spl_type_info_t *spl_type_slice(spl_type_info_t *elem);
spl_type_info_t *spl_type_struct(const char *name);
spl_type_info_t *spl_type_union(const char *name);
spl_type_info_t *spl_type_enum(const char *name);
void spl_type_add_field(spl_type_info_t *st, const char *name, spl_type_info_t *ftype);
void spl_type_add_variant(spl_type_info_t *et, const char *name, spl_type_info_t *dtype);
@@ -251,4 +253,8 @@ void spl_emit_defer_epilogue(spl_comp_t *ctx);
spl_type_info_t *spl_resolve_type(spl_comp_t *ctx, const char *name);
spl_type_info_t *spl_parse_type(spl_comp_t *ctx);
/* Shared token helpers (defined in spl_parser.c) */
spl_tok_t *peek(spl_comp_t *ctx);
spl_tok_t *advance(spl_comp_t *ctx);
#endif /* __SPL_COMP_H__ */

View File

@@ -10,14 +10,7 @@
* Token helpers
* ============================================================ */
static 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 *t = &vec_at(ctx->toks, ctx->tok_idx);
if (t->type != TOK_EOF)
ctx->tok_idx++;
return t;
}
/* Token helpers — using shared peek/advance from spl_parser.c */
static int match(spl_comp_t *ctx, spl_tok_type_t type) {
if (peek(ctx)->type == type) {
@@ -156,6 +149,48 @@ static void emit_slice_index(spl_comp_t *ctx, spl_type_info_t *elem) {
spl_emit(ctx, SPL_ADD, SPL_U64, 0); /* [data_ptr + index * elem_size] */
}
/* Try to resolve Type.Member for compile-time type access:
* - Enum variants → push variant integer value
* - Nested types (struct/enum/union) → return nested type
* Uses qualified name (TypeName.Member) first for namespace isolation,
* then falls back to simple name lookup.
* Returns 1 if resolved. */
static int spl_resolve_type_member(spl_comp_t *ctx, spl_type_info_t *type,
const char *field, spl_expr_result_t *result) {
/* For enum: check variants first */
if (type->kind == TYPE_ENUM) {
vec_for(type->variants, i) {
if (strcmp(vec_at(type->variants, i).name, field) == 0) {
spl_emit(ctx, SPL_PUSH, SPL_I32, vec_at(type->variants, i).value);
*result = (spl_expr_result_t){spl_type_basic(SPL_I32), 0};
return 1;
}
}
}
/* Check nested types — try qualified name (Type.field) first for namespace isolation */
if (type->name) {
char qualified[512];
int qlen = snprintf(qualified, sizeof(qualified), "%s.%s", type->name, field);
if (qlen > 0 && (usize)qlen < sizeof(qualified)) {
spl_type_info_t *nested = spl_resolve_type(ctx, qualified);
if (nested) {
*result = (spl_expr_result_t){nested, 1};
return 1;
}
}
}
/* Fallback: try simple name lookup */
spl_type_info_t *nested = spl_resolve_type(ctx, field);
if (nested) {
*result = (spl_expr_result_t){nested, 1};
return 1;
}
return 0;
}
/* ============================================================
* SIR opcode for binary operator
* ============================================================ */
@@ -470,6 +505,13 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
return r;
}
/* Check if it's a type name (for enum variant access like Color.Red) */
spl_type_info_t *ttype = spl_resolve_type(ctx, name);
if (ttype) {
spl_expr_result_t r = {ttype, 1};
return r;
}
spl_comp_error(ctx, "undefined variable '%s'", name);
spl_expr_result_t r = {0};
return r;
@@ -678,18 +720,14 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
memcpy(fname, field->lexeme, fnl);
fname[fnl] = '\0';
/* Check for enum variant: Type.Variant */
if (left.type && left.type->kind == TYPE_ENUM) {
/* It's a type-level enum reference */
vec_for(left.type->variants, vi) {
if (strcmp(vec_at(left.type->variants, vi).name, fname) == 0) {
spl_emit(ctx, SPL_PUSH, SPL_I32, vec_at(left.type->variants, vi).value);
left = (spl_expr_result_t){spl_type_basic(SPL_I32), 0};
break;
}
}
/* Compile-time type member resolution (enum variants, nested types) */
if (left.type) {
spl_expr_result_t mresult = {0};
if (spl_resolve_type_member(ctx, left.type, fname, &mresult)) {
left = mresult;
continue;
}
}
/* Struct field access */
if (left.type && left.type->kind == TYPE_STRUCT) {

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';
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);
skip_nl(ctx);
if (peek(ctx)->type == TOK_L_BRACE) {
static void parse_struct_body(spl_comp_t *ctx, spl_type_info_t *st) {
if (peek(ctx)->type != TOK_L_BRACE)
return;
advance(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;
}
/* === Pass 2: Parse fields and methods === */
{
int depth = 1;
while (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) { 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);
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
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);
}
}
if (peek(ctx)->type == TOK_R_BRACE)
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);
}
}
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) {
}
/* ============================================================
* 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) {
advance(ctx);
skip_nl(ctx);
}
}
if (peek(ctx)->type == TOK_R_BRACE)
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);
}
}
else {
advance(ctx);
}
}
}
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);

View File

@@ -4,14 +4,7 @@
#include <stdlib.h>
#include <string.h>
static 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 *t = &vec_at(ctx->toks, ctx->tok_idx);
if (t->type != TOK_EOF)
ctx->tok_idx++;
return t;
}
/* Token helpers — using shared peek/advance from spl_parser.c */
static int expect(spl_comp_t *ctx, spl_tok_type_t type) {
if (peek(ctx)->type == type) {

View File

@@ -136,6 +136,16 @@ spl_type_info_t *spl_type_struct(const char *name) {
return t;
}
spl_type_info_t *spl_type_union(const char *name) {
spl_type_info_t *t = calloc(1, sizeof(spl_type_info_t));
t->kind = TYPE_UNION;
if (name)
t->name = strdup(name);
vec_init(t->fields);
t->resolved = 0;
return t;
}
spl_type_info_t *spl_type_enum(const char *name) {
spl_type_info_t *t = calloc(1, sizeof(spl_type_info_t));
t->kind = TYPE_ENUM;
@@ -168,20 +178,34 @@ void spl_type_compute_layout(spl_type_info_t *t) {
if (!t || t->resolved)
return;
if (t->kind == TYPE_STRUCT) {
if (t->kind == TYPE_STRUCT || t->kind == TYPE_UNION) {
usize offset = 0;
usize max_field_size = 0;
vec_for(t->fields, i) {
spl_field_t *f = &vec_at(t->fields, i);
if (f->type) {
spl_type_compute_layout(f->type);
if (t->kind == TYPE_UNION) {
/* Union: all fields at offset 0, size = max field size */
f->offset = 0;
if (f->type->byte_size > max_field_size)
max_field_size = f->type->byte_size;
} else {
/* Struct: sequential layout */
f->offset = offset;
offset += f->type->byte_size;
}
}
}
if (t->kind == TYPE_UNION) {
t->byte_size = max_field_size;
} else {
t->byte_size = offset;
}
/* Round up to slot alignment */
usize slot_sz = sizeof(spl_val_t);
t->slot_count = (offset + slot_sz - 1) / slot_sz;
t->slot_count = (t->byte_size + slot_sz - 1) / slot_sz;
if (t->slot_count < 1) t->slot_count = 1;
t->resolved = 1;
} else if (t->kind == TYPE_ENUM) {
/* Enums with data need special handling */
@@ -287,6 +311,8 @@ const char *spl_type_str(spl_type_info_t *t) {
}
case TYPE_STRUCT:
return t->name ? t->name : "struct";
case TYPE_UNION:
return t->name ? t->name : "union";
case TYPE_ENUM:
return t->name ? t->name : "enum";
case TYPE_NAME:
@@ -355,6 +381,67 @@ spl_type_info_t *spl_parse_type(spl_comp_t *ctx) {
return spl_type_array(elem, len);
}
/* Inline struct/union/enum type: struct { field: type, ... } */
if (tok->type == KW_STRUCT || tok->type == KW_UNION) {
int is_union = (tok->type == KW_UNION);
ctx->tok_idx++;
spl_type_info_t *t = is_union ? spl_type_union(NULL) : spl_type_struct(NULL);
if (peek(ctx)->type == TOK_L_BRACE) {
advance(ctx); /* { */
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
spl_tok_t *ftok = advance(ctx);
if (peek(ctx)->type == TOK_COLON) {
advance(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(t, fname, ftype);
}
if (peek(ctx)->type == TOK_COMMA)
advance(ctx);
}
if (peek(ctx)->type == TOK_R_BRACE)
advance(ctx);
}
spl_type_compute_layout(t);
return t;
}
/* Inline enum type: enum { A, B, C, ... } */
if (tok->type == KW_ENUM) {
ctx->tok_idx++;
spl_type_info_t *t = spl_type_enum(NULL);
if (peek(ctx)->type == TOK_L_BRACE) {
advance(ctx); /* { */
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
spl_tok_t *vtok = advance(ctx);
if (peek(ctx)->type == TOK_COLON) {
advance(ctx); /* : */
spl_type_info_t *dtype = spl_parse_type(ctx);
char vname[256];
usize vnl = vtok->len < 255 ? vtok->len : 255;
memcpy(vname, vtok->lexeme, vnl);
vname[vnl] = '\0';
spl_type_add_variant(t, vname, dtype);
} else {
char vname[256];
usize vnl = vtok->len < 255 ? vtok->len : 255;
memcpy(vname, vtok->lexeme, vnl);
vname[vnl] = '\0';
spl_type_add_variant(t, vname, NULL);
}
if (peek(ctx)->type == TOK_COMMA)
advance(ctx);
}
if (peek(ctx)->type == TOK_R_BRACE)
advance(ctx);
}
spl_type_compute_layout(t);
return t;
}
/* Identifier: basic type or named type */
if (tok->type == TOK_IDENT || ((int)tok->type >= (int)KW_AS && (int)tok->type <= (int)KW_ANY)) {
const char *name = tok->lexeme;

View File

@@ -28,12 +28,18 @@ fn main() i32 {
with_cleanup();
vm_printf("after with_cleanup\n");
/* 多个 defer 应逆序执行出作用域应该立刻执行,包括循环作用域 */
{
defer vm_printf("block defer last\n");
defer vm_printf("block defer middle\n");
defer vm_printf("block defer first (should print third)\n");
}
/* 多个 defer 应逆序执行 */
defer vm_printf("defer last\n");
defer vm_printf("defer middle\n");
defer vm_printf("defer first (should print third)\n");
vm_printf("--- defer test end ---\n");
ret 0;
}