module DSL.Deep where
import Matrix  ( Vec, vecX, vecY  -- | :: Vec -> Double|
               , Angle            -- | = Double|
               , Point            -- | = Vec|
               , sub, divide      -- | :: Point  -> Vec    -> Point|
               , rot              -- | :: Angle  -> Point  -> Point|
               )   

empty   :: Shape
disc    :: Shape    -- disc with radius |1| around the origin
square  :: Shape    -- square between |(0,0)| and |(1,1)|    

translate   :: Vec    ->  Shape -> Shape  -- shift the shape along a vector                  
scale       :: Vec    ->  Shape -> Shape  -- magnify the shape by a vector                   
rotate      :: Angle  ->  Shape -> Shape  -- rotate the shape by an angle (around the origin)
union       :: Shape  ->  Shape -> Shape
intersect   :: Shape  ->  Shape -> Shape
difference  :: Shape  ->  Shape -> Shape

inside      :: Point ->  Shape -> Bool    -- run function: is the point inside the shape?

-- Deep embedded = far from the semantics, close to the syntax = AST datatype
data Shape = Empty | Disc   | Square | Translate Vec Shape | Scale Vec Shape | Rotate Angle Shape | Union Shape Shape | Intersect Shape Shape | Difference Shape Shape

empty       = Empty
disc        = Disc  
square      = Square
translate   = Translate
scale       = Scale
rotate      = Rotate
union       = Union
intersect   = Intersect
difference  = Difference

inside p Empty   =  False
inside p Disc    =  norm p <= 1
inside p Square  =  ordered [0, vecX p, 1] && ordered [0, vecY p, 1]
inside p (Translate   v  s)  =  inside (sub p v)     s
inside p (Scale       v  s)  =  inside (divide p v)  s
inside p (Rotate      a  s)  =  inside (rot (-a) p)  s
inside p (Union       x  y)  =  inside p x  ||  inside p y
inside p (Intersect   x  y)  =  inside p x  &&  inside p y
inside p (Difference  x  y)  =  inside p x  && not (inside p y)

-- Helper functions:

norm :: Vec -> Double
norm p = sqrt ((vecX p)^2 + (vecY p)^2)

ordered :: Ord a => [a] -> Bool
ordered (x:y:ys) = x <= y && ordered (y:ys)
ordered _        = True

----------------