From ac4e9ac96e7e424a927862ade77394b458dd5b5a Mon Sep 17 00:00:00 2001 From: giles Date: Tue, 5 May 2026 11:30:11 +0000 Subject: [PATCH] =?UTF-8?q?HS:=20fix=20bare=20repeat=20=E2=80=94=20don't?= =?UTF-8?q?=20consume=20command=20keyword=20as=20count=20expression?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parse-repeat-cmd fallback called parse-expr on the next token, which parse-atom would consume any keyword as (ref val). For bare `repeat` followed by a command like `set`, this ate the `set` token so the loop body started from the wrong position. Fix: only attempt to parse a count expression when the next token is a number, ident, or paren-open — the types that can form a numeric count. Any keyword (set, put, if, end, …) means bare repeat-forever. Fixes "repeat forever works w/o keyword" (+1 test). Co-Authored-By: Claude Sonnet 4.6 --- lib/hyperscript/parser.sx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/hyperscript/parser.sx b/lib/hyperscript/parser.sx index 90bcea51..bdfedb21 100644 --- a/lib/hyperscript/parser.sx +++ b/lib/hyperscript/parser.sx @@ -1891,7 +1891,7 @@ (list (quote for) "it" collection body))))) (true (let - ((mode (cond ((match-kw "forever") (list (quote forever))) ((match-kw "while") (list (quote while) (parse-expr))) ((match-kw "until") (list (quote until) (parse-expr))) (true (let ((n (parse-expr))) (if (match-kw "times") (list (quote times) n) (list (quote forever)))))))) + ((mode (cond ((match-kw "forever") (list (quote forever))) ((match-kw "while") (list (quote while) (parse-expr))) ((match-kw "until") (list (quote until) (parse-expr))) (true (if (or (= (tp-type) "number") (= (tp-type) "ident") (= (tp-type) "paren-open")) (let ((n (parse-expr))) (if (match-kw "times") (list (quote times) n) (list (quote forever)))) (list (quote forever))))))) (let ((body (do (match-kw "then") (parse-cmd-list)))) (cond