The examples are files that run, not prose, so the page cannot drift from them
Copying a snippet into HTML is where a documented language stops being the real one. Each block on the page is a program here with its recorded output beside it, and check.sh is what says the page is still true after a change.
This commit is contained in:
parent
2ecfac7561
commit
dfd64d89ea
23
web/examples/arrays.flan
Normal file
23
web/examples/arrays.flan
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
(defconst rows 3)
|
||||||
|
(defconst cols 4)
|
||||||
|
|
||||||
|
;; A fixed array is a value: inline storage, copies on assignment.
|
||||||
|
(defconst palette [4 u32] [0xE6B800FF 0x3B6E8CFF 0xA83232FF 0xCC6B1FFF])
|
||||||
|
|
||||||
|
;; No initialiser means all-bytes-zero, so this is BSS and costs nothing.
|
||||||
|
(defvar grid [rows [cols i32]])
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(set (at grid 1 2) 7)
|
||||||
|
(print-i64 (i64 (at grid 1 2))) (newline) ; 7
|
||||||
|
(print-i64 (i64 (len palette))) (newline) ; 4
|
||||||
|
|
||||||
|
;; A slice is ptr+len and non-owning: it views the array, it does not copy it.
|
||||||
|
(let [row (slice (at grid 1) 0 cols)]
|
||||||
|
(set (at row 0) 5)
|
||||||
|
(print-i64 (i64 (at grid 1 0))) (newline) ; 5 — the same storage
|
||||||
|
(print-i64 (sum-i32 row)) (newline)) ; 12
|
||||||
|
|
||||||
|
;; (zeroed) is a memset, not an allocation.
|
||||||
|
(set grid (zeroed))
|
||||||
|
(print-i64 (i64 (at grid 1 2))) (newline)) ; 0
|
||||||
6
web/examples/arrays.out
Normal file
6
web/examples/arrays.out
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
7
|
||||||
|
4
|
||||||
|
5
|
||||||
|
12
|
||||||
|
0
|
||||||
|
exit 0
|
||||||
12
web/examples/boom.flan
Normal file
12
web/examples/boom.flan
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
(defstruct Missing [id i32])
|
||||||
|
|
||||||
|
(defn load [n i32] i32
|
||||||
|
(restart-case
|
||||||
|
(do (error (Missing {:id n})) ; Never — only a transfer gets past
|
||||||
|
0)
|
||||||
|
(use-placeholder [] -1)
|
||||||
|
(retry [] 7)))
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(print-i64 (i64 (load 1)))
|
||||||
|
(newline))
|
||||||
2
web/examples/boom.out
Normal file
2
web/examples/boom.out
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
unhandled Missing
|
||||||
|
exit 134
|
||||||
37
web/examples/check.sh
Normal file
37
web/examples/check.sh
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Every Flan program shown on index.html is in this directory, and this script
|
||||||
|
# runs all of them and compares what they print against the .out file beside
|
||||||
|
# them. An example that does not compile is worse than no example, so the page
|
||||||
|
# quotes only what this script has been green on.
|
||||||
|
#
|
||||||
|
# $ dune build && sh web/examples/check.sh
|
||||||
|
#
|
||||||
|
# FLAN overrides the compiler; the default is the one dune just built.
|
||||||
|
here=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
root=$(cd "$here/../.." && pwd)
|
||||||
|
FLAN=${FLAN:-$root/_build/default/bin/main.exe}
|
||||||
|
|
||||||
|
cd "$here" || exit 1
|
||||||
|
fail=0
|
||||||
|
for f in *.flan; do
|
||||||
|
# shimdemo.flan calls raylib, so it is not run. What it demonstrates is the
|
||||||
|
# C the compiler writes, which is checked below by generating that instead.
|
||||||
|
[ "$f" = shimdemo.flan ] && continue
|
||||||
|
got=$( { "$FLAN" run "$f"; echo "exit $?"; } 2>&1 )
|
||||||
|
if [ "$got" = "$(cat "${f%.flan}.out")" ]; then
|
||||||
|
echo "ok $f"
|
||||||
|
else
|
||||||
|
echo "FAIL $f"
|
||||||
|
printf '%s\n' "$got" | diff -u "${f%.flan}.out" - || true
|
||||||
|
fail=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if "$FLAN" shim shimdemo.flan | grep -q 'GetMousePosition(void)'; then
|
||||||
|
echo "ok shimdemo.flan (flan shim)"
|
||||||
|
else
|
||||||
|
echo "FAIL shimdemo.flan (flan shim)"
|
||||||
|
fail=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $fail
|
||||||
16
web/examples/conds.flan
Normal file
16
web/examples/conds.flan
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
(defstruct AssetMissing [id i32])
|
||||||
|
|
||||||
|
(defvar seen i64)
|
||||||
|
|
||||||
|
(defn load-all []
|
||||||
|
(signal (AssetMissing {:id 1})) ; Unit — the caller carries on
|
||||||
|
(signal (AssetMissing {:id 2})))
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(load-all) ; no handler: a no-op
|
||||||
|
(print-i64 seen) (newline) ; 0
|
||||||
|
|
||||||
|
;; A handler that returns normally accumulates and lets the signaller run on.
|
||||||
|
(handler-bind [(AssetMissing [c] (set seen (+ seen (i64 (.id c)))))]
|
||||||
|
(load-all))
|
||||||
|
(print-i64 seen) (newline)) ; 3
|
||||||
3
web/examples/conds.out
Normal file
3
web/examples/conds.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
0
|
||||||
|
3
|
||||||
|
exit 0
|
||||||
30
web/examples/control.flan
Normal file
30
web/examples/control.flan
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
(defconst nums [5 i32] [1 3 8 9 10])
|
||||||
|
|
||||||
|
(defn classify [n i32] string
|
||||||
|
(cond
|
||||||
|
(< n 0) "negative"
|
||||||
|
(= n 0) "zero"
|
||||||
|
:else "positive"))
|
||||||
|
|
||||||
|
(defn countdown [n i32]
|
||||||
|
(let [i n]
|
||||||
|
(while (> i 0)
|
||||||
|
(print-i64 (i64 i))
|
||||||
|
(print-str " ")
|
||||||
|
(set i (- i 1)))
|
||||||
|
(newline)))
|
||||||
|
|
||||||
|
(defn first-even [s [i32]] (Option i32)
|
||||||
|
(dotimes [i (len s)]
|
||||||
|
(when (= 0 (% (at s i) 2))
|
||||||
|
(return (Some (at s i)))))
|
||||||
|
None)
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(print-line (classify -3))
|
||||||
|
(countdown 4)
|
||||||
|
(unless false
|
||||||
|
(print-line "unless runs when the test is false"))
|
||||||
|
(match (first-even (slice nums 0 (len nums)))
|
||||||
|
(Some n) (do (print-i64 (i64 n)) (newline))
|
||||||
|
None (print-line "none")))
|
||||||
5
web/examples/control.out
Normal file
5
web/examples/control.out
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
negative
|
||||||
|
4 3 2 1
|
||||||
|
unless runs when the test is false
|
||||||
|
8
|
||||||
|
exit 0
|
||||||
11
web/examples/defer.flan
Normal file
11
web/examples/defer.flan
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
(defn work [n i32] i32
|
||||||
|
(defer (print-line "second"))
|
||||||
|
(defer (print-line "first")) ; innermost-first at exit
|
||||||
|
(when (< n 0)
|
||||||
|
(return 0)) ; runs both defers above it
|
||||||
|
(print-line "body")
|
||||||
|
n)
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(print-i64 (i64 (work 3)))
|
||||||
|
(newline))
|
||||||
5
web/examples/defer.out
Normal file
5
web/examples/defer.out
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
body
|
||||||
|
first
|
||||||
|
second
|
||||||
|
3
|
||||||
|
exit 0
|
||||||
14
web/examples/enums.flan
Normal file
14
web/examples/enums.flan
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
(defenum Key
|
||||||
|
[space 32 escape 256 left 263 right 262])
|
||||||
|
|
||||||
|
(defn key-name [k Key] string
|
||||||
|
(cond
|
||||||
|
(= k :space) "space"
|
||||||
|
(= k :escape) "escape"
|
||||||
|
:else "an arrow"))
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
;; :space resolves against the parameter's enum at compile time.
|
||||||
|
;; A typo is an error here, not a wrong number later.
|
||||||
|
(print-line (key-name :space))
|
||||||
|
(print-line (key-name :left)))
|
||||||
3
web/examples/enums.out
Normal file
3
web/examples/enums.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
space
|
||||||
|
an arrow
|
||||||
|
exit 0
|
||||||
6
web/examples/ffi.flan
Normal file
6
web/examples/ffi.flan
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
;; A plain `declare` names a C symbol in a signature Flan can already spell:
|
||||||
|
;; no aggregate crosses, so no wrapper is generated.
|
||||||
|
(declare cos-f64 [x f64] f64 "cos")
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(print-f64 (cos-f64 0.0)) (newline))
|
||||||
2
web/examples/ffi.out
Normal file
2
web/examples/ffi.out
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
1
|
||||||
|
exit 0
|
||||||
4
web/examples/geom/len.flan
Normal file
4
web/examples/geom/len.flan
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
;; A second file in the same directory shares one top-level scope: it does not
|
||||||
|
;; import vec.flan, and the order of the two files does not matter.
|
||||||
|
(defn length [v V2] f32
|
||||||
|
(sqrt-f32 (+ (* (.x v) (.x v)) (* (.y v) (.y v)))))
|
||||||
5
web/examples/geom/vec.flan
Normal file
5
web/examples/geom/vec.flan
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
;; No package declaration: the name comes from the directory.
|
||||||
|
(defstruct V2 [x f32 y f32])
|
||||||
|
|
||||||
|
(defn add [a V2 b V2] V2
|
||||||
|
(V2 {:x (+ (.x a) (.x b)) :y (+ (.y a) (.y b))}))
|
||||||
2
web/examples/hello.flan
Normal file
2
web/examples/hello.flan
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
(defn main []
|
||||||
|
(print-line "hello from flan"))
|
||||||
2
web/examples/hello.out
Normal file
2
web/examples/hello.out
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
hello from flan
|
||||||
|
exit 0
|
||||||
8
web/examples/numbers.flan
Normal file
8
web/examples/numbers.flan
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
(defn main [] i32
|
||||||
|
(let [n 40 ; i32, inferred
|
||||||
|
big (i64 n) ; every widening is written
|
||||||
|
x 1.5] ; f64
|
||||||
|
(print-i64 (+ big 2)) (newline)
|
||||||
|
(print-f64 (* x 2.5)) (newline)
|
||||||
|
(print-i64 (i64 (bit-xor (<< 1 8) 255))) (newline)
|
||||||
|
0))
|
||||||
4
web/examples/numbers.out
Normal file
4
web/examples/numbers.out
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
42
|
||||||
|
3.75
|
||||||
|
511
|
||||||
|
exit 0
|
||||||
13
web/examples/option.flan
Normal file
13
web/examples/option.flan
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
(defconst nums [4 i32] [4 8 15 16])
|
||||||
|
|
||||||
|
;; `some` unwraps Some and early-returns None from *this* function.
|
||||||
|
(defn doubled-first [s [i32]] (Option i32)
|
||||||
|
(Some (* 2 (some (index-of-i32 s 15)))))
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(match (doubled-first (slice nums 0 4))
|
||||||
|
(Some i) (do (print-i64 (i64 i)) (newline)) ; 4
|
||||||
|
None (print-line "not found"))
|
||||||
|
(match (index-of-i32 (slice nums 0 4) 99)
|
||||||
|
(Some i) (do (print-i64 (i64 i)) (newline))
|
||||||
|
None (print-line "not found")))
|
||||||
3
web/examples/option.out
Normal file
3
web/examples/option.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
4
|
||||||
|
not found
|
||||||
|
exit 0
|
||||||
8
web/examples/pkg.flan
Normal file
8
web/examples/pkg.flan
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
;; The directory is the package. Everything it declares arrives qualified.
|
||||||
|
(import g "geom")
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(let [v (g/add (g/V2 {:x 3.0 :y 0.0})
|
||||||
|
(g/V2 {:x 0.0 :y 4.0}))]
|
||||||
|
(print-f64 (f64 (g/length v)))
|
||||||
|
(newline)))
|
||||||
2
web/examples/pkg.out
Normal file
2
web/examples/pkg.out
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
5
|
||||||
|
exit 0
|
||||||
24
web/examples/restart.flan
Normal file
24
web/examples/restart.flan
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
(defstruct AssetMissing [id i32])
|
||||||
|
|
||||||
|
(defvar cleanups i64)
|
||||||
|
|
||||||
|
(defn load [n i32] i32
|
||||||
|
(signal (AssetMissing {:id n}))
|
||||||
|
100)
|
||||||
|
|
||||||
|
(defn middle [n i32] i32
|
||||||
|
(defer (set cleanups (+ cleanups 1))) ; runs on the transfer too
|
||||||
|
(+ (load n) 1))
|
||||||
|
|
||||||
|
(defn fetch [n i32] i32
|
||||||
|
(restart-case (middle n) ; its value if nothing transfers
|
||||||
|
(use-placeholder [] -1)
|
||||||
|
(retry [] 7)))
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(print-i64 (i64 (fetch 1))) (newline) ; 101 — nothing handled it
|
||||||
|
|
||||||
|
(handler-bind [(AssetMissing [c] (invoke-restart 'use-placeholder))]
|
||||||
|
(print-i64 (i64 (fetch 2))) (newline)) ; -1
|
||||||
|
|
||||||
|
(print-i64 cleanups) (newline)) ; 2 — the defer ran both times
|
||||||
4
web/examples/restart.out
Normal file
4
web/examples/restart.out
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
101
|
||||||
|
-1
|
||||||
|
2
|
||||||
|
exit 0
|
||||||
7
web/examples/shimdemo.flan
Normal file
7
web/examples/shimdemo.flan
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
(defstruct Vector2 [x f32 y f32])
|
||||||
|
|
||||||
|
(declare-c get-mouse-position [] Vector2 "GetMousePosition")
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(print-f64 (f64 (.x (get-mouse-position))))
|
||||||
|
(newline))
|
||||||
17
web/examples/structs.flan
Normal file
17
web/examples/structs.flan
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
(defstruct Cursor
|
||||||
|
[src [u8] ; a non-owning slice
|
||||||
|
pos i32]) ; no initialiser means zeroed
|
||||||
|
|
||||||
|
(defn peek [c (Ptr Cursor)] u8
|
||||||
|
(if (< (.pos c) (len (.src c)))
|
||||||
|
(at (.src c) (.pos c))
|
||||||
|
0))
|
||||||
|
|
||||||
|
(defn advance [c (Ptr Cursor)]
|
||||||
|
(set (.pos c) (+ (.pos c) 1))) ; field access derefs one level
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(let [c (Cursor {:src (bytes "hi")})] ; pos omitted, so pos is 0
|
||||||
|
(print-i64 (i64 (peek (addr c)))) (newline)
|
||||||
|
(advance (addr c))
|
||||||
|
(print-i64 (i64 (peek (addr c)))) (newline)))
|
||||||
3
web/examples/structs.out
Normal file
3
web/examples/structs.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
104
|
||||||
|
105
|
||||||
|
exit 0
|
||||||
Loading…
x
Reference in New Issue
Block a user