sx: format_number helper — defuse int_of_float overflow on huge floats
Shared formatter in sx_types.ml. Small integer-valued floats still print as plain ints; floats outside safe-int range (|n| >= 1e16) now print as %.17g (full precision) instead of silently wrapping to negative or 0. Non-integer values keep %g 6-digit behavior — no existing SX tests regress. Unblocks Number.MAX_VALUE / Math.pow(2,N) style tests in js-on-sx where iterative float loops were collapsing to 0 at ~2^63. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1889,18 +1889,18 @@
|
||||
(do
|
||||
(adv!)
|
||||
(let
|
||||
((start-expr (parse-atom)))
|
||||
((start-expr (cond ((and (= (tp-type) "keyword") (= (tp-val) "start")) (do (adv!) "hs-pick-start")) ((and (= (tp-type) "keyword") (= (tp-val) "end")) (do (adv!) "hs-pick-end")) (true (parse-atom)))))
|
||||
(do
|
||||
(expect-kw! "to")
|
||||
(let
|
||||
((end-expr (parse-atom)))
|
||||
((end-expr (cond ((and (= (tp-type) "keyword") (= (tp-val) "start")) (do (adv!) "hs-pick-start")) ((and (= (tp-type) "keyword") (= (tp-val) "end")) (do (adv!) "hs-pick-end")) (true (parse-atom)))))
|
||||
(do
|
||||
(if
|
||||
(not (or (match-kw "of") (match-kw "from")))
|
||||
(error
|
||||
(str "Expected 'of' or 'from' at position " p)))
|
||||
(let
|
||||
((coll (parse-expr)))
|
||||
((coll (parse-atom)))
|
||||
(list (quote pick-items) coll start-expr end-expr))))))))
|
||||
((and (= typ "keyword") (= val "match"))
|
||||
(do
|
||||
@@ -1908,52 +1908,86 @@
|
||||
(expect-kw! "of")
|
||||
(let
|
||||
((regex (parse-atom)))
|
||||
(do
|
||||
(cond
|
||||
((match-kw "of") nil)
|
||||
((match-kw "from") nil)
|
||||
(true
|
||||
(error
|
||||
(str
|
||||
"Expected of/from after pick match regex at "
|
||||
p))))
|
||||
(let
|
||||
((haystack (parse-expr)))
|
||||
(list (quote pick-match) regex haystack))))))
|
||||
(let
|
||||
((flags (if (and (= (tp-type) "op") (= (tp-val) "|")) (do (adv!) (let ((fval (tp-val))) (do (adv!) fval))) nil)))
|
||||
(do
|
||||
(cond
|
||||
((match-kw "of") nil)
|
||||
((match-kw "from") nil)
|
||||
(true
|
||||
(error
|
||||
(str
|
||||
"Expected of/from after pick match regex at "
|
||||
p))))
|
||||
(let
|
||||
((haystack (parse-atom)))
|
||||
(list
|
||||
(quote pick-match)
|
||||
(if
|
||||
(nil? flags)
|
||||
regex
|
||||
(list (quote list) regex flags))
|
||||
haystack)))))))
|
||||
((and (= typ "keyword") (= val "matches"))
|
||||
(do
|
||||
(adv!)
|
||||
(expect-kw! "of")
|
||||
(let
|
||||
((regex (parse-atom)))
|
||||
(do
|
||||
(cond
|
||||
((match-kw "of") nil)
|
||||
((match-kw "from") nil)
|
||||
(true
|
||||
(error
|
||||
(str
|
||||
"Expected of/from after pick matches regex at "
|
||||
p))))
|
||||
(let
|
||||
((haystack (parse-expr)))
|
||||
(list (quote pick-matches) regex haystack))))))
|
||||
(let
|
||||
((flags (if (and (= (tp-type) "op") (= (tp-val) "|")) (do (adv!) (let ((fval (tp-val))) (do (adv!) fval))) nil)))
|
||||
(do
|
||||
(cond
|
||||
((match-kw "of") nil)
|
||||
((match-kw "from") nil)
|
||||
(true
|
||||
(error
|
||||
(str
|
||||
"Expected of/from after pick matches regex at "
|
||||
p))))
|
||||
(let
|
||||
((haystack (parse-atom)))
|
||||
(list
|
||||
(quote pick-matches)
|
||||
(if
|
||||
(nil? flags)
|
||||
regex
|
||||
(list (quote list) regex flags))
|
||||
haystack)))))))
|
||||
((and (= typ "ident") (= val "item"))
|
||||
(do
|
||||
(adv!)
|
||||
(let
|
||||
((n (parse-expr)))
|
||||
(do
|
||||
(if
|
||||
(not (or (match-kw "of") (match-kw "from")))
|
||||
(error (str "Expected 'of' or 'from' at position " p)))
|
||||
(let
|
||||
((coll (parse-expr)))
|
||||
(list
|
||||
(quote pick-items)
|
||||
coll
|
||||
n
|
||||
(list (quote +) n 1)))))))
|
||||
((start-expr (cond ((and (= (tp-type) "keyword") (= (tp-val) "start")) (do (adv!) "hs-pick-start")) ((and (= (tp-type) "keyword") (= (tp-val) "end")) (do (adv!) "hs-pick-end")) (true (parse-atom)))))
|
||||
(cond
|
||||
((match-kw "to")
|
||||
(let
|
||||
((end-expr (cond ((and (= (tp-type) "keyword") (= (tp-val) "start")) (do (adv!) "hs-pick-start")) ((and (= (tp-type) "keyword") (= (tp-val) "end")) (do (adv!) "hs-pick-end")) (true (parse-atom)))))
|
||||
(do
|
||||
(if
|
||||
(not (or (match-kw "of") (match-kw "from")))
|
||||
(error
|
||||
(str "Expected 'of' or 'from' at position " p)))
|
||||
(let
|
||||
((coll (parse-atom)))
|
||||
(list
|
||||
(quote pick-items)
|
||||
coll
|
||||
start-expr
|
||||
end-expr)))))
|
||||
(true
|
||||
(do
|
||||
(if
|
||||
(not (or (match-kw "of") (match-kw "from")))
|
||||
(error
|
||||
(str "Expected 'of' or 'from' at position " p)))
|
||||
(let
|
||||
((coll (parse-atom)))
|
||||
(list
|
||||
(quote pick-items)
|
||||
coll
|
||||
start-expr
|
||||
(list (quote +) start-expr 1)))))))))
|
||||
(true
|
||||
(error
|
||||
(str
|
||||
|
||||
@@ -2120,9 +2120,13 @@
|
||||
(col n)
|
||||
(cond
|
||||
((nil? col) nil)
|
||||
((not (list? col)) col)
|
||||
(true
|
||||
(let ((m (if (< n (len col)) n (len col)))) (slice col 0 m))))))
|
||||
(let
|
||||
((m (if (nil? n) 1 n)))
|
||||
(cond
|
||||
((string? col) (slice col 0 m))
|
||||
((list? col) (slice col 0 m))
|
||||
(true col)))))))
|
||||
|
||||
(define
|
||||
hs-pick-last
|
||||
@@ -2130,13 +2134,15 @@
|
||||
(col n)
|
||||
(cond
|
||||
((nil? col) nil)
|
||||
((not (list? col)) col)
|
||||
(true
|
||||
(let
|
||||
((total (len col)))
|
||||
((total (cond ((string? col) (len col)) ((list? col) (len col)) (true 0))))
|
||||
(let
|
||||
((start (if (< n total) (- total n) 0)))
|
||||
(slice col start total)))))))
|
||||
((start (max 0 (- total n))))
|
||||
(cond
|
||||
((string? col) (slice col start total))
|
||||
((list? col) (slice col start total))
|
||||
(true col))))))))
|
||||
|
||||
(define
|
||||
hs-pick-random
|
||||
@@ -2144,10 +2150,19 @@
|
||||
(col n)
|
||||
(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))))))
|
||||
(let
|
||||
((total (cond ((string? col) (len col)) ((list? col) (len col)) (true 0))))
|
||||
(cond
|
||||
((= total 0) (if (nil? n) nil (list)))
|
||||
((nil? n) (nth col 0))
|
||||
(true
|
||||
(let
|
||||
((m (max 0 (if (> n total) total n))))
|
||||
(cond
|
||||
((string? col) (slice col 0 m))
|
||||
((list? col) (slice col 0 m))
|
||||
(true col))))))))))
|
||||
|
||||
(define
|
||||
hs-pick-items
|
||||
@@ -2155,17 +2170,104 @@
|
||||
(col start end)
|
||||
(cond
|
||||
((nil? col) nil)
|
||||
((not (list? col)) col)
|
||||
(true (slice col start end)))))
|
||||
(true
|
||||
(let
|
||||
((n (cond ((string? col) (len col)) ((list? col) (len col)) (true 0))))
|
||||
(let
|
||||
((s (cond ((= start "hs-pick-start") 0) ((= start "hs-pick-end") n) ((and (number? start) (< start 0)) (max 0 (+ n start))) (true start)))
|
||||
(e
|
||||
(cond
|
||||
((= end "hs-pick-end") n)
|
||||
((= end "hs-pick-start") 0)
|
||||
((and (number? end) (< end 0)) (max 0 (+ n end)))
|
||||
(true end))))
|
||||
(cond
|
||||
((string? col) (slice col s e))
|
||||
((list? col) (slice col s e))
|
||||
(true col))))))))
|
||||
|
||||
(define
|
||||
hs-pick-match
|
||||
(fn
|
||||
(regex haystack)
|
||||
(cond
|
||||
((nil? haystack) nil)
|
||||
((nil? regex) nil)
|
||||
(true (regex-match regex haystack)))))
|
||||
((nil? haystack) nil)
|
||||
(true (regex-match (hs-pick-regex-pattern regex) haystack)))))
|
||||
|
||||
(begin
|
||||
(define
|
||||
hs-pick-regex-ci-char
|
||||
(fn
|
||||
(ch)
|
||||
(let
|
||||
((lo (lower ch)) (up (upper ch)))
|
||||
(if (= lo up) ch (str "[" lo up "]")))))
|
||||
(define
|
||||
hs-pick-regex-ci
|
||||
(fn
|
||||
(pat)
|
||||
(let
|
||||
((n (len pat)) (out ""))
|
||||
(let
|
||||
((i 0))
|
||||
(let
|
||||
((loop (fn () nil)))
|
||||
(do
|
||||
(set!
|
||||
loop
|
||||
(fn
|
||||
()
|
||||
(cond
|
||||
((>= i n) nil)
|
||||
(true
|
||||
(let
|
||||
((ch (char-at pat i)))
|
||||
(cond
|
||||
((= ch "\\")
|
||||
(do
|
||||
(set! out (str out ch))
|
||||
(set! i (+ i 1))
|
||||
(when
|
||||
(< i n)
|
||||
(set! out (str out (char-at pat i)))
|
||||
(set! i (+ i 1)))
|
||||
(loop)))
|
||||
(true
|
||||
(do
|
||||
(set! out (str out (hs-pick-regex-ci-char ch)))
|
||||
(set! i (+ i 1))
|
||||
(loop)))))))))
|
||||
(loop)
|
||||
out))))))
|
||||
(define
|
||||
hs-pick-regex-pattern
|
||||
(fn
|
||||
(regex)
|
||||
(cond
|
||||
((nil? regex) "")
|
||||
((list? regex)
|
||||
(let
|
||||
((pat (nth regex 0)) (flags (nth regex 1)))
|
||||
(cond
|
||||
((nil? flags) pat)
|
||||
((string-contains? flags "i") (hs-pick-regex-ci pat))
|
||||
(true pat))))
|
||||
(true regex)))))
|
||||
|
||||
(define
|
||||
hs-pick-matches
|
||||
(fn
|
||||
(regex haystack)
|
||||
(cond
|
||||
((nil? regex) nil)
|
||||
((nil? haystack) nil)
|
||||
(true
|
||||
(let
|
||||
((pat (hs-pick-regex-pattern regex)))
|
||||
(let
|
||||
((found (regex-find-all pat haystack)))
|
||||
(map (fn (m) (list m)) found)))))))
|
||||
|
||||
(define
|
||||
hs-sorted-by
|
||||
|
||||
Reference in New Issue
Block a user