Ejemplo n.º 1
0
    def make_function(self, fnargs, nbargs_before, mrdtable):
        if self._function is not None:
            return self._function
        name = self.get_function_name()
        self.compress_typechecks(mrdtable)
        checklines = self.generate_typechecks(fnargs[nbargs_before:])
        if not checklines:
            body = self.body
        else:
            checklines.append(self.body)
            body = '\n    '.join(checklines)
        source = 'def %s(%s):\n    %s\n' % (name, ', '.join(fnargs), body)

        if 0:  # for debugging the generated mm sources
            f = open('/tmp/mm-source/%s' % name, 'a')
            for possiblename in self.possiblenames:
                print >> f, '#',
                for part in possiblename:
                    print >> f, getattr(part, '__name__', part),
                print >> f
            print >> f
            print >> f, source
            f.close()

        exec compile2(source) in self.miniglobals
        self._function = self.miniglobals[name]
        return self._function
Ejemplo n.º 2
0
 def make_fastfunc(unwrap_spec, func):
     unwrap_info = UnwrapSpec_FastFunc_Unwrap()
     unwrap_info.apply_over(unwrap_spec)
     narg = unwrap_info.n
     args = ['space'] + unwrap_info.args
     if args == unwrap_info.unwrap:
         fastfunc = func
     else:
         # try to avoid excessive bloat
         if func.__module__ == 'pypy.interpreter.astcompiler.ast':
             raise FastFuncNotSupported
         if (not func.__module__.startswith('pypy.module.__builtin__') and
             not func.__module__.startswith('pypy.module.sys') and
             not func.__module__.startswith('pypy.module.math')):
             if not func.__name__.startswith('descr'):
                 raise FastFuncNotSupported
         d = {}
         unwrap_info.miniglobals['func'] = func
         source = """if 1: 
             def fastfunc_%s_%d(%s):
                 return func(%s)
             \n""" % (func.__name__, narg,
                      ', '.join(args),
                      ', '.join(unwrap_info.unwrap))
         exec compile2(source) in unwrap_info.miniglobals, d
         fastfunc = d['fastfunc_%s_%d' % (func.__name__, narg)]
     return narg, fastfunc
Ejemplo n.º 3
0
def make_objclass_getter(func, cls, cache={}):
    if hasattr(func, "im_func"):
        assert not cls or cls is func.im_class
        cls = func.im_class
    if not cls:
        return unknown_objclass_getter, cls
    try:
        return cache[cls]
    except KeyError:
        pass
    miniglobals = {}
    if isinstance(cls, str):
        assert cls.startswith("<"), "pythontype typecheck should begin with <"
        cls_name = cls[1:]
        typeexpr = "space.w_%s" % cls_name
    else:
        miniglobals["cls"] = cls
        typeexpr = "space.gettypeobject(cls.typedef)"
    source = """if 1:
        def objclass_getter(space):
            return %s
        \n""" % (
        typeexpr,
    )
    exec compile2(source) in miniglobals
    res = miniglobals["objclass_getter"], cls
    cache[cls] = res
    return res
Ejemplo n.º 4
0
 def make_fastfunc(unwrap_spec, func):
     unwrap_info = UnwrapSpec_FastFunc_Unwrap()
     unwrap_info.apply_over(unwrap_spec)
     narg = unwrap_info.n
     args = ['space'] + unwrap_info.args
     if args == unwrap_info.unwrap:
         fastfunc = func
     else:
         # try to avoid excessive bloat
         mod = func.__module__
         if mod is None:
             mod = ""
         if mod == 'pypy.interpreter.astcompiler.ast':
             raise FastFuncNotSupported
         if (not mod.startswith('pypy.module.__builtin__') and
             not mod.startswith('pypy.module.sys') and
             not mod.startswith('pypy.module.math')):
             if not func.__name__.startswith('descr'):
                 raise FastFuncNotSupported
         d = {}
         unwrap_info.miniglobals['func'] = func
         source = """if 1:
             def fastfunc_%s_%d(%s):
                 return func(%s)
             \n""" % (func.__name__, narg,
                      ', '.join(args),
                      ', '.join(unwrap_info.unwrap))
         exec compile2(source) in unwrap_info.miniglobals, d
         fastfunc = d['fastfunc_%s_%d' % (func.__name__, narg)]
     return narg, fastfunc
Ejemplo n.º 5
0
    def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
        try:
            key = tuple(unwrap_spec)
            activation_factory_cls, run_args = cache[key]
            assert run_args == self.run_args, (
                "unexpected: same spec, different run_args")
            return activation_factory_cls
        except KeyError:
            parts = []          
            for el in unwrap_spec:
                if isinstance(el, tuple):
                    parts.append(''.join([getattr(subel, '__name__', subel)
                                          for subel in el]))
                else:
                    parts.append(getattr(el, '__name__', el))
            label = '_'.join(parts)
            #print label

            d = {}
            source = """if 1: 
                def _run_UWS_%s(self, space, scope_w):
                    return self.behavior(%s)
                \n""" % (label, ', '.join(self.run_args))
            exec compile2(source) in self.miniglobals, d
            d['_run'] = d['_run_UWS_%s' % label]
            del d['_run_UWS_%s' % label]

            activation_cls = type("BuiltinActivation_UwS_%s" % label,
                             (BuiltinActivation,), d)

            cache[key] = activation_cls, self.run_args
            return activation_cls
Ejemplo n.º 6
0
    def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
        try:
            key = tuple(unwrap_spec)
            activation_factory_cls, run_args = cache[key]
            assert run_args == self.run_args, (
                "unexpected: same spec, different run_args")
            return activation_factory_cls
        except KeyError:
            parts = []
            for el in unwrap_spec:
                if isinstance(el, tuple):
                    parts.append(''.join([getattr(subel, '__name__', subel)
                                          for subel in el]))
                else:
                    parts.append(getattr(el, '__name__', el))
            label = '_'.join(parts)
            #print label

            d = {}
            source = """if 1:
                def _run(self, space, scope_w):
                    return self.behavior(%s)
                \n""" % (', '.join(self.run_args),)
            exec compile2(source) in self.miniglobals, d

            activation_cls = type("BuiltinActivation_UwS_%s" % label,
                             (BuiltinActivation,), d)
            activation_cls._immutable_ = True

            cache[key] = activation_cls, self.run_args
            return activation_cls
Ejemplo n.º 7
0
def setup():
    for name in (ObjSpace.ConstantTable + ObjSpace.ExceptionTable + [
            'int', 'str', 'float', 'long', 'tuple', 'list', 'dict', 'unicode',
            'complex', 'slice', 'bool', 'basestring', 'object'
    ]):
        setattr(FakeObjSpace, 'w_' + name, w_some_obj())
    FakeObjSpace.w_type = w_some_type()
    #
    for (name, _, arity, _) in ObjSpace.MethodTable:
        if name == 'type':
            continue
        args = ['w_%d' % i for i in range(arity)]
        params = args[:]
        d = {'is_root': is_root, 'w_some_obj': w_some_obj}
        if name in ('get', ):
            params[-1] += '=None'
        exec compile2("""\
            def meth(self, %s):
                %s
                return w_some_obj()
        """ % (', '.join(params), '; '.join(
            ['is_root(%s)' % arg for arg in args]))) in d
        meth = func_with_new_name(d['meth'], name)
        setattr(FakeObjSpace, name, meth)
    #
    for name in ObjSpace.IrregularOpTable:
        assert hasattr(FakeObjSpace, name)  # missing?
Ejemplo n.º 8
0
    def make_function(self, fnargs, nbargs_before, mrdtable):
        if self._function is not None:
            return self._function
        name = self.get_function_name()
        self.compress_typechecks(mrdtable)
        checklines = self.generate_typechecks(fnargs[nbargs_before:])
        if not checklines:
            body = self.body
        else:
            checklines.append(self.body)
            body = '\n    '.join(checklines)
        source = 'def %s(%s):\n    %s\n' % (name, ', '.join(fnargs), body)

        if 0:    # for debugging the generated mm sources
            f = open('/tmp/mm-source/%s' % name, 'a')
            for possiblename in self.possiblenames:
                print >> f, '#',
                for part in possiblename:
                    print >> f, getattr(part, '__name__', part),
                print >> f
            print >> f
            print >> f, source
            f.close()

        exec compile2(source) in self.miniglobals
        self._function = self.miniglobals[name]
        return self._function
Ejemplo n.º 9
0
def setup():
    for name in (ObjSpace.ConstantTable +
                 ObjSpace.ExceptionTable +
                 ['int', 'str', 'float', 'long', 'tuple', 'list',
                  'dict', 'unicode', 'complex', 'slice', 'bool',
                  'basestring', 'object']):
        setattr(FakeObjSpace, 'w_' + name, w_some_obj())
    FakeObjSpace.w_type = w_some_type()
    #
    for (name, _, arity, _) in ObjSpace.MethodTable:
        if name == 'type':
            continue
        args = ['w_%d' % i for i in range(arity)]
        params = args[:]
        d = {'is_root': is_root,
             'w_some_obj': w_some_obj}
        if name in ('get',):
            params[-1] += '=None'
        exec compile2("""\
            def meth(self, %s):
                %s
                return w_some_obj()
        """ % (', '.join(params),
               '; '.join(['is_root(%s)' % arg for arg in args]))) in d
        meth = func_with_new_name(d['meth'], name)
        setattr(FakeObjSpace, name, meth)
    #
    for name in ObjSpace.IrregularOpTable:
        assert hasattr(FakeObjSpace, name)    # missing?
Ejemplo n.º 10
0
def generate_function(sig, opcodes):
    consolidate(opcodes)
    lines = []
    has_orbyte = False
    for op in opcodes:
        if isinstance(op, str):
            if has_orbyte:
                nextbyte = ord(op[0])
                if nextbyte:
                    lines.append('orbyte |= %d' % nextbyte)
                lines.append('builder.writechr(orbyte)')
                has_orbyte = False
                op = op[1:]
            if op:
                if len(op) > 1:
                    lines.append('builder.write(constlistofchars(%r))' % (op,))
                else:
                    lines.append('builder.writechr(%d)' % (ord(op),))
        else:
            has_orbyte = op.eval(lines, has_orbyte)
    assert not has_orbyte, "malformed bytecode"

    if not lines:
        lines.append('pass')
    args = ', '.join(['builder'] + ['arg%d'%i for i in range(1, len(sig)+1)])
    lines.insert(0, 'def encode(%s):' % args)
    source = '\n    '.join(lines) + '\n'
    miniglobals = {
        'packimm32': packimm32,
        'packimm8': packimm8,
        'packimm16': packimm16,
        'constlistofchars': constlistofchars,
        }
    exec compile2(source) in miniglobals
    return miniglobals['encode']
Ejemplo n.º 11
0
def make_func(name, desc):
    sig = []
    fieldvalues = []
    for field in desc.fields:
        if field in desc.specializations:
            fieldvalues.append((field, desc.specializations[field]))
        else:
            sig.append(field.name)
            fieldvalues.append((field, field.name))
    if isinstance(desc, IDupDesc):
        for destfield, srcfield in desc.dupfields.iteritems():
            fieldvalues.append((destfield, srcfield.name))
    body = ['v = r_uint(0)']
    assert 'v' not in sig # that wouldn't be funny
    #body.append('print %r'%name + ', ' + ', '.join(["'%s:', %s"%(s, s) for s in sig]))
    for field, value in fieldvalues:
        if field.name == 'spr':
            body.append('spr = (%s&31) << 5 | (%s >> 5 & 31)'%(value, value))
            value = 'spr'
        body.append('v |= (%3s & r_uint(%#05x)) << %d'%(value,
                                           field.mask,
                                           (32 - field.right - 1)))
    body.append('self.emit(v)')
    src = 'def %s(self, %s):\n    %s'%(name, ', '.join(sig), '\n    '.join(body))
    d = {'r_uint':r_uint}
    #print src
    exec compile2(src) in d
    return d[name]
Ejemplo n.º 12
0
def generate_function(sig, opcodes):
    consolidate(opcodes)
    lines = []
    has_orbyte = False
    for op in opcodes:
        if isinstance(op, str):
            if has_orbyte:
                nextbyte = ord(op[0])
                if nextbyte:
                    lines.append('orbyte |= %d' % nextbyte)
                lines.append('builder.write(chr(orbyte))')
                has_orbyte = False
                op = op[1:]
            if op:
                lines.append('builder.write(%r)' % (op,))
        else:
            has_orbyte = op.eval(lines, has_orbyte)
    assert not has_orbyte, "malformed bytecode"

    if not lines:
        lines.append('pass')
    args = ', '.join(['builder'] + ['arg%d'%i for i in range(1, len(sig)+1)])
    lines.insert(0, 'def encode(%s):' % args)
    source = '\n    '.join(lines) + '\n'
    miniglobals = {
        'packimm32': packimm32,
        'packimm8': packimm8,
        'packimm16': packimm16,
        }
    exec compile2(source) in miniglobals
    return miniglobals['encode']
Ejemplo n.º 13
0
def make_objclass_getter(func, cls, cache={}):
    if hasattr(func, 'im_func'):
        assert not cls or cls is func.im_class
        cls = func.im_class
    if not cls:
        return unknown_objclass_getter, cls
    try:
        return cache[cls]
    except KeyError:
        pass
    miniglobals = {}
    if isinstance(cls, str):
        assert cls.startswith('<'), "pythontype typecheck should begin with <"
        cls_name = cls[1:]
        typeexpr = "space.w_%s" % cls_name
    else:
        miniglobals['cls'] = cls
        typeexpr = "space.gettypeobject(cls.typedef)"
    source = """if 1:
        def objclass_getter(space):
            return %s
        \n""" % (typeexpr, )
    exec compile2(source) in miniglobals
    res = miniglobals['objclass_getter'], cls
    cache[cls] = res
    return res
Ejemplo n.º 14
0
 def make_function(self, fnargs, nbargs_before, mrdtable):
     if self._function is not None:
         return self._function
     name = self.get_function_name()
     self.compress_typechecks(mrdtable)
     checklines = self.generate_typechecks(mrdtable, fnargs[nbargs_before:])
     if not checklines:
         body = self.body
     else:
         checklines.append(self.body)
         body = '\n    '.join(checklines)
     source = 'def %s(%s):\n    %s\n' % (name, ', '.join(fnargs), body)
     self.debug_dump(source)
     exec compile2(source) in self.miniglobals
     self._function = self.miniglobals[name]
     return self._function
Ejemplo n.º 15
0
 def make_function(self, fnargs, nbargs_before, mrdtable):
     if self._function is not None:
         return self._function
     name = self.get_function_name()
     self.compress_typechecks(mrdtable)
     checklines = self.generate_typechecks(mrdtable, fnargs[nbargs_before:])
     if not checklines:
         body = self.body
     else:
         checklines.append(self.body)
         body = '\n    '.join(checklines)
     source = 'def %s(%s):\n    %s\n' % (name, ', '.join(fnargs), body)
     self.debug_dump(source)
     exec compile2(source) in self.miniglobals
     self._function = self.miniglobals[name]
     return self._function
Ejemplo n.º 16
0
def _make_objclass_getter(cls):
    if not cls:
        return unknown_objclass_getter, cls
    miniglobals = {}
    if isinstance(cls, str):
        assert cls.startswith('<'),"pythontype typecheck should begin with <"
        cls_name = cls[1:]
        typeexpr = "space.w_%s" % cls_name
    else:
        miniglobals['cls'] = cls
        typeexpr = "space.gettypeobject(cls.typedef)"
    source = """if 1:
        def objclass_getter(space):
            return %s
        \n""" % (typeexpr,)
    exec compile2(source) in miniglobals
    res = miniglobals['objclass_getter'], cls
    return res
Ejemplo n.º 17
0
def inplace_add(x, y):
    x += y
    return x

def inplace_sub(x, y):
    x -= y
    return x

def inplace_mul(x, y):
    x *= y
    return x

exec compile2("""
def inplace_truediv(x, y):
    x /= y
    return x
""", flags=__future__.CO_FUTURE_DIVISION, dont_inherit=1)
#                     makes an INPLACE_TRUE_DIVIDE

def inplace_floordiv(x, y):
    x //= y
    return x

exec compile2("""
def inplace_div(x, y):
    x /= y
    return x
""", flags=0, dont_inherit=1)    # makes an INPLACE_DIVIDE

def inplace_mod(x, y):
Ejemplo n.º 18
0
                typename = space.type(w_obj).getname(space)
                raise operationerrfmt(space.w_TypeError,
                      "unsupported operand type for %(targetname)s(): '%%s'",
                                      typename)
            w_result = space.get_and_call_function(w_impl, w_obj)

            if %(checker)s:
                return w_result
            typename = space.type(w_result).getname(space)
            msg = "%(specialname)s returned non-%(targetname)s (type '%%s')"
            raise operationerrfmt(space.w_TypeError, msg, typename)
        assert not hasattr(DescrOperation, %(targetname)r)
        DescrOperation.%(targetname)s = %(targetname)s
        del %(targetname)s
        \n""" % locals()
    exec compile2(source)

for targetname, specialname in [('str', '__str__'), ('repr', '__repr__'),
                                ('oct', '__oct__'), ('hex', '__hex__')]:

    source = """if 1:
        def %(targetname)s(space, w_obj):
            w_impl = space.lookup(w_obj, %(specialname)r)
            if w_impl is None:
                typename = space.type(w_obj).getname(space)
                raise operationerrfmt(space.w_TypeError,
                      "unsupported operand type for %(targetname)s(): '%%s'",
                                      typename)
            w_result = space.get_and_call_function(w_impl, w_obj)

            if space.is_true(space.isinstance(w_result, space.w_str)):
Ejemplo n.º 19
0
def make_perform_trampoline(prefix, exprargs, expr, miniglobals,  multimethod, selfindex=0,
                            allow_NotImplemented_results=False):
    """NOT_RPYTHON"""    
    # mess to figure out how to put a gateway around executing expr
    argnames = ['_%d'%(i+1) for i in range(multimethod.arity)]
    explicit_argnames = multimethod.extras.get('argnames', [])
    argnames[len(argnames)-len(explicit_argnames):] = explicit_argnames
    solid_arglist = ['w_'+name for name in argnames]
    wrapper_arglist = solid_arglist[:]
    if multimethod.extras.get('varargs_w', False):
        wrapper_arglist.append('args_w')
    if multimethod.extras.get('w_varargs', False):
        wrapper_arglist.append('w_args')        
    if multimethod.extras.get('keywords', False):
        raise Exception, "no longer supported, use __args__"
    if multimethod.extras.get('general__args__', False):
        wrapper_arglist.append('__args__')
    wrapper_arglist += multimethod.extras.get('extra_args', ())

    miniglobals.update({ 'OperationError': OperationError,
                         'typeerrormsg': typeerrormsg})
    
    app_defaults = multimethod.extras.get('defaults', ())
    i = len(argnames) - len(app_defaults)
    wrapper_signature = wrapper_arglist[:]
    for app_default in app_defaults:
        name = wrapper_signature[i]
        wrapper_signature[i] = '%s=%s' % (name, name)
        miniglobals[name] = app_default
        i += 1

    wrapper_signature.insert(0, wrapper_signature.pop(selfindex))
    wrapper_sig  = ', '.join(wrapper_signature)

    src = []
    dest = []
    for wrapper_arg,expr_arg in zip(['space']+wrapper_arglist, exprargs):
        if wrapper_arg != expr_arg:
            src.append(wrapper_arg)
            dest.append(expr_arg)
    renaming = ', '.join(dest) +" = "+', '.join(src)

    # add a call to resolve_target to give the thunk space a chance to replace
    # the thing with something else
    offset = len(multimethod.argnames_before)
    renaming += "; %s = space.resolve_target(%s)" % (
            exprargs[selfindex+offset], exprargs[selfindex+offset])

    if allow_NotImplemented_results and (len(multimethod.specialnames) > 1 or
                                         multimethod.name.startswith('inplace_')):
        # turn FailedToImplement into NotImplemented
        code = """def %s_perform_call(space, %s):
                      %s
                      try:
                          return %s
                      except FailedToImplement, e:
                          if e.w_type is not None:
                              raise OperationError(e.w_type, e.w_value)
                          else:
                              return space.w_NotImplemented
"""        % (prefix, wrapper_sig, renaming, expr)
    else:
        # turn FailedToImplement into nice TypeErrors
        code = """def %s_perform_call(space, %s):
                      %s
                      try:
                          w_res = %s
                      except FailedToImplement, e:
                          if e.w_type is not None:
                              raise OperationError(e.w_type, e.w_value)
                          else:
                              raise OperationError(space.w_TypeError,
                                  typeerrormsg(space, %r, [%s]))
                      if w_res is None:
                          w_res = space.w_None
                      return w_res
"""        % (prefix, wrapper_sig, renaming, expr,
              multimethod.operatorsymbol, ', '.join(solid_arglist))
    exec compile2(code, '', 'exec') in miniglobals 
    return miniglobals["%s_perform_call" % prefix]
Ejemplo n.º 20
0

def inplace_sub(x, y):
    x -= y
    return x


def inplace_mul(x, y):
    x *= y
    return x


exec compile2("""
def inplace_truediv(x, y):
    x /= y
    return x
""",
              flags=__future__.CO_FUTURE_DIVISION,
              dont_inherit=1)
#                     makes an INPLACE_TRUE_DIVIDE


def inplace_floordiv(x, y):
    x //= y
    return x


exec compile2("""
def inplace_div(x, y):
    x /= y
    return x
Ejemplo n.º 21
0
def make_perform_trampoline(prefix,
                            exprargs,
                            expr,
                            miniglobals,
                            multimethod,
                            selfindex=0,
                            allow_NotImplemented_results=False):
    """NOT_RPYTHON"""
    # mess to figure out how to put a gateway around executing expr
    argnames = ['_%d' % (i + 1) for i in range(multimethod.arity)]
    explicit_argnames = multimethod.extras.get('argnames', [])
    argnames[len(argnames) - len(explicit_argnames):] = explicit_argnames
    solid_arglist = ['w_' + name for name in argnames]
    wrapper_arglist = solid_arglist[:]
    if multimethod.extras.get('varargs_w', False):
        wrapper_arglist.append('args_w')
    if multimethod.extras.get('w_varargs', False):
        wrapper_arglist.append('w_args')
    if multimethod.extras.get('keywords', False):
        raise Exception, "no longer supported, use __args__"
    if multimethod.extras.get('general__args__', False):
        wrapper_arglist.append('__args__')
    wrapper_arglist += multimethod.extras.get('extra_args', ())

    miniglobals.update({
        'OperationError': OperationError,
        'typeerrormsg': typeerrormsg
    })

    app_defaults = multimethod.extras.get('defaults', ())
    i = len(argnames) - len(app_defaults)
    wrapper_signature = wrapper_arglist[:]
    for app_default in app_defaults:
        name = wrapper_signature[i]
        wrapper_signature[i] = '%s=%s' % (name, name)
        miniglobals[name] = app_default
        i += 1

    wrapper_signature.insert(0, wrapper_signature.pop(selfindex))
    wrapper_sig = ', '.join(wrapper_signature)

    src = []
    dest = []
    for wrapper_arg, expr_arg in zip(['space'] + wrapper_arglist, exprargs):
        if wrapper_arg != expr_arg:
            src.append(wrapper_arg)
            dest.append(expr_arg)
    renaming = ', '.join(dest) + " = " + ', '.join(src)

    if allow_NotImplemented_results and (
            len(multimethod.specialnames) > 1
            or multimethod.name.startswith('inplace_')):
        # turn FailedToImplement into NotImplemented
        code = """def %s_perform_call(space, %s):
                      %s
                      try:
                          return %s
                      except FailedToImplement, e:
                          if e.w_type is not None:
                              raise OperationError(e.w_type, e.w_value)
                          else:
                              return space.w_NotImplemented
""" % (prefix, wrapper_sig, renaming, expr)
    else:
        # turn FailedToImplement into nice TypeErrors
        code = """def %s_perform_call(space, %s):
                      %s
                      try:
                          w_res = %s
                      except FailedToImplement, e:
                          if e.w_type is not None:
                              raise OperationError(e.w_type, e.w_value)
                          else:
                              raise OperationError(space.w_TypeError,
                                  typeerrormsg(space, %r, [%s]))
                      if w_res is None:
                          w_res = space.w_None
                      return w_res
""" % (prefix, wrapper_sig, renaming, expr, multimethod.operatorsymbol,
        ', '.join(solid_arglist))
    exec compile2(code, '', 'exec') in miniglobals
    return miniglobals["%s_perform_call" % prefix]
Ejemplo n.º 22
0
    def build_function(self, target, funcname, func_selfarg_index,
                       things_to_call):
        # support for inventing names for the entries in things_to_call
        # which are real function objects instead of strings
        miniglobals = {
            'FailedToImplement': FailedToImplement,
            '__name__': __name__
        }

        def invent_name(obj):
            if isinstance(obj, str):
                return obj
            name = obj.__name__
            n = 1
            while name in miniglobals:
                n += 1
                name = '%s%d' % (obj.__name__, n)
            miniglobals[name] = obj
            return name

        funcargs = ['arg%d' % i for i in range(self.multimethod.arity)]

        bodylines = []
        for conversion, call, call_selfarg_index in things_to_call:
            callargs = funcargs[:]
            if conversion is not None:
                to_convert = func_selfarg_index
                convert_callargs = (self.multimethod.argnames_before +
                                    [callargs[to_convert]])
                callargs[to_convert] = '%s(%s)' % (invent_name(conversion),
                                                   ', '.join(convert_callargs))
            callname = invent_name(call)
            if call_selfarg_index is not None:
                # fallback on root_class
                self.build_function(self.multimethod.root_class, callname,
                                    call_selfarg_index, [])
                callname = '%s.%s' % (callargs.pop(call_selfarg_index),
                                      callname)
            callargs = (self.multimethod.argnames_before + callargs +
                        self.multimethod.argnames_after)
            bodylines.append('return %s(%s)' % (callname, ', '.join(callargs)))

        fallback = False
        if not bodylines:
            miniglobals['raiseFailedToImplement'] = raiseFailedToImplement
            bodylines = ['return raiseFailedToImplement()']
            fallback = True
            # NB. make sure that there is only one fallback function object,
            # i.e. the key used in the mmfunccache below is always the same
            # for all functions with the same name and an empty bodylines.

        # protect all lines apart from the last one by a try:except:
        for i in range(len(bodylines) - 2, -1, -1):
            bodylines[i:i + 1] = [
                'try:', '    ' + bodylines[i], 'except FailedToImplement:',
                '    pass'
            ]

        if func_selfarg_index is not None:
            selfargs = [funcargs.pop(func_selfarg_index)]
        else:
            selfargs = []
        funcargs = (selfargs + self.multimethod.argnames_before + funcargs +
                    self.multimethod.argnames_after)

        if target is None and not self.baked_perform_call:
            return funcargs, bodylines[0][len('return '
                                              ):], miniglobals, fallback

        # indent mode
        bodylines = ['    ' + line for line in bodylines]

        bodylines.insert(0, 'def %s(%s):' % (funcname, ', '.join(funcargs)))
        bodylines.append('')
        source = '\n'.join(bodylines)

        # XXX find a better place (or way) to avoid duplicate functions
        l = miniglobals.items()
        l.sort()
        l = tuple(l)
        key = (source, l)
        try:
            func = self.mmfunccache[key]
        except KeyError:
            exec compile2(source) in miniglobals
            func = miniglobals[funcname]
            self.mmfunccache[key] = func
        #else:
        #    print "avoided duplicate function", func
        self.to_install.append((target, funcname, func, source, fallback))
        return func
Ejemplo n.º 23
0
    def build_function(self, target, funcname, func_selfarg_index,
                       things_to_call):
        # support for inventing names for the entries in things_to_call
        # which are real function objects instead of strings
        miniglobals = {'FailedToImplement': FailedToImplement, '__name__': __name__}
        def invent_name(obj):
            if isinstance(obj, str):
                return obj
            name = obj.__name__
            n = 1
            while name in miniglobals:
                n += 1
                name = '%s%d' % (obj.__name__, n)
            miniglobals[name] = obj
            return name

        funcargs = ['arg%d' % i for i in range(self.multimethod.arity)]

        bodylines = []
        for conversion, call, call_selfarg_index in things_to_call:
            callargs = funcargs[:]
            if conversion is not None:
                to_convert = func_selfarg_index
                convert_callargs = (self.multimethod.argnames_before +
                                    [callargs[to_convert]])
                callargs[to_convert] = '%s(%s)' % (
                    invent_name(conversion), ', '.join(convert_callargs))
            callname = invent_name(call)
            if call_selfarg_index is not None:
                # fallback on root_class
                self.build_function(self.multimethod.root_class,
                                    callname, call_selfarg_index, [])
                callname = '%s.%s' % (callargs.pop(call_selfarg_index), callname)
            callargs = (self.multimethod.argnames_before +
                        callargs + self.multimethod.argnames_after)
            bodylines.append('return %s(%s)' % (callname, ', '.join(callargs)))

        fallback = False
        if not bodylines:
            miniglobals['raiseFailedToImplement'] = raiseFailedToImplement
            bodylines = ['return raiseFailedToImplement()']
            fallback = True
            # NB. make sure that there is only one fallback function object,
            # i.e. the key used in the mmfunccache below is always the same
            # for all functions with the same name and an empty bodylines.

        # protect all lines apart from the last one by a try:except:
        for i in range(len(bodylines)-2, -1, -1):
            bodylines[i:i+1] = ['try:',
                                '    ' + bodylines[i],
                                'except FailedToImplement:',
                                '    pass']

        if func_selfarg_index is not None:
            selfargs = [funcargs.pop(func_selfarg_index)]
        else:
            selfargs = []
        funcargs = (selfargs + self.multimethod.argnames_before +
                    funcargs + self.multimethod.argnames_after)

        if target is None and not self.baked_perform_call:
            return funcargs, bodylines[0][len('return '):], miniglobals, fallback

        # indent mode
        bodylines = ['    ' + line for line in bodylines]

        bodylines.insert(0, 'def %s(%s):' % (funcname, ', '.join(funcargs)))
        bodylines.append('')
        source = '\n'.join(bodylines)

        # XXX find a better place (or way) to avoid duplicate functions 
        l = miniglobals.items()
        l.sort()
        l = tuple(l)
        key = (source, l)
        try: 
            func = self.mmfunccache[key]
        except KeyError: 
            exec compile2(source) in miniglobals
            func = miniglobals[funcname]
            self.mmfunccache[key] = func 
        #else: 
        #    print "avoided duplicate function", func
        self.to_install.append((target, funcname, func, source, fallback))
        return func
Ejemplo n.º 24
0
def make_perform_trampoline(
    prefix, exprargs, expr, miniglobals, multimethod, selfindex=0, allow_NotImplemented_results=False
):
    """NOT_RPYTHON"""
    # mess to figure out how to put a gateway around executing expr
    argnames = ["_%d" % (i + 1) for i in range(multimethod.arity)]
    explicit_argnames = multimethod.extras.get("argnames", [])
    argnames[len(argnames) - len(explicit_argnames) :] = explicit_argnames
    solid_arglist = ["w_" + name for name in argnames]
    wrapper_arglist = solid_arglist[:]
    if multimethod.extras.get("varargs_w", False):
        wrapper_arglist.append("args_w")
    if multimethod.extras.get("w_varargs", False):
        wrapper_arglist.append("w_args")
    if multimethod.extras.get("keywords", False):
        raise Exception, "no longer supported, use __args__"
    if multimethod.extras.get("general__args__", False):
        wrapper_arglist.append("__args__")
    wrapper_arglist += multimethod.extras.get("extra_args", ())

    miniglobals.update({"OperationError": OperationError, "typeerrormsg": typeerrormsg})

    app_defaults = multimethod.extras.get("defaults", ())
    i = len(argnames) - len(app_defaults)
    wrapper_signature = wrapper_arglist[:]
    for app_default in app_defaults:
        name = wrapper_signature[i]
        wrapper_signature[i] = "%s=%s" % (name, name)
        miniglobals[name] = app_default
        i += 1

    wrapper_signature.insert(0, wrapper_signature.pop(selfindex))
    wrapper_sig = ", ".join(wrapper_signature)

    src = []
    dest = []
    for wrapper_arg, expr_arg in zip(["space"] + wrapper_arglist, exprargs):
        if wrapper_arg != expr_arg:
            src.append(wrapper_arg)
            dest.append(expr_arg)
    renaming = ", ".join(dest) + " = " + ", ".join(src)

    if allow_NotImplemented_results and (len(multimethod.specialnames) > 1 or multimethod.name.startswith("inplace_")):
        # turn FailedToImplement into NotImplemented
        code = """def %s_perform_call(space, %s):
                      %s
                      try:
                          return %s
                      except FailedToImplement, e:
                          if e.w_type is not None:
                              raise OperationError(e.w_type, e.w_value)
                          else:
                              return space.w_NotImplemented
""" % (
            prefix,
            wrapper_sig,
            renaming,
            expr,
        )
    else:
        # turn FailedToImplement into nice TypeErrors
        code = """def %s_perform_call(space, %s):
                      %s
                      try:
                          w_res = %s
                      except FailedToImplement, e:
                          if e.w_type is not None:
                              raise OperationError(e.w_type, e.w_value)
                          else:
                              raise OperationError(space.w_TypeError,
                                  typeerrormsg(space, %r, [%s]))
                      if w_res is None:
                          w_res = space.w_None
                      return w_res
""" % (
            prefix,
            wrapper_sig,
            renaming,
            expr,
            multimethod.operatorsymbol,
            ", ".join(solid_arglist),
        )
    exec compile2(code, "", "exec") in miniglobals
    return miniglobals["%s_perform_call" % prefix]
Ejemplo n.º 25
0
                typename = space.type(w_obj).getname(space)
                raise operationerrfmt(space.w_TypeError,
                      "unsupported operand type for %(targetname)s(): '%%s'",
                                      typename)
            w_result = space.get_and_call_function(w_impl, w_obj)

            if %(checker)s:
                return w_result
            typename = space.type(w_result).getname(space)
            msg = "%(specialname)s returned non-%(targetname)s (type '%%s')"
            raise operationerrfmt(space.w_TypeError, msg, typename)
        assert not hasattr(DescrOperation, %(targetname)r)
        DescrOperation.%(targetname)s = %(targetname)s
        del %(targetname)s
        \n""" % locals()
    exec compile2(source)

for targetname, specialname in [
    ('str', '__str__'),
    ('repr', '__repr__'),
    ('oct', '__oct__'),
    ('hex', '__hex__')]:

    source = """if 1:
        def %(targetname)s(space, w_obj):
            w_impl = space.lookup(w_obj, %(specialname)r)
            if w_impl is None:
                typename = space.type(w_obj).getname(space)
                raise operationerrfmt(space.w_TypeError,
                      "unsupported operand type for %(targetname)s(): '%%s'",
                                      typename)