예제 #1
0
 def store_back_address(self, opcodes: OpcodeList):
     """
     INPUT:  | EoS | New Back address
     OUTPUT: | EoS |
     """
     self.load_back_address_addr(opcodes)
     opcodes.add('MSTORE')
예제 #2
0
 def load_atom_value(self, opcodes: OpcodeList, atom_address: int):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS | Value of Atom on provided address |
     """
     self.load_atom_address(opcodes, atom_address)
     opcodes.add('MLOAD')
예제 #3
0
 def load_cur_atom_counter(self, opcodes: OpcodeList):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS | Value of Current Atom counter
     """
     self.load_cur_atom_counter_addr(opcodes)
     opcodes.add('MLOAD')
예제 #4
0
 def load_back_address(self, opcodes: OpcodeList):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS | Current Back address
     """
     self.load_back_address_addr(opcodes)
     opcodes.add('MLOAD')
예제 #5
0
 def store_new_gap(self, opcodes: OpcodeList):
     """
     INPUT:  | EoS | New gap
     OUTPUT: | EoS |
     """
     opcodes.add('PUSH', dec_to_hex(0, 2 * self.__address_length))
     opcodes.add('MSTORE')
예제 #6
0
 def load_prev_gap(self, opcodes: OpcodeList):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS | Address of previout frame's start
     """
     self.load_cur_gap(opcodes)
     opcodes.add('MLOAD')
예제 #7
0
 def store_atom_value(self, opcodes: OpcodeList, atom_address: int):
     """
     INPUT:  | EoS | New value of Atom
     OUTPUT: | EoS |
     """
     self.load_atom_address(opcodes, atom_address)
     opcodes.add('MSTORE')
예제 #8
0
 def load_cur_gap(self, opcodes: OpcodeList):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS | Gap of current frame |
     """
     opcodes.add('PUSH', dec_to_hex(0, 2 * self.__address_length))
     opcodes.add('MLOAD')
예제 #9
0
 def calc_new_frame_gap(self, opcodes: OpcodeList):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS | Gap of new frame
     """
     self.load_cur_gap(opcodes)
     self.calc_cur_frame_size(opcodes)
     opcodes.add('ADD')
예제 #10
0
 def load_back_address_addr(self, opcodes: OpcodeList):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS | Address of Current Back address
     """
     self.load_cur_gap(opcodes)
     opcodes.add('PUSH', dec_to_hex(0x40, 2 * self.__address_length))
     opcodes.add('ADD')
예제 #11
0
    def __plus(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (2): | EoS | Value 1 | Value 2
        OUTPUT (1): | EoS | Sum of values
        """
        assert len(body.child_nodes) == 3

        opcodes.add('ADD')
예제 #12
0
    def __and(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (2): | EoS | v1 (bool) | v2 (bool)
        OUTPUT (1): | EoS | v1 AND v2 (bool)
        """
        assert len(body.child_nodes) == 3

        opcodes.add('AND')
예제 #13
0
    def __greater(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (2): | EoS | Value 1 | Value 2
        OUTPUT (1): | EoS | Is Value 1 greater than Value 2
        """
        assert len(body.child_nodes) == 3

        opcodes.add('LT')
예제 #14
0
 def load_cur_atom_counter_addr(self, opcodes: OpcodeList):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS | Address of Current Atom counter
     """
     self.load_cur_gap(opcodes)
     opcodes.add('PUSH', dec_to_hex(0x20, 2 * self.__address_length))
     opcodes.add('ADD')
예제 #15
0
    def __times(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (2): | EoS | Value 1 | Value 2
        OUTPUT (1): | EoS | Value 1 * Value 2
        """
        assert len(body.child_nodes) == 3

        opcodes.add('MUL')
예제 #16
0
    def __equal(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (2): | EoS | Value 1 | Value 2
        OUTPUT (1): | EoS | Does value 1 equals value 2 (bool)
        """
        assert len(body.child_nodes) == 3

        opcodes.add('EQ')
예제 #17
0
    def __greatereq(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (2): | EoS | Value 1 | Value 2
        OUTPUT (1): | EoS | Does Value 1 less or equals Value (bool)
        """
        assert len(body.child_nodes) == 3

        opcodes.add('GT')
        opcodes.add('ISZERO')
예제 #18
0
 def __break(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS |
     """
     assert len(body.child_nodes) == 1
     opcodes.add('PUSH', dec_to_hex(0, 2 * self.__address_length))
     opcodes.add('JUMP', dec_to_hex(self.__current_while_id, 2 * self.__address_length))
     pass
예제 #19
0
    def __not(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (1): | EoS | value (bool)
        OUTPUT (1): | EoS | !value (bool)
        """
        assert len(body.child_nodes) == 2

        opcodes.add('PUSH', dec_to_hex(0, 2 * self.address_length))
        opcodes.add('EQ')
예제 #20
0
 def load_atom_address(self, opcodes: OpcodeList, atom_address: int):
     """
     INPUT:  | EoS |
     OUTPUT: | EoS | Address of Atom on provided address
     """
     self.load_cur_gap(opcodes)
     opcodes.add('PUSH', dec_to_hex(atom_address,
                                    2 * self.__address_length))
     opcodes.add('ADD')
예제 #21
0
    def __divide(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (2): | EoS | Value 1 | Value 2
        OUTPUT (1): | EoS | Value 1 // Value 2
        """
        assert len(body.child_nodes) == 3

        opcodes.add('SWAP1')
        opcodes.add('DIV')
예제 #22
0
    def add_frame(self, opcodes: OpcodeList):
        """
        INPUT:  | EoS | Arg1 | ... | ArgN | Back Address |
        OUTPUT: | EoS | Arg1 | ... | ArgN |
        """
        self.load_cur_gap(opcodes)
        self.calc_new_frame_gap(opcodes)
        opcodes.add('MSTORE')

        self.calc_new_frame_gap(opcodes)
        self.store_new_gap(opcodes)

        # Back address gone
        self.store_back_address(opcodes)
예제 #23
0
    def calc_cur_frame_size(self, opcodes: OpcodeList):
        """
        INPUT:  | EoS |
        OUTPUT: | EoS | Size of current frame
        """
        opcodes.add(
            'PUSH',
            dec_to_hex(self.__frame_service_atoms * 0x20,
                       2 * self.__address_length))

        self.load_cur_atom_counter(opcodes)
        opcodes.add('PUSH', dec_to_hex(32, 2 * self.__address_length))
        opcodes.add('MUL')

        opcodes.add('ADD')
예제 #24
0
    def __init__(self, ast: AST, address_length=32, frame_service_atoms=3):
        self.__address_length = address_length
        self.__frame_service_atoms = frame_service_atoms

        assert 32 >= address_length >= 1
        assert frame_service_atoms >= 2

        self.__opcodes: OpcodeList = OpcodeList(address_length)
        self.__ast = ast

        # Init Virtual stack and function Singletons
        VirtualStackHelper(address_length, frame_service_atoms).init_stack(self.__opcodes)
        SpecialForms(address_length)
        BuiltIns(self.__address_length)
        Declared(address_length, frame_service_atoms)
예제 #25
0
    def __nonequal(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (2): | EoS | Value 1 | Value 2
        OUTPUT (1): | EoS | Does Value 1 differs from Value 2 (bool)
        """
        assert len(body.child_nodes) == 3

        opcodes.add('EQ')
        opcodes.add('PUSH', dec_to_hex(0, 2 * self.address_length))
        opcodes.add('EQ')
예제 #26
0
    def __read(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (0): | EoS |
        OUTPUT (1): | EoS | Value from input
        """
        assert len(body.child_nodes) == 2

        opcodes.add('PUSH', dec_to_hex(0x20, 2 * self.address_length))
        opcodes.add('MUL')

        opcodes.add('CALLDATALOAD')
예제 #27
0
    def call(self, call_body: AstNode, ctx: Context, opcodes: OpcodeList):
        assert call_body.type == AstNodeType.List
        assert call_body.child_nodes[
            0].type == AstNodeType.Literal or call_body.child_nodes[
                0].type == AstNodeType.Atom

        # Prepare back address, part 1
        opcodes.add('PUSH')
        back_address = len(opcodes.list) - 1

        # Jump into the function
        opcodes.add(
            'PUSH',
            dec_to_hex(self.__funcs[call_body.child_nodes[0].value],
                       2 * self.address_length))
        opcodes.add('JUMP')

        # Prepare back address, part 2
        opcodes.add('JUMPDEST')
        opcodes.list[back_address].extra_value = dec_to_hex(
            opcodes.list[-1].id, 2 * self.address_length)
예제 #28
0
    def declare_function(self, call_body: AstNode, ctx: Context, opcodes: OpcodeList):
        assert call_body.type == AstNodeType.List
        assert call_body.child_nodes[0].type == AstNodeType.Literal or call_body.child_nodes[0].type == AstNodeType.Atom
        assert call_body.child_nodes[0].value == 'func'
        """
        INPUT:  | EoS | Arg1 | ... | ArgN | Back address
        OUTPUT: | EoS |
        """
        # Set entry point
        opcodes.add('JUMPDEST')
        Declared().add(call_body.child_nodes[1].value, opcodes.list[-1].id)

        # Make new stack frame
        # Back address gone
        VirtualStackHelper().add_frame(opcodes)

        # Set atom counter, part 1
        opcodes.add('PUSH')
        func_atom_counter = len(opcodes.list) - 1
        VirtualStackHelper().load_cur_atom_counter_addr(opcodes)
        opcodes.add('MSTORE')

        # Declare arguments in context
        # Args gone
        for arg_name in reversed(call_body.child_nodes[2].child_nodes):
            assert arg_name.type == AstNodeType.Atom
            address, is_new = ctx.get_atom_addr(arg_name.value)
            VirtualStackHelper().store_atom_value(opcodes, address)

        # Generate body
        self.process_call(call_body.child_nodes[3], ctx, opcodes)

        # Set atom counter, part 2
        opcodes.list[func_atom_counter].extra_value = \
            dec_to_hex(ctx.id_counter - self.__frame_service_atoms, 2 * self.__address_length)

        # Remove frame and leave function
        VirtualStackHelper().load_back_address(opcodes)
        VirtualStackHelper().remove_frame(opcodes)
        opcodes.add('JUMP')
예제 #29
0
 def init_stack(self, opcodes: OpcodeList):
     """
     NO SIDE EFFECTS
     """
     # Set ZERO FRAME (prog frame) gap = 0x40
     opcodes.add('PUSH', dec_to_hex(0x40, 2 * self.__address_length))
     opcodes.add('PUSH', dec_to_hex(0, 2 * self.__address_length))
     opcodes.add('MSTORE')
     # Init zero frame
     # Set start of previous frame and back address as 0x00
     opcodes.add('PUSH', dec_to_hex(0x0, 2 * self.__address_length))
     opcodes.add('DUP1')
     opcodes.add('PUSH', dec_to_hex(0x40, 2 * self.__address_length))
     opcodes.add('MSTORE')
     opcodes.add('PUSH', dec_to_hex(0x40 + 0x40, 2 * self.__address_length))
     opcodes.add('MSTORE')
     # Set counter of atoms as 0x00
     opcodes.add('PUSH', dec_to_hex(0x0, 2 * self.__address_length))
     opcodes.add('PUSH', dec_to_hex(0x40 + 0x20, 2 * self.__address_length))
     opcodes.add('MSTORE')
예제 #30
0
    def __return(self, body: AstNode, ctx: Context, opcodes: OpcodeList):
        """
        INPUT  (1): | EoS | Some value
        OUTPUT (0): | EoS |
        """
        assert len(body.child_nodes) == 2

        if ctx.is_prog:
            opcodes.add('PUSH', dec_to_hex(0, 2 * self.address_length))
            opcodes.add('MSTORE')
            opcodes.add('PUSH', dec_to_hex(32, 2 * self.address_length))
            opcodes.add('PUSH', dec_to_hex(0, 2 * self.address_length))
            opcodes.add('RETURN')
        else:
            VirtualStackHelper().load_back_address(opcodes)
            VirtualStackHelper().remove_frame(opcodes)
            opcodes.add('JUMP')