Ejemplo n.º 1
0
Archivo: expr.py Proyecto: sdtsui/viper
    def build_in_comparator(self):
        from viper.parser.parser import make_setter
        left = Expr(self.expr.left, self.context).lll_node
        right = Expr(self.expr.comparators[0], self.context).lll_node

        result_placeholder = self.context.new_placeholder(BaseType('bool'))
        setter = []

        # Load nth item from list in memory.
        if right.value == 'multi':
            # Copy literal to memory to be compared.
            tmp_list = LLLnode.from_list(
                obj=self.context.new_placeholder(ListType(right.typ.subtype, right.typ.count)),
                typ=ListType(right.typ.subtype, right.typ.count),
                location='memory'
            )
            setter = make_setter(tmp_list, right, 'memory')
            load_i_from_list = ['mload', ['add', tmp_list, ['mul', 32, ['mload', MemoryPositions.FREE_LOOP_INDEX]]]]
        elif right.location == "storage":
            load_i_from_list = ['sload', ['add', ['sha3_32', right], ['mload', MemoryPositions.FREE_LOOP_INDEX]]]
        else:
            load_i_from_list = ['mload', ['add', right, ['mul', 32, ['mload', MemoryPositions.FREE_LOOP_INDEX]]]]

        # Condition repeat loop has to break on.
        break_loop_condition = [
            'if',
            ['eq', unwrap_location(left), load_i_from_list],
            ['seq',
                ['mstore', '_result', 1],  # store true.
                'break']
        ]

        # Repeat loop to loop-compare each item in the list.
        for_loop_sequence = [
            ['mstore', result_placeholder, 0],
            ['with', '_result', result_placeholder,
                ['repeat', MemoryPositions.FREE_LOOP_INDEX, 0, right.typ.count, break_loop_condition]],
            ['mload', result_placeholder]
        ]

        # Save list to memory, so one can iterate over it,
        # used when literal was created with tmp_list.
        if setter:
            compare_sequence = ['seq', setter] + for_loop_sequence
        else:
            compare_sequence = ['seq'] + for_loop_sequence

        # Compare the result of the repeat loop to 1, to know if a match was found.
        o = LLLnode.from_list([
            'eq', 1,
            compare_sequence],
            typ='bool',
            annotation="in comporator"
        )

        return o
Ejemplo n.º 2
0
Archivo: expr.py Proyecto: sdtsui/viper
 def list_literals(self):
     if not len(self.expr.elts):
         raise StructureException("List must have elements", self.expr)
     o = []
     out_type = None
     for elt in self.expr.elts:
         o.append(Expr(elt, self.context).lll_node)
         if not out_type:
             out_type = o[-1].typ
         elif len(o) > 1 and o[-1].typ != out_type:
             out_type = MixedType()
     return LLLnode.from_list(["multi"] + o, typ=ListType(out_type, len(o)), pos=getpos(self.expr))
Ejemplo n.º 3
0
 def list_literals(self):
     if not len(self.expr.elts):
         raise StructureException("List must have elements", self.expr)
     o = []
     out_type = None
     for elt in self.expr.elts:
         o.append(Expr(elt, self.context).lll_node)
         if not out_type:
             out_type = o[-1].typ
         previous_type = o[-1].typ.subtype.typ if hasattr(
             o[-1].typ, 'subtype') else o[-1].typ
         current_type = out_type.subtype.typ if hasattr(
             out_type, 'subtype') else out_type
         if len(o) > 1 and previous_type != current_type:
             raise TypeMismatchException("Lists may only contain one type",
                                         self.expr)
     return LLLnode.from_list(["multi"] + o,
                              typ=ListType(out_type, len(o)),
                              pos=getpos(self.expr))
Ejemplo n.º 4
0
    def parse_for_list(self):
        from .parser import (parse_body, make_setter)

        iter_list_node = Expr(self.stmt.iter, self.context).lll_node
        if not isinstance(iter_list_node.typ.subtype,
                          BaseType):  # Sanity check on list subtype.
            raise StructureException(
                'For loops allowed only on basetype lists.', self.stmt.iter)
        iter_var_type = self.context.vars.get(
            self.stmt.iter.id).typ if isinstance(self.stmt.iter,
                                                 ast.Name) else None
        subtype = iter_list_node.typ.subtype.typ
        varname = self.stmt.target.id
        value_pos = self.context.new_variable(varname, BaseType(subtype))
        i_pos = self.context.new_variable('_index_for_' + varname,
                                          BaseType(subtype))
        self.context.forvars[varname] = True
        if iter_var_type:  # Is a list that is already allocated to memory.
            self.context.set_in_for_loop(
                self.stmt.iter.id
            )  # make sure list cannot be altered whilst iterating.
            iter_var = self.context.vars.get(self.stmt.iter.id)
            body = [
                'seq',
                [
                    'mstore', value_pos,
                    [
                        'mload',
                        ['add', iter_var.pos, ['mul', ['mload', i_pos], 32]]
                    ]
                ],
                parse_body(self.stmt.body, self.context)
            ]
            o = LLLnode.from_list(['repeat', i_pos, 0, iter_var.size, body],
                                  typ=None,
                                  pos=getpos(self.stmt))
            self.context.remove_in_for_loop(self.stmt.iter.id)
        elif isinstance(self.stmt.iter,
                        ast.List):  # List gets defined in the for statement.
            # Allocate list to memory.
            count = iter_list_node.typ.count
            tmp_list = LLLnode.from_list(obj=self.context.new_placeholder(
                ListType(iter_list_node.typ.subtype, count)),
                                         typ=ListType(
                                             iter_list_node.typ.subtype,
                                             count),
                                         location='memory')
            setter = make_setter(tmp_list, iter_list_node, 'memory')
            body = [
                'seq',
                [
                    'mstore', value_pos,
                    [
                        'mload',
                        ['add', tmp_list, ['mul', ['mload', i_pos], 32]]
                    ]
                ],
                parse_body(self.stmt.body, self.context)
            ]
            o = LLLnode.from_list(
                ['seq', setter, ['repeat', i_pos, 0, count, body]],
                typ=None,
                pos=getpos(self.stmt))
        elif isinstance(self.stmt.iter,
                        ast.Attribute):  # List is contained in storage.
            count = iter_list_node.typ.count
            self.context.set_in_for_loop(
                iter_list_node.annotation
            )  # make sure list cannot be altered whilst iterating.
            body = [
                'seq',
                [
                    'mstore', value_pos,
                    [
                        'sload',
                        ['add', ['sha3_32', iter_list_node], ['mload', i_pos]]
                    ]
                ],
                parse_body(self.stmt.body, self.context),
            ]
            o = LLLnode.from_list(['seq', ['repeat', i_pos, 0, count, body]],
                                  typ=None,
                                  pos=getpos(self.stmt))
            self.context.remove_in_for_loop(iter_list_node.annotation)
        del self.context.vars[varname]
        del self.context.vars['_index_for_' + varname]
        del self.context.forvars[varname]
        return o