Compare commits
3
Commits
a1e684f6d4
...
983746c797
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
983746c797 | ||
|
|
3175e04e6e | ||
|
|
a621e34d51 |
No files matched your search
+49
-18
@@ -238,6 +238,7 @@ static int can_start_expr(spl_tok_type_t t) {
|
|||||||
case TOK_IDENT:
|
case TOK_IDENT:
|
||||||
case TOK_AT:
|
case TOK_AT:
|
||||||
case TOK_SHARP:
|
case TOK_SHARP:
|
||||||
|
case TOK_DOLLAR:
|
||||||
case TOK_L_PAREN:
|
case TOK_L_PAREN:
|
||||||
case TOK_L_BRACKET:
|
case TOK_L_BRACKET:
|
||||||
case TOK_L_BRACE:
|
case TOK_L_BRACE:
|
||||||
@@ -1261,6 +1262,40 @@ static spl_ast_node_ref_t parse_prefix(parser_t *p) {
|
|||||||
if (!t)
|
if (!t)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (t->type == TOK_DOLLAR) {
|
||||||
|
spl_ast_node_ref_t label = parse_label(p);
|
||||||
|
const spl_tok_t *kw = peek(p);
|
||||||
|
spl_ast_node_ref_t ref = 0;
|
||||||
|
if (kw && kw->type == KW_WHILE)
|
||||||
|
ref = parse_while_expr(p);
|
||||||
|
else if (kw && kw->type == KW_LOOP)
|
||||||
|
ref = parse_loop_expr(p);
|
||||||
|
else if (kw && kw->type == KW_FOR)
|
||||||
|
ref = parse_for_expr(p);
|
||||||
|
else {
|
||||||
|
SPL_FATAL(kw, "expected while/loop/for after label");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!ref)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
spl_ast_node_t *n = node_at(p->ast, ref);
|
||||||
|
switch (n->kind) {
|
||||||
|
case SPL_AST_EXPR_WHILE:
|
||||||
|
n->while_expr.label = label;
|
||||||
|
break;
|
||||||
|
case SPL_AST_EXPR_LOOP:
|
||||||
|
n->loop_expr.label = label;
|
||||||
|
break;
|
||||||
|
case SPL_AST_EXPR_FOR:
|
||||||
|
n->for_expr.label = label;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
spl_unary_op_t uop;
|
spl_unary_op_t uop;
|
||||||
switch (t->type) {
|
switch (t->type) {
|
||||||
case TOK_SUB:
|
case TOK_SUB:
|
||||||
@@ -1738,8 +1773,6 @@ static spl_ast_node_ref_t parse_while_expr(parser_t *p) {
|
|||||||
return 0;
|
return 0;
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
spl_ast_node_ref_t label = parse_label(p);
|
|
||||||
|
|
||||||
p->stop_agg++;
|
p->stop_agg++;
|
||||||
spl_ast_node_ref_t cond = parse_expr(p);
|
spl_ast_node_ref_t cond = parse_expr(p);
|
||||||
p->stop_agg--;
|
p->stop_agg--;
|
||||||
@@ -1760,7 +1793,7 @@ static spl_ast_node_ref_t parse_while_expr(parser_t *p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_WHILE, kw);
|
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_WHILE, kw);
|
||||||
node_at(p->ast, ref)->while_expr.label = label;
|
node_at(p->ast, ref)->while_expr.label = 0;
|
||||||
node_at(p->ast, ref)->while_expr.cond = cond;
|
node_at(p->ast, ref)->while_expr.cond = cond;
|
||||||
node_at(p->ast, ref)->while_expr.body = body;
|
node_at(p->ast, ref)->while_expr.body = body;
|
||||||
node_at(p->ast, ref)->while_expr.else_branch = else_branch;
|
node_at(p->ast, ref)->while_expr.else_branch = else_branch;
|
||||||
@@ -1773,11 +1806,10 @@ static spl_ast_node_ref_t parse_loop_expr(parser_t *p) {
|
|||||||
return 0;
|
return 0;
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
spl_ast_node_ref_t label = parse_label(p);
|
|
||||||
spl_ast_node_ref_t body = parse_block(p);
|
spl_ast_node_ref_t body = parse_block(p);
|
||||||
|
|
||||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_LOOP, kw);
|
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_LOOP, kw);
|
||||||
node_at(p->ast, ref)->loop_expr.label = label;
|
node_at(p->ast, ref)->loop_expr.label = 0;
|
||||||
node_at(p->ast, ref)->loop_expr.body = body;
|
node_at(p->ast, ref)->loop_expr.body = body;
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
@@ -1788,9 +1820,6 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
|
|||||||
return 0;
|
return 0;
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
spl_ast_node_ref_t label = parse_label(p);
|
|
||||||
|
|
||||||
// 解析迭代表达式列表(用 stop_as 阻止 'as' 被误解析为类型转换)
|
|
||||||
p->stop_as = 1;
|
p->stop_as = 1;
|
||||||
spl_ast_node_ref_vec_t iter_exprs;
|
spl_ast_node_ref_vec_t iter_exprs;
|
||||||
vec_init(iter_exprs);
|
vec_init(iter_exprs);
|
||||||
@@ -1801,7 +1830,6 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
|
|||||||
}
|
}
|
||||||
p->stop_as = 0;
|
p->stop_as = 0;
|
||||||
|
|
||||||
// 必须有关键字 as
|
|
||||||
const spl_tok_t *t = peek(p);
|
const spl_tok_t *t = peek(p);
|
||||||
if (!t || t->type != KW_AS) {
|
if (!t || t->type != KW_AS) {
|
||||||
SPL_FATAL(t, "expected 'as' in for loop");
|
SPL_FATAL(t, "expected 'as' in for loop");
|
||||||
@@ -1809,7 +1837,6 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
|
|||||||
}
|
}
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
// 解析绑定变量列表(允许 '_')
|
|
||||||
spl_ast_node_ref_vec_t idents;
|
spl_ast_node_ref_vec_t idents;
|
||||||
vec_init(idents);
|
vec_init(idents);
|
||||||
t = peek(p);
|
t = peek(p);
|
||||||
@@ -1835,12 +1862,10 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
|
|||||||
vec_push(idents, id_node);
|
vec_push(idents, id_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 循环体必须为块
|
|
||||||
spl_ast_node_ref_t body = parse_block(p);
|
spl_ast_node_ref_t body = parse_block(p);
|
||||||
if (!body)
|
if (!body)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// 可选的 else 分支
|
|
||||||
spl_ast_node_ref_t else_branch = 0;
|
spl_ast_node_ref_t else_branch = 0;
|
||||||
if (peek(p) && peek(p)->type == KW_ELSE) {
|
if (peek(p) && peek(p)->type == KW_ELSE) {
|
||||||
advance(p);
|
advance(p);
|
||||||
@@ -1852,7 +1877,7 @@ static spl_ast_node_ref_t parse_for_expr(parser_t *p) {
|
|||||||
|
|
||||||
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_FOR, kw);
|
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_FOR, kw);
|
||||||
spl_ast_node_t *fe = node_at(p->ast, ref);
|
spl_ast_node_t *fe = node_at(p->ast, ref);
|
||||||
fe->for_expr.label = label;
|
fe->for_expr.label = 0;
|
||||||
fe->for_expr.iter_exprs = iter_exprs;
|
fe->for_expr.iter_exprs = iter_exprs;
|
||||||
fe->for_expr.idents = idents;
|
fe->for_expr.idents = idents;
|
||||||
fe->for_expr.body = body;
|
fe->for_expr.body = body;
|
||||||
@@ -2153,12 +2178,18 @@ static spl_ast_node_ref_t parse_block(parser_t *p) {
|
|||||||
SPL_FATAL(t, "only one tail expression allowed");
|
SPL_FATAL(t, "only one tail expression allowed");
|
||||||
}
|
}
|
||||||
block->block.tail_expr = expr;
|
block->block.tail_expr = expr;
|
||||||
} else if (expr && node_at(p->ast, expr)->kind == SPL_AST_EXPR_BLOCK) {
|
|
||||||
vec_push(block->block.stmts, expr);
|
|
||||||
// 继续循环,处理下一个语句
|
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "expected ';' or '}' after expression");
|
spl_ast_node_kind_t k = node_at(p->ast, expr)->kind;
|
||||||
break;
|
bool block_like =
|
||||||
|
(k == SPL_AST_EXPR_BLOCK || k == SPL_AST_EXPR_IF || k == SPL_AST_EXPR_IFVAR ||
|
||||||
|
k == SPL_AST_EXPR_WHILE || k == SPL_AST_EXPR_LOOP || k == SPL_AST_EXPR_FOR ||
|
||||||
|
k == SPL_AST_EXPR_MATCH);
|
||||||
|
if (block_like) {
|
||||||
|
vec_push(block->block.stmts, expr);
|
||||||
|
} else {
|
||||||
|
SPL_FATAL(t, "expected ';' or '}' after expression");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SPL_FATAL(t, "unrecognized token in block");
|
SPL_FATAL(t, "unrecognized token in block");
|
||||||
|
|||||||
+259
-81
@@ -25,8 +25,10 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
|||||||
static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
||||||
static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
||||||
static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
||||||
static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n);
|
static void emit_fn_reserve(spl_ast2ir_t *a, spl_ast_node_t *n);
|
||||||
static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n);
|
||||||
|
static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
||||||
|
static void emit_container_body(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 emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n);
|
||||||
static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
|
||||||
@@ -42,7 +44,8 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
|
|||||||
spl_type_node_t *tn = spl_type_node(a->sema->type, tid);
|
spl_type_node_t *tn = spl_type_node(a->sema->type, tid);
|
||||||
if (!tn)
|
if (!tn)
|
||||||
return 0;
|
return 0;
|
||||||
switch (tn->kind) {
|
spl_type_node_kind_t tk = tn->kind;
|
||||||
|
switch (tk) {
|
||||||
case SPL_TYPE_BOOL:
|
case SPL_TYPE_BOOL:
|
||||||
return spl_ir_builder_type_const_bool(a->ir, tid, false);
|
return spl_ir_builder_type_const_bool(a->ir, tid, false);
|
||||||
case SPL_TYPE_INT:
|
case SPL_TYPE_INT:
|
||||||
@@ -53,9 +56,11 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
|
|||||||
case SPL_TYPE_FN:
|
case SPL_TYPE_FN:
|
||||||
return spl_ir_builder_type_const_ptr(a->ir, tid, NULL);
|
return spl_ir_builder_type_const_ptr(a->ir, tid, NULL);
|
||||||
case SPL_TYPE_ARRAY: {
|
case SPL_TYPE_ARRAY: {
|
||||||
|
usize arr_len = tn->array_type.len;
|
||||||
|
spl_type_id_t arr_elem = tn->array_type.element;
|
||||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid);
|
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid);
|
||||||
for (usize i = 0; i < tn->array_type.len; ++i) {
|
for (usize i = 0; i < arr_len; ++i) {
|
||||||
spl_ir_node_ref_t f = emit_zero_value(a, tn->array_type.element);
|
spl_ir_node_ref_t f = emit_zero_value(a, arr_elem);
|
||||||
if (!f)
|
if (!f)
|
||||||
return 0;
|
return 0;
|
||||||
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
||||||
@@ -64,20 +69,31 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
|
|||||||
}
|
}
|
||||||
case SPL_TYPE_STRUCT:
|
case SPL_TYPE_STRUCT:
|
||||||
case SPL_TYPE_SHAPE: {
|
case SPL_TYPE_SHAPE: {
|
||||||
|
usize nfield = vec_size(tn->agg_type.variants);
|
||||||
|
spl_type_id_vec_t field_tids;
|
||||||
|
vec_init(field_tids);
|
||||||
|
for (usize i = 0; i < nfield; ++i)
|
||||||
|
vec_push(field_tids, vec_at(tn->agg_type.variants, i).type_id);
|
||||||
|
|
||||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid);
|
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid);
|
||||||
for (usize i = 0; i < vec_size(tn->agg_type.variants); ++i) {
|
for (usize i = 0; i < nfield; ++i) {
|
||||||
spl_ir_node_ref_t f = emit_zero_value(a, vec_at(tn->agg_type.variants, i).type_id);
|
spl_ir_node_ref_t f = emit_zero_value(a, vec_at(field_tids, i));
|
||||||
if (!f)
|
if (!f) {
|
||||||
|
vec_free(field_tids);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
||||||
}
|
}
|
||||||
|
vec_free(field_tids);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
case SPL_TYPE_UNION: {
|
case SPL_TYPE_UNION: {
|
||||||
|
usize nfield = vec_size(tn->agg_type.variants);
|
||||||
|
if (nfield == 0)
|
||||||
|
return spl_ir_builder_agg_construct(a->ir, tid);
|
||||||
|
spl_type_id_t first_tid = vec_at(tn->agg_type.variants, 0).type_id;
|
||||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid);
|
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid);
|
||||||
if (vec_size(tn->agg_type.variants) == 0)
|
spl_ir_node_ref_t f = emit_zero_value(a, first_tid);
|
||||||
return node;
|
|
||||||
spl_ir_node_ref_t f = emit_zero_value(a, vec_at(tn->agg_type.variants, 0).type_id);
|
|
||||||
if (!f)
|
if (!f)
|
||||||
return 0;
|
return 0;
|
||||||
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
||||||
@@ -87,7 +103,6 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copy_attrs_to_ir_node(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_node_ref_t ir_ref) {
|
static void copy_attrs_to_ir_node(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_node_ref_t ir_ref) {
|
||||||
if (!ir_ref || !n || vec_size(n->attrs) == 0)
|
if (!ir_ref || !n || vec_size(n->attrs) == 0)
|
||||||
return;
|
return;
|
||||||
@@ -232,14 +247,17 @@ 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);
|
spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang);
|
||||||
if (!obj_ln)
|
if (!obj_ln)
|
||||||
return 0;
|
return 0;
|
||||||
if (spl_intrin_lookup_field(obj_ln->kind, n->field.field) != SPL_INTRIN_NONE)
|
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; /* 内建字段不是左值 */
|
return 0; /* 内建字段不是左值 */
|
||||||
|
|
||||||
spl_ir_node_ref_t base = 0;
|
spl_ir_node_ref_t base = 0;
|
||||||
spl_lang_type_id_t agg_lang = 0;
|
spl_lang_type_id_t agg_lang = 0;
|
||||||
if (obj_ln->kind == SPL_LANG_TYPE_PTR) {
|
if (obj_kind == SPL_LANG_TYPE_PTR) {
|
||||||
base = emit_expr(a, n->field.obj);
|
base = emit_expr(a, n->field.obj);
|
||||||
agg_lang = obj_ln->extra.elem;
|
agg_lang = obj_elem;
|
||||||
} else {
|
} else {
|
||||||
base = emit_lvalue(a, n->field.obj);
|
base = emit_lvalue(a, n->field.obj);
|
||||||
agg_lang = obj_lang;
|
agg_lang = obj_lang;
|
||||||
@@ -270,25 +288,43 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
if (!obj_ln)
|
if (!obj_ln)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
spl_lang_type_kind_t obj_kind = obj_ln->kind;
|
||||||
|
spl_lang_type_id_t obj_elem = 0;
|
||||||
|
if (obj_kind == SPL_LANG_TYPE_PTR || obj_kind == SPL_LANG_TYPE_ARRAY ||
|
||||||
|
obj_kind == SPL_LANG_TYPE_SLICE)
|
||||||
|
obj_elem = obj_ln->extra.elem;
|
||||||
|
|
||||||
|
if (obj_kind == SPL_LANG_TYPE_TUPLE) {
|
||||||
|
spl_ast_node_t *idx_node = spl_ast_node(a->sema->ast, n->index.index);
|
||||||
|
if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT)
|
||||||
|
return 0;
|
||||||
|
usize i = (usize)idx_node->int_lit.val;
|
||||||
|
spl_ir_node_ref_t base = emit_lvalue(a, n->index.obj);
|
||||||
|
if (!base)
|
||||||
|
return 0;
|
||||||
|
spl_type_id_t tuple_ir = to_ir_type(a, obj_lang);
|
||||||
|
if (!tuple_ir)
|
||||||
|
return 0;
|
||||||
|
return spl_ir_builder_mem_field(a->ir, tuple_ir, base, i);
|
||||||
|
}
|
||||||
|
|
||||||
spl_ir_node_ref_t base = 0;
|
spl_ir_node_ref_t base = 0;
|
||||||
spl_lang_type_id_t elem_lang = 0;
|
spl_lang_type_id_t elem_lang = 0;
|
||||||
if (obj_ln->kind == SPL_LANG_TYPE_PTR) {
|
if (obj_kind == SPL_LANG_TYPE_PTR) {
|
||||||
base = emit_expr(a, n->index.obj);
|
base = emit_expr(a, n->index.obj);
|
||||||
elem_lang = obj_ln->extra.elem;
|
elem_lang = obj_elem;
|
||||||
} else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) {
|
} else if (obj_kind == SPL_LANG_TYPE_ARRAY) {
|
||||||
base = emit_lvalue(a, n->index.obj);
|
base = emit_lvalue(a, n->index.obj);
|
||||||
elem_lang = obj_ln->extra.elem;
|
elem_lang = obj_elem;
|
||||||
} else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) {
|
} else if (obj_kind == SPL_LANG_TYPE_SLICE) {
|
||||||
/* 切片:取出切片值,再 agg_extract 出 ptr 字段 */
|
|
||||||
spl_ir_node_ref_t slice_val = emit_expr(a, n->index.obj);
|
spl_ir_node_ref_t slice_val = emit_expr(a, n->index.obj);
|
||||||
if (!slice_val)
|
if (!slice_val)
|
||||||
return 0;
|
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, obj_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_ir_node_ref_t ptr = spl_ir_builder_agg_extract(a->ir, ptr_ir, ptr_ir,
|
||||||
SPL_SLICE_PTR_FIELD_IDX, slice_val);
|
SPL_SLICE_PTR_FIELD_IDX, slice_val);
|
||||||
base = ptr;
|
base = ptr;
|
||||||
elem_lang = elem;
|
elem_lang = obj_elem;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -671,7 +707,9 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
if (!tn)
|
if (!tn)
|
||||||
Panic("aggregate type node missing");
|
Panic("aggregate type node missing");
|
||||||
|
|
||||||
if (tn->kind == SPL_TYPE_ENUM) {
|
spl_type_node_kind_t tn_kind = tn->kind;
|
||||||
|
|
||||||
|
if (tn_kind == SPL_TYPE_ENUM) {
|
||||||
if (vec_size(n->aggregate_literal.fields) != 1)
|
if (vec_size(n->aggregate_literal.fields) != 1)
|
||||||
Panic("enum literal must have exactly one variant");
|
Panic("enum literal must have exactly one variant");
|
||||||
spl_ast_node_t *item =
|
spl_ast_node_t *item =
|
||||||
@@ -684,25 +722,30 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
Panic("enum variant `%s` not found (sema should have caught this)",
|
Panic("enum variant `%s` not found (sema should have caught this)",
|
||||||
item->struct_init_item.name);
|
item->struct_init_item.name);
|
||||||
|
|
||||||
|
spl_type_id_t tag_ir = tn->agg_type.tag_type;
|
||||||
|
spl_type_id_t payload_ir = vec_at(tn->agg_type.variants, vidx).type_id;
|
||||||
|
|
||||||
spl_ir_node_ref_t eptr = spl_ir_builder_mem_alloca(a->ir, t, const_usize(a, 1));
|
spl_ir_node_ref_t eptr = spl_ir_builder_mem_alloca(a->ir, t, const_usize(a, 1));
|
||||||
|
|
||||||
spl_type_id_t tag_ir = tn->agg_type.tag_type;
|
|
||||||
spl_ir_node_ref_t tptr =
|
spl_ir_node_ref_t tptr =
|
||||||
spl_ir_builder_mem_field(a->ir, t, eptr, SPL_ENUM_TAG_FIELD_IDX);
|
spl_ir_builder_mem_field(a->ir, t, eptr, SPL_ENUM_TAG_FIELD_IDX);
|
||||||
spl_ir_node_ref_t tag_val = spl_ir_builder_type_const_int(a->ir, tag_ir, vidx);
|
spl_ir_node_ref_t tag_val = spl_ir_builder_type_const_int(a->ir, tag_ir, vidx);
|
||||||
spl_ir_builder_mem_store(a->ir, tag_ir, tptr, tag_val);
|
spl_ir_builder_mem_store(a->ir, tag_ir, tptr, tag_val);
|
||||||
|
|
||||||
spl_type_id_t ftid = vec_at(tn->agg_type.variants, vidx).type_id;
|
|
||||||
spl_ir_node_ref_t pptr = spl_ir_builder_mem_field(a->ir, t, eptr, vidx + 1);
|
spl_ir_node_ref_t pptr = spl_ir_builder_mem_field(a->ir, t, eptr, vidx + 1);
|
||||||
spl_ir_node_ref_t payload = emit_expr(a, item->struct_init_item.expr);
|
spl_ir_node_ref_t payload = emit_expr(a, item->struct_init_item.expr);
|
||||||
if (!payload)
|
if (!payload)
|
||||||
Panic("enum payload emit failed");
|
Panic("enum payload emit failed");
|
||||||
spl_ir_builder_mem_store(a->ir, ftid, pptr, payload);
|
spl_ir_builder_mem_store(a->ir, payload_ir, pptr, payload);
|
||||||
|
|
||||||
return eptr;
|
return eptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
usize nfields = vec_size(tn->agg_type.variants);
|
usize nfields = vec_size(tn->agg_type.variants);
|
||||||
|
spl_type_id_vec_t field_tids;
|
||||||
|
vec_init(field_tids);
|
||||||
|
for (usize i = 0; i < nfields; ++i)
|
||||||
|
vec_push(field_tids, vec_at(tn->agg_type.variants, i).type_id);
|
||||||
|
|
||||||
spl_ir_node_ref_vec_t fields;
|
spl_ir_node_ref_vec_t fields;
|
||||||
vec_init(fields);
|
vec_init(fields);
|
||||||
@@ -728,24 +771,34 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
|
|
||||||
for (usize i = 0; i < nfields; ++i) {
|
for (usize i = 0; i < nfields; ++i) {
|
||||||
if (!vec_at(fields, i)) {
|
if (!vec_at(fields, i)) {
|
||||||
spl_type_id_t ftid = vec_at(tn->agg_type.variants, i).type_id;
|
spl_ir_node_ref_t f = emit_zero_value(a, vec_at(field_tids, i));
|
||||||
spl_ir_node_ref_t f = emit_zero_value(a, ftid);
|
if (!f) {
|
||||||
if (!f)
|
vec_free(field_tids);
|
||||||
|
vec_free(fields);
|
||||||
Panic("cannot zero-init aggregate field #%zu", i);
|
Panic("cannot zero-init aggregate field #%zu", i);
|
||||||
|
}
|
||||||
vec_at(fields, i) = f;
|
vec_at(fields, i) = f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t);
|
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t);
|
||||||
if (!node)
|
if (!node) {
|
||||||
|
vec_free(field_tids);
|
||||||
|
vec_free(fields);
|
||||||
Panic("agg_construct failed for aggregate literal");
|
Panic("agg_construct failed for aggregate literal");
|
||||||
|
}
|
||||||
|
|
||||||
for (usize i = 0; i < nfields; ++i) {
|
for (usize i = 0; i < nfields; ++i) {
|
||||||
spl_ir_node_ref_t f = vec_at(fields, i);
|
spl_ir_node_ref_t f = vec_at(fields, i);
|
||||||
if (!f)
|
if (!f) {
|
||||||
|
vec_free(field_tids);
|
||||||
|
vec_free(fields);
|
||||||
Panic("aggregate field #%zu missing (sema should have caught this)", i);
|
Panic("aggregate field #%zu missing (sema should have caught this)", i);
|
||||||
|
}
|
||||||
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec_free(field_tids);
|
||||||
vec_free(fields);
|
vec_free(fields);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -770,11 +823,15 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
if (!obj_ln)
|
if (!obj_ln)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
spl_lang_type_kind_t obj_kind = obj_ln->kind;
|
||||||
|
spl_lang_type_id_t obj_elem = obj_ln->extra.elem;
|
||||||
|
spl_type_id_t obj_ir = obj_ln->ir_type_id;
|
||||||
|
|
||||||
spl_type_id_t slice_ir = node_ir(a, n);
|
spl_type_id_t slice_ir = node_ir(a, n);
|
||||||
if (!slice_ir)
|
if (!slice_ir)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spl_lang_type_id_t elem_lang = obj_ln->extra.elem;
|
spl_lang_type_id_t elem_lang = obj_elem;
|
||||||
spl_type_id_t elem_ir = to_ir_type(a, elem_lang);
|
spl_type_id_t elem_ir = to_ir_type(a, elem_lang);
|
||||||
spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 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);
|
spl_type_id_t usize_ir = to_ir_type(a, usize_lang);
|
||||||
@@ -798,13 +855,16 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
|||||||
spl_ir_node_ref_t end_v = 0;
|
spl_ir_node_ref_t end_v = 0;
|
||||||
if (n->slice.end) {
|
if (n->slice.end) {
|
||||||
end_v = emit_expr(a, n->slice.end);
|
end_v = emit_expr(a, n->slice.end);
|
||||||
} else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) {
|
} else if (obj_kind == SPL_LANG_TYPE_ARRAY) {
|
||||||
spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ln->ir_type_id);
|
spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ir);
|
||||||
end_v = spl_ir_builder_type_const_int(a->ir, usize_ir, arr->array_type.len);
|
if (!arr)
|
||||||
} else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) {
|
return 0;
|
||||||
|
usize arr_len = arr->array_type.len;
|
||||||
|
end_v = spl_ir_builder_type_const_int(a->ir, usize_ir, arr_len);
|
||||||
|
} else if (obj_kind == SPL_LANG_TYPE_SLICE) {
|
||||||
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
|
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
|
||||||
end_v = spl_ir_builder_agg_extract(a->ir, obj_ln->ir_type_id, usize_ir,
|
end_v = spl_ir_builder_agg_extract(a->ir, obj_ir, usize_ir, SPL_SLICE_LEN_FIELD_IDX,
|
||||||
SPL_SLICE_LEN_FIELD_IDX, slice_val);
|
slice_val);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -852,21 +912,6 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case SPL_AST_STATEMENT_BREAK: {
|
|
||||||
if (vec_size(a->loop_stack) == 0)
|
|
||||||
return;
|
|
||||||
spl_ir_node_ref_t jmp = spl_ir_builder_control_jmp(a->ir);
|
|
||||||
vec_push(vec_at(a->loop_stack, vec_size(a->loop_stack) - 1).breaks, jmp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case SPL_AST_STATEMENT_CONTINUE: {
|
|
||||||
if (vec_size(a->loop_stack) == 0)
|
|
||||||
return;
|
|
||||||
spl_ir_node_ref_t jmp = spl_ir_builder_control_jmp(a->ir);
|
|
||||||
usize cont = vec_at(a->loop_stack, vec_size(a->loop_stack) - 1).cont_blk;
|
|
||||||
spl_ir_builder_control_jmp_fixup(a->ir, jmp, cont);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case SPL_AST_STATEMENT_DEFER:
|
case SPL_AST_STATEMENT_DEFER:
|
||||||
if (n->statement_defer.body)
|
if (n->statement_defer.body)
|
||||||
vec_push(a->defer_stack, n->statement_defer.body);
|
vec_push(a->defer_stack, n->statement_defer.body);
|
||||||
@@ -981,6 +1026,12 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
spl_loop_ctx_t ctx = {0};
|
spl_loop_ctx_t ctx = {0};
|
||||||
ctx.cont_blk = head_blk;
|
ctx.cont_blk = head_blk;
|
||||||
ctx.brk_blk = 0;
|
ctx.brk_blk = 0;
|
||||||
|
ctx.label = NULL;
|
||||||
|
if (n->while_expr.label) {
|
||||||
|
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->while_expr.label);
|
||||||
|
if (ln && ln->kind == SPL_AST_LABEL)
|
||||||
|
ctx.label = ln->label.name;
|
||||||
|
}
|
||||||
vec_init(ctx.breaks);
|
vec_init(ctx.breaks);
|
||||||
vec_push(a->loop_stack, ctx);
|
vec_push(a->loop_stack, ctx);
|
||||||
|
|
||||||
@@ -1019,6 +1070,12 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
spl_loop_ctx_t ctx = {0};
|
spl_loop_ctx_t ctx = {0};
|
||||||
ctx.cont_blk = head_blk;
|
ctx.cont_blk = head_blk;
|
||||||
ctx.brk_blk = 0;
|
ctx.brk_blk = 0;
|
||||||
|
ctx.label = NULL;
|
||||||
|
if (n->loop_expr.label) {
|
||||||
|
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->loop_expr.label);
|
||||||
|
if (ln && ln->kind == SPL_AST_LABEL)
|
||||||
|
ctx.label = ln->label.name;
|
||||||
|
}
|
||||||
vec_init(ctx.breaks);
|
vec_init(ctx.breaks);
|
||||||
vec_push(a->loop_stack, ctx);
|
vec_push(a->loop_stack, ctx);
|
||||||
|
|
||||||
@@ -1043,6 +1100,61 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
vec_pop(a->loop_stack);
|
vec_pop(a->loop_stack);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case SPL_AST_STATEMENT_BREAK: {
|
||||||
|
if (vec_size(a->loop_stack) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *lbl = NULL;
|
||||||
|
if (n->statement_break.label) {
|
||||||
|
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->statement_break.label);
|
||||||
|
if (ln && ln->kind == SPL_AST_LABEL)
|
||||||
|
lbl = ln->label.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_ir_node_ref_t jmp = spl_ir_builder_control_jmp(a->ir);
|
||||||
|
|
||||||
|
if (lbl) {
|
||||||
|
for (usize i = vec_size(a->loop_stack); i > 0; --i) {
|
||||||
|
spl_loop_ctx_t *c = &vec_at(a->loop_stack, i - 1);
|
||||||
|
if (c->label && strcmp(c->label, lbl) == 0) {
|
||||||
|
vec_push(c->breaks, jmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec_push(vec_at(a->loop_stack, vec_size(a->loop_stack) - 1).breaks, jmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case SPL_AST_STATEMENT_CONTINUE: {
|
||||||
|
if (vec_size(a->loop_stack) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *lbl = NULL;
|
||||||
|
if (n->statement_continue.label) {
|
||||||
|
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->statement_continue.label);
|
||||||
|
if (ln && ln->kind == SPL_AST_LABEL)
|
||||||
|
lbl = ln->label.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_ir_node_ref_t jmp = spl_ir_builder_control_jmp(a->ir);
|
||||||
|
|
||||||
|
if (lbl) {
|
||||||
|
for (usize i = vec_size(a->loop_stack); i > 0; --i) {
|
||||||
|
spl_loop_ctx_t *c = &vec_at(a->loop_stack, i - 1);
|
||||||
|
if (c->label && strcmp(c->label, lbl) == 0) {
|
||||||
|
spl_ir_builder_control_jmp_fixup(a->ir, jmp, c->cont_blk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize cont = vec_at(a->loop_stack, vec_size(a->loop_stack) - 1).cont_blk;
|
||||||
|
spl_ir_builder_control_jmp_fixup(a->ir, jmp, cont);
|
||||||
|
return;
|
||||||
|
}
|
||||||
case SPL_AST_EXPR_BLOCK:
|
case SPL_AST_EXPR_BLOCK:
|
||||||
emit_expr(a, ref);
|
emit_expr(a, ref);
|
||||||
return;
|
return;
|
||||||
@@ -1085,16 +1197,13 @@ static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case SPL_AST_FN_DECL:
|
|
||||||
emit_fn(a, n);
|
|
||||||
return;
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
static void emit_fn_reserve(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||||
if (!n->resolved_def_id)
|
if (!n || !n->resolved_def_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spl_lang_type_id_t fn_lang = spl_def_get_lang_id(a->sema->type, n->resolved_def_id);
|
spl_lang_type_id_t fn_lang = spl_def_get_lang_id(a->sema->type, n->resolved_def_id);
|
||||||
@@ -1106,13 +1215,34 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
|||||||
if (!fn_ir)
|
if (!fn_ir)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spl_ir_func_ref_t fn_ref = spl_ir_builder_fn_begin(a->ir, n->fn_decl.name, fn_ir);
|
spl_ir_func_ref_t fn_ref = spl_ir_builder_fn_reserve(a->ir, n->fn_decl.name, fn_ir);
|
||||||
map_put(a->def2ir_map, n->resolved_def_id, (spl_ir_node_ref_t)fn_ref);
|
map_put(a->def2ir_map, n->resolved_def_id, (spl_ir_node_ref_t)fn_ref);
|
||||||
|
|
||||||
copy_attrs_to_ir_func(a, n, fn_ref);
|
copy_attrs_to_ir_func(a, n, fn_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||||
|
if (!n || !n->resolved_def_id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
spl_ir_func_ref_t fn_ref = 0;
|
||||||
|
if (!map_get(a->def2ir_map, n->resolved_def_id, &fn_ref))
|
||||||
|
return;
|
||||||
|
|
||||||
|
spl_lang_type_id_t fn_lang = spl_def_get_lang_id(a->sema->type, n->resolved_def_id);
|
||||||
|
spl_lang_type_node_t *fn_ln = spl_lang_type_node(a->sema->type, fn_lang);
|
||||||
|
if (!fn_ln || fn_ln->kind != SPL_LANG_TYPE_FN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
spl_lang_type_id_t ret_lang = fn_ln->extra.fn.ret;
|
||||||
|
spl_type_id_t ret_ir = to_ir_type(a, ret_lang);
|
||||||
|
spl_lang_type_node_t *ret_ln = spl_lang_type_node(a->sema->type, ret_lang);
|
||||||
|
int ret_is_unit = (ret_ln && ret_ln->kind == SPL_LANG_TYPE_UNIT) ? 1 : 0;
|
||||||
|
|
||||||
|
spl_ir_builder_fn_begin_at(a->ir, fn_ref);
|
||||||
|
|
||||||
spl_lang_type_id_t saved_ret = a->cur_ret_lang;
|
spl_lang_type_id_t saved_ret = a->cur_ret_lang;
|
||||||
a->cur_ret_lang = fn_ln->extra.fn.ret;
|
a->cur_ret_lang = ret_lang;
|
||||||
|
|
||||||
usize defer_base = vec_size(a->defer_stack);
|
usize defer_base = vec_size(a->defer_stack);
|
||||||
usize loop_base = vec_size(a->loop_stack);
|
usize loop_base = vec_size(a->loop_stack);
|
||||||
@@ -1149,21 +1279,17 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
|||||||
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
|
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
|
||||||
emit_stmt(a, d);
|
emit_stmt(a, d);
|
||||||
}
|
}
|
||||||
spl_lang_type_id_t ret_lang = fn_ln->extra.fn.ret;
|
|
||||||
spl_lang_type_node_t *ret_ln = spl_lang_type_node(a->sema->type, ret_lang);
|
if (ret_is_unit) {
|
||||||
if (ret_ln && ret_ln->kind == SPL_LANG_TYPE_UNIT) {
|
spl_ir_builder_control_ret(a->ir, ret_ir, 0);
|
||||||
spl_ir_builder_control_ret(a->ir, to_ir_type(a, ret_lang), 0);
|
} else if (ret_ir) {
|
||||||
|
spl_ir_node_ref_t zero = emit_zero_value(a, ret_ir);
|
||||||
|
spl_ir_builder_control_ret(a->ir, ret_ir, zero);
|
||||||
} else {
|
} else {
|
||||||
spl_ir_builder_control_unreachable(a->ir);
|
spl_ir_builder_control_unreachable(a->ir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 兜底清理:
|
|
||||||
* - 若 body 已显式 return,defer 栈可能已被清空到 defer_base 之下
|
|
||||||
* (被 return 逻辑弹过),此时 vec_size <= defer_base,无需处理。
|
|
||||||
* - 若 body 里开了 loop 却没关(理论上不会,sema 已保证),
|
|
||||||
* 这里的 while 只是防止异常路径残留。
|
|
||||||
*/
|
|
||||||
while (vec_size(a->defer_stack) > defer_base) {
|
while (vec_size(a->defer_stack) > defer_base) {
|
||||||
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
|
spl_ast_node_ref_t d = vec_pop(a->defer_stack);
|
||||||
(void)d;
|
(void)d;
|
||||||
@@ -1180,28 +1306,43 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
|||||||
spl_ir_builder_fn_end(a->ir);
|
spl_ir_builder_fn_end(a->ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_aggregate_fns(spl_ast2ir_t *a, spl_ast_node_t *te) {
|
static void emit_aggregate_fns_reserve(spl_ast2ir_t *a, spl_ast_node_t *te) {
|
||||||
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
|
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
|
||||||
spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(te->type_aggregate.members, i));
|
spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(te->type_aggregate.members, i));
|
||||||
if (!mn)
|
if (!mn)
|
||||||
continue;
|
continue;
|
||||||
if (mn->kind == SPL_AST_FN_DECL) {
|
if (mn->kind == SPL_AST_FN_DECL) {
|
||||||
emit_fn(a, mn);
|
emit_fn_reserve(a, mn);
|
||||||
} else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) {
|
} else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) {
|
||||||
spl_ast_node_t *mt = spl_ast_node(a->sema->ast, mn->member_decl.type_expr);
|
spl_ast_node_t *mt = spl_ast_node(a->sema->ast, mn->member_decl.type_expr);
|
||||||
if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE)
|
if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE)
|
||||||
emit_aggregate_fns(a, mt);
|
emit_aggregate_fns_reserve(a, mt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
static void emit_aggregate_fns_body(spl_ast2ir_t *a, spl_ast_node_t *te) {
|
||||||
|
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
|
||||||
|
spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(te->type_aggregate.members, i));
|
||||||
|
if (!mn)
|
||||||
|
continue;
|
||||||
|
if (mn->kind == SPL_AST_FN_DECL) {
|
||||||
|
emit_fn_body(a, mn);
|
||||||
|
} else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) {
|
||||||
|
spl_ast_node_t *mt = spl_ast_node(a->sema->ast, mn->member_decl.type_expr);
|
||||||
|
if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE)
|
||||||
|
emit_aggregate_fns_body(a, mt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||||
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
|
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
|
||||||
if (!n)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) {
|
if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) {
|
||||||
if (n->top_level_block.block)
|
if (n->top_level_block.block)
|
||||||
emit_container(a, n->top_level_block.block);
|
emit_container_reserve(a, n->top_level_block.block);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (n->kind != SPL_AST_CONTAINER_MEMBERS)
|
if (n->kind != SPL_AST_CONTAINER_MEMBERS)
|
||||||
@@ -1214,16 +1355,52 @@ static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
|||||||
continue;
|
continue;
|
||||||
switch (d->kind) {
|
switch (d->kind) {
|
||||||
case SPL_AST_FN_DECL:
|
case SPL_AST_FN_DECL:
|
||||||
emit_fn(a, d);
|
emit_fn_reserve(a, d);
|
||||||
break;
|
break;
|
||||||
case SPL_AST_TYPE_DECL: {
|
case SPL_AST_TYPE_DECL: {
|
||||||
spl_ast_node_t *te = spl_ast_node(a->sema->ast, d->type_decl.type_expr);
|
spl_ast_node_t *te = spl_ast_node(a->sema->ast, d->type_decl.type_expr);
|
||||||
if (te && te->kind == SPL_AST_TYPE_AGGREGATE)
|
if (te && te->kind == SPL_AST_TYPE_AGGREGATE)
|
||||||
emit_aggregate_fns(a, te);
|
emit_aggregate_fns_reserve(a, te);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPL_AST_TOP_LEVEL_BLOCK:
|
case SPL_AST_TOP_LEVEL_BLOCK:
|
||||||
emit_container(a, dref);
|
emit_container_reserve(a, dref);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_container_body(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||||
|
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
|
||||||
|
if (!n)
|
||||||
|
return;
|
||||||
|
if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) {
|
||||||
|
if (n->top_level_block.block)
|
||||||
|
emit_container_body(a, n->top_level_block.block);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (n->kind != SPL_AST_CONTAINER_MEMBERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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(a->sema->ast, dref);
|
||||||
|
if (!d)
|
||||||
|
continue;
|
||||||
|
switch (d->kind) {
|
||||||
|
case SPL_AST_FN_DECL:
|
||||||
|
emit_fn_body(a, d);
|
||||||
|
break;
|
||||||
|
case SPL_AST_TYPE_DECL: {
|
||||||
|
spl_ast_node_t *te = spl_ast_node(a->sema->ast, d->type_decl.type_expr);
|
||||||
|
if (te && te->kind == SPL_AST_TYPE_AGGREGATE)
|
||||||
|
emit_aggregate_fns_body(a, te);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SPL_AST_TOP_LEVEL_BLOCK:
|
||||||
|
emit_container_body(a, dref);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1295,5 +1472,6 @@ void spl_ast2ir_run(spl_ast2ir_t *ast2ir) {
|
|||||||
spl_ast_node_t *root = spl_ast_node(ast, ast->root);
|
spl_ast_node_t *root = spl_ast_node(ast, ast->root);
|
||||||
if (!root || root->kind != SPL_AST_ROOT)
|
if (!root || root->kind != SPL_AST_ROOT)
|
||||||
return;
|
return;
|
||||||
emit_container(ast2ir, root->root.members);
|
emit_container_reserve(ast2ir, root->root.members);
|
||||||
|
emit_container_body(ast2ir, root->root.members);
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ typedef MAP(spl_def_id_t, spl_ir_node_ref_t) spl_def2ir_map_t;
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
usize cont_blk;
|
usize cont_blk;
|
||||||
usize brk_blk;
|
usize brk_blk;
|
||||||
|
const char *label;
|
||||||
spl_ir_node_ref_vec_t breaks;
|
spl_ir_node_ref_vec_t breaks;
|
||||||
} spl_loop_ctx_t;
|
} spl_loop_ctx_t;
|
||||||
typedef VEC(spl_loop_ctx_t) spl_loop_ctx_vec_t;
|
typedef VEC(spl_loop_ctx_t) spl_loop_ctx_vec_t;
|
||||||
|
|||||||
@@ -387,6 +387,27 @@ spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name,
|
|||||||
return fid;
|
return fid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spl_ir_func_ref_t spl_ir_builder_fn_reserve(spl_ir_builder_t *b, const char *name,
|
||||||
|
spl_type_id_t fn_tid) {
|
||||||
|
spl_ir_func_ref_t fid = spl_ir_alloc_fn(&b->ir);
|
||||||
|
spl_ir_func_t *f = spl_ir_func(&b->ir, fid);
|
||||||
|
f->name = name;
|
||||||
|
vec_init(f->attrs);
|
||||||
|
f->fn_tid = fn_tid;
|
||||||
|
return fid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_ir_builder_fn_begin_at(spl_ir_builder_t *b, spl_ir_func_ref_t fid) {
|
||||||
|
if (b->current_fn && b->current_fn != fid) {
|
||||||
|
spl_ir_builder_fn_end(b);
|
||||||
|
}
|
||||||
|
b->current_fn = fid;
|
||||||
|
b->current_block = 0;
|
||||||
|
b->blocks.size = 0;
|
||||||
|
b->fixups.size = 0;
|
||||||
|
b->terminated = false;
|
||||||
|
}
|
||||||
|
|
||||||
void spl_ir_builder_fn_end(spl_ir_builder_t *b) {
|
void spl_ir_builder_fn_end(spl_ir_builder_t *b) {
|
||||||
spl_ir_func_t *f = spl_ir_func(&b->ir, b->current_fn);
|
spl_ir_func_t *f = spl_ir_func(&b->ir, b->current_fn);
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
|||||||
@@ -311,6 +311,9 @@ void spl_ir_builder_drop(spl_ir_builder_t *b);
|
|||||||
|
|
||||||
spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name,
|
spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name,
|
||||||
spl_type_id_t fn_tid);
|
spl_type_id_t fn_tid);
|
||||||
|
spl_ir_func_ref_t spl_ir_builder_fn_reserve(spl_ir_builder_t *b, const char *name,
|
||||||
|
spl_type_id_t fn_tid);
|
||||||
|
void spl_ir_builder_fn_begin_at(spl_ir_builder_t *b, spl_ir_func_ref_t fid);
|
||||||
void spl_ir_builder_fn_end(spl_ir_builder_t *b);
|
void spl_ir_builder_fn_end(spl_ir_builder_t *b);
|
||||||
|
|
||||||
usize spl_ir_builder_block_begin(spl_ir_builder_t *b);
|
usize spl_ir_builder_block_begin(spl_ir_builder_t *b);
|
||||||
|
|||||||
+350
-97
@@ -145,6 +145,8 @@ static spl_lang_type_id_t sema_check(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_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in,
|
||||||
spl_ast_node_ref_vec_t *args);
|
spl_ast_node_ref_vec_t *args);
|
||||||
static spl_lang_type_id_t sema_intrin_field(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 spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id);
|
||||||
|
static spl_lang_type_id_t sema_infer_fn_signature(spl_sema_t *sema, spl_ast_node_t *n);
|
||||||
|
|
||||||
static bool sema_is_infer(spl_sema_t *sema, spl_lang_type_id_t tid) {
|
static bool sema_is_infer(spl_sema_t *sema, spl_lang_type_id_t tid) {
|
||||||
spl_lang_type_node_t *n = spl_lang_type_node(sema->type, tid);
|
spl_lang_type_node_t *n = spl_lang_type_node(sema->type, tid);
|
||||||
@@ -200,13 +202,38 @@ static spl_lang_type_id_t sema_for_elem_type(spl_sema_t *sema, spl_lang_type_id_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t *te) {
|
static spl_lang_type_id_t sema_infer_fn_signature(spl_sema_t *sema, spl_ast_node_t *n) {
|
||||||
|
if (!n || n->resolved_def_id == 0)
|
||||||
|
return 0;
|
||||||
|
spl_def_node_t *def = spl_def_node(sema->type, n->resolved_def_id);
|
||||||
|
if (def && def->lang_id != 0)
|
||||||
|
return def->lang_id;
|
||||||
|
|
||||||
|
spl_lang_type_id_vec_t param_types;
|
||||||
|
vec_init(param_types);
|
||||||
|
for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) {
|
||||||
|
spl_ast_node_t *pd = spl_ast_node(sema->ast, vec_at(n->fn_decl.params, i));
|
||||||
|
if (pd && pd->kind == SPL_AST_PARAM_DECL && pd->param_decl.type_expr)
|
||||||
|
vec_push(param_types, sema_infer(sema, pd->param_decl.type_expr));
|
||||||
|
else
|
||||||
|
vec_push(param_types, spl_lang_make_varargs(sema->type));
|
||||||
|
}
|
||||||
|
spl_lang_type_id_t ret_tid = sema_infer(sema, n->fn_decl.ret_type);
|
||||||
|
if (ret_tid == 0)
|
||||||
|
ret_tid = spl_lang_make_unit(sema->type);
|
||||||
|
spl_lang_type_id_t fn_tid = spl_lang_make_fn(
|
||||||
|
sema->type, ret_tid, vec_unsafe_get_data(param_types), vec_size(param_types));
|
||||||
|
vec_free(param_types);
|
||||||
|
spl_def_resolve(sema->type, n->resolved_def_id, fn_tid);
|
||||||
|
return fn_tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t *te,
|
||||||
|
spl_def_id_t owner_def_id) {
|
||||||
spl_type_member_vec_t members;
|
spl_type_member_vec_t members;
|
||||||
vec_init(members);
|
vec_init(members);
|
||||||
spl_lang_method_vec_t methods;
|
spl_lang_method_vec_t methods;
|
||||||
vec_init(methods);
|
vec_init(methods);
|
||||||
spl_ast_node_ref_vec_t fn_nodes;
|
|
||||||
vec_init(fn_nodes);
|
|
||||||
|
|
||||||
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
|
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
|
||||||
spl_ast_node_ref_t mref = vec_at(te->type_aggregate.members, i);
|
spl_ast_node_ref_t mref = vec_at(te->type_aggregate.members, i);
|
||||||
@@ -224,9 +251,11 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t
|
|||||||
spl_def_id_t fn_def =
|
spl_def_id_t fn_def =
|
||||||
spl_def_alloc(sema->type, SPL_DEF_FN, mn->fn_decl.name, mn->dbg, mref);
|
spl_def_alloc(sema->type, SPL_DEF_FN, mn->fn_decl.name, mn->dbg, mref);
|
||||||
mn->resolved_def_id = fn_def;
|
mn->resolved_def_id = fn_def;
|
||||||
|
spl_def_node_t *fn_d = spl_def_node(sema->type, fn_def);
|
||||||
|
if (fn_d)
|
||||||
|
fn_d->owner_def = owner_def_id;
|
||||||
spl_lang_method_t meth = {.name = mn->fn_decl.name, .def_id = fn_def};
|
spl_lang_method_t meth = {.name = mn->fn_decl.name, .def_id = fn_def};
|
||||||
vec_push(methods, meth);
|
vec_push(methods, meth);
|
||||||
vec_push(fn_nodes, mref);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,19 +296,80 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t
|
|||||||
ln.kind = lk;
|
ln.kind = lk;
|
||||||
ln.ir_type_id = agg_ir;
|
ln.ir_type_id = agg_ir;
|
||||||
ln.methods = methods;
|
ln.methods = methods;
|
||||||
spl_lang_type_id_t agg_lang = spl_lang_node_push(sema->type, &ln);
|
return spl_lang_node_push(sema->type, &ln);
|
||||||
|
|
||||||
spl_lang_type_id_t saved_agg = sema->current_aggregate_lang;
|
|
||||||
sema->current_aggregate_lang = agg_lang;
|
|
||||||
for (usize i = 0; i < vec_size(fn_nodes); ++i)
|
|
||||||
sema_infer(sema, vec_at(fn_nodes, i));
|
|
||||||
sema->current_aggregate_lang = saved_agg;
|
|
||||||
|
|
||||||
vec_free(fn_nodes);
|
|
||||||
return agg_lang;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) {
|
||||||
|
spl_def_node_t *def = spl_def_node(sema->type, def_id);
|
||||||
|
if (!def)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (def->state == SPL_DECL_RESOLVED || def->state == SPL_DECL_ERROR)
|
||||||
|
return def->lang_id;
|
||||||
|
|
||||||
|
if (def->lang_id != 0) {
|
||||||
|
def->state = SPL_DECL_RESOLVED;
|
||||||
|
return def->lang_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def->state == SPL_DECL_RESOLVING) {
|
||||||
|
SPL_ERROR(&def->dbg_node, "circular dependency on `%s`", def->name ? def->name : "?");
|
||||||
|
sema->error_count++;
|
||||||
|
def->state = SPL_DECL_ERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
def->state = SPL_DECL_RESOLVING;
|
||||||
|
|
||||||
|
spl_ast_node_t *n = spl_ast_node(sema->ast, def->ast_node_ref);
|
||||||
|
spl_lang_type_id_t result = 0;
|
||||||
|
|
||||||
|
if (n) {
|
||||||
|
switch (n->kind) {
|
||||||
|
case SPL_AST_TYPE_DECL: {
|
||||||
|
if (n->type_decl.type_expr) {
|
||||||
|
spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr);
|
||||||
|
if (te && te->kind == SPL_AST_TYPE_AGGREGATE)
|
||||||
|
result = sema_build_aggregate(sema, te, def_id);
|
||||||
|
else
|
||||||
|
result = sema_infer(sema, n->type_decl.type_expr);
|
||||||
|
}
|
||||||
|
n->resolved_lang_tid = result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SPL_AST_FN_DECL: {
|
||||||
|
spl_lang_type_id_t saved_agg = sema->current_aggregate_lang;
|
||||||
|
if (def->owner_def) {
|
||||||
|
spl_def_node_t *owner = spl_def_node(sema->type, def->owner_def);
|
||||||
|
if (owner && owner->lang_id != 0)
|
||||||
|
sema->current_aggregate_lang = owner->lang_id;
|
||||||
|
}
|
||||||
|
result = sema_infer_fn_signature(sema, n);
|
||||||
|
sema->current_aggregate_lang = saved_agg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SPL_AST_VAR_DECL:
|
||||||
|
case SPL_AST_CONST_DECL: {
|
||||||
|
if (n->var_const_decl.type)
|
||||||
|
result = sema_infer(sema, n->var_const_decl.type);
|
||||||
|
else if (n->var_const_decl.init_expr)
|
||||||
|
result = sema_infer(sema, n->var_const_decl.init_expr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_def_node_t *final_def = spl_def_node(sema->type, def_id);
|
||||||
|
if (final_def) {
|
||||||
|
final_def->lang_id = result;
|
||||||
|
final_def->state = result ? SPL_DECL_RESOLVED : SPL_DECL_ERROR;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||||
spl_ast_node_t *n = spl_ast_node(sema->ast, ref);
|
spl_ast_node_t *n = spl_ast_node(sema->ast, ref);
|
||||||
if (!n)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
@@ -303,7 +393,7 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
spl_scope_insert(sema->scope, mod_scope, file_sym);
|
spl_scope_insert(sema->scope, mod_scope, file_sym);
|
||||||
|
|
||||||
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
|
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
|
||||||
sema_collect(sema, vec_at(n->container_members.declarations, i));
|
sema_collect_names(sema, vec_at(n->container_members.declarations, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 故意不恢复 current_scope
|
/* 故意不恢复 current_scope
|
||||||
@@ -351,7 +441,7 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
case SPL_AST_TOP_LEVEL_BLOCK:
|
case SPL_AST_TOP_LEVEL_BLOCK:
|
||||||
if (n->top_level_block.block) {
|
if (n->top_level_block.block) {
|
||||||
sema_collect(sema, n->top_level_block.block);
|
sema_collect_names(sema, n->top_level_block.block);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -359,6 +449,43 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sema_collect_types(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 && d->resolved_def_id)
|
||||||
|
sema_eval_decl(sema, d->resolved_def_id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPL_AST_TOP_LEVEL_BLOCK:
|
||||||
|
if (n->top_level_block.block)
|
||||||
|
sema_collect_types(sema, n->top_level_block.block);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sema_collect_signatures(spl_sema_t *sema) {
|
||||||
|
usize n = vec_size(sema->type->def_table);
|
||||||
|
for (usize i = 1; i < n; ++i) {
|
||||||
|
spl_def_node_t *d = &vec_at(sema->type->def_table, i);
|
||||||
|
if (d->kind == SPL_DEF_FN && d->state == SPL_DECL_UNRESOLVED)
|
||||||
|
sema_eval_decl(sema, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||||
|
sema_collect_names(sema, ref);
|
||||||
|
sema_collect_types(sema, ref);
|
||||||
|
sema_collect_signatures(sema);
|
||||||
|
}
|
||||||
|
|
||||||
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_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in,
|
||||||
spl_ast_node_ref_vec_t *args) {
|
spl_ast_node_ref_vec_t *args) {
|
||||||
const spl_intrin_info_t *info = spl_intrin_info(in);
|
const spl_intrin_info_t *info = spl_intrin_info(in);
|
||||||
@@ -502,6 +629,28 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
break; /* 非数组 expected:退回通用逻辑 */
|
break; /* 非数组 expected:退回通用逻辑 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SPL_AST_EXPR_TUPLE: {
|
||||||
|
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
|
||||||
|
if (en && en->kind == SPL_LANG_TYPE_TUPLE) {
|
||||||
|
usize nelems = vec_size(n->tuple.elems);
|
||||||
|
usize ntypes = vec_size(en->extra.elems);
|
||||||
|
if (nelems != ntypes) {
|
||||||
|
SPL_ERROR(&n->dbg, "tuple arity mismatch (expected %zu, got %zu)", ntypes, nelems);
|
||||||
|
sema->error_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (usize i = 0; i < nelems; ++i) {
|
||||||
|
spl_lang_type_id_t et = vec_at(en->extra.elems, i);
|
||||||
|
if (!sema_check(sema, vec_at(n->tuple.elems, i), et))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
n->resolved_lang_tid = expected;
|
||||||
|
n->expected_lang_tid = 0;
|
||||||
|
return expected;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SPL_AST_EXPR_AGGREGATE_LIT: {
|
case SPL_AST_EXPR_AGGREGATE_LIT: {
|
||||||
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
|
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
|
||||||
if (!en || (en->kind != SPL_LANG_TYPE_STRUCT && en->kind != SPL_LANG_TYPE_UNION &&
|
if (!en || (en->kind != SPL_LANG_TYPE_STRUCT && en->kind != SPL_LANG_TYPE_UNION &&
|
||||||
@@ -582,8 +731,8 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
seen[idx] = true;
|
seen[idx] = true;
|
||||||
spl_type_member_t *m = &vec_at(irn->agg_type.variants, idx);
|
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id);
|
spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
|
||||||
if (!ft)
|
if (!ft)
|
||||||
continue;
|
continue;
|
||||||
if (!item->struct_init_item.expr) {
|
if (!item->struct_init_item.expr) {
|
||||||
@@ -741,14 +890,9 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n->resolved_def_id = sym.node;
|
n->resolved_def_id = sym.node;
|
||||||
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
spl_lang_type_id_t t = sema_eval_decl(sema, sym.node);
|
||||||
if (!def) {
|
n->resolved_lang_tid = t;
|
||||||
SPL_ERROR(&n->dbg, "definition for `%s` not found", name);
|
return t;
|
||||||
sema->error_count++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
n->resolved_lang_tid = def->lang_id;
|
|
||||||
return def->lang_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- UNARY ---------- */
|
/* ---------- UNARY ---------- */
|
||||||
@@ -955,7 +1099,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
|
|
||||||
/* 固定参数:check 到形参类型 */
|
/* 固定参数:check 到形参类型 */
|
||||||
for (usize i = 0; i < nargs && i < fixed; ++i) {
|
for (usize i = 0; i < nargs && i < fixed; ++i) {
|
||||||
spl_lang_type_id_t pt = vec_at(fn->extra.fn.params, i);
|
spl_lang_type_id_t pt =
|
||||||
|
vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i);
|
||||||
sema_check(sema, vec_at(n->call.args, i), pt);
|
sema_check(sema, vec_at(n->call.args, i), pt);
|
||||||
}
|
}
|
||||||
/* varargs:默认提升到 isize */
|
/* varargs:默认提升到 isize */
|
||||||
@@ -1008,15 +1153,13 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (usize i = 0; i < vec_size(agg->methods); ++i) {
|
for (usize i = 0; i < vec_size(agg->methods); ++i) {
|
||||||
spl_lang_method_t *meth = &vec_at(agg->methods, i);
|
spl_lang_method_t meth = vec_at(agg->methods, i);
|
||||||
if (strcmp(meth->name, n->field.field) != 0)
|
if (strcmp(meth.name, n->field.field) != 0)
|
||||||
continue;
|
continue;
|
||||||
spl_def_node_t *fd = spl_def_node(sema->type, meth->def_id);
|
n->resolved_def_id = meth.def_id;
|
||||||
if (!fd)
|
spl_lang_type_id_t t = sema_eval_decl(sema, meth.def_id);
|
||||||
return 0;
|
n->resolved_lang_tid = t;
|
||||||
n->resolved_def_id = meth->def_id;
|
return t;
|
||||||
n->resolved_lang_tid = fd->lang_id;
|
|
||||||
return fd->lang_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SPL_ERROR(&n->dbg, "no field `%s`", n->field.field);
|
SPL_ERROR(&n->dbg, "no field `%s`", n->field.field);
|
||||||
@@ -1039,10 +1182,22 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
case SPL_LANG_TYPE_PTR:
|
case SPL_LANG_TYPE_PTR:
|
||||||
elem = obj->extra.elem;
|
elem = obj->extra.elem;
|
||||||
break;
|
break;
|
||||||
case SPL_LANG_TYPE_TUPLE:
|
case SPL_LANG_TYPE_TUPLE: {
|
||||||
if (vec_size(obj->extra.elems) > 0)
|
spl_ast_node_t *idx_node = spl_ast_node(sema->ast, n->index.index);
|
||||||
elem = vec_at(obj->extra.elems, 0);
|
if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT) {
|
||||||
|
SPL_ERROR(&n->dbg, "tuple index must be an integer literal");
|
||||||
|
sema->error_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
isize i = idx_node->int_lit.val;
|
||||||
|
if (i < 0 || (usize)i >= vec_size(obj->extra.elems)) {
|
||||||
|
SPL_ERROR(&n->dbg, "tuple index out of range");
|
||||||
|
sema->error_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
elem = vec_at(obj->extra.elems, (usize)i);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
SPL_ERROR(&n->dbg, "index base must be array/slice/ptr/range/tuple");
|
SPL_ERROR(&n->dbg, "index base must be array/slice/ptr/range/tuple");
|
||||||
sema->error_count++;
|
sema->error_count++;
|
||||||
@@ -1183,8 +1338,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
sema->error_count++;
|
sema->error_count++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
spl_type_member_t *m = &vec_at(irn->agg_type.variants, idx);
|
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id);
|
spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
|
||||||
if (ft && item->struct_init_item.expr)
|
if (ft && item->struct_init_item.expr)
|
||||||
sema_check(sema, item->struct_init_item.expr, ft);
|
sema_check(sema, item->struct_init_item.expr, ft);
|
||||||
}
|
}
|
||||||
@@ -1245,20 +1400,48 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SPL_AST_EXPR_WHILE: {
|
case SPL_AST_EXPR_WHILE: {
|
||||||
|
const char *lbl = NULL;
|
||||||
|
if (n->while_expr.label) {
|
||||||
|
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->while_expr.label);
|
||||||
|
if (ln && ln->kind == SPL_AST_LABEL)
|
||||||
|
lbl = ln->label.name;
|
||||||
|
}
|
||||||
|
vec_push(sema->label_stack, lbl);
|
||||||
|
|
||||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||||
sema_check(sema, n->while_expr.cond, bt);
|
sema_check(sema, n->while_expr.cond, bt);
|
||||||
if (n->while_expr.body)
|
if (n->while_expr.body)
|
||||||
sema_infer(sema, n->while_expr.body);
|
sema_infer(sema, n->while_expr.body);
|
||||||
if (n->while_expr.else_branch)
|
if (n->while_expr.else_branch)
|
||||||
sema_infer(sema, n->while_expr.else_branch);
|
sema_infer(sema, n->while_expr.else_branch);
|
||||||
|
|
||||||
|
vec_pop(sema->label_stack);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SPL_AST_EXPR_LOOP: {
|
case SPL_AST_EXPR_LOOP: {
|
||||||
|
const char *lbl = NULL;
|
||||||
|
if (n->loop_expr.label) {
|
||||||
|
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->loop_expr.label);
|
||||||
|
if (ln && ln->kind == SPL_AST_LABEL)
|
||||||
|
lbl = ln->label.name;
|
||||||
|
}
|
||||||
|
vec_push(sema->label_stack, lbl);
|
||||||
|
|
||||||
if (n->loop_expr.body)
|
if (n->loop_expr.body)
|
||||||
sema_infer(sema, n->loop_expr.body);
|
sema_infer(sema, n->loop_expr.body);
|
||||||
|
|
||||||
|
vec_pop(sema->label_stack);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SPL_AST_EXPR_FOR: {
|
case SPL_AST_EXPR_FOR: {
|
||||||
|
const char *lbl = NULL;
|
||||||
|
if (n->for_expr.label) {
|
||||||
|
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->for_expr.label);
|
||||||
|
if (ln && ln->kind == SPL_AST_LABEL)
|
||||||
|
lbl = ln->label.name;
|
||||||
|
}
|
||||||
|
vec_push(sema->label_stack, lbl);
|
||||||
|
|
||||||
sema_push_scope(sema);
|
sema_push_scope(sema);
|
||||||
for (usize i = 0; i < vec_size(n->for_expr.iter_exprs); ++i) {
|
for (usize i = 0; i < vec_size(n->for_expr.iter_exprs); ++i) {
|
||||||
spl_lang_type_id_t container_tid = sema_infer(sema, vec_at(n->for_expr.iter_exprs, i));
|
spl_lang_type_id_t container_tid = sema_infer(sema, vec_at(n->for_expr.iter_exprs, i));
|
||||||
@@ -1284,6 +1467,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
if (n->for_expr.else_branch)
|
if (n->for_expr.else_branch)
|
||||||
sema_infer(sema, n->for_expr.else_branch);
|
sema_infer(sema, n->for_expr.else_branch);
|
||||||
sema_pop_scope(sema);
|
sema_pop_scope(sema);
|
||||||
|
|
||||||
|
vec_pop(sema->label_stack);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SPL_AST_EXPR_MATCH: {
|
case SPL_AST_EXPR_MATCH: {
|
||||||
@@ -1326,11 +1511,9 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
sema->error_count++;
|
sema->error_count++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
spl_lang_type_id_t t = sema_eval_decl(sema, sym.node);
|
||||||
if (!def || !def->lang_id)
|
n->resolved_lang_tid = t;
|
||||||
return 0;
|
return t;
|
||||||
n->resolved_lang_tid = def->lang_id;
|
|
||||||
return def->lang_id;
|
|
||||||
}
|
}
|
||||||
case SPL_AST_TYPE_POINTER: {
|
case SPL_AST_TYPE_POINTER: {
|
||||||
spl_lang_type_id_t p = sema_infer(sema, n->type_pointer.pointee);
|
spl_lang_type_id_t p = sema_infer(sema, n->type_pointer.pointee);
|
||||||
@@ -1386,7 +1569,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
case SPL_AST_TYPE_AGGREGATE:
|
case SPL_AST_TYPE_AGGREGATE:
|
||||||
return sema_build_aggregate(sema, n);
|
return sema_build_aggregate(sema, n, 0);
|
||||||
case SPL_AST_TYPE_COMPTIME_CALL: {
|
case SPL_AST_TYPE_COMPTIME_CALL: {
|
||||||
const char *name = n->type_comptime_call.name;
|
const char *name = n->type_comptime_call.name;
|
||||||
if (name && strcmp(name, "self") == 0) {
|
if (name && strcmp(name, "self") == 0) {
|
||||||
@@ -1411,62 +1594,79 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
if (n->resolved_def_id == 0)
|
if (n->resolved_def_id == 0)
|
||||||
Panic("fn `%s` not collected", n->fn_decl.name);
|
Panic("fn `%s` not collected", n->fn_decl.name);
|
||||||
|
|
||||||
spl_lang_type_id_vec_t param_types;
|
spl_def_node_t *def = spl_def_node(sema->type, n->resolved_def_id);
|
||||||
vec_init(param_types);
|
if (!def)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
spl_def_id_t owner_def_id = def->owner_def;
|
||||||
|
spl_lang_type_id_t fn_tid = def->lang_id;
|
||||||
|
if (fn_tid == 0)
|
||||||
|
fn_tid = sema_eval_decl(sema, n->resolved_def_id);
|
||||||
|
spl_lang_type_node_t *fn_ln = spl_lang_type_node(sema->type, fn_tid);
|
||||||
|
if (!fn_ln || fn_ln->kind != SPL_LANG_TYPE_FN)
|
||||||
|
return 0;
|
||||||
|
spl_lang_type_id_t ret_tid = fn_ln->extra.fn.ret;
|
||||||
|
|
||||||
|
if (!n->fn_decl.body)
|
||||||
|
return fn_tid;
|
||||||
|
|
||||||
|
spl_lang_type_id_t saved_agg = sema->current_aggregate_lang;
|
||||||
|
if (owner_def_id) {
|
||||||
|
spl_def_node_t *owner = spl_def_node(sema->type, owner_def_id);
|
||||||
|
if (owner && owner->lang_id != 0)
|
||||||
|
sema->current_aggregate_lang = owner->lang_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
sema_push_scope(sema);
|
||||||
for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) {
|
for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) {
|
||||||
spl_ast_node_t *pd = spl_ast_node(sema->ast, vec_at(n->fn_decl.params, i));
|
spl_ast_node_t *pd = spl_ast_node(sema->ast, vec_at(n->fn_decl.params, i));
|
||||||
if (pd && pd->kind == SPL_AST_PARAM_DECL && pd->param_decl.type_expr)
|
if (pd && pd->kind == SPL_AST_PARAM_DECL) {
|
||||||
vec_push(param_types, sema_infer(sema, pd->param_decl.type_expr));
|
spl_symbol_t psym = {.name = pd->param_decl.name, .kind = SPL_SYMBOL_KIND_VAR};
|
||||||
else
|
psym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, psym.name, pd->dbg,
|
||||||
vec_push(param_types, spl_lang_make_varargs(sema->type));
|
vec_at(n->fn_decl.params, i));
|
||||||
}
|
spl_lang_type_id_t p_tid = sema_infer(sema, pd->param_decl.type_expr);
|
||||||
spl_lang_type_id_t ret_tid = sema_infer(sema, n->fn_decl.ret_type);
|
spl_def_node_t *pdef = spl_def_node(sema->type, psym.node);
|
||||||
if (ret_tid == 0)
|
if (pdef) {
|
||||||
ret_tid = spl_lang_make_unit(sema->type);
|
pdef->lang_id = p_tid;
|
||||||
spl_lang_type_id_t fn_tid = spl_lang_make_fn(
|
pdef->state = p_tid ? SPL_DECL_RESOLVED : SPL_DECL_ERROR;
|
||||||
sema->type, ret_tid, vec_unsafe_get_data(param_types), vec_size(param_types));
|
|
||||||
vec_free(param_types);
|
|
||||||
spl_def_resolve(sema->type, n->resolved_def_id, fn_tid);
|
|
||||||
|
|
||||||
if (n->fn_decl.body) {
|
|
||||||
sema_push_scope(sema);
|
|
||||||
for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) {
|
|
||||||
spl_ast_node_t *pd = spl_ast_node(sema->ast, vec_at(n->fn_decl.params, i));
|
|
||||||
if (pd && pd->kind == SPL_AST_PARAM_DECL) {
|
|
||||||
spl_symbol_t psym = {.name = pd->param_decl.name, .kind = SPL_SYMBOL_KIND_VAR};
|
|
||||||
psym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, psym.name, pd->dbg,
|
|
||||||
vec_at(n->fn_decl.params, i));
|
|
||||||
spl_lang_type_id_t p_tid = sema_infer(sema, pd->param_decl.type_expr);
|
|
||||||
spl_def_resolve(sema->type, psym.node, p_tid);
|
|
||||||
pd->resolved_def_id = psym.node;
|
|
||||||
spl_scope_insert(sema->scope, sema->scope->current_scope, psym);
|
|
||||||
}
|
}
|
||||||
|
pd->resolved_def_id = psym.node;
|
||||||
|
spl_scope_insert(sema->scope, sema->scope->current_scope, psym);
|
||||||
}
|
}
|
||||||
spl_lang_type_id_t old_ret = sema->current_fn_ret_tid;
|
|
||||||
sema->current_fn_ret_tid = ret_tid;
|
|
||||||
sema_infer(sema, n->fn_decl.body);
|
|
||||||
sema->current_fn_ret_tid = old_ret;
|
|
||||||
sema_pop_scope(sema);
|
|
||||||
}
|
}
|
||||||
|
spl_lang_type_id_t old_ret = sema->current_fn_ret_tid;
|
||||||
|
sema->current_fn_ret_tid = ret_tid;
|
||||||
|
sema_infer(sema, n->fn_decl.body);
|
||||||
|
sema->current_fn_ret_tid = old_ret;
|
||||||
|
sema_pop_scope(sema);
|
||||||
|
|
||||||
|
sema->current_aggregate_lang = saved_agg;
|
||||||
return fn_tid;
|
return fn_tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SPL_AST_TYPE_DECL: {
|
case SPL_AST_TYPE_DECL: {
|
||||||
if (!n->type_decl.type_expr)
|
if (!n->type_decl.type_expr)
|
||||||
break;
|
break;
|
||||||
spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr);
|
spl_def_node_t *def =
|
||||||
if (!te)
|
n->resolved_def_id ? spl_def_node(sema->type, n->resolved_def_id) : NULL;
|
||||||
|
if (!def)
|
||||||
break;
|
break;
|
||||||
if (te->kind == SPL_AST_TYPE_AGGREGATE) {
|
spl_lang_type_id_t lang = def->lang_id;
|
||||||
spl_lang_type_id_t agg_lang = sema_build_aggregate(sema, te);
|
if (lang == 0)
|
||||||
spl_def_resolve(sema->type, n->resolved_def_id, agg_lang);
|
lang = sema_eval_decl(sema, n->resolved_def_id);
|
||||||
n->resolved_lang_tid = agg_lang;
|
if (lang == 0)
|
||||||
} else {
|
break;
|
||||||
spl_lang_type_id_t tid = sema_infer(sema, n->type_decl.type_expr);
|
|
||||||
spl_def_resolve(sema->type, n->resolved_def_id, tid);
|
spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr);
|
||||||
n->resolved_lang_tid = tid;
|
if (te && te->kind == SPL_AST_TYPE_AGGREGATE) {
|
||||||
|
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
|
||||||
|
spl_ast_node_ref_t mref = vec_at(te->type_aggregate.members, i);
|
||||||
|
spl_ast_node_t *mn = spl_ast_node(sema->ast, mref);
|
||||||
|
if (mn && mn->kind == SPL_AST_FN_DECL)
|
||||||
|
sema_infer(sema, mref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
return lang;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- VAR / CONST ---------- */
|
/* ---------- VAR / CONST ---------- */
|
||||||
@@ -1541,9 +1741,64 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SPL_AST_STATEMENT_BREAK:
|
case SPL_AST_STATEMENT_BREAK: {
|
||||||
case SPL_AST_STATEMENT_CONTINUE:
|
const char *lbl = NULL;
|
||||||
|
if (n->statement_break.label) {
|
||||||
|
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->statement_break.label);
|
||||||
|
if (ln && ln->kind == SPL_AST_LABEL)
|
||||||
|
lbl = ln->label.name;
|
||||||
|
}
|
||||||
|
if (vec_size(sema->label_stack) == 0) {
|
||||||
|
SPL_ERROR(&n->dbg, "`break` outside of loop");
|
||||||
|
sema->error_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (lbl) {
|
||||||
|
bool found = false;
|
||||||
|
for (usize i = vec_size(sema->label_stack); i > 0; --i) {
|
||||||
|
const char *cur = vec_at(sema->label_stack, i - 1);
|
||||||
|
if (cur && strcmp(cur, lbl) == 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
|
||||||
|
sema->error_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n->statement_break.expr)
|
||||||
|
sema_infer(sema, n->statement_break.expr);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
case SPL_AST_STATEMENT_CONTINUE: {
|
||||||
|
const char *lbl = NULL;
|
||||||
|
if (n->statement_continue.label) {
|
||||||
|
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->statement_continue.label);
|
||||||
|
if (ln && ln->kind == SPL_AST_LABEL)
|
||||||
|
lbl = ln->label.name;
|
||||||
|
}
|
||||||
|
if (vec_size(sema->label_stack) == 0) {
|
||||||
|
SPL_ERROR(&n->dbg, "`continue` outside of loop");
|
||||||
|
sema->error_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (lbl) {
|
||||||
|
bool found = false;
|
||||||
|
for (usize i = vec_size(sema->label_stack); i > 0; --i) {
|
||||||
|
const char *cur = vec_at(sema->label_stack, i - 1);
|
||||||
|
if (cur && strcmp(cur, lbl) == 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
|
||||||
|
sema->error_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
case SPL_AST_STATEMENT_DEFER:
|
case SPL_AST_STATEMENT_DEFER:
|
||||||
if (n->statement_defer.body)
|
if (n->statement_defer.body)
|
||||||
sema_infer(sema, n->statement_defer.body);
|
sema_infer(sema, n->statement_defer.body);
|
||||||
@@ -1580,12 +1835,14 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope
|
|||||||
sema->scope = scope;
|
sema->scope = scope;
|
||||||
sema->error_count = 0;
|
sema->error_count = 0;
|
||||||
sema->current_fn_ret_tid = 0;
|
sema->current_fn_ret_tid = 0;
|
||||||
|
sema->current_aggregate_lang = 0;
|
||||||
sema->attr = attr;
|
sema->attr = attr;
|
||||||
sema->root = (spl_symbol_t){0};
|
sema->root = (spl_symbol_t){0};
|
||||||
sema->store_scope = 0;
|
sema->store_scope = 0;
|
||||||
|
vec_init(sema->label_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spl_sema_drop(spl_sema_t *sema) { (void)sema; }
|
void spl_sema_drop(spl_sema_t *sema) { vec_free(sema->label_stack); }
|
||||||
|
|
||||||
void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) {
|
void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) {
|
||||||
if (!sema->ast || !module_ref)
|
if (!sema->ast || !module_ref)
|
||||||
@@ -1595,8 +1852,6 @@ void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) {
|
|||||||
return;
|
return;
|
||||||
spl_scope_id_t saved = sema->scope->current_scope;
|
spl_scope_id_t saved = sema->scope->current_scope;
|
||||||
sema_collect(sema, module_ref);
|
sema_collect(sema, module_ref);
|
||||||
fprintf(stderr, "after collect: current=%zu root=%zu\n", sema->scope->current_scope,
|
|
||||||
sema->scope->root_scope);
|
|
||||||
sema_infer(sema, module_ref);
|
sema_infer(sema, module_ref);
|
||||||
sema->scope->current_scope = saved;
|
sema->scope->current_scope = saved;
|
||||||
}
|
}
|
||||||
@@ -1604,11 +1859,9 @@ void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) {
|
|||||||
void spl_sema_run(spl_sema_t *sema) {
|
void spl_sema_run(spl_sema_t *sema) {
|
||||||
if (!sema->ast || !sema->ast->root)
|
if (!sema->ast || !sema->ast->root)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spl_ast_node_t *root = spl_ast_node(sema->ast, sema->ast->root);
|
spl_ast_node_t *root = spl_ast_node(sema->ast, sema->ast->root);
|
||||||
if (!root || root->kind != SPL_AST_ROOT)
|
if (!root || root->kind != SPL_AST_ROOT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spl_sema_run_module(sema, root->root.members);
|
spl_sema_run_module(sema, root->root.members);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ typedef struct {
|
|||||||
spl_attr_t *attr;
|
spl_attr_t *attr;
|
||||||
spl_lang_type_id_t current_aggregate_lang;
|
spl_lang_type_id_t current_aggregate_lang;
|
||||||
spl_lang_type_id_t current_fn_ret_tid;
|
spl_lang_type_id_t current_fn_ret_tid;
|
||||||
|
spl_symbol_path_t label_stack;
|
||||||
} spl_sema_t;
|
} spl_sema_t;
|
||||||
|
|
||||||
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope,
|
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope,
|
||||||
|
|||||||
+3
-11
@@ -495,6 +495,8 @@ spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const cha
|
|||||||
n.dbg_node = dbg;
|
n.dbg_node = dbg;
|
||||||
n.lang_id = 0;
|
n.lang_id = 0;
|
||||||
n.ast_node_ref = ast_node_ref;
|
n.ast_node_ref = ast_node_ref;
|
||||||
|
n.state = SPL_DECL_UNRESOLVED;
|
||||||
|
n.owner_def = 0;
|
||||||
vec_push(type->def_table, n);
|
vec_push(type->def_table, n);
|
||||||
return vec_size(type->def_table) - 1;
|
return vec_size(type->def_table) - 1;
|
||||||
}
|
}
|
||||||
@@ -1091,17 +1093,7 @@ void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) {
|
|||||||
def_kind_name = "agg";
|
def_kind_name = "agg";
|
||||||
break;
|
break;
|
||||||
case SPL_DEF_BUILTIN:
|
case SPL_DEF_BUILTIN:
|
||||||
switch (node->builtin_kind) {
|
def_kind_name = "builtin";
|
||||||
case SPL_BUILTIN_RANGE:
|
|
||||||
def_kind_name = "builtin.range";
|
|
||||||
break;
|
|
||||||
case SPL_BUILTIN_SLICE:
|
|
||||||
def_kind_name = "builtin.slice";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
def_kind_name = "builtin";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SPL_DEF_DISTINCT:
|
case SPL_DEF_DISTINCT:
|
||||||
def_kind_name = "distinct";
|
def_kind_name = "distinct";
|
||||||
|
|||||||
+9
-5
@@ -138,17 +138,21 @@ typedef enum {
|
|||||||
SPL_DEF_BUILTIN,
|
SPL_DEF_BUILTIN,
|
||||||
} spl_def_node_kind_t;
|
} spl_def_node_kind_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SPL_DECL_UNRESOLVED,
|
||||||
|
SPL_DECL_RESOLVING,
|
||||||
|
SPL_DECL_RESOLVED,
|
||||||
|
SPL_DECL_ERROR,
|
||||||
|
} spl_decl_state_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spl_def_node_kind_t kind;
|
spl_def_node_kind_t kind;
|
||||||
enum {
|
|
||||||
SPL_BUILTIN_NONE,
|
|
||||||
SPL_BUILTIN_SLICE,
|
|
||||||
SPL_BUILTIN_RANGE,
|
|
||||||
} builtin_kind;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
spl_dbg_node_t dbg_node;
|
spl_dbg_node_t dbg_node;
|
||||||
spl_lang_type_id_t lang_id;
|
spl_lang_type_id_t lang_id;
|
||||||
usize ast_node_ref;
|
usize ast_node_ref;
|
||||||
|
spl_decl_state_t state;
|
||||||
|
spl_def_id_t owner_def;
|
||||||
} spl_def_node_t;
|
} spl_def_node_t;
|
||||||
typedef VEC(spl_def_node_t) spl_def_node_vec_t;
|
typedef VEC(spl_def_node_t) spl_def_node_vec_t;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user