feat(lang): friend module lab of fishing, data - a friend of the modules it names
A scoped friend sees those modules' private names and only the exports of every other; a plain friend module still sees everything. Reseed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
f4533331e7
commit
70d05bd504
8 changed files with 41388 additions and 41329 deletions
|
|
@ -103,7 +103,8 @@ visible.ludic:5: error: add is private to module bank; mark it 'export' where it
|
||||||
A file in no module - the program's own file, the runtime - is public, and a package found
|
A file in no module - the program's own file, the runtime - is public, and a package found
|
||||||
through `ludic_modules` or the toolchain keeps its own module rather than its importer's. A
|
through `ludic_modules` or the toolchain keeps its own module rather than its importer's. A
|
||||||
program that says `friend module lab` sees every module's private names: that is for a test
|
program that says `friend module lab` sees every module's private names: that is for a test
|
||||||
harness, which has to reach inside what it tests. `export` is a keyword before a declaration
|
harness, which has to reach inside what it tests. `friend module lab of fishing, data` narrows
|
||||||
|
that to the modules named: `lab` sees their private names, and every other module's exports only. `export` is a keyword before a declaration
|
||||||
and is not the `@export` annotation, which names a C symbol.
|
and is not the `@export` annotation, which names a C symbol.
|
||||||
|
|
||||||
To move an existing codebase onto modules, build it once with `LUDIC_VIS_REPORT=1`: every
|
To move an existing codebase onto modules, build it once with `LUDIC_VIS_REPORT=1`: every
|
||||||
|
|
@ -132,7 +133,8 @@ fishing/land.ludic:4: error: fishing uses items.inv_add (items/index.ludic:3): a
|
||||||
switched on one module at a time. Two module lines for one module add their lists together.
|
switched on one module at a time. Two module lines for one module add their lists together.
|
||||||
- A file in no module (the program's root, the runtime) is unaffected either way, and a package's
|
- A file in no module (the program's root, the runtime) is unaffected either way, and a package's
|
||||||
module (found through `ludic_modules` or the toolchain, such as `ludic_ui`) is always usable.
|
module (found through `ludic_modules` or the toolchain, such as `ludic_ui`) is always usable.
|
||||||
- A friend of a module (below) is not held to its `uses` for that module.
|
- A friend of a module (`friend module lab`, or `friend module lab of fishing`) is not held to its
|
||||||
|
`uses` for that module.
|
||||||
- The declared graph may not go round: `module a uses b` beside `module b uses a` is refused
|
- The declared graph may not go round: `module a uses b` beside `module b uses a` is refused
|
||||||
(`the modules' uses go round in a circle: a -> b -> a`) - one of them takes the other through a
|
(`the modules' uses go round in a circle: a -> b -> a`) - one of them takes the other through a
|
||||||
port instead.
|
port instead.
|
||||||
|
|
|
||||||
5
changes/friend-of.md
Normal file
5
changes/friend-of.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
bump: minor
|
||||||
|
type: feature
|
||||||
|
**`friend module lab of fishing, data` - a friend of some modules, not all.** A scoped friend sees
|
||||||
|
the private names of the modules it names and only the exports of every other; `friend module lab`
|
||||||
|
alone still sees everything.
|
||||||
12
examples/modules/friend_of.ludic
Normal file
12
examples/modules/friend_of.ludic
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# friend_of.ludic — L3: `friend module lab of bank` sees bank's private names and no other module's;
|
||||||
|
# a test harness reaches inside exactly what it tests. `friend module lab` alone still sees all.
|
||||||
|
#
|
||||||
|
# Running it prints: 7 7
|
||||||
|
import "bank"
|
||||||
|
program FriendOf {
|
||||||
|
friend module lab of bank
|
||||||
|
entry {
|
||||||
|
add(7)
|
||||||
|
print(`{balance} {total()}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
10
examples/rejected/friend_scope.ludic
Normal file
10
examples/rejected/friend_scope.ludic
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# L3: a friend of kit is not a friend of bank - bank's private `add` stays out of reach
|
||||||
|
import "private_bank"
|
||||||
|
import "private_kit"
|
||||||
|
program FriendScope {
|
||||||
|
friend module lab of kit
|
||||||
|
entry {
|
||||||
|
add(5)
|
||||||
|
print(total())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -61,7 +61,11 @@ function mod_parse_friend() -> void {
|
||||||
pi += 2
|
pi += 2
|
||||||
let fm = eat_id()
|
let fm = eat_id()
|
||||||
module_set(g_parse_file, fm)
|
module_set(g_parse_file, fm)
|
||||||
let scope = ""
|
var scope = ""
|
||||||
|
if is_id("of") {
|
||||||
|
pi += 1
|
||||||
|
scope = mod_parse_names()
|
||||||
|
}
|
||||||
push(g_mod_friends, fm)
|
push(g_mod_friends, fm)
|
||||||
push(g_fr_scope, scope)
|
push(g_fr_scope, scope)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
41338
selfhost/ludicc.seed.ll
41338
selfhost/ludicc.seed.ll
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -738,6 +738,8 @@ function cmd_dev_test() -> int {
|
||||||
feat_case("modules/uses", "", "8 3", "uses.ludic (L3: `module fishing uses base` - a module reaches only the modules it names)")
|
feat_case("modules/uses", "", "8 3", "uses.ludic (L3: `module fishing uses base` - a module reaches only the modules it names)")
|
||||||
reject_case("rejected/uses_missing", "fishing uses items.inv_add", "a module that says `uses` cannot reach a module it does not name, exported or not")
|
reject_case("rejected/uses_missing", "fishing uses items.inv_add", "a module that says `uses` cannot reach a module it does not name, exported or not")
|
||||||
reject_case("rejected/uses_cycle", "go round in a circle: a -> b -> a", "a cycle in the declared uses is refused")
|
reject_case("rejected/uses_cycle", "go round in a circle: a -> b -> a", "a cycle in the declared uses is refused")
|
||||||
|
feat_case("modules/friend_of", "", "7 7", "friend_of.ludic (L3: `friend module lab of bank` sees bank's private names)")
|
||||||
|
reject_case("rejected/friend_scope", "add is private to module bank", "a friend of one module is not a friend of another")
|
||||||
vis_report_case("rejected/uses_missing", "uses: examples/rejected/uses_valley/items/index.ludic:3: items.inv_add used from", "LUDIC_VIS_REPORT=1 lists a uses violation and builds")
|
vis_report_case("rejected/uses_missing", "uses: examples/rejected/uses_valley/items/index.ludic:3: items.inv_add used from", "LUDIC_VIS_REPORT=1 lists a uses violation and builds")
|
||||||
feat_case("lang/checked", "", "7.5 3 12 hi 2 ok", "checked.ludic (L4: literals take their slot's kind, string(p), []string as []pointer, null, named args)")
|
feat_case("lang/checked", "", "7.5 3 12 hi 2 ok", "checked.ludic (L4: literals take their slot's kind, string(p), []string as []pointer, null, named args)")
|
||||||
reject_case("rejected/wrong_arity", "this call to area leaves out h, which has no default", "a call with the wrong number of arguments is refused")
|
reject_case("rejected/wrong_arity", "this call to area leaves out h, which has no default", "a call with the wrong number of arguments is refused")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue