From 6c34d4a66e26dd9aa52f8a7829ae34308ba1b8b2 Mon Sep 17 00:00:00 2001
From: Joseph Ferano
Date: Sat, 12 Sep 2026 03:50:48 +0700
Subject: [PATCH] Quote the compiler's own words for the index rule, and pin
the Emacs keys
The paraphrase of why a wide index is refused was shorter and said less than
the message; and the keybinding table came from NEXT.md, which is two keys
behind flan-mode.el, so it now reads the keymap instead.
---
web/examples/quotes.sh | 31 +++++++++++++++++++++----------
web/index.html | 7 +++++--
2 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/web/examples/quotes.sh b/web/examples/quotes.sh
index a9eaaa8..d7d26a5 100644
--- a/web/examples/quotes.sh
+++ b/web/examples/quotes.sh
@@ -11,14 +11,16 @@ FLAN=${FLAN:-$root/_build/default/bin/main.exe}
page=$here/../index.html
fail=0
-# Look for a literal string in the page, allowing for HTML escaping of < and >.
+# The page is compared with its whitespace collapsed, so that a long compiler
+# message may be wrapped in the HTML and still be recognised as the same text.
+flat=$(sed -e 's/<//g' -e 's/&/\&/g' "$page" | tr '\n' ' ' | tr -s ' ')
+
want() {
- esc=$(printf '%s' "$2" | sed -e 's/&/\&/g' -e 's/\</g' -e 's/>/\>/g')
- if grep -qF -- "$esc" "$page"; then echo "ok $1"; else
- echo "FAIL $1"
- echo " not on the page: $2"
- fail=1
- fi
+ needle=$(printf '%s' "$2" | tr '\n' ' ' | tr -s ' ')
+ case $flat in
+ *"$needle"*) echo "ok $1" ;;
+ *) echo "FAIL $1"; echo " not on the page: $2"; fail=1 ;;
+ esac
}
# The usage text, from the binary itself.
@@ -27,7 +29,8 @@ want "flan usage" "$("$FLAN" 2>&1 | sed -n 2p)"
# calc-me, the first acceptance program, still answers what the page says.
want "calc-me" "$("$FLAN" run "$root/calc-me.flan" '1 + 2 * (3 - 0.5) / 2')"
-# The refusal messages quoted in "Not implemented yet" and under defer.
+# The refusal and diagnostic messages quoted in the prose and in the
+# "Not implemented yet" table.
for pair in \
'vec:(defvar xs (Vec i32))' \
'map:(defvar m (Map string i32))' \
@@ -35,12 +38,13 @@ for pair in \
'handle:(defvar h (Handle i32))' \
'fnty:(defn f [g (Fn [i32] i32)] i32 (g 1))' \
'quoted:(defn f [] i32 (quote a))' \
- 'deferblock:(defn f [] i32 (let [x 1] (defer (print-line "a")) x))'
+ 'deferblock:(defn f [] i32 (let [x 1] (defer (print-line "a")) x))' \
+ 'i64index:(defconst xs [3 i32] [1 2 3]) (defn main [] i32 (let [i (i64 1)] (at xs i)))'
do
name=${pair%%:*}; src=${pair#*:}
printf '%s\n' "$src" > "$here/.q.flan"
msg=$("$FLAN" check "$here/.q.flan" 2>&1 | sed 's/^[^ ]*: //')
- want "refusal: $name" "$msg"
+ want "message: $name" "$msg"
done
rm -f "$here/.q.flan"
@@ -59,4 +63,11 @@ want "agent declare" "$(grep -F 'flan_agent_poll' "$root/vendor/agent/agent.fla
want "conditions.org" "$(grep -F 'Innermost frame offering the name wins' "$root/conditions.org")"
want "renderer" "$(grep -F ':r 17 :g 34 :b 51 :a 68' "$root/NEXT.md")"
+# The Emacs bindings, from the keymap rather than from any prose about it.
+for k in "C-c C-c" "C-c C-k" "C-x C-e" "C-c C-b" "C-c C-v" "C-c C-x"; do
+ grep -qF "(kbd \"$k\")" "$root/emacs/flan-mode.el" || {
+ echo "FAIL keybinding $k is not in flan-mode.el"; fail=1; continue; }
+ want "keybinding $k" "$k"
+done
+
exit $fail
diff --git a/web/index.html b/web/index.html
index 82a7e9d..79b2343 100644
--- a/web/index.html
+++ b/web/index.html
@@ -372,8 +372,11 @@ and logical on an unsigned one.
An index converts from a narrower integer and never from a wider one. A
u32 index is fine — anything above 231 truncates to a negative
i32 and the unsigned bounds check rejects it. An i64 index is
-refused, because 232+5 truncates to 5 and would read the wrong element with
-no trap at all.
+refused, and the message is worth reading because it is the shape of most of them:
+
+an index is an i32, and i64 is wider — write (i32 …), because a value that does
+not fit truncates to one that does and would read the wrong element without
+tripping the bounds check
Structs and enums