chunked tables: a key is unique across its map and the slot's own, not interned - a slot keeps row i's key in its own buffer i, rewritten when the slot is refilled (interning ~92k map-unique keys as a player walks would fill the bounded intern table and keep them all); ludicc --check refuses a key written in two of a map's chunk files, naming both; reseeded
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0634116d59
commit
49e32f9b47
11 changed files with 75842 additions and 74646 deletions
|
|
@ -208,6 +208,7 @@ function pmk_map(md: pointer) -> void {
|
|||
r += 1
|
||||
}
|
||||
pmk_dups()
|
||||
pmk_chunk_dups()
|
||||
var e = 0
|
||||
while e < len(g_pmk_rec) {
|
||||
let rr = g_pmk_reg[e]
|
||||
|
|
@ -237,6 +238,30 @@ function pmk_dups() -> void {
|
|||
i += 1
|
||||
}
|
||||
}
|
||||
# a chunked table's key is unique across its map (a row's id is (map, key), and a tree moved into
|
||||
# another chunk keeps it): a key in two of a map's chunk files is refused, naming both
|
||||
function pmk_chunk_dups() -> void {
|
||||
let xs = new []int
|
||||
let keys = new []pointer
|
||||
var i = 0
|
||||
while i < len(g_pmk_key) {
|
||||
if g_rg_chunk[g_pmk_reg[i]] > 0 {
|
||||
push(xs, i)
|
||||
push(keys, `{g_rg_name[g_pmk_reg[i]]}\n{g_pmk_key[i]}`)
|
||||
} else { push(keys, "") }
|
||||
i += 1
|
||||
}
|
||||
sc_sort(xs, keys)
|
||||
i = 1
|
||||
while i < len(xs) {
|
||||
let a = xs[i - 1]
|
||||
let k = xs[i]
|
||||
if (keys[k] == keys[a]) and not (g_pmk_file[k] == g_pmk_file[a]) {
|
||||
pmk_err(g_pmk_file[k], g_pmk_kline[k], g_pmk_kcol[k], `the key {g_pmk_key[k]} is also written at {g_pmk_file[a]}:{itoa(g_pmk_kline[a])} - a chunked table's key is unique across its map`)
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
# every cross-row @Ref met names a row of its table in this map
|
||||
function pmk_refs() -> void {
|
||||
let xs = new []int
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ function pm_gen_chunk_types(b: Buf, R: pointer, T: pointer) -> void {
|
|||
pm_l(b, ` rows: []{T} = new []{T}`)
|
||||
pm_l(b, ` pl__: {R}__Pool = new {R}__Pool`)
|
||||
pm_l(b, ` hs__: LresHash = new LresHash`)
|
||||
pm_l(b, ` ks__: LresKeys = new LresKeys`)
|
||||
pm_l(b, "}")
|
||||
pm_l(b, `state {R} {{`)
|
||||
pm_l(b, ` chunks: []{R}Chunk = new []{R}Chunk`)
|
||||
|
|
@ -331,7 +332,7 @@ function pm_gen_rows(b: Buf, sn: pointer, R: pointer, T: pointer) -> void {
|
|||
pm_l(b, " return r")
|
||||
pm_l(b, "}")
|
||||
pm_l(b, `@alloc_ok("the rows list grows only past the most rows this table has held (high water)")`)
|
||||
pm_l(b, `function {sn}__fill_rows(t: LresTree, pl: {R}__Pool, rows: []{T}, hs: LresHash) -> bool {{`)
|
||||
pm_l(b, `function {sn}__fill_rows(t: LresTree, pl: {R}__Pool, rows: []{T}, hs: LresHash, ks: LresKeys) -> bool {{`)
|
||||
pm_l(b, " List.clear(rows)")
|
||||
pm_l(b, ` {sn}__rewind(pl)`)
|
||||
pm_l(b, " lres_hash_reset(hs, lres_entries(t))")
|
||||
|
|
@ -341,7 +342,7 @@ function pm_gen_rows(b: Buf, sn: pointer, R: pointer, T: pointer) -> void {
|
|||
pm_l(b, ` let r = {sn}__row(pl, i)`)
|
||||
pm_l(b, ` {sn}__reset_{T}(pl, r)`)
|
||||
pm_l(b, ` {sn}__fill_{T}(t, pl, r, e)`)
|
||||
pm_l(b, " r.key = lres_name(t, e)")
|
||||
pm_l(b, " r.key = lres_key_of(t, e, ks, i)")
|
||||
pm_l(b, " if lres_hash_put(hs, r.key, i) >= 0 { lres_dup(t, e) }")
|
||||
pm_l(b, " push(rows, r)")
|
||||
pm_l(b, " i += 1")
|
||||
|
|
@ -381,10 +382,11 @@ function pm_gen_whole_verbs(b: Buf, r: int, sn: pointer, R: pointer) -> void {
|
|||
pm_l(b, `@alloc_ok("a load grows the table's rows and lists only past its high water; an error's message only when a file is wrong")`)
|
||||
pm_l(b, `function {sn}_load(st: mut {R}, map: string) -> bool {{`)
|
||||
pm_l(b, " let t = st.lt__")
|
||||
pm_l(b, " t.local = false")
|
||||
pm_gen_path(b, r)
|
||||
pm_l(b, " let got = lres_read(t)")
|
||||
pm_l(b, " if got == 0 { lres_missing(t) }")
|
||||
pm_l(b, ` if got <= 0 or not {sn}__fill_rows(t, st.pl__, st.rows, st.hs__) {{`)
|
||||
pm_l(b, ` if got <= 0 or not {sn}__fill_rows(t, st.pl__, st.rows, st.hs__, null) {{`)
|
||||
pm_l(b, ` {sn}__drop(st.pl__, st.rows, st.hs__)`)
|
||||
pm_l(b, " st.err = lres_error(t)")
|
||||
pm_l(b, " st.map = \"\"")
|
||||
|
|
@ -444,6 +446,7 @@ function pm_gen_chunk_verbs(b: Buf, r: int, sn: pointer, R: pointer) -> void {
|
|||
pm_l(b, " ch.cx = cx")
|
||||
pm_l(b, " ch.cz = cz")
|
||||
pm_l(b, " let t = st.lt__")
|
||||
pm_l(b, " t.local = true # the keys are the slot's own, never interned")
|
||||
pm_gen_path(b, r)
|
||||
pm_l(b, " let got = lres_read(t)")
|
||||
pm_l(b, " if got == 0 {")
|
||||
|
|
@ -451,7 +454,7 @@ function pm_gen_chunk_verbs(b: Buf, r: int, sn: pointer, R: pointer) -> void {
|
|||
pm_l(b, " st.err = \"\"")
|
||||
pm_l(b, " return s")
|
||||
pm_l(b, " }")
|
||||
pm_l(b, ` if got < 0 or not {sn}__fill_rows(t, ch.pl__, ch.rows, ch.hs__) {{`)
|
||||
pm_l(b, ` if got < 0 or not {sn}__fill_rows(t, ch.pl__, ch.rows, ch.hs__, ch.ks__) {{`)
|
||||
pm_l(b, ` {sn}__off(ch)`)
|
||||
pm_l(b, " st.err = lres_error(t)")
|
||||
pm_l(b, " return -1")
|
||||
|
|
|
|||
73334
selfhost/ludicc.seed.ll
73334
selfhost/ludicc.seed.ll
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue