From 5b31d935bd76c20291df54fbdb385eca1c5be37b Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 23 Apr 2026 17:08:04 +0000 Subject: [PATCH] HS pick runtime: guard nil inputs so pick first/last/items/match/matches don't hang - hs-pick-first/last/random/items/slice: short-circuit nil or non-list (strings flow through unchanged). - New hs-pick-match / hs-pick-matches wrappers around regex-match / regex-find-all, also nil-safe; compiler routes pick-match / pick-matches through them. Unblocks 'pick first from null returns null' and 'pick match from null returns null' which previously looped past step_limit. --- lib/hyperscript/compiler.sx | 4 +- lib/hyperscript/runtime.sx | 60 +++++++++++++++++++++------- shared/static/wasm/sx/hs-compiler.sx | 4 +- shared/static/wasm/sx/hs-runtime.sx | 60 +++++++++++++++++++++------- 4 files changed, 94 insertions(+), 34 deletions(-) diff --git a/lib/hyperscript/compiler.sx b/lib/hyperscript/compiler.sx index 0c41c4a5..4d6d3e35 100644 --- a/lib/hyperscript/compiler.sx +++ b/lib/hyperscript/compiler.sx @@ -818,7 +818,7 @@ (quote set!) (quote it) (list - (quote regex-match) + (quote hs-pick-match) (hs-to-sx (nth ast 1)) (hs-to-sx (nth ast 2))))) ((= head (quote pick-matches)) @@ -826,7 +826,7 @@ (quote set!) (quote it) (list - (quote regex-find-all) + (quote hs-pick-matches) (hs-to-sx (nth ast 1)) (hs-to-sx (nth ast 2))))) ((= head (quote prop-is)) diff --git a/lib/hyperscript/runtime.sx b/lib/hyperscript/runtime.sx index e9b15406..ee577e1b 100644 --- a/lib/hyperscript/runtime.sx +++ b/lib/hyperscript/runtime.sx @@ -1767,37 +1767,67 @@ hs-slice (fn (col start end) - (let - ((s (if (nil? start) 0 start)) - (e (if (nil? end) (len col) (+ end 1)))) - (slice col s e)))) + (cond + ((nil? col) nil) + ((not (list? col)) col) + (true + (let + ((s (if (nil? start) 0 start)) + (e (if (nil? end) (len col) (+ end 1)))) + (slice col s e)))))) (define hs-pick-first (fn (col n) - (let ((m (if (< n (len col)) n (len col)))) (slice col 0 m)))) + (cond + ((nil? col) nil) + ((not (list? col)) col) + (true + (let ((m (if (< n (len col)) n (len col)))) (slice col 0 m)))))) (define hs-pick-last (fn (col n) - (let - ((total (len col))) - (let - ((start (if (< n total) (- total n) 0))) - (slice col start total))))) + (cond + ((nil? col) nil) + ((not (list? col)) col) + (true + (let + ((total (len col))) + (let + ((start (if (< n total) (- total n) 0))) + (slice col start total))))))) (define hs-pick-random (fn (col n) - (if - (nil? n) - (first col) - (let ((m (if (< n (len col)) n (len col)))) (slice col 0 m))))) + (cond + ((nil? col) nil) + ((not (list? col)) col) + ((nil? n) (first col)) + (true + (let ((m (if (< n (len col)) n (len col)))) (slice col 0 m)))))) -(define hs-pick-items (fn (col start end) (slice col start end))) +(define + hs-pick-items + (fn + (col start end) + (cond + ((nil? col) nil) + ((not (list? col)) col) + (true (slice col start end))))) + +(define + hs-pick-match + (fn + (regex haystack) + (cond + ((nil? haystack) nil) + ((nil? regex) nil) + (true (regex-match regex haystack))))) (define hs-sorted-by diff --git a/shared/static/wasm/sx/hs-compiler.sx b/shared/static/wasm/sx/hs-compiler.sx index 0c41c4a5..4d6d3e35 100644 --- a/shared/static/wasm/sx/hs-compiler.sx +++ b/shared/static/wasm/sx/hs-compiler.sx @@ -818,7 +818,7 @@ (quote set!) (quote it) (list - (quote regex-match) + (quote hs-pick-match) (hs-to-sx (nth ast 1)) (hs-to-sx (nth ast 2))))) ((= head (quote pick-matches)) @@ -826,7 +826,7 @@ (quote set!) (quote it) (list - (quote regex-find-all) + (quote hs-pick-matches) (hs-to-sx (nth ast 1)) (hs-to-sx (nth ast 2))))) ((= head (quote prop-is)) diff --git a/shared/static/wasm/sx/hs-runtime.sx b/shared/static/wasm/sx/hs-runtime.sx index e9b15406..ee577e1b 100644 --- a/shared/static/wasm/sx/hs-runtime.sx +++ b/shared/static/wasm/sx/hs-runtime.sx @@ -1767,37 +1767,67 @@ hs-slice (fn (col start end) - (let - ((s (if (nil? start) 0 start)) - (e (if (nil? end) (len col) (+ end 1)))) - (slice col s e)))) + (cond + ((nil? col) nil) + ((not (list? col)) col) + (true + (let + ((s (if (nil? start) 0 start)) + (e (if (nil? end) (len col) (+ end 1)))) + (slice col s e)))))) (define hs-pick-first (fn (col n) - (let ((m (if (< n (len col)) n (len col)))) (slice col 0 m)))) + (cond + ((nil? col) nil) + ((not (list? col)) col) + (true + (let ((m (if (< n (len col)) n (len col)))) (slice col 0 m)))))) (define hs-pick-last (fn (col n) - (let - ((total (len col))) - (let - ((start (if (< n total) (- total n) 0))) - (slice col start total))))) + (cond + ((nil? col) nil) + ((not (list? col)) col) + (true + (let + ((total (len col))) + (let + ((start (if (< n total) (- total n) 0))) + (slice col start total))))))) (define hs-pick-random (fn (col n) - (if - (nil? n) - (first col) - (let ((m (if (< n (len col)) n (len col)))) (slice col 0 m))))) + (cond + ((nil? col) nil) + ((not (list? col)) col) + ((nil? n) (first col)) + (true + (let ((m (if (< n (len col)) n (len col)))) (slice col 0 m)))))) -(define hs-pick-items (fn (col start end) (slice col start end))) +(define + hs-pick-items + (fn + (col start end) + (cond + ((nil? col) nil) + ((not (list? col)) col) + (true (slice col start end))))) + +(define + hs-pick-match + (fn + (regex haystack) + (cond + ((nil? haystack) nil) + ((nil? regex) nil) + (true (regex-match regex haystack))))) (define hs-sorted-by