flan/vendor/raylib/bindings
Joseph Ferano 9223c9002a An enum is four bytes, and the header check now reads the constants
Two gaps the raylib examples hit.

The layout check compared a Flan enum against the header's `int` and
called it a disagreement. It is not one: Shim.cty lowers a defenum to
int32_t in a struct field exactly as it does in a parameter, which is
what the signature check already knew and the layout check did not. One
predicate now serves both, symmetric, and tolerant of a 32-bit integer
and nothing else -- f64 against the library's float still fails, in the
very struct whose other field is an enum. Camera3D.projection is a
CameraProjection again and rl/camera-projection is gone with it, so
`.projection :perspective` resolves at the construction site.

And generate-c's claim said nothing about a defconst or a defenum
member, so a wrong flag bit was completely silent. `bindings` gained
`enum`, `const` and `constant` lines saying what a Flan constant is
called in C -- the prefix is nowhere in the Flan name, so it is declared
rather than guessed. Nothing goes quiet in either direction: a name the
rule builds and the header lacks is reported, a rule that reaches
nothing is reported, and a defenum with no line is itself a finding,
because otherwise the silence just moves up one level.

clang's dump gives anonymous EnumDecls for every raylib enum and no
value at all for an enumerator written without `= n`, so the constants
are one flat table and the values are counted the way C counts them.
cache_format bumped with the dump type.
2026-09-13 14:11:35 +07:00

166 lines
8.5 KiB
Plaintext

# How the generated bindings in generated.flan are shaped. One directive per
# line, `#` comments, blank lines ignored. A line that is neither directive is
# an error rather than a line quietly skipped.
#
# exclude <C symbol or pattern> do not generate a binding for this
# name <C symbol> <flan-name> call it this instead of the kebab rule's
#
# `*` in an exclude pattern stands for any run of characters, and nothing else
# does anything.
#
# Why this file exists. generated.flan is committed, so it is not a build
# artefact anybody can hand-correct: the next `flan generate-c vendor/raylib`
# overwrites it, and an edit made there is destroyed without anybody being
# told. This file is read *while* those lines are made, so it is the edit that
# survives regeneration. A postprocessing pass over the generated text was the
# alternative and was rejected — a second program to understand, applied to
# 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
# 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
# by a Flan defn of the same name without the suffix.
# ── raylib's allocator ──────────────────────────────────────────────
#
# raylib exports malloc, realloc and free under its own names. Flan's memory
# model is explicit — plan.org's rule is that an operation never falls back to
# a hidden allocator — so binding these would put a second, untracked heap
# behind three innocuous-looking Flan names, and a pointer from one freed by
# the other is the kind of bug that does not point at itself. Nothing in the
# package needs them: raylib's own Load*/Unload* pairs own everything raylib
# allocates.
exclude MemAlloc
exclude MemRealloc
exclude MemFree
# ── Predicates read as questions ────────────────────────────────────
#
# The kebab rule gives `is-window-ready`, which is C's phrasing wearing Flan's
# punctuation. The hand-written bindings in raylib.flan settled the convention
# years of Lisp settled first — a predicate ends in `?` and does not begin with
# `is` — and these are the generated half of the same set, so they follow it.
# key-pressed? and window-ready? being spelled differently would be the split
# this whole change exists to remove.
#
# The C symbol is kept verbatim in the declaration either way, so nothing here
# is lost: the name is the Flan face and `IsWindowReady` is still what is
# called and still what the check compares against.
name IsWindowReady window-ready?
name IsWindowFullscreen window-fullscreen?
name IsWindowHidden window-hidden?
name IsWindowMinimized window-minimized?
name IsWindowMaximized window-maximized?
name IsWindowFocused window-focused?
name IsWindowResized window-resized?
name IsWindowState window-state?
name IsCursorOnScreen cursor-on-screen?
name IsKeyUp key-up?
name IsKeyPressedRepeat key-pressed-repeat?
name IsMouseButtonUp mouse-button-up?
name IsFileDropped file-dropped?
name IsFileExtension file-extension?
name IsFileNameValid file-name-valid?
name IsPathFile path-file?
name IsAudioStreamValid audio-stream-valid?
name IsAudioStreamPlaying audio-stream-playing?
name IsAudioStreamProcessed audio-stream-processed?
# Hand-written in raylib.flan, 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 (PORTING.md), and a hand-written line is what the signature
# check has to compare against -- generated output agrees with the header by
# construction, so it can only check the hand-written half.
exclude DrawTexturePro
exclude ImageFromImage
exclude IsWindowReady
# The scissor pair and the 3D surface the ported examples in examples/ draw
# through, excluded here for the same two reasons in different proportions.
#
# - BeginScissorMode/EndScissorMode, BeginMode3D/EndMode3D, DrawCube,
# DrawCubeWires, DrawGrid are inside a frame. The rule above is about the
# per-frame path, and a begin/end pair is taken together: hand-writing one
# half and generating the other is the asymmetry that reads as a mistake.
# - SetExitKey, UpdateCamera and GetWorldToScreen are excluded because their
# Flan face is not the C signature. SetExitKey takes a Key and not an int,
# UpdateCamera takes a CameraMode, and both of those refuse a typo the
# generated i32 would take. GetWorldToScreen goes with BeginMode3D
# because they read the same camera.
#
# What this line splits, and deliberately: draw-cube is here and draw-cube-v
# is generated, get-world-to-screen is here and get-world-to-screen-ex is
# generated, update-camera is here and update-camera-pro is generated. Every
# other family in raylib.flan — 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 the examples ask for.
#
# What is deliberately NOT here: the window-state family (IsWindowState,
# SetWindowState, ClearWindowState, ToggleFullscreen, Minimize/Maximize/
# RestoreWindow), GetMouseX/GetMouseY and GetRandomValue. Those are called
# per frame by the examples too, but their Flan face IS the C one — plain
# scalars, nothing an enum or a pointer improves — and generated.flan is
# committed, so the default build has them with no header set either way.
exclude BeginScissorMode
exclude EndScissorMode
exclude BeginMode3D
exclude EndMode3D
exclude DrawCube
exclude DrawCubeWires
exclude DrawGrid
exclude SetExitKey
exclude UpdateCamera
exclude GetWorldToScreen
# ── What the package's constants are called in C ────────────────────
#
# enum <FlanEnum> <C_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
#
# Why any of this is needed. `generate-c` used to claim only that every
# defstruct and every hand-written declare-c agreed with raylib.h. It said
# nothing about a defconst or a defenum member — so a wrong flag bit or a
# wrong enum value was *silent*: no link error, no type error, just a window
# that does not open. These lines are what let the check reach them.
#
# The Flan member name becomes the C one by uppercasing and turning `-` into
# `_`, which gets KEY_LEFT_SHIFT out of `left-shift` and FLAG_MSAA_4X_HINT out
# of `msaa-4x-hint`. What it cannot get is the prefix, because the prefix is
# nowhere in the Flan name — so the prefix is said here rather than guessed. A
# name the rule builds and the header does not have is REPORTED and not
# skipped; a mapping that quietly matched nothing would read as coverage and
# provide none.
#
# 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 TraceLogLevel LOG_
enum CameraProjection CAMERA_
enum CameraMode CAMERA_
enum GamepadButton GAMEPAD_BUTTON_
enum GamepadAxis GAMEPAD_AXIS_
enum Gesture GESTURE_
# raylib writes GESTURE_DOUBLETAP as one word where every other member of that
# enum is underscored. This is the narrow exception and not a general escape
# hatch: one name the prefix rule gets wrong, said once.
constant Gesture/double-tap GESTURE_DOUBLETAP
# The 16 ConfigFlags bits. These are the values sand.flan 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.
const flag- FLAG_
# What is deliberately NOT mapped: the 26 colours (a Color is a struct, not an
# enumerator), the examples' screen sizes, and `gesture-all`. That last one is
# 1023, the OR of all ten Gesture members, and raylib has no enumerator with
# that value — there is nothing in the header to compare it against, so
# nothing claims to.