From cfbolz at codespeak.net Fri Jun 1 01:18:59 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 1 Jun 2007 01:18:59 +0200 (CEST) Subject: [pypy-svn] r43952 - in pypy/dist/pypy/lang/prolog: builtin interpreter interpreter/test Message-ID: <20070531231859.1153080AE@code0.codespeak.net> Author: cfbolz Date: Fri Jun 1 01:18:58 2007 New Revision: 43952 Modified: pypy/dist/pypy/lang/prolog/builtin/allsolution.py pypy/dist/pypy/lang/prolog/builtin/exception.py pypy/dist/pypy/lang/prolog/builtin/formatting.py pypy/dist/pypy/lang/prolog/builtin/register.py pypy/dist/pypy/lang/prolog/builtin/termconstruction.py pypy/dist/pypy/lang/prolog/interpreter/engine.py pypy/dist/pypy/lang/prolog/interpreter/parsing.py pypy/dist/pypy/lang/prolog/interpreter/term.py pypy/dist/pypy/lang/prolog/interpreter/test/test_builtin.py pypy/dist/pypy/lang/prolog/interpreter/test/test_engine.py pypy/dist/pypy/lang/prolog/interpreter/test/test_unification.py pypy/dist/pypy/lang/prolog/interpreter/test/tool.py Log: refactor the way logic variables in the prolog interpreter are handled to be quite a bit simpler Modified: pypy/dist/pypy/lang/prolog/builtin/allsolution.py ============================================================================== --- pypy/dist/pypy/lang/prolog/builtin/allsolution.py (original) +++ pypy/dist/pypy/lang/prolog/builtin/allsolution.py Fri Jun 1 01:18:58 2007 @@ -26,8 +26,7 @@ for i in range(len(collector.found) - 1, -1, -1): copy = collector.found[i] d = {} - copy = copy.clone_compress_vars(d, engine.heap.maxvar()) - engine.heap.extend(len(d)) + copy = copy.copy(engine.heap, d) result = term.Term(".", [copy, result]) bag.unify(result, engine.heap) expose_builtin(impl_findall, "findall", unwrap_spec=['raw', 'callable', 'raw']) Modified: pypy/dist/pypy/lang/prolog/builtin/exception.py ============================================================================== --- pypy/dist/pypy/lang/prolog/builtin/exception.py (original) +++ pypy/dist/pypy/lang/prolog/builtin/exception.py Fri Jun 1 01:18:58 2007 @@ -17,8 +17,7 @@ exc_term = e.term.getvalue(engine.heap) engine.heap.revert(old_state) d = {} - exc_term = exc_term.clone_compress_vars(d, engine.heap.maxvar()) - engine.heap.extend(len(d)) + exc_term = exc_term.copy(engine.heap, d) try: impl_ground(engine, exc_term) except error.UnificationFailed: Modified: pypy/dist/pypy/lang/prolog/builtin/formatting.py ============================================================================== --- pypy/dist/pypy/lang/prolog/builtin/formatting.py (original) +++ pypy/dist/pypy/lang/prolog/builtin/formatting.py Fri Jun 1 01:18:58 2007 @@ -14,6 +14,7 @@ self.ignore_ops = ignore_ops self.curr_depth = 0 self._make_reverse_op_mapping() + self.var_to_number = {} def from_option_list(engine, options): # XXX add numbervars support @@ -76,8 +77,11 @@ return str(num.floatval) def format_var(self, var): - return "_G%s" % (var.index, ) - + try: + num = self.var_to_number[var] + except KeyError: + num = self.var_to_number[var] = len(self.var_to_number) + return "_G%s" % (num, ) def format_term_normally(self, term): return "%s(%s)" % (self.format_atom(term.name), Modified: pypy/dist/pypy/lang/prolog/builtin/register.py ============================================================================== --- pypy/dist/pypy/lang/prolog/builtin/register.py (original) +++ pypy/dist/pypy/lang/prolog/builtin/register.py Fri Jun 1 01:18:58 2007 @@ -1,5 +1,4 @@ import py -from pypy.lang.prolog.interpreter import arithmetic from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder from pypy.lang.prolog.interpreter import engine, helper, term, error from pypy.lang.prolog.builtin import builtins, builtins_list @@ -66,7 +65,7 @@ elif spec == "atom": code.append(" %s = helper.unwrap_atom(%s)" % (varname, varname)) elif spec == "arithmetic": - code.append(" %s = arithmetic.eval_arithmetic(engine, %s)" % + code.append(" %s = %s.eval_arithmetic(engine)" % (varname, varname)) elif spec == "list": code.append(" %s = helper.unwrap_list(%s)" % (varname, varname)) Modified: pypy/dist/pypy/lang/prolog/builtin/termconstruction.py ============================================================================== --- pypy/dist/pypy/lang/prolog/builtin/termconstruction.py (original) +++ pypy/dist/pypy/lang/prolog/builtin/termconstruction.py Fri Jun 1 01:18:58 2007 @@ -15,8 +15,6 @@ elif isinstance(t, term.Var): if isinstance(functor, term.Var): error.throw_instantiation_error() - elif isinstance(functor, term.Var): - error.throw_instantiation_error() a = helper.unwrap_int(arity) if a < 0: error.throw_domain_error("not_less_than_zero", arity) @@ -26,11 +24,8 @@ t.unify(helper.ensure_atomic(functor), engine.heap) else: name = helper.unwrap_atom(functor) - start = engine.heap.needed_vars - engine.heap.extend(a) t.unify( - term.Term(name, - [term.Var(i) for i in range(start, start + a)]), + term.Term(name, [term.Var() for i in range(a)]), engine.heap) expose_builtin(impl_functor, "functor", unwrap_spec=["obj", "obj", "obj"]) @@ -92,8 +87,7 @@ def impl_copy_term(engine, interm, outterm): d = {} - copy = interm.clone_compress_vars(d, engine.heap.maxvar()) - engine.heap.extend(len(d)) + copy = interm.copy(engine.heap, d) outterm.unify(copy, engine.heap) expose_builtin(impl_copy_term, "copy_term", unwrap_spec=["obj", "obj"]) Modified: pypy/dist/pypy/lang/prolog/interpreter/engine.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/engine.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/engine.py Fri Jun 1 01:18:58 2007 @@ -37,76 +37,36 @@ self.scope_active = False return self.continuation.call(engine, choice_point=False) -START_NUMBER_OF_VARS = 4096 - - class Heap(object): def __init__(self): - self.vars = [None] * START_NUMBER_OF_VARS self.trail = [] - self.needed_vars = 0 - self.last_branch = 0 def reset(self): - self.vars = [None] * len(self.vars) self.trail = [] self.last_branch = 0 - def clear(self, length): - l = max(START_NUMBER_OF_VARS, length) - self.vars = [None] * l - self.needed_vars = length - self.last_branch = length - self.trail = [] - - def getvar(self, index): - return self.vars[index] - - def setvar(self, index, val): - oldval = self.vars[index] - self.vars[index] = val - # only trail for variables that have a chance to get restored - # on the last choice point - if index < self.last_branch and oldval is not val: - self.trail.append((index, oldval)) + def add_trail(self, var): + self.trail.append((var, var.binding)) def branch(self): - old_last_branch = self.last_branch - self.last_branch = self.needed_vars - return len(self.trail), self.needed_vars, old_last_branch + return len(self.trail) def revert(self, state): - trails, length, old_last_branch = state - assert length == self.last_branch + trails = state for i in range(len(self.trail) - 1, trails - 1, -1): - index, val = self.trail[i] - if index >= length: - val = None - self.vars[index] = val - for i in range(length, self.needed_vars): - self.vars[i] = None + var, val = self.trail[i] + var.binding = val del self.trail[trails:] - self.needed_vars = length def discard(self, state): - old_last_branch = state[2] - self.last_branch = old_last_branch - - def extend(self, numvars): - if numvars: - self.needed_vars += numvars - newvars = max(0, numvars - (len(self.vars) - self.needed_vars)) - if newvars == 0: - return - self.vars.extend([None] * (2 * newvars)) # allocate a bit more - assert self.needed_vars <= len(self.vars) + pass #XXX for now def maxvar(self): + XXX return self.needed_vars def newvar(self): - result = Var.newvar(self.maxvar()) - self.extend(1) + result = Var(self) return result class LinkedRules(object): @@ -211,8 +171,6 @@ def run(self, query, continuation=DONOTHING): if not isinstance(query, Callable): error.throw_type_error("callable", query) - vars = query.get_max_var() + 1 - self.heap.clear(vars) try: return self.call(query, continuation, choice_point=True) except CutException, e: @@ -412,7 +370,7 @@ builder = TermBuilder() trees = parse_file(s, self.parser) terms = builder.build_many(trees) - return terms, builder.var_to_pos + return terms, builder.varname_to_var def getoperations(self): from pypy.lang.prolog.interpreter.parsing import default_operations Modified: pypy/dist/pypy/lang/prolog/interpreter/parsing.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/parsing.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/parsing.py Fri Jun 1 01:18:58 2007 @@ -219,7 +219,7 @@ s = parser_query.parse(tokens, lazy=False) builder = TermBuilder() query = builder.build(s) - return query, builder.var_to_pos + return query, builder.varname_to_var class OrderTransformer(object): def transform(self, node): @@ -271,8 +271,7 @@ class TermBuilder(RPythonVisitor): def __init__(self): - self.var_to_pos = {} - self.freevar = 0 + self.varname_to_var = {} def build(self, s): "NOT_RPYTHON" @@ -294,8 +293,7 @@ return self.visit(s.children[0]) def build_fact(self, node): - self.var_to_pos = {} - self.freevar = 0 + self.varname_to_var = {} return self.visit(node.children[0]) def visit(self, node): @@ -355,14 +353,11 @@ from pypy.lang.prolog.interpreter.term import Var varname = node.additional_info if varname == "_": - pos = self.freevar - self.freevar += 1 - return Var.newvar(pos) - if varname in self.var_to_pos: - return self.var_to_pos[varname] - res = Var.newvar(self.freevar) - self.freevar += 1 - self.var_to_pos[varname] = res + return Var() + if varname in self.varname_to_var: + return self.varname_to_var[varname] + res = Var() + self.varname_to_var[varname] = res return res def visit_NUMBER(self, node): Modified: pypy/dist/pypy/lang/prolog/interpreter/term.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/term.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/term.py Fri Jun 1 01:18:58 2007 @@ -36,18 +36,12 @@ def dereference(self, heap): raise NotImplementedError("abstract base class") - def get_max_var(self): - return -1 - def copy(self, heap, memo): raise NotImplementedError("abstract base class") def copy_and_unify(self, other, heap, memo): raise NotImplementedError("abstract base class") - def clone_compress_vars(self, vars_new_indexes, offset): - return self - def get_unify_hash(self, heap): # if two non-var objects return two different numbers # they must not be unifiable @@ -80,12 +74,11 @@ TAG = 0 STANDARD_ORDER = 0 - __slots__ = ('index', ) + __slots__ = ('binding', ) cache = {} - _immutable_ = True - def __init__(self, index): - self.index = index + def __init__(self, heap=None): + self.binding = None @specialize.arg(3) def unify(self, other, heap, occurs_check=False): @@ -99,16 +92,16 @@ elif occurs_check and other.contains_var(self, heap): raise UnificationFailed() else: - heap.setvar(self.index, other) + self.setvalue(other, heap) def dereference(self, heap): - next = heap.getvar(self.index) + next = self.binding if next is None: return self else: result = next.dereference(heap) # do path compression - heap.setvar(self.index, result) + self.setvalue(result, heap) return result def getvalue(self, heap): @@ -117,6 +110,10 @@ return res.getvalue(heap) return res + def setvalue(self, value, heap): + heap.add_trail(self) + self.binding = value + def copy(self, heap, memo): hint(self, concrete=True) try: @@ -137,17 +134,6 @@ seen_value.unify(other, heap) return seen_value - - def get_max_var(self): - return self.index - - def clone_compress_vars(self, vars_new_indexes, offset): - if self.index in vars_new_indexes: - return Var.newvar(vars_new_indexes[self.index]) - index = len(vars_new_indexes) + offset - vars_new_indexes[self.index] = index - return Var.newvar(index) - def get_unify_hash(self, heap): if heap is not None: self = self.dereference(heap) @@ -165,22 +151,12 @@ return False def __repr__(self): - return "Var(%s)" % (self.index, ) + return "Var(%s)" % (self.binding, ) def __eq__(self, other): # for testing - return (self.__class__ == other.__class__ and - self.index == other.index) - - @staticmethod - @purefunction - def newvar(index): - result = Var.cache.get(index, None) - if result is not None: - return result - Var.cache[index] = result = Var(index) - return result + return self is other def eval_arithmetic(self, engine): self = self.dereference(engine.heap) @@ -413,9 +389,6 @@ def _clone(obj, offset): return obj.clone(offset) -def _clone_compress_vars(obj, vars_new_indexes, offset): - return obj.clone_compress_vars(vars_new_indexes, offset) - def _getvalue(obj, heap): return obj.getvalue(heap) @@ -475,15 +448,6 @@ else: raise UnificationFailed - def get_max_var(self): - result = -1 - for subterm in self.args: - result = max(result, subterm.get_max_var()) - return result - - def clone_compress_vars(self, vars_new_indexes, offset): - return self._copy_term(_clone_compress_vars, vars_new_indexes, offset) - def getvalue(self, heap): return self._copy_term(_getvalue, heap) @@ -542,16 +506,13 @@ unify_hash = [] def __init__(self, head, body): from pypy.lang.prolog.interpreter import helper - d = {} - head = head.clone_compress_vars(d, 0) assert isinstance(head, Callable) self.head = head if body is not None: body = helper.ensure_callable(body) - self.body = body.clone_compress_vars(d, 0) + self.body = body else: self.body = None - self.numvars = len(d) self.signature = self.head.signature if isinstance(head, Term): self.unify_hash = [arg.get_unify_hash(None) for arg in head.args] @@ -611,7 +572,7 @@ return c if isinstance(obj1, Var): assert isinstance(obj2, Var) - return rcmp(obj1.index, obj2.index) + return rcmp(id(obj1), id(obj2)) if isinstance(obj1, Atom): assert isinstance(obj2, Atom) return rcmp(obj1.name, obj2.name) Modified: pypy/dist/pypy/lang/prolog/interpreter/test/test_builtin.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/test/test_builtin.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/test/test_builtin.py Fri Jun 1 01:18:58 2007 @@ -105,12 +105,12 @@ assert_true("assertz(f(a, a)).", e) assert_true("A = a, asserta(h(A, A)).", e) f = assert_true("g(B, B).", e) - assert f.vars[0].name == "b" + assert f['B'].name == "b" f = assert_true("f(B, B).", e) - assert f.vars[0].name == "b" + assert f['B'].name == "b" assert_false("h(c, c).", e) f = assert_true("h(B, B).", e) - assert f.vars[0].name == "a" + assert f['B'].name == "a" def test_assert_logical_update_view(): e = get_engine(""" @@ -281,7 +281,7 @@ assert_false("between(12, 15, 16).") heaps = collect_all(Engine(), "between(1, 4, X).") assert len(heaps) == 4 - assert heaps[0].vars[0].num == 1 + assert heaps[0]['X'].num == 1 def test_is(): assert_true("5 is 1 + 1 + 1 + 1 + 1.") @@ -319,10 +319,12 @@ def test_standard_comparison(): assert_true("X = Y, f(X, Y, X, Y) == f(X, X, Y, Y).") assert_true("X = Y, f(X, Y, X, Z) \\== f(X, X, Y, Y).") - assert_true("X @< Y, X @=< X, X @=< Y, Y @> X.") + assert_true("""X \\== Y, ((X @< Y, X @=< X, X @=< Y, Y @> X); + (X @> Y, X @>= X, X @>= Y, Y @< X)).""") assert_true("'\\\\=='(f(X, Y), 12).") assert_true("X = f(a), Y = f(b), Y @> X.") + def test_atom_length(): assert_true("atom_length('abc', 3).") assert_true("atom_length('\\\\', 1).") Modified: pypy/dist/pypy/lang/prolog/interpreter/test/test_engine.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/test/test_engine.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/test/test_engine.py Fri Jun 1 01:18:58 2007 @@ -1,6 +1,7 @@ import py from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder from pypy.lang.prolog.interpreter.parsing import parse_query_term, get_engine +from pypy.lang.prolog.interpreter.parsing import get_query_and_vars from pypy.lang.prolog.interpreter.error import UnificationFailed, CatchableError from pypy.lang.prolog.interpreter.test.tool import collect_all, assert_true, assert_false from pypy.lang.prolog.interpreter.test.tool import prolog_raises @@ -9,8 +10,9 @@ e = get_engine(""" f(a). """) - e.run(parse_query_term("f(X).")) - assert e.heap.getvar(0).name == "a" + t, vars = get_query_and_vars("f(X).") + e.run(t) + assert vars['X'].dereference(e.heap).name == "a" def test_and(): e = get_engine(""" @@ -20,9 +22,9 @@ f(X, Z) :- g(X, Y), g(Y, Z). """) e.run(parse_query_term("f(a, c).")) - e.run(parse_query_term("f(X, c).")) - print e.heap.vars[:10] - assert e.heap.getvar(0).name == "a" + t, vars = get_query_and_vars("f(X, c).") + e.run(t) + assert vars['X'].dereference(e.heap).name == "a" def test_and_long(): e = get_engine(""" @@ -52,8 +54,9 @@ return "succ(%s)" % nstr(n - 1) e.run(parse_query_term("num(0).")) e.run(parse_query_term("num(succ(0)).")) - e.run(parse_query_term("num(X).")) - assert e.heap.getvar(0).num == 0 + t, vars = get_query_and_vars("num(X).") + e.run(t) + assert vars['X'].dereference(e.heap).num == 0 e.run(parse_query_term("add(0, 0, 0).")) py.test.raises(UnificationFailed, e.run, parse_query_term(""" add(0, 0, succ(0)).""")) @@ -88,8 +91,9 @@ g(a, a). f(X, Y, Z) :- (g(X, Z); g(X, Z); g(Z, Y)), a(Z). """) - e.run(parse_query_term("f(a, b, Z).")) - assert e.heap.getvar(0).name == "a" + t, vars = get_query_and_vars("f(a, b, Z).") + e.run(t) + assert vars['Z'].dereference(e.heap).name == "a" f = collect_all(e, "X = 1; X = 2.") assert len(f) == 2 @@ -127,9 +131,9 @@ """) heaps = collect_all(e, "g(X).") assert len(heaps) == 3 - assert heaps[0].getvar(0).name == "a" - assert heaps[1].getvar(0).name == "b" - assert heaps[2].getvar(0).name == "c" + assert heaps[0]['X'].name == "a" + assert heaps[1]['X'].name == "b" + assert heaps[2]['X'].name == "c" def test_cut(): e = get_engine(""" Modified: pypy/dist/pypy/lang/prolog/interpreter/test/test_unification.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/test/test_unification.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/test/test_unification.py Fri Jun 1 01:18:58 2007 @@ -11,41 +11,35 @@ py.test.raises(UnificationFailed, "a.unify(Atom.newatom('xxx'), None)") def test_var(): - b = Var.newvar(0) + b = Var() heap = Heap() - heap.clear(1) b.unify(Atom.newatom("hallo"), heap) assert b.getvalue(heap).name == "hallo" - a = Var.newvar(0) - b = Var.newvar(1) - heap.clear(2) + a = Var() + b = Var() a.unify(b, heap) a.unify(Atom.newatom("hallo"), heap) assert a.getvalue(heap).name == "hallo" assert b.getvalue(heap).name == "hallo" def test_unify_var(): - b = Var.newvar(0) + b = Var() heap = Heap() - heap.clear(1) b.unify(b, heap) b.unify(Atom.newatom("hallo"), heap) py.test.raises(UnificationFailed, b.unify, Atom.newatom("bye"), heap) def test_recursive(): - b = Var.newvar(0) + b = Var() heap = Heap() - heap.clear(1) b.unify(Term("hallo", [b]), heap) - def test_term(): - X = Var.newvar(0) - Y = Var.newvar(1) + X = Var() + Y = Var() t1 = Term("f", [Atom.newatom("hallo"), X]) t2 = Term("f", [Y, Atom.newatom("HALLO")]) heap = Heap() - heap.clear(2) print t1, t2 t1.unify(t2, heap) assert X.getvalue(heap).name == "HALLO" @@ -61,9 +55,11 @@ def test_run(): e = Engine() e.add_rule(Term("f", [Atom.newatom("a"), Atom.newatom("b")])) - e.add_rule(Term("f", [Var.newvar(0), Var.newvar(0)])) - e.add_rule(Term(":-", [Term("f", [Var.newvar(0), Var.newvar(1)]), - Term("f", [Var.newvar(1), Var.newvar(0)])])) + X = Var() + Y = Var() + e.add_rule(Term("f", [X, X])) + e.add_rule(Term(":-", [Term("f", [X, Y]), + Term("f", [Y, X])])) X = e.heap.newvar() e.run(Term("f", [Atom.newatom("b"), X])) assert X.dereference(e.heap).name == "b" Modified: pypy/dist/pypy/lang/prolog/interpreter/test/tool.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/test/tool.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/test/tool.py Fri Jun 1 01:18:58 2007 @@ -6,12 +6,11 @@ def assert_true(query, e=None): if e is None: e = Engine() - term = e.parse(query)[0][0] + terms, vars = e.parse(query) + term, = terms e.run(term) - f = Heap() - f.vars = e.heap.vars[:] - return f - + return dict([(name, var.dereference(e.heap)) + for name, var in vars.iteritems()]) def assert_false(query, e=None): if e is None: e = Engine() @@ -23,20 +22,20 @@ (query, exc), e) class CollectAllContinuation(Continuation): - def __init__(self): + def __init__(self, vars): self.heaps = [] + self.vars = vars def _call(self, engine): - f = Heap() - f.vars = engine.heap.vars[:] - self.heaps.append(f) -# import pdb; pdb.set_trace() + self.heaps.append(dict([(name, var.dereference(engine.heap)) + for name, var in self.vars.iteritems()])) print "restarting computation" raise UnificationFailed def collect_all(engine, s): - collector = CollectAllContinuation() - term = engine.parse(s)[0][0] + terms, vars = engine.parse(s) + term, = terms + collector = CollectAllContinuation(vars) py.test.raises(UnificationFailed, engine.run, term, collector) return collector.heaps From fijal at codespeak.net Fri Jun 1 04:09:13 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Jun 2007 04:09:13 +0200 (CEST) Subject: [pypy-svn] r43953 - pypy/branch/kill-ctypes/pypy/rpython/module Message-ID: <20070601020913.D9BE580B0@code0.codespeak.net> Author: fijal Date: Fri Jun 1 04:09:12 2007 New Revision: 43953 Modified: pypy/branch/kill-ctypes/pypy/rpython/module/ll_termios.py Log: We've got try: finally: in rpython, forgotten.. Modified: pypy/branch/kill-ctypes/pypy/rpython/module/ll_termios.py ============================================================================== --- pypy/branch/kill-ctypes/pypy/rpython/module/ll_termios.py (original) +++ pypy/branch/kill-ctypes/pypy/rpython/module/ll_termios.py Fri Jun 1 04:09:12 2007 @@ -49,17 +49,18 @@ def tcgetattr_llimpl(fd): c_struct = lltype.malloc(TERMIOSP.TO, flavor='raw') error = c_tcgetattr(fd, c_struct) - if error == -1: + try: + if error == -1: + raise termios_error(error, 'tcgetattr failed') + cc = [chr(c_struct.c_c_cc[i]) for i in range(NCCS)] + ispeed = c_cfgetispeed(c_struct) + ospeed = c_cfgetospeed(c_struct) + result = (intmask(c_struct.c_c_iflag), intmask(c_struct.c_c_oflag), + intmask(c_struct.c_c_cflag), intmask(c_struct.c_c_lflag), + intmask(ispeed), intmask(ospeed), cc) + return result + finally: lltype.free(c_struct, flavor='raw') - raise termios_error(error, 'tcgetattr failed') - cc = [chr(c_struct.c_c_cc[i]) for i in range(NCCS)] - ispeed = c_cfgetispeed(c_struct) - ospeed = c_cfgetospeed(c_struct) - result = (intmask(c_struct.c_c_iflag), intmask(c_struct.c_c_oflag), - intmask(c_struct.c_c_cflag), intmask(c_struct.c_c_lflag), - intmask(ispeed), intmask(ospeed), cc) - lltype.free(c_struct, flavor='raw') - return result register_external(termios.tcgetattr, [int], (int, int, int, int, int, int, [str]), llimpl=tcgetattr_llimpl, export_name='termios.tcgetattr') @@ -68,21 +69,20 @@ c_struct = lltype.malloc(TERMIOSP.TO, flavor='raw') c_struct.c_c_iflag, c_struct.c_c_oflag, c_struct.c_c_cflag, \ c_struct.c_c_lflag, ispeed, ospeed, cc = attributes - for i in range(NCCS): - c_struct.c_c_cc[i] = rffi.r_uchar(ord(cc[i])) - error = c_cfsetispeed(c_struct, ispeed) - if error == -1: - lltype.free(c_struct, flavor='raw') - raise termios_error(error, 'tcsetattr failed') - error = c_cfsetospeed(c_struct, ospeed) - if error == -1: - lltype.free(c_struct, flavor='raw') - raise termios_error(error, 'tcsetattr failed') - error = c_tcsetattr(fd, when, c_struct) - if error == -1: + try: + for i in range(NCCS): + c_struct.c_c_cc[i] = rffi.r_uchar(ord(cc[i])) + error = c_cfsetispeed(c_struct, ispeed) + if error == -1: + raise termios_error(error, 'tcsetattr failed') + error = c_cfsetospeed(c_struct, ospeed) + if error == -1: + raise termios_error(error, 'tcsetattr failed') + error = c_tcsetattr(fd, when, c_struct) + if error == -1: + raise termios_error(error, 'tcsetattr failed') + finally: lltype.free(c_struct, flavor='raw') - raise termios_error(error, 'tcsetattr failed') - lltype.free(c_struct, flavor='raw') r_uint = rffi.r_uint register_external(termios.tcsetattr, [int, int, (r_uint, r_uint, r_uint, From fijal at codespeak.net Fri Jun 1 07:47:33 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Jun 2007 07:47:33 +0200 (CEST) Subject: [pypy-svn] r43964 - in pypy/branch/kill-ctypes/pypy/module/termios: . test Message-ID: <20070601054733.689AF80A8@code0.codespeak.net> Author: fijal Date: Fri Jun 1 07:47:33 2007 New Revision: 43964 Modified: pypy/branch/kill-ctypes/pypy/module/termios/interp_termios.py pypy/branch/kill-ctypes/pypy/module/termios/test/test_termios.py Log: Fix a bug in termios module and a test Modified: pypy/branch/kill-ctypes/pypy/module/termios/interp_termios.py ============================================================================== --- pypy/branch/kill-ctypes/pypy/module/termios/interp_termios.py (original) +++ pypy/branch/kill-ctypes/pypy/module/termios/interp_termios.py Fri Jun 1 07:47:33 2007 @@ -33,7 +33,8 @@ space.wrap(0), space.wrap(-1), space.wrap(1))) w_iflag, w_oflag, w_cflag, w_lflag, w_ispeed, w_ospeed = \ space.unpackiterable(tup_w) - cc = [space.str_w(c) for c in space.unpackiterable(w_cc)] + cc = [space.str_w(space.call_function(space.getattr(w_c, + space.wrap('__str__')))) for w_c in space.unpackiterable(w_cc)] tup = (space.int_w(w_iflag), space.int_w(w_oflag), space.int_w(w_cflag), space.int_w(w_lflag), space.int_w(w_ispeed), space.int_w(w_ospeed), cc) Modified: pypy/branch/kill-ctypes/pypy/module/termios/test/test_termios.py ============================================================================== --- pypy/branch/kill-ctypes/pypy/module/termios/test/test_termios.py (original) +++ pypy/branch/kill-ctypes/pypy/module/termios/test/test_termios.py Fri Jun 1 07:47:33 2007 @@ -60,6 +60,17 @@ child = self.spawn(['--withmod-termios', str(f)]) child.expect('ok!') + def test_tcsetattr(self): + source = py.code.Source(""" + import termios + termios.tcsetattr(0, 1, [16640, 4, 191, 2608, 15, 15, ['\x03', '\x1c', '\x7f', '\x15', '\x04', 0, 1, '\x00', '\x11', '\x13', '\x1a', '\x00', '\x12', '\x0f', '\x17', '\x16', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00']]) + print 'ok!' + """) + f = udir.join("test_tcsetattr.py") + f.write(source) + child = self.spawn(['--withmod-termios', str(f)]) + child.expect('ok!') + class AppTestTermios(object): def setup_class(cls): cls.space = gettestobjspace(usemodules=['termios']) From fijal at codespeak.net Fri Jun 1 07:48:38 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Jun 2007 07:48:38 +0200 (CEST) Subject: [pypy-svn] r43965 - in pypy/branch/kill-ctypes/pypy/rpython/lltypesystem: . test Message-ID: <20070601054838.0EED380A7@code0.codespeak.net> Author: fijal Date: Fri Jun 1 07:48:37 2007 New Revision: 43965 Modified: pypy/branch/kill-ctypes/pypy/rpython/lltypesystem/rffi.py pypy/branch/kill-ctypes/pypy/rpython/lltypesystem/test/test_rffi.py Log: Add a possibility to map backwards from charp to str. There is still open question what to do with free, since RTyper is sometimes complaining Modified: pypy/branch/kill-ctypes/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/kill-ctypes/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/kill-ctypes/pypy/rpython/lltypesystem/rffi.py Fri Jun 1 07:48:37 2007 @@ -18,11 +18,12 @@ def lltype(self): return self.TP -def llexternal(name, args, result, sources=[], includes=[]): +def llexternal(name, args, result, sources=[], includes=[], libraries=[]): ext_type = lltype.FuncType(args, result) return lltype.functionptr(ext_type, name, external='C', sources=tuple(sources), - includes=tuple(includes)) + includes=tuple(includes), + libraries=tuple(libraries)) def setup(): """ creates necessary c-level types @@ -61,6 +62,7 @@ CCHARP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True})) # various type mapping +# str -> char* def str2charp(s): """ str -> char* """ @@ -70,6 +72,16 @@ array[len(s)] = '\x00' return array +# char* -> str +# doesn't free char* +def charp2str(cp): + l = [] + i = 0 + while cp[i] != '\x00': + l.append(cp[i]) + i += 1 + return "".join(l) + # char** CCHARPP = lltype.Ptr(lltype.Array(CCHARP, hints={'nolength': True})) Modified: pypy/branch/kill-ctypes/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/kill-ctypes/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/kill-ctypes/pypy/rpython/lltypesystem/test/test_rffi.py Fri Jun 1 07:48:37 2007 @@ -1,5 +1,5 @@ -#import py +import py from pypy.rpython.lltypesystem.rffi import * from pypy.translator.c.test.test_genc import compile from pypy.rpython.lltypesystem.lltype import Signed, Ptr, Char, malloc @@ -51,6 +51,33 @@ xf = compile(f, [], backendopt=False) assert xf() == 3 +def test_string_reverse(): + c_source = py.code.Source(""" + #include + + char *f(char* arg) + { + char *ret; + ret = (char*)malloc(strlen(arg) + 1); + strcpy(ret, arg); + return ret; + } + """) + c_file = udir.join("stringrev.c") + c_file.write(c_source) + z = llexternal('f', [CCHARP], CCHARP, sources=[str(c_file)]) + + def f(): + s = str2charp("xxx") + l_res = z(s) + res = charp2str(l_res) + lltype.free(l_res, flavor='raw') + lltype.free(s, flavor='raw') + return len(res) + + xf = compile(f, [], backendopt=False) + assert xf(expected_extra_mallocs=-1) == 3 + def test_stringstar(): c_source = """ #include From fijal at codespeak.net Fri Jun 1 07:49:46 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Jun 2007 07:49:46 +0200 (CEST) Subject: [pypy-svn] r43966 - in pypy/branch/kill-ctypes/pypy/module/_curses: . test Message-ID: <20070601054946.121DE80A6@code0.codespeak.net> Author: fijal Date: Fri Jun 1 07:49:45 2007 New Revision: 43966 Added: pypy/branch/kill-ctypes/pypy/module/_curses/ (props changed) pypy/branch/kill-ctypes/pypy/module/_curses/__init__.py pypy/branch/kill-ctypes/pypy/module/_curses/app_curses.py pypy/branch/kill-ctypes/pypy/module/_curses/fficurses.py pypy/branch/kill-ctypes/pypy/module/_curses/interp_curses.py pypy/branch/kill-ctypes/pypy/module/_curses/test/ (props changed) pypy/branch/kill-ctypes/pypy/module/_curses/test/__init__.py pypy/branch/kill-ctypes/pypy/module/_curses/test/test_curses.py Log: Add a dummy _curses module, just enough to run pyrepl. Still, there are major concerns about merging this branch: * storing annotations on __class__ of ExtFunc * termios exception hacks (annotation) * seems that lltype.free has some problems with exception_is_here() (fficurses.py/tigetstr_llimpl) * we_are_translated in interp_termios, which is ugly. Added: pypy/branch/kill-ctypes/pypy/module/_curses/__init__.py ============================================================================== --- (empty file) +++ pypy/branch/kill-ctypes/pypy/module/_curses/__init__.py Fri Jun 1 07:49:45 2007 @@ -0,0 +1,35 @@ + +from pypy.interpreter.mixedmodule import MixedModule +from pypy.module._curses import fficurses +from pypy.module._curses import interp_curses +from pypy.rlib.nonconst import NonConstant +import _curses + +class Module(MixedModule): + """ Low-level interface for curses module, + not meant to be used directly + """ + applevel_name = "_curses" + + appleveldefs = { + 'error' : 'app_curses.error', + } + + interpleveldefs = { + 'setupterm' : 'interp_curses.setupterm', + 'tigetstr' : 'interp_curses.tigetstr', + 'tparm' : 'interp_curses.tparm', + } + + def startup(self, space): + # XXX nasty annotation trick + try: + raise interp_curses.curses_error(NonConstant("xxx")) + except _curses.error, e: + pass + +import _curses +for i in dir(_curses): + val = getattr(_curses, i) + if i.isupper() and type(val) is int: + Module.interpleveldefs[i] = "space.wrap(%s)" % val Added: pypy/branch/kill-ctypes/pypy/module/_curses/app_curses.py ============================================================================== --- (empty file) +++ pypy/branch/kill-ctypes/pypy/module/_curses/app_curses.py Fri Jun 1 07:49:45 2007 @@ -0,0 +1,3 @@ + +class error(Exception): + pass Added: pypy/branch/kill-ctypes/pypy/module/_curses/fficurses.py ============================================================================== --- (empty file) +++ pypy/branch/kill-ctypes/pypy/module/_curses/fficurses.py Fri Jun 1 07:49:45 2007 @@ -0,0 +1,101 @@ + +""" The ffi for rpython, need to be imported for side effects +""" + +import sys +from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.extfunc import register_external +from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.module._curses import interp_curses +from pypy.rpython.lltypesystem import llmemory + +# waaa... +includes = ['curses.h', 'term.h'] +libs = ['curses'] + +INT = rffi.INT +INTP = lltype.Ptr(lltype.Array(INT, hints={'nolength':True})) +c_setupterm = rffi.llexternal('setupterm', [rffi.CCHARP, INT, INTP], INT, + includes=includes, libraries=libs) +c_tigetstr = rffi.llexternal('tigetstr', [rffi.CCHARP], rffi.CCHARP, + includes=includes, libraries=libs) +c_tparm = rffi.llexternal('tparm', [rffi.CCHARP, INT, INT, INT, INT, INT, + INT, INT, INT, INT, INT], rffi.CCHARP, + includes=includes, libraries=libs) + +ERR = rffi.CConstant('ERR', INT) +OK = rffi.CConstant('OK', INT) + +def curses_setupterm(term, fd): + intp = lltype.malloc(INTP.TO, 1, flavor='raw') + err = c_setupterm(term, fd, intp) + try: + if err == ERR: + if intp[0] == 0: + msg = "setupterm: could not find terminal" + elif intp[0] == -1: + msg = "setupterm: could not find terminfo database" + else: + msg = "setupterm: unknown error" + raise interp_curses.curses_error(msg) + interp_curses.module_info.setupterm_called = True + finally: + lltype.free(intp, flavor='raw') + +def curses_setupterm_null_llimpl(fd): + curses_setupterm(lltype.nullptr(rffi.CCHARP.TO), fd) + +def curses_setupterm_llimpl(term, fd): + ll_s = rffi.str2charp(term) + try: + curses_setupterm(ll_s, fd) + finally: + lltype.free(ll_s, flavor='raw') + +register_external(interp_curses._curses_setupterm_null, + [int], llimpl=curses_setupterm_null_llimpl, + export_name='_curses.setupterm_null') +register_external(interp_curses._curses_setupterm, + [str, int], llimpl=curses_setupterm_llimpl, + export_name='_curses.setupterm') + +def check_setup_invoked(): + if not interp_curses.module_info.setupterm_called: + raise interp_curses.curses_error("must call (at least) setupterm() first") + +def tigetstr_llimpl(cap): + check_setup_invoked() + ll_cap = rffi.str2charp(cap) + try: + ll_res = c_tigetstr(ll_cap) + num = lltype.cast_ptr_to_int(ll_res) + if num == 0 or num == -1: + raise interp_curses.TermError() + res = rffi.charp2str(ll_res) + # XXX - how to avoid a problem with leaking stuff here??? + #lltype.free(ll_res, flavor='raw') + return res + finally: + lltype.free(ll_cap, flavor='raw') + +register_external(interp_curses._curses_tigetstr, [str], str, + export_name='_curses.tigetstr', llimpl=tigetstr_llimpl) + +def tparm_llimpl(s, args): + check_setup_invoked() + l = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + for i in range(min(len(args), 10)): + l[i] = args[i] + ll_s = rffi.str2charp(s) + # XXX nasty trick stolen from CPython + ll_res = c_tparm(ll_s, l[0], l[1], l[2], l[3], l[4], l[5], l[6], + l[7], l[8], l[9]) + lltype.free(ll_s, flavor='raw') + # XXX - how to make this happy? + # lltype.free(ll_res, flavor.raw) + return rffi.charp2str(ll_res) + +register_external(interp_curses._curses_tparm, [str, [int]], str, + export_name='_curses.tparm', llimpl=tparm_llimpl) + Added: pypy/branch/kill-ctypes/pypy/module/_curses/interp_curses.py ============================================================================== --- (empty file) +++ pypy/branch/kill-ctypes/pypy/module/_curses/interp_curses.py Fri Jun 1 07:49:45 2007 @@ -0,0 +1,77 @@ + +from pypy.interpreter.baseobjspace import ObjSpace, W_Root +from pypy.interpreter.error import OperationError + +import _curses + +class ModuleInfo: + def __init__(self): + self.setupterm_called = False + +module_info = ModuleInfo() + +class curses_error(_curses.error): + def __init__(self, msg): + self.args = [msg] + +def convert_error(space, error): + msg = error.args[0] + w_module = space.getbuiltinmodule('_curses') + w_exception_class = space.getattr(w_module, space.wrap('error')) + w_exception = space.call_function(w_exception_class, space.wrap(msg)) + return OperationError(w_exception_class, w_exception) + +def _curses_setupterm_null(fd): + # NOT_RPYTHON + _curses.setupterm(None, fd) + +def _curses_setupterm(termname, fd): + # NOT_RPYTHON + _curses.setupterm(termname, fd) + +def setupterm(space, w_termname=None, fd=-1): + if fd == -1: + w_stdout = space.getattr(space.getbuiltinmodule('sys'), + space.wrap('stdout')) + fd = space.int_w(space.call_function(space.getattr(w_stdout, + space.wrap('fileno')))) + try: + if space.is_w(w_termname, space.w_None) or w_termname is None: + _curses_setupterm_null(fd) + else: + _curses_setupterm(space.str_w(w_termname), fd) + except _curses.error, e: + raise convert_error(space, e) +setupterm.unwrap_spec = [ObjSpace, W_Root, int] + +class TermError(Exception): + pass + +def _curses_tigetstr(capname): + # NOT_RPYTHON + res = _curses.tigetstr(capname) + if res is None: + raise TermError + return res + +def _curses_tparm(s, args): + # NOT_RPYTHON + return _curses.tparm(s, *args) + +def tigetstr(space, capname): + try: + result = _curses_tigetstr(capname) + except TermError: + return space.w_None + except _curses.error, e: + raise convert_error(space, e) + return space.wrap(result) +tigetstr.unwrap_spec = [ObjSpace, str] + +def tparm(space, s, args_w): + args = [space.int_w(a) for a in args_w] + try: + return space.wrap(_curses_tparm(s, args)) + except _curses.error, e: + raise convert_error(space, e) +tparm.unwrap_spec = [ObjSpace, str, 'args_w'] Added: pypy/branch/kill-ctypes/pypy/module/_curses/test/__init__.py ============================================================================== Added: pypy/branch/kill-ctypes/pypy/module/_curses/test/test_curses.py ============================================================================== --- (empty file) +++ pypy/branch/kill-ctypes/pypy/module/_curses/test/test_curses.py Fri Jun 1 07:49:45 2007 @@ -0,0 +1,89 @@ + +from pypy.translator.c.test.test_genc import compile +from pypy.module._curses import interp_curses +from pypy.module._curses import fficurses +from pypy.conftest import gettestobjspace +from pypy.tool.autopath import pypydir +from pypy.tool.udir import udir +import py +import sys + +class AppTestCurses(object): + def setup_class(cls): + cls.space = gettestobjspace(usemodules=['_curses']) + + def test_tigetstr(self): + import _curses + _curses.setupterm() + assert _curses.tigetstr('cup') == '\x1b[%i%p1%d;%p2%dH' + + def test_tparm(self): + import _curses + _curses.setupterm() + assert _curses.tparm(_curses.tigetstr('cup'), 5, 3) == '\033[6;4H' + +class TestCurses(object): + """ We need to fork here, to prevent + the setup to be done + """ + def _spawn(self, *args, **kwds): + import pexpect + print 'SPAWN:', args, kwds + child = pexpect.spawn(*args, **kwds) + child.logfile = sys.stdout + return child + + def spawn(self, argv): + py_py = py.path.local(pypydir).join('bin', 'py.py') + return self._spawn(sys.executable, [str(py_py)] + argv) + + def setup_class(self): + try: + import pexpect + except ImportError: + py.test.skip('pexpect not found') + + def test_setupterm(self): + source = py.code.Source(""" + import _curses + try: + _curses.tigetstr('cup') + except _curses.error: + print 'ok!' + """) + f = udir.join("test_setupterm.py") + f.write(source) + child = self.spawn(['--withmod-_curses', str(f)]) + child.expect('ok!') + +# XXX probably we need to run all the stuff here in pexpect anyway... + +class TestCCurses(object): + """ Test compiled version + """ + def test_csetupterm(self): + def runs_setupterm(): + interp_curses._curses_setupterm_null(1) + + fn = compile(runs_setupterm, []) + fn() + + def test_ctgetstr(self): + def runs_ctgetstr(): + interp_curses._curses_setupterm("xterm", 1) + res = interp_curses._curses_tigetstr('cup') + assert res == '\x1b[%i%p1%d;%p2%dH' + + fn = compile(runs_ctgetstr, []) + fn() + + def test_ctparm(self): + def runs_tparm(): + interp_curses._curses_setupterm("xterm", 1) + cup = interp_curses._curses_tigetstr('cup') + res = interp_curses._curses_tparm(cup, [5, 3]) + assert res == '\033[6;4H' + + fn = compile(runs_tparm, []) + fn() + From niko at codespeak.net Fri Jun 1 12:20:40 2007 From: niko at codespeak.net (niko at codespeak.net) Date: Fri, 1 Jun 2007 12:20:40 +0200 (CEST) Subject: [pypy-svn] r43972 - in pypy/dist/pypy/translator/jvm: src/pypy test Message-ID: <20070601102040.4FA3A80A5@code0.codespeak.net> Author: niko Date: Fri Jun 1 12:20:39 2007 New Revision: 43972 Modified: pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java pypy/dist/pypy/translator/jvm/test/test_primitive.py Log: quickly implement ll_time_time 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 Fri Jun 1 12:20:39 2007 @@ -485,6 +485,10 @@ // Primitive built-in functions public static double ll_time_clock() { + return System.currentTimeMillis()/1000; // XXX: processor time? + } + + public static double ll_time_time() { return System.currentTimeMillis()/1000; } Modified: pypy/dist/pypy/translator/jvm/test/test_primitive.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_primitive.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_primitive.py Fri Jun 1 12:20:39 2007 @@ -7,9 +7,8 @@ class TestPrimitive(JvmTest): def test_time_time(self): - py.test.skip("ll_time_time is not implemented in jvm backend") -# def fn(): -# return time.time() -# t1 = self.interpret(fn, []) -# t2 = self.interpret(fn, []) -# assert t1 <= t2 + def fn(): + return time.time() + t1 = self.interpret(fn, []) + t2 = self.interpret(fn, []) + assert t1 <= t2 From niko at codespeak.net Fri Jun 1 13:30:06 2007 From: niko at codespeak.net (niko at codespeak.net) Date: Fri, 1 Jun 2007 13:30:06 +0200 (CEST) Subject: [pypy-svn] r43973 - pypy/dist/pypy/translator/jvm/src/pypy Message-ID: <20070601113006.EFB9680A7@code0.codespeak.net> Author: niko Date: Fri Jun 1 13:30:06 2007 New Revision: 43973 Modified: pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java Log: divide by 1000.0 not 1000 in an effort to avoid rounding errors 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 Fri Jun 1 13:30:06 2007 @@ -485,11 +485,11 @@ // Primitive built-in functions public static double ll_time_clock() { - return System.currentTimeMillis()/1000; // XXX: processor time? + return System.currentTimeMillis()/1000.0; // XXX: processor time? } public static double ll_time_time() { - return System.currentTimeMillis()/1000; + return System.currentTimeMillis()/1000.0; } public static int ll_os_write(int fd, String text) { From santagada at codespeak.net Fri Jun 1 21:07:02 2007 From: santagada at codespeak.net (santagada at codespeak.net) Date: Fri, 1 Jun 2007 21:07:02 +0200 (CEST) Subject: [pypy-svn] r43978 - in pypy/dist/pypy/lang/js: . test Message-ID: <20070601190702.08A6E80AE@code0.codespeak.net> Author: santagada Date: Fri Jun 1 21:06:59 2007 New Revision: 43978 Modified: pypy/dist/pypy/lang/js/operations.py pypy/dist/pypy/lang/js/test/test_interp.py Log: implemented string comparisons for the logical ops, did some tests for it and then removed the static methods from the binary math ops Modified: pypy/dist/pypy/lang/js/operations.py ============================================================================== --- pypy/dist/pypy/lang/js/operations.py (original) +++ pypy/dist/pypy/lang/js/operations.py Fri Jun 1 21:06:59 2007 @@ -74,8 +74,6 @@ class BinaryOp(Expression): def __init__(self, pos, left, right): self.pos = pos - assert isinstance(left, Node) - assert isinstance(right, Node) self.left = left self.right = right @@ -109,7 +107,7 @@ class PropertyInit(BinaryOp): pass -class Array(ListOp): +class Array(ListOp): def eval(self, ctx): array = W_Array() for i in range(len(self.nodes)): @@ -121,7 +119,7 @@ self.pos = pos self.left = left self.right = right - self.type = atype + self.type = atype def eval(self, ctx): v1 = self.left.eval(ctx) @@ -187,7 +185,8 @@ return W_Number(op1|op2) -class BitwiseXor(BinaryBitwiseOp): + +class BitwiseXor(BinaryBitwiseOp): def decision(self, ctx, op1, op2): return W_Number(op1^op2) @@ -207,7 +206,8 @@ raise ExecutionReturned('continue', None, None) -class Call(BinaryOp): + +class Call(BinaryOp): def eval(self, ctx): r1 = self.left.eval(ctx) r2 = self.right.eval(ctx) @@ -323,7 +323,6 @@ Implements the Abstract Relational Comparison x < y Still not fully to the spec """ - # TODO complete the funcion with strings comparison s1 = x.ToPrimitive(ctx, 'Number') s2 = y.ToPrimitive(ctx, 'Number') if not (isinstance(s1, W_String) and isinstance(s2, W_String)): @@ -336,6 +335,12 @@ else: return 0 else: + s4 = s1.ToString() + s5 = s2.ToString() + if s4 < s5: + return 1 + if s4 == s5: + return 0 return -1 class Or(BinaryOp): @@ -566,7 +571,7 @@ thing = self.expr.eval(ctx) val = thing.GetValue() x = val.ToNumber() - resl = Plus.mathop(ctx, W_Number(x), W_Number(1)) + resl = plus(ctx, W_Number(x), W_Number(1)) thing.PutValue(resl, ctx) if self.postfix: return val @@ -584,7 +589,7 @@ thing = self.expr.eval(ctx) val = thing.GetValue() x = val.ToNumber() - resl = Plus.mathop(ctx, W_Number(x), W_Number(-1)) + resl = sub(ctx, W_Number(x), W_Number(1)) thing.PutValue(resl, ctx) if self.postfix: return val @@ -617,6 +622,9 @@ nright = self.right.eval(ctx).GetValue().ToPrimitive(ctx, 'Number') result = self.mathop(ctx, nleft, nright) return result + + def mathop(self, ctx, n1, n2): + raise NotImplementedError def plus(ctx, nleft, nright): if isinstance(nleft, W_String) or isinstance(nright, W_String): @@ -650,28 +658,33 @@ class Plus(BinaryNumberOp): - mathop = staticmethod(plus) - + def mathop(self, ctx, n1, n2): + return plus(ctx, n1, n2) + class Mult(BinaryNumberOp): - mathop = staticmethod(mult) - + def mathop(self, ctx, n1, n2): + return mult(ctx, n1, n2) + class Mod(BinaryNumberOp): - mathop = staticmethod(mod) - + def mathop(self, ctx, n1, n2): + return mod(ctx, n1, n2) + class Division(BinaryNumberOp): - mathop = staticmethod(division) - + def mathop(self, ctx, n1, n2): + return division(ctx, n1, n2) + class Sub(BinaryNumberOp): - mathop = staticmethod(sub) - + def mathop(self, ctx, n1, n2): + return sub(ctx, n1, n2) + -class Null(Expression): +class Null(Expression): def eval(self, ctx): - return w_Null + return w_Null ############################################################################## @@ -697,7 +710,8 @@ return x.Construct(ctx=ctx, args=args) -class Number(Expression): + +class Number(Expression): def __init__(self, pos, num): self.pos = pos assert isinstance(num, float) @@ -737,7 +751,7 @@ temp.append(unescapeseq) last = unescapeseq continue - if c != SLASH: + if c != SLASH: temp.append(c) last = c return ''.join(temp) @@ -999,7 +1013,7 @@ class For(Statement): def __init__(self, pos, setup, condition, update, body): - self.pos = pos + self.pos = pos self.setup = setup self.condition = condition self.update = update @@ -1036,7 +1050,7 @@ def eval(self, ctx): return W_Number(-self.expr.eval(ctx).GetValue().ToNumber()) -class UPlus(UnaryOp): +class UPlus(UnaryOp): def eval(self, ctx): return W_Number(+self.expr.eval(ctx).GetValue().ToNumber()) Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Fri Jun 1 21:06:59 2007 @@ -233,6 +233,11 @@ yield assertv, "0!=1;", True yield assertv, "1!=1;", False +def test_string_compare(): + yield assertv, "'aaa' > 'a';", True + yield assertv, "'aaa' < 'a';", False + yield assertv, "'a' > 'a';", False + def test_binary_op(): yield assertp, "print(0||0); print(1||0);", ["0", "1"] yield assertp, "print(0&&1); print(1&&1);", ["0", "1"] From fijal at codespeak.net Fri Jun 1 23:34:05 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Jun 2007 23:34:05 +0200 (CEST) Subject: [pypy-svn] r43985 - in pypy/branch/kill-ctypes/pypy/module/fcntl: . test Message-ID: <20070601213405.AFADF8090@code0.codespeak.net> Author: fijal Date: Fri Jun 1 23:34:04 2007 New Revision: 43985 Modified: pypy/branch/kill-ctypes/pypy/module/fcntl/interp_fcntl.py pypy/branch/kill-ctypes/pypy/module/fcntl/test/test_fcntl.py Log: Minor tweak to allow ioctl to return 0-containing strings Modified: pypy/branch/kill-ctypes/pypy/module/fcntl/interp_fcntl.py ============================================================================== --- pypy/branch/kill-ctypes/pypy/module/fcntl/interp_fcntl.py (original) +++ pypy/branch/kill-ctypes/pypy/module/fcntl/interp_fcntl.py Fri Jun 1 23:34:04 2007 @@ -246,7 +246,6 @@ If the arg given is an integer or if none is specified, the result value is an integer corresponding to the return value of the ioctl call in the C code.""" - fd = _conv_descriptor(space, w_fd) # Python turns number > sys.maxint into long, we need the signed C value op = c_int(op).value @@ -272,7 +271,7 @@ if rv < 0: raise OperationError(space.w_IOError, space.wrap(_get_error_msg())) - return space.wrap(buf.value) + return space.wrap(buf.raw) else: raise OperationError(space.w_TypeError, space.wrap("an integer or a buffer required")) Modified: pypy/branch/kill-ctypes/pypy/module/fcntl/test/test_fcntl.py ============================================================================== --- pypy/branch/kill-ctypes/pypy/module/fcntl/test/test_fcntl.py (original) +++ pypy/branch/kill-ctypes/pypy/module/fcntl/test/test_fcntl.py Fri Jun 1 23:34:04 2007 @@ -162,7 +162,7 @@ raises(TypeError, fcntl.ioctl, f, "foo") raises(TypeError, fcntl.ioctl, f, TIOCGPGRP, float(0)) raises(TypeError, fcntl.ioctl, f, TIOCGPGRP, 1, "foo") - + # buf = array.array('h', [0]) # fcntl.ioctl(0, TIOCGPGRP, buf, True) # buf = array.array('c', "a"*1025) From santagada at codespeak.net Sun Jun 3 00:12:41 2007 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sun, 3 Jun 2007 00:12:41 +0200 (CEST) Subject: [pypy-svn] r43998 - in pypy/dist/pypy/lang/js: . test Message-ID: <20070602221241.7874780CC@code0.codespeak.net> Author: santagada Date: Sun Jun 3 00:12:40 2007 New Revision: 43998 Removed: pypy/dist/pypy/lang/js/js.cleanup pypy/dist/pypy/lang/js/newparser.py Modified: pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/operations.py pypy/dist/pypy/lang/js/test/test_interp.py pypy/dist/pypy/lang/js/test/test_parser.py Log: now part of the interpreter is using the right rules of prototype inheritance... Still the stdlibrary needs lots of work, but now it seems like it is worth it. Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Sun Jun 3 00:12:40 2007 @@ -186,7 +186,7 @@ w_Global.Put('Array', w_Array) w_Global.Put('version', W_Builtin(versionjs)) - #Number + #Date w_Date = W_Object(Class="Number") w_Global.Put('Date', w_Date) Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Sun Jun 3 00:12:40 2007 @@ -57,7 +57,8 @@ def ToString(self): return '' - def ToObject(self): + def ToObject(self, ctx): + # XXX should raise not implemented return self def ToNumber(self): @@ -131,9 +132,11 @@ def __init__(self, ctx=None, Prototype=None, Class='Object', Value=w_Undefined, callfunc=None): self.propdict = {} - self.propdict['prototype'] = Property('prototype', w_Undefined, - dd=True, de=True) self.Prototype = Prototype + if Prototype is None: + Prototype = w_Undefined + self.propdict['prototype'] = Property('prototype', Prototype, + dd=True, de=True) self.Class = Class self.callfunc = callfunc if callfunc is not None: @@ -143,6 +146,8 @@ self.Value = Value def Call(self, ctx, args=[], this=None): + if self.callfunc is None: # XXX Not sure if I should raise it here + raise JsTypeError('not a function') act = ActivationObject() paramn = len(self.callfunc.params) for i in range(paramn): @@ -164,9 +169,8 @@ prot = self.Get('prototype') if isinstance(prot, W_PrimitiveObject): obj.Prototype = prot - else: - obj.Prototype = ctx.get_global().Get('Object') - + else: # would love to test this, but I fail to find a case that falls into this + obj.Prototype = ctx.get_global().Get('Object').Get('prototype') try: #this is a hack to be compatible to spidermonkey self.Call(ctx, args, this=obj) return obj @@ -563,3 +567,7 @@ def __str__(self): return "<" + str(self.base) + " -> " + str(self.property_name) + ">" +def create_object(ctx, prototypename='Object', callfunc=None): + proto = ctx.get_global().Get(prototypename).Get('prototype') + obj = W_Object(ctx, callfunc = callfunc,Prototype=proto, Class = proto.Class) + return obj \ No newline at end of file Modified: pypy/dist/pypy/lang/js/operations.py ============================================================================== --- pypy/dist/pypy/lang/js/operations.py (original) +++ pypy/dist/pypy/lang/js/operations.py Sun Jun 3 00:12:40 2007 @@ -249,14 +249,14 @@ class Member(BinaryOp): def eval(self, ctx): - w_obj = self.left.eval(ctx).GetValue().ToObject() + w_obj = self.left.eval(ctx).GetValue().ToObject(ctx) name = self.right.eval(ctx).GetValue().ToString() return W_Reference(name, w_obj) class MemberDot(BinaryOp): def eval(self, ctx): - w_obj = self.left.eval(ctx).GetValue().ToObject() + w_obj = self.left.eval(ctx).GetValue().ToObject(ctx) name = self.right.get_literal() return W_Reference(name, w_obj) @@ -269,10 +269,13 @@ self.params = params def eval(self, ctx): - #XXX this is wrong, should clone the function prototype - w_obj = W_Object(ctx=ctx, callfunc = self) - w_obj.Put('prototype', W_Object(ctx=ctx)) - return w_obj + proto = ctx.get_global().Get('Function').Get('prototype') + w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function', callfunc=self) + w_func.Put('length', W_Number(len(self.params))) + w_obj = create_object(ctx, 'Object') + w_obj.Put('constructor', w_func, de=True) + w_func.Put('prototype', w_obj) + return w_func def execute(self, ctx): return self.eval(ctx) @@ -601,7 +604,7 @@ opcode = 'INDEX' def eval(self, ctx): - w_obj = self.left.eval(ctx).GetValue().ToObject() + w_obj = self.left.eval(ctx).GetValue().ToObject(ctx) name= self.right.eval(ctx).GetValue().ToString() return W_Reference(name, w_obj) @@ -761,7 +764,7 @@ opcode = 'OBJECT_INIT' def eval(self, ctx): - w_obj = W_Object() + w_obj = create_object(ctx, 'Object') for prop in self.nodes: name = prop.left.eval(ctx).GetPropertyName() w_expr = prop.right.eval(ctx).GetValue() @@ -915,7 +918,7 @@ self.body = body def execute(self, ctx): - obj = self.identifier.eval(ctx).GetValue().ToObject() + obj = self.identifier.eval(ctx).GetValue().ToObject(ctx) ctx.push_object(obj) try: @@ -972,7 +975,7 @@ def execute(self, ctx): self.vardecl.eval(ctx) - obj = self.object.eval(ctx).GetValue().ToObject() + obj = self.object.eval(ctx).GetValue().ToObject(ctx) for prop in obj.propdict.values(): if prop.de: continue @@ -996,7 +999,7 @@ self.body = body def execute(self, ctx): - obj = self.object.eval(ctx).GetValue().ToObject() + obj = self.object.eval(ctx).GetValue().ToObject(ctx) for prop in obj.propdict.values(): if prop.de: continue Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Sun Jun 3 00:12:40 2007 @@ -529,15 +529,6 @@ f.bar(); """, 'debug') -def test_switch(): - py.test.skip("not ready yet") - assertv(""" - x = 1; - switch(x){ - case 1: 15; break; - default: 30; - };""", 15) - def test_inplace_assign(): yield assertv, "x=1; x+=1; x;", 2 yield assertv, "x=1; x-=1; x;", 0 @@ -567,3 +558,37 @@ def test_octal_and_hex(): yield assertv, "010;", 8 yield assertv, "0xF", 15 + +def test_switch(): + py.test.skip("not ready yet") + yield assertv, """ + x = 1; + switch(x){ + case 1: 15; break; + default: 30; + };""", 15 + yield assertv, """ + x = 1; + switch(x){ + case 1: 15; break; + default: 30; + };""", 15 + +def test_autoboxing(): + py.test.skip("not ready yet") + yield assertv, "'abc'.charAt(0)", 0 + yield assertv, "true.toString()", 'true' + yield assertv, "5.toString()", '5' + +def test_proper_prototype_inheritance(): + yield assertv, """ + Object.prototype.my = function() {return 1}; + x = {}; + x.my(); + """, 1 + yield assertv, """ + Function.prototype.my = function() {return 1}; + function x () {}; + x.my(); + """, 1 + \ No newline at end of file Modified: pypy/dist/pypy/lang/js/test/test_parser.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_parser.py (original) +++ pypy/dist/pypy/lang/js/test/test_parser.py Sun Jun 3 00:12:40 2007 @@ -4,7 +4,7 @@ from pypy.rlib.parsing.ebnfparse import parse_ebnf, make_parse_function from pypy.rlib.parsing.parsing import ParseError, Rule from pypy.rlib.parsing.tree import RPythonVisitor -from pypy.lang.js.jsobj import empty_context, ThrowException +from pypy.lang.js.jsobj import W_Object, global_context, ThrowException from pypy.lang.js.astbuilder import ASTBuilder from pypy import conftest import sys @@ -285,7 +285,10 @@ def eval_expr(self, s): ast = self.to_ast(s) - return ast.eval(empty_context()) + w_Global = W_Object() + w_Object = W_Object(Prototype=W_Object()) + w_Global.Put('Object', w_Object) + return ast.eval(global_context(w_Global)) def test_get_pos(self): from pypy.lang.js import operations From santagada at codespeak.net Mon Jun 4 13:23:10 2007 From: santagada at codespeak.net (santagada at codespeak.net) Date: Mon, 4 Jun 2007 13:23:10 +0200 (CEST) Subject: [pypy-svn] r44022 - in pypy/dist/pypy/lang/js: . test test/ecma/FunctionObjects test/ecma/ObjectObjects Message-ID: <20070604112310.BC3A380B2@code0.codespeak.net> Author: santagada Date: Mon Jun 4 13:23:09 2007 New Revision: 44022 Modified: pypy/dist/pypy/lang/js/__init__.py pypy/dist/pypy/lang/js/astbuilder.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsgrammar.txt pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/operations.py pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.1.1-3.js pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.2.1-3.js pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.5-1.js pypy/dist/pypy/lang/js/test/ecma/ObjectObjects/15.2.4.2.js pypy/dist/pypy/lang/js/test/test_interp.py Log: Object, Function and Booleans have been reworked to follow the specs Modified: pypy/dist/pypy/lang/js/__init__.py ============================================================================== --- pypy/dist/pypy/lang/js/__init__.py (original) +++ pypy/dist/pypy/lang/js/__init__.py Mon Jun 4 13:23:09 2007 @@ -0,0 +1,2 @@ +# + Modified: pypy/dist/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/dist/pypy/lang/js/astbuilder.py (original) +++ pypy/dist/pypy/lang/js/astbuilder.py Mon Jun 4 13:23:09 2007 @@ -278,7 +278,7 @@ return self.dispatch(node.children[0]) else: pos = self.get_pos(node) - val = self.dispatch(node.children[0]) + val = self.dispatch(node.children[1]) return operations.New(pos, val) def visit_ifstatement(self, node): Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Mon Jun 4 13:23:09 2007 @@ -21,7 +21,42 @@ t = load_source(f.readall()) f.close() return t - + +class W_ObjectObject(W_Object): + def __init__(self, ctx=None, Prototype=None, Class='Object', + Value=w_Undefined, callfunc=None): + W_Object.__init__(self, ctx, Prototype, + Class, Value, callfunc) + + def Call(self, ctx, args=[], this=None): + if len(args) >= 1 and not isnull_or_undefined(args[0]): + return args[0].ToObject(ctx) + else: + return self.Construct(ctx) + + def Construct(self, ctx, args=[]): + if len(args) >= 1 and not (isinstance(args[0], W_Undefined) or isinstance(args[0], W_Null)): + # XXX later we could separate builtins and normal objects + return args[0].ToObject(ctx) + return create_object(ctx, 'Object') + +class W_BooleanObject(W_Object): + def __init__(self, ctx=None, Prototype=None, Class='Boolean', + Value=w_Undefined, callfunc=None): + W_Object.__init__(self, ctx, Prototype, + Class, Value, callfunc) + + def Call(self, ctx, args=[], this=None): + if len(args) >= 1 and not isnull_or_undefined(args[0]): + return W_Boolean(args[0].ToBoolean()) + else: + return W_Boolean(False) + + def Construct(self, ctx, args=[]): + if len(args) >= 1 and not isnull_or_undefined(args[0]): + Value = W_Boolean(args[0].ToBoolean()) + return create_object(ctx, 'Boolean', Value = Value) + return create_object(ctx, 'Boolean', Value = W_Boolean(False)) def evaljs(ctx, args, this): if len(args) >= 1: @@ -38,21 +73,6 @@ return node.execute(ctx) -def functionjs(ctx, args, this): - tam = len(args) - if tam >= 1: - fbody = args[tam-1].GetValue().ToString() - argslist = [] - for i in range(tam-1): - argslist.append(args[i].GetValue().ToString()) - fargs = ','.join(argslist) - functioncode = "function (%s) {%s}"%(fargs, fbody) - else: - functioncode = "function () {}" - #remove program and sourcelements node - funcnode = parse(functioncode).children[0].children[0] - return ASTBUILDER.dispatch(funcnode).execute(ctx) - def parseIntjs(ctx, args, this): if len(args) < 1: return W_Number(NaN) @@ -87,9 +107,6 @@ writer(",".join([i.GetValue().ToString() for i in args])) return w_Undefined -def objectconstructor(ctx, args, this): - return W_Object() - def isnanjs(ctx, args, this): if len(args) < 1: return W_Boolean(True) @@ -141,26 +158,170 @@ def versionjs(ctx, args, this): return w_Undefined +class W_ToString(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + return W_String("[object %s]"%this.Class) + +class W_ValueOf(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + return this + +class W_HasOwnProperty(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + if len(args) >= 1: + propname = args[0].ToString() + if propname in this.propdict: + return W_Boolean(True) + return W_Boolean(False) + +class W_IsPrototypeOf(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + if len(args) >= 1 and isinstance(args[0], W_PrimitiveObject): + O = this + V = args[0].Prototype + while V is not None: + if O == V: + return W_Boolean(True) + V = V.Prototype + return W_Boolean(False) + +class W_PropertyIsEnumerable(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + if len(args) >= 1: + propname = args[0].ToString() + if propname in this.propdict and not this.propdict[propname].de: + return W_Boolean(True) + return W_Boolean(False) + +class W_Function(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + tam = len(args) + if tam >= 1: + fbody = args[tam-1].GetValue().ToString() + argslist = [] + for i in range(tam-1): + argslist.append(args[i].GetValue().ToString()) + fargs = ','.join(argslist) + functioncode = "function (%s) {%s}"%(fargs, fbody) + else: + functioncode = "function () {}" + #remove program and sourcelements node + funcnode = parse(functioncode).children[0].children[0] + return ASTBUILDER.dispatch(funcnode).execute(ctx) + + def Construct(self, ctx, args=[]): + return self.Call(ctx, args, this=None) + +class W_FToString(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + if this.Class == 'Function': + return W_String('function (arguments go here!) {\n [lots of stuff :)]\n}') + else: + raise JsTypeError('this is not a function object') + +class W_Apply(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + try: + if isnull_or_undefined(args[0]): + thisArg = ctx.get_global() + else: + thisArg = args[0].ToObject(ctx) + except IndexError: + thisArg = ctx.get_global() + + try: + arrayArgs = args[1] + if isinstance(arrayArgs, W_ListObject): + callargs = arrayArgs.tolist() + elif isinstance(arrayArgs, W_Undefined) or isinstance(arrayArgs, W_Null): + callargs = [] + else: + raise JsTypeError('arrayArgs is not an Array or Arguments object') + except IndexError: + callargs = [] + return this.Call(ctx, callargs, this=thisArg) + +class W_Call(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + if len(args) >= 1: + if isnull_or_undefined(args[0]): + thisArg = ctx.get_global() + else: + thisArg = args[0] + callargs = args[1:] + else: + thisArg = ctx.get_global() + callargs = [] + return this.Call(ctx, callargs, this = thisArg) + +class W_ValueToString(W_NewBuiltin): + "this is the toString function for objects with Value" + def Call(self, ctx, args=[], this=None): + return W_String(this.Value.ToString()) + +class W_ValueValueOf(W_NewBuiltin): + "this is the valueOf function for objects with Value" + def Call(self, ctx, args=[], this=None): + return this.Value + +class W_DateFake(W_NewBuiltin): # XXX This is temporary + def Call(self, ctx, args=[], this=None): + return create_object(ctx, 'Object') + + def Construct(self, ctx, args=[]): + return create_object(ctx, 'Object') + class Interpreter(object): """Creates a js interpreter""" def __init__(self): w_Global = W_Object(Class="global") - ctx = global_context(w_Global) + ctx = global_context(w_Global) + w_ObjPrototype = W_Object(Prototype=None, Class='Object') - #Function stuff - w_Function = W_Builtin(functionjs, ctx=ctx, Class='Function', + w_Function = W_Function(ctx, Class='Function', Prototype=w_ObjPrototype) - w_Function.Put('prototype', w_Function, dd=True, de=True, ro=True) + + w_Global.Put('Function', w_Function) + + w_Object = W_ObjectObject(Prototype=w_Function) + w_Object.Put('prototype', w_ObjPrototype, dd=True, de=True, ro=True) + + w_Global.Put('Object', w_Object) + w_FncPrototype = w_Function.Call(ctx, this=w_Function) + w_Function.Put('prototype', w_FncPrototype, dd=True, de=True, ro=True) w_Function.Put('constructor', w_Function) - #Object stuff - w_Object = W_Builtin(objectconstructor, Prototype=w_Function) w_Object.Put('length', W_Number(1), ro=True, dd=True) - w_Object.Put('prototype', w_ObjPrototype, dd=True, de=True, ro=True) + w_ObjPrototype.Put('constructor', w_Object) - #And some other stuff + w_ObjPrototype.Put('__proto__', w_Null) + toString = W_ToString(ctx) + w_ObjPrototype.Put('toString', toString) + w_ObjPrototype.Put('toLocaleString', toString) + w_ObjPrototype.Put('valueOf', W_ValueOf(ctx)) + w_ObjPrototype.Put('hasOwnProperty', W_HasOwnProperty(ctx)) + w_ObjPrototype.Put('isPrototypeOf', W_IsPrototypeOf(ctx)) + w_ObjPrototype.Put('propertyIsEnumerable', W_PropertyIsEnumerable(ctx)) + + #properties of the function prototype + w_FncPrototype.Put('constructor', w_FncPrototype) + w_FncPrototype.Put('__proto__', w_ObjPrototype) + w_FncPrototype.Put('toString', W_FToString(ctx)) + w_FncPrototype.Put('apply', W_Apply(ctx)) + w_FncPrototype.Put('call', W_Call(ctx)) + + w_Boolean = W_BooleanObject(Prototype=w_FncPrototype) + w_Boolean.Put('constructor', w_FncPrototype) + w_BoolPrototype = create_object(ctx, 'Object', Value=W_Boolean(False)) + w_BoolPrototype.Class = 'Boolean' + w_Boolean.Put('prototype', w_BoolPrototype) + w_BoolPrototype.Put('constructor', w_FncPrototype) + w_BoolPrototype.Put('toString', W_ValueToString(ctx)) + w_BoolPrototype.Put('valueOf', W_ValueValueOf(ctx)) + w_Global.Put('Boolean', w_Boolean) + #Math w_math = W_Object(Class='Math') @@ -181,13 +342,11 @@ w_Array.Put('prototype', w_ObjPrototype, dd=True, de=True, ro=True) #Global Properties - w_Global.Put('Object', w_Object) - w_Global.Put('Function', w_Function) w_Global.Put('Array', w_Array) w_Global.Put('version', W_Builtin(versionjs)) #Date - w_Date = W_Object(Class="Number") + w_Date = W_DateFake(ctx, Class='Date') w_Global.Put('Date', w_Date) #Number @@ -197,17 +356,17 @@ w_Number.Put('NEGATIVE_INFINITY', W_Number(-Infinity)) w_Global.Put('Number', w_Number) - w_Global.Put('Boolean', W_Builtin(booleanjs, Class="Boolean")) - w_Global.Put('eval', W_Builtin(evaljs)) - w_Global.Put('print', W_Builtin(printjs)) - w_Global.Put('isNaN', W_Builtin(isnanjs)) - w_Global.Put('isFinite', W_Builtin(isnanjs)) - w_Global.Put('parseFloat', W_Builtin(parseFloatjs)) - w_Global.Put('parseInt', W_Builtin(parseIntjs)) w_Global.Put('NaN', W_Number(NaN)) w_Global.Put('Infinity', W_Number(Infinity)) w_Global.Put('undefined', w_Undefined) + w_Global.Put('eval', W_Builtin(evaljs)) + w_Global.Put('parseInt', W_Builtin(parseIntjs)) + w_Global.Put('parseFloat', W_Builtin(parseFloatjs)) + w_Global.Put('isNaN', W_Builtin(isnanjs)) + w_Global.Put('isFinite', W_Builtin(isnanjs)) + + w_Global.Put('print', W_Builtin(printjs)) w_Global.Put('this', w_Global) Modified: pypy/dist/pypy/lang/js/jsgrammar.txt ============================================================================== --- pypy/dist/pypy/lang/js/jsgrammar.txt (original) +++ pypy/dist/pypy/lang/js/jsgrammar.txt Mon Jun 4 13:23:09 2007 @@ -191,10 +191,10 @@ | ; -SINGLESTRING : "'([^']|\\')*'" +SINGLESTRING : "'([^'\\]|\\(\"|'|\\|n|r|b|f|u|t|v))*'" ; -DOUBLESTRING : "\"([^\"]|\\\")*\"" +DOUBLESTRING : "\"([^\"\\]|\\(\"|'|\\|n|r|b|f|u|t|v))*\"" ; primaryexpression : "this" Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Mon Jun 4 13:23:09 2007 @@ -228,7 +228,7 @@ def DefaultValue(self, ctx, hint=""): if hint == "String": return self.internal_def_value(ctx, "toString", "valueOf") - else: #suppose hint is "Number" dunno what to do otherwise + else: # hint can only be empty, String or Number return self.internal_def_value(ctx, "valueOf", "toString") ToPrimitive = DefaultValue @@ -253,16 +253,28 @@ Value=w_Undefined, callfunc=None): W_PrimitiveObject.__init__(self, ctx, Prototype, Class, Value, callfunc) - self.propdict['toString'] = Property('toString', W_Builtin(str_builtin), de=True) +class W_NewBuiltin(W_PrimitiveObject): + def __init__(self, ctx, Prototype=None, Class='function', + Value=w_Undefined, callfunc=None): + if Prototype is None: + proto = ctx.get_global().Get('Function').Get('prototype') + Prototype = proto + + W_PrimitiveObject.__init__(self, ctx, Prototype, Class, Value, callfunc) + + def Call(self, ctx, args=[], this = None): + return NotImplementedError + + def type(self): + return 'builtin' class W_Builtin(W_PrimitiveObject): def __init__(self, builtin=None, ctx=None, Prototype=None, Class='function', - Value=w_Undefined, callfunc=None): - W_PrimitiveObject.__init__(self, ctx, Prototype, - Class, Value, callfunc) + Value=w_Undefined, callfunc=None): + W_PrimitiveObject.__init__(self, ctx, Prototype, Class, Value, callfunc) self.set_builtin_call(builtin) - + def set_builtin_call(self, callfuncbi): self.callfuncbi = callfuncbi @@ -274,8 +286,15 @@ def type(self): return 'builtin' - -class W_Arguments(W_PrimitiveObject): + +class W_ListObject(W_PrimitiveObject): + def tolist(self): + l = [] + for i in range(self.length): + l.append(self.propdict[str(i)].value) + return l + +class W_Arguments(W_ListObject): def __init__(self, callee, args): W_PrimitiveObject.__init__(self, Class='Arguments') del self.propdict["prototype"] @@ -283,6 +302,7 @@ self.Put('length', W_Number(len(args))) for i in range(len(args)): self.Put(str(i), args[i]) + self.length = len(args) class ActivationObject(W_PrimitiveObject): """The object used on function calls to hold arguments and this""" @@ -296,7 +316,7 @@ def arraycallbi(ctx, args, this): return W_Array() -class W_Array(W_PrimitiveObject): +class W_Array(W_ListObject): def __init__(self, ctx=None, Prototype=None, Class='Array', Value=w_Undefined, callfunc=None): W_PrimitiveObject.__init__(self, ctx, Prototype, Class, Value, callfunc) @@ -567,7 +587,13 @@ def __str__(self): return "<" + str(self.base) + " -> " + str(self.property_name) + ">" -def create_object(ctx, prototypename='Object', callfunc=None): +def create_object(ctx, prototypename, callfunc=None, Value=None): proto = ctx.get_global().Get(prototypename).Get('prototype') - obj = W_Object(ctx, callfunc = callfunc,Prototype=proto, Class = proto.Class) - return obj \ No newline at end of file + obj = W_Object(ctx, callfunc = callfunc,Prototype=proto, Class = proto.Class, Value = Value) + return obj + +def isnull_or_undefined(obj): + if isinstance(obj, W_Undefined) or isinstance(obj, W_Null): + return True + else: + return False Modified: pypy/dist/pypy/lang/js/operations.py ============================================================================== --- pypy/dist/pypy/lang/js/operations.py (original) +++ pypy/dist/pypy/lang/js/operations.py Mon Jun 4 13:23:09 2007 @@ -543,8 +543,6 @@ """ The in operator, eg: "property in object" """ - opcode = 'IN' - def decision(self, ctx, op1, op2): if not isinstance(op2, W_Object): raise ThrowException(W_String("TypeError")) @@ -568,8 +566,6 @@ """ ++value (prefix) and value++ (postfix) """ - opcode = 'INCREMENT' - def eval(self, ctx): thing = self.expr.eval(ctx) val = thing.GetValue() @@ -586,8 +582,6 @@ """ same as increment --value and value -- """ - opcode = 'DECREMENT' - def eval(self, ctx): thing = self.expr.eval(ctx) val = thing.GetValue() @@ -601,8 +595,6 @@ class Index(BinaryOp): - opcode = 'INDEX' - def eval(self, ctx): w_obj = self.left.eval(ctx).GetValue().ToObject(ctx) name= self.right.eval(ctx).GetValue().ToString() @@ -752,17 +744,14 @@ if last == SLASH: unescapeseq = unescapedict[last+c] temp.append(unescapeseq) - last = unescapeseq - continue - if c != SLASH: + c = ' ' # Could be anything + elif c != SLASH: temp.append(c) last = c return ''.join(temp) class ObjectInit(ListOp): - opcode = 'OBJECT_INIT' - def eval(self, ctx): w_obj = create_object(ctx, 'Object') for prop in self.nodes: @@ -864,8 +853,6 @@ class Typeof(UnaryOp): - opcode = 'TYPEOF' - def eval(self, ctx): val = self.expr.eval(ctx) if isinstance(val, W_Reference) and val.GetBase() is None: Modified: pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.1.1-3.js ============================================================================== --- pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.1.1-3.js (original) +++ pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.1.1-3.js Mon Jun 4 13:23:09 2007 @@ -79,6 +79,7 @@ } } +/* MyFunc = Function( args, "var r=0; for (var i = 0; i < MyFunc.length; i++ ) { if ( eval('arg'+i) == void 0) break; else r += eval('arg'+i); }; return r"); MyObject = Function( args, "for (var i = 0; i < MyFunc.length; i++ ) { if ( eval('arg'+i) == void 0) break; eval('this.arg'+i +'=arg'+i); };"); @@ -93,5 +94,5 @@ new TestCase( SECTION, "FUN1 = Function( 'a','b','c', 'return FUN1.length' ); FUN1.length", 3, eval("FUN1 = Function( 'a','b','c', 'return FUN1.length' ); FUN1.length") ); new TestCase( SECTION, "FUN1 = Function( 'a','b','c', 'return FUN1.length' ); FUN1()", 3, eval("FUN1 = Function( 'a','b','c', 'return FUN1.length' ); FUN1()") ); new TestCase( SECTION, "FUN1 = Function( 'a','b','c', 'return FUN1.length' ); FUN1(1,2,3,4,5)", 3, eval("FUN1 = Function( 'a','b','c', 'return FUN1.length' ); FUN1(1,2,3,4,5)") ); - +*/ test(); Modified: pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.2.1-3.js ============================================================================== --- pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.2.1-3.js (original) +++ pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.2.1-3.js Mon Jun 4 13:23:09 2007 @@ -78,6 +78,7 @@ } } +/* MyFunc = new Function( args, "var r=0; for (var i = 0; i < MyFunc.length; i++ ) { if ( eval('arg'+i) == void 0) break; else r += eval('arg'+i); }; return r"); MyObject = new Function( args, "for (var i = 0; i < MyFunc.length; i++ ) { if ( eval('arg'+i) == void 0) break; eval('this.arg'+i +'=arg'+i); };"); @@ -89,5 +90,5 @@ new TestCase( SECTION, "FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1.length", 3, eval("FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1.length") ); new TestCase( SECTION, "FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1()", 3, eval("FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1()") ); new TestCase( SECTION, "FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1(1,2,3,4,5)", 3, eval("FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1(1,2,3,4,5)") ); - +*/ test(); Modified: pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.5-1.js ============================================================================== --- pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.5-1.js (original) +++ pypy/dist/pypy/lang/js/test/ecma/FunctionObjects/15.3.5-1.js Mon Jun 4 13:23:09 2007 @@ -96,6 +96,7 @@ } } +/* MyFunc = new Function( args, "var r=0; for (var i = 0; i < MyFunc.length; i++ ) { if ( eval('arg'+i) == void 0) break; else r += eval('arg'+i); }; return r"); MyObject = new Function( args, "for (var i = 0; i < MyFunc.length; i++ ) { if ( eval('arg'+i) == void 0) break; eval('this.arg'+i +'=arg'+i); };"); @@ -111,5 +112,5 @@ new TestCase( SECTION, "FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1.length", 3, eval("FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1.length") ); new TestCase( SECTION, "FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1()", 3, eval("FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1()") ); new TestCase( SECTION, "FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1(1,2,3,4,5)", 3, eval("FUN1 = new Function( 'a','b','c', 'return FUN1.length' ); FUN1(1,2,3,4,5)") ); - +*/ test(); Modified: pypy/dist/pypy/lang/js/test/ecma/ObjectObjects/15.2.4.2.js ============================================================================== --- pypy/dist/pypy/lang/js/test/ecma/ObjectObjects/15.2.4.2.js (original) +++ pypy/dist/pypy/lang/js/test/ecma/ObjectObjects/15.2.4.2.js Mon Jun 4 13:23:09 2007 @@ -61,10 +61,13 @@ new TestCase( SECTION, "(new Object()).toString()", "[object Object]", (new Object()).toString() ); +// see below for the reason to comment this +/* new TestCase( SECTION, "myvar = this; myvar.toString = Object.prototype.toString; myvar.toString()", GLOBAL.replace(/ @ 0x[0-9a-fA-F]+ \(native @ 0x[0-9a-fA-F]+\)/, ''), eval("myvar = this; myvar.toString = Object.prototype.toString; myvar.toString()") ); +*/ new TestCase( SECTION, "myvar = MyObject; myvar.toString = Object.prototype.toString; myvar.toString()", "[object Function]", @@ -102,10 +105,12 @@ "[object Date]", eval("myvar = new Date(); myvar.toString = Object.prototype.toString; myvar.toString()") ); -new TestCase( SECTION, "var MYVAR = new Object( this ); MYVAR.toString()", +// XXX Literal regexes are not supported +/*new TestCase( SECTION, "var MYVAR = new Object( this ); MYVAR.toString()", GLOBAL.replace(/ @ 0x[0-9a-fA-F]+ \(native @ 0x[0-9a-fA-F]+\)/, ''), eval("var MYVAR = new Object( this ); MYVAR.toString()") ); +*/ new TestCase( SECTION, "var MYVAR = new Object(); MYVAR.toString()", "[object Object]", Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Mon Jun 4 13:23:09 2007 @@ -340,7 +340,7 @@ assertp(""" var x = new Object(1,2,3,4); print(x); - """, "[object Object]") + """, '1') def test_increment(): assertv(""" @@ -591,4 +591,7 @@ function x () {}; x.my(); """, 1 - \ No newline at end of file + +def test_new_without_args_really(): + assertv("var x = new Boolean; x.toString();", 'false') + From santagada at codespeak.net Mon Jun 4 15:24:17 2007 From: santagada at codespeak.net (santagada at codespeak.net) Date: Mon, 4 Jun 2007 15:24:17 +0200 (CEST) Subject: [pypy-svn] r44026 - in pypy/dist/pypy/lang/js: . test/ecma test/ecma/GlobalObject Message-ID: <20070604132417.B055080B2@code0.codespeak.net> Author: santagada Date: Mon Jun 4 15:24:17 2007 New Revision: 44026 Modified: pypy/dist/pypy/lang/js/astbuilder.py pypy/dist/pypy/lang/js/constants.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsgrammar.txt pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/operations.py pypy/dist/pypy/lang/js/test/ecma/GlobalObject/15.1.2.2-2.js pypy/dist/pypy/lang/js/test/ecma/conftest.py Log: eval can return "error" when tests are running, jsgrammar changes for expressionnoin, some code on constants and jsobj to make more test run (but they are mostly wrong or incomplete) and operations should always raise ThrowException (so it can be capture in javascript). Modified: pypy/dist/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/dist/pypy/lang/js/astbuilder.py (original) +++ pypy/dist/pypy/lang/js/astbuilder.py Mon Jun 4 15:24:17 2007 @@ -112,6 +112,7 @@ visit_relationalexpression = binaryop visit_shiftexpression = binaryop visit_expression = binaryop + visit_expressionnoin = binaryop def visit_memberexpression(self, node): if isinstance(node.children[0], Symbol) and \ Modified: pypy/dist/pypy/lang/js/constants.py ============================================================================== --- pypy/dist/pypy/lang/js/constants.py (original) +++ pypy/dist/pypy/lang/js/constants.py Mon Jun 4 15:24:17 2007 @@ -8,7 +8,8 @@ r"\'", r'\b', r'\"', - r'\\'] + r'\\', + r'\u'] #don't know what to do with these codes = [ '\n', @@ -20,7 +21,8 @@ "'", "\b", '"', - '\\'] + '\\', + 'u'] escapedict = dict(zip(codes, escapes)) unescapedict = dict(zip(escapes, codes)) Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Mon Jun 4 15:24:17 2007 @@ -58,6 +58,8 @@ return create_object(ctx, 'Boolean', Value = Value) return create_object(ctx, 'Boolean', Value = W_Boolean(False)) +TEST = False + def evaljs(ctx, args, this): if len(args) >= 1: if isinstance(args[0], W_String): @@ -71,7 +73,13 @@ except ParseError, e: raise ThrowException(W_String('SintaxError: '+str(e))) - return node.execute(ctx) + if TEST: + try: + return node.execute(ctx) + except ThrowException, e: + return W_String("error") + else: + return node.execute(ctx) def parseIntjs(ctx, args, this): if len(args) < 1: Modified: pypy/dist/pypy/lang/js/jsgrammar.txt ============================================================================== --- pypy/dist/pypy/lang/js/jsgrammar.txt (original) +++ pypy/dist/pypy/lang/js/jsgrammar.txt Mon Jun 4 15:24:17 2007 @@ -397,7 +397,7 @@ | ; -expressionnoin : assignmentexpressionnoin ([","] assignmentexpressionnoin)+ +expressionnoin : assignmentexpressionnoin ("," assignmentexpressionnoin)+ | ; Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Mon Jun 4 15:24:17 2007 @@ -371,6 +371,9 @@ class W_Boolean(W_Primitive): def __init__(self, boolval): self.boolval = bool(boolval) + + def ToObject(self, ctx): + return create_object(ctx, 'Boolean', Value=self) def ToString(self): if self.boolval == True: @@ -412,7 +415,11 @@ class W_Number(W_Primitive): def __init__(self, floatval): - self.floatval = float(floatval) + try: + self.floatval = float(floatval) + except OverflowError: # XXX this should not be happening, there is an error somewhere else + #an ecma test to stress this is GlobalObject/15.1.2.2-2.js + self.floatval = Infinity def __str__(self): return str(self.floatval)+"W" Modified: pypy/dist/pypy/lang/js/operations.py ============================================================================== --- pypy/dist/pypy/lang/js/operations.py (original) +++ pypy/dist/pypy/lang/js/operations.py Mon Jun 4 15:24:17 2007 @@ -213,7 +213,7 @@ r2 = self.right.eval(ctx) r3 = r1.GetValue() if not isinstance(r3, W_PrimitiveObject): # TODO: review this on the spec - raise JsTypeError(str(r3) + " is not a function") + raise ThrowException(W_String("it is not a callable")) if isinstance(r1, W_Reference): r6 = r1.GetBase() @@ -224,8 +224,11 @@ else: r7 = r6 - return r3.Call(ctx=ctx, args=r2.get_args(), this=r7) - + try: + res = r3.Call(ctx=ctx, args=r2.get_args(), this=r7) + except JsTypeError: + raise ThrowException(W_String('it is not a function')) + return res class Comma(BinaryOp): def eval(self, ctx): @@ -688,21 +691,26 @@ # ############################################################################## +def commonnew(ctx, obj, args): + if not isinstance(obj, W_PrimitiveObject): + raise ThrowException(W_String('it is not a constructor')) + try: + res = obj.Construct(ctx=ctx, args=args) + except JsTypeError: + raise ThrowException(W_String('it is not a constructor')) + return res + class New(UnaryOp): def eval(self, ctx): x = self.expr.eval(ctx).GetValue() - if not isinstance(x, W_PrimitiveObject): - raise TypeError() - return x.Construct(ctx=ctx) + return commonnew(ctx, x, []) class NewWithArgs(BinaryOp): def eval(self, ctx): x = self.left.eval(ctx).GetValue() - if not isinstance(x, W_PrimitiveObject): - raise TypeError() args = self.right.eval(ctx).get_args() - return x.Construct(ctx=ctx, args=args) + return commonnew(ctx, x, args) Modified: pypy/dist/pypy/lang/js/test/ecma/GlobalObject/15.1.2.2-2.js ============================================================================== --- pypy/dist/pypy/lang/js/test/ecma/GlobalObject/15.1.2.2-2.js (original) +++ pypy/dist/pypy/lang/js/test/ecma/GlobalObject/15.1.2.2-2.js Mon Jun 4 15:24:17 2007 @@ -194,7 +194,7 @@ s = "0xFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; -s += "0000000000000000000000000000000000000" +s += "0000000000000000000000000000000000000"; new TestCase( SECTION, @@ -210,7 +210,7 @@ -1.7976931348623157e+308, -s ); -s += "0" +s += "0"; new TestCase( SECTION, "s = " + s + "; -s", Modified: pypy/dist/pypy/lang/js/test/ecma/conftest.py ============================================================================== --- pypy/dist/pypy/lang/js/test/ecma/conftest.py (original) +++ pypy/dist/pypy/lang/js/test/ecma/conftest.py Mon Jun 4 15:24:17 2007 @@ -4,6 +4,9 @@ from pypy.rlib.parsing.parsing import ParseError from py.__.test.outcome import Failed, ExceptionFailure import pypy.lang.js as js +from pypy.lang.js import interpreter + +interpreter.TEST = True rootdir = py.magic.autopath().dirpath() exclusionlist = ['shell.js', 'browser.js'] From cfbolz at codespeak.net Mon Jun 4 16:41:33 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 Jun 2007 16:41:33 +0200 (CEST) Subject: [pypy-svn] r44027 - pypy/dist/pypy/lang/prolog/interpreter Message-ID: <20070604144133.6FE4B80B2@code0.codespeak.net> Author: cfbolz Date: Mon Jun 4 16:41:32 2007 New Revision: 44027 Modified: pypy/dist/pypy/lang/prolog/interpreter/parsing.py Log: rewrite very strange code used for parsing lists Modified: pypy/dist/pypy/lang/prolog/interpreter/parsing.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/parsing.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/parsing.py Mon Jun 4 16:41:32 2007 @@ -323,16 +323,21 @@ return Term(name, children) def build_list(self, node): + result = [] + while node is not None: + node = self._build_list(node, result) + return result + + def _build_list(self, node, result): node = self.find_first_interesting(node) if isinstance(node, Nonterminal): child = node.children[1] if (isinstance(child, Symbol) and node.children[1].additional_info == ","): element = self.visit(node.children[0]) - l = self.build_list(node.children[2]) - l.insert(0, element) - return l - return [self.visit(node)] + result.append(element) + return node.children[2] + result.append(self.visit(node)) def find_first_interesting(self, node): if isinstance(node, Nonterminal) and len(node.children) == 1: From cfbolz at codespeak.net Tue Jun 5 11:19:24 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Jun 2007 11:19:24 +0200 (CEST) Subject: [pypy-svn] r44037 - pypy/dist/pypy/lang/prolog/builtin Message-ID: <20070605091924.732F880A5@code0.codespeak.net> Author: cfbolz Date: Tue Jun 5 11:19:23 2007 New Revision: 44037 Modified: pypy/dist/pypy/lang/prolog/builtin/register.py Log: attack some more info to builtin functions Modified: pypy/dist/pypy/lang/prolog/builtin/register.py ============================================================================== --- pypy/dist/pypy/lang/prolog/builtin/register.py (original) +++ pypy/dist/pypy/lang/prolog/builtin/register.py Tue Jun 5 11:19:23 2007 @@ -7,8 +7,11 @@ class Builtin(object): _immutable_ = True - def __init__(self, function): + def __init__(self, function, name, numargs, signature): self.function = function + self.name = name + self.numargs = numargs + self.signature = signature def call(self, engine, query, continuation): return self.function(engine, query, continuation) @@ -84,7 +87,8 @@ exec py.code.Source("\n".join(code)).compile() in miniglobals for name in expose_as: signature = "%s/%s" % (name, len(unwrap_spec)) - b = Builtin(miniglobals[funcname]) + b = Builtin(miniglobals[funcname], funcname, len(unwrap_spec), + signature) builtins[signature] = b if signature in [",/2", "is/2"]: builtins_list.insert(0, (signature, b)) From hpk at codespeak.net Tue Jun 5 11:55:20 2007 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jun 2007 11:55:20 +0200 (CEST) Subject: [pypy-svn] r44040 - pypy/extradoc/talk/dzug2007 Message-ID: <20070605095520.9D2DE809F@code0.codespeak.net> Author: hpk Date: Tue Jun 5 11:55:19 2007 New Revision: 44040 Added: pypy/extradoc/talk/dzug2007/ pypy/extradoc/talk/dzug2007/arch-framework-2.png (contents, props changed) pypy/extradoc/talk/dzug2007/arch-framework.png (contents, props changed) pypy/extradoc/talk/dzug2007/arch-overview.png (contents, props changed) pypy/extradoc/talk/dzug2007/arch-translation.png (contents, props changed) pypy/extradoc/talk/dzug2007/benchmarks-gc.png (contents, props changed) pypy/extradoc/talk/dzug2007/benchmarks.png (contents, props changed) pypy/extradoc/talk/dzug2007/compat-matrix.png (contents, props changed) pypy/extradoc/talk/dzug2007/dynlang.png (contents, props changed) pypy/extradoc/talk/dzug2007/dzug2007.txt pypy/extradoc/talk/dzug2007/interpreterarch.png (contents, props changed) pypy/extradoc/talk/dzug2007/python-arch-overview.png (contents, props changed) pypy/extradoc/talk/dzug2007/stackless_informal.png (contents, props changed) pypy/extradoc/talk/dzug2007/translation-overview.png (contents, props changed) pypy/extradoc/talk/dzug2007/translation.pdf (contents, props changed) pypy/extradoc/talk/dzug2007/translation.png (contents, props changed) pypy/extradoc/talk/dzug2007/ui (contents, props changed) Log: adding dzug talk at its intended place (hopefully i de-messed up things now) Added: pypy/extradoc/talk/dzug2007/arch-framework-2.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/arch-framework.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/arch-overview.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/arch-translation.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/benchmarks-gc.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/benchmarks.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/compat-matrix.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/dynlang.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/dzug2007.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dzug2007/dzug2007.txt Tue Jun 5 11:55:19 2007 @@ -0,0 +1,283 @@ +.. include:: + +=========================================== +How PyPy can be useful for Zope +=========================================== + +:Authors: Holger Krekel (merlinux GmbH) et al. + +What is PyPy? +---------------- + +* A compiler metaprogramming toolchain for dynamic languages + +* A flexible and fast Python Interpreter + +* An open source project (MIT License) + +* A (former) EU research project + +Paradigm +------------- + +.. raw:: html + +
+ +.. image:: arch-overview.png + :align: center + +PyPy Overview +-------------- + +.. raw:: html + +
+ +.. image:: dynlang.png + + + +Backends / Runtime integration +----------------------------------- + +- Main target: C/Posix +- Main new target: .NET/CLI/CLR +- Work in progress: JVM +- Special target: Javascript for Web applications + + +CLR/CLI Backend +---------------- + +- full python interpreter generated for .NET + +- support for CLR integration: + + - static RPython-level bindings + - on top dynamic bindings using reflection (clr module) + +.. - supports interpreter prototypes (using single source) + +More high-level backends +------------------------- + +- emerging JVM target: + + - translates complex RPython programs + - no problems foreseen for full interpreter generation + +- Javascript target: + + - translates complex programs + + +Python Interpreter Prototypes +------------------------------------- + +- features are independent of backend + +- Security / Taint Space + +- Transparent Proxies: + + - Transparent Distribution + - Orthogonal Persistence + + +Taint Space +-------------------- + +- control of information data flow: + + * label sensitive data + * avoid sensitive information leaks + * explicit primitive to declassify + +- easily implemented as an object space around + the standard one securing all operations + on objects + +Taint Space diagram +--------------------- + +.. raw:: html + +
+ +.. image:: interpreterarch.png + +- interactive prompt demo + + + +Transparent Proxies +-------------------------- + +- proxy: intercept any operation on an builtin object +- transparent: don't change object interface +- useful for implementing application level functionality + orthogonally to usage of objects +- is the mechanism for distribution and persistence prototypes +- see also .NET TransparentProxy + +Transparent Distribution +-------------------------- + +- transparent lazy access to remote objects +- internally uses RPC-like protocol +- remote objects are presented through transparent proxies +- access to remote tracebacks, frames, etc. work as if local! + +Orthogonal Persistence +-------------------------- + +- persist Python objects "invisibly" +- interpose interception of changes to objects +- implement your own custom persistence scheme (e.g. using ZODB) + +Threading in PyPy +----------------------- + +- principal choice of os-threading models (GIL, no, ...) +- stackless *transform* / micro-threads: + + - suspending/resuming computations + - pickling/migration of computations + - unlimited recursion + - *composable* greenlets, tasklets, co-routines + +Relative speeds to CPython +------------------------------ + ++----------+-------------------+---------------+ +| | CPython 2.4.4 | pypy-llvm | ++==========+===================+===============+ +| richards | 1.00 | 1.17 | ++----------+-------------------+---------------+ +| pystone | 1.00 | 1.55 | ++----------+-------------------+---------------+ +| templess | 1.00 | 5.41 | ++----------+-------------------+---------------+ +| gadfly | 1.00 | 6.38 | ++----------+-------------------+---------------+ +| mako | 1.00 | 7.65 | ++----------+-------------------+---------------+ + +(March 2007, improvements afterwards) + +JIT Compiler Generator +---------------------------- + +- generate JIT Compilers automatically! + +JIT Compiler Generator +---------------------------- + +- generate JIT Compilers automatically! + +- we began to apply it to the Python Interpreter + (integer arithmetic) + +- approach more complete than Psyco + +- gets us in the range of C-speed ("gcc -O0")! + +Python Interpreter Status (1.0) +--------------------------------- + +- compliant, 340 KLOC / 85 test KLOC +- single source for all platforms +- flexibel, fast, well-tested (11975 tests) +- new middleware features +- need more extension modules! +- better GCs and more JITting will even improve speed! + +Special RPython programs +-------------------------- + +- webservers, web applications, algorithms + +- can be translated to various targets + +- can run up to 100 times faster compared + to being interpreted through CPython + +- very fast startup times! + +- used for commercial purposes + +RPython advantages over C +----------------------------------- + +- portable code +- high level data structures +- easy to test, quick to develop +- translates to various targets, including CPython extension module + +py lib release +---------------------- + +* py lib / py.test 0.9 release (Feb 2007): + + - project independent tool for automated testing + - lightweight no-boilerplate approach + - many development support features for PyPy + - includes distributed testing (started as SOP project) + +Summary (1) +--------------------- + +- with PyPy it is easy to: + + - implement advanced Python Interpreter features + - write new backends / runtime targets + - implement new (non-python) interpreters + +- PyPy's rough edges: it is a research result! + +- emerging as platform to implement dynamic languages + +Summary (2) +------------------------ + +- advantages of PyPy's meta-programming approach: + + - separation of lang implementation aspects + - integrates with today's mainstream platforms + - single source eases maintenance + - all interpreters benefit from advanced transformations + - all code at high abstraction level! + +Possible Zope applications +------------------------------- + +- security + transparent proxies: persistence, distribution +- experiment with RPython to implement + + - Page Template Engine? + - AJAX/Javascript web applications? + - speedy extension modules? +- use for web hosting (fast startup times)? + +Future +--------------- + +- caretaker/trusted contributors group (pypy-ct): + + - takes care for conceptual integrity + - negotiates (sprint) funding + +- pending community process: + + - many directions and interests + - consolidation phase?! + - settle on rough roadmap + +- more sprints! (19 so far) + + +.. |bullet| unicode:: U+02022 +.. footer:: Holger Krekel (merlinux GmbH) + + Added: pypy/extradoc/talk/dzug2007/interpreterarch.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/python-arch-overview.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/stackless_informal.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/translation-overview.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/translation.pdf ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/translation.png ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dzug2007/ui ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dzug2007/ui Tue Jun 5 11:55:19 2007 @@ -0,0 +1 @@ +link ../ui \ No newline at end of file From hpk at codespeak.net Tue Jun 5 12:01:37 2007 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jun 2007 12:01:37 +0200 (CEST) Subject: [pypy-svn] r44041 - pypy/extradoc/talk/dzug2007 Message-ID: <20070605100137.09EB480A5@code0.codespeak.net> Author: hpk Date: Tue Jun 5 12:01:37 2007 New Revision: 44041 Modified: pypy/extradoc/talk/dzug2007/dzug2007.txt Log: fix number of tests Modified: pypy/extradoc/talk/dzug2007/dzug2007.txt ============================================================================== --- pypy/extradoc/talk/dzug2007/dzug2007.txt (original) +++ pypy/extradoc/talk/dzug2007/dzug2007.txt Tue Jun 5 12:01:37 2007 @@ -188,7 +188,7 @@ - compliant, 340 KLOC / 85 test KLOC - single source for all platforms -- flexibel, fast, well-tested (11975 tests) +- flexibel, fast, well-tested (11805 tests) - new middleware features - need more extension modules! - better GCs and more JITting will even improve speed! From hpk at codespeak.net Tue Jun 5 16:16:47 2007 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jun 2007 16:16:47 +0200 (CEST) Subject: [pypy-svn] r44044 - pypy/extradoc/talk/dzug2007 Message-ID: <20070605141647.C0CD4808E@code0.codespeak.net> Author: hpk Date: Tue Jun 5 16:16:47 2007 New Revision: 44044 Added: pypy/extradoc/talk/dzug2007/dzug2007.html Modified: pypy/extradoc/talk/dzug2007/dzug2007.txt Log: the talk as i gave it (went quite well - but somewhat difficult to do in 30 minutes including demos) Added: pypy/extradoc/talk/dzug2007/dzug2007.html ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dzug2007/dzug2007.html Tue Jun 5 16:16:47 2007 @@ -0,0 +1,637 @@ + + + + + + + +How PyPy could be useful for Zope + + + + + + + + + + + + + + + +
+
+
+ + +
+
+
+

How PyPy could be useful for Zope

+ +++ + + + +
Authors:Holger Krekel (merlinux GmbH) et al.
+ + + + + + + + + +
+
+

What is PyPy?

+
    +
  • A compiler metaprogramming toolchain for dynamic languages
  • +
  • A flexible and fast Python Interpreter
  • +
  • An open source project (MIT License)
  • +
  • A (former) EU research project
  • +
  • -> PyPy-1.0 is a research result
  • +
+
+
+

Paradigm

+
arch-overview.png
+
+
+

PyPy Overview

+
dynlang.png +
+
+

Backends / Runtime integration

+
    +
  • single source program translates to:
      +
    • Main target: C/Posix
    • +
    • Main new target: .NET/CLI/CLR
    • +
    • Work in progress: JVM
    • +
    • Special target: Javascript for Web applications
    • +
    +
  • +
+
+
+

CLR/CLI Backend

+
    +
  • full python interpreter generated for .NET
  • +
  • support for CLR integration:
      +
    • static RPython-level bindings
    • +
    • on top dynamic bindings using reflection (clr module)
    • +
    +
  • +
+ +
+
+

More high-level backends

+
    +
  • emerging JVM target:
      +
    • translates complex RPython programs
    • +
    • no problems foreseen for full interpreter generation
    • +
    +
  • +
  • Javascript target:
      +
    • translates complex programs
    • +
    +
  • +
+
+
+

Python Interpreter Prototypes

+
    +
  • features are independent of backend
  • +
  • Security / Taint Space
  • +
  • Transparent Proxies:
      +
    • Transparent Distribution
    • +
    • Orthogonal Persistence
    • +
    +
  • +
+
+
+

Taint Space

+
    +
  • control of information data flow:
      +
    • label sensitive data
    • +
    • avoid sensitive information leaks
    • +
    • explicit primitive to declassify
    • +
    +
  • +
  • easily implemented as an object space around +the standard one securing all operations +on objects
  • +
+
+
+

Taint Space diagram

+
interpreterarch.png +
    +
  • interactive prompt demo
  • +
+
+
+

Transparent Proxies

+
    +
  • proxy: intercept any operation on an builtin object
  • +
  • transparent: don't change object interface
  • +
  • useful for implementing application level functionality +orthogonally to usage of objects
  • +
  • is the mechanism for distribution and persistence prototypes
  • +
  • see also .NET TransparentProxy
  • +
+
+
+

Transparent Distribution

+
    +
  • transparent lazy access to remote objects
  • +
  • internally uses RPC-like protocol
  • +
  • remote objects are presented through transparent proxies
  • +
  • access to remote tracebacks, frames, etc. work as if local!
  • +
+
+
+

Orthogonal Persistence

+
    +
  • persist Python objects "invisibly"
  • +
  • interpose interception of changes to objects
  • +
  • implement your own custom persistence scheme (e.g. using ZODB)
  • +
+
+
+

Threading in PyPy

+
    +
  • principal choice of os-threading models (GIL, no, ...)
  • +
  • stackless transform / micro-threads:
      +
    • suspending/resuming computations
    • +
    • pickling/migration of computations
    • +
    • unlimited recursion
    • +
    • composable greenlets, tasklets, co-routines
    • +
    +
  • +
+
+
+

Relative speeds to CPython

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 CPython 2.4.4pypy-llvm
richards1.001.17
pystone1.001.55
templess1.005.41
gadfly1.006.38
mako1.007.65
+

(March 2007, improvements afterwards)

+
+
+

JIT Compiler Generator

+
    +
  • generate JIT Compilers automatically!
  • +
+
+
+

JIT Compiler Generator

+
    +
  • generate JIT Compilers automatically!
  • +
  • we began to apply it to the Python Interpreter +(integer arithmetic)
  • +
  • approach more complete than Psyco
  • +
  • gets us in the range of C-speed ("gcc -O0")!
  • +
+
+