{-# LANGUAGE FunctionalDependencies #-}
module Lorentz.ReferencedByName
(
HasNamedVar
, HasNamedVars
, (:=)
, dupL
, dupLNamed
, VarIsUnnamed
) where
import Data.Constraint ((\\))
import Data.Singletons (Sing)
import Lorentz.ADT
import Lorentz.Base
import Lorentz.Coercions
import Lorentz.Constraints
import Lorentz.Instr
import Morley.Michelson.Text
import Morley.Michelson.Typed
import Morley.Util.Label
import Morley.Util.Named
import Morley.Util.Peano
import Morley.Util.Type
import Morley.Util.TypeLits
type family StackElemNotFound name :: ErrorMessage where
StackElemNotFound name =
'Text "Element with name `" ':<>: 'ShowType name ':<>:
'Text "` is not present on stack"
data NamedVariableNotFound name
data VarNamed = VarNamed Symbol | VarUnnamed | VarNameDummy
type family VarName (a :: Type) :: VarNamed where
VarName (NamedF _ _ name) = 'VarNamed name
VarName _ = 'VarUnnamed
type family AnyVN :: VarNamed
type family Assert (vn :: VarNamed) (err :: Constraint) :: VarNamed where
Assert 'VarNameDummy _ = AnyVN
Assert vn _ = vn
type family VarNamePretty' (x :: Type) (vn :: VarNamed) :: VarNamed where
VarNamePretty' x vn = Assert vn
(TypeError
('Text "Not clear which name `" ':<>: 'ShowType x ':<>: 'Text "` variable has" ':$$:
'Text "Consider adding `VarIsUnnamed " ':<>: 'ShowType x ':<>: 'Text "` constraint" ':$$:
'Text "or carrying a named variable instead"
)
)
type VarNamePretty x = VarNamePretty' x (VarName x)
type VarIsUnnamed x = VarName x ~ 'VarUnnamed
class HasNamedVar (s :: [Type]) (name :: Symbol) (var :: Type)
| s name -> var where
varPosition :: VarPosition s name var
type ConstraintVarPosition s n =
( SingI n, n > 'Z ~ 'True
, RequireLongerOrSameLength s n, RequireLongerOrSameLength (ToTs s) n
)
data VarPosition (s :: [Type]) (name :: Symbol) (var :: Type) where
VarPosition
:: (ConstraintVarPosition s n)
=> (Sing (n :: Nat))
-> VarPosition s name var
instance ( TypeError (StackElemNotFound name)
, var ~ NamedVariableNotFound name
) =>
HasNamedVar '[] name var where
varPosition :: VarPosition '[] name var
varPosition = Text -> VarPosition '[] name var
forall a. HasCallStack => Text -> a
error Text
"impossible"
instance ( ElemHasNamedVar (ty : s) name var
(VarNamePretty ty == 'VarNamed name)
) =>
HasNamedVar (ty : s) name var where
varPosition :: VarPosition (ty : s) name var
varPosition = ElemHasNamedVar
(ty : s) name var (VarNamePretty ty == 'VarNamed name) =>
VarPosition (ty : s) name var
forall (s :: [*]) (name :: Symbol) var (nameMatch :: Bool).
ElemHasNamedVar s name var nameMatch =>
VarPosition s name var
elemVarPosition @(ty : s) @name @var @(VarNamePretty ty == 'VarNamed name)
class ElemHasNamedVar s name var (nameMatch :: Bool)
| s name nameMatch -> var where
elemVarPosition :: VarPosition s name var
instance (ty ~ NamedF f var name) =>
ElemHasNamedVar (ty : s) name var 'True where
elemVarPosition :: VarPosition (ty : s) name var
elemVarPosition = Sing ('S 'Z) -> VarPosition (ty : s) name var
forall (s :: [*]) (n :: Nat) (name :: Symbol) var.
ConstraintVarPosition s n =>
Sing n -> VarPosition s name var
VarPosition (SingNat 'Z -> SingNat ('S 'Z)
forall (n1 :: Nat). SingNat n1 -> SingNat ('S n1)
SS SingNat 'Z
SZ)
instance (HasNamedVar s name var) =>
ElemHasNamedVar (ty : s) name var 'False where
elemVarPosition :: VarPosition (ty : s) name var
elemVarPosition = case HasNamedVar s name var => VarPosition s name var
forall (s :: [*]) (name :: Symbol) var.
HasNamedVar s name var =>
VarPosition s name var
varPosition @s @name @var of
VarPosition Sing n
n -> Sing ('S n) -> VarPosition (ty : s) name var
forall (s :: [*]) (n :: Nat) (name :: Symbol) var.
ConstraintVarPosition s n =>
Sing n -> VarPosition s name var
VarPosition (SingNat n -> SingNat ('S n)
forall (n1 :: Nat). SingNat n1 -> SingNat ('S n1)
SS Sing n
SingNat n
n)
type family HasNamedVars (s :: [Type]) (vs :: [NamedField]) :: Constraint where
HasNamedVars _ '[] = ()
HasNamedVars s ((n := ty) ': vs) = (HasNamedVar s n ty, HasNamedVars s vs)
unsafeDupL
:: forall n s var.
(ConstraintVarPosition s n, Dupable var)
=> Sing (n :: Nat) -> s :-> var : s
unsafeDupL :: Sing n -> s :-> (var : s)
unsafeDupL Sing n
_ =
forall a (inp :: [*]) (out :: [*]).
(ConstraintDUPNLorentz n inp out a, Dupable a) =>
inp :-> out
forall (n :: Nat) a (inp :: [*]) (out :: [*]).
(ConstraintDUPNLorentz n inp out a, Dupable a) =>
inp :-> out
dupNPeano @n
(((Take (Decrement n) s ++ (var : Drop n s)) ~ s) =>
s :-> (var : s))
-> Dict ((Take (Decrement n) s ++ (var : Drop n s)) ~ s)
-> s :-> (var : s)
forall (c :: Constraint) e r. HasDict c e => (c => r) -> e -> r
\\ MockableConstraint
((Take (Decrement n) s ++ (var : Drop n s)) ~ s) =>
Dict ((Take (Decrement n) s ++ (var : Drop n s)) ~ s)
forall (c :: Constraint). MockableConstraint c => Dict c
unsafeProvideConstraint @(Take (Decrement n) s ++ (var : Drop n s) ~ s)
(((Take (Decrement n) (ToTs s) ++ (ToT var : Drop n (ToTs s)))
~ ToTs s) =>
s :-> (var : s))
-> Dict
((Take (Decrement n) (ToTs s) ++ (ToT var : Drop n (ToTs s)))
~ ToTs s)
-> s :-> (var : s)
forall (c :: Constraint) e r. HasDict c e => (c => r) -> e -> r
\\ MockableConstraint
((Take (Decrement n) (ToTs s) ++ (ToT var : Drop n (ToTs s)))
~ ToTs s) =>
Dict
((Take (Decrement n) (ToTs s) ++ (ToT var : Drop n (ToTs s)))
~ ToTs s)
forall (c :: Constraint). MockableConstraint c => Dict c
unsafeProvideConstraint @(Take (Decrement n) (ToTs s) ++ (ToT var : Drop n (ToTs s)) ~ ToTs s)
dupLNamed
:: forall var name s.
(HasNamedVar s name var, Dupable var)
=> Label name -> s :-> (name :! var) : s
dupLNamed :: Label name -> s :-> ((name :! var) : s)
dupLNamed Label{} =
case HasNamedVar s name var => VarPosition s name var
forall (s :: [*]) (name :: Symbol) var.
HasNamedVar s name var =>
VarPosition s name var
varPosition @s @name @var of
VarPosition Sing n
sn -> Sing n -> s :-> ((name :! var) : s)
forall (n :: Nat) (s :: [*]) var.
(ConstraintVarPosition s n, Dupable var) =>
Sing n -> s :-> (var : s)
unsafeDupL Sing n
sn
dupL :: forall var name s.
(HasNamedVar s name var, Dupable var)
=> Label name -> s :-> var : s
dupL :: Label name -> s :-> (var : s)
dupL Label name
l = Label name -> s :-> ((name :! var) : s)
forall var (name :: Symbol) (s :: [*]).
(HasNamedVar s name var, Dupable var) =>
Label name -> s :-> ((name :! var) : s)
dupLNamed Label name
l (s :-> ((name :! var) : s))
-> (((name :! var) : s) :-> (var : s)) -> s :-> (var : s)
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# Label name -> ((name :! var) : s) :-> (var : s)
forall (name :: Symbol) a (s :: [*]).
Label name -> ((name :! a) : s) :-> (a : s)
fromNamed Label name
l
_dupSample1
:: [Integer, Natural, "a" :! (), "b" :! MText, "c" :! ByteString]
:-> [MText, Integer, Natural, "a" :! (), "b" :! MText, "c" :! ByteString]
_dupSample1 :: '[Integer, Natural, "a" :! (), "b" :! MText, "c" :! ByteString]
:-> '[MText, Integer, Natural, "a" :! (), "b" :! MText,
"c" :! ByteString]
_dupSample1 =
Label "b"
-> '[Integer, Natural, "a" :! (), "b" :! MText, "c" :! ByteString]
:-> '[MText, Integer, Natural, "a" :! (), "b" :! MText,
"c" :! ByteString]
forall var (name :: Symbol) (s :: [*]).
(HasNamedVar s name var, Dupable var) =>
Label name -> s :-> (var : s)
dupL IsLabel "b" (Label "b")
Label "b"
#b
_dupSample2
:: (HasNamedVar s "x" Natural)
=> (Integer : s)
:-> (Natural : Integer : s)
_dupSample2 :: (Integer : s) :-> (Natural : Integer : s)
_dupSample2 =
Label "x" -> (Integer : s) :-> (Natural : Integer : s)
forall var (name :: Symbol) (s :: [*]).
(HasNamedVar s name var, Dupable var) =>
Label name -> s :-> (var : s)
dupL IsLabel "x" (Label "x")
Label "x"
#x
_dupSample3
:: (HasNamedVar s "x" Natural, VarIsUnnamed store)
=> (store : s)
:-> (Natural : store : s)
_dupSample3 :: (store : s) :-> (Natural : store : s)
_dupSample3 =
Label "x" -> (store : s) :-> (Natural : store : s)
forall var (name :: Symbol) (s :: [*]).
(HasNamedVar s name var, Dupable var) =>
Label name -> s :-> (var : s)
dupL IsLabel "x" (Label "x")
Label "x"
#x