feat(lang): packages count under uses; a port of defaults may go unbound
A module that says uses must name every package module it reaches; a package with no module line is named for its directory (ludic_render3d) for this rule, so a mechanic reaching into the renderer is caught. Only the engine's runtime needs no naming. 'module x uses' with nothing after it reaches no other module. A port whose every member has a default answers with its defaults when unbound, and 'new' of a port says to bind it. ludic-dev test runs 'ludic test packages'. Reseed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e8c1d54a96
commit
f4062010e9
15 changed files with 47465 additions and 46516 deletions
|
|
@ -25,7 +25,8 @@ function rec_field(rec: Node, fname: pointer) -> Node {
|
|||
# default. `rec` is the E_REC of overrides (or null for the bare `new T`).
|
||||
function emit_new_struct(name: pointer, rec: Node) -> Val {
|
||||
let s = layout_node(name) # a struct or a property — same shape
|
||||
if (s == null) { perr("unknown record type in new") }
|
||||
if (s == null) and port_find(name) >= 0 { perr(`{name} is a port: it is filled once with 'bind {name} {{ ... }}' where the program is put together, not made with new`) }
|
||||
if (s == null) { perr(`unknown record type {name} in new`) }
|
||||
vis_check(s, name)
|
||||
let lty = layout_ty(name)
|
||||
let sz = emit_sizeof(lty)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
# emit_vis.ludic — L3: module scope. A file belongs to the module its own `module NAME` line or
|
||||
# its importer's names (frontend/parse.ludic, module_of); a file in no module is public. A
|
||||
# reference from one module to another module's function, global, record or event needs that
|
||||
# declaration `export`ed, and - when the referring module says `uses` - that module named there
|
||||
# (frontend/modules.ludic), unless the referring module is a friend of it (a test harness).
|
||||
# declaration `export`ed, and - when the referring module says `uses` - that module (or, for a
|
||||
# package with no module line, the package) named there (frontend/modules.ludic), unless the
|
||||
# referring module is a friend of it (a test harness). The engine's runtime needs no naming.
|
||||
# LUDIC_VIS_REPORT=1 prints every violation as `vis: <file>: <module>.<name>` (a private name) or
|
||||
# `uses: <file>: ...` (a module not in the uses list) and goes on, so a tool can add the exports
|
||||
# and the uses a codebase needs before the rule is switched on for it.
|
||||
|
|
@ -37,16 +38,17 @@ function vis_check(d: Node, what0: pointer) -> void {
|
|||
var here = g_err_file
|
||||
if here == null { return }
|
||||
let from = module_of(here)
|
||||
let uto = module_for_uses(d.file)
|
||||
if not (uto == "") and not (from == uto) and not module_friend_of(from, uto) and not module_may_use(from, uto) {
|
||||
if vis_reporting() {
|
||||
vis_say(`uses: {d.file}:{itoa(d.line)}: {uto}.{what} used from {here} (module {from})\n`)
|
||||
} else {
|
||||
perr(`{from} uses {uto}.{what} ({d.file}:{itoa(d.line)}): add 'uses {uto}' to {from}'s module line, or take it through a port`)
|
||||
}
|
||||
}
|
||||
let to = module_of(d.file)
|
||||
if (to == "") or (from == to) { return }
|
||||
if module_friend_of(from, to) { return }
|
||||
if not module_may_use(from, to) {
|
||||
if vis_reporting() {
|
||||
vis_say(`uses: {d.file}:{itoa(d.line)}: {to}.{what} used from {here} (module {from})\n`)
|
||||
} else {
|
||||
perr(`{from} uses {to}.{what} ({d.file}:{itoa(d.line)}): add 'uses {to}' to {from}'s module line, or take it through a port`)
|
||||
}
|
||||
}
|
||||
if d.vis == 1 { return }
|
||||
if vis_reporting() {
|
||||
vis_say(`vis: {d.file}:{itoa(d.line)}: {to}.{what} used from {here}\n`)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue