5. Names and Bindings
5.1 Name Domains
Culsma uses distinct name domains:
- Include targets (source file loading domain)
- Library import targets (frontend library-resolution domain)
- Module names (source-file and imported-library namespace domain)
- Protocol names (program structure domain)
- Protocol parameter names (call-frame domain)
- Local
letnames (expression domain) - Semantic/material names (runtime container/group binding domain)
- Content identities and aliases (runtime content domain)
These domains have different resolution rules and diagnostics.
5.2 Include Target Resolution
include target resolution is a load-stage concern.
Rules:
- Source-level include targets resolve from including file directory (relative) or absolute path.
- Loader resolves include targets recursively and deduplicates canonical paths.
- Missing targets and include cycles are load-stage hard errors.
5.2.1 Library Import Target Resolution
import target resolution is a frontend-resolution concern.
Rules:
- Import targets resolve against configured library roots and bundled stdlib sources.
- Missing import targets are frontend-resolution hard errors.
- Imported library protocols join the active program namespace before compilation.
- Bundled standard-library protocols remain separately available for protocol resolution and do not join the active program namespace.
5.3 Protocol Name Resolution
Protocol reference baseline:
- Preferred protocol reference syntax is
Module.Protocol(...). Moduleresolves to source module name (default: file stem in loader) or imported library module name.Protocolresolves from the active program namespace or the separately available bundled standard-library definitions.include ProtocolName;remains part of the source surface.
Rules:
- Resolution is exact and case-sensitive.
- Missing targets are reported as
PLAN_UNKNOWN_REFERENCE. - Cyclic reference chains are reported as
PLAN_REFERENCE_CYCLE. - Diagnostic code definitions and stage placement are specified in Chapter 8.
- Duplicate module names across loaded files are load-stage hard errors.
5.3.1 Protocol Parameter Binding
Rules:
- Plan lowering binds protocol-call arguments to callee parameters in a dedicated call frame.
- Binding precedence: explicit arg > default value.
- Missing, unknown, or duplicate protocol-call arguments are reported as
PLAN_CALL_ARG_MISSING,PLAN_CALL_ARG_UNKNOWN, orPLAN_CALL_ARG_DUPLICATE. - Diagnostic code definitions and stage placement are specified in Chapter 8.
- Parameter names
MUSTbe unique within one protocol declaration. - Parameter names and local
letnames in the same protocol bodyMUST NOTconflict. - Parameter names and repeat binding names in the same protocol body
MUST NOTconflict. - Callee parameter binding does not implicitly inherit caller
letbindings. - The call contract is name-based; examples SHOULD use named arguments.
- The parser may normalize positional protocol-call arguments as
arg0,arg1, ... but those names are not the preferred stable binding contract.
5.4 Local Binding Resolution (let)
let names are resolved in protocol-local context. A protocol has one root name scope. Nested statement bodies create child scopes for lookup, but they do not permit shadowing; local let declarations remain protocol-body unique as specified below.
Rules:
IDENTIFIERexpressionsMAYresolve to priorletbindings in the same protocol-local context.- Protocol parameter names also enter the callee protocol-local binding context.
if,repeat,with env, andwith constraintbodies create nested lookup scopes.- Nested lookup scopes
MAYread and assign names declared in an enclosing protocol-local scope. - Nested lookup scopes
MUST NOTredeclare an existing protocol parameter, localletname, or repeat binding visible from an enclosing scope. - Local
letnamesMUSTbe unique within one protocol body, including all nested statement bodies and both branches of anif. - A
repeatbinding is visible only inside its repeat body. ItMUST NOTshadow a protocol parameter, a localletname, or an active enclosing repeat binding. Sibling repeat statements whose scopes do not overlapMAYreuse the same binding name. - The same parameter or local names
MAYbe reused in different protocol declarations, including imported or indirectly imported protocols. repeatandifcompile-time checks rely on resolvable local values.- Unresolvable compile-time requirements (for example, non-constant repeat count) are compile errors.
Runtime-controlled mutation of protocol-local scalar state is supported. Assignments to an existing protocol-local binding inside a runtime-controlled block update that binding for subsequent runtime evaluation along the executed control-flow path.
5.5 Semantic Name Resolution (Material Domain)
Step arguments that denote containers/material names resolve via runtime binding state.
Resolution model:
- Names resolve to
container_idthrough binding tables and direct container references. container_idis a logical vessel identity; in real lab setup it typically maps to a tube or a plate well.- Physical carrier mapping is represented by container metadata (for example carrier kind/id/well), not by replacing the logical identity model.
- Material-name resolution is invariant across reporting and external inventory configuration.
Failure surface:
- Binding validation checks identifier-form source refs and string-literal source refs with the same binding rule.
- Binding coverage is attached to source IR:
mutation_stmt (<<)target/source,with env(...)inferred/explicit-hold targets, andsep/frac/img/ecp/physample refs. agit(...)sample refs are also covered by binding read checks.- Unbound runtime-visible names are commonly reported as
SEM_UNBOUND_NAME_REFERENCEwhen statically decidable orMAT_BINDING_NOT_FOUNDduring material execution. - Diagnostic code definitions and stage placement are specified in Chapter 8.
5.5.1 Content Identity Resolution (Content Domain)
For content-aware constructor and load flows:
Contentsymbols resolve tocontent_idin runtime content registry/state.content_idis independent ofcontainer_id; association is formed by load/apply operations.- One content identity may appear in multiple containers over time through transfer/split/mix semantics.
- Container bindings and content bindings are distinct domains and must not be conflated.
Failure surface:
- Constructor contracts validate content identity fields before runtime use.
- Missing or invalid content constructor fields are commonly reported with
SEM_MISSING_CONTENT_KINDorSEM_INVALID_CONTENT_KIND. - Runtime/material execution fails with
MAT_CONTENT_NOT_FOUNDwhen a referenced content identity is absent. - Diagnostic code definitions and stage placement are specified in Chapter 8.
5.5.2 Component-Entry Identity and Selection
Each normalized material component entry has a non-empty entry_id that is unique within its containing container. entry_id identifies that physical entry; content_ref independently identifies what the entry contains. Two entries may therefore share one content_ref while retaining different entry_id values and material relations.
The read-only ContainerRef.materials selector surface used by sep.transitions supports:
container.materials[index], whereindexis a statically decidable non-negative integer into the normalized ordered live-entry list;container.materials.get(entry_id), whereentry_idis a statically decidable non-empty string matched exactly within the same live-entry list.
get(entry_id) does not match content_ref, labels, or prefixes and does not fall back to another same-content entry. Local aliases may supply the selector or key when plan lowering can resolve them statically.
For runtime-generated identities, the unsuffixed content_ref is used when available. A collision uses the first available underscore ordinal, such as DNA_1, DNA_2, and so on. Existing IDs are opaque and are not rewritten; for example, a pre-existing DNA::1 remains valid but is not newly generated by this rule.
5.6 Cross-Protocol Binding Boundary
Rules:
letis protocol-local.- Each protocol declaration has an independent local name scope.
- Protocol parameter bindings are protocol-local to the callee frame created during plan lowering.
- File includes and library imports add protocol declarations to the active program namespace; they do not merge local
let, parameter, or repeat-binding names across protocols. - A protocol may reuse parameter and local names that are already used in another protocol, including imported or indirectly imported protocols.
- Material bindings are global within one runtime run.
- Protocol reference expansion does not create a separate runtime material namespace.
- Content identities are also global within one runtime run and follow runtime/event-log lifecycle.
include ProtocolName;inlining and qualified protocol-reference expansion both expose the referenced protocol body to downstream plan-time processing.- Protocol-local
letbindings do not automatically cross protocol boundaries. - Under strict binding validation, referenced/include'd protocol bodies may still contribute runtime-visible constructor-defined names to downstream semantic read checks.
- Protocol boundary exports follow the Chapter 9 protocol-return projection rules; returned runtime references do not collapse to plain text names.
5.7 Conformance Boundary
Frontend, planner, validator, typechecker, and runtime implementations must conform to these binding rules; they do not define separate binding behavior.
