Documentation/Reference

Build-time embedded values

On this page

EMBED reads a UTF-8 file while building and makes a readonly module value. The executable needs neither the input file nor the decoder. PUBLIC/PRIVATE work as for other module declarations. Implementation reference .

TYPE ServerConfig
    Host AS STRING
    Port AS INTEGER = 8080
END TYPE

EMBED Defaults FROM "config/defaults.json" AS ServerConfig USING Json
EMBED DefaultText FROM "config/defaults.json" AS STRING
EMBED Port FROM "config/port.txt" AS INTEGER USING ReadPort

PRINT Defaults.Host; ":"; Defaults.Port
local = Defaults
local.Port = 9000
PRINT Defaults.Port       ' Still the original value.

FUNCTION ReadPort(text AS STRING) AS INTEGER FAILS NumericError
    RETURN VAL(TRIM(text))
END FUNCTION

Paths are relative to the declaring source, including imported modules. A path must stay inside its declared project tree, or its source directory for a standalone module; absolute paths and escaping symlinks are rejected. Inputs must be stable regular files. STRING preserves UTF-8 bytes, NUL, a BOM and line endings exactly. A decoder applies its own text/format policy.

USING names an ordinary visible function. Its first argument receives STRING content; trailing arguments use their checked defaults. The AS type supplies ordinary result context, including inferred generic result types. The same function works at runtime. Json selects DecodeJson when no visible function named Json exists. Other user decoders need no registration or compiler plugin. YAML/TOML/XML codecs are separate pending work.

All declarations are checked, including unused inputs. Decoders may read other embedded values; dependencies are ordered before execution and cycles are errors. Application top-level statements and Main do not run during decoding.

The declaration and its nested data cannot be assigned, transferred or passed BYREF. Ordinary readonly calls borrow it. Assignment/owned return/BYVAL use the normal independent-value rules; changing a copy cannot change the embedded value. Immutable STRING bytes can safely remain shared. Records, lists, sets, dictionaries, dense arrays, optionals, choices and enums are supported recursively. Resources, pointers, function values, task/channel handles and errors as successful data are rejected. A decoder can still fail with its declared typed errors.

Raw STRING embeddings also work in ordinary constant/default contexts. A value produced by USING is a readonly runtime value; it does not become a general constant-expression factory. Exported .blib values preserve these rules after moving the package and deleting producer sources/data. Generic bodies may refer to private embedded values in their own module.

Deterministic decoding and failures

Local construction, computation and cleanup are allowed. The decoder’s checked call/callback/cleanup closure must avoid I/O, clocks, randomness, tasks, unsafe operations and unknown foreign behavior. Prebuilt BASIL decoders require a versioned build-effects contract; legacy packages work normally but must be rebuilt to serve as opaque build-time decoders. Scheduler EFFECTS alone is not evidence of deterministic behavior.

A Linux x86-64 child receives the authorized content and has bounded memory, CPU, wall time and output. Filesystem/network/process access and executable memory are denied. Unsupported kernel isolation fails the build. Normal decoder failures clean owned values, then report the declaration’s source line/column, input path, concrete error and primitive error fields. JSON offsets additionally map to input line/scalar-column alongside path/offset/message fields. Diagnostic I/O does not replace the primary failure. Nonprimitive error fields are not dumped; user Display/serialization hooks do not run while reporting failures. Forced termination/fatal allocation does not promise normal decoder cleanup.

Current build policy: 8 MiB per input; 32 MiB aggregate input including an eight-byte length per declaration; 32 MiB evaluator image; 64 MiB value packet; 1,048,576 value nodes; nesting depth128; 16 KiB diagnostics; 256 MiB child virtual memory; 5 CPU seconds and 10 wall seconds. Exceeding a limit is a build diagnostic, not a recoverable error in the resulting application.

Caches and output

build/.basic/embed beneath the entry source directory holds optional evaluator images and successful checked packets. Keys include compiler/SDK, target/policy, source/module/project identities, type schemas, decoder/default code and compiled inputs. Changed typed content reuses a compatible evaluator but reruns decoding. Semantic/effect checks and packet validation still run on hits. Damaged entries miss/rebuild; a malformed executable with otherwise valid cache metadata is explicitly rejected by the job boundary. Failures are never cached. Readonly projects build without a writable cache. Remove this directory to clear it.

From the BASIL documentation. View source ↗

Find your way around BASIL

Type to search the manual.