Fix REPL: buffer-based output prevents interleaved raw tuples

Rewrite print-value/print-collection to use StringBuffer:
- write-collection/v buf appends formatted output to buf
- write-value/v buf dispatches by type, appends to buf
- print-value creates buffer, builds string, outputs atomically

Prevents Janet C runtime from interleaving <tuple 0x...> with
formatted [v1 v2 ...] output in jpm build executables.

315 ok, 2 fail (pre-existing, unchanged)
This commit is contained in:
Yogthos 2026-06-03 01:07:42 -04:00
parent 5cd9c47fe8
commit e63c2ce8d5

View file

@ -14,100 +14,104 @@
(if line (string/trim line) nil))) (if line (string/trim line) nil)))
# Forward declaration for mutual recursion # Forward declaration for mutual recursion
(var print-value nil) (var write-value nil)
(defn- print-collection [v] (defn- push-str [buf s]
(buffer/push-string buf s))
(defn- write-collection [v buf]
(cond (cond
(tuple? v) (tuple? v)
(do (do
(prin "[") (push-str buf "[")
(var i 0) (var i 0)
(let [n (length v)] (let [n (length v)]
(while (< i n) (while (< i n)
(print-value (in v i)) (write-value (in v i) buf)
(when (< (+ i 1) n) (prin " ")) (when (< (+ i 1) n) (push-str buf " "))
(++ i))) (++ i)))
(prin "]")) (push-str buf "]"))
(array? v) (array? v)
(do (do
(prin "(") (push-str buf "(")
(var i 0) (var i 0)
(let [n (length v)] (let [n (length v)]
(while (< i n) (while (< i n)
(print-value (in v i)) (write-value (in v i) buf)
(when (< (+ i 1) n) (prin " ")) (when (< (+ i 1) n) (push-str buf " "))
(++ i))) (++ i)))
(prin ")")) (push-str buf ")"))
(and (table? v) (= :jolt/set (v :jolt/type))) (and (table? v) (= :jolt/set (v :jolt/type)))
(do (do
(prin "#{") (push-str buf "#{")
(var first? true) (var first? true)
(each k (keys (v :phm)) (each k (keys (v :phm))
(when (not= k :jolt/deftype) (when (not= k :jolt/deftype)
(if first? (set first? false) (prin " ")) (if first? (set first? false) (push-str buf " "))
(print-value k))) (write-value k buf)))
(prin "}")) (push-str buf "}"))
(and (table? v) (get v :jolt/deftype)) (and (table? v) (get v :jolt/deftype))
(do (do
(prin "{") (push-str buf "{")
(var first? true) (var first? true)
(each [k val] (pairs v) (each [k val] (pairs v)
(when (and (not= k :jolt/deftype) (not= k :cnt) (not= k :buckets) (not= k :_meta) (when (and (not= k :jolt/deftype) (not= k :cnt) (not= k :buckets)
(not= k :jolt/type) (not= k :phm)) (not= k :_meta) (not= k :jolt/type) (not= k :phm))
(if first? (set first? false) (prin " ")) (if first? (set first? false) (push-str buf " "))
(print-value k) (write-value k buf)
(prin " ") (push-str buf " ")
(print-value val))) (write-value val buf)))
(prin "}")) (push-str buf "}"))
(struct? v) (struct? v)
(do (do
(prin "{") (push-str buf "{")
(var first? true) (var first? true)
(each [k val] (pairs v) (each [k val] (pairs v)
(if first? (set first? false) (prin " ")) (if first? (set first? false) (push-str buf " "))
(print-value k) (write-value k buf)
(prin " ") (push-str buf " ")
(print-value val)) (write-value val buf))
(prin "}")) (push-str buf "}"))
(table? v) (table? v)
(do (do
(prin "{") (push-str buf "{")
(var first? true) (var first? true)
(each [k val] (pairs v) (each [k val] (pairs v)
(when (not= k :jolt/type) (when (not= k :jolt/type)
(if first? (set first? false) (prin " ")) (if first? (set first? false) (push-str buf " "))
(print-value k) (write-value k buf)
(prin " ") (push-str buf " ")
(print-value val))) (write-value val buf)))
(prin "}")))) (push-str buf "}"))))
(set print-value (fn [v] (set write-value (fn [v buf]
(cond (cond
(nil? v) (prin "nil") (nil? v) (push-str buf "nil")
(= true v) (prin "true") (= true v) (push-str buf "true")
(= false v) (prin "false") (= false v) (push-str buf "false")
(number? v) (prin v) (number? v) (push-str buf (string v))
(string? v) (prin v) (string? v) (push-str buf v)
(keyword? v) (prin ":") (prin (string v)) (keyword? v) (do (push-str buf ":") (push-str buf (string v)))
(tuple? v)
(do (print-collection v) (print))
(array? v)
(do (print-collection v) (print))
(and (struct? v) (= :symbol (get v :jolt/type))) (and (struct? v) (= :symbol (get v :jolt/type)))
(let [ns (get v :ns) name (get v :name)] (let [ns (get v :ns) name (get v :name)]
(if ns (prin ns "/" name) (prin name))) (if ns
(push-str buf (string ns "/" name))
(push-str buf name)))
(and (table? v) (= :jolt/var (v :jolt/type))) (and (table? v) (= :jolt/var (v :jolt/type)))
(prin "#'" (ctx-current-ns ctx) "/" ((var-name v) :name)) (push-str buf (string "#'" (ctx-current-ns ctx) "/" ((var-name v) :name)))
(struct? v) (or (tuple? v) (array? v) (struct? v) (table? v))
(do (print-collection v) (print)) (write-collection v buf)
(table? v) (push-str buf (string v)))))
(do (print-collection v) (print))
(print v)))) (defn print-value [v]
(def buf @"")
(write-value v buf)
(print (string buf)))
(defn main [&] (defn main [&]
(print "Jolt — Clojure on Janet") (print "Jolt — Clojure on Janet")