From cfbolz at codespeak.net Mon Apr 2 12:08:34 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 2 Apr 2007 12:08:34 +0200 (CEST) Subject: [pypy-svn] r41794 - pypy/dist/pypy/doc Message-ID: <20070402100834.9117B10077@code0.codespeak.net> Author: cfbolz Date: Mon Apr 2 12:08:32 2007 New Revision: 41794 Modified: pypy/dist/pypy/doc/sprint-reports.txt Log: add link to pycon sprint report (lene again) Modified: pypy/dist/pypy/doc/sprint-reports.txt ============================================================================== --- pypy/dist/pypy/doc/sprint-reports.txt (original) +++ pypy/dist/pypy/doc/sprint-reports.txt Mon Apr 2 12:08:32 2007 @@ -20,7 +20,7 @@ * `Paris (Oct 2005)`_ * `Gothenburg (Dec 2005)`_ * `Mallorca (Jan 2006)`_ - * PyCon/Dallas (Feb 2006) + * `PyCon/Dallas (Feb 2006)`_ * `LouvainLaNeuve (March 2006)`_ * `Leysin (April 2006)`_ * `Tokyo (April 2006)`_ @@ -54,3 +54,4 @@ .. _`Leysin (January 2007)`: http://codespeak.net/pypy/extradoc/sprintinfo/leysin-winter-2007/report.txt .. _Hildesheim (Feb 2007): http://codespeak.net/pypy/extradoc/sprintinfo/trillke-2007/sprint-report.txt .. _`EU report writing sprint`: http://codespeak.net/pypy/extradoc/sprintinfo/trillke-2007/eu-report-sprint-report.txt + .. _`PyCon/Dallas (Feb 2006)`: http://codespeak.net/pypy/extradoc/sprintinfo/pycon06/sprint-report.txt From arigo at codespeak.net Mon Apr 2 14:57:51 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Apr 2007 14:57:51 +0200 (CEST) Subject: [pypy-svn] r41803 - in pypy/dist/pypy: config objspace/std Message-ID: <20070402125751.95CFF10077@code0.codespeak.net> Author: arigo Date: Mon Apr 2 14:57:49 2007 New Revision: 41803 Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/objspace/std/objspace.py Log: A version of BINARY_SUBSCR that special-cases 'list[integer]'. Not enabled by default, measuring... Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon Apr 2 14:57:49 2007 @@ -226,6 +226,9 @@ BoolOption("optimized_int_add", "special case the addition of two integers in BINARY_ADD", default=False), + BoolOption("optimized_list_getitem", + "special case the 'list[integer]' expressions", + default=False), BoolOption("oldstyle", "specify whether the default metaclass should be classobj", Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Mon Apr 2 14:57:49 2007 @@ -88,6 +88,20 @@ w_result = f.space.add(w_1, w_2) f.pushvalue(w_result) + if self.config.objspace.std.optimized_list_getitem: + def BINARY_SUBSCR(f, *ignored): + w_2 = f.popvalue() + w_1 = f.popvalue() + if type(w_1) is W_ListObject and type(w_2) is W_IntObject: + try: + w_result = w_1.wrappeditems[w_2.intval] + except IndexError: + raise OperationError(f.space.w_IndexError, + f.space.wrap("list index out of range")) + else: + w_result = f.space.getitem(w_1, w_2) + f.pushvalue(w_result) + def CALL_LIKELY_BUILTIN(f, oparg, *ignored): from pypy.module.__builtin__ import OPTIMIZED_BUILTINS, Module from pypy.objspace.std.dictmultiobject import W_DictMultiObject From mwh at codespeak.net Mon Apr 2 15:13:39 2007 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 2 Apr 2007 15:13:39 +0200 (CEST) Subject: [pypy-svn] r41804 - in pypy/dist/pypy: config interpreter objspace/std Message-ID: <20070402131339.AA2441007A@code0.codespeak.net> Author: mwh Date: Mon Apr 2 15:13:37 2007 New Revision: 41804 Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/pyopcode.py pypy/dist/pypy/objspace/std/objspace.py Log: add some code to dump out the types verious simple bytecodes receive, the idea being to inspire optimized bytecodes. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon Apr 2 15:13:37 2007 @@ -1,4 +1,4 @@ -import autopath +]import autopath import py, os import sys from pypy.config.config import OptionDescription, BoolOption, IntOption, ArbitraryOption @@ -234,6 +234,11 @@ "specify whether the default metaclass should be classobj", default=False, cmdline="--oldstyle"), + BoolOption("logspaceoptypes", + "a instrumentation option: before exit, print the types seen by " + "certain simpler bytecodes", + default=False), + BoolOption("allopts", "enable all thought-to-be-working optimizations", default=False, Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Mon Apr 2 15:13:37 2007 @@ -225,6 +225,9 @@ report() if self.config.objspace.logbytecodes: self.reportbytecodecounts() + if self.config.objspace.std.logspaceoptypes: + for s in self.FrameClass._space_op_types: + print s def reportbytecodecounts(self): os.write(2, "Starting bytecode report.\n") Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Mon Apr 2 15:13:37 2007 @@ -26,6 +26,7 @@ w_1 = f.popvalue() w_result = operation(w_1) f.pushvalue(w_result) + opimpl.unaryop = operationname return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname) @@ -37,6 +38,7 @@ w_1 = f.popvalue() w_result = operation(w_1, w_2) f.pushvalue(w_result) + opimpl.binop = operationname return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname) Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Mon Apr 2 15:13:37 2007 @@ -132,6 +132,41 @@ f.dropvalues(nargs) f.pushvalue(w_result) + if self.config.objspace.std.logspaceoptypes: + _space_op_types = [] + for name, func in pyframe.PyFrame.__dict__.iteritems(): + if hasattr(func, 'binop'): + operationname = func.binop + def make_opimpl(operationname): + def opimpl(f, *ignored): + operation = getattr(f.space, operationname) + w_2 = f.popvalue() + w_1 = f.popvalue() + if we_are_translated(): + s = operationname + ' ' + str(w_1) + ' ' + str(w_2) + else: + s = operationname + ' ' + w_1.__class__.__name__ + ' ' + w_2.__class__.__name__ + f._space_op_types.append(s) + w_result = operation(w_1, w_2) + f.pushvalue(w_result) + return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname) + locals()[name] = make_opimpl(operationname) + elif hasattr(func, 'unaryop'): + operationname = func.unaryop + def make_opimpl(operationname): + def opimpl(f, *ignored): + operation = getattr(f.space, operationname) + w_1 = f.popvalue() + if we_are_translated(): + s = operationname + ' ' + str(w_1) + else: + s = operationname + ' ' + w_1.__class__.__name__ + f._space_op_types.append(s) + w_result = operation(w_1) + f.pushvalue(w_result) + return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname) + locals()[name] = make_opimpl(operationname) + self.FrameClass = StdObjSpaceFrame # XXX store the dict class on the space to access it in various places From cfbolz at codespeak.net Mon Apr 2 15:17:40 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 2 Apr 2007 15:17:40 +0200 (CEST) Subject: [pypy-svn] r41805 - pypy/dist/pypy/config Message-ID: <20070402131740.07A1A10078@code0.codespeak.net> Author: cfbolz Date: Mon Apr 2 15:17:38 2007 New Revision: 41805 Modified: pypy/dist/pypy/config/pypyoption.py Log: huh? Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon Apr 2 15:17:38 2007 @@ -1,4 +1,4 @@ -]import autopath +import autopath import py, os import sys from pypy.config.config import OptionDescription, BoolOption, IntOption, ArbitraryOption From mwh at codespeak.net Mon Apr 2 18:45:03 2007 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 2 Apr 2007 18:45:03 +0200 (CEST) Subject: [pypy-svn] r41816 - pypy/dist/pypy/doc/config Message-ID: <20070402164503.7C53E10081@code0.codespeak.net> Author: mwh Date: Mon Apr 2 18:45:02 2007 New Revision: 41816 Added: pypy/dist/pypy/doc/config/objspace.std.logspaceoptypes.txt (contents, props changed) pypy/dist/pypy/doc/config/objspace.std.optimized_list_getitem.txt (contents, props changed) Log: add minimal docs for the new options. Added: pypy/dist/pypy/doc/config/objspace.std.logspaceoptypes.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/config/objspace.std.logspaceoptypes.txt Mon Apr 2 18:45:02 2007 @@ -0,0 +1,4 @@ +.. internal + +Wrap "simple" bytecode implementations like BINARY_ADD with code that collects +information about which types these bytecodes receive as arguments. Added: pypy/dist/pypy/doc/config/objspace.std.optimized_list_getitem.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/config/objspace.std.optimized_list_getitem.txt Mon Apr 2 18:45:02 2007 @@ -0,0 +1 @@ +Optimized list[int] a bit. From arigo at codespeak.net Mon Apr 2 22:13:03 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Apr 2007 22:13:03 +0200 (CEST) Subject: [pypy-svn] r41828 - pypy/dist/pypy/lib Message-ID: <20070402201303.655B510077@code0.codespeak.net> Author: arigo Date: Mon Apr 2 22:13:01 2007 New Revision: 41828 Modified: pypy/dist/pypy/lib/_formatting.py Log: A completely essential bug now fixed. Yippee! Modified: pypy/dist/pypy/lib/_formatting.py ============================================================================== --- pypy/dist/pypy/lib/_formatting.py (original) +++ pypy/dist/pypy/lib/_formatting.py Mon Apr 2 22:13:01 2007 @@ -173,7 +173,7 @@ class PercentFormatter(Formatter): def format(self): - return '%' + return self.std_wp('%') # isinf isn't too hard... def isinf(v): From arigo at codespeak.net Mon Apr 2 22:13:54 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Apr 2007 22:13:54 +0200 (CEST) Subject: [pypy-svn] r41829 - pypy/dist/pypy/objspace/std Message-ID: <20070402201354.A732F10077@code0.codespeak.net> Author: arigo Date: Mon Apr 2 22:13:51 2007 New Revision: 41829 Modified: pypy/dist/pypy/objspace/std/typeobject.py Log: A comment. Modified: pypy/dist/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/typeobject.py (original) +++ pypy/dist/pypy/objspace/std/typeobject.py Mon Apr 2 22:13:51 2007 @@ -267,6 +267,8 @@ w_value = w_self.dict_w.get(attr, None) if w_self.lazyloaders and w_value is None: if attr in w_self.lazyloaders: + # very clever next line: it forces the attr string + # to be interned. w_attr = space.new_interned_str(attr) loader = w_self.lazyloaders[attr] del w_self.lazyloaders[attr] From mwh at codespeak.net Tue Apr 3 12:23:48 2007 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 3 Apr 2007 12:23:48 +0200 (CEST) Subject: [pypy-svn] r41841 - pypy/dist/pypy/translator/goal Message-ID: <20070403102348.2E9C51007D@code0.codespeak.net> Author: mwh Date: Tue Apr 3 12:23:47 2007 New Revision: 41841 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: finally change bench-cronjob to reflect change in tproxy option name Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Tue Apr 3 12:23:47 2007 @@ -183,7 +183,7 @@ c--thread c--_objspace=taint c--_allworkingmodules - c--_with-transparent-proxy--_faassen + c--_objspace-std-withtproxy--_faassen c--gc=framework--_faassen c--_objspace-std-withrope cli From fijal at codespeak.net Tue Apr 3 16:07:46 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Apr 2007 16:07:46 +0200 (CEST) Subject: [pypy-svn] r41851 - in pypy/dist/pypy/translator/js: . jssrc test Message-ID: <20070403140746.504A11008A@code0.codespeak.net> Author: fijal Date: Tue Apr 3 16:07:44 2007 New Revision: 41851 Added: pypy/dist/pypy/translator/js/test/test_str.py Modified: pypy/dist/pypy/translator/js/_class.py pypy/dist/pypy/translator/js/function.py pypy/dist/pypy/translator/js/jsbuiltin.py pypy/dist/pypy/translator/js/jssrc/misc.js pypy/dist/pypy/translator/js/opcodes.py pypy/dist/pypy/translator/js/test/runtest.py pypy/dist/pypy/translator/js/test/test_rclass.py pypy/dist/pypy/translator/js/test/test_rpbc.py pypy/dist/pypy/translator/js/test/test_runtest.py Log: * A bit of wacking * A bit of skipping * bunch of new tests * improved testing machinery = we've got test_str, somehow working. Modified: pypy/dist/pypy/translator/js/_class.py ============================================================================== --- pypy/dist/pypy/translator/js/_class.py (original) +++ pypy/dist/pypy/translator/js/_class.py Tue Apr 3 16:07:44 2007 @@ -11,6 +11,7 @@ self.cts = db.genoo.TypeSystem(db) self.classdef = classdef self.name = classdef._name.replace('.', '_')#[-1] + self.real_name = classdef._name if not self.is_root(classdef): self.parent = self.db.pending_class(classdef._superclass) @@ -50,7 +51,7 @@ # begin to_String method ilasm.begin_method("toString", self.name, []) - ilasm.load_str("'<%s instance>'" % self.name) + ilasm.load_str("'<%s object>'" % self.real_name) ilasm.ret() ilasm.end_function() Modified: pypy/dist/pypy/translator/js/function.py ============================================================================== --- pypy/dist/pypy/translator/js/function.py (original) +++ pypy/dist/pypy/translator/js/function.py Tue Apr 3 16:07:44 2007 @@ -28,6 +28,8 @@ self.ilasm.load_local(v) elif isinstance(v, flowmodel.Constant): self.db.load_const(v.concretetype, v.value, self.ilasm) + elif isinstance(v, str): + self.ilasm.load_const("'" + v + "'") else: assert False Modified: pypy/dist/pypy/translator/js/jsbuiltin.py ============================================================================== --- pypy/dist/pypy/translator/js/jsbuiltin.py (original) +++ pypy/dist/pypy/translator/js/jsbuiltin.py Tue Apr 3 16:07:44 2007 @@ -42,8 +42,16 @@ 'll_substring' : CallBuiltin('substring'), 'll_lower' : lambda g, op: Call._render_builtin_method(g, 'toLowerCase', [op.args[1]]), 'll_upper' : lambda g, op: Call._render_builtin_method(g, 'toUpperCase', [op.args[1]]), - 'll_find' : lambda g, op: Call._render_builtin_method(g, 'search', [op.args[1], op.args[2]]), - 'll_find_char' : lambda g, op: Call._render_builtin_method(g, 'search', [op.args[1], op.args[2]]), + 'll_find' : CallBuiltin('findIndexOf'), + 'll_find_char' : CallBuiltin('findIndexOf'), + #'ll_find' : lambda g, op: Call._render_builtin_method(g, 'indexOf', [op.args[1], op.args[2], op.args[3]]), + #'ll_find_char' : lambda g, op: Call._render_builtin_method(g, 'indexOf', [op.args[1], op.args[2], op.args[3]]), + 'll_contains' : CallBuiltin('findIndexOfTrue'), + 'll_replace_chr_chr' : lambda g, op: + Call._render_builtin_method(g, 'replace', + [op.args[1], op.args[2], op.args[3], 'g']), + 'll_count_char' : CallBuiltin('countCharOf'), + 'll_count' : CallBuiltin('countOf'), }, ootype.List: { 'll_setitem_fast' : ListSetitem, Modified: pypy/dist/pypy/translator/js/jssrc/misc.js ============================================================================== --- pypy/dist/pypy/translator/js/jssrc/misc.js (original) +++ pypy/dist/pypy/translator/js/jssrc/misc.js Tue Apr 3 16:07:44 2007 @@ -175,4 +175,46 @@ delete(d[elem]); } } + +function findIndexOf(s1, s2, start, end) { + if (start > end || start > s1.length) { + return -1; + } + s1 = s1.substr(start, end-start); + res = s1.indexOf(s2); + if (res == -1) { + return -1; + } + return res + start; +} + +function findIndexOfTrue(s1, s2) { + return findIndexOf(s1, s2, 0, s1.length) != -1; +} + +function countCharOf(s, c, start, end) { + s = s.substring(start, end); + var i = 0; + for (c1 in s) { + if (s[c1] == c) { + i++; + } + } + return(i); +} + +function countOf(s, s1, start, end) { + var ret = findIndexOf(s, s1, start, end); + var i = 0; + var lgt = 1; + if (s1.length > 0) { + lgt = s1.length; + } + while (ret != -1) { + i++; + ret = findIndexOf(s, s1, ret + lgt, end); + } + return (i); +} + // ends hand written code Modified: pypy/dist/pypy/translator/js/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/js/opcodes.py (original) +++ pypy/dist/pypy/translator/js/opcodes.py Tue Apr 3 16:07:44 2007 @@ -130,6 +130,7 @@ 'oononnull' : [PushAllArgs,_Prefix('!!')], 'oostring' : [PushArg(0),CastString], 'ooparse_int' : [PushAllArgs,_CastFun("parseInt",2)], + 'ooparse_float' : [PushAllArgs,_CastFun("parseFloat",1)], 'oois' : '===', # when casting from bool we want that every truth value is casted # to 1: we can't simply DoNothing, because the CLI stack could Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Tue Apr 3 16:07:44 2007 @@ -1,6 +1,3 @@ -''' - Sests with DONT in front of them will probably not be fixed for the time being. -''' import py, os, re, subprocess from pypy.translator.translator import TranslationContext @@ -12,6 +9,7 @@ from pypy.conftest import option from pypy.rpython.test.tool import BaseRtypingTest, OORtypeMixin from pypy.rlib.nonconst import NonConstant +from pypy.rpython.ootypesystem import ootype from pypy.rpython.llinterp import LLException @@ -21,6 +19,9 @@ port = 8080 +class JSException(LLException): + pass + def _CLI_is_on_path(): if py.path.local.sysfind('js') is None: #we recommend Spidermonkey return False @@ -104,18 +105,22 @@ input = "load(%r);\n" % self.js.filename.strpath for call in self.function_calls[:-1]: input += "%s;\n" % call - input += "print(%s);\n" % self.function_calls[-1] + input += "print(\"'\" + %s + \"'\");\n" % self.function_calls[-1] js.stdin.write(input) stdout, stderr = js.communicate() output = (stderr + stdout).strip() for s in output.split('\n'): log(s) - return self.reinterpret(s) + m = re.match("'(.*)'", output, re.DOTALL) + if not m: + log("Error: %s" % output) + raise JSException(output) + return self.reinterpret(m.group(1)) def reinterpret(cls, s): - while s.startswith(" "): - s = s[1:] # :-) quite inneficient, but who cares + #while s.startswith(" "): + # s = s[1:] # :-) quite inneficient, but who cares if s == 'false': res = False elif s == 'true': @@ -126,8 +131,6 @@ res = 1e300 * 1e300 elif s == 'NaN': res = (1e300 * 1e300) / (1e300 * 1e300) - elif s.startswith("uncaught exception:"): - raise LLException(str(s)) elif s.startswith('[') or s.startswith('('): l = s[1:-1].split(',') res = [cls.reinterpret(i) for i in l] @@ -144,6 +147,9 @@ class JsTest(BaseRtypingTest, OORtypeMixin): def _compile(self, _fn, args, policy=None): argnames = _fn.func_code.co_varnames[:_fn.func_code.co_argcount] + func_name = _fn.func_name + if func_name == '': + func_name = 'func' source = py.code.Source(""" def %s(): from pypy.rlib.nonconst import NonConstant @@ -152,10 +158,13 @@ return None else: return str(res)""" - % (_fn.func_name, ",".join(["%s=NonConstant(%s)" % (name,i) for + % (func_name, ",".join(["%s=NonConstant(%r)" % (name, i) for name, i in zip(argnames, args)]))) exec source.compile() in locals() - return compile_function(locals()[_fn.func_name], [], policy=policy) + return compile_function(locals()[func_name], [], policy=policy) + + def string_to_ll(self, s): + return s def interpret(self, fn, args, policy=None): f = self._compile(fn, args, policy) @@ -168,7 +177,7 @@ #import pdb; pdb.set_trace() try: res = self.interpret(fn, args) - except LLException, e: + except JSException, e: s = e.args[0] assert s.startswith('uncaught exception:') assert re.search(str(exception), s) @@ -180,7 +189,7 @@ # assert False, 'function did raise no exception at all' def ll_to_string(self, s): - return s + return str(s) def ll_to_list(self, l): return l Modified: pypy/dist/pypy/translator/js/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_rclass.py (original) +++ pypy/dist/pypy/translator/js/test/test_rclass.py Tue Apr 3 16:07:44 2007 @@ -73,11 +73,3 @@ def test_isinstance(self): py.test.skip("WIP") -#class TestJsPBC(JsTest, BaseTestRPBC): -# pass -## -#class TestJsRtuple(JsTest, BaseTestRtuple): -# pass -## -#class TestJsStr(JsTest, BaseTestRstr): -# pass Modified: pypy/dist/pypy/translator/js/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_rpbc.py (original) +++ pypy/dist/pypy/translator/js/test/test_rpbc.py Tue Apr 3 16:07:44 2007 @@ -35,5 +35,6 @@ def test_conv_from_None(self): py.test.skip("WIP") - - + def test_multiple_ll_one_hl_op(self): + py.test.skip("XXX fix me soon") + Modified: pypy/dist/pypy/translator/js/test/test_runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_runtest.py (original) +++ pypy/dist/pypy/translator/js/test/test_runtest.py Tue Apr 3 16:07:44 2007 @@ -56,6 +56,12 @@ assert rp('[a,b]') == ["a", "b"] #assert rp('(true,[a,b])') == [True, ["a", "b"]] +def test_return_newline(): + def fun_newline(): + return "\n" + fun = compile_function(fun_newline, []) + assert fun() == "\n" + ##def test_multiple_function(): ## def one(): ## return 1 Added: pypy/dist/pypy/translator/js/test/test_str.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js/test/test_str.py Tue Apr 3 16:07:44 2007 @@ -0,0 +1,63 @@ + +import py +from pypy.translator.js.test.runtest import JsTest +import pypy.translator.oosupport.test_template.string as oostring + +class TestJsString(JsTest, oostring.BaseTestString): + def test_unichar_const(self): + py.test.skip("Cannot test it yet") + + def test_unichar_eq(self): + py.test.skip("Cannot test it yet") + + def test_unichar_ord(self): + py.test.skip("Cannot test it yet") + + def test_unichar_hash(self): + py.test.skip("Cannot test it yet") + + def test_rfind(self): + py.test.skip("Not implemented") + + def test_rfind_empty_string(self): + py.test.skip("Not implemented") + + def test_find_char(self): + py.test.skip("Not implemented") + + def test_strip(self): + py.test.skip("Not implemented") + + def test_upper(self): + #XXX Testing machinery is quite confused by js print + strings = ['', ' ', 'upper', 'UpPeR', ',uppEr,'] + #for i in range(256): + # if chr(i) != "\x00" and chr(i) != '(' and chr(i) != '[': + # strings.append(chr(i)) + def fn(i): + return strings[i].upper() + for i in range(len(strings)): + res = self.interpret(fn, [i]) + assert self.ll_to_string(res) == fn(i) + + def test_lower(self): + #XXX Testing machinery is quite confused by js print + strings = ['', ' ', 'lower', 'LoWeR', ',lowEr,'] + #for i in range(256): strings.append(chr(i)) + def fn(i): + return strings[i].lower() + for i in range(len(strings)): + res = self.interpret(fn, [i]) + assert self.ll_to_string(res) == fn(i) + + def test_strformat(self): + py.test.skip("string formatting not implemented for base different than 10") + + def test_float(self): + py.test.skip("returning NaN instead of raising ValueError") + + def test_hash(self): + py.test.skip("Not implemented") + + def test_hash_value(self): + py.test.skip("Not implemented") From fijal at codespeak.net Tue Apr 3 16:33:46 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Apr 2007 16:33:46 +0200 (CEST) Subject: [pypy-svn] r41852 - pypy/dist/pypy/doc Message-ID: <20070403143346.C4AAC1008A@code0.codespeak.net> Author: fijal Date: Tue Apr 3 16:33:44 2007 New Revision: 41852 Modified: pypy/dist/pypy/doc/jit.txt Log: Add a bit about integer arithmetics Modified: pypy/dist/pypy/doc/jit.txt ============================================================================== --- pypy/dist/pypy/doc/jit.txt (original) +++ pypy/dist/pypy/doc/jit.txt Tue Apr 3 16:33:44 2007 @@ -31,8 +31,8 @@ --------------- So far there is little point in trying the JIT on anything else than -arithmetic-intensive functions (unless you want to help find bugs). For -small examples, you can also look at the machine code it produces, but +integer arithmetic-intensive functions (unless you want to help find bugs). +For small examples, you can also look at the machine code it produces, but if you do please keep in mind that the assembler will look fundamentally different after we extend the range of PyPy that the JIT generator processes. From fijal at codespeak.net Tue Apr 3 16:40:39 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Apr 2007 16:40:39 +0200 (CEST) Subject: [pypy-svn] r41853 - pypy/dist/pypy/translator/js/examples/test Message-ID: <20070403144039.E9E411008A@code0.codespeak.net> Author: fijal Date: Tue Apr 3 16:40:38 2007 New Revision: 41853 Modified: pypy/dist/pypy/translator/js/examples/test/test_examples.py Log: Add a test that pings play1. Unsure how to do it better. Modified: pypy/dist/pypy/translator/js/examples/test/test_examples.py ============================================================================== --- pypy/dist/pypy/translator/js/examples/test/test_examples.py (original) +++ pypy/dist/pypy/translator/js/examples/test/test_examples.py Tue Apr 3 16:40:38 2007 @@ -30,3 +30,9 @@ from pypy.translator.js.examples.console import console, client assert rpython2javascript(client, console.FUNCTION_LIST, use_pdb=False) + +def test_ping_play1(): + from urllib import URLopener + u = URLopener() + text = "pypy.js various demos" + assert u.open("http://play1.pypy.org/").read().find(text) != -1 From arigo at codespeak.net Tue Apr 3 16:41:57 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 3 Apr 2007 16:41:57 +0200 (CEST) Subject: [pypy-svn] r41854 - pypy/extradoc/pypy.org Message-ID: <20070403144157.3B1311008A@code0.codespeak.net> Author: arigo Date: Tue Apr 3 16:41:56 2007 New Revision: 41854 Modified: pypy/extradoc/pypy.org/news.txt Log: Fix the release announcement links (thanks xoraxax). Modified: pypy/extradoc/pypy.org/news.txt ============================================================================== --- pypy/extradoc/pypy.org/news.txt (original) +++ pypy/extradoc/pypy.org/news.txt Tue Apr 3 16:41:56 2007 @@ -2,7 +2,9 @@ ------------------------------------------------------------------ We are proud to release PyPy 1.0.0, our sixth public release. See -the `release announcement `__ to read about the +the `release announcement +`__ +to read about the many new features in this release, especially the results of our JIT generation technology. See also our detailed instructions on how to `get started`_. *(March 27th, 2007)* @@ -13,7 +15,9 @@ ------------------------------------------------------------------- We are proud to release PyPy 0.99.0, our fifth public release. See -the `release announcement `__ to read about the +the `release announcement +`__ +to read about the many new features in this release. See also our detailed instructions on how to `get started`_. *(February 17th, 2007)* From arigo at codespeak.net Tue Apr 3 18:44:58 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 3 Apr 2007 18:44:58 +0200 (CEST) Subject: [pypy-svn] r41859 - pypy/dist/pypy/doc Message-ID: <20070403164458.4E98E1007C@code0.codespeak.net> Author: arigo Date: Tue Apr 3 18:44:57 2007 New Revision: 41859 Modified: pypy/dist/pypy/doc/cleanup-todo.txt Log: Unicode strings in RPython! Modified: pypy/dist/pypy/doc/cleanup-todo.txt ============================================================================== --- pypy/dist/pypy/doc/cleanup-todo.txt (original) +++ pypy/dist/pypy/doc/cleanup-todo.txt Tue Apr 3 18:44:57 2007 @@ -25,6 +25,7 @@ https://codespeak.net/issue/pypy-dev/issue303 and the fact that we can have more than one translator/annotator around (with the timeshifter) + - unicode strings in RPython interpreter ----------- @@ -32,4 +33,4 @@ - review the things implemented at applevel whether they are performance- critical - - review threading (especially GIL). It's segfaulting quite often now. \ No newline at end of file + - review threading (especially GIL). It's segfaulting quite often now. From fijal at codespeak.net Wed Apr 4 09:29:24 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Apr 2007 09:29:24 +0200 (CEST) Subject: [pypy-svn] r41880 - pypy/dist/pypy/translator/js/test Message-ID: <20070404072924.ADB3D1005A@code0.codespeak.net> Author: fijal Date: Wed Apr 4 09:29:22 2007 New Revision: 41880 Modified: pypy/dist/pypy/translator/js/test/runtest.py pypy/dist/pypy/translator/js/test/test_class.py pypy/dist/pypy/translator/js/test/test_rlist.py Log: Few fixes regarding new way of displaying objects. Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Wed Apr 4 09:29:22 2007 @@ -199,10 +199,10 @@ return tuple(t) def class_name(self, value): - return value[:-10].split('_')[-1] + return value[:-8].split('.')[-1] def is_of_instance_type(self, val): - m = re.match("^<.* instance>$", val) + m = re.match("^<.* object>$", val) return bool(m) def read_attr(self, obj, name): Modified: pypy/dist/pypy/translator/js/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_class.py (original) +++ pypy/dist/pypy/translator/js/test/test_class.py Wed Apr 4 09:29:22 2007 @@ -136,11 +136,11 @@ return str(C()) fn = compile_function(instance_str, []) - assert fn() == '' + assert fn() == '' def test_instance_ret(): def instance_ret(): return str(C()) fn = compile_function(instance_ret, []) - assert fn() == '' + assert fn() == '' Modified: pypy/dist/pypy/translator/js/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_rlist.py (original) +++ pypy/dist/pypy/translator/js/test/test_rlist.py Wed Apr 4 09:29:22 2007 @@ -79,5 +79,5 @@ x = l2.pop() return str(x)+";"+str(l) res = self.ll_to_string(self.interpret(fn, [])) - res = res.replace('pypy_translator_js_test_test_rlist_', '') - assert res == ';[, , , , ]' + res = res.replace('pypy.translator.js.test.test_rlist.', '') + assert res == ';[, , , , ]' From niko at codespeak.net Wed Apr 4 09:52:52 2007 From: niko at codespeak.net (niko at codespeak.net) Date: Wed, 4 Apr 2007 09:52:52 +0200 (CEST) Subject: [pypy-svn] r41882 - in pypy/dist/pypy/translator/jvm: . src/pypy test Message-ID: <20070404075252.19C0C10060@code0.codespeak.net> Author: niko Date: Wed Apr 4 09:52:50 2007 New Revision: 41882 Added: pypy/dist/pypy/translator/jvm/src/pypy/Callback.java pypy/dist/pypy/translator/jvm/src/pypy/CustomDict.java pypy/dist/pypy/translator/jvm/src/pypy/Equals.java pypy/dist/pypy/translator/jvm/src/pypy/Filter.java pypy/dist/pypy/translator/jvm/src/pypy/FilterIterator.java pypy/dist/pypy/translator/jvm/src/pypy/FilterSet.java pypy/dist/pypy/translator/jvm/src/pypy/HashCode.java pypy/dist/pypy/translator/jvm/test/test_objectmodel.py Modified: pypy/dist/pypy/translator/jvm/ (props changed) pypy/dist/pypy/translator/jvm/builtin.py pypy/dist/pypy/translator/jvm/constant.py pypy/dist/pypy/translator/jvm/database.py pypy/dist/pypy/translator/jvm/generator.py pypy/dist/pypy/translator/jvm/genjvm.py pypy/dist/pypy/translator/jvm/metavm.py pypy/dist/pypy/translator/jvm/node.py pypy/dist/pypy/translator/jvm/opcodes.py pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java pypy/dist/pypy/translator/jvm/test/test_dict.py pypy/dist/pypy/translator/jvm/test/test_snippet.py pypy/dist/pypy/translator/jvm/typesystem.py Log: Implement custom dicts (rdicts) in the JVM backend. All tests in objectmodel now pass. The technique is to find all functions which could be used as hashCode() or equals() functions, and to make any static functions that are defined implement either pypy.Equals or pypy.HashCode, then allowing them to be passed to pypy.CustomDict. Modified: pypy/dist/pypy/translator/jvm/builtin.py ============================================================================== --- pypy/dist/pypy/translator/jvm/builtin.py (original) +++ pypy/dist/pypy/translator/jvm/builtin.py Wed Apr 4 09:52:50 2007 @@ -3,7 +3,8 @@ from pypy.rpython.ootypesystem import ootype from pypy.translator.jvm.typesystem import \ jInt, jVoid, jStringBuilder, jString, jPyPy, jChar, jArrayList, jObject, \ - jBool, jHashMap, jPyPyDictItemsIterator, Generifier, jCharSequence + jBool, jHashMap, jPyPyDictItemsIterator, Generifier, jCharSequence, \ + jPyPyCustomDict # ______________________________________________________________________ # Mapping of built-in OOTypes to JVM types @@ -128,6 +129,21 @@ (ootype.Dict, "ll_clear"): jvmgen.Method.v(jHashMap, "clear", (), jVoid), + (ootype.CustomDict, "ll_set"): + jvmgen.Method.v(jPyPyCustomDict, "put", (jObject, jObject), jObject), + + (ootype.CustomDict, "ll_get"): + jvmgen.Method.v(jPyPyCustomDict, "get", (jObject,), jObject), + + (ootype.CustomDict, "ll_contains"): + jvmgen.Method.v(jPyPyCustomDict, "containsKey", (jObject,), jBool), + + (ootype.CustomDict, "ll_length"): + jvmgen.Method.v(jPyPyCustomDict, "size", (), jInt), + + (ootype.CustomDict, "ll_clear"): + jvmgen.Method.v(jPyPyCustomDict, "clear", (), jVoid), + (ootype.List, "ll_length"): jvmgen.Method.v(jArrayList, "size", (), jInt), Modified: pypy/dist/pypy/translator/jvm/constant.py ============================================================================== --- pypy/dist/pypy/translator/jvm/constant.py (original) +++ pypy/dist/pypy/translator/jvm/constant.py Wed Apr 4 09:52:50 2007 @@ -1,9 +1,9 @@ from pypy.rpython.ootypesystem import ootype from pypy.translator.jvm.generator import \ - Field, Method + Field, Method, CUSTOMDICTMAKE from pypy.translator.oosupport.constant import \ BaseConstantGenerator, RecordConst, InstanceConst, ClassConst, \ - StaticMethodConst + StaticMethodConst, CustomDictConst from pypy.translator.jvm.typesystem import \ jPyPyConst, jObject, jVoid @@ -63,7 +63,8 @@ self.delegate_impl = None return StaticMethodConst.record_dependencies(self) - self.delegate_impl = self.db.record_delegate_impl(self.value.graph) + self.delegate_impl = self.db.record_delegate_standalone_func_impl( + self.value.graph) def create_pointer(self, gen): if self.delegate_impl: @@ -74,3 +75,20 @@ def initialize_data(self, ilasm): return +class JVMCustomDictConst(CustomDictConst): + + def record_dependencies(self): + # Near as I can tell, self.value is an ootype._custom_dict, + # key_eq is a Python function and graph is, well, a method + # graph that seems to be added to the function pointer + # somewhere. Adapted from cli/constant.py + self.eq_jcls = self.db.record_delegate_standalone_func_impl( + self.value._dict.key_eq.graph) + self.hash_jcls = self.db.record_delegate_standalone_func_impl( + self.value._dict.key_hash.graph) + + def create_pointer(self, gen): + gen.new_with_jtype(self.eq_jcls) + gen.new_with_jtype(self.hash_jcls) + gen.emit(CUSTOMDICTMAKE) + Modified: pypy/dist/pypy/translator/jvm/database.py ============================================================================== --- pypy/dist/pypy/translator/jvm/database.py (original) +++ pypy/dist/pypy/translator/jvm/database.py Wed Apr 4 09:52:50 2007 @@ -32,7 +32,10 @@ self._functions = {} # graph -> jvmgen.Method # (jargtypes, jrettype) -> node.StaticMethodInterface - self._delegates = {} + self._delegates = {} + + # (INSTANCE, method_name) -> node.StaticMethodImplementation + self._bound_methods = {} self._function_names = {} # graph --> function_name @@ -235,12 +238,27 @@ return res def record_delegate(self, TYPE): - """ TYPE is a StaticMethod """ + """ + Creates and returns a StaticMethodInterface type; this type + represents an abstract base class for functions with a given + signature, represented by TYPE, a ootype.StaticMethod + instance. + """ # Translate argument/return types into java types, check if # we already have such a delegate: - jargs = tuple([self.lltype_to_cts(ARG) for ARG in TYPE.ARGS]) + jargs = tuple([self.lltype_to_cts(ARG) for ARG in TYPE.ARGS + if ARG is not ootype.Void]) jret = self.lltype_to_cts(TYPE.RESULT) + return self.record_delegate_sig(jargs, jret) + + def record_delegate_sig(self, jargs, jret): + """ + Like record_delegate, but the signature is in terms of java + types. jargs is a list of JvmTypes, one for each argument, + and jret is a JvmType. Note that jargs does NOT include an + entry for the this pointer of the resulting object. + """ key = (jargs, jret) if key in self._delegates: return self._delegates[key] @@ -250,19 +268,42 @@ name = self._pkg(self._uniq('Delegate')) # Create a new one if we do not: - interface = node.StaticMethodInterface(name, TYPE, jargs, jret) + interface = node.StaticMethodInterface(name, jargs, jret) self._delegates[key] = interface self.pending_node(interface) return interface - def record_delegate_impl(self, graph): - """ TYPE is a StaticMethod """ + def record_delegate_standalone_func_impl(self, graph): + """ + Creates a class with an invoke() method that invokes the given + graph. This object can be used as a function pointer. It + will extend the appropriate delegate for the graph's + signature. + """ jargtypes, jrettype = self.types_for_graph(graph) - key = (jargtypes, jrettype) - assert key in self._delegates + super_class = self.record_delegate_sig(jargtypes, jrettype) pfunc = self.pending_function(graph) implnm = self._pkg(self._uniq(graph.name+'_delegate')) - n = node.StaticMethodImplementation(implnm, self._delegates[key], pfunc) + n = node.StaticMethodImplementation(implnm, super_class, None, pfunc) + self.pending_node(n) + return n + + def record_delegate_bound_method_impl(self, INSTANCE, method_name): + """ + Creates an object with an invoke() method which invokes + a method named method_name on an instance of INSTANCE. + """ + key = (INSTANCE, method_name) + if key in self._bound_methods: + return self._bound_methods[key] + METH_TYPE = INSTANCE._lookup(method_name)[1]._TYPE + super_class = self.record_delegate(METH_TYPE) + self_class = self.lltype_to_cts(INSTANCE) + mthd_obj = self_class.lookup_method(method_name) + implnm = self._pkg(self._uniq( + self_class.simple_name()+"_"+method_name+"_delegate")) + n = self._bound_methods[key] = node.StaticMethodImplementation( + implnm, super_class, self_class, mthd_obj) self.pending_node(n) return n @@ -338,6 +379,7 @@ ootype.List: jvmtype.jArrayList, ootype.Dict: jvmtype.jHashMap, ootype.DictItemsIterator:jvmtype.jPyPyDictItemsIterator, + ootype.CustomDict: jvmtype.jPyPyCustomDict, } def lltype_to_cts(self, OOT): Modified: pypy/dist/pypy/translator/jvm/generator.py ============================================================================== --- pypy/dist/pypy/translator/jvm/generator.py (original) +++ pypy/dist/pypy/translator/jvm/generator.py Wed Apr 4 09:52:50 2007 @@ -10,7 +10,8 @@ jPyPy, jVoid, jMath, desc_for_method, jPrintStream, jClass, jChar, \ jObject, jByteArray, jPyPyExcWrap, jIntegerClass, jLongClass, \ jDoubleClass, jCharClass, jStringBuilder, JvmScalarType, jArrayList, \ - jObjectArray, jPyPyInterlink + jObjectArray, jPyPyInterlink, jPyPyCustomDict, jPyPyEquals, \ + jPyPyHashCode, jMap # ___________________________________________________________________________ # Miscellaneous helper functions @@ -176,6 +177,7 @@ INVOKESTATIC = Opcode('invokestatic') INVOKEVIRTUAL = Opcode('invokevirtual') INVOKESPECIAL = Opcode('invokespecial') +INVOKEINTERFACE = Opcode('invokeinterface') # Other opcodes LDC = Opcode('ldc') # single-word types @@ -293,11 +295,15 @@ not the this ptr 'rettype' - JvmType for return type """ - assert isinstance(classty, JvmType) classnm = classty.name - return Method(classnm, methnm, argtypes, rettype, opcode=INVOKEVIRTUAL) + if isinstance(classty, jvmtype.JvmInterfaceType): + opc = INVOKEINTERFACE + else: + assert isinstance(classty, jvmtype.JvmClassType) + opc = INVOKEVIRTUAL + return Method(classnm, methnm, argtypes, rettype, opcode=opc) v = staticmethod(v) - + # Create a static method: def s(classty, methnm, argtypes, rettype): """ @@ -329,9 +335,14 @@ def is_static(self): return self.opcode == INVOKESTATIC def jasmin_syntax(self): - return "%s/%s%s" % (self.class_name.replace('.','/'), - self.method_name, - self.descriptor) + res = "%s/%s%s" % (self.class_name.replace('.','/'), + self.method_name, + self.descriptor) + # A weird, inexplicable quirk of Jasmin syntax is that it requires + # the number of arguments after an invokeinterface call: + if self.opcode == INVOKEINTERFACE: + res += " %d" % (len(self.argument_types),) + return res OBJHASHCODE = Method.v(jObject, 'hashCode', (), jInt) OBJTOSTRING = Method.v(jObject, 'toString', (), jString) @@ -375,6 +386,8 @@ OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass) CLASSGETNAME = Method.v(jClass, 'getName', (), jString) EXCWRAPWRAP = Method.s(jPyPyExcWrap, 'wrap', (jObject,), jPyPyExcWrap) +CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make', + (jPyPyEquals, jPyPyHashCode), jPyPyCustomDict) # ___________________________________________________________________________ # Fields @@ -594,9 +607,9 @@ The correct opcode and their types depends on the opcode. """ unimplemented - def return_val(self, vartype): - """ Returns a value from top of stack of the JvmType 'vartype' """ - self._instr(RETURN.for_type(vartype)) + def return_val(self, jtype): + """ Returns a value from top of stack of the JvmType 'jtype' """ + self._instr(RETURN.for_type(jtype)) def load_class_name(self): """ Loads the name of the *Java* class of the object on the top of @@ -681,6 +694,9 @@ def prepare_generic_argument(self, ITEMTYPE): jty = self.db.lltype_to_cts(ITEMTYPE) + self.prepare_generic_argument_with_jtype(jty) + + def prepare_generic_argument_with_jtype(self, jty): if jty is jvmtype.jVoid: self.emit(ACONST_NULL) elif isinstance(jty, JvmScalarType): @@ -688,6 +704,9 @@ def prepare_generic_result(self, ITEMTYPE): jresty = self.db.lltype_to_cts(ITEMTYPE) + self.prepare_generic_result_with_jtype(jresty) + + def prepare_generic_result_with_jtype(self, jresty): if jresty is jvmtype.jVoid: self.emit(POP) elif isinstance(jresty, JvmScalarType): @@ -696,7 +715,7 @@ self.unbox_value(jresty) else: # Perform any casting required: - self.downcast(ITEMTYPE) + self.downcast_jtype(jresty) def box_value(self, jscalartype): """ Assuming that an value of type jscalartype is on the stack, Modified: pypy/dist/pypy/translator/jvm/genjvm.py ============================================================================== --- pypy/dist/pypy/translator/jvm/genjvm.py (original) +++ pypy/dist/pypy/translator/jvm/genjvm.py Wed Apr 4 09:52:50 2007 @@ -18,7 +18,7 @@ from pypy.translator.jvm.opcodes import opcodes from pypy.rpython.ootypesystem import ootype from pypy.translator.jvm.constant import \ - JVMConstantGenerator, JVMStaticMethodConst + JVMConstantGenerator, JVMStaticMethodConst, JVMCustomDictConst from pypy.translator.jvm.prebuiltnodes import create_interlink_node class JvmError(Exception): @@ -128,10 +128,18 @@ print "... completed!" self.compiled = True - self._compile_helper(('DictItemsIterator', - 'PyPy', + self._compile_helper(('Callback', + 'CustomDict', + 'DictItemsIterator', + 'Equals', 'ExceptionWrapper', - 'Interlink')) + 'Filter', + 'FilterIterator', + 'FilterSet', + 'HashCode', + 'Interlink', + 'PyPy', + )) def _make_str(self, a): if isinstance(a, ootype._string): @@ -199,6 +207,7 @@ log = log ConstantGenerator = JVMConstantGenerator + CustomDictConst = JVMCustomDictConst StaticMethodConst = JVMStaticMethodConst def __init__(self, tmpdir, translator, entrypoint): Modified: pypy/dist/pypy/translator/jvm/metavm.py ============================================================================== --- pypy/dist/pypy/translator/jvm/metavm.py (original) +++ pypy/dist/pypy/translator/jvm/metavm.py Wed Apr 4 09:52:50 2007 @@ -89,3 +89,28 @@ gen.try_catch_region(self.java_exc, trylbl, catchlbl, catchlbl) +class _NewCustomDict(MicroInstruction): + def _load_func(self, gen, fn, obj, method_name): + db = gen.db + if fn.value: + # Standalone function: find the delegate class and + # instantiate it. + assert method_name.value is None + smimpl = fn.value.concretize().value # ootype._static_meth + db.record_delegate(smimpl._TYPE) # _TYPE is a StaticMethod + ty = db.record_delegate_standalone_func_impl(smimpl.graph) + gen.new_with_jtype(ty) + else: + # Bound method: create a wrapper bound to the given + # object, using the "bind()" static method that bound + # method wrapper classes have. + INSTANCE = obj.concretetype + method_name = method_name.value + ty = db.record_delegate_bound_method_impl(INSTANCE, method_name) + gen.load(obj) + gen.emit(ty.bind_method) + def render(self, generator, op): + self._load_func(generator, *op.args[1:4]) + self._load_func(generator, *op.args[4:7]) + generator.emit(jvmgen.CUSTOMDICTMAKE) +NewCustomDict = _NewCustomDict() Modified: pypy/dist/pypy/translator/jvm/node.py ============================================================================== --- pypy/dist/pypy/translator/jvm/node.py (original) +++ pypy/dist/pypy/translator/jvm/node.py Wed Apr 4 09:52:50 2007 @@ -13,7 +13,6 @@ interface defined by database.JvmType. """ - from pypy.objspace.flow import \ model as flowmodel from pypy.rpython.lltypesystem import \ @@ -22,7 +21,7 @@ ootype, rclass from pypy.translator.jvm.typesystem import \ JvmClassType, jString, jStringArray, jVoid, jThrowable, jInt, jPyPyMain, \ - jObject, JvmType, jStringBuilder, jPyPyInterlink + jObject, JvmType, jStringBuilder, jPyPyInterlink, jCallbackInterfaces from pypy.translator.jvm.opcodes import \ opcodes from pypy.translator.jvm.option import \ @@ -359,20 +358,27 @@ abstract class Foo { public abstract ReturnType invoke(Arg1, Arg2, ...); } - + + Depending on the signature of Arg1, Arg2, and ReturnType, this + abstract class may have additional methods and may implement + interfaces such as PyPy.Equals or PyPy.HashCode. This is to allow + it to interface with the the standalone Java code. See + the pypy.Callback interface for more information. """ - def __init__(self, name, STATIC_METHOD, jargtypes, jrettype): + def __init__(self, name, jargtypes, jrettype): """ argtypes: list of JvmTypes rettype: JvmType """ JvmClassType.__init__(self, name) - self.STATIC_METHOD = STATIC_METHOD assert isinstance(jrettype, JvmType) self.java_argument_types = [self] + list(jargtypes) self.java_return_type = jrettype self.dump_method = ConstantStringDumpMethod( self, "StaticMethodInterface") + self.invoke_method_obj = jvmgen.Method.v( + self, 'invoke', + self.java_argument_types[1:], self.java_return_type) def lookup_field(self, fieldnm): """ Given a field name, returns a jvmgen.Field object """ @@ -381,18 +387,58 @@ """ Given the method name, returns a jvmgen.Method object """ assert isinstance(self.java_return_type, JvmType) if methodnm == 'invoke': - return jvmgen.Method.v( - self, 'invoke', - self.java_argument_types[1:], self.java_return_type) + return self.invoke_method_obj raise KeyError(methodnm) # only one method def render(self, gen): assert isinstance(self.java_return_type, JvmType) + + # Scan through the jCallbackInterfaces and look for any + # that apply. + for jci in jCallbackInterfaces: + if jci.matches(self.java_argument_types[1:], self.java_return_type): + break + else: + jci = None + gen.begin_class(self, jObject, abstract=True) + if jci: gen.implements(jci) gen.begin_constructor() gen.end_constructor() + gen.begin_function('invoke', [], self.java_argument_types, self.java_return_type, abstract=True) gen.end_function() + + # Because methods in the JVM are identified by both their name + # and static signature, we need to create a dummy "invoke" + # method if the Java callback interface argument types don't + # match the actual types for this method. For example, the + # equals interface has the static signature + # "(Object,Object)=>boolean", but there may be static methods + # with some signature "(X,Y)=>boolean" where X and Y are other + # types. In that case, we create an adaptor method like: + # + # boolean invoke(Object x, Object y) { + # return invoke((X)x, (Y)y); + # } + if (jci and + (jci.java_argument_types != self.java_argument_types[1:] or + jci.java_return_type != self.java_return_type)): + + jci_jargs = [self] + list(jci.java_argument_types) + jci_ret = jci.java_return_type + gen.begin_function('invoke', [], jci_jargs, jci_ret) + idx = 0 + for jci_arg, self_arg in zip(jci_jargs, self.java_argument_types): + gen.load_jvm_var(jci_arg, idx) + if jci_arg != self_arg: + gen.prepare_generic_result_with_jtype(self_arg) + idx += jci_arg.descriptor.type_width() + gen.emit(self.invoke_method_obj) + assert jci_ret == self.java_return_type # no variance here currently + gen.return_val(jci_ret) + gen.end_function() + gen.end_class() class StaticMethodImplementation(Node, JvmClassType): @@ -406,26 +452,81 @@ return SomeStaticClass.StaticMethod(Arg1, Arg2); } } + + If the bound_to_jty argument is not None, then this class + represents a bound method, and looks something like: + + class Bar extends Foo { + Qux bound_to; + public static Bar bind(Qux to) { + Bar b = new Bar(); + b.bound_to = to; + return b; + } + public ReturnType invoke(Arg1, Arg2) { + return bound_to.SomeMethod(Arg1, Arg2); + } + } """ - def __init__(self, name, interface, impl_method): - JvmClassType.__init__(self, name) - self.super_class = interface + def __init__(self, name, super_class, bound_to_jty, impl_method): + JvmClassType.__init__(self, name) + self.super_class = super_class self.impl_method = impl_method self.dump_method = ConstantStringDumpMethod( self, "StaticMethodImplementation") + + if bound_to_jty: + self.bound_to_jty = bound_to_jty + self.bound_to_fld = jvmgen.Field( + self.name, 'bound_to', bound_to_jty, False) + self.bind_method = jvmgen.Method.s( + self, 'bind', (self.bound_to_jty,), self) + else: + self.bound_to_jty = None + self.bound_to_fld = None + self.bind_method = None + def lookup_field(self, fieldnm): - """ Given a field name, returns a jvmgen.Field object """ + if self.bound_to_fld and fieldnm == self.bound_to_fld.name: + return self.bound_to_fld return self.super_class.lookup_field(fieldnm) def lookup_method(self, methodnm): - """ Given the method name, returns a jvmgen.Method object """ + if self.bind_method and methodnm == 'bind': + return self.bind_method return self.super_class.lookup_method(methodnm) def render(self, gen): gen.begin_class(self, self.super_class) + + if self.bound_to_fld: + gen.add_field(self.bound_to_fld) + gen.begin_constructor() gen.end_constructor() + + # Emit the "bind" function which creates an instance if there is + # a bound field: + if self.bound_to_jty: + assert self.bound_to_fld and self.bind_method + gen.begin_function( + 'bind', [], (self.bound_to_jty,), self, static=True) + gen.new_with_jtype(self) + gen.emit(jvmgen.DUP) + gen.load_jvm_var(self.bound_to_jty, 0) + self.bound_to_fld.store(gen) + gen.return_val(self) + gen.end_function() + + # Emit the invoke() function, which just re-pushes the + # arguments and then invokes either the (possibly static) + # method self.impl_method. Note that if we are bound to an + # instance, we push that as the this pointer for + # self.impl_method. gen.begin_function('invoke', [], self.super_class.java_argument_types, self.super_class.java_return_type) + if self.bound_to_fld: + gen.load_jvm_var(self, 0) + gen.emit(self.bound_to_fld) for i in range(len(self.super_class.java_argument_types)): if not i: continue # skip the this ptr gen.load_function_argument(i) @@ -457,6 +558,11 @@ # attributes: name, method() and render(). Usually, this is a # Function object, but in some subclasses it is not. + def simple_name(self): + dot = self.name.rfind('.') + if dot == -1: return self.name + return self.name[dot+1:] + def set_super_class(self, supercls): self.super_class = supercls Modified: pypy/dist/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/opcodes.py (original) +++ pypy/dist/pypy/translator/jvm/opcodes.py Wed Apr 4 09:52:50 2007 @@ -9,7 +9,7 @@ PushArg, PushAllArgs, StoreResult, InstructionList, New, DoNothing, Call,\ SetField, GetField, DownCast, RuntimeNew, OOString, CastTo from pypy.translator.jvm.metavm import \ - IndirectCall, JvmCallMethod, TranslateException + IndirectCall, JvmCallMethod, TranslateException, NewCustomDict import pypy.translator.jvm.generator as jvmgen import pypy.translator.jvm.typesystem as jvmtype @@ -53,10 +53,10 @@ 'oohash': [PushAllArgs, jvmgen.OBJHASHCODE, StoreResult], 'oostring': [OOString, StoreResult], #'ooparse_int': [PushAllArgs, 'call int32 [pypylib]pypy.runtime.Utils::OOParseInt(string, int32)'], - #'oonewcustomdict': [NewCustomDict], + 'oonewcustomdict': [NewCustomDict, StoreResult], # 'same_as': DoNothing, - #'hint': [PushArg(0), StoreResult], + 'hint': [PushArg(0), StoreResult], 'direct_call': [Call, StoreResult], 'indirect_call': [PushAllArgs, IndirectCall, StoreResult], # Added: pypy/dist/pypy/translator/jvm/src/pypy/Callback.java ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/src/pypy/Callback.java Wed Apr 4 09:52:50 2007 @@ -0,0 +1,26 @@ +package pypy; + +/** + * This interface has no function but to serve as a documentation + * point and marker. All the interfaces which inherit from it are + * "callback" interfaces: that means that they are used to allow the + * standalone Java code to invoke methods defined in the RPython code. + * + * Whenever a standalone RPython module has a signature that might + * fit as one of the appropriate callbacks, it simply implements required + * interface. Note that these callback interfaces are simply hard-coded + * into database. A more flexible mechanism may eventually be required. + * + * As an example, consider {@link HashCode}. Any time that we generate + * a standalone method which returns a signed integer and takes a single + * object, we cause it to implement {@link HashCode}, which then allows it + * to be used in an {@link #RDict}. + * + * These callback functions are hard-coded in jvm/typesystem.py. To add + * new ones simply add items to the list. + * + * @author Niko Matsakis + */ +public interface Callback { + +} Added: pypy/dist/pypy/translator/jvm/src/pypy/CustomDict.java ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/src/pypy/CustomDict.java Wed Apr 4 09:52:50 2007 @@ -0,0 +1,145 @@ +package pypy; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Iterator; +import java.util.Set; + +/** + * An implementation of the Map interface where the hashcode and + * equals methods are supplied in the constructor. It is backed + * by a standard Java hashmap, and uses adapter classes to bridge + * between them. + * @author Niko Matsakis + */ +public class CustomDict implements Map +{ + public final Equals equals; + public final HashCode hashCode; + public final Map, V> backingMap = + new HashMap, V>(); + + public static CustomDict make( + final Equals equals, final HashCode hashCode) + { + return new CustomDict(equals, hashCode); + } + + public CustomDict(final Equals equals, final HashCode hashCode) { + this.hashCode = hashCode; + this.equals = equals; + System.err.println("Equals: "+equals.getClass()); + System.err.println("HashCode: "+hashCode.getClass()); + } + + public class Adapter { + public final AK object; + public Adapter(AK object) { + this.object = object; + } + + public int hashCode() { + return hashCode.invoke(this.object); + } + + public boolean equals(Object other) { + return equals.invoke(this.object, ((Adapter)other).object); + } + } + + private Adapter w(AK k) { + return new Adapter(k); + } + + public void clear() { + this.backingMap.clear(); + } + + public boolean containsKey(Object arg0) { + return this.backingMap.containsKey(w(arg0)); + } + + public boolean containsValue(Object value) { + return this.backingMap.containsValue(value); + } + + public Set> entrySet() { + return new FilterSet, V>, Map.Entry>( + this.backingMap.entrySet(), + new Filter, V>, Map.Entry>() { + public Map.Entry, V> from(final Map.Entry to) { + return new Map.Entry, V>() { + public Adapter getKey() { + return new Adapter(to.getKey()); + } + public V getValue() { + return to.getValue(); + } + public V setValue(V value) { + return to.setValue(value); + } + }; + } + + public Map.Entry to(final Map.Entry, V> from) { + return new Map.Entry() { + public K getKey() { + return from.getKey().object; + } + public V getValue() { + return from.getValue(); + } + public V setValue(V value) { + return from.setValue(value); + } + }; + } + }); + } + + public V get(Object key) { + return this.backingMap.get(w(key)); + } + + public boolean isEmpty() { + return this.backingMap.isEmpty(); + } + + public Set keySet() { + return new FilterSet, K>( + this.backingMap.keySet(), + new Filter, K>() { + public Adapter from(K to) { + return new Adapter(to); + } + public K to(Adapter from) { + return from.object; + } + }); + } + + public V put(K key, V value) { + return this.backingMap.put(w(key), value); + } + + public void putAll(Map t) { + for (Map.Entry entry : t.entrySet()) { + this.put(entry.getKey(), entry.getValue()); + } + } + + public V remove(Object key) { + return this.backingMap.remove(w(key)); + } + + public int size() { + return this.backingMap.size(); + } + + public Collection values() { + return this.backingMap.values(); + } + +} \ No newline at end of file Added: pypy/dist/pypy/translator/jvm/src/pypy/Equals.java ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/src/pypy/Equals.java Wed Apr 4 09:52:50 2007 @@ -0,0 +1,6 @@ +package pypy; + +/** @see Callback */ +public interface Equals extends Callback { + public boolean invoke(Object one, Object two); +} Added: pypy/dist/pypy/translator/jvm/src/pypy/Filter.java ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/src/pypy/Filter.java Wed Apr 4 09:52:50 2007 @@ -0,0 +1,6 @@ +package pypy; + +public interface Filter { + public T to(F from); + public F from(T to); +} Added: pypy/dist/pypy/translator/jvm/src/pypy/FilterIterator.java ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/src/pypy/FilterIterator.java Wed Apr 4 09:52:50 2007 @@ -0,0 +1,27 @@ +package pypy; + +import java.util.Iterator; + +public class FilterIterator implements Iterator { + + public final Iterator iter; + public final Filter filter; + + public FilterIterator(final Iterator iter, final Filter filter) { + this.iter = iter; + this.filter = filter; + } + + public boolean hasNext() { + return this.iter.hasNext(); + } + + public T next() { + return filter.to(this.iter.next()); + } + + public void remove() { + this.iter.remove(); + } + +} Added: pypy/dist/pypy/translator/jvm/src/pypy/FilterSet.java ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/src/pypy/FilterSet.java Wed Apr 4 09:52:50 2007 @@ -0,0 +1,85 @@ +package pypy; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +public class FilterSet implements Set { + + public final Set base; + public final Filter filter; + + public FilterSet(final Set base, final Filter filter) { + this.base = base; + this.filter = filter; + } + + public boolean add(T o) { + return this.base.add(filter.from(o)); + } + + public boolean addAll(Collection c) { + boolean res = false; + for (T t : c) { + res = add(t) || res; + } + return res; + } + + public void clear() { + this.base.clear(); + } + + public boolean contains(Object o) { + return this.base.contains(o); + } + + public boolean containsAll(Collection c) { + return this.base.containsAll(c); + } + + public boolean isEmpty() { + return this.base.isEmpty(); + } + + public Iterator iterator() { + return new FilterIterator(this.base.iterator(), filter); + } + + public boolean remove(Object o) { + return this.base.remove(o); + } + + public boolean removeAll(Collection c) { + return this.base.removeAll(c); + } + + public boolean retainAll(Collection c) { + return this.base.retainAll(c); + } + + public int size() { + return this.base.size(); + } + + @SuppressWarnings("unchecked") + public Object[] toArray() { + Object[] froms = this.base.toArray(); + Object[] tos = new Object[froms.length]; + for (int i = 0; i < froms.length; i++) + tos[i] = filter.to((F)tos[i]); + return tos; + } + + public X[] toArray(X[] a) { + Object[] arr = toArray(); + if (a.length == arr.length) { + System.arraycopy(arr, 0, a, 0, a.length); + return a; + } + // can't be bothered to navigate reflection apis right now + throw new RuntimeException("TODO"); + } + +} Added: pypy/dist/pypy/translator/jvm/src/pypy/HashCode.java ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/src/pypy/HashCode.java Wed Apr 4 09:52:50 2007 @@ -0,0 +1,6 @@ +package pypy; + +/** @see Callback */ +public interface HashCode extends Callback { + public int invoke(Object obj); +} Modified: pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java ============================================================================== --- pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java (original) +++ pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java Wed Apr 4 09:52:50 2007 @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Arrays; +import java.util.Map; /** * Class with a number of utility routines. @@ -521,15 +522,34 @@ // ---------------------------------------------------------------------- // Dicts + // + // Note: it's easier to cut and paste a few methods here than + // make the code generator smarter to avoid the duplicate code. public static boolean ll_remove(HashMap map, Object key) { return map.remove(key) != null; } + public static boolean ll_remove(CustomDict map, Object key) { + return map.remove(key) != null; + } + public static DictItemsIterator ll_get_items_iterator(HashMap map) { return new DictItemsIterator(map); } + + public static DictItemsIterator ll_get_items_iterator(CustomDict map) { + return new DictItemsIterator(map); + } + public static CustomDict ll_copy(CustomDict map) { + CustomDict cd = new CustomDict(map.equals, map.hashCode); + for (Map.Entry me : map.entrySet()) { + cd.put(me.getKey(), me.getValue()); + } + return cd; + } + // ---------------------------------------------------------------------- // Lists Modified: pypy/dist/pypy/translator/jvm/test/test_dict.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_dict.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_dict.py Wed Apr 4 09:52:50 2007 @@ -17,5 +17,4 @@ py.test.skip("Iteration over empty dict is not supported, yet") class TestJvmConstantDict(JvmTest, oodict.BaseTestConstantDict): - def test_constant_r_dict(self): - py.test.skip("JVM doesn't support r_dict so far") + pass Added: pypy/dist/pypy/translator/jvm/test/test_objectmodel.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/test/test_objectmodel.py Wed Apr 4 09:52:50 2007 @@ -0,0 +1,9 @@ +import py +from pypy.translator.jvm.test.runtest import JvmTest +from pypy.rlib.test.test_objectmodel import BaseTestObjectModel + +from pypy.rlib.objectmodel import cast_object_to_weakgcaddress,\ + cast_weakgcaddress_to_object + +class TestJvmObjectModel(JvmTest, BaseTestObjectModel): + pass Modified: pypy/dist/pypy/translator/jvm/test/test_snippet.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_snippet.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_snippet.py Wed Apr 4 09:52:50 2007 @@ -1,6 +1,26 @@ from pypy.translator.jvm.test.runtest import JvmTest from pypy.translator.oosupport.test_template.snippets import BaseTestSnippets -class TestSnippets(BaseTestSnippets, JvmTest): +class Foo: pass +class TestSnippets(BaseTestSnippets, JvmTest): + + def test_equals_func(self): + def equals(x, y): + return x == y + def unequals(x, y): + return x != y + def base_func(op): + res = 0 + a = Foo() + b = Foo() + if op: func = equals + else: func = unequals + if func(a,b): res += 1 + if func(a,a): res += 10 + if func(b,b): res += 100 + return res + assert self.interpret(base_func, [True]) == 110 + assert self.interpret(base_func, [False]) == 001 + Modified: pypy/dist/pypy/translator/jvm/typesystem.py ============================================================================== --- pypy/dist/pypy/translator/jvm/typesystem.py (original) +++ pypy/dist/pypy/translator/jvm/typesystem.py Wed Apr 4 09:52:50 2007 @@ -127,7 +127,7 @@ def __repr__(self): return "%s<%s>" % (self.__class__.__name__, self.descriptor) - + class JvmClassType(JvmType): """ Base class used for all class instances. Kind of an abstract class; @@ -143,6 +143,9 @@ def lookup_method(self, methodnm): raise KeyError(fieldnm) # we treat as opaque type +class JvmInterfaceType(JvmClassType): + pass + jIntegerClass = JvmClassType('java.lang.Integer') jLongClass = JvmClassType('java.lang.Long') jDoubleClass = JvmClassType('java.lang.Double') @@ -153,15 +156,15 @@ jObject = JvmClassType('java.lang.Object') jString = JvmClassType('java.lang.String') jCharSequence = JvmClassType('java.lang.CharSequence') -jArrayList = JvmClassType('java.util.ArrayList') jArrays = JvmClassType('java.util.Arrays') +jMap = JvmInterfaceType('java.util.Map') jHashMap = JvmClassType('java.util.HashMap') jIterator = JvmClassType('java.util.Iterator') jClass = JvmClassType('java.lang.Class') jStringBuilder = JvmClassType('java.lang.StringBuilder') jPrintStream = JvmClassType('java.io.PrintStream') jMath = JvmClassType('java.lang.Math') -jList = JvmClassType('java.util.List') +jList = JvmInterfaceType('java.util.List') jArrayList = JvmClassType('java.util.ArrayList') jPyPy = JvmClassType('pypy.PyPy') jPyPyExcWrap = JvmClassType('pypy.ExceptionWrapper') @@ -169,6 +172,7 @@ jPyPyMain = JvmClassType('pypy.Main') jPyPyDictItemsIterator = JvmClassType('pypy.DictItemsIterator') jPyPyInterlink = JvmClassType('pypy.Interlink') +jPyPyCustomDict = JvmClassType('pypy.CustomDict') jArithmeticException = JvmClassType('java.lang.ArithmeticException') @@ -184,6 +188,7 @@ raise KeyError(fieldnm) # Scalar objects have no fields def lookup_method(self, methodnm): raise KeyError(methodnm) # Scalar objects have no methods + jVoid = JvmScalarType('V', None, None) jInt = JvmScalarType('I', jIntegerClass, 'intValue') jLong = JvmScalarType('J', jLongClass, 'longValue') @@ -240,9 +245,9 @@ def full_types(self, method_name): """ Returns a tuple of argument and return types for the method - named 'method_name'. These are the actual generic types. The set method for - a list of strings, for example, might return: - ( [INT, STRING], VOID ) + named 'method_name'. These are the actual generic types. The + set method for a list of strings, for example, might return: + ( [INT, STRING], VOID ) """ GENMETH = self.OOTYPE._GENERIC_METHODS[method_name] ARGS, RESULT = (GENMETH.ARGS, GENMETH.RESULT) @@ -253,9 +258,9 @@ def erased_types(self, method_name): """ Returns a tuple of argument and return types for the method - named 'method_name'. These are the erased generic types. The set method for - a list of strings, for example, might return: - ( [INT, OBJECT], VOID ) + named 'method_name'. These are the erased generic types. The + set method for a list of strings, for example, might return: + ( [INT, OBJECT], VOID ) """ GENMETH = self.OOTYPE._GENERIC_METHODS[method_name] ARGS, RESULT = (GENMETH.ARGS, GENMETH.RESULT) @@ -263,5 +268,35 @@ RESULT = self.generics.get(RESULT, (None,RESULT))[1] return (ARGS, RESULT) +# ______________________________________________________________________ +# Java Callback Interfaces +# +# A list of interfaces which static functions that we generate will +# automatically implement if application. See the pypy/Callback.java, +# node.py/StaticMethodInterface for more information. + +jCallbackInterfaces = [] # collects all of the defined JvmCallbackInterfaces + +class JvmCallbackInterface(JvmInterfaceType): + def __init__(self, name, jargtypes, jrettype): + JvmInterfaceType.__init__(self, name) + self.java_argument_types = jargtypes + self.java_return_type = jrettype + jCallbackInterfaces.append(self) # add to global list + def matches(self, jargtypes, jrettype): + """ Given a set of argument types and a return type for some + static function defined by the user, returns true if this + JvmCallbackInterface applies. Note that the types don't have + to match exactly: we assume that (in the list of arguments) + jObject is used as a wildcard, and some adaptation code may + have to be inserted.""" + if len(self.java_argument_types) != len(jargtypes): + return False + for expjarg, actjarg in zip(self.java_argument_types, jargtypes): + if expjarg == jObject: continue # hack: assume obj means any type + if expjarg != actjarg: return False + return jrettype == self.java_return_type - +jPyPyHashCode = JvmCallbackInterface('pypy.HashCode', [jObject], jInt) +jPyPyEquals = JvmCallbackInterface('pypy.Equals', [jObject, jObject], jBool) + From cfbolz at codespeak.net Wed Apr 4 12:23:10 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 4 Apr 2007 12:23:10 +0200 (CEST) Subject: [pypy-svn] r41893 - pypy/extradoc/eu-report Message-ID: <20070404102310.D54A910053@code0.codespeak.net> Author: cfbolz Date: Wed Apr 4 12:23:07 2007 New Revision: 41893 Added: pypy/extradoc/eu-report/D06.1_Core_Optimizations-2007-04-04.pdf (contents, props changed) Log: interim of D06.1 Added: pypy/extradoc/eu-report/D06.1_Core_Optimizations-2007-04-04.pdf ============================================================================== Binary file. No diff available. From arigo at codespeak.net Wed Apr 4 12:29:02 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 4 Apr 2007 12:29:02 +0200 (CEST) Subject: [pypy-svn] r41894 - pypy/dist/pypy/doc Message-ID: <20070404102902.D2C4B1005A@code0.codespeak.net> Author: arigo Date: Wed Apr 4 12:29:00 2007 New Revision: 41894 Modified: pypy/dist/pypy/doc/index-report.txt Log: Link to the interim of D06.1. Modified: pypy/dist/pypy/doc/index-report.txt ============================================================================== --- pypy/dist/pypy/doc/index-report.txt (original) +++ pypy/dist/pypy/doc/index-report.txt Wed Apr 4 12:29:00 2007 @@ -12,6 +12,10 @@ Reports of 2007 =============== +`D06.1 Core Object Optimization Results`_ documents the optimizations +we implemented in the interpreter and object space: dictionary +imlementations, method call optimizations, etc. *(2007-04-04)* + `D14.5 Documentation of the development process`_ documents PyPy's sprint-driven development process and puts it into the context of agile methodologies. *(2007-03-30)* @@ -129,6 +133,7 @@ .. _`D05.2 A Compiled Version of PyPy`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.2_A_compiled,_self-contained_version_of_PyPy.pdf .. _`D05.3 Implementation with Translation Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.3_Publish_on_implementation_with_translation_aspects.pdf .. _`D05.4 Encapsulating Low Level Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.4_Publish_on_encapsulating_low_level_language_aspects.pdf +.. _`D06.1 Core Object Optimization Results`: http://codespeak.net/svn/pypy/extradoc/eu-report/D06.1_Core_Optimizations-2007-04-04.pdf .. _`D07.1 Massive Parallelism and Translation Aspects`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-2007-02-28.pdf .. _`Draft D08.2 JIT Compiler Architecture`: http://codespeak.net/pypy/extradoc/eu-report/D08.2_JIT_Compiler_Architecture-interim-2007-01-28.pdf .. _`D09.1 Constraint Solving and Semantic Web`: http://codespeak.net/pypy/extradoc/eu-report/D09.1_Constraint_Solving_and_Semantic_Web-interim-2007-02-28.pdf From cfbolz at codespeak.net Wed Apr 4 12:34:08 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 4 Apr 2007 12:34:08 +0200 (CEST) Subject: [pypy-svn] r41896 - pypy/dist/pypy/doc Message-ID: <20070404103408.CA13610060@code0.codespeak.net> Author: cfbolz Date: Wed Apr 4 12:34:07 2007 New Revision: 41896 Modified: pypy/dist/pypy/doc/index-report.txt Log: add a feedback wanted sentence Modified: pypy/dist/pypy/doc/index-report.txt ============================================================================== --- pypy/dist/pypy/doc/index-report.txt (original) +++ pypy/dist/pypy/doc/index-report.txt Wed Apr 4 12:34:07 2007 @@ -14,7 +14,8 @@ `D06.1 Core Object Optimization Results`_ documents the optimizations we implemented in the interpreter and object space: dictionary -imlementations, method call optimizations, etc. *(2007-04-04)* +imlementations, method call optimizations, etc. The report is still not final +so we are very interested in any feedback *(2007-04-04)* `D14.5 Documentation of the development process`_ documents PyPy's sprint-driven development process and puts it into the context of agile From cfbolz at codespeak.net Thu Apr 5 13:55:45 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 5 Apr 2007 13:55:45 +0200 (CEST) Subject: [pypy-svn] r41911 - pypy/extradoc/eu-report Message-ID: <20070405115545.8F3A910075@code0.codespeak.net> Author: cfbolz Date: Thu Apr 5 13:55:44 2007 New Revision: 41911 Added: pypy/extradoc/eu-report/D14.4_Report_About_Milestone_Phase_3-interim-2007-2007-04-05.pdf (contents, props changed) Log: interim Added: pypy/extradoc/eu-report/D14.4_Report_About_Milestone_Phase_3-interim-2007-2007-04-05.pdf ============================================================================== Binary file. No diff available. From hpk at codespeak.net Thu Apr 5 18:29:15 2007 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 5 Apr 2007 18:29:15 +0200 (CEST) Subject: [pypy-svn] r41916 - pypy/dist/pypy/doc Message-ID: <20070405162915.4158F10072@code0.codespeak.net> Author: hpk Date: Thu Apr 5 18:29:13 2007 New Revision: 41916 Modified: pypy/dist/pypy/doc/index-report.txt Log: added reference to 14.4 and rewrote the intro to make it a bit more timeless. Modified: pypy/dist/pypy/doc/index-report.txt ============================================================================== --- pypy/dist/pypy/doc/index-report.txt (original) +++ pypy/dist/pypy/doc/index-report.txt Thu Apr 5 18:29:13 2007 @@ -2,16 +2,21 @@ PyPy - Overview over the EU-reports ============================================ - -We have written several reports for the EU of which some are also quite useful -as documentation. The ones not so useful as documentation mostly contain text -that can also be found in the regular documentation section. All of these -documents from the years 2006 and 2007 are preliminary versions, none of them -have been approved by the European Union. +Below reports summarize and discuss research and development results +of the PyPy project during the EU funding period (Dez 2004 - March 2007). +They also are very good documentation if you'd like to know in more +detail about motivation and implementation of the various parts +and aspects of PyPy. Feel free to send questions or comments +to `pypy-dev`_, the development list. Reports of 2007 =============== +`D14.4 PyPy-1.0 Milestone report`_ (for language developers and researchers) +summarizes research & technical results of the PyPy-1.0 release and discusses +related development process and community aspects. This report is an interim +version, we may still incorporate feedback. *(2007-04-05)* + `D06.1 Core Object Optimization Results`_ documents the optimizations we implemented in the interpreter and object space: dictionary imlementations, method call optimizations, etc. The report is still not final @@ -81,6 +86,7 @@ .. _`py-lib`: http://codespeak.net/py/current/doc/ .. _`py.test`: http://codespeak.net/py/current/doc/test.html .. _codespeak: http://codespeak.net/ +.. _`pypy-dev`: http://codespeak.net/mailman/listinfo/pypy-dev Reports of 2006 @@ -145,6 +151,7 @@ .. _`D14.1 Report about Milestone/Phase 1`: http://codespeak.net/svn/pypy/extradoc/eu-report/D14.1_Report_about_Milestone_Phase_1.pdf .. _`D14.2 Tutorials and Guide Through the PyPy Source Code`: http://codespeak.net/pypy/extradoc/eu-report/D14.2_Tutorials_and_Guide_Through_the_PyPy_Source_Code-2007-03-22.pdf .. _`D14.3 Report about Milestone/Phase 2`: http://codespeak.net/pypy/extradoc/eu-report/D14.3_Report_about_Milestone_Phase_2-final-2006-08-03.pdf +.. _`D14.4 PyPy-1.0 Milestone report`: http://codespeak.net/pypy/extradoc/eu-report/D14.4_Report_About_Milestone_Phase_3-interim-2007-2007-04-05.pdf .. _`D14.5 Documentation of the development process`: http://codespeak.net/pypy/extradoc/eu-report/D14.5_Documentation_of_the_development_process-2007-03-30.pdf From arigo at codespeak.net Tue Apr 10 18:19:24 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 10 Apr 2007 18:19:24 +0200 (CEST) Subject: [pypy-svn] r41989 - in pypy/dist/pypy/translator/js: . test Message-ID: <20070410161924.69C1B8090@code0.codespeak.net> Author: arigo Date: Tue Apr 10 18:19:24 2007 New Revision: 41989 Modified: pypy/dist/pypy/translator/js/main.py pypy/dist/pypy/translator/js/test/test_main.py Log: (scott dial) Don't invoke Pygame from the JS test suite. Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Tue Apr 10 18:19:24 2007 @@ -117,7 +117,7 @@ print retval return retval -def rpython2javascript(mod, function_names, jsconfig=None, use_pdb=True): +def rpython2javascript(mod, function_names, jsconfig=None): if isinstance(function_names, str): function_names = [function_names] # avoid confusion @@ -129,8 +129,6 @@ if jsconfig is None: jsconfig = Config(js_optiondescr) - if use_pdb: - jsconfig.use_pdb = True module_name = mod.__name__ if not function_names and 'main' in mod.__dict__: function_names.append('main') @@ -162,4 +160,4 @@ # XXX: Add some possibility to write down selected file except Exception, e: # do something nice with it - debug(driver, use_pdb) + debug(driver, jsconfig.use_pdb) Modified: pypy/dist/pypy/translator/js/test/test_main.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_main.py (original) +++ pypy/dist/pypy/translator/js/test/test_main.py Tue Apr 10 18:19:24 2007 @@ -33,11 +33,11 @@ pass def test_bookkeeper_cleanup(): - assert rpython2javascript(sys.modules[__name__], ["fun"]) - assert rpython2javascript(sys.modules[__name__], ["fun"]) + assert rpython2javascript(sys.modules[__name__], ["fun"], jsconfig) + assert rpython2javascript(sys.modules[__name__], ["fun"], jsconfig) def test_module_none(): - assert rpython2javascript(None, "fff") + assert rpython2javascript(None, "fff", jsconfig) class TestJsMain(object): def _test_not_raises(self, mod_file, args_rest=[]): From arigo at codespeak.net Tue Apr 10 18:23:42 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 10 Apr 2007 18:23:42 +0200 (CEST) Subject: [pypy-svn] r41990 - in pypy/dist/pypy/translator/js: . test Message-ID: <20070410162342.481968097@code0.codespeak.net> Author: arigo Date: Tue Apr 10 18:23:41 2007 New Revision: 41990 Modified: pypy/dist/pypy/translator/js/main.py pypy/dist/pypy/translator/js/test/test_main.py Log: Revert r41989 - many tests fail. Mea culpa. Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Tue Apr 10 18:23:41 2007 @@ -117,7 +117,7 @@ print retval return retval -def rpython2javascript(mod, function_names, jsconfig=None): +def rpython2javascript(mod, function_names, jsconfig=None, use_pdb=True): if isinstance(function_names, str): function_names = [function_names] # avoid confusion @@ -129,6 +129,8 @@ if jsconfig is None: jsconfig = Config(js_optiondescr) + if use_pdb: + jsconfig.use_pdb = True module_name = mod.__name__ if not function_names and 'main' in mod.__dict__: function_names.append('main') @@ -160,4 +162,4 @@ # XXX: Add some possibility to write down selected file except Exception, e: # do something nice with it - debug(driver, jsconfig.use_pdb) + debug(driver, use_pdb) Modified: pypy/dist/pypy/translator/js/test/test_main.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_main.py (original) +++ pypy/dist/pypy/translator/js/test/test_main.py Tue Apr 10 18:23:41 2007 @@ -33,11 +33,11 @@ pass def test_bookkeeper_cleanup(): - assert rpython2javascript(sys.modules[__name__], ["fun"], jsconfig) - assert rpython2javascript(sys.modules[__name__], ["fun"], jsconfig) + assert rpython2javascript(sys.modules[__name__], ["fun"]) + assert rpython2javascript(sys.modules[__name__], ["fun"]) def test_module_none(): - assert rpython2javascript(None, "fff", jsconfig) + assert rpython2javascript(None, "fff") class TestJsMain(object): def _test_not_raises(self, mod_file, args_rest=[]): From arigo at codespeak.net Tue Apr 10 20:16:02 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 10 Apr 2007 20:16:02 +0200 (CEST) Subject: [pypy-svn] r41992 - in pypy/dist/pypy/jit: codegen/llgraph hintannotator hintannotator/test timeshifter/test Message-ID: <20070410181602.B0ECC8090@code0.codespeak.net> Author: arigo Date: Tue Apr 10 20:16:02 2007 New Revision: 41992 Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py pypy/dist/pypy/jit/hintannotator/model.py pypy/dist/pypy/jit/hintannotator/test/test_annotator.py pypy/dist/pypy/jit/timeshifter/test/test_portal.py Log: cast_ptr_to_int support. Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/llimpl.py Tue Apr 10 20:16:02 2007 @@ -167,11 +167,17 @@ block.operations.append(op) return to_opaque_object(erasedvar(v, block)) +RESULT_TYPES = { + 'cast_ptr_to_int': lltype.Signed, + } + def guess_result_type(opname, opvars): if opname.endswith('_zer'): # h opname = opname[:-4] # a if opname.endswith('_ovf'): # c opname = opname[:-4] # k + if opname in RESULT_TYPES: + return RESULT_TYPES[opname] op = getattr(llop, opname) need_result_type = getattr(op.fold, 'need_result_type', False) assert not need_result_type, ("cannot guess the result type of %r" Modified: pypy/dist/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/dist/pypy/jit/hintannotator/model.py Tue Apr 10 20:16:02 2007 @@ -15,6 +15,7 @@ cast_uint_to_int cast_char_to_int cast_bool_to_int + cast_ptr_to_int ptr_nonzero ptr_iszero is_early_constant Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Tue Apr 10 20:16:02 2007 @@ -909,3 +909,13 @@ assert hs.is_green() for graph in hannotator.translator.graphs: assert 'int_mul' not in flowmodel.summary(graph) + + +def test_cast_ptr_to_int(): + GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed)) + def f(): + p = lltype.malloc(GCS1) + return lltype.cast_ptr_to_int(p) + + hs = hannotate(f, [], policy=P_NOVIRTUAL) + assert not hs.is_green() Modified: pypy/dist/pypy/jit/timeshifter/test/test_portal.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_portal.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_portal.py Tue Apr 10 20:16:02 2007 @@ -5,6 +5,7 @@ from pypy.jit.timeshifter.test.test_timeshift import P_NOVIRTUAL, StopAtXPolicy from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC from pypy.rpython.llinterp import LLInterpreter +from pypy.rpython.lltypesystem import lltype from pypy.objspace.flow.model import summary from pypy.rlib.objectmodel import hint from pypy.jit.codegen.llgraph.rgenop import RGenOp as LLRGenOp @@ -517,3 +518,14 @@ res = self.timeshift_from_portal(f, f, [15], policy=P_OOPSPEC) assert res == 15 + + def test_cast_ptr_to_int(self): + GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed)) + def g(p): + return lltype.cast_ptr_to_int(p) + def f(): + p = lltype.malloc(GCS1) + return g(p) - lltype.cast_ptr_to_int(p) + + res = self.timeshift_from_portal(f, g, [], policy=P_NOVIRTUAL) + assert res == 0 From arigo at codespeak.net Tue Apr 10 20:40:00 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 10 Apr 2007 20:40:00 +0200 (CEST) Subject: [pypy-svn] r41993 - in pypy/dist/pypy/jit/codegen: . dump i386 llgraph test Message-ID: <20070410184000.560628090@code0.codespeak.net> Author: arigo Date: Tue Apr 10 20:39:58 2007 New Revision: 41993 Modified: pypy/dist/pypy/jit/codegen/dump/rgenop.py pypy/dist/pypy/jit/codegen/graph2rgenop.py pypy/dist/pypy/jit/codegen/i386/rgenop.py pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/codegen/model.py pypy/dist/pypy/jit/codegen/test/rgenop_tests.py Log: Cast tests. Support for cast_int_to_ptr too, just in case. Modified: pypy/dist/pypy/jit/codegen/dump/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/dump/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/dump/rgenop.py Tue Apr 10 20:39:58 2007 @@ -181,6 +181,15 @@ self.rgenop.vname(gv_ptr2))) return v + def genop_cast_int_to_ptr(self, kind, gv_int): + v = self.llbuilder.genop_cast_int_to_ptr(kind, gv_int) + self.dump("%s = %s.genop_cast_int_to_ptr(%s, %s)" % ( + self.rgenop.vname(v), + self.name, + self.rgenop.kindtokenname(kind), + self.rgenop.vname(gv_int))) + return v + def genop_same_as(self, kind, gv_x): v = self.llbuilder.genop_same_as(kind, gv_x) self.dump("%s = %s.genop_same_as(%s, %s)" % ( Modified: pypy/dist/pypy/jit/codegen/graph2rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/graph2rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/graph2rgenop.py Tue Apr 10 20:39:58 2007 @@ -171,7 +171,12 @@ gv_result = builder.genop_ptr_ne(token, var2gv(op.args[0]), var2gv(op.args[1])) - + + elif op.opname == 'cast_int_to_ptr': + token = rgenop.kindToken(op.result.concretetype) + gv_result = builder.genop_cast_int_to_ptr(token, + var2gv(op.args[0])) + elif len(op.args) == 1: gv_result = builder.genop1(op.opname, var2gv(op.args[0])) elif len(op.args) == 2: Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/rgenop.py Tue Apr 10 20:39:58 2007 @@ -419,6 +419,9 @@ self.operations.append(op) return op + def genop_cast_int_to_ptr(self, kind, gv_int): + return gv_int # identity + def genop_same_as(self, kind, gv_x): if gv_x.is_const: # must always return a var op = OpSameAs(gv_x) Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Tue Apr 10 20:39:58 2007 @@ -254,6 +254,12 @@ return LLVar(llimpl.genop(self.b, 'ptr_ne', [gv_ptr1, gv_ptr2], gv_Bool.v)) + def genop_cast_int_to_ptr(self, gv_PTRTYPE, gv_int): + debug_assert(self.rgenop.currently_writing is self, + "genop_cast_int_to_ptr: bad currently_writing") + return LLVar(llimpl.genop(self.b, 'cast_int_to_ptr', [gv_int], + gv_PTRTYPE.v)) + def _newblock(self, kinds): self.b = newb = llimpl.newblock() return [LLVar(llimpl.geninputarg(newb, kind.v)) for kind in kinds] Modified: pypy/dist/pypy/jit/codegen/model.py ============================================================================== --- pypy/dist/pypy/jit/codegen/model.py (original) +++ pypy/dist/pypy/jit/codegen/model.py Tue Apr 10 20:39:58 2007 @@ -88,6 +88,7 @@ ## def genop_ptr_nonzero(self, kindtoken, gv_ptr) ## def genop_ptr_eq(self, kindtoken, gv_ptr1, gv_ptr2) ## def genop_ptr_ne(self, kindtoken, gv_ptr1, gv_ptr2) +## def genop_cast_int_to_ptr(self, kindtoken, gv_int) # the other thing that happens for a given chunk is entering and # leaving basic blocks inside it. Modified: pypy/dist/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/dist/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/dist/pypy/jit/codegen/test/rgenop_tests.py Tue Apr 10 20:39:58 2007 @@ -1,6 +1,6 @@ import random, sys from pypy.rpython.annlowlevel import MixLevelAnnotatorPolicy, llhelper -from pypy.rlib.rarithmetic import intmask +from pypy.rlib.rarithmetic import intmask, r_uint from pypy.rlib.objectmodel import keepalive_until_here from pypy.rpython.lltypesystem import lltype, llmemory from pypy.translator.c.test import test_boehm @@ -2038,3 +2038,40 @@ assert (res & 1) == 1 else: assert res == intmask(expected << 1) | 0 + + def test_cast_direct(self): + yield self.cast_direct, ["int_is_true", "cast_bool_to_int"], bool + yield self.cast_direct, ["int_is_true", + "cast_bool_to_uint", + "cast_uint_to_int"], bool + yield self.cast_direct, ["cast_int_to_char", + "cast_char_to_int"], int, 255 + yield self.cast_direct, ["cast_int_to_unichar", + "cast_unichar_to_int"], int, sys.maxunicode + yield self.cast_direct, ["cast_int_to_uint", "cast_uint_to_int"], int + yield self.cast_direct, ["cast_int_to_ptr", "cast_ptr_to_int"], int + + def cast_direct(self, operations, expected, max=r_uint(-1)): + need_odd_integer = False + rgenop = self.RGenOp() + sigtoken = rgenop.sigToken(FUNC) + builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, "cast") + builder.start_writing() + for opname in operations: + if opname == "cast_int_to_ptr": + S = lltype.GcStruct('s', ('x', lltype.Signed)) + ptrkind = rgenop.kindToken(lltype.Ptr(S)) + gv_x = builder.genop_cast_int_to_ptr(ptrkind, gv_x) + need_odd_integer = True + else: + gv_x = builder.genop1(opname, gv_x) + builder.finish_and_return(sigtoken, gv_x) + builder.end() + + fnptr = self.cast(gv_fn, 1) + for x in [0, 1, max // 6, max // 2, max - 1, max]: + x = intmask(x) + if need_odd_integer: + x |= 1 + result = fnptr(x) + assert result == expected(x) From arigo at codespeak.net Tue Apr 10 20:43:02 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 10 Apr 2007 20:43:02 +0200 (CEST) Subject: [pypy-svn] r41994 - pypy/dist/pypy/jit/codegen/ppc Message-ID: <20070410184302.022238096@code0.codespeak.net> Author: arigo Date: Tue Apr 10 20:43:02 2007 New Revision: 41994 Modified: pypy/dist/pypy/jit/codegen/ppc/rgenop.py Log: Implement genop_cast_int_to_ptr in codegen/ppc too. Modified: pypy/dist/pypy/jit/codegen/ppc/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/ppc/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/ppc/rgenop.py Tue Apr 10 20:43:02 2007 @@ -398,6 +398,9 @@ else: return gv_arg + def genop_cast_int_to_ptr(self, ptrkindtoken, gv_int): + return gv_int + ## def genop_debug_pdb(self): # may take an args_gv later def genop_get_frame_base(self): @@ -1111,7 +1114,6 @@ return self._compare('eq', gv_arg, self.rgenop.genconst(0)) op_cast_ptr_to_int = _identity - op_cast_int_to_ptr = _identity # ... address operations ... From stephan at codespeak.net Thu Apr 12 10:42:53 2007 From: stephan at codespeak.net (stephan at codespeak.net) Date: Thu, 12 Apr 2007 10:42:53 +0200 (CEST) Subject: [pypy-svn] r41999 - pypy/dist/pypy/lib Message-ID: <20070412084253.D37888091@code0.codespeak.net> Author: stephan Date: Thu Apr 12 10:42:52 2007 New Revision: 41999 Modified: pypy/dist/pypy/lib/stackless.py Log: added a tasklet.run method Modified: pypy/dist/pypy/lib/stackless.py ============================================================================== --- pypy/dist/pypy/lib/stackless.py (original) +++ pypy/dist/pypy/lib/stackless.py Thu Apr 12 10:42:52 2007 @@ -71,7 +71,7 @@ """ try: return greenlet.switch(self._frame) - except TypeError: # self._frame is the main coroutine + except TypeError, exp: # self._frame is the main coroutine return greenlet.switch(self._frame.something) def kill(self): @@ -353,6 +353,12 @@ _scheduler_append(self) return self + def run(self): + if _scheduler_contains(self): + return + else: + _scheduler_append(self) + def __reduce__(self): one, two, three = coroutine.__reduce__(self) assert one is coroutine From stephan at codespeak.net Thu Apr 12 10:51:30 2007 From: stephan at codespeak.net (stephan at codespeak.net) Date: Thu, 12 Apr 2007 10:51:30 +0200 (CEST) Subject: [pypy-svn] r42000 - pypy/dist/pypy/lib Message-ID: <20070412085130.2D7378091@code0.codespeak.net> Author: stephan Date: Thu Apr 12 10:51:29 2007 New Revision: 42000 Modified: pypy/dist/pypy/lib/stackless.py Log: removed calls to super in tasklet.__new__ and tasklet.__init__ Modified: pypy/dist/pypy/lib/stackless.py ============================================================================== --- pypy/dist/pypy/lib/stackless.py (original) +++ pypy/dist/pypy/lib/stackless.py Thu Apr 12 10:51:29 2007 @@ -282,10 +282,10 @@ """ tempval = None def __new__(cls, func=None, label=''): - return super(tasklet,cls).__new__(cls) + return coroutine.__new__(cls) def __init__(self, func=None, label=''): - super(tasklet, self).__init__() + coroutine.__init__(self) self._init(func, label) def _init(self, func=None, label=''): From fijal at codespeak.net Thu Apr 12 14:36:08 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Apr 2007 14:36:08 +0200 (CEST) Subject: [pypy-svn] r42002 - in pypy/dist/pypy/rpython: lltypesystem test Message-ID: <20070412123608.CF73E8096@code0.codespeak.net> Author: fijal Date: Thu Apr 12 14:36:07 2007 New Revision: 42002 Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: Support for 'x' * negative, apparently this worked in ootypesystem before (not sure if backends support it though) Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rstr.py Thu Apr 12 14:36:07 2007 @@ -149,6 +149,8 @@ class LLHelpers(AbstractLLHelpers): def ll_char_mul(ch, times): + if times < 0: + times = 0 newstr = mallocstr(times) j = 0 while j < times: Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Thu Apr 12 14:36:07 2007 @@ -600,6 +600,13 @@ res = self.interpret(f, ['a', 0]) assert self.ll_to_string(res) == "" + def test_char_mul_negative(self): + def f(c): + return c * -3 + + res = self.interpret(f, ['a']) + assert self.ll_to_string(res) == '' + def test_n_mul_char(self): def f(c, n): return n*c From arigo at codespeak.net Thu Apr 12 19:41:11 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Apr 2007 19:41:11 +0200 (CEST) Subject: [pypy-svn] r42003 - pypy/dist/pypy/doc Message-ID: <20070412174111.DCACE80A2@code0.codespeak.net> Author: arigo Date: Thu Apr 12 19:41:11 2007 New Revision: 42003 Modified: pypy/dist/pypy/doc/index-report.txt Log: Typo. Modified: pypy/dist/pypy/doc/index-report.txt ============================================================================== --- pypy/dist/pypy/doc/index-report.txt (original) +++ pypy/dist/pypy/doc/index-report.txt Thu Apr 12 19:41:11 2007 @@ -19,7 +19,7 @@ `D06.1 Core Object Optimization Results`_ documents the optimizations we implemented in the interpreter and object space: dictionary -imlementations, method call optimizations, etc. The report is still not final +implementations, method call optimizations, etc. The report is still not final so we are very interested in any feedback *(2007-04-04)* `D14.5 Documentation of the development process`_ documents PyPy's From fijal at codespeak.net Thu Apr 12 19:50:21 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Apr 2007 19:50:21 +0200 (CEST) Subject: [pypy-svn] r42004 - in pypy/dist/pypy/objspace: cpy cpy/test std Message-ID: <20070412175021.353C980A9@code0.codespeak.net> Author: fijal Date: Thu Apr 12 19:50:20 2007 New Revision: 42004 Modified: pypy/dist/pypy/objspace/cpy/objspace.py pypy/dist/pypy/objspace/cpy/test/test_objspace.py pypy/dist/pypy/objspace/std/objspace.py Log: Change newunicode semantics to use list of unichars Modified: pypy/dist/pypy/objspace/cpy/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/objspace.py Thu Apr 12 19:50:20 2007 @@ -236,7 +236,7 @@ def newunicode(self, codes): # XXX inefficient - lst = [PyUnicode_FromOrdinal(code) for code in codes] + lst = [PyUnicode_FromOrdinal(ord(code)) for code in codes] w_lst = self.newlist(lst) w_emptyunicode = PyUnicode_FromUnicode(None, 0) return self.call_method(w_emptyunicode, 'join', w_lst) Modified: pypy/dist/pypy/objspace/cpy/test/test_objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/test/test_objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/test/test_objspace.py Thu Apr 12 19:50:20 2007 @@ -56,7 +56,7 @@ def test_newunicode(): space = CPyObjSpace() - w = space.newunicode([65, 66]) + w = space.newunicode([unichr(65), unichr(66)]) assert space.is_w(space.type(w), space.w_unicode) for i in range(2): code = space.int_w(space.ord(space.getitem(w, space.wrap(i)))) @@ -68,9 +68,9 @@ assert space.int_w(space.ord(w)) == 65 w = space.wrap('\x00') assert space.int_w(space.ord(w)) == 0 - w = space.newunicode([65]) + w = space.newunicode([unichr(65)]) assert space.int_w(space.ord(w)) == 65 - w = space.newunicode([0]) + w = space.newunicode([unichr(0)]) assert space.int_w(space.ord(w)) == 0 def test_id(): Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Apr 12 19:50:20 2007 @@ -531,11 +531,6 @@ return self.wrap(''.join(chars)) def newunicode(self, chars): - try: - chars = [unichr(c) for c in chars] - except ValueError, e: # unichr(out-of-range) - msg = "character code not in range(%s)" % hex(sys.maxunicode+1) - raise OperationError(self.w_ValueError, self.wrap(msg)) return W_UnicodeObject(chars) def newseqiter(self, w_obj): From fijal at codespeak.net Thu Apr 12 19:51:08 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Apr 2007 19:51:08 +0200 (CEST) Subject: [pypy-svn] r42005 - in pypy/dist/pypy/module: __builtin__ unicodedata Message-ID: <20070412175108.EC87B80A9@code0.codespeak.net> Author: fijal Date: Thu Apr 12 19:51:08 2007 New Revision: 42005 Modified: pypy/dist/pypy/module/__builtin__/operation.py pypy/dist/pypy/module/unicodedata/interp_ucd.py Log: Use list[unichr] as a parameter of space.newunicode Modified: pypy/dist/pypy/module/__builtin__/operation.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/operation.py (original) +++ pypy/dist/pypy/module/__builtin__/operation.py Thu Apr 12 19:51:08 2007 @@ -4,7 +4,8 @@ from pypy.interpreter import gateway from pypy.interpreter.baseobjspace import ObjSpace -from pypy.interpreter.error import OperationError +from pypy.interpreter.error import OperationError +import __builtin__ NoneNotWrapped = gateway.NoneNotWrapped def abs(space, w_val): @@ -18,7 +19,7 @@ def unichr(space, w_code): "Return a Unicode string of one character with the given ordinal." - return space.newunicode([space.int_w(w_code)]) + return space.newunicode([__builtin__.unichr(space.int_w(w_code))]) def len(space, w_obj): "len(object) -> integer\n\nReturn the number of items of a sequence or mapping." Modified: pypy/dist/pypy/module/unicodedata/interp_ucd.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/interp_ucd.py (original) +++ pypy/dist/pypy/module/unicodedata/interp_ucd.py Thu Apr 12 19:51:08 2007 @@ -215,10 +215,10 @@ result[0] = ch if not composed: # If decomposed normalization we are done - return space.newunicode(result[:j]) + return space.newunicode([unichr(i) for i in result[:j]]) if j <= 1: - return space.newunicode(result[:j]) + return space.newunicode([unichr(i) for i in result[:j]]) current = result[0] starter_pos = 0 @@ -268,7 +268,7 @@ result[starter_pos] = current - return space.newunicode(result[:next_insert]) + return space.newunicode([unichr(i) for i in result[:next_insert]]) normalize.unwrap_spec = ['self', ObjSpace, str, W_Root] From fijal at codespeak.net Thu Apr 12 21:44:25 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Apr 2007 21:44:25 +0200 (CEST) Subject: [pypy-svn] r42008 - in pypy/dist/pypy: module/__builtin__ rlib Message-ID: <20070412194425.ED7E380AD@code0.codespeak.net> Author: fijal Date: Thu Apr 12 21:44:24 2007 New Revision: 42008 Modified: pypy/dist/pypy/module/__builtin__/special.py pypy/dist/pypy/rlib/rarithmetic.py Log: Move overflow checking version of formatd from __builtin__.special to rlib, to reuse by formatting Modified: pypy/dist/pypy/module/__builtin__/special.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/special.py (original) +++ pypy/dist/pypy/module/__builtin__/special.py Thu Apr 12 21:44:24 2007 @@ -3,19 +3,11 @@ from pypy.rlib import rarithmetic def _formatd(space, alt, prec, kind, x): - formatd_max_length = rarithmetic.formatd_max_length - if ((kind == 'g' and formatd_max_length <= 10+prec) or - (kind == 'f' and formatd_max_length <= 53+prec)): - raise OperationError(space.w_OverflowError, - space.wrap("formatted float is too long (precision too large?)")) - if alt: - alt = '#' - else: - alt = '' - - fmt = "%%%s.%d%s" % (alt, prec, kind) - - return space.wrap(rarithmetic.formatd(fmt, x)) + try: + return space.wrap(rarithmetic.formatd_overflow(alt, prec, kind, x)) + except OverflowError: + raise OperationError(space.w_OverflowError, space.wrap( + "formatted float is too long (precision too large?)")) _formatd.unwrap_spec = [gateway.ObjSpace, int, int, str, float] Modified: pypy/dist/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rlib/rarithmetic.py (original) +++ pypy/dist/pypy/rlib/rarithmetic.py Thu Apr 12 21:44:24 2007 @@ -409,6 +409,19 @@ def formatd(fmt, x): return fmt % (x,) +def formatd_overflow(alt, prec, kind, x): + if ((kind == 'g' and formatd_max_length <= 10+prec) or + (kind == 'f' and formatd_max_length <= 53+prec)): + raise OverflowError("formatted float is too long (precision too large?)") + if alt: + alt = '#' + else: + alt = '' + + fmt = "%%%s.%d%s" % (alt, prec, kind) + + return formatd(fmt, x) + # a common string hash function def _hash_string(s): From fijal at codespeak.net Thu Apr 12 21:45:27 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Apr 2007 21:45:27 +0200 (CEST) Subject: [pypy-svn] r42009 - in pypy/dist/pypy/lib/distributed: . demo Message-ID: <20070412194527.83F6F80AD@code0.codespeak.net> Author: fijal Date: Thu Apr 12 21:45:27 2007 New Revision: 42009 Modified: pypy/dist/pypy/lib/distributed/demo/sockdemo.py pypy/dist/pypy/lib/distributed/socklayer.py Log: Fix demo. Long laying in WC checkin Modified: pypy/dist/pypy/lib/distributed/demo/sockdemo.py ============================================================================== --- pypy/dist/pypy/lib/distributed/demo/sockdemo.py (original) +++ pypy/dist/pypy/lib/distributed/demo/sockdemo.py Thu Apr 12 21:45:27 2007 @@ -1,5 +1,8 @@ from distributed import RemoteProtocol, remote_loop +from distributed.socklayer import Finished, socket_listener, socket_connecter + +PORT = 12122 class X: def __init__(self, z): @@ -10,23 +13,24 @@ def raising(self): 1/0 - + x = X(3) def remote(): - from distributed.socklayer import socket_listener - send, receive = socket_listener() + send, receive = socket_listener(address=('', PORT)) remote_loop(RemoteProtocol(send, receive, globals())) def local(): - from distributed.socklayer import socket_connecter - send, receive = socket_connecter(('localhost', 12122)) + send, receive = socket_connecter(('localhost', PORT)) return RemoteProtocol(send, receive) import sys if __name__ == '__main__': if len(sys.argv) > 1 and sys.argv[1] == '-r': - remote() + try: + remote() + except Finished: + print "Finished" else: rp = local() x = rp.get_remote("x") Modified: pypy/dist/pypy/lib/distributed/socklayer.py ============================================================================== --- pypy/dist/pypy/lib/distributed/socklayer.py (original) +++ pypy/dist/pypy/lib/distributed/socklayer.py Thu Apr 12 21:45:27 2007 @@ -11,6 +11,9 @@ if TRACE: print >>sys.stderr, msg +class Finished(Exception): + pass + class SocketWrapper(object): def __init__(self, conn): self.buffer = "" @@ -19,7 +22,10 @@ def receive(self): msg, self.buffer = decodemessage(self.buffer) while msg is None: - self.buffer += self.conn.recv(8192) + data = self.conn.recv(8192) + if not data: + raise Finished() + self.buffer += data msg, self.buffer = decodemessage(self.buffer) assert msg[0] == 'c' trace("received %s" % msg[1]) From fijal at codespeak.net Thu Apr 12 21:46:42 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Apr 2007 21:46:42 +0200 (CEST) Subject: [pypy-svn] r42010 - pypy/dist/pypy/lib Message-ID: <20070412194642.C37D580AD@code0.codespeak.net> Author: fijal Date: Thu Apr 12 21:46:42 2007 New Revision: 42010 Modified: pypy/dist/pypy/lib/_formatting.py Log: checkin some silly changes to delete this file later Modified: pypy/dist/pypy/lib/_formatting.py ============================================================================== --- pypy/dist/pypy/lib/_formatting.py (original) +++ pypy/dist/pypy/lib/_formatting.py Thu Apr 12 21:46:42 2007 @@ -1,3 +1,4 @@ + # Application level implementation of string formatting. # There's some insane stuff in here. Blame CPython. Please. @@ -14,7 +15,7 @@ # for the usage of rpython-level unicode strings. -import sys +import sys, py class _Flags(object): def __repr__(self): @@ -33,12 +34,13 @@ if not v.isint(): raise TypeError, "* wants int" return fmtiter.next(), v.maybe_int() - n = '' + i0 = fmtiter.i - 1 + ik = i0 while c in '0123456789': - n += c c = fmtiter.next() - if n: - return c, int(n) + ik += 1 + if ik != i0: + return c, int(fmtiter.fmt[i0:ik]) else: return c, 0 @@ -69,7 +71,8 @@ value = None gotvalue = False if c == '(': - n = '' + i0 = fmtiter.i + ik = i0 pcount = 1 while 1: c = fmtiter.next() @@ -79,8 +82,8 @@ break elif c == '(': pcount += 1 - n += c - value = valuegetter.getitem(n) + ik += 1 + value = valuegetter.getitem(fmtiter.fmt[i0:ik]) gotvalue = True c = fmtiter.next() c, flags = peel_flags(c, fmtiter) @@ -108,72 +111,67 @@ class NeedUnicodeFormattingError(Exception): pass -class Formatter(object): - def __init__(self, char, flags, width, prec, valuebox): - self.char = char - self.flags = flags - self.width = width - self.prec = prec - self.valuebox = valuebox - - def numeric_preprocess(self, v): - # negative zeroes? - # * mwh giggles, falls over - # still, if we can recognize them, here's the place to do it. - import math - if v < 0 or v == 0 and isinstance(v, float) and math.atan2(0, v) != 0: - sign = '-' - v = -v - else: - if self.flags.f_sign: - sign = '+' - elif self.flags.f_blank: - sign = ' ' - else: - sign = '' - return v, sign - def numeric_postprocess(self, r, sign, prefix=""): - assert self.char in 'iduoxXeEfFgG' - padchar = ' ' - if self.flags.f_zero: - padchar = '0' - if self.width is not None: - p = self.width - len(r) - len(sign) -len(prefix) - if self.flags.f_ljust: - r = sign + prefix + r + ' '*p - else: - if self.flags.f_zero: - r = sign+prefix+padchar*p + r - else: - r = padchar*p + sign + prefix + r +#class Formatter(object): +# def __init__(self, char, flags, width, prec, valuebox): +# self.char = char +# self.flags = flags +# self.width = width +# self.prec = prec +# self.valuebox = valuebox + +def numeric_preprocess(v, flags): + # negative zeroes? + # * mwh giggles, falls over + # still, if we can recognize them, here's the place to do it. + import math + if v < 0 or v == 0 and isinstance(v, float) and math.atan2(0, v) != 0: + sign = '-' + v = -v + else: + if flags.f_sign: + sign = '+' + elif flags.f_blank: + sign = ' ' else: - r = sign + prefix + r - return r - - def format(self): - raise NotImplementedError + sign = '' + return v, sign - def std_wp(self, r): - assert self.char not in 'iduoxXeEfFgG' - if self.prec is not None: - r = r[:self.prec] - if self.width is not None: - p = self.width - len(r) - if self.flags.f_ljust: - r = r + ' '*p +def numeric_postprocess(r, sign, char, flags, width, prefix=""): + assert char in 'iduoxXeEfFgG' + padchar = ' ' + if flags.f_zero: + padchar = '0' + if width is not None: + p = width - len(r) - len(sign) -len(prefix) + if flags.f_ljust: + r = sign + prefix + r + ' '*p + else: + if flags.f_zero: + r = sign+prefix+padchar*p + r else: - r = ' '*p + r - return r + r = padchar*p + sign + prefix + r + else: + r = sign + prefix + r + return r +def std_wp(r, char, flags, width, prec): + assert char not in 'iduoxXeEfFgG' + if prec is not None: + r = r[:prec] + if width is not None: + p = width - len(r) + if flags.f_ljust: + r = r + ' '*p + else: + r = ' '*p + r + return r -class ReprFormatter(Formatter): - def format(self): - return self.std_wp(self.valuebox.repr()) +def repr_format(char, flags, width, prec, valuebox): + return std_wp(valuebox.repr(), char, flags, width, prec) -class PercentFormatter(Formatter): - def format(self): - return self.std_wp('%') +def percent_format(char, flags, width, prec, valuebox): + return std_wp('%', char, flags, width, prec) # isinf isn't too hard... def isinf(v): @@ -185,210 +183,186 @@ def isnan(v): return v != v*1.0 or (v == 1.0 and v == 2.0) -class FloatFormatter(Formatter): - def eDigits(self, ds): - ds = ds[:self.prec + 1] + ['0'] * (self.prec + 1 - len(ds)) - if self.prec > 0 or self.flags.f_alt: - ds[1:1] = ['.'] - return ''.join(ds) - - def fDigits(self, ds, k): - p = max(self.prec, 0) - if 0 < k < len(ds): - if len(ds) - k < p: - ds.extend(['0'] * (p - (len(ds) - k))) - else: - ds = ds[:p + k] - ds[k:k] = ['.'] - elif k <= 0: - ds[0:0] = ['0']*(-k) - ds = ds[:p] - ds.extend(['0'] * (p - len(ds))) - ds[0:0]= ['0', '.'] - elif k >= len(ds): - ds.extend((k-len(ds))*['0'] + ['.'] + ['0']*p) - return ''.join(ds) - - def format(self): - v = self.valuebox.maybe_float() - if isnan(v): - return 'nan' - elif isinf(v): - return 'inf' - v, sign = self.numeric_preprocess(v) - if self.prec is None: - self.prec = 6 - r = self._format(v) - return self.numeric_postprocess(r, sign) - - def _formatd(self, kind, v): - import __builtin__ - return __builtin__._formatd(self.flags.f_alt, self.prec, kind, v) - -class FloatFFormatter(FloatFormatter): - def _format(self, v): - if v/1e25 > 1e25: - return FloatGFormatter('g', self.flags, self.width, - self.prec, self.valuebox).format() - return self._formatd('f', v) - -# system specific formatting. Linux does 3, Windows does 4... -# XXX this works only when we use geninte