module Indigo.Internal.Field
       ( AccessFieldC
       , fetchField
       , assignField
       
       , FieldLens (..)
       , flSFO
       
       , HasField (..)
       , fieldLensDeeper
       , fieldLensADT
       ) where
import Data.Vinyl (RElem)
import Data.Vinyl.Lens (rget, rput)
import Data.Vinyl.TypeLevel (RIndex)
import GHC.TypeLits (KnownSymbol)
import Indigo.Lorentz
import Indigo.Prelude
import qualified Lorentz.ADT as L
import Michelson.Typed.Haskell.Instr.Product
  (ConstructorFieldNames, GetFieldType, InstrGetFieldC, InstrSetFieldC)
type AccessFieldC a name =
  RElem name (ConstructorFieldNames a) (RIndex name (ConstructorFieldNames a))
fetchField
  :: forall a name f proxy . AccessFieldC a name
  => proxy name -> Rec f (ConstructorFieldNames a) -> f name
fetchField :: proxy name -> Rec f (ConstructorFieldNames a) -> f name
fetchField _ = forall (rs :: [Symbol]) (f :: Symbol -> *)
       (record :: (Symbol -> *) -> [Symbol] -> *).
(RecElem record name name rs rs (RIndex name rs),
 RecElemFCtx record f) =>
record f rs -> f name
forall k (r :: k) (rs :: [k]) (f :: k -> *)
       (record :: (k -> *) -> [k] -> *).
(RecElem record r r rs rs (RIndex r rs), RecElemFCtx record f) =>
record f rs -> f r
rget @name
assignField
  :: forall a name f proxy . AccessFieldC a name
  => proxy name -> f name -> Rec f (ConstructorFieldNames a) -> Rec f (ConstructorFieldNames a)
assignField :: proxy name
-> f name
-> Rec f (ConstructorFieldNames a)
-> Rec f (ConstructorFieldNames a)
assignField _ = forall (rs :: [Symbol]) (record :: (Symbol -> *) -> [Symbol] -> *)
       (f :: Symbol -> *).
(RecElem record name name rs rs (RIndex name rs),
 RecElemFCtx record f) =>
f name -> record f rs -> record f rs
forall k (r :: k) (rs :: [k]) (record :: (k -> *) -> [k] -> *)
       (f :: k -> *).
(RecElem record r r rs rs (RIndex r rs), RecElemFCtx record f) =>
f r -> record f rs -> record f rs
rput @name
data FieldLens dt fname ftype where
  
  
  
  
  
  TargetField
    :: ( InstrGetFieldC dt fname
       , InstrSetFieldC dt fname
       , GetFieldType dt fname ~ targetFType
       , AccessFieldC dt fname
       )
    => Label fname
    -> StoreFieldOps dt targetFName targetFType
    -> FieldLens dt targetFName targetFType
  
  
  
  
  
  
  DeeperField
    :: ( AccessFieldC dt fname
       , InstrSetFieldC dt fname
       , HasField (GetFieldType dt fname) targetFName targetFType
       )
    => Label fname
    -> StoreFieldOps dt targetFName targetFType
    -> FieldLens dt targetFName targetFType
flSFO :: FieldLens dt fname ftype -> StoreFieldOps dt fname ftype
flSFO :: FieldLens dt fname ftype -> StoreFieldOps dt fname ftype
flSFO (TargetField _ sfo :: StoreFieldOps dt fname ftype
sfo) = StoreFieldOps dt fname ftype
sfo
flSFO (DeeperField _ sfo :: StoreFieldOps dt fname ftype
sfo) = StoreFieldOps dt fname ftype
sfo
class (KnownValue ftype, KnownValue dt) => HasField dt fname ftype | dt fname -> ftype  where
  fieldLens :: FieldLens dt fname ftype
fieldLensADT
  :: forall dt targetFName targetFType fname  .
  ( InstrGetFieldC dt fname
  , InstrSetFieldC dt fname
  , GetFieldType dt fname ~ targetFType
  , AccessFieldC dt fname
  )
 => Label fname -> FieldLens dt targetFName targetFType
fieldLensADT :: Label fname -> FieldLens dt targetFName targetFType
fieldLensADT lb :: Label fname
lb =
  let sfo :: StoreFieldOps dt fname targetFType
sfo = forall ftype.
HasFieldOfType dt fname ftype =>
StoreFieldOps dt fname ftype
forall dt (fname :: Symbol) ftype.
HasFieldOfType dt fname ftype =>
StoreFieldOps dt fname ftype
storeFieldOpsADT @dt @fname in
  Label fname
-> StoreFieldOps dt targetFName targetFType
-> FieldLens dt targetFName targetFType
forall dt (fname :: Symbol) targetFType (targetFName :: Symbol).
(InstrGetFieldC dt fname, InstrSetFieldC dt fname,
 GetFieldType dt fname ~ targetFType, AccessFieldC dt fname) =>
Label fname
-> StoreFieldOps dt targetFName targetFType
-> FieldLens dt targetFName targetFType
TargetField Label fname
lb (StoreFieldOps dt targetFName targetFType
 -> FieldLens dt targetFName targetFType)
-> StoreFieldOps dt targetFName targetFType
-> FieldLens dt targetFName targetFType
forall a b. (a -> b) -> a -> b
$ Label fname
-> StoreFieldOps dt fname targetFType
-> StoreFieldOps dt targetFName targetFType
forall (name :: Symbol) storage field (desiredName :: Symbol).
Label name
-> StoreFieldOps storage name field
-> StoreFieldOps storage desiredName field
storeFieldOpsReferTo Label fname
lb StoreFieldOps dt fname targetFType
sfo
fieldLensDeeper
  :: forall dt targetName targetType fname .
  ( AccessFieldC dt fname
  , L.HasFieldOfType dt fname (GetFieldType dt fname)
  , HasField (GetFieldType dt fname) targetName targetType
  )
  => Label fname
  -> FieldLens dt targetName targetType
fieldLensDeeper :: Label fname -> FieldLens dt targetName targetType
fieldLensDeeper lb :: Label fname
lb =
  Label fname
-> StoreFieldOps dt targetName targetType
-> FieldLens dt targetName targetType
forall dt (fname :: Symbol) (targetFName :: Symbol) targetFType.
(AccessFieldC dt fname, InstrSetFieldC dt fname,
 HasField (GetFieldType dt fname) targetFName targetFType) =>
Label fname
-> StoreFieldOps dt targetFName targetFType
-> FieldLens dt targetFName targetFType
DeeperField Label fname
lb (Label fname
-> StoreFieldOps
     dt
     fname
     (LnrFieldType
        (LNRequireFound fname dt (GLookupNamed fname (Rep dt))))
-> StoreFieldOps
     (LnrFieldType
        (LNRequireFound fname dt (GLookupNamed fname (Rep dt))))
     targetName
     targetType
-> StoreFieldOps dt targetName targetType
forall (nameInStore :: Symbol) store substore
       (nameInSubstore :: Symbol) field.
Label nameInStore
-> StoreFieldOps store nameInStore substore
-> StoreFieldOps substore nameInSubstore field
-> StoreFieldOps store nameInSubstore field
composeStoreFieldOps Label fname
lb (forall dt (fname :: Symbol) ftype.
HasFieldOfType dt fname ftype =>
StoreFieldOps dt fname ftype
forall (fname :: Symbol) ftype.
HasFieldOfType dt fname ftype =>
StoreFieldOps dt fname ftype
storeFieldOpsADT @dt) (FieldLens
  (LnrFieldType
     (LNRequireFound fname dt (GLookupNamed fname (Rep dt))))
  targetName
  targetType
-> StoreFieldOps
     (LnrFieldType
        (LNRequireFound fname dt (GLookupNamed fname (Rep dt))))
     targetName
     targetType
forall dt (fname :: Symbol) ftype.
FieldLens dt fname ftype -> StoreFieldOps dt fname ftype
flSFO FieldLens
  (LnrFieldType
     (LNRequireFound fname dt (GLookupNamed fname (Rep dt))))
  targetName
  targetType
forall dt (fname :: Symbol) ftype.
HasField dt fname ftype =>
FieldLens dt fname ftype
fieldLens))
instance {-# OVERLAPPABLE #-}
         ( InstrSetFieldC dt fname
         , InstrGetFieldC dt fname
         , GetFieldType dt fname ~ ftype
         , AccessFieldC dt fname
         , KnownSymbol fname
         , KnownValue ftype, KnownValue dt
         )
         => HasField dt fname ftype where
  fieldLens :: FieldLens dt fname ftype
fieldLens = Label fname
-> StoreFieldOps dt fname ftype -> FieldLens dt fname ftype
forall dt (fname :: Symbol) targetFType (targetFName :: Symbol).
(InstrGetFieldC dt fname, InstrSetFieldC dt fname,
 GetFieldType dt fname ~ targetFType, AccessFieldC dt fname) =>
Label fname
-> StoreFieldOps dt targetFName targetFType
-> FieldLens dt targetFName targetFType
TargetField (KnownSymbol fname => Label fname
forall (name :: Symbol). KnownSymbol name => Label name
Label @fname) StoreFieldOps dt fname ftype
forall dt (fname :: Symbol) ftype.
HasFieldOfType dt fname ftype =>
StoreFieldOps dt fname ftype
storeFieldOpsADT