[pypy-svn] r24200 - in pypy/branch/njriley-trans: demo lib-python/modified-2.4.1 pypy pypy/annotation pypy/annotation/test pypy/bin pypy/doc pypy/doc/discussion pypy/doc/image pypy/interpreter pypy/interpreter/astcompiler pypy/interpreter/pyparser pypy/interpreter/pyparser/data pypy/interpreter/pyparser/test pypy/interpreter/pyparser/test/samples pypy/interpreter/stablecompiler pypy/interpreter/test pypy/jit pypy/jit/test pypy/lib pypy/lib/logic pypy/lib/logic/computation_space pypy/lib/logic/gecode_wrapper pypy/module/__builtin__ pypy/module/__builtin__/test pypy/module/recparser pypy/module/stackless/test pypy/module/symbol pypy/objspace pypy/objspace/flow pypy/objspace/flow/test pypy/objspace/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/memory pypy/rpython/ootypesystem pypy/rpython/ootypesystem/test pypy/rpython/rctypes pypy/rpython/rctypes/test pypy/rpython/test pypy/tool pypy/translator pypy/translator/c pypy/translator/c/src pypy/translator/c/test pypy/translator/c/winproj/extension pypy/translator/c/winproj/standalone pypy/translator/goal pypy/translator/llvm pypy/translator/llvm/demo pypy/translator/llvm/pyllvm pypy/translator/llvm/pyllvm/test pypy/translator/llvm/test pypy/translator/squeak pypy/translator/squeak/test pypy/translator/tool

njriley at codespeak.net njriley at codespeak.net
Fri Mar 10 06:12:20 CET 2006


Author: njriley
Date: Fri Mar 10 06:12:02 2006
New Revision: 24200

Added:
   pypy/branch/njriley-trans/demo/producerconsumer.py
      - copied unchanged from r24195, pypy/dist/demo/producerconsumer.py
   pypy/branch/njriley-trans/demo/uthread.py
      - copied unchanged from r24195, pypy/dist/demo/uthread.py
   pypy/branch/njriley-trans/lib-python/modified-2.4.1/__future__.py
      - copied unchanged from r24195, pypy/dist/lib-python/modified-2.4.1/__future__.py
   pypy/branch/njriley-trans/lib-python/modified-2.4.1/opcode.py
      - copied unchanged from r24195, pypy/dist/lib-python/modified-2.4.1/opcode.py
   pypy/branch/njriley-trans/pypy/doc/discussion/removing-stable-compiler.txt
      - copied unchanged from r24195, pypy/dist/pypy/doc/discussion/removing-stable-compiler.txt
   pypy/branch/njriley-trans/pypy/doc/discussion/use_case_of_logic.txt
      - copied unchanged from r24195, pypy/dist/pypy/doc/discussion/use_case_of_logic.txt
   pypy/branch/njriley-trans/pypy/doc/image/arch-impllevels.graffle
      - copied unchanged from r24195, pypy/dist/pypy/doc/image/arch-impllevels.graffle
   pypy/branch/njriley-trans/pypy/doc/image/arch-impllevels.pdf
      - copied unchanged from r24195, pypy/dist/pypy/doc/image/arch-impllevels.pdf
   pypy/branch/njriley-trans/pypy/doc/image/arch-jit-gen.graffle
      - copied unchanged from r24195, pypy/dist/pypy/doc/image/arch-jit-gen.graffle
   pypy/branch/njriley-trans/pypy/doc/image/arch-jit-gen.pdf
      - copied unchanged from r24195, pypy/dist/pypy/doc/image/arch-jit-gen.pdf
   pypy/branch/njriley-trans/pypy/doc/image/arch-pypy-basic.graffle
      - copied unchanged from r24195, pypy/dist/pypy/doc/image/arch-pypy-basic.graffle
   pypy/branch/njriley-trans/pypy/doc/image/arch-pypy-basic.pdf
      - copied unchanged from r24195, pypy/dist/pypy/doc/image/arch-pypy-basic.pdf
   pypy/branch/njriley-trans/pypy/doc/image/arch-translation.graffle
      - copied unchanged from r24195, pypy/dist/pypy/doc/image/arch-translation.graffle
   pypy/branch/njriley-trans/pypy/doc/image/arch-translation.pdf
      - copied unchanged from r24195, pypy/dist/pypy/doc/image/arch-translation.pdf
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/data/Grammar2.5a
      - copied unchanged from r24195, pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/data/Grammar2.5a_with
      - copied unchanged from r24195, pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a_with
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/data/Grammar_stablecompiler
      - copied unchanged from r24195, pypy/dist/pypy/interpreter/pyparser/data/Grammar_stablecompiler
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/data/README
      - copied unchanged from r24195, pypy/dist/pypy/interpreter/pyparser/data/README
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/samples/snippet_with_1.py
      - copied unchanged from r24195, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_with_1.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/samples/snippet_with_2.py
      - copied unchanged from r24195, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_with_2.py
   pypy/branch/njriley-trans/pypy/lib/functional.py
      - copied unchanged from r24195, pypy/dist/pypy/lib/functional.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/event.py
      - copied unchanged from r24195, pypy/dist/pypy/lib/logic/computation_space/event.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/parsesudoku.py
      - copied unchanged from r24195, pypy/dist/pypy/lib/logic/computation_space/parsesudoku.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/puzzle1.su
      - copied unchanged from r24195, pypy/dist/pypy/lib/logic/computation_space/puzzle1.su
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/solution.su
      - copied unchanged from r24195, pypy/dist/pypy/lib/logic/computation_space/solution.su
   pypy/branch/njriley-trans/pypy/lib/logic/gecode_wrapper/
      - copied from r24195, pypy/dist/pypy/lib/logic/gecode_wrapper/
   pypy/branch/njriley-trans/pypy/objspace/logic.py
      - copied unchanged from r24195, pypy/dist/pypy/objspace/logic.py
   pypy/branch/njriley-trans/pypy/objspace/test/test_logicobjspace.py
      - copied unchanged from r24195, pypy/dist/pypy/objspace/test/test_logicobjspace.py
   pypy/branch/njriley-trans/pypy/rpython/exceptiondata.py
      - copied unchanged from r24195, pypy/dist/pypy/rpython/exceptiondata.py
   pypy/branch/njriley-trans/pypy/rpython/extregistry.py
      - copied unchanged from r24195, pypy/dist/pypy/rpython/extregistry.py
   pypy/branch/njriley-trans/pypy/rpython/ootypesystem/exceptiondata.py
      - copied unchanged from r24195, pypy/dist/pypy/rpython/ootypesystem/exceptiondata.py
   pypy/branch/njriley-trans/pypy/rpython/rctypes/rarray.py
      - copied unchanged from r24195, pypy/dist/pypy/rpython/rctypes/rarray.py
   pypy/branch/njriley-trans/pypy/rpython/rctypes/rprimitive.py
      - copied unchanged from r24195, pypy/dist/pypy/rpython/rctypes/rprimitive.py
   pypy/branch/njriley-trans/pypy/rpython/rctypes/test/__init__.py
      - copied unchanged from r24195, pypy/dist/pypy/rpython/rctypes/test/__init__.py
   pypy/branch/njriley-trans/pypy/rpython/rctypes/test/test_rarray.py
      - copied unchanged from r24195, pypy/dist/pypy/rpython/rctypes/test/test_rarray.py
   pypy/branch/njriley-trans/pypy/rpython/rctypes/test/test_rprimitive.py
      - copied unchanged from r24195, pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py
   pypy/branch/njriley-trans/pypy/rpython/test/test_extregistry.py
      - copied unchanged from r24195, pypy/dist/pypy/rpython/test/test_extregistry.py
   pypy/branch/njriley-trans/pypy/tool/__future__.py
      - copied unchanged from r24195, pypy/dist/pypy/tool/__future__.py
   pypy/branch/njriley-trans/pypy/translator/goal/targetlogicstandalone.py
      - copied unchanged from r24195, pypy/dist/pypy/translator/goal/targetlogicstandalone.py
   pypy/branch/njriley-trans/pypy/translator/llvm/buildllvm.py
      - copied unchanged from r24195, pypy/dist/pypy/translator/llvm/buildllvm.py
   pypy/branch/njriley-trans/pypy/translator/llvm/extfunchelper.py
      - copied unchanged from r24195, pypy/dist/pypy/translator/llvm/extfunchelper.py
   pypy/branch/njriley-trans/pypy/translator/llvm/pyllvm/   (props changed)
      - copied from r24195, pypy/dist/pypy/translator/llvm/pyllvm/
   pypy/branch/njriley-trans/pypy/translator/llvm/test/test_symbolic.py
      - copied unchanged from r24195, pypy/dist/pypy/translator/llvm/test/test_symbolic.py
   pypy/branch/njriley-trans/pypy/translator/squeak/test/support.py
      - copied unchanged from r24195, pypy/dist/pypy/translator/squeak/test/support.py
Removed:
   pypy/branch/njriley-trans/pypy/interpreter/astcompiler/transformer.py
   pypy/branch/njriley-trans/pypy/translator/llvm/build_llvm_module.py
Modified:
   pypy/branch/njriley-trans/pypy/annotation/binaryop.py
   pypy/branch/njriley-trans/pypy/annotation/bookkeeper.py
   pypy/branch/njriley-trans/pypy/annotation/builtin.py
   pypy/branch/njriley-trans/pypy/annotation/description.py
   pypy/branch/njriley-trans/pypy/annotation/model.py
   pypy/branch/njriley-trans/pypy/annotation/test/test_model.py
   pypy/branch/njriley-trans/pypy/annotation/unaryop.py
   pypy/branch/njriley-trans/pypy/bin/py.py
   pypy/branch/njriley-trans/pypy/conftest.py
   pypy/branch/njriley-trans/pypy/doc/ctypes-integration.txt
   pypy/branch/njriley-trans/pypy/doc/events.txt
   pypy/branch/njriley-trans/pypy/doc/news.txt
   pypy/branch/njriley-trans/pypy/doc/svn-help.txt
   pypy/branch/njriley-trans/pypy/interpreter/astcompiler/ast.py
   pypy/branch/njriley-trans/pypy/interpreter/astcompiler/ast.txt
   pypy/branch/njriley-trans/pypy/interpreter/astcompiler/consts.py
   pypy/branch/njriley-trans/pypy/interpreter/astcompiler/future.py
   pypy/branch/njriley-trans/pypy/interpreter/astcompiler/pyassem.py
   pypy/branch/njriley-trans/pypy/interpreter/astcompiler/pycodegen.py
   pypy/branch/njriley-trans/pypy/interpreter/gateway.py
   pypy/branch/njriley-trans/pypy/interpreter/pycompiler.py
   pypy/branch/njriley-trans/pypy/interpreter/pyopcode.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/astbuilder.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/ebnfparse.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/pysymbol.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/pythonparse.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/pythonutil.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/symbol.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_astbuilder.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_astcompiler.py
   pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_samples.py
   pypy/branch/njriley-trans/pypy/interpreter/stablecompiler/transformer.py
   pypy/branch/njriley-trans/pypy/interpreter/test/test_syntax.py
   pypy/branch/njriley-trans/pypy/jit/hintrtyper.py
   pypy/branch/njriley-trans/pypy/jit/hinttimeshift.py
   pypy/branch/njriley-trans/pypy/jit/rtimeshift.py
   pypy/branch/njriley-trans/pypy/jit/test/test_hint_annotation.py
   pypy/branch/njriley-trans/pypy/jit/test/test_hint_timeshift.py
   pypy/branch/njriley-trans/pypy/jit/test/test_llabstractinterp.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/computationspace.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/constraint.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/distributor.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/problems.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/state.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/strategies.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/test_computationspace.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/test_variable.py
   pypy/branch/njriley-trans/pypy/lib/logic/computation_space/variable.py
   pypy/branch/njriley-trans/pypy/lib/logic/oz-dataflow-concurrency.txt
   pypy/branch/njriley-trans/pypy/module/__builtin__/__init__.py
   pypy/branch/njriley-trans/pypy/module/__builtin__/app_functional.py
   pypy/branch/njriley-trans/pypy/module/__builtin__/test/test_functional.py
   pypy/branch/njriley-trans/pypy/module/recparser/pyparser.py
   pypy/branch/njriley-trans/pypy/module/stackless/test/test_interp_coroutine.py
   pypy/branch/njriley-trans/pypy/module/symbol/__init__.py
   pypy/branch/njriley-trans/pypy/objspace/flow/model.py
   pypy/branch/njriley-trans/pypy/objspace/flow/objspace.py
   pypy/branch/njriley-trans/pypy/objspace/flow/test/test_objspace.py
   pypy/branch/njriley-trans/pypy/rpython/callparse.py
   pypy/branch/njriley-trans/pypy/rpython/llinterp.py
   pypy/branch/njriley-trans/pypy/rpython/lltypesystem/exceptiondata.py
   pypy/branch/njriley-trans/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/njriley-trans/pypy/rpython/lltypesystem/lloperation.py   (props changed)
   pypy/branch/njriley-trans/pypy/rpython/lltypesystem/lltype.py
   pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rclass.py
   pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rpbc.py
   pypy/branch/njriley-trans/pypy/rpython/lltypesystem/test/test_lloperation.py   (contents, props changed)
   pypy/branch/njriley-trans/pypy/rpython/lltypesystem/test/test_lltype.py
   pypy/branch/njriley-trans/pypy/rpython/memory/gc.py
   pypy/branch/njriley-trans/pypy/rpython/memory/gctransform.py
   pypy/branch/njriley-trans/pypy/rpython/ootypesystem/ootype.py
   pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rbuiltin.py
   pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rclass.py
   pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rpbc.py
   pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_ooann.py
   pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_oopbc.py
   pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_oortype.py
   pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_ootype.py
   pypy/branch/njriley-trans/pypy/rpython/rbuiltin.py
   pypy/branch/njriley-trans/pypy/rpython/rclass.py
   pypy/branch/njriley-trans/pypy/rpython/rctypes/implementation.py
   pypy/branch/njriley-trans/pypy/rpython/rctypes/interface.py
   pypy/branch/njriley-trans/pypy/rpython/rctypes/test/   (props changed)
   pypy/branch/njriley-trans/pypy/rpython/rctypes/test/test_rctypes.py
   pypy/branch/njriley-trans/pypy/rpython/rgenop.py
   pypy/branch/njriley-trans/pypy/rpython/rmodel.py
   pypy/branch/njriley-trans/pypy/rpython/rpbc.py
   pypy/branch/njriley-trans/pypy/rpython/rtyper.py
   pypy/branch/njriley-trans/pypy/rpython/test/test_llinterp.py
   pypy/branch/njriley-trans/pypy/rpython/test/test_ootype_llinterp.py
   pypy/branch/njriley-trans/pypy/rpython/test/test_rclass.py
   pypy/branch/njriley-trans/pypy/rpython/test/test_rgenop.py
   pypy/branch/njriley-trans/pypy/rpython/test/test_rpbc.py
   pypy/branch/njriley-trans/pypy/rpython/typesystem.py
   pypy/branch/njriley-trans/pypy/tool/isolate.py
   pypy/branch/njriley-trans/pypy/tool/opcode.py
   pypy/branch/njriley-trans/pypy/tool/option.py
   pypy/branch/njriley-trans/pypy/translator/c/database.py
   pypy/branch/njriley-trans/pypy/translator/c/external.py
   pypy/branch/njriley-trans/pypy/translator/c/funcgen.py
   pypy/branch/njriley-trans/pypy/translator/c/gc.py
   pypy/branch/njriley-trans/pypy/translator/c/genc.py
   pypy/branch/njriley-trans/pypy/translator/c/node.py
   pypy/branch/njriley-trans/pypy/translator/c/primitive.py
   pypy/branch/njriley-trans/pypy/translator/c/src/address.h
   pypy/branch/njriley-trans/pypy/translator/c/src/g_prerequisite.h
   pypy/branch/njriley-trans/pypy/translator/c/src/support.h
   pypy/branch/njriley-trans/pypy/translator/c/stackless.py
   pypy/branch/njriley-trans/pypy/translator/c/symboltable.py
   pypy/branch/njriley-trans/pypy/translator/c/test/test_boehm.py
   pypy/branch/njriley-trans/pypy/translator/c/test/test_genc.py
   pypy/branch/njriley-trans/pypy/translator/c/test/test_newgc.py
   pypy/branch/njriley-trans/pypy/translator/c/test/test_symbolic.py   (contents, props changed)
   pypy/branch/njriley-trans/pypy/translator/c/winproj/extension/extension.vcproj
   pypy/branch/njriley-trans/pypy/translator/c/winproj/standalone/standalone.vcproj
   pypy/branch/njriley-trans/pypy/translator/driver.py
   pypy/branch/njriley-trans/pypy/translator/geninterplevel.py
   pypy/branch/njriley-trans/pypy/translator/gensupp.py
   pypy/branch/njriley-trans/pypy/translator/goal/translate.py
   pypy/branch/njriley-trans/pypy/translator/interactive.py
   pypy/branch/njriley-trans/pypy/translator/llvm/codewriter.py
   pypy/branch/njriley-trans/pypy/translator/llvm/database.py
   pypy/branch/njriley-trans/pypy/translator/llvm/demo/bpnn.py
   pypy/branch/njriley-trans/pypy/translator/llvm/demo/run.py
   pypy/branch/njriley-trans/pypy/translator/llvm/externs2ll.py
   pypy/branch/njriley-trans/pypy/translator/llvm/genllvm.py
   pypy/branch/njriley-trans/pypy/translator/llvm/opwriter.py
   pypy/branch/njriley-trans/pypy/translator/llvm/pyllvm/test/   (props changed)
   pypy/branch/njriley-trans/pypy/translator/llvm/structnode.py
   pypy/branch/njriley-trans/pypy/translator/llvm/test/runtest.py
   pypy/branch/njriley-trans/pypy/translator/squeak/gensqueak.py
   pypy/branch/njriley-trans/pypy/translator/squeak/test/test_oo.py
   pypy/branch/njriley-trans/pypy/translator/squeak/test/test_squeaktrans.py
   pypy/branch/njriley-trans/pypy/translator/tool/cbuild.py
   pypy/branch/njriley-trans/pypy/translator/tool/graphpage.py
   pypy/branch/njriley-trans/pypy/translator/tool/make_dot.py
   pypy/branch/njriley-trans/pypy/translator/translator.py
Log:
merged to trunk r24194

Modified: pypy/branch/njriley-trans/pypy/annotation/binaryop.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/annotation/binaryop.py	(original)
+++ pypy/branch/njriley-trans/pypy/annotation/binaryop.py	Fri Mar 10 06:12:02 2006
@@ -16,9 +16,11 @@
 from pypy.annotation.model import SomeCTypesObject
 from pypy.annotation.model import unionof, UnionError, set, missing_operation, TLS
 from pypy.annotation.model import add_knowntypedata, merge_knowntypedata
+from pypy.annotation.model import lltype_to_annotation
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.objspace.flow.model import Variable
 from pypy.annotation.listdef import ListDef
+from pypy.rpython import extregistry
 
 # convenience only!
 def immutablevalue(x):
@@ -761,6 +763,10 @@
             # are those having memorystate NOMEMORY
             return s_cto.knowntype._type_.annotator_type
         except AttributeError:
+            if extregistry.is_registered_type(s_cto.knowntype._type_):
+                entry = extregistry.lookup_type(s_cto.knowntype._type_)
+                return lltype_to_annotation(entry.lowleveltype)
+                
             return SomeCTypesObject(
                     s_cto.knowntype._type_,
                     memorystate=s_cto.memorystate)

Modified: pypy/branch/njriley-trans/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/annotation/bookkeeper.py	(original)
+++ pypy/branch/njriley-trans/pypy/annotation/bookkeeper.py	Fri Mar 10 06:12:02 2006
@@ -23,6 +23,7 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.memory import lladdress
+from pypy.rpython import extregistry
 
 class Stats:
 
@@ -358,6 +359,8 @@
         elif ishashable(x) and x in BUILTIN_ANALYZERS:
             _module = getattr(x,"__module__","unknown")
             result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (_module, x.__name__))
+        elif extregistry.is_registered(x):
+            result = extregistry.lookup(x).get_annotation(tp, x)
         elif hasattr(x, "compute_result_annotation"):
             result = SomeBuiltin(x.compute_result_annotation, methodname=x.__name__)
         elif hasattr(tp, "compute_annotation"):
@@ -511,6 +514,8 @@
             return SomeExternalObject(t)
         elif hasattr(t, "compute_annotation"):
             return t.compute_annotation()
+        elif extregistry.is_registered_type(t):
+            return extregistry.lookup_type(t).get_annotation(t)
         elif t.__module__ != '__builtin__' and t not in self.pbctypes:
             classdef = self.getuniqueclassdef(t)
             return SomeInstance(classdef)

Modified: pypy/branch/njriley-trans/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/annotation/builtin.py	(original)
+++ pypy/branch/njriley-trans/pypy/annotation/builtin.py	Fri Mar 10 06:12:02 2006
@@ -464,6 +464,11 @@
     assert isinstance(i, SomeOOInstance) 
     return SomeOOClass(i.ootype)
 
+def subclassof(class1, class2):
+    assert isinstance(class1, SomeOOClass) 
+    assert isinstance(class2, SomeOOClass) 
+    return SomeBool()
+
 def runtimenew(c):
     assert isinstance(c, SomeOOClass)
     if c.ootype is None:
@@ -480,6 +485,7 @@
 BUILTIN_ANALYZERS[ootype.null] = null
 BUILTIN_ANALYZERS[ootype.runtimenew] = runtimenew
 BUILTIN_ANALYZERS[ootype.classof] = classof
+BUILTIN_ANALYZERS[ootype.subclassof] = subclassof
 BUILTIN_ANALYZERS[ootype.ooidentityhash] = ooidentityhash
 
 #________________________________

Modified: pypy/branch/njriley-trans/pypy/annotation/description.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/annotation/description.py	(original)
+++ pypy/branch/njriley-trans/pypy/annotation/description.py	Fri Mar 10 06:12:02 2006
@@ -398,7 +398,7 @@
                 from pypy.annotation.model import s_None, SomeInstance
                 s_func = self.s_read_attribute('__del__')
                 args_s = [SomeInstance(classdef)]
-                s = self.bookkeeper.emulate_pbc_call(None, s_func, args_s)
+                s = self.bookkeeper.emulate_pbc_call(classdef, s_func, args_s)
                 assert s_None.contains(s)
             return classdef
 

Modified: pypy/branch/njriley-trans/pypy/annotation/model.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/annotation/model.py	(original)
+++ pypy/branch/njriley-trans/pypy/annotation/model.py	Fri Mar 10 06:12:02 2006
@@ -565,6 +565,8 @@
             return SomeOOInstance(T)
         elif isinstance(T, ootype.StaticMethod):
             return SomeOOStaticMeth(T)
+        elif T == ootype.Class:
+            return SomeOOClass(ootype.ROOT)
         else:
             return SomePtr(T)
     else:

Modified: pypy/branch/njriley-trans/pypy/annotation/test/test_model.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/annotation/test/test_model.py	(original)
+++ pypy/branch/njriley-trans/pypy/annotation/test/test_model.py	Fri Mar 10 06:12:02 2006
@@ -3,6 +3,7 @@
 import py
 from pypy.annotation.model import *
 from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF
+from pypy.rpython.ootypesystem.ootype import ROOT
 
 
 listdef1 = ListDef(None, SomeTuple([SomeInteger(nonneg=True), SomeString()]))
@@ -118,7 +119,7 @@
     assert isinstance(s_p, SomePtr) and s_p.ll_ptrtype == lltype.Ptr(S)
     s_p = ll_to_annotation(lltype.malloc(A, 0))
     assert isinstance(s_p, SomePtr) and s_p.ll_ptrtype == lltype.Ptr(A)
-    C = ootype.Instance('C', None, {})
+    C = ootype.Instance('C', ROOT, {})
     s_p = ll_to_annotation(ootype.new(C))
     assert isinstance(s_p, SomeOOInstance) and s_p.ootype == C
 
@@ -143,7 +144,7 @@
     s_p = SomePtr(ll_ptrtype=PS)
     assert annotation_to_lltype(s_p) == PS
     py.test.raises(ValueError, "annotation_to_lltype(si0)")
-    C = ootype.Instance('C', None, {})
+    C = ootype.Instance('C', ROOT, {})
     ref = SomeOOInstance(C)
     assert annotation_to_lltype(ref) == C
     
@@ -173,10 +174,10 @@
     py.test.raises(AssertionError, "unionof(SomeObject(), SomePtr(PS1))")
 
 def test_oo_union():
-    C1 = ootype.Instance("C1", None)
+    C1 = ootype.Instance("C1", ROOT)
     C2 = ootype.Instance("C2", C1)
     C3 = ootype.Instance("C3", C1)
-    D = ootype.Instance("D", None)
+    D = ootype.Instance("D", ROOT)
     assert unionof(SomeOOInstance(C1), SomeOOInstance(C1)) == SomeOOInstance(C1)
     assert unionof(SomeOOInstance(C1), SomeOOInstance(C2)) == SomeOOInstance(C1)
     assert unionof(SomeOOInstance(C2), SomeOOInstance(C1)) == SomeOOInstance(C1)
@@ -185,12 +186,7 @@
     assert unionof(SomeOOInstance(C1),SomeImpossibleValue()) == SomeOOInstance(C1)
     assert unionof(SomeImpossibleValue(), SomeOOInstance(C1)) == SomeOOInstance(C1)
 
-    py.test.raises(AssertionError, "unionof(SomeOOInstance(C1), SomeOOInstance(D))")
-    py.test.raises(AssertionError, "unionof(SomeOOInstance(D), SomeOOInstance(C1))")
-    py.test.raises(AssertionError, "unionof(SomeOOInstance(C1), SomeInteger())")
-    py.test.raises(AssertionError, "unionof(SomeInteger(), SomeOOInstance(C1))")
-    py.test.raises(AssertionError, "unionof(SomeOOInstance(C1), SomeObject())")
-    py.test.raises(AssertionError, "unionof(SomeObject(), SomeOOInstance(C1))")
+    assert unionof(SomeOOInstance(C1), SomeOOInstance(D)) == SomeOOInstance(ROOT)
 
 if __name__ == '__main__':
     for name, value in globals().items():

Modified: pypy/branch/njriley-trans/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/annotation/unaryop.py	(original)
+++ pypy/branch/njriley-trans/pypy/annotation/unaryop.py	Fri Mar 10 06:12:02 2006
@@ -13,6 +13,7 @@
 from pypy.annotation import builtin
 
 from pypy.annotation.binaryop import _clone ## XXX where to put this?
+from pypy.rpython import extregistry
 
 # convenience only!
 def immutablevalue(x):
@@ -644,7 +645,12 @@
                                 "%r object has no attribute %r" % (
                                     cto.knowntype, s_attr.const))
             else:
-                atype = cto.knowntype._fields_def_[attr]
+                if extregistry.is_registered_type(cto.knowntype):
+                    entry = extregistry.lookup_type(cto.knowntype)
+                    s_value = entry.fields_s[attr]
+                    return s_value
+                else:
+                    atype = cto.knowntype._fields_def_[attr]
             try:
                 return atype.annotator_type
             except AttributeError:

Modified: pypy/branch/njriley-trans/pypy/bin/py.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/bin/py.py	(original)
+++ pypy/branch/njriley-trans/pypy/bin/py.py	Fri Mar 10 06:12:02 2006
@@ -58,6 +58,8 @@
         from pypy.objspace.std import Space
     elif cmdlineopt.objspace == 'thunk':
         from pypy.objspace.thunk import Space
+    elif cmdlineopt.objspace == 'logic':
+        from pypy.objspace.logic import Space
     else:
         raise ValueError("cannot instantiate %r space" %(cmdlineopt.objspace,))
 

Modified: pypy/branch/njriley-trans/pypy/conftest.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/conftest.py	(original)
+++ pypy/branch/njriley-trans/pypy/conftest.py	Fri Mar 10 06:12:02 2006
@@ -54,7 +54,7 @@
     try:
         return _SPACECACHE[key]
     except KeyError:
-        assert name in ('std', 'thunk'), name 
+        assert name in ('std', 'thunk', 'logic'), name 
         mod = __import__('pypy.objspace.%s' % name, None, None, ['Space'])
         Space = mod.Space
         try: 

Modified: pypy/branch/njriley-trans/pypy/doc/ctypes-integration.txt
==============================================================================
--- pypy/branch/njriley-trans/pypy/doc/ctypes-integration.txt	(original)
+++ pypy/branch/njriley-trans/pypy/doc/ctypes-integration.txt	Fri Mar 10 06:12:02 2006
@@ -80,46 +80,116 @@
 Memory-Layout
 -------------
 
+In Ctypes, all instances are mutable boxes containing either some raw
+memory with a layout compatible to that of the equivalent C type, or a
+reference to such memory.  The reference indirection is transparent to
+the user; for example, dereferencing a ctypes object "pointer to
+structure" results in a "structure" object that doesn't include a copy
+of the data, but only a reference to that data.  (This is similar to the
+C++ notion of reference: it is just a pointer at the machine level, but
+at the language level it behaves like the object that it points to, not
+like a pointer.)
+
+We map this to the LLType model as follows.  For boxes that embed the
+raw memory content::
+
+    Ptr( GcStruct( "name",
+           ("c_data", Struct(...) ) ) )
+
+where the raw memory content and layout is specified by the
+"Struct(...)" part.
+
+For boxes that don't embed the raw memory content::
+
+    Ptr( GcStruct( "name",
+           ("c_data_ref", Ptr(Struct(...)) ) ) )
+
+In both cases, the outer GcStruct is needed to make the boxes tracked by
+the GC automatically.  The "c_data" or "c_data_ref" field either embeds
+or references the raw memory; the "Struct(...)" definition specifies the
+exact C layout expected for that memory.
+
+Of course, the "c_data" and "c_data_ref" fields are not visible to the
+rpython-level user.  This is where an rctype-specific restriction comes
+from: it must be possible for the annotator to figure out statically for
+each variable if it needs to be implemented with a "c_data" or a
+"c_data_ref" field.  (The annotation SomeCTypesObject contains a
+memorystate field which can be OWNSMEMORY ("c_data" case) or MEMORYALIAS
+("c_data_ref" case).)
+
 Primitive Types
 ~~~~~~~~~~~~~~~
+Ctypes' primitive types are mapped directly to the correspondending PyPy
+LLType: Signed, Float, etc.  For the owned-memory case, we get::
 
-Ctypes' primitive types are mapped directly to the correspondending
-PyPy type.
-
-Structures
-~~~~~~~~~~
-Structures will have the following memory layout if they were allocated by ctypes::
-
-    Ptr( GcStruct( "CtypesGcStructure_<ClassName> 
-            ( "c_data" 
-                    (Struct "C-Data_<ClassName>
-                            *<Fieldefintions>) ) ) )
-
-We will try hard not to expose the "c-data" member of the structure
-at rpython level.
-
-Structures that result form dereferencing a pointer will have the following
-layout::
-
-    Ptr( GcStruct( "CtypesStructure_<ClassName>
-        ( "c_data"
-                Ptr( Struct( "C-Data_<ClassName>
-                             *<Fieldefintions>) ) ) ) )
+    Ptr( GcStruct( "CtypesBox_<TypeName>
+            ( "c_data"
+                    (Struct "C_Data_<TypeName>
+                            ( "value", Signed/Float/etc. ) ) ) ) )
+
+Note that we don't make "c_data" itself a Signed or Float directly because
+in LLType we can't take pointers to Signed or Float, only to Struct or
+Array.
+
+The non-owned-memory case is::
+
+    Ptr( GcStruct( "CtypesBox_<TypeName>
+            ( "c_data_ref"
+                    (Ptr(Struct "C_Data_<TypeName>
+                            ( "value", Signed/Float/etc. ) ) ) ) ) )
 
 Pointers
 ~~~~~~~~
-Pointers pointing to structures allocated by ctypes will have the following memory layout::
 
-    Ptr( GcStruct( "CtypesGCPointer_<ClassName>
-        "contents" Ptr( GcStruct( "CtypesGcStructure_<Name>" ... ) ) ) )
+::
 
+    Ptr( GcStruct( "CtypesBox_<TypeName>
+            ( "c_data"
+                    (Struct "C_Data_<TypeName>
+                            ( "value", Ptr(...) ) ) ) ) )
+
+or::
+
+    Ptr( GcStruct( "CtypesBox_<TypeName>
+            ( "c_data_ref"
+                    (Ptr(Struct "C_Data_<TypeName>
+                            ( "value", Ptr(...) ) ) ) ) ) )
+
+However, there is a special case here: the pointer might point to data
+owned by another CtypesBox -- i.e. it can point to the "c_data" field of
+some other CtypesBox.  In this case we must make sure that the other
+CtypesBox stays alive.  This is done by adding an extra field
+referencing the gc box (this field is not otherwise used)::
+
+    Ptr( GcStruct( "CtypesBox_<TypeName>
+            ( "c_data"
+                    (Struct "C_Data_<TypeName>
+                            ( "value", Ptr(...) ) ) )
+            ( "keepalive"
+                    (Ptr(GcStruct("CtypesBox_<TargetTypeName>"))) ) ) )
 
-Pointers pointing returned from external functions have the follwing layout if the
-point to a structure::
+Structures
+~~~~~~~~~~
+Structures will have the following memory layout (owning their raw memory)
+if they were allocated by ctypes::
+
+    Ptr( GcStruct( "CtypesBox_<StructName>
+            ( "c_data" 
+                    (Struct "C_Data_<StructName>
+                            *<Fieldefintions>) ) ) )
 
-    Ptr( GcStruct( "CtypesPointer_<ClassName>"
-        "contents" Ptr( Struct( "CtypesStructure_<Name>" ... ) ) ) )
+For structures obtained by dereferencing a pointer (by reading its
+"contents" attribute), the structure box does not own the memory::
 
-Currently it is not decided whether assiging a pointers `contents` attribute from
-a GC-pointer should be allowed. The other case will only become valid if we implement
-structures with mixed memory state.
+    Ptr( GcStruct( "CtypesBox_<StructName>
+            ( "c_data_ref" 
+                    (Ptr(Struct "C_Data_<StructName>
+                            *<Fieldefintions>) ) ) ) )
+
+One or several Keepalive fields might be necessary in each case.
+(To be clarified...)
+
+Arrays
+~~~~~~
+Arrays behave like structures, but use an Array instead of a Struct in
+the "c_data" or "c_data_ref" declaration.

Modified: pypy/branch/njriley-trans/pypy/doc/events.txt
==============================================================================
--- pypy/branch/njriley-trans/pypy/doc/events.txt	(original)
+++ pypy/branch/njriley-trans/pypy/doc/events.txt	Fri Mar 10 06:12:02 2006
@@ -7,26 +7,6 @@
 
 .. _`over there`: webcal://pypycal.sabi.net///calendars/PyPy.ics
 
-Talks at PyCon 2006 (Dallas, Texas, USA)
-===================================================================
-
-*Feb 24th - Feb 26th 2006.* PyPy developers will speak at `PyCon 2006`_.
-
-.. _`PyCon 2006`: http://us.pycon.org/TX2006/HomePage 
-
-PyCon Sprint 2006 (Dallas, Texas, USA)
-==================================================================
-
-*Feb 27th - March 2nd 2006.* The Post-PyCon PyPy Sprint is scheduled to
-take place right after PyCon 2006. 
-
-We hope to see lots of newcomers at this sprint, so we'll give
-friendly introductions. Note that during the Pycon conference we are
-giving PyPy talks which serve well as preparation.  Read more in the
-`announcement`_.
-
-.. _`announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/pycon06/sprint-announcement.html
-
 Logic Sprint at Louvain-la-Neuve University (Louvain-la-Neuve, Belgium)
 ========================================================================
 

Modified: pypy/branch/njriley-trans/pypy/doc/news.txt
==============================================================================
--- pypy/branch/njriley-trans/pypy/doc/news.txt	(original)
+++ pypy/branch/njriley-trans/pypy/doc/news.txt	Fri Mar 10 06:12:02 2006
@@ -7,6 +7,23 @@
 .. _Python: http://www.python.org/doc/current/ref/ref.html
 .. _`more...`: http://codespeak.net/pypy/dist/pypy/doc/architecture.html#mission-statement 
 
+PyCon Sprint 2006 (Dallas, Texas, USA)
+==================================================================
+
+*Feb 27th - March 2nd 2006.* The Post-PyCon PyPy Sprint took place
+right after PyCon 2006.
+
+A report is coming up.
+
+
+Talks at PyCon 2006 (Dallas, Texas, USA)
+===================================================================
+
+*Feb 24th - Feb 26th 2006.* PyPy developers spoke at `PyCon 2006`_.
+
+.. _`PyCon 2006`: http://us.pycon.org/TX2006/HomePage 
+
+
 PyPy at Solutions Linux in Paris January 31st - February 2nd 2006
 ===================================================================
 

Modified: pypy/branch/njriley-trans/pypy/doc/svn-help.txt
==============================================================================
--- pypy/branch/njriley-trans/pypy/doc/svn-help.txt	(original)
+++ pypy/branch/njriley-trans/pypy/doc/svn-help.txt	Fri Mar 10 06:12:02 2006
@@ -120,6 +120,9 @@
 http: in the subversion URL. This will make use of SSL encryption, which
 cannot be intercepted by proxies.
 
+Alternatively, if you want to change your proxy configuration, see the
+subversion FAQ: http://subversion.tigris.org/faq.html#proxy
+
 How to Avoid Line-ending Hell
 -----------------------------
 

Modified: pypy/branch/njriley-trans/pypy/interpreter/astcompiler/ast.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/astcompiler/ast.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/astcompiler/ast.py	Fri Mar 10 06:12:02 2006
@@ -1232,6 +1232,63 @@
                     ops=GetSetProperty(Compare.fget_ops, Compare.fset_ops ),
                     )
 
+class CondExpr(Node):
+    def __init__(self, test, true_expr, false_expr, lineno=-1):
+        Node.__init__(self, lineno)
+        self.test = test
+        self.true_expr = true_expr
+        self.false_expr = false_expr
+
+    def getChildren(self):
+        "NOT_RPYTHON"
+        return self.test, self.true_expr, self.false_expr
+
+    def getChildNodes(self):
+        return [self.test, self.true_expr, self.false_expr]
+
+    def __repr__(self):
+        return "CondExpr(%s, %s, %s)" % (self.test.__repr__(), self.true_expr.__repr__(), self.false_expr.__repr__())
+
+    def accept(self, visitor):
+        return visitor.visitCondExpr(self)
+
+    def fget_test( space, self):
+        return space.wrap(self.test)
+    def fset_test( space, self, w_arg):
+        self.test = space.interp_w(Node, w_arg, can_be_None=False)
+    def fget_true_expr( space, self):
+        return space.wrap(self.true_expr)
+    def fset_true_expr( space, self, w_arg):
+        self.true_expr = space.interp_w(Node, w_arg, can_be_None=False)
+    def fget_false_expr( space, self):
+        return space.wrap(self.false_expr)
+    def fset_false_expr( space, self, w_arg):
+        self.false_expr = space.interp_w(Node, w_arg, can_be_None=False)
+
+def descr_CondExpr_new(space, w_subtype, w_test, w_true_expr, w_false_expr, lineno=-1):
+    self = space.allocate_instance(CondExpr, w_subtype)
+    test = space.interp_w(Node, w_test, can_be_None=False)
+    self.test = test
+    true_expr = space.interp_w(Node, w_true_expr, can_be_None=False)
+    self.true_expr = true_expr
+    false_expr = space.interp_w(Node, w_false_expr, can_be_None=False)
+    self.false_expr = false_expr
+    self.lineno = lineno
+    return space.wrap(self)
+
+def descr_CondExpr_accept( space, w_self, w_visitor):
+    w_callable = space.getattr(w_visitor, space.wrap('visitCondExpr'))
+    args = Arguments(space, [ w_self ])
+    return space.call_args(w_callable, args)
+
+CondExpr.typedef = TypeDef('CondExpr', Node.typedef, 
+                     __new__ = interp2app(descr_CondExpr_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]),
+                     accept=interp2app(descr_CondExpr_accept, unwrap_spec=[ObjSpace, W_Root, W_Root] ),
+                    test=GetSetProperty(CondExpr.fget_test, CondExpr.fset_test ),
+                    true_expr=GetSetProperty(CondExpr.fget_true_expr, CondExpr.fset_true_expr ),
+                    false_expr=GetSetProperty(CondExpr.fget_false_expr, CondExpr.fset_false_expr ),
+                    )
+
 class Const(Node):
     def __init__(self, value, lineno=-1):
         Node.__init__(self, lineno)
@@ -4129,6 +4186,75 @@
                     else_=GetSetProperty(While.fget_else_, While.fset_else_ ),
                     )
 
+class With(Node):
+    def __init__(self, expr, body, var, lineno=-1):
+        Node.__init__(self, lineno)
+        self.expr = expr
+        self.body = body
+        self.var = var
+
+    def getChildren(self):
+        "NOT_RPYTHON"
+        children = []
+        children.append(self.expr)
+        children.append(self.body)
+        children.append(self.var)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        nodelist.append(self.body)
+        if self.var is not None:
+            nodelist.append(self.var)
+        return nodelist
+
+    def __repr__(self):
+        return "With(%s, %s, %s)" % (self.expr.__repr__(), self.body.__repr__(), self.var.__repr__())
+
+    def accept(self, visitor):
+        return visitor.visitWith(self)
+
+    def fget_expr( space, self):
+        return space.wrap(self.expr)
+    def fset_expr( space, self, w_arg):
+        self.expr = space.interp_w(Node, w_arg, can_be_None=False)
+    def fget_body( space, self):
+        return space.wrap(self.body)
+    def fset_body( space, self, w_arg):
+        self.body = space.interp_w(Node, w_arg, can_be_None=False)
+    def fget_var( space, self):
+        if self.var is None:
+            return space.w_None
+        else:
+            return space.wrap(self.var)
+    def fset_var( space, self, w_arg):
+        self.var = space.interp_w(Node, w_arg, can_be_None=True)
+
+def descr_With_new(space, w_subtype, w_expr, w_body, w_var, lineno=-1):
+    self = space.allocate_instance(With, w_subtype)
+    expr = space.interp_w(Node, w_expr, can_be_None=False)
+    self.expr = expr
+    body = space.interp_w(Node, w_body, can_be_None=False)
+    self.body = body
+    var = space.interp_w(Node, w_var, can_be_None=True)
+    self.var = var
+    self.lineno = lineno
+    return space.wrap(self)
+
+def descr_With_accept( space, w_self, w_visitor):
+    w_callable = space.getattr(w_visitor, space.wrap('visitWith'))
+    args = Arguments(space, [ w_self ])
+    return space.call_args(w_callable, args)
+
+With.typedef = TypeDef('With', Node.typedef, 
+                     __new__ = interp2app(descr_With_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]),
+                     accept=interp2app(descr_With_accept, unwrap_spec=[ObjSpace, W_Root, W_Root] ),
+                    expr=GetSetProperty(With.fget_expr, With.fset_expr ),
+                    body=GetSetProperty(With.fget_body, With.fset_body ),
+                    var=GetSetProperty(With.fget_var, With.fset_var ),
+                    )
+
 class Yield(Node):
     def __init__(self, value, lineno=-1):
         Node.__init__(self, lineno)
@@ -4232,6 +4358,8 @@
         return self.default( node )
     def visitCompare(self, node):
         return self.default( node )
+    def visitCondExpr(self, node):
+        return self.default( node )
     def visitConst(self, node):
         return self.default( node )
     def visitContinue(self, node):
@@ -4340,6 +4468,8 @@
         return self.default( node )
     def visitWhile(self, node):
         return self.default( node )
+    def visitWith(self, node):
+        return self.default( node )
     def visitYield(self, node):
         return self.default( node )
 

Modified: pypy/branch/njriley-trans/pypy/interpreter/astcompiler/ast.txt
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/astcompiler/ast.txt	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/astcompiler/ast.txt	Fri Mar 10 06:12:02 2006
@@ -27,6 +27,7 @@
 Break: 
 Continue: 
 For: assign, list, body, else_&
+With: expr, body, var&
 While: test, body, else_&
 If: tests!, else_&
 Exec: expr, locals&, globals&
@@ -78,6 +79,7 @@
 AbstractTest:
 Or(AbstractTest): nodes!
 And(AbstractTest): nodes!
+CondExpr: test, true_expr, false_expr
 BitOp:
 Bitor(BitOp): nodes!
 Bitxor(BitOp): nodes!

Modified: pypy/branch/njriley-trans/pypy/interpreter/astcompiler/consts.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/astcompiler/consts.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/astcompiler/consts.py	Fri Mar 10 06:12:02 2006
@@ -19,3 +19,4 @@
 CO_GENERATOR = 0x0020
 CO_GENERATOR_ALLOWED = 0x1000
 CO_FUTURE_DIVISION = 0x2000
+CO_FUTURE_WITH_STATEMENT = 0x8000

Modified: pypy/branch/njriley-trans/pypy/interpreter/astcompiler/future.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/astcompiler/future.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/astcompiler/future.py	Fri Mar 10 06:12:02 2006
@@ -15,7 +15,7 @@
 
 class FutureParser(ast.ASTVisitor):
 
-    features = ("nested_scopes", "generators", "division")
+    features = ("nested_scopes", "generators", "division", "with_statement")
 
     def __init__(self):
         self.found = {} # set

Modified: pypy/branch/njriley-trans/pypy/interpreter/astcompiler/pyassem.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/astcompiler/pyassem.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/astcompiler/pyassem.py	Fri Mar 10 06:12:02 2006
@@ -1,6 +1,5 @@
 """A flow graph representation for Python bytecode"""
 
-import dis
 import sys
 
 from pypy.interpreter.astcompiler import misc, ast
@@ -8,8 +7,7 @@
      import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS
 from pypy.interpreter.pycode import PyCode
 from pypy.interpreter.baseobjspace import W_Root
-
-
+from pypy.tool import opcode as pythonopcode
 
 class BlockSet:
     """A Set implementation specific to Blocks
@@ -633,11 +631,11 @@
         self.stage = FLAT
 
     hasjrel = {}
-    for i in dis.hasjrel:
-        hasjrel[dis.opname[i]] = True
+    for i in pythonopcode.hasjrel:
+        hasjrel[pythonopcode.opname[i]] = True
     hasjabs = {}
-    for i in dis.hasjabs:
-        hasjabs[dis.opname[i]] = True
+    for i in pythonopcode.hasjabs:
+        hasjabs[pythonopcode.opname[i]] = True
 
     def convertArgs(self):
         """Convert arguments from symbolic to concrete form"""
@@ -772,7 +770,7 @@
         index = self._lookupName(arg, self.closure)
         return InstrInt(inst.op, index)
     
-    _cmp = list(dis.cmp_op)
+    _cmp = list(pythonopcode.cmp_op)
     def _convert_COMPARE_OP(self, inst):
         assert isinstance(inst, InstrName)
         arg = inst.name                        
@@ -817,8 +815,9 @@
         self.stage = DONE
 
     opnum = {}
-    for num in range(len(dis.opname)):
-        opnum[dis.opname[num]] = num
+    for num in range(len(pythonopcode.opname)):
+        opnum[pythonopcode.opname[num]] = num
+        # This seems to duplicate dis.opmap from opcode.opmap
     del num
 
     def newCodeObject(self):
@@ -1048,6 +1047,7 @@
         'SETUP_EXCEPT': 3,
         'SETUP_FINALLY': 3,
         'FOR_ITER': 1,
+        'WITH_CLEANUP': 3,
         }
     # use pattern match
     patterns = [

Modified: pypy/branch/njriley-trans/pypy/interpreter/astcompiler/pycodegen.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/astcompiler/pycodegen.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/astcompiler/pycodegen.py	Fri Mar 10 06:12:02 2006
@@ -10,7 +10,8 @@
 from pypy.interpreter.astcompiler.consts import SC_LOCAL, SC_GLOBAL, \
     SC_FREE, SC_CELL, SC_DEFAULT, OP_APPLY, OP_ASSIGN, OP_DELETE, OP_NONE
 from pypy.interpreter.astcompiler.consts import CO_VARARGS, CO_VARKEYWORDS, \
-    CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
+    CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, \
+    CO_FUTURE_DIVISION, CO_FUTURE_WITH_STATEMENT
 from pypy.interpreter.pyparser.error import SyntaxError
 
 # drop VERSION dependency since it the ast transformer for 2.4 doesn't work with 2.3 anyway
@@ -164,6 +165,8 @@
                 self._div_op = "BINARY_TRUE_DIVIDE"
             elif feature == "generators":
                 self.graph.setFlag(CO_GENERATOR_ALLOWED)
+            elif feature == "with_statement":
+                self.graph.setFlag(CO_FUTURE_WITH_STATEMENT)
 
     def emit(self, inst ):
         return self.graph.emit( inst )
@@ -525,6 +528,76 @@
     def visitOr(self, node):
         self._visitTest(node, 'JUMP_IF_TRUE')
 
+    def visitCondExpr(self, node):
+        node.test.accept(self)
+
+        end = self.newBlock()
+        falseblock = self.newBlock()
+
+        self.emitop_block('JUMP_IF_FALSE', falseblock)
+
+        self.emit('POP_TOP')
+        node.true_expr.accept(self)
+        self.emitop_block('JUMP_FORWARD', end)
+
+        self.nextBlock(falseblock)
+        self.emit('POP_TOP')
+        node.false_expr.accept(self)
+
+        self.nextBlock(end)
+
+    __with_count = 0
+
+    def visitWith(self, node):
+        node.expr.accept(self)
+        self.emitop('LOAD_ATTR', '__context__')
+        self.emitop_int('CALL_FUNCTION', 0)
+        self.emit('DUP_TOP')
+
+        ## exit = ctx.__exit__
+        self.emitop('LOAD_ATTR', '__exit__')
+        exit = "$exit%d" % self.__with_count
+        var = "$var%d" % self.__with_count
+        self.__with_count = self.__with_count + 1
+        self._implicitNameOp('STORE', exit)
+
+        self.emitop('LOAD_ATTR', '__enter__')
+        self.emitop_int('CALL_FUNCTION', 0)
+        finally_block = self.newBlock()
+        body = self.newBlock()
+
+        self.setups.append((TRY_FINALLY, body))
+
+        if node.var is not None:        # VAR is present
+            self._implicitNameOp('STORE', var)
+            self.emitop_block('SETUP_FINALLY', finally_block)
+            self.nextBlock(body)
+            self._implicitNameOp('LOAD', var)
+            self._implicitNameOp('DELETE', var)
+            node.var.accept(self)
+        else:
+            self.emit('POP_TOP')
+            self.emitop_block('SETUP_FINALLY', finally_block)
+            self.nextBlock(body)
+
+        node.body.accept(self)
+        
+        self.emit('POP_BLOCK')
+        self.setups.pop()
+        self.emitop_obj('LOAD_CONST', self.space.w_None) # WITH_CLEANUP checks for normal exit
+        self.nextBlock(finally_block)
+        self.setups.append((END_FINALLY, finally_block))
+
+        # find local variable with is context.__exit__
+        self._implicitNameOp('LOAD', exit)
+        self._implicitNameOp('DELETE', exit)
+
+        self.emit('WITH_CLEANUP')
+        self.emitop_int('CALL_FUNCTION', 3)
+        self.emit('POP_TOP')
+        self.emit('END_FINALLY')
+        self.setups.pop()
+
     def visitCompare(self, node):
         node.expr.accept( self )
         cleanup = self.newBlock()

Modified: pypy/branch/njriley-trans/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/gateway.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/gateway.py	Fri Mar 10 06:12:02 2006
@@ -140,7 +140,7 @@
 
     def check__object(self, el, orig_sig, app_sig):
         if el not in (int, str, float):
-            assert False, "unsupported basic type in uwnrap_spec"
+            assert False, "unsupported basic type in unwrap_spec"
         name = el.__name__
         argname = orig_sig.next_arg()
         assert not argname.startswith('w_'), (

Modified: pypy/branch/njriley-trans/pypy/interpreter/pycompiler.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pycompiler.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pycompiler.py	Fri Mar 10 06:12:02 2006
@@ -78,7 +78,7 @@
 # faked compiler
 
 import warnings
-import __future__
+from pypy.tool import __future__
 compiler_flags = 0
 compiler_features = {}
 for fname in __future__.all_feature_names:

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyopcode.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyopcode.py	Fri Mar 10 06:12:02 2006
@@ -14,17 +14,7 @@
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rpython.objectmodel import we_are_translated
 from pypy.rpython.rarithmetic import intmask
-
-# load opcode.py as pythonopcode from our own lib
-def load_opcode():
-    import new, py
-    global pythonopcode
-    pythonopcode = new.module('opcode')
-    opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/2.4.1/opcode.py')
-    execfile(str(opcode_path), pythonopcode.__dict__)
-
-load_opcode()
-
+from pypy.tool import opcode as pythonopcode
 
 def unaryoperation(operationname):
     """NOT_RPYTHON"""
@@ -647,6 +637,20 @@
         block = pyframe.FinallyBlock(f, f.next_instr + offsettoend)
         f.blockstack.push(block)
 
+    def WITH_CLEANUP(f):
+        # see comment in END_FINALLY for stack state
+        w_unroller = f.valuestack.top(3)
+        unroller = f.space.interpclass_w(w_unroller)
+        if (isinstance(unroller, pyframe.SuspendedUnroller)
+            and isinstance(unroller.flowexc, pyframe.SApplicationException)):
+            f.valuestack.push(unroller.flowexc.operr.w_type)
+            f.valuestack.push(unroller.flowexc.operr.w_value)
+            f.valuestack.push(unroller.flowexc.operr.application_traceback)
+        else:
+            f.valuestack.push(f.space.w_None)
+            f.valuestack.push(f.space.w_None)
+            f.valuestack.push(f.space.w_None)
+                      
     def call_function(f, oparg, w_star=None, w_starstar=None):
         n_arguments = oparg & 0xff
         n_keywords = (oparg>>8) & 0xff

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyparser/astbuilder.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyparser/astbuilder.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyparser/astbuilder.py	Fri Mar 10 06:12:02 2006
@@ -1,15 +1,18 @@
 """This module provides the astbuilder class which is to be used
 by GrammarElements to directly build the AST during parsing
-without going trhough the nested tuples step
+without going through the nested tuples step
 """
 
 from grammar import BaseGrammarBuilder, AbstractContext
 from pypy.interpreter.astcompiler import ast, consts
-from pypy.interpreter.pyparser.pysymbol import _cpython_symbols as sym
+from pypy.interpreter.pyparser import pythonparse
 import pypy.interpreter.pyparser.pytoken as tok
 from pypy.interpreter.pyparser.error import SyntaxError
 from pypy.interpreter.pyparser.parsestring import parsestr
 
+sym      = pythonparse.PYTHON_PARSER.symbols
+sym_with = pythonparse.PYTHON_PARSER.with_grammar.symbols
+
 DEBUG_MODE = 0
 
 ### Parsing utilites #################################################
@@ -257,9 +260,9 @@
             ifs = []
         else:
             assert False, 'Unexpected token: expecting for in listcomp'
-        # 
+        #
         # Original implementation:
-        # 
+        #
         # if tokens[index].get_value() == 'for':
         #     index += 1 # skip 'for'
         #     ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN)
@@ -320,7 +323,7 @@
 
 def get_docstring(builder,stmt):
     """parses a Stmt node.
-    
+
     If a docstring if found, the Discard node is **removed**
     from <stmt> and the docstring is returned.
 
@@ -340,7 +343,7 @@
                 del stmt.nodes[0]
                 doc = expr.value
     return doc
-    
+
 
 def to_lvalue(ast_node, flags):
     lineno = ast_node.lineno
@@ -388,7 +391,7 @@
                                  lineno, 0, '')
         else:
             raise SyntaxError("can't assign to non-lvalue",
-                             lineno, 0, '') 
+                             lineno, 0, '')
 
 def is_augassign( ast_node ):
     if ( isinstance( ast_node, ast.Name ) or
@@ -410,7 +413,7 @@
         i -= 1
     atoms.reverse()
     return atoms
-    
+
 #def eval_string(value):
 #    """temporary implementation
 #
@@ -466,7 +469,7 @@
 
 def parse_attraccess(tokens):
     """parses token list like ['a', '.', 'b', '.', 'c', ...]
-    
+
     and returns an ast node : ast.Getattr(Getattr(Name('a'), 'b'), 'c' ...)
     """
     token = tokens[0]
@@ -519,7 +522,7 @@
 ## where Var and Expr are AST subtrees and Token is a not yet
 ## reduced token
 ##
-## AST_RULES is kept as a dictionnary to be rpython compliant this is the
+## ASTRULES is kept as a dictionnary to be rpython compliant this is the
 ## main reason why build_* functions are not methods of the AstBuilder class
 ##
 
@@ -579,7 +582,7 @@
         return lst[first:last]
     else:
         return []
-    
+
 
 def build_power(builder, nb):
     """power: atom trailer* ['**' factor]"""
@@ -742,7 +745,10 @@
             builder.push(TokenObject(tok.NAME, 'is not', lineno))
     else:
         assert False, "TODO" # uh ?
-        
+
+def build_or_test(builder, nb):
+    return build_binary_expr(builder, nb, ast.Or)
+
 def build_and_test(builder, nb):
     return build_binary_expr(builder, nb, ast.And)
 
@@ -756,8 +762,18 @@
         assert False, "not_test implementation incomplete in not_test"
 
 def build_test(builder, nb):
-    return build_binary_expr(builder, nb, ast.Or)
-    
+    atoms = get_atoms(builder, nb)
+    if len(atoms) == 1:
+        builder.push(atoms[0])
+    elif len(atoms) == 5:
+        builder.push(
+            ast.CondExpr(atoms[2], atoms[0], atoms[4], atoms[1].lineno))
+    else:
+        assert False, "invalid number of atoms for rule 'test'"
+
+# Note: we do not include a build_old_test() because it does not need to do
+# anything.
+
 def build_testlist(builder, nb):
     return build_binary_expr(builder, nb, ast.Tuple)
 
@@ -837,7 +853,7 @@
             stmts.extend(node.nodes)
         elif isinstance(node, TokenObject) and node.name == tok.ENDMARKER:
             # XXX Can't we just remove the last element of the list ?
-            break    
+            break
         elif isinstance(node, TokenObject) and node.name == tok.NEWLINE:
             continue
         else:
@@ -911,7 +927,6 @@
     names, defaults, flags = parse_arglist(slicecut(atoms, 1, -2))
     builder.push(ast.Lambda(names, defaults, flags, code, lineno))
 
-
 def build_trailer(builder, nb):
     """trailer: '(' ')' | '(' arglist ')' | '[' subscriptlist ']' | '.' NAME
     """
@@ -1009,7 +1024,7 @@
         else:
             builder.push(SlicelistObject('slice', sliceinfos, lineno))
 
-        
+
 def build_listmaker(builder, nb):
     """listmaker: test ( list_for | (',' test)* [','] )"""
     atoms = get_atoms(builder, nb)
@@ -1223,6 +1238,25 @@
         else_ = atoms[6]
     builder.push(ast.While(test, body, else_, atoms[0].lineno))
 
+def build_with_stmt(builder, nb):
+    """with_stmt: 'with' test [ NAME expr ] ':' suite"""
+
+    atoms = get_atoms(builder, nb)
+    # skip 'with'
+    test =  atoms[1]
+    if len(atoms) == 4:
+        body = atoms[3]
+        var = None
+    # if there is an "as" clause
+    else:
+        token = atoms[2]
+        assert isinstance(token, TokenObject)
+        if token.get_value() != 'as':
+            raise SyntaxError("invalid syntax", token.lineno, token.col)
+        varexpr = atoms[3]
+        var = to_lvalue(varexpr, consts.OP_ASSIGN)
+        body = atoms[5]
+    builder.push(ast.With(test, body, var, atoms[0].lineno))
 
 def build_import_name(builder, nb):
     """import_name: 'import' dotted_as_names
@@ -1311,6 +1345,12 @@
             names.append((name, as_name))
             if index < l: # case ','
                 index += 1
+    if from_name == '__future__':
+        for name, asname in names:
+            if name == 'with_statement':
+                # found from __future__ import with_statement
+                if not builder.with_enabled:
+                    raise pythonparse.AlternateGrammarException()
     builder.push(ast.From(from_name, names, atoms[0].lineno))
 
 
@@ -1325,7 +1365,7 @@
 def build_del_stmt(builder, nb):
     atoms = get_atoms(builder, nb)
     builder.push(to_lvalue(atoms[1], consts.OP_DELETE))
-        
+
 
 def build_assert_stmt(builder, nb):
     """assert_stmt: 'assert' test [',' test]"""
@@ -1404,7 +1444,7 @@
                ['else' ':' suite] | 'try' ':' suite 'finally' ':' suite)
     # NB compile.c makes sure that the default except clause is last
     except_clause: 'except' [test [',' test]]
-   
+
     """
     atoms = get_atoms(builder, nb)
     l = len(atoms)
@@ -1433,59 +1473,69 @@
             else_ = atoms[index+2] # skip ':'
         builder.push(ast.TryExcept(body, handlers, else_, atoms[0].lineno))
 
-
-ASTRULES = {
-    sym['atom'] : build_atom,
-    sym['power'] : build_power,
-    sym['factor'] : build_factor,
-    sym['term'] : build_term,
-    sym['arith_expr'] : build_arith_expr,
-    sym['shift_expr'] : build_shift_expr,
-    sym['and_expr'] : build_and_expr,
-    sym['xor_expr'] : build_xor_expr,
-    sym['expr'] : build_expr,
-    sym['comparison'] : build_comparison,
-    sym['comp_op'] : build_comp_op,
-    sym['and_test'] : build_and_test,
-    sym['not_test'] : build_not_test,
-    sym['test'] : build_test,
-    sym['testlist'] : build_testlist,
-    sym['expr_stmt'] : build_expr_stmt,
-    sym['small_stmt'] : return_one,
-    sym['simple_stmt'] : build_simple_stmt,
-    sym['single_input'] : build_single_input,
-    sym['file_input'] : build_file_input,
-    sym['testlist_gexp'] : build_testlist_gexp,
-    sym['lambdef'] : build_lambdef,
-    sym['trailer'] : build_trailer,
-    sym['arglist'] : build_arglist,
-    sym['subscript'] : build_subscript,
-    sym['listmaker'] : build_listmaker,
-    sym['funcdef'] : build_funcdef,
-    sym['classdef'] : build_classdef,
-    sym['return_stmt'] : build_return_stmt,
-    sym['suite'] : build_suite,
-    sym['if_stmt'] : build_if_stmt,
-    sym['pass_stmt'] : build_pass_stmt,
-    sym['break_stmt'] : build_break_stmt,
-    sym['for_stmt'] : build_for_stmt,
-    sym['while_stmt'] : build_while_stmt,
-    sym['import_name'] : build_import_name,
-    sym['import_from'] : build_import_from,
-    sym['yield_stmt'] : build_yield_stmt,
-    sym['continue_stmt'] : build_continue_stmt,
-    sym['del_stmt'] : build_del_stmt,
-    sym['assert_stmt'] : build_assert_stmt,
-    sym['exec_stmt'] : build_exec_stmt,
-    sym['print_stmt'] : build_print_stmt,
-    sym['global_stmt'] : build_global_stmt,
-    sym['raise_stmt'] : build_raise_stmt,
-    sym['try_stmt'] : build_try_stmt,
-    sym['exprlist'] : build_exprlist,
-    sym['decorator'] : build_decorator,
-    sym['eval_input'] : build_eval_input,
+ASTRULES_Template = {
+    'atom' : build_atom,
+    'power' : build_power,
+    'factor' : build_factor,
+    'term' : build_term,
+    'arith_expr' : build_arith_expr,
+    'shift_expr' : build_shift_expr,
+    'and_expr' : build_and_expr,
+    'xor_expr' : build_xor_expr,
+    'expr' : build_expr,
+    'comparison' : build_comparison,
+    'comp_op' : build_comp_op,
+    'or_test' : build_or_test,
+    'and_test' : build_and_test,
+    'not_test' : build_not_test,
+    'test' : build_test,
+    'testlist' : build_testlist,
+    'expr_stmt' : build_expr_stmt,
+    'small_stmt' : return_one,
+    'simple_stmt' : build_simple_stmt,
+    'single_input' : build_single_input,
+    'file_input' : build_file_input,
+    'testlist_gexp' : build_testlist_gexp,
+    'lambdef' : build_lambdef,
+    'old_lambdef' : build_lambdef,
+    'trailer' : build_trailer,
+    'arglist' : build_arglist,
+    'subscript' : build_subscript,
+    'listmaker' : build_listmaker,
+    'funcdef' : build_funcdef,
+    'classdef' : build_classdef,
+    'return_stmt' : build_return_stmt,
+    'suite' : build_suite,
+    'if_stmt' : build_if_stmt,
+    'pass_stmt' : build_pass_stmt,
+    'break_stmt' : build_break_stmt,
+    'for_stmt' : build_for_stmt,
+    'while_stmt' : build_while_stmt,
+    'import_name' : build_import_name,
+    'import_from' : build_import_from,
+    'yield_stmt' : build_yield_stmt,
+    'continue_stmt' : build_continue_stmt,
+    'del_stmt' : build_del_stmt,
+    'assert_stmt' : build_assert_stmt,
+    'exec_stmt' : build_exec_stmt,
+    'print_stmt' : build_print_stmt,
+    'global_stmt' : build_global_stmt,
+    'raise_stmt' : build_raise_stmt,
+    'try_stmt' : build_try_stmt,
+    'exprlist' : build_exprlist,
+    'decorator' : build_decorator,
+    'eval_input' : build_eval_input,
     }
 
+# Build two almost identical ASTRULES dictionaries
+ASTRULES      = dict([(sym[key], value) for (key, value) in
+                      ASTRULES_Template.iteritems()])
+
+ASTRULES_Template['with_stmt'] = build_with_stmt
+ASTRULES_with = dict([(sym_with[key], value) for (key, value) in
+                      (ASTRULES_Template).iteritems()])
+del ASTRULES_Template
+
 ## Stack elements definitions ###################################
 
 class BaseRuleObject(ast.Node):
@@ -1494,8 +1544,8 @@
         self.count = count
         self.lineno = lineno # src.getline()
         self.col = 0  # src.getcol()
-        
-    
+
+
 class RuleObject(BaseRuleObject):
     """A simple object used to wrap a rule or token"""
     def __init__(self, name, count, lineno):
@@ -1511,18 +1561,18 @@
 
 class TempRuleObject(BaseRuleObject):
     """used to keep track of how many items get_atom() should pop"""
-    
+
     def __init__(self, name, count, lineno):
         BaseRuleObject.__init__(self, count, lineno)
         self.temp_rulename = name
-        
+
     def __str__(self):
         return "<Rule: %s/%d>" % (self.temp_rulename, self.count)
 
     def __repr__(self):
         return "<Rule: %s/%d>" % (self.temp_rulename, self.count)
 
-    
+
 class TokenObject(ast.Node):
     """A simple object used to wrap a rule or token"""
     def __init__(self, name, value, lineno):
@@ -1532,7 +1582,7 @@
         # self.line = 0 # src.getline()
         self.col = 0  # src.getcol()
         self.lineno = lineno
-        
+
     def get_name(self):
         return tok.tok_rpunct.get(self.name,
                                   tok.tok_name.get(self.name, str(self.name)))
@@ -1542,10 +1592,10 @@
         if value is None:
             value = ''
         return value
-    
+
     def __str__(self):
         return "<Token: (%s,%s)>" % (self.get_name(), self.value)
-    
+
     def __repr__(self):
         return "<Token: (%r,%s)>" % (self.get_name(), self.value)
 
@@ -1568,13 +1618,13 @@
 
     def __str__(self):
         return "<ArgList: (%s, %s, %s)>" % self.value
-    
+
     def __repr__(self):
         return "<ArgList: (%s, %s, %s)>" % self.value
-    
+
 class SubscriptObject(ObjectAccessor):
     """helper class to build subscript list
-    
+
     self.value represents the __getitem__ argument
     """
     def __init__(self, name, value, lineno):
@@ -1584,7 +1634,7 @@
 
     def __str__(self):
         return "<SubscriptList: (%s)>" % self.value
-    
+
     def __repr__(self):
         return "<SubscriptList: (%s)>" % self.value
 
@@ -1603,10 +1653,10 @@
 
     def __str__(self):
         return "<SliceList: (%s)>" % self.value
-    
+
     def __repr__(self):
         return "<SliceList: (%s)>" % self.value
-    
+
 
 class AstBuilderContext(AbstractContext):
     """specific context management for AstBuidler"""
@@ -1622,7 +1672,13 @@
         self.rule_stack = []
         self.space = space
         self.source_encoding = None
-        
+        self.ASTRULES = ASTRULES
+        self.with_enabled = False
+
+    def enable_with(self):
+        self.ASTRULES = ASTRULES_with
+        self.with_enabled = True
+
     def context(self):
         return AstBuilderContext(self.rule_stack)
 
@@ -1661,7 +1717,7 @@
         if rule.is_root():
 ##             if DEBUG_MODE:
 ##                 print "ALT:", sym.sym_name[rule.codename], self.rule_stack
-            builder_func = ASTRULES.get(rule.codename, None)
+            builder_func = self.ASTRULES.get(rule.codename, None)
             if builder_func:
                 builder_func(self, 1)
             else:
@@ -1682,7 +1738,7 @@
         if rule.is_root():
 ##             if DEBUG_MODE:
 ##                 print "SEQ:", sym.sym_name[rule.codename]
-            builder_func = ASTRULES.get(rule.codename, None)
+            builder_func = self.ASTRULES.get(rule.codename, None)
             if builder_func:
                 # print "REDUCING SEQUENCE %s" % sym.sym_name[rule.codename]
                 builder_func(self, elts_number)
@@ -1718,12 +1774,12 @@
             l = space.builtin.get('long')
             return space.call_function(l, space.wrap(value), space.wrap(base))
         if value.endswith('j') or value.endswith('J'):
-            c = space.builtin.get('complex') 
+            c = space.builtin.get('complex')
             return space.call_function(c, space.wrap(value))
         try:
             i = space.builtin.get('int')
             return space.call_function(i, space.wrap(value), space.wrap(base))
-        except: 
+        except:
             f = space.builtin.get('float')
             return space.call_function(f, space.wrap(value))
 
@@ -1760,4 +1816,4 @@
         else:
             obj2 = "-"
         print "% 3d | %30s | %30s" % (i, obj1, obj2)
-    
+

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyparser/ebnfparse.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyparser/ebnfparse.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyparser/ebnfparse.py	Fri Mar 10 06:12:02 2006
@@ -260,7 +260,7 @@
 
 from pprint import pprint
 if __name__ == "__main__":
-    grambuild = parse_grammar(file('data/Grammar2.3'))
+    grambuild = parse_grammar(file('data/Grammar2.5a'))
     for i,r in enumerate(grambuild.items):
         print "%  3d : %s" % (i, r)
     pprint(grambuild.terminals.keys())

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyparser/pysymbol.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyparser/pysymbol.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyparser/pysymbol.py	Fri Mar 10 06:12:02 2006
@@ -1,9 +1,4 @@
-# replacement for the CPython symbol module
-try:
-    from pypy.interpreter.pyparser import symbol
-except ImportError:
-    # for standalone testing
-    import symbol
+from pypy.interpreter.pyparser import symbol
 
 # try to avoid numeric values conflict with tokens
 # it's important for CPython, but I'm not so sure it's still
@@ -54,19 +49,45 @@
 
 _cpython_symbols = SymbolMapper( symbol.sym_name )
 
-
-# prepopulate symbol table from symbols used by CPython
-for _value, _name in _cpython_symbols.sym_name.items():
-    globals()[_name] = _value
-
-    
-
-def update_symbols( parser ):
-    """Update the symbol module according to rules
-    in PythonParser instance : parser"""
-    for rule in parser.rules:
-        _cpython_symbols.add_symbol( rule )
-
 # There is no symbol in this module until the grammar is loaded
 # once loaded the grammar parser will fill the mappings with the
 # grammar symbols
+
+def gen_symbol_file(fname):
+    """
+    Generate a compatible symbol file for symbol.py, using the grammar that has
+    been generated from the grammar in the PyPy parser.  (Note that we assume
+    that the parser generates the tokens deterministically.)
+    """
+
+    import ebnfparse
+    gram = ebnfparse.parse_grammar( file(fname) )
+
+    import os.path
+    f = open(os.path.join(os.path.dirname(__file__), 'symbol.py'), 'w')
+    print >> f, """
+#  This file is automatically generated; please don't muck it up!
+#
+#  To update the symbols in this file, call this function from python_grammar()
+#  and call PyPy.
+"""
+    for k, v in gram.symbols.sym_name.iteritems():
+        if k >= 0:
+            print >> f, '%s = %s' % (v, k)
+
+    print >> f, """
+
+# Generate sym_name
+sym_name = {}
+for _name, _value in globals().items():
+    if type(_value) is type(0):
+        sym_name[_value] = _name
+"""
+    f.close()
+    
+if __name__ == '__main__':
+    import sys
+    if len(sys.argv) != 2:
+        print 'Call pysymbol with the filename of the python grammar'
+        sys.exit(0)
+    gen_symbol_file(sys.argv[1])

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyparser/pythonparse.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyparser/pythonparse.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyparser/pythonparse.py	Fri Mar 10 06:12:02 2006
@@ -10,6 +10,7 @@
 from pypy.interpreter.pyparser.error import SyntaxError
 from pypy.tool.option import Options
 from pythonlexer import Source, match_encoding_declaration
+from pypy.interpreter.astcompiler.consts import CO_FUTURE_WITH_STATEMENT
 import pysymbol
 import ebnfparse
 import sys
@@ -18,6 +19,9 @@
 
 from codeop import PyCF_DONT_IMPLY_DEDENT
 
+class AlternateGrammarException(Exception):
+    pass
+
 class PythonParser(object):
     """Wrapper class for python grammar"""
     def __init__(self, grammar_builder):
@@ -25,6 +29,8 @@
         self.rules = grammar_builder.rules
         # Build first sets for each rule (including anonymous ones)
         grammar.build_first_sets(self.items)
+        self.symbols = grammar_builder.symbols
+        self.with_grammar = None
 
     def parse_source(self, textsrc, goal, builder, flags=0):
         """Parse a python source according to goal"""
@@ -44,19 +50,30 @@
             flags &= ~PyCF_DONT_IMPLY_DEDENT
         return self.parse_lines(lines, goal, builder, flags)
 
+
     def parse_lines(self, lines, goal, builder, flags=0):
-        goalnumber = pysymbol._cpython_symbols.sym_values[goal]
+        if (self.with_grammar is not None and # don't recurse into ourself
+            flags & CO_FUTURE_WITH_STATEMENT):
+            builder.enable_with()
+            return self.with_grammar.parse_lines(lines, goal, builder, flags)
+        goalnumber = self.symbols.sym_values[goal]
         target = self.rules[goalnumber]
         src = Source(lines, flags)
-    
-        result = target.match(src, builder)
+        
+        result = None
+        try:
+            result = target.match(src, builder)
+        except AlternateGrammarException: # handle from __future__ import with_statement
+            if self.with_grammar is not None:
+                builder.enable_with()
+                return self.with_grammar.parse_lines(lines, goal, builder, flags)
         if not result:
             line, lineno = src.debug()
             # XXX needs better error messages
             raise SyntaxError("invalid syntax", lineno, -1, line)
             # return None
         return builder
-    
+
 _recode_to_utf8 = gateway.applevel(r'''
     def _recode_to_utf8(text, encoding):
         return unicode(text, encoding).encode("utf-8")
@@ -96,7 +113,7 @@
     if eol2 < 0:
         return _check_line_for_encoding(s[eol + 1:])
     return _check_line_for_encoding(s[eol + 1:eol2])
-    
+
 def _check_line_for_encoding(line):
     """returns the declared encoding or None"""
     i = 0
@@ -112,7 +129,9 @@
     """returns the python grammar corresponding to our CPython version"""
     if version == "native":
         _ver = PYTHON_VERSION
-    elif version in ("2.3","2.4"):
+    elif version == "stable":
+        _ver = "_stablecompiler"
+    elif version in ("2.3","2.4","2.5a"):
         _ver = version
     return os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ), _ver
 
@@ -130,6 +149,7 @@
 
 debug_print( "Loading grammar %s" % PYTHON_GRAMMAR )
 PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR )
+PYTHON_PARSER.with_grammar = python_grammar( PYTHON_GRAMMAR + '_with' )
 
 def reload_grammar(version):
     """helper function to test with pypy different grammars"""
@@ -141,7 +161,7 @@
 def parse_file_input(pyf, gram, builder ):
     """Parse a python file"""
     return gram.parse_source( pyf.read(), "file_input", builder )
-    
+
 def parse_single_input(textsrc, gram, builder ):
     """Parse a python single statement"""
     return gram.parse_source( textsrc, "single_input", builder )
@@ -152,9 +172,12 @@
 
 
 def grammar_rules( space ):
-    return space.wrap( PYTHON_PARSER.rules )
+    w_rules = space.newdict([])
+    for key, value in PYTHON_PARSER.rules.iteritems():
+        space.setitem(w_rules, space.wrap(key), space.wrap(value))
+    return w_rules
 
 
 def make_rule( space, w_rule ):
     rule = space.str_w( w_rule )
-    
+

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyparser/pythonutil.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyparser/pythonutil.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyparser/pythonutil.py	Fri Mar 10 06:12:02 2006
@@ -5,7 +5,6 @@
 import pythonparse
 from tuplebuilder import TupleBuilder
 from astbuilder import AstBuilder
-from pypy.interpreter.pyparser import pysymbol
 
 PYTHON_PARSER = pythonparse.PYTHON_PARSER
 TARGET_DICT = {
@@ -50,7 +49,8 @@
     pyf.close()
     return pypy_parse(source, 'exec', lineno)
 
-def internal_pypy_parse(source, mode='exec', lineno=False, flags=0, space=None):
+def internal_pypy_parse(source, mode='exec', lineno=False, flags=0, space=None,
+                        parser = PYTHON_PARSER):
     """This function has no other role than testing the parser's annotation
 
     annotateme() is basically the same code that pypy_parse(), but with the
@@ -60,11 +60,11 @@
        tuples (StackElement is only a wrapper class around these tuples)
 
     """
-    builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False)
+    builder = TupleBuilder(parser.rules, lineno=False)
     if space is not None:
         builder.space = space
     target_rule = TARGET_DICT[mode]
-    PYTHON_PARSER.parse_source(source, target_rule, builder, flags)
+    parser.parse_source(source, target_rule, builder, flags)
     stack_element = builder.stack[-1]
     return (builder.source_encoding, stack_element)
 
@@ -72,12 +72,9 @@
     """NOT_RPYTHON"""
     source_encoding, stack_element = parse_result
     nested_tuples = stack_element.as_tuple(lineno)
-    if source_encoding is not None:
-        return (pysymbol.encoding_decl, nested_tuples, source_encoding)
-    else:
-        return nested_tuples
+    return nested_tuples
 
-def pypy_parse(source, mode='exec', lineno=False, flags=0):
+def pypy_parse(source, mode='exec', lineno=False, flags=0, parser = PYTHON_PARSER):
     """
     NOT_RPYTHON !
     parse <source> using PyPy's parser module and return
@@ -90,13 +87,14 @@
      - The encoding string or None if there were no encoding statement
     nested tuples
     """
-    source_encoding, stack_element = internal_pypy_parse(source, mode, lineno=lineno, flags=lineno)
+    source_encoding, stack_element = internal_pypy_parse(source, mode, lineno=lineno,
+                                                         flags=lineno, parser = parser)
     # convert the stack element into nested tuples (caution, the annotator
     # can't follow this call)
     return parse_result_to_nested_tuples((source_encoding, stack_element), lineno=lineno)
 
 ## convenience functions for computing AST objects using recparser
-def ast_from_input(input, mode, transformer):
+def ast_from_input(input, mode, transformer, parser = PYTHON_PARSER):
     """converts a source input into an AST
 
      - input : the source to be converted
@@ -107,7 +105,7 @@
           here to explicitly import compiler or stablecompiler or
           etc. This is to be fixed in a clean way
     """
-    tuples = pypy_parse(input, mode, True)
+    tuples = pypy_parse(input, mode, True, parser)
     ast = transformer.compile_node(tuples)
     return ast
 

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyparser/symbol.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyparser/symbol.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyparser/symbol.py	Fri Mar 10 06:12:02 2006
@@ -1,15 +1,9 @@
-#! /usr/bin/env python
-
-"""Non-terminal symbols of Python grammar (from "graminit.h")."""
 
 #  This file is automatically generated; please don't muck it up!
 #
-#  To update the symbols in this file, 'cd' to the top directory of
-#  the python source tree after building the interpreter and run:
-#
-#    python Lib/symbol.py
+#  To update the symbols in this file, call this function from python_grammar()
+#  and call PyPy.
 
-#--start constants--
 single_input = 256
 file_input = 257
 eval_input = 258
@@ -88,20 +82,14 @@
 gen_if = 331
 testlist1 = 332
 encoding_decl = 333
-#--end constants--
+old_test = 334
+or_test = 335
+old_lambdef = 336
+
 
+# Generate sym_name
 sym_name = {}
 for _name, _value in globals().items():
     if type(_value) is type(0):
         sym_name[_value] = _name
 
-
-def main():
-    import sys
-    import token
-    if len(sys.argv) == 1:
-        sys.argv = sys.argv + ["Include/graminit.h", "Lib/symbol.py"]
-    token.main()
-
-if __name__ == "__main__":
-    main()

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_astbuilder.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_astbuilder.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_astbuilder.py	Fri Mar 10 06:12:02 2006
@@ -1,6 +1,6 @@
 import os
 
-from pypy.interpreter.pyparser.pythonparse import PYTHON_PARSER
+from pypy.interpreter.pyparser import pythonparse
 from pypy.interpreter.pyparser.astbuilder import AstBuilder
 from pypy.interpreter.pyparser.pythonutil import ast_from_input
 from pypy.interpreter.stablecompiler.transformer import Transformer
@@ -206,8 +206,22 @@
     "[a, (b,c), d] = e",
     "a, (b, c), d = e",
     ]
-EXPECTED["k[v,]"] = "Module(None, Stmt([Discard(Subscript(Name('k'), 2, Tuple([Name('v')])))]))"
-EXPECTED["m[a,b]"] = "Module(None, Stmt([Discard(Subscript(Name('m'), 2, Tuple([Name('a'), Name('b')])))]))"
+
+# We do not export the following tests because we would have to implement 2.5
+# features in the stable compiler (other than just building the AST).
+expressions_inbetweenversions = expressions + [
+    "1 if True else 2",
+    "1 if False else 2",
+    ]
+
+EXPECTED["k[v,]"] = ("Module(None, Stmt([Discard(Subscript(Name('k'), 2, "
+                     "Tuple([Name('v')])))]))")
+EXPECTED["m[a,b]"] = ("Module(None, Stmt([Discard(Subscript(Name('m'), 2, "
+                      "Tuple([Name('a'), Name('b')])))]))")
+EXPECTED["1 if True else 2"] = ("Module(None, Stmt([Discard(CondExpr("
+                                "Name('True'), Const(1), Const(2)))]))")
+EXPECTED["1 if False else 2"] = ("Module(None, Stmt([Discard(CondExpr("
+                                 "Name('False'), Const(1), Const(2)))]))")
 
 funccalls = [
     "l = func()",
@@ -601,7 +615,7 @@
 
 TESTS = [
     constants,
-    expressions,
+    expressions_inbetweenversions,
     augassigns,
     comparisons,
     funccalls,
@@ -690,12 +704,16 @@
 def ast_parse_expr(expr, target='single'):
     target = TARGET_DICT[target]
     builder = AstBuilder(space=FakeSpace())
-    PYTHON_PARSER.parse_source(expr, target, builder)
+    pythonparse.PYTHON_PARSER.parse_source(expr, target, builder)
     return builder
 
+# Create parser from Grammar_stable, not current grammar.
+stable_grammar, _ = pythonparse.get_grammar_file("stable")
+stable_parser = pythonparse.python_grammar(stable_grammar)
+
 def tuple_parse_expr(expr, target='single'):
     t = Transformer("dummyfile")
-    return ast_from_input(expr, target, t)
+    return ast_from_input(expr, target, t, stable_parser)
 
 def check_expression(expr, target='single'):
     r1 = ast_parse_expr(expr, target)
@@ -727,6 +745,11 @@
         for expr in family:
             yield check_expression, expr, 'exec'
 
+NEW_GRAMMAR_SNIPPETS = [    
+    'snippet_with_1.py',
+    'snippet_with_2.py',
+    ]
+
 SNIPPETS = [    
     'snippet_1.py',
     'snippet_several_statements.py',
@@ -769,9 +792,14 @@
     ]
 
 def test_snippets():
-    for snippet_name in SNIPPETS:
+    for snippet_name in SNIPPETS + NEW_GRAMMAR_SNIPPETS:
         filepath = os.path.join(os.path.dirname(__file__), 'samples', snippet_name)
         source = file(filepath).read()
+        # To avoid using the stable compiler we pull an explicit AST out of the snippet
+        if source.startswith('# EXPECT:'):
+            firstline,_ = source.split('\n', 1)
+            firstline = firstline[len('# EXPECT:'):].strip()
+            EXPECTED[source] = firstline
         yield check_expression, source, 'exec'
 
 def test_libstuff():

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_astcompiler.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_astcompiler.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_astcompiler.py	Fri Mar 10 06:12:02 2006
@@ -1,5 +1,5 @@
 import os
-from pypy.interpreter.pyparser.pythonparse import PYTHON_PARSER
+from pypy.interpreter.pyparser import pythonparse
 from pypy.interpreter.pyparser.astbuilder import AstBuilder
 from pypy.interpreter.pyparser.tuplebuilder import TupleBuilder
 from pypy.interpreter.pycode import PyCode
@@ -63,7 +63,7 @@
 def ast_parse_expr(expr, target='single', space=FakeSpace()):
     target = TARGET_DICT[target]
     builder = AstBuilder(space=space)
-    PYTHON_PARSER.parse_source(expr, target, builder)
+    pythonparse.PYTHON_PARSER.parse_source(expr, target, builder)
     return builder.rule_stack[-1]
 
 
@@ -80,10 +80,15 @@
     rcode = codegen.getCode()
     return rcode
 
+
+# Create parser from Grammar_stable, not current grammar.
+stable_grammar, _ = pythonparse.get_grammar_file("stable")
+stable_parser = pythonparse.python_grammar(stable_grammar)
+
 def compile_with_testcompiler(expr, target='exec', space=FakeSpace()):
     target2 = TARGET_DICT['exec'] # xxx exec: single not really tested
     builder = TupleBuilder()
-    PYTHON_PARSER.parse_source(expr, target2, builder)
+    stable_parser.parse_source(expr, target2, builder)
     tuples =  builder.stack[-1].as_tuple(True)
     from pypy.interpreter.stablecompiler import transformer, pycodegen, misc
     ast = transformer.Transformer('<?>').compile_node(tuples)

Modified: pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_samples.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_samples.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/pyparser/test/test_samples.py	Fri Mar 10 06:12:02 2006
@@ -21,6 +21,10 @@
     #"snippet_import_statements.py",
     "snippet_decorators.py",
 ]
+SKIP_ALWAYS = [
+    "snippet_with_1.py",
+    "snippet_with_2.py",
+]
 REAL_EXPECTED_OUTPUT = {
     # for snippets that show bugs of Python's compiler package
     "snippet_transformer_bug.py":
@@ -73,6 +77,8 @@
         for fname in os.listdir(samples_dir):
             if not fname.endswith('.py'):
                 continue
+            if fname in SKIP_ALWAYS:
+                continue
             if GRAMMAR_MISMATCH and fname in SKIP_IF_NOT_NATIVE:
                 print "Skipping", fname
                 continue

Modified: pypy/branch/njriley-trans/pypy/interpreter/stablecompiler/transformer.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/stablecompiler/transformer.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/stablecompiler/transformer.py	Fri Mar 10 06:12:02 2006
@@ -26,14 +26,26 @@
 # and replace OWNER, ORGANIZATION, and YEAR as appropriate.
 
 # make sure we import the parser with the correct grammar
-import pypy.interpreter.pyparser.pythonparse
+from pypy.interpreter.pyparser import pythonparse
+
+import pypy.interpreter.pyparser.pythonparse as pythonparse
+
 from pypy.interpreter.stablecompiler.ast import *
 import parser
-import pypy.interpreter.pyparser.pysymbol as symbol
 import pypy.interpreter.pyparser.pytoken as token
 import sys
 
-sym_name = symbol._cpython_symbols.sym_name
+# Create parser from Grammar_stable, not current grammar.
+stable_grammar, _ = pythonparse.get_grammar_file("stable")
+stable_parser = pythonparse.python_grammar(stable_grammar)
+
+sym_name = stable_parser.symbols.sym_name
+
+class symbol:
+    pass
+
+for value, name in sym_name.iteritems():
+    setattr(symbol, name, value)
 
 # transforming is requiring a lot of recursion depth so make sure we have enough
 if sys.getrecursionlimit()<5000:
@@ -308,9 +320,12 @@
 
         return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
 
+    # (This is like lambdef but it uses the old_test instead.)
+    # old_lambdef: 'lambda' [varargslist] ':' old_test
+    old_lambdef = lambdef
+
     def classdef(self, nodelist):
         # classdef: 'class' NAME ['(' testlist ')'] ':' suite
-
         name = nodelist[1][1]
         doc = self.get_docstring(nodelist[-1])
         if nodelist[2][0] == token.COLON:
@@ -579,7 +594,7 @@
 
     def testlist(self, nodelist):
         # testlist: expr (',' expr)* [',']
-        # testlist_safe: test [(',' test)+ [',']]
+        # testlist_safe: old_test [(',' old_test)+ [',']]
         # exprlist: expr (',' expr)* [',']
         return self.com_binary(Tuple, nodelist)
 
@@ -594,15 +609,33 @@
         return self.testlist(nodelist)
 
     def test(self, nodelist):
-        # and_test ('or' and_test)* | lambdef
-        if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
-            return self.lambdef(nodelist[0])
-        return self.com_binary(Or, nodelist)
+        # test: or_test ['if' or_test 'else' test] | lambdef
+        if len(nodelist) == 1:
+            if nodelist[0][0] == symbol.lambdef:
+                return self.lambdef(nodelist[0])
+            else:
+                # Normal or-expression
+                return self.com_node(nodelist[0])
+        else:
+            # Here we implement conditional expressions
+            return ast.CondExpr(nodelist[2], nodelist[0], nodelist[4],
+                                nodelist[1].lineno)
 
     def and_test(self, nodelist):
         # not_test ('and' not_test)*
         return self.com_binary(And, nodelist)
 
+    def old_test(self, nodelist):
+        # old_test: or_test | old_lambdef
+        if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
+            return self.lambdef(nodelist[0])
+        assert len(nodelist) == 1
+        return self.com_node(nodelist[0])
+
+    def or_test(self, nodelist):
+        # or_test: and_test ('or' and_test)*
+        return self.com_binary(Or, nodelist)
+
     def not_test(self, nodelist):
         # 'not' not_test | comparison
         result = self.com_node(nodelist[-1])
@@ -1396,6 +1429,8 @@
     symbol.testlist,
     symbol.testlist_safe,
     symbol.test,
+    symbol.old_test,
+    symbol.or_test,
     symbol.and_test,
     symbol.not_test,
     symbol.comparison,
@@ -1421,54 +1456,10 @@
     token.NOTEQUAL : '!=',
     }
 
-_legal_node_types = [
-    symbol.funcdef,
-    symbol.classdef,
-    symbol.stmt,
-    symbol.small_stmt,
-    symbol.flow_stmt,
-    symbol.simple_stmt,
-    symbol.compound_stmt,
-    symbol.expr_stmt,
-    symbol.print_stmt,
-    symbol.del_stmt,
-    symbol.pass_stmt,
-    symbol.break_stmt,
-    symbol.continue_stmt,
-    symbol.return_stmt,
-    symbol.raise_stmt,
-    symbol.import_stmt,
-    symbol.global_stmt,
-    symbol.exec_stmt,
-    symbol.assert_stmt,
-    symbol.if_stmt,
-    symbol.while_stmt,
-    symbol.for_stmt,
-    symbol.try_stmt,
-    symbol.suite,
-    symbol.testlist,
-    symbol.testlist_safe,
-    symbol.test,
-    symbol.and_test,
-    symbol.not_test,
-    symbol.comparison,
-    symbol.exprlist,
-    symbol.expr,
-    symbol.xor_expr,
-    symbol.and_expr,
-    symbol.shift_expr,
-    symbol.arith_expr,
-    symbol.term,
-    symbol.factor,
-    symbol.power,
-    symbol.atom,
-    ]
-
-if hasattr(symbol, 'yield_stmt'):
-    _legal_node_types.append(symbol.yield_stmt)
-
 _assign_types = [
     symbol.test,
+    symbol.old_test,
+    symbol.or_test,
     symbol.and_test,
     symbol.not_test,
     symbol.comparison,

Modified: pypy/branch/njriley-trans/pypy/interpreter/test/test_syntax.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/interpreter/test/test_syntax.py	(original)
+++ pypy/branch/njriley-trans/pypy/interpreter/test/test_syntax.py	Fri Mar 10 06:12:02 2006
@@ -248,6 +248,271 @@
         raise
 
 
+class AppTestCondExpr:
+
+    def test_condexpr(self):
+        for s, expected in [("x = 1 if True else 2", 1),
+                            ("x = 1 if False else 2", 2)]:
+            exec s
+            assert x == expected
+
+class AppTestWith:
+    def test_with_1(self):
+
+        s = """from __future__ import with_statement
+if 1:        
+        class ContextFactory:
+
+            class Context:
+                def __init__(self, factory):
+                    self.factory = factory
+
+                def __enter__(self):
+                    self.factory.calls.append('__enter__')
+                    pass
+
+                def __exit__(self, exc_type, exc_value, exc_tb):
+                    self.factory.calls.append('__exit__')
+                    pass
+
+            def __init__(self):
+                self.calls = list()
+                self.context = self.Context(self)
+
+            def __context__(self):
+                self.calls.append('__context__')
+                return self.context
+            
+        acontext = ContextFactory()
+        with acontext:
+            pass
+        """
+        exec s
+
+        assert acontext.calls == '__context__ __enter__ __exit__'.split()
+        
+    def test_with_2(self):
+
+        s = """from __future__ import with_statement
+if 1:
+        class ContextFactory:
+
+            class Context:
+                def __init__(self, factory):
+                    self.factory = factory
+
+                def __enter__(self):
+                    self.factory.calls.append('__enter__')
+                    return self.factory.calls
+
+                def __exit__(self, exc_type, exc_value, exc_tb):
+                    self.factory.calls.append('__exit__')
+                    self.factory.exit_params = (exc_type, exc_value, exc_tb)
+
+            def __init__(self):
+                self.calls = list()
+                self.context = self.Context(self)
+
+            def __context__(self):
+                self.calls.append('__context__')
+                return self.context
+            
+        acontextfact = ContextFactory()
+        with acontextfact as avar:
+            avar.append('__body__')
+            pass
+        """
+        exec s
+
+        assert acontextfact.exit_params == (None, None, None)
+        assert acontextfact.calls == '__context__ __enter__ __body__ __exit__'.split()
+        
+    def test_with_3(self):
+
+        s = """from __future__ import with_statement
+if 1:
+        class ContextFactory:
+
+            class Context:
+                def __init__(self, factory):
+                    self.factory = factory
+
+                def __enter__(self):
+                    self.factory.calls.append('__enter__')
+                    return self.factory.calls
+
+                def __exit__(self, exc_type, exc_value, exc_tb):
+                    self.factory.calls.append('__exit__')
+                    self.factory.exit_params = (exc_type, exc_value, exc_tb)
+
+            def __init__(self):
+                self.calls = list()
+                self.context = self.Context(self)
+
+            def __context__(self):
+                self.calls.append('__context__')
+                return self.context
+            
+        acontextfact = ContextFactory()
+        error = RuntimeError('With Test')
+        try:
+            with acontextfact as avar:
+                avar.append('__body__')
+                raise error
+                avar.append('__after_raise__')
+        except RuntimeError:
+            pass
+        else:
+            raise AssertionError('With did not raise RuntimeError')
+        """
+        exec s
+
+        assert acontextfact.calls == '__context__ __enter__ __body__ __exit__'.split()
+        assert acontextfact.exit_params[0:2] == (RuntimeError, error)
+        import types
+        assert isinstance(acontextfact.exit_params[2], types.TracebackType)
+        
+    def test_with_4(self):
+
+        s = """from __future__ import with_statement
+if 1:
+        class ContextFactory:
+
+            class Context:
+                def __init__(self, factory):
+                    self.factory = factory
+
+                def __enter__(self):
+                    self.factory.calls.append('__enter__')
+                    return self.factory.calls
+
+                def __exit__(self, exc_type, exc_value, exc_tb):
+                    self.factory.calls.append('__exit__')
+                    self.factory.exit_params = (exc_type, exc_value, exc_tb)
+
+            def __init__(self):
+                self.calls = list()
+                self.context = self.Context(self)
+
+            def __context__(self):
+                self.calls.append('__context__')
+                return self.context
+            
+        acontextfact = ContextFactory()
+        error = RuntimeError('With Test')
+        for x in 1,:
+            with acontextfact as avar:
+                avar.append('__body__')
+                break
+                avar.append('__after_break__')
+        else:
+            raise AssertionError('Break failed with With, reached else clause')
+        """
+        exec s
+
+        assert acontextfact.calls == '__context__ __enter__ __body__ __exit__'.split()
+        assert acontextfact.exit_params == (None, None, None)
+        
+    def test_with_5(self):
+
+        s = """from __future__ import with_statement
+if 1:
+        class ContextFactory:
+
+            class Context:
+                def __init__(self, factory):
+                    self.factory = factory
+
+                def __enter__(self):
+                    self.factory.calls.append('__enter__')
+                    return self.factory.calls
+
+                def __exit__(self, exc_type, exc_value, exc_tb):
+                    self.factory.calls.append('__exit__')
+                    self.factory.exit_params = (exc_type, exc_value, exc_tb)
+
+            def __init__(self):
+                self.calls = list()
+                self.context = self.Context(self)
+
+            def __context__(self):
+                self.calls.append('__context__')
+                return self.context
+            
+        acontextfact = ContextFactory()
+        error = RuntimeError('With Test')
+        for x in 1,:
+            with acontextfact as avar:
+                avar.append('__body__')
+                continue
+                avar.append('__after_break__')
+        else:
+            avar.append('__continue__')
+        """
+        exec s
+
+        assert acontextfact.calls == '__context__ __enter__ __body__ __exit__ __continue__'.split()
+        assert acontextfact.exit_params == (None, None, None)
+        
+    def test_with_6(self):
+
+        s = """from __future__ import with_statement
+if 1:
+        class ContextFactory:
+
+            class Context:
+                def __init__(self, factory):
+                    self.factory = factory
+
+                def __enter__(self):
+                    self.factory.calls.append('__enter__')
+                    return self.factory.calls
+
+                def __exit__(self, exc_type, exc_value, exc_tb):
+                    self.factory.calls.append('__exit__')
+                    self.factory.exit_params = (exc_type, exc_value, exc_tb)
+
+            def __init__(self):
+                self.calls = list()
+                self.context = self.Context(self)
+
+            def __context__(self):
+                self.calls.append('__context__')
+                return self.context
+            
+        acontextfact = ContextFactory()
+        error = RuntimeError('With Test')
+        def g(acontextfact):
+            with acontextfact as avar:
+                avar.append('__body__')
+                return '__return__'
+                avar.append('__after_return__')
+        acontextfact.calls.append(g(acontextfact))
+        """
+        exec s
+
+        assert acontextfact.calls == '__context__ __enter__ __body__ __exit__ __return__'.split()
+        assert acontextfact.exit_params == (None, None, None)
+        
+    def test_with_7(self):
+        exec "with = 9"
+
+    def test_with_8(self):
+        try:
+            exec "from __future__ import with_statement\nwith = 9"
+        except SyntaxError:
+            pass
+        else:
+            assert False, 'Assignment to with did not raise SyntaxError'
+
+    def test_with_9(self):
+        s = """from __future__ import with_statement
+if 1:
+        compile('''with x:
+        pass''', '', 'exec')
+        """
+        exec s
+
 if __name__ == '__main__':
     # only to check on top of CPython (you need 2.4)
     from py.test import raises

Modified: pypy/branch/njriley-trans/pypy/jit/hintrtyper.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/jit/hintrtyper.py	(original)
+++ pypy/branch/njriley-trans/pypy/jit/hintrtyper.py	Fri Mar 10 06:12:02 2006
@@ -12,6 +12,8 @@
 class HintTypeSystem(TypeSystem):
     name = "hinttypesystem"
 
+    offers_exceptiondata = False
+    
     def perform_normalizations(self, rtyper):
         pass   # for now
 
@@ -27,7 +29,7 @@
         return hs.concretetype
 
 class HintRTyper(RPythonTyper):
-    
+
     def __init__(self, hannotator, timeshifter):
     	RPythonTyper.__init__(self, hannotator, 
                               type_system=HintTypeSystem.instance)

Modified: pypy/branch/njriley-trans/pypy/jit/hinttimeshift.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/jit/hinttimeshift.py	(original)
+++ pypy/branch/njriley-trans/pypy/jit/hinttimeshift.py	Fri Mar 10 06:12:02 2006
@@ -43,13 +43,17 @@
         self.ll_build_jitstate_graph = self.annhelper.getgraph(
             rtimeshift.ll_build_jitstate,
             [], self.s_JITState)
-        self.ll_signed_box_graph = self.annhelper.getgraph(
-            rtimeshift.ll_signed_box,
-            [self.s_JITState, annmodel.SomeInteger()],
+        self.ll_int_box_graph = self.annhelper.getgraph(
+            rtimeshift.ll_int_box,
+            [rgenop.s_ConstOrVar],
             self.s_RedBox)
-        self.ll_adr_box_graph = self.annhelper.getgraph(
-            rtimeshift.ll_adr_box,
-            [self.s_JITState, annmodel.SomeAddress(), annmodel.SomePtr(rgenop.CONSTORVAR)],
+        self.ll_addr_box_graph = self.annhelper.getgraph(
+            rtimeshift.ll_addr_box,
+            [rgenop.s_ConstOrVar],
+            self.s_RedBox)
+        self.ll_double_box_graph = self.annhelper.getgraph(
+            rtimeshift.ll_int_box,
+            [rgenop.s_ConstOrVar],
             self.s_RedBox)
         self.ll_var_box_graph = self.annhelper.getgraph(
             rtimeshift.ll_var_box,

Modified: pypy/branch/njriley-trans/pypy/jit/rtimeshift.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/jit/rtimeshift.py	(original)
+++ pypy/branch/njriley-trans/pypy/jit/rtimeshift.py	Fri Mar 10 06:12:02 2006
@@ -45,31 +45,28 @@
 class ConstRedBox(RedBox):
     "A red box that contains a run-time constant."
 
+    def __init__(self, genvar):
+        self.genvar = genvar
+
+    def getgenvar(self):
+        return self.genvar
+
     def ll_fromvalue(value):
         T = lltype.typeOf(value)
+        gv = rgenop.genconst(value)
         if isinstance(T, lltype.Ptr):
-            return AddrRedBox(llmemory.cast_ptr_to_adr(value), rgenop.genconst(value))
+            return AddrRedBox(gv)
         elif T is lltype.Float:
-            return DoubleRedBox(value)
+            return DoubleRedBox(gv)
         else:
             assert T is not lltype.Void, "cannot make red boxes of voids"
             # XXX what about long longs?
-            return IntRedBox(lltype.cast_primitive(lltype.Signed, value))
+            return IntRedBox(gv)
     ll_fromvalue = staticmethod(ll_fromvalue)
 
     def ll_getvalue(self, T):
         # note: this is specialized by low-level type T, as a low-level helper
-        if isinstance(T, lltype.Ptr):
-            assert isinstance(self, AddrRedBox)
-            return llmemory.cast_adr_to_ptr(self.adrvalue, T)
-        elif T is lltype.Float:
-            assert isinstance(self, DoubleRedBox)
-            return self.dblvalue
-        else:
-            assert T is not lltype.Void, "no red box contains voids"
-            assert isinstance(self, IntRedBox)
-            # XXX what about long longs?
-            return lltype.cast_primitive(T, self.intvalue)
+        return rgenop.revealconst(T, self.genvar)
 
 def ll_getvalue(box, T):
     return box.ll_getvalue(T)
@@ -78,44 +75,25 @@
 class IntRedBox(ConstRedBox):
     "A red box that contains a constant integer-like value."
 
-    def __init__(self, intvalue):
-        self.intvalue = intvalue
-
-    def getgenvar(self):
-        return rgenop.genconst(self.intvalue)
-
     def same_constant(self, other):
-        return isinstance(other, IntRedBox) and self.intvalue == other.intvalue
+        return (isinstance(other, IntRedBox) and
+                self.ll_getvalue(lltype.Signed) == other.ll_getvalue(lltype.Signed))
 
 
 class DoubleRedBox(ConstRedBox):
     "A red box that contains a constant double-precision floating point value."
 
-    def __init__(self, dblvalue):
-        self.dblvalue = dblvalue
-
-    def getgenvar(self):
-        return rgenop.genconst(self.dblvalue)
-
     def same_constant(self, other):
-        return isinstance(other, DoubleRedBox) and self.dblvalue == other.dblvalue
+        return (isinstance(other, DoubleRedBox) and
+                self.ll_getvalue(lltype.Float) == other.ll_getvalue(lltype.Float))
 
 
 class AddrRedBox(ConstRedBox):
     "A red box that contains a constant address."
 
-    # xxx the constant genvar needs to preserve the pointer itself!
-    # for now do it this way, anyway addresses are not the right thing
-    # GC wise
-    def __init__(self, adrvalue, genvar): 
-        self.adrvalue = adrvalue
-        self.genvar = genvar 
-
-    def getgenvar(self):
-        return self.genvar # created eagerly
-
     def same_constant(self, other):
-        return isinstance(other, AddrRedBox) and self.adrvalue == other.adrvalue
+        return (isinstance(other, AddrRedBox) and
+                self.ll_getvalue(llmemory.Address) == other.ll_getvalue(llmemory.Address))
 
 
 # ____________________________________________________________
@@ -295,7 +273,7 @@
 def leave_block_split(jitstate, switchredbox, exitindex, redboxes):
     if isinstance(switchredbox, IntRedBox):
         jitstate.curoutgoinglink = rgenop.closeblock1(jitstate.curblock)        
-        return bool(switchredbox.intvalue)
+        return switchredbox.ll_getvalue(lltype.Bool)
     else:
         exitgvar = switchredbox.getgenvar()
         linkpair = rgenop.closeblock2(jitstate.curblock, exitgvar)    
@@ -383,12 +361,14 @@
     jitstate.setup()
     return jitstate
 
-def ll_signed_box(jitstate, value):
-    value = lltype.cast_primitive(lltype.Signed, value)
-    return ConstRedBox.ll_fromvalue(value)
+def ll_int_box(gv):
+    return IntRedBox(gv)
+
+def ll_double_box(gv):
+    return DoubleRedBox(gv)
 
-def ll_adr_box(jitstate, addr, genvar): # xxx
-    return AddrRedBox(addr, genvar)
+def ll_addr_box(gv):
+    return AddrRedBox(gv)
 
 def ll_var_box(jitstate, gv_TYPE):
     genvar = rgenop.geninputarg(jitstate.curblock, gv_TYPE)

Modified: pypy/branch/njriley-trans/pypy/jit/test/test_hint_annotation.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/jit/test/test_hint_annotation.py	(original)
+++ pypy/branch/njriley-trans/pypy/jit/test/test_hint_annotation.py	Fri Mar 10 06:12:02 2006
@@ -386,7 +386,7 @@
     py.test.raises(HintError, hannotate,
                    ll_getitem_switch, [annmodel.SomePtr(lltype.Ptr(S))])
 
-def test_invalid_hint_2():
+def undecided_relevance_test_invalid_hint_2():
     S = lltype.GcStruct('S', ('x', lltype.Signed))
     def ll_getitem_switch(s):
         if s.x > 0:   # variable exitswitch

Modified: pypy/branch/njriley-trans/pypy/jit/test/test_hint_timeshift.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/jit/test/test_hint_timeshift.py	(original)
+++ pypy/branch/njriley-trans/pypy/jit/test/test_hint_timeshift.py	Fri Mar 10 06:12:02 2006
@@ -65,11 +65,12 @@
                                                                  rgenop.constTYPE(TYPE)])
             if i in opt_consts: # XXX what should happen here interface wise is unclear
                 if isinstance(lltype.typeOf(llvalue), lltype.Ptr):
-                    box = llinterp.eval_graph(htshift.ll_adr_box_graph, [jitstate,
-                                                                         llmemory.cast_ptr_to_adr(llvalue),
-                                                                         rgenop.genconst(llvalue)]) # xxx
+                    ll_box_graph = htshift.ll_addr_box_graph
+                elif isinstance(llvalue, float):
+                    ll_box_graph = htshift.ll_double_box_graph
                 else:
-                    box = llinterp.eval_graph(htshift.ll_signed_box_graph, [jitstate, llvalue])
+                    ll_box_graph = htshift.ll_int_box_graph
+                box = llinterp.eval_graph(ll_box_graph, [rgenop.genconst(llvalue)])
             graph1args.append(box)
             residual_graph_args.append(llvalue)
     startblock = llinterp.eval_graph(htshift.ll_end_setup_jitstate_graph, [jitstate])

Modified: pypy/branch/njriley-trans/pypy/jit/test/test_llabstractinterp.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/jit/test/test_llabstractinterp.py	(original)
+++ pypy/branch/njriley-trans/pypy/jit/test/test_llabstractinterp.py	Fri Mar 10 06:12:02 2006
@@ -211,7 +211,7 @@
     graph2, insns = abstrinterp(ll_function, [s, 0, 0], [0, 1, 2])
     assert insns == {}
 
-def test_recursive_call():
+def no_longer_relevant_test_recursive_call():
     py.test.skip("reimplement or remove the test: "
                  "non-inlined calls with constant results")
     def ll_factorial(k):

Modified: pypy/branch/njriley-trans/pypy/lib/logic/computation_space/computationspace.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/computation_space/computationspace.py	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/computation_space/computationspace.py	Fri Mar 10 06:12:02 2006
@@ -1,29 +1,53 @@
 # TODO
-# * support several distribution strategies
-# * add a linear constraint solver (vital for fast
+# * [1] adapt other distribution strategies
+# * [5] add a linear constraint solver (vital for fast
 #   constraint propagation over finite integer domains)
-# * make all propagators live in their own threads and
+#   and other kinds of specialized propagators
+# * [9] make all propagators live in their own threads and
 #   be awakened by variable/domains events
 
+
+# Gert Smolka in
+# http://www.cetic.be/moz2004/talks/MOZ2004.pdf :
+# * Abandon Logic Variables
+#  * can be bound everywhere
+#  * malicious consummer can bind tail variable of stream
+#  * break abstractions
+#  * unification not needed
+# * Have Futures instead
+#  * Multilisp [Halstead 85]
+#  * added to Mozart in 1998
+#  * refine logic variable into
+#   * consummer end (future)
+#   * producer end (promise)
+#  * dataflow synchronization + by-need synchronization
+
+
 from threading import Thread, Condition, RLock, local
 
-from state import Succeeded, Distributable, Failed, Unknown
+from state import Succeeded, Distributable, Failed, \
+     Unknown, Forsaken
 
-from variable import EqSet, Var, NoValue, NoDom, \
-     VariableException, NotAVariable, AlreadyInStore
+from variable import EqSet, CsVar, NoValue, NoDom, \
+     VariableException, NotAVariable, AlreadyInStore, \
+     AlreadyBound, SimpleVar
 from constraint import FiniteDomain, ConsistencyFailure, \
      Expression
 from distributor import DefaultDistributor
+import event # NewSpace, Clone, Revise
 
-class Alternatives(object):
+class Alternative(object):
 
-    def __init__(self, nb_alternatives):
-        self._nbalt = nb_alternatives
+    def __init__(self, choices):
+        self._choices = choices
 
     def __eq__(self, other):
         if other is None: return False
-        if not isinstance(other, Alternatives): return False
-        return self._nbalt == other._nbalt
+        if not isinstance(other, Alternative): return False
+        return self._choices == other._choices
+
+    def __str__(self):
+        return "Alternatives(%s)" % self._choices
 
 def NoProblem():
     """the empty problem, used by clone()"""
@@ -69,55 +93,59 @@
     # we have to enforce only one distributor
     # thread running in one space at the same time
     _nb_choices = 0
+    _id_count = 0
 
     def __init__(self, problem, parent=None):
+        self.id = ComputationSpace._id_count
+        ComputationSpace._id_count += 1
+        self.status = Unknown
         # consistency-preserving stuff
         self.in_transaction = False
         self.bind_lock = RLock()
         self.var_lock = RLock()
-        self.dist_lock = RLock()
         self.distributor = DefaultDistributor(self)
-        self.status = Unknown
+        # parent/children
         self.parent = parent
         self.children = set()
+        # mapping from domains to variables
+        self.doms = {}
+        # set of all constraints 
+        self.constraints = set()
+        # mapping from vars to constraints
+        self.var_const_map = {}
+        self.event_set = set()
         
         if parent is None:
             self.vars = set()
             # mapping of names to vars (all of them)
             self.names = {}
-            # mapping from vars to constraints
-            self.var_const_map = {}
-            # mapping from domains to variables
-            self.doms = {}
-            # set of all constraints 
-            self.constraints = set()
             self.root = self.var('__root__')
             # set up the problem
             self.bind(self.root, problem(self))
-            # check satisfiability of the space
             self._init_choose_commit()
+            self.distributor.start()
         else:
+            self.parent.children.add(self)
+            # shared stuff
             self.vars = parent.vars
             self.names = parent.names
-            # we should really copy stuff
-            self.var_const_map = parent.var_const_map
-            self.constraints = parent.constraints
-            self.doms = {} # shall be copied by clone
             self.root = parent.root
-            self.status = parent.status
+            # copied stuff
+            self.copy_domains(parent)
+            self.copy_constraints(parent)
+            # ...
+            self.status = Unknown
             self.distributor = parent.distributor.__class__(self)
             self._init_choose_commit()
 
-        self.distributor.start()
-
     def _init_choose_commit(self):
         # create a unique choice point
-        # using two vars as channels betwen
+        # using two spaceless vars as channels betwen
         # space and distributor threads
-        self.CHOOSE = self._make_choice_var()
-        self.STABLE = self._make_stable_var()
+        self.CHOOSE = SimpleVar()
+        self.STABLE = SimpleVar()
 
-#-- utilities -------------------------------------------------
+#-- utilities & instrumentation -----------------------------
 
     def __str__(self):
         ret = ["<space:\n"]
@@ -127,69 +155,96 @@
         ret.append(">")
         return ' '.join(ret)
 
+    def __del__(self):
+        # try to break ref. cycles and help
+        # threads terminate
+        self.status = Forsaken
+        self.parent = None
+        self.children = None
+        self.CHOOSE.bind(True)
+        self.STABLE.bind(True)
+
+    def __eq__(self, spc):
+        """space equality defined as :
+           * identity, or
+           * same set of vars with a domain, and
+           * same name set, and
+           * equal domains, and
+           * same set of constraints, and
+           * different propagators of the same type"""
+        if not isinstance(spc, ComputationSpace): return False
+        if id(self) == id(spc): return True
+        r1 = self.vars == spc.vars
+        r2 = self.names == spc.names
+        r3 = self.constraints != spc.constraints
+        r4 = self.distributor != spc.distributor
+        r5 = self.root == spc.root
+        if not r1 and r2 and r3 and r4 and r5:
+            return False
+        # now the domains
+        it1 = [item for item in self.doms.items()
+               if item[1] != NoDom]
+        it2 = [item for item in spc.doms.items()
+               if item[1] != NoDom]
+        it1.sort()
+        it2.sort()
+        for (v1, d1), (v2, d2) in zip (it1, it2):
+            if v1 != v2: return False
+            if d1 != d2: return False
+            if id(v1) != id(v2): return False
+            if id(d1) == id(d2): return False
+        return True
+
+    def __ne__(self, other):
+        return not self == other
+
     def pretty_doms(self):
         print "(-- domains --"
-        for v, d in self.doms.items():
+        doms = self.doms.items()
+        doms.sort()
+        for v, d in doms:
             if d != NoDom:
-                print ' ', str(d)
+                print ' ', str(d.get_values())
         print " -- domains --)"
 
+           
 #-- Computation Space -----------------------------------------
 
-    def _make_choice_var(self):
-        ComputationSpace._nb_choices += 1
-        ch_var = self.var('__choice__'+str(self._nb_choices))
-        return ch_var
-
-    def _make_stable_var(self):
-        ComputationSpace._nb_choices += 1
-        st_var = self.var('__stable__'+str(self._nb_choices))
-        return st_var
+    #-- space helpers -----------------------------------------
 
     def _process(self):
-        """auxilary of the distributor
-        """
-        #XXX: shouldn't only the distributor call it ?
-        #XXX: this is all sequential, but in the future
-        #     when propagators live in threads and are
-        #     awaken by events on variables, this might
-        #     completely disappear
-        try:
-            self.satisfy_all()
-        except ConsistencyFailure:
-            self.status = Failed
-        else:
-            if self._distributable():
-                self.status = Distributable
+        """wraps the propagator"""
+        if len(self.event_set):
+            try:
+                self.satisfy_all()
+            except ConsistencyFailure:
+                self.status = Failed
             else:
-                self.status = Succeeded
+                if not self._distributable():
+                    self.status = Succeeded
 
     def _distributable(self):
-        self.dist_lock.acquire()
-        try:
-            if self.status not in (Failed, Succeeded):
-                for var in self.root.val:
-                    if self.dom(var).size() > 1 :
-                        return True
-            return False
-        finally:
-            self.dist_lock.release()
-        # in The Book : "the space has one thread that is
-        # suspended on a choice point with two or more alternatives.
-        # A space can have at most one choice point; attempting to
-        # create another gives an error."
+        if self.status not in (Failed, Succeeded):
+            for var in self.root.val:
+                if self.dom(var).size() > 1 :
+                    return True
+        return False
 
     def top_level(self):
         return self.parent is None
 
+    def _notify(self, event):
+        self.event_set.add(event)
+
+    #-- space official API ------------------------------------
+
     def ask(self):
-        #print "SPACE Ask() checks stability ..."
-        self.STABLE.get() # that's real stability
-        #print "SPACE is stable, resuming Ask()"
+        self.STABLE.get() 
         status = self.status in (Failed, Succeeded)
         if status: return self.status
         if self._distributable():
-            return Alternatives(self.distributor.nb_subdomains())
+            return Alternative(self.distributor.nb_subdomains())
+
         # should be unreachable
         print "DOMS", [(var, self.doms[var]) 
                        for var in self.vars
@@ -197,11 +252,13 @@
         raise NotImplementedError
 
     def clone(self):
-        #XXX: lazy copy of domains would be nice
+        # did you ask before ... ?
+        assert self.STABLE.is_bound()
         spc = ComputationSpace(NoProblem, parent=self)
-        for var in spc.vars:
-            if self.dom(var) != NoDom:
-                spc.set_dom(var, self.dom(var).copy())
+        print "-- cloning %s to %s --" % (self.id, spc.id)
+        self._notify(event.Clone)
+        spc._process()
+        spc.distributor.start()            
         return spc
 
     def inject(self, restricting_problem):
@@ -216,14 +273,10 @@
            some_number must satisfy 1=<I=<N where N is the first arg
            of the Choose call.
         """
-        #print "SPACE commited to", choice
-        # block future calls to Ask until the distributor
-        # binds STABLE
-        old_stable_var = self.STABLE
-        self.STABLE = self._make_stable_var()
-        self._del_var(old_stable_var)
-        #print "SPACE binds CHOOSE to", choice
-        self.bind(self.CHOOSE, choice)
+        # did you ask before ... ?
+        assert self.STABLE.is_bound()
+        self.STABLE = SimpleVar()
+        self.CHOOSE.bind(choice)
 
     def choose(self, nb_choices):
         """
@@ -241,11 +294,17 @@
     def merge(self):
         """binds root vars to their singleton domains """
         assert self.status == Succeeded
-        for var in self.root.val:
-            var.bind(self.dom(var).get_values()[0])
+        # this can't work if we don't copy vars too
+        #for var in self.root.val:
+        #    var.bind(self.dom(var).get_values()[0])
         # shut down the distributor
-        self.CHOOSE.bind(0)
-        return self.root.val
+        self.CHOOSE.bind(True)
+        self.status = Forsaken
+        res = {}
+        for var in self.root.val:
+            res[var.name] = self.dom(var).get_values()[0]
+        self.distributor.join()
+        return res
 
     def set_distributor(self, dist):
         self.distributor = dist
@@ -259,7 +318,7 @@
            and puts it into the store"""
         self.var_lock.acquire()
         try:
-            v = Var(name, self)
+            v = CsVar(name, self)
             self.add_unbound(v)
             return v
         finally:
@@ -281,22 +340,6 @@
         # put into new singleton equiv. set
         var.val = EqSet([var])
 
-    def set_dom(self, var, dom):
-        """bind variable to domain"""
-        assert(isinstance(var, Var) and (var in self.vars))
-        if var.is_bound():
-            print "warning : setting domain %s to bound var %s" \
-                  % (dom, var)
-        self.doms[var] = FiniteDomain(dom)
-
-    def dom(self, var):
-        assert isinstance(var, Var)
-        try:
-            return self.doms[var]
-        except KeyError:
-            self.doms[var] = NoDom
-            return NoDom
-
     def get_var_by_name(self, name):
         """looks up one variable"""
         try:
@@ -331,21 +374,49 @@
         self.vars.remove(var)
         if self.doms.has_key(var):
             del self.doms[var]
-    
+
+    #-- Domains -----------------------------
+
+    def set_dom(self, var, dom):
+        """bind variable to domain"""
+        assert(isinstance(var, CsVar) and (var in self.vars))
+        if var.is_bound():
+            print "warning : setting domain %s to bound var %s" \
+                  % (dom, var)
+        self.doms[var] = FiniteDomain(dom)
+
+    def dom(self, var):
+        assert isinstance(var, CsVar)
+        return self.doms.get(var, NoDom)
+        try:
+            return self.doms[var]
+        except KeyError:
+            self.doms[var] = NoDom
+            return NoDom
+
+
+    def copy_domains(self, space):
+        for var in self.vars:
+            if space.dom(var) != NoDom:
+                self.set_dom(var, space.dom(var).copy())
+                assert space.dom(var) == self.dom(var)
+                assert id(self.dom(var)) != id(space.dom(var))
+
     #-- Constraints -------------------------
 
-    def add_expression(self, constraint):
+    def _add_const(self, constraint):
         self.constraints.add(constraint)
-        for var in constraint.affectedVariables():
+        self._notify(event.Inject(constraint))
+        for var in constraint.affected_variables():
             self.var_const_map.setdefault(var, set())
             self.var_const_map[var].add(constraint)
 
+    def add_expression(self, constraint):
+        self._add_const(constraint)
+        
     def add_constraint(self, vars, const):
         constraint = Expression(self, vars, const)
-        self.constraints.add(constraint)
-        for var in constraint.affectedVariables():
-            self.var_const_map.setdefault(var, set())
-            self.var_const_map[var].add(constraint)
+        self._add_const(constraint)
 
     def dependant_constraints(self, var):
         return self.var_const_map[var]
@@ -356,6 +427,11 @@
             if self.dom(var) != NoDom: varset.add(var)
         return varset
 
+    def copy_constraints(self, space):
+        self.constraints = set()
+        for const in space.constraints:
+            self._add_const(const.copy_to(self))
+
     #-- Constraint propagation ---------------
 
     def satisfiable(self, constraint):
@@ -421,14 +497,34 @@
                 self.restore_domains(old_domains)
                 raise
 
+    #-- real propagation begins there -------------------------
+
+    def add_distributed(self, var):
+        self.changelog.append(var)
+
+    def _init_constraint_queue(self):
+        cqueue = []
+        init_const_set = set()
+        for ev in self.event_set:
+            if isinstance(ev, event.Revise):
+                for const in self.var_const_map[ev.var]:
+                    init_const_set.add(const)
+            elif isinstance(ev, event.Inject):
+                init_const_set.add(ev.constraint)
+                
+        cqueue = [(const.estimate_cost(), const)
+                  for const in init_const_set]
+        return cqueue
+
     def satisfy_all(self):
         """really PROPAGATE"""
-        const_q = [(const.estimateCost(), const)
-                   for const in self.constraints]
+        const_q = self._init_constraint_queue()
+        assert const_q != []
+        const_q.sort()
         affected_constraints = set()
         while True:
             if not const_q:
-                const_q = [(const.estimateCost(), const)
+                const_q = [(const.estimate_cost(), const)
                            for const in affected_constraints]
                 if not const_q:
                     break
@@ -436,7 +532,7 @@
                 affected_constraints.clear()
             cost, const = const_q.pop(0)
             entailed = const.revise3()
-            for var in const.affectedVariables():
+            for var in const.affected_variables():
                 dom = self.dom(var)
                 if not dom.has_changed():
                     continue
@@ -454,7 +550,7 @@
                                constset):
         if constraint in constset: return
         constset.add(constraint)
-        for var in constraint.affectedVariables():
+        for var in constraint.affected_variables():
             varset.add(var)
             dep_consts = self.var_const_map[var]
             for const in dep_consts:
@@ -508,7 +604,7 @@
         # removed (this last condition remains to be checked)
         self.bind_lock.acquire()
         try:
-            assert(isinstance(var, Var) and (var in self.vars))
+            assert(isinstance(var, CsVar) and (var in self.vars))
             if var == val:
                 return
             if _both_are_vars(var, val):
@@ -657,7 +753,7 @@
         return False
     if _mapping(term1) and _mapping(term2):
         return _mapping_unifiable(term1, term2)
-    if not(isinstance(term1, Var) or isinstance(term2, Var)):
+    if not(isinstance(term1, CsVar) or isinstance(term2, CsVar)):
         return term1 == term2 # same 'atomic' object
     return True
         
@@ -686,13 +782,49 @@
 #-- Some utilities -------------------------------------------
 
 def _both_are_vars(v1, v2):
-    return isinstance(v1, Var) and isinstance(v2, Var)
+    return isinstance(v1, CsVar) and isinstance(v2, CsVar)
     
 def _both_are_bound(v1, v2):
     return v1._is_bound() and v2._is_bound()
 
-def fif(test, iftrue, iffalse):
-    if test:
-        return iftrue
+def diff_list(l1, l2):
+    diff = {}
+    idx = 0
+    for e1, e2 in zip(l1, l2):
+        if e1 != e2: diff[idx] = (e1, e2)
+        idx += 1
+    return diff
+
+def backup_domains(space):
+    print "-- backup of domains (%s) --" % space.id
+    doms = []
+    for v, d in space.doms.items():
+        if d != NoDom:
+            doms.append((v, len(d)))
+    doms.sort()
+    print "  (", [elt[1] for elt in doms], ")"
+    return doms
+
+def print_quick_diff(space, domain_history):
+    ldh = len(domain_history)
+    if ldh > 0:
+        print "history size (%s) : %s" % (space.id, ldh)
+        last = domain_history[-1]
     else:
-        return iffalse
+        curr = [(item[0], len(item[1].get_values()))
+                for item in space.doms.items()
+                if item[1] != NoDom]
+        curr.sort()
+        print "(diff -- v : d 0        (%s)" % space.id
+        for l in curr:
+            print ' '*6, '%s :  %2d' % (l[0], l[1]) 
+        print " --)"
+        return
+    curr = [(item[0], len(item[1].get_values()))
+            for item in space.doms.items()
+            if item[1] != NoDom]
+    curr.sort()
+    print "(diff -- v : d%2d | d%2d (%s)" % (ldh, ldh+1, space.id)
+    for l1, l2 in zip(last, curr):
+        print ' '*6, '%s :  %2d | %2d ' % (l1[0], l1[1], l2[1]) 
+    print " --)"

Modified: pypy/branch/njriley-trans/pypy/lib/logic/computation_space/constraint.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/computation_space/constraint.py	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/computation_space/constraint.py	Fri Mar 10 06:12:02 2006
@@ -18,7 +18,6 @@
     """Implements the functionnality related to the changed flag.
     Can be used as a starting point for concrete domains"""
 
-    #__implements__ = DomainInterface
     def __init__(self):
         self.__changed = 0
 
@@ -40,44 +39,24 @@
     Variable Domain with a finite set of possible values
     """
 
-    _copy_count = 0
-    _write_count = 0
-    
     def __init__(self, values):
         """values is a list of values in the domain
         This class uses a dictionnary to make sure that there are
         no duplicate values"""
         AbstractDomain.__init__(self)
-        if isinstance(values,FiniteDomain):
-            # do a copy on write
-            self._cow = True
-            values._cow = True
-            FiniteDomain._copy_count += 1
-            self._values = values._values
-        else:
-            # don't check this there (a)
-            #assert len(values) > 0
-            self.set_values(values)
-            
-        ##self.getValues = self._values.keys
+        self.set_values(values)
 
     def set_values(self, values):
-        self._cow = False
-        FiniteDomain._write_count += 1
         self._values = set(values)
         
     def remove_value(self, value):
         """Remove value of domain and check for consistency"""
 ##         print "removing", value, "from", self._values.keys()
-        if self._cow:
-            self.set_values(self._values)
         del self._values[value]
         self._value_removed()
 
     def remove_values(self, values):
         """Remove values of domain and check for consistency"""
-        if self._cow:
-            self.set_values(self._values)
         if values:
 ##             print "removing", values, "from", self._values.keys()
             for val in values :
@@ -103,7 +82,7 @@
         return FiniteDomain(self)
     
     def __repr__(self):
-        return '<FiniteDomain %s>' % str(self.get_values())
+        return '<FD %s>' % str(self.get_values())
 
     def __eq__(self, other):
         if other is NoDom: return False
@@ -131,18 +110,24 @@
             self._names_to_vars[var.name] = var
         self._variables = variables
 
-    def affectedVariables(self):
+    def affected_variables(self):
         """ Return a list of all variables affected by this constraint """
         return self._variables
 
     def isVariableRelevant(self, variable):
         return variable in self._variables
 
-    def estimateCost(self):
+    def estimate_cost(self):
         """Return an estimate of the cost of the narrowing of the constraint"""
         return reduce(operator.mul,
                       [self.cs.dom(var).size() for var in self._variables])
 
+    def copy_to(self, space):
+        return self.__class__(space, self._variables)
+
+    def __eq__(self, other): #FIXME and parent
+        if not isinstance(other, self.__class__): return False
+        return self._variables == other._variables
 
 class BasicConstraint(object):
     """A BasicConstraint, which is never queued by the Repository
@@ -159,6 +144,9 @@
     def __repr__(self):
         return '<%s %s %s>'% (self.__class__, self._variable, self._reference)
 
+    def copy_to(self, space):
+        raise NotImplementedError
+
     def isVariableRelevant(self, variable):
         return variable == self._variable
 
@@ -184,6 +172,8 @@
                                      repr(self))
         return 1
 
+    def __eq__(self, other):
+        raise NotImplementedError
 
 def make_lambda_head(vars):
     var_ids = ','.join([var.name for var in vars])
@@ -211,6 +201,11 @@
                                    + expand_expr_template(formula, variables), {}, {})
             Expression._FILTER_CACHE[formula] = self.filterFunc
 
+
+    def copy_to(self, space):
+        return self.__class__(space, self._variables,
+                              self.formula, self.type)
+
     def _init_result_cache(self):
         """key = (variable,value), value = [has_success,has_failure]"""
         result_cache = {}
@@ -248,7 +243,7 @@
         
     def revise3(self):
         # removed domain arg. (auc, ale)
-        """generic narrowing algorithm for n-ary expressions"""
+        """generic propagation algorithm for n-ary expressions"""
         maybe_entailed = 1
         ffunc = self.filterFunc
         result_cache = self._init_result_cache()
@@ -264,6 +259,7 @@
                     result_cache[var][val] = 1
             else:
                 maybe_entailed = 0
+                
         try:
             for var, keep in result_cache.iteritems():
                 domain = self.cs.dom(self._names_to_vars[var])
@@ -278,6 +274,13 @@
 
         return maybe_entailed
 
+    def __eq__(self, other):
+        if not super(Expression, self).__eq__(other): return False
+        r1 = self.formula == other.formula
+        r2 = self.type == other.type
+        return r1 and r2
+        
+
     def __repr__(self):
         return '<%s>' % self.formula
 
@@ -291,6 +294,9 @@
         assert len(variables) == 2
         Expression.__init__(self, variables, formula, type)
 
+    def copy_to(self, space):
+        raise NotImplementedError
+
     def revise3(self, domains):
         """specialized narrowing algorithm for binary expressions
         Runs much faster than the generic version"""

Modified: pypy/branch/njriley-trans/pypy/lib/logic/computation_space/distributor.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/computation_space/distributor.py	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/computation_space/distributor.py	Fri Mar 10 06:12:02 2006
@@ -1,6 +1,8 @@
 import math, random
 from threading import Thread
-from state import Succeeded, Distributable, Failed
+from state import Succeeded, Distributable, Failed, Forsaken
+from event import Revise
+from variable import SimpleVar
 
 def arrange_domains(cs, variables):
     """build a data structure from var to dom
@@ -95,7 +97,7 @@
 
 
 class RandomizingDistributor(AbstractDistributor):
-    """distributes domains as the NaiveDistrutor, except that the unique
+    """distributes domains as the NaiveDistributor, except that the unique
     value of the first domain is picked at random."""
         
     def _distribute(self, dom1, dom2):
@@ -138,22 +140,26 @@
     ### new threaded distributor
 
     def run(self):
-        self.cs._process() # propagate first
-        self.cs.STABLE.bind(0)
+        print "-- distributor started (%s) --" % self.cs.id
+        assert not self.cs.STABLE.is_bound()
+        #XXX: are the domains properly set up ?
+        #self.cs._process() # propagate first
+        #better let clone() do this call
         while self.cs._distributable():
+            self.cs.STABLE.bind(True)
             choice = self.cs.choose(self.nb_subdomains())
-            # racey ... ?
+            if self.cs.status == Forsaken:
+                print "-- distributor (%s) ready for GC --" % self.cs.id
+                break
+            print "-- distribution & propagation (%s) --" % self.cs.id
             self.distribute(choice-1)
             self.cs._process()
-            old_choose_var = self.cs.CHOOSE
-            self.cs.CHOOSE = self.cs._make_choice_var()
-            self.cs._del_var(old_choose_var)
-            self.cs.STABLE.bind(0) # unlocks Ask
-        print "-- distributor terminated --"
+            self.cs.CHOOSE = SimpleVar()
+            self.cs.STABLE.bind(True) # unlocks Ask
+        print "-- distributor terminated (%s) --" % self.cs.id
 
 
     def distribute(self, choice):
-        """See AbstractDistributor"""
         variable = self.findSmallestDomain()
         #variables = self.cs.get_variables_with_a_domain()
         #domains = arrange_domains(self.cs, variables)
@@ -164,6 +170,7 @@
                       int(math.floor((choice + 1) * nb_elts)))
         self.cs.dom(variable).remove_values(values[:start])
         self.cs.dom(variable).remove_values(values[end:])
+        self.cs._notify(Revise(variable))
 
 
 class DichotomyDistributor(SplitDistributor):

Modified: pypy/branch/njriley-trans/pypy/lib/logic/computation_space/problems.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/computation_space/problems.py	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/computation_space/problems.py	Fri Mar 10 06:12:02 2006
@@ -11,8 +11,8 @@
     cs = computation_space
     x, y, z = cs.var('x'), cs.var('y'), cs.var('z')
     cs.set_dom(x, c.FiniteDomain([-4, -2, -1, 0, 1, 2, 4]))
-    cs.set_dom(y, c.FiniteDomain([0, 2, 3, 4, 5, 16]))
-    cs.set_dom(z, c.FiniteDomain([-2, -1, 0, 1, 2]))
+    cs.set_dom(y, c.FiniteDomain([0, 1, 2, 4, 8, 16]))
+    cs.set_dom(z, c.FiniteDomain([0, 1, 2]))
     cs.add_constraint([x, y, z], 'y==x**2-z')
     # set up a distribution strategy
     cs.set_distributor(di.DichotomyDistributor(cs))
@@ -114,4 +114,35 @@
         for conf2 in variables:
             if conf2 > conf1:
                 cs.add_constraint([conf1,conf2], '%s != %s'%(conf1.name,conf2.name))
+
+    return tuple(variables)
+
+def sudoku(computation_space):
+    cs = computation_space
+    import constraint as c
+
+    variables = [cs.var('v%i%i'%(x,y)) for x in range(1,10) for y in range(1,10)]
+
+    # Make the variables
+    for v in variables:
+        cs.set_dom(v, c.FiniteDomain(range(1,10)))
+    # Add constraints for rows (sum should be 45)
+    for i in range(1,10):
+        row = [ v for v in variables if v.name[1] == str(i)]
+        cs.add_constraint(row, 'sum([%s]) == 45' % ', '.join([v.name for v in row]))
+    # Add constraints for columns (sum should be 45)
+    for i in range(1,10):
+        row = [ v for v in variables if v.name[2] == str(i)]
+        cs.add_constraint(row, 'sum([%s]) == 45' % ', '.join([v.name for v in row]))   
+    # Add constraints for subsquares (sum should be 45)
+    offsets = [(r,c) for r in [-1,0,1] for c in [-1,0,1]]
+    subsquares = [(r,c) for r in [2,5,8] for c in [2,5,8]]
+    for rc in subsquares:
+        sub = [cs.get_var_by_name('v%d%d'% (rc[0] + off[0],rc[1] + off[1])) for off in offsets]
+        cs.add_constraint(sub, 'sum([%s]) == 45' % ', '.join([v.name for v in sub]))
+        for v in sub:
+            for m in sub[sub.index(v)+1:]:
+                cs.add_constraint([v,m], '%s != %s' % (v.name, m.name))
+    #print cs.constraints
     return tuple(variables)
+    

Modified: pypy/branch/njriley-trans/pypy/lib/logic/computation_space/state.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/computation_space/state.py	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/computation_space/state.py	Fri Mar 10 06:12:02 2006
@@ -11,4 +11,4 @@
 
 class Unknown: pass
 
-
+class Forsaken: pass

Modified: pypy/branch/njriley-trans/pypy/lib/logic/computation_space/strategies.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/computation_space/strategies.py	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/computation_space/strategies.py	Fri Mar 10 06:12:02 2006
@@ -15,11 +15,12 @@
             return None
         elif status == csp.Succeeded:
             return space
-        elif status == csp.Alternatives(2):
+        elif status == csp.Alternative(2):
             new_space = space.clone()
             space.commit(1)
             outcome = do_dfs(space)
             if outcome is None:
+                new_space.ask()
                 new_space.commit(2)
                 return do_dfs(new_space)
             else:
@@ -50,12 +51,14 @@
         if status == csp.Succeeded:
             print ' '*len(sp_stack), "solution !"
             solutions.append(space)
-        elif status == csp.Alternatives(2):
+        elif status == csp.Alternative(2):
             print ' '*len(sp_stack), "branches ..."
             sp1 = space.clone()
+            sp1.ask()
             sp1.commit(1)
             sp_stack.append(sp1)
             sp2 = space.clone()
+            sp2.ask()
             sp2.commit(2)
             sp_stack.append(sp2)
 

Modified: pypy/branch/njriley-trans/pypy/lib/logic/computation_space/test_computationspace.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/computation_space/test_computationspace.py	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/computation_space/test_computationspace.py	Fri Mar 10 06:12:02 2006
@@ -484,48 +484,63 @@
         assert set(['x', 'y', 'z']) == \
                set([var.name for var in spc.root.val])
 
-    def test_ask_success(self):
-        spc = newspace(problems.one_solution_problem)
-        assert spc.ask() == space.Succeeded
-        assert spc.ask() == space.Succeeded
+# we need to carefully craft some noop problems
+# for these tests
+# also what is tested below is tested in other places
+# so me might want to just forget about it
+
+##     def test_ask_success(self):
+##         spc = newspace(problems.one_solution_problem)
+##         assert spc.ask() == space.Succeeded
+##         assert spc.ask() == space.Succeeded
         
-    def test_ask_failure(self):
-        spc = newspace(problems.unsatisfiable_problem)
-        assert spc.ask() == space.Failed
+##     def test_ask_failure(self):
+##         spc = newspace(problems.unsatisfiable_problem)
+##         assert spc.ask() == space.Failed
 
     def test_ask_alternatives(self):
         spc = newspace(problems.satisfiable_problem)
-        assert spc.ask() == space.Alternatives(2)
+        assert spc.ask() == space.Alternative(2)
 
-    def test_clone_and_process(self):
-        spc = newspace(problems.satisfiable_problem)
-        assert spc.ask() == space.Alternatives(2)
-        new_spc = spc.clone()
-        assert new_spc.parent == spc
-        assert new_spc.vars == spc.vars
-        assert new_spc.names == spc.names
-        assert new_spc.root == spc.root
-        assert new_spc.constraints == spc.constraints
-        assert new_spc.distributor != spc.distributor
-        it1 = [item for item in spc.doms.items()
-               if item[1] != space.NoDom]
-        it2 = [item for item in new_spc.doms.items()
-               if item[1] != space.NoDom]
-        it1.sort()
-        it2.sort()
-        for (v1, d1), (v2, d2) in zip (it1, it2):
-            assert v1 == v2
-            assert d1 == d2
-            assert id(v1) == id(v2)
-            assert id(d1) != id(d2)
-        # following couple of ops superceeded by inject()
-        x, y, z = new_spc.find_vars('x', 'y', 'z')
-        new_spc.add_constraint([x], 'x == 0')
-        new_spc.add_constraint([z, y], 'z == y')
-        new_spc.add_constraint([y], 'y < 2')
-        new_spc._process()
-        assert spc.ask() == space.Alternatives(2)
-        assert new_spc.ask() == space.Succeeded
+##     def test_clone_and_process(self):
+##         spc = newspace(problems.satisfiable_problem)
+##         assert spc.ask() == space.Alternative(2)
+##         new_spc = spc.clone()
+##         #assert spc == new_spc
+##         assert new_spc.parent == spc
+##         # following couple of ops superceeded by inject()
+##         x, y, z = new_spc.find_vars('x', 'y', 'z')
+##         new_spc.add_constraint([x], 'x == 0')
+##         new_spc.add_constraint([z, y], 'z == y')
+##         new_spc.add_constraint([y], 'y < 2')
+##         new_spc._process()
+##         assert spc.ask() == space.Alternative(2)
+##         assert new_spc.ask() == space.Succeeded
+
+    def test_clone(self):
+        """checks that a chain of initially s1 = s2
+           s1 - commit(1) - commit(1) ...
+           s2 - clone - commit(1) - clone - commit(1) ...
+           converges toward the same solution
+        """
+        s1 = newspace(problems.conference_scheduling)
+        s2 = s1
+
+        def eager_and(t1,  t2):
+            return t1 and t2
+
+        while not (eager_and(s2.ask() == space.Succeeded,
+                             s1.ask() == space.Succeeded)):
+            #print "S1", s1.pretty_doms()
+            #print "S2", s2.pretty_doms()
+            #assert s1 == s2
+            temp = s2.clone()
+            temp.ask()
+            assert temp.parent is s2
+            assert temp in s2.children
+            s2 = temp
+            s1.commit(1)
+            s2.commit(1)
 
     def test_inject(self):
         def more_constraints(space):
@@ -535,49 +550,81 @@
             space.add_constraint([y], 'y < 2')
 
         spc = newspace(problems.satisfiable_problem)
-        assert spc.ask() == space.Alternatives(2)
+        assert spc.ask() == space.Alternative(2)
         new_spc = spc.clone()
+        new_spc.ask()
         new_spc.inject(more_constraints)
-        assert spc.ask() == space.Alternatives(2)
+        assert spc.ask() == space.Alternative(2)
         assert new_spc.ask() == space.Succeeded
         
     def test_merge(self):
-        spc = newspace(problems.satisfiable_problem)
-        x, y, z = spc.find_vars('x', 'y', 'z')
-        print spc.doms
-        assert spc.top_level()
-        assert spc.dom(x) == c.FiniteDomain([-4, -2, -1, 0,
-                                             1, 2, 4])
-        assert spc.dom(y) == c.FiniteDomain([0, 2, 3,
-                                             4, 5, 16])
-        assert spc.dom(z) == c.FiniteDomain([-2, -1, 0,
-                                             1, 2])
-
         def more_constraints(space):
-            x, y, z = space.find_vars('x', 'y', 'z')
-            space.add_constraint([x], '3 > x > 1')
-            space.add_constraint([z, y], 'z == -1')
-            space.add_constraint([y], 'y == 3')
-
-        nspc = spc.clone()
-        nspc.inject(more_constraints)
-        x, y, z = nspc.find_vars('x', 'y', 'z')
-        assert not nspc.top_level()
-        for v in nspc.vars: print v, "==", v.val, nspc.dom(v)
-        assert nspc.dom(x) == c.FiniteDomain([2])
-        assert nspc.dom(y) == c.FiniteDomain([3])
-        assert nspc.dom(z) == c.FiniteDomain([-1])
-        assert nspc.ask() == space.Succeeded
-        nspc.merge()
-        assert x.val == 2
-        assert y.val == 3
-        assert z.val == -1
-        assert (x, y, z) == nspc.root.val
+            x, y, z = new_spc.find_vars('x', 'y', 'z')
+            space.add_constraint([x], 'x == 0')
+            space.add_constraint([z, y], 'z == y')
+            space.add_constraint([y], 'y < 2')
 
-    def test_scheduling_problem_dfs_one_solution(self):
+        spc = newspace(problems.satisfiable_problem)
+        assert spc.ask() == space.Alternative(2)
+        new_spc = spc.clone()
+        new_spc.ask()
+        new_spc.inject(more_constraints)
+        assert spc.ask() == space.Alternative(2)
+        assert new_spc.ask() == space.Succeeded
+        x, y, z = new_spc.find_vars('x', 'y', 'z')
+        res = new_spc.merge()
+        assert res.values() == [0, 0, 0]
+        
+    def test_scheduling_dfs_one_solution(self):
         sol = strategies.dfs_one(problems.conference_scheduling)
 
-        sol2 = [var.val for var in sol]
+        vars = sol.keys()
+        vars.sort()
+        sols = [ sol[k] for k in vars ]
+        result = [('room A', 'day 1 PM'),
+                  ('room A', 'day 2 AM'),
+                  ('room C', 'day 2 PM'),
+                  ('room C', 'day 2 AM'),
+                  ('room C', 'day 1 AM'),
+                  ('room C', 'day 1 PM'),
+                  ('room B', 'day 2 AM'),
+                  ('room B', 'day 1 AM'),
+                  ('room B', 'day 2 PM'),
+                  ('room A', 'day 1 AM'),
+                  ]
+
+        for v, r1, r2 in zip(vars, sols, result):
+            print v, r1, r2
+        assert sols == result
+
+
+    def test_scheduling_all_solutions(self):
+        sols = strategies.solve_all(problems.conference_scheduling)
+        assert len(sols) == 64
+        print sols
+
+    def no_test_sudoku(self):
+        #spc = newspace(problems.sudoku)
+        #print spc.constraints
+        def more_constraints(space):
+            f = 'puzzle1.su'
+            
+            file = open(f)
+            c = []
+            row = 1
+            for line in file.readlines():
+                for col in range(1,10):
+                    if line[col-1] != ' ':
+                        tup = ('v%d%d' % (col, row), int(line[col-1]))
+                        space.add_constraint([space.get_var_by_name(tup[0])],'%s == %d' % tup)
+                row += 1
+                
+        #nspc = spc.clone()
+        #nspc.inject(more_constraints)
+        #print nspc.constraints
+        sol2 = strategies.dfs_one(strategies.sudoku)
+        print "done dfs"
+        #sol2 = [var.val for var in sol]
         assert sol2 == [('room A', 'day 1 PM'),
                         ('room B', 'day 2 PM'),
                         ('room C', 'day 2 AM'),
@@ -590,9 +637,4 @@
                         ('room A', 'day 1 AM')]
 
 
-
-    def test_scheduling_problem_all_solutions(self):
-        sols = strategies.solve_all(problems.conference_scheduling)
-        assert len(sols) == 64
-
         

Modified: pypy/branch/njriley-trans/pypy/lib/logic/computation_space/test_variable.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/computation_space/test_variable.py	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/computation_space/test_variable.py	Fri Mar 10 06:12:02 2006
@@ -41,7 +41,52 @@
 
 #-- meat ----------------------------
 
-class TestVariable:
+class TestSimpleVariable:
+
+    def test_basics(self):
+        x = v.SimpleVar()
+        assert x.val == v.NoValue
+        x.bind(42)
+        assert x.val == 42
+        x.bind(42)
+        raises(v.AlreadyBound, x.bind, 43)
+
+    def test_dataflow(self):
+        def fun(thread, var):
+            thread.state = 1
+            v = var.get()
+            thread.state = v
+
+        x = v.SimpleVar()
+        t = FunThread(fun, x)
+        import time
+        t.start()
+        time.sleep(.5)
+        assert t.state == 1
+        x.bind(42)
+        t.join()
+        assert t.state == 42
+            
+    def test_stream(self):
+        def consummer(thread, S):
+            v = S.get()
+            if v:
+                thread.res += v[0]
+                consummer(thread, v[1])
+
+        S = v.SimpleVar()
+        t = FunThread(consummer, S)
+        t.res = 0
+        t.start()
+        for i in range(10):
+            tail = v.SimpleVar()
+            S.bind((i, tail))
+            S = tail
+        S.bind(None)
+        t.join()
+        assert t.res == 45
+
+class TestCsVariable:
 
     def test_no_same_name(self):
         sp = newspace()

Modified: pypy/branch/njriley-trans/pypy/lib/logic/computation_space/variable.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/computation_space/variable.py	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/computation_space/variable.py	Fri Mar 10 06:12:02 2006
@@ -1,4 +1,5 @@
 import threading
+import time
 
 #----------- Exceptions ---------------------------------
 class VariableException(Exception):
@@ -9,6 +10,16 @@
     def __str__(self):
         return "%s already in store" % self.name
 
+class AlreadyBound(Exception):
+    def __init__(self, var, val):
+        self.var = var
+        self.val = val
+    
+    def __str__(self):
+        return "%s:%s already bound to %s" % (self.var.name,
+                                              self.var.val,
+                                              self.val)
+
 class NotAVariable(VariableException):
     def __str__(self):
         return "%s is not a variable" % self.name
@@ -20,8 +31,74 @@
 
 class NoDom: pass
 
-class Var(object):
-    """Single-assignment variable"""
+class SimpleVar(object):
+    """Spaceless dataflow variable"""
+    
+    def __init__(self):
+        self.name = str(id(self))
+        self._val = NoValue
+        # a condition variable for concurrent access
+        self._value_condition = threading.Condition()
+
+    # value accessors
+    def _set_val(self, val):
+        self._value_condition.acquire()
+        try:
+            if self._val != NoValue:
+                if val != self._val:
+                    raise AlreadyBound(self, val)
+            self._val = val
+            self._value_condition.notifyAll()
+        finally:
+            self._value_condition.release()
+        
+    def _get_val(self):
+        return self._val
+    val = property(_get_val, _set_val)
+
+
+    # public interface
+
+    def is_bound(self):
+        return self.val != NoValue
+
+    def bind(self, val):
+        self.val = val
+
+    def get(self):
+        """Make threads wait on the variable
+           being bound in the top-level space
+        """
+        try:
+            self._value_condition.acquire()
+            while not self.is_bound():
+                t1 = time.time()
+                self._value_condition.wait(80)
+                t2 = time.time()
+                if t2-t1>80:
+                    raise RuntimeError("possible deadlock??")
+            return self.val
+        finally:
+            self._value_condition.release()
+
+
+    def reset(self):
+        self._value_condition.acquire()
+        self._val = NoValue
+        self._value_condition.release()
+
+
+class StreamVar(object):
+    def __init__(self):
+        self.var = SimpleVar()
+
+    def bind( self, val ):
+        newvar = SimpleVar()
+        self.var.bind( (val, newvar) )
+        
+
+class CsVar(SimpleVar):
+    """Dataflow variable linked to a space"""
 
     def __init__(self, name, cs):
         if name in cs.names:
@@ -56,13 +133,15 @@
     # value accessors
     def _set_val(self, val):
         self._value_condition.acquire()
-        if self._cs.in_transaction:
-            if not self._changed:
-                self._previous = self._val
-                self._changed = True
-        self._val = val
-        self._value_condition.notifyAll()
-        self._value_condition.release()
+        try:
+            if self._cs.in_transaction:
+                if not self._changed:
+                    self._previous = self._val
+                    self._changed = True
+            self._val = val
+            self._value_condition.notifyAll()
+        finally:
+            self._value_condition.release()
         
     def _get_val(self):
         return self._val
@@ -76,34 +155,8 @@
     def __repr__(self):
         return self.__str__()
 
-    def __eq__(self, thing):
-        return isinstance(thing, Var) \
-               and self.name == thing.name
-
-    def __hash__(self):
-        return self.name.__hash__()
-
     def bind(self, val):
-        """top-level space bind"""
+        """home space bind"""
         self._cs.bind(self, val)
 
     is_bound = _is_bound
-
-
-    #-- Dataflow ops with concurrent semantics ------
-    # should be used by threads that want to block on
-    # unbound variables
-
-    def get(self):
-        """Make threads wait on the variable
-           being bound in the top-level space
-        """
-        try:
-            self._value_condition.acquire()
-            while not self._is_bound():
-                self._value_condition.wait()
-            return self.val
-        finally:
-            self._value_condition.release()
-
-    

Modified: pypy/branch/njriley-trans/pypy/lib/logic/oz-dataflow-concurrency.txt
==============================================================================
--- pypy/branch/njriley-trans/pypy/lib/logic/oz-dataflow-concurrency.txt	(original)
+++ pypy/branch/njriley-trans/pypy/lib/logic/oz-dataflow-concurrency.txt	Fri Mar 10 06:12:02 2006
@@ -1,15 +1,18 @@
-Some rough notes about the Oz threading model
-=============================================
+====================================================================
+Some rough notes about the Oz threading model and dataflow variables
+====================================================================
 
 (almost verbatim from CTM)
 
+Threads
+=======
+
 Scheduling
 ----------
 
 Fair scheduling through round-robin.
 
-Needs not be deterministic (would be nice, especially when debugging,
-but probably impossible to achieve).
+Needs not be deterministic.
 
 With priority levels : three queues exist, which manage high, medium,
 low priority threads. The time slice ratio for these is
@@ -77,9 +80,9 @@
 
 The combination of threads and dataflow variables leads to implicit
 synchronization : that means synchronization is not textually visible
-in the source code but follow from the semantics of dataflow variables
-; using such a variable implies synchronization on the variable being
-bound to a value.
+in the source code but follow from the semantics of dataflow
+variables; using such a variable implies synchronization on the
+variable being bound to a value.
 
 Eager execution (the mere fact of executing statements as they present
 themselves to the interpreter, withou delay) plus dataflow vars also
@@ -94,7 +97,7 @@
 values can be seen as complete values that are only partially known").
 
 Dataflow variables
-------------------
+==================
 
 (see http://www.sics.se/~frej/flow_java/ for an implementation of
 dataflow variables in Java).
@@ -121,3 +124,57 @@
 values, provided the partial values are compatible (unifiable) with
 each other.
 
+Futures
+=======
+
+Dataflow variables are but one technique to implement dataflow
+execution. Another, quite popular technique is based on a slightly
+different concept, the single-assignment variable. Two of the
+best-known instances of the single-assignment variable are futures and
+I-structures. The purpose of futures and I-structures is to increase
+the potential parallelism of a program by removing inessential
+dependencies between calculations. They allow concurrency between a
+computation that calculates a value and one that uses the value. This
+concurrency can be exploited on a parallel machine. We define futures
+and I-structures and compare them with dataflow variables.
+
+Futures were first introduced in Multilisp, a language intended for
+writting parallel programs. Multilisp introduces the function call
+(future E) where E is any expression. This does two things: it
+immediately returns a placeholder for the result of E and it initiates
+a concurrent evaluation of E. When the value of E is needed, i.e., a
+computation tries to access the placeholder, then the computation
+blocks until the value is available. We model this as follows in the
+declarative concurrent model (where E is a zero-argument function) :
+
+fun {Future E}
+X in
+  thread X={E} end
+  !!X
+end
+
+A future can only be bound by the concurrent computation that is
+created along with it. This is enforced by returning a read-only
+variable. Multilisp also has a delay construct that does not initiate
+any evaluation but uses by-need execution. It causes evaluation of its
+argument only when the result is needed.  An I-structure (for
+"incomplete structure") is an array of single-assignment
+variables. Individual elements can be accessed before the elements are
+computed. I-structures were introduced as a language construct for
+writing parallel programs in dataflow machines, e.g., in the dataflow
+language Id. I-structures are also used in pH ("parallel Haskell"), a
+recent language design that extends Haskell for implicit
+parallelism. An I-structure permits concurrency between a computation
+that calculates the array elements and a computation that uses their
+values. When the value of an element is needed, then the computatio
+blocks until it is available. Like a future and a read-only variable,
+an element of an I-structure can only be bound by the computation that
+calculates it.  There is a fundamental difference between dataflow
+variables on one side and futures and I-structures on the other
+side. The latter can be bound only once, whereas dataflow variables
+can be bound more than once, as long as the bindings are consistent
+with each other. Two partial values are consistent if they are
+unifiable. A dataflow variable can be bound many times to different
+partial values as long as the partial values are unifiable.
+
+

Modified: pypy/branch/njriley-trans/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/module/__builtin__/__init__.py	(original)
+++ pypy/branch/njriley-trans/pypy/module/__builtin__/__init__.py	Fri Mar 10 06:12:02 2006
@@ -27,6 +27,8 @@
         # is still needed and should stay where it is.
         'min'           : 'app_functional.min',
         'max'           : 'app_functional.max',
+        'all'           : 'app_functional.all',
+        'any'           : 'app_functional.any',
         'enumerate'     : 'app_functional.enumerate',
         'xrange'        : 'app_functional.xrange',
         'sorted'        : 'app_functional.sorted',

Modified: pypy/branch/njriley-trans/pypy/module/__builtin__/app_functional.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/module/__builtin__/app_functional.py	(original)
+++ pypy/branch/njriley-trans/pypy/module/__builtin__/app_functional.py	Fri Mar 10 06:12:02 2006
@@ -258,6 +258,26 @@
     def __iter__(self):
         return self
 
+# ____________________________________________________________
+
+def all( it ):
+    """
+    Implementation of the all() builtin function from 2.5.
+    """
+    for i in it:
+        if not i:
+            return False
+    return True
+    
+def any( it ):
+    """
+    Implementation of the all() builtin function from 2.5.
+    """
+    for i in it:
+        if i:
+            return True
+    return False
+
 
 # ____________________________________________________________
 

Modified: pypy/branch/njriley-trans/pypy/module/__builtin__/test/test_functional.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/module/__builtin__/test/test_functional.py	(original)
+++ pypy/branch/njriley-trans/pypy/module/__builtin__/test/test_functional.py	Fri Mar 10 06:12:02 2006
@@ -7,7 +7,7 @@
       assert map(lambda x: x+2, [1, 2, 3, 4]) == [3, 4, 5, 6]
 
    def test_trivial_map_two_seq(self):
-      assert map(lambda x,y: x+y, 
+      assert map(lambda x,y: x+y,
                            [1, 2, 3, 4],[1, 2, 3, 4]) == (
                        [2, 4, 6, 8])
 
@@ -16,23 +16,23 @@
 
    def test_trivial_map_no_arguments(self):
       raises(TypeError, map)
-      
+
    def test_trivial_map_no_function_no_seq(self):
       raises(TypeError, map, None)
 
    def test_trivial_map_no_fuction_one_seq(self):
       assert map(None, [1, 2, 3]) == [1, 2, 3]
-      
+
    def test_trivial_map_no_function(self):
       assert map(None, [1,2,3], [4,5,6], [7,8], [1]) == (
                        [(1, 4, 7, 1), (2, 5, 8, None), (3, 6, None, None)])
-                       
+
    def test_map_identity1(self):
       a = ['1', 2, 3, 'b', None]
       b = a[:]
       assert map(lambda x: x, a) == a
       assert a == b
- 
+
    def test_map_None(self):
       a = ['1', 2, 3, 'b', None]
       b = a[:]
@@ -72,7 +72,7 @@
    def test_sum(self):
        assert reduce(lambda x, y: x+y, [1,2,3,4], 0) == 10
        assert reduce(lambda x, y: x+y, [1,2,3,4]) == 10
-   
+
    def test_minus(self):
        assert reduce(lambda x, y: x-y, [10, 2, 8]) == 0
        assert reduce(lambda x, y: x-y, [2, 8], 10) == 0
@@ -86,7 +86,7 @@
        assert filter(None, txt) == txt
        tup = ("a", None, 0, [], 1)
        assert filter(None, tup) == ("a", 1)
-       
+
    def test_function(self):
        assert filter(lambda x: x != "a", "a small text") == " smll text"
 
@@ -131,3 +131,54 @@
       assert len(r) == 0
       assert list(reversed(list(reversed("hello")))) == ['h','e','l','l','o']
       raises(TypeError, reversed, reversed("hello"))
+
+
+class AppTestAllAny:
+    """
+    These are copied directly and replicated from the Python 2.5 source code.
+    """
+
+    def test_all(self):
+
+        class TestFailingBool:
+            def __nonzero__(self):
+                raise RuntimeError
+        class TestFailingIter:
+            def __iter__(self):
+                raise RuntimeError
+
+        assert all([2, 4, 6]) == True
+        assert all([2, None, 6]) == False
+        raises(RuntimeError, all, [2, TestFailingBool(), 6])
+        raises(RuntimeError, all, TestFailingIter())
+        raises(TypeError, all, 10)               # Non-iterable
+        raises(TypeError, all)                   # No args
+        raises(TypeError, all, [2, 4, 6], [])    # Too many args
+        assert all([]) == True                   # Empty iterator
+        S = [50, 60]
+        assert all(x > 42 for x in S) == True
+        S = [50, 40, 60]
+        assert all(x > 42 for x in S) == False
+
+    def test_any(self):
+
+        class TestFailingBool:
+            def __nonzero__(self):
+                raise RuntimeError
+        class TestFailingIter:
+            def __iter__(self):
+                raise RuntimeError
+
+        assert any([None, None, None]) == False
+        assert any([None, 4, None]) == True
+        raises(RuntimeError, any, [None, TestFailingBool(), 6])
+        raises(RuntimeError, all, TestFailingIter())
+        raises(TypeError, any, 10)               # Non-iterable
+        raises(TypeError, any)                   # No args
+        raises(TypeError, any, [2, 4, 6], [])    # Too many args
+        assert any([]) == False                  # Empty iterator
+        S = [40, 60, 30]
+        assert any(x > 42 for x in S) == True
+        S = [10, 20, 30]
+        assert any(x > 42 for x in S) == False
+

Modified: pypy/branch/njriley-trans/pypy/module/recparser/pyparser.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/module/recparser/pyparser.py	(original)
+++ pypy/branch/njriley-trans/pypy/module/recparser/pyparser.py	Fri Mar 10 06:12:02 2006
@@ -10,7 +10,7 @@
 from pypy.interpreter.pyparser.syntaxtree import TokenNode, SyntaxNode, AbstractSyntaxVisitor
 from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER
 from pypy.interpreter.pyparser.error import SyntaxError
-from pypy.interpreter.pyparser import grammar, pysymbol, pytoken
+from pypy.interpreter.pyparser import grammar, symbol, pytoken
 from pypy.interpreter.argument import Arguments
 
 
@@ -94,14 +94,14 @@
         Returns true if the root node in the syntax tree is an expr node,
         false otherwise.
         """
-        return self.node.name == pysymbol.eval_input
+        return self.node.name == symbol.eval_input
 
     def issuite(self):
         """STType.issuite()
         Returns true if the root node in the syntax tree is a suite node,
         false otherwise.
         """
-        return self.node.name == pysymbol.file_input
+        return self.node.name == symbol.file_input
 
     def descr_compile(self, w_filename = "<syntax_tree>"):
         """STType.compile()
@@ -226,8 +226,8 @@
 
 def descr_grammarelement_repr( self, space ):
     """TODO: make __repr__ RPython"""
-    import pysymbol
-    return space.wrap( self.display(0, pysymbol.sym_name) )
+    import symbol
+    return space.wrap( self.display(0, symbol.sym_name) )
 
 def descr_grammarelement_get_children( self, space ):
     return space.newlist( [ space.wrap(it) for it in self.args ] )

Modified: pypy/branch/njriley-trans/pypy/module/stackless/test/test_interp_coroutine.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/module/stackless/test/test_interp_coroutine.py	(original)
+++ pypy/branch/njriley-trans/pypy/module/stackless/test/test_interp_coroutine.py	Fri Mar 10 06:12:02 2006
@@ -209,3 +209,81 @@
     
     data = wrap_stackless_function(f)
     assert int(data.strip()) == 4711
+
+def test_tree_compare():
+    class Node:
+        def __init__(self, value, left=None, right=None):
+            self.value = value
+            self.left = left
+            self.right = right
+        def __repr__(self):
+            return 'Node(%r, %r, %r)'%(self.value, self.left, self.right)
+
+    tree1 = Node(1, Node(2, Node(3)))
+    tree2 = Node(1, Node(3, Node(2)))
+    tree3 = Node(1, Node(2), Node(3))
+    
+    class Super:
+        pass
+    class Producer(Super):
+        def __init__(self, tree, objects, consumer):
+            self.tree = tree
+            self.objects = objects
+            self.consumer = consumer
+        def produce(self, t):
+            if t is None:
+                return
+            self.objects.append(t.value)
+            self.consumer.switch()
+            self.produce(t.left)
+            self.produce(t.right)
+        def call(self):
+            self.produce(self.tree)
+            while 1:
+                self.consumer.switch()
+    class Consumer(Super):
+        def __init__(self, tree, objects, producer):
+            self.tree = tree
+            self.objects = objects
+            self.producer = producer
+        def consume(self, t):
+            if t is None:
+                return True
+            self.producer.switch()
+            if not self.objects:
+                return False
+            if self.objects.pop(0) != t.value:
+                return False
+            if not self.consume(t.left):
+                return False
+            return self.consume(t.right)
+            
+        def call(self):
+            self.result = self.consume(self.tree)
+            costate.main.switch()
+
+    def pre_order_eq(t1, t2):
+        objects = []
+        producer = Coroutine()
+        consumer = Coroutine()
+        
+        producer.bind(Producer(t1, objects, consumer))
+        cons = Consumer(t2, objects, producer)
+        consumer.bind(cons)
+
+        consumer.switch()
+
+        return cons.result
+
+    def ep():
+        return "%d %d %d %d"%(pre_order_eq(tree1, tree2),
+                              pre_order_eq(tree1, tree1),
+                              pre_order_eq(tree1, tree3),
+                              pre_order_eq(tree2, tree1),
+
+                              )
+    
+    output = wrap_stackless_function(ep)
+    assert output.strip() == '0 1 1 0'
+            
+            

Modified: pypy/branch/njriley-trans/pypy/module/symbol/__init__.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/module/symbol/__init__.py	(original)
+++ pypy/branch/njriley-trans/pypy/module/symbol/__init__.py	Fri Mar 10 06:12:02 2006
@@ -21,10 +21,10 @@
 # Export the values from our custom symbol module.
 # Skip negative values (the corresponding symbols are not visible in
 # pure Python).
-from pypy.interpreter.pyparser import pysymbol
+from pypy.interpreter.pyparser.pythonparse import PYTHON_PARSER
 
 sym_name = {}
-for val, name in pysymbol._cpython_symbols.sym_name.items():
+for val, name in PYTHON_PARSER.symbols.sym_name.items():
     if val >= 0:
         Module.interpleveldefs[name] = 'space.wrap(%d)' % val
         sym_name[val] = name

Modified: pypy/branch/njriley-trans/pypy/objspace/flow/model.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/objspace/flow/model.py	(original)
+++ pypy/branch/njriley-trans/pypy/objspace/flow/model.py	Fri Mar 10 06:12:02 2006
@@ -171,7 +171,7 @@
         self.exc_handler = False          # block at the start of exception handling code
 
     def at(self):
-        if self.operations:
+        if self.operations and self.operations[0].offset >= 0:
             return "@%d" % self.operations[0].offset
         else:
             return ""

Modified: pypy/branch/njriley-trans/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/objspace/flow/objspace.py	(original)
+++ pypy/branch/njriley-trans/pypy/objspace/flow/objspace.py	Fri Mar 10 06:12:02 2006
@@ -508,8 +508,12 @@
     the func_closure of a function object."""
     # yuk! this is all I could come up with that works in Python 2.2 too
     class X(object):
+        def __cmp__(self, other):
+            self.other = other
+            return 0
         def __eq__(self, other):
             self.other = other
+            return True
     x = X()
     x_cell, = (lambda: x).func_closure
     x_cell == c

Modified: pypy/branch/njriley-trans/pypy/objspace/flow/test/test_objspace.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/objspace/flow/test/test_objspace.py	(original)
+++ pypy/branch/njriley-trans/pypy/objspace/flow/test/test_objspace.py	Fri Mar 10 06:12:02 2006
@@ -4,6 +4,7 @@
 from pypy.interpreter.argument import Arguments
 from pypy.translator.simplify import simplify_graph
 from pypy.objspace.flow import FlowObjSpace 
+from pypy.objspace.flow import objspace
 
 import os
 import operator
@@ -641,3 +642,14 @@
 
 def user_defined_function():
     pass
+
+
+def test_extract_cell_content():
+    class Strange(object):
+        def __cmp__(self, other):
+            assert False, "should not be called"
+    strange = Strange()
+    def f():
+        return strange
+    res = objspace.extract_cell_content(f.func_closure[0])
+    assert res is strange

Modified: pypy/branch/njriley-trans/pypy/rpython/callparse.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/callparse.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/callparse.py	Fri Mar 10 06:12:02 2006
@@ -26,18 +26,21 @@
             getrinputs(rtyper, graph),
             getrresult(rtyper, graph))
 
-def callparse(rtyper, graph, hop, opname):
+def callparse(rtyper, graph, hop, opname, is_method=False):
     """Parse the arguments of 'hop' when calling the given 'graph'.
     """
     rinputs = getrinputs(rtyper, graph)
     space = RPythonCallsSpace()
     def args_h(start):
-        return [VarHolder(i, hop.args_s[i]) for i in range(start, hop.nb_args)]
+        return [VarHolder(i, hop.args_s[i])
+                        for i in range(start, hop.nb_args)]
+    start = 1 - is_method
     if opname == "simple_call":
-        arguments =  Arguments(space, args_h(1))
+        arguments =  Arguments(space, args_h(start))
     elif opname == "call_args":
-        arguments = Arguments.fromshape(space, hop.args_s[1].const, # shape
-                                        args_h(2))
+        arguments = Arguments.fromshape(space,
+                hop.args_s[start].const, # shape
+                args_h(start+1))
     # parse the arguments according to the function we are calling
     signature = graph.signature
     defs_h = []

Modified: pypy/branch/njriley-trans/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/llinterp.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/llinterp.py	Fri Mar 10 06:12:02 2006
@@ -256,9 +256,25 @@
         # if these special cases pile up, do something better here
         if operation.opname in ['cast_pointer', 'ooupcast', 'oodowncast', 'cast_adr_to_ptr']:
             vals.insert(0, operation.result.concretetype)
-        retval = ophandler(*vals)
+        try:
+            retval = ophandler(*vals)
+        except LLException:
+            self.handle_cleanup(operation, exception=True)
+            raise
+        else:
+            self.handle_cleanup(operation)
         self.setvar(operation.result, retval)
 
+    def handle_cleanup(self, operation, exception=False):
+        cleanup = getattr(operation, 'cleanup', None)
+        if cleanup is not None:
+            cleanup_finally, cleanup_except = cleanup
+            for op in cleanup_finally:
+                self.eval_operation(op)
+            if exception:
+                for op in cleanup_except:
+                    self.eval_operation(op)
+
     def make_llexception(self, exc=None):
         if exc is None:
             original = sys.exc_info()
@@ -744,6 +760,9 @@
         assert isinstance(INST, ootype.Instance)
         return ootype.new(INST)
 
+    def op_runtimenew(self, class_):
+        return ootype.runtimenew(class_)
+
     def op_oosetfield(self, inst, name, value):
         assert isinstance(inst, ootype._instance)
         assert isinstance(name, str)
@@ -776,11 +795,16 @@
         assert isinstance(inst, ootype._instance)
         return bool(inst)
 
-    def op_oois(self, inst1, inst2):
-        assert isinstance(inst1, ootype._instance)
-        assert isinstance(inst2, ootype._instance)
-        return inst1 == inst2   # NB. differently-typed NULLs must be equal
-
+    def op_oois(self, obj1, obj2):
+        if isinstance(obj1, ootype._instance):
+            assert isinstance(obj2, ootype._instance)
+            return obj1 == obj2   # NB. differently-typed NULLs must be equal
+        elif isinstance(obj1, ootype._class):
+            assert isinstance(obj2, ootype._class)
+            return obj1 is obj2
+        else:
+            assert False, "oois on something silly"
+            
     def op_instanceof(self, inst, INST):
         return ootype.instanceof(inst, INST)
 
@@ -790,11 +814,6 @@
     def op_subclassof(self, class1, class2):
         return ootype.subclassof(class1, class2)
 
-    def op_oosameclass(self, class1, class2):
-        assert isinstance(class1, ootype._class)
-        assert isinstance(class2, ootype._class)
-        return class1 is class2
-
     def op_ooidentityhash(self, inst):
         return ootype.ooidentityhash(inst)
 

Modified: pypy/branch/njriley-trans/pypy/rpython/lltypesystem/exceptiondata.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/lltypesystem/exceptiondata.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/lltypesystem/exceptiondata.py	Fri Mar 10 06:12:02 2006
@@ -4,25 +4,12 @@
 from pypy.rpython.lltypesystem.lltype import \
      Array, malloc, Ptr, PyObject, pyobjectptr, \
      FuncType, functionptr, Signed
+from pypy.rpython.exceptiondata import AbstractExceptionData
 from pypy.rpython.extfunctable import standardexceptions
 from pypy.annotation.classdef import FORCE_ATTRIBUTES_INTO_CLASSES
 
-class ExceptionData:
+class ExceptionData(AbstractExceptionData):
     """Public information for the code generators to help with exceptions."""
-    standardexceptions = standardexceptions
-
-    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 functionptrs
@@ -31,14 +18,6 @@
         self.fn_pyexcclass2exc   = self.make_pyexcclass2exc(rtyper)
         self.fn_raise_OSError    = self.make_raise_OSError(rtyper)
 
-
-    def make_standard_exceptions(self, rtyper):
-        bk = rtyper.annotator.bookkeeper
-        for cls in self.standardexceptions:
-            classdef = bk.getuniqueclassdef(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)

Modified: pypy/branch/njriley-trans/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/lltypesystem/llmemory.py	Fri Mar 10 06:12:02 2006
@@ -89,6 +89,20 @@
     def set(self, ob, value):
         raise Exception("can't assign to an array's items")
 
+class ArrayLengthOffset(AddressOffset):
+
+    def __init__(self, TYPE):
+        self.TYPE = TYPE
+
+    def __repr__(self):
+        return '< ArrayLengthOffset >'
+
+    def get(self, ob):
+        return len(ob)
+
+    def set(self, ob, value):
+        raise Exception("can't assign to an array's length")
+
 
 def sizeof(TYPE, n=None):
     if n is None:

Modified: pypy/branch/njriley-trans/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/lltypesystem/lltype.py	Fri Mar 10 06:12:02 2006
@@ -64,6 +64,8 @@
     def __ne__(self, other):
         return not (self == other)
 
+    _is_compatible = __eq__
+
     def __hash__(self):
         # cannot use saferecursive() -- see test_lltype.test_hash().
         # NB. the __cached_hash should neither be used nor updated
@@ -738,7 +740,12 @@
 
     def __len__(self):
         if isinstance(self._T, Array):
+            if self._T._hints.get('nolength', False):
+                raise TypeError("%r instance has no length attribute" %
+                                    (self._T,))
+
             return len(self._obj.items)
+
         raise TypeError("%r instance is not an array" % (self._T,))
 
     def __repr__(self):
@@ -1095,6 +1102,7 @@
     return result
 
 def isCompatibleType(TYPE1, TYPE2):
+    return TYPE1._is_compatible(TYPE2)
     return TYPE1 == TYPE2
 
 # mark type ADT methods
@@ -1102,5 +1110,30 @@
 def typeMethod(func):
     func._type_method = True
     return func
-    
 
+def dissect_ll_instance(v, t=None, memo=None):
+    if memo is None:
+        memo = {}
+    if id(v) in memo:
+        return
+    memo[id(v)] = True
+    if t is None:
+        t = typeOf(v)
+    yield t, v
+    if isinstance(t, Ptr):
+        if v._obj:
+            for i in dissect_ll_instance(v._obj, t.TO, memo):
+                yield i
+    elif isinstance(t, Struct):
+        parent = v._parentstructure()
+        if parent:
+            for i in dissect_ll_instance(parent, typeOf(parent), memo):
+                yield i
+        for n in t._flds:
+            f = getattr(t, n)
+            for i in dissect_ll_instance(getattr(v, n), t._flds[n], memo):
+                yield i
+    elif isinstance(t, Array):
+        for item in v.items:
+            for i in dissect_ll_instance(item, t.OF, memo):
+                yield i

Modified: pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rclass.py	Fri Mar 10 06:12:02 2006
@@ -224,6 +224,8 @@
         return llops.genop('cast_pointer', [vcls],
                            resulttype=self.lowleveltype)
 
+    fromclasstype = fromtypeptr
+
     def getclsfield(self, vcls, attr, llops):
         """Read the given attribute of 'vcls'."""
         if attr in self.clsfields:
@@ -366,32 +368,14 @@
     def getflavor(self):
         return self.classdef.classdesc.read_attribute('_alloc_flavor_', Constant('gc')).value
 
-    def convert_const(self, value):
-        if value is None:
-            return nullptr(self.object_type)
-        if isinstance(value, types.MethodType):
-            value = value.im_self   # bound method -> instance
-        cls = value.__class__
-        bk = self.rtyper.annotator.bookkeeper
-        classdef = bk.getdesc(cls).getuniqueclassdef()
-        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.commonbase(self.classdef) != self.classdef:
-                raise TyperError("not an instance of %r: %r" % (
-                    self.classdef.name, 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, flavor=self.getflavor()) # pick flavor
-            self.prebuiltinstances[id(value)] = value, result
-            self.initialize_prebuilt_instance(value, classdef, result)
-            return result
+    def null_instance(self):
+        return nullptr(self.object_type)
+
+    def upcast(self, result):
+        return cast_pointer(self.lowleveltype, result)
+
+    def create_instance(self):
+        return malloc(self.object_type, flavor=self.getflavor()) # pick flavor
 
     def get_ll_eq_function(self):
         return ll_inst_eq

Modified: pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rpbc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rpbc.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rpbc.py	Fri Mar 10 06:12:02 2006
@@ -7,12 +7,13 @@
      typeOf, Void, ForwardReference, Struct, Bool, \
      Ptr, malloc, nullptr
 from pypy.rpython.rmodel import Repr, TyperError, inputconst, inputdesc
-from pypy.rpython.rmodel import warning, mangle, CanBeNull
 from pypy.rpython import robject
 from pypy.rpython import rtuple
-from pypy.rpython.rpbc import SingleFrozenPBCRepr, samesig,\
-     commonbase, allattributenames, FunctionsPBCRepr, \
-     AbstractClassesPBCRepr, AbstractMethodsPBCRepr, OverriddenFunctionPBCRepr
+from pypy.rpython.rpbc import samesig,\
+     commonbase, allattributenames, adjust_shape, \
+     AbstractClassesPBCRepr, AbstractMethodsPBCRepr, OverriddenFunctionPBCRepr, \
+     AbstractMultipleFrozenPBCRepr, MethodOfFrozenPBCRepr, \
+     AbstractFunctionsPBCRepr
 from pypy.rpython.lltypesystem import rclass
 from pypy.tool.sourcetools import has_varargs
 
@@ -26,7 +27,7 @@
     
 # ____________________________________________________________
 
-class MultipleFrozenPBCRepr(CanBeNull, Repr):
+class MultipleFrozenPBCRepr(AbstractMultipleFrozenPBCRepr):
     """Representation selected for multiple non-callable pre-built constants."""
     def __init__(self, rtyper, access_set):
         self.rtyper = rtyper
@@ -36,159 +37,38 @@
         self.pbc_cache = {}
 
     def _setup_repr(self):
-        llfields = []
-        llfieldmap = {}
-        if self.access_set is not None:
-            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 = mangle('pbc', attr)
-                llfields.append((mangled_name, r_value.lowleveltype))
-                llfieldmap[attr] = mangled_name, r_value
+        llfields = self._setup_repr_fields()
         self.pbc_type.become(Struct('pbc', *llfields))
-        self.llfieldmap = llfieldmap
 
-    def convert_desc(self, frozendesc):
-        if (self.access_set is not None and
-            frozendesc not in self.access_set.descs):
-            raise TyperError("not found in PBC access set: %r" % (frozendesc,))
-        try:
-            return self.pbc_cache[frozendesc]
-        except KeyError:
-            self.setup()
-            result = malloc(self.pbc_type, immortal=True)
-            self.pbc_cache[frozendesc] = result
-            for attr, (mangled_name, r_value) in self.llfieldmap.items():
-                if r_value.lowleveltype is Void:
-                    continue
-                try:
-                    thisattrvalue = frozendesc.read_attribute(attr)
-                except AttributeError:
-                    warning("Desc %r has no attribute %r" % (frozendesc, attr))
-                    continue
-                llvalue = r_value.convert_const(thisattrvalue)
-                setattr(result, mangled_name, llvalue)
-            return result
-
-    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
-        frozendesc = self.rtyper.annotator.bookkeeper.getdesc(pbc)
-        return self.convert_desc(frozendesc)
-
-    def rtype_getattr(self, hop):
-        attr = hop.args_s[1].const
-        vpbc, vattr = hop.inputargs(self, Void)
-        v_res = self.getfield(vpbc, attr, hop.llops)
-        mangled_name, r_res = self.llfieldmap[attr]
-        return hop.llops.convertvar(v_res, r_res, hop.r_result)
+    def create_instance(self):
+        return malloc(self.pbc_type, immortal=True)
+
+    def null_instance(self):
+        return nullptr(self.pbc_type)
 
     def getfield(self, vpbc, attr, llops):
-        mangled_name, r_value = self.llfieldmap[attr]
+        mangled_name, r_value = self.fieldmap[attr]
         cmangledname = inputconst(Void, mangled_name)
         return llops.genop('getfield', [vpbc, cmangledname],
                            resulttype = r_value)
 
-class __extend__(pairtype(MultipleFrozenPBCRepr, MultipleFrozenPBCRepr)):
-    def convert_from_to((r_pbc1, r_pbc2), v, llops):
-        if r_pbc1.access_set == r_pbc2.access_set:
-            return v
-        return NotImplemented
-
-class __extend__(pairtype(SingleFrozenPBCRepr, MultipleFrozenPBCRepr)):
-    def convert_from_to((r_pbc1, r_pbc2), v, llops):
-        frozendesc1 = r_pbc1.frozendesc
-        access = frozendesc1.queryattrfamily()
-        if access is r_pbc2.access_set:
-            return inputdesc(r_pbc2, frozendesc1)
-        return NotImplemented
-
 # ____________________________________________________________
 
+class FunctionsPBCRepr(AbstractFunctionsPBCRepr):
+    """Representation selected for a PBC of function(s)."""
 
-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.funcdesc = s_pbc.descriptions.keys()[0].funcdesc
-
-        # a hack to force the underlying function to show up in call_families
-        # (generally not needed, as normalizecalls() should ensure this,
-        # but needed for bound methods that are ll helpers)
-        # XXX sort this out
-        #call_families = rtyper.annotator.getpbccallfamilies()
-        #call_families.find((None, self.function))
+    def setup_specfunc(self):
+        fields = []
+        for row in self.uniquerows:
+            fields.append((row.attrname, row.fntype))
+        return Ptr(Struct('specfunc', *fields))
         
-        if s_pbc.can_be_none():
-            raise TyperError("unsupported: variable of type "
-                             "method-of-frozen-PBC or None")
-
-        im_selves = []
-        for desc in s_pbc.descriptions:
-            assert desc.funcdesc is self.funcdesc
-            im_selves.append(desc.frozendesc)
-            
-        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 get_s_callable(self):
-        return annmodel.SomePBC([self.funcdesc])
-
-    def get_r_implfunc(self):
-        r_func = self.rtyper.getrepr(self.get_s_callable())
-        return r_func, 1
-
-    def convert_desc(self, mdesc):
-        if mdesc.funcdesc is not self.funcdesc:
-            raise TyperError("not a method bound on %r: %r" % (self.funcdesc, 
-                                                               mdesc))
-        return self.r_im_self.convert_desc(mdesc.frozendesc)
-
-    def convert_const(self, method):
-        mdesc = self.rtyper.annotator.bookkeeper.getdesc(method)
-        return self.convert_desc(mdesc)
-
-    def rtype_simple_call(self, hop):
-        return self.redispatch_call(hop, call_args=False)
-
-    def rtype_call_args(self, hop):
-        return self.redispatch_call(hop, call_args=True)
-
-    def redispatch_call(self, hop, call_args):
-        # XXX obscure, try to refactor...
-        s_function = annmodel.SomePBC([self.funcdesc])
-        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):
-            boundmethod = hop2.args_v[0].value
-            hop2.args_v[0] = Constant(boundmethod.im_self)
-        if call_args:
-            hop2.swap_fst_snd_args()
-            _, s_shape = hop2.r_s_popfirstarg() # temporarely remove shape
-            adjust_shape(hop2, s_shape)
-        # a marker that would crash if actually used...
-        c = Constant("obscure-don't-use-me")
-        hop2.v_s_insertfirstarg(c, s_function)   # insert 'function'
-        # now hop2 looks like simple_call(function, self, args...)
-        return hop2.dispatch()
-
-def adjust_shape(hop2, s_shape):
-    new_shape = (s_shape.const[0]+1,) + s_shape.const[1:]
-    c_shape = Constant(new_shape)
-    s_shape = hop2.rtyper.annotator.bookkeeper.immutablevalue(new_shape)
-    hop2.v_s_insertfirstarg(c_shape, s_shape) # reinsert adjusted shape
-    
-# ____________________________________________________________
+    def create_specfunc(self):
+        return malloc(self.lowleveltype.TO, immortal=True)
 
+    def get_specfunc_row(self, llop, v, c_rowname, resulttype):
+        return llop.genop('getfield', [v, c_rowname], resulttype=resulttype)
+        
 class MethodsPBCRepr(AbstractMethodsPBCRepr):
     """Representation selected for a PBC of the form {func: classdef...}.
     It assumes that all the methods come from the same name in a base
@@ -201,7 +81,6 @@
         return self.redispatch_call(hop, call_args=True)
 
     def redispatch_call(self, hop, call_args):
-        hop2 = hop.copy()
         r_class = self.r_im_self.rclass
         mangled_name, r_func = r_class.clsfields[self.methodname]
         assert isinstance(r_func, (FunctionsPBCRepr,
@@ -214,14 +93,9 @@
         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.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')
-
+        hop2 = self.add_instance_arg_to_hop(hop, call_args)
         opname = 'simple_call'
         if call_args:
-            hop2.swap_fst_snd_args()
-            _, s_shape = hop2.r_s_popfirstarg()
-            adjust_shape(hop2, s_shape)
             opname = 'call_args'
 
         hop2.v_s_insertfirstarg(v_func, s_func)   # insert 'function'
@@ -275,14 +149,8 @@
             assert hop.nb_args == 1, ("arguments passed to __init__, "
                                       "but no __init__!")
         else:
-            hop2 = hop.copy()
-            hop2.r_s_popfirstarg()   # discard the class pointer argument
-            if call_args:
-                _, s_shape = hop2.r_s_popfirstarg() # temporarely remove shape
-                hop2.v_s_insertfirstarg(v_instance, s_instance)  # add 'instance'
-                adjust_shape(hop2, s_shape)
-            else:
-                hop2.v_s_insertfirstarg(v_instance, s_instance)  # add 'instance'
+            hop2 = self.replace_class_with_inst_arg(
+                    hop, v_instance, s_instance, call_args)
             hop2.v_s_insertfirstarg(v_init, s_init)   # add 'initfunc'
             hop2.s_result = annmodel.s_None
             hop2.r_result = self.rtyper.getrepr(hop2.s_result)

Modified: pypy/branch/njriley-trans/pypy/rpython/lltypesystem/test/test_lloperation.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/lltypesystem/test/test_lloperation.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/lltypesystem/test/test_lloperation.py	Fri Mar 10 06:12:02 2006
@@ -11,6 +11,7 @@
                                              name == 'op_subclassof' or
                                              name == 'op_instanceof' or
                                              name == 'op_classof' or
+                                             name == 'op_runtimenew' or
                                              name.startswith('op_oo'))]
 
 

Modified: pypy/branch/njriley-trans/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/lltypesystem/test/test_lltype.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/lltypesystem/test/test_lltype.py	Fri Mar 10 06:12:02 2006
@@ -508,3 +508,41 @@
          assert typeOf(res) == TGT
          assert res == expect
         
+def test_array_with_no_length():
+    A = GcArray(Signed, hints={'nolength': True})
+    a = malloc(A, 10)
+    py.test.raises(TypeError, len, a)
+
+def test_dissect_ll_instance():
+    assert list(dissect_ll_instance(1)) == [(Signed, 1)]
+    GcS = GcStruct("S", ('x', Signed))
+    s = malloc(GcS)
+    s.x = 1
+    assert list(dissect_ll_instance(s)) == [(Ptr(GcS), s), (GcS, s._obj), (Signed, 1)]
+    
+    A = GcArray(('x', Signed))
+    a = malloc(A, 10)
+    for i in range(10):
+        a[i].x = i
+    expected = [(Ptr(A), a), (A, a._obj)]
+    for t in [((A.OF, a._obj.items[i]), (Signed, i)) for i in range(10)]:
+        expected.extend(t)
+    assert list(dissect_ll_instance(a)) == expected
+
+    R = GcStruct("R", ('r', Ptr(GcForwardReference())))
+    R.r.TO.become(R)
+
+    r = malloc(R)
+    r.r = r
+    r_expected = [(Ptr(R), r), (R, r._obj)]
+    assert list(dissect_ll_instance(r)) == r_expected
+
+    B = GcArray(Ptr(R))
+    b = malloc(B, 2)
+    b[0] = b[1] = r
+    b_expected = [(Ptr(B), b), (B, b._obj)]
+    assert list(dissect_ll_instance(b)) == b_expected + r_expected
+
+    memo = {}
+    assert list(dissect_ll_instance(r, None, memo)) == r_expected
+    assert list(dissect_ll_instance(b, None, memo)) == b_expected

Modified: pypy/branch/njriley-trans/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/memory/gc.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/memory/gc.py	Fri Mar 10 06:12:02 2006
@@ -87,7 +87,7 @@
 
     def __init__(self, dummy=None, get_roots=None):
         self.get_roots = get_roots
-        self.set_query_functions(None, None, None, None, None, None, None)
+        #self.set_query_functions(None, None, None, None, None, None, None)
    
     def malloc(self, typeid, length=0):
         size = self.fixed_size(typeid)
@@ -115,7 +115,7 @@
         #need to maintain a list of malloced objects, since we used the systems
         #allocator and can't walk the heap
         self.malloced_objects = AddressLinkedList()
-        self.set_query_functions(None, None, None, None, None, None, None)
+        #self.set_query_functions(None, None, None, None, None, None, None)
         self.get_roots = get_roots
 
     def malloc(self, typeid, length=0):
@@ -127,6 +127,8 @@
         size_gc_header = self.size_gc_header()
         result = raw_malloc(size + size_gc_header)
 ##         print "mallocing %s, size %s at %s" % (typeid, size, result)
+        if self.is_varsize(typeid):        
+            (result + self.varsize_offset_to_length(typeid)).signed[0] = length
         self.init_gc_object(result, typeid)
         self.malloced_objects.append(result)
         self.bytes_malloced += size + size_gc_header
@@ -224,7 +226,7 @@
         self.top_of_space = self.tospace + space_size
         self.fromspace = raw_malloc(space_size)
         self.free = self.tospace
-        self.set_query_functions(None, None, None, None, None, None, None)
+        #self.set_query_functions(None, None, None, None, None, None, None)
         self.get_roots = get_roots
 
     def free_memory(self):
@@ -359,7 +361,7 @@
         self.zero_ref_counts = AddressLinkedList()
         self.length_zero_ref_counts = 0
         self.max_refcount_zero = max_refcount_zero
-        self.set_query_functions(None, None, None, None, None, None, None)
+        #self.set_query_functions(None, None, None, None, None, None, None)
         self.get_roots = get_roots
         self.collecting = False
 

Modified: pypy/branch/njriley-trans/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/memory/gctransform.py	Fri Mar 10 06:12:02 2006
@@ -88,10 +88,20 @@
             for var in block.inputargs:
                 if var_needsgc(var):
                     newops.extend(self.push_alive(var))
+        # XXX this is getting obscure.  Maybe we should use the basic
+        # graph-transforming capabilities of the RTyper instead, as we
+        # seem to run into all the same problems as the ones we already
+        # had to solve there.
+        num_ops_after_exc_raising = 0
         for op in block.operations:
-            ops, cleanup_before_exception = self.replacement_operations(op, livevars)
+            num_ops_after_exc_raising = 0
+            res = self.replacement_operations(op, livevars)
+            try:
+                ops, cleanup_before_exception = res
+            except ValueError:
+                ops, cleanup_before_exception, num_ops_after_exc_raising = res
             newops.extend(ops)
-            op = ops[-1]
+            op = ops[-1-num_ops_after_exc_raising]
             # XXX for now we assume that everything can raise
             if 1 or op.opname in EXCEPTION_RAISING_OPS:
                 if tuple(livevars) in livevars2cleanup:
@@ -103,9 +113,12 @@
                     cleanup_on_exception = tuple(cleanup_on_exception)
                     livevars2cleanup[tuple(livevars)] = cleanup_on_exception
                 op.cleanup = tuple(cleanup_before_exception), cleanup_on_exception
+            op = ops[-1]
             if var_needsgc(op.result):
                 if op.opname not in ('direct_call', 'indirect_call') and not var_ispyobj(op.result):
-                    newops.extend(self.push_alive(op.result))
+                    lst = list(self.push_alive(op.result))
+                    newops.extend(lst)
+                    num_ops_after_exc_raising += len(lst)
                 livevars.append(op.result)
         if len(block.exits) == 0:
             # everything is fine already for returnblocks and exceptblocks
@@ -117,6 +130,15 @@
                 # to the block, even if the variable dies in all
                 # linked blocks.
                 deadinallexits = sets.Set([])
+                if num_ops_after_exc_raising > 0:
+                    # No place to put the remaining pending operations!
+                    # Need a new block along the non-exceptional link.
+                    # XXX test this.
+                    tail = newops[-num_ops_after_exc_raising:]
+                    del newops[-num_ops_after_exc_raising:]
+                    link = block.exits[0]
+                    assert link.exitcase is None
+                    insert_empty_block(self.translator, link, tail)
             else:
                 deadinallexits = sets.Set(livevars)
                 for link in block.exits:
@@ -603,36 +625,122 @@
         self.finalizer_funcptrs[TYPE] = fptr
         return fptr
 
+
+def gc_pointers_inside(v, adr):
+    t = lltype.typeOf(v)
+    if isinstance(t, lltype.Struct):
+        for n, t2 in t._flds.iteritems():
+            if isinstance(t2, lltype.Ptr) and t2._needsgc() and t2.TO != lltype.PyObject:
+                yield adr + llmemory.offsetof(t, n)
+            elif isinstance(t2, (lltype.Array, lltype.Struct)):
+                for a in gc_pointers_inside(getattr(v, n), adr + llmemory.offsetof(t, n)):
+                    yield a
+    elif isinstance(t, lltype.Array):
+        if isinstance(t.OF, lltype.Ptr) and t2._needsgc():
+            for i in range(len(v.items)):
+                yield adr + llmemory.itemoffsetof(t, i)
+        elif isinstance(t.OF, lltype.Struct):
+            for i in range(len(v.items)):
+                for a in gc_pointers_inside(v.items[i], adr + llmemory.itemoffsetof(t, i)):
+                    yield a
+
 class FrameworkGCTransformer(BoehmGCTransformer):
 
     def __init__(self, translator):
         super(FrameworkGCTransformer, self).__init__(translator)
         class GCData(object):
+            from pypy.rpython.memory.gc import MarkSweepGC as GCClass
             startheapsize = 640*1024    # XXX adjust
             rootstacksize = 640*1024    # XXX adjust
+
+            # types of the GC information tables
+            OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
+            TYPE_INFO = lltype.Struct("type_info",
+                ("fixedsize",   lltype.Signed),
+                ("ofstoptrs",   lltype.Ptr(OFFSETS_TO_GC_PTR)),
+                ("varitemsize", lltype.Signed),
+                ("ofstovar",    lltype.Signed),
+                ("ofstolength", lltype.Signed),
+                ("varofstoptrs",lltype.Ptr(OFFSETS_TO_GC_PTR)),
+                )
+            TYPE_INFO_TABLE = lltype.Array(TYPE_INFO)
+
+        def q_is_varsize(typeid):
+            return gcdata.type_info_table[typeid].varitemsize != 0
+
+        def q_offsets_to_gc_pointers(typeid):
+            return gcdata.type_info_table[typeid].ofstoptrs
+
+        def q_fixed_size(typeid):
+            return gcdata.type_info_table[typeid].fixedsize
+
+        def q_varsize_item_sizes(typeid):
+            return gcdata.type_info_table[typeid].varitemsize
+
+        def q_varsize_offset_to_variable_part(typeid):
+            return gcdata.type_info_table[typeid].ofstovar
+
+        def q_varsize_offset_to_length(typeid):
+            return gcdata.type_info_table[typeid].ofstolength
+
+        def q_varsize_offsets_to_gcpointers_in_var_part(typeid):
+            return gcdata.type_info_table[typeid].varofstoptrs
+
         gcdata = GCData()
+        # set up dummy a table, to be overwritten with the real one in finish()
+        gcdata.type_info_table = lltype.malloc(GCData.TYPE_INFO_TABLE, 0,
+                                               immortal=True)
+        gcdata.static_roots = lltype.malloc(lltype.Array(llmemory.Address), 0,
+                                            immortal=True)
+        gcdata.static_root_start = gcdata.static_root_end = llmemory.cast_ptr_to_adr(gcdata.static_roots)
+        self.gcdata = gcdata
+        self.type_info_list = []
+        self.id_of_type = {}      # {LLTYPE: type_id}
+        self.seen_roots = {}
+        self.static_gc_roots = []
+        self.addresses_of_static_ptrs_in_nongc = []
+        self.offsettable_cache = {}
+        self.malloc_fnptr_cache = {}
+
         sizeofaddr = llmemory.sizeof(llmemory.Address)
         from pypy.rpython.memory.lladdress import NULL
 
         class StackRootIterator:
             _alloc_flavor_ = 'raw'
             def __init__(self):
-                self.current = gcdata.root_stack_top
+                self.stack_current = gcdata.root_stack_top
+                self.static_current = gcdata.static_root_start
 
             def pop(self):
-                while self.current != gcdata.root_stack_base:
-                    self.current -= sizeofaddr
-                    result = self.current.address[0]
-                    if result != NULL:
-                        return result
+                while self.static_current != gcdata.static_root_end:
+                    result = self.static_current
+                    self.static_current += sizeofaddr
+                    if result.address[0].address[0] != NULL:
+                        return result.address[0]
+                while self.stack_current != gcdata.root_stack_base:
+                    self.stack_current -= sizeofaddr
+                    if self.stack_current.address[0] != NULL:
+                        return self.stack_current
                 return NULL
 
         def frameworkgc_setup():
+            # run-time initialization code
             stackbase = lladdress.raw_malloc(GCData.rootstacksize)
             gcdata.root_stack_top  = stackbase
             gcdata.root_stack_base = stackbase
-#            from pypy.rpython.memory.gc import MarkSweepGC
-#            gcdata.gc = MarkSweepGC(GCData.startheapsize, StackRootIterator)
+            gcdata.gc = GCData.GCClass(GCData.startheapsize, StackRootIterator)
+            gcdata.gc.set_query_functions(
+                q_is_varsize,
+                q_offsets_to_gc_pointers,
+                q_fixed_size,
+                q_varsize_item_sizes,
+                q_varsize_offset_to_variable_part,
+                q_varsize_offset_to_length,
+                q_varsize_offsets_to_gcpointers_in_var_part)
+            i = 0
+            while i < len(gcdata.static_roots):
+                push_root(gcdata.static_roots[i])
+                i += 1
 
         def push_root(addr):
             top = gcdata.root_stack_top
@@ -645,6 +753,24 @@
             gcdata.root_stack_top = top
             return result
 
+        bk = self.translator.annotator.bookkeeper
+
+        # the point of this little dance is to not annotate
+        # self.gcdata.type_info_table as a constant.
+        data_classdef = bk.getuniqueclassdef(GCData)
+        data_classdef.generalize_attr(
+            'type_info_table',
+            annmodel.SomePtr(lltype.Ptr(GCData.TYPE_INFO_TABLE)))
+        data_classdef.generalize_attr(
+            'static_roots',
+            annmodel.SomePtr(lltype.Ptr(lltype.Array(llmemory.Address))))
+        data_classdef.generalize_attr(
+            'static_root_start',
+            annmodel.SomeAddress())
+        data_classdef.generalize_attr(
+            'static_root_end',
+            annmodel.SomeAddress())
+        
         annhelper = annlowlevel.MixLevelHelperAnnotator(self.translator.rtyper)
         frameworkgc_setup_graph = annhelper.getgraph(frameworkgc_setup, [],
                                                      annmodel.s_None)
@@ -653,11 +779,20 @@
                                              annmodel.s_None)
         pop_root_graph = annhelper.getgraph(pop_root, [],
                                             annmodel.SomeAddress())
+
+        classdef = bk.getuniqueclassdef(GCData.GCClass)
+        s_gcdata = annmodel.SomeInstance(classdef)
+        malloc_graph = annhelper.getgraph(GCData.GCClass.malloc.im_func,
+                                          [s_gcdata,
+                                           annmodel.SomeInteger(nonneg=True),
+                                           annmodel.SomeInteger(nonneg=True)],
+                                          annmodel.SomeAddress())
         annhelper.finish()   # at this point, annotate all mix-level helpers
         self.frameworkgc_setup_ptr = self.graph2funcptr(frameworkgc_setup_graph,
                                                         attach_empty_cleanup=True)
         self.push_root_ptr = self.graph2funcptr(push_root_graph)
         self.pop_root_ptr  = self.graph2funcptr(pop_root_graph)
+        self.malloc_ptr    = self.graph2funcptr(malloc_graph, True)
 
     def graph2funcptr(self, graph, attach_empty_cleanup=False):
         self.seen_graphs[graph] = True
@@ -665,6 +800,114 @@
             MinimalGCTransformer(self.translator).transform_graph(graph)
         return const_funcptr_fromgraph(graph)
 
+    def get_type_id(self, TYPE):
+        try:
+            return self.id_of_type[TYPE]
+        except KeyError:
+            assert not self.finished
+            assert isinstance(TYPE, (lltype.GcStruct, lltype.GcArray))
+            # Record the new type_id description as a small dict for now.
+            # It will be turned into a Struct("type_info") in finish()
+            type_id = len(self.type_info_list)
+            info = {}
+            self.type_info_list.append(info)
+            self.id_of_type[TYPE] = type_id
+            offsets = offsets_to_gc_pointers(TYPE)
+            info["ofstoptrs"] = self.offsets2table(offsets)
+            if not TYPE._is_varsize():
+                info["fixedsize"] = llmemory.sizeof(TYPE)
+            else:
+                info["fixedsize"] = llmemory.sizeof(TYPE, 0)
+                if isinstance(TYPE, lltype.Struct):
+                    ARRAY = TYPE._flds[TYPE._arrayfld]
+                    ofs1 = llmemory.offsetof(TYPE, TYPE._arrayfld)
+                    info["ofstolength"] = ofs1
+                    info["ofstovar"] = ofs1 + llmemory.itemoffsetof(ARRAY, 0)
+                else:
+                    ARRAY = TYPE
+                    info["ofstolength"] = llmemory.ArrayLengthOffset(ARRAY)
+                    info["ofstovar"] = llmemory.itemoffsetof(TYPE, 0)
+                assert isinstance(ARRAY, lltype.Array)
+                offsets = offsets_to_gc_pointers(ARRAY.OF)
+                info["varofstoptrs"] = self.offsets2table(offsets)
+                info["varitemsize"] = llmemory.sizeof(ARRAY.OF)
+            return type_id
+
+    def consider_constant(self, TYPE, value):
+        if id(value) not in self.seen_roots:
+            self.seen_roots[id(value)] = True
+        if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
+            self.get_type_id(TYPE)
+        if TYPE != lltype.PyObject and find_gc_ptrs_in_type(TYPE):
+            if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
+                self.static_gc_roots.append(value)
+            else: 
+                for a in gc_pointers_inside(value, llmemory.fakeaddress(value)):
+                    self.addresses_of_static_ptrs_in_nongc.append(a)
+
+    def offsets2table(self, offsets):
+        key = tuple(offsets)
+        try:
+            return self.offsettable_cache[key]
+        except KeyError:
+            cachedarray = lltype.malloc(self.gcdata.OFFSETS_TO_GC_PTR,
+                                        len(offsets), immortal=True)
+            for i, value in enumerate(offsets):
+                cachedarray[i] = value
+            self.offsettable_cache[key] = cachedarray
+            return cachedarray
+
+    def finish(self):
+        newgcdependencies = super(FrameworkGCTransformer, self).finish()
+        if self.type_info_list is not None:
+
+            table = lltype.malloc(self.gcdata.TYPE_INFO_TABLE,
+                                  len(self.type_info_list), immortal=True)
+            for tableentry, newcontent in zip(table, self.type_info_list):
+                for key, value in newcontent.items():
+                    setattr(tableentry, key, value)
+            self.type_info_list = None
+            self.offsettable_cache = None
+            
+            # replace the type_info_table pointer in gcdata -- at this point,
+            # the database is in principle complete, so it has already seen
+            # the old (empty) array.  We need to force it to consider the new
+            # array now.  It's a bit hackish as the old empty array will also
+            # be generated in the C source, but that's a rather minor problem.
+            
+            # XXX because we call inputconst already in replace_malloc, we can't
+            # modify the instance, we have to modify the 'rtyped instance'
+            # instead.  horrors.  is there a better way?
+            
+            s_gcdata = self.translator.annotator.bookkeeper.immutablevalue(
+                self.gcdata)
+            r_gcdata = self.translator.rtyper.getrepr(s_gcdata)
+            ll_instance = rmodel.inputconst(r_gcdata, self.gcdata).value
+            ll_instance.inst_type_info_table = table
+            #self.gcdata.type_info_table = table
+
+            ll_static_roots = lltype.malloc(lltype.Array(llmemory.Address),
+                                            len(self.static_gc_roots),
+                                            immortal=True)
+            for i in range(len(self.static_gc_roots)):
+                c = self.static_gc_roots[i]
+                ll_static_roots[i] = llmemory.fakeaddress(c)
+            ll_instance.inst_static_roots = ll_static_roots
+
+            ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address),
+                                                   len(self.addresses_of_static_ptrs_in_nongc),
+                                                   immortal=True)
+            for i in range(len(self.addresses_of_static_ptrs_in_nongc)):
+                ll_static_roots_inside[i] = self.addresses_of_static_ptrs_in_nongc[i]
+            ll_instance.inst_static_root_start = llmemory.cast_ptr_to_adr(ll_static_roots_inside) + llmemory.ArrayItemsOffset(lltype.Array(llmemory.Address))
+            ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(ll_static_roots_inside)
+            
+            newgcdependencies = newgcdependencies or []
+            newgcdependencies.append(table)
+            newgcdependencies.append(ll_static_roots)
+            newgcdependencies.append(ll_static_roots_inside)
+        return newgcdependencies
+
     def protect_roots(self, op, livevars):
         livevars = [var for var in livevars if not var_ispyobj(var)]
         newops = list(self.push_roots(livevars))
@@ -673,8 +916,39 @@
 
     replace_direct_call    = protect_roots
     replace_indirect_call  = protect_roots
-    replace_malloc         = protect_roots
-    replace_malloc_varsize = protect_roots
+
+    def replace_malloc(self, op, livevars):
+        TYPE = op.args[0].value
+        PTRTYPE = op.result.concretetype
+        assert PTRTYPE.TO == TYPE
+        type_id = self.get_type_id(TYPE)
+
+        v = varoftype(llmemory.Address)
+        c_type_id = rmodel.inputconst(lltype.Signed, type_id)
+        if len(op.args) == 1:
+            v_length = rmodel.inputconst(lltype.Signed, 0)
+        else:
+            v_length = op.args[1]
+
+        # surely there's a better way of doing this?
+        s_gcdata = self.translator.annotator.bookkeeper.immutablevalue(self.gcdata)
+        r_gcdata = self.translator.rtyper.getrepr(s_gcdata)
+        s_gc = self.translator.annotator.bookkeeper.valueoftype(self.gcdata.GCClass)
+        r_gc = self.translator.rtyper.getrepr(s_gc)
+        
+        newop0 = SpaceOperation(
+            "getfield",
+            [rmodel.inputconst(r_gcdata, self.gcdata), Constant("inst_gc", lltype.Void)],
+            varoftype(r_gc.lowleveltype))
+        newop = SpaceOperation("direct_call",
+                               [self.malloc_ptr, newop0.result, c_type_id, v_length],
+                               v)
+        ops, finally_ops = self.protect_roots(newop, livevars)
+        ops.insert(0, newop0)
+        ops.append(SpaceOperation("cast_adr_to_ptr", [v], op.result))
+        return ops, finally_ops, 1
+
+    replace_malloc_varsize = replace_malloc
 
     def push_alive_nopyobj(self, var):
         return []
@@ -697,6 +971,25 @@
             yield SpaceOperation("gc_reload_possibly_moved", [v, var],
                                  varoftype(lltype.Void))
 
+# XXX copied and modified from lltypelayout.py
+def offsets_to_gc_pointers(TYPE):
+    offsets = []
+    if isinstance(TYPE, lltype.Struct):
+        for name in TYPE._names:
+            FIELD = getattr(TYPE, name)
+            if isinstance(FIELD, lltype.Array):
+                continue    # skip inlined array
+            baseofs = llmemory.offsetof(TYPE, name)
+            suboffsets = offsets_to_gc_pointers(FIELD)
+            for s in suboffsets:
+                if s == 0:
+                    offsets.append(baseofs)
+                else:
+                    offsets.append(baseofs + s)
+    elif (isinstance(TYPE, lltype.Ptr) and TYPE._needsgc() and
+          TYPE.TO is not lltype.PyObject):
+        offsets.append(0)
+    return offsets
 
 # ___________________________________________________________________
 # calculate some statistics about the number of variables that need

Modified: pypy/branch/njriley-trans/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/ootypesystem/ootype.py	Fri Mar 10 06:12:02 2006
@@ -1,19 +1,36 @@
 from pypy.rpython.lltypesystem.lltype import LowLevelType, Signed, Unsigned, Float, Char
-from pypy.rpython.lltypesystem.lltype import Bool, Void, UniChar, typeOf, Primitive
-from pypy.rpython.lltypesystem.lltype import frozendict
+from pypy.rpython.lltypesystem.lltype import Bool, Void, UniChar, typeOf, \
+        Primitive, isCompatibleType
+from pypy.rpython.lltypesystem.lltype import frozendict, isCompatibleType
 
 class OOType(LowLevelType):
-    pass
+
+    def _is_compatible(TYPE1, TYPE2):
+        if TYPE1 == TYPE2:
+            return True
+        if isinstance(TYPE1, Instance) and isinstance(TYPE2, Instance):
+            return isSubclass(TYPE1, TYPE2)
+        else:
+            return False
 
 class Class(OOType):
-    pass
+
+    def _defl(self):
+        return nullruntimeclass
+    
 Class = Class()
 
 class Instance(OOType):
     """this is the type of user-defined objects"""
-    def __init__(self, name, superclass, fields={}, methods={}):
+    def __init__(self, name, superclass, fields={}, methods={},
+            _is_root=False):
         self._name = name
-        self._superclass = superclass
+
+        if _is_root:
+            self._superclass = None
+        else:
+            assert isinstance(superclass, Instance)
+            self._superclass = superclass
 
         self._methods = frozendict()
         self._fields = frozendict()
@@ -27,8 +44,7 @@
     def _defl(self):
         return self._null
 
-    def _example(self):
-        return new(self)
+    def _example(self): return new(self)
 
     def __repr__(self):
         return '<%s>' % (self,)
@@ -118,6 +134,7 @@
         all.update(self._fields)
         return all
 
+
 class StaticMethod(OOType):
     __slots__ = ['_null']
 
@@ -129,6 +146,9 @@
     def _example(self):
         _retval = self.RESULT._example()
         return _static_meth(self, _callable=lambda *args: _retval)
+
+    def _defl(self):
+        return null(self)
     
 class Meth(StaticMethod):
 
@@ -162,7 +182,7 @@
     def __setattr__(self, name, value):
         self.__getattr__(name)
             
-        if self._TYPE._field_type(name) != typeOf(value):
+        if not isCompatibleType(typeOf(value), self._TYPE._field_type(name)):
             raise TypeError("Expected type %r" % self._TYPE._field_type(name))
 
         self.__dict__[name] = value
@@ -325,14 +345,6 @@
         c = c._superclass
     return None
 
-def isCompatibleType(TYPE1, TYPE2):
-    if TYPE1 == TYPE2:
-        return True
-    if isinstance(TYPE1, Instance) and isinstance(TYPE2, Instance):
-        return isSubclass(TYPE1, TYPE2)
-    else:
-        return False
-        
 def ooupcast(INSTANCE, instance):
     assert instanceof(instance, INSTANCE)
     return instance
@@ -347,3 +359,6 @@
         return id(inst)
     else:
         return 0   # for all null instances
+
+
+ROOT = Instance('Root', None, _is_root=True)

Modified: pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rbuiltin.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rbuiltin.py	Fri Mar 10 06:12:02 2006
@@ -10,11 +10,23 @@
     return hop.genop('new', vlist,
                      resulttype = hop.r_result.lowleveltype)
 
+def rtype_null(hop):
+    assert hop.args_s[0].is_constant()
+    TYPE = hop.args_s[0].const
+    nullvalue = ootype.null(TYPE)
+    return hop.inputconst(TYPE, nullvalue)
+
 def rtype_classof(hop):
     assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)
     return hop.genop('classof', hop.args_v,
                      resulttype = ootype.Class)
 
+def rtype_subclassof(hop):
+    assert isinstance(hop.args_s[0], annmodel.SomeOOClass)
+    assert isinstance(hop.args_s[1], annmodel.SomeOOClass)
+    return hop.genop('subclassof', hop.args_v,
+                     resulttype = ootype.Bool)
+
 def rtype_runtimenew(hop):
     assert isinstance(hop.args_s[0], annmodel.SomeOOClass)
     return hop.genop('runtimenew', hop.args_v,
@@ -40,7 +52,7 @@
 
     v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
     if isinstance(v_cls, Constant):
-        c_cls = hop.inputconst(ootype.Void, v_cls.value._INSTANCE)
+        c_cls = hop.inputconst(ootype.Void, v_cls.value.class_._INSTANCE)
         return hop.genop('instanceof', [v_obj, c_cls], resulttype=ootype.Bool)
     else:
         raise TyperError("XXX missing impl of isinstance(x, variable)")
@@ -48,7 +60,9 @@
 
 BUILTIN_TYPER = {}
 BUILTIN_TYPER[ootype.new] = rtype_new
+BUILTIN_TYPER[ootype.null] = rtype_null
 BUILTIN_TYPER[ootype.classof] = rtype_classof
+BUILTIN_TYPER[ootype.subclassof] = rtype_subclassof
 BUILTIN_TYPER[ootype.runtimenew] = rtype_runtimenew
 BUILTIN_TYPER[ootype.ooidentityhash] = rtype_ooidentityhash
 BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance

Modified: pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rclass.py	Fri Mar 10 06:12:02 2006
@@ -1,46 +1,140 @@
 import types
 from pypy.annotation import model as annmodel
 from pypy.annotation import description
+from pypy.objspace.flow import model as flowmodel
 from pypy.rpython.rmodel import inputconst, TyperError
+from pypy.rpython.rmodel import mangle as pbcmangle
 from pypy.rpython.rclass import AbstractClassRepr, AbstractInstanceRepr, \
                                 getinstancerepr, getclassrepr, get_type_repr
 from pypy.rpython.ootypesystem import ootype
 from pypy.annotation.pairtype import pairtype
 from pypy.tool.sourcetools import func_with_new_name
 
-CLASSTYPE = ootype.Class
+CLASSTYPE = ootype.Instance("Object_meta", ootype.ROOT,
+        fields={"class_": ootype.Class})
+OBJECT = ootype.Instance("Object", ootype.ROOT,
+        fields={'meta': CLASSTYPE})
+
 
 class ClassRepr(AbstractClassRepr):
     def __init__(self, rtyper, classdef):
         AbstractClassRepr.__init__(self, rtyper, classdef)
 
-        self.lowleveltype = ootype.Class
+        if self.classdef is not None:
+            self.rbase = getclassrepr(self.rtyper, self.classdef.basedef)
+            base_type = self.rbase.lowleveltype
+            self.lowleveltype = ootype.Instance(
+                    self.classdef.name + "_meta", base_type)
+        else:
+            # we are ROOT
+            self.lowleveltype = CLASSTYPE
 
     def _setup_repr(self):
-        pass # not actually needed?
+        clsfields = {}
+        pbcfields = {}
+        if self.classdef is not None:
+            # class attributes
+            llfields = []
+            """
+            attrs = self.classdef.attrs.items()
+            attrs.sort()
+            for name, attrdef in attrs:
+                if attrdef.readonly:
+                    s_value = attrdef.s_value
+                    s_unboundmethod = self.prepare_method(s_value)
+                    if s_unboundmethod is not None:
+                        allmethods[name] = True
+                        s_value = s_unboundmethod
+                    r = self.rtyper.getrepr(s_value)
+                    mangled_name = 'cls_' + name
+                    clsfields[name] = mangled_name, r
+                    llfields.append((mangled_name, r.lowleveltype))
+            """
+            # attributes showing up in getattrs done on the class as a PBC
+            extra_access_sets = self.rtyper.class_pbc_attributes.get(
+                self.classdef, {})
+            for access_set, counter in extra_access_sets.items():
+                for attr, s_value in access_set.attrs.items():
+                    r = self.rtyper.getrepr(s_value)
+                    mangled_name = pbcmangle('pbc%d' % counter, attr)
+                    pbcfields[access_set, attr] = mangled_name, r
+                    llfields.append((mangled_name, r.lowleveltype))
+            
+            self.rbase.setup()
+            ootype.addFields(self.lowleveltype, dict(llfields))
+        #self.clsfields = clsfields
+        self.pbcfields = pbcfields
+        self.meta_instance = None
+ 
+    def get_meta_instance(self, cast_to_root_meta=True):
+        if self.meta_instance is None:
+            self.meta_instance = ootype.new(self.lowleveltype) 
+            self.setup_meta_instance(self.meta_instance, self)
+        
+        meta_instance = self.meta_instance
+        if cast_to_root_meta:
+            meta_instance = ootype.ooupcast(CLASSTYPE, meta_instance)
+        return meta_instance
 
-    def getruntime(self):
-        return getinstancerepr(self.rtyper, self.classdef).lowleveltype._class
+    def setup_meta_instance(self, meta_instance, rsubcls):
+        if self.classdef is None:
+            rinstance = getinstancerepr(self.rtyper, rsubcls.classdef)
+            setattr(meta_instance, 'class_', rinstance.lowleveltype._class)
+        else:
+            # setup class attributes: for each attribute name at the level
+            # of 'self', look up its value in the subclass rsubcls
+            def assign(mangled_name, value):
+                if isinstance(value, flowmodel.Constant) and isinstance(value.value, staticmethod):
+                    value = flowmodel.Constant(value.value.__get__(42))   # staticmethod => bare function
+                llvalue = r.convert_desc_or_const(value)
+                setattr(meta_instance, mangled_name, llvalue)
+
+            #mro = list(rsubcls.classdef.getmro())
+            #for fldname in self.clsfields:
+            #    mangled_name, r = self.clsfields[fldname]
+            #    if r.lowleveltype is Void:
+            #        continue
+            #    value = rsubcls.classdef.classdesc.read_attribute(fldname, None)
+            #    if value is not None:
+            #        assign(mangled_name, value)
+            # extra PBC attributes
+            for (access_set, attr), (mangled_name, r) in self.pbcfields.items():
+                if rsubcls.classdef.classdesc not in access_set.descs:
+                    continue   # only for the classes in the same pbc access set
+                if r.lowleveltype is ootype.Void:
+                    continue
+                attrvalue = rsubcls.classdef.classdesc.read_attribute(attr, None)
+                if attrvalue is not None:
+                    assign(mangled_name, attrvalue)
+
+            # then initialize the 'super' portion of the vtable
+            meta_instance_super = ootype.ooupcast(
+                    self.rbase.lowleveltype, meta_instance)
+            self.rbase.setup_meta_instance(meta_instance_super, rsubcls)
+
+    getruntime = get_meta_instance
+    
+    def fromclasstype(self, vclass, llops):
+        return llops.genop('oodowncast', [vclass],
+                resulttype=self.lowleveltype)
+
+    def getpbcfield(self, vcls, access_set, attr, llops):
+        if (access_set, attr) not in self.pbcfields:
+            raise TyperError("internal error: missing PBC field")
+        mangled_name, r = self.pbcfields[access_set, attr]
+        v_meta = self.fromclasstype(vcls, llops)
+        cname = inputconst(ootype.Void, mangled_name)
+        return llops.genop('oogetfield', [v_meta, cname], resulttype=r)
 
     def rtype_issubtype(self, hop):
         class_repr = get_type_repr(self.rtyper)
-        vlist = hop.inputargs(class_repr, class_repr)
-        return hop.genop('subclassof', vlist, resulttype=ootype.Bool)
+        vmeta1, vmeta2 = hop.inputargs(class_repr, class_repr)
+        return hop.gendirectcall(ll_issubclass, vmeta1, vmeta2)
 
-
-    def rtype_is_((r_cls1, r_cls2), hop):
-        class_repr = get_type_repr(self.rtyper)
-        vlist = hop.inputargs(class_repr, class_repr)
-        return hop.genop('oosameclass', vlist, resulttype=ootype.Bool)
-
-
-def rtype_classes_is_(_, hop):
-    class_repr = get_type_repr(hop.rtyper)
-    vlist = hop.inputargs(class_repr, class_repr)
-    return hop.genop('oosameclass', vlist, resulttype=ootype.Bool)
-
-class __extend__(pairtype(ClassRepr, ClassRepr)):
-    rtype_is_ = rtype_classes_is_
+def ll_issubclass(meta1, meta2):
+    class1 = meta1.class_
+    class2 = meta2.class_
+    return ootype.subclassof(class1, class2)
 
 # ____________________________________________________________
 
@@ -59,16 +153,27 @@
         AbstractInstanceRepr.__init__(self, rtyper, classdef)
 
         self.baserepr = None
-        b = self.classdef.basedef
-        if b is not None:
-            self.baserepr = getinstancerepr(rtyper, b)
-            b = self.baserepr.lowleveltype
+        if self.classdef is None:
+            self.lowleveltype = OBJECT
+        else:
+            b = self.classdef.basedef
+            if b is not None:
+                self.baserepr = getinstancerepr(rtyper, b)
+                b = self.baserepr.lowleveltype
+            else:
+                b = OBJECT
 
-        self.lowleveltype = ootype.Instance(classdef.shortname, b, {}, {})
+            self.lowleveltype = ootype.Instance(classdef.name, b, {}, {})
         self.prebuiltinstances = {}   # { id(x): (x, _ptr) }
         self.object_type = self.lowleveltype
 
     def _setup_repr(self):
+        if self.classdef is None:
+            self.allfields = {}
+            self.allmethods = {}
+            self.allclassattributes = {}
+            return
+
         if self.baserepr is not None:
             allfields = self.baserepr.allfields.copy()
             allmethods = self.baserepr.allmethods.copy()
@@ -108,7 +213,18 @@
                 if mangled in allmethods:
                     raise TyperError("class attribute overrides method")
                 allclassattributes[mangled] = name, s_value
-                                
+
+        special_methods = ["__init__", "__del__"]
+        for meth_name in special_methods:
+            if meth_name not in selfattrs and \
+                    self.classdef.classdesc.find_source_for(meth_name) is not None:
+                s_meth = self.classdef.classdesc.s_get_value(self.classdef,
+                        meth_name)
+                if isinstance(s_meth, annmodel.SomePBC):
+                    mangled = mangle(meth_name)
+                    allmethods[mangled] = meth_name, s_meth
+                # else: it's the __init__ of a builtin exception
+            
         #
         # hash() support
         if self.rtyper.needs_hash_support(self.classdef):
@@ -145,9 +261,10 @@
             # get method implementation
             from pypy.rpython.ootypesystem.rpbc import MethodImplementations
             methimpls = MethodImplementations.get(self.rtyper, s_value)
-            m = methimpls.get_impl(mangled, methdesc)
-
-            methods[mangled] = m
+            m_impls = methimpls.get_impl(mangled, methdesc,
+                    is_finalizer=name == "__del__")
+            
+            methods.update(m_impls)
                                         
 
         for classdef in self.classdef.getmro():
@@ -256,7 +373,8 @@
         if hop.args_s[0].can_be_none():
             return hop.gendirectcall(ll_inst_type, vinst)
         else:
-            return hop.genop('classof', [vinst], resulttype=ootype.Class)
+            cmeta = inputconst(ootype.Void, "meta")
+            return hop.genop('oogetfield', [vinst, cmeta], resulttype=CLASSTYPE)
 
     def rtype_hash(self, hop):
         if self.classdef is None:
@@ -271,46 +389,34 @@
         vinst, = hop.inputargs(self)
         return hop.genop('ooidentityhash', [vinst], resulttype=ootype.Signed)
 
-    def convert_const(self, value):
-        if value is None:
-            return ootype.null(self.lowleveltype)
-        bk = self.rtyper.annotator.bookkeeper
-        try:
-            classdef = bk.getuniqueclassdef(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.name, value))
-            rinstance = getinstancerepr(self.rtyper, classdef)
-            result = rinstance.convert_const(value)
-            return ootype.ooupcast(self.lowleveltype, result)
-        # common case
-        try:
-            return self.prebuiltinstances[id(value)][1]
-        except KeyError:
-            self.setup()
-            result = ootype.new(self.object_type)
-            self.prebuiltinstances[id(value)] = value, result
-            self.initialize_prebuilt_instance(value, result)
-            return result
+    def null_instance(self):
+        return ootype.null(self.lowleveltype)
+
+    def upcast(self, result):
+        return ootype.ooupcast(self.lowleveltype, result)
+
+    def create_instance(self):
+        return ootype.new(self.object_type)
 
     def new_instance(self, llops):
         """Build a new instance, without calling __init__."""
-
-        return llops.genop("new",
+        classrepr = getclassrepr(self.rtyper, self.classdef) 
+        v_instance =  llops.genop("new",
             [inputconst(ootype.Void, self.lowleveltype)], self.lowleveltype)
-
-    def initialize_prebuilt_instance(self, value, result):
+        cmeta = inputconst(ootype.Void, "meta")
+        cmeta_instance = inputconst(CLASSTYPE, classrepr.get_meta_instance())
+        llops.genop("oosetfield", [v_instance, cmeta, cmeta_instance], 
+                  resulttype=ootype.Void)
+        return v_instance
+        
+    def initialize_prebuilt_instance(self, value, classdef, result):
         # then add instance attributes from this level
+        classrepr = getclassrepr(self.rtyper, self.classdef)
         for mangled, (oot, default) in self.lowleveltype._allfields().items():
             if oot is ootype.Void:
                 llattrvalue = None
+            elif mangled == 'meta':
+                llattrvalue = classrepr.get_meta_instance()
             elif mangled == '_hash_cache_': # hash() support
                 llattrvalue = hash(value)
             else:
@@ -367,7 +473,7 @@
 
 def ll_inst_type(obj):
     if obj:
-        return ootype.classof(obj)
+        return obj.meta
     else:
         # type(None) -> NULL  (for now)
-        return ootype.nullruntimeclass
+        return ootype.null(CLASSTYPE)

Modified: pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rpbc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rpbc.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/ootypesystem/rpbc.py	Fri Mar 10 06:12:02 2006
@@ -1,35 +1,93 @@
-from pypy.rpython.rpbc import AbstractClassesPBCRepr, AbstractMethodsPBCRepr
+from pypy.rpython.rmodel import CanBeNull, Repr, inputconst
+from pypy.rpython.rpbc import AbstractClassesPBCRepr, AbstractMethodsPBCRepr, \
+        AbstractMultipleFrozenPBCRepr, MethodOfFrozenPBCRepr, \
+        AbstractFunctionsPBCRepr
+from pypy.rpython.rclass import rtype_new_instance, getinstancerepr
 from pypy.rpython.rpbc import get_concrete_calltable
-from pypy.rpython.rclass import rtype_new_instance
+from pypy.rpython import callparse
 from pypy.rpython.ootypesystem import ootype
-from pypy.rpython.ootypesystem.rclass import ClassRepr, InstanceRepr, mangle
-from pypy.rpython.ootypesystem.rclass import rtype_classes_is_
+from pypy.rpython.ootypesystem.rclass import ClassRepr, InstanceRepr 
+from pypy.rpython.ootypesystem.rclass import mangle
+from pypy.annotation import model as annmodel
+from pypy.annotation import description
 from pypy.annotation.pairtype import pairtype
+import types
 
+
+class FunctionsPBCRepr(AbstractFunctionsPBCRepr):
+    """Representation selected for a PBC of function(s)."""
+
+    def setup_specfunc(self):
+        fields = {}
+        for row in self.uniquerows:
+            fields[row.attrname] = row.fntype
+        return ootype.Instance('specfunc', ootype.ROOT, fields)
+
+    def create_specfunc(self):
+        return ootype.new(self.lowleveltype)
+
+    def get_specfunc_row(self, llop, v, c_rowname, resulttype):
+        return llop.genop('oogetfield', [v, c_rowname], resulttype=resulttype)
+        
 class ClassesPBCRepr(AbstractClassesPBCRepr):
+
     def rtype_simple_call(self, hop):
+        classdef = hop.s_result.classdef
         if self.lowleveltype is not ootype.Void:
-            raise NotImplementedError()
+            # instantiating a class from multiple possible classes
+            v_meta = hop.inputarg(self, arg=0)
+            c_class_ = hop.inputconst(ootype.Void, "class_")
+            v_class = hop.genop('oogetfield', [v_meta, c_class_],
+                    resulttype=ootype.Class)
+            resulttype = getinstancerepr(hop.rtyper, classdef).lowleveltype
+            v_instance = hop.genop('runtimenew', [v_class], resulttype=resulttype)
+            c_meta = hop.inputconst(ootype.Void, "meta")
+            hop.genop('oosetfield', [v_instance, c_meta, v_meta],
+                    resulttype=ootype.Void)
+        else:
+            # instantiating a single class
+            v_instance = rtype_new_instance(hop.rtyper, classdef, hop.llops)
 
-        classdef = hop.s_result.classdef
-        v_instance = rtype_new_instance(hop.rtyper, classdef, hop.llops)
+        inits = []
+        for desc in self.s_pbc.descriptions:
+            if desc.find_source_for('__init__') is not None:
+                unbound = desc.s_get_value(desc.getuniqueclassdef(), '__init__')
+                unbound, = unbound.descriptions
+                bound = unbound.bind_self(desc.getuniqueclassdef())
+                inits.append(bound)
+
+        if inits:
+            s_init = annmodel.SomePBC(inits)
+            s_instance = annmodel.SomeInstance(classdef)
+            hop2 = hop.copy()
+            hop2.r_s_popfirstarg()   # discard the class pointer argument
+            hop2.v_s_insertfirstarg(v_instance, s_init)  # add 'instance'
+            hop2.s_result = annmodel.s_None
+            hop2.r_result = self.rtyper.getrepr(hop2.s_result)
+            # now hop2 looks like simple_call(initmeth, args...)
+            hop2.dispatch()
+        else:
+            assert hop.nb_args == 1, ("arguments passed to __init__, "
+                                      "but no __init__!")
         return v_instance
 
+    rtype_call_args = rtype_simple_call
+
+def row_method_name(methodname, rowname):
+    return "%s_%s" % (methodname, rowname)
+    
 class MethodImplementations(object):
 
     def __init__(self, rtyper, methdescs):
         samplemdesc = methdescs.iterkeys().next()
         concretetable, uniquerows = get_concrete_calltable(rtyper,
                                              samplemdesc.funcdesc.getcallfamily())
-        self._uniquerows = uniquerows
-        if len(uniquerows) == 1:
-            row = uniquerows[0]
+        self.row_mapping = {} 
+        for row in uniquerows:
             sample_as_static_meth = row.itervalues().next()
             SM = ootype.typeOf(sample_as_static_meth)
             M = ootype.Meth(SM.ARGS[1:], SM.RESULT) # cut self
-            self.lowleveltype = M
-        else:
-            XXX_later
+            self.row_mapping[row.attrname] = row, M
 
     def get(rtyper, s_pbc):
         lst = list(s_pbc.descriptions)
@@ -43,27 +101,58 @@
             return methodsimpl
     get = staticmethod(get)
 
-    def get_impl(self, name, methdesc):
-        M = self.lowleveltype
-        if methdesc is None:
-            return ootype.meth(M, _name=name, abstract=True)
-        else:
-            impl_graph = self._uniquerows[0][methdesc.funcdesc].graph
-            return ootype.meth(M, _name=name, graph=impl_graph)
-    
+    def get_impl(self, name, methdesc, is_finalizer=False):
+        impls = {}
+        flags = {}
+        if is_finalizer:
+            flags['finalizer'] = True
+        for rowname, (row, M) in self.row_mapping.iteritems():
+            if methdesc is None:
+                m = ootype.meth(M, _name=name, abstract=True, **flags)
+            else:
+                impl_graph = row[methdesc.funcdesc].graph
+                m = ootype.meth(M, _name=name, graph=impl_graph, **flags)
+            derived_name = row_method_name(name, rowname)
+            impls[derived_name] = m
+        return impls
+
 
 class MethodsPBCRepr(AbstractMethodsPBCRepr):
 
     def __init__(self, rtyper, s_pbc):
         AbstractMethodsPBCRepr.__init__(self, rtyper, s_pbc)
+        sampledesc = s_pbc.descriptions.iterkeys().next()
+        self.concretetable, _ = get_concrete_calltable(rtyper,
+                                             sampledesc.funcdesc.getcallfamily())
 
     def rtype_simple_call(self, hop):
-        vlist = hop.inputargs(self, *hop.args_r[1:])
-        mangled = mangle(self.methodname)
-        cname = hop.inputconst(ootype.Void, mangled)
-        return hop.genop("oosend", [cname]+vlist,
-                         resulttype = hop.r_result.lowleveltype)
+        return self.call("simple_call", hop)
 
+    def rtype_call_args(self, hop):
+        return self.call("call_args", hop)
+
+    def call(self, opname, hop):
+        bk = self.rtyper.annotator.bookkeeper
+        args = bk.build_args(opname, hop.args_s[1:])
+        args = args.prepend(self.s_im_self)
+        s_pbc = hop.args_s[0]   # possibly more precise than self.s_pbc
+        descs = [desc.funcdesc for desc in s_pbc.descriptions]
+        callfamily = descs[0].getcallfamily()
+        shape, index = description.FunctionDesc.variant_for_call_site(
+                bk, callfamily, descs, args)
+        row_of_graphs = callfamily.calltables[shape][index]
+        anygraph = row_of_graphs.itervalues().next()  # pick any witness
+        hop2 = self.add_instance_arg_to_hop(hop, opname == "call_args")
+        vlist = callparse.callparse(self.rtyper, anygraph, hop2, opname,
+                is_method=True)
+        rresult = callparse.getrresult(self.rtyper, anygraph)
+        hop.exception_is_here()
+        mangled = mangle(self.methodname)
+        row = self.concretetable[shape, index]
+        derived_mangled = row_method_name(mangled, row.attrname)
+        cname = hop.inputconst(ootype.Void, derived_mangled)
+        v = hop.genop("oosend", [cname]+vlist, resulttype=rresult)
+        return hop.llops.convertvar(v, rresult, hop.r_result)
         
 
 class __extend__(pairtype(InstanceRepr, MethodsPBCRepr)):
@@ -71,9 +160,28 @@
     def convert_from_to(_, v, llops):
         return v
 
+class MultipleFrozenPBCRepr(AbstractMultipleFrozenPBCRepr):
+    """Representation selected for multiple non-callable pre-built constants."""
+    def __init__(self, rtyper, access_set):
+        self.rtyper = rtyper
+        self.access_set = access_set
+        self.lowleveltype = ootype.Instance('pbc', ootype.ROOT)
+        self.pbc_cache = {}
+
+    def _setup_repr(self):
+        fields_list = self._setup_repr_fields()
+        ootype.addFields(self.lowleveltype, dict(fields_list))
+
+    def create_instance(self):
+        return ootype.new(self.lowleveltype)
+
+    def null_instance(self):
+        return ootype.null(self.lowleveltype)
+
+    def getfield(self, vpbc, attr, llops):
+        mangled_name, r_value = self.fieldmap[attr]
+        cmangledname = inputconst(ootype.Void, mangled_name)
+        return llops.genop('oogetfield', [vpbc, cmangledname],
+                           resulttype = r_value)
 
-class __extend__(pairtype(ClassRepr, ClassesPBCRepr)):
-    rtype_is_ = rtype_classes_is_
 
-class __extend__(pairtype(ClassesPBCRepr, ClassRepr)):
-    rtype_is_ = rtype_classes_is_

Modified: pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_ooann.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_ooann.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_ooann.py	Fri Mar 10 06:12:02 2006
@@ -5,7 +5,7 @@
 
 
 def test_simple_new():
-    C = Instance("test", None, {'a': Signed})
+    C = Instance("test", ROOT, {'a': Signed})
     
     def oof():
         c = new(C)
@@ -19,7 +19,7 @@
     assert s.knowntype == int
 
 def test_simple_instanceof():
-    C = Instance("test", None, {'a': Signed})
+    C = Instance("test", ROOT, {'a': Signed})
     
     def oof():
         c = new(C)
@@ -32,7 +32,7 @@
     assert s.knowntype == bool
 
 def test_simple_null():
-    I = Instance("test", None, {'a': Signed})
+    I = Instance("test", ROOT, {'a': Signed})
     
     def oof():
         i = null(I)
@@ -45,7 +45,7 @@
     assert s == annmodel.SomeOOInstance(I)
 
 def test_simple_classof():
-    I = Instance("test", None, {'a': Signed})
+    I = Instance("test", ROOT, {'a': Signed})
     
     def oof():
         i = new(I)
@@ -57,8 +57,23 @@
 
     assert s == annmodel.SomeOOClass(I)
 
+def test_subclassof():
+    I = Instance("test", ROOT, {'a': Signed})
+    I1 = Instance("test1", I) 
+    
+    def oof():
+        i = new(I)
+        i1 = new(I1)
+        return subclassof(classof(i1), classof(i))
+
+    a = RPythonAnnotator()
+    s = a.build_types(oof, [])
+    #a.translator.view()
+
+    assert s == annmodel.SomeBool()
+
 def test_simple_runtimenew():
-    I = Instance("test", None, {'a': Signed})
+    I = Instance("test", ROOT, {'a': Signed})
     
     def oof():
         i = new(I)
@@ -73,7 +88,7 @@
     assert s == annmodel.SomeOOInstance(I)
 
 def test_complex_runtimenew():
-    I = Instance("test", None, {'a': Signed})
+    I = Instance("test", ROOT, {'a': Signed})
     J = Instance("test2", I, {'b': Signed})
     K = Instance("test2", I, {'b': Signed})
     
@@ -94,7 +109,7 @@
     assert s == annmodel.SomeOOInstance(I)
 
 def test_method():
-    C = Instance("test", None, {"a": (Signed, 3)})
+    C = Instance("test", ROOT, {"a": (Signed, 3)})
 
     M = Meth([C], Signed)
     def m_(self, other):
@@ -114,7 +129,7 @@
     assert s.knowntype == int
 
 def test_unionof():
-    C1 = Instance("C1", None)
+    C1 = Instance("C1", ROOT)
     C2 = Instance("C2", C1)
     C3 = Instance("C3", C1)
 
@@ -158,7 +173,7 @@
     assert s == annmodel.SomeOOStaticMeth(F)
 
 def test_truth_value():
-    C = Instance("C", None)
+    C = Instance("C", ROOT)
     def oof(f):
         if f:
             c = new(C)

Modified: pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_oopbc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_oopbc.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_oopbc.py	Fri Mar 10 06:12:02 2006
@@ -17,3 +17,67 @@
     assert res == 110
     res = interpret(f, [False], type_system='ootype')
     assert res == 221
+
+def test_call_classes():
+    class A: pass
+    class B(A): pass
+    def f(i):
+        if i == 1:
+            cls = B
+        else:
+            cls = A
+        return cls()
+    res = interpret(f, [0], type_system='ootype')
+    assert ootype.typeOf(res)._name.split(".")[-1] == 'A'
+    res = interpret(f, [1], type_system='ootype')
+    assert ootype.typeOf(res)._name.split(".")[-1] == 'B'
+
+def test_call_classes_init():
+    class A: 
+        def __init__(self, a, b=0):
+            self.a = a
+    class B(A): 
+        def __init__(self, a):
+            self.a = a + 1
+    def f(i):
+        if i == 1:
+            cls = B
+        else:
+            cls = A
+        return cls(a=1).a
+    res = interpret(f, [0], type_system='ootype')
+    assert res == 1
+    res = interpret(f, [1], type_system='ootype')
+    assert res == 2
+
+def test_method_call_kwds():
+    class A:
+        def m(self, a, b=0, c=0):
+            return a + b + c
+    
+    def f1():
+        a = A()
+        return a.m(1, b=2)
+    def f2():
+        a = A()
+        return a.m(1, b=2, c=3)
+    assert 3 == interpret(f1, [], type_system="ootype")
+    assert 6 == interpret(f2, [], type_system="ootype")
+
+def test_classes_attribute():
+    class A: 
+        a = 3
+    class B(A): 
+        a = 2
+    def f(i):
+        if i == 1:
+            cls = B
+        else:
+            cls = A
+        instance = cls()
+        return cls.a
+    res = interpret(f, [0], type_system='ootype')
+    assert res == 3
+    res = interpret(f, [1], type_system='ootype')
+    assert res == 2
+

Modified: pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_oortype.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_oortype.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_oortype.py	Fri Mar 10 06:12:02 2006
@@ -16,7 +16,7 @@
     return graphof(t, f)
 
 def test_simple_class():
-    C = Instance("test", None, {'a': Signed})
+    C = Instance("test", ROOT, {'a': Signed})
     
     def f():
         c = new(C)
@@ -27,7 +27,7 @@
     assert rettype == C
     
 def test_simple_field():
-    C = Instance("test", None, {'a': (Signed, 3)})
+    C = Instance("test", ROOT, {'a': (Signed, 3)})
     
     def f():
         c = new(C)
@@ -39,7 +39,7 @@
     assert rettype == Signed
     
 def test_simple_method():
-    C = Instance("test", None, {'a': (Signed, 3)})
+    C = Instance("test", ROOT, {'a': (Signed, 3)})
     M = Meth([], Signed)
     def m_(self):
        return self.a
@@ -55,7 +55,7 @@
     assert rettype == Signed
 
 def test_truth_value():
-    C = Instance("C", None)
+    C = Instance("C", ROOT)
     NULL = null(C)
     def oof(f):
         if f:
@@ -72,3 +72,28 @@
     assert res is False
     res = interpret(oof, [False], type_system='ootype')
     assert res is True
+
+def test_simple_classof():
+    I = Instance("test", ROOT, {'a': Signed})
+    
+    def oof():
+        i = new(I)
+        return classof(i)
+
+    g = gengraph(oof, [])
+    rettype = g.getreturnvar().concretetype
+    assert rettype == Class
+
+def test_subclassof():
+    I = Instance("test", ROOT, {'a': Signed})
+    I1 = Instance("test1", I) 
+    
+    def oof():
+        i = new(I)
+        i1 = new(I1)
+        return subclassof(classof(i1), classof(i))
+
+    g = gengraph(oof, [])
+    rettype = g.getreturnvar().concretetype
+    assert rettype == Bool
+

Modified: pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_ootype.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_ootype.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/ootypesystem/test/test_ootype.py	Fri Mar 10 06:12:02 2006
@@ -9,11 +9,11 @@
     def m_(self, b):
        return self.a + b
     m = meth(M, _name="m", _callable=m_)
-    I = Instance("test", None, {"a": Signed}, {"m": m})
+    I = Instance("test", ROOT, {"a": Signed}, {"m": m})
     assert type(hash(I)) == int
 
 def test_simple_class():
-    I = Instance("test", None, {"a": Signed})
+    I = Instance("test", ROOT, {"a": Signed})
     i = new(I)
 
     py.test.raises(TypeError, "i.z")
@@ -23,7 +23,7 @@
     assert i.a == 3
 
 def test_assign_super_attr():
-    C = Instance("test", None, {"a": (Signed, 3)})
+    C = Instance("test", ROOT, {"a": (Signed, 3)})
     D = Instance("test2", C, {})
 
     d = new(D)
@@ -33,7 +33,7 @@
     assert d.a == 1
 
 def test_runtime_instanciation():
-    I = Instance("test", None, {"a": Signed})
+    I = Instance("test", ROOT, {"a": Signed})
     c = runtimeClass(I)
     i = runtimenew(c)
 
@@ -41,7 +41,7 @@
     assert typeOf(c) == Class
 
 def test_classof():
-    I = Instance("test", None, {"a": Signed})
+    I = Instance("test", ROOT, {"a": Signed})
     c = runtimeClass(I)
     i = new(I)
 
@@ -56,15 +56,15 @@
     assert classof(i2) != classof(i)
     
 def test_simple_default_class():
-    I = Instance("test", None, {"a": (Signed, 3)})
+    I = Instance("test", ROOT, {"a": (Signed, 3)})
     i = new(I)
 
     assert i.a == 3
 
-    py.test.raises(TypeError, "Instance('test', None, {'a': (Signed, 3.0)})")
+    py.test.raises(TypeError, "Instance('test', ROOT, {'a': (Signed, 3.0)})")
 
 def test_simple_null():
-    C = Instance("test", None, {"a": Signed})
+    C = Instance("test", ROOT, {"a": Signed})
 
     c = null(C)
     assert typeOf(c) == C
@@ -72,9 +72,9 @@
     py.test.raises(RuntimeError, "c.a")
 
 def test_simple_class_field():
-    C = Instance("test", None, {})
+    C = Instance("test", ROOT, {})
 
-    D = Instance("test2", None, {"a": C})
+    D = Instance("test2", ROOT, {"a": C})
     d = new(D)
 
     assert typeOf(d.a) == C
@@ -82,7 +82,7 @@
     assert d.a == null(C)
 
 def test_simple_recursive_class():
-    C = Instance("test", None, {})
+    C = Instance("test", ROOT, {})
 
     addFields(C, {"inst": C})
 
@@ -90,14 +90,14 @@
     assert c.inst == null(C)
 
 def test_simple_super():
-    C = Instance("test", None, {"a": (Signed, 3)})
+    C = Instance("test", ROOT, {"a": (Signed, 3)})
     D = Instance("test2", C, {})
 
     d = new(D)
     assert d.a == 3
 
 def test_simple_field_shadowing():
-    C = Instance("test", None, {"a": (Signed, 3)})
+    C = Instance("test", ROOT, {"a": (Signed, 3)})
     
     py.test.raises(TypeError, """D = Instance("test2", C, {"a": (Signed, 3)})""")
 
@@ -131,7 +131,7 @@
        return self.a + b
     m = meth(M, _name="m", _callable=m_)
 
-    C = Instance("test", None, {"a": (Signed, 2)}, {"m": m})
+    C = Instance("test", ROOT, {"a": (Signed, 2)}, {"m": m})
     c = new(C)
 
     assert c.m(3) == 5
@@ -146,12 +146,12 @@
        return self.a + b
     m = meth(M, _name="m", _callable=m_)
 
-    py.test.raises(TypeError, """Instance("test", None, {"a": M})""")
+    py.test.raises(TypeError, """Instance("test", ROOT, {"a": M})""")
 
-    py.test.raises(TypeError, """Instance("test", None, {"m": Signed}, {"m":m})""")
+    py.test.raises(TypeError, """Instance("test", ROOT, {"m": Signed}, {"m":m})""")
 
 def test_simple_recursive_meth():
-    C = Instance("test", None, {"a": (Signed, 3)})
+    C = Instance("test", ROOT, {"a": (Signed, 3)})
 
     M = Meth([C], Signed)
     def m_(self, other):
@@ -164,7 +164,7 @@
     assert c.m(c) == 6
 
 def test_explicit_name_clash():
-    C = Instance("test", None, {})
+    C = Instance("test", ROOT, {})
 
     addFields(C, {"a": (Signed, 3)})
 
@@ -178,7 +178,7 @@
     py.test.raises(TypeError, """addFields(C, {"b": Signed})""")
 
 def test_instanceof():
-    C = Instance("test", None, {})
+    C = Instance("test", ROOT, {})
     D = Instance("test2", C, {})
     c = new(C)
     d = new(D)
@@ -188,7 +188,7 @@
     assert instanceof(d, C)
 
 def test_superclass_meth_lookup():
-    C = Instance("test", None, {"a": (Signed, 3)})
+    C = Instance("test", ROOT, {"a": (Signed, 3)})
 
     M = Meth([C], Signed)
     def m_(self, other):
@@ -211,7 +211,7 @@
     assert d.m(d) == 9
 
 def test_isSubclass():
-    A = Instance("A", None)
+    A = Instance("A", ROOT)
     B = Instance("B", A)
     C = Instance("C", A)
     D = Instance("D", C)
@@ -226,11 +226,11 @@
     assert not isSubclass(D, B)
     
 def test_commonBaseclass():
-    A = Instance("A", None)
+    A = Instance("A", ROOT)
     B = Instance("B", A)
     C = Instance("C", A)
     D = Instance("D", C)
-    E = Instance("E", None)
+    E = Instance("E", ROOT)
     F = Instance("F", E)
 
     assert commonBaseclass(A, A) == A
@@ -247,12 +247,12 @@
     assert commonBaseclass(B, D) == A
     assert commonBaseclass(C, D) == C
     
-    assert commonBaseclass(E, A) is None
-    assert commonBaseclass(E, B) is None
-    assert commonBaseclass(F, A) is None
+    assert commonBaseclass(E, A) is ROOT
+    assert commonBaseclass(E, B) is ROOT
+    assert commonBaseclass(F, A) is ROOT
     
 def test_equality():
-    A = Instance("A", None)
+    A = Instance("A", ROOT)
     B = Instance("B", A)
     a1 = new(A)
     a2 = new(A)
@@ -278,7 +278,7 @@
         ]
 
 def test_subclassof():
-    A = Instance("A", None)
+    A = Instance("A", ROOT)
     B = Instance("B", A)
     C = Instance("C", B)
     result = []

Modified: pypy/branch/njriley-trans/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/rbuiltin.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/rbuiltin.py	Fri Mar 10 06:12:02 2006
@@ -11,6 +11,7 @@
 from pypy.rpython.robject import pyobj_repr
 from pypy.rpython.rdict import rtype_r_dict
 from pypy.tool import sourcetools
+from pypy.rpython import extregistry
 
 class __extend__(annmodel.SomeBuiltin):
     def rtyper_makerepr(self, rtyper):
@@ -30,7 +31,13 @@
     def rtyper_makekey(self):
         if self.s_self is None:
             # built-in function case
-            return self.__class__, getattr(self, 'const', None)
+
+            const = getattr(self, 'const', None)
+
+            if extregistry.is_registered(const):
+                const = extregistry.lookup(const)
+
+            return self.__class__, const
         else:
             # built-in method case
             # NOTE: we hash by id of self.s_self here.  This appears to be
@@ -53,14 +60,17 @@
     def rtype_simple_call(self, hop):
         try:
             bltintyper = BUILTIN_TYPER[self.builtinfunc]
-        except KeyError:
+        except (KeyError, TypeError):
             try:
                 rtyper = hop.rtyper
                 bltintyper = rtyper.type_system.rbuiltin.\
                                     BUILTIN_TYPER[self.builtinfunc]
-            except KeyError:
+            except (KeyError, TypeError):
                 if hasattr(self.builtinfunc,"specialize"):
                     bltintyper = self.builtinfunc.specialize
+                elif extregistry.is_registered(self.builtinfunc):
+                    entry = extregistry.lookup(self.builtinfunc)
+                    bltintyper = entry.specialize_call
                 else:
                     raise TyperError("don't know about built-in function %r" % (
                         self.builtinfunc,))

Modified: pypy/branch/njriley-trans/pypy/rpython/rclass.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/rclass.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/rclass.py	Fri Mar 10 06:12:02 2006
@@ -71,7 +71,7 @@
             if self.classdef.commonbase(subclassdef) != self.classdef:
                 raise TyperError("not a subclass of %r: %r" % (
                     self.classdef.name, desc))
-        #
+        
         return getclassrepr(self.rtyper, subclassdef).getruntime()
 
     def convert_const(self, value):
@@ -135,6 +135,35 @@
     def new_instance(self, llops):
         pass
 
+    def convert_const(self, value):
+        if value is None:
+            return self.null_instance()
+        if isinstance(value, types.MethodType):
+            value = value.im_self   # bound method -> instance
+        bk = self.rtyper.annotator.bookkeeper
+        try:
+            classdef = bk.getuniqueclassdef(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.commonbase(self.classdef) != self.classdef:
+                raise TyperError("not an instance of %r: %r" % (
+                    self.classdef.name, value))
+            rinstance = getinstancerepr(self.rtyper, classdef)
+            result = rinstance.convert_const(value)
+            return self.upcast(result)
+        # common case
+        try:
+            return self.prebuiltinstances[id(value)][1]
+        except KeyError:
+            self.setup()
+            result = self.create_instance()
+            self.prebuiltinstances[id(value)] = value, result
+            self.initialize_prebuilt_instance(value, classdef, result)
+            return result
+
     def rtype_type(self, hop):
         pass
 

Modified: pypy/branch/njriley-trans/pypy/rpython/rctypes/implementation.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/rctypes/implementation.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/rctypes/implementation.py	Fri Mar 10 06:12:02 2006
@@ -9,33 +9,38 @@
 if sys.platform == "win32":
     from ctypes import _FUNCFLAG_STDCALL
 from pypy.annotation.model import SomeInteger, SomeCTypesObject, \
-        SomeString, SomeFloat
+        SomeString, SomeFloat, SomeBuiltin
 from pypy.rpython.lltypesystem.lltype import Signed, SignedLongLong, \
         Unsigned, UnsignedLongLong, Char, Float, Ptr, \
         GcStruct, Struct, \
         Void
 from pypy.rpython.rmodel import Repr, IntegerRepr, inputconst
 from pypy.rpython.error import TyperError
+from pypy.rpython import extregistry
 from pypy.annotation.pairtype import pairtype
+from pypy.rpython import rint
 
+# Importing for side effect of registering types with extregistry
+import pypy.rpython.rctypes.rarray
+import pypy.rpython.rctypes.rprimitive
 
 # ctypes_annotation_list contains various attributes that
 # are used by the pypy annotation.
 
 ctypes_annotation_list = [
-    (c_char,          Char,             None),
-    (c_byte,          Signed,           None),
-    (c_ubyte,         Unsigned,         None),
-    (c_short,         Signed,           None),
-    (c_ushort,        Unsigned,         None),
-    (c_int,           Signed,           None),
-    (c_uint,          Unsigned,         None),
-    (c_long,          Signed,           None),
-    (c_ulong,         Unsigned,         None),
-    (c_longlong,      SignedLongLong,   None),
-    (c_ulonglong,     UnsignedLongLong, None),
-    (c_float,         Float,            None),
-    (c_double,        Float,            None),
+#    (c_char,          Char,             None),
+#    (c_byte,          Signed,           None),
+#    (c_ubyte,         Unsigned,         None),
+#    (c_short,         Signed,           None),
+#    (c_ushort,        Unsigned,         None),
+#    (c_int,           Signed,           None),
+#    (c_uint,          Unsigned,         None),
+#    (c_long,          Signed,           None),
+#    (c_ulong,         Unsigned,         None),
+#    (c_longlong,      SignedLongLong,   None),
+#    (c_ulonglong,     UnsignedLongLong, None),
+#    (c_float,         Float,            None),
+#    (c_double,        Float,            None),
     (c_char_p,        None, 
             staticmethod(lambda ll_type, arg_name:"RPyString_AsString(%s)" % arg_name)),
     (POINTER(c_char), None, 
@@ -63,11 +68,74 @@
             # the basic c_types need some annotation information
             # at the moment that are exactly the types that have
             # no 'wrap_arg'. This might change in the future
-            the_type.compute_result_annotation = classmethod(lambda cls, s_arg:SomeCTypesObject(cls))
+            #the_type.compute_result_annotation = classmethod(lambda cls, s_arg:SomeCTypesObject(cls))
+            def do_register(the_type):
+                extregistry.register_value(the_type, 
+                compute_result_annotation=lambda s_arg: SomeCTypesObject(the_type))
+                # XXX we need to register the correct repr for each primitive
+                extregistry.register_type(the_type,
+                    get_repr=lambda rtyper, s_primitive: rint.signed_repr)
+            do_register(the_type)
             the_type.default_memorystate = SomeCTypesObject.NOMEMORY
 
 create_ctypes_annotations()
 
+CFuncPtrType = type(ctypes.CFUNCTYPE(None))
+
+def cfuncptrtype_compute_annotation(type, instance):
+    def compute_result_annotation(*args_s):
+        """
+        Answer the annotation of the external function's result
+        """
+        # Take 3, Check whether we can get away with the cheap
+        # precomputed solution and if not it, use a special
+        # attribute with the memory state
+        try:
+            return instance.restype.annotator_type
+        except AttributeError:
+            return SomeCTypesObject( 
+                    instance.restype, 
+                    instance.restype.external_function_result_memorystate )
+        # Take 2, looks like we need another level of indirection
+        # That's to complicated
+        #o#return self.restype.compute_external_function_result_annotator_type()
+        # TODO: Check whether the function returns a pointer
+        # an correct the memory state appropriately
+        try:
+            return instance.restype.annotator_type
+        except AttributeError:
+            return SomeCTypesObject(instance.restype)
+        
+    return SomeBuiltin(compute_result_annotation, 
+        methodname=instance.__name__)
+
+def cfuncptrtype_specialize_call(hop):
+    # this is necessary to get the original function pointer when specializing
+    # the metatype
+    cfuncptr = hop.spaceop.args[0].value
+
+    def convert_params(backend, param_info_list):
+        assert "c" == backend.lower()
+        assert cfuncptr.argtypes is not None
+        answer = []
+        for ctype_type, (ll_type, arg_name) in zip(cfuncptr.argtypes,
+                                                    param_info_list):
+            if ll_type == ctype_type.ll_type:
+                answer.append(arg_name)
+            else:
+                answer.append(ctype_type.wrap_arg(ll_type, arg_name))
+        return answer
+
+    return hop.llops.gencapicall(
+            cfuncptr.__name__,
+            hop.args_v,
+            resulttype = cfuncptr.restype.ll_type,
+            _callable=None,
+            convert_params = convert_params ) 
+
+extregistry.register_metatype(CFuncPtrType, 
+    compute_annotation=cfuncptrtype_compute_annotation,
+    specialize_call=cfuncptrtype_specialize_call)
 
 class FunctionPointerTranslation(object):
 
@@ -98,9 +166,12 @@
             return id(self)
 
         def specialize(self, hop):
-            return hop.llops.gencapicall(self.__name__, hop.args_v,
-                         resulttype=self.restype.ll_type, _callable=None,
-                         convert_params=self.convert_params) 
+            return hop.llops.gencapicall(
+                    self.__name__,
+                    hop.args_v,
+                    resulttype = self.restype.ll_type,
+                    _callable=None,
+                    convert_params = self.convert_params ) 
 
         def convert_params(self, backend, param_info_list):
             assert "c" == backend.lower()
@@ -123,11 +194,15 @@
     def __new__(mta,name,bases,clsdict):
         _fields = clsdict.get('_fields_',None)
         _adict = {}
+        ll_types = []
         if _fields is not None:
             for attr, atype in _fields:
                 _adict[attr] = atype
+                ll_types.append( ( attr, atype.ll_type ) )
         clsdict['_fields_def_'] = _adict
-        print "_fields_def_ s:", _adict
+        # ll_type is just the C-level data part of the structure
+        clsdict[ "ll_type" ] = Struct( "C-Data_%s" % name, *ll_types )
+        #d#print "_fields_def_ s:", _adict
 
         return super(RStructureMeta,mta).__new__(mta, name, bases, clsdict)
 
@@ -221,7 +296,12 @@
         """
         Create a lowlevel representation for the pointer.
         """
-        return CtypesMemoryOwningPointerRepresentation( rtyper, annotationObject )
+        if annotationObject.memorystate == annotationObject.OWNSMEMORY:
+            return CtypesMemoryOwningPointerRepresentation( rtyper, annotationObject )
+        elif annotationObject.memorystate == annotationObject.MEMORYALIAS:
+            return CtypesMemoryAliasPointerRepresentation( rtyper, annotationObject )
+        else:
+            raise TyperError( "Unkown memory state in %r" % annotationObject )
     answer.createLowLevelRepresentation = staticmethod(
             createLowLevelRepresentation )
 
@@ -248,60 +328,69 @@
     # because we can't use the memory state from 'cls'.
     # So the obvious way to do it is obsolete (#o#).
     answer._fields_def_ = {"contents": cls}
-    print "p _fields_def_:", answer._fields_def_
+    #d#print "p _fields_def_:", answer._fields_def_
 
     # XXX Think about that twice and think about obsoleting
     # the obsoletion above
     answer.default_memorystate = None
     answer.external_function_result_memorystate = SomeCTypesObject.MEMORYALIAS
+    
+    # Add a low level type attribute, which is only used for computing the
+    # result of an external function. In other words this is just the non
+    # gc case
+    try:
+        answer.ll_type = Ptr(
+                Struct(
+                    'CtypesMemoryAliasPointer_%s' % answer.__name__,
+                    ( "contents", answer._type_.ll_type ) ) )
+    except TypeError:
+        pass
     return answer
 
 
-class RCDLL(CDLL):
-    """
-    This is the restricted version of ctypes' CDLL class.
-    """
-
-    class _CdeclFuncPtr(FunctionPointerTranslation, CDLL._CdeclFuncPtr):
-        """
-        A simple extension of ctypes function pointers that
-        implements a simple interface to the anotator.
-        """
-        _flags_ = _FUNCFLAG_CDECL
-
-
-
-if sys.platform == "win32":
-    class RWinDLL(WinDLL):
-        """
-        This is the restricted version of ctypes' WINDLL class
-        """
-
-        class _StdcallFuncPtr(FunctionPointerTranslation, WinDLL._StdcallFuncPtr):
-            """
-            A simple extension of ctypes function pointers that
-            implements a simple interface to the anotator.
-            """
-            _flags_ = _FUNCFLAG_STDCALL
-
-def RARRAY(typ,length):
-    answer = ARRAY(typ,length)
-    def compute_result_annotation(cls, *arg_s):
-        """
-        Answer the result annotation of calling 'cls'.
-        """
-        assert answer is cls
-        return SomeCTypesObject(cls, SomeCTypesObject.OWNSMEMORY)
-    answer.compute_result_annotation = classmethod(compute_result_annotation)
-    return answer
-
+# class RCDLL(CDLL):
+#     """
+#     This is the restricted version of ctypes' CDLL class.
+#     """
+# 
+#     class _CdeclFuncPtr(FunctionPointerTranslation, CDLL._CdeclFuncPtr):
+#         """
+#         A simple extension of ctypes function pointers that
+#         implements a simple interface to the anotator.
+#         """
+#         _flags_ = _FUNCFLAG_CDECL
+# 
+# 
+# 
+# if sys.platform == "win32":
+#     class RWinDLL(WinDLL):
+#         """
+#         This is the restricted version of ctypes' WINDLL class
+#         """
+# 
+#         class _StdcallFuncPtr(FunctionPointerTranslation, WinDLL._StdcallFuncPtr):
+#             """
+#             A simple extension of ctypes function pointers that
+#             implements a simple interface to the anotator.
+#             """
+#             _flags_ = _FUNCFLAG_STDCALL
+
+# def RARRAY(typ,length):
+#     answer = ARRAY(typ,length)
+#     def compute_result_annotation(cls, *arg_s):
+#         """
+#         Answer the result annotation of calling 'cls'.
+#         """
+#         assert answer is cls
+#         return SomeCTypesObject(cls, SomeCTypesObject.OWNSMEMORY)
+#     answer.compute_result_annotation = classmethod(compute_result_annotation)
+#     return answer
 
 class AbstractCtypesRepresentation( Repr ):
     """
     The abstract base class of all ctypes low level representations.
     """
 
-
 class AbstractCtypesStructureRepresentation( AbstractCtypesRepresentation ):
     """
     The abstract base class of ctypes structures' low level representation.
@@ -352,7 +441,8 @@
         fields = [ ( name, ctypesType.ll_type )
                         for name, ctypesType in annotationObject.knowntype._fields_ ]
         name = annotationObject.knowntype.__name__
-        self.c_data_lowleveltype = Struct( "C-Data_%s" % name, *fields )
+        #o#self.c_data_lowleveltype = Struct( "C-Data_%s" % name, *fields )
+        self.c_data_lowleveltype = annotationObject.knowntype.ll_type
         self.lowleveltype = Ptr(
                 GcStruct( 
                     "CtypesStructure_%s" % name,
@@ -382,10 +472,11 @@
     def __init__( self, rtyper, annotationObject ):
         self.lowleveltype = Ptr(
                 GcStruct(
-                    'CtypesPointer_%s' % annotationObject.knowntype.__name__,
+                    'CtypesMemoryOwningPointer_%s' % annotationObject.knowntype.__name__,
                     ( "contents",
                       rtyper.getrepr(
-                        annotationObject.knowntype._type_.compute_annotation() ).lowleveltype ) ) )
+                        annotationObject.knowntype._type_.compute_annotation()
+                        ).lowleveltype ) ) )
 
     def rtype_getattr( self, highLevelOperation ):
         inputargs = [ 
@@ -401,9 +492,15 @@
     to memory owned by an external library.
     """
 
+    def __init__( self, rtyper, annotationObject ):
+        self.lowleveltype = annotationObject.knowntype.ll_type
+
         
 class __extend__( SomeCTypesObject ):
     def rtyper_makerepr( self, rtyper ):
+        if extregistry.is_registered_type(self.knowntype):
+            entry = extregistry.lookup_type(self.knowntype)
+            return entry.get_repr(rtyper, self)
         return self.knowntype.createLowLevelRepresentation( rtyper, self )
         
     def rtyper_makekey( self ):

Modified: pypy/branch/njriley-trans/pypy/rpython/rctypes/interface.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/rctypes/interface.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/rctypes/interface.py	Fri Mar 10 06:12:02 2006
@@ -1,18 +1,18 @@
-from ctypes import _DLLS
-from implementation import RCDLL as CDLL, c_int, c_char_p, \
+from ctypes import cdll
+from implementation import c_int, c_char_p, \
         c_char, c_byte, c_ubyte, \
         c_short, c_ushort, c_uint,\
         c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double, \
         RStructure as Structure, RByref as byref, RPOINTER as POINTER, \
-        RARRAY as ARRAY
-try:
-    from implementation import RWinDLL as WinDLL
-except ImportError:
-    WinDLL = None
-
-cdll = _DLLS(CDLL)
-if WinDLL:
-    windll = _DLLS(WinDLL)
+        ARRAY
+#try:
+#    from implementation import RWinDLL as WinDLL
+#except ImportError:
+#    WinDLL = None
+
+#cdll = _DLLS(CDLL)
+#if WinDLL:
+#    windll = _DLLS(WinDLL)
 
 
 """

Modified: pypy/branch/njriley-trans/pypy/rpython/rctypes/test/test_rctypes.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/rctypes/test/test_rctypes.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/rctypes/test/test_rctypes.py	Fri Mar 10 06:12:02 2006
@@ -11,6 +11,7 @@
 from pypy.annotation.model import SomeCTypesObject, SomeObject
 from pypy import conftest
 import sys
+from pypy.rpython.test.test_llinterp import interpret
 
 thisdir = py.magic.autopath().dirpath()
 
@@ -42,15 +43,25 @@
     py.test.skip("this test needs ctypes installed")
 
 
+py.test.skip("these tests are broken while the ctypes primitive types are ported to use the extregistry")
+
 from pypy.rpython.rctypes import cdll, c_char_p, c_int, c_char, \
         c_char, c_byte, c_ubyte, c_short, c_ushort, c_uint,\
         c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double, \
         POINTER, Structure, byref, ARRAY
 
+# LoadLibrary is deprecated in ctypes, this should be removed at some point
+if "load" in dir(cdll):
+    cdll_load = cdll.load
+else:
+    cdll_load = cdll.LoadLibrary
+
 if sys.platform == 'win32':
-    mylib = cdll.LoadLibrary('msvcrt.dll')
+    mylib = cdll_load('msvcrt.dll')
 elif sys.platform == 'linux2':
-    mylib = cdll.LoadLibrary('libc.so.6')
+    mylib = cdll_load('libc.so.6')
+elif sys.platform == 'darwin':
+    mylib = cdll.c
 else:
     py.test.skip("don't know how to load the c lib for %s" % 
             sys.platform)
@@ -73,9 +84,9 @@
 compile_c_module([thisdir.join("_rctypes_test.c")], "_rctypes_test")
 
 if sys.platform == "win32":
-    _rctypes_test = cdll.LoadLibrary("_rctypes_test.pyd")
+    _rctypes_test = cdll_load("_rctypes_test.pyd")
 else:
-    _rctypes_test = cdll.LoadLibrary(str(thisdir.join("_rctypes_test.so")))
+    _rctypes_test = cdll_load(str(thisdir.join("_rctypes_test.so")))
 
 # _testfunc_byval
 testfunc_byval = _rctypes_test._testfunc_byval
@@ -234,7 +245,6 @@
     s.y = y
     return s
 
-
 class Test_rctypes:
 
     def test_simple(self):
@@ -265,16 +275,19 @@
 class Test_structure:
 
     def test_simple_as_extension_module(self):
-        import _rctypes_test as t0
-        import _rctypes_test as t1
+        # Full path names follow because of strange behavior in the presence
+        # of an __init__.py in this test directory.  When there is an
+        # __init__.py then the full path names appear in sys.modules
+        import pypy.rpython.rctypes.test._rctypes_test as t0
+        import pypy.rpython.rctypes.test._rctypes_test as t1
         assert t1 is t0
-        assert "_rctypes_test" in sys.modules
+        assert "pypy.rpython.rctypes.test._rctypes_test" in sys.modules
 
     def test_simple(self):
         if sys.platform == "win32":
-            dll = cdll.LoadLibrary("_rctypes_test.pyd")
+            dll = cdll_load("_rctypes_test.pyd")
         else:
-            dll = cdll.LoadLibrary(str(thisdir.join("_rctypes_test.so")))
+            dll = cdll_load(str(thisdir.join("_rctypes_test.so")))
         in_point = tagpoint()
         in_point.x = 42
         in_point.y = 17
@@ -292,10 +305,13 @@
 
     def test_annotate_struct(self):
         a = RPythonAnnotator()
-        s = a.build_types(py_testfunc_struct, [int])
+        s = a.build_types(py_testfunc_struct, [tagpoint])
         assert s.knowntype == int
+        
+        if conftest.option.view:
+            a.translator.view()
 
-    def test_annotate_struct(self):
+    def test_annotate_struct2(self):
         t = TranslationContext()
         a = t.buildannotator()
         s = a.build_types(py_testfunc_struct_id, [tagpoint])
@@ -316,6 +332,9 @@
         s = a.build_types(py_create_point,[])
         assert s.knowntype == int
 
+        if conftest.option.view:
+            a.translator.view()
+
     def test_annotate_byval(self):
         t = TranslationContext()
         a = t.buildannotator()
@@ -357,7 +376,7 @@
         #d#t.view()
         assert s.knowntype == tagpoint
         # This memory state will be supported in the future (#f#)
-	# Obviously the test is wrong for now
+        # Obviously the test is wrong for now
         #f#assert s.memorystate == SomeCTypesObject.MIXEDMEMORYOWNERSHIP
         assert isinstance(s, SomeObject)
 
@@ -399,8 +418,8 @@
         try:
             t.buildrtyper().specialize()
         finally:
-            #d#t.view()
-            pass
+            if conftest.option.view:
+                t.view()
 
     def test_specialize_struct_1(self):
         t = TranslationContext()
@@ -413,14 +432,14 @@
             #d#t.view()
             pass
 
-    # This does not work yet, ctype structures and pointers are
-    # missing the ll_type attribute that directly maps ctypes objects
-    # to the lltype system
-    # TODO: Find an indirect way to get that mapping done
-    def x_test_specialize_pointer_to_struct(self):
+    def test_specialize_pointer_to_struct(self):
         t = self.test_annotate_pointer_to_struct()
         t.buildrtyper().specialize()
-        t.view()
+        if conftest.option.view:
+            t.view()
+
+    def x_test_compile_pointer_to_struct(self):
+        fn = compile( py_testfunc_struct_pointer_id, [ oppoint_type ] )
 
     def test_compile_struct(self):
         fn = compile( py_test_compile_struct, [ int, int ] )
@@ -451,62 +470,3 @@
         fn = compile( py_test_compile_pointer, [ int, int ] )
         res = fn( -42, 42 )
         assert res == -42
-
-
-class Test_array:
-
-    def test_annotate_array(self):
-        a = RPythonAnnotator()
-        s = a.build_types(py_test_annotate_array, [])
-        assert s.knowntype == c_int_10
-
-    def test_annotate_array_access(self):
-        t = TranslationContext()
-        a = t.buildannotator()
-        s = a.build_types(py_test_annotate_array_content, [])
-        assert s.knowntype == int
-        #d#t.view()
-
-    def test_annotate_pointer_access_as_array(self):
-        """
-        Make sure that pointers work the same way as arrays, for 
-        ctypes compatibility.
-
-        :Note: This works because pointer and array classes both
-        have a _type_ attribute, that contains the type of the 
-        object pointed to or in the case of an array the element type. 
-        """
-        t = TranslationContext()
-        a = t.buildannotator()
-        s = a.build_types(py_test_annotate_pointer_content, [])
-        assert s.knowntype == int
-        #d#t.view()
-
-    def test_annotate_array_slice_access(self):
-        t = TranslationContext()
-        a = t.buildannotator()
-        s = a.build_types(py_test_annotate_array_slice_content, [])
-        #d#t.view()
-        #d#print "v90:", s, type(s)
-        assert s.knowntype == list
-        s.listdef.listitem.s_value.knowntype == int
-
-    def test_annotate_array_access_variable(self):
-        t = TranslationContext()
-        a = t.buildannotator()
-        s = a.build_types(py_test_annotate_array_content_variable_index, [])
-        assert s.knowntype == int
-        #t#t.view()
-
-    def test_annotate_array_access_index_error_on_positive_index(self):
-        t = TranslationContext()
-        a = t.buildannotator()
-        
-        py.test.raises(IndexError, "s = a.build_types(py_test_annotate_array_content_index_error_on_positive_index,[])")
-
-    def test_annotate_array_access_index_error_on_negative_index(self):
-        t = TranslationContext()
-        a = t.buildannotator()
-        
-        py.test.raises(IndexError, "s = a.build_types(py_test_annotate_array_content_index_error_on_negative_index,[])")
-

Modified: pypy/branch/njriley-trans/pypy/rpython/rgenop.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/rgenop.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/rgenop.py	Fri Mar 10 06:12:02 2006
@@ -4,7 +4,7 @@
 that can be used to produce any other kind of graph.
 """
 
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.objspace.flow import model as flowmodel
 from pypy.translator.simplify import eliminate_empty_blocks, join_blocks
 from pypy.rpython.module.support import init_opaque_object
@@ -72,6 +72,16 @@
         assert not isinstance(llvalue, str) and not isinstance(llvalue, lltype.LowLevelType)
     return to_opaque_object(v)
 
+def revealconst(T, gv_value):
+    c = from_opaque_object(gv_value)
+    assert isinstance(c, flowmodel.Constant)
+    if isinstance(T, lltype.Ptr):
+        return lltype.cast_pointer(T, c.value)
+    elif T == llmemory.Address:
+        return llmemory.cast_ptr_to_adr(c.value)
+    else:
+        return lltype.cast_primitive(T, c.value)
+                                    
 # XXX
 # temporary interface; it's unclera if genop itself should change to ease dinstinguishing
 # Void special args from the rest. Or there should be variation for the ops involving them
@@ -238,6 +248,7 @@
 setannotation(geninputarg, s_ConstOrVar)
 setannotation(genop, s_ConstOrVar)
 setannotation(genconst, s_ConstOrVar)
+revealconst.compute_result_annotation = lambda s_T, s_gv: annmodel.lltype_to_annotation(s_T.const)
 setannotation(closeblock1, s_Link)
 setannotation(closeblock2, s_LinkPair)
 setannotation(closelink, None)
@@ -248,6 +259,7 @@
 setspecialize(geninputarg)
 setspecialize(genop)
 setspecialize(genconst)
+setspecialize(revealconst)
 setspecialize(closeblock1)
 setspecialize(closeblock2)
 setspecialize(closelink)

Modified: pypy/branch/njriley-trans/pypy/rpython/rmodel.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/rmodel.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/rmodel.py	Fri Mar 10 06:12:02 2006
@@ -4,7 +4,7 @@
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.lltypesystem.lltype import \
      Void, Bool, Float, Signed, Char, UniChar, \
-     typeOf, LowLevelType, Ptr, PyObject
+     typeOf, LowLevelType, Ptr, PyObject, isCompatibleType
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.error import TyperError, MissingRTypeOperation 
 
@@ -235,22 +235,7 @@
     def rtype_is_((robj1, robj2), hop):
         if hop.s_result.is_constant():
             return inputconst(Bool, hop.s_result.const)
-        roriginal1 = robj1
-        roriginal2 = robj2
-        if robj1.lowleveltype is Void:
-            robj1 = robj2
-        elif robj2.lowleveltype is Void:
-            robj2 = robj1
-        if (not isinstance(robj1.lowleveltype, Ptr) or
-            not isinstance(robj2.lowleveltype, Ptr)):
-            raise TyperError('is of instances of the non-pointers: %r, %r' % (
-                roriginal1, roriginal2))
-        if robj1.lowleveltype != robj2.lowleveltype:
-            raise TyperError('is of instances of different pointer types: %r, %r' % (
-                roriginal1, roriginal2))
-            
-        v_list = hop.inputargs(robj1, robj2)
-        return hop.genop('ptr_eq', v_list, resulttype=Bool)
+        return hop.rtyper.type_system.generic_is(robj1, robj2, hop)
 
 # ____________________________________________________________
 
@@ -344,7 +329,7 @@
             realtype = typeOf(value)
         except (AssertionError, AttributeError):
             realtype = '???'
-        if realtype != lltype:
+        if not isCompatibleType(realtype, lltype):
             raise TyperError("inputconst(reqtype = %s, value = %s):\n"
                              "expected a %r,\n"
                              "     got a %r" % (reqtype, value,

Modified: pypy/branch/njriley-trans/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/rpbc.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/rpbc.py	Fri Mar 10 06:12:02 2006
@@ -7,7 +7,8 @@
 from pypy.rpython.lltypesystem.lltype import \
      typeOf, Void, Bool, nullptr, frozendict, Ptr, Struct, malloc
 from pypy.rpython.error import TyperError
-from pypy.rpython.rmodel import Repr, inputconst, HalfConcreteWrapper, CanBeNull
+from pypy.rpython.rmodel import Repr, inputconst, HalfConcreteWrapper, CanBeNull, \
+        mangle, inputdesc, warning
 from pypy.rpython import rclass
 from pypy.rpython import robject
 
@@ -25,7 +26,7 @@
                 if sample.overridden:
                     getRepr = OverriddenFunctionPBCRepr
                 else:
-                    getRepr = FunctionsPBCRepr
+                    getRepr = rtyper.type_system.rpbc.FunctionsPBCRepr
             else:
                 getRepr = getFrozenPBCRepr
         elif issubclass(kind, description.ClassDesc):
@@ -154,7 +155,7 @@
     return concretetable, uniquerows
 
 
-class FunctionsPBCRepr(CanBeNull, Repr):
+class AbstractFunctionsPBCRepr(CanBeNull, Repr):
     """Representation selected for a PBC of function(s)."""
 
     def __init__(self, rtyper, s_pbc):
@@ -176,10 +177,7 @@
                 # several functions, each with several specialized variants.
                 # each function becomes a pointer to a Struct containing
                 # pointers to its variants.
-                fields = []
-                for row in uniquerows:
-                    fields.append((row.attrname, row.fntype))
-                self.lowleveltype = Ptr(Struct('specfunc', *fields))
+                self.lowleveltype = self.setup_specfunc()
         self.funccache = {}
 
     def get_s_callable(self):
@@ -229,7 +227,7 @@
                 result = llfn   # from the loop above
             else:
                 # build a Struct with all the values collected in 'llfns'
-                result = malloc(self.lowleveltype.TO, immortal=True)
+                result = self.create_specfunc()
                 for attrname, llfn in llfns.items():
                     setattr(result, attrname, llfn)
         self.funccache[funcdesc] = result
@@ -266,7 +264,7 @@
             # 'v' is a Struct pointer, read the corresponding field
             row = self.concretetable[shape, index]
             cname = inputconst(Void, row.attrname)
-            return llop.genop('getfield', [v, cname], resulttype = row.fntype)
+            return self.get_specfunc_row(llop, v, cname, row.fntype)
 
     def get_unique_llfn(self):
         # try to build a unique low-level function.  Avoid to use
@@ -319,7 +317,7 @@
             v = hop.genop('indirect_call', vlist, resulttype = rresult)
         return hop.llops.convertvar(v, rresult, hop.r_result)
 
-class __extend__(pairtype(FunctionsPBCRepr, FunctionsPBCRepr)):
+class __extend__(pairtype(AbstractFunctionsPBCRepr, AbstractFunctionsPBCRepr)):
         def convert_from_to((r_fpbc1, r_fpbc2), v, llops):
             # this check makes sense because both source and dest repr are FunctionsPBCRepr
             if r_fpbc1.lowleveltype == r_fpbc2.lowleveltype:
@@ -378,6 +376,146 @@
         assert frozendesc is self.frozendesc
         return object()  # lowleveltype is Void
 
+
+class AbstractMultipleFrozenPBCRepr(CanBeNull, Repr):
+
+    def _setup_repr_fields(self):
+        fields = []
+        self.fieldmap = {}
+        if self.access_set is not None:
+            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 = mangle('pbc', attr)
+                fields.append((mangled_name, r_value.lowleveltype))
+                self.fieldmap[attr] = mangled_name, r_value
+        return fields 
+
+    def convert_desc(self, frozendesc):
+        if (self.access_set is not None and
+            frozendesc not in self.access_set.descs):
+            raise TyperError("not found in PBC access set: %r" % (frozendesc,))
+        try:
+            return self.pbc_cache[frozendesc]
+        except KeyError:
+            self.setup()
+            result = self.create_instance()
+            self.pbc_cache[frozendesc] = result
+            for attr, (mangled_name, r_value) in self.fieldmap.items():
+                if r_value.lowleveltype is Void:
+                    continue
+                try:
+                    thisattrvalue = frozendesc.read_attribute(attr)
+                except AttributeError:
+                    warning("Desc %r has no attribute %r" % (frozendesc, attr))
+                    continue
+                llvalue = r_value.convert_const(thisattrvalue)
+                setattr(result, mangled_name, llvalue)
+            return result
+
+    def convert_const(self, pbc):
+        if pbc is None:
+            return self.null_instance() 
+        if isinstance(pbc, types.MethodType) and pbc.im_self is None:
+            value = pbc.im_func   # unbound method -> bare function
+        frozendesc = self.rtyper.annotator.bookkeeper.getdesc(pbc)
+        return self.convert_desc(frozendesc)
+    
+    def rtype_getattr(self, hop):
+        attr = hop.args_s[1].const
+        vpbc, vattr = hop.inputargs(self, Void)
+        v_res = self.getfield(vpbc, attr, hop.llops)
+        mangled_name, r_res = self.fieldmap[attr]
+        return hop.llops.convertvar(v_res, r_res, hop.r_result)
+
+class __extend__(pairtype(AbstractMultipleFrozenPBCRepr, AbstractMultipleFrozenPBCRepr)):
+    def convert_from_to((r_pbc1, r_pbc2), v, llops):
+        if r_pbc1.access_set == r_pbc2.access_set:
+            return v
+        return NotImplemented
+
+class __extend__(pairtype(SingleFrozenPBCRepr, AbstractMultipleFrozenPBCRepr)):
+    def convert_from_to((r_pbc1, r_pbc2), v, llops):
+        frozendesc1 = r_pbc1.frozendesc
+        access = frozendesc1.queryattrfamily()
+        if access is r_pbc2.access_set:
+            return inputdesc(r_pbc2, frozendesc1)
+        return NotImplemented
+
+
+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.funcdesc = s_pbc.descriptions.keys()[0].funcdesc
+
+        # a hack to force the underlying function to show up in call_families
+        # (generally not needed, as normalizecalls() should ensure this,
+        # but needed for bound methods that are ll helpers)
+        # XXX sort this out
+        #call_families = rtyper.annotator.getpbccallfamilies()
+        #call_families.find((None, self.function))
+        
+        if s_pbc.can_be_none():
+            raise TyperError("unsupported: variable of type "
+                             "method-of-frozen-PBC or None")
+
+        im_selves = []
+        for desc in s_pbc.descriptions:
+            assert desc.funcdesc is self.funcdesc
+            im_selves.append(desc.frozendesc)
+            
+        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 get_s_callable(self):
+        return annmodel.SomePBC([self.funcdesc])
+
+    def get_r_implfunc(self):
+        r_func = self.rtyper.getrepr(self.get_s_callable())
+        return r_func, 1
+
+    def convert_desc(self, mdesc):
+        if mdesc.funcdesc is not self.funcdesc:
+            raise TyperError("not a method bound on %r: %r" % (self.funcdesc, 
+                                                               mdesc))
+        return self.r_im_self.convert_desc(mdesc.frozendesc)
+
+    def convert_const(self, method):
+        mdesc = self.rtyper.annotator.bookkeeper.getdesc(method)
+        return self.convert_desc(mdesc)
+
+    def rtype_simple_call(self, hop):
+        return self.redispatch_call(hop, call_args=False)
+
+    def rtype_call_args(self, hop):
+        return self.redispatch_call(hop, call_args=True)
+
+    def redispatch_call(self, hop, call_args):
+        # XXX obscure, try to refactor...
+        s_function = annmodel.SomePBC([self.funcdesc])
+        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):
+            boundmethod = hop2.args_v[0].value
+            hop2.args_v[0] = Constant(boundmethod.im_self)
+        if call_args:
+            hop2.swap_fst_snd_args()
+            _, s_shape = hop2.r_s_popfirstarg() # temporarely remove shape
+            adjust_shape(hop2, s_shape)
+        # a marker that would crash if actually used...
+        c = Constant("obscure-don't-use-me")
+        hop2.v_s_insertfirstarg(c, s_function)   # insert 'function'
+        # now hop2 looks like simple_call(function, self, args...)
+        return hop2.dispatch()
+
 # __ None ____________________________________________________
 class NoneFrozenPBCRepr(SingleFrozenPBCRepr):
     
@@ -468,6 +606,18 @@
             r_res = self.rtyper.getrepr(s_res)
             return hop.llops.convertvar(v_res, r_res, hop.r_result)
 
+    def replace_class_with_inst_arg(self, hop, v_inst, s_inst, call_args):
+        hop2 = hop.copy()
+        hop2.r_s_popfirstarg()   # discard the class pointer argument
+        if call_args:
+            _, s_shape = hop2.r_s_popfirstarg() # temporarely remove shape
+            hop2.v_s_insertfirstarg(v_inst, s_inst)  # add 'instance'
+            adjust_shape(hop2, s_shape)
+        else:
+            hop2.v_s_insertfirstarg(v_inst, s_inst)  # add 'instance'
+        return hop2
+
+
 class __extend__(pairtype(AbstractClassesPBCRepr, rclass.AbstractClassRepr)):
     def convert_from_to((r_clspbc, r_cls), v, llops):
         # turn a PBC of classes to a standard pointer-to-vtable class repr
@@ -481,7 +631,7 @@
             r_clspbc.rtyper.type_system.rclass.CLASSTYPE)
         if not r_clspbc.get_class_repr().classdef.issubclass(r_cls.classdef):
             return NotImplemented
-        return r_cls.fromtypeptr(v, llops)
+        return r_cls.fromclasstype(v, llops)
 
 class __extend__(pairtype(AbstractClassesPBCRepr, AbstractClassesPBCRepr)):
     def convert_from_to((r_clspbc1, r_clspbc2), v, llops):
@@ -492,6 +642,12 @@
             return inputconst(r_clspbc2, r_clspbc1.s_pbc.const)
         return NotImplemented
 
+def adjust_shape(hop2, s_shape):
+    new_shape = (s_shape.const[0]+1,) + s_shape.const[1:]
+    c_shape = Constant(new_shape)
+    s_shape = hop2.rtyper.annotator.bookkeeper.immutablevalue(new_shape)
+    hop2.v_s_insertfirstarg(c_shape, s_shape) # reinsert adjusted shape
+
 class AbstractMethodsPBCRepr(Repr):
     """Representation selected for a PBC of MethodDescs.
     It assumes that all the methods come from the same name and have
@@ -541,6 +697,16 @@
         # (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 add_instance_arg_to_hop(self, hop, call_args):
+        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 call_args:
+            hop2.swap_fst_snd_args()
+            _, s_shape = hop2.r_s_popfirstarg()
+            adjust_shape(hop2, s_shape)
+        return hop2
 # ____________________________________________________________
 
 ##def getsignature(rtyper, func):

Modified: pypy/branch/njriley-trans/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/rtyper.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/rtyper.py	Fri Mar 10 06:12:02 2006
@@ -66,10 +66,8 @@
         for s_primitive, lltype in annmodel.annotation_to_ll_map:
             r = self.getrepr(s_primitive)
             self.primitive_to_repr[r.lowleveltype] = r
-        if type_system == "lltype":
-            from pypy.rpython.lltypesystem.exceptiondata import ExceptionData
-
-            self.exceptiondata = ExceptionData(self)
+        if self.type_system.offers_exceptiondata:
+            self.exceptiondata = self.type_system.exceptiondata.ExceptionData(self)
         else:
             self.exceptiondata = None
 

Modified: pypy/branch/njriley-trans/pypy/rpython/test/test_llinterp.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/test/test_llinterp.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/test/test_llinterp.py	Fri Mar 10 06:12:02 2006
@@ -65,6 +65,10 @@
 
 _lastinterpreted = []
 _tcache = {}
+def clear_tcache():
+    del _lastinterpreted[:]
+    _tcache.clear()
+
 def get_interpreter(func, values, view='auto', viewbefore='auto', policy=None,
                     someobjects=False, type_system="lltype"):
     key = (func,) + tuple([typeOf(x) for x in values])+ (someobjects,)
@@ -423,6 +427,58 @@
     fgraph.startblock.operations[0].opname = "flavored_malloc"
     fgraph.startblock.operations[0].args.insert(0, inputconst(Void, "stack"))
     py.test.raises(AttributeError, "interp.eval_graph(graph, [])")
+
+
+def test_cleanup_finally():
+    interp, graph = get_interpreter(cleanup_f, [-1])
+    clear_tcache()    # because we hack the graph in place
+    operations = graph.startblock.operations
+    assert operations[0].opname == "direct_call"
+    assert operations[1].opname == "direct_call"
+    assert getattr(operations[0], 'cleanup', None) is None
+    assert getattr(operations[1], 'cleanup', None) is None
+    cleanup_finally = (operations.pop(1),)
+    cleanup_except = ()
+    operations[0].cleanup = cleanup_finally, cleanup_except
+
+    # state.current == 1
+    res = interp.eval_graph(graph, [1])
+    assert res == 102
+    # state.current == 2
+    res = interp.eval_graph(graph, [1])
+    assert res == 203
+    # state.current == 3
+    py.test.raises(LLException, "interp.eval_graph(graph, [-1])")
+    # state.current == 4
+    res = interp.eval_graph(graph, [1])
+    assert res == 405
+    # state.current == 5
+
+def test_cleanup_except():
+    interp, graph = get_interpreter(cleanup_f, [-1])
+    clear_tcache()    # because we hack the graph in place
+    operations = graph.startblock.operations
+    assert operations[0].opname == "direct_call"
+    assert operations[1].opname == "direct_call"
+    assert getattr(operations[0], 'cleanup', None) is None
+    assert getattr(operations[1], 'cleanup', None) is None
+    cleanup_finally = ()
+    cleanup_except = (operations.pop(1),)
+    operations[0].cleanup = cleanup_finally, cleanup_except
+
+    # state.current == 1
+    res = interp.eval_graph(graph, [1])
+    assert res == 101
+    # state.current == 1
+    res = interp.eval_graph(graph, [1])
+    assert res == 101
+    # state.current == 1
+    py.test.raises(LLException, "interp.eval_graph(graph, [-1])")
+    # state.current == 2
+    res = interp.eval_graph(graph, [1])
+    assert res == 202
+    # state.current == 2
+
 #__________________________________________________________________
 # example functions for testing the LLInterpreter
 _snap = globals().copy()
@@ -483,3 +539,19 @@
     except ValueError:
         raise TypeError
 
+# test for the 'cleanup' attribute of SpaceOperations
+class CleanupState(object):
+    pass
+cleanup_state = CleanupState()
+cleanup_state.current = 1
+def cleanup_g(n):
+    cleanup_state.saved = cleanup_state.current
+    if n < 0:
+        raise ZeroDivisionError
+def cleanup_h():
+    cleanup_state.current += 1
+def cleanup_f(n):
+    cleanup_g(n)
+    cleanup_h()     # the test hacks the graph to put this h() in the
+                    # cleanup clause of the previous direct_call(g)
+    return cleanup_state.saved * 100 + cleanup_state.current

Modified: pypy/branch/njriley-trans/pypy/rpython/test/test_ootype_llinterp.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/test/test_ootype_llinterp.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/test/test_ootype_llinterp.py	Fri Mar 10 06:12:02 2006
@@ -2,7 +2,7 @@
 from pypy.rpython.test.test_llinterp import interpret
 
 def test_simple_field():
-    C = Instance("test", None, {'a': (Signed, 3)})
+    C = Instance("test", ROOT, {'a': (Signed, 3)})
     
     def f():
         c = new(C)
@@ -13,7 +13,7 @@
     assert result == 5
 
 def test_simple_method():
-    C = Instance("test", None, {'a': (Signed, 3)})
+    C = Instance("test", ROOT, {'a': (Signed, 3)})
     M = Meth([], Signed)
     def m_(self):
        return self.a

Modified: pypy/branch/njriley-trans/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/test/test_rclass.py	Fri Mar 10 06:12:02 2006
@@ -1,79 +1,18 @@
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.lltypesystem.lltype import *
+from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.rpython.rarithmetic import intmask
 
+
 class EmptyBase(object):
     pass
 
-
-def test_simple():
-    def dummyfn():
-        x = EmptyBase()
-        return x
-    res = interpret(dummyfn, [])
-    T = typeOf(res)
-    assert isinstance(T, Ptr) and isinstance(T.TO, GcStruct)
-
-def test_instanceattr():
-    def dummyfn():
-        x = EmptyBase()
-        x.a = 5
-        x.a += 1
-        return x.a
-    res = interpret(dummyfn, [])
-    assert res == 6
-
 class Random:
     xyzzy = 12
     yadda = 21
 
-def test_classattr():
-    def dummyfn():
-        x = Random()
-        return x.xyzzy
-    res = interpret(dummyfn, [])
-    assert res == 12
-
-def test_classattr_as_defaults():
-    def dummyfn():
-        x = Random()
-        x.xyzzy += 1
-        return x.xyzzy
-    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
-
-def test_prebuilt_instances_with_void():
-    def marker():
-        return 42
-    a = EmptyBase()
-    a.nothing_special = marker
-    def dummyfn():
-        return a.nothing_special()
-    res = interpret(dummyfn, [])
-    assert res == 42
-
-# method calls
+# for method calls
 class A:
     def f(self):
         return self.g()
@@ -88,349 +27,503 @@
 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 f(i):
-        if i == 0:
-            o = None
-        elif i == 1:
-            o = A()
-        elif i == 2:
-            o = B()
+class BaseTestRclass:
+
+    def test_instanceattr(self):
+        def dummyfn():
+            x = EmptyBase()
+            x.a = 5
+            x.a += 1
+            return x.a
+        res = interpret(dummyfn, [], type_system=self.ts)
+        assert res == 6
+
+    def test_simple(self):
+        def dummyfn():
+            x = EmptyBase()
+            return x
+        res = interpret(dummyfn, [], type_system=self.ts)
+        T = typeOf(res)
+        if self.ts == "lltype":
+            assert isinstance(T, Ptr) and isinstance(T.TO, GcStruct)
         else:
-            o = C()
-        return 100*isinstance(o, A)+10*isinstance(o, B)+1*isinstance(o ,C)
+            assert isinstance(T, ootype.Instance)
 
-    res = interpret(f, [1])
-    assert res == 100
-    res = interpret(f, [2])
-    assert res == 110
-    res = interpret(f, [3])
-    assert res == 111
-
-    res = interpret(f, [0])
-    assert res == 0
-
-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
-
-def test_issubclass_type():
-    class Abstract:
-        pass
-    class A(Abstract):
-        pass
-    class B(A):
-        pass
-    def f(i):
-        if i == 0: 
-            c1 = A()
-        else: 
-            c1 = B()
-        return issubclass(type(c1), B)
-    assert interpret(f, [0], view=False, viewbefore=False) == False 
-    assert interpret(f, [1], view=False, viewbefore=False) == True
-
-    def g(i):
-        if i == 0: 
-            c1 = A()
-        else: 
-            c1 = B()
-        return issubclass(type(c1), A)
-    assert interpret(g, [0], view=False, viewbefore=False) == True
-    assert interpret(g, [1], view=False, viewbefore=False) == True
-
-def test_staticmethod():
-    class A(object):
-        f = staticmethod(lambda x, y: x*y)
-    def f():
-        a = A()
-        return a.f(6, 7)
-    res = interpret(f, [])
-    assert res == 42
-
-def test_is():
-    class A: pass
-    class B(A): pass
-    class C: pass
-    def f(i):
-        a = A()
-        b = B()
-        c = C()
-        d = None
-        e = None
-        if i == 0:
-            d = a
-        elif i == 1:
-            d = b
-        elif i == 2:
-            e = c
-        return (0x0001*(a is b) | 0x0002*(a is c) | 0x0004*(a is d) |
-                0x0008*(a is e) | 0x0010*(b is c) | 0x0020*(b is d) |
-                0x0040*(b is e) | 0x0080*(c is d) | 0x0100*(c is e) |
-                0x0200*(d is e))
-    res = interpret(f, [0])
-    assert res == 0x0004
-    res = interpret(f, [1])
-    assert res == 0x0020
-    res = interpret(f, [2])
-    assert res == 0x0100
-    res = interpret(f, [3])
-    assert res == 0x0200
-
-def test_eq():
-    class A: pass
-    class B(A): pass
-    class C: pass
-    def f(i):
-        a = A()
-        b = B()
-        c = C()
-        d = None
-        e = None
-        if i == 0:
-            d = a
-        elif i == 1:
-            d = b
-        elif i == 2:
-            e = c
-        return (0x0001*(a == b) | 0x0002*(a == c) | 0x0004*(a == d) |
-                0x0008*(a == e) | 0x0010*(b == c) | 0x0020*(b == d) |
-                0x0040*(b == e) | 0x0080*(c == d) | 0x0100*(c == e) |
-                0x0200*(d == e))
-    res = interpret(f, [0])
-    assert res == 0x0004
-    res = interpret(f, [1])
-    assert res == 0x0020
-    res = interpret(f, [2])
-    assert res == 0x0100
-    res = interpret(f, [3])
-    assert res == 0x0200
-
-def test_istrue():
-    class A:
-        pass
-    def f(i):
-        if i == 0:
+
+    def test_classattr(self):
+        def dummyfn():
+            x = Random()
+            return x.xyzzy
+        res = interpret(dummyfn, [], type_system=self.ts)
+        assert res == 12
+
+    def test_classattr_both(self):
+        print self.ts
+        class A:
+            a = 1
+        class B(A):
+            a = 2
+        def pick(i):
+            if i == 0:
+                return A
+            else:
+                return B
+            
+        def dummyfn(i):
+            C = pick(i)
+            i = C()
+            return C.a + i.a
+        res = interpret(dummyfn, [0], type_system=self.ts)
+        assert res == 2
+        res = interpret(dummyfn, [1], type_system=self.ts)
+        assert res == 4
+
+    def test_classattr_as_defaults(self):
+        def dummyfn():
+            x = Random()
+            x.xyzzy += 1
+            return x.xyzzy
+        res = interpret(dummyfn, [], type_system=self.ts)
+        assert res == 13
+
+    def test_prebuilt_instance(self):
+        a = EmptyBase()
+        a.x = 5
+        def dummyfn():
+            a.x += 1
+            return a.x
+        interpret(dummyfn, [], type_system=self.ts)
+
+    def test_recursive_prebuilt_instance(self):
+        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, [], type_system=self.ts)
+        assert res == 6
+
+    def test_prebuilt_instances_with_void(self):
+        def marker():
+            return 42
+        a = EmptyBase()
+        a.nothing_special = marker
+        def dummyfn():
+            return a.nothing_special()
+        res = interpret(dummyfn, [], type_system=self.ts)
+        assert res == 42
+
+    def test_simple_method_call(self):
+        def f(i):
+            if i:
+                a = A()
+            else:
+                a = B()
+            return a.f()
+        res = interpret(f, [True], type_system=self.ts)
+        assert res == 42
+        res = interpret(f, [False], type_system=self.ts)
+        assert res == 1
+
+    def test_isinstance(self):
+        def f(i):
+            if i == 0:
+                o = None
+            elif i == 1:
+                o = A()
+            elif i == 2:
+                o = B()
+            else:
+                o = C()
+            return 100*isinstance(o, A)+10*isinstance(o, B)+1*isinstance(o ,C)
+
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 100
+        res = interpret(f, [2], type_system=self.ts)
+        assert res == 110
+        res = interpret(f, [3], type_system=self.ts)
+        assert res == 111
+
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 0
+
+    def test_method_used_in_subclasses_only(self):
+        class A:
+            def meth(self):
+                return 123
+        class B(A):
+            pass
+        def f():
+            x = B()
+            return x.meth()
+        res = interpret(f, [], type_system=self.ts)
+        assert res == 123
+
+    def test_method_both_A_and_B(self):
+        class A:
+            def meth(self):
+                return 123
+        class B(A):
+            pass
+        def f():
             a = A()
-        else:
-            a = None
-        if a:
-            return 1
-        else:
-            return 2
-    res = interpret(f, [0])
-    assert res == 1
-    res = interpret(f, [1])
-    assert res == 2
-
-def test_ne():
-    class A: pass
-    class B(A): pass
-    class C: pass
-    def f(i):
-        a = A()
-        b = B()
+            b = B()
+            return a.meth() + b.meth()
+        res = interpret(f, [], type_system=self.ts)
+        assert res == 246
+
+    def test_issubclass_type(self):
+        class Abstract:
+            pass
+        class A(Abstract):
+            pass
+        class B(A):
+            pass
+        def f(i):
+            if i == 0: 
+                c1 = A()
+            else: 
+                c1 = B()
+            return issubclass(type(c1), B)
+        assert interpret(f, [0], type_system=self.ts) == False 
+        assert interpret(f, [1], type_system=self.ts) == True
+
+        def g(i):
+            if i == 0: 
+                c1 = A()
+            else: 
+                c1 = B()
+            return issubclass(type(c1), A)
+        assert interpret(g, [0], type_system=self.ts) == True
+        assert interpret(g, [1], type_system=self.ts) == True
+
+    def test_staticmethod(self):
+        class A(object):
+            f = staticmethod(lambda x, y: x*y)
+        def f():
+            a = A()
+            return a.f(6, 7)
+        res = interpret(f, [], type_system=self.ts)
+        assert res == 42
+
+    def test_is(self):
+        class A: pass
+        class B(A): pass
+        class C: pass
+        def f(i):
+            a = A()
+            b = B()
+            c = C()
+            d = None
+            e = None
+            if i == 0:
+                d = a
+            elif i == 1:
+                d = b
+            elif i == 2:
+                e = c
+            return (0x0001*(a is b) | 0x0002*(a is c) | 0x0004*(a is d) |
+                    0x0008*(a is e) | 0x0010*(b is c) | 0x0020*(b is d) |
+                    0x0040*(b is e) | 0x0080*(c is d) | 0x0100*(c is e) |
+                    0x0200*(d is e))
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 0x0004
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 0x0020
+        res = interpret(f, [2], type_system=self.ts)
+        assert res == 0x0100
+        res = interpret(f, [3], type_system=self.ts)
+        assert res == 0x0200
+
+    def test_eq(self):
+        class A: pass
+        class B(A): pass
+        class C: pass
+        def f(i):
+            a = A()
+            b = B()
+            c = C()
+            d = None
+            e = None
+            if i == 0:
+                d = a
+            elif i == 1:
+                d = b
+            elif i == 2:
+                e = c
+            return (0x0001*(a == b) | 0x0002*(a == c) | 0x0004*(a == d) |
+                    0x0008*(a == e) | 0x0010*(b == c) | 0x0020*(b == d) |
+                    0x0040*(b == e) | 0x0080*(c == d) | 0x0100*(c == e) |
+                    0x0200*(d == e))
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 0x0004
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 0x0020
+        res = interpret(f, [2], type_system=self.ts)
+        assert res == 0x0100
+        res = interpret(f, [3])
+        assert res == 0x0200
+
+    def test_istrue(self):
+        class A:
+            pass
+        def f(i):
+            if i == 0:
+                a = A()
+            else:
+                a = None
+            if a:
+                return 1
+            else:
+                return 2
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 1
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 2
+
+    def test_ne(self):
+        class A: pass
+        class B(A): pass
+        class C: pass
+        def f(i):
+            a = A()
+            b = B()
+            c = C()
+            d = None
+            e = None
+            if i == 0:
+                d = a
+            elif i == 1:
+                d = b
+            elif i == 2:
+                e = c
+            return (0x0001*(a != b) | 0x0002*(a != c) | 0x0004*(a != d) |
+                    0x0008*(a != e) | 0x0010*(b != c) | 0x0020*(b != d) |
+                    0x0040*(b != e) | 0x0080*(c != d) | 0x0100*(c != e) |
+                    0x0200*(d != e))
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == ~0x0004 & 0x3ff
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == ~0x0020 & 0x3ff
+        res = interpret(f, [2], type_system=self.ts)
+        assert res == ~0x0100 & 0x3ff
+        res = interpret(f, [3], type_system=self.ts)
+        assert res == ~0x0200 & 0x3ff
+
+    def test_hash_preservation(self):
+        class C:
+            pass
+        class D(C):
+            pass
         c = C()
-        d = None
-        e = None
-        if i == 0:
-            d = a
-        elif i == 1:
-            d = b
-        elif i == 2:
-            e = c
-        return (0x0001*(a != b) | 0x0002*(a != c) | 0x0004*(a != d) |
-                0x0008*(a != e) | 0x0010*(b != c) | 0x0020*(b != d) |
-                0x0040*(b != e) | 0x0080*(c != d) | 0x0100*(c != e) |
-                0x0200*(d != e))
-    res = interpret(f, [0])
-    assert res == ~0x0004 & 0x3ff
-    res = interpret(f, [1])
-    assert res == ~0x0020 & 0x3ff
-    res = interpret(f, [2])
-    assert res == ~0x0100 & 0x3ff
-    res = interpret(f, [3])
-    assert res == ~0x0200 & 0x3ff
-
-def test_hash_preservation():
-    class C:
-        pass
-    class D(C):
-        pass
-    c = C()
-    d = D()
-    def f():
-        d2 = D()
-        x = hash(d2) == id(d2) # xxx check for this CPython peculiarity for now
-        return x, hash(c)+hash(d)
+        d = D()
+        def f():
+            d2 = D()
+            x = hash(d2) == id(d2) # xxx check for this CPython peculiarity for now
+            return x, hash(c)+hash(d)
+
+        res = interpret(f, [], type_system=self.ts)
+
+        assert res.item0 == True
+        assert res.item1 == intmask(hash(c)+hash(d))
+        
+    def test_type(self):
+        class A:
+            pass
+        class B(A):
+            pass
+        def g(a):
+            return type(a)
+        def f(i):
+            if i > 0:
+                a = A()
+            elif i < 0:
+                a = B()
+            else:
+                a = None
+            return g(a) is A    # should type(None) work?  returns None for now
+        res = interpret(f, [1], type_system=self.ts)
+        assert res is True
+        res = interpret(f, [-1], type_system=self.ts)
+        assert res is False
+        res = interpret(f, [0], type_system=self.ts)
+        assert res is False
+
+    def test_void_fnptr(self):
+        def g():
+            return 42
+        def f():
+            e = EmptyBase()
+            e.attr = g
+            return e.attr()
+        res = interpret(f, [], type_system=self.ts)
+        assert res == 42
+
+    def test_getattr_on_classes(self):
+        class A:
+            def meth(self):
+                return self.value + 42
+        class B(A):
+            def meth(self):
+                shouldnt**be**seen
+        class C(B):
+            def meth(self):
+                return self.value - 1
+        def pick_class(i):
+            if i > 0:
+                return A
+            else:
+                return C
+        def f(i):
+            meth = pick_class(i).meth
+            x = C()
+            x.value = 12
+            return meth(x)   # calls A.meth or C.meth, completely ignores B.meth
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 54
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 11
+
+    def test_constant_bound_method(self):
+        class C:
+            value = 1
+            def meth(self):
+                return self.value
+        meth = C().meth
+        def f():
+            return meth()
+        res = interpret(f, [], type_system=self.ts)
+        assert res == 1
+
+   
+
+class TestLltype(BaseTestRclass):
 
-    res = interpret(f, [])
+    ts = "lltype"
 
-    assert res.item0 == True
-    assert res.item1 == intmask(hash(c)+hash(d))
+    def test__del__(self):
+        class A(object):
+            def __init__(self):
+                self.a = 2
+            def __del__(self):
+                self.a = 3
+        def f():
+            a = A()
+            return a.a
+        t = TranslationContext()
+        t.buildannotator().build_types(f, [])
+        t.buildrtyper().specialize()
+        graph = graphof(t, f)
+        TYPE = graph.startblock.operations[0].args[0].value
+        RTTI = getRuntimeTypeInfo(TYPE)
+        queryptr = RTTI._obj.query_funcptr # should not raise
+        destrptr = RTTI._obj.destructor_funcptr
+        assert destrptr is not None
     
-def test_type():
-    class A:
-        pass
-    class B(A):
-        pass
-    def g(a):
-        return type(a)
-    def f(i):
-        if i > 0:
+    def test_del_inheritance(self):
+        class State:
+            pass
+        s = State()
+        s.a_dels = 0
+        s.b_dels = 0
+        class A(object):
+            def __del__(self):
+                s.a_dels += 1
+        class B(A):
+            def __del__(self):
+                s.b_dels += 1
+        class C(A):
+            pass
+        def f():
+            A()
+            B()
+            C()
+            A()
+            B()
+            C()
+            return s.a_dels * 10 + s.b_dels
+        res = f()
+        assert res == 42
+        t = TranslationContext()
+        t.buildannotator().build_types(f, [])
+        t.buildrtyper().specialize()
+        graph = graphof(t, f)
+        TYPEA = graph.startblock.operations[0].args[0].value
+        RTTIA = getRuntimeTypeInfo(TYPEA)
+        TYPEB = graph.startblock.operations[3].args[0].value
+        RTTIB = getRuntimeTypeInfo(TYPEB)
+        TYPEC = graph.startblock.operations[6].args[0].value
+        RTTIC = getRuntimeTypeInfo(TYPEC)
+        queryptra = RTTIA._obj.query_funcptr # should not raise
+        queryptrb = RTTIB._obj.query_funcptr # should not raise
+        queryptrc = RTTIC._obj.query_funcptr # should not raise
+        destrptra = RTTIA._obj.destructor_funcptr
+        destrptrb = RTTIB._obj.destructor_funcptr
+        destrptrc = RTTIC._obj.destructor_funcptr
+        assert destrptra == destrptrc
+        assert typeOf(destrptra).TO.ARGS[0] != typeOf(destrptrb).TO.ARGS[0]
+        assert destrptra is not None
+        assert destrptrb is not None
+
+class TestOotype(BaseTestRclass):
+
+    ts = "ootype"
+
+    def test__del__(self):
+        class A(object):
+            def __init__(self):
+                self.a = 2
+            def __del__(self):
+                self.a = 3
+        def f():
             a = A()
-        elif i < 0:
-            a = B()
-        else:
-            a = None
-        return g(a) is A    # should type(None) work?  returns None for now
-    res = interpret(f, [1])
-    assert res is True
-    res = interpret(f, [-1])
-    assert res is False
-    res = interpret(f, [0])
-    assert res is False
+            return a.a
+        t = TranslationContext()
+        t.buildannotator().build_types(f, [])
+        t.buildrtyper(type_system=self.ts).specialize()
+        graph = graphof(t, f)
+        TYPE = graph.startblock.operations[0].args[0].value
+        meth = TYPE._lookup("o__del___variant0")
+        assert meth.finalizer
+
+    def test_del_inheritance(self):
+        class State:
+            pass
+        s = State()
+        s.a_dels = 0
+        s.b_dels = 0
+        class A(object):
+            def __del__(self):
+                s.a_dels += 1
+        class B(A):
+            def __del__(self):
+                s.b_dels += 1
+        class C(A):
+            pass
+        def f():
+            A()
+            B()
+            C()
+            A()
+            B()
+            C()
+            return s.a_dels * 10 + s.b_dels
+        res = f()
+        assert res == 42
+        t = TranslationContext()
+        t.buildannotator().build_types(f, [])
+        t.buildrtyper(type_system=self.ts).specialize()
+        graph = graphof(t, f)
+        TYPEA = graph.startblock.operations[0].args[0].value
+        TYPEB = graph.startblock.operations[2].args[0].value
+        TYPEC = graph.startblock.operations[4].args[0].value
+        destra = TYPEA._lookup("o__del___variant0")
+        destrb = TYPEB._lookup("o__del___variant0")
+        destrc = TYPEC._lookup("o__del___variant0")
+        assert destra == destrc
+        assert destrb is not None
+        assert destra is not None
 
-def test_void_fnptr():
-    def g():
-        return 42
-    def f():
-        e = EmptyBase()
-        e.attr = g
-        return e.attr()
-    res = interpret(f, [])
-    assert res == 42
-
-def test_getattr_on_classes():
-    class A:
-        def meth(self):
-            return self.value + 42
-    class B(A):
-        def meth(self):
-            shouldnt**be**seen
-    class C(B):
-        def meth(self):
-            return self.value - 1
-    def pick_class(i):
-        if i > 0:
-            return A
-        else:
-            return C
-    def f(i):
-        meth = pick_class(i).meth
-        x = C()
-        x.value = 12
-        return meth(x)   # calls A.meth or C.meth, completely ignores B.meth
-    res = interpret(f, [1])
-    assert res == 54
-    res = interpret(f, [0])
-    assert res == 11
-
-def test_constant_bound_method():
-    class C:
-        value = 1
-        def meth(self):
-            return self.value
-    meth = C().meth
-    def f():
-        return meth()
-    res = interpret(f, [])
-    assert res == 1
-
-def test__del__():
-    class A(object):
-        def __init__(self):
-            self.a = 2
-        def __del__(self):
-            self.a = 3
-    def f():
-        a = A()
-        return a.a
-    t = TranslationContext()
-    t.buildannotator().build_types(f, [])
-    t.buildrtyper().specialize()
-    graph = graphof(t, f)
-    TYPE = graph.startblock.operations[0].args[0].value
-    RTTI = getRuntimeTypeInfo(TYPE)
-    queryptr = RTTI._obj.query_funcptr # should not raise
-    destrptr = RTTI._obj.destructor_funcptr
-    assert destrptr is not None
-    
-   
-def test_del_inheritance():
-    class State:
-        pass
-    s = State()
-    s.a_dels = 0
-    s.b_dels = 0
-    class A(object):
-        def __del__(self):
-            s.a_dels += 1
-    class B(A):
-        def __del__(self):
-            s.b_dels += 1
-    class C(A):
-        pass
-    def f():
-        A()
-        B()
-        C()
-        A()
-        B()
-        C()
-        return s.a_dels * 10 + s.b_dels
-    res = f()
-    assert res == 42
-    t = TranslationContext()
-    t.buildannotator().build_types(f, [])
-    t.buildrtyper().specialize()
-    graph = graphof(t, f)
-    TYPEA = graph.startblock.operations[0].args[0].value
-    RTTIA = getRuntimeTypeInfo(TYPEA)
-    TYPEB = graph.startblock.operations[3].args[0].value
-    RTTIB = getRuntimeTypeInfo(TYPEB)
-    TYPEC = graph.startblock.operations[6].args[0].value
-    RTTIC = getRuntimeTypeInfo(TYPEC)
-    queryptra = RTTIA._obj.query_funcptr # should not raise
-    queryptrb = RTTIB._obj.query_funcptr # should not raise
-    queryptrc = RTTIC._obj.query_funcptr # should not raise
-    destrptra = RTTIA._obj.destructor_funcptr
-    destrptrb = RTTIB._obj.destructor_funcptr
-    destrptrc = RTTIC._obj.destructor_funcptr
-    assert destrptra == destrptrc
-    assert typeOf(destrptra).TO.ARGS[0] != typeOf(destrptrb).TO.ARGS[0]
-    assert destrptra is not None
-    assert destrptrb is not None

Modified: pypy/branch/njriley-trans/pypy/rpython/test/test_rgenop.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/test/test_rgenop.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/test/test_rgenop.py	Fri Mar 10 06:12:02 2006
@@ -143,3 +143,19 @@
     assert isinstance(c, flowmodel.Constant)
     assert c.concretetype == lltype.Void
     assert c.value == None
+
+def test_rtype_revealcosnt():
+    def hide_and_reveal(v):
+        gv = genconst(v)
+        return revealconst(lltype.Signed, gv)
+    res = interpret(hide_and_reveal, [42])
+    assert res == 42
+
+    S = lltype.GcStruct('s', ('x', lltype.Signed))
+    S_PTR = lltype.Ptr(S)
+    def hide_and_reveal_p(p):
+        gv = genconst(p)
+        return revealconst(S_PTR, gv)
+    s = malloc(S)
+    res = interpret(hide_and_reveal_p, [s])
+    assert res == s

Modified: pypy/branch/njriley-trans/pypy/rpython/test/test_rpbc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/test/test_rpbc.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/test/test_rpbc.py	Fri Mar 10 06:12:02 2006
@@ -3,31 +3,6 @@
 from pypy.rpython.test.test_llinterp import interpret
 
 
-def test_easy_call():
-    def f(x):
-        return x+1
-    def g(y):
-        return f(y+2)
-    res = interpret(g, [5])
-    assert res == 8
-
-def test_multiple_call():
-    def f1(x):
-        return x+1
-    def f2(x):
-        return x+2
-    def g(y):
-        if y < 0:
-            f = f1
-        else:
-            f = f2
-        return f(y+3)
-    res = interpret(g, [-1])
-    assert res == 3
-    res = interpret(g, [1])
-    assert res == 6
-
-
 class MyBase:
     def m(self, x):
         return self.z + x
@@ -40,44 +15,6 @@
     def m(self, x, y):
         return x*y
 
-def test_method_call():
-    def f(a, b):
-        obj = MyBase()
-        obj.z = a
-        return obj.m(b)
-    res = interpret(f, [4, 5])
-    assert res == 9
-
-def test_virtual_method_call():
-    def f(a, b):
-        if a > 0:
-            obj = MyBase()
-        else:
-            obj = MySubclass()
-        obj.z = a
-        return obj.m(b)
-    res = interpret(f, [1, 2.3])
-    assert res == 3.3
-    res = interpret(f, [-1, 2.3])
-    assert res == -3.3
-
-def test_stranger_subclass_1():
-    def f1():
-        obj = MyStrangerSubclass()
-        obj.z = 100
-        return obj.m(6, 7)
-    res = interpret(f1, [])
-    assert res == 42
-
-def test_stranger_subclass_2():
-    def f2():
-        obj = MyStrangerSubclass()
-        obj.z = 100
-        return obj.m(6, 7) + MyBase.m(obj, 58)
-    res = interpret(f2, [])
-    assert res == 200
-
-
 class MyBaseWithInit:
     def __init__(self, a):
         self.a1 = a
@@ -87,791 +24,1097 @@
         MyBaseWithInit.__init__(self, a)
         self.b1 = b
 
-def test_class_init():
-    def f(a):
-        instance = MyBaseWithInit(a)
-        return instance.a1
-    assert interpret(f, [5]) == 5
-
-def test_class_init_w_kwds():
-    def f(a):
-        instance = MyBaseWithInit(a=a)
-        return instance.a1
-    assert interpret(f, [5]) == 5
-
-def test_class_init_2():
-    def f(a, b):
-        instance = MySubclassWithInit(a, b)
-        return instance.a1 * instance.b1
-    assert interpret(f, [6, 7]) == 42
-
-def test_class_init_2_w_kwds():
-    def f(a, b):
-        instance = MySubclassWithInit(a, b=b)
-        return instance.a1 * instance.b1
-    assert interpret(f, [6, 7]) == 42
-
-def test_class_calling_init():
-    def f():
-        instance = MySubclassWithInit(1, 2)
-        instance.__init__(3, 4)
-        return instance.a1 * instance.b1
-    assert interpret(f, []) == 12
-
-
 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_simple_w_kwds():
-    fr1 = Freezing()
-    fr1.x = 5
-    def f(n):
-        return fr1.mymethod(y=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
+class BaseTestRPBC:
 
-def test_call_frozen_pbc_multiple_w_kwds():
-    fr1 = Freezing()
-    fr2 = Freezing()
-    fr1.x = 5
-    fr2.x = 6
-    def f(n):
-        if n > 0:
-            fr = fr1
-        else:
-            fr = fr2
-        return fr.mymethod(y=n)
-    res = interpret(f, [1])
-    assert res == 6
-    res = interpret(f, [-1])
-    assert res == 5
+    def test_easy_call(self):
+        def f(x):
+            return x+1
+        def g(y):
+            return f(y+2)
+        res = interpret(g, [5], type_system=self.ts)
+        assert res == 8
 
-def test_is_among_frozen():
-    fr1 = Freezing()
-    fr2 = Freezing()
-    def givefr1():
-        return fr1
-    def givefr2():
-        return fr2
-    def f(i):
-        if i == 1:
-            fr = givefr1()
-        else:
-            fr = givefr2()
-        return fr is fr1
-    res = interpret(f, [0])
-    assert res is False
-    res = interpret(f, [1])
-    assert res is True
-
-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)
+    def test_multiple_call(self):
+        def f1(x):
+            return x+1
+        def f2(x):
+            return x+2
+        def g(y):
+            if y < 0:
+                f = f1
+            else:
+                f = f2
+            return f(y+3)
+        res = interpret(g, [-1], type_system=self.ts)
+        assert res == 3
+        res = interpret(g, [1], type_system=self.ts)
+        assert res == 6
 
-    res = interpret(f1, [0]) 
-    assert res == 7
-    res = interpret(f1, [1]) 
-    assert res == 3
-
-def test_call_memoized_function_with_bools():
-    fr1 = Freezing()
-    fr2 = Freezing()
-    def getorbuild(key, flag1, flag2):
-        a = 1
-        if key is fr1:
-            result = eval("a+2")
-        else:
-            result = eval("a+6")
-        if flag1:
-            result += 100
-        if flag2:
-            result += 1000
-        return result
-    getorbuild._annspecialcase_ = "specialize:memo"
-
-    def f1(i):
-        if i > 0:
-            fr = fr1
-        else:
-            fr = fr2
-        return getorbuild(fr, i % 2 == 0, i % 3 == 0)
 
-    for n in [0, 1, 2, -3, 6]:
-        res = interpret(f1, [n])
-        assert res == f1(n)
-
-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 
+    def test_method_call(self):
+        def f(a, b):
+            obj = MyBase()
+            obj.z = a
+            return obj.m(b)
+        res = interpret(f, [4, 5], type_system=self.ts)
+        assert res == 9
+
+    def test_virtual_method_call(self):
+        def f(a, b):
+            if a > 0:
+                obj = MyBase()
             else:
-                return fr1 
-
-    class Cache2(Cache): 
-        def _build(self, key): 
-            "NOT_RPYTHON" 
+                obj = MySubclass()
+            obj.z = a
+            return obj.m(b)
+        res = interpret(f, [1, 2.3], type_system=self.ts)
+        assert res == 3.3
+        res = interpret(f, [-1, 2.3], type_system=self.ts)
+        assert res == -3.3
+
+    def test_stranger_subclass_1(self):
+        def f1():
+            obj = MyStrangerSubclass()
+            obj.z = 100
+            return obj.m(6, 7)
+        res = interpret(f1, [], type_system=self.ts)
+        assert res == 42
+
+    def test_stranger_subclass_2(self):
+        def f2():
+            obj = MyStrangerSubclass()
+            obj.z = 100
+            return obj.m(6, 7) + MyBase.m(obj, 58)
+        res = interpret(f2, [], type_system=self.ts)
+        assert res == 200
+
+
+    def test_class_init(self):
+        def f(a):
+            instance = MyBaseWithInit(a)
+            return instance.a1
+        assert interpret(f, [5], type_system=self.ts) == 5
+
+    def test_class_init_2(self):
+        def f(a, b):
+            instance = MySubclassWithInit(a, b)
+            return instance.a1 * instance.b1
+        assert interpret(f, [6, 7], type_system=self.ts) == 42
+
+    def test_class_calling_init(self):
+        def f():
+            instance = MySubclassWithInit(1, 2)
+            instance.__init__(3, 4)
+            return instance.a1 * instance.b1
+        assert interpret(f, [], type_system=self.ts) == 12
+
+    def test_class_init_w_kwds(self):
+        def f(a):
+            instance = MyBaseWithInit(a=a)
+            return instance.a1
+        assert interpret(f, [5], type_system=self.ts) == 5
+
+    def test_class_init_2_w_kwds(self):
+        def f(a, b):
+            instance = MySubclassWithInit(a, b=b)
+            return instance.a1 * instance.b1
+        assert interpret(f, [6, 7], type_system=self.ts) == 42
+
+
+    def test_freezing(self):
+        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], type_system=self.ts)
+        assert res == 5
+        res = interpret(f, [-1], type_system=self.ts)
+        assert res == 6
+
+    def test_call_frozen_pbc_simple(self):
+        fr1 = Freezing()
+        fr1.x = 5
+        def f(n):
+            return fr1.mymethod(n)
+        res = interpret(f, [6], type_system=self.ts)
+        assert res == 11
+
+    def test_call_frozen_pbc_simple_w_kwds(self):
+        fr1 = Freezing()
+        fr1.x = 5
+        def f(n):
+            return fr1.mymethod(y=n)
+        res = interpret(f, [6], type_system=self.ts)
+        assert res == 11
+
+    def test_call_frozen_pbc_multiple(self):
+        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], type_system=self.ts)
+        assert res == 6
+        res = interpret(f, [-1], type_system=self.ts)
+        assert res == 5
+
+    def test_call_frozen_pbc_multiple_w_kwds(self):
+        fr1 = Freezing()
+        fr2 = Freezing()
+        fr1.x = 5
+        fr2.x = 6
+        def f(n):
+            if n > 0:
+                fr = fr1
+            else:
+                fr = fr2
+            return fr.mymethod(y=n)
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 6
+        res = interpret(f, [-1], type_system=self.ts)
+        assert res == 5
+
+    def test_is_among_frozen(self):
+        fr1 = Freezing()
+        fr2 = Freezing()
+        def givefr1():
+            return fr1
+        def givefr2():
+            return fr2
+        def f(i):
+            if i == 1:
+                fr = givefr1()
+            else:
+                fr = givefr2()
+            return fr is fr1
+        res = interpret(f, [0], type_system=self.ts)
+        assert res is False
+        res = interpret(f, [1], type_system=self.ts)
+        assert res is True
+
+    def test_unbound_method(self):
+        def f():
+            inst = MySubclass()
+            inst.z = 40
+            return MyBase.m(inst, 2)
+        res = interpret(f, [], type_system=self.ts)
+        assert res == 42
+
+    def test_call_defaults(self):
+        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, [], type_system=self.ts)
+        assert res == 1+2+3
+        res = interpret(f2, [], type_system=self.ts)
+        assert res == 1+10+3
+        res = interpret(f3, [], type_system=self.ts)
+        assert res == 1+10+100
+
+    def test_call_memoized_function(self):
+        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"
 
-    cache1 = Cache1()
-    cache2 = Cache2()
+        def f1(i):
+            if i > 0:
+                fr = fr1
+            else:
+                fr = fr2
+            return getorbuild(fr)
 
-    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_call_memo_with_class():
-    class A: pass
-    class FooBar(A): pass
-    def memofn(cls):
-        return len(cls.__name__)
-    memofn._annspecialcase_ = "specialize:memo"
-
-    def f1(i):
-        if i == 1:
-            cls = A
-        else:
-            cls = FooBar
-        FooBar()    # make sure we have ClassDefs
-        return memofn(cls)
-    res = interpret(f1, [1])
-    assert res == 1
-    res = interpret(f1, [2])
-    assert res == 6
+        res = interpret(f1, [0], type_system=self.ts) 
+        assert res == 7
+        res = interpret(f1, [1], type_system=self.ts) 
+        assert res == 3
+
+    def test_call_memoized_function_with_bools(self):
+        fr1 = Freezing()
+        fr2 = Freezing()
+        def getorbuild(key, flag1, flag2):
+            a = 1
+            if key is fr1:
+                result = eval("a+2")
+            else:
+                result = eval("a+6")
+            if flag1:
+                result += 100
+            if flag2:
+                result += 1000
+            return result
+        getorbuild._annspecialcase_ = "specialize:memo"
 
-def test_call_memo_with_single_value():
-    class A: pass
-    def memofn(cls):
-        return len(cls.__name__)
-    memofn._annspecialcase_ = "specialize:memo"
-
-    def f1():
-        A()    # make sure we have a ClassDef
-        return memofn(A)
-    res = interpret(f1, [])
-    assert res == 1
+        def f1(i):
+            if i > 0:
+                fr = fr1
+            else:
+                fr = fr2
+            return getorbuild(fr, i % 2 == 0, i % 3 == 0)
 
-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_rpbc_bound_method_static_call_w_kwds():
-    class R:
-        def meth(self, x):
-            return x
-    r = R()
-    m = r.meth
-    def fn():
-        return m(x=3)
-    res = interpret(fn, [])
-    assert res == 3
-
-
-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 test_classpbc_getattr():
-    class A:
-        myvalue = 123
-    class B(A):
-        myvalue = 456
-    def f(i):
-        return [A,B][i].myvalue
-    res = interpret(f, [0])
-    assert res == 123
-    res = interpret(f, [1])
-    assert res == 456
-
-def test_function_or_None():
-    def g1():
-        return 42
-    def f(i):
-        g = None
-        if i > 5:
-            g = g1
-        if i > 6:
-            return g()
-        else:
-            return 12
+        for n in [0, 1, 2, -3, 6]:
+            res = interpret(f1, [n], type_system=self.ts)
+            assert res == f1(n)
+
+    def test_call_memoized_cache(self):
+
+        # 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], type_system=self.ts)  
+        assert res == 3
+        res = interpret(f1, [1], type_system=self.ts) 
+        assert res == 7
+
+    def test_call_memo_with_single_value(self):
+        class A: pass
+        def memofn(cls):
+            return len(cls.__name__)
+        memofn._annspecialcase_ = "specialize:memo"
+
+        def f1():
+            A()    # make sure we have a ClassDef
+            return memofn(A)
+        res = interpret(f1, [], type_system=self.ts)
+        assert res == 1
+
+    def test_call_memo_with_class(self):
+        class A: pass
+        class FooBar(A): pass
+        def memofn(cls):
+            return len(cls.__name__)
+        memofn._annspecialcase_ = "specialize:memo"
+
+        def f1(i):
+            if i == 1:
+                cls = A
+            else:
+                cls = FooBar
+            FooBar()    # make sure we have ClassDefs
+            return memofn(cls)
+        res = interpret(f1, [1], type_system=self.ts)
+        assert res == 1
+        res = interpret(f1, [2], type_system=self.ts)
+        assert res == 6
+
+    def test_rpbc_bound_method_static_call(self):
+        class R:
+            def meth(self):
+                return 0
+        r = R()
+        m = r.meth
+        def fn():
+            return m()
+        res = interpret(fn, [], type_system=self.ts)
+        assert res == 0
+
+    def test_rpbc_bound_method_static_call_w_kwds(self):
+        class R:
+            def meth(self, x):
+                return x
+        r = R()
+        m = r.meth
+        def fn():
+            return m(x=3)
+        res = interpret(fn, [], type_system=self.ts)
+        assert res == 3
+
+
+    def test_constant_return_disagreement(self):
+        class R:
+            def meth(self):
+                return 0
+        r = R()
+        def fn():
+            return r.meth()
+        res = interpret(fn, [], type_system=self.ts)
+        assert res == 0
+
+    def test_None_is_false(self):
+        def fn(i):
+            if i == 0:
+                v = None
+            else:
+                v = fn
+            return bool(v)
+        res = interpret(fn, [1], type_system=self.ts)
+        assert res is True
+        res = interpret(fn, [0], type_system=self.ts)
+        assert res is False
+
+    def test_classpbc_getattr(self):
+        class A:
+            myvalue = 123
+        class B(A):
+            myvalue = 456
+        def f(i):
+            if i == 0:
+                v = A
+            else:
+                v = B
+            return v.myvalue
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 123
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 456
+
+    def test_function_or_None(self):
+        def g1():
+            return 42
+        def f(i):
+            g = None
+            if i > 5:
+                g = g1
+            if i > 6:
+                return g()
+            else:
+                return 12
 
-    res = interpret(f, [0])
-    assert res == 12
-    res = interpret(f, [6])
-    assert res == 12
-    res = interpret(f, [7])
-    assert res == 42
-
-def test_classdef_getattr():
-    class A:
-        myvalue = 123
-    class B(A):
-        myvalue = 456
-    def f(i):
-        B()    # for A and B to have classdefs
-        return [A,B][i].myvalue
-    res = interpret(f, [0])
-    assert res == 123
-    res = interpret(f, [1])
-    assert res == 456
-
-def test_call_classes():
-    class A: pass
-    class B(A): pass
-    def f(i):
-        if i == 1:
-            cls = B
-        else:
-            cls = A
-        return cls()
-    res = interpret(f, [0])
-    assert res.super.typeptr.name[0] == 'A'
-    res = interpret(f, [1])
-    assert res.super.typeptr.name[0] == 'B'
-
-def test_call_classes_with_init2():
-    class A:
-        def __init__(self, z):
-            self.z = z
-    class B(A):
-        def __init__(self, z, x=42):
-            A.__init__(self, z)
-            self.extra = x
-    def f(i, z):
-        if i == 1:
-            cls = B
-        else:
-            cls = A
-        return cls(z)
-    res = interpret(f, [0, 5])
-    assert res.super.typeptr.name[0] == 'A'
-    assert res.inst_z == 5
-    res = interpret(f, [1, -7645])
-    assert res.super.typeptr.name[0] == 'B'
-    assert res.inst_z == -7645
-    assert res._obj._parentstructure().inst_extra == 42
-
-def test_call_starargs():
-    def g(x=-100, *arg):
-        return x + len(arg)
-    def f(i):
-        if i == -1:
-            return g()
-        elif i == 0:
-            return g(4)
-        elif i == 1:
-            return g(5, 15)
-        elif i == 2:
-            return g(7, 17, 27)
-        else:
-            return g(10, 198, 1129, 13984)
-    res = interpret(f, [-1])
-    assert res == -100
-    res = interpret(f, [0])
-    assert res == 4
-    res = interpret(f, [1])
-    assert res == 6
-    res = interpret(f, [2])
-    assert res == 9
-    res = interpret(f, [3])
-    assert res == 13
-
-def test_conv_from_None():
-    class A(object): pass
-    def none():
-        return None
-    
-    def f(i):
-        if i == 1:
-            return none()
-        else:
-            return "ab"
-    res = interpret(f, [1])
-    assert not res
-    res = interpret(f, [0])
-    assert ''.join(res.chars) == "ab"
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 12
+        res = interpret(f, [6], type_system=self.ts)
+        assert res == 12
+        res = interpret(f, [7], type_system=self.ts)
+        assert res == 42
+
+    def test_classdef_getattr(self):
+        class A:
+            myvalue = 123
+        class B(A):
+            myvalue = 456
+        def f(i):
+            B()    # for A and B to have classdefs
+            if i == 0:
+                v = A
+            else:
+                v = B
+            return v.myvalue
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 123
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 456
+
+    def test_call_classes(self):
+        class A: pass
+        class B(A): pass
+        def f(i):
+            if i == 1:
+                cls = B
+            else:
+                cls = A
+            return cls()
+        res = interpret(f, [0], type_system=self.ts)
+        assert self.class_name(res) == 'A'
+        res = interpret(f, [1], type_system=self.ts)
+        assert self.class_name(res) == 'B'
+
+    def test_call_classes_with_init2(self):
+        class A:
+            def __init__(self, z):
+                self.z = z
+        class B(A):
+            def __init__(self, z, x=42):
+                A.__init__(self, z)
+                self.extra = x
+        def f(i, z):
+            if i == 1:
+                cls = B
+            else:
+                cls = A
+            return cls(z)
+        res = interpret(f, [0, 5], type_system=self.ts)
+        assert self.class_name(res) == 'A'
+        assert self.read_attr(res, "z") == 5
+        res = interpret(f, [1, -7645], type_system=self.ts)
+        assert self.class_name(res) == 'B'
+        assert self.read_attr(res, "z") == -7645
+        assert self.read_attr(res, "extra") == 42
+
+    def test_conv_from_None(self):
+        class A(object): pass
+        def none():
+            return None
         
-    def g(i):
-        if i == 1:
-            return none()
-        else:
-            return A()
-    res = interpret(g, [1])
-    assert not res
-    res = interpret(g, [0])
-    assert res.super.typeptr.name[0] == 'A'
+        def f(i):
+            if i == 1:
+                return none()
+            else:
+                return "ab"
+        res = interpret(f, [1], type_system=self.ts)
+        assert not res
+        res = interpret(f, [0], type_system=self.ts)
+        assert ''.join(res.chars) == "ab"
+            
+        def g(i):
+            if i == 1:
+                return none()
+            else:
+                return A()
+        res = interpret(g, [1], type_system=self.ts)
+        assert not res
+        res = interpret(g, [0], type_system=self.ts)
+        assert self.class_name(res) == 'A'
 
     
-def test_conv_from_classpbcset_to_larger():
-    class A(object): pass
-    class B(A): pass
-    class C(A): pass
-
-    def a():
-        return A
-    def b():
-        return B
-    
-
-    def g(i):
-        if i == 1:
-            cls = a()
-        else:
-            cls = b()
-        return cls()
-
-    res = interpret(g, [0])
-    assert res.super.typeptr.name[0] == 'B'
-    res = interpret(g, [1])
-    assert res.super.typeptr.name[0] == 'A'
-
-    def bc(j):
-        if j == 1:
+    def test_conv_from_classpbcset_to_larger(self):
+        class A(object): pass
+        class B(A): pass
+        class C(A): pass
+
+        def a():
+            return A
+        def b():
             return B
-        else:
-            return C
-
-    def g(i, j):
-        if i == 1:
-            cls = a()
-        else:
-            cls = bc(j)
-        return cls()
+        
 
-    res = interpret(g, [0, 0])
-    assert res.super.typeptr.name[0] == 'C'
-    res = interpret(g, [0, 1])
-    assert res.super.typeptr.name[0] == 'B'    
-    res = interpret(g, [1, 0])
-    assert res.super.typeptr.name[0] == 'A'    
-    
-def test_call_keywords():
-    def g(a=1, b=2, c=3):
-        return 100*a+10*b+c
-
-    def f(i):
-        if i == 0:
-            return g(a=7)
-        elif i == 1:
-            return g(b=11)
-        elif i == 2:
-            return g(c=13)
-        elif i == 3:
-            return g(a=7, b=11)
-        elif i == 4:
-            return g(b=7, a=11)
-        elif i == 5:
-            return g(a=7, c=13)
-        elif i == 6:
-            return g(c=7, a=13)
-        elif i == 7:
-            return g(a=7,b=11,c=13)
-        elif i == 8:
-            return g(a=7,c=11,b=13)
-        elif i == 9:
-            return g(b=7,a=11,c=13)
-        else:
-            return g(b=7,c=11,a=13)
+        def g(i):
+            if i == 1:
+                cls = a()
+            else:
+                cls = b()
+            return cls()
 
-    for i in range(11):
-        res = interpret(f, [i])
-        assert res == f(i)
-
-def test_call_star_and_keywords():
-    def g(a=1, b=2, c=3):
-        return 100*a+10*b+c
-
-    def f(i, x):
-        if x == 1:
-            j = 11
-        else:
-            j = 22
-        if i == 0:
-            return g(7)
-        elif i == 1:
-            return g(7,*(j,))
-        elif i == 2:
-            return g(7,*(11,j))
-        elif i == 3:
-            return g(a=7)
-        elif i == 4:
-            return g(b=7, *(j,))
-        elif i == 5:
-            return g(b=7, c=13, *(j,))
-        elif i == 6:
-            return g(c=7, b=13, *(j,))
-        elif i == 7:
-            return g(c=7,*(j,))
-        elif i == 8:
-            return g(c=7,*(11,j))
-        else:
-            return 0
+        res = interpret(g, [0], type_system=self.ts)
+        assert self.class_name(res) == 'B'
+        res = interpret(g, [1], type_system=self.ts)
+        assert self.class_name(res) == 'A'
+
+        def bc(j):
+            if j == 1:
+                return B
+            else:
+                return C
 
-    for i in range(9):
-        for x in range(1):
-            res = interpret(f, [i, x])
-            assert res == f(i, x)
-
-def test_call_star_and_keywords_starargs():
-    def g(a=1, b=2, c=3, *rest):
-        return 1000*len(rest)+100*a+10*b+c
-
-    def f(i, x):
-        if x == 1:
-            j = 13
-        else:
-            j = 31
-        if i == 0:
-            return g()
-        elif i == 1:
-            return g(*(j,))
-        elif i == 2:
-            return g(*(13, j))
-        elif i == 3:
-            return g(*(13, j, 19))
-        elif i == 4:
-            return g(*(13, j, 19, 21))
-        elif i == 5:
-            return g(7)
-        elif i == 6:
-            return g(7, *(j,))
-        elif i == 7:
-            return g(7, *(13, j))
-        elif i == 8:
-            return g(7, *(13, 17, j))
-        elif i == 9:
-            return g(7, *(13, 17, j, 21))
-        elif i == 10:
-            return g(7, 9)
-        elif i == 11:
-            return g(7, 9, *(j,))
-        elif i == 12:
-            return g(7, 9, *(j, 17))
-        elif i == 13:
-            return g(7, 9, *(13, j, 19))
-        elif i == 14:
-            return g(7, 9, 11)
-        elif i == 15:
-            return g(7, 9, 11, *(j,))
-        elif i == 16:
-            return g(7, 9, 11, *(13, j))
-        elif i == 17:
-            return g(7, 9, 11, *(13, 17, j))
-        elif i == 18:
-            return g(7, 9, 11, 2)
-        elif i == 19:
-            return g(7, 9, 11, 2, *(j,))
-        elif i == 20:
-            return g(7, 9, 11, 2, *(13, j))
-        else:
-            return 0
+        def g(i, j):
+            if i == 1:
+                cls = a()
+            else:
+                cls = bc(j)
+            return cls()
 
-    for i in range(21):
-        for x in range(1):
-            res = interpret(f, [i, x])
-            assert res == f(i, x)
-
-def test_conv_from_funcpbcset_to_larger():
-    def f1():
-        return 7
-    def f2():
-        return 11
-    def f3():
-        return 13
-
-    def a():
-        return f1
-    def b():
-        return f2
-    
+        res = interpret(g, [0, 0], type_system=self.ts)
+        assert self.class_name(res) == 'C'
+        res = interpret(g, [0, 1], type_system=self.ts)
+        assert self.class_name(res) == 'B'    
+        res = interpret(g, [1, 0], type_system=self.ts)
+        assert self.class_name(res) == 'A'    
+        
+    def test_call_starargs(self):
+        def g(x=-100, *arg):
+            return x + len(arg)
+        def f(i):
+            if i == -1:
+                return g()
+            elif i == 0:
+                return g(4)
+            elif i == 1:
+                return g(5, 15)
+            elif i == 2:
+                return g(7, 17, 27)
+            else:
+                return g(10, 198, 1129, 13984)
+        res = interpret(f, [-1], type_system=self.ts)
+        assert res == -100
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 4
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 6
+        res = interpret(f, [2], type_system=self.ts)
+        assert res == 9
+        res = interpret(f, [3], type_system=self.ts)
+        assert res == 13
+
+    def test_call_keywords(self):
+        def g(a=1, b=2, c=3):
+            return 100*a+10*b+c
+
+        def f(i):
+            if i == 0:
+                return g(a=7)
+            elif i == 1:
+                return g(b=11)
+            elif i == 2:
+                return g(c=13)
+            elif i == 3:
+                return g(a=7, b=11)
+            elif i == 4:
+                return g(b=7, a=11)
+            elif i == 5:
+                return g(a=7, c=13)
+            elif i == 6:
+                return g(c=7, a=13)
+            elif i == 7:
+                return g(a=7,b=11,c=13)
+            elif i == 8:
+                return g(a=7,c=11,b=13)
+            elif i == 9:
+                return g(b=7,a=11,c=13)
+            else:
+                return g(b=7,c=11,a=13)
 
-    def g(i):
-        if i == 1:
-            f = a()
-        else:
-            f = b()
-        return f()
+        for i in range(11):
+            res = interpret(f, [i], type_system=self.ts)
+            assert res == f(i)
+
+    def test_call_star_and_keywords(self):
+        def g(a=1, b=2, c=3):
+            return 100*a+10*b+c
+
+        def f(i, x):
+            if x == 1:
+                j = 11
+            else:
+                j = 22
+            if i == 0:
+                return g(7)
+            elif i == 1:
+                return g(7,*(j,))
+            elif i == 2:
+                return g(7,*(11,j))
+            elif i == 3:
+                return g(a=7)
+            elif i == 4:
+                return g(b=7, *(j,))
+            elif i == 5:
+                return g(b=7, c=13, *(j,))
+            elif i == 6:
+                return g(c=7, b=13, *(j,))
+            elif i == 7:
+                return g(c=7,*(j,))
+            elif i == 8:
+                return g(c=7,*(11,j))
+            else:
+                return 0
 
-    res = interpret(g, [0])
-    assert res == 11
-    res = interpret(g, [1])
-    assert res == 7
+        for i in range(9):
+            for x in range(1):
+                res = interpret(f, [i, x], type_system=self.ts)
+                assert res == f(i, x)
+
+    def test_call_star_and_keywords_starargs(self):
+        def g(a=1, b=2, c=3, *rest):
+            return 1000*len(rest)+100*a+10*b+c
+
+        def f(i, x):
+            if x == 1:
+                j = 13
+            else:
+                j = 31
+            if i == 0:
+                return g()
+            elif i == 1:
+                return g(*(j,))
+            elif i == 2:
+                return g(*(13, j))
+            elif i == 3:
+                return g(*(13, j, 19))
+            elif i == 4:
+                return g(*(13, j, 19, 21))
+            elif i == 5:
+                return g(7)
+            elif i == 6:
+                return g(7, *(j,))
+            elif i == 7:
+                return g(7, *(13, j))
+            elif i == 8:
+                return g(7, *(13, 17, j))
+            elif i == 9:
+                return g(7, *(13, 17, j, 21))
+            elif i == 10:
+                return g(7, 9)
+            elif i == 11:
+                return g(7, 9, *(j,))
+            elif i == 12:
+                return g(7, 9, *(j, 17))
+            elif i == 13:
+                return g(7, 9, *(13, j, 19))
+            elif i == 14:
+                return g(7, 9, 11)
+            elif i == 15:
+                return g(7, 9, 11, *(j,))
+            elif i == 16:
+                return g(7, 9, 11, *(13, j))
+            elif i == 17:
+                return g(7, 9, 11, *(13, 17, j))
+            elif i == 18:
+                return g(7, 9, 11, 2)
+            elif i == 19:
+                return g(7, 9, 11, 2, *(j,))
+            elif i == 20:
+                return g(7, 9, 11, 2, *(13, j))
+            else:
+                return 0
 
-    def bc(j):
-        if j == 1:
+        for i in range(21):
+            for x in range(1):
+                res = interpret(f, [i, x], type_system=self.ts)
+                assert res == f(i, x)
+
+    def test_conv_from_funcpbcset_to_larger(self):
+        def f1():
+            return 7
+        def f2():
+            return 11
+        def f3():
+            return 13
+
+        def a():
+            return f1
+        def b():
             return f2
-        else:
-            return f3
-
-    def g(i, j):
-        if i == 1:
-            cls = a()
-        else:
-            cls = bc(j)
-        return cls()
-
-    res = interpret(g, [0, 0])
-    assert res == 13
-    res = interpret(g, [0, 1])
-    assert res == 11
-    res = interpret(g, [1, 0])
-    assert res == 7
-
-def test_call_special_starargs_method():
-    class Star:
-        def __init__(self, d):
-            self.d = d
-        def meth(self, *args):
-            return self.d + len(args)
-
-    def f(i, j):
-        s = Star(i)
-        return s.meth(i, j)
+        
 
-    res = interpret(f, [3, 0])
-    assert res == 5
+        def g(i):
+            if i == 1:
+                f = a()
+            else:
+                f = b()
+            return f()
 
-def test_call_star_method():
-    class N:
-        def __init__(self, d):
-            self.d = d
-        def meth(self, a, b):
-            return self.d + a + b
-
-    def f(i, j):
-        n = N(i)
-        return n.meth(*(i, j))
-
-    res = interpret(f, [3, 7])
-    assert res == 13
-
-def test_call_star_special_starargs_method():
-    class N:
-        def __init__(self, d):
-            self.d = d
-        def meth(self, *args):
-            return self.d + len(args)
-
-    def f(i, j):
-        n = N(i)
-        return n.meth(*(i, j))
+        res = interpret(g, [0], type_system=self.ts)
+        assert res == 11
+        res = interpret(g, [1], type_system=self.ts)
+        assert res == 7
+
+        def bc(j):
+            if j == 1:
+                return f2
+            else:
+                return f3
 
-    res = interpret(f, [3, 0])
-    assert res == 5
+        def g(i, j):
+            if i == 1:
+                cls = a()
+            else:
+                cls = bc(j)
+            return cls()
 
-def test_various_patterns_but_one_signature_method():
-    class A:
-        def meth(self, a, b=0):
-            raise NotImplementedError
-    class B(A):
-        def meth(self, a, b=0):
-            return a+b
+        res = interpret(g, [0, 0], type_system=self.ts)
+        assert res == 13
+        res = interpret(g, [0, 1], type_system=self.ts)
+        assert res == 11
+        res = interpret(g, [1, 0], type_system=self.ts)
+        assert res == 7
+
+    def test_call_special_starargs_method(self):
+        class Star:
+            def __init__(self, d):
+                self.d = d
+            def meth(self, *args):
+                return self.d + len(args)
+
+        def f(i, j):
+            s = Star(i)
+            return s.meth(i, j)
+
+        res = interpret(f, [3, 0], type_system=self.ts)
+        assert res == 5
+
+    def test_call_star_method(self):
+        class N:
+            def __init__(self, d):
+                self.d = d
+            def meth(self, a, b):
+                return self.d + a + b
+
+        def f(i, j):
+            n = N(i)
+            return n.meth(*(i, j))
+
+        res = interpret(f, [3, 7], type_system=self.ts)
+        assert res == 13
+
+    def test_call_star_special_starargs_method(self):
+        class N:
+            def __init__(self, d):
+                self.d = d
+            def meth(self, *args):
+                return self.d + len(args)
+
+        def f(i, j):
+            n = N(i)
+            return n.meth(*(i, j))
+
+        res = interpret(f, [3, 0], type_system=self.ts)
+        assert res == 5
+
+    def test_various_patterns_but_one_signature_method(self):
+        class A:
+            def meth(self, a, b=0):
+                raise NotImplementedError
+        class B(A):
+            def meth(self, a, b=0):
+                return a+b
+            
+        class C(A):
+            def meth(self, a, b=0):
+                return a*b
+        def f(i):
+            if i == 0:
+                x = B()
+            else:
+                x = C()
+            r1 = x.meth(1)
+            r2 = x.meth(3, 2)
+            r3 = x.meth(7, b=11)
+            return r1+r2+r3
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 1+3+2+7+11
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 3*2+11*7
         
-    class C(A):
-        def meth(self, a, b=0):
-            return a*b
-    def f(i):
-        if i == 0:
-            x = B()
-        else:
-            x = C()
-        r1 = x.meth(1)
-        r2 = x.meth(3, 2)
-        r3 = x.meth(7, b=11)
-        return r1+r2+r3
-    res = interpret(f, [0])
-    assert res == 1+3+2+7+11
-    res = interpret(f, [1])
-    assert res == 3*2+11*7
-    
 
-def test_multiple_ll_one_hl_op():
-    class E(Exception):
-        pass
-    class A(object):
-        pass
-    class B(A):
-        pass
-    class C(object):
-        def method(self, x):
-            if x:
-                raise E()
+    def test_multiple_ll_one_hl_op(self):
+        class E(Exception):
+            pass
+        class A(object):
+            pass
+        class B(A):
+            pass
+        class C(object):
+            def method(self, x):
+                if x:
+                    raise E()
+                else:
+                    return A()
+        class D(C):
+            def method(self, x):
+                if x:
+                    raise E()
+                else:
+                    return B()
+        def call(x):
+            c = D()
+            c.method(x)
+            try:
+                c.method(x + 1)
+            except E:
+                pass
+            c = C()
+            c.method(x)
+            try:
+                return c.method(x + 1)
+            except E:
+                return None
+        res = interpret(call, [0], type_system=self.ts)
+
+    def test_multiple_pbc_with_void_attr(self):
+        class A:
+            def _freeze_(self):
+                return True
+        a1 = A()
+        a2 = A()
+        unique = A()
+        unique.result = 42
+        a1.value = unique
+        a2.value = unique
+        def g(a):
+            return a.value.result
+        def f(i):
+            if i == 1:
+                a = a1
             else:
-                return A()
-    class D(C):
-        def method(self, x):
-            if x:
-                raise E()
-            else:
-                return B()
-    def call(x):
-        c = D()
-        c.method(x)
-        try:
-            c.method(x + 1)
-        except E:
+                a = a2
+            return g(a)
+        res = interpret(f, [0], type_system=self.ts)
+        assert res == 42
+        res = interpret(f, [1], type_system=self.ts)
+        assert res == 42
+
+    def test_function_or_none(self):
+        def h(y):
+            return y+84
+        def g(y):
+            return y+42
+        def f(x, y):
+            if x == 1:
+                func = g
+            elif x == 2:
+                func = h
+            else:
+                func = None
+            if func:
+                return func(y)
+            return -1
+        res = interpret(f, [1, 100], type_system=self.ts)
+        assert res == 142
+        res = interpret(f, [2, 100], type_system=self.ts)
+        assert res == 184
+        res = interpret(f, [3, 100], type_system=self.ts)
+        assert res == -1
+
+    def test_pbc_getattr_conversion(self):
+        fr1 = Freezing()
+        fr2 = Freezing()
+        fr3 = Freezing()
+        fr1.value = 10
+        fr2.value = 5
+        fr3.value = 2.5
+        def pick12(i):
+            if i > 0:
+                return fr1
+            else:
+                return fr2
+        def pick23(i):
+            if i > 5:
+                return fr2
+            else:
+                return fr3
+        def f(i):
+            x = pick12(i)
+            y = pick23(i)
+            return x.value, y.value
+        for i in [0, 5, 10]:
+            res = interpret(f, [i], type_system=self.ts)
+            assert type(res.item0) is int   # precise
+            assert type(res.item1) is float
+            assert res.item0 == f(i)[0]
+            assert res.item1 == f(i)[1]
+
+    def test_pbc_getattr_conversion_with_classes(self):
+        class base: pass
+        class fr1(base): pass
+        class fr2(base): pass
+        class fr3(base): pass
+        fr1.value = 10
+        fr2.value = 5
+        fr3.value = 2.5
+        def pick12(i):
+            if i > 0:
+                return fr1
+            else:
+                return fr2
+        def pick23(i):
+            if i > 5:
+                return fr2
+            else:
+                return fr3
+        def f(i):
+            x = pick12(i)
+            y = pick23(i)
+            return x.value, y.value
+        for i in [0, 5, 10]:
+            res = interpret(f, [i], type_system=self.ts)
+            assert type(res.item0) is int   # precise
+            assert type(res.item1) is float
+            assert res.item0 == f(i)[0]
+            assert res.item1 == f(i)[1]
+
+    def test_multiple_specialized_functions(self):
+        def myadder(x, y):   # int,int->int or str,str->str
+            return x+y
+        def myfirst(x, y):   # int,int->int or str,str->str
+            return x
+        def mysecond(x, y):  # int,int->int or str,str->str
+            return y
+        myadder._annspecialcase_ = 'specialize:argtype(0)'
+        myfirst._annspecialcase_ = 'specialize:argtype(0)'
+        mysecond._annspecialcase_ = 'specialize:argtype(0)'
+        def f(i):
+            if i == 0:
+                g = myfirst
+            elif i == 1:
+                g = mysecond
+            else:
+                g = myadder
+            s = g("hel", "lo")
+            n = g(40, 2)
+            return len(s) * n
+        for i in range(3):
+            res = interpret(f, [i], type_system=self.ts)
+            assert res == f(i)
+
+    def test_specialized_method_of_frozen(self):
+        class space:
+            def _freeze_(self):
+                return True
+            def __init__(self, tag):
+                self.tag = tag
+            def wrap(self, x):
+                if isinstance(x, int):
+                    return self.tag + '< %d >' % x
+                else:
+                    return self.tag + x
+            wrap._annspecialcase_ = 'specialize:argtype(1)'
+        space1 = space("tag1:")
+        space2 = space("tag2:")
+        def f(i):
+            if i == 1:
+                sp = space1
+            else:
+                sp = space2
+            w1 = sp.wrap('hello')
+            w2 = sp.wrap(42)
+            return w1 + w2
+        res = interpret(f, [1], type_system=self.ts)
+        assert ''.join(res.chars) == 'tag1:hellotag1:< 42 >'
+        res = interpret(f, [0], type_system=self.ts)
+        assert ''.join(res.chars) == 'tag2:hellotag2:< 42 >'
+
+    def test_specialized_method(self):
+        class A:
+            def __init__(self, tag):
+                self.tag = tag
+            def wrap(self, x):
+                if isinstance(x, int):
+                    return self.tag + '< %d >' % x
+                else:
+                    return self.tag + x
+            wrap._annspecialcase_ = 'specialize:argtype(1)'
+        a1 = A("tag1:")
+        a2 = A("tag2:")
+        def f(i):
+            if i == 1:
+                sp = a1
+            else:
+                sp = a2
+            w1 = sp.wrap('hello')
+            w2 = sp.wrap(42)
+            return w1 + w2
+        res = interpret(f, [1], type_system=self.ts)
+        assert ''.join(res.chars) == 'tag1:hellotag1:< 42 >'
+        res = interpret(f, [0], type_system=self.ts)
+        assert ''.join(res.chars) == 'tag2:hellotag2:< 42 >'
+
+    def test_precise_method_call_1(self):
+        class A(object):
+            def meth(self, x=5):
+                return x+1
+        class B(A):
+            def meth(self, x=5):
+                return x+2
+        class C(A):
             pass
-        c = C()
-        c.method(x)
-        try:
-            return c.method(x + 1)
-        except E:
-            return None
-    res = interpret(call, [0])
+        def f(i, n):
+            # call both A.meth and B.meth with an explicit argument
+            if i > 0:
+                x = A()
+            else:
+                x = B()
+            result1 = x.meth(n)
+            # now call A.meth only, using the default argument
+            result2 = C().meth()
+            return result1 * result2
+        for i in [0, 1]:
+            res = interpret(f, [i, 1234], type_system=self.ts)
+            assert res == f(i, 1234)
+
+    def test_precise_method_call_2(self):
+        class A(object):
+            def meth(self, x=5):
+                return x+1
+        class B(A):
+            def meth(self, x=5):
+                return x+2
+        class C(A):
+            def meth(self, x=5):
+                return x+3
+        def f(i, n):
+            # call both A.meth and B.meth with an explicit argument
+            if i > 0:
+                x = A()
+            else:
+                x = B()
+            result1 = x.meth(n)
+            # now call A.meth and C.meth, using the default argument
+            if i > 0:
+                x = C()
+            else:
+                x = A()
+            result2 = x.meth()
+            return result1 * result2
+        for i in [0, 1]:
+            res = interpret(f, [i, 1234], type_system=self.ts)
+            assert res == f(i, 1234)
 
-def test_multiple_pbc_with_void_attr():
-    class A:
-        def _freeze_(self):
-            return True
-    a1 = A()
-    a2 = A()
-    unique = A()
-    unique.result = 42
-    a1.value = unique
-    a2.value = unique
-    def g(a):
-        return a.value.result
-    def f(i):
-        if i == 1:
-            a = a1
-        else:
-            a = a2
-        return g(a)
-    res = interpret(f, [0])
-    assert res == 42
-    res = interpret(f, [1])
-    assert res == 42
+
+def test_call_from_list():
+    # Don't test with ootype, since it doesn't support lists in a
+    # coherent way yet.
+    def f0(n): return n+200
+    def f1(n): return n+192
+    def f2(n): return n+46
+    def f3(n): return n+2987
+    def f4(n): return n+217
+    lst = [f0, f1, f2, f3, f4]
+    def f(i, n):
+        return lst[i](n)
+    for i in range(5):
+        res = interpret(f, [i, 1000])
+        assert res == f(i, 1000)
+
+
+# We don't care about the following test_hlinvoke tests working on
+# ootype. Maybe later. This kind of thing is only used in rdict
+# anyway, that will probably have a different kind of implementation
+# in ootype.
 
 def test_hlinvoke_simple():
     def f(a,b):
@@ -960,7 +1203,6 @@
     res = interp.eval_graph(ll_h_graph, [None, r_f.convert_desc(f2desc), 3])
     assert res == 1
 
-
 def test_hlinvoke_hltype():
     class A(object):
         def __init__(self, v):
@@ -1121,190 +1363,31 @@
     res = interp.eval_graph(ll_h_graph, [None, c_f, c_a])
     assert typeOf(res) == A_repr.lowleveltype
 
-def test_function_or_none():
-    def h(y):
-        return y+84
-    def g(y):
-        return y+42
-    def f(x, y):
-        d = {1: g, 2:h}
-        func = d.get(x, None)
-        if func:
-            return func(y)
-        return -1
-    res = interpret(f, [1, 100])
-    assert res == 142
-    res = interpret(f, [2, 100])
-    assert res == 184
-    res = interpret(f, [3, 100])
-    assert res == -1
-
-def test_pbc_getattr_conversion():
-    fr1 = Freezing()
-    fr2 = Freezing()
-    fr3 = Freezing()
-    fr1.value = 10
-    fr2.value = 5
-    fr3.value = 2.5
-    def pick12(i):
-        if i > 0:
-            return fr1
-        else:
-            return fr2
-    def pick23(i):
-        if i > 5:
-            return fr2
-        else:
-            return fr3
-    def f(i):
-        x = pick12(i)
-        y = pick23(i)
-        return x.value, y.value
-    for i in [0, 5, 10]:
-        res = interpret(f, [i])
-        assert type(res.item0) is int   # precise
-        assert type(res.item1) is float
-        assert res.item0 == f(i)[0]
-        assert res.item1 == f(i)[1]
-
-def test_pbc_getattr_conversion_with_classes():
-    class base: pass
-    class fr1(base): pass
-    class fr2(base): pass
-    class fr3(base): pass
-    fr1.value = 10
-    fr2.value = 5
-    fr3.value = 2.5
-    def pick12(i):
-        if i > 0:
-            return fr1
-        else:
-            return fr2
-    def pick23(i):
-        if i > 5:
-            return fr2
-        else:
-            return fr3
-    def f(i):
-        x = pick12(i)
-        y = pick23(i)
-        return x.value, y.value
-    for i in [0, 5, 10]:
-        res = interpret(f, [i])
-        assert type(res.item0) is int   # precise
-        assert type(res.item1) is float
-        assert res.item0 == f(i)[0]
-        assert res.item1 == f(i)[1]
-
-def test_multiple_specialized_functions():
-    def myadder(x, y):   # int,int->int or str,str->str
-        return x+y
-    def myfirst(x, y):   # int,int->int or str,str->str
-        return x
-    def mysecond(x, y):  # int,int->int or str,str->str
-        return y
-    myadder._annspecialcase_ = 'specialize:argtype(0)'
-    myfirst._annspecialcase_ = 'specialize:argtype(0)'
-    mysecond._annspecialcase_ = 'specialize:argtype(0)'
-    def f(i):
-        if i == 0:
-            g = myfirst
-        elif i == 1:
-            g = mysecond
-        else:
-            g = myadder
-        s = g("hel", "lo")
-        n = g(40, 2)
-        return len(s) * n
-    for i in range(3):
-        res = interpret(f, [i])
-        assert res == f(i)
-
-def test_specialized_method_of_frozen():
-    class space:
-        def __init__(self, tag):
-            self.tag = tag
-        def wrap(self, x):
-            if isinstance(x, int):
-                return self.tag + '< %d >' % x
-            else:
-                return self.tag + x
-        wrap._annspecialcase_ = 'specialize:argtype(1)'
-    space1 = space("tag1:")
-    space2 = space("tag2:")
-    def f(i):
-        if i == 1:
-            sp = space1
-        else:
-            sp = space2
-        w1 = sp.wrap('hello')
-        w2 = sp.wrap(42)
-        return w1 + w2
-    res = interpret(f, [1])
-    assert ''.join(res.chars) == 'tag1:hellotag1:< 42 >'
-    res = interpret(f, [0])
-    assert ''.join(res.chars) == 'tag2:hellotag2:< 42 >'
 
-def test_call_from_list():
-    def f0(n): return n+200
-    def f1(n): return n+192
-    def f2(n): return n+46
-    def f3(n): return n+2987
-    def f4(n): return n+217
-    lst = [f0, f1, f2, f3, f4]
-    def f(i, n):
-        return lst[i](n)
-    for i in range(5):
-        res = interpret(f, [i, 1000])
-        assert res == f(i, 1000)
+class TestLltype(BaseTestRPBC):
 
-def test_precise_method_call_1():
-    class A(object):
-        def meth(self, x=5):
-            return x+1
-    class B(A):
-        def meth(self, x=5):
-            return x+2
-    class C(A):
-        pass
-    def f(i, n):
-        # call both A.meth and B.meth with an explicit argument
-        if i > 0:
-            x = A()
-        else:
-            x = B()
-        result1 = x.meth(n)
-        # now call A.meth only, using the default argument
-        result2 = C().meth()
-        return result1 * result2
-    for i in [0, 1]:
-        res = interpret(f, [i, 1234])
-        assert res == f(i, 1234)
+    ts = "lltype"
+
+    def class_name(self, value):
+        return "".join(value.super.typeptr.name)[:-1]
+
+    def read_attr(self, value, attr_name):
+        value = value._obj
+        while value is not None:
+            attr = getattr(value, "inst_" + attr_name, None)
+            if attr is None:
+                value = value._parentstructure()
+            else:
+                return attr
+        raise AttributeError()
+
+class TestOotype(BaseTestRPBC):
+
+    ts = "ootype"
+
+    def class_name(self, value):
+        return typeOf(value)._name.split(".")[-1] 
+
+    def read_attr(self, value, attr):
+        return getattr(value, "o" + attr)
 
-def test_precise_method_call_2():
-    class A(object):
-        def meth(self, x=5):
-            return x+1
-    class B(A):
-        def meth(self, x=5):
-            return x+2
-    class C(A):
-        def meth(self, x=5):
-            return x+3
-    def f(i, n):
-        # call both A.meth and B.meth with an explicit argument
-        if i > 0:
-            x = A()
-        else:
-            x = B()
-        result1 = x.meth(n)
-        # now call A.meth and C.meth, using the default argument
-        if i > 0:
-            x = C()
-        else:
-            x = A()
-        result2 = x.meth()
-        return result1 * result2
-    for i in [0, 1]:
-        res = interpret(f, [i, 1234])
-        assert res == f(i, 1234)

Modified: pypy/branch/njriley-trans/pypy/rpython/typesystem.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/rpython/typesystem.py	(original)
+++ pypy/branch/njriley-trans/pypy/rpython/typesystem.py	Fri Mar 10 06:12:02 2006
@@ -5,10 +5,13 @@
 
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.lltypesystem import lltype
+from pypy.rpython import error
 
 class TypeSystem(object):
     __metaclass__ = extendabletype
 
+    offers_exceptiondata = True
+
     def __getattr__(self, name):
         """Lazy import to avoid circular dependencies."""
         def load(modname):
@@ -17,7 +20,7 @@
                                   None, None, ['__doc__'])
             except ImportError:
                 return None
-        if name in ('rclass', 'rpbc', 'rbuiltin'):
+        if name in ('rclass', 'rpbc', 'rbuiltin', 'exceptiondata'):
             mod = load(name)
             if mod is not None:
                 setattr(self, name, mod)
@@ -92,6 +95,24 @@
     def isCompatibleType(self, t1, t2):
         return lltype.isCompatibleType(t1, t2)
 
+    def generic_is(self, robj1, robj2, hop):
+        roriginal1 = robj1
+        roriginal2 = robj2
+        if robj1.lowleveltype is lltype.Void:
+            robj1 = robj2
+        elif robj2.lowleveltype is lltype.Void:
+            robj2 = robj1
+        if (not isinstance(robj1.lowleveltype, lltype.Ptr) or
+            not isinstance(robj2.lowleveltype, lltype.Ptr)):
+            raise TyperError('is of instances of the non-pointers: %r, %r' % (
+                roriginal1, roriginal2))
+        if robj1.lowleveltype != robj2.lowleveltype:
+            raise TyperError('is of instances of different pointer types: %r, %r' % (
+                roriginal1, roriginal2))
+            
+        v_list = hop.inputargs(robj1, robj2)
+        return hop.genop('ptr_eq', v_list, resulttype=lltype.Bool)
+
 class ObjectOrientedTypeSystem(TypeSystem):
     name = "ootypesystem"
     callable_trait = (ootype.StaticMethod, ootype.static_meth)
@@ -106,6 +127,23 @@
     def isCompatibleType(self, t1, t2):
         return ootype.isCompatibleType(t1, t2)
 
+    def generic_is(self, robj1, robj2, hop):
+        roriginal1 = robj1
+        roriginal2 = robj2
+        if robj1.lowleveltype is lltype.Void:
+            robj1 = robj2
+        elif robj2.lowleveltype is lltype.Void:
+            robj2 = robj1
+        if (not isinstance(robj1.lowleveltype, ootype.Instance) or
+            not isinstance(robj2.lowleveltype, ootype.Instance)) and \
+            (robj1.lowleveltype is not ootype.Class or
+             robj2.lowleveltype is not ootype.Class):
+            raise error.TyperError('is of instances of the non-instances: %r, %r' % (
+                roriginal1, roriginal2))
+            
+        v_list = hop.inputargs(robj1, robj2)
+        return hop.genop('oois', v_list, resulttype=lltype.Bool)
+
 # All typesystems are singletons
 LowLevelTypeSystem.instance = LowLevelTypeSystem()
 ObjectOrientedTypeSystem.instance = ObjectOrientedTypeSystem()

Modified: pypy/branch/njriley-trans/pypy/tool/isolate.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/tool/isolate.py	(original)
+++ pypy/branch/njriley-trans/pypy/tool/isolate.py	Fri Mar 10 06:12:02 2006
@@ -28,6 +28,7 @@
     _closed = False
 
     def __init__(self, module):
+        self.module = module
         self.slave = slaveproc.SlaveProcess(os.path.join(os.path.dirname(__file__),
                                                          'isolate_slave.py'))
         res = self.slave.cmd(('load', module))

Modified: pypy/branch/njriley-trans/pypy/tool/opcode.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/tool/opcode.py	(original)
+++ pypy/branch/njriley-trans/pypy/tool/opcode.py	Fri Mar 10 06:12:02 2006
@@ -1,193 +1,9 @@
-# XXX this is a (hopefully temporary) copy of the 2.3 module of CPython.
-#     See pydis.py.
+# load opcode.py as pythonopcode from our own lib
+# This should handle missing local copy
+def load_opcode():
+    import py
+    opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/modified-2.4.1/opcode.py')
+    execfile(str(opcode_path), globals())
 
-"""
-opcode module - potentially shared between dis and other modules which
-operate on bytecodes (e.g. peephole optimizers).
-"""
-
-__all__ = ["cmp_op", "hasconst", "hasname", "hasjrel", "hasjabs",
-           "haslocal", "hascompare", "hasfree", "opname", "opmap",
-           "HAVE_ARGUMENT", "EXTENDED_ARG"]
-
-cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
-        'is not', 'exception match', 'BAD')
-
-hasconst = []
-hasname = []
-hasjrel = []
-hasjabs = []
-haslocal = []
-hascompare = []
-hasfree = []
-
-opmap = {}
-opname = [''] * 256
-for op in range(256): opname[op] = '<' + `op` + '>'
-del op
-
-def def_op(name, op):
-    opname[op] = name
-    opmap[name] = op
-
-def name_op(name, op):
-    def_op(name, op)
-    hasname.append(op)
-
-def jrel_op(name, op):
-    def_op(name, op)
-    hasjrel.append(op)
-
-def jabs_op(name, op):
-    def_op(name, op)
-    hasjabs.append(op)
-
-# Instruction opcodes for compiled code
-
-def_op('STOP_CODE', 0)
-def_op('POP_TOP', 1)
-def_op('ROT_TWO', 2)
-def_op('ROT_THREE', 3)
-def_op('DUP_TOP', 4)
-def_op('ROT_FOUR', 5)
-def_op('IEXEC_THROW', 6)
-
-def_op('UNARY_POSITIVE', 10)
-def_op('UNARY_NEGATIVE', 11)
-def_op('UNARY_NOT', 12)
-def_op('UNARY_CONVERT', 13)
-
-def_op('UNARY_INVERT', 15)
-
-def_op('BINARY_POWER', 19)
-
-def_op('BINARY_MULTIPLY', 20)
-def_op('BINARY_DIVIDE', 21)
-def_op('BINARY_MODULO', 22)
-def_op('BINARY_ADD', 23)
-def_op('BINARY_SUBTRACT', 24)
-def_op('BINARY_SUBSCR', 25)
-def_op('BINARY_FLOOR_DIVIDE', 26)
-def_op('BINARY_TRUE_DIVIDE', 27)
-def_op('INPLACE_FLOOR_DIVIDE', 28)
-def_op('INPLACE_TRUE_DIVIDE', 29)
-
-def_op('SLICE+0', 30)
-def_op('SLICE+1', 31)
-def_op('SLICE+2', 32)
-def_op('SLICE+3', 33)
-
-def_op('STORE_SLICE+0', 40)
-def_op('STORE_SLICE+1', 41)
-def_op('STORE_SLICE+2', 42)
-def_op('STORE_SLICE+3', 43)
-
-def_op('DELETE_SLICE+0', 50)
-def_op('DELETE_SLICE+1', 51)
-def_op('DELETE_SLICE+2', 52)
-def_op('DELETE_SLICE+3', 53)
-
-def_op('INPLACE_ADD', 55)
-def_op('INPLACE_SUBTRACT', 56)
-def_op('INPLACE_MULTIPLY', 57)
-def_op('INPLACE_DIVIDE', 58)
-def_op('INPLACE_MODULO', 59)
-def_op('STORE_SUBSCR', 60)
-def_op('DELETE_SUBSCR', 61)
-
-def_op('BINARY_LSHIFT', 62)
-def_op('BINARY_RSHIFT', 63)
-def_op('BINARY_AND', 64)
-def_op('BINARY_XOR', 65)
-def_op('BINARY_OR', 66)
-def_op('INPLACE_POWER', 67)
-def_op('GET_ITER', 68)
-
-def_op('PRINT_EXPR', 70)
-def_op('PRINT_ITEM', 71)
-def_op('PRINT_NEWLINE', 72)
-def_op('PRINT_ITEM_TO', 73)
-def_op('PRINT_NEWLINE_TO', 74)
-def_op('INPLACE_LSHIFT', 75)
-def_op('INPLACE_RSHIFT', 76)
-def_op('INPLACE_AND', 77)
-def_op('INPLACE_XOR', 78)
-def_op('INPLACE_OR', 79)
-def_op('BREAK_LOOP', 80)
-def_op('END_IEXEC', 81)        
-
-def_op('LOAD_LOCALS', 82)
-def_op('RETURN_VALUE', 83)
-def_op('IMPORT_STAR', 84)
-def_op('EXEC_STMT', 85)
-def_op('YIELD_VALUE', 86)
-
-def_op('POP_BLOCK', 87)
-def_op('END_FINALLY', 88)
-def_op('BUILD_CLASS', 89)
-
-HAVE_ARGUMENT = 90              # Opcodes from here have an argument:
-
-name_op('STORE_NAME', 90)       # Index in name list
-name_op('DELETE_NAME', 91)      # ""
-def_op('UNPACK_SEQUENCE', 92)   # Number of tuple items
-jrel_op('FOR_ITER', 93)
-
-name_op('STORE_ATTR', 95)       # Index in name list
-name_op('DELETE_ATTR', 96)      # ""
-name_op('STORE_GLOBAL', 97)     # ""
-name_op('DELETE_GLOBAL', 98)    # ""
-def_op('DUP_TOPX', 99)          # number of items to duplicate
-def_op('LOAD_CONST', 100)       # Index in const list
-hasconst.append(100)
-name_op('LOAD_NAME', 101)       # Index in name list
-def_op('BUILD_TUPLE', 102)      # Number of tuple items
-def_op('BUILD_LIST', 103)       # Number of list items
-def_op('BUILD_MAP', 104)        # Always zero for now
-name_op('LOAD_ATTR', 105)       # Index in name list
-def_op('COMPARE_OP', 106)       # Comparison operator
-hascompare.append(106)
-name_op('IMPORT_NAME', 107)     # Index in name list
-name_op('IMPORT_FROM', 108)     # Index in name list
-
-jrel_op('JUMP_FORWARD', 110)    # Number of bytes to skip
-jrel_op('JUMP_IF_FALSE', 111)   # ""
-jrel_op('JUMP_IF_TRUE', 112)    # ""
-jabs_op('JUMP_ABSOLUTE', 113)   # Target byte offset from beginning of code
-
-name_op('LOAD_GLOBAL', 116)     # Index in name list
-
-jabs_op('CONTINUE_LOOP', 119)   # Target address
-jrel_op('SETUP_LOOP', 120)      # Distance to target address
-jrel_op('SETUP_EXCEPT', 121)    # ""
-jrel_op('SETUP_FINALLY', 122)   # ""
-jrel_op('SETUP_IEXEC', 123)     # ""
-
-def_op('LOAD_FAST', 124)        # Local variable number
-haslocal.append(124)
-def_op('STORE_FAST', 125)       # Local variable number
-haslocal.append(125)
-def_op('DELETE_FAST', 126)      # Local variable number
-haslocal.append(126)
-
-def_op('RAISE_VARARGS', 130)    # Number of raise arguments (1, 2, or 3)
-def_op('CALL_FUNCTION', 131)    # #args + (#kwargs << 8)
-def_op('MAKE_FUNCTION', 132)    # Number of args with default values
-def_op('BUILD_SLICE', 133)      # Number of items
-
-def_op('MAKE_CLOSURE', 134)
-def_op('LOAD_CLOSURE', 135)
-hasfree.append(135)
-def_op('LOAD_DEREF', 136)
-hasfree.append(136)
-def_op('STORE_DEREF', 137)
-hasfree.append(137)
-
-def_op('CALL_FUNCTION_VAR', 140)     # #args + (#kwargs << 8)
-def_op('CALL_FUNCTION_KW', 141)      # #args + (#kwargs << 8)
-def_op('CALL_FUNCTION_VAR_KW', 142)  # #args + (#kwargs << 8)
-
-def_op('EXTENDED_ARG', 143)
-EXTENDED_ARG = 143
-
-del def_op, name_op, jrel_op, jabs_op
+load_opcode()
+del load_opcode

Modified: pypy/branch/njriley-trans/pypy/tool/option.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/tool/option.py	(original)
+++ pypy/branch/njriley-trans/pypy/tool/option.py	Fri Mar 10 06:12:02 2006
@@ -16,7 +16,7 @@
          # "ast" uses interpreter/pyparser & interpreter/astcompiler.py 
          # "cpython" uses cpython parser and cpython c-level compiler 
     usemodules = []                        
-    version = "2.4" # "native" / "2.3" / "2.4"
+    version = "2.5a" # "native" / "2.3" / "2.4" / "2.5a"
 
 def run_tb_server(option, opt, value, parser):
     from pypy.tool import tb_server

Modified: pypy/branch/njriley-trans/pypy/translator/c/database.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/database.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/database.py	Fri Mar 10 06:12:02 2006
@@ -2,6 +2,7 @@
      Primitive, Ptr, typeOf, RuntimeTypeInfo, \
      Struct, Array, FuncType, PyObject, Void, \
      ContainerType, OpaqueType
+from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem.llmemory import Address
 from pypy.rpython.memory.lladdress import NULL
 from pypy.translator.c.primitive import PrimitiveName, PrimitiveType
@@ -107,6 +108,9 @@
             node = self.containernodes[container]
         except KeyError:
             T = typeOf(container)
+            if isinstance(T, (lltype.Array, lltype.Struct)):
+                if hasattr(self.gctransformer, 'consider_constant'):
+                    self.gctransformer.consider_constant(T, container)
             nodefactory = ContainerNodeFactory[T.__class__]
             node = nodefactory(self, T, container)
             self.containernodes[container] = node
@@ -178,16 +182,23 @@
                 if i == show_i:
                     dump()
                     show_i += 1000
+            work_to_do = False
             if not is_later_yet:
-                self.gctransformer.finish()
+                newgcdependencies = self.gctransformer.finish()
+                if newgcdependencies:
+                    work_to_do = True
+                    for value in newgcdependencies:
+                        if isinstance(typeOf(value), ContainerType):
+                            self.getcontainernode(value)
+                        else:
+                            self.get(value)
                 is_later_yet = True
             if self.latercontainerlist:
+                work_to_do = True
                 for node in self.latercontainerlist:
-                    node.make_funcgen()
+                    node.make_funcgens()
                     self.containerlist.append(node)
                 self.latercontainerlist = []
-            else:
-                work_to_do = False
         self.completed = True
         if show_progress:
             dump()

Modified: pypy/branch/njriley-trans/pypy/translator/c/external.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/external.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/external.py	Fri Mar 10 06:12:02 2006
@@ -16,6 +16,9 @@
         self.argtypenames = [db.gettype(T) for T in self.FUNCTYPE.ARGS]
         self.resulttypename = db.gettype(self.FUNCTYPE.RESULT)
 
+    def name(self, cname):  #virtual
+        return cname
+
     def argnames(self):
         return ['%s%d' % (somelettersfrom(self.argtypenames[i]), i)
                 for i in range(len(self.argtypenames))]

Modified: pypy/branch/njriley-trans/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/funcgen.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/funcgen.py	Fri Mar 10 06:12:02 2006
@@ -52,10 +52,9 @@
             for op in block.operations:
                 mix.extend(op.args)
                 mix.append(op.result)
-                if hasattr(op, "cleanup"):
-                    if op.cleanup is None:
-                        continue
-                    for cleanupop in op.cleanup[0] + op.cleanup[1]:
+                if getattr(op, "cleanup", None) is not None:
+                    cleanup_finally, cleanup_except = op.cleanup
+                    for cleanupop in cleanup_finally + cleanup_except:
                         mix.extend(cleanupop.args)
                         mix.append(cleanupop.result)
             for link in block.exits:
@@ -83,6 +82,9 @@
         self.vars = uniquemix
         self.lltypes = None
 
+    def name(self, cname):  #virtual
+        return cname
+
     def implementation_begin(self):
         db = self.db
         lltypes = {}
@@ -164,7 +166,7 @@
                 seen[name] = True
                 result = cdecl(self.lltypename(v), LOCALVAR % name) + ';'
                 if self.lltypemap(v) is Void:
-                    result = '/*%s*/' % result
+                    continue  #result = '/*%s*/' % result
                 result_by_name.append((v._name, result))
         result_by_name.sort()
         return [result for name, result in result_by_name]
@@ -184,9 +186,13 @@
                 err   = 'err%d_%d' % (myblocknum, i)
                 for line in self.gen_op(op, err):
                     yield line
+                # XXX hackish -- insert the finally code unless the operation
+                # already did
                 cleanup = getattr(op, 'cleanup', None)
-                if cleanup is not None:
-                    for subop in op.cleanup[0]:
+                if (cleanup is not None and
+                    op.opname not in ("direct_call", "indirect_call")):
+                    cleanup_finally, cleanup_except = cleanup
+                    for subop in cleanup_finally:
                         for line in self.gen_op(subop, "should_never_be_jumped_to2"):
                             yield line
             fallthrough = False
@@ -308,10 +314,11 @@
             for i, op in list(enumerate(block.operations))[::-1]:
                 if getattr(op, 'cleanup', None) is None:
                     continue
-                errorcases.setdefault(op.cleanup[1], []).append(i)
+                cleanup_finally, cleanup_except = op.cleanup
+                errorcases.setdefault(cleanup_except, []).append(i)
 
             if fallthrough:
-                firstclean = tuple(block.operations[-1].cleanup[1])
+                cleanup_finally, firstclean = block.operations[-1].cleanup
                 first = errorcases[firstclean]
                 del errorcases[firstclean]
                 first.remove(len(block.operations) - 1)
@@ -421,8 +428,17 @@
         try:
             cleanup = op.cleanup
         except AttributeError:
-            raise AttributeError("(in)direct_call %r without explicit .cleanup" % op)
+            raise AttributeError("%r without explicit .cleanup"
+                                 %  (op,))
         if cleanup is not None:
+            # insert the 'finally' operations before the exception check
+            cleanup_finally, cleanup_except = op.cleanup
+            if cleanup_finally:
+                finally_lines = ['/* finally: */']
+                for cleanupop in cleanup_finally:
+                    finally_lines.extend(
+                        self.gen_op(cleanupop, 'should_never_be_jumped_to'))
+                line = '%s\n%s' % (line, '\n\t'.join(finally_lines))
             line = '%s\n%s' % (line, self.check_directcall_result(op, err))
         return line
 

Modified: pypy/branch/njriley-trans/pypy/translator/c/gc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/gc.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/gc.py	Fri Mar 10 06:12:02 2006
@@ -192,7 +192,7 @@
                                                                 is_varsize,
                                                                 err)
         if gcinfo and gcinfo.finalizer:
-            result += ('\nGC_REGISTER_FINALIZER(%s, %s, NULL, NULL, NULL);'
+            result += ('\nGC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);'
                        % (eresult, gcinfo.finalizer))
         return result
 
@@ -278,6 +278,22 @@
         fnptr = self.db.gctransformer.frameworkgc_setup_ptr.value
         yield '%s();' % (self.db.get(fnptr),)
 
+    def pre_gc_code(self):
+        return []
+
     def OP_GC_RELOAD_POSSIBLY_MOVED(self, funcgen, op, err):
         args = [funcgen.expr(v) for v in op.args]
         return '%s = %s; /* for moving GCs */' % (args[1], args[0])
+
+    def common_gcheader_definition(self, defnode):
+        return [('flags', lltype.Signed), ('typeid', lltype.Signed)]
+
+    def common_gcheader_initdata(self, defnode):
+        # this more or less assumes mark-and-sweep gc
+        o = defnode.obj
+        while True:
+            n = o._parentstructure()
+            if n is None:
+                break
+            o = n
+        return [0, defnode.db.gctransformer.id_of_type[typeOf(o)]]

Modified: pypy/branch/njriley-trans/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/genc.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/genc.py	Fri Mar 10 06:12:02 2006
@@ -736,5 +736,5 @@
 \t$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDEDIRS)
 
 clean:
-\trm -f $(OBJECTS)
+\trm -f $(OBJECTS) $(TARGET)
 '''

Modified: pypy/branch/njriley-trans/pypy/translator/c/node.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/node.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/node.py	Fri Mar 10 06:12:02 2006
@@ -59,6 +59,9 @@
         db = self.db
         STRUCT = self.STRUCT
         varlength = self.varlength
+        if needs_gcheader(self.STRUCT):
+            for fname, T in db.gcpolicy.struct_gcheader_definition(self):
+                self.fields.append((fname, db.gettype(T, who_asks=self)))
         for name in STRUCT._names:
             T = self.c_struct_field_type(name)
             if name == STRUCT._arrayfld:
@@ -67,9 +70,6 @@
             else:
                 typename = db.gettype(T, who_asks=self)
             self.fields.append((self.c_struct_field_name(name), typename))
-        if needs_gcheader(self.STRUCT):
-            for fname, T in db.gcpolicy.struct_gcheader_definition(self):
-                self.fields.insert(0, (fname, db.gettype(T, who_asks=self)))
         self.gcinfo  # force it to be computed
 
     def computegcinfo(self):
@@ -182,7 +182,8 @@
         yield 'struct %s {' % self.name
         for fname, typename in self.gcfields:
             yield '\t' + cdecl(typename, fname) + ';'
-        yield '\tlong length;'
+        if not self.ARRAY._hints.get('nolength', False):
+            yield '\tlong length;'
         line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength)
         if self.ARRAY.OF is Void:    # strange
             line = '/* %s */' % line
@@ -216,7 +217,10 @@
 
     def debug_offsets(self):
         # generate three offsets for debugging inspection
-        yield 'offsetof(struct %s, length)' % (self.name,)
+        if not self.ARRAY._hints.get('nolength', False):
+            yield 'offsetof(struct %s, length)' % (self.name,)
+        else:
+            yield '-1'
         if self.ARRAY.OF is not Void:
             yield 'offsetof(struct %s, items[0])' % (self.name,)
             yield 'offsetof(struct %s, items[1])' % (self.name,)
@@ -417,7 +421,7 @@
 class FuncNode(ContainerNode):
     nodekind = 'func'
     if USESLOTS:
-        __slots__ = """funcgen""".split()
+        __slots__ = """funcgens""".split()
 
     def __init__(self, db, T, obj):
         self.globalcontainer = True
@@ -431,37 +435,38 @@
             self.includes = ()
             self.name = db.namespace.uniquename('g_' + self.basename())
         if not getattr(obj, 'isgchelper', False):
-            self.make_funcgen()
+            self.make_funcgens()
         #self.dependencies = {}
         self.typename = db.gettype(T)  #, who_asks=self)
         self.ptrname = self.name
 
-    def make_funcgen(self):
-        self.funcgen = select_function_code_generator(self.obj, self.db, self.name)
-        if self.funcgen:
-            argnames = self.funcgen.argnames()
+    def make_funcgens(self):
+        self.funcgens = select_function_code_generators(self.obj, self.db, self.name)
+        if self.funcgens:
+            argnames = self.funcgens[0].argnames()  #Assume identical for all funcgens
             self.implementationtypename = self.db.gettype(self.T, argnames=argnames)
 
     def basename(self):
         return self.obj._name
 
     def enum_dependencies(self):
-        if self.funcgen is None:
+        if not self.funcgens:
             return []
-        return self.funcgen.allconstantvalues()
+        return self.funcgens[0].allconstantvalues() #Assume identical for all funcgens
 
     def forward_declaration(self):
-        if self.funcgen:
-            return ContainerNode.forward_declaration(self)
-        else:
-            return []
+        for funcgen in self.funcgens:
+            yield '%s;' % (
+                cdecl(self.implementationtypename, funcgen.name(self.name)))
 
     def implementation(self):
-        funcgen = self.funcgen
-        if funcgen is None:
-            return
+        for funcgen in self.funcgens:
+            for s in self.funcgen_implementation(funcgen):
+                yield s
+
+    def funcgen_implementation(self, funcgen):
         funcgen.implementation_begin()
-        yield '%s {' % cdecl(self.implementationtypename, self.name)
+        yield '%s {' % cdecl(self.implementationtypename, funcgen.name(self.name))
         #
         # declare the local variables
         #
@@ -504,30 +509,36 @@
 
 assert not USESLOTS or '__dict__' not in dir(FuncNode)
 
-def select_function_code_generator(fnobj, db, functionname):
+def select_function_code_generators(fnobj, db, functionname):
     if fnobj._callable in extfunc.EXTERNALS:
         # 'fnobj' is one of the ll_xyz() functions with the suggested_primitive
         # flag in pypy.rpython.module.*.  The corresponding C wrappers are
         # written by hand in src/ll_*.h, and declared in extfunc.EXTERNALS.
         db.externalfuncs[fnobj._callable] = fnobj
-        return None
+        return []
     elif getattr(fnobj._callable, 'suggested_primitive', False):
         raise ValueError, "trying to compile suggested primitive %r" % (
             fnobj._callable,)
     elif hasattr(fnobj, 'graph'):
         cpython_exc = getattr(fnobj, 'exception_policy', None) == "CPython"
         if hasattr(db, 'stacklessdata') and not db.use_stackless_transformation:
-            from pypy.translator.c.stackless import SlpFunctionCodeGenerator
-            gencls = SlpFunctionCodeGenerator
+            split_slp_function = False
+            if split_slp_function:
+                from pypy.translator.c.stackless import SlpSaveOnlyFunctionCodeGenerator, \
+                                                        SlpResumeFunctionCodeGenerator
+                return [SlpSaveOnlyFunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname),
+                        SlpResumeFunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname)]
+            else:
+                from pypy.translator.c.stackless import SlpFunctionCodeGenerator
+                return [SlpFunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname)]
         else:
-            gencls = FunctionCodeGenerator
-        return gencls(fnobj.graph, db, cpython_exc, functionname)
+            return [FunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname)]
     elif getattr(fnobj, 'external', None) == 'C':
         # deprecated case
         if getattr(fnobj, 'includes', None):
-            return None   # assume no wrapper needed
+            return []   # assume no wrapper needed
         else:
-            return CExternalFunctionCodeGenerator(fnobj, db)
+            return [CExternalFunctionCodeGenerator(fnobj, db)]
     else:
         raise ValueError, "don't know how to generate code for %r" % (fnobj,)
 

Modified: pypy/branch/njriley-trans/pypy/translator/c/primitive.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/primitive.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/primitive.py	Fri Mar 10 06:12:02 2006
@@ -2,7 +2,7 @@
 from pypy.rpython.lltypesystem.lltype import *
 from pypy.rpython.lltypesystem.llmemory import Address, fakeaddress, \
      AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \
-     CompositeOffset
+     CompositeOffset, ArrayLengthOffset
 from pypy.rpython.memory.gc import GCHeaderOffset
 from pypy.rpython.memory.lladdress import NULL
 
@@ -24,6 +24,9 @@
         elif isinstance(value, ArrayItemsOffset):
             return 'offsetof(%s, items)'%(
                 db.gettype(value.TYPE).replace('@', ''))
+        elif isinstance(value, ArrayLengthOffset):
+            return 'offsetof(%s, length)'%(
+                db.gettype(value.TYPE).replace('@', ''))
         elif isinstance(value, CompositeOffset):
             return '%s + %s' % (name_signed(value.first, db), name_signed(value.second, db))
         elif type(value) == AddressOffset:
@@ -83,10 +86,22 @@
     if value is NULL:
         return 'NULL'
     assert isinstance(value, fakeaddress)
-    if value.ob is None:
-        return 'NULL'
+    if value.offset is None:
+        if value.ob is None:
+            return 'NULL'
+        else:
+            if isinstance(typeOf(value.ob), ContainerType):
+                return db.getcontainernode(value.ob).ptrname
+            else:
+                return db.get(value.ob)
     else:
-        return db.get(value.ob)
+        assert value.offset is not None
+        if isinstance(typeOf(value.ob), ContainerType):
+            base = db.getcontainernode(value.ob).ptrname
+        else:
+            base = db.get(value.ob)
+        
+        return '(void*)(((char*)(%s)) + (%s))'%(base, db.get(value.offset))
 
 PrimitiveName = {
     Signed:   name_signed,

Modified: pypy/branch/njriley-trans/pypy/translator/c/src/address.h
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/src/address.h	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/src/address.h	Fri Mar 10 06:12:02 2006
@@ -17,7 +17,7 @@
 #define OP_ADR_GE(x,y,r,err)	  r = ((x) >= (y))
 
 #define OP_RAW_MALLOC(size,r,err)                                           \
-    r = (void*) malloc(size);                                              \
+    r = (void*) calloc(1, size);                                            \
     if (r == NULL) FAIL_EXCEPTION(err, PyExc_MemoryError, "out of memory");\
 
 #ifdef MS_WINDOWS

Modified: pypy/branch/njriley-trans/pypy/translator/c/src/g_prerequisite.h
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/src/g_prerequisite.h	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/src/g_prerequisite.h	Fri Mar 10 06:12:02 2006
@@ -11,3 +11,5 @@
 
 #include "thread.h"   /* needs to be included early to define the
                          struct RPyOpaque_ThreadLock */
+
+#include <stddef.h>

Modified: pypy/branch/njriley-trans/pypy/translator/c/src/support.h
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/src/support.h	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/src/support.h	Fri Mar 10 06:12:02 2006
@@ -33,7 +33,9 @@
 PyObject * gencfunc_descr_get(PyObject *func, PyObject *obj, PyObject *type);
 PyObject* PyList_Pack(int n, ...);
 PyObject* PyDict_Pack(int n, ...);
+#if PY_VERSION_HEX < 0x02040000   /* 2.4 */
 PyObject* PyTuple_Pack(int n, ...);
+#endif
 #if PY_VERSION_HEX >= 0x02030000   /* 2.3 */
 # define PyObject_GetItem1  PyObject_GetItem
 # define PyObject_SetItem1  PyObject_SetItem

Modified: pypy/branch/njriley-trans/pypy/translator/c/stackless.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/stackless.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/stackless.py	Fri Mar 10 06:12:02 2006
@@ -211,6 +211,7 @@
 
 
 class SlpFunctionCodeGenerator(FunctionCodeGenerator):
+    needs_resume = True
 
     def cfunction_body(self):
         # lists filled by check_directcall_result() from super.cfunction_body()
@@ -219,13 +220,16 @@
         body = list(super(SlpFunctionCodeGenerator, self).cfunction_body())
         #
         if self.savelines:   # header (if we need to resume)
-            yield 'if (slp_frame_stack_top) goto resume;'
+            if self.needs_resume:
+                yield 'if (slp_frame_stack_top) goto resume;'
         for line in body:    # regular body
             yield line
         if self.savelines:
             yield ''
             for line in self.savelines:  # save-state-away lines
                 yield line
+            if not self.needs_resume:
+                return
             yield ''
             yield 'resume:'    # resume-state blocks
             yield '{'
@@ -247,7 +251,7 @@
             argtypes = [T for T in argtypes if T is not lltype.Void]
             rettype = signature_type(self.lltypemap(self.graph.getreturnvar()))
             FUNC = lltype.FuncType(argtypes, rettype)
-            slpdata.registerunwindable(self.functionname, FUNC,
+            slpdata.registerunwindable(self.name(self.functionname), FUNC,
                                        resume_points = len(self.resumeblocks))
 
         del self.savelines
@@ -346,6 +350,17 @@
         return line
 
 
+class SlpSaveOnlyFunctionCodeGenerator(SlpFunctionCodeGenerator):
+    needs_resume = False
+
+
+class SlpResumeFunctionCodeGenerator(SlpFunctionCodeGenerator):
+    needs_resume = True
+
+    def name(self, cname):
+        return cname + '_SlpResume'
+        
+
 def signature_type(T):
     """Return T unless it's a pointer type, in which case we return a general
     basic pointer type.

Modified: pypy/branch/njriley-trans/pypy/translator/c/symboltable.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/symboltable.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/symboltable.py	Fri Mar 10 06:12:02 2006
@@ -142,13 +142,18 @@
         ARRAY = self._TYPE.TO
         if isinstance(ARRAY, Array):
             length_offset = self._nth_offset(0)
+            if length_offset == -1:
+                raise TypeError, "array has no stored length: %r" % (ARRAY,)
             return self._read(Signed, length_offset)
         raise TypeError, "not an array: %r" % (ARRAY,)
 
     def __getitem__(self, index):
         ARRAY = self._TYPE.TO
         if isinstance(ARRAY, Array):
-            if not (0 <= index < len(self)):
+            length_offset = self._nth_offset(0)
+            if length_offset == -1:
+                pass       # just assume the access is within bounds
+            elif not (0 <= index < len(self)):
                 raise IndexError("array index out of bounds")
             item0_offset = self._nth_offset(1)
             item1_offset = self._nth_offset(2)

Modified: pypy/branch/njriley-trans/pypy/translator/c/test/test_boehm.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/test/test_boehm.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/test/test_boehm.py	Fri Mar 10 06:12:02 2006
@@ -2,6 +2,7 @@
 from pypy.translator.translator import TranslationContext
 from pypy.translator.tool.cbuild import skip_missing_compiler, check_boehm_presence
 from pypy.translator.c.genc import CExtModuleBuilder
+from pypy import conftest
 
 def setup_module(mod):
     if not check_boehm_presence():
@@ -32,6 +33,8 @@
         def compile():
             cbuilder = CExtModuleBuilder(t, func, gcpolicy=self.gcpolicy)
             c_source_filename = cbuilder.generate_source()
+            if conftest.option.view:
+                t.view()
             cbuilder.compile()
             mod = cbuilder.isolated_import()
             self._cleanups.append(cbuilder.cleanup) # schedule cleanup after test

Modified: pypy/branch/njriley-trans/pypy/translator/c/test/test_genc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/test/test_genc.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/test/test_genc.py	Fri Mar 10 06:12:02 2006
@@ -4,6 +4,7 @@
 from pypy.translator.translator import TranslationContext
 from pypy.translator.c.database import LowLevelDatabase
 from pypy.translator.c.genc import gen_source
+from pypy.translator.c.gc import NoneGcPolicy
 from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
 from pypy.objspace.flow.model import Block, Link, FunctionGraph
 from pypy.tool.udir import udir
@@ -28,18 +29,19 @@
                            include_dirs = [os.path.dirname(autopath.this_dir)])
     return m
 
-def compile(fn, argtypes, view=False):
+def compile(fn, argtypes, view=False, gcpolicy=None, backendopt=True):
     t = TranslationContext()
     a = t.buildannotator()
     a.build_types(fn, argtypes)
     t.buildrtyper().specialize()
-    if view or conftest.option.view:
-        t.view()
-    backend_optimizations(t)
-    db = LowLevelDatabase(t)
+    if backendopt:
+        backend_optimizations(t)
+    db = LowLevelDatabase(t, gcpolicy=gcpolicy)
     entrypoint = db.get(pyobjectptr(fn))
     db.complete()
     module = compile_db(db)
+    if view or conftest.option.view:
+        t.view()
     compiled_fn = getattr(module, entrypoint)
     def checking_fn(*args, **kwds):
         res = compiled_fn(*args, **kwds)
@@ -296,3 +298,91 @@
 
     f1 = compile(f, [])
     assert f1() == 1
+
+# ____________________________________________________________
+# test for the 'cleanup' attribute of SpaceOperations
+class CleanupState(object):
+    pass
+cleanup_state = CleanupState()
+cleanup_state.current = 1
+def cleanup_g(n):
+    cleanup_state.saved = cleanup_state.current
+    try:
+        return 10 // n
+    except ZeroDivisionError:
+        raise
+def cleanup_h():
+    cleanup_state.current += 1
+def cleanup_f(n):
+    cleanup_g(n)
+    cleanup_h()     # the test hacks the graph to put this h() in the
+                    # cleanup clause of the previous direct_call(g)
+    return cleanup_state.saved * 100 + cleanup_state.current
+
+def test_cleanup_finally():
+    class DummyGCTransformer(NoneGcPolicy.transformerclass):
+        def transform_graph(self, graph):
+            super(DummyGCTransformer, self).transform_graph(graph)
+            if graph is self.translator.graphs[0]:
+                operations = graph.startblock.operations
+                op_call_g = operations[0]
+                op_call_h = operations.pop(1)
+                assert op_call_g.opname == "direct_call"
+                assert op_call_h.opname == "direct_call"
+                assert op_call_g.cleanup == ((), ())
+                assert op_call_h.cleanup == ((), ())
+                cleanup_finally = (op_call_h,)
+                cleanup_except = ()
+                op_call_g.cleanup = cleanup_finally, cleanup_except
+                op_call_h.cleanup = None
+
+    class DummyGcPolicy(NoneGcPolicy):
+        transformerclass = DummyGCTransformer
+
+    f1 = compile(cleanup_f, [int], backendopt=False, gcpolicy=DummyGcPolicy)
+    # state.current == 1
+    res = f1(1)
+    assert res == 102
+    # state.current == 2
+    res = f1(1)
+    assert res == 203
+    # state.current == 3
+    py.test.raises(ZeroDivisionError, f1, 0)
+    # state.current == 4
+    res = f1(1)
+    assert res == 405
+    # state.current == 5
+
+def test_cleanup_except():
+    class DummyGCTransformer(NoneGcPolicy.transformerclass):
+        def transform_graph(self, graph):
+            super(DummyGCTransformer, self).transform_graph(graph)
+            if graph is self.translator.graphs[0]:
+                operations = graph.startblock.operations
+                op_call_g = operations[0]
+                op_call_h = operations.pop(1)
+                assert op_call_g.opname == "direct_call"
+                assert op_call_h.opname == "direct_call"
+                assert op_call_g.cleanup == ((), ())
+                assert op_call_h.cleanup == ((), ())
+                cleanup_finally = ()
+                cleanup_except = (op_call_h,)
+                op_call_g.cleanup = cleanup_finally, cleanup_except
+                op_call_h.cleanup = None
+
+    class DummyGcPolicy(NoneGcPolicy):
+        transformerclass = DummyGCTransformer
+
+    f1 = compile(cleanup_f, [int], backendopt=False, gcpolicy=DummyGcPolicy)
+    # state.current == 1
+    res = f1(1)
+    assert res == 101
+    # state.current == 1
+    res = f1(1)
+    assert res == 101
+    # state.current == 1
+    py.test.raises(ZeroDivisionError, f1, 0)
+    # state.current == 2
+    res = f1(1)
+    assert res == 202
+    # state.current == 2

Modified: pypy/branch/njriley-trans/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/test/test_newgc.py	Fri Mar 10 06:12:02 2006
@@ -193,7 +193,7 @@
 class TestUsingFramework(AbstractTestClass):
     from pypy.translator.c.gc import FrameworkGcPolicy as gcpolicy
 
-    def test_nongcing_gc(self):
+    def test_framework_simple(self):
         def g(x):
             return x + 1
         class A(object):
@@ -201,7 +201,86 @@
         def f():
             a = A()
             a.b = g(1)
+            # this should trigger a couple of collections
+            # XXX make sure it triggers at least one somehow!
+            for i in range(100000):
+                [A()] * 1000
             return a.b
         fn = self.getcompiled(f)
         res = fn()
         assert res == 2
+
+    def test_framework_varsized(self):
+        S = lltype.GcStruct("S", ('x', lltype.Signed))
+        T = lltype.GcStruct("T", ('y', lltype.Signed),
+                                 ('s', lltype.Ptr(S)))
+        ARRAY_Ts = lltype.GcArray(lltype.Ptr(T))
+        
+        def f():
+            r = 0
+            for i in range(30):
+                a = lltype.malloc(ARRAY_Ts, i)
+                for j in range(i):
+                    a[j] = lltype.malloc(T)
+                    a[j].y = i
+                    a[j].s = lltype.malloc(S)
+                    a[j].s.x = 2*i
+                    r += a[j].y + a[j].s.x
+                    a[j].s = lltype.malloc(S)
+                    a[j].s.x = 3*i
+                    r -= a[j].s.x
+                for j in range(i):
+                    r += a[j].y
+            return r
+        fn = self.getcompiled(f)
+        res = fn()
+        assert res == f()
+            
+
+    def test_framework_using_lists(self):
+        class A(object):
+            pass
+        N = 1000
+        def f():
+            static_list = []
+            for i in range(N):
+                a = A()
+                a.x = i
+                static_list.append(a)
+            r = 0
+            for a in static_list:
+                r += a.x
+            return r
+        fn = self.getcompiled(f)
+        res = fn()
+        assert res == N*(N - 1)/2
+    
+    def test_framework_static_roots(self):
+        class A(object):
+            def __init__(self, y):
+                self.y = y
+        a = A(0)
+        a.x = None
+        def f():
+            a.x = A(42)
+            for i in range(1000000):
+                A(i)
+            return a.x.y
+        fn = self.getcompiled(f)
+        res = fn()
+        assert res == 42
+
+    def test_framework_nongc_static_root(self):
+        S = lltype.GcStruct("S", ('x', lltype.Signed))
+        T = lltype.Struct("T", ('p', lltype.Ptr(S)))
+        t = lltype.malloc(T, immortal=True)
+        def f():
+            t.p = lltype.malloc(S)
+            t.p.x = 43
+            for i in range(1000000):
+                s = lltype.malloc(S)
+                s.x = i
+            return t.p.x
+        fn = self.getcompiled(f)
+        res = fn()
+        assert res == 43

Modified: pypy/branch/njriley-trans/pypy/translator/c/test/test_symbolic.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/test/test_symbolic.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/test/test_symbolic.py	Fri Mar 10 06:12:02 2006
@@ -25,6 +25,16 @@
     res = fn()
     assert res == 12
 
+def test_sizeof_array_with_no_length():
+    A = lltype.Array(lltype.Signed, hints={'nolength': True})
+    arraysize = llmemory.sizeof(A, 10)
+    signedsize = llmemory.sizeof(lltype.Signed)
+    def f():
+        return arraysize-signedsize*10
+    fn, t = getcompiled(f, [])
+    res = fn()
+    assert res == 0
+
 def test_itemoffsetof():
     ARRAY = lltype.GcArray(lltype.Signed)
     itemoffsets = [llmemory.itemoffsetof(ARRAY, i) for i in range(5)]

Modified: pypy/branch/njriley-trans/pypy/translator/c/winproj/extension/extension.vcproj
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/winproj/extension/extension.vcproj	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/winproj/extension/extension.vcproj	Fri Mar 10 06:12:02 2006
@@ -33,6 +33,7 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
+				AdditionalDependencies="\python24\libs\python24_d.lib"
 				OutputFile="$(OutDir)/testing_1.pyd"
 				LinkIncremental="2"
 				GenerateDebugInformation="TRUE"
@@ -64,13 +65,14 @@
 			Name="Release|Win32"
 			OutputDirectory="Release"
 			IntermediateDirectory="Release"
-			ConfigurationType="1"
+			ConfigurationType="2"
 			CharacterSet="2">
 			<Tool
 				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="\pypy\dist\pypy\translator\c;\Python24\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
-				RuntimeLibrary="4"
-				UsePrecompiledHeader="3"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
 				WarningLevel="3"
 				Detect64BitPortabilityProblems="TRUE"
 				DebugInformationFormat="3"/>
@@ -78,7 +80,8 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/extension.exe"
+				AdditionalDependencies="\python24\libs\python24.lib"
+				OutputFile="$(OutDir)/testing_1.pyd"
 				LinkIncremental="1"
 				GenerateDebugInformation="TRUE"
 				SubSystem="1"
@@ -110,38 +113,105 @@
 	<References>
 	</References>
 	<Files>
+		<Filter
+			Name="permanent"
+			Filter="">
+			<File
+				RelativePath="..\..\src\address.h">
+			</File>
+			<File
+				RelativePath="..\..\src\addrinfo.h">
+			</File>
+			<File
+				RelativePath="..\..\src\char.h">
+			</File>
+			<File
+				RelativePath="..\..\src\debuginfo.h">
+			</File>
+			<File
+				RelativePath="..\..\src\exception.h">
+			</File>
+			<File
+				RelativePath="..\..\src\float.h">
+			</File>
+			<File
+				RelativePath="..\..\src\g_include.h">
+			</File>
+			<File
+				RelativePath="..\..\src\g_prerequisite.h">
+			</File>
+			<File
+				RelativePath="..\..\src\int.h">
+			</File>
+			<File
+				RelativePath="..\..\src\ll__socket.h">
+			</File>
+			<File
+				RelativePath="..\..\src\ll_math.h">
+			</File>
+			<File
+				RelativePath="..\..\src\ll_os.h">
+			</File>
+			<File
+				RelativePath="..\..\src\ll_osdefs.h">
+			</File>
+			<File
+				RelativePath="..\..\src\ll_stackless.h">
+			</File>
+			<File
+				RelativePath="..\..\src\ll_strtod.h">
+			</File>
+			<File
+				RelativePath="..\..\src\ll_thread.h">
+			</File>
+			<File
+				RelativePath="..\..\src\ll_time.h">
+			</File>
+			<File
+				RelativePath="..\..\src\main.h">
+			</File>
+			<File
+				RelativePath="..\..\src\mem.h">
+			</File>
+			<File
+				RelativePath="..\..\src\module.h">
+			</File>
+			<File
+				RelativePath="..\..\src\pyobj.h">
+			</File>
+			<File
+				RelativePath="..\..\src\rtyper.h">
+			</File>
+			<File
+				RelativePath="..\..\src\stack.h">
+			</File>
+			<File
+				RelativePath="..\..\src\standalone.h">
+			</File>
+			<File
+				RelativePath="..\..\src\support.h">
+			</File>
+			<File
+				RelativePath="..\..\src\thread.h">
+			</File>
+			<File
+				RelativePath="..\..\src\thread_nt.h">
+			</File>
+			<File
+				RelativePath="..\..\src\thread_pthread.h">
+			</File>
+			<File
+				RelativePath="..\..\src\trace.h">
+			</File>
+			<File
+				RelativePath="..\..\src\unichar.h">
+			</File>
+		</Filter>
 		<File
-			RelativePath="F:\tmp\usession-44\testing_1\common_header.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-44\testing_1\forwarddecl.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-44\testing_1\implement.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-44\testing_1\nonfuncnodes.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-44\testing_1\slp_defs.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-44\testing_1\slp_impl.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-44\testing_1\slp_signatures.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-44\testing_1\slp_state_decoding.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-44\testing_1\structdef.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-44\testing_1\structimpl.c">
+			RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-257\testing_1\common_header.h">
 		</File>
 		<File
-			RelativePath="F:\tmp\usession-44\testing_1\testing_1.c">
+			RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-257\testing_1\testing_1.c">
 		</File>
 	</Files>
 	<Globals>

Modified: pypy/branch/njriley-trans/pypy/translator/c/winproj/standalone/standalone.vcproj
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/c/winproj/standalone/standalone.vcproj	(original)
+++ pypy/branch/njriley-trans/pypy/translator/c/winproj/standalone/standalone.vcproj	Fri Mar 10 06:12:02 2006
@@ -208,181 +208,7 @@
 			</File>
 		</Filter>
 		<File
-			RelativePath="F:\tmp\usession-436\testing_1\common_header.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\forwarddecl.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_1.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_10.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_11.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_12.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_13.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_14.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_15.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_16.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_17.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_18.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_19.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_2.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_3.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_4.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_5.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_6.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_7.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_8.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\implement_9.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_1.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_10.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_11.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_12.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_13.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_14.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_15.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_16.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_17.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_18.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_19.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_2.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_20.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_21.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_22.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_23.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_24.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_25.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_26.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_27.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_28.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_29.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_3.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_4.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_5.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_6.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_7.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_8.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\nonfuncnodes_9.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\slp_defs.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\slp_impl.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\slp_signatures.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\slp_state_decoding.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\structdef.h">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\structimpl.c">
-		</File>
-		<File
-			RelativePath="F:\tmp\usession-436\testing_1\testing_1.c">
+			RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-257\testing_1\testing_1.c">
 		</File>
 	</Files>
 	<Globals>

Modified: pypy/branch/njriley-trans/pypy/translator/driver.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/driver.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/driver.py	Fri Mar 10 06:12:02 2006
@@ -188,6 +188,15 @@
     #
     task_rtype = taskdef(task_rtype, ['annotate'], "RTyping")
 
+    def task_ootype(self):
+        # Maybe type_system should simply be an option used in task_rtype
+        opt = self.options
+        rtyper = self.translator.buildrtyper(type_system="ootype")
+        rtyper.specialize(dont_simplify_again=True,
+                          crash_on_first_typeerror=not opt.insist)
+    #
+    task_ootype = taskdef(task_ootype, ['annotate'], "ootyping")
+
     def task_backendopt(self):
         from pypy.translator.backendopt.all import backend_optimizations
         opt = self.options
@@ -211,6 +220,9 @@
         if opt.gc == 'none':
             from pypy.translator.c import gc
             gcpolicy = gc.NoneGcPolicy
+        if opt.gc == 'framework':
+            from pypy.translator.c import gc
+            gcpolicy = gc.FrameworkGcPolicy
 
         if standalone:
             from pypy.translator.c.genc import CStandaloneBuilder as CBuilder

Modified: pypy/branch/njriley-trans/pypy/translator/geninterplevel.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/geninterplevel.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/geninterplevel.py	Fri Mar 10 06:12:02 2006
@@ -203,7 +203,7 @@
         self.builtin_ids = dict( [
             (id(value), bltinstub(key))
             for key, value in __builtin__.__dict__.items()
-            if callable(value) and type(value) not in [type(Exception), type] ] )
+            if callable(value) and type(value) not in [types.ClassType, type] ] )
         
         self.space = FlowObjSpace() # for introspection
 
@@ -748,7 +748,7 @@
                 return 'space.w_%s' % cls.__name__
 
         if not isinstance(cls, type):
-            assert type(cls) is type(Exception)
+            assert type(cls) is types.ClassType
             # do *not* change metaclass, but leave the
             # decision to what PyPy thinks is correct.
             # metaclass = 'space.w_classobj'
@@ -824,7 +824,7 @@
         str:    'space.w_str',
         float:  'space.w_float',
         slice:  'space.w_slice',
-        type(Exception()): (eval_helper, 'InstanceType', 'types.InstanceType'),
+        types.InstanceType: (eval_helper, 'InstanceType', 'types.InstanceType'),
         type:   'space.w_type',
         complex: (eval_helper, 'complex', 'types.ComplexType'),
         unicode:'space.w_unicode',

Modified: pypy/branch/njriley-trans/pypy/translator/gensupp.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/gensupp.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/gensupp.py	Fri Mar 10 06:12:02 2006
@@ -85,11 +85,12 @@
 # while always keeping all globals visible.
 
 class NameManager(object):
-    def __init__(self, global_prefix=''):
+    def __init__(self, global_prefix='', number_sep='_'):
         self.seennames = {}
         self.scope = 0
         self.scopelist = []
         self.global_prefix = global_prefix
+        self.number_sep = number_sep
 
     def make_reserved_names(self, txt):
         """add names to list of known names. If one exists already,
@@ -113,7 +114,7 @@
         self.seennames[basename] = n+1
         if with_number is None:
             with_number = basename in ('v', 'w_')
-        fmt = '%s_%d'
+        fmt = '%%s%s%%d' % self.number_sep
         if with_number and not basename[-1].isdigit():
             fmt = '%s%d'
         if n != 0 or with_number:

Modified: pypy/branch/njriley-trans/pypy/translator/goal/translate.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/goal/translate.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/goal/translate.py	Fri Mar 10 06:12:02 2006
@@ -48,7 +48,7 @@
 
     '1_backend': [OPT(('-b', '--backend'), "Backend", ['c', 'llvm'])],
 
-    '2_gc': [OPT(('--gc',), "Garbage collector", ['boehm', 'ref', 'none'])],
+    '2_gc': [OPT(('--gc',), "Garbage collector", ['boehm', 'ref', 'framework', 'none'])],
     '3_stackless': [OPT(('--stackless',), "Stackless code generation", True)],
     '4_tsc': [OPT(('--tsc',), "(x86, PowerPC, Alpha) Timestamp counter profile", True)],
     '5_merge_if_blocks': [OPT(('--no-if-blocks-merge',), "Do not merge if ... elif ... chains and use a switch statement for them.", False)],

Modified: pypy/branch/njriley-trans/pypy/translator/interactive.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/interactive.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/interactive.py	Fri Mar 10 06:12:02 2006
@@ -48,6 +48,7 @@
     GOAL_USES_OPTS = {
         'annotate': ['debug'],
         'rtype': ['insist'],
+        'ootype': [],
         'backendopt': ['merge_if_blocks'],
         'database_c': ['gc', 'stackless'],
         'source_llvm': ['gc', 'stackless'],
@@ -81,9 +82,9 @@
         else:
             # check consistency
             if argtypes is not None and argtypes != self.ann_argtypes:
-                raise Exception("incosistent argtype supplied")
+                raise Exception("inconsistent argtype supplied")
             if policy is not None and policy != self.ann_policy:
-                raise Exception("incosistent annotation polish supplied")
+                raise Exception("inconsistent annotation polish supplied")
 
     def update_options(self, argtypes, kwds):
         if argtypes or kwds.get('policy'):
@@ -91,7 +92,7 @@
         for optname, value in kwds.iteritems():
             if optname in self.frozen_options:
                 if getattr(self.driver.options, optname) != value:
-                     raise Exception("incosistent option supplied: %s" % optname)
+                     raise Exception("inconsistent option supplied: %s" % optname)
             else:
                 setattr(self.driver.options, optname, value)
                 self.frozen_options[optname] = True
@@ -120,6 +121,10 @@
         self.update_options(argtypes, kwds)
         return self.driver.rtype()
 
+    def ootype(self, argtypes=None, **kwds):
+        self.update_options(argtypes, kwds)
+        return self.driver.ootype()
+
     # backend depedent
 
     def backendopt(self, argtypes=None, **kwds):

Modified: pypy/branch/njriley-trans/pypy/translator/llvm/codewriter.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/llvm/codewriter.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/llvm/codewriter.py	Fri Mar 10 06:12:02 2006
@@ -135,7 +135,16 @@
                      "%(fromvar)s to %(targettype)s" % locals())
 
     def getelementptr(self, targetvar, type, typevar, indices, getptr=True):
-        # XXX comment getptr
+        # getelementptr gives you back a value for the last thing indexed
+
+        # what is getptr?
+        # ---------------
+        # All global variables in LLVM are pointers, and pointers must also be
+        # dereferenced with the getelementptr instruction (hence the int 0)
+
+        # not only that, but if we need to look into something (ie a struct)
+        # then we must get the initial pointer to ourself
+
         if getptr:
             indices = [(self.word_repr, 0)] + list(indices)
         res = "%(targetvar)s = getelementptr %(type)s %(typevar)s, " % locals()

Modified: pypy/branch/njriley-trans/pypy/translator/llvm/database.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/llvm/database.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/llvm/database.py	Fri Mar 10 06:12:02 2006
@@ -5,7 +5,7 @@
 from pypy.translator.llvm.funcnode import FuncNode, FuncTypeNode
 from pypy.translator.llvm.extfuncnode import ExternalFuncNode
 from pypy.translator.llvm.structnode import StructNode, StructVarsizeNode, \
-     StructTypeNode, StructVarsizeTypeNode
+     StructTypeNode, StructVarsizeTypeNode, getindexhelper
 from pypy.translator.llvm.arraynode import ArrayNode, StrArrayNode, \
      VoidArrayNode, ArrayTypeNode, VoidArrayTypeNode
 from pypy.translator.llvm.opaquenode import OpaqueNode, ExtOpaqueNode, \
@@ -366,10 +366,39 @@
             # XXXXX things are happening in the gc world...
             # assert value == NULL
             repr = 'null' 
+        elif isinstance(value, llmemory.AddressOffset):
+            return self.offset_str(value)
         else:
             repr = str(value)
         return repr
 
+    def offset_str(self, value):
+
+        #XXX Need to understand and doc this better
+        
+        if isinstance(value, llmemory.FieldOffset):
+            pos = getindexhelper(value.fldname, value.TYPE)
+            return "cast(%s* getelementptr(%s* null, int 0, uint %s) to int)" % (
+                self.repr_type(getattr(value.TYPE, value.fldname)),
+                self.repr_type(value.TYPE),
+                pos)
+
+        elif isinstance(value, llmemory.ItemOffset):
+            return "cast(%s* getelementptr(%s* null, int %s) to int)" % (
+                self.repr_type(value.TYPE), self.repr_type(value.TYPE), value.repeat)
+
+        elif isinstance(value, llmemory.ArrayItemsOffset):
+            return "cast(%s* getelementptr(%s* null, int 0, uint 1) to int)" % (
+                self.repr_type(value.TYPE.OF), self.repr_type(value.TYPE))
+
+        elif isinstance(value, llmemory.CompositeOffset):
+            return "cast(%s* getelementptr(%s* null, int 0, uint 1, int %s) to int)" % (
+                self.repr_type(value.second.TYPE),
+                self.repr_type(value.first.TYPE),
+                value.second.repeat)
+        else:
+            raise Exception("unsupported offset")
+        
     def get_machine_word(self):
         return self.primitives[lltype.Signed]
 

Modified: pypy/branch/njriley-trans/pypy/translator/llvm/demo/bpnn.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/llvm/demo/bpnn.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/llvm/demo/bpnn.py	Fri Mar 10 06:12:02 2006
@@ -221,8 +221,6 @@
     return 0
 
 #_________________________________________________________
-
-from pypy.translator.llvm.genllvm import compile_function
     
 if __name__ == "__main__":
     from pypy.translator.llvm.demo.run import run

Modified: pypy/branch/njriley-trans/pypy/translator/llvm/demo/run.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/llvm/demo/run.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/llvm/demo/run.py	Fri Mar 10 06:12:02 2006
@@ -25,8 +25,9 @@
     backend_optimizations(t)
     cbuilder = CStandaloneBuilder(t, entry_point, gcpolicy=BoehmGcPolicy)
     cbuilder.generate_source()
-    cbuilder.compile()
-    os.system("XXX")
+    exe_path = cbuilder.compile()
+    print exe_path
+    os.system(exe_path)
     
 def l(name):
     s_list_of_strings = SomeList(ListDef(None, SomeString()))

Modified: pypy/branch/njriley-trans/pypy/translator/llvm/externs2ll.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/llvm/externs2ll.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/llvm/externs2ll.py	Fri Mar 10 06:12:02 2006
@@ -104,7 +104,7 @@
 
 def setup_externs(db):
     rtyper = db.translator.rtyper
-    from pypy.translator.c.extfunc import predeclare_all
+    from pypy.translator.llvm.extfunchelper import predeclare_all
 
     # hacks to make predeclare_all work
     # XXX Rationalise this

Modified: pypy/branch/njriley-trans/pypy/translator/llvm/genllvm.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/llvm/genllvm.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/llvm/genllvm.py	Fri Mar 10 06:12:02 2006
@@ -1,6 +1,8 @@
 import time
 
-from pypy.translator.llvm import build_llvm_module
+from pypy.tool import isolate
+
+from pypy.translator.llvm import buildllvm
 from pypy.translator.llvm.database import Database 
 from pypy.translator.llvm.pyxwrapper import write_pyx_wrapper 
 from pypy.rpython.rmodel import inputconst
@@ -17,6 +19,7 @@
 from pypy.translator.llvm.exception import ExceptionPolicy
 from pypy.translator.llvm.log import log
 from pypy import conftest
+from pypy.translator.llvm.buildllvm import llvm_is_on_path
 
 class GenLLVM(object):
 
@@ -237,9 +240,9 @@
         if exe_name is not None:
             assert self.standalone
             assert not return_fn
-            return build_llvm_module.make_module_from_llvm(self, self.filename,
-                                                           optimize=optimize,
-                                                           exe_name=exe_name)
+            return buildllvm.make_module_from_llvm(self, self.filename,
+                                                   optimize=optimize,
+                                                   exe_name=exe_name)
         else:
             assert not self.standalone
 
@@ -248,15 +251,20 @@
             basename = self.filename.purebasename + '_wrapper' + postfix + '.pyx'
             pyxfile = self.filename.new(basename = basename)
             write_pyx_wrapper(self, pyxfile)    
-            res = build_llvm_module.make_module_from_llvm(self, self.filename,
-                                                          pyxfile=pyxfile,
-                                                          optimize=optimize)
-            wrap_fun = getattr(res, 'pypy_' + self.entry_func_name + "_wrapper")
+            info = buildllvm.make_module_from_llvm(self, self.filename,
+                                                   pyxfile=pyxfile,
+                                                   optimize=optimize)
+
+            mod, wrap_fun = self.isolate_module(*info)
             if return_fn:
                 return wrap_fun
+            return mod, wrap_fun
 
-            return res, wrap_fun
-        
+    def isolate_module(self, modname, dirpath):
+        ext_module = isolate.Isolate((dirpath, modname))
+        wrap_fun = getattr(ext_module, 'pypy_' + self.entry_func_name + "_wrapper")
+        return ext_module, wrap_fun
+    
     def _checkpoint(self, msg=None):
         if not self.logging:
             return
@@ -298,6 +306,8 @@
     return gen.compile_llvm_source(**kwds)
 
 def genllvm_compile(function, annotation, view=False, optimize=True, **kwds):
+    assert llvm_is_on_path()
+    
     from pypy.translator.translator import TranslationContext
     from pypy.translator.backendopt.all import backend_optimizations
     t = TranslationContext()
@@ -316,7 +326,3 @@
     if view or conftest.option.view:
         t.view()
     return genllvm(t, function, optimize=optimize, **kwds)
-
-def compile_function(function, annotation, **kwds):
-    """ Helper - which get the compiled module from CPython. """
-    return compile_module(function, annotation, return_fn=True, **kwds)

Modified: pypy/branch/njriley-trans/pypy/translator/llvm/opwriter.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/llvm/opwriter.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/llvm/opwriter.py	Fri Mar 10 06:12:02 2006
@@ -1,6 +1,8 @@
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.lltypesystem import lltype
 from pypy.translator.llvm.log import log 
+from pypy.translator.llvm.structnode import getindexhelper
+
 log = log.opwriter
 
 class OpRepr(object):
@@ -313,21 +315,11 @@
         else:
             raise NotImplementedError
 
-    def _getindexhelper(self, name, struct):
-        assert name in list(struct._names)
-
-        fieldnames = struct._names_without_voids()
-        try:
-            index = fieldnames.index(name)
-        except ValueError:
-            index = -1
-        return index
-
     def getfield(self, opr):
         op = opr.op
         if opr.rettype != "void":
-            index = self._getindexhelper(op.args[1].value,
-                                         op.args[0].concretetype.TO)
+            index = getindexhelper(op.args[1].value,
+                                   op.args[0].concretetype.TO)
             assert index != -1
             tmpvar = self._tmp()
             self.codewriter.getelementptr(tmpvar, opr.argtypes[0],
@@ -337,8 +329,8 @@
             self._skipped(opr)
  
     def getsubstruct(self, opr): 
-        index = self._getindexhelper(opr.op.args[1].value,
-                                     opr.op.args[0].concretetype.TO)
+        index = getindexhelper(opr.op.args[1].value,
+                               opr.op.args[0].concretetype.TO)
         assert opr.rettype != "void"
         self.codewriter.getelementptr(opr.retref, opr.argtypes[0], 
                                       opr.argrefs[0], [("uint", index)])        
@@ -347,8 +339,8 @@
         op = opr.op
         if opr.argtypes[2] != "void":
             tmpvar = self._tmp()
-            index = self._getindexhelper(op.args[1].value,
-                                         op.args[0].concretetype.TO)
+            index = getindexhelper(op.args[1].value,
+                                   op.args[0].concretetype.TO)
             self.codewriter.getelementptr(tmpvar, opr.argtypes[0],
                                           opr.argrefs[0], [("uint", index)])
             self.codewriter.store(opr.argtypes[2], opr.argrefs[2], tmpvar)

Modified: pypy/branch/njriley-trans/pypy/translator/llvm/structnode.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/llvm/structnode.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/llvm/structnode.py	Fri Mar 10 06:12:02 2006
@@ -2,6 +2,16 @@
 from pypy.translator.llvm.node import LLVMNode, ConstantLLVMNode
 from pypy.rpython.lltypesystem import lltype
 
+def getindexhelper(name, struct):
+    assert name in list(struct._names)
+
+    fieldnames = struct._names_without_voids()
+    try:
+        index = fieldnames.index(name)
+    except ValueError:
+        index = -1
+    return index
+
 log = log.structnode 
 
 class StructTypeNode(LLVMNode):

Modified: pypy/branch/njriley-trans/pypy/translator/llvm/test/runtest.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/llvm/test/runtest.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/llvm/test/runtest.py	Fri Mar 10 06:12:02 2006
@@ -1,24 +1,9 @@
 import py
 from pypy.translator.llvm.genllvm import genllvm_compile
-
+from pypy.translator.llvm.buildllvm import llvm_is_on_path, llvm_version
 optimize_tests = False
 MINIMUM_LLVM_VERSION = 1.6
 
-def llvm_is_on_path():
-    try:
-        py.path.local.sysfind("llvm-as")
-        py.path.local.sysfind("llvm-gcc")
-    except py.error.ENOENT: 
-        return False 
-    return True
-
-def llvm_version():
-    import os
-    v = os.popen('llvm-as -version 2>&1').readline()
-    v = ''.join([c for c in v if c.isdigit()])
-    v = int(v) / 10.0
-    return v
-
 def llvm_test():
     if not llvm_is_on_path():
         py.test.skip("llvm not found")

Modified: pypy/branch/njriley-trans/pypy/translator/squeak/gensqueak.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/squeak/gensqueak.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/squeak/gensqueak.py	Fri Mar 10 06:12:02 2006
@@ -1,254 +1,71 @@
-import sys
+import datetime, sys
 from pypy.objspace.flow.model import traverse
 from pypy.objspace.flow import FlowObjSpace
 from pypy.objspace.flow.model import Constant, Variable, Block
 from pypy.objspace.flow.model import last_exception, checkgraph
+from pypy.translator.gensupp import NameManager
 from pypy.translator.unsimplify import remove_direct_loops
 from pypy.translator.simplify import simplify_graph
+from pypy.rpython.ootypesystem.ootype import Instance, ROOT
 from pypy import conftest
+try:
+    set
+except NameError:
+    from sets import Set as set
 
-selectormap = {
-    'setitem:with:': 'at:put:',
-    'getitem:':      'at:',
-    'new':           'new',
-    'runtimenew':    'new',
-    'classof':       'class',
-    'sameAs':        'yourself',
-    'intAdd:':       '+',
-}
-
-def camel_case(str):
-    words = str.split('_')
-    for i in range(1, len(words)):
-        words[i] = words[i].capitalize()
-    return ''.join(words)
-
-def arg_names(graph):
-    #XXX need to handle more args, see 
-    #    http://docs.python.org/ref/types.html#l2h-139
-    names, vararg, kwarg = graph.signature
-    assert vararg is None
-    assert kwarg is None
-    return names
-
-def selector(name, args):
-    s = name
-    if args:
-        s += '_'
-        for arg in args:
-            s += arg + ':'
-    return camel_case(s)
-
-def signature(sel, args):
-    if (':' in sel):
-        parts = []
-        names = sel.split(':')
-#       assert len(names) == len(args)
-        while args:
-            parts.append(names.pop(0) + ': ' + args.pop(0))
-        return ' '.join(parts)
-    elif not sel[0].isalnum():
-#       assert len(args) == 1
-        return "%s %s" %(sel, args[0])
-    else:
-#       assert len(args) == 0
-        return sel
-
-
-class LoopFinder:
-    def __init__(self, startblock):
-        self.loops = {}
-        self.parents = {startblock: startblock}
-        self.temps = {}
-        self.seen = []
-        self.visit_Block(startblock)
-    def visit_Block(self, block, switches=[]):
-        #self.temps.has_key()
-        self.seen.append(block)
-        if block.exitswitch:
-            switches.append(block)
-            self.parents[block] = block
-        for link in block.exits:
-            self.visit_Link(link, switches) 
-    def visit_Link(self, link, switches):
-        if link.target in switches:
-            self.loops[link.target] = True
-        if not link.target in self.seen:
-            self.parents[link.target] = self.parents[link.prevblock]
-            self.visit_Block(link.target, switches)
 
 class GenSqueak:
 
+    sqnames = {
+        Constant(None).key:  'nil',
+        Constant(False).key: 'false',
+        Constant(True).key:  'true',
+    }
+    
     def __init__(self, sqdir, translator, modname=None):
         self.sqdir = sqdir
         self.translator = translator
         self.modname = (modname or
                         translator.graphs[0].name)
-        self.sqnames = {
-            Constant(None).key:  'nil',
-            Constant(False).key: 'false',
-            Constant(True).key:  'true',
-        }
-        self.seennames = {}
-        self.pendinggraphs = []
-        self.pendingclasses = []
-        self.pendingmethods = []
-        self.classes = [] 
-        self.methods = [] 
-
-        t = self.translator
-        graph = t.graphs[0]
-        simplify_graph(graph)
-        remove_direct_loops(t, graph)
-        checkgraph(graph)
+
+        self.name_manager = NameManager(number_sep="")
+        self.unique_name_mapping = {}
+        self.pending_nodes = []
+        self.generated_nodes = set()
 
         if conftest.option.view:
             self.translator.view()
 
-        self.nameof(graph) #add to pending
-        file = self.sqdir.join('%s.st' % graph.name).open('w')
+        graph = self.translator.graphs[0]
+        self.pending_nodes.append(FunctionNode(self, graph))
+        self.filename = '%s.st' % graph.name
+        file = self.sqdir.join(self.filename).open('w')
         self.gen_source(file)
         file.close()
 
-
     def gen_source(self, file):
-        while self.pendinggraphs or self.pendingclasses or self.pendingmethods:
-            while self.pendinggraphs:
-                graph = self.pendinggraphs.pop()
-                self.gen_sqfunction(graph, file)
-            while self.pendingclasses:
-                inst = self.pendingclasses.pop()
-                self.gen_sqclass(inst, file)
-            while self.pendingmethods:
-                (inst, meth) = self.pendingmethods.pop()
-                self.gen_sqmethod(inst, meth, file)
-
-    def gen_sqclass(self, inst, f):
-        self.classes.append(inst)
-        print >> f, """%s subclass: #%s
-        instanceVariableNames: '%s'
-        classVariableNames: ''
-        poolDictionaries: ''
-        category: 'PyPy-Test'!
-        """ % (
-            self.nameof_Instance(inst._superclass), 
-            self.nameof_Instance(inst),
-            ' '.join(inst._fields.iterkeys()))
-
-    def gen_sqmethod(self, inst, meth, f):
-        if (inst, meth) in self.methods:
-            return
-        self.methods.append((inst, meth))
-        print >> f, "!%s methodsFor: 'methods' stamp: 'pypy 1/1/2000 00:00'!" % (
-            self.nameof_Instance(inst))
-        print >> f, "%s" % meth
-        print >> f, '   "XXX methods not generated yet"'
-        print >> f, "! !"
-        print >> f
-
-
-    def gen_sqfunction(self, graph, f):
-
-        def expr(v):
-            if isinstance(v, Variable):
-                return camel_case(v.name)
-            elif isinstance(v, Constant):
-                return self.nameof(v.value)
-            else:
-                raise TypeError, "expr(%r)" % (v,)
-
-        def oper(op):
-            args = [expr(arg) for arg in op.args]
-            if op.opname == "oosend":
-                name = op.args[0].value
-                receiver = args[1]
-                args = args[2:]
-                self.note_meth(op.args[1].concretetype, name)
-            elif op.opname == "oogetfield":
-                receiver = args[0]
-                name = op.args[1].value
-                args = args[2:]
-            elif op.opname == "oosetfield":
-                receiver = args[0]
-                name = op.args[1].value
-                args = args[2:]
-            else:
-                name = op.opname
-                receiver = args[0]
-                args = args[1:]
-            argnames = ['with'] * len(args)
-            if argnames:
-                argnames[0] = ''
-            sel = selector(name, argnames)
-            if op.opname != "oosend":
-                sel = selectormap.get(sel, sel)
-            return "%s := %s %s." % (expr(op.result), receiver, signature(sel, args))
-
-        def render_return(args):
-            if len(args) == 2:
-                # exception
-                exc_cls = expr(args[0])
-                exc_val = expr(args[1])
-                yield "(PyOperationError class: %s value: %s) signal." % (exc_cls, exc_val)
-            else:
-                # regular return block
-                retval = expr(args[0])
-                yield "^%s" % retval
-
-        def render_link(link):
-            block = link.target
-            if link.args:
-                for i in range(len(link.args)):
-                    yield '%s := %s.' % (expr(block.inputargs[i]), expr(link.args[i]))
-            for line in render_block(block):
-                yield line
-
-        def render_block(block):
-            if loops.has_key(block):
-                if not loops[block]:
-                    yield '"skip1"'
-                    return
-                yield "["
-            for op in block.operations:
-                yield "%s" % oper(op)
-            if len(block.exits) == 0:
-                for line in render_return(block.inputargs):
-                    yield line
+        while self.pending_nodes:
+            node = self.pending_nodes.pop()
+            self.gen_node(node, file)
+
+    def gen_node(self, node, f):
+        for dep in node.dependencies():
+            if dep not in self.generated_nodes:
+                self.pending_nodes.append(node)
+                self.schedule_node(dep)
                 return
-            elif block.exitswitch is None:
-                # single-exit block
-                assert len(block.exits) == 1
-                for line in render_link(block.exits[0]):
-                    yield line
-            else:
-                #exitswitch
-                if loops.has_key(block):
-                    if loops[block]:
-                        loops[block] = False
-                        yield "%s] whileTrue: [" % expr(block.exitswitch)
-                        for line in render_link(block.exits[True]):
-                            yield "    %s" % line
-                        yield "]."
-                        for line in render_link(block.exits[False]):
-                            yield "%s" % line
-                else:
-                    yield "%s ifTrue: [" % expr(block.exitswitch)
-                    for line in render_link(block.exits[True]):
-                        yield "    %s" % line
-                    yield "] ifFalse: [" 
-                    for line in render_link(block.exits[False]):
-                        yield "    %s" % line
-                    yield "]"
-
-        start = graph.startblock
-        args = [expr(arg) for arg in start.inputargs]
-        print >> f, '%s' % signature(self.nameof(graph), args)
-    
-        loops = LoopFinder(start).loops
-
-        for line in render_block(start):
-            print >> f, '       %s' % line
-        print >> f
+        self.generated_nodes.add(node)
+        for line in node.render():
+            print >> f, line
+        print >> f, ""
+
+    def schedule_node(self, node):
+        if node not in self.generated_nodes:
+            if node in self.pending_nodes:
+                # We move the node to the front so we can enforce
+                # the generation of dependencies.
+                self.pending_nodes.remove(node)
+            self.pending_nodes.append(node)
 
     def nameof(self, obj):
         key = Constant(obj).key
@@ -274,64 +91,344 @@
     def nameof_str(self, s):
         return "'s'"
 
-    def nameof_FunctionGraph(self, graph):
-        #XXX this should actually be a StaticMeth
-        name = self.unique_name(graph.name.split('.')[-1])
-        args = arg_names(graph)
-        sel = selector(name, args)
-        self.pendinggraphs.append(graph)
-        return sel
-
-    #def nameof_function(self, func):
-    #    #XXX this should actually be a StaticMeth
-    #    printable_name = '(%s:%d) %s' % (
-    #        func.func_globals.get('__name__', '?'),
-    #        func.func_code.co_firstlineno,
-    #        func.__name__)
-    #    if self.translator.frozen:
-    #        if func not in self.translator.flowgraphs:
-    #            print "NOT GENERATING", printable_name
-    #            return self.skipped_function(func)
-    #    else:
-    #        if (func.func_doc and
-    #            func.func_doc.lstrip().startswith('NOT_RPYTHON')):
-    #            print "skipped", printable_name
-    #            return self.skipped_function(func)
-    #    name = self.unique_name(func.__name__)
-    #    args = arg_names(func)
-    #    sel = selector(name, args)
-    #    self.pendingfunctions.append(func)
-    #    return sel
-
-    def nameof_Instance(self, inst):
-        if inst is None:
-            #empty superclass
+    def nameof_Instance(self, INSTANCE):
+        if INSTANCE is None:
             return "Object"
-        self.note_Instance(inst)
-        return "Py%s" % inst._name.capitalize()
+        self.schedule_node(ClassNode(self, INSTANCE))
+        class_name = INSTANCE._name.split(".")[-1]
+        squeak_class_name = self.unique_name(INSTANCE, class_name)
+        return "Py%s" % squeak_class_name
+
+    def nameof__instance(self, inst):
+        return self.nameof_Instance(inst._TYPE)
+
+    def nameof__callable(self, callable):
+        return self.nameof_function(callable.graph.func)
+
+    def nameof_function(self, function):
+        squeak_func_name = self.unique_name(function, function.__name__)
+        return squeak_func_name
+        
+    def unique_name(self, key, basename):
+        if self.unique_name_mapping.has_key(key):
+            unique = self.unique_name_mapping[key]
+        else:
+            camel_basename = camel_case(basename)
+            unique = self.name_manager.uniquename(camel_basename)
+            self.unique_name_mapping[key] = unique
+        return unique
+
+
+def camel_case(identifier):
+    identifier = identifier.replace(".", "_")
+    words = identifier.split('_')
+    return ''.join([words[0]] + [w.capitalize() for w in words[1:]])
+
+class Selector:
+
+    def __init__(self, function_name, arg_count):
+        self.parts = [camel_case(function_name)]
+        self.arg_count = arg_count
+        self.infix = False
+        if not self.parts[0].isalnum():
+            # Binary infix selector, e.g. "+"
+            assert arg_count == 1
+            self.infix = True
+        if arg_count > 1:
+            self.parts += ["with"] * (arg_count - 1)
+
+    def __str__(self):
+        if self.arg_count == 0 or self.infix:
+            return self.parts[0]
+        else:
+            return "%s:%s" % (self.parts[0],
+                    "".join([p + ":" for p in self.parts[1:]]))
+
+    def symbol(self):
+        return str(self)
+
+    def signature(self, arg_names):
+        assert len(arg_names) == self.arg_count
+        if self.arg_count == 0:
+            return self.parts[0]
+        elif self.infix:
+            return "%s %s" % (self.parts[0], arg_names[0])
+        else:
+            return " ".join(["%s: %s" % (p, a)
+                    for (p, a) in zip(self.parts, arg_names)])
+
+
+class CodeNode:
+
+    def __hash__(self):
+        return hash(self.hash_key)
+    
+    def __eq__(self, other):
+        return isinstance(other, CodeNode) \
+                and self.hash_key == other.hash_key
+    
+    # XXX need other comparison methods?
+
+    def render_fileout_header(self, class_name, category):
+        return "!%s methodsFor: '%s' stamp: 'pypy %s'!" % (
+                class_name, category,
+                datetime.datetime.now().strftime("%m/%d/%Y %H:%M"))
+
+class ClassNode(CodeNode):
+
+    def __init__(self, gen, INSTANCE):
+        self.gen = gen
+        self.INSTANCE = INSTANCE
+        self.hash_key = INSTANCE
+
+    def dependencies(self):
+        if self.INSTANCE._superclass is not None: # not root
+            return [ClassNode(self.gen, self.INSTANCE._superclass)]
+        else:
+            return []
+
+    def render(self):
+        yield "%s subclass: #%s" % (
+            self.gen.nameof_Instance(self.INSTANCE._superclass), 
+            self.gen.nameof_Instance(self.INSTANCE))
+        yield "    instanceVariableNames: '%s'" % \
+            ' '.join(self.INSTANCE._fields.iterkeys())
+        yield "    classVariableNames: ''"
+        yield "    poolDictionaries: ''"
+        yield "    category: 'PyPy-Test'!"
+
+class LoopFinder:
+
+    def __init__(self, startblock):
+        self.loops = {}
+        self.parents = {startblock: startblock}
+        self.temps = {}
+        self.seen = []
+        self.visit_Block(startblock)
+   
+    def visit_Block(self, block, switches=[]):
+        #self.temps.has_key()
+        self.seen.append(block)
+        if block.exitswitch:
+            switches.append(block)
+            self.parents[block] = block
+        for link in block.exits:
+            self.visit_Link(link, switches) 
+
+    def visit_Link(self, link, switches):
+        if link.target in switches:
+            self.loops[link.target] = True
+        if not link.target in self.seen:
+            self.parents[link.target] = self.parents[link.prevblock]
+            self.visit_Block(link.target, switches)
+
+class CallableNode(CodeNode):
 
-    def note_Instance(self, inst):
-        if inst not in self.classes:
-            if inst not in self.pendingclasses:
-                self.pendingclasses.append(inst)
-
-    def note_meth(self, inst, meth):
-        bm = (inst, meth)
-        if bm not in self.methods:
-            if bm not in self.pendingmethods:
-                self.pendingmethods.append(bm)
-
-    def unique_name(self, basename):
-        n = self.seennames.get(basename, 0)
-        self.seennames[basename] = n+1
-        if n == 0:
-            return basename
+    selectormap = {
+        #'setitem:with:': 'at:put:',
+        #'getitem:':      'at:',
+        'new':           Selector('new', 0),
+        'runtimenew':    Selector('new', 0),
+        'classof':       Selector('class', 0),
+        'sameAs':        Selector('yourself', 0), 
+        'intAdd:':       Selector('+', 1),
+    }
+
+    def render_body(self, startblock):
+        self.loops = LoopFinder(startblock).loops
+        args = self.arguments(startblock)
+        sel = Selector(self.name, len(args))
+        yield sel.signature([self.expr(v) for v in args])
+ 
+        # XXX should declare local variables here
+        for line in self.render_block(startblock):
+            yield "    %s" % line
+        yield '! !'
+
+    def expr(self, v):
+        if isinstance(v, Variable):
+            return camel_case(v.name)
+        elif isinstance(v, Constant):
+            return self.gen.nameof(v.value)
+        else:
+            raise TypeError, "expr(%r)" % (v,)
+
+    def oper(self, op):
+        args = [self.expr(arg) for arg in op.args]
+        if op.opname == "oosend":
+            name = op.args[0].value
+            receiver = args[1]
+            if hasattr(self, "self") and op.args[1] == self.self:
+                receiver = "self"
+            args = args[2:]
+            self.gen.schedule_node(
+                    MethodNode(self.gen, op.args[1].concretetype, name))
+        elif op.opname == "oogetfield":
+            receiver = args[0]
+            name = op.args[1].value
+            args = args[2:]
+            if hasattr(self, "self") and op.args[0] == self.self:
+                # Could also directly substitute op.result with name
+                # everywhere for optimization.
+                return "%s := %s." % (self.expr(op.result), name) 
+            else:
+                self.gen.schedule_node(
+                        GetterNode(self.gen, op.args[0].concretetype, name))
+        elif op.opname == "oosetfield":
+            receiver = args[0]
+            name = op.args[1].value
+            args = args[2:]
+            if hasattr(self, "self") and op.args[0] == self.self:
+                # Note that the receiver variable is never used
+                return "%s := %s." % (name, args[0])
+            else:
+                self.gen.schedule_node(
+                        SetterNode(self.gen, op.args[0].concretetype, name))
+        elif op.opname == "direct_call":
+            # XXX not sure if static methods of a specific class should
+            # be treated differently.
+            receiver = "PyFunctions"
+            name = args[0]
+            args = args[1:]
+            self.gen.schedule_node(
+                FunctionNode(self.gen, op.args[0].value.graph))
+        else:
+            name = op.opname
+            receiver = args[0]
+            args = args[1:]
+        sel = Selector(name, len(args))
+        if op.opname != "oosend":
+            sel = self.selectormap.get(sel.symbol(), sel)
+        return "%s := %s %s." \
+                % (self.expr(op.result), receiver, sel.signature(args))
+
+    def render_return(self, args):
+        if len(args) == 2:
+            # exception
+            exc_cls = self.expr(args[0])
+            exc_val = self.expr(args[1])
+            yield "(PyOperationError class: %s value: %s) signal." % (exc_cls, exc_val)
+        else:
+            # regular return block
+            retval = self.expr(args[0])
+            yield "^%s" % retval
+
+    def render_link(self, link):
+        block = link.target
+        if link.args:
+            for i in range(len(link.args)):
+                yield '%s := %s.' % \
+                        (self.expr(block.inputargs[i]), self.expr(link.args[i]))
+        for line in self.render_block(block):
+            yield line
+
+    def render_block(self, block):
+        if self.loops.has_key(block):
+            if not self.loops[block]:
+                yield '"skip1"'
+                return
+            yield "["
+        for op in block.operations:
+            yield "%s" % self.oper(op)
+        if len(block.exits) == 0:
+            for line in self.render_return(block.inputargs):
+                yield line
+            return
+        elif block.exitswitch is None:
+            # single-exit block
+            assert len(block.exits) == 1
+            for line in self.render_link(block.exits[0]):
+                yield line
         else:
-            return self.unique_name('%s_%d' % (basename, n))
+            #exitswitch
+            if self.loops.has_key(block):
+                if self.loops[block]:
+                    self.loops[block] = False
+                    yield "%s] whileTrue: [" % self.expr(block.exitswitch)
+                    for line in self.render_link(block.exits[True]):
+                        yield "    %s" % line
+                    yield "]."
+                    for line in self.render_link(block.exits[False]):
+                        yield "%s" % line
+            else:
+                yield "%s ifTrue: [" % self.expr(block.exitswitch)
+                for line in self.render_link(block.exits[True]):
+                    yield "    %s" % line
+                yield "] ifFalse: [" 
+                for line in self.render_link(block.exits[False]):
+                    yield "    %s" % line
+                yield "]"
+
+class MethodNode(CallableNode):
+
+    def __init__(self, gen, INSTANCE, method_name):
+        self.gen = gen
+        self.INSTANCE = INSTANCE
+        self.name = method_name
+        self.hash_key = (INSTANCE, method_name)
+
+    def dependencies(self):
+        return [ClassNode(self.gen, self.INSTANCE)]
+
+    def arguments(self, startblock):
+        # Omit the explicit self
+        return startblock.inputargs[1:]
+    
+    def render(self):
+        yield self.render_fileout_header(
+                self.gen.nameof(self.INSTANCE), "methods")
+        graph = self.INSTANCE._methods[self.name].graph
+        self.self = graph.startblock.inputargs[0]
+        for line in self.render_body(graph.startblock):
+            yield line
+
+class FunctionNode(CallableNode):
+    
+    FUNCTIONS = Instance("Functions", ROOT)
 
+    def __init__(self, gen, graph):
+        self.gen = gen
+        self.graph = graph
+        self.name = gen.nameof(graph.func)
+        self.hash_key = graph
+
+    def dependencies(self):
+        return [ClassNode(self.gen, self.FUNCTIONS)]
+
+    def arguments(self, startblock):
+        return startblock.inputargs
+    
+    def render(self):
+        yield self.render_fileout_header("PyFunctions class", "functions")
+        for line in self.render_body(self.graph.startblock):
+            yield line
+
+class AccessorNode(CodeNode):
+
+    def __init__(self, gen, INSTANCE, field_name):
+        self.gen = gen
+        self.INSTANCE = INSTANCE
+        self.field_name = field_name
+        self.hash_key = (INSTANCE, field_name, self.__class__)
+
+    def dependencies(self):
+        return [ClassNode(self.gen, self.INSTANCE)]
+
+class SetterNode(AccessorNode):
+
+    def render(self):
+        yield self.render_fileout_header(
+                self.gen.nameof_Instance(self.INSTANCE), "accessors")
+        yield "%s: value" % self.field_name
+        yield "    %s := value" % self.field_name
+        yield "! !"
+
+class GetterNode(AccessorNode):
+
+    def render(self):
+        yield self.render_fileout_header(
+                self.gen.nameof_Instance(self.INSTANCE), "accessors")
+        yield self.field_name
+        yield "    ^%s" % self.field_name
+        yield "! !"
 
-    def skipped_function(self, func):
-        # debugging only!  Generates a placeholder for missing functions
-        # that raises an exception when called.
-        name = self.unique_name(camel_case('skipped_' + func.__name__))
-        return name

Modified: pypy/branch/njriley-trans/pypy/translator/squeak/test/test_oo.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/squeak/test/test_oo.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/squeak/test/test_oo.py	Fri Mar 10 06:12:02 2006
@@ -16,7 +16,7 @@
    GenSqueak(udir, t)
 
 
-C = Instance("test", None, {'a': (Signed, 3)})
+C = Instance("test", ROOT, {'a': (Signed, 3)})
 M = Meth([Signed], Signed)
 def m_(self, b):
    return self.a+b
@@ -28,12 +28,6 @@
       return new(C)
    build_sqfunc(f_new)
 
-def test_simple_meth():
-   def f_meth():
-      c = new(C)
-      return c.m(5)
-   build_sqfunc(f_meth)
-
 def test_simple_fields():
    def f_fields():
       c = new(C)

Modified: pypy/branch/njriley-trans/pypy/translator/squeak/test/test_squeaktrans.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/squeak/test/test_squeaktrans.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/squeak/test/test_squeaktrans.py	Fri Mar 10 06:12:02 2006
@@ -1,36 +1,192 @@
+import os
+import py
 from pypy.tool.udir import udir
 from pypy.translator.test import snippet
-from pypy.translator.squeak.gensqueak import GenSqueak
+from pypy.translator.squeak.gensqueak import GenSqueak, Selector, camel_case
 from pypy.translator.translator import TranslationContext
+from pypy import conftest
 
 
-def looping(i = (int), j = (int)):
+def looping(i, j):
     while i > 0:
         i -= 1
         while j > 0:
             j -= 1
 
-class TestSqueakTrans:
+def build_sqfunc(func, args=[]):
+    try: func = func.im_func
+    except AttributeError: pass
+    t = TranslationContext()
+    t.buildannotator().build_types(func, args)
+    t.buildrtyper(type_system="ootype").specialize()
+    if conftest.option.view:
+       t.viewcg()
+    return GenSqueak(udir, t)
 
-    def build_sqfunc(self, func):
-        try: func = func.im_func
-        except AttributeError: pass
-        t = TranslationContext()
-        graph = t.buildflowgraph(func)
-        t._prebuilt_graphs[func] = graph
-        self.gen = GenSqueak(udir, t)
+class TestSqueakTrans:
 
     def test_simple_func(self):
-        self.build_sqfunc(snippet.simple_func)
+        build_sqfunc(snippet.simple_func, [int])
 
     def test_if_then_else(self):
-        self.build_sqfunc(snippet.if_then_else)
-
-    def test_two_plus_two(self):
-        self.build_sqfunc(snippet.two_plus_two)
+        build_sqfunc(snippet.if_then_else, [bool, int, int])
 
     def test_my_gcd(self):
-        self.build_sqfunc(snippet.my_gcd)
+        build_sqfunc(snippet.my_gcd, [int, int])
 
     def test_looping(self):
-        self.build_sqfunc(looping)
+        build_sqfunc(looping, [int, int])
+
+
+# For now use pipes to communicate with squeak. This is very flaky
+# and only works for posix systems. At some later point we'll
+# probably need a socket based solution for this.
+startup_script = """
+| stdout src selector result arguments arg i |
+src := Smalltalk getSystemAttribute: 3.
+FileStream fileIn: src.
+selector := (Smalltalk getSystemAttribute: 4) asSymbol.
+arguments := OrderedCollection new.
+i := 4.
+[(arg := Smalltalk getSystemAttribute: (i := i + 1)) notNil]
+    whileTrue: [arguments add: arg asInteger].
+
+result := (PyFunctions perform: selector withArguments: arguments asArray).
+stdout := StandardFileStream fileNamed: '/dev/stdout'.
+stdout nextPutAll: result asString.
+Smalltalk snapshot: false andQuit: true.
+"""
+
+class TestGenSqueak:
+
+    def setup_class(self):
+        self.startup_st = udir.join("startup.st")
+        f = self.startup_st.open("w")
+        f.write(startup_script)
+        f.close()
+
+    def run_on_squeak(self, function, *args):
+        # NB: only integers arguments are supported currently
+        try:
+            import posix
+        except ImportError:
+            py.test.skip("Squeak tests only work on Unix right now.")
+        try:
+            py.path.local.sysfind("squeak")
+        except py.error.ENOENT:
+            py.test.skip("Squeak is not on your path.")
+        if os.getenv("SQUEAK_IMAGE") is None:
+            py.test.skip("Squeak tests expect the SQUEAK_IMAGE environment "
+                    "variable to point to an image.")
+        arg_types = [type(arg) for arg in args]
+        gen_squeak = build_sqfunc(function, arg_types)
+        cmd = 'squeak -headless -- %s %s "%s" %s' \
+                % (self.startup_st, udir.join(gen_squeak.filename),
+                   Selector(function.__name__, len(args)).symbol(),
+                   " ".join(['"%s"' % a for a in args]))
+        squeak_process = os.popen(cmd)
+        result = squeak_process.read()
+        assert squeak_process.close() is None # exit status was 0
+        return result
+
+    def test_theanswer(self):
+        def theanswer():
+            return 42
+        assert self.run_on_squeak(theanswer) == "42"
+
+    def test_simplemethod(self):
+        class A:
+            def m(self):
+                return 42
+        def simplemethod():
+            return A().m()
+        assert self.run_on_squeak(simplemethod) == "42"
+
+    def test_argfunction(self):
+        def function(i, j=2):
+            return i + j
+        assert self.run_on_squeak(function, 1, 3) == "4"
+
+    def test_argmethod(self):
+        class A:
+            def m(self, i, j, h=2):
+                return i + j + h
+        def simplemethod(i):
+            return A().m(i, j=3)
+        assert self.run_on_squeak(simplemethod, 1) == "6"
+
+    def test_nameclash_classes(self):
+        from pypy.translator.squeak.test.support import A as A2
+        class A:
+            def m(self, i): return 2 + i
+        def f():
+            return A().m(0) + A2().m(0)
+        assert self.run_on_squeak(f) == "3"
+
+    def test_nameclash_classes_mean(self):
+        class A:
+            def m(self, i): return 1 + i
+        A2 = A
+        class A:
+            def m(self, i): return 2 + i
+        def f():
+            return A().m(0) + A2().m(0)
+        assert self.run_on_squeak(f) == "3"
+
+    def test_nameclash_camel_case(self):
+        class ASomething:
+            def m(self, i): return 1 + i
+        class A_Something:
+            def m(self, i): return 2 + i
+        def f():
+            x = ASomething().m(0) + A_Something().m(0)
+            return x + ASomething().m(0) + A_Something().m(0)
+        assert self.run_on_squeak(f) == "6"
+
+    def test_nameclash_functions(self):
+        from pypy.translator.squeak.test.support import f as f2
+        def f(i):
+            return i + 2
+        def g():
+            return f(0) + f2(0)
+        assert self.run_on_squeak(g) == "3"
+
+    def test_direct_call(self):
+        def h(i):
+            return g(i) + 1 # another call to g to try to trap GenSqueak
+        def g(i):
+            return i + 1 
+        def f(i):
+            return h(i) + g(i)
+        assert self.run_on_squeak(f, 1) == "5"
+
+    def test_getfield_setfield(self):
+        class A:
+            def set(self, i):
+                self.i = i
+            def inc(self):
+                self.i = self.i + 1
+        def f(i):
+            a = A()
+            a.set(i)
+            i = a.i
+            a.i = 3
+            a.inc()
+            return i + a.i
+        assert self.run_on_squeak(f, 2) == "6"
+
+
+class TestSelector:
+
+    def test_selector(self):
+        assert Selector("bla_bla", 0).symbol() == "blaBla"
+        assert Selector("bla", 1).symbol() == "bla:"
+        assert Selector("bla_bla_bla", 3).symbol() == "blaBlaBla:with:with:"
+        assert Selector("+", 1).symbol() == "+"
+
+    def test_signature(self):
+        assert Selector("bla", 0).signature([]) == "bla"
+        assert Selector("bla", 1).signature(["v"]) == "bla: v"
+        assert Selector("bla", 2).signature(["v0", "v1"]) == "bla: v0 with: v1"
+        assert Selector("+", 1).signature(["v"]) == "+ v"
+

Modified: pypy/branch/njriley-trans/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/tool/cbuild.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/tool/cbuild.py	Fri Mar 10 06:12:02 2006
@@ -94,7 +94,8 @@
                         extra_compile_args = []
                         # ensure correct math on windows
                         if sys.platform == 'win32':
-                            extra_compile_args.append('/Op')
+                            extra_compile_args.append('/Op') # get extra precision
+                            extra_compile_args.append('/PDB:laber') # create debug info
                         if get_default_compiler() == 'unix':
                             old_version = False
                             try:
@@ -273,6 +274,8 @@
                 self.libraries.append('pthread')
             self.compile_extra += ['-O2', '-pthread']
             self.link_extra += ['-pthread']
+        if sys.platform == 'win32':
+            self.link_extra += ['/DEBUG'] # generate .pdb file
         if sys.platform == 'darwin':
             if '/sw/include' not in self.include_dirs:
                 self.include_dirs.append('/sw/include')

Modified: pypy/branch/njriley-trans/pypy/translator/tool/graphpage.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/tool/graphpage.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/tool/graphpage.py	Fri Mar 10 06:12:02 2006
@@ -169,6 +169,8 @@
                     #info = self.links.get(var.name, var.name)
                     #info = '(%s) %s' % (var.concretetype, info)
                     info = str(var.concretetype)
+                    if info == 'Void':     # gray out Void variables
+                        info = info, (160,160,160)
                     self.links[var.name] = info
 
         for graph in graphs:

Modified: pypy/branch/njriley-trans/pypy/translator/tool/make_dot.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/tool/make_dot.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/tool/make_dot.py	Fri Mar 10 06:12:02 2006
@@ -143,10 +143,10 @@
 
         iargs = " ".join(map(repr, block.inputargs))
         if block.exc_handler:
-            eh = 'EH'
+            eh = ' (EH)'
         else:
             eh = ''
-        data = "%s%s(%s %s)\\ninputargs: %s\\n\\n" % (name, block.at(), block.__class__.__name__, eh, iargs)
+        data = "%s%s%s\\ninputargs: %s\\n\\n" % (name, block.at(), eh, iargs)
         if block.operations and self.func:
             maxoffs = max([op.offset for op in block.operations])
             if maxoffs >= 0:

Modified: pypy/branch/njriley-trans/pypy/translator/translator.py
==============================================================================
--- pypy/branch/njriley-trans/pypy/translator/translator.py	(original)
+++ pypy/branch/njriley-trans/pypy/translator/translator.py	Fri Mar 10 06:12:02 2006
@@ -2,7 +2,7 @@
 
 The Translator is a glue class putting together the various pieces of the
 translation-related code.  It can be used for interactive testing of the
-translator; see pypy/bin/translator.py.
+translator; see pypy/bin/translatorshell.py.
 """
 import autopath, os, sys, types, copy
 



More information about the Pypy-commit mailing list