From arigo at codespeak.net Thu Feb 12 00:25:13 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2004 00:25:13 +0100 (MET) Subject: [pypy-svn] r2952 - pypy/trunk/src/pypy/tool Message-ID: <20040211232513.AC9C05AC3C@thoth.codespeak.net> Author: arigo Date: Thu Feb 12 00:25:12 2004 New Revision: 2952 Modified: pypy/trunk/src/pypy/tool/testit.py Log: Fix to run the test suite under the cvs head of CPython. This is just one more workaround for unittest.py. Modified: pypy/trunk/src/pypy/tool/testit.py ============================================================================== --- pypy/trunk/src/pypy/tool/testit.py (original) +++ pypy/trunk/src/pypy/tool/testit.py Thu Feb 12 00:25:12 2004 @@ -114,7 +114,7 @@ self.stream.writeln(self.separator1) self.stream.writeln("%s: %s" % (flavour,self.getDescription(test))) self.stream.writeln(self.separator2) - t1 = self._exc_info_to_string(err) + t1 = ''.join(traceback.format_exception(*err)) if isinstance(err[1], OperationError) and \ test.space.full_exceptions: if not Options.quiet: From arigo at codespeak.net Thu Feb 12 01:00:26 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2004 01:00:26 +0100 (MET) Subject: [pypy-svn] r2953 - in pypy/trunk/src/pypy: objspace tool Message-ID: <20040212000026.3EA8D5AC3F@thoth.codespeak.net> Author: arigo Date: Thu Feb 12 01:00:25 2004 New Revision: 2953 Modified: pypy/trunk/src/pypy/objspace/trace.py pypy/trunk/src/pypy/tool/testit.py Log: A few more testit hacks to let some advertised options work: -P runs the tests in TraceObjSpace, printing traces for failures. -i starts pdb on the traceback of each error in turn. Modified: pypy/trunk/src/pypy/objspace/trace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trace.py (original) +++ pypy/trunk/src/pypy/objspace/trace.py Thu Feb 12 01:00:25 2004 @@ -107,7 +107,12 @@ return getattr(self.__func, name) class TraceObjSpace: - def __init__(self, space): + def __init__(self, space=None): + if space is None: + # make up a TrivialObjSpace by default + # ultimately, remove this hack and fix the -P option of tests + from pypy.objspace import trivial + space = trivial.TrivialObjSpace() self.__space = space self.settrace() Modified: pypy/trunk/src/pypy/tool/testit.py ============================================================================== --- pypy/trunk/src/pypy/tool/testit.py (original) +++ pypy/trunk/src/pypy/tool/testit.py Thu Feb 12 01:00:25 2004 @@ -64,8 +64,16 @@ class MyTextTestResult(unittest._TextTestResult): ignored = 0 + trace_information = () + + def record_trace(self, test): + # XXX hack for TraceObjSpace + if hasattr(test.space, 'settrace'): + self.trace_information += test.space.getresult(), + test.space.settrace() def addError(self, test, err): + self.record_trace(test) from pypy.interpreter.baseobjspace import OperationError if isinstance(err[1], OperationError) and test.space.full_exceptions: if err[1].match(test.space, test.space.w_AssertionError): @@ -75,6 +83,7 @@ self.errors[-1] = (test, sys.exc_info()) def addFailure(self, test, err): + self.record_trace(test) unittest._TextTestResult.addFailure(self, test, err) self.failures[-1] = (test, sys.exc_info()) @@ -93,12 +102,19 @@ self.stream.write('i') def interact(self): - efs = self.errors + self.failures - from pypy.tool.testitpm import TestPM - c = TestPM(efs) - c.cmdloop() + #efs = self.errors + self.failures + #from pypy.tool.testitpm import TestPM + #c = TestPM(efs) + #c.cmdloop() + for test, (exc_type, exc_value, exc_tb) in self.errors: + import pdb; pdb.post_mortem(exc_tb) def printErrors(self): + if self.trace_information: + from pypy.tool.traceop import print_result + for trace in self.trace_information: + print_result(trace) + sys.stdout.flush() if Options.interactive: print if self.errors or self.failures: From arigo at codespeak.net Thu Feb 12 01:03:53 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2004 01:03:53 +0100 (MET) Subject: [pypy-svn] r2954 - pypy/trunk/src/pypy/module/test Message-ID: <20040212000353.E47275AC41@thoth.codespeak.net> Author: arigo Date: Thu Feb 12 01:03:53 2004 New Revision: 2954 Modified: pypy/trunk/src/pypy/module/test/test_builtin.py Log: Fixed an error for Python cvs head, in which support for recursive comparison has been removed (something which I am to blame for, incidentally :-) Strangely, __builtins__ end up containing itself in '__builtins__', hence the infinite recursion problem that this patch removes. The reason is that we run a lot of stuff in the __builtin__ module itself at initialization time. Modified: pypy/trunk/src/pypy/module/test/test_builtin.py ============================================================================== --- pypy/trunk/src/pypy/module/test/test_builtin.py (original) +++ pypy/trunk/src/pypy/module/test/test_builtin.py Thu Feb 12 01:03:53 2004 @@ -33,7 +33,7 @@ d = {"foo":"bar"} exec "def f(): return globals()" in d d2 = d["f"]() - self.assertEquals(d2,d) + self.assert_(d2 is d) def test_locals(self): def f(): From arigo at codespeak.net Mon Feb 16 21:00:06 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 16 Feb 2004 21:00:06 +0100 (MET) Subject: [pypy-svn] r2984 - in pypy/trunk/src/pypy: annotation translator translator/tool Message-ID: <20040216200006.3427C5AC3C@thoth.codespeak.net> Author: arigo Date: Mon Feb 16 21:00:04 2004 New Revision: 2984 Modified: pypy/trunk/src/pypy/annotation/annset.py pypy/trunk/src/pypy/annotation/model.py pypy/trunk/src/pypy/translator/annrpython.py pypy/trunk/src/pypy/translator/tool/traceann.py Log: Removed a few XXX in Samuele's getattr/setattr support for user-defined classes. Modified: pypy/trunk/src/pypy/annotation/annset.py ============================================================================== --- pypy/trunk/src/pypy/annotation/annset.py (original) +++ pypy/trunk/src/pypy/annotation/annset.py Mon Feb 16 21:00:04 2004 @@ -119,6 +119,14 @@ self.kill(predicate, subject) self.set(predicate, subject, newanswer) + def set_or_generalize(self, predicate, subject, otherpossibleanswer): + """This is a hack. Do not use for SomeValues that could be merged.""" + about = self._about(subject) + if predicate in about.annotations: + self.generalize(predicate, subject, otherpossibleanswer) + else: + self.set(predicate, subject, otherpossibleanswer) + def merge(self, oldvalue, newvalue): """Update the heap to account for the merging of oldvalue and newvalue. Return the merged somevalue.""" Modified: pypy/trunk/src/pypy/annotation/model.py ============================================================================== --- pypy/trunk/src/pypy/annotation/model.py (original) +++ pypy/trunk/src/pypy/annotation/model.py Mon Feb 16 21:00:04 2004 @@ -29,6 +29,7 @@ const = Predicate('const') type = Predicate('type') immutable = Predicate('immutable') + instanceattr = PredicateFamily('instanceattr') def debugname(someval, prefix, _seen = {}): Modified: pypy/trunk/src/pypy/translator/annrpython.py ============================================================================== --- pypy/trunk/src/pypy/translator/annrpython.py (original) +++ pypy/trunk/src/pypy/translator/annrpython.py Mon Feb 16 21:00:04 2004 @@ -29,8 +29,6 @@ self.annotated = {} # set of blocks already seen self.translator = translator - self.classes = {} # map classes to attr-name -> SomaValue dicts - #___ convenience high-level interface __________________ def build_types(self, flowgraph, input_arg_types): @@ -217,39 +215,24 @@ def consider_op_setattr(self,obj,attr,newval): objtype = self.heap.get(ANN.type,obj) if isinstance(objtype,type): - attrdict = self.classes.setdefault(objtype,{}) attr = self.heap.get(ANN.const,attr) - if attr is not mostgeneralvalue: - oldval = attrdict.get(attr,impossiblevalue) - newval = self.heap.merge(oldval,newval) - # XXX - # if newval is not oldval (using isshared) - # we should reflow the places that depend on this - # we really need to make the attrdict an annotation - # on the type as const - # or invent a fake annotation - # that we get on getattr and kill and reset on setattr - # to trigger that - attrdict[attr] = newval - else: - raise ValueError,"setattr op with non-const attrname not expected" + if isinstance(attr, str): + # update the annotation 'instanceattr' about the class 'cls' + cls = self.constant(objtype) + self.heap.set_or_generalize(ANN.instanceattr[attr], cls, newval) return SomeValue() def consider_op_getattr(self,obj,attr): result = SomeValue() objtype = self.heap.get(ANN.type,obj) if isinstance(objtype,type): - attrdict = self.classes.setdefault(objtype,{}) attr = self.heap.get(ANN.const,attr) - if attr is not mostgeneralvalue: + if isinstance(attr, str): if hasattr(objtype,attr): # XXX shortcut to keep methods working return result - oldval = attrdict.get(attr,impossiblevalue) - if oldval is impossiblevalue: - return impossiblevalue - return oldval - else: - raise ValueError,"getattr op with non-const attrname not expected" + # return the current annotation for the class 'cls' + cls = self.constant(objtype) + return self.heap.get(ANN.instanceattr[attr], cls) return result Modified: pypy/trunk/src/pypy/translator/tool/traceann.py ============================================================================== --- pypy/trunk/src/pypy/translator/tool/traceann.py (original) +++ pypy/trunk/src/pypy/translator/tool/traceann.py Mon Feb 16 21:00:04 2004 @@ -20,9 +20,9 @@ from pypy.translator.translator import * from pypy.translator.test import snippet as test -from pypy.translator.tool import tracer -tracer.trace(AnnotationSet) -tracer.trace(RPythonAnnotator) +#from pypy.translator.tool import tracer +#tracer.trace(AnnotationSet) +#tracer.trace(RPythonAnnotator) try: snippet_name = sys.argv[1] @@ -40,8 +40,8 @@ lines = [] for key, value in a.bindings.items(): lines.append('%r: %r' % (key, value)) -for cl, attrdict in a.classes.items(): - lines.append('%s: %r' % (cl.__name__,attrdict)) +#for cl, attrdict in a.classes.items(): +# lines.append('%s: %r' % (cl.__name__,attrdict)) lines.sort() for line in lines: print line From arigo at codespeak.net Mon Feb 16 22:20:40 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 16 Feb 2004 22:20:40 +0100 (MET) Subject: [pypy-svn] r2986 - in pypy/trunk/src/pypy: tool translator translator/testtranslator/tool Message-ID: <20040216212040.0157B5AC3C@thoth.codespeak.net> Author: arigo Date: Mon Feb 16 22:20:39 2004 New Revision: 2986 Modified: pypy/trunk/src/pypy/tool/testit.py pypy/trunk/src/pypy/translator/annrpython.py pypy/trunk/src/pypy/translator/gencl.py pypy/trunk/src/pypy/translator/genpyrex.py pypy/trunk/src/pypy/translator/test/test_pyrextrans.py pypy/trunk/src/pypy/translator/tool/buildcl.py pypy/trunk/src/pypy/translator/tool/buildpyxmodule.py pypy/trunk/src/pypy/translator/translator.py Log: Generate Pyrex class definitions. This is for attributes only, there is no support for methods, and it is not clear if there should be. If we keep C in mind then we should probably generate global functions only, and introduce explicit tricks to emulate virtual methods -- though I believe that Pyrex can do precisely that, so maybe we should just go ahead and emit methods. Modified: pypy/trunk/src/pypy/tool/testit.py ============================================================================== --- pypy/trunk/src/pypy/tool/testit.py (original) +++ pypy/trunk/src/pypy/tool/testit.py Mon Feb 16 22:20:39 2004 @@ -68,8 +68,12 @@ def record_trace(self, test): # XXX hack for TraceObjSpace - if hasattr(test.space, 'settrace'): - self.trace_information += test.space.getresult(), + try: + result = test.space.getresult() + except AttributeError: + pass + else: + self.trace_information += result test.space.settrace() def addError(self, test, err): Modified: pypy/trunk/src/pypy/translator/annrpython.py ============================================================================== --- pypy/trunk/src/pypy/translator/annrpython.py (original) +++ pypy/trunk/src/pypy/translator/annrpython.py Mon Feb 16 22:20:39 2004 @@ -28,6 +28,8 @@ self.bindings = {} # map Variables/Constants to SomeValues self.annotated = {} # set of blocks already seen self.translator = translator + self.userclasses = {} # set of user classes discovered, + # mapped to sets of instance attributes #___ convenience high-level interface __________________ @@ -58,6 +60,19 @@ raise TypeError, ("Variable or Constant instance expected, " "got %r" % (variable,)) + def getuserclasses(self): + """Return a set of known user classes.""" + return self.userclasses + + def getuserattributes(self, cls): + """Enumerate the attributes of the given user class, as Variable()s.""" + for attr in self.userclasses[cls]: + clscell = self.constant(cls) + attrcell = self.heap.get(ANN.instanceattr[attr], clscell) + v = Variable(name=attr) + self.bindings[v] = attrcell + yield v + #___ medium-level interface ____________________________ @@ -214,25 +229,33 @@ def consider_op_setattr(self,obj,attr,newval): objtype = self.heap.get(ANN.type,obj) - if isinstance(objtype,type): + if objtype in self.userclasses: attr = self.heap.get(ANN.const,attr) if isinstance(attr, str): - # update the annotation 'instanceattr' about the class 'cls' - cls = self.constant(objtype) - self.heap.set_or_generalize(ANN.instanceattr[attr], cls, newval) + # do we already know about this attribute? + attrdict = self.userclasses[objtype] + clscell = self.constant(objtype) + if attr not in attrdict: + # no -> create it + attrdict[attr] = True + self.heap.set(ANN.instanceattr[attr], clscell, newval) + else: + # yes -> update it + self.heap.generalize(ANN.instanceattr[attr], clscell, newval) return SomeValue() def consider_op_getattr(self,obj,attr): result = SomeValue() objtype = self.heap.get(ANN.type,obj) - if isinstance(objtype,type): + if objtype in self.userclasses: attr = self.heap.get(ANN.const,attr) if isinstance(attr, str): - if hasattr(objtype,attr): # XXX shortcut to keep methods working - return result - # return the current annotation for the class 'cls' - cls = self.constant(objtype) - return self.heap.get(ANN.instanceattr[attr], cls) + # do we know something about this attribute? + attrdict = self.userclasses[objtype] + if attr in attrdict: + # yes -> return the current annotation + clscell = self.constant(objtype) + return self.heap.get(ANN.instanceattr[attr], clscell) return result @@ -376,6 +399,8 @@ elif isinstance(func,type): # XXX flow into __init__/__new__ self.heap.settype(result,func) + if func.__module__ != '__builtin__': + self.userclasses.setdefault(func, {}) return result def consider_const(self, constvalue): Modified: pypy/trunk/src/pypy/translator/gencl.py ============================================================================== --- pypy/trunk/src/pypy/translator/gencl.py (original) +++ pypy/trunk/src/pypy/translator/gencl.py Mon Feb 16 22:20:39 2004 @@ -205,7 +205,6 @@ sys.stdout = oldstdout return out.getvalue() def emit(self): - self.emit_prelude() self.emit_defun(self.fun) def emit_defun(self, fun): print ";;;; Main" @@ -322,12 +321,11 @@ print trans % argreprs, print ")" print ")" - def emit_prelude(self): - print ";;;; Prelude" - print prelude + def globaldeclarations(self): + return prelude -prelude = """\ +prelude = """;;;; Prelude (defun make-iterator (seq) (let ((i 0)) (lambda () Modified: pypy/trunk/src/pypy/translator/genpyrex.py ============================================================================== --- pypy/trunk/src/pypy/translator/genpyrex.py (original) +++ pypy/trunk/src/pypy/translator/genpyrex.py Mon Feb 16 22:20:39 2004 @@ -127,6 +127,14 @@ else: return "%s = getattr(%s)" % (self.resultname, ", ".join(args)) + def op_setattr(self): + args = self.argnames + attr = self.op.args[1] + if isinstance(attr, Constant) and self.ispythonident(attr.value): + return "%s.%s = %s" % (args[0], attr.value, args[2]) + else: + return "setattr(%s, %s, %s)" % args + def op_not(self): return "%s = not %s" % (self.resultname, self.argnames[0]) @@ -214,8 +222,11 @@ return None def get_varname(self, var): - if self.get_type(var) in (int, bool): + vartype = self.get_type(var) + if vartype in (int, bool): prefix = "i_" + elif self.annotator and vartype in self.annotator.getuserclasses(): + prefix = "p_" else: prefix = "" return prefix + var.name @@ -224,11 +235,16 @@ vartype = self.get_type(var) if vartype in (int, bool): ctype = "int" + elif self.annotator and vartype in self.annotator.getuserclasses(): + ctype = self.get_classname(vartype) else: ctype = "object" return (ctype, self.get_varname(var)) + def get_classname(self, userclass): + return userclass.__name__ + def _vardecl(self, var): vartype, varname = self._paramvardecl(var) if vartype != "object": @@ -310,3 +326,27 @@ self.putline("%s = %s" % (", ".join(targs), ", ".join(sargs))) self.gen_block(block) + + def globaldeclarations(self): + """Static method to generate the global class declaration for a + group of functions.""" + if self.annotator: + self.lines = [] + self.indent = 0 + for cls in self.annotator.getuserclasses(): + self.putline("cdef class %s:" % self.get_classname(cls)) + self.indent += 1 + empty = True + for var in self.annotator.getuserattributes(cls): + vartype, varname = self._paramvardecl(var) + varname = var.name # no 'i_' prefix + self.putline("cdef %s %s" % (vartype, varname)) + empty = False + else: + if empty: + self.putline("pass") + self.indent -= 1 + self.putline("") + return '\n'.join(self.lines) + else: + return '' Modified: pypy/trunk/src/pypy/translator/test/test_pyrextrans.py ============================================================================== --- pypy/trunk/src/pypy/translator/test/test_pyrextrans.py (original) +++ pypy/trunk/src/pypy/translator/test/test_pyrextrans.py Mon Feb 16 22:20:39 2004 @@ -7,7 +7,7 @@ from pypy.translator.test import snippet as t -class TypedPyrexGenTestCase(testit.IntTestCase): +class NoTypePyrexGenTestCase(testit.IntTestCase): def setUp(self): self.space = testit.objspace('flow') @@ -20,7 +20,6 @@ options = { 'simplify' : 1, 'dot' : dot, - 'inputargtypes' : [int] * func.func_code.co_argcount } return build_cfunc(func, **options) @@ -84,7 +83,7 @@ self.assertEquals(sand(0, 6), "no") self.assertEquals(sand(0, 0), "no") -class NoTypePyrexGenTestCase(TypedPyrexGenTestCase): +class TypedPyrexGenTestCase(NoTypePyrexGenTestCase): def build_cfunc(self, func): try: func = func.im_func @@ -94,8 +93,15 @@ options = { 'simplify' : 1, 'dot' : dot, + 'inputargtypes' : [int] * func.func_code.co_argcount } return build_cfunc(func, **options) + # _______________________________________________________ + # The following tests require the type inference to work. + def test_set_attr(self): + set_attr = self.build_cfunc(t.set_attr) + self.assertEquals(set_attr(), 2) + if __name__ == '__main__': testit.main() Modified: pypy/trunk/src/pypy/translator/tool/buildcl.py ============================================================================== --- pypy/trunk/src/pypy/translator/tool/buildcl.py (original) +++ pypy/trunk/src/pypy/translator/tool/buildcl.py Mon Feb 16 22:20:39 2004 @@ -45,7 +45,7 @@ def _make_cl_func(func, cl, path, argtypes=[]): fun = FlowObjSpace().build_flow(func) gen = GenCL(fun, argtypes) - out = gen.emitcode() + out = gen.globaldeclarations() + '\n' + gen.emitcode() i = 1 fpath = path.join("%s.lisp" % fun.name) def _(*args): Modified: pypy/trunk/src/pypy/translator/tool/buildpyxmodule.py ============================================================================== --- pypy/trunk/src/pypy/translator/tool/buildpyxmodule.py (original) +++ pypy/trunk/src/pypy/translator/tool/buildpyxmodule.py Mon Feb 16 22:20:39 2004 @@ -133,10 +133,11 @@ pyxstring = genpyrex.emitcode() #funcgraph.source = inspect.getsource(func) - mod = make_module_from_pyxstring(name, udir, pyxstring) else: pyxstring = genpyrex.emitcode() - mod = make_module_from_pyxstring(name, udir, pyxstring) + + pyxheader = genpyrex.globaldeclarations() + mod = make_module_from_pyxstring(name, udir, pyxheader + '\n' + pyxstring) if dot: if name != func.func_name: # if some transformations have been done Modified: pypy/trunk/src/pypy/translator/translator.py ============================================================================== --- pypy/trunk/src/pypy/translator/translator.py (original) +++ pypy/trunk/src/pypy/translator/translator.py Mon Feb 16 22:20:39 2004 @@ -144,16 +144,18 @@ else: ann = RPythonAnnotator(self) if func is None: - code = self.generatecode1(gencls, input_arg_types, - self.entrypoint, ann) - codes = [code] + codes = [self.generatecode1(gencls, input_arg_types, + self.entrypoint, ann)] for func in self.functions: if func is not self.entrypoint: code = self.generatecode1(gencls, None, func, ann) codes.append(code) - return '\n\n#_________________\n\n'.join(codes) else: - return self.generatecode1(gencls, input_arg_types, func, ann) + codes = [self.generatecode1(gencls, input_arg_types, func, ann)] + code = self.generateglobaldecl(gencls, func, ann) + if code: + codes.insert(0, code) + return '\n\n#_________________\n\n'.join(codes) def generatecode1(self, gencls, input_arg_types, func, ann): graph = self.getflowgraph(func) @@ -164,6 +166,13 @@ g.setannotator(ann) return g.emitcode() + def generateglobaldecl(self, gencls, func, ann): + graph = self.getflowgraph(func) + g = gencls(graph) + if ann is not None: + g.setannotator(ann) + return g.globaldeclarations() + def compile(self): """Returns compiled function.