Merge branch 'worktree-agent-a604237a7cbd45379' into dev-loop
# Conflicts: # FIX.org # lib/check.ml
This commit is contained in:
commit
df89869962
48
FIX.org
48
FIX.org
@ -3977,3 +3977,51 @@ A *compound constant expression* at a bounded ~$t~ — ~(+ x (+ 1 2))~ where
|
||||
at a type variable, and nothing folds the compound to a bare one before the
|
||||
ask. Walk-backable (admitting more programs later invalidates nothing
|
||||
written now), so it waits until a body actually wants it.
|
||||
* Enum keyword prefixes, 2026-09-20
|
||||
|
||||
** The decision, author's words
|
||||
raylib's enum keywords carry a disambiguating prefix, because bare members
|
||||
collide across enums and with user code. Key members are ~:key-r~,
|
||||
~:key-space~, ~:key-left-shift~; MouseButton members are ~:mouse-left~,
|
||||
~:mouse-right~ and so on. ~mouse-~ over ~button-~ because gamepads have
|
||||
buttons too. Only Key and MouseButton are decided; the rest of the survey is
|
||||
below, awaiting a ruling per enum.
|
||||
|
||||
** The bindings directive extension
|
||||
The `enum` line in vendor/raylib/bindings grew an optional third column: the
|
||||
prefix the members carry on the Flan side, stripped before the C prefix is
|
||||
applied. `enum Key KEY_ key-` checks ~key-r~ against KEY_R rather than
|
||||
KEY_KEY_R; `enum MouseButton MOUSE_BUTTON_ mouse-` reaches MOUSE_BUTTON_LEFT
|
||||
from ~mouse-left~. A member that does not carry the declared prefix is
|
||||
reported, not checked under a guessed name — ~null~ beside a declared ~key-~
|
||||
would otherwise build KEY_NULL, which the header happens to have, and the
|
||||
naming rule would erode silently. A name the rule builds that the header
|
||||
lacks is still reported, never skipped. `flan generate-c vendor/raylib` runs
|
||||
green against raylib-5.5.h with both lines in place.
|
||||
|
||||
The checker also grew a did-you-mean for enum members: one edit away, and the
|
||||
bare name of a prefixed member — ~:r~ suggests ~:key-r~, ~:left~ suggests
|
||||
~:mouse-left~ at a MouseButton site.
|
||||
|
||||
** Open, author's call — the survey of the other nine enums
|
||||
None are renamed; these are the collision-prone bare members found:
|
||||
- TraceLogLevel: nearly all generic — ~all~, ~trace~, ~debug~, ~info~,
|
||||
~warning~, ~error~, ~fatal~, ~none~. ~none~ also collides with Gesture's.
|
||||
- Gesture: ~none~ (collides with TraceLogLevel's), ~tap~, ~hold~, ~drag~.
|
||||
- CameraMode: ~custom~, ~free~ (also the name of the language's free).
|
||||
- MouseCursor: ~default~, ~arrow~, ~crosshair~.
|
||||
- TextureFilter: ~point~.
|
||||
- GamepadButton: ~unknown~, ~middle~ (plus ~middle-left~/~middle-right~).
|
||||
- GamepadAxis: ~left-x~/~left-y~/~right-x~/~right-y~ read gamepad-ish
|
||||
already, but ~left-trigger~/~right-trigger~ sit one hyphen from
|
||||
GamepadButton's ~left-trigger-1~/~2~ — a prefix ruling should take the two
|
||||
enums together.
|
||||
- CameraProjection (~perspective~, ~orthographic~) and PixelFormat
|
||||
(~uncompressed-*~, ~compressed-*~) are effectively self-naming; low risk.
|
||||
|
||||
** Open, author's call — sand.flan
|
||||
sand.flan calls ~(rl/key-pressed? :r)~ and ~(rl/mouse-button-down? :left)~
|
||||
(lines 161–166), and the default suite compiles it (test_session, and
|
||||
test/programs/sand-headless.flan imports it). The file is the author's live
|
||||
WIP and was not touched, so those two tests are red on this branch until the
|
||||
three keywords there become ~:key-r~ / ~:mouse-left~.
|
||||
|
||||
6
NEXT.md
6
NEXT.md
@ -956,8 +956,8 @@ header of `vendor/raylib/raylib.flan`:
|
||||
queue in two places, once to prime the loop and once at the bottom of the body, and the Option shape reads it in
|
||||
one.
|
||||
- **An enum where the header says `int`.** `key-up?`, `key-pressed-repeat?`, `mouse-button-up?` — holes in families
|
||||
whose other halves already took a `Key` or a `MouseButton`, so `(rl/key-down? :space)` compiled and
|
||||
`(rl/key-up? :space)` did not. **These are not wrappers.** A C enum parameter has an int's ABI, so the hand-written
|
||||
whose other halves already took a `Key` or a `MouseButton`, so `(rl/key-down? :key-space)` compiled and
|
||||
`(rl/key-up? :key-space)` did not. **These are not wrappers.** A C enum parameter has an int's ABI, so the hand-written
|
||||
`declare-c` with the Flan type on it is the whole fix and a `defn` around it would be a rename.
|
||||
|
||||
The mechanism for the first two is the `name` directive in `vendor/raylib/bindings`: the generated declaration keeps
|
||||
@ -1241,7 +1241,7 @@ second.
|
||||
|
||||
One smaller thing found and worth not re-deriving: an enum parameter imports as `i32`, because the header says
|
||||
`KeyboardKey` and nothing tells the importer the package calls that `Key`. The ABI is identical, the face is worse,
|
||||
and it is why `(rl/key-down? :space)` keeps its hand-written line. The idiomatic-layer lane closed the three holes
|
||||
and it is why `(rl/key-down? :key-space)` keeps its hand-written line. The idiomatic-layer lane closed the three holes
|
||||
this left — `key-up?`, `key-pressed-repeat?` and `mouse-button-up?` were generated and therefore took an `i32`, so the
|
||||
sibling of a call that worked did not — by excluding them and hand-writing the enum type, which is all it takes.
|
||||
|
||||
|
||||
@ -222,7 +222,7 @@ hand-written lines are untouched.
|
||||
Worth noting what migration would actually lose, since it is small but real: the hand-written names are
|
||||
better than the rule's. `IsKeyPressed` is `key-pressed?` by hand and `is-key-pressed` by rule;
|
||||
`CheckCollisionRecs` is `collision-recs?`. And an enum parameter imports as `i32`, because the header says
|
||||
`KeyboardKey` and nothing tells the importer the package calls that `Key` — so `(rl/key-down? :space)`
|
||||
`KeyboardKey` and nothing tells the importer the package calls that `Key` — so `(rl/key-down? :key-space)`
|
||||
would become an integer at the call site. A migration is therefore not a deletion; it is a deletion plus a
|
||||
kept list of the lines whose face is deliberately nicer than the header's.
|
||||
|
||||
@ -238,7 +238,7 @@ What actually decides it is that migration would gut the check. Everything the g
|
||||
by construction, so diffing generated output against its own source proves nothing; the hand-written lines have a
|
||||
different author, so they are the only declarations a header can contradict — and all ten of the 5.1-dev differences
|
||||
came from them. Delete them and the signature half of the check silently becomes a tautology. The enum point above
|
||||
survives intact as a second reason: `(rl/key-down? :space)` keeps its `Key` parameter only because that line is
|
||||
survives intact as a second reason: `(rl/key-down? :key-space)` keeps its `Key` parameter only because that line is
|
||||
hand-written.
|
||||
|
||||
## 7. Watching variables
|
||||
|
||||
@ -230,7 +230,7 @@
|
||||
("(rl/Vector2 {.x 1.0 .y 2.0})" ".y" "and the second one")
|
||||
("(set total (.bytes c))" ".bytes" "a field accessor")
|
||||
;; The keyword rule is still there: an enum member is one.
|
||||
("(rl/mouse-button-down? :left)" ":left" "an enum member")))
|
||||
("(rl/mouse-button-down? :mouse-left)" ":mouse-left" "an enum member")))
|
||||
(test-flan--check (format "%s is a constant" (nth 2 case))
|
||||
(eq (test-flan-mode--face-at (nth 0 case) (nth 1 case))
|
||||
'font-lock-constant-face)))
|
||||
|
||||
@ -77,24 +77,24 @@
|
||||
;; Update
|
||||
;; The C's `if (RIGHT) ... else if (LEFT) ...`: both held cancels to the
|
||||
;; right, which is the else-if and not an accident.
|
||||
(if (rl/key-down? :right)
|
||||
(if (rl/key-down? :key-right)
|
||||
(set (.x player) (+ (.x player) 2.0))
|
||||
(when (rl/key-down? :left) (set (.x player) (- (.x player) 2.0))))
|
||||
(when (rl/key-down? :key-left) (set (.x player) (- (.x player) 2.0))))
|
||||
|
||||
;; The camera follows the player's centre.
|
||||
(set (.target camera) (rl/Vector2 {.x (+ (.x player) 20.0)
|
||||
.y (+ (.y player) 20.0)}))
|
||||
|
||||
(if (rl/key-down? :a)
|
||||
(if (rl/key-down? :key-a)
|
||||
(set (.rotation camera) (- (.rotation camera) 1.0))
|
||||
(when (rl/key-down? :s)
|
||||
(when (rl/key-down? :key-s)
|
||||
(set (.rotation camera) (+ (.rotation camera) 1.0))))
|
||||
(set (.rotation camera) (clamp (.rotation camera) -40.0 40.0))
|
||||
|
||||
(set (.zoom camera) (+ (.zoom camera) (* (rl/get-mouse-wheel-move) 0.05)))
|
||||
(set (.zoom camera) (clamp (.zoom camera) 0.1 3.0))
|
||||
|
||||
(when (rl/key-pressed? :r)
|
||||
(when (rl/key-pressed? :key-r)
|
||||
(set (.zoom camera) 1.0)
|
||||
(set (.rotation camera) 0.0))
|
||||
|
||||
|
||||
@ -97,10 +97,10 @@
|
||||
;; could not be used to aim at anything.
|
||||
(when (rl/cursor-hidden?) (rl/update-camera (addr camera) :first-person))
|
||||
|
||||
(when (rl/mouse-button-pressed? :right)
|
||||
(when (rl/mouse-button-pressed? :mouse-right)
|
||||
(if (rl/cursor-hidden?) (rl/enable-cursor) (rl/disable-cursor)))
|
||||
|
||||
(when (rl/mouse-button-pressed? :left)
|
||||
(when (rl/mouse-button-pressed? :mouse-left)
|
||||
(if (not (.hit collision))
|
||||
;; The pixel under the pointer, as a line through the scene, tested
|
||||
;; against the cube's bounds.
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
(when (> (.x delta-circle) (f32 screen-width)) (set (.x delta-circle) 0.0))
|
||||
(when (> (.x frame-circle) (f32 screen-width)) (set (.x frame-circle) 0.0))
|
||||
|
||||
(when (rl/key-pressed? :r)
|
||||
(when (rl/key-pressed? :key-r)
|
||||
(set (.x delta-circle) 0.0)
|
||||
(set (.x frame-circle) 0.0))
|
||||
|
||||
|
||||
@ -173,9 +173,9 @@
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
(when (and (rl/key-pressed? :left) (> gamepad 0))
|
||||
(when (and (rl/key-pressed? :key-left) (> gamepad 0))
|
||||
(set gamepad (- gamepad 1)))
|
||||
(when (rl/key-pressed? :right) (set gamepad (+ gamepad 1)))
|
||||
(when (rl/key-pressed? :key-right) (set gamepad (+ gamepad 1)))
|
||||
|
||||
(let [axis-count (min 6 (rl/get-gamepad-axis-count gamepad))
|
||||
vibrate-rect (rl/Rectangle {.x 10.0
|
||||
|
||||
@ -299,7 +299,7 @@
|
||||
(set last-gesture g))
|
||||
|
||||
;; The two mode buttons toggle one bit each of log-mode.
|
||||
(when (rl/mouse-button-released? :left)
|
||||
(when (rl/mouse-button-released? :mouse-left)
|
||||
(let [m (rl/get-mouse-position)]
|
||||
(when (rl/collision-point-rec? m b1)
|
||||
(set log-mode (cond (= log-mode 3) 2
|
||||
|
||||
@ -34,10 +34,10 @@
|
||||
(until (rl/window-should-close?)
|
||||
;; Update. key-down? and not key-pressed?: this is meant to repeat for as
|
||||
;; long as the key is held, which is the whole difference between the two.
|
||||
(when (rl/key-down? :right) (set (.x ball) (+ (.x ball) 2.0)))
|
||||
(when (rl/key-down? :left) (set (.x ball) (- (.x ball) 2.0)))
|
||||
(when (rl/key-down? :up) (set (.y ball) (- (.y ball) 2.0)))
|
||||
(when (rl/key-down? :down) (set (.y ball) (+ (.y ball) 2.0)))
|
||||
(when (rl/key-down? :key-right) (set (.x ball) (+ (.x ball) 2.0)))
|
||||
(when (rl/key-down? :key-left) (set (.x ball) (- (.x ball) 2.0)))
|
||||
(when (rl/key-down? :key-up) (set (.y ball) (- (.y ball) 2.0)))
|
||||
(when (rl/key-down? :key-down) (set (.y ball) (+ (.y ball) 2.0)))
|
||||
|
||||
;; Draw
|
||||
(rl/with-drawing
|
||||
|
||||
@ -33,19 +33,19 @@
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
(when (rl/key-pressed? :h)
|
||||
(when (rl/key-pressed? :key-h)
|
||||
(if (rl/cursor-hidden?) (rl/show-cursor) (rl/hide-cursor)))
|
||||
|
||||
(let [ball (rl/get-mouse-position)]
|
||||
(set ball-color
|
||||
(cond
|
||||
(rl/mouse-button-pressed? :left) rl/maroon
|
||||
(rl/mouse-button-pressed? :middle) rl/lime
|
||||
(rl/mouse-button-pressed? :right) rl/darkblue
|
||||
(rl/mouse-button-pressed? :side) rl/purple
|
||||
(rl/mouse-button-pressed? :extra) rl/yellow
|
||||
(rl/mouse-button-pressed? :forward) rl/orange
|
||||
(rl/mouse-button-pressed? :back) rl/beige
|
||||
(rl/mouse-button-pressed? :mouse-left) rl/maroon
|
||||
(rl/mouse-button-pressed? :mouse-middle) rl/lime
|
||||
(rl/mouse-button-pressed? :mouse-right) rl/darkblue
|
||||
(rl/mouse-button-pressed? :mouse-side) rl/purple
|
||||
(rl/mouse-button-pressed? :mouse-extra) rl/yellow
|
||||
(rl/mouse-button-pressed? :mouse-forward) rl/orange
|
||||
(rl/mouse-button-pressed? :mouse-back) rl/beige
|
||||
:else ball-color))
|
||||
|
||||
;; Draw
|
||||
|
||||
@ -165,7 +165,7 @@
|
||||
input (if touching
|
||||
(rl/get-touch-position 0)
|
||||
(rl/get-mouse-position))
|
||||
pressed (if (or touching (rl/mouse-button-down? :left))
|
||||
pressed (if (or touching (rl/mouse-button-down? :mouse-left))
|
||||
(nearest-button input)
|
||||
button-none)]
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
(when (rl/key-pressed? :s) (set scissor-mode (not scissor-mode)))
|
||||
(when (rl/key-pressed? :key-s) (set scissor-mode (not scissor-mode)))
|
||||
|
||||
;; Centre the scissor area on the mouse.
|
||||
(set (.x scissor) (- (f32 (rl/get-mouse-x)) (/ (.width scissor) 2.0)))
|
||||
|
||||
@ -79,18 +79,18 @@
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
(when (rl/key-pressed? :f) (rl/toggle-fullscreen))
|
||||
(when (rl/key-pressed? :r) (toggle-flag rl/flag-window-resizable))
|
||||
(when (rl/key-pressed? :d) (toggle-flag rl/flag-window-undecorated))
|
||||
(when (rl/key-pressed? :u) (toggle-flag rl/flag-window-unfocused))
|
||||
(when (rl/key-pressed? :t) (toggle-flag rl/flag-window-topmost))
|
||||
(when (rl/key-pressed? :a) (toggle-flag rl/flag-window-always-run))
|
||||
(when (rl/key-pressed? :v) (toggle-flag rl/flag-vsync-hint))
|
||||
(when (rl/key-pressed? :key-f) (rl/toggle-fullscreen))
|
||||
(when (rl/key-pressed? :key-r) (toggle-flag rl/flag-window-resizable))
|
||||
(when (rl/key-pressed? :key-d) (toggle-flag rl/flag-window-undecorated))
|
||||
(when (rl/key-pressed? :key-u) (toggle-flag rl/flag-window-unfocused))
|
||||
(when (rl/key-pressed? :key-t) (toggle-flag rl/flag-window-topmost))
|
||||
(when (rl/key-pressed? :key-a) (toggle-flag rl/flag-window-always-run))
|
||||
(when (rl/key-pressed? :key-v) (toggle-flag rl/flag-vsync-hint))
|
||||
|
||||
;; Hidden and minimized are not toggles: the window they hide is also the
|
||||
;; window the key would have to be pressed in, so each comes back on a
|
||||
;; timer instead.
|
||||
(when (rl/key-pressed? :h)
|
||||
(when (rl/key-pressed? :key-h)
|
||||
(unless (rl/window-state? rl/flag-window-hidden)
|
||||
(rl/set-window-state rl/flag-window-hidden))
|
||||
(set frames 0))
|
||||
@ -100,7 +100,7 @@
|
||||
(when (>= frames restore-after)
|
||||
(rl/clear-window-state rl/flag-window-hidden)))
|
||||
|
||||
(when (rl/key-pressed? :n)
|
||||
(when (rl/key-pressed? :key-n)
|
||||
(unless (rl/window-state? rl/flag-window-minimized)
|
||||
(rl/minimize-window))
|
||||
(set frames 0))
|
||||
@ -110,7 +110,7 @@
|
||||
(when (>= frames restore-after) (rl/restore-window)))
|
||||
|
||||
;; Maximize needs FLAG_WINDOW_RESIZABLE first, which is what R is for.
|
||||
(when (rl/key-pressed? :m)
|
||||
(when (rl/key-pressed? :key-m)
|
||||
(if (rl/window-state? rl/flag-window-maximized)
|
||||
(rl/restore-window)
|
||||
(rl/maximize-window)))
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
;;;; 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 :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
|
||||
@ -34,7 +34,7 @@
|
||||
(defer (rl/close-window))
|
||||
|
||||
;; No key closes the window any more. ESC is an ordinary key from here on.
|
||||
(rl/set-exit-key :null)
|
||||
(rl/set-exit-key :key-null)
|
||||
|
||||
(rl/set-target-fps 60)
|
||||
|
||||
@ -42,16 +42,16 @@
|
||||
;; Update. Either way of asking to leave raises the question; only Y and N
|
||||
;; answer it. window-should-close? is false again on the next frame, so
|
||||
;; the request has to be remembered in a variable.
|
||||
(when (or (rl/window-should-close?) (rl/key-pressed? :escape))
|
||||
(when (or (rl/window-should-close?) (rl/key-pressed? :key-escape))
|
||||
(set exit-requested true))
|
||||
|
||||
;; The C's `if (Y) ... else if (N) ...`, which is an `if` with a `when`
|
||||
;; in its else and not a `cond`: a `cond` needs an `:else` arm and there
|
||||
;; is nothing to do when neither key was pressed.
|
||||
(when exit-requested
|
||||
(if (rl/key-pressed? :y)
|
||||
(if (rl/key-pressed? :key-y)
|
||||
(set exiting true)
|
||||
(when (rl/key-pressed? :n) (set exit-requested false))))
|
||||
(when (rl/key-pressed? :key-n) (set exit-requested false))))
|
||||
|
||||
;; Draw
|
||||
(rl/with-drawing
|
||||
|
||||
@ -93,10 +93,10 @@
|
||||
;; means only one direction applies per frame — diagonal movement is not
|
||||
;; possible, deliberately.
|
||||
(cond
|
||||
(rl/key-down? :right) (set (.x player-position) (+ (.x player-position) 0.2))
|
||||
(rl/key-down? :left) (set (.x player-position) (- (.x player-position) 0.2))
|
||||
(rl/key-down? :down) (set (.z player-position) (+ (.z player-position) 0.2))
|
||||
(rl/key-down? :up) (set (.z player-position) (- (.z player-position) 0.2)))
|
||||
(rl/key-down? :key-right) (set (.x player-position) (+ (.x player-position) 0.2))
|
||||
(rl/key-down? :key-left) (set (.x player-position) (- (.x player-position) 0.2))
|
||||
(rl/key-down? :key-down) (set (.z player-position) (+ (.z player-position) 0.2))
|
||||
(rl/key-down? :key-up) (set (.z player-position) (- (.z player-position) 0.2)))
|
||||
|
||||
(let [player-box (box-around player-position player-size)
|
||||
hit (or (rl/check-collision-boxes player-box
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
;; rather than reading that back. This follows it.
|
||||
(when collision (set box-collision (rl/get-collision-rec box-a box-b)))
|
||||
|
||||
(when (rl/key-pressed? :space) (set paused (not paused)))
|
||||
(when (rl/key-pressed? :key-space) (set paused (not paused)))
|
||||
|
||||
;; Draw
|
||||
(rl/with-drawing
|
||||
|
||||
@ -219,14 +219,14 @@
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
(when (rl/key-pressed? :space) (set show-font-atlas (not show-font-atlas)))
|
||||
(when (rl/key-pressed? :key-space) (set show-font-atlas (not show-font-atlas)))
|
||||
|
||||
;; The C's "testing code": walk the text and throw the answer away. Kept
|
||||
;; because it is what exercises the codepoint walk, which is now symmetric
|
||||
;; here the way it is in the C — a raylib call in each direction.
|
||||
(cond
|
||||
(rl/key-pressed? :right) (set cursor (step-forward cursor))
|
||||
(rl/key-pressed? :left) (set cursor (step-back cursor)))
|
||||
(rl/key-pressed? :key-right) (set cursor (step-forward cursor))
|
||||
(rl/key-pressed? :key-left) (set cursor (step-back cursor)))
|
||||
|
||||
;; Draw
|
||||
(rl/with-drawing
|
||||
|
||||
@ -100,7 +100,7 @@
|
||||
(set (at name letter-count) (u8 key))
|
||||
(set letter-count (+ letter-count 1))))))
|
||||
|
||||
(when (rl/key-pressed? :backspace)
|
||||
(when (rl/key-pressed? :key-backspace)
|
||||
(set letter-count (- letter-count 1))
|
||||
(when (< letter-count 0) (set letter-count 0))))
|
||||
(rl/set-mouse-cursor :default))
|
||||
|
||||
@ -184,7 +184,7 @@
|
||||
(rl/set-target-fps 60)
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
(when (rl/key-pressed? :space) (set word-wrap? (not word-wrap?)))
|
||||
(when (rl/key-pressed? :key-space) (set word-wrap? (not word-wrap?)))
|
||||
|
||||
(let [mouse (rl/get-mouse-position)]
|
||||
;; The border fades while the pointer is over the container.
|
||||
@ -195,14 +195,14 @@
|
||||
|
||||
(if resizing?
|
||||
(do
|
||||
(when (rl/mouse-button-released? :left) (set resizing? false))
|
||||
(when (rl/mouse-button-released? :mouse-left) (set resizing? false))
|
||||
(let [w (+ (.width container) (- (.x mouse) (.x last-mouse)))
|
||||
h (+ (.height container) (- (.y mouse) (.y last-mouse)))]
|
||||
(set (.width container)
|
||||
(clamp w min-width max-width))
|
||||
(set (.height container)
|
||||
(clamp h min-height max-height))))
|
||||
(when (and (rl/mouse-button-down? :left)
|
||||
(when (and (rl/mouse-button-down? :mouse-left)
|
||||
(rl/collision-point-rec? mouse resizer))
|
||||
(set resizing? true)))
|
||||
|
||||
|
||||
@ -54,11 +54,11 @@
|
||||
(until (rl/window-should-close?)
|
||||
;; Update. Holding space runs the counter eight times faster; enter starts
|
||||
;; it over.
|
||||
(if (rl/key-down? :space)
|
||||
(if (rl/key-down? :key-space)
|
||||
(set frames-counter (+ frames-counter 8))
|
||||
(set frames-counter (+ frames-counter 1)))
|
||||
|
||||
(when (rl/key-pressed? :enter) (set frames-counter 0))
|
||||
(when (rl/key-pressed? :key-enter) (set frames-counter 0))
|
||||
|
||||
;; Draw
|
||||
(rl/with-drawing
|
||||
|
||||
@ -97,10 +97,10 @@
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
(when (rl/key-down? :right) (set (.x player-position) (+ (.x player-position) 5.0)))
|
||||
(when (rl/key-down? :left) (set (.x player-position) (- (.x player-position) 5.0)))
|
||||
(when (rl/key-down? :down) (set (.y player-position) (+ (.y player-position) 5.0)))
|
||||
(when (rl/key-down? :up) (set (.y player-position) (- (.y player-position) 5.0)))
|
||||
(when (rl/key-down? :key-right) (set (.x player-position) (+ (.x player-position) 5.0)))
|
||||
(when (rl/key-down? :key-left) (set (.x player-position) (- (.x player-position) 5.0)))
|
||||
(when (rl/key-down? :key-down) (set (.y player-position) (+ (.y player-position) 5.0)))
|
||||
(when (rl/key-down? :key-up) (set (.y player-position) (- (.y player-position) 5.0)))
|
||||
|
||||
;; Keep the player inside the tilemap. The far edge is measured against
|
||||
;; the player's far side, which is why player-size is subtracted.
|
||||
|
||||
@ -100,7 +100,7 @@
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
(when (or (rl/mouse-button-pressed? :left) (rl/key-pressed? :right))
|
||||
(when (or (rl/mouse-button-pressed? :mouse-left) (rl/key-pressed? :key-right))
|
||||
(set current-texture (% (+ current-texture 1) num-textures)))
|
||||
|
||||
;; Draw
|
||||
|
||||
@ -212,7 +212,7 @@
|
||||
(dotimes [i num-processes]
|
||||
(when (rl/collision-point-rec? (rl/get-mouse-position) (at toggle-recs i))
|
||||
(set mouse-hover-rec i)
|
||||
(when (rl/mouse-button-released? :left)
|
||||
(when (rl/mouse-button-released? :mouse-left)
|
||||
(set current-process i)
|
||||
(set reload true))))
|
||||
|
||||
@ -222,13 +222,13 @@
|
||||
;; as it is because changing it here would make this file disagree with
|
||||
;; the example it claims to be.
|
||||
(cond
|
||||
(rl/key-pressed? :down)
|
||||
(rl/key-pressed? :key-down)
|
||||
(do (set current-process (+ current-process 1))
|
||||
(when (> current-process (- num-processes 1))
|
||||
(set current-process 0))
|
||||
(set reload true))
|
||||
|
||||
(rl/key-pressed? :up)
|
||||
(rl/key-pressed? :key-up)
|
||||
(do (set current-process (- current-process 1))
|
||||
(when (< current-process 0) (set current-process 7))
|
||||
(set reload true)))
|
||||
|
||||
@ -125,9 +125,9 @@
|
||||
(until (rl/window-should-close?)
|
||||
;; Update
|
||||
(let [mouse-pos (rl/get-mouse-position)]
|
||||
(if (rl/key-pressed? :right)
|
||||
(if (rl/key-pressed? :key-right)
|
||||
(set color-selected (+ color-selected 1))
|
||||
(when (rl/key-pressed? :left)
|
||||
(when (rl/key-pressed? :key-left)
|
||||
(set color-selected (- color-selected 1))))
|
||||
(set color-selected (clamp color-selected 0 (- max-colors-count 1)))
|
||||
|
||||
@ -139,20 +139,20 @@
|
||||
(set color-mouse-hover i)
|
||||
(break)))
|
||||
|
||||
(when (and (>= color-mouse-hover 0) (rl/mouse-button-pressed? :left))
|
||||
(when (and (>= color-mouse-hover 0) (rl/mouse-button-pressed? :mouse-left))
|
||||
(set color-selected color-mouse-hover)
|
||||
(set color-selected-prev color-selected))
|
||||
|
||||
(set brush-size (clamp (+ brush-size (* (rl/get-mouse-wheel-move) 5.0))
|
||||
2.0 50.0))
|
||||
|
||||
(when (rl/key-pressed? :c)
|
||||
(when (rl/key-pressed? :key-c)
|
||||
(rl/with-texture-mode target
|
||||
(rl/clear-background (at colors 0))))
|
||||
|
||||
;; Paint. The gesture test is what makes the example work on a
|
||||
;; touchscreen, where there is no mouse button to hold.
|
||||
(when (or (rl/mouse-button-down? :left)
|
||||
(when (or (rl/mouse-button-down? :mouse-left)
|
||||
(= (rl/get-gesture-detected) :drag))
|
||||
(rl/with-texture-mode target
|
||||
;; Above y=50 is the palette strip, and a stroke there would paint
|
||||
@ -164,7 +164,7 @@
|
||||
;; Right button erases, which is painting in the clear colour. The
|
||||
;; selected swatch is parked while the button is held so the toolbar
|
||||
;; shows what is being drawn, and restored on release.
|
||||
(if (rl/mouse-button-down? :right)
|
||||
(if (rl/mouse-button-down? :mouse-right)
|
||||
(do
|
||||
(when (not mouse-was-pressed)
|
||||
(set color-selected-prev color-selected)
|
||||
@ -174,7 +174,7 @@
|
||||
(when (> (.y mouse-pos) 50.0)
|
||||
(rl/draw-circle (i32 (.x mouse-pos)) (i32 (.y mouse-pos))
|
||||
brush-size (at colors 0)))))
|
||||
(when (and (rl/mouse-button-released? :right) mouse-was-pressed)
|
||||
(when (and (rl/mouse-button-released? :mouse-right) mouse-was-pressed)
|
||||
(set color-selected color-selected-prev)
|
||||
(set mouse-was-pressed false)))
|
||||
|
||||
@ -182,8 +182,8 @@
|
||||
|
||||
;; The round trip. See the header comment for why the flip is here and
|
||||
;; not on the draw.
|
||||
(when (or (and btn-save-mouse-hover (rl/mouse-button-released? :left))
|
||||
(rl/key-pressed? :s))
|
||||
(when (or (and btn-save-mouse-hover (rl/mouse-button-released? :mouse-left))
|
||||
(rl/key-pressed? :key-s))
|
||||
(let [image (rl/load-image-from-texture (.texture target))]
|
||||
(rl/image-flip-vertical (addr image))
|
||||
(rl/export-image image "my_amazing_texture_painting.png")
|
||||
@ -210,7 +210,7 @@
|
||||
|
||||
;; The brush preview, drawn on the screen and not into the canvas.
|
||||
(when (> (.y mouse-pos) 50.0)
|
||||
(if (rl/mouse-button-down? :right)
|
||||
(if (rl/mouse-button-down? :mouse-right)
|
||||
(rl/draw-circle-lines (i32 (.x mouse-pos)) (i32 (.y mouse-pos))
|
||||
brush-size rl/gray)
|
||||
(rl/draw-circle (rl/get-mouse-x) (rl/get-mouse-y)
|
||||
|
||||
56
lib/check.ml
56
lib/check.ml
@ -666,6 +666,45 @@ let predicate_names = [ "ordered?"; "equal?"; "hashable?"; "numeric?"; "integer?
|
||||
walk could read — an untagged union is treated as owning nothing, and what
|
||||
its members point at is the program's, through whatever tag it keeps
|
||||
beside the union. *)
|
||||
(* One edit apart — a substitution, an insertion, a deletion or a
|
||||
transposition of neighbours. Bounded at one, because two edits is no longer
|
||||
a typo, it is a guess. Shared by the unknown-type near miss and the enum
|
||||
member one. *)
|
||||
let one_edit a b =
|
||||
let la = String.length a and lb = String.length b in
|
||||
if abs (la - lb) > 1 then false
|
||||
else begin
|
||||
(* Walk both until they diverge, then require the tails to match with the
|
||||
single edit applied. *)
|
||||
let i = ref 0 in
|
||||
while !i < la && !i < lb && a.[!i] = b.[!i] do incr i done;
|
||||
let ta s k = String.sub s k (String.length s - k) in
|
||||
if la = lb then
|
||||
!i < la
|
||||
&& (ta a (!i + 1) = ta b (!i + 1)
|
||||
(* stirng/string: two neighbours swapped. *)
|
||||
|| (!i + 1 < la && a.[!i] = b.[!i + 1] && a.[!i + 1] = b.[!i]
|
||||
&& ta a (!i + 2) = ta b (!i + 2)))
|
||||
else if la < lb then ta a !i = ta b (!i + 1)
|
||||
else ta a (!i + 1) = ta b !i
|
||||
end
|
||||
|
||||
(* The enum members' own near miss. One edit away is the usual typo; the
|
||||
second rule is for a package whose members carry a disambiguating prefix —
|
||||
raylib's Key spells them [key-r], [key-space] — where the natural mistake
|
||||
is writing the bare name. [:r] against [key-r] is four edits and one
|
||||
thought, so the rule is the thought: a member whose last segment is exactly
|
||||
the name written. *)
|
||||
let member_near_miss members k =
|
||||
List.find_opt
|
||||
(fun (m, _) ->
|
||||
one_edit k m
|
||||
|| (let lm = String.length m and lk = String.length k in
|
||||
lm > lk + 1
|
||||
&& m.[lm - lk - 1] = '-'
|
||||
&& String.sub m (lm - lk) lk = k))
|
||||
members
|
||||
|
||||
let owning_fields env n =
|
||||
match Hashtbl.find_opt env.structs n with
|
||||
| Some s -> [ s.Tast.fields ]
|
||||
@ -2896,9 +2935,20 @@ let rec check ctx ?want (e : Ast.expr) : Tast.expr =
|
||||
(match List.assoc_opt k members with
|
||||
| Some v -> mk loc (Types.Enum name) (Tast.Int (v, Types.I32))
|
||||
| None ->
|
||||
fail loc "%s has no member :%s — it has %s" name k
|
||||
(String.concat " "
|
||||
(List.map (fun (m, _) -> ":" ^ m) members)))
|
||||
(* The near miss first, because the raylib enums carry a
|
||||
disambiguating member prefix — [:r] is four edits from [:key-r]
|
||||
and one thought, and the list alone makes the reader do the
|
||||
thought. The list still follows: the suggestion can be wrong. *)
|
||||
(match member_near_miss members k with
|
||||
| Some (m, _) ->
|
||||
fail loc "%s has no member :%s — did you mean :%s? It has %s"
|
||||
name k m
|
||||
(String.concat " "
|
||||
(List.map (fun (m, _) -> ":" ^ m) members))
|
||||
| None ->
|
||||
fail loc "%s has no member :%s — it has %s" name k
|
||||
(String.concat " "
|
||||
(List.map (fun (m, _) -> ":" ^ m) members))))
|
||||
| Some Types.Dyn | None ->
|
||||
expect ctx loc ~want
|
||||
(rt loc Types.Dyn "flan_dyn_kw" [ mk loc Types.String (Tast.Str k) ])
|
||||
|
||||
@ -628,6 +628,15 @@ type config = {
|
||||
prefix ["-"] means the header has nothing to check this enum against and
|
||||
that is deliberate.
|
||||
|
||||
[enum_flan_prefixes]: the prefix the same defenum's members carry on the
|
||||
*Flan* side, when they carry one. Members can be prefixed there too —
|
||||
[key-r] rather than [r], so a keyword cannot collide across enums — and
|
||||
the C name is built by stripping the Flan prefix first and then applying
|
||||
the C one: [("Key", "key-")] against [("Key", "KEY_")] checks [key-r] as
|
||||
[KEY_R] rather than [KEY_KEY_R]. Declared as a fourth column on the
|
||||
`enum` line, and a member that does not carry the declared prefix is a
|
||||
finding, not a member checked under a guessed name.
|
||||
|
||||
[const_prefixes]: a prefix of [defconst] names, and the prefix the
|
||||
corresponding C enumerators carry. [("flag-", "FLAG_")] checks
|
||||
[flag-vsync-hint] against [FLAG_VSYNC_HINT].
|
||||
@ -638,13 +647,14 @@ type config = {
|
||||
[GESTURE_DOUBLETAP] against a member the package spells [double-tap]. It
|
||||
also brings a name under the check that no prefix rule covers. *)
|
||||
enum_prefixes : (string * string) list;
|
||||
enum_flan_prefixes : (string * string) list;
|
||||
const_prefixes : (string * string) list;
|
||||
constants : (string * string) list;
|
||||
}
|
||||
|
||||
let no_config =
|
||||
{ excludes = []; renames = []; enum_prefixes = []; const_prefixes = [];
|
||||
constants = [] }
|
||||
{ excludes = []; renames = []; enum_prefixes = []; enum_flan_prefixes = [];
|
||||
const_prefixes = []; constants = [] }
|
||||
|
||||
(* [*] stands for any run of characters and nothing else does anything. Enough
|
||||
for [rl*] or [*Callback], and small enough to read at a glance; a package
|
||||
@ -679,7 +689,8 @@ let read_config path : config =
|
||||
else begin
|
||||
let ch = open_in path in
|
||||
let excludes = ref [] and renames = ref [] in
|
||||
let enum_prefixes = ref [] and const_prefixes = ref [] and constants = ref [] in
|
||||
let enum_prefixes = ref [] and enum_flan_prefixes = ref []
|
||||
and const_prefixes = ref [] and constants = ref [] in
|
||||
let rec go n =
|
||||
match input_line ch with
|
||||
| line ->
|
||||
@ -694,15 +705,29 @@ let read_config path : config =
|
||||
| [ "exclude"; p ] -> excludes := p :: !excludes
|
||||
| [ "name"; sym; flan ] -> renames := (sym, flan) :: !renames
|
||||
| [ "enum"; flan; c ] -> enum_prefixes := (flan, c) :: !enum_prefixes
|
||||
(* The optional fourth column: the prefix the members carry on the
|
||||
Flan side, stripped before the C prefix is applied. Refused on
|
||||
`enum Foo -` rather than ignored — a column that does nothing on
|
||||
one shape of line is a column somebody will trust on both. *)
|
||||
| [ "enum"; flan; c; fp ] ->
|
||||
if String.equal c "-" then begin
|
||||
close_in ch;
|
||||
fail (Loc.make path n 0)
|
||||
"`enum %s -` says the header has nothing to check %s against, \
|
||||
so a Flan member prefix on that line would strip for no \
|
||||
comparison — drop `%s`, or name the C prefix" flan flan fp
|
||||
end;
|
||||
enum_prefixes := (flan, c) :: !enum_prefixes;
|
||||
enum_flan_prefixes := (flan, fp) :: !enum_flan_prefixes
|
||||
| [ "const"; flan; c ] -> const_prefixes := (flan, c) :: !const_prefixes
|
||||
| [ "constant"; flan; c ] -> constants := (flan, c) :: !constants
|
||||
| _ ->
|
||||
close_in ch;
|
||||
fail (Loc.make path n 0)
|
||||
"a line here is `exclude <C symbol or pattern>`, `name <C \
|
||||
symbol> <flan-name>`, `enum <FlanEnum> <C_PREFIX>`, `const \
|
||||
<flan-prefix> <C_PREFIX>` or `constant <flan-name> <C_NAME>`, \
|
||||
and this is neither: %s" t
|
||||
symbol> <flan-name>`, `enum <FlanEnum> <C_PREFIX> \
|
||||
[<flan-prefix>]`, `const <flan-prefix> <C_PREFIX>` or \
|
||||
`constant <flan-name> <C_NAME>`, and this is neither: %s" t
|
||||
end;
|
||||
go (n + 1)
|
||||
| exception End_of_file -> ()
|
||||
@ -711,6 +736,7 @@ let read_config path : config =
|
||||
close_in ch;
|
||||
{ excludes = List.rev !excludes; renames = List.rev !renames;
|
||||
enum_prefixes = List.rev !enum_prefixes;
|
||||
enum_flan_prefixes = List.rev !enum_flan_prefixes;
|
||||
const_prefixes = List.rev !const_prefixes;
|
||||
constants = List.rev !constants }
|
||||
end
|
||||
@ -1209,15 +1235,31 @@ let check_constants ~config
|
||||
| Some "-" -> Hashtbl.replace used ("enum:" ^ ename) ()
|
||||
| Some prefix ->
|
||||
Hashtbl.replace used ("enum:" ^ ename) ();
|
||||
(* The Flan-side member prefix, when the `enum` line declares one:
|
||||
[key-r] is KEY_R and not KEY_KEY_R, because the prefix is stripped
|
||||
before the C one is applied. A member that does not carry the
|
||||
declared prefix is a finding rather than a member checked under a
|
||||
guessed name — [null] beside a declared [key-] would otherwise
|
||||
build KEY_NULL, which the header happens to have, and the naming
|
||||
rule the line declares would erode silently. *)
|
||||
let fprefix = List.assoc_opt ename config.enum_flan_prefixes in
|
||||
List.iter
|
||||
(fun (m, v) ->
|
||||
let flan = ename ^ "/" ^ m in
|
||||
let cname =
|
||||
match List.assoc_opt flan explicit with
|
||||
| Some c -> c
|
||||
| None -> prefix ^ screaming m
|
||||
in
|
||||
compare_one flan v cname)
|
||||
match List.assoc_opt flan explicit with
|
||||
| Some c -> compare_one flan v c
|
||||
| None ->
|
||||
(match fprefix with
|
||||
| None -> compare_one flan v (prefix ^ screaming m)
|
||||
| Some fp ->
|
||||
(match strip_prefix fp m with
|
||||
| Some stem -> compare_one flan v (prefix ^ screaming stem)
|
||||
| None ->
|
||||
mapping_say flan
|
||||
"the `enum %s` line in the package's `bindings` says \
|
||||
its members carry the prefix %s on the Flan side, \
|
||||
and %s does not — rename the member, or fix the line"
|
||||
ename fp m)))
|
||||
members)
|
||||
enums;
|
||||
(* Plain constants, and only the ones a rule or a [constant] line reaches. *)
|
||||
|
||||
@ -2890,6 +2890,16 @@ let () =
|
||||
rejects_check "a keyword that is not a member"
|
||||
"(defenum Key [space 32]) (defn g [k Key] ()) (defn f [] () (g :spcae))"
|
||||
~needle:"has no member :spcae";
|
||||
(* The near miss. A typo one edit away is suggested, and so is the bare
|
||||
name of a member that carries a disambiguating prefix — raylib's Key
|
||||
spells its members key-r, key-space, and :r is the natural mistake. *)
|
||||
rejects_check "a member one edit away is suggested"
|
||||
"(defenum Key [space 32]) (defn g [k Key] ()) (defn f [] () (g :spcae))"
|
||||
~needle:"did you mean :space?";
|
||||
rejects_check "a bare name suggests the prefixed member"
|
||||
"(defenum Key [key-space 32 key-r 82]) (defn g [k Key] ()) \
|
||||
(defn f [] () (g :r))"
|
||||
~needle:"did you mean :key-r?";
|
||||
accepts "a keyword that is a member"
|
||||
"(defenum Key [space 32 r 82]) (defn g [k Key] ()) (defn f [] () (g :r))";
|
||||
(* Converting an enum, explicitly, in both directions. The point of the
|
||||
@ -3880,6 +3890,17 @@ let () =
|
||||
(match Cimport.read_config (config_file "rename Foo bar\n") with
|
||||
| _ -> false
|
||||
| exception Loc.Error { Loc.dmsg = m; _ } -> contains m "and this is neither");
|
||||
(* The enum line's fourth column: the prefix the members carry on the Flan
|
||||
side, so `key-r` is checked as KEY_R and not KEY_KEY_R. *)
|
||||
let c = Cimport.read_config (config_file "enum Key KEY_ key-\n") in
|
||||
check "read_config reads an enum line's Flan member prefix"
|
||||
(c.Cimport.enum_prefixes = [ ("Key", "KEY_") ]
|
||||
&& c.Cimport.enum_flan_prefixes = [ ("Key", "key-") ]);
|
||||
check "a Flan member prefix on `enum Foo -` is refused"
|
||||
(match Cimport.read_config (config_file "enum Foo - key-\n") with
|
||||
| _ -> false
|
||||
| exception Loc.Error { Loc.dmsg = m; _ } ->
|
||||
contains m "nothing to check Foo against");
|
||||
|
||||
(* A refused name is a name that exists and cannot be had — Zig's failDecl,
|
||||
which Load.refuse_hidden already implements for main. Nothing may be in
|
||||
@ -4153,6 +4174,37 @@ let () =
|
||||
contains why "no constant named SHADE_HALF_DARK"
|
||||
| _ -> false);
|
||||
|
||||
(* The Flan-side member prefix, declared as the enum line's fourth column.
|
||||
raylib's Key spells its members key-r, key-space — a bare member name
|
||||
collides across enums — and the C name is built by stripping that prefix
|
||||
first, so key-r is KEY_R and not KEY_KEY_R. *)
|
||||
let prefixed =
|
||||
{ mapping with Cimport.enum_flan_prefixes = [ ("Mood", "mood-") ] }
|
||||
in
|
||||
check "a declared Flan member prefix is stripped before the C name is built"
|
||||
(constants ~config:prefixed
|
||||
(const_fixture ~mood:"[mood-calm 0 mood-cross 1]" ())
|
||||
= []);
|
||||
check "a wrong value is still caught through the stripped prefix"
|
||||
(match
|
||||
constants ~config:prefixed
|
||||
(const_fixture ~mood:"[mood-calm 0 mood-cross 2]" ())
|
||||
with
|
||||
| [ ("Mood/mood-cross", why) ] ->
|
||||
contains why "MOOD_CROSS" && contains why "is 2 here"
|
||||
| _ -> false);
|
||||
(* A member that does not carry the declared prefix is a finding, not a
|
||||
member checked under a guessed name: `calm` beside a declared `mood-`
|
||||
would otherwise build MOOD_CALM, which the header has, and the naming
|
||||
rule the line declares would erode silently. *)
|
||||
check "a member without the declared Flan prefix is a mapping finding"
|
||||
(match raw_constants ~config:prefixed (const_fixture ()) with
|
||||
| [ a; b ] ->
|
||||
a.Cimport.cmapping && b.Cimport.cmapping
|
||||
&& contains a.Cimport.cwhy "carry the prefix mood-"
|
||||
&& contains b.Cimport.cwhy "carry the prefix mood-"
|
||||
| _ -> false);
|
||||
|
||||
(* Coverage itself must not go quiet. A defenum nobody mapped would be
|
||||
silently unchecked, which is the same hole one level up. *)
|
||||
check "a defenum with no enum line is itself a finding"
|
||||
|
||||
15
vendor/raylib/bindings
vendored
15
vendor/raylib/bindings
vendored
@ -194,7 +194,7 @@ name ImageDrawTriangleStrip image-draw-triangle-strip-raw
|
||||
|
||||
# ── What the package's constants are called in C ────────────────────
|
||||
#
|
||||
# enum <FlanEnum> <C_PREFIX> every member of that defenum
|
||||
# enum <FlanEnum> <C_PREFIX> [<flan-prefix>] every member of that defenum
|
||||
# const <flan-prefix> <C_PREFIX> every defconst whose name starts so
|
||||
# constant <flan-name> <C_NAME> one name, exactly
|
||||
#
|
||||
@ -212,11 +212,20 @@ name ImageDrawTriangleStrip image-draw-triangle-strip-raw
|
||||
# skipped; a mapping that quietly matched nothing would read as coverage and
|
||||
# provide none.
|
||||
#
|
||||
# An enum line's optional third column is a prefix the members carry on the
|
||||
# *Flan* side. Key and MouseButton spell their members `key-r` and
|
||||
# `mouse-left`, because the bare names collide — across the two enums and
|
||||
# with a user's own — and without the column the rule above would double the
|
||||
# prefix: KEY_KEY_R. The declared Flan prefix is stripped first and the C one
|
||||
# applied to what is left, so `key-r` checks against KEY_R and `mouse-left`
|
||||
# against MOUSE_BUTTON_LEFT. A member that does not carry the declared prefix
|
||||
# is reported, not checked under a guessed name.
|
||||
#
|
||||
# Every defenum needs a line, including one the header cannot check, which
|
||||
# says so with `-`. That is the same rule one level up: an enum nobody mapped
|
||||
# would be silently unchecked, which is the hole this closes.
|
||||
enum Key KEY_
|
||||
enum MouseButton MOUSE_BUTTON_
|
||||
enum Key KEY_ key-
|
||||
enum MouseButton MOUSE_BUTTON_ mouse-
|
||||
enum TraceLogLevel LOG_
|
||||
enum CameraProjection CAMERA_
|
||||
enum CameraMode CAMERA_
|
||||
|
||||
40
vendor/raylib/raylib.flan
vendored
40
vendor/raylib/raylib.flan
vendored
@ -70,22 +70,32 @@
|
||||
|
||||
;; KeyboardKey, the subset sand.flan 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, and MouseButton's carry `mouse-`,
|
||||
;; because the bare names collide — :left would mean a key here and a button
|
||||
;; there, and a plain word like :space is one a user's own enum wants too.
|
||||
;; The prefix is declared in `bindings` (the enum line's third column), which
|
||||
;; is what keeps :key-r checking against KEY_R rather than KEY_KEY_R.
|
||||
(defenum Key
|
||||
[space 32 apostrophe 39 comma 44 minus 45 period 46 slash 47
|
||||
zero 48 one 49 two 50 three 51 four 52
|
||||
five 53 six 54 seven 55 eight 56 nine 57
|
||||
a 65 b 66 c 67 d 68 e 69 f 70 g 71 h 72 i 73
|
||||
j 74 k 75 l 76 m 77 n 78 o 79 p 80 q 81 r 82
|
||||
s 83 t 84 u 85 v 86 w 87 x 88 y 89 z 90
|
||||
escape 256 enter 257 tab 258 backspace 259
|
||||
right 262 left 263 down 264 up 265
|
||||
left-shift 340
|
||||
[key-space 32 key-apostrophe 39 key-comma 44 key-minus 45
|
||||
key-period 46 key-slash 47
|
||||
key-zero 48 key-one 49 key-two 50 key-three 51 key-four 52
|
||||
key-five 53 key-six 54 key-seven 55 key-eight 56 key-nine 57
|
||||
key-a 65 key-b 66 key-c 67 key-d 68 key-e 69 key-f 70 key-g 71
|
||||
key-h 72 key-i 73 key-j 74 key-k 75 key-l 76 key-m 77 key-n 78
|
||||
key-o 79 key-p 80 key-q 81 key-r 82 key-s 83 key-t 84 key-u 85
|
||||
key-v 86 key-w 87 key-x 88 key-y 89 key-z 90
|
||||
key-escape 256 key-enter 257 key-tab 258 key-backspace 259
|
||||
key-right 262 key-left 263 key-down 264 key-up 265
|
||||
key-left-shift 340
|
||||
;; KEY_NULL is not a key. It is the value set-exit-key takes to mean "no
|
||||
;; key closes the window", which is the only thing that ever passes it.
|
||||
null 0])
|
||||
key-null 0])
|
||||
|
||||
;; `mouse-` and not `button-`: gamepads have buttons too.
|
||||
(defenum MouseButton
|
||||
[left 0 right 1 middle 2 side 3 extra 4 forward 5 back 6])
|
||||
[mouse-left 0 mouse-right 1 mouse-middle 2 mouse-side 3 mouse-extra 4
|
||||
mouse-forward 5 mouse-back 6])
|
||||
|
||||
(defenum TraceLogLevel
|
||||
[all 0 trace 1 debug 2 info 3 warning 4 error 5 fatal 6 none 7])
|
||||
@ -144,8 +154,8 @@
|
||||
;; Which key closes the window, ESCAPE by default. Hand-written rather than
|
||||
;; left to the generated half because the Flan face is the difference: raylib
|
||||
;; declares it `void SetExitKey(int key)` and the generated line therefore
|
||||
;; takes an i32, where this one takes a Key and so accepts :escape and refuses
|
||||
;; a typo. `:null` is how a program says "no key does that" and takes the
|
||||
;; takes an i32, where this one takes a Key and so accepts :key-escape and refuses
|
||||
;; a typo. `:key-null` is how a program says "no key does that" and takes the
|
||||
;; close over itself.
|
||||
(declare-c set-exit-key [key Key] "SetExitKey")
|
||||
|
||||
@ -155,7 +165,7 @@
|
||||
|
||||
;; 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/key-up? :space)` did not compile while `(rl/key-down? :space)` did.
|
||||
;; `(rl/key-up? :key-space)` did not compile while `(rl/key-down? :key-space)` did.
|
||||
;; That is a hole in a family rather than a missing convenience — a caller
|
||||
;; who has used 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
|
||||
@ -192,7 +202,7 @@
|
||||
;; get-key-pressed answers an i32 and not a Key. A Key is a *closed* set the
|
||||
;; package names a subset of, and this queue reports every key on the
|
||||
;; keyboard including the ones no member covers, so the enum would be a
|
||||
;; promise the value does not keep. Comparing the answer against `:space`
|
||||
;; promise the value does not keep. Comparing the answer against `:key-space`
|
||||
;; would be the reason to want it, and that is what key-pressed? is for.
|
||||
(defn get-key-pressed [] (Option i32)
|
||||
(let [k (get-key-pressed-raw)]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user