 
 
 
-;; constructors
-
-(fact "I can make and recognize instances of :points, :lines and :circles"
-  ((:recognizer push-point) (make-point 3 9))         => true
-  ((:recognizer push-point) 9912)                     => false
-
-  ((:recognizer push-line)
-     (make-line (make-point 2 9) (make-point 2 1)))   => true
-  ((:recognizer push-line)
-     (make-point 2 9))                                => false
-
-  ((:recognizer push-circle)
-     (make-circle (make-point 2 9) (make-point 2 1))) => true
-  ((:recognizer push-circle)
-     (make-point 2 9))                                => false
-  ((:recognizer push-circle)
-     (make-line (make-point 2 9) (make-point 2 1)))   => false)
-
-
-(fact "make-line-from-xyxy"
-  (make-line-from-xyxy 0 1 2 3) => (make-line (make-point 0 1) (make-point 2 3))
-  (make-line-from-xyxy 0 1 0 1) => (throws #"points must differ")
-  )
-
-(fact "`make-line` throws an Exception if both point arguments are the same"
-  (make-line (make-point 1 2) (make-point 1 2)) => (throws #"points must differ"))
-
-
-
-(fact "`make-circle` throws an Exception if both point arguments are the same"
-  (make-circle (make-point 1 2) (make-point 1 2)) => (throws #"points must differ")
-  (make-circle (make-point 1 2.000002) (make-point 1 2.000003)) =not=> (throws)
-  )
-
-
-
-; ;;; helpers
-
-; ;; line slopes
-
-
-(fact "slope works as expected"
-  (slope (make-line (make-point 2.0 2.0) (make-point 1.0 1.0))) => (apf 1.0)
-  (slope (make-line (make-point 1.0 0.0) (make-point 0.0 1.0))) => (apf -1.0)
-  (slope (make-line (make-point 1.0 3.0) (make-point 2.0 1.0))) => (apf -2.0)
-  (slope (make-line (make-point 2.0 1.0) (make-point 1.0 3.0))) => (apf -2.0)
-  (slope (make-line (make-point 1.0 1.0) (make-point 0.0 1.0))) => (apf 0.0))
-
-
-(fact "slope returns the keyword :infinity if the line is vertical"
-  (slope (make-line (make-point 0.0 0.0) (make-point 0.0 1.0))) => :infinity)
-
-
-(fact "slope can detect subtle differences"
-  (< 0.0 (.subtract
-    (slope (make-line (make-point 3.111 2.9128) (make-point 0 0))) 
-    (slope (make-line (make-point 0 0) (make-point 3.11100000001 2.9128))))) => true)
-
-
-; ;; line intercepts
-
-(fact "intercept works as expected"
-  (intercept (make-line (make-point 2.0 2.0) (make-point 1.0 1.0))) => (apf 0.0)
-  (intercept (make-line (make-point 1.0 0.0) (make-point 0.0 1.0))) => (apf 1.0)
-  (intercept (make-line (make-point 1.0 0.0) (make-point -1.0 -1.0))) => (apf -0.5)
-  (intercept (make-line (make-point 1.0 3.0) (make-point 2.0 1.0))) => (apf 5.0)
-  (intercept (make-line (make-point 2.0 1.0) (make-point 1.0 3.0))) => (apf 5.0)
-  (intercept (make-line (make-point 1.0 1.0) (make-point 0.0 1.0))) => (apf 1.0))
-
-(fact "intercept works for horizontal lines"
-  (intercept (make-line-from-xyxy 0  2 5  2)) => 2)
-
-(fact "intercept returns nil if the line is vertical"
-  (intercept (make-line (make-point 0.0 0.0) (make-point 0.0 1.0))) => nil)
-
-
-(fact "intercept can detect subtle differences"
-  (< 0.0
-    (.subtract
-      (intercept (make-line (make-point 129 333) (make-point 88 0.00001)))
-      (intercept (make-line (make-point 88 0) (make-point 129 333))))) => true)
-
-
 ;; rounding
 
 (fact "I can use ApfloatMath/round successfully"

  (pretty-much-equal?
    (intercept (make-line (make-point 3.3 9.9) (make-point 0 0)))
    (intercept (make-line (make-point 0 0) (make-point 3.3 9.9)))) => true)


; ;; lines-coincide?




;;;; Push types and instructions


;; recognizers work for routing

(def test-interpreter
  (core/register-types 
    (owe/make-everything-interpreter)
    [push-point push-line push-circle]))


(def point-class (class (make-point 0.0 0.0)))


(def line-class (class (make-line (make-point 0.0 0.0) (make-point 1 2))))


(def circle-class (class (make-circle (make-point 0.0 0.0) (make-point 1 2))))

(fact "the stacks are already there (though it doesn't really matter)"
  (keys (:stacks test-interpreter)) => (contains [:circle :line :point] :gaps-ok :any-order))


(fact "items can be routed to those stacks correctly"
  (u/get-stack
    (core/handle-item test-interpreter (make-point 3 9))
    :point) => (list (map->Point {:x 3, :y 9}))

  (u/get-stack
    (core/handle-item test-interpreter (make-line (make-point 2 9) (make-point 2 1)))
    :line) => (list (map->Line { :p1 (map->Point {:x 2, :y 9})
                                 :p2 (map->Point {:x 2, :y 1}) }))

  (u/get-stack
    (core/handle-item test-interpreter (make-circle (make-point 2 9) (make-point 2 1)))
    :circle) => (list (map->Circle {
                    :origin
                      (map->Point {:x 2, :y 9})
                    :edgepoint
                      (map->Point {:x 2, :y 1})})))


;; interpreter executes instructions


(fact "test-interpreter knows :line-intersection"
  (keys (:instructions test-interpreter)) => (contains :line-intersection))


(fact "the intersection ends up on the :point stack"
  (let [prepped (core/recycle-interpreter
                test-interpreter
                [line1 line2 :line-intersection])]
    (:stacks prepped) =>
    `{:boolean (), :booleans (), :char (), :chars (), :circle (), :code (), :environment (), :error (), :exec (~line1 ~line2 :line-intersection), :float (), :floats (), :integer (), :integers (), :line (), :log (), :point (), :print (), :return (), :set (), :string (), :strings (), :unknown (), :vector ()}
    
    (u/get-stack (core/run prepped 1000) :point) => (list (make-point 3.0 4.0))))


