content: {- |
  Internal shader program representation.
  -}
  
  module Hylogen.Program where
  
  
  import Data.Reify
  import Data.Monoid
  import System.IO.Unsafe
  
  import Hylogen.Expr
  import Hylogen.Types.Vec (Vec4)
  
  newtype Id = Id Int
  instance Show Id where
    show (Id h) = "_" <> show h
  
  -- | Statement internal representation
  --
  -- We tag a Statement with a Unique ID and its corresponding untyped expression
  data Statement = NewAssign (Unique, ExprMonoF Unique)
                 -- MutAssign (Unique, ExprMonoF Unique)
  
  getExpr :: Statement -> ExprMonoF Unique
  getExpr (NewAssign (_, expr)) = expr
  
  
  
  instance Show Statement where
    show (NewAssign (i, expr@(TreeF (_, ty, _, _) _)))
      = mconcat [ show ty, " ", show . Id $ i, " = ", show . (Id<$>) $  expr, ";"]
  
  -- | GLSL Function internal representation
  --
  -- A Function is composed of Statements.
  newtype Function = Function [Statement]
  instance Show Function where
    show (Function xs) = unlines [ "void main() {"
                                , assignments
                                , "    gl_FragColor = _1;"
                                , "}"
                                ]
      where
        assignments = mconcat $  (<> "\n") . ("    "<>) . show <$> reverse xs
  
  
  -- | Returns a program given an expression in closed untyped form
  monoToProgram :: ExprMono -> Function
  monoToProgram v = unsafePerformIO $ do
    Graph nodes _ <- reifyGraph v
    return . Function $ NewAssign <$> nodes
  
  -- | A GLSL program. Currently synonym for Function.
  type Program = Function
  
  -- | Helper function from a Vec4 to A GLSL Program, with sharing.
  toProgram :: Vec4 -> Program
  toProgram = monoToProgram . toMono
  