Return to the language guide for lessons, or the language reference for implemented rules.
The language separates three kinds of work: describing values, changing an ordered ECS world, and asking a host to present that world. Rust owns language semantics and validation. A browser, native application or editor owns its platform resources and lifecycle.
Current boundaries
| Layer | Current responsibility |
|---|---|
| Parser and linker | Named UTF-8 sources, syntax, declarations, imports and trait signatures |
| Type checker | All bodies, inferred locals, method calls, fields, returns and typed component selectors |
| Interpreter | Checked values, calls, control flow, execution budgets and transactions |
| ECS | Stable entity IDs, typed component joins and sequential lifecycle callbacks |
| Spatial bridge | Validated geometry and supported rigid-body components |
| Host | Drawing, UI, playback, device permissions and resource access |
The built-in Sphere type describes a value type. Sphere { radius: 0.3 }
creates a value. spawn(Sphere { radius: 0.3 }) creates an entity with that component.
A renderer can then interpret the component as geometry. Keeping those steps
explicit makes pure data useful outside a scene and makes scene effects
inspectable.
The built-in schemas include geometry, transforms, material, rigid-body state, text, image, video, audio, streams and controls. Consult the generated catalog for each name’s support status. A resource contract is data exchanged with a host; it is not evidence that a camera was opened, media played or a device permission was granted.
Rust hosts register typed native functions through NativeRegistry, pass it to
compile_with_registry, then initialize a machine with the same signatures.
Compilation checks native calls, and the runtime rechecks host argument and
return values. A registered function must be pure and bounded: no I/O, device access,
external mutation or panics. The interpreter cannot roll back such effects or
preempt an unbounded native function. Keep those operations at an explicit host
boundary instead.
Type-system direction
The numeric foundation implements explicit widths, checked arithmetic and exact conversion in the SDK. The language retains literal digits and chooses a dtype during checking. Tensors reuse the same scalar rules over packed storage.
Keep type, trait and system separate. A type defines reusable data and methods, a
trait defines a behavior contract, and a system schedules work over matching
components. Giving a type an implicit update loop would hide when its behavior
runs and whether constructing an ordinary value changes the world.
Every function, method and callback body is statically checked, including unused
code. Locals have inferred fixed types and collection elements are homogeneous.
There is no permissive Any type in authored programs. Type checking establishes
expression and call contracts; runtime checks still handle world membership,
numeric bounds, allocation and termination budgets.
User-defined generic functions, access modifiers, and trait-associated types remain proposed extensions. Enums and exhaustive branching are implemented; see Enums and results.
Any expansion needs a precise interaction with nominal type identity, serialized values, module visibility and host bindings. Adding syntax without those contracts would make the editor promise more than the runtime checks.
Implementation choices
konjure-lang currently uses a bounded handwritten lexer and Pratt parser,
with Ariadne for terminal diagnostics. Chumsky is a candidate parser library;
it is not a dependency or a prerequisite for the public language contract.
Rust token spans, symbols and the built-in catalog drive both documentation
highlighting and the browser editor. The editor is a textarea with a token
overlay and source services, not a full language server.
The interpreter owns a small ordered ECS whose components are runtime-defined
type values. This avoids requiring a Rust type for each type in a loaded
program. Keep storage and scheduling behind that interface so a different ECS
implementation can be evaluated against the same tests when workloads justify
it. Rapier supplies the current rigid-body solver; libm supplies shared
numeric operations for native and WASM execution.
Systems and events
The scheduler runs explicit init, frame and done callbacks. A query selects
one type or trait, or joins several distinct concrete component types.
Bindings are typed and successful callbacks write component changes back as one
transaction. Lifecycle membership participates in rollback.
Optional and excluded components, trait joins, declared read/write sets, parallel scheduling and explicit dependency constraints remain proposed extensions. Each needs a defined ordering and conflict policy.
A typed event queue is also a possible next boundary: events would need source, delivery order, lifetime and replay semantics. Host calls into named functions do not already constitute that event system. Input, voice and assistant actions must retain their own authorization and completion evidence.
Debugging direction
The runtime exposes source spans, metadata, logs and bounded execution traces. The workbench can advance a tick and inspect state. A full source debugger would additionally need breakpoints, paused stack frames, local-variable inspection and statement-level stepping; these are not implemented by a tick control.
Likewise, deterministic language execution is narrower than a replay guarantee for all host behavior. External model inference, media timing, physical sensors and irreversible effects require separate recording and replay contracts.
Rendering and spatial work
The shared spatial bridge should remain the source for geometry and physics semantics. A new renderer should consume those outputs rather than reimplement language evaluation. Blender and Unity adapters, custom shaders, advanced materials, animation rigs and richer collision shapes remain separate adapter or runtime work where they are not explicitly supported.
A rendered moving object or successful rigid-body test does not establish room anchoring. Camera calibration, tracking, room alignment and device rendering need their own measured integration evidence.
Retained scene compiler
The Rust SDK’s declarative scene and node compiler remains available with its
existing examples. Its .konjure document output, unit suffixes and declared
actions are documented in the legacy scene format.
The programmable language does not silently reinterpret that source, and the
two formats should not be mixed within one program.
Data pipeline invariants
| Phase | Input | Output and invariant |
|---|---|---|
| Parse | Named UTF-8 source | Raw literal digits, explicit generic selectors and slice syntax; byte spans retained |
| Check | AST and Rust builtin declarations | Fixed scalar or tensor dtype on every checked expression, including unused bodies |
| Evaluate | Checked expressions and budgets | SDK scalar/tensor operations; allocation, shape and arithmetic errors abort the transaction |
| Present | Accepted state | Rust-validated geometry and typed buffer exports; the browser owns drawing and lifecycle |
For let t = [1, 2]:i32; print(t[-1]?);, parsing preserves the
selector and negative index. Checking assigns i32 to the elements and scalar
result. Execution builds eight packed bytes and normalizes -1 against the
length. Presentation receives the log 2; no JavaScript evaluates the program.
Validate this path with bash scripts/check-language.sh,
cargo test -p konjure-sdk --doc, and npm run test:web after rebuilding WASM.
The Rust-owned examples embedded in this site run in both native and WASM tests.