glsl-0.0.1.0: src/Language/GLSL/AST.hs
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StrictData #-}
module Language.GLSL.AST where
import Control.Applicative (Applicative (..))
import Data.Attoparsec.ByteString.Char8 (Parser)
import qualified Data.Text.Lazy.Builder as LTB
import GHC.Generics (Generic)
data GLSL a = GLSL Version [TopDecl a]
deriving (Generic, Show, Eq, Functor, Foldable, Traversable)
newtype Version = Version Int
deriving (Generic, Show, Eq)
data TopDecl a
= LayoutDecl LayoutSpec GlobalDecl
| GlobalDecl GlobalDecl
| ProcDecl ProcName [ParamDecl] [StmtAnnot a]
deriving (Generic, Show, Eq, Functor, Foldable, Traversable)
data ProcName
= ProcMain
| ProcName NameId
deriving (Generic, Show, Eq)
data LayoutSpec
= LayoutStd140
| LayoutLocation Int
deriving (Generic, Show, Eq)
data ParamDecl
= Param ParamKind LocalDecl
deriving (Generic, Show, Eq)
data ParamKind
= PkIn
| PkOut
| PkInout
deriving (Generic, Show, Eq)
data LocalDecl
= LDecl Type NameId (Maybe Expr)
deriving (Generic, Show, Eq)
data GlobalDecl
= GDecl GDeclKind Type Name
deriving (Generic, Show, Eq)
data GDeclKind
= GkIn
| GkOut
| GkUniform
deriving (Generic, Show, Eq)
data Type
= TyBool
| TyFloat
| TySampler2D
| TyVec Int
| TyMat Int Int
| TyStruct NameId [(Type, NameId)]
deriving (Generic, Show, Eq)
newtype NameId = NameId Int
deriving (Generic, Show, Eq)
data Name
= Name Namespace NameId
deriving (Generic, Show, Eq)
data Namespace
= NsT
| NsS
| NsU
| NsVF
| NsIn
| NsOut
deriving (Generic, Show, Eq)
data FunName
= PrimAbs
| PrimAsin
| PrimAtan
| PrimCos
| PrimCross
| PrimDot
| PrimFloor
| PrimFract
| PrimLength
| PrimMat3x3
| PrimMat4x4
| PrimMod
| PrimNormalize
| PrimPow
| PrimSin
| PrimSmoothstep
| PrimSqrt
| PrimStep
| PrimTan
| PrimVec2
| PrimVec3
| PrimVec4
deriving (Generic, Show, Eq)
data Swizzle
= X | Y | Z | W
deriving (Generic, Show, Eq)
data NameExpr
= NameExpr Name
| UniformExpr NameId NameId
deriving (Generic, Show, Eq)
data Cast
= Cast
| NoCast
deriving (Generic, Show, Eq)
data ExprAtom
= LitIntExpr Cast Int
| LitFloatExpr Cast Float
| IdentifierExpr NameExpr
| SwizzleExpr NameId Swizzle
| VecIndexExpr NameExpr Swizzle
| MatIndexExpr NameExpr Swizzle Swizzle
deriving (Generic, Show, Eq)
data Expr
= UnaryExpr UnaryOp ExprAtom
| BinaryExpr ExprAtom BinaryOp ExprAtom
| FunCallExpr FunName [ExprAtom]
| TextureExpr ExprAtom ExprAtom ExprAtom
| AtomExpr ExprAtom
deriving (Generic, Show, Eq)
data BinaryOp
= BOpPlus
| BOpMinus
| BOpMul
| BOpDiv
| BOpGE
| BOpGT
| BOpLE
| BOpLT
| BOpAnd
| BOpOr
deriving (Generic, Show, Eq)
data UnaryOp
= UOpMinus
| UOpNot
deriving (Generic, Show, Eq)
data StmtAnnot a = SA
{ annot :: a
, unAnnot :: Stmt a
}
deriving (Generic, Show, Eq, Functor, Foldable, Traversable)
instance Applicative StmtAnnot where
pure a = SA a (pure a)
liftA2 f a b = SA (f (annot a) (annot b)) $ liftA2 f (unAnnot a) (unAnnot b)
data Stmt a
= AssignStmt Name Expr
| DeclStmt LocalDecl
| EmitStmt Emit
| IfStmt NameId [StmtAnnot a] [StmtAnnot a]
deriving (Generic, Show, Eq, Functor, Foldable, Traversable)
instance Applicative Stmt where
-- Arbitrary decision because "pure" doesn't really make sense.
pure _ = EmitStmt EmitFragDepth
liftA2 f (IfStmt n t1 e1) (IfStmt _ t2 e2) = IfStmt n
((zipWith . liftA2) f t1 t2)
((zipWith . liftA2) f e1 e2)
liftA2 _ (AssignStmt n e) _ = AssignStmt n e
liftA2 _ (DeclStmt d) _ = DeclStmt d
liftA2 _ (EmitStmt e) _ = EmitStmt e
liftA2 _ (IfStmt n _ _) _ = IfStmt n [] []
data Emit
= EmitPosition Expr
| EmitFragDepth
deriving (Generic, Show, Eq)
class Annot a where
parseAnnot :: Parser a
ppAnnot :: a -> Maybe LTB.Builder
instance Annot () where
parseAnnot = pure ()
ppAnnot = const Nothing
instance (Annot a, Annot b) => Annot (a, b) where
parseAnnot = error "not implemented"
ppAnnot (a, b) = do
ppA <- ppAnnot a
ppB <- ppAnnot b
return $ "(" <> ppA <> ", " <> ppB <> ")"
----------------------------------
argCountForFunName :: FunName -> Int
argCountForFunName PrimAbs = 1
argCountForFunName PrimAsin = 1
argCountForFunName PrimAtan = 2
argCountForFunName PrimCos = 1
argCountForFunName PrimCross = 2
argCountForFunName PrimDot = 2
argCountForFunName PrimFloor = 1
argCountForFunName PrimFract = 1
argCountForFunName PrimLength = 1
argCountForFunName PrimMat3x3 = 3
argCountForFunName PrimMat4x4 = 4
argCountForFunName PrimMod = 2
argCountForFunName PrimNormalize = 1
argCountForFunName PrimPow = 2
argCountForFunName PrimSin = 1
argCountForFunName PrimSmoothstep = 3
argCountForFunName PrimSqrt = 1
argCountForFunName PrimStep = 2
argCountForFunName PrimTan = 1
argCountForFunName PrimVec2 = 2
argCountForFunName PrimVec3 = 3
argCountForFunName PrimVec4 = 4
isLitExpr :: ExprAtom -> Bool
isLitExpr LitFloatExpr{} = True
isLitExpr LitIntExpr{} = True
isLitExpr _ = False
isIdentifierExpr :: ExprAtom -> Bool
isIdentifierExpr IdentifierExpr{} = True
isIdentifierExpr _ = False