You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
:string ASCII fast path — both directions of a :string now take
a typed check-and-store loop while the text is ASCII and hand the same
bytes to babel at the first char/byte ≥ 128, after a peek at the first
one so text that is non-ASCII from the start (CJK, say) allocates
nothing extra. Host-neutral, no wire change, the copy contract of
BOUNDARY §4 untouched — zero-copy :string stays refused. A 64 KiB
ASCII round trip drops from ~1 ms to ~0.32 ms on the benchmark host
(docs/benchmarks.md); non-ASCII text costs what it did. New v05.utf8-fastpath-boundary walks the seam (empty, DEL, code 128,
interior NUL, Latin-1 range, 4-byte chars first/last, fill-pointer and
base strings) through wordbag's echo on all three hosts, and the bench
gains an rx "count over 1 MiB" row: a real &str consumer.
Releases with audited assets — every v* tag builds the four
examples in the release profile on each required host (Linux x86-64,
macOS arm64, Windows x86-64), runs tools/rulisp-audit.sh over each
(Windows: the script prints SKIP, recorded as a gap in BOUNDARY §12),
and attaches the twelve blobs, named for load-blob-crate, to a
GitHub Release whose body is that version's CHANGELOG section. make check-versions holds every site that repeats the version to
one string; docs/releasing.md is the checklist around it.
MSRV — rust-version = "1.78" in the three crates, checked in CI
on exactly that toolchain over the macros, the runtime, rulisp and
the code the macros generate for wordbag.
Linux aarch64 — SBCL / Linux aarch64 (best-effort) on GitHub's
arm runners: the loader's aarch64 paths (the target check, the blob
suffix) execute for the first time. Promotion follows the written
procedure; the linux-arm64 release asset comes with it.
docs.rs front door — the three macros document the full attribute
grammar and the closed type vocabulary, every public item in rulisp
has a doc, the crate-level example is a compiled doctest, and CI builds
the docs with missing_docs and broken links as errors.
Docstrings, describe, and :doc — the REPL front door. Every
generated function and handle class now has a docstring synthesized
from the manifest (the Lisp call shape, the Rust signature, and which
condition an Err becomes); (describe crate) prints where the crate
came from, its generation, versions, dump hook, handle classes and every
export's signature. A glue crate's /// comments travel too: the macros
put them in the manifest as :doc (an enhancement key — older loaders
ignore it) and they lead the docstring. #. inside a :doc is text,
never code: the loader's reader runs with *read-eval* off.
:rulisp-version in the manifest, and the key-class rule (BOUNDARY
§11): a load-bearing manifest key raises :schema; an enhancement key
rides the ignore-unknown-keys rule. Every crate now records the rulisp
it was built with, and a loader whose major.minor is older signals rulisp-version-skew (a style-warning) and loads anyway. Stated
plainly, because this rule is new: a crate built with 0.4 or later that
declares on_dump loads cleanly on a 0.3 loader with its dump hook
silently dropped — :on-dump predates the rule and stays at :schema 1,
since a retroactive bump would refuse every newer crate on the 0.4.0
loaders that support it fully. Upgrade the loader.
docs/stability.md — what is stable and what 1.0 will promise: the
four versioned surfaces (Rust API, the 32-symbol Lisp API, the manifest
schema, the C ABI) and what breaks each; semver and deprecation policy;
host support defined as the required CI matrix with a written
promotion/demotion procedure; the manifest key-class rule; the 1.0 exit
criteria; the Quicklisp prerequisites. CI now proves the system loads
with no cargo on PATH.
Fixed
Docstrings named a symbol that does not exist — for a Result<_, Error> export the synthesized "Signals:" line said <crate>:rust-error; the condition is rulisp:rust-error itself. describe listed a ///-documented export by its first doc line
instead of its call shape; it now prints the call shape for every
export. Both surfaced when the docs audit compared usage.md's
transcript with the loader's real output.
Audit false positive on macOS — tools/rulisp-audit.sh matched an
inner _signal (_dispatch_semaphore_signal, imported by every macOS
artifact) as a signal import; only a leading underscore is Mach-O's now,
and the self-test checks the pattern both ways.
On CCL, lending a buffer to Rust stopped the world. CFFI's with-pointer-to-vector-data is ccl:with-pointer-to-ivector there,
whose body runs under without-gcing — so every :string, :bytes
and :vec argument suspended garbage collection for every thread for
the whole export, callbacks included (measured: 0 collections
completed on another thread during a 600 ms borrow; ~30 unpinned). The
loader now pins only long enough to memcpy into a heap buffer on CCL
and lends the copy. SBCL keeps the zero-copy borrow; ECL's pin never
inhibited GC. v05.pin-does-not-stop-the-world proves it on all three.
Changed
Docs claim audit — every capability, host and performance claim in
README and the docs pages (371 of them) now has a citation in
docs/claims.md or was corrected: the handle bullet (a second free is
refused, a racing free is deferred), "Scope (v0.1)" and the stale
"non-SBCL image dump" out-list, the quickstart's error-class rule and
its ~50 ns figure, usage.md's :target-check story and its Quicklisp
mention, benchmarks.md's 16× comparison, installation.md's
cargo-not-found and Windows cache-path rows. One support table (README
§Status) equals the required CI matrix; benchmarks.md carries SBCL,
CCL and ECL columns. CI now also loads rulisp from Quicklisp's
local-projects and load-blob-crates a downloaded release asset, as
the pages instruct.
The fuzzers can fail now.m4h.thread-race and m4h.random-op-sequence asserted only "no unexpected condition"; a
leaked in-flight count or a free that never reached Rust passed. Both
now reconcile every generation's live-handle and live-allocation
counters at the end (captured as wrapper closures, so generations
reloaded mid-run reconcile against their own library copy), take their
seed from RULISP_FUZZ_SEED (a workflow_dispatch input in CI) and
print it on failure. Verified by mutation: with half of all frees
skipped, the race fuzzer reports the leak. New m4h.reload-under-load
proves BOUNDARY §4's cross-reload claim — strings round-tripped by four
threads across three live reloads are released through their own
generation's dealloc; every generation ends at zero.
The fetch suite runs in CI (SBCL/Linux and CCL/Linux required; macOS
best-effort) — the 23 tests BOUNDARY §12 cites had only ever run on the
maintainer's machine. Its first run on CCL fixed two host assumptions in
the tests themselves.