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:
Yogthos 2026-06-22 03:20:31 -04:00
parent 5e916433b8
commit 10e3a00777
5 changed files with 59 additions and 8 deletions

View file

@ -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))