|  | @@ -62,8 +62,8 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  (def parse-variables (memoize (fn [expression]
 | 
	
		
			
				|  |  |                                  (js->clj (.getVariables mathjs expression)))))
 | 
	
		
			
				|  |  | -(def evaluate-expressions (memoize (fn [expression variables]
 | 
	
		
			
				|  |  | -                                     (.evaluate mathjs expression (clj->js variables)))))
 | 
	
		
			
				|  |  | +(def evaluate-expression (memoize (fn [expression variables]
 | 
	
		
			
				|  |  | +                                    (.evaluate mathjs expression (clj->js variables)))))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  (defn temp3 [[k v]]
 | 
	
		
			
				|  |  |    (let [w (name k)
 | 
	
	
		
			
				|  | @@ -90,7 +90,7 @@
 | 
	
		
			
				|  |  |            parsed (zipmap (keys remaining) evaluated-vars)
 | 
	
		
			
				|  |  |            not-ready (group-by (fn [[ k v ]] (some #(= :not-yet (last %)) v)) parsed)
 | 
	
		
			
				|  |  |            ;TODO: detect circular references
 | 
	
		
			
				|  |  | -          prepared (map (fn [[k v]] [k (evaluate-expressions (remaining k) (apply hash-map (flatten v)))]) (not-ready nil))
 | 
	
		
			
				|  |  | +          prepared (map (fn [[k v]] [k (evaluate-expression (remaining k) (apply hash-map (flatten v)))]) (not-ready nil))
 | 
	
		
			
				|  |  |            new-evaluated (reduce conj evaluated prepared)
 | 
	
		
			
				|  |  |            still-remaining (apply hash-map (flatten (map #(list (key %) (remaining (key %))) (not-ready true))))]
 | 
	
		
			
				|  |  |        ;remaining ; {:B8 B7 * 2, :C7 D1, :B7 C5 + D6}
 | 
	
	
		
			
				|  | @@ -106,6 +106,73 @@
 | 
	
		
			
				|  |  |        )
 | 
	
		
			
				|  |  |      ))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +(def str->rc (memoize (fn [s]
 | 
	
		
			
				|  |  | +                        (let [c (re-find #"^[A-Z]+" s)
 | 
	
		
			
				|  |  | +                              r (.parseInt js/window (re-find #"[0-9]+$" s))]
 | 
	
		
			
				|  |  | +                          {:row r :col c}))))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +(defn find-cell [data c r]
 | 
	
		
			
				|  |  | +  (some #(if (and (= (:col %) c) (= (:row %) r)) %) data))
 | 
	
		
			
				|  |  | +(defn find-val [data c r]
 | 
	
		
			
				|  |  | +  (let [l (find-cell data c r)
 | 
	
		
			
				|  |  | +        v (get l :display (get l :value))]
 | 
	
		
			
				|  |  | +    (println "found?" c r v l (get l :value) (get l :display))
 | 
	
		
			
				|  |  | +    (cond
 | 
	
		
			
				|  |  | +      (nil? v) 0
 | 
	
		
			
				|  |  | +      (and (string? v) (= (first v) "=")) :not-yet
 | 
	
		
			
				|  |  | +      :else v)))
 | 
	
		
			
				|  |  | +(defn copy-display-values' [data display-values]
 | 
	
		
			
				|  |  | +  (if (empty? display-values)
 | 
	
		
			
				|  |  | +    data
 | 
	
		
			
				|  |  | +    (let [v (first display-values)
 | 
	
		
			
				|  |  | +          r (:row v)
 | 
	
		
			
				|  |  | +          c (:col v)
 | 
	
		
			
				|  |  | +          inserted (map #(if (and (= r (:row %)) (= c (:col %)) (= (first (:value %)) "=")) (assoc % :display (:display v)) %) data)]
 | 
	
		
			
				|  |  | +      (recur inserted (rest display-values)))))
 | 
	
		
			
				|  |  | +(defn copy-display-values [data display-values]
 | 
	
		
			
				|  |  | +  (let [removed (map #(-> % (dissoc :vars) (dissoc :refs) (dissoc :found) (dissoc :inputs)) display-values)]
 | 
	
		
			
				|  |  | +    (into data removed)))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +(defn experimental [data]
 | 
	
		
			
				|  |  | +  (let [remove-old-displays (map #(dissoc % :display) data)
 | 
	
		
			
				|  |  | +        {has-formula true original-values false} (group-by #(= (first (:value %)) "=") remove-old-displays)
 | 
	
		
			
				|  |  | +        ;TODO: detect circular references
 | 
	
		
			
				|  |  | +        variables (map #(assoc % :vars (parse-variables (subs (:value %) 1))) has-formula)
 | 
	
		
			
				|  |  | +        first-mapped-cell-keys (map (fn [datum] (assoc datum :refs (map str->rc (:vars datum)))) variables)]
 | 
	
		
			
				|  |  | +    (loop [values original-values mapped-cell-keys first-mapped-cell-keys]
 | 
	
		
			
				|  |  | +      (let [search-values (map (fn [datum] (assoc datum :found (map #(find-val (concat values mapped-cell-keys) (:col %) (:row %)) (:refs datum)))) mapped-cell-keys)
 | 
	
		
			
				|  |  | +            {not-ready true ready nil} (group-by (fn [datum] (some #(= :not-yet %) (:found datum))) search-values)
 | 
	
		
			
				|  |  | +            prepped-for-eval (map (fn [datum] (assoc datum :inputs (apply hash-map (interleave (:vars datum) (:found datum))))) ready)
 | 
	
		
			
				|  |  | +            evaluated (map (fn [datum] (assoc datum :display (evaluate-expression (subs (:value datum) 1) (:inputs datum)))) prepped-for-eval)
 | 
	
		
			
				|  |  | +            updated-values (copy-display-values values evaluated)
 | 
	
		
			
				|  |  | +            ]
 | 
	
		
			
				|  |  | +        (println)
 | 
	
		
			
				|  |  | +        (println)
 | 
	
		
			
				|  |  | +        (println)
 | 
	
		
			
				|  |  | +        (println "has-formula" has-formula)
 | 
	
		
			
				|  |  | +        (println "values" values)
 | 
	
		
			
				|  |  | +        (println "variables" variables)
 | 
	
		
			
				|  |  | +        (println "mapped-cell-keys" mapped-cell-keys)
 | 
	
		
			
				|  |  | +        (println "search-values" search-values)
 | 
	
		
			
				|  |  | +        (println "not ready to eval" not-ready)
 | 
	
		
			
				|  |  | +        (println "             nil?" (nil? not-ready))
 | 
	
		
			
				|  |  | +        (println "ready to eval" ready)
 | 
	
		
			
				|  |  | +        (println "prepped-for-eval" prepped-for-eval)
 | 
	
		
			
				|  |  | +        (println "evaluated" evaluated)
 | 
	
		
			
				|  |  | +        (println "updated-values" updated-values)
 | 
	
		
			
				|  |  | +        (println "done!")
 | 
	
		
			
				|  |  | +        (println)
 | 
	
		
			
				|  |  | +        (println "loop    " values "      " mapped-cell-keys)
 | 
	
		
			
				|  |  | +        (println "")
 | 
	
		
			
				|  |  | +        (println "recur   " updated-values "    " not-ready)
 | 
	
		
			
				|  |  | +        (if (nil? not-ready)
 | 
	
		
			
				|  |  | +          updated-values
 | 
	
		
			
				|  |  | +          (recur updated-values not-ready)
 | 
	
		
			
				|  |  | +          )
 | 
	
		
			
				|  |  | +        ))
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +  )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  ;TODO: figure out how to re-evaluate only when the cell modified affects other cells
 | 
	
		
			
				|  |  |  (defn re-evaluate-data []
 | 
	
		
			
				|  |  |    (let [rt (temp1 @data-atom)
 | 
	
	
		
			
				|  | @@ -164,6 +231,10 @@
 | 
	
		
			
				|  |  |  (defn app []
 | 
	
		
			
				|  |  |    [:div
 | 
	
		
			
				|  |  |     [:h3 "Microtables"]
 | 
	
		
			
				|  |  | +   (do
 | 
	
		
			
				|  |  | +     (println "hi again")
 | 
	
		
			
				|  |  | +     (experimental @data-atom)
 | 
	
		
			
				|  |  | +     "hi again")
 | 
	
		
			
				|  |  |     [sheet @data-atom]])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ;; -------------------------
 |