Sigil Releases
0.11.0
Register VM and self-hosting CPS compiler. This release adds a register-based virtual machine as an alternative backend for the CPS compiler introduced in 0.10.0. The new toolchain is opt-in via SIGIL_NEXT=1 and is 7-57% faster than the direct compiler across all benchmark categories. It is fully self-hosting — the CPS compiler running on the register VM can compile itself.
Register VM
Enable with SIGIL_NEXT=1. This activates both the CPS compiler and the register VM together. All stdlib modules compile, all ecosystem tests pass (zero regvm-specific failures across ~2,700 tests in 23 repos).
The register VM uses 32-bit fixed-width instructions with 3-address register operands. Key design features:
- Liveness-aware register allocation via CFG-based backward dataflow analysis
- Register coalescing eliminates redundant moves between registers
- Self-tail-call loop optimization converts recursive tail calls to JMP instructions
- Call window optimization overlaps caller/callee register frames
- Full continuation support — call/cc, delimited continuations, abort-to-prompt
- Exception handling — raise, guard, with-exception-handler
New source files:
regvm.c-- register VM interpreter (90+ opcodes)regvm.h-- register VM instruction encoding and opcodescps-emit-reg.c-- CPS IR to register bytecode emission
Performance
Benchmarks across 60+ tests (ratio = register VM time / direct compiler time, lower is faster):
| Category | Ratio | Improvement |
|---|---|---|
| Compute (fib, tak, ack) | 0.79-0.93x | 7-21% faster |
| Closures | 0.56-1.03x | Up to 44% faster |
| Tail calls | 0.76-0.96x | Up to 24% faster |
| String processing | 0.43-0.90x | Up to 57% faster |
| Allocation/trees | 0.80-1.01x | Up to 20% faster |
| Higher-order functions | 0.72-1.03x | Up to 28% faster |
| JSON encode/decode | ~1.0x | Parity (stdlib-bound) |
The register VM went from 3.3x slower (initial prototype) to consistently faster than the direct compiler through register allocation, coalescing, and call window optimizations.
Self-Hosting Bootstrap
The CPS compiler + register VM can compile itself. A two-stage bootstrap (stack VM binary compiles regvm binary, regvm binary recompiles itself) produces byte-identical output for 43/44 stdlib modules. This proves the new toolchain is correct enough to replace the direct compiler.
CPS Compiler Improvements
Fixes and enhancements to the CPS compiler from 0.10.0:
- Forward-referenced macro expansion during CPS conversion
- CFG-based liveness analysis for register and slot allocation
- Rest parameter slot allocation fix (was dropping the rest param)
- GC rooting for import set datums during module loading
- Module context save/restore across nested module loads
- call/cc stack reservation for lambda locals
- CPS emitter abort-to-prompt continuation routing for delimited continuations
- 19 primitive operation fallbacks added to register emitter
- Syntax transparency for register VM type predicates (car, cdr, null?, pair?, symbol?)
- Bignum arithmetic operations (mod, rem, neg, abs, number->string)
Other Changes
SIGIL_NEXT=1flag activates CPS + register VM togetherSIGIL_MODULE_MAX_MACROSincreased from 64 to 256- Benchmark suite added at
benchmarks/for release-to-release comparison
0.10.0
Experimental CPS compiler with optimization passes. This release adds a continuation-passing style intermediate representation to the compiler pipeline, sitting between macro expansion and bytecode generation. The CPS path is opt-in and does not change default compiler behavior.
CPS Compiler
Enable with SIGIL_USE_CPS=1. The CPS pipeline converts expanded S-expressions into CPS IR, runs optimization passes, then emits bytecode. All existing tests pass through the CPS path.
New source files:
cps.h-- CPS IR data structures and arena allocatorcps-convert.c-- S-expression to CPS conversioncps-emit.c-- CPS to bytecode emissioncps-opt.c-- optimization pass pipelinecps-dump.c-- CPS IR pretty-printer for debugging
Optimization Passes
Control the optimization level with SIGIL_OPT_LEVEL (0, 1, or 2). Individual passes can be disabled with environment variables.
-O1 (contification + dead code elimination):
- Contification: converts single-call closures in tail position into continuation jumps, eliminating closure allocation. Non-tail contification enabled for pure callees.
- Dead code elimination: removes unreachable continuations via BFS reachability analysis.
-O2 (adds inlining, constant propagation, capture minimization):
- Beta reduction / inlining: inlines small functions (10 or fewer CPS terms, called at most twice) at tail call sites.
- Constant propagation: folds fixnum arithmetic and boolean operations at compile time, eliminates constant branches. Overflow-safe using compiler builtins.
- Capture minimization: removes unused captures from closures after dead code elimination.
Pass ordering: contification, inlining, constant propagation, DCE, capture minimization. At -O2, the pipeline iterates up to 3 times for cascading opportunities.
Debugging
SIGIL_DUMP_CPS=1-- dump CPS IR before optimizationSIGIL_DUMP_CPS_OPT=1-- dump CPS IR after optimization- Individual pass toggles:
SIGIL_CPS_NO_CONTIFY=1,SIGIL_CPS_NO_DCE=1,SIGIL_CPS_NO_INLINE=1,SIGIL_CPS_NO_CONSTPROP=1,SIGIL_CPS_NO_CAPMIN=1
Other Changes
cond-expandimplemented as an expression form in the CPS convertercase-lambdaCPS expansion bypasses hygiene interaction bug in syntax-rules dispatch- Fix
sigil_apply{0,1,2,3}to reserve stack space for locals - Fix module context inheritance for closures created inside
define-librarybody - Fix
make-vectorto use native call instead of primitive opcode makedefault target now builds stdlib (previously requiredmake stdlib)
0.9.1
Transitive dependency resolution, version ranges, and lockfile support. The package manager now recursively resolves the full dependency tree — projects only need to declare their direct dependencies, and everything else is fetched automatically. This is the feature that makes the extracted ecosystem from 0.9.0 practical to use at scale.
Transitive Dependency Resolution
sigil deps install now recursively follows from-git dependencies. When a package is fetched, its package.sgl is read and its own dependencies are queued for fetching. Deduplication by package name prevents redundant fetches and cycles.
Before (0.9.0): if your project depends on press, and press depends on sigil-markdown, sigil-sxml, sigil-fp, and 7 other packages, you had to declare all of them manually in your package.sgl.
After (0.9.1): declare press and everything else resolves transitively. sigil-site went from 4 declared dependencies to 2, with 12 more resolved automatically.
Version Ranges
The from-git dependency form now supports an optional version: field with Cargo-style semver ranges:
(from-git url: "codeberg:sigil/sigil-sxml" version: "^0.9.0")Supported range syntax:
^0.9.0— minor-compatible:>=0.9.0, <0.10.0~0.9.0— patch-only:>=0.9.0, <0.9.1- Exact version:
0.9.0 *or omitted — any version (latest tag)
Resolution happens after cloning the bare repo: available tags are listed and the highest matching version is selected.
Lockfile
sigil deps install now writes sigil.lock with the exact commit hash for every resolved dependency (direct and transitive):
;; Auto-generated by sigil deps install. Do not edit.
(lock
(package name: "press" url: "codeberg:sigil/press" ref: "v0.1.0" sha: "abc123...")
(package name: "sigil-stdlib" url: "codeberg:sigil/sigil" ref: "v0.9.0" sha: "def456...")
...)sigil deps installreads the lockfile and uses pinned refs for reproducible installssigil deps updateignores the lockfile, re-resolves frompackage.sglranges, and writes a fresh lockfile--redirectsskips the lockfile entirely (neither read nor written) since local development overrides everything
Version Conflict Detection
When a transitive dependency requires a version range incompatible with an already-resolved version, sigil deps install errors with an actionable message suggesting you add an explicit pin in your package.sgl.
Bug Fixes
- Added
sigil/deps/semverandsigil/deps/lockto Makefile bootstrap modules
0.9.0
Lean core, ecosystem split, Zig everywhere. Sigil's monorepo sheds over 25,000 lines as libraries move to independent repositories with their own release cycles. The standard library is streamlined for AI-native development — pattern matching, transducers, R7RS compatibility, and functional programming utilities move to optional packages. Zig replaces GCC as the default C compiler for native builds, and Emscripten is replaced entirely by Zig + WASI for WebAssembly, enabling the Sigil REPL to run in browsers without heavyweight toolchain dependencies.
Ecosystem Split
The monorepo shrinks from 39 packages to 26. Extracted libraries are now independent repositories on Codeberg under the sigil/ organization, each with their own version tags, CI, and release cycle.
| Extracted Package | Repository | Description |
|---|---|---|
| sigil-peg | codeberg.org/sigil/sigil-peg | PEG parser combinators |
| sigil-sxml | codeberg.org/sigil/sigil-sxml | SXML to HTML/XML conversion |
| sigil-markdown | codeberg.org/sigil/sigil-markdown | CommonMark parser with YAML front matter |
| sigil-web | codeberg.org/sigil/sigil-web | Web application framework |
| sigil-css | codeberg.org/sigil/sigil-css | Programmatic CSS generation |
| sigil-match | codeberg.org/sigil/sigil-match | Pattern matching |
| sigil-fp | codeberg.org/sigil/sigil-fp | Functional programming utilities (compose, pipe, partial, threading macros) |
| sigil-transducers | codeberg.org/sigil/sigil-transducers | Composable transducers |
| sigil-r7rs | codeberg.org/sigil/sigil-r7rs | R7RS-small compatibility (scheme *) modules and SRFI-9 records |
| sigil-web-repl | codeberg.org/sigil/sigil-web-repl | Browser-based REPL (was sigil-playground) |
| press | codeberg.org/sigil/press | Static site generator (was sigil-publish) |
| sigil-site | codeberg.org/sigil/sigil-site | Official Sigil website |
| sigil-web-demo | codeberg.org/sigil/sigil-web-demo | Demo web application |
Extracted packages use from-git dependencies and dev-redirects.sgl for local development. All existing functionality is preserved — packages just live in their own repos.
AI-Native Standard Library
The standard library is streamlined based on a comprehensive audit of how AI agents actually use Sigil across 12 production codebases (117 libraries). Features with zero AI usage were moved to optional packages:
- Pattern matching (
match,match-let) — moved tosigil-match - Transducers (
mapping,filtering,transduce) — moved tosigil-transducers - Functional combinators (
compose,pipe,curry,partial,cut/cute) — moved tosigil-fp - Threading macros (
chain,->,some->) — moved tosigil-fp - R7RS compatibility (
(scheme base),(scheme write), etc.) — moved tosigil-r7rs - SRFI-9 records (
define-record-type) — moved tosigil-r7rs
The core language retains what AI agents naturally reach for: when/unless, keyword arguments, define-struct, guard/error, map/filter/apply/find, dicts, broadcast channels, and go concurrency.
Zig as Default Compiler
Zig is now the preferred C compiler across all build paths:
- Native builds:
detect-default-compilerandcompile-native-testspreferzig ccwhen available, falling back to systemcc/gcc - Cross-compilation: All eight platform targets use Zig (unchanged from 0.8)
- CI: Test and GC stress jobs use Zig via
with-zigwrapper - WebAssembly: New
webbuild config useszig cc -target wasm32-wasi(see below)
WebAssembly Without Emscripten
The web build target is completely rewritten. Emscripten is replaced by Zig targeting wasm32-wasi with a browser WASI polyfill:
- All 34 C source files compile with
zig cc -target wasm32-wasi - 3.3MB WASM binary (comparable to Emscripten output)
- Uses
@bjorn3/browser_wasi_shimfor WASI polyfill in browsers - New
__SIGIL_WEB__platform define replaces__EMSCRIPTEN__guards - Web build config:
sigil build sigil-web-repl --config web - Sigil REPL runs fully in the browser — expression evaluation, module loading, interactive input
sigil-docs Trimmed
sigil-docs is now a lightweight JSON lookup package for REPL inline help:
- Removed
(sigil docs commands)— thesigil docsCLI subcommand. Press handles all doc site generation now. - Removed
(sigil docs execute)— code block execution for doc validation - Removed dependencies on
sigil-markdownandsigil-sxml - Remaining:
(sigil docs lookup),(sigil docs search),(sigil docs types)— just reads the JSON files the compiler generates
sigil-cli Slimmed
The CLI drops several optional command modules and dependencies:
- Removed
sigil docscommand (handled by press) - Removed
sigil publishcommand (handled by press) - Removed
sigil changescommand (package deleted) - Removed dependencies:
sigil-docs,sigil-web,sigil-changes
0.8.0
Dynamic FFI and portable foundations. Sigil gains the ability to call any C library at runtime without writing glue code, a content-addressable build cache for faster incremental builds, and seven new packages spanning graphics, game development, calendar sync, and messaging. Cross-compilation now passes across all eight platform targets, and a new app management system makes it easy to install and run Sigil applications from git repos. With this release, Sigil reaches a stability point that enables us to begin decoupling libraries from the monorepo for independent releases and faster iteration.
Dynamic FFI
The headline feature. sigil-ffi lets you call C library functions directly from Scheme without writing any C glue code. Load shared libraries with ffi-open, look up symbols with ffi-ref, define call signatures, and invoke — all at runtime.
(import (sigil ffi))
(define lib (ffi-open "libm.so.6"))
(define c-sqrt (ffi-ref lib "sqrt" '(double) 'double))
(c-sqrt 144.0) ; => 12.0- Callbacks:
c-callbackcreates function pointers that call back into Scheme, enabling integration with event-driven C APIs like GUI toolkits - Pointer finalizers:
set-pointer-finalizer!attaches GC-triggered cleanup to foreign pointers (pass#fto clear) - dyncall backend: Replaced pure-C trampolines with dyncall for portable calling convention support, including mixed int/double argument signatures used by Cairo and similar libraries
Content-Addressable Build Store
A new sigil-store package provides content-addressable storage for build artifacts. C compilation results and static libraries are cached by content hash, so unchanged native code is never recompiled. Build outputs are properly rooted for GC, and the store integrates transparently with the existing build system.
App Management
New sigil app commands for installing, updating, and removing Sigil applications from git repositories:
sigil app install— clone a repo, resolve dependencies, bundle the app, and register any MCP serverssigil app list— show installed applicationssigil app update— pull latest changes and rebuildsigil app remove— clean up installed app and deregister MCP serverssigil app rollback— revert to the previous version
Supports --scope for MCP server registration, --env and secret-env for configuration, and graceful handling of missing environment variables.
New Packages
| Package | Description |
|---|---|
sigil-ffi | Dynamic FFI for calling C libraries at runtime via dyncall |
sigil-cairo | Cairo 2D graphics bindings — paths, transforms, surfaces, PNG loading, compositing operators, glyph rendering |
sigil-freetype | FreeType font loading and glyph metrics via FFI |
sigil-harfbuzz | HarfBuzz text shaping via FFI |
sigil-raylib | Raylib game development bindings — 2D shapes, text, input, collision, audio |
sigil-caldav | CalDAV calendar client with iCalendar parsing, event CRUD, recurrence expansion, timezone handling |
sigil-telegram | Telegram Bot API client with bot framework, MarkdownV2 formatting, inline keyboards, file uploads |
MCP Server Improvements
- Channel servers: New
(sigil mcp channel)module with helpers for building MCP channel-based servers (stdin/stdout transport) - Server-initiated notifications: MCP servers can now push notifications to clients, declare custom capabilities, and provide instructions
- Structured logging: MCP message handling uses
sigil-logwithlog-configure-from-args!for CLI integration - Better error reporting: Stack traces included in MCP tool error responses
HTTP Improvements
/jsonroute helpers now return JSON bodies on all HTTP status codes, not just 2xxurl-encode-valueandbuild-query-stringfor proper URL query parameter encoding- Fixed UTF-8 split across HTTP read chunk boundaries
- Fixed chunked transfer decoding for non-ASCII UTF-8 content
- Fixed
Content-Lengthusing character count instead of byte length - Fixed partial socket writes truncating large HTTP responses
- Unix domain socket server support via
unix-listen
CalDAV and iCalendar
Beyond the new sigil-caldav package, significant improvements to calendar handling:
- Timezone-aware datetime parsing with correct DST offset calculation via
mktime - Attendee parameter support for event creation
- Calendar name and timezone fields on
ical-event - RRULE recurrence expansion with
RECURRENCE-IDexception suppression - Date range filtering for non-recurring events in recurrence expansion
Formatter Performance
The code formatter was optimized from 30 seconds to under 2 seconds on large files (2800+ lines):
- Replaced struct-based tokens with raw vectors
- Inlined tokenizer hot loops with delimiter lookup table
- Zero-allocation form type matching
- Fixed tokenizer mishandling of delimiter character literals
Build System
- Content-addressable store for cached C compilation and static libraries
- Fixed build cache ignoring dependency changes
- Fixed false source file matches in module dependency resolution
- Fixed test runner dependency resolution for external packages
- Fixed build store hard-link self-copy corruption
- Hardened test runner against load errors
- Default release/prerelease configs switched to glibc dynamic linking (supporting FFI and dlopen)
- Static build configs available as
release-staticandprerelease-static
JMAP Improvements
jmap-email-countfor lightweight email counting without fetching messagesjmap-download-blobfor downloading JMAP blobs to files- Batch email move support
- Fixed send compatibility issues
Performance and Code Quality
- Fixed quadratic
string-join— now uses linear accumulation - Improved
list-unzipto use simultaneous traversal - Deduplicated
inspect-vectorandinspect-arraywith shared helper - Dict-based lookups in diagnostic module and watch module for faster type-guard and mtime resolution
Bug Fixes
- Fixed crash when
formatdisplays bignum values - Fixed segfault from unbounded macro export recursion
- Fixed preemptive yield escaping through
sigil_applyboundaries - Fixed
string->listto properly decode UTF-8 characters - Fixed
string-joinoverflow with large lists - Fixed double-encoded UTF-8 in build output and diagnostics
- Fixed YAML encoder to handle Sigil arrays
- Raised module binding limit from 2048 to 4096
- Fixed async stdin handling for MCP servers (pipe detection, fd-waiter integration)
- Fixed
char-ready?for pipes with async-aware stdin polling - Added Scheme module definition for
sigil-tlspackage - Fixed Windows cross-compilation:
fcntl/FD_CLOEXECguards replaced withSetHandleInformation - Fixed OpenBSD cross-compilation:
setvbufworkaround for opaqueFILEstruct in Zig headers - Fixed OpenBSD executable path resolution, poll fd limit, and partial write handling
- Set
FD_CLOEXECon TCP sockets to prevent child process inheritance
0.7.0
Parallelism and production readiness. Sigil gains multi-core execution, better I/O scalability, proper exception semantics, machine-readable procedure specifications, structured logging, and four new packages. With the stability and DX foundations from 0.5.0 and 0.6.0, this release focuses on the features needed to build and run serious applications.
Multi-VM Threading
The headline feature. Each thread-spawn creates a new VM with its own stack, heap, GC, symbol table, and module registry — zero shared mutable state, no locks needed. Threads communicate by message passing with automatic serialization/deserialization. parallel-map provides a high-level API for data-parallel workloads, partitioning work across N workers and collecting results.
Tail-Optimized Exception Handling
Replaced prompt-based exception handling with a dedicated VM-level handler stack. guard bodies now execute in true tail position, eliminating the 512-prompt practical limit. Deep recursive guard patterns (10,000+ iterations) work without overflow. Closure arity errors are now catchable by guard. Cross-context exception propagation works correctly through eval and load boundaries.
I/O Multiplexing
Replaced select(2) with epoll (Linux) and kqueue (macOS/BSD) behind the existing socket-select and fd-select APIs. Purely internal change with no Scheme API impact. Handles 200+ concurrent file descriptors efficiently.
Preemptive Yield Points
Yield checks at loop back-edges prevent CPU-bound tasks from starving other coroutines in the async scheduler. Default disabled — only activates when running inside with-async. Configurable interval via SIGIL_YIELD_INTERVAL environment variable.
Procedure Specifications
Machine-readable specs for procedure parameters and return values using real Scheme predicates. Specs use the inline (: ...) syntax placed as the first expression in a define or lambda body:
(define (add a b)
(: number? number? -> number?)
(+ a b))- Runtime checking: Optional predicate checks gated by the
sigil-checksfeature — zero cost in release builds - Predicate combinators:
any-of,maybe,list-of,none-offor expressive type constraints - Struct field annotations:
define-structfields accept type predicates, auto-generating specs for constructors, accessors, and mutators - Full coverage: 330+ specs across 35+ modules, all audited against conventions
- Tooling: Specs displayed in MCP search/exports output and generated API documentation
define-native Compiler Form
Declares bindings provided by native C code at runtime. Scheme modules can document and export native functions without fallback implementations, with optional specs and docstrings. Uses the new OP_DEFINE_IF_UNBOUND opcode to avoid overwriting native bindings registered at VM startup.
New Packages
| Package | Description |
|---|---|
sigil-tui | Immediate-mode terminal UI toolkit with native C grid, layout system, components, event parsing, and text input |
sigil-jmap | JMAP email client (RFC 8620/8621) with session discovery, mailbox operations, email query/send |
sigil-yaml | YAML parsing and serialization with block/flow collections, block scalars, anchors/aliases, multi-document |
sigil-log | Structured logging with levels, text/JSON output, configurable targets, and lazy macros |
sigil-tui-demo provides a chat client simulation exercising all TUI components.
HTTP Improvements
- Streaming HTTP download support with binary-safe reads
- File serving with Range request support and port positioning
Developer Tooling
- MCP server: Procedure specs shown in search and exports output
- API docs:
sigil docs apifixed and now displays spec signatures in generated documentation - Build system: Test compilation propagates build config features (e.g.,
sigil-checks)
Bug Fixes
- Fixed false positive capture corruption check in serializer
- Fixed Windows build: mingw macro collision with
_inlinefield name - Fixed Windows build: use
define-nativeforunix-connect(not available on Windows) - Fixed exception handler double-pop causing test runner segfault
- Fixed bootstrap compilation: replaced
whenwithifin%set-spec!
0.6.0
This release brings Sigil much closer to full R7RS compliance, adds a complete web development workflow with live browser reloading, and introduces three new packages: a PEG parsing library, an Org Mode parser, and an XMPP client. Developer tooling improves significantly with rich error diagnostics, an enhanced MCP server, and watch mode for incremental builds.
R7RS Compliance
The biggest area of work in this release. Sigil now supports nearly all of R7RS Small:
- Control flow:
dynamic-wind,dosyntax,guardprompt limit raised for deeper exception handling - Macros:
let-syntax,letrec-syntax - Modules:
include,include-ci, import set modifiers (only,except,prefix,rename) - I/O: Bytevector ports,
read-bytevector!,char-ready?,u8-ready? - Output:
write-sharedwith datum labels for circular structure printing - Feature detection:
features,cond-expand,syntax-error - Libraries:
(scheme time),(scheme process-context),(scheme repl)withinteraction-environment - Literals:
#u8(...)bytevector literal syntax in compiler and reader
Web Development
A full live-development workflow for web applications:
- Live reloading: nREPL server with SSE-based browser reload — edit code, see changes instantly
- Higher-level UI components: Expanded component library for sigil-web
- API refinements: Improved ergonomics for routing, form handling, and GET requests
- CSS generation:
css-selfor compound selectors - MCP browser tools: 7 new tools for live browser control (morph, navigate, execute JS, reload CSS, error overlay)
- Demo application: Vinyl Vault, a full CRUD demo showcasing the web stack
New Packages
| Package | Description |
|---|---|
sigil-peg | Parsing Expression Grammars with S-expression DSL, backtracking, and captures |
sigil-org | Org Mode parser producing SXML (headlines, metadata, source blocks, tables, lists) |
sigil-xmpp | XMPP client with STARTTLS, SASL (SCRAM-SHA-1/PLAIN), roster, presence, and MUC |
Supporting packages: sigil-crypto gains HMAC-SHA1 and PBKDF2-SHA1, sigil-tls adds tls-upgrade for STARTTLS.
Developer Tooling
- Rich error diagnostics: Structured error type hierarchy with Levenshtein-based "did you mean?" suggestions, source snippets with caret indicators in stack traces
- MCP server: Package-provided tool discovery, multi-form eval, format auto-fix, runtime doc fallback for undocumented exports, nREPL
describeandmodulesoperations - Watch mode:
sigil build --watchandsigil test --watchwith--format jsonsupport - Value inspection: New
(sigil inspect)module for structured introspection via nREPL and MCP - Project templates:
sigil initgainsweb-app,api-service, andmcp-tooltemplates - Docstring collection: Variable definitions now collect docstrings; native docs propagate through re-exports
Performance
- Dict lookup: FNV-1a hash cached on string keys, avoiding repeated computation
Library Improvements
- sigil-markdown: Inline parser rewritten using PEG grammars (~120 fewer lines, same behavior)
- sigil-json: Handle UTF-16 surrogate pairs in unicode escapes per RFC 8259
- sigil-docs: Re-export descriptions resolved from source module entries
Bug Fixes
- Fixed
SIGIL_NATIVES_MAXlimit (increased to 2048) for projects with many native bindings - Fixed
--no-colorflag in test runner - Fixed
git-fetchto include tags when updating cached bare repos - Fixed binary-safe nREPL wire protocol and SIGPIPE handling
- Fixed MCP format tool crash
0.5.0
This release is all about stability and correctness. A comprehensive audit of the garbage collector uncovered and fixed a critical write barrier gap, and GC stress testing now runs across the entire compiler pipeline. The HAMT dict implementation is complete, arbitrary-precision integers (bignums) are fully integrated, and every open issue has been resolved. Performance improves with inline caching and superinstructions, and the multimedia packages have been reorganized for flexibility.
GC Correctness
The most impactful change in this release: the tri-color write barrier was implemented but never called. Every mutation site that writes a heap pointer into an existing object could violate the tri-color invariant during incremental marking. This was the root cause of several hard-to-reproduce crashes.
- Write barriers: Added
sigil__gc_write_barrier()calls to all 13 heap mutation sites across vm.c and natives.c - Compiler rooting: Removed the
SIGIL_GC_DISABLE_DURING_COMPILATIONworkaround entirely. Fixed 46+ unrooted allocation sites in the compiler through systematic audit - GC stress testing:
SIGIL_GC_STRESS=1forces GC on every allocation, maximizing the window for bugs. All tests pass under stress
Performance
- Inline caching: Module binding lookups now use per-code cache arrays. On benchmarks, 3.3M hash lookups reduced to ~38K cold-start misses, with 100% steady-state cache hit rate
- Superinstructions: Peephole optimizer fuses 8 common opcode patterns (e.g., PUSHLOCAL+PUSHLOCAL, PUSH_CONST+ADD). Compiler-level fusion merges source location tracking with call opcodes
Arbitrary-Precision Integers
Integers larger than 2^47 now automatically promote to bignums instead of raising an error:
- Full arithmetic operations (add, subtract, multiply, divide, modulo, GCD)
- Comparison and bitwise operations
- Transparent promotion and demotion (bignum results that fit in a fixnum automatically demote)
- Serialization support in bytecode files
Dict Completeness
The HAMT (Hash Array Mapped Trie) implementation is now feature-complete:
- Printing: HAMT dicts display all entries with
displayandwrite - Equality:
equal?walks HAMT nodes for structural comparison - Collision handling: Fixed silent key dropping when hash collisions occur at the same node
- Removal: Proper structural
dict-removewith sharing, branch collapse, and HAMT-to-array demotion when count drops below 8
Error Handling
- Three
exit(1)calls in the module system replaced withsigil__vm_error()so the Scheme-level exception system handles them gracefully OP_ABORT_TO_PROMPTnow extracts real error messages from exception objects- Macro expansion errors propagate properly to the compiler
matchraises an error instead of printing a warning when no clauses match
Stack Traces
Procedures now track where they were defined. Stack traces show definition locations, making it easier to identify which function failed:
Stack trace (most recent call first):
0: my-helper
at utils.sgl:42:5Multimedia Packages
sigil-studio has been split into three independent packages for more flexible dependency management:
| Package | Description |
|---|---|
sigil-app | Windowing, input, application lifecycle (sokol_app) |
sigil-graphics | 2D rendering, image loading, font rendering (sokol_gfx, stb) |
sigil-audio | Sound effects and music streaming (sokolaudio, stbvorbis) |
sigil-studio remains as a meta-package that pulls in all three. New: playlist support with wait-music-end and play-playlist.
Build System
- Test harness generation for packages with native C dependencies
c-flagsfield on library definitions--profileflag for opcode-level performance analysis- Build safety: warns when replacing the running binary, errors on 0-byte output or missing target package
Test Coverage
Added test suites for 15+ packages that previously had none, including sigil-crypto, sigil-tls, sigil-web (routing, middleware, cookies, SSE, security), sigil-socket, sigil-process, sigil-mcp, sigil-jwt, sigil-websocket, sigil-markdown, sigil-format, and sigil-sxml. Error path tests added across the standard library.
Bug Fixes
- Fixed
assq-refto return values instead of aliasingassq; addedassv-ref - Fixed
number->stringprecision for exact IEEE 754 roundtrip (was losing digits on large flonums) - Fixed REPL
string-lengtherror after exception recovery - Fixed cross-module symbol resolution corruption
- Fixed bundle directory listing for bundled applications (VFS)
- Fixed
sigil-runre-import of(sigil core)before calling entry main - Fixed process port caching for stable repeated access
- Removed dead opcodes (
OP_LOAD_BYTECODE,OP_MAKE_CLOSURE_RT,OP_WRITE_BYTECODE_FILE)
0.4.0
This release makes Sigil leaner and faster. Native list operations cut compilation time in half, release binaries are 44% smaller, and a new profiling module helps you find bottlenecks in your own code. Macro authors get full hygiene support, and error handling improves with catchable VM errors and cleaner stack traces.
Breaking Changes
- sigil-web: Renamed UI components from
sigil-*tosg-*prefix (e.g.,sigil-buttonbecomessg-button) to mirrordata-sg-*attributes
Performance
Profiling revealed hotspots in list operations during macro expansion. Native C implementations of assoc, assq, assv, member, memq, and memv deliver significant speedups:
- Test suite runs 2x faster (33s → 15s)
- Module compilation 50% faster
- Release binaries 44% smaller (3.2MB → 1.8MB)
Macro Hygiene
Full hygienic macro support for syntax-rules and syntax-case. Macros now properly respect lexical scope, preventing accidental variable capture:
- Local and module-level hygiene
free-identifier=?for comparing identifiers during expansion#'reader shorthand for(syntax ...)expressions- New
(sigil syntax)module withsyntax->datum,datum->syntax,generate-temporaries
Error Handling
- Catchable VM errors:
guardcan now catch type errors, division by zero, and out-of-bounds access. Use the newvm-error?predicate in(sigil error). - Better stack traces: Errors display file paths with line and column positions. Anonymous lambda frames are filtered by default for cleaner output.
Profiling
New (sigil profile) module for performance analysis:
(with-profiling
(my-expensive-operation))
(profile-report) ; Shows call counts, timing, allocationsLibrary Improvements
- sigil-http: Keyword arguments for
make-http-serverandhttp-serve(port:,host:,handler:) - sigil-sxml: New
sxml->htmlfor converting SXML trees to HTML strings - sigil-version: New package for semantic version parsing and comparison
Bug Fixes
- Fixed source file names in error stack traces
- Fixed socket API consistency across platforms
- Fixed
with-api-docspath resolution in sigil-publish - Fixed sigil-irc package dependency declaration
0.3.0
This release focuses on modular compilation and improved application bundling. Native dependencies like SQLite, TLS, and crypto are now separate packages, so applications only compile what they actually use. The new sigil publish command provides a complete static site generation pipeline, and bundling gains script mode support for simpler deployments.
Breaking Changes
- sigil-http: API review changes including lazy TLS loading for compile-time independence
Modular Native Packages
Heavy native dependencies have been extracted from sigil-lib into separate packages:
| Package | Description |
|---|---|
sigil-sqlite | SQLite database bindings |
sigil-tls | TLS/SSL support |
sigil-crypto | Cryptographic functions |
Applications that don't use these features no longer compile them, resulting in smaller binaries and faster builds.
Application Bundling
- Script mode: Bundle single-file scripts with
sigil bundle script.sgl - Custom runtimes: Build tailored runtimes with only needed native modules
- Native package detection: Automatic entrypoint generation for native dependencies
- Production runtime (
sigil-run): Script mode support for bundled applications
New Command: sigil publish
Static site generation with a pipeline-based architecture:
(site output-dir: "dist"
pipeline: (list markdown-processor syntax-highlighter)
watch-patterns: '("content/**/*.md" "templates/**/*.html"))Site operators integrate with the threading macro for composable pipelines.
Library Improvements
- sigil-json: Added
json-get-infor nested access - sigil-stdlib: New conveniences and predicates from API review
- sigil-args: New features and comprehensive documentation
- sigil-test: Native test build integration and new assertions
- sigil-build: Consolidated shared code and improved test support
Bug Fixes
- Fixed temp file creation on Windows (
sigil-lib)
0.2.0
This release focuses on improving the idiomatic functional programming style of Sigil. New modules for sequences and function composition make it easier to write clean, composable code. Pattern matching gains dict, vector, and struct support, and several APIs have been refined for consistency.
Breaking Changes
- Module renamed:
(sigil exceptions)→(sigil error) - API changes:
mapandfor-eachnow operate on single lists only. Uselist-mapandlist-for-eachfor multi-list operations. - Renamed functions:
remove-directory→delete-directory,channel-close→channel-close!
New Modules
| Module | Description |
|---|---|
(sigil random) | Random number generation, shuffling, and sampling |
(sigil seq) | Polymorphic sequences and transducers |
(sigil array) | Efficient fixed-size collections |
(sigil fn) | Function composition: compose, pipe, partial, juxt |
Pattern Matching Improvements
- Dict pattern matching:
(match d ((dict a: x b: y) ...)) - Vector literal syntax:
#(a b c)patterns - New forms:
match-lambda,match-lambda* - Struct and vector pattern support
Other Enhancements
- Unicode case conversion:
char-upcase,char-downcase,string-upcase,string-downcasewith full Unicode support - HTTP client: Added chunked transfer encoding support
- CLI:
sigil cli upgradenow uses native HTTP client (no curl dependency) - Dict utilities:
dict-select,dict-rename-keys,dict-get-infor nested access - Threading:
some->macro for nil-short-circuiting pipelines
0.1.0
The first public release of Sigil, a practical Scheme for building standalone applications.
NOTE: Sigil is still highly experimental and changing fast, but don't let that stop you from trying it out and providing feedback!
Highlights
- Standalone executables: Bundle your application with all dependencies into a single binary (~1-2MB base size)
- Fast startup: Bytecode VM with incremental garbage collection
- Hygienic macros: Full
syntax-ruleswithsyntax-casesupport - Batteries included: JSON, HTTP client/server, sockets, process management, and more
Core Runtime (sigil-lib)
The foundation: bytecode VM, S-expression reader, incremental mark-sweep GC, and native bindings for I/O, filesystem, networking, and process management.
Standard Library (sigil-stdlib)
Nearly complete R7RS base with practical extensions:
(sigil core)- Pattern matching, records, delimited continuations, array/dict utilities(sigil math)- Trigonometric, exponential, and bitwise operations(sigil string)- String manipulation utilities(sigil path)- Cross-platform path handling(sigil fs)- Filesystem operations(sigil io)- Extended I/O primitives(sigil process)- Process spawning and pipes(sigil time)- Date/time operations(sigil exceptions)- Exception handling(scheme *)- R7RS compatibility modules
Build System (sigil-build)
Package-based workspace architecture with:
- Dependency resolution across workspace packages
- Multiple build configurations (dev, debug, release)
- Executable bundling with embedded bytecode archives
CLI Tools (sigil-cli)
Development workflow commands:
sigil build- Compile packages and dependenciessigil bundle- Create standalone executablessigil test- Run test suitessigil repl- Interactive developmentsigil format- Code formattingsigil changes- Release managementsigil cli- Install and manage Sigil installations
Libraries
| Package | Description |
|---|---|
| sigil-json | JSON parsing and serialization |
| sigil-http | HTTP/1.1 client and server with TLS support |
| sigil-socket | TCP/UDP networking |
| sigil-websocket | WebSocket client and server |
| sigil-sqlite | SQLite database bindings |
| sigil-git | Git repository operations |
| sigil-repl | Interactive REPL with readline |
| sigil-nrepl | Network REPL for editor integration |
| sigil-test | Test framework with assertions |
| sigil-format | S-expression code formatter |
| sigil-markdown | Markdown parsing with frontmatter |
| sigil-sxml | SXML document construction |
| sigil-ansi | Terminal colors and formatting |
| sigil-args | Command-line argument parsing |
| sigil-hooks | Extensible hook system |
| sigil-mcp | Model Context Protocol server |
| sigil-jwt | JWT token encoding and verification |
| sigil-docs | Documentation generation |
| sigil-web | Web application framework |
| sigil-publish | Static site generation pipeline |
| sigil-irc | IRC client |
| sigil-css | CSS generation from Sigil code |
Note: Library APIs may change between minor releases until 1.0. Core modules (sigil-lib,sigil-stdlib) aim for stability.
Platform Support
| Platform | Architecture | Status |
|---|---|---|
| Linux | x86_64, aarch64 | Primary development platform |
| macOS | arm64, x86_64 | Builds and runs, not yet extensively tested |
| Windows | x86_64 | Builds and runs, not yet extensively tested |
| FreeBSD | x86_64 | Cross-compiles, not yet tested on real hardware |
| OpenBSD | x86_64 | Cross-compiles, not yet tested on real hardware |
| NetBSD | x86_64 | Cross-compiles, not yet tested on real hardware |
| Web/WASM | - | Runs in browser via Emscripten |
Known Limitations
- R7RS Small coverage is not yet complete; full compliance planned for a future release
- Limited SRFI coverage
Getting Started
See the Getting Started guide for installation and first steps.