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.
87 lines
4.3 KiB
Scheme
87 lines
4.3 KiB
Scheme
;; type predicates + simple accessors (jolt-9ziu) — host-coupled seed natives.
|
|
;;
|
|
;; These are seed primitives (not clojure.core overlay fns), so they're never
|
|
;; def-var!'d by the assembled prelude; the Chez host must provide them. Semantics
|
|
;; match the Janet seed (src/jolt/core_types.janet): map?/vector?/set? are STRICT
|
|
;; over the persistent-collection records, seq? is true only for real sequences,
|
|
;; coll? is the union. Records (shape-recs) are Phase 2, so the record arms of the
|
|
;; seed predicates are simply absent here for now.
|
|
|
|
(define (jolt-map? x) (pmap? x))
|
|
;; a map entry is a pvec under the hood AND is vector? — Clojure's MapEntry
|
|
;; implements IPersistentVector, so (vector? (first {:a 1})) is true (the seed
|
|
;; agrees; jolt-75sv corrected the earlier exclusion).
|
|
(define (jolt-vector? x) (pvec? x))
|
|
(define (jolt-set? x) (pset? x))
|
|
(define (jolt-seq? x) (or (cseq? x) (empty-list-t? x)))
|
|
;; (list? x): a list-marked cseq node or the empty list (). A lazy/vector-backed
|
|
;; seq, (rest list), (seq coll), (map …) are seqs but not lists (jolt-75sv).
|
|
(define (jolt-list-pred? x) (or (and (cseq? x) (cseq-list? x)) (empty-list-t? x)))
|
|
(define (jolt-coll-pred? x)
|
|
(or (pvec? x) (pmap? x) (pset? x) (cseq? x) (empty-list-t? x)))
|
|
(define (jolt-number? x) (number? x))
|
|
(define (jolt-string? x) (string? x))
|
|
(define (jolt-char-pred? x) (char? x))
|
|
;; JVM-parity number-type predicates over the Chez numeric tower. integer? is the
|
|
;; 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-boolean-pred? x) (boolean? x))
|
|
|
|
;; (boolean x) coerces truthiness (nil/false -> false, else true).
|
|
(define (jolt-boolean x) (if (jolt-truthy? x) #t #f))
|
|
|
|
;; (name x): keyword/symbol -> name string; string -> itself.
|
|
(define (jolt-name x)
|
|
(cond
|
|
((keyword? x) (keyword-t-name x))
|
|
((symbol-t? x) (symbol-t-name x))
|
|
((string? x) x)
|
|
(else (error #f "name: expected string/symbol/keyword" x))))
|
|
|
|
;; (namespace x): keyword/symbol ns string, or nil when unqualified.
|
|
(define (jolt-namespace x)
|
|
(let ((ns (cond ((keyword? x) (keyword-t-ns x))
|
|
((symbol-t? x) (symbol-t-ns x))
|
|
(else (error #f "namespace: expected symbol/keyword" x)))))
|
|
(if (or (jolt-nil? ns) (not ns) (eq? ns '())) jolt-nil ns)))
|
|
|
|
(def-var! "clojure.core" "nil?" jolt-nil?)
|
|
(def-var! "clojure.core" "number?" jolt-number?)
|
|
(def-var! "clojure.core" "string?" jolt-string?)
|
|
(def-var! "clojure.core" "char?" jolt-char-pred?)
|
|
(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" "keyword?" keyword?)
|
|
(def-var! "clojure.core" "map?" jolt-map?)
|
|
(def-var! "clojure.core" "vector?" jolt-vector?)
|
|
(def-var! "clojure.core" "set?" jolt-set?)
|
|
(def-var! "clojure.core" "seq?" jolt-seq?)
|
|
(def-var! "clojure.core" "list?" jolt-list-pred?)
|
|
(def-var! "clojure.core" "coll?" jolt-coll-pred?)
|
|
(def-var! "clojure.core" "fn?" jolt-fn?)
|
|
(def-var! "clojure.core" "boolean?" jolt-boolean-pred?)
|
|
(def-var! "clojure.core" "boolean" jolt-boolean)
|
|
(def-var! "clojure.core" "name" jolt-name)
|
|
(def-var! "clojure.core" "namespace" jolt-namespace)
|