feat(cli): 0.R5 - ludic deps says what a function can come to change (widest_write_reach, --wreach N); a port member and a registry field reach only themselves

A reach through Port.member() follows that member's binding (or its default), and Registry[i].field -
or a local holding Registry[i] - follows that field in each entry, so a question asked of a port or a
table that also holds verbs no longer reaches the verbs. In Maroon Lake that took the valley's
'what is this Thing called' from 47 states it could change to 1. examples/state/write_reach.ludic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-26 23:19:54 +03:00
parent c64f8750e2
commit 5df0747642
7 changed files with 46858 additions and 43583 deletions

View file

@ -0,0 +1,35 @@
# ludic deps --wreach: what a function can come to CHANGE. A port asked one member reaches that
# member's binding only, and a registry read for one field reaches that field only - so a
# question stays a question even when the port or the table beside it also holds a verb.
program WriteReach {
state Store { n: int = 0 }
state Log { lines: int = 0 }
function store_count(s: Store) -> int { return s.n }
function store_add(s: mut Store) -> void { s.n += 1 }
port Shelf {
count: fn() -> int
add: fn() -> void
}
bind Shelf { count: fn store_count, add: fn store_add }
function log_note(l: mut Log) -> void { l.lines += 1 }
property Kind {
key: string = ""
size: int = 0
note: fn() -> void = null
}
registry Kinds of Kind as KD
def Kinds box { size: 3, note: fn log_note }
function asks() -> int { return Shelf.count() + Kinds[KD_BOX].size }
function asks_local() -> int {
let k = Kinds[KD_BOX]
return k.size
}
function changes() -> void {
Shelf.add()
Kinds[KD_BOX].note()
}
entry {
changes()
print(`{asks()} {asks_local()}`)
}
}