Commits

holger krekel  committed fae6a37

the final merge of the builtinrefactor branch into the trunk. See

http://codespeak.net/pipermail/pypy-dev/2003q3/001012.html

for in-depth discussion and description of what is new.

  • Participants
  • Parent commits 944aa9c

Comments (0)

Files changed (149)

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)/math.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 __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
+        elif typ is types.ComplexType: # cough
+            return self, complex(other.real, other.imag)
+            
+        raise TypeError, "number coercion failed"
+
+
+    def conjugate(self):
+        return complex(self.real, -self.imag)
+
+
+    def __eq__(self, other):
+        self, other = self.__coerce__(other)
+        return self.real == other.real and self.imag == other.imag
+
+    def __ne__(self, other):
+        self, other = self.__coerce__(other)
+        return self.real != other.real or self.imag != other.imag
+
+
+    # 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/__init__.py

+# empty

File pypy/appspace/test/autopath.py

+"""
+self cloning, automatic path configuration 
+
+copy this into any subdirectory of pypy from which scripts need 
+to be run, typically all of the test subdirs. 
+The idea is that any such script simply issues
+
+    import autopath
+
+and this will make sure that the parent directory containing "pypy"
+is in sys.path. 
+
+If you modify the master "autopath.py" version (in pypy/tool/autopath.py) 
+you can directly run it which will copy itself on all autopath.py files
+it finds under the pypy root directory. 
+
+This module always provides these attributes:
+
+    pypydir    pypy root directory path 
+    this_dir   directory where this autopath.py resides 
+
+"""
+
+
+def __dirinfo(part):
+    """ return (partdir, this_dir) and insert parent of partdir
+    into sys.path. If the parent directories dont have the part
+    an EnvironmentError is raised."""
+
+    import sys, os 
+    try:
+        head = this_dir = os.path.abspath(os.path.dirname(__file__))
+    except NameError:
+        head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
+
+    while head:
+        partdir = head
+        head, tail = os.path.split(head)
+        if tail == part:
+            sys.path = [p for p in sys.path if not p.startswith(head)]
+            if head not in sys.path:
+                sys.path.insert(0, head)
+            return partdir, this_dir
+        
+    raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path)
+
+def __clone():
+    """ clone master version of autopath.py into all subdirs """
+    from os.path import join, walk
+    if not this_dir.endswith(join('pypy','tool')):
+        raise EnvironmentError("can only clone master version "
+                               "'%s'" % join(pypydir, 'tool',_myname))
+
+
+    def sync_walker(arg, dirname, fnames):
+        if _myname in fnames:
+            fn = join(dirname, _myname)
+            f = open(fn, 'rwb+')
+            try:
+                if f.read() == arg:
+                    print "checkok", fn
+                else:
+                    print "syncing", fn
+                    f = open(fn, 'w')
+                    f.write(arg)
+            finally:
+                f.close()
+    s = open(join(pypydir, 'tool', _myname), 'rb').read()
+    walk(pypydir, sync_walker, s)
+
+_myname = 'autopath.py'
+
+# set guaranteed attributes
+
+pypydir, this_dir = __dirinfo('pypy')
+
+if __name__ == '__main__':
+    __clone()

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
+import autopath
+
+#try:
+from pypy.tool import test
+from pypy.appspace import cmathmodule
+from pypy.appspace.complexobject import complex as pycomplex
+#except ImportError:
+#    import cmathmodule
+#    from pypy.complexobject import complex as pycomplex
+
+from pypy.appspace.test.test_complexobject import equal, enumerate
+
+
+class TestCMathModule(test.TestCase):
+
+    def assertAEqual(self, a, b):
+        if not equal(a, b):
+            raise self.failureException, '%s ~== %s'%(a, b)
+
+    def test_funcs(self):
+        "Compare many functions with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            mc = z0c*z1c
+            mp = z0p*z1p
+            self.assertAEqual(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.assertAEqual(op0, op1)
+
+            # check divisions
+            if equal(z0c, complex(0,0)) or equal(z1c, complex(0,0)):
+                continue
+            self.assertAEqual(mc/z0c, mp/z0p)
+            self.assertAEqual(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():
+                if z0p != 0:
+                    op0 = cmath.__dict__[op](z0c)
+                    op1 = cmathmodule.__dict__[op](z0p)
+                    self.assertAEqual(op0, op1)
+
+
+if __name__ == "__main__":
+    test.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 autopath
+
+import math
+import cmath
+import sys
+import types
+import unittest
+
+from pypy.tool import test
+from pypy.appspace.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 assertAEqual(self, a, b):
+        if not equal(a, b):
+            raise self.failureException, '%s ~== %s'%(a, b)
+
+    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.assertAEqual(mc, mp)
+
+            sc = z0c+z1c
+            sp = z0p+z1p
+            self.assertAEqual(sc, sp)
+
+            dc = z0c-z1c
+            dp = z0p-z1p
+            self.assertAEqual(dc, dp)
+
+            if not equal(z1c, complex(0,0)): 
+                qc = z0c/z1c
+                qp = z0p/z1p
+                self.assertAEqual(qc, qp)
+
+                
+    def test_special(self):
+        "Compare special methods with CPython."
+        
+        for (x, y) in [(0,0), (0,1), (1,3.)]:
+            zc = complex(x, y)
+            zp = pycomplex(x, y)
+
+            self.assertAEqual(zc, zp)
+            self.assertAEqual(-zc, -zp)
+            self.assertAEqual(+zc, +zp)
+            self.assertAEqual(abs(zc), abs(zp))
+            self.assertAEqual(zc, zp)
+            self.assertEqual(zc.conjugate(), zp.conjugate())
+            self.assertEqual(str(zc), str(zp))
+            self.assertEqual(hash(zc), hash(zp))
+
+
+    # this fails on python2.3 and is depreacted anyway
+    def _test_divmod(self):
+        "Compare divmod with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            mc = z0c*z1c
+            mp = z0p*z1p
+            self.assertAEqual(mc, mp)
+
+            if not equal(z1c, complex(0,0)): 
+                ddc, mmc = divmod(z0c, z1c)
+                self.assertAEqual(ddc*z1c + mmc, z0c)
+                ddp, mmp = divmod(z0p, z1p)
+                self.assertAEqual(ddp*z1p + mmp, z0p)
+                self.assertAEqual(ddc, ddp)
+                self.assertAEqual(mmc, mmp)
+
+
+    # these fail on python2.3
+    def _test_mod(self):
+        "Compare mod with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            mc = z0c*z1c
+            mp = z0p*z1p
+            self.assertAEqual(mc, mp)
+
+            if not equal(z1c, complex(0,0)): 
+                rc = z0c%z1c
+                rp = z0p%z1p
+                self.assertAEqual(rc, rp)
+                    
+    def test_div(self):
+        "Compare mod with CPython."
+        
+        for (z0c, z1c, z0p, z1p) in enumerate():
+            mc = z0c*z1c
+            mp = z0p*z1p
+            self.assertAEqual(mc, mp)
+
+            if not equal(z1c, complex(0,0)): 
+                rc = z0c/z1c
+                rp = z0p/z1p
+                self.assertAEqual(rc, 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
+                self.assertAEqual(pc, pp)
+                pc = z0c**z0c.real
+                pp = z0p**z0p.real
+                self.assertAEqual(pc, pp)
+
+if __name__ == "__main__":
+    unittest.main()

File pypy/appspace/types.py

+"""Appspace types module. 
+
+Define names for all type symbols known in the standard interpreter.
+
+Types that are part of optional modules (e.g. array) are not listed.
+"""
+#from __future__ import generators
+
+import sys
+
+# Iterators in Python aren't a matter of type but of protocol.  A large
+# and changing number of builtin types implement *some* flavor of
+# iterator.  Don't check the type!  Use hasattr to check for both
+# "__iter__" and "next" attributes instead.
+
+NoneType = type(None)
+TypeType = type
+ObjectType = object
+
+IntType = int
+try:
+    LongType = long
+except NameError:
+    pass
+FloatType = float
+try:
+    ComplexType = complex
+except NameError:
+    pass
+
+StringType = str
+try:
+    UnicodeType = unicode
+    StringTypes = (StringType, UnicodeType)
+except NameError:
+    StringTypes = (StringType,)
+
+try:
+    BufferType = type(buffer(''))
+except NameError:
+    pass
+
+TupleType = tuple
+ListType = list
+DictType = DictionaryType = dict
+
+def _f(): pass
+FunctionType = type(_f)
+LambdaType = type(lambda: None)         # Same as FunctionType
+try:
+    CodeType = type(_f.func_code)
+except RuntimeError:
+    # Execution in restricted environment
+    pass
+
+def g():
+    yield 1
+try:
+    GeneratorType = type(g())
+except:
+    # Refusing generators
+    pass
+del g
+
+class _C:
+    def _m(self): pass
+ClassType = type(_C)
+try:
+    UnboundMethodType = type(_C._m)         # Same as MethodType
+except AttributeError:
+    pass
+_x = _C()
+InstanceType = type(_x)
+MethodType = type(_x._m)
+
+BuiltinFunctionType = type(len)
+BuiltinMethodType = type([].append)     # Same as BuiltinFunctionType
+
+ModuleType = type(sys)
+try:
+    FileType = file
+    XRangeType = type(xrange(0))
+except NameError:
+   pass
+
+try:
+    raise TypeError
+except TypeError:
+    try:
+        tb = sys.exc_info()[2]
+        TracebackType = type(tb)
+        FrameType = type(tb.tb_frame)
+    except AttributeError:
+        # In the restricted environment, exc_info returns (None, None,
+        # None) Then, tb.tb_frame gives an attribute error
+        pass
+    tb = None; del tb
+
+SliceType = type(slice(0))
+EllipsisType = type(Ellipsis)
+
+#DictProxyType = type(TypeType.__dict__)
+
+del sys, _f, _C, _x#, generators                  # Not for export

File pypy/interpreter/__init__.py

+# empty

File pypy/interpreter/autopath.py

+"""
+self cloning, automatic path configuration 
+
+copy this into any subdirectory of pypy from which scripts need 
+to be run, typically all of the test subdirs. 
+The idea is that any such script simply issues
+
+    import autopath
+
+and this will make sure that the parent directory containing "pypy"
+is in sys.path. 
+
+If you modify the master "autopath.py" version (in pypy/tool/autopath.py) 
+you can directly run it which will copy itself on all autopath.py files
+it finds under the pypy root directory. 
+
+This module always provides these attributes:
+
+    pypydir    pypy root directory path 
+    this_dir   directory where this autopath.py resides 
+
+"""
+
+
+def __dirinfo(part):
+    """ return (partdir, this_dir) and insert parent of partdir
+    into sys.path. If the parent directories dont have the part
+    an EnvironmentError is raised."""
+
+    import sys, os 
+    try:
+        head = this_dir = os.path.abspath(os.path.dirname(__file__))
+    except NameError:
+        head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
+
+    while head:
+        partdir = head
+        head, tail = os.path.split(head)
+        if tail == part:
+            sys.path = [p for p in sys.path if not p.startswith(head)]
+            if head not in sys.path:
+                sys.path.insert(0, head)
+            return partdir, this_dir
+        
+    raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path)
+
+def __clone():
+    """ clone master version of autopath.py into all subdirs """
+    from os.path import join, walk
+    if not this_dir.endswith(join('pypy','tool')):
+        raise EnvironmentError("can only clone master version "
+                               "'%s'" % join(pypydir, 'tool',_myname))
+
+
+    def sync_walker(arg, dirname, fnames):
+        if _myname in fnames:
+            fn = join(dirname, _myname)
+            f = open(fn, 'rwb+')
+            try:
+                if f.read() == arg:
+                    print "checkok", fn
+                else:
+                    print "syncing", fn
+                    f = open(fn, 'w')
+                    f.write(arg)
+            finally:
+                f.close()
+    s = open(join(pypydir, 'tool', _myname), 'rb').read()
+    walk(pypydir, sync_walker, s)
+
+_myname = 'autopath.py'
+
+# set guaranteed attributes
+
+pypydir, this_dir = __dirinfo('pypy')
+
+if __name__ == '__main__':
+    __clone()

File pypy/interpreter/baseobjspace.py

+from pypy.interpreter.executioncontext import ExecutionContext
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.miscutils import Stack, getthreadlocals
+
+__all__ = ['ObjSpace', 'OperationError', 'NoValue']
+
+
+class Wrappable(object):
+    """A subclass of Wrappable is an internal, interpreter-level class
+    that can nevertheless be exposed at application-level by space.wrap()."""
+
+
+class NoValue(Exception):
+    """Raised to signal absence of value, e.g. in the iterator accessing
+    method 'op.next()' of object spaces."""
+
+
+class ObjSpace:
+    """Base class for the interpreter-level implementations of object spaces.
+    http://codespeak.net/moin/pypy/moin.cgi/ObjectSpace"""
+
+    def __init__(self):
+        "Basic initialization of objects."
+        self.appfile_helpers = {}
+        self.initialize()
+
+    def make_builtins(self):
+        # initializing builtins may require creating a frame which in
+        # turn already accesses space.w_builtins, provide a dummy one ...
+        self.w_builtins = self.newdict([])
+
+        assert not hasattr(self, 'builtin')
+        if not hasattr(self, 'sys'):
+            self.make_sys()
+
+        from pypy.module import builtin
+        self.builtin = builtin.__builtin__(self)
+        self.w_builtin = self.wrap(self.builtin)
+        #self.w_builtins = self.getattr(self.w_builtin, self.wrap("__dict__"))
+        self.w_builtins = self.builtin.w_dict
+
+        for name, value in self.__dict__.items():
+            if name.startswith('w_'):
+                name = name[2:]
+                if name.startswith('builtin'):
+                    continue
+                #print "setitem: space instance %-20s into builtins" % name
+                self.setitem(self.w_builtins, self.wrap(name), value)
+
+        self.sys._setmodule(self.w_builtin)
+
+    def make_sys(self):
+        assert not hasattr(self, 'sys')
+        from pypy.module import sysmodule
+        self.sys = sysmodule.Sys(self)
+        self.w_sys = self.wrap(self.sys)
+        self.sys._setmodule(self.w_sys)
+
+    # XXX get rid of this. 
+    def get_builtin_module(self, name):
+        if name == '__builtin__':
+            return self.w_builtin
+        elif name == 'sys':
+            return self.w_sys
+        return None
+
+    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."
+        ec = getthreadlocals().executioncontext
+        if ec is None:
+            ec = self.createexecutioncontext()
+        return ec
+
+    def createexecutioncontext(self):
+        "Factory function for execution contexts."
+        return ExecutionContext(self)
+
+    def gethelper(self, applicationfile):
+        try:
+            helper = self.appfile_helpers[applicationfile]
+        except KeyError:
+            from appfile import AppHelper
+            helper = AppHelper(self.gethelperspace(), applicationfile)
+            self.appfile_helpers[applicationfile] = helper
+        return helper
+
+    def gethelperspace(self):
+        # Return the object space to be used for executing helper code.
+        # A subclass may override this if it wants to use a different
+        # space to execute helpers (e.g. the annotating space)
+        return self
+
+    # Following is a friendly interface to common object space operations
+    # that can be defined in term of more primitive ones.  Subclasses
+    # may also override specific functions for performance.
+
+    def is_(self, w_x, w_y):
+        "'x is y'."
+        w_id_x = self.id(w_x)
+        w_id_y = self.id(w_y)
+        return self.eq(w_id_x, w_id_y)
+
+    def newbool(self, b):
+        if b:
+            return self.w_True
+        else:
+            return self.w_False
+
+    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.iter(w_iterable)
+        items = []
+        while True:
+            try:
+                w_item = self.next(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
+
+    def unpacktuple(self, w_tuple, expected_length=None):
+        """Same as unpackiterable(), but only for tuples.
+        Only use for bootstrapping or performance reasons."""
+        tuple_length = self.unwrap(self.len(w_tuple))
+        if expected_length is not None and tuple_length != expected_length:
+            raise ValueError, "got a tuple of length %d instead of %d" % (
+                tuple_length, expected_length)
+        items = [
+            self.getitem(w_tuple, self.wrap(i)) for i in range(tuple_length)]
+        return items
+
+    def exception_match(self, w_exc_type, w_check_class):
+        """Checks if the given exception type matches 'w_check_class'."""
+        check_list = [w_check_class]
+        while check_list:
+            w_item = check_list.pop()
+            # Match identical items.
+            if self.is_true(self.is_(w_exc_type, w_item)):
+                return True
+            # Test within iterables (i.e. tuples)
+            try:
+                exclst = self.unpackiterable(w_item)
+                check_list.extend(exclst)
+            except OperationError:
+                # w_item is not iterable; it should then be an Exception.
+                # Match subclasses.
+                if self.is_true(self.issubtype(w_exc_type, w_item)):
+                    return True
+        return False
+
+    def call_function(self, w_func, *args_w, **kw_w):
+        w_kw = self.newdict([(self.wrap(k), w_v) for k, w_v in kw_w.iteritems()])
+        return self.call(w_func, self.newtuple(list(args_w)), w_kw)
+
+    def call_method(self, w_obj, methname, *arg_w, **kw_w):
+        w_meth = self.getattr(w_obj, self.wrap(methname))
+        return self.call_function(w_meth, *arg_w, **kw_w)
+
+    def isinstance(self, w_obj, w_type):
+        w_objtype = self.type(w_obj)
+        return self.issubtype(w_objtype, w_type)
+
+
+## Table describing the regular part of the interface of object spaces,
+## namely all methods which only take w_ arguments and return a w_ result
+## (if any).  XXX Maybe we should say that these methods must be accessed
+## as 'space.op.xxx()' instead of directly 'space.xxx()'.
+
+ObjSpace.MethodTable = [
+# method name # symbol # number of arguments # special method name(s)
+    ('id',              'id',        1, []),
+    ('type',            'type',      1, []),
+    ('issubtype',       'issubtype', 2, []),  # not for old-style classes
+    ('repr',            'repr',      1, ['__repr__']),
+    ('str',             'str',       1, ['__str__']),
+    ('len',             'len',       1, ['__len__']),
+    ('hash',            'hash',      1, ['__hash__']),
+    ('getattr',         'getattr',   2, ['__getattribute__']),
+    ('setattr',         'setattr',   3, ['__setattr__']),
+    ('delattr',         'delattr',   2, ['__delattr__']),
+    ('getitem',         'getitem',   2, ['__getitem__']),
+    ('setitem',         'setitem',   3, ['__setitem__']),
+    ('delitem',         'delitem',   2, ['__delitem__']),
+    ('pos',             'pos',       1, ['__pos__']),
+    ('neg',             'neg',       1, ['__neg__']),
+    ('not_',            'not',       1, []),
+    ('abs' ,            'abs',       1, ['__abs__']),
+    ('hex',             'hex',       1, ['__hex__']),
+    ('oct',             'oct',       1, ['__oct__']),
+    ('ord',             'ord',       1, []),
+    ('invert',          '~',         1, ['__invert__']),
+    ('add',             '+',         2, ['__add__', '__radd__']),
+    ('sub',             '-',         2, ['__sub__', '__rsub__']),
+    ('mul',             '*',         2, ['__mul__', '__rmul__']),
+    ('truediv',         '/',         2, ['__truediv__', '__rtruediv__']),
+    ('floordiv',        '//',        2, ['__floordiv__', '__rfloordiv__']),
+    ('div',             'div',       2, ['__div__', '__rdiv__']),
+    ('mod',             '%',         2, ['__mod__', '__rmod__']),
+    ('divmod',          'divmod',    2, ['__divmod__', '__rdivmod__']),
+    ('pow',             '**',        3, ['__pow__', '__rpow__']),
+    ('lshift',          '<<',        2, ['__lshift__', '__rlshift__']),
+    ('rshift',          '>>',        2, ['__rshift__', '__rrshift__']),
+    ('and_',            '&',         2, ['__and__', '__rand__']),
+    ('or_',             '|',         2, ['__or__', '__ror__']),
+    ('xor',             '^',         2, ['__xor__', '__rxor__']),
+    ('int',             'int',       1, ['__int__']),
+    ('float',           'float',     1, ['__float__']),
+    ('inplace_add',     '+=',        2, ['__iadd__']),
+    ('inplace_sub',     '-=',        2, ['__isub__']),
+    ('inplace_mul',     '*=',        2, ['__imul__']),
+    ('inplace_truediv', '/=',        2, ['__itruediv__']),
+    ('inplace_floordiv','//=',       2, ['__ifloordiv__']),
+    ('inplace_div',     'div=',      2, ['__idiv__']),
+    ('inplace_mod',     '%=',        2, ['__imod__']),
+    ('inplace_pow',     '**=',       2, ['__ipow__']),
+    ('inplace_lshift',  '<<=',       2, ['__ilshift__']),
+    ('inplace_rshift',  '>>=',       2, ['__irshift__']),
+    ('inplace_and',     '&=',        2, ['__iand__']),
+    ('inplace_or',      '|=',        2, ['__ior__']),
+    ('inplace_xor',     '^=',        2, ['__ixor__']),
+    ('lt',              '<',         2, ['__lt__', '__gt__']),
+    ('le',              '<=',        2, ['__le__', '__ge__']),
+    ('eq',              '==',        2, ['__eq__', '__eq__']),
+    ('ne',              '!=',        2, ['__ne__', '__ne__']),
+    ('gt',              '>',         2, ['__gt__', '__lt__']),
+    ('ge',              '>=',        2, ['__ge__', '__le__']),
+    ('contains',        'contains',  2, ['__contains__']),
+    ('iter',            'iter',      1, ['__iter__']),
+    ('call',            'call',      3, ['__call__']),
+    ('get',             'get',       3, ['__get__']),
+    ('set',             'set',       3, ['__set__']),
+    ('delete',          'delete',    2, ['__delete__']),
+    ]
+
+ObjSpace.BuiltinModuleTable = [
+    '__builtin__',
+    'sys',
+    ]
+
+ObjSpace.ConstantTable = [
+    'None',
+    'False',
+    'True',
+    'Ellipsis',
+    'NotImplemented',
+    ]
+
+ObjSpace.ExceptionTable = [
+    'ArithmeticError',
+    'AssertionError',
+    'AttributeError',
+    'EOFError',
+    'EnvironmentError',
+    'Exception',
+    'FloatingPointError',
+    'IOError',
+    'ImportError',
+    'IndentationError',
+    'IndexError',
+    'KeyError',
+    'KeyboardInterrupt',
+    'LookupError',
+    'MemoryError',
+    'NameError',
+    'NotImplementedError',
+    'OSError',
+    'OverflowError',
+    'ReferenceError',
+    'RuntimeError',
+    'StandardError',
+    'StopIteration',
+    'SyntaxError',
+    'SystemError',
+    'SystemExit',
+    'TabError',
+    'TypeError',
+    'UnboundLocalError',
+    'UnicodeError',
+    'ValueError',
+    'ZeroDivisionError',
+    ]
+
+## Irregular part of the interface:
+#
+#                        wrap(x) -> w_x
+#                    unwrap(w_x) -> x
+#                   is_true(w_x) -> True or False
+#       newtuple([w_1, w_2,...]) -> w_tuple
+#        newlist([w_1, w_2,...]) -> w_list
+#      newstring([w_1, w_2,...]) -> w_string from ascii numbers (bytes)
+# newdict([(w_key,w_value),...]) -> w_dict
+# newslice(w_start,w_stop,w_end) -> w_slice     (w_end may be a real None)
+#                   next(w_iter) -> w_value or raise NoValue
+#

File pypy/interpreter/debug.py

+"""
+PyPy-oriented interface to pdb.
+"""
+
+import pdb, sys
+
+def fire(operationerr):
+    if not operationerr.debug_tbs:
+        return
+    tb = operationerr.debug_tbs[-1]
+    pdb.post_mortem(tb)

File pypy/interpreter/error.py

+import sys
+
+AUTO_DEBUG = 1
+
+
+class PyPyError(Exception):
+    "Raise this when you encounter an exceptional situation in PyPy itself."
+    def __init__(self, space, operationerr):
+        self.space = space
+        self.operationerr = operationerr
+
+
+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 application_traceback, which contain the wrapped
+    type and value describing the exception, and the unwrapped list of
+    (frame, instruction_position) making the application-level traceback.
+    """
+
+    def __init__(self, w_type, w_value):
+        self.w_type = w_type
+        self.w_value = w_value
+        self.application_traceback = []
+        self.debug_tbs = []
+
+    def record_application_traceback(self, frame, last_instruction):
+        self.application_traceback.append((frame, last_instruction))
+
+    def match(self, space, w_check_class):
+        "Check if this application-level exception matches 'w_check_class'."
+        return space.exception_match(self.w_type, w_check_class)
+
+    def __str__(self):
+        "Convenience for tracebacks."
+        return '[%s: %s]' % (self.w_type, self.w_value)
+
+    def errorstr(self, space):
+        "The exception class and value, as a string."
+        exc_type  = space.unwrap(
+            space.getattr(self.w_type, space.wrap('__name__')))
+        exc_value = space.unwrap(space.str(self.w_value))
+        return '%s: %s' % (exc_type, exc_value)
+
+    def getframe(self):
+        "The frame this exception was raised in, or None."
+        if self.application_traceback:
+            frame, last_instruction = self.application_traceback[0]
+            return frame
+        else:
+            return None
+
+    def record_interpreter_traceback(self):
+        """Records the current traceback inside the interpreter.
+        This traceback is only useful to debug the interpreter, not the
+        application."""
+        self.debug_tbs.append(sys.exc_info()[2])
+
+    def print_application_traceback(self, space, file=None):
+        "Dump a standard application-level traceback."
+        if file is None: file = sys.stderr
+        self.print_app_tb_only(file)
+        print >> file, self.errorstr(space)
+
+    def print_app_tb_only(self, file):
+        tb = self.application_traceback[:]
+        if tb:
+            import linecache
+            tb.reverse()
+            print >> file, "Traceback (application-level):"
+            for f, i in tb:
+                co = f.code
+                lineno = offset2lineno(co, i)
+                fname = co.co_filename
+                if fname.startswith('<inline>\n'):
+                    lines = fname.split('\n')
+                    fname = lines[0].strip()
+                    try:
+                        l = lines[lineno]
+                    except IndexError:
+                        l = ''
+                else:
+                    l = linecache.getline(fname, lineno)
+                print >> file, "  File \"%s\"," % fname,
+                print >> file, "line", lineno, "in", co.co_name
+                if l:
+                    if l.endswith('\n'):
+                        l = l[:-1]
+                    print >> file, l
+
+    def print_detailed_traceback(self, space=None, file=None):
+        """Dump a nice detailed interpreter- and application-level traceback,
+        useful to debug the interpreter."""
+        if file is None: file = sys.stderr
+        for i in range(len(self.debug_tbs)-1, -1, -1):
+            import traceback
+            interpr_file = LinePrefixer(file, '||')
+            print >> interpr_file, "Traceback (interpreter-level):"
+            traceback.print_tb(self.debug_tbs[i], file=interpr_file)
+        self.print_app_tb_only(file)
+        if space is None:
+            exc_typename = str(self.w_type)
+            exc_value    = self.w_value
+        else:
+            w = space.wrap
+            exc_typename  = space.unwrap(
+                space.getattr(self.w_type, w('__name__')))
+            exc_value = space.unwrap(space.str(self.w_value))
+            print >> file, '(application-level)',
+        if exc_value is None:
+            print >> file, exc_typename
+        else:
+            print >> file, exc_typename+':', exc_value
+        if AUTO_DEBUG:
+            import debug
+            debug.fire(self)
+
+
+# Utilities
+
+def inlinecompile(source, space, symbol='exec'):
+    """Compile the given 'source' string.
+    This function differs from the built-in compile() because it abuses
+    co_filename to store a copy of the complete source code.
+    This lets OperationError.print_application_traceback() print the
+    actual source line in the traceback."""
+    compile = space.builtin.compile
+    w = space.wrap
+    return compile(w(source), w('<inline>\n%s'%source), w(symbol), w(0), w(0))
+
+
+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 LinePrefixer:
+    """File-like class that inserts a prefix string
+    at the beginning of each line it prints."""
+    def __init__(self, file, prefix):
+        self.file = file
+        self.prefix = prefix
+        self.linestart = True
+    def write(self, data):
+        if self.linestart:
+            self.file.write(self.prefix)
+        if data.endswith('\n'):
+            data = data[:-1]
+            self.linestart = True
+        else:
+            self.linestart = False
+        self.file.write(data.replace('\n', '\n'+self.prefix))
+        if self.linestart:
+            self.file.write('\n')
+
+# installing the excepthook for OperationErrors
+def operr_excepthook(exctype, value, traceback):
+    if issubclass(exctype, OperationError):
+        value.debug_tbs.append(traceback)
+        value.print_detailed_traceback()
+    else:
+        old_excepthook(exctype, value, traceback)
+old_excepthook = sys.excepthook
+sys.excepthook = operr_excepthook

File pypy/interpreter/eval.py

+"""
+This module defines the abstract base classes that support execution:
+Code and Frame.
+"""
+
+
+class Code(object):
+    """A code is a compiled version of some source code.
+    Abstract base class."""
+
+    def __init__(self, co_name):
+        self.co_name = co_name
+
+    def create_frame(self, space, w_globals, closure=None):
+        "Create an empty frame object suitable for evaluation of this code."
+        raise TypeError, "abstract"
+
+    def exec_code(self, space, w_globals, w_locals):
+        "Implements the 'exec' statement."
+        frame = self.create_frame(space, w_globals)
+        frame.setdictscope(w_locals)
+        return frame.run()
+
+    def signature(self):
+        "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
+        return [], None, None
+
+    def getvarnames(self):
+        """List of names including the arguments, vararg and kwarg,
+        and possibly more locals."""
+        argnames, varargname, kwargname = self.signature()
+        if varargname is not None:
+            argnames = argnames + [varargname]
+        if kwargname is not None:
+            argnames = argnames + [kwargname]
+        return argnames
+
+
+UNDEFINED = object()  # marker for undefined local variables
+
+
+class Frame(object):
+    """A frame is an environment supporting the execution of a code object.
+    Abstract base class."""
+
+    def __init__(self, space, code, w_globals=None, numlocals=-1):
+        self.space      = space
+        self.code       = code       # Code instance
+        self.w_globals  = w_globals  # wrapped dict of globals
+        self.w_locals   = None       # wrapped dict of locals
+        if numlocals < 0:  # compute the minimal size based on arguments
+            numlocals = len(code.getvarnames())
+        self.fastlocals_w = [UNDEFINED]*numlocals  # flat list of wrapped locals
+
+    def run(self):
+        "Run the frame."
+        executioncontext = self.space.getexecutioncontext()
+        previous = executioncontext.enter(self)
+        try:
+            result = self.eval(executioncontext)
+        finally:
+            executioncontext.leave(previous)
+        return result
+
+    def eval(self, executioncontext):
+        "Abstract method to override."
+        raise TypeError, "abstract"
+
+    def getdictscope(self):
+        "Get the locals as a dictionary."
+        self.fast2locals()
+        return self.w_locals
+
+    def setdictscope(self, w_locals):
+        "Initialize the locals from a dictionary."
+        self.w_locals = w_locals
+        self.locals2fast()
+
+    def getfastscope(self):
+        "Get the fast locals as a list."
+        return self.fastlocals_w
+
+    def setfastscope(self, scope_w):
+        """Initialize the fast locals from a list of values,
+        where the order is according to self.code.signature()."""
+        if len(scope_w) > len(self.fastlocals_w):
+            raise ValueError, "new fastscope is longer than the allocated area"
+        self.fastlocals_w[:len(scope_w)] = scope_w
+
+    def fast2locals(self):
+        # Copy values from self.fastlocals_w to self.w_locals
+        if self.w_locals is None:
+            self.w_locals = self.space.newdict([])
+        varnames = self.code.getvarnames()
+        for name, w_value in zip(varnames, self.fastlocals_w):
+            if w_value is not UNDEFINED:
+                w_name = self.space.wrap(name)
+                self.space.setitem(self.w_locals, w_name, w_value)
+
+    def locals2fast(self):
+        # Copy values from self.w_locals to self.fastlocals_w
+        varnames = self.code.getvarnames()
+        for name, i in zip(varnames, range(len(self.fastlocals_w))):
+            w_name = self.space.wrap(varnames[i])
+            try:
+                w_value = self.space.getitem(self.w_locals, w_name)
+            except OperationError, e:
+                if not e.match(self.space, self.space.w_KeyError):
+                    raise
+            else:
+                self.fastlocals_w[i] = w_value

File pypy/interpreter/executioncontext.py

+from pypy.interpreter.miscutils import getthreadlocals, Stack
+
+class ExecutionContext:
+    """An ExecutionContext holds the state of an execution thread
+    in the Python interpreter."""
+    
+    def __init__(self, space):
+        # Note that self.framestack only contains PyFrames
+        self.space = space
+        self.framestack = Stack()
+
+    def enter(self, frame):
+        locals = getthreadlocals()
+        self.framestack.push(frame)
+        previous_ec = locals.executioncontext
+        locals.executioncontext = self
+        return previous_ec
+
+    def leave(self, previous_ec):
+        locals = getthreadlocals()
+        locals.executioncontext = previous_ec
+        self.framestack.pop()
+
+    def get_w_builtins(self):
+        if self.framestack.empty():
+            return self.space.w_builtins
+        else:
+            return self.framestack.top().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 bytecode_trace(self, frame):
+        "Trace function called before each bytecode."
+
+    def exception_trace(self, operationerr):
+        "Trace function called upon OperationError."
+        operationerr.record_interpreter_traceback()
+        #operationerr.print_detailed_traceback(self.space)
+
+    def sys_exc_info(self):
+        """Implements sys.exc_info().
+        Return an OperationError instance or None."""
+        for i in range(self.framestack.depth()):
+            frame = self.framestack.top(i)
+            if frame.last_exception is not None:
+                return frame.last_exception
+        return None

File pypy/interpreter/extmodule.py

+"""
+
+Helpers to build extension modules.
+
+"""
+
+from pypy.interpreter import gateway
+from pypy.interpreter.miscutils import InitializedClass, RwDictProxy
+from pypy.interpreter.module import Module
+
+
+class ExtModule(Module):
+    """An empty extension module.
+    Non-empty extension modules are made by subclassing ExtModule."""
+
+    def __init__(self, space):
+        Module.__init__(self, space, space.wrap(self.__name__))
+