stage1 实现更多ast2ir 修复bug 提供内置操作
This commit is contained in:
1 parent
ab6e99c958
commit
49ccdec3dd
10 files changed
+396
-76
No files matched your search
+25
-14
@@ -311,7 +311,8 @@ static void parse_tag_list(parser_t *p, spl_ast_node_ref_vec_t *out, int is_exte
|
||||
t = peek(p);
|
||||
if (t && t->type == TOK_L_PAREN) {
|
||||
advance(p);
|
||||
tag->tag_item.args = parse_expr_list(p);
|
||||
spl_ast_node_ref_vec_t args = parse_expr_list(p);
|
||||
node_at(p->ast, ref)->tag_item.args = args;
|
||||
t = peek(p);
|
||||
if (!t || t->type != TOK_R_PAREN) {
|
||||
SPL_FATAL(t, "expected ')' in tag args");
|
||||
@@ -474,7 +475,8 @@ static spl_ast_node_ref_t parse_type_decl(parser_t *p, spl_ast_node_ref_vec_t ta
|
||||
spl_ast_node_t *td = node_at(p->ast, ref);
|
||||
MOVE_VEC(td->type_decl.attr_list, tag_list);
|
||||
SET_STR_FIELD(p->ast, td->type_decl.name, name);
|
||||
td->type_decl.type_expr = parse_type_expr(p);
|
||||
spl_ast_node_ref_t type_expr = parse_type_expr(p);
|
||||
node_at(p->ast, ref)->type_decl.type_expr = type_expr;
|
||||
|
||||
t = peek(p);
|
||||
if (t && (t->type == TOK_COMMA || t->type == TOK_SEMICOLON)) {
|
||||
@@ -645,13 +647,15 @@ static spl_ast_node_ref_t parse_var_pattern_atom(parser_t *p) {
|
||||
return 0;
|
||||
}
|
||||
advance(p);
|
||||
|
||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_PATTERN_DOT, t);
|
||||
spl_ast_node_t *pat = node_at(p->ast, ref);
|
||||
SET_STR_FIELD(p->ast, pat->pattern_dot.name, name);
|
||||
|
||||
if (peek(p) && peek(p)->type == TOK_L_BRACKET) {
|
||||
advance(p);
|
||||
pat->pattern_dot.sub_pattern = parse_var_pattern(p);
|
||||
spl_ast_node_ref_t sub = parse_var_pattern(p);
|
||||
node_at(p->ast, ref)->pattern_dot.sub_pattern = sub;
|
||||
t = peek(p);
|
||||
if (!t || t->type != TOK_R_BRACKET) {
|
||||
SPL_FATAL(t, "expected ']' in pattern");
|
||||
@@ -778,8 +782,8 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
|
||||
|
||||
if (peek(p) && peek(p)->type == TOK_COLON) {
|
||||
advance(p);
|
||||
fn_type = node_at(p->ast, ref);
|
||||
fn_type->type_fn.ret_type = parse_type_expr(p);
|
||||
spl_ast_node_ref_t ret = parse_type_expr(p);
|
||||
node_at(p->ast, ref)->type_fn.ret_type = ret;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
@@ -948,7 +952,8 @@ static spl_ast_node_ref_t parse_type_expr(parser_t *p) {
|
||||
if (t->type == TOK_MUL) {
|
||||
advance(p);
|
||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_POINTER, t);
|
||||
node_at(p->ast, ref)->type_pointer.pointee = parse_type_expr(p);
|
||||
spl_ast_node_ref_t pointee = parse_type_expr(p);
|
||||
node_at(p->ast, ref)->type_pointer.pointee = pointee;
|
||||
return ref;
|
||||
}
|
||||
|
||||
@@ -1292,7 +1297,10 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
|
||||
advance(p);
|
||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_CALL, t);
|
||||
node_at(p->ast, ref)->call.callee = expr;
|
||||
node_at(p->ast, ref)->call.args = parse_expr_list(p);
|
||||
|
||||
spl_ast_node_ref_vec_t args = parse_expr_list(p);
|
||||
node_at(p->ast, ref)->call.args = args;
|
||||
|
||||
t = peek(p);
|
||||
if (!t || t->type != TOK_R_PAREN) {
|
||||
SPL_FATAL(t, "expected ')' in call");
|
||||
@@ -1415,14 +1423,15 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
||||
case TOK_IDENT: {
|
||||
advance(p);
|
||||
if (peek(p) && peek(p)->type == TOK_L_BRACE && !p->stop_agg) {
|
||||
// 具名聚合字面量:Identifier { fields }
|
||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_AGGREGATE_LIT, t);
|
||||
spl_ast_node_t *agg = node_at(p->ast, ref);
|
||||
agg->aggregate_literal.name = intern_string(p->ast, t->lexeme, t->len);
|
||||
agg->aggregate_literal.fields = parse_aggregate_fields(p);
|
||||
|
||||
spl_ast_node_ref_vec_t fields = parse_aggregate_fields(p);
|
||||
node_at(p->ast, ref)->aggregate_literal.fields = fields;
|
||||
return ref;
|
||||
}
|
||||
// 普通标识符引用
|
||||
/* 普通标识符 */
|
||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_IDENT, t);
|
||||
node_at(p->ast, ref)->ident.name = intern_string(p->ast, t->lexeme, t->len);
|
||||
return ref;
|
||||
@@ -1435,11 +1444,11 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
|
||||
return 0;
|
||||
}
|
||||
if (nx->type == TOK_L_BRACE && !p->stop_agg) {
|
||||
// 匿名聚合字面量:. { fields }
|
||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_AGGREGATE_LIT, t);
|
||||
spl_ast_node_t *agg = node_at(p->ast, ref);
|
||||
agg->aggregate_literal.name = NULL;
|
||||
agg->aggregate_literal.fields = parse_aggregate_fields(p);
|
||||
node_at(p->ast, ref)->aggregate_literal.name = NULL;
|
||||
|
||||
spl_ast_node_ref_vec_t fields = parse_aggregate_fields(p);
|
||||
node_at(p->ast, ref)->aggregate_literal.fields = fields;
|
||||
return ref;
|
||||
} else if (nx->type == TOK_L_BRACKET) {
|
||||
// 匿名数组字面量:. [ elems ]
|
||||
@@ -1934,6 +1943,8 @@ static spl_ast_node_ref_t parse_match_expr(parser_t *p) {
|
||||
spl_ast_node_t *arm_node = node_at(p->ast, arm);
|
||||
arm_node->match_arm.pattern = patterns.data[i];
|
||||
arm_node->match_arm.body = bodies.data[i];
|
||||
|
||||
me = node_at(p->ast, ref); /* 每次迭代重新获取 防止 new_node 扩容 */
|
||||
vec_push(me->match_expr.arms, arm);
|
||||
}
|
||||
vec_free(patterns);
|
||||
|
||||
+154
-11
@@ -1,5 +1,5 @@
|
||||
#include "spl_ast2ir.h"
|
||||
#include <string.h>
|
||||
#include "spl_intrin.h"
|
||||
|
||||
static spl_type_id_t to_ir_type(spl_ast2ir_t *a, spl_lang_type_id_t lang) {
|
||||
if (!lang)
|
||||
@@ -32,6 +32,70 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n);
|
||||
static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
||||
static spl_ir_node_ref_t emit_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);
|
||||
static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in);
|
||||
static spl_ir_node_ref_t ast2ir_intrin_len(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) {
|
||||
switch (in) {
|
||||
case SPL_INTRIN_SIZEOF: {
|
||||
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(n->call.args, 0));
|
||||
return spl_ir_builder_type_sizeof(a->ir, node_ir(a, arg));
|
||||
}
|
||||
case SPL_INTRIN_ALIGNOF: {
|
||||
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(n->call.args, 0));
|
||||
return spl_ir_builder_type_alignof(a->ir, node_ir(a, arg));
|
||||
}
|
||||
case SPL_INTRIN_ASSERT: {
|
||||
/* 目前 SEMA 只做类型检查,emit 阶段留空,
|
||||
@assert 展开需待 control.trap 语义明确后再实现 */
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in) {
|
||||
switch (in) {
|
||||
case SPL_INTRIN_LEN:
|
||||
return ast2ir_intrin_len(a, n);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj);
|
||||
spl_lang_type_id_t recv_lang = node_lang(a, obj);
|
||||
spl_lang_type_node_t *recv = spl_lang_type_node(a->sema->type, recv_lang);
|
||||
if (!recv)
|
||||
return 0;
|
||||
|
||||
spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
|
||||
spl_type_id_t usize_ir = to_ir_type(a, usize_lang);
|
||||
|
||||
switch (recv->kind) {
|
||||
case SPL_LANG_TYPE_ARRAY: {
|
||||
spl_type_node_t *arr = spl_type_node(a->sema->type, recv->ir_type_id);
|
||||
if (!arr)
|
||||
return 0;
|
||||
return spl_ir_builder_type_const_int(a->ir, usize_ir, arr->array_type.len);
|
||||
}
|
||||
case SPL_LANG_TYPE_SLICE: {
|
||||
spl_ir_node_ref_t slice_val = emit_expr(a, n->field.obj);
|
||||
if (!slice_val)
|
||||
return 0;
|
||||
return spl_ir_builder_agg_extract(a->ir, usize_ir, usize_ir, SPL_SLICE_LEN_FIELD_IDX,
|
||||
slice_val);
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
|
||||
if (!n)
|
||||
@@ -55,6 +119,8 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||
spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang);
|
||||
if (!obj_ln)
|
||||
return 0;
|
||||
if (spl_intrin_lookup_field(obj_ln->kind, n->field.field) != SPL_INTRIN_NONE)
|
||||
return 0; /* 内建字段不是左值 */
|
||||
|
||||
spl_ir_node_ref_t base = 0;
|
||||
spl_lang_type_id_t agg_lang = 0;
|
||||
@@ -97,9 +163,20 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||
if (obj_ln->kind == SPL_LANG_TYPE_PTR) {
|
||||
base = emit_expr(a, n->index.obj);
|
||||
elem_lang = obj_ln->extra.elem;
|
||||
} else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY || obj_ln->kind == SPL_LANG_TYPE_SLICE) {
|
||||
} else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) {
|
||||
base = emit_lvalue(a, n->index.obj);
|
||||
elem_lang = obj_ln->extra.elem;
|
||||
} else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) {
|
||||
/* 切片:取出切片值,再 agg_extract 出 ptr 字段 */
|
||||
spl_ir_node_ref_t slice_val = emit_expr(a, n->index.obj);
|
||||
if (!slice_val)
|
||||
return 0;
|
||||
spl_lang_type_id_t elem = obj_ln->extra.elem;
|
||||
spl_type_id_t ptr_ir = spl_type_builder_ptr(a->sema->type, to_ir_type(a, elem));
|
||||
spl_ir_node_ref_t ptr = spl_ir_builder_agg_extract(a->ir, ptr_ir, ptr_ir,
|
||||
SPL_SLICE_PTR_FIELD_IDX, slice_val);
|
||||
base = ptr;
|
||||
elem_lang = elem;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@@ -315,6 +392,13 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
}
|
||||
case SPL_AST_EXPR_CALL: {
|
||||
spl_ast_node_t *callee = spl_ast_node(a->sema->ast, n->call.callee);
|
||||
if (callee && callee->kind == SPL_AST_EXPR_IDENT) {
|
||||
spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name);
|
||||
if (in != SPL_INTRIN_NONE)
|
||||
return ast2ir_intrin_call(a, n, in);
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t fn = emit_expr(a, n->call.callee);
|
||||
if (!fn)
|
||||
return 0;
|
||||
@@ -331,6 +415,14 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||
return call;
|
||||
}
|
||||
case SPL_AST_EXPR_FIELD: {
|
||||
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj);
|
||||
spl_lang_type_id_t obj_lang = node_lang(a, obj);
|
||||
spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang);
|
||||
if (obj_ln) {
|
||||
spl_intrin_t in = spl_intrin_lookup_field(obj_ln->kind, n->field.field);
|
||||
if (in != SPL_INTRIN_NONE)
|
||||
return ast2ir_intrin_field(a, n, in);
|
||||
}
|
||||
spl_ir_node_ref_t ptr = emit_lvalue(a, ref);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
@@ -436,7 +528,56 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||
emit_stmt(a, ref);
|
||||
return 0;
|
||||
}
|
||||
case SPL_AST_EXPR_SLICE: {
|
||||
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->slice.obj);
|
||||
spl_lang_type_id_t obj_lang = node_lang(a, obj);
|
||||
spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang);
|
||||
if (!obj_ln)
|
||||
return 0;
|
||||
|
||||
/* 目前只处理数组->切片的完整形式 arr[..](无 begin / end)
|
||||
或 arr[begin..end] 的通用形式。简化实现只做完整切片。 */
|
||||
spl_type_id_t slice_ir = node_ir(a, n); /* struct{ptr, len} */
|
||||
if (!slice_ir)
|
||||
return 0;
|
||||
|
||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, slice_ir);
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
/* 取数组元素指针 */
|
||||
spl_ir_node_ref_t base = emit_lvalue(a, n->slice.obj);
|
||||
if (!base)
|
||||
return 0;
|
||||
|
||||
spl_type_id_t ptr_ir =
|
||||
spl_type_builder_ptr(a->sema->type, to_ir_type(a, obj_ln->extra.elem));
|
||||
|
||||
/* 字段 0:ptr */
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, base);
|
||||
|
||||
/* 字段 1:len —— 数组取 len,切片取原切片 len */
|
||||
spl_ir_node_ref_t len = 0;
|
||||
if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) {
|
||||
spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ln->ir_type_id);
|
||||
spl_lang_type_id_t usize = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
|
||||
len = spl_ir_builder_type_const_int(a->ir, to_ir_type(a, usize), arr->array_type.len);
|
||||
} else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) {
|
||||
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
|
||||
spl_lang_type_id_t usize = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
|
||||
len = spl_ir_builder_agg_extract(a->ir, to_ir_type(a, usize), to_ir_type(a, usize),
|
||||
SPL_SLICE_LEN_FIELD_IDX, slice_val);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, len);
|
||||
return node;
|
||||
}
|
||||
case SPL_AST_EXPR_COMPTIME_CALL:
|
||||
// TODO
|
||||
return 0;
|
||||
default:
|
||||
TODO();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -449,18 +590,15 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||
switch (n->kind) {
|
||||
case SPL_AST_STATEMENT_RET: {
|
||||
while (vec_size(a->defer_stack) > 0) {
|
||||
spl_ast_node_ref_t d = vec_at(a->defer_stack, vec_size(a->defer_stack) - 1);
|
||||
vec_pop(a->defer_stack);
|
||||
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
|
||||
emit_stmt(a, d);
|
||||
}
|
||||
spl_type_id_t ret_ir = to_ir_type(a, a->cur_ret_lang);
|
||||
if (n->statement_ret.expr) {
|
||||
spl_ast_node_t *en = spl_ast_node(a->sema->ast, n->statement_ret.expr);
|
||||
spl_ir_node_ref_t v = emit_expr(a, n->statement_ret.expr);
|
||||
spl_type_id_t t = node_ir(a, en);
|
||||
spl_ir_builder_control_ret(a->ir, t, v);
|
||||
spl_ir_builder_control_ret(a->ir, ret_ir, v);
|
||||
} else {
|
||||
spl_lang_type_id_t rt = a->sema->current_fn_ret_tid;
|
||||
spl_ir_builder_control_ret(a->ir, to_ir_type(a, rt), 0);
|
||||
spl_ir_builder_control_ret(a->ir, ret_ir, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -722,6 +860,9 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||
spl_ir_func_ref_t fn_ref = spl_ir_builder_fn_begin(a->ir, n->fn_decl.name, fn_ir, attr);
|
||||
map_put(a->def2ir_map, n->resolved_def_id, (spl_ir_node_ref_t)fn_ref);
|
||||
|
||||
spl_lang_type_id_t saved_ret = a->cur_ret_lang;
|
||||
a->cur_ret_lang = fn_ln->extra.fn.ret;
|
||||
|
||||
usize defer_base = vec_size(a->defer_stack);
|
||||
usize loop_base = vec_size(a->loop_stack);
|
||||
|
||||
@@ -753,7 +894,6 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||
emit_expr(a, n->fn_decl.body);
|
||||
|
||||
if (!a->ir->terminated) {
|
||||
/* 隐式返回路径:先跑 defer(LIFO),再 ret/unreachable */
|
||||
while (vec_size(a->defer_stack) > defer_base) {
|
||||
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
|
||||
emit_stmt(a, d);
|
||||
@@ -783,6 +923,8 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||
vec_pop(a->loop_stack);
|
||||
}
|
||||
|
||||
a->cur_ret_lang = saved_ret;
|
||||
|
||||
spl_ir_builder_block_end(a->ir);
|
||||
spl_ir_builder_fn_end(a->ir);
|
||||
}
|
||||
@@ -827,6 +969,7 @@ void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_
|
||||
vec_init(ast2ir->loop_stack);
|
||||
vec_init(ast2ir->defer_stack);
|
||||
ast2ir->err_count = 0;
|
||||
ast2ir->cur_ret_lang = 0;
|
||||
}
|
||||
|
||||
void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) {
|
||||
@@ -845,4 +988,4 @@ void spl_ast2ir_run(spl_ast2ir_t *ast2ir) {
|
||||
if (!root || root->kind != SPL_AST_ROOT)
|
||||
return;
|
||||
emit_container(ast2ir, root->root.members);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -21,6 +21,7 @@ typedef struct {
|
||||
spl_def2ir_map_t def2ir_map;
|
||||
spl_loop_ctx_vec_t loop_stack;
|
||||
spl_defer_stack_t defer_stack;
|
||||
spl_lang_type_id_t cur_ret_lang;
|
||||
int err_count;
|
||||
} spl_ast2ir_t;
|
||||
|
||||
@@ -29,4 +30,4 @@ void spl_ast2ir_drop(spl_ast2ir_t *ast2ir);
|
||||
|
||||
void spl_ast2ir_run(spl_ast2ir_t *ast2ir);
|
||||
|
||||
#endif /* __SPL_AST2IR_H__ */
|
||||
#endif /* __SPL_AST2IR_H__ */
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "spl_intrin.h"
|
||||
|
||||
static const spl_intrin_info_t g_intrin_table[] = {
|
||||
[SPL_INTRIN_NONE] = {0},
|
||||
[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,
|
||||
SPL_INTRIN_RESULT_USIZE},
|
||||
[SPL_INTRIN_ASSERT] = {"@assert", SPL_INTRIN_ASSERT, SPL_INTRIN_FORM_CALL, 1, 2,
|
||||
SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_LEN] = {"len", SPL_INTRIN_LEN, SPL_INTRIN_FORM_FIELD, 0, 0,
|
||||
SPL_INTRIN_RESULT_USIZE},
|
||||
};
|
||||
|
||||
static const usize g_intrin_count = sizeof(g_intrin_table) / sizeof(g_intrin_table[0]);
|
||||
|
||||
const spl_intrin_info_t *spl_intrin_info(spl_intrin_t kind) {
|
||||
if ((usize)kind >= g_intrin_count)
|
||||
return NULL;
|
||||
return &g_intrin_table[kind];
|
||||
}
|
||||
|
||||
spl_intrin_t spl_intrin_lookup_call(const char *name) {
|
||||
if (!name)
|
||||
return SPL_INTRIN_NONE;
|
||||
const char *n = name[0] == '@' ? name + 1 : name;
|
||||
for (usize i = 1; i < g_intrin_count; ++i) {
|
||||
const spl_intrin_info_t *d = &g_intrin_table[i];
|
||||
if (d->form != SPL_INTRIN_FORM_CALL)
|
||||
continue;
|
||||
const char *dn = d->name[0] == '@' ? d->name + 1 : d->name;
|
||||
if (strcmp(dn, n) == 0)
|
||||
return d->kind;
|
||||
}
|
||||
return SPL_INTRIN_NONE;
|
||||
}
|
||||
|
||||
spl_intrin_t spl_intrin_lookup_field(spl_lang_type_kind_t recv_kind, const char *field) {
|
||||
if (!field)
|
||||
return SPL_INTRIN_NONE;
|
||||
if (strcmp(field, "len") == 0) {
|
||||
if (recv_kind == SPL_LANG_TYPE_ARRAY || recv_kind == SPL_LANG_TYPE_SLICE)
|
||||
return SPL_INTRIN_LEN;
|
||||
}
|
||||
return SPL_INTRIN_NONE;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef __SPL_INTRIN_H__
|
||||
#define __SPL_INTRIN_H__
|
||||
|
||||
#include "../stage0/include/utils.h"
|
||||
#include "spl_type.h"
|
||||
|
||||
typedef enum {
|
||||
SPL_INTRIN_NONE = 0,
|
||||
SPL_INTRIN_SIZEOF,
|
||||
SPL_INTRIN_ALIGNOF,
|
||||
SPL_INTRIN_ASSERT,
|
||||
SPL_INTRIN_LEN,
|
||||
} spl_intrin_t;
|
||||
|
||||
typedef enum {
|
||||
SPL_INTRIN_FORM_CALL = 1, /* @sizeof(...) @assert(...) */
|
||||
SPL_INTRIN_FORM_FIELD = 2, /* recv.len */
|
||||
} spl_intrin_form_t;
|
||||
|
||||
typedef enum {
|
||||
SPL_INTRIN_RESULT_UNIT,
|
||||
SPL_INTRIN_RESULT_BOOL,
|
||||
SPL_INTRIN_RESULT_USIZE,
|
||||
} spl_intrin_result_t;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
spl_intrin_t kind;
|
||||
spl_intrin_form_t form;
|
||||
int min_args; /* FIELD 形态忽略 */
|
||||
int max_args; /* -1 = variadic */
|
||||
spl_intrin_result_t result;
|
||||
} spl_intrin_info_t;
|
||||
|
||||
/* 统一入口:名字 → 枚举。name 允许带或不带 '@'。 */
|
||||
spl_intrin_t spl_intrin_lookup_call(const char *name);
|
||||
|
||||
/* 统一入口:字段形态,按接收者类型分派。 */
|
||||
spl_intrin_t spl_intrin_lookup_field(spl_lang_type_kind_t recv_kind, const char *field);
|
||||
|
||||
/* 从枚举取得元数据,SEMA/AST2IR 都从这里读。 */
|
||||
const spl_intrin_info_t *spl_intrin_info(spl_intrin_t kind);
|
||||
|
||||
/* ---- 与 IR 侧共享的类型布局约定 ---- */
|
||||
#define SPL_SLICE_PTR_FIELD_IDX 0
|
||||
#define SPL_SLICE_LEN_FIELD_IDX 1
|
||||
|
||||
#endif /* __SPL_INTRIN_H__ */
|
||||
+4
-2
@@ -773,9 +773,11 @@ spl_ir_node_ref_t spl_ir_builder_control_unreachable(spl_ir_builder_t *b) {
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b) {
|
||||
return builder_alloc_node(b, SPL_IR_CONTROL_TRAP);
|
||||
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_TRAP);
|
||||
b->terminated = true;
|
||||
return ref;
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b) {
|
||||
return builder_alloc_node(b, SPL_IR_DBG_BREAKPOINT);
|
||||
}
|
||||
}
|
||||
+96
-19
@@ -1,4 +1,5 @@
|
||||
#include "spl_sema.h"
|
||||
#include "spl_intrin.h"
|
||||
#include "spl_type.h"
|
||||
|
||||
void spl_scope_init(spl_scope_t *scope) {
|
||||
@@ -52,6 +53,10 @@ bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref);
|
||||
static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in);
|
||||
static spl_lang_type_id_t sema_intrin_field(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in);
|
||||
|
||||
static inline void sema_push_scope(spl_sema_t *sema) {
|
||||
spl_scope_id_t new_scope = spl_scope_alloc(sema->scope);
|
||||
sema->store_scope = sema->scope->current_scope;
|
||||
@@ -170,6 +175,67 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref);
|
||||
|
||||
static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in) {
|
||||
const spl_intrin_info_t *info = spl_intrin_info(in);
|
||||
usize nargs = vec_size(n->call.args);
|
||||
|
||||
if ((int)nargs < info->min_args || (info->max_args >= 0 && (int)nargs > info->max_args)) {
|
||||
SPL_ERROR(&n->dbg, "`%s` expects %d..%d args, got %zu", info->name, info->min_args,
|
||||
info->max_args, nargs);
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (in) {
|
||||
case SPL_INTRIN_SIZEOF:
|
||||
case SPL_INTRIN_ALIGNOF: {
|
||||
spl_ast_node_ref_t arg_ref = vec_at(n->call.args, 0);
|
||||
spl_ast_node_t *arg = spl_ast_node(sema->ast, arg_ref);
|
||||
if (!arg || !(arg->kind == SPL_AST_TYPE_PATH || arg->kind == SPL_AST_TYPE_POINTER ||
|
||||
arg->kind == SPL_AST_TYPE_ARRAY || arg->kind == SPL_AST_TYPE_SLICE ||
|
||||
arg->kind == SPL_AST_TYPE_FN || arg->kind == SPL_AST_TYPE_PAREN)) {
|
||||
SPL_ERROR(&n->dbg, "`%s` expects a type argument", info->name);
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
sema_parse(sema, arg_ref);
|
||||
return spl_lang_make_int(sema->type, sizeof(void *) * 8, 0);
|
||||
}
|
||||
case SPL_INTRIN_ASSERT: {
|
||||
spl_lang_type_id_t cond = sema_parse(sema, vec_at(n->call.args, 0));
|
||||
spl_lang_type_id_t b = spl_lang_make_bool(sema->type);
|
||||
if (spl_lang_type_coerce_to(sema->type, b, cond) == 0) {
|
||||
SPL_ERROR(&n->dbg, "`@assert` condition must be bool");
|
||||
sema->error_count++;
|
||||
}
|
||||
if (nargs == 2)
|
||||
sema_parse(sema, vec_at(n->call.args, 1));
|
||||
return spl_lang_make_unit(sema->type);
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_intrin_field(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in) {
|
||||
const spl_intrin_info_t *info = spl_intrin_info(in);
|
||||
switch (info->result) {
|
||||
case SPL_INTRIN_RESULT_USIZE:
|
||||
return spl_lang_make_int(sema->type, sizeof(void *) * 8, 0);
|
||||
case SPL_INTRIN_RESULT_BOOL:
|
||||
return spl_lang_make_bool(sema->type);
|
||||
case SPL_INTRIN_RESULT_UNIT:
|
||||
return spl_lang_make_unit(sema->type);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
(void)n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
if (ref == 0)
|
||||
return 0;
|
||||
@@ -268,31 +334,33 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
sema->type, tk, &members, spl_type_builder_int(sema->type, 32, 1), layout);
|
||||
vec_free(members);
|
||||
|
||||
// 创建语言级节点
|
||||
spl_lang_type_node_t lang_node = {0};
|
||||
spl_lang_type_kind_t lk;
|
||||
switch (tk) {
|
||||
case SPL_TYPE_STRUCT:
|
||||
lang_node.kind = SPL_LANG_TYPE_STRUCT;
|
||||
lk = SPL_LANG_TYPE_STRUCT;
|
||||
break;
|
||||
case SPL_TYPE_UNION:
|
||||
lang_node.kind = SPL_LANG_TYPE_UNION;
|
||||
lk = SPL_LANG_TYPE_UNION;
|
||||
break;
|
||||
case SPL_TYPE_ENUM:
|
||||
lang_node.kind = SPL_LANG_TYPE_ENUM;
|
||||
lk = SPL_LANG_TYPE_ENUM;
|
||||
break;
|
||||
case SPL_TYPE_SHAPE:
|
||||
lang_node.kind = SPL_LANG_TYPE_SHAPE;
|
||||
lk = SPL_LANG_TYPE_SHAPE;
|
||||
break;
|
||||
default:
|
||||
lk = SPL_LANG_TYPE_STRUCT;
|
||||
break;
|
||||
}
|
||||
lang_node.ir_type_id = agg_ir;
|
||||
vec_push(sema->type->lang_table, lang_node);
|
||||
spl_lang_type_id_t agg_lang = vec_size(sema->type->lang_table) - 1;
|
||||
spl_def_resolve(sema->type, n->resolved_def_id, agg_lang);
|
||||
n->resolved_type_id = agg_lang; // 存储 lang_id
|
||||
|
||||
// 处理聚合内部的函数声明
|
||||
spl_lang_type_node_t lang_node = {0};
|
||||
lang_node.kind = lk;
|
||||
lang_node.ir_type_id = agg_ir;
|
||||
spl_lang_type_id_t agg_lang = spl_lang_node_push(sema->type, &lang_node);
|
||||
spl_def_resolve(sema->type, n->resolved_def_id, agg_lang);
|
||||
n->resolved_type_id = agg_lang;
|
||||
|
||||
/* 聚合内部函数:方法后续单独处理,这里暂只做函数体的语义解析 */
|
||||
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
|
||||
spl_ast_node_t *mn = spl_ast_node(sema->ast, vec_at(te->type_aggregate.members, i));
|
||||
if (mn && mn->kind == SPL_AST_FN_DECL) {
|
||||
@@ -302,7 +370,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
} else {
|
||||
spl_lang_type_id_t tid = sema_parse(sema, n->type_decl.type_expr);
|
||||
spl_def_resolve(sema->type, n->resolved_def_id, tid);
|
||||
n->resolved_type_id = tid; // 存储 lang_id
|
||||
n->resolved_type_id = tid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -630,6 +698,16 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
|
||||
case SPL_AST_EXPR_CALL: {
|
||||
spl_ast_node_t *callee = spl_ast_node(sema->ast, n->call.callee);
|
||||
if (callee && callee->kind == SPL_AST_EXPR_IDENT) {
|
||||
spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name);
|
||||
if (in != SPL_INTRIN_NONE) {
|
||||
spl_lang_type_id_t t = sema_intrin_call(sema, n, in);
|
||||
n->resolved_type_id = t;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
spl_lang_type_id_t callee_tid = sema_parse(sema, n->call.callee);
|
||||
spl_lang_type_node_t *fn = spl_lang_type_node(sema->type, callee_tid);
|
||||
if (!fn || fn->kind != SPL_LANG_TYPE_FN) {
|
||||
@@ -702,12 +780,11 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
if (!obj_node)
|
||||
return 0;
|
||||
|
||||
// 内建字段:数组/切片的 len
|
||||
if ((obj_node->kind == SPL_LANG_TYPE_ARRAY || obj_node->kind == SPL_LANG_TYPE_SLICE) &&
|
||||
strcmp(n->field.field, "len") == 0) {
|
||||
spl_lang_type_id_t usize_tid = spl_lang_make_int(sema->type, sizeof(void *) * 8, 0);
|
||||
n->resolved_type_id = usize_tid;
|
||||
return usize_tid;
|
||||
spl_intrin_t in = spl_intrin_lookup_field(obj_node->kind, n->field.field);
|
||||
if (in != SPL_INTRIN_NONE) {
|
||||
spl_lang_type_id_t t = sema_intrin_field(sema, n, in);
|
||||
n->resolved_type_id = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
// 自动解引用
|
||||
|
||||
+1
-1
@@ -218,7 +218,7 @@ static void spl_lang_node_free_extra(spl_lang_type_node_t *n) {
|
||||
}
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t spl_lang_node_push(spl_type_t *type, spl_lang_type_node_t *node) {
|
||||
spl_lang_type_id_t spl_lang_node_push(spl_type_t *type, spl_lang_type_node_t *node) {
|
||||
usize hash = spl_lang_type_hash(*node);
|
||||
usize idx = (usize)-1;
|
||||
spl_lang_type_id_t cand = 0;
|
||||
|
||||
@@ -168,6 +168,7 @@ spl_def_node_t *spl_def_node(const spl_type_t *type, spl_def_id_t id);
|
||||
bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub,
|
||||
spl_lang_type_id_t super);
|
||||
bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_t super);
|
||||
spl_lang_type_id_t spl_lang_node_push(spl_type_t *type, spl_lang_type_node_t *node);
|
||||
|
||||
/* 计算 from 是否可以隐式转换到 to。
|
||||
* - to 是 INFER 时视为"接受任意 from",返回 from。
|
||||
|
||||
Reference in new issue
Block a user