js-on-sx: callable Number/String/Boolean/Array + Array.sort

Builtin constructors now have :__callable__ slot. js-call-plain
and js-function? detect dicts with __callable__ and dispatch
through it. Number('42')===42, String(true)==='true', Boolean(0)
===false, Array(3) builds length-3 list.

Array.prototype.sort(comparator?): bubble sort via js-list-sort-
outer!/-inner!. Default lex order, custom comparator supported.

Wide scoreboard committed: 259/5354 (4.8%) from earlier runtime.

438/440 unit (+11), 148/148 slice unchanged.
This commit is contained in:
2026-04-23 22:53:13 +00:00
parent d6975d3c79
commit 1459f7a637
5 changed files with 501 additions and 5 deletions

View File

@@ -232,6 +232,8 @@
(cond
((js-undefined? fn-val)
(error "TypeError: undefined is not a function"))
((and (dict? fn-val) (contains? (keys fn-val) "__callable__"))
(js-call-with-this :js-undefined (get fn-val "__callable__") args))
(else (js-call-with-this :js-undefined fn-val args)))))
(define
@@ -396,7 +398,11 @@
(v)
(let
((t (type-of v)))
(or (= t "lambda") (= t "function") (= t "component")))))
(or
(= t "lambda")
(= t "function")
(= t "component")
(and (= t "dict") (contains? (keys v) "__callable__"))))))
;; Bitwise + logical-not
(define __js_proto_table__ (dict))
@@ -835,6 +841,13 @@
(js-num-to-int (nth args 2)))))
(js-list-fill-loop arr v s e)
arr)))
((= name "sort")
(fn
(&rest args)
(let
((cmp (if (= (len args) 0) nil (nth args 0))))
(js-list-sort! arr cmp)
arr)))
(else js-undefined))))
(define pop-last! (fn (lst) nil))
@@ -1009,6 +1022,38 @@
(else
(begin (js-list-set! arr s v) (js-list-fill-loop arr v (+ s 1) e))))))
(define
js-list-sort!
(fn (arr cmp) (let ((n (len arr))) (js-list-sort-outer! arr cmp 0 n))))
(define
js-list-sort-outer!
(fn
(arr cmp i n)
(cond
((>= i n) nil)
(else
(begin
(js-list-sort-inner! arr cmp 0 (- n i 1))
(js-list-sort-outer! arr cmp (+ i 1) n))))))
(define
js-list-sort-inner!
(fn
(arr cmp i end)
(cond
((>= i end) nil)
(else
(begin
(let
((a (nth arr i)) (b (nth arr (+ i 1))))
(let
((result (if (= cmp nil) (if (js-str-lt (js-to-string b) (js-to-string a)) 1 -1) (js-to-number (cmp a b)))))
(when
(> result 0)
(begin (js-list-set! arr i b) (js-list-set! arr (+ i 1) a)))))
(js-list-sort-inner! arr cmp (+ i 1) end))))))
(define
js-list-every-loop
(fn
@@ -1337,6 +1382,7 @@
((= key "reverse") (js-array-method obj "reverse"))
((= key "flat") (js-array-method obj "flat"))
((= key "fill") (js-array-method obj "fill"))
((= key "sort") (js-array-method obj "sort"))
(else js-undefined)))
((= (type-of obj) "string")
(cond
@@ -1566,7 +1612,7 @@
(define js-global-is-nan (fn (v) (js-number-is-nan (js-to-number v))))
(define Number {:isFinite js-number-is-finite :MAX_SAFE_INTEGER 9007199254740991 :EPSILON 2.22045e-16 :MAX_VALUE 0 :POSITIVE_INFINITY inf :isInteger js-number-is-integer :isNaN js-number-is-nan :isSafeInteger js-number-is-safe-integer :NEGATIVE_INFINITY -inf :NaN 0 :MIN_VALUE 4.94066e-324 :MIN_SAFE_INTEGER -9007199254740991})
(define Number {:isFinite js-number-is-finite :MAX_SAFE_INTEGER 9007199254740991 :EPSILON 2.22045e-16 :MAX_VALUE 0 :POSITIVE_INFINITY inf :__callable__ js-to-number :isInteger js-number-is-integer :isNaN js-number-is-nan :isSafeInteger js-number-is-safe-integer :NEGATIVE_INFINITY -inf :NaN 0 :MIN_VALUE 4.94066e-324 :MIN_SAFE_INTEGER -9007199254740991})
(define isFinite js-global-is-finite)
@@ -1815,7 +1861,7 @@
src)
result)))))))
(define Array {:isArray js-array-is-array :of js-array-of :from js-array-from})
(define Array {:__callable__ (fn (&rest args) (cond ((= (len args) 0) (list)) ((and (= (len args) 1) (number? (nth args 0))) (js-make-list-of-length (js-num-to-int (nth args 0)) js-undefined)) (else args))) :isArray js-array-is-array :of js-array-of :from js-array-from})
(define
js-string-from-char-code
@@ -1833,7 +1879,9 @@
(+ i 1)
(str acc (js-code-to-char (js-num-to-int (nth args i))))))))
(define String {:fromCharCode js-string-from-char-code})
(define String {:fromCharCode js-string-from-char-code :__callable__ (fn (&rest args) (if (= (len args) 0) "" (js-to-string (nth args 0))))})
(define Boolean {:__callable__ (fn (&rest args) (if (= (len args) 0) false (js-to-boolean (nth args 0))))})
(define
parseInt
@@ -2508,4 +2556,4 @@
(str "/" (get rx "source") "/" (get rx "flags")))
(else js-undefined))))
(define js-global {:isFinite js-global-is-finite :console console :Number Number :parseFloat parseFloat :Math Math :Array Array :String String :NaN 0 :Infinity inf :isNaN js-global-is-nan :Object Object :parseInt parseInt :JSON JSON :undefined js-undefined})
(define js-global {:isFinite js-global-is-finite :console console :Number Number :parseFloat parseFloat :Math Math :Array Array :Boolean Boolean :String String :NaN 0 :Infinity inf :isNaN js-global-is-nan :Object Object :parseInt parseInt :JSON JSON :undefined js-undefined})