Lexer / Parser
Tokens are produced on demand. The parser builds a source-located AST and interns names for cheap identity comparisons downstream.
Language design / Runtime
A small bytecode-interpreted language that gives C programs a familiar, table-centered layer for dynamic data, automation, and rapid iteration.
make_adder := fun(base) {
ret fun(value) {
ret base + value
}
}
add_ten := make_adder(10)
result := add_ten(32)Compilation path
A compact C-like surface backed by a complete compiler pipeline and slot-based virtual machine.
02 / Intent
C remains the right tool when a system needs direct control over memory, layout, the operating system, or native performance. It becomes less pleasant when the work is mostly dynamic data, strings, configuration, automation, or logic that needs to change quickly.
Elf is not meant to replace C. It supplies the smaller dynamic layer I wanted inside native programs without asking a C programmer to adopt an unfamiliar surface grammar, object model, or large runtime ecosystem.
03 / Architecture
Elf compiles source before execution. Each stage makes the program more explicit, while temporary compiler structures and persistent runtime data have deliberately separate lifetimes.
Tokens are produced on demand. The parser builds a source-located AST and interns names for cheap identity comparisons downstream.
Scopes, declarations, constants, closure captures, defers, labels, and jumps become a smaller and more explicit representation.
Slot allocation, frame sizing, branch patching, constant pools, and source maps are finalized into one executable module.
Slot-based frames execute bytecode while garbage-collected closures and native C functions share one callable value model.
04 / Engineering decisions
C owns the host, runtime, and systems that require direct control. Elf handles the flexible layer where short iteration cycles and dynamic values matter more than native machinery.
Every value lives in one contiguous array. A separate open-addressed table maps keys to those array indices, allowing the same structure to behave as an array, map, or record without duplicating value storage.
Plain brackets now address the contiguous array view, while dot access addresses keyed values. Changing the earlier syntax removed a local convenience in favor of a rule that remains predictable across the language.
AST, IR, and module builders live in scratch storage and disappear after compilation. Only finalized bytecode, constants, source, and runtime objects survive in the owning state.
05 / Current reality
Elf is currently 0.2.0-dev and officially supports Windows x64. Its syntax and API remain unstable; parameter annotations and defaults are not yet enforced, runtime failures lack a protected-call boundary, compiled modules cannot be independently unloaded or serialized as portable bytecode, and the VM has no JIT. Garbage collection is synchronous mark-and-sweep, and there is no package ecosystem yet.