module Polar.Shader.Types where
import qualified Data.Map as M
import Control.Lens.TH (makeFields)
data Token = LetT
| EqualsT
| PlusT
| AsteriskT
| NewLineT
| BracketOpenT
| BracketCloseT
| BraceOpenT
| BraceCloseT
| StatementEndT
| IdentifierT String
| LiteralT Double
deriving (Eq, Show)
data AST = Let String AST
| Assignment AST AST
| Additive AST AST
| Multiplicative AST AST
| Swizzle [AST]
| Literal Double
| Identifier String
| NamePosition
| NameVar String DataType
| NameGlobal String DataType
| NameInput String DataType
| NameOutput String DataType
deriving (Eq, Show)
data ShaderType = ShaderVertex | ShaderPixel
data DataType = DataFloat | DataFloat2 | DataFloat4 | DataMatrix4x4 deriving (Eq, Show)
data Function = Function
{ _functionName :: String
, _functionLets :: [(String, DataType)]
, _functionAsts :: [AST]
} deriving (Eq, Show)
makeFields ''Function
data CompilerEnv = CompilerEnv
{ _compilerEnvFunctions :: M.Map String Function
, _compilerEnvGlobals :: M.Map String DataType
, _compilerEnvInputs :: M.Map String DataType
, _compilerEnvOutputs :: M.Map String DataType
}
makeFields ''CompilerEnv
class Compiler a where generate :: CompilerEnv -> a -> Either String (String, String)
class HasComponents a where numComponents :: a -> Either String Int
instance HasComponents DataType where
numComponents DataFloat = return 1
numComponents DataFloat2 = return 2
numComponents DataFloat4 = return 4
numComponents DataMatrix4x4 = return 16
instance HasComponents AST where
numComponents (Let _ right) = numComponents right
numComponents (Assignment left right) = do
l <- numComponents left
(l ==) <$> numComponents right >>= \case
True -> return l
False -> Left "number of components on left does not match number of components on right"
numComponents (Additive left right) = do
l <- numComponents left
(l ==) <$> numComponents right >>= \case
True -> return l
False -> Left "number of components on left does not match number of components on right"
numComponents (Multiplicative left right) = do
l <- numComponents left
r <- numComponents right
if l == 16 && r == 4
then return 4
else (l ==) <$> numComponents right >>= \case
True -> return l
False -> Left "number of components on left does not match number of components on right"
numComponents (Swizzle []) = return 0
numComponents (Swizzle (ast : asts)) = (+) <$> numComponents ast <*> numComponents (Swizzle asts)
numComponents (Literal _) = return 1
numComponents NamePosition = return 4
numComponents (NameVar _ ty) = numComponents ty
numComponents (NameGlobal _ ty) = numComponents ty
numComponents (NameInput _ ty) = numComponents ty
numComponents (NameOutput _ ty) = numComponents ty
numComponents (Identifier name) = Left ("numComponents: unresolved identifier (" ++ name ++ ")")
astType :: AST -> Either String DataType
astType ast = numComponents ast >>= \case
1 -> return DataFloat
2 -> return DataFloat2
4 -> return DataFloat4
16 -> return DataMatrix4x4
x -> Left ("number of components (" ++ show x ++ ") does not match any supported data type")