From fc47489802ec66ceb4f007e248997b25b2e42f6e Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 12 Sep 2026 03:49:41 +0700 Subject: [PATCH] Show the bounds check failing, because "checked" without a message says little The claim worth making is not that there is a check but that a failure names the line, and the only way to show that is to trip one. --- web/examples/bounds.flan | 10 ++++++++++ web/examples/bounds.out | 3 +++ web/index.html | 24 +++++++++++++++++++++--- 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 web/examples/bounds.flan create mode 100644 web/examples/bounds.out diff --git a/web/examples/bounds.flan b/web/examples/bounds.flan new file mode 100644 index 0000000..762b186 --- /dev/null +++ b/web/examples/bounds.flan @@ -0,0 +1,10 @@ +(defconst xs [3 i32] [1 2 3]) + +;; (at xs 7) with a literal index does not reach the backend at all: check.ml +;; rejects it. This one goes through a local, so it is the runtime check that +;; catches it — the same message, and the program stops where it happened. +(defn main [] + (let [i 7] + (print-line "before") + (print-i64 (i64 (at xs i))) + (print-line "unreachable"))) diff --git a/web/examples/bounds.out b/web/examples/bounds.out new file mode 100644 index 0000000..fd24439 --- /dev/null +++ b/web/examples/bounds.out @@ -0,0 +1,3 @@ +before +bounds.flan:9:28: index 7 is out of bounds for length 3 +exit 134 diff --git a/web/index.html b/web/index.html index df57f6a..82a7e9d 100644 --- a/web/index.html +++ b/web/index.html @@ -294,10 +294,28 @@ is why (set (.hp p) 8) above is legal when p is a

Bounds are checked

+
(defconst xs [3 i32] [1 2 3])
+
+;; (at xs 7) with a literal index does not reach the backend at all: check.ml
+;; rejects it. This one goes through a local, so it is the runtime check that
+;; catches it — the same message, and the program stops where it happened.
+(defn main []
+  (let [i 7]
+    (print-line "before")
+    (print-i64 (i64 (at xs i)))
+    (print-line "unreachable")))
+ +
$ flan run bounds.flan
+before
+bounds.flan:9:28: index 7 is out of bounds for length 3
+$ echo $?
+134
+

at and slice emit a comparison and a branch to a cold -block that names the source location and stops. A literal index out of bounds is -rejected at compile time instead. Checks are on by default and are not tied to the -optimisation level; --no-bounds-checks turns them off. Measured cost on a +block that names the source location and stops. Checks are on by default and are not +tied to the optimisation level, which is what lets the acceptance table run the same +programs at -O0 and -O2 with identical checks; +--no-bounds-checks turns them off. Measured cost on a 50-million-iteration dependency chain over a 1024-element array: 0.11–0.12s checked against 0.12–0.13s unchecked.