TinyFX architecture
TinyFX is one language with three executable target paths:
- Native Rust execution. The
tfxCLI compiles source to a bytecode program, executes it in the Rust VM, and renders through the Rust wgpu runtime in a winit window. - Browser Rust/WASM execution. The same bytecode program and Rust runtime are compiled to WebAssembly and render to a WebGPU canvas.
- Generated TypeScript/WebGPU execution. The compiler emits readable
TypeScript plus compiler-authored WGSL and physical pass descriptions. That
program runs against the JavaScript core in
@tinyfx-lang/runtime; it does not load the TinyFX VM or a TinyFX WASM runner.
The target choice changes execution and host ownership, not the language front end. Parsing, checking, GPU legality, capture analysis, and WGSL generation have one Rust source of truth.
End-to-end shape
TinyFX sources + imports + embedded standard library
|
v
checked Frontend
(AST, definitions, types, semantic side tables, stage facts)
/ \
v v
VM-specific lowering generated-program lowering
bytecode + WGSL blueprints structured CPU IR + physical GPU blueprints
| |
v v
native or WASM VM readable TypeScript/ESM
self-contained .tfxb JavaScript CPU/WebGPU coreWGSL is generated while lowering compile-time shader and compute sites. The runtime receives generated WGSL, layouts, binding descriptions, and packing plans; it does not recompile TinyFX ASTs during a frame.
The two lowerers deliberately remain siblings. The generated-program IR is
not an intermediate representation for VM bytecode, and VM bytecode is not a
serialized form of generated TypeScript. Both consume the checked
Frontend and preserve the checker’s decisions rather than
resolving calls, defaults, coercions, fields, captures, or resources again.
See Compiler internals and The VM and artifacts.
Workspace map
| Area | Primary location | Responsibility |
|---|---|---|
| Compiler | crates/tinyfx-compiler | Lexer, parser, checking, stage analysis, WGSL, generated-program IR, TypeScript emission, formatter, IDE analysis, operation catalog |
| Virtual machine | crates/tinyfx-vm | Bytecode lowering, interpreter, heap/GC, serialized-program format, host boundary |
| Rust renderer | crates/tinyfx-runtime | wgpu resource management, frame encoding, environment/camera, overlay, UI backends, assets, native media |
| CLI | crates/tinyfx-cli | Filesystem imports, diagnostics, artifact emission, winit application and watch mode |
| WASM bindings | crates/tinyfx-wasm | Separate source-facing compiler/editor and bytecode-facing runner bindings |
| Language server | crates/tinyfx-lsp | LSP protocol adapter over compiler IDE analysis |
| Browser facade | packages/tinyfx | Browser-facing compile/check/editor API and lazy WASM runner loading |
| JavaScript runtime | packages/tinyfx-runtime | Generated-program CPU/WebGPU core, shared platform contracts, browser platform, WASM bridge |
| Vite integration | packages/tinyfx-vite | Build-time .tfx-to-VM modules, assets, declarations, and invalidation |
| Browser application | apps/playground | Interactive VM/WASM playground and generated-program example browser |
| VS Code extension | editors/vscode | TextMate grammar and language-client process management |
| Standard library | std | TinyFX source compiled into every program |
Rust dependency direction is:
tinyfx-cli / tinyfx-wasm -> tinyfx-runtime -> tinyfx-vm -> tinyfx-compiler
tinyfx-lsp -> tinyfx-compilerThe compiler has no wgpu dependency. This keeps type checking, editor analysis, and compiler-only WASM builds independent of graphics initialization.
The browser boundary
The browser has two independent execution cores:
- The WASM core contains the Rust VM and Rust renderer. It accepts an already compiled bytecode artifact.
- The generated JavaScript core interprets neither bytecode nor TinyFX source. It executes compiler-emitted CPU code and compiler-authored physical WebGPU blueprints.
Both implement the same browser-core shape and are driven by one shared
BrowserPlatformSession. That session owns request-animation-frame
scheduling, canvas backing-store size and device-pixel-ratio updates, focus,
visibility, pointer/keyboard/text input, cleanup, browser media, and optional
Canvas2D paint composition. The execution cores own only program semantics and
rendering. This prevents browser lifecycle policy from drifting between the
WASM and generated-program paths.
The browser facade in packages/tinyfx keeps the compiler/editor
WASM separate from the runner. Calls such as check, completion, hover, and
source compilation load only the compiler artifact. run() first
compiles valid source to bytecode, then dynamically imports the runner, so an
invalid program never downloads the larger execution artifact.
The generated TypeScript target instead imports
@tinyfx-lang/runtime/core. Its optional browser embedding imports
the platform boundary separately. The runtime package intentionally exposes
subpaths rather than a catch-all root module so applications own only the
layers they need.
Shared contracts and artifacts
TinyFX has several separately versioned contracts. They should not be treated as one global format revision:
.tfxbis the self-contained VM artifact. It contains bytecode, strings, functions, type/runtime metadata, WGSL blueprints, layouts, and packing plans.- Program metadata is a stable, compiler-owned entry/per-file view used by source tooling and compiled artifacts.
- Generated TypeScript declares the capabilities it needs from the JavaScript core.
- Physical render and compute descriptions are strict compiler-to-WebGPU DTOs. New capabilities are added through explicit shapes rather than silently widening old shapes.
- Builtin wire keys have append-only order because serialized bytecode refers to those keys.
The practical rule is simple: consumers validate the contract they receive, and a source artifact should be rebuilt when its reader reports an incompatible format.
Where to go next
- Compiler internals explains the checked Frontend and the two lowerers.
- The VM and artifacts describes bytecode, the host boundary, and
.tfxb. - Renderer and browser platform covers shader blueprints, frame encoding, and the JavaScript WebGPU path.
- Testing and validation maps claims to the tests that support them.