[pypy-svn] r14042 - in pypy/branch/pycompiler: annotation bin documentation documentation/tool documentation/website interpreter lib module module/_codecs module/recparser module/sys objspace objspace/flow objspace/std objspace/std/test rpython rpython/test tool

adim at codespeak.net adim at codespeak.net
Fri Jul 1 18:30:58 CEST 2005


Author: adim
Date: Fri Jul  1 18:30:34 2005
New Revision: 14042

Added:
   pypy/branch/pycompiler/rpython/llinterp.py
      - copied unchanged from r14039, pypy/dist/pypy/rpython/llinterp.py
   pypy/branch/pycompiler/rpython/rconstantdict.py
      - copied unchanged from r14039, pypy/dist/pypy/rpython/rconstantdict.py
   pypy/branch/pycompiler/rpython/rdict.py
      - copied unchanged from r14039, pypy/dist/pypy/rpython/rdict.py
   pypy/branch/pycompiler/rpython/test/test_llinterp.py
      - copied unchanged from r14039, pypy/dist/pypy/rpython/test/test_llinterp.py
   pypy/branch/pycompiler/rpython/test/test_rbuiltin.py
      - copied unchanged from r14039, pypy/dist/pypy/rpython/test/test_rbuiltin.py
   pypy/branch/pycompiler/rpython/test/test_rconstantdict.py
      - copied unchanged from r14039, pypy/dist/pypy/rpython/test/test_rconstantdict.py
   pypy/branch/pycompiler/rpython/test/test_rdict.py
      - copied unchanged from r14039, pypy/dist/pypy/rpython/test/test_rdict.py
   pypy/branch/pycompiler/tool/asterisk.py
      - copied unchanged from r14039, pypy/dist/pypy/tool/asterisk.py
Removed:
   pypy/branch/pycompiler/lib/inprogress__codecs.py
   pypy/branch/pycompiler/lib/unicodecodec.py
   pypy/branch/pycompiler/objspace/dummy.py
Modified:
   pypy/branch/pycompiler/annotation/binaryop.py
   pypy/branch/pycompiler/annotation/bookkeeper.py
   pypy/branch/pycompiler/annotation/builtin.py
   pypy/branch/pycompiler/annotation/classdef.py
   pypy/branch/pycompiler/annotation/model.py
   pypy/branch/pycompiler/annotation/pairtype.py
   pypy/branch/pycompiler/annotation/policy.py
   pypy/branch/pycompiler/annotation/specialize.py
   pypy/branch/pycompiler/annotation/unaryop.py
   pypy/branch/pycompiler/bin/translator.py
   pypy/branch/pycompiler/documentation/architecture.txt
   pypy/branch/pycompiler/documentation/coding-guide.txt
   pypy/branch/pycompiler/documentation/contributor.txt   (contents, props changed)
   pypy/branch/pycompiler/documentation/faq.txt   (contents, props changed)
   pypy/branch/pycompiler/documentation/misc.txt
   pypy/branch/pycompiler/documentation/objspace.txt
   pypy/branch/pycompiler/documentation/svn-help.txt
   pypy/branch/pycompiler/documentation/tool/makecontributor.py   (props changed)
   pypy/branch/pycompiler/documentation/translation.txt
   pypy/branch/pycompiler/documentation/website/EP2005-announcement.txt   (props changed)
   pypy/branch/pycompiler/documentation/website/news.txt
   pypy/branch/pycompiler/interpreter/eval.py
   pypy/branch/pycompiler/interpreter/function.py
   pypy/branch/pycompiler/interpreter/nestedscope.py
   pypy/branch/pycompiler/interpreter/pycode.py
   pypy/branch/pycompiler/interpreter/pyopcode.py
   pypy/branch/pycompiler/interpreter/typedef.py
   pypy/branch/pycompiler/lib/_exceptions.py
   pypy/branch/pycompiler/module/README.txt   (props changed)
   pypy/branch/pycompiler/module/_codecs/   (props changed)
   pypy/branch/pycompiler/module/recparser/automata.py
   pypy/branch/pycompiler/module/recparser/ebnfparse.py
   pypy/branch/pycompiler/module/recparser/grammar.py
   pypy/branch/pycompiler/module/recparser/pythonlexer.py
   pypy/branch/pycompiler/module/recparser/pythonutil.py
   pypy/branch/pycompiler/module/recparser/tuplebuilder.py   (contents, props changed)
   pypy/branch/pycompiler/module/sys/state.py
   pypy/branch/pycompiler/objspace/flow/flowcontext.py
   pypy/branch/pycompiler/objspace/flow/model.py
   pypy/branch/pycompiler/objspace/flow/objspace.py
   pypy/branch/pycompiler/objspace/flow/operation.py
   pypy/branch/pycompiler/objspace/std/floatobject.py
   pypy/branch/pycompiler/objspace/std/floattype.py
   pypy/branch/pycompiler/objspace/std/inttype.py
   pypy/branch/pycompiler/objspace/std/listobject.py
   pypy/branch/pycompiler/objspace/std/model.py
   pypy/branch/pycompiler/objspace/std/mro.py
   pypy/branch/pycompiler/objspace/std/objspace.py
   pypy/branch/pycompiler/objspace/std/stringobject.py
   pypy/branch/pycompiler/objspace/std/strutil.py
   pypy/branch/pycompiler/objspace/std/test/test_floatobject.py
   pypy/branch/pycompiler/objspace/std/test/test_strutil.py
   pypy/branch/pycompiler/objspace/std/test/test_unicodestring.py
   pypy/branch/pycompiler/objspace/std/tupleobject.py
   pypy/branch/pycompiler/objspace/std/unicodeobject.py
   pypy/branch/pycompiler/objspace/std/unicodetype.py
   pypy/branch/pycompiler/rpython/annlowlevel.py
   pypy/branch/pycompiler/rpython/exceptiondata.py
   pypy/branch/pycompiler/rpython/lltype.py
   pypy/branch/pycompiler/rpython/normalizecalls.py
   pypy/branch/pycompiler/rpython/rarithmetic.py
   pypy/branch/pycompiler/rpython/rbool.py   (contents, props changed)
   pypy/branch/pycompiler/rpython/rbuiltin.py
   pypy/branch/pycompiler/rpython/rclass.py
   pypy/branch/pycompiler/rpython/rfloat.py   (contents, props changed)
   pypy/branch/pycompiler/rpython/rint.py
   pypy/branch/pycompiler/rpython/rlist.py
   pypy/branch/pycompiler/rpython/rmodel.py
   pypy/branch/pycompiler/rpython/robject.py
   pypy/branch/pycompiler/rpython/rpbc.py
   pypy/branch/pycompiler/rpython/rptr.py
   pypy/branch/pycompiler/rpython/rrange.py
   pypy/branch/pycompiler/rpython/rslice.py
   pypy/branch/pycompiler/rpython/rstr.py
   pypy/branch/pycompiler/rpython/rtuple.py
   pypy/branch/pycompiler/rpython/rtyper.py
   pypy/branch/pycompiler/rpython/test/snippet.py   (props changed)
   pypy/branch/pycompiler/rpython/test/test_llann.py
   pypy/branch/pycompiler/rpython/test/test_lltype.py
   pypy/branch/pycompiler/rpython/test/test_normalizecalls.py
   pypy/branch/pycompiler/rpython/test/test_rbool.py   (contents, props changed)
   pypy/branch/pycompiler/rpython/test/test_rclass.py
   pypy/branch/pycompiler/rpython/test/test_rfloat.py   (contents, props changed)
   pypy/branch/pycompiler/rpython/test/test_rint.py   (contents, props changed)
   pypy/branch/pycompiler/rpython/test/test_rlist.py
   pypy/branch/pycompiler/rpython/test/test_rpbc.py
   pypy/branch/pycompiler/rpython/test/test_rptr.py
   pypy/branch/pycompiler/rpython/test/test_rrange.py
   pypy/branch/pycompiler/rpython/test/test_rstr.py
   pypy/branch/pycompiler/rpython/test/test_rtuple.py
   pypy/branch/pycompiler/rpython/test/test_rtyper.py
   pypy/branch/pycompiler/tool/_enum_exceptions.py
   pypy/branch/pycompiler/tool/ansi_print.py
   pypy/branch/pycompiler/tool/cache.py
   pypy/branch/pycompiler/tool/import_graph.py   (props changed)
   pypy/branch/pycompiler/tool/traceconfig.py   (props changed)
   pypy/branch/pycompiler/tool/unionfind.py
Log:
(merged from the top directory)
svn merge -r13379:14040 http://codespeak.net/svn/pypy/dist/pypy


Modified: pypy/branch/pycompiler/annotation/binaryop.py
==============================================================================
--- pypy/branch/pycompiler/annotation/binaryop.py	(original)
+++ pypy/branch/pycompiler/annotation/binaryop.py	Fri Jul  1 18:30:34 2005
@@ -32,14 +32,11 @@
                          'inplace_lshift', 'inplace_rshift',
                          'inplace_and', 'inplace_or', 'inplace_xor',
                          'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'is_', 'cmp',
-                         'union', 'coerce',
+                         'coerce',
                          ]
                         +[opname+'_ovf' for opname in
-                          """add sub mul truediv
-                           floordiv div mod divmod pow lshift
-                           inplace_add inplace_sub inplace_mul inplace_truediv
-                           inplace_floordiv inplace_div inplace_mod inplace_pow
-                           inplace_lshift""".split()
+                          """add sub mul floordiv div mod pow lshift
+                           """.split()
                           ])
 
 for opname in BINARY_OPERATIONS:
@@ -98,39 +95,46 @@
         if obj1.is_constant() and obj2.is_constant():
             return immutablevalue(obj1.const < obj2.const)
         else:
+            getbookkeeper().count("non_int_comp", obj1, obj2)
             return SomeBool()
 
     def le((obj1, obj2)):
         if obj1.is_constant() and obj2.is_constant():
             return immutablevalue(obj1.const <= obj2.const)
         else:
+            getbookkeeper().count("non_int_comp", obj1, obj2)
             return SomeBool()
 
     def eq((obj1, obj2)):
         if obj1.is_constant() and obj2.is_constant():
             return immutablevalue(obj1.const == obj2.const)
         else:
+            getbookkeeper().count("non_int_eq", obj1, obj2)
             return SomeBool()
 
     def ne((obj1, obj2)):
         if obj1.is_constant() and obj2.is_constant():
             return immutablevalue(obj1.const != obj2.const)
         else:
+            getbookkeeper().count("non_int_eq", obj1, obj2)
             return SomeBool()
 
     def gt((obj1, obj2)):
         if obj1.is_constant() and obj2.is_constant():
             return immutablevalue(obj1.const > obj2.const)
         else:
+            getbookkeeper().count("non_int_comp", obj1, obj2)
             return SomeBool()
 
     def ge((obj1, obj2)):
         if obj1.is_constant() and obj2.is_constant():
             return immutablevalue(obj1.const >= obj2.const)
         else:
+            getbookkeeper().count("non_int_comp", obj1, obj2)
             return SomeBool()
 
     def cmp((obj1, obj2)):
+        getbookkeeper().count("cmp", obj1, obj2)
         if obj1.is_constant() and obj2.is_constant():
             return immutablevalue(cmp(obj1.const, obj2.const))
         else:
@@ -179,9 +183,11 @@
         return r
 
     def divmod((obj1, obj2)):
+        getbookkeeper().count("divmod", obj1, obj2)
         return SomeTuple([pair(obj1, obj2).div(), pair(obj1, obj2).mod()])
 
     def coerce((obj1, obj2)):
+        getbookkeeper().count("coerce", obj1, obj2)
         return pair(obj1, obj2).union()   # reasonable enough
 
 # cloning a function with identical code, for the can_only_throw attribute
@@ -302,6 +308,7 @@
 class __extend__(pairtype(SomeString, SomeObject)):
 
     def mod((str, args)):
+        getbookkeeper().count('strformat', str, args)
         return SomeString()
 
 
@@ -328,6 +335,11 @@
         lst1.listdef.union(lst2.listdef)
         return lst1
 
+    def eq((lst1, lst2)):
+        lst1.listdef.union(lst2.listdef)
+        return SomeBool()
+    ne = eq
+
 
 class __extend__(pairtype(SomeList, SomeObject)):
 
@@ -364,13 +376,16 @@
 class __extend__(pairtype(SomeDict, SomeObject)):
 
     def getitem((dic1, obj2)):
+        getbookkeeper().count("dict_getitem", dic1)
         return dic1.dictdef.read_value()
 
     def setitem((dic1, obj2), s_value):
+        getbookkeeper().count("dict_setitem", dic1)
         dic1.dictdef.generalize_key(obj2)
         dic1.dictdef.generalize_value(s_value)
 
     def delitem((dic1, obj1)):
+        getbookkeeper().count("dict_delitem", dic1)
         pass
 
 
@@ -391,6 +406,7 @@
             except IndexError:
                 return SomeImpossibleValue()
         else:
+            getbookkeeper().count("tuple_random_getitem", tup1)
             return unionof(*tup1.items)
 
 
@@ -400,13 +416,16 @@
         return getbookkeeper().newlist(lst1.listdef.read_item())
 
     def getitem((lst1, int2)):
+        getbookkeeper().count("list_getitem", int2)
         return lst1.listdef.read_item()
 
     def setitem((lst1, int2), s_value):
+        getbookkeeper().count("list_setitem", int2)        
         lst1.listdef.mutate()
         lst1.listdef.generalize(s_value)
 
     def delitem((lst1, int2)):
+        getbookkeeper().count("list_delitem", int2)        
         lst1.listdef.resize()
 
 class __extend__(pairtype(SomeList, SomeSlice)):
@@ -430,14 +449,17 @@
 class __extend__(pairtype(SomeString, SomeInteger)):
 
     def getitem((str1, int2)):
+        getbookkeeper().count("str_getitem", int2)        
         return SomeChar()
 
     def mul((str1, int2)): # xxx do we want to support this
+        getbookkeeper().count("str_mul", str1, int2)
         return SomeString()
 
 class __extend__(pairtype(SomeInteger, SomeString)):
     
     def mul((int1, str2)): # xxx do we want to support this
+        getbookkeeper().count("str_mul", str2, int1)
         return SomeString()
 
 class __extend__(pairtype(SomeInteger, SomeList)):
@@ -464,11 +486,11 @@
 class __extend__(pairtype(SomeBuiltin, SomeBuiltin)):
 
     def union((bltn1, bltn2)):
-        if bltn1.analyser != bltn2.analyser:
+        if bltn1.analyser != bltn2.analyser or bltn1.methodname != bltn2.methodname:
             raise UnionError("merging incompatible builtins == BAD!")
         else:
             s_self = unionof(bltn1.s_self, bltn2.s_self)
-            return SomeBuiltin(bltn1.analyser, s_self)
+            return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname)
 
 class __extend__(pairtype(SomePBC, SomePBC)):
     def union((pbc1, pbc2)):       
@@ -485,11 +507,7 @@
                     classdef2 = classdef
                     if classdef != d[x]:
                         classdef = classdef.commonbase(d[x])
-                        for cand in classdef.getmro():
-                            if x in cand.cls.__dict__.values():
-                                classdef = cand
-                                break
-                        else:
+                        if classdef is None:
                             raise UnionError(
                                 "confused pbc union trying unwarranted"
                                 "moving up of method %s from pair %s %s" %

Modified: pypy/branch/pycompiler/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/pycompiler/annotation/bookkeeper.py	(original)
+++ pypy/branch/pycompiler/annotation/bookkeeper.py	Fri Jul  1 18:30:34 2005
@@ -24,6 +24,7 @@
         self.objects = { obj: True }
         self.read_locations = {}
         self.attrs = {}
+        self.values = {}   # used in the typer 
 
     def update(self, other):
         self.objects.update(other.objects)
@@ -39,6 +40,123 @@
         self.objects.update(other.objects)
         self.patterns.update(other.patterns)
 
+class Stats:
+
+    def __init__(self, bookkeeper):
+        self.bookkeeper = bookkeeper
+        self.classify = {}
+
+    def count(self, category, *args):
+        for_category = self.classify.setdefault(category, {})
+        classifier = getattr(self, 'consider_%s' % category, self.consider_generic)
+        outcome = classifier(*args)
+        for_category[self.bookkeeper.position_key] = outcome
+
+    def indexrepr(self, idx):
+        if idx.is_constant():
+            if idx.const is None:
+                return ''
+            if isinstance(idx, SomeInteger):
+                if idx.const >=0:
+                    return 'pos-constant'
+                else:
+                    return 'Neg-constant'
+            return idx.const
+        else:
+            if isinstance(idx, SomeInteger):
+                if idx.nonneg:
+                    return "non-neg"
+                else:
+                    return "MAYBE-NEG"
+            else:
+                return self.typerepr(idx)
+
+    def steprepr(self, stp):
+        if stp.is_constant():
+            if stp.const in (1, None):
+                return 'step=1'
+            else:
+                return 'step=%s?' % stp.const
+        else:
+            return 'non-const-step %s' % self.typerepr(stp)
+
+    def consider_generic(self, *args):
+        return tuple([self.typerepr(x) for x in args])
+
+    def consider_newslice(self, s_start, s_stop, s_step):
+        return ':'.join([self.indexrepr(s_start), self.indexrepr(s_stop), self.steprepr(s_step)])
+
+    def consider_list_list_eq(self, obj1, obj2):
+        return obj1, obj2
+
+    def consider_contains(self, seq):
+        return seq
+
+    def consider_non_int_eq(self, obj1, obj2):
+        if obj1.knowntype == obj2.knowntype == list:
+            self.count("list_list_eq", obj1, obj2)
+        return obj1.knowntype.__name__, obj2.knowntype.__name__
+
+    def consider_non_int_comp(self, obj1, obj2):
+        return obj1.knowntype.__name__, obj2.knowntype.__name__
+
+    def typerepr(self, obj):
+        if isinstance(obj, SomeInstance):
+            return obj.classdef.cls.__name__
+        else:
+            return obj.knowntype.__name__
+
+    def consider_tuple_iter(self, tup):
+        ctxt = "[%s]" % sys._getframe(4).f_code.co_name
+        if tup.is_constant():
+            return ctxt, tup.const
+        else:
+            return ctxt, tuple([self.typerepr(x) for x in tup.items])
+
+    def consider_tuple_random_getitem(self, tup):
+        return tuple([self.typerepr(x) for x in tup.items])
+
+    def consider_list_index(self):
+        return '!'
+
+    def consider_list_getitem(self, idx):
+        return self.indexrepr(idx)
+
+    def consider_list_setitem(self, idx):
+        return self.indexrepr(idx)
+
+    def consider_list_delitem(self, idx):
+        return self.indexrepr(idx)
+    
+    def consider_str_join(self, s):
+        if s.is_constant():
+            return repr(s.const)
+        else:
+            return "NON-CONSTANT"
+
+    def consider_str_getitem(self, idx):
+        return self.indexrepr(idx)
+
+    def consider_strformat(self, str, args):
+        if str.is_constant():
+            s = repr(str.const)
+        else:
+            s = "?!!!!!!"
+        if isinstance(args, SomeTuple):
+            return (s, tuple([self.typerepr(x) for x in args.items]))
+        else:
+            return (s, self.typerepr(args))
+
+    def consider_dict_getitem(self, dic):
+        return dic
+
+    def consider_dict_setitem(self, dic):
+        return dic
+
+    def consider_dict_delitem(self, dic):
+        return dic
+            
+
 class Bookkeeper:
     """The log of choices that have been made while analysing the operations.
     It ensures that the same 'choice objects' will be returned if we ask
@@ -47,6 +165,12 @@
 
     Currently used for factories and user-defined classes."""
 
+    def __setstate__(self, dic):
+        self.__dict__.update(dic) # normal action
+        # import ordering hack
+        global BUILTIN_ANALYZERS
+        from pypy.annotation.builtin import BUILTIN_ANALYZERS
+
     def __init__(self, annotator):
         self.annotator = annotator
         self.userclasses = {}    # map classes to ClassDefs
@@ -57,7 +181,8 @@
         self.seen_mutable = {}
         self.listdefs = {}       # map position_keys to ListDefs
         self.dictdefs = {}       # map position_keys to DictDefs
-        
+        self.immutable_cache = {}
+
         # mapping position -> key, prev_result for specializations
         self.spec_callsite_keys_results = {}
 
@@ -69,11 +194,17 @@
         
         self.pbc_call_sites = {}
 
-        
+        self.memo_tables = []
+
+        self.stats = Stats(self)
+
         # import ordering hack
         global BUILTIN_ANALYZERS
         from pypy.annotation.builtin import BUILTIN_ANALYZERS
 
+    def count(self, category, *args):
+        self.stats.count(category, *args)
+
     def enter(self, position_key):
         """Start of an operation.
         The operation is uniquely identified by the given key."""
@@ -147,8 +278,6 @@
             dictdef.generalize_value(s_value)
         return SomeDict(dictdef)
 
-    immutable_cache = {}
-
     def immutablevalue(self, x):
         """The most precise SomeValue instance that contains the
         immutable value x."""
@@ -177,23 +306,28 @@
         elif tp is float:
             result = SomeFloat()
         elif tp is list:
+            key = Constant(x)
             try:
-                return self.immutable_cache[id(x)]
+                return self.immutable_cache[key]
             except KeyError:
-                items_s = [self.immutablevalue(e) for e in x]
-                result = SomeList(ListDef(self, unionof(*items_s)))
-                self.immutable_cache[id(x)] = result
+                result = SomeList(ListDef(self, SomeImpossibleValue()))
+                self.immutable_cache[key] = result
+                for e in x:
+                    result.listdef.generalize(self.immutablevalue(e))
         elif tp is dict:   # exactly a dict
+            key = Constant(x)
             try:
-                return self.immutable_cache[id(x)]
+                return self.immutable_cache[key]
             except KeyError:
-                keys_s   = [self.immutablevalue(e) for e in x.keys()]
-                values_s = [self.immutablevalue(e) for e in x.values()]
-                result = SomeDict(DictDef(self, unionof(*keys_s),
-                                          unionof(*values_s)))
-                self.immutable_cache[id(x)] = result
+                result = SomeDict(DictDef(self, 
+                                          SomeImpossibleValue(),
+                                          SomeImpossibleValue()))
+                self.immutable_cache[key] = result
+                for ek, ev in x.iteritems():
+                    result.dictdef.generalize_key(self.immutablevalue(ek))
+                    result.dictdef.generalize_value(self.immutablevalue(ev))
         elif ishashable(x) and x in BUILTIN_ANALYZERS:
-            result = SomeBuiltin(BUILTIN_ANALYZERS[x])
+            result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (x.__module__, x.__name__))
         elif isinstance(x, lltype._ptr):
             result = SomePtr(lltype.typeOf(x))
         elif callable(x) or isinstance(x, staticmethod): # XXX
@@ -287,38 +421,36 @@
 
         access_sets = self.pbc_maximal_access_sets
         objects = pbc.prebuiltinstances.keys()
-        access = None
-        first = None
-        change = False
-        
+
         for obj in objects:
             if obj is not None:
                 first = obj
                 break
+        else:
+            return SomeImpossibleValue()
+
+        change, rep, access = access_sets.find(first)
+        for obj in objects:
+            if obj is not None:
+                change1, rep, access = access_sets.union(rep, obj)
+                change = change or change1
 
-        if first is not None:
-            change, rep, access = access_sets.find(objects[0])
-            for obj in objects:
-                if obj is not None:
-                    change1, rep, access = access_sets.union(rep, obj)
-                    change = change or change1
-
-            access.attrs[attr] = True
-            position = self.position_key
-            access.read_locations[position] = True
+        position = self.position_key
+        access.read_locations[position] = True
 
         actuals = []
+        for c in access.objects:
+            if hasattr(c, attr):
+                actuals.append(self.immutablevalue(getattr(c, attr)))
+        s_result = unionof(*actuals)
 
-        if access:
-            for c in access.objects:
-                if hasattr(c, attr):
-                    actuals.append(self.immutablevalue(getattr(c, attr)))
+        access.attrs[attr] = s_result
 
         if change:
             for position in access.read_locations:
                 self.annotator.reflowfromposition(position)
                 
-        return unionof(*actuals)        
+        return s_result
 
     def consider_pbc_call(self, pbc, shape, spaceop=None, implicit_init=None): # computation done at fix-point
         if not isinstance(pbc, SomePBC):

Modified: pypy/branch/pycompiler/annotation/builtin.py
==============================================================================
--- pypy/branch/pycompiler/annotation/builtin.py	(original)
+++ pypy/branch/pycompiler/annotation/builtin.py	Fri Jul  1 18:30:34 2005
@@ -85,8 +85,8 @@
 def builtin_unichr(s_int):
     return constpropagate(unichr, [s_int], SomeUnicodeCodePoint())
 
-def builtin_unicode(s_obj):
-    raise TypeError, "unicode() calls should not happen at interp-level"
+##def builtin_unicode(s_obj):
+##    raise TypeError, "unicode() calls should not happen at interp-level"
 
 def our_issubclass(cls1, cls2):
     """ we're going to try to be less silly in the face of old-style classes"""
@@ -148,8 +148,8 @@
         r.const = hasattr(s_obj.const, s_attr.const)
     return r
 
-def builtin_callable(s_obj):
-    return SomeBool()
+##def builtin_callable(s_obj):
+##    return SomeBool()
 
 def builtin_tuple(s_iterable):
     if isinstance(s_iterable, SomeTuple):
@@ -179,10 +179,10 @@
     getbookkeeper().warning("ignoring apply%r" % (stuff,))
     return SomeObject()
 
-def builtin_compile(*stuff):
-    s = SomeObject()
-    s.knowntype = types.CodeType
-    return s
+##def builtin_compile(*stuff):
+##    s = SomeObject()
+##    s.knowntype = types.CodeType
+##    return s
 
 def builtin_slice(*args):
     bk = getbookkeeper()
@@ -220,15 +220,15 @@
 def rarith_intmask(s_obj):
     return SomeInteger()
 
-def rarith_ovfcheck(s_obj):
-    if isinstance(s_obj, SomeInteger) and s_obj.unsigned:
-        getbookkeeper().warning("ovfcheck on unsigned")
-    return s_obj
-
-def rarith_ovfcheck_lshift(s_obj1, s_obj2):
-    if isinstance(s_obj1, SomeInteger) and s_obj1.unsigned:
-        getbookkeeper().warning("ovfcheck_lshift with unsigned")
-    return SomeInteger()
+##def rarith_ovfcheck(s_obj):
+##    if isinstance(s_obj, SomeInteger) and s_obj.unsigned:
+##        getbookkeeper().warning("ovfcheck on unsigned")
+##    return s_obj
+
+##def rarith_ovfcheck_lshift(s_obj1, s_obj2):
+##    if isinstance(s_obj1, SomeInteger) and s_obj1.unsigned:
+##        getbookkeeper().warning("ovfcheck_lshift with unsigned")
+##    return SomeInteger()
 
 def unicodedata_decimal(s_uchr):
     raise TypeError, "unicodedate.decimal() calls should not happen at interp-level"    
@@ -254,8 +254,8 @@
         BUILTIN_ANALYZERS[original] = value
 
 BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.r_uint] = restricted_uint
-BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck] = rarith_ovfcheck
-BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck_lshift] = rarith_ovfcheck_lshift
+##BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck] = rarith_ovfcheck
+##BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck_lshift] = rarith_ovfcheck_lshift
 BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.intmask] = rarith_intmask
 
 BUILTIN_ANALYZERS[Exception.__init__.im_func] = exception_init
@@ -272,9 +272,9 @@
 BUILTIN_ANALYZERS[unicodedata.decimal] = unicodedata_decimal # xxx
 
 # os.path stuff
-BUILTIN_ANALYZERS[os.path.dirname] = pathpart
-BUILTIN_ANALYZERS[os.path.normpath] = pathpart
-BUILTIN_ANALYZERS[os.path.join] = pathpart
+#BUILTIN_ANALYZERS[os.path.dirname] = pathpart
+#BUILTIN_ANALYZERS[os.path.normpath] = pathpart
+#BUILTIN_ANALYZERS[os.path.join] = pathpart
 BUILTIN_ANALYZERS[os.path.exists] = test
 BUILTIN_ANALYZERS[os.path.isdir] = test
 
@@ -306,9 +306,7 @@
 def nullptr(T):
     assert T.is_constant()
     p = lltype.nullptr(T.const)
-    r = SomePtr(lltype.typeOf(p))
-    r.const = p
-    return r
+    return immutablevalue(p)
 
 def cast_pointer(PtrT, s_p):
     assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p
@@ -316,9 +314,18 @@
     cast_p = lltype.cast_pointer(PtrT.const, s_p.ll_ptrtype._defl())
     return SomePtr(ll_ptrtype=lltype.typeOf(cast_p))
 
+def getRuntimeTypeInfo(T):
+    assert T.is_constant()
+    return immutablevalue(lltype.getRuntimeTypeInfo(T.const))
+
+def runtime_type_info(s_p):
+    assert isinstance(s_p, SomePtr), "runtime_type_info of non-pointer: %r" % s_p
+    return SomePtr(lltype.typeOf(lltype.runtime_type_info(s_p.ll_ptrtype._example())))
 
 BUILTIN_ANALYZERS[lltype.malloc] = malloc
 BUILTIN_ANALYZERS[lltype.typeOf] = typeOf
 BUILTIN_ANALYZERS[lltype.nullptr] = nullptr
 BUILTIN_ANALYZERS[lltype.cast_pointer] = cast_pointer
+BUILTIN_ANALYZERS[lltype.getRuntimeTypeInfo] = getRuntimeTypeInfo
+BUILTIN_ANALYZERS[lltype.runtime_type_info] = runtime_type_info
 

Modified: pypy/branch/pycompiler/annotation/classdef.py
==============================================================================
--- pypy/branch/pycompiler/annotation/classdef.py	(original)
+++ pypy/branch/pycompiler/annotation/classdef.py	Fri Jul  1 18:30:34 2005
@@ -7,42 +7,115 @@
 from pypy.annotation.model import SomeImpossibleValue, SomePBC, tracking_unionof
 
 
+# The main purpose of a ClassDef is to collect information about class/instance
+# attributes as they are really used.  An Attribute object is stored in the
+# most general ClassDef where an attribute of that name is read/written:
+#    classdef.attrs = {'attrname': Attribute()}
+#
+# The following invariants hold:
+#
+# (A) if an attribute is read/written on an instance of class A, then the
+#     classdef of A or a parent class of A has an Attribute object corresponding
+#     to that name.
+#
+# (I) if B is a subclass of A, then they don't have both an Attribute for the
+#     same name.  (All information from B's Attribute must be merged into A's.)
+#
+# Additionally, each ClassDef records an 'attr_sources': it maps attribute
+# names to a set of objects that want to provide a constant value for this
+# attribute at the level of this class.  The attrsources provide information
+# higher in the class hierarchy than concrete Attribute()s.  It is for the case
+# where (so far or definitely) the user program only reads/writes the attribute
+# at the level of a subclass, but a value for this attribute could possibly
+# exist in the parent class or in an instance of a parent class.
+#
+# The point of not automatically forcing the Attribute instance up to the
+# parent class which has a class attribute of the same name is apparent with
+# multiple subclasses:
+#
+#                                    A
+#                                 attr=s1
+#                                  /   \
+#                                 /     \
+#                                B       C
+#                             attr=s2  attr=s3
+#
+# In this case, as long as 'attr' is only read/written from B or C, the
+# Attribute on B says that it can be 's1 or s2', and the Attribute on C says
+# it can be 's1 or s3'.  Merging them into a single Attribute on A would give
+# the more imprecise 's1 or s2 or s3'.
+#
+# The following invariant holds:
+#
+# (II) if a class A has an Attribute, the 'attrsources' for the same name is
+#      empty.  It is also empty on all subclasses of A.  (The information goes
+#      into the Attribute directly in this case.)
+#
+# The attrsources have the format {object: classdef}.  For class attributes,
+# 'object' is the class in question and 'classdef' its corresponding classdef,
+# used for binding methods.  For attribute sources that are prebuilt instances,
+# 'classdef' is None.
+#
+# The following invariant holds:
+#
+#  (III) for a class A, each attrsource that comes from the class (as opposed to
+#        from a prebuilt instance) must be merged into all Attributes of the
+#        same name in all subclasses of A, if any.  (Parent class attributes can
+#        be visible in reads from instances of subclasses.)
+
+
 class Attribute:
     # readonly-ness
     # SomeThing-ness
-    # more potential sources (pbcs or classes) of information
-    # NB. the laziness of 'sources' was required for two reasons:
-    #     * some strange attributes exist on classes but are never touched,
-    #       immutablevalue() wouldn't be happy with them
-    #     * there is an infinite recursion between immutablevalue() and
-    #       add_source_for_attribute() for cyclic constant structures.
+    # NB.  an attribute is readonly if it is a constant class attribute.
+    #      Both writing to the instance attribute and discovering prebuilt
+    #      instances that have the attribute set will turn off readonly-ness.
 
     def __init__(self, name, bookkeeper):
         self.name = name
         self.bookkeeper = bookkeeper
-        self.sources = {} # source -> None or ClassDef
         # XXX a SomeImpossibleValue() constant?  later!!
         self.s_value = SomeImpossibleValue()
         self.readonly = True
         self.read_locations = {}
 
+    def add_constant_source(self, source, classdef):
+        s_value = self.bookkeeper.immutablevalue(
+            source.__dict__[self.name])
+        if classdef:
+            s_value = s_value.bindcallables(classdef)
+        else:
+            # a prebuilt instance source forces readonly=False, see above
+            self.readonly = False
+        self.s_value = tracking_unionof(self, self.s_value, s_value)
+
     def getvalue(self):
-        while self.sources:
-            source, classdef = self.sources.popitem()
-            s_value = self.bookkeeper.immutablevalue(
-                source.__dict__[self.name])
-            if classdef:
-                s_value = s_value.bindcallables(classdef)
-            self.s_value = tracking_unionof(self, self.s_value, s_value)
+        # Same as 'self.s_value' for historical reasons.
         return self.s_value
 
     def merge(self, other):
         assert self.name == other.name
-        self.sources.update(other.sources)
         self.s_value = tracking_unionof(self, self.s_value, other.s_value)
         self.readonly = self.readonly and other.readonly
         self.read_locations.update(other.read_locations)
 
+    def mutated(self, homedef): # reflow from attr read positions
+        s_newvalue = self.getvalue()
+        # check for method demotion
+        if isinstance(s_newvalue, SomePBC):
+            attr = self.name
+            meth = False
+            for func, classdef  in s_newvalue.prebuiltinstances.items():
+                if isclassdef(classdef):
+                    meth = True
+                    break
+            if meth and getattr(homedef.cls, attr, None) is None:
+                self.bookkeeper.warning("demoting method %s to base class %s" % (self.name, homedef))
+
+        for position in self.read_locations:
+            self.bookkeeper.annotator.reflowfromposition(position)        
+
+
 
 class ClassDef:
     "Wraps a user class."
@@ -53,6 +126,7 @@
         #self.instantiation_locations = {}
         self.cls = cls
         self.subdefs = {}
+        self.attr_sources = {}   # {name: {constant_object: classdef_or_None}}
         base = object
         mixeddict = {}
         sources = {}
@@ -93,41 +167,47 @@
                     value.class_ = cls # remember that this is really a method
             self.add_source_for_attribute(name, sources.get(name, cls), self)
 
-    def attr_mutated(self, homedef, attrdef): # reflow from attr read positions
-        s_newvalue = attrdef.getvalue()
-        # check for method demotion
-        if isinstance(s_newvalue, SomePBC):
-            attr = attrdef.name
-            meth = False
-            for func, classdef  in s_newvalue.prebuiltinstances.items():
-                if isclassdef(classdef):
-                    meth = True
-                    break
-            if meth and getattr(homedef.cls, attr, None) is None:
-                self.bookkeeper.warning("demoting method %s to base class %s" % (attrdef.name, homedef))
-
-        for position in attrdef.read_locations:
-            self.bookkeeper.annotator.reflowfromposition(position)        
-
     def add_source_for_attribute(self, attr, source, clsdef=None):
-        homedef = self.locate_attribute(attr)
-        attrdef = homedef.attrs[attr]
-        attrdef.sources[source] = clsdef
-        if attrdef.read_locations:
-            # we should reflow from all the reader's position,
-            # but as an optimization we try to see if the attribute
-            # has really been generalized
-            s_prev_value = attrdef.s_value
-            s_next_value = attrdef.getvalue()
-            if s_prev_value != s_next_value:
-                self.attr_mutated(homedef, attrdef)
-
-    def locate_attribute(self, attr):
+        """Adds information about a constant source for an attribute.
+        """
         for cdef in self.getmro():
             if attr in cdef.attrs:
-                return cdef
-        self.generalize_attr(attr)
-        return self
+                # the Attribute() exists already for this class (or a parent)
+                attrdef = cdef.attrs[attr]
+                s_prev_value = attrdef.s_value
+                attrdef.add_constant_source(source, clsdef)
+                # we should reflow from all the reader's position,
+                # but as an optimization we try to see if the attribute
+                # has really been generalized
+                if attrdef.s_value != s_prev_value:
+                    attrdef.mutated(cdef) # reflow from all read positions
+                return
+        else:
+            # remember the source in self.attr_sources
+            sources = self.attr_sources.setdefault(attr, {})
+            sources[source] = clsdef
+            # register the source in any Attribute found in subclasses,
+            # to restore invariant (III)
+            # NB. add_constant_source() may discover new subdefs but the
+            #     right thing will happen to them because self.attr_sources
+            #     was already updated
+            if clsdef is not None:
+                for subdef in self.getallsubdefs():
+                    if attr in subdef.attrs:
+                        attrdef = subdef.attrs[attr]
+                        s_prev_value = attrdef.s_value
+                        attrdef.add_constant_source(source, clsdef)
+                        if attrdef.s_value != s_prev_value:
+                            attrdef.mutated(subdef) # reflow from all read positions
+
+    def locate_attribute(self, attr):
+        while True:
+            for cdef in self.getmro():
+                if attr in cdef.attrs:
+                    return cdef
+            self.generalize_attr(attr)
+            # the return value will likely be 'self' now, but not always -- see
+            # test_annrpython.test_attr_moving_from_subclass_to_class_to_parent
 
     def find_attribute(self, attr):
         return self.locate_attribute(attr).attrs[attr]
@@ -140,7 +220,7 @@
         while other is not None and not issubclass(self.cls, other.cls):
             other = other.basedef
         # special case for MI with Exception
-        if not other:
+        if other is None and other1 is not None:
             if issubclass(self.cls, Exception) and issubclass(other1.cls, Exception):
                 return self.bookkeeper.getclassdef(Exception)
         return other
@@ -169,41 +249,59 @@
                     pending.append(sub)
                     seen[sub] = True
 
-##    def getallinstantiations(self):
-##        locations = {}
-##        for clsdef in self.getallsubdefs():
-##            locations.update(clsdef.instantiation_locations)
-##        return locations
-
     def _generalize_attr(self, attr, s_value):
         # first remove the attribute from subclasses -- including us!
+        # invariant (I)
         subclass_attrs = []
+        constant_sources = {}
         for subdef in self.getallsubdefs():
             if attr in subdef.attrs:
                 subclass_attrs.append(subdef.attrs[attr])
                 del subdef.attrs[attr]
+            if attr in subdef.attr_sources:
+                # accumulate attr_sources for this attribute from all subclasses
+                d = subdef.attr_sources[attr]
+                constant_sources.update(d)
+                d.clear()    # invariant (II)
+
+        # accumulate attr_sources for this attribute from all parents, too
+        # invariant (III)
+        for superdef in self.getmro():
+            if attr in superdef.attr_sources:
+                for source, classdef in superdef.attr_sources[attr].items():
+                    if classdef is not None:
+                        constant_sources[source] = classdef
 
-        # do the generalization
+        # create the Attribute and do the generalization asked for
         newattr = Attribute(attr, self.bookkeeper)
         if s_value:
             newattr.s_value = s_value
-            
+
+        # keep all subattributes' values
         for subattr in subclass_attrs:
             newattr.merge(subattr)
+
+        # store this new Attribute, generalizing the previous ones from
+        # subclasses -- invariant (A)
         self.attrs[attr] = newattr
 
+        # add the values of the pending constant attributes
+        # completes invariants (II) and (III)
+        for source, classdef in constant_sources.items():
+            newattr.add_constant_source(source, classdef)
+
         # reflow from all read positions
-        self.attr_mutated(self, newattr)
+        newattr.mutated(self)
 
     def generalize_attr(self, attr, s_value=None):
-        # if the attribute exists in a superclass, generalize there.
+        # if the attribute exists in a superclass, generalize there,
+        # as imposed by invariant (I)
         for clsdef in self.getmro():
             if attr in clsdef.attrs:
                 clsdef._generalize_attr(attr, s_value)
                 break
         else:
             self._generalize_attr(attr, s_value)
-            assert attr in self.attrs
 
     def about_attribute(self, name):
         """This is the interface for the code generators to ask about
@@ -238,7 +336,11 @@
                     continue # not matching
             d[func] = value
         if uplookup is not None:
-            d[upfunc] = uplookup
+            # when the method is found in a parent class, it get bound to the
+            # 'self' subclass.  This allows the 'func: classdef' entry of the
+            # PBC dictionary to track more precisely with which 'self' the
+            # method is called.
+            d[upfunc] = self
         elif meth:
             self.check_missing_attribute_update(name)
         if d:

Modified: pypy/branch/pycompiler/annotation/model.py
==============================================================================
--- pypy/branch/pycompiler/annotation/model.py	(original)
+++ pypy/branch/pycompiler/annotation/model.py	Fri Jul  1 18:30:34 2005
@@ -50,7 +50,7 @@
 So I trashed 8 hours of work, without a check-in. (Just
 writing this here to leave *some* trace of work).
 
-Then I tried to make allinstances unique and wrote a lot
+Then I tried to make all instances unique and wrote a lot
 of attribute tracking code here, locked write access
 outside of __init__, and patched many modules and several
 hundred lines of code.
@@ -204,8 +204,15 @@
     def __init__(self, listdef):
         self.listdef = listdef
     def __eq__(self, other):
-        return (self.__class__ is other.__class__ and
-                self.listdef.same_as(other.listdef))
+        if self.__class__ is not other.__class__:
+            return False
+        if not self.listdef.same_as(other.listdef):
+            return False
+        selfdic = self.__dict__.copy()
+        otherdic = other.__dict__.copy()
+        del selfdic['listdef']
+        del otherdic['listdef']
+        return selfdic == otherdic
 
     def can_be_none(self):
         return True
@@ -240,12 +247,26 @@
     def __init__(self, dictdef):
         self.dictdef = dictdef
     def __eq__(self, other):
-        return (self.__class__ is other.__class__ and
-                self.dictdef.same_as(other.dictdef))
+        if self.__class__ is not other.__class__:
+            return False
+        if not self.dictdef.same_as(other.dictdef):
+            return False
+        selfdic = self.__dict__.copy()
+        otherdic = other.__dict__.copy()
+        del selfdic['dictdef']
+        del otherdic['dictdef']
+        return selfdic == otherdic
 
     def can_be_none(self):
         return False
 
+    def fmt_const(self, const):
+        if len(const) < 20:
+            return repr(const)
+        else:
+            return '{...%s...}'%(len(const),)
+
+
 class SomeIterator(SomeObject):
     "Stands for an iterator returning objects from a given container."
     knowntype = type(iter([]))  # arbitrarily chose seqiter as the type
@@ -381,6 +402,7 @@
     (SomeInteger(nonneg=True, unsigned=True), lltype.Unsigned),    
     (SomeFloat(), lltype.Float),
     (SomeChar(), lltype.Char),
+    (SomeUnicodeCodePoint(), lltype.UniChar),
 ]
 
 def annotation_to_lltype(s_val, info=None):
@@ -407,7 +429,10 @@
 
 def ll_to_annotation(v):
     if v is None:
-        raise ValueError, "cannot retrieve Void low-level type value"
+        # i think we can only get here in the case of void-returning
+        # functions
+        from bookkeeper import getbookkeeper
+        return getbookkeeper().immutablevalue(None)
     return lltype_to_annotation(lltype.typeOf(v))
 
 # ____________________________________________________________

Modified: pypy/branch/pycompiler/annotation/pairtype.py
==============================================================================
--- pypy/branch/pycompiler/annotation/pairtype.py	(original)
+++ pypy/branch/pycompiler/annotation/pairtype.py	Fri Jul  1 18:30:34 2005
@@ -9,6 +9,9 @@
         if name == '__extend__':
             cls = bases[0]   # override data into the existing base
             for key, value in dict.items():
+                if key == '__module__':
+                    continue
+                    # XXX do we need to provide something more for pickling?
                 setattr(cls, key, value)
             return None
         else:

Modified: pypy/branch/pycompiler/annotation/policy.py
==============================================================================
--- pypy/branch/pycompiler/annotation/policy.py	(original)
+++ pypy/branch/pycompiler/annotation/policy.py	Fri Jul  1 18:30:34 2005
@@ -1,6 +1,20 @@
 # base annotation policy for overrides and specialization
 from pypy.annotation.specialize import memo, ctr_location, default_specialize as default
-from pypy.translator.annrpython import BasicAnnotatorPolicy
+from pypy.annotation.specialize import argtype, argvalue
+# for some reason, model must be imported first,
+# or we create a cycle.
+from pypy.annotation import model as annmodel
+from pypy.annotation.bookkeeper import getbookkeeper
+
+
+class BasicAnnotatorPolicy:
+    
+    def specialize(pol, bookkeeper, spaceop, func, args, mono):
+        return None, None
+
+    def compute_at_fixpoint(pol, annotator):
+        annotator.bookkeeper.compute_at_fixpoint()
+
 
 class AnnotatorPolicy(BasicAnnotatorPolicy):
     """
@@ -48,3 +62,11 @@
     default_specialize = staticmethod(default)
     specialize__memo = staticmethod(memo)
     specialize__ctr_location = staticmethod(ctr_location)
+    specialize__arg0 = staticmethod(argvalue(0))
+    specialize__argtype0 = staticmethod(argtype(0))
+    specialize__arg1 = staticmethod(argvalue(1))
+    specialize__argtype1 = staticmethod(argtype(1))
+
+    def override__ignore(pol, *args):
+        bk = getbookkeeper()
+        return bk.immutablevalue(None)

Modified: pypy/branch/pycompiler/annotation/specialize.py
==============================================================================
--- pypy/branch/pycompiler/annotation/specialize.py	(original)
+++ pypy/branch/pycompiler/annotation/specialize.py	Fri Jul  1 18:30:34 2005
@@ -126,6 +126,18 @@
 # ____________________________________________________________________________
 # specializations
 
+class MemoTable:
+    def __init__(self, bookkeeper, func, s_result, arglist_s):
+        self.table = {}
+        self.arglist_s = arglist_s
+        self.s_result = s_result 
+        for arglist in possible_arguments(arglist_s):
+            result = func(*arglist)
+            self.table[arglist] = result
+        bookkeeper.memo_tables.append(self)
+    def _freeze_(self):
+        return True
+
 def memo(bookkeeper, mod, spaceop, func, args, mono):
     """NOT_RPYTHON"""
     assert mono, "not-static call to memoized %s" % func
@@ -140,28 +152,32 @@
         possible_results.append(bookkeeper.immutablevalue(result))
     return unionof(*possible_results), args
 
-def possible_arguments(args):
+def possible_values_of(s):
     from pypy.annotation.model import SomeBool, SomePBC
-    # enumerate all tuples (x1,..xn) of concrete values that are contained
-    # in a tuple args=(s1,..sn) of SomeXxx.  Requires that each s be either
-    # a constant or SomePBC.
-    if not args:
-        yield ()
-        return
-    s = args[0]
     if s.is_constant():
-        possible_values = [s.const]
+        return [s.const]
     elif isinstance(s, SomePBC):
         for value in s.prebuiltinstances.values():
             assert value is True, ("concrete call with a method bound "
                                    "on a non-constant instance")
-        possible_values = s.prebuiltinstances.keys()
+        return s.prebuiltinstances.keys()
     elif isinstance(s, SomeBool):
-        possible_values = [False, True]
+        return [False, True]
     else:
-        raise AssertionError, "concrete call with a non-constant arg %r" % (s,)
-    for tuple_tail in possible_arguments(args[1:]):
-        for value in possible_values:
+        raise ValueError, "memo call with a non-constant arg %r" % (s,)
+
+def possible_arguments(args):
+    # enumerate all tuples (x1,..xn) of concrete values that are contained
+    # in a tuple args=(s1,..sn) of SomeXxx.  Requires that each s be either
+    # a constant or SomePBC.
+    return cartesian_product([possible_values_of(s) for s in args])
+
+def cartesian_product(lstlst):
+    if not lstlst:
+        yield ()
+        return
+    for tuple_tail in cartesian_product(lstlst[1:]):
+        for value in lstlst[0]:
             yield (value,) + tuple_tail
 
 #def argtypes(bookkeeper, spaceop, func, args, mono):

Modified: pypy/branch/pycompiler/annotation/unaryop.py
==============================================================================
--- pypy/branch/pycompiler/annotation/unaryop.py	(original)
+++ pypy/branch/pycompiler/annotation/unaryop.py	Fri Jul  1 18:30:34 2005
@@ -83,9 +83,20 @@
         return SomeInteger()
 
     def str(obj):
+        getbookkeeper().count('str', obj)
         return SomeString()
 
-    repr = hex = oct = str
+    def repr(obj):
+        getbookkeeper().count('repr', obj)
+        return SomeString()
+
+    def hex(obj):
+        getbookkeeper().count('hex', obj)
+        return SomeString()
+
+    def oct(obj):
+        getbookkeeper().count('oct', obj)
+        return SomeString()
 
     def id(obj): # xxx
         return SomeInteger()
@@ -197,6 +208,7 @@
         return immutablevalue(len(tup.items))
 
     def iter(tup):
+        getbookkeeper().count("tuple_iter", tup)
         return SomeIterator(tup)
 
     def getanyitem(tup):
@@ -211,8 +223,11 @@
 
     def method_extend(lst, s_iterable):
         lst.listdef.resize()
-        s_iter = s_iterable.iter()
-        pair(lst, SomeInteger()).setitem(s_iter.next())
+        if isinstance(s_iterable, SomeList):   # unify the two lists
+            lst.listdef.union(s_iterable.listdef)
+        else:
+            s_iter = s_iterable.iter()
+            pair(lst, SomeInteger()).setitem(s_iter.next())
 
     def method_reverse(lst):
         lst.listdef.mutate()
@@ -220,20 +235,19 @@
     def method_insert(lst, s_index, s_value):
         lst.listdef.resize()
         pair(lst, SomeInteger()).setitem(s_value)
-        
+
     def method_pop(lst, s_index=None):
         lst.listdef.resize()
         return lst.listdef.read_item()
 
     def method_index(lst, el):
+        getbookkeeper().count("list_index")
         return SomeInteger(nonneg=True)
 
     def len(lst):
         s_item = lst.listdef.read_item()
         if isinstance(s_item, SomeImpossibleValue):
-            r = SomeInteger(nonneg=True)
-            r.const = 0
-            return r
+            return immutablevalue(0)
         return SomeObject.len(lst)
 
     def iter(lst):
@@ -247,12 +261,10 @@
     def len(dct):
         s_key = dct.dictdef.read_key()
         s_value = dct.dictdef.read_value()
-        if isinstance(s_key, SomeImpossibleValue) and isinstance(s_value, SomeImpossibleValue):
-            r = SomeInteger(nonneg=True)
-            r.const = 0
-            return r
+        if isinstance(s_key, SomeImpossibleValue) or isinstance(s_value, SomeImpossibleValue):
+            return immutablevalue(0)
         return SomeObject.len(dct)
-    
+
     def iter(dct):
         return SomeIterator(dct)
 
@@ -260,14 +272,15 @@
         return dct.dictdef.read_key()
 
     def method_get(dct, key, dfl):
-        return unionof(dct.dictdef.read_value(), dfl)
+        dct.dictdef.generalize_key(key)
+        dct.dictdef.generalize_value(dfl)
+        return dct.dictdef.read_value()
 
     def method_copy(dct):
         return dct
 
     def method_update(dct1, dct2):
-        dct1.dictdef.generalize_key(dct2.dictdef.read_key())
-        dct1.dictdef.generalize_value(dct2.dictdef.read_value())
+        dct1.dictdef.union(dct2.dictdef)
 
     def method_keys(dct):
         return getbookkeeper().newlist(dct.dictdef.read_key())
@@ -278,10 +291,10 @@
     def method_items(dct):
         return getbookkeeper().newlist(SomeTuple((dct.dictdef.read_key(),
                                                   dct.dictdef.read_value())))
-        
 
-class __extend__(SomeString):
 
+class __extend__(SomeString):
+    
     def method_startswith(str, frag):
         return SomeBool()
 
@@ -289,6 +302,10 @@
         return SomeBool()
 
     def method_join(str, s_list):
+        getbookkeeper().count("str_join", str)
+        s_item = s_list.listdef.read_item()
+        if s_item == SomeImpossibleValue():
+            return immutablevalue("")
         return SomeString()
 
     def method_find(str, frag):
@@ -316,14 +333,21 @@
         return SomeInteger(nonneg=True)
 
     def method_split(str, patt): # XXX
+        getbookkeeper().count("str_split", str, patt)
         return getbookkeeper().newlist(SomeString())
 
+    def method_replace(str, s1, s2):
+        return SomeString()
+
 
 class __extend__(SomeChar):
 
     def len(chr):
         return immutablevalue(1)
 
+    def method_isspace(chr):
+        return SomeBool()
+
 class __extend__(SomeUnicodeCodePoint):
 
     def ord(uchr):
@@ -378,6 +402,7 @@
         if bltn.s_self is not None:
             return bltn.analyser(bltn.s_self, *args)
         else:
+            getbookkeeper().count(bltn.methodname.replace('.', '_'), *args)
             return bltn.analyser(*args)
 
     def call(bltn, args, implicit_init=False):
@@ -387,14 +412,14 @@
             return bltn.analyser(bltn.s_self, *args)
         else:
             return bltn.analyser(*args)
-        
+
 
 class __extend__(SomePBC):
 
     def getattr(pbc, s_attr):
         bookkeeper = getbookkeeper()
         return bookkeeper.pbc_getattr(pbc, s_attr)
-        
+
     def setattr(pbc, s_attr, s_value):
         getbookkeeper().warning("setattr not wanted on %r" % (pbc,))
 
@@ -405,21 +430,21 @@
         #bookkeeper = getbookkeeper()
         #results = []
         #for func, classdef in pbc.prebuiltinstances.items():
-        #    if isclassdef(classdef): 
+        #    if isclassdef(classdef):
         #        s_self = SomeInstance(classdef)
         #        args1 = args.prepend(s_self)
         #    else:
         #        args1 = args
         #    results.append(bookkeeper.pycall(func, args1))
-        #return unionof(*results) 
+        #return unionof(*results)
 
-    def bindcallables(pbc, classdef):   
-        """ turn the callables in the given SomeCallable 'cal' 
+    def bindcallables(pbc, classdef):
+        """ turn the callables in the given SomeCallable 'cal'
             into bound versions.
         """
         d = {}
         for func, value in pbc.prebuiltinstances.items():
-            if isinstance(func, FunctionType): 
+            if isinstance(func, FunctionType):
                 if isclassdef(value):
                     getbookkeeper().warning("rebinding an already bound "
                                             "method %r with %r" % (func, value))
@@ -427,20 +452,24 @@
             elif isinstance(func, staticmethod):
                 d[func.__get__(43)] = value
             else:
-                d[func] = value 
+                d[func] = value
         return SomePBC(d)
 
     def is_true(pbc):
         outcome = None
         for c in pbc.prebuiltinstances:
+            if c is not None and not bool(c):
+                getbookkeeper().warning("PBC %r has truth value False" % (c,))
+                getbookkeeper().count("pbc_is_true", pbc)
+        for c in pbc.prebuiltinstances:
             if outcome is None:
                 outcome = bool(c)
             else:
                 if outcome != bool(c):
                     return SomeBool()
         return immutablevalue(outcome)
-            
-            
+
+
 # annotation of low-level types
 from pypy.annotation.model import SomePtr, ll_to_annotation, annotation_to_lltype
 class __extend__(SomePtr):
@@ -451,7 +480,8 @@
         return ll_to_annotation(v)
 
     def len(p):
-        return ll_to_annotation(len(p.ll_ptrtype._example()))
+        len(p.ll_ptrtype._example())   # just doing checking
+        return SomeObject.len(p)
 
     def setattr(p, s_attr, s_value): # just doing checking
         assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % p.ll_ptrtype

Modified: pypy/branch/pycompiler/bin/translator.py
==============================================================================
--- pypy/branch/pycompiler/bin/translator.py	(original)
+++ pypy/branch/pycompiler/bin/translator.py	Fri Jul  1 18:30:34 2005
@@ -211,8 +211,12 @@
 
 def setup_readline():
     import readline
-    import rlcompleter
-    readline.parse_and_bind("tab: complete")
+    try:
+        import rlcompleter2
+        rlcompleter2.setup()
+    except ImportError:
+        import rlcompleter
+        readline.parse_and_bind("tab: complete")
     import os
     histfile = os.path.join(os.environ["HOME"], ".pypytrhist")
     try:

Modified: pypy/branch/pycompiler/documentation/architecture.txt
==============================================================================
--- pypy/branch/pycompiler/documentation/architecture.txt	(original)
+++ pypy/branch/pycompiler/documentation/architecture.txt	Fri Jul  1 18:30:34 2005
@@ -105,7 +105,7 @@
 Please note that we are using the term *interpreter* most often in
 reference to the *plain interpreter* which just knows enough to read,
 dispatch and implement *bytecodes* thus shuffling objects around on the
-stack and between namespaces.  The (plain) interpreter is completly
+stack and between namespaces.  The (plain) interpreter is completely
 ignorant of how to access, modify or construct objects and their
 structure and thus delegates such operations to a so called `Object Space`_.
 
@@ -351,7 +351,7 @@
 order for our translation and type inference mechanisms to work
 effectively, we need to restrict the dynamism of our interpreter-level
 Python code at some point.  However, in the start-up phase, we are
-completly free to use all kind of nice python constructs, including
+completely free to use all kind of nice python constructs, including
 metaclasses and execution of dynamically constructed strings.  However,
 when the initialization phase (mainly, the function
 ``objspace.initialize()``) finishes, all code objects involved need to
@@ -367,7 +367,7 @@
 of values, and an exitswitch to one, two or multiple links which connect
 each basic block to other basic blocks. 
 
-The flow graphs are fed as input into the Annotator. The Annotator,
+The flow graphs are fed as input into the Annotator.  The Annotator,
 given entry point types, infers the types of values that flow through
 the program variables.  Here, the definition of `RPython`_ comes
 again into play: RPython code is restricted in such a way that the
@@ -383,7 +383,7 @@
 definition will probably continue to shift marginally as we improve it.
 
 The actual low-level code (and, in fact, also other high-level code) is
-emitted by "visiting" the type-annotated flow graph. Currently, we have
+emitted by "visiting" the type-annotated flow graph.  Currently we have
 a C-producing backend, and an LLVM-producing backend.  The former also
 accepts non-annotated or partially-annotated graphs, which allow us to
 test it on a larger class of programs than what the Annotator can (or

Modified: pypy/branch/pycompiler/documentation/coding-guide.txt
==============================================================================
--- pypy/branch/pycompiler/documentation/coding-guide.txt	(original)
+++ pypy/branch/pycompiler/documentation/coding-guide.txt	Fri Jul  1 18:30:34 2005
@@ -1,24 +1,25 @@
 =====================================
-PyPy - Coding Guide 
+PyPy - Coding Guide
 =====================================
 
 .. contents::
 .. sectnum::
 
 
-This document describes coding requirements and conventions for 
-working with the PyPy code base.  Please read it carefully and 
-ask back any questions you might have. 
+This document describes coding requirements and conventions for
+working with the PyPy code base.  Please read it carefully and
+ask back any questions you might have.
 
-.. _`RPython`: 
+.. _`RPython`:
 
 Restricted Python
 ==================
 
-We are writing a Python interpreter in Python, using Python's well known ability 
-to step behind the algorithmic problems as language. At first glance, one might 
-think this achieves nothing but a better understanding how the interpreter works. 
-This alone would make it worth doing, but we have much larger goals. 
+We are writing a Python interpreter in Python, using Python's well known
+ability to step behind the algorithmic problems as language. At first glance,
+one might think this achieves nothing but a better understanding how the
+interpreter works.  This alone would make it worth doing, but we have much
+larger goals.
 
 
 CPython vs. PyPy
@@ -29,36 +30,36 @@
 also aim at writing a more flexible interpreter at C level but but we
 want to use Python to give an alternative description of the interpreter.
 
-The clear advantage is that such a description is shorter and simpler to 
-read, and many implementation details vanish. The drawback of this approach is 
+The clear advantage is that such a description is shorter and simpler to
+read, and many implementation details vanish. The drawback of this approach is
 that this interpreter will be unbearably slow as long as it is run on top
 of CPython.
 
 To get to a useful interpreter again, we need to translate our
 high-level description of Python to a lower level one.  One rather
 straight-forward way is to do a whole program analysis of the PyPy
-interpreter and create a C source, again. There are many other ways, 
-but let's stick with this somewhat canonical approach.  
+interpreter and create a C source, again. There are many other ways,
+but let's stick with this somewhat canonical approach.
 
-our runtime interpreter is "restricted python" 
+our runtime interpreter is "restricted python"
 ----------------------------------------------
 
 In order to make a C code generator feasible we restrict ourselves to a
 subset of the Python language, and we adhere to some rules which make
-translation to lower level languages more obvious. 
+translation to lower level languages more obvious.
 
 Unlike source-to-source translations (like e.g. Starkiller_) we start
 translation from live python code objects which constitute our Python
 interpreter.   When doing its work of interpreting bytecode our Python
-implementation must behave in a static way often referenced as 
-"RPythonic". 
+implementation must behave in a static way often referenced as
+"RPythonic".
 
 .. _Starkiller: http://www.python.org/pycon/dc2004/papers/1/paper.pdf
 
 However, when the PyPy interpreter is started as a Python program, it
 can use all of the Python language until it reaches interpretation
 runtime. That is, during initialization our program is free to use the
-full dynamism of Python, including dynamic code generation. 
+full dynamism of Python, including dynamic code generation.
 
 An example can be found in the current implementation which is quite
 elegant: For the definition of all the opcodes of the Python
@@ -74,19 +75,19 @@
 during translation, a whole program analysis ("type inference") is
 performed, which makes use of the restrictions defined in RPython. This
 enables the code generator to emit efficient machine level replacements
-for pure integer objects, for instance.   
+for pure integer objects, for instance.
 
-.. _`pyopcode.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py 
+.. _`pyopcode.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py
 
 RPython Definition, not
 -----------------------
 
-The list and exact details of the "RPython" restrictions are a somewhat 
+The list and exact details of the "RPython" restrictions are a somewhat
 evolving topic.  In particular, we have no formal language definition
-as we find it more practical to discuss and evolve the set of 
+as we find it more practical to discuss and evolve the set of
 restrictions while working on the whole program analysis.  If you
 have any questions about the restrictions below then please feel
-free to mail us at pypy-dev at codespeak net. 
+free to mail us at pypy-dev at codespeak net.
 
 .. _`wrapped object`: coding-guide.html#wrapping-rules
 
@@ -94,7 +95,7 @@
 -------------------------
 
 **variables**
-  
+
   variables should contain values of at most one type as described in
   `Object restrictions`_ at each control flow point, that means for
   example that joining control paths using the same variable to
@@ -103,16 +104,16 @@
   and class instances is allowed.
 
 **constants**
-  
+
   all module globals are considered constants.
 
 **control structures**
-  
+
   all allowed
 
 **range**
-  
-  does not create an array. It is only allowed in for loops. The step argument 
+
+  does not create an array. It is only allowed in for loops. The step argument
   must be a constant.
 
 **definitions**
@@ -135,55 +136,55 @@
 We are using
 
 **integer, float, string, boolean**
-  
+
   avoid string methods and complex operations like slicing with a step
 
 **tuples**
-  
-  no variable-length tuples; use them to store or return pairs or n-tuples of 
+
+  no variable-length tuples; use them to store or return pairs or n-tuples of
   values. Each combination of types for elements and length constitute a separate
   and not mixable type.
 
 **lists**
-  
-  lists are used as an allocated array; list.append() does naive resizing, so as 
+
+  lists are used as an allocated array; list.append() does naive resizing, so as
   far as possible use list comprehensions (see below).  list.extend() or the +=
   operator are allowed and efficient.  Unless there is really a use case for it,
   repetition is limited to initialization purposes: '[single_value] * length'.
 
 **dicts**
-  
+
   dicts with string keys only (preferably the kind of strings that are usually
   interned in CPython, i.e. short strings that look like identifiers).  The
   implementation could safely decide that all dict keys should be interned.
 
 
 **list comprehensions**
-  
-  may be used to create allocated, initialized array. the array size must be 
+
+  may be used to create allocated, initialized array. the array size must be
   computable in advance, which implies that we don't allow an if clause.
 
 **functions**
 
-+ statically called functions may use defaults and a variable number of 
-  arguments (which may be passed as a list instead of a tuple, so write code that 
-  does not depend on it being a tuple).
-
-+ dynamic dispatch enforces use of very simple signatures, equal for all 
-  functions to be called in that context. At the moment, this occurs in the opcode 
-  dispatch, only.
++ statically called functions may use defaults and a variable number of
+  arguments (which may be passed as a list instead of a tuple, so write code
+  that does not depend on it being a tuple).
+
++ dynamic dispatch enforces use of very simple signatures, equal for all
+  functions to be called in that context. At the moment, this occurs in the
+  opcode dispatch, only.
 
 **builtin functions**
 
-  A few builtin functions will be used, while this set is not defined 
+  A few builtin functions will be used, while this set is not defined
   completely, yet. Some builtin functions are special forms:
 
 **len**
 
-+ may be used with basic types that have a length. But len is a special form 
++ may be used with basic types that have a length. But len is a special form
   that is recognized by the compiler.
 
-+ If a certain structure is never touched by len, the compiler might save the 
++ If a certain structure is never touched by len, the compiler might save the
   length field from the underlying structure.
 
 ``int, float, ord, chr``... are available as simple conversion functions.
@@ -198,8 +199,8 @@
 
 **objects**
 
-  wrapped objects are borrowed from the object space. Just like in CPython, code 
-  that needs e.g. a dictionary can use a wrapped dict and the object space 
+  wrapped objects are borrowed from the object space. Just like in CPython,
+  code that needs e.g. a dictionary can use a wrapped dict and the object space
   operations on it.
 
 This layout makes the number of types to take care about quite limited.
@@ -208,13 +209,13 @@
 Integer Types
 -------------------------
 
-While implementing the integer type, we stumbled over the problem, that 
+While implementing the integer type, we stumbled over the problem, that
 integers are quite in flux in CPython right now. Starting on Python 2.2,
-integers mutate into longs on overflow.  However, shifting to the left truncates
-up to 2.3 but extends to longs as well in 2.4.  By contrast, we need a way to
-perform wrap-around machine-sized arithmetic by default, while still being
-able to check for overflow when we need it explicitly.  Moreover, we need a
-consistent behavior before and after translation.
+integers mutate into longs on overflow.  However, shifting to the left
+truncates up to 2.3 but extends to longs as well in 2.4.  By contrast, we need
+a way to perform wrap-around machine-sized arithmetic by default, while still
+being able to check for overflow when we need it explicitly.  Moreover, we need
+a consistent behavior before and after translation.
 
 We use normal integers for signed arithmetic.  It means that before
 translation we get longs in case of overflow, and after translation we get a
@@ -226,7 +227,7 @@
   This special function should only be used with a single arithmetic operation
   as its argument, e.g. ``z = ovfcheck(x+y)``.  Its intended meaning is to
   perform the given operation in overflow-checking mode.
-  
+
   At run-time, in Python, the ovfcheck() function itself checks the result
   and raises OverflowError if it is a ``long``.  But the code generators use
   ovfcheck() as a hint: they replace the whole ``ovfcheck(x+y)`` expression
@@ -245,7 +246,7 @@
 
   This function is used for wrap-around arithmetic.  It returns the lower bits
   of its argument, masking away anything that doesn't fit in a C "signed long int".
-  Its purpose is, in Python, to convert from a Python ``long`` that resulted from a 
+  Its purpose is, in Python, to convert from a Python ``long`` that resulted from a
   previous operation back to a Python ``int``.  The code generators ignore
   intmask() entirely, as they are doing wrap-around signed arithmetic all the time
   by default anyway.  (We have no equivalent of the "int" versus "long int"
@@ -311,35 +312,46 @@
 
 Exceptions explicitly raised or re-raised will always be generated.
 
-PyPy is debuggable on top of CPython 
------------------------------------- 
+PyPy is debuggable on top of CPython
+------------------------------------
 
 PyPy has the advantage that it is runnable on standard
 CPython.  That means, we can run all of PyPy with all exception
 handling enabled, so we might catch cases where we failed to
 adhere to our implicit assertions.
 
-.. _`wrapping rules`: 
+.. _`wrapping rules`:
 
 Wrapping rules
 ==============
 
-PyPy is made of Python source code at two levels: there is on the one hand *application-level code* that looks like normal Python code, and that implements some functionalities as one would expect from Python code (e.g. one can give a pure Python implementation of some built-in functions like ``zip()``).  There is also *interpreter-level code* for the functionalities that must more directly manipulate interpreter data and objects (e.g. the main loop of the interpreter, and the various object spaces).
-
-Application-level code doesn't see object spaces explicitly: it runs using an object space to support the objects it manipulates, but this is implicit.  There is no need for particular conventions for application-level code.  The sequel is only about interpreter-level code.  (Ideally, no application-level variable should be called ``space`` or ``w_xxx`` to avoid confusion.)
+PyPy is made of Python source code at two levels: there is on the one hand
+*application-level code* that looks like normal Python code, and that
+implements some functionalities as one would expect from Python code (e.g. one
+can give a pure Python implementation of some built-in functions like
+``zip()``).  There is also *interpreter-level code* for the functionalities
+that must more directly manipulate interpreter data and objects (e.g. the main
+loop of the interpreter, and the various object spaces).
+
+Application-level code doesn't see object spaces explicitly: it runs using an
+object space to support the objects it manipulates, but this is implicit.
+There is no need for particular conventions for application-level code.  The
+sequel is only about interpreter-level code.  (Ideally, no application-level
+variable should be called ``space`` or ``w_xxx`` to avoid confusion.)
 
 
 Naming conventions
 ------------------
 
 * ``space``: the object space is only visible at
-  interpreter-level code, where it is by convention passed around by the name ``space``. 
+  interpreter-level code, where it is by convention passed around by the name
+  ``space``.
 
 * ``w_xxx``: any object seen by application-level code is an
   object explicitly managed by the object space.  From the
   interpreter-level point of view, this is called a *wrapped*
   object.  The ``w_`` prefix is used for any type of
-  application-level object.   
+  application-level object.
 
 * ``xxx_w``: an interpreter-level container for wrapped
   objects, for example a list or a dict containing wrapped
@@ -375,7 +387,8 @@
 Building ``w_xxx`` objects
 --------------------------
 
-From the core interpreter, wrapped objects are usually built as the result of an object space operation.  The ways to directly create a wrapped object are:
+From the core interpreter, wrapped objects are usually built as the result of
+an object space operation.  The ways to directly create a wrapped object are:
 
 * ``space.wrap(x)``: returns a wrapped object containing the
   value ``x``.  Only works if ``x`` is either a simple value
@@ -510,32 +523,32 @@
 application-level classes.
 
 
-.. _`modules`: 
+.. _`modules`:
 
-Modules in PyPy 
-=============== 
+Modules in PyPy
+===============
 
-Modules visible from application programs are imported from 
+Modules visible from application programs are imported from
 interpreter or application level files.  PyPy reuses almost all python
 modules of CPython's standard library, currently from version 2.3.4.  We
 sometimes need to `modify modules`_ and - more often - regression tests
-because they rely on implementation details of CPython.  
+because they rely on implementation details of CPython.
 
 If we don't just modify an original CPython module but need to rewrite
 it from scratch we put it into `pypy/lib/`_ as a pure application level
-module.  
+module.
 
 When we need access to interpreter-level objects we put the module into
 `pypy/module`_.  Such modules use a `mixed module mechanism`_
 which makes it convenient to use both interpreter- and applicationlevel
 parts for the implementation.  Note that there is no extra facility for
-pure-interpreter level modules because we haven't needed it so far. 
+pure-interpreter level modules because we haven't needed it so far.
 
-Determining the location of a module implementation 
---------------------------------------------------- 
+Determining the location of a module implementation
+---------------------------------------------------
 
-You can interactively find out where a module comes from, 
-here are examples for the possible locations:: 
+You can interactively find out where a module comes from,
+here are examples for the possible locations::
 
     >>>> import sys
     >>>> sys.__file__
@@ -556,21 +569,21 @@
     '/home/hpk/pypy-dist/lib-python/2.3.4/os.py'
     >>>>
 
-Module directories / Import order 
+Module directories / Import order
 ---------------------------------
 
-Here is the order in which PyPy looks up Python modules: 
+Here is the order in which PyPy looks up Python modules:
+
+*pypy/modules*
 
-*pypy/modules* 
+    mixed interpreter/app-level builtin modules, such as
+    the ``sys`` and ``__builtin__`` module.
 
-    mixed interpreter/app-level builtin modules, such as 
-    the ``sys`` and ``__builtin__`` module. 
+*contents of PYTHONPATH*
 
-*contents of PYTHONPATH* 
-    
-    lookup application level modules in each of the ``:`` separated 
-    list of directories, specified in the ``PYTHONPATH`` environment 
-    variable. 
+    lookup application level modules in each of the ``:`` separated
+    list of directories, specified in the ``PYTHONPATH`` environment
+    variable.
 
 *pypy/lib/*
 
@@ -582,93 +595,94 @@
 
 *lib-python/2.3.4/*
 
-    The unmodified CPython library. **Never ever checkin anything here**. 
+    The unmodified CPython library. **Never ever checkin anything here**.
 
-.. _`modify modules`: 
+.. _`modify modules`:
 
-Modifying a CPython library module or regression test 
-------------------------------------------------------- 
+Modifying a CPython library module or regression test
+-------------------------------------------------------
 
-Although PyPy is very compatible with CPython we sometimes need 
-to change modules contained in our copy of the standard library, 
-often due to the fact that PyPy works with all new-style classes 
-by default and CPython has a number of places where it relies 
-on some classes being old-style.  
+Although PyPy is very compatible with CPython we sometimes need
+to change modules contained in our copy of the standard library,
+often due to the fact that PyPy works with all new-style classes
+by default and CPython has a number of places where it relies
+on some classes being old-style.
 
 If you want to change a module or test contained in ``lib-python/2.3.4``
-then make sure that you copy the file to our ``lib-python/modified-2.3.4`` 
-directory first.  In subversion commandline terms this reads:: 
+then make sure that you copy the file to our ``lib-python/modified-2.3.4``
+directory first.  In subversion commandline terms this reads::
 
-    svn cp lib-python/2.3.4/somemodule.py lib-python/modified-2.3.4/ 
+    svn cp lib-python/2.3.4/somemodule.py lib-python/modified-2.3.4/
 
-and subsequently you edit and commit ``lib-python/modified-2.3.4/somemodule.py``. 
-This copying operation is important because it keeps the original 
-CPython tree clean and makes it obvious what we had to change. 
+and subsequently you edit and commit
+``lib-python/modified-2.3.4/somemodule.py``.  This copying operation is
+important because it keeps the original CPython tree clean and makes it
+obvious what we had to change.
 
-.. _`mixed module mechanism`: 
-.. _`mixed modules`: 
+.. _`mixed module mechanism`:
+.. _`mixed modules`:
 
-Implementing a mixed interpreter/application level Module 
---------------------------------------------------------- 
+Implementing a mixed interpreter/application level Module
+---------------------------------------------------------
 
-If a module needs to access PyPy's interpreter level 
-then it is implemented as a mixed module.   
+If a module needs to access PyPy's interpreter level
+then it is implemented as a mixed module.
 
 Mixed modules are directories in `pypy/module`_ with an  `__init__.py`
 file containing specifications where each name in a module comes from.
 Only specified names will be exported to a Mixed Module's applevel
-namespace.  
+namespace.
 
 application level definitions
 .............................
 
-Application level specifications are found in the `appleveldefs` 
-dictionary found in ``__init__.py`` files of directories in ``pypy/module``. 
-For example, in `pypy/module/__builtin__/__init__.py`_ you find the following 
-entry specifying where ``__builtin__.locals`` comes from:: 
+Application level specifications are found in the `appleveldefs`
+dictionary found in ``__init__.py`` files of directories in ``pypy/module``.
+For example, in `pypy/module/__builtin__/__init__.py`_ you find the following
+entry specifying where ``__builtin__.locals`` comes from::
 
      ...
      'locals'        : 'app_inspect.locals',
      ...
 
-The ``app_`` prefix indicates that the submodule ``app_inspect`` is 
-interpreted at application level and the wrapped function value for ``locals`` 
-will be extracted accordingly. 
+The ``app_`` prefix indicates that the submodule ``app_inspect`` is
+interpreted at application level and the wrapped function value for ``locals``
+will be extracted accordingly.
 
 interpreter level definitions
 .............................
 
-Interpreter level specifications are found in the ``interpleveldefs`` 
-dictionary found in ``__init__.py`` files of directories in ``pypy/module``. 
-For example, in `pypy/module/__builtin__/__init__.py`_ the following 
-entry specifies where ``__builtin__.len`` comes from:: 
+Interpreter level specifications are found in the ``interpleveldefs``
+dictionary found in ``__init__.py`` files of directories in ``pypy/module``.
+For example, in `pypy/module/__builtin__/__init__.py`_ the following
+entry specifies where ``__builtin__.len`` comes from::
 
      ...
      'len'       : 'operation.len',
      ...
 
-The ``operation`` submodule lives at interpreter level and ``len`` 
+The ``operation`` submodule lives at interpreter level and ``len``
 is expected to be exposable to application level.  Here is
-the definition for ``operation.len()``:: 
+the definition for ``operation.len()``::
 
     def len(space, w_obj):
         "len(object) -> integer\n\nReturn the number of items of a sequence or mapping."
         return space.len(w_obj)
 
 Exposed interpreter level functions usually take a ``space`` argument
-and some wrapped values (see `wrapping rules`_) .   
+and some wrapped values (see `wrapping rules`_) .
 
-You can also use a convenient shortcut in ``interpleveldefs`` dictionaries: 
-namely an expression in parentheses to specify an interpreter level 
-expression directly (instead of pulling it indirectly from a file):: 
+You can also use a convenient shortcut in ``interpleveldefs`` dictionaries:
+namely an expression in parentheses to specify an interpreter level
+expression directly (instead of pulling it indirectly from a file)::
 
     ...
     'None'          : '(space.w_None)',
     'False'         : '(space.w_False)',
-    ... 
+    ...
 
 The interpreter level expression has a ``space`` binding when
-it is executed. 
+it is executed.
 
 Testing modules in ``pypy/lib``
 --------------------------------
@@ -677,50 +691,50 @@
 ("py.test" or "python ../../test_all.py") to run tests against the
 pypy/lib hierarchy.  Note, that tests in `pypy/lib/test2`_ are allowed
 and encouraged to let their tests run at interpreter level although
-`pypy/lib/`_ modules eventually live at PyPy's application level.  
-This allows us to quickly test our python-coded reimplementations 
-against CPython.   
+`pypy/lib/`_ modules eventually live at PyPy's application level.
+This allows us to quickly test our python-coded reimplementations
+against CPython.
 
 .. _`pypy/lib/test2`: http://codespeak.net/svn/pypy/dist/pypy/lib/test2
 
 Testing modules in ``pypy/module``
 ----------------------------------
 
-Simply change to ``pypy/module`` or to a subdirectory and `run the 
-tests as usual`_. 
+Simply change to ``pypy/module`` or to a subdirectory and `run the
+tests as usual`_.
 
 
 Testing modules in ``lib-python``
 -----------------------------------
 
-In order to let CPython's regression tests run against PyPy 
-you can switch to the `lib-python/`_ directory and run 
-the testing tool in order to start compliance tests. 
-(XXX check windows compatibility for producing test reports). 
+In order to let CPython's regression tests run against PyPy
+you can switch to the `lib-python/`_ directory and run
+the testing tool in order to start compliance tests.
+(XXX check windows compatibility for producing test reports).
 
-Naming conventions and directory layout 
+Naming conventions and directory layout
 ===========================================
 
-Directory and File Naming 
+Directory and File Naming
 -------------------------
 
 - directories/modules/namespaces are always **lowercase**
 
 - never use plural names in directory and file names
 
-- ``__init__.py`` is usually empty except for 
-  ``pypy/objspace/*`` and ``pypy/module/*/__init__.py``. 
+- ``__init__.py`` is usually empty except for
+  ``pypy/objspace/*`` and ``pypy/module/*/__init__.py``.
 
 - don't use more than 4 directory nesting levels
 
-- keep filenames concise and completion-friendly. 
+- keep filenames concise and completion-friendly.
 
 Naming of python objects
 ------------------------
 
 - class names are **CamelCase**
 
-- functions/methods are lowercase and ``_`` separated  
+- functions/methods are lowercase and ``_`` separated
 
 - objectspace classes are spelled ``XyzObjSpace``. e.g.
 
@@ -736,25 +750,25 @@
 -----------------------------------------------------
 
 - write good log messages because several people
-  are reading the diffs. 
+  are reading the diffs.
 
 - if you add (text/py) files to the repository then please run
-  pypy/tool/fixeol in that directory.  This will make sure 
-  that the property 'svn:eol-style' is set to native which 
+  pypy/tool/fixeol in that directory.  This will make sure
+  that the property 'svn:eol-style' is set to native which
   allows checkin/checkout in native line-ending format.
 
 - branching (aka "svn copy") of source code should usually
   happen at ``svn/pypy/dist`` level in order to have a full
   self-contained pypy checkout for each branch.   For branching
-  a ``try1`` branch you would for example do:: 
+  a ``try1`` branch you would for example do::
 
     svn cp http://codespeak.net/svn/pypy/dist \
-           http://codespeak.net/svn/pypy/branch/try1 
+           http://codespeak.net/svn/pypy/branch/try1
 
-  This allows to checkout the ``try1`` branch and receive a 
-  self-contained working-copy for the branch.   Note that 
-  branching/copying is a cheap operation with subversion, as it 
-  takes constant time irrespective of the size of the tree. 
+  This allows to checkout the ``try1`` branch and receive a
+  self-contained working-copy for the branch.   Note that
+  branching/copying is a cheap operation with subversion, as it
+  takes constant time irrespective of the size of the tree.
 
 - To learn more about how to use subversion read `this document`_.
 
@@ -762,41 +776,41 @@
 
 
 
-.. _`using development tracker`: 
+.. _`using development tracker`:
 
 Using the development bug/feature tracker
 =========================================
 
-We have a `development tracker`_, based on Richard Jones' 
-`roundup`_ application.  You can file bugs, 
-feature requests or see what's going on 
-for the next milestone, both from an E-Mail and from a 
-web interface.   
+We have a `development tracker`_, based on Richard Jones'
+`roundup`_ application.  You can file bugs,
+feature requests or see what's going on
+for the next milestone, both from an E-Mail and from a
+web interface.
 
 use your codespeak login or register
------------------------------------- 
+------------------------------------
 
 If you already committed to the PyPy source code, chances
 are that you can simply use your codespeak login that
-you use for subversion or for shell access.   
+you use for subversion or for shell access.
 
 If you are not a commiter then you can still `register with
-the tracker`_ easily. 
+the tracker`_ easily.
 
 modifying Issues from svn commit messages
------------------------------------------ 
+-----------------------------------------
 
-If you are committing something related to  
-an issue in the development tracker you 
-can correlate your login message to a tracker 
-item by following these rules: 
+If you are committing something related to
+an issue in the development tracker you
+can correlate your login message to a tracker
+item by following these rules:
 
-- put the content of ``issueN STATUS`` on a single 
-  new line 
+- put the content of ``issueN STATUS`` on a single
+  new line
 
-- `N` must be an existing issue number from the `development tracker`_. 
+- `N` must be an existing issue number from the `development tracker`_.
 
-- STATUS is one of:: 
+- STATUS is one of::
 
     unread
     chatting
@@ -811,10 +825,10 @@
 .. _`roundup`: http://roundup.sf.net
 
 
-.. _`testing in PyPy`: 
+.. _`testing in PyPy`:
 
 Testing in PyPy
-=============== 
+===============
 
 Our tests are based on the new `py.test`_ tool which lets you write
 unittests without boilerplate.  All tests of modules
@@ -829,55 +843,55 @@
 
 Both types of tests need an `objectspace`_ they can run with (the interpreter
 dispatches operations on objects to an objectspace).  If you run a test you
-can usually give the '-o' switch to select an object space.  E.g. '-o thunk' 
-will select the thunk object space. The default is the `Standard Object Space`_ 
-which aims to implement unmodified Python semantics. 
+can usually give the '-o' switch to select an object space.  E.g. '-o thunk'
+will select the thunk object space. The default is the `Standard Object Space`_
+which aims to implement unmodified Python semantics.
 
 .. _`standard object space`: objspace.html#standard-object-space
-.. _`objectspace`: architecture.html#objectspace 
-.. _`py.test`: http://codespeak.net/py/current/doc/test.html 
+.. _`objectspace`: architecture.html#objectspace
+.. _`py.test`: http://codespeak.net/py/current/doc/test.html
+
+Interpreter level tests
+-----------------------
 
-Interpreter level tests 
------------------------ 
+You can write test functions and methods like this::
 
-You can write test functions and methods like this:: 
+    def test_something(space):
+        # use space ...
 
-    def test_something(space): 
-        # use space ... 
-        
-    class TestSomething: 
-        def test_some(self): 
-            # use 'self.space' here 
+    class TestSomething:
+        def test_some(self):
+            # use 'self.space' here
 
 Note that the prefix `test` for test functions and `Test` for test
 classes is mandatory.  In both cases you can import Python modules at
 module global level and use plain 'assert' statements thanks to the
-usage of the `py.test`_ tool.  
+usage of the `py.test`_ tool.
 
-Application Level tests 
------------------------ 
+Application Level tests
+-----------------------
 
 For testing the conformance and well-behavedness of PyPy it
-is often sufficient to write "normal" application-level 
+is often sufficient to write "normal" application-level
 Python code that doesn't need to be aware of any particular
 coding style or restrictions.  If we have a choice we often
 use application level tests which usually look like this::
 
     def app_test_something():
-        # application level test code 
+        # application level test code
 
-    class AppTestSomething: 
-        def test_this(self): 
-            # application level test code 
+    class AppTestSomething:
+        def test_this(self):
+            # application level test code
 
 These application level test functions will run on top
-of PyPy, i.e. they have no access to interpreter details. 
+of PyPy, i.e. they have no access to interpreter details.
 You cannot use imported modules from global level because
 they are imported at interpreter-level while you test code
 runs at application level. If you need to use modules
-you have to import them within the test function. 
+you have to import them within the test function.
 
-.. _`run the tests as usual`: 
+.. _`run the tests as usual`:
 
 Command line tool test_all
 --------------------------
@@ -886,65 +900,65 @@
 
   python test_all.py
 
-which is a synonym for the general `py.test`_ utility 
-located in the ``pypy`` directory.  For switches to 
-modify test execution pass the ``-h`` option. 
+which is a synonym for the general `py.test`_ utility
+located in the ``pypy`` directory.  For switches to
+modify test execution pass the ``-h`` option.
 
 Test conventions
 ----------------
 
 - adding features requires adding appropriate tests.  (It often even
   makes sense to first write the tests so that you are sure that they
-  actually can fail.) 
+  actually can fail.)
 
-- All over the pypy source code there are test/ directories 
+- All over the pypy source code there are test/ directories
   which contain unittests.  Such scripts can usually be executed
-  directly or are collectively run by pypy/test_all.py 
+  directly or are collectively run by pypy/test_all.py
 
 - each test directory needs a copy of pypy/tool/autopath.py which
   upon import will make sure that sys.path contains the directory
-  where 'pypy' is in. 
+  where 'pypy' is in.
 
-.. _`change documentation and website`: 
+.. _`change documentation and website`:
 
-Changing documentation and website 
-================================== 
+Changing documentation and website
+==================================
 
-documentation/website files in your local checkout 
+documentation/website files in your local checkout
 ---------------------------------------------------
 
-Most of the PyPy's documentation and website is kept in 
-`pypy/documentation` and `pypy/documentation/website` respectively. 
-You can simply edit or add '.txt' files which contain ReST-markuped 
+Most of the PyPy's documentation and website is kept in
+`pypy/documentation` and `pypy/documentation/website` respectively.
+You can simply edit or add '.txt' files which contain ReST-markuped
 files.  Here is a `ReST quickstart`_ but you can also just look
-at the existing documentation and see how things work. 
+at the existing documentation and see how things work.
 
 .. _`ReST quickstart`: http://docutils.sourceforge.net/docs/rst/quickref.html
 
 Automatically test documentation/website changes
 ------------------------------------------------
 
-.. _`docutils home page`: 
-.. _`docutils`: http://docutils.sourceforge.net/ 
+.. _`docutils home page`:
+.. _`docutils`: http://docutils.sourceforge.net/
 
-We automatically check referential integrity and ReST-conformance.  In order to 
-run the tests you need docutils_ installed.  Then go to the local checkout 
-of the documentation directory and run the tests:: 
+We automatically check referential integrity and ReST-conformance.  In order to
+run the tests you need docutils_ installed.  Then go to the local checkout
+of the documentation directory and run the tests::
 
-    cd .../pypy/documentation 
-    python ../test_all.py 
+    cd .../pypy/documentation
+    python ../test_all.py
 
-If you see no failures chances are high that your modifications at least 
+If you see no failures chances are high that your modifications at least
 don't produce ReST-errors or wrong local references.  A side effect of running
-the tests is that you have `.html` files in the documentation directory 
-which you can point your browser to! 
+the tests is that you have `.html` files in the documentation directory
+which you can point your browser to!
 
-Additionally, if you also want to check for remote references inside 
-the documentation issue:: 
+Additionally, if you also want to check for remote references inside
+the documentation issue::
 
-    python ../test_all.py --checkremote 
+    python ../test_all.py --checkremote
 
-which will check that remote URLs are reachable.  
+which will check that remote URLs are reachable.
 
 
 .. include:: _ref.txt

Modified: pypy/branch/pycompiler/documentation/contributor.txt
==============================================================================
--- pypy/branch/pycompiler/documentation/contributor.txt	(original)
+++ pypy/branch/pycompiler/documentation/contributor.txt	Fri Jul  1 18:30:34 2005
@@ -1,10 +1,10 @@
 
-Contributors to PyPy 
-==================== 
+Contributors to PyPy
+====================
 
-Here is a list of developers who have committed to the PyPy source 
-code base, ordered by number of commits (which is certainly not a very 
-appropriate measure but it's something):: 
+Here is a list of developers who have committed to the PyPy source
+code base, ordered by number of commits (which is certainly not a very
+appropriate measure but it's something)::
 
     Armin Rigo
     Samuele Pedroni

Modified: pypy/branch/pycompiler/documentation/faq.txt
==============================================================================
--- pypy/branch/pycompiler/documentation/faq.txt	(original)
+++ pypy/branch/pycompiler/documentation/faq.txt	Fri Jul  1 18:30:34 2005
@@ -1,13 +1,12 @@
 
-Frequently Asked Questions 
-========================== 
+Frequently Asked Questions
+==========================
 
-How fast is PyPy?   
+How fast is PyPy?
 
     As of June 2005, PyPy still runs on top of CPython and thus
-    is slower by a factor of 2000 compared to CPython.  We don't 
+    is slower by a factor of 2000 compared to CPython.  We don't
     know yet how fast it will be once we complete our translation
-    efforts, aimed at a first static self-contained low-level 
-    translated version. 
-    
+    efforts, aimed at a first static self-contained low-level
+    translated version.
 

Modified: pypy/branch/pycompiler/documentation/misc.txt
==============================================================================
--- pypy/branch/pycompiler/documentation/misc.txt	(original)
+++ pypy/branch/pycompiler/documentation/misc.txt	Fri Jul  1 18:30:34 2005
@@ -138,7 +138,7 @@
 
 _codecsmodule
 
-_csv - already exists?
+_csv - already exists? See http://python-dsv.sourceforge.net/
 
 _heapqmodule - already exists
 

Modified: pypy/branch/pycompiler/documentation/objspace.txt
==============================================================================
--- pypy/branch/pycompiler/documentation/objspace.txt	(original)
+++ pypy/branch/pycompiler/documentation/objspace.txt	Fri Jul  1 18:30:34 2005
@@ -354,7 +354,7 @@
     :args:    list of arguments.  Each one is a Constant or a Variable seen previously in the basic block.
     :result:  a *new* Variable into which the result is to be stored.
 
-    Note that operations usually cannot implicitely raise exceptions at run-time; so for example, code generators can assume that a ``getitem`` operation on a list is safe and can be performed without bound checking.  The exceptions to this rule are: (1) if the operation is the last in the block, which ends with ``exitswitch == Constant(last_exception)``, then the implicit exceptions must be checked for, generated, and caught appropriately; (2) calls to other functions, as per ``simple_call`` or ``call_args``, can always raise whatever the called function can raise --- and such exceptions must be passed through to the parent unless they are caught as above.
+    Note that operations usually cannot implicitly raise exceptions at run-time; so for example, code generators can assume that a ``getitem`` operation on a list is safe and can be performed without bound checking.  The exceptions to this rule are: (1) if the operation is the last in the block, which ends with ``exitswitch == Constant(last_exception)``, then the implicit exceptions must be checked for, generated, and caught appropriately; (2) calls to other functions, as per ``simple_call`` or ``call_args``, can always raise whatever the called function can raise --- and such exceptions must be passed through to the parent unless they are caught as above.
 
 
 Variable

Modified: pypy/branch/pycompiler/documentation/svn-help.txt
==============================================================================
--- pypy/branch/pycompiler/documentation/svn-help.txt	(original)
+++ pypy/branch/pycompiler/documentation/svn-help.txt	Fri Jul  1 18:30:34 2005
@@ -1,9 +1,9 @@
 
-Installing subversion for PyPy 
-============================== 
+Installing subversion for PyPy
+==============================
 
-Jens-Uwe Mager has prepared some installation files which should 
-help you to install subversion on your computer. 
+Jens-Uwe Mager has prepared some installation files which should
+help you to install subversion on your computer.
 
 + Download Unix source tarball or prepackaged versions_ for MacOS, Windows, FreeBSD and Linux
 
@@ -12,7 +12,7 @@
   *  See Microsoft website_ if you have .DLL issues.
 
   *  Windows Installer file for Tortoise SVN (like Tortoise CVS) GUI_
-     (Pick the UNICODE version for Windows 2000 and XP and 
+     (Pick the UNICODE version for Windows 2000 and XP and
      see Win_ 2000, NT if you have problems loading it.)
 
 + Local copy of MacOS_ X binary tar ball
@@ -28,7 +28,7 @@
 
 **Download and install the appropriate installation file of subversion above.**
 
-For linux: 
+For linux:
 
 download the tarball.  unzip and untar it.  Then type *./configure*.  Then, as root, *make* followed by *make install*.  Voilà ... a subversion client.
 
@@ -87,7 +87,7 @@
  Transmitting file data .
  Committed revision 631.
 
-Check online on the `svn-commit archives`_ and you'll see your revision. Feel free to add a documentation file on any major changes you've made!  
+Check online on the `svn-commit archives`_ and you'll see your revision. Feel free to add a documentation file on any major changes you've made!
 
 .. _`svn-commit archives`: http://codespeak.net/pipermail/pypy-svn/
 
@@ -158,4 +158,4 @@
 .. _guide: http://svnbook.red-bean.com/book.html#svn-ch-1
 .. _backports: http://www.backports.org
 .. _online: http://codespeak.net/svn/pypy/dist/
-.. _coding-guide: coding-guide.html 
+.. _coding-guide: coding-guide.html

Modified: pypy/branch/pycompiler/documentation/translation.txt
==============================================================================
--- pypy/branch/pycompiler/documentation/translation.txt	(original)
+++ pypy/branch/pycompiler/documentation/translation.txt	Fri Jul  1 18:30:34 2005
@@ -24,12 +24,12 @@
 Here are the steps we follow to translate a given program:
 
 1. The complete program is imported.  If needed, extra initialization is
-   performed.  Once this is done, the program must be present in memory is
+   performed.  Once this is done, the program must be present in memory as
    a form that is "static enough" in the sense of RPython_.
 
 2. The `Flow Object Space`_ processes the input program, turning each
    function independently into a `control flow graph`_ data structure
-   recording sequences of basic operations in 
+   recording sequences of basic operations in
    static single assignment form `SSA`_.
 
 3. Optionally, the Annotator_ performs global type inference on the
@@ -67,56 +67,56 @@
 
 (INCOMPLETE DRAFT)
 
-We describe below how a control flow graph can be "annotated" to 
-discover the types of the objects.  This annotation pass is a form of 
-type inference.  It is done after control flow graphs are built by the 
-FlowObjSpace, but before these graphs are translated into low-level code 
+We describe below how a control flow graph can be "annotated" to
+discover the types of the objects.  This annotation pass is a form of
+type inference.  It is done after control flow graphs are built by the
+FlowObjSpace, but before these graphs are translated into low-level code
 (e.g. C/Lisp/Pyrex).
 
 
 Model
 ------------------------
 
-The major goal of the annotator is to "annotate" each variable that 
-appears in a flow graph.  An "annotation" describes all the possible 
-Python objects that this variable could contain at run-time, based on a 
+The major goal of the annotator is to "annotate" each variable that
+appears in a flow graph.  An "annotation" describes all the possible
+Python objects that this variable could contain at run-time, based on a
 whole-program analysis of all the flow graphs --- one per function.
 
-An "annotation" is an instance of ``SomeObject``.  There are subclasses 
-that are meant to represent specific families of objects.  Note that 
-these classes are all meant to be instantiated; the classes ``SomeXxx`` 
+An "annotation" is an instance of ``SomeObject``.  There are subclasses
+that are meant to represent specific families of objects.  Note that
+these classes are all meant to be instantiated; the classes ``SomeXxx``
 themselves are not the annotations.
 
 Here is an overview (see ``pypy.annotation.model``):
 
-* ``SomeObject`` is the base class.  An instance ``SomeObject()`` 
-  represents any Python object.  It is used for the case where we don't 
-  have enough information to be more precise.  In practice, the presence 
-  of ``SomeObject()`` means that we have to make the annotated source code 
+* ``SomeObject`` is the base class.  An instance ``SomeObject()``
+  represents any Python object.  It is used for the case where we don't
+  have enough information to be more precise.  In practice, the presence
+  of ``SomeObject()`` means that we have to make the annotated source code
   simpler or the annotator smarter.
 
-* ``SomeInteger()`` represents any integer.  
+* ``SomeInteger()`` represents any integer.
   ``SomeInteger(nonneg=True)`` represent a non-negative integer (``>=0``).
 
-* ``SomeString()`` represents any string; ``SomeChar()`` a string of 
+* ``SomeString()`` represents any string; ``SomeChar()`` a string of
   length 1.
 
-* ``SomeTuple([s1,s2,..,sn])`` represents a tuple of length ``n``.  The 
-  elements in this tuple are themselves constrained by the given list of 
-  annotations.  For example, ``SomeTuple([SomeInteger(), SomeString()])`` 
+* ``SomeTuple([s1,s2,..,sn])`` represents a tuple of length ``n``.  The
+  elements in this tuple are themselves constrained by the given list of
+  annotations.  For example, ``SomeTuple([SomeInteger(), SomeString()])``
   represents a tuple with two items: an integer and a string.
 
-There are more complex subclasses of ``SomeObject`` that we describe in 
+There are more complex subclasses of ``SomeObject`` that we describe in
 more details below.
 
-All the ``SomeXxx`` instances can optionally have a ``const`` attribute, 
-which means that we know exactly which Python object the Variable will 
+All the ``SomeXxx`` instances can optionally have a ``const`` attribute,
+which means that we know exactly which Python object the Variable will
 contain.
 
-All the ``SomeXxx`` instances are supposed to be immutable.  The 
-annotator manages a dictionary mapping Variables (which appear in flow 
-graphs) to ``SomeXxx`` instances; if it needs to revise its belief about 
-what a Variable can contain, it does so by updating this dictionary, not 
+All the ``SomeXxx`` instances are supposed to be immutable.  The
+annotator manages a dictionary mapping Variables (which appear in flow
+graphs) to ``SomeXxx`` instances; if it needs to revise its belief about
+what a Variable can contain, it does so by updating this dictionary, not
 the ``SomeXxx`` instance.
 
 
@@ -124,18 +124,18 @@
 Annotator
 --------------------------
 
-The annotator itself (``pypy.translator.annrpython``) works by 
-propagating the annotations forward in the flow graphs, starting at some 
-entry point function, possibly with explicitely provided annotations 
-about the entry point's input arguments.  It considers each operation in 
-the flow graph in turn.  Each operation takes a few input arguments 
-(Variables and Constants) and produce a single result (a Variable).  
-Depending on the input argument's annotations, an annotation about the 
-operation result is produced.  The exact rules to do this are provided 
-by the whole ``pypy.annotation`` subdirectory, which defines all the 
-cases in detail according to the R-Python semantics.  For example, if 
-the operation is 'v3=add(v1,v2)' and the Variables v1 and v2 are 
-annotated with ``SomeInteger()``, then v3 also receives the annotation 
+The annotator itself (``pypy.translator.annrpython``) works by
+propagating the annotations forward in the flow graphs, starting at some
+entry point function, possibly with explicitely provided annotations
+about the entry point's input arguments.  It considers each operation in
+the flow graph in turn.  Each operation takes a few input arguments
+(Variables and Constants) and produce a single result (a Variable).
+Depending on the input argument's annotations, an annotation about the
+operation result is produced.  The exact rules to do this are provided
+by the whole ``pypy.annotation`` subdirectory, which defines all the
+cases in detail according to the R-Python semantics.  For example, if
+the operation is 'v3=add(v1,v2)' and the Variables v1 and v2 are
+annotated with ``SomeInteger()``, then v3 also receives the annotation
 ``SomeInteger()``.  So for example the function::
 
     def f(n):
@@ -145,22 +145,22 @@
 
     start ----------.
                     |
-                    V 
+                    V
            +-------------------+
            |  v2 = add(v1, 1)  |
            +-------------------+
                     |
                     `---> return block
 
-If the annotator is told that v1 is ``SomeInteger()``, then it will 
-deduce that v2 (and hence the function's return value) is 
+If the annotator is told that v1 is ``SomeInteger()``, then it will
+deduce that v2 (and hence the function's return value) is
 ``SomeInteger()``.
 
 .. _above:
 
-This step-by-step annotation phase proceeds through all the operations 
-in a block, and then along the links between the blocks of the flow 
-graph.  If there are loops in the flow graph, then the links will close 
+This step-by-step annotation phase proceeds through all the operations
+in a block, and then along the links between the blocks of the flow
+graph.  If there are loops in the flow graph, then the links will close
 back to already-seen blocks, as in::
 
     def g(n):
@@ -189,60 +189,60 @@
                     |  m3 = sub(n3, 1)   |---'
                     +--------------------+
 
-Be sure to follow the variable renaming that occurs systematically 
-across each link in a flow graph.  In the above example the Variables 
-have been given names similar to the name of the original variables in 
-the source code (the FlowObjSpace tries to do this too) but keep in mind 
+Be sure to follow the variable renaming that occurs systematically
+across each link in a flow graph.  In the above example the Variables
+have been given names similar to the name of the original variables in
+the source code (the FlowObjSpace tries to do this too) but keep in mind
 that all Variables are different: n1, n2, i2, v2, n3, i3, j3, m3.
 
-Assume that we call the annotator with an input annotation of 
-``SomeInteger()`` for n1.  Following the links from the start, the 
-annotator will first believe that the Variable i2, whose value comes 
-from the constant 0 of the first link, must always be zero.  It will 
-thus use the annotation ``SomeInteger(const=0)`` for i2.  Then it will 
-propagate the annotations through both blocks, and find that v2 is 
-``SomeBool()`` and all other variables are ``SomeInteger()``.  In 
-particular, the annotation of j3 is different from the annotation of the 
-Variable i2 into which it is copied (via the back-link).  More 
-precisely, j3 is ``SomeInteger()`` but i2 is the more specific 
-``SomeInteger(const=0)``.  This means that the assumption that i2 must 
-always be zero is found to be wrong.  At this point, the annotation of 
-i2 is *generalized* to include both the existing and the new annotation.  
-(This is the purpose of ``pypy.annotation.model.unionof()``).  Then 
+Assume that we call the annotator with an input annotation of
+``SomeInteger()`` for n1.  Following the links from the start, the
+annotator will first believe that the Variable i2, whose value comes
+from the constant 0 of the first link, must always be zero.  It will
+thus use the annotation ``SomeInteger(const=0)`` for i2.  Then it will
+propagate the annotations through both blocks, and find that v2 is
+``SomeBool()`` and all other variables are ``SomeInteger()``.  In
+particular, the annotation of j3 is different from the annotation of the
+Variable i2 into which it is copied (via the back-link).  More
+precisely, j3 is ``SomeInteger()`` but i2 is the more specific
+``SomeInteger(const=0)``.  This means that the assumption that i2 must
+always be zero is found to be wrong.  At this point, the annotation of
+i2 is *generalized* to include both the existing and the new annotation.
+(This is the purpose of ``pypy.annotation.model.unionof()``).  Then
 these more general annotations must again be propagated forward.
 
-This process of successive generalizations continues until the 
-annotations stabilize.  In the above example, it is sufficient to 
-re-analyse the first block once, but in general it can take several 
-iterations to reach a fixpoint.  Annotations may also be propagated from 
-one flow graph to another and back repeatedly, across ``call`` 
-operations.  The overall model should ensure that this process 
-eventually terminates under reasonable conditions.  Note that as long as 
-the process is not finished, the annotations given to the Variables are 
-wrong, in the sense that they are too specific; at run-time, the 
-Variables will possibly contain Python objects outside the set defined 
+This process of successive generalizations continues until the
+annotations stabilize.  In the above example, it is sufficient to
+re-analyse the first block once, but in general it can take several
+iterations to reach a fixpoint.  Annotations may also be propagated from
+one flow graph to another and back repeatedly, across ``call``
+operations.  The overall model should ensure that this process
+eventually terminates under reasonable conditions.  Note that as long as
+the process is not finished, the annotations given to the Variables are
+wrong, in the sense that they are too specific; at run-time, the
+Variables will possibly contain Python objects outside the set defined
 by the annotation, and the annotator doesn't know it yet.
 
 
 Description of the available types
 -----------------------------------------------
 
-The reference and the details for the annotation model is found in the 
-module ``pypy.annotation.model``.  We describe below the issues related 
+The reference and the details for the annotation model is found in the
+module ``pypy.annotation.model``.  We describe below the issues related
 to the various kinds of annotations.
 
 
 Simple Types
 ++++++++++++
 
-``SomeInteger``, ``SomeBool``, ``SomeString``, ``SomeChar`` all stands 
+``SomeInteger``, ``SomeBool``, ``SomeString``, ``SomeChar`` all stands
 for the obvious corresponding set of immutable Python objects.
 
 
 Tuples
 ++++++
 
-``SomeTuple`` only considers tuples of known length.  We don't try to 
+``SomeTuple`` only considers tuples of known length.  We don't try to
 handle tuples of varying length (the program should use lists instead).
 
 
@@ -337,46 +337,46 @@
 User-defined Classes and Instances
 ++++++++++++++++++++++++++++++++++
 
-``SomeInstance`` stands for an instance of the given class or any 
-subclass of it.  For each user-defined class seen by the annotator, we 
-maintain a ClassDef (``pypy.annotation.classdef``) describing the 
-attributes of the instances of the class; essentially, a ClassDef gives 
-the set of all class-level and instance-level attributes, and for each 
+``SomeInstance`` stands for an instance of the given class or any
+subclass of it.  For each user-defined class seen by the annotator, we
+maintain a ClassDef (``pypy.annotation.classdef``) describing the
+attributes of the instances of the class; essentially, a ClassDef gives
+the set of all class-level and instance-level attributes, and for each
 one, a corresponding ``SomeXxx`` annotation.
 
-Instance-level attributes are discovered progressively as the annotation 
+Instance-level attributes are discovered progressively as the annotation
 progresses.  Assignments like::
 
    inst.attr = value
 
-update the ClassDef of the given instance to record that the given 
+update the ClassDef of the given instance to record that the given
 attribute exists and can be as general as the given value.
 
-For every attribute, the ClassDef also records all the positions where 
-the attribute is *read*.  If, at some later time, we discover an 
-assignment that forces the annotation about the attribute to be 
-generalized, then all the places that read the attribute so far are 
-marked as invalid and the annotator will have to restart its analysis 
+For every attribute, the ClassDef also records all the positions where
+the attribute is *read*.  If, at some later time, we discover an
+assignment that forces the annotation about the attribute to be
+generalized, then all the places that read the attribute so far are
+marked as invalid and the annotator will have to restart its analysis
 from there.
 
-The distinction between instance-level and class-level attributes is 
-thin; class-level attributes are essentially considered as initial 
-values for instance-level attributes.  Methods are not special in this 
-respect, expect that they are bound to the instance (i.e. ``self = 
-SomeInstance(cls)``) when considered as the initial value for the 
+The distinction between instance-level and class-level attributes is
+thin; class-level attributes are essentially considered as initial
+values for instance-level attributes.  Methods are not special in this
+respect, except that they are bound to the instance (i.e. ``self =
+SomeInstance(cls)``) when considered as the initial value for the
 instance.
 
-The inheritance rules are as follows: the union of two ``SomeInstance`` 
-annotations is the ``SomeInstance`` of the most precise common base 
-class.  If an attribute is considered (i.e. read or written) through a 
-``SomeInstance`` of a parent class, then we assume that all subclasses 
-also have the same attribute, and that the same annotation applies to 
-them all (so code like ``return self.x`` in a method of a parent class 
-forces the parent class and all its subclasses to have an attribute 
-``x``, whose annotation is general enough to contain all the values that 
-all the subclasses might want to store in ``x``).  However, distinct 
-subclasses can have attributes of the same names with different, 
-unrelated annotations if they are not used in a general way through the 
+The inheritance rules are as follows: the union of two ``SomeInstance``
+annotations is the ``SomeInstance`` of the most precise common base
+class.  If an attribute is considered (i.e. read or written) through a
+``SomeInstance`` of a parent class, then we assume that all subclasses
+also have the same attribute, and that the same annotation applies to
+them all (so code like ``return self.x`` in a method of a parent class
+forces the parent class and all its subclasses to have an attribute
+``x``, whose annotation is general enough to contain all the values that
+all the subclasses might want to store in ``x``).  However, distinct
+subclasses can have attributes of the same names with different,
+unrelated annotations if they are not used in a general way through the
 parent class.
 
 
@@ -443,9 +443,25 @@
 Overview
 --------
 
-The RPython Typer is the bridge between the Annotator_ and the low-level code generators.  The annotator computes types (or "annotations") that are high-level, in the sense that they describe RPython types like lists or instances of user-defined classes.  In general, though, to emit code we need to represent these high-level annotations into the low-level model of the target language; for C, this means structures and pointers and arrays.  The Typer both determines the appropriate low-level type for each annotation, and tries to replace *all* operations in the control flow graphs with one or a few low-level operations.  Just like low-level types, there is only a fairly restricted set of low-level operations, along the lines of reading or writing from or to a field of a structure.
-
-In theory, this step is optional; some code generators might be able to read directly the high-level types.  However, we expect that case to be the exception.  "Compiling" high-level types into low-level ones is rather more messy than one would expect.  This was the motivation for making this step explicit and isolated in a single place.  After Typing, the graphs can only contain very few operations, which makes the job of the code generators much simpler.
+The RPython Typer is the bridge between the Annotator_ and the low-level code
+generators.  The annotator computes types (or "annotations") that are
+high-level, in the sense that they describe RPython types like lists or
+instances of user-defined classes.  In general, though, to emit code we need
+to represent these high-level annotations into the low-level model of the
+target language; for C, this means structures and pointers and arrays.  The
+Typer both determines the appropriate low-level type for each annotation, and
+tries to replace *all* operations in the control flow graphs with one or a few
+low-level operations.  Just like low-level types, there is only a fairly
+restricted set of low-level operations, along the lines of reading or writing
+from or to a field of a structure.
+
+In theory, this step is optional; some code generators might be able to read
+directly the high-level types.  However, we expect that case to be the
+exception.  "Compiling" high-level types into low-level ones is rather more
+messy than one would expect.  This was the motivation for making this step
+explicit and isolated in a single place.  After Typing, the graphs can only
+contain very few operations, which makes the job of the code generators much
+simpler.
 
 
 Example: Integer operations
@@ -465,33 +481,78 @@
 
     v3 = int_add(v1, v2)
 
-where -- in C notation -- all three variables v1, v2 and v3 are typed ``int``.  This is done by attaching an attribute ``concretetype`` to v1, v2 and v3 (which might be instances of Variable or possibly Constant).  In our model, this ``concretetype`` is ``pypy.rpython.lltype.Signed``.  Of course, the purpose of replacing the operation called ``add`` with ``int_add`` is that code generators no longer have to worry about what kind of addition (or concatenation maybe?) it means.
+where -- in C notation -- all three variables v1, v2 and v3 are typed ``int``.
+This is done by attaching an attribute ``concretetype`` to v1, v2 and v3
+(which might be instances of Variable or possibly Constant).  In our model,
+this ``concretetype`` is ``pypy.rpython.lltype.Signed``.  Of course, the
+purpose of replacing the operation called ``add`` with ``int_add`` is that
+code generators no longer have to worry about what kind of addition (or
+concatenation maybe?) it means.
 
 
 The process in more details
 ---------------------------
 
-The RPython Typer has a structure similar to that of the Annotator_: both consider each block of the flow graphs in turn, and perform some analysis on each operation.  In both cases the analysis of an operation depends on the annotations of its input arguments.  This is reflected in the usage of the same ``__extend__`` syntax in the source files (compare e.g. `annotation/binaryop.py`_ and `rpython/rint.py`_).
-
-The analogy stops here, though: while it runs, the Annotator is in the middle of computing the annotations, so it might need to reflow and generalize until a fixpoint is reached.  The Typer, by contrast, works on the final annotations that the Annotator computed, without changing them, assuming that they are globally consistent.  There is no need to reflow: the Typer considers each block only once.  And unlike the Annotator, the Typer completely modifies the flow graph, by replacing each operation with some low-level operations.
-
-In addition to replacing operations, the RTyper creates a ``concretetype`` attribute on all Variables and Constants in the flow graphs, which tells code generators which type to use for each of them.  This attribute is a `low-level type`_, as described below.
+The RPython Typer has a structure similar to that of the Annotator_: both
+consider each block of the flow graphs in turn, and perform some analysis on
+each operation.  In both cases the analysis of an operation depends on the
+annotations of its input arguments.  This is reflected in the usage of the same
+``__extend__`` syntax in the source files (compare e.g.
+`annotation/binaryop.py`_ and `rpython/rint.py`_).
+
+The analogy stops here, though: while it runs, the Annotator is in the middle
+of computing the annotations, so it might need to reflow and generalize until
+a fixpoint is reached.  The Typer, by contrast, works on the final annotations
+that the Annotator computed, without changing them, assuming that they are
+globally consistent.  There is no need to reflow: the Typer considers each
+block only once.  And unlike the Annotator, the Typer completely modifies the
+flow graph, by replacing each operation with some low-level operations.
+
+In addition to replacing operations, the RTyper creates a ``concretetype``
+attribute on all Variables and Constants in the flow graphs, which tells code
+generators which type to use for each of them.  This attribute is a
+`low-level type`_, as described below.
 
 
 Representations
 ---------------
 
-Representations -- the Repr classes -- are the most important internal classes used by the RTyper.  (They are internal in the sense that they are an "implementation detail" and their instances just go away after the RTyper is finished; the code generators should only use the ``concretetype`` attributes, which are not Repr instances but `low-level types`_.)
-
-A representation contains all the logic about mapping a specific SomeXxx() annotation to a specific low-level type.  For the time being, the RTyper assumes that each SomeXxx() instance needs only one "canonical" representation.  For example, all variables annotated with SomeInteger() will correspond to the ``Signed`` low-level type via the ``IntegerRepr`` representation.  More subtly, variables annotated SomeList() can correspond either to a structure holding an array of items of the correct type, or -- if the list in question is just a range() with a constant step -- a structure with just start and stop fields.
-
-This example shows that two representations may need very different low-level implementations for the same high-level operations.  This is the reason for turning representations into explicit objects.
-
-The base Repr class is defined in `rpython/rmodel.py`_.  Most of the ``rpython/r*.py`` files define one or a few subclasses of Repr.  The method getrepr() of the RTyper will build and cache a single Repr instance per SomeXxx() instance; moreover, two SomeXxx() instances that are equal get the same Repr instance.
-
-The key attribute of a Repr instance is called ``lowleveltype``, which is what gets copied into the attribute ``concretetype`` of the Variables that have been given this representation.  The RTyper also computes a ``concretetype`` for Constants, to match the way they are used in the low-level operations (for example, ``int_add(x, 1)`` requires a ``Constant(1)`` with ``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a ``Constant(1)`` that must actually be a PyObject at run-time).
-
-In addition to ``lowleveltype``, each Repr subclass provides a set of methods called ``rtype_op_xxx()`` which define how each high-level operation ``op_xxx`` is turned into low-level operations.
+Representations -- the Repr classes -- are the most important internal classes
+used by the RTyper.  (They are internal in the sense that they are an
+"implementation detail" and their instances just go away after the RTyper is
+finished; the code generators should only use the ``concretetype`` attributes,
+which are not Repr instances but `low-level types`_.)
+
+A representation contains all the logic about mapping a specific SomeXxx()
+annotation to a specific low-level type.  For the time being, the RTyper
+assumes that each SomeXxx() instance needs only one "canonical" representation.
+For example, all variables annotated with SomeInteger() will correspond to the
+``Signed`` low-level type via the ``IntegerRepr`` representation.  More subtly,
+variables annotated SomeList() can correspond either to a structure holding an
+array of items of the correct type, or -- if the list in question is just a
+range() with a constant step -- a structure with just start and stop fields.
+
+This example shows that two representations may need very different low-level
+implementations for the same high-level operations.  This is the reason for
+turning representations into explicit objects.
+
+The base Repr class is defined in `rpython/rmodel.py`_.  Most of the
+``rpython/r*.py`` files define one or a few subclasses of Repr.  The method
+getrepr() of the RTyper will build and cache a single Repr instance per
+SomeXxx() instance; moreover, two SomeXxx() instances that are equal get the
+same Repr instance.
+
+The key attribute of a Repr instance is called ``lowleveltype``, which is what
+gets copied into the attribute ``concretetype`` of the Variables that have been
+given this representation.  The RTyper also computes a ``concretetype`` for
+Constants, to match the way they are used in the low-level operations (for
+example, ``int_add(x, 1)`` requires a ``Constant(1)`` with
+``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a
+``Constant(1)`` that must actually be a PyObject at run-time).
+
+In addition to ``lowleveltype``, each Repr subclass provides a set of methods
+called ``rtype_op_xxx()`` which define how each high-level operation ``op_xxx``
+is turned into low-level operations.
 
 
 .. _`low-level type`:
@@ -499,17 +560,30 @@
 Low-Level Types
 ---------------
 
-The RPython Typer uses a standard low-level model which we believe can correspond rather directly to various target languages from C to LLVM to Java.  This model is implemented in the first part of `rpython/lltype.py`_.
-
-The second part of `rpython/lltype.py`_ is a runnable implementation of these types, for testing purposes.  It allows us to write and test plain Python code using a malloc() function to obtain and manipulate structures and arrays.  This is useful for example to implement and test RPython types like 'list' with its operations and methods.
-
-The basic assumption is that Variables (i.e. local variables and function arguments and return value) all contain "simple" values: basically, just integers or pointers.  All the "container" data structures (struct and array) are allocated in the heap, and they are always manipulated via pointers.  (There is no equivalent to the C notion of local variable of a ``struct`` type.)
-
-Here is a quick tour (NOTE: this is up-to-date with the Subversion head.  If you have some older version, the ``lltype`` module might be called ``lltypes`` and you may need to add or remove a few ``Gc`` prefixes here and there)::
+The RPython Typer uses a standard low-level model which we believe can
+correspond rather directly to various target languages from C to LLVM to Java.
+This model is implemented in the first part of `rpython/lltype.py`_.
+
+The second part of `rpython/lltype.py`_ is a runnable implementation of these
+types, for testing purposes.  It allows us to write and test plain Python code
+using a malloc() function to obtain and manipulate structures and arrays.
+This is useful for example to implement and test RPython types like 'list' with
+its operations and methods.
+
+The basic assumption is that Variables (i.e. local variables and function
+arguments and return value) all contain "simple" values: basically, just
+integers or pointers.  All the "container" data structures (struct and array)
+are allocated in the heap, and they are always manipulated via pointers.
+(There is no equivalent to the C notion of local variable of a ``struct`` type.)
+
+Here is a quick tour (NOTE: this is up-to-date with the Subversion head.  If you
+have some older version, the ``lltype`` module might be called ``lltypes`` and
+you may need to add or remove a few ``Gc`` prefixes here and there)::
 
     >>> from pypy.rpython.lltype import *
 
-Here are a few primitive low-level types, and the typeOf() function to figure them out::
+Here are a few primitive low-level types, and the typeOf() function to figure
+them out::
 
     >>> Signed
     <Signed>
@@ -520,15 +594,20 @@
     >>> typeOf('x')
     <Char>
 
-Let's say that we want to build a type "point", which is a structure with two integer fields "x" and "y"::
+Let's say that we want to build a type "point", which is a structure with two
+integer fields "x" and "y"::
 
     >>> POINT = GcStruct('point', ('x', Signed), ('y', Signed))
     >>> POINT
     <GcStruct point { x: Signed, y: Signed }>
 
-The structure is a ``GcStruct``, which means a structure that can be allocated in the heap and eventually freed by some garbage collector.  (For platforms where we use reference counting, think about ``GcStruct`` as a struct with an additional reference counter field.)
+The structure is a ``GcStruct``, which means a structure that can be allocated
+in the heap and eventually freed by some garbage collector.  (For platforms
+where we use reference counting, think about ``GcStruct`` as a struct with an
+additional reference counter field.)
 
-Giving a name ('point') to the GcStruct is only for clarity: it is used in the representation.
+Giving a name ('point') to the GcStruct is only for clarity: it is used in the
+representation.
 
     >>> p = malloc(POINT)
     >>> p
@@ -539,14 +618,23 @@
     >>> p
     <ptr(gc) to struct point { x=5, y=0 }>
 
-``malloc()`` allocates a structure from the heap, initalizes it to 0 (currently), and returns a pointer to it.  The point of all this is to work with a very limited, easily controllable set of types, and define implementations of types like list in this elementary world.  The ``malloc()`` function is a kind of placeholder, which must eventually be provided by the code generator for the target platform; but as we have just seen its Python implementation in `rpython/lltype.py`_ works too, which is primarily useful for testing, interactive exploring, etc.
+``malloc()`` allocates a structure from the heap, initalizes it to 0
+(currently), and returns a pointer to it.  The point of all this is to work with
+a very limited, easily controllable set of types, and define implementations of
+types like list in this elementary world.  The ``malloc()`` function is a kind
+of placeholder, which must eventually be provided by the code generator for the
+target platform; but as we have just seen its Python implementation in `
+rpython/lltype.py`_ works too, which is primarily useful for testing,
+interactive exploring, etc.
 
-The argument to ``malloc()`` is the structure type directly, but it returns a pointer to the structure, as ``typeOf()`` tells you::
+The argument to ``malloc()`` is the structure type directly, but it returns a
+pointer to the structure, as ``typeOf()`` tells you::
 
     >>> typeOf(p)
     <ptr(gc) to GcStruct point { x: Signed, y: Signed }>
 
-For the purpose of creating structures with pointers to other structures, we can declare pointer types explicitely::
+For the purpose of creating structures with pointers to other structures, we can
+declare pointer types explicitely::
 
     >>> typeOf(p) == Ptr(POINT)
     True
@@ -559,7 +647,8 @@
     >>> b.p2.y
     42
 
-The world of low-level types is more complicated than integers and GcStructs, though.  The next pages are a reference guide.
+The world of low-level types is more complicated than integers and GcStructs,
+though.  The next pages are a reference guide.
 
 
 Primitive Types
@@ -571,6 +660,9 @@
 Unsigned
     a non-signed integer in one machine word (``unsigned long``)
 
+Float
+    a 64-bit float (``double``)
+
 Char
     a single character (``char``)
 
@@ -578,8 +670,8 @@
     a boolean value
 
 Void
-    a constant.  Meant for variables and function arguments that should
-    disappear from the generated code.
+    a constant.  Meant for variables, function arguments, structure fields, etc.
+    which should disappear from the generated code.
 
 
 Structure Types
@@ -590,13 +682,27 @@
     MyStructType = Struct('somename',  ('field1', Type1), ('field2', Type2)...)
     MyStructType = GcStruct('somename',  ('field1', Type1), ('field2', Type2)...)
 
-This declares a structure (or a Pascal ``record``) containing the specified named fields with the given types.  The field names cannot start with an underscore.  As noted above, you cannot directly manipulate structure objects, but only pointer to structures living in the heap.
-
-By contrast, the fields themselves can be of primitive, pointer or container type.  When a structure contains another structure as a field we say that the latter is "inlined" in the former: the bigger structure contains the smaller one as part of its memory layout.
-
-A structure can also contain an inlined array (see below), but only as its last field: in this case it is a "variable-sized" structure, whose memory layout starts with the non-variable fields and ends with a variable number of array items.  This number is determined when a structure is allocated in the heap.  Variable-sized structures cannot be inlined in other structures.
-
-GcStructs have a platform-specific GC header (e.g. a reference counter); only these can be dynamically malloc()ed.  The non-GC version of Struct does not have any header, and is suitable for being embedded ("inlined") inside other structures.  As an exception, a GcStruct can be embedded as the first field of a GcStruct: the parent structure uses the same GC header as the substructure.
+This declares a structure (or a Pascal ``record``) containing the specified
+named fields with the given types.  The field names cannot start with an
+underscore.  As noted above, you cannot directly manipulate structure objects,
+but only pointer to structures living in the heap.
+
+By contrast, the fields themselves can be of primitive, pointer or container
+type.  When a structure contains another structure as a field we say that the
+latter is "inlined" in the former: the bigger structure contains the smaller one
+as part of its memory layout.
+
+A structure can also contain an inlined array (see below), but only as its last
+field: in this case it is a "variable-sized" structure, whose memory layout
+starts with the non-variable fields and ends with a variable number of array
+items.  This number is determined when a structure is allocated in the heap.
+Variable-sized structures cannot be inlined in other structures.
+
+GcStructs have a platform-specific GC header (e.g. a reference counter); only
+these can be dynamically malloc()ed.  The non-GC version of Struct does not have
+any header, and is suitable for being embedded ("inlined") inside other
+structures.  As an exception, a GcStruct can be embedded as the first field of a
+GcStruct: the parent structure uses the same GC header as the substructure.
 
 
 Array Types
@@ -612,23 +718,48 @@
 
     MyArrayType = Array(('field1', Type1), ('field2', Type2)...)
 
-You can build arrays whose items are either primitive or pointer types, or (non-GC non-varsize) structures.
-
-GcArrays can be malloc()ed.  The length must be specified when malloc() is called, and arrays cannot be resized; this length is stored explicitely in a header.
+You can build arrays whose items are either primitive or pointer types, or
+(non-GC non-varsize) structures.
 
-The non-GC version of Array can be used as the last field of a structure, to make a variable-sized structure.  The whole structure can then be malloc()ed, and the length of the array is specified at this time.
+GcArrays can be malloc()ed.  The length must be specified when malloc() is
+called, and arrays cannot be resized; this length is stored explicitely in a
+header.
+
+The non-GC version of Array can be used as the last field of a structure, to
+make a variable-sized structure.  The whole structure can then be malloc()ed,
+and the length of the array is specified at this time.
 
 
 Pointer Types
 +++++++++++++
 
-As in C, pointers provide the indirection needed to make a reference modifiable or sharable.  Pointers can only point to a structure, an array, a function (see below) or a PyObject (see below).  Pointers to primitive types, if needed, must be done by pointing to a structure with a single field of the required type.  Pointer types are declared by::
+As in C, pointers provide the indirection needed to make a reference modifiable
+or sharable.  Pointers can only point to a structure, an array, a function
+(see below) or a PyObject (see below).  Pointers to primitive types, if needed,
+must be done by pointing to a structure with a single field of the required
+type.  Pointer types are declared by::
 
    Ptr(TYPE)
 
-At run-time, pointers to GC structures (GcStruct, GcArray and PyObject) hold a reference to what they are pointing to.  Pointers to non-GC structures that can go away when their container is deallocated (Struct, Array) must be handled with care: the bigger structure of which they are part of could be freed while the Ptr to the substructure is still in use.  In general, it is a good idea to avoid passing around pointers to inlined substructures of malloc()ed structures.  (The testing implementation of `rpython/lltype.py`_ checks to some extend that you are not trying to use a pointer to a structure after its container has been freed, using weak references.  But pointers to non-GC structures are not officially meant to be weak references: using them after what they point to has been freed just crashes.)
-
-The malloc() operation allocates and returns a Ptr to a new GC structure or array.  In a refcounting implementation, malloc() would allocate enough space for a reference counter before the actual structure, and initialize it to 1.  Note that the testing implementation also allows malloc() to allocate a non-GC structure or array with a keyword argument ``immortal=True``.  Its purpose is to declare and initialize prebuilt data structures which the code generators will turn into static immortal non-GC'ed data.
+At run-time, pointers to GC structures (GcStruct, GcArray and PyObject) hold a
+reference to what they are pointing to.  Pointers to non-GC structures that can
+go away when their container is deallocated (Struct, Array) must be handled
+with care: the bigger structure of which they are part of could be freed while
+the Ptr to the substructure is still in use.  In general, it is a good idea to
+avoid passing around pointers to inlined substructures of malloc()ed structures.
+(The testing implementation of `rpython/lltype.py`_ checks to some extend that
+you are not trying to use a pointer to a structure after its container has been
+freed, using weak references.  But pointers to non-GC structures are not
+officially meant to be weak references: using them after what they point to has
+been freed just crashes.)
+
+The malloc() operation allocates and returns a Ptr to a new GC structure or
+array.  In a refcounting implementation, malloc() would allocate enough space
+for a reference counter before the actual structure, and initialize it to 1.
+Note that the testing implementation also allows malloc() to allocate a non-GC
+structure or array with a keyword argument ``immortal=True``.  Its purpose is to
+declare and initialize prebuilt data structures which the code generators will
+turn into static immortal non-GC'ed data.
 
 
 Function Types
@@ -638,9 +769,16 @@
 
     MyFuncType = FuncType([Type1, Type2, ...], ResultType)
 
-declares a function type taking arguments of the given types and returning a result of the given type.  All these types must be primitives or pointers.  The function type itself is considered to be a "container" type: if you wish, a function contains the bytes that make up its executable code.  As with structures and arrays, they can only be manipulated through pointers.
-
-The testing implementation allows you to "create" functions by calling ``functionptr(TYPE, name, **attrs)``.  The extra attributes describe the function in a way that isn't fully specified now, but the following attributes *might* be present:
+declares a function type taking arguments of the given types and returning a
+result of the given type.  All these types must be primitives or pointers.  The
+function type itself is considered to be a "container" type: if you wish, a
+function contains the bytes that make up its executable code.  As with
+structures and arrays, they can only be manipulated through pointers.
+
+The testing implementation allows you to "create" functions by calling
+``functionptr(TYPE, name, **attrs)``.  The extra attributes describe the
+function in a way that isn't fully specified now, but the following attributes
+*might* be present:
 
     :_callable:  a Python callable, typically a function object.
     :graph:      the flow graph of the function.
@@ -649,17 +787,48 @@
 The PyObject Type
 +++++++++++++++++
 
-This is a special type, for compatibility with CPython: it stands for a structure compatible with PyObject.  This is also a "container" type (thinking about C, this is ``PyObject``, not ``PyObject*``), so it is usually manipulated via a Ptr.  A typed graph can still contain generic space operations (add, getitem, etc.) provided they are applied on objects whose low-level type is ``Ptr(PyObject)``.  In fact, code generators that support this should consider that the default type of a variable, if none is specified, is ``Ptr(PyObject)``.  In this way, they can generate the correct code for fully-untyped flow graphs.
+This is a special type, for compatibility with CPython: it stands for a
+structure compatible with PyObject.  This is also a "container" type (thinking
+about C, this is ``PyObject``, not ``PyObject*``), so it is usually manipulated
+via a Ptr.  A typed graph can still contain generic space operations (add,
+getitem, etc.) provided they are applied on objects whose low-level type is
+``Ptr(PyObject)``.  In fact, code generators that support this should consider
+that the default type of a variable, if none is specified, is ``Ptr(PyObject)``.
+In this way, they can generate the correct code for fully-untyped flow graphs.
+
+The testing implementation allows you to "create" PyObjects by calling
+``pyobjectptr(obj)``.
+
+
+Opaque Types
+++++++++++++
+
+Opaque types represent data implemented in a back-end specific way.  This data cannot be inspected or manipulated.
 
-The testing implementation allows you to "create" PyObjects by calling ``pyobjectptr(obj)``.
+There is a predefined opaque type ``RuntimeTypeInfo``; at run-time, a value of type ``RuntimeTypeInfo`` represents a low-level type.  In practice it is probably enough to be able to represent GcStruct and GcArray types.  This is useful if we have a pointer of type ``Ptr(S)`` which can at run-time point either to a malloc'ed ``S`` alone, or to the ``S`` first field of a larger malloc'ed structure.  The information about the exact larger type that it points to can be computed or passed around as a ``Ptr(RuntimeTypeInfo)``.  Pointer equality on ``Ptr(RuntimeTypeInfo)`` can be used to check the type at run-time.
+
+At the moment, for memory management purposes, some back-ends actually require such information to be available at run-time in the following situation: when a GcStruct has another GcStruct as its first field.  A reference-counting back-end needs to be able to know when a pointer to the smaller structure actually points to the larger one, so that it can also decref the extra fields.  Depending on the situation, it is possible to reconstruct this information without having to store a flag in each and every instance of the smaller GcStruct.  For example, the instances of a class hierarchy can be implemented by nested GcStructs, with instances of subclasses extending instances of parent classes by embedding the parent part of the instance as the first field.  In this case, there is probably already a way to know the run-time class of the instance (e.g. a vtable pointer), but the back-end cannot guess this.  This is the reason for which ``RuntimeTypeInfo`` was originally introduced: just after the GcStruct is created, the function attachRuntimeTypeInfo() should be called to attach to the GcStruct a low-level function of signature ``Ptr(GcStruct) -> Ptr(RuntimeTypeInfo)``.  This function will be compiled by the back-end and automatically called at run-time.  In the above example, it would follow the vtable pointer and fetch the opaque ``Ptr(RuntimeTypeInfo)`` from the vtable itself.  (The reference-counting GenC back-end uses a pointer to the deallocation function as the opaque ``RuntimeTypeInfo``.)
 
 
 Implementing RPython types
 --------------------------
 
-As hinted above, the RPython types (e.g. 'list') are implemented in some "restricted-restricted Python" format by manipulating only low-level types, as provided by the testing implementation of malloc() and friends.  What occurs then is that the same (tested!) very-low-level Python code -- which looks really just like C -- is then transformed into a flow graph and integrated with the rest of the user program.  In other words, we replace an operation like ``add`` between two variables annotated as SomeList, with a ``direct_call`` operation invoking this very-low-level list concatenation.
-
-This list concatenation flow graph is then annotated as usual, with one difference: the annotator has to be taught about malloc() and the way the pointer thus obtained can be manipulated.  This generates a flow graph which is hopefully completely annotated with SomePtr() annotation.  Introduced just for this case, SomePtr maps directly to a low-level pointer type.  This is the only change needed to the Annotator to allow it to perform type inference of our very-low-level snippets of code.
+As hinted above, the RPython types (e.g. 'list') are implemented in some
+"restricted-restricted Python" format by manipulating only low-level types, as
+provided by the testing implementation of malloc() and friends.  What occurs
+then is that the same (tested!) very-low-level Python code -- which looks really
+just like C -- is then transformed into a flow graph and integrated with the
+rest of the user program.  In other words, we replace an operation like ``add``
+between two variables annotated as SomeList, with a ``direct_call`` operation
+invoking this very-low-level list concatenation.
+
+This list concatenation flow graph is then annotated as usual, with one
+difference: the annotator has to be taught about malloc() and the way the
+pointer thus obtained can be manipulated.  This generates a flow graph which is
+hopefully completely annotated with SomePtr() annotation.  Introduced just for
+this case, SomePtr maps directly to a low-level pointer type.  This is the only
+change needed to the Annotator to allow it to perform type inference of our
+very-low-level snippets of code.
 
 See for example `rpython/rlist.py`_.
 
@@ -677,9 +846,16 @@
 Overview
 --------
 
-The task of GenC is to convert a flow graph into C code.  By itself, GenC does not use the annotations in the graph.  It can actually convert unannotated graphs to C.  However, to make use of the annotations if they are present, an extra pass is needed: the `RPython Typer`_, whose task is to modify the flow graph according to the annotations, replacing operations with lower-level C-ish equivalents.
-
-XXX GenC is currently in the process of being updated to use the RPython Typer. more documentation needed when this is done. But the basic principle of creating code from flowgraphs is similar to the `Python back-end`_.
+The task of GenC is to convert a flow graph into C code.  By itself, GenC does
+not use the annotations in the graph.  It can actually convert unannotated
+graphs to C.  However, to make use of the annotations if they are present, an
+extra pass is needed: the `RPython Typer`_, whose task is to modify the flow
+graph according to the annotations, replacing operations with lower-level C-ish
+equivalents.
+
+XXX GenC is currently in the process of being updated to use the RPython Typer.
+More documentation needed when this is done. But the basic principle of creating
+code from flowgraphs is similar to the `Python back-end`_.
 
 
 
@@ -727,11 +903,11 @@
 generates LLVM code that allocates enough memory for an instance of the class
 and then (if the class or a base class has an ``__init__`` method) tells the
 ``FuncRepr`` of the appropriate ``__init__`` method to generate the code for
-the call to it. 
+the call to it.
 
-Every representation object has a some other representations it depends on: A
+Every representation object has some other representations it depends on: A
 ``ListRepr`` of lists instances of a class depends on the ``ClassRepr`` of
-that class. To ensure that the typedef of of the class is written to the llvm
+that class. To ensure that the typedef of the class is written to the llvm
 file before the typedef of the list, the dependency tree of representations
 traversed depth first when the LLVM code is written to a file.
 
@@ -824,10 +1000,10 @@
 Motivation
 ----------
 
-PyPy often makes use of `application-level`_ helper methods.  
-The idea of the 'geninterplevel' backend is to automatically transform 
-such application level implementations to their equivalent representation 
-at interpreter level.  Then, the RPython to C translation hopefully can 
+PyPy often makes use of `application-level`_ helper methods.
+The idea of the 'geninterplevel' backend is to automatically transform
+such application level implementations to their equivalent representation
+at interpreter level.  Then, the RPython to C translation hopefully can
 produce more efficient code than always re-interpreting these methods.
 
 One property of translation from application level Python to
@@ -864,26 +1040,26 @@
 
 .. _implementation: http://codespeak.net/svn/pypy/dist/pypy/translator/geninterplevel.py
 
-Let's try the little example from above_. You might want to look at the 
-flowgraph that it produces. Here, we directly run the Python translation 
-and look at the generated source. See also the header section of the implementation_ 
+Let's try the little example from above_. You might want to look at the
+flowgraph that it produces. Here, we directly run the Python translation
+and look at the generated source. See also the header section of the implementation_
 for the interface::
 
     >>> from pypy.translator.geninterplevel import translate_as_module
     >>> entrypoint, source = translate_as_module("""
-    ... 
+    ...
     ... def g(n):
     ...     i = 0
     ...     while n:
     ...         i = i + n
     ...         n = n - 1
     ...     return i
-    ... 
+    ...
     ... """)
-    
+
 This call has invoked a PyPy interpreter running on FlowObjspace, recorded every
 possible codepath into a flowgraph, and then rendered the following source code::
-    
+
     >>> print source
     #!/bin/env python
     # -*- coding: LATIN-1 -*-

Modified: pypy/branch/pycompiler/documentation/website/news.txt
==============================================================================
--- pypy/branch/pycompiler/documentation/website/news.txt	(original)
+++ pypy/branch/pycompiler/documentation/website/news.txt	Fri Jul  1 18:30:34 2005
@@ -12,17 +12,20 @@
 Next Sprint after EuroPython 2005 1st-7th July 
 ======================================================
 
-The next sprint is scheduled right after EuroPython_ 2005 in Göteborg, Sweden.
-We take a day of break after the conference and start sprinting from 1st-7th
-of July 2005.  See the `sprint announcement`_.  The sprint theme is related
-strongly to `translation`_ and working towards getting a first self-contained
-PyPy version.  Additionally there will be a four day Pre-EuroPython sprint for
-people who already are familiar with the PyPy code base.  *(05/04/2005,
-12/06/2005)*
+The next sprint is scheduled right after EuroPython_ 2005 in
+Göteborg, Sweden.  We take a day of break after the conference
+and start sprinting from 1st-7th of July 2005.  See the
+`sprint announcement`_ and the `list of people coming`_.  The
+sprint theme is related strongly to `translation`_ and working
+towards getting a first self-contained PyPy version.
+Additionally there will be a four day Pre-EuroPython sprint
+for people who already are familiar with the PyPy code base.   
+*(05/04/2005, 12/06/2005, 22/06/2005)*
 
 .. _EuroPython: http://europython.org 
 .. _`translation`: ../translation.html 
 .. _`sprint announcement`: EP2005-announcement.html
+.. _`list of people coming`: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/EP2005-people.html
 
 First PyPy release!
 =================== 

Modified: pypy/branch/pycompiler/interpreter/eval.py
==============================================================================
--- pypy/branch/pycompiler/interpreter/eval.py	(original)
+++ pypy/branch/pycompiler/interpreter/eval.py	Fri Jul  1 18:30:34 2005
@@ -19,7 +19,7 @@
 
     def exec_code(self, space, w_globals, w_locals):
         "Implements the 'exec' statement."
-        frame = self.create_frame(space, w_globals)
+        frame = self.create_frame(space, w_globals, None)
         frame.setdictscope(w_locals)
         return frame.run()
 
@@ -107,7 +107,10 @@
         if self.w_locals is None:
             self.w_locals = self.space.newdict([])
         varnames = self.code.getvarnames()
-        for name, w_value in zip(varnames, self.getfastscope()):
+        fastscope_w = self.getfastscope()
+        for i in range(min(len(varnames), len(fastscope_w))):
+            name = varnames[i]
+            w_value = fastscope_w[i]
             if w_value is not None:
                 w_name = self.space.wrap(name)
                 self.space.setitem(self.w_locals, w_name, w_value)
@@ -119,7 +122,7 @@
 
         new_fastlocals_w = [None]*self.numlocals
         
-        for name, i in zip(varnames, range(self.numlocals)):
+        for i in range(min(len(varnames), self.numlocals)):
             w_name = self.space.wrap(varnames[i])
             try:
                 w_value = self.space.getitem(self.w_locals, w_name)

Modified: pypy/branch/pycompiler/interpreter/function.py
==============================================================================
--- pypy/branch/pycompiler/interpreter/function.py	(original)
+++ pypy/branch/pycompiler/interpreter/function.py	Fri Jul  1 18:30:34 2005
@@ -16,7 +16,7 @@
     """A function is a code object captured with some environment:
     an object space, a dictionary of globals, default arguments,
     and an arbitrary 'closure' passed to the code object."""
-    
+
     def __init__(self, space, code, w_globals=None, defs_w=[], closure=None, forcename=None):
         self.space = space
         self.name = forcename or code.co_name
@@ -76,7 +76,7 @@
             if not isinstance(code, PyCode) or len(code.co_freevars) == 0:
                 raise OperationError(space.w_ValueError, space.wrap("no closure needed"))
             elif len(code.co_freevars) != n:
-                raise OperationError(space.w_ValueError, space.wrap("closure is wrong size"))                
+                raise OperationError(space.w_ValueError, space.wrap("closure is wrong size"))
             closure = []
             for w_cell in closure_w:
                 cell = space.interpclass_w(w_cell)
@@ -98,7 +98,7 @@
         if not values_w:
             return space.w_None
         return space.newtuple(values_w)
-    
+
     def fset_func_defaults(space, self, w_defaults):
         if not space.is_true( space.isinstance( w_defaults, space.w_tuple ) ):
             raise OperationError( space.w_TypeError, space.wrap("func_defaults must be set to a tuple object") )
@@ -125,10 +125,10 @@
             else:
                 self.w_module = space.w_None
         return self.w_module
-        
+
     def fset___module__(space, self, w_module):
         self.w_module = w_module
-    
+
     def fdel___module__(space, self):
         self.w_module = space.w_None
 
@@ -140,7 +140,7 @@
         if not isinstance(code, Code ):
             raise OperationError( space.w_TypeError, space.wrap("func_code must be set to a code object") )
         self.code = code
-    
+
     def fget_func_closure(space, self):
         if self.closure is not None:
             w_res = space.newtuple( [ space.wrap(i) for i in self.closure ] )
@@ -171,7 +171,7 @@
             return space.type(w_obj)
         raise
 
-class Method(Wrappable): 
+class Method(Wrappable):
     """A method is a function bound to a specific instance or class."""
 
     def __init__(self, space, w_function, w_instance, w_class):
@@ -179,7 +179,7 @@
         self.w_function = w_function
         self.w_instance = w_instance   # or None
         self.w_class = w_class         # possibly space.w_None
-        
+
     def descr_method__new__(space, w_subtype, w_function, w_instance, w_class=None):
         if space.is_w( w_instance, space.w_None ):
             w_instance = None
@@ -218,7 +218,7 @@
                         instname += " "
                     instdescr = "%sinstance" %instname
                 msg = ("unbound method %s() must be called with %s"
-                       "instance as first argument (got %s instead)")  % (myname, clsdescr, instdescr) 
+                       "instance as first argument (got %s instead)")  % (myname, clsdescr, instdescr)
                 raise OperationError(space.w_TypeError,
                                      space.wrap(msg))
         return space.call_args(self.w_function, args)
@@ -241,17 +241,17 @@
     def descr_method_call(self, __args__):
         return self.call_args(__args__)
 
-    def descr_method_repr(self): 
+    def descr_method_repr(self):
         space = self.space
         name = self.w_function.getname(self.space, '?')
-        # XXX do we handle all cases sanely here? 
-        if space.is_w(self.w_class, space.w_None): 
-            w_class = space.type(self.w_instance) 
-        else: 
-            w_class = self.w_class 
+        # XXX do we handle all cases sanely here?
+        if space.is_w(self.w_class, space.w_None):
+            w_class = space.type(self.w_instance)
+        else:
+            w_class = self.w_class
         typename = w_class.getname(self.space, '?')
-        if self.w_instance is None: 
-            s = "<method '%s' of '%s' objects>" %(name, typename) 
+        if self.w_instance is None:
+            s = "<method '%s' of '%s' objects>" %(name, typename)
             return space.wrap(s)
         else:
             info = "method %s of %s object" % (name, typename)

Modified: pypy/branch/pycompiler/interpreter/nestedscope.py
==============================================================================
--- pypy/branch/pycompiler/interpreter/nestedscope.py	(original)
+++ pypy/branch/pycompiler/interpreter/nestedscope.py	Fri Jul  1 18:30:34 2005
@@ -73,7 +73,9 @@
         # cellvars are values exported to inner scopes
         # freevars are values coming from outer scopes 
         freevarnames = self.code.co_cellvars + self.code.co_freevars
-        for name, cell in zip(freevarnames, self.cells):
+        for i in range(len(freevarnames)):
+            name = freevarnames[i]
+            cell = self.cells[i]
             try:
                 w_value = cell.get()
             except ValueError:
@@ -85,7 +87,9 @@
     def locals2fast(self):
         PyInterpFrame.locals2fast(self)
         freevarnames = self.code.co_cellvars + self.code.co_freevars
-        for name, cell in zip(freevarnames, self.cells):
+        for i in range(len(freevarnames)):
+            name = freevarnames[i]
+            cell = self.cells[i]
             w_name = self.space.wrap(name)
             try:
                 w_value = self.space.getitem(self.w_locals, w_name)
@@ -140,13 +144,13 @@
         except ValueError:
             varname = f.getfreevarname(varindex)
             if f.iscellvar(varindex):
-                message = "local variable '%s' referenced before assignment"
+                message = "local variable '%s' referenced before assignment"%varname
                 w_exc_type = f.space.w_UnboundLocalError
             else:
                 message = ("free variable '%s' referenced before assignment"
-                           " in enclosing scope")
+                           " in enclosing scope"%varname)
                 w_exc_type = f.space.w_NameError
-            raise OperationError(w_exc_type, f.space.wrap(message % varname))
+            raise OperationError(w_exc_type, f.space.wrap(message))
         else:
             f.valuestack.push(w_value)
 

Modified: pypy/branch/pycompiler/interpreter/pycode.py
==============================================================================
--- pypy/branch/pycompiler/interpreter/pycode.py	(original)
+++ pypy/branch/pycompiler/interpreter/pycode.py	Fri Jul  1 18:30:34 2005
@@ -48,7 +48,7 @@
 NESTED    = 1
 GENERATOR = 2
 
-frame_classes = {}
+frame_classes = []
 
 def setup_frame_classes():
     "NOT_RPYTHON"
@@ -66,6 +66,7 @@
                 dic[n] = func_with_new_name(x, x.__name__)
         return dic
 
+    frame_classes.extend([None]*4)
     frame_classes[0]                = PyInterpFrame
     frame_classes[NESTED]           = PyNestedScopeFrame
     frame_classes[GENERATOR]        = type('PyGeneratorFrame',

Modified: pypy/branch/pycompiler/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/pycompiler/interpreter/pyopcode.py	(original)
+++ pypy/branch/pycompiler/interpreter/pyopcode.py	Fri Jul  1 18:30:34 2005
@@ -628,7 +628,7 @@
         block = pyframe.FinallyBlock(f, f.next_instr + offsettoend)
         f.blockstack.push(block)
 
-    def CALL_FUNCTION(f, oparg, w_star=None, w_starstar=None):
+    def call_function(f, oparg, w_star=None, w_starstar=None):
         n_arguments = oparg & 0xff
         n_keywords = (oparg>>8) & 0xff
         keywords = {}
@@ -644,18 +644,21 @@
         w_result = f.space.call_args(w_function, args)
         f.valuestack.push(w_result)
 
+    def CALL_FUNCTION(f, oparg):
+        f.call_function(oparg)
+
     def CALL_FUNCTION_VAR(f, oparg):
         w_varargs = f.valuestack.pop()
-        f.CALL_FUNCTION(oparg, w_varargs)
+        f.call_function(oparg, w_varargs)
 
     def CALL_FUNCTION_KW(f, oparg):
         w_varkw = f.valuestack.pop()
-        f.CALL_FUNCTION(oparg, None, w_varkw)
+        f.call_function(oparg, None, w_varkw)
 
     def CALL_FUNCTION_VAR_KW(f, oparg):
         w_varkw = f.valuestack.pop()
         w_varargs = f.valuestack.pop()
-        f.CALL_FUNCTION(oparg, w_varargs, w_varkw)
+        f.call_function(oparg, w_varargs, w_varkw)
 
     def MAKE_FUNCTION(f, numdefaults):
         w_codeobj = f.valuestack.pop()
@@ -776,6 +779,7 @@
             return 
         # XXX add unicode handling
         file_softspace(stream, True)
+    print_item_to._annspecialcase_ = "specialize:argtype0"
 
     def print_newline_to(stream):
         stream.write("\n")

Modified: pypy/branch/pycompiler/interpreter/typedef.py
==============================================================================
--- pypy/branch/pycompiler/interpreter/typedef.py	(original)
+++ pypy/branch/pycompiler/interpreter/typedef.py	Fri Jul  1 18:30:34 2005
@@ -24,16 +24,38 @@
         # hint for the annotator: track individual constant instances of TypeDef
         return True
 
-subclass_cache = {}
-def get_unique_interplevel_subclass(cls, hasdict, wants_slots):
-    key = (cls, hasdict, wants_slots)
-    try:
-        return subclass_cache[key]
-    except KeyError:
-        subcls = _buildusercls(cls, hasdict, wants_slots)
-        subclass_cache[key] = subcls
-        return subcls
-get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo"
+
+# we cannot specialize:memo by more than one PBC key 
+# so we need to work a bit to allow that 
+
+def get_unique_interplevel_subclass(cls, hasdict, wants_slots): 
+    if hasdict: 
+        if wants_slots: 
+            return get_unique_interplevel_WithDictWithSlots(cls)
+        else: 
+            return get_unique_interplevel_WithDictNoSlots(cls)
+    else: 
+        if wants_slots: 
+            return get_unique_interplevel_NoDictWithSlots(cls)
+        else: 
+            return get_unique_interplevel_NoDictNoSlots(cls)
+
+for hasdict in False, True: 
+    for wants_slots in False, True: 
+        name = hasdict and "WithDict" or "NoDict"
+        name += wants_slots and "WithSlots" or "NoSlots" 
+        funcname = "get_unique_interplevel_%s" % (name,)
+        exec compile2("""
+            subclass_cache_%(name)s = {}
+            def %(funcname)s(cls): 
+                try: 
+                    return subclass_cache_%(name)s[cls]
+                except KeyError: 
+                    subcls = _buildusercls(cls, %(hasdict)r, %(wants_slots)r)
+                    subclass_cache_%(name)s[cls] = subcls
+                    return subcls
+            %(funcname)s._annspecialcase_ = "specialize:memo"
+        """ % locals())
 
 def _buildusercls(cls, hasdict, wants_slots):
     "NOT_RPYTHON: initialization-time only"

Modified: pypy/branch/pycompiler/lib/_exceptions.py
==============================================================================
--- pypy/branch/pycompiler/lib/_exceptions.py	(original)
+++ pypy/branch/pycompiler/lib/_exceptions.py	Fri Jul  1 18:30:34 2005
@@ -131,10 +131,24 @@
         argc = len(args)
         self.args = args # modified: always assign args, no error check
         if argc == 4:
-            self.object = args[0]
-            self.start = args[1]
-            self.end = args[2]
-            self.reason = args[3]
+            if type(args[0]) == unicode:
+                self.object = args[0]
+            else:
+                raise TypeError('argument 0 must be unicode, not %s'%type(args[0]))
+            if type(args[1]) == int:
+                self.start = args[1]
+            else:
+                raise TypeError('argument 1 must be int, not %s'%type(args[1]))
+            if type(args[2]) == int:
+                self.end = args[2]
+            else:
+                raise TypeError('argument 2 must be int, not %s'%type(args[2]))
+            if type(args[3]) == str:
+                self.reason = args[3]
+            else:
+                raise TypeError('argument 3 must be str, not %s'%type(args[3]))
+        else:
+            raise TypeError('function takes exactly 4 arguments (%d given)'%argc)
 
     # auto-generated code, please check carefully!
     def __str__(self):
@@ -181,9 +195,9 @@
     def __init__(self, *args):
         argc = len(args)
         self.args = args
-        self.errno = None # default, hopefully
-        self.strerror = None # default, hopefully
-        self.filename = None # default, hopefully
+        self.errno = None
+        self.strerror = None
+        self.filename = None
         if 2 <= argc <= 3:
             self.errno = args[0]
             self.strerror = args[1]
@@ -207,6 +221,50 @@
 class DeprecationWarning(Warning):
     """Base class for warnings about deprecated features."""
 
+class UnicodeEncodeError(UnicodeError):
+    """Unicode encoding error."""
+
+    # auto-generated code, please check carefully!
+    def __init__(self, *args):
+        argc = len(args)
+        self.args = args # modified: always assign args, no error check
+        if argc == 5:
+            if type(args[0]) == str:
+                self.encoding = args[0]
+            else:
+                raise TypeError('argument 0 must be str, not %s'%type(args[0]))
+            if type(args[1]) == unicode:
+                self.object = args[1]
+            else:
+                raise TypeError('argument 1 must be unicode, not %s'%type(args[1]))
+            if type(args[2]) == int:
+                self.start = args[2]
+            else:
+                raise TypeError('argument 2 must be int, not %s'%type(args[2]))
+            if type(args[3]) == int:
+                self.end = args[3]
+            else:
+                raise TypeError('argument 3 must be int, not %s'%type(args[3]))
+            if type(args[4]) == str:
+                self.reason = args[4]
+            else:
+                raise TypeError('argument 4 must be str, not %s'%type(args[4]))
+        else:
+            raise TypeError('function takes exactly 5 arguments (%d given)'%argc)
+
+    # auto-generated code, please check carefully!
+    def __str__(self):
+        # this is a bad hack, please supply an implementation
+        res = ' '.join([
+           'object=' + str(getattr(self, 'object', None)),
+           'end=' + str(getattr(self, 'end', None)),
+           'encoding=' + str(getattr(self, 'encoding', None)),
+           'args=' + str(getattr(self, 'args', None)),
+           'start=' + str(getattr(self, 'start', None)),
+           'reason=' + str(getattr(self, 'reason', None)),
+        ])
+        return res
+
 class ArithmeticError(StandardError):
     """Base class for arithmetic errors."""
 
@@ -241,10 +299,22 @@
         if argc >= 1:
             self.msg = args[0]
         if argc == 2:
-            self.filename = args[1][0]
-            self.lineno = args[1][1]
-            self.offset = args[1][2]
-            self.text = args[1][3]
+            if type(args[1][0]) == str:
+                self.filename = args[1][0]
+            else:
+                raise TypeError('argument 1 must be str, not %s'%type(args[1][0]))
+            if type(args[1][1]) == str:
+                self.lineno = args[1][1]
+            else:
+                raise TypeError('argument 2 must be str, not %s'%type(args[1][1]))
+            if type(args[1][2]) == str:
+                self.offset = args[1][2]
+            else:
+                raise TypeError('argument 3 must be str, not %s'%type(args[1][2]))
+            if type(args[1][3]) == str:
+                self.text = args[1][3]
+            else:
+                raise TypeError('argument 4 must be str, not %s'%type(args[1][3]))
 
     def __str__(self):
         if type(self.msg) is not str:
@@ -275,12 +345,15 @@
     def __init__(self, *args):
         argc = len(args)
         if argc == 0:
-            self.code = None # default, hopefully
+            self.code = None
         self.args = args
         if argc == 1:
             self.code = args[0]
         if argc >= 2:
-            self.code = args
+            if type(args) == tuple:
+                self.code = args
+            else:
+                raise TypeError('argument 0 must be tuple, not %s'%type(args))
 
 class EOFError(StandardError):
     """Read beyond end of file."""
@@ -311,11 +384,28 @@
         argc = len(args)
         self.args = args # modified: always assign args, no error check
         if argc == 5:
-            self.encoding = args[0]
-            self.object = args[1]
-            self.start = args[2]
-            self.end = args[3]
-            self.reason = args[4]
+            if type(args[0]) == str:
+                self.encoding = args[0]
+            else:
+                raise TypeError('argument 0 must be str, not %s'%type(args[0]))
+            if type(args[1]) == str:
+                self.object = args[1]
+            else:
+                raise TypeError('argument 1 must be str, not %s'%type(args[1]))
+            if type(args[2]) == int:
+                self.start = args[2]
+            else:
+                raise TypeError('argument 2 must be int, not %s'%type(args[2]))
+            if type(args[3]) == int:
+                self.end = args[3]
+            else:
+                raise TypeError('argument 3 must be int, not %s'%type(args[3]))
+            if type(args[4]) == str:
+                self.reason = args[4]
+            else:
+                raise TypeError('argument 4 must be str, not %s'%type(args[4]))
+        else:
+            raise TypeError('function takes exactly 5 arguments (%d given)'%argc)
 
     # auto-generated code, please check carefully!
     def __str__(self):
@@ -363,29 +453,5 @@
 class OverflowError(ArithmeticError):
     """Result too large to be represented."""
 
-class UnicodeEncodeError(UnicodeError):
-    """Unicode encoding error."""
-
-    # auto-generated code, please check carefully!
-    def __init__(self, *args):
-        argc = len(args)
-        self.args = args # modified: always assign args, no error check
-        if argc == 5:
-            self.encoding = args[0]
-            self.object = args[1]
-            self.start = args[2]
-            self.end = args[3]
-            self.reason = args[4]
-
-    # auto-generated code, please check carefully!
-    def __str__(self):
-        # this is a bad hack, please supply an implementation
-        res = ' '.join([
-           'object=' + str(getattr(self, 'object', None)),
-           'end=' + str(getattr(self, 'end', None)),
-           'encoding=' + str(getattr(self, 'encoding', None)),
-           'args=' + str(getattr(self, 'args', None)),
-           'start=' + str(getattr(self, 'start', None)),
-           'reason=' + str(getattr(self, 'reason', None)),
-        ])
-        return res
+class WindowsError(OSError):
+    """MS-Windows OS system call failed."""

Deleted: /pypy/branch/pycompiler/lib/inprogress__codecs.py
==============================================================================
--- /pypy/branch/pycompiler/lib/inprogress__codecs.py	Fri Jul  1 18:30:34 2005
+++ (empty file)
@@ -1,407 +0,0 @@
-"""
-
-   _codecs -- Provides access to the codec registry and the builtin
-              codecs.
-
-   This module should never be imported directly. The standard library
-   module "codecs" wraps this builtin module for use within Python.
-
-   The codec registry is accessible via:
-
-     register(search_function) -> None
-
-     lookup(encoding) -> (encoder, decoder, stream_reader, stream_writer)
-
-   The builtin Unicode codecs use the following interface:
-
-     <encoding>_encode(Unicode_object[,errors='strict']) -> 
-         (string object, bytes consumed)
-
-     <encoding>_decode(char_buffer_obj[,errors='strict']) -> 
-        (Unicode object, bytes consumed)
-
-   <encoding>_encode() interfaces also accept non-Unicode object as
-   input. The objects are then converted to Unicode using
-   PyUnicode_FromObject() prior to applying the conversion.
-
-   These <encoding>s are available: utf_8, unicode_escape,
-   raw_unicode_escape, unicode_internal, latin_1, ascii (7-bit),
-   mbcs (on win32).
-
-
-Written by Marc-Andre Lemburg (mal at lemburg.com).
-
-Copyright (c) Corporation for National Research Initiatives.
-
-"""
-from unicodecodec import *
-#/* --- Registry ----------------------------------------------------------- */
-codec_search_path = []
-codec_search_cache = {}
-
-def codec_register( search_function ):
-    """register(search_function)
-    
-    Register a codec search function. Search functions are expected to take
-    one argument, the encoding name in all lower case letters, and return
-    a tuple of functions (encoder, decoder, stream_reader, stream_writer).
-    """
-
-    if callable(search_function):
-        codec_search_path.append(search_function)
-
-register = codec_register
-
-def codec_lookup(encoding):
-    """lookup(encoding) -> (encoder, decoder, stream_reader, stream_writer)
-    Looks up a codec tuple in the Python codec registry and returns
-    a tuple of functions.
-    """
-    
-    result = codec_search_cache.get(encoding,None)
-    if not result:
-        if len(codec_search_path) == 0:
-            import encodings
-            if len(codec_search_path) == 0:
-                raise LookupError("no codec search functions registered: can't find encoding")
-        if not isinstance(encoding,str):
-            raise TypeError("Encoding must be a string")
-        for search in codec_search_path:
-            result=search(encoding)
-            if result :
-                if not( type(result) == tuple and len(result) == 4):
-                    raise TypeError("codec search functions must return 4-tuples")
-                else:
-                    codec_search_cache[encoding] = result 
-                    return result
-        if not result:
-            raise LookupError( "unknown encoding: %s" % encoding)
-    return result
-    
-
-lookup = codec_lookup
-
-def encode(v, encoding='defaultencoding',errors='strict'):
-    """encode(obj, [encoding[,errors]]) -> object
-    
-    Encodes obj using the codec registered for encoding. encoding defaults
-    to the default encoding. errors may be given to set a different error
-    handling scheme. Default is 'strict' meaning that encoding errors raise
-    a ValueError. Other possible values are 'ignore', 'replace' and
-    'xmlcharrefreplace' as well as any other name registered with
-    codecs.register_error that can handle ValueErrors.
-    """
-    if isinstance(encoding,str):
-        encoder = lookup(encoding)[0]
-        if encoder and isinstance(errors,str):
-            res = encoder(v,errors)
-            return res[0]
-        else:
-            raise TypeError("Errors must be a string")
-    else:
-        raise TypeError("Encoding must be a string")
-
-def decode(obj,encoding='defaultencoding',errors='strict'):
-    """decode(obj, [encoding[,errors]]) -> object
-
-    Decodes obj using the codec registered for encoding. encoding defaults
-    to the default encoding. errors may be given to set a different error
-    handling scheme. Default is 'strict' meaning that encoding errors raise
-    a ValueError. Other possible values are 'ignore' and 'replace'
-    as well as any other name registerd with codecs.register_error that is
-    able to handle ValueErrors.
-    """
-    if isinstance(encoding,str):
-        decoder = lookup(encoding)[1]
-        if decoder and isinstance(errors,str):
-            res = decoder(obj,errors)
-            if not isinstance(res,tuple) or len(res) != 2:
-                raise TypeError("encoder must return a tuple (object,integer)")
-            return res[0]
-        else:
-            raise TypeError("Errors must be a string")
-    else:
-        raise TypeError("Encoding must be a string")
-
-def latin_1_encode( obj,errors='strict'):
-    """None
-    """
-    res = PyUnicode_EncodeLatin1(obj,len(obj),errors)
-    res = ''.join(res)
-    return res, len(res)
-# XXX MBCS codec might involve ctypes ?
-def mbcs_decode():
-    """None
-    """
-    pass
-
-def readbuffer_encode( obj,errors='strict'):
-    """None
-    """
-    res = str(obj)
-    return res,len(res)
-
-def escape_encode( obj,errors='strict'):
-    """None
-    """
-    s = repr(obj)
-    v = s[1:-1]
-    return v,len(v)
-
-def utf_8_decode( data,errors='strict',final=None):
-    """None
-    """
-    res = PyUnicode_DecodeUTF8Stateful(data, len(data), errors, final)
-    res = u''.join(res)
-    return res,len(res)
-
-def raw_unicode_escape_decode( data,errors='strict'):
-    """None
-    """
-    res = PyUnicode_DecodeRawUnicodeEscape(data, len(data), errors)
-    res = u''.join(res)
-    return res,len(res)
-
-def utf_7_decode( data,errors='strict'):
-    """None
-    """
-    res = PyUnicode_DecodeUTF7(data,len(data),errors)
-    res = u''.join(res)
-    return res,len(res)
-
-def unicode_escape_encode( obj,errors='strict'):
-    """None
-    """
-    res = unicodeescape_string(obj,len(obj),0)
-    res = ''.join(res)
-    return res, len(res)
-
-def latin_1_decode( data,errors='strict'):
-    """None
-    """
-    res = PyUnicode_DecodeLatin1(data,len(data),errors)
-    res = u''.join(res)
-    return res, len(res)
-
-def utf_16_decode( data,errors='strict',final=None):
-    """None
-    """
-    res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors)
-    res = ''.join(res)
-    return res, len(res)
-
-def unicode_escape_decode( data,errors='strict'):
-    """None
-    """
-    res = PyUnicode_DecodeUnicodeEscape(data,len(data),errors)
-    res = ''.join(res)
-    return res, len(res)
-
-
-def ascii_decode( data,errors='strict'):
-    """None
-    """
-    res = PyUnicode_DecodeASCII(data,len(data),errors)
-    res = u''.join(res)
-    return res, len(res)
-
-def charmap_encode(obj,errors='strict',mapping='latin-1'):
-    """None
-    """
-    res = PyUnicode_EncodeCharmap(obj,len(obj),mapping,errors)
-    res = ''.join(res)
-    return res, len(res)
-
-unicode_bytes = (len(hex(sys.maxunicode))-1)/2
-
-def unicode_internal_encode( obj,errors='strict'):
-    """None
-    """
-    if type(obj) == unicode:
-        p = []
-        t = [ord(x) for x in obj]
-        for i in t:
-            for j in xrange(unicode_bytes):
-                p += chr(i%256)
-                i >>= 8
-        res = ''.join(p)
-        return res, len(res)
-    else:
-        res = "You can do better than this" # XXX make this right
-        return res,len(res)
-
-def unicode_internal_decode( unistr,errors='strict'):
-    """None
-    """
-    if type(unistr) == unicode:
-        return unistr,len(unistr)
-    else:
-        p=[]
-        i=0
-        while i < len(unistr)-unicode_bytes+1:
-            t = 0
-            for j in range(unicode_bytes):
-                t += ord(unistr[i+j])<<(j*8)
-            i += unicode_bytes
-            p += unichr(t)
-        res = u''.join(p)
-        return res, len(res)
-
-def utf_16_ex_decode( data,errors='strict'):
-    """None
-    """
-    res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors,'native')
-    res = ''.join(res)
-    return res, len(res)
-# XXX escape_decode Check if this is right
-def escape_decode(data,errors='strict'):
-    """None
-    """
-    return data,len(data)
-
-def charbuffer_encode( obj,errors='strict'):
-    """None
-    """
-    res = str(obj)
-    res = ''.join(res)
-    return res, len(res)
-
-def charmap_decode( data,errors='strict',mapping=None):
-    """None
-    """
-    res = PyUnicode_DecodeCharmap(data, len(data), mapping, errors)
-    res = ''.join(res)
-    return res, len(res)
-
-
-def utf_7_encode( obj,errors='strict'):
-    """None
-    """
-    res = PyUnicode_EncodeUTF7(obj,len(obj),0,0,errors)
-    res = ''.join(res)
-    return res, len(res)
-
-def mbcs_encode( obj,errors='strict'):
-    """None
-    """
-    pass
-##    return (PyUnicode_EncodeMBCS(
-##			       (obj), 
-##			       len(obj),
-##			       errors),
-##		    len(obj))
-    
-
-def ascii_encode( obj,errors='strict'):
-    """None
-    """
-    res = PyUnicode_EncodeASCII(obj,len(obj),errors)
-    res = ''.join(res)
-    return res, len(res)
-
-def utf_16_encode( obj,errors='strict'):
-    """None
-    """
-    res = PyUnicode_EncodeUTF16(obj,len(obj),errors)
-    res = ''.join(res)
-    return res, len(res)
-
-def raw_unicode_escape_encode( obj,errors='strict'):
-    """None
-    """
-    res = PyUnicode_EncodeRawUnicodeEscape(obj,len(obj))
-    res = ''.join(res)
-    return res, len(res)
-
-def utf_8_encode( obj,errors='strict'):
-    """None
-    """
-    res = PyUnicode_EncodeUTF8(obj,len(obj),errors)
-    res = ''.join(res)
-    return res, len(res)
-
-def utf_16_le_encode( obj,errors='strict'):
-    """None
-    """
-    res = PyUnicode_EncodeUTF16(obj,len(obj),errors,'little')
-    res = ''.join(res)
-    return res, len(res)
-
-def utf_16_be_encode( obj,errors='strict'):
-    """None
-    """
-    res = PyUnicode_EncodeUTF16(obj,len(obj),errors,'big')
-    res = ''.join(res)
-    return res, len(res)
-
-def utf_16_le_decode( data,errors='strict'):
-    """None
-    """
-    res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors,'little')
-    res = ''.join(res)
-    return res, len(res)
-
-def utf_16_be_decode( data,errors='strict'):
-    """None
-    """
-    res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors,'big')
-    res = ''.join(res)
-    return res, len(res)
-
-def strict_errors(exc):
-    if isinstance(exc,Exception):
-        raise exc
-    else:
-        raise TypeError("codec must pass exception instance")
-    
-def ignore_errors(exc):
-    if isinstance(exc,(UnicodeEncodeError,UnicodeDecodeError,UnicodeTranslateError)):
-        return u'',exc.end
-    else:
-        raise TypeError("don't know how to handle %.400s in error callback"%exc)
-
-Py_UNICODE_REPLACEMENT_CHARACTER = u"\ufffd"
-
-def replace_errors(exc):
-    if isinstance(exc,UnicodeEncodeError):
-        return u'?'*(exc.end-exc.start),exc.end
-    elif isinstance(exc,(UnicodeTranslateError,UnicodeDecodeError)):
-        return Py_UNICODE_REPLACEMENT_CHARACTER*(exc.end-exc.start),exc.end
-    else:
-        raise TypeError("don't know how to handle %.400s in error callback"%exc)
-
-def xmlcharrefreplace_errors(exc):
-    if isinstance(exc,UnicodeEncodeError):
-        res = []
-        for ch in exc.object[exc.start:exc.end]:
-            res += '&#'
-            res += str(ord(ch))
-            res += ';'
-        return u''.join(res),exc.end
-    else:
-        raise TypeError("don't know how to handle %.400s in error callback"%type(exc))
-    
-def backslashreplace_errors(exc):
-    if isinstance(exc,UnicodeEncodeError):
-        p=[]
-        for c in exc.object[exc.start:exc.end]:
-            p.append('\\')
-            oc = ord(c)
-            if (oc >= 0x00010000):
-                p.append('U')
-                p.append("%.8x" % ord(c))
-            elif (oc >= 0x100):
-                p.append('u')
-                p.append("%.4x" % ord(c))
-            else:
-                p.append('x')
-                p.append("%.2x" % ord(c))
-        return u''.join(p),exc.end
-    else:
-        raise TypeError("don't know how to handle %.400s in error callback"%type(exc))
-
-register_error("strict",strict_errors)
-register_error("ignore",ignore_errors)
-register_error("replace",replace_errors)
-register_error("xmlcharrefreplace",xmlcharrefreplace_errors)
-register_error("backslashreplace",backslashreplace_errors)
\ No newline at end of file

Deleted: /pypy/branch/pycompiler/lib/unicodecodec.py
==============================================================================
--- /pypy/branch/pycompiler/lib/unicodecodec.py	Fri Jul  1 18:30:34 2005
+++ (empty file)
@@ -1,1196 +0,0 @@
-import sys
-""" Python implementation of CPythons builtin unicode codecs.
-
-    Generally the functions in this module take a list of characters an returns 
-    a list of characters.
-    
-    For use in the PyPy project"""
-
-
-## indicate whether a UTF-7 character is special i.e. cannot be directly
-##       encoded:
-##	   0 - not special
-##	   1 - special
-##	   2 - whitespace (optional)
-##	   3 - RFC2152 Set O (optional)
-    
-utf7_special = [
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 1, 0, 0, 0, 1,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0,
-    3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3,
-    3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1,
-]
-unicode_latin1=[None]*256
-
-codec_error_registry = {}
-def lookup_error(errors):
-    """lookup_error(errors) -> handler
-
-    Return the error handler for the specified error handling name
-    or raise a LookupError, if no handler exists under this name.
-    """
-    
-    try:
-        err_handler = codec_error_registry[errors]
-    except KeyError:
-        raise LookupError("unknown error handler name %s"%errors)
-    return err_handler
-
-def register_error(errors, handler):
-    """register_error(errors, handler)
-
-    Register the specified error handler under the name
-    errors. handler must be a callable object, that
-    will be called with an exception instance containing
-    information about the location of the encoding/decoding
-    error and must return a (replacement, new position) tuple.
-    """
-    if callable(handler):
-        codec_error_registry[errors] = handler
-    else:
-        raise TypeError("handler must be callable")
-    
-def SPECIAL(c, encodeO, encodeWS):
-    c = ord(c)
-    return (c>127 or utf7_special[c] == 1) or \
-            (encodeWS and (utf7_special[(c)] == 2)) or \
-            (encodeO and (utf7_special[(c)] == 3))
-def B64(n):
-    return ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f])
-def B64CHAR(c):
-    return (c.isalnum() or (c) == '+' or (c) == '/')
-def UB64(c):
-    if (c) == '+' :
-        return 62 
-    elif (c) == '/':
-        return 63 
-    elif (c) >= 'a':
-        return ord(c) - 71 
-    elif (c) >= 'A':
-        return ord(c) - 65 
-    else: 
-        return ord(c) + 4
-
-def ENCODE( ch, bits) :
-    charvalue = 0
-    out = []
-##    for c in ch:
-##        charvalue <<= 16
-##        charvalue += ord(c)
-    while (bits >= 6):
-        out +=  B64(ch >> (bits-6))
-        bits -= 6 
-    return out,bits
-
-
-def PyUnicode_DecodeUTF7(s, size, errors):
-
-    starts = s
-    errmsg = ""
-    inShift = 0
-    bitsleft = 0
-    charsleft = 0
-    surrogate = 0
-    p = []
-    errorHandler = None
-    exc = None
-
-    if (size == 0):
-        return unicode('')
-    i = 0
-    while i < size:
-        
-        ch = s[i]
-        if (inShift):
-            if ((ch == '-') or not B64CHAR(ch)):
-                inShift = 0
-                i += 1
-                
-                while (bitsleft >= 16):
-                    outCh =  ((charsleft) >> (bitsleft-16)) & 0xffff
-                    bitsleft -= 16
-                    
-                    if (surrogate):
-                        ##            We have already generated an error for the high surrogate
-                        ##            so let's not bother seeing if the low surrogate is correct or not 
-                        surrogate = 0
-                    elif (0xDC00 <= (outCh) and (outCh) <= 0xDFFF):
-            ##             This is a surrogate pair. Unfortunately we can't represent 
-            ##               it in a 16-bit character 
-                        surrogate = 1
-                        msg = "code pairs are not supported"
-                        out,x = unicode_call_errorhandler(errors,'utf-7',msg,s,i-1,i)
-                        p += out
-                        bitsleft = 0
-                        break
-                    else:
-                        p +=  unichr(outCh )
-                        #p += out
-                if (bitsleft >= 6):
-##                    /* The shift sequence has a partial character in it. If
-##                       bitsleft < 6 then we could just classify it as padding
-##                       but that is not the case here */
-                    msg = "partial character in shift sequence"
-                    out,x = unicode_call_errorhandler(errors,'utf-7',msg,s,i-1,i)
-                    
-##                /* According to RFC2152 the remaining bits should be zero. We
-##                   choose to signal an error/insert a replacement character
-##                   here so indicate the potential of a misencoded character. */
-
-##                /* On x86, a << b == a << (b%32) so make sure that bitsleft != 0 */
-##                if (bitsleft and (charsleft << (sizeof(charsleft) * 8 - bitsleft))):
-##                    raise UnicodeDecodeError, "non-zero padding bits in shift sequence"
-                if (ch == '-') :
-                    if ((i < size) and (s[i] == '-')) :
-                        p +=  '-'
-                        inShift = 1
-                    
-                elif SPECIAL(ch,0,0) :
-                    raise  UnicodeDecodeError,"unexpected special character"
-	                
-                else:  
-                    p +=  ch 
-            else:
-                charsleft = (charsleft << 6) | UB64(ch)
-                bitsleft += 6
-                i+=1
-##                /* p, charsleft, bitsleft, surrogate = */ DECODE(p, charsleft, bitsleft, surrogate);
-        elif ( ch == '+' ):
-            startinpos = i
-            i+=1
-            if (i<size and s[i] == '-'):
-                i+=1
-                p +=  '+'
-            else:
-                inShift = 1
-                bitsleft = 0
-                
-        elif (SPECIAL(ch,0,0)):
-            i+=1
-            raise UnicodeDecodeError,"unexpected special character"
-        else:
-            p +=  ch 
-            i+=1
-
-    if (inShift) :
-        #XXX This aint right
-        endinpos = size
-        raise UnicodeDecodeError, "unterminated shift sequence"
-        
-    return p
-
-def PyUnicode_EncodeUTF7(s, size, encodeSetO, encodeWhiteSpace, errors):
-
-#    /* It might be possible to tighten this worst case */
-    inShift = False
-    i = 0
-    bitsleft = 0
-    charsleft = 0
-    out = []
-    for ch in s:
-        if (not inShift) :
-            if (ch == '+'):
-                out +=  '+'
-                out +=  '-'
-            elif (SPECIAL(ch, encodeSetO, encodeWhiteSpace)):
-                charsleft = ord(ch)
-                bitsleft = 16
-                out += '+'
-                p, bitsleft = ENCODE( charsleft, bitsleft)
-                out += p
-                inShift = bitsleft > 0
-            else:
-                out += chr(ord(ch))
-        else:
-            if (not SPECIAL(ch, encodeSetO, encodeWhiteSpace)):
-                out += B64((charsleft) << (6-bitsleft))
-                charsleft = 0
-                bitsleft = 0
-##                /* Characters not in the BASE64 set implicitly unshift the sequence
-##                   so no '-' is required, except if the character is itself a '-' */
-                if (B64CHAR(ch) or ch == '-'):
-                    out += '-'
-                inShift = False
-                out += chr(ord(ch))
-            else:
-                bitsleft += 16
-                charsleft = (((charsleft) << 16) | ord(ch))
-                p, bitsleft =  ENCODE(charsleft, bitsleft)
-                out += p
-##                /* If the next character is special then we dont' need to terminate
-##                   the shift sequence. If the next character is not a BASE64 character
-##                   or '-' then the shift sequence will be terminated implicitly and we
-##                   don't have to insert a '-'. */
-
-                if (bitsleft == 0):
-                    if (i + 1 < size):
-                        ch2 = s[i+1]
-
-                        if (SPECIAL(ch2, encodeSetO, encodeWhiteSpace)):
-                            pass
-                        elif (B64CHAR(ch2) or ch2 == '-'):
-                            out +=  '-'
-                            inShift = False
-                        else:
-                            inShift = False
-                    else:
-                        out +=  '-'
-                        inShift = False
-        i+=1
-            
-    if (bitsleft):
-        out += B64(charsleft << (6-bitsleft) ) 
-        out +=  '-'
-
-    return out
-
-unicode_empty=u''
-
-##def PyUnicode_Decode(s,size,encoding,errors):
-##
-##    if (encoding == None):
-##        encoding = PyUnicode_GetDefaultEncoding()
-##
-####    /* Shortcuts for common default encodings */
-##    decoder = encodings.get(encoding,None)
-##    if decoder:
-##        return decoder(s,encoding,errors)
-####    /* Decode via the codec registry */
-##    buf = buffer(s)
-##    result = PyCodec_Decode(buf, encoding, errors)
-##    if (not isinstance(result,unicode)):
-##        raise UnicodeDecodeError, "decoder did not return an unicode object (type=%.400s)"%type(result)
-##    return result
-
-def unicodeescape_string(s, size, quotes):
-
-    p = []
-    if (quotes) :
-        p += 'u'
-        if (s.find('\'')!=-1 and s.find('"')==-1):
-            p += '"' 
-        else:
-            p += '\''
-    pos = 0
-    while (pos < size):
-        ch = s[pos]
-        #/* Escape quotes */
-        if (quotes and (ch == p[1] or ch == '\\')):
-            p += '\\'
-            p += ch
-            pos += 1
-            continue
-
-#ifdef Py_UNICODE_WIDE
-        #/* Map 21-bit characters to '\U00xxxxxx' */
-        elif (ord(ch) >= 0x10000):
-            p += '\\'
-            p += 'U'
-            p += '%08x'%ord(ch)
-            pos += 1
-            continue        
-#endif
-	#/* Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes */
-        elif (ord(ch) >= 0xD800 and ord(ch) < 0xDC00):
-            pos += 1
-            ch2 = s[pos]
-	    
-            if (ord(ch2) >= 0xDC00 and ord(ch2) <= 0xDFFF):
-                ucs = (((ord(ch) & 0x03FF) << 10) | (ord(ch2) & 0x03FF)) + 0x00010000
-                p += '\\'
-                p += 'U'
-                p += '%08x'%ucs
-                pos += 1
-                continue
-	   
-	    #/* Fall through: isolated surrogates are copied as-is */
-	    pos -= 1
-	    
-        #/* Map 16-bit characters to '\uxxxx' */
-        if (ord(ch) >= 256):
-            p += '\\'
-            p += 'u'
-            p += '%04x'%ord(ch)
-            
-        #/* Map special whitespace to '\t', \n', '\r' */
-        elif (ch == '\t'):
-            p += '\\'
-            p += 't'
-        
-        elif (ch == '\n'):
-            p += '\\'
-            p += 'n'
-
-        elif (ch == '\r'):
-            p += '\\'
-            p += 'r'
-
-        #/* Map non-printable US ASCII to '\xhh' */
-        elif (ch < ' ' or ch >= 0x7F) :
-            p += '\\'
-            p += 'x'
-            p += '%02x'%ord(ch)
-        #/* Copy everything else as-is */
-        else:
-            p += chr(ord(ch))
-        pos += 1
-    if (quotes):
-        p += p[1]
-    return p
-
-def PyUnicode_DecodeASCII(s, size, errors):
-
-#    /* ASCII is equivalent to the first 128 ordinals in Unicode. */
-    if (size == 1 and ord(s) < 128) :
-        return [unichr(ord(s))]
-    if (size == 0):
-        return [u''] #unicode('')
-    p = []
-    pos = 0
-    while pos < len(s):
-        c = s[pos]
-        if ord(c) < 128:
-            p += unichr(ord(c))
-            pos += 1
-        else:
-            
-            res = unicode_call_errorhandler(
-                    errors, "ascii", "ordinal not in range(128)",
-                    s,  pos, pos+1)
-            p += [unichr(ord(x)) for x in res[0]]
-            pos = res[1]
-    return p
-
-def PyUnicode_EncodeASCII(p,size,errors):
-
-    return unicode_encode_ucs1(p, size, errors, 128)
-
-def PyUnicode_AsASCIIString(unistr):
-
-    if not type(unistr) == unicode:
-        raise TypeError
-    return PyUnicode_EncodeASCII(unicode(unistr),
-				 len(unicode),
-				None)
-
-def PyUnicode_DecodeUTF16Stateful(s,size,errors,byteorder='native',consumed=None):
-
-    bo = 0       #/* assume native ordering by default */
-    errmsg = ""
-
-    if sys.byteorder == 'little':
-        ihi = 1
-        ilo = 0
-    else:
-        ihi = 0
-        ilo = 1
-    
-    if (size == 0):
-        return [u'']
-
-    #/* Unpack UTF-16 encoded data */
-
-##    /* Check for BOM marks (U+FEFF) in the input and adjust current
-##       byte order setting accordingly. In native mode, the leading BOM
-##       mark is skipped, in all other modes, it is copied to the output
-##       stream as-is (giving a ZWNBSP character). */
-    q = 0
-    p = []
-    if byteorder == 'native':
-        if (size >= 2):
-            bom = (ord(s[ihi]) << 8) | ord(s[ilo])
-#ifdef BYTEORDER_IS_LITTLE_ENDIAN
-            if sys.byteorder == 'little':
-        	    if (bom == 0xFEFF):
-        	        q += 2
-        	        bo = -1
-        	    elif bom == 0xFFFE:
-        	        q += 2
-        	        bo = 1
-            else:
-        	    if bom == 0xFEFF:
-        	        q += 2
-        	        bo = 1
-        	    elif bom == 0xFFFE:
-        	        q += 2
-        	        bo = -1
-    elif byteorder == 'little':
-        bo = -1
-    else:
-        bo = 1
-        
-    if (bo == -1):
-        #/* force LE */
-        ihi = 1
-        ilo = 0
-
-    elif (bo == 1):
-        #/* force BE */
-        ihi = 0
-        ilo = 1
-
-    while (q < len(s)):
-    
-    	#/* remaining bytes at the end? (size should be even) */
-    	if (len(s)-q<2):
-    	    if (consumed):
-                break
-    	    errmsg = "truncated data"
-    	    startinpos = q
-    	    endinpos = len(s)
-    	    unicode_call_errorhandler()
-##    	    /* The remaining input chars are ignored if the callback
-##    	       chooses to skip the input */
-    
-    	ch = (ord(s[q+ihi]) << 8) | ord(s[q+ilo])
-    	q += 2
-    
-    	if (ch < 0xD800 or ch > 0xDFFF):
-    	   p += unichr(ch)
-    	   continue
-    
-	#/* UTF-16 code pair: */
-        if (q >= len(s)):
-            errmsg = "unexpected end of data"
-            startinpos = q-2
-            endinpos = len(s)
-            unicode_call_errorhandler
-
-    	if (0xD800 <= ch and ch <= 0xDBFF):
-            ch2 = (ord(s[q+ihi]) << 8) | ord(s[q+ilo])
-            q += 2
-            if (0xDC00 <= ch2 and ch2 <= 0xDFFF):
-    #ifndef Py_UNICODE_WIDE
-                if sys.maxunicode < 65536:
-                    p += unichr(ch)
-                    p += unichr(ch2)
-                else:
-                    p += unichr((((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000)
-    #endif
-                continue
-
-            else:
-    	        errmsg = "illegal UTF-16 surrogate"
-                startinpos = q-4
-                endinpos = startinpos+2
-                unicode_call_errorhandler
-    	   
-	errmsg = "illegal encoding"
-	startinpos = q-2
-	endinpos = startinpos+2
-	unicode_call_errorhandler
-	
-    return p
-
-def PyUnicode_EncodeUTF16(s,size,errors,byteorder='little'):
-
-#    /* Offsets from p for storing byte pairs in the right order. */
-
-    def STORECHAR(CH,byteorder):
-        hi = chr(((CH) >> 8) & 0xff)
-        lo = chr((CH) & 0xff)
-        if byteorder == 'little':
-            return [lo,hi]
-        else:
-            return [hi,lo]
-        
-    p = []
-    bom = sys.byteorder
-    if (byteorder == 'native'):
-        
-        bom = sys.byteorder
-        p += STORECHAR(0xFEFF,bom)
-        
-    if (size == 0):
-        return ""
-
-    if (byteorder == 'little' ):
-        bom = 'little'
-    elif (byteorder == 'big'):
-        bom = 'big'
-
-
-    for c in s:
-        ch = ord(c)
-        ch2 = 0
-        if (ch >= 0x10000) :
-            ch2 = 0xDC00 | ((ch-0x10000) & 0x3FF)
-            ch  = 0xD800 | ((ch-0x10000) >> 10)
-
-        p += STORECHAR(ch,bom)
-        if (ch2):
-            p +=STORECHAR(ch2,bom)
-
-    return p
-
-
-def PyUnicode_DecodeMBCS(s, size, errors):
-    pass
-
-def PyUnicode_EncodeMBCS(p, size, errors):
-    pass
-####    /* If there are no characters, bail now! */
-##    if (size==0)
-##	    return ""
-##    from ctypes import *
-##    WideCharToMultiByte = windll.kernel32.WideCharToMultiByte
-####    /* First get the size of the result */
-##    mbcssize = WideCharToMultiByte(CP_ACP, 0, p, size, s, 0, None, None);
-##    if (mbcssize==0)
-##        raise UnicodeEncodeError, "Windows cannot decode the string %s" %p
-### More error handling required (check windows errors and such)
-##    
-###    /* Do the conversion */
-####    s = ' '*mbcssize
-####    if (0 == WideCharToMultiByte(CP_ACP, 0, p, size, s, mbcssize, NULL, NULL)):
-####        raise UnicodeEncodeError, "Windows cannot decode the string %s" %p
-##    return s
-def unicode_call_errorhandler(errors,  encoding, 
-                reason, input, startinpos, endinpos,decode=True):
-    
-    errorHandler = lookup_error(errors)
-    if decode:
-        exceptionObject = UnicodeDecodeError(encoding, input, startinpos, endinpos, reason)
-    else:
-        exceptionObject = UnicodeEncodeError(encoding, input, startinpos, endinpos, reason)
-    res = errorHandler(exceptionObject)
-    if isinstance(res,tuple) and isinstance(res[0],unicode) and isinstance(res[1],int):
-        newpos = res[1]
-        if (newpos<0):
-            newpos = len(input)+newpos
-        if newpos<0 or newpos>len(input):
-            raise IndexError( "position %d from error handler out of bounds" % newpos)
-        return res[0],newpos
-    else:
-        raise TypeError("encoding error handler must return (unicode, int) tuple")
-
-def PyUnicode_DecodeUTF8(s, size, errors):
-
-    return PyUnicode_DecodeUTF8Stateful(s, size, errors, None)
-
-##    /* Map UTF-8 encoded prefix byte to sequence length.  zero means
-##       illegal prefix.  see RFC 2279 for details */
-utf8_code_length = [
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0
-]
-
-def PyUnicode_DecodeUTF8Stateful(s,size,errors,consumed):
-    
-    if (size == 0):
-        if (consumed):
-            consumed = 0
-        return u''
-    
-    p = []
-    pos = 0
-    while pos < size:
-        ch = s[pos]
-        if ord(ch) < 0x80:
-            p += ch
-            pos += 1
-            continue
-        
-        n = utf8_code_length[ord(ch)]
-        startinpos =  pos 
-        if (startinpos + n > size):
-            if (consumed):
-                break
-            else:
-                errmsg = "unexpected end of data"
-                endinpos = size 
-                res = unicode_call_errorhandler(
-                                    errors, "utf8", errmsg,
-                                    s,  startinpos, endinpos)
-                p += res[0]
-                pos = res[1]
-        if n == 0:
-            errmsg = "unexpected code byte"
-            endinpos = startinpos+1
-            res = unicode_call_errorhandler(
-                                    errors, "utf8", errmsg,
-                                    s,  startinpos, endinpos)
-            p += res[0]
-            pos = res[1]
-        elif n == 1:
-            errmsg = "internal error"
-            endinpos = startinpos+1
-            res = unicode_call_errorhandler(
-                                    errors, "utf8", errmsg,
-                                    s,  startinpos, endinpos)
-            p += res[0]
-            pos = res[1]
-        elif n == 2:
-            if ((ord(s[pos+1]) & 0xc0) != 0x80):
-                errmsg = "invalid data"
-                endinpos = startinpos+2
-                res = unicode_call_errorhandler(
-                                    errors, "utf8", errmsg,
-                                    s,  startinpos, endinpos)
-                p += res[0]
-                pos = res[1]
-            else:
-                c = ((ord(s[pos]) & 0x1f) << 6) + (ord(s[pos+1]) & 0x3f)
-                if c<0x80:
-                    errmsg = "illegal encoding"
-                    endinpos = startinpos+2
-                    res = unicode_call_errorhandler(
-                                            errors, "utf8", errmsg,
-                                            s,  startinpos, endinpos)
-                    p += res[0]
-                    pos = res[1]
-                else:
-                    p += unichr(c)
-                    pos += n
-                    #break
-        elif n == 3:
-            if ((ord(s[pos+1]) & 0xc0) != 0x80 or
-                    (ord(s[pos+2]) & 0xc0) != 0x80):
-                errmsg = "invalid data"
-                endinpos = startinpos+3
-                res = unicode_call_errorhandler(
-                                            errors, "utf8", errmsg,
-                                            s,  startinpos, endinpos)
-                p += res[0]
-                pos = res[1]
-            else:
-                c = ((ord(s[pos]) & 0x0f) << 12) + \
-                        ((ord(s[pos+1]) & 0x3f) << 6) +\
-                        (ord(s[pos+2]) & 0x3f)       
-                        
-##		/* Note: UTF-8 encodings of surrogates are considered
-##		   legal UTF-8 sequences;
-##
-##		   XXX For wide builds (UCS-4) we should probably try
-##		       to recombine the surrogates into a single code
-##		       unit.
-##		*/
-                if c < 0x0800:
-                    errmsg = "illegal encoding"
-                    endinpos = startinpos+3
-                    res = unicode_call_errorhandler(
-                                        errors, "utf8", errmsg,
-                                        s,  startinpos, endinpos)
-                    p += res[0]
-                    pos = res[1]
-                else:
-                    p += unichr(c)
-                    pos += n
-        elif n == 4:
-##        case 4:
-            if ((ord(s[pos+1]) & 0xc0) != 0x80 or
-                (ord(s[pos+2]) & 0xc0) != 0x80 or
-                (ord(s[pos+3]) & 0xc0) != 0x80):
-                
-                errmsg = "invalid data"
-                startinpos = pos
-                endinpos = startinpos+4
-                res = unicode_call_errorhandler(
-                            errors, "utf8", errmsg,
-                            s,  startinpos, endinpos)
-                p += res[0]
-                pos = res[1]
-            else:
-                c = ((ord(s[pos+0]) & 0x7) << 18) + ((ord(s[pos+1]) & 0x3f) << 12) +\
-                     ((ord(s[pos+2]) & 0x3f) << 6) + (ord(s[pos+3]) & 0x3f)
-                #/* validate and convert to UTF-16 */
-                if ((c < 0x10000) or (c > 0x10ffff)):
-                    #/* minimum value allowed for 4 byte encoding */
-                    #/* maximum value allowed for UTF-16 */
-	   
-                    errmsg = "illegal encoding"
-                    startinpos = pos
-                    endinpos = startinpos+4
-                    res = unicode_call_errorhandler(
-                                            errors, "utf8", errmsg,
-                                            s,  startinpos, endinpos)
-                    p += res[0]
-                    pos = res[1]
-                else:
-#ifdef Py_UNICODE_WIDE
-                    if c<sys.maxunicode:
-                        p += unichr(c)
-                        pos += n
-                    else:
-##                /*  compute and append the two surrogates: */
-##                /*  translate from 10000..10FFFF to 0..FFFF */
-                        c -= 0x10000
-            #/*  high surrogate = top 10 bits added to D800 */
-                        p += unichr(0xD800 + (c >> 10))
-            #/*  low surrogate = bottom 10 bits added to DC00 */
-                        p += unichr(0xDC00 + (c & 0x03FF))
-                        pos += n
-        else:
-##        default:
-##            /* Other sizes are only needed for UCS-4 */
-            errmsg = "unsupported Unicode code range"
-    	    startinpos = pos
-    	    endinpos = startinpos+n
-    	    res = unicode_call_errorhandler(
-                     errors, "utf8", errmsg,
-                     s,  startinpos, endinpos)
-            p += res[0]
-            pos = res[1]
-            
-	#continue
-
-    if (consumed):
-        consumed = pos
-    return p
-
-def PyUnicode_EncodeUTF8(s,size,errors):
-
-    #assert(s != None)
-    assert(size >= 0)
-    p = []
-    i = 0
-    while i<size:
-        ch = s[i]
-        i+=1
-        if (ord(ch) < 0x80):
-##         /* Encode ASCII */
-            p += chr(ord(ch))
-        elif (ord(ch) < 0x0800) :
-##            /* Encode Latin-1 */
-            p += chr((0xc0 | (ord(ch) >> 6)))
-            p += chr((0x80 | (ord(ch) & 0x3f)))
-        else:
-##            /* Encode UCS2 Unicode ordinals */
-            if (ord(ch) < 0x10000):
-##                /* Special case: check for high surrogate */
-                if (0xD800 <=ord(ch) and ord(ch) <= 0xDBFF and i != size) :
-                    ch2 = s[i]
-##                    /* Check for low surrogate and combine the two to
-##                       form a UCS4 value */
-                    if (0xDC00 <= ord(ch2) and ord(ch2) <= 0xDFFF) :
-                        ch3 = ((ord(ch) - 0xD800) << 10 | (ord(ch2) - 0xDC00)) + 0x10000
-                        i+=1
-                        p.extend(encodeUCS4(ch3))
-                        continue
-##                    /* Fall through: handles isolated high surrogates */
-                p += (chr((0xe0 | (ord(ch) >> 12))))
-                p += (chr((0x80 | ((ord(ch) >> 6) & 0x3f))))
-                p += (chr((0x80 | (ord(ch) & 0x3f))))
-                continue
-    return p
-
-def encodeUCS4(ch):
-##      /* Encode UCS4 Unicode ordinals */
-    p=[]
-    p +=  (chr((0xf0 | (ch >> 18))))
-    p +=  (chr((0x80 | ((ch >> 12) & 0x3f))))
-    p +=  (chr((0x80 | ((ch >> 6) & 0x3f))))
-    p +=  (chr((0x80 | (ch & 0x3f))))
-    return p
-
-#/* --- Latin-1 Codec ------------------------------------------------------ */
-
-def PyUnicode_DecodeLatin1(s, size, errors):
-    #/* Latin-1 is equivalent to the first 256 ordinals in Unicode. */
-##    if (size == 1):
-##        return [PyUnicode_FromUnicode(s, 1)]
-    pos = 0
-    p = []
-    while (pos < size):
-        p += unichr(ord(s[pos]))
-        pos += 1
-    return p
-
-def unicode_encode_ucs1(p,size,errors,limit):
-    
-    if limit == 256:
-        reason = "ordinal not in range(256)"
-        encoding = "latin-1"
-    else:
-        reason = "ordinal not in range(128)"
-        encoding = "ascii"
-    
-    if (size == 0):
-        return ['']
-    res = []
-    pos=0
-    while pos < len(p):
-    #for ch in p:
-        ch = p[pos]
-        
-        if ord(ch) < limit:
-            res += chr(ord(ch))
-            pos += 1
-        else:
-            #/* startpos for collecting unencodable chars */
-            collstart = pos 
-            collend = pos+1 
-            while collend < len(p) and ord(p[collend]) >= limit:
-                collend += 1
-            x = unicode_call_errorhandler(errors,encoding,reason,p,collstart,collend,False)
-            res += str(x[0])
-            pos = x[1]
-    
-    return res
-
-def PyUnicode_EncodeLatin1(p,size,errors):
-    res=unicode_encode_ucs1(p, size, errors, 256)
-    return res
-
-hexdigits = [hex(i)[-1] for i in range(16)]+[hex(i)[-1].upper() for i in range(10,16)]
-def hexescape(s,pos,digits,message,errors):
-    chr = 0
-    p = []
-    if (pos+digits>len(s)):
-        message = "end of string in escape sequence"
-        x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2,len(s))
-        p += x[0]
-        pos = x[1]
-    else:
-        try:
-            chr = int(s[pos:pos+digits],16)
-        except ValueError:
-            endinpos = pos
-            while s[endinpos] in hexdigits: 
-                endinpos +=1
-            x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2,
-                        endinpos+1)
-            p += x[0]
-            pos = x[1]
-        #/* when we get here, chr is a 32-bit unicode character */
-        else:
-            if chr <= sys.maxunicode:
-                p += [unichr(chr)]
-                pos += digits
-            
-            elif (chr <= 0x10ffff):
-                chr -= 0x10000L
-                p += unichr(0xD800 + (chr >> 10))
-                p += unichr(0xDC00 +  (chr & 0x03FF))
-                pos += digits
-            else:
-                message = "illegal Unicode character"
-                x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2,
-                        pos+1)
-                p += x[0]
-                pos = x[1]
-    res = p
-    return res,pos
-
-def PyUnicode_DecodeUnicodeEscape(s, size, errors):
-
-    if (size == 0):
-        return u''
-    
-    p = []
-    pos = 0
-    while (pos < size): 
-##        /* Non-escape characters are interpreted as Unicode ordinals */
-        if (s[pos] != '\\') :
-            p += s[pos]
-            pos += 1
-            continue
-##        /* \ - Escapes */
-        else:
-            pos +=1
-            if pos>=len(s):
-                errmessage = "\\ at end of string"
-                unicode_call_errorhandler(errors,"unicodeescape",errmessage,s,pos-1,size)
-            ch = s[pos]
-            pos += 1
-    ##        /* \x escapes */
-            #if ch == '\n': break;
-            if ch == '\\': p += '\\'
-            elif ch == '\'': p += '\''
-            elif ch == '\"': p += '\"' 
-            elif ch == 'b': p += '\b' 
-            elif ch == 'f': p += '\014' #/* FF */
-            elif ch == 't': p += '\t' 
-            elif ch == 'n': p += '\n'
-            elif ch == 'r': 
-                p += '\r' 
-                
-            elif ch == 'v': p += '\013' #break; /* VT */
-            elif ch == 'a': p += '\007' # break; /* BEL, not classic C */
-    
-    ##        /* \OOO (octal) escapes */
-            elif ch in [ '0','1', '2', '3','4', '5', '6','7']:
-                x = ord(ch) - ord('0')
-                ch = s[pos]
-                if ('0' <= ch and ch <= '7'):
-                    x = (x<<3) + ord(ch) - ord('0')
-                    ch = s[pos+1]
-                    if ('0' <= ch and ch <= '7'):
-                        x = (x<<3) + ord(ch) - ord('0')
-                        pos += 2
-    
-                p += unichr(x)
-    ##        /* hex escapes */
-    ##        /* \xXX */
-            elif ch == 'x':
-                digits = 2
-                message = "truncated \\xXX escape"
-                x = hexescape(s,pos,digits,message,errors)
-                p += x[0]
-                pos = x[1]
-    
-         #   /* \uXXXX */
-            elif ch == 'u':
-                digits = 4
-                message = "truncated \\uXXXX escape"
-                x = hexescape(s,pos,digits,message,errors)
-                p += x[0]
-                pos = x[1]
-    
-          #  /* \UXXXXXXXX */
-            elif ch == 'U':
-                digits = 8
-                message = "truncated \\UXXXXXXXX escape"
-                x = hexescape(s,pos,digits,message,errors)
-                p += x[0]
-                pos = x[1]
-##        /* \N{name} */
-            elif ch == 'N':
-                message = "malformed \\N character escape"
-                #pos += 1
-                try:
-                    import unicodedata
-                except ImportError:
-                    message = "\\N escapes not supported (can't load unicodedata module)"
-                    unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-1,size)
-                if (s[pos] == '{'):
-                    look = pos+1
-                    #/* look for the closing brace */
-                    while (s[look] != '}' and look < size):
-                        look += 1
-                    if (look > pos+1 and look < size and s[look] == '}'):
-                        #/* found a name.  look it up in the unicode database */
-                        message = "unknown Unicode character name"
-                        look += 1
-                        try:
-                            chr = unicodedata.lookup(s[pos:look])
-                            #x = hexescape(chr,pos+1,8,message,errors)
-                        except KeyError:
-                            x=unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-1,look)
-                        else:
-                            x = hexescape(s,pos+1,look-pos,message,errors)
-                        p += x[0]
-                        pos = x[1]
-            else:
-                if (pos > size):
-                    message = "\\ at end of string"
-                    handler = lookup_error(errors)
-                    x = handler(UnicodeDecodeError("unicodeescape",s,pos,
-                                size,message))
-                    p += x[0]
-                    pos = x[1]
-                else:
-                    p += '\\'
-                    p += s[pos]
-    return p
-
-def PyUnicode_EncodeRawUnicodeEscape(s,size):
-    
-    if (size == 0):
-        return ''
-
-    p = []
-    for ch in s:
-#	/* Map 32-bit characters to '\Uxxxxxxxx' */
-        if (ord(ch) >= 0x10000):
-            p += '\\'
-            p += 'U'
-            p += '%08x'%(ord(ch))
-        elif (ord(ch) >= 256) :
-#	/* Map 16-bit characters to '\uxxxx' */
-            p += '\\'
-            p += 'u'
-            p += '%04x'%(ord(ch))
-#	/* Copy everything else as-is */
-        else:
-            p += chr(ord(ch))
-    
-    #p += '\0'
-    return p
-
-def charmapencode_output(c,mapping):
-
-    
-    rep = mapping[c]
-    if isinstance(rep,(int,long)):
-        if rep<256:
-            return chr(rep)
-        else:
-            raise TypeError("character mapping must be in range(256)")
-    elif isinstance(rep,str):
-        return rep
-    elif rep == None:
-        raise KeyError("character maps to <undefined>")
-    else:
-        raise TypeError("character mapping must return integer, None or str")
-
-def PyUnicode_EncodeCharmap(p,size,mapping='latin-1',errors='strict'):
-
-##    /* the following variable is used for caching string comparisons
-##     * -1=not initialized, 0=unknown, 1=strict, 2=replace,
-##     * 3=ignore, 4=xmlcharrefreplace */
-
-#    /* Default to Latin-1 */
-    if mapping == 'latin-1':
-        return PyUnicode_EncodeLatin1(p, size, errors)
-    if (size == 0):
-        return ''
-    inpos = 0
-    res = []
-    while (inpos<size):
-	#/* try to encode it */
-        try:
-            x = charmapencode_output(ord(p[inpos]),mapping)
-            res += [x]
-        except KeyError:
-            x = unicode_call_errorhandler(errors,"charmap",
-            "character maps to <undefined>",p,inpos,inpos+1,False)
-            try:
-                res += [charmapencode_output(ord(y),mapping) for y in x[0]]
-            except KeyError:
-                raise UnicodeEncodeError("charmap",p,inpos,inpos+1,
-                                        "character maps to <undefined>")
-##        except TypeError,err:
-##            x = unicode_call_errorhandler(errors,"charmap",
-##            err,p,inpos,inpos+1,False)
-##            try:
-##                res += [charmapencode_output(ord(y),mapping) for y in x[0]]
-##            except KeyError:
-##                raise UnicodeEncodeError("charmap",p,inpos,inpos+1,
-##                                        "character maps to <undefined>")
-##    
-	    #/* done with this character => adjust input position */
-        inpos+=1
-    return res
-
-def PyUnicode_DecodeCharmap(s, size, mapping, errors):
-
-##    /* Default to Latin-1 */
-    if (mapping == None):
-        return PyUnicode_DecodeLatin1(s, size, errors)
-
-    if (size == 0):
-        return u''
-    p = []
-    inpos = 0
-    while (inpos< len(s)):
-	
-	#/* Get mapping (char ordinal -> integer, Unicode char or None) */
-        ch = s[inpos]
-        try:
-            x = mapping[ord(ch)]
-            if isinstance(x,int):
-                if x<65536:
-                    p += unichr(x)
-                else:
-                    raise TypeError("character mapping must be in range(65536)")
-            elif isinstance(x,unicode):
-                p += x
-            elif not x:
-                raise KeyError
-            else:
-                raise TypeError
-        except KeyError:
-            x = unicode_call_errorhandler(errors,"charmap",
-                "character maps to <undefined>",s,inpos,inpos+1)
-            p += x[0]
-##        except TypeError:
-##            x = unicode_call_errorhandler(errors,"charmap",
-##                "character mapping must return integer, None or unicode",
-##                s,inpos,inpos+1)
-##            p += x[0]
-        inpos +=1
-    return p
-
-def PyUnicode_DecodeRawUnicodeEscape(s, size,errors):
-
-    if (size == 0):
-        return u''
-    pos = 0
-    p = []
-    while (pos < len(s)):
-        ch = s[pos]
-    #/* Non-escape characters are interpreted as Unicode ordinals */
-        if (ch != '\\'):
-            p += unichr(ord(ch))
-            pos += 1
-            continue        
-        startinpos = pos
-        #pos += 1
-##	/* \u-escapes are only interpreted iff the number of leading
-##	   backslashes is odd */
-        bs = pos
-        while pos < size:
-            if (s[pos] != '\\'):
-                break
-            p += unichr(ord(s[pos]))
-            pos += 1
-    
-        if (((pos - bs) & 1) == 0 or
-            pos >= size or
-            (s[pos] != 'u' and s[pos] != 'U')) :
-            p += s[pos]
-            pos += 1
-            continue
-        
-        p.pop(-1)
-        if s[pos] == 'u':
-            count = 4 
-        else: 
-            count = 8
-        pos += 1
-
-	#/* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */
-
-        i = 0
-        x = 0
-        try:
-            x = int(s[pos:pos+count],16)
-        except ValueError:
-            res = unicode_call_errorhandler(
-                    errors, "rawunicodeescape", "truncated \\uXXXX",
-                    s, size, pos, pos+count)
-            p += res[0]
-            pos = res[1]
-        else:
-    #ifndef Py_UNICODE_WIDE
-            if sys.maxunicode > 0xffff:
-                if (x > 0x10000):
-                    res = unicode_call_errorhandler(
-                        errors, "rawunicodeescape", "\\Uxxxxxxxx out of range",
-                        s, size, pos, pos+1)
-                    pos = i = res[1]
-                    p += res[0]
-                    i += 1
-            else:
-                if (x > 0x10000):
-                    res = unicode_call_errorhandler(
-                        errors, "rawunicodeescape", "\\Uxxxxxxxx out of range",
-                        s, size, pos, pos+1)
-                    pos = i = res[1]
-                    p += res[0]
-
-    #endif
-                else:
-                    p += unichr(x)
-                    pos += count
-
-    return p
\ No newline at end of file

Modified: pypy/branch/pycompiler/module/recparser/automata.py
==============================================================================
--- pypy/branch/pycompiler/module/recparser/automata.py	(original)
+++ pypy/branch/pycompiler/module/recparser/automata.py	Fri Jul  1 18:30:34 2005
@@ -38,9 +38,9 @@
             # arcMap, accept = self.states[crntState]
             arcMap = self.states[crntState]
             accept = self.accepts[crntState]
-            if arcMap.has_key(item):
+            if item in arcMap:
                 crntState = arcMap[item]
-            elif arcMap.has_key(DEFAULT):
+            elif DEFAULT in arcMap:
                 crntState = arcMap[DEFAULT]
             elif accept:
                 return i

Modified: pypy/branch/pycompiler/module/recparser/ebnfparse.py
==============================================================================
--- pypy/branch/pycompiler/module/recparser/ebnfparse.py	(original)
+++ pypy/branch/pycompiler/module/recparser/ebnfparse.py	Fri Jul  1 18:30:34 2005
@@ -123,8 +123,8 @@
         
     def visit_alternative( self, node ):
         items = [ node.nodes[0].visit(self) ]
-        items+= node.nodes[1].visit(self)        
-        if len(items)==1 and items[0].name.startswith(':'):
+        items += node.nodes[1].visit(self)        
+        if len(items) == 1 and items[0].name.startswith(':'):
             return items[0]
         alt = Alternative( self.new_name(), items )
         return self.new_item( alt )
@@ -143,10 +143,6 @@
     def visit_sequence_cont( self, node ):
         """Returns a list of sequences (possibly empty)"""
         return [n.visit(self) for n in node.nodes]
-##         L = []
-##         for n in node.nodes:
-##             L.append( n.visit(self) )
-##         return L
 
     def visit_seq_cont_list(self, node):
         return node.nodes[1].visit(self)

Modified: pypy/branch/pycompiler/module/recparser/grammar.py
==============================================================================
--- pypy/branch/pycompiler/module/recparser/grammar.py	(original)
+++ pypy/branch/pycompiler/module/recparser/grammar.py	Fri Jul  1 18:30:34 2005
@@ -77,7 +77,7 @@
 
 class BaseGrammarBuilder(object):
     """Base/default class for a builder"""
-    def __init__( self, rules=None, debug=0):
+    def __init__(self, rules=None, debug=0):
         self.rules = rules or {} # a dictionary of grammar rules for debug/reference
         self.debug = debug
         self.stack = []
@@ -139,7 +139,7 @@
         self._is_root = False
         self.first_set = []
         self.first_set_complete = False
-        self._processing = False
+        # self._processing = False
         self._trace = False
 
     def is_root(self):

Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py
==============================================================================
--- pypy/branch/pycompiler/module/recparser/pythonlexer.py	(original)
+++ pypy/branch/pycompiler/module/recparser/pythonlexer.py	Fri Jul  1 18:30:34 2005
@@ -73,7 +73,7 @@
 class TokenError(Exception):
     """Raised when EOF is found prematuerly"""
     def __init__(self, msg, strstart, token_stack):
-        Exception.__init__(self, msg)
+        # Exception.__init__(self, msg)
         self.strstart = strstart
         self.token_stack = token_stack
     
@@ -296,9 +296,9 @@
 
 class PythonSource(TokenSource):
     """This source uses Jonathan's tokenizer"""
-    def __init__(self, inpstring):
+    def __init__(self, strings):
         # TokenSource.__init__(self)
-        tokens, encoding = generate_tokens(inpstring.splitlines(True))
+        tokens, encoding = generate_tokens(strings) # inpstring.splitlines(True))
         self.token_stack = tokens
         self.encoding = encoding
         self._current_line = '' # the current line (as a string)

Modified: pypy/branch/pycompiler/module/recparser/pythonutil.py
==============================================================================
--- pypy/branch/pycompiler/module/recparser/pythonutil.py	(original)
+++ pypy/branch/pycompiler/module/recparser/pythonutil.py	Fri Jul  1 18:30:34 2005
@@ -1,4 +1,5 @@
-__all__ = ["python_parse", "pypy_parse","ast_single_input", "ast_file_input", "ast_eval_input" ]
+__all__ = ["python_parse", "pypy_parse","ast_single_input", "ast_file_input",
+           "ast_eval_input" ]
 
 import grammar
 import pythonparse
@@ -22,7 +23,7 @@
     pyf = file(filename)
     text = pyf.read()
     pyf.close()
-    builder = TupleBuilder( PYTHON_PARSER.rules, lineno=False)
+    builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False)
     pythonparse.parse_python_source(text, PYTHON_PARSER, 'file_input', builder)
     nested_tuples = builder.stack[-1]
     if hasattr(builder, '_source_encoding'):
@@ -30,6 +31,17 @@
         return ( symbol.encoding_decl, nested_tuples, builder._source_encoding)
     return nested_tuples
 
+def annotateme(text):
+    strings = text.split('\n')
+    builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False)
+    pythonparse.parse_python_source(text, PYTHON_PARSER, 'file_input', builder)
+##     nested_tuples = builder.stack[-1]
+##     if hasattr(builder, '_source_encoding'):
+##         # XXX: maybe the parser could fix that instead ?
+##         return ( symbol.encoding_decl, nested_tuples, builder._source_encoding)
+##     return nested_tuples
+    return 0
+
 def ast_single_input( text ):
     builder = TupleBuilder( PYTHON_PARSER.rules )
     pythonparse.parse_python_source( text, PYTHON_PARSER, "single_input", builder )

Modified: pypy/branch/pycompiler/module/recparser/tuplebuilder.py
==============================================================================
--- pypy/branch/pycompiler/module/recparser/tuplebuilder.py	(original)
+++ pypy/branch/pycompiler/module/recparser/tuplebuilder.py	Fri Jul  1 18:30:34 2005
@@ -2,8 +2,6 @@
 from grammar import BaseGrammarBuilder
 from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET
 
-
-class 
 def _expand_nodes(nodes):
     expanded = []
     for n in nodes:

Modified: pypy/branch/pycompiler/module/sys/state.py
==============================================================================
--- pypy/branch/pycompiler/module/sys/state.py	(original)
+++ pypy/branch/pycompiler/module/sys/state.py	Fri Jul  1 18:30:34 2005
@@ -76,11 +76,17 @@
 def get(space): 
     return space.fromcache(State)
 
-def pypy_getudir(space):
+def _pypy_getudir(space):
     """NOT_RPYTHON"""
     from pypy.tool.udir import udir
     return space.wrap(str(udir))
-pypy_getudir._annspecialcase_ = "override:ignore"
+_pypy_getudir._annspecialcase_ = "override:ignore"
+
+# we need the inderaction because this function will live in a dictionary with other 
+# RPYTHON functions and share call sites with them. Better it not be a special-case
+# directly. 
+def pypy_getudir(space):
+    return _pypy_getudir(space)
 
 def getdefaultencoding(space): 
     return space.wrap(sys.getdefaultencoding())

Deleted: /pypy/branch/pycompiler/objspace/dummy.py
==============================================================================
--- /pypy/branch/pycompiler/objspace/dummy.py	Fri Jul  1 18:30:34 2005
+++ (empty file)
@@ -1,146 +0,0 @@
-from pypy.interpreter.baseobjspace import ObjSpace, W_Root, BaseWrappable
-from pypy.interpreter.module import Module
-from pypy.interpreter.error import OperationError
-
-from pypy.tool.cache import Cache
-
-class W_Obj(W_Root):
-    
-    def is_true(self):
-        return True
-
-    def str_w(self, space):
-        raise OperationError(space.w_TypeError,space.wrap("!")) 
-
-    def int_w(self, space):
-        raise OperationError(space.w_TypeError,space.wrap("!")) 
-
-    def float_w(self, space):
-        raise OperationError(space.w_TypeError,space.wrap("!")) 
-
-    def unwrap(self, space):
-        raise OperationError(space.w_TypeError,space.wrap("!")) 
-
-class W_Str(W_Obj):
-    def __init__(self, s):
-        self.s = s
-
-    def is_true(self):
-        return self.s != ""
-
-    def str_w(self, space):
-        return self.s
-
-    def unwrap(self, space):
-        return self.s
-
-class W_Int(W_Obj):
-    def __init__(self, i):
-        self.i = i
-
-    def is_true(self):
-        return self.i != 0
-
-    def int_w(self, space):
-        return self.i
-
-    def unwrap(self, space):
-        return self.i
-
-class W_None(W_Obj):
-    
-    def unwrap(self, space):
-        return None
-
-class W_Special(W_Obj):
-    def __init__(self, spec):
-        self.spec = spec
-
-class BuiltinModule(Module):
-    def __init__(self, space):
-        Module.__init__(self, space, space.wrap('__builtin__'), space.wrap({}))
-
-    def pick_builtin(self, w_globals):
-        return self
-    
-class DummyObjSpace(ObjSpace):
-
-    def __init__(self):
-        """NOT_RPYTHON"""
-        self.builtin    = BuiltinModule(self)
-
-        self.sys    = Module(self, self.wrap('sys'), self.wrap({}))
-        self.sys.recursionlimit = 1000
-
-        self.w_None = W_None()
-        self.w_NotImplemented = W_Special(NotImplemented)
-        self.w_Ellpisis = W_Special(Ellipsis)
-        self.w_False = self.wrap(0)
-        self.w_True = self.wrap(1)
-        self.w_tuple = W_Special(tuple)
-        self.w_type = W_Special(type)
-        self.w_str = W_Special(str)
-
-        for en in ObjSpace.ExceptionTable:
-            setattr(self, 'w_'+en, self.wrap(en))
-
-        self._gatewaycache = Cache()
-
-    for n, symbol, arity, ign in ObjSpace.MethodTable+[('newdict',"",1,[]), ('newlist',"",1,[]),
-                                                       ('newtuple',"",1,[]), ('newslice',"",3,[]), ]:
-        source = ("""if 1:
-        def %s(self, %s):
-            return W_Root()
-""" % (n, ', '.join(["w_a%d" % i for i in range(arity)])))
-        #print source
-        exec source
-
-    del n, symbol, arity, ign, i
-        
-    def wrap(self, obj):
-        if obj is None:
-            return self.w_None
-        if isinstance(obj, str):
-            return W_Str(obj)
-        if isinstance(obj, int):
-            return W_Int(obj)
-        return W_Root()
-    wrap._specialize_ = "argtypes"
-
-    def call_args(self, w_obj, args):
-        return W_Root()
-    
-    def is_true(self, w_obj):
-        if isinstance(w_obj, W_Obj):
-            return w_obj.is_true()
-        return True
-
-    def str_w(self, w_obj):
-        if not isinstance(w_obj, W_Obj):
-            w_obj = self.w_None
-        
-        return w_obj.str_w(self)
-
-    def int_w(self, w_obj):
-        if not isinstance(w_obj, W_Obj):
-            w_obj = self.w_None
-        
-        return w_obj.int_w(self)
-
-    def float_w(self, w_obj):
-        if not isinstance(w_obj, W_Obj):
-            w_obj = self.w_None
-               
-        return w_obj.float_w(self)
-
-    def unwrap(self, w_obj):
-        if isinstance(w_obj, BaseWrappable):
-            return w_obj
-        return w_obj.unwrap()
-
-    def _freeze_(self):
-        return True
-
-if __name__ == '__main__':
-  dummy_space = DummyObjSpace()
-  print dummy_space.eval("a+b",dummy_space.wrap({'a': 1,'b': 2}),dummy_space.wrap({}))

Modified: pypy/branch/pycompiler/objspace/flow/flowcontext.py
==============================================================================
--- pypy/branch/pycompiler/objspace/flow/flowcontext.py	(original)
+++ pypy/branch/pycompiler/objspace/flow/flowcontext.py	Fri Jul  1 18:30:34 2005
@@ -20,8 +20,9 @@
 
 
 class SpamBlock(Block):
-    
-    __slots__ = "dead framestate fillcolor".split()
+    # make slots optional, for debugging
+    if hasattr(Block, '__slots__'):
+        __slots__ = "dead framestate fillcolor".split()
 
     def __init__(self, framestate):
         Block.__init__(self, framestate.getvariables())
@@ -36,8 +37,9 @@
 
 
 class EggBlock(Block):
-
-    __slots__ = "prevblock booloutcome last_exception fillcolor".split()
+    # make slots optional, for debugging
+    if hasattr(Block, '__slots__'):
+        __slots__ = "prevblock booloutcome last_exception fillcolor".split()
 
     def __init__(self, inputargs, prevblock, booloutcome):
         Block.__init__(self, inputargs)

Modified: pypy/branch/pycompiler/objspace/flow/model.py
==============================================================================
--- pypy/branch/pycompiler/objspace/flow/model.py	(original)
+++ pypy/branch/pycompiler/objspace/flow/model.py	Fri Jul  1 18:30:34 2005
@@ -31,7 +31,6 @@
 __metaclass__ = type
 
 class FunctionGraph(object):
-    __slots__ = """func source name startblock returnblock exceptblock""".split()
     
     def __init__(self, name, startblock, return_var=None):
         self.name        = name    # function name (possibly mangled already)
@@ -304,9 +303,9 @@
 
 class Atom:
     def __init__(self, name):
-        self.name = name
+        self.__name__ = name # make save_global happy
     def __repr__(self):
-        return self.name
+        return self.__name__
 
 last_exception = Atom('last_exception')
 # if Block().exitswitch == Constant(last_exception), it means that we are
@@ -331,11 +330,6 @@
 import inspect   # for getmro
 
 class traverse:
-    edgedef = {
-        FunctionGraph : ('startblock',),
-        Block : ('exits',),
-        Link : ('target',),
-        }
 
     def __init__(self, visitor, functiongraph):
         """ send the visitor over all (reachable) nodes. 
@@ -343,6 +337,7 @@
             or otherwise is callable itself.  
         """
         self.visitor = visitor
+        self.visitor_cache = {}
         self.seen = {}
         self.visit(functiongraph)
 
@@ -352,26 +347,32 @@
 
         # do the visit
         cls = node.__class__
-        for subclass in inspect.getmro(cls):
-            consume = getattr(self.visitor, "visit_" + subclass.__name__, None)
-            if consume:
-                break
-        else:
-            consume = getattr(self.visitor, 'visit', self.visitor)
+        try:
+            consume = self.visitor_cache[cls]
+        except KeyError:
+            for subclass in inspect.getmro(cls):
+                consume = getattr(self.visitor, "visit_" + subclass.__name__, None)
+                if consume:
+                    break
+            else:
+                consume = getattr(self.visitor, 'visit', self.visitor)
+
+                assert callable(consume), "visitor not found for %r on %r" % (cls, self.visitor)
+
+                self.visitor_cache[cls] = consume
 
-        assert callable(consume), "visitor not found for %r on %r" % (cls, self.visitor)
         self.seen[id(node)] = consume(node)
 
         # recurse
-        for dispclass, attrs in self.edgedef.items():
-            for subclass in inspect.getmro(cls):
-                if subclass == dispclass:
-                    for attr in attrs:
-                        for obj in flattenobj(getattr(node, attr)):
-                            self.visit(obj)
-                    return
-
-        raise ValueError, "could not dispatch %r" % cls
+        if isinstance(node, Block):
+            for obj in node.exits:
+                self.visit(obj)
+        elif isinstance(node, Link):
+            self.visit(node.target)
+        elif isinstance(node, FunctionGraph):
+            self.visit(node.startblock)
+        else:
+            raise ValueError, "could not dispatch %r" % cls
 
 def flatten(funcgraph):
     l = []

Modified: pypy/branch/pycompiler/objspace/flow/objspace.py
==============================================================================
--- pypy/branch/pycompiler/objspace/flow/objspace.py	(original)
+++ pypy/branch/pycompiler/objspace/flow/objspace.py	Fri Jul  1 18:30:34 2005
@@ -465,11 +465,12 @@
                    inplace_add inplace_sub inplace_mul inplace_truediv
                    inplace_floordiv inplace_div inplace_mod inplace_divmod
                    inplace_pow""", FloatingPointError)
-_add_except_ovf("""neg abs invert add sub mul truediv
-                   floordiv div mod divmod pow lshift
+_add_exceptions("""truediv divmod
                    inplace_add inplace_sub inplace_mul inplace_truediv
                    inplace_floordiv inplace_div inplace_mod inplace_pow
-                   inplace_lshift""")
+                   inplace_lshift""", OverflowError) # without a _ovf version
+_add_except_ovf("""neg abs add sub mul
+                   floordiv div mod pow lshift""")   # with a _ovf version
 del _add_exceptions, _add_except_ovf
 
 def extract_cell_content(c):

Modified: pypy/branch/pycompiler/objspace/flow/operation.py
==============================================================================
--- pypy/branch/pycompiler/objspace/flow/operation.py	(original)
+++ pypy/branch/pycompiler/objspace/flow/operation.py	Fri Jul  1 18:30:34 2005
@@ -5,6 +5,7 @@
 from pypy.interpreter.baseobjspace import ObjSpace
 import operator, types, __future__
 from pypy.tool.sourcetools import compile2
+from pypy.rpython.rarithmetic import ovfcheck, ovfcheck_lshift
 
 FunctionByName = {}   # dict {"operation_name": <built-in function>}
 OperationName  = {}   # dict {<built-in function>: "operation_name"}
@@ -100,12 +101,44 @@
 def userdel(x):
     x.__del__()
 
+def neg_ovf(x):
+    return ovfcheck(-x)
+
+def abs_ovf(x):
+    return ovfcheck(abs(x))
+
+def add_ovf(x, y):
+    return ovfcheck(x + y)
+
+def sub_ovf(x, y):
+    return ovfcheck(x - y)
+
+def mul_ovf(x, y):
+    return ovfcheck(x * y)
+
+def floordiv_ovf(x, y):
+    return ovfcheck(operator.floordiv(x, y))
+
+def div_ovf(x, y):
+    return ovfcheck(operator.div(x, y))
+
+def mod_ovf(x, y):
+    return ovfcheck(x % y)
+
+def pow_ovf(*two_or_three_args):
+    return ovfcheck(pow(*two_or_three_args))
+
+def lshift_ovf(x, y):
+    return ovfcheck_lshift(x, y)
+
 # ____________________________________________________________
 
 # The following table can list several times the same operation name,
 # if multiple built-in functions correspond to it.  The first one should
 # be picked, though, as the best built-in for the given operation name.
 # Lines ('name', operator.name) are added automatically.
+
+# INTERNAL ONLY, use the dicts declared at the top of the file.
 Table = [
     ('id',              id),
     ('type',            new_style_type),
@@ -120,6 +153,8 @@
     ('delattr',         delattr),
     ('nonzero',         bool),
     ('nonzero',         operator.truth),
+    ('is_true',         bool),
+    ('is_true',         operator.truth),
     ('abs' ,            abs),
     ('hex',             hex),
     ('oct',             oct),
@@ -150,6 +185,17 @@
     ('set',             set),
     ('delete',          delete),
     ('userdel',         userdel),
+    # --- operations added by graph transformations ---
+    ('neg_ovf',         neg_ovf),
+    ('abs_ovf',         abs_ovf),
+    ('add_ovf',         add_ovf),
+    ('sub_ovf',         sub_ovf),
+    ('mul_ovf',         mul_ovf),
+    ('floordiv_ovf',    floordiv_ovf),
+    ('div_ovf',         div_ovf),
+    ('mod_ovf',         mod_ovf),
+    ('pow_ovf',         pow_ovf),
+    ('lshift_ovf',      lshift_ovf),
     ]
 
 def setup():
@@ -164,11 +210,12 @@
     for name, func in Table:
         if name not in FunctionByName:
             FunctionByName[name] = func
-        assert func not in OperationName
-        OperationName[func] = name
+        if func not in OperationName:
+            OperationName[func] = name
     # check that the result is complete
     for line in ObjSpace.MethodTable:
         name = line[0]
         Arity[name] = line[2]
         assert name in FunctionByName
 setup()
+del Table   # INTERNAL ONLY, use the dicts declared at the top of the file

Modified: pypy/branch/pycompiler/objspace/std/floatobject.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/floatobject.py	(original)
+++ pypy/branch/pycompiler/objspace/std/floatobject.py	Fri Jul  1 18:30:34 2005
@@ -241,7 +241,7 @@
 def nonzero__Float(space, w_float):
     return space.newbool(w_float.floatval != 0.0)
 
-######## coersion must be done later
+######## coercion must be done later
 later = """
 def float_coerce(space, w_float):
     if w_float.__class__ == W_FloatObject:

Modified: pypy/branch/pycompiler/objspace/std/floattype.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/floattype.py	(original)
+++ pypy/branch/pycompiler/objspace/std/floattype.py	Fri Jul  1 18:30:34 2005
@@ -1,21 +1,22 @@
 from pypy.objspace.std.stdtypedef import *
 from pypy.interpreter.error import OperationError
-from pypy.objspace.std.strutil import ParseStringError
+from pypy.objspace.std.strutil import string_to_float, ParseStringError
 
 def descr__new__(space, w_floattype, w_x=0.0):
     from pypy.objspace.std.floatobject import W_FloatObject
     w_value = w_x     # 'x' is the keyword argument name in CPython
     if space.is_true(space.isinstance(w_value, space.w_str)):
+        strvalue = space.str_w(w_value)
         try:
-            value = float(space.str_w(w_value))
-        except ValueError, e:
+            value = string_to_float(strvalue)
+        except ParseStringError, e:
             raise OperationError(space.w_ValueError,
-                                 space.wrap(str(e)))
+                                 space.wrap(e.msg))
     elif space.is_true(space.isinstance(w_value, space.w_unicode)):
+        from unicodeobject import unicode_to_decimal_w
+        strvalue = unicode_to_decimal_w(space, w_value)
         try:
-            # XXX can produce unwrapped long
-            from unicodeobject import unicode_to_decimal_w
-            value = float(unicode_to_decimal_w(space, w_value))
+            value = string_to_float(strvalue)
         except ParseStringError, e:
             raise OperationError(space.w_ValueError,
                                  space.wrap(e.msg))

Modified: pypy/branch/pycompiler/objspace/std/inttype.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/inttype.py	(original)
+++ pypy/branch/pycompiler/objspace/std/inttype.py	Fri Jul  1 18:30:34 2005
@@ -22,7 +22,7 @@
             value = w_value.intval
         elif space.is_true(space.isinstance(w_value, space.w_str)):
             try:
-                value = string_to_int(space, space.str_w(w_value))
+                value = string_to_int(space.str_w(w_value))
             except ParseStringError, e:
                 raise OperationError(space.w_ValueError,
                                      space.wrap(e.msg))
@@ -32,7 +32,7 @@
             from unicodeobject import unicode_to_decimal_w
             string = unicode_to_decimal_w(space, w_value)
             try:
-                value = string_to_int(space, string)
+                value = string_to_int(string)
             except ParseStringError, e:
                 raise OperationError(space.w_ValueError,
                                      space.wrap(e.msg))
@@ -68,7 +68,7 @@
                                      space.wrap("int() can't convert non-string "
                                                 "with explicit base"))
         try:
-            value = string_to_int(space, s, base)
+            value = string_to_int(s, base)
         except ParseStringError, e:
             raise OperationError(space.w_ValueError,
                                  space.wrap(e.msg))

Modified: pypy/branch/pycompiler/objspace/std/listobject.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/listobject.py	(original)
+++ pypy/branch/pycompiler/objspace/std/listobject.py	Fri Jul  1 18:30:34 2005
@@ -597,20 +597,23 @@
         assert isinstance(b, KeyContainer)
         return CustomCompareSort.lt(self, a.w_key, b.w_key)
 
-SortClass = {
-    (False, False): SimpleSort,
-    (True,  False): CustomCompareSort,
-    (False, True) : CustomKeySort,
-    (True,  True) : CustomKeyCompareSort,
-    }
-
 def list_sort__List_ANY_ANY_ANY(space, w_list, w_cmp, w_keyfunc, w_reverse):
     has_cmp = not space.is_w(w_cmp, space.w_None)
     has_key = not space.is_w(w_keyfunc, space.w_None)
     has_reverse = space.is_true(w_reverse)
 
     # create and setup a TimSort instance
-    sorterclass = SortClass[has_cmp, has_key]
+    if has_cmp: 
+        if has_key: 
+            sorterclass = CustomKeyCompareSort
+        else: 
+            sorterclass = CustomCompareSort
+    else: 
+        if has_key: 
+            sorterclass = CustomKeySort
+        else: 
+            sorterclass = SimpleSort
+            
     sorter = sorterclass(w_list.ob_item, w_list.ob_size)
     sorter.space = space
     sorter.w_cmp = w_cmp

Modified: pypy/branch/pycompiler/objspace/std/model.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/model.py	(original)
+++ pypy/branch/pycompiler/objspace/std/model.py	Fri Jul  1 18:30:34 2005
@@ -136,7 +136,6 @@
             specialnames = [operatorsymbol]
         self.specialnames = specialnames  # e.g. ['__xxx__', '__rxxx__']
         self.extras = extras
-        self.unbound_versions = {}
         # transform  '+'  =>  'add'  etc.
         for line in ObjSpace.MethodTable:
             realname, symbolname = line[:2]

Modified: pypy/branch/pycompiler/objspace/std/mro.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/mro.py	(original)
+++ pypy/branch/pycompiler/objspace/std/mro.py	Fri Jul  1 18:30:34 2005
@@ -37,7 +37,13 @@
         cycle.append(candidate)
         nextblockinglist = blockinglist(candidate, orderlists)
         candidate = nextblockinglist[0]
-    del cycle[:cycle.index(candidate)]
+    # avoid the only use of list.index in the PyPy code base:
+    i = 0
+    for c in cycle:
+        if c == candidate:
+            break
+        i += 1
+    del cycle[:i]
     cycle.append(candidate)
     cycle.reverse()
     names = [cls.__name__ for cls in cycle]

Modified: pypy/branch/pycompiler/objspace/std/objspace.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/objspace.py	(original)
+++ pypy/branch/pycompiler/objspace/std/objspace.py	Fri Jul  1 18:30:34 2005
@@ -66,7 +66,6 @@
         self.w_Ellipsis = self.wrap(Ellipsis(self))  
 
         # types
-        self.types_w = {}
         for typedef in self.model.pythontypes:
             w_type = self.gettypeobject(typedef)
             setattr(self, 'w_' + typedef.name, w_type)
@@ -180,7 +179,7 @@
         return ec
 
     def gettypeobject(self, typedef):
-        # types_w maps each StdTypeDef instance to its
+        # stdtypedef.TypeCache maps each StdTypeDef instance to its
         # unique-for-this-space W_TypeObject instance
         return self.fromcache(stdtypedef.TypeCache).getorbuild(typedef)
 

Modified: pypy/branch/pycompiler/objspace/std/stringobject.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/stringobject.py	(original)
+++ pypy/branch/pycompiler/objspace/std/stringobject.py	Fri Jul  1 18:30:34 2005
@@ -348,10 +348,10 @@
     if len(fillchar) != 1:
         raise OperationError(space.w_TypeError,
             space.wrap("rjust() argument 2 must be a single character"))
-
     
     d = u_arg - len(u_self)
     if d>0:
+        fillchar = fillchar[0]    # annotator hint: it's a single character
         u_self = d * fillchar + u_self
         
     return space.wrap(u_self)
@@ -368,6 +368,7 @@
 
     d = u_arg - len(u_self)
     if d>0:
+        fillchar = fillchar[0]    # annotator hint: it's a single character
         u_self += d * fillchar
         
     return space.wrap(u_self)
@@ -585,6 +586,7 @@
     d = u_arg - len(u_self) 
     if d>0:
         offset = d//2
+        fillchar = fillchar[0]    # annotator hint: it's a single character
         u_centered = offset * fillchar + u_self + (d - offset) * fillchar
     else:
         u_centered = u_self

Modified: pypy/branch/pycompiler/objspace/std/strutil.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/strutil.py	(original)
+++ pypy/branch/pycompiler/objspace/std/strutil.py	Fri Jul  1 18:30:34 2005
@@ -86,7 +86,7 @@
         else:
             return -1
 
-def string_to_int(space, s, base=10):
+def string_to_int(s, base=10):
     """Utility to converts a string to an integer (or possibly a long).
     If base is 0, the proper base is guessed based on the leading
     characters of 's'.  Raises ParseStringError in case of error.
@@ -134,3 +134,110 @@
                 return w_result
         w_result = space.add(space.mul(w_result,w_base),space.newlong(r_uint(digit)))
 
+def break_up_float(s):
+    i = 0
+
+    sign = ''
+    before_point = ''
+    after_point = ''
+    exponent = ''
+
+    if s[i] in '+-':
+        sign = s[i]
+        i += 1
+
+    while i < len(s) and s[i] in '0123456789':
+        before_point += s[i]
+        i += 1
+
+    if i == len(s):
+        return sign, before_point, after_point, exponent
+
+    if s[i] == '.':
+        i += 1
+        while i < len(s) and s[i] in '0123456789':
+            after_point += s[i]
+            i += 1
+            
+        if i == len(s):
+            return sign, before_point, after_point, exponent
+
+    if s[i] not in  'eE':
+        raise ParseStringError("invalid string literal for float()")
+
+    i += 1
+    if i == len(s):
+        raise ParseStringError("invalid string literal for float()")
+
+    if s[i] in '-+':
+        exponent += s[i]
+        i += 1
+
+    if i == len(s):
+        raise ParseStringError("invalid string literal for float()")
+    
+    while i < len(s) and s[i] in '0123456789':
+        exponent += s[i]
+        i += 1
+
+    if i != len(s):
+        raise ParseStringError("invalid string literal for float()")
+
+    return sign, before_point, after_point, exponent
+
+
+def string_to_float(s):
+    s = strip_spaces(s)
+
+    if not s:
+        raise ParseStringError("empty string for float()")
+
+    sign, before_point, after_point, exponent = break_up_float(s)
+    
+    if not before_point and not after_point:
+        raise ParseStringError("invalid string literal for float()")
+
+    r = 0.0
+    i = len(before_point) - 1
+    j = 0
+    while i >= 0:
+        d = float(ord(before_point[i]) - ord('0'))
+        r += d * (10.0 ** j)
+        i -= 1
+        j += 1
+
+    i = 0
+    while i < len(after_point):
+        d = float(ord(after_point[i]) - ord('0'))
+        r += d * (10.0 ** (-i-1))
+        i += 1
+
+    if exponent:
+        # XXX this fails for float('0.' + '0'*100 + '1e400')
+        # XXX later!
+        try:
+            e = string_to_int(exponent)
+        except ParseStringOverflowError:
+            if exponent[0] == '-':
+                e = -400
+            else:
+                e = 400
+        if e > 0:
+            if e >= 400:
+                r = 1e200 * 1e200
+            else:
+                while e > 0:
+                    r *= 10.0
+                    e -= 1
+        else:
+            if e <= -400:
+                r = 0.0
+            else:
+                while e < 0:
+                    r /= 10.0
+                    e += 1
+
+    if sign == '-':
+        r = -r
+
+    return r

Modified: pypy/branch/pycompiler/objspace/std/test/test_floatobject.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/test/test_floatobject.py	(original)
+++ pypy/branch/pycompiler/objspace/std/test/test_floatobject.py	Fri Jul  1 18:30:34 2005
@@ -56,9 +56,11 @@
 
     def test_float_string(self):
         assert 42 == float("42")
+        assert 42.25 == float("42.25")
 
     def test_float_unicode(self):
-        assert 42.3 == float(unicode("42.3"))
+        # u00A0 and u2000 are some kind of spaces
+        assert 42.75 == float(unichr(0x00A0)+unicode("42.75")+unichr(0x2000))
 
     def test_float_long(self):
         assert 42.0 == float(42L)

Modified: pypy/branch/pycompiler/objspace/std/test/test_strutil.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/test/test_strutil.py	(original)
+++ pypy/branch/pycompiler/objspace/std/test/test_strutil.py	Fri Jul  1 18:30:34 2005
@@ -1,6 +1,9 @@
 import autopath
+import py, random
 from pypy.objspace.std.strutil import *
 
+import py
+
 objspacename = 'std'
 
 class TestStrUtil:
@@ -24,7 +27,7 @@
                  ('  -123456789 ', -123456789),
                  ]
         for s, expected in cases:
-            assert string_to_int(space, s) == expected
+            assert string_to_int(s) == expected
             assert string_to_w_long(space, s).longval() == expected
 
     def test_string_to_int_base(self):
@@ -54,12 +57,12 @@
                  ('0X',  16, 0),    #     "           "
                  ]
         for s, base, expected in cases:
-            assert string_to_int(space, s, base) == expected
-            assert string_to_int(space, '+'+s, base) == expected
-            assert string_to_int(space, '-'+s, base) == -expected
-            assert string_to_int(space, s+'\n', base) == expected
-            assert string_to_int(space, '  +'+s, base) == expected
-            assert string_to_int(space, '-'+s+'  ', base) == -expected
+            assert string_to_int(s, base) == expected
+            assert string_to_int('+'+s, base) == expected
+            assert string_to_int('-'+s, base) == -expected
+            assert string_to_int(s+'\n', base) == expected
+            assert string_to_int('  +'+s, base) == expected
+            assert string_to_int('-'+s+'  ', base) == -expected
 
     def test_string_to_int_error(self):
         space = self.space
@@ -78,16 +81,16 @@
                  '@',
                  ]
         for s in cases:
-            raises(ParseStringError, string_to_int, space, s)
-            raises(ParseStringError, string_to_int, space, '  '+s)
-            raises(ParseStringError, string_to_int, space, s+'  ')
-            raises(ParseStringError, string_to_int, space, '+'+s)
-            raises(ParseStringError, string_to_int, space, '-'+s)
+            raises(ParseStringError, string_to_int, s)
+            raises(ParseStringError, string_to_int, '  '+s)
+            raises(ParseStringError, string_to_int, s+'  ')
+            raises(ParseStringError, string_to_int, '+'+s)
+            raises(ParseStringError, string_to_int, '-'+s)
 
     def test_string_to_int_overflow(self):
         import sys
         space = self.space
-        raises(ParseStringOverflowError, string_to_int, space,
+        raises(ParseStringOverflowError, string_to_int,
                str(sys.maxint*17))
 
     def test_string_to_int_base_error(self):
@@ -107,11 +110,11 @@
                  ('12.3', 16),
                  ]
         for s, base in cases:
-            raises(ParseStringError, string_to_int, space, s, base)
-            raises(ParseStringError, string_to_int, space, '  '+s, base)
-            raises(ParseStringError, string_to_int, space, s+'  ', base)
-            raises(ParseStringError, string_to_int, space, '+'+s, base)
-            raises(ParseStringError, string_to_int, space, '-'+s, base)
+            raises(ParseStringError, string_to_int, s, base)
+            raises(ParseStringError, string_to_int, '  '+s, base)
+            raises(ParseStringError, string_to_int, s+'  ', base)
+            raises(ParseStringError, string_to_int, '+'+s, base)
+            raises(ParseStringError, string_to_int, '-'+s, base)
 
     def test_string_to_w_long(self):
         space = self.space
@@ -124,3 +127,72 @@
         assert string_to_w_long(space, '123L', 22).longval() == 10648 + 968 + 66 + 21
         assert string_to_w_long(space, '123L', 21).longval() == 441 + 42 + 3
         assert string_to_w_long(space, '1891234174197319').longval() == 1891234174197319
+
+
+def test_break_up_float():
+    assert break_up_float('1') == ('', '1', '', '')
+    assert break_up_float('+1') == ('+', '1', '', '')
+    assert break_up_float('-1') == ('-', '1', '', '')
+
+    assert break_up_float('.5') == ('', '', '5', '')
+    
+    assert break_up_float('1.2e3') == ('', '1', '2', '3')
+    assert break_up_float('1.2e+3') == ('', '1', '2', '+3')
+    assert break_up_float('1.2e-3') == ('', '1', '2', '-3')
+
+    # some that will get thrown out on return:
+    assert break_up_float('.') == ('', '', '', '')
+    assert break_up_float('+') == ('+', '', '', '')
+    assert break_up_float('-') == ('-', '', '', '')
+    assert break_up_float('e1') == ('', '', '', '1')
+
+    py.test.raises(ParseStringError, break_up_float, 'e')
+
+
+def test_string_to_float():
+    assert string_to_float('0') == 0.0
+    assert string_to_float('1') == 1.0
+    assert string_to_float('-1.5') == -1.5
+    assert string_to_float('1.5E2') == 150.0
+    assert string_to_float('2.5E-1') == 0.25
+    assert string_to_float('1e1111111111111') == float('1e1111111111111')
+    assert string_to_float('1e-1111111111111') == float('1e-1111111111111')
+    assert string_to_float('-1e1111111111111') == float('-1e1111111111111')
+    assert string_to_float('-1e-1111111111111') == float('-1e-1111111111111')
+    assert string_to_float('1e111111111111111111111') == float('1e111111111111111111111')
+    assert string_to_float('1e-111111111111111111111') == float('1e-111111111111111111111')
+    assert string_to_float('-1e111111111111111111111') == float('-1e111111111111111111111')
+    assert string_to_float('-1e-111111111111111111111') == float('-1e-111111111111111111111')
+
+    valid_parts = [['', '  ', ' \f\n\r\t\v'],
+                   ['', '+', '-'],
+                   ['00', '90', '.5', '2.4', '3.', '0.07',
+                    '12.3489749871982471987198371293717398256187563298638726'
+                    '2187362820947193247129871083561249818451804287437824015'
+                    '013816418758104762348932657836583048761487632840726386'],
+                   ['', 'e0', 'E+1', 'E-01', 'E42'],
+                   ['', '  ', ' \f\n\r\t\v'],
+                   ]
+    invalid_parts = [['#'],
+                     ['++', '+-', '-+', '--'],
+                     ['', '1.2.3', '.', '5..6'],
+                     ['E+', 'E-', 'e', 'e++', 'E++2'],
+                     ['#'],
+                     ]
+    for part0 in valid_parts[0]:
+        for part1 in valid_parts[1]:
+            for part2 in valid_parts[2]:
+                for part3 in valid_parts[3]:
+                    for part4 in valid_parts[4]:
+                        s = part0+part1+part2+part3+part4
+                        assert (abs(string_to_float(s) - float(s)) <=
+                                1E-13 * abs(float(s)))
+
+    for j in range(len(invalid_parts)):
+        for invalid in invalid_parts[j]:
+            for i in range(20):
+                parts = [random.choice(lst) for lst in valid_parts]
+                parts[j] = invalid
+                s = ''.join(parts)
+                print repr(s)
+                py.test.raises(ParseStringError, string_to_float, s)

Modified: pypy/branch/pycompiler/objspace/std/test/test_unicodestring.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/test/test_unicodestring.py	(original)
+++ pypy/branch/pycompiler/objspace/std/test/test_unicodestring.py	Fri Jul  1 18:30:34 2005
@@ -72,4 +72,4 @@
         assert int(u'12345') == 12345
 
     def test_float_from_unicode(self):
-        assert float(u'123.456e89') == 123.456e89
+        assert float(u'123.456e89') == float('123.456e89')

Modified: pypy/branch/pycompiler/objspace/std/tupleobject.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/tupleobject.py	(original)
+++ pypy/branch/pycompiler/objspace/std/tupleobject.py	Fri Jul  1 18:30:34 2005
@@ -86,7 +86,9 @@
     items2 = w_tuple2.wrappeditems
     if len(items1) != len(items2):
         return space.w_False
-    for item1, item2 in zip(items1, items2):
+    for i in range(len(items1)):
+        item1 = items1[i]
+        item2 = items2[i]
         if not space.is_true(space.eq(item1, item2)):
             return space.w_False
     return space.w_True

Modified: pypy/branch/pycompiler/objspace/std/unicodeobject.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/unicodeobject.py	(original)
+++ pypy/branch/pycompiler/objspace/std/unicodeobject.py	Fri Jul  1 18:30:34 2005
@@ -4,7 +4,6 @@
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.objspace.std.sliceobject import W_SliceObject
 from pypy.objspace.std import slicetype
-from pypy.objspace.std.strutil import string_to_int, string_to_long, ParseStringError
 from pypy.rpython.rarithmetic import intmask
 from pypy.module.unicodedata import unicodedb
 
@@ -782,7 +781,7 @@
     else:
         retval, length = encoder(unistr, errors)
     if not isinstance(retval,str):
-        raise TypeError("encoder did not return an unicode object (type=%s)" %
+        raise TypeError("encoder did not return a string object (type=%s)" %
                         type(retval).__name__)
     return retval
 

Modified: pypy/branch/pycompiler/objspace/std/unicodetype.py
==============================================================================
--- pypy/branch/pycompiler/objspace/std/unicodetype.py	(original)
+++ pypy/branch/pycompiler/objspace/std/unicodetype.py	Fri Jul  1 18:30:34 2005
@@ -46,9 +46,6 @@
 import codecs, sys
 
 def unicode_from_encoded_object(obj, encoding, errors):
-    # Fix later for buffer
-    if type(obj).__name__ == 'buffer':
-        obj = obj.buf
     if encoding is None:
         encoding = sys.getdefaultencoding()
     decoder = codecs.getdecoder(encoding)
@@ -105,7 +102,7 @@
     # help the annotator! also the ._value depends on W_UnicodeObject layout
     assert isinstance(w_value, W_UnicodeObject)
     w_newobj = space.allocate_instance(W_UnicodeObject, w_unicodetype)
-    w_newobj.__init__(space, w_value._value)
+    W_UnicodeObject.__init__(w_newobj, space, w_value._value)
     return w_newobj
 
 # ____________________________________________________________

Modified: pypy/branch/pycompiler/rpython/annlowlevel.py
==============================================================================
--- pypy/branch/pycompiler/rpython/annlowlevel.py	(original)
+++ pypy/branch/pycompiler/rpython/annlowlevel.py	Fri Jul  1 18:30:34 2005
@@ -4,7 +4,7 @@
 
 from pypy.annotation import model as annmodel
 from pypy.annotation.specialize import decide_callable
-from pypy.translator.annrpython import BasicAnnotatorPolicy
+from pypy.annotation.policy import BasicAnnotatorPolicy
 
 def not_const(s_obj): # xxx move it somewhere else
     if s_obj.is_constant():
@@ -26,7 +26,7 @@
     def __hash__(self):
         return hash(self.val)
     def __str__(self):
-        return getattr(self.val, '__name__', self.val) + 'Const'
+        return getattr(self.val, '__name__', repr(self.val)) + 'Const'
 
 class LowLevelAnnotatorPolicy(BasicAnnotatorPolicy):
 
@@ -56,7 +56,7 @@
         (ll_function, args), key = decide_callable(annotator.bookkeeper, None, ll_function, args, mono=True, unpacked=True)
         args_s, kwds_s = args.unpack()
         assert not kwds_s
-        oldblocks = annotator.annotated.keys()
+        oldblocks = annotator.annotated.copy()
         s = annotator.build_types(ll_function, args_s)
         newblocks = [block for block in annotator.annotated.iterkeys() if block not in oldblocks]
         # invoke annotation simplifications for the new blocks

Modified: pypy/branch/pycompiler/rpython/exceptiondata.py
==============================================================================
--- pypy/branch/pycompiler/rpython/exceptiondata.py	(original)
+++ pypy/branch/pycompiler/rpython/exceptiondata.py	Fri Jul  1 18:30:34 2005
@@ -1,27 +1,44 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython import rclass
 from pypy.rpython.annlowlevel import annotate_lowlevel_helper
-from pypy.rpython.lltype import *
+from pypy.rpython.lltype import Array, malloc, Ptr, PyObject, pyobjectptr
+from pypy.rpython.lltype import FuncType, functionptr, Signed
 
 
 class ExceptionData:
     """Public information for the code generators to help with exceptions."""
 
+    # the exceptions that can be implicitely raised by some operations
+    standardexceptions = [TypeError, OverflowError, ValueError,
+                          ZeroDivisionError, MemoryError]
+
     def __init__(self, rtyper):
+        self.make_standard_exceptions(rtyper)
         # (NB. rclass identifies 'Exception' and 'object')
         r_type = rclass.getclassrepr(rtyper, None)
         r_instance = rclass.getinstancerepr(rtyper, None)
         r_type.setup()
         r_instance.setup()
+        self.r_exception_type  = r_type
+        self.r_exception_value = r_instance
         self.lltype_of_exception_type  = r_type.lowleveltype
         self.lltype_of_exception_value = r_instance.lowleveltype
 
+
+    def make_helpers(self, rtyper):
         # create helper functions
         self.ll_exception_match  = self.make_exception_matcher(rtyper)
         self.ll_type_of_exc_inst = self.make_type_of_exc_inst(rtyper)
         self.ll_pyexcclass2exc   = self.make_pyexcclass2exc(rtyper)
 
 
+    def make_standard_exceptions(self, rtyper):
+        bk = rtyper.annotator.bookkeeper
+        for cls in self.standardexceptions:
+            classdef = bk.getclassdef(cls)
+            rclass.getclassrepr(rtyper, classdef).setup()
+
+
     def make_exception_matcher(self, rtyper):
         # ll_exception_matcher(real_exception_vtable, match_exception_vtable)
         s_typeptr = annmodel.SomePtr(self.lltype_of_exception_type)
@@ -72,7 +89,7 @@
         for cls in table.keys():
             add_class(cls)
         assert table == {}
-        print sortedtable
+        #print sortedtable
 
         A = Array(('pycls', Ptr(PyObject)),
                   ('excinst', self.lltype_of_exception_value))

Modified: pypy/branch/pycompiler/rpython/lltype.py
==============================================================================
--- pypy/branch/pycompiler/rpython/lltype.py	(original)
+++ pypy/branch/pycompiler/rpython/lltype.py	Fri Jul  1 18:30:34 2005
@@ -1,4 +1,4 @@
-import weakref
+import weakref, operator
 import py
 from pypy.rpython.rarithmetic import r_uint
 from pypy.tool.uid import Hashable
@@ -22,6 +22,8 @@
             del seeing[seeingkey]
     return safe
 
+safe_equal = saferecursive(operator.eq, True)
+
 class frozendict(dict):
 
     def __hash__(self):
@@ -32,8 +34,8 @@
 
 class LowLevelType(object):
     def __eq__(self, other):
-        return self.__class__ is other.__class__ and self.__dict__ == other.__dict__
-    __eq__ = saferecursive(__eq__, True)
+        return self.__class__ is other.__class__ and (
+            self is other or safe_equal(self.__dict__, other.__dict__))
 
     def __ne__(self, other):
         return not (self == other)
@@ -55,6 +57,14 @@
         finally:
             TLS.nested_hash_level -= 1
 
+    # due to this dynamic hash value, we must forbid
+    # pickling, until we have an algorithm for that
+    def __reduce_ex__(self, *args):
+        raise Exception('%s insts cannot be pickled, yet. __hash__ is not'
+                        ' constant during reconstruction.' %
+                        self.__class__.__name__)
+    __reduce__ = __reduce_ex__
+
     def __repr__(self):
         return '<%s>' % (self,)
 
@@ -151,7 +161,21 @@
         return _struct(self, n)
 
 class GcStruct(Struct):
-    pass
+    _runtime_type_info = None
+
+    def _attach_runtime_type_info_funcptr(self, funcptr):
+        if self._runtime_type_info is None:
+            self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj
+        if funcptr is not None:
+            T = typeOf(funcptr)
+            if (not isinstance(T, Ptr) or
+                not isinstance(T.TO, FuncType) or
+                len(T.TO.ARGS) != 1 or
+                T.TO.RESULT != Ptr(RuntimeTypeInfo) or
+                castable(T.TO.ARGS[0], Ptr(self)) < 0):
+                raise TypeError("expected a runtime type info function "
+                                "implementation, got: %s" % funcptr)
+            self._runtime_type_info.query_funcptr = funcptr
 
 class Array(ContainerType):
     __name__ = 'array'
@@ -213,9 +237,20 @@
 
     def _container_example(self):
         def ex(*args):
-            return self.RESULT._example()
+            return self.RESULT._defl()
         return _func(self, _callable=ex)
 
+class OpaqueType(ContainerType):
+    
+    def __init__(self, tag):
+        self.tag = tag
+        self.__name__ = tag
+
+    def __str__(self):
+        return "%s (opaque)" % self.tag
+
+RuntimeTypeInfo = OpaqueType("RuntimeTypeInfo")
+
 class PyObjectType(ContainerType):
     __name__ = 'PyObject'
     def __str__(self):
@@ -264,6 +299,7 @@
 Char     = Primitive("Char", '\x00')
 Bool     = Primitive("Bool", False)
 Void     = Primitive("Void", None)
+UniChar  = Primitive("UniChar", u'\x00')
 
 
 class Ptr(LowLevelType):
@@ -278,17 +314,8 @@
     def _needsgc(self):
         return self.TO._gcstatus()
 
-    def _str_flags(self):
-        if self._needsgc():
-            return 'gc'
-        else:
-            return ''
-
-    def _str_flavor(self):
-        return 'ptr(%s)' % self._str_flags()
-
     def __str__(self):
-        return '%s to %s' % (self._str_flavor(), self.TO)
+        return '* %s' % (self.TO, )
 
     def _defl(self, parent=None, parentindex=None):
         return _ptr(self, None)
@@ -313,6 +340,9 @@
     if isinstance(val, str):
         assert len(val) == 1
         return Char
+    if isinstance(val, unicode):
+        assert len(val) == 1
+        return UniChar
     if val is None:
         return Void   # maybe
     return val._TYPE
@@ -426,9 +456,14 @@
     def __ne__(self, other):
         return not (self == other)
 
+    def __hash__(self):
+        raise TypeError("pointer objects are not hashable")
+
     def __nonzero__(self):
         return self._obj is not None
 
+    # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr,
+    # use _obj if necessary instead !
     def _setobj(self, pointing_to, immortal=False):        
         if pointing_to is None:
             obj0 = None
@@ -520,7 +555,7 @@
         return '<%s>' % (self,)
 
     def __str__(self):
-        return '%s to %s' % (self._TYPE._str_flavor(), self._obj)
+        return '* %s' % (self._obj, )
 
     def __call__(self, *args):
         if isinstance(self._T, FuncType):
@@ -650,7 +685,36 @@
         return '<%s>' % (self,)
 
     def __str__(self):
-        return "func %s" % self._name
+        return "fn %s" % self._name
+
+    def __eq__(self, other):
+        return (self.__class__ is other.__class__ and
+                self.__dict__ == other.__dict__)
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __hash__(self):
+        return hash(frozendict(self.__dict__))
+
+class _opaque(object):
+    def __init__(self, TYPE, **attrs):
+        self._TYPE = TYPE
+        self._name = "?"
+        self.__dict__.update(attrs)
+
+    def _parentstructure(self):
+        return None
+
+    def _check(self):
+        pass
+
+    def __repr__(self):
+        return '<%s>' % (self,)
+
+    def __str__(self):
+        return "%s %s" % (self._TYPE.__name__, self._name)
+
 
 class _pyobject(Hashable):
     _TYPE = PyObject
@@ -681,14 +745,59 @@
 
 def functionptr(TYPE, name, **attrs):
     if not isinstance(TYPE, FuncType):
-        raise TypeError, "function() for FuncTypes only"
+        raise TypeError, "functionptr() for FuncTypes only"
+    try:
+        hash(tuple(attrs.items()))
+    except TypeError:
+        raise TypeError("'%r' must be hashable"%attrs)
     o = _func(TYPE, _name=name, **attrs)
     return _ptr(Ptr(TYPE), o)
 
 def nullptr(T):
     return Ptr(T)._defl()
 
+def opaqueptr(TYPE, name, **attrs):
+    if not isinstance(TYPE, OpaqueType):
+        raise TypeError, "opaqueptr() for OpaqueTypes only"
+    o = _opaque(TYPE, _name=name, **attrs)
+    return _ptr(Ptr(TYPE), o, immortal=attrs.get('immortal', True))
+
 def pyobjectptr(obj):
     o = _pyobject(obj)
     return _ptr(Ptr(PyObject), o) 
 
+def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None):
+    if not isinstance(GCSTRUCT, GcStruct):
+        raise TypeError, "expected a GcStruct: %s" % GCSTRUCT
+    GCSTRUCT._attach_runtime_type_info_funcptr(funcptr)
+    return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info)
+
+def getRuntimeTypeInfo(GCSTRUCT):
+    if not isinstance(GCSTRUCT, GcStruct):
+        raise TypeError, "expected a GcStruct: %s" % GCSTRUCT
+    if GCSTRUCT._runtime_type_info is None:
+        raise ValueError, "no attached runtime type info for %s" % GCSTRUCT
+    return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info)
+
+def runtime_type_info(p):
+    T = typeOf(p)
+    if not isinstance(T, Ptr) or not isinstance(T.TO, GcStruct):
+        raise TypeError, "runtime_type_info on non-GcStruct pointer: %s" % p
+    top_parent = struct = p._obj
+    while True:
+        parent = top_parent._parentstructure()
+        if parent is None:
+            break
+        top_parent = parent
+    result = getRuntimeTypeInfo(top_parent._TYPE)
+    static_info = getRuntimeTypeInfo(T.TO)
+    query_funcptr = getattr(static_info._obj, 'query_funcptr', None)
+    if query_funcptr is not None:
+        T = typeOf(query_funcptr).TO.ARGS[0]
+        result2 = query_funcptr(cast_pointer(T, p))
+        if result != result2:
+            raise RuntimeError, ("runtime type-info function for %s:\n"
+                                 "        returned: %s,\n"
+                                 "should have been: %s" % (p, result2, result))
+    return result
+    

Modified: pypy/branch/pycompiler/rpython/normalizecalls.py
==============================================================================
--- pypy/branch/pycompiler/rpython/normalizecalls.py	(original)
+++ pypy/branch/pycompiler/rpython/normalizecalls.py	Fri Jul  1 18:30:34 2005
@@ -1,15 +1,17 @@
+import types
 from pypy.objspace.flow.model import Variable, Constant, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, checkgraph
-from pypy.annotation.model import *
+from pypy.annotation import model as annmodel
 from pypy.tool.sourcetools import has_varargs
 from pypy.rpython.rmodel import TyperError
 
 
 def normalize_function_signatures(annotator):
-    # make sure that all functions called in a group have exactly
-    # the same signature, by hacking their flow graphs if needed
-    callables = annotator.getpbccallables()
+    """Make sure that all functions called in a group have exactly
+    the same signature, by hacking their flow graphs if needed.
+    """
     call_families = annotator.getpbccallfamilies()
+
     # for methods, we create or complete a corresponding function-only
     # family with call patterns that have the extra 'self' argument
     for family in call_families.infos():
@@ -29,10 +31,51 @@
                 argcount = pattern[0]
                 pattern = (argcount+1,) + pattern[1:]
                 func_family.patterns[pattern] = True
+
+    # for classes that appear in families, unify their __init__ as well.
+    for family in call_families.infos():
+        prevkey = None
+        for _, klass in family.objects:
+            if isinstance(klass, (type, types.ClassType)):
+                try:
+                    initfunc = klass.__init__.im_func
+                except AttributeError:
+                    continue
+                if prevkey is None:
+                    prevkey = (None, initfunc)
+                else:
+                    call_families.union((None, initfunc), prevkey)
+
+    # for bound method objects, make sure the im_func shows up too.
+    for family in call_families.infos():
+        first = family.objects.keys()[0][1]
+        for _, callable in family.objects:
+            if isinstance(callable, types.MethodType):
+                # for bound methods families for now just accept and check that
+                # they all refer to the same function
+                if not isinstance(first, types.MethodType):
+                    raise TyperError("call family with both bound methods and "
+                                     "%r" % (first,))
+                if first.im_func is not callable.im_func:
+                    raise TyperError("call family of bound methods: should all "
+                                     "refer to the same function")
+        # create a family for the common im_func
+        if isinstance(first, types.MethodType):
+            _, _, func_family = call_families.find((None, first.im_func))
+            for pattern in family.patterns:
+                argcount = pattern[0]
+                pattern = (argcount+1,) + pattern[1:]
+                func_family.patterns[pattern] = True
+
     # find the most general signature of each family
     for family in call_families.infos():
+        # collect functions in this family, ignoring:
+        #  - methods: taken care of above
+        #  - bound methods: their im_func will also show up
+        #  - classes: their __init__ unbound methods are also families
         functions = [func for classdef, func in family.objects
-                          if classdef is None]  # ignore methods now
+                          if classdef is None and
+                not isinstance(func, (type, types.ClassType, types.MethodType))]
         if len(functions) > 1:  # otherwise, nothing to do
             if len(family.patterns) > 1:
                 raise TyperError("don't support multiple call patterns "
@@ -40,61 +83,125 @@
                     functions))
             pattern, = family.patterns
             shape_cnt, shape_keys, shape_star, shape_stst = pattern
-            assert not shape_keys, "XXX not implemented"
             assert not shape_star, "XXX not implemented"
             assert not shape_stst, "XXX not implemented"
+
             # for the first 'shape_cnt' arguments we need to generalize to
             # a common type
-            generalizedargs = []
             graph_bindings = {}
-            default_values = {}
+            graph_argorders = {}
             for func in functions:
                 assert not has_varargs(func), "XXX not implemented"
-                graph = annotator.translator.getflowgraph(func)
+                try:
+                    graph = annotator.translator.flowgraphs[func]
+                except KeyError:
+                    raise TyperError("the skipped %r must not show up in a "
+                                     "call family" % (func,))
                 graph_bindings[graph] = [annotator.binding(v)
                                          for v in graph.getargs()]
-            for i in range(shape_cnt):
+                argorder = range(shape_cnt)
+                for key in shape_keys:
+                    i = list(func.func_code.co_varnames).index(key)
+                    assert i not in argorder
+                    argorder.append(i)
+                graph_argorders[graph] = argorder
+
+            call_nbargs = shape_cnt + len(shape_keys)
+            generalizedargs = []
+            for i in range(call_nbargs):
                 args_s = []
-                for bindings in graph_bindings.values():
-                    args_s.append(bindings[i])
-                s_value = unionof(*args_s)
+                for graph, bindings in graph_bindings.items():
+                    j = graph_argorders[graph][i]
+                    args_s.append(bindings[j])
+                s_value = annmodel.unionof(*args_s)
                 generalizedargs.append(s_value)
+            result_s = [annotator.binding(graph.getreturnvar())
+                        for graph in graph_bindings]
+            generalizedresult = annmodel.unionof(*result_s)
+
             for func in functions:
                 graph = annotator.translator.getflowgraph(func)
                 bindings = graph_bindings[graph]
-                if generalizedargs != bindings: #NB. bindings can also be longer
+                argorder = graph_argorders[graph]
+                need_reordering = (argorder != range(call_nbargs))
+                need_conversion = (generalizedargs != bindings)
+                if need_reordering or need_conversion:
                     oldblock = graph.startblock
-                    vlist = []
-                    for i in range(len(generalizedargs)):
-                        v = Variable(graph.getargs()[i])
-                        annotator.setbinding(v, generalizedargs[i])
-                        vlist.append(v)
-                    newblock = Block(vlist)
-                    # add the defaults as constants
+                    inlist = []
+                    for s_value, j in zip(generalizedargs, argorder):
+                        v = Variable(graph.getargs()[j])
+                        annotator.setbinding(v, s_value)
+                        inlist.append(v)
+                    newblock = Block(inlist)
+                    # prepare the output args of newblock:
+                    # 1. collect the positional arguments
+                    outlist = inlist[:shape_cnt]
+                    # 2. add defaults and keywords
                     defaults = func.func_defaults or ()
-                    for i in range(len(generalizedargs), len(bindings)):
+                    for j in range(shape_cnt, len(bindings)):
                         try:
-                            default = defaults[i-len(bindings)]
-                        except IndexError:
-                            raise TyperError("call pattern has %d arguments, "
-                                             "but %r takes at least %d "
-                                             "arguments" % (
-                                len(generalizedargs), func,
-                                len(bindings) - len(defaults)))
-                        vlist.append(Constant(default))
-                    newblock.closeblock(Link(vlist, oldblock))
+                            i = argorder.index(j)
+                            v = inlist[i]
+                        except ValueError:
+                            try:
+                                default = defaults[j-len(bindings)]
+                            except IndexError:
+                                raise TyperError(
+                                    "call pattern has %d positional arguments, "
+                                    "but %r takes at least %d arguments" % (
+                                        shape_cnt, func,
+                                        len(bindings) - len(defaults)))
+                            v = Constant(default)
+                        outlist.append(v)
+                    newblock.closeblock(Link(outlist, oldblock))
                     oldblock.isstartblock = False
                     newblock.isstartblock = True
                     graph.startblock = newblock
                     # finished
                     checkgraph(graph)
                     annotator.annotated[newblock] = annotator.annotated[oldblock]
-                # XXX convert the return value too
+                graph.normalized_for_calls = True
+                # convert the return value too
+                annotator.setbinding(graph.getreturnvar(), generalizedresult)
+
+
+def specialize_pbcs_by_memotables(annotator):
+    memo_tables = annotator.bookkeeper.memo_tables
+    access_sets = annotator.getpbcaccesssets()
+    for memo_table in memo_tables: 
+        arglist_s = memo_table.arglist_s 
+        assert len(arglist_s) == 1, "XXX implement >1 arguments" 
+        arg1 = arglist_s[0]
+        assert isinstance(arg1, annmodel.SomePBC)
+
+        if None in arg1.prebuiltinstances:
+            raise TyperError("unsupported: memo call with an argument that can be None")
+        pbcs = arg1.prebuiltinstances.keys()
+        _, _, access_set = access_sets.find(pbcs[0])
 
+        # enforce a structure where we can uniformly access 
+        # our memofield later 
+        for pbc in pbcs[1:]:
+            _, _, access_set = access_sets.union(pbcs[0], pbc)
+        
+        # we can have multiple memo_tables per PBC 
+        i = 0
+        while 1: 
+            fieldname = "memofield_%d" % i
+            if fieldname in access_set.attrs: 
+                i += 1
+                continue
+            memo_table.fieldname = fieldname
+            break
+        access_set.attrs[fieldname] = memo_table.s_result
+        for pbc in pbcs: 
+            value = memo_table.table[(pbc,)] 
+            access_set.values[(pbc, fieldname)] = value 
 
 def perform_normalizations(annotator):
     annotator.frozen += 1
     try:
         normalize_function_signatures(annotator)
+        specialize_pbcs_by_memotables(annotator) 
     finally:
         annotator.frozen -= 1

Modified: pypy/branch/pycompiler/rpython/rarithmetic.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rarithmetic.py	(original)
+++ pypy/branch/pycompiler/rpython/rarithmetic.py	Fri Jul  1 18:30:34 2005
@@ -159,7 +159,7 @@
 
 def intmask(n):
     if isinstance(n, int):
-        return n
+        return int(n)   # possibly bool->int
     if isinstance(n, r_uint):
         n = long(n)
     n &= LONG_MASK

Modified: pypy/branch/pycompiler/rpython/rbool.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rbool.py	(original)
+++ pypy/branch/pycompiler/rpython/rbool.py	Fri Jul  1 18:30:34 2005
@@ -1,7 +1,8 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
-from pypy.rpython.lltype import Signed, Unsigned, Bool, Float
+from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, pyobjectptr
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, BoolRepr
+from pypy.rpython.robject import PyObjRepr, pyobj_repr
 
 
 debug = False
@@ -22,6 +23,9 @@
             raise TyperError("not a bool: %r" % (value,))
         return value
 
+    def get_ll_eq_function(self):
+        return None 
+
     def rtype_is_true(_, hop):
         vlist = hop.inputargs(Bool)
         return vlist[0]
@@ -46,3 +50,16 @@
             if debug: print 'explicit cast_bool_to_int'
             return llops.genop('cast_bool_to_int', [v], resulttype=Signed)
         return NotImplemented
+
+class __extend__(pairtype(PyObjRepr, BoolRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        if r_to.lowleveltype == Bool:
+            return llops.gencapicall('PyObject_IsTrue', [v], resulttype=Bool)
+        return NotImplemented
+
+class __extend__(pairtype(BoolRepr, PyObjRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        if r_from.lowleveltype == Bool:
+            return llops.gencapicall('PyBool_FromLong', [v],
+                                     resulttype = pyobj_repr)
+        return NotImplemented

Modified: pypy/branch/pycompiler/rpython/rbuiltin.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rbuiltin.py	(original)
+++ pypy/branch/pycompiler/rpython/rbuiltin.py	Fri Jul  1 18:30:34 2005
@@ -2,11 +2,13 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython import lltype
 from pypy.rpython import rarithmetic
-from pypy.rpython.lltype import Void, Signed
 from pypy.rpython.rtyper import TyperError
-from pypy.rpython.rrange import rtype_builtin_range
-from pypy.rpython.rmodel import Repr, TyperError
+from pypy.rpython.rrange import rtype_builtin_range, rtype_builtin_xrange 
+from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
 from pypy.rpython import rptr
+from pypy.rpython.robject import pyobj_repr
+from pypy.rpython.rfloat import float_repr, FloatRepr
+from pypy.rpython import rclass
 
 
 class __extend__(annmodel.SomeBuiltin):
@@ -22,14 +24,16 @@
             return BuiltinMethodRepr(rtyper.getrepr(self.s_self),
                                      self.methodname)
     def rtyper_makekey(self):
-        key = (getattr(self, 'const', None), self.methodname)
-        if self.s_self is not None:
-            key += (self.s_self.rtyper_makekey(),)
-        return key
+        if self.s_self is None:
+            # built-in function case
+            return getattr(self, 'const', None)
+        else:
+            # built-in method case
+            return (self.methodname, self.s_self.rtyper_makekey())
 
 
 class BuiltinFunctionRepr(Repr):
-    lowleveltype = Void
+    lowleveltype = lltype.Void
 
     def __init__(self, builtinfunc):
         self.builtinfunc = builtinfunc
@@ -40,8 +44,9 @@
         except KeyError:
             raise TyperError("don't know about built-in function %r" % (
                 self.builtinfunc,))
-        hop.r_s_popfirstarg()
-        return bltintyper(hop)
+        hop2 = hop.copy()
+        hop2.r_s_popfirstarg()
+        return bltintyper(hop2)
 
 
 class BuiltinMethodRepr(Repr):
@@ -61,9 +66,10 @@
             raise TyperError("missing %s.%s" % (
                 self.self_repr.__class__.__name__, name))
         # hack based on the fact that 'lowleveltype == self_repr.lowleveltype'
-        assert hop.args_r[0] is self
-        hop.args_r[0] = self.self_repr
-        return bltintyper(hop)
+        hop2 = hop.copy()
+        assert hop2.args_r[0] is self
+        hop2.args_r[0] = self.self_repr
+        return bltintyper(hop2)
 
 
 ##class __extend__(pairtype(SomeBuiltin, SomeObject)):
@@ -89,12 +95,76 @@
     assert hop.nb_args == 1
     return hop.args_r[0].rtype_float(hop)
 
+def rtype_builtin_chr(hop):
+    assert hop.nb_args == 1
+    return hop.args_r[0].rtype_chr(hop)
+
+def rtype_builtin_unichr(hop):
+    assert hop.nb_args == 1
+    return hop.args_r[0].rtype_unichr(hop)
+
+def rtype_builtin_list(hop):
+    return hop.args_r[0].rtype_bltn_list(hop)
+
+def rtype_builtin_isinstance(hop):
+    instance_repr = rclass.getinstancerepr(hop.rtyper, None)
+    class_repr = rclass.get_type_repr(hop.rtyper)
+    
+    v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
+
+    v_objcls = hop.gendirectcall(rclass.ll_type, v_obj)
+    return hop.gendirectcall(rclass.ll_issubclass, v_objcls, v_cls)
+    
+
 #def rtype_builtin_range(hop): see rrange.py
 
+#def rtype_builtin_xrange(hop): see rrange.py
+
 def rtype_intmask(hop):
-    vlist = hop.inputargs(Signed)
+    vlist = hop.inputargs(lltype.Signed)
     return vlist[0]
 
+def rtype_r_uint(hop):
+    vlist = hop.inputargs(lltype.Unsigned)
+    return vlist[0]
+
+def rtype_builtin_min(hop):
+    rint1, rint2 = hop.args_r
+    assert isinstance(rint1, IntegerRepr)
+    assert isinstance(rint2, IntegerRepr)
+    assert rint1.lowleveltype == rint2.lowleveltype
+    v1, v2 = hop.inputargs(rint1, rint2)
+    return hop.gendirectcall(ll_min, v1, v2)
+
+def ll_min(i1, i2):
+    if i1 < i2:
+        return i1
+    return i2
+
+def rtype_builtin_max(hop):
+    rint1, rint2 = hop.args_r
+    assert isinstance(rint1, IntegerRepr)
+    assert isinstance(rint2, IntegerRepr)
+    assert rint1.lowleveltype == rint2.lowleveltype
+    v1, v2 = hop.inputargs(rint1, rint2)
+    return hop.gendirectcall(ll_max, v1, v2)
+
+def ll_max(i1, i2):
+    if i1 > i2:
+        return i1
+    return i2
+
+def rtype_math_floor(hop):
+    vlist = hop.inputargs(lltype.Float)
+    return hop.genop('float_floor', vlist, resulttype=lltype.Float)
+
+def rtype_math_fmod(hop):
+    vlist = hop.inputargs(lltype.Float, lltype.Float)
+    return hop.genop('float_fmod', vlist, resulttype=lltype.Float)
+
+import math
+##def ll_floor(f1):
+##    return float(int((f1)
 
 # collect all functions
 import __builtin__
@@ -103,33 +173,70 @@
     if name.startswith('rtype_builtin_'):
         original = getattr(__builtin__, name[14:])
         BUILTIN_TYPER[original] = value
-
+BUILTIN_TYPER[math.floor] = rtype_math_floor
+BUILTIN_TYPER[math.fmod] = rtype_math_fmod
 # annotation of low-level types
 
 def rtype_malloc(hop):
     assert hop.args_s[0].is_constant()
     if hop.nb_args == 1:
-        vlist = hop.inputargs(Void)
+        vlist = hop.inputargs(lltype.Void)
         return hop.genop('malloc', vlist,
                          resulttype = hop.r_result.lowleveltype)
     else:
-        vlist = hop.inputargs(Void, Signed)
+        vlist = hop.inputargs(lltype.Void, lltype.Signed)
         return hop.genop('malloc_varsize', vlist,
                          resulttype = hop.r_result.lowleveltype)
 
 def rtype_const_result(hop):
-    return hop.inputconst(Void, hop.s_result.const)
+    return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
 
 def rtype_cast_pointer(hop):
     assert hop.args_s[0].is_constant()
     assert isinstance(hop.args_r[1], rptr.PtrRepr)
-    v_type, v_input = hop.inputargs(Void, hop.args_r[1])
+    v_type, v_input = hop.inputargs(lltype.Void, hop.args_r[1])
     return hop.genop('cast_pointer', [v_input],    # v_type implicit in r_result
                      resulttype = hop.r_result.lowleveltype)
 
+def rtype_runtime_type_info(hop):
+    assert isinstance(hop.args_r[0], rptr.PtrRepr)
+    vlist = hop.inputargs(hop.args_r[0])
+    return hop.genop('runtime_type_info', vlist,
+                 resulttype = rptr.PtrRepr(lltype.Ptr(lltype.RuntimeTypeInfo)))
+
 
 BUILTIN_TYPER[lltype.malloc] = rtype_malloc
 BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer
 BUILTIN_TYPER[lltype.typeOf] = rtype_const_result
 BUILTIN_TYPER[lltype.nullptr] = rtype_const_result
+BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_const_result
+BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info
 BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask
+BUILTIN_TYPER[rarithmetic.r_uint] = rtype_r_uint
+
+import time
+
+def rtype_time_clock(hop):
+    c = hop.inputconst(pyobj_repr, time.clock)
+    v = hop.genop('simple_call', [c], resulttype = pyobj_repr)
+    return hop.llops.convertvar(v, pyobj_repr, float_repr)
+
+BUILTIN_TYPER[time.clock] = rtype_time_clock
+
+
+def rtype_time_time(hop):
+    c = hop.inputconst(pyobj_repr, time.time)
+    v = hop.genop('simple_call', [c], resulttype = pyobj_repr)
+    return hop.llops.convertvar(v, pyobj_repr, float_repr)
+
+BUILTIN_TYPER[time.time] = rtype_time_time
+    
+import math
+
+def rtype_math_exp(hop):
+    vlist = hop.inputargs(lltype.Float)
+    # XXX need PyFPE_START_PROTECT/PyFPE_END_PROTECT/Py_SET_ERRNO_ON_MATH_ERROR
+    return hop.llops.gencapicall('exp', vlist, resulttype=lltype.Float,
+                                 includes=("math.h",))   # XXX clean up needed
+
+BUILTIN_TYPER[math.exp] = rtype_math_exp

Modified: pypy/branch/pycompiler/rpython/rclass.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rclass.py	(original)
+++ pypy/branch/pycompiler/rpython/rclass.py	Fri Jul  1 18:30:34 2005
@@ -2,8 +2,12 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.annotation.classdef import isclassdef
-from pypy.rpython.lltype import *
 from pypy.rpython.rmodel import Repr, TyperError, inputconst
+from pypy.rpython.lltype import ForwardReference, GcForwardReference
+from pypy.rpython.lltype import Ptr, Struct, GcStruct, malloc
+from pypy.rpython.lltype import cast_pointer, castable, nullptr
+from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo, typeOf
+from pypy.rpython.lltype import Array, Char, Void, attachRuntimeTypeInfo
 
 #
 #  There is one "vtable" per user class, with the following structure:
@@ -11,6 +15,8 @@
 #
 #      struct object_vtable {
 #          struct object_vtable* parenttypeptr;
+#          RuntimeTypeInfo * rtti;
+#          array { char } * name;
 #      }
 #
 #  Every other class X, with parent Y, has the structure:
@@ -34,7 +40,10 @@
 
 OBJECT_VTABLE = ForwardReference()
 TYPEPTR = Ptr(OBJECT_VTABLE)
-OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', TYPEPTR)))
+OBJECT_VTABLE.become(Struct('object_vtable',
+                            ('parenttypeptr', TYPEPTR),
+                            ('rtti', Ptr(RuntimeTypeInfo)),
+                            ('name', Ptr(Array(Char)))))
 
 OBJECT = GcStruct('object', ('typeptr', TYPEPTR))
 OBJECTPTR = Ptr(OBJECT)
@@ -55,6 +64,7 @@
         else:
             result = ClassRepr(rtyper, classdef)
         rtyper.class_reprs[classdef] = result
+        rtyper.reprs_must_call_setup.append(result)
     return result
 
 def getinstancerepr(rtyper, classdef):
@@ -67,6 +77,7 @@
         else:
             result = InstanceRepr(rtyper,classdef)
         rtyper.instance_reprs[classdef] = result
+        rtyper.reprs_must_call_setup.append(result)
     return result
 
 class MissingRTypeAttribute(TyperError):
@@ -149,10 +160,10 @@
             count = 0
             for x, classdef in s_value.prebuiltinstances.items():
                 if isclassdef(classdef):
-                    if classdef.commonbase(self.classdef) != self.classdef:
-                        raise TyperError("methods from PBC set %r don't belong "
-                                         "in %r" % (s_value.prebuiltinstances,
-                                                    self.classdef.cls))
+                    #if classdef.commonbase(self.classdef) != self.classdef:
+                    #    raise TyperError("methods from PBC set %r don't belong "
+                    #                     "in %r" % (s_value.prebuiltinstances,
+                    #                                self.classdef.cls))
                     count += 1
                     classdef = True
                 debound[x] = classdef
@@ -183,8 +194,7 @@
         """Return a ptr to the vtable of this type."""
         if self.vtable is None:
             self.vtable = malloc(self.vtable_type, immortal=True)
-            if self.classdef is not None:
-                self.setup_vtable(self.vtable, self)
+            self.setup_vtable(self.vtable, self)
         #
         vtable = self.vtable
         if cast_to_typeptr:
@@ -195,8 +205,20 @@
         """Initialize the 'self' portion of the 'vtable' belonging to the
         given subclass."""
         if self.classdef is None:
-            # initialize the 'parenttypeptr' field
-            vtable.parenttypeptr = rsubcls.rbase.getvtable()
+            # initialize the 'parenttypeptr' and 'name' fields
+            if rsubcls.classdef is not None:
+                vtable.parenttypeptr = rsubcls.rbase.getvtable()
+            rinstance = getinstancerepr(self.rtyper, rsubcls.classdef)
+            rinstance.setup()
+            vtable.rtti = getRuntimeTypeInfo(rinstance.object_type)
+            if rsubcls.classdef is None:
+                name = 'object'
+            else:
+                name = rsubcls.classdef.cls.__name__
+            vtable.name = malloc(Array(Char), len(name)+1, immortal=True)
+            for i in range(len(name)):
+                vtable.name[i] = name[i]
+            vtable.name[len(name)] = '\x00'
         else:
             # setup class attributes: for each attribute name at the level
             # of 'self', look up its value in the subclass rsubcls
@@ -282,6 +304,7 @@
             self.object_type = OBJECT
         else:
             self.object_type = GcForwardReference()
+        self.prebuiltinstances = {}   # { id(x): (x, _ptr) }
         self.lowleveltype = Ptr(self.object_type)
 
     def __repr__(self):
@@ -327,34 +350,59 @@
         allinstancefields.update(fields)
         self.fields = fields
         self.allinstancefields = allinstancefields
+        attachRuntimeTypeInfo(self.object_type)
         self.initialized = True
 
-    def convert_const(self, value, targetptr=None, vtable=None):
+    def setup_final_touch(self):
+        self.rtyper.attachRuntimeTypeInfoFunc(self.object_type,
+                                              ll_runtime_type_info,
+                                              OBJECT)
+
+    def convert_const(self, value):
         if value is None:
             return nullptr(self.object_type)
-        # we will need the vtable pointer, so ask it first, to let
-        # ClassRepr.convert_const() perform all the necessary checks on 'value'
-        if vtable is None:
-            vtable = self.rclass.convert_const(value.__class__)
-        if targetptr is None:
-            targetptr = malloc(self.object_type)
-        #
-        if self.classdef is None:
-            # instantiate 'object': should be disallowed, but it's convenient
-            # to write convert_const() this way and use itself recursively
-            targetptr.typeptr = cast_vtable_to_typeptr(vtable)
-        else:
-            # build the parent part of the instance
-            self.rbase.convert_const(value,
-                                     targetptr = targetptr.super,
-                                     vtable = vtable)
-            # add instance attributes from this level
+        try:
+            classdef = self.rtyper.annotator.getuserclasses()[value.__class__]
+        except KeyError:
+            raise TyperError("no classdef: %r" % (value.__class__,))
+        if classdef != self.classdef:
+            # if the class does not match exactly, check that 'value' is an
+            # instance of a subclass and delegate to that InstanceRepr
+            if classdef is None:
+                raise TyperError("not implemented: object() instance")
+            if classdef.commonbase(self.classdef) != self.classdef:
+                raise TyperError("not an instance of %r: %r" % (
+                    self.classdef.cls, value))
+            rinstance = getinstancerepr(self.rtyper, classdef)
+            result = rinstance.convert_const(value)
+            return cast_pointer(self.lowleveltype, result)
+        # common case
+        try:
+            return self.prebuiltinstances[id(value)][1]
+        except KeyError:
+            self.setup()
+            result = malloc(self.object_type)
+            self.prebuiltinstances[id(value)] = value, result
+            self.initialize_prebuilt_instance(value, classdef, result)
+            return result
+
+    def get_ll_eq_function(self):
+        return None
+
+    def initialize_prebuilt_instance(self, value, classdef, result):
+        if self.classdef is not None:
+            # recursively build the parent part of the instance
+            self.rbase.initialize_prebuilt_instance(value, classdef,
+                                                    result.super)
+            # then add instance attributes from this level
             for name, (mangled_name, r) in self.fields.items():
                 attrvalue = getattr(value, name)
-                # XXX RECURSIVE PREBUILT DATA STRUCTURES XXX
                 llattrvalue = r.convert_const(attrvalue)
-                setattr(targetptr, mangled_name, llattrvalue)
-        return targetptr
+                setattr(result, mangled_name, llattrvalue)
+        else:
+            # OBJECT part
+            rclass = getclassrepr(self.rtyper, classdef)
+            result.typeptr = rclass.getvtable()
 
     #def parentpart(self, vinst, llops):
     #    """Return the pointer 'vinst' cast to the parent type."""
@@ -372,33 +420,31 @@
                 raise MissingRTypeAttribute(attr)
             return self.rbase.getfieldrepr(attr)
 
-    def getfield(self, vinst, attr, llops, start_repr=None):
+    def getfield(self, vinst, attr, llops, force_cast=False):
         """Read the given attribute (or __class__ for the type) of 'vinst'."""
-        if start_repr is None:
-            start_repr = self
         if attr in self.fields:
             mangled_name, r = self.fields[attr]
             cname = inputconst(Void, mangled_name)
-            vinst = llops.convertvar(vinst, start_repr, self)
+            if force_cast:
+                vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
             return llops.genop('getfield', [vinst, cname], resulttype=r)
         else:
             if self.classdef is None:
                 raise MissingRTypeAttribute(attr)
-            return self.rbase.getfield(vinst, attr, llops, start_repr=start_repr)
+            return self.rbase.getfield(vinst, attr, llops, force_cast=True)
 
-    def setfield(self, vinst, attr, vvalue, llops, start_repr=None):
+    def setfield(self, vinst, attr, vvalue, llops, force_cast=False):
         """Write the given attribute (or __class__ for the type) of 'vinst'."""
-        if start_repr is None:
-            start_repr = self        
         if attr in self.fields:
             mangled_name, r = self.fields[attr]
             cname = inputconst(Void, mangled_name)
-            vinst = llops.convertvar(vinst, start_repr, self)            
+            if force_cast:
+                vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
             llops.genop('setfield', [vinst, cname, vvalue])
         else:
             if self.classdef is None:
                 raise MissingRTypeAttribute(attr)
-            self.rbase.setfield(vinst, attr, vvalue, llops, start_repr=start_repr)
+            self.rbase.setfield(vinst, attr, vvalue, llops, force_cast=True)
 
     def new_instance(self, llops):
         """Build a new instance, without calling __init__."""
@@ -408,21 +454,22 @@
         ctypeptr = inputconst(TYPEPTR, self.rclass.getvtable())
         self.setfield(vptr, '__class__', ctypeptr, llops)
         # initialize instance attributes from their defaults from the class
-        flds = self.allinstancefields.keys()
-        flds.sort()
-        mro = list(self.classdef.getmro())
-        for fldname in flds:
-            if fldname == '__class__':
-                continue
-            mangled_name, r = self.allinstancefields[fldname]
-            if r.lowleveltype == Void:
-                continue
-            for clsdef in mro:
-                if fldname in clsdef.cls.__dict__:
-                    value = clsdef.cls.__dict__[fldname]
-                    cvalue = inputconst(r, value)
-                    self.setfield(vptr, fldname, cvalue, llops)
-                    break
+        if self.classdef is not None:
+            flds = self.allinstancefields.keys()
+            flds.sort()
+            mro = list(self.classdef.getmro())
+            for fldname in flds:
+                if fldname == '__class__':
+                    continue
+                mangled_name, r = self.allinstancefields[fldname]
+                if r.lowleveltype == Void:
+                    continue
+                for clsdef in mro:
+                    if fldname in clsdef.cls.__dict__:
+                        value = clsdef.cls.__dict__[fldname]
+                        cvalue = inputconst(r, value)
+                        self.setfield(vptr, fldname, cvalue, llops)
+                        break
         return vptr
 
     def rtype_type(self, hop):
@@ -437,7 +484,8 @@
         elif attr in self.rclass.allmethods:
             # special case for methods: represented as their 'self' only
             # (see MethodsPBCRepr)
-            return vinst
+            return hop.r_result.get_method_from_instance(self, vinst,
+                                                         hop.llops)
         else:
             vcls = self.getfield(vinst, '__class__', hop.llops)
             return self.rclass.getclsfield(vcls, attr, hop.llops)
@@ -448,6 +496,20 @@
         vinst, vattr, vvalue = hop.inputargs(self, Void, r_value)
         self.setfield(vinst, attr, vvalue, hop.llops)
 
+    def ll_str(i, r):
+        instance = cast_pointer(OBJECTPTR, i)
+        from pypy.rpython import rstr
+        nameLen = len(instance.typeptr.name)
+        nameString = malloc(rstr.STR, nameLen-1)
+        i = 0
+        while i < nameLen - 1:
+            nameString.chars[i] = instance.typeptr.name[i]
+            i += 1
+        return rstr.ll_strconcat(rstr.instance_str_prefix,
+                                 rstr.ll_strconcat(nameString,
+                                                   rstr.instance_str_suffix))
+    ll_str = staticmethod(ll_str)
+
 
 class __extend__(pairtype(InstanceRepr, InstanceRepr)):
     def convert_from_to((r_ins1, r_ins2), v, llops):
@@ -478,6 +540,13 @@
     rinstance = getinstancerepr(hop.rtyper, classdef)
     return rinstance.new_instance(hop.llops)
 
+def instance_annotation_for_cls(rtyper, cls):
+    try:
+        classdef = rtyper.annotator.getuserclasses()[cls]
+    except KeyError:
+        raise TyperError("no classdef: %r" % (cls,))
+    return annmodel.SomeInstance(classdef)
+
 # ____________________________________________________________
 #
 #  Low-level implementation of operations on classes and instances
@@ -494,3 +563,6 @@
             return False
         subcls = subcls.parenttypeptr
     return True
+
+def ll_runtime_type_info(obj):
+    return obj.typeptr.rtti

Modified: pypy/branch/pycompiler/rpython/rfloat.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rfloat.py	(original)
+++ pypy/branch/pycompiler/rpython/rfloat.py	Fri Jul  1 18:30:34 2005
@@ -1,9 +1,13 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
-from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void
+from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Ptr
 from pypy.rpython.rmodel import Repr, TyperError, FloatRepr
 from pypy.rpython.rmodel import IntegerRepr, BoolRepr
-
+from pypy.rpython.robject import PyObjRepr, pyobj_repr
+from pypy.rpython.lltype import PyObject, Array, Char
+from pypy.rpython.rstr import STR
+from pypy.rpython.lltype import functionptr, FuncType, malloc
+from pypy.rpython import rstr
 
 debug = False
 
@@ -37,17 +41,25 @@
     rtype_inplace_mul = rtype_mul
 
     def rtype_div(_, hop):
-        return _rtype_template(hop, 'div')
+        # turn 'div' on floats into 'truediv'
+        return _rtype_template(hop, 'truediv')
+
+    rtype_inplace_div     = rtype_div
+    rtype_truediv         = rtype_div
+    rtype_inplace_truediv = rtype_div
+
+    def rtype_mod(_, hop):
+        return _rtype_template(hop, 'mod')
 
-    rtype_inplace_div = rtype_div
+    rtype_inplace_mod = rtype_mod
 
     def rtype_pow(_, hop):
         s_float3 = hop.args_s[2]
         if s_float3.is_constant() and s_float3.const is None:
             vlist = hop.inputargs(Float, Float, Void)[:2]
+            return hop.genop('float_pow', vlist, resulttype=Float)
         else:
-            vlist = hop.inputargs(Float, Float, Float)
-        return hop.genop('float_pow', vlist, resulttype=Float)
+            raise TyperError("cannot handle pow with three float arguments")
 
     def rtype_inplace_pow(_, hop):
         return _rtype_template(hop, 'pow')
@@ -74,6 +86,9 @@
     def rtype_ge(_, hop):
         return _rtype_compare_template(hop, 'ge')
 
+class __extend__(pairtype(rstr.StringRepr, FloatRepr)):
+    def rtype_mod(_, hop):
+        return rstr.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
 
 #Helpers FloatRepr,FloatRepr
 
@@ -94,6 +109,9 @@
             raise TyperError("not a float: %r" % (value,))
         return float(value)
 
+    def get_ll_eq_function(self):
+        return None 
+
     def rtype_is_true(_, hop):
         vlist = hop.inputargs(Float)
         return hop.genop('float_is_true', vlist, resulttype=Bool)
@@ -112,6 +130,34 @@
 
     rtype_float = rtype_pos
 
+    def ll_str(f, repr):
+        pyfloat = pyfloat_fromdouble_ptr(f)
+        pystring = pyobject_str_ptr(pyfloat)
+        stringsize = pystring_size_ptr(pystring)
+
+        ret = malloc(STR, stringsize)
+
+        tollchararray_ptr(pystring, ret.chars)
+
+        return ret
+        
+    ll_str = staticmethod(ll_str)
+
+PyObjectPtr = Ptr(PyObject)
+
+pystring_size_ptr = functionptr(FuncType([PyObjectPtr], Signed),
+                                "PyString_Size",
+                                external="C")
+pyfloat_fromdouble_ptr = functionptr(FuncType([Float], PyObjectPtr),
+                                     "PyFloat_FromDouble",
+                                     external="C")
+pyobject_str_ptr = functionptr(FuncType([PyObjectPtr], PyObjectPtr),
+                               "PyObject_Str",
+                               external="C")
+tollchararray_ptr = functionptr(FuncType([PyObjectPtr, Ptr(Array(Char))], Void),
+                                "PyString_ToLLCharArray",
+                                external="C")
+    
 #
 # _________________________ Conversions _________________________
 
@@ -131,3 +177,17 @@
             if debug: print 'explicit cast_bool_to_float'
             return llops.genop('cast_bool_to_float', [v], resulttype=Float)
         return NotImplemented
+
+class __extend__(pairtype(PyObjRepr, FloatRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        if r_to.lowleveltype == Float:
+            return llops.gencapicall('PyFloat_AsDouble', [v],
+                                     resulttype=Float)
+        return NotImplemented
+
+class __extend__(pairtype(FloatRepr, PyObjRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        if r_from.lowleveltype == Float:
+            return llops.gencapicall('PyFloat_FromDouble', [v],
+                                     resulttype=pyobj_repr)
+        return NotImplemented

Modified: pypy/branch/pycompiler/rpython/rint.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rint.py	(original)
+++ pypy/branch/pycompiler/rpython/rint.py	Fri Jul  1 18:30:34 2005
@@ -1,8 +1,12 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
-from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void
-from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
+from pypy.objspace.flow.objspace import op_appendices
+from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Char, \
+     UniChar, GcArray, malloc, Array
+from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, CharRepr, \
+     inputconst
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
+from pypy.rpython.rarithmetic import intmask, r_uint
 
 
 debug = False
@@ -24,10 +28,10 @@
 class __extend__(pairtype(IntegerRepr, IntegerRepr)):
 
     def convert_from_to((r_from, r_to), v, llops):
-        if r_from.lowleveltype == Unsigned and r_to.lowleveltype == Signed:
+        if r_from.lowleveltype == Signed and r_to.lowleveltype == Unsigned:
             if debug: print 'explicit cast_int_to_uint'
             return llops.genop('cast_int_to_uint', [v], resulttype=Unsigned)
-        if r_from.lowleveltype == Signed and r_to.lowleveltype == Unsigned:
+        if r_from.lowleveltype == Unsigned and r_to.lowleveltype == Signed:
             if debug: print 'explicit cast_uint_to_int'
             return llops.genop('cast_uint_to_int', [v], resulttype=Signed)
         return v
@@ -40,7 +44,6 @@
 
     def rtype_add_ovf(_, hop):
         return _rtype_template(hop, 'add_ovf')
-    rtype_inplace_add_ovf = rtype_add_ovf
 
     def rtype_sub(_, hop):
         return _rtype_template(hop, 'sub')
@@ -48,24 +51,40 @@
 
     def rtype_sub_ovf(_, hop):
         return _rtype_template(hop, 'sub_ovf')
-    rtype_inplace_sub_ovf = rtype_sub_ovf
 
     def rtype_mul(_, hop):
         return _rtype_template(hop, 'mul')
     rtype_inplace_mul = rtype_mul
 
+    def rtype_mul_ovf(_, hop):
+        return _rtype_template(hop, 'mul_ovf')
+
     def rtype_div(_, hop):
-        return _rtype_template(hop, 'div')
+        # turn 'div' on integers into 'floordiv'
+        return _rtype_template(hop, 'floordiv', [ZeroDivisionError])
     rtype_inplace_div = rtype_div
 
+    def rtype_div_ovf(_, hop):
+        return _rtype_template(hop, 'div_ovf', [ZeroDivisionError])
+
     def rtype_floordiv(_, hop):
-        return _rtype_template(hop, 'floordiv')
+        return _rtype_template(hop, 'floordiv', [ZeroDivisionError])
     rtype_inplace_floordiv = rtype_floordiv
 
+    def rtype_floordiv_ovf(_, hop):
+        return _rtype_template(hop, 'floordiv_ovf', [ZeroDivisionError])
+
+    def rtype_truediv(_, hop):
+        return _rtype_template(hop, 'truediv', [ZeroDivisionError])
+    rtype_inplace_truediv = rtype_truediv
+
     def rtype_mod(_, hop):
-        return _rtype_template(hop, 'mod')
+        return _rtype_template(hop, 'mod', [ZeroDivisionError])
     rtype_inplace_mod = rtype_mod
 
+    def rtype_mod_ovf(_, hop):
+        return _rtype_template(hop, 'mod_ovf', [ZeroDivisionError])
+
     def rtype_xor(_, hop):
         return _rtype_template(hop, 'xor')
     rtype_inplace_xor = rtype_xor
@@ -79,38 +98,40 @@
     rtype_inplace_or = rtype_or_
 
     def rtype_lshift(_, hop):
-        return _rtype_template(hop, 'lshift')
+        return _rtype_template(hop, 'lshift', [ValueError])
     rtype_inplace_lshift = rtype_lshift
 
     def rtype_lshift_ovf(_, hop):
-        return _rtype_template(hop, 'lshift_ovf')
-    rtype_inplace_lshift_ovf = rtype_lshift_ovf
+        return _rtype_template(hop, 'lshift_ovf', [ValueError])
 
     def rtype_rshift(_, hop):
-        return _rtype_template(hop, 'rshift')
+        return _rtype_template(hop, 'rshift', [ValueError])
     rtype_inplace_rshift = rtype_rshift
 
-    def rtype_rshift_ovf(_, hop):
-        return _rtype_template(hop, 'rshift_ovf')
-    rtype_inplace_rshift_ovf = rtype_rshift_ovf
-
-    def rtype_pow(_, hop):
+    def rtype_pow(_, hop, suffix=''):
+        if hop.has_implicit_exception(ZeroDivisionError):
+            suffix += '_zer'
         s_int3 = hop.args_s[2]
         if hop.s_result.unsigned:
             if s_int3.is_constant() and s_int3.const is None:
                 vlist = hop.inputargs(Unsigned, Unsigned, Void)[:2]
             else:
                 vlist = hop.inputargs(Unsigned, Unsigned, Unsigned)
-            return hop.genop('uint_pow', vlist, resulttype=Unsigned)
+            return hop.genop('uint_pow' + suffix, vlist, resulttype=Unsigned)
         else:
             if s_int3.is_constant() and s_int3.const is None:
                 vlist = hop.inputargs(Signed, Signed, Void)[:2]
             else:
                 vlist = hop.inputargs(Signed, Signed, Signed)
-            return hop.genop('int_pow', vlist, resulttype=Signed)
+            return hop.genop('int_pow' + suffix, vlist, resulttype=Signed)
+
+    def rtype_pow_ovf(_, hop):
+        if hop.s_result.unsigned:
+            raise TyperError("forbidden uint_pow_ovf")
+        return self.rtype_pow(_, hop, suffix='_ovf')
 
     def rtype_inplace_pow(_, hop):
-        return _rtype_template(hop, 'pow')
+        return _rtype_template(hop, 'pow', [ZeroDivisionError])
 
     #comparisons: eq is_ ne lt le gt ge
 
@@ -136,8 +157,15 @@
 
 #Helper functions
 
-def _rtype_template(hop, func):
+def _rtype_template(hop, func, implicit_excs=[]):
+    func1 = func
+    for implicit_exc in implicit_excs:
+        if hop.has_implicit_exception(implicit_exc):
+            appendix = op_appendices[implicit_exc]
+            func += '_' + appendix
     if hop.s_result.unsigned:
+        if func1.endswith('_ovf'):
+            raise TyperError("forbidden uint_" + func)
         vlist = hop.inputargs(Unsigned, Unsigned)
         return hop.genop('uint_'+func, vlist, resulttype=Unsigned)
     else:
@@ -163,14 +191,29 @@
 class __extend__(IntegerRepr):
 
     def convert_const(self, value):
-        if not isinstance(value, int):   # can be bool
+        if not isinstance(value, (int, r_uint)):   # can be bool
             raise TyperError("not an integer: %r" % (value,))
-        return int(value)
+        if self.lowleveltype == Signed:
+            return intmask(value)
+        if self.lowleveltype == Unsigned:
+            return r_uint(value)
+        raise NotImplementedError
+
+    def get_ll_eq_function(self):
+        return None 
 
     def rtype_float(_, hop):
         vlist = hop.inputargs(Float)
         return vlist[0]
 
+    def rtype_chr(_, hop):
+        vlist =  hop.inputargs(Signed)
+        return hop.genop('cast_int_to_char', vlist, resulttype=Char)
+
+    def rtype_unichr(_, hop):
+        vlist =  hop.inputargs(Signed)
+        return hop.genop('cast_int_to_unichar', vlist, resulttype=UniChar)
+
     def rtype_is_true(self, hop):
         if self.lowleveltype == Unsigned:
             vlist = hop.inputargs(Unsigned)
@@ -191,8 +234,7 @@
 
     def rtype_abs_ovf(_, hop):
         if hop.s_result.unsigned:
-            vlist = hop.inputargs(Unsigned)
-            return vlist[0]
+            raise TyperError("forbidden uint_abs_ovf")
         else:
             vlist = hop.inputargs(Signed)
             return hop.genop('int_abs_ovf', vlist, resulttype=Signed)
@@ -213,6 +255,13 @@
             vlist = hop.inputargs(Signed)
             return hop.genop('int_neg', vlist, resulttype=Signed)
 
+    def rtype_neg_ovf(_, hop):
+        if hop.s_result.unsigned:
+            raise TyperError("forbidden uint_neg_ovf")
+        else:
+            vlist = hop.inputargs(Signed)
+            return hop.genop('int_neg_ovf', vlist, resulttype=Signed)
+
     def rtype_pos(_, hop):
         if hop.s_result.unsigned:
             vlist = hop.inputargs(Unsigned)
@@ -230,6 +279,82 @@
         vlist = hop.inputargs(Float)
         return vlist[0]
 
+    def ll_str(i, repr):
+        from pypy.rpython.rstr import STR
+        temp = malloc(CHAR_ARRAY, 20)
+        len = 0
+        sign = 0
+        if i < 0:
+            sign = 1
+            i = -i
+        if i == 0:
+            len = 1
+            temp[0] = '0'
+        else:
+            while i:
+                temp[len] = chr(i%10+ord('0'))
+                i //= 10
+                len += 1
+        len += sign
+        result = malloc(STR, len)
+        if sign:
+            result.chars[0] = '-'
+            j = 1
+        else:
+            j = 0
+        while j < len:
+            result.chars[j] = temp[len-j-1]
+            j += 1
+        return result
+    ll_str = staticmethod(ll_str)
+
+    def rtype_hex(_, hop):
+        varg = hop.inputarg(hop.args_r[0], 0)
+        true = inputconst(Bool, True)
+        return hop.gendirectcall(ll_int2hex, varg, true)
+
+
+
+CHAR_ARRAY = GcArray(Char)
+
+hex_chars = malloc(Array(Char), 16, immortal=True)
+
+for i in range(16):
+    hex_chars[i] = "%x"%i
+
+def ll_int2hex(i, addPrefix):
+    from pypy.rpython.rstr import STR
+    temp = malloc(CHAR_ARRAY, 20)
+    len = 0
+    sign = 0
+    if i < 0:
+        sign = 1
+        i = -i
+    if i == 0:
+        len = 1
+        temp[0] = '0'
+    else:
+        while i:
+            temp[len] = hex_chars[i%16]
+            i //= 16
+            len += 1
+    len += sign
+    if addPrefix:
+        len += 2
+    result = malloc(STR, len)
+    j = 0
+    if sign:
+        result.chars[0] = '-'
+        j = 1
+    if addPrefix:
+        result.chars[j] = '0'
+        result.chars[j+1] = 'x'
+        j += 2
+    while j < len:
+        result.chars[j] = temp[len-j-1]
+        j += 1
+    return result
+
 #
 # _________________________ Conversions _________________________
 

Modified: pypy/branch/pycompiler/rpython/rlist.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rlist.py	(original)
+++ pypy/branch/pycompiler/rpython/rlist.py	Fri Jul  1 18:30:34 2005
@@ -1,11 +1,15 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow.model import Constant
-from pypy.rpython.lltype import *
-from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
+from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst
 from pypy.rpython import rrange
 from pypy.rpython.rslice import SliceRepr
 from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr
+from pypy.rpython.rclass import InstanceRepr
+from pypy.rpython.lltype import GcForwardReference, Ptr, GcArray, GcStruct
+from pypy.rpython.lltype import Void, Signed, malloc, typeOf, Primitive
+from pypy.rpython.lltype import Bool
+from pypy.rpython import rstr
 
 # ____________________________________________________________
 #
@@ -44,6 +48,7 @@
         else:
             self.item_repr = item_repr
         self.listitem = listitem
+        self.list_cache = {}
         # setup() needs to be called to finish this initialization
 
     def setup(self):
@@ -51,9 +56,35 @@
             self.item_repr = self._item_repr_computer()
         if isinstance(self.LIST, GcForwardReference):
             ITEM = self.item_repr.lowleveltype
-            ITEMARRAY = GcArray(("item", ITEM))
+            ITEMARRAY = GcArray(ITEM)
             self.LIST.become(GcStruct("list", ("items", Ptr(ITEMARRAY))))
 
+    def convert_const(self, listobj):
+        # get object from bound list method
+        listobj = getattr(listobj, '__self__', listobj)
+        if not isinstance(listobj, list):
+            raise TyperError("expected a list: %r" % (listobj,))
+        try:
+            key = Constant(listobj)
+            return self.list_cache[key]
+        except KeyError:
+            self.setup()
+            result = malloc(self.LIST, immortal=True)
+            self.list_cache[key] = result
+            result.items = malloc(self.LIST.items.TO, len(listobj))
+            r_item = self.item_repr
+            for i in range(len(listobj)):
+                x = listobj[i]
+                result.items[i] = r_item.convert_const(x)
+            return result
+
+    def get_eqfunc(self):
+        return inputconst(Void, self.item_repr.get_ll_eq_function())
+
+    def rtype_bltn_list(self,hop):
+        v_lst = hop.inputarg(self,0)
+        return hop.gendirectcall(ll_copy,v_lst)
+    
     def rtype_len(self, hop):
         v_lst, = hop.inputargs(self)
         return hop.gendirectcall(ll_len, v_lst)
@@ -62,13 +93,76 @@
         v_lst, v_value = hop.inputargs(self, self.item_repr)
         hop.gendirectcall(ll_append, v_lst, v_value)
 
+    def rtype_method_index(self, hop):
+        v_lst, v_value = hop.inputargs(self, self.item_repr)
+        return hop.gendirectcall(ll_listindex, v_lst, v_value, self.get_eqfunc())
+
+    def rtype_method_insert(self, hop):
+        v_lst, v_index, v_value = hop.inputargs(self, Signed, self.item_repr)
+        arg1 = hop.args_s[1]
+        args = v_lst, v_index, v_value
+        if arg1.is_constant() and arg1.const == 0:
+            llfn = ll_prepend
+            args = v_lst, v_value
+        elif arg1.nonneg:
+            llfn = ll_insert_nonneg
+        else:
+            llfn = ll_insert
+        hop.gendirectcall(llfn, *args)
+
     def rtype_method_extend(self, hop):
         v_lst1, v_lst2 = hop.inputargs(self, self)
         hop.gendirectcall(ll_extend, v_lst1, v_lst2)
+    
+    def rtype_method_reverse(self, hop):
+        v_lst, = hop.inputargs(self)
+        hop.gendirectcall(ll_reverse,v_lst)
+
+    def rtype_method_pop(self, hop):
+        if hop.nb_args == 2:
+            args = hop.inputargs(self, Signed)
+            assert hasattr(args[1], 'concretetype')
+            arg1 = hop.args_s[1]
+            if arg1.is_constant() and arg1.const == 0:
+                llfn = ll_pop_zero
+                args = args[:1]
+            elif hop.args_s[1].nonneg:
+                llfn = ll_pop_nonneg
+            else:
+                llfn = ll_pop
+        else:
+            args = hop.inputargs(self)
+            llfn = ll_pop_default
+        return hop.gendirectcall(llfn, *args)
 
     def make_iterator_repr(self):
         return ListIteratorRepr(self)
 
+    def ll_str(l, listrepr):
+        items = l.items
+        length = len(items)
+        item_repr = listrepr.item_repr
+
+        temp = malloc(TEMP, length)
+        i = 0
+        while i < length:
+            temp[i] = item_repr.ll_str(items[i], item_repr)
+            i += 1
+
+        return rstr.ll_strconcat(
+            rstr.list_str_open_bracket,
+            rstr.ll_strconcat(rstr.ll_join(rstr.list_str_sep,
+                                           temp),
+                              rstr.list_str_close_bracket))
+    ll_str = staticmethod(ll_str)
+    
+
+class __extend__(pairtype(ListRepr, Repr)):
+
+    def rtype_contains((r_lst, _), hop):
+        v_lst, v_any = hop.inputargs(r_lst, r_lst.item_repr)
+        return hop.gendirectcall(ll_listcontains, v_lst, v_any, r_lst.get_eqfunc())
+
 
 class __extend__(pairtype(ListRepr, IntegerRepr)):
 
@@ -79,7 +173,7 @@
         else:
             llfn = ll_getitem
         return hop.gendirectcall(llfn, v_lst, v_index)
-
+    
     def rtype_setitem((r_lst, r_int), hop):
         v_lst, v_index, v_item = hop.inputargs(r_lst, Signed, r_lst.item_repr)
         if hop.args_s[1].nonneg:
@@ -135,12 +229,33 @@
         hop.gendirectcall(ll_extend, v_lst1, v_lst2)
         return v_lst1
 
+    def rtype_eq((self, _), hop):
+        v_lst1, v_lst2 = hop.inputargs(self, self)
+        return hop.gendirectcall(ll_listeq, v_lst1, v_lst2, self.get_eqfunc())
+
+    def rtype_ne((self, _), hop):
+        v_lst1, v_lst2 = hop.inputargs(self, self)
+        flag = hop.gendirectcall(ll_listeq, v_lst1, v_lst2, self.get_eqfunc())
+        return hop.genop('bool_not', [flag], resulttype=Bool)
+
+
 # ____________________________________________________________
 #
 #  Low-level methods.  These can be run for testing, but are meant to
 #  be direct_call'ed from rtyped flow graphs, which means that they will
 #  get flowed and annotated, mostly with SomePtr.
 
+def ll_copy(l):
+    items = l.items
+    length = len(items)
+    new_lst = ll_newlist(typeOf(l), length)
+    i = 0
+    new_items = new_lst.items
+    while i < length:
+        new_items[i] = items[i]
+        i += 1
+    return new_lst
+
 def ll_len(l):
     return len(l.items)
 
@@ -148,65 +263,132 @@
     length = len(l.items)
     newitems = malloc(typeOf(l).TO.items.TO, length+1)
     i = 0
-    while i<length:
-        newitems[i].item = l.items[i].item
+    while i < length:
+        newitems[i] = l.items[i]
+        i += 1
+    newitems[length] = newitem
+    l.items = newitems
+
+# this one is for the special case of insert(0, x)
+def ll_prepend(l, newitem):
+    length = len(l.items)
+    newitems = malloc(typeOf(l).TO.items.TO, length+1)
+    i = 0
+    while i < length:
+        newitems[i+1] = l.items[i]
         i += 1
-    newitems[length].item = newitem
+    newitems[0] = newitem
+    l.items = newitems
+
+def ll_insert_nonneg(l, index, newitem):
+    length = len(l.items)
+    newitems = malloc(typeOf(l).TO.items.TO, length+1)
+    i = 0
+    while i < index:
+        newitems[i] = l.items[i]
+        i += 1
+    newitems[i] = newitem
+    i += 1
+    while i <= length:
+        newitems[i] = l.items[i-1]
+        i += 1
+    l.items = newitems
+
+def ll_insert(l, index, newitem):
+    if index < 0:
+        index += len(l.items)
+    ll_insert_nonneg(l, index, newitem)
+
+def ll_pop_nonneg(l, index):
+    res = l.items[index]
+    ll_delitem_nonneg(l, index)
+    return res
+
+def ll_pop_default(l):
+    index = len(l.items) - 1
+    res = l.items[index]
+    newlength = index
+    newitems = malloc(typeOf(l).TO.items.TO, newlength)
+    j = 0
+    while j < newlength:
+        newitems[j] = l.items[j]
+        j += 1
+    l.items = newitems
+    return res
+
+def ll_pop_zero(l):
+    index = len(l.items) - 1
+    res = l.items[0]
+    newlength = index
+    newitems = malloc(typeOf(l).TO.items.TO, newlength)
+    j = 0
+    while j < newlength:
+        newitems[j] = l.items[j+1]
+        j += 1
     l.items = newitems
+    return res
+
+def ll_pop(l, index):
+    if index < 0:
+        index += len(l.items)
+    res = l.items[index]
+    ll_delitem_nonneg(l, index)
+    return res
+
+def ll_reverse(l):
+    length = len(l.items)
+    len2 = length // 2 # moved this out of the loop
+    i = 0
+    while i < len2:
+        tmp = l.items[i]
+        l.items[i] = l.items[length-1-i]
+        l.items[length-1-i] = tmp
+        i += 1
 
 def ll_getitem_nonneg(l, i):
-    return l.items[i].item
+    return l.items[i]
 
 def ll_getitem(l, i):
-    if i<0:
+    if i < 0:
         i += len(l.items)
-    return l.items[i].item
+    return l.items[i]
 
 def ll_setitem_nonneg(l, i, newitem):
-    l.items[i].item = newitem
+    l.items[i] = newitem
 
 def ll_setitem(l, i, newitem):
-    if i<0:
-        i += len(l.items)
-    l.items[i].item = newitem
-
-def ll_delitem(l, i):
     if i < 0:
         i += len(l.items)
-    newlength = len(l.items) - 1
-    newitems = malloc(typeOf(l).TO.items.TO, newlength)
-    j = 0
-    while j < i:
-        newitems[j].item = l.items[j].item
-        j += 1
-    while j < newlength:
-        newitems[j].item = l.items[j+1].item
-        j += 1
-    l.items = newitems
+    l.items[i] = newitem
 
 def ll_delitem_nonneg(l, i):
     newlength = len(l.items) - 1
     newitems = malloc(typeOf(l).TO.items.TO, newlength)
     j = 0
     while j < i:
-        newitems[j].item = l.items[j].item
+        newitems[j] = l.items[j]
         j += 1
     while j < newlength:
-        newitems[j].item = l.items[j+1].item
+        newitems[j] = l.items[j+1]
         j += 1
     l.items = newitems
 
+def ll_delitem(l, i):
+    if i < 0:
+        i += len(l.items)
+    ll_delitem_nonneg(l, i)
+
 def ll_concat(l1, l2):
     len1 = len(l1.items)
     len2 = len(l2.items)
     newitems = malloc(typeOf(l1).TO.items.TO, len1 + len2)
     j = 0
     while j < len1:
-        newitems[j].item = l1.items[j].item
+        newitems[j] = l1.items[j]
         j += 1
     i = 0
     while i < len2:
-        newitems[j].item = l2.items[i].item
+        newitems[j] = l2.items[i]
         i += 1
         j += 1
     l = malloc(typeOf(l1).TO)
@@ -219,11 +401,11 @@
     newitems = malloc(typeOf(l1).TO.items.TO, len1 + len2)
     j = 0
     while j < len1:
-        newitems[j].item = l1.items[j].item
+        newitems[j] = l1.items[j]
         j += 1
     i = 0
     while i < len2:
-        newitems[j].item = l2.items[i].item
+        newitems[j] = l2.items[i]
         i += 1
         j += 1
     l1.items = newitems
@@ -233,7 +415,7 @@
     newitems = malloc(typeOf(l1).TO.items.TO, len1 - start)
     j = 0
     while start < len1:
-        newitems[j].item = l1.items[start].item
+        newitems[j] = l1.items[start]
         start += 1
         j += 1
     l = malloc(typeOf(l1).TO)
@@ -246,7 +428,7 @@
     newitems = malloc(typeOf(l1).TO.items.TO, stop - start)
     j = 0
     while start < stop:
-        newitems[j].item = l1.items[start].item
+        newitems[j] = l1.items[start]
         start += 1
         j += 1
     l = malloc(typeOf(l1).TO)
@@ -257,7 +439,7 @@
     newitems = malloc(typeOf(l1).TO.items.TO, start)
     j = 0
     while j < start:
-        newitems[j].item = l1.items[j].item
+        newitems[j] = l1.items[j]
         j += 1
     l1.items = newitems
 
@@ -268,16 +450,70 @@
     newitems = malloc(typeOf(l1).TO.items.TO, newlength)
     j = 0
     while j < start:
-        newitems[j].item = l1.items[j].item
+        newitems[j] = l1.items[j]
         j += 1
     while j < newlength:
-        newitems[j].item = l1.items[stop].item
+        newitems[j] = l1.items[stop]
         stop += 1
         j += 1
     l1.items = newitems
 
 # ____________________________________________________________
 #
+#  Comparison.
+
+def ll_listeq(l1, l2, eqfn):
+    len1 = len(l1.items)
+    len2 = len(l2.items)
+    if len1 != len2:
+        return False
+    j = 0
+    items1 = l1.items
+    items2 = l2.items
+    while j < len1:
+        if eqfn is None:
+            if items1[j] != items2[j]:
+                return False
+        else:
+            if not eqfn(items1[j], items2[j]):
+                return False
+        j += 1
+    return True
+
+def ll_listcontains(lst, obj, eqfn):
+    items = lst.items
+    lng = len(items)
+    j = 0
+    while j < lng:
+        if eqfn is None:
+            if items[j] == obj:
+                return True
+        else:
+            if eqfn(items[j], obj):
+                return True
+        j += 1
+    return False
+
+def ll_listindex(lst, obj, eqfn):
+    items = lst.items
+    lng = len(items)
+    j = 0
+    while j < lng:
+        if eqfn is None:
+            if items[j] == obj:
+                return j
+        else:
+            if eqfn(items[j], obj):
+                return j
+        j += 1
+    raise ValueError # can't say 'list.index(x): x not in list'
+
+TEMP = GcArray(Ptr(rstr.STR))
+
+        
+        
+# ____________________________________________________________
+#
 #  Irregular operations.
 
 def ll_newlist(LISTPTR, length):
@@ -303,7 +539,7 @@
     l.items = malloc(LISTPTR.TO.items.TO, count)
     i = 0
     while i < count:
-        l.items[i].item = item
+        l.items[i] = item
         i += 1
     return l
 
@@ -346,4 +582,4 @@
     if index >= len(l.items):
         raise StopIteration
     iter.index = index + 1
-    return l.items[index].item
+    return l.items[index]

Modified: pypy/branch/pycompiler/rpython/rmodel.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rmodel.py	(original)
+++ pypy/branch/pycompiler/rpython/rmodel.py	Fri Jul  1 18:30:34 2005
@@ -1,7 +1,7 @@
 from pypy.annotation.pairtype import pair, pairtype, extendabletype
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow.model import Constant
-from pypy.rpython.lltype import Void, Bool, Float, Signed, Char
+from pypy.rpython.lltype import Void, Bool, Float, Signed, Char, UniChar
 from pypy.rpython.lltype import typeOf, LowLevelType, Ptr, PyObject
 from pypy.rpython.lltype import FuncType, functionptr
 
@@ -10,7 +10,7 @@
     """ An instance of Repr is associated with each instance of SomeXxx.
     It defines the chosen representation for the SomeXxx.  The Repr subclasses
     generally follows the SomeXxx subclass hierarchy, but there are numerous
-    exceptions.  For example, the anotator uses SomeIter for any iterator, but
+    exceptions.  For example, the annotator uses SomeIter for any iterator, but
     we need different representations according to the type of container we are
     iterating over.
     """
@@ -22,6 +22,11 @@
     def setup(self):
         "For recursive data structure, which must be initialized in two steps."
 
+    def setup_final_touch(self):
+        """Same as setup(), called a bit later, for effects that are only
+        needed after the typer finished (as opposed to needed for other parts
+        of the typer itself)."""
+
     def __getattr__(self, name):
         # Assume that when an attribute is missing, it's because setup() needs
         # to be called
@@ -32,6 +37,9 @@
             raise AttributeError("%s instance has no attribute %s" % (
                 self.__class__.__name__, name))
 
+    def _freeze_(self):
+        return True
+
     def convert_const(self, value):
         "Convert the given constant value to the low-level repr of 'self'."
         if self.lowleveltype != Void:
@@ -44,6 +52,9 @@
                     self, value))
         return value
 
+    def get_ll_eq_function(self): 
+        raise TyperError, 'no equality function for %r' % self
+
     # default implementation of some operations
 
     def rtype_getattr(self, hop):
@@ -61,6 +72,10 @@
         else:
             raise TyperError("getattr() with a non-constant attribute name")
 
+    def rtype_str(self, hop):
+        vrepr = inputconst(Void, self)
+        return hop.gendirectcall(self.ll_str, hop.args_v[0], vrepr)
+
     def rtype_nonzero(self, hop):
         return self.rtype_is_true(hop)   # can call a subclass' rtype_is_true()
 
@@ -72,6 +87,14 @@
         else:
             return hop.genop('int_is_true', [vlen], resulttype=Bool)
 
+    def rtype_id(self, hop):
+        if not isinstance(self.lowleveltype, Ptr):
+            raise TyperError('id() of an instance of the non-pointer %r' % (
+                self,))
+        vobj, = hop.inputargs(self)
+        # XXX
+        return hop.genop('cast_ptr_to_int', [vobj], resulttype=Signed)
+
     def rtype_iter(self, hop):
         r_iter = self.make_iterator_repr()
         return r_iter.newiter(hop)
@@ -93,6 +116,23 @@
     def rtyper_makekey(self):
         return None
 
+# ____ generic binary operations _____________________________
+
+
+class __extend__(pairtype(Repr, Repr)):
+    
+    def rtype_is_((robj1, robj2), hop):
+        if (not isinstance(robj1.lowleveltype, Ptr) or
+            not isinstance(robj2.lowleveltype, Ptr)):
+            raise TyperError('is of instances of the non-pointers: %r, %r' % (
+                robj1, robj2))
+        if robj1.lowleveltype != robj2.lowleveltype:
+            raise TyperError('is of instances of different pointer types: %r, %r' % (
+                robj1, robj2))
+            
+        v_list = hop.inputargs(robj1, robj2)
+        return hop.genop('ptr_eq', v_list, resulttype=Bool)
+
 # ____________________________________________________________
 
 class TyperError(Exception):
@@ -143,6 +183,9 @@
 class CharRepr(StringRepr):
     lowleveltype = Char
 
+class UniCharRepr(Repr):
+    lowleveltype = UniChar
+
 class VoidRepr(Repr):
     lowleveltype = Void
 impossible_repr = VoidRepr()
@@ -168,8 +211,10 @@
         except (AssertionError, AttributeError):
             realtype = '???'
         if realtype != lltype:
-            raise TyperError("inputconst(reqtype = %s, value = %s)" % (
-                reqtype, value))
+            raise TyperError("inputconst(reqtype = %s, value = %s):\n"
+                             "expected a %r,\n"
+                             "     got a %r" % (reqtype, value,
+                                                lltype, realtype))
     c = Constant(value)
     c.concretetype = lltype
     return c
@@ -188,3 +233,4 @@
     lloutput = getconcretetype(graph.getreturnvar())
     FT = FuncType(llinputs, lloutput)
     return functionptr(FT, func.func_name, graph = graph, _callable = func)
+

Modified: pypy/branch/pycompiler/rpython/robject.py
==============================================================================
--- pypy/branch/pycompiler/rpython/robject.py	(original)
+++ pypy/branch/pycompiler/rpython/robject.py	Fri Jul  1 18:30:34 2005
@@ -1,7 +1,7 @@
 from pypy.annotation.pairtype import pair, pairtype
 from pypy.annotation import model as annmodel
-from pypy.rpython.lltype import PyObject, Ptr, Void, Bool, pyobjectptr
-from pypy.rpython.rmodel import Repr, TyperError
+from pypy.rpython.lltype import PyObject, Ptr, Void, Bool, pyobjectptr, nullptr
+from pypy.rpython.rmodel import Repr, TyperError, VoidRepr, inputconst
 from pypy.rpython import rclass
 from pypy.tool.sourcetools import func_with_new_name
 
@@ -32,6 +32,14 @@
 constpyobj_repr = PyObjRepr()
 constpyobj_repr.lowleveltype = Void
 
+
+class __extend__(pairtype(VoidRepr, PyObjRepr)):
+    # conversion used to return a PyObject* when a function can really only
+    # raise an exception, in which case the return value is a VoidRepr
+    def convert_from_to(_, v, llops):
+        return inputconst(Ptr(PyObject), nullptr(PyObject))
+
+
 # ____________________________________________________________
 #
 #  All operations involving a PyObjRepr are "replaced" by themselves,
@@ -46,7 +54,7 @@
 
     funcname = 'rtype_' + opname
     func = func_with_new_name(rtype_op, funcname)
-    assert funcname not in cls.__dict__  # can be in Repr; overriden then.
+    assert funcname not in cls.__dict__  # can be in Repr; overridden then.
     setattr(cls, funcname, func)
 
 

Modified: pypy/branch/pycompiler/rpython/rpbc.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rpbc.py	(original)
+++ pypy/branch/pycompiler/rpython/rpbc.py	Fri Jul  1 18:30:34 2005
@@ -1,28 +1,33 @@
 import types
-from pypy.annotation.pairtype import pairtype
+from pypy.annotation.pairtype import pairtype, pair
 from pypy.annotation import model as annmodel
 from pypy.annotation.classdef import isclassdef
-from pypy.rpython.lltype import typeOf, Void
-from pypy.rpython.rmodel import Repr, TyperError
+from pypy.objspace.flow.model import Constant
+from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct, Bool
+from pypy.rpython.lltype import Ptr, malloc, nullptr
+from pypy.rpython.rmodel import Repr, TyperError, inputconst
 from pypy.rpython import rclass
-
+from pypy.rpython.rtyper import HighLevelOp
+from pypy.rpython import robject
 
 class __extend__(annmodel.SomePBC):
     def rtyper_makerepr(self, rtyper):
         # for now, we require that the PBC fits neatly into one of the Repr
         # categories below, and doesn't for example mix functions, classes
         # and methods.
-        callb = rtyper.annotator.getpbccallables()
+        call_families = rtyper.annotator.getpbccallfamilies()
         choices = {}
         for x, classdef in self.prebuiltinstances.items():
             cdefflag = isclassdef(classdef)
+            if not cdefflag:
+                classdef = None
 
             # consider unbound methods as plain functions
             if isinstance(x, types.MethodType) and x.im_self is None:
                 x = x.im_func
 
             # callable or frozen object?
-            if x in callb:
+            if (classdef, x) in call_families:
                 # what type of callable?
                 if isinstance(x, types.FunctionType):
                     if cdefflag:
@@ -32,13 +37,13 @@
                         choice = FunctionsPBCRepr
                 elif isinstance(x, (type, types.ClassType)):
                     choice = ClassesPBCRepr
-                #elif isinstance(x, types.MethodType):
-                #    choice = ConstMethodsPBCRepr
+                elif isinstance(x, types.MethodType):
+                    choice = MethodOfFrozenPBCRepr
                 else:
                     raise TyperError("don't know about callable %r" % (x,))
             else:
                 # frozen object
-                choice = FrozenPBCRepr
+                choice = getFrozenPBCRepr
 
             if cdefflag:
                 raise TyperError("unexpected classdef in PBC set %r" % (
@@ -56,22 +61,185 @@
         lst.sort()
         return tuple(lst)
 
-
 # ____________________________________________________________
 
 
-class FrozenPBCRepr(Repr):
+def getFrozenPBCRepr(rtyper, s_pbc):
+    if len(s_pbc.prebuiltinstances) <= 1:
+        if s_pbc.const is None:
+            return none_frozen_pbc_repr
+        return single_frozen_pbc_repr
+    else:
+        pbcs = [pbc for pbc in s_pbc.prebuiltinstances.keys()
+                    if pbc is not None]
+        access_sets = rtyper.annotator.getpbcaccesssets()
+        _, _, access = access_sets.find(pbcs[0])
+        for obj in pbcs[1:]:
+            _, _, access1 = access_sets.find(obj)
+            assert access1 is access       # XXX not implemented
+        try:
+            return rtyper.pbc_reprs[access]
+        except KeyError:
+            result = MultipleFrozenPBCRepr(rtyper, access)
+            rtyper.pbc_reprs[access] = result
+            rtyper.reprs_must_call_setup.append(result)
+            return result
+
+
+class SingleFrozenPBCRepr(Repr):
     """Representation selected for a single non-callable pre-built constant."""
     lowleveltype = Void
 
-    def __init__(self, rtyper, s_pbc):
-        assert len(s_pbc.prebuiltinstances) == 1   # XXX not implemented
-
     def rtype_getattr(_, hop):
         if not hop.s_result.is_constant():
             raise TyperError("getattr on a constant PBC returns a non-constant")
         return hop.inputconst(hop.r_result, hop.s_result.const)
 
+single_frozen_pbc_repr = SingleFrozenPBCRepr()
+
+# __ None ____________________________________________________
+class NoneFrozenPBCRepr(SingleFrozenPBCRepr):
+    
+    def rtype_is_true(self, hop):
+        return Constant(False, Bool)
+
+none_frozen_pbc_repr = NoneFrozenPBCRepr()
+
+
+def rtype_is_None(robj1, rnone2, hop, pos=0):
+        if not isinstance(robj1.lowleveltype, Ptr):
+            raise TyperError('is None of instance of the non-pointer: %r' % (robj1))           
+        v1 = hop.inputarg(robj1, pos)
+        return hop.genop('ptr_iszero', [v1], resulttype=Bool)
+    
+class __extend__(pairtype(Repr, NoneFrozenPBCRepr)):
+    
+    def rtype_is_((robj1, rnone2), hop):
+        return rtype_is_None(robj1, rnone2, hop)
+
+class __extend__(pairtype(NoneFrozenPBCRepr, Repr)):
+
+    def rtype_is_((rnone1, robj2), hop):
+        return rtype_is_None(robj2, rnone1, hop, pos=1)
+        
+class __extend__(pairtype(NoneFrozenPBCRepr, robject.PyObjRepr)):
+
+    def convert_from_to(_, v, llops):
+        return inputconst(robject.pyobj_repr, None)
+
+# ____________________________________________________________
+
+class MultipleFrozenPBCRepr(Repr):
+    """Representation selected for multiple non-callable pre-built constants."""
+    initialized = False
+
+    def __init__(self, rtyper, access_set):
+        self.rtyper = rtyper
+        self.access_set = access_set
+        self.pbc_type = ForwardReference()
+        self.lowleveltype = Ptr(self.pbc_type)
+        self.pbc_cache = {}
+
+    def setup(self):
+        if self.initialized:
+            assert self.initialized == True
+            return
+        self.initialized = "in progress"
+        llfields = []
+        llfieldmap = {}
+        attrlist = self.access_set.attrs.keys()
+        attrlist.sort()
+        for attr in attrlist:
+            s_value = self.access_set.attrs[attr]
+            r_value = self.rtyper.getrepr(s_value)
+            mangled_name = 'pbc_' + attr
+            llfields.append((mangled_name, r_value.lowleveltype))
+            llfieldmap[attr] = mangled_name, r_value
+        self.pbc_type.become(Struct('pbc', *llfields))
+        self.llfieldmap = llfieldmap
+        self.initialized = True
+
+    def convert_const(self, pbc):
+        if pbc is None:
+            return nullptr(self.pbc_type)
+        if isinstance(pbc, types.MethodType) and pbc.im_self is None:
+            value = pbc.im_func   # unbound method -> bare function
+##        if pbc not in self.access_set.objects:
+##            raise TyperError("not found in PBC set: %r" % (pbc,))
+        try:
+            return self.pbc_cache[pbc]
+        except KeyError:
+            self.setup()
+            result = malloc(self.pbc_type, immortal=True)
+            self.pbc_cache[pbc] = result
+            for attr, (mangled_name, r_value) in self.llfieldmap.items():
+                try: 
+                    thisattrvalue = self.access_set.values[(pbc, attr)] 
+                except KeyError: 
+                    thisattrvalue = getattr(pbc, attr)
+                llvalue = r_value.convert_const(thisattrvalue)
+                setattr(result, mangled_name, llvalue)
+            return result
+
+    def rtype_is_true(self, hop):
+        if hop.s_result.is_constant():
+            assert hop.s_result.const is True    # custom __nonzero__ on PBCs?
+            return hop.inputconst(Bool, hop.s_result.const)
+        else:
+            # None is a nullptr, which is false; everything else is true.
+            vlist = hop.inputargs(self)
+            return hop.genop('ptr_nonzero', vlist, resulttype=Bool)
+
+    def rtype_getattr(self, hop):
+        attr = hop.args_s[1].const
+        vpbc, vattr = hop.inputargs(self, Void)
+        return self.getfield(vpbc, attr, hop.llops)
+
+    def getfield(self, vpbc, attr, llops):
+        mangled_name, r_value = self.llfieldmap[attr]
+        cmangledname = inputconst(Void, mangled_name)
+        return llops.genop('getfield', [vpbc, cmangledname],
+                           resulttype = r_value)
+
+
+# ____________________________________________________________
+
+
+class MethodOfFrozenPBCRepr(Repr):
+    """Representation selected for a PBC of method object(s) of frozen PBCs.
+    It assumes that all methods are the same function bound to different PBCs.
+    The low-level representation can then be a pointer to that PBC."""
+
+    def __init__(self, rtyper, s_pbc):
+        self.rtyper = rtyper
+        self.function = s_pbc.prebuiltinstances.keys()[0].im_func
+        im_selves = {}
+        for pbc, not_a_classdef in s_pbc.prebuiltinstances.items():
+            assert pbc.im_func is self.function
+            assert not isclassdef(not_a_classdef)
+            im_selves[pbc.im_self] = True
+        self.s_im_self = annmodel.SomePBC(im_selves)
+        self.r_im_self = rtyper.getrepr(self.s_im_self)
+        self.lowleveltype = self.r_im_self.lowleveltype
+
+    def convert_const(self, method):
+        if getattr(method, 'im_func', None) is not self.function:
+            raise TyperError("not a method bound on %r: %r" % (self.function,
+                                                               method))
+        return self.r_im_self.convert_const(method.im_self)
+
+    def rtype_simple_call(self, hop):
+        s_function = annmodel.SomePBC({self.function: True})
+        hop2 = hop.copy()
+        hop2.args_s[0] = self.s_im_self   # make the 1st arg stand for 'im_self'
+        hop2.args_r[0] = self.r_im_self   # (same lowleveltype as 'self')
+        if isinstance(hop2.args_v[0], Constant):
+            hop2.args_v[0] = hop.inputarg(self, 0)
+        c = Constant(self.function)
+        hop2.v_s_insertfirstarg(c, s_function)   # insert 'function'
+        # now hop2 looks like simple_call(function, self, args...)
+        return hop2.dispatch()
+
 
 # ____________________________________________________________
 
@@ -124,6 +292,8 @@
 ##                assert not shape_stst, "XXX not implemented"
 
     def convert_const(self, value):
+        if isinstance(value, types.MethodType) and value.im_self is None:
+            value = value.im_func   # unbound method -> bare function
         if value not in self.function_signatures:
             raise TyperError("%r not in %r" % (value,
                                                self.s_pbc.prebuiltinstances))
@@ -132,12 +302,40 @@
 
     def rtype_simple_call(self, hop):
         f, rinputs, rresult = self.function_signatures.itervalues().next()
-        vlist = hop.inputargs(self, *rinputs)
+        defaultclist = []
+        if len(rinputs) != hop.nb_args-1:  # argument count mismatch
+            assert not getattr(f._obj.graph, 'normalized_for_calls', False), (
+                "normalization bug")
+            assert len(self.function_signatures) == 1, "normalization bug too"
+            func, = self.function_signatures.keys()
+            defaults = func.func_defaults or ()
+            if len(rinputs) - len(defaults) <= hop.nb_args-1 <= len(rinputs):
+                rinputs = list(rinputs)
+                defaults = list(defaults)
+                while len(rinputs) != hop.nb_args-1:
+                    c = hop.inputconst(rinputs.pop(), defaults.pop())
+                    defaultclist.insert(0, c)
+            else:
+                if hop.nb_args-1 > len(rinputs):
+                    raise RTyperError("too many arguments in function call")
+                else:
+                    raise RTyperError("not enough arguments in function call")
+        vlist = hop.inputargs(self, *rinputs) + defaultclist
         if self.lowleveltype == Void:
             assert len(self.function_signatures) == 1
             vlist[0] = hop.inputconst(typeOf(f), f)
-        return hop.genop('direct_call', vlist, resulttype = rresult)
+        v = hop.genop('direct_call', vlist, resulttype = rresult)
+        return hop.llops.convertvar(v, rresult, hop.r_result)
 
+    def rtype_call_args(self, hop):
+        f, rinputs, rresult = self.function_signatures.itervalues().next()
+        # the function arguments may have been normalized by normalizecalls()
+        # already
+        if not f._obj.graph.normalized_for_calls:
+            assert False, "XXX do stuff here"
+        vlist = hop.inputargs(self, Void, *rinputs)
+        return hop.genop('direct_call', vlist[:1] + vlist[2:],
+                         resulttype = rresult)
 
 # ____________________________________________________________
 
@@ -183,30 +381,36 @@
                              "methods can be found: %r" % (
                 s_pbc.prebuiltinstances,))
         # the low-level representation is just the bound 'self' argument.
-        self.r_instance = rclass.getinstancerepr(rtyper, self.classdef)
-        self.lowleveltype = self.r_instance.lowleveltype
+        self.s_im_self = annmodel.SomeInstance(self.classdef)
+        self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef)
+        self.lowleveltype = self.r_im_self.lowleveltype
+
+    def convert_const(self, method):
+        if getattr(method, 'im_func', None) is None:
+            raise TyperError("not a bound method: %r" % method)
+        return self.r_im_self.convert_const(method.im_self)
+
+    def get_method_from_instance(self, r_inst, v_inst, llops):
+        # The 'self' might have to be cast to a parent class
+        # (as shown for example in test_rclass/test_method_both_A_and_B)
+        return llops.convertvar(v_inst, r_inst, self.r_im_self)
 
     def rtype_simple_call(self, hop):
-        # XXX the graph of functions used as methods may need to be hacked
-        # XXX so that its 'self' argument accepts a pointer to an instance of
-        # XXX the common base class.  This is needed to make the direct_call
-        # XXX below well-typed.
-        r_class = self.r_instance.rclass
+        r_class = self.r_im_self.rclass
         mangled_name, r_func = r_class.clsfields[self.methodname]
         assert isinstance(r_func, FunctionsPBCRepr)
-        #
-        # XXX try to unify with FunctionsPBCRepr.rtype_simple_call()
-        f, rinputs, rresult = r_func.function_signatures.itervalues().next()
-        vlist = hop.inputargs(self, *rinputs[1:])  # ignore the self from r_func
-        if r_func.lowleveltype == Void:
-            assert len(r_func.function_signatures) == 1
-            vfunc = hop.inputconst(typeOf(f), f)
-        else:
-            vinst = vlist[0]
-            vcls = self.r_instance.getfield(vinst, '__class__', hop.llops)
-            vfunc = r_class.getclsfield(vcls, self.methodname, hop.llops)
-        vlist.insert(0, vfunc)
-        return hop.genop('direct_call', vlist, resulttype = rresult)
+        s_func = r_func.s_pbc
+
+        hop2 = hop.copy()
+        hop2.args_s[0] = self.s_im_self   # make the 1st arg stand for 'im_self'
+        hop2.args_r[0] = self.r_im_self   # (same lowleveltype as 'self')
+
+        v_im_self = hop.inputarg(self, arg=0)
+        v_cls = self.r_im_self.getfield(v_im_self, '__class__', hop.llops)
+        v_func = r_class.getclsfield(v_cls, self.methodname, hop.llops)
+        hop2.v_s_insertfirstarg(v_func, s_func)   # insert 'function'
+        # now hop2 looks like simple_call(function, self, args...)
+        return hop2.dispatch()
 
 
 # ____________________________________________________________
@@ -232,5 +436,37 @@
 ##                    s_pbc.prebuiltinstances,))
 
     def rtype_simple_call(self, hop):
-        return rclass.rtype_new_instance(self.s_pbc.const, hop)
-        # XXX call __init__ somewhere
+        klass = self.s_pbc.const
+        v_instance = rclass.rtype_new_instance(klass, hop)
+        try:
+            initfunc = klass.__init__.im_func
+        except AttributeError:
+            assert hop.nb_args == 1, ("arguments passed to __init__, "
+                                      "but no __init__!")
+        else:
+            if initfunc == Exception.__init__.im_func:
+                return v_instance    # ignore __init__ and arguments completely
+            s_instance = rclass.instance_annotation_for_cls(self.rtyper, klass)
+            s_init = annmodel.SomePBC({initfunc: True})
+            hop2 = hop.copy()
+            hop2.r_s_popfirstarg()   # discard the class pointer argument
+            hop2.v_s_insertfirstarg(v_instance, s_instance)  # add 'instance'
+            c = Constant(initfunc)
+            hop2.v_s_insertfirstarg(c, s_init)   # add 'initfunc'
+            hop2.s_result = annmodel.SomePBC({None: True})
+            hop2.r_result = self.rtyper.getrepr(hop2.s_result)
+            # now hop2 looks like simple_call(initfunc, instance, args...)
+            hop2.dispatch()
+        return v_instance
+
+# ____________________________________________________________
+
+def rtype_call_memo(hop): 
+    memo_table = hop.args_v[0].value
+    fieldname = memo_table.fieldname 
+    assert hop.nb_args == 2, "XXX"  
+
+    r_pbc = hop.args_r[1]
+    assert isinstance(r_pbc, MultipleFrozenPBCRepr)
+    v_table, v_pbc = hop.inputargs(Void, r_pbc)
+    return r_pbc.getfield(v_pbc, fieldname, hop.llops)

Modified: pypy/branch/pycompiler/rpython/rptr.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rptr.py	(original)
+++ pypy/branch/pycompiler/rpython/rptr.py	Fri Jul  1 18:30:34 2005
@@ -7,15 +7,15 @@
 
 class __extend__(annmodel.SomePtr):
     def rtyper_makerepr(self, rtyper):
-        if self.is_constant() and not self.const:   # constant NULL
-            return nullptr_repr
-        else:
-            return PtrRepr(self.ll_ptrtype)
+##        if self.is_constant() and not self.const:   # constant NULL
+##            return nullptr_repr
+##        else:
+        return PtrRepr(self.ll_ptrtype)
     def rtyper_makekey(self):
-        if self.is_constant() and not self.const:
-            return None
-        else:
-            return self.ll_ptrtype
+##        if self.is_constant() and not self.const:
+##            return None
+##        else:
+        return self.ll_ptrtype
 
 
 class PtrRepr(Repr):
@@ -83,18 +83,18 @@
 #
 #  Null Pointers
 
-class NullPtrRepr(Repr):
-    lowleveltype = Void
+##class NullPtrRepr(Repr):
+##    lowleveltype = Void
 
-    def rtype_is_true(self, hop):
-        return hop.inputconst(Bool, False)
+##    def rtype_is_true(self, hop):
+##        return hop.inputconst(Bool, False)
 
-nullptr_repr = NullPtrRepr()
+##nullptr_repr = NullPtrRepr()
 
-class __extend__(pairtype(NullPtrRepr, PtrRepr)):
-    def convert_from_to((r_null, r_ptr), v, llops):
-        # nullptr to general pointer
-        return inputconst(r_ptr, _ptr(r_ptr.lowleveltype, None))
+##class __extend__(pairtype(NullPtrRepr, PtrRepr)):
+##    def convert_from_to((r_null, r_ptr), v, llops):
+##        # nullptr to general pointer
+##        return inputconst(r_ptr, _ptr(r_ptr.lowleveltype, None))
 
 # ____________________________________________________________
 #

Modified: pypy/branch/pycompiler/rpython/rrange.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rrange.py	(original)
+++ pypy/branch/pycompiler/rpython/rrange.py	Fri Jul  1 18:30:34 2005
@@ -1,7 +1,7 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
-from pypy.rpython.lltype import *
+from pypy.rpython.lltype import Ptr, GcStruct, Signed, malloc, Void
 
 # ____________________________________________________________
 #
@@ -33,8 +33,8 @@
 class __extend__(pairtype(RangeRepr, IntegerRepr)):
 
     def rtype_getitem((r_rng, r_int), hop):
-        v_lst, v_index = hop.inputargs(r_lst, Signed)
-        cstep = hop.inputconst(Signed, self.step)
+        v_lst, v_index = hop.inputargs(r_rng, Signed)
+        cstep = hop.inputconst(Signed, r_rng.step)
         if hop.args_s[1].nonneg:
             llfn = ll_rangeitem_nonneg
         else:
@@ -59,12 +59,7 @@
 
 def ll_rangeitem(l, i, step):
     if i<0:
-        # XXX ack. cannot call ll_rangelen() here for now :-(
-        if step > 0:
-            length = (l.stop - l.start + (step-1)) // step
-        else:
-            length = (l.start - l.stop - (step+1)) // (-step)
-        #assert length >= 0
+        length = ll_rangelen(l, step)
         i += length
     return l.start + i*step
 
@@ -97,6 +92,8 @@
                          "XXX not implemented")
         #return hop.gendirectcall(ll_range2list, vstart, vstop, vstep)
 
+rtype_builtin_xrange = rtype_builtin_range
+
 # ____________________________________________________________
 #
 #  Iteration.

Modified: pypy/branch/pycompiler/rpython/rslice.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rslice.py	(original)
+++ pypy/branch/pycompiler/rpython/rslice.py	Fri Jul  1 18:30:34 2005
@@ -1,9 +1,9 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow.model import Constant
-from pypy.rpython.lltype import *
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
 import sys
+from pypy.rpython.lltype import GcStruct, Signed, Ptr, Void,malloc
 
 # ____________________________________________________________
 #

Modified: pypy/branch/pycompiler/rpython/rstr.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rstr.py	(original)
+++ pypy/branch/pycompiler/rpython/rstr.py	Fri Jul  1 18:30:34 2005
@@ -1,11 +1,18 @@
 from weakref import WeakValueDictionary
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
-from pypy.rpython.lltype import *
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
-from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst
+from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst, UniCharRepr
 from pypy.rpython.rarithmetic import intmask
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
+from pypy.rpython.rtuple import TupleRepr
+from pypy.rpython import rint
+from pypy.rpython.rslice import SliceRepr
+from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr
+from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc
+from pypy.rpython.lltype import Bool, Void, GcArray, nullptr, typeOf
+from pypy.rpython.rclass import InstanceRepr
+
 
 # ____________________________________________________________
 #
@@ -13,13 +20,11 @@
 #
 #    struct str {
 #        hash: Signed
-#        chars: array {
-#            Char ch
-#        }
+#        chars: array of Char
 #    }
 
 STR = GcStruct('str', ('hash',  Signed),
-                      ('chars', Array(('ch', Char))))
+                      ('chars', Array(Char)))
 
 
 class __extend__(annmodel.SomeString):
@@ -34,8 +39,17 @@
     def rtyper_makekey(self):
         return None
 
+class __extend__(annmodel.SomeUnicodeCodePoint):
+    def rtyper_makerepr(self, rtyper):
+        return unichar_repr
+    def rtyper_makekey(self):
+        return None
 
 CONST_STR_CACHE = WeakValueDictionary()
+string_repr = StringRepr()
+char_repr   = CharRepr()
+unichar_repr = UniCharRepr()
+
 
 class __extend__(StringRepr):
     lowleveltype = Ptr(STR)
@@ -43,6 +57,7 @@
     def convert_const(self, value):
         if value is None:
             return nullptr(STR)
+        value = getattr(value, '__self__', value)  # for bound string methods
         if not isinstance(value, str):
             raise TyperError("not a str: %r" % (value,))
         try:
@@ -50,11 +65,14 @@
         except KeyError:
             p = malloc(STR, len(value))
             for i in range(len(value)):
-                p.chars[i].ch = value[i]
+                p.chars[i] = value[i]
             ll_strhash(p)   # precompute the hash
             CONST_STR_CACHE[value] = p
             return p
 
+    def get_ll_eq_function(self):
+        return ll_streq
+
     def rtype_len(_, hop):
         v_str, = hop.inputargs(string_repr)
         return hop.gendirectcall(ll_strlen, v_str)
@@ -78,6 +96,47 @@
         v_str, = hop.inputargs(string_repr)
         return hop.gendirectcall(ll_strhash, v_str)
 
+    def rtype_method_startswith(_, hop):
+        v_str, v_value = hop.inputargs(string_repr, string_repr)
+        return hop.gendirectcall(ll_startswith, v_str, v_value)
+
+    def rtype_method_endswith(_, hop):
+        v_str, v_value = hop.inputargs(string_repr, string_repr)
+        return hop.gendirectcall(ll_endswith, v_str, v_value)
+
+    def rtype_method_join(_, hop):
+        r_lst = hop.args_r[1]
+        s_item = r_lst.listitem.s_value
+        if s_item == annmodel.SomeImpossibleValue():
+            return inputconst(string_repr, "")
+        elif not s_item.__class__ == annmodel.SomeString:
+            raise TyperError("join of non-string list: %r" % r_lst)
+        v_str, v_lst = hop.inputargs(string_repr, r_lst)
+        cname = inputconst(Void, "items")
+        v_items = hop.genop("getfield", [v_lst, cname],
+                            resulttype=Ptr(GcArray(Ptr(STR))))
+        return hop.gendirectcall(ll_join, v_str, v_items)
+
+    def rtype_method_split(_, hop):
+        v_str, v_chr = hop.inputargs(string_repr, char_repr)
+        c = hop.inputconst(Void, hop.r_result.lowleveltype)
+        return hop.gendirectcall(ll_split_chr, c, v_str, v_chr)
+
+    def rtype_method_replace(_, hop):
+        if not (hop.args_r[1] == char_repr and hop.args_r[2] == char_repr):
+            raise TyperError, 'replace only works for char args'
+        v_str, v_c1, v_c2 = hop.inputargs(string_repr, char_repr, char_repr)
+        return hop.gendirectcall(ll_replace_chr_chr, v_str, v_c1, v_c2)
+
+    def ll_str(s, r):
+        if typeOf(s) == Char:
+            return ll_chr2str(s)
+        else:
+            return s
+    ll_str = staticmethod(ll_str)
+        
+    def make_iterator_repr(self):
+        return string_iterator_repr
 
 class __extend__(pairtype(StringRepr, IntegerRepr)):
     def rtype_getitem(_, hop):
@@ -88,6 +147,21 @@
             llfn = ll_stritem
         return hop.gendirectcall(llfn, v_str, v_index)
 
+    def rtype_mod(_, hop):
+        return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
+
+
+class __extend__(pairtype(StringRepr, SliceRepr)):
+
+    def rtype_getitem((r_str, r_slic), hop):
+        if r_slic == startonly_slice_repr:
+            v_str, v_start = hop.inputargs(r_str, startonly_slice_repr)
+            return hop.gendirectcall(ll_stringslice_startonly, v_str, v_start)
+        if r_slic == startstop_slice_repr:
+            v_str, v_slice = hop.inputargs(r_str, startstop_slice_repr)
+            return hop.gendirectcall(ll_stringslice, v_str, v_slice)
+        raise TyperError(r_slic)
+
 
 class __extend__(pairtype(StringRepr, StringRepr)):
     def rtype_add(_, hop):
@@ -95,8 +169,140 @@
         return hop.gendirectcall(ll_strconcat, v_str1, v_str2)
     rtype_inplace_add = rtype_add
 
+    def rtype_eq(_, hop):
+        v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
+        return hop.gendirectcall(ll_streq, v_str1, v_str2)
+    
+    def rtype_ne(_, hop):
+        v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
+        vres = hop.gendirectcall(ll_streq, v_str1, v_str2)
+        return hop.genop('bool_not', [vres], resulttype=Bool)
+
+    def rtype_lt(_, hop):
+        v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
+        vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2)
+        return hop.genop('int_lt', [vres, hop.inputconst(Signed, 0)],
+                         resulttype=Bool)
+
+    def rtype_le(_, hop):
+        v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
+        vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2)
+        return hop.genop('int_le', [vres, hop.inputconst(Signed, 0)],
+                         resulttype=Bool)
+
+    def rtype_ge(_, hop):
+        v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
+        vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2)
+        return hop.genop('int_ge', [vres, hop.inputconst(Signed, 0)],
+                         resulttype=Bool)
+
+    def rtype_gt(_, hop):
+        v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
+        vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2)
+        return hop.genop('int_gt', [vres, hop.inputconst(Signed, 0)],
+                         resulttype=Bool)
+
+    def rtype_mod(_, hop):
+        return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
+
+class __extend__(pairtype(StringRepr, CharRepr)):
+    def rtype_contains(_, hop):
+        v_str, v_chr = hop.inputargs(string_repr, char_repr)
+        return hop.gendirectcall(ll_contains, v_str, v_chr)
+    
+def parse_fmt_string(fmt):
+    # we support x, d, s, f, [r]
+
+    it = iter(fmt)
+    r = []
+    curstr = ''
+    for c in it:
+        if c == '%':
+            f = it.next()
+            if f == '%':
+                curstr += '%'
+                continue
+
+            if curstr:
+                r.append(curstr)
+            curstr = ''
+            assert f in 'xdsrf'
+
+            r.append((f,))
+        else:
+            curstr += c
+    if curstr:
+        r.append(curstr)
+    return r
+            
+
+def do_stringformat(hop, sourcevarsrepr):
+    s_str = hop.args_s[0]
+    assert s_str.is_constant()
+    s = s_str.const
+    things = parse_fmt_string(s)
+    size = inputconst(Signed, len(things)) # could be unsigned?
+    TEMP = GcArray(Ptr(STR))
+    cTEMP = inputconst(Void, TEMP)
+    vtemp = hop.genop("malloc_varsize", [cTEMP, size],
+                      resulttype=Ptr(TEMP))
+    r_tuple = hop.args_r[1]
+    v_tuple = hop.args_v[1]
+
+    argsiter = iter(sourcevarsrepr)
+    
+    for i, thing in enumerate(things):
+        if isinstance(thing, tuple):
+            code = thing[0]
+            vitem, r_arg = argsiter.next()
+            rep = inputconst(Void, r_arg)
+            if code == 's' or (code == 'r' and isinstance(r_arg, InstanceRepr)):
+                vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep)
+            elif code == 'd':
+                assert isinstance(r_arg, IntegerRepr)
+                vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep)
+            elif code == 'f':
+                #assert isinstance(r_arg, FloatRepr)
+                vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep)
+            elif code == 'x':
+                assert isinstance(r_arg, IntegerRepr)
+                vchunk = hop.gendirectcall(rint.ll_int2hex, vitem,
+                                           inputconst(Bool, False))
+            else:
+                assert 0
+        else:
+            vchunk = inputconst(string_repr, thing)
+        i = inputconst(Signed, i)
+        hop.genop('setarrayitem', [vtemp, i, vchunk])
+
+    return hop.gendirectcall(ll_join, inputconst(string_repr, ""), vtemp)
+    
+
+class __extend__(pairtype(StringRepr, TupleRepr)):
+    def rtype_mod(_, hop):
+        r_tuple = hop.args_r[1]
+        v_tuple = hop.args_v[1]
+
+        sourcevars = []
+        for fname, r_arg in zip(r_tuple.fieldnames, r_tuple.items_r):
+            cname = hop.inputconst(Void, fname)
+            vitem = hop.genop("getfield", [v_tuple, cname],
+                              resulttype=r_arg)
+            sourcevars.append((vitem, r_arg))
+
+        return do_stringformat(hop, sourcevars)
+                
+
 class __extend__(CharRepr):
 
+    def convert_const(self, value):
+        if not isinstance(value, str) or len(value) != 1:
+            raise TyperError("not a character: %r" % (value,))
+        return value
+
+    def get_ll_eq_function(self):
+        return None 
+
     def rtype_len(_, hop):
         return hop.inputconst(Signed, 1)
 
@@ -108,6 +314,70 @@
         vlist = hop.inputargs(char_repr)
         return hop.genop('cast_char_to_int', vlist, resulttype=Signed)
 
+    def rtype_method_isspace(_, hop):
+        vlist = hop.inputargs(char_repr)
+        return hop.gendirectcall(ll_char_isspace, vlist[0])
+
+class __extend__(pairtype(CharRepr, IntegerRepr)):
+    
+    def rtype_mul(_, hop):
+        v_char, v_int = hop.inputargs(char_repr, Signed)
+        return hop.gendirectcall(ll_char_mul, v_char, v_int)
+    rtype_inplace_mul = rtype_mul
+
+class __extend__(pairtype(CharRepr, CharRepr)):
+    def rtype_eq(_, hop): return _rtype_compare_template(hop, 'eq')
+    def rtype_ne(_, hop): return _rtype_compare_template(hop, 'ne')
+    def rtype_lt(_, hop): return _rtype_compare_template(hop, 'lt')
+    def rtype_le(_, hop): return _rtype_compare_template(hop, 'le')
+    def rtype_gt(_, hop): return _rtype_compare_template(hop, 'gt')
+    def rtype_ge(_, hop): return _rtype_compare_template(hop, 'ge')
+
+#Helper functions for comparisons
+
+def _rtype_compare_template(hop, func):
+    vlist = hop.inputargs(char_repr, char_repr)
+    return hop.genop('char_'+func, vlist, resulttype=Bool)
+
+class __extend__(UniCharRepr):
+
+    def convert_const(self, value):
+        if not isinstance(value, unicode) or len(value) != 1:
+            raise TyperError("not a unicode character: %r" % (value,))
+        return value
+
+    def get_ll_eq_function(self):
+        return None 
+
+##    def rtype_len(_, hop):
+##        return hop.inputconst(Signed, 1)
+##
+##    def rtype_is_true(_, hop):
+##        assert not hop.args_s[0].can_be_None
+##        return hop.inputconst(Bool, True)
+
+    def rtype_ord(_, hop):
+        vlist = hop.inputargs(unichar_repr)
+        return hop.genop('cast_unichar_to_int', vlist, resulttype=Signed)
+
+
+class __extend__(pairtype(UniCharRepr, UniCharRepr)):
+    def rtype_eq(_, hop): return _rtype_unchr_compare_template(hop, 'eq')
+    def rtype_ne(_, hop): return _rtype_unchr_compare_template(hop, 'ne')
+##    def rtype_lt(_, hop): return _rtype_unchr_compare_template(hop, 'lt')
+##    def rtype_le(_, hop): return _rtype_unchr_compare_template(hop, 'le')
+##    def rtype_gt(_, hop): return _rtype_unchr_compare_template(hop, 'gt')
+##    def rtype_ge(_, hop): return _rtype_unchr_compare_template(hop, 'ge')
+
+#Helper functions for comparisons
+
+def _rtype_unchr_compare_template(hop, func):
+    vlist = hop.inputargs(unichar_repr, unichar_repr)
+    return hop.genop('unichar_'+func, vlist, resulttype=Bool)
+
+
+#
+# _________________________ Conversions _________________________
 
 class __extend__(pairtype(CharRepr, StringRepr)):
     def convert_from_to((r_from, r_to), v, llops):
@@ -122,16 +392,17 @@
             return llops.gendirectcall(ll_stritem_nonneg, v, c_zero)
         return NotImplemented
 
-
-string_repr = StringRepr()
-char_repr   = CharRepr()
-
-#
-# _________________________ Conversions _________________________
-
-##class __extend__(pairtype(PyObjRepr, StringRepr)):
-##    def convert_from_to((r_from, r_to), v, llops):
-##        XXX
+class __extend__(pairtype(PyObjRepr, StringRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        v_len = llops.gencapicall('PyString_Size', [v], resulttype=Signed)
+        cstr = inputconst(Void, STR)
+        v_result = llops.genop('malloc_varsize', [cstr, v_len],
+                               resulttype=Ptr(STR))
+        cchars = inputconst(Void, "chars")
+        v_chars = llops.genop('getsubstruct', [v_result, cchars],
+                              resulttype=Ptr(STR.chars))
+        llops.gencapicall('PyString_ToLLCharArray', [v, v_chars])
+        return v_result
 
 class __extend__(pairtype(StringRepr, PyObjRepr)):
     def convert_from_to((r_from, r_to), v, llops):
@@ -141,11 +412,8 @@
                               resulttype=Ptr(STR.chars))
         v_size = llops.genop('getarraysize', [v_chars],
                              resulttype=Signed)
-        czero = inputconst(Signed, 0)
-        v_char0ptr = llops.genop('getarraysubstruct', [v_chars, czero],
-                                 resulttype=Ptr(STR.chars.OF))
-        return llops.gencapicall('PyString_FromStringAndSize_Hack',
-                                 [v_char0ptr, v_size],
+        return llops.gencapicall('PyString_FromLLCharArrayAndSize',
+                                 [v_chars, v_size],
                                  resulttype=pyobj_repr)
 
 # ____________________________________________________________
@@ -153,17 +421,31 @@
 #  Low-level methods.  These can be run for testing, but are meant to
 #  be direct_call'ed from rtyped flow graphs, which means that they will
 #  get flowed and annotated, mostly with SomePtr.
+#
+def ll_char_isspace(ch):
+    # XXX: 
+    #return ord(ch) in (9, 10, 11, 12, 13, 32)
+    c = ord(ch) 
+    return 9 <= c <= 13 or c == 32 
+
+def ll_char_mul(ch, times):
+    newstr = malloc(STR, times)
+    j = 0
+    while j < times:
+        newstr.chars[j] = ch
+        j += 1
+    return newstr
 
 def ll_strlen(s):
     return len(s.chars)
 
 def ll_stritem_nonneg(s, i):
-    return s.chars[i].ch
+    return s.chars[i]
 
 def ll_stritem(s, i):
-    if i<0:
+    if i < 0:
         i += len(s.chars)
-    return s.chars[i].ch
+    return s.chars[i]
 
 def ll_str_is_true(s):
     # check if a string is True, allowing for None
@@ -171,7 +453,7 @@
 
 def ll_chr2str(ch):
     s = malloc(STR, 1)
-    s.chars[0].ch = ch
+    s.chars[0] = ch
     return s
 
 def ll_strhash(s):
@@ -184,10 +466,10 @@
         if length == 0:
             x = -1
         else:
-            x = ord(s.chars[0].ch) << 7
-            i = 1
+            x = ord(s.chars[0]) << 7
+            i = 0
             while i < length:
-                x = (1000003*x) ^ ord(s.chars[i].ch)
+                x = (1000003*x) ^ ord(s.chars[i])
                 i += 1
             x ^= length
             if x == 0:
@@ -201,13 +483,240 @@
     newstr = malloc(STR, len1 + len2)
     j = 0
     while j < len1:
-        newstr.chars[j].ch = s1.chars[j].ch
+        newstr.chars[j] = s1.chars[j]
         j += 1
     i = 0
     while i < len2:
-        newstr.chars[j].ch = s2.chars[i].ch
+        newstr.chars[j] = s2.chars[i]
         i += 1
         j += 1
     return newstr
 
-    
+def ll_strcmp(s1, s2):
+    chars1 = s1.chars
+    chars2 = s2.chars
+    len1 = len(chars1)
+    len2 = len(chars2)
+
+    if len1 < len2:
+        cmplen = len1
+    else:
+        cmplen = len2
+    i = 0
+    while i < cmplen:
+        diff = ord(chars1[i]) - ord(chars2[i])
+        if diff != 0:
+            return diff
+        i += 1
+    return len1 - len2
+
+def ll_streq(s1, s2):
+    len1 = len(s1.chars)
+    len2 = len(s2.chars)
+    if len1 != len2:
+        return False
+    j = 0
+    chars1 = s1.chars
+    chars2 = s2.chars
+    while j < len1:
+        if chars1[j] != chars2[j]:
+            return False
+        j += 1
+
+    return True
+
+def ll_startswith(s1, s2):
+    len1 = len(s1.chars)
+    len2 = len(s2.chars)
+    if len1 < len2:
+        return False
+    j = 0
+    chars1 = s1.chars
+    chars2 = s2.chars
+    while j < len2:
+        if chars1[j] != chars2[j]:
+            return False
+        j += 1
+
+    return True
+
+def ll_endswith(s1, s2):
+    len1 = len(s1.chars)
+    len2 = len(s2.chars)
+    if len1 < len2:
+        return False
+    j = 0
+    chars1 = s1.chars
+    chars2 = s2.chars
+    offset = len1 - len2
+    while j < len2:
+        if chars1[offset + j] != chars2[j]:
+            return False
+        j += 1
+
+    return True
+
+emptystr = string_repr.convert_const("")
+
+def ll_join(s, items):
+    s_chars = s.chars
+    s_len = len(s_chars)
+    num_items = len(items)
+    if num_items == 0:
+        return emptystr
+    itemslen = 0
+    i = 0
+    while i < num_items:
+        itemslen += len(items[i].chars)
+        i += 1
+    result = malloc(STR, itemslen + s_len * (num_items - 1))
+    res_chars = result.chars
+    res_index = 0
+    i = 0
+    item_chars = items[i].chars
+    item_len = len(item_chars)
+    j = 0
+    while j < item_len:
+        res_chars[res_index] = item_chars[j]
+        j += 1
+        res_index += 1
+    i += 1
+    while i < num_items:
+        j = 0
+        while j < s_len:
+            res_chars[res_index] = s_chars[j]
+            j += 1
+            res_index += 1
+
+        item_chars = items[i].chars
+        item_len = len(item_chars)
+        j = 0
+        while j < item_len:
+            res_chars[res_index] = item_chars[j]
+            j += 1
+            res_index += 1
+        i += 1
+    return result
+
+def ll_stringslice_startonly(s1, start):
+    len1 = len(s1.chars)
+    newstr = malloc(STR, len1 - start)
+    j = 0
+    while start < len1:
+        newstr.chars[j] = s1.chars[start]
+        start += 1
+        j += 1
+    return newstr
+
+def ll_stringslice(s1, slice):
+    start = slice.start
+    stop = slice.stop
+    newstr = malloc(STR, stop - start)
+    j = 0
+    while start < stop:
+        newstr.chars[j] = s1.chars[start]
+        start += 1
+        j += 1
+    return newstr
+
+def ll_split_chr(LISTPTR, s, c):
+    chars = s.chars
+    strlen = len(chars)
+    count = 1
+    i = 0
+    while i < strlen:
+        if chars[i] == c:
+            count += 1
+        i += 1
+    res = malloc(LISTPTR.TO)
+    items = res.items = malloc(LISTPTR.TO.items.TO, count)
+
+    i = 0
+    j = 0
+    resindex = 0
+    while j < strlen:
+        if chars[j] == c:
+            item = items[resindex] = malloc(STR, j - i)
+            newchars = item.chars
+            k = i
+            while k < j:
+                newchars[k - i] = chars[k]
+                k += 1
+            resindex += 1
+            i = j + 1
+        j += 1
+    item = items[resindex] = malloc(STR, j - i)
+    newchars = item.chars
+    k = i
+    while k < j:
+        newchars[k - i] = chars[k]
+        k += 1
+    resindex += 1
+
+    return res
+
+def ll_replace_chr_chr(s, c1, c2):
+    length = len(s.chars)
+    newstr = malloc(STR, length)
+    src = s.chars
+    dst = newstr.chars
+    j = 0
+    while j < length:
+        c = src[j]
+        if c == c1:
+            c = c2
+        dst[j] = c
+        j += 1
+    return newstr
+
+def ll_contains(s, c):
+    chars = s.chars
+    strlen = len(chars)
+    i = 0
+    while i < strlen:
+        if chars[i] == c:
+            return True
+        i += 1
+    return False
+
+# ____________________________________________________________
+#
+#  Iteration.
+
+class StringIteratorRepr(Repr):
+    lowleveltype = Ptr(GcStruct('stringiter',
+                                ('string', string_repr.lowleveltype),
+                                ('index', Signed)))
+    def newiter(self, hop):
+        v_str, = hop.inputargs(string_repr)
+        return hop.gendirectcall(ll_striter, v_str)
+
+    def rtype_next(self, hop):
+        v_iter, = hop.inputargs(self)
+        return hop.gendirectcall(ll_strnext, v_iter)
+
+string_iterator_repr = StringIteratorRepr()
+
+def ll_striter(string):
+    iter = malloc(string_iterator_repr.lowleveltype.TO)
+    iter.string = string
+    iter.index = 0
+    return iter
+
+def ll_strnext(iter):
+    chars = iter.string.chars
+    index = iter.index
+    if index >= len(chars):
+        raise StopIteration
+    iter.index = index + 1
+    return chars[index]
+
+# these should be in rclass, but circular imports prevent (also it's
+# not that insane that a string constant is built in this file).
+
+instance_str_prefix = string_repr.convert_const("<")
+instance_str_suffix = string_repr.convert_const(" object>")
+
+list_str_open_bracket = string_repr.convert_const("[")
+list_str_close_bracket = string_repr.convert_const("]")
+list_str_sep = string_repr.convert_const(", ")

Modified: pypy/branch/pycompiler/rpython/rtuple.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rtuple.py	(original)
+++ pypy/branch/pycompiler/rpython/rtuple.py	Fri Jul  1 18:30:34 2005
@@ -1,9 +1,9 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow.model import Constant
-from pypy.rpython.lltype import *
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
+from pypy.rpython.lltype import Ptr, GcStruct, Void, Signed, malloc
 
 # ____________________________________________________________
 #
@@ -19,6 +19,7 @@
 class __extend__(annmodel.SomeTuple):
     def rtyper_makerepr(self, rtyper):
         return TupleRepr([rtyper.getrepr(s_item) for s_item in self.items])
+    
     def rtyper_makekey(self):
         keys = [s_item.rtyper_makekey() for s_item in self.items]
         return tuple(keys)
@@ -40,10 +41,50 @@
             setattr(p, name, r.convert_const(obj))
         return p
 
+    #def get_eqfunc(self):
+    #    return inputconst(Void, self.item_repr.get_ll_eq_function())
+
     def rtype_len(self, hop):
         return hop.inputconst(Signed, len(self.items_r))
 
-
+    def rtype_bltn_list(self, hop):
+        from pypy.rpython import rlist
+        nitems = len(self.items_r)
+        vtup = hop.inputarg(self, 0)
+        c1 = inputconst(Void, hop.r_result.lowleveltype)
+        c2 = inputconst(Signed, nitems)
+        vlist = hop.gendirectcall(rlist.ll_newlist, c1, c2)
+        for index in range(nitems):
+            name = self.fieldnames[index]
+            ritem = self.items_r[index]
+            cname = hop.inputconst(Void, name)
+            vitem = hop.genop('getfield', [vtup, cname], resulttype = ritem)
+            vitem = hop.llops.convertvar(vitem, ritem, hop.r_result.item_repr)
+            cindex = inputconst(Signed, index)
+            hop.gendirectcall(rlist.ll_setitem_nonneg, vlist, cindex, vitem)
+        return vlist
+
+class __extend__(pairtype(TupleRepr, Repr)): 
+    def rtype_contains((r_tup, r_item), hop): 
+        v_tup = hop.args_v[0] 
+        if not isinstance(v_tup, Constant): 
+            raise TyperError("contains() on non-const tuple") 
+        t = v_tup.value 
+        typ = type(t[0]) 
+        for x in t[1:]: 
+            if type(x) is not typ: 
+                raise TyperError("contains() on mixed-type tuple "
+                                 "constant %r" % (v_tup,))
+        d = {}
+        for x in t: 
+            d[x] = None 
+        hop2 = hop.copy()
+        _, _ = hop2.r_s_popfirstarg()
+        v_dict = Constant(d)
+        s_dict = hop.rtyper.annotator.bookkeeper.immutablevalue(d)
+        hop2.v_s_insertfirstarg(v_dict, s_dict)
+        return hop2.dispatch()
+ 
 class __extend__(pairtype(TupleRepr, IntegerRepr)):
 
     def rtype_getitem((r_tup, r_int), hop):
@@ -56,12 +97,23 @@
         cname = hop.inputconst(Void, name)
         return hop.genop('getfield', [v_tuple, cname], resulttype = llresult)
 
+class __extend__(pairtype(TupleRepr, TupleRepr)):
+    
+    def rtype_add((r_tup1, r_tup2), hop):
+        v_tuple, v_tuple1 = hop.inputargs(r_tup1.items_r, r_tup2.items_r)
+        items_r = r_tup1.items_r + r_tup2.items_r
+        res = TupleRepr(items_r)
+        vlist = v_tuple + v_tuple1
+        return newtuple(hop.llops, res, vlist)
+    rtype_inplace_add = rtype_add
+
+
 # ____________________________________________________________
 #
 #  Irregular operations.
 
 def newtuple(llops, r_tuple, items_v):
-    c1 = inputconst(Void, r_tuple.lowleveltype)
+    c1 = inputconst(Void, r_tuple.lowleveltype.TO)
     v_result = llops.genop('malloc', [c1], resulttype = r_tuple.lowleveltype)
     for i in range(len(r_tuple.items_r)):
         cname = inputconst(Void, r_tuple.fieldnames[i])

Modified: pypy/branch/pycompiler/rpython/rtyper.py
==============================================================================
--- pypy/branch/pycompiler/rpython/rtyper.py	(original)
+++ pypy/branch/pycompiler/rpython/rtyper.py	Fri Jul  1 18:30:34 2005
@@ -1,11 +1,27 @@
+"""
+RTyper: converts high-level operations into low-level operations in flow graphs.
+
+The main class, with code to walk blocks and dispatch individual operations
+to the care of the rtype_*() methods implemented in the other r* modules.
+For each high-level operation 'hop', the rtype_*() methods produce low-level
+operations that are collected in the 'llops' list defined here.  When necessary,
+conversions are inserted.
+
+This logic borrows a bit from pypy.translator.annrpython, without the fixpoint
+computation part.
+"""
+
+from __future__ import generators
 import sys
+import py
 from pypy.annotation.pairtype import pair
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow.model import Variable, Constant, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, last_exception
 from pypy.rpython.lltype import Signed, Unsigned, Float, Char, Bool, Void
 from pypy.rpython.lltype import LowLevelType, Ptr, ContainerType
-from pypy.rpython.lltype import FuncType, functionptr, typeOf
+from pypy.rpython.lltype import FuncType, functionptr, typeOf, RuntimeTypeInfo
+from pypy.rpython.lltype import attachRuntimeTypeInfo, Primitive
 from pypy.tool.sourcetools import func_with_new_name, valid_identifier
 from pypy.translator.unsimplify import insert_empty_block
 from pypy.rpython.rmodel import Repr, inputconst, TyperError, getfunctionptr
@@ -13,14 +29,10 @@
 from pypy.rpython.annlowlevel import annotate_lowlevel_helper
 from pypy.rpython.exceptiondata import ExceptionData
 
-
-debug = False
+log = py.log.Producer("rtyper")
+py.log.setconsumer("rtyper", None) 
 crash_on_first_typeerror = True
 
-# XXX copied from pypy.translator.typer and modified.
-#     We'll remove pypy.translator.typer at some point.
-#     It also borrows a bit from pypy.translator.annrpython.
-
 class RPythonTyper:
 
     def __init__(self, annotator):
@@ -30,12 +42,14 @@
         self.specialized_ll_functions = {}
         self.class_reprs = {}
         self.instance_reprs = {}
+        self.pbc_reprs = {}
         self.typererror = None
         # make the primitive_to_repr constant mapping
         self.primitive_to_repr = {}
         for s_primitive, lltype in annmodel.annotation_to_ll_map:
             r = self.getrepr(s_primitive)
             self.primitive_to_repr[r.lowleveltype] = r
+        self.exceptiondata = ExceptionData(self)
 
     def getexceptiondata(self):
         return self.exceptiondata    # built at the end of specialize()
@@ -89,8 +103,8 @@
                 self.call_all_setups()
 
         specialize_more_blocks()
-        self.exceptiondata = ExceptionData(self)
-        specialize_more_blocks()
+        self.exceptiondata.make_helpers(self)
+        specialize_more_blocks()   # for the helpers just made
 
         if self.typererror:
             exc, value, tb = self.typererror
@@ -104,17 +118,51 @@
 
     def call_all_setups(self):
         # make sure all reprs so far have had their setup() called
+        must_setup_more = []
         while self.reprs_must_call_setup:
-            self.reprs_must_call_setup.pop().setup()
+            r = self.reprs_must_call_setup.pop()
+            r.setup()
+            must_setup_more.append(r)
+        for r in must_setup_more:
+            r.setup_final_touch()
 
     def setconcretetype(self, v):
         assert isinstance(v, Variable)
         v.concretetype = self.bindingrepr(v).lowleveltype
 
+    def typedconstant(self, c, using_repr=None):
+        """Make a copy of the Constant 'c' and give it a concretetype."""
+        assert isinstance(c, Constant)
+        if using_repr is None:
+            using_repr = self.bindingrepr(c)
+        if not hasattr(c, 'concretetype'):
+            c = inputconst(using_repr, c.value)
+        else:
+            if c.concretetype != Void:
+                assert typeOf(c.value) == using_repr.lowleveltype
+        return c
+
+    def setup_block_entry(self, block):
+        if block.operations == () and len(block.inputargs) == 2:
+            # special case for exception blocks: force them to return an
+            # exception type and value in a standardized format
+            v1, v2 = block.inputargs
+            v1.concretetype = self.exceptiondata.lltype_of_exception_type
+            v2.concretetype = self.exceptiondata.lltype_of_exception_value
+            return [self.exceptiondata.r_exception_type,
+                    self.exceptiondata.r_exception_value]
+        else:
+            # normal path
+            result = []
+            for a in block.inputargs:
+                r = self.bindingrepr(a)
+                a.concretetype = r.lowleveltype
+                result.append(r)
+            return result
+
     def specialize_block(self, block):
         # give the best possible types to the input args
-        for a in block.inputargs:
-            self.setconcretetype(a)
+        self.setup_block_entry(block)
 
         # specialize all the operations, as far as possible
         if block.operations == ():   # return or except block
@@ -124,12 +172,11 @@
         for v in block.getvariables():
             varmapping[v] = v    # records existing Variables
 
-        for op in block.operations:
+        for hop in self.highlevelops(block, newops):
             try:
-                hop = HighLevelOp(self, op, newops)
                 self.translate_hl_to_ll(hop, varmapping)
             except TyperError, e:
-                self.gottypererror(e, block, op, newops)
+                self.gottypererror(e, block, hop.spaceop, newops)
                 return  # cannot continue this block: no op.result.concretetype
 
         block.operations[:] = newops
@@ -147,15 +194,27 @@
                     assert block.exitswitch == Constant(last_exception)
                     r_case = rclass.get_type_repr(self)
                 link.llexitcase = r_case.convert_const(link.exitcase)
-            for a in [link.last_exception, link.last_exc_value]:
-                if isinstance(a, Variable):
-                    self.setconcretetype(a)
+
+            a = link.last_exception
+            if isinstance(a, Variable):
+                a.concretetype = self.exceptiondata.lltype_of_exception_type
+            elif isinstance(a, Constant):
+                link.last_exception = self.typedconstant(
+                    a, using_repr=self.exceptiondata.r_exception_type)
+
+            a = link.last_exc_value
+            if isinstance(a, Variable):
+                a.concretetype = self.exceptiondata.lltype_of_exception_value
+            elif isinstance(a, Constant):
+                link.last_exc_value = self.typedconstant(
+                    a, using_repr=self.exceptiondata.r_exception_value)
+
+            inputargs_reprs = self.setup_block_entry(link.target)
             for i in range(len(link.args)):
                 a1 = link.args[i]
-                a2 = link.target.inputargs[i]
-                r_a2 = self.bindingrepr(a2)
+                r_a2 = inputargs_reprs[i]
                 if isinstance(a1, Constant):
-                    link.args[i] = inputconst(r_a2, a1.value)
+                    link.args[i] = self.typedconstant(a1, using_repr=r_a2)
                     continue   # the Constant was typed, done
                 r_a1 = self.bindingrepr(a1)
                 if r_a1 == r_a2:
@@ -179,34 +238,49 @@
                     block.operations.extend(newops)
                     link.args[i] = a1
 
+    def highlevelops(self, block, llops):
+        # enumerate the HighLevelOps in a block.
+        if block.operations:
+            for op in block.operations[:-1]:
+                yield HighLevelOp(self, op, [], llops)
+            # look for exception links for the last operation
+            if block.exitswitch == Constant(last_exception):
+                exclinks = block.exits[1:]
+            else:
+                exclinks = []
+            yield HighLevelOp(self, block.operations[-1], exclinks, llops)
+
     def translate_hl_to_ll(self, hop, varmapping):
-        if debug:
-            print hop.spaceop.opname, hop.args_s
+        log.translating(hop.spaceop.opname, hop.args_s)
+        resultvar = hop.dispatch()
         op = hop.spaceop
-        translate_meth = getattr(self, 'translate_op_'+op.opname,
-                                 self.missing_operation)
-        resultvar = translate_meth(hop)
         if resultvar is None:
             # no return value
             if hop.s_result != annmodel.SomeImpossibleValue():
                 raise TyperError("the annotator doesn't agree that '%s' "
                                  "has no return value" % op.opname)
             op.result.concretetype = Void
-        elif isinstance(resultvar, Variable):
+        else:
+            assert isinstance(resultvar, (Variable, Constant))
             # for simplicity of the translate_meth, resultvar is usually not
             # op.result here.  We have to replace resultvar with op.result
             # in all generated operations.
+            if hop.s_result.is_constant():
+                if isinstance(resultvar, Constant) and \
+                       isinstance(hop.r_result.lowleveltype, Primitive):
+                    assert resultvar.value == hop.s_result.const
             resulttype = resultvar.concretetype
             op.result.concretetype = hop.r_result.lowleveltype
             if op.result.concretetype != resulttype:
                 raise TyperError("inconsistent type for the result of '%s':\n"
-                                 "annotator says  %s,\n"
-                                 "whose lltype is %r\n"
-                                 "but rtype* says %r" % (
+                                 "annotator says %s,\n"
+                                 "whose repr is %r\n"
+                                 "but rtype_%s returned %r" % (
                     op.opname, hop.s_result,
-                    op.result.concretetype, resulttype))
+                    hop.r_result, op.opname, resulttype))
             # figure out if the resultvar is a completely fresh Variable or not
-            if (resultvar not in self.annotator.bindings and
+            if (isinstance(resultvar, Variable) and
+                resultvar not in self.annotator.bindings and
                 resultvar not in varmapping):
                 # fresh Variable: rename it to the previously existing op.result
                 varmapping[resultvar] = op.result
@@ -214,18 +288,6 @@
                 # renaming unsafe.  Insert a 'same_as' operation...
                 hop.llops.append(SpaceOperation('same_as', [resultvar],
                                                 op.result))
-        else:
-            # translate_meth() returned a Constant
-            assert isinstance(resultvar, Constant)
-            if not hop.s_result.is_constant():
-                raise TyperError("the annotator doesn't agree that '%s' "
-                                 "returns a constant" % op.opname)
-            if resultvar.value != hop.s_result.const:
-                raise TyperError("constant mismatch: %r vs %r" % (
-                    resultvar.value, hop.s_result.const))
-            op.result.concretetype = hop.r_result.lowleveltype
-            hop.llops.append(SpaceOperation('same_as', [resultvar],
-                                            op.result))
 
     def gottypererror(self, e, block, position, llops):
         """Record a TyperError without crashing immediately.
@@ -261,11 +323,20 @@
     _registeroperations(locals())
     del _registeroperations
 
+    # this one is not in BINARY_OPERATIONS
+    def translate_op_contains(self, hop):
+        r_arg1 = hop.args_r[0]
+        r_arg2 = hop.args_r[1]
+        return pair(r_arg1, r_arg2).rtype_contains(hop)
+
     # __________ irregular operations __________
 
     def translate_op_newlist(self, hop):
         return rlist.rtype_newlist(hop)
 
+    def translate_op_newdict(self, hop):
+        return rdict.rtype_newdict(hop)
+
     def translate_op_alloc_and_set(self, hop):
         return rlist.rtype_alloc_and_set(hop)
 
@@ -275,6 +346,9 @@
     def translate_op_newslice(self, hop):
         return rslice.rtype_newslice(hop)
 
+    def translate_op_call_memo(self, hop):
+        return rpbc.rtype_call_memo(hop)
+
     def missing_operation(self, hop):
         raise TyperError("unimplemented operation: '%s'" % hop.spaceop.opname)
 
@@ -285,23 +359,52 @@
             return self.bindingrepr(v).lowleveltype
         return getfunctionptr(self.annotator.translator, func, getconcretetype)
 
+    def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None):
+        self.call_all_setups()  # compute ForwardReferences now
+        if ARG_GCSTRUCT is None:
+            ARG_GCSTRUCT = GCSTRUCT
+        args_s = [annmodel.SomePtr(Ptr(ARG_GCSTRUCT))]
+        s, spec_function = annotate_lowlevel_helper(self.annotator,
+                                                    func, args_s)
+        if (not isinstance(s, annmodel.SomePtr) or
+            s.ll_ptrtype != Ptr(RuntimeTypeInfo)):
+            raise TyperError("runtime type info function %r returns %r, "
+                             "excepted Ptr(RuntimeTypeInfo)" % (func, s))
+        funcptr = self.getfunctionptr(spec_function)
+        attachRuntimeTypeInfo(GCSTRUCT, funcptr)
 
 # ____________________________________________________________
 
 
-class HighLevelOp:
-    nb_popped = 0
+class HighLevelOp(object):
 
-    def __init__(self, rtyper, spaceop, llops):
+    def __init__(self, rtyper, spaceop, exceptionlinks, llops):
         self.rtyper   = rtyper
         self.spaceop  = spaceop
         self.nb_args  = len(spaceop.args)
         self.llops    = llops
+        self.args_v   = list(spaceop.args)
         self.args_s   = [rtyper.binding(a) for a in spaceop.args]
         self.s_result = rtyper.binding(spaceop.result)
         self.args_r   = [rtyper.getrepr(s_a) for s_a in self.args_s]
         self.r_result = rtyper.getrepr(self.s_result)
         rtyper.call_all_setups()  # compute ForwardReferences now
+        self.exceptionlinks = exceptionlinks
+
+    def copy(self):
+        result = HighLevelOp.__new__(HighLevelOp)
+        for key, value in self.__dict__.items():
+            if type(value) is list:     # grunt
+                value = value[:]
+            setattr(result, key, value)
+        return result
+
+    def dispatch(self):
+        op = self.spaceop
+        rtyper = self.rtyper
+        translate_meth = getattr(rtyper, 'translate_op_'+op.opname,
+                                 rtyper.missing_operation)
+        return translate_meth(self)
 
     def inputarg(self, converted_to, arg):
         """Returns the arg'th input argument of the current operation,
@@ -311,7 +414,7 @@
         """
         if not isinstance(converted_to, Repr):
             converted_to = self.rtyper.primitive_to_repr[converted_to]
-        v = self.spaceop.args[self.nb_popped + arg]
+        v = self.args_v[arg]
         if isinstance(v, Constant):
             return inputconst(converted_to, v.value)
         assert hasattr(v, 'concretetype')
@@ -326,9 +429,10 @@
     inputconst = staticmethod(inputconst)    # export via the HighLevelOp class
 
     def inputargs(self, *converted_to):
-        assert len(converted_to) == self.nb_args, (
-            "operation argument count mismatch: '%s' has %d+%d arguments" % (
-            self.spaceop.opname, self.nb_popped, self.nb_args))
+        if len(converted_to) != self.nb_args:
+            raise TyperError("operation argument count mismatch:\n"
+                             "'%s' has %d arguments, rtyper wants %d" % (
+                self.spaceop.opname, self.nb_args, len(converted_to)))
         vars = []
         for i in range(len(converted_to)):
             vars.append(self.inputarg(converted_to[i], i))
@@ -342,10 +446,23 @@
 
     def r_s_popfirstarg(self):
         "Return and discard the first argument."
-        self.nb_popped += 1
         self.nb_args -= 1
+        self.args_v.pop(0)
         return self.args_r.pop(0), self.args_s.pop(0)
 
+    def v_s_insertfirstarg(self, v_newfirstarg, s_newfirstarg):
+        r_newfirstarg = self.rtyper.getrepr(s_newfirstarg)
+        self.args_v.insert(0, v_newfirstarg)
+        self.args_r.insert(0, r_newfirstarg)
+        self.args_s.insert(0, s_newfirstarg)
+        self.nb_args += 1
+
+    def has_implicit_exception(self, exc_cls):
+        for link in self.exceptionlinks:
+            if issubclass(exc_cls, link.exitcase):
+                return True
+        return False
+
 # ____________________________________________________________
 
 class LowLevelOpList(list):
@@ -356,7 +473,7 @@
         self.rtyper = rtyper
 
     def convertvar(self, v, r_from, r_to):
-        assert isinstance(v, Variable)
+        assert isinstance(v, (Variable, Constant))
         if r_from != r_to:
             v = pair(r_from, r_to).convert_from_to(v, self)
             if v is NotImplemented:
@@ -403,12 +520,12 @@
         return self.genop('direct_call', [c]+list(args_v),
                           resulttype = typeOf(f).TO.RESULT)
 
-    def gencapicall(self, cfnname, args_v, resulttype=None):
+    def gencapicall(self, cfnname, args_v, resulttype=None, **flags):
         if isinstance(resulttype, Repr):
             resulttype = resulttype.lowleveltype
         argtypes = [v.concretetype for v in args_v]
         FUNCTYPE = FuncType(argtypes, resulttype or Void)
-        f = functionptr(FUNCTYPE, cfnname, external="C")
+        f = functionptr(FUNCTYPE, cfnname, external="C", **flags)
         cf = inputconst(typeOf(f), f)
         return self.genop('direct_call', [cf]+list(args_v), resulttype)
 
@@ -419,6 +536,6 @@
 from pypy.rpython import robject
 from pypy.rpython import rint, rbool, rfloat
 from pypy.rpython import rslice
-from pypy.rpython import rlist, rstr, rtuple
+from pypy.rpython import rlist, rstr, rtuple, rdict 
 from pypy.rpython import rclass, rbuiltin, rpbc
 from pypy.rpython import rptr

Modified: pypy/branch/pycompiler/rpython/test/test_llann.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_llann.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_llann.py	Fri Jul  1 18:30:34 2005
@@ -258,3 +258,25 @@
                 assert a.binding(vp).ll_ptrtype == T
                 assert a.binding(rv) == annmodel.lltype_to_annotation(T.TO.OF)
         return a, vTs
+
+    def test_getRuntimeTypeInfo(self):
+        S = GcStruct('s', ('x', Signed))
+        attachRuntimeTypeInfo(S)
+        def llf():
+            return getRuntimeTypeInfo(S)
+        a = self.RPythonAnnotator()
+        s, dontcare = annotate_lowlevel_helper(a, llf, [])
+        assert isinstance(s, annmodel.SomePtr)
+        assert s.ll_ptrtype == Ptr(RuntimeTypeInfo)
+        assert s.const == getRuntimeTypeInfo(S)
+
+    def test_runtime_type_info(self):
+        S = GcStruct('s', ('x', Signed))
+        attachRuntimeTypeInfo(S)
+        def llf(p):
+            return runtime_type_info(p)
+        a = self.RPythonAnnotator()
+        s, dontcare = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(Ptr(S))])
+        assert isinstance(s, annmodel.SomePtr)
+        assert s.ll_ptrtype == Ptr(RuntimeTypeInfo)
+        

Modified: pypy/branch/pycompiler/rpython/test/test_lltype.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_lltype.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_lltype.py	Fri Jul  1 18:30:34 2005
@@ -338,3 +338,50 @@
     del p
     p = cast_pointer(Ptr(S), p1)
     assert p.s1.x == 5
+
+def test_getRuntimeTypeInfo():
+    S = GcStruct('s', ('x', Signed))
+    py.test.raises(ValueError, "getRuntimeTypeInfo(S)")
+    pinf0 = attachRuntimeTypeInfo(S)
+    assert pinf0._obj.about == S
+    pinf = getRuntimeTypeInfo(S)
+    assert pinf == pinf0
+    pinf1 = getRuntimeTypeInfo(S)
+    assert pinf == pinf1
+    Z = GcStruct('z', ('x', Unsigned))
+    attachRuntimeTypeInfo(Z)
+    assert getRuntimeTypeInfo(Z) != pinf0
+    Sbis = GcStruct('s', ('x', Signed))
+    attachRuntimeTypeInfo(Sbis)
+    assert getRuntimeTypeInfo(Sbis) != pinf0
+    assert Sbis != S # the attached runtime type info distinguishes them
+
+def test_runtime_type_info():
+    S = GcStruct('s', ('x', Signed))
+    attachRuntimeTypeInfo(S)
+    s = malloc(S)
+    assert runtime_type_info(s) == getRuntimeTypeInfo(S)
+    S1 = GcStruct('s1', ('sub', S), ('x', Signed))
+    attachRuntimeTypeInfo(S1)
+    s1 = malloc(S1)
+    assert runtime_type_info(s1) == getRuntimeTypeInfo(S1)
+    assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1)
+    assert runtime_type_info(cast_pointer(Ptr(S), s1)) == getRuntimeTypeInfo(S1)
+    def dynamic_type_info_S(p):
+        if p.x == 0:
+            return getRuntimeTypeInfo(S)
+        else:
+            return getRuntimeTypeInfo(S1)
+    fp = functionptr(FuncType([Ptr(S)], Ptr(RuntimeTypeInfo)), 
+                     "dynamic_type_info_S", 
+                     _callable=dynamic_type_info_S)
+    attachRuntimeTypeInfo(S, fp)
+    assert s.x == 0
+    assert runtime_type_info(s) == getRuntimeTypeInfo(S)
+    s.x = 1
+    py.test.raises(RuntimeError, "runtime_type_info(s)")
+    assert s1.sub.x == 0
+    py.test.raises(RuntimeError, "runtime_type_info(s1.sub)")
+    s1.sub.x = 1
+    assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1)
+    

Modified: pypy/branch/pycompiler/rpython/test/test_normalizecalls.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_normalizecalls.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_normalizecalls.py	Fri Jul  1 18:30:34 2005
@@ -36,3 +36,22 @@
     assert s_l1.__class__ == annmodel.SomeString   # and not SomeChar
     assert s_l2.__class__ == annmodel.SomeString   # and not SomeChar
     #translator.view()
+
+def test_normalize_keyword_call():
+    def f1(a, b):
+        return (a, b, 0, 0)
+    def f2(b, c=123, a=456, d=789):
+        return (a, b, c, d)
+    def g(n):
+        if n > 0:
+            f = f1
+        else:
+            f = f2
+        f(a=5, b=6)
+
+    translator = rtype(g, [int])
+    f1graph = translator.getflowgraph(f1)
+    f2graph = translator.getflowgraph(f2)
+    assert len(f1graph.getargs()) == 2
+    assert len(f2graph.getargs()) == 2   # normalized to the common call pattern
+    #translator.view()

Modified: pypy/branch/pycompiler/rpython/test/test_rbool.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rbool.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rbool.py	Fri Jul  1 18:30:34 2005
@@ -1,7 +1,9 @@
 from pypy.translator.translator import Translator
+from pypy.rpython.lltype import pyobjectptr
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.annotation import model as annmodel
 from pypy.rpython.test import snippet
+from pypy.rpython.test.test_llinterp import interpret
 
 
 class TestSnippet(object):
@@ -36,3 +38,13 @@
         # XXX TODO test if all binary operations are implemented
         for opname in annmodel.BINARY_OPERATIONS:
             print 'BINARY_OPERATIONS:', opname
+
+    def test_bool2int(self):
+        def f(n):
+            if n:
+                n = 2
+            return n
+        res = interpret(f, [False])
+        assert res == 0 and res is not False   # forced to int by static typing
+        res = interpret(f, [True])
+        assert res == 2

Modified: pypy/branch/pycompiler/rpython/test/test_rclass.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rclass.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rclass.py	Fri Jul  1 18:30:34 2005
@@ -1,16 +1,6 @@
 from pypy.translator.translator import Translator
 from pypy.rpython.lltype import *
-from pypy.rpython.rtyper import RPythonTyper
-
-
-def rtype(fn, argtypes=[]):
-    t = Translator(fn)
-    t.annotate(argtypes)
-    typer = RPythonTyper(t.annotator)
-    typer.specialize()
-    #t.view()
-    t.checkgraphs()
-    return t
+from pypy.rpython.test.test_llinterp import interpret
 
 
 class EmptyBase(object):
@@ -21,7 +11,9 @@
     def dummyfn():
         x = EmptyBase()
         return x
-    rtype(dummyfn)
+    res = interpret(dummyfn, [])
+    T = typeOf(res)
+    assert isinstance(T, Ptr) and isinstance(T.TO, GcStruct)
 
 def test_instanceattr():
     def dummyfn():
@@ -29,8 +21,8 @@
         x.a = 5
         x.a += 1
         return x.a
-    rtype(dummyfn)
-
+    res = interpret(dummyfn, [])
+    assert res == 6
 
 class Random:
     xyzzy = 12
@@ -40,11 +32,105 @@
     def dummyfn():
         x = Random()
         return x.xyzzy
-    rtype(dummyfn)
+    res = interpret(dummyfn, [])
+    assert res == 12
 
 def test_classattr_as_defaults():
     def dummyfn():
         x = Random()
         x.xyzzy += 1
         return x.xyzzy
-    rtype(dummyfn)
+    res = interpret(dummyfn, [])
+    assert res == 13
+
+def test_prebuilt_instance():
+    a = EmptyBase()
+    a.x = 5
+    def dummyfn():
+        a.x += 1
+        return a.x
+    interpret(dummyfn, [])
+
+def test_recursive_prebuilt_instance():
+    a = EmptyBase()
+    b = EmptyBase()
+    a.x = 5
+    b.x = 6
+    a.peer = b
+    b.peer = a
+    def dummyfn():
+        return a.peer.peer.peer.x
+    res = interpret(dummyfn, [])
+    assert res == 6
+
+# method calls
+class A:
+    def f(self):
+        return self.g()
+
+    def g(self):
+        return 42
+
+class B(A):
+    def g(self):
+        return 1
+
+class C(B):
+    pass
+
+def test_simple_method_call():
+    def f(i):
+        if i:
+            a = A()
+        else:
+            a = B()
+        return a.f()
+    res = interpret(f, [True])
+    assert res == 42
+    res = interpret(f, [False])
+    assert res == 1
+
+def test_isinstance():
+    def a():
+        b = B()
+        return isinstance(b, A)
+    def b():
+        b = B()
+        return isinstance(b, B)
+    def c():
+        b = B()
+        return isinstance(b, C)
+
+    res = interpret(a, [])
+    assert res is True
+
+    res = interpret(b, [])
+    assert res is True
+
+    res = interpret(c, [])
+    assert res is False
+
+def test_method_used_in_subclasses_only():
+    class A:
+        def meth(self):
+            return 123
+    class B(A):
+        pass
+    def f():
+        x = B()
+        return x.meth()
+    res = interpret(f, [])
+    assert res == 123
+
+def test_method_both_A_and_B():
+    class A:
+        def meth(self):
+            return 123
+    class B(A):
+        pass
+    def f():
+        a = A()
+        b = B()
+        return a.meth() + b.meth()
+    res = interpret(f, [])
+    assert res == 246

Modified: pypy/branch/pycompiler/rpython/test/test_rfloat.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rfloat.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rfloat.py	Fri Jul  1 18:30:34 2005
@@ -2,6 +2,7 @@
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.annotation import model as annmodel
 from pypy.rpython.test import snippet
+from pypy.rpython.test.test_llinterp import interpret
 
 
 class TestSnippet(object):
@@ -36,3 +37,13 @@
         # XXX TODO test if all binary operations are implemented
         for opname in annmodel.BINARY_OPERATIONS:
             print 'BINARY_OPERATIONS:', opname
+
+def test_int_conversion():
+    def fn(f):
+        return int(f)
+
+    res = interpret(fn, [1.0])
+    assert res == 1
+    assert type(res) is int 
+    res = interpret(fn, [2.34])
+    assert res == fn(2.34) 

Modified: pypy/branch/pycompiler/rpython/test/test_rint.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rint.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rint.py	Fri Jul  1 18:30:34 2005
@@ -2,6 +2,8 @@
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.annotation import model as annmodel
 from pypy.rpython.test import snippet
+from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython.rarithmetic import r_uint
 
 
 class TestSnippet(object):
@@ -36,3 +38,53 @@
         # XXX TODO test if all binary operations are implemented
         for opname in annmodel.BINARY_OPERATIONS:
             print 'BINARY_OPERATIONS:', opname
+
+
+def test_char_constant():
+    def dummyfn(i):
+        return chr(i)
+    res = interpret(dummyfn, [ord(' ')])
+    assert res == ' '
+    res = interpret(dummyfn, [0])
+    assert res == '\0'
+    res = interpret(dummyfn, [ord('a')])
+    assert res == 'a'
+    
+def test_str_of_int():
+    def dummy(i):
+        return str(i)
+    
+    res = interpret(dummy, [0])
+    assert ''.join(res.chars) == '0'
+
+    res = interpret(dummy, [1034])
+    assert ''.join(res.chars) == '1034'
+
+    res = interpret(dummy, [-123])
+    assert ''.join(res.chars) == '-123'
+    
+def test_hex_of_int():
+    def dummy(i):
+        return hex(i)
+    
+    res = interpret(dummy, [0])
+    assert ''.join(res.chars) == '0x0'
+
+    res = interpret(dummy, [1034])
+    assert ''.join(res.chars) == '0x40a'
+
+    res = interpret(dummy, [-123])
+    assert ''.join(res.chars) == '-0x7b'
+    
+def test_unsigned():
+    def dummy(i):
+        i = r_uint(i)
+        j = r_uint(12)
+        return i < j
+
+    res = interpret(dummy,[0])
+    assert res is True
+
+    res = interpret(dummy, [-1])
+    assert res is False    # -1 ==> 0xffffffff
+

Modified: pypy/branch/pycompiler/rpython/test/test_rlist.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rlist.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rlist.py	Fri Jul  1 18:30:34 2005
@@ -4,6 +4,8 @@
 from pypy.rpython.rlist import *
 from pypy.rpython.rslice import ll_newslice
 from pypy.rpython.rint import signed_repr
+from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython.test.test_llinterp import find_exception
 
 
 def sample_list():
@@ -94,7 +96,7 @@
 
 def test_simple():
     def dummyfn():
-        l = [10,20,30]
+        l = [10, 20, 30]
         return l[2]
     rtype(dummyfn)
 
@@ -108,14 +110,14 @@
 
 def test_len():
     def dummyfn():
-        l = [5,10]
+        l = [5, 10]
         return len(l)
     rtype(dummyfn)
 
 def test_iterate():
     def dummyfn():
         total = 0
-        for x in [1,3,5,7,9]:
+        for x in [1, 3, 5, 7, 9]:
             total += x
         return total
     rtype(dummyfn)
@@ -151,3 +153,165 @@
         del l[-1]
         del l[:]
     rtype(dummyfn)
+
+def test_insert_pop():
+    def dummyfn():
+        l = [6, 7, 8]
+        l.insert(0, 5)
+        l.insert(1, 42)
+        l.pop(2)
+        l.pop(0)
+        l.pop(-1)
+        l.pop()
+        return l[-1]
+    res = interpret(dummyfn, ())#, view=True)
+    assert res == 42
+
+def test_reverse():
+    def dummyfn():
+        l = [5, 3, 2]
+        l.reverse()
+        return l[0]*100 + l[1]*10 + l[2]
+    res = interpret(dummyfn, ())
+    assert res == 235
+
+def test_prebuilt_list():
+    klist = ['a', 'd', 'z', 'k']
+    def dummyfn(n):
+        return klist[n]
+    res = interpret(dummyfn, [0])
+    assert res == 'a'
+    res = interpret(dummyfn, [3])
+    assert res == 'k'
+    res = interpret(dummyfn, [-2])
+    assert res == 'z'
+
+def test_bound_list_method():
+    klist = [1, 2, 3]
+    # for testing constant methods without actually mutating the constant
+    def dummyfn(n):
+        klist.extend([])
+    interpret(dummyfn, [7])
+
+def test_list_is():
+    def dummyfn():
+        l1 = []
+        return l1 is l1
+    res = interpret(dummyfn, [])
+    assert res is True
+    def dummyfn():
+        l2 = [1, 2]
+        return l2 is l2
+    res = interpret(dummyfn, [])
+    assert res is True
+    def dummyfn():
+        l1 = [2]
+        l2 = [1, 2]
+        return l1 is l2
+    res = interpret(dummyfn, [])
+    assert res is False
+    def dummyfn():
+        l1 = [1, 2]
+        l2 = [1, 2]
+        return l1 is l2
+    res = interpret(dummyfn, [])
+    assert res is False
+
+    def dummyfn():
+        l1 = None
+        l2 = [1, 2]
+        return l1 is l2
+    res = interpret(dummyfn, [])
+    assert res is False
+
+def test_list_compare():
+    def fn(i, j, neg=False):
+        s1 = [[1, 2, 3], [4, 5, 1]]
+        s2 = [[1, 2, 3], [4, 5, 1], [1], [1, 2], [4, 5, 1, 6], [7, 1, 1, 8, 9, 10]]
+        if neg: return s1[i] != s2[i]
+        return s1[i] == s2[j]
+    for i in range(2):
+        for j in range(6):
+            for case in False, True:
+                res = interpret(fn, [i,j,case])
+                assert res is fn(i, j, case)
+
+def test_list_comparestr():
+    def fn(i, j, neg=False):
+        s1 = [["hell"], ["hello", "world"]]
+        s1[0][0] += "o" # ensure no interning
+        s2 = [["hello"], ["world"]]
+        if neg: return s1[i] != s2[i]
+        return s1[i] == s2[j]
+    for i in range(2):
+        for j in range(2):
+            for case in False, True:
+                res = interpret(fn, [i,j,case])
+                assert res is fn(i, j, case)
+
+class Foo: pass
+
+class Bar(Foo): pass
+
+def test_list_compareinst():
+    def fn(i, j, neg=False):
+        foo1 = Foo()
+        foo2 = Foo()
+        bar1 = Bar()
+        s1 = [[foo1], [foo2], [bar1]]
+        s2 = s1[:]
+        if neg: return s1[i] != s2[i]
+        return s1[i] == s2[j]
+    for i in range(3):
+        for j in range(3):
+            for case in False, True:
+                res = interpret(fn, [i, j, case])
+                assert res is fn(i, j, case)
+
+def test_list_contains():
+    def fn(i, neg=False):
+        foo1 = Foo()
+        foo2 = Foo()
+        bar1 = Bar()
+        bar2 = Bar()
+        lis = [foo1, foo2, bar1]
+        args = lis + [bar2]
+        if neg : return args[i] not in lis
+        return args[i] in lis
+    for i in range(4):
+        for case in False, True:
+            res = interpret(fn, [i, case])
+            assert res is fn(i, case)
+
+def test_list_index():
+    def fn(i):
+        foo1 = Foo()
+        foo2 = Foo()
+        bar1 = Bar()
+        bar2 = Bar()
+        lis = [foo1, foo2, bar1]
+        args = lis + [bar2]
+        return lis.index(args[i])
+    for i in range(4):
+        try:
+            res = interpret(fn, [i])
+        except Exception, e:
+            res = find_exception(e)
+        try:
+            res2 = fn(i)
+        except Exception, e:
+            res2 = e.__class__
+        assert res == res2
+
+def test_list_str():
+    def fn():
+        return str([1,2,3])
+    
+    res = interpret(fn, [])
+    assert ''.join(res.chars) == fn()
+
+    def fn():
+        return str([[1,2,3]])
+    
+    res = interpret(fn, [])
+    assert ''.join(res.chars) == fn()

Modified: pypy/branch/pycompiler/rpython/test/test_rpbc.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rpbc.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rpbc.py	Fri Jul  1 18:30:34 2005
@@ -1,15 +1,7 @@
 from pypy.translator.translator import Translator
 from pypy.rpython.lltype import *
 from pypy.rpython.rtyper import RPythonTyper
-
-
-def rtype(fn, argtypes=[]):
-    t = Translator(fn)
-    t.annotate(argtypes)
-    typer = RPythonTyper(t.annotator)
-    typer.specialize()
-    t.checkgraphs()
-    return t
+from pypy.rpython.test.test_llinterp import interpret
 
 
 def test_easy_call():
@@ -17,7 +9,8 @@
         return x+1
     def g(y):
         return f(y+2)
-    rtype(g, [int])
+    res = interpret(g, [5])
+    assert res == 8
 
 def test_multiple_call():
     def f1(x):
@@ -30,7 +23,10 @@
         else:
             f = f2
         return f(y+3)
-    rtype(g, [int])
+    res = interpret(g, [-1])
+    assert res == 3
+    res = interpret(g, [1])
+    assert res == 6
 
 
 class MyBase:
@@ -46,7 +42,8 @@
         obj = MyBase()
         obj.z = a
         return obj.m(b)
-    rtype(f, [int, int])
+    res = interpret(f, [4, 5])
+    assert res == 9
 
 def test_virtual_method_call():
     def f(a, b):
@@ -56,4 +53,203 @@
             obj = MySubclass()
         obj.z = a
         return obj.m(b)
-    rtype(f, [int, int])
+    res = interpret(f, [1, 2.3])
+    assert res == 3.3
+    res = interpret(f, [-1, 2.3])
+    assert res == -3.3
+
+
+class MyBaseWithInit:
+    def __init__(self, a):
+        self.a1 = a
+
+def test_class_init():
+    def f(a):
+        instance = MyBaseWithInit(a)
+        return instance.a1
+    assert interpret(f, [5]) == 5
+
+
+class Freezing:
+    def _freeze_(self):
+        return True
+    def mymethod(self, y):
+        return self.x + y
+
+def test_freezing():
+    fr1 = Freezing()
+    fr2 = Freezing()
+    fr1.x = 5
+    fr2.x = 6
+    def g(fr):
+        return fr.x
+    def f(n):
+        if n > 0:
+            fr = fr1
+        elif n < 0:
+            fr = fr2
+        else:
+            fr = None
+        return g(fr)
+    res = interpret(f, [1])
+    assert res == 5
+    res = interpret(f, [-1])
+    assert res == 6
+
+def test_call_frozen_pbc_simple():
+    fr1 = Freezing()
+    fr1.x = 5
+    def f(n):
+        return fr1.mymethod(n)
+    res = interpret(f, [6])
+    assert res == 11
+
+def test_call_frozen_pbc_multiple():
+    fr1 = Freezing()
+    fr2 = Freezing()
+    fr1.x = 5
+    fr2.x = 6
+    def f(n):
+        if n > 0:
+            fr = fr1
+        else:
+            fr = fr2
+        return fr.mymethod(n)
+    res = interpret(f, [1])
+    assert res == 6
+    res = interpret(f, [-1])
+    assert res == 5
+
+def test_unbound_method():
+    def f():
+        inst = MySubclass()
+        inst.z = 40
+        return MyBase.m(inst, 2)
+    res = interpret(f, [])
+    assert res == 42
+
+def test_call_defaults():
+    def g(a, b=2, c=3):
+        return a+b+c
+    def f1():
+        return g(1)
+    def f2():
+        return g(1, 10)
+    def f3():
+        return g(1, 10, 100)
+    res = interpret(f1, [])
+    assert res == 1+2+3
+    res = interpret(f2, [])
+    assert res == 1+10+3
+    res = interpret(f3, [])
+    assert res == 1+10+100
+
+def test_call_memoized_function():
+    fr1 = Freezing()
+    fr2 = Freezing()
+    def getorbuild(key):
+        a = 1
+        if key is fr1:
+            result = eval("a+2")
+        else:
+            result = eval("a+6")
+        return result
+    getorbuild._annspecialcase_ = "specialize:memo"
+
+    def f1(i):
+        if i > 0:
+            fr = fr1
+        else:
+            fr = fr2
+        return getorbuild(fr)
+
+    res = interpret(f1, [0]) 
+    assert res == 7
+    res = interpret(f1, [1]) 
+    assert res == 3
+
+def test_call_memoized_cache():
+
+    # this test checks that we add a separate field 
+    # per specialization and also it uses a subclass of 
+    # the standard pypy.tool.cache.Cache
+
+    from pypy.tool.cache import Cache
+    fr1 = Freezing()
+    fr2 = Freezing()
+
+    class Cache1(Cache): 
+        def _build(self, key): 
+            "NOT_RPYTHON" 
+            if key is fr1:
+                return fr2 
+            else:
+                return fr1 
+
+    class Cache2(Cache): 
+        def _build(self, key): 
+            "NOT_RPYTHON" 
+            a = 1
+            if key is fr1:
+                result = eval("a+2")
+            else:
+                result = eval("a+6")
+            return result
+
+    cache1 = Cache1()
+    cache2 = Cache2()
+
+    def f1(i):
+        if i > 0:
+            fr = fr1
+        else:
+            fr = fr2
+        newfr = cache1.getorbuild(fr)
+        return cache2.getorbuild(newfr)
+
+    res = interpret(f1, [0], view=0, viewbefore=0)  
+    assert res == 3
+    res = interpret(f1, [1]) 
+    assert res == 7
+
+def test_rpbc_bound_method_static_call():
+    class R:
+        def meth(self):
+            return 0
+    r = R()
+    m = r.meth
+    def fn():
+        return m()
+    res = interpret(fn, [])
+    assert res == 0
+
+def test_constant_return_disagreement():
+    class R:
+        def meth(self):
+            return 0
+    r = R()
+    def fn():
+        return r.meth()
+    res = interpret(fn, [])
+    assert res == 0
+
+def test_None_is_false():
+    def fn(i):
+        return bool([None, fn][i])
+    res = interpret(fn, [1])
+    assert res is True
+    res = interpret(fn, [0])
+    assert res is False
+
+def INPROGRESS_test_classpbc_getattr():
+    class A:
+        myvalue = 123
+    class B(A):
+        myvalue = 456
+    def f(i):
+        B()      # force B and A to have a ClassDef
+        return [A,B][i].myvalue
+    res = interpret(f, [0], view=True)
+    assert res == 123
+    res = interpret(f, [1])
+    assert res == 456

Modified: pypy/branch/pycompiler/rpython/test/test_rptr.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rptr.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rptr.py	Fri Jul  1 18:30:34 2005
@@ -31,3 +31,15 @@
         return cast_pointer(PS2, p)
     s, t = ll_rtype(llup, [annmodel.SomePtr(PS)])
     assert s.ll_ptrtype == PS2
+
+def test_runtime_type_info():
+    S = GcStruct('s', ('x', Signed))
+    attachRuntimeTypeInfo(S)
+    def ll_example(p):
+        return (runtime_type_info(p),
+                runtime_type_info(p) == getRuntimeTypeInfo(S))
+
+    assert ll_example(malloc(S)) == (getRuntimeTypeInfo(S), True)
+    s, t = ll_rtype(ll_example, [annmodel.SomePtr(Ptr(S))])
+    assert s == annmodel.SomeTuple([annmodel.SomePtr(Ptr(RuntimeTypeInfo)),
+                                    annmodel.SomeBool()])

Modified: pypy/branch/pycompiler/rpython/test/test_rrange.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rrange.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rrange.py	Fri Jul  1 18:30:34 2005
@@ -1,6 +1,6 @@
 from pypy.translator.translator import Translator
-from pypy.rpython.rtyper import RPythonTyper
 from pypy.rpython.rrange import *
+from pypy.rpython.test.test_llinterp import interpret
 
 def test_rlist_range():
     def test1(start, stop, step):
@@ -22,20 +22,40 @@
 
 # ____________________________________________________________
 
-def rtype(fn, argtypes=[]):
-    t = Translator(fn)
-    t.annotate(argtypes)
-    typer = RPythonTyper(t.annotator)
-    typer.specialize()
-    #t.view()
-    t.checkgraphs()
-    return t
+def test_range():
+    def dummyfn(N):
+        total = 0
+        for i in range(N):
+            total += i
+        return total
+    res = interpret(dummyfn, [10])
+    assert res == 45
 
+def test_range_is_lazy():
+    def dummyfn(N, M):
+        total = 0
+        for i in range(M):
+            if i == N:
+                break
+            total += i
+        return total
+    res = interpret(dummyfn, [10, 2147418112])
+    assert res == 45
+
+def test_range_item():
+    def dummyfn(start, stop, i):
+        r = range(start, stop)
+        return r[i]
+    res = interpret(dummyfn, [10, 17, 4])
+    assert res == 14
+    res = interpret(dummyfn, [10, 17, -2])
+    assert res == 15
 
 def test_range():
     def dummyfn(N):
         total = 0
-        for i in range(N):
+        for i in xrange(N):
             total += i
         return total
-    rtype(dummyfn, [int])
+    res = interpret(dummyfn, [10])
+    assert res == 45

Modified: pypy/branch/pycompiler/rpython/test/test_rstr.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rstr.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rstr.py	Fri Jul  1 18:30:34 2005
@@ -1,55 +1,332 @@
 from pypy.translator.translator import Translator
 from pypy.rpython.lltype import *
-from pypy.rpython.rtyper import RPythonTyper
+from pypy.rpython.rstr import parse_fmt_string
+from pypy.rpython.rtyper import RPythonTyper, TyperError
+from pypy.rpython.test.test_llinterp import interpret
 
 
 def test_simple():
-    def dummyfn(i):
+    def fn(i):
         s = 'hello'
         return s[i]
-
-    t = Translator(dummyfn)
-    t.annotate([int])
-    typer = RPythonTyper(t.annotator)
-    typer.specialize()
-    #t.view()
-    t.checkgraphs()
+    for i in range(5):
+        res = interpret(fn, [i])
+        assert res == 'hello'[i]
 
 
 def test_nonzero():
-    def dummyfn(i, s):
+    def fn(i, j):
+        s = ['', 'xx'][j]
         if i < 0:
             s = None
         if i > -2:
             return bool(s)
         else:
             return False
-
-    t = Translator(dummyfn)
-    t.annotate([int, str])
-    typer = RPythonTyper(t.annotator)
-    typer.specialize()
-    #t.view()
-    t.checkgraphs()
+    for i in [-2, -1, 0]:
+        for j in range(2):
+            res = interpret(fn, [i, j])
+            assert res is fn(i, j)
 
 def test_hash():
-    def dummyfn(s):
+    def fn(i):
+        if i == 0:
+            s = ''
+        else:
+            s = "xxx"
         return hash(s)
-
-    t = Translator(dummyfn)
-    t.annotate([str])
-    typer = RPythonTyper(t.annotator)
-    typer.specialize()
-    #t.view()
-    t.checkgraphs()
+    res = interpret(fn, [0])
+    assert res == -1
+    res = interpret(fn, [1])
+    assert typeOf(res) == Signed
 
 def test_concat():
-    def dummyfn(s1, s2):
-        return s1 + s2
+    def fn(i, j):
+        s1 = ['', 'a', 'ab']
+        s2 = ['', 'x', 'xy']
+        return s1[i] + s2[j]
+    for i in range(3):
+        for j in range(3):
+            res = interpret(fn, [i,j])
+            assert ''.join(res.chars) == fn(i, j)
+
+def test_iter():
+    def fn(i):
+        s = ['', 'a', 'hello'][i]
+        i = 0
+        for c in s:
+            if c != s[i]:
+                return False
+            i += 1
+        if i == len(s):
+            return True
+        return False
+
+    for i in range(3):
+        res = interpret(fn, [i])
+        assert res is True
+        
+def test_char_constant():
+    def fn(s):
+        return s + '.'
+    res = interpret(fn, ['x'])
+    assert len(res.chars) == 2
+    assert res.chars[0] == 'x'
+    assert res.chars[1] == '.'
+
+def test_char_isspace():
+    def fn(s):
+        return s.isspace() 
+    res = interpret(fn, ['x']) 
+    assert res == False 
+    res = interpret(fn, [' '])
+    assert res == True 
+
+def test_char_compare():
+    res = interpret(lambda c1, c2: c1 == c2,  ['a', 'b'])
+    assert res is False
+    res = interpret(lambda c1, c2: c1 == c2,  ['a', 'a'])
+    assert res is True
+    res = interpret(lambda c1, c2: c1 <= c2,  ['z', 'a'])
+    assert res is False
+
+def test_char_mul():
+    def fn(c, mul):
+        s = c * mul
+        res = 0
+        for i in range(len(s)):
+            res = res*10 + ord(s[i]) - ord('0')
+        c2 = c
+        c2 *= mul
+        res = 10 * res + (c2 == s)
+        return res
+    res = interpret(fn, ['3', 5])
+    assert res == 333331
+    res = interpret(fn, ['5', 3])
+    assert res == 5551
+
+def test_str_compare():
+    def fn(i, j):
+        s1 = ['one', 'two']
+        s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar']
+        return s1[i] == s2[j]
+    for i in range(2):
+        for j in range(6):
+            res = interpret(fn, [i,j])
+            assert res is fn(i, j)
+
+    def fn(i, j):
+        s1 = ['one', 'two']
+        s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar']
+        return s1[i] != s2[j]
+    for i in range(2):
+        for j in range(6):
+            res = interpret(fn, [i, j])
+            assert res is fn(i, j)
+
+    def fn(i, j):
+        s1 = ['one', 'two']
+        s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar']
+        return s1[i] < s2[j]
+    for i in range(2):
+        for j in range(6):
+            res = interpret(fn, [i,j])
+            assert res is fn(i, j)
+
+    def fn(i, j):
+        s1 = ['one', 'two']
+        s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar']
+        return s1[i] <= s2[j]
+    for i in range(2):
+        for j in range(6):
+            res = interpret(fn, [i,j])
+            assert res is fn(i, j)
+
+    def fn(i, j):
+        s1 = ['one', 'two']
+        s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar']
+        return s1[i] >= s2[j]
+    for i in range(2):
+        for j in range(6):
+            res = interpret(fn, [i,j])
+            assert res is fn(i, j)
+
+    def fn(i, j):
+        s1 = ['one', 'two']
+        s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar']
+        return s1[i] > s2[j]
+    for i in range(2):
+        for j in range(6):
+            res = interpret(fn, [i,j])
+            assert res is fn(i, j)
+
+def test_startswith():
+    def fn(i, j):
+        s1 = ['one', 'two']
+        s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo']
+        return s1[i].startswith(s2[j])
+    for i in range(2):
+        for j in range(9):
+            res = interpret(fn, [i,j])
+            assert res is fn(i, j)
+
+def test_endswith():
+    def fn(i, j):
+        s1 = ['one', 'two']
+        s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo']
+        return s1[i].endswith(s2[j])
+    for i in range(2):
+        for j in range(9):
+            res = interpret(fn, [i,j])
+            assert res is fn(i, j)
+
+def test_join():
+    res = interpret(lambda: ''.join([]), [])
+    assert ''.join(res.chars) == ""
+    
+    def fn(i, j):
+        s1 = [ '', ',', ' and ']
+        s2 = [ [], ['foo'], ['bar', 'baz', 'bazz']]
+        return s1[i].join(s2[j])
+    for i in range(3):
+        for j in range(3):
+            res = interpret(fn, [i,j])
+            assert ''.join(res.chars) == fn(i, j)
+
+def test_parse_fmt():
+    assert parse_fmt_string('a') == ['a']
+    assert parse_fmt_string('%s') == [('s',)]
+    assert parse_fmt_string("name '%s' is not defined") == ["name '", ("s",), "' is not defined"]
+
+def test_strformat():
+    def percentS(s):
+        return "before %s after" % (s,)
+
+    res = interpret(percentS, ['1'])
+    assert ''.join(res.chars) == 'before 1 after'
+
+    def percentD(i):
+        return "bing %d bang" % (i,)
+    
+    res = interpret(percentD, [23])
+    assert ''.join(res.chars) == 'bing 23 bang'
+
+    def percentX(i):
+        return "bing %x bang" % (i,)
+    
+    res = interpret(percentX, [23])
+    assert ''.join(res.chars) == 'bing 17 bang'
+
+    res = interpret(percentX, [-123])
+    assert ''.join(res.chars) == 'bing -7b bang'
+
+    def moreThanOne(s, d, x):
+        return "string: %s decimal: %d hex: %x" % (s, d, x)
+
+    args = 'a', 2, 3
+    res = interpret(moreThanOne, list(args))
+    assert ''.join(res.chars) == moreThanOne(*args)
+
+def test_strformat_nontuple():
+    def percentD(i):
+        return "before %d after" % i
+
+    res = interpret(percentD, [1])
+    assert ''.join(res.chars) == 'before 1 after'
+
+    def percentS(i):
+        return "before %s after" % i
+
+    res = interpret(percentS, ['D'])
+    assert ''.join(res.chars) == 'before D after'
+
+def test_str_slice():
+    def fn():
+        s = 'hello'
+        s1 = s[:3]
+        s2 = s[3:]
+        return s1+s2 == s and s2+s1 == 'lohel'
+    res = interpret(fn, ())
+    assert res
+
+def test_strformat_instance():
+    class C:
+        pass
+    class D(C):
+        pass
+    def dummy(i):
+        if i:
+            x = C()
+        else:
+            x = D()
+        return str(x)
+        
+    res = interpret(dummy, [1])
+    assert ''.join(res.chars) == '<C object>'
+
+    res = interpret(dummy, [0])
+    assert ''.join(res.chars) == '<D object>'
+
+def test_percentformat_instance():
+    class C:
+        pass
+    class D(C):
+        pass
+    
+    def dummy(i):
+        if i:
+            x = C()
+            y = D()
+        else:
+            x = D()
+            y = C()
+        return "what a nice %s, much nicer than %r"%(x, y)
+        
+    res = interpret(dummy, [1])
+    assert ''.join(res.chars) == 'what a nice <C object>, much nicer than <D object>'
+
+    res = interpret(dummy, [0])
+    assert ''.join(res.chars) == 'what a nice <D object>, much nicer than <C object>'
+
+def test_split():
+    def fn(i):
+        s = ['', '0.1.2.4.8', '.1.2', '1.2.', '.1.2.4.'][i]
+        l = s.split('.')
+        sum = 0
+        for num in l:
+             if len(num):
+                 sum += ord(num) - ord('0')
+        return sum + len(l) * 100
+    for i in range(5):
+        res = interpret(fn, [i])
+        assert res == fn(i)
+
+def test_contains():
+    def fn(i):
+        s = 'Hello world'
+        return chr(i) in s
+    for i in range(256):
+        res = interpret(fn, [i])#, view=i==42)
+        assert res == fn(i)
 
-    t = Translator(dummyfn)
-    t.annotate([str, str])
-    typer = RPythonTyper(t.annotator)
-    typer.specialize()
-    #t.view()
-    t.checkgraphs()
+def test_replace():
+    def fn(c1, c2):
+        s = 'abbccc'
+        s = s.replace(c1, c2)
+        res = 0
+        for c in s:
+            if c == c2:
+                res += 1
+        return res
+    res = interpret(fn, ['a', 'c'])
+    assert res == 4
+    res = interpret(fn, ['c', 'b'])
+    assert res == 5
+    def fn():
+        s = 'abbccc'
+        s = s.replace('a', 'baz')
+    raises (TyperError, interpret, fn, ())
+    def fn():
+        s = 'abbccc'
+        s = s.replace('abb', 'c')
+    raises (TyperError, interpret, fn, ())

Modified: pypy/branch/pycompiler/rpython/test/test_rtuple.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rtuple.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rtuple.py	Fri Jul  1 18:30:34 2005
@@ -4,7 +4,8 @@
 from pypy.rpython.rtuple import *
 from pypy.rpython.rint import signed_repr
 from pypy.rpython.rbool import bool_repr
-
+from pypy.rpython.test.test_llinterp import interpret 
+import py
 
 def test_rtuple():
     rtuple = TupleRepr([signed_repr, bool_repr])
@@ -44,3 +45,35 @@
 ##            total += x
 ##        return total
 ##    rtype(dummyfn)
+
+def test_return_tuple():
+    def dummyfn(x, y):
+        return (x<y, x>y)
+    rtype(dummyfn, [int, int])
+
+def test_tuple_concatenation():
+    def f():
+        tup = (1,2)
+        tup1 = (3,)
+        res = tup + tup1 + ()
+        return res[0]*100 + res[1]*10 + res[2]
+    res = interpret(f, []) 
+    assert res == 123
+
+def test_tuple_concatenation_mix():
+    def f():
+        tup = (1,2)
+        tup1 = ('3',)
+        res = tup + tup1
+        return res[0]*100 + res[1]*10 + ord(res[2]) - ord('0')
+    res = interpret(f, []) 
+    assert res == 123
+
+def test_constant_tuple_contains(): 
+    def f(i): 
+        t1 = (1, 2, 3, 4)
+        return i in t1 
+    res = interpret(f, [3], view=False, viewbefore=False) 
+    assert res is True 
+    res = interpret(f, [0])
+    assert res is False 

Modified: pypy/branch/pycompiler/rpython/test/test_rtyper.py
==============================================================================
--- pypy/branch/pycompiler/rpython/test/test_rtyper.py	(original)
+++ pypy/branch/pycompiler/rpython/test/test_rtyper.py	Fri Jul  1 18:30:34 2005
@@ -1,20 +1,24 @@
 from pypy.annotation import model as annmodel
 from pypy.translator.translator import Translator
 from pypy.rpython.lltype import *
+from pypy.rpython.test.test_llinterp import interpret 
 from pypy.rpython.rtyper import RPythonTyper
+import py
 
+def setup_module(mod): 
+    mod.logstate = py.log._getstate()
+    py.log.setconsumer("rtyper", py.log.STDOUT)
+    py.log.setconsumer("annrpython", None)   
+
+def teardown_module(mod): 
+    py.log._setstate(mod.logstate) 
 
 def test_simple():
     def dummyfn(x):
         return x+1
 
-    t = Translator(dummyfn)
-    t.annotate([int])
-    typer = RPythonTyper(t.annotator)
-    typer.specialize()
-    #t.view()
-    t.checkgraphs()
-
+    res = interpret(dummyfn, [7])
+    assert res == 8
 
 def test_function_call():
     def g(x, y):
@@ -22,13 +26,8 @@
     def f(x):
         return g(1, x)
 
-    t = Translator(f)
-    t.annotate([int])
-    typer = RPythonTyper(t.annotator)
-    typer.specialize()
-    #t.view()
-    t.checkgraphs()
-
+    res = interpret(f, [4])
+    assert res == -3 
 
 def test_retval():
     def f(x):

Modified: pypy/branch/pycompiler/tool/_enum_exceptions.py
==============================================================================
--- pypy/branch/pycompiler/tool/_enum_exceptions.py	(original)
+++ pypy/branch/pycompiler/tool/_enum_exceptions.py	Fri Jul  1 18:30:34 2005
@@ -177,7 +177,7 @@
     return tuple(res)
 
 def findAllArgs(exc, maxprobe):
-    minargs, maxargs = probeArgCount(exc, maxprobe=20)
+    minargs, maxargs = probeArgCount(exc, maxprobe)
     res = []
     # for minargs args, we need to try combinations
     arglist = tuple([genArgsToTry(i) for i in range(minargs)])
@@ -231,11 +231,11 @@
             txt = br[0] + ", ".join(stuff) + br[-1]
             names[obj] = txt
         else:
-            names[obj] = "%r # default, hopefully" % obj
+            names[obj] = "%r" % obj
         return names[obj]
     res = []
     for i,(name, obj) in enumerate(assigned):
-        if isinstance(obj,ProbeObject) or name == 'args':
+        if isinstance(obj,ProbeObject) or name == 'args' or obj==None:
             res.append("self.%s = %s" % (name, nameof(obj)))
         else:
             res.append("if type(%s) == %s:"%(nameof(obj),repr(type(obj))[7:-2]))
@@ -284,8 +284,10 @@
             dense = tuple(range(argcounts[0], argcounts[-1]+1)) == argcounts
             if len(argcounts) == 1:
                 yield "    if argc == %d:" % argcounts
-                trailer = ["    else:"]
-                trailer += ["        raise TypeError('function takes exactly 5 arguments (%d given)'%argc)"]
+                if maxargs == minargs:
+                    trailer = ["    else:"]
+                    err_msg = ""
+                    trailer += ["        raise TypeError('function takes exactly "+str(argcounts[0])+" arguments (%d given)'%argc)"]
             elif dense and argcounts[0] == 0:
                 yield "    if argc <= %d:" % argcounts[-1]
             elif dense and argcounts[-1] == maxprobe-1:
@@ -294,8 +296,11 @@
                 yield "    if %d <= argc <= %d:" % (argcounts[0], argcounts[-1])
             else:
                 yield "    if argc in %r:" % (argcounts, )
-        for order, line in ordered_statements:
-            yield indent * "    " + line
+        if len(ordered_statements)>0:
+            for order, line in ordered_statements:
+                yield indent * "    " + line
+        else:
+            yield indent * "    " + "pass"
         if trailer:
             for line in trailer : yield line
 

Modified: pypy/branch/pycompiler/tool/ansi_print.py
==============================================================================
--- pypy/branch/pycompiler/tool/ansi_print.py	(original)
+++ pypy/branch/pycompiler/tool/ansi_print.py	Fri Jul  1 18:30:34 2005
@@ -7,8 +7,21 @@
 def ansi_print(text, esc, file=None):
     if file is None: file = sys.stderr
     text = text.rstrip()
-    if sys.platform != "win32" and file.isatty():
+    if esc and sys.platform != "win32" and file.isatty():
         text = ('\x1b[%sm' % esc  +  
                 text +
                 '\x1b[0m')     # ANSI color code "reset"
     file.write(text + '\n')
+
+def ansi_log(msg): 
+    keywords = list(msg.keywords)
+    if 'bold' in keywords: 
+        keywords.remove('bold')
+        esc = "1"
+    elif 'red' in keywords: 
+        keywords.remove('red')
+        esc = "31"
+    else: 
+        esc = None
+    ansi_print("[%s] %s" %(":".join(keywords), msg.content()), esc)
+ 

Modified: pypy/branch/pycompiler/tool/cache.py
==============================================================================
--- pypy/branch/pycompiler/tool/cache.py	(original)
+++ pypy/branch/pycompiler/tool/cache.py	Fri Jul  1 18:30:34 2005
@@ -13,7 +13,7 @@
 # Cache class:
 #     a cache meant to map a finite number of keys to values.
 #     It is normally extended lazily, until it contains all possible
-#     keys.  The _specialize_ attribute of the getorbuild() method
+#     keys.  The _annspecialcase_ attribute of the getorbuild() method
 #     forces the annotator to decode the argument's annotations,
 #     which must be constants or SomePBCs, actually call the
 #     method with all possible combinations, and gather the results.

Modified: pypy/branch/pycompiler/tool/unionfind.py
==============================================================================
--- pypy/branch/pycompiler/tool/unionfind.py	(original)
+++ pypy/branch/pycompiler/tool/unionfind.py	Fri Jul  1 18:30:34 2005
@@ -4,7 +4,7 @@
 
 class UnionFind(object):
 
-    def __init__(self, info_factory):
+    def __init__(self, info_factory=None):
         self.link_to_parent = {}
         self.weight = {}
         self.info_factory = info_factory
@@ -15,9 +15,9 @@
         if obj not in self.link_to_parent:
             raise KeyError, obj
 
-        ignore, rep, access = self.find(obj)
+        ignore, rep, info = self.find(obj)
 
-        return access
+        return info
 
     def __contains__(self, obj):
         return obj in self.link_to_parent
@@ -31,9 +31,17 @@
     def infos(self):
         return self.root_info.values()
 
+    def find_rep(self, obj):
+        ignore, rep, info = self.find(obj)
+        return rep
+
     def find(self, obj):  # -> new_root, obj, info
         if obj not in self.link_to_parent:
-            info = self.root_info[obj] = self.info_factory(obj)
+            if self.info_factory:
+                info = self.info_factory(obj)
+            else:
+                info = None
+            self.root_info[obj] = info
             self.weight[obj] = 1
             self.link_to_parent[obj] = obj
             return True, obj, info
@@ -66,7 +74,8 @@
         if w1 < w2:
             rep1, rep2, info1, info2, = rep2, rep1, info2, info1
 
-        info1.update(info2)
+        if info1 is not None:
+            info1.update(info2)
 
         self.link_to_parent[rep2] = rep1
 



More information about the Pypy-commit mailing list