Say that a ring is refused, since the last note said the opposite
BUILT.md described a tolerated cycle as a property — "mutually dependent packages simply work" — and NEXT.md still listed a package importing a package as the real gap, which it stopped being some commits ago. Both now say what the code does. Written down with them: what a name imported through an intermediate package is called, and why the inner alias is forced rather than chosen; that the diamond is proven by the numbers pkg-diamond prints rather than by its compiling; and that pkgs is topologically ordered while the declaration list deliberately is not. Package visibility stays on the list. The gap is that a package has no way to mark a name private, which is surface syntax; the predicate and the refusal it would hang off are already there.
This commit is contained in:
parent
c604911ecb
commit
dc73b63446
29
BUILT.md
29
BUILT.md
@ -346,10 +346,28 @@ all four. A file carries no `.c` and no `link` file; those belong to a directory
|
||||
|
||||
**A package may import a package.** The qualification flattens to the *inner* alias — raylib imported by a package that
|
||||
is itself imported is still `rl/…`, never `sand/rl/…` — because a directory reached along two routes has to arrive under
|
||||
one set of names or the checker sees every declaration twice. A directory is keyed by its real path and read once, which
|
||||
is also what ends a cycle: a package that imports itself meets its own entry and contributes nothing the second time,
|
||||
and the namespace being flat, mutually dependent packages simply work. The same directory under two *different* aliases
|
||||
is refused.
|
||||
one set of names or the checker sees every declaration twice. It is the one decision here that would be hardest to
|
||||
change later, because a qualified name is an identity the `layout` op and the break loop both resolve by.
|
||||
|
||||
A directory is keyed by its real path and read once, so a **diamond** shares one copy of its bottom package.
|
||||
`programs/pkg-diamond.flan` is the case that proves it at the level that matters: `area/` and `draw/` both import
|
||||
`shape/`, a `shape/Box` is built inside `area/` and passed to a function declared inside `draw/`. Read `shape/` twice
|
||||
and there are two structs both named `shape/Box` which do not unify, so what proves the dedupe is that the program
|
||||
prints `3 6 20` and not that it compiles.
|
||||
|
||||
The same directory under two *different* aliases is refused, including when one of the two is a package's own import
|
||||
and the other is pages away in the entry file — `programs/pkg-alias-clash.flan`.
|
||||
|
||||
**A ring is refused and named.** Earlier it was not: the read-once table swallowed the second arrival, so mutually
|
||||
dependent packages appeared to work, and BUILT.md said so. What that cost is a definite package order, which is what
|
||||
the macro expander needs — every `defmacro` has to be compiled before anything that calls it — so it is now a refusal
|
||||
that names the ring, `a -> b -> c -> a`, rather than the single import that happened to close it. The two questions are
|
||||
kept apart by two pieces of state: the chain currently being read, and the set already finished. Found in the first is
|
||||
a cycle; found only in the second is the diamond's second route and still a no-op.
|
||||
|
||||
`Load.t.pkgs` comes back **dependencies first** — the topological order the acyclic rule buys. The declaration list is
|
||||
deliberately unsorted: `check.ml` collects every top-level name in one pass before it checks any body, so top-level
|
||||
names are order-independent by construction. The order exists for the expander, which cannot work that way.
|
||||
|
||||
**Visibility is one rule: `main` is not exported.** A package carrying one would collide with the importer's the moment
|
||||
anything imported it, so a program could never be a package; and `main` is a reachability root, so an imported one would
|
||||
@ -357,6 +375,9 @@ keep everything it calls alive. Writing `sand/main` is refused at the line that
|
||||
checker it would be "unknown name", which is true and useless.
|
||||
|
||||
Still missing: a package-private marker for anything other than `main`, which is why `rl/get-color-raw` is callable.
|
||||
The gap is surface syntax and not `load.ml` — `exported` is one predicate and the refusal machinery that points at the
|
||||
line which tried already exists, so a second rule is a line. What does not exist is any way for a package to *mark* a
|
||||
name private, and inventing one is a reader and parser change.
|
||||
|
||||
## The link follows the program
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user