1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::{kw, Spanned};
use proc_macro2::Span;
use syn::{
    parse::{Parse, ParseStream},
    Result, Token,
};

macro_rules! yul_evm_builtin_enum_builder {
    ($( $variant:ident($($token:tt)* ) ),* $(,)?) => {
        /// Representation of an EVM builtin opcode.
        ///
        /// Solidity Reference:
        /// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityLexer.YulEVMBuiltin>
        #[derive(Clone, Debug)]
        pub enum YulEVMBuiltIn {
            $( $variant($($token)*), )*
        }

        // Generate the parser
        impl Parse for YulEVMBuiltIn {
            fn parse(input: ParseStream<'_>) -> Result<Self> {
                let lookahead = input.lookahead1();
                $(
                    if lookahead.peek($($token)*) {
                        return input.parse().map(Self::$variant);
                    }
                )*
                Err(lookahead.error())
            }
        }

        impl Spanned for YulEVMBuiltIn {
            fn span(&self) -> Span {
                match self {
                    $( Self::$variant(inner) => inner.span(), )*
                }
            }

            fn set_span(&mut self, span: proc_macro2::Span) {
                match self {
                    $( Self::$variant(inner) => inner.span = span, )*
                }
            }
        }
    };
}

yul_evm_builtin_enum_builder!(
    Stop(kw::stop),
    Add(kw::add),
    Sub(kw::sub),
    Mul(kw::mul),
    Div(kw::div),
    Sdiv(kw::sdiv),
    Mod(Token![mod]),
    Smod(kw::smod),
    Exp(kw::exp),
    Not(kw::not),
    Lt(kw::lt),
    Gt(kw::gt),
    Slt(kw::slt),
    Sgt(kw::sgt),
    Eq(kw::eq),
    Iszero(kw::iszero),
    And(kw::and),
    Or(kw::or),
    Xor(kw::xor),
    Byte(kw::byte),
    Shl(kw::shl),
    Shr(kw::shr),
    Sar(kw::sar),
    Addmod(kw::addmod),
    Mulmod(kw::mulmod),
    Signextend(kw::signextend),
    Keccak256(kw::keccak256),
    Pop(kw::pop),
    Mload(kw::mload),
    Mstore(kw::mstore),
    Mstore8(kw::mstore8),
    Sload(kw::sload),
    Sstore(kw::sstore),
    Msize(kw::msize),
    Gas(kw::gas),
    Address(kw::address),
    Balance(kw::balance),
    Selfbalance(kw::selfbalance),
    Caller(kw::caller),
    Callvalue(kw::callvalue),
    Calldataload(kw::calldataload),
    Calldatasize(kw::calldatasize),
    Calldatacopy(kw::calldatacopy),
    Extcodesize(kw::extcodesize),
    Extcodecopy(kw::extcodecopy),
    Returndatasize(kw::returndatasize),
    Returndatacopy(kw::returndatacopy),
    Extcodehash(kw::extcodehash),
    Create(kw::create),
    Create2(kw::create2),
    Call(kw::call),
    Callcode(kw::callcode),
    Delegatecall(kw::delegatecall),
    Staticcall(kw::staticcall),
    Return(Token![return]),
    Revert(kw::revert),
    Selfdestruct(kw::selfdestruct),
    Invalid(kw::invalid),
    Log0(kw::log0),
    Log1(kw::log1),
    Log2(kw::log2),
    Log3(kw::log3),
    Log4(kw::log4),
    Chainid(kw::chainid),
    Origin(kw::origin),
    Gasprice(kw::gasprice),
    Blockhash(kw::blockhash),
    Coinbase(kw::coinbase),
    Timestamp(kw::timestamp),
    Number(kw::number),
    Difficulty(kw::difficulty),
    Prevrandao(kw::prevrandao),
    Gaslimit(kw::gaslimit),
    Basefee(kw::basefee),
);