parser: an attribute before export is kept - @ToClients export event E was a local event (the attributes read in front of export were dropped when the declaration was parsed afresh one call down), as were @Sync / @Owned / @Server / @On / @Public ... before export; and export @ToClients event was refused. Attributes and export now read in either order into one declaration, and a wrapper marks what it added exported (g_at_keep goes); examples/networking/net_export and three schema cases (added, not run); reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
64adb052b4
commit
26b986de5b
7 changed files with 89034 additions and 88841 deletions
|
|
@ -36,7 +36,6 @@ var g_at_nargs: []int = new []int
|
|||
var g_at_unres: []bool = new []bool # its target is not in this program (a warning; the schema says so)
|
||||
var g_at_open: int = -1 # the group the attributes being read go into
|
||||
var g_at_decl: []pointer = new []pointer # @AppendOnly / @ByKey read before a declaration
|
||||
var g_at_keep: bool = false # `export` parses its declaration one call down
|
||||
|
||||
# a new group, empty; its index
|
||||
function at_group() -> int {
|
||||
|
|
@ -165,10 +164,6 @@ function at_decl_with(a: pointer, args: pointer) -> void {
|
|||
push(g_at_decl_args, args)
|
||||
}
|
||||
function at_decl_reset() -> void {
|
||||
if g_at_keep {
|
||||
g_at_keep = false
|
||||
return
|
||||
}
|
||||
if len(g_at_decl) > 0 { at_decl_clear() }
|
||||
}
|
||||
function at_decl_clear() -> void {
|
||||
|
|
|
|||
|
|
@ -982,7 +982,36 @@ function decl_hook_target(ev: pointer, sp: pointer, dsp: pointer, att: pointer,
|
|||
# parse one top-level declaration (or resolve an import) into `prog`.
|
||||
# Modifiers are `@annotations` in front of the declaration: `@export`, `@edge`,
|
||||
# `@pure`, `@deterministic`, … — one channel, not a zoo of prefix keywords.
|
||||
var g_decl_exported: bool = false # `export` read in front of the declaration being parsed
|
||||
function parse_one_decl() -> void {
|
||||
let p0 = len(prog)
|
||||
let e0 = len(g_events)
|
||||
let r0 = len(g_rg_var)
|
||||
let outer = g_decl_exported
|
||||
g_decl_exported = false
|
||||
parse_one_decl_in()
|
||||
if g_decl_exported { decl_mark_exported(p0, e0, r0) }
|
||||
g_decl_exported = outer
|
||||
}
|
||||
# `export function f`, `export var v`, ...: what the declaration added is visible from other modules (L3)
|
||||
function decl_mark_exported(p0: int, e0: int, r0: int) -> void {
|
||||
var k = p0
|
||||
while k < len(prog) {
|
||||
prog[k].vis = 1
|
||||
k += 1
|
||||
}
|
||||
k = r0
|
||||
while k < len(g_rg_var) { # a @PerMap registry's own node is not in prog
|
||||
g_rg_var[k].vis = 1
|
||||
k += 1
|
||||
}
|
||||
k = e0
|
||||
while k < len(g_events) {
|
||||
g_events[k].vis = 1
|
||||
k += 1
|
||||
}
|
||||
}
|
||||
function parse_one_decl_in() -> void {
|
||||
at_decl_reset() # attrs.ludic: @AppendOnly / @ByKey belong to one declaration
|
||||
var is_export = false
|
||||
var qspec: Node = null
|
||||
|
|
@ -1005,7 +1034,14 @@ function parse_one_decl() -> void {
|
|||
var esys_phase: pointer = null
|
||||
var ns_name: pointer = null # @Namespace(Name) — a package-provided Foo.* namespace (#62)
|
||||
var is_det = false # @deterministic — no floating point inside (emit_float.ludic)
|
||||
while is_op("@") {
|
||||
# attributes and `export` in any order: `@ToClients export event E` keeps its @ToClients
|
||||
while is_op("@") or (is_id("export") and (toks[pi + 1].kind == TK_ID or toks[pi + 1].text == "@")) {
|
||||
if is_id("export") {
|
||||
pi += 1
|
||||
g_decl_exported = true
|
||||
skipnl()
|
||||
continue
|
||||
}
|
||||
pi += 1; let a = eat_id() # collect a leading @annotation
|
||||
if a == "export" { is_export = true }
|
||||
else if a == "Public" { is_public = true } # @Public hook promotion
|
||||
|
|
@ -1045,7 +1081,7 @@ function parse_one_decl() -> void {
|
|||
let why = expr()
|
||||
if why.kind != E_STR or len(why.s) == 0 { perr("@alloc_ok needs its reason: @alloc_ok(\"a memo miss, bounded by MM_CAP\")") }
|
||||
eat_op(")")
|
||||
g_aok_pending = true # a global: `export` parses the declaration one call down
|
||||
g_aok_pending = true # a global: the declaration after the attributes reads it
|
||||
}
|
||||
else if a == "creates" or a == "releases" { # 25.5e: @creates(PhysShape) / @releases(PhysShape)
|
||||
eat_op("(")
|
||||
|
|
@ -1073,31 +1109,6 @@ function parse_one_decl() -> void {
|
|||
mod_parse_line() # module NAME [uses A, B]
|
||||
return
|
||||
}
|
||||
# `export function f`, `export var v`, ...: visible from other modules (L3)
|
||||
if is_id("export") and (toks[pi + 1].kind == TK_ID) {
|
||||
pi += 1
|
||||
g_at_keep = true
|
||||
let p0 = len(prog)
|
||||
let e0 = len(g_events)
|
||||
let r0 = len(g_rg_var)
|
||||
parse_one_decl()
|
||||
var k = p0
|
||||
while k < len(prog) {
|
||||
prog[k].vis = 1
|
||||
k += 1
|
||||
}
|
||||
k = r0
|
||||
while k < len(g_rg_var) { # a @PerMap registry's own node is not in prog
|
||||
g_rg_var[k].vis = 1
|
||||
k += 1
|
||||
}
|
||||
k = e0
|
||||
while k < len(g_events) {
|
||||
g_events[k].vis = 1
|
||||
k += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
if is_id("numbers") and (toks[pi + 1].text == "float") {
|
||||
pi += 2
|
||||
if not is_float_file(g_parse_file) { float_file_add(g_parse_file) }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue