-- 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
  ) 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.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 :: Expr Bool -> IndigoState inp xs () -> IndigoState inp inp ()
while :: Expr Bool -> IndigoState inp xs () -> IndigoState inp inp ()
while e :: Expr Bool
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 (Expr Bool -> IndigoState inp (Bool & inp) ()
forall a (inp :: [*]). Expr a -> IndigoState inp (a & inp) ()
compileExpr Expr Bool
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
  :: (KnownValue l, KnownValue r)
  => Expr (Either l r)
  -> (Var l -> IndigoState (l & inp) xs ())
  -> IndigoState inp (r & inp) (Var r)
whileLeft :: Expr (Either l r)
-> (Var l -> IndigoState (l & inp) xs ())
-> IndigoState inp (r & inp) (Var r)
whileLeft e :: Expr (Either l r)
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 (Expr (Either l r) -> IndigoState inp (Either l r & inp) ()
forall a (inp :: [*]). Expr a -> IndigoState inp (a & inp) ()
compileExpr Expr (Either l r)
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
  :: (IterOpHs a, KnownValue (IterOpElHs a))
  => Expr a -> (Var (IterOpElHs a) -> IndigoState ((IterOpElHs a) & inp) xs ())
  -> IndigoState inp inp ()
forEach :: Expr a
-> (Var (IterOpElHs a) -> IndigoState (IterOpElHs a & inp) xs ())
-> IndigoState inp inp ()
forEach container :: Expr a
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 (Expr a -> IndigoState inp (a & inp) ()
forall a (inp :: [*]). Expr a -> IndigoState inp (a & inp) ()
compileExpr Expr a
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
  :: (NiceParameterFull cp, RequireSumType cp, HasCallStack)
  => (Var cp -> IndigoState (cp & inp) out x)
  -> (Expr cp -> IndigoState inp out x)
finalizeParamCallingDoc :: (Var cp -> IndigoState (cp & inp) out x)
-> Expr cp -> IndigoState inp out x
finalizeParamCallingDoc act :: Var cp -> IndigoState (cp & inp) out x
act param :: Expr cp
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 (Expr cp -> IndigoState inp (cp & inp) ()
forall a (inp :: [*]). Expr a -> IndigoState inp (a & inp) ()
compileExpr Expr cp
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.
     ( HasEntrypointArg cp epRef epArg
     , ToTAddress cp addr
     , ToT addr ~ ToT Address
     , KnownValue epArg
     )
  => epRef -> Expr addr
  -> IndigoState inp (Maybe (ContractRef epArg) & inp) (Var (Maybe (ContractRef epArg)))
contractCalling :: epRef
-> Expr addr
-> IndigoState
     inp
     (Maybe (ContractRef epArg) & inp)
     (Var (Maybe (ContractRef epArg)))
contractCalling epRef :: epRef
epRef addr :: Expr addr
addr = do
  Expr addr
-> ((addr & inp) :-> (Maybe (ContractRef epArg) & inp))
-> IndigoState inp (Maybe (ContractRef epArg) & inp) ()
forall res n (inp :: [*]).
KnownValue res =>
Expr n
-> ((n & inp) :-> (res & inp)) -> IndigoState inp (res & inp) ()
unaryOp Expr addr
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
  :: (NiceParameter p, HasSideEffects)
  => Expr p -> Expr Mutez -> Expr (ContractRef p)
  -> IndigoState inp inp ()
transferTokens :: Expr p
-> Expr Mutez -> Expr (ContractRef p) -> IndigoState inp inp ()
transferTokens ep :: Expr p
ep em :: Expr Mutez
em ec :: Expr (ContractRef p)
ec = do
  MetaData s :: StackVars inp
s _ <- IndigoState inp inp (MetaData inp)
forall (inp :: [*]). IndigoState inp inp (MetaData inp)
iget
  Expr p
-> Expr Mutez
-> Expr (ContractRef p)
-> ((p & (Mutez & (ContractRef p & inp))) :-> inp)
-> IndigoState inp inp ()
forall n m l (inp :: [*]).
Expr n
-> Expr m
-> Expr l
-> ((n & (m & (l & inp))) :-> inp)
-> IndigoState inp inp ()
ternaryOpFlat Expr p
ep Expr Mutez
em Expr (ContractRef p)
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 => Expr (Maybe KeyHash) -> IndigoState inp inp ()
setDelegate :: Expr (Maybe KeyHash) -> IndigoState inp inp ()
setDelegate e :: Expr (Maybe KeyHash)
e =  do
  MetaData s :: StackVars inp
s _ <- IndigoState inp inp (MetaData inp)
forall (inp :: [*]). IndigoState inp inp (MetaData inp)
iget
  Expr (Maybe KeyHash)
-> ((Maybe KeyHash & inp) :-> inp) -> IndigoState inp inp ()
forall n (inp :: [*]).
Expr n -> ((n & inp) :-> inp) -> IndigoState inp inp ()
unaryOpFlat Expr (Maybe KeyHash)
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