Fix conformance gaps: exception types, byte/getBytes, host classes
Shake-out from the conformance-library sweep. Host-side fixes (runtime .ss, no re-mint) plus one analyzer change (re-minted): - Exception fidelity: ex-info and host-constructed throwables (RuntimeException. etc.) now carry their JVM class, so (class e), instance? across the exception hierarchy, .getMessage, and clojure.test thrown?/thrown-with-msg? all work. - .getBytes returns a seqable/countable byte-array and honors UTF-16/UTF-32; String. decodes them. ->bytevector accepts byte-arrays (Base64). - Universal .getClass / .toString / .indexOf / .lastIndexOf on any value/seq. - record? uses the host jrec? predicate (the old (get x :jolt/deftype) crashed on a sorted-map by invoking its comparator). - extend-protocol to abstract host types (clojure.lang.Fn/IFn/APersistentVector, java.net.URI) dispatches. - New host classes: clojure.lang.PersistentQueue, java.util.ArrayList, java.net.URI, java.io.File / java.util.UUID ctors, Double/Float ctors+statics, regex instance? Pattern, System/setProperty. - *assert* / *print-readably* are real settable/bindable vars. - (symbol "ns/name") splits the namespace at the last slash. - letfn fn params desugar destructuring (analyzer; re-minted). unit.edn gains exinfo/hostobj/queue/hostctor/destructure regression rows.
This commit is contained in:
parent
185b4fd3ca
commit
d83175b8c2
14 changed files with 570 additions and 39 deletions
|
|
@ -84,6 +84,30 @@
|
|||
(let loop ((p (reverse parts)))
|
||||
(if (and (pair? p) (string=? (car p) "")) (loop (cdr p)) (reverse p))))
|
||||
|
||||
;; Encode a string to bytes (a bytevector) under a named charset. UTF-8 default;
|
||||
;; ISO-8859-1/latin1/ascii are one byte per char; UTF-16/UTF-32 via Chez's codecs
|
||||
;; (plain "UTF-16" emits a big-endian BOM then BE, matching the JVM). Shared by
|
||||
;; .getBytes and decode-bytevector (String.).
|
||||
(define (charset-encode-bv s csname)
|
||||
(let ((cs (ascii-string-down (if (string? csname) csname (jolt-str-render-one csname)))))
|
||||
(cond
|
||||
((or (string=? cs "utf-8") (string=? cs "utf8")) (string->utf8 s))
|
||||
((member cs '("iso-8859-1" "latin1" "iso8859-1" "us-ascii" "ascii"))
|
||||
(let* ((n (string-length s)) (bv (make-bytevector n)))
|
||||
(do ((i 0 (+ i 1))) ((= i n) bv)
|
||||
(bytevector-u8-set! bv i (bitwise-and (char->integer (string-ref s i)) #xff)))))
|
||||
((string=? cs "utf-16be") (string->utf16 s (endianness big)))
|
||||
((string=? cs "utf-16le") (string->utf16 s (endianness little)))
|
||||
((or (string=? cs "utf-16") (string=? cs "utf16") (string=? cs "unicode"))
|
||||
(let ((be (string->utf16 s (endianness big))))
|
||||
(let* ((n (bytevector-length be)) (bv (make-bytevector (+ n 2))))
|
||||
(bytevector-u8-set! bv 0 #xfe) (bytevector-u8-set! bv 1 #xff)
|
||||
(bytevector-copy! be 0 bv 2 n) bv)))
|
||||
((or (string=? cs "utf-32be") (string=? cs "utf-32") (string=? cs "utf32"))
|
||||
(string->utf32 s (endianness big)))
|
||||
((string=? cs "utf-32le") (string->utf32 s (endianness little)))
|
||||
(else (string->utf8 s)))))
|
||||
|
||||
(define (jolt-string-method method s rest)
|
||||
(define (arg n) (list-ref rest n))
|
||||
(cond
|
||||
|
|
@ -118,16 +142,12 @@
|
|||
((string=? method "compareTo")
|
||||
(let ((o (arg 0))) (cond ((string<? s o) -1.0) ((string>? s o) 1.0) (else 0.0))))
|
||||
((string=? method "getBytes")
|
||||
;; (.getBytes s) / (.getBytes s charset). UTF-8 default; ISO-8859-1/latin1/
|
||||
;; ascii encode one byte per char (clj-http-lite's body-encoding path).
|
||||
(if (null? rest)
|
||||
(string->utf8 s)
|
||||
(let ((cn (ascii-string-down (if (string? (arg 0)) (arg 0) (jolt-str-render-one (arg 0))))))
|
||||
(if (member cn '("iso-8859-1" "latin1" "iso8859-1" "us-ascii" "ascii"))
|
||||
(let* ((n (string-length s)) (bv (make-bytevector n)))
|
||||
(do ((i 0 (+ i 1))) ((= i n) bv)
|
||||
(bytevector-u8-set! bv i (bitwise-and (char->integer (string-ref s i)) #xff))))
|
||||
(string->utf8 s)))))
|
||||
;; (.getBytes s) / (.getBytes s charset) -> a jolt byte-array (seqable /
|
||||
;; countable / alength-able, like (byte-array …)); the JVM returns byte[].
|
||||
(na-byte-array
|
||||
(charset-encode-bv s (if (null? rest)
|
||||
"utf-8"
|
||||
(if (string? (arg 0)) (arg 0) (jolt-str-render-one (arg 0)))))))
|
||||
((string=? method "matches") (if (irregex-match (str-irx (arg 0)) s) #t #f))
|
||||
((string=? method "replaceAll") (irregex-replace/all (str-irx (arg 0)) s (arg 1)))
|
||||
((string=? method "replaceFirst") (irregex-replace (str-irx (arg 0)) s (arg 1)))
|
||||
|
|
@ -141,6 +161,11 @@
|
|||
;; String.intern: jolt strings aren't pooled, but value equality holds, so the
|
||||
;; canonical representation is the string itself.
|
||||
((string=? method "intern") s)
|
||||
;; A class token is its canonical-name string, so Class methods land here:
|
||||
;; (.getName (.getClass x)) / (.getSimpleName …) over the name string.
|
||||
((or (string=? method "getName") (string=? method "getCanonicalName")) s)
|
||||
((string=? method "getSimpleName")
|
||||
(let ((i (str-last-index-of s "."))) (if (>= i 0) (substring s (+ i 1) (string-length s)) s)))
|
||||
(else (error #f (string-append "No method " method " for value")))))
|
||||
|
||||
;; --- clojure.core str-* primitives (the substrate clojure.string.clj calls) ---
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue