-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ

-- | Allows specifying entrypoints without declaring 'ParamterHasEntrypoints'
-- instance.
module Lorentz.Entrypoints.Manual
  ( ParameterWrapper (..)
  ) where

import qualified Data.Kind as Kind

import Lorentz.Constraints
import Lorentz.Entrypoints.Core
import Michelson.Typed
import Lorentz.Wrappable (Wrappable)

-- | Wrap parameter into this to locally assign a way to derive entrypoints for
-- it.
newtype ParameterWrapper (deriv :: Kind.Type) cp = ParameterWrapper { ParameterWrapper deriv cp -> cp
unParameterWraper :: cp }
  deriving stock (forall x.
 ParameterWrapper deriv cp -> Rep (ParameterWrapper deriv cp) x)
-> (forall x.
    Rep (ParameterWrapper deriv cp) x -> ParameterWrapper deriv cp)
-> Generic (ParameterWrapper deriv cp)
forall x.
Rep (ParameterWrapper deriv cp) x -> ParameterWrapper deriv cp
forall x.
ParameterWrapper deriv cp -> Rep (ParameterWrapper deriv cp) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall deriv cp x.
Rep (ParameterWrapper deriv cp) x -> ParameterWrapper deriv cp
forall deriv cp x.
ParameterWrapper deriv cp -> Rep (ParameterWrapper deriv cp) x
$cto :: forall deriv cp x.
Rep (ParameterWrapper deriv cp) x -> ParameterWrapper deriv cp
$cfrom :: forall deriv cp x.
ParameterWrapper deriv cp -> Rep (ParameterWrapper deriv cp) x
Generic
  deriving anyclass (WellTypedToT (ParameterWrapper deriv cp)
WellTypedToT (ParameterWrapper deriv cp) =>
(ParameterWrapper deriv cp
 -> Value (ToT (ParameterWrapper deriv cp)))
-> (Value (ToT (ParameterWrapper deriv cp))
    -> ParameterWrapper deriv cp)
-> IsoValue (ParameterWrapper deriv cp)
Value (ToT (ParameterWrapper deriv cp))
-> ParameterWrapper deriv cp
ParameterWrapper deriv cp
-> Value (ToT (ParameterWrapper deriv cp))
forall a.
WellTypedToT a =>
(a -> Value (ToT a)) -> (Value (ToT a) -> a) -> IsoValue a
forall deriv cp.
IsoValue cp =>
WellTypedToT (ParameterWrapper deriv cp)
forall deriv cp.
IsoValue cp =>
Value (ToT (ParameterWrapper deriv cp))
-> ParameterWrapper deriv cp
forall deriv cp.
IsoValue cp =>
ParameterWrapper deriv cp
-> Value (ToT (ParameterWrapper deriv cp))
fromVal :: Value (ToT (ParameterWrapper deriv cp))
-> ParameterWrapper deriv cp
$cfromVal :: forall deriv cp.
IsoValue cp =>
Value (ToT (ParameterWrapper deriv cp))
-> ParameterWrapper deriv cp
toVal :: ParameterWrapper deriv cp
-> Value (ToT (ParameterWrapper deriv cp))
$ctoVal :: forall deriv cp.
IsoValue cp =>
ParameterWrapper deriv cp
-> Value (ToT (ParameterWrapper deriv cp))
$cp1IsoValue :: forall deriv cp.
IsoValue cp =>
WellTypedToT (ParameterWrapper deriv cp)
IsoValue, ToT (ParameterWrapper deriv cp)
~ ToT (Unwrappable (ParameterWrapper deriv cp))
(ToT (ParameterWrapper deriv cp)
 ~ ToT (Unwrappable (ParameterWrapper deriv cp))) =>
Wrappable (ParameterWrapper deriv cp)
forall s. (ToT s ~ ToT (Unwrappable s)) => Wrappable s
forall deriv cp.
ToT (ParameterWrapper deriv cp)
~ ToT (Unwrappable (ParameterWrapper deriv cp))
Wrappable)

-- Helper for implementing @instance ParameterHasEntrypoints ParameterWrapper@.
data PwDeriv deriv
instance EntrypointsDerivation deriv cp =>
         EntrypointsDerivation (PwDeriv deriv) (ParameterWrapper deriv cp) where
  type EpdAllEntrypoints (PwDeriv deriv) (ParameterWrapper deriv cp) =
    EpdAllEntrypoints deriv cp
  type EpdLookupEntrypoint (PwDeriv deriv) (ParameterWrapper deriv cp) =
    EpdLookupEntrypoint deriv cp
  epdNotes :: (Notes (ToT (ParameterWrapper deriv cp)), RootAnn)
epdNotes = EntrypointsDerivation deriv cp => (Notes (ToT cp), RootAnn)
forall k (deriv :: k) cp.
EntrypointsDerivation deriv cp =>
(Notes (ToT cp), RootAnn)
epdNotes @deriv @cp
  epdCall :: Label name
-> EpConstructionRes
     (ToT (ParameterWrapper deriv cp))
     (Eval
        (EpdLookupEntrypoint
           (PwDeriv deriv) (ParameterWrapper deriv cp) name))
epdCall = forall (name :: Symbol).
(EntrypointsDerivation deriv cp, ParameterScope (ToT cp)) =>
Label name
-> EpConstructionRes
     (ToT cp) (Eval (EpdLookupEntrypoint deriv cp name))
forall k (deriv :: k) cp (name :: Symbol).
(EntrypointsDerivation deriv cp, ParameterScope (ToT cp)) =>
Label name
-> EpConstructionRes
     (ToT cp) (Eval (EpdLookupEntrypoint deriv cp name))
epdCall @deriv @cp
  epdDescs :: Rec
  EpCallingDesc
  (EpdAllEntrypoints (PwDeriv deriv) (ParameterWrapper deriv cp))
epdDescs = EntrypointsDerivation deriv cp =>
Rec EpCallingDesc (EpdAllEntrypoints deriv cp)
forall k (deriv :: k) cp.
EntrypointsDerivation deriv cp =>
Rec EpCallingDesc (EpdAllEntrypoints deriv cp)
epdDescs @deriv @cp

instance ( NiceParameter cp
         , EntrypointsDerivation epd cp
         , RequireAllUniqueEntrypoints' epd cp
         ) =>
         ParameterHasEntrypoints (ParameterWrapper epd cp) where
  type ParameterEntrypointsDerivation (ParameterWrapper epd cp) = PwDeriv epd