Sigmal Language Specification — Part 06
Top > Design docs > Core design > Part 06
1. Compilation Philosophy
Sigmal is a compiled language.
The core language is designed to:
- Elaborate to a minimal, explicitly typed core calculus
- Compile to LLVM IR, native machine code, or WebAssembly
- Require minimal runtime support
- Preserve totality guarantees for the pure fragment at compile time
Sigmal is not an interpreted, runtime-dependent language.
Compilation is ahead-of-time.
There is no required virtual machine or managed runtime.
2. Core-to-Backend Pipeline
Compilation proceeds conceptually in stages:
- Surface syntax parsing
- Elaboration to core calculus
- Const-normalization
- Type checking
- Structural lowering
- Target-specific code generation
Const-normalizable expressions are evaluated at compile time as part of semantics, not as an optimization.
All generated code must preserve:
- Purity
- Totality
- Structural equivalence
Runtime execution may be non-terminating only via explicit effect encodings and their interpreters; the compiler must not introduce hidden divergence.
3. Runtime Assumptions
Sigmal makes minimal runtime assumptions.
There is:
- No mandatory garbage collector
- No required runtime system
- No hidden global allocator
- No implicit world state
Reference-counted types are permitted.
Manual or explicit allocator models are allowed.
Freestanding execution must be supported.
A default allocator may be provided by standard libraries for convenience, including on WASM targets.
4. Memory Model
The memory model must support:
- Immutable data structures by default
- Efficient record layout
- Efficient inductive representation
- Predictable stack discipline
There must be no hidden unbounded recursion at runtime.
Since the language is total, recursion must be structurally justified or encoded through data.
Explicit effect interpreters may execute indefinitely (e.g., event loops), but such nontermination must never arise from the pure fragment.
Precise ownership and borrowing semantics are not yet specified.
However:
- Any ownership system must preserve purity.
- Any aliasing rules must be explicit.
- No implicit mutation semantics are introduced by the core language.
5. Representation Strategy
Backends must define representations for:
- Records (
&{ ... })
- Inductive types (
#{ ... })
- Symbols (
Sym)
- Universes (compile-time only)
Records should have:
- Deterministic field layout
- Efficient projection
- Predictable memory footprint
Inductive types must support:
- Tagged representation
- Efficient pattern matching
Symbol values may:
- Be interned
- Be represented as numeric identifiers
- Be represented as static handles
But their equality semantics must remain structural.
Symbol construction and representation are implementation-defined but must be deterministic for a fixed implementation and target.
Primary targets include:
Hosted Targets
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-gnu
- macOS
- Windows
- FreeBSD
Freestanding Targets
- wasm32-unknown-unknown
- Bare-metal environments
- Kernel-level contexts
Sigmal is designed to operate correctly in both hosted and freestanding contexts.
7. WASM Target Strategy
For wasm32-unknown-unknown:
- Sigmal emits a standalone WebAssembly module.
- No mandatory OS bindings are assumed.
- All external interaction occurs via explicit capability injection.
A default allocator may be provided for convenience.
The generated module should:
- Avoid reliance on WASI unless explicitly requested
- Expose only explicitly exported symbols
- Require no ambient environment
8. ABI Considerations
Each backend target must define:
- Calling conventions
- Record layout strategy
- Inductive representation strategy
- Symbol representation strategy
- Export/import model
ABI design must:
- Preserve semantic equivalence
- Be deterministic
- Avoid hidden runtime metadata
Stable ABI specifications may be defined per target.
The .std.abi module provides the standardized ABI interface; its contents and behavior may vary by target, subject to the per-target ABI specification.
9. Linking and Resolution
Module resolution occurs before compilation.
The resolver provides a deterministic top-level module value.
The top-level module value includes standardized .std.* modules. In particular, .std.core is always available (including freestanding targets). Some .std.* modules (e.g. .std.abi) are target-dependent within their standardized interface.
Compilation must:
- Not depend on filesystem semantics
- Not assume global namespaces
- Not embed implicit module paths
Cross-module linking must preserve structural type equivalence.
10. No Implicit World
Even in hosted environments:
- There is no implicit I/O model
- No hidden world parameter
- No ambient authority
Effects must be expressed explicitly via:
- Capability records
- Free constructions
- Explicit handler invocation
The runtime never injects a hidden context.
11. Determinism
Compilation must be deterministic:
- Given identical source, resolver configuration, and target triple
- The produced artifact must be semantically equivalent
Deterministic builds are a design goal.
Optimization passes must:
- Preserve totality
- Preserve semantic equivalence
- Not introduce observable nondeterminism
12. Optimization Constraints
Optimizations may include:
- Inlining
- Specialization of dictionary passing
- Dead code elimination
- Fusion of effect encodings
- Inductive representation optimization
However, optimizations must not:
- Break explicit capability discipline
- Introduce implicit instance resolution
- Alter structural type identity
Const-normalization is semantic and cannot be skipped.
13. Open Questions (Compilation & Runtime)
- Precise ownership and borrowing model
- Stable ABI specification format
- Cross-module linking semantics
- Deterministic build guarantees across toolchains
- Optimization strategies respecting totality proofs
- Specialization of effect encodings (e.g., free monad fusion)
- Symbol representation stability across compilation units within a fixed implementation/target (or with an explicit scheme identifier)
14. Summary
Sigmal’s compilation model is:
- Ahead-of-time
- Deterministic
- Minimal in runtime assumptions
- Freestanding-capable
- Pure
- Total
There is:
- No required GC
- No ambient world
- No implicit runtime system
- No hidden allocation model
All operational power arises from:
- Explicit capabilities
- Explicit data encodings
- Explicit interpretation
Sigmal aims to combine:
- Strong logical guarantees
- Low-level compilation targets
- Predictable runtime behavior
- Minimal runtime machinery
Sigmal.org - the calculus we can build on