- 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>
112 lines
3.1 KiB
Text
112 lines
3.1 KiB
Text
# component_rw.ludic — L11: a component's code names its props, state, fields and functions plainly;
|
|
# each becomes the instance's: `taps += 1` is `self.taps += 1`, `label()` is cmp_x_label(self), a
|
|
# field is its getter called on self. Every function of the component takes `self` first.
|
|
function cm_rewrite(c: int, f: Node, self_ty: pointer) -> void {
|
|
var i = 0
|
|
while i < len(f.kids) {
|
|
let p = f.kids[i]
|
|
if cm_is_keep(c, p.s) or cm_is_field(c, p.s) {
|
|
g_err_file = f.file
|
|
g_err_line = f.line
|
|
g_parsing = false
|
|
perr(`component {g_cm_name[c]}: the parameter {p.s} has the name of its prop, state or field; call it something else`)
|
|
}
|
|
i += 1
|
|
}
|
|
let me = node(N_PARAM)
|
|
me.s = "self"
|
|
me.ty = self_ty
|
|
let kids = new []Node
|
|
push(kids, me)
|
|
i = 0
|
|
while i < len(f.kids) {
|
|
push(kids, f.kids[i])
|
|
i += 1
|
|
}
|
|
f.kids = kids
|
|
cm_rw(c, f.a)
|
|
state_params_onto(f, g_cm_ps[c]) # 0.S: its states, before the instance
|
|
}
|
|
# a member's call to another passes its states on (they are its own parameters), then the instance
|
|
function cm_member_args(c: int, rest: []Node) -> []Node {
|
|
let args = new []Node
|
|
var i = 0
|
|
while i < len(g_cm_ps[c]) {
|
|
let id = node(E_ID)
|
|
id.s = g_cm_ps[c][i].s
|
|
id.pos = -1
|
|
push(args, id)
|
|
i += 1
|
|
}
|
|
push(args, cm_self())
|
|
i = 0
|
|
while i < len(rest) {
|
|
push(args, rest[i])
|
|
i += 1
|
|
}
|
|
return args
|
|
}
|
|
function cm_is_keep(c: int, s: pointer) -> bool {
|
|
var i = 0
|
|
while i < len(g_cm_keep[c]) {
|
|
if (g_cm_keep[c][i] == s) { return true }
|
|
i += 1
|
|
}
|
|
return false
|
|
}
|
|
function cm_is_field(c: int, s: pointer) -> bool {
|
|
var i = 0
|
|
while i < len(g_cm_fnames[c]) {
|
|
if (g_cm_fnames[c][i] == s) { return true }
|
|
i += 1
|
|
}
|
|
return false
|
|
}
|
|
function cm_is_call(c: int, s: pointer) -> bool {
|
|
var i = 0
|
|
while i < len(g_cm_cnames[c]) {
|
|
if (g_cm_cnames[c][i] == s) { return true }
|
|
i += 1
|
|
}
|
|
return false
|
|
}
|
|
function cm_self() -> Node {
|
|
let e = node(E_ID)
|
|
e.s = "self"
|
|
return e
|
|
}
|
|
function cm_rw(c: int, n: Node) -> void {
|
|
if n == null { return }
|
|
if (n.kind == S_LET or n.kind == S_FOR) and n.s != null and (cm_is_keep(c, n.s) or cm_is_field(c, n.s)) {
|
|
g_err_file = n.file
|
|
g_err_line = n.line
|
|
g_parsing = false
|
|
perr(`component {g_cm_name[c]}: {n.s} is its own prop, state or field; name the local something else`)
|
|
}
|
|
if n.kind == E_ID and cm_is_keep(c, n.s) {
|
|
n.kind = E_MEMBER
|
|
n.a = cm_self()
|
|
return
|
|
}
|
|
if n.kind == E_ID and cm_is_field(c, n.s) {
|
|
n.kind = E_CALL
|
|
let callee = node(E_ID)
|
|
callee.s = cm_prefix(g_cm_name[c]) + "get_" + n.s
|
|
n.a = callee
|
|
n.kids = cm_member_args(c, new []Node)
|
|
n.pos = -1 # a call the compiler wrote: nothing in the source to edit
|
|
return
|
|
}
|
|
if n.kind == E_CALL and n.a != null and n.a.kind == E_ID and cm_is_call(c, n.a.s) and not cm_is_keep(c, n.a.s) {
|
|
n.a.s = cm_prefix(g_cm_name[c]) + n.a.s
|
|
n.kids = cm_member_args(c, n.kids)
|
|
}
|
|
cm_rw(c, n.a)
|
|
cm_rw(c, n.b)
|
|
cm_rw(c, n.c)
|
|
var i = 0
|
|
while i < len(n.kids) {
|
|
cm_rw(c, n.kids[i])
|
|
i += 1
|
|
}
|
|
}
|