morley-0.3.0: src/Lorentz/Instr.hs
module Lorentz.Instr
( nop
, drop
, dup
, swap
, push
, some
, none
, unit
, ifNone
, pair
, car
, cdr
, left
, right
, ifLeft
, nil
, cons
, size
, emptySet
, emptyMap
, map
, iter
, mem
, get
, update
, failingWhenPresent
, updateNew
, if_
, ifCons
, loop
, loopLeft
, lambda
, exec
, dip
, failWith
, failText
, failTagged
, failUsing
, failUnexpected
, cast
, pack
, unpack
, concat
, concat'
, slice, isNat, add, sub, rsub, mul, ediv, abs
, neg
, lsl
, lsr
, or
, and
, xor
, not
, compare
, eq0
, neq0
, lt0
, gt0
, le0
, ge0
, int
, self
, contract
, transferTokens
, setDelegate
, createAccount
, createContract
, implicitAccount
, now
, amount
, balance
, checkSignature
, sha256
, sha512
, blake2B
, hashKey
, stepsToQuota
, source
, sender
, address
, LorentzFunctor (..)
) where
import Prelude hiding
(EQ, GT, LT, abs, and, compare, concat, drop, get, map, not, or, some, swap, xor)
import qualified Data.Kind as Kind
import Lorentz.Arith
import Lorentz.Base
import Lorentz.Constraints
import Lorentz.Polymorphic
import Lorentz.Value
import Michelson.Typed
(Instr(..), Notes(NStar), ToT, Value'(..), checkBigMapConstraint, forbiddenBigMap,
forbiddenOp)
import Michelson.Text
import Michelson.Typed.Arith
nop :: s :-> s
nop = I Nop
drop :: a & s :-> s
drop = I DROP
dup :: a & s :-> a & a & s
dup = I DUP
swap :: a & b & s :-> b & a & s
swap = I SWAP
push :: forall t s .(KnownValue t, NoOperation t, NoBigMap t, IsoValue t) => t -> (s :-> t & s)
push a = I $ forbiddenOp @(ToT t) $ forbiddenBigMap @(ToT t) $ PUSH (toVal a)
some :: a & s :-> Maybe a & s
some = I SOME
none :: forall a s . KnownValue a => s :-> (Maybe a & s)
none = I NONE
unit :: s :-> () & s
unit = I UNIT
ifNone
:: (s :-> s') -> (a & s :-> s') -> (Maybe a & s :-> s')
ifNone (I l) (I r) = I (IF_NONE l r)
pair :: a & b & s :-> (a, b) & s
pair = I PAIR
car :: (a, b) & s :-> a & s
car = I CAR
cdr :: (a, b) & s :-> b & s
cdr = I CDR
left :: forall a b s. KnownValue b => a & s :-> Either a b & s
left = I LEFT
right :: forall a b s. KnownValue a => b & s :-> Either a b & s
right = I RIGHT
ifLeft
:: (a & s :-> s') -> (b & s :-> s') -> (Either a b & s :-> s')
ifLeft (I l) (I r) = I (IF_LEFT l r)
nil :: KnownValue p => s :-> List p & s
nil = I NIL
cons :: a & List a & s :-> List a & s
cons = I CONS
ifCons
:: (a & List a & s :-> s') -> (s :-> s') -> (List a & s :-> s')
ifCons (I l) (I r) = I (IF_CONS l r)
size :: SizeOpHs c => c & s :-> Natural & s
size = I SIZE
emptySet :: (KnownCValue e) => s :-> Set e & s
emptySet = I EMPTY_SET
emptyMap :: (KnownCValue k, KnownValue v)
=> s :-> Map k v & s
emptyMap = I EMPTY_MAP
map
:: (MapOpHs c, IsoMapOpRes c b)
=> (MapOpInpHs c & s :-> b & s) -> (c & s :-> MapOpResHs c b & s)
map (I action) = I (MAP action)
iter
:: (IterOpHs c)
=> (IterOpElHs c & s :-> s) -> (c & s :-> s)
iter (I action) = I (ITER action)
mem :: MemOpHs c => MemOpKeyHs c & c & s :-> Bool & s
mem = I MEM
get :: GetOpHs c => GetOpKeyHs c & c & s :-> Maybe (GetOpValHs c) & s
get = I GET
update :: UpdOpHs c => UpdOpKeyHs c & UpdOpParamsHs c & c & s :-> c & s
update = I UPDATE
if_ :: (s :-> s') -> (s :-> s') -> (Bool & s :-> s')
if_ (I l) (I r) = I (IF l r)
loop :: (s :-> Bool & s) -> (Bool & s :-> s)
loop (I b) = I (LOOP b)
loopLeft
:: (a & s :-> Either a b & s) -> (Either a b & s :-> b & s)
loopLeft (I b) = I (LOOP_LEFT b)
lambda
:: (KnownValue i, KnownValue o)
=> Lambda i o -> (s :-> Lambda i o & s)
lambda (I l) = I (LAMBDA $ VLam l)
exec :: a & Lambda a b & s :-> b & s
exec = I EXEC
dip :: forall a s s'. (s :-> s') -> (a & s :-> a & s')
dip (I a) = I (DIP a)
failWith :: (KnownValue a) => a & s :-> t
failWith = I FAILWITH
cast :: KnownValue a => (a & s :-> a & s)
cast = I CAST
pack
:: forall a s. (KnownValue a, NoOperation a, NoBigMap a)
=> a & s :-> ByteString & s
pack = I $ forbiddenOp @(ToT a) $ forbiddenBigMap @(ToT a) PACK
unpack
:: forall a s. (KnownValue a, NoOperation a, NoBigMap a)
=> ByteString & s :-> Maybe a & s
unpack = I $ forbiddenOp @(ToT a) $ forbiddenBigMap @(ToT a) UNPACK
concat :: ConcatOpHs c => c & c & s :-> c & s
concat = I CONCAT
concat' :: ConcatOpHs c => List c & s :-> c & s
concat' = I CONCAT'
slice :: SliceOpHs c => Natural & Natural & c & s :-> Maybe c & s
slice = I SLICE
isNat :: Integer & s :-> Maybe Natural & s
isNat = I ISNAT
add
:: ArithOpHs Add n m
=> n & m & s :-> ArithResHs Add n m & s
add = I ADD
sub
:: ArithOpHs Sub n m
=> n & m & s :-> ArithResHs Sub n m & s
sub = I SUB
rsub
:: ArithOpHs Sub n m
=> m & n & s :-> ArithResHs Sub n m & s
rsub = swap # sub
mul
:: ArithOpHs Mul n m
=> n & m & s :-> ArithResHs Mul n m & s
mul = I MUL
ediv :: EDivOpHs n m
=> n & m & s
:-> Maybe ((EDivOpResHs n m, EModOpResHs n m)) & s
ediv = I EDIV
abs :: UnaryArithOpHs Abs n => n & s :-> UnaryArithResHs Abs n & s
abs = I ABS
neg :: UnaryArithOpHs Neg n => n & s :-> UnaryArithResHs Neg n & s
neg = I NEG
lsl
:: ArithOpHs Lsl n m
=> n & m & s :-> ArithResHs Lsl n m & s
lsl = I LSL
lsr
:: ArithOpHs Lsr n m
=> n & m & s :-> ArithResHs Lsr n m & s
lsr = I LSR
or
:: ArithOpHs Or n m
=> n & m & s :-> ArithResHs Or n m & s
or = I OR
and
:: ArithOpHs And n m
=> n & m & s :-> ArithResHs And n m & s
and = I AND
xor
:: (ArithOpHs Xor n m)
=> n & m & s :-> ArithResHs Xor n m & s
xor = I XOR
not :: UnaryArithOpHs Not n => n & s :-> UnaryArithResHs Not n & s
not = I NOT
compare :: ArithOpHs Compare n m
=> n & m & s :-> ArithResHs Compare n m & s
compare = I COMPARE
eq0 :: UnaryArithOpHs Eq' n => n & s :-> UnaryArithResHs Eq' n & s
eq0 = I EQ
neq0 :: UnaryArithOpHs Neq n => n & s :-> UnaryArithResHs Neq n & s
neq0 = I NEQ
lt0 :: UnaryArithOpHs Lt n => n & s :-> UnaryArithResHs Lt n & s
lt0 = I LT
gt0 :: UnaryArithOpHs Gt n => n & s :-> UnaryArithResHs Gt n & s
gt0 = I GT
le0 :: UnaryArithOpHs Le n => n & s :-> UnaryArithResHs Le n & s
le0 = I LE
ge0 :: UnaryArithOpHs Ge n => n & s :-> UnaryArithResHs Ge n & s
ge0 = I GE
int :: Natural & s :-> Integer & s
int = I INT
self :: forall cp s . s :-> ContractAddr cp & s
self = I SELF
contract :: (KnownValue p) => Address & s :-> Maybe (ContractAddr p) & s
contract = I (CONTRACT NStar)
transferTokens
:: forall p s. (KnownValue p, NoOperation p, NoBigMap p)
=> p & Mutez & ContractAddr p & s :-> Operation & s
transferTokens = I $ forbiddenOp @(ToT p) $ forbiddenBigMap @(ToT p) TRANSFER_TOKENS
setDelegate :: Maybe KeyHash & s :-> Operation & s
setDelegate = I SET_DELEGATE
createAccount :: KeyHash & Maybe KeyHash & Bool & Mutez & s
:-> Operation & Address & s
createAccount = I CREATE_ACCOUNT
createContract
:: forall p g s. (KnownValue p, NoOperation p, KnownValue g, NoOperation g
, NoBigMap p, CanHaveBigMap g)
=> '[(p, g)] :-> '[(List Operation, g)]
-> KeyHash & Maybe KeyHash & Bool & Bool & Mutez & g & s
:-> Operation & Address & s
createContract (I c) =
I $ forbiddenOp @(ToT p) $ forbiddenOp @(ToT g) $
forbiddenBigMap @(ToT p) $ checkBigMapConstraint @(ToT g) $ CREATE_CONTRACT c
implicitAccount :: KeyHash & s :-> ContractAddr () & s
implicitAccount = I IMPLICIT_ACCOUNT
now :: s :-> Timestamp & s
now = I NOW
amount :: s :-> Mutez & s
amount = I AMOUNT
balance :: s :-> Mutez & s
balance = I BALANCE
checkSignature :: PublicKey & Signature & ByteString & s :-> Bool & s
checkSignature = I CHECK_SIGNATURE
sha256 :: ByteString & s :-> ByteString & s
sha256 = I SHA256
sha512 :: ByteString & s :-> ByteString & s
sha512 = I SHA512
blake2B :: ByteString & s :-> ByteString & s
blake2B = I BLAKE2B
hashKey :: PublicKey & s :-> KeyHash & s
hashKey = I HASH_KEY
stepsToQuota :: s :-> Natural & s
stepsToQuota = I STEPS_TO_QUOTA
{-# WARNING source
"Using `source` is considered a bad practice.\n\
\ Consider using `sender` instead until further investigation" #-}
source :: s :-> Address & s
source = I SOURCE
sender :: s :-> Address & s
sender = I SENDER
address :: ContractAddr a & s :-> Address & s
address = I ADDRESS
----------------------------------------------------------------------------
-- Non-canonical instructions
----------------------------------------------------------------------------
-- | Helper instruction.
--
-- Checks whether given key present in the storage and fails if it is.
-- This instruction leaves stack intact.
failingWhenPresent
:: forall c k s v st e.
( MemOpHs c, k ~ MemOpKeyHs c
, KnownValue e
, st ~ (k & v & c & s)
)
=> (forall s0. k : s0 :-> e : s0)
-> st :-> st
failingWhenPresent mkErr =
dip (dip dup # swap) # swap # dip dup # swap # mem #
if_ (mkErr # failWith) nop
-- | Like 'update', but throw an error on attempt to overwrite existing entry.
updateNew
:: forall c k s e.
( UpdOpHs c, MemOpHs c, k ~ UpdOpKeyHs c, k ~ MemOpKeyHs c
, KnownValue e
)
=> (forall s0. k : s0 :-> e : s0)
-> k & UpdOpParamsHs c & c & s :-> c & s
updateNew mkErr = failingWhenPresent mkErr # update
-- | Fail with a given message.
failText :: MText -> s :-> t
failText msg = push msg # failWith
-- | Fail with a given message and the top of the current stack.
failTagged :: (KnownValue a) => MText -> a & s :-> t
failTagged tag = push tag # pair # failWith
-- | Fail with the given Haskell value.
failUsing
:: (IsoValue a, KnownValue a, NoOperation a, NoBigMap a)
=> a -> s :-> t
failUsing err = push err # failWith
-- | Fail, providing a reference to the place in the code where
-- this function is called.
--
-- Like 'error' in Haskell code, this instruction is for internal errors only.
failUnexpected :: HasCallStack => MText -> s :-> t
failUnexpected msg =
failText $ [mt|Unexpected failure: |] <> msg <> [mt|\n|]
<> mkMTextCut (toText $ prettyCallStack callStack)
class LorentzFunctor (c :: Kind.Type -> Kind.Type) where
lmap :: KnownValue b => (a : s :-> b : s) -> (c a : s :-> c b : s)
instance LorentzFunctor Maybe where
lmap f = ifNone none (f # some)