read-string constructs sets; format %x lowercase; extend/extends? on nil
read-string/read now return real sets for #{...} literals (top-level and
nested) instead of the reader's {:jolt/type :jolt/set} form — the data
seams convert set forms to sets (recursing, preserving metadata and source
map-key order); clojure.edn already did this. The compiler keeps reading
via the raw reader, so set literals in code stay forms the analyzer lowers.
format %x now emits lowercase hex (Chez number->string is uppercase); %X
unchanged.
extend and extends? handle a nil target type (host tag "nil"), matching
extend-type — protocols can be extended to nil via the function form, not
just the macro.
Found porting transit/data.json and shaking out aero.
This commit is contained in:
parent
e74b940db5
commit
c26fd175f2
8 changed files with 604 additions and 534 deletions
|
|
@ -15,7 +15,10 @@
|
|||
;; inference when the unit opted into direct-linking (jolt build --opt). Off that
|
||||
;; path it is a pure const-fold. Loaded from the compiler image (jolt.passes).
|
||||
(define jolt-ce-run-passes (var-deref "jolt.passes" "run-passes"))
|
||||
(define jolt-ce-read (var-deref "clojure.core" "read-string"))
|
||||
;; The compiler reads source as FORMS (set literals stay {:jolt/type :jolt/set},
|
||||
;; which the analyzer lowers) — the raw reader, not clojure.core/read-string,
|
||||
;; whose data conversion would turn those into real sets.
|
||||
(define jolt-ce-read jolt-read-form-raw)
|
||||
|
||||
;; The spine ALWAYS runs with the full clojure.core prelude loaded, so a clojure.*
|
||||
;; ref must lower to var-deref (resolved from the prelude), not trip the emitter's
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
((#\d) (number->string (->long a)))
|
||||
((#\s) (jolt-str-render-one a))
|
||||
((#\f) (fmt-float a (or prec 6)))
|
||||
((#\x) (number->string (->long a) 16))
|
||||
((#\x) (string-downcase (number->string (->long a) 16)))
|
||||
((#\X) (string-upcase (number->string (->long a) 16)))
|
||||
((#\o) (number->string (->long a) 8))
|
||||
((#\b) (if (jolt-truthy? a) "true" "false"))
|
||||
|
|
|
|||
|
|
@ -526,12 +526,62 @@
|
|||
(jolt-throw (jolt-ex-info "EOF while reading reader macro" (empty-pmap))))
|
||||
(values (jolt-list head form) j)))
|
||||
|
||||
;; --- form -> data -----------------------------------------------------------
|
||||
;; read-string/read return DATA, so set literal FORMS ({:jolt/type :jolt/set
|
||||
;; :value [...]}) become real sets, recursing through maps/vectors/lists. The
|
||||
;; COMPILER reads via rdr-read-form and keeps the set FORM (the analyzer lowers
|
||||
;; it), so this conversion runs only on the data seams. Structural sharing keeps
|
||||
;; identity (and the rdr-map-order entry + metadata) for any branch with no set.
|
||||
(define (rdr-set-form? x)
|
||||
(and (pmap? x) (eq? (jolt-get x rdr-kw-jolt-type) rdr-kw-jolt-set)
|
||||
(not (jolt-nil? (jolt-get x rdr-kw-value)))))
|
||||
|
||||
(define (rdr-conv-each xs) ; (values converted-list changed?)
|
||||
(let loop ((xs xs) (acc '()) (changed #f))
|
||||
(if (null? xs)
|
||||
(values (reverse acc) changed)
|
||||
(let ((c (rdr-form->data (car xs))))
|
||||
(loop (cdr xs) (cons c acc) (or changed (not (eq? c (car xs)))))))))
|
||||
|
||||
(define (rdr-carry-meta src dst)
|
||||
(let ((m (jolt-meta src))) (if (jolt-nil? m) dst (jolt-with-meta dst m))))
|
||||
|
||||
(define (rdr-form->data x)
|
||||
(cond
|
||||
((rdr-set-form? x)
|
||||
(let ((items (jolt-get x rdr-kw-value)))
|
||||
(rdr-carry-meta x
|
||||
(let loop ((i 0) (s empty-pset))
|
||||
(if (fx>=? i (pvec-count items)) s
|
||||
(loop (fx+ i 1) (pset-conj s (rdr-form->data (pvec-nth-d items i jolt-nil)))))))))
|
||||
((pvec? x)
|
||||
(let-values (((items changed) (rdr-conv-each (vector->list (pvec-v x)))))
|
||||
(if changed (rdr-carry-meta x (apply jolt-vector items)) x)))
|
||||
((pmap? x)
|
||||
(let ((order (hashtable-ref rdr-map-order x #f)))
|
||||
(if order
|
||||
(let-values (((kvs changed) (rdr-conv-each order)))
|
||||
(if changed
|
||||
(let ((m (rdr-make-map kvs))) (rdr-carry-meta x m))
|
||||
x))
|
||||
(let-values (((kvs changed)
|
||||
(rdr-conv-each (pmap-fold x (lambda (k v a) (cons k (cons v a))) '()))))
|
||||
(if changed (rdr-carry-meta x (apply jolt-hash-map kvs)) x)))))
|
||||
((cseq? x)
|
||||
(let-values (((items changed) (rdr-conv-each (seq->list x))))
|
||||
(if changed (rdr-carry-meta x (apply jolt-list items)) x)))
|
||||
(else x)))
|
||||
|
||||
;; --- the two host seams -----------------------------------------------------
|
||||
;; clojure.core/read-string: first form, or nil for blank / comment-only input
|
||||
;; (parse-string wart, matched deliberately).
|
||||
(define (jolt-read-string s)
|
||||
;; (parse-string wart, matched deliberately). jolt-read-form-raw keeps set FORMS
|
||||
;; for the compiler spine (compile-eval); the data seam converts them to sets.
|
||||
(define (jolt-read-form-raw s)
|
||||
(let-values (((form j) (rdr-read-form s 0 (string-length s))))
|
||||
(if (rdr-eof? form) jolt-nil form)))
|
||||
(define (jolt-read-string s)
|
||||
(let ((form (jolt-read-form-raw s)))
|
||||
(if (jolt-nil? form) form (rdr-form->data form))))
|
||||
|
||||
;; __parse-next: [form rest-of-string] or nil when only whitespace/comments left.
|
||||
(define (jolt-parse-next s)
|
||||
|
|
@ -539,7 +589,7 @@
|
|||
(let-values (((form j) (rdr-read-form s 0 end)))
|
||||
(if (rdr-eof? form)
|
||||
jolt-nil
|
||||
(jolt-vector form (substring s j end))))))
|
||||
(jolt-vector (rdr-form->data form) (substring s j end))))))
|
||||
|
||||
;; __read-tagged: apply a built-in data reader to an already-read form. The tag
|
||||
;; is the :#name keyword the reader produced; #uuid/#inst reuse the inst-time ctors.
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue