def run(self):
        # Set jump to main program body
        self.__opcodes.add('PUSH', dec_to_hex(0, 2 * self.__address_length))
        jump_to_prog_start_i = len(self.__opcodes.list) - 1
        self.__opcodes.add('JUMP')

        for el in self.__ast.root.child_nodes:
            context = Context(self.__frame_service_atoms)

            if el.child_nodes[0].value == 'prog':
                context.is_prog = True
                # Jump from header to prog body
                self.__opcodes.add('JUMPDEST')
                self.__opcodes.list[jump_to_prog_start_i].extra_value = dec_to_hex(self.__opcodes.list[-1].id,
                                                                                   2 * self.__address_length)

                self.__opcodes.add('PUSH', dec_to_hex(0, 2 * self.__address_length))
                prog_atom_count = len(self.__opcodes.list) - 1
                VirtualStackHelper().load_cur_atom_counter_addr(self.__opcodes)
                self.__opcodes.add('MSTORE')

                self.process_code_block(el.child_nodes[1], context, self.__opcodes)

                self.__opcodes.list[prog_atom_count].extra_value = \
                    dec_to_hex(context.id_counter - self.__frame_service_atoms, 2 * self.__address_length)

            else:
                self.declare_function(el, context, self.__opcodes)
        return self
 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
Beispiel #3
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')
Beispiel #4
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')
Beispiel #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')
Beispiel #6
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')
Beispiel #7
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')
Beispiel #8
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')
Beispiel #9
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')
Beispiel #10
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')
Beispiel #11
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')
Beispiel #12
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')
Beispiel #13
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)
    def __cond(self, body: AstNode, ctx: Context, opcodes: OpcodeList, generator: Generator):
        """
        INPUT  (0): | EoS |
        OUTPUT (0): | EoS |
        """
        assert len(body.child_nodes) == 3 or len(body.child_nodes) == 4

        # Conditions check
        generator.process_call(body.child_nodes[1], ctx, opcodes)
        # JUMP TO TRUE
        opcodes.add('PUSH')
        jump_from_check_to_true = len(opcodes.list) - 1
        opcodes.add('JUMPI')
        # JUMP TO ELSE
        opcodes.add('PUSH')
        jump_from_check_to_false = len(opcodes.list) - 1
        opcodes.add('JUMP')
        # TRUE BLOCK
        opcodes.add('JUMPDEST')
        block_id = opcodes.list[-1].id
        opcodes.list[jump_from_check_to_true].extra_value = dec_to_hex(block_id, 2 * self.__address_length)
        generator.process_call(body.child_nodes[2], ctx, opcodes)
        opcodes.add('PUSH', )
        jump_from_true_to_end = len(opcodes.list) - 1
        opcodes.add('JUMP')
        # FALSE BLOCK
        opcodes.add('JUMPDEST')
        block_id = opcodes.list[-1].id
        opcodes.list[jump_from_check_to_false].extra_value = dec_to_hex(block_id, 2 * self.__address_length)
        if len(body.child_nodes) == 4:
            generator.process_call(body.child_nodes[3], ctx, opcodes)
        opcodes.add('PUSH')
        jump_from_false_to_end = len(opcodes.list) - 1
        opcodes.add('JUMP')
        # END
        opcodes.add('JUMPDEST')
        block_id = opcodes.list[-1].id
        opcodes.list[jump_from_true_to_end].extra_value = dec_to_hex(block_id, 2 * self.__address_length)
        opcodes.list[jump_from_false_to_end].extra_value = dec_to_hex(block_id, 2 * self.__address_length)
Beispiel #15
0
 def __init__(self,
              name: str,
              address_length: int,
              extra_value=None,
              instruction_set: dict = None):
     self.id = Opcode.__counter
     self.__instruction_set = instruction_set
     Opcode.__counter += 1
     self.name = name
     if extra_value is not None:
         self.extra_value = extra_value
     elif name == 'PUSH':
         self.extra_value = dec_to_hex(0, 2 * address_length)
     else:
         self.extra_value = None
     if name == 'PUSH':
         Opcode.__counter += address_length
    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')
Beispiel #17
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')
    def __while(self, body: AstNode, ctx: Context, opcodes: OpcodeList, generator: Generator):
        """
        INPUT:  | EoS |
        OUTPUT: | EoS |
        """
        assert len(body.child_nodes) == 3
        prev_while = self.__current_while_id
        self.__current_while_id = self.__while_count
        self.__while_count += 1
        opcodes.add('JUMPDEST', dec_to_hex(self.__current_while_id, 2 * self.__address_length))
        jumpdest_to_condition_check_id = dec_to_hex(opcodes.list[-1].id, 2 * self.__address_length)
        generator.process_call(body.child_nodes[1], ctx, opcodes)
        # if true: jump to while body
        opcodes.add('PUSH')
        jump_to_while_body = len(opcodes.list) - 1
        opcodes.add('JUMPI')
        # else: jump to while end
        opcodes.add('PUSH')
        jump_to_while_end = len(opcodes.list) - 1
        opcodes.add('JUMP')

        # while body
        opcodes.add('JUMPDEST')
        opcodes.list[jump_to_while_body].extra_value = dec_to_hex(opcodes.list[-1].id, 2 * self.__address_length)
        generator.process_call(body.child_nodes[2], ctx, opcodes)
        opcodes.add('PUSH', jumpdest_to_condition_check_id)
        opcodes.add('JUMP')
        # while end
        opcodes.add('JUMPDEST')
        opcodes.list[jump_to_while_end].extra_value = dec_to_hex(opcodes.list[-1].id, 2 * self.__address_length)
        for i in range(len(opcodes.list)):
            if opcodes.list[i].name == 'JUMP' and opcodes.list[i].extra_value == dec_to_hex(self.__current_while_id,
                                                                                            2 * self.__address_length):
                opcodes.list[i - 1].extra_value = dec_to_hex(opcodes.list[-1].id, 2 * self.__address_length)
                opcodes.list[i].extra_value = None
        BuiltIns.current_while = prev_while
 def process_literal(self, call_body: AstNode, opcodes: OpcodeList):
     assert call_body.type == AstNodeType.Literal
     value = dec_to_hex(call_body.value, 2 * self.__address_length)
     opcodes.add('PUSH', value)