Commits

Anonymous committed 45eff22

Move the pypy trunk into its own top level directory so the path names
stay constant.

  • Participants

Comments (0)

Files changed (62)

File pypy/__init__.py

+# empty

File pypy/appspace/__init__.py

+#

File pypy/appspace/cmathmodule.py

+"""This module is always available. It provides access to mathematical
+functions for complex numbers."""
+
+# Complex math module
+
+# much code borrowed from mathmodule.c
+
+import math
+from complexobject import complex
+
+M_PI = 3.141592653589793239
+
+        
+
+# constants
+_one = complex(1., 0.)
+_half = complex(0.5, 0.)
+_i = complex(0., 1.)
+_halfi = complex(0., 0.5)
+
+
+# internal function not available from Python
+def _prodi(x):
+    real = -x.imag
+    imag = x.real
+    return complex(real, imag)
+
+
+def acos(x):
+    """acos(x)
+
+    Return the arc cosine of x."""
+    
+    return -(_prodi(log((x+(_i*sqrt((_one-(x*x))))))))
+
+
+def acosh(x):
+    """acosh(x)
+
+    Return the hyperbolic arccosine of x."""
+
+    z = complex()
+    z = sqrt(_half)
+    z = log(z*(sqrt(x+_one)+sqrt(x-_one)))
+    return z+z
+
+
+def asin(x):
+    """asin(x)
+
+    Return the arc sine of x."""
+    
+    # -i * log[(sqrt(1-x**2) + i*x]
+    squared = x*x
+    sqrt_1_minus_x_sq = sqrt(_one-squared)
+    return -(_prodi(log((sqrt_1_minus_x_sq+_prodi(x)))))
+
+
+def asinh(x):
+    """asinh(x)
+
+    Return the hyperbolic arc sine of x."""
+    
+    z = complex()
+    z = sqrt(_half)
+    z = log((z * (sqrt(x+_i)+sqrt((x-_i))) ))
+    return z+z
+
+
+def atan(x):
+    """atan(x)
+    
+    Return the arc tangent of x."""
+    
+    return _halfi*log(((_i+x)/(_i-x)))
+
+
+def atanh(x):
+    """atanh(x)
+
+    Return the hyperbolic arc tangent of x."""
+    
+    return _half*log((_one+x)/(_one-x))
+
+
+def cos(x):
+    """cos(x)
+
+    Return the cosine of x."""
+    
+    real = math.cos(x.real) * math.cosh(x.imag)
+    imag = -math.sin(x.real) * math.sinh(x.imag)
+    return complex(real, imag)
+
+
+def cosh(x):
+    """cosh(x)
+    
+    Return the hyperbolic cosine of x."""
+    
+    real = math.cos(x.imag) * math.cosh(x.real)
+    imag = math.sin(x.imag) * math.sinh(x.real)
+    return complex(real, imag)
+
+
+def exp(x):
+    """exp(x)
+    
+    Return the exponential value e**x."""
+    
+    l = math.exp(x.real)
+    real = l * math.cos(x.imag)
+    imag = l * math.sin(x.imag)
+    return complex(real, imag)
+
+
+def log(x):
+    """log(x)
+
+    Return the natural logarithm of x."""
+    
+    l = math.hypot(x.real,x.imag)
+    imag = math.atan2(x.imag, x.real)
+    real = math.log(l)
+    return complex(real, imag)
+
+
+def log10(x):
+    """log10(x)
+
+    Return the base-10 logarithm of x."""
+    
+    l = math.hypot(x.real, x.imag)
+    imag = math.atan2(x.imag, x.real)/log(10.)
+    real = math.log10(l)
+    return complex(real, imag)
+
+
+def sin(x):
+    """sin(x)
+
+    Return the sine of x."""
+    
+    real = math.sin(x.real) * math.cosh(x.imag)
+    imag = math.cos(x.real) * math.sinh(x.imag)
+    return complex(real, imag)
+
+
+def sinh(x):
+    """sinh(x)
+
+    Return the hyperbolic sine of x."""
+    
+    real = math.cos(x.imag) * math.sinh(x.real)
+    imag = math.sin(x.imag) * math.cosh(x.real)
+    return complex(real, imag)
+
+
+def sqrt(x):
+    """sqrt(x)
+
+    Return the square root of x."""
+    
+    if x.real == 0. and x.imag == 0.:
+        real, imag = 0, 0
+    else:
+        s = math.sqrt(0.5*(math.fabs(x.real) + math.hypot(x.real,x.imag)))
+        d = 0.5*x.imag/s
+        if x.real > 0.:
+            real = s
+            imag = d
+        elif x.imag >= 0.:
+            real = d
+            imag = s
+        else:
+            real = -d
+            imag = -s
+    return complex(real, imag)
+
+
+def tan(x):
+    """tan(x)
+
+    Return the tangent of x."""
+
+    sr = math.sin(x.real)
+    cr = math.cos(x.real)
+    shi = math.sinh(x.imag)
+    chi = math.cosh(x.imag)
+    rs = sr * chi
+    is_ = cr * shi
+    rc = cr * chi
+    ic = -sr * shi
+    d = rc*rc + ic * ic
+    real = (rs*rc + is_*ic) / d
+    imag = (is_*rc - rs*ic) / d
+    return complex(real, imag)
+
+
+def tanh(x):
+    """tanh(x)
+
+    Return the hyperbolic tangent of x."""
+    
+    si = math.sin(x.imag)
+    ci = math.cos(x.imag)
+    shr = math.sinh(x.real)
+    chr = math.cosh(x.real)
+    rs = ci * shr
+    is_ = si * chr
+    rc = ci * chr
+    ic = si * shr
+    d = rc*rc + ic*ic
+    real = (rs*rc + is_*ic) / d
+    imag = (is_*rc - rs*ic) / d
+    return complex(real, imag)

File pypy/appspace/complexobject.py

+import re
+import math
+import types
+import warnings
+
+
+PREC_REPR = 0 # 17
+PREC_STR = 0 # 12
+
+
+class complex(object):
+    """complex(real[, imag]) -> complex number
+
+    Create a complex number from a real part and an optional imaginary part.
+    This is equivalent to (real + imag*1j) where imag defaults to 0."""
+    
+    def __init__(self, real=0.0, imag=None):
+        if type(real) == types.StringType and imag is not None:
+            msg = "complex() can't take second arg if first is a string"
+            raise TypeError, msg
+
+        if type(imag) == types.StringType:
+            msg = "complex() second arg can't be a string"
+            raise TypeError, msg
+
+        if type(real) in (types.StringType, types.UnicodeType):
+            real, imag = self._makeComplexFromString(real)
+            self.__dict__['real'] = real
+            self.__dict__['imag'] = imag
+        else:
+            if imag is None:
+               imag = 0.
+            self.__dict__['real'] = float(real)
+            self.__dict__['imag'] = float(imag)
+        
+
+    def __setattr__(self, name, value):
+        if name in ('real', 'imag'):
+            raise TypeError, "readonly attribute"
+        else:
+            self.__dict__[name] = value
+
+
+    def _makeComplexFromString(self, string):
+        pat = re.compile(" *([\+\-]?\d*\.?\d*)([\+\-]?\d*\.?\d*)[jJ] *")
+        m = pat.match(string)
+        x, y = m.groups()
+        if len(y) == 1 and y in '+-':
+            y = y + '1.0'
+        x, y = map(float, [x, y])
+        return x, y
+
+
+    def __description(self, precision):
+        sign = '+'
+        if self.imag < 0.:
+            sign = ''
+        if self.real != 0.:
+            format = "(%%%02dg%%s%%%02dgj)" % (precision, precision)
+            args = (self.real, sign, self.imag)
+        else:
+            format = "%%%02dgj" % precision
+            args = self.imag
+        return format % args
+
+
+    def __repr__(self):
+        return self.__description(PREC_REPR)
+
+
+    def __str__(self):
+        return self.__description(PREC_STR)
+
+        
+    def __hash__(self):
+        hashreal = hash(self.real)
+        hashimag = hash(self.imag)
+
+        # Note:  if the imaginary part is 0, hashimag is 0 now,
+        # so the following returns hashreal unchanged.  This is
+        # important because numbers of different types that
+        # compare equal must have the same hash value, so that
+        # hash(x + 0*j) must equal hash(x).
+
+        combined = hashreal + 1000003 * hashimag
+        if combined == -1:
+            combined = -2
+
+        return combined
+
+
+    def __add__(self, other):
+        self, other = self.__coerce__(other)
+        real = self.real + other.real
+        imag = self.imag + other.imag
+        return complex(real, imag)
+
+
+    def __sub__(self, other):
+        self, other = self.__coerce__(other)
+        real = self.real - other.real
+        imag = self.imag - other.imag
+        return complex(real, imag)
+
+
+    def __mul__(self, other):
+        if other.__class__ != complex:
+            return complex(other*self.real, other*self.imag)
+
+        real = self.real*other.real - self.imag*other.imag
+        imag = self.real*other.imag + self.imag*other.real
+        return complex(real, imag)
+
+
+    def __div__(self, other):
+        if other.__class__ != complex:
+            return complex(self.real/other, self.imag/other)
+
+        if other.real < 0:
+            abs_breal = -other.real
+        else: 
+            abs_breal = other.real
+      
+        if other.imag < 0:
+            abs_bimag = -other.imag
+        else:
+            abs_bimag = other.imag
+
+        if abs_breal >= abs_bimag:
+            # divide tops and bottom by other.real
+            if abs_breal == 0.0:
+                real = imag = 0.0
+            else:
+                ratio = other.imag / other.real
+                denom = other.real + other.imag * ratio
+                real = (self.real + self.imag * ratio) / denom
+                imag = (self.imag - self.real * ratio) / denom
+        else:
+            # divide tops and bottom by other.imag
+            ratio = other.real / other.imag
+            denom = other.real * ratio + other.imag
+            assert other.imag != 0.0
+            real = (self.real * ratio + self.imag) / denom
+            imag = (self.imag * ratio - self.real) / denom
+
+        return complex(real, imag)
+
+
+    def __d_i_v__(self, other):
+        # the canonical alternative, which is said to have problems 
+        # with floating point precision...
+        if other.__class__ != complex:
+            return complex(self.real/other, self.imag/other)
+
+        a, b = self.real, self.imag
+        c, d = other.real, other.imag
+        zr = a*c + b*d
+        zi = b*c - a*d
+        n = c*c + d*d
+
+        return complex(zr/n, zi/n)
+
+
+    def __floordiv__(self, other):
+        return self / other
+        
+        
+    def __truediv__(self, other):
+        return self / other
+        
+
+    def __mod__(self, other):
+        warnings.warn("complex divmod(), // and % are deprecated", DeprecationWarning)
+
+        if other.real == 0. and other.imag == 0.:
+            raise ZeroDivisionError, "complex remainder"
+
+        div = self/other # The raw divisor value.
+        div = complex(math.floor(div.real), 0.0)
+        mod = self - div*other
+
+        if mod.__class__ == complex:
+            return mod
+        else:
+            return complex(mod)
+
+
+    def __divmod__(self, other):
+        warnings.warn("complex divmod(), // and % are deprecated", DeprecationWarning)
+
+        if other.real == 0. and other.imag == 0.:
+            raise ZeroDivisionError, "complex remainder"
+
+        div = self/other # The raw divisor value.
+        div = complex(math.floor(div.real), 0.0)
+        mod = self - div*other
+        return div, mod
+
+
+    def __pow__(self, other):
+        if other.__class__ != complex:
+            other = complex(other, 0)
+                    
+        a, b = self, other
+
+        if b.real == 0. and b.imag == 0.:
+            real = 1.
+            imag = 0.
+        elif a.real == 0. and a.imag == 0.:
+            real = 0.
+            imag = 0.
+        else:
+            vabs = math.hypot(a.real,a.imag)
+            len = math.pow(vabs,b.real)
+            at = math.atan2(a.imag, a.real)
+            phase = at*b.real
+            if b.imag != 0.0:
+                len /= math.exp(at*b.imag)
+                phase += b.imag*math.log(vabs)
+            real = len*math.cos(phase)
+            imag = len*math.sin(phase)
+
+        return complex(real, imag)
+
+
+    def __neg__(self):
+        return complex(-self.real, -self.imag)
+
+
+    def __pos__(self):
+        return complex(self.real, self.imag)
+
+
+    def __abs__(self):
+        result = math.hypot(self.real, self.imag)
+        return float(result)
+
+
+    def __nonzero__(self):
+        return self.real != 0.0 or self.imag != 0.0
+
+
+    def __coerce__(self, other):
+        typ = type(other)
+        
+        if typ is types.IntType:
+            return self, complex(float(other))
+        elif typ is types.LongType:
+            return self, complex(float(other))
+        elif typ is types.FloatType:
+            return self, complex(other)
+        elif other.__class__ == complex:
+            return self, other
+
+        raise TypeError, "number coercion failed"
+
+
+    def conjugate(self):
+        return complex(self.real, -self.imag)
+
+
+    def __ne__(self, other):
+        if self.real != other.real:
+            return 1
+        if self.imag != other.imag:
+            return 1
+        return 0            
+
+
+    # unsupported operations
+    
+    def __lt__(self, other):
+        raise TypeError, "cannot compare complex numbers using <, <=, >, >="
+
+        
+    def __le__(self, other):
+        raise TypeError, "cannot compare complex numbers using <, <=, >, >="
+
+        
+    def __gt__(self, other):
+        raise TypeError, "cannot compare complex numbers using <, <=, >, >="
+
+        
+    def __ge__(self, other):
+        raise TypeError, "cannot compare complex numbers using <, <=, >, >="
+
+
+    def __int__(self):
+        raise TypeError, "can't convert complex to int; use e.g. int(abs(z))"
+
+
+    def __long__(self):
+        raise TypeError, "can't convert complex to long; use e.g. long(abs(z))"
+
+
+    def __float__(self):
+        raise TypeError, "can't convert complex to float; use e.g. float(abs(z))"
+
+
+    def _unsupportedOp(self, other, op):
+        selfTypeName = type(self).__name__
+        otherTypeName = type(other).__name__
+        args = (op, selfTypeName, otherTypeName)
+        msg = "unsupported operand type(s) for %s: '%s' and '%s'" % args
+        raise TypeError, msg
+
+
+    def __and__(self, other):
+        self._unsupportedOp(self, other, "&")
+
+
+    def __or__(self, other):
+        self._unsupportedOp(self, other, "|")
+
+
+    def __xor__(self, other):
+        self._unsupportedOp(self, other, "^")
+
+
+    def __rshift__(self, other):
+        self._unsupportedOp(self, other, ">>")
+
+
+    def __lshift__(self, other):
+        self._unsupportedOp(self, other, "<<")
+
+
+    def __iand__(self, other):
+        self._unsupportedOp(self, other, "&=")
+
+
+    def __ior__(self, other):
+        self._unsupportedOp(self, other, "|=")
+
+
+    def __ixor__(self, other):
+        self._unsupportedOp(self, other, "^=")
+
+
+    def __irshift__(self, other):
+        self._unsupportedOp(self, other, ">>=")
+
+
+    def __ilshift__(self, other):
+        self._unsupportedOp(self, other, "<<=")
+
+
+    # augmented assignment operations
+    
+    def __iadd__(self, other):
+        return self + other
+    
+
+    def __isub__(self, other):
+        return self - other
+    
+
+    def __imul__(self, other):
+        return self * other
+    
+
+    def __idiv__(self, other):
+        return self / other
+    
+
+#    def __new__(self, ...):
+#        pass
+
+
+# test mod, divmod
+
+# add radd, rsub, rmul, rdiv...
+

File pypy/appspace/test/setpath.py

+import sys, os
+
+dirname = os.path.dirname
+
+testdir   = dirname(os.path.abspath(__file__))
+parentdir = dirname(testdir)
+rootdir   = dirname(parentdir)
+
+del dirname
+
+sys.path.insert(0, rootdir)
+
+# rootdir should probably be one level up, since then you
+# could really import pypy.appsapce... and not just from
+# appspace... 

File pypy/appspace/test/test_cmathmodule.py

+#!/usr/bin/env python
+
+# taken from CPython 2.3
+
+"""
+Test module for functions in cmathmodule.py
+
+It seems the log and log10 functions are generating errors
+due to numerical problems with floor() in complex.__div__.
+"""
+
+import math
+import cmath
+import sys
+import types
+import unittest
+
+try:
+    import setpath
+    from appspace import cmathmodule
+    from appspace.complexobject import complex as pycomplex
+except ImportError:
+    import cmathmodule
+    from complexobject import complex as pycomplex
+
+from test_complexobject import equal, enumerate
+
+
+class TestCMathModule(unittest.TestCase):
+
+    def test_funcs(self):
+        "Compare many functions with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            mc = z0c*z1c
+            mp = z0p*z1p
+            self.assert_(equal(mc, mp))
+
+            for op in "sqrt acos acosh asin asinh atan atanh cos cosh exp".split():
+                if op == "atan" and equal(z0c, complex(0,-1)) or equal(z0c, complex(0,1)):
+                    continue
+                if op == "atanh" and equal(z0c, complex(-1,0)) or equal(z0c, complex(1,0)):
+                    continue
+                op0 = cmath.__dict__[op](z0c)
+                op1 = cmathmodule.__dict__[op](z0p)
+                self.assert_(equal(op0, op1))
+
+            # check divisions
+            if equal(z0c, complex(0,0)) or equal(z1c, complex(0,0)):
+                continue
+            self.assert_(equal(mc/z0c, mp/z0p))
+            self.assert_(equal(mc/z1c, mp/z1p))
+
+
+    def test_log_log10(self):
+        "Compare log/log10 functions with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            for op in "log log10".split():
+                op0 = cmath.__dict__[op](z0c)
+                op1 = cmathmodule.__dict__[op](z0p)
+                self.assert_(equal(op0, op1))
+
+
+
+if __name__ == "__main__":
+    unittest.main()

File pypy/appspace/test/test_complexobject.py

+#!/usr/bin/env python
+
+#taken from CPython 2.3 (?)
+
+"""
+Test module for class complex in complexobject.py
+
+As it seems there are some numerical differences in 
+the __div__ and __divmod__ methods which have to be 
+sorted out.
+"""
+
+
+import math
+import cmath
+import sys
+import types
+import unittest
+
+
+try:
+    import setpath
+    from appspace.complexobject import complex as pycomplex
+except ImportError:
+    from complexobject import complex as pycomplex
+
+
+try:
+    unicode
+    have_unicode = 1
+except NameError:
+    have_unicode = 0
+
+
+def equal(a, b):
+    "Compare two complex or normal numbers. 0 if different, 1 if roughly equal."
+    
+    numTypes = [types.IntType, types.LongType, types.FloatType]
+    da, db = dir(a), dir(b)
+    
+    if 'real' in da and 'real' in db and 'imag' in da and 'imag' in db:
+        if math.fabs(a.real-b.real) > 1e-10:
+            return 0
+        if math.fabs(a.imag-b.imag) > 1e-10:
+            return 0
+        else:
+            return 1
+    elif type(a) in numTypes and type(b) in numTypes:
+        if math.fabs(a-b) > 1e-10:
+            return 0
+        else:
+            return 1
+    
+
+
+
+def enumerate():
+    valueRange = xrange(-3, 3)
+    res = []
+    for x0 in valueRange:
+        for y0 in valueRange:
+            for x1 in valueRange:
+                for y1 in valueRange:
+                    z0c = complex(x0,y0)
+                    z1c = complex(x1,y1)
+                    z0p = pycomplex(x0,y0)
+                    z1p = pycomplex(x1,y1)
+                    res.append((z0c, z1c, z0p, z1p))
+
+    return res
+
+
+
+
+class TestComplex(unittest.TestCase):
+
+    def test_wrongInit1(self):
+        "Compare wrong init. with CPython."
+        
+        try:
+            complex("1", "1")
+        except TypeError:
+            pass
+        else:
+            self.fail('complex("1", "1")')
+
+        try:
+            pycomplex("1", "1")
+        except TypeError:
+            pass
+        else:
+            self.fail('complex("1", "1")')
+
+
+    def test_wrongInit2(self):
+        "Compare wrong init. with CPython."
+        
+        try:
+            complex(1, "1")
+        except TypeError:
+            pass
+        else:
+            self.fail('complex(1, "1")')
+
+        try:
+            pycomplex(1, "1")
+        except TypeError:
+            pass
+        else:
+            self.fail('complex(1, "1")')
+
+
+    def test_wrongInitFromString(self):
+        "Compare string init. with CPython."
+
+        if complex("  3.14+J  ") != 3.14+1j:
+            self.fail('complex("  3.14+J  )"')
+        if not equal(pycomplex("  3.14+J  "), pycomplex(3.14,1)):
+            self.fail('complex("  3.14+J  )"')
+
+
+    def test_wrongInitFromUnicodeString(self):
+        "Compare unicode string init. with CPython."
+
+        if have_unicode:
+            if complex(unicode("  3.14+J  ")) != 3.14+1j:
+                self.fail('complex(u"  3.14+J  )"')
+            if not equal(pycomplex(unicode("  3.14+J  ")), pycomplex(3.14, 1)):
+                self.fail('complex(u"  3.14+J  )"')
+
+
+    def test_class(self):
+        "Compare class with CPython."
+        
+        class Z:
+            def __complex__(self):
+                return 3.14j
+        z = Z()
+        if complex(z) != 3.14j:
+            self.fail('complex(classinstance)')
+
+        if not equal(complex(z), pycomplex(0, 3.14)): 
+            self.fail('complex(classinstance)')
+
+
+    def test_add_sub_mul_div(self):
+        "Compare add/sub/mul/div with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            mc = z0c*z1c
+            mp = z0p*z1p
+            self.assert_(equal(mc, mp))
+
+            sc = z0c+z1c
+            sp = z0p+z1p
+            self.assert_(equal(sc, sp))
+
+            dc = z0c-z1c
+            dp = z0p-z1p
+            self.assert_(equal(dc, dp))
+
+            if not equal(z1c, complex(0,0)): 
+                try:
+                    qc = z0c/z1c
+                    qp = z0p/z1p
+                    self.assert_(equal(qc, qp))
+                except AssertionError:
+                    print "c: (%s/%s) = (%s)" % (z0c, z1c, qc)
+                    print "py:(%s/%s) = (%s)" % (z0p, z1p, qp)
+
+                
+    def test_special(self):
+        "Compare special methods with CPython."
+        
+        ass = self.assert_
+        for (x, y) in [(0,0), (0,1), (1,3.)]:
+            zc = complex(x, y)
+            zp = pycomplex(x, y)
+
+            ass(equal(zc, zp), "%s != %s" % (zc, zp))
+            ass(equal(-zc, -zp), "%s != %s" % (-zc, -zp))
+            ass(equal(+zc, +zp), "%s != %s" % (+zc, +zp))
+            ass(equal(abs(zc), abs(zp)), "%s != %s" % (abs(zc), abs(zp)))
+            ass(equal(zc.conjugate(), zp.conjugate()), "%s != %s" % (zc.conjugate(), zp.conjugate()))
+            ass(str(zc) == str(zp), "str(%s) != str(%s)" % (str(zc), str(zp)))
+            ass(hash(zc) == hash(zp), "%s == hash(%s) != hash(%s) == %s" % (hash(zc), zc, zp, hash(zp)))
+
+
+    def test_divmod(self):
+        "Compare divmod with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            mc = z0c*z1c
+            mp = z0p*z1p
+            self.assert_(equal(mc, mp))
+
+            if not equal(z1c, complex(0,0)): 
+                try:
+                    ddc, mmc = divmod(z0c, z1c)
+                    self.assert_(ddc*z1c + mmc == z0c)
+                    ddp, mmp = divmod(z0p, z1p)
+                    # self.assert_(ddp*z1p + mmp == z0p)
+                    self.assert_(equal(ddc, ddp))
+                    self.assert_(equal(mmc, mmp))
+                except AssertionError:
+                    print "c: divmod(%s,%s) = (%s,%s)" % (z0c, z1c, ddc,mmc)
+                    print "py:divmod(%s,%s) = (%s,%s)" % (z0p, z1p, ddp,mmp)
+
+
+    def test_mod(self):
+        "Compare mod with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            mc = z0c*z1c
+            mp = z0p*z1p
+            self.assert_(equal(mc, mp))
+
+            if not equal(z1c, complex(0,0)): 
+                try:
+                    rc = z0c%z1c
+                    rp = z0p%z1p
+                    self.assert_(equal(rc, rp))
+                except AssertionError:
+                    print "c: %s%%%s = %s" % (z0c, z1c, rc)
+                    print "py:%s%%%s = %s" % (z0p, z1p, rp)
+                    
+
+    def test_pow(self):
+        "Compare pow with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            if not equal(z0c, 0j) and (z1c.imag != 0.0):
+                pc = z0c**z1c
+                pp = z0p**z1p
+                assert equal(pc, pp)
+                pc = z0c**z0c.real
+                pp = z0p**z0p.real
+                self.assert_(equal(pc, pp))
+
+
+
+# used previously for investigating numerical instabilities
+
+def dm(self, other):
+    # a divmod like used in complex.
+    
+    div = self/other
+    print div
+    div = complex(math.floor(div.real), 0.0)
+    print div
+    mod = self - div*other
+    print mod
+    return div, mod
+
+
+def testNumericalInstability():
+    x, y = -3+1j, -1-3j
+    print x, y, divmod(x, y)
+    print x/y
+    print math.floor((x/y).real)+0j
+    print
+
+    x, y = complex(-3,1), complex(-1,-3)
+    print x, y
+    dm(x, y)
+
+
+
+
+if __name__ == "__main__":
+    unittest.main()

File pypy/interpreter/__init__.py

+# empty

File pypy/interpreter/appfile.py

+import os
+
+
+class AppFile:
+    """Dynamic loader of a set of Python functions and objects that
+    should work at the application level (conventionally in .app.py files)"""
+
+    # absolute name of the parent directory
+    ROOTDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+    DEFAULT_PATH_EXT = [('appspace', '.py')]
+    LOCAL_PATH = []
+
+    def __init__(self, modulename, localpath=[]):
+        "Load and compile the helper file."
+        # XXX looking for a pre-compiled file here will be quite essential
+        #     when we want to bootstrap the compiler
+
+        # 'modulename' could be 'package.module' if passed in as __name__
+        # we ignore that package part
+        modulename = modulename.split('.')[-1]
+        path_ext = [(path, '_app.py') for path in localpath + self.LOCAL_PATH]
+        for path, ext in path_ext + self.DEFAULT_PATH_EXT:
+            dirname = os.path.join(self.ROOTDIR, path.replace('.', os.sep))
+            filename = os.path.join(dirname, modulename+ext)
+            if os.path.exists(filename):
+                break
+        else:
+            raise IOError, "cannot locate helper module '%s' in %s" % (
+                modulename, lookuppaths_ext)
+        f = open(filename, 'r')
+        src = f.read()
+        f.close()
+        self.bytecode = compile(src, filename, 'exec')
+
+
+class Namespace:
+
+    def __init__(self, space):
+        self.space = space
+        ec = space.getexecutioncontext()
+        self.w_namespace = ec.make_standard_w_globals()
+
+    def get(self, objname):
+        "Returns a wrapped copy of an object by name."
+        w_name = self.space.wrap(objname)
+        w_obj = self.space.getitem(self.w_namespace, w_name)
+        return w_obj
+
+    def call(self, functionname, argumentslist):
+        "Call a module function."
+        w_function = self.get(functionname)
+        w_arguments = self.space.newtuple(argumentslist)
+        w_keywords = self.space.newdict([])
+        return self.space.call(w_function, w_arguments, w_keywords)
+
+    def runbytecode(self, bytecode):
+        # initialize the module by running the bytecode in a new
+        # dictionary, in a new execution context
+        from pyframe import PyFrame
+        ec = self.space.getexecutioncontext()
+        frame = PyFrame(self.space, bytecode,
+                                self.w_namespace, self.w_namespace)
+        ec.eval_frame(frame)
+
+
+class AppHelper(Namespace):
+
+    def __init__(self, space, bytecode):
+        Namespace.__init__(self, space)
+        self.runbytecode(bytecode)

File pypy/interpreter/baseobjspace.py

+
+__all__ = ['ObjSpace', 'OperationError', 'NoValue']
+
+class OperationError(Exception):
+    """Interpreter-level exception that signals an exception that should be
+    sent to the application level.
+
+    OperationError instances have three public attributes (and no .args),
+    w_type, w_value and w_traceback, which contain the wrapped type, value
+    and traceback describing the exception."""
+
+    def __init__(self, w_type, w_value, w_traceback=None):
+        self.w_type = w_type
+        self.w_value = w_value
+        self.w_traceback = w_traceback
+        ### DEBUG DUMP ###
+        #self.nicetraceback(None)
+    
+    def __str__(self):
+        "Convenience for tracebacks."
+        return '[%s: %s]' % (self.w_type, self.w_value)
+    def nicetraceback(self, space):
+        "Dump a nice custom traceback to sys.stderr."
+        import sys, traceback
+        tb = sys.exc_info()[2]
+        if space is not None:
+            exc = space.unwrap(self.w_type)
+            value = space.unwrap(self.w_value)
+            msg = traceback.format_exception_only(exc, value)
+        else:
+            msg = '%r: %r' % (self.w_type, self.w_value)
+        print >> sys.stderr, "*"*10, " OperationError ", "*"*10
+        traceback.print_tb(tb)
+##         if self.w_traceback:
+##             traceback.print_tb(space.unwrap(self.w_traceback))
+        print >> sys.stderr, "[Application-level]", ''.join(msg).strip()
+        print >> sys.stderr, "*"*10
+
+class NoValue(Exception):
+    """Raised to signal absence of value, e.g. in the iterator accessing
+    method 'iternext()' of object spaces."""
+
+
+##################################################################
+
+import executioncontext, pyframe
+
+
+class ObjSpace:
+    """Base class for the interpreter-level implementations of object spaces.
+    XXX describe here in more details what the object spaces are."""
+
+    def __init__(self):
+        "Basic initialization of objects.  Override me."
+        self.w_builtins = self.newdict([])
+        self.w_modules  = self.newdict([])
+        self.appfile_helpers = {}
+        self.initialize()
+        #import builtins
+        #builtins.init(self)
+
+    def initialize(self):
+        """Abstract method that should put some minimal content into the
+        w_builtins."""
+
+    def getexecutioncontext(self):
+        "Return what we consider to be the active execution context."
+        import sys
+        f = sys._getframe()           # !!hack!!
+        while f:
+            if f.f_locals.has_key('__executioncontext__'):
+                result = f.f_locals['__executioncontext__']
+                if result.space is self:
+                    return result
+            f = f.f_back
+        return executioncontext.ExecutionContext(self)
+
+    def gethelper(self, applicationfile):
+        try:
+            helper = self.appfile_helpers[applicationfile]
+        except KeyError:
+            from appfile import AppHelper
+            helper = AppHelper(self, applicationfile.bytecode)
+            self.appfile_helpers[applicationfile] = helper
+        return helper
+
+    # Following is a friendly interface to common object space operations
+    # that can be defined in term of more primitive ones
+
+    def unpackiterable(self, w_iterable, expected_length=None):
+        """Unpack an iterable object into a real (interpreter-level) list.
+        Raise a real ValueError if the length is wrong."""
+        w_iterator = self.getiter(w_iterable)
+        items = []
+        while True:
+            try:
+                w_item = self.iternext(w_iterator)
+            except NoValue:
+                break  # done
+            if expected_length is not None and len(items) == expected_length:
+                raise ValueError, "too many values to unpack"
+            items.append(w_item)
+        if expected_length is not None and len(items) < expected_length:
+            i = len(items)
+            if i == 1:
+                plural = ""
+            else:
+                plural = "s"
+            raise ValueError, "need more than %d value%s to unpack" % (i, plural)
+        return items
+
+
+## Table describing the regular part of the interface of object spaces,
+## namely all methods which only take w_ arguments and return a w_ result.
+
+ObjSpace.MethodTable = [
+# method name # symbol # number of arguments
+    ('type',            'type',     1),
+    ('checktype',       'type?',    2),
+    ('repr',            'repr',     1),
+    ('str',             'str',      1),
+    ('getattr',         'getattr',  2),
+    ('setattr',         'setattr',  3),
+    ('delattr',         'delattr',  2),
+    ('getitem',         'getitem',  2),
+    ('setitem',         'setitem',  3),
+    ('delitem',         'delitem',  2),
+    ('pos',             'unary+',   1),
+    ('neg',             'unary-',   1),
+    ('not_',            'not',      1),
+    ('abs' ,            'abs',      1),
+    ('invert',          '~',        1),
+    ('add',             '+',        2),
+    ('sub',             '-',        2),
+    ('mul',             '*',        2),
+    ('truediv',         '/',        2),
+    ('floordiv',        '//',       2),
+    ('div',             'div',      2),
+    ('mod',             '%',        2),
+    ('divmod',          'divmod',   2),
+    ('pow',             '**',       3),
+    ('lshift',          '<<',       2),
+    ('rshift',          '>>',       2),
+    ('and_',            '&',        2),
+    ('or_',             '|',        2),
+    ('xor',             '^',        2),
+    ('inplace_add',     '+=',       2),
+    ('inplace_sub',     '-=',       2),
+    ('inplace_mul',     '*=',       2),
+    ('inplace_truediv', '/=',       2),
+    ('inplace_floordiv','//=',      2),
+    ('inplace_div',     'div=',     2),
+    ('inplace_mod',     '%=',       2),
+    ('inplace_pow',     '**=',      2),
+    ('inplace_lshift',  '<<=',      2),
+    ('inplace_rshift',  '>>=',      2),
+    ('inplace_and',     '&=',       2),
+    ('inplace_or',      '|=',       2),
+    ('inplace_xor',     '^=',       2),
+    ('getiter',         'iter',     1),
+    ('iternext',        'next',     1),
+    ('call',            'call',     3),
+    ]
+
+## Irregular part of the interface:
+#
+#                        wrap(x) -> w_x
+#                    unwrap(w_x) -> x
+#                   is_true(w_x) -> True or False
+#                      hash(w_x) -> int
+#          compare(w_x, w_y, op) -> w_result
+#       newtuple([w_1, w_2,...]) -> w_tuple
+#        newlist([w_1, w_2,...]) -> w_list
+# newdict([(w_key,w_value),...]) -> w_dict
+# newslice(w_start,w_stop,w_end) -> w_slice     (w_end may be a real None)
+#               newfunction(...) -> w_function
+#

File pypy/interpreter/executioncontext.py

+import sys
+
+class ExecutionContext:
+
+    def __init__(self, space):
+        self.space = space
+        self.framestack = []
+
+    def eval_frame(self, frame):
+        __executioncontext__ = self
+        self.framestack.append(frame)
+        try:
+            result = frame.eval(self)
+        finally:
+            self.framestack.pop()
+        return result
+
+    def get_w_builtins(self):
+        if self.framestack:
+            return self.framestack[-1].w_builtins
+        else:
+            return self.space.w_builtins
+
+    def make_standard_w_globals(self):
+        "Create a new empty 'globals' dictionary."
+        w_key = self.space.wrap("__builtins__")
+        w_value = self.get_w_builtins()
+        w_globals = self.space.newdict([(w_key, w_value)])
+        return w_globals
+
+    def exception_trace(self, operationerr):
+        "Trace function called upon OperationError."
+        operationerr.nicetraceback(self.space)

File pypy/interpreter/interactive.py

+from pypy.interpreter import executioncontext
+from pypy.interpreter import pyframe
+from pypy.interpreter import baseobjspace
+from pypy.objspace import trivial
+import code
+import linecache
+
+def offset2lineno(c, stopat):
+    tab = c.co_lnotab
+    line = c.co_firstlineno
+    addr = 0
+    for i in range(0, len(tab), 2):
+        addr = addr + ord(tab[i])
+        if addr > stopat:
+            break
+        line = line + ord(tab[i+1])
+    return line
+
+class PyPyConsole(code.InteractiveConsole):
+    def __init__(self):
+        code.InteractiveConsole.__init__(self)
+        self.space = trivial.TrivialObjSpace()
+        self.ec = executioncontext.ExecutionContext(self.space)
+        self.locals['__builtins__'] = self.space.w_builtins
+
+    def runcode(self, code):
+        # ah ha!
+        frame = pyframe.PyFrame(self.space, code,
+                        self.locals, self.locals)
+        try:
+            self.ec.eval_frame(frame)
+        except baseobjspace.OperationError, e:
+            print "Traceback"
+            tb = e.w_traceback[:]
+            tb.reverse()
+            for f, i in tb:
+                co = f.bytecode
+                fname = co.co_filename
+                lineno = offset2lineno(co, i)
+                print "  File", `fname`+',',
+                print "line", lineno, "in", co.co_name
+                l = linecache.getline(fname, lineno)
+                if l:
+                    print l[:-1]
+            print e.w_type.__name__+':', e.w_value
+            import traceback
+            traceback.print_exc()
+        
+if __name__ == '__main__':
+    con = PyPyConsole()
+    con.interact()
+

File pypy/interpreter/opcode.py

+import dis, pyframe, baseobjspace
+from appfile import AppFile
+from baseobjspace import OperationError, NoValue
+
+
+# dynamically loaded application-space utilities
+appfile = AppFile(__name__, ["interpreter"])
+
+
+class unaryoperation:
+    def __init__(self, operationname):
+        self.operationname = operationname
+    def __call__(self, f):
+        operation = getattr(f.space, self.operationname)
+        w_1 = f.valuestack.pop()
+        w_result = operation(w_1)
+        f.valuestack.push(w_result)
+
+class binaryoperation:
+    def __init__(self, operationname):
+        self.operationname = operationname
+    def __call__(self, f):
+        operation = getattr(f.space, self.operationname)
+        w_2 = f.valuestack.pop()
+        w_1 = f.valuestack.pop()
+        w_result = operation(w_1, w_2)
+        f.valuestack.push(w_result)
+
+
+################################################################
+##  Implementation of the opcodes
+##
+
+def LOAD_FAST(f, varindex):
+    varname = f.getlocalvarname(varindex)
+    w_varname = f.space.wrap(varname)
+    w_value = f.space.getitem(f.w_locals, w_varname)
+    # XXX catch KeyError and make it a NameError
+    f.valuestack.push(w_value)
+
+def LOAD_CONST(f, constindex):
+    w_const = f.space.wrap(f.getconstant(constindex))
+    f.valuestack.push(w_const)
+
+def STORE_FAST(f, varindex):
+    varname = f.getlocalvarname(varindex)
+    w_varname = f.space.wrap(varname)
+    w_value = f.valuestack.pop()
+    f.space.setitem(f.w_locals, w_varname, w_value)
+
+def POP_TOP(f):
+    f.valuestack.pop()
+
+def ROT_TWO(f):
+    w_1 = f.valuestack.pop()
+    w_2 = f.valuestack.pop()
+    f.valuestack.push(w_1)
+    f.valuestack.push(w_2)
+
+def ROT_THREE(f):
+    w_1 = f.valuestack.pop()
+    w_2 = f.valuestack.pop()
+    w_3 = f.valuestack.pop()
+    f.valuestack.push(w_1)
+    f.valuestack.push(w_3)
+    f.valuestack.push(w_2)
+
+def ROT_FOUR(f):
+    w_1 = f.valuestack.pop()
+    w_2 = f.valuestack.pop()
+    w_3 = f.valuestack.pop()
+    w_4 = f.valuestack.pop()
+    f.valuestack.push(w_1)
+    f.valuestack.push(w_4)
+    f.valuestack.push(w_3)
+    f.valuestack.push(w_2)
+
+def DUP_TOP(f):
+    w_1 = f.valuestack.top()
+    f.valuestack.push(w_1)
+
+def DUP_TOPX(f, itemcount):
+    assert 1 <= itemcount <= 5, "limitation of the current interpreter"
+    for i in range(itemcount):
+        w_1 = f.valuestack.top(itemcount-1)
+        f.valuestack.push(w_1)
+
+UNARY_POSITIVE = unaryoperation("pos")
+UNARY_NEGATIVE = unaryoperation("neg")
+UNARY_NOT      = unaryoperation("not_")
+UNARY_CONVERT  = unaryoperation("repr")
+UNARY_INVERT   = unaryoperation("invert")
+
+def BINARY_POWER(f):
+    w_2 = f.valuestack.pop()
+    w_1 = f.valuestack.pop()
+    w_result = f.space.pow(w_1, w_2, f.space.w_None)
+    f.valuestack.push(w_result)
+
+BINARY_MULTIPLY = binaryoperation("mul")
+BINARY_TRUE_DIVIDE  = binaryoperation("truediv")
+BINARY_FLOOR_DIVIDE = binaryoperation("floordiv")
+BINARY_DIVIDE       = binaryoperation("div")
+BINARY_MODULO       = binaryoperation("mod")
+BINARY_ADD      = binaryoperation("add")
+BINARY_SUBTRACT = binaryoperation("sub")
+BINARY_SUBSCR   = binaryoperation("getitem")
+BINARY_LSHIFT   = binaryoperation("lshift")
+BINARY_RSHIFT   = binaryoperation("rshift")
+BINARY_AND = binaryoperation("and_")
+BINARY_XOR = binaryoperation("xor")
+BINARY_OR  = binaryoperation("or_")
+
+def INPLACE_POWER(f):
+    w_2 = f.valuestack.pop()
+    w_1 = f.valuestack.pop()
+    w_result = f.space.inplace_pow(w_1, w_2, f.space.w_None)
+    f.valuestack.push(w_result)
+
+INPLACE_MULTIPLY = binaryoperation("inplace_mul")
+INPLACE_TRUE_DIVIDE  = binaryoperation("inplace_truediv")
+INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv")
+INPLACE_DIVIDE       = binaryoperation("inplace_div")
+INPLACE_MODULO       = binaryoperation("inplace_mod")
+INPLACE_ADD      = binaryoperation("inplace_add")
+INPLACE_SUBTRACT = binaryoperation("inplace_sub")
+INPLACE_LSHIFT   = binaryoperation("inplace_lshift")
+INPLACE_RSHIFT   = binaryoperation("inplace_rshift")
+INPLACE_AND = binaryoperation("inplace_and")
+INPLACE_XOR = binaryoperation("inplace_xor")
+INPLACE_OR  = binaryoperation("inplace_or")
+
+def slice(f, w_start, w_end):
+    w_slice = f.space.newslice(w_start, w_end, None)
+    w_obj = f.valuestack.pop()
+    w_result = f.space.getitem(w_obj, w_slice)
+    f.valuestack.push(w_result)
+
+def SLICE_0(f):
+    slice(f, None, None)
+
+def SLICE_1(f):
+    w_start = f.valuestack.pop()
+    slice(f, w_start, None)
+
+def SLICE_2(f):
+    w_end = f.valuestack.pop()
+    slice(f, None, w_end)
+
+def SLICE_3(f):
+    w_end = f.valuestack.pop()
+    w_start = f.valuestack.pop()
+    slice(f, w_start, w_end)
+
+def storeslice(f, w_start, w_end):
+    w_slice = f.space.newslice(w_start, w_end, None)
+    w_obj = f.valuestack.pop()
+    w_newvalue = f.valuestack.pop()
+    f.space.setitem(w_obj, w_slice, w_newvalue)
+
+def STORE_SLICE_0(f):
+    storeslice(f, None, None)
+
+def STORE_SLICE_1(f):
+    w_start = f.valuestack.pop()
+    storeslice(f, w_start, None)
+
+def STORE_SLICE_2(f):
+    w_end = f.valuestack.pop()
+    storeslice(f, None, w_end)
+
+def STORE_SLICE_3(f):
+    w_end = f.valuestack.pop()
+    w_start = f.valuestack.pop()
+    storeslice(f, w_start, w_end)
+
+def deleteslice(f, w_start, w_end):
+    w_slice = f.space.newslice(w_start, w_end, None)
+    w_obj = f.valuestack.pop()
+    f.space.delitem(w_obj, w_slice)
+
+def DELETE_SLICE_0(f):
+    deleteslice(f, None, None)
+
+def DELETE_SLICE_1(f):
+    w_start = f.valuestack.pop()
+    deleteslice(f, w_start, None)
+
+def DELETE_SLICE_2(f):
+    w_end = f.valuestack.pop()
+    deleteslice(f, None, w_end)
+
+def DELETE_SLICE_3(f):
+    w_end = f.valuestack.pop()
+    w_start = f.valuestack.pop()
+    deleteslice(f, w_start, w_end)
+
+def STORE_SUBSCR(f):
+    "obj[subscr] = newvalue"
+    w_subscr = f.valuestack.pop()
+    w_obj = f.valuestack.pop()
+    w_newvalue = f.valuestack.pop()
+    f.space.setitem(w_obj, w_subscr, w_newvalue)
+
+def DELETE_SUBSCR(f):
+    "del obj[subscr]"
+    w_subscr = f.valuestack.pop()
+    w_obj = f.valuestack.pop()
+    f.space.delitem(w_obj, w_subscr)
+
+def PRINT_EXPR(f):
+    w_expr = f.valuestack.pop()
+    f.space.gethelper(appfile).call("print_expr", [w_expr])
+
+def PRINT_ITEM_TO(f):
+    w_stream = f.valuestack.pop()
+    w_item = f.valuestack.pop()
+    f.space.gethelper(appfile).call("print_item_to", [w_item, w_stream])
+
+def PRINT_ITEM(f):
+    w_item = f.valuestack.pop()
+    f.space.gethelper(appfile).call("print_item", [w_item])
+
+def PRINT_NEWLINE_TO(f):
+    w_stream = f.valuestack.pop()
+    f.space.gethelper(appfile).call("print_newline_to", [w_stream])
+
+def PRINT_NEWLINE(f):
+    f.space.gethelper(appfile).call("print_newline", [])
+
+def BREAK_LOOP(f):
+    raise pyframe.SBreakLoop
+
+def CONTINUE_LOOP(f, startofloop):
+    raise pyframe.SContinueLoop(startofloop)
+
+def RAISE_VARARGS(f, nbargs):
+    # we use the .app.py file to prepare the exception/value/traceback
+    # but not to actually raise it, because we cannot use the 'raise'
+    # statement to implement RAISE_VARARGS
+    if nbargs == 0:
+        w_resulttuple = f.space.gethelper(appfile).call("prepare_raise0")
+    elif nbargs == 1:
+        w_type = f.valuestack.pop()
+        w_resulttuple = f.space.gethelper(appfile).call(
+            "prepare_raise", [w_type, None, None])
+    elif nbargs == 2:
+        w_value = f.valuestack.pop()
+        w_type  = f.valuestack.pop()
+        w_resulttuple = f.space.gethelper(appfile).call(
+            "prepare_raise", [w_type, w_value, None])
+    elif nbargs == 3:
+        w_traceback = f.valuestack.pop()
+        w_value     = f.valuestack.pop()
+        w_type      = f.valuestack.pop()
+        w_resulttuple = f.space.gethelper(appfile).call(
+            "prepare_raise", [w_type, w_value, w_traceback])
+    else:
+        raise pyframe.BytecodeCorruption, "bad RAISE_VARARGS oparg"
+    w_type, w_value, w_traceback = f.space.unpackiterable(w_resulttuple)
+    raise OperationError(w_type, w_value, w_traceback)
+
+def LOAD_LOCALS(f):
+    f.valuestack.push(f.w_locals)
+
+def RETURN_VALUE(f):
+    w_returnvalue = f.valuestack.pop()
+    raise pyframe.SReturnValue(w_returnvalue)
+
+def YIELD_VALUE(f):
+    w_yieldedvalue = f.valuestack.pop()
+    raise pyframe.SYieldValue(w_yieldedvalue)
+YIELD_STMT = YIELD_VALUE  # misnamed in dis.opname
+
+def EXEC_STMT(f):
+    w_locals  = f.valuestack.pop()
+    w_globals = f.valuestack.pop()
+    w_prog    = f.valuestack.pop()
+    f.space.gethelper(appfile).call("exec_statement",
+                                    [w_prog, w_globals, w_locals,
+                                     f.w_builtins, f.w_globals, f.w_locals])
+
+def POP_BLOCK(f):
+    block = f.blockstack.pop()
+    block.cleanup(f)  # the block knows how to clean up the value stack
+
+def END_FINALLY(f):
+    # unlike CPython, the information on what to do at the end
+    # of a 'finally' is not stored in the value stack, but in
+    # the block stack, in a new dedicated block type which knows
+    # how to restore the environment (exception, break/continue...)
+    # at the beginning of the 'finally'.
+    block = f.blockstack.pop()
+    block.cleanup(f)
+
+def BUILD_CLASS(f):
+    w_methodsdict = f.valuestack.pop()
+    w_bases       = f.valuestack.pop()
+    w_name        = f.valuestack.pop()
+    w_newclass = f.space.gethelper(appfile).call(
+        "build_class", [w_methodsdict, w_bases, w_name])
+    f.valuestack.push(w_newclass)
+
+def STORE_NAME(f, varindex):
+    varname = f.getname(varindex)
+    w_varname = f.space.wrap(varname)
+    w_newvalue = f.valuestack.pop()
+    f.space.setitem(f.w_locals, w_varname, w_newvalue)
+
+def DELETE_NAME(f, varindex):
+    varname = f.getname(varindex)
+    w_varname = f.space.wrap(varname)
+    f.space.delitem(f.w_locals, w_varname)
+    # XXX catch KeyError and make it a NameError
+
+def UNPACK_SEQUENCE(f, itemcount):
+    w_iterable = f.valuestack.pop()
+    try:
+        items = f.space.unpackiterable(w_iterable, itemcount)
+    except ValueError, e:
+        raise OperationError(f.space.w_ValueError, f.space.wrap(str(e)))
+    items.reverse()
+    for item in items:
+        f.valuestack.push(item)
+
+def STORE_ATTR(f, nameindex):
+    "obj.attributename = newvalue"
+    attributename = f.getname(nameindex)
+    w_attributename = f.space.wrap(attributename)
+    w_obj = f.valuestack.pop()
+    w_newvalue = f.valuestack.pop()
+    f.space.setattr(w_obj, w_attributename, w_newvalue)
+
+def DELETE_ATTR(f, nameindex):
+    "del obj.attributename"
+    attributename = f.getname(nameindex)
+    w_attributename = f.space.wrap(attributename)
+    w_obj = f.valuestack.pop()
+    f.space.delattr(w_obj, w_attributename)
+
+def STORE_GLOBAL(f, nameindex):
+    varname = f.getname(nameindex)
+    w_varname = f.space.wrap(varname)
+    w_newvalue = f.valuestack.pop()
+    f.space.setitem(f.w_globals, w_varname, w_newvalue)
+
+def DELETE_GLOBAL(f, nameindex):
+    varname = f.getname(nameindex)
+    w_varname = f.space.wrap(varname)
+    f.space.delitem(f.w_globals, w_varname)
+
+def LOAD_NAME(f, nameindex):
+    varname = f.getname(nameindex)
+    w_varname = f.space.wrap(varname)
+    w_value = f.space.gethelper(appfile).call(
+        "load_name", [w_varname, f.w_locals, f.w_globals, f.w_builtins])
+    f.valuestack.push(w_value)
+
+def LOAD_GLOBAL(f, nameindex):
+    varname = f.getname(nameindex)
+    w_varname = f.space.wrap(varname)
+    try:
+        w_value = f.space.getitem(f.w_globals, w_varname)
+    except OperationError, e:
+        # catch KeyErrors
+        w_KeyError = f.space.w_KeyError
+        w_match = f.space.compare(e.w_type, w_KeyError, "exc match")
+        if not f.space.is_true(w_match):
+            raise
+        # we got a KeyError, now look in the built-ins
+        try:
+            w_value = f.space.getitem(f.w_builtins, w_varname)
+        except OperationError, e:
+            # catch KeyErrors again
+            w_match = f.space.compare(e.w_type, w_KeyError, "exc match")
+            if not f.space.is_true(w_match):
+                raise
+            message = "global name '%s' is not defined" % varname
+            w_exc_type = f.space.w_NameError
+            w_exc_value = f.space.wrap(message)
+            raise OperationError(w_exc_type, w_exc_value)
+    f.valuestack.push(w_value)
+
+def DELETE_FAST(f, varindex):
+    varname = f.getlocalvarname(varindex)
+    w_varname = f.space.wrap(varname)
+    f.space.delitem(f.w_locals, w_varname)
+    # XXX catch KeyError and make it a NameError
+
+def LOAD_CLOSURE(f, varindex):
+    # nested scopes: access the cell object
+    # XXX at some point implement an explicit traversal of
+    #     syntactically nested frames?
+    varname = f.getfreevarname(varindex)
+    w_varname = f.space.wrap(varname)
+    w_value = f.space.gethelper(appfile).call("load_closure",
+                                              [f.w_locals, w_varname])
+    f.valuestack.push(w_value)
+
+def LOAD_DEREF(f, varindex):
+    # nested scopes: access a variable through its cell object
+    varname = f.getfreevarname(varindex)
+    w_varname = f.space.wrap(varname)
+    w_value = f.space.getitem(f.w_locals, w_varname)
+    # XXX catch KeyError and make it a NameError
+    f.valuestack.push(w_value)
+
+def STORE_DEREF(f, varindex):
+    # nested scopes: access a variable through its cell object
+    varname = f.getfreevarname(varindex)
+    w_varname = f.space.wrap(varname)
+    w_newvalue = f.valuestack.pop()
+    f.space.setitem(f.w_locals, w_varname, w_newvalue)
+
+def BUILD_TUPLE(f, itemcount):
+    items = [f.valuestack.pop() for i in range(itemcount)]
+    items.reverse()
+    w_tuple = f.space.newtuple(items)
+    f.valuestack.push(w_tuple)
+
+def BUILD_LIST(f, itemcount):
+    items = [f.valuestack.pop() for i in range(itemcount)]
+    items.reverse()
+    w_list = f.space.newlist(items)
+    f.valuestack.push(w_list)
+
+def BUILD_MAP(f, zero):
+    if zero != 0:
+        raise pyframe.BytecodeCorruption
+    w_dict = f.space.newdict([])
+    f.valuestack.push(w_dict)
+
+def LOAD_ATTR(f, nameindex):
+    "obj.attributename"
+    attributename = f.getname(nameindex)
+    w_attributename = f.space.wrap(attributename)
+    w_obj = f.valuestack.pop()
+    w_value = f.space.getattr(w_obj, w_attributename)
+    f.valuestack.push(w_value)
+
+def COMPARE_OP(f, test):
+    testnames = ["<", "<=", "==", "!=", ">", ">=",
+                 "in", "not in", "is", "is not", "exc match"]
+    testname = testnames[test]
+    w_2 = f.valuestack.pop()
+    w_1 = f.valuestack.pop()
+    w_result = f.space.compare(w_1, w_2, testname)
+    f.valuestack.push(w_result)
+
+def IMPORT_NAME(f, nameindex):
+    modulename = f.getname(nameindex)
+    w_modulename = f.space.wrap(modulename)
+    w_fromlist = f.valuestack.pop()
+    w_obj = f.space.gethelper(appfile).call(
+        "import_name", [f.w_builtins,
+                        w_modulename, f.w_globals, f.w_locals, w_fromlist])
+    f.valuestack.push(w_obj)
+
+def IMPORT_STAR(f):
+    w_module = f.valuestack.pop()
+    f.space.gethelper(appfile).call("import_star", [w_module, f.w_locals])
+
+def IMPORT_FROM(f, nameindex):
+    name = f.getname(nameindex)
+    w_name = f.space.wrap(name)
+    w_module = f.valuestack.top()
+    w_obj = f.space.gethelper(appfile).call("import_from", [w_module, w_name])
+    f.valuestack.push(w_obj)
+
+def JUMP_FORWARD(f, stepby):
+    f.next_instr += stepby
+
+def JUMP_IF_FALSE(f, stepby):
+    w_cond = f.valuestack.top()
+    if not f.space.is_true(w_cond):
+        f.next_instr += stepby
+
+def JUMP_IF_TRUE(f, stepby):
+    w_cond = f.valuestack.top()
+    if f.space.is_true(w_cond):
+        f.next_instr += stepby
+
+def JUMP_ABSOLUTE(f, jumpto):
+    f.next_instr = jumpto
+
+def GET_ITER(f):
+    w_iterable = f.valuestack.pop()
+    w_iterator = f.space.getiter(w_iterable)
+    f.valuestack.push(w_iterator)
+
+def FOR_ITER(f, jumpby):
+    w_iterator = f.valuestack.top()
+    try:
+        w_nextitem = f.space.iternext(w_iterator)
+    except NoValue:
+        # iterator exhausted
+        f.valuestack.pop()
+        f.next_instr += jumpby
+    else:
+        f.valuestack.push(w_nextitem)
+
+def FOR_LOOP(f, oparg):
+    raise pyframe.BytecodeCorruption, "old opcode, no longer in use"
+
+def SETUP_LOOP(f, offsettoend):
+    block = pyframe.LoopBlock(f, f.next_instr + offsettoend)
+    f.blockstack.push(block)
+
+def SETUP_EXCEPT(f, offsettoend):
+    block = pyframe.ExceptBlock(f, f.next_instr + offsettoend)
+    f.blockstack.push(block)
+
+def SETUP_FINALLY(f, offsettoend):
+    block = pyframe.FinallyBlock(f, f.next_instr + offsettoend)
+    f.blockstack.push(block)
+
+def call_function_extra(f, oparg, with_varargs, with_varkw):
+    n_arguments = oparg & 0xff
+    n_keywords = (oparg>>8) & 0xff
+    if with_varkw:
+        w_varkw = f.valuestack.pop()
+    if with_varargs:
+        w_varargs = f.valuestack.pop()
+    keywords = []
+    for i in range(n_keywords):
+        w_value = f.valuestack.pop()
+        w_key   = f.valuestack.pop()
+        keywords.append((w_value, w_key))
+    arguments = [f.valuestack.pop() for i in range(n_arguments)]
+    arguments.reverse()
+    w_function  = f.valuestack.pop()
+    w_arguments = f.space.newtuple(arguments)
+    w_keywords  = f.space.newdict(keywords)
+    if with_varargs:
+        w_arguments = f.space.gethelper(appfile).call("concatenate_arguments",
+                                                      [w_arguments, w_varargs])
+    if with_varkw:
+        w_keywords  = f.space.gethelper(appfile).call("concatenate_keywords",
+                                                      [w_keywords,  w_varkw])
+    w_result = f.space.call(w_function, w_arguments, w_keywords)
+    f.valuestack.push(w_result)
+
+def CALL_FUNCTION(f, oparg):
+    call_function_extra(f, oparg, False, False)
+
+def CALL_FUNCTION_VAR(f, oparg):
+    call_function_extra(f, oparg, True,  False)
+
+def CALL_FUNCTION_KW(f, oparg):
+    call_function_extra(f, oparg, False, True)
+
+def CALL_FUNCTION_VAR_KW(f, oparg):
+    call_function_extra(f, oparg, True,  True)
+
+def MAKE_FUNCTION(f, numdefaults):
+    w_codeobj = f.valuestack.pop()
+    defaultarguments = [f.valuestack.pop() for i in range(numdefaults)]
+    defaultarguments.reverse()
+    w_defaultarguments = f.space.newtuple(defaultarguments)
+    w_func = f.space.newfunction(w_codeobj, f.w_globals, w_defaultarguments)
+    f.valuestack.push(w_func)
+
+def MAKE_CLOSURE(f, numdefaults):
+    w_codeobj = f.valuestack.pop()
+    codeobj = f.space.unwrap(w_codeobj)
+    nfreevars = len(codeobj.co_freevars)
+    freevars = [f.valuestack.pop() for i in range(nfreevars)]
+    freevars.reverse()
+    w_freevars = f.space.newtuple(freevars)
+    defaultarguments = [f.valuestack.pop() for i in range(numdefaults)]
+    defaultarguments.reverse()
+    w_defaultarguments = f.space.newtuple(defaultarguments)
+    w_func = f.space.newfunction(w_codeobj, f.w_globals, w_defaultarguments,
+                                 w_freevars)
+    f.valuestack.push(w_func)
+
+def BUILD_SLICE(f, numargs):
+    if numargs == 3:
+        w_step = f.valuestack.pop()
+    elif numargs == 2:
+        w_step = None
+    else:
+        raise pyframe.BytecodeCorruption
+    w_end   = f.valuestack.pop()
+    w_start = f.valuestack.pop()
+    w_slice = f.space.newslice(w_start, w_end, w_step)
+    f.valuestack.push(w_slice)
+
+def SET_LINENO(f, lineno):
+    pass
+
+def EXTENDED_ARG(f, oparg):
+    opcode = f.nextop()
+    oparg = oparg<<16 | f.nextarg()
+    dispatch_arg(f, oparg)
+
+def MISSING_OPCODE(f, oparg=None):
+    raise pyframe.BytecodeCorruption, "unknown opcode"
+
+
+################################################################
+
+dispatch_table = []
+for i in range(256):
+    opname = dis.opname[i].replace('+', '_')
+    fn = MISSING_OPCODE
+    if opname in globals():
+        fn = globals()[opname]
+    elif not opname.startswith('<') and i>0:
+        print "* Warning, missing opcode %s" % opname
+    dispatch_table.append(fn)
+
+
+def name(thing):
+    try:
+        return thing.operationname
+    except AttributeError:
+        return thing.__name__
+
+def has_arg(opcode):
+    return opcode >= dis.HAVE_ARGUMENT
+
+def dispatch_noarg(f, opcode):
+    try:
+        fn = dispatch_table[opcode]
+#        print name(fn)
+    except KeyError:
+        raise KeyError, "missing opcode %s" % dis.opname[opcode]
+    fn(f)
+
+def dispatch_arg(f, opcode, oparg):
+    assert oparg >= 0
+    try:
+        fn = dispatch_table[opcode]
+#        print name(fn)
+    except KeyError:
+        raise KeyError, "missing opcode %s" % dis.opname[opcode]
+    fn(f, oparg)

File pypy/interpreter/opcode_app.py

+def prepare_raise0():
+    import sys
+    return sys.exc_info()
+    
+def prepare_raise(etype, value, traceback):
+    import types
+    if  not isinstance(traceback, (types.NoneType, types.TracebackType)):
+            raise TypeError, "raise: arg 3 must be traceback or None"
+    while isinstance(etype, tuple):
+        etype = etype[0]
+    if type(etype) is str:
+        # warn
+        pass
+    elif isinstance(etype, types.ClassType):
+        if value is None:
+            value = ()
+        elif not isinstance(value, tuple):
+            value = (value,)
+        value = etype(*value)
+    elif isinstance(etype, types.InstanceType):
+        if value is not None:
+            raise TypeError, "instance exception may not have a separate value"
+        value = etype
+        etype = value.__class__
+    else:
+        raise TypeError, "exceptions must be classes, instances, or " \
+              "strings (deprecated), not %s"%(type(etype).__name__,)
+    return etype, value, traceback
+
+def build_class(methods, bases, name):
+    return classobj(name, bases, methods)
+
+def print_expr(x):
+    import sys
+    try:
+        displayhook = sys.displayhook
+    except AttributeError:
+        raise RuntimeError, "lost sys.displayhook"
+    displayhook(x)
+
+
+def file_softspace(file, newflag):
+    softspace = getattr(file, "softspace", False)
+    try:
+        file.softspace = newflag
+    except AttributeError:
+        pass
+    return softspace
+
+def print_item_to(x, stream):
+    if file_softspace(stream, False):