- Swift 79.6%
- C 19.4%
- C++ 1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| CFFI | ||
| Host | ||
| klir | ||
| klnl/recipekl/parser | ||
| Native | ||
| Sources | ||
| Tests/recipeKLTests | ||
| README.md | ||
KLIR host and recipeKL implementation
Swift currently implements KLIR assembly, module loading, hashing, locks, linking, the VM, primitive host operations, and the generic libffi call bridge. Recipe grammar and evaluation live in KLIRT under klnl/recipekl/parser. String, dictionary, AST, platform, and Git policy modules are also in KLIRT. Host capability migration into KLIR is incomplete, and this README describes the current implementation rather than the intended final boundary.
swift build
swift test
.build/debug/klir run recipeKL/klnl/recipekl/parser/recipe.klirt klnlPm/platforms/linux/porter/debian/debian.klnl
.build/debug/klir compile recipeKL/klnl/recipekl/parser/recipe.klirt /tmp/recipe.klir
.build/debug/klir run /tmp/recipe.klir klnlPm/platforms/linux/porter/debian/debian.klnl
File commands create a .lock sidecar on first use and verify it thereafter. Locks cover the complete linked instruction model, including included functions and extern library paths and symbol declarations. They do not hash external library contents or host implementations. Compiled .klir artifacts use canonical JSON. After reviewing a source change, explicitly update its lock.
.build/debug/klir lock recipeKL/klnl/recipekl/parser/recipe.klirt
KLIR and externs
KLIR v2 supports local variables, shared per-run globals, functions, recursion, dynamic application and labels. Calls share a one million instruction budget and a maximum depth of 256. Checked arithmetic, invalid operands and exhausted limits report errors. Includes resolve relative to their including module, are deduplicated by resolved path and reject cycles and duplicate functions. Use one interpreter per concurrent execution.
klir 2
func twice value
load value
load value
add
return
end
const int 21
call twice 1
halt
Instructions include const, load, store, getglobal, setglobal, add, sub, mul, div, eq, concat, dup, pop, jump, jump_false, call, apply, return, halt and extern. Constants support integers, booleans, null and JSON quoted strings. apply consumes a function name and a list of arguments. KLIR functions take precedence over host externs.
Recipe source declares typed native functions directly. A library opens only when the first call occurs, and libffi dispatches the declared C ABI.
extern fn nativeSum(left: Int64, right: Int64): Int64 from "libexample.so" as "native_sum";
result = nativeSum(20, 22);
The supported C types are Int64, Int32, UInt64, UInt32, Bool,
CString, Pointer, and Void. Every argument and return type is explicit.
#include <stdint.h>
int64_t native_sum(int64_t left, int64_t right);
The standard libraries use soname-based linking for libc and libssh2. Other shared libraries must be present on the selected platform and target.
Native compilation
KLIRNativeCompiler.llvmIR directly lowers scalar KLIR instructions to LLVM basic blocks. It supports integer, boolean and null values, checked arithmetic, equality, local and global variables, branches, functions and declared integer C externs. Dynamic libraries load lazily in the native runtime too. Unsupported instructions and values fail compilation. There is no VM fallback inside generated executables.
The optional object backend uses swiftlang/swift-llvm-bindings, pinned in Package.swift. Its StringRef bridge passes generated IR to Native/LLVM.cpp, which parses and verifies the module and emits a host object through LLVM's target machine. Clang compiles the small C runtime and links the executable. Generated executables require the C runtime and system loader, but do not require Swift or LLVM at execution time.
A working Swift C++ interoperability toolchain, LLVM development headers, a shared libLLVM, matching C++ standard-library headers and Clang are required. Normal VM builds have no LLVM dependency. On a configured development system, use the helper to set the upstream binding's header variables.
KLIR_LLVM_PREFIX=/path/to/llvm scripts/native-swift build --scratch-path .build/native
.build/native/debug/klir native recipeKL/klir/arithmetic.klirt /tmp/arithmetic /path/to/clang
/tmp/arithmetic
KLIR_LLVM_BINDINGS_CHECKOUT optionally selects a local checkout instead of the pinned remote package. KLIR_CLANG supplies the CLI's default linker path. Select a C++ standard library matching LLVM's ABI and configure its include and library paths for your toolchain.
The LLVM bindings object backend could not be validated on the current development host. Swift 6.3.3's embedded Clang fails while importing the installed GCC 16 C++ standard-library overlay. The bridge C++ source compiles against LLVM 23, and tests independently compile the generated LLVM IR with Clang and execute scalar programs, dynamic externs and runtime error cases. They exercise the binding object backend instead when it is enabled and builds successfully.
LLVM text emission also works in the default build and can be inspected independently.
.build/debug/klir emit-llvm recipeKL/klir/arithmetic.klirt /tmp/arithmetic.ll
The generated native runtime supports strings, lists, objects, apply, bundled
source imports and the recipe parser's functional evaluation path. Some host
services remain VM-only, so native compilation rejects unsupported calls.
Recipe grammar
The entry module is klnl/recipekl/parser/recipe.klirt, with source supplied as its initial source variable. The full root README recipe example is a regression fixture. Its namespace and using declarations, named blocks, timer metadata, scoped enum members, callable bracket arguments, list and dictionary indexing, receiver join calls, build descriptors and normalization tables parse and evaluate in KLIR. Evaluation of that example requires a caller-supplied profile.install_prefix. The test supplies a profile block explicitly.
The lexer handles comments, Unicode strings, integer literals and scalar
offsets. Expressions support references, literals, lists, object bindings,
parentheses, member access, calls, unary minus, arithmetic, lambdas, named
functions, conditionals, matching, and functional list operations. Bindings
evaluate in source order and nested blocks can read outer bindings. Repeated
namespace declarations merge their contents. using brings a namespace's
members into the current environment. import "./module.klnl" as Module
evaluates a file module and exposes only declarations marked with export.
Recipe source declares typed, lazy native bindings with
extern fn name(value: Int64): Int64 from "libc.so.6" as "labs";.
The runtime resolves the library and symbol on first call, then passes the
declared signature through libffi. Supported scalar signatures include signed
and unsigned integers, booleans, strings, pointers, and void results. No
library-specific C wrapper is needed. Binding declarations remain part of the
recipe module and use the generic dynamic extern path.
Normalization descriptors preserve glob patterns, capture selectors, output
tokens and nested tables, including @apply[:base]($1). The KLIR normalizer
matches glob captures and applies nested rules. Timers, Git source descriptors
and build configuration have no execution effects during recipe evaluation.
fakehash is an explicit unverified placeholder, never a successful integrity
check. The type system checks basic annotations, aliases, record schemas, and
object literal fields returned through named interfaces. Generic inference
and exhaustive pattern coverage remain limited. Internal call inference still
has a dynamic fallback, so static soundness is unfinished.
Standard libraries
The project libraries in ../libs use explicit imports, exported recipeKL
functions, record interfaces, and typed libffi externs. libPOSIX binds libc
process, identity, file access, permission, and terminal calls. libSSH binds
libssh2 initialization functions. libWeb combines typed route functions
with direct libc socket calls. It does not yet provide a complete HTTP server
loop.
core/core/ast.klirt provides a persistent bottom-up ast.transform traversal with a named KLIR visitor. The core modules follow the README's library structure, with dedicated string, dictionary, command, platform and provider modules.