stage2 更多的工具函数 stage1支持更多的内置函数
This commit is contained in:
1 parent
1a6df012cd
commit
b8e2bba140
10 files changed
+1713
-7
No files matched your search
+4
-3
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
typedef enum {
|
||||
SPL_INTRIN_NONE = 0,
|
||||
SPL_INTRIN_BITSIZEOF,
|
||||
SPL_INTRIN_SIZEOF,
|
||||
SPL_INTRIN_ALIGNOF,
|
||||
SPL_INTRIN_ASSERT,
|
||||
|
||||
+142
-3
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user