-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
287 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
(ns hyperfiddle.domlike " | ||
A mutable tree implementation with an API isomorphic to a subset of the DOM. | ||
") | ||
|
||
(defn node " | ||
Return a fresh node. | ||
" [] | ||
(doto (object-array 3) | ||
(aset 2 []))) | ||
|
||
(defn parent " | ||
Return `node`'s current parent. | ||
" [^objects node] | ||
(aget node 0)) | ||
|
||
(defn set-parent " | ||
Assign `node`'s parent to `parent`. | ||
" [^objects node parent] | ||
(aset node 0 parent)) | ||
|
||
(defn index " | ||
Return `node`'s current index. | ||
" [^objects node] | ||
(aget node 1)) | ||
|
||
(defn set-index " | ||
Assign `node`'s index to `index`. | ||
" [^objects node index] | ||
(aset node 1 index)) | ||
|
||
(defn children " | ||
Return `node`'s current children. | ||
" [^objects node] | ||
(aget node 2)) | ||
|
||
(defn set-children " | ||
Assign `node`s children to `children`. | ||
" [^objects node children] | ||
(aset node 2 children)) | ||
|
||
(defn nth-child " | ||
Return `node`'s child in position `i`, or `nil` if out of bounds. | ||
" [node i] | ||
(nth (children node) i nil)) | ||
|
||
(defn remove-at [node i] | ||
(let [v (children node)] | ||
(set-children node | ||
(into (subvec v 0 i) | ||
(map (fn [c] (set-index c (dec (index c))) c)) | ||
(subvec v (inc i)))))) | ||
|
||
(defn remove-child " | ||
Remove `child` from `node`'s children and return the removed node. | ||
" [node child] | ||
(when-not (identical? node (parent child)) | ||
(throw (#?(:clj Error. :cljs js/Error.) "not a child"))) | ||
(remove-at node (index child)) | ||
(set-parent child nil) | ||
(set-index child nil) | ||
child) | ||
|
||
(defn replace-child " | ||
Replace `old` by `child` in `node`'s children and return the removed node. | ||
" [node child old] | ||
(when-not (identical? node (parent old)) | ||
(throw (#?(:clj Error. :cljs js/Error.) "not a child"))) | ||
(when-some [p (parent child)] | ||
(remove-at p (index child))) | ||
(set-parent child node) | ||
(set-index child (index old)) | ||
(set-children node | ||
(assoc (children node) | ||
(index old) child)) | ||
(set-parent old nil) | ||
(set-index old nil) | ||
old) | ||
|
||
(defn insert-before " | ||
Insert `child` before `sibling` in `node`s children and return the added node. | ||
" [node child sibling] | ||
(when-not (nil? sibling) | ||
(when (identical? child sibling) | ||
(throw (#?(:clj Error. :cljs js/Error.) "insert before self"))) | ||
(when-not (identical? node (parent sibling)) | ||
(throw (#?(:clj Error. :cljs js/Error.) "not a child")))) | ||
(when-some [p (parent child)] | ||
(remove-at p (index child))) | ||
(let [v (children node) | ||
i (if (nil? sibling) | ||
(count v) | ||
(index sibling))] | ||
(set-parent child node) | ||
(set-index child i) | ||
(set-children node | ||
(-> [] | ||
(into (subvec v 0 i)) | ||
(conj child) | ||
(into (map (fn [c] (set-index c (inc (index c))) c)) | ||
(subvec v i)))) | ||
child)) | ||
|
||
(defn append-child " | ||
Adds `child` at the end of `node`'s children and return the added node. | ||
" [node child] | ||
(insert-before node child nil)) | ||
|
||
(defn tree " | ||
Return a snapshot of the tree rooted at `node`. | ||
" [node] (into [node] (map tree) (children node))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
(ns hyperfiddle.incseq.mount-impl | ||
(:require [hyperfiddle.incseq.perm-impl :as p])) | ||
|
||
(defn permute-keys [rf r p m] | ||
(reduce-kv (fn [r k v] (rf r (p k k) v)) r m)) | ||
|
||
(defn mount [append-child replace-child insert-before remove-child nth-child] | ||
(letfn [(append [element degree grow permutation change] | ||
(let [q (p/inverse permutation)] | ||
(loop [i (- degree grow) | ||
c change] | ||
(if (== i degree) | ||
(do (permute-keys replace element permutation c) | ||
(p/rotations rotate element permutation)) | ||
(let [j (q i i)] | ||
(append-child element (c j)) | ||
(recur (inc i) (dissoc c j))))))) | ||
(replace [element i e] | ||
(replace-child element e (nth-child element i))) | ||
(rotate [element i j] | ||
(insert-before element (nth-child element i) | ||
(nth-child element (if (< i j) (inc j) j))) | ||
element)] | ||
(fn [element {:keys [grow shrink degree permutation change]}] | ||
(let [size-after (- degree shrink)] | ||
(loop [d degree | ||
p permutation] | ||
(if (== d size-after) | ||
(append element d grow p change) | ||
(let [i (dec d) | ||
j (p i i)] | ||
(remove-child element (nth-child element j)) | ||
(recur i (p/compose p (p/rotation i j)))))))))) |
Oops, something went wrong.