-
released this
2026-10-08 20:51:57 +02:00 | 283 commits to main since this release- AOT: values travel in registers. A value is passed to and returned
from the runtime's out-of-line paths in registers instead of through
memory; a tight arithmetic loop no longer keeps its variables in memory
for a slow path it never takes.sum4.3 -> 1.3 s (now faster than the
interpreter); over all 55 benchmarks 4% faster (geomean). - AOT:
equal?is the interpreter's (shared code now): iterative, with
an interleaved memo, so cycles and shared structures stay cheap; the
equalbenchmark 0.52 -> 0.31 s.(equal? 0.0 -0.0)is now #f, as R7RS
says (equal?on numbers iseqv?); it answered #t. - AOT: bignums 2.3-3.5x faster. Division and integer square root are the
VM's algorithms (shared code now), and a bignum is one allocation instead
of two;pi0.56 -> 0.18 s,chudnovsky0.30 -> 0.14 s, level with the
interpreter. - AOT:
readfrom a file stops asking the file once it is exhausted.
Each call after the end made a system call that returned nothing;sum1
(100,000 numbers read 25 times) 1.46 -> 0.20 s. - AOT: a program's top level runs in order. Every top-level
define
ran before any top-level expression, so a define after aset!or a
string-set!saw the old value; compiled programs now run their forms as
written, as the interpreter does. - AOT: strings are one byte a character while every character is below
U+0100, four after -- the VM's representation, and its code.string
0.45 -> 0.11 s (faster than the VM's 0.15 s),tail-58%,bv2string
-25%, and text takes the same memory under both engines. Invalid UTF-8
read into a string decodes as the VM's does: a byte that starts no valid
sequence is the Latin-1 character it would be (it used to make the whole
string bytes-as-characters). - VM:
string-fill!andstring-copy!accept any character into a
string that held only Latin-1 ones; they refused with "a wide character
into a narrow string" (string-set!already widened). - AOT: large objects reuse their memory. Strings, vectors and
bytevectors over 2 KB were a fresh OS mapping each, zero-filled by the
kernel and unmapped when collected; freed blocks are now kept by size class
and reused, bounded by the heap's own size.string2.4x faster,array1
-19%, peak memory unchanged. - AOT: tail calls between compiled functions are jumps, and every
compiled function and closure takes its arguments in registers. A tail
call no longer grows the machine stack until it bounces: continuation-
passing code runs at the VM's speed (cpstak 16.8 -> 7.2 s), and closure-
heavy code gains broadly: conform -22%, lattice -16%, scheme -24%,
graphs -21% over the three steps (closure entries in registers, known
functions' arguments in registers, jumps); the last two steps alone are
about -3% geomean over all 55 runnable benchmarks. - Embedding:
lamp.native, host functions as plain Zig functions with
typed parameters, in a library:native.Library(.{ .name = "(my lib)", .Context = Engine, .natives = .{ .{ "name", zigFn }, ... } })and
Session.addLibrary(lib, &ctx). lamp reads each argument into its
parameter's type (integers including bignums that fit, floats, booleans,
strings, symbols, bytevectors, optional and rest arguments) and boxes the
result (lists from slices); refusals name the native and the argument.
A library's names are hidden until a unit imports it, and a session not
given it cannot (docs/EMBEDDING.md). Every native is in a library: the
oldSession.defineNative,defineTypeandembed.*native helpers are
gone. - Native value types in
lamp.native:native.Type(Vec3, .{ .name, .format, .equal, .eqv, .add/.sub/.mul/.div })in a library's.types;
natives take and returnVec3; a native type is a value, so*Vec3is a
compile error. Operator overloads are typed functions, the first whose
parameters the operands fit (vec3 * number,number * vec3). lamp.nativein AOT binaries: the same library declaration compiles
ahead of time.addSchemeExecutable's.native_types(a hand-written
.zonandpack_T/unpack_Thelpers) is replaced by.native_library, a
module whose root declarespub const libraries; the build generates the
descriptor and the bridge from it. Imports of a host library are enforced
as in the VM;+ - * /on native values the compiler could not prove
dispatch at run time; an unproven argument of the wrong type raises the
VM's error instead of undefined behaviour. A native type's.format,
.equaland.eqvwork in AOT binaries too (they printed
#<native-type-0>, andequal?was identity). AOT native values hold at
most 24 bytes; a larger type is a compile error there.lamp.nativeresults: an array, or a struct or tuple, is a list of its
elements or fields --[2]usizeis(3 14), a slice ofstruct { block, start, end }a list of(block start end).- A host native called with the wrong number of arguments now says so --
"f: expected 1 argument, got 0" -- instead of "unbound variable: f". - Errors are never printed by the VM. An unhandled
errororraise
used to writeerror: <message>to standard output and fault with "a
raise with no handler"; the message is now the fault's own text --
Session.errorMessagereturns it, andlampprints it on stderr as
before. Standard output stays the program's, which a host may be using.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- AOT: values travel in registers. A value is passed to and returned