{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE OverloadedStrings #-}

module Mischief.Shader.Internal.Params where

import Data.Data
import Data.Default
import Data.Singletons (SingI)
import Data.Text (Text)
import Data.Text qualified as T
import GHC.Generics
import GHC.Records
import GHC.TypeLits (KnownNat, KnownSymbol, Nat, Symbol, natVal, symbolVal)
import Mischief.Shader.Internal.Bindings
import Mischief.Shader.Internal.Singletons
import Mischief.Shader.Internal.State

data BuiltInParam (n :: Symbol) b = BuiltInParam

data LocationParam (n :: Nat) b = LocationParam

data ParamDefinition = StructParam Text Params | AnonParam Text Text

type family BuiltIn a n b where
  BuiltIn Internal n b = BuiltInParam n b
  BuiltIn GPU n (Expr b) = Expr b

type family Location a n b where
  Location Internal n b = LocationParam n b
  Location GPU n (Expr b) = Expr b

-- data BuiltIn (name :: Symbol) a where
--   BuiltIn :: forall a name. (Expr a) -> BuiltIn name (Expr a)

-- data Location (n :: Nat) a where
--   Location :: forall a n. (Expr a) -> Location n (Expr a)

data ParamKind = LocKind Integer | BuiltInKind Text deriving (Int -> ParamKind -> ShowS
[ParamKind] -> ShowS
ParamKind -> String
(Int -> ParamKind -> ShowS)
-> (ParamKind -> String)
-> ([ParamKind] -> ShowS)
-> Show ParamKind
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ParamKind -> ShowS
showsPrec :: Int -> ParamKind -> ShowS
$cshow :: ParamKind -> String
show :: ParamKind -> String
$cshowList :: [ParamKind] -> ShowS
showList :: [ParamKind] -> ShowS
Show)

data ParamData = ParamData
  { ParamData -> Text
pType :: Text,
    ParamData -> ParamKind
index :: ParamKind
  }
  deriving (Int -> ParamData -> ShowS
[ParamData] -> ShowS
ParamData -> String
(Int -> ParamData -> ShowS)
-> (ParamData -> String)
-> ([ParamData] -> ShowS)
-> Show ParamData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ParamData -> ShowS
showsPrec :: Int -> ParamData -> ShowS
$cshow :: ParamData -> String
show :: ParamData -> String
$cshowList :: [ParamData] -> ShowS
showList :: [ParamData] -> ShowS
Show)

newtype Params = Params [ParamData] deriving newtype (NonEmpty Params -> Params
Params -> Params -> Params
(Params -> Params -> Params)
-> (NonEmpty Params -> Params)
-> (forall b. Integral b => b -> Params -> Params)
-> Semigroup Params
forall b. Integral b => b -> Params -> Params
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: Params -> Params -> Params
<> :: Params -> Params -> Params
$csconcat :: NonEmpty Params -> Params
sconcat :: NonEmpty Params -> Params
$cstimes :: forall b. Integral b => b -> Params -> Params
stimes :: forall b. Integral b => b -> Params -> Params
Semigroup, Int -> Params -> ShowS
[Params] -> ShowS
Params -> String
(Int -> Params -> ShowS)
-> (Params -> String) -> ([Params] -> ShowS) -> Show Params
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Params -> ShowS
showsPrec :: Int -> Params -> ShowS
$cshow :: Params -> String
show :: Params -> String
$cshowList :: [Params] -> ShowS
showList :: [Params] -> ShowS
Show)

data Value where
  Value :: Expr a -> Value

newtype Values = Values [Value] deriving newtype (NonEmpty Values -> Values
Values -> Values -> Values
(Values -> Values -> Values)
-> (NonEmpty Values -> Values)
-> (forall b. Integral b => b -> Values -> Values)
-> Semigroup Values
forall b. Integral b => b -> Values -> Values
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: Values -> Values -> Values
<> :: Values -> Values -> Values
$csconcat :: NonEmpty Values -> Values
sconcat :: NonEmpty Values -> Values
$cstimes :: forall b. Integral b => b -> Values -> Values
stimes :: forall b. Integral b => b -> Values -> Values
Semigroup)

class (Typeable (a GPU)) => ShaderParam a where
  collectParams :: Params
  default collectParams :: (GCollectParams (Rep (a Internal))) => Params
  collectParams = forall {k} (f :: k). GCollectParams f => Params
forall (f :: * -> *). GCollectParams f => Params
gCollectParams @(Rep (a Internal))

  paramDefinition :: ParamDefinition
  paramDefinition = Text -> Params -> ParamDefinition
StructParam ((Char -> Char) -> Text -> Text
T.map (\case Char
' ' -> Char
'_'; Char
n -> Char
n) (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ TypeRep -> String
forall a. Show a => a -> String
show (Proxy (a GPU) -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(a GPU)))) (forall (a :: * -> *). ShaderParam a => Params
collectParams @a)

  -- collectValues :: a -> Values
  -- default collectValues :: (Generic a, ShaderParam' (Rep (a ))) => a -> Values
  -- collectValues a = collectValues' (from a)

  dummyParam :: a GPU
  default dummyParam :: (Generic (a GPU), GDummyParam (Rep (a Internal)) (Rep (a GPU))) => a GPU
  dummyParam = Rep (a GPU) (ZonkAny 0) -> a GPU
forall a x. Generic a => Rep a x -> a
forall x. Rep (a GPU) x -> a GPU
to (forall {k} {k} (f :: k) (g :: k -> *) (p :: k).
GDummyParam f g =>
g p
forall (f :: * -> *) (g :: * -> *) p. GDummyParam f g => g p
gDummyParam @(Rep (a Internal)) @(Rep (a GPU)))

  collectValues :: a GPU -> Values
  default collectValues :: (Generic (a GPU), GCollectValues (Rep (a GPU))) => a GPU -> Values
  collectValues a GPU
a = Rep (a GPU) (ZonkAny 1) -> Values
forall p. Rep (a GPU) p -> Values
forall {k} (f :: k -> *) (p :: k).
GCollectValues f =>
f p -> Values
gCollectValues (a GPU -> Rep (a GPU) (ZonkAny 1)
forall x. a GPU -> Rep (a GPU) x
forall a x. Generic a => a -> Rep a x
from a GPU
a)

class CollectParam a where
  collectParam :: ParamData
  getName' :: Text
  getType' :: Text -> Text

class GCollectParams f where
  gCollectParams :: Params

instance GCollectParams V1 where
  gCollectParams :: Params
gCollectParams = Params
forall a. HasCallStack => a
undefined

instance GCollectParams U1 where
  gCollectParams :: Params
gCollectParams = [ParamData] -> Params
Params []

instance (GCollectParams f, GCollectParams g) => GCollectParams (f :*: g) where
  gCollectParams :: Params
gCollectParams = forall {k} (f :: k). GCollectParams f => Params
forall (f :: k -> *). GCollectParams f => Params
gCollectParams @f Params -> Params -> Params
forall a. Semigroup a => a -> a -> a
<> forall {k} (f :: k). GCollectParams f => Params
forall (f :: k -> *). GCollectParams f => Params
gCollectParams @g

instance (CollectParam c) => GCollectParams (K1 i c) where
  gCollectParams :: Params
gCollectParams = [ParamData] -> Params
Params [forall a. CollectParam a => ParamData
forall {k} (a :: k). CollectParam a => ParamData
collectParam @c]

instance (GCollectParams f) => GCollectParams (M1 i t f) where
  gCollectParams :: Params
gCollectParams = forall {k} (f :: k). GCollectParams f => Params
forall (f :: k -> *). GCollectParams f => Params
gCollectParams @f

instance (KnownSymbol s, SingI (Primitive a)) => CollectParam (BuiltInParam s (Expr (Primitive a))) where
  collectParam :: ParamData
collectParam = ParamData {pType :: Text
pType = Expr ('Primitive a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('Primitive a)
forall a. HasCallStack => a
undefined :: Expr (Primitive a)), index :: ParamKind
index = Text -> ParamKind
BuiltInKind (Text -> ParamKind) -> Text -> ParamKind
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s)}
  getName' :: Text
getName' = Text
""

  getType' :: Text -> Text
getType' Text
"" = Text
"@builtin(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('Primitive a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('Primitive a)
forall a. HasCallStack => a
undefined :: Expr (Primitive a))
  getType' Text
n = Text
"@builtin(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('Primitive a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('Primitive a)
forall a. HasCallStack => a
undefined :: Expr (Primitive a))

instance (KnownSymbol s, SingI (VectorType m a)) => CollectParam (BuiltInParam s (Expr (VectorType m a))) where
  collectParam :: ParamData
collectParam = ParamData {pType :: Text
pType = Expr ('VectorType m a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('VectorType m a)
forall a. HasCallStack => a
undefined :: Expr (VectorType m a)), index :: ParamKind
index = Text -> ParamKind
BuiltInKind (Text -> ParamKind) -> Text -> ParamKind
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s)}
  getName' :: Text
getName' = Text
""
  getType' :: Text -> Text
getType' Text
"" = Text
"@builtin(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('VectorType m a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('VectorType m a)
forall a. HasCallStack => a
undefined :: Expr (VectorType m a))
  getType' Text
n = Text
"@builtin(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('VectorType m a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('VectorType m a)
forall a. HasCallStack => a
undefined :: Expr (VectorType m a))

instance (KnownSymbol s, SingI (ArrayType a)) => CollectParam (BuiltInParam s (Expr (ArrayType a))) where
  collectParam :: ParamData
collectParam = ParamData {pType :: Text
pType = Expr ('ArrayType a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('ArrayType a)
forall a. HasCallStack => a
undefined :: Expr (ArrayType a)), index :: ParamKind
index = Text -> ParamKind
BuiltInKind (Text -> ParamKind) -> Text -> ParamKind
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s)}
  getName' :: Text
getName' = Text
""
  getType' :: Text -> Text
getType' Text
"" = Text
"@builtin(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('ArrayType a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('ArrayType a)
forall a. HasCallStack => a
undefined :: Expr (ArrayType a))
  getType' Text
n = Text
"@builtin(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('ArrayType a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('ArrayType a)
forall a. HasCallStack => a
undefined :: Expr (ArrayType a))

instance (KnownNat n, SingI (Primitive a)) => CollectParam (LocationParam n (Expr (Primitive a))) where
  collectParam :: ParamData
collectParam = ParamData {pType :: Text
pType = Expr ('Primitive a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('Primitive a)
forall a. HasCallStack => a
undefined :: Expr (Primitive a)), index :: ParamKind
index = Integer -> ParamKind
LocKind (Integer -> ParamKind) -> Integer -> ParamKind
forall a b. (a -> b) -> a -> b
$ Integer -> Integer
forall a. Num a => Integer -> a
fromInteger (Integer -> Integer) -> Integer -> Integer
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)}
  getName' :: Text
getName' = Text
""
  getType' :: Text -> Text
getType' Text
"" = Text
"@location(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Integer -> String
forall a. Show a => a -> String
show (Integer -> String) -> Integer -> String
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('Primitive a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('Primitive a)
forall a. HasCallStack => a
undefined :: Expr (Primitive a))
  getType' Text
n = Text
"@location(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Integer -> String
forall a. Show a => a -> String
show (Integer -> String) -> Integer -> String
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('Primitive a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('Primitive a)
forall a. HasCallStack => a
undefined :: Expr (Primitive a))

instance (KnownNat n, SingI (VectorType m a)) => CollectParam (LocationParam n (Expr (VectorType m a))) where
  collectParam :: ParamData
collectParam = ParamData {pType :: Text
pType = Expr ('VectorType m a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('VectorType m a)
forall a. HasCallStack => a
undefined :: Expr (VectorType m a)), index :: ParamKind
index = Integer -> ParamKind
LocKind (Integer -> ParamKind) -> Integer -> ParamKind
forall a b. (a -> b) -> a -> b
$ Integer -> Integer
forall a. Num a => Integer -> a
fromInteger (Integer -> Integer) -> Integer -> Integer
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)}
  getName' :: Text
getName' = Text
""
  getType' :: Text -> Text
getType' Text
"" = Text
"@location(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Integer -> String
forall a. Show a => a -> String
show (Integer -> String) -> Integer -> String
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('VectorType m a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('VectorType m a)
forall a. HasCallStack => a
undefined :: Expr (VectorType m a))
  getType' Text
n = Text
"@location(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Integer -> String
forall a. Show a => a -> String
show (Integer -> String) -> Integer -> String
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('VectorType m a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('VectorType m a)
forall a. HasCallStack => a
undefined :: Expr (VectorType m a))

instance (KnownNat n, SingI (ArrayType a)) => CollectParam (LocationParam n (Expr (ArrayType a))) where
  collectParam :: ParamData
collectParam = ParamData {pType :: Text
pType = Expr ('ArrayType a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('ArrayType a)
forall a. HasCallStack => a
undefined :: Expr (ArrayType a)), index :: ParamKind
index = Integer -> ParamKind
LocKind (Integer -> ParamKind) -> Integer -> ParamKind
forall a b. (a -> b) -> a -> b
$ Integer -> Integer
forall a. Num a => Integer -> a
fromInteger (Integer -> Integer) -> Integer -> Integer
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)}
  getName' :: Text
getName' = Text
""
  getType' :: Text -> Text
getType' Text
"" = Text
"@location(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Integer -> String
forall a. Show a => a -> String
show (Integer -> String) -> Integer -> String
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('ArrayType a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('ArrayType a)
forall a. HasCallStack => a
undefined :: Expr (ArrayType a))
  getType' Text
n = Text
"@location(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Integer -> String
forall a. Show a => a -> String
show (Integer -> String) -> Integer -> String
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Expr ('ArrayType a) -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr ('ArrayType a)
forall a. HasCallStack => a
undefined :: Expr (ArrayType a))

class DummyParam a b where
  dummyParam' :: b

class GDummyParam f g where
  gDummyParam :: g p

instance GDummyParam V1 V1 where
  gDummyParam :: forall (p :: k). V1 p
gDummyParam = V1 p
forall a. HasCallStack => a
undefined

instance GDummyParam U1 U1 where
  gDummyParam :: forall (p :: k). U1 p
gDummyParam = U1 p
forall k (p :: k). U1 p
U1

instance (GDummyParam f1 g1, GDummyParam f2 g2) => GDummyParam (f1 :*: f2) (g1 :*: g2) where
  gDummyParam :: forall (p :: k). (:*:) g1 g2 p
gDummyParam = forall {k} {k} (f :: k) (g :: k -> *) (p :: k).
GDummyParam f g =>
g p
forall (f :: k -> *) (g :: k -> *) (p :: k). GDummyParam f g => g p
gDummyParam @f1 @g1 g1 p -> g2 p -> (:*:) g1 g2 p
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: forall {k} {k} (f :: k) (g :: k -> *) (p :: k).
GDummyParam f g =>
g p
forall (f :: k -> *) (g :: k -> *) (p :: k). GDummyParam f g => g p
gDummyParam @f2 @g2

instance (DummyParam a b) => GDummyParam (K1 i a) (K1 i b) where
  gDummyParam :: forall (p :: k). K1 i b p
gDummyParam = b -> K1 i b p
forall k i c (p :: k). c -> K1 i c p
K1 (b -> K1 i b p) -> b -> K1 i b p
forall a b. (a -> b) -> a -> b
$ forall {k} (a :: k) b. DummyParam a b => b
forall a b. DummyParam a b => b
dummyParam' @a @b

instance (GDummyParam a b) => GDummyParam (M1 i t a) (M1 i' t' b) where
  gDummyParam :: forall (p :: k). M1 i' t' b p
gDummyParam = b p -> M1 i' t' b p
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (b p -> M1 i' t' b p) -> b p -> M1 i' t' b p
forall a b. (a -> b) -> a -> b
$ forall {k} {k} (f :: k) (g :: k -> *) (p :: k).
GDummyParam f g =>
g p
forall (f :: k -> *) (g :: k -> *) (p :: k). GDummyParam f g => g p
gDummyParam @a @b

instance (KnownSymbol n, SingI b) => DummyParam (BuiltInParam n a) (Expr b) where
  dummyParam' :: Expr b
dummyParam' = Text -> Expr b
forall (a :: Types). SingI a => Text -> Expr a
BuiltInVar (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Proxy n -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy n -> String) -> Proxy n -> String
forall a b. (a -> b) -> a -> b
$ forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @n)

instance (KnownNat n, SingI b) => DummyParam (LocationParam n a) (Expr b) where
  dummyParam' :: Expr b
dummyParam' = Integer -> Expr b
forall (a :: Types). SingI a => Integer -> Expr a
LocationVar (Integer -> Integer
forall a. Num a => Integer -> a
fromInteger (Integer -> Integer) -> Integer -> Integer
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n -> Integer) -> Proxy n -> Integer
forall a b. (a -> b) -> a -> b
$ forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)

class GCollectValues f where
  gCollectValues :: f p -> Values

instance GCollectValues V1 where
  gCollectValues :: forall (p :: k). V1 p -> Values
gCollectValues V1 p
_ = Values
forall a. HasCallStack => a
undefined

instance GCollectValues U1 where
  gCollectValues :: forall (p :: k). U1 p -> Values
gCollectValues U1 p
_ = [Value] -> Values
Values []

instance (GCollectValues f, GCollectValues g) => GCollectValues (f :*: g) where
  gCollectValues :: forall (p :: k). (:*:) f g p -> Values
gCollectValues (f p
f :*: g p
g) = f p -> Values
forall (p :: k). f p -> Values
forall {k} (f :: k -> *) (p :: k).
GCollectValues f =>
f p -> Values
gCollectValues f p
f Values -> Values -> Values
forall a. Semigroup a => a -> a -> a
<> g p -> Values
forall (p :: k). g p -> Values
forall {k} (f :: k -> *) (p :: k).
GCollectValues f =>
f p -> Values
gCollectValues g p
g

instance GCollectValues (K1 i (Expr b)) where
  gCollectValues :: forall (p :: k). K1 i (Expr b) p -> Values
gCollectValues (K1 Expr b
c) = [Value] -> Values
Values [Expr b -> Value
forall (a :: Types). Expr a -> Value
Value Expr b
c]

instance (GCollectValues f) => GCollectValues (M1 i t f) where
  gCollectValues :: forall (p :: k). M1 i t f p -> Values
gCollectValues (M1 f p
f) = f p -> Values
forall (p :: k). f p -> Values
forall {k} (f :: k -> *) (p :: k).
GCollectValues f =>
f p -> Values
gCollectValues f p
f

-- instance (KnownNat n, Typeable (Location' n (Expr a) GPU)) => ShaderParam (Location' n (Expr a)) where
--   collectParams = undefined
--   getName = undefined
--   getType = undefined
--   dummyParam = undefined
--   collectValues a = Values [a]

newtype LocInternal n a f = Loc (Location f n a) deriving stock ((forall x. LocInternal n a f -> Rep (LocInternal n a f) x)
-> (forall x. Rep (LocInternal n a f) x -> LocInternal n a f)
-> Generic (LocInternal n a f)
forall (n :: Nat) a f x.
Rep (LocInternal n a f) x -> LocInternal n a f
forall (n :: Nat) a f x.
LocInternal n a f -> Rep (LocInternal n a f) x
forall x. Rep (LocInternal n a f) x -> LocInternal n a f
forall x. LocInternal n a f -> Rep (LocInternal n a f) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall (n :: Nat) a f x.
LocInternal n a f -> Rep (LocInternal n a f) x
from :: forall x. LocInternal n a f -> Rep (LocInternal n a f) x
$cto :: forall (n :: Nat) a f x.
Rep (LocInternal n a f) x -> LocInternal n a f
to :: forall x. Rep (LocInternal n a f) x -> LocInternal n a f
Generic)

instance
  ( SingI b,
    Typeable a,
    Location GPU n a ~ Expr b,
    KnownNat n,
    CollectParam (LocationParam n a),
    DummyParam
      (LocationParam n a)
      (Location GPU n a)
  ) =>
  ShaderParam (LocInternal n a)
  where
  paramDefinition :: ParamDefinition
paramDefinition = Text -> Text -> ParamDefinition
AnonParam (Text
"@location(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Integer -> String
forall a. Show a => a -> String
show (Integer -> String) -> Integer -> String
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n -> Integer) -> Proxy n -> Integer
forall a b. (a -> b) -> a -> b
$ forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")") (Expr b -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr b
forall a. HasCallStack => a
undefined :: Expr b))

  dummyParam :: LocInternal n a GPU
dummyParam = Location GPU n a -> LocInternal n a GPU
forall (n :: Nat) a f. Location f n a -> LocInternal n a f
Loc (Location GPU n a -> LocInternal n a GPU)
-> Location GPU n a -> LocInternal n a GPU
forall a b. (a -> b) -> a -> b
$ forall (a :: Types). Text -> Expr a
VarCustom @b Text
"input"

type Loc n a = LocInternal n a GPU

newtype BInInternal n a f = BIn (BuiltIn f n a) deriving stock ((forall x. BInInternal n a f -> Rep (BInInternal n a f) x)
-> (forall x. Rep (BInInternal n a f) x -> BInInternal n a f)
-> Generic (BInInternal n a f)
forall x. Rep (BInInternal n a f) x -> BInInternal n a f
forall x. BInInternal n a f -> Rep (BInInternal n a f) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (n :: Symbol) a f x.
Rep (BInInternal n a f) x -> BInInternal n a f
forall (n :: Symbol) a f x.
BInInternal n a f -> Rep (BInInternal n a f) x
$cfrom :: forall (n :: Symbol) a f x.
BInInternal n a f -> Rep (BInInternal n a f) x
from :: forall x. BInInternal n a f -> Rep (BInInternal n a f) x
$cto :: forall (n :: Symbol) a f x.
Rep (BInInternal n a f) x -> BInInternal n a f
to :: forall x. Rep (BInInternal n a f) x -> BInInternal n a f
Generic)

instance
  ( SingI b,
    Typeable a,
    BuiltIn GPU n a ~ Expr b,
    KnownSymbol n,
    CollectParam (BuiltInParam n a),
    DummyParam
      (BuiltInParam n a)
      (BuiltIn GPU n a)
  ) =>
  ShaderParam (BInInternal n a)
  where
  paramDefinition :: ParamDefinition
paramDefinition = Text -> Text -> ParamDefinition
AnonParam (Text
"@builtin(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Proxy n -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy n -> String) -> Proxy n -> String
forall a b. (a -> b) -> a -> b
$ forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @n) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")") (Expr b -> Text
forall (a :: Types). SingI a => Expr a -> Text
typeToWGSL (Expr b
forall a. HasCallStack => a
undefined :: Expr b))
  dummyParam :: BInInternal n a GPU
dummyParam = BuiltIn GPU n a -> BInInternal n a GPU
forall (n :: Symbol) a f. BuiltIn f n a -> BInInternal n a f
BIn (BuiltIn GPU n a -> BInInternal n a GPU)
-> BuiltIn GPU n a -> BInInternal n a GPU
forall a b. (a -> b) -> a -> b
$ forall (a :: Types). Text -> Expr a
VarCustom @b Text
"input"

type BIn n a = BInInternal n a GPU