A def from another module into a registry that is not open is refused, and defs go through visibility (the registry exported, its module in the definer's uses). Index order: the declaring module's entries, then the other modules' by module name, each in reading order. A registry entry is emitted as its own file's code, so what it names is seen from its own module. Reseed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
2.5 KiB
Text
80 lines
2.5 KiB
Text
# registry_open.ludic — L8 + L3: which defs a registry takes, and in what order.
|
|
#
|
|
# A def written in another module than its registry's is refused unless the registry says `open
|
|
# registry`, and then it goes through the same visibility as any reference: the registry must be
|
|
# exported, and a module that says `uses` names the registry's module. The index order is the
|
|
# declaring module's own entries first, in the order they were read, then each other module's, the
|
|
# modules in the order of their names and each one's entries in the order they were read - so an
|
|
# entry's index does not depend on the order a barrel happens to import things in. A registry and
|
|
# its defs in one module, or in no module, keep exactly the order they always had.
|
|
function reg_def_check(d: int) -> void {
|
|
let r = reg_find(g_df_reg[d])
|
|
let v = g_rg_var[r]
|
|
let rec = g_df_rec[d]
|
|
let to = module_of(v.file)
|
|
let from = module_of(rec.file)
|
|
if (to == "") or (from == to) { return }
|
|
g_err_file = rec.file
|
|
g_err_line = rec.line
|
|
let saved = g_parsing
|
|
g_parsing = false
|
|
if g_rg_open[r] == 0 {
|
|
perr(`def {v.s} {g_df_key[d]}: registry {v.s} is not open to other modules; declare it 'open registry {v.s}' in module {to}, or write the def there`)
|
|
}
|
|
vis_check(v, v.s)
|
|
g_parsing = saved
|
|
}
|
|
# a < b, byte by byte
|
|
function reg_str_less(a: pointer, b: pointer) -> bool {
|
|
var i = 0
|
|
while i < len(a) and i < len(b) {
|
|
if a[i] != b[i] { return a[i] < b[i] }
|
|
i += 1
|
|
}
|
|
return len(a) < len(b)
|
|
}
|
|
# the defs of registry r, as indices into g_df_*, in index order
|
|
function reg_order(r: int) -> []int {
|
|
let out = new []int
|
|
let own = module_of(g_rg_var[r].file)
|
|
let others = new []pointer
|
|
var d = 0
|
|
while d < len(g_df_reg) {
|
|
if (g_df_reg[d] == g_rg_name[r]) {
|
|
let m = module_of(g_df_rec[d].file)
|
|
if (m == own) { push(out, d) }
|
|
else {
|
|
var seen = false
|
|
var j = 0
|
|
while j < len(others) {
|
|
if (others[j] == m) { seen = true }
|
|
j += 1
|
|
}
|
|
if not seen { push(others, m) }
|
|
}
|
|
}
|
|
d += 1
|
|
}
|
|
# a handful of modules: an insertion sort by name
|
|
var i = 1
|
|
while i < len(others) {
|
|
let x = others[i]
|
|
var j = i - 1
|
|
while j >= 0 and reg_str_less(x, others[j]) {
|
|
others[j + 1] = others[j]
|
|
j -= 1
|
|
}
|
|
others[j + 1] = x
|
|
i += 1
|
|
}
|
|
i = 0
|
|
while i < len(others) {
|
|
d = 0
|
|
while d < len(g_df_reg) {
|
|
if (g_df_reg[d] == g_rg_name[r]) and (module_of(g_df_rec[d].file) == others[i]) { push(out, d) }
|
|
d += 1
|
|
}
|
|
i += 1
|
|
}
|
|
return out
|
|
}
|