flan/examples/core-input-mouse-wheel.flan
Joseph Ferano 421e09e0d6 A number can reach draw-text now
(string b) is the mirror of (bytes s) and costs nothing: emit.ml already
lowers Types.String and Types.Slice _ to the same %slice, 16 bytes at
align 8, so a string and a [u8] are the identical value at run time and
both directions emit as the argument itself. What changes is only what
the checker will let the value be passed to — which was the whole gap.

Two decisions, both written into check.ml's comment.

It does not check UTF-8, because `string` does not claim UTF-8. The
prelude settles it: valid-utf8? is an ordinary function you call when you
care, decode-rune / rune-at / rune-count all take [u8] and not string,
and decode-rune answers {:ok false :width 1} on a malformed byte rather
than assuming well-formed input. The one place the runtime treats a
string differently from a byte slice is flan_escape_bytes, for a string
nested in a printed structure, and that is a byte-wise escape table with
no decoding in it. A check here would be the only enforcement point in
the language, which is a claim the rest of it does not make.

It does not widen the literal-write hole. That hole is the other
direction — (bytes "Hi") hands back a writable-looking slice over
constant data — and this direction only loses the ability to write, so
the result reaches strictly fewer stores than its argument could.
Provenance is still what the other direction needs; nothing here waits
on it.

The one sharp edge is not new but is easier to trip over now, and is
recorded in both the checker and digits.flan: i64->bytes, f64->bytes and
u64->bytes all view the same static buffer in the runtime, overwritten
by the next call, and calling it a string does not copy it. Format, draw,
then format the next one.

examples/digits.flan keeps its three signatures and loses its middle: the
[10 string] table, the per-glyph pen and the digit arithmetic are gone,
and draw-int is one draw-text. What survives is the part (string ...)
does not answer — i64->bytes has no field width, so "%03i" is still
assembled, and f64->bytes is "%g", so fixed decimal places are still a
split into two integers. core-input-multitouch and
core-input-virtual-controls ignored the width they were given, so both
inline the draw and stop importing digits.flan entirely.

test/programs/string-of-bytes.flan at -O2 and -O0: a number round-tripped,
an empty slice, sub-views whose length is not the underlying storage's,
and the result across a declare-c boundary. The last is the one that
could have been wrong — "hello world" cut to five bytes has a space where
C wants a NUL, so a shim that trusted the bytes would print all eleven.
2026-09-12 05:19:23 +07:00

56 lines
2.0 KiB
Plaintext

;;;; raylib [core] example - input mouse wheel
;;;;
;;;; examples/core/core_input_mouse_wheel.c. Needed get-mouse-wheel-move, now
;;;; bound.
;;;;
;;;; This is the first example with a `TextFormat` in it. The C draws
;;;;
;;;; DrawText(TextFormat("Box position Y: %03i", boxPositionY), ...)
;;;;
;;;; and the number half of that is now sayable: (string (i64->bytes n)).
;;;; What is not is the "%03" — i64->bytes has no field width — so the label
;;;; is drawn with draw-text and the number with draw-int-padded from
;;;; examples/digits.flan, which draws the leading zeroes itself and then the
;;;; number in one call. A number wider than three digits is drawn in full,
;;;; exactly as printf's minimum-width means.
;;;;
;;;; The position is signed and goes negative as soon as the box scrolls past
;;;; the top, which is why draw-int-padded handles a sign at all.
(import rl "vendor:raylib")
(import d "digits.flan")
(defconst screen-width 800)
(defconst screen-height 450)
(defconst scroll-speed 4)
(defvar box-y i32)
(defn main []
(rl/init-window screen-width screen-height
"raylib [core] example - input mouse wheel")
(defer (rl/close-window))
(set box-y (- (/ screen-height 2) 40))
(rl/set-target-fps 60)
(until (rl/window-should-close?)
;; Update. The wheel reading is a per-frame delta, so it is 0.0 on every
;; frame the wheel did not turn and this is a no-op then.
(set box-y (- box-y (i32 (* (rl/get-mouse-wheel-move) (f32 scroll-speed)))))
;; Draw
(rl/begin-drawing)
(rl/clear-background rl/raywhite)
(rl/draw-rectangle (- (/ screen-width 2) 40) box-y 80 80 rl/maroon)
(rl/draw-text "Use mouse wheel to move the cube up and down!" 10 10 20
rl/gray)
;; The two halves of the C's one TextFormat call: the literal, measured,
;; and then the number starting where it ended.
(rl/draw-text "Box position Y: " 10 40 20 rl/lightgray)
(d/draw-int-padded box-y 3 (+ 10 (rl/measure-text "Box position Y: " 20))
40 20 rl/lightgray)
(rl/end-drawing)))