stage1 支持任意顺序声明 使用eval求值的机制
This commit is contained in:
1 parent
a1e684f6d4
commit
a621e34d51
6 files changed
+336
-123
No files matched your search
+215
-83
@@ -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,
|
||||
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_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) {
|
||||
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;
|
||||
vec_init(members);
|
||||
spl_lang_method_vec_t 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) {
|
||||
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_alloc(sema->type, SPL_DEF_FN, mn->fn_decl.name, mn->dbg, mref);
|
||||
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};
|
||||
vec_push(methods, meth);
|
||||
vec_push(fn_nodes, mref);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,19 +296,81 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t
|
||||
ln.kind = lk;
|
||||
ln.ir_type_id = agg_ir;
|
||||
ln.methods = methods;
|
||||
spl_lang_type_id_t agg_lang = 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;
|
||||
return spl_lang_node_push(sema->type, &ln);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
def->lang_id = result;
|
||||
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);
|
||||
if (!n)
|
||||
return;
|
||||
@@ -303,7 +394,7 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_scope_insert(sema->scope, mod_scope, file_sym);
|
||||
|
||||
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
|
||||
@@ -351,7 +442,7 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
case SPL_AST_TOP_LEVEL_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;
|
||||
default:
|
||||
@@ -359,6 +450,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,
|
||||
spl_ast_node_ref_vec_t *args) {
|
||||
const spl_intrin_info_t *info = spl_intrin_info(in);
|
||||
@@ -741,14 +869,9 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return 0;
|
||||
}
|
||||
n->resolved_def_id = sym.node;
|
||||
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
||||
if (!def) {
|
||||
SPL_ERROR(&n->dbg, "definition for `%s` not found", name);
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = def->lang_id;
|
||||
return def->lang_id;
|
||||
spl_lang_type_id_t t = sema_eval_decl(sema, sym.node);
|
||||
n->resolved_lang_tid = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* ---------- UNARY ---------- */
|
||||
@@ -1011,12 +1134,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_lang_method_t *meth = &vec_at(agg->methods, i);
|
||||
if (strcmp(meth->name, n->field.field) != 0)
|
||||
continue;
|
||||
spl_def_node_t *fd = spl_def_node(sema->type, meth->def_id);
|
||||
if (!fd)
|
||||
return 0;
|
||||
n->resolved_def_id = meth->def_id;
|
||||
n->resolved_lang_tid = fd->lang_id;
|
||||
return fd->lang_id;
|
||||
spl_lang_type_id_t t = sema_eval_decl(sema, meth->def_id);
|
||||
n->resolved_lang_tid = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
SPL_ERROR(&n->dbg, "no field `%s`", n->field.field);
|
||||
@@ -1326,11 +1447,9 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
||||
if (!def || !def->lang_id)
|
||||
return 0;
|
||||
n->resolved_lang_tid = def->lang_id;
|
||||
return def->lang_id;
|
||||
spl_lang_type_id_t t = sema_eval_decl(sema, sym.node);
|
||||
n->resolved_lang_tid = t;
|
||||
return t;
|
||||
}
|
||||
case SPL_AST_TYPE_POINTER: {
|
||||
spl_lang_type_id_t p = sema_infer(sema, n->type_pointer.pointee);
|
||||
@@ -1386,7 +1505,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return t;
|
||||
}
|
||||
case SPL_AST_TYPE_AGGREGATE:
|
||||
return sema_build_aggregate(sema, n);
|
||||
return sema_build_aggregate(sema, n, 0);
|
||||
case SPL_AST_TYPE_COMPTIME_CALL: {
|
||||
const char *name = n->type_comptime_call.name;
|
||||
if (name && strcmp(name, "self") == 0) {
|
||||
@@ -1411,62 +1530,78 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
if (n->resolved_def_id == 0)
|
||||
Panic("fn `%s` not collected", n->fn_decl.name);
|
||||
|
||||
spl_lang_type_id_vec_t param_types;
|
||||
vec_init(param_types);
|
||||
spl_def_node_t *def = spl_def_node(sema->type, n->resolved_def_id);
|
||||
if (!def)
|
||||
return 0;
|
||||
|
||||
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 (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;
|
||||
}
|
||||
|
||||
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 && 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);
|
||||
|
||||
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);
|
||||
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_node_t *pdef = spl_def_node(sema->type, psym.node);
|
||||
if (pdef) {
|
||||
pdef->lang_id = p_tid;
|
||||
pdef->state = p_tid ? SPL_DECL_RESOLVED : SPL_DECL_ERROR;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
case SPL_AST_TYPE_DECL: {
|
||||
if (!n->type_decl.type_expr)
|
||||
break;
|
||||
spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr);
|
||||
if (!te)
|
||||
spl_def_node_t *def =
|
||||
n->resolved_def_id ? spl_def_node(sema->type, n->resolved_def_id) : NULL;
|
||||
if (!def)
|
||||
break;
|
||||
if (te->kind == SPL_AST_TYPE_AGGREGATE) {
|
||||
spl_lang_type_id_t agg_lang = sema_build_aggregate(sema, te);
|
||||
spl_def_resolve(sema->type, n->resolved_def_id, agg_lang);
|
||||
n->resolved_lang_tid = agg_lang;
|
||||
} else {
|
||||
spl_lang_type_id_t tid = sema_infer(sema, n->type_decl.type_expr);
|
||||
spl_def_resolve(sema->type, n->resolved_def_id, tid);
|
||||
n->resolved_lang_tid = tid;
|
||||
spl_lang_type_id_t lang = def->lang_id;
|
||||
if (lang == 0)
|
||||
lang = sema_eval_decl(sema, n->resolved_def_id);
|
||||
if (lang == 0)
|
||||
break;
|
||||
|
||||
spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr);
|
||||
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 ---------- */
|
||||
@@ -1580,6 +1715,7 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope
|
||||
sema->scope = scope;
|
||||
sema->error_count = 0;
|
||||
sema->current_fn_ret_tid = 0;
|
||||
sema->current_aggregate_lang = 0;
|
||||
sema->attr = attr;
|
||||
sema->root = (spl_symbol_t){0};
|
||||
sema->store_scope = 0;
|
||||
@@ -1595,8 +1731,6 @@ void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) {
|
||||
return;
|
||||
spl_scope_id_t saved = sema->scope->current_scope;
|
||||
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->scope->current_scope = saved;
|
||||
}
|
||||
@@ -1604,11 +1738,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) {
|
||||
if (!sema->ast || !sema->ast->root)
|
||||
return;
|
||||
|
||||
spl_ast_node_t *root = spl_ast_node(sema->ast, sema->ast->root);
|
||||
if (!root || root->kind != SPL_AST_ROOT)
|
||||
return;
|
||||
|
||||
spl_sema_run_module(sema, root->root.members);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user