compiler: implement blank package name semantics
This commit is contained in:
106
docs/spec.md
106
docs/spec.md
@@ -273,7 +273,8 @@ does not return (e.g. a call to `abort`).
|
||||
|
||||
```
|
||||
SourceFile = PackageClause { ImportDecl } { TopDecl } .
|
||||
PackageClause = "package" ident ";" .
|
||||
PackageClause = "package" PackageName ";" .
|
||||
PackageName = ident .
|
||||
ImportDecl = "import" ( ImportPath | ImportName ImportPath ) ";" .
|
||||
ImportName = ident .
|
||||
ImportPath = ident { "." ident } .
|
||||
@@ -285,6 +286,101 @@ ImportPath = ident { "." ident } .
|
||||
use the related `p_test`, and the actions remain separate even though one
|
||||
canonical directory owns their test product. The declared name need not equal
|
||||
the directory name or the final component of its canonical import identity.
|
||||
- The discard identifier `_` is syntactically valid as `PackageName`, but it
|
||||
is never a valid declared package name. A complete source with
|
||||
`package _;` reaches checker initialization, which reports exactly
|
||||
`invalid package name _` at the underscore token and continues checking the
|
||||
retained file. The package-clause parser admits the discard token only in
|
||||
this grammar slot; no other identifier position is broadened. A malformed or
|
||||
missing package name remains a parser error, and any complete-file syntax
|
||||
error prevents this checker diagnostic.
|
||||
|
||||
Loading may retain `_` transiently to compare declared source families,
|
||||
record imports, and construct the applicable action, but it is not canonical
|
||||
package, import, graph, action, symbol, `.wwi`, artifact, publication, or
|
||||
persistence identity. Direct sources retain `__root`; dotted directories
|
||||
and providers retain their dotted identities. Selected files with distinct
|
||||
declared names remain a loader/family conflict. In an all-blank action the
|
||||
checker emits one blank-name diagnostic per retained package marker in
|
||||
deterministic source order.
|
||||
|
||||
Observable ordering is source eligibility and loader-visible header/family
|
||||
validation, recursive import loading, the `ww run` main-package check,
|
||||
eligible dependency producers, complete parent-source parsing, then the
|
||||
blank-name, reached imported-package, and later checker diagnostics. Thus
|
||||
missing or invalid imports may precede the parent check; a blank run root is
|
||||
not `main` and starts no producer; and a full-source syntax error suppresses
|
||||
the blank-name error. An
|
||||
ordinary blank source provider cannot publish an interface or archive for an
|
||||
importer. A supplied or caller-corrupted `.wwi` can nevertheless contain
|
||||
that spelling and is defensively validated when reached.
|
||||
|
||||
Import interfaces are read, owner-checked, and syntax-parsed as separate
|
||||
lists before the primary source is parsed. Interface structural errors keep
|
||||
their existing precedence, but a primary syntax error returns before
|
||||
imported-package semantic checking and therefore suppresses every
|
||||
blank-provider import diagnostic. After successful primary syntax, compiler
|
||||
test mode first materializes its required `test` or collision-safe
|
||||
`__wwtest` support occurrence unless an equivalent primary occurrence
|
||||
exists. With no matching interface that occurrence retains the external
|
||||
support fallback; with a matching interface its provider name is validated,
|
||||
and the reserved spelling does not bypass the check.
|
||||
|
||||
Each represented canonical interface package is classified as valid,
|
||||
missing, conflicting, or invalid, where invalid means one nonconflicting
|
||||
real declared name `_`. Imported-interface reachability is rooted only at
|
||||
canonical uses in the primary and compiler-required lists. A reached valid
|
||||
interface owner may contribute its imported uses transitively; an invalid,
|
||||
missing, conflicting, unreachable, or ownerless section may not. Before
|
||||
interface facts are bound or merged, every declaration and use whose owner
|
||||
is not both reached and valid is discarded. An unused invalid interface is
|
||||
therefore wholly inert, even when it embeds a valid-origin section that
|
||||
imports the invalid path: it emits no diagnostic, installs no scope or
|
||||
declaration, changes no output, and is byte-equivalent to supplying no such
|
||||
interface. If primary source separately reaches that valid origin, its
|
||||
retained edge may legitimately reach and diagnose the invalid provider.
|
||||
|
||||
A retained use of an invalid provider is marked used. A nonblank use receives
|
||||
a fake empty-scope package binding under its explicit alias or, without one,
|
||||
the canonical path leaf; a blank use creates no visible binding. This
|
||||
recovery prevents qualified values, calls, and types from producing
|
||||
missing-member, unknown-type, export, or calling-nonfunction cascades.
|
||||
Ordinary lexical shadowing of a nonblank recovery alias still applies.
|
||||
|
||||
Immediately after primary blank-name diagnostics, the first retained use of
|
||||
each invalid canonical path reports exactly
|
||||
`could not import PATH (invalid package name: "_")`; later uses of that path
|
||||
are deduplicated, distinct paths retain occurrence order, and independent
|
||||
checker errors continue. Default, explicit, and blank import forms all
|
||||
position this error at the path's first identifier rather than at the alias.
|
||||
Canonical path, source spelling, alias, declared provider name, owner marker,
|
||||
placeholder, edge, and binding remain separate facts. A physical `.wwi`
|
||||
path is observation metadata and a same-named `.ww` file remains an import
|
||||
decoy.
|
||||
|
||||
Ordinary `ww build` still omits a valid visible literal `*_test.ww` after
|
||||
header loading, so `package _;` in that omitted role has no action or
|
||||
diagnostic. Under `ww test`, production plus a same-package blank test forms
|
||||
one augmented internal-test action; the test recompile substitutes for the
|
||||
separate production node and one compiler invocation diagnoses every
|
||||
retained blank marker. A test-only blank source has one test-package action.
|
||||
Mixed valid/blank production and test names retain family-mismatch
|
||||
precedence, and no failed blank product reaches generated main, link, or
|
||||
runtime.
|
||||
|
||||
Normal blank-package failure publishes no assembly, interface, object,
|
||||
archive, executable, retained test, or new semantic generation. Existing
|
||||
request rollback removes owned stages and preserves prior public and
|
||||
committed bytes; a public build or test consuming a reached corrupted
|
||||
committed interface likewise publishes no replacement consumer generation,
|
||||
retained test, or downstream artifact. Exact valid-interface restoration
|
||||
follows ordinary reuse. Independent requests share no blank-name,
|
||||
reachability, deduplication, or fake-binding state. Cstage and WWstage have
|
||||
the same path-positioned diagnostic stream and artifact outcome. The private
|
||||
in-memory AST adds only path-position fields; AST enum/printing, `.wwi`
|
||||
schema, build workdir format 18, test workdir format 19, and semantic storage
|
||||
format 3 do not change. External driver interruption is unchanged; the fixed
|
||||
`.new` residue and later persistent request poisoning remain open.
|
||||
- Each source file has one contiguous import section immediately after its
|
||||
package clause. Once a non-import top-level declaration begins, a later
|
||||
`import` is rejected as `imports must appear before other declarations`.
|
||||
@@ -643,10 +739,10 @@ ImportPath = ident { "." ident } .
|
||||
interruption preserve existing directory contents and remove only
|
||||
request-created prefixes and stages. Direct external `SIGTERM` of a build
|
||||
driver is a verified-open exception: both stages preserve public and
|
||||
committed work bytes and reap their process group, but may leave `.new`
|
||||
staging files that make a later persistent-work request reject until those
|
||||
files are removed. A non-directory output retains the single-product
|
||||
file/archive rule.
|
||||
committed work bytes, but leave the directly spawned compiler alive and
|
||||
exactly three fixed-name `.new` staging files; the existing `.unit.new`
|
||||
makes a later persistent-work request reject. A non-directory output retains
|
||||
the single-product file/archive rule.
|
||||
If a lone
|
||||
command's synthesized default basename already names a directory, loading
|
||||
and graph validation complete and the build rejects before tools without
|
||||
|
||||
Reference in New Issue
Block a user