stage2 提供词法分析器通过与stage1的差异测试 stage1提供数组到切片的隐式转换
This commit is contained in:
1 parent
c30143609a
commit
bb9d0a9f18
13 files changed
+1275
-52
No files matched your search
@@ -133,12 +133,33 @@ static bool collect_headers(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// stage2 的所有 .spl:作为 splc1.sir 的依赖(不解析 @import,保守全量重建)。
|
||||
static Nob_Files g_spl2 = {0};
|
||||
|
||||
static bool collect_spl2_entry(Nob_Walk_Entry entry) {
|
||||
if (entry.type != NOB_FILE_REGULAR)
|
||||
return true;
|
||||
const char *dot = strrchr(entry.path, '.');
|
||||
if (!dot || strcmp(dot, ".spl") != 0)
|
||||
return true;
|
||||
da_append(&g_spl2, nob_temp_strdup(entry.path));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool collect_spl2(void) {
|
||||
if (g_spl2.count > 0)
|
||||
return true;
|
||||
return nob_walk_dir("stage2", collect_spl2_entry);
|
||||
}
|
||||
|
||||
static bool prepare_build(void) {
|
||||
if (!nob_mkdir_if_not_exists(BUILD_FOLDER))
|
||||
return false;
|
||||
if (!sync_cflags_stamp())
|
||||
return false;
|
||||
return collect_headers();
|
||||
if (!collect_headers())
|
||||
return false;
|
||||
return collect_spl2();
|
||||
}
|
||||
|
||||
static bool build_object(const char *src) {
|
||||
@@ -320,6 +341,105 @@ static bool test_once_with_dump(const char *fname, void *user_data) {
|
||||
return nob_cmd_run(&cmd);
|
||||
}
|
||||
|
||||
// 用 splc0 编译 stage2/splc1.spl -> build/splc1.sir(依赖 stage2 全部 .spl)。
|
||||
static bool build_splc1(void) {
|
||||
if (!build_target("splc0"))
|
||||
return false;
|
||||
|
||||
const char *src = "stage2/splc1.spl";
|
||||
const char *sir = BUILD_FOLDER "splc1.sir";
|
||||
|
||||
size_t ninputs = g_spl2.count + 2;
|
||||
const char **inputs = (const char **)nob_temp_alloc(sizeof(const char *) * ninputs);
|
||||
inputs[0] = src;
|
||||
for (size_t i = 0; i < g_spl2.count; ++i)
|
||||
inputs[i + 1] = g_spl2.items[i];
|
||||
inputs[ninputs - 1] = CFLAGS_STAMP;
|
||||
|
||||
int needs = nob_needs_rebuild(sir, inputs, ninputs);
|
||||
if (needs < 0)
|
||||
return false;
|
||||
if (needs == 0)
|
||||
return true;
|
||||
|
||||
Nob_Cmd cmd = {0};
|
||||
nob_cmd_append(&cmd, exe_path("splc0"), src, sir);
|
||||
return nob_cmd_run(&cmd);
|
||||
}
|
||||
|
||||
static bool run_capture(Nob_Cmd *cmd, Nob_Cmd_Result *result) {
|
||||
Nob_String_Builder rendered = {0};
|
||||
nob_cmd_render(*cmd, &rendered);
|
||||
Nob_String_View sv = nob_sb_to_sv(rendered);
|
||||
bool ok = nob_cmd_capture_popen(nob_temp_sv_to_cstr(sv), result);
|
||||
nob_sb_free(rendered);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// diff 测试:对同一文件跑 `splc0 --dump <mode>` 与 `spl_cli splc1.sir --dump <mode>`,
|
||||
// 逐字节比较 stdout。
|
||||
static bool test_once_diff(const char *fname, void *user_data) {
|
||||
const char *mode = (const char *)user_data;
|
||||
if (!mode) {
|
||||
nob_log(NOB_ERROR, "diff test requires a mode: lex|ast|sema|ir|vm");
|
||||
return false;
|
||||
}
|
||||
if (!build_target("splc0"))
|
||||
return false;
|
||||
if (!build_target("spl_cli"))
|
||||
return false;
|
||||
if (!build_splc1())
|
||||
return false;
|
||||
|
||||
Nob_Cmd c_cmd = {0};
|
||||
nob_cmd_append(&c_cmd, exe_path("splc0"), "--dump", (char *)mode, (char *)fname,
|
||||
BUILD_FOLDER "diff_c.sir");
|
||||
Nob_Cmd_Result c_res = {0};
|
||||
if (!run_capture(&c_cmd, &c_res)) {
|
||||
nob_cmd_result_free(c_res);
|
||||
return false;
|
||||
}
|
||||
|
||||
Nob_Cmd s_cmd = {0};
|
||||
nob_cmd_append(&s_cmd, exe_path("spl_cli"), BUILD_FOLDER "splc1.sir", "--dump",
|
||||
(char *)mode, (char *)fname);
|
||||
Nob_Cmd_Result s_res = {0};
|
||||
if (!run_capture(&s_cmd, &s_res)) {
|
||||
nob_cmd_result_free(c_res);
|
||||
nob_cmd_result_free(s_res);
|
||||
return false;
|
||||
}
|
||||
|
||||
Nob_String_View c_out = nob_sb_to_sv(c_res.out);
|
||||
Nob_String_View s_out = nob_sb_to_sv(s_res.out);
|
||||
bool same = nob_sv_eq(c_out, s_out);
|
||||
if (!same) {
|
||||
nob_log(NOB_ERROR, "diff mismatch: %s (c=%zu bytes, spl=%zu bytes)", fname,
|
||||
c_out.count, s_out.count);
|
||||
// 打印首个不相同行(按行比较)。
|
||||
Nob_String_View ca = c_out;
|
||||
Nob_String_View sa = s_out;
|
||||
size_t lineno = 1;
|
||||
while (ca.count > 0 || sa.count > 0) {
|
||||
Nob_String_View cl = nob_sv_chop_by_delim(&ca, '\n');
|
||||
Nob_String_View sl = nob_sv_chop_by_delim(&sa, '\n');
|
||||
if (!nob_sv_eq(cl, sl)) {
|
||||
nob_log(NOB_ERROR, " line %zu:", lineno);
|
||||
nob_log(NOB_ERROR, " c : %.*s", (int)cl.count, cl.data);
|
||||
nob_log(NOB_ERROR, " spl: %.*s", (int)sl.count, sl.data);
|
||||
break;
|
||||
}
|
||||
lineno++;
|
||||
}
|
||||
nob_log(NOB_ERROR, "--- c stderr/stdout merged above; exit=%d vs spl exit=%d ---",
|
||||
c_res.exit_code, s_res.exit_code);
|
||||
}
|
||||
|
||||
nob_cmd_result_free(c_res);
|
||||
nob_cmd_result_free(s_res);
|
||||
return same;
|
||||
}
|
||||
|
||||
static bool is_stage_name(const char *s) {
|
||||
return strcmp(s, "stage1") == 0 || strcmp(s, "stage2") == 0 || strcmp(s, "diff") == 0;
|
||||
}
|
||||
@@ -481,6 +601,15 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
// diff 需要显式 mode,且使用专门的双编译器比较函数。
|
||||
if (strcmp(stage, "diff") == 0) {
|
||||
if (!mode_name) {
|
||||
nob_log(NOB_ERROR, "diff requires a mode: lex|ast|sema|ir|vm");
|
||||
return 1;
|
||||
}
|
||||
tfn = test_once_diff;
|
||||
}
|
||||
|
||||
// 3. 剩下的都当 pattern
|
||||
Nob_Files files = {0};
|
||||
while (argc > 0) {
|
||||
|
||||
Reference in new issue
Block a user