IronKernel.Tool
0.3.0
See the version list below for details.
dotnet tool install --global IronKernel.Tool --version 0.3.0
dotnet new tool-manifest
dotnet tool install --local IronKernel.Tool --version 0.3.0
#tool dotnet:?package=IronKernel.Tool&version=0.3.0
nuke :add-package IronKernel.Tool --version 0.3.0
IronKernel
IronKernel is a dialect of John N. Shutt’s Kernel for .NET 10.
Kernel is Scheme-like but more homoiconic: combiners and environments are first-class, and the core abstraction is the operative (vau) rather than macros.
This tree is a hybrid CLR runtime: programs are analyzed to a Core IR and compiled to CLR delegates while preserving runtime combiner dispatch, with a trampolined CPS interpreter for full Kernel semantics (vau, first-class eval/environments, call/cc, shift/reset).
Build & test
dotnet build
dotnet test
Requires the .NET 10 SDK.
CI & releases
- CI (
.github/workflows/ci.yml) runsdotnet teston Ubuntu for pushes/PRs tomain/master. - Release (
.github/workflows/release.yml) triggers on tagsv*(e.g.v0.3.0): tests on Linux, then publishes self-contained single-file binaries forlinux-x64,win-x64,osx-arm64, andosx-x64, attached asironkernel-<rid>.tar.gz(binary +kernel.ikr/promises.ikr).
Website
The promotional site and docs live in website/ and target ironkernel.org (Iron = I run on .NET; the .net TLD was taken).
# local preview
python3 -m http.server -d website 8080
GitHub Pages deploys from website/ via .github/workflows/pages.yml (enable Pages → “GitHub Actions” in repo settings, then point the domain’s DNS at GitHub).
Getting started
With the .NET 10 SDK:
dotnet build
dotnet run --project IronKernel -- Examples/hello.ikr
For a release archive, extract it and run ./IronKernel (IronKernel.exe on
Windows) from the extracted directory. The archive includes the standard
library files required by the runtime.
See the getting-started guide for the full
REPL, script, and package workflow, and Examples/README.md
for runnable programs.
Projects and packages
.ikproj files are MSBuild-compatible IronKernel projects. Install this
repository's tool package—or invoke the same commands through the IronKernel
binary—to create and manage projects:
ik new app hello
cd hello
ik run
ik test
ik restore
ik add Acme.IronKernel.Http 1.2.0
ik add Npgsql 9.0.0 --clr
ik tree
ik build
ik pack
Projects use standard NuGet PackageReference entries and commit
packages.lock.json. Restored IronKernel package sources under
ironkernel/src/**/*.ikr load before project source; declared CLR runtime
assemblies are loaded for interop.
Public packages use NuGet.org initially. See
docs/packages.md for package layout and
ADR 0001 for the
extension and ecosystem decision.
REPL
dotnet run --project IronKernel
Loads kernel.ikr and promises.ikr, then presents an interactive prompt. Type quit to exit.
Run a script
dotnet run --project IronKernel -- path/to/program.ikr arg1 arg2
# Equivalent explicit form:
dotnet run --project IronKernel -- run path/to/program.ikr arg1 arg2
Script mode loads kernel.ikr and promises.ikr in a fresh environment, then
binds command-line arguments to args. Evaluation and startup errors are written
to stderr and produce a non-zero exit code.
Compile to an IKC package
dotnet run --project IronKernel -- compile path/to/program.ikr -o program.ikc
dotnet run --project IronKernel -- run program.ikc
Compilation validates and packages the source without executing it. An IKC1
file is an IronKernel package containing the source payload; it is not a CLR
assembly. At run time IronKernel loads the standard library, compiles the payload
to delegates, and executes it. Omitting -o writes <source-name>.ikc.
Use --help for all commands and --version for the runtime version.
Diagnostics
Parse and runtime failures include the source path, line and column, offending line, and a caret range. CLI modes write diagnostics to stderr and return a non-zero exit code:
program.ikr:2:1: Getting an unbound variable: 'missing'
(missing 42)
^^^^^^^^^^^^
Capability profiles and generated CLR bindings
IronKernel can construct root environments with different host authority:
| Profile | Host access |
|---|---|
minimal |
Kernel evaluation and data primitives only |
safe |
Minimal profile plus reviewed generated CLR wrappers |
unrestricted |
Raw CLR reflection, source loading, and host I/O (default) |
dotnet run --project IronKernel -- --profile safe Examples/safe-clr.ikr
Safe wrappers such as Console.write-line, String.concat, and Math.sqrt
are generated from manifests/safe-clr-bindings.json.
The generator resolves one exact public static signature and emits direct typed
calls—there is no runtime overload selection or reflection in the generated
path:
dotnet fsi tools/generate-clr-bindings.fsx \
manifests/safe-clr-bindings.json IronKernel/Generated/Bindings.Safe.fs
Child environments intersect their parents' capability sets. Imported or stolen
interop values still check the authority of the environment where they are
invoked, so copying a binding cannot grant host access. See
docs/capabilities.md for the security model and limits.
Tagged handlers and async
Prompt tags are unforgeable runtime values. Tagged shift selects the nearest
matching reset, while prompt installs a deep effect handler:
(define request (make-prompt-tag))
(prompt request
(lambda (value k) (resume k (+ value 1)))
(+ 1 (perform request 40)))
; ⇒ 42
perform supplies the operation value and a one-shot resumption to the handler.
Resuming reinstalls the same tagged handler; attempting to resume twice is an
error. Existing untagged (reset body) and (shift handler) remain multi-shot
and backward compatible.
The unrestricted profile also provides (task-delay milliseconds value) and
(await-task task). Task callbacks only publish an outcome; Eval.runAsync
resumes the trampoline serially rather than evaluating on a CLR callback thread.
See Examples/effects-async.ikr.
Operative contracts and partial evaluation
Contracts are optional combiner metadata. They distinguish raw operative operands from evaluated applicative arguments and validate fixed value shapes:
(define double (lambda (x) (+ x x)))
(contract double applicative (number) number pure #t)
(define raw (vau operands _ operands))
(contract raw operative (any) any pure #t)
Supported shapes are any, number, integer, string, boolean, atom,
list, prompt-tag, and resumption. The final fields declare the effect
summary (pure or effectful) and whether the combiner is intended to be
inlineable.
User contracts are asserted metadata and are never executed by the compiler.
Reviewed primitive contracts are certified; pure literal calls such as
(+ 20 22) may be folded behind a binding-cell/version/contract fingerprint
guard. Rebinding the operator selects the untouched generic combination before
any operand effects occur. Dynamic eval, control effects, CLR calls, and async
operations remain residual.
VS Code extension and playground
The extension in editors/vscode/ provides IronKernel syntax
highlighting, snippets, run/compile commands, Problems diagnostics, and a
playground backed by the real CLI. Build a local VSIX with:
cd editors/vscode
npm install
npm run package
The playground requires a trusted workspace because IronKernel programs can
invoke .NET APIs. See the extension README for
runtime discovery and .ikr file-association guidance.
CLR namespaces and Clojure-style calls
Under the unrestricted profile you can open namespaces and use short type names:
(clr-open System System.IO)
(clr-alias SB System.Text.StringBuilder)
(Guid/NewGuid) ; static method
(StringBuilder.) ; constructor
(.Append sb "hi") ; instance method
(.-Length sb) ; field / property
(clr-type Path) ; first-class System.Type value
Full names such as System.Console remain valid. Ambiguous short names after
clr-open raise an error; use clr-alias or a full name to disambiguate.
Syntax
IronKernel keeps a LISP / Kernel S-expression surface (parentheses are intentional). Notable surface forms:
| Form | Meaning |
|---|---|
(…) |
Lists / combinations |
[…] |
Vectors |
(a & b) |
Improper / dotted lists (& instead of .) |
:keyword |
Keywords |
#t #f #inert |
Booleans and inert |
λ / ϝ |
Aliases for lambda / vau |
Architecture
| Module | Role |
|---|---|
Parser.fs |
FParsec → homoiconic LispVal |
Ir.fs / Analyze.fs |
Core IR + binding-aware guarded analysis |
Eval.fs |
Trampolined CPS interpreter (TCO-capable) |
Compiler.fs |
Guarded Expression-tree compiler with generic fallback |
Emit.fs |
IKC package emit / load |
Runtime.fs |
Primitive operatives & applicatives |
kernel.ikr |
Stdlib (lambda, let, modules, …) |
Compiler fast paths are guarded by stable binding-cell identity and version. Rebinding or shadowing a primitive invalidates its guard before any specialized work begins, so execution falls back to ordinary Kernel combiner dispatch.
License
Apache 2.0 — see COPYING.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.