Skip to content
This repository was archived by the owner on Aug 12, 2026. It is now read-only.

Commit 6e2cac3

Browse files
committed
S4 entered by its spike: the two deliverables meet, 6765 crosses the boundary
bb spike-s4 is the stage-entry check /next demands — the smallest thing that would fail if S4's premise were wrong, run before any design note. cljwit (the S3 emitter) compiles (defn fib ...) to a prod module, wasm-tools wraps it as a component with zero Canonical ABI machinery — 0007's scalar path, and the clj-exn tag export rides along without complaint — and cljwit.host (the S1 library) calls it from the JVM through FFM: (fib 20) = 6765 through the component boundary. The S4 survey proper (the Canonical ABI's string/list lowering as specced today, the Kotlin sample, 0007's dated claims re-verified) is the next unit, before a design note shapes the first real slice. Claude-Session: https://claude.ai/code/session_01XF5Hfq4Ca2N2XYEzWQQuHt
1 parent 908665a commit 6e2cac3

4 files changed

Lines changed: 74 additions & 6 deletions

File tree

‎bb.edn‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555
repl {:doc "The ClojureWit nREPL server (0029): evals compile to Wasm, run in the engine child"
5656
:task (run "clojure" "-M:repl")}
5757

58+
spike-s4 {:doc "S4 entry: cljwit compiles fib, wasm-tools wraps it, cljwit.host calls it. Needs `nix develop`."
59+
:task (run "clojure" "-M:dev" "-m" "cljwit.spike.s4-end-to-end")}
60+
5861
test {:doc "Unit tests (JVM)"
5962
:task (if (and (fs/exists? "test") (seq (fs/glob "test" "**.clj")))
6063
(run "clojure" "-X:test")

‎dev/cljwit/spike/s4_end_to_end.clj‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
(ns cljwit.spike.s4-end-to-end
2+
"The S4 entry spike: the project's two deliverables meet. `cljwit`
3+
(the S3 emitter) compiles `(defn fib …)` to a prod module,
4+
`wasm-tools` wraps it as a component (`0007`: scalar-only exports
5+
need no Canonical ABI lowering at all), and `cljwit.host` (the S1
6+
library) calls it from the JVM. Success is 6765 through the
7+
component boundary — the smallest thing that would fail if S4's
8+
premise were wrong. Needs `nix develop` (wasm-tools and
9+
CLJWIT_WASMTIME_LIB)."
10+
(:require [cljwit.analyze :as analyze]
11+
[cljwit.emit :as emit]
12+
[cljwit.host :as host]
13+
[clojure.java.io :as io]
14+
[clojure.java.process :as process]))
15+
16+
(set! *warn-on-reflection* true)
17+
18+
(def ^:private program
19+
['(defn fib [n] (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
20+
'(fib 20)])
21+
22+
(defn- sh! [& args]
23+
(let [p (apply process/start {:out :pipe :err :pipe} args)
24+
err (future (slurp (process/stderr p)))
25+
exit @(process/exit-ref p)]
26+
(when-not (zero? exit)
27+
(throw (ex-info (str "failed: " (pr-str args)) {:err @err})))))
28+
29+
(defn -main [& _]
30+
(let [dir (doto (io/file "target/spike-s4") (.mkdirs))
31+
wat (io/file dir "fib.wat")
32+
core (io/file dir "fib.core.wasm")
33+
emb (io/file dir "fib.embed.wasm")
34+
comp (io/file dir "fib.component.wasm")]
35+
(spit wat (emit/emit-module (analyze/analyze-forms program) :prod))
36+
(sh! "wasm-tools" "parse" (str wat) "-o" (str core))
37+
(sh! "wasm-tools" "component" "embed" "dev/resources/s4_fib.wit" (str core) "-o" (str emb))
38+
(sh! "wasm-tools" "component" "new" (str emb) "-o" (str comp))
39+
(println "component:" (str comp) (str "(" (.length comp) " bytes)"))
40+
(with-open [e (host/engine)
41+
a (host/compile e comp)
42+
i (host/instantiate a)]
43+
(println "exports: " (host/exports i))
44+
(println "signature:" (host/signature i "entry"))
45+
(let [v ((i "entry"))]
46+
(println "(fib 20) through the component boundary =" v)
47+
(when-not (= 6765 v)
48+
(println "✗ expected 6765")
49+
(System/exit 1))))))

‎dev/resources/s4_fib.wit‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// The S4 entry spike's world (doc/status.md): a cljwit-compiled module
2+
// exports exactly one scalar function, which is the boundary shape 0007
3+
// showed costs nothing.
4+
package cljwit:spike;
5+
6+
world fib-world {
7+
export entry: func() -> s64;
8+
}

‎doc/status.md‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,20 @@ _Short by design, and printed at every session start — so findings live in
9191
classify as errors, out-of-slice stays loud. The dev assembler
9292
entered `tools.json` and `bb check` materializes it (guarded
9393
`npm ci`) — `0026`'s promise kept on its named trigger. An editor
94-
connection (CIDER/Calva) remains a manual check. Next: **entering
95-
S4 starts with its survey** (`/next`'s stage rule; `0007` sized the
96-
stage — lift/lower over linear memory, `cabi_realloc`, resource
97-
tables — and `/survey`'s Kotlin sample is the closest prior art);
98-
S2's watcher waits for namespace loading, post-S3 compiler work
99-
either way.
94+
connection (CIDER/Calva) remains a manual check. **S4 is entered
95+
the way `/next`'s stage rule demands — by running what would fail
96+
if its premise were wrong**: `bb spike-s4` has the project's two
97+
deliverables meet for the first time — `cljwit` compiles
98+
`(defn fib …)` to a prod module, `wasm-tools` wraps it as a
99+
component (`0007`'s scalar path, zero Canonical ABI machinery, the
100+
tag export tolerated), and **`cljwit.host` calls it from the JVM:
101+
6765 through the component boundary** (2026-07-30). Next unit: the
102+
S4 survey proper — the Canonical ABI's string/list lowering as
103+
specced *today*, the Kotlin sample read closely, `0007`'s dated
104+
claims re-verified — before a design note shapes S4's first real
105+
slice (strings are also what the corpus's message comparisons and
106+
printing wait on). S2's watcher waits for namespace loading,
107+
post-S3 compiler work either way.
100108

101109
Done since the last update: `0016` `own<T>` handles, `0017` host imports
102110
(A–F), `0018` host-defined resources, `0012`'s `ex-data` contract shrunk to

0 commit comments

Comments
 (0)