Phase 2: enforce statement separators (Rule B)
The parser now requires a newline or ';' between statements (block() in selfhost/parse.ludic); two statements may no longer sit adjacent with only spaces. Also fixed if-without-else swallowing its trailing separator. Migration: tools/ludic-tools/migrate_separators.c inserts ';' at statement boundaries corpus-wide (examples, runtime, 25 self-host fragments, ~1100 boundaries). Verified semantically identical — the migrated compiler compiles itself to IR byte-identical to the pre-migration seed, and every golden game renders identically. Reseeded to the strict compiler; C-free fixpoint holds; test.sh 14/14. Docs: Rule B documented in LANGUAGE.md; BOOTSTRAP.md R1 + stale fences updated; check-docs green across all docs. Fixed a multi-line string literal in emit_expr.ludic (byte-identical \n escape) that the C toolchain lexer mis-lexes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
985f9ad8f2
commit
eac8f8f335
35 changed files with 3861 additions and 3588 deletions
|
|
@ -1,15 +1,15 @@
|
|||
# emit_head.ludic — string constants and the module header (libc declarations,
|
||||
# the slice header type, struct layouts, globals, argv, format strings).
|
||||
|
||||
fn hexdig(n: int) -> int { if n < 10 { return 48 + n } return 55 + n } # 0-9 A-F
|
||||
fn hexdig(n: int) -> int { if n < 10 { return 48 + n }; return 55 + n } # 0-9 A-F
|
||||
|
||||
# emit `@.strN = ... c"escaped\00"` and return its name; % and non-print -> \XX
|
||||
fn emit_str_const(s: ptr) -> ptr {
|
||||
let name = sconcat("@.str", itoa(ll_str))
|
||||
ll_str = ll_str + 1
|
||||
let n = slen(s)
|
||||
emith(name) emith(" = private unnamed_addr constant [")
|
||||
emith(itoa(n + 1)) emith(" x i8] c\"")
|
||||
emith(name); emith(" = private unnamed_addr constant [")
|
||||
emith(itoa(n + 1)); emith(" x i8] c\"")
|
||||
let i = 0
|
||||
while i < n {
|
||||
let c = peek8(s, i)
|
||||
|
|
@ -27,14 +27,14 @@ fn emit_str_const(s: ptr) -> ptr {
|
|||
# a fresh SSA register bound to a `getelementptr`, returned as its name
|
||||
fn emit_gep_i8(base: ptr, idx: ptr) -> ptr {
|
||||
let r = nreg()
|
||||
emit(" ") emit(r) emit(" = getelementptr inbounds i8, ptr ")
|
||||
emit(base) emit(", i32 ") emit(idx) emit("\n")
|
||||
emit(" "); emit(r); emit(" = getelementptr inbounds i8, ptr ")
|
||||
emit(base); emit(", i32 "); emit(idx); emit("\n")
|
||||
return r
|
||||
}
|
||||
|
||||
# the constant initializer for a global var: a literal, or 0/null
|
||||
fn global_init(d: Node) -> ptr {
|
||||
if ptr_is_null(d.a) { if streq(llty(d.ty), "ptr") { return "null" } return "0" }
|
||||
if ptr_is_null(d.a) { if streq(llty(d.ty), "ptr") { return "null" }; return "0" }
|
||||
let e = d.a
|
||||
if e.kind == E_INT or e.kind == E_FLOAT or e.kind == E_BOOL { return itoa(e.ival) }
|
||||
if e.kind == E_UN and streq(e.s, "-") and e.a.kind == E_INT { return sconcat("-", itoa(e.a.ival)) }
|
||||
|
|
@ -74,14 +74,14 @@ fn emit_header() -> void {
|
|||
emith("@L_argc = internal global i32 0\n")
|
||||
emith("@L_argv = internal global ptr null\n")
|
||||
emith("@.gametitle = private unnamed_addr constant [")
|
||||
emith(itoa(slen(g_game_name) + 1)) emith(" x i8] c\"") emith(g_game_name) emith("\\00\"\n")
|
||||
emith(itoa(slen(g_game_name) + 1)); emith(" x i8] c\""); emith(g_game_name); emith("\\00\"\n")
|
||||
emith("%LSlice = type { ptr, i32, i32 }\n")
|
||||
# struct layouts
|
||||
let i = 0
|
||||
while i < len(prog) {
|
||||
let d = prog[i]
|
||||
if d.kind == N_STRUCT {
|
||||
emith("%Str_") emith(d.s) emith(" = type { ")
|
||||
emith("%Str_"); emith(d.s); emith(" = type { ")
|
||||
if len(d.kids) == 0 { emith("i32") }
|
||||
let f = 0
|
||||
while f < len(d.kids) {
|
||||
|
|
@ -98,8 +98,8 @@ fn emit_header() -> void {
|
|||
while i < len(prog) {
|
||||
let d = prog[i]
|
||||
if d.kind == N_VAR {
|
||||
emith("@g_") emith(d.s) emith(" = internal global ")
|
||||
emith(llty(d.ty)) emith(" ")
|
||||
emith("@g_"); emith(d.s); emith(" = internal global ")
|
||||
emith(llty(d.ty)); emith(" ")
|
||||
emith(global_init(d))
|
||||
emith("\n")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue