stage2 更多的工具函数 stage1支持更多的内置函数

This commit is contained in:
zzy committed 2026-09-17 18:47:56 +08:00
1 parent 1a6df012cd
commit b8e2bba140
10 files changed
+1713 -7

No files matched your search

+4 -3
View File
@@ -361,6 +361,10 @@ static spl_ir_node_ref_t ast2ir_intrin_cast(spl_ast2ir_t *a, spl_ast_node_t *n,
static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in,
spl_ast_node_ref_vec_t *args) {
switch (in) {
case SPL_INTRIN_BITSIZEOF: {
spl_ast_node_t *arg = spl_ast_node(a->ast, vec_at(*args, 0));
return spl_ir_builder_type_bitsizeof(a->ir, node_ir(a, arg));
}
case SPL_INTRIN_SIZEOF: {
spl_ast_node_t *arg = spl_ast_node(a->ast, vec_at(*args, 0));
return spl_ir_builder_type_sizeof(a->ir, node_ir(a, arg));
@@ -501,9 +505,6 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_lang_type_kind_t obj_kind = obj_ln->kind;
spl_lang_type_id_t obj_elem = (obj_kind == SPL_LANG_TYPE_PTR) ? obj_ln->extra.elem : 0;
if (spl_intrin_lookup_field(obj_kind, n->field.field) != SPL_INTRIN_NONE)
return 0;
spl_ir_node_ref_t base = 0;
spl_lang_type_id_t agg_lang = 0;
if (obj_kind == SPL_LANG_TYPE_PTR) {
+3 -1
View File
@@ -2,6 +2,8 @@
static const spl_intrin_info_t g_intrin_table[] = {
[SPL_INTRIN_NONE] = {0},
[SPL_INTRIN_BITSIZEOF] = {"@bitsizeof", SPL_INTRIN_BITSIZEOF, SPL_INTRIN_FORM_CALL, 1, 1,
SPL_INTRIN_RESULT_USIZE},
[SPL_INTRIN_SIZEOF] = {"@sizeof", SPL_INTRIN_SIZEOF, SPL_INTRIN_FORM_CALL, 1, 1,
SPL_INTRIN_RESULT_USIZE},
[SPL_INTRIN_ALIGNOF] = {"@alignof", SPL_INTRIN_ALIGNOF, SPL_INTRIN_FORM_CALL, 1, 1,
@@ -96,4 +98,4 @@ spl_intrin_t spl_intrin_lookup_cast(spl_type_t *type, spl_type_id_t ft, spl_type
/* int float 刻意不在这里:只能通过显式 builtin 调用。 */
return SPL_INTRIN_NONE;
}
}
+1
View File
@@ -6,6 +6,7 @@
typedef enum {
SPL_INTRIN_NONE = 0,
SPL_INTRIN_BITSIZEOF,
SPL_INTRIN_SIZEOF,
SPL_INTRIN_ALIGNOF,
SPL_INTRIN_ASSERT,
+142 -3
View File
@@ -746,8 +746,6 @@ static void sema_collect_types(spl_sema_t *sema, spl_ast_node_ref_t ref) {
if (pat->kind == SPL_AST_PATTERN_IDENT) {
if (d->resolved_def_id)
sema_eval_decl(sema, d->resolved_def_id);
} else {
sema_do_type_unpack(sema, d, pat, d->type_decl.type_expr);
}
}
break;
@@ -772,6 +770,144 @@ static void sema_collect_signatures(spl_sema_t *sema) {
}
}
static int sema_def_is_type(const spl_def_node_t *def) {
if (!def)
return 0;
switch (def->kind) {
case SPL_DEF_SCALAR:
case SPL_DEF_AGG:
case SPL_DEF_DISTINCT:
case SPL_DEF_ALIAS:
case SPL_DEF_BUILTIN:
return 1;
default:
return 0;
}
}
/* 解包声明本身不会在 collect_names 阶段建立符号,因此必须在构建模块根
* 聚合之前处理。否则根字段无法引用通过 `type .{ ... } = source` 导入的类型。 */
static void sema_collect_type_unpacks(spl_sema_t *sema, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(sema->ast, ref);
if (!n)
return;
switch (n->kind) {
case SPL_AST_CONTAINER_MEMBERS:
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i);
spl_ast_node_t *d = spl_ast_node(sema->ast, dref);
if (!d || d->kind != SPL_AST_TYPE_DECL)
continue;
spl_ast_node_t *pat = spl_ast_node(sema->ast, d->type_decl.pattern);
if (pat && pat->kind != SPL_AST_PATTERN_IDENT)
sema_do_type_unpack(sema, d, pat, d->type_decl.type_expr);
}
break;
case SPL_AST_TOP_LEVEL_BLOCK:
if (n->top_level_block.block)
sema_collect_type_unpacks(sema, n->top_level_block.block);
break;
default:
break;
}
}
/* @sizeof/@bitsizeof/@alignof 的参数在语法层仍是普通 Expr。
intrinsic 的类型上下文在这里解释表达式形态,不要求 parser 识别 intrinsic。 */
static spl_lang_type_id_t sema_infer_type_context(spl_sema_t *sema, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(sema->ast, ref);
if (!n)
return 0;
switch (n->kind) {
case SPL_AST_EXPR_IDENT: {
spl_lang_type_id_t builtin = spl_type_lookup_builtin(sema->type, n->ident.name);
if (builtin) {
n->resolved_lang_tid = builtin;
return builtin;
}
spl_symbol_t symbol;
if (!spl_scope_find(sema->scope, n->ident.name, &symbol) ||
symbol.kind != SPL_SYMBOL_KIND_TYPE) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"`%s` is not a type", n->ident.name);
return 0;
}
spl_def_node_t *def = spl_def_node(sema->type, symbol.node);
if (!sema_def_is_type(def)) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"`%s` is not a type", n->ident.name);
return 0;
}
n->resolved_def_id = symbol.node;
spl_lang_type_id_t result = sema_eval_decl(sema, symbol.node);
n->resolved_lang_tid = result;
return result;
}
case SPL_AST_EXPR_FIELD: {
spl_lang_type_id_t owner_id = sema_infer_type_context(sema, n->field.obj);
spl_lang_type_node_t *owner = spl_lang_type_node(sema->type, owner_id);
if (!owner)
return 0;
for (usize i = 0; i < vec_size(owner->methods); ++i) {
spl_lang_method_t *member = &vec_at(owner->methods, i);
if (strcmp(member->name, n->field.field) != 0)
continue;
spl_def_node_t *def = spl_def_node(sema->type, member->def_id);
if (!sema_def_is_type(def))
break;
n->resolved_def_id = member->def_id;
spl_lang_type_id_t result = sema_eval_decl(sema, member->def_id);
n->resolved_lang_tid = result;
return result;
}
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"`%s` is not a type member", n->field.field);
return 0;
}
case SPL_AST_EXPR_UNARY:
if (n->unary.op == SPL_UNARY_OP_DEREF) {
spl_lang_type_id_t pointee = sema_infer_type_context(sema, n->unary.operand);
if (!pointee)
return 0;
spl_lang_type_id_t result = spl_lang_make_ptr(sema->type, pointee);
n->resolved_lang_tid = result;
return result;
}
break;
case SPL_AST_EXPR_TUPLE: {
spl_lang_type_id_vec_t elements;
vec_init(elements);
for (usize i = 0; i < vec_size(n->tuple.elems); ++i) {
spl_lang_type_id_t element =
sema_infer_type_context(sema, vec_at(n->tuple.elems, i));
if (!element) {
vec_free(elements);
return 0;
}
vec_push(elements, element);
}
spl_lang_type_id_t result = spl_lang_make_tuple(
sema->type, vec_unsafe_get_data(elements), vec_size(elements));
vec_free(elements);
n->resolved_lang_tid = result;
return result;
}
case SPL_AST_EXPR_COMPTIME_CALL: {
spl_lang_type_id_t result = sema_infer(sema, ref);
n->resolved_lang_tid = result;
return result;
}
default:
break;
}
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"intrinsic argument is not a type expression");
return 0;
}
static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in,
spl_ast_node_ref_vec_t *args) {
const spl_intrin_info_t *info = spl_intrin_info(in);
@@ -784,9 +920,11 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
}
switch (in) {
case SPL_INTRIN_BITSIZEOF:
case SPL_INTRIN_SIZEOF:
case SPL_INTRIN_ALIGNOF: {
sema_infer(sema, vec_at(*args, 0));
if (!sema_infer_type_context(sema, vec_at(*args, 0)))
return 0;
return spl_lang_make_int(sema->type, sizeof(void *) * 8, 0);
}
case SPL_INTRIN_ASSERT: {
@@ -2600,6 +2738,7 @@ void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) {
spl_lang_type_id_t saved_agg = sema->current_aggregate_lang;
sema_collect_names(sema, module_ref);
sema_collect_type_unpacks(sema, module_ref);
spl_lang_type_id_t container_lang = 0;
if (mod->resolved_def_id)