From c1018d87c51d6cb639498741a218984fb212bd29 Mon Sep 17 00:00:00 2001
From: Joseph Ferano
Date: Sat, 26 Sep 2026 18:13:56 +0700
Subject: [PATCH] Every reference to the removed .flan files is updated,
generated.fln's stale banner line is regenerated, and the ported .fln files
read like handwritten Flan.
---
README.md | 4 +-
examples/core-2d-camera.fln | 28 +++--
examples/core-3d-picking.fln | 16 +--
examples/core-basic-window.fln | 2 +-
examples/core-delta-time.fln | 2 +-
examples/core-input-gamepad.fln | 8 +-
examples/core-input-gestures-testbed.fln | 8 +-
examples/core-input-gestures.fln | 4 +-
examples/core-input-keys.fln | 4 +-
examples/core-input-mouse.fln | 2 +-
examples/core-input-multitouch.fln | 8 +-
examples/core-input-virtual-controls.fln | 20 ++--
examples/core-scissor-test.fln | 2 +-
examples/core-window-flags.fln | 12 +-
examples/core-window-should-close.fln | 13 +--
examples/core-world-screen.fln | 4 +-
examples/digits.fln | 10 +-
examples/models-box-collisions.fln | 10 +-
examples/shapes-basic-shapes.fln | 6 +-
examples/shapes-collision-area.fln | 14 +--
examples/shapes-following-eyes.fln | 8 +-
examples/text-codepoints-loading.fln | 10 +-
examples/text-input-box.fln | 8 +-
examples/text-rectangle-bounds.fln | 13 +--
examples/text-writing-anim.fln | 10 +-
examples/textures-fog-of-war.fln | 14 +--
examples/textures-image-generation.fln | 2 +-
examples/textures-image-processing.fln | 18 +--
examples/textures-mouse-painting.fln | 18 ++-
lib/build.ml | 2 +-
lib/dev.ml | 4 +-
lib/load.ml | 4 +-
lib/prelude.ml | 8 +-
lib/session.ml | 2 +-
runtime/flan_dyn.c | 4 +-
sand.fln | 4 +-
test/programs/pkg-hidden-main.flan | 4 +-
test/programs/pkg-shared.flan | 4 +-
test/programs/raylib-codepoints.flan | 2 +-
test/programs/raylib-image-processing.flan | 2 +-
test/programs/virtual-controls-headless.flan | 2 +-
test/test_acceptance.ml | 41 +++----
test/test_dev.ml | 6 +-
test/test_flan.ml | 5 +-
test/test_session.ml | 47 ++++----
test/test_syntax.ml | 4 +-
test/test_web.ml | 8 +-
vendor/agent/flan_agent.web.c | 6 +-
vendor/edn/edn.fln | 22 ++--
vendor/edn/provide.fln | 113 ++++++++++++-------
vendor/edn/read.fln | 8 +-
vendor/json/json.fln | 18 +--
vendor/json/provide.fln | 78 ++++++++-----
vendor/raylib/bindings | 20 ++--
vendor/raylib/generated.fln | 2 +-
vendor/raylib/headers | 6 +-
vendor/raylib/modes.fln | 16 +--
vendor/raylib/raylib.fln | 52 ++++-----
vendor/raylib/vector.fln | 16 +--
web/examples/quotes.sh | 4 +-
web/index.html | 4 +-
61 files changed, 423 insertions(+), 373 deletions(-)
diff --git a/README.md b/README.md
index 28161a4b..836afe5f 100644
--- a/README.md
+++ b/README.md
@@ -66,7 +66,7 @@ dune exec ./bin/main.exe -- build web/examples/hello.flan -o hello
The falling-sand demo uses raylib:
```sh
-dune exec ./bin/main.exe -- run sand.flan
+dune exec ./bin/main.exe -- run sand.fln
```
Once you are iterating regularly, put the built executable on your `PATH` if
@@ -77,7 +77,7 @@ you want to use the shorter `flan` commands shown below.
Start a long-lived development session:
```sh
-flan dev sand.flan
+flan dev sand.fln
```
The program runs normally and publishes a local socket beside the source file.
diff --git a/examples/core-2d-camera.fln b/examples/core-2d-camera.fln
index 07a4a6ce..e88eca53 100644
--- a/examples/core-2d-camera.fln
+++ b/examples/core-2d-camera.fln
@@ -2,22 +2,22 @@
;;;;
;;;; examples/core/core_2d_camera.c. Needed no new binding at all, which is
;;;; the reason to port it: Camera2D, begin-mode-2d and end-mode-2d have been
-;;;; in vendor/raylib/raylib.flan since the beginning and nothing in the
+;;;; in vendor/raylib/raylib.fln since the beginning and nothing in the
;;;; corpus had ever passed a whole Camera2D across the FFI on a frame's path.
;;;; Two Vector2s, a float and a float, by value, sixty times a second — the
;;;; acceptance table pins that layout with get-screen-to-world-2d, and this
;;;; is the same struct going into the call that actually draws with it.
;;;;
-;;;; The hundred buildings are a `defonce` of fixed arrays rather than a Vec:
+;;;; The hundred buildings are a `once` of fixed arrays rather than a Vec:
;;;; a global cannot hold a Vec (docs/PORTING.md §3) and does not need to here,
-;;;; because the count is a constant in the C too. `(array n T)` is the zeroed
+;;;; because the count is a constant in the C too. `array(n, T)` is the zeroed
;;;; fixed array, and the C's `= { 0 }` is exactly that.
;;;;
;;;; get-random-value comes from the generated half of the bindings. It is on
;;;; no frame's path — it runs once, before the loop — and its Flan face is
;;;; the C one, so docs/PORTING.md §1's rule does not reach it.
;;;;
-;;;; One deliberate difference from the C: `(- camera.rotation 1.0)` and the
+;;;; One deliberate difference from the C: `camera.rotation - 1.0` and the
;;;; clamp after it are written with the prelude's `clamp` macro rather than
;;;; two ifs. It is the same arithmetic; the C spells it out because C has no
;;;; clamp.
@@ -38,7 +38,7 @@ fn main() -> ()
rl/init-window(screen-width, screen-height,
"raylib [core] example - 2d camera")
defer rl/close-window()
- player = rl/Rectangle{.x 400.0 .y 280.0 .width 40.0 .height 40.0}
+ player = rl/Rectangle{.x 400.0, .y 280.0, .width 40.0, .height 40.0}
buildings = array(max-buildings, rl/Rectangle)
build-colors = array(max-buildings, rl/Color)
;; The skyline: each building is as wide as the last one left room for, so
@@ -47,13 +47,13 @@ fn main() -> ()
for i in range(max-buildings)
let w = f32(rl/get-random-value(50, 200))
h = f32(rl/get-random-value(100, 800))
- buildings[i] = rl/Rectangle({.x -6000.0 + f32(spacing), .y (f32(screen-height) - 130.0) - h, .width w, .height h})
+ buildings[i] = rl/Rectangle{.x -6000.0 + f32(spacing), .y (f32(screen-height) - 130.0) - h, .width w, .height h}
spacing += i32(w)
- build-colors[i] = rl/Color({.r u8(rl/get-random-value(200, 240)) .g u8(rl/get-random-value(200, 240)) .b u8(rl/get-random-value(200, 250)) .a 255})
+ build-colors[i] = rl/Color{.r u8(rl/get-random-value(200, 240)) .g u8(rl/get-random-value(200, 240)) .b u8(rl/get-random-value(200, 250)) .a 255}
;; A fresh Camera2D is all zeroes and a zoom of 0 makes the transform
- ;; singular, so the zoom is the one field that must be set — raylib.flan's
+ ;; singular, so the zoom is the one field that must be set — raylib.fln's
;; own comment on the struct says so.
- camera = rl/Camera2D({.offset rl/Vector2{.x f32(screen-width) / 2.0, .y f32(screen-height) / 2.0} .target rl/Vector2{.x player.x + 20.0, .y player.y + 20.0} .rotation 0.0 .zoom 1.0})
+ camera = rl/Camera2D{.offset rl/Vector2{.x f32(screen-width) / 2.0, .y f32(screen-height) / 2.0} .target rl/Vector2{.x player.x + 20.0, .y player.y + 20.0} .rotation 0.0 .zoom 1.0}
rl/set-target-fps(60)
until rl/window-should-close()
;; Update
@@ -61,16 +61,14 @@ fn main() -> ()
;; right, which is the else-if and not an accident.
if rl/is-key-down(:key-right)
player.x += 2.0
- else
- if rl/is-key-down(:key-left)
- player.x -= 2.0
+ elif rl/is-key-down(:key-left)
+ player.x -= 2.0
;; The camera follows the player's centre.
camera.target = rl/Vector2{.x player.x + 20.0, .y player.y + 20.0}
if rl/is-key-down(:key-a)
camera.rotation -= 1.0
- else
- if rl/is-key-down(:key-s)
- camera.rotation += 1.0
+ elif rl/is-key-down(:key-s)
+ camera.rotation += 1.0
camera.rotation = clamp(camera.rotation, -40.0, 40.0)
camera.zoom += rl/get-mouse-wheel-move() * 0.05
camera.zoom = clamp(camera.zoom, 0.1, 3.0)
diff --git a/examples/core-3d-picking.fln b/examples/core-3d-picking.fln
index 708c2eb3..ffdcc627 100644
--- a/examples/core-3d-picking.fln
+++ b/examples/core-3d-picking.fln
@@ -5,7 +5,7 @@
;;;; anywhere upstream that uses Ray and RayCollision without also loading a
;;;; Model, so it is the only way those two structs get a caller at all.
;;;;
-;;;; Picking is the round trip the corpus was missing. core-world-screen.flan
+;;;; Picking is the round trip the corpus was missing. core-world-screen.fln
;;;; already runs get-world-to-screen — a point in the scene to a pixel. This
;;;; is the inverse and it is a different shape: a pixel does not name a
;;;; point, it names a *line* through the scene, which is what a Ray is, and
@@ -13,7 +13,7 @@
;;;; something, which is what a RayCollision is. Two structs the package could
;;;; not describe, for one operation that cannot be written without them.
;;;;
-;;;; What was added, all in vendor/raylib/raylib.flan:
+;;;; What was added, all in vendor/raylib/raylib.fln:
;;;;
;;;; - `Ray` — two Vector3s, origin and direction.
;;;; - `RayCollision` — a C `bool`, a float and two Vector3s. This is the
@@ -21,7 +21,7 @@
;;;; `hit` is one byte and `distance` is four, so there are three padding
;;;; bytes between them that a permutation destroys. BoundingBox's two
;;;; Vector3s are interchangeable and nothing would catch swapping them.
-;;;; - `BoundingBox` — shared with examples/models-box-collisions.flan.
+;;;; - `BoundingBox` — shared with examples/models-box-collisions.fln.
;;;; - get-screen-to-world-ray and draw-ray, hand-written beside
;;;; get-world-to-screen and the cube draws for the reasons `bindings`
;;;; gives: the first reads the same camera as its inverse, and the second
@@ -53,12 +53,12 @@ once ray: rl/Ray
once collision: rl/RayCollision
;; The same centre/size to min/max conversion as in
-;; examples/models-box-collisions.flan. Written out here rather than shared
+;; examples/models-box-collisions.fln. Written out here rather than shared
;; because an example is a single file the reader can follow end to end.
;;
;; It used to be eight expressions of field arithmetic; it is the half-extent
;; subtracted and added, which is what the C means, now that the package
-;; carries vector arithmetic — see vendor/raylib/vector.flan. That file
+;; carries vector arithmetic — see vendor/raylib/vector.fln. That file
;; exists because raymath is `static inline` and has no symbol to bind, so
;; v3-sub and v3-add are Flan and not C.
fn box-around(centre: rl/Vector3, size: rl/Vector3) -> rl/BoundingBox
@@ -69,14 +69,14 @@ fn main() -> ()
rl/init-window(screen-width, screen-height,
"raylib [core] example - 3d picking")
defer rl/close-window()
- camera = rl/Camera3D({.position rl/Vector3{.x 10.0 .y 10.0 .z 10.0} .target rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .up rl/Vector3{.x 0.0 .y 1.0 .z 0.0} .fovy 45.0 .projection :projection-perspective})
+ camera = rl/Camera3D{.position rl/Vector3{.x 10.0 .y 10.0 .z 10.0} .target rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .up rl/Vector3{.x 0.0 .y 1.0 .z 0.0} .fovy 45.0 .projection :projection-perspective}
cube-position = rl/Vector3{.x 0.0 .y 1.0 .z 0.0}
cube-size = rl/Vector3{.x 2.0 .y 2.0 .z 2.0}
;; Both start zeroed, which is the C's `= { 0 }`. A zero Ray draws as a
;; degenerate line at the origin and a zero RayCollision has hit false, so
;; neither needs a "not yet" flag beside it.
- ray = rl/Ray({.position rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .direction rl/Vector3{.x 0.0 .y 0.0 .z 0.0}})
- collision = rl/RayCollision({.hit false .distance 0.0 .point rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .normal rl/Vector3{.x 0.0 .y 0.0 .z 0.0}})
+ ray = rl/Ray{.position rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .direction rl/Vector3{.x 0.0 .y 0.0 .z 0.0}}
+ collision = rl/RayCollision{.hit false .distance 0.0 .point rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .normal rl/Vector3{.x 0.0 .y 0.0 .z 0.0}}
rl/set-target-fps(60)
until rl/window-should-close()
;; Update. The first-person controls only run while the cursor is
diff --git a/examples/core-basic-window.fln b/examples/core-basic-window.fln
index 5a663392..61050807 100644
--- a/examples/core-basic-window.fln
+++ b/examples/core-basic-window.fln
@@ -6,7 +6,7 @@
;;;;
;;;; The one structural difference from the C is the loop: the C writes
;;;; `while (!WindowShouldClose())` and Flan has `until`, which is the same
-;;;; thing without the negation. sand.flan does likewise.
+;;;; thing without the negation. sand.fln does likewise.
;;;;
;;;; `defer` closes the window. It is function-scoped — it runs when `main`
;;;; returns and not at the end of any inner block — which is exactly what the
diff --git a/examples/core-delta-time.fln b/examples/core-delta-time.fln
index 7a2aeb79..f7a341f0 100644
--- a/examples/core-delta-time.fln
+++ b/examples/core-delta-time.fln
@@ -19,7 +19,7 @@
;;;; here rather than instead of it, so the file is not quietly asserting that
;;;; the original was right.
;;;;
-;;;; The two circle positions are `defonce`s for the usual reason: they are
+;;;; The two circle positions are `once`s for the usual reason: they are
;;;; state between frames and a `let` inside the loop would reset them.
import rl "vendor:raylib"
diff --git a/examples/core-input-gamepad.fln b/examples/core-input-gamepad.fln
index 4ffa356d..e9b40bd8 100644
--- a/examples/core-input-gamepad.fln
+++ b/examples/core-input-gamepad.fln
@@ -21,7 +21,7 @@
;;;; branches that matched on it are the artwork's and are gone with it.
;;;;
;;;; **The VIBRATE button is drawn and inert.** SetGamepadVibration is the one
-;;;; call in the C this refuses to bind, and vendor/raylib/raylib.flan already
+;;;; call in the C this refuses to bind, and vendor/raylib/raylib.fln already
;;;; carries the paragraph saying why: its arity differs between raylib
;;;; versions with no 5.5 header here to settle it, so a guess is a corrupted
;;;; stack frame rather than a link error — and the symbol in libraylib.so.550
@@ -51,7 +51,7 @@ fn deadzone(v: f32, limit: f32) -> f32
if v > 0.0 - limit and v < limit then 0.0 else v
;; The triggers rest at -1 rather than 0, which raylib does not normalise —
-;; see the note on GamepadAxis in vendor/raylib/raylib.flan. So their deadzone
+;; see the note on GamepadAxis in vendor/raylib/raylib.fln. So their deadzone
;; is a floor near the resting end and not a band around the middle.
fn trigger-deadzoned(v: f32) -> f32
if v < trigger-deadzone then -1.0 else v
@@ -162,7 +162,7 @@ fn main() -> ()
if rl/is-key-pressed(:key-right)
gamepad += 1
let axis-count = min(6, rl/get-gamepad-axis-count(gamepad))
- let vibrate-rect = rl/Rectangle({.x 10.0, .y 90.0 + 20.0 * f32(axis-count), .width 75.0, .height 24.0})
+ let vibrate-rect = rl/Rectangle{.x 10.0, .y 90.0 + 20.0 * f32(axis-count), .width 75.0, .height 24.0}
;; Draw
rl/with-drawing:
rl/clear-background(rl/raywhite)
@@ -225,7 +225,7 @@ fn main() -> ()
;; has type i32 while its sibling has type () and the `if` will not
;; typecheck — "expected i32, found ()". Both arms end in a
;; draw-text here, which is the tidy way out; where that is awkward a
- ;; trailing `(do)` is the other.
+ ;; trailing `()` is the other.
let b = rl/get-gamepad-button-pressed()
if b >= 0
rl/draw-text("DETECTED BUTTON: ", 10, 430, 10, rl/red)
diff --git a/examples/core-input-gestures-testbed.fln b/examples/core-input-gestures-testbed.fln
index efc95e60..33d8bc69 100644
--- a/examples/core-input-gestures-testbed.fln
+++ b/examples/core-input-gestures-testbed.fln
@@ -24,11 +24,11 @@
;;;; The rule the refusal came from is unchanged and worth keeping: an enum is
;;;; its own type in the checker, so `:tpa` is an error at the call site
;;;; instead of a number that is wrong later, and a bare integer still does not
-;;;; fit an `rl/Gesture` parameter. `(i32 g)` does not weaken that — it is
+;;;; fit an `rl/Gesture` parameter. `i32(g)` does not weaken that — it is
;;;; named, and it is at the site. The rule was "an integer must not arrive
;;;; silently", not "an integer is dangerous".
;;;;
-;;;; The `!= 4` stays a keyword comparison, `(not (= g :gesture-hold))`. That
+;;;; The `!= 4` stays a keyword comparison, `not g == :gesture-hold`. That
;;;; one was never a range test; it is a single member, and the C's 4 is a
;;;; magic number the keyword reads better than.
;;;;
@@ -48,9 +48,9 @@
;;;;
;;;; **No local fixed arrays.** The C declares `char gestureLog[20][12]` and
;;;; `Vector2 touchPosition[32]` inside main. A `let` binding takes no type
-;;;; annotation, so a fixed array can only be a top-level `defonce` or a literal
+;;;; annotation, so a fixed array can only be a top-level `once` or a literal
;;;; with every element written out — thirty-two Vector2s, here. They are
-;;;; `defonce`s, which is what the C's storage amounts to anyway.
+;;;; `once`s, which is what the C's storage amounts to anyway.
;;;;
;;;; The log itself came out simpler than the C's: the names are compile-time
;;;; literals, so a slot holds a `string` and there is no TextCopy and no
diff --git a/examples/core-input-gestures.fln b/examples/core-input-gestures.fln
index 703d6eb9..b0c4dd64 100644
--- a/examples/core-input-gestures.fln
+++ b/examples/core-input-gestures.fln
@@ -18,7 +18,7 @@
;;;; has nothing to catch.
;;;;
;;;; A slot that has not been written yet holds a zero-length string, because a
-;;;; `defonce` with no initialiser is all-bytes-zero and a string is ptr+len —
+;;;; `once` with no initialiser is all-bytes-zero and a string is ptr+len —
;;;; a null pointer with a length of 0. draw-text draws nothing for it. That is
;;;; the C's `{ "" }` initialiser arriving by a different route, and it is why
;;;; resetting the log below only has to reset the counter.
@@ -67,7 +67,7 @@ fn main() -> ()
"raylib [core] example - input gestures")
defer rl/close-window()
rl/set-target-fps(60)
- let touch-area = rl/Rectangle({.x 220.0, .y 10.0, .width f32(screen-width) - 230.0, .height f32(screen-height) - 20.0})
+ let touch-area = rl/Rectangle{.x 220.0, .y 10.0, .width f32(screen-width) - 230.0, .height f32(screen-height) - 20.0}
until rl/window-should-close()
;; Update
last-gesture = current-gesture
diff --git a/examples/core-input-keys.fln b/examples/core-input-keys.fln
index 5cec7bc9..1f872cd5 100644
--- a/examples/core-input-keys.fln
+++ b/examples/core-input-keys.fln
@@ -5,13 +5,13 @@
;;;;
;;;; The C moves the ball by writing `ballPosition.x += 2.0f` on a local
;;;; struct. Flan has the same thing — a local IS an assignable place
-;;;; (spec-memory.md) — but the local has to be a `defonce` here rather than a
+;;;; (spec-memory.md) — but the local has to be a `once` here rather than a
;;;; `let` inside the loop, because a `let` binding is rebound every iteration
;;;; and the position has to survive between frames. The C's variable is
;;;; outside its while loop for the same reason; this is that, spelled with the
;;;; storage the language has.
;;;;
-;;;; `(set (.x ball) ...)` works on a struct field of a global: a field of an
+;;;; `ball.x = ...` works on a struct field of a global: a field of an
;;;; assignable place is itself one.
import rl "vendor:raylib"
diff --git a/examples/core-input-mouse.fln b/examples/core-input-mouse.fln
index 24d2141a..192c3c0a 100644
--- a/examples/core-input-mouse.fln
+++ b/examples/core-input-mouse.fln
@@ -9,7 +9,7 @@
;;;; matters in both — two buttons pressed on the same frame give the earlier
;;;; one, which is the C's behaviour and not an accident of the port.
;;;;
-;;;; The colour has to be a `defonce` rather than a `let`, for the reason
+;;;; The colour has to be a `once` rather than a `let`, for the reason
;;;; core-input-keys' position does: it is state between frames.
import rl "vendor:raylib"
diff --git a/examples/core-input-multitouch.fln b/examples/core-input-multitouch.fln
index a2757a80..d39cf16f 100644
--- a/examples/core-input-multitouch.fln
+++ b/examples/core-input-multitouch.fln
@@ -1,19 +1,19 @@
;;;; raylib [core] example - input multitouch
;;;;
;;;; examples/core/core_input_multitouch.c. No new bindings: the whole touch
-;;;; surface was already there for sand.flan's read-out.
+;;;; surface was already there for sand.fln's read-out.
;;;;
;;;; The C keeps `Vector2 touchPositions[MAX_TOUCH_POINTS]`, and this is the
;;;; first example that needs a fixed array whose element type is a STRUCT
;;;; rather than a number. That works — `[10 rl/Vector2]` is ten Vector2s laid
-;;;; out flat, no headers, and `(at touch-positions i)` is a place that can be
+;;;; out flat, no headers, and `touch-positions[i]` is a place that can be
;;;; assigned a whole struct. Nothing in the repository used one before, so it
;;;; is worth saying that it does.
;;;;
-;;;; It is a top-level `defonce` and not a local, which is NOT a stylistic
+;;;; It is a top-level `once` and not a local, which is NOT a stylistic
;;;; choice. A `let` binding takes no type annotation, so the only way to make
;;;; a fixed array inside a function is to initialise it from a literal with
-;;;; every element written out — ten `(rl/Vector2 {.x 0.0 .y 0.0})`s here, and
+;;;; every element written out — ten `rl/Vector2{.x 0.0 .y 0.0}`s here, and
;;;; thirty-two in the gestures testbed. A zeroed local array of a given type
;;;; cannot be spelled. Static storage is what the C's `= { 0 }` gets anyway.
;;;;
diff --git a/examples/core-input-virtual-controls.fln b/examples/core-input-virtual-controls.fln
index e69eaa91..fa0bb74b 100644
--- a/examples/core-input-virtual-controls.fln
+++ b/examples/core-input-virtual-controls.fln
@@ -2,7 +2,7 @@
;;;;
;;;; examples/core/core_input_virtual_controls.c. No new bindings.
;;;;
-;;;; Split the way sand.flan is split: everything above the second banner is
+;;;; Split the way sand.fln is split: everything above the second banner is
;;;; arithmetic with no raylib calls in it, so test/programs/virtual-controls-
;;;; headless.flan can import this file as a package, drive the pointer over a
;;;; scripted path and hash where the player ended up. That is the only one of
@@ -18,7 +18,7 @@
;;;;
;;;; for (i = 0; i < BUTTON_MAX; i++) { if (...) { pressedButton = i; break; } }
;;;;
-;;;; and `(break)` is refused: "break is not implemented yet (see the build
+;;;; and `break()` is refused: "break is not implemented yet (see the build
;;;; sequence in plan.org)". `return` from the function works and is what this
;;;; uses — which is why the search is its own `defn` and not written inline
;;;; the way the C has it. That is not a loss: the function is the thing the
@@ -26,14 +26,14 @@
;;;; function, the shape left is a flag and a compound loop condition.
;;;;
;;;; **No `fabsf`.** The prelude has sqrt-f32 and sign-f32 but no absolute
-;;;; value for floats, and the comment there says why for integers. `(max v
-;;;; (- 0.0 v))` is it, and unlike the integer case it has no edge: there is no
-;;;; float whose negation is itself except -0.0, whose absolute value is 0.0
-;;;; either way.
+;;;; value for floats, and the comment there says why for integers.
+;;;; `max(v, 0.0 - v)` is it, and unlike the integer case it has no edge: there
+;;;; is no float whose negation is itself except -0.0, whose absolute value is
+;;;; 0.0 either way.
;;;;
-;;;; The button geometry is `defconst` arrays of struct literals. That works —
+;;;; The button geometry is `const` arrays of struct literals. That works —
;;;; and it is the only way a fixed array can be made inside anything but a
-;;;; top-level `defonce`, since a `let` binding takes no type annotation.
+;;;; top-level `once`, since a `let` binding takes no type annotation.
import rl "vendor:raylib"
@@ -41,7 +41,7 @@ const screen-width = 800
const screen-height = 450
;; The C's PadButton enum. -1 is BUTTON_NONE and the four directions are 0..3,
-;; in the order the arrays below are written. A `defenum` would not help: the
+;; in the order the arrays below are written. An `enum` would not help: the
;; value is used as an index and an enum does not convert to an integer
;; ("i32 converts a number, found ..."), so it would have to be turned back
;; into one at every use.
@@ -56,7 +56,7 @@ const button-radius: f32 = 30.0
;; padPosition is {100, 350} and the buttons sit a radius and a half away from
;; it on each axis. The C computes these at run time from padPosition; they are
-;; written out here because a defconst is compile-time and the numbers are.
+;; written out here because a const is compile-time and the numbers are.
const button-positions: [button-max rl/Vector2] = [rl/Vector2{.x 100.0 .y 305.0} ; up
; left
; right
diff --git a/examples/core-scissor-test.fln b/examples/core-scissor-test.fln
index 74070788..a6f32c2a 100644
--- a/examples/core-scissor-test.fln
+++ b/examples/core-scissor-test.fln
@@ -1,7 +1,7 @@
;;;; raylib [core] example - scissor test
;;;;
;;;; examples/core/core_scissor_test.c. Needed begin-scissor-mode and
-;;;; end-scissor-mode, now hand-written in vendor/raylib/raylib.flan: they are
+;;;; end-scissor-mode, now hand-written in vendor/raylib/raylib.fln: they are
;;;; a begin/end pair inside a frame, which is the class docs/PORTING.md §1 says
;;;; belongs in the hand-written half and not in the importer's. get-mouse-x
;;;; and get-mouse-y come from the generated half — their Flan face is the C
diff --git a/examples/core-window-flags.fln b/examples/core-window-flags.fln
index a16845d6..6cfdf12f 100644
--- a/examples/core-window-flags.fln
+++ b/examples/core-window-flags.fln
@@ -1,14 +1,14 @@
;;;; raylib [core] example - window flags
;;;;
;;;; examples/core/core_window_flags.c. The reason to port this one is the
-;;;; flags themselves: raylib.flan carried four of ConfigFlags' sixteen
-;;;; members — the four sand.flan sets before the window exists — and this
+;;;; flags themselves: raylib.fln carried four of ConfigFlags' sixteen
+;;;; members — the four sand.fln sets before the window exists — and this
;;;; example reads and writes eleven of them after it exists. All sixteen are
-;;;; in raylib.flan now, read off raylib.h 5.5, in the header's order and not
+;;;; in raylib.fln now, read off raylib.h 5.5, in the header's order and not
;;;; in bit order (FLAG_VSYNC_HINT is 0x40 and FLAG_FULLSCREEN_MODE is 0x02,
;;;; which is the kind of thing nobody remembers correctly).
;;;;
-;;;; They are `defconst u32`s and not a `defenum` for the reason the file
+;;;; They are `const u32`s and not an `enum` for the reason the file
;;;; already gives about gestures: raylib wants the OR of several and a
;;;; keyword can only ever name one member.
;;;;
@@ -16,7 +16,7 @@
;;;; minimize-window, maximize-window and restore-window all come from the
;;;; generated half. That is the line drawn in vendor/raylib/bindings and it
;;;; is worth saying why it falls here: the rule in docs/PORTING.md §1 exists so
-;;;; that a build with no header set can still draw, and generated.flan is
+;;;; that a build with no header set can still draw, and generated.fln is
;;;; committed, so it can. What a hand-written line adds on top of that is a
;;;; Flan face the C signature does not have — a Key instead of an int, a
;;;; (Ptr Camera3D) instead of a raw pointer — and these seven have no such
@@ -71,7 +71,7 @@ fn main() -> ()
rl/init-window(screen-width, screen-height,
"raylib [core] example - window flags")
defer rl/close-window()
- ball-pos = rl/Vector2({.x f32(rl/get-screen-width()) / 2.0, .y f32(rl/get-screen-height()) / 2.0})
+ ball-pos = rl/Vector2{.x f32(rl/get-screen-width()) / 2.0, .y f32(rl/get-screen-height()) / 2.0}
ball-speed = rl/Vector2{.x 5.0 .y 4.0}
;; No set-target-fps, as in the C: with FLAG_VSYNC_HINT among the flags the
;; example toggles, a frame limiter on top of it would hide what V-Sync
diff --git a/examples/core-window-should-close.fln b/examples/core-window-should-close.fln
index 22bfd1a1..2cb008c2 100644
--- a/examples/core-window-should-close.fln
+++ b/examples/core-window-should-close.fln
@@ -1,22 +1,22 @@
;;;; raylib [core] example - window should close
;;;;
;;;; examples/core/core_window_should_close.c. Needed set-exit-key, and one
-;;;; enum member to go with it: raylib.flan's `Key` now has `null 0`, read off
+;;;; enum member to go with it: raylib.fln's `Key` now has `null 0`, read off
;;;; KEY_NULL in raylib.h. The binding is hand-written rather than taken from
;;;; the generated half because the Flan face differs — raylib declares
;;;; `void SetExitKey(int key)` and the generated line therefore takes an i32,
-;;;; where this one takes a Key, so `(rl/set-exit-key :key-null)` is checked
+;;;; where this one takes a Key, so `rl/set-exit-key(:key-null)` is checked
;;;; against the enum and `:nul` is a compile error instead of a 0.
;;;;
;;;; The whole example is about what window-should-close means. It is not a
;;;; flag raylib latches: it is "the close button was clicked, or the exit key
;;;; is down", recomputed each frame, and it goes back to false on its own.
;;;; That is what lets this program ask for confirmation and then carry on —
-;;;; and it is also why the loop is driven by a `defonce` of its own rather
+;;;; and it is also why the loop is driven by a `once` of its own rather
;;;; than by the predicate, which is the one structural difference from every
;;;; other example in this directory.
;;;;
-;;;; `(set-exit-key :null)` takes ESC away from raylib so the program can read
+;;;; `set-exit-key(:null)` takes ESC away from raylib so the program can read
;;;; it itself. The window's X button still works and is still what
;;;; window-should-close reports.
@@ -47,9 +47,8 @@ fn main() -> ()
if exit-requested
if rl/is-key-pressed(:key-y)
exiting = true
- else
- if rl/is-key-pressed(:key-n)
- exit-requested = false
+ elif rl/is-key-pressed(:key-n)
+ exit-requested = false
;; Draw
rl/with-drawing:
rl/clear-background(rl/raywhite)
diff --git a/examples/core-world-screen.fln b/examples/core-world-screen.fln
index 24e0c0a9..2e6cfe1a 100644
--- a/examples/core-world-screen.fln
+++ b/examples/core-world-screen.fln
@@ -8,7 +8,7 @@
;;;; none of them, and the generated half grew the cubes, spheres, cylinders
;;;; and billboards along with the eight lines this example needs.
;;;;
-;;;; Hand-written in raylib.flan rather than generated, and why each:
+;;;; Hand-written in raylib.fln rather than generated, and why each:
;;;;
;;;; begin-mode-3d / end-mode-3d a begin/end pair inside a frame, the
;;;; class docs/PORTING.md §1 names, and taken
@@ -51,7 +51,7 @@ fn main() -> ()
;; enum's members right here and a misspelt projection is a compile error
;; rather than a 0. raylib's field is `int` and the layout is unchanged —
;; an enum is four bytes either way.
- camera = rl/Camera3D({.position rl/Vector3{.x 10.0 .y 10.0 .z 10.0} .target rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .up rl/Vector3{.x 0.0 .y 1.0 .z 0.0} .fovy 45.0 .projection :projection-perspective})
+ camera = rl/Camera3D{.position rl/Vector3{.x 10.0 .y 10.0 .z 10.0} .target rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .up rl/Vector3{.x 0.0 .y 1.0 .z 0.0} .fovy 45.0 .projection :projection-perspective}
cube = rl/Vector3{.x 0.0 .y 0.0 .z 0.0}
;; The mouse becomes the camera's, not a pointer's.
rl/disable-cursor()
diff --git a/examples/digits.fln b/examples/digits.fln
index c4d8e8ce..611b14b7 100644
--- a/examples/digits.fln
+++ b/examples/digits.fln
@@ -7,12 +7,12 @@
;;;; allocator to build one in. So a number was drawn one glyph at a time out
;;;; of a `[10 string]` table.
;;;;
-;;;; `(string b)` closed that. It is the mirror of `(bytes-view s)` and costs no
+;;;; `string(b)` closed that. It is the mirror of `bytes-view(s)` and costs no
;;;; instructions — a `string` and a `[u8]` are the same 16-byte %slice — so
-;;;; `(string (i64->bytes n))` draws in one call and the table, the per-glyph
+;;;; `string(i64->bytes(n))` draws in one call and the table, the per-glyph
;;;; pen and the digit arithmetic behind them are gone.
;;;;
-;;;; What is left is the part `(string ...)` does not answer, which is
+;;;; What is left is the part `string(...)` does not answer, which is
;;;; *formatting*: `i64->bytes` has no field width, so "%03i" still has to be
;;;; assembled, and `f64->bytes` is `%g` and not "%.02f", so a fixed number of
;;;; decimal places still has to be split and drawn in two pieces. Those two
@@ -25,8 +25,8 @@
;;;; name anyway.
;;;;
;;;; `i64->bytes` and `f64->bytes` put their text in the temp allocator, where
-;;;; it lasts until the next `(free-temp)`. A program drawing these every frame
-;;;; calls `(free-temp)` once per frame, after drawing, and clones any text it
+;;;; it lasts until the next `free-temp()`. A program drawing these every frame
+;;;; calls `free-temp()` once per frame, after drawing, and clones any text it
;;;; keeps longer.
;;;;
;;;; Everything here needs a window: `measure-text` answers 0 for every string
diff --git a/examples/models-box-collisions.fln b/examples/models-box-collisions.fln
index 520125b4..1fd87926 100644
--- a/examples/models-box-collisions.fln
+++ b/examples/models-box-collisions.fln
@@ -10,11 +10,11 @@
;;;;
;;;; That aggregate is BoundingBox, and it is two Vector3s and nothing else —
;;;; no owned pointer, no array, no lifetime. One `defstruct` in
-;;;; vendor/raylib/raylib.flan un-refuses four raylib functions at once
+;;;; vendor/raylib/raylib.fln un-refuses four raylib functions at once
;;;; (CheckCollisionBoxes, CheckCollisionBoxSphere, DrawBoundingBox and
;;;; GetRayCollisionBox), and that is the cheapest widening of the 3D surface
;;;; available anywhere in the tree. Ray and RayCollision went in beside it
-;;;; for examples/core-3d-picking.flan and for the same reason.
+;;;; for examples/core-3d-picking.fln and for the same reason.
;;;;
;;;; So the answer to "is a models example just a binding exercise" is: the
;;;; ones that need Model are, and this one is the counterexample. What
@@ -57,7 +57,7 @@ const enemy-sphere-size: f32 = 1.5
;;
;; It used to be eight expressions of field arithmetic here too; it is the
;; half-extent subtracted and added now that the package carries vector
-;; arithmetic — see vendor/raylib/vector.flan, which is Flan and not C
+;; arithmetic — see vendor/raylib/vector.fln, which is Flan and not C
;; because raymath is `static inline` and has no symbol to bind.
fn box-around(centre: rl/Vector3, size: rl/Vector3) -> rl/BoundingBox
let half = rl/v3-scale(size, 0.5)
@@ -68,9 +68,9 @@ fn main() -> ()
"raylib [models] example - box collisions")
defer rl/close-window()
;; The C writes this camera as a brace initialiser with a trailing 0 for the
- ;; projection, which is CAMERA_PERSPECTIVE. Named here, because the defenum
+ ;; projection, which is CAMERA_PERSPECTIVE. Named here, because the enum
;; exists precisely so that the 0 does not have to be remembered.
- camera = rl/Camera3D({.position rl/Vector3{.x 0.0 .y 10.0 .z 10.0} .target rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .up rl/Vector3{.x 0.0 .y 1.0 .z 0.0} .fovy 45.0 .projection :projection-perspective})
+ camera = rl/Camera3D{.position rl/Vector3{.x 0.0 .y 10.0 .z 10.0} .target rl/Vector3{.x 0.0 .y 0.0 .z 0.0} .up rl/Vector3{.x 0.0 .y 1.0 .z 0.0} .fovy 45.0 .projection :projection-perspective}
player-position = rl/Vector3{.x 0.0 .y 1.0 .z 2.0}
player-size = rl/Vector3{.x 1.0 .y 2.0 .z 1.0}
player-color = rl/green
diff --git a/examples/shapes-basic-shapes.fln b/examples/shapes-basic-shapes.fln
index c8c73906..af34d674 100644
--- a/examples/shapes-basic-shapes.fln
+++ b/examples/shapes-basic-shapes.fln
@@ -7,17 +7,17 @@
;;;; poly draws — in one frame, beside the four the core examples already
;;;; exercise. Every one of them came out of the generated half of the
;;;; bindings and none needed a new line anywhere; that is the result worth
-;;;; recording, because the whole point of a committed generated.flan is that
+;;;; recording, because the whole point of a committed generated.fln is that
;;;; a build with no FLAN_RAYLIB_H set can draw with all of it.
;;;;
;;;; What it is actually a test of. The gradient calls are the first thing in
;;;; the corpus to pass *two* Colors in one call, and draw-triangle is the
;;;; first to pass three Vector2s. A struct argument crosses the FFI by
-;;;; pointer into a generated shim (vendor/raylib/raylib.flan's header note),
+;;;; pointer into a generated shim (vendor/raylib/raylib.fln's header note),
;;;; so the arity of that copying is what a call with several small structs in
;;;; a row puts under load. Nothing here can be asserted headless — every line
;;;; needs a GL context — so the check is the link and the screen, which is
-;;;; what the Shapes comment in raylib.flan already says about this family.
+;;;; what the Shapes comment in raylib.fln already says about this family.
;;;;
;;;; The one deliberate difference from the C: the C writes `screenWidth/4*2`
;;;; and `screenWidth/4.0f*3.0f` for the same column and gets 400 and 600 out
diff --git a/examples/shapes-collision-area.fln b/examples/shapes-collision-area.fln
index 7709409c..183939ba 100644
--- a/examples/shapes-collision-area.fln
+++ b/examples/shapes-collision-area.fln
@@ -40,9 +40,9 @@ fn main() -> ()
rl/init-window(screen-width, screen-height,
"raylib [shapes] example - collision area")
defer rl/close-window()
- box-a = rl/Rectangle({.x 10.0, .y f32(screen-height) / 2.0 - 50.0, .width 200.0, .height 100.0})
+ box-a = rl/Rectangle{.x 10.0, .y f32(screen-height) / 2.0 - 50.0, .width 200.0, .height 100.0}
box-a-speed-x = 4
- box-b = rl/Rectangle({.x f32(screen-width) / 2.0 - 30.0, .y f32(screen-height) / 2.0 - 30.0, .width 60.0, .height 60.0})
+ box-b = rl/Rectangle{.x f32(screen-width) / 2.0 - 30.0, .y f32(screen-height) / 2.0 - 30.0, .width 60.0, .height 60.0}
;; A fresh Rectangle is four zeroes, which is the C's `= { 0 }`. It is never
;; drawn before the first collision sets it.
box-collision = rl/Rectangle{.x 0.0 .y 0.0 .width 0.0 .height 0.0}
@@ -63,14 +63,12 @@ fn main() -> ()
box-b.y = f32(rl/get-mouse-y()) - box-b.height / 2.0
if box-b.x + box-b.width >= f32(rl/get-screen-width())
box-b.x = f32(rl/get-screen-width()) - box-b.width
- else
- if box-b.x <= 0.0
- box-b.x = 0.0
+ elif box-b.x <= 0.0
+ box-b.x = 0.0
if box-b.y + box-b.height >= f32(rl/get-screen-height())
box-b.y = f32(rl/get-screen-height()) - box-b.height
- else
- if box-b.y <= f32(screen-upper-limit)
- box-b.y = f32(screen-upper-limit)
+ elif box-b.y <= f32(screen-upper-limit)
+ box-b.y = f32(screen-upper-limit)
collision = rl/check-collision-recs(box-a, box-b)
;; Only meaningful while they touch: raylib answers a zero rectangle for
;; two boxes that do not, and the C leaves the previous one in place
diff --git a/examples/shapes-following-eyes.fln b/examples/shapes-following-eyes.fln
index fd9683f1..de59be58 100644
--- a/examples/shapes-following-eyes.fln
+++ b/examples/shapes-following-eyes.fln
@@ -18,7 +18,7 @@
;;;; file.
;;;;
;;;; That measurement is what decided the answer, and the answer landed:
-;;;; vendor/raylib/vector.flan is raymath written in Flan, since a C shim
+;;;; vendor/raylib/vector.fln is raymath written in Flan, since a C shim
;;;; re-exporting the inlines would have bought identical arithmetic at the
;;;; price of a compilation unit and a second place raylib's semantics live.
;;;; The measurement is left standing rather than rewritten away — one
@@ -69,7 +69,7 @@ fn track(mouse: rl/Vector2, centre: rl/Vector2) -> rl/Vector2
else
let d = rl/v2-sub(mouse, centre)
angle = atan2-f32(d.y, d.x)
- rl/Vector2({.x centre.x + limit * cos-f32(angle), .y centre.y + limit * sin-f32(angle)})
+ rl/Vector2{.x centre.x + limit * cos-f32(angle), .y centre.y + limit * sin-f32(angle)}
fn main() -> ()
rl/init-window(screen-width, screen-height,
@@ -78,8 +78,8 @@ fn main() -> ()
;; The C reads these off get-screen-width/get-screen-height after the window
;; is open rather than off the constants, and so does this: on a high-DPI
;; display the two can differ.
- sclera-left = rl/Vector2({.x f32(rl/get-screen-width()) / 2.0 - 100.0, .y f32(rl/get-screen-height()) / 2.0})
- sclera-right = rl/Vector2({.x f32(rl/get-screen-width()) / 2.0 + 100.0, .y f32(rl/get-screen-height()) / 2.0})
+ sclera-left = rl/Vector2{.x f32(rl/get-screen-width()) / 2.0 - 100.0, .y f32(rl/get-screen-height()) / 2.0}
+ sclera-right = rl/Vector2{.x f32(rl/get-screen-width()) / 2.0 + 100.0, .y f32(rl/get-screen-height()) / 2.0}
iris-left = sclera-left
iris-right = sclera-right
rl/set-target-fps(60)
diff --git a/examples/text-codepoints-loading.fln b/examples/text-codepoints-loading.fln
index feb51819..2709bf20 100644
--- a/examples/text-codepoints-loading.fln
+++ b/examples/text-codepoints-loading.fln
@@ -19,7 +19,7 @@
;;;; come back out of LoadCodepoints as the right 54, and as 49 distinct ones.
;;;; Nothing in the
;;;; language claims to know what a character is — a `string` is bytes and a
-;;;; `[u8]` is the same bytes, which `(string ...)` and `(bytes-view ...)` say in
+;;;; `[u8]` is the same bytes, which `string(...)` and `bytes-view(...)` say in
;;;; both directions — and that turns out to be exactly the right amount of
;;;; opinion for this. The count below is a count of codepoints because raylib
;;;; decoded them, not because Flan did.
@@ -37,7 +37,7 @@
;;;; the bytes in front of that pointer belong to the allocator and not
;;;; to the text. It did not crash; it read rubbish and answered 0, which
;;;; is the worst of the available outcomes. The repair is a binding that
-;;;; says `(Ptr u8)` and means it, which the header check refused until
+;;;; says `Ptr(u8)` and means it, which the header check refused until
;;;; lib/cimport.ml's `agrees` grew the pointer arm its own comment had
;;;; been promising. `rl/get-codepoint-previous` is that binding and
;;;; `step-back` below is now one call to it.
@@ -126,7 +126,7 @@ fn collect-unique(codepoints: [i32]) -> ()
;; The codepoint starting at `off`, and its size in bytes through `size-out`.
;;
-;; `(string (slice b off (length b)))` is the whole of what the C's `ptr`
+;; `string(slice(b, off, length(b)))` is the whole of what the C's `ptr`
;; is: the tail of the text from here on. It costs nothing to say — a `string` and a
;; `[u8]` are the same two words — and the shim NUL-terminates a copy of it
;; for the duration of the call, which is all GetCodepointNext wants, because
@@ -160,7 +160,7 @@ fn step-forward(off: i32) -> i32
;; string — which reaches C as a copy — is the one thing it must not be
;; handed. `rl/get-codepoint-previous` takes the bytes and an offset instead
;; and builds the interior pointer itself; see the note beside it in
-;; vendor/raylib/raylib.flan. What comes back through `size` is the length of
+;; vendor/raylib/raylib.fln. What comes back through `size` is the length of
;; the codepoint *behind* `off`, so the previous offset is the difference.
;;
;; This used to be a hand-written walk over continuation bytes — step back one
@@ -179,7 +179,7 @@ fn step-back(off: i32) -> i32
once font: rl/Font
-;; Whether the TTF was there, asked once. A `defonce` and not the call itself
+;; Whether the TTF was there, asked once. A `once` and not the call itself
;; in the draw loop: is-path-file is a stat, and a syscall per frame to answer a
;; question whose answer cannot change while the program runs is exactly what
;; the per-frame rule in docs/PORTING.md is about.
diff --git a/examples/text-input-box.fln b/examples/text-input-box.fln
index b2a4ce66..a1fcc0ce 100644
--- a/examples/text-input-box.fln
+++ b/examples/text-input-box.fln
@@ -13,7 +13,7 @@
;;;; the second character of a fast pair.
;;;;
;;;; raylib says "empty" by answering 0, and rl/get-char-pressed is now a
-;;;; Flan wrapper that says it with None instead — see raylib.flan, "Draining
+;;;; Flan wrapper that says it with None instead — see raylib.fln, "Draining
;;;; raylib's two input queues". What that buys is visible below: the C
;;;; shape, which this file had, reads the queue in *two* places, once to
;;;; prime the loop and once at the bottom of the body, and a `> 0` in
@@ -21,9 +21,9 @@
;;;; Option shape reads it in one place, and the case where there is no
;;;; character is a branch the checker knows about rather than a comparison.
;;;;
-;;;; The second is set-mouse-cursor, which needed a new defenum. raylib's
+;;;; The second is set-mouse-cursor, which needed a new enum. raylib's
;;;; header says `int cursor` and means one of eleven MOUSE_CURSOR_ values, so
-;;;; the Flan face is `MouseCursor` — hand-written in raylib.flan beside the
+;;;; the Flan face is `MouseCursor` — hand-written in raylib.fln beside the
;;;; other cursor calls, excluded from the generated half, and mapped in
;;;; `bindings` so the eleven members are checked against the header. See the
;;;; comment there: this call is made on every frame off a hover test, and the
@@ -66,7 +66,7 @@ fn main() -> ()
defer rl/close-window()
name = array(max-input-chars, u8)
letter-count = 0
- text-box = rl/Rectangle({.x f32(screen-width) / 2.0 - 100.0, .y 180.0, .width 225.0, .height 50.0})
+ text-box = rl/Rectangle{.x f32(screen-width) / 2.0 - 100.0, .y 180.0, .width 225.0, .height 50.0}
mouse-on-text = false
frames-counter = 0
rl/set-target-fps(60)
diff --git a/examples/text-rectangle-bounds.fln b/examples/text-rectangle-bounds.fln
index 6f995874..2c2f86d4 100644
--- a/examples/text-rectangle-bounds.fln
+++ b/examples/text-rectangle-bounds.fln
@@ -5,9 +5,9 @@
;;;; form was built rather than an application found for it afterwards.
;;;;
;;;; Its inner loop reads `font.recs[index]` and `font.glyphs[index]`. Both
-;;;; fields are `(Ptr T)` — that is what raylib hands back and there is nothing
+;;;; fields are `Ptr(T)` — that is what raylib hands back and there is nothing
;;;; else it could hand back — and a pointer from C carries no length, so
-;;;; `(at (.recs font) i)` answered `(Ptr rl/Rectangle) cannot be indexed` and
+;;;; `font.recs[i]` answered `Ptr(rl/Rectangle) cannot be indexed` and
;;;; the whole example stopped there. Element 0 through `deref` was the entire
;;;; readable surface of a two-hundred-glyph array.
;;;;
@@ -35,7 +35,7 @@
;;;; wrap, which is the thing the example is about.
;;;;
;;;; - `GetCodepoint` wants a pointer into the middle of the text, and Flan has
-;;;; the operation the C is spelling by hand: `(string (slice b i n))` is the
+;;;; the operation the C is spelling by hand: `string(slice(b, i, n))` is the
;;;; tail from `i` with no copy and no pointer arithmetic. It is not free:
;;;; the shim NUL-terminates a copy on the way into C, into a 256-byte stack
;;;; buffer or a malloc when the tail is longer — and this message is 284
@@ -158,7 +158,7 @@ fn main() -> ()
let text = bytes-view(message)
is-resizing = false
is-word-wrap = true
- let container = rl/Rectangle({.x 25.0, .y 25.0, .width f32(screen-width) - 50.0, .height f32(screen-height) - 250.0})
+ let container = rl/Rectangle{.x 25.0, .y 25.0, .width f32(screen-width) - 50.0, .height f32(screen-height) - 250.0}
let resizer = rl/Rectangle{.x 0.0 .y 0.0 .width 14.0 .height 14.0}
let min-width = f32(60.0)
min-height = f32(60.0)
@@ -185,9 +185,8 @@ fn main() -> ()
let h = container.height + (mouse.y - last-mouse.y)
container.width = clamp(w, min-width, max-width)
container.height = clamp(h, min-height, max-height)
- else
- if rl/is-mouse-button-down(:mouse-left) and rl/check-collision-point-rec(mouse, resizer)
- is-resizing = true
+ elif rl/is-mouse-button-down(:mouse-left) and rl/check-collision-point-rec(mouse, resizer)
+ is-resizing = true
resizer.x = container.x + container.width - 17.0
resizer.y = container.y + container.height - 17.0
last-mouse = mouse
diff --git a/examples/text-writing-anim.fln b/examples/text-writing-anim.fln
index fd52795b..2d3ac3e6 100644
--- a/examples/text-writing-anim.fln
+++ b/examples/text-writing-anim.fln
@@ -6,14 +6,14 @@
;;;; DrawText(TextSubtext(message, 0, framesCounter/10), ...)
;;;;
;;;; TextSubtext is in raylib.h and is not in the bindings, on the rule
-;;;; raylib.flan states for the whole Text* family: it answers a `char *` into
+;;;; raylib.fln states for the whole Text* family: it answers a `char *` into
;;;; a rotating static buffer, and declare-c refuses a returned pointer to
;;;; memory the caller does not own. There is no missing line to add — the
;;;; binding would be wrong at any signature.
;;;;
;;;; And it does not matter, because Flan has the operation as a primitive.
-;;;; `(slice a lo hi)` takes a view of an array, `(string b)` reinterprets the
-;;;; bytes as a string at no cost, and `(string (slice message 0 n))` is
+;;;; `slice(a, lo, hi)` takes a view of an array, `string(b)` reinterprets the
+;;;; bytes as a string at no cost, and `string(slice(message, 0, n))` is
;;;; TextSubtext with the static buffer removed — no copy, no shared state, no
;;;; rotation to run out of. Porting the example is therefore how the gap gets
;;;; *closed* rather than reported: the C's workaround for not having slices
@@ -28,8 +28,8 @@
;;;; the C's, and it costs one `min`.
;;;;
;;;; The message is a `[u8]` and not a `string` because `slice` takes an array
-;;;; or a slice; `(bytes-view "…")` is the bridge in the other direction from
-;;;; `(string …)` and costs nothing either. The embedded newline is written as
+;;;; or a slice; `bytes-view("…")` is the bridge in the other direction from
+;;;; `string(…)` and costs nothing either. The embedded newline is written as
;;;; an escape, and raylib's draw-text breaks the line on it.
import rl "vendor:raylib"
diff --git a/examples/textures-fog-of-war.fln b/examples/textures-fog-of-war.fln
index b8f25460..29011030 100644
--- a/examples/textures-fog-of-war.fln
+++ b/examples/textures-fog-of-war.fln
@@ -8,8 +8,8 @@
;;;; bilinear sampler doing the interpolation. With the default
;;;; :filter-point the same program draws 32-pixel squares.
;;;;
-;;;; That is what needed adding: `TextureFilter`, a new defenum in
-;;;; vendor/raylib/raylib.flan, with set-texture-filter moved from the
+;;;; That is what needed adding: `TextureFilter`, a new enum in
+;;;; vendor/raylib/raylib.fln, with set-texture-filter moved from the
;;;; generated half to the hand-written one and mapped in `bindings` so its
;;;; six members are checked against raylib.h. The header says `int filter`
;;;; and there is nothing in an `int` to say that 1 is the interesting value;
@@ -117,14 +117,14 @@ fn main() -> ()
;; Light the square around the player, skipping anything off the map.
;; Without that test this reads and writes outside the array, which in the
;; C is undefined and here is a bounds trap — the same bug, reported.
- let y-2 = player-tile-y - player-tile-visibility
- while y-2 < player-tile-y + player-tile-visibility
+ let vis-y = player-tile-y - player-tile-visibility
+ while vis-y < player-tile-y + player-tile-visibility
let x = player-tile-x - player-tile-visibility
while x < player-tile-x + player-tile-visibility
- if x >= 0 and x < tiles-x and y-2 >= 0 and y-2 < tiles-y
- tile-fog[y-2 * tiles-x + x] = 1
+ if x >= 0 and x < tiles-x and vis-y >= 0 and vis-y < tiles-y
+ tile-fog[vis-y * tiles-x + x] = 1
x += 1
- y-2 += 1
+ vis-y += 1
;; Draw the fog into its own little target first, at one pixel per tile.
;; blank is alpha 0, so a tile that is neither unseen nor remembered
;; leaves nothing behind and the map below shows through unmodified.
diff --git a/examples/textures-image-generation.fln b/examples/textures-image-generation.fln
index fba55d12..4d1c992c 100644
--- a/examples/textures-image-generation.fln
+++ b/examples/textures-image-generation.fln
@@ -8,7 +8,7 @@
;;;; of its pixels.
;;;;
;;;; What it puts under load that nothing else does. An Image is the one
-;;;; struct in raylib.flan that carries a pointer to memory raylib owns —
+;;;; struct in raylib.fln that carries a pointer to memory raylib owns —
;;;; `data (Ptr u8)` — and it is returned by value, so every one of these nine
;;;; calls hands back a 24-byte aggregate through the shim's out-pointer with
;;;; a live heap block inside it. The corpus had crossed an Image before
diff --git a/examples/textures-image-processing.fln b/examples/textures-image-processing.fln
index dfcf3973..d5d12931 100644
--- a/examples/textures-image-processing.fln
+++ b/examples/textures-image-processing.fln
@@ -9,16 +9,16 @@
;;;; had ever handed raylib a buffer and asked it to rewrite the buffer.
;;;;
;;;; What that puts under load, and it is a different thing from the nine
-;;;; Gen* calls in examples/textures-image-generation.flan: **in-place
+;;;; Gen* calls in examples/textures-image-generation.fln: **in-place
;;;; mutation of an Image through a (Ptr Image)**. Eight of the nine filters
;;;; take the image by pointer and change `data` under the caller —
;;;; image-format and image-blur-gaussian *reallocate* it, so the pointer the
-;;;; caller held before the call is freed by it. raylib.flan's Images section
+;;;; caller held before the call is freed by it. raylib.fln's Images section
;;;; already says that the by-value/by-pointer split is raylib's own and is
;;;; kept deliberately so a caller can see which calls change what they are
;;;; given; this is the example that depends on it being right.
;;;;
-;;;; What needed adding: `PixelFormat`, a defenum in vendor/raylib/raylib.flan,
+;;;; What needed adding: `PixelFormat`, a enum in vendor/raylib/raylib.fln,
;;;; with image-format moved from the generated half to the hand-written one
;;;; and mapped in `bindings` so its twenty-four members are checked against
;;;; raylib.h. The C's line is
@@ -67,9 +67,9 @@ const screen-height = 450
const num-processes = 9
-;; The C's ImageProcess enum. Flan's defenum lowers to an i32 for C's benefit
-;; and these never cross to C, so they are defconsts — the same choice
-;; examples/textures-image-generation.flan made for its texture index.
+;; The C's ImageProcess enum. Flan's enum lowers to an i32 for C's benefit
+;; and these never cross to C, so they are consts — the same choice
+;; examples/textures-image-generation.fln made for its texture index.
const proc-none = 0
const proc-color-grayscale = 1
const proc-color-tint = 2
@@ -109,7 +109,7 @@ fn make-source-image() -> rl/Image
img
;; The C's `switch (currentProcess)`. A cond here, as in
-;; examples/textures-image-generation.flan, and for the same reason: Flan has
+;; examples/textures-image-generation.fln, and for the same reason: Flan has
;; no switch and the chain reads the same.
;;
;; Every arm takes the image by pointer and every arm rewrites the buffer the
@@ -188,14 +188,14 @@ fn main() -> ()
mouse-hover-rec = -1
toggle-recs = array(num-processes, rl/Rectangle)
for i in range(num-processes)
- toggle-recs[i] = rl/Rectangle({.x 40.0 .y f32(50 + 32 * i) .width 150.0 .height 30.0})
+ toggle-recs[i] = rl/Rectangle{.x 40.0 .y f32(50 + 32 * i) .width 150.0 .height 30.0}
rl/set-target-fps(60)
until rl/window-should-close()
;; Update
;;
;; The C computes mouseHoverRec with a loop whose `else` clause resets it
;; on every miss and whose `break` leaves it set on a hit. As in
- ;; examples/textures-mouse-painting.flan the reset is lifted out in front
+ ;; examples/textures-mouse-painting.fln the reset is lifted out in front
;; and the loop only ever sets it, which is the same answer said plainly —
;; the nine rectangles do not overlap, so there is no first-hit-wins rule
;; to preserve.
diff --git a/examples/textures-mouse-painting.fln b/examples/textures-mouse-painting.fln
index 60fcaa06..799ec463 100644
--- a/examples/textures-mouse-painting.fln
+++ b/examples/textures-mouse-painting.fln
@@ -7,14 +7,14 @@
;;;; load-image-from-texture → image-flip-vertical → export-image
;;;;
;;;; Nothing in the corpus had run it. image-from-image has a headless
-;;;; acceptance case and sand.flan loads images the other way, but the path
+;;;; acceptance case and sand.fln loads images the other way, but the path
;;;; that reads a render target's pixels back into CPU memory, corrects for
;;;; GL's bottom-up rows and encodes a PNG had never been exercised at all.
;;;; All three came out of the generated half of the bindings; nothing needed
;;;; adding for this file.
;;;;
;;;; The flip is the same fact as the negative source height in
-;;;; examples/textures-fog-of-war.flan, met from the other side: on screen the
+;;;; examples/textures-fog-of-war.fln, met from the other side: on screen the
;;;; canvas is drawn with a negative-height source rectangle so GL's bottom-up
;;;; rows come out the right way up, and on save there is no source rectangle
;;;; to negate, so the pixels are turned over in memory instead. A program
@@ -92,7 +92,7 @@ fn main() -> ()
;; 30 wide with a 2-pixel gap, starting 10 from the left.
colors-recs = array(max-colors-count, rl/Rectangle)
for i in range(max-colors-count)
- colors-recs[i] = rl/Rectangle({.x 10.0 + 32.0 * f32(i), .y 10.0, .width 30.0, .height 30.0})
+ colors-recs[i] = rl/Rectangle{.x 10.0 + 32.0 * f32(i), .y 10.0, .width 30.0, .height 30.0}
color-selected = 0
color-selected-prev = 0
color-mouse-hover = 0
@@ -117,9 +117,8 @@ fn main() -> ()
let mouse-pos = rl/get-mouse-position()
if rl/is-key-pressed(:key-right)
color-selected += 1
- else
- if rl/is-key-pressed(:key-left)
- color-selected -= 1
+ elif rl/is-key-pressed(:key-left)
+ color-selected -= 1
color-selected = clamp(color-selected, 0, max-colors-count - 1)
;; Which swatch the pointer is over, or -1. See the header comment: the
;; reset is here rather than in an else branch inside the loop.
@@ -156,10 +155,9 @@ fn main() -> ()
if mouse-pos.y > 50.0
rl/draw-circle(i32(mouse-pos.x), i32(mouse-pos.y), brush-size,
colors[0])
- else
- if rl/is-mouse-button-released(:mouse-right) and mouse-was-pressed
- color-selected = color-selected-prev
- mouse-was-pressed = false
+ elif rl/is-mouse-button-released(:mouse-right) and mouse-was-pressed
+ color-selected = color-selected-prev
+ mouse-was-pressed = false
btn-save-mouse-hover = rl/check-collision-point-rec(mouse-pos, btn-save-rec)
;; The round trip. See the header comment for why the flip is here and
;; not on the draw.
diff --git a/lib/build.ml b/lib/build.ml
index af69d4be..af4f255f 100644
--- a/lib/build.ml
+++ b/lib/build.ml
@@ -919,7 +919,7 @@ let executable ?(opts = default) ?(csrcs = []) ?(lflags = []) ?(pnames = [])
a release build calls into it — the compiler only emits a registry lookup
for a name the host was not built with, which cannot arise without cells —
but the agent package's C refers to it, and a package's C sources are
- collected whatever [main] does. Leaving it out made [flan build sand.flan]
+ collected whatever [main] does. Leaving it out made [flan build sand.fln]
fail at the link with an undefined symbol, which reads as a compiler bug
rather than as a missing flag. The table is BSS, so this costs address
space and not binary size, and [-rdynamic] and the cells are still what
diff --git a/lib/dev.ml b/lib/dev.ml
index 6897d2a8..de4aa469 100644
--- a/lib/dev.ml
+++ b/lib/dev.ml
@@ -1427,7 +1427,7 @@ let eval_expr_at t ~code ~origin ~pause ~at =
and its only other reader is the select in [accept_loop] —
which is not running, because it is further up this very call
stack, inside [serve]. A program that prints as it goes (and a
- game loop prints as it goes; sand.flan does) fills those 64K
+ game loop prints as it goes; sand.fln does) fills those 64K
while the module below was being built, and the game thread is
then stopped inside [flan_write_stdout], in an [fwrite] that
will not return until somebody reads. It never reaches the
@@ -3344,7 +3344,7 @@ let reg_listing t ~verb ~note =
Locals were the half the shadow stack was built for; these are arguably the
more useful half in this language. A game keeps most of its state in
- top-level [defonce]s and sand.flan holds its entire grid that way, so "what
+ top-level [defonce]s and sand.fln holds its entire grid that way, so "what
is the program's state right now" is a question about globals and there was
nowhere to ask it.
diff --git a/lib/load.ml b/lib/load.ml
index 1ac7734c..95420256 100644
--- a/lib/load.ml
+++ b/lib/load.ml
@@ -45,7 +45,7 @@ type t = {
owns. A file on disk does not say what it is called from outside — the
*importer* chooses that — so this is the only place the answer exists, and
a REPL editing a package's source needs it to know that [poll] typed in
- vendor/agent/agent.flan means [agent/poll] to the running program. *)
+ vendor/agent/agent.fln means [agent/poll] to the running program. *)
pkgs : pkg list;
(* Every [defmacro] the imported packages declare, qualified under the alias
each was imported as and quasiquote-desugared, ready for
@@ -95,7 +95,7 @@ let rec find_collection dir name =
if String.equal parent dir then None else find_collection parent name
(* A package is a directory, or a single source file named outright. The file
- form is for the program that is also a library: sand.flan sits beside three
+ form is for the program that is also a library: sand.fln sits beside three
other loose .flan files, so naming its directory would import all four, and
moving it into one of its own would be arranging the tree around a
limitation. A file carries no [.c] and no [link] — those belong to a
diff --git a/lib/prelude.ml b/lib/prelude.ml
index 8a227ded..d2f0041a 100644
--- a/lib/prelude.ml
+++ b/lib/prelude.ml
@@ -106,7 +106,7 @@ let source = {flan|
;; what it buys is a *different element*, silently.
;;
;; The restarts that matter are the ones the program already established — a
-;; frame loop's `continue`, sand.flan's shape — and they are on the restart
+;; frame loop's `continue`, sand.fln's shape — and they are on the restart
;; stack and reachable from a handler or from the break loop without anything
;; being pushed here. That is plan.org's "restarts go at the resync point,
;; once", with allocation and file failure as the named exceptions and this on
@@ -985,7 +985,7 @@ let source = {flan|
;;
;; They are here anyway, because the alternative on offer today is worse: a
;; caller that wants an angle writes the same two `declare` lines at the top
-;; of its own file (examples/core-input-gestures-testbed.flan did, before
+;; of its own file (examples/core-input-gestures-testbed.fln did, before
;; this), which is the identical libm call with the identical caveat and
;; nobody's name on it. One copy with the caveat written down beats a copy per
;; file with none.
@@ -1217,7 +1217,7 @@ let source = {flan|
;; **Which face to use.** The i64 of nanoseconds is exact and is what a
;; difference should be taken in. The f64 of seconds is what a frame loop
;; wants, and it is the shape raylib's `get-time` already answers with
-;; (vendor/raylib/raylib.flan, `(declare-c get-time [] f64 "GetTime")`), so the
+;; (vendor/raylib/raylib.fln, `(declare-c get-time [] f64 "GetTime")`), so the
;; two mix without a conversion at every site. The monotonic origin is latched
;; at the first read rather than being boot — see runtime/flan_rt.c — so that
;; the f64 stays integer-exact in nanoseconds for a hundred days of process
@@ -2469,7 +2469,7 @@ let source = {flan|
;; Whether a form is the empty list, (). [form-items] cannot answer this: it
;; returns the empty slice for a non-list too, so "no items" and "not a list"
;; arrive the same. A macro that has to tell `()` from a name needs the
-;; difference — see vendor/raylib/modes.flan, where a lone () argument is a
+;; difference — see vendor/raylib/modes.fln, where a lone () argument is a
;; body that was not written rather than a body of one form.
(defn is-form-empty-list [f Form] bool
(match f
diff --git a/lib/session.ml b/lib/session.ml
index 30f426b2..54910f12 100644
--- a/lib/session.ml
+++ b/lib/session.ml
@@ -398,7 +398,7 @@ let package_decls t =
(* Which package a file being edited belongs to, if any.
- A form typed into vendor/agent/agent.flan declares [poll], but the running
+ A form typed into vendor/agent/agent.fln declares [poll], but the running
program only ever knew it as [agent/poll]: the alias is chosen by whatever
imported the directory, and is written nowhere in the file itself. Without
this the form splices as a brand-new unrelated name, the evaluation reports
diff --git a/runtime/flan_dyn.c b/runtime/flan_dyn.c
index d3c8fcbf..6c72f526 100644
--- a/runtime/flan_dyn.c
+++ b/runtime/flan_dyn.c
@@ -116,7 +116,7 @@ int8_t flan_vec_push(void *v, const void *elem, int64_t size, int64_t align,
*
* NaN-boxed, in a word. A double is *itself*: the 2^64 minus a NaN's worth of
* bit patterns that are not quiet NaNs are read straight back as f64, at no
- * cost, which is what a language where f64 is first class and where sand.flan
+ * cost, which is what a language where f64 is first class and where sand.fln
* runs a physics loop wants. Everything else hides inside the quiet-NaN space.
*
* The box is sign bit + all-ones exponent + quiet bit, which is
@@ -2927,7 +2927,7 @@ uint8_t flan_dyn_need_bool(flan_dyn v) {
* box's kind was not what the program apparently expected.
*
* Once per *site*, not per value. These casts sit in per-cell-per-frame
- * loops — sand.flan runs at 120fps — and a per-occurrence line would be a
+ * loops — sand.fln runs at 120fps — and a per-occurrence line would be a
* flood rather than a diagnostic. The site is the [loc] text [check.ml]
* passes in, and the table below is keyed on its *bytes* rather than its
* address: the two backends emit their own constants for it and neither
diff --git a/sand.fln b/sand.fln
index 0489adb7..552c7817 100644
--- a/sand.fln
+++ b/sand.fln
@@ -64,8 +64,10 @@ fn settle(row: i32, col: i32) -> ()
1
elif not is-right
-1
+ elif f32(rand()) < 0.5
+ 1
else
- if f32(rand()) < 0.5 then 1 else -1
+ -1
grid[y, col + side] = grid[row, col]
grid[row, col] = 0
velocity[y, col + side] = vel
diff --git a/test/programs/pkg-hidden-main.flan b/test/programs/pkg-hidden-main.flan
index 7d247f31..084ed18c 100644
--- a/test/programs/pkg-hidden-main.flan
+++ b/test/programs/pkg-hidden-main.flan
@@ -1,11 +1,11 @@
;;;; A name the import did not bring.
;;;;
-;;;; sand.flan declares a main and this imports it, so sand/main is a name
+;;;; sand.fln declares a main and this imports it, so sand/main is a name
;;;; somebody might reasonably write — and is not one. Left to the checker it
;;;; would be "unknown name", which is true and unhelpful; the refusal has to
;;;; say the name is missing on purpose. Never built: the refusal is the test.
-(import sand "../../sand.flan")
+(import sand "../../sand.fln")
(defn main [] i32
(sand/main)
diff --git a/test/programs/pkg-shared.flan b/test/programs/pkg-shared.flan
index 4f52442a..31691b8f 100644
--- a/test/programs/pkg-shared.flan
+++ b/test/programs/pkg-shared.flan
@@ -1,11 +1,11 @@
;;;; One package reached along two routes.
;;;;
-;;;; raylib is imported here and again by sand.flan, which this also imports.
+;;;; raylib is imported here and again by sand.fln, which this also imports.
;;;; Loading it twice would declare every binding twice and be refused as a
;;;; collision, so a directory is read once and keyed by its real path. Nothing
;;;; calls into raylib, so nothing links it either.
-(import sand "../../sand.flan")
+(import sand "../../sand.fln")
(import rl "vendor:raylib")
(defn main [] i32
diff --git a/test/programs/raylib-codepoints.flan b/test/programs/raylib-codepoints.flan
index f76b44fb..57a33b7f 100644
--- a/test/programs/raylib-codepoints.flan
+++ b/test/programs/raylib-codepoints.flan
@@ -36,7 +36,7 @@
;;;;
;;;; Nothing here draws, so nothing here needs the TTF the example looks for.
-(import cp "../../examples/text-codepoints-loading.flan")
+(import cp "../../examples/text-codepoints-loading.fln")
(import rl "vendor:raylib")
(defconst max-walk 128)
diff --git a/test/programs/raylib-image-processing.flan b/test/programs/raylib-image-processing.flan
index 4e8de18f..815ff862 100644
--- a/test/programs/raylib-image-processing.flan
+++ b/test/programs/raylib-image-processing.flan
@@ -37,7 +37,7 @@
;;;; at all, so there is nothing in them for an implementation to have an
;;;; opinion about.
-(import ip "../../examples/textures-image-processing.flan")
+(import ip "../../examples/textures-image-processing.fln")
(import rl "vendor:raylib")
;; Three probes, chosen so that between them every shape and the background
diff --git a/test/programs/virtual-controls-headless.flan b/test/programs/virtual-controls-headless.flan
index 80ace528..58fd906b 100644
--- a/test/programs/virtual-controls-headless.flan
+++ b/test/programs/virtual-controls-headless.flan
@@ -26,7 +26,7 @@
;;;; the four directions move the player the four different ways. A crossed
;;;; axis anywhere in nearest-button or move-player changes the hash.
-(import vc "../../examples/core-input-virtual-controls.flan")
+(import vc "../../examples/core-input-virtual-controls.fln")
(import rl "vendor:raylib")
;; A sixtieth of a second, fixed. The real program uses get-frame-time, which
diff --git a/test/test_acceptance.ml b/test/test_acceptance.ml
index eb42c7ab..2d608e3e 100644
--- a/test/test_acceptance.ml
+++ b/test/test_acceptance.ml
@@ -278,28 +278,21 @@ module Pool = struct
done
end
-(* sand.flan is the workspace's own program, edited by hand and not by this
- suite, and three cases here compile it. It still calls the randomness
- functions by names the prelude does not have, so those three cannot check
- until it is brought up to date — and the fixture, rather than a comment, is
- what says so: the moment sand.flan calls (rand) every case below runs again
- with nothing to undo. The one thing that is not automatic is the sand hash,
- which is stale whatever happens because the generator now answers 64 bits
- per draw; its row says so where the number is. *)
+(* sand.fln is the workspace's own program, edited by hand and not by this
+ suite, and several cases here compile it. It once called randomness
+ functions by names the prelude did not have, and was skipped until it
+ called real ones; it now calls `rand`, which the prelude does have, so
+ these cases run unconditionally. The one thing that is not automatic is
+ the sand hash, which is stale whatever happens because the generator now
+ answers 64 bits per draw; its row says so where the number is. *)
let sand_checks =
- match In_channel.with_open_bin "../sand.flan" In_channel.input_all with
- (* The open paren is the test and not the bare name: sand.flan explains
- itself in a comment that says rand-f32 too, and a guard that matched that
- would go on skipping after the calls were fixed — a guard that can never
- release is worse than no guard. *)
- | src -> not (contains src "(rand-f32")
+ match In_channel.with_open_bin "../sand.fln" In_channel.input_all with
+ | _ -> true
| exception _ -> false
let () =
if not sand_checks then
- print_endline
- "acceptance: skipping the cases that compile sand.flan — it calls \
- rand-f32, which is not a name";
+ print_endline "acceptance: skipping the cases that compile sand.fln — it is not there";
match Sys.command "command -v clang > /dev/null 2>&1" with
| 0 ->
let exe = compile "../calc-me.flan" in
@@ -2778,9 +2771,9 @@ let () =
This used to be skipped without FLAN_RAYLIB_H, because the generated
bindings only existed when a header was read. They are committed now —
- vendor/raylib/generated.flan — so it runs on the same terms as every
+ vendor/raylib/generated.fln — so it runs on the same terms as every
other raylib case here: libraylib linkable, and no raylib-devel. That is
- the change stated as a test rather than as a claim. If generated.flan
+ the change stated as a test rather than as a claim. If generated.fln
were ever regenerated empty or stale, this is what would say so, and it
would say so on an ordinary machine rather than only on one with a
header exported. *)
@@ -3126,7 +3119,7 @@ let () =
Texture2D notes above say it: glyph-padding is read by nothing raylib
computes on the CPU, offset-y only moves a glyph when it is drawn, and
of each atlas rectangle only `width` is ever looked at. Those four
- fields rest on the header agreeing with raylib's and on sand.flan
+ fields rest on the header agreeing with raylib's and on sand.fln
looking right, and on nothing else. *)
let raylib_font_out =
"valid yes\n\
@@ -3150,7 +3143,7 @@ let () =
(* Again at -O0. Everything above runs through mem2reg, which launders a
sloppy alloca; -O0 tests the IR actually emitted, so a disagreement
between the two points at undefined behaviour rather than a typo. *)
- (* sand.flan's simulation, headless. This is the milestone-4 acceptance
+ (* sand.fln's simulation, headless. This is the milestone-4 acceptance
case: N frames from a seeded PRNG, one hash. It imports the sim package
and not raylib, deliberately — a program that imports raylib links
libraylib on every target, and this one is the version meant to run on
@@ -3686,7 +3679,7 @@ let () =
outputs "an imported package nothing calls, -O0" ~opt:"-O0"
"programs/pkg-unused.flan" "ok\n";
(* A package may import a package, and one reached along two routes is read
- once: pkg-shared imports sand.flan, which imports raylib, and imports
+ once: pkg-shared imports sand.fln, which imports raylib, and imports
raylib itself. Loading it twice would declare every binding twice. *)
if sand_checks then
outputs "a package reached along two routes" "programs/pkg-shared.flan"
@@ -4022,7 +4015,7 @@ let () =
"programs/generic-map-reject.flan" "at $t = f64";
(* This one is refused either way, so the guard is about *which* refusal:
- with sand.flan out of date the file stops at the import and the needle
+ with sand.fln out of date the file stops at the import and the needle
below would pass on the wrong error. *)
if sand_checks then
refuses "a package's main is not visible" "programs/pkg-hidden-main.flan"
@@ -6291,7 +6284,7 @@ level "1"
of the program's three cross-kind cast *sites*, the third being the
(f32 int-box) after the loop. That count is the whole reason the
runtime carries a table of sites at all: these casts live in frame
- loops, sand.flan's at 120fps, and a flood is not a diagnostic.
+ loops, sand.fln's at 120fps, and a flood is not a diagnostic.
[run] merges stderr into stdout, so the warnings and the numbers come
back in one string and the count is a count over it. *)
diff --git a/test/test_dev.ml b/test/test_dev.ml
index e7940991..89ba8cb1 100644
--- a/test/test_dev.ml
+++ b/test/test_dev.ml
@@ -670,13 +670,13 @@ let () =
either. The daemon derives the package from the path, so
the file this is sent with is the one the import qualified. *)
let agent_file =
- let p = "../vendor/agent/agent.flan" in
+ let p = "../vendor/agent/agent.fln" in
try Unix.realpath p with Unix.Unix_error _ -> p
in
let r =
request c
(Printf.sprintf
- "(:op \"eval\" :code \"(defstruct Blob [id i32])\" :file %s)"
+ "(:op \"eval\" :code \"struct Blob(id: i32)\" :file %s)"
(Wire.quote agent_file))
in
if status r <> "ok" then
@@ -8924,7 +8924,7 @@ let () =
half of the same claim and lives where it always did. *)
(* ── A program that starts its agent late ──────────────────────────
- The shape a real one has: sand.flan opens a window and starts the
+ The shape a real one has: sand.fln opens a window and starts the
agent afterwards, so the program's own [(agent/start ...)] is seconds
into the run. The merged session used to wait up to ten seconds for the
socket *before* running its accept loop, which charged those seconds to
diff --git a/test/test_flan.ml b/test/test_flan.ml
index 59b8221e..bfdd2a08 100644
--- a/test/test_flan.ml
+++ b/test/test_flan.ml
@@ -860,8 +860,9 @@ let () =
Printf.printf "FAIL %s does not parse: %s: %s\n"
path (Loc.to_string loc) msg)
(* dune runs tests in _build/default/test/; the corpus is declared as a
- dep in test/dune and lands at the build root. *)
- [ "../calc-me.flan"; "../sand.flan" ];
+ dep in test/dune and lands at the build root. sand is .fln now
+ (decision 130), so it is not here — this reads the paren syntax only. *)
+ [ "../calc-me.flan" ];
Test_support.report ~label:"parse" ()
diff --git a/test/test_session.ml b/test/test_session.ml
index f7bbcc17..7924856b 100644
--- a/test/test_session.ml
+++ b/test/test_session.ml
@@ -16,19 +16,15 @@ let () = Watchdog.arm ~seconds:600 "test_session"
let fail fmt = Test_support.fail fmt
let has = Test_support.contains
-(* sand.flan is the workspace's own program, edited by hand and not by this
+(* sand.fln is the workspace's own program, edited by hand and not by this
suite, and three cases below read it: it is the file with imports, and it is
- the single-file package. While it calls the randomness functions by names
- the prelude does not have it does not check at all, and those three would be
- reporting that rather than anything about a session. The fixture decides,
- so there is nothing to undo once sand.flan is brought up to date. *)
+ the single-file package. It once called randomness functions by names the
+ prelude did not have; it now calls `rand`, which the prelude does have, so
+ these cases run unconditionally — see test_acceptance.ml, which guards on
+ the same file for the same reason. *)
let sand_checks =
- match In_channel.with_open_bin "../sand.flan" In_channel.input_all with
- (* The open paren and not the bare name — see test_acceptance.ml, which
- guards on the same file for the same reason: sand.flan names rand-f32 in
- a comment as well, and matching that would leave these skipped for ever.
- *)
- | src -> not (has src "(rand-f32")
+ match In_channel.with_open_bin "../sand.fln" In_channel.input_all with
+ | _ -> true
| exception _ -> false
(* Every rejection is asserted on its reason, not just on the failure: the
@@ -760,23 +756,24 @@ let () =
keeps the *expanded* declarations, so the package's names are replaced in
place rather than appended a second time and rejected as duplicates. *)
if not sand_checks then
- print_endline
- "session: skipping the cases that read sand.flan — it calls rand-f32, \
- which is not a name"
+ print_endline "session: skipping the cases that read sand.fln — it is not there"
else begin
- let t, _ = Session.create ~file:"../sand.flan" () in
- let src = In_channel.with_open_bin "../sand.flan" In_channel.input_all in
+ let t, _ = Session.create ~file:"../sand.fln" () in
+ let src = In_channel.with_open_bin "../sand.fln" In_channel.input_all in
(* [~origin] is the buffer's own path and both editor paths send it
(flan.el's `:file (or buffer-file-name "")`). Omitting it here
was testing a request the editor never sends. It used to matter to this
- case for a second reason — sand.flan embedded brush.png, and an embedded
+ case for a second reason — sand.fln embedded brush.png, and an embedded
path resolves relative to the file the form is written in, so the default
- origin of "" found nothing. sand.flan has no embed any more; the
+ origin of "" found nothing. sand.fln has no embed any more; the
first reason is the one that stands. *)
- (match Session.eval ~origin:"../sand.flan" t src with
+ (match
+ Source.with_code ~syntax:Source.Indented ~at:None (fun () ->
+ Session.eval ~origin:"../sand.fln" t src)
+ with
| c ->
if not (List.mem "game-draw" c.Session.fns) then
- fail "reloading sand.flan did not include its own functions"
+ fail "reloading sand.fln did not include its own functions"
| exception Loc.Error { Loc.dmsg = m; _ } ->
fail "reloading a file with imports failed: %s" m)
end;
@@ -1418,9 +1415,9 @@ let () =
that can decide it — which is why it is derived here and not sent by the
editor. *)
if sand_checks then begin
- let t, _ = Session.create ~file:"../sand.flan" () in
+ let t, _ = Session.create ~file:"../sand.fln" () in
(match
- Session.eval ~origin:"../vendor/agent/agent.flan" t
+ Session.eval ~origin:"../vendor/agent/agent.fln" t
"(defn poll [] i32 (poll-raw))"
with
| c ->
@@ -1428,13 +1425,13 @@ let () =
fail "a form from a package file reported %s, wanted agent/poll"
(String.concat " " c.Session.fns)
| exception Loc.Error { Loc.dmsg = m; _ } -> fail "redefining agent/poll: %s" m);
- (* A package that is a single file, which is what sand.flan is to the
+ (* A package that is a single file, which is what sand.fln is to the
headless driver. The file being edited *is* the package rather than a
member of a directory, so matching on the directory alone would answer
"not a package" — and the failure is the silent one above: the form
splices as a bare [step] and the running program keeps the one it had. *)
let t2, _ = Session.create ~file:"programs/sand-headless.flan" () in
- (match Session.eval ~origin:"../sand.flan" t2 "(defn step [] () (do))" with
+ (match Session.eval ~origin:"../sand.fln" t2 "(defn step [] () (do))" with
| c ->
if c.Session.fns <> [ "sand/step" ] then
fail "a form from a single-file package reported %s, wanted sand/step"
@@ -1442,7 +1439,7 @@ let () =
| exception Loc.Error { Loc.dmsg = m; _ } -> fail "redefining sand/step: %s" m);
(* And a file that is not a package keeps its names as written. *)
- (match Session.eval ~origin:"../sand.flan" t "(defn game-draw [] () (do))" with
+ (match Session.eval ~origin:"../sand.fln" t "(defn game-draw [] () (do))" with
| c ->
if c.Session.fns <> [ "game-draw" ] then
fail "a form from the program's own file reported %s"
diff --git a/test/test_syntax.ml b/test/test_syntax.ml
index d64e413d..78d363f7 100644
--- a/test/test_syntax.ml
+++ b/test/test_syntax.ml
@@ -252,7 +252,9 @@ let pair flan fln =
let () =
pair "syntax/algorithms.flan" "syntax/algorithms.fln";
- pair "../sand.flan" "syntax/sand.fln";
+ (* sand itself is .fln now (decision 130), so there is no more paren
+ original to pair it against here; syntax/sand.fln is still checked
+ below. *)
pair "syntax/infer/main.flan" "syntax/infer/main.fln";
(* Checked, never run: sand opens a window. *)
List.iter
diff --git a/test/test_web.ml b/test/test_web.ml
index a4130555..19e577a7 100644
--- a/test/test_web.ml
+++ b/test/test_web.ml
@@ -174,7 +174,7 @@ let () =
end;
(* ── raylib in the browser ────────────────────────────────────────
- The claim docs/BUILT.md left open. core-basic-window.flan is built for the
+ The claim docs/BUILT.md left open. core-basic-window.fln is built for the
web unchanged — no edit to its `until` loop, which is the whole point
of choosing asyncify over emscripten_set_main_loop — and the module is
then read for the two things that prove the claim rather than assert
@@ -203,7 +203,7 @@ let () =
fail "no GL imports in the module — raylib did not link";
cleanup out);
- (* ── sand.flan, the flagship, for the browser ──────────────────
+ (* ── sand.fln, the flagship, for the browser ──────────────────
The program the whole target was wanted for, and the last web build
in this process on purpose — see [raylib_web] on why anything after
it would pick the archive up silently.
@@ -233,8 +233,8 @@ let () =
paints. Only a human opening it can say that; docs/BUILT.md carries the
commands. *)
let out = Filename.concat scratch "flan-web-sand.html" in
- (match web_build "../sand.flan" out with
- | exception Failure m -> fail "sand.flan for the browser: %s" m
+ (match web_build "../sand.fln" out with
+ | exception Failure m -> fail "sand.fln for the browser: %s" m
| () ->
let html, js, wasm = parts out in
List.iter
diff --git a/vendor/agent/flan_agent.web.c b/vendor/agent/flan_agent.web.c
index 6c8bd477..0ab375cf 100644
--- a/vendor/agent/flan_agent.web.c
+++ b/vendor/agent/flan_agent.web.c
@@ -29,7 +29,7 @@
* is no editor, no socket, and no session — `--dev` is refused by name on
* every wasm target, so a web build has no cells to install a redefinition
* into even if one arrived. There is nothing to lose because there was never
- * anything there. sand.flan already says the same thing about a *native*
+ * anything there. sand.fln already says the same thing about a *native*
* release build, at the call site:
*
* "Building without --dev is fine — nothing has cells to install into, so a
@@ -44,9 +44,9 @@
*
* It was the other candidate and it is ruled out by arithmetic, not taste.
* Flan has no conditional compilation, so a program cannot say "skip this on
- * web". sand.flan calls (agent/start ...) unconditionally, Reach cannot prune
+ * web". sand.fln calls (agent/start ...) unconditionally, Reach cannot prune
* a package something reachable calls into, and a build-time refusal would
- * therefore mean sand.flan does not build for the browser at all without being
+ * therefore mean sand.fln does not build for the browser at all without being
* edited into a second program. Refusing is only honest when the caller has a
* way to not ask; here it has none.
*
diff --git a/vendor/edn/edn.fln b/vendor/edn/edn.fln
index eedfc4c5..394a1997 100644
--- a/vendor/edn/edn.fln
+++ b/vendor/edn/edn.fln
@@ -5,9 +5,9 @@
;;;; anything: every token's text is a `slice` of the input buffer, not a copy
;;;; of it.
;;;;
-;;;; Two layers sit above it. `read.flan`, in this package, is the one that
-;;;; exists: `(edn/read bytes)` walks this cursor and answers a dynamic
-;;;; `Value`. The other, `(read-edn Enemy bytes)` emitting a parser from a
+;;;; Two layers sit above it. `read.fln`, in this package, is the one that
+;;;; exists: `edn/read(bytes)` walks this cursor and answers a dynamic
+;;;; `Value`. The other, `read-edn(Enemy, bytes)` emitting a parser from a
;;;; compile-time walk over a struct's fields, belongs to the compiler and is
;;;; not here; until it exists a caller writes the struct reader by hand
;;;; against this cursor, and test/programs/edn.flan is a worked example of
@@ -29,19 +29,19 @@
;;;; the kind of contract that otherwise gets discovered from a corrupted
;;;; string three frames later.
;;;;
-;;;; **`read.flan` does not follow this rule, deliberately.** The two layers of
+;;;; **`read.fln` does not follow this rule, deliberately.** The two layers of
;;;; this package diverge on exactly this point: a Token is a view, and a Value
;;;; owns copies of every string in it. The reason is that a view is a fine
;;;; thing for a cursor a caller is driving inside the function that holds the
;;;; buffer, and a trap for a document handed back out of one. Said the other
;;;; way: the contract above is a property of the *layer*, not of the package,
-;;;; and a caller who mixes them — holding a Token out of an `(edn/read ...)`
+;;;; and a caller who mixes them — holding a Token out of an `edn/read(...)`
;;;; that has returned — is on the tokenizer's terms and not the reader's.
;;;;
;;;; ── What is refused, and why ────────────────────────────────────────
;;;;
;;;; Every refusal below is a *named* one with a reason attached, reachable as
-;;;; (edn/error-message code). A tokenizer that quietly skipped what it did not
+;;;; edn/error-message(code). A tokenizer that quietly skipped what it did not
;;;; understand would hand a caller a value that is not the one in the file.
;;;;
;;;; escaped strings "a\nb", "a\"b" — the important one. Unescaping needs
@@ -81,9 +81,9 @@
;;;;
;;;; On the cursor, not in the return type. `next` answers a Token whose kind
;;;; is tok-error, and the cursor carries the code and the byte offset it was
-;;;; found at; (edn/error-message code) turns the code into the sentence. The
+;;;; found at; edn/error-message(code) turns the code into the sentence. The
;;;; offset is the point: an editor underlines a byte range, and an Option with
-;;;; no position could not tell it where. An (Option Token) was the alternative
+;;;; no position could not tell it where. An Option(Token) was the alternative
;;;; and it loses exactly that — None says something went wrong, and a second
;;;; out-parameter for the position is the same two fields with a worse shape.
;;;;
@@ -93,7 +93,7 @@
;; ── Token kinds ─────────────────────────────────────────────────────
;;
-;; Plain i32 constants and not a `defenum`, which is the shape that wants
+;; Plain i32 constants and not an `enum`, which is the shape that wants
;; explaining. An enum here is FFI-only: `=` on an Enum value fails in emit,
;; and a keyword is not a pattern, so `match` cannot see one either. Both fixes
;; live in check.ml and emit.ml, which this lane does not touch. An i32 loses
@@ -101,7 +101,7 @@
;; actually branch on, which is the whole job.
const tok-eof = 0 ; the input is exhausted; text is empty
-const tok-error = 1 ; see (edn/error c) and (edn/error-message ...)
+const tok-error = 1 ; see edn/error(c) and edn/error-message(...)
const tok-nil = 2 ; nil
const tok-bool = 3 ; true / false — text is the word
const tok-int = 4 ; text parses as i64
@@ -379,7 +379,7 @@ fn- read-string(c: Ptr(Cursor), lo: i32) -> Token
;; The one call a caller makes. Advances the cursor past the token it returns.
;;
;; A cursor that has already failed keeps answering the same error token and
-;; does not advance, so `(while (!= (.kind t) tok-eof) ...)` terminates on a
+;; does not advance, so `while t.kind != tok-eof ...` terminates on a
;; malformed file instead of spinning.
fn next(c: Ptr(Cursor)) -> Token
if not is-ok(c)
diff --git a/vendor/edn/provide.fln b/vendor/edn/provide.fln
index 2ccc6d9b..d8c7bb83 100644
--- a/vendor/edn/provide.fln
+++ b/vendor/edn/provide.fln
@@ -1,13 +1,13 @@
;;;; defedn: a struct derived from a data file, at compile time.
;;;;
;;;; F#'s type providers, with the part that makes them worth having and none
-;;;; of the part that needs a plugin protocol. `(edn/defedn Tileset "t.edn")`
+;;;; of the part that needs a plugin protocol. `edn/defedn(Tileset, "t.edn")`
;;;; reads t.edn while the program is being compiled, works out what shape it
;;;; is, and emits the struct that shape implies together with a reader for it.
;;;; From then on `(.texture-path data)` is a field load off a struct: no Value,
;;;; no match, no runtime tag, nothing to look up by name.
;;;;
-;;;; read.flan is the other half of the same choice, and both belong here. A
+;;;; read.fln is the other half of the same choice, and both belong here. A
;;;; dynamic Value is what you want when the shape is the program's *input* —
;;;; an editor opening a file it has never seen. A provider is what you want
;;;; when the shape is part of the program and only the numbers change, which
@@ -20,25 +20,25 @@
;;;; able to run arbitrary code at expansion time. Three things it could not do
;;;; are what this file rests on, and all three are general:
;;;;
-;;;; - `(macro-slurp "t.edn")` reads a file at expansion time, resolved the
-;;;; way `(embed "t.edn")` resolves a path — against the directory of the
+;;;; - `macro-slurp("t.edn")` reads a file at expansion time, resolved the
+;;;; way `embed("t.edn")` resolves a path — against the directory of the
;;;; source file the form is written in.
;;;; - a package's macro may call the package's own functions, which is why
;;;; the derivation below is ordinary Flan over the tokenizer next door
;;;; rather than a second scanner inlined into a macro body.
-;;;; - a macro may answer several declarations, as a top-level `(do ...)`,
-;;;; and may refuse with a sentence through `(compile-error "...")`.
+;;;; - a macro may answer several declarations, as a top-level `do:`,
+;;;; and may refuse with a sentence through `compile-error("...")`.
;;;;
;;;; ── The rules ────────────────────────────────────────────────────────
;;;;
;;;; A map with keyword keys is a struct, one field per key, named for the
;;;; keyword. An integer is an i64, a float an f64, a boolean a bool, a string
-;;;; a `string` — copied, which is read.flan's contract and not the tokenizer's:
+;;;; a `string` — copied, which is read.fln's contract and not the tokenizer's:
;;;; a Token's text points into the buffer, and a struct that outlives the
;;;; buffer cannot hold one.
;;;;
-;;;; A vector of one repeated shape is a `(Vec T)`. A set is this repo's own
-;;;; spelling of one, `(Map T bool)` — check.ml says exactly that where it
+;;;; A vector of one repeated shape is a `Vec(T)`. A set is this repo's own
+;;;; spelling of one, `Map(T, bool)` — check.ml says exactly that where it
;;;; refuses a map with a `()` value — and its elements are therefore read as
;;;; map *keys*. That is why a vector inside a set derives to a fixed array
;;;; `[n T]` rather than to a Vec: a Vec is not a map key and `[2 i64]` is.
@@ -65,7 +65,7 @@ fn- joined(a: str, b: str) -> str
fn- joined3(a: str, b: str, c: str) -> str = joined(a, joined(b, c))
-;; Copied out, and not `(str (i64->bytes n))`. The prelude's note over
+;; Copied out, and not `str(i64->bytes(n))`. The prelude's note over
;; append-i64 is the reason: i64->bytes renders into one shared static buffer
;; in the runtime, so two of its results cannot be held at once — and `where`
;; below holds a line and a column at the same time, which read as the same
@@ -145,7 +145,7 @@ fn need-bool(c: Ptr(Cursor)) -> bool
None -> false
;; Copied into the allocator, which is the whole difference between a field of
-;; a struct and a Token's text. The lifetime contract at the top of edn.flan is
+;; a struct and a Token's text. The lifetime contract at the top of edn.fln is
;; the reason: `text` is a slice of the buffer, and a struct read out of a
;; buffer that is later freed would hold a dangling one.
fn need-string(c: Ptr(Cursor), a: Allocator) -> str
@@ -210,7 +210,9 @@ struct ReadFailed(struct: str, code: i32, pos: i32)
fn- derive(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
let t = next(c)
if not is-ok(c)
- return derived-bad(joined3("the data file could not be read at ", where(src, error-pos(c)), joined(": ", error-message(c.err))))
+ return derived-bad(joined3("the data file could not be read at ",
+ where(src, error-pos(c)),
+ joined(": ", error-message(c.err))))
if t.kind == tok-int
ok-derived(quasiquote(i64), form-nil(), quasiquote(need-int(c)))
elif t.kind == tok-float
@@ -226,9 +228,11 @@ fn- derive(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
elif t.kind == tok-set-open
derive-set(c, name, t.pos, src)
elif t.kind == tok-nil
- derived-bad(joined3("the nil at ", where(src, t.pos), " has no type to derive — a field that is sometimes absent is not something a struct can hold, so give it a value in the file or take the key out"))
+ derived-bad(joined3("the nil at ", where(src, t.pos),
+ " has no type to derive — a field that is sometimes absent is not something a struct can hold, so give it a value in the file or take the key out"))
else
- derived-bad(joined3("the value at ", where(src, t.pos), " is not one defedn derives a type from — a map, a vector, a set, an integer, a float, a boolean or a string"))
+ derived-bad(joined3("the value at ", where(src, t.pos),
+ " is not one defedn derives a type from — a map, a vector, a set, an integer, a float, a boolean or a string"))
;; A vector, whose elements must all come to the same type. The first element
;; decides; every one after it is compared against that decision and both
@@ -236,7 +240,8 @@ fn- derive(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
;; saying where sends someone to read the whole file.
fn- derive-vec(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Derived
if is-at-byte(c, \])
- return derived-bad(joined3("the empty vector at ", where(src, at-pos), " has no element to derive an element type from — defedn reads the shape out of the data, and an empty collection carries none"))
+ return derived-bad(joined3("the empty vector at ", where(src, at-pos),
+ " has no element to derive an element type from — defedn reads the shape out of the data, and an empty collection carries none"))
let head = derive(c, joined(name, "-item"), src)
if is-bad(head)
return head
@@ -255,29 +260,34 @@ fn- derive-vec(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Deriv
cn = Form.Sym{.s joined(name, "-new")}
ok-derived(ty,
with-decl(head.decls, quasiquote(defn(~cn, [a Allocator], ~ty, vec-new(a)))),
- quasiquote(let([xs ~cn(a)], expect(c, tok-vec-open), while(is-ok(c) and not is-at-byte(c, \]), push(xs, ~read1)), expect(c, tok-vec-close), xs)))
+ quasiquote(let([xs ~cn(a)],
+ expect(c, tok-vec-open),
+ while(is-ok(c) and not is-at-byte(c, \]), push(xs, ~read1)),
+ expect(c, tok-vec-close),
+ xs)))
;; Why every collection gets a one-line constructor of its own.
;;
-;; `(vec-new)` and `(map-new)` each need to be told what they build, and the
+;; `vec-new()` and `map-new()` each need to be told what they build, and the
;; way to tell them in argument position is to *name* a type: check.ml's
;; vec_new_elem and map_new_types take an `Ast.Var` and nothing else. A type
-;; this derives may have no name — `(Vec i64)` has none, and `[2 i64]`, which
+;; this derives may have no name — `Vec(i64)` has none, and `[2 i64]`, which
;; is the key of the set in the file this was built for, has none either.
;;
;; Both fall back to what the context wants, and a function's return type is a
;; type position where anything can be written. So the type is stated once, in
;; a signature, and the bare call in the body gets it from `want`. It is also
-;; the more readable expansion: the reader says `(cells-new a)` where it would
+;; the more readable expansion: the reader says `cells-new(a)` where it would
;; otherwise carry a type nobody wrote.
fn- with-decl(decls: [Form], d: Form) -> [Form]
form-append(decls, form-cons(d, form-nil()))
-;; A set becomes `(Map T bool)`, so its elements are map keys. `derive-key` is
+;; A set becomes `Map(T, bool)`, so its elements are map keys. `derive-key` is
;; where that constraint is enforced and said.
fn- derive-set(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Derived
if is-at-byte(c, \})
- return derived-bad(joined3("the empty set at ", where(src, at-pos), " has no element to derive an element type from"))
+ return derived-bad(joined3("the empty set at ", where(src, at-pos),
+ " has no element to derive an element type from"))
let head = derive-key(c, joined(name, "-key"), src)
if is-bad(head)
return head
@@ -296,11 +306,15 @@ fn- derive-set(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Deriv
cn = Form.Sym{.s joined(name, "-new")}
ok-derived(ty,
with-decl(head.decls, quasiquote(defn(~cn, [a Allocator], ~ty, map-new(a)))),
- quasiquote(let([tbl ~cn(a)], expect(c, tok-set-open), while(is-ok(c) and not is-at-byte(c, \}), put(tbl, ~read1, true)), expect(c, tok-map-close), tbl)))
+ quasiquote(let([tbl ~cn(a)],
+ expect(c, tok-set-open),
+ while(is-ok(c) and not is-at-byte(c, \}), put(tbl, ~read1, true)),
+ expect(c, tok-map-close),
+ tbl)))
;; One element of a set. The scalars that are map keys pass; a vector becomes a
;; fixed array, which is one where a Vec is not; anything else is refused here
-;; rather than at the `(Map ...)` the caller would build out of it, because a
+;; rather than at the `Map(...)` the caller would build out of it, because a
;; map-key refusal names a type nobody wrote.
fn- derive-key(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
if is-at-byte(c, \[)
@@ -309,7 +323,8 @@ fn- derive-key(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
if is-bad(d)
return d
if not is-key-type(d.ty)
- return derived-bad(joined3("a set of ", render(d.ty), " is not something this builds: a set becomes a (Map T bool), so its elements are map keys. Integers, booleans, strings and vectors of those are"))
+ return derived-bad(joined3("a set of ", render(d.ty),
+ " is not something this builds: a set becomes a (Map T bool), so its elements are map keys. Integers, booleans, strings and vectors of those are"))
d
;; A vector in key position. Its length is part of its type, so every element
@@ -319,7 +334,8 @@ fn- derive-key(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
fn- derive-array(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
let open = next(c)
if is-at-byte(c, \])
- return derived-bad(joined3("the empty vector at ", where(src, open.pos), " is inside a set, and an empty fixed array has no element type and no length"))
+ return derived-bad(joined3("the empty vector at ", where(src, open.pos),
+ " is inside a set, and an empty fixed array has no element type and no length"))
let head = derive(c, joined(name, "-item"), src)
if is-bad(head)
return head
@@ -333,16 +349,26 @@ fn- derive-array(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
n += 1
expect(c, tok-vec-close)
if not is-key-type(head.ty)
- return derived-bad(joined3("a set of vectors of ", render(head.ty), " is not something this builds: the vector becomes a fixed array, which is a map key only when its elements are compared bytewise"))
+ return derived-bad(joined3("a set of vectors of ", render(head.ty),
+ " is not something this builds: the vector becomes a fixed array, which is a map key only when its elements are compared bytewise"))
let elem = head.ty
read1 = head.reader
count = Form.Int{.i n}
ok-derived(quasiquote([~count ~elem]), head.decls,
- quasiquote(let([arr array(~count, ~elem) i 0], expect(c, tok-vec-open), while(is-ok(c) and not is-at-byte(c, \]) and i < ~count, set(arr[i], ~read1), set(i, i + 1)), expect(c, tok-vec-close), arr)))
+ quasiquote(let([arr array(~count, ~elem) i 0],
+ expect(c, tok-vec-open),
+ while(is-ok(c) and not is-at-byte(c, \]) and i < ~count,
+ set(arr[i], ~read1), set(i, i + 1)),
+ expect(c, tok-vec-close),
+ arr)))
fn- disagreement(what: str, src: [const u8], at-pos: i32, n: i64, first: Form, second: Form) -> str
joined3(joined3("the ", what, " at "), where(src, at-pos),
- joined3(joined3(" holds more than one shape: its first element is ", render(first), " and element "), i64->string(n), joined3(" is ", render(second), ". Every element has to be the same shape, because the type this becomes has one element type")))
+ joined3(joined3(" holds more than one shape: its first element is ", render(first),
+ " and element "),
+ i64->string(n),
+ joined3(" is ", render(second),
+ ". Every element has to be the same shape, because the type this becomes has one element type")))
;; ── A map, which is a struct ────────────────────────────────────────
;;
@@ -357,7 +383,8 @@ fn- disagreement(what: str, src: [const u8], at-pos: i32, n: i64, first: Form, s
;; Both signal SchemaDrift. See the note over that type.
fn- derive-map(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Derived
if is-at-byte(c, \})
- return derived-bad(joined3("the empty map at ", where(src, at-pos), " has no keys to derive fields from — a struct with no fields is not a shape anything can be read into"))
+ return derived-bad(joined3("the empty map at ", where(src, at-pos),
+ " has no keys to derive fields from — a struct with no fields is not a shape anything can be read into"))
let fields = vec-new(Form) ; the defstruct's [name type ...] vector
clauses = vec-new(Form) ; the reader's cond: test, body, test, body
missing = vec-new(Form) ; one per field, checked when the map closes
@@ -366,9 +393,13 @@ fn- derive-map(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Deriv
while is-ok(c) and not is-at-byte(c, \})
let k = next(c)
if not is-ok(c)
- return derived-bad(joined3("the data file could not be read at ", where(src, error-pos(c)), joined(": ", error-message(c.err))))
+ return derived-bad(joined3("the data file could not be read at ",
+ where(src, error-pos(c)),
+ joined(": ", error-message(c.err))))
if k.kind != tok-keyword
- return derived-bad(joined3(joined3("the map at ", where(src, at-pos), " has a key at "), where(src, k.pos), " that is not a keyword. A struct's fields are named, so every key of a map defedn reads has to be one — :name, not \"name\" and not 1"))
+ return derived-bad(joined3(joined3("the map at ", where(src, at-pos), " has a key at "),
+ where(src, k.pos),
+ " that is not a keyword. A struct's fields are named, so every key of a map defedn reads has to be one — :name, not \"name\" and not 1"))
let fname = copy-text(k.text)
let d = derive(c, joined3(name, "-", fname), src)
if is-bad(d)
@@ -388,7 +419,9 @@ fn- derive-map(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Deriv
;; bit is decided here, where the field is, so the two cannot fall
;; out of step the way a parallel list of names would.
push(missing,
- quasiquote(when seen && ~bit == 0 then signal(SchemaDrift{.field ~lit .struct ~(Form.Str{.s name}) .is-extra false .pos k.pos})))
+ quasiquote(when seen && ~bit == 0 then
+ signal(SchemaDrift{.field ~lit .struct ~(Form.Str{.s name})
+ .is-extra false .pos k.pos})))
idx += 1
expect(c, tok-map-close)
;; An unknown key. The hand-written reader skips one, which is right when a
@@ -398,7 +431,9 @@ fn- derive-map(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Deriv
;; handle the condition still reads the rest.
push(clauses, quasiquote(:else))
push(clauses,
- quasiquote(do(signal(SchemaDrift{.field copy-text(k.text) .struct ~(Form.Str{.s name}) .is-extra true .pos k.pos}), when not skip-value(c) then return out)))
+ quasiquote(do(signal(SchemaDrift{.field copy-text(k.text) .struct ~(Form.Str{.s name})
+ .is-extra true .pos k.pos}),
+ when not skip-value(c) then return out)))
let sname = Form.Sym{.s name}
rname = Form.Sym{.s joined("read-", name)}
let (struct) = quasiquote(defstruct(~sname, ~(Form.Vec{.xs slice(fields)})))
@@ -428,7 +463,7 @@ fn- is-same-type(a: Form, b: Form) -> bool
is-bytes-equal(bytes-view(render(a)), bytes-view(render(b)))
;; A type form as text, for the refusals. Only the shapes this file builds — a
-;; name, a number, `(Vec T)`, `(Map K V)` and `[n T]` — because nothing else
+;; name, a number, `Vec(T)`, `Map(K, V)` and `[n T]` — because nothing else
;; ever reaches it.
fn render(f: Form) -> str
match f
@@ -449,12 +484,13 @@ fn- render-items(xs: [Form]) -> str
;; itself, so there is no equality for a map to hash.
fn- is-key-type(t: Form) -> bool
let s = bytes-view(render(t))
- is-bytes-equal(s, bytes-view("i64")) or (is-bytes-equal(s, bytes-view("bool")) or is-bytes-equal(s, bytes-view("string")))
+ is-bytes-equal(s, bytes-view("i64")) or
+ (is-bytes-equal(s, bytes-view("bool")) or is-bytes-equal(s, bytes-view("string")))
;; ── The macro ───────────────────────────────────────────────────────
;;
-;; `(edn/defedn Tileset "assets/tileset.edn")`. The path is relative to the
-;; file this is written in, exactly as `(embed "assets/tileset.edn")` is — see
+;; `edn/defedn(Tileset, "assets/tileset.edn")`. The path is relative to the
+;; file this is written in, exactly as `embed("assets/tileset.edn")` is — see
;; `macro-slurp` in the prelude, and check.ml's `embed_path`, which is the rule
;; it copies.
;;
@@ -474,7 +510,8 @@ macro defedn(& args)
match macro-slurp(path)
Some(src) -> provide(name, path, src)
None ->
- refuse(joined3("there is no file at ", path, ", read relative to the file this defedn is written in — the same place (embed \"...\") would look"))
+ refuse(joined3("there is no file at ", path,
+ ", read relative to the file this defedn is written in — the same place (embed \"...\") would look"))
_ ->
refuse("defedn's first argument is the name of the struct to declare, written as a name")
_ ->
diff --git a/vendor/edn/read.fln b/vendor/edn/read.fln
index b1d4678b..a5fb88c1 100644
--- a/vendor/edn/read.fln
+++ b/vendor/edn/read.fln
@@ -1,9 +1,9 @@
;;;; The dynamic reader: an EDN document, and no type to read it into.
;;;;
-;;;; `edn.flan` answers "what is the next token". This answers "what is in the
+;;;; `edn.fln` answers "what is the next token". This answers "what is in the
;;;; file", for a caller that has no struct to hand — a config file whose keys
-;;;; are not known until it is read, a tileset, a save. `(edn/defedn T path)`
-;;;; in provide.flan is the other direction: the shape known at compile time,
+;;;; are not known until it is read, a tileset, a save. `edn/defedn(T, path)`
+;;;; in provide.fln is the other direction: the shape known at compile time,
;;;; read into a struct, at no run-time cost. Together they are the two sides
;;;; of one capability, and this is the dynamic one.
;;;;
@@ -59,7 +59,7 @@
;; ── Copying a token's text ──────────────────────────────────────────
;; Not the dyn reader's own — everything below boxes through the runtime,
-;; which copies for itself — but provide.flan's generated readers build typed
+;; which copies for itself — but provide.fln's generated readers build typed
;; strings out of token text and this is where that copy has always lived.
;; The (Vec u8) is the copy; the string is a view of it, and the Vec header is
;; dropped here on purpose. Nothing individually owns a block in a region —
diff --git a/vendor/json/json.fln b/vendor/json/json.fln
index d162e319..fc65fb52 100644
--- a/vendor/json/json.fln
+++ b/vendor/json/json.fln
@@ -3,7 +3,7 @@
;;;; The shape is vendor/edn's, deliberately: a Cursor over a caller's buffer,
;;;; one `next` that answers a Token, errors accumulated on the cursor with the
;;;; byte offset they were found at, and every refusal named and given a reason
-;;;; reachable as (json/error-message code). Read vendor/edn/edn.flan first if
+;;;; reachable as json/error-message(code). Read vendor/edn/edn.fln first if
;;;; you have not; everything that file argues for is argued for there and only
;;;; the differences are argued for here.
;;;;
@@ -26,7 +26,7 @@
;;;;
;;;; * a Token's `text` is a slice INTO the buffer, exactly as edn's is, and
;;;; for a string token it is the RAW interior — backslashes and all;
-;;;; * (json/string-of t) is the one call that allocates. It answers a
+;;;; * json/string-of(t) is the one call that allocates. It answers a
;;;; string whose bytes are a fresh copy in the context's allocator, with
;;;; every escape resolved.
;;;;
@@ -40,7 +40,7 @@
;;;; survive the free-all in the cases that had no escapes and not in the
;;;; others, which is the kind of contract nobody can hold in their head.
;;;;
-;;;; Note what that buys against vendor/edn/read.flan's dyn reader, which
+;;;; Note what that buys against vendor/edn/read.fln's dyn reader, which
;;;; settled the same question a different way: it takes no allocator at all,
;;;; because every string it produces is boxed onto the collector's heap on
;;;; the spot — read-value's "a document owns its strings" rule. This
@@ -53,8 +53,8 @@
;;;; ── The allocator ───────────────────────────────────────────────────
;;;;
;;;; string-of names no allocator and takes no parameter. spec-memory.md puts
-;;;; the allocator in the calling convention, so the (vec-new u8) inside it
-;;;; takes the context's, and (with-allocator frame (json/string-of t)) is the
+;;;; the allocator in the calling convention, so the vec-new(u8) inside it
+;;;; takes the context's, and with-allocator(frame, json/string-of(t)) is the
;;;; whole of "reading against an arena". An explicit allocator at the
;;;; construction site would override that, which is how this would take one if
;;;; the idiom could not express it. It can.
@@ -75,7 +75,7 @@
;;;; single quotes 'x' — legal in JSON5.
;;;; +1 — a leading plus is JSON5's.
;;;; .5 and 1. — JSON5 allows a bare leading or trailing
-;;;; decimal point. Worth contrasting with edn.flan, which
+;;;; decimal point. Worth contrasting with edn.fln, which
;;;; goes the other way and reads `.5` as a float on
;;;; purpose; here it is an error, and named.
;;;; 0x1f — hexadecimal is JSON5's.
@@ -145,12 +145,12 @@
;; ── Token kinds ─────────────────────────────────────────────────────
;;
-;; Plain i32 constants and not a `defenum`, for the reason vendor/edn gives:
+;; Plain i32 constants and not an `enum`, for the reason vendor/edn gives:
;; `=` on an Enum value fails in emit and a keyword is not a pattern, so an
;; enum here would be a token kind a caller could not branch on.
const tok-eof = 0 ; the input is exhausted; text is empty
-const tok-error = 1 ; see (json/error c) and (json/error-message ...)
+const tok-error = 1 ; see json/error(c) and json/error-message(...)
const tok-null = 2 ; null
const tok-bool = 3 ; true / false — text is the word
const tok-int = 4 ; a number with no fraction and no exponent
@@ -555,7 +555,7 @@ fn- read-string(c: Ptr(Cursor), lo: i32) -> Token
;; The one call a caller makes. Advances the cursor past the token it returns.
;;
;; A cursor that has already failed keeps answering the same error token and
-;; does not advance, so `(while (!= (.kind t) tok-eof) ...)` terminates on a
+;; does not advance, so `while t.kind != tok-eof ...` terminates on a
;; malformed document instead of spinning.
fn next(c: Ptr(Cursor)) -> Token
if not is-ok(c)
diff --git a/vendor/json/provide.fln b/vendor/json/provide.fln
index 9aa4d692..8935392b 100644
--- a/vendor/json/provide.fln
+++ b/vendor/json/provide.fln
@@ -1,8 +1,8 @@
;;;; defjson: a struct derived from a JSON file, at compile time.
;;;;
-;;;; `(json/defjson Config "config.json")` reads config.json while the program
+;;;; `json/defjson(Config, "config.json")` reads config.json while the program
;;;; is being compiled, derives the struct its shape implies, and emits that
-;;;; struct with a reader over the tokenizer next door. `(.port cfg)` is then a
+;;;; struct with a reader over the tokenizer next door. `cfg.port` is then a
;;;; field load: no Value, no match, no runtime tag, nothing looked up by name.
;;;;
;;;; It is the same idea as vendor/edn's defedn and deliberately not the same
@@ -16,7 +16,7 @@
;;;;
;;;; ── What is different, and why ───────────────────────────────────────
;;;;
-;;;; **Strings go through `string-of` and never through `.text`.** json.flan's
+;;;; **Strings go through `string-of` and never through `.text`.** json.fln's
;;;; `.text` is the RAW interior of a string token, escapes undecoded, so a
;;;; field read off it would hold a literal backslash-n where the file meant a
;;;; newline. `string-of` is the one call in that package that allocates, and
@@ -31,7 +31,7 @@
;;;; field.
;;;;
;;;; **There are no sets**, so there is no map-key path and no fixed array:
-;;;; every collection here is a `(Vec T)`. defjson is strictly the smaller of
+;;;; every collection here is a `Vec(T)`. defjson is strictly the smaller of
;;;; the two.
;;;;
;;;; JSON has no integer type of its own — the tokenizer draws the line at
@@ -50,7 +50,7 @@ fn- joined(a: str, b: str) -> str
fn- joined3(a: str, b: str, c: str) -> str = joined(a, joined(b, c))
-;; Copied out, and not `(str (i64->bytes n))`: the prelude's note over
+;; Copied out, and not `str(i64->bytes(n))`: the prelude's note over
;; append-i64 is the reason — i64->bytes renders into one shared static buffer
;; in the runtime, so two of its results cannot be held at once, and `where`
;; holds a line and a column at the same time.
@@ -138,7 +138,7 @@ fn is-at-byte(c: Ptr(Cursor), b: u8) -> bool
not is-at-end(c) and c.src[c.pos] == b
;; The comma between two members, taken when there is one. A trailing comma is
-;; json.flan's err-trailing-comma and is the tokenizer's to refuse, not this
+;; json.fln's err-trailing-comma and is the tokenizer's to refuse, not this
;; loop's: taking it here and then meeting the closer is exactly the shape that
;; refusal is written against.
fn comma(c: Ptr(Cursor)) -> ()
@@ -173,7 +173,9 @@ struct ReadFailed(struct: str, code: i32, pos: i32)
fn- derive(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
let t = next(c)
if not is-ok(c)
- return derived-bad(joined3("the data file could not be read at ", where(src, error-pos(c)), joined(": ", error-message(c.err))))
+ return derived-bad(joined3("the data file could not be read at ",
+ where(src, error-pos(c)),
+ joined(": ", error-message(c.err))))
if t.kind == tok-int
ok-derived(quasiquote(i64), form-nil(), quasiquote(need-int(c)))
elif t.kind == tok-float
@@ -187,9 +189,11 @@ fn- derive(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
elif t.kind == tok-array-open
derive-array(c, name, t.pos, src)
elif t.kind == tok-null
- derived-bad(joined3("the null at ", where(src, t.pos), " has no type to derive — a field that is sometimes absent is not something a struct can hold, so give it a value in the file or take the key out"))
+ derived-bad(joined3("the null at ", where(src, t.pos),
+ " has no type to derive — a field that is sometimes absent is not something a struct can hold, so give it a value in the file or take the key out"))
else
- derived-bad(joined3("the value at ", where(src, t.pos), " is not one defjson derives a type from — an object, an array, a number, a boolean or a string"))
+ derived-bad(joined3("the value at ", where(src, t.pos),
+ " is not one defjson derives a type from — an object, an array, a number, a boolean or a string"))
;; An array, whose elements must all come to the same type. The first decides;
;; every one after it is compared against that, and both positions are named
@@ -197,7 +201,8 @@ fn- derive(c: Ptr(Cursor), name: str, src: [const u8]) -> Derived
;; whole file.
fn- derive-array(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Derived
if is-at-byte(c, \])
- return derived-bad(joined3("the empty array at ", where(src, at-pos), " has no element to derive an element type from — defjson reads the shape out of the data, and an empty collection carries none"))
+ return derived-bad(joined3("the empty array at ", where(src, at-pos),
+ " has no element to derive an element type from — defjson reads the shape out of the data, and an empty collection carries none"))
let head = derive(c, joined(name, "-item"), src)
if is-bad(head)
return head
@@ -208,7 +213,12 @@ fn- derive-array(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Der
if is-bad(item)
return item
if not is-same-type(head.ty, item.ty)
- return derived-bad(joined3(joined3("the array at ", where(src, at-pos), " holds more than one shape: element 0 is "), render(head.ty), joined3(joined3(" and element ", i64->string(n), " is "), render(item.ty), ". Every element of an array has to be the same shape, because the (Vec T) it becomes has one element type")))
+ return derived-bad(joined3(joined3("the array at ", where(src, at-pos),
+ " holds more than one shape: element 0 is "),
+ render(head.ty),
+ joined3(joined3(" and element ", i64->string(n), " is "),
+ render(item.ty),
+ ". Every element of an array has to be the same shape, because the (Vec T) it becomes has one element type")))
comma(c)
n += 1
expect(c, tok-array-close)
@@ -216,20 +226,25 @@ fn- derive-array(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Der
read1 = head.reader
ty = quasiquote(Vec(~elem))
cn = Form.Sym{.s joined(name, "-new")}
- ;; The constructor states the type so the bare (vec-new a) in its body
- ;; can take it from `want`. (vec-new) has to be *told* what it builds by
- ;; naming a type, and `(Vec i64)` has no name to be — but a signature is
+ ;; The constructor states the type so the bare vec-new(a) in its body
+ ;; can take it from `want`. vec-new() has to be *told* what it builds by
+ ;; naming a type, and `Vec(i64)` has no name to be — but a signature is
;; a type position where anything can be written. The reader reads
;; better for it too.
ok-derived(ty,
with-decl(head.decls, quasiquote(defn(~cn, [a Allocator], ~ty, vec-new(a)))),
- quasiquote(let([xs ~cn(a)], expect(c, tok-array-open), while(is-ok(c) and not is-at-byte(c, \]), push(xs, ~read1), comma(c)), expect(c, tok-array-close), xs)))
+ quasiquote(let([xs ~cn(a)],
+ expect(c, tok-array-open),
+ while(is-ok(c) and not is-at-byte(c, \]), push(xs, ~read1), comma(c)),
+ expect(c, tok-array-close),
+ xs)))
;; ── An object, which is a struct ────────────────────────────────────
fn- derive-object(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> Derived
if is-at-byte(c, \})
- return derived-bad(joined3("the empty object at ", where(src, at-pos), " has no members to derive fields from — a struct with no fields is not a shape anything can be read into"))
+ return derived-bad(joined3("the empty object at ", where(src, at-pos),
+ " has no members to derive fields from — a struct with no fields is not a shape anything can be read into"))
let fields = vec-new(Form) ; the defstruct's [name type ...] vector
clauses = vec-new(Form) ; the reader's cond: test, body, test, body
missing = vec-new(Form) ; one per field, checked when the object closes
@@ -238,9 +253,13 @@ fn- derive-object(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> De
while is-ok(c) and not is-at-byte(c, \})
let k = next(c)
if not is-ok(c)
- return derived-bad(joined3("the data file could not be read at ", where(src, error-pos(c)), joined(": ", error-message(c.err))))
+ return derived-bad(joined3("the data file could not be read at ",
+ where(src, error-pos(c)),
+ joined(": ", error-message(c.err))))
if k.kind != tok-string
- return derived-bad(joined3("the object at ", joined3(where(src, at-pos), " has a member at ", where(src, k.pos)), " whose name is not a string, which JSON requires"))
+ return derived-bad(joined3("the object at ",
+ joined3(where(src, at-pos), " has a member at ", where(src, k.pos)),
+ " whose name is not a string, which JSON requires"))
;; The comparison in the generated reader is against the token's RAW
;; text, which costs no allocation per key. That is only the same
;; question as "is this the field" when the name has no escape in it —
@@ -249,9 +268,11 @@ fn- derive-object(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> De
;; the file where it would have mattered.
let raw = k.text
if has-escape(raw)
- return derived-bad(joined3("the member name at ", where(src, k.pos), " has an escape in it. A generated reader compares a key against the bytes as written, which costs nothing per key and is only the same question when the name is written plainly — so this one is refused rather than matched wrongly"))
+ return derived-bad(joined3("the member name at ", where(src, k.pos),
+ " has an escape in it. A generated reader compares a key against the bytes as written, which costs nothing per key and is only the same question when the name is written plainly — so this one is refused rather than matched wrongly"))
if not is-name-like(raw)
- return derived-bad(joined3("the member name at ", where(src, k.pos), " is not a name a program could write, so there is no field it can become. A struct's fields are named; letters, digits, - and ? are what a name is made of"))
+ return derived-bad(joined3("the member name at ", where(src, k.pos),
+ " is not a name a program could write, so there is no field it can become. A struct's fields are named; letters, digits, - and ? are what a name is made of"))
expect(c, tok-colon)
let fname = copy-of(raw)
let d = derive(c, joined3(name, "-", fname), src)
@@ -272,7 +293,9 @@ fn- derive-object(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> De
;; beside the field, so the two cannot fall out of step the way a
;; parallel list of names would.
push(missing,
- quasiquote(when seen && ~bit == 0 then signal(SchemaDrift{.field ~lit .struct ~(Form.Str{.s name}) .is-extra false .pos close.pos})))
+ quasiquote(when seen && ~bit == 0 then
+ signal(SchemaDrift{.field ~lit .struct ~(Form.Str{.s name})
+ .is-extra false .pos close.pos})))
comma(c)
idx += 1
expect(c, tok-object-close)
@@ -281,7 +304,9 @@ fn- derive-object(c: Ptr(Cursor), name: str, at-pos: i32, src: [const u8]) -> De
;; program that declines to handle the condition still reads the rest.
push(clauses, quasiquote(:else))
push(clauses,
- quasiquote(do(signal(SchemaDrift{.field match(string-of(k), Some(s), s, None, "") .struct ~(Form.Str{.s name}) .is-extra true .pos k.pos}), when not skip-value(c) then return out)))
+ quasiquote(do(signal(SchemaDrift{.field match(string-of(k), Some(s), s, None, "")
+ .struct ~(Form.Str{.s name}) .is-extra true .pos k.pos}),
+ when not skip-value(c) then return out)))
let sname = Form.Sym{.s name}
rname = Form.Sym{.s joined("read-", name)}
let (struct) = quasiquote(defstruct(~sname, ~(Form.Vec{.xs slice(fields)})))
@@ -343,7 +368,7 @@ fn- is-same-type(a: Form, b: Form) -> bool
is-bytes-equal(bytes-view(render(a)), bytes-view(render(b)))
;; A type form as text, for the refusals. Only the shapes this file builds — a
-;; name and `(Vec T)` — because nothing else ever reaches it.
+;; name and `Vec(T)` — because nothing else ever reaches it.
fn render(f: Form) -> str
match f
Form.Sym(s) -> s
@@ -360,8 +385,8 @@ fn- render-items(xs: [Form]) -> str
;; ── The macro ───────────────────────────────────────────────────────
;;
-;; `(json/defjson Config "config.json")`. The path is relative to the file this
-;; is written in, exactly as `(embed "config.json")` is — see `macro-slurp` in
+;; `json/defjson(Config, "config.json")`. The path is relative to the file this
+;; is written in, exactly as `embed("config.json")` is — see `macro-slurp` in
;; the prelude, and check.ml's `embed_path`, which is the rule it copies.
;;
;; It answers a `do`, which the top level splices: the nested structs innermost
@@ -378,7 +403,8 @@ macro defjson(& args)
match macro-slurp(path)
Some(src) -> provide(name, path, src)
None ->
- refuse(joined3("there is no file at ", path, ", read relative to the file this defjson is written in — the same place (embed \"...\") would look"))
+ refuse(joined3("there is no file at ", path,
+ ", read relative to the file this defjson is written in — the same place (embed \"...\") would look"))
_ ->
refuse("defjson's first argument is the name of the struct to declare, written as a name")
_ ->
diff --git a/vendor/raylib/bindings b/vendor/raylib/bindings
index ddee763a..81b14c1b 100644
--- a/vendor/raylib/bindings
+++ b/vendor/raylib/bindings
@@ -17,7 +17,7 @@
# output the generator had already committed to.
#
# What does NOT belong here. Anything neither directive can express is a
-# hand-written `declare-c` in raylib.flan, which wins over the generated file
+# hand-written `declare-c` in raylib.fln, which wins over the generated file
# and is left alone by the importer. That is the escape hatch for a signature
# the importer gets wrong and for a Flan face the header cannot describe —
# load-font-ex-raw and load-image-from-memory-raw are both that, each wrapped
@@ -40,9 +40,9 @@ exclude MemFree
#
# A predicate keeps the kebab rule's name, `is-window-ready` for
# `IsWindowReady`: a Flan name carries no `?`, and the hand-written bindings in
-# raylib.flan follow the C name the same way.
+# raylib.fln follow the C name the same way.
-# Hand-written in raylib.flan, so excluded here: a second declare-c for one C
+# Hand-written in raylib.fln, so excluded here: a second declare-c for one C
# symbol is refused for the whole program. These three are on a game's
# per-frame path (docs/PORTING.md), and a hand-written line is what the signature
# check has to compare against -- generated output agrees with the header by
@@ -69,7 +69,7 @@ exclude IsWindowReady
# update-camera-pro is generated. (draw-cube-v was named here as the third
# such pair and no longer is — see the DrawCubeV line further down, which is
# what happens to a split of this kind when an example starts calling the
-# other half.) Every other family in raylib.flan — the texture draws, the
+# other half.) Every other family in raylib.fln — the texture draws, the
# circle draws — sits together, so the split is worth naming: what is
# hand-written is what the ported examples call, and hand-writing the variants
# as well would widen the half that has to be maintained by hand for nothing
@@ -99,7 +99,7 @@ exclude GetWorldToScreen
# of a closed set of names in fact, so their Flan face is a defenum and
# not the C signature — the same trade SetExitKey makes.
# - DrawCubeV, DrawSphere, DrawSphereWires and DrawRay are inside a frame,
-# in examples/models-box-collisions.flan and examples/core-3d-picking.flan.
+# in examples/models-box-collisions.fln and examples/core-3d-picking.fln.
# draw-cube-v moving here is the one place this batch *narrows* the split
# the paragraph above names: it was generated because nothing called it,
# and something calls it now.
@@ -117,17 +117,17 @@ exclude GetScreenToWorldRay
# is a PixelFormat in fact — twenty-four codes of which exactly one is what a
# texture upload needs — so its Flan face is the defenum and not the C
# signature, the same trade SetTextureFilter makes one block up.
-# examples/textures-image-processing.flan is what wanted it: the C's
+# examples/textures-image-processing.fln is what wanted it: the C's
# `PIXELFORMAT_UNCOMPRESSED_R8G8B8A8` is a name there and would have been a 7
# here.
exclude ImageFormat
# ── The idiomatic layer, which is what these last two blocks are for ──
#
-# Three kinds of C signature get a Flan face in raylib.flan rather than the
+# Three kinds of C signature get a Flan face in raylib.fln rather than the
# generated one, and each kind is a directive here so that the generated file
# does not also define the name. See the "An idiomatic layer" section of
-# raylib.flan for what each wrapper buys at the call site.
+# raylib.fln for what each wrapper buys at the call site.
#
# 1. An `int` parameter the package already has a defenum for. These are
# excluded and hand-written with the enum type, exactly as SetExitKey and
@@ -156,7 +156,7 @@ name GetKeyPressed get-key-pressed-raw
# every raylib entry point that takes an array of vectors as pointer plus
# count, and it is the whole family on purpose — a subset would put the
# hole exactly where the next caller looks, which is the argument
-# raylib.flan makes about ConfigFlags.
+# raylib.fln makes about ConfigFlags.
name DrawLineStrip draw-line-strip-raw
name DrawTriangleFan draw-triangle-fan-raw
name DrawTriangleStrip draw-triangle-strip-raw
@@ -231,7 +231,7 @@ constant Gesture/gesture-double-tap GESTURE_DOUBLETAP
constant PixelFormat/pixel-compressed-astc-4x4-rgba PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA
constant PixelFormat/pixel-compressed-astc-8x8-rgba PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA
-# The 16 ConfigFlags bits. These are the values sand.flan and the ported
+# The 16 ConfigFlags bits. These are the values sand.fln and the ported
# window-flags example pass to set-config-flags, set-window-state and
# clear-window-state, and each is a single bit read off raylib.h by hand —
# exactly the transcription this check exists to second-guess.
diff --git a/vendor/raylib/generated.fln b/vendor/raylib/generated.fln
index 4ac56a94..26f60b24 100644
--- a/vendor/raylib/generated.fln
+++ b/vendor/raylib/generated.fln
@@ -6,7 +6,7 @@
;;;; beside it, which is read *while* these lines are made: `exclude` drops
;;;; a function, `name` gives one a Flan name the kebab rule would not.
;;;; Anything neither directive can express is a hand-written declare-c in
-;;;; the package's own .flan, which wins over this file and is left alone.
+;;;; the package's own source, which wins over this file and is left alone.
;;;;
;;;; Regenerating compares the package against the header first and
;;;; refuses to write when they disagree, so this file and the
diff --git a/vendor/raylib/headers b/vendor/raylib/headers
index ac089ad9..3368999b 100644
--- a/vendor/raylib/headers
+++ b/vendor/raylib/headers
@@ -15,7 +15,7 @@
# library they claim to bind.
#
# 2. every ordinary build. Every C symbol
-# is bound already — by hand in raylib.flan or by generation in
+# is bound already — by hand in raylib.fln or by generation in
# generated.fln — so the importer generates nothing and the header read
# is purely the check. It runs over every declaration in the package and
# not only the hand-written ones, because the generated file is a package
@@ -27,7 +27,7 @@
# the time anybody checked them — which is what a census written into a
# comment beside a growing file always does. The generated half is
# `grep -c '^(declare-c' generated.fln` and the hand-written half is the
-# same over the other .flan files here; neither number goes stale.)
+# same over the other .fln files here; neither number goes stale.)
#
# Why it is no longer optional. It used to be `?${FLAN_RAYLIB_H}`, and the
# argument was that a build needs libraylib linkable and *not* raylib-devel
@@ -56,7 +56,7 @@
#
# To see what regeneration would produce without writing anything:
#
-# flan import-c vendor/raylib/raylib-5.5.h vendor/raylib/raylib.flan
+# flan import-c vendor/raylib/raylib-5.5.h vendor/raylib/raylib.fln
#
# What shapes the generated half — which functions are skipped, and what they
# are called — is `bindings` beside this file. See its comments for why a
diff --git a/vendor/raylib/modes.fln b/vendor/raylib/modes.fln
index 0c6c24e6..f8114e63 100644
--- a/vendor/raylib/modes.fln
+++ b/vendor/raylib/modes.fln
@@ -47,7 +47,7 @@
;;;; one place anybody writes it, which is a worse thing to hand somebody than
;;;; a macro that is honest about its extent.
;;;;
-;;;; So the discipline sand.flan already writes down stays the discipline:
+;;;; So the discipline sand.fln already writes down stays the discipline:
;;;; keep the restart boundary OUTSIDE the pair, so choosing `continue` for a
;;;; frame abandons the update and still reaches the drawing. spec-conditions
;;;; §5 is the rule behind that — a transfer runs the intervening frames'
@@ -55,17 +55,17 @@
;;;;
;;;; ── Why this is a file of its own ───────────────────────────────────
;;;;
-;;;; vector.flan's reasoning, unchanged: the split is on `declare-c`.
-;;;; raylib.flan is the package's statement about C, it is the file the header
+;;;; vector.fln's reasoning, unchanged: the split is on `declare-c`.
+;;;; raylib.fln is the package's statement about C, it is the file the header
;;;; check reads hand-written signatures out of, and a wrong line in it stops
;;;; the build. There is not one `declare-c` below — every macro here expands
-;;;; into names raylib.flan already declares — so there is nothing for the
+;;;; into names raylib.fln already declares — so there is nothing for the
;;;; header check to read and nothing raylib can make wrong. A package is a
-;;;; directory, so this is another .flan beside the others and is qualified
+;;;; directory, so this is another .fln beside the others and is qualified
;;;; `rl/` like the rest of it.
;;;;
-;;;; The names come out qualified: the importer writes `(rl/with-drawing …)`
-;;;; and a bare `(with-drawing …)` is an unknown name there, the rule every
+;;;; The names come out qualified: the importer writes `rl/with-drawing:`
+;;;; and a bare `with-drawing:` is an unknown name there, the rule every
;;;; declaration in this package follows. The expansions name this package's
;;;; own functions unqualified and the expander qualifies them on the way out
;;;; — see test/programs/pkgs/mac/mac.flan, which is that rule's worked
@@ -105,7 +105,7 @@ macro with-drawing(& args)
;; The 2D camera. The argument is a Camera2D value, evaluated once where it
;; always was. Remember that a fresh (Camera2D {}) has zoom 0.0 and is not
-;; usable as an identity — raylib.flan says so beside the struct.
+;; usable as an identity — raylib.fln says so beside the struct.
macro with-mode-2d(& args)
if length(args) < 2 or (length(args) == 2 and is-form-empty-list(args[1]))
quote
diff --git a/vendor/raylib/raylib.fln b/vendor/raylib/raylib.fln
index 509c15ab..7787c645 100644
--- a/vendor/raylib/raylib.fln
+++ b/vendor/raylib/raylib.fln
@@ -71,7 +71,7 @@ struct Texture2D(id: u32, width: i32, height: i32, mipmaps: i32, format: i32)
struct Rectangle(x: f32, y: f32, width: f32, height: f32)
-;; KeyboardKey, the subset sand.flan uses. A keyword at a call site resolves
+;; KeyboardKey, the subset sand.fln uses. A keyword at a call site resolves
;; against these members at compile time and a typo is an error there.
;;
;; Every member carries the `key-` prefix, as every member of every other
@@ -185,7 +185,7 @@ declare-c(set-trace-log-level, [level TraceLogLevel], "SetTraceLogLevel")
;; A bitfield, like the gestures below and for the same reason: raylib wants
;; the OR of several and a keyword can only ever name one member, so the
-;; parameter is a u32 and the members are defconsts rather than a defenum.
+;; parameter is a u32 and the members are consts rather than a enum.
;;
;; The part that is NOT obvious from the signature: set-config-flags has to
;; be called BEFORE init-window. raylib stores the flags and reads them while
@@ -193,7 +193,7 @@ declare-c(set-trace-log-level, [level TraceLogLevel], "SetTraceLogLevel")
;; INFO, and does nothing to the window that already exists — which looks
;; exactly like a binding that did not work. Afterwards is what the generated
;; set-window-state, clear-window-state and is-window-state are for, and they
-;; take these same bits, which is why the four sand.flan sets grew into the
+;; take these same bits, which is why the four sand.fln sets grew into the
;; whole of ConfigFlags: a subset has its hole exactly where the next caller
;; looks. Every value below was read off raylib.h 5.5.
;;
@@ -236,7 +236,7 @@ declare-c(is-key-released, [key Key], bool, "IsKeyReleased")
;; The other two halves of that family, hand-written for exactly the reason
;; above and added late: they were generated, so they took an i32, so
-;; `(rl/is-key-up :key-space)` did not compile while `(rl/is-key-down :key-space)` did.
+;; `rl/is-key-up(:key-space)` did not compile while `rl/is-key-down(:key-space)` did.
;; That is a hole in a family rather than a missing convenience — a caller
;; who has used is-key-down has no reason to expect the sibling to be spelled
;; differently, and what they get instead of a keyword is a number nobody
@@ -263,8 +263,8 @@ declare-c(is-mouse-button-up, [button MouseButton], bool, "IsMouseButtonUp")
;; caller could otherwise have to think about — KEY_NULL for one, the NUL
;; byte for the other. An Option says which of the two it is in the type, so
;; the loop that drains the queue cannot read the sentinel as a key or as a
-;; character: `while (> key 0)` is a comparison a reader has to know the
-;; convention to trust, and `(while-some ...)` — or the `if-let` shape the
+;; character: `while key > 0` is a comparison a reader has to know the
+;; convention to trust, and `while-some(...)` — or the `if-let` shape the
;; examples use — is one a reader can check.
;;
;; The generated declarations are still what call C; only their names moved
@@ -303,7 +303,7 @@ declare-c(get-mouse-wheel-move, [], f32, "GetMouseWheelMove")
;; EnableCursor — are in the generated half rather than here: they take no
;; arguments at all, so there is no Flan face for a hand-written line to
;; improve, which is the same rule that leaves GetMouseX there.
-;; examples/core-3d-picking.flan toggles them from the right mouse button.
+;; examples/core-3d-picking.fln toggles them from the right mouse button.
declare-c(show-cursor, [], "ShowCursor")
declare-c(hide-cursor, [], "HideCursor")
@@ -313,7 +313,7 @@ declare-c(is-cursor-hidden, [], bool, "IsCursorHidden")
;; The shape the pointer takes. raylib's SetMouseCursor says `int` and means
;; one of these eleven, so the Flan face is the enum for the same reason
;; set-exit-key takes a Key: the call is made every frame from a hover test,
-;; and `(rl/set-mouse-cursor :cursor-ibeam)` is checked against the members
+;; and `rl/set-mouse-cursor(:cursor-ibeam)` is checked against the members
;; where an i32 would take any number at all — including the one off-by-one
;; that picks the arrow instead of the I-beam and looks like nothing at all
;; went wrong.
@@ -482,7 +482,7 @@ declare-c(get-world-to-screen-2d, [position Vector2 camera Camera2D], Vector2,
;; not a number.
;;
;; `projection` is `int` in the header and `CameraProjection` here, which is
-;; the same four bytes with a face on it: a Flan defenum lowers to int32_t in
+;; the same four bytes with a face on it: a Flan enum lowers to int32_t in
;; a struct field exactly as it does in a parameter, and the layout check
;; knows that, so it accepts an enum where the header says `int` and still
;; refuses an `f64` where the header says `float`. What it buys is at the
@@ -773,7 +773,7 @@ struct Image(data: Ptr(u8), width: i32, height: i32, mipmaps: i32, format: i32)
;; everywhere one is passed, and there is nothing in an `int` to say that 7 is
;; the one a texture upload requires — which is exactly the trade
;; TextureFilter and MouseCursor already made, and the reason this is a
-;; defenum rather than a row of defconsts.
+;; enum rather than a row of consts.
;;
;; The set is closed and is here whole, compressed members included, because a
;; subset would put the hole where the next caller looks: `format` is a field
@@ -889,7 +889,7 @@ declare-c(image-crop, [image Ptr(Image) crop Rectangle], "ImageCrop")
;; duplicates it, which is what this was originally reached for — though
;; image-copy in the generated half says that in one argument and is the
;; better call for it. (An earlier comment here said 5.5 had no ImageCopy. It
-;; does — raylib-5.5.h line 1348 — and generated.flan has bound it all along.)
+;; does — raylib-5.5.h line 1348 — and generated.fln has bound it all along.)
;;
;; The result owns its own buffer: unload-image it, like anything else that
;; allocated.
@@ -917,7 +917,7 @@ declare-c(load-texture-from-image, [image Image], Texture2D,
;;
;; Immediate-mode drawing: each of these needs a GL context, so a window has
;; to be open and none of them can be in the acceptance table. They are
-;; exercised by running sand.flan and looking at it, which is the honest
+;; exercised by running sand.fln and looking at it, which is the honest
;; description — "it links" is not "it draws the right thing".
;;
;; raylib's own naming is kept: a plain name fills, `-lines` outlines, and a
@@ -954,7 +954,7 @@ declare-c(draw-circle-lines-v, [center Vector2 radius f32 color Color],
;; Two radii, horizontal then vertical. Equal radii is a circle, so a binding
;; that exchanged them would be invisible unless they differ — which is why
-;; sand.flan's ellipse is deliberately wider than it is tall.
+;; sand.fln's ellipse is deliberately wider than it is tall.
declare-c(draw-ellipse, [x i32 y i32 radius-h f32 radius-v f32 color Color],
"DrawEllipse")
@@ -1014,14 +1014,14 @@ declare-c(draw-rectangle-rounded-lines-ex,
;;
;; Eleven entry points take an array of vectors as a pointer plus an `int`
;; count. A Flan slice already carries both, so every call site that does not
-;; go through a wrapper has to take the slice apart itself — `(addr (at pts
-;; 0))` and `(length pts)`, twice, in the right order — and the compiler cannot
+;; go through a wrapper has to take the slice apart itself — `addr(pts[0])`
+;; and `length(pts)`, twice, in the right order — and the compiler cannot
;; check that the two halves came from the same slice. The wrapper is where
;; that idiom lives, which is the rule check-collision-point-poly set.
;;
;; It also guards the empty case, which is the part a hand-written call site
;; gets wrong rather than merely writes out. raylib takes a count of 0 and
-;; draws nothing, but `(at pts 0)` on an empty slice is out of bounds before
+;; draws nothing, but `pts[0]` on an empty slice is out of bounds before
;; raylib is ever reached: the safe call is "do not call at all", and it is
;; written once here instead of at every use.
;;
@@ -1146,7 +1146,7 @@ declare-c(get-screen-height, [], i32, "GetScreenHeight")
;; *at all* without a pad plugged in: with no gamepad, is-gamepad-available is
;; false, every button predicate is false and every axis reads 0.0, which is
;; also exactly what a wrapper with its two int arguments exchanged would
-;; report. So these are bound, wired into sand.flan's HUD, and honestly
+;; report. So these are bound, wired into sand.fln's HUD, and honestly
;; described as untested — the only check they get is that a pad moves the
;; read-out.
;;
@@ -1234,7 +1234,7 @@ declare-c(get-gamepad-axis-movement, [pad i32 axis GamepadAxis], f32,
;; silently accepted integers would give up what makes a keyword argument
;; checkable. The consequence is simply that an enum parameter cannot be
;; indexed, and the caller spells the loop as a cond over the members it
-;; knows — which is what examples/core-input-gamepad.flan does.
+;; knows — which is what examples/core-input-gamepad.fln does.
;; SetGamepadVibration is NOT bound, and the reason is not the usual one. Two
;; things are wrong with it at once. Its arity changed — 5.1-dev takes three
@@ -1249,7 +1249,7 @@ declare-c(get-gamepad-axis-movement, [pad i32 axis GamepadAxis], f32,
;;
;; Touch is a superset of the mouse on a desktop: with no touchscreen,
;; get-touch-point-count is 0 but get-touch-position 0 still tracks the mouse,
-;; which is what makes it visible in sand.flan at all.
+;; which is what makes it visible in sand.fln at all.
;;
;; The gesture system is fed by raylib's own event polling, so a gesture is
;; only ever detected inside a window's frame loop — nothing here is headless
@@ -1259,7 +1259,7 @@ declare-c(get-gamepad-axis-movement, [pad i32 axis GamepadAxis], f32,
;; several and is-gesture-detected tests against one. That is why the enabling
;; call below takes a u32 and not a Gesture — a keyword can only ever name one
;; member, and `gesture-all` is spelled out below so the common case still
-;; reads. The defconst and the members now share the `gesture-` stem, which
+;; reads. The const and the members now share the `gesture-` stem, which
;; is the prefix reading its way out of the enum and into the constant beside
;; it.
enum Gesture
@@ -1319,7 +1319,7 @@ declare-c(get-gesture-hold-duration, [], f32, "GetGestureHoldDuration")
;; The one thing the layout gets for free: RenderTexture2D is a u32 and two
;; Texture2Ds, and Texture2D is already pinned as far as anything headless can
;; pin it, so the only new claim here is the order of the three members.
-;; sand.flan draws through one, which is where a wrong order shows up.
+;; sand.fln draws through one, which is where a wrong order shows up.
struct RenderTexture2D(id: u32, texture: Texture2D, depth: Texture2D)
@@ -1337,7 +1337,7 @@ declare-c(unload-render-texture, [target RenderTexture2D],
;; Everything drawn between these two lands in the target instead of the
;; screen, and the target's texture comes out of the GPU upside down — raylib
;; renders it bottom-up — so drawing it back with a NEGATIVE source height is
-;; not a flourish, it is the correction. sand.flan does exactly that.
+;; not a flourish, it is the correction. sand.fln does exactly that.
declare-c(begin-texture-mode, [target RenderTexture2D], "BeginTextureMode")
declare-c(end-texture-mode, [], "EndTextureMode")
@@ -1353,7 +1353,7 @@ declare-c(end-texture-mode, [], "EndTextureMode")
;; That makes Wave the audio equivalent of the Image family — raylib
;; *computes* with it, headlessly — and it is the only part of this section
;; the acceptance table asserts. Everything from Sound down is exercised by
-;; running sand.flan with a working sound server, and a machine without one
+;; running sand.fln with a working sound server, and a machine without one
;; gets silence rather than a crash: init-audio-device logs a warning, every
;; load answers a zeroed struct and every play is a no-op.
@@ -1594,7 +1594,7 @@ declare-c(load-font, [path str], Font, "LoadFont")
;; raylib's own convention is that a NULL pointer with a count of 0 means the
;; default ASCII set, and the wrapper keeps it — but Flan has no null pointer
;; literal, so the null comes from the one place the language does hand out
-;; zeroed bytes: a `defonce` with no initialiser is BSS (plan.org, zero
+;; zeroed bytes: a `once` with no initialiser is BSS (plan.org, zero
;; values), and a zeroed (Ptr i32) is exactly a null one. It is never written
;; to and never read through; raylib only ever compares it against NULL.
once default-codepoints: Ptr(i32)
@@ -1685,7 +1685,7 @@ declare-c(draw-text-codepoint,
;; which is also its answer for genuinely malformed UTF-8. Nothing in the
;; result tells the two apart. docs/PORTING.md §A.1 is the whole story.
;;
-;; So the declaration says `(Ptr u8)` and means it. That is a hand-written line
+;; So the declaration says `Ptr(u8)` and means it. That is a hand-written line
;; over a `const char *` the importer would have rendered as `string`, which is
;; exactly the case lib/cimport.ml's [ptr_agrees] exists for, and the generated
;; half no longer carries the string-faced version at all — a binding that is
@@ -1713,7 +1713,7 @@ fn get-codepoint-previous(text: [const u8], offset: i32, codepoint-size: Ptr(i32
;;
;; Layouts only, read off raylib.h 5.5 and checked against it on every build.
;; Describing them is what lets the importer bind the Load/Gen/Draw/Unload
-;; families over them in generated.flan; none of those calls is written here.
+;; families over them in generated.fln; none of those calls is written here.
;;
;; The field names are the header's through the kebab rule, which is how the
;; layout check pairs them, so Matrix's are m-0 to m-15 in raylib's order — a
diff --git a/vendor/raylib/vector.fln b/vendor/raylib/vector.fln
index 43280286..baf61cb6 100644
--- a/vendor/raylib/vector.fln
+++ b/vendor/raylib/vector.fln
@@ -10,7 +10,7 @@
;;;; the arithmetic in Flan, or a small C file re-exporting them as symbols.
;;;;
;;;; It is written in Flan, and the measurement that decided it was already
-;;;; taken: examples/shapes-following-eyes.flan is an example whose every
+;;;; taken: examples/shapes-following-eyes.fln is an example whose every
;;;; line is vector maths, ported without a vector library, and its own
;;;; header reports that this cost nothing — the C does not use raymath there
;;;; either. A C shim would buy identical arithmetic at the price of a
@@ -25,7 +25,7 @@
;;;;
;;;; ── Why this is a file of its own ───────────────────────────────────
;;;;
-;;;; The split is on `declare-c`, not on "idiomatic". raylib.flan is the
+;;;; The split is on `declare-c`, not on "idiomatic". raylib.fln is the
;;;; package's statement about C: every line in it is a declaration or a thin
;;;; wrapper over one, it is the file the header check reads hand-written
;;;; signatures out of, and a wrong line in it stops the build. There is not
@@ -34,15 +34,15 @@
;;;; nothing here can be made wrong by raylib changing. A reader who wants to
;;;; know what the package claims about C should not have to walk past four
;;;; hundred lines of float arithmetic to find out, and 1300 lines of
-;;;; raylib.flan is already the argument against adding to it.
+;;;; raylib.fln is already the argument against adding to it.
;;;;
-;;;; A package is a directory, so this is simply another .flan beside the
+;;;; A package is a directory, so this is simply another .fln beside the
;;;; others and is qualified `rl/` like the rest of it.
;;;;
;;;; ── Names ───────────────────────────────────────────────────────────
;;;;
;;;; `v2-` and `v3-`, not `vector2-`. These appear nested inside each other —
-;;;; `(rl/v2-add p (rl/v2-scale d t))` is the ordinary shape — and the longer
+;;;; `rl/v2-add(p, rl/v2-scale(d, t))` is the ordinary shape — and the longer
;;;; spelling puts more characters between the reader and the arithmetic than
;;;; it puts meaning. The prefix still says the type, which is the part a
;;;; language without generics needs it to say.
@@ -52,7 +52,7 @@
;;;; `clamp` and `lerp`. Both are already in the prelude — clamp as a macro
;;;; (prelude.ml, "clamp is a macro and not a function"), lerp as a function
;;;; — and both are unqualified names every program already has;
-;;;; examples/textures-fog-of-war.flan calls the prelude's clamp today. A
+;;;; examples/textures-fog-of-war.fln calls the prelude's clamp today. A
;;;; second `rl/lerp` would not even be the same function: the prelude writes
;;;; the weighted sum `(1-t)a + tb`, which returns b exactly at t = 1.0,
;;;; where raymath writes `a + t*(b - a)`, which does not once rounding is
@@ -77,8 +77,8 @@ fn inverse-lerp(value: f32, start: f32, end: f32) -> f32
;; for extrapolation — a caller who wants it bounded writes the prelude's
;; clamp around it and can see that they did.
;;
-;; Written as one expression rather than as (lerp out-start out-end
-;; (inverse-lerp ...)) because the prelude's lerp is the weighted-sum form
+;; Written as one expression rather than as lerp(out-start, out-end,
+;; inverse-lerp(...)) because the prelude's lerp is the weighted-sum form
;; and raymath's Remap is the a + t*(b - a) form; composing them would be a
;; different function in the last bit.
fn remap(value: f32, in-start: f32, in-end: f32, out-start: f32, out-end: f32) -> f32
diff --git a/web/examples/quotes.sh b/web/examples/quotes.sh
index 631bf749..4bd5902d 100644
--- a/web/examples/quotes.sh
+++ b/web/examples/quotes.sh
@@ -107,8 +107,8 @@ want "xfer channel" "$(printf '%s\n' "$ir" | grep 'define {} @"flan.main"')"
want "shim wrapper" "$("$FLAN" shim "$here/shimdemo.flan" | grep 'GetMousePosition();')"
# Lines quoted verbatim from repository files.
-want "raylib binding" "$(grep -F 'unload-texture' "$root/vendor/raylib/raylib.flan")"
-want "agent declare" "$(grep -F 'flan_agent_poll' "$root/vendor/agent/agent.flan" | head -1)"
+want "raylib binding" "$(grep -F 'unload-texture' "$root/vendor/raylib/raylib.fln")"
+want "agent declare" "$(grep -F 'flan_agent_poll' "$root/vendor/agent/agent.fln" | head -1)"
want "conditions.org" "$(grep -F 'Innermost frame offering the name wins' "$root/conditions.org")"
# The value renderer, anchored in the test corpus rather than in NEXT.md (the
# rolling scratch document TODO.org replaced). It used to grep NEXT.md for this
diff --git a/web/index.html b/web/index.html
index ab340edd..a7198fab 100644
--- a/web/index.html
+++ b/web/index.html
@@ -1858,10 +1858,10 @@ directory may carry a headers file naming the library's own C heade
flan generate-c <package-dir> reads it with
clang -Xclang -ast-dump=json, turns every function it can represent into
the same declare-c line a person would have written, and writes them to
-generated.flan in the package — which is committed.
+generated.fln in the package — which is committed.
$ flan generate-c vendor/raylib
-wrote vendor/raylib/generated.flan: 268 declarations, 117 refused, of 581 functions
+wrote vendor/raylib/generated.fln: 318 declarations, 61 refused, of 581 functions
in vendor/raylib/raylib-5.5.h.
Every defstruct, every hand-written declare-c and every mapped
constant agrees with it.