feat(lang): bind a port member that takes nothing to a variable
bind Purse { money: g_money } writes the getter bind_Purse_money in the
bind's own file, so a one-line wrapper per member is not needed; a
member that takes something is refused a variable. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
7b8c134c21
commit
7ef6c7ec75
8 changed files with 45376 additions and 44711 deletions
|
|
@ -2,7 +2,7 @@
|
|||
# program together, so the module never names (or `uses`) the code that answers it.
|
||||
#
|
||||
# port Clock { now: fn() -> float, day: fn() -> int = fn default_day } # in module clock
|
||||
# bind Clock { now: fn game_now } # in the app
|
||||
# bind Clock { now: fn game_now, day: g_day } # in the app; a variable for a member taking nothing
|
||||
# Clock.now() # anywhere that sees it
|
||||
#
|
||||
# A port is a record of function values (the record `Clock_port`, members without a default are
|
||||
|
|
@ -88,6 +88,13 @@ function port_bind_one(b: Node) -> void {
|
|||
}
|
||||
i += 1
|
||||
}
|
||||
# `member: some_global` binds a member that takes nothing to a variable: a getter is written
|
||||
i = 0
|
||||
while i < len(rec.kids) {
|
||||
let e = rec.kids[i].a
|
||||
if e != null and e.kind == E_ID { port_bind_var(b, c, rec.kids[i]) }
|
||||
i += 1
|
||||
}
|
||||
# what the bind names is seen from the bind's file: the port itself, and every `fn name`
|
||||
g_err_file = b.file
|
||||
g_err_line = b.line
|
||||
|
|
@ -125,6 +132,40 @@ function port_defaults_only(k: int) -> void {
|
|||
v.a = nw
|
||||
g_pt_bind[k] = nw
|
||||
}
|
||||
# `money: gm_money` for a `money: fn() -> int` member: the function `bind_<Port>_<member>` that
|
||||
# returns the variable, written in the bind's own file (so it sees what the bind sees)
|
||||
function port_bind_var(b: Node, c: Node, fi: Node) -> void {
|
||||
let name = fi.a.s
|
||||
let g = find_global(name)
|
||||
if g == null { port_err(b, `bind {b.s}: {fi.s}: {name} is not a variable (a function is bound as fn {name})`) }
|
||||
let fty = field_type(c, fi.s)
|
||||
let n = len(fty)
|
||||
if n < 7 or not (fty[0 .. 6] == "fn()->") {
|
||||
port_err(b, `bind {b.s}: {fi.s} is a {fty}, and only a member that takes nothing can be bound to a variable`)
|
||||
}
|
||||
let ret = fty[6 .. n]
|
||||
let gen = `bind_{b.s}_{fi.s}`
|
||||
let src = `function {gen}() -> {ret} {{\n return {name}\n}}\n`
|
||||
let saved_toks = toks
|
||||
let saved_pi = pi
|
||||
let saved_file = g_parse_file
|
||||
let saved_parsing = g_parsing
|
||||
g_parse_file = b.file
|
||||
g_parsing = true
|
||||
lex_at(src, b.line)
|
||||
pi = 0
|
||||
skipnl()
|
||||
parse_one_decl()
|
||||
toks = saved_toks
|
||||
pi = saved_pi
|
||||
g_parse_file = saved_file
|
||||
g_parsing = saved_parsing
|
||||
let r = node(E_FNREF)
|
||||
r.s = gen
|
||||
r.file = b.file
|
||||
r.line = b.line
|
||||
fi.a = r
|
||||
}
|
||||
function ports_finish() -> void {
|
||||
let saved = g_parsing
|
||||
g_parsing = false
|
||||
|
|
|
|||
45000
selfhost/ludicc.seed.ll
45000
selfhost/ludicc.seed.ll
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue