stage1 完成11-13测试
This commit is contained in:
@@ -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,17 +720,13 @@ 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;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Struct field access */
|
||||
|
||||
Reference in New Issue
Block a user