evm-opcodes-0.1.2: src/EVM/Opcode/Traversal.hs
{-# LANGUAGE ScopedTypeVariables #-}
-- |
-- Module: EVM.Opcode.Traversal
-- Copyright: 2018-2022 Simon Shine
-- Maintainer: Simon Shine <simon@simonshine.dk>
-- License: MIT
--
-- This module exposes a generic method of traversing 'Opcode''s.
module EVM.Opcode.Traversal
( OpcodeMapper(..)
, mapOpcodeM
) where
import EVM.Opcode
import Prelude hiding (EQ, GT, LT)
-- | An 'OpcodeMapper' is a collection of four mapping functions that can
-- map any @'Opcode'' a@ to an @'Opcode'' b@. For each of the three opcodes
-- that are annotated, 'JUMP', 'JUMPI' and 'JUMPDEST', a separate mapping
-- function is specified, and for any other opcode, a general mapping function
-- is specified that falls back to the same opcode of type @'Opcode'' b@.
--
-- See 'EVM.Opcode.Labelled.translate' for an example of usage.
data OpcodeMapper m a b = OpcodeMapper
{ mapOnJump :: a -> m (Opcode' b)
, mapOnJumpi :: a -> m (Opcode' b)
, mapOnJumpdest :: a -> m (Opcode' b)
, mapOnOther :: Opcode' a -> m (Maybe (Opcode' b))
}
-- | Given an 'OpcodeMapper' and an @'Opcode'' a@, produce @m ('Opcode'' b)@.
mapOpcodeM :: forall m a b. Monad m => OpcodeMapper m a b -> Opcode' a -> m (Opcode' b)
mapOpcodeM mapper opcode = case opcode of
JUMP a -> mapOnJump mapper a
JUMPI a -> mapOnJumpi mapper a
JUMPDEST a -> mapOnJumpdest mapper a
-- 0s: Stop and Arithmetic Operations
STOP -> mapOnOther' STOP STOP
ADD -> mapOnOther' ADD ADD
MUL -> mapOnOther' MUL MUL
SUB -> mapOnOther' SUB SUB
DIV -> mapOnOther' DIV DIV
SDIV -> mapOnOther' SDIV SDIV
MOD -> mapOnOther' MOD MOD
SMOD -> mapOnOther' SMOD SMOD
ADDMOD -> mapOnOther' ADDMOD ADDMOD
MULMOD -> mapOnOther' MULMOD MULMOD
EXP -> mapOnOther' EXP EXP
SIGNEXTEND -> mapOnOther' SIGNEXTEND SIGNEXTEND
-- 10s: Comparison & Bitwise Logic Operations
LT -> mapOnOther' LT LT
GT -> mapOnOther' GT GT
SLT -> mapOnOther' SLT SLT
SGT -> mapOnOther' SGT SGT
EQ -> mapOnOther' EQ EQ
ISZERO -> mapOnOther' ISZERO ISZERO
AND -> mapOnOther' AND AND
OR -> mapOnOther' OR OR
XOR -> mapOnOther' XOR XOR
NOT -> mapOnOther' NOT NOT
BYTE -> mapOnOther' BYTE BYTE
SHL -> mapOnOther' SHL SHL
SHR -> mapOnOther' SHR SHR
SAR -> mapOnOther' SAR SAR
-- 20s: SHA3
SHA3 -> mapOnOther' SHA3 SHA3
-- 30s: Environmental Information
ADDRESS -> mapOnOther' ADDRESS ADDRESS
BALANCE -> mapOnOther' BALANCE BALANCE
ORIGIN -> mapOnOther' ORIGIN ORIGIN
CALLER -> mapOnOther' CALLER CALLER
CALLVALUE -> mapOnOther' CALLVALUE CALLVALUE
CALLDATALOAD -> mapOnOther' CALLDATALOAD CALLDATALOAD
CALLDATASIZE -> mapOnOther' CALLDATASIZE CALLDATASIZE
CALLDATACOPY -> mapOnOther' CALLDATACOPY CALLDATACOPY
CODESIZE -> mapOnOther' CODESIZE CODESIZE
CODECOPY -> mapOnOther' CODECOPY CODECOPY
GASPRICE -> mapOnOther' GASPRICE GASPRICE
EXTCODESIZE -> mapOnOther' EXTCODESIZE EXTCODESIZE
EXTCODECOPY -> mapOnOther' EXTCODECOPY EXTCODECOPY
RETURNDATASIZE -> mapOnOther' RETURNDATASIZE RETURNDATASIZE
RETURNDATACOPY -> mapOnOther' RETURNDATACOPY RETURNDATACOPY
EXTCODEHASH -> mapOnOther' EXTCODEHASH EXTCODEHASH
-- 40s: Block Information
BLOCKHASH -> mapOnOther' BLOCKHASH BLOCKHASH
COINBASE -> mapOnOther' COINBASE COINBASE
TIMESTAMP -> mapOnOther' TIMESTAMP TIMESTAMP
NUMBER -> mapOnOther' NUMBER NUMBER
DIFFICULTY -> mapOnOther' DIFFICULTY DIFFICULTY
GASLIMIT -> mapOnOther' GASLIMIT GASLIMIT
CHAINID -> mapOnOther' CHAINID CHAINID
SELFBALANCE -> mapOnOther' SELFBALANCE SELFBALANCE
-- 50s: Stack, Memory, Storage and Flow Operations
POP -> mapOnOther' POP POP
MLOAD -> mapOnOther' MLOAD MLOAD
MSTORE -> mapOnOther' MSTORE MSTORE
MSTORE8 -> mapOnOther' MSTORE8 MSTORE8
SLOAD -> mapOnOther' SLOAD SLOAD
SSTORE -> mapOnOther' SSTORE SSTORE
PC -> mapOnOther' PC PC
MSIZE -> mapOnOther' MSIZE MSIZE
GAS -> mapOnOther' GAS GAS
-- 60s & 70s: Push Operations
PUSH n -> mapOnOther' (PUSH n) (PUSH n)
-- 80s: Duplication Operations (DUP)
DUP i -> mapOnOther' (DUP i) (DUP i)
-- 90s: Exchange operations (SWAP)
SWAP i -> mapOnOther' (SWAP i) (SWAP i)
-- a0s: Logging Operations (LOG)
LOG i -> mapOnOther' (LOG i) (LOG i)
-- f0s: System Operations
CREATE -> mapOnOther' CREATE CREATE
CALL -> mapOnOther' CALL CALL
CALLCODE -> mapOnOther' CALLCODE CALLCODE
RETURN -> mapOnOther' RETURN RETURN
DELEGATECALL -> mapOnOther' DELEGATECALL DELEGATECALL
CREATE2 -> mapOnOther' CREATE2 CREATE2
STATICCALL -> mapOnOther' STATICCALL STATICCALL
REVERT -> mapOnOther' REVERT REVERT
INVALID -> mapOnOther' INVALID INVALID
SELFDESTRUCT -> mapOnOther' SELFDESTRUCT SELFDESTRUCT
where
mapOnOther' :: Opcode' a -> Opcode' b -> m (Opcode' b)
mapOnOther' opa opbDefault = do
res <- mapOnOther mapper opa
case res of
Just opb -> return opb
Nothing -> return opbDefault