feat(lang): 0.S - components take states in their header; migrate writes them, never inside a name, never outside the programs given, never into a package's state
- component Name (a: mut A, b: B) { ... }: every getter, default, function and event takes the
header's states before the instance; a member's call to another passes them on; the glue is
supplied them; the template never sees them; a read-only one is read-only in every member
- ludic migrate state: a component's members' needs go into its header (added to an existing one,
mut added where now changed); a field read or a member call inside a component is the compiler's,
so nothing is written inside a name and no ', )' is left; an entry point that declares states
already gets the rest after them
- a program's module named like a package gets <Name>AppState; a program's own file its own state;
a friend module's files go by directory; a package's settable var stays state
- it writes only under the programs and directories given (and runtime/ with --runtime), and
refuses the whole run naming any other file that would have to change
- a name a package already moved into its state is rewritten through it; a read of the runtime's
var through the runtime function that answers it (gl_w: gl_width())
- a state's instance supplied by the runtime is not a uses reference
- tests: state/component, rejected/state_component_ro, rendering/ui_render3d, migrate component
and foreign cases
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
c167ecc714
commit
ce80e64b24
23 changed files with 67967 additions and 61444 deletions
|
|
@ -11,6 +11,11 @@
|
|||
# on buy() { taps += 1 } # props and state are plain names here
|
||||
# }
|
||||
#
|
||||
# 0.S: `component PauseMenu (clock: ClockState, s: mut Session) { ... }` - the states its members
|
||||
# read and change. Every getter, default, function and event takes them before the instance, the
|
||||
# glue's calls are supplied them by the runtime, a member's call to another passes them on, and
|
||||
# the template never sees them.
|
||||
#
|
||||
# Each mounted instance is a record of its props and state. The compiler reads the template and the
|
||||
# styles into the program, so a missing template fails the build and nothing more has to ship, and
|
||||
# registers the component with ludic.ui when the program starts.
|
||||
|
|
@ -27,6 +32,8 @@ var g_cm_fnames: [][]pointer = new [][]pointer
|
|||
var g_cm_calls: [][]Node = new [][]Node
|
||||
var g_cm_cnames: [][]pointer = new [][]pointer
|
||||
var g_cm_head: []Node = new []Node
|
||||
var g_cm_hdr: []int = new []int # 0.S: where state parameters go (after the name)
|
||||
var g_cm_ps: [][]Node = new [][]Node # the states it declares
|
||||
|
||||
function cm_prefix(name: pointer) -> pointer { return `cmp_{reg_lower(name)}_` }
|
||||
|
||||
|
|
@ -34,6 +41,8 @@ function cm_prefix(name: pointer) -> pointer { return `cmp_{reg_lower(name)}_` }
|
|||
function parse_ui_component() -> void {
|
||||
pi += 1
|
||||
let name = eat_id()
|
||||
push(g_cm_hdr, toks[pi - 1].end)
|
||||
push(g_cm_ps, parse_entry_params())
|
||||
cm_unique(name)
|
||||
let px = cm_prefix(name)
|
||||
g_uses_value = true
|
||||
|
|
@ -79,6 +88,7 @@ function cm_member(c: int, px: pointer) -> void {
|
|||
pi += 1
|
||||
def = cm_getter(px + "def_" + fname, ty, expr())
|
||||
}
|
||||
if def != null { def.cm = c }
|
||||
push(g_cm_defs[c], def)
|
||||
return
|
||||
}
|
||||
|
|
@ -86,6 +96,7 @@ function cm_member(c: int, px: pointer) -> void {
|
|||
let ev = is_id("on")
|
||||
if ev { toks[pi].text = "function" }
|
||||
let f = parse_fn()
|
||||
f.cm = c
|
||||
push(g_cm_cnames[c], f.s)
|
||||
if ev { f.s = px + "on_" + f.s } else { f.s = px + f.s }
|
||||
push(g_cm_calls[c], f)
|
||||
|
|
@ -101,7 +112,9 @@ function cm_member(c: int, px: pointer) -> void {
|
|||
if not is_op("=") { perr(`component field {fname}: say what it is - {fname} = some_global`) }
|
||||
pi += 1
|
||||
push(g_cm_fnames[c], fname)
|
||||
push(g_cm_fields[c], cm_getter(px + "get_" + fname, ty, expr()))
|
||||
let g = cm_getter(px + "get_" + fname, ty, expr())
|
||||
g.cm = c
|
||||
push(g_cm_fields[c], g)
|
||||
}
|
||||
# a function of the instance that answers one expression (a field, or a default)
|
||||
function cm_getter(name: pointer, ty: pointer, e: Node) -> Node {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue