sci 2026-07-02

I gave Fable 5 a spin on a curiosity of mine, what would it take to make sci work in clojuredart. I am pretty impressed, it got a decent proof of concept working. I wonder if I should burn more tokens to try to polish it to a potentially presentable PR.

@kloud edamame master + sci cljd branch should be usable now. sci depends on my cljd fork with a small change for empty list metadata. if you have anything else in your sci fork + cljs upstream patches, I'd like to know! locally I'm working on some niche stuff but for the most part it will be merged like this, so don't let it stop you from making something cool and giving it a spin

very cool, I integrated it into my prototype. I am using only simple expressions, not exercising the language much, but works great so far! 👍

👍 1

Cool, what are you building?

I am experimenting with driving Flutter UI for small apps over a wire protocol ala hypermedia. It is inspired by Datastar (Anders planted a bug in my head at ClojureDays 🙂), but instead of HTML+JS it is JSON encoded widget tree + clj(sci) for client logic.

👍 1

Fairly good feature coverage already:

(def smoke-tests
  [["(inc 1)" 2]
   ["(let [x 1 y 2] (+ x y))" 3]
   ["((fn [x] (* x x)) 5)" 25]
   ["(do (defn twice [x] (* 2 x)) (twice 21))" 42]
   ["(vec (map inc [1 2 3]))" [2 3 4]]
   ["(vec (filter odd? (range 10)))" [1 3 5 7 9]]
   ["(reduce + (range 101))" 5050]
   ["(try (throw (ex-info \"boom\" {:x 1})) (catch Exception e (:x (ex-data e))))" 1]
   ["(str \"a\" 1 :kw)" "a1:kw"]
   ["(:b {:a 1 :b 2})" 2]
   ["(if true :yes :no)" :yes]
   ["(loop [i 0 acc 0] (if (< i 5) (recur (inc i) (+ acc i)) acc))" 10]
   ["(vec (for [x [1 2 3]] (* x 10)))" [10 20 30]]
   ["(apply + 1 2 [3 4])" 10]
   ["(count \"hello\")" 5]
   ["(do (def a (atom 0)) (swap! a inc) @a)" 1]
   ["(vec (doall (take 3 (repeatedly (constantly :x)))))" [:x :x :x]]
   ["(with-out-str (print \"hi\"))" "hi"]
   ["(vec (map (comp inc :n) [{:n 1} {:n 2}]))" [2 3]]
   ["(let [[a b & r] [1 2 3 4]] [a b (vec r)])" [1 2 [3 4]]]
   ["(let [{:keys [x y] :or {y 9}} {:x 1}] [x y])" [1 9]]
   ["(do (defmulti area :shape) (defmethod area :circle [{:keys [r]}] (* 3 r r)) (area {:shape :circle :r 2}))" 12]
   ["(do (defprotocol Greet (hello [this])) (defrecord P [n] Greet (hello [_] (str \"hi \" n))) (hello (->P \"bob\")))" "hi bob"]
   ["(pr-str {:a [1 2] :b #{3}})" "{:a [1 2], :b #{3}}"]
   ["(do (doseq [x [1]] x) :ok)" :ok]
   ["(condp = 3 1 :one 3 :three :other)" :three]
   ["(case 5 5 :five :other)" :five]
   ["(binding [*print-length* 3] (pr-str (range 10)))" "(0 1 2 ...)"]])

yes! I wanted to do this as well! but I was working on getting edamame to work in clojuredart first. how did you do this?

the edamame work is almost there, but have to review it more thoroughly. some parts are a bit iffy since the normal edamame still relies on tools.reader for some things

it replaced edamame with cljd.reader 🙂

yeah so EDN only?

or is cljd.reader a code reader?

there might be some limitations, also for now does not track line/column numbers properly

porting edamame is probably a way to go

ok let's focus on that one first. I have a working branch in edamame

👍 1

I'm excited that you're interested in joining this effort

I've wired up the suite, many test namespaces pass. Next steps: 1) integrate edamame based on the cljd branch 2) let it cook some more 3) rounds of review and cleanups 4) it made same fixes to ClojureDart, so will need to verify if they are legit and should be submitted to ClojureDart I will post again once I have something in a presentable quality. Rough status of the test suite:

[sci.defrecords-and-deftype-test]
[sci.hierarchies-test]
[sci.io-test]
[sci.multimethods-test]
[sci.namespaces-test]
[sci.parse-test]
[sci.protocols-test]
[sci.core-test] ;; ~25 asserts guarded: arrays, custom reader tags,
               ;; read-cond, line/column, copy-ns, set-literal gap
[sci.reify-test] ;; 2 nested-reify asserts guarded (cljd parser gap)
[sci.repl-test]
[sci.vars-test]))

;; Compiles (compile blockers already fixed in place), but 8 of its 9
;; runnable deftests assert :line/:column and stacktrace data the cljd
;; parser does not track (cljd.reader has no location metadata):
;; [sci.error-test]

;; The port does not expose IDeref/IAtom/IAtom2 protocol names to
;; interpreted code on cljd (clojure.lang.* on the JVM, core protocols
;; on cljs), so reify/defrecord over them cannot work yet:
;; [sci.core-protocols-test]

;; JVM/JS host interop (reflection), out of scope for the port:
;; [sci.interop-test]

;; Needs reader features cljd.reader lacks: reader conditionals
;; (\"No reader function for tag ?\"), read-cond :preserve, and
;; edamame options; the port reads with cljd.reader:
;; [sci.read-test]