clojure-mode decided each shape. A with- head, and a def or with- head behind a namespace, indents as a body; a qualified head finds its unqualified spec. The rest was hand formatting: cond and match results under their tests, ordinary call arguments under the first one, and lone ; continuation comments rewritten as ;; lines above the code.
33 lines
1.2 KiB
Plaintext
33 lines
1.2 KiB
Plaintext
;;;; A data type a package exports, which is what vendor/edn's Value needed.
|
|
;;;;
|
|
;;;; A struct imports by renaming one name. A data type has a second half — the
|
|
;;;; case table — and the question this package exists to answer is where each
|
|
;;;; half ends up. The answer is that a case is not a top-level name: it has no
|
|
;;;; existence apart from its type, so the only thing to qualify is the [Node.]
|
|
;;;; in front of it, and an importer's [(Leaf n)] pattern stays bare because it
|
|
;;;; resolves against the scrutinee's type and never against a name.
|
|
|
|
(defdata Node
|
|
[(Leaf [n i64])
|
|
(Branch [kids (Vec Node)])
|
|
(Empty [])])
|
|
|
|
;; Built inside the package, where the constructor is written unqualified and
|
|
;; the import has to rewrite it.
|
|
(defn leaf [n i64] Node (Node.Leaf {.n n}))
|
|
|
|
;; A case with no fields is a value and not a call, so this is the [Var] node
|
|
;; where the others are [Struct] nodes — the second shape the rename has to
|
|
;; catch, and the one it is easy to catch only half of.
|
|
(defn nothing [] Node Node.Empty)
|
|
|
|
(defn total [t Node] i64
|
|
(match t
|
|
(Leaf n) n
|
|
(Branch kids)
|
|
(let [s (i64 0)]
|
|
(dotimes [i (length kids)]
|
|
(set s (+ s (total (at kids i)))))
|
|
s)
|
|
Empty (i64 0)))
|