feat(test): ludic test <dir>, each test block in a process of its own

A directory stands for its *_test.ludic files and the files straight
inside any tests/ under it. The runner answers --list and runs one test
by name, and ludic test runs every block in a child process, so tests
no longer share globals. A failed expect names the file it is written
in (the path the compiler was given) and its line. Reseed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-25 04:39:55 +03:00
parent 8075892e0e
commit 9faaa2094d
8 changed files with 19724 additions and 19278 deletions

View file

@ -23,6 +23,12 @@ function emit_expect_fail(cond1: pointer, msgsym: pointer, got: pointer, want: p
emit(`{lok}:\n`)
}
# an assertion names the file it is written in, as the compiler was given it, and its line
function expect_where(e: Node) -> pointer {
if e.file != null { return `{e.file}:{itoa(e.line)}` }
return `{g_src_name}:{itoa(e.line)}`
}
# lowercase an ASCII identifier (for #62 package-namespace aliasing: Foo -> foo)
function ns_lower(s: pointer) -> pointer {
let n = cstr_len(s)
@ -673,7 +679,7 @@ function emit_call(e: Node) -> Val {
g_uses_expect = true
let a = emit_expr(e.kids[0])
let c = emit_bind(`icmp ne i32 {a.code}, 0`)
let msg = emit_str_const(`{g_src_name}:{itoa(e.line)}: expect failed`)
let msg = emit_str_const(`{expect_where(e)}: expect failed`)
emit_expect_fail(c, msg, "", "")
return val("0", "void")
}
@ -681,7 +687,7 @@ function emit_call(e: Node) -> Val {
g_uses_expect = true
let a = emit_expr(e.kids[0]); let b = emit_expr(e.kids[1])
let c = emit_bind(`icmp eq i32 {a.code}, {b.code}`)
let msg = emit_str_const(`{g_src_name}:{itoa(e.line)}: expect_eq failed`)
let msg = emit_str_const(`{expect_where(e)}: expect_eq failed`)
emit_expect_fail(c, msg, a.code, b.code)
return val("0", "void")
}
@ -693,7 +699,7 @@ function emit_call(e: Node) -> Val {
let isneg = emit_bind(`icmp slt i32 {d}, 0`)
let ad = emit_bind(`select i1 {isneg}, i32 {neg}, i32 {d}`)
let c = emit_bind(`icmp sle i32 {ad}, {tol.code}`)
let msg = emit_str_const(`{g_src_name}:{itoa(e.line)}: expect_near failed`)
let msg = emit_str_const(`{expect_where(e)}: expect_near failed`)
emit_expect_fail(c, msg, a.code, b.code)
return val("0", "void")
}