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