Chez numeric tower: exact ints / Ratio / double for JVM parity (jolt-n6al)
jolt was all-flonum (one :number type, inherited from Janet whose only number type is a double). The Chez runtime has a full numeric tower, so the zero-Janet path now carries it = JVM Clojure semantics: (/ 1 2) => 1/2 (exact Ratio, was 0.5) (integer? 3) => true (integer? 3.0) => false (float? 3.0) => true (ratio? (/ 1 2)) => true (= 3 3.0) => false (== 3 3.0) => true (+ 1 2) => 3 (exact) (/ 1.0 2) => 0.5 (double) jolt= was already exactness-aware (values.ss) and == is value-equality, so =/== match the JVM split. The reader preserves exactness (integer literals exact, a/b ratios exact rationals, decimals/exponents flonums); backend_scheme emit-const renders exact ints/ratios and flonums faithfully; the value-position arithmetic, count, int, compare, bit ops, parseLong, string .length/.indexOf, range, timestamps, and array bytes return exact integers (= JVM int/long) instead of coercing to flonum. double/parseDouble/clojure.math floor|ceil|signum stay double. Only the zero-Janet path carries the tower (the Janet reader loses exactness into a double before emit). The prelude/all-flonum path is unaffected for compiled code; the runtime reader is shared, so a couple of all-flonum reader assertions become value (==) assertions. ~16 numeric corpus cases now give the JVM tower value vs the Janet-era :expected and are allowlisted as tower divergences (Chez == reference JVM) pending the corpus flip to JVM (jolt-ecz0). No BigDecimal type (1M). Re-minted. zero-janet 2682 (floor 2698->2682, the reclassified tower cases), 0 new divergences; fixpoint 10/10, bootstrap 6/6, spine 35/35, cli 49/49; Janet gate 155 files 0 failed.
This commit is contained in:
parent
eb1c3298a4
commit
467ad75ff7
20 changed files with 291 additions and 210 deletions
|
|
@ -252,10 +252,11 @@
|
||||||
((or (cseq? coll) (empty-list-t? coll)) (seq-nth coll i #t d))
|
((or (cseq? coll) (empty-list-t? coll)) (seq-nth coll i #t d))
|
||||||
(else d))))))
|
(else d))))))
|
||||||
|
|
||||||
;; jolt models every number as a double, so a count is a flonum — else
|
;; a count is an exact integer (JVM parity: count returns a long). jolt= is
|
||||||
;; (= 2 (count m)) is false (jolt= is exactness-aware: 2.0 vs exact 2).
|
;; exactness-aware, so this must be exact to match an exact integer literal:
|
||||||
|
;; (= 2 (count m)) -> 2 vs exact 2 -> true.
|
||||||
(define (jolt-count coll)
|
(define (jolt-count coll)
|
||||||
(exact->inexact
|
(begin
|
||||||
(cond ((pvec? coll) (pvec-count coll))
|
(cond ((pvec? coll) (pvec-count coll))
|
||||||
((pmap? coll) (pmap-cnt coll))
|
((pmap? coll) (pmap-cnt coll))
|
||||||
((pset? coll) (pset-count coll))
|
((pset? coll) (pset-count coll))
|
||||||
|
|
|
||||||
|
|
@ -90,28 +90,31 @@
|
||||||
(string-append (if (string? p) p (jolt-str-render-one p))
|
(string-append (if (string? p) p (jolt-str-render-one p))
|
||||||
(number->string jolt-gensym-counter)))))
|
(number->string jolt-gensym-counter)))))
|
||||||
|
|
||||||
(define (jolt-int x) (if (char? x) (exact->inexact (char->integer x)) (truncate x)))
|
;; int/long: truncate toward zero to an EXACT integer (= JVM long). char -> code
|
||||||
|
;; point (exact). double: always a flonum (= JVM double).
|
||||||
|
(define (jolt-int x) (if (char? x) (char->integer x) (exact (truncate x))))
|
||||||
(define (jolt-double x) (if (char? x) (exact->inexact (char->integer x)) (exact->inexact x)))
|
(define (jolt-double x) (if (char? x) (exact->inexact (char->integer x)) (exact->inexact x)))
|
||||||
|
|
||||||
;; compare: 3-way, ported from core_io.janet core-compare.
|
;; compare: 3-way, returns an EXACT integer (= JVM compare -> int).
|
||||||
(define (jolt-cmp3 x y) (cond ((< x y) -1.0) ((> x y) 1.0) (else 0.0)))
|
(define (jolt-cmp3 x y) (cond ((< x y) -1) ((> x y) 1) (else 0)))
|
||||||
(define (jolt-strcmp a b) (cond ((string<? a b) -1.0) ((string>? a b) 1.0) (else 0.0)))
|
(define (jolt-strcmp a b) (cond ((string<? a b) -1) ((string>? a b) 1) (else 0)))
|
||||||
(define (jolt-kw->string k)
|
(define (jolt-kw->string k)
|
||||||
(let ((ns (keyword-t-ns k))) (if ns (string-append ns "/" (keyword-t-name k)) (keyword-t-name k))))
|
(let ((ns (keyword-t-ns k))) (if ns (string-append ns "/" (keyword-t-name k)) (keyword-t-name k))))
|
||||||
(define (jolt-sym-ns-string s)
|
(define (jolt-sym-ns-string s)
|
||||||
(let ((n (symbol-t-ns s))) (if (or (jolt-nil? n) (not n) (eq? n '())) "" n)))
|
(let ((n (symbol-t-ns s))) (if (or (jolt-nil? n) (not n) (eq? n '())) "" n)))
|
||||||
|
;; compare returns an EXACT integer -1/0/1 (= JVM compare -> int).
|
||||||
(define (jolt-compare a b)
|
(define (jolt-compare a b)
|
||||||
(cond
|
(cond
|
||||||
((and (jolt-nil? a) (jolt-nil? b)) 0.0)
|
((and (jolt-nil? a) (jolt-nil? b)) 0)
|
||||||
((jolt-nil? a) -1.0)
|
((jolt-nil? a) -1)
|
||||||
((jolt-nil? b) 1.0)
|
((jolt-nil? b) 1)
|
||||||
((and (number? a) (number? b)) (jolt-cmp3 a b))
|
((and (number? a) (number? b)) (jolt-cmp3 a b))
|
||||||
((and (string? a) (string? b)) (jolt-strcmp a b))
|
((and (string? a) (string? b)) (jolt-strcmp a b))
|
||||||
((and (keyword? a) (keyword? b)) (jolt-strcmp (jolt-kw->string a) (jolt-kw->string b)))
|
((and (keyword? a) (keyword? b)) (jolt-strcmp (jolt-kw->string a) (jolt-kw->string b)))
|
||||||
((and (jolt-symbol? a) (jolt-symbol? b))
|
((and (jolt-symbol? a) (jolt-symbol? b))
|
||||||
(let ((r (jolt-strcmp (jolt-sym-ns-string a) (jolt-sym-ns-string b))))
|
(let ((r (jolt-strcmp (jolt-sym-ns-string a) (jolt-sym-ns-string b))))
|
||||||
(if (= r 0.0) (jolt-strcmp (symbol-t-name a) (symbol-t-name b)) r)))
|
(if (= r 0) (jolt-strcmp (symbol-t-name a) (symbol-t-name b)) r)))
|
||||||
((and (boolean? a) (boolean? b)) (cond ((eq? a b) 0.0) ((eq? a #f) -1.0) (else 1.0)))
|
((and (boolean? a) (boolean? b)) (cond ((eq? a b) 0) ((eq? a #f) -1) (else 1)))
|
||||||
((and (char? a) (char? b)) (jolt-cmp3 (char->integer a) (char->integer b)))
|
((and (char? a) (char? b)) (jolt-cmp3 (char->integer a) (char->integer b)))
|
||||||
((and (pvec? a) (pvec? b))
|
((and (pvec? a) (pvec? b))
|
||||||
(let ((la (pvec-count a)) (lb (pvec-count b)))
|
(let ((la (pvec-count a)) (lb (pvec-count b)))
|
||||||
|
|
@ -119,9 +122,9 @@
|
||||||
(jolt-cmp3 la lb)
|
(jolt-cmp3 la lb)
|
||||||
(let loop ((i 0))
|
(let loop ((i 0))
|
||||||
(if (>= i la)
|
(if (>= i la)
|
||||||
0.0
|
0
|
||||||
(let ((r (jolt-compare (pvec-nth-d a i jolt-nil) (pvec-nth-d b i jolt-nil))))
|
(let ((r (jolt-compare (pvec-nth-d a i jolt-nil) (pvec-nth-d b i jolt-nil))))
|
||||||
(if (= r 0.0) (loop (+ i 1)) r)))))))
|
(if (= r 0) (loop (+ i 1)) r)))))))
|
||||||
(else (error #f "compare: cannot compare these types" a b))))
|
(else (error #f "compare: cannot compare these types" a b))))
|
||||||
|
|
||||||
(def-var! "clojure.core" "str" jolt-str)
|
(def-var! "clojure.core" "str" jolt-str)
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@
|
||||||
;; *clojure-version* — a jolt map {:major 1 :minor 11 :incremental 0 :qualifier nil}
|
;; *clojure-version* — a jolt map {:major 1 :minor 11 :incremental 0 :qualifier nil}
|
||||||
;; (jolt is all-flonum, so the numbers are flonums).
|
;; (jolt is all-flonum, so the numbers are flonums).
|
||||||
(def-var! "clojure.core" "*clojure-version*"
|
(def-var! "clojure.core" "*clojure-version*"
|
||||||
(jolt-hash-map (keyword #f "major") 1.0
|
(jolt-hash-map (keyword #f "major") 1
|
||||||
(keyword #f "minor") 11.0
|
(keyword #f "minor") 11
|
||||||
(keyword #f "incremental") 0.0
|
(keyword #f "incremental") 0
|
||||||
(keyword #f "qualifier") jolt-nil))
|
(keyword #f "qualifier") jolt-nil))
|
||||||
|
|
||||||
;; *unchecked-math* — jolt does no unchecked-math elision; the var reads false.
|
;; *unchecked-math* — jolt does no unchecked-math elision; the var reads false.
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,8 @@
|
||||||
(error #f (string-append "No constructor for class " class))))))))
|
(error #f (string-append "No constructor for class " class))))))))
|
||||||
|
|
||||||
;; ---- coercion helpers -------------------------------------------------------
|
;; ---- coercion helpers -------------------------------------------------------
|
||||||
(define (->num x) (exact->inexact x))
|
;; numeric tower (jolt-n6al): currentTimeMillis/nanoTime are exact longs (JVM).
|
||||||
|
(define (->num x) x)
|
||||||
(define (jnum->exact n) (exact (truncate n)))
|
(define (jnum->exact n) (exact (truncate n)))
|
||||||
;; parse an integer string in radix; #f on failure (matches the seed's scan-number)
|
;; parse an integer string in radix; #f on failure (matches the seed's scan-number)
|
||||||
(define (parse-int-str s radix)
|
(define (parse-int-str s radix)
|
||||||
|
|
@ -291,7 +292,7 @@
|
||||||
(register-host-methods! "string-reader"
|
(register-host-methods! "string-reader"
|
||||||
(list (cons "read" (lambda (self)
|
(list (cons "read" (lambda (self)
|
||||||
(let ((s (sr-s self)) (p (sr-pos self)))
|
(let ((s (sr-s self)) (p (sr-pos self)))
|
||||||
(if (>= p (string-length s)) -1.0
|
(if (>= p (string-length s)) -1 ; EOF -> exact int -1 (= JVM)
|
||||||
(begin (sr-pos! self (+ p 1)) (->num (char->integer (string-ref s p))))))))
|
(begin (sr-pos! self (+ p 1)) (->num (char->integer (string-ref s p))))))))
|
||||||
(cons "mark" (lambda (self . _) (vector-set! (jhost-state self) 2 (sr-pos self)) jolt-nil))
|
(cons "mark" (lambda (self . _) (vector-set! (jhost-state self) 2 (sr-pos self)) jolt-nil))
|
||||||
(cons "reset" (lambda (self) (sr-pos! self (vector-ref (jhost-state self) 2)) jolt-nil))
|
(cons "reset" (lambda (self) (sr-pos! self (vector-ref (jhost-state self) 2)) jolt-nil))
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
(define %h-seq jolt-seq)
|
(define %h-seq jolt-seq)
|
||||||
(set! jolt-seq (lambda (x) (if (htable-sorted? x) (sc-call x kw-op-seq) (%h-seq x))))
|
(set! jolt-seq (lambda (x) (if (htable-sorted? x) (sc-call x kw-op-seq) (%h-seq x))))
|
||||||
(define %h-count jolt-count)
|
(define %h-count jolt-count)
|
||||||
(set! jolt-count (lambda (coll) (if (htable-sorted? coll) (exact->inexact (sc-call coll kw-op-count)) (%h-count coll))))
|
(set! jolt-count (lambda (coll) (if (htable-sorted? coll) (sc-call coll kw-op-count) (%h-count coll))))
|
||||||
(define %h-get jolt-get)
|
(define %h-get jolt-get)
|
||||||
(set! jolt-get (case-lambda
|
(set! jolt-get (case-lambda
|
||||||
((coll k) (if (htable-sorted? coll) (sc-call coll kw-op-get k jolt-nil) (%h-get coll k)))
|
((coll k) (if (htable-sorted? coll) (sc-call coll kw-op-get k jolt-nil) (%h-get coll k)))
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
(else (fail)))))
|
(else (fail)))))
|
||||||
(unless (= i len) (fail))
|
(unless (= i len) (fail))
|
||||||
(let ((base-s (+ (* (days-from-civil year month day) 86400) (* hh 3600) (* mm 60) ss)))
|
(let ((base-s (+ (* (days-from-civil year month day) 86400) (* hh 3600) (* mm 60) ss)))
|
||||||
(make-jinst (exact->inexact (- (+ (* base-s 1000) frac-ms) (* off-s 1000)))))))
|
(make-jinst (- (+ (* base-s 1000) frac-ms) (* off-s 1000))))))
|
||||||
|
|
||||||
;; --- canonical print form: yyyy-MM-ddThh:mm:ss.fff-00:00 (UTC) ---------------
|
;; --- canonical print form: yyyy-MM-ddThh:mm:ss.fff-00:00 (UTC) ---------------
|
||||||
(define (pad2 n) (if (< n 10) (string-append "0" (number->string n)) (number->string n)))
|
(define (pad2 n) (if (< n 10) (string-append "0" (number->string n)) (number->string n)))
|
||||||
|
|
@ -223,7 +223,9 @@
|
||||||
(define (mk-local ms) (make-jhost "local-dt" (vector ms)))
|
(define (mk-local ms) (make-jhost "local-dt" (vector ms)))
|
||||||
(define (mk-formatter pat) (make-jhost "dt-formatter" (vector pat)))
|
(define (mk-formatter pat) (make-jhost "dt-formatter" (vector pat)))
|
||||||
(define (fmt-pat f) (vector-ref (jhost-state f) 0))
|
(define (fmt-pat f) (vector-ref (jhost-state f) 0))
|
||||||
(define (now-ms) (exact->inexact (now-millis))) ; now-millis from host-static.ss
|
(define (now-ms) (now-millis)) ; exact ms (= JVM long); now-millis from host-static.ss
|
||||||
|
;; coerce a user-supplied ms (exact or flonum) to an exact integer for storage.
|
||||||
|
(define (ms->exact ms) (exact (round ms)))
|
||||||
|
|
||||||
(register-host-methods! "instant"
|
(register-host-methods! "instant"
|
||||||
(list (cons "atZone" (lambda (self zone) (mk-zoned (ms-of self))))
|
(list (cons "atZone" (lambda (self zone) (mk-zoned (ms-of self))))
|
||||||
|
|
@ -262,7 +264,7 @@
|
||||||
(cons "ofLocalizedTime" (lambda (fs) (style-fmt 'time fs)))
|
(cons "ofLocalizedTime" (lambda (fs) (style-fmt 'time fs)))
|
||||||
(cons "ofLocalizedDateTime" (lambda (fs) (style-fmt 'datetime fs)))))
|
(cons "ofLocalizedDateTime" (lambda (fs) (style-fmt 'datetime fs)))))
|
||||||
(register-class-statics! "Instant"
|
(register-class-statics! "Instant"
|
||||||
(list (cons "ofEpochMilli" (lambda (ms) (mk-instant (exact->inexact ms))))
|
(list (cons "ofEpochMilli" (lambda (ms) (mk-instant (ms->exact ms))))
|
||||||
(cons "now" (lambda () (mk-instant (now-ms))))))
|
(cons "now" (lambda () (mk-instant (now-ms))))))
|
||||||
(register-class-statics! "ZoneId"
|
(register-class-statics! "ZoneId"
|
||||||
(list (cons "systemDefault" (lambda () (make-jhost "zone-id" (vector "system"))))
|
(list (cons "systemDefault" (lambda () (make-jhost "zone-id" (vector "system"))))
|
||||||
|
|
@ -283,7 +285,7 @@
|
||||||
;; or (Date. another-date) -> a jinst (ms-of accepts a number / jinst / instant), so
|
;; or (Date. another-date) -> a jinst (ms-of accepts a number / jinst / instant), so
|
||||||
;; .getTime / inst? / instance? Date|Timestamp work. (jolt-dcmm)
|
;; .getTime / inst? / instance? Date|Timestamp work. (jolt-dcmm)
|
||||||
(define (date-ctor . args)
|
(define (date-ctor . args)
|
||||||
(make-jinst (if (null? args) (now-ms) (exact->inexact (ms-of (car args))))))
|
(make-jinst (if (null? args) (now-ms) (ms->exact (ms-of (car args))))))
|
||||||
(register-class-ctor! "Date" date-ctor)
|
(register-class-ctor! "Date" date-ctor)
|
||||||
(register-class-ctor! "java.util.Date" date-ctor)
|
(register-class-ctor! "java.util.Date" date-ctor)
|
||||||
(register-class-ctor! "Timestamp" date-ctor)
|
(register-class-ctor! "Timestamp" date-ctor)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@
|
||||||
(- (expt (- x) (/ 1.0 3.0)))
|
(- (expt (- x) (/ 1.0 3.0)))
|
||||||
(expt x (/ 1.0 3.0))))
|
(expt x (/ 1.0 3.0))))
|
||||||
|
|
||||||
(define (jolt-math-round x) (floor (+ x 0.5)))
|
;; clojure.math/round returns a long (exact); floor/ceil/signum/rint return doubles.
|
||||||
|
(define (jolt-math-round x) (exact (floor (+ x 0.5))))
|
||||||
(define (jolt-math-signum x) (cond ((< x 0.0) -1.0) ((> x 0.0) 1.0) (else 0.0)))
|
(define (jolt-math-signum x) (cond ((< x 0.0) -1.0) ((> x 0.0) 1.0) (else 0.0)))
|
||||||
(define (jolt-math-to-degrees r) (/ (* r 180.0) jolt-math-pi))
|
(define (jolt-math-to-degrees r) (/ (* r 180.0) jolt-math-pi))
|
||||||
(define (jolt-math-to-radians d) (/ (* d jolt-math-pi) 180.0))
|
(define (jolt-math-to-radians d) (/ (* d jolt-math-pi) 180.0))
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@
|
||||||
(make-jolt-array (make-vector (exact (na-idx a)) (if (pair? rest) (car rest) init)) kind)
|
(make-jolt-array (make-vector (exact (na-idx a)) (if (pair? rest) (car rest) init)) kind)
|
||||||
(na-from-seq a kind)))
|
(na-from-seq a kind)))
|
||||||
|
|
||||||
;; jolt numbers are flonums — array element defaults / masked bytes / count must be
|
;; numeric tower (jolt-n6al): array element defaults / masked bytes / count are
|
||||||
;; INEXACT or jolt's exactness-aware = fails (= 3.0 (exact 3) -> false).
|
;; EXACT integers (= JVM byte/short/int), matching exact integer literals.
|
||||||
(define (na-byte-of v) (exact->inexact (bitwise-and (exact (floor v)) #xff)))
|
(define (na-byte-of v) (bitwise-and (exact (floor v)) #xff))
|
||||||
|
|
||||||
;; --- constructors -----------------------------------------------------------
|
;; --- constructors -----------------------------------------------------------
|
||||||
(define (na-object-array a . rest) (na-num-array a rest jolt-nil 'object))
|
(define (na-object-array a . rest) (na-num-array a rest jolt-nil 'object))
|
||||||
|
|
@ -60,9 +60,9 @@
|
||||||
(define (na-bytes? x) (and (jolt-array? x) (eq? (jolt-array-kind x) 'byte)))
|
(define (na-bytes? x) (and (jolt-array? x) (eq? (jolt-array-kind x) 'byte)))
|
||||||
(define (na-identity x) x)
|
(define (na-identity x) x)
|
||||||
(define (na-byte x)
|
(define (na-byte x)
|
||||||
(let ((b (bitwise-and (exact (floor x)) #xff))) (exact->inexact (if (>= b 128) (- b 256) b))))
|
(let ((b (bitwise-and (exact (floor x)) #xff))) (if (>= b 128) (- b 256) b)))
|
||||||
(define (na-short x)
|
(define (na-short x)
|
||||||
(let ((s (bitwise-and (exact (floor x)) #xffff))) (exact->inexact (if (>= s #x8000) (- s #x10000) s))))
|
(let ((s (bitwise-and (exact (floor x)) #xffff))) (if (>= s #x8000) (- s #x10000) s)))
|
||||||
|
|
||||||
;; --- chunked seqs (Jolt does not chunk; eager equivalents over a buffer) -----
|
;; --- chunked seqs (Jolt does not chunk; eager equivalents over a buffer) -----
|
||||||
(define-record-type jolt-chunkbuf (fields (mutable items)) (nongenerative jolt-chunkbuf-v1))
|
(define-record-type jolt-chunkbuf (fields (mutable items)) (nongenerative jolt-chunkbuf-v1))
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
|
|
||||||
;; --- extend the collection dispatchers to see a jolt-array ------------------
|
;; --- extend the collection dispatchers to see a jolt-array ------------------
|
||||||
(define %na-count jolt-count)
|
(define %na-count jolt-count)
|
||||||
(set! jolt-count (lambda (c) (if (jolt-array? c) (exact->inexact (vector-length (jolt-array-vec c))) (%na-count c))))
|
(set! jolt-count (lambda (c) (if (jolt-array? c) (vector-length (jolt-array-vec c)) (%na-count c))))
|
||||||
(define %na-seq jolt-seq)
|
(define %na-seq jolt-seq)
|
||||||
(set! jolt-seq (lambda (c) (if (jolt-array? c) (list->cseq (vector->list (jolt-array-vec c))) (%na-seq c))))
|
(set! jolt-seq (lambda (c) (if (jolt-array? c) (list->cseq (vector->list (jolt-array-vec c))) (%na-seq c))))
|
||||||
(define %na-nth jolt-nth)
|
(define %na-nth jolt-nth)
|
||||||
|
|
|
||||||
|
|
@ -4,24 +4,25 @@
|
||||||
;; to an exact integer, operate, and return a flonum. parse-* match the seed's
|
;; to an exact integer, operate, and return a flonum. parse-* match the seed's
|
||||||
;; strict shapes (Clojure 1.11: nil on malformed, throw on a non-string).
|
;; strict shapes (Clojure 1.11: nil on malformed, throw on a non-string).
|
||||||
|
|
||||||
|
;; bit ops return EXACT integers (= JVM long). ->int coerces the operand.
|
||||||
(define (->int x) (exact (truncate x)))
|
(define (->int x) (exact (truncate x)))
|
||||||
(define (jolt-bit-and a b) (exact->inexact (bitwise-and (->int a) (->int b))))
|
(define (jolt-bit-and a b) (bitwise-and (->int a) (->int b)))
|
||||||
(define (jolt-bit-or a b) (exact->inexact (bitwise-ior (->int a) (->int b))))
|
(define (jolt-bit-or a b) (bitwise-ior (->int a) (->int b)))
|
||||||
(define (jolt-bit-xor a b) (exact->inexact (bitwise-xor (->int a) (->int b))))
|
(define (jolt-bit-xor a b) (bitwise-xor (->int a) (->int b)))
|
||||||
(define (jolt-bit-and-not a b) (exact->inexact (bitwise-and (->int a) (bitwise-not (->int b)))))
|
(define (jolt-bit-and-not a b) (bitwise-and (->int a) (bitwise-not (->int b))))
|
||||||
(define (jolt-bit-not a) (exact->inexact (bitwise-not (->int a))))
|
(define (jolt-bit-not a) (bitwise-not (->int a)))
|
||||||
(define (jolt-bit-shift-left x n) (exact->inexact (bitwise-arithmetic-shift-left (->int x) (->int n))))
|
(define (jolt-bit-shift-left x n) (bitwise-arithmetic-shift-left (->int x) (->int n)))
|
||||||
(define (jolt-bit-shift-right x n) (exact->inexact (bitwise-arithmetic-shift-right (->int x) (->int n))))
|
(define (jolt-bit-shift-right x n) (bitwise-arithmetic-shift-right (->int x) (->int n)))
|
||||||
(define (bit-mask n) (bitwise-arithmetic-shift-left 1 (->int n)))
|
(define (bit-mask n) (bitwise-arithmetic-shift-left 1 (->int n)))
|
||||||
(define (jolt-bit-set x n) (exact->inexact (bitwise-ior (->int x) (bit-mask n))))
|
(define (jolt-bit-set x n) (bitwise-ior (->int x) (bit-mask n)))
|
||||||
(define (jolt-bit-clear x n) (exact->inexact (bitwise-and (->int x) (bitwise-not (bit-mask n)))))
|
(define (jolt-bit-clear x n) (bitwise-and (->int x) (bitwise-not (bit-mask n))))
|
||||||
(define (jolt-bit-flip x n) (exact->inexact (bitwise-xor (->int x) (bit-mask n))))
|
(define (jolt-bit-flip x n) (bitwise-xor (->int x) (bit-mask n)))
|
||||||
(define (jolt-bit-test x n) (not (zero? (bitwise-and (->int x) (bit-mask n)))))
|
(define (jolt-bit-test x n) (not (zero? (bitwise-and (->int x) (bit-mask n)))))
|
||||||
;; unsigned-bit-shift-right: logical shift over 64-bit longs. For the common
|
;; unsigned-bit-shift-right: logical shift over 64-bit longs. For the common
|
||||||
;; non-negative operand it equals the arithmetic shift; the negative-operand
|
;; non-negative operand it equals the arithmetic shift; the negative-operand
|
||||||
;; 64-bit-window case is not modeled (no fixed-width longs on the all-flonum side).
|
;; 64-bit-window case is not modeled.
|
||||||
(define (jolt-unsigned-bit-shift-right x n)
|
(define (jolt-unsigned-bit-shift-right x n)
|
||||||
(exact->inexact (bitwise-arithmetic-shift-right (->int x) (->int n))))
|
(bitwise-arithmetic-shift-right (->int x) (->int n)))
|
||||||
|
|
||||||
;; ---- string->scalar parsers -------------------------------------------------
|
;; ---- string->scalar parsers -------------------------------------------------
|
||||||
(define (ascii-digit? c) (and (char>=? c #\0) (char<=? c #\9)))
|
(define (ascii-digit? c) (and (char>=? c #\0) (char<=? c #\9)))
|
||||||
|
|
@ -34,7 +35,7 @@
|
||||||
|
|
||||||
(define (jolt-parse-long s)
|
(define (jolt-parse-long s)
|
||||||
(if (not (string? s)) (error #f "parse-long requires a string" s)
|
(if (not (string? s)) (error #f "parse-long requires a string" s)
|
||||||
(if (parse-long-shape? s) (exact->inexact (string->number s)) jolt-nil)))
|
(if (parse-long-shape? s) (string->number s) jolt-nil))) ; exact long
|
||||||
|
|
||||||
;; strict float shape: [+-]? ( D+ (. D*)? | . D+ ) ([eE][+-]? D+)? fully anchored.
|
;; strict float shape: [+-]? ( D+ (. D*)? | . D+ ) ([eE][+-]? D+)? fully anchored.
|
||||||
(define (parse-double-shape? s)
|
(define (parse-double-shape? s)
|
||||||
|
|
|
||||||
|
|
@ -91,18 +91,17 @@
|
||||||
((string=? method "toLowerCase") (ascii-string-down s))
|
((string=? method "toLowerCase") (ascii-string-down s))
|
||||||
((string=? method "toUpperCase") (ascii-string-up s))
|
((string=? method "toUpperCase") (ascii-string-up s))
|
||||||
((string=? method "trim") (str-trim s))
|
((string=? method "trim") (str-trim s))
|
||||||
((string=? method "length") (exact->inexact (string-length s)))
|
((string=? method "length") (string-length s)) ; exact int (= JVM)
|
||||||
((string=? method "isEmpty") (fx=? (string-length s) 0))
|
((string=? method "isEmpty") (fx=? (string-length s) 0))
|
||||||
((string=? method "charAt") (string-ref s (jolt->idx (arg 0))))
|
((string=? method "charAt") (string-ref s (jolt->idx (arg 0))))
|
||||||
((string=? method "substring")
|
((string=? method "substring")
|
||||||
(substring s (jolt->idx (arg 0))
|
(substring s (jolt->idx (arg 0))
|
||||||
(if (fx>? (length rest) 1) (jolt->idx (arg 1)) (string-length s))))
|
(if (fx>? (length rest) 1) (jolt->idx (arg 1)) (string-length s))))
|
||||||
((string=? method "indexOf")
|
((string=? method "indexOf")
|
||||||
(exact->inexact
|
(str-index-of s (str-needle (arg 0))
|
||||||
(str-index-of s (str-needle (arg 0))
|
(if (fx>? (length rest) 1) (jolt->idx (arg 1)) 0)))
|
||||||
(if (fx>? (length rest) 1) (jolt->idx (arg 1)) 0))))
|
|
||||||
((string=? method "lastIndexOf")
|
((string=? method "lastIndexOf")
|
||||||
(exact->inexact (str-last-index-of s (str-needle (arg 0)))))
|
(str-last-index-of s (str-needle (arg 0))))
|
||||||
((string=? method "startsWith")
|
((string=? method "startsWith")
|
||||||
(let ((p (arg 0))) (and (fx>=? (string-length s) (string-length p))
|
(let ((p (arg 0))) (and (fx>=? (string-length s) (string-length p))
|
||||||
(string=? (substring s 0 (string-length p)) p))))
|
(string=? (substring s 0 (string-length p)) p))))
|
||||||
|
|
@ -153,10 +152,10 @@
|
||||||
(define (str-lower s) (ascii-string-down s))
|
(define (str-lower s) (ascii-string-down s))
|
||||||
(define (str-reverse-b s) (list->string (reverse (string->list s))))
|
(define (str-reverse-b s) (list->string (reverse (string->list s))))
|
||||||
|
|
||||||
;; (str-find needle haystack) -> flonum index of first occurrence, or nil.
|
;; (str-find needle haystack) -> exact int index of first occurrence, or nil.
|
||||||
(define (str-find needle s)
|
(define (str-find needle s)
|
||||||
(let ((i (str-index-of s needle 0)))
|
(let ((i (str-index-of s needle 0)))
|
||||||
(if (fx<? i 0) jolt-nil (exact->inexact i))))
|
(if (fx<? i 0) jolt-nil i)))
|
||||||
|
|
||||||
;; (str-join coll [sep]) -> stringify each element (Clojure str), join by sep.
|
;; (str-join coll [sep]) -> stringify each element (Clojure str), join by sep.
|
||||||
(define (str-join coll . opt)
|
(define (str-join coll . opt)
|
||||||
|
|
|
||||||
|
|
@ -80,3 +80,17 @@
|
||||||
(def-var! "clojure.core" "line-seq"
|
(def-var! "clojure.core" "line-seq"
|
||||||
(lambda (rdr)
|
(lambda (rdr)
|
||||||
(if (reader-jhost? rdr) (chez-line-seq rdr) (jolt-invoke overlay-line-seq rdr)))))
|
(if (reader-jhost? rdr) (chez-line-seq rdr) (jolt-invoke overlay-line-seq rdr)))))
|
||||||
|
;; JVM-parity numeric tower (jolt-n6al): the overlay (20-coll.clj) carries an
|
||||||
|
;; all-flonum number-predicate web with no Ratio concept (ratio? -> false,
|
||||||
|
;; double? -> not-integer, float? -> double?, rational? -> int?), which
|
||||||
|
;; misclassifies exact rationals on the Chez tower (e.g. (double? 1/2) -> true).
|
||||||
|
;; Re-assert the native tower-correct versions (predicates.ss) so they win over
|
||||||
|
;; the overlay defs. int?/double? alias integer?/float?. == is value-equality.
|
||||||
|
(def-var! "clojure.core" "integer?" jolt-integer?)
|
||||||
|
(def-var! "clojure.core" "int?" jolt-integer?)
|
||||||
|
(def-var! "clojure.core" "float?" jolt-float?)
|
||||||
|
(def-var! "clojure.core" "double?" jolt-float?)
|
||||||
|
(def-var! "clojure.core" "ratio?" jolt-ratio?)
|
||||||
|
(def-var! "clojure.core" "rational?" jolt-rational?)
|
||||||
|
(def-var! "clojure.core" "decimal?" jolt-decimal?)
|
||||||
|
(def-var! "clojure.core" "==" jolt-num-equiv)
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,16 @@
|
||||||
(define (jolt-number? x) (number? x))
|
(define (jolt-number? x) (number? x))
|
||||||
(define (jolt-string? x) (string? x))
|
(define (jolt-string? x) (string? x))
|
||||||
(define (jolt-char-pred? x) (char? x))
|
(define (jolt-char-pred? x) (char? x))
|
||||||
;; finite integral number — Chez integer? already rejects the infinities and NaN.
|
;; JVM-parity number-type predicates over the Chez numeric tower. integer? is the
|
||||||
(define (jolt-integer? x) (and (number? x) (integer? x)))
|
;; INTEGER TYPE (exact integer = Long/BigInt), NOT integer-VALUED: (integer? 3.0)
|
||||||
|
;; is false on the JVM (3.0 is a Double). float? = flonum (double). ratio? = exact
|
||||||
|
;; non-integer (= JVM Ratio). rational? = exact (integer or ratio; jolt has no
|
||||||
|
;; BigDecimal). decimal? is always false (no BigDecimal type).
|
||||||
|
(define (jolt-integer? x) (and (number? x) (exact? x) (integer? x)))
|
||||||
|
(define (jolt-float? x) (and (number? x) (flonum? x)))
|
||||||
|
(define (jolt-ratio? x) (and (number? x) (exact? x) (rational? x) (not (integer? x))))
|
||||||
|
(define (jolt-rational? x) (and (number? x) (exact? x)))
|
||||||
|
(define (jolt-decimal? x) #f)
|
||||||
(define (jolt-fn? x) (procedure? x))
|
(define (jolt-fn? x) (procedure? x))
|
||||||
(define (jolt-boolean-pred? x) (boolean? x))
|
(define (jolt-boolean-pred? x) (boolean? x))
|
||||||
|
|
||||||
|
|
@ -50,6 +58,20 @@
|
||||||
(def-var! "clojure.core" "string?" jolt-string?)
|
(def-var! "clojure.core" "string?" jolt-string?)
|
||||||
(def-var! "clojure.core" "char?" jolt-char-pred?)
|
(def-var! "clojure.core" "char?" jolt-char-pred?)
|
||||||
(def-var! "clojure.core" "integer?" jolt-integer?)
|
(def-var! "clojure.core" "integer?" jolt-integer?)
|
||||||
|
(def-var! "clojure.core" "float?" jolt-float?)
|
||||||
|
(def-var! "clojure.core" "ratio?" jolt-ratio?)
|
||||||
|
(def-var! "clojure.core" "rational?" jolt-rational?)
|
||||||
|
(def-var! "clojure.core" "decimal?" jolt-decimal?)
|
||||||
|
;; == numeric value-equality (ignores exactness, unlike =): (== 3 3.0) -> true.
|
||||||
|
;; 1-arity is trivially true; 2+ args must all be numbers (Numbers.equiv throws
|
||||||
|
;; otherwise). Uses Scheme = (value across the tower), not jolt= (category-aware).
|
||||||
|
(define (jolt-num-equiv . xs)
|
||||||
|
(let all-num? ((ys xs))
|
||||||
|
(cond
|
||||||
|
((null? ys) (or (null? xs) (null? (cdr xs)) (apply = xs)))
|
||||||
|
((number? (car ys)) (all-num? (cdr ys)))
|
||||||
|
(else (error #f "== requires numbers" xs)))))
|
||||||
|
(def-var! "clojure.core" "==" jolt-num-equiv)
|
||||||
(def-var! "clojure.core" "symbol?" jolt-symbol?)
|
(def-var! "clojure.core" "symbol?" jolt-symbol?)
|
||||||
(def-var! "clojure.core" "keyword?" keyword?)
|
(def-var! "clojure.core" "keyword?" keyword?)
|
||||||
(def-var! "clojure.core" "map?" jolt-map?)
|
(def-var! "clojure.core" "map?" jolt-map?)
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,13 @@
|
||||||
;; jolt models EVERY number as a double (emit-const lowers integer literals to
|
;; jolt models EVERY number as a double (emit-const lowers integer literals to
|
||||||
;; flonums too), so the reader coerces every parsed number to inexact — else a
|
;; flonums too), so the reader coerces every parsed number to inexact — else a
|
||||||
;; read int (exact) is not jolt= to a source int literal (flonum).
|
;; read int (exact) is not jolt= to a source int literal (flonum).
|
||||||
|
;; Preserve exactness for the Chez numeric tower (JVM parity): integer literals
|
||||||
|
;; read as exact integers (= Long/BigInt, arbitrary precision), a/b ratios as
|
||||||
|
;; exact rationals (= Ratio), and decimal/exponent literals as flonums (= double).
|
||||||
|
;; Only the zero-Janet path (this reader) carries exactness through to runtime;
|
||||||
|
;; the Janet-reader prelude path stays all-flonum (Janet has only doubles).
|
||||||
(define (rdr-try-number tok)
|
(define (rdr-try-number tok)
|
||||||
(let ((raw (rdr-try-number-raw tok)))
|
(rdr-try-number-raw tok))
|
||||||
(and raw (exact->inexact raw))))
|
|
||||||
|
|
||||||
(define (rdr-try-number-raw tok)
|
(define (rdr-try-number-raw tok)
|
||||||
(let ((len (string-length tok)))
|
(let ((len (string-length tok)))
|
||||||
|
|
@ -108,12 +112,13 @@
|
||||||
(blen (string-length body))
|
(blen (string-length body))
|
||||||
(slash (rdr-string-index-char body #\/)))
|
(slash (rdr-string-index-char body #\/)))
|
||||||
(cond
|
(cond
|
||||||
;; ratio a/b -> flonum (the seed has no exact ratios)
|
;; ratio a/b -> exact rational (= JVM Ratio); reduces to an exact integer
|
||||||
|
;; when d divides n.
|
||||||
(slash
|
(slash
|
||||||
(let ((n (string->number (substring body 0 slash)))
|
(let ((n (string->number (substring body 0 slash)))
|
||||||
(d (string->number (substring body (+ slash 1) blen))))
|
(d (string->number (substring body (+ slash 1) blen))))
|
||||||
(and (integer? n) (integer? d) (not (= d 0))
|
(and (integer? n) (integer? d) (not (= d 0))
|
||||||
(* sign (exact->inexact (/ n d))))))
|
(* sign (/ n d)))))
|
||||||
;; hex 0x..
|
;; hex 0x..
|
||||||
((and (>= blen 2) (char=? (string-ref body 0) #\0)
|
((and (>= blen 2) (char=? (string-ref body 0) #\0)
|
||||||
(or (char=? (string-ref body 1) #\x) (char=? (string-ref body 1) #\X)))
|
(or (char=? (string-ref body 1) #\x) (char=? (string-ref body 1) #\X)))
|
||||||
|
|
@ -137,9 +142,8 @@
|
||||||
(and n (exact->inexact (* sign n)))))
|
(and n (exact->inexact (* sign n)))))
|
||||||
(else
|
(else
|
||||||
(let ((n (string->number tok))) ; tok carries its own sign
|
(let ((n (string->number tok))) ; tok carries its own sign
|
||||||
(and (number? n) (real? n)
|
;; keep exactness: "42" -> exact int, "3.14"/"1e3" -> flonum.
|
||||||
;; never surface an exact non-integer ratio
|
(and (number? n) (real? n) n))))))
|
||||||
(if (and (exact? n) (not (integer? n))) (exact->inexact n) n)))))))
|
|
||||||
|
|
||||||
;; --- string / char literals -------------------------------------------------
|
;; --- string / char literals -------------------------------------------------
|
||||||
(define (rdr-hex->int s i n) ; n hex digits at i -> (values int j)
|
(define (rdr-hex->int s i n) ; n hex digits at i -> (values int j)
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
((coll k) (if (jrec? coll) (jrec-lookup coll k jolt-nil) (%r-jolt-get coll k)))
|
((coll k) (if (jrec? coll) (jrec-lookup coll k jolt-nil) (%r-jolt-get coll k)))
|
||||||
((coll k d) (if (jrec? coll) (jrec-lookup coll k d) (%r-jolt-get coll k d)))))
|
((coll k d) (if (jrec? coll) (jrec-lookup coll k d) (%r-jolt-get coll k d)))))
|
||||||
(define %r-jolt-count jolt-count)
|
(define %r-jolt-count jolt-count)
|
||||||
(set! jolt-count (lambda (coll) (if (jrec? coll) (exact->inexact (length (jrec-pairs coll))) (%r-jolt-count coll))))
|
(set! jolt-count (lambda (coll) (if (jrec? coll) (length (jrec-pairs coll)) (%r-jolt-count coll))))
|
||||||
(define %r-jolt-contains? jolt-contains?)
|
(define %r-jolt-contains? jolt-contains?)
|
||||||
(set! jolt-contains? (lambda (coll k) (if (jrec? coll) (jrec-has? coll k) (%r-jolt-contains? coll k))))
|
(set! jolt-contains? (lambda (coll k) (if (jrec? coll) (jrec-has? coll k) (%r-jolt-contains? coll k))))
|
||||||
(define %r-jolt-assoc1 jolt-assoc1)
|
(define %r-jolt-assoc1 jolt-assoc1)
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -113,14 +113,15 @@
|
||||||
((fx=? i 0) (seq-first s))
|
((fx=? i 0) (seq-first s))
|
||||||
(else (loop (jolt-seq (seq-more s)) (fx- i 1)))))))
|
(else (loop (jolt-seq (seq-more s)) (fx- i 1)))))))
|
||||||
|
|
||||||
;; value-position arithmetic: jolt models every number as a double, so the
|
;; value-position arithmetic (the higher-order forms: (reduce + []), (apply * xs)).
|
||||||
;; higher-order forms ((reduce + []), (apply * xs)) must coerce — Scheme's (+)/(*)
|
;; Scheme's +/-/*// already implement the JVM-parity numeric tower: exact+exact ->
|
||||||
;; identities are EXACT 0/1, which aren't jolt= to the double 0.0/1.0. The hot
|
;; exact, exact/exact -> Ratio, any flonum -> flonum. Identities (+)=0 / (*)=1 are
|
||||||
;; path uses the inlined native ops, not these.
|
;; exact, matching exact integer arithmetic. The hot path uses the inlined native
|
||||||
(define (jolt-add . xs) (exact->inexact (apply + xs)))
|
;; ops, not these.
|
||||||
(define (jolt-sub . xs) (exact->inexact (apply - xs)))
|
(define (jolt-add . xs) (apply + xs))
|
||||||
(define (jolt-mul . xs) (exact->inexact (apply * xs)))
|
(define (jolt-sub . xs) (apply - xs))
|
||||||
(define (jolt-div . xs) (exact->inexact (apply / xs)))
|
(define (jolt-mul . xs) (apply * xs))
|
||||||
|
(define (jolt-div . xs) (apply / xs))
|
||||||
|
|
||||||
;; ============================================================================
|
;; ============================================================================
|
||||||
;; IFn dispatch — the dynamic "value as fn" fallback. A callee that the emitter
|
;; IFn dispatch — the dynamic "value as fn" fallback. A callee that the emitter
|
||||||
|
|
@ -181,16 +182,18 @@
|
||||||
|
|
||||||
(define (jolt-into to from) (reduce-seq (lambda (acc x) (jolt-conj1 acc x)) to (jolt-seq from)))
|
(define (jolt-into to from) (reduce-seq (lambda (acc x) (jolt-conj1 acc x)) to (jolt-seq from)))
|
||||||
|
|
||||||
(define (range-from n) (cseq-lazy n (lambda () (range-from (+ n 1.0)))))
|
(define (range-from n) (cseq-lazy n (lambda () (range-from (+ n 1)))))
|
||||||
(define (range-bounded n end step)
|
(define (range-bounded n end step)
|
||||||
(if (if (> step 0.0) (< n end) (> n end))
|
(if (if (> step 0.0) (< n end) (> n end))
|
||||||
(cseq-lazy n (lambda () (range-bounded (+ n step) end step)))
|
(cseq-lazy n (lambda () (range-bounded (+ n step) end step)))
|
||||||
jolt-nil))
|
jolt-nil))
|
||||||
|
;; numeric tower (jolt-n6al): exact 0/1 defaults so (range 3) yields exact ints
|
||||||
|
;; (= JVM longs); flonum args still produce flonums (Scheme arithmetic preserves).
|
||||||
(define jolt-range
|
(define jolt-range
|
||||||
(case-lambda
|
(case-lambda
|
||||||
(() (range-from 0.0))
|
(() (range-from 0))
|
||||||
((end) (range-bounded 0.0 end 1.0))
|
((end) (range-bounded 0 end 1))
|
||||||
((start end) (range-bounded start end 1.0))
|
((start end) (range-bounded start end 1))
|
||||||
((start end step) (range-bounded start end step))))
|
((start end step) (range-bounded start end step))))
|
||||||
|
|
||||||
(define (jolt-take n coll)
|
(define (jolt-take n coll)
|
||||||
|
|
|
||||||
|
|
@ -133,16 +133,18 @@
|
||||||
(cond
|
(cond
|
||||||
(nil? v) "jolt-nil"
|
(nil? v) "jolt-nil"
|
||||||
(boolean? v) (if v "#t" "#f")
|
(boolean? v) (if v "#t" "#f")
|
||||||
;; jolt models every number as a double. Emit flonums so arithmetic matches
|
;; Numeric tower (jolt-n6al): emit a literal Chez re-reads as the SAME number.
|
||||||
;; the Janet host and Chez doesn't fall into exploding exact rationals.
|
;; Exact integers -> "42", exact ratios -> "1/2" (str renders both faithfully);
|
||||||
;; ##Inf/##-Inf/##NaN -> Chez's flonum literals (Janet stringifies them as
|
;; a flonum must carry a decimal point/exponent or Chez reads it back as exact,
|
||||||
;; inf/-inf/nan, unbound symbols in Chez).
|
;; so a whole flonum (str drops its .0) gets ".0" appended. ##Inf/##-Inf/##NaN
|
||||||
|
;; -> Chez's flonum literals.
|
||||||
(number? v) (cond
|
(number? v) (cond
|
||||||
(= v ##Inf) "+inf.0"
|
(= v ##Inf) "+inf.0"
|
||||||
(= v ##-Inf) "-inf.0"
|
(= v ##-Inf) "-inf.0"
|
||||||
(not= v v) "+nan.0"
|
(not= v v) "+nan.0"
|
||||||
:else (let [s (str v)]
|
(float? v) (let [s (str v)]
|
||||||
(if (or (str/includes? s ".") (str/includes? s "e")) s (str s ".0"))))
|
(if (or (str/includes? s ".") (str/includes? s "e")) s (str s ".0")))
|
||||||
|
:else (str v))
|
||||||
(string? v) (chez-str-lit v)
|
(string? v) (chez-str-lit v)
|
||||||
;; keyword literal -> (keyword ns name)
|
;; keyword literal -> (keyword ns name)
|
||||||
(keyword? v) (if-let [kns (namespace v)]
|
(keyword? v) (if-let [kns (namespace v)]
|
||||||
|
|
@ -310,9 +312,9 @@
|
||||||
kind (ifn-kind fnode)
|
kind (ifn-kind fnode)
|
||||||
default (if (> (count args) 1) (str " " (nth args 1)) "")]
|
default (if (> (count args) 1) (str " " (nth args 1)) "")]
|
||||||
(cond
|
(cond
|
||||||
;; zero-arg + / * : flonum identity to keep the all-double model.
|
;; zero-arg + / * : exact integer identity (= JVM long: (+) -> 0, (*) -> 1).
|
||||||
(and nop (empty? args) (= nop "+")) "0.0"
|
(and nop (empty? args) (= nop "+")) "0"
|
||||||
(and nop (empty? args) (= nop "*")) "1.0"
|
(and nop (empty? args) (= nop "*")) "1"
|
||||||
(and nop (= 1 (count args)) (cmp1-ops nop)) (str "(begin " (first args) " #t)")
|
(and nop (= 1 (count args)) (cmp1-ops nop)) (str "(begin " (first args) " #t)")
|
||||||
nop (str "(" nop " " (str/join " " args) ")")
|
nop (str "(" nop " " (str/join " " args) ")")
|
||||||
;; (:k coll [default]) -> (jolt-get coll :k [default])
|
;; (:k coll [default]) -> (jolt-get coll :k [default])
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,12 @@
|
||||||
[# --- scalars + collections (value equality, order-independent) ---
|
[# --- scalars + collections (value equality, order-independent) ---
|
||||||
["(= 42 (read-string \"42\"))" "true"]
|
["(= 42 (read-string \"42\"))" "true"]
|
||||||
["(= 42 (read-string \"0x2A\"))" "true"]
|
["(= 42 (read-string \"0x2A\"))" "true"]
|
||||||
["(= 0.5 (read-string \"1/2\"))" "true"]
|
# numeric tower (jolt-n6al): "1/2" reads as an exact Ratio (= JVM), so a
|
||||||
|
# category-aware = against the double 0.5 is false; assert numeric value (==),
|
||||||
|
# which holds in both the all-flonum and tower models.
|
||||||
|
["(== 0.5 (read-string \"1/2\"))" "true"]
|
||||||
["(= -3.5 (read-string \"-3.5\"))" "true"]
|
["(= -3.5 (read-string \"-3.5\"))" "true"]
|
||||||
["(= 1000.0 (read-string \"1e3\"))" "true"]
|
["(== 1000.0 (read-string \"1e3\"))" "true"]
|
||||||
["(= 1 (read-string \"1N\"))" "true"]
|
["(= 1 (read-string \"1N\"))" "true"]
|
||||||
["(integer? (read-string \"7\"))" "true"]
|
["(integer? (read-string \"7\"))" "true"]
|
||||||
["(= :foo (read-string \":foo\"))" "true"]
|
["(= :foo (read-string \":foo\"))" "true"]
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,27 @@
|
||||||
# unquoted value forms eval in hash order, not source order — a minor ordering
|
# unquoted value forms eval in hash order, not source order — a minor ordering
|
||||||
# gap (pmap has no insertion order; the reader's source-order table doesn't cover
|
# gap (pmap has no insertion order; the reader's source-order table doesn't cover
|
||||||
# syntax-quote-built maps). 1 case; the non-syntax-quote map-order cases pass.
|
# syntax-quote-built maps). 1 case; the non-syntax-quote map-order cases pass.
|
||||||
"source order through syntax-quote" true})
|
"source order through syntax-quote" true
|
||||||
|
# numeric tower (jolt-n6al): the zero-Janet path now carries the Chez numeric
|
||||||
|
# tower (exact ints / Ratio / double) = JVM parity, while the corpus :expected
|
||||||
|
# is the all-flonum Janet value (the Janet host has only doubles). So Chez gives
|
||||||
|
# the JVM value and the Janet-era corpus diverges — flipped to JVM at Phase 5
|
||||||
|
# (jolt-ecz0), these stay allowlisted during the transition. Each verified
|
||||||
|
# Chez == reference JVM Clojure.
|
||||||
|
"divide to fraction" true # (/ 1 2) -> 1/2 (JVM Ratio), corpus 0.5
|
||||||
|
"ratio 3/4" true # 3/4 literal -> Ratio
|
||||||
|
"neg ratio" true # -1/2 -> Ratio
|
||||||
|
"ratio -> double" true # ratio result, corpus double
|
||||||
|
"/ ratio-as-double" true
|
||||||
|
"native unary div" true # (/ 2) -> 1/2
|
||||||
|
"double" true # (double 3) -> 3.0 (double != exact 3)
|
||||||
|
"doubles" true "floats" true
|
||||||
|
"unchecked-double" true "unchecked-float" true
|
||||||
|
"floor" true # clojure.math/floor -> 2.0 (JVM double)
|
||||||
|
"signum" true # clojure.math/signum -> -1.0 (JVM double)
|
||||||
|
"Math/sqrt" true # -> 3.0 (double)
|
||||||
|
"Math/pow" true # -> 8.0 (double)
|
||||||
|
"bigdec int M" true}) # 1M: no BigDecimal type on Chez (documented gap)
|
||||||
|
|
||||||
# Cases that BLOCK forever on a shared-heap / JVM host (profile.edn :bucket
|
# Cases that BLOCK forever on a shared-heap / JVM host (profile.edn :bucket
|
||||||
# :timeout) — skip them, like :throws: a single hung case would stall the whole
|
# :timeout) — skip them, like :throws: a single hung case would stall the whole
|
||||||
|
|
@ -226,7 +246,12 @@
|
||||||
# date/time (Date/Timestamp/SimpleDateFormat/TimeZone) + clojure.edn/read over a
|
# date/time (Date/Timestamp/SimpleDateFormat/TimeZone) + clojure.edn/read over a
|
||||||
# reader -> 2692; STM stub + portable line-seq -> 2696; realized? on a lazy-seq +
|
# reader -> 2692; STM stub + portable line-seq -> 2696; realized? on a lazy-seq +
|
||||||
# conj! 1-arity (transducer-completion identity) -> 2698.
|
# conj! 1-arity (transducer-completion identity) -> 2698.
|
||||||
(def base-floor (scan-number (or (os/getenv "JOLT_CHEZ_ZJ_FLOOR") "2698")))
|
# numeric tower (jolt-n6al): 2698 -> 2682. ~16 numeric cases that the all-flonum
|
||||||
|
# model coincidentally passed (corpus :expected is the Janet double value) now give
|
||||||
|
# the JVM tower value (1/2, 3.0, ...) and are reclassified as known tower
|
||||||
|
# divergences (Chez == reference JVM). The floor rises back when the corpus flips
|
||||||
|
# to JVM values (jolt-ecz0, Phase 5).
|
||||||
|
(def base-floor (scan-number (or (os/getenv "JOLT_CHEZ_ZJ_FLOOR") "2682")))
|
||||||
(def floor (if (os/getenv "JOLT_CORPUS_LIMIT") 0 base-floor))
|
(def floor (if (os/getenv "JOLT_CORPUS_LIMIT") 0 base-floor))
|
||||||
(when (or (> (length diverged) 0) (< pass floor))
|
(when (or (> (length diverged) 0) (< pass floor))
|
||||||
(printf "REGRESSION: pass %d < floor %d or %d new divergence(s)" pass floor (length diverged)))
|
(printf "REGRESSION: pass %d < floor %d or %d new divergence(s)" pass floor (length diverged)))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue