|  | @@ -66,6 +66,12 @@
 | 
	
		
			
				|  |  |    (memoize (fn [expression]
 | 
	
		
			
				|  |  |               (clojure.string/replace expression #"\(\s*[A-Z]+[0-9]+\s*:\s*[A-Z]+[0-9]+\s*\)" parse-range))))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +(defn formula?
 | 
	
		
			
				|  |  | +  "Determines if a value is a fomula. If it is, it returns it (without the leading equals sign. If not, it returns nil."
 | 
	
		
			
				|  |  | +  [value]
 | 
	
		
			
				|  |  | +  (if (= (first value) "=")
 | 
	
		
			
				|  |  | +    (subs value 1)
 | 
	
		
			
				|  |  | +    nil))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  (def parse-variables (memoize (fn [expression]
 | 
	
		
			
				|  |  |                                  (as-> (js->clj (.parse mathjs (replace-ranges-in-expression expression))) $
 | 
	
	
		
			
				|  | @@ -83,16 +89,17 @@
 | 
	
		
			
				|  |  |  (defn add-references
 | 
	
		
			
				|  |  |    "Parses the expression in the value of a datum, and adds refs as necessary"
 | 
	
		
			
				|  |  |    [datum]
 | 
	
		
			
				|  |  | -  (if (= (first (:value datum)) "=")
 | 
	
		
			
				|  |  | -    (let [vars (parse-variables (subs (:value datum) 1))
 | 
	
		
			
				|  |  | -          refs (map str->rc vars)]
 | 
	
		
			
				|  |  | +  (let [formula (formula? (:value datum))]
 | 
	
		
			
				|  |  | +    (if formula
 | 
	
		
			
				|  |  | +      (let [vars (parse-variables formula)
 | 
	
		
			
				|  |  | +            refs (map str->rc vars)]
 | 
	
		
			
				|  |  | +        (-> datum
 | 
	
		
			
				|  |  | +            (assoc :refs refs)
 | 
	
		
			
				|  |  | +            (dissoc :error)))
 | 
	
		
			
				|  |  |        (-> datum
 | 
	
		
			
				|  |  | -          (assoc :refs refs)
 | 
	
		
			
				|  |  | -          (dissoc :error)))
 | 
	
		
			
				|  |  | -    (-> datum
 | 
	
		
			
				|  |  | -        (dissoc :refs)
 | 
	
		
			
				|  |  | -        (dissoc :display)
 | 
	
		
			
				|  |  | -        (dissoc :error))))
 | 
	
		
			
				|  |  | +          (dissoc :refs)
 | 
	
		
			
				|  |  | +          (dissoc :display)
 | 
	
		
			
				|  |  | +          (dissoc :error)))))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ; the references in the data are a set of disconnected, doubly-linked trees
 | 
	
		
			
				|  |  |  ;TODO: rather than denotify all, then re-notify all, maybe use a diff? maybe on small scales it's not worth it?
 | 
	
	
		
			
				|  | @@ -150,7 +157,7 @@
 | 
	
		
			
				|  |  |    "Assuming all references have been added, insert all back references."
 | 
	
		
			
				|  |  |    [data]
 | 
	
		
			
				|  |  |    (loop [data data
 | 
	
		
			
				|  |  | -         formulas (walk-get-refs data #(= (first (:value %3)) "="))]
 | 
	
		
			
				|  |  | +         formulas (walk-get-refs data formula?)]
 | 
	
		
			
				|  |  |      (if (empty? formulas)
 | 
	
		
			
				|  |  |        data
 | 
	
		
			
				|  |  |        (let [origin (first formulas)
 | 
	
	
		
			
				|  | @@ -253,9 +260,9 @@
 | 
	
		
			
				|  |  |    (let [datum (dissoc (dissoc (get-in data [c r]) :dirty) :display) ; get rid of the dirty flag right away (it must be included with the returned data to have effect)
 | 
	
		
			
				|  |  |          refs (:refs datum)
 | 
	
		
			
				|  |  |          value (:value datum)
 | 
	
		
			
				|  |  | -        formula? (= (first value) "=")
 | 
	
		
			
				|  |  | +        formula (formula? value)
 | 
	
		
			
				|  |  |          resolved-refs (map #(merge % (get-in data [(:col %) (:row %)])) refs)
 | 
	
		
			
				|  |  | -        evaluated-refs (map #(if (= (first (:value %)) "=") (:display %) (:value %)) resolved-refs)
 | 
	
		
			
				|  |  | +        evaluated-refs (map #(if (formula? (:value %)) (:display %) (:value %)) resolved-refs)
 | 
	
		
			
				|  |  |          invalid-refs (some nil? resolved-refs)
 | 
	
		
			
				|  |  |          dirty-refs (some :dirty resolved-refs)
 | 
	
		
			
				|  |  |          error-refs (some #(= (:display %) :error) resolved-refs)
 | 
	
	
		
			
				|  | @@ -263,7 +270,7 @@
 | 
	
		
			
				|  |  |          cycle-refs (some #(= (:display %) :cycle-error) resolved-refs)
 | 
	
		
			
				|  |  |          disqualified? (or invalid-refs dirty-refs error-refs)]
 | 
	
		
			
				|  |  |      (cond
 | 
	
		
			
				|  |  | -      (false? formula?) (assoc-in data [c r] datum) ; if it's not a formula, then return as is (with the dirty flag removed)
 | 
	
		
			
				|  |  | +      formula (assoc-in data [c r] datum)           ; if it's not a formula, then return as is (with the dirty flag removed)
 | 
	
		
			
				|  |  |        cycle-refs (-> data                           ; if one of its references has a reference cycle, then this one is "poisoned" as well
 | 
	
		
			
				|  |  |                       (assoc-in [c r] datum)
 | 
	
		
			
				|  |  |                       (assoc-in [c r :display] :cycle-error))
 |