diff --git a/web/examples/quotes.sh b/web/examples/quotes.sh index d7d26a5..44f6465 100644 --- a/web/examples/quotes.sh +++ b/web/examples/quotes.sh @@ -29,6 +29,13 @@ want "flan usage" "$("$FLAN" 2>&1 | sed -n 2p)" # calc-me, the first acceptance program, still answers what the page says. want "calc-me" "$("$FLAN" run "$root/calc-me.flan" '1 + 2 * (3 - 0.5) / 2')" +# The sand hash. The page shows it twice — native and wasm32 — and the claim is +# that the two agree; only the native half is cheap enough to check here. +want "sand hash" "$("$FLAN" run "$root/test/programs/sand-headless.flan")" + +# The two cross-target refusals, in the compiler's own words. +want "run --target" "$("$FLAN" run "$here/hello.flan" --target=wasm32-wasi 2>&1)" + # The refusal and diagnostic messages quoted in the prose and in the # "Not implemented yet" table. for pair in \ diff --git a/web/index.html b/web/index.html index 5a2682c..55889f1 100644 --- a/web/index.html +++ b/web/index.html @@ -905,6 +905,8 @@ is generated; a Flan string crosses as ptr+len, exactly as it is stored.
1
+That is 1.0, printed by the same rule as before.
+declare-c names the C library's own function in the C library's own
signature, and the compiler writes the wrapper. This is what raylib's package is made
of — one line per binding:
So the boundary has one wrapper per binding, each flattening the aggregates: a struct
returns through an out-pointer, a struct argument is passed by pointer, and clang
classifies all of it, per target, for free. flan shim <file> prints
-the whole generated file:
(defstruct Vector2 [x f32 y f32])
@@ -1170,8 +1173,19 @@ uses; it is program-scoped, so in sand you write sim/settle and not
Native x86-64 is the development target. --target=wasm32-wasi produces a
module, and the headless sand acceptance program prints the same 64-bit hash under it as
-natively, byte for byte, at -O2 and at -O0. That is the
-milestone the RNG is written in Flan for.
+it does natively:
+
+$ flan run test/programs/sand-headless.flan
+2256461126764447066
+$ flan build test/programs/sand-headless.flan --target=wasm32-wasi -o sand.wasm
+$ node --no-warnings test/wasm-run.mjs sand.wasm
+2256461126764447066
+
+That number is the whole point of writing the RNG in Flan rather than calling libc's:
+a grid hash is only a regression test if the sequence is byte-identical on both targets.
+It holds at -O2 and at -O0. The wasm side needs a
+wasm32 builtins archive — from wasi-sdk, or emscripten's substituting for
+it — and the compiler names every path it looked in when it cannot find one.
Dev and release builds are deliberately different. --dev means
indirection cells and -rdynamic, which is what exports the cells for a loaded
@@ -1179,9 +1193,16 @@ module to bind to; release builds call directly, emit constants as constants, an
the folding back. Dev builds are not pruned by reachability, because what a REPL may
redefine next is not a function of what has been called so far.
-Some things are refused by name rather than half-supported:
---dev with a wasm target and flan run --target=, both because a
-cross-built module is not something this host can dlopen or exec.
+Some things are refused by name rather than half-supported, and both cross-target
+refusals say why:
+
+$ flan run hello.flan --target=wasm32-wasi
+flan run: --target is refused — a cross-built module is not something this host
+can exec. Use flan build --target=... and a wasm runtime.
+
+$ flan build hello.flan --dev --target=wasm32-wasi
+wasm32: --dev is native only — the reload path is dlopen, which wasm32 has no
+equivalent of
Build time for calc-me.flan is about 110ms, of which the frontend — read,
parse, load, check, emit — is under 10ms. Every C translation unit goes through an object