stage1 重构代码 语法上重新实现解包语法
This commit is contained in:
1 parent
2a84b61e3d
commit
54425a50c7
10 files changed
+2681
-2478
No files matched your search
+157
-46
@@ -833,6 +833,67 @@ static spl_lang_type_id_t sema_block_body(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
return r;
|
||||
}
|
||||
|
||||
static void sema_bind_pattern(spl_sema_t *sema, spl_ast_node_ref_t pat_ref,
|
||||
spl_lang_type_id_t matched_tid) {
|
||||
if (!pat_ref)
|
||||
return;
|
||||
spl_ast_node_t *pat = spl_ast_node(sema->ast, pat_ref);
|
||||
if (!pat)
|
||||
return;
|
||||
|
||||
switch (pat->kind) {
|
||||
case SPL_AST_PATTERN_IDENT: {
|
||||
const char *name = pat->pattern_ident.name;
|
||||
spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR};
|
||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, pat->dbg, sema->ast, pat_ref);
|
||||
spl_def_resolve(sema->type, sym.node, matched_tid);
|
||||
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &pat->dbg,
|
||||
"duplicate symbol `%s`", name);
|
||||
}
|
||||
pat->resolved_def_id = sym.node;
|
||||
pat->resolved_lang_tid = matched_tid;
|
||||
return;
|
||||
}
|
||||
|
||||
case SPL_AST_PATTERN_UNDERSCORE:
|
||||
return;
|
||||
|
||||
case SPL_AST_PATTERN_TUPLE: {
|
||||
spl_lang_type_node_t *tn = spl_lang_type_node(sema->type, matched_tid);
|
||||
if (!tn || tn->kind != SPL_LANG_TYPE_TUPLE) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &pat->dbg,
|
||||
"tuple pattern requires a tuple value");
|
||||
return;
|
||||
}
|
||||
usize natoms = vec_size(pat->pattern_tuple.patterns);
|
||||
usize nelems = vec_size(tn->extra.elems);
|
||||
if (natoms != nelems) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &pat->dbg,
|
||||
"tuple pattern arity mismatch (expected %zu, got %zu)", nelems, natoms);
|
||||
return;
|
||||
}
|
||||
/* 递归 bind 会 push lang_table,tn 会悬垂;先把元素类型拷到本地 */
|
||||
spl_lang_type_id_vec_t elem_tids;
|
||||
vec_init(elem_tids);
|
||||
for (usize i = 0; i < nelems; ++i)
|
||||
vec_push(elem_tids, vec_at(tn->extra.elems, i));
|
||||
for (usize i = 0; i < natoms; ++i)
|
||||
sema_bind_pattern(sema, vec_at(pat->pattern_tuple.patterns, i), vec_at(elem_tids, i));
|
||||
vec_free(elem_tids);
|
||||
pat->resolved_lang_tid = matched_tid;
|
||||
return;
|
||||
}
|
||||
|
||||
case SPL_AST_PATTERN_DOT:
|
||||
case SPL_AST_PATTERN_AGGREGATE:
|
||||
default:
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNHANDLED_NODE, &pat->dbg,
|
||||
"pattern kind %d not yet supported", (int)pat->kind);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
spl_lang_type_id_t expected) {
|
||||
if (!ref || !expected)
|
||||
@@ -1014,23 +1075,34 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
}
|
||||
|
||||
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, expected);
|
||||
spl_type_node_t *irn = spl_type_node(&sema->type->ir, agg_ir);
|
||||
if (!irn) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"aggregate type unresolved");
|
||||
return 0;
|
||||
|
||||
/* 先把每个字段的 ir type_id 拷到本地:循环里 sema_coerce 会 push
|
||||
type_table,irn 会悬垂。 */
|
||||
spl_type_id_vec_t field_ir_ids;
|
||||
vec_init(field_ir_ids);
|
||||
{
|
||||
spl_type_node_t *irn = spl_type_node(&sema->type->ir, agg_ir);
|
||||
if (!irn) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"aggregate type unresolved");
|
||||
return 0;
|
||||
}
|
||||
for (usize i = 0; i < vec_size(irn->agg_type.variants); i++)
|
||||
vec_push(field_ir_ids, vec_at(irn->agg_type.variants, i).type_id);
|
||||
}
|
||||
|
||||
if (en->kind == SPL_LANG_TYPE_ENUM) {
|
||||
if (vec_size(n->aggregate_literal.fields) != 1) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"enum literal must have exactly one variant");
|
||||
vec_free(field_ir_ids);
|
||||
return 0;
|
||||
}
|
||||
spl_ast_node_t *item = spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, 0));
|
||||
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"invalid enum literal");
|
||||
vec_free(field_ir_ids);
|
||||
return 0;
|
||||
}
|
||||
usize idx = 0;
|
||||
@@ -1038,14 +1110,22 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
&idx)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no variant `%s`",
|
||||
item->struct_init_item.name);
|
||||
vec_free(field_ir_ids);
|
||||
return 0;
|
||||
}
|
||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||
if (idx >= vec_size(field_ir_ids)) {
|
||||
vec_free(field_ir_ids);
|
||||
return 0;
|
||||
}
|
||||
usize field_tid_ir = vec_at(field_ir_ids, idx);
|
||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
|
||||
if (ft && item->struct_init_item.expr) {
|
||||
if (!sema_coerce(sema, item->struct_init_item.expr, ft))
|
||||
if (!sema_coerce(sema, item->struct_init_item.expr, ft)) {
|
||||
vec_free(field_ir_ids);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
vec_free(field_ir_ids);
|
||||
n->resolved_lang_tid = expected;
|
||||
return expected;
|
||||
}
|
||||
@@ -1061,13 +1141,18 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
item->struct_init_item.name);
|
||||
continue;
|
||||
}
|
||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||
if (idx >= vec_size(field_ir_ids))
|
||||
continue;
|
||||
usize field_tid_ir = vec_at(field_ir_ids, idx);
|
||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
|
||||
if (ft && item->struct_init_item.expr) {
|
||||
if (!sema_coerce(sema, item->struct_init_item.expr, ft))
|
||||
if (!sema_coerce(sema, item->struct_init_item.expr, ft)) {
|
||||
vec_free(field_ir_ids);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
vec_free(field_ir_ids);
|
||||
n->resolved_lang_tid = expected;
|
||||
return expected;
|
||||
}
|
||||
@@ -1671,26 +1756,41 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return 0;
|
||||
}
|
||||
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg);
|
||||
spl_type_node_t *irn = spl_type_node(&sema->type->ir, agg_ir);
|
||||
if (irn) {
|
||||
for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) {
|
||||
spl_ast_node_t *item =
|
||||
spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, i));
|
||||
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM)
|
||||
continue;
|
||||
usize idx = 0;
|
||||
if (!spl_type_agg_member_idx(&sema->type->ir, agg_ir, item->struct_init_item.name,
|
||||
&idx)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
|
||||
item->struct_init_item.name);
|
||||
continue;
|
||||
}
|
||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
|
||||
if (ft && item->struct_init_item.expr)
|
||||
sema_coerce(sema, item->struct_init_item.expr, ft);
|
||||
|
||||
/* 循环里 sema_coerce 会 push type_table,irn 会悬垂。
|
||||
先把每个字段的 ir type_id 拷到本地。 */
|
||||
spl_type_id_vec_t field_ir_ids;
|
||||
vec_init(field_ir_ids);
|
||||
{
|
||||
spl_type_node_t *irn = spl_type_node(&sema->type->ir, agg_ir);
|
||||
if (!irn) {
|
||||
n->resolved_lang_tid = agg;
|
||||
return agg;
|
||||
}
|
||||
for (usize i = 0; i < vec_size(irn->agg_type.variants); i++)
|
||||
vec_push(field_ir_ids, vec_at(irn->agg_type.variants, i).type_id);
|
||||
}
|
||||
|
||||
for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) {
|
||||
spl_ast_node_t *item = spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, i));
|
||||
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM)
|
||||
continue;
|
||||
usize idx = 0;
|
||||
if (!spl_type_agg_member_idx(&sema->type->ir, agg_ir, item->struct_init_item.name,
|
||||
&idx)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
|
||||
item->struct_init_item.name);
|
||||
continue;
|
||||
}
|
||||
if (idx >= vec_size(field_ir_ids))
|
||||
continue;
|
||||
usize field_tid_ir = vec_at(field_ir_ids, idx);
|
||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
|
||||
if (ft && item->struct_init_item.expr)
|
||||
sema_coerce(sema, item->struct_init_item.expr, ft);
|
||||
}
|
||||
vec_free(field_ir_ids);
|
||||
|
||||
n->resolved_lang_tid = agg;
|
||||
return agg;
|
||||
}
|
||||
@@ -1793,28 +1893,39 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
vec_push(sema->label_stack, lbl);
|
||||
|
||||
sema_push_scope(sema);
|
||||
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 elem_tid = sema_for_elem_type(sema, container_tid);
|
||||
if (i < vec_size(n->for_expr.idents)) {
|
||||
spl_ast_node_t *id_node = spl_ast_node(sema->ast, vec_at(n->for_expr.idents, i));
|
||||
if (id_node && id_node->kind == SPL_AST_EXPR_IDENT) {
|
||||
const char *var_name = id_node->ident.name;
|
||||
if (strcmp(var_name, "_") != 0) {
|
||||
spl_symbol_t sym = {.name = var_name, .kind = SPL_SYMBOL_KIND_VAR};
|
||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, var_name, id_node->dbg,
|
||||
sema->ast, vec_at(n->for_expr.idents, i));
|
||||
spl_def_resolve(sema->type, sym.node, elem_tid);
|
||||
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL,
|
||||
&id_node->dbg, "duplicate symbol `%s`", var_name);
|
||||
}
|
||||
id_node->resolved_def_id = sym.node;
|
||||
id_node->resolved_lang_tid = elem_tid;
|
||||
}
|
||||
|
||||
usize nsrc = vec_size(n->for_expr.iter_exprs);
|
||||
spl_ast_node_ref_t pat_ref = n->for_expr.pattern;
|
||||
spl_ast_node_t *pat = pat_ref ? spl_ast_node(sema->ast, pat_ref) : NULL;
|
||||
|
||||
if (pat && pat->kind == SPL_AST_PATTERN_LIST) {
|
||||
usize natoms = vec_size(pat->pattern_list.patterns);
|
||||
for (usize i = 0; i < nsrc; ++i) {
|
||||
spl_lang_type_id_t container_tid =
|
||||
sema_infer(sema, vec_at(n->for_expr.iter_exprs, i));
|
||||
spl_lang_type_id_t elem_tid = sema_for_elem_type(sema, container_tid);
|
||||
if (i < natoms)
|
||||
sema_bind_pattern(sema, vec_at(pat->pattern_list.patterns, i), elem_tid);
|
||||
}
|
||||
if (natoms > nsrc) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &pat->dbg,
|
||||
"for: pattern has %zu atoms but only %zu sources", natoms, nsrc);
|
||||
}
|
||||
} else {
|
||||
for (usize i = 0; i < nsrc; ++i) {
|
||||
spl_lang_type_id_t container_tid =
|
||||
sema_infer(sema, vec_at(n->for_expr.iter_exprs, i));
|
||||
if (i == 0 && pat_ref) {
|
||||
spl_lang_type_id_t elem_tid = sema_for_elem_type(sema, container_tid);
|
||||
sema_bind_pattern(sema, pat_ref, elem_tid);
|
||||
}
|
||||
}
|
||||
if (nsrc > 1 && pat_ref) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &pat->dbg,
|
||||
"for: multiple sources require pattern list");
|
||||
}
|
||||
}
|
||||
|
||||
if (n->for_expr.body)
|
||||
sema_infer(sema, n->for_expr.body);
|
||||
if (n->for_expr.else_branch)
|
||||
|
||||
Reference in new issue
Block a user