Systems & interop
Modules and Imports
Every .vel file is a module. Use import to bring another module's top-level declarations (functions, classes, extensions) into scope.
Importing
import "std/bool" # standard-library module (no .vel needed)
import "util/hash" # a file util/hash.vel, relative to THIS file
import "./sibling" # a sibling module
Terminal term = new Terminal()
term.println(true.str()) # "true" — from std/boolRules:
- The
.velextension is optional —import "std/map"loadsstd/map.vel. std/names resolve to the bundled standard library.- Any other path resolves relative to the importing file, so code can be organised in sub-directories (a module in
util/canimport "./helper"). - Each module is loaded once per compilation, keyed by its real path — the same file reached two ways (directly and transitively) is not re-imported.
- A name clash between modules is a compile error, not a silent override. Rename one of the declarations to resolve it, or import under a namespace (below).
Namespaced imports (as)
import "path" as ns brings a module's declarations in under the prefix ns instead of into the top-level scope. Reach every top-level function and class of that module qualified as ns.name:
import "geom" as g
import "shapes" as s # both modules may define `area` — no clash
term.println(g.area(3).str())
g.Point p = new g.Point(1, 2) # a namespaced class is a type AND a constructorRules:
- Members are reached qualified —
ns.func(...),new ns.Class(...), and the typens.Class(e.g.g.Point p = ...). Barefunc()/Classdo not see a namespaced module's names. - Namespacing sidesteps clashes — two modules that both export
areacan be importedas a/as band used asa.area()/b.area(). - Inside the module nothing changes — its own functions, methods, and class references resolve to each other normally; the namespace is only how callers see it.
- One alias per module — a module already loaded (by any import) keeps its first binding; importing the same file again under a different alias is a no-op.
Standard modules
The standard library lives under std/ — real Velo code you import:
std/bool— Boolean extensions (int;bool.str()is a built-in, no import needed)std/int— Integer extensions (abs,format)std/str— String extensions (bytes)std/array— Array extensions (str)std/map— Generic hash map (dict[K:V]imports this automatically)std/error— theErrortype andERR_*codes (auto-imported bytry/catch/throw; see Error Handling)std/base64— Base64 encoding/decodingstd/crc32— CRC-32 checksumstd/deflate— raw DEFLATE compressionstd/zip— single-entry ZIP archivesstd/random—Random, a bit-for-bit reimplementation ofjava.util.Random
The native classes Terminal, Time, Http, FileSystem and Socket need no import: the runtime provides them and the compiler knows their types from the registration (see Native Classes).