Namespaces
Imports & Modules
An import pulls another file's declarations into the current document. There are two forms, distinguished by how the path is written.
Disk imports
A quoted path imports a file from disk, resolved relative to the importing file.
import "./pages/values.wcl"
import "../shared/types.wcl"
System imports
An angle-bracket path imports a system module — a file provided by the host program through a registry, not the filesystem. wdoc's standard library is served this way: a single import <wdoc.wcl> pulls in the whole stdlib.
import <wdoc.wcl>
Import the wdoc stdlib once, at the root
Start the document you pass to wcl wdoc build with import <wdoc.wcl>, and the stdlib is in scope there and in every page file it imports. Imported page files do not repeat the line.
How imports compose
Top-level imports are eager; an import inside a block is lazy. Imported declarations participate fully in the importer — in structural validation and name resolution — so a type or let declared in an imported file is usable as if local. An imported file keeps its own declaring namespace. See Namespaces.
An import inside a block also splices the imported file's top-level block instances into the enclosing block as children — exactly as if written inline — so you can factor a nested subtree into its own file. The spliced instances are validated against the parent's @child / @children slots like any literal child.
A namespace declaration scopes a file's declarations under a dotted path, use pulls names from other namespaces into local scope, and a ns::kind qualifier picks a block schema from a specific namespace. Together they let independently-authored libraries share a document without name collisions.
Declaring a namespace
namespace takes a dotted path and must be the first item in the file. Every declaration then lives under that path: with namespace company, a type Point is fully qualified company.Point. A dotted declaration name nests further — type utils.Point becomes company.utils.Point.
namespace company
type utils.Point { x: f64 y: f64 }
type shapes.Circle { center: utils.Point radius: f64 }
Imported files keep their own namespace — an import brings their declarations in, but the names stay qualified under the imported file's path. See Imports & Modules.
use declarations
use brings qualified names into local scope so they can be written bare. It is top-level only; an unknown target or duplicate alias is an error when the document is opened.
use company.utils.Point // bind the leaf: write `Point`
use company.utils.Point as P // leaf under another name: `P`
use company.utils // whole namespace: every member resolves bare
use company.utils as U // namespace alias: `U.Point`
use company.shapes.{Circle, Square as Sq} // pick several members at once
| Form | Effect |
|---|---|
| use ns.Name | Binds Name locally |
| use ns.Name as Alias | Binds the member under Alias |
| use ns | Adds the namespace to the bare-name search path |
| use ns as Alias | Namespace alias — members reachable as Alias.Name |
| use ns.{A, B as C} | Binds several members in one declaration |
Qualified block kinds
Block (and table) kinds are namespace-scoped too. A ::-qualified kind at the instance site selects the @block declaration from that namespace, even when a local declaration shadows the bare kind.
import <wdoc.wcl>
// A local @block("process") shadows the bare kind...
@block("process") type MyProcess { @inline(0) text: utf8 cost: i64 }
process "mine" { cost = 3 } // -> MyProcess (local wins)
wdoc::process "theirs" { } // -> wdoc's Process, explicitly
How bare names resolve
A bare kind prefers a declaration in the referencing file's own namespace; otherwise it falls back to an imported one. So a user @block("process") deterministically shadows a library's. Two same-kind declarations in the same namespace are an error; the same kind across different namespaces is fine — disambiguate at the instance with ::.
import vs namespace vs use
An import decides which files participate. The imported file's namespace decides what its declarations are called, and your use declarations (or :: qualifiers) decide how you refer to them.