Merge lang/foundations b513f7b into lang/ecs

This commit is contained in:
Orkun ÇAKILKAYA 2026-09-28 20:06:25 +03:00
commit 00408604da
7 changed files with 58578 additions and 57763 deletions

View file

@ -27,6 +27,7 @@ export function photo_frame_subject(photo_st: mut PhotoState, sp: int, name: str
}
# anything else in the picture worth naming: a landmark, the water, a sign
@alloc_ok("a shot's tags: once per photograph taken")
export function photo_frame_tag(photo_st: mut PhotoState, text: string) -> void {
if len(text) == 0 { return }
if len(photo_st.pht_pending_tags) > 0 { photo_st.pht_pending_tags = photo_st.pht_pending_tags + ", " }

View file

@ -12,7 +12,7 @@ export function photo_sort_set(photo_st: mut PhotoState, s: int) -> void { photo
# the roll in the chosen order: newest first, best first, or by subject
export function photo_order(photo_st: mut PhotoState) -> []int {
photo_st.pht_order = new []int
List.clear(photo_st.pht_order)
for i in 0 .. photo_st.pht_n { push(photo_st.pht_order, i) }
if photo_st.pht_sort == PHOTO_NEWEST {
for i in 0 .. photo_st.pht_n { photo_st.pht_order[i] = photo_st.pht_n - 1 - i }
@ -39,13 +39,14 @@ export function photo_page_step(photo_st: mut PhotoState, d: int) -> void { phot
# a page of the roll, in its order; the page is held inside the roll
export function photo_page_list(photo_st: mut PhotoState) -> []int {
let out = new []int
let out = photo_st.pht_page_out
List.clear(out)
if photo_st.pht_n == 0 { return out }
let order = photo_order(photo_st)
if photo_st.pht_page >= photo_pages(photo_st) { photo_st.pht_page = photo_pages(photo_st) - 1 }
for k in 0 .. PHOTO_PAGE {
let oi = photo_st.pht_page * PHOTO_PAGE + k
if oi < photo_st.pht_n { push(out, order[oi]) }
if oi < photo_st.pht_n { push(photo_st.pht_page_out, order[oi]) }
}
return out
}

View file

@ -29,7 +29,8 @@ export property PhotoFact {
export state PhotoState {
pht_sort: int = 0
pht_page: int = 0
pht_order: []int = null
@max(256) pht_order: []int = new []int # the roll's order, refilled in place (a page asks it every frame)
@max(8) pht_page_out: []int = new []int # a page of it, the same
pht_max: int = 40
pht_n: int = 0
pht_day: []int = null
@ -39,8 +40,8 @@ export state PhotoState {
pht_sold: []int = null
pht_grade: []int = null
pht_why: []int = null
pht_tags: []string = null
pht_file: []string = null
@max(256) pht_tags: []string = null
@max(256) pht_file: []string = null
pht_best: []int = null # the best grade yet, per subject
pht_species_shot: int = 0 # every subject ever photographed, sold or deleted
pht_legend_shot: int = 0
@ -63,6 +64,7 @@ export function photo_facts(photo_st: PhotoState) -> Queue<PhotoFact> {
return photo_st.pht_fact_q
}
@alloc_ok("a photograph's fact: one per shot kept, sold or deleted")
function pht_fact(photo_st: PhotoState, what: int, i: int) -> PhotoFact {
var f = q_rec(photo_facts(photo_st))
if f == null {
@ -98,6 +100,7 @@ function pht_floats(n: int) -> []float {
}
# an empty roll of `max` frames
@alloc_ok("a new roll: once a trip, and when the roll is emptied")
function pht_blank(photo_st: mut PhotoState) -> void {
photo_st.pht_n = 0
photo_st.pht_day = pht_ints(photo_st.pht_max)

View file

@ -304,6 +304,14 @@ function dr_walk(n: Node, refs: []int) -> void {
return
}
if dr_reg_field(n, refs) { return }
if n.kind == E_NEW and n.b != null and n.s != null { # 25.2: a dispatch reaches its action's reducers
let pre = `ludic_reduce__{n.s}__`
var ri = 0
while ri < len(g_dr_name) {
if str_starts(g_dr_name[ri], pre) { push(refs, ri) }
ri += 1
}
}
if n.kind == S_EMIT and n.s != null { # 25.2: an emit reaches its event's listeners
var li = 0
while li < len(g_onlisten) {

View file

@ -27,6 +27,27 @@ function fr_has_aok(n: Node) -> bool {
var g_fr_root: []bool = new []bool
var g_fr_from: []int = new []int # the node a reached one was first reached from
function fr_capped(t: Node) -> bool {
if t == null or t.kind != E_MEMBER or t.s == null { return false }
let tail = `.{t.s}`
var i = 0
while i < len(g_cap_keys) {
let k = g_cap_keys[i]
if len(k) > len(tail) and (k[len(k) - len(tail) .. len(k)] == tail) { return true }
i += 1
}
return false
}
function fr_is_event_handler(name: pointer) -> bool {
var i = 0
while i + 4 <= len(name) {
if name[i] == '_' and name[i + 1] == 'o' and name[i + 2] == 'n' and name[i + 3] == '_' { return true }
i += 1
}
return false
}
function fr_phase_frame(ph: pointer) -> bool {
return (ph == "Input") or (ph == "FixedUpdate") or (ph == "Update") or (ph == "LateUpdate") or (ph == "Render") or (ph == "Overlay")
}
@ -96,7 +117,11 @@ function fr_alloc_kind(n: Node, text_above: bool) -> pointer {
if n.kind == E_BIN and (n.s == "+") and not text_above and fr_is_textish(n) { return "text" }
if n.kind == E_CALL and n.a != null and n.a.kind == E_ID and n.a.s != null {
let c = n.a.s
if (c == "push") { return "grow" }
if (c == "push") {
# a push into a field declared @max(n) grows to n at most, and the fence fails the run past it
if len(n.kids) > 0 and fr_capped(n.kids[0]) { return null }
return "grow"
}
if (c == "words") or (c == "floats") or (c == "doubles") or (c == "buffer") or (c == "bytes") or (c == "fixeds") or (c == "pointers") { return `{c}()` }
}
return null
@ -150,8 +175,9 @@ function deps_frame(f: pointer) -> void {
while i < len(prog) {
let d = prog[i]
if d.kind == N_SYS and d.s != null and fr_phase_frame(d.ty) { fr_mark_root(d.s) }
if d.kind == N_FN and d.s != null and str_starts(d.s, "ludic_reduce__") { fr_mark_root(d.s) }
if d.kind == N_FN and d.s != null and d.cm >= 0 { fr_mark_root(d.s) } # a component's own: it runs while its page is open
# a component's own functions run while its page is open - but not its event handlers (`on click`),
# which run when the player does something; a reducer is reached from its action's dispatch
if d.kind == N_FN and d.s != null and d.cm >= 0 and not fr_is_event_handler(d.s) { fr_mark_root(d.s) }
fr_find_roots(d)
i += 1
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff