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

{-# OPTIONS_GHC -Wno-redundant-constraints #-}

-- | Strictly typed statements of Indigo language.

module Indigo.Backend
  ( module ReExports

  -- * Loop
  , forEach
  , while
  , whileLeft

  -- * Contract call
  , selfCalling
  , contractCalling

  -- * Documentation
  , doc
  , docGroup
  , docStorage
  , contractName
  , finalizeParamCallingDoc
  , contractGeneral
  , contractGeneralDefault

  -- * Side-effects
  , transferTokens
  , setDelegate

  -- * Functions, Procedures and Scopes
  , scope

  -- * Comments
  , comment

  -- * Conversion from Lorentz
  , fromLorentzFun1
  , fromLorentzFun2
  , fromLorentzFun3
  , fromLorentzFun1Void
  , fromLorentzFun2Void
  , fromLorentzFun3Void
  ) where

import Indigo.Backend.Case as ReExports
import Indigo.Backend.Conditional as ReExports
import Indigo.Backend.Error as ReExports
import Indigo.Backend.Lambda as ReExports
import Indigo.Backend.Scope as ReExports
import Indigo.Backend.Var as ReExports

import Indigo.Backend.Prelude
import Indigo.FromLorentz
import Indigo.Internal
import Indigo.Lorentz
import qualified Lorentz.Doc as L
import qualified Lorentz.EntryPoints.Doc as L (finalizeParamCallingDoc)
import Lorentz.EntryPoints.Helpers (RequireSumType)
import qualified Lorentz.Instr as L
import qualified Michelson.Typed as MT
import Util.Type (type (++))

----------------------------------------------------------------------------
-- Loop
----------------------------------------------------------------------------

-- | While statement. The same rule about releasing.
while :: forall inp xs ex . ex :~> Bool => ex -> IndigoState inp xs () -> IndigoState inp inp ()
while :: ex -> IndigoState inp xs () -> IndigoState inp inp ()
while e :: ex
e body :: IndigoState inp xs ()
body = (MetaData inp -> GenCode inp inp ()) -> IndigoState inp inp ()
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState ((MetaData inp -> GenCode inp inp ()) -> IndigoState inp inp ())
-> (MetaData inp -> GenCode inp inp ()) -> IndigoState inp inp ()
forall a b. (a -> b) -> a -> b
$ \md :: MetaData inp
md ->
  let expCd :: inp :-> (Bool & inp)
expCd = GenCode inp (Bool & inp) () -> inp :-> (Bool & inp)
forall (inp :: [*]) (out :: [*]) a.
GenCode inp out a -> inp :-> out
gcCode (GenCode inp (Bool & inp) () -> inp :-> (Bool & inp))
-> GenCode inp (Bool & inp) () -> inp :-> (Bool & inp)
forall a b. (a -> b) -> a -> b
$ IndigoState inp (Bool & inp) ()
-> MetaData inp -> GenCode inp (Bool & inp) ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState (ex -> IndigoState inp (ExprType ex & inp) ()
forall a (inp :: [*]).
ToExpr a =>
a -> IndigoState inp (ExprType a & inp) ()
compileToExpr ex
e) MetaData inp
md in
  let bodyIndigoState :: inp :-> inp
bodyIndigoState = GenCode inp xs () -> inp :-> inp
forall (inp :: [*]) (out :: [*]) a.
GenCode inp out a -> inp :-> inp
cleanGenCode (GenCode inp xs () -> inp :-> inp)
-> GenCode inp xs () -> inp :-> inp
forall a b. (a -> b) -> a -> b
$ IndigoState inp xs () -> MetaData inp -> GenCode inp xs ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState IndigoState inp xs ()
body MetaData inp
md in
  ()
-> MetaData inp
-> (inp :-> inp)
-> (inp :-> inp)
-> GenCode inp inp ()
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode () MetaData inp
md (inp :-> (Bool & inp)
expCd (inp :-> (Bool & inp)) -> ((Bool & inp) :-> inp) -> inp :-> inp
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# (inp :-> (Bool & inp)) -> (Bool & inp) :-> inp
forall (s :: [*]). (s :-> (Bool & s)) -> (Bool & s) :-> s
L.loop (inp :-> inp
bodyIndigoState (inp :-> inp) -> (inp :-> (Bool & inp)) -> inp :-> (Bool & inp)
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# inp :-> (Bool & inp)
expCd)) inp :-> inp
forall (s :: [*]). s :-> s
L.nop

whileLeft
  :: forall inp xs ex l r .
     ( ex :~> Either l r
     , KnownValue l
     , KnownValue r
     )
  => ex
  -> (Var l -> IndigoState (l & inp) xs ())
  -> IndigoState inp (r & inp) (Var r)
whileLeft :: ex
-> (Var l -> IndigoState (l & inp) xs ())
-> IndigoState inp (r & inp) (Var r)
whileLeft e :: ex
e body :: Var l -> IndigoState (l & inp) xs ()
body = (MetaData inp -> GenCode inp (r & inp) (Var r))
-> IndigoState inp (r & inp) (Var r)
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState ((MetaData inp -> GenCode inp (r & inp) (Var r))
 -> IndigoState inp (r & inp) (Var r))
-> (MetaData inp -> GenCode inp (r & inp) (Var r))
-> IndigoState inp (r & inp) (Var r)
forall a b. (a -> b) -> a -> b
$ \md :: MetaData inp
md ->
  let
    cde :: inp :-> (Either l r & inp)
cde = GenCode inp (Either l r & inp) () -> inp :-> (Either l r & inp)
forall (inp :: [*]) (out :: [*]) a.
GenCode inp out a -> inp :-> out
gcCode (GenCode inp (Either l r & inp) () -> inp :-> (Either l r & inp))
-> GenCode inp (Either l r & inp) () -> inp :-> (Either l r & inp)
forall a b. (a -> b) -> a -> b
$ IndigoState inp (Either l r & inp) ()
-> MetaData inp -> GenCode inp (Either l r & inp) ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState (ex -> IndigoState inp (ExprType ex & inp) ()
forall a (inp :: [*]).
ToExpr a =>
a -> IndigoState inp (ExprType a & inp) ()
compileToExpr ex
e) MetaData inp
md
    (l :: Var l
l, newMd :: MetaData (l & inp)
newMd) = MetaData inp -> (Var l, MetaData (l & inp))
forall x (stk :: [*]).
KnownValue x =>
MetaData stk -> (Var x, MetaData (x & stk))
pushRefMd MetaData inp
md
    gc :: (l & inp) :-> (l & inp)
gc = GenCode (l & inp) xs () -> (l & inp) :-> (l & inp)
forall (inp :: [*]) (out :: [*]) a.
GenCode inp out a -> inp :-> inp
cleanGenCode (GenCode (l & inp) xs () -> (l & inp) :-> (l & inp))
-> GenCode (l & inp) xs () -> (l & inp) :-> (l & inp)
forall a b. (a -> b) -> a -> b
$ IndigoState (l & inp) xs ()
-> MetaData (l & inp) -> GenCode (l & inp) xs ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState (Var l -> IndigoState (l & inp) xs ()
body Var l
l) MetaData (l & inp)
newMd
    (r :: Var r
r, resMd :: MetaData (r & inp)
resMd) = MetaData inp -> (Var r, MetaData (r & inp))
forall x (stk :: [*]).
KnownValue x =>
MetaData stk -> (Var x, MetaData (x & stk))
pushRefMd MetaData inp
md
  in Var r
-> MetaData (r & inp)
-> (inp :-> (r & inp))
-> ((r & inp) :-> inp)
-> GenCode inp (r & inp) (Var r)
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode Var r
r MetaData (r & inp)
resMd (inp :-> (Either l r & inp)
cde (inp :-> (Either l r & inp))
-> ((Either l r & inp) :-> (r & inp)) -> inp :-> (r & inp)
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# ((l & inp) :-> (Either l r & inp))
-> (Either l r & inp) :-> (r & inp)
forall a (s :: [*]) b.
((a & s) :-> (Either a b & s)) -> (Either a b & s) :-> (b & s)
L.loopLeft ((l & inp) :-> (l & inp)
gc ((l & inp) :-> (l & inp))
-> ((l & inp) :-> inp) -> (l & inp) :-> inp
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# (l & inp) :-> inp
forall a (s :: [*]). (a & s) :-> s
L.drop ((l & inp) :-> inp)
-> (inp :-> (Either l r & inp)) -> (l & inp) :-> (Either l r & inp)
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# inp :-> (Either l r & inp)
cde)) (r & inp) :-> inp
forall a (s :: [*]). (a & s) :-> s
L.drop

-- | For statements to iterate over container.
forEach
  :: forall a e inp xs. (IterOpHs a, KnownValue (IterOpElHs a), e :~> a)
  => e -> (Var (IterOpElHs a) -> IndigoState ((IterOpElHs a) & inp) xs ())
  -> IndigoState inp inp ()
forEach :: e
-> (Var (IterOpElHs a) -> IndigoState (IterOpElHs a & inp) xs ())
-> IndigoState inp inp ()
forEach container :: e
container body :: Var (IterOpElHs a) -> IndigoState (IterOpElHs a & inp) xs ()
body = (MetaData inp -> GenCode inp inp ()) -> IndigoState inp inp ()
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState ((MetaData inp -> GenCode inp inp ()) -> IndigoState inp inp ())
-> (MetaData inp -> GenCode inp inp ()) -> IndigoState inp inp ()
forall a b. (a -> b) -> a -> b
$ \md :: MetaData inp
md ->
  let cde :: inp :-> (a & inp)
cde = GenCode inp (a & inp) () -> inp :-> (a & inp)
forall (inp :: [*]) (out :: [*]) a.
GenCode inp out a -> inp :-> out
gcCode (GenCode inp (a & inp) () -> inp :-> (a & inp))
-> GenCode inp (a & inp) () -> inp :-> (a & inp)
forall a b. (a -> b) -> a -> b
$ IndigoState inp (a & inp) ()
-> MetaData inp -> GenCode inp (a & inp) ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState (e -> IndigoState inp (ExprType e & inp) ()
forall a (inp :: [*]).
ToExpr a =>
a -> IndigoState inp (ExprType a & inp) ()
compileToExpr e
container) MetaData inp
md in
  let (var :: Var (IterOpElHs a)
var, newMd :: MetaData (IterOpElHs a & inp)
newMd) = MetaData inp -> (Var (IterOpElHs a), MetaData (IterOpElHs a & inp))
forall x (stk :: [*]).
KnownValue x =>
MetaData stk -> (Var x, MetaData (x & stk))
pushRefMd MetaData inp
md in
  let bodyIndigoState :: (IterOpElHs a & inp) :-> (IterOpElHs a & inp)
bodyIndigoState = GenCode (IterOpElHs a & inp) xs ()
-> (IterOpElHs a & inp) :-> (IterOpElHs a & inp)
forall (inp :: [*]) (out :: [*]) a.
GenCode inp out a -> inp :-> inp
cleanGenCode (GenCode (IterOpElHs a & inp) xs ()
 -> (IterOpElHs a & inp) :-> (IterOpElHs a & inp))
-> GenCode (IterOpElHs a & inp) xs ()
-> (IterOpElHs a & inp) :-> (IterOpElHs a & inp)
forall a b. (a -> b) -> a -> b
$ IndigoState (IterOpElHs a & inp) xs ()
-> MetaData (IterOpElHs a & inp)
-> GenCode (IterOpElHs a & inp) xs ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState (Var (IterOpElHs a) -> IndigoState (IterOpElHs a & inp) xs ()
body Var (IterOpElHs a)
var) MetaData (IterOpElHs a & inp)
newMd in
  ()
-> MetaData inp
-> (inp :-> inp)
-> (inp :-> inp)
-> GenCode inp inp ()
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode () MetaData inp
md (inp :-> (a & inp)
cde (inp :-> (a & inp)) -> ((a & inp) :-> inp) -> inp :-> inp
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# ((IterOpElHs a & inp) :-> inp) -> (a & inp) :-> inp
forall c (s :: [*]).
(IterOpHs c, HasCallStack) =>
((IterOpElHs c & s) :-> s) -> (c & s) :-> s
L.iter ((IterOpElHs a & inp) :-> (IterOpElHs a & inp)
bodyIndigoState ((IterOpElHs a & inp) :-> (IterOpElHs a & inp))
-> ((IterOpElHs a & inp) :-> inp) -> (IterOpElHs a & inp) :-> inp
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# (IterOpElHs a & inp) :-> inp
forall a (s :: [*]). (a & s) :-> s
L.drop)) inp :-> inp
forall (s :: [*]). s :-> s
L.nop

----------------------------------------------------------------------------
-- Documentation
----------------------------------------------------------------------------

-- | Put a document item.
doc :: DocItem di => di -> IndigoState s s ()
doc :: di -> IndigoState s s ()
doc di :: di
di = (MetaData s -> GenCode s s ()) -> IndigoState s s ()
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState \md :: MetaData s
md -> () -> MetaData s -> (s :-> s) -> (s :-> s) -> GenCode s s ()
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode () MetaData s
md (di -> s :-> s
forall di (s :: [*]). DocItem di => di -> s :-> s
L.doc di
di) s :-> s
forall (s :: [*]). s :-> s
L.nop

-- | Group documentation built in the given piece of code
-- into block dedicated to one thing, e.g. to one entrypoint.
docGroup :: DocGrouping -> IndigoState i o () -> IndigoState i o ()
docGroup :: DocGrouping -> IndigoState i o () -> IndigoState i o ()
docGroup gr :: DocGrouping
gr ii :: IndigoState i o ()
ii = (MetaData i -> GenCode i o ()) -> IndigoState i o ()
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState ((MetaData i -> GenCode i o ()) -> IndigoState i o ())
-> (MetaData i -> GenCode i o ()) -> IndigoState i o ()
forall a b. (a -> b) -> a -> b
$ \md :: MetaData i
md ->
  let GenCode _ mdii :: MetaData o
mdii cd :: i :-> o
cd clr :: o :-> i
clr = IndigoState i o () -> MetaData i -> GenCode i o ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState IndigoState i o ()
ii MetaData i
md in
  () -> MetaData o -> (i :-> o) -> (o :-> i) -> GenCode i o ()
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode () MetaData o
mdii (DocGrouping -> (i :-> o) -> i :-> o
forall (inp :: [*]) (out :: [*]).
DocGrouping -> (inp :-> out) -> inp :-> out
L.docGroup DocGrouping
gr i :-> o
cd) o :-> i
clr

-- | Insert documentation of the contract storage type. The type
-- should be passed using type applications.
docStorage :: forall storage s. TypeHasDoc storage => IndigoState s s ()
docStorage :: IndigoState s s ()
docStorage = (MetaData s -> GenCode s s ()) -> IndigoState s s ()
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState \md :: MetaData s
md -> () -> MetaData s -> (s :-> s) -> (s :-> s) -> GenCode s s ()
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode () MetaData s
md (forall (s :: [*]). TypeHasDoc storage => s :-> s
forall storage (s :: [*]). TypeHasDoc storage => s :-> s
L.docStorage @storage) s :-> s
forall (s :: [*]). s :-> s
L.nop

-- | Give a name to given contract. Apply it to the whole contract code.
contractName :: Text -> IndigoState i o () -> IndigoState i o ()
contractName :: Text -> IndigoState i o () -> IndigoState i o ()
contractName cName :: Text
cName b :: IndigoState i o ()
b = (MetaData i -> GenCode i o ()) -> IndigoState i o ()
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState ((MetaData i -> GenCode i o ()) -> IndigoState i o ())
-> (MetaData i -> GenCode i o ()) -> IndigoState i o ()
forall a b. (a -> b) -> a -> b
$ \md :: MetaData i
md ->
  let GenCode _ mdb :: MetaData o
mdb gc :: i :-> o
gc clr :: o :-> i
clr = IndigoState i o () -> MetaData i -> GenCode i o ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState IndigoState i o ()
b MetaData i
md in
  () -> MetaData o -> (i :-> o) -> (o :-> i) -> GenCode i o ()
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode () MetaData o
mdb (Text -> (i :-> o) -> i :-> o
forall (inp :: [*]) (out :: [*]).
Text -> (inp :-> out) -> inp :-> out
L.contractName Text
cName i :-> o
gc) o :-> i
clr

-- | Attach general info to given contract.
contractGeneral :: IndigoState i o () -> IndigoState i o ()
contractGeneral :: IndigoState i o () -> IndigoState i o ()
contractGeneral b :: IndigoState i o ()
b = (MetaData i -> GenCode i o ()) -> IndigoState i o ()
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState ((MetaData i -> GenCode i o ()) -> IndigoState i o ())
-> (MetaData i -> GenCode i o ()) -> IndigoState i o ()
forall a b. (a -> b) -> a -> b
$ \md :: MetaData i
md ->
  let GenCode _ mdb :: MetaData o
mdb gc :: i :-> o
gc clr :: o :-> i
clr = IndigoState i o () -> MetaData i -> GenCode i o ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState IndigoState i o ()
b MetaData i
md in
  () -> MetaData o -> (i :-> o) -> (o :-> i) -> GenCode i o ()
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode () MetaData o
mdb ((i :-> o) -> i :-> o
forall (inp :: [*]) (out :: [*]). (inp :-> out) -> inp :-> out
L.contractGeneral i :-> o
gc) o :-> i
clr

-- | Attach default general info to the contract documentation.
contractGeneralDefault :: IndigoState s s ()
contractGeneralDefault :: IndigoState s s ()
contractGeneralDefault =
  (MetaData s -> GenCode s s ()) -> IndigoState s s ()
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState \md :: MetaData s
md -> () -> MetaData s -> (s :-> s) -> (s :-> s) -> GenCode s s ()
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode () MetaData s
md s :-> s
forall (s :: [*]). s :-> s
L.contractGeneralDefault s :-> s
forall (s :: [*]). s :-> s
L.nop

-- | Indigo version for the function of the same name from Lorentz.
finalizeParamCallingDoc
  :: forall cp param inp out x. (param :~> cp, NiceParameterFull cp, RequireSumType cp, HasCallStack)
  => (Var cp -> IndigoState (cp & inp) out x)
  -> (param -> IndigoState inp out x)
finalizeParamCallingDoc :: (Var cp -> IndigoState (cp & inp) out x)
-> param -> IndigoState inp out x
finalizeParamCallingDoc act :: Var cp -> IndigoState (cp & inp) out x
act param :: param
param = (MetaData inp -> GenCode inp out x) -> IndigoState inp out x
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState ((MetaData inp -> GenCode inp out x) -> IndigoState inp out x)
-> (MetaData inp -> GenCode inp out x) -> IndigoState inp out x
forall a b. (a -> b) -> a -> b
$ \md :: MetaData inp
md ->
  let cde :: inp :-> (cp & inp)
cde = GenCode inp (cp & inp) () -> inp :-> (cp & inp)
forall (inp :: [*]) (out :: [*]) a.
GenCode inp out a -> inp :-> out
gcCode (GenCode inp (cp & inp) () -> inp :-> (cp & inp))
-> GenCode inp (cp & inp) () -> inp :-> (cp & inp)
forall a b. (a -> b) -> a -> b
$ IndigoState inp (cp & inp) ()
-> MetaData inp -> GenCode inp (cp & inp) ()
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState (param -> IndigoState inp (ExprType param & inp) ()
forall a (inp :: [*]).
ToExpr a =>
a -> IndigoState inp (ExprType a & inp) ()
compileToExpr param
param) MetaData inp
md in
  let (var :: Var cp
var, newMd :: MetaData (cp & inp)
newMd) = MetaData inp -> (Var cp, MetaData (cp & inp))
forall x (stk :: [*]).
KnownValue x =>
MetaData stk -> (Var x, MetaData (x & stk))
pushRefMd MetaData inp
md in
  let GenCode x :: x
x md1 :: MetaData out
md1 cd :: (cp & inp) :-> out
cd clr :: out :-> (cp & inp)
clr = IndigoState (cp & inp) out x
-> MetaData (cp & inp) -> GenCode (cp & inp) out x
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState (Var cp -> IndigoState (cp & inp) out x
act Var cp
var) MetaData (cp & inp)
newMd in
  x
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out x
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode x
x MetaData out
md1 (inp :-> (cp & inp)
cde (inp :-> (cp & inp)) -> ((cp & inp) :-> out) -> inp :-> out
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# ((cp & inp) :-> out) -> (cp & inp) :-> out
forall cp (inp :: [*]) (out :: [*]).
(NiceParameterFull cp, RequireSumType cp, HasCallStack) =>
((cp : inp) :-> out) -> (cp : inp) :-> out
L.finalizeParamCallingDoc (cp & inp) :-> out
cd) (out :-> (cp & inp)
clr (out :-> (cp & inp)) -> ((cp & inp) :-> inp) -> out :-> inp
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# (cp & inp) :-> inp
forall a (s :: [*]). (a & s) :-> s
L.drop)

----------------------------------------------------------------------------
-- Contract call
----------------------------------------------------------------------------

selfCalling
  :: forall p inp mname.
     ( NiceParameterFull p
     , KnownValue (GetEntryPointArgCustom p mname)
     )
  => EntryPointRef mname
  -> IndigoState inp (ContractRef (GetEntryPointArgCustom p mname) & inp)
                     (Var (ContractRef (GetEntryPointArgCustom p mname)))
selfCalling :: EntryPointRef mname
-> IndigoState
     inp
     (ContractRef (GetEntryPointArgCustom p mname) & inp)
     (Var (ContractRef (GetEntryPointArgCustom p mname)))
selfCalling epRef :: EntryPointRef mname
epRef = do
  (inp :-> (ContractRef (GetEntryPointArgCustom p mname) & inp))
-> IndigoState
     inp (ContractRef (GetEntryPointArgCustom p mname) & inp) ()
forall res (inp :: [*]).
KnownValue res =>
(inp :-> (res : inp)) -> IndigoState inp (res : inp) ()
nullaryOp (EntryPointRef mname
-> inp :-> (ContractRef (GetEntryPointArgCustom p mname) & inp)
forall p (mname :: Maybe Symbol) (s :: [*]).
NiceParameterFull p =>
EntryPointRef mname
-> s :-> (ContractRef (GetEntryPointArgCustom p mname) & s)
L.selfCalling @p EntryPointRef mname
epRef)
  IndigoState
  (ContractRef (GetEntryPointArgCustom p mname) & inp)
  (ContractRef (GetEntryPointArgCustom p mname) & inp)
  (Var (ContractRef (GetEntryPointArgCustom p mname)))
forall x (inp :: [*]).
KnownValue x =>
IndigoState (x & inp) (x & inp) (Var x)
makeTopVar

contractCalling
  :: forall cp inp epRef epArg addr exAddr.
     ( HasEntryPointArg cp epRef epArg
     , ToTAddress cp addr
     , ToT addr ~ ToT Address
     , IsExpr exAddr addr
     , KnownValue epArg
     )
  => epRef -> exAddr
  -> IndigoState inp (Maybe (ContractRef epArg) & inp) (Var (Maybe (ContractRef epArg)))
contractCalling :: epRef
-> exAddr
-> IndigoState
     inp
     (Maybe (ContractRef epArg) & inp)
     (Var (Maybe (ContractRef epArg)))
contractCalling epRef :: epRef
epRef addr :: exAddr
addr = do
  exAddr
-> ((addr & inp) :-> (Maybe (ContractRef epArg) & inp))
-> IndigoState inp (Maybe (ContractRef epArg) & inp) ()
forall n ex res (inp :: [*]).
(IsExpr ex n, KnownValue res) =>
ex -> ((n & inp) :-> (res & inp)) -> IndigoState inp (res & inp) ()
unaryOp exAddr
addr (epRef -> (addr & inp) :-> (Maybe (ContractRef epArg) & inp)
forall cp epRef epArg addr (s :: [*]).
(HasEntryPointArg cp epRef epArg, ToTAddress_ cp addr) =>
epRef -> (addr & s) :-> (Maybe (ContractRef epArg) & s)
L.contractCalling @cp epRef
epRef)
  IndigoState
  (Maybe (ContractRef epArg) & inp)
  (Maybe (ContractRef epArg) & inp)
  (Var (Maybe (ContractRef epArg)))
forall x (inp :: [*]).
KnownValue x =>
IndigoState (x & inp) (x & inp) (Var x)
makeTopVar

----------------------------------------------------------------------------
-- Side-effects
----------------------------------------------------------------------------

transferTokens
  :: (IsExpr exp p, IsExpr exm Mutez, IsExpr exc (ContractRef p), NiceParameter p, HasSideEffects)
  => exp -> exm -> exc -> IndigoState inp inp ()
transferTokens :: exp -> exm -> exc -> IndigoState inp inp ()
transferTokens ep :: exp
ep em :: exm
em ec :: exc
ec = do
  MetaData s :: StackVars inp
s _ <- IndigoState inp inp (MetaData inp)
forall (inp :: [*]). IndigoState inp inp (MetaData inp)
iget
  exp
-> exm
-> exc
-> ((p & (Mutez & (ContractRef p & inp))) :-> inp)
-> IndigoState inp inp ()
forall n m l ex1 ex2 ex3 (inp :: [*]).
(AreExprs ex1 ex2 n m, IsExpr ex3 l) =>
ex1
-> ex2
-> ex3
-> ((n & (m & (l & inp))) :-> inp)
-> IndigoState inp inp ()
ternaryOpFlat exp
ep exm
em exc
ec ((p & (Mutez & (ContractRef p & inp))) :-> (Operation & inp)
forall p (s :: [*]).
NiceParameter p =>
(p & (Mutez & (ContractRef p & s))) :-> (Operation & s)
L.transferTokens ((p & (Mutez & (ContractRef p & inp))) :-> (Operation & inp))
-> ((Operation & inp) :-> inp)
-> (p & (Mutez & (ContractRef p & inp))) :-> inp
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# StackVars inp -> (Operation & inp) :-> inp
forall (stk :: [*]).
HasSideEffects =>
StackVars stk -> (Operation : stk) :-> stk
varActionOperation StackVars inp
s)

setDelegate :: (HasSideEffects, IsExpr ex (Maybe KeyHash)) => ex -> IndigoState inp inp ()
setDelegate :: ex -> IndigoState inp inp ()
setDelegate e :: ex
e =  do
  MetaData s :: StackVars inp
s _ <- IndigoState inp inp (MetaData inp)
forall (inp :: [*]). IndigoState inp inp (MetaData inp)
iget
  ex -> ((Maybe KeyHash & inp) :-> inp) -> IndigoState inp inp ()
forall n ex (inp :: [*]).
IsExpr ex n =>
ex -> ((n & inp) :-> inp) -> IndigoState inp inp ()
unaryOpFlat ex
e ((Maybe KeyHash & inp) :-> (Operation & inp)
forall (s :: [*]). (Maybe KeyHash & s) :-> (Operation & s)
L.setDelegate ((Maybe KeyHash & inp) :-> (Operation & inp))
-> ((Operation & inp) :-> inp) -> (Maybe KeyHash & inp) :-> inp
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# StackVars inp -> (Operation & inp) :-> inp
forall (stk :: [*]).
HasSideEffects =>
StackVars stk -> (Operation : stk) :-> stk
varActionOperation StackVars inp
s)

----------------------------------------------------------------------------
-- Functions, Procedures and Scopes
----------------------------------------------------------------------------

-- | Takes an arbitrary 'IndigoM' and wraps it into an 'IndigoFunction'
-- producing a local scope for its execution. Once it executed, all
-- non-returned variables are cleaned up so that the stack has only
-- returned variables at the top. This also can be interpreted as
-- @if True then f else nop@.
--
-- Note, that by default we do not define scope inside indigo functions,
-- meaning that once we want to create a new variable or return it from
-- a function we need to do it inside @scope $ instr@ construction, for
-- example:
--
-- @
-- f :: IndigoFunction s Natural
-- f = scope $ do
--   *[s]*
--   res <- newVar (0 :: Natural)
--   *[Natural, s]*
--   scope $ do
--     _n <- newVar (1 :: Integer)
--     *[Integer, Natural, s]
--     res += 4
--   *[Natural, s]*
--   return res
--   *[s]*
-- @
scope
  :: forall a inp out . ScopeCodeGen a
  => IndigoState inp out a
  -> IndigoState inp (RetOutStack a ++ inp) (RetVars a)
scope :: IndigoState inp out a
-> IndigoState inp (RetOutStack a ++ inp) (RetVars a)
scope f :: IndigoState inp out a
f = (MetaData inp -> GenCode inp (RetOutStack a ++ inp) (RetVars a))
-> IndigoState inp (RetOutStack a ++ inp) (RetVars a)
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState ((MetaData inp -> GenCode inp (RetOutStack a ++ inp) (RetVars a))
 -> IndigoState inp (RetOutStack a ++ inp) (RetVars a))
-> (MetaData inp -> GenCode inp (RetOutStack a ++ inp) (RetVars a))
-> IndigoState inp (RetOutStack a ++ inp) (RetVars a)
forall a b. (a -> b) -> a -> b
$ \md :: MetaData inp
md ->
  let gc :: GenCode inp out a
gc = IndigoState inp out a -> MetaData inp -> GenCode inp out a
forall (inp :: [*]) (out :: [*]) a.
IndigoState inp out a -> MetaData inp -> GenCode inp out a
runIndigoState IndigoState inp out a
f MetaData inp
md in
  MetaData inp
-> (inp :-> (RetOutStack a ++ inp))
-> GenCode inp (RetOutStack a ++ inp) (RetVars a)
forall ret (inp :: [*]).
ScopeCodeGen ret =>
MetaData inp
-> (inp :-> (RetOutStack ret ++ inp))
-> GenCode inp (RetOutStack ret ++ inp) (RetVars ret)
finalizeStatement @a MetaData inp
md (GenCode inp out a -> inp :-> (RetOutStack a ++ inp)
forall ret (inp :: [*]) (xs :: [*]).
ScopeCodeGen ret =>
GenCode inp xs ret -> inp :-> (RetOutStack ret ++ inp)
compileScope GenCode inp out a
gc)

-- | Add a comment
comment :: MT.CommentType -> IndigoState i i ()
comment :: CommentType -> IndigoState i i ()
comment t :: CommentType
t = (MetaData i -> GenCode i i ()) -> IndigoState i i ()
forall (inp :: [*]) (out :: [*]) a.
(MetaData inp -> GenCode inp out a) -> IndigoState inp out a
IndigoState ((MetaData i -> GenCode i i ()) -> IndigoState i i ())
-> (MetaData i -> GenCode i i ()) -> IndigoState i i ()
forall a b. (a -> b) -> a -> b
$ \md :: MetaData i
md -> () -> MetaData i -> (i :-> i) -> (i :-> i) -> GenCode i i ()
forall (inp :: [*]) (out :: [*]) a.
a
-> MetaData out
-> (inp :-> out)
-> (out :-> inp)
-> GenCode inp out a
GenCode () MetaData i
md (CommentType -> i :-> i
forall (s :: [*]). CommentType -> s :-> s
L.comment CommentType
t) i :-> i
forall (s :: [*]). s :-> s
L.nop

----------------------------------------------------------------------------
-- Conversion from Lorentz
----------------------------------------------------------------------------

-- Functions that convert Lorentz code to Indigo.
-- Will be removed when all Lorentz code is translated in Indigo.

$(genFromLorentzFunN 3)