stage2 提供词法分析器通过与stage1的差异测试 stage1提供数组到切片的隐式转换
This commit is contained in:
1 parent
c30143609a
commit
bb9d0a9f18
13 files changed
+1275
-52
No files matched your search
@@ -1138,6 +1138,46 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
||||
|
||||
usize nelems = vec_size(n->array_literal.elems);
|
||||
|
||||
/* [N]T -> []T:物化数组到局部存储,再构造 {ptr, len} 切片。 */
|
||||
spl_lang_type_node_t *sln = spl_lang_type_node(a->sema->type, node_lang(a, n));
|
||||
if (sln && sln->kind == SPL_LANG_TYPE_SLICE) {
|
||||
spl_type_id_t elem_ir = to_ir_type(a, sln->extra.elem);
|
||||
if (!elem_ir)
|
||||
Panic("array literal slice element has no ir type");
|
||||
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 ptr_ir = spl_type_builder_ptr(&a->sema->type->ir, elem_ir);
|
||||
|
||||
spl_ir_node_ref_t base = 0;
|
||||
if (nelems == 0) {
|
||||
base = spl_ir_builder_type_const_ptr(a->ir, ptr_ir, NULL);
|
||||
} else {
|
||||
spl_type_id_t arr_ir =
|
||||
spl_type_builder_array(&a->sema->type->ir, elem_ir, nelems);
|
||||
spl_ir_node_ref_t slot =
|
||||
spl_ir_builder_mem_alloca(a->ir, arr_ir, const_usize(a, 1));
|
||||
for (usize i = 0; i < nelems; ++i) {
|
||||
spl_ir_node_ref_t fptr =
|
||||
spl_ir_builder_mem_field(a->ir, arr_ir, slot, i);
|
||||
spl_ir_node_ref_t v = emit_expr(a, vec_at(n->array_literal.elems, i));
|
||||
if (!v)
|
||||
Panic("array element emit failed");
|
||||
spl_ir_builder_mem_store(a->ir, elem_ir, fptr, v);
|
||||
}
|
||||
base = spl_ir_builder_mem_field(a->ir, arr_ir, slot, 0);
|
||||
}
|
||||
if (!base)
|
||||
Panic("array literal slice base failed");
|
||||
|
||||
spl_ir_node_ref_t len = spl_ir_builder_type_const_int(a->ir, usize_ir, nelems);
|
||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t);
|
||||
if (!node)
|
||||
Panic("agg_construct failed for array-to-slice");
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, base);
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, len);
|
||||
return node;
|
||||
}
|
||||
|
||||
spl_ir_node_ref_vec_t field_refs;
|
||||
vec_init(field_refs);
|
||||
for (usize i = 0; i < nelems; ++i) {
|
||||
|
||||
@@ -1520,6 +1520,15 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
n->resolved_lang_tid = expected;
|
||||
return expected;
|
||||
}
|
||||
/* [N]T -> []T:数组字面量在需要切片处隐式物化为切片。 */
|
||||
if (en && en->kind == SPL_LANG_TYPE_SLICE) {
|
||||
spl_lang_type_id_t et = en->extra.elem;
|
||||
for (usize i = 0; i < vec_size(n->array_literal.elems); ++i)
|
||||
if (!sema_coerce(sema, vec_at(n->array_literal.elems, i), et))
|
||||
return 0;
|
||||
n->resolved_lang_tid = expected;
|
||||
return expected;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,39 @@ static void dump_tokens(spl_tok_vec_t toks) {
|
||||
vec_free(toks);
|
||||
}
|
||||
|
||||
/* 折叠重复分隔符并去掉 "." 路径分量,使同一模块的 import 解析结果唯一。
|
||||
就地重写,'\' 统一成 '/';保留前导分隔符(绝对路径)。 */
|
||||
static void normalize_import_path(char *p) {
|
||||
usize n = strlen(p);
|
||||
char *out = malloc(n + 1);
|
||||
if (!out)
|
||||
return;
|
||||
char *w = out;
|
||||
if (p[0] == '/' || p[0] == '\\')
|
||||
*w++ = '/';
|
||||
|
||||
char *r = p;
|
||||
while (*r) {
|
||||
while (*r == '/' || *r == '\\')
|
||||
r++;
|
||||
if (!*r)
|
||||
break;
|
||||
char *seg = r;
|
||||
while (*r && *r != '/' && *r != '\\')
|
||||
r++;
|
||||
usize len = (usize)(r - seg);
|
||||
if (len == 1 && seg[0] == '.')
|
||||
continue;
|
||||
if (w != out && w[-1] != '/')
|
||||
*w++ = '/';
|
||||
memcpy(w, seg, len);
|
||||
w += len;
|
||||
}
|
||||
*w = 0;
|
||||
strcpy(p, out);
|
||||
free(out);
|
||||
}
|
||||
|
||||
/* 把 import_path 拼接到 importing_file 所在目录。
|
||||
from_fname 为空时按相对 cwd 处理。绝对路径直接透传。 */
|
||||
static void resolve_relative(const char *from, const char *path, char *out, usize cap) {
|
||||
@@ -91,6 +124,7 @@ static void resolve_relative(const char *from, const char *path, char *out, usiz
|
||||
}
|
||||
if (path[0] == '/' || path[0] == '\\' || (path[0] && path[1] == ':')) {
|
||||
snprintf(out, cap, "%s", path);
|
||||
normalize_import_path(out);
|
||||
return;
|
||||
}
|
||||
const char *last_sep = NULL;
|
||||
@@ -99,10 +133,12 @@ static void resolve_relative(const char *from, const char *path, char *out, usiz
|
||||
last_sep = p;
|
||||
if (!last_sep) {
|
||||
snprintf(out, cap, "%s", path);
|
||||
normalize_import_path(out);
|
||||
return;
|
||||
}
|
||||
usize dir_len = (usize)(last_sep - from) + 1;
|
||||
snprintf(out, cap, "%.*s%s", (int)dir_len, from, path);
|
||||
normalize_import_path(out);
|
||||
}
|
||||
|
||||
static spl_ast_t *driver_load(void *user, const char *from_fname, const char *path,
|
||||
|
||||
Reference in new issue
Block a user