Host completeness for the ring stack (ring-app)
Gaps surfaced loading ring-core / hiccup / config / tools.logging on Chez:
- clojure.java.io/resource — resolve a named resource against the loader's
source roots (no classpath), returning a slurp-able File.
- (Object.) constructor — a fresh distinct value (lock / unique sentinel).
- *out* / *err* as dynamic vars over a port-writer, so (binding [*out* *err*] …)
and #'*out* compile and run (tools.logging, selmer).
- :refer :all now registers a refer-all relation, so an unqualified var from a
(require '[ns :refer :all]) resolves at compile time — including #'var.
- java.lang.Character interop ((.toString \+) etc.).
- StringReader accepts a char[] ((StringReader. (char-array s))), not just a
String.
- the \p{L} translation stops just below the UTF-16 surrogate gap (\x{D7FF})
instead of \x{10FFFF} — a range across the surrogates made irregex's char-set
construction call integer->char on a surrogate and crash.
This commit is contained in:
parent
5e916433b8
commit
10e3a00777
5 changed files with 59 additions and 8 deletions
|
|
@ -267,6 +267,10 @@
|
|||
(define (render-piece x)
|
||||
(cond ((jolt-nil? x) "null") ((char? x) (string x)) ((string? x) x)
|
||||
(else (jolt-str-render-one x))))
|
||||
;; (Object.) — a fresh value with distinct identity (libraries use it as a lock
|
||||
;; or a unique sentinel). Each call returns a new jhost so identical?/= separate.
|
||||
(register-class-ctor! "Object" (lambda _ (make-jhost "object" (vector))))
|
||||
|
||||
(register-class-ctor! "StringBuilder"
|
||||
(lambda args (make-jhost "string-builder"
|
||||
;; a numeric first arg is a CAPACITY hint, not content.
|
||||
|
|
@ -308,6 +312,19 @@
|
|||
(cons "close" (lambda (self) (fw-flush! self) jolt-nil))
|
||||
(cons "toString" (lambda (self) (fw-buf self)))))
|
||||
|
||||
;; a writer over a real Chez port — the values *out* / *err* hold. write/append
|
||||
;; push to the port (so (.write *out* s) and (binding [*out* *err*] …) work);
|
||||
;; it isn't a buffer, so toString is empty. Lets libraries that touch *out*/*err*
|
||||
;; (tools.logging, selmer) compile and run.
|
||||
(register-host-methods! "port-writer"
|
||||
(list (cons "write" (lambda (self x) (display (writer-piece x) (vector-ref (jhost-state self) 0)) jolt-nil))
|
||||
(cons "append" (lambda (self x) (display (render-piece x) (vector-ref (jhost-state self) 0)) self))
|
||||
(cons "flush" (lambda (self) (flush-output-port (vector-ref (jhost-state self) 0)) jolt-nil))
|
||||
(cons "close" (lambda (self) jolt-nil))
|
||||
(cons "toString" (lambda (self) ""))))
|
||||
(def-var! "clojure.core" "*out*" (make-jhost "port-writer" (vector (current-output-port))))
|
||||
(def-var! "clojure.core" "*err*" (make-jhost "port-writer" (vector (current-error-port))))
|
||||
|
||||
;; ---- java.util.HashMap ------------------------------------------------------
|
||||
;; A mutable map keyed by jolt values (jolt-hash / jolt=2). State #(chez-hashtable).
|
||||
;; Constructors: () | (capacity) | (capacity load-factor) [sizing args ignored] |
|
||||
|
|
@ -360,7 +377,14 @@
|
|||
;; ---- StringReader -----------------------------------------------------------
|
||||
;; state: a vector #(string pos marked).
|
||||
(register-class-ctor! "StringReader"
|
||||
(lambda (src . _) (make-jhost "string-reader" (vector (if (string? src) src (jolt-str-render-one src)) 0 0))))
|
||||
;; src is a String or a char[] ((StringReader. (char-array s)) — selmer's parser
|
||||
;; reads templates this way); a char-array becomes the string of its chars.
|
||||
(lambda (src . _)
|
||||
(make-jhost "string-reader"
|
||||
(vector (cond ((string? src) src)
|
||||
((jolt-array? src) (apply string-append (map jolt-str-render-one (seq->list (jolt-seq src)))))
|
||||
(else (jolt-str-render-one src)))
|
||||
0 0))))
|
||||
(define (sr-s self) (vector-ref (jhost-state self) 0))
|
||||
(define (sr-pos self) (vector-ref (jhost-state self) 1))
|
||||
(define (sr-pos! self p) (vector-set! (jhost-state self) 1 p))
|
||||
|
|
|
|||
|
|
@ -263,4 +263,15 @@
|
|||
(def-var! "clojure.java.io" "writer" jolt-io-writer)
|
||||
(def-var! "clojure.java.io" "input-stream" jolt-io-reader)
|
||||
(def-var! "clojure.java.io" "output-stream" jolt-io-writer)
|
||||
;; resource: jolt has no classpath, so a named resource is resolved against the
|
||||
;; loader's source roots (a project's :paths, e.g. "resources"). Returns a File
|
||||
;; (slurp/reader-able) for the first match, else nil. get-source-roots is the
|
||||
;; loader's accessor (loader.ss), resolved at call time — the runtime CLI loads it.
|
||||
(define (jolt-io-resource name)
|
||||
(let ((nm (jolt-str-render-one name)))
|
||||
(let loop ((roots (get-source-roots)))
|
||||
(cond ((null? roots) jolt-nil)
|
||||
((file-exists? (string-append (car roots) "/" nm)) (make-jfile (string-append (car roots) "/" nm)))
|
||||
(else (loop (cdr roots)))))))
|
||||
(def-var! "clojure.java.io" "resource" jolt-io-resource)
|
||||
(def-var! "clojure.java.io" "as-url" (lambda (x) (if (and (jhost? x) (string=? (jhost-tag x) "url")) x (make-url (jolt-str-render-one x)))))
|
||||
|
|
|
|||
|
|
@ -68,10 +68,14 @@
|
|||
((string=? (keyword-t-name k) "as")
|
||||
(when (symbol-t? v) (chez-register-alias! cns (symbol-t-name v) target)))
|
||||
((string=? (keyword-t-name k) "refer")
|
||||
(when (pvec? v)
|
||||
(for-each (lambda (n)
|
||||
(when (symbol-t? n) (chez-register-refer! cns (symbol-t-name n) target)))
|
||||
(seq->list v)))))))
|
||||
(cond
|
||||
;; :refer :all — bring in every public var (require :refer :all)
|
||||
((and (keyword? v) (string=? (keyword-t-name v) "all"))
|
||||
(chez-register-refer-all! cns target))
|
||||
((pvec? v)
|
||||
(for-each (lambda (n)
|
||||
(when (symbol-t? n) (chez-register-refer! cns (symbol-t-name n) target)))
|
||||
(seq->list v))))))))
|
||||
(loop (cddr xs))))))))
|
||||
|
||||
;; a namespace designator -> its name string (a jns or a symbol; the corpus never
|
||||
|
|
|
|||
|
|
@ -266,6 +266,15 @@
|
|||
(let ((v (jolt-first s))) (jiterator-cur-set! obj (jolt-rest s)) v))))
|
||||
(else (error #f (string-append "No method " method-name " on Iterator")))))
|
||||
((string=? method-name "iterator") (make-jiterator (jolt-seq obj)))
|
||||
;; java.lang.Character interop: (.toString \+) -> "+", etc.
|
||||
((char? obj)
|
||||
(cond ((string=? method-name "toString") (string obj))
|
||||
((string=? method-name "charValue") obj)
|
||||
((string=? method-name "hashCode") (char->integer obj))
|
||||
((string=? method-name "equals") (and (pair? rest) (char? (car rest)) (char=? obj (car rest))))
|
||||
((string=? method-name "compareTo")
|
||||
(let ((o (car rest))) (cond ((char<? obj o) -1) ((char>? obj o) 1) (else 0))))
|
||||
(else (error #f (string-append "No method " method-name " on char")))))
|
||||
(else (error #f (string-append "No method " method-name " for value: "
|
||||
(jolt-pr-str obj)))))))
|
||||
|
||||
|
|
|
|||
|
|
@ -42,9 +42,12 @@
|
|||
;; ORIGINAL source is kept for printing; only the compiled pattern is translated.
|
||||
(define (prop-class name)
|
||||
(cond
|
||||
;; L/Alpha: ASCII letters + any non-ASCII codepoint (UTF-8 high
|
||||
;; bytes count as letters, so ^\p{L}+$ accepts accented words). N/Z stay ASCII-only.
|
||||
((or (string=? name "L") (string=? name "Alpha")) "a-zA-Z\\x80-\\x{10FFFF}")
|
||||
;; L/Alpha: ASCII letters + non-ASCII up to just below the UTF-16 surrogate gap
|
||||
;; (D800). This covers essentially every real letter (Latin/Greek/Cyrillic/CJK/…
|
||||
;; live below D800); the supplementary planes above it are rare and a range that
|
||||
;; reaches them makes irregex's char-set construction call integer->char on a
|
||||
;; surrogate and crash. N/Z stay ASCII-only.
|
||||
((or (string=? name "L") (string=? name "Alpha")) "a-zA-Z\\x80-\\x{D7FF}")
|
||||
((string=? name "Lu") "A-Z")
|
||||
((string=? name "Ll") "a-z")
|
||||
((or (string=? name "N") (string=? name "Nd") (string=? name "Digit")) "0-9")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue