Esempio n. 1
0
    def trace(self, *args, **kwargs):
        """
        Given args and kwargs, call the Python function and get its
        symbolic representation.

        A dictionary of shadowed symbolic variables is maintained:
            self.s_vars   : {id(obj) : sym_var}
                            Contains all symbolic variables traced during
                            function execution, indexed by the id of the
                            corresponding Python object.

        Additionally, self.s_inputs and self.s_outputs are lists of symbolic
        arguments and results, respectively.
        """

        # clean args and kwargs
        c_args, c_kwargs = clean_int_args(*args, **kwargs)

        # call the Context
        results = self.context.call(self.pyfn, c_args, c_kwargs)

        # get a tuple of the symbolic inputs
        # but avoid 'self' and 'cls' bound arguments
        callargs = utils.orderedcallargs(self.pyfn, *c_args, **c_kwargs)
        all_args = utils.flat_from_doc(callargs)
        if (inspect.ismethod(self.pyfn)
                or (len(all_args) > 0 and type(all_args[0]) is type)):
            all_args = all_args[1:]
        self.s_inputs = tuple([self.s_vars[id(a)] for a in all_args])

        # get a tuple of the symbolic outputs
        self.s_outputs = tuple(
            [self.s_vars[id(r)] for r in utils.as_seq(results)])

        # update variable names where possible
        for name, arg in callargs.iteritems():
            if self.s_vars.get(id(arg), None) in self.s_inputs:
                self.s_vars[name] = self.s_vars[id(arg)]

        return results
Esempio n. 2
0
    def trace(self, *args, **kwargs):
        """
        Given args and kwargs, call the Python function and get its
        symbolic representation.

        A dictionary of shadowed symbolic variables is maintained:
            self.s_vars   : {id(obj) : sym_var}
                            Contains all symbolic variables traced during
                            function execution, indexed by the id of the
                            corresponding Python object.

        Additionally, self.s_inputs and self.s_outputs are lists of symbolic
        arguments and results, respectively.
        """

        # clean args and kwargs
        c_args, c_kwargs = clean_int_args(*args, **kwargs)

        # call the Context
        results = self.context.call(self.pyfn, c_args, c_kwargs)

        # get a tuple of the symbolic inputs
        # but avoid 'self' and 'cls' bound arguments
        callargs = utils.orderedcallargs(self.pyfn, *c_args, **c_kwargs)
        all_args = utils.flat_from_doc(callargs)
        if (inspect.ismethod(self.pyfn) or
           (len(all_args) > 0 and type(all_args[0]) is type)):
            all_args = all_args[1:]
        self.s_inputs = tuple([self.s_vars[id(a)] for a in all_args])

        # get a tuple of the symbolic outputs
        self.s_outputs = tuple(
            [self.s_vars[id(r)] for r in utils.as_seq(results)])

        # update variable names where possible
        for name, arg in callargs.iteritems():
            if self.s_vars.get(id(arg), None) in self.s_inputs:
                self.s_vars[name] = self.s_vars[id(arg)]

        return results
Esempio n. 3
0
    def call(self, args, kwargs):
        if not isinstance(args, tuple):
            raise TypeError('vm.call: args must be tuple', args)
        if not isinstance(kwargs, dict):
            raise TypeError('vm.call: kwargs must be dict', kwargs)

        func = self.func

        if isinstance(func, type) and issubclass(func, BaseException):
            # XXX not shadowing exception creation, because exceptions
            # do not have func_code. Is this OK? can we do better?
            return func(*args, **kwargs)

        func_code = self.func.func_code

        self._myglobals = {}
        self._locals = []

        for name in func_code.co_names:
            #print 'name', name
            try:
                self._myglobals[name] = func.func_globals[name]
            except KeyError:
                try:
                    self._myglobals[name] = __builtin__.__getattribute__(name)
                except AttributeError:
                    #print 'WARNING: name lookup failed', name
                    pass

        # get function arguments
        argspec = inspect.getargspec(func)

        # match function arguments to passed parameters
        callargs = orderedcallargs(func, *args, **kwargs)

        # named args => locals
        self._locals.extend(callargs[arg] for arg in argspec.args)

        # *args => locals
        if argspec.varargs:
            self._locals.append(callargs[argspec.varargs])

        # **kwargs => locals
        if argspec.keywords:
            self._locals.append(callargs[argspec.keywords])

        # other vars => locals
        no_unbound_args = len(func_code.co_varnames) - len(self._locals)
        self._locals.extend([Unassigned] * no_unbound_args)

        # shadow arguments
        for val in flat_from_doc(callargs):
            if id(val) not in self.watcher:
                self.add_shadow(val)

        self.code_iter = itercode(func_code.co_code)
        jmp = None
        while not hasattr(self, 'rval'):
            try:
                i, op, arg = self.code_iter.send(jmp)
            except StopIteration:
                break
            name = opcode.opname[op]
            # method names can't have '+' in them
            name = {'SLICE+0': 'SLICE_PLUS_0',
                    'SLICE+1': 'SLICE_PLUS_1',
                    'SLICE+2': 'SLICE_PLUS_2',
                    'SLICE+3': 'SLICE_PLUS_3',
                    'STORE_SLICE+0': 'STORE_SLICE_PLUS_0',
                    'STORE_SLICE+1': 'STORE_SLICE_PLUS_1',
                    'STORE_SLICE+2': 'STORE_SLICE_PLUS_2',
                    'STORE_SLICE+3': 'STORE_SLICE_PLUS_3',
                    }.get(name, name)
            if self.print_ops:
                print 'OP: ', i, name
            if self.print_stack:
                print self.stack
            try:
                op_method = getattr(self, 'op_' + name)
            except AttributeError:
                raise AttributeError('FrameVM does not have a method defined '
                                     'for \'op_{0}\''.format(name))
            except:
                raise
            jmp = op_method(i, op, arg)

        return self.rval
Esempio n. 4
0
    def call(self, args, kwargs):
        if not isinstance(args, tuple):
            raise TypeError('vm.call: args must be tuple', args)
        if not isinstance(kwargs, dict):
            raise TypeError('vm.call: kwargs must be dict', kwargs)

        func = self.func

        if isinstance(func, type) and issubclass(func, BaseException):
            # XXX not shadowing exception creation, because exceptions
            # do not have func_code. Is this OK? can we do better?
            return func(*args, **kwargs)

        func_code = self.func.func_code

        self._myglobals = {}
        self._locals = []

        for name in func_code.co_names:
            #print 'name', name
            try:
                self._myglobals[name] = func.func_globals[name]
            except KeyError:
                try:
                    self._myglobals[name] = __builtin__.__getattribute__(name)
                except AttributeError:
                    #print 'WARNING: name lookup failed', name
                    pass

        # get function arguments
        argspec = inspect.getargspec(func)

        # match function arguments to passed parameters
        callargs = orderedcallargs(func, *args, **kwargs)

        # named args => locals
        self._locals.extend(callargs[arg] for arg in argspec.args)

        # *args => locals
        if argspec.varargs:
            self._locals.append(callargs[argspec.varargs])

        # **kwargs => locals
        if argspec.keywords:
            self._locals.append(callargs[argspec.keywords])

        # other vars => locals
        no_unbound_args = len(func_code.co_varnames) - len(self._locals)
        self._locals.extend([Unassigned] * no_unbound_args)

        # shadow arguments
        for val in flat_from_doc(callargs):
            if id(val) not in self.watcher:
                self.add_shadow(val)

        self.code_iter = itercode(func_code.co_code)
        jmp = None
        while not hasattr(self, 'rval'):
            try:
                i, op, arg = self.code_iter.send(jmp)
            except StopIteration:
                break
            name = opcode.opname[op]
            # method names can't have '+' in them
            name = {
                'SLICE+0': 'SLICE_PLUS_0',
                'SLICE+1': 'SLICE_PLUS_1',
                'SLICE+2': 'SLICE_PLUS_2',
                'SLICE+3': 'SLICE_PLUS_3',
                'STORE_SLICE+0': 'STORE_SLICE_PLUS_0',
                'STORE_SLICE+1': 'STORE_SLICE_PLUS_1',
                'STORE_SLICE+2': 'STORE_SLICE_PLUS_2',
                'STORE_SLICE+3': 'STORE_SLICE_PLUS_3',
            }.get(name, name)
            if self.print_ops:
                print 'OP: ', i, name
            if self.print_stack:
                print self.stack
            try:
                op_method = getattr(self, 'op_' + name)
            except AttributeError:
                raise AttributeError('FrameVM does not have a method defined '
                                     'for \'op_{0}\''.format(name))
            except:
                raise
            jmp = op_method(i, op, arg)

        return self.rval