From jlg at codespeak.net Wed Aug 1 16:23:20 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Wed, 1 Aug 2007 16:23:20 +0200 (CEST) Subject: [pypy-svn] r45447 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070801142320.E0372814E@code0.codespeak.net> Author: jlg Date: Wed Aug 1 16:23:19 2007 New Revision: 45447 Modified: pypy/dist/pypy/lang/scheme/execution.py pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/ssparser.py pypy/dist/pypy/lang/scheme/test/test_macro.py pypy/dist/pypy/lang/scheme/test/test_parser.py Log: bug in macro expansions removed, SyntacticClosure is no more, instead we have PairClosure and SymbolClosure; parsing for ellipsis; macros with flat ellipsis works Modified: pypy/dist/pypy/lang/scheme/execution.py ============================================================================== --- pypy/dist/pypy/lang/scheme/execution.py (original) +++ pypy/dist/pypy/lang/scheme/execution.py Wed Aug 1 16:23:19 2007 @@ -83,13 +83,11 @@ self.closure = closure def _dispatch(self, symb): - if isinstance(symb, W_Symbol): - return (self, symb.name) + if isinstance(symb, SymbolClosure): + return (symb.closure, symb.name) - elif isinstance(symb, SyntacticClosure): - symbol = symb.sexpr - if isinstance(symbol, W_Symbol): - return (symb.closure, symbol.name) + elif isinstance(symb, W_Symbol): + return (self, symb.name) raise SchemeSyntaxError Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Wed Aug 1 16:23:19 2007 @@ -77,6 +77,8 @@ def eq_symbol(self, w_symb): return w_symb is self +w_ellipsis = W_Symbol("...") + def symbol(name): #use this to create new symbols, it stores all symbols #in W_Symbol.obarray dict @@ -205,6 +207,9 @@ #end proper list with dotted return car + " . " + cdr.to_string() + def __repr__(self): + return "" + def eval_tr(self, ctx): oper = self.car.eval(ctx) if not isinstance(oper, W_Callable): @@ -316,7 +321,7 @@ return "#" % (self.pname,) def procedure_tr(self, ctx, lst): - """must be tail-recursive aware, uses eval_body""" + #must be tail-recursive aware, uses eval_body #ctx is a caller context, which is joyfully ignored local_ctx = self.closure.copy() @@ -619,7 +624,7 @@ class MacroIf(W_Macro): def call_tr(self, ctx, lst): - """if needs to be tail-recursive aware""" + #if needs to be tail-recursive aware if not isinstance(lst, W_Pair): raise SchemeSyntaxError w_condition = lst.car @@ -667,7 +672,7 @@ class LetStar(W_Macro): def call_tr(self, ctx, lst): - """let* uses eval_body, so it is tail-recursive aware""" + #let* uses eval_body, so it is tail-recursive aware if not isinstance(lst, W_Pair): raise SchemeSyntaxError local_ctx = ctx.copy() @@ -856,6 +861,11 @@ #closes template in syntactic enviroment at the point of definition return W_Transformer(syntax_lst, ctx) +class Ellipsis(Exception): + def __init__(self, expr, level): + self.expr = expr + self.level = level + class SyntaxRule(object): def __init__(self, pattern, template, literals): self.pattern = pattern @@ -886,6 +896,13 @@ if w_form is not w_literal: return (False, {}) + w_pattcdr = w_patt.cdr + if isinstance(w_pattcdr, W_Pair) and w_pattcdr.car is w_ellipsis: + #w_pattcar should be matched 0-inf times in ellipsis + print w_patt, w_expr + match_dict[w_pattcar.to_string()] = Ellipsis(w_expr, 1) + return (True, match_dict) + if isinstance(w_pattcar, W_Pair): if not isinstance(w_exprcar, W_Pair): return (False, {}) @@ -897,28 +914,60 @@ match_dict.update(match_nested) match_dict[w_pattcar.to_string()] = w_exprcar + w_patt = w_patt.cdr w_expr = w_expr.cdr - if w_expr is w_nil and w_patt is w_nil: - return (True, match_dict) + if (w_expr is w_nil) and (w_patt is w_nil): + return (True, match_dict) + + if w_patt is w_nil: + return (False, {}) + + #w_patt is symbol or primitive //as cdr of dotted list + match_dict[w_patt.to_string()] = w_expr + return (True, match_dict) return (False, {}) -class SyntacticClosure(W_Root): - def __init__(self, ctx, sexpr): - assert not isinstance(sexpr, SyntacticClosure) - assert isinstance(sexpr, W_Root) - self.sexpr = sexpr +class SymbolClosure(W_Symbol): + def __init__(self, ctx, symbol): + assert isinstance(symbol, W_Symbol) + assert not isinstance(symbol, SymbolClosure) + self.symbol = symbol + self.name = symbol.name self.closure = ctx def eval_tr(self, ctx): #this symbol is in Syntactic Closure - return self.sexpr.eval_tr(self.closure) + return self.symbol.eval_tr(self.closure) + + def to_string(self): + #return "#" + return self.symbol.to_string() + + def __repr__(self): + return "" + +class PairClosure(W_Pair): + def __init__(self, ctx, pair): + assert isinstance(pair, W_Pair) + assert not isinstance(pair, PairClosure) + self.pair = pair + self.car = pair.car + self.cdr = pair.cdr + self.closure = ctx + + def eval_tr(self, ctx): + #this pair is in Syntactic Closure + return self.pair.eval_tr(self.closure) def to_string(self): #return "#" - return self.sexpr.to_string() + return self.pair.to_string() + + def __repr__(self): + return "" class W_Transformer(W_Procedure): def __init__(self, syntax_lst, ctx, pname=""): @@ -950,16 +999,31 @@ # enviroment at the point of use #not always needed, because w_sub can have no W_Symbol inside - if isinstance(w_sub, W_Symbol) or isinstance(w_sub, W_Pair): - return SyntacticClosure(ctx, w_sub) + if isinstance(w_sub, W_Symbol) and \ + not isinstance(w_sub, SymbolClosure): + return SymbolClosure(ctx, w_sub) + + if isinstance(w_sub, W_Pair) and \ + not isinstance(w_sub, PairClosure): + return PairClosure(ctx, w_sub) + + if isinstance(w_sub, Ellipsis): + raise w_sub return w_sub return sexpr elif isinstance(sexpr, W_Pair): - w_pair = W_Pair(self.substitute(ctx, sexpr.car, match_dict), - self.substitute(ctx, sexpr.cdr, match_dict)) + try: + w_pair = W_Pair(self.substitute(ctx, sexpr.car, match_dict), + self.substitute(ctx, sexpr.cdr, match_dict)) + except Ellipsis, e: + scdr = sexpr.cdr + if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis: + return e.expr + else: + raise SchemeSyntaxError w_paircar = w_pair.car if isinstance(w_paircar, W_Symbol): @@ -972,8 +1036,7 @@ except UnboundVariable: pass - elif isinstance(w_paircar, SyntacticClosure) and \ - isinstance(w_paircar.sexpr, W_Symbol): + elif isinstance(w_paircar, SymbolClosure): try: #ops, which context? w_macro = ctx.get(w_paircar.sexpr.to_string()) @@ -1043,7 +1106,6 @@ w_formal = lst.car while isinstance(w_formal, W_Pair): w_def = w_formal.get_car_as_pair() - #evaluate the values in caller ctx w_transformer = w_def.get_cdr_as_pair().car.eval(ctx) if not isinstance(w_transformer, W_Transformer): raise SchemeSyntaxError Modified: pypy/dist/pypy/lang/scheme/ssparser.py ============================================================================== --- pypy/dist/pypy/lang/scheme/ssparser.py (original) +++ pypy/dist/pypy/lang/scheme/ssparser.py Wed Aug 1 16:23:19 2007 @@ -2,7 +2,8 @@ from pypy.rlib.parsing.pypackrat import PackratParser from pypy.rlib.parsing.makepackrat import BacktrackException, Status from pypy.lang.scheme.object import W_Pair, W_Integer, W_String, symbol, \ - w_nil, W_Boolean, W_Real, quote, qq, unquote, unquote_splicing + w_nil, W_Boolean, W_Real, quote, qq, unquote, unquote_splicing, \ + w_ellipsis def str_unquote(s): str_lst = [] @@ -29,13 +30,18 @@ IGNORE* return {symbol(c)}; + ELLIPSIS: + c = '...' + IGNORE* + return {w_ellipsis}; + FIXNUM: c = `\-?(0|([1-9][0-9]*))` IGNORE* return {W_Integer(int(c))}; FLOAT: - c = `\-?[0-9]*\.[0-9]*` + c = `\-?([0-9]*\.[0-9]+|[0-9]+\.[0-9]*)` IGNORE* return {W_Real(float(c))}; @@ -83,6 +89,7 @@ | qq | unquote_splicing | unquote + | ELLIPSIS | FLOAT | FIXNUM | BOOLEAN Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Wed Aug 1 16:23:19 2007 @@ -236,6 +236,19 @@ assert eval_(ctx, "(my-or #f 42)").to_number() == 42 assert eval_(ctx, "(my-or #f #f 82)").to_number() == 82 +def test_macro_expand(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax foo (syntax-rules () + ((foo) #t) + ((foo arg) arg)))""") + eval_(ctx, """(define-syntax bar (syntax-rules () + ((bar) (foo)) + ((bar arg) (foo arg))))""") + + w_expr = parse("(bar 42)")[0] + #should expand directly (recursively) to 42 + assert ctx.get("bar").expand(ctx, w_expr).to_string() == "42" + def test_let_syntax(): ctx = ExecutionContext() w_result = \ @@ -260,3 +273,32 @@ assert eval_(ctx, "a").to_number() == 0 +def test_reverse(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax reverse-order + (syntax-rules () + ((_ e) (reverse-order e ())) + ((_ (e . rest) r) + (reverse-order rest (e . r))) + ((_ () r) r)))""") + + w_result = eval_(ctx, "(reverse-order (2 3 -))") + assert w_result.to_number() == 1 + +def test_ellipsis_symbol(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax or (syntax-rules () + ((or) #f) + ((or e) e) + ((or e1 e2 ...) + (let ((temp e1)) + (if temp + temp + (or e2 ...))))))""") + + assert eval_(ctx, "(or 12)").to_number() == 12 + assert eval_(ctx, "(or 12 42)").to_number() == 12 + assert eval_(ctx, "(or #f 42)").to_number() == 42 + assert eval_(ctx, "(or #f #f 82)").to_number() == 82 + assert eval_(ctx, "(or #f #f #f 162)").to_number() == 162 + Modified: pypy/dist/pypy/lang/scheme/test/test_parser.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_parser.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_parser.py Wed Aug 1 16:23:19 2007 @@ -2,6 +2,7 @@ from pypy.lang.scheme.ssparser import parse from pypy.lang.scheme.object import W_Boolean, W_Real, W_Integer, W_String from pypy.lang.scheme.object import W_Pair, W_Nil, W_Symbol, W_Symbol +from pypy.rlib.parsing.makepackrat import BacktrackException def parse_sexpr(expr): return parse(expr)[0] @@ -56,6 +57,15 @@ assert isinstance(w_float, W_Real) assert unwrap(w_float) == -123456.1234 + w_float = parse_sexpr('.1234') + assert isinstance(w_float, W_Real) + assert unwrap(w_float) == 0.1234 + w_float = parse_sexpr('12.') + assert isinstance(w_float, W_Real) + assert unwrap(w_float) == 12.0 + + py.test.raises(BacktrackException, parse_sexpr, '.') + def test_sexpr(): w_list = parse_sexpr('( 1 )') assert isinstance(w_list, W_Pair) @@ -155,3 +165,8 @@ assert unwrap(t) == ['unquote-splicing', ['list', ['unquote-splicing', 'b'], 3]] +def test_ellipsis(): + w_float = parse_sexpr('...') + assert isinstance(w_float, W_Symbol) + assert unwrap(w_float) == "..." + From jlg at codespeak.net Wed Aug 1 16:47:41 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Wed, 1 Aug 2007 16:47:41 +0200 (CEST) Subject: [pypy-svn] r45448 - pypy/dist/pypy/lang/scheme Message-ID: <20070801144741.3B5F18157@code0.codespeak.net> Author: jlg Date: Wed Aug 1 16:47:40 2007 New Revision: 45448 Modified: pypy/dist/pypy/lang/scheme/object.py Log: scheme translation repaired Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Wed Aug 1 16:47:40 2007 @@ -861,11 +861,15 @@ #closes template in syntactic enviroment at the point of definition return W_Transformer(syntax_lst, ctx) -class Ellipsis(Exception): +class Ellipsis(W_Root): def __init__(self, expr, level): self.expr = expr self.level = level +class EllipsisException(SchemeException): + def __init__(self, ellipsis): + self.expr = ellipsis.expr + class SyntaxRule(object): def __init__(self, pattern, template, literals): self.pattern = pattern @@ -1008,7 +1012,7 @@ return PairClosure(ctx, w_sub) if isinstance(w_sub, Ellipsis): - raise w_sub + raise EllipsisException(w_sub) return w_sub @@ -1018,7 +1022,7 @@ try: w_pair = W_Pair(self.substitute(ctx, sexpr.car, match_dict), self.substitute(ctx, sexpr.cdr, match_dict)) - except Ellipsis, e: + except EllipsisException, e: scdr = sexpr.cdr if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis: return e.expr @@ -1027,6 +1031,8 @@ w_paircar = w_pair.car if isinstance(w_paircar, W_Symbol): + #XXX what if we have here SymbolClosure? + # can happen when recursive macro try: w_macro = ctx.get(w_paircar.name) @@ -1036,18 +1042,6 @@ except UnboundVariable: pass - elif isinstance(w_paircar, SymbolClosure): - try: - #ops, which context? - w_macro = ctx.get(w_paircar.sexpr.to_string()) - - # recursive macro expansion - if isinstance(w_macro, W_DerivedMacro): - return w_macro.expand(ctx, w_pair) - - except UnboundVariable: - pass - return w_pair return sexpr From arigo at codespeak.net Wed Aug 1 18:37:31 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Aug 2007 18:37:31 +0200 (CEST) Subject: [pypy-svn] r45449 - in pypy/dist/pypy/translator/sandbox: . test Message-ID: <20070801163731.46F3A817F@code0.codespeak.net> Author: arigo Date: Wed Aug 1 18:37:29 2007 New Revision: 45449 Added: pypy/dist/pypy/translator/sandbox/sandlib.py (contents, props changed) pypy/dist/pypy/translator/sandbox/test/test_sandlib.py (contents, props changed) Modified: pypy/dist/pypy/translator/sandbox/sandboxmsg.py Log: Start a library meant for the parent process that runs a subprocess that was translated with --sandbox. Modified: pypy/dist/pypy/translator/sandbox/sandboxmsg.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/sandboxmsg.py (original) +++ pypy/dist/pypy/translator/sandbox/sandboxmsg.py Wed Aug 1 18:37:29 2007 @@ -155,11 +155,58 @@ raise ValueError return self.value[i:self.pos] + def decode(self, argtypes): + "NOT_RPYTHON" # optimized decoder + v = self.value + i = self.pos + for t in argtypes: + if v[i] != t: + raise ValueError + end = i + 5 + if t == "s": + length, = struct.unpack("!i", v[i+1:i+5]) + end += length + yield v[i+5:end] + elif t == "i": + result, = struct.unpack("!i", v[i+1:end]) + yield result + elif t == "I": + result, = struct.unpack("!I", v[i+1:end]) + yield result + else: + raise ValueError + i = end + if i != len(v): + raise ValueError("more values to decode") + +def encode_message(types, values): + "NOT_RPYTHON" # optimized encoder for messages + chars = ["!"] + entries = [] + if len(types) != len(values): + raise ValueError("mismatch in the number of values to encode") + for t, val in zip(types, values): + chars.append("c") + entries.append(t) + if t == "s": + if not isinstance(val, str): + raise TypeError + chars.append("i%ds" % len(val)) + entries.append(len(val)) + entries.append(val) + elif t in "iI": + chars.append(t) + entries.append(val) + else: + raise ValueError + data = struct.pack(''.join(chars), *entries) + return struct.pack("!i", len(data) + 4) + data + def timeout_read(f, size, timeout=None): if size < 0: raise ValueError("negative size") if timeout is None: - return f.read(size) + result = f.read(size) else: # XXX not Win32-compliant! assert not sys.platform.startswith('win'), "XXX fix me" @@ -173,9 +220,11 @@ len(result), timeout, size)) buf = os.read(fd, size - len(result)) if not buf: - raise EOFError + break result += buf - return result + if len(result) < size: + raise EOFError + return result class Timeout(Exception): pass Added: pypy/dist/pypy/translator/sandbox/sandlib.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/sandbox/sandlib.py Wed Aug 1 18:37:29 2007 @@ -0,0 +1,110 @@ +""" +A Python library to execute and communicate with a subprocess that +was translated from RPython code with --sandbox. This library is +for the outer process, which can run CPython or PyPy. +""" + +from py.compat import subprocess +from pypy.translator.sandbox.sandboxmsg import Message, encode_message +from pypy.translator.sandbox.sandboxmsg import read_message + +class SandboxedProc(object): + """Base class to control a sandboxed subprocess. + Inherit from this class and implement all the do_xxx() methods + for the external functions xxx that you want to support. + """ + def __init__(self, args): + """'args' should a sequence of argument for the subprocess, + starting with the full path of the executable. + """ + self.popen = subprocess.Popen(args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + + def poll(self): + return self.popen.poll() + + def wait(self): + return self.popen.wait() + + def handle_forever(self): + while True: + try: + msg = read_message(self.popen.stdout) + except EOFError, e: + break + answer = self.handle_message(msg) + self.popen.stdin.write(answer) + returncode = self.popen.wait() + if returncode != 0: + raise OSError("the sandboxed subprocess exited with code %d" % ( + returncode,)) + + def handle_message(self, msg): + fn = msg.nextstring() + try: + argtypes, restypes = self.TYPES[fn] + except KeyError: + raise IOError("trying to invoke unknown external function %r" % ( + fn,)) + handler = getattr(self, 'do_' + fn) + answers = handler(*msg.decode(argtypes)) + if len(restypes) == 0: + assert answers is None + answers = (0,) + elif len(restypes) == 1: + answers = (0, answers) + else: + answers = (0,) + answers + return encode_message("i" + restypes, answers) + + TYPES = { + "open": ("sii", "i"), + "read": ("iI", "s"), + "write": ("is", "I"), + "close": ("i", "i"), + } + + +class SimpleIOSandboxedProc(SandboxedProc): + """Control a sandboxed subprocess which is only allowed to read from + its stdin and write to its stdout and stderr. + """ + _input = None + _output = None + _error = None + + def communicate(self, input=None): + """Send data to stdin. Read data from stdout and stderr, + until end-of-file is reached. Wait for process to terminate. + """ + import cStringIO + if input: + if isinstance(input, str): + input = cStringIO.StringIO(input) + self._input = input + self._output = cStringIO.StringIO() + self._error = cStringIO.StringIO() + self.handle_forever() + output = self._output.getvalue() + self._output = None + error = self._error.getvalue() + self._error = None + return (output, error) + + def do_read(self, fd, size): + if fd == 0: + if self._input is None: + return "" + else: + return self._input.read(size) + raise OSError("trying to read from fd %d" % (fd,)) + + def do_write(self, fd, data): + if fd == 1: + self._output.write(data) + return len(data) + if fd == 2: + self._error.write(data) + return len(data) + raise OSError("trying to write to fd %d" % (fd,)) Added: pypy/dist/pypy/translator/sandbox/test/test_sandlib.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/sandbox/test/test_sandlib.py Wed Aug 1 18:37:29 2007 @@ -0,0 +1,79 @@ +import os, StringIO +from pypy.tool.sourcetools import func_with_new_name +from pypy.translator.sandbox.sandlib import SandboxedProc +from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc +from pypy.translator.interactive import Translation + + +class MySandboxedProc(SandboxedProc): + + def __init__(self, args, expected): + SandboxedProc.__init__(self, args) + self.expected = expected + self.seen = 0 + + def _make_method(name): + def do_xxx(self, *input): + print "decoded from subprocess: %s%r" % (name, input) + expectedmsg, expectedinput, output = self.expected[self.seen] + assert name == expectedmsg + assert input == expectedinput + self.seen += 1 + return output + return func_with_new_name(do_xxx, 'do_%s' % name) + + do_open = _make_method("open") + do_read = _make_method("read") + do_write = _make_method("write") + do_close = _make_method("close") + + +def test_lib(): + def entry_point(argv): + fd = os.open("/tmp/foobar", os.O_RDONLY, 0777) + assert fd == 77 + res = os.read(fd, 123) + assert res == "he\x00llo" + count = os.write(fd, "world\x00!\x00") + assert count == 42 + for arg in argv: + count = os.write(fd, arg) + assert count == 61 + os.close(fd) + return 0 + t = Translation(entry_point, backend='c', standalone=True, sandbox=True) + exe = t.compile() + + proc = MySandboxedProc([exe, 'x1', 'y2'], expected = [ + ("open", ("/tmp/foobar", os.O_RDONLY, 0777), 77), + ("read", (77, 123), "he\x00llo"), + ("write", (77, "world\x00!\x00"), 42), + ("write", (77, exe), 61), + ("write", (77, "x1"), 61), + ("write", (77, "y2"), 61), + ("close", (77,), 0), + ]) + proc.handle_forever() + assert proc.seen == len(proc.expected) + +def test_simpleio(): + def entry_point(argv): + print "Please enter a number:" + buf = "" + while True: + t = os.read(0, 1) # 1 character from stdin + if not t: + raise EOFError + if t == '\n': + break + buf += t + num = int(buf) + print "The double is:", num * 2 + return 0 + t = Translation(entry_point, backend='c', standalone=True, sandbox=True) + exe = t.compile() + + proc = SimpleIOSandboxedProc([exe, 'x1', 'y2']) + output, error = proc.communicate("21\n") + assert output == "Please enter a number:\nThe double is: 42\n" + assert error == "" From jlg at codespeak.net Thu Aug 2 11:46:03 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Thu, 2 Aug 2007 11:46:03 +0200 (CEST) Subject: [pypy-svn] r45450 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070802094603.29C1B80EC@code0.codespeak.net> Author: jlg Date: Thu Aug 2 11:46:01 2007 New Revision: 45450 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: ellipsis in macro template can refer to list Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Thu Aug 2 11:46:01 2007 @@ -862,9 +862,8 @@ return W_Transformer(syntax_lst, ctx) class Ellipsis(W_Root): - def __init__(self, expr, level): + def __init__(self, expr): self.expr = expr - self.level = level class EllipsisException(SchemeException): def __init__(self, ellipsis): @@ -904,7 +903,7 @@ if isinstance(w_pattcdr, W_Pair) and w_pattcdr.car is w_ellipsis: #w_pattcar should be matched 0-inf times in ellipsis print w_patt, w_expr - match_dict[w_pattcar.to_string()] = Ellipsis(w_expr, 1) + match_dict[w_pattcar.to_string()] = Ellipsis(w_expr) return (True, match_dict) if isinstance(w_pattcar, W_Pair): @@ -1024,10 +1023,18 @@ self.substitute(ctx, sexpr.cdr, match_dict)) except EllipsisException, e: scdr = sexpr.cdr + print ">", sexpr, e.expr if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis: return e.expr else: - raise SchemeSyntaxError + plst = [] + w_pair = e.expr + while isinstance(w_pair, W_Pair): + plst.append(W_Pair(w_pair.car, scdr)) + w_pair = w_pair.cdr + + ellipsis = Ellipsis(plst2lst(plst)) + raise EllipsisException(ellipsis) w_paircar = w_pair.car if isinstance(w_paircar, W_Symbol): Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Thu Aug 2 11:46:01 2007 @@ -302,3 +302,40 @@ assert eval_(ctx, "(or #f #f 82)").to_number() == 82 assert eval_(ctx, "(or #f #f #f 162)").to_number() == 162 +def test_ellipsis_list_template(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax letzero + (syntax-rules () + ((_ (sym ...) body ...) + (let ((sym 0) ...) body ...))))""") + + assert eval_(ctx, "(letzero (x) x)").to_number() == 0 + assert eval_(ctx, "(letzero (x) (set! x 1) x)").to_number() == 1 + + assert eval_(ctx, "(letzero (x y z) (+ x y z))").to_number() == 0 + assert eval_(ctx, """(letzero (x y z) (set! x 1) + (set! y 1) + (set! z 1) + (+ x y z))""").to_number() == 3 + +def test_ellipsis_list_pattern(): + py.test.skip("in progress") + ctx = ExecutionContext() + eval_(ctx, """(define-syntax rlet + (syntax-rules () + ((_ ((val sym) ...) body ...) + (let ((sym val) ...) body ...))))""") + + assert eval_(ctx, "(rlet ((0 x)) x)").to_number() == 0 + assert eval_(ctx, "(rlet ((0 x)) (set! x 1) x)").to_number() == 1 + + assert eval_(ctx, """(rlet ((0 x) (0 y) (0 z)) + (+ x y z))""").to_number() == 0 + assert eval_(ctx, """(rlet ((0 x) (0 y) (0 z)) + (set! x 1) + (set! y 1) + (set! z 1) + (+ x y z))""").to_number() == 3 + + assert False + From jlg at codespeak.net Thu Aug 2 12:28:07 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Thu, 2 Aug 2007 12:28:07 +0200 (CEST) Subject: [pypy-svn] r45451 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070802102807.9C12580E6@code0.codespeak.net> Author: jlg Date: Thu Aug 2 12:28:00 2007 New Revision: 45451 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: not nested ellipsis in template in glory Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Thu Aug 2 12:28:00 2007 @@ -866,8 +866,9 @@ self.expr = expr class EllipsisException(SchemeException): - def __init__(self, ellipsis): + def __init__(self, ellipsis, name): self.expr = ellipsis.expr + self.name = name class SyntaxRule(object): def __init__(self, pattern, template, literals): @@ -1011,7 +1012,7 @@ return PairClosure(ctx, w_sub) if isinstance(w_sub, Ellipsis): - raise EllipsisException(w_sub) + raise EllipsisException(w_sub, sexpr.name) return w_sub @@ -1023,18 +1024,23 @@ self.substitute(ctx, sexpr.cdr, match_dict)) except EllipsisException, e: scdr = sexpr.cdr - print ">", sexpr, e.expr + print ">", sexpr, e.name, e.expr if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis: - return e.expr - else: + print ">>", sexpr, e.name, e.expr plst = [] w_pair = e.expr while isinstance(w_pair, W_Pair): - plst.append(W_Pair(w_pair.car, scdr)) + #plst.append(W_Pair(w_pair.car, scdr)) + zzz = self.substitute(ctx, sexpr.car, + {e.name: w_pair.car}) + plst.append(zzz) w_pair = w_pair.cdr - ellipsis = Ellipsis(plst2lst(plst)) - raise EllipsisException(ellipsis) + ellipsis = plst2lst(plst) + print ellipsis + return ellipsis + else: + raise e #EllipsisException(ellipsis, e.name) w_paircar = w_pair.car if isinstance(w_paircar, W_Symbol): Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Thu Aug 2 12:28:00 2007 @@ -318,6 +318,22 @@ (set! z 1) (+ x y z))""").to_number() == 3 +def test_ellipsis_expr_template(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax zero-if-true + (syntax-rules () + ((_ sym ...) + (begin + (if sym (set! sym 0)) ...))))""") + + eval_(ctx, "(define x #t)") + eval_(ctx, "(define y #f)") + eval_(ctx, "(define z #t)") + eval_(ctx, "(zero-if-true x y z)") + assert eval_(ctx, "x").to_number() == 0 + assert eval_(ctx, "y").to_boolean() is False + assert eval_(ctx, "z").to_number() == 0 + def test_ellipsis_list_pattern(): py.test.skip("in progress") ctx = ExecutionContext() From arigo at codespeak.net Thu Aug 2 13:38:34 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 13:38:34 +0200 (CEST) Subject: [pypy-svn] r45452 - pypy/dist/pypy/translator/goal Message-ID: <20070802113834.89A0780E8@code0.codespeak.net> Author: arigo Date: Thu Aug 2 13:38:33 2007 New Revision: 45452 Modified: pypy/dist/pypy/translator/goal/targetjsstandalone.py Log: Fix the JS target to use the current interface. Modified: pypy/dist/pypy/translator/goal/targetjsstandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetjsstandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetjsstandalone.py Thu Aug 2 13:38:33 2007 @@ -3,7 +3,6 @@ """ import sys -from pypy.rlib.streamio import open_file_as_stream from pypy.lang.js.interpreter import * from pypy.lang.js.jsobj import ExecutionReturned @@ -13,8 +12,8 @@ def entry_point(argv): if len(argv) == 2: - f = open_file_as_stream(argv[1]) - interp.run(load_source(f.readall())) + t = load_file(argv[1]) + interp.run(t) return 0 elif argv[0] == 'foo': raise ExecutionReturned(None) From arigo at codespeak.net Thu Aug 2 13:46:40 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 13:46:40 +0200 (CEST) Subject: [pypy-svn] r45453 - pypy/dist/pypy/rpython Message-ID: <20070802114640.00E2580C4@code0.codespeak.net> Author: arigo Date: Thu Aug 2 13:46:40 2007 New Revision: 45453 Modified: pypy/dist/pypy/rpython/extfunc.py Log: A more explicit error message for bad annotations reaching external function calls. Modified: pypy/dist/pypy/rpython/extfunc.py ============================================================================== --- pypy/dist/pypy/rpython/extfunc.py (original) +++ pypy/dist/pypy/rpython/extfunc.py Thu Aug 2 13:46:40 2007 @@ -82,9 +82,19 @@ if self.signature_args is not None: assert len(args_s) == len(self.signature_args),\ "Argument number mismatch" - for arg, expected in zip(args_s, self.signature_args): - arg = unionof(arg, expected) - assert expected.contains(arg) + for i, expected in enumerate(self.signature_args): + arg = unionof(args_s[i], expected) + if not expected.contains(arg): + name = getattr(self, 'name', None) + if not name: + try: + name = self.instance.__name__ + except AttributeError: + name = '?' + raise Exception("In call to external function %r:\n" + "arg %d must be %s,\n" + " got %s" % ( + name, i+1, expected, args_s[i])) return self.signature_result def specialize_call(self, hop): From arigo at codespeak.net Thu Aug 2 13:50:11 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 13:50:11 +0200 (CEST) Subject: [pypy-svn] r45454 - pypy/dist/pypy/lang/prolog/builtin Message-ID: <20070802115011.E5EB580E8@code0.codespeak.net> Author: arigo Date: Thu Aug 2 13:50:11 2007 New Revision: 45454 Modified: pypy/dist/pypy/lang/prolog/builtin/formatting.py Log: Annotation fix - the implicitly returned None eventually reaches os.write(), where is explodes. 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 Thu Aug 2 13:50:11 2007 @@ -56,6 +56,8 @@ return self.format_term(term) elif isinstance(term, Var): return self.format_var(term) + else: + return '?' def format_atom(self, s): from pypy.rlib.parsing.deterministic import LexerError From jlg at codespeak.net Thu Aug 2 16:07:00 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Thu, 2 Aug 2007 16:07:00 +0200 (CEST) Subject: [pypy-svn] r45455 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070802140700.2BD2B80F4@code0.codespeak.net> Author: jlg Date: Thu Aug 2 16:06:58 2007 New Revision: 45455 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: SyntaxRule match refactoring; test_macro.py changed; more ellipsis working Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Thu Aug 2 16:06:58 2007 @@ -862,13 +862,18 @@ return W_Transformer(syntax_lst, ctx) class Ellipsis(W_Root): - def __init__(self, expr): - self.expr = expr + def __init__(self, mdict_lst): + self.mdict_lst = mdict_lst class EllipsisException(SchemeException): - def __init__(self, ellipsis, name): - self.expr = ellipsis.expr - self.name = name + def __init__(self, ellipsis): + self.mdict_lst = ellipsis.mdict_lst + +class EllipsisPattern(SchemeException): + pass + +class MatchError(SchemeException): + pass class SyntaxRule(object): def __init__(self, pattern, template, literals): @@ -881,58 +886,63 @@ def match(self, ctx, w_expr, pattern=None): if pattern is None: - w_patt = self.pattern - else: - w_patt = pattern + return self.matchr(ctx, self.pattern, w_expr) - match_dict = {} - while isinstance(w_patt, W_Pair) and isinstance(w_expr, W_Pair): + return self.matchr(ctx, pattern, w_expr) + + def matchr(self, ctx, w_patt, w_expr): + if isinstance(w_patt, W_Pair): w_pattcar = w_patt.car - w_exprcar = w_expr.car + if isinstance(w_expr, W_Pair): + mdict_car = self.matchr(ctx, w_pattcar, w_expr.car) - w_literal = self.literals.get(w_pattcar.to_string(), None) - if w_literal is not None: try: - w_form = ctx.get(w_exprcar.to_string()) - except UnboundVariable: - w_form = w_exprcar - - if w_form is not w_literal: - return (False, {}) + #we catch EllipsisPattern here because in car + # we dont know how to deal with it + mdict_cdr = self.matchr(ctx, w_patt.cdr, w_expr.cdr) + except EllipsisPattern: + print "ellipsis matched", w_patt, w_expr - w_pattcdr = w_patt.cdr - if isinstance(w_pattcdr, W_Pair) and w_pattcdr.car is w_ellipsis: - #w_pattcar should be matched 0-inf times in ellipsis - print w_patt, w_expr - match_dict[w_pattcar.to_string()] = Ellipsis(w_expr) - return (True, match_dict) - - if isinstance(w_pattcar, W_Pair): - if not isinstance(w_exprcar, W_Pair): - return (False, {}) + mdict_lst = [] + w_pair = w_expr + while isinstance(w_pair, W_Pair): + mdict = self.matchr(ctx, w_pattcar, w_pair.car) + mdict_lst.append(mdict) + w_pair = w_pair.cdr - (matched, match_nested) = self.match(ctx, w_exprcar, w_pattcar) - if not matched: - return (False, {}) + mdict_cdr = {} + ellipsis = Ellipsis(mdict_lst) + for name in mdict_lst[0].keys(): + mdict_cdr[name] = ellipsis + + mdict_car.update(mdict_cdr) + return mdict_car - match_dict.update(match_nested) + if w_pattcar is w_ellipsis and w_expr is w_nil: + raise EllipsisPattern - match_dict[w_pattcar.to_string()] = w_exprcar + if w_patt is w_ellipsis: + raise EllipsisPattern - w_patt = w_patt.cdr - w_expr = w_expr.cdr + if isinstance(w_patt, W_Symbol): + w_literal = self.literals.get(w_patt.name, None) + if w_literal is not None: + try: + w_form = ctx.get(w_expr.to_string()) + except UnboundVariable: + w_form = w_expr - if (w_expr is w_nil) and (w_patt is w_nil): - return (True, match_dict) + if w_form is not w_literal: + raise MatchError - if w_patt is w_nil: - return (False, {}) + return {w_patt.name: w_expr} - #w_patt is symbol or primitive //as cdr of dotted list - match_dict[w_patt.to_string()] = w_expr - return (True, match_dict) + if w_patt is w_nil and w_expr is w_nil: + return {} - return (False, {}) + #w_patt is w_nil, but w_expr is not + # or w_patt is W_Pair but w_expr is not + raise MatchError class SymbolClosure(W_Symbol): def __init__(self, ctx, symbol): @@ -981,16 +991,18 @@ def match(self, ctx, w_expr): for rule in self.syntax_lst: - (matched, match_dict) = rule.match(ctx, w_expr) - if matched: + try: + match_dict = rule.match(ctx, w_expr) return (rule.template, match_dict) + except MatchError: + pass - return (None, {}) + raise MatchError def expand(self, ctx, w_expr): - (template, match_dict) = self.match(ctx, w_expr) - - if template is None : + try: + (template, match_dict) = self.match(ctx, w_expr) + except MatchError: raise SchemeSyntaxError return self.substitute(ctx, template, match_dict) @@ -1012,7 +1024,7 @@ return PairClosure(ctx, w_sub) if isinstance(w_sub, Ellipsis): - raise EllipsisException(w_sub, sexpr.name) + raise EllipsisException(w_sub) return w_sub @@ -1024,23 +1036,20 @@ self.substitute(ctx, sexpr.cdr, match_dict)) except EllipsisException, e: scdr = sexpr.cdr - print ">", sexpr, e.name, e.expr + print ">", sexpr, e.mdict_lst if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis: - print ">>", sexpr, e.name, e.expr + print ">>", sexpr, e.mdict_lst + plst = [] - w_pair = e.expr - while isinstance(w_pair, W_Pair): - #plst.append(W_Pair(w_pair.car, scdr)) - zzz = self.substitute(ctx, sexpr.car, - {e.name: w_pair.car}) + for mdict in e.mdict_lst: + zzz = self.substitute(ctx, sexpr.car, mdict) plst.append(zzz) - w_pair = w_pair.cdr ellipsis = plst2lst(plst) print ellipsis return ellipsis else: - raise e #EllipsisException(ellipsis, e.name) + raise e w_paircar = w_pair.car if isinstance(w_paircar, W_Symbol): Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Thu Aug 2 16:06:58 2007 @@ -9,41 +9,42 @@ def eval_noctx(expr): return parse(expr)[0].eval(ExecutionContext()) +def parse_(expr): + return parse(expr)[0] + def test_syntax_rules_match(): ctx = ExecutionContext() py.test.raises(SchemeSyntaxError, eval_noctx, "(syntax-rules 1)") py.test.raises(SchemeSyntaxError, eval_noctx, "(syntax-rules () 1)") w_transformer = eval_noctx("(syntax-rules ())") - w_expr = parse("(foo)")[0] - assert not w_transformer.match(ctx, w_expr)[0] + w_expr = parse_("(foo)") + py.test.raises(MatchError, w_transformer.match, ctx, w_expr) w_transformer = eval_noctx("(syntax-rules () ((foo) #t))") - w_expr = parse("(bar)")[0] - assert w_transformer.match(ctx, w_expr)[0] - w_expr = parse("(foo bar)")[0] - assert not w_transformer.match(ctx, w_expr)[0] + w_expr = parse_("(bar)") + assert w_transformer.match(ctx, w_expr)[0].to_boolean() + w_expr = parse_("(foo bar)") + py.test.raises(MatchError, w_transformer.match, ctx, w_expr) w_transformer = eval_noctx("""(syntax-rules () ((_) #t) ((_ foo) foo))""") - w_expr = parse("(foo)")[0] + w_expr = parse_("(foo)") assert w_transformer.match(ctx, w_expr)[0].to_boolean() - w_expr = parse("(foo bar)")[0] + w_expr = parse_("(foo bar)") (template, match_dict) = w_transformer.match(ctx, w_expr) assert template.to_string() == "foo" assert match_dict["foo"].to_string() == "bar" - w_expr = parse("(foo bar boo)")[0] - (template, match_dict) = w_transformer.match(ctx, w_expr) - assert not template - assert match_dict == {} + w_expr = parse_("(foo bar boo)") + py.test.raises(MatchError, w_transformer.match, ctx, w_expr) w_transformer = eval_noctx("(syntax-rules () ((foo (bar)) bar))") - w_expr = parse("(_ fuzz)")[0] - assert not w_transformer.match(ctx, w_expr)[0] - w_expr = parse("(_ (fuzz))")[0] + w_expr = parse_("(_ fuzz)") + py.test.raises(MatchError, w_transformer.match, ctx, w_expr) + w_expr = parse_("(_ (fuzz))") (template, match_dict) = w_transformer.match(ctx, w_expr) - assert template + assert template.to_string() == "bar" assert match_dict["bar"].to_string() == "fuzz" def test_syntax_rules_literals(): @@ -53,14 +54,14 @@ # w_transformer created in ctx w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") - w_expr = parse("(foo bar boo)")[0] - assert not w_transformer.match(ctx, w_expr)[0] + w_expr = parse_("(foo bar boo)") + py.test.raises(MatchError, w_transformer.match, ctx, w_expr) # exact match - w_expr = parse("(foo => boo)")[0] + w_expr = parse_("(foo => boo)") # within the same context - assert w_transformer.match(ctx, w_expr)[0] + assert w_transformer.match(ctx, w_expr)[0].to_boolean() w_42 = W_Number(42) @@ -68,19 +69,19 @@ closure = ctx.copy() closure.put("=>", w_42) w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") - assert not w_transformer.match(closure, w_expr)[0] + py.test.raises(MatchError, w_transformer.match, closure, w_expr) # different lexical scope, not the same bindings for => in ctx and closure ctx.put("=>", W_Number(12)) assert ctx.get("=>") is not closure.get("=>") w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") - assert not w_transformer.match(closure, w_expr)[0] + py.test.raises(MatchError, w_transformer.match, closure, w_expr) # the same binding for => in ctx and closure ctx.put("=>", w_42) assert ctx.get("=>") is closure.get("=>") w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") - assert w_transformer.match(closure, w_expr)[0] + assert w_transformer.match(closure, w_expr)[0].to_boolean() def test_syntax_rules_expand_simple(): ctx = ExecutionContext() @@ -88,12 +89,12 @@ w_transformer = eval_(ctx, """(syntax-rules () ((_) #t) ((_ foo) foo))""") - w_expr = parse("(foo)")[0] + w_expr = parse_("(foo)") w_expanded = w_transformer.expand(ctx, w_expr) assert isinstance(w_expanded, W_Boolean) assert w_expanded.to_boolean() == True - w_expr = parse("(foo bar)")[0] + w_expr = parse_("(foo bar)") w_expanded = w_transformer.expand(ctx, w_expr) assert w_expanded.to_string() == "bar" @@ -101,7 +102,7 @@ ((let1 var val body) (let ((var val)) body)))""") - w_expr = parse("(let1 var 12 (+ 1 var))")[0] + w_expr = parse_("(let1 var 12 (+ 1 var))") w_expanded = w_transformer.expand(ctx, w_expr) assert isinstance(w_expanded, W_Pair) assert w_expanded.to_string() == "(let ((var 12)) (+ 1 var))" @@ -110,7 +111,7 @@ ((let1 (var val) body) (let ((var val)) body)))""") - w_expr = parse("(let1 (var 12) (+ 1 var))")[0] + w_expr = parse_("(let1 (var 12) (+ 1 var))") w_expanded = w_transformer.expand(ctx, w_expr) assert isinstance(w_expanded, W_Pair) assert w_expanded.to_string() == "(let ((var 12)) (+ 1 var))" @@ -122,14 +123,14 @@ ((_ var) (let ((temp 1)) (+ var temp))))""") - w_expr = parse("(_ 12)")[0] + w_expr = parse_("(_ 12)") w_expanded = w_transformer.expand(ctx, w_expr) assert w_expanded.to_string() == "(let ((temp 1)) (+ 12 temp))" assert w_transformer.expand_eval(ctx, w_expr).to_number() == 13 #transparency eval_(ctx, "(define temp 12)") - w_expr = parse("(_ temp)")[0] + w_expr = parse_("(_ temp)") w_expanded = w_transformer.expand(ctx, w_expr) assert w_expanded.to_string() == "(let ((temp 1)) (+ temp temp))" assert w_transformer.expand_eval(ctx, w_expr).to_number() == 13 @@ -157,11 +158,11 @@ (loop (- counter 1))))))) (loop count))))""") - w_expr = parse("(dotimes 5 (set! counter (+ counter 1)))")[0] + w_expr = parse_("(dotimes 5 (set! counter (+ counter 1)))") py.test.raises(UnboundVariable, w_transformer.expand_eval, ctx, w_expr) eval_(ctx, "(define counter 0)") - w_expr = parse("(dotimes 5 (set! counter (+ counter 1)))")[0] + w_expr = parse_("(dotimes 5 (set! counter (+ counter 1)))") w_transformer.expand_eval(ctx, w_expr) assert ctx.get("counter").to_number() == 5 @@ -172,7 +173,7 @@ ((shadow used-arg body) (let ((used-arg 5)) body)))""") - w_expr = parse("(shadow test test)")[0] + w_expr = parse_("(shadow test test)") assert w_transformer.expand_eval(ctx, w_expr).to_number() == 5 eval_(ctx, "(define test 7)") @@ -182,7 +183,7 @@ ((shadow used-arg body) (letrec ((used-arg 5)) body)))""") - w_expr = parse("(shadow test test)")[0] + w_expr = parse_("(shadow test test)") assert w_transformer.expand_eval(ctx, w_expr).to_number() == 5 eval_(ctx, "(define test 7)") @@ -226,10 +227,10 @@ assert eval_(ctx, "(my-or 12)").to_number() == 12 #should expand recursively and after that eval - w_expr = parse("(my-or 12 42)")[0] + w_expr = parse_("(my-or 12 42)") assert ctx.get("my-or").expand(ctx, w_expr).to_string() == \ "(if 12 12 42)" - w_expr = parse("(my-or 12 42 82)")[0] + w_expr = parse_("(my-or 12 42 82)") assert ctx.get("my-or").expand(ctx, w_expr).to_string() == \ "(if 12 12 (if 42 42 82))" assert eval_(ctx, "(my-or 12 42)").to_number() == 12 @@ -245,7 +246,7 @@ ((bar) (foo)) ((bar arg) (foo arg))))""") - w_expr = parse("(bar 42)")[0] + w_expr = parse_("(bar 42)") #should expand directly (recursively) to 42 assert ctx.get("bar").expand(ctx, w_expr).to_string() == "42" @@ -298,7 +299,7 @@ assert eval_(ctx, "(or 12)").to_number() == 12 assert eval_(ctx, "(or 12 42)").to_number() == 12 - assert eval_(ctx, "(or #f 42)").to_number() == 42 + assert eval_(ctx, "(or #f #f 82)").to_number() == 82 assert eval_(ctx, "(or #f #f #f 162)").to_number() == 162 @@ -335,7 +336,6 @@ assert eval_(ctx, "z").to_number() == 0 def test_ellipsis_list_pattern(): - py.test.skip("in progress") ctx = ExecutionContext() eval_(ctx, """(define-syntax rlet (syntax-rules () @@ -353,5 +353,3 @@ (set! z 1) (+ x y z))""").to_number() == 3 - assert False - From jlg at codespeak.net Thu Aug 2 17:30:48 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Thu, 2 Aug 2007 17:30:48 +0200 (CEST) Subject: [pypy-svn] r45459 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070802153048.9D9AB80D6@code0.codespeak.net> Author: jlg Date: Thu Aug 2 17:30:47 2007 New Revision: 45459 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: more on macros and ellipses; W_Transformer.substitute changes Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Thu Aug 2 17:30:47 2007 @@ -866,8 +866,8 @@ self.mdict_lst = mdict_lst class EllipsisException(SchemeException): - def __init__(self, ellipsis): - self.mdict_lst = ellipsis.mdict_lst + def __init__(self, length): + self.length = length class EllipsisPattern(SchemeException): pass @@ -897,8 +897,8 @@ mdict_car = self.matchr(ctx, w_pattcar, w_expr.car) try: - #we catch EllipsisPattern here because in car - # we dont know how to deal with it + #we catch EllipsisPattern here because in car + # we dont know how to deal with it mdict_cdr = self.matchr(ctx, w_patt.cdr, w_expr.cdr) except EllipsisPattern: print "ellipsis matched", w_patt, w_expr @@ -1007,13 +1007,22 @@ return self.substitute(ctx, template, match_dict) - def substitute(self, ctx, sexpr, match_dict): + def substitute(self, ctx, sexpr, match_dict, ellipsis_cnt=-1): if isinstance(sexpr, W_Symbol): w_sub = match_dict.get(sexpr.name, None) if w_sub is not None: # Hygenic macros close their input forms in the syntactic # enviroment at the point of use + if isinstance(w_sub, Ellipsis): + if ellipsis_cnt < 0: + raise EllipsisException(len(w_sub.mdict_lst)) + else: + mdict = w_sub.mdict_lst[ellipsis_cnt] + w_sub = mdict[sexpr.name] + #for nested ellipsis we should probably raise + # here if w_sub is still Ellipsis + #not always needed, because w_sub can have no W_Symbol inside if isinstance(w_sub, W_Symbol) and \ not isinstance(w_sub, SymbolClosure): @@ -1023,30 +1032,24 @@ not isinstance(w_sub, PairClosure): return PairClosure(ctx, w_sub) - if isinstance(w_sub, Ellipsis): - raise EllipsisException(w_sub) - return w_sub return sexpr elif isinstance(sexpr, W_Pair): try: - w_pair = W_Pair(self.substitute(ctx, sexpr.car, match_dict), - self.substitute(ctx, sexpr.cdr, match_dict)) + w_pair = W_Pair( + self.substitute(ctx, sexpr.car, match_dict, ellipsis_cnt), + self.substitute(ctx, sexpr.cdr, match_dict, ellipsis_cnt)) except EllipsisException, e: scdr = sexpr.cdr - print ">", sexpr, e.mdict_lst if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis: - print ">>", sexpr, e.mdict_lst - plst = [] - for mdict in e.mdict_lst: - zzz = self.substitute(ctx, sexpr.car, mdict) + for i in range(e.length): + zzz = self.substitute(ctx, sexpr.car, match_dict, i) plst.append(zzz) ellipsis = plst2lst(plst) - print ellipsis return ellipsis else: raise e Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Thu Aug 2 17:30:47 2007 @@ -353,3 +353,50 @@ (set! z 1) (+ x y z))""").to_number() == 3 +def test_ellipsis_mixed(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax set-if-true + (syntax-rules () + ((_ (sym val) ...) + (begin + (if sym (set! sym val)) ...))))""") + + eval_(ctx, "(define x #t)") + eval_(ctx, "(define y #f)") + eval_(ctx, "(define z #t)") + eval_(ctx, "(set-if-true (x 1) (y 2) (z 3))") + assert eval_(ctx, "x").to_number() == 1 + assert eval_(ctx, "y").to_boolean() is False + assert eval_(ctx, "z").to_number() == 3 + +def test_ellipsis_wo_ellipsis(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax let-default + (syntax-rules () + ((_ (sym ...) val body ...) + (let ((sym val) ...) body ...))))""") + + assert eval_(ctx, "(let-default (x y z) 1 (+ x y z))").to_number() == 3 + +def test_different_ellipsis(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax let2 + (syntax-rules () + ((_ (sym ...) (val ...) body ...) + (let ((sym val) ...) body ...))))""") + + assert eval_(ctx, "(let2 (x y z) (1 2 3) (+ x y z))").to_number() == 6 + +def test_nested_ellipsis(): + py.test.skip("in progress") + ctx = ExecutionContext() + eval_(ctx, """(define-syntax quote-append + (syntax-rules () + ((_ (obj ...) ...) + (quote (obj ... ...)))))""") + + assert eval_(ctx, """(quote-append (x y) + (1 2 3 4) + (+))""").to_string() == \ + "(x y 1 2 3 4 +)" + From arigo at codespeak.net Thu Aug 2 19:15:40 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 19:15:40 +0200 (CEST) Subject: [pypy-svn] r45460 - pypy/dist/pypy/rpython Message-ID: <20070802171540.8F6BA80A4@code0.codespeak.net> Author: arigo Date: Thu Aug 2 19:15:39 2007 New Revision: 45460 Modified: pypy/dist/pypy/rpython/normalizecalls.py Log: A hard-to-test fix in assign_inheritence_ids(). This tries to ensure that newly seen classes all go to the end of the peers list as long as they don't extend previous hierarchies (no common base class). Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Thu Aug 2 19:15:39 2007 @@ -273,16 +273,6 @@ # ____________________________________________________________ -class Max(object): - def __cmp__(self, other): - if self is other: - return 0 - else: - return 1 - -MAX = Max() # a maximum object - - class TotalOrderSymbolic(ComputedIntSymbolic): def __init__(self, orderwitness, peers): @@ -301,14 +291,34 @@ if self.value is None: self.peers.sort() for i, peer in enumerate(self.peers): - assert peer.value is None + assert peer.value is None or peer.value == i peer.value = i assert self.value is not None return self.value + def dump(self, annotator): # for debugging + self.peers.sort() + mapping = {} + for classdef in annotator.bookkeeper.classdefs: + if hasattr(classdef, '_unique_cdef_id'): + mapping[classdef._unique_cdef_id] = classdef + for peer in self.peers: + if peer is self: + print '==>', + else: + print ' ', + print 'value %4s --' % (peer.value,), peer.orderwitness, + if peer.orderwitness[-1] in mapping: + print mapping[peer.orderwitness[-1]] + else: + print + def assign_inheritance_ids(annotator): # we sort the classes by lexicographic order of reversed(mro), - # which gives a nice depth-first order. + # which gives a nice depth-first order. The classes are turned + # into numbers in order to (1) help determinism, (2) ensure that + # new hierarchies of classes with no common base classes can be + # added later and get higher numbers. bk = annotator.bookkeeper try: lst = bk._inheritance_id_symbolics @@ -316,11 +326,22 @@ lst = bk._inheritance_id_symbolics = [] for classdef in annotator.bookkeeper.classdefs: if not hasattr(classdef, 'minid'): - witness = list(classdef.getmro()) + witness = [get_unique_cdef_id(cdef) for cdef in classdef.getmro()] witness.reverse() classdef.minid = TotalOrderSymbolic(witness, lst) classdef.maxid = TotalOrderSymbolic(witness + [MAX], lst) +MAX = 1E100 +_cdef_id_counter = 0 +def get_unique_cdef_id(cdef): + global _cdef_id_counter + try: + return cdef._unique_cdef_id + except AttributeError: + cdef._unique_cdef_id = _cdef_id_counter + _cdef_id_counter += 1 + return cdef._unique_cdef_id + # ____________________________________________________________ def perform_normalizations(rtyper): From arigo at codespeak.net Thu Aug 2 19:16:23 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 19:16:23 +0200 (CEST) Subject: [pypy-svn] r45461 - pypy/dist/pypy/translator/sandbox Message-ID: <20070802171623.C50F680E3@code0.codespeak.net> Author: arigo Date: Thu Aug 2 19:16:23 2007 New Revision: 45461 Modified: pypy/dist/pypy/translator/sandbox/rsandbox.py Log: Cannot use EOFError here. If the original program didn't use it already, then it's a new Exception subclass and normalizecalls is unhappy. Modified: pypy/dist/pypy/translator/sandbox/rsandbox.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/rsandbox.py (original) +++ pypy/dist/pypy/translator/sandbox/rsandbox.py Thu Aug 2 19:16:23 2007 @@ -38,10 +38,8 @@ while length > 0: size = rffi.cast(rffi.SIZE_T, length) count = rffi.cast(lltype.Signed, ll_write_not_sandboxed(fd, buf, size)) - if count < 0: + if count <= 0: raise IOError - if count == 0: - raise EOFError length -= count buf = lltype.direct_ptradd(lltype.direct_arrayitems(buf), count) buf = rffi.cast(rffi.CCHARP, buf) @@ -53,10 +51,8 @@ while got < length: size1 = rffi.cast(rffi.SIZE_T, length - got) count = rffi.cast(lltype.Signed, ll_read_not_sandboxed(fd, p, size1)) - if count < 0: + if count <= 0: raise IOError - if count == 0: - raise EOFError got += count p = lltype.direct_ptradd(lltype.direct_arrayitems(p), count) p = rffi.cast(rffi.CCHARP, p) From arigo at codespeak.net Thu Aug 2 19:17:24 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 19:17:24 +0200 (CEST) Subject: [pypy-svn] r45462 - in pypy/dist/pypy: rpython translator/sandbox/test Message-ID: <20070802171724.CE56380EB@code0.codespeak.net> Author: arigo Date: Thu Aug 2 19:17:24 2007 New Revision: 45462 Modified: pypy/dist/pypy/rpython/extfunc.py pypy/dist/pypy/rpython/extfuncregistry.py pypy/dist/pypy/translator/sandbox/test/test_sandbox.py Log: Mark the math.*() functions as sandbox-safe, i.e. they are kept unmodified in executables even if they are built with the --sandbox option. Modified: pypy/dist/pypy/rpython/extfunc.py ============================================================================== --- pypy/dist/pypy/rpython/extfunc.py (original) +++ pypy/dist/pypy/rpython/extfunc.py Thu Aug 2 19:17:24 2007 @@ -76,6 +76,8 @@ annotation(self.instance.result, self.bookkeeper)) class ExtFuncEntry(ExtRegistryEntry): + safe_not_sandboxed = False + def compute_result_annotation(self, *args_s): if hasattr(self, 'ann_hook'): self.ann_hook() @@ -117,7 +119,8 @@ impl, self.signature_args, hop.s_result) else: obj = rtyper.type_system.getexternalcallable(args_ll, ll_result, - name, _external_name=self.name, _callable=fakeimpl) + name, _external_name=self.name, _callable=fakeimpl, + _safe_not_sandboxed=self.safe_not_sandboxed) vlist = [hop.inputconst(typeOf(obj), obj)] + hop.inputargs(*args_r) hop.exception_is_here() return hop.genop('direct_call', vlist, r_result) @@ -125,7 +128,8 @@ def _register_external(function, args, result=None, export_name=None, llimpl=None, ooimpl=None, llfakeimpl=None, oofakeimpl=None, - annotation_hook=None): + annotation_hook=None, + sandboxsafe=False): """ function: the RPython function that will be rendered as an external function (e.g.: math.floor) args: a list containing the annotation of the arguments @@ -134,10 +138,12 @@ llimpl, ooimpl: optional; if provided, these RPython functions are called instead of the target function llfakeimpl, oofakeimpl: optional; if provided, they are called by the llinterpreter annotationhook: optional; a callable that is called during annotation, useful for genc hacks + sandboxsafe: use True if the function performs no I/O (safe for --sandbox) """ class FunEntry(ExtFuncEntry): _about_ = function + safe_not_sandboxed = sandboxsafe if args is None: signature_args = None else: Modified: pypy/dist/pypy/rpython/extfuncregistry.py ============================================================================== --- pypy/dist/pypy/rpython/extfuncregistry.py (original) +++ pypy/dist/pypy/rpython/extfuncregistry.py Thu Aug 2 19:17:24 2007 @@ -24,7 +24,8 @@ 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' ] for name in simple_math_functions: - _register_external(getattr(math, name), [float], float, "ll_math.ll_math_%s" % name) + _register_external(getattr(math, name), [float], float, "ll_math.ll_math_%s" % name, + sandboxsafe=True) def frexp_hook(): from pypy.rpython.extfunctable import record_call @@ -54,7 +55,8 @@ oofake = getattr(oo_math, 'll_math_%s' % name, None) _register_external(func, args, res, 'll_math.ll_math_%s' % name, llfakeimpl=llfake, oofakeimpl=oofake, - annotation_hook = hook) + annotation_hook = hook, + sandboxsafe=True) # ___________________________ Modified: pypy/dist/pypy/translator/sandbox/test/test_sandbox.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/test/test_sandbox.py (original) +++ pypy/dist/pypy/translator/sandbox/test/test_sandbox.py Thu Aug 2 19:17:24 2007 @@ -130,3 +130,26 @@ tail = f.read() f.close() assert tail == "" + +class TestPrintedResults: + + def run(self, entry_point, args, expected): + t = Translation(entry_point, backend='c', standalone=True, + sandbox=True) + exe = t.compile() + from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc + proc = SimpleIOSandboxedProc([exe] + args) + output, error = proc.communicate() + assert error == '' + assert output == expected + + def test_safefuncs(self): + import math + def entry_point(argv): + a = float(argv[1]) + print int(math.floor(a - 0.2)), + print int(math.ceil(a)), + print int(100.0 * math.sin(a)), + print + return 0 + self.run(entry_point, ["3.011"], "2 4 13\n") From arigo at codespeak.net Thu Aug 2 19:21:49 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 19:21:49 +0200 (CEST) Subject: [pypy-svn] r45463 - pypy/dist/pypy/translator/sandbox Message-ID: <20070802172149.D799880ED@code0.codespeak.net> Author: arigo Date: Thu Aug 2 19:21:48 2007 New Revision: 45463 Modified: pypy/dist/pypy/translator/sandbox/rsandbox.py Log: Grumble. I wouldn't mind a sane approach to separate compilation instead of this... Modified: pypy/dist/pypy/translator/sandbox/rsandbox.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/rsandbox.py (original) +++ pypy/dist/pypy/translator/sandbox/rsandbox.py Thu Aug 2 19:21:48 2007 @@ -119,6 +119,7 @@ msg.packstring(chr(CFalse) + chr(CFalse)) msg.packsize_t(rffi.cast(rffi.SIZE_T, CFalse)) msg.packbuf(buf, CFalse * 5, CFalse * 6) + msg.packccharp(lltype.nullptr(rffi.CCHARP.TO)) try: writeall_not_sandboxed(STDOUT, buf, msg.getlength()) finally: From arigo at codespeak.net Thu Aug 2 19:24:38 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 19:24:38 +0200 (CEST) Subject: [pypy-svn] r45464 - pypy/dist/pypy/translator/sandbox Message-ID: <20070802172438.172FC80ED@code0.codespeak.net> Author: arigo Date: Thu Aug 2 19:24:37 2007 New Revision: 45464 Modified: pypy/dist/pypy/translator/sandbox/rsandbox.py Log: Oups, lltype.nullptr returns a SomePtr(const=<* None>). More grumbles. Modified: pypy/dist/pypy/translator/sandbox/rsandbox.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/rsandbox.py (original) +++ pypy/dist/pypy/translator/sandbox/rsandbox.py Thu Aug 2 19:24:37 2007 @@ -119,7 +119,7 @@ msg.packstring(chr(CFalse) + chr(CFalse)) msg.packsize_t(rffi.cast(rffi.SIZE_T, CFalse)) msg.packbuf(buf, CFalse * 5, CFalse * 6) - msg.packccharp(lltype.nullptr(rffi.CCHARP.TO)) + msg.packccharp(rffi.str2charp(str(CFalse))) try: writeall_not_sandboxed(STDOUT, buf, msg.getlength()) finally: From arigo at codespeak.net Thu Aug 2 19:35:30 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 19:35:30 +0200 (CEST) Subject: [pypy-svn] r45465 - pypy/dist/pypy/translator/sandbox Message-ID: <20070802173530.CB16680EB@code0.codespeak.net> Author: arigo Date: Thu Aug 2 19:35:30 2007 New Revision: 45465 Added: pypy/dist/pypy/translator/sandbox/interact.py (contents, props changed) Modified: pypy/dist/pypy/translator/sandbox/sandlib.py Log: A wrapper tool for CPython to run a sandboxed subprocess: stdin, stdout, stderr are redirected from the parent to the subprocess, but all other external functions are forbidden. A sandboxed pyrolog-c can be run in this way. Added: pypy/dist/pypy/translator/sandbox/interact.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/sandbox/interact.py Thu Aug 2 19:35:30 2007 @@ -0,0 +1,17 @@ +#! /usr/bin/env python + +"""Interacts with a subprocess translated with --sandbox. +The subprocess is only allowed to use stdin/stdout/stderr. + +Usage: + interact.py +""" + +import sys +from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc + +if __name__ == '__main__': + if len(sys.argv) < 2: + print >> sys.stderr, __doc_ + sys.exit(2) + SimpleIOSandboxedProc(sys.argv[1:]).interact() Modified: pypy/dist/pypy/translator/sandbox/sandlib.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/sandlib.py (original) +++ pypy/dist/pypy/translator/sandbox/sandlib.py Thu Aug 2 19:35:30 2007 @@ -92,6 +92,18 @@ self._error = None return (output, error) + def interact(self, stdin=None, stdout=None, stderr=None): + """Interact with the subprocess. By default, stdin, stdout and + stderr are set to the ones from 'sys'.""" + import sys + self._input = stdin or sys.stdin + self._output = stdout or sys.stdout + self._error = stderr or sys.stderr + self.handle_forever() + self._input = None + self._output = None + self._error = None + def do_read(self, fd, size): if fd == 0: if self._input is None: From arigo at codespeak.net Thu Aug 2 19:55:09 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 19:55:09 +0200 (CEST) Subject: [pypy-svn] r45466 - pypy/dist/pypy/translator/sandbox/test Message-ID: <20070802175509.0B24480F5@code0.codespeak.net> Author: arigo Date: Thu Aug 2 19:55:09 2007 New Revision: 45466 Modified: pypy/dist/pypy/translator/sandbox/test/test_sandlib.py Log: A test just for fun: the sandboxed process calls the external function foobar(). Clearly, translating code using foobar() only works when sandboxing. Modified: pypy/dist/pypy/translator/sandbox/test/test_sandlib.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/test/test_sandlib.py (original) +++ pypy/dist/pypy/translator/sandbox/test/test_sandlib.py Thu Aug 2 19:55:09 2007 @@ -1,5 +1,6 @@ import os, StringIO from pypy.tool.sourcetools import func_with_new_name +from pypy.rpython.lltypesystem import rffi from pypy.translator.sandbox.sandlib import SandboxedProc from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc from pypy.translator.interactive import Translation @@ -26,6 +27,10 @@ do_read = _make_method("read") do_write = _make_method("write") do_close = _make_method("close") + do_foobar = _make_method("foobar") + + TYPES = SandboxedProc.TYPES.copy() + TYPES["foobar"] = "s", "i" def test_lib(): @@ -56,6 +61,22 @@ proc.handle_forever() assert proc.seen == len(proc.expected) +def test_foobar(): + foobar = rffi.llexternal("foobar", [rffi.CCHARP], rffi.LONG) + def entry_point(argv): + s = rffi.str2charp(argv[1]); n = foobar(s); rffi.free_charp(s) + s = rffi.str2charp(argv[n]); n = foobar(s); rffi.free_charp(s) + return n + t = Translation(entry_point, backend='c', standalone=True, sandbox=True) + exe = t.compile() + + proc = MySandboxedProc([exe, 'spam', 'egg'], expected = [ + ("foobar", ("spam",), 2), + ("foobar", ("egg",), 0), + ]) + proc.handle_forever() + assert proc.seen == len(proc.expected) + def test_simpleio(): def entry_point(argv): print "Please enter a number:" From arigo at codespeak.net Thu Aug 2 20:04:39 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 20:04:39 +0200 (CEST) Subject: [pypy-svn] r45467 - pypy/dist/pypy/rpython/test Message-ID: <20070802180439.1A26680F7@code0.codespeak.net> Author: arigo Date: Thu Aug 2 20:04:38 2007 New Revision: 45467 Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: Fixes Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Thu Aug 2 20:04:38 2007 @@ -216,7 +216,6 @@ assert self.ll_to_string(res) == 'hello world' def test_os_dup(self): - from pypy.rpython.module.ll_os import dup_lltypeimpl import os def fn(fd): return os.dup(fd) @@ -228,15 +227,11 @@ count = 0 for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, fn): cfptr = dir_call.args[0] - if self.type_system == 'lltype': - assert self.get_callable(cfptr.value) == dup_lltypeimpl - else: - assert self.get_callable(cfptr.value) == os.dup + assert self.get_callable(cfptr.value).__name__.startswith('dup') count += 1 assert count == 1 def test_os_open(self): - from pypy.rpython.module.ll_os import os_open_lltypeimpl, os_open_oofakeimpl tmpdir = str(udir.udir.join("os_open_test")) import os def wr_open(fname): @@ -248,10 +243,7 @@ count = 0 for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, wr_open): cfptr = dir_call.args[0] - if self.type_system == 'lltype': - assert self.get_callable(cfptr.value) == os_open_lltypeimpl - else: - assert self.get_callable(cfptr.value) == os_open_oofakeimpl + assert self.get_callable(cfptr.value).__name__.startswith('os_open') count += 1 assert count == 1 From arigo at codespeak.net Thu Aug 2 20:30:05 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 20:30:05 +0200 (CEST) Subject: [pypy-svn] r45468 - in pypy/dist/pypy: rpython rpython/module rpython/module/test translator/c translator/c/src Message-ID: <20070802183005.28A258102@code0.codespeak.net> Author: arigo Date: Thu Aug 2 20:30:03 2007 New Revision: 45468 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/test/test_ll_os.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h Log: Convert os.access(). Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Aug 2 20:30:03 2007 @@ -179,7 +179,6 @@ # external function declarations posix = __import__(os.name) -declare(os.access , int , 'll_os/access') declare(os.lseek , r_longlong , 'll_os/lseek') declare(os.isatty , bool , 'll_os/isatty') if hasattr(posix, 'ftruncate'): Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Thu Aug 2 20:30:03 2007 @@ -13,8 +13,8 @@ from pypy.tool.staticmethods import ClassMethods import stat from pypy.rpython.extfunc import BaseLazyRegistering, registering -from pypy.annotation.model import SomeString, SomeInteger, s_ImpossibleValue, \ - s_None +from pypy.annotation.model import SomeString, SomeInteger +from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool from pypy.rpython.lltypesystem import rffi from pypy.rpython.lltypesystem.rffi import platform from pypy.rpython.lltypesystem import lltype @@ -296,6 +296,26 @@ self.register(os.close, [int], s_None, llimpl=close_lltypeimpl, export_name="ll_os.ll_os_close", oofakeimpl=os.close) + @registering(os.access) + def register_os_access(self): + os_access = rffi.llexternal('access', + [rffi.CCHARP, rffi.INT], + rffi.INT) + + def access_lltypeimpl(path, mode): + path = rffi.str2charp(path) + mode = rffi.cast(rffi.INT, mode) + error = rffi.cast(lltype.Signed, os_access(path, mode)) + rffi.free_charp(path) + return error == 0 + + def os_access_oofakeimpl(path, mode): + return os.access(OOSupport.from_rstr(path), mode) + + self.register(os.access, [str, int], s_Bool, llimpl=access_lltypeimpl, + export_name="ll_os.ll_os_access", + oofakeimpl=os_access_oofakeimpl) + # ------------------------------- os.W* --------------------------------- w_star = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED', @@ -354,10 +374,6 @@ return cls.to_rstr(os.getcwd()) ll_os_getcwd.suggested_primitive = True - def ll_os_access(cls, path, mode): - return os.access(cls.from_rstr(path), mode) - ll_os_access.suggested_primitive = True - def ll_os_lseek(cls, fd,pos,how): return r_longlong(os.lseek(fd,pos,how)) ll_os_lseek.suggested_primitive = True Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_os.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_os.py Thu Aug 2 20:30:03 2007 @@ -3,19 +3,22 @@ from pypy.tool.pytest.modcheck import skipimporterror from pypy.translator.c.test.test_genc import compile +from pypy.rpython import extregistry from pypy.rpython.lltypesystem.module.ll_os import Implementation as impl import sys import py +def getllimpl(fn): + return extregistry.lookup(fn).lltypeimpl + def test_access(): filename = str(udir.join('test_access.txt')) - rsfilename = impl.to_rstr(filename) - fd = file(filename, 'w') fd.close() for mode in os.R_OK, os.W_OK, os.X_OK, os.R_OK | os.W_OK | os.X_OK: - assert os.access(filename, mode) == impl.ll_os_access(rsfilename, mode) + result = getllimpl(os.access)(filename, mode) + assert result == os.access(filename, mode) def test_getcwd(): Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Thu Aug 2 20:30:03 2007 @@ -23,7 +23,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_access.im_func: 'LL_os_access', impl.ll_os_stat.im_func: 'LL_os_stat', impl.ll_os_fstat.im_func: 'LL_os_fstat', impl.ll_os_lstat.im_func: 'LL_os_lstat', Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Thu Aug 2 20:30:03 2007 @@ -51,7 +51,6 @@ /* prototypes */ -int LL_os_access(RPyString *filename, int mode); RPySTAT_RESULT* _stat_construct_result_helper(STRUCT_STAT st); RPySTAT_RESULT* LL_os_stat(RPyString * fname); RPySTAT_RESULT* LL_os_lstat(RPyString * fname); @@ -99,11 +98,6 @@ #include "ll_osdefs.h" -int LL_os_access(RPyString *filename, int mode) { - int n = access(RPyString_AsString(filename), mode); - return (n == 0); -} - #ifdef LL_NEED_OS_STAT RPySTAT_RESULT* _stat_construct_result_helper(STRUCT_STAT st) { From arigo at codespeak.net Thu Aug 2 20:36:39 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Aug 2007 20:36:39 +0200 (CEST) Subject: [pypy-svn] r45469 - in pypy/dist/pypy: rpython rpython/module translator/c translator/c/src Message-ID: <20070802183639.619888103@code0.codespeak.net> Author: arigo Date: Thu Aug 2 20:36:38 2007 New Revision: 45469 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h Log: os.getpid()... Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Aug 2 20:36:38 2007 @@ -202,8 +202,6 @@ declare(os._exit , noneannotation, 'll_os/_exit') if hasattr(os, 'kill'): declare(os.kill , noneannotation, 'll_os/kill') -if hasattr(os, 'getpid'): - declare(os.getpid , int, 'll_os/getpid') if hasattr(os, 'link'): declare(os.link , noneannotation, 'll_os/link') if hasattr(os, 'symlink'): Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Thu Aug 2 20:36:38 2007 @@ -20,8 +20,10 @@ from pypy.rpython.lltypesystem import lltype class RegisterOs(BaseLazyRegistering): + UNISTD_INCL = ['unistd.h', 'sys/types.h'] + def __init__(self): - self.getuid_incl = ['unistd.h', 'sys/types.h'] + pass # XXX fijal: why do I need this? # a simple, yet usefull factory def register_os_function_returning_int(self, fun, name, **kwds): @@ -177,12 +179,18 @@ @registering(os.getuid) def register_os_getuid(self): self.register_os_function_returning_int(os.getuid, 'getuid', - includes=self.getuid_incl) + includes=self.UNISTD_INCL) @registering(os.geteuid) def register_os_geteuid(self): self.register_os_function_returning_int(os.geteuid, 'geteuid', - includes=self.getuid_incl) + includes=self.UNISTD_INCL) + + if hasattr(os, 'getpid'): + @registering(os.getpid) + def register_os_getpid(self): + self.register_os_function_returning_int(os.getpid, 'getpid', + includes=self.UNISTD_INCL) @registering(os.open) def register_os_open(self): @@ -462,10 +470,6 @@ return os.umask(mask) ll_os_umask.suggested_primitive = True - def ll_os_getpid(cls): - return os.getpid() - ll_os_getpid.suggested_primitive = True - def ll_os_kill(cls, pid, sig): os.kill(pid, sig) ll_os_kill.suggested_primitive = True Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Thu Aug 2 20:36:38 2007 @@ -46,7 +46,6 @@ impl.ll_os_chmod.im_func: 'LL_os_chmod', impl.ll_os_rename.im_func: 'LL_os_rename', impl.ll_os_umask.im_func: 'LL_os_umask', - impl.ll_os_getpid.im_func: 'LL_os_getpid', impl.ll_os_kill.im_func: 'LL_os_kill', impl.ll_os_link.im_func: 'LL_os_link', impl.ll_os_symlink.im_func: 'LL_os_symlink', Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Thu Aug 2 20:36:38 2007 @@ -68,7 +68,6 @@ void LL_os_chmod(RPyString * path, int mode); void LL_os_rename(RPyString * path1, RPyString * path2); int LL_os_umask(int mode); -long LL_os_getpid(void); void LL_os_kill(int pid, int sig); void LL_os_link(RPyString * path1, RPyString * path2); void LL_os_symlink(RPyString * path1, RPyString * path2); @@ -293,10 +292,6 @@ return umask(mode); } -long LL_os_getpid(void) { - return getpid(); -} - #ifdef HAVE_KILL void LL_os_kill(int pid, int sig) { int error = kill(pid, sig); From arigo at codespeak.net Fri Aug 3 09:50:53 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 3 Aug 2007 09:50:53 +0200 (CEST) Subject: [pypy-svn] r45471 - in pypy/dist/pypy: rpython rpython/module rpython/module/test translator/c translator/c/src Message-ID: <20070803075053.4DF8E80EE@code0.codespeak.net> Author: arigo Date: Fri Aug 3 09:50:51 2007 New Revision: 45471 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/test/test_ll_os.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h Log: os.getcwd()... Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Fri Aug 3 09:50:51 2007 @@ -189,7 +189,6 @@ declare(os.system , int , 'll_os/system') declare(os.strerror , str , 'll_os/strerror') declare(os.unlink , noneannotation, 'll_os/unlink') -declare(os.getcwd , str , 'll_os/getcwd') declare(os.chdir , noneannotation, 'll_os/chdir') declare(os.mkdir , noneannotation, 'll_os/mkdir') declare(os.rmdir , noneannotation, 'll_os/rmdir') Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Fri Aug 3 09:50:51 2007 @@ -324,6 +324,55 @@ export_name="ll_os.ll_os_access", oofakeimpl=os_access_oofakeimpl) + @registering(os.getcwd) + def register_os_getcwd(self): + os_getcwd = rffi.llexternal('getcwd', + [rffi.CCHARP, rffi.SIZE_T], + rffi.CCHARP) + + def os_getcwd_lltypeimpl(): + bufsize = 256 + while True: + buf = lltype.malloc(rffi.CCHARP.TO, bufsize, flavor='raw') + res = os_getcwd(buf, rffi.cast(rffi.SIZE_T, bufsize)) + if res: + break # ok + error = rffi.c_errno + lltype.free(buf, flavor='raw') + if error != errno.ERANGE: + raise OSError(error, "getcwd failed") + # else try again with a larger buffer, up to some sane limit + bufsize *= 4 + if bufsize > 1024*1024: # xxx hard-coded upper limit + raise OSError(error, "getcwd result too large") + result = rffi.charp2str(res) + lltype.free(buf, flavor='raw') + return result + + def os_getcwd_oofakeimpl(): + return OOSupport.to_rstr(os.getcwd()) + + self.register(os.getcwd, [], SomeString(), + "ll_os.ll_os_getcwd", llimpl=os_getcwd_lltypeimpl, + oofakeimpl=os_getcwd_oofakeimpl) + + # '--sandbox' support + def os_getcwd_marshal_input(msg, buf, bufsize): + msg.packsize_t(bufsize) + def os_getcwd_unmarshal_output(msg, buf, bufsize): + # the outside process should not send a result larger than + # the requested 'bufsize' + result = msg.nextstring() + n = len(result) + if rffi.cast(rffi.SIZE_T, n) >= bufsize: + raise OverflowError + for i in range(n): + buf[i] = result[i] + buf[n] = '\x00' + return buf + os_getcwd._obj._marshal_input = os_getcwd_marshal_input + os_getcwd._obj._unmarshal_output = os_getcwd_unmarshal_output + # ------------------------------- os.W* --------------------------------- w_star = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED', @@ -378,10 +427,6 @@ class BaseOS: __metaclass__ = ClassMethods - def ll_os_getcwd(cls): - return cls.to_rstr(os.getcwd()) - ll_os_getcwd.suggested_primitive = True - def ll_os_lseek(cls, fd,pos,how): return r_longlong(os.lseek(fd,pos,how)) ll_os_lseek.suggested_primitive = True Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_os.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_os.py Fri Aug 3 09:50:51 2007 @@ -22,8 +22,8 @@ def test_getcwd(): - data = impl.ll_os_getcwd() - assert impl.from_rstr(data) == os.getcwd() + data = getllimpl(os.getcwd)() + assert data == os.getcwd() def test_strerror(): data = impl.ll_os_strerror(2) Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Fri Aug 3 09:50:51 2007 @@ -32,7 +32,6 @@ impl.ll_os_strerror.im_func: 'LL_os_strerror', impl.ll_os_system.im_func: 'LL_os_system', impl.ll_os_unlink.im_func: 'LL_os_unlink', - impl.ll_os_getcwd.im_func: 'LL_os_getcwd', impl.ll_os_chdir.im_func: 'LL_os_chdir', impl.ll_os_mkdir.im_func: 'LL_os_mkdir', impl.ll_os_rmdir.im_func: 'LL_os_rmdir', Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Fri Aug 3 09:50:51 2007 @@ -61,7 +61,6 @@ RPyString *LL_os_strerror(int errnum); long LL_os_system(RPyString * fname); void LL_os_unlink(RPyString * fname); -RPyString *LL_os_getcwd(void); void LL_os_chdir(RPyString * path); void LL_os_mkdir(RPyString * path, int mode); void LL_os_rmdir(RPyString * path); @@ -237,17 +236,6 @@ } } -RPyString *LL_os_getcwd(void) { - char buf[PATH_MAX]; - char *res; - res = getcwd(buf, sizeof buf); - if (res == NULL) { - RPYTHON_RAISE_OSERROR(errno); - return NULL; - } - return RPyString_FromString(buf); -} - void LL_os_chdir(RPyString * path) { int error = chdir(RPyString_AsString(path)); if (error != 0) { From arigo at codespeak.net Fri Aug 3 15:12:58 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 3 Aug 2007 15:12:58 +0200 (CEST) Subject: [pypy-svn] r45473 - pypy/dist/pypy/rpython Message-ID: <20070803131258.5DB938106@code0.codespeak.net> Author: arigo Date: Fri Aug 3 15:12:57 2007 New Revision: 45473 Modified: pypy/dist/pypy/rpython/extfunc.py Log: A case where an exception can obscurely mask a previous problem. Modified: pypy/dist/pypy/rpython/extfunc.py ============================================================================== --- pypy/dist/pypy/rpython/extfunc.py (original) +++ pypy/dist/pypy/rpython/extfunc.py Fri Aug 3 15:12:57 2007 @@ -1,3 +1,4 @@ +from pypy.rpython import extregistry from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.lltypesystem.lltype import typeOf from pypy.objspace.flow.model import Constant @@ -20,6 +21,12 @@ except: exc, exc_inst, tb = sys.exc_info() for func in funcs: + # if the function has already been registered and we got + # an exception afterwards, the ExtRaisingEntry would create + # a double-registration and crash in an AssertionError that + # masks the original problem. In this case, just re-raise now. + if extregistry.lookup(func): + raise exc, exc_inst, tb class ExtRaisingEntry(ExtRegistryEntry): _about_ = func def compute_result_annotation(self, *args_s): From arigo at codespeak.net Fri Aug 3 15:14:17 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 3 Aug 2007 15:14:17 +0200 (CEST) Subject: [pypy-svn] r45474 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20070803131417.208ED8106@code0.codespeak.net> Author: arigo Date: Fri Aug 3 15:14:16 2007 New Revision: 45474 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: More laziness in invoking ll2ctypes. Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Fri Aug 3 15:14:16 2007 @@ -141,7 +141,7 @@ elif isinstance(T, lltype.OpaqueType): if T.hints.get('external', None) != 'C': raise TypeError("%s is not external" % T) - cls = ctypes.c_char * T.hints['size'] + cls = ctypes.c_char * T.hints['getsize']() else: _setup_ctypes_cache() if T in _ctypes_cache: @@ -338,7 +338,7 @@ convert_array(container) elif isinstance(T.TO, lltype.OpaqueType): container._storage = ctypes.create_string_buffer( - T.TO.hints['size']) + T.TO.hints['getsize']()) else: raise NotImplementedError(T) storage = container._storage @@ -466,18 +466,23 @@ return cfunc def make_callable_via_ctypes(funcptr, cfunc=None): - try: - if cfunc is None: - cfunc = get_ctypes_callable(funcptr) - except NotImplementedError, e: - def invoke_via_ctypes(*argvalues): - raise NotImplementedError, e + RESULT = lltype.typeOf(funcptr).TO.RESULT + if cfunc is None: + cfunc1 = [] else: - RESULT = lltype.typeOf(funcptr).TO.RESULT - def invoke_via_ctypes(*argvalues): - cargs = [lltype2ctypes(value) for value in argvalues] - cres = cfunc(*cargs) - return ctypes2lltype(RESULT, cres) + cfunc1 = [cfunc] + + def invoke_via_ctypes(*argvalues): + if cfunc1: + cfunc = cfunc1[0] + else: + # lazily build the corresponding ctypes function object + cfunc = get_ctypes_callable(funcptr) + cfunc1.append(cfunc) # cache + # perform the call + cargs = [lltype2ctypes(value) for value in argvalues] + cres = cfunc(*cargs) + return ctypes2lltype(RESULT, cres) funcptr._obj._callable = invoke_via_ctypes def force_cast(RESTYPE, value): Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Fri Aug 3 15:14:16 2007 @@ -100,7 +100,12 @@ hints = hints.copy() hints['external'] = 'C' hints['c_name'] = name - hints['size'] = platform.sizeof(name, **kwds) + def lazy_getsize(result=[]): + if not result: + size = platform.sizeof(name, **kwds) + result.append(size) + return result[0] + hints['getsize'] = lazy_getsize return lltype.Ptr(lltype.OpaqueType(name, hints)) c_errno = CConstant('errno', lltype.Signed) From arigo at codespeak.net Fri Aug 3 15:15:41 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 3 Aug 2007 15:15:41 +0200 (CEST) Subject: [pypy-svn] r45475 - in pypy/dist/pypy: rpython/module translator/c/test Message-ID: <20070803131541.15D7980E6@code0.codespeak.net> Author: arigo Date: Fri Aug 3 15:15:41 2007 New Revision: 45475 Modified: pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/translator/c/test/test_extfunc.py Log: RPython support for os.listdir(). In-progress; the previous ros.opendir/readdir/closedir interface is still there but the idea is to get rid of it. Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Fri Aug 3 15:15:41 2007 @@ -5,7 +5,7 @@ # Implementation details about those functions # might be found in doc/rffi.txt -import os, errno +import os, sys, errno from pypy.rpython.module.support import ll_strcpy, _ll_strfill, OOSupport from pypy.rpython.module.support import to_opaque_object, from_opaque_object from pypy.rlib import ros @@ -15,6 +15,7 @@ from pypy.rpython.extfunc import BaseLazyRegistering, registering from pypy.annotation.model import SomeString, SomeInteger from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool +from pypy.annotation.listdef import s_list_of_strings from pypy.rpython.lltypesystem import rffi from pypy.rpython.lltypesystem.rffi import platform from pypy.rpython.lltypesystem import lltype @@ -373,6 +374,51 @@ os_getcwd._obj._marshal_input = os_getcwd_marshal_input os_getcwd._obj._unmarshal_output = os_getcwd_unmarshal_output + @registering(os.listdir) + def register_os_listdir(self): + # we need a different approach on Windows and on Posix + if sys.platform.startswith('win'): + XXX # FindFirstFile, FindNextFile + else: + INCL = ['sys/types.h', 'dirent.h'] + DIRP = rffi.COpaque('DIR', includes=INCL) + NAME_MAX = platform.intdefined('NAME_MAX', includes=INCL) + DIRENTP = rffi.CStruct('dirent', + ('d_name', lltype.FixedSizeArray(lltype.Char, NAME_MAX+1)), + ) + # XXX so far, DIRENTP cannot be handled by ll2ctypes because + # it contains other fields before 'd_name', at least on Linux + os_opendir = rffi.llexternal('opendir', [rffi.CCHARP], DIRP, + includes = INCL) + os_readdir = rffi.llexternal('readdir', [DIRP], DIRENTP, + includes = INCL) + os_closedir = rffi.llexternal('closedir', [DIRP], rffi.INT, + includes = INCL) + + def os_listdir_lltypeimpl(path): + path = rffi.str2charp(path) + dirp = os_opendir(path) + rffi.free_charp(path) + if not dirp: + raise OSError(rffi.c_errno, "os_opendir failed") + result = [] + while True: + direntp = os_readdir(dirp) + if not direntp: + error = rffi.c_errno + break + name = rffi.charp2str(direntp.c_d_name) + if name != '.' and name != '..': + result.append(name) + os_closedir(dirp) + if error: + raise OSError(error, "os_readdir failed") + return result + + self.register(os.listdir, [str], s_list_of_strings, + "ll_os.ll_os_listdir", + llimpl=os_listdir_lltypeimpl) + # ------------------------------- os.W* --------------------------------- w_star = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED', Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Fri Aug 3 15:15:41 2007 @@ -703,6 +703,18 @@ compared_with.sort() assert result == compared_with +def test_listdir(): + def mylistdir(s): + result = os.listdir(s) + return '/'.join(result) + func = compile(mylistdir, [str]) + result = func(str(udir)) + result = result.split('/') + result.sort() + compared_with = os.listdir(str(udir)) + compared_with.sort() + assert result == compared_with + if hasattr(posix, 'execv'): def test_execv(): filename = str(udir.join('test_execv.txt')) From jlg at codespeak.net Fri Aug 3 15:54:37 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 3 Aug 2007 15:54:37 +0200 (CEST) Subject: [pypy-svn] r45476 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070803135437.999078105@code0.codespeak.net> Author: jlg Date: Fri Aug 3 15:54:36 2007 New Revision: 45476 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: nested macros; but no support for (obj ... ...) Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Fri Aug 3 15:54:36 2007 @@ -336,9 +336,8 @@ return self.eval_body(local_ctx, self.body) -def plst2lst(plst): +def plst2lst(plst, w_cdr=w_nil): """coverts python list() of W_Root into W_Pair scheme list""" - w_cdr = w_nil plst.reverse() for w_obj in plst: w_cdr = W_Pair(w_obj, w_cdr) @@ -865,10 +864,16 @@ def __init__(self, mdict_lst): self.mdict_lst = mdict_lst + def __repr__(self): + return "#" + class EllipsisException(SchemeException): def __init__(self, length): self.length = length +class EllipsisTemplate(SchemeException): + pass + class EllipsisPattern(SchemeException): pass @@ -895,7 +900,6 @@ w_pattcar = w_patt.car if isinstance(w_expr, W_Pair): mdict_car = self.matchr(ctx, w_pattcar, w_expr.car) - try: #we catch EllipsisPattern here because in car # we dont know how to deal with it @@ -915,6 +919,8 @@ for name in mdict_lst[0].keys(): mdict_cdr[name] = ellipsis + return mdict_cdr + mdict_car.update(mdict_cdr) return mdict_car @@ -1008,6 +1014,97 @@ return self.substitute(ctx, template, match_dict) def substitute(self, ctx, sexpr, match_dict, ellipsis_cnt=-1): + #return self.substitute_(ctx, sexpr, match_dict, -1) + return self.substituter(ctx, sexpr, match_dict) + + def find_elli(self, expr, mdict): + if isinstance(expr, W_Pair): + edict_car = self.find_elli(expr.car, mdict) + edict_cdr = self.find_elli(expr.cdr, mdict) + edict_car.update(edict_cdr) + return edict_car + + if isinstance(expr, W_Symbol): + val = mdict.get(expr.name, None) + if val is None: + return {} + + if isinstance(val, Ellipsis): + return {expr.name: val} + + return {} + + def substituter(self, ctx, sexpr, match_dict): + if isinstance(sexpr, W_Pair): + w_car = self.substituter(ctx, sexpr.car, match_dict) + try: + w_cdr = self.substituter(ctx, sexpr.cdr, match_dict) + except EllipsisTemplate: + print "ellipsis expand", sexpr + try: + w_cdr = self.substituter(ctx, sexpr.cdr.cdr, match_dict) + except EllipsisTemplate: + raise NotImplementedError + + plst = [] + mdict_elli = self.find_elli(sexpr.car, match_dict) + elli_len = 0 + for (key, val) in mdict_elli.items(): + elli_len = len(val.mdict_lst) + + for i in range(elli_len): + new_mdict = match_dict.copy() + for (key, val) in mdict_elli.items(): + yyy = val.mdict_lst[i][key] + new_mdict[key] = yyy + + print new_mdict + zzz = self.substituter(ctx, sexpr.car, new_mdict) + plst.append(zzz) + + w_lst = plst2lst(plst, w_cdr) + return w_lst + + w_pair = W_Pair(w_car, w_cdr) + if isinstance(w_car, W_Symbol): + #XXX what if we have here SymbolClosure? + # can happen when recursive macro + try: + w_macro = ctx.get(w_car.name) + # recursive macro expansion + if isinstance(w_macro, W_DerivedMacro): + return w_macro.expand(ctx, w_pair) + except UnboundVariable: + pass + + return w_pair + + if isinstance(sexpr, W_Symbol): + if sexpr is w_ellipsis: + raise EllipsisTemplate + + w_sub = match_dict.get(sexpr.name, None) + if w_sub is not None: + # Hygenic macros close their input forms in the syntactic + # enviroment at the point of use + + if isinstance(w_sub, Ellipsis): + return w_sub + + #not always needed, because w_sub can have no W_Symbol inside + if isinstance(w_sub, W_Symbol) and \ + not isinstance(w_sub, SymbolClosure): + return SymbolClosure(ctx, w_sub) + + if isinstance(w_sub, W_Pair) and \ + not isinstance(w_sub, PairClosure): + return PairClosure(ctx, w_sub) + + return w_sub + + return sexpr + + def substitute_(self, ctx, sexpr, match_dict, ellipsis_cnt=-1): if isinstance(sexpr, W_Symbol): w_sub = match_dict.get(sexpr.name, None) if w_sub is not None: @@ -1039,14 +1136,14 @@ elif isinstance(sexpr, W_Pair): try: w_pair = W_Pair( - self.substitute(ctx, sexpr.car, match_dict, ellipsis_cnt), - self.substitute(ctx, sexpr.cdr, match_dict, ellipsis_cnt)) + self.substitute_(ctx, sexpr.car, match_dict, ellipsis_cnt), + self.substitute_(ctx, sexpr.cdr, match_dict, ellipsis_cnt)) except EllipsisException, e: scdr = sexpr.cdr if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis: plst = [] for i in range(e.length): - zzz = self.substitute(ctx, sexpr.car, match_dict, i) + zzz = self.substitute_(ctx, sexpr.car, match_dict, i) plst.append(zzz) ellipsis = plst2lst(plst) Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Fri Aug 3 15:54:36 2007 @@ -325,12 +325,12 @@ (syntax-rules () ((_ sym ...) (begin - (if sym (set! sym 0)) ...))))""") + (if sym (set! sym 0)) ... #t))))""") eval_(ctx, "(define x #t)") eval_(ctx, "(define y #f)") eval_(ctx, "(define z #t)") - eval_(ctx, "(zero-if-true x y z)") + assert eval_(ctx, "(zero-if-true x y z)").to_boolean() == True assert eval_(ctx, "x").to_number() == 0 assert eval_(ctx, "y").to_boolean() is False assert eval_(ctx, "z").to_number() == 0 @@ -388,6 +388,18 @@ assert eval_(ctx, "(let2 (x y z) (1 2 3) (+ x y z))").to_number() == 6 def test_nested_ellipsis(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax quote-lists + (syntax-rules () + ((_ (obj ...) ...) + (quote ((obj ...) ... end)))))""") + + assert eval_(ctx, """(quote-lists (x y) + (1 2 3 4) + (+))""").to_string() == \ + "((x y) (1 2 3 4) (+) end)" + +def test_nested_ellipsis2(): py.test.skip("in progress") ctx = ExecutionContext() eval_(ctx, """(define-syntax quote-append From jlg at codespeak.net Fri Aug 3 15:56:18 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 3 Aug 2007 15:56:18 +0200 (CEST) Subject: [pypy-svn] r45477 - pypy/dist/pypy/lang/scheme Message-ID: <20070803135618.8E5288105@code0.codespeak.net> Author: jlg Date: Fri Aug 3 15:56:18 2007 New Revision: 45477 Modified: pypy/dist/pypy/lang/scheme/object.py Log: old substitute_/substitute removed Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Fri Aug 3 15:56:18 2007 @@ -1013,10 +1013,6 @@ return self.substitute(ctx, template, match_dict) - def substitute(self, ctx, sexpr, match_dict, ellipsis_cnt=-1): - #return self.substitute_(ctx, sexpr, match_dict, -1) - return self.substituter(ctx, sexpr, match_dict) - def find_elli(self, expr, mdict): if isinstance(expr, W_Pair): edict_car = self.find_elli(expr.car, mdict) @@ -1104,70 +1100,8 @@ return sexpr - def substitute_(self, ctx, sexpr, match_dict, ellipsis_cnt=-1): - if isinstance(sexpr, W_Symbol): - w_sub = match_dict.get(sexpr.name, None) - if w_sub is not None: - # Hygenic macros close their input forms in the syntactic - # enviroment at the point of use - - if isinstance(w_sub, Ellipsis): - if ellipsis_cnt < 0: - raise EllipsisException(len(w_sub.mdict_lst)) - else: - mdict = w_sub.mdict_lst[ellipsis_cnt] - w_sub = mdict[sexpr.name] - #for nested ellipsis we should probably raise - # here if w_sub is still Ellipsis - - #not always needed, because w_sub can have no W_Symbol inside - if isinstance(w_sub, W_Symbol) and \ - not isinstance(w_sub, SymbolClosure): - return SymbolClosure(ctx, w_sub) + substitute = substituter - if isinstance(w_sub, W_Pair) and \ - not isinstance(w_sub, PairClosure): - return PairClosure(ctx, w_sub) - - return w_sub - - return sexpr - - elif isinstance(sexpr, W_Pair): - try: - w_pair = W_Pair( - self.substitute_(ctx, sexpr.car, match_dict, ellipsis_cnt), - self.substitute_(ctx, sexpr.cdr, match_dict, ellipsis_cnt)) - except EllipsisException, e: - scdr = sexpr.cdr - if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis: - plst = [] - for i in range(e.length): - zzz = self.substitute_(ctx, sexpr.car, match_dict, i) - plst.append(zzz) - - ellipsis = plst2lst(plst) - return ellipsis - else: - raise e - - w_paircar = w_pair.car - if isinstance(w_paircar, W_Symbol): - #XXX what if we have here SymbolClosure? - # can happen when recursive macro - try: - w_macro = ctx.get(w_paircar.name) - - # recursive macro expansion - if isinstance(w_macro, W_DerivedMacro): - return w_macro.expand(ctx, w_pair) - except UnboundVariable: - pass - - return w_pair - - return sexpr - def expand_eval(self, ctx, sexpr): #we have lexical scopes: # 1. macro was defined - self.closure From jlg at codespeak.net Fri Aug 3 16:52:29 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 3 Aug 2007 16:52:29 +0200 (CEST) Subject: [pypy-svn] r45478 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070803145229.9AF0C80E9@code0.codespeak.net> Author: jlg Date: Fri Aug 3 16:52:29 2007 New Revision: 45478 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: dirty code to handle with (obj ... ...) like ellipses Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Fri Aug 3 16:52:29 2007 @@ -1030,7 +1030,21 @@ return {} - def substituter(self, ctx, sexpr, match_dict): + def plst_append(self, plst): + first_cons = plst[0] + + last_cons = None + for lst in plst: + if last_cons is not None: + last_cons.cdr = lst + + while isinstance(lst, W_Pair): + last_cons = lst + lst = lst.cdr + + return first_cons + + def substituter(self, ctx, sexpr, match_dict, flatten=False): if isinstance(sexpr, W_Pair): w_car = self.substituter(ctx, sexpr.car, match_dict) try: @@ -1040,7 +1054,9 @@ try: w_cdr = self.substituter(ctx, sexpr.cdr.cdr, match_dict) except EllipsisTemplate: - raise NotImplementedError + w_inner = W_Pair(sexpr.car, W_Pair(sexpr.cdr.car, w_nil)) + w_outer = W_Pair(w_inner, sexpr.cdr.cdr) + return self.substituter(ctx, w_outer, match_dict, True) plst = [] mdict_elli = self.find_elli(sexpr.car, match_dict) @@ -1051,20 +1067,21 @@ for i in range(elli_len): new_mdict = match_dict.copy() for (key, val) in mdict_elli.items(): - yyy = val.mdict_lst[i][key] - new_mdict[key] = yyy + new_mdict[key] = val.mdict_lst[i][key] + + sub = self.substituter(ctx, sexpr.car, new_mdict) + plst.append(sub) + + if flatten: + w_lst = self.plst_append(plst) - print new_mdict - zzz = self.substituter(ctx, sexpr.car, new_mdict) - plst.append(zzz) + else: + w_lst = plst2lst(plst, w_cdr) - w_lst = plst2lst(plst, w_cdr) return w_lst w_pair = W_Pair(w_car, w_cdr) if isinstance(w_car, W_Symbol): - #XXX what if we have here SymbolClosure? - # can happen when recursive macro try: w_macro = ctx.get(w_car.name) # recursive macro expansion Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Fri Aug 3 16:52:29 2007 @@ -400,7 +400,7 @@ "((x y) (1 2 3 4) (+) end)" def test_nested_ellipsis2(): - py.test.skip("in progress") + #py.test.skip("in progress") ctx = ExecutionContext() eval_(ctx, """(define-syntax quote-append (syntax-rules () From jlg at codespeak.net Fri Aug 3 17:11:39 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 3 Aug 2007 17:11:39 +0200 (CEST) Subject: [pypy-svn] r45479 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070803151139.220248105@code0.codespeak.net> Author: jlg Date: Fri Aug 3 17:11:38 2007 New Revision: 45479 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: rest is not ingored anymore; comments added Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Fri Aug 3 17:11:38 2007 @@ -1030,7 +1030,7 @@ return {} - def plst_append(self, plst): + def plst_append(self, plst, w_cdr=None): first_cons = plst[0] last_cons = None @@ -1042,6 +1042,9 @@ last_cons = lst lst = lst.cdr + if w_cdr is not None: + last_cons.cdr = w_cdr + return first_cons def substituter(self, ctx, sexpr, match_dict, flatten=False): @@ -1052,19 +1055,28 @@ except EllipsisTemplate: print "ellipsis expand", sexpr try: + #we can still have something behind ellipsis w_cdr = self.substituter(ctx, sexpr.cdr.cdr, match_dict) except EllipsisTemplate: + #it can also be ellipsis + # lets pretend its usual <(obj ...) ...> + # instead of + # we will *flatten* the result later w_inner = W_Pair(sexpr.car, W_Pair(sexpr.cdr.car, w_nil)) w_outer = W_Pair(w_inner, sexpr.cdr.cdr) return self.substituter(ctx, w_outer, match_dict, True) plst = [] + #find_elli gets part of match_dict relevant to sexpr.car mdict_elli = self.find_elli(sexpr.car, match_dict) elli_len = 0 for (key, val) in mdict_elli.items(): + assert elli_len == 0 or elli_len == len(val.mdict_lst) elli_len = len(val.mdict_lst) + #generate elli_len substitutions for ellipsis for i in range(elli_len): + #one level of ellipsis nesting lower new_mdict = match_dict.copy() for (key, val) in mdict_elli.items(): new_mdict[key] = val.mdict_lst[i][key] @@ -1073,7 +1085,9 @@ plst.append(sub) if flatten: - w_lst = self.plst_append(plst) + #we have to flatten these list, it means append them + # together, and remember about w_cdr + w_lst = self.plst_append(plst, w_cdr) else: w_lst = plst2lst(plst, w_cdr) Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Fri Aug 3 17:11:38 2007 @@ -405,10 +405,10 @@ eval_(ctx, """(define-syntax quote-append (syntax-rules () ((_ (obj ...) ...) - (quote (obj ... ...)))))""") + (quote (obj ... ... end)))))""") assert eval_(ctx, """(quote-append (x y) (1 2 3 4) (+))""").to_string() == \ - "(x y 1 2 3 4 +)" + "(x y 1 2 3 4 + end)" From arigo at codespeak.net Fri Aug 3 20:09:39 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 3 Aug 2007 20:09:39 +0200 (CEST) Subject: [pypy-svn] r45480 - pypy/dist/pypy/lang/scheme/test Message-ID: <20070803180939.5DDCD80F7@code0.codespeak.net> Author: arigo Date: Fri Aug 3 20:09:37 2007 New Revision: 45480 Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py Log: Review the macro test cases. Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Fri Aug 3 20:09:37 2007 @@ -78,6 +78,20 @@ py.test.raises(MatchError, w_transformer.match, closure, w_expr) # the same binding for => in ctx and closure + # XXX + # I think this should also raise MatchError. When R5RS says + # "same binding" it probably means bound to the same *location*, not + # just that there is the same object in both locations; something like + # this: (let ((x 42) (y 42)) + # (let-syntax ((foo (syntax-rules (x y) + # ((foo x) 123) + # ((foo y) 456) + # ((foo whatever) 789)))) + # (foo y))) + # ---> 456 + # but if we change the last line: + # (let ((y 42)) (foo y)))) + # ---> 789 ctx.put("=>", w_42) assert ctx.get("=>") is closure.get("=>") w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") @@ -133,6 +147,7 @@ w_expr = parse_("(_ temp)") w_expanded = w_transformer.expand(ctx, w_expr) assert w_expanded.to_string() == "(let ((temp 1)) (+ temp temp))" + # the two occurrences of 'temp in (+ temp temp) are not the same symbol! assert w_transformer.expand_eval(ctx, w_expr).to_number() == 13 #define in closure, should not affect macro eval @@ -190,6 +205,8 @@ assert w_transformer.expand_eval(ctx, w_expr).to_number() == 5 def test_transformer_eval(): + # test direct manipulation of syntax-rules objects: + # that's an extension to the R5RS ctx = ExecutionContext() eval_(ctx, """(define foo (syntax-rules () ((_) #t) @@ -249,6 +266,16 @@ w_expr = parse_("(bar 42)") #should expand directly (recursively) to 42 assert ctx.get("bar").expand(ctx, w_expr).to_string() == "42" + # XXX no, I believe it should not expand recursively... + # here is another example which returns (foo) in MIT-Scheme where + # we get 42 so far: + py.test.skip("XXX in-progress (or wrong test?)") + ctx = ExecutionContext() + eval_(ctx, """(define-syntax foo (syntax-rules () + ((foo) #t)))""") + eval_(ctx, """(define-syntax bar (syntax-rules () + ((bar) (quote (foo)))))""") + assert eval_(ctx, "(bar)").to_string() == "(foo)" def test_let_syntax(): ctx = ExecutionContext() @@ -412,3 +439,14 @@ (+))""").to_string() == \ "(x y 1 2 3 4 + end)" +def test_cornercase1(): + py.test.skip("in-progress") + w_result = eval_noctx("""(let-syntax ((foo (syntax-rules () + ((bar) 'bar)))) + (foo)) + """) + assert w_result.to_string() == 'bar' + # I think that the correct answer is 'bar, according to + # the R5RS, because it says that the keyword bar in the syntax rule + # pattern should be ignored during matching and not be a pattern + # variable. But MIT-Scheme disagrees with me... From arigo at codespeak.net Fri Aug 3 20:23:49 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 3 Aug 2007 20:23:49 +0200 (CEST) Subject: [pypy-svn] r45481 - pypy/dist/pypy/lang/scheme/test Message-ID: <20070803182349.8779E80F8@code0.codespeak.net> Author: arigo Date: Fri Aug 3 20:23:48 2007 New Revision: 45481 Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py Log: Hygienic macro tests from http://sisc-scheme.org/r5rs_pitfall.scm. One of them fails. Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Fri Aug 3 20:23:48 2007 @@ -440,7 +440,7 @@ "(x y 1 2 3 4 + end)" def test_cornercase1(): - py.test.skip("in-progress") + py.test.skip("currently crashes") w_result = eval_noctx("""(let-syntax ((foo (syntax-rules () ((bar) 'bar)))) (foo)) @@ -450,3 +450,38 @@ # the R5RS, because it says that the keyword bar in the syntax rule # pattern should be ignored during matching and not be a pattern # variable. But MIT-Scheme disagrees with me... + +# some tests from http://sisc-scheme.org/r5rs_pitfall.scm +def test_pitfall_3_1(): + w_result = eval_noctx("""(let-syntax ((foo (syntax-rules () + ((_ expr) (+ expr 1))))) + (let ((+ *)) + (foo 3)))""") + assert w_result.to_number() == 4 + +def test_pitfall_3_2(): + py.test.skip("(cond ...) not implemented yet") + w_result = eval_noctx("""(let-syntax ((foo (syntax-rules () + ((_ var) (define var 1))))) + (let ((x 2)) + (begin (define foo +)) + (cond (else (foo x))) + x))""") + assert w_result.to_number() == 2 + +def test_pitfall_3_3(): + py.test.skip("currently fails") + w_result = eval_noctx(""" + (let ((x 1)) + (let-syntax + ((foo (syntax-rules () + ((_ y) (let-syntax + ((bar (syntax-rules () + ((_) (let ((x 2)) y))))) + (bar)))))) + (foo x)))""") + assert w_result.to_number() == 1 + +def test_pitfall_3_4(): + w_result = eval_noctx("(let-syntax ((x (syntax-rules ()))) 1)") + assert w_result.to_number() == 1 From arigo at codespeak.net Sat Aug 4 11:04:04 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Aug 2007 11:04:04 +0200 (CEST) Subject: [pypy-svn] r45482 - pypy/dist/pypy/rpython Message-ID: <20070804090404.2BD4580D2@code0.codespeak.net> Author: arigo Date: Sat Aug 4 11:04:02 2007 New Revision: 45482 Modified: pypy/dist/pypy/rpython/extfunc.py Log: Oups! Modified: pypy/dist/pypy/rpython/extfunc.py ============================================================================== --- pypy/dist/pypy/rpython/extfunc.py (original) +++ pypy/dist/pypy/rpython/extfunc.py Sat Aug 4 11:04:02 2007 @@ -25,7 +25,7 @@ # an exception afterwards, the ExtRaisingEntry would create # a double-registration and crash in an AssertionError that # masks the original problem. In this case, just re-raise now. - if extregistry.lookup(func): + if extregistry.is_registered(func): raise exc, exc_inst, tb class ExtRaisingEntry(ExtRegistryEntry): _about_ = func From fijal at codespeak.net Sat Aug 4 17:03:27 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 4 Aug 2007 17:03:27 +0200 (CEST) Subject: [pypy-svn] r45485 - in pypy/dist/pypy/module/thread: . test Message-ID: <20070804150327.879F180E3@code0.codespeak.net> Author: fijal Date: Sat Aug 4 17:03:26 2007 New Revision: 45485 Modified: pypy/dist/pypy/module/thread/ll_thread.py pypy/dist/pypy/module/thread/test/test_ll_thread.py Log: Intermediate checkin, some support for thread.start_new_thread Modified: pypy/dist/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/ll_thread.py (original) +++ pypy/dist/pypy/module/thread/ll_thread.py Sat Aug 4 17:03:26 2007 @@ -5,8 +5,16 @@ from pypy.rpython.extfunc import genericcallable from pypy.module.thread.os_thread import Bootstrapper from pypy.translator.tool.cbuild import cache_c_module +from pypy.rpython.annlowlevel import cast_instance_to_base_ptr,\ + cast_base_ptr_to_instance import thread, py - +from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.annotation import model as annmodel +from pypy.rpython.lltypesystem.lltype import typeOf + +class BaseBootstrapper: + def bootstrap(self): + pass class ThreadError(Exception): def __init__(self, msg): @@ -35,8 +43,9 @@ return rffi.llexternal(name, args, result, includes=includes, libraries=libraries) -c_thread_start = llexternal('RPyThreadStart', [lltype.FuncType([rffi.VOIDP], - rffi.VOIDP)], rffi.INT) +CALLBACK = lltype.FuncType([rffi.VOIDP], rffi.VOIDP) +c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT) +c_thread_get_ident = llexternal('RPyThreadGetIdent', [], lltype.Void) TLOCKP = rffi.COpaque('struct RPyOpaque_ThreadLock', includes=includes) @@ -62,4 +71,46 @@ finally: c_thread_releaselock(lock._lock) - +def ll_start_new_thread(l_func, arg): + l_arg = cast_instance_to_base_ptr(arg) + ident = c_thread_start(l_func, l_arg) + if ident == -1: + raise ThreadError("can't start new thread") + return ident + +class LLStartNewThread(ExtRegistryEntry): + _about_ = ll_start_new_thread + + def compute_result_annotation(self, s_func, s_arg): + bookkeeper = self.bookkeeper + assert s_func.is_constant(), "Cannot call ll_start_new_thread with non-constant function" + s_result = bookkeeper.emulate_pbc_call(bookkeeper.position_key, + s_func, [s_arg]) + assert annmodel.s_None.contains(s_result), ( + """thread.start_new_thread(f, arg): f() should return None""") + return annmodel.SomeInteger() + + def compute_annotation_bk(self, bookkeeper): + return annmodel.SomePBC([bookkeeper.getdesc(self.instance)]) + + def specialize_call(self, hop): + rtyper = hop.rtyper + bookkeeper = rtyper.annotator.bookkeeper + _callable = hop.args_s[0].const + args_r = [rtyper.getrepr(s_arg) for s_arg in hop.args_s] + ll_arg = args_r[1].lowleveltype + _type = lltype.FuncType([ll_arg], lltype.Void) + funcptr = lltype.functionptr(_type, _callable.func_name, + _callable=_callable) + r_result = rtyper.getrepr(hop.s_result) + ll_result = r_result.lowleveltype + args_s = [bookkeeper.immutablevalue(i) for i in [funcptr, ll_arg]] + obj = rtyper.getannmixlevel().delayedfunction( + ll_start_new_thread, args_s, annmodel.SomeInteger()) + vlist = [hop.inputconst(typeOf(obj), obj)] + hop.inputargs(*args_r) + hop.exception_is_here() + return hop.genop('direct_call', vlist, r_result) + +# a simple wrapper, not to expose C functions (is this really necessary?) +def ll_get_ident(): + return c_thread_get_ident() Modified: pypy/dist/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/dist/pypy/module/thread/test/test_ll_thread.py Sat Aug 4 17:03:26 2007 @@ -1,5 +1,6 @@ from pypy.module.thread.ll_thread import * +from pypy.translator.c.test.test_genc import compile import py def test_lock(): @@ -14,3 +15,26 @@ def test_thread_error(): l = ll_allocate_lock() py.test.raises(ThreadError, ll_release_lock, l) + +def test_thread_init_new(): + """ This test works only after translation + """ + py.test.skip("does not work") + import time + import thread + + class X(BaseBootstrapper): + def __init__(self): + self.top = [] + + def bootstrap(self): + self.top.append(1) + + def f(): + x = X() + ll_start_new_thread(X.bootstrap, x) + time.sleep(.3) + return len(x.top) + + fn = compile(f, []) + assert fn() == 1 From pedronis at codespeak.net Sat Aug 4 18:23:47 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Aug 2007 18:23:47 +0200 (CEST) Subject: [pypy-svn] r45486 - pypy/dist/pypy/rpython/rctypes/test Message-ID: <20070804162347.0DBC980E4@code0.codespeak.net> Author: pedronis Date: Sat Aug 4 18:23:45 2007 New Revision: 45486 Modified: pypy/dist/pypy/rpython/rctypes/test/test_overhead.py Log: make this test really test something and skip it because right now it is broken. malloc removal doesn't know about zero malloc Modified: pypy/dist/pypy/rpython/rctypes/test/test_overhead.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/test/test_overhead.py (original) +++ pypy/dist/pypy/rpython/rctypes/test/test_overhead.py Sat Aug 4 18:23:45 2007 @@ -4,6 +4,8 @@ """ import py +py.test.skip("broken: malloc removal doesn't do anything with zero mallocs") + import pypy.rpython.rctypes.implementation from pypy import conftest from pypy.rpython.test.test_llinterp import gengraph @@ -22,7 +24,7 @@ result = [] for block in t.graphs[0].iterblocks(): for op in block.operations: - if op.opname.startswith('malloc'): + if op.opname.startswith('malloc') or op.opname.startswith('zero_malloc'): result.append(op.result.concretetype) return result From pedronis at codespeak.net Sun Aug 5 00:42:14 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 5 Aug 2007 00:42:14 +0200 (CEST) Subject: [pypy-svn] r45487 - in pypy/dist/pypy: jit/codegen/llgraph jit/hintannotator jit/timeshifter rlib rpython rpython/lltypesystem rpython/memory rpython/memory/gctransform rpython/memory/gctransform/test rpython/rctypes rpython/test translator/backendopt translator/backendopt/test translator/c translator/c/src translator/stackless Message-ID: <20070804224214.EC52780C5@code0.codespeak.net> Author: pedronis Date: Sun Aug 5 00:42:12 2007 New Revision: 45487 Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/hintannotator/annotator.py pypy/dist/pypy/jit/timeshifter/hrtyper.py pypy/dist/pypy/rlib/rgc.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/rpython/lltypesystem/rstr.py pypy/dist/pypy/rpython/lltypesystem/rtuple.py pypy/dist/pypy/rpython/memory/gctransform/boehm.py pypy/dist/pypy/rpython/memory/gctransform/framework.py pypy/dist/pypy/rpython/memory/gctransform/refcounting.py pypy/dist/pypy/rpython/memory/gctransform/stacklessframework.py pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py pypy/dist/pypy/rpython/memory/gctransform/transform.py pypy/dist/pypy/rpython/memory/lltypesimulation.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rctypes/astringbuf.py pypy/dist/pypy/rpython/rctypes/rmodel.py pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/translator/backendopt/escape.py pypy/dist/pypy/translator/backendopt/malloc.py pypy/dist/pypy/translator/backendopt/mallocprediction.py pypy/dist/pypy/translator/backendopt/test/test_escape.py pypy/dist/pypy/translator/c/exceptiontransform.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/src/mem.h pypy/dist/pypy/translator/stackless/transform.py Log: kill flavor_malloc_*, zero_malloc_* now only malloc_* operations should be present in graphs until gc transform malloc and malloc_varsize now always carry a dictionary of flags as second operand, the 'flavor' key must always be set in this dict the flavored_free operation is now just free(p, flavor), flavor is just the flavor string the base gc transform class has now more responsabilities, subclasses need to care only about 'gc' flavor operations, using the gct_fv_gc_malloc* hooks backends need to support only raw/boehm memory operations (and the oddballs op stack_malloc, and cpy_* ) I have run quite a lot of tests and some translation, may stil have missed something, we'll see Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Sun Aug 5 00:42:12 2007 @@ -43,6 +43,7 @@ gv_Signed = gv_TYPE(lltype.Signed) gv_Bool = gv_TYPE(lltype.Bool) gv_dummy_placeholder = LLConst(llimpl.dummy_placeholder) +gv_flavor_gc = LLConst(llimpl.placeholder({'flavor': 'gc'})) gv_Address = gv_TYPE(llmemory.Address) @@ -209,14 +210,14 @@ def genop_malloc_fixedsize(self, (gv_TYPE, gv_PTRTYPE)): debug_assert(self.rgenop.currently_writing is self, "genop_malloc_fixedsize: bad currently_writing") - vars_gv = [gv_TYPE.v] + vars_gv = [gv_TYPE.v, gv_flavor_gc.v] return LLVar(llimpl.genop(self.b, 'malloc', vars_gv, gv_PTRTYPE.v)) def genop_malloc_varsize(self, (gv_TYPE, gv_PTRTYPE), gv_length): debug_assert(self.rgenop.currently_writing is self, "genop_malloc_varsize: bad currently_writing") - vars_gv = [gv_TYPE.v, gv_length.v] + vars_gv = [gv_TYPE.v, gv_flavor_gc.v, gv_length.v] return LLVar(llimpl.genop(self.b, 'malloc_varsize', vars_gv, gv_PTRTYPE.v)) Modified: pypy/dist/pypy/jit/hintannotator/annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/annotator.py Sun Aug 5 00:42:12 2007 @@ -28,26 +28,26 @@ def getuserclassdefinitions(self): return [] - def consider_op_malloc(self, hs_TYPE): + def consider_op_malloc(self, hs_TYPE, hs_flags): TYPE = hs_TYPE.const + flags = hs_flags.const + assert flags['flavor'] == 'gc' if self.policy.novirtualcontainer: return hintmodel.SomeLLAbstractVariable(lltype.Ptr(TYPE)) else: vstructdef = self.bookkeeper.getvirtualcontainerdef(TYPE) return hintmodel.SomeLLAbstractContainer(vstructdef) - consider_op_zero_malloc = consider_op_malloc - - def consider_op_malloc_varsize(self, hs_TYPE, hs_length): + def consider_op_malloc_varsize(self, hs_TYPE, hs_flags, hs_length): TYPE = hs_TYPE.const + flags = hs_flags.const + assert flags['flavor'] == 'gc' if self.policy.novirtualcontainer: return hintmodel.SomeLLAbstractVariable(lltype.Ptr(TYPE)) else: vcontainerdef = self.bookkeeper.getvirtualcontainerdef(TYPE) return hintmodel.SomeLLAbstractContainer(vcontainerdef) - consider_op_zero_malloc_varsize = consider_op_malloc_varsize - def consider_op_zero_gc_pointers_inside(self, hs_v): pass Modified: pypy/dist/pypy/jit/timeshifter/hrtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/hrtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/hrtyper.py Sun Aug 5 00:42:12 2007 @@ -889,7 +889,7 @@ assert isinstance(hop.r_result, RedRepr) PTRTYPE = originalconcretetype(hop.s_result) TYPE = PTRTYPE.TO - v_size = hop.inputarg(self.getredrepr(lltype.Signed), arg=1) + v_size = hop.inputarg(self.getredrepr(lltype.Signed), arg=2) if isinstance(TYPE, lltype.Struct): return hop.r_result.create_varsize(hop, v_size) Modified: pypy/dist/pypy/rlib/rgc.py ============================================================================== --- pypy/dist/pypy/rlib/rgc.py (original) +++ pypy/dist/pypy/rlib/rgc.py Sun Aug 5 00:42:12 2007 @@ -105,13 +105,14 @@ r_tuple = hop.r_result c_CLONE = hop.inputconst(lltype.Void, X_CLONE) + c_flags = hop.inputconst(lltype.Void, {'flavor': 'gc'}) c_gcobjectptr = hop.inputconst(lltype.Void, "gcobjectptr") c_pool = hop.inputconst(lltype.Void, "pool") v_gcobject, v_pool = hop.inputargs(hop.args_r[0], r_pool_ptr) v_gcobjectptr = hop.genop('cast_opaque_ptr', [v_gcobject], resulttype = llmemory.GCREF) - v_clonedata = hop.genop('malloc', [c_CLONE], + v_clonedata = hop.genop('malloc', [c_CLONE, c_flags], resulttype = X_CLONE_PTR) hop.genop('setfield', [v_clonedata, c_gcobjectptr, v_gcobjectptr]) hop.genop('setfield', [v_clonedata, c_pool, v_pool]) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sun Aug 5 00:42:12 2007 @@ -613,53 +613,48 @@ return lltype._cast_whatever(TGT, result) op_adr_call.need_result_type = True - def op_malloc(self, obj): - if self.llinterpreter.gc is not None: + def op_malloc(self, obj, flags): + flavor = flags['flavor'] + zero = flags.get('zero', False) + if self.llinterpreter.gc is not None and flavor == 'gc': + assert not zero args = self.llinterpreter.gc.get_arg_malloc(obj) malloc = self.llinterpreter.gc.get_funcptr_malloc() result = self.op_direct_call(malloc, *args) return self.llinterpreter.gc.adjust_result_malloc(result, obj) - else: - return self.heap.malloc(obj) - - def op_zero_malloc(self, obj): - assert self.llinterpreter.gc is None - return self.heap.malloc(obj, zero=True) - - def op_malloc_varsize(self, obj, size): - if self.llinterpreter.gc is not None: - args = self.llinterpreter.gc.get_arg_malloc(obj, size) - malloc = self.llinterpreter.gc.get_funcptr_malloc() - result = self.op_direct_call(malloc, *args) - return self.llinterpreter.gc.adjust_result_malloc(result, obj, size) - else: - try: - return self.heap.malloc(obj, size) - except MemoryError: - self.make_llexception() - - def op_zero_malloc_varsize(self, obj, size): - assert self.llinterpreter.gc is None - return self.heap.malloc(obj, size, zero=True) - - def op_flavored_malloc_varsize(self, flavor, obj, size): - # XXX should we keep info about all mallocs for later checks of - # frees? - assert flavor == 'raw' - return self.heap.malloc(obj, size, flavor=flavor) - - def op_flavored_malloc(self, flavor, obj): - assert isinstance(flavor, str) - if flavor == "stack": + elif flavor == "stack": if isinstance(obj, lltype.Struct) and obj._arrayfld is None: result = self.heap.malloc(obj) self.alloca_objects.append(result) return result else: raise ValueError("cannot allocate variable-sized things on the stack") - return self.heap.malloc(obj, flavor=flavor) + + return self.heap.malloc(obj, zero=zero, flavor=flavor) + + # only after gc transform + def op_cpy_malloc(self, obj, cpytype): # xxx + return self.heap.malloc(obj, flavor='cpy', extra_args=(cpytype,)) + + def op_cpy_free(self, obj): + return self.heap.free(obj, flavor='cpy') # xxx ? + + def op_malloc_varsize(self, obj, flags, size): + flavor = flags['flavor'] + zero = flags.get('zero', False) + if self.llinterpreter.gc is not None and flavor == 'gc': + assert not zero + args = self.llinterpreter.gc.get_arg_malloc(obj, size) + malloc = self.llinterpreter.gc.get_funcptr_malloc() + result = self.op_direct_call(malloc, *args) + return self.llinterpreter.gc.adjust_result_malloc(result, obj, size) + assert flavor in ('gc', 'raw') + try: + return self.heap.malloc(obj, size, zero=zero, flavor=flavor) + except MemoryError: + self.make_llexception() - def op_flavored_free(self, flavor, obj): + def op_free(self, obj, flavor): assert isinstance(flavor, str) self.heap.free(obj, flavor=flavor) @@ -791,6 +786,9 @@ assert lltype.typeOf(value) == typ getattr(addr, str(typ).lower())[offset] = value + def op_stack_malloc(self, size): # mmh + raise NotImplementedError("backend only") + # ______ for the JIT ____________ def op_call_boehm_gc_alloc(self): raise NotImplementedError("call_boehm_gc_alloc") Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sun Aug 5 00:42:12 2007 @@ -309,13 +309,9 @@ # __________ pointer operations __________ 'malloc': LLOp(canraise=(MemoryError,), canunwindgc=True), - 'zero_malloc': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), - 'zero_malloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), 'zero_gc_pointers_inside': LLOp(), - 'flavored_malloc': LLOp(canraise=(MemoryError,)), - 'flavored_malloc_varsize' : LLOp(canraise=(MemoryError,)), - 'flavored_free': LLOp(), + 'free': LLOp(), 'getfield': LLOp(sideeffects=False, canrun=True), 'getarrayitem': LLOp(sideeffects=False, canrun=True), 'getarraysize': LLOp(canfold=True), @@ -349,6 +345,9 @@ 'raw_memcopy': LLOp(), 'raw_load': LLOp(sideeffects=False), 'raw_store': LLOp(), + 'stack_malloc': LLOp(), # mmh + 'cpy_malloc': LLOp(), # xxx + 'cpy_free': LLOp(), # xxx 'adr_add': LLOp(canfold=True), 'adr_sub': LLOp(canfold=True), 'adr_delta': LLOp(canfold=True), Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Sun Aug 5 00:42:12 2007 @@ -504,21 +504,19 @@ def new_instance(self, llops, classcallhop=None, v_cpytype=None): """Build a new instance, without calling __init__.""" - mallocop = 'malloc' + flavor = self.gcflavor + flags = {'flavor': flavor } ctype = inputconst(Void, self.object_type) - vlist = [ctype] + cflags = inputconst(Void, flags) + vlist = [ctype, cflags] if self.classdef is not None: - flavor = self.gcflavor - if flavor != 'gc': # not default flavor - mallocop = 'flavored_malloc' - vlist.insert(0, inputconst(Void, flavor)) - if flavor == 'cpy': - if v_cpytype is None: - from pypy.rpython import rcpy - cpytype = rcpy.build_pytypeobject(self) - v_cpytype = inputconst(Ptr(PyObject), cpytype) - vlist.append(v_cpytype) - vptr = llops.genop(mallocop, vlist, + if flavor == 'cpy': + if v_cpytype is None: + from pypy.rpython import rcpy + cpytype = rcpy.build_pytypeobject(self) + v_cpytype = inputconst(Ptr(PyObject), cpytype) + vlist.append(v_cpytype) + vptr = llops.genop('malloc', vlist, resulttype = Ptr(self.object_type)) ctypeptr = inputconst(CLASSTYPE, self.rclass.getvtable()) self.setfield(vptr, '__class__', ctypeptr, llops) Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rstr.py Sun Aug 5 00:42:12 2007 @@ -84,7 +84,8 @@ def convert_from_to((r_from, r_to), v, llops): v_len = llops.gencapicall('PyString_Size', [v], resulttype=Signed) cstr = inputconst(Void, STR) - v_result = llops.genop('malloc_varsize', [cstr, v_len], + cflags = inputconst(Void, {'flavor': 'gc'}) + v_result = llops.genop('malloc_varsize', [cstr, cflags, v_len], resulttype=Ptr(STR)) cchars = inputconst(Void, "chars") v_chars = llops.genop('getsubstruct', [v_result, cchars], @@ -707,7 +708,8 @@ things = cls.parse_fmt_string(s) size = inputconst(Signed, len(things)) # could be unsigned? cTEMP = inputconst(Void, TEMP) - vtemp = hop.genop("malloc_varsize", [cTEMP, size], + cflags = inputconst(Void, {'flavor': 'gc'}) + vtemp = hop.genop("malloc_varsize", [cTEMP, cflags, size], resulttype=Ptr(TEMP)) # XXX hash r_tuple = hop.args_r[1] Modified: pypy/dist/pypy/rpython/lltypesystem/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rtuple.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rtuple.py Sun Aug 5 00:42:12 2007 @@ -30,7 +30,9 @@ if len(r_tuple.items_r) == 0: return inputconst(Void, ()) # a Void empty tuple c1 = inputconst(Void, r_tuple.lowleveltype.TO) - v_result = llops.genop('malloc', [c1], resulttype = r_tuple.lowleveltype) + cflags = inputconst(Void, {'flavor': 'gc'}) + v_result = llops.genop('malloc', [c1, cflags], + resulttype = r_tuple.lowleveltype) for i in range(len(r_tuple.items_r)): cname = inputconst(Void, r_tuple.fieldnames[i]) llops.genop('setfield', [v_result, cname, items_v[i]]) Modified: pypy/dist/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/boehm.py Sun Aug 5 00:42:12 2007 @@ -1,11 +1,11 @@ -from pypy.rpython.memory.gctransform.transform import GCTransformer +from pypy.rpython.memory.gctransform.transform import GCTransformer, mallocHelpers from pypy.rpython.memory.gctransform.support import type_contains_pyobjs, \ get_rtti, _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython import rmodel from pypy.rlib.rarithmetic import ovfcheck from pypy.objspace.flow.model import Constant +from pypy.rpython.lltypesystem.lloperation import llop class BoehmGCTransformer(GCTransformer): FINALIZER_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void)) @@ -13,37 +13,25 @@ def __init__(self, translator, inline=False): super(BoehmGCTransformer, self).__init__(translator, inline=inline) self.finalizer_funcptrs = {} - memoryError = MemoryError() - def ll_malloc_fixedsize(size, finalizer): - result = llop.boehm_malloc(llmemory.Address, size) - if not result: - raise memoryError + atomic_mh = mallocHelpers() + atomic_mh.allocate = lambda size: llop.boehm_malloc_atomic(llmemory.Address, size) + def ll_malloc_fixedsize_atomic(size, finalizer): + result = atomic_mh._ll_malloc_fixedsize(size) if finalizer: # XXX runtime check here is bad? llop.boehm_register_finalizer(lltype.Void, result, finalizer) return result - def ll_malloc_fixedsize_atomic(size, finalizer): - result = llop.boehm_malloc_atomic(llmemory.Address, size) - if not result: - raise memoryError + + mh = mallocHelpers() + mh.allocate = lambda size: llop.boehm_malloc(llmemory.Address, size) + def ll_malloc_fixedsize(size, finalizer): + result = mh._ll_malloc_fixedsize(size) if finalizer: # XXX runtime check here is bad? llop.boehm_register_finalizer(lltype.Void, result, finalizer) return result # XXX, do we need/want an atomic version of this function? - def ll_malloc_varsize_no_length(length, size, itemsize): - try: - varsize = ovfcheck(itemsize * length) - tot_size = ovfcheck(size + varsize) - except OverflowError: - raise memoryError - result = llop.boehm_malloc(llmemory.Address, tot_size) - if not result: - raise memoryError - return result - def ll_malloc_varsize(length, size, itemsize, lengthoffset): - result = ll_malloc_varsize_no_length(length, size, itemsize) - (result + lengthoffset).signed[0] = length - return result + ll_malloc_varsize_no_length = mh.ll_malloc_varsize_no_length + ll_malloc_varsize = mh.ll_malloc_varsize if self.translator: self.malloc_fixedsize_ptr = self.inittime_helper( @@ -71,10 +59,8 @@ """ for boehm it is enough to do nothing""" pass - def gct_malloc(self, hop): - TYPE = hop.spaceop.result.concretetype.TO - assert not TYPE._is_varsize() - c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) + def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size): + # XXX same behavior for zero=True: in theory that's wrong if TYPE._is_atomic(): funcptr = self.malloc_fixedsize_atomic_ptr else: @@ -83,49 +69,23 @@ v_raw = hop.genop("direct_call", [funcptr, c_size, c_finalizer_ptr], resulttype=llmemory.Address) - hop.cast_result(v_raw) - - # XXX In theory this is wrong: - gct_zero_malloc = gct_malloc - - def gct_malloc_varsize(self, hop): - def intconst(c): return rmodel.inputconst(lltype.Signed, c) - - op = hop.spaceop - TYPE = op.result.concretetype.TO - assert TYPE._is_varsize() + return v_raw - assert not self.finalizer_funcptr_for_type(TYPE) - if isinstance(TYPE, lltype.Struct): - ARRAY = TYPE._flds[TYPE._arrayfld] - else: - ARRAY = TYPE - assert isinstance(ARRAY, lltype.Array) - if ARRAY._hints.get('isrpystring', False): - c_const_size = intconst(llmemory.sizeof(TYPE, 1)) - else: - c_const_size = intconst(llmemory.sizeof(TYPE, 0)) - c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) - - if ARRAY._hints.get("nolength", False): + def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size, + c_offset_to_length): + # XXX same behavior for zero=True: in theory that's wrong + if c_offset_to_length is None: v_raw = hop.genop("direct_call", - [self.malloc_varsize_no_length_ptr, op.args[-1], + [self.malloc_varsize_no_length_ptr, v_length, c_const_size, c_item_size], resulttype=llmemory.Address) else: - if isinstance(TYPE, lltype.Struct): - offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \ - llmemory.ArrayLengthOffset(ARRAY) - else: - offset_to_length = llmemory.ArrayLengthOffset(ARRAY) v_raw = hop.genop("direct_call", - [self.malloc_varsize_ptr, op.args[-1], - c_const_size, c_item_size, intconst(offset_to_length)], + [self.malloc_varsize_ptr, v_length, + c_const_size, c_item_size, c_offset_to_length], resulttype=llmemory.Address) - hop.cast_result(v_raw) - - gct_zero_malloc_varsize = gct_malloc_varsize + return v_raw def finalizer_funcptr_for_type(self, TYPE): if TYPE in self.finalizer_funcptrs: Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Sun Aug 5 00:42:12 2007 @@ -16,8 +16,11 @@ class CollectAnalyzer(graphanalyze.GraphAnalyzer): def operation_is_true(self, op): - return op.opname in ("malloc", "malloc_varsize", "gc__collect", - "gc_x_become", "zero_malloc_varsize", "zero_malloc") + if op.opname in ('gc__collect', 'gc_x_become'): + return True + if op.opname in ('malloc', 'malloc_varsize'): + flags = op.args[1].value + return flags['flavor'] == 'gc' and not flags.get('nocollect', False) ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void) @@ -479,22 +482,11 @@ gct_indirect_call = gct_direct_call - def gct_malloc(self, hop): + def gct_fv_gc_malloc(self, hop, flags, TYPE, *args): op = hop.spaceop + flavor = flags['flavor'] + c_can_collect = rmodel.inputconst(lltype.Bool, not flags.get('nocollect', False)) - if op.opname.startswith('flavored_'): - flavor = op.args[0].value - TYPE = op.args[1].value - else: - flavor = 'gc' - TYPE = op.args[0].value - - if not flavor.startswith('gc'): - self.default(hop) - return - - c_can_collect = rmodel.inputconst(lltype.Bool, - flavor != 'gc_nocollect') PTRTYPE = op.result.concretetype assert PTRTYPE.TO == TYPE type_id = self.get_type_id(TYPE) @@ -504,7 +496,8 @@ c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"]) if not op.opname.endswith('_varsize'): #malloc_ptr = self.malloc_fixedsize_ptr - if op.opname.startswith('zero'): + zero = flags.get('zero', False) + if zero: malloc_ptr = self.malloc_fixedsize_clear_ptr else: malloc_ptr = self.malloc_fixedsize_ptr @@ -528,13 +521,9 @@ v_result = hop.genop("direct_call", [malloc_ptr] + args, resulttype=llmemory.GCREF) self.pop_roots(hop) - hop.cast_result(v_result) + return v_result - gct_zero_malloc = gct_malloc - gct_malloc_varsize = gct_malloc - gct_zero_malloc_varsize = gct_malloc - gct_flavored_malloc = gct_malloc - gct_flavored_malloc_varsize = gct_malloc + gct_fv_gc_malloc_varsize = gct_fv_gc_malloc def gct_gc__collect(self, hop): op = hop.spaceop Modified: pypy/dist/pypy/rpython/memory/gctransform/refcounting.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/refcounting.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/refcounting.py Sun Aug 5 00:42:12 2007 @@ -1,5 +1,5 @@ import py -from pypy.rpython.memory.gctransform.transform import GCTransformer +from pypy.rpython.memory.gctransform.transform import GCTransformer, mallocHelpers from pypy.rpython.memory.gctransform.support import find_gc_ptrs_in_type, \ get_rtti, _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor from pypy.rpython.lltypesystem import lltype, llmemory @@ -70,11 +70,11 @@ def ll_no_pointer_dealloc(adr): llop.gc_free(lltype.Void, adr) + mh = mallocHelpers() + mh.allocate = lladdress.raw_malloc def ll_malloc_fixedsize(size): size = gc_header_offset + size - result = lladdress.raw_malloc(size) - if not result: - raise memoryError + result = mh._ll_malloc_fixedsize(size) lladdress.raw_memclear(result, size) result += gc_header_offset return result @@ -84,17 +84,13 @@ varsize = ovfcheck(itemsize * length) tot_size = ovfcheck(fixsize + varsize) except OverflowError: - raise memoryError - result = lladdress.raw_malloc(tot_size) - if not result: - raise memoryError + raise MemoryError() + result = mh._ll_malloc_fixedsize(tot_size) lladdress.raw_memclear(result, tot_size) result += gc_header_offset return result - def ll_malloc_varsize(length, size, itemsize, lengthoffset): - result = ll_malloc_varsize_no_length(length, size, itemsize) - (result + lengthoffset).signed[0] = length - return result + mh.ll_malloc_varsize_no_length = ll_malloc_varsize_no_length + ll_malloc_varsize = mh.ll_malloc_varsize if self.translator: self.increfptr = self.inittime_helper( @@ -112,7 +108,8 @@ ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address) self.malloc_varsize_ptr = self.inittime_helper( ll_malloc_varsize, [lltype.Signed]*4, llmemory.Address) - self.mixlevelannotator.finish() # for now + self.mixlevelannotator.finish() + self.mixlevelannotator.backend_optimize() # cache graphs: self.decref_funcptrs = {} self.static_deallocator_funcptrs = {} @@ -147,52 +144,24 @@ """ get this object back into gc control """ self.pop_alive(hop.spaceop.args[0]) - def gct_malloc(self, hop): - TYPE = hop.spaceop.result.concretetype.TO - assert not TYPE._is_varsize() - c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) + def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size): v_raw = hop.genop("direct_call", [self.malloc_fixedsize_ptr, c_size], resulttype=llmemory.Address) - hop.cast_result(v_raw) - - gct_zero_malloc = gct_malloc - - def gct_malloc_varsize(self, hop): - def intconst(c): return rmodel.inputconst(lltype.Signed, c) - - op = hop.spaceop - TYPE = op.result.concretetype.TO - assert TYPE._is_varsize() + return v_raw - if isinstance(TYPE, lltype.Struct): - ARRAY = TYPE._flds[TYPE._arrayfld] - else: - ARRAY = TYPE - assert isinstance(ARRAY, lltype.Array) - if ARRAY._hints.get('isrpystring', False): - c_const_size = intconst(llmemory.sizeof(TYPE, 1)) - else: - c_const_size = intconst(llmemory.sizeof(TYPE, 0)) - c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) - - if ARRAY._hints.get("nolength", False): + def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size, + c_offset_to_length): + if c_offset_to_length is None: v_raw = hop.genop("direct_call", - [self.malloc_varsize_no_length_ptr, op.args[-1], + [self.malloc_varsize_no_length_ptr, v_length, c_const_size, c_item_size], resulttype=llmemory.Address) else: - if isinstance(TYPE, lltype.Struct): - offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \ - llmemory.ArrayLengthOffset(ARRAY) - else: - offset_to_length = llmemory.ArrayLengthOffset(ARRAY) v_raw = hop.genop("direct_call", - [self.malloc_varsize_ptr, op.args[-1], - c_const_size, c_item_size, intconst(offset_to_length)], + [self.malloc_varsize_ptr, v_length, + c_const_size, c_item_size, c_offset_to_length], resulttype=llmemory.Address) - hop.cast_result(v_raw) - - gct_zero_malloc_varsize = gct_malloc_varsize + return v_raw def gct_gc_deallocate(self, hop): TYPE = hop.spaceop.args[0].value Modified: pypy/dist/pypy/rpython/memory/gctransform/stacklessframework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/stacklessframework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/stacklessframework.py Sun Aug 5 00:42:12 2007 @@ -1,23 +1,11 @@ -from pypy.rpython.memory.gctransform.transform import \ - MinimalGCTransformer, var_ispyobj -from pypy.rpython.memory.gctransform.framework import \ - FrameworkGCTransformer +from pypy.rpython.memory.gctransform.transform import var_ispyobj +from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer from pypy.rpython.lltypesystem import lltype, llmemory -class StacklessFrameworkMinimalGCTransformer(MinimalGCTransformer): - def gct_flavored_malloc(self, hop): - flavor = hop.spaceop.args[0].value - if flavor == 'gc_nocollect': - return self.parenttransformer.gct_flavored_malloc(hop) - else: - self.default(hop) - gct_flavored_malloc_varsize = gct_flavored_malloc - class StacklessFrameworkGCTransformer(FrameworkGCTransformer): use_stackless = True extra_static_slots = 1 # for the stack_capture()'d frame - MinimalGCTransformer = StacklessFrameworkMinimalGCTransformer def __init__(self, translator): FrameworkGCTransformer.__init__(self, translator) Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py Sun Aug 5 00:42:12 2007 @@ -1,4 +1,4 @@ -from pypy.rpython.memory.gctransform.transform import GCTransformer +from pypy.rpython.memory.gctransform.transform import BaseGCTransformer from pypy.objspace.flow.model import c_last_exception, Variable from pypy.rpython.memory.gctransform.support import var_ispyobj from pypy.translator.backendopt.support import var_needsgc @@ -87,7 +87,7 @@ res = llinterp.eval_graph(graph, [cc('brrrrrr')]) assert res == f('brrrrrr') -class _TestGCTransformer(GCTransformer): +class _TestGCTransformer(BaseGCTransformer): def push_alive_nopyobj(self, var, llops): llops.genop("gc_push_alive", [var]) Modified: pypy/dist/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/transform.py Sun Aug 5 00:42:12 2007 @@ -12,12 +12,14 @@ from pypy.translator.backendopt.ssa import DataFlowFamilyBuilder from pypy.annotation import model as annmodel from pypy.rpython import rmodel, annlowlevel -from pypy.rpython.memory import gc, lladdress +from pypy.rpython.memory import gc from pypy.rpython.annlowlevel import MixLevelHelperAnnotator from pypy.rpython.rtyper import LowLevelOpList from pypy.rpython.rbuiltin import gen_cast from pypy.rlib.rarithmetic import ovfcheck import sets, os, sys +from pypy.rpython.memory import lladdress +from pypy.rpython.lltypesystem.lloperation import llop def var_ispyobj(var): if hasattr(var, 'concretetype'): @@ -83,8 +85,9 @@ assert v_new != var self.llops[-1].result = v_result +# ________________________________________________________________ -class GCTransformer(object): +class BaseGCTransformer(object): finished_helpers = False def __init__(self, translator, inline=False): @@ -103,7 +106,7 @@ self.minimalgctransformer = self.MinimalGCTransformer(self) else: self.minimalgctransformer = None - + def get_lltype_of_exception_value(self): if self.translator is not None: exceptiondata = self.translator.rtyper.getexceptiondata() @@ -189,6 +192,7 @@ if graph in self.seen_graphs: return self.seen_graphs[graph] = True + self.links_to_split = {} # link -> vars to pop_alive across the link # for sanity, we need an empty block at the start of the graph @@ -323,9 +327,10 @@ def gct_zero_gc_pointers_inside(self, hop): pass -class MinimalGCTransformer(GCTransformer): + +class MinimalGCTransformer(BaseGCTransformer): def __init__(self, parenttransformer): - GCTransformer.__init__(self, parenttransformer.translator) + BaseGCTransformer.__init__(self, parenttransformer.translator) self.parenttransformer = parenttransformer def push_alive(self, var, llops=None): @@ -334,5 +339,174 @@ def pop_alive(self, var, llops=None): pass -GCTransformer.MinimalGCTransformer = MinimalGCTransformer + def gct_malloc(self, hop): + flags = hop.spaceop.args[1].value + flavor = flags['flavor'] + assert flavor == 'raw' + return self.parenttransformer.gct_malloc(hop) + + def gct_malloc_varsize(self, hop): + flags = hop.spaceop.args[1].value + flavor = flags['flavor'] + assert flavor == 'raw' + return self.parenttransformer.gct_malloc_varsize(hop) + + def gct_free(self, hop): + flavor = hop.spaceop.args[1].value + assert flavor == 'raw' + return self.parenttransformer.gct_free(hop) + +BaseGCTransformer.MinimalGCTransformer = MinimalGCTransformer MinimalGCTransformer.MinimalGCTransformer = None + +# ________________________________________________________________ + +def mallocHelpers(): + class _MallocHelpers(object): + def _freeze_(self): + return True + mh = _MallocHelpers() + + def _ll_malloc_fixedsize(size): + result = mh.allocate(size) + if not result: + raise MemoryError() + return result + mh._ll_malloc_fixedsize = _ll_malloc_fixedsize + + def _ll_malloc_varsize_no_length(length, size, itemsize): + try: + varsize = ovfcheck(itemsize * length) + tot_size = ovfcheck(size + varsize) + except OverflowError: + raise MemoryError() + result = mh.allocate(tot_size) + if not result: + raise MemoryError() + return result + mh._ll_malloc_varsize_no_length = _ll_malloc_varsize_no_length + mh.ll_malloc_varsize_no_length = _ll_malloc_varsize_no_length + + def ll_malloc_varsize(length, size, itemsize, lengthoffset): + result = mh.ll_malloc_varsize_no_length(length, size, itemsize) + (result + lengthoffset).signed[0] = length + return result + mh.ll_malloc_varsize = ll_malloc_varsize + + return mh + +class GCTransformer(BaseGCTransformer): + + def __init__(self, translator, inline=False): + super(GCTransformer, self).__init__(translator, inline=inline) + + mh = mallocHelpers() + mh.allocate = lladdress.raw_malloc + ll_raw_malloc_fixedsize = mh._ll_malloc_fixedsize + ll_raw_malloc_varsize_no_length = mh.ll_malloc_varsize_no_length + ll_raw_malloc_varsize = mh.ll_malloc_varsize + + stack_mh = mallocHelpers() + stack_mh.allocate = lambda size: llop.stack_malloc(llmemory.Address, size) + ll_stack_malloc_fixedsize = stack_mh._ll_malloc_fixedsize + + if self.translator: + self.raw_malloc_fixedsize_ptr = self.inittime_helper( + ll_raw_malloc_fixedsize, [lltype.Signed], llmemory.Address) + self.raw_malloc_varsize_no_length_ptr = self.inittime_helper( + ll_raw_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address, inline=False) + self.raw_malloc_varsize_ptr = self.inittime_helper( + ll_raw_malloc_varsize, [lltype.Signed]*4, llmemory.Address, inline=False) + + self.stack_malloc_fixedsize_ptr = self.inittime_helper( + ll_stack_malloc_fixedsize, [lltype.Signed], llmemory.Address) + + def gct_malloc(self, hop): + TYPE = hop.spaceop.result.concretetype.TO + assert not TYPE._is_varsize() + flags = hop.spaceop.args[1].value + flavor = flags['flavor'] + meth = getattr(self, 'gct_fv_%s_malloc' % flavor, None) + assert meth, "%s has no support for malloc with flavor %r" % (self, flavor) + c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) + v_raw = meth(hop, flags, TYPE, c_size) + hop.cast_result(v_raw) + + def gct_fv_raw_malloc(self, hop, flags, TYPE, c_size): + v_raw = hop.genop("direct_call", [self.raw_malloc_fixedsize_ptr, c_size], + resulttype=llmemory.Address) + return v_raw + + def gct_fv_stack_malloc(self, hop, flags, TYPE, c_size): + v_raw = hop.genop("direct_call", [self.stack_malloc_fixedsize_ptr, c_size], + resulttype=llmemory.Address) + return v_raw + + def gct_fv_cpy_malloc(self, hop, flags, TYPE, c_size): # xxx + op = hop.spaceop + args = op.args[:] + del args[1] + return hop.genop('cpy_malloc', args, resulttype=op.result.concretetype) + + def gct_malloc_varsize(self, hop): + def intconst(c): return rmodel.inputconst(lltype.Signed, c) + + op = hop.spaceop + TYPE = op.result.concretetype.TO + assert TYPE._is_varsize() + flags = hop.spaceop.args[1].value + flavor = flags['flavor'] + meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) + assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) + + if isinstance(TYPE, lltype.Struct): + ARRAY = TYPE._flds[TYPE._arrayfld] + else: + ARRAY = TYPE + assert isinstance(ARRAY, lltype.Array) + if ARRAY._hints.get('isrpystring', False): + c_const_size = intconst(llmemory.sizeof(TYPE, 1)) + else: + c_const_size = intconst(llmemory.sizeof(TYPE, 0)) + c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) + + if ARRAY._hints.get("nolength", False): + c_offset_to_length = None + else: + if isinstance(TYPE, lltype.Struct): + offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \ + llmemory.ArrayLengthOffset(ARRAY) + else: + offset_to_length = llmemory.ArrayLengthOffset(ARRAY) + c_offset_to_length = intconst(offset_to_length) + + v_raw = meth(hop, flags, TYPE, op.args[-1], c_const_size, c_item_size, + c_offset_to_length) + + hop.cast_result(v_raw) + + def gct_fv_raw_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size, + c_offset_to_length): + if c_offset_to_length is None: + v_raw = hop.genop("direct_call", + [self.raw_malloc_varsize_no_length_ptr, v_length, + c_const_size, c_item_size], + resulttype=llmemory.Address) + else: + v_raw = hop.genop("direct_call", + [self.raw_malloc_varsize_ptr, v_length, + c_const_size, c_item_size, c_offset_to_length], + resulttype=llmemory.Address) + return v_raw + + def gct_free(self, hop): + op = hop.spaceop + flavor = op.args[1].value + v = op.args[0] + if flavor == 'raw': + v = hop.genop("cast_ptr_to_adr", [v], resulttype=llmemory.Address) + hop.genop('raw_free', [v]) + elif flavor == 'cpy': + hop.genop('cpy_free', [v]) # xxx + else: + assert False, "%s has no support for free with flavor %r" % (self, flavor) Modified: pypy/dist/pypy/rpython/memory/lltypesimulation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/lltypesimulation.py (original) +++ pypy/dist/pypy/rpython/memory/lltypesimulation.py Sun Aug 5 00:42:12 2007 @@ -194,7 +194,7 @@ return self._address # for now use the simulators raw_malloc -def malloc(T, n=None, immortal=False, flavor='gc'): +def malloc(T, n=None, immortal=False, flavor='gc', zero=True): fixedsize = get_fixed_size(T) varsize = get_variable_size(T) if n is None: Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sun Aug 5 00:42:12 2007 @@ -330,12 +330,15 @@ v_flavor, v_extra_args, v_zero = parse_kwds(hop, (i_flavor, lltype.Void), (i_extra_args, None), (i_zero, None)) + + flags = {'flavor': 'gc'} if v_flavor is not None: - vlist.insert(0, v_flavor) - opname = 'flavored_' + opname + flags['flavor'] = v_flavor.value if i_zero is not None: assert i_extra_args is i_flavor is None - opname = 'zero_' + opname + flags['zero'] = v_zero.value + vlist.append(hop.inputconst(lltype.Void, flags)) + if hop.nb_args == 2: vlist.append(hop.inputarg(lltype.Signed, arg=1)) opname += '_varsize' @@ -355,8 +358,7 @@ assert i_flavor == 1 hop.exception_cannot_occur() vlist = hop.inputargs(hop.args_r[0], lltype.Void) - vlist.reverse() # just for confusion - hop.genop('flavored_free', vlist) + hop.genop('free', vlist) def rtype_const_result(hop): return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const) @@ -595,9 +597,9 @@ def rtype_free_non_gc_object(hop): vinst, = hop.inputargs(hop.args_r[0]) flavor = hop.args_r[0].gcflavor - assert not flavor.startswith('gc') + assert flavor != 'gc' cflavor = hop.inputconst(lltype.Void, flavor) - return hop.genop('flavored_free', [cflavor, vinst]) + return hop.genop('free', [vinst, cflavor]) BUILTIN_TYPER[objectmodel.free_non_gc_object] = rtype_free_non_gc_object Modified: pypy/dist/pypy/rpython/rctypes/astringbuf.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/astringbuf.py (original) +++ pypy/dist/pypy/rpython/rctypes/astringbuf.py Sun Aug 5 00:42:12 2007 @@ -34,8 +34,9 @@ [v_length] = hop.inputargs(lltype.Signed) r_stringbuf = hop.r_result hop.exception_cannot_occur() - return hop.genop("zero_malloc_varsize", [ + return hop.genop("malloc_varsize", [ hop.inputconst(lltype.Void, r_stringbuf.lowleveltype.TO), + hop.inputconst(lltype.Void, {'flavor': 'gc', 'zero': True}), v_length, ], resulttype=r_stringbuf.lowleveltype, ) Modified: pypy/dist/pypy/rpython/rctypes/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/rmodel.py (original) +++ pypy/dist/pypy/rpython/rctypes/rmodel.py Sun Aug 5 00:42:12 2007 @@ -123,14 +123,16 @@ if TYPE._is_varsize(): raise TyperError("allocating array with unknown length") c1 = inputconst(lltype.Void, TYPE) - return llops.genop("zero_malloc", [c1], resulttype=self.lowleveltype) + cflags = inputconst(lltype.Void, {'flavor': 'gc', 'zero': True}) + return llops.genop("malloc", [c1, cflags], resulttype=self.lowleveltype) def allocate_instance_varsize(self, llops, v_length): TYPE = self.lowleveltype.TO if not TYPE._is_varsize(): raise TyperError("allocating non-array with a specified length") c1 = inputconst(lltype.Void, TYPE) - return llops.genop("zero_malloc_varsize", [c1, v_length], + cflags = inputconst(lltype.Void, {'flavor': 'gc', 'zero': True}) + return llops.genop("malloc_varsize", [c1, cflags, v_length], resulttype=self.lowleveltype) def allocate_instance_ref(self, llops, v_c_data, v_c_data_owner=None): Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Sun Aug 5 00:42:12 2007 @@ -410,8 +410,7 @@ a.i = 1 return a.i interp, graph = get_interpreter(f, []) - graph.startblock.operations[0].opname = "flavored_malloc" - graph.startblock.operations[0].args.insert(0, inputconst(Void, "stack")) + graph.startblock.operations[0].args[1] = inputconst(Void, {'flavor': "stack"}) result = interp.eval_graph(graph, []) assert result == 1 @@ -432,8 +431,7 @@ return globala.next.i interp, graph = get_interpreter(h, []) fgraph = graph.startblock.operations[0].args[0].value._obj.graph - fgraph.startblock.operations[0].opname = "flavored_malloc" - fgraph.startblock.operations[0].args.insert(0, inputconst(Void, "stack")) + fgraph.startblock.operations[0].args[1] = inputconst(Void, {'flavor': "stack"}) py.test.raises(AttributeError, "interp.eval_graph(graph, [])") #__________________________________________________________________ Modified: pypy/dist/pypy/translator/backendopt/escape.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/escape.py (original) +++ pypy/dist/pypy/translator/backendopt/escape.py Sun Aug 5 00:42:12 2007 @@ -185,19 +185,21 @@ args = self.getstates(op.args) #print "args:", args opimpl = getattr(self, 'op_'+op.opname, None) - if opimpl is None: - if isonheap(op.result) or filter(None, args): - for arg in args: - if arg is not None: - changed = arg.setchanges() - self.handle_changed(changed) - changed = arg.setescapes() - self.handle_changed(changed) - #raise NotImplementedError("can't handle %s" % (op.opname, )) + if opimpl is not None: + res = opimpl(op, *args) + if res is not NotImplemented: + self.setstate(op.result, res) + return + + if isonheap(op.result) or filter(None, args): + for arg in args: + if arg is not None: + changed = arg.setchanges() + self.handle_changed(changed) + changed = arg.setescapes() + self.handle_changed(changed) + #raise NotImplementedError("can't handle %s" % (op.opname, )) #print "assuming that '%s' is irrelevant" % op - return - res = opimpl(op, *args) - self.setstate(op.result, res) def complete(self): while self.scheduled: @@ -235,10 +237,18 @@ # _____________________________________________________________________ # operation implementations - def op_malloc(self, op, typestate): + def op_malloc(self, op, typestate, flagsstate): + assert flagsstate is None + flags = op.args[1].value + if flags != {'flavor': 'gc'}: + return NotImplemented return VarState(self.get_creationpoint(op.result, "malloc")) - def op_malloc_varsize(self, op, typestate, lengthstate): + def op_malloc_varsize(self, op, typestate, flagsstate, lengthstate): + assert flagsstate is None + flags = op.args[1].value + if flags != {'flavor': 'gc'}: + return NotImplemented return VarState(self.get_creationpoint(op.result, "malloc_varsize")) def op_keepalive(self, op, state): @@ -391,8 +401,9 @@ if not crep.escapes: if block not in loop_blocks: print "moving object from heap to stack %s in %s" % (op, graph.name) - op.opname = 'flavored_malloc' - op.args.insert(0, inputconst(lltype.Void, 'stack')) + flags = op.args[1].value + assert flags == {'flavor': 'gc'} + op.args[1] = Constant({'flavor': 'stack'}, lltype.Void) else: print "%s in %s is a non-escaping malloc in a loop" % (op, graph.name) Modified: pypy/dist/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/malloc.py Sun Aug 5 00:42:12 2007 @@ -32,6 +32,12 @@ def __init__(self, verbose=True): self.verbose = verbose + def check_malloc(self, op): + return op.opname == self.MALLOC_OP + + def recreate_malloc(self, c, v): + return SpaceOperation(self.MALLOC_OP, [c], v) + def get_STRUCT(self, TYPE): raise NotImplementedError @@ -89,7 +95,7 @@ if c.value == op.args[0].value: progress = False # replacing a malloc with # the same malloc! - newop = SpaceOperation(self.MALLOC_OP, [c], v) + newop = self.recreate_malloc(c, v) self.newops.append(newop) newvarsmap[key] = v count[0] += progress @@ -191,7 +197,7 @@ if cp[0] != "op": return False op = cp[2] - if op.opname != self.MALLOC_OP: + if not self.check_malloc(op): return False if not self.inline_type(op.args[0].value): return False @@ -282,7 +288,7 @@ # look for variables created inside the block by a malloc vars_created_here = [] for op in block.operations: - if op.opname == self.MALLOC_OP and op.result in vars: + if self.check_malloc(op) and op.result in vars: vars_created_here.append(op.result) for var in vars_created_here: self.flowin(block, count, var, newvarsmap=None) @@ -333,6 +339,19 @@ "setarrayitem", "getarraysubstruct"]) + def check_malloc(self, op): + if op.opname == 'malloc': + flags = op.args[1].value + if flags == {'flavor': 'gc'}: + return True + return False + + def recreate_malloc(self, c, v): + return SpaceOperation(self.MALLOC_OP, [c, + Constant({'flavor': 'gc'}, + lltype.Void)], + v) + def get_STRUCT(self, TYPE): STRUCT = TYPE.TO assert isinstance(STRUCT, lltype.GcStruct) Modified: pypy/dist/pypy/translator/backendopt/mallocprediction.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/mallocprediction.py (original) +++ pypy/dist/pypy/translator/backendopt/mallocprediction.py Sun Aug 5 00:42:12 2007 @@ -17,6 +17,9 @@ if op.opname == 'malloc': STRUCT = op.args[0].value # must not remove mallocs of structures that have a RTTI with a destructor + flags = op.args[1].value + if flags != {'flavor': 'gc'}: + continue try: destr_ptr = lltype.getRuntimeTypeInfo( STRUCT)._obj.destructor_funcptr Modified: pypy/dist/pypy/translator/backendopt/test/test_escape.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_escape.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_escape.py Sun Aug 5 00:42:12 2007 @@ -4,6 +4,8 @@ from pypy.rpython.llinterp import LLInterpreter from pypy.rlib.objectmodel import instantiate +import py + def build_adi(function, types): t = TranslationContext() t.buildannotator().build_types(function, types) @@ -26,7 +28,8 @@ if must_remove: for block in graph.iterblocks(): for op in block.operations: - assert op.opname != "malloc" + if op.opname == "malloc": + assert op.args[1].value['flavor'] == 'stack' res = interp.eval_graph(graph, args) assert res == expected_result return t @@ -382,6 +385,7 @@ t, adi, graph = build_adi(entrypoint, [int]) def test_extfunc_onheaparg(): + py.test.skip("not a valid test anymore") import os def f(i): s = str(i) Modified: pypy/dist/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/exceptiontransform.py Sun Aug 5 00:42:12 2007 @@ -355,10 +355,8 @@ insert_zeroing_op = False if spaceop.opname == 'malloc': - insert_zeroing_op = True - elif spaceop.opname == 'flavored_malloc': - flavor = spaceop.args[0].value - if flavor.startswith('gc'): + flavor = spaceop.args[1].value['flavor'] + if flavor == 'gc': insert_zeroing_op = True if insert_zeroing_op: Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Sun Aug 5 00:42:12 2007 @@ -527,90 +527,21 @@ esize = self.expr(op.args[0]) return "OP_RAW_MALLOC(%s, %s, void *);" % (esize, eresult) - def OP_FLAVORED_MALLOC(self, op): - # XXX this function should DIE! - TYPE = self.lltypemap(op.result).TO - typename = self.db.gettype(TYPE) + def OP_STACK_MALLOC(self, op): eresult = self.expr(op.result) - esize = 'sizeof(%s)' % cdecl(typename, '') - erestype = cdecl(typename, '*') - flavor = op.args[0].value - if flavor == "raw": - return "OP_RAW_MALLOC(%s, %s, %s);" % (esize, eresult, erestype) - elif flavor == "stack": - return "OP_STACK_MALLOC(%s, %s, %s);" % (esize, eresult, erestype) - elif flavor == "cpy": - cpytype = self.expr(op.args[2]) - return "OP_CPY_MALLOC(%s, %s, %s);" % (cpytype, eresult, erestype) - else: - raise NotImplementedError + esize = self.expr(op.args[0]) + return "OP_STACK_MALLOC(%s, %s, void *);" % (esize, eresult) - def OP_FLAVORED_MALLOC_VARSIZE(self, op): - # XXX this function should DIE!, at least twice over - # XXX I know this working in just one case, probably makes - # sense to assert it here, rest is just copied - flavor = op.args[0].value - assert flavor == 'raw' + def OP_CPY_MALLOC(self, op): TYPE = self.lltypemap(op.result).TO - assert isinstance(TYPE, Array) - assert TYPE._hints.get('nolength', False) - # typename = self.db.gettype(TYPE) - lenfld = 'length' - nodedef = self.db.gettypedefnode(TYPE) - if isinstance(TYPE, Struct): - arfld = TYPE._arrayfld - lenfld = "%s.length" % nodedef.c_struct_field_name(arfld) - VARPART = TYPE._flds[TYPE._arrayfld] - else: - VARPART = TYPE - assert isinstance(VARPART, Array) - itemtypename = self.db.gettype(VARPART.OF) - elength = self.expr(op.args[2]) - eresult = self.expr(op.result) erestype = cdecl(typename, '*') - if VARPART.OF is Void: # strange - esize = 'sizeof(%s)' % (cdecl(typename, ''),) - result = '{\n' - else: - itemtype = cdecl(itemtypename, '') - result = 'IF_VARSIZE_OVERFLOW(%s, %s, %s)\nelse {\n' % ( - elength, - itemtype, - eresult) - esize = 'sizeof(%s)-sizeof(%s)+%s*sizeof(%s)' % ( - cdecl(typename, ''), - itemtype, - elength, - itemtype) - - # ctypes Arrays have no length field - if not VARPART._hints.get('nolength', False): - result += '\nif(%s) %s->%s = %s;' % (eresult, eresult, lenfld, elength) - if flavor == "raw": - result += "OP_RAW_MALLOC(%s, %s, %s);" % (esize, eresult, erestype) - elif flavor == "stack": - result += "OP_STACK_MALLOC(%s, %s, %s);" % (esize, eresult, erestype) - elif flavor == "cpy": - xxx # this will never work, as I don't know which arg it would be - # tests, tests, tests.... - cpytype = self.expr(op.args[2]) - result += "OP_CPY_MALLOC(%s, %s, %s);" % (cpytype, eresult, erestype) - else: - raise NotImplementedError - - result += '\n}' - return result - - def OP_FLAVORED_FREE(self, op): - flavor = op.args[0].value - if flavor == "raw": - return "OP_RAW_FREE(%s, %s)" % (self.expr(op.args[1]), - self.expr(op.result)) - elif flavor == "cpy": - return "OP_CPY_FREE(%s)" % (self.expr(op.args[1]),) - else: - raise NotImplementedError + eresult = self.expr(op.result) + cpytype = self.expr(op.args[1]) + return "OP_CPY_MALLOC(%s, %s, %s);" % (cpytype, eresult, erestype) + + def OP_CPY_FREE(self, op): + return "OP_CPY_FREE(%s)" % (self.expr(op.args[1]),) def OP_DIRECT_FIELDPTR(self, op): return self.OP_GETFIELD(op, ampersand='&') Modified: pypy/dist/pypy/translator/c/src/mem.h ============================================================================== --- pypy/dist/pypy/translator/c/src/mem.h (original) +++ pypy/dist/pypy/translator/c/src/mem.h Sun Aug 5 00:42:12 2007 @@ -43,39 +43,12 @@ #define OP_STACK_MALLOC(size,r,restype) \ r = (restype) alloca(size); \ - if (r == NULL) FAIL_EXCEPTION(PyExc_MemoryError, "out of memory"); \ - memset((void*) r, 0, size); - + if (r != NULL) memset((void*) r, 0, size); + #define OP_RAW_MEMCOPY(x,y,size,r) memcpy(y,x,size); /************************************************************/ -/* a reasonably safe bound on the largest allowed argument value - that we can pass to malloc. This is used for var-sized mallocs - to compute the largest allowed number of items in the array. */ -#define MAXIMUM_MALLOCABLE_SIZE (LONG_MAX-4096) - -#define IF_VARSIZE_OVERFLOW(numitems, itemtype, r) \ - if (((unsigned long)(numitems)) > \ - (MAXIMUM_MALLOCABLE_SIZE / sizeof(itemtype))) { \ - FAIL_EXCEPTION(PyExc_MemoryError, "addr space overflow"); \ - r = NULL; \ - } -/* else { ...} -- generated by funcgen.py */ - -#if RAW_MALLOC_ZERO_FILLED - -#define OP_ZERO_MALLOC OP_RAW_MALLOC - -#else - -#define OP_ZERO_MALLOC(size, r, restype) { \ - OP_RAW_MALLOC(size, r, restype); \ - if (r != NULL) OP_RAW_MEMCLEAR(r, size, /* */); \ - } - -#endif - #define OP_FREE(p) OP_RAW_FREE(p, do_not_use) /*------------------------------------------------------------*/ Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Sun Aug 5 00:42:12 2007 @@ -152,10 +152,8 @@ def __init__(self, stackless_gc=False, transformer=None): self.frametypes = {} self.stackless_gc = stackless_gc - self.c_gc_nocollect = model.Constant("gc_nocollect", lltype.Void) self.transformer = transformer - def _key_for_types(self, TYPES): counts = {} for EXACT_TYPE in TYPES: @@ -173,16 +171,13 @@ save_block = model.Block([v_exception, v_restart]) llops = LowLevelOpList() + flags = {'flavor': 'gc'} if self.stackless_gc: - v_state = llops.genop( - 'flavored_malloc', - [self.c_gc_nocollect, model.Constant(FRAME_TYPE, lltype.Void)], - resulttype=lltype.Ptr(FRAME_TYPE)) - else: - v_state = llops.genop( - 'malloc', - [model.Constant(FRAME_TYPE, lltype.Void)], - resulttype=lltype.Ptr(FRAME_TYPE)) + flags['nocollect'] = True + v_state = llops.genop('malloc', + [model.Constant(FRAME_TYPE, lltype.Void), + model.Constant(flags, lltype.Void)], + resulttype=lltype.Ptr(FRAME_TYPE)) for fieldname in FRAME_TYPE._names[1:]: # skip the 'header' field v_arg = varoftype(FRAME_TYPE._flds[fieldname]) @@ -263,7 +258,12 @@ return True elif op.opname == 'resume_state_create': return True - return self.stackless_gc and LL_OPERATIONS[op.opname].canunwindgc + if self.stackless_gc: + if op.opname in ('malloc', 'malloc_varsize'): + flags = op.args[1].value + return flags['flavor'] == 'gc' and not flags.get('nocollect', False) + return LL_OPERATIONS[op.opname].canunwindgc + return False def analyze_external_call(self, op): callable = op.args[0].value._obj._callable @@ -452,7 +452,7 @@ self.c_minus_one = model.Constant(-1, lltype.Signed) self.c_null_state = model.Constant(null_state, lltype.typeOf(null_state)) - self.c_gc_nocollect = model.Constant("gc_nocollect", lltype.Void) + self.c_gc_nocollect = model.Constant({'flavor': 'gc', 'nocollect': True}, lltype.Void) self.is_finished = False @@ -662,7 +662,8 @@ # it to the saving function, then read the thus created state # out of and then clear global_state.top c_EXC = model.Constant(self.unwind_exception_type.TO, lltype.Void) - v_exc = llops.genop('malloc', [c_EXC], + c_flags = model.Constant({'flavor': 'gc'}, lltype.Void) + v_exc = llops.genop('malloc', [c_EXC, c_flags], resulttype = self.unwind_exception_type) realvarsforcall = [] @@ -1177,7 +1178,7 @@ for block in graph.iterblocks(): for i, op in enumerate(block.operations): if op.opname.startswith('malloc'): - newop = model.SpaceOperation('flavored_' + op.opname, - [self.c_gc_nocollect]+op.args, - op.result) + newargs = op.args[:] + newargs[1] = self.c_gc_nocollect + newop = model.SpaceOperation(op.opname, newargs, op.result) block.operations[i] = newop From pedronis at codespeak.net Sun Aug 5 00:54:50 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 5 Aug 2007 00:54:50 +0200 (CEST) Subject: [pypy-svn] r45488 - pypy/dist/pypy/doc Message-ID: <20070804225450.A083380C7@code0.codespeak.net> Author: pedronis Date: Sun Aug 5 00:54:50 2007 New Revision: 45488 Modified: pypy/dist/pypy/doc/cleanup-todo.txt Log: update with next steps regarding gc/mem mgmt stuff Modified: pypy/dist/pypy/doc/cleanup-todo.txt ============================================================================== --- pypy/dist/pypy/doc/cleanup-todo.txt (original) +++ pypy/dist/pypy/doc/cleanup-todo.txt Sun Aug 5 00:54:50 2007 @@ -13,11 +13,8 @@ - geninterp is a hack - keepalives need to die, finally - change weakrefs to work together with the GC - - delegate finding type stuff like vtables etc to GC - - clean up the tangle of how the various mallocs are implemented - and responsability distributed acrosss headers, policies, backends, - and the gctransfomers, which varies depending on the GC :(, - exploit better the removal of zeroing assumption + - delegate finding type stuff like vtables etc to GC, cleaner interface for rtti, + simplify translator/c/gc.py - clean up the tangle of including headers in the C backend - make approach for loading modules more sane, mixedmodule capture too many platform dependecies especially for pypy-cli From pedronis at codespeak.net Sun Aug 5 09:42:17 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 5 Aug 2007 09:42:17 +0200 (CEST) Subject: [pypy-svn] r45495 - pypy/dist/pypy/jit/codegen Message-ID: <20070805074217.9810880B2@code0.codespeak.net> Author: pedronis Date: Sun Aug 5 09:42:16 2007 New Revision: 45495 Modified: pypy/dist/pypy/jit/codegen/graph2rgenop.py Log: fix the little breakage I introduced, not too bad. I forgot about this one Modified: pypy/dist/pypy/jit/codegen/graph2rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/graph2rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/graph2rgenop.py Sun Aug 5 09:42:16 2007 @@ -120,6 +120,8 @@ def generate_operation(rgenop, builder, op, var2gv): # XXX only supports some operations for now if op.opname == 'malloc': + flags = op.args[1].value + assert flags['flavor'] == 'gc' token = rgenop.allocToken(op.args[0].value) gv_result = builder.genop_malloc_fixedsize(token) elif op.opname == 'getfield': @@ -134,9 +136,11 @@ var2gv(op.args[0]), var2gv(op.args[2])) elif op.opname == 'malloc_varsize': + flags = op.args[1].value + assert flags['flavor'] == 'gc' token = rgenop.varsizeAllocToken(op.args[0].value) gv_result = builder.genop_malloc_varsize(token, - var2gv(op.args[1])) + var2gv(op.args[2])) elif op.opname == 'getarrayitem': token = rgenop.arrayToken(op.args[0].concretetype.TO) gv_result = builder.genop_getarrayitem(token, From pedronis at codespeak.net Sun Aug 5 09:49:36 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 5 Aug 2007 09:49:36 +0200 (CEST) Subject: [pypy-svn] r45496 - in pypy/dist/pypy/translator/llvm: . test Message-ID: <20070805074936.3517380B2@code0.codespeak.net> Author: pedronis Date: Sun Aug 5 09:49:35 2007 New Revision: 45496 Modified: pypy/dist/pypy/translator/llvm/opwriter.py pypy/dist/pypy/translator/llvm/test/test_lladdresses.py Log: as usual not sure what to do about the LLVM backend, some ops are not needed anymore. stack_malloc would need adding. Freeing stack allocated objects doesn't make much sense tough, change the test. Modified: pypy/dist/pypy/translator/llvm/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm/opwriter.py Sun Aug 5 09:49:35 2007 @@ -289,6 +289,7 @@ # ha, ha pass + # XXX not needed anymore def flavored_malloc(self, opr): flavor = opr.op.args[0].value type_ = opr.rettype[:-1] #XXX stripping of * @@ -318,6 +319,7 @@ self.codewriter.comment('***Skipping free of stack allocated data') else: raise NotImplementedError + # XXX /not needed anymore def call_boehm_gc_alloc(self, opr): word = self.db.get_machine_word() Modified: pypy/dist/pypy/translator/llvm/test/test_lladdresses.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_lladdresses.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_lladdresses.py Sun Aug 5 09:49:35 2007 @@ -132,7 +132,6 @@ def f(x): a = A(x + 1) result = a.val - free_non_gc_object(a) return result fn = compile_function(f, [int]) assert fn(1) == 2 From arigo at codespeak.net Sun Aug 5 14:38:59 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 5 Aug 2007 14:38:59 +0200 (CEST) Subject: [pypy-svn] r45498 - in pypy/dist/pypy: module/posix translator/c/src translator/cli/src translator/cli/test Message-ID: <20070805123859.E468A80B3@code0.codespeak.net> Author: arigo Date: Sun Aug 5 14:38:57 2007 New Revision: 45498 Modified: pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/cli/src/ (props changed) pypy/dist/pypy/translator/cli/src/ll_os.cs pypy/dist/pypy/translator/cli/test/test_builtin.py Log: Move away from ros.opendir/readdir/closedir and use os.listdir() directly in PyPy's Posix module - now supported by the CLI backend too. Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Sun Aug 5 14:38:57 2007 @@ -287,16 +287,6 @@ unsetenv.unwrap_spec = [ObjSpace, str] -def enumeratedir(space, dir): - result = [] - while True: - nextentry = dir.readdir() - if nextentry is None: - break - if nextentry not in ('.' , '..'): - result.append(space.wrap(nextentry)) - return space.newlist(result) - def listdir(space, dirname): """Return a list containing the names of the entries in the directory. @@ -305,15 +295,11 @@ The list is in arbitrary order. It does not include the special entries '.' and '..' even if they are present in the directory.""" try: - dir = ros.opendir(dirname) - except OSError, e: - raise wrap_oserror(space, e) - try: - # sub-function call to make sure that 'try:finally:' will catch - # everything including MemoryErrors - return enumeratedir(space, dir) - finally: - dir.closedir() + result = os.listdir(dirname) + except OSError, e: + raise wrap_oserror(space, e) + result_w = [space.wrap(s) for s in result] + return space.newlist(result_w) listdir.unwrap_spec = [ObjSpace, str] def pipe(space): Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Sun Aug 5 14:38:57 2007 @@ -423,6 +423,7 @@ } /******************** opendir/readdir/closedir ********************/ +/* XXX old interface no longer used in PyPy, will be removed at some point */ #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) /* emulation of opendir, readdir, closedir */ @@ -450,6 +451,7 @@ char arg[1]; /*also used as flag */ } DIR; +/* XXX old interface no longer used in PyPy, will be removed at some point */ static DIR *opendir(char *dirname) { int lng = strlen(dirname); @@ -473,6 +475,7 @@ return d; } +/* XXX old interface no longer used in PyPy, will be removed at some point */ static struct dirent *readdir(DIR *d) { if (d->arg[0]) @@ -489,6 +492,7 @@ return d->d_name ? d : NULL; } +/* XXX old interface no longer used in PyPy, will be removed at some point */ static int closedir(DIR *d) { HANDLE hFind = d->hFind; @@ -503,6 +507,7 @@ #endif /* defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) */ +/* XXX old interface no longer used in PyPy, will be removed at some point */ struct RPyOpaque_DIR *LL_os_opendir(RPyString *dirname) { DIR *dir = opendir(RPyString_AsString(dirname)); @@ -511,6 +516,7 @@ return (struct RPyOpaque_DIR *) dir; } +/* XXX old interface no longer used in PyPy, will be removed at some point */ RPyString *LL_os_readdir(struct RPyOpaque_DIR *dir) { struct dirent *d; @@ -523,6 +529,7 @@ return NULL; } +/* XXX old interface no longer used in PyPy, will be removed at some point */ void LL_os_closedir(struct RPyOpaque_DIR *dir) { if (closedir((DIR *) dir) < 0) Modified: pypy/dist/pypy/translator/cli/src/ll_os.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/ll_os.cs (original) +++ pypy/dist/pypy/translator/cli/src/ll_os.cs Sun Aug 5 14:38:57 2007 @@ -463,6 +463,25 @@ Helpers.raise_OSError(Errno.EPERM); // this is only a stub } + public static pypy.runtime.List ll_os_listdir(string path) + { + if (path == "") + Helpers.raise_OSError(Errno.ENOENT); + + DirectoryInfo dir = new DirectoryInfo(path); + if (!dir.Exists) + Helpers.raise_OSError(Errno.ENOENT); + + pypy.runtime.List names = new pypy.runtime.List(); + foreach(DirectoryInfo d in dir.GetDirectories()) + names.Add(d.Name); + foreach(FileInfo f in dir.GetFiles()) + names.Add(f.Name); + + return names; + } + + /* XXX old interface, will be removed at some point */ public static object ll_os_opendir(string path) { if (path == "") @@ -481,6 +500,7 @@ return names.GetEnumerator(); } + /* XXX old interface, will be removed at some point */ public static string ll_os_readdir(object obj) { IEnumerator names = (IEnumerator)obj; @@ -490,6 +510,7 @@ return null; } + /* XXX old interface, will be removed at some point */ public static void ll_os_closedir(object obj) { } Modified: pypy/dist/pypy/translator/cli/test/test_builtin.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_builtin.py (original) +++ pypy/dist/pypy/translator/cli/test/test_builtin.py Sun Aug 5 14:38:57 2007 @@ -1,6 +1,7 @@ import platform import os, stat, errno import py +from py.builtin import sorted from pypy.tool import udir from pypy.translator.cli.test.runtest import CliTest from pypy.rpython.test.test_rbuiltin import BaseTestRbuiltin @@ -105,18 +106,9 @@ res = self.ll_to_string(self.interpret(fn, [])) # XXX assert something about res - def test_os_opendir(self): - from pypy.rlib import ros + def test_os_listdir(self): def fn(): - d = ros.opendir('.') - res = [] - while True: - current = d.readdir() - if current is None: - break - res.append(current) - d.closedir() - return res + return os.listdir('.') res = self.ll_to_list(self.interpret(fn, [])) res = [self.ll_to_string(s) for s in res] res.sort() From arigo at codespeak.net Sun Aug 5 14:47:53 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 5 Aug 2007 14:47:53 +0200 (CEST) Subject: [pypy-svn] r45499 - pypy/dist/pypy/translator/benchmark Message-ID: <20070805124753.92A248091@code0.codespeak.net> Author: arigo Date: Sun Aug 5 14:47:52 2007 New Revision: 45499 Added: pypy/dist/pypy/translator/benchmark/conftest.py (contents, props changed) Log: Exclude from py.test runs the subdirectories added by 'svn co' from benchmarks.py. Added: pypy/dist/pypy/translator/benchmark/conftest.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/benchmark/conftest.py Sun Aug 5 14:47:52 2007 @@ -0,0 +1,7 @@ +import py + +class Directory(py.test.collect.Directory): + + def recfilter(self, path): + # exclude the subdirectories added by 'svn co' from benchmarks.py + return path.check(basename='test') From arigo at codespeak.net Sun Aug 5 15:01:19 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 5 Aug 2007 15:01:19 +0200 (CEST) Subject: [pypy-svn] r45500 - pypy/dist/pypy/rpython/module Message-ID: <20070805130119.242A7809A@code0.codespeak.net> Author: arigo Date: Sun Aug 5 15:01:18 2007 New Revision: 45500 Modified: pypy/dist/pypy/rpython/module/ll_os.py Log: Only use charp2str() on pointers of type exactly CCHARP. Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Sun Aug 5 15:01:18 2007 @@ -407,7 +407,8 @@ if not direntp: error = rffi.c_errno break - name = rffi.charp2str(direntp.c_d_name) + namep = rffi.cast(rffi.CCHARP, direntp.c_d_name) + name = rffi.charp2str(namep) if name != '.' and name != '..': result.append(name) os_closedir(dirp) From arigo at codespeak.net Sun Aug 5 15:56:38 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 5 Aug 2007 15:56:38 +0200 (CEST) Subject: [pypy-svn] r45501 - pypy/dist/pypy/translator/c/test Message-ID: <20070805135638.5A83480B0@code0.codespeak.net> Author: arigo Date: Sun Aug 5 15:56:37 2007 New Revision: 45501 Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py Log: Another test. Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Sun Aug 5 15:56:37 2007 @@ -708,12 +708,13 @@ result = os.listdir(s) return '/'.join(result) func = compile(mylistdir, [str]) - result = func(str(udir)) - result = result.split('/') - result.sort() - compared_with = os.listdir(str(udir)) - compared_with.sort() - assert result == compared_with + for testdir in [str(udir), os.curdir]: + result = func(testdir) + result = result.split('/') + result.sort() + compared_with = os.listdir(testdir) + compared_with.sort() + assert result == compared_with if hasattr(posix, 'execv'): def test_execv(): From arigo at codespeak.net Sun Aug 5 16:08:21 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 5 Aug 2007 16:08:21 +0200 (CEST) Subject: [pypy-svn] r45502 - pypy/dist/pypy/translator/c/test Message-ID: <20070805140821.0133680B8@code0.codespeak.net> Author: arigo Date: Sun Aug 5 16:08:21 2007 New Revision: 45502 Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py Log: Finally a test that shows why os.listdir() is broken in pypy-c. Fixing now... Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Sun Aug 5 16:08:21 2007 @@ -704,7 +704,14 @@ assert result == compared_with def test_listdir(): + py.test.skip("in-progress") def mylistdir(s): + try: + os.listdir('this/directory/really/cannot/exist') + except OSError: + pass + else: + raise AssertionError("should have failed!") result = os.listdir(s) return '/'.join(result) func = compile(mylistdir, [str]) From arigo at codespeak.net Sun Aug 5 17:03:23 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 5 Aug 2007 17:03:23 +0200 (CEST) Subject: [pypy-svn] r45503 - pypy/dist/pypy/translator/cli Message-ID: <20070805150323.E5F4680BA@code0.codespeak.net> Author: arigo Date: Sun Aug 5 17:03:23 2007 New Revision: 45503 Modified: pypy/dist/pypy/translator/cli/ (props changed) Log: svn:ignore this file. From arigo at codespeak.net Sun Aug 5 17:05:23 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 5 Aug 2007 17:05:23 +0200 (CEST) Subject: [pypy-svn] r45504 - in pypy/dist/pypy: rpython/lltypesystem rpython/lltypesystem/test rpython/module translator/c translator/c/test Message-ID: <20070805150523.B4CBF80BA@code0.codespeak.net> Author: arigo Date: Sun Aug 5 17:05:22 2007 New Revision: 45504 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/primitive.py pypy/dist/pypy/translator/c/test/test_extfunc.py Log: Fix the issue with os.listdir() by changing the rffi.c_errno hack into a different hack. We need to clean it up at some point. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Sun Aug 5 17:05:22 2007 @@ -3,6 +3,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.lltypesystem import ll2ctypes from pypy.annotation.model import lltype_to_annotation +from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic from pypy.rlib import rarithmetic import os @@ -108,7 +109,25 @@ hints['getsize'] = lazy_getsize return lltype.Ptr(lltype.OpaqueType(name, hints)) -c_errno = CConstant('errno', lltype.Signed) +def CExternVariable(TYPE, name): + """Return a pair of functions - a getter and a setter - to access + the given global C variable. + """ + # XXX THIS IS ONLY A QUICK HACK TO MAKE IT WORK + # In general, we need to re-think a few things to be more consistent, + # e.g. what if a CStruct, COpaque or CExternVariable requires + # some #include... + assert not isinstance(TYPE, lltype.ContainerType) + CTYPE = lltype.FixedSizeArray(TYPE, 1) + c_variable_ref = CConstant('(&%s)' % (name,), lltype.Ptr(CTYPE)) + def getter(): + return c_variable_ref[0] + def setter(newvalue): + c_variable_ref[0] = newvalue + return (func_with_new_name(getter, '%s_getter' % (name,)), + func_with_new_name(setter, '%s_setter' % (name,))) + +get_errno, set_errno = CExternVariable(lltype.Signed, 'errno') # char, represented as a Python character # (use SIGNEDCHAR or UCHAR for the small integer types) Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Sun Aug 5 17:05:22 2007 @@ -144,21 +144,22 @@ fn = compile(f, [], backendopt=False) assert fn() == 8 -def test_constant(): +def test_externvar(): import os def f(): - return c_errno + set_errno(12) + return get_errno() def g(): try: os.write(12312312, "xxx") except OSError: pass - return c_errno + return get_errno() fn = compile(f, []) - assert fn() == 0 + assert fn() == 12 gn = compile(g, []) import errno assert gn() == errno.EBADF Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Sun Aug 5 17:05:22 2007 @@ -32,7 +32,7 @@ def c_func_lltypeimpl(): res = c_func() if res == -1: - raise OSError(rffi.c_errno, "%s failed" % name) + raise OSError(rffi.get_errno(), "%s failed" % name) return res c_func_lltypeimpl.func_name = name + '_llimpl' @@ -51,7 +51,7 @@ os_execv(l_path, l_args) rffi.free_charpp(l_args) rffi.free_charp(l_path) - raise OSError(rffi.c_errno, "execv failed") + raise OSError(rffi.get_errno(), "execv failed") self.register(os.execv, [str, [str]], s_ImpossibleValue, llimpl= execv_lltypeimpl, export_name="ll_os.ll_os_execv") @@ -63,7 +63,7 @@ def dup_lltypeimpl(fd): newfd = rffi.cast(lltype.Signed, os_dup(rffi.cast(rffi.INT, fd))) if newfd == -1: - raise OSError(rffi.c_errno, "dup failed") + raise OSError(rffi.get_errno(), "dup failed") return newfd self.register(os.dup, [int], int, llimpl=dup_lltypeimpl, @@ -77,7 +77,7 @@ error = rffi.cast(lltype.Signed, os_dup2(rffi.cast(rffi.INT, fd), rffi.cast(rffi.INT, newfd))) if error == -1: - raise OSError(rffi.c_errno, "dup2 failed") + raise OSError(rffi.get_errno(), "dup2 failed") self.register(os.dup2, [int, int], s_None, llimpl=dup2_lltypeimpl, export_name="ll_os.ll_os_dup2") @@ -99,7 +99,7 @@ lltype.nullptr(UTIMEBUFP.TO))) rffi.free_charp(l_path) if error == -1: - raise OSError(rffi.c_errno, "utime_null failed") + raise OSError(rffi.get_errno(), "utime_null failed") self.register(ros.utime_null, [str], s_None, "ll_os.utime_null", llimpl=utime_null_lltypeimpl) @@ -115,7 +115,7 @@ rffi.free_charp(l_path) lltype.free(l_utimebuf, flavor='raw') if error == -1: - raise OSError(rffi.c_errno, "utime_tuple failed") + raise OSError(rffi.get_errno(), "utime_tuple failed") self.register(ros.utime_tuple, [str, (float, float)], s_None, "ll_os.utime_tuple", @@ -130,7 +130,7 @@ def setsid_lltypeimpl(): result = rffi.cast(lltype.Signed, os_setsid()) if result == -1: - raise OSError(rffi.c_errno, "os_setsid failed") + raise OSError(rffi.get_errno(), "os_setsid failed") return result self.register(os.setsid, [], int, export_name="ll_os.ll_os_setsid", @@ -165,7 +165,7 @@ l_utsbuf = lltype.malloc(UTSNAMEP.TO, flavor='raw') result = os_uname(l_utsbuf) if result == -1: - raise OSError(rffi.c_errno, "os_uname failed") + raise OSError(rffi.get_errno(), "os_uname failed") fields = [l_utsbuf.c_sysname, l_utsbuf.c_nodename, l_utsbuf.c_release, l_utsbuf.c_version, l_utsbuf.c_machine] @@ -209,7 +209,7 @@ rffi.cast(mode_t, mode))) rffi.free_charp(l_path) if result == -1: - raise OSError(rffi.c_errno, "os_open failed") + raise OSError(rffi.get_errno(), "os_open failed") return result def os_open_oofakeimpl(o_path, flags, mode): @@ -233,7 +233,7 @@ got = rffi.cast(lltype.Signed, os_read(rffi.cast(rffi.INT, fd), inbuf, rffi.cast(rffi.SIZE_T, count))) if got < 0: - raise OSError(rffi.c_errno, "os_read failed") + raise OSError(rffi.get_errno(), "os_read failed") # XXX too many copies of the data! l = [inbuf[i] for i in range(got)] finally: @@ -275,7 +275,7 @@ rffi.cast(rffi.INT, fd), outbuf, rffi.cast(rffi.SIZE_T, count))) if written < 0: - raise OSError(rffi.c_errno, "os_write failed") + raise OSError(rffi.get_errno(), "os_write failed") finally: lltype.free(outbuf, flavor='raw') return written @@ -300,7 +300,7 @@ def close_lltypeimpl(fd): error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd))) if error == -1: - raise OSError(rffi.c_errno, "close failed") + raise OSError(rffi.get_errno(), "close failed") self.register(os.close, [int], s_None, llimpl=close_lltypeimpl, export_name="ll_os.ll_os_close", oofakeimpl=os.close) @@ -338,7 +338,7 @@ res = os_getcwd(buf, rffi.cast(rffi.SIZE_T, bufsize)) if res: break # ok - error = rffi.c_errno + error = rffi.get_errno() lltype.free(buf, flavor='raw') if error != errno.ERANGE: raise OSError(error, "getcwd failed") @@ -400,12 +400,13 @@ dirp = os_opendir(path) rffi.free_charp(path) if not dirp: - raise OSError(rffi.c_errno, "os_opendir failed") + raise OSError(rffi.get_errno(), "os_opendir failed") + rffi.set_errno(0) result = [] while True: direntp = os_readdir(dirp) if not direntp: - error = rffi.c_errno + error = rffi.get_errno() break namep = rffi.cast(rffi.CCHARP, direntp.c_d_name) name = rffi.charp2str(namep) @@ -465,7 +466,7 @@ def ttyname_lltypeimpl(fd): l_name = os_ttyname(fd) if not l_name: - raise OSError(rffi.c_errno, "ttyname raised") + raise OSError(rffi.get_errno(), "ttyname raised") return rffi.charp2str(l_name) self.register(os.ttyname, [int], str, "ll_os.ttyname", Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Sun Aug 5 17:05:22 2007 @@ -4,6 +4,7 @@ ContainerType, OpaqueType, FixedSizeArray, _uninitialized from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.llmemory import Address +from pypy.rpython.lltypesystem.rffi import CConstant from pypy.tool.sourcetools import valid_identifier from pypy.translator.c.primitive import PrimitiveName, PrimitiveType from pypy.translator.c.primitive import PrimitiveErrorValue @@ -168,6 +169,8 @@ else: raise Exception("don't know about %r" % (T,)) else: + if isinstance(obj, CConstant): + return obj.c_name # without further checks T = typeOf(obj) if isinstance(T, Primitive): return PrimitiveName[T](obj, self) Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Sun Aug 5 17:05:22 2007 @@ -1,7 +1,6 @@ import sys from pypy.rlib.objectmodel import Symbolic, ComputedIntSymbolic from pypy.rlib.objectmodel import CDefinedIntSymbolic -from pypy.rpython.lltypesystem.rffi import CConstant from pypy.rpython.lltypesystem.lltype import * from pypy.rpython.lltypesystem.llmemory import Address, \ AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \ @@ -48,8 +47,6 @@ return str(value.expr) elif isinstance(value, ComputedIntSymbolic): value = value.compute_fn() - elif isinstance(value, CConstant): - return value.c_name else: raise Exception("unimplemented symbolic %r"%value) if value is None: Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Sun Aug 5 17:05:22 2007 @@ -704,7 +704,6 @@ assert result == compared_with def test_listdir(): - py.test.skip("in-progress") def mylistdir(s): try: os.listdir('this/directory/really/cannot/exist') From arigo at codespeak.net Sun Aug 5 17:30:44 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 5 Aug 2007 17:30:44 +0200 (CEST) Subject: [pypy-svn] r45505 - pypy/dist/pypy/translator/sandbox Message-ID: <20070805153044.3670180B8@code0.codespeak.net> Author: arigo Date: Sun Aug 5 17:30:43 2007 New Revision: 45505 Modified: pypy/dist/pypy/translator/sandbox/rsandbox.py Log: Typos, RPython fixes. Modified: pypy/dist/pypy/translator/sandbox/rsandbox.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/rsandbox.py (original) +++ pypy/dist/pypy/translator/sandbox/rsandbox.py Sun Aug 5 17:30:43 2007 @@ -43,6 +43,7 @@ length -= count buf = lltype.direct_ptradd(lltype.direct_arrayitems(buf), count) buf = rffi.cast(rffi.CCHARP, buf) +writeall_not_sandboxed._annenforceargs_ = [int, rffi.CCHARP, int] def readall_not_sandboxed(fd, length): buf = lltype.malloc(rffi.CCHARP.TO, length, flavor='raw') @@ -57,6 +58,7 @@ p = lltype.direct_ptradd(lltype.direct_arrayitems(p), count) p = rffi.cast(rffi.CCHARP, p) return buf +readall_not_sandboxed._annenforceargs_ = [int, int] def buf2num(buf, index=0): c0 = ord(buf[index ]) @@ -106,7 +108,7 @@ try: return cache[FUNCTYPE.RESULT] except KeyError: - raise NotImplementedError("exernal function %r return type %s" % ( + raise NotImplementedError("external function %r return type %s" % ( namehint, FUNCTYPE.RESULT)) CFalse = CDefinedIntSymbolic('0') # hack hack From arigo at codespeak.net Mon Aug 6 10:32:23 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Aug 2007 10:32:23 +0200 (CEST) Subject: [pypy-svn] r45507 - pypy/dist/pypy/rpython/module/test Message-ID: <20070806083223.BFA6B8092@code0.codespeak.net> Author: arigo Date: Mon Aug 6 10:32:22 2007 New Revision: 45507 Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py Log: Skip currently failing test. Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_os.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_os.py Mon Aug 6 10:32:22 2007 @@ -120,6 +120,7 @@ def setup_class(cls): if not hasattr(os, 'ttyname'): py.test.skip("no ttyname") + py.test.skip("XXX get_errno() does not work with ll2ctypes") def test_ttyname(self): import os From antocuni at codespeak.net Mon Aug 6 10:59:36 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 6 Aug 2007 10:59:36 +0200 (CEST) Subject: [pypy-svn] r45508 - in pypy/dist/pypy: jit/timeshifter rpython rpython/memory/gctransform/test rpython/test translator translator/c translator/c/test Message-ID: <20070806085936.2E76F80CC@code0.codespeak.net> Author: antocuni Date: Mon Aug 6 10:59:35 2007 New Revision: 45508 Added: pypy/dist/pypy/translator/exceptiontransform.py - copied unchanged from r45507, pypy/dist/pypy/translator/c/exceptiontransform.py Removed: pypy/dist/pypy/translator/c/exceptiontransform.py Modified: pypy/dist/pypy/jit/timeshifter/oop.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/translator/c/test/test_exceptiontransform.py pypy/dist/pypy/translator/translator.py Log: port exceptiontransform to ootype, step #1: move exceptiontransform from translator/c to translator/ Modified: pypy/dist/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/oop.py (original) +++ pypy/dist/pypy/jit/timeshifter/oop.py Mon Aug 6 10:59:35 2007 @@ -2,7 +2,7 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.jit.timeshifter.rcontainer import cachedtype from pypy.jit.timeshifter import rvalue, rtimeshift -from pypy.translator.c import exceptiontransform +from pypy.translator import exceptiontransform from pypy.rlib.unroll import unrolling_iterable from pypy.tool.sourcetools import func_with_new_name Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon Aug 6 10:59:35 2007 @@ -312,7 +312,7 @@ tracer.dump('raise') exc_data.exc_type = lltype.typeOf(etype )._defl() exc_data.exc_value = lltype.typeOf(evalue)._defl() - from pypy.translator.c import exceptiontransform + from pypy.translator import exceptiontransform T = resultvar.concretetype errvalue = exceptiontransform.error_value(T) # check that the exc-transformed graph returns the error @@ -402,7 +402,7 @@ evalue = e.args[1] exc_data.exc_type = etype exc_data.exc_value = evalue - from pypy.translator.c import exceptiontransform + from pypy.translator import exceptiontransform retval = exceptiontransform.error_value( operation.result.concretetype) else: Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py Mon Aug 6 10:59:35 2007 @@ -3,7 +3,7 @@ from pypy.rpython.memory.gctransform.support import var_ispyobj from pypy.translator.backendopt.support import var_needsgc from pypy.translator.translator import TranslationContext, graphof -from pypy.translator.c.exceptiontransform import ExceptionTransformer +from pypy.translator.exceptiontransform import ExceptionTransformer from pypy.rpython.lltypesystem import lltype from pypy.objspace.flow.model import Variable from pypy.annotation import model as annmodel Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Mon Aug 6 10:59:35 2007 @@ -514,7 +514,7 @@ res = interp.eval_graph(graph, [1]) def test_half_exceptiontransformed_graphs(): - from pypy.translator.c import exceptiontransform + from pypy.translator import exceptiontransform def f1(x): if x < 0: raise ValueError @@ -564,7 +564,7 @@ assert res == 7 def test_exceptiontransformed_add_ovf(): - from pypy.translator.c import exceptiontransform + from pypy.translator import exceptiontransform def f(x, y): try: return ovfcheck(x + y) Modified: pypy/dist/pypy/translator/c/test/test_exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/test/test_exceptiontransform.py Mon Aug 6 10:59:35 2007 @@ -1,7 +1,8 @@ import py from pypy.translator.translator import TranslationContext, graphof from pypy.translator.simplify import join_blocks -from pypy.translator.c import exceptiontransform, genc, gc +from pypy.translator import exceptiontransform +from pypy.translator.c import genc, gc from pypy.objspace.flow.model import c_last_exception from pypy.rpython.test.test_llinterp import get_interpreter from pypy.translator.c.test.test_genc import compile Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Mon Aug 6 10:59:35 2007 @@ -113,7 +113,7 @@ raise ValueError("no rtyper") if self.exceptiontransformer is not None: return self.exceptiontransformer - from pypy.translator.c.exceptiontransform import ExceptionTransformer + from pypy.translator.exceptiontransform import ExceptionTransformer self.exceptiontransformer = ExceptionTransformer(self) return self.exceptiontransformer From antocuni at codespeak.net Mon Aug 6 11:01:34 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 6 Aug 2007 11:01:34 +0200 (CEST) Subject: [pypy-svn] r45509 - in pypy/dist/pypy/translator: c/test test Message-ID: <20070806090134.EE1BB80CC@code0.codespeak.net> Author: antocuni Date: Mon Aug 6 11:01:34 2007 New Revision: 45509 Added: pypy/dist/pypy/translator/test/test_exceptiontransform.py - copied unchanged from r45508, pypy/dist/pypy/translator/c/test/test_exceptiontransform.py Removed: pypy/dist/pypy/translator/c/test/test_exceptiontransform.py Log: port exceptiontransform to ootype, step #2: move test_exceptiontransform From jlg at codespeak.net Mon Aug 6 11:56:10 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 6 Aug 2007 11:56:10 +0200 (CEST) Subject: [pypy-svn] r45512 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070806095610.54FDB80DC@code0.codespeak.net> Author: jlg Date: Mon Aug 6 11:56:09 2007 New Revision: 45512 Modified: pypy/dist/pypy/lang/scheme/execution.py pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: OPERATION_MAP generated based on _symbol_name class atribute; macros tuning, most test are passing Modified: pypy/dist/pypy/lang/scheme/execution.py ============================================================================== --- pypy/dist/pypy/lang/scheme/execution.py (original) +++ pypy/dist/pypy/lang/scheme/execution.py Mon Aug 6 11:56:09 2007 @@ -1,72 +1,25 @@ -from pypy.lang.scheme.object import * +import pypy.lang.scheme.object as ssobject +#from pypy.lang.scheme.object import * class Location(object): def __init__(self, w_obj=None): self.obj = w_obj -## -# dict mapping operations to W_Xxx objects -# callables must have 2 arguments -# - ctx = execution context -# - lst = list of arguments -## -OMAP = \ - { - #arithmetic operations - '+': Add, - '-': Sub, - '*': Mul, - '/': Div, - #list operations - 'cons': Cons, - 'car': Car, - 'cdr': Cdr, - 'set-car!': SetCar, - 'set-cdr!': SetCdr, - 'list': List, - 'quit': Quit, - #comparisons - '=': Equal, - #predicates - 'integer?': IntegerP, - 'rational?': RealP, - 'real?': RealP, - 'complex?': NumberP, - 'number?': NumberP, - 'exact?': ExactP, - 'inexact?': InexactP, - 'zero?': ZeroP, - 'odd?': OddP, - 'even?': EvenP, - #delayed evaluation - 'force': Force, - 'delay': Delay, #macro - #macros - 'define': Define, - 'set!': Sete, - 'if': MacroIf, - 'lambda': Lambda, - 'begin': Begin, - 'let': Let, - 'let*': LetStar, - 'letrec': Letrec, - 'quote': Quote, - 'quasiquote': QuasiQuote, - 'syntax-rules': SyntaxRules, - 'define-syntax': DefineSyntax, - 'let-syntax': LetSyntax, - } - OPERATION_MAP = {} -for name, cls in OMAP.items(): - OPERATION_MAP[name] = cls(name) +for obj_name in dir(ssobject): + obj = getattr(ssobject, obj_name) + try: + issubclass(obj, ssobject.W_Callable) + OPERATION_MAP[obj._symbol_name] = obj(obj._symbol_name) + except (TypeError, AttributeError): + pass class ExecutionContext(object): """Execution context implemented as a dict. { "IDENTIFIER": Location(W_Root()) } """ - def __init__(self, globalscope=None, scope=None, closure=False, macro=False): + def __init__(self, globalscope=None, scope=None, closure=False): if globalscope is None: self.globalscope = {} for name, oper in OPERATION_MAP.items(): @@ -83,13 +36,13 @@ self.closure = closure def _dispatch(self, symb): - if isinstance(symb, SymbolClosure): + if isinstance(symb, ssobject.SymbolClosure): return (symb.closure, symb.name) - elif isinstance(symb, W_Symbol): + elif isinstance(symb, ssobject.W_Symbol): return (self, symb.name) - raise SchemeSyntaxError + raise ssobject.SchemeSyntaxError def copy(self): return ExecutionContext(self.globalscope, self.scope.copy(), True) @@ -98,16 +51,16 @@ loc = self.scope.get(name, None) if loc is not None: if loc.obj is None: - raise UnboundVariable(name) + raise ssobject.UnboundVariable(name) return loc.obj loc = self.globalscope.get(name, None) if loc is not None: if loc.obj is None: - raise UnboundVariable(name) + raise ssobject.UnboundVariable(name) return loc.obj - raise UnboundVariable(name) + raise ssobject.UnboundVariable(name) def ssete(self, symb, obj): (ctx, name) = self._dispatch(symb) @@ -117,7 +70,7 @@ """update existing location or raise directly used by (set! ) macro """ - assert isinstance(obj, W_Root) + assert isinstance(obj, ssobject.W_Root) loc = self.scope.get(name, None) if loc is not None: loc.obj = obj @@ -128,11 +81,11 @@ loc.obj = obj return obj - raise UnboundVariable(name) + raise ssobject.UnboundVariable(name) def set(self, name, obj): """update existing location or create new location""" - assert isinstance(obj, W_Root) + assert isinstance(obj, ssobject.W_Root) if self.closure: loc = self.scope.get(name, None) else: @@ -149,7 +102,7 @@ def put(self, name, obj): """create new location""" - assert isinstance(obj, W_Root) + assert isinstance(obj, ssobject.W_Root) if self.closure: self.scope[name] = Location(obj) else: @@ -179,3 +132,4 @@ return loc return None + Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Mon Aug 6 11:56:09 2007 @@ -440,6 +440,7 @@ Op.default_result = W_Integer(default_result) Op.__name__ = "Op" + title + Op._symbol_name = oper return Op Add = create_op_class('+', '', "Add", 0) @@ -448,6 +449,8 @@ Div = create_op_class('/', '1 /', "Div") class Equal(W_Procedure): + _symbol_name = "=" + def procedure(self, ctx, lst): if len(lst) < 2: return W_Boolean(True) @@ -467,10 +470,14 @@ return W_Boolean(True) class List(W_Procedure): + _symbol_name = "list" + def procedure(self, ctx, lst): return plst2lst(lst) class Cons(W_Procedure): + _symbol_name = "cons" + def procedure(self, ctx, lst): w_car = lst[0] w_cdr = lst[1] @@ -478,6 +485,8 @@ return W_Pair(w_car, w_cdr) class Car(W_Procedure): + _symbol_name = "car" + def procedure(self, ctx, lst): w_pair = lst[0] if not isinstance(w_pair, W_Pair): @@ -485,6 +494,8 @@ return w_pair.car class Cdr(W_Procedure): + _symbol_name = "cdr" + def procedure(self, ctx, lst): w_pair = lst[0] if not isinstance(w_pair, W_Pair): @@ -492,6 +503,8 @@ return w_pair.cdr class SetCar(W_Procedure): + _symbol_name = "set-car!" + def procedure(self, ctx, lst): w_pair = lst[0] w_obj = lst[1] @@ -502,6 +515,8 @@ return w_undefined class SetCdr(W_Procedure): + _symbol_name = "set-cdr!" + def procedure(self, ctx, lst): w_pair = lst[0] w_obj = lst[1] @@ -512,10 +527,14 @@ return w_undefined class Quit(W_Procedure): + _symbol_name = "quit" + def procedure(self, ctx, lst): raise SchemeQuit class Force(W_Procedure): + _symbol_name = "force" + def procedure(self, ctx, lst): if len(lst) != 1: raise WrongArgsNumber @@ -544,6 +563,8 @@ raise NotImplementedError class IntegerP(PredicateNumber): + _symbol_name = "integer?" + def predicate(self, w_obj): if not w_obj.exact: return w_obj.is_integer() @@ -551,26 +572,44 @@ return True class RealP(PredicateNumber): + _symbol_name = "real?" + def predicate(self, w_obj): return isinstance(w_obj, W_Real) +class RationalP(RealP): + _symbol_name = "rational?" + class NumberP(PredicateNumber): + _symbol_name = "number?" + def predicate(self, w_obj): return isinstance(w_obj, W_Number) +class ComplexP(NumberP): + _symbol_name = "complex?" + class ExactP(PredicateNumber): + _symbol_name = "exact?" + def predicate(self, w_obj): return w_obj.exact class InexactP(PredicateNumber): + _symbol_name = "inexact?" + def predicate(self, w_obj): return not w_obj.exact class ZeroP(PredicateNumber): + _symbol_name = "zero?" + def predicate(self, w_obj): return w_obj.to_number() == 0.0 class OddP(PredicateNumber): + _symbol_name = "odd?" + def predicate(self, w_obj): if not w_obj.is_integer(): raise WrongArgType(w_obj, "Integer") @@ -578,6 +617,8 @@ return w_obj.round() % 2 != 0 class EvenP(PredicateNumber): + _symbol_name = "even?" + def predicate(self, w_obj): if not w_obj.is_integer(): raise WrongArgType(w_obj, "Integer") @@ -588,6 +629,8 @@ # Macro ## class Define(W_Macro): + _symbol_name = "define" + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError @@ -612,6 +655,8 @@ raise SchemeSyntaxError class Sete(W_Macro): + _symbol_name = "set!" + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError @@ -622,6 +667,8 @@ return w_val #undefined class MacroIf(W_Macro): + _symbol_name = "if" + def call_tr(self, ctx, lst): #if needs to be tail-recursive aware if not isinstance(lst, W_Pair): @@ -641,6 +688,8 @@ return (w_else, ctx) class Lambda(W_Macro): + _symbol_name = "lambda" + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError(lst, "Pair") @@ -649,11 +698,15 @@ return W_Lambda(w_args, w_body, ctx) class Begin(W_Macro): + _symbol_name = "begin" + def call_tr(self, ctx, lst): #begin uses eval_body, so it is tail-recursive aware return self.eval_body(ctx, lst) class Let(W_Macro): + _symbol_name = "let" + def call_tr(self, ctx, lst): #let uses eval_body, so it is tail-recursive aware if not isinstance(lst, W_Pair): @@ -670,6 +723,8 @@ return self.eval_body(local_ctx, lst.cdr) class LetStar(W_Macro): + _symbol_name = "let*" + def call_tr(self, ctx, lst): #let* uses eval_body, so it is tail-recursive aware if not isinstance(lst, W_Pair): @@ -686,6 +741,8 @@ return self.eval_body(local_ctx, lst.cdr) class Letrec(W_Macro): + _symbol_name = "letrec" + def call_tr(self, ctx, lst): """let uses eval_body, so it is tail-recursive aware""" if not isinstance(lst, W_Pair): @@ -724,6 +781,8 @@ return W_Pair(W_Symbol('unquote-splicing'), W_Pair(sexpr, w_nil)) class Quote(W_Macro): + _symbol_name = "quote" + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError @@ -731,6 +790,8 @@ return lst.car class QuasiQuote(W_Macro): + _symbol_name = "quasiquote" + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError @@ -809,6 +870,8 @@ return w_lst class Delay(W_Macro): + _symbol_name = "delay" + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError @@ -819,6 +882,8 @@ # DerivedMacros ## class SyntaxRules(W_Macro): + _symbol_name = "syntax-rules" + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError @@ -832,11 +897,9 @@ if not isinstance(w_literals.car, W_Symbol): raise SchemeSyntaxError + #XXX locations here literal_name = w_literals.car.to_string() - try: - w_temp = ctx.get(literal_name) - except UnboundVariable: - w_temp = w_literals.car + w_temp = ctx.get_location(literal_name) literals_map[literal_name] = w_temp @@ -890,10 +953,11 @@ return self.pattern.to_string() + " -> " + self.template.to_string() def match(self, ctx, w_expr, pattern=None): + #we use .cdr here, because keyword should not be a macro variable if pattern is None: - return self.matchr(ctx, self.pattern, w_expr) + return self.matchr(ctx, self.pattern.cdr, w_expr.cdr) - return self.matchr(ctx, pattern, w_expr) + return self.matchr(ctx, pattern.cdr, w_expr.cdr) def matchr(self, ctx, w_patt, w_expr): if isinstance(w_patt, W_Pair): @@ -931,16 +995,22 @@ raise EllipsisPattern if isinstance(w_patt, W_Symbol): - w_literal = self.literals.get(w_patt.name, None) - if w_literal is not None: - try: - w_form = ctx.get(w_expr.to_string()) - except UnboundVariable: - w_form = w_expr + try: + w_literal = self.literals[w_patt.name] + if not isinstance(w_expr, W_Symbol): + raise MatchError + + if w_patt.name != w_expr.name: + raise MatchError + + w_form = ctx.get_location(w_expr.name) if w_form is not w_literal: raise MatchError + except KeyError: + pass + return {w_patt.name: w_expr} if w_patt is w_nil and w_expr is w_nil: @@ -1100,7 +1170,8 @@ w_macro = ctx.get(w_car.name) # recursive macro expansion if isinstance(w_macro, W_DerivedMacro): - return w_macro.expand(ctx, w_pair) + if w_macro.transformer is self: + return w_macro.expand(ctx, w_pair) except UnboundVariable: pass @@ -1161,6 +1232,8 @@ return self.transformer.expand(ctx, lst) class DefineSyntax(W_Macro): + _symbol_name = "define-syntax" + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError @@ -1179,6 +1252,8 @@ return w_macro #undefined class LetSyntax(W_Macro): + _symbol_name = "let-syntax" + def call_tr(self, ctx, lst): #let uses eval_body, so it is tail-recursive aware if not isinstance(lst, W_Pair): Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Mon Aug 6 11:56:09 2007 @@ -54,6 +54,9 @@ # w_transformer created in ctx w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") + w_expr = parse_("(foo 12 boo)") + py.test.raises(MatchError, w_transformer.match, ctx, w_expr) + w_expr = parse_("(foo bar boo)") py.test.raises(MatchError, w_transformer.match, ctx, w_expr) @@ -77,29 +80,35 @@ w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") py.test.raises(MatchError, w_transformer.match, closure, w_expr) - # the same binding for => in ctx and closure - # XXX + # the same object for => in ctx and closure, but different bindings # I think this should also raise MatchError. When R5RS says # "same binding" it probably means bound to the same *location*, not - # just that there is the same object in both locations; something like - # this: (let ((x 42) (y 42)) - # (let-syntax ((foo (syntax-rules (x y) - # ((foo x) 123) - # ((foo y) 456) - # ((foo whatever) 789)))) - # (foo y))) - # ---> 456 - # but if we change the last line: - # (let ((y 42)) (foo y)))) - # ---> 789 + # just that there is the same object in both locations ctx.put("=>", w_42) assert ctx.get("=>") is closure.get("=>") w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") - assert w_transformer.match(closure, w_expr)[0].to_boolean() + py.test.raises(MatchError, w_transformer.match, closure, w_expr) -def test_syntax_rules_expand_simple(): +def test_literals_eval(): ctx = ExecutionContext() + w_result = eval_(ctx, """(let ((x 42) (y 42)) + (let-syntax ((foo (syntax-rules (x y) + ((foo x) 123) + ((foo y) 456) + ((foo whatever) 789)))) + (foo y)))""") + assert w_result.to_number() == 456 + + w_result = eval_(ctx, """(let ((x 42) (y 42)) + (let-syntax ((foo (syntax-rules (x y) + ((foo x) 123) + ((foo y) 456) + ((foo whatever) 789)))) + (let ((y x)) (foo y))))""") + assert w_result.to_number() == 789 +def test_syntax_rules_expand_simple(): + ctx = ExecutionContext() w_transformer = eval_(ctx, """(syntax-rules () ((_) #t) ((_ foo) foo))""") @@ -264,13 +273,9 @@ ((bar arg) (foo arg))))""") w_expr = parse_("(bar 42)") - #should expand directly (recursively) to 42 - assert ctx.get("bar").expand(ctx, w_expr).to_string() == "42" - # XXX no, I believe it should not expand recursively... - # here is another example which returns (foo) in MIT-Scheme where - # we get 42 so far: - py.test.skip("XXX in-progress (or wrong test?)") - ctx = ExecutionContext() + assert ctx.get("bar").expand(ctx, w_expr).to_string() == "(foo 42)" + assert eval_(ctx, "(bar 42)").to_number() == 42 + eval_(ctx, """(define-syntax foo (syntax-rules () ((foo) #t)))""") eval_(ctx, """(define-syntax bar (syntax-rules () @@ -440,11 +445,10 @@ "(x y 1 2 3 4 + end)" def test_cornercase1(): - py.test.skip("currently crashes") w_result = eval_noctx("""(let-syntax ((foo (syntax-rules () ((bar) 'bar)))) - (foo)) - """) + (foo)) """) + assert w_result.to_string() == 'bar' # I think that the correct answer is 'bar, according to # the R5RS, because it says that the keyword bar in the syntax rule @@ -461,8 +465,9 @@ def test_pitfall_3_2(): py.test.skip("(cond ...) not implemented yet") + #define inside macors can and sometimes can not introduce new binding w_result = eval_noctx("""(let-syntax ((foo (syntax-rules () - ((_ var) (define var 1))))) + ((_ var) (define var 1))))) (let ((x 2)) (begin (define foo +)) (cond (else (foo x))) @@ -470,7 +475,6 @@ assert w_result.to_number() == 2 def test_pitfall_3_3(): - py.test.skip("currently fails") w_result = eval_noctx(""" (let ((x 1)) (let-syntax @@ -485,3 +489,4 @@ def test_pitfall_3_4(): w_result = eval_noctx("(let-syntax ((x (syntax-rules ()))) 1)") assert w_result.to_number() == 1 + From cfbolz at codespeak.net Mon Aug 6 12:04:19 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 6 Aug 2007 12:04:19 +0200 (CEST) Subject: [pypy-svn] r45513 - pypy/extradoc/talk/dyla2007 Message-ID: <20070806100419.D41AE80DD@code0.codespeak.net> Author: cfbolz Date: Mon Aug 6 12:04:18 2007 New Revision: 45513 Added: pypy/extradoc/talk/dyla2007/talk.pdf (contents, props changed) Modified: pypy/extradoc/talk/dyla2007/talk.tex Log: version of the talk as given at ECOOP Added: pypy/extradoc/talk/dyla2007/talk.pdf ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/dyla2007/talk.tex ============================================================================== --- pypy/extradoc/talk/dyla2007/talk.tex (original) +++ pypy/extradoc/talk/dyla2007/talk.tex Mon Aug 6 12:04:18 2007 @@ -25,10 +25,10 @@ Heinrich-Heine-Universit?t D?sseldorf } -\date{3rd Workshop on Dynamic Languages and Applications, July 31 2007} +\date{3rd Workshop on Dynamic Languages and Applications, July 31st 2007} -\pgfdeclareimage[height=0.5cm]{pypy-logo}{image/py-web.png} -\logo{\pgfuseimage{pypy-logo}} +%\pgfdeclareimage[height=0.5cm]{pypy-logo}{image/py-web.png} +%\logo{\pgfuseimage{pypy-logo}} @@ -74,7 +74,7 @@ \end{itemize} \pause \begin{block}{ - Our point} + Our points} \begin{itemize} \item Do not write virtual machines ``by hand'' @@ -88,9 +88,9 @@ \begin{frame} - \frametitle{Common Approaches to VM construction} + \frametitle{Common Approaches to Language Implementation} \begin{block}{ - Using C directly (or C disguised as another language)} + Using C/C++ (potentially disguised as another language)} \begin{itemize} \item CPython @@ -99,9 +99,10 @@ \item Spidermonkey (Mozilla's JavaScript VM) \item - but also: Squeak, Scheme48 + but also: Scheme48, Squeak \end{itemize} \end{block} + \pause \begin{block}{ Building on top of a general-purpose OO VM} \begin{itemize} @@ -109,6 +110,8 @@ Jython, IronPython \item JRuby, IronRuby + \item + various Prolog, Lisp, even Smalltalk implementations \end{itemize} \end{block} \end{frame} @@ -120,9 +123,9 @@ \item flexibility, maintainability \item - simplicity of the VM + simplicity \item - performance (needs dynamic compilation techniques) + performance \end{itemize} \pause \begin{block}{ @@ -141,32 +144,11 @@ \end{frame} \begin{frame} - \frametitle{Compilers are a bad encoding of Semantics} - \begin{itemize} - \item to reach good performance levels, dynamic compilation is often needed - \item a dynamic compiler needs to encode language semantics - \item this encoding is often obscure and hard to change - \end{itemize} - \pause - \begin{block}{ - Python Case} - \begin{itemize} - \item - Psyco is a dynamic compiler for Python - \item - synchronizing with CPython's rapid development is a lot of effort - \item - many of CPython's new features not supported well - \end{itemize} - \end{block} -\end{frame} - -\begin{frame} \frametitle{Fixing of Early Design Decisions} \begin{itemize} \item when starting a VM in C, many design decisions need to be made upfront \item examples: memory management technique, threading model - \item the decision is manifested throughout the VM source + \item such decisions are manifested throughout the VM source \item very hard to change later \end{itemize} \pause @@ -183,31 +165,28 @@ \end{frame} \begin{frame} - \frametitle{Implementation Proliferation} + \frametitle{Compilers are a bad encoding of Semantics} \begin{itemize} - \item - restrictions of the original implementation lead to re-implementations, - forks - \item - all implementations need to be synchronized with language evolution - \item - lots of duplicate effort + \item to reach good performance levels, dynamic compilation is often needed + \item a compiler (obviously) needs to encode language semantics + \item this encoding is often obscure and hard to change \end{itemize} \pause \begin{block}{ Python Case} \begin{itemize} \item - several serious implementations: CPython, Stackless, Psyco, Jython, - IronPython, PyPy + Psyco is a dynamic compiler for Python + \item + synchronizing with CPython's rapid development is a lot of effort \item - the implementations have various grades of compliance + many of CPython's new features not supported well \end{itemize} \end{block} \end{frame} \begin{frame} - \frametitle{Implementing Languages on Top of General-Purpose OO VMs} + \frametitle{Implementing Languages on Top of OO VMs} \begin{itemize} \item users wish to have easy interoperation with the general-purpose OO VMs used @@ -215,9 +194,9 @@ \item therefore re-implementations of the language on the OO VMs are started \item - even more implementation proliferation + more implementations! \item - implementing on top of an OO VM has its own set of problems + implementing on top of an OO VM has its own set of benefits of problems \end{itemize} \pause \begin{block}{ @@ -243,8 +222,6 @@ the VM supplies a GC and mostly a JIT \item better interoperability than what the C level provides - \item - some proponents believe that eventually one single VM should be enough \end{itemize} \pause \begin{block}{ @@ -253,7 +230,7 @@ \item both Jython and IronPython integrate well with their host OO VM \item - XXX what else? + Jython has free threading \end{itemize} \end{block} \end{frame} @@ -262,18 +239,12 @@ \frametitle{The problems of OO VMs} \begin{itemize} \item - some of the benefits of OO VMs don't work out in practice - \item most immediate problem: it can be hard to map - concepts of the dynamic lang to + concepts of the dynamic language to the host OO VM \item performance is often not improved, and can be very bad, because of the semantic mismatch between the dynamic language and the host VM - \item - poor interoperability with everything outside the OO VM - \item - in practice, one OO VM is not enough \end{itemize} \pause \begin{block}{ @@ -282,16 +253,40 @@ \item Jython about 5 times slower than CPython \item - IronPython is about as fast as CPython (but some introspection features - missing) + IronPython is about as fast as CPython (but some stack introspection + features missing) \item - XXX something about semantic mismatch? + Python has very different semantics for method calls than Java \end{itemize} \end{block} \end{frame} \begin{frame} + \frametitle{Implementation Proliferation} + \begin{itemize} + \item + restrictions of the original implementation lead to re-implementations, + forks + \item + all implementations need to be synchronized with language evolution + \item + lots of duplicate effort, compatibility problems + \end{itemize} + \pause + \begin{block}{ + Python Case} + \begin{itemize} + \item + several serious implementations: CPython, Stackless, Psyco, Jython, + IronPython, PyPy + \item + various incompatibilities + \end{itemize} + \end{block} +\end{frame} + +\begin{frame} \frametitle{PyPy's Approach to VM Construction} \emph{Goal: achieve flexibility, simplicity and performance together} @@ -303,8 +298,8 @@ \item high-level description: an interpreter written in a high-level language \item - ... which we translate (i.e.\ compile) to VMs running on top of various - targets, like C/Posix, CLR, JVM + ... which we translate (i.e.\ compile) to a VM running in various target + environments, like C/Posix, CLR, JVM \end{itemize} \end{frame} @@ -324,7 +319,7 @@ \item subset chosen in such a way that type-inference can be performed \item - still a high-level language (unlike SLang or Prescheme) + still a high-level language (unlike SLang or PreScheme) \item ...really a subset, can't give a small example of code that doesn't just look like Python :-) @@ -336,8 +331,6 @@ \frametitle{Auto-generating VMs} \begin{itemize} \item - high-level source: early design decisions not necessary - \item we need a custom \emph{translation toolchain} to compile the interpreter to a full VM \item @@ -369,13 +362,14 @@ \item dynamic languages can be implemented in a high level language \item - separation of concerns from low-level details + separation of language semantics from low-level details \item - a potential single-source-fits-all interpreter -- - less duplication of efforts - \item - runs everywhere with the same semantics -- - no outdated implementations, no ties to any standard platform + a single-source-fits-all interpreter + \begin{itemize} + \item runs everywhere with the same semantics + \item no outdated implementations, no ties to any standard platform + \item less duplication of efforts + \end{itemize} \end{itemize} \pause \begin{block}{PyPy} @@ -423,13 +417,12 @@ JIT compiler generator} \begin{itemize} \item - almost orthogonal from the interpreter source - applicable to many + almost orthogonal from the interpreter source ? applicable to many languages, follows language evolution ``for free'' \item - based on Partial Evaluation + based on Partial Evaluation techniques \item - benefits from a high-level interpreter and a tweakable translation - toolchain + benefits from a high-level interpreter \item generating a dynamic compiler is easier than generating a static one! \end{itemize} @@ -437,7 +430,7 @@ \end{frame} \begin{frame} - \frametitle{Open Issues / Drawbacks / Further Work} + \frametitle{Drawbacks / Open Issues / Further Work} \begin{itemize} \item writing the translation toolchain in the first place takes lots of effort @@ -446,10 +439,7 @@ writing a good GC is still necessary. But: maybe we can reuse existing good GCs (e.g.\ from the Jikes RVM)? \item - conceptually simple approach but many abstraction layers - \item dynamic compiler generation seems to work, but needs more efforts. - Also: can we layer it on top of the JIT of a general purpose OO VM? \end{itemize} \end{frame} @@ -457,22 +447,20 @@ \frametitle{Conclusion / Meta-Points} \begin{itemize} \item + VMs shouldn't be written by hand + \item high-level languages are suitable to implement dynamic languages \item doing so has many benefits \item - VMs shouldn't be written by hand - \item PyPy's concrete approach is not so important \item - diversity is good - \item let's write more meta-programming toolchains! \end{itemize} \end{frame} \begin{frame} - \frametitle{Links} + \frametitle{Questions?} \begin{block}{ PyPy} \bigskip From jlg at codespeak.net Mon Aug 6 12:18:24 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 6 Aug 2007 12:18:24 +0200 (CEST) Subject: [pypy-svn] r45514 - pypy/dist/pypy/lang/scheme Message-ID: <20070806101824.85E8480CA@code0.codespeak.net> Author: jlg Date: Mon Aug 6 12:18:23 2007 New Revision: 45514 Modified: pypy/dist/pypy/lang/scheme/object.py Log: scheme translates again Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Mon Aug 6 12:18:23 2007 @@ -945,6 +945,7 @@ class SyntaxRule(object): def __init__(self, pattern, template, literals): + assert isinstance(pattern, W_Pair) self.pattern = pattern self.template = template self.literals = literals @@ -952,12 +953,10 @@ def __str__(self): return self.pattern.to_string() + " -> " + self.template.to_string() - def match(self, ctx, w_expr, pattern=None): + def match(self, ctx, w_expr): #we use .cdr here, because keyword should not be a macro variable - if pattern is None: - return self.matchr(ctx, self.pattern.cdr, w_expr.cdr) - - return self.matchr(ctx, pattern.cdr, w_expr.cdr) + assert isinstance(w_expr, W_Pair) + return self.matchr(ctx, self.pattern.cdr, w_expr.cdr) def matchr(self, ctx, w_patt, w_expr): if isinstance(w_patt, W_Pair): @@ -1124,16 +1123,17 @@ w_cdr = self.substituter(ctx, sexpr.cdr, match_dict) except EllipsisTemplate: print "ellipsis expand", sexpr + sexprcdr = sexpr.get_cdr_as_pair() try: #we can still have something behind ellipsis - w_cdr = self.substituter(ctx, sexpr.cdr.cdr, match_dict) + w_cdr = self.substituter(ctx, sexprcdr.cdr, match_dict) except EllipsisTemplate: #it can also be ellipsis # lets pretend its usual <(obj ...) ...> # instead of # we will *flatten* the result later - w_inner = W_Pair(sexpr.car, W_Pair(sexpr.cdr.car, w_nil)) - w_outer = W_Pair(w_inner, sexpr.cdr.cdr) + w_inner = W_Pair(sexpr.car, W_Pair(sexprcdr.car, w_nil)) + w_outer = W_Pair(w_inner, sexprcdr.cdr) return self.substituter(ctx, w_outer, match_dict, True) plst = [] From antocuni at codespeak.net Mon Aug 6 15:39:01 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 6 Aug 2007 15:39:01 +0200 (CEST) Subject: [pypy-svn] r45515 - pypy/dist/pypy/translator/cli/test Message-ID: <20070806133901.27BA880C9@code0.codespeak.net> Author: antocuni Date: Mon Aug 6 15:39:00 2007 New Revision: 45515 Modified: pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_runtest.py Log: add the ability to automatically propagate RPython exceptions raised in compiled cli programs. Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Mon Aug 6 15:39:00 2007 @@ -127,13 +127,13 @@ assert False, 'Input type %s not supported' % arg_type -def compile_function(func, annotation=[], graph=None, backendopt=True): +def compile_function(func, annotation=[], graph=None, backendopt=True, auto_raise_exc=False): olddefs = patch() gen = _build_gen(func, annotation, graph, backendopt) gen.generate_source() exe_name = gen.build_exe() unpatch(*olddefs) # restore original values - return CliFunctionWrapper(exe_name) + return CliFunctionWrapper(exe_name, func.__name__, auto_raise_exc) def _build_gen(func, annotation, graph=None, backendopt=True): try: @@ -172,8 +172,10 @@ return GenCli(tmpdir, t, TestEntryPoint(main_graph, True)) class CliFunctionWrapper(object): - def __init__(self, exe_name): + def __init__(self, exe_name, name=None, auto_raise_exc=False): self._exe = exe_name + self.__name__ = name or exe_name + self.auto_raise_exc = auto_raise_exc def run(self, *args): if self._exe is None: @@ -199,6 +201,13 @@ res = StructTuple(res) # so tests can access tuple elements with .item0, .item1, etc. elif isinstance(res, list): res = OOList(res) + elif self.auto_raise_exc and isinstance(res, ExceptionWrapper): + excname = res.class_name + if excname.startswith('exceptions.'): + import exceptions + raise eval(excname) + else: + raise res # probably it's a .NET exception with no RPython equivalent return res class StructTuple(tuple): @@ -233,13 +242,14 @@ self._ann = None self._cli_func = None - def _compile(self, fn, args, ann=None, backendopt=True): + def _compile(self, fn, args, ann=None, backendopt=True, auto_raise_exc=False): if ann is None: ann = [lltype_to_annotation(typeOf(x)) for x in args] if self._func is fn and self._ann == ann: return self._cli_func else: - self._cli_func = compile_function(fn, ann, backendopt=backendopt) + self._cli_func = compile_function(fn, ann, backendopt=backendopt, + auto_raise_exc=auto_raise_exc) self._func = fn self._ann = ann return self._cli_func Modified: pypy/dist/pypy/translator/cli/test/test_runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/test_runtest.py Mon Aug 6 15:39:00 2007 @@ -1,3 +1,4 @@ +import py from pypy.translator.cli.test.runtest import CliTest from pypy.translator.cli.test.runtest import FLOAT_PRECISION from pypy.annotation.listdef import s_list_of_strings @@ -64,3 +65,10 @@ else: return None assert self.interpret(fn, [False]) is None + + def test_auto_raise_exc(self): + def fn(): + raise ValueError + f = self._compile(fn, [], auto_raise_exc=True) + py.test.raises(ValueError, f) + From fijal at codespeak.net Mon Aug 6 15:55:44 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 6 Aug 2007 15:55:44 +0200 (CEST) Subject: [pypy-svn] r45516 - in pypy/dist/pypy: rlib rpython/module rpython/module/test Message-ID: <20070806135544.A0F6180CA@code0.codespeak.net> Author: fijal Date: Mon Aug 6 15:55:43 2007 New Revision: 45516 Modified: pypy/dist/pypy/rlib/ros.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/test/test_ll_os.py pypy/dist/pypy/rpython/module/test/test_posix.py Log: os.tmpfile, RPython level implementation Modified: pypy/dist/pypy/rlib/ros.py ============================================================================== --- pypy/dist/pypy/rlib/ros.py (original) +++ pypy/dist/pypy/rlib/ros.py Mon Aug 6 15:55:43 2007 @@ -3,6 +3,7 @@ """ import os +from pypy.rlib.streamio import fdopen_as_stream def putenv(name_eq_value): # we fake it with the real one @@ -62,3 +63,18 @@ def utime_tuple(path, tp): os.utime(path, tp) + +# ARGH! strange hack to allow os.tmpfile not to be deleted +# (it should guess it based on getting file desc) +# this is only when run on top of cpython +# this will eventually lead to two closes (when this list is deleted), but +# well.., unsure we can do anything with that. +KEEP_ME_ALIVE_PLEASE = [] + +def _tmpfile(): + tmpfile = os.tmpfile() + KEEP_ME_ALIVE_PLEASE.append(tmpfile) + return tmpfile.fileno() + +def tmpfile(): + return fdopen_as_stream(_tmpfile(), "w+b", True) Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Mon Aug 6 15:55:43 2007 @@ -12,7 +12,8 @@ from pypy.rlib.rarithmetic import r_longlong from pypy.tool.staticmethods import ClassMethods import stat -from pypy.rpython.extfunc import BaseLazyRegistering, registering +from pypy.rpython.extfunc import BaseLazyRegistering, registering,\ + lazy_register, _register_external from pypy.annotation.model import SomeString, SomeInteger from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool from pypy.annotation.listdef import s_list_of_strings @@ -472,6 +473,28 @@ self.register(os.ttyname, [int], str, "ll_os.ttyname", llimpl=ttyname_lltypeimpl) +def register_tmpfile(): + from pypy.rpython.lltypesystem import rffi + includes = ['stdio.h'] + + FILEP = rffi.COpaque('FILE', includes=includes) + + c_tmpfile = rffi.llexternal('tmpfile', [], FILEP, includes=includes) + c_fileno = rffi.llexternal('fileno', [FILEP], rffi.INT, includes=includes) + + def _tmpfile_llimpl(): + fileobj = c_tmpfile() + if not fileobj: + raise OSError(rffi.get_errno(), "tmpfile failed") + ret = c_fileno(fileobj) + if ret == -1: + raise OSError(rffi.get_errno(), "fileno failed") + return ret + + _register_external(ros._tmpfile, [], int, export_name='ros._tmpfile', + llimpl=_tmpfile_llimpl) +lazy_register(ros._tmpfile, register_tmpfile) + class BaseOS: __metaclass__ = ClassMethods Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_os.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_os.py Mon Aug 6 15:55:43 2007 @@ -114,7 +114,7 @@ fn = compile(fun, [int]) for value in [0, 1, 127, 128, 255]: - assert fn(value) == fun(value) + assert fn(value) == fun(value) class ExpectTestOs: def setup_class(cls): Modified: pypy/dist/pypy/rpython/module/test/test_posix.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_posix.py (original) +++ pypy/dist/pypy/rpython/module/test/test_posix.py Mon Aug 6 15:55:43 2007 @@ -104,6 +104,46 @@ return os.getuid() assert self.interpret(f, []) == f() + def test_tmpfile(self): + py.test.skip("XXX get_errno() does not work with ll2ctypes") + from pypy.rlib import ros + def f(): + f = ros.tmpfile() + f.write('xxx') + f.flush() + return f.try_to_find_file_descriptor() + + def f2(num): + os.close(num) + + fd = self.interpret(f, []) + realfile = os.fdopen(fd) + realfile.seek(0) + assert realfile.read() == 'xxx' + self.interpret(f2, [fd]) + +def test_tmpfile_translate(): + from pypy.rlib import ros + def f(): + f = ros.tmpfile() + f.write('xxx') + f.flush() + return f.try_to_find_file_descriptor() + + def f2(num): + os.close(num) + + from pypy.translator.c.test.test_genc import compile + + fn1 = compile(f, []) + fn2 = compile(f2, [int]) + + fd = fn1() + realfile = os.fdopen(fd) + realfile.seek(0) + assert realfile.read() == 'xxx' + fn2(fd) + if not hasattr(os, 'ftruncate'): del BaseTestPosix.test_ftruncate @@ -118,4 +158,3 @@ class TestOOtype(BaseTestPosix, OORtypeMixin): pass - From fijal at codespeak.net Mon Aug 6 15:56:47 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 6 Aug 2007 15:56:47 +0200 (CEST) Subject: [pypy-svn] r45517 - in pypy/dist/pypy/module: _file posix posix/test Message-ID: <20070806135647.0523180D0@code0.codespeak.net> Author: fijal Date: Mon Aug 6 15:56:47 2007 New Revision: 45517 Modified: pypy/dist/pypy/module/_file/app_file.py pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/module/posix/test/test_posix2.py Log: os.tmpfile, app-level implementation, including simple hack to app-level file to create file from stream. Modified: pypy/dist/pypy/module/_file/app_file.py ============================================================================== --- pypy/dist/pypy/module/_file/app_file.py (original) +++ pypy/dist/pypy/module/_file/app_file.py Mon Aug 6 15:56:47 2007 @@ -38,6 +38,14 @@ return f fdopen = classmethod(fdopen) + def tmpfile(cls, stream): + f = cls.__new__(cls) + fd = stream.try_to_find_file_descriptor() + assert fd != -1 + f._fdopenstream(fd, "w+b", -1, "", stream) + return f + tmpfile = classmethod(tmpfile) + def _fdopenstream(self, fd, mode, buffering, name, stream): self.fd = fd self._name = name Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Mon Aug 6 15:56:47 2007 @@ -50,6 +50,7 @@ #'getuid' : 'interp_posix.getuid', #'geteuid' : 'interp_posix.geteuid', 'utime' : 'interp_posix.utime', + 'tmpfile' : 'interp_posix.tmpfile', } if hasattr(os, 'ftruncate'): interpleveldefs['ftruncate'] = 'interp_posix.ftruncate' Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Mon Aug 6 15:56:47 2007 @@ -3,6 +3,7 @@ from pypy.rlib import ros from pypy.interpreter.error import OperationError, wrap_oserror from pypy.rpython.module.ll_os import RegisterOs +from pypy.module._file.interp_file import W_Stream, wrap_oserror_as_ioerror import os @@ -527,3 +528,13 @@ except OSError, e: raise wrap_oserror(space, e) ttyname.unwrap_spec = [ObjSpace, int] + +def tmpfile(space): + try: + stream = ros.tmpfile() + w_stream = space.wrap(W_Stream(space, stream)) + w_fobj = space.getattr(space.getbuiltinmodule('__builtin__'), space.wrap('file')) + return space.call_function(space.getattr(w_fobj, space.wrap('tmpfile')), w_stream) + except OSError, e: + raise wrap_oserror_as_ioerror(space, e) +tmpfile.unwrap_spec = [ObjSpace] Modified: pypy/dist/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/dist/pypy/module/posix/test/test_posix2.py (original) +++ pypy/dist/pypy/module/posix/test/test_posix2.py Mon Aug 6 15:56:47 2007 @@ -262,6 +262,15 @@ res = os.system(cmd) assert res == 0 + def test_tmpfile(self): + os = self.os + f = os.tmpfile() + f.write("xxx") + f.flush() + f.seek(0, 0) + assert isinstance(f, file) + assert f.read() == 'xxx' + class TestPexpect(object): # XXX replace with AppExpectTest class as soon as possible def setup_class(cls): From antocuni at codespeak.net Mon Aug 6 16:06:23 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 6 Aug 2007 16:06:23 +0200 (CEST) Subject: [pypy-svn] r45521 - in pypy/dist/pypy/translator: . cli cli/test test Message-ID: <20070806140623.754FD80CA@code0.codespeak.net> Author: antocuni Date: Mon Aug 6 16:06:22 2007 New Revision: 45521 Modified: pypy/dist/pypy/translator/cli/gencli.py pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/exceptiontransform.py pypy/dist/pypy/translator/test/test_exceptiontransform.py Log: port exceptiontransform to ootype, step #3: exceptiontransform ported to ootype :-). Test passes, but it still does not work with gencli :-( Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Mon Aug 6 16:06:22 2007 @@ -49,7 +49,7 @@ DictConst = constant.CLIDictConst WeakRefConst = constant.CLIWeakRefConst - def __init__(self, tmpdir, translator, entrypoint, config=None): + def __init__(self, tmpdir, translator, entrypoint, config=None, exctrans=False): GenOO.__init__(self, tmpdir, translator, entrypoint, config) for node in get_prebuilt_nodes(translator, self.db): self.db.pending_node(node) @@ -62,6 +62,11 @@ SSI_to_SSA(graph) build_trees(graph) + if exctrans: + etrafo = translator.getexceptiontransformer() + for graph in translator.graphs: + etrafo.create_exception_handling(graph) + def generate_source(self): GenOO.generate_source(self) self.db.const_count.dump(self.const_stat) Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Mon Aug 6 16:06:22 2007 @@ -127,15 +127,16 @@ assert False, 'Input type %s not supported' % arg_type -def compile_function(func, annotation=[], graph=None, backendopt=True, auto_raise_exc=False): +def compile_function(func, annotation=[], graph=None, backendopt=True, + auto_raise_exc=False, exctrans=False): olddefs = patch() - gen = _build_gen(func, annotation, graph, backendopt) + gen = _build_gen(func, annotation, graph, backendopt, exctrans) gen.generate_source() exe_name = gen.build_exe() unpatch(*olddefs) # restore original values return CliFunctionWrapper(exe_name, func.__name__, auto_raise_exc) -def _build_gen(func, annotation, graph=None, backendopt=True): +def _build_gen(func, annotation, graph=None, backendopt=True, exctrans=False): try: func = func.im_func except AttributeError: @@ -169,7 +170,7 @@ else: tmpdir = udir - return GenCli(tmpdir, t, TestEntryPoint(main_graph, True)) + return GenCli(tmpdir, t, TestEntryPoint(main_graph, True), exctrans=exctrans) class CliFunctionWrapper(object): def __init__(self, exe_name, name=None, auto_raise_exc=False): Modified: pypy/dist/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/exceptiontransform.py Mon Aug 6 16:06:22 2007 @@ -5,6 +5,7 @@ from pypy.objspace.flow.model import Block, Constant, Variable, Link, \ c_last_exception, SpaceOperation, checkgraph, FunctionGraph from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem import lloperation from pypy.rpython.memory.lladdress import NULL from pypy.rpython import rtyper @@ -31,30 +32,24 @@ return PrimitiveErrorValue[T] elif isinstance(T, lltype.Ptr): return lltype.nullptr(T.TO) + elif isinstance(T, ootype.OOType): + return ootype.null(T) assert 0, "not implemented yet" def error_constant(T): return Constant(error_value(T), T) -class ExceptionTransformer(object): +class BaseExceptionTransformer(object): + def __init__(self, translator): self.translator = translator self.raise_analyzer = canraise.RaiseAnalyzer(translator) edata = translator.rtyper.getexceptiondata() self.lltype_of_exception_value = edata.lltype_of_exception_value self.lltype_of_exception_type = edata.lltype_of_exception_type - mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper) - l2a = annmodel.lltype_to_annotation + self.mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper) + exc_data, null_type, null_value = self.setup_excdata() - EXCDATA = lltype.Struct('ExcData', - ('exc_type', self.lltype_of_exception_type), - ('exc_value', self.lltype_of_exception_value)) - self.EXCDATA = EXCDATA - - exc_data = lltype.malloc(EXCDATA, immortal=True) - null_type = lltype.nullptr(self.lltype_of_exception_type.TO) - null_value = lltype.nullptr(self.lltype_of_exception_value.TO) - def rpyexc_occured(): exc_type = exc_data.exc_type return bool(exc_type) @@ -80,89 +75,48 @@ # assert(!RPyExceptionOccurred()); exc_data.exc_type = etype exc_data.exc_value = evalue - - RPYEXC_OCCURED_TYPE = lltype.FuncType([], lltype.Bool) - rpyexc_occured_graph = mixlevelannotator.getgraph( - rpyexc_occured, [], l2a(lltype.Bool)) - self.rpyexc_occured_ptr = Constant(lltype.functionptr( - RPYEXC_OCCURED_TYPE, "RPyExceptionOccurred", - graph=rpyexc_occured_graph, - exception_policy="exc_helper"), - lltype.Ptr(RPYEXC_OCCURED_TYPE)) - # XXX tmp HACK for genllvm - _RPYEXC_OCCURED_TYPE = lltype.FuncType([], lltype.Signed) - _rpyexc_occured_graph = mixlevelannotator.getgraph( - _rpyexc_occured, [], l2a(lltype.Signed)) - self._rpyexc_occured_ptr = Constant(lltype.functionptr( - _RPYEXC_OCCURED_TYPE, "_RPyExceptionOccurred", - graph=_rpyexc_occured_graph, - exception_policy="exc_helper"), - lltype.Ptr(_RPYEXC_OCCURED_TYPE)) - - RPYEXC_FETCH_TYPE_TYPE = lltype.FuncType([], self.lltype_of_exception_type) - rpyexc_fetch_type_graph = mixlevelannotator.getgraph( - rpyexc_fetch_type, [], - l2a(self.lltype_of_exception_type)) - self.rpyexc_fetch_type_ptr = Constant(lltype.functionptr( - RPYEXC_FETCH_TYPE_TYPE, "RPyFetchExceptionType", - graph=rpyexc_fetch_type_graph, - exception_policy="exc_helper"), - lltype.Ptr(RPYEXC_FETCH_TYPE_TYPE)) - - RPYEXC_FETCH_VALUE_TYPE = lltype.FuncType([], self.lltype_of_exception_value) - rpyexc_fetch_value_graph = mixlevelannotator.getgraph( - rpyexc_fetch_value, [], - l2a(self.lltype_of_exception_value)) - self.rpyexc_fetch_value_ptr = Constant(lltype.functionptr( - RPYEXC_FETCH_VALUE_TYPE, "RPyFetchExceptionValue", - graph=rpyexc_fetch_value_graph, - exception_policy="exc_helper"), - lltype.Ptr(RPYEXC_FETCH_VALUE_TYPE)) - - RPYEXC_CLEAR = lltype.FuncType([], lltype.Void) - rpyexc_clear_graph = mixlevelannotator.getgraph( - rpyexc_clear, [], l2a(lltype.Void)) - self.rpyexc_clear_ptr = Constant(lltype.functionptr( - RPYEXC_CLEAR, "RPyClearException", - graph=rpyexc_clear_graph, - exception_policy="exc_helper"), - lltype.Ptr(RPYEXC_CLEAR)) - - RPYEXC_RAISE = lltype.FuncType([self.lltype_of_exception_type, - self.lltype_of_exception_value], - lltype.Void) - rpyexc_raise_graph = mixlevelannotator.getgraph( - rpyexc_raise, [l2a(self.lltype_of_exception_type), - l2a(self.lltype_of_exception_value)], - l2a(lltype.Void)) - self.rpyexc_raise_ptr = Constant(lltype.functionptr( - RPYEXC_RAISE, "RPyRaiseException", - graph=rpyexc_raise_graph, - exception_policy="exc_helper", - jitcallkind='rpyexc_raise', # for the JIT - ), - lltype.Ptr(RPYEXC_RAISE)) + self.rpyexc_occured_ptr = self.build_func( + "RPyExceptionOccurred", + rpyexc_occured, + [], lltype.Bool) - mixlevelannotator.finish() + # XXX tmp HACK for genllvm + self._rpyexc_occured_ptr = self.build_func( + "_RPyExceptionOccurred", + _rpyexc_occured, + [], lltype.Signed) + + self.rpyexc_fetch_type_ptr = self.build_func( + "RPyFetchExceptionType", + rpyexc_fetch_type, + [], self.lltype_of_exception_type) + + self.rpyexc_fetch_value_ptr = self.build_func( + "RPyFetchExceptionValue", + rpyexc_fetch_value, + [], self.lltype_of_exception_value) + + self.rpyexc_clear_ptr = self.build_func( + "RPyClearException", + rpyexc_clear, + [], lltype.Void) + + self.rpyexc_raise_ptr = self.build_func( + "RPyRaiseException", + rpyexc_raise, + [self.lltype_of_exception_type, self.lltype_of_exception_value], + lltype.Void, + jitcallkind='rpyexc_raise') # for the JIT - self.exc_data_ptr = exc_data - self.cexcdata = Constant(exc_data, lltype.Ptr(EXCDATA)) - + self.mixlevelannotator.finish() self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping() - p = lltype.nullptr(self.lltype_of_exception_type.TO) - self.c_null_etype = Constant(p, self.lltype_of_exception_type) - p = lltype.nullptr(self.lltype_of_exception_value.TO) - self.c_null_evalue = Constant(p, self.lltype_of_exception_value) - def gen_getfield(self, name, llops): - c_name = inputconst(lltype.Void, name) - return llops.genop('getfield', [self.cexcdata, c_name], - resulttype = getattr(self.EXCDATA, name)) - - def gen_setfield(self, name, v_value, llops): - c_name = inputconst(lltype.Void, name) - llops.genop('setfield', [self.cexcdata, c_name, v_value]) + def build_func(self, name, fn, inputtypes, rettype, **kwds): + l2a = annmodel.lltype_to_annotation + graph = self.mixlevelannotator.getgraph(fn, map(l2a, inputtypes), l2a(rettype)) + return self.constant_func(name, inputtypes, rettype, graph, + exception_policy="exc_helper", **kwds) def transform_completely(self): for graph in self.translator.graphs: @@ -177,7 +131,7 @@ Because of the added exitswitch we need an additional block. """ if hasattr(graph, 'exceptiontransformed'): - assert self.exc_data_ptr._same_obj(graph.exceptiontransformed) + assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed) return else: self.raise_analyzer.analyze_direct_call(graph) @@ -308,9 +262,7 @@ excblock.closeblock(Link([var_type, var_value], newgraph.exceptblock)) startblock.exits[True].target = excblock startblock.exits[True].args = [] - FUNCTYPE = lltype.FuncType(ARGTYPES, op.result.concretetype) - fptr = Constant(lltype.functionptr(FUNCTYPE, "dummy_exc1", graph=newgraph), - lltype.Ptr(FUNCTYPE)) + fptr = self.constant_func("dummy_exc1", ARGTYPES, op.result.concretetype, newgraph) return newgraph, SpaceOperation("direct_call", [fptr] + callargs, op.result) def gen_exc_check(self, block, returnblock, normalafterblock=None): @@ -319,26 +271,17 @@ #block.operations.append(SpaceOperation("safe_call", [self.rpyexc_occured_ptr], var_exc_occured)) llops = rtyper.LowLevelOpList(None) - alloc_shortcut = False spaceop = block.operations[-1] - if spaceop.opname in ('malloc', 'malloc_varsize'): - alloc_shortcut = True - elif spaceop.opname == 'direct_call': - fnobj = spaceop.args[0].value._obj - if hasattr(fnobj, '_callable'): - oopspec = getattr(fnobj._callable, 'oopspec', None) - if oopspec and oopspec == 'newlist(length)': - alloc_shortcut = True - + alloc_shortcut = self.check_for_alloc_shortcut(spaceop) + + # XXX: does alloc_shortcut make sense also for ootype? if alloc_shortcut: T = spaceop.result.concretetype - var_no_exc = llops.genop('ptr_nonzero', [spaceop.result], - lltype.Bool) + var_no_exc = self.gen_nonnull(spaceop.result, llops) else: v_exc_type = self.gen_getfield('exc_type', llops) - var_no_exc = llops.genop('ptr_iszero', [v_exc_type], - lltype.Bool) + var_no_exc = self.gen_isnull(v_exc_type, llops) block.operations.extend(llops) @@ -384,3 +327,110 @@ self.gen_setfield('exc_value', self.c_null_evalue, llops) self.gen_setfield('exc_type', self.c_null_etype, llops) normalafterblock.operations[:0] = llops + +class LLTypeExceptionTransformer(BaseExceptionTransformer): + + def setup_excdata(self): + EXCDATA = lltype.Struct('ExcData', + ('exc_type', self.lltype_of_exception_type), + ('exc_value', self.lltype_of_exception_value)) + self.EXCDATA = EXCDATA + + exc_data = lltype.malloc(EXCDATA, immortal=True) + null_type = lltype.nullptr(self.lltype_of_exception_type.TO) + null_value = lltype.nullptr(self.lltype_of_exception_value.TO) + + self.exc_data_ptr = exc_data + self.cexcdata = Constant(exc_data, lltype.Ptr(self.EXCDATA)) + self.c_null_etype = Constant(null_type, self.lltype_of_exception_type) + self.c_null_evalue = Constant(null_value, self.lltype_of_exception_value) + + return exc_data, null_type, null_value + + def constant_func(self, name, inputtypes, rettype, graph, **kwds): + FUNC_TYPE = lltype.FuncType(inputtypes, rettype) + fn_ptr = lltype.functionptr(FUNC_TYPE, name, graph=graph, **kwds) + return Constant(fn_ptr, lltype.Ptr(FUNC_TYPE)) + + def gen_getfield(self, name, llops): + c_name = inputconst(lltype.Void, name) + return llops.genop('getfield', [self.cexcdata, c_name], + resulttype = getattr(self.EXCDATA, name)) + + def gen_setfield(self, name, v_value, llops): + c_name = inputconst(lltype.Void, name) + llops.genop('setfield', [self.cexcdata, c_name, v_value]) + + def gen_isnull(self, v, llops): + return llops.genop('ptr_iszero', [v], lltype.Bool) + + def gen_nonnull(self, v, llops): + return llops.genop('ptr_nonzero', [v], lltype.Bool) + + def same_obj(self, ptr1, ptr2): + return ptr1._same_obj(ptr2) + + def check_for_alloc_shortcut(self, spaceop): + if spaceop.opname in ('malloc', 'malloc_varsize'): + return True + elif spaceop.opname == 'direct_call': + fnobj = spaceop.args[0].value._obj + if hasattr(fnobj, '_callable'): + oopspec = getattr(fnobj._callable, 'oopspec', None) + if oopspec and oopspec == 'newlist(length)': + return True + return False + +class OOTypeExceptionTransformer(BaseExceptionTransformer): + + def setup_excdata(self): + EXCDATA = ootype.Record({'exc_type': self.lltype_of_exception_type, + 'exc_value': self.lltype_of_exception_value}) + self.EXCDATA = EXCDATA + + exc_data = ootype.new(EXCDATA) + null_type = ootype.null(self.lltype_of_exception_type) + null_value = ootype.null(self.lltype_of_exception_value) + + self.exc_data_ptr = exc_data + self.cexcdata = Constant(exc_data, self.EXCDATA) + + self.c_null_etype = Constant(null_type, self.lltype_of_exception_type) + self.c_null_evalue = Constant(null_value, self.lltype_of_exception_value) + + return exc_data, null_type, null_value + + def constant_func(self, name, inputtypes, rettype, graph, **kwds): + FUNC_TYPE = ootype.StaticMethod(inputtypes, rettype) + fn_ptr = ootype.static_meth(FUNC_TYPE, name, graph=graph, **kwds) + return Constant(fn_ptr, FUNC_TYPE) + + def gen_getfield(self, name, llops): + c_name = inputconst(lltype.Void, name) + return llops.genop('oogetfield', [self.cexcdata, c_name], + resulttype = self.EXCDATA._field_type(name)) + + def gen_setfield(self, name, v_value, llops): + c_name = inputconst(lltype.Void, name) + llops.genop('oosetfield', [self.cexcdata, c_name, v_value]) + + def gen_isnull(self, v, llops): + nonnull = self.gen_nonnull(v, llops) + return llops.genop('bool_not', [nonnull], lltype.Bool) + + def gen_nonnull(self, v, llops): + return llops.genop('oononnull', [v], lltype.Bool) + + def same_obj(self, obj1, obj2): + return obj1 is obj2 + + def check_for_alloc_shortcut(self, spaceop): + return False + +def ExceptionTransformer(translator): + type_system = translator.rtyper.type_system.name + if type_system == 'lltypesystem': + return LLTypeExceptionTransformer(translator) + else: + assert type_system == 'ootypesystem' + return OOTypeExceptionTransformer(translator) Modified: pypy/dist/pypy/translator/test/test_exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/test/test_exceptiontransform.py (original) +++ pypy/dist/pypy/translator/test/test_exceptiontransform.py Mon Aug 6 16:06:22 2007 @@ -2,10 +2,7 @@ from pypy.translator.translator import TranslationContext, graphof from pypy.translator.simplify import join_blocks from pypy.translator import exceptiontransform -from pypy.translator.c import genc, gc -from pypy.objspace.flow.model import c_last_exception from pypy.rpython.test.test_llinterp import get_interpreter -from pypy.translator.c.test.test_genc import compile from pypy import conftest import sys @@ -16,20 +13,6 @@ if not hasattr(sys, 'gettotalrefcount') and not conftest.option.view: py.test.skip("test needs a debug build of Python") -def transform_func(fn, inputtypes): - t = TranslationContext() - t.buildannotator().build_types(fn, inputtypes) - t.buildrtyper().specialize() - if conftest.option.view: - t.view() - g = graphof(t, fn) - etrafo = exceptiontransform.ExceptionTransformer(t) - etrafo.create_exception_handling(g) - join_blocks(g) - if conftest.option.view: - t.view() - return t, g - _already_transformed = {} def interpret(func, values): @@ -41,164 +24,201 @@ _already_transformed[t] = True return interp.eval_graph(graph, values) -def test_simple(): - def one(): - return 1 - - def foo(): - one() - return one() - - t, g = transform_func(foo, []) - assert len(list(g.iterblocks())) == 2 # graph does not change - result = interpret(foo, []) - assert result == 1 - f = compile(foo, []) - assert f() == 1 +class BaseTestExceptionTransform: + type_system = None + + def transform_func(self, fn, inputtypes): + t = TranslationContext() + t.buildannotator().build_types(fn, inputtypes) + t.buildrtyper(type_system=self.type_system).specialize() + if conftest.option.view: + t.view() + g = graphof(t, fn) + etrafo = exceptiontransform.ExceptionTransformer(t) + etrafo.create_exception_handling(g) + join_blocks(g) + if conftest.option.view: + t.view() + return t, g + + def compile(self, fn, inputargs): + raise NotImplementedError -def test_passthrough(): - def one(x): - if x: - raise ValueError() - - def foo(): - one(0) - one(1) - t, g = transform_func(foo, []) - f = compile(foo, []) - py.test.raises(ValueError, f) - -def test_catches(): - def one(x): - if x == 1: - raise ValueError() - elif x == 2: - raise TypeError() - return x - 5 - - def foo(x): - x = one(x) - try: + def test_simple(self): + def one(): + return 1 + + def foo(): + one() + return one() + + t, g = self.transform_func(foo, []) + assert len(list(g.iterblocks())) == 2 # graph does not change + result = interpret(foo, []) + assert result == 1 + f = self.compile(foo, []) + assert f() == 1 + + def test_passthrough(self): + def one(x): + if x: + raise ValueError() + + def foo(): + one(0) + one(1) + t, g = self.transform_func(foo, []) + f = self.compile(foo, []) + py.test.raises(ValueError, f) + + def test_catches(self): + def one(x): + if x == 1: + raise ValueError() + elif x == 2: + raise TypeError() + return x - 5 + + def foo(x): x = one(x) - except ValueError: - return 1 + x - except TypeError: - return 2 + x - except: - return 3 + x - return 4 + x - t, g = transform_func(foo, [int]) - assert len(list(g.iterblocks())) == 9 - f = compile(foo, [int]) - result = interpret(foo, [6]) - assert result == 2 - result = f(6) - assert result == 2 - result = interpret(foo, [7]) - assert result == 4 - result = f(7) - assert result == 4 - result = interpret(foo, [8]) - assert result == 2 - result = f(8) - assert result == 2 - -def test_bare_except(): - def one(x): - if x == 1: - raise ValueError() - elif x == 2: - raise TypeError() - return x - 5 - - def foo(x): - x = one(x) - try: + try: + x = one(x) + except ValueError: + return 1 + x + except TypeError: + return 2 + x + except: + return 3 + x + return 4 + x + t, g = self.transform_func(foo, [int]) + assert len(list(g.iterblocks())) == 9 + f = self.compile(foo, [int]) + result = interpret(foo, [6]) + assert result == 2 + result = f(6) + assert result == 2 + result = interpret(foo, [7]) + assert result == 4 + result = f(7) + assert result == 4 + result = interpret(foo, [8]) + assert result == 2 + result = f(8) + assert result == 2 + + def test_bare_except(self): + def one(x): + if x == 1: + raise ValueError() + elif x == 2: + raise TypeError() + return x - 5 + + def foo(x): x = one(x) - except: - return 1 + x - return 4 + x - t, g = transform_func(foo, [int]) - assert len(list(g.iterblocks())) == 5 - f = compile(foo, [int]) - result = interpret(foo, [6]) - assert result == 2 - result = f(6) - assert result == 2 - result = interpret(foo, [7]) - assert result == 3 - result = f(7) - assert result == 3 - result = interpret(foo, [8]) - assert result == 2 - result = f(8) - assert result == 2 - -def test_raises(): - def foo(x): - if x: - raise ValueError() - t, g = transform_func(foo, [int]) - assert len(list(g.iterblocks())) == 3 - f = compile(foo, [int]) - f(0) - py.test.raises(ValueError, f, 1) - -def test_needs_keepalive(): - check_debug_build() - from pypy.rpython.lltypesystem import lltype - X = lltype.GcStruct("X", - ('y', lltype.Struct("Y", ('z', lltype.Signed)))) - def can_raise(n): - if n: - raise Exception - else: - return 1 - def foo(n): - x = lltype.malloc(X) - y = x.y - y.z = 42 - r = can_raise(n) - return r + y.z - f = compile(foo, [int]) - res = f(0) - assert res == 43 - -def test_no_multiple_transform(): - def f(x): - return x + 1 - t = TranslationContext() - t.buildannotator().build_types(f, [int]) - t.buildrtyper().specialize() - g = graphof(t, f) - etrafo = exceptiontransform.ExceptionTransformer(t) - etrafo.create_exception_handling(g) - etrafo2 = exceptiontransform.ExceptionTransformer(t) - py.test.raises(AssertionError, etrafo2.create_exception_handling, g) - -def test_preserve_can_raise(): - def f(x): - raise ValueError - t = TranslationContext() - t.buildannotator().build_types(f, [int]) - t.buildrtyper().specialize() - g = graphof(t, f) - etrafo = exceptiontransform.ExceptionTransformer(t) - etrafo.create_exception_handling(g) - assert etrafo.raise_analyzer.analyze_direct_call(g) - -def test_inserting_zeroing_op(): - from pypy.rpython.lltypesystem import lltype - S = lltype.GcStruct("S", ('x', lltype.Signed)) - def f(x): - s = lltype.malloc(S) - s.x = 0 - return s.x - t = TranslationContext() - t.buildannotator().build_types(f, [int]) - t.buildrtyper().specialize() - g = graphof(t, f) - etrafo = exceptiontransform.ExceptionTransformer(t) - etrafo.create_exception_handling(g) - ops = dict.fromkeys([o.opname for b, o in g.iterblockops()]) - assert 'zero_gc_pointers_inside' in ops + try: + x = one(x) + except: + return 1 + x + return 4 + x + t, g = self.transform_func(foo, [int]) + assert len(list(g.iterblocks())) == 5 + f = self.compile(foo, [int]) + result = interpret(foo, [6]) + assert result == 2 + result = f(6) + assert result == 2 + result = interpret(foo, [7]) + assert result == 3 + result = f(7) + assert result == 3 + result = interpret(foo, [8]) + assert result == 2 + result = f(8) + assert result == 2 + + def test_raises(self): + def foo(x): + if x: + raise ValueError() + t, g = self.transform_func(foo, [int]) + assert len(list(g.iterblocks())) == 3 + f = self.compile(foo, [int]) + f(0) + py.test.raises(ValueError, f, 1) + + + def test_no_multiple_transform(self): + def f(x): + return x + 1 + t = TranslationContext() + t.buildannotator().build_types(f, [int]) + t.buildrtyper(type_system=self.type_system).specialize() + g = graphof(t, f) + etrafo = exceptiontransform.ExceptionTransformer(t) + etrafo.create_exception_handling(g) + etrafo2 = exceptiontransform.ExceptionTransformer(t) + py.test.raises(AssertionError, etrafo2.create_exception_handling, g) + + def test_preserve_can_raise(self): + def f(x): + raise ValueError + t = TranslationContext() + t.buildannotator().build_types(f, [int]) + t.buildrtyper(type_system=self.type_system).specialize() + g = graphof(t, f) + etrafo = exceptiontransform.ExceptionTransformer(t) + etrafo.create_exception_handling(g) + assert etrafo.raise_analyzer.analyze_direct_call(g) + + +class TestLLType(BaseTestExceptionTransform): + type_system = 'lltype' + + def compile(self, fn, inputargs): + from pypy.translator.c.test.test_genc import compile + return compile(fn, inputargs) + + def test_needs_keepalive(self): + check_debug_build() + from pypy.rpython.lltypesystem import lltype + X = lltype.GcStruct("X", + ('y', lltype.Struct("Y", ('z', lltype.Signed)))) + def can_raise(n): + if n: + raise Exception + else: + return 1 + def foo(n): + x = lltype.malloc(X) + y = x.y + y.z = 42 + r = can_raise(n) + return r + y.z + f = self.compile(foo, [int]) + res = f(0) + assert res == 43 + + def test_inserting_zeroing_op(self): + from pypy.rpython.lltypesystem import lltype + S = lltype.GcStruct("S", ('x', lltype.Signed)) + def f(x): + s = lltype.malloc(S) + s.x = 0 + return s.x + t = TranslationContext() + t.buildannotator().build_types(f, [int]) + t.buildrtyper(type_system=self.type_system).specialize() + g = graphof(t, f) + etrafo = exceptiontransform.ExceptionTransformer(t) + etrafo.create_exception_handling(g) + ops = dict.fromkeys([o.opname for b, o in g.iterblockops()]) + assert 'zero_gc_pointers_inside' in ops + +class TestOOType(BaseTestExceptionTransform): + type_system = 'ootype' + + def compile(self, fn, inputargs): + from pypy.translator.cli.test.runtest import compile_function + # XXX: set exctrans=True + return compile_function(fn, inputargs, auto_raise_exc=True, exctrans=False) From fijal at codespeak.net Mon Aug 6 16:41:21 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 6 Aug 2007 16:41:21 +0200 (CEST) Subject: [pypy-svn] r45522 - pypy/dist/pypy/module/_curses/test Message-ID: <20070806144121.7852F80C9@code0.codespeak.net> Author: fijal Date: Mon Aug 6 16:41:19 2007 New Revision: 45522 Modified: pypy/dist/pypy/module/_curses/test/test_curses.py Log: Skip those tests if database is not there (don't know how to fake it) Modified: pypy/dist/pypy/module/_curses/test/test_curses.py ============================================================================== --- pypy/dist/pypy/module/_curses/test/test_curses.py (original) +++ pypy/dist/pypy/module/_curses/test/test_curses.py Mon Aug 6 16:41:19 2007 @@ -8,6 +8,13 @@ import py import sys +def setup_module(mod): + try: + import curses + curses.setupterm() + except: + py.test.skip("Cannot test this here") + class TestCurses(object): """ We need to fork here, to prevent the setup to be done From fijal at codespeak.net Mon Aug 6 16:44:50 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 6 Aug 2007 16:44:50 +0200 (CEST) Subject: [pypy-svn] r45523 - pypy/dist/pypy/translator/llvm/test Message-ID: <20070806144450.42E3E80CD@code0.codespeak.net> Author: fijal Date: Mon Aug 6 16:44:49 2007 New Revision: 45523 Modified: pypy/dist/pypy/translator/llvm/test/test_lladdresses.py pypy/dist/pypy/translator/llvm/test/test_typed.py Log: Skip failing tests (just because) Modified: pypy/dist/pypy/translator/llvm/test/test_lladdresses.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_lladdresses.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_lladdresses.py Mon Aug 6 16:44:49 2007 @@ -125,6 +125,7 @@ # assert fn(2, 24) == 6 def test_flavored_malloc_stack(): + py.test.skip("Broken and noone wants to fix it") class A(object): _alloc_flavor_ = "stack" def __init__(self, val): Modified: pypy/dist/pypy/translator/llvm/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_typed.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_typed.py Mon Aug 6 16:44:49 2007 @@ -54,6 +54,7 @@ assert result def test_is(): + py.test.skip("Broken and noone wants to fix it") def testfn(): l1 = [] return l1 is l1 @@ -68,6 +69,7 @@ assert result == False def test_nones(): + py.test.skip("Broken and noone wants to fix it") a = [None] * 4 def nones(): a.append(None) From antocuni at codespeak.net Mon Aug 6 17:12:39 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 6 Aug 2007 17:12:39 +0200 (CEST) Subject: [pypy-svn] r45524 - in pypy/dist/pypy/translator: cli cli/test test Message-ID: <20070806151239.1801780D0@code0.codespeak.net> Author: antocuni Date: Mon Aug 6 17:12:39 2007 New Revision: 45524 Modified: pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/gencli.py pypy/dist/pypy/translator/cli/prebuiltnodes.py pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/test/test_exceptiontransform.py Log: some tweaks to gencli to make exception transformer working Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Mon Aug 6 17:12:39 2007 @@ -171,8 +171,6 @@ def __init__(self, *args, **kwargs): OOFunction.__init__(self, *args, **kwargs) - self._set_args() - self._set_locals() namespace = getattr(self.graph.func, '_namespace_', None) str if namespace: @@ -196,6 +194,9 @@ OOFunction.record_ll_meta_exc(self, ll_meta_exc) def begin_render(self): + self._set_args() + self._set_locals() + returntype, returnvar = self.cts.llvar_to_cts(self.graph.getreturnvar()) if self.is_method: args = self.args[1:] # self is implicit Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Mon Aug 6 17:12:39 2007 @@ -51,22 +51,25 @@ def __init__(self, tmpdir, translator, entrypoint, config=None, exctrans=False): GenOO.__init__(self, tmpdir, translator, entrypoint, config) + if exctrans: + self.db.exceptiontransformer = translator.getexceptiontransformer() + for node in get_prebuilt_nodes(translator, self.db): self.db.pending_node(node) self.assembly_name = entrypoint.get_name() self.tmpfile = tmpdir.join(self.assembly_name + '.il') self.const_stat = str(tmpdir.join('const_stat')) + if exctrans: + etrafo = self.db.exceptiontransformer + for graph in translator.graphs: + etrafo.create_exception_handling(graph) + if translator.config.translation.backendopt.stack_optimization: for graph in translator.graphs: SSI_to_SSA(graph) build_trees(graph) - if exctrans: - etrafo = translator.getexceptiontransformer() - for graph in translator.graphs: - etrafo.create_exception_handling(graph) - def generate_source(self): GenOO.generate_source(self) self.db.const_count.dump(self.const_stat) Modified: pypy/dist/pypy/translator/cli/prebuiltnodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/prebuiltnodes.py (original) +++ pypy/dist/pypy/translator/cli/prebuiltnodes.py Mon Aug 6 17:12:39 2007 @@ -50,4 +50,17 @@ prebuilt_nodes = _build_helpers(translator, db) raise_OSError_graph = translator.rtyper.exceptiondata.fn_raise_OSError.graph prebuilt_nodes.append(Helper(db, raise_OSError_graph, 'raise_OSError')) + + try: + etrafo = db.exceptiontransformer + except AttributeError: + pass + else: + for name in ('rpyexc_clear', + 'rpyexc_fetch_type', + 'rpyexc_fetch_value', + 'rpyexc_occured', + 'rpyexc_raise'): + sm = getattr(etrafo, name+'_ptr').value + prebuilt_nodes.append(Function(db, sm.graph, name)) return prebuilt_nodes Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Mon Aug 6 17:12:39 2007 @@ -90,15 +90,28 @@ ilasm.leave('return') ilasm.end_catch() + # check for USE_LAST exceptions ilasm.label('check_last_exception') ilasm.opcode('ldsfld', 'object last_exception') - ilasm.opcode('brnull', 'print_result') + ilasm.opcode('brnull', 'check_etrafo_exception') # there is a pending exception ilasm.opcode('ldsfld', 'object last_exception') ilasm.call('string class [pypylib]pypy.test.Result::FormatException(object)') ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') ilasm.opcode('br', 'return') + # check for exception tranformer exceptions + ilasm.label('check_etrafo_exception') + if hasattr(self.db, 'exceptiontransformer'): + ilasm.opcode('call', 'bool rpyexc_occured()') + ilasm.opcode('brfalse', 'print_result') # no exceptions + ilasm.opcode('call', 'Object rpyexc_fetch_value()') + ilasm.call('string class [pypylib]pypy.test.Result::FormatException(object)') + ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') + ilasm.opcode('br', 'return') + else: + ilasm.opcode('br', 'print_result') + ilasm.label('print_result') if return_type != 'void': ilasm.opcode('ldloc', 'res') Modified: pypy/dist/pypy/translator/test/test_exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/test/test_exceptiontransform.py (original) +++ pypy/dist/pypy/translator/test/test_exceptiontransform.py Mon Aug 6 17:12:39 2007 @@ -220,5 +220,4 @@ def compile(self, fn, inputargs): from pypy.translator.cli.test.runtest import compile_function - # XXX: set exctrans=True - return compile_function(fn, inputargs, auto_raise_exc=True, exctrans=False) + return compile_function(fn, inputargs, auto_raise_exc=True, exctrans=True) From antocuni at codespeak.net Tue Aug 7 16:34:49 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 7 Aug 2007 16:34:49 +0200 (CEST) Subject: [pypy-svn] r45533 - in pypy/dist/pypy/translator: cli jvm oosupport Message-ID: <20070807143449.EA7AF80AD@code0.codespeak.net> Author: antocuni Date: Tue Aug 7 16:34:48 2007 New Revision: 45533 Modified: pypy/dist/pypy/translator/cli/conftest.py pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/jvm/node.py pypy/dist/pypy/translator/oosupport/function.py Log: move --trace from jvm to oosupport, and teach gencli how to use it. Modified: pypy/dist/pypy/translator/cli/conftest.py ============================================================================== --- pypy/dist/pypy/translator/cli/conftest.py (original) +++ pypy/dist/pypy/translator/cli/conftest.py Tue Aug 7 16:34:48 2007 @@ -28,6 +28,9 @@ Option('--nostackopt', action='store_true', dest='nostackopt', default=False, help="don't optimize stack load/store operations"), + + Option('--trace', action='store_true', dest='trace', default=False, + help='Trace execution of generated code'), ) Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Tue Aug 7 16:34:48 2007 @@ -193,6 +193,21 @@ if NATIVE_INSTANCE is None: OOFunction.record_ll_meta_exc(self, ll_meta_exc) + def _trace_enabled(self): + return getoption('trace') + + def _trace(self, s, writeline=False): + self.ilasm.stderr(s, writeline=writeline) + + def _trace_value(self, prompt, v): + self.ilasm.stderr(' ' + prompt + ': ', writeline=False) + self.ilasm.load_stderr() + self.load(v) + if v.concretetype is not ootype.String: + from pypy.translator.cli.test.runtest import format_object + format_object(v.concretetype, self.cts, self.ilasm) + self.ilasm.write_stderr() + def begin_render(self): self._set_args() self._set_locals() Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Tue Aug 7 16:34:48 2007 @@ -252,12 +252,22 @@ self.code.write(opcode + ' ') self.code.writeline(' '.join(map(str, args))) - def stderr(self, msg, cond=True): + def stderr(self, msg, cond=True, writeline=True): from pypy.translator.cli.support import string_literal if cond: - self.call('class [mscorlib]System.IO.TextWriter class [mscorlib]System.Console::get_Error()') + self.load_stderr() self.opcode('ldstr', string_literal(msg)) - self.call_method('void class [mscorlib]System.IO.TextWriter::WriteLine(string)', virtual=True) + self.write_stderr(writeline) + + def load_stderr(self): + self.call('class [mscorlib]System.IO.TextWriter class [mscorlib]System.Console::get_Error()') + + def write_stderr(self, writeline=True): + if writeline: + meth = 'WriteLine' + else: + meth = 'Write' + self.call_method('void class [mscorlib]System.IO.TextWriter::%s(string)' % meth, virtual=True) def add_comment(self, text): self.code.writeline('// %s' % text) Modified: pypy/dist/pypy/translator/jvm/node.py ============================================================================== --- pypy/dist/pypy/translator/jvm/node.py (original) +++ pypy/dist/pypy/translator/jvm/node.py Tue Aug 7 16:34:48 2007 @@ -337,7 +337,9 @@ self.ilasm.throw() - def _trace(self, str): + def _trace(self, str, writeline=False): + if writeline: + str += '\n' jvmgen.SYSTEMERR.load(self.generator) self.generator.load_string(str) jvmgen.PRINTSTREAMPRINTSTR.invoke(self.generator) @@ -381,19 +383,13 @@ self.generator.emit(jvmgen.PRINTSTREAMPRINTSTR) self._trace("\n") + def _trace_enabled(self): + return getoption('trace') + def _render_op(self, op): self.generator.add_comment(str(op)) - - if getoption('trace'): - self._trace(str(op)+"\n") - - for i, arg in enumerate(op.args): - self._trace_value('Arg %02d' % i, arg) - OOFunction._render_op(self, op) - if getoption('trace'): - self._trace_value('Result', op.result) class StaticMethodInterface(Node, JvmClassType): """ Modified: pypy/dist/pypy/translator/oosupport/function.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/function.py (original) +++ pypy/dist/pypy/translator/oosupport/function.py Tue Aug 7 16:34:48 2007 @@ -242,11 +242,29 @@ self.generator.load(to_load) self.generator.store(to_store) + def _trace_enabled(self): + return False + + def _trace(self, s): + raise NotImplementedError + + def _trace_value(self, prompt, v): + raise NotImplementedError + def _render_op(self, op): instr_list = self.db.genoo.opcodes.get(op.opname, None) assert instr_list is not None, 'Unknown opcode: %s ' % op assert isinstance(instr_list, InstructionList) + + if self._trace_enabled(): + self._trace(str(op), writeline=True) + for i, arg in enumerate(op.args): + self._trace_value('Arg %02d' % i, arg) + instr_list.render(self.generator, op) + + if self._trace_enabled(): + self._trace_value('Result', op.result) def _render_sub_op(self, sub_op): op = sub_op.op From antocuni at codespeak.net Wed Aug 8 11:22:54 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 8 Aug 2007 11:22:54 +0200 (CEST) Subject: [pypy-svn] r45544 - in pypy/dist/pypy: annotation rpython/ootypesystem/test Message-ID: <20070808092254.CABC280F6@code0.codespeak.net> Author: antocuni Date: Wed Aug 8 11:22:53 2007 New Revision: 45544 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py Log: (antocuni, with moral support from fijal :-)) handle correctly ootype._record pbcs Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Wed Aug 8 11:22:53 2007 @@ -408,6 +408,8 @@ result = SomeOOClass(x._INSTANCE) # NB. can be None elif isinstance(x, ootype.instance_impl): # XXX result = SomeOOInstance(ootype.typeOf(x)) + elif isinstance(x, ootype._record): + result = SomeOOInstance(ootype.typeOf(x)) elif callable(x): if hasattr(x, '__self__') and x.__self__ is not None: # for cases like 'l.append' where 'l' is a global constant list Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py Wed Aug 8 11:22:53 2007 @@ -149,6 +149,18 @@ assert s == annmodel.SomeOOInstance(C1) +def test_record(): + R = Record({'foo': Signed}) + r = new(R) + + def oof(): + return r + + a = RPythonAnnotator() + s = a.build_types(oof, []) + assert isinstance(s, annmodel.SomeOOInstance) + assert s.ootype == R + def test_static_method(): F = StaticMethod([Signed, Signed], Signed) def f_(a, b): Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py Wed Aug 8 11:22:53 2007 @@ -288,3 +288,14 @@ def fn(): return Bar() py.test.raises(AssertionError, gengraph, fn, mangle=False) + +def test_pbc_record(): + R = Record({'foo': Signed}) + r = new(R) + r.foo = 42 + + def oof(): + return r.foo + + res = interpret(oof, [], type_system='ootype') + assert res == 42 From pypy-svn at codespeak.net Wed Aug 8 13:54:25 2007 From: pypy-svn at codespeak.net (pypy-svn at codespeak.net) Date: Wed, 8 Aug 2007 13:54:25 +0200 (CEST) Subject: [pypy-svn] Mail-id : 69656598349248729 - NEW Fall Collection Message-ID: <20070808125538.8119.qmail@webcache-4.netmadeira.net> An HTML attachment was scrubbed... URL: From antocuni at codespeak.net Wed Aug 8 15:21:27 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 8 Aug 2007 15:21:27 +0200 (CEST) Subject: [pypy-svn] r45551 - pypy/dist/pypy/translator/cli Message-ID: <20070808132127.4411A8110@code0.codespeak.net> Author: antocuni Date: Wed Aug 8 15:21:25 2007 New Revision: 45551 Modified: pypy/dist/pypy/translator/cli/function.py Log: oups... typo! Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Wed Aug 8 15:21:25 2007 @@ -255,7 +255,7 @@ true_label = self.next_label('link_true') self.generator.load(block.exitswitch) - self.generator.branch_conditionally(link.exitcase, true_label) + self.generator.branch_conditionally(True, true_label) self._follow_link(link_false) # if here, the exitswitch is false self.set_label(true_label) self._follow_link(link_true) # if here, the exitswitch is true From antocuni at codespeak.net Wed Aug 8 15:24:24 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 8 Aug 2007 15:24:24 +0200 (CEST) Subject: [pypy-svn] r45552 - pypy/dist/pypy/translator/goal Message-ID: <20070808132424.9C73B8111@code0.codespeak.net> Author: antocuni Date: Wed Aug 8 15:24:24 2007 New Revision: 45552 Modified: pypy/dist/pypy/translator/goal/targetrpystonedalone.py Log: add a newline to rpystone's output Modified: pypy/dist/pypy/translator/goal/targetrpystonedalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystonedalone.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystonedalone.py Wed Aug 8 15:24:24 2007 @@ -16,7 +16,7 @@ if loops >= 0: s = ("RPystone(%s) time for %d passes = %f" % (VERSION, loops, benchtime) + '\n' + ( - "This machine benchmarks at %f pystones/second" % stones)) + "This machine benchmarks at %f pystones/second\n" % stones)) os.write(1, s) if loops == 12345: pystones_main(loops-1) @@ -73,4 +73,4 @@ This is a case treated specially in the driver.py . If the list of input types is empty, it is meant to be a list of strings, actually implementing argv of the executable. -""" \ No newline at end of file +""" From antocuni at codespeak.net Wed Aug 8 15:58:16 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 8 Aug 2007 15:58:16 +0200 (CEST) Subject: [pypy-svn] r45553 - in pypy/dist/pypy: config doc/config translator/cli Message-ID: <20070808135816.BAFE780F8@code0.codespeak.net> Author: antocuni Date: Wed Aug 8 15:58:16 2007 New Revision: 45553 Added: pypy/dist/pypy/doc/config/translation.cli.exception_transformer.txt (contents, props changed) Modified: pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/translator/cli/gencli.py Log: add a new option to tell gencli to use the exception transformer Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Wed Aug 8 15:58:16 2007 @@ -195,7 +195,8 @@ OptionDescription("cli", "GenCLI options", [ BoolOption("trace_calls", "Trace function calls", default=False, - cmdline="--cli-trace-calls") + cmdline="--cli-trace-calls"), + BoolOption("exception_transformer", "Use exception transformer", default=False), ]), ]) Added: pypy/dist/pypy/doc/config/translation.cli.exception_transformer.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/config/translation.cli.exception_transformer.txt Wed Aug 8 15:58:16 2007 @@ -0,0 +1,3 @@ +Use the exception transformer instead of the native .NET exceptions to +implement RPython exceptions. Enable this option only if you know what +you are doing. Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Wed Aug 8 15:58:16 2007 @@ -51,6 +51,7 @@ def __init__(self, tmpdir, translator, entrypoint, config=None, exctrans=False): GenOO.__init__(self, tmpdir, translator, entrypoint, config) + exctrans = exctrans or translator.config.translation.cli.exception_transformer if exctrans: self.db.exceptiontransformer = translator.getexceptiontransformer() From antocuni at codespeak.net Wed Aug 8 16:18:51 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 8 Aug 2007 16:18:51 +0200 (CEST) Subject: [pypy-svn] r45554 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20070808141851.ADECA810E@code0.codespeak.net> Author: antocuni Date: Wed Aug 8 16:18:50 2007 New Revision: 45554 Modified: pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/metavm.py pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_exception.py Log: - test test_exception both with the native exceptions and the exception transformer - kill LastExceptionHandler Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Wed Aug 8 16:18:50 2007 @@ -18,156 +18,7 @@ from pypy.translator.cli.support import log from pypy.translator.cli.ilgenerator import CLIBaseGenerator -USE_LAST = False - -class NativeExceptionHandler(object): - def begin_try(self): - self.ilasm.begin_try() - - def end_try(self, target_label): - self.ilasm.leave(target_label) - self.ilasm.end_try() - - def begin_catch(self, llexitcase): - ll_meta_exc = llexitcase - ll_exc = ll_meta_exc._inst.class_._INSTANCE - cts_exc = self.cts.lltype_to_cts(ll_exc, False) - self.ilasm.begin_catch(cts_exc) - - def end_catch(self, target_label): - self.ilasm.leave(target_label) - self.ilasm.end_catch() - - def render_raise_block(self, block): - exc = block.inputargs[1] - self.load(exc) - self.ilasm.opcode('throw') - - def store_exception_and_link(self, link): - if self._is_raise_block(link.target): - # the exception value is on the stack, use it as the 2nd target arg - assert len(link.args) == 2 - assert len(link.target.inputargs) == 2 - self.store(link.target.inputargs[1]) - else: - # the exception value is on the stack, store it in the proper place - if isinstance(link.last_exception, flowmodel.Variable): - self.ilasm.opcode('dup') - self.store(link.last_exc_value) - self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) - self.store(link.last_exception) - else: - self.store(link.last_exc_value) - self._setup_link(link) - -class LastExceptionHandler(object): - in_try = False - - def begin_try(self): - self.in_try = True - self.ilasm.opcode('// begin_try') - - def end_try(self, target_label): - self.ilasm.opcode('ldsfld', 'object last_exception') - self.ilasm.opcode('brnull', target_label) - self.ilasm.opcode('// end try') - self.in_try = False - - def begin_catch(self, llexitcase): - self.ilasm.label(self.current_label('catch')) - ll_meta_exc = llexitcase - ll_exc = ll_meta_exc._inst.class_._INSTANCE - cts_exc = self.cts.lltype_to_cts(ll_exc, False) - self.ilasm.opcode('ldsfld', 'object last_exception') - self.isinstance(cts_exc) - self.ilasm.opcode('dup') - self.ilasm.opcode('brtrue.s', 6) - self.ilasm.opcode('pop') - self.ilasm.opcode('br', self.next_label('catch')) - # here is the target of the above brtrue.s - self.ilasm.opcode('ldnull') - self.ilasm.opcode('stsfld', 'object last_exception') - - def end_catch(self, target_label): - self.ilasm.opcode('br', target_label) - - def store_exception_and_link(self, link): - if self._is_raise_block(link.target): - # the exception value is on the stack, use it as the 2nd target arg - assert len(link.args) == 2 - assert len(link.target.inputargs) == 2 - self.store(link.target.inputargs[1]) - else: - # the exception value is on the stack, store it in the proper place - if isinstance(link.last_exception, flowmodel.Variable): - self.ilasm.opcode('dup') - self.store(link.last_exc_value) - self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) - self.store(link.last_exception) - else: - self.store(link.last_exc_value) - self._setup_link(link) - - def before_last_blocks(self): - self.ilasm.label(self.current_label('catch')) - self.ilasm.opcode('nop') - - def render_raise_block(self, block): - exc = block.inputargs[1] - self.load(exc) - self.ilasm.opcode('stsfld', 'object last_exception') - if not self.return_block: # must be a void function - TYPE = self.graph.getreturnvar().concretetype - default = TYPE._defl() - if default is not None: # concretetype is Void - try: - self.db.constant_generator.push_primitive_constant(self, TYPE, default) - except AssertionError: - self.ilasm.opcode('ldnull') # :-( - self.ilasm.opcode('ret') - else: - self.ilasm.opcode('br', self._get_block_name(self.return_block)) - - def _render_op(self, op): - OOFunction._render_op(self, op) - if op.opname in ('direct_call', 'oosend', 'indirect_call') and not self.in_try: - self._premature_return() - - def _render_sub_op(self, sub_op): - OOFunction._render_sub_op(self, sub_op) - if sub_op.op.opname in ('direct_call', 'oosend', 'indirect_call') and not self.in_try: - self._premature_return(need_pop=sub_op.op.result is not ootype.Void) - - - def _premature_return(self, need_pop=False): - try: - return_block = self._get_block_name(self.graph.returnblock) - except KeyError: - self.ilasm.opcode('//premature return') - self.ilasm.opcode('ldsfld', 'object last_exception') - TYPE = self.graph.getreturnvar().concretetype - default = TYPE._defl() - if default is None: # concretetype is Void - self.ilasm.opcode('brfalse.s', 1) - self.ilasm.opcode('ret') - else: - self.ilasm.opcode('brfalse.s', 3) # ?? - try: - self.db.constant_generator.push_primitive_constant(self, TYPE, default) - except AssertionError: - self.ilasm.opcode('ldnull') # :-( - self.ilasm.opcode('ret') - else: - self.ilasm.opcode('ldsfld', 'object last_exception') - self.ilasm.opcode('brtrue', return_block) - - -if USE_LAST: - ExceptionHandler = LastExceptionHandler -else: - ExceptionHandler = NativeExceptionHandler - -class Function(ExceptionHandler, OOFunction, Node, CLIBaseGenerator): +class Function(OOFunction, Node, CLIBaseGenerator): def __init__(self, *args, **kwargs): OOFunction.__init__(self, *args, **kwargs) @@ -243,6 +94,45 @@ self.load(return_var) self.ilasm.opcode('ret') + def begin_try(self): + self.ilasm.begin_try() + + def end_try(self, target_label): + self.ilasm.leave(target_label) + self.ilasm.end_try() + + def begin_catch(self, llexitcase): + ll_meta_exc = llexitcase + ll_exc = ll_meta_exc._inst.class_._INSTANCE + cts_exc = self.cts.lltype_to_cts(ll_exc, False) + self.ilasm.begin_catch(cts_exc) + + def end_catch(self, target_label): + self.ilasm.leave(target_label) + self.ilasm.end_catch() + + def render_raise_block(self, block): + exc = block.inputargs[1] + self.load(exc) + self.ilasm.opcode('throw') + + def store_exception_and_link(self, link): + if self._is_raise_block(link.target): + # the exception value is on the stack, use it as the 2nd target arg + assert len(link.args) == 2 + assert len(link.target.inputargs) == 2 + self.store(link.target.inputargs[1]) + else: + # the exception value is on the stack, store it in the proper place + if isinstance(link.last_exception, flowmodel.Variable): + self.ilasm.opcode('dup') + self.store(link.last_exc_value) + self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) + self.store(link.last_exception) + else: + self.store(link.last_exc_value) + self._setup_link(link) + # XXX: this method should be moved into oosupport, but other # backends are not ready :-( def render_bool_switch(self, block): Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Wed Aug 8 16:18:50 2007 @@ -58,7 +58,6 @@ self.code.writeline('.module %s.netmodule' % name) else: self.code.writeline('.assembly %s {}' % name) - self.code.writeline('.field static object last_exception') # XXX def close(self): self.out.close() Modified: pypy/dist/pypy/translator/cli/metavm.py ============================================================================== --- pypy/dist/pypy/translator/cli/metavm.py (original) +++ pypy/dist/pypy/translator/cli/metavm.py Wed Aug 8 16:18:50 2007 @@ -159,13 +159,6 @@ self.mapping = mapping def render(self, generator, op): - from pypy.translator.cli.function import LastExceptionHandler - if isinstance(generator, LastExceptionHandler): - self.render_last(generator, op) - else: - self.render_native(generator, op) - - def render_native(self, generator, op): ilasm = generator.ilasm label = '__check_block_%d' % MapException.COUNT MapException.COUNT += 1 @@ -181,25 +174,6 @@ ilasm.label(label) ilasm.opcode('nop') - def render_last(self, generator, op): - ilasm = generator.ilasm - stdflow = '__check_block_%d' % MapException.COUNT - MapException.COUNT += 1 - premature_return = '__check_block_%d' % MapException.COUNT - MapException.COUNT += 1 - ilasm.begin_try() - self.instr.render(generator, op) - ilasm.leave(stdflow) - ilasm.end_try() - for cli_exc, py_exc in self.mapping: - ilasm.begin_catch(cli_exc) - ilasm.new('instance void class %s::.ctor()' % py_exc) - ilasm.opcode('stsfld', 'object last_exception') - ilasm.leave(stdflow) - ilasm.end_catch() - ilasm.label(stdflow) - ilasm.opcode('nop') - class _Box(MicroInstruction): def render(self, generator, op): generator.load(op.args[0]) Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Wed Aug 8 16:18:50 2007 @@ -73,7 +73,7 @@ if return_type != 'void': ilasm.opcode('stloc', 'res') if self.wrap_exceptions: - ilasm.leave('check_last_exception') + ilasm.leave('check_etrafo_exception') else: ilasm.leave('print_result') @@ -90,16 +90,6 @@ ilasm.leave('return') ilasm.end_catch() - # check for USE_LAST exceptions - ilasm.label('check_last_exception') - ilasm.opcode('ldsfld', 'object last_exception') - ilasm.opcode('brnull', 'check_etrafo_exception') - # there is a pending exception - ilasm.opcode('ldsfld', 'object last_exception') - ilasm.call('string class [pypylib]pypy.test.Result::FormatException(object)') - ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') - ilasm.opcode('br', 'return') - # check for exception tranformer exceptions ilasm.label('check_etrafo_exception') if hasattr(self.db, 'exceptiontransformer'): @@ -256,14 +246,15 @@ self._ann = None self._cli_func = None - def _compile(self, fn, args, ann=None, backendopt=True, auto_raise_exc=False): + def _compile(self, fn, args, ann=None, backendopt=True, auto_raise_exc=False, exctrans=False): if ann is None: ann = [lltype_to_annotation(typeOf(x)) for x in args] if self._func is fn and self._ann == ann: return self._cli_func else: self._cli_func = compile_function(fn, ann, backendopt=backendopt, - auto_raise_exc=auto_raise_exc) + auto_raise_exc=auto_raise_exc, + exctrans=exctrans) self._func = fn self._ann = ann return self._cli_func @@ -276,17 +267,17 @@ if platform.processor() == 'powerpc': py.test.skip('PowerPC --> %s' % reason) - def interpret(self, fn, args, annotation=None, backendopt=True): - f = self._compile(fn, args, annotation, backendopt) + def interpret(self, fn, args, annotation=None, backendopt=True, exctrans=False): + f = self._compile(fn, args, annotation, backendopt=backendopt, exctrans=exctrans) res = f(*args) if isinstance(res, ExceptionWrapper): raise res return res - def interpret_raises(self, exception, fn, args): + def interpret_raises(self, exception, fn, args, exctrans=False): import exceptions # needed by eval try: - self.interpret(fn, args) + self.interpret(fn, args, exctrans=exctrans) except ExceptionWrapper, ex: assert issubclass(eval(ex.class_name), exception) else: Modified: pypy/dist/pypy/translator/cli/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_exception.py (original) +++ pypy/dist/pypy/translator/cli/test/test_exception.py Wed Aug 8 16:18:50 2007 @@ -3,6 +3,12 @@ from pypy.rpython.test.test_exception import BaseTestException class TestCliException(CliTest, BaseTestException): + use_exception_transformer = False + + def interpret(self, *args, **kwds): + kwds['exctrans'] = self.use_exception_transformer + return CliTest.interpret(self, *args, **kwds) + def test_nested_try(self): def helper(x): if x == 0: @@ -55,3 +61,6 @@ obj = Derived() return obj.foo() assert self.interpret(fn, [0]) == 42 + +class TestCliExceptionTransformer(TestCliException): + use_exception_transformer = True From antocuni at codespeak.net Wed Aug 8 16:24:28 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 8 Aug 2007 16:24:28 +0200 (CEST) Subject: [pypy-svn] r45555 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20070808142428.E02A480FE@code0.codespeak.net> Author: antocuni Date: Wed Aug 8 16:24:28 2007 New Revision: 45555 Removed: pypy/dist/pypy/translator/cli/stackopt.py pypy/dist/pypy/translator/cli/test/test_stackopt.py Modified: pypy/dist/pypy/translator/cli/conftest.py pypy/dist/pypy/translator/cli/gencli.py pypy/dist/pypy/translator/cli/option.py Log: kill stackopt: treebuilder does a much better job Modified: pypy/dist/pypy/translator/cli/conftest.py ============================================================================== --- pypy/dist/pypy/translator/cli/conftest.py (original) +++ pypy/dist/pypy/translator/cli/conftest.py Wed Aug 8 16:24:28 2007 @@ -26,9 +26,6 @@ Option('--norun', action='store_true', dest="norun", default=False, help="don't run the compiled executable"), - Option('--nostackopt', action='store_true', dest='nostackopt', default=False, - help="don't optimize stack load/store operations"), - Option('--trace', action='store_true', dest='trace', default=False, help='Trace execution of generated code'), ) Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Wed Aug 8 16:24:28 2007 @@ -19,7 +19,6 @@ from pypy.translator.cli.rte import get_pypy_dll from pypy.translator.cli.support import Tee from pypy.translator.cli.prebuiltnodes import get_prebuilt_nodes -from pypy.translator.cli.stackopt import StackOptGenerator from pypy.translator.cli import query from pypy.translator.cli import constant @@ -28,10 +27,6 @@ except NameError: from sets import Set as set -#USE_STACKOPT = True and not getoption('nostackopt') -USE_STACKOPT = False - - class GenCli(GenOO): TypeSystem = CTS Function = Function @@ -81,12 +76,8 @@ out = self.tmpfile.open('w') if getoption('stdout'): out = Tee(sys.stdout, out) - - if USE_STACKOPT: - return StackOptGenerator(out, self.assembly_name, self.config) - else: - isnetmodule = self.entrypoint.isnetmodule - return IlasmGenerator(out, self.assembly_name, self.config, isnetmodule) + isnetmodule = self.entrypoint.isnetmodule + return IlasmGenerator(out, self.assembly_name, self.config, isnetmodule) def build_exe(self): if getoption('source'): Modified: pypy/dist/pypy/translator/cli/option.py ============================================================================== --- pypy/dist/pypy/translator/cli/option.py (original) +++ pypy/dist/pypy/translator/cli/option.py Wed Aug 8 16:24:28 2007 @@ -1,6 +1,6 @@ from pypy.translator.cli.conftest import option -_defaultopt = dict(wd = False, source = False, nostop = False, stdout = False, nostackopt = False) +_defaultopt = dict(wd = False, source = False, nostop = False, stdout = False) def getoption(name): return getattr(option, name, _defaultopt.get(name)) From jlg at codespeak.net Wed Aug 8 18:02:37 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Wed, 8 Aug 2007 18:02:37 +0200 (CEST) Subject: [pypy-svn] r45556 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070808160237.D09C28099@code0.codespeak.net> Author: jlg Date: Wed Aug 8 18:02:36 2007 New Revision: 45556 Added: pypy/dist/pypy/lang/scheme/test/test_continuation.py (contents, props changed) Modified: pypy/dist/pypy/lang/scheme/TODO.txt pypy/dist/pypy/lang/scheme/execution.py pypy/dist/pypy/lang/scheme/object.py Log: ellipses in same templ. obj. with different match length -> error; naive, stack-only implementation of continuations Modified: pypy/dist/pypy/lang/scheme/TODO.txt ============================================================================== --- pypy/dist/pypy/lang/scheme/TODO.txt (original) +++ pypy/dist/pypy/lang/scheme/TODO.txt Wed Aug 8 18:02:36 2007 @@ -1,7 +1,10 @@ Do now ------ -- lambda called with wrong number of arguments issue +- continuations + +continuation frame must be saved fot every non tail-call +(for tail calls there is no cc) Do next ------- @@ -16,8 +19,8 @@ Here starts the real fun! -- macros - * macros are not first-class objects -- continuations +- lambda called with wrong number of arguments issue +- macros *are* not first-class objects + - switch to byte-code generation + eval instead of evaluating AST Modified: pypy/dist/pypy/lang/scheme/execution.py ============================================================================== --- pypy/dist/pypy/lang/scheme/execution.py (original) +++ pypy/dist/pypy/lang/scheme/execution.py Wed Aug 8 18:02:36 2007 @@ -19,7 +19,8 @@ { "IDENTIFIER": Location(W_Root()) } """ - def __init__(self, globalscope=None, scope=None, closure=False): + def __init__(self, globalscope=None, scope=None, closure=False, + cont_stack=None): if globalscope is None: self.globalscope = {} for name, oper in OPERATION_MAP.items(): @@ -35,6 +36,11 @@ self.closure = closure + if cont_stack is None: + self.cont_stack = [] + else: + self.cont_stack = cont_stack + def _dispatch(self, symb): if isinstance(symb, ssobject.SymbolClosure): return (symb.closure, symb.name) @@ -45,7 +51,8 @@ raise ssobject.SchemeSyntaxError def copy(self): - return ExecutionContext(self.globalscope, self.scope.copy(), True) + return ExecutionContext(self.globalscope, self.scope.copy(), True, + self.cont_stack) def get(self, name): loc = self.scope.get(name, None) Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Wed Aug 8 18:02:36 2007 @@ -244,18 +244,34 @@ def call(self, ctx, lst): raise NotImplementedError - def eval_body(self, ctx, body): + def eval_body(self, ctx, body, cnt=False): body_expression = body - while True: - if not isinstance(body_expression, W_Pair): - raise SchemeSyntaxError - elif body_expression.cdr is w_nil: - return (body_expression.car, ctx) + while isinstance(body_expression, W_Pair): + if body_expression.cdr is w_nil: + if cnt is False: + return (body_expression.car, ctx) + + if ctx is None: + result = body_expression.car + else: + result = body_expression.car.eval(ctx) + + if len(ctx.cont_stack) == 0: + raise ContinuationReturn(result) + + cont = ctx.cont_stack.pop() + return cont.run(ctx, result) + else: + ctx.cont_stack.append( + ContinuationFrame(self, body_expression.cdr)) body_expression.car.eval(ctx) + ctx.cont_stack.pop() body_expression = body_expression.cdr + raise SchemeSyntaxError + class W_Procedure(W_Callable): def __init__(self, pname=""): self.pname = pname @@ -264,17 +280,45 @@ return "#" % (self.pname,) def call_tr(self, ctx, lst): + return self.continue_tr(ctx, lst, [], False) + + def continue_tr(self, ctx, lst, elst, cnt=True): #evaluate all arguments into list - arg_lst = [] + arg_lst = elst arg = lst - while not arg is w_nil: - if not isinstance(arg, W_Pair): - raise SchemeSyntaxError + while isinstance(arg, W_Pair): + #this is non tail-call, it should create continuation frame + # continuation frame consist: + # - plst of arleady evaluated arguments + # - arg (W_Pair) = arg.cdr as a pointer to not evaluated + # arguments + # - actual context + ctx.cont_stack.append(ContinuationFrame(self, arg.cdr, arg_lst)) w_obj = arg.car.eval(ctx) + ctx.cont_stack.pop() + arg_lst.append(w_obj) arg = arg.cdr - return self.procedure_tr(ctx, arg_lst) + if arg is not w_nil: + raise SchemeSyntaxError + + procedure_result = self.procedure_tr(ctx, arg_lst) + if cnt is False: + return procedure_result + + #if procedure_result still has to be evaluated + # this can happen in case if self isinstance of W_Lambda + if procedure_result[1] is None: + procedure_result = procedure_result[0] + else: + procedure_result = procedure_result[0].eval(procedure_result[1]) + + if len(ctx.cont_stack) == 0: + raise ContinuationReturn(procedure_result) + + cont = ctx.cont_stack.pop() + return cont.run(ctx, procedure_result) def procedure(self, ctx, lst): raise NotImplementedError @@ -291,6 +335,10 @@ def to_string(self): return "#" % (self.pname,) + def continue_tr(self, ctx, lst, elst, cnt=True): + lst = W_Pair(elst[0], lst) + return self.eval_body(ctx, lst, cnt=True) + class Formal(object): def __init__(self, name, islist=False): self.name = name @@ -1083,6 +1131,7 @@ return self.substitute(ctx, template, match_dict) def find_elli(self, expr, mdict): + #filter mdict, returning only ellipsis which appear in expr if isinstance(expr, W_Pair): edict_car = self.find_elli(expr.car, mdict) edict_cdr = self.find_elli(expr.cdr, mdict) @@ -1137,12 +1186,17 @@ return self.substituter(ctx, w_outer, match_dict, True) plst = [] - #find_elli gets part of match_dict relevant to sexpr.car + #find_elli gets ellipses from match_dict relevant to sexpr.car mdict_elli = self.find_elli(sexpr.car, match_dict) elli_len = 0 for (key, val) in mdict_elli.items(): - assert elli_len == 0 or elli_len == len(val.mdict_lst) - elli_len = len(val.mdict_lst) + if elli_len == 0 or elli_len == len(val.mdict_lst): + elli_len = len(val.mdict_lst) + else: + #we can treat is as an error if ellipsis has + # different match length + # # or get the shortest one + raise SchemeSyntaxError #generate elli_len substitutions for ellipsis for i in range(elli_len): @@ -1183,7 +1237,7 @@ w_sub = match_dict.get(sexpr.name, None) if w_sub is not None: - # Hygenic macros close their input forms in the syntactic + #Hygenic macros close their input forms in the syntactic # enviroment at the point of use if isinstance(w_sub, Ellipsis): @@ -1277,3 +1331,58 @@ return self.eval_body(local_ctx, lst.cdr) +class ContinuationReturn(SchemeException): + def __init__(self, result): + self.result = result + +class ContinuationFrame(object): + def __init__(self, callable, continuation, evaluated_args = []): + assert isinstance(callable, W_Callable) + self.callable = callable + assert isinstance(continuation, W_Root) + self.continuation = continuation + assert isinstance(evaluated_args, list) + #XXX copying of evaluated_args here is SLOW, + # it should ocur only on continuation capture + self.evaluated_args = evaluated_args[:] + + def run(self, ctx, arg): + elst = self.evaluated_args[:] + elst.append(arg) + print self.callable.to_string(), elst, self.continuation + return self.callable.continue_tr(ctx, self.continuation, elst, True) + +class Continuation(W_Procedure): + def __init__(self, ctx, continuation): + self.closure = ctx #XXX to .copy() ot not to .copy() + #copy of continuation stack + self.cont_stack = continuation[:] + try: + self.continuation = self.cont_stack.pop() + except IndexError: + #continuation captured on top-level + self.continuation = None + + def procedure_tr(self, ctx, lst): + if len(lst) == 0: + lst.append(w_undefined) + + print "Continuation called" + self.closure.cont_stack = self.cont_stack[:] + cont = self.continuation + if cont is None: + raise ContinuationReturn(lst[0]) + + return cont.run(self.closure, lst[0]) + +class CallCC(W_Procedure): + _symbol_name = "call/cc" + + def procedure_tr(self, ctx, lst): + if len(lst) != 1 or not isinstance(lst[0], W_Procedure): + raise SchemeSyntaxError + + w_lambda = lst[0] + cc = Continuation(ctx, ctx.cont_stack) + return w_lambda.call_tr(ctx, W_Pair(cc, w_nil)) + Added: pypy/dist/pypy/lang/scheme/test/test_continuation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lang/scheme/test/test_continuation.py Wed Aug 8 18:02:36 2007 @@ -0,0 +1,109 @@ +import py +from pypy.lang.scheme.ssparser import parse +from pypy.lang.scheme.execution import ExecutionContext +from pypy.lang.scheme.object import * + +def eval_(ctx, expr): + try: + return parse(expr)[0].eval(ctx) + except ContinuationReturn, e: + return e.result + +def test_callcc(): + ctx = ExecutionContext() + + eval_(ctx, "(define cont #f)") + w_result = eval_(ctx, """(call/cc (lambda (k) (set! cont k) 3))""") + + w_result = eval_(ctx, "(cont 3)") + assert w_result.to_number() == 3 + w_result = eval_(ctx, "(cont #f)") + assert w_result.to_boolean() is False + + #this (+ 1 [...]) should be ingored + w_result = eval_(ctx, "(+ 1 (cont 3))") + assert w_result.to_number() == 3 + w_result = eval_(ctx, "(+ 1 (cont #t))") + assert w_result.to_boolean() is True + +def test_simple_multi_shot(): + ctx = ExecutionContext() + + eval_(ctx, "(define cont #f)") + w_result = eval_(ctx, """ + (+ 1 2 (call/cc (lambda (k) (set! cont k) 3)) 4)""") + + assert w_result.to_number() == 10 + assert isinstance(eval_(ctx, "cont"), W_Procedure) + w_result = eval_(ctx, "(cont 0)") + assert w_result.to_number() == 7 + w_result = eval_(ctx, "(cont 3)") + assert w_result.to_number() == 10 + +def test_nested_multi_shot(): + ctx = ExecutionContext() + + eval_(ctx, "(define cont #f)") + w_result = eval_(ctx, """ + (* 2 (+ 1 2 (call/cc (lambda (k) (set! cont k) 3)) 4) 1)""") + assert w_result.to_number() == 20 + w_result = eval_(ctx, "(cont 0)") + assert w_result.to_number() == 14 + w_result = eval_(ctx, "(cont 3)") + assert w_result.to_number() == 20 + +def test_as_lambda_arg(): + ctx = ExecutionContext() + + eval_(ctx, "(define cont #f)") + eval_(ctx, "(define (add3 a1 a2 a3) (+ a3 a2 a1))") + w_result = eval_(ctx, """ + (add3 (call/cc (lambda (k) (set! cont k) 3)) 2 1)""") + assert w_result.to_number() == 6 + w_result = eval_(ctx, "(cont 0)") + assert w_result.to_number() == 3 + w_result = eval_(ctx, "(cont 3)") + assert w_result.to_number() == 6 + +def test_the_continuation(): + ctx = ExecutionContext() + + eval_(ctx, "(define con #f)") + eval_(ctx, """ + (define (test) + (let ((i 0)) + (call/cc (lambda (k) (set! con k))) + ; The next time tc is called, we start here. + (set! i (+ i 1)) + i))""") + + assert eval_(ctx, "(test)").to_number() == 1 + assert eval_(ctx, "(con)").to_number() == 2 + assert eval_(ctx, "(con)").to_number() == 3 + eval_(ctx, "(define con2 con)") + assert eval_(ctx, "(test)").to_number() == 1 + assert eval_(ctx, "(con)").to_number() == 2 + assert eval_(ctx, "(con2)").to_number() == 4 + assert eval_(ctx, "(+ 1 (con2))").to_number() == 5 + +def test_the_continuation_x2(): + ctx = ExecutionContext() + + eval_(ctx, "(define con #f)") + eval_(ctx, """ + (define (test) + (* 2 + (let ((i 0)) + (call/cc (lambda (k) (set! con k))) + (set! i (+ i 1)) + i)))""") + + assert eval_(ctx, "(test)").to_number() == 2 + assert eval_(ctx, "(con)").to_number() == 4 + assert eval_(ctx, "(con)").to_number() == 6 + eval_(ctx, "(define con2 con)") + assert eval_(ctx, "(test)").to_number() == 2 + assert eval_(ctx, "(con)").to_number() == 4 + assert eval_(ctx, "(con2)").to_number() == 8 + assert eval_(ctx, "(+ 1 (con2))").to_number() == 10 + From fijal at codespeak.net Wed Aug 8 23:55:44 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 8 Aug 2007 23:55:44 +0200 (CEST) Subject: [pypy-svn] r45557 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20070808215544.E7B9A8120@code0.codespeak.net> Author: fijal Date: Wed Aug 8 23:55:43 2007 New Revision: 45557 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py Log: Improve error reporting Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Wed Aug 8 23:55:43 2007 @@ -1097,7 +1097,12 @@ raise TypeError,"calling %r with wrong argument number: %r" % (self._T, args) for a, ARG in zip(args, self._T.ARGS): if typeOf(a) != ARG: - raise TypeError,"calling %r with wrong argument types: %r" % (self._T, args) + try: + args_repr = [arg._T for arg in args] + except: + # well... + args_repr = args + raise TypeError,"calling %r with wrong argument types: %r" % (self._T, args_repr) callb = self._obj._callable if callb is None: raise RuntimeError,"calling undefined function" From fijal at codespeak.net Thu Aug 9 00:11:29 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 9 Aug 2007 00:11:29 +0200 (CEST) Subject: [pypy-svn] r45558 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20070808221129.EFF558117@code0.codespeak.net> Author: fijal Date: Thu Aug 9 00:11:29 2007 New Revision: 45558 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py Log: Different error reporting, now should work. Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Thu Aug 9 00:11:29 2007 @@ -1097,11 +1097,7 @@ raise TypeError,"calling %r with wrong argument number: %r" % (self._T, args) for a, ARG in zip(args, self._T.ARGS): if typeOf(a) != ARG: - try: - args_repr = [arg._T for arg in args] - except: - # well... - args_repr = args + args_repr = [typeOf(arg) for arg in args] raise TypeError,"calling %r with wrong argument types: %r" % (self._T, args_repr) callb = self._obj._callable if callb is None: From fijal at codespeak.net Thu Aug 9 01:17:45 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 9 Aug 2007 01:17:45 +0200 (CEST) Subject: [pypy-svn] r45559 - pypy/dist/pypy/translator/c/src Message-ID: <20070808231745.83F5F8119@code0.codespeak.net> Author: fijal Date: Thu Aug 9 01:17:42 2007 New Revision: 45559 Modified: pypy/dist/pypy/translator/c/src/thread.h Log: Make sure we don't import this twice Modified: pypy/dist/pypy/translator/c/src/thread.h ============================================================================== --- pypy/dist/pypy/translator/c/src/thread.h (original) +++ pypy/dist/pypy/translator/c/src/thread.h Thu Aug 9 01:17:42 2007 @@ -1,6 +1,9 @@ /* #ifdef logic from CPython */ +#ifndef __PYPY_THREAD_H +#define __PYPY_THREAD_H + #ifndef _POSIX_THREADS /* This means pthreads are not implemented in libc headers, hence the macro not present in unistd.h. But they still can be implemented as an external @@ -35,3 +38,5 @@ #define RPyThreadStaticTLS_Set(key, value) RPyThreadTLS_Set(key, value) #endif + +#endif From fijal at codespeak.net Thu Aug 9 01:18:37 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 9 Aug 2007 01:18:37 +0200 (CEST) Subject: [pypy-svn] r45560 - in pypy/dist/pypy/module/thread: . test Message-ID: <20070808231837.694CB8119@code0.codespeak.net> Author: fijal Date: Thu Aug 9 01:18:36 2007 New Revision: 45560 Modified: pypy/dist/pypy/module/thread/ll_thread.py pypy/dist/pypy/module/thread/test/test_ll_thread.py Log: Rffi implementation of start_new_thread, quite unsafe though and a bit of XXX around, I would really appreciate if someone take a look at it Modified: pypy/dist/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/ll_thread.py (original) +++ pypy/dist/pypy/module/thread/ll_thread.py Thu Aug 9 01:18:36 2007 @@ -4,9 +4,9 @@ from pypy.rpython.lltypesystem.rffi import platform from pypy.rpython.extfunc import genericcallable from pypy.module.thread.os_thread import Bootstrapper +from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.translator.tool.cbuild import cache_c_module -from pypy.rpython.annlowlevel import cast_instance_to_base_ptr,\ - cast_base_ptr_to_instance +from pypy.rpython.lltypesystem import llmemory import thread, py from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel @@ -27,14 +27,14 @@ def __init__(self, ll_lock): self._lock = ll_lock -includes = ['unistd.h', 'thread.h'] +includes = ['unistd.h', 'src/thread.h'] +from pypy.tool.autopath import pypydir +pypydir = py.path.local(pypydir) +srcdir = pypydir.join('translator', 'c', 'src') def setup_thread_so(): - from pypy.tool.autopath import pypydir - pypydir = py.path.local(pypydir) - srcdir = pypydir.join('translator', 'c', 'src') - modname = '_thread' files = [srcdir.join('thread.c')] + modname = '_thread' cache_c_module(files, modname, include_dirs=[str(srcdir)]) return str(pypydir.join('_cache', modname)) + '.so' libraries = [setup_thread_so()] @@ -43,9 +43,9 @@ return rffi.llexternal(name, args, result, includes=includes, libraries=libraries) -CALLBACK = lltype.FuncType([rffi.VOIDP], rffi.VOIDP) +CALLBACK = lltype.Ptr(lltype.FuncType([rffi.VOIDP], rffi.VOIDP)) c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT) -c_thread_get_ident = llexternal('RPyThreadGetIdent', [], lltype.Void) +c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT) TLOCKP = rffi.COpaque('struct RPyOpaque_ThreadLock', includes=includes) @@ -71,46 +71,45 @@ finally: c_thread_releaselock(lock._lock) +# a simple wrapper, not to expose C functions (is this really necessary?) +def ll_get_ident(): + return c_thread_get_ident() + +def start_new_thread(x, y): + raise NotImplementedError("Should never be invoked directly") + def ll_start_new_thread(l_func, arg): l_arg = cast_instance_to_base_ptr(arg) - ident = c_thread_start(l_func, l_arg) - if ident == -1: - raise ThreadError("can't start new thread") - return ident + l_arg = rffi.cast(rffi.VOIDP, l_arg) + return c_thread_start(l_func, l_arg) class LLStartNewThread(ExtRegistryEntry): - _about_ = ll_start_new_thread - + _about_ = start_new_thread + def compute_result_annotation(self, s_func, s_arg): bookkeeper = self.bookkeeper - assert s_func.is_constant(), "Cannot call ll_start_new_thread with non-constant function" s_result = bookkeeper.emulate_pbc_call(bookkeeper.position_key, s_func, [s_arg]) - assert annmodel.s_None.contains(s_result), ( - """thread.start_new_thread(f, arg): f() should return None""") + assert annmodel.s_None.contains(s_result) return annmodel.SomeInteger() - - def compute_annotation_bk(self, bookkeeper): - return annmodel.SomePBC([bookkeeper.getdesc(self.instance)]) - + def specialize_call(self, hop): rtyper = hop.rtyper - bookkeeper = rtyper.annotator.bookkeeper - _callable = hop.args_s[0].const + bk = rtyper.annotator.bookkeeper + r_result = rtyper.getrepr(hop.s_result) + hop.exception_is_here() args_r = [rtyper.getrepr(s_arg) for s_arg in hop.args_s] - ll_arg = args_r[1].lowleveltype - _type = lltype.FuncType([ll_arg], lltype.Void) - funcptr = lltype.functionptr(_type, _callable.func_name, + _callable = hop.args_s[0].const + funcptr = lltype.functionptr(CALLBACK.TO, _callable.func_name, _callable=_callable) - r_result = rtyper.getrepr(hop.s_result) - ll_result = r_result.lowleveltype - args_s = [bookkeeper.immutablevalue(i) for i in [funcptr, ll_arg]] + func_s = bk.immutablevalue(funcptr) + s_args = [func_s, hop.args_s[1]] obj = rtyper.getannmixlevel().delayedfunction( - ll_start_new_thread, args_s, annmodel.SomeInteger()) - vlist = [hop.inputconst(typeOf(obj), obj)] + hop.inputargs(*args_r) - hop.exception_is_here() + ll_start_new_thread, s_args, annmodel.SomeInteger()) + bootstrap = rtyper.getannmixlevel().delayedfunction( + _callable, [hop.args_s[1]], annmodel.s_None) + vlist = [hop.inputconst(typeOf(obj), obj), + hop.inputconst(typeOf(bootstrap), bootstrap), + #hop.inputarg(args_r[0], 0), + hop.inputarg(args_r[1], 1)] return hop.genop('direct_call', vlist, r_result) - -# a simple wrapper, not to expose C functions (is this really necessary?) -def ll_get_ident(): - return c_thread_get_ident() Modified: pypy/dist/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/dist/pypy/module/thread/test/test_ll_thread.py Thu Aug 9 01:18:36 2007 @@ -1,6 +1,7 @@ from pypy.module.thread.ll_thread import * from pypy.translator.c.test.test_genc import compile +from pypy.rpython.lltypesystem import lltype import py def test_lock(): @@ -16,25 +17,28 @@ l = ll_allocate_lock() py.test.raises(ThreadError, ll_release_lock, l) -def test_thread_init_new(): - """ This test works only after translation - """ - py.test.skip("does not work") +def test_start_new_thread(): import time - import thread - - class X(BaseBootstrapper): + class Y: + _alloc_flavor_ = 'raw' + def __init__(self): self.top = [] def bootstrap(self): - self.top.append(1) + self.top.append(ll_get_ident()) def f(): - x = X() - ll_start_new_thread(X.bootstrap, x) - time.sleep(.3) - return len(x.top) + y = Y() + start_new_thread(Y.bootstrap, y) + time.sleep(1) + res = len(y.top) + lltype.free(y.top, flavor='raw') + lltype.free(y, flavor='raw') + return res == ll_get_ident() + # XXX is this testable on top of llinterp at all? fn = compile(f, []) - assert fn() == 1 + # XXX where does additional malloc come from??? + assert fn(expected_extra_mallocs=1) == False + From fijal at codespeak.net Thu Aug 9 09:39:38 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 9 Aug 2007 09:39:38 +0200 (CEST) Subject: [pypy-svn] r45561 - pypy/dist/pypy/module/thread Message-ID: <20070809073938.4E5158109@code0.codespeak.net> Author: fijal Date: Thu Aug 9 09:39:36 2007 New Revision: 45561 Modified: pypy/dist/pypy/module/thread/ll_thread.py Log: Oops, didn't mean to kill error handling Modified: pypy/dist/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/ll_thread.py (original) +++ pypy/dist/pypy/module/thread/ll_thread.py Thu Aug 9 09:39:36 2007 @@ -81,7 +81,10 @@ def ll_start_new_thread(l_func, arg): l_arg = cast_instance_to_base_ptr(arg) l_arg = rffi.cast(rffi.VOIDP, l_arg) - return c_thread_start(l_func, l_arg) + ident = c_thread_start(l_func, l_arg) + if ident == -1: + raise ThreadError("can't start new thread") + return ident class LLStartNewThread(ExtRegistryEntry): _about_ = start_new_thread From antocuni at codespeak.net Thu Aug 9 11:35:06 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 9 Aug 2007 11:35:06 +0200 (CEST) Subject: [pypy-svn] r45565 - pypy/dist/pypy/translator/cli/test Message-ID: <20070809093506.761688117@code0.codespeak.net> Author: antocuni Date: Thu Aug 9 11:35:05 2007 New Revision: 45565 Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py Log: remove the last references to the killed USE_LAST flag. Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/dist/pypy/translator/cli/test/test_dotnet.py Thu Aug 9 11:35:05 2007 @@ -174,11 +174,6 @@ def _skip_pythonnet(self, msg): pass - def _skip_exception(self): - from pypy.translator.cli import function - if function.USE_LAST: - py.test.skip("Fixme!") - def test_staticmeth_call(self): def fn(x): return Math.Abs(x) @@ -292,7 +287,6 @@ assert self.interpret(fn, []) is None def test_native_exception_precise(self): - self._skip_exception() ArgumentOutOfRangeException = NativeException(CLR.System.ArgumentOutOfRangeException) def fn(): x = ArrayList() @@ -304,7 +298,6 @@ assert self.interpret(fn, []) == True def test_native_exception_superclass(self): - self._skip_exception() SystemException = NativeException(CLR.System.Exception) def fn(): x = ArrayList() @@ -316,7 +309,6 @@ assert self.interpret(fn, []) == True def test_native_exception_object(self): - self._skip_exception() SystemException = NativeException(CLR.System.Exception) def fn(): x = ArrayList() @@ -330,7 +322,6 @@ assert res.startswith("Index is less than 0") def test_native_exception_invoke(self): - self._skip_exception() TargetInvocationException = NativeException(CLR.System.Reflection.TargetInvocationException) def fn(): x = ArrayList() From antocuni at codespeak.net Thu Aug 9 15:22:58 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 9 Aug 2007 15:22:58 +0200 (CEST) Subject: [pypy-svn] r45568 - pypy/dist/pypy/doc/discussion Message-ID: <20070809132258.3C9D88118@code0.codespeak.net> Author: antocuni Date: Thu Aug 9 15:22:56 2007 New Revision: 45568 Modified: pypy/dist/pypy/doc/discussion/outline-external-ootype.txt Log: some notes about a new approach to external objects. Modified: pypy/dist/pypy/doc/discussion/outline-external-ootype.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/outline-external-ootype.txt (original) +++ pypy/dist/pypy/doc/discussion/outline-external-ootype.txt Thu Aug 9 15:22:56 2007 @@ -8,7 +8,7 @@ * SomeCliXxx for .NET backend BasicExternal -============= +------------- * Is using types to make rpython happy (ie, every single method or field is hardcoded) @@ -18,7 +18,7 @@ * Supports fields, also with callable fields SomeCliXxx -========== +---------- * Supports method overloading @@ -39,4 +39,175 @@ manually or automatically. * Should support superset of needs of all backends (ie callbacks, - method overloading, etc.) \ No newline at end of file + method overloading, etc.) + + +Proposal of alternative approach +================================ + +The goal of the task is to let RPython program access "external +objects" which are available in the target platform; these include: + + - external classes (e.g. for .NET: System.Collections.ArrayList) + + - external instances (e.g. for js: window, window.document) + + - external functions? (they are not needed for .NET and JVM, maybe + for js?) + +External objects should behave as much as possible as "internal +objects". + +Moreover, we want to preserve the possibility of *testing* RPython +programs on top of CPython if possible. For example, it should be +possible to RPython programs using .NET external objects using +PythonNet; probably there is something similar for JVM, but not for +JS as I know. + + +How to represent types +---------------------- + +First, some definitions: + + - high-level types are the types used by the annotator + (SomeInteger() & co.) + + - low-level types are the types used by the rtyper (Signed & co.) + + - platform-level types are the types used by the backends (e.g. int32 for + .NET) + +Usually, RPython types are described "top-down": we start from the +annotation, then the rtyper transforms the high-level types into +low-level types, then the backend transforms low-level types into +platform-level types. E.g. for .NET, SomeInteger() -> Signed -> int32. + +External objects are different: we *already* know the platform-level +types of our objects and we can't modify them. What we need to do is +to specify an annotation that after the high-level -> low-level -> +platform-level transformation will give us the correct types. + +For primitive types it is usually easy to find the correct annotation; +if we have an int32, we know that it's ootype is Signed and the +corresponding annotation is SomeInteger(). + +For non-primitive types such as classes, we must use a "bottom-up" +approach: first, we need a description of platform-level interface of +the class; then we construct the corresponding low-level type and +teach the backends how to treat such "external types". Finally, we +wrap the low-level types into special "external annotation". + +For example, consider a simple existing .NET class:: + + class Foo { + public float bar(int x, int y) { ... } + } + +The corresponding low-level type could be something like this:: + + Foo = ootype.ExternalInstance({'bar': ([Signed, Signed], Float)}) + +Then, the annotation for Foo's intances is SomeExternalInstance(Foo). +This way, the transformation from high-level types to platform-level +types is straightforward and correct. + +Finally, we need support for static methods: similarly for classes, we +can define an ExternalStaticMeth low-level type and a +SomeExternalStaticMeth annotation. + + +How to describe types +--------------------- + +To handle external objects we must specify their signatures. For CLI +and JVM the job can be easily automatized, since the objects have got +precise signatures. + +For JS, signatures must be written by hand, so we must provide a +convenient syntax for it; I think it should be possible to use the +current syntax and write a tool which translates it to low-level +types. + + +RPython interface +----------------- + +External objects are exposed as special Python objects that gets +annotated as SomeExternalXXX. Each backend can choose its own way to +provide these objects to the RPython programmer. + +External classes will be annotated as SomeExternalClass; two +operations are allowed: + + - call: used to instantiate the class, return an object which will + be annotated as SomeExternalInstance. + + - access to static methods: return an object which will be annotated + as SomeExternalStaticMeth. + +Instances are annotated as SomeExternalInstance. Prebuilt external +objects (such as JS's window.document) are annotated as +SomeExternalInstance(const=...). + +Open issues +----------- + +Exceptions +~~~~~~~~~~ + +.NET and JVM users want to catch external exceptions in a natuarl way; +e.g.:: + + try: + ... + except System.OverflowException: + ... + +This is not straighforward because to make the flow objspace happy the +object which represent System.OverflowException must be a real Python +class that inherits from Exception. + +This means that the Python objects which represent external classes +must be Python classes itself, and that classes representing +exceptions must be special cased and made subclasses of Exception. + + +Inheritance +~~~~~~~~~~~ + +It would be nice to allow programmers to inherit from an external +class. Not sure about the implications, though. + +Callbacks +~~~~~~~~~ + +I know that they are an issue for JS, but I don't know how they are +currently implemented. + +Special methods/properties +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In .NET there are special methods that can be accessed using a special +syntax, for example indexer or properties. It would be nice to have in +RPython the same syntax as C#. + + +Implementation details +---------------------- + +The CLI backend use a similar approach right now, but it could be +necessary to rewrite a part of it. + +To represent low-level types, it uses NativeInstance, a subclass of +ootype.Instance that contains all the informations needed by the +backend to reference the class (e.g., the namespace). It also supports +overloading. + +For annotations, it reuses SomeOOInstance, which is also a wrapper +around a low-level type but it has been designed for low-level +helpers. It might be saner to use another annotation not to mix apples +and oranges, maybe factoring out common code. + +I don't know whether and how much code can be reused from the exising +bltregistry. From jlg at codespeak.net Thu Aug 9 16:33:30 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Thu, 9 Aug 2007 16:33:30 +0200 (CEST) Subject: [pypy-svn] r45569 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070809143330.E212D810A@code0.codespeak.net> Author: jlg Date: Thu Aug 9 16:33:29 2007 New Revision: 45569 Modified: pypy/dist/pypy/lang/scheme/TODO.txt pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_continuation.py Log: W_Callable.eval_body is no more, Body(W_Root) now in charge; W_Pair operator is now call/cc frindly, funny (call/cc call/cc) tests Modified: pypy/dist/pypy/lang/scheme/TODO.txt ============================================================================== --- pypy/dist/pypy/lang/scheme/TODO.txt (original) +++ pypy/dist/pypy/lang/scheme/TODO.txt Thu Aug 9 16:33:29 2007 @@ -10,7 +10,7 @@ ------- - implement key functions - (apply, reduce, map and so on) + (apply, map and so on) - comparison: < > eq? eqv? Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Thu Aug 9 16:33:29 2007 @@ -105,7 +105,7 @@ return self.boolval def __repr__(self): - return "" + return "" class W_String(W_Root): def __init__(self, val): @@ -115,7 +115,7 @@ return self.strval def __repr__(self): - return "" + return "" class W_Real(W_Root): def __init__(self, val): @@ -210,8 +210,32 @@ def __repr__(self): return "" + def continue_tr(self, ctx, lst, elst, cnt=True): + oper = elst[0] + if not isinstance(oper, W_Callable): + raise NotCallable(oper) + + cdr = lst + if isinstance(cdr, W_List): + result = oper.call_tr(ctx, cdr) + else: + raise SchemeSyntaxError + + if result[1] is None: + result = result[0] + else: + result = result[0].eval(result[1]) + + if len(ctx.cont_stack) == 0: + raise ContinuationReturn(result) + + cont = ctx.cont_stack.pop() + return cont.run(ctx, result) + def eval_tr(self, ctx): + ctx.cont_stack.append(ContinuationFrame(self, self.cdr)) oper = self.car.eval(ctx) + ctx.cont_stack.pop() if not isinstance(oper, W_Callable): raise NotCallable(oper) @@ -244,7 +268,14 @@ def call(self, ctx, lst): raise NotImplementedError - def eval_body(self, ctx, body, cnt=False): +class Body(W_Root): + def __init__(self, body): + self.body = body + + def eval_tr(self, ctx): + return self.continue_tr(ctx, self.body, [], False) + + def continue_tr(self, ctx, body, elst, cnt=True): body_expression = body while isinstance(body_expression, W_Pair): if body_expression.cdr is w_nil: @@ -335,10 +366,6 @@ def to_string(self): return "#" % (self.pname,) - def continue_tr(self, ctx, lst, elst, cnt=True): - lst = W_Pair(elst[0], lst) - return self.eval_body(ctx, lst, cnt=True) - class Formal(object): def __init__(self, name, islist=False): self.name = name @@ -361,7 +388,7 @@ self.args.append(Formal(arg.car.to_string(), False)) arg = arg.cdr - self.body = body + self.body = Body(body) self.pname = pname self.closure = closure @@ -382,7 +409,7 @@ else: local_ctx.put(formal.name, lst[idx]) - return self.eval_body(local_ctx, self.body) + return self.body.eval_tr(local_ctx) def plst2lst(plst, w_cdr=w_nil): """coverts python list() of W_Root into W_Pair scheme list""" @@ -673,6 +700,20 @@ return w_obj.round() % 2 == 0 +#XXX no tests for it +class PairP(W_Procedure): + _symbol_name = "pair?" + + def procedure(self, ctx, lst): + if len(lst) != 1: + raise WrongArgsNumber + + w_obj = lst[0] + if isinstance(w_obj, W_Pair): + return W_Boolean(True) + + return W_Boolean(False) + ## # Macro ## @@ -750,7 +791,7 @@ def call_tr(self, ctx, lst): #begin uses eval_body, so it is tail-recursive aware - return self.eval_body(ctx, lst) + return Body(lst).eval_tr(ctx) class Let(W_Macro): _symbol_name = "let" @@ -768,7 +809,7 @@ local_ctx.sput(w_def.car, w_val) w_formal = w_formal.cdr - return self.eval_body(local_ctx, lst.cdr) + return Body(lst.cdr).eval_tr(local_ctx) class LetStar(W_Macro): _symbol_name = "let*" @@ -786,7 +827,7 @@ local_ctx.sput(w_def.car, w_val) w_formal = w_formal.cdr - return self.eval_body(local_ctx, lst.cdr) + return Body(lst.cdr).eval_tr(local_ctx) class Letrec(W_Macro): _symbol_name = "letrec" @@ -814,7 +855,7 @@ for (name, w_val) in map_name_val.items(): local_ctx.ssete(map_name_symb[name], w_val) - return self.eval_body(local_ctx, lst.cdr) + return Body(lst.cdr).eval_tr(local_ctx) def quote(sexpr): return W_Pair(W_Symbol('quote'), W_Pair(sexpr, w_nil)) @@ -1329,7 +1370,7 @@ local_ctx.put(w_name.name, w_macro) w_formal = w_formal.cdr - return self.eval_body(local_ctx, lst.cdr) + return Body(lst.cdr).eval_tr(local_ctx) class ContinuationReturn(SchemeException): def __init__(self, result): @@ -1337,7 +1378,7 @@ class ContinuationFrame(object): def __init__(self, callable, continuation, evaluated_args = []): - assert isinstance(callable, W_Callable) + assert hasattr(callable, "continue_tr") self.callable = callable assert isinstance(continuation, W_Root) self.continuation = continuation @@ -1363,11 +1404,14 @@ #continuation captured on top-level self.continuation = None + def to_string(self): + return "# %s>" % (self.continuation,) + def procedure_tr(self, ctx, lst): if len(lst) == 0: lst.append(w_undefined) - print "Continuation called" + print "Continuation called", self.cont_stack self.closure.cont_stack = self.cont_stack[:] cont = self.continuation if cont is None: Modified: pypy/dist/pypy/lang/scheme/test/test_continuation.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_continuation.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_continuation.py Thu Aug 9 16:33:29 2007 @@ -9,6 +9,21 @@ except ContinuationReturn, e: return e.result +def test_callcc_callcc(): + ctx = ExecutionContext() + w_procedure = eval_(ctx, "(call/cc call/cc)") + assert isinstance(w_procedure, W_Procedure) + print w_procedure + + eval_(ctx, "(define cont 'none)") + w_result = eval_(ctx, """((call/cc call/cc) (lambda (k) + (set! cont k) + 'done))""") + assert w_result.to_string() == "done" + assert isinstance(eval_(ctx, "cont"), W_Procedure) + eval_(ctx, "(cont +)") + assert eval_(ctx, "cont") is ctx.get("+") + def test_callcc(): ctx = ExecutionContext() @@ -107,3 +122,17 @@ assert eval_(ctx, "(con2)").to_number() == 8 assert eval_(ctx, "(+ 1 (con2))").to_number() == 10 +def test_escape_continuation(): + ctx = ExecutionContext() + + eval_(ctx, "(define ret-failed #f)") + w_result = eval_(ctx, """ + (let ((test 17)) + (call/cc (lambda (return) + (if (odd? test) (return 'odd)) + (set! ret-failed #t) + 'even)))""") + + assert w_result.to_string() == "odd" + assert eval_(ctx, "ret-failed").to_boolean() == False + From fijal at codespeak.net Thu Aug 9 17:50:34 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 9 Aug 2007 17:50:34 +0200 (CEST) Subject: [pypy-svn] r45570 - in pypy/dist/pypy/module/thread: . test Message-ID: <20070809155034.8122E8105@code0.codespeak.net> Author: fijal Date: Thu Aug 9 17:50:33 2007 New Revision: 45570 Modified: pypy/dist/pypy/module/thread/ll_thread.py pypy/dist/pypy/module/thread/test/test_ll_thread.py Log: Various improvements, be more thread-like in API, Modified: pypy/dist/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/ll_thread.py (original) +++ pypy/dist/pypy/module/thread/ll_thread.py Thu Aug 9 17:50:33 2007 @@ -3,7 +3,6 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.rffi import platform from pypy.rpython.extfunc import genericcallable -from pypy.module.thread.os_thread import Bootstrapper from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.translator.tool.cbuild import cache_c_module from pypy.rpython.lltypesystem import llmemory @@ -11,28 +10,19 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem.lltype import typeOf +from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.nonconst import NonConstant -class BaseBootstrapper: - def bootstrap(self): - pass - -class ThreadError(Exception): +class error(Exception): def __init__(self, msg): self.msg = msg -class Lock(object): - """ Container for low-level implementation - of a lock object - """ - def __init__(self, ll_lock): - self._lock = ll_lock - includes = ['unistd.h', 'src/thread.h'] -from pypy.tool.autopath import pypydir -pypydir = py.path.local(pypydir) -srcdir = pypydir.join('translator', 'c', 'src') def setup_thread_so(): + from pypy.tool.autopath import pypydir + pypydir = py.path.local(pypydir) + srcdir = pypydir.join('translator', 'c', 'src') files = [srcdir.join('thread.c')] modname = '_thread' cache_c_module(files, modname, include_dirs=[str(srcdir)]) @@ -54,40 +44,26 @@ rffi.INT) c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void) -def ll_allocate_lock(): +def allocate_lock(): ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') res = c_thread_lock_init(ll_lock) if res == -1: - raise ThreadError("out of resources") + raise error("out of resources") return Lock(ll_lock) -def ll_acquire_lock(lock, waitflag): - return c_thread_acuirelock(lock._lock, waitflag) - -def ll_release_lock(lock): - try: - if ll_acquire_lock(lock, 0): - raise ThreadError("bad lock") - finally: - c_thread_releaselock(lock._lock) - -# a simple wrapper, not to expose C functions (is this really necessary?) -def ll_get_ident(): - return c_thread_get_ident() - -def start_new_thread(x, y): - raise NotImplementedError("Should never be invoked directly") +def _start_new_thread(x, y): + return thread.start_new_thread(x, (y,)) def ll_start_new_thread(l_func, arg): l_arg = cast_instance_to_base_ptr(arg) l_arg = rffi.cast(rffi.VOIDP, l_arg) ident = c_thread_start(l_func, l_arg) if ident == -1: - raise ThreadError("can't start new thread") + raise error("can't start new thread") return ident class LLStartNewThread(ExtRegistryEntry): - _about_ = start_new_thread + _about_ = _start_new_thread def compute_result_annotation(self, s_func, s_arg): bookkeeper = self.bookkeeper @@ -116,3 +92,38 @@ #hop.inputarg(args_r[0], 0), hop.inputarg(args_r[1], 1)] return hop.genop('direct_call', vlist, r_result) + +# wrappers... + +def get_ident(): + return c_thread_get_ident() + +def start_new_thread(x, y): + return _start_new_thread(x, y[0]) + +class Lock(object): + """ Container for low-level implementation + of a lock object + """ + def __init__(self, ll_lock): + self._lock = ll_lock + + def acquire(self, flag): + return bool(c_thread_acuirelock(self._lock, int(flag))) + + def release(self): + try: + if self.acquire(False): + # XXX the annotator trick to annotate it with non-const + # string, probably should be put into bltn-analyzers + raise error(NonConstant("bad lock")) + finally: + c_thread_releaselock(self._lock) + + def fused_release_acquire(self): + self.release() + self.acquire(True) + + def __del__(self): + lltype.free(self._lock, flavor='raw') + Modified: pypy/dist/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/dist/pypy/module/thread/test/test_ll_thread.py Thu Aug 9 17:50:33 2007 @@ -5,17 +5,22 @@ import py def test_lock(): - l = ll_allocate_lock() - ok1 = ll_acquire_lock(l, 1) - ok2 = ll_acquire_lock(l, 0) - ll_release_lock(l) - ok3 = ll_acquire_lock(l, 0) + l = allocate_lock() + ok1 = l.acquire(True) + ok2 = l.acquire(False) + l.release() + ok3 = l.acquire(False) res = ok1 and not ok2 and ok3 assert res == 1 def test_thread_error(): - l = ll_allocate_lock() - py.test.raises(ThreadError, ll_release_lock, l) + l = allocate_lock() + try: + l.release() + except error: + pass + else: + py.test.fail("Did not raise") def test_start_new_thread(): import time @@ -26,19 +31,29 @@ self.top = [] def bootstrap(self): - self.top.append(ll_get_ident()) - + self.top.append(get_ident()) + def f(): y = Y() - start_new_thread(Y.bootstrap, y) - time.sleep(1) + start_new_thread(Y.bootstrap, (y,)) + time.sleep(.3) res = len(y.top) - lltype.free(y.top, flavor='raw') lltype.free(y, flavor='raw') - return res == ll_get_ident() + return 1 == get_ident() + # for some reason, refcounting does not handle _alloc_flavor_ = 'raw' # XXX is this testable on top of llinterp at all? - fn = compile(f, []) - # XXX where does additional malloc come from??? - assert fn(expected_extra_mallocs=1) == False + fn = compile(f, [], gcpolicy='boehm') + assert fn() == False + +def test_prebuilt_lock(): + l = allocate_lock() + + def f(): + l.acquire(True) + l.release() + + fn = compile(f, [], gcpolicy='boehm') + fn() + From cfbolz at codespeak.net Thu Aug 9 19:58:14 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 9 Aug 2007 19:58:14 +0200 (CEST) Subject: [pypy-svn] r45575 - pypy/dist/pypy/rpython/ootypesystem Message-ID: <20070809175814.0E22D8117@code0.codespeak.net> Author: cfbolz Date: Thu Aug 9 19:58:13 2007 New Revision: 45575 Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py Log: use nice py-lib facility for this Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Thu Aug 9 19:58:13 2007 @@ -6,10 +6,6 @@ from pypy.rlib import objectmodel from pypy.tool.uid import uid -try: - set -except NameError: - from sets import Set as set STATICNESS = True @@ -923,7 +919,7 @@ self._check_overloadings() def _check_overloadings(self): - signatures = set() + signatures = py.builtin.set() for meth in self.overloadings: ARGS = meth._TYPE.ARGS if ARGS in signatures: From cfbolz at codespeak.net Thu Aug 9 19:59:22 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 9 Aug 2007 19:59:22 +0200 (CEST) Subject: [pypy-svn] r45576 - pypy/dist/pypy/rpython/ootypesystem Message-ID: <20070809175922.1E79C8118@code0.codespeak.net> Author: cfbolz Date: Thu Aug 9 19:59:22 2007 New Revision: 45576 Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py Log: Eventually I will learn. Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Thu Aug 9 19:59:22 2007 @@ -1,3 +1,4 @@ +import py from pypy.rpython.lltypesystem.lltype import LowLevelType, Signed, Unsigned, Float, Char from pypy.rpython.lltypesystem.lltype import Bool, Void, UniChar, typeOf, \ Primitive, isCompatibleType, enforce, saferecursive, SignedLongLong, UnsignedLongLong From fijal at codespeak.net Thu Aug 9 20:49:16 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 9 Aug 2007 20:49:16 +0200 (CEST) Subject: [pypy-svn] r45577 - in pypy/dist/pypy/objspace/flow: . test Message-ID: <20070809184916.0651E8119@code0.codespeak.net> Author: fijal Date: Thu Aug 9 20:49:15 2007 New Revision: 45577 Modified: pypy/dist/pypy/objspace/flow/objspace.py pypy/dist/pypy/objspace/flow/test/test_objspace.py Log: Explode when encountering generators (heh, I'm curious whether I did the right thing) Modified: pypy/dist/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/objspace.py (original) +++ pypy/dist/pypy/objspace/flow/objspace.py Thu Aug 9 20:49:15 2007 @@ -237,6 +237,9 @@ if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'): raise Exception, "%r is tagged as NOT_RPYTHON" % (func,) code = func.func_code + if code.co_flags & 32: + # generator + raise TypeError("%r is a generator" % (func,)) code = PyCode._from_code(self, code) if func.func_closure is None: closure = None Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_objspace.py Thu Aug 9 20:49:15 2007 @@ -825,6 +825,11 @@ assert all_ops['simple_call'] == 2 assert all_ops['getattr'] == 1 + def test_generator(self): + def f(): + yield 3 + + py.test.raises(TypeError, "self.codetest(f)") class TestFlowObjSpaceDelay(Base): def setup_class(cls): From jlg at codespeak.net Thu Aug 9 20:53:31 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Thu, 9 Aug 2007 20:53:31 +0200 (CEST) Subject: [pypy-svn] r45578 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070809185331.29FB5811A@code0.codespeak.net> Author: jlg Date: Thu Aug 9 20:53:30 2007 New Revision: 45578 Modified: pypy/dist/pypy/lang/scheme/interactive.py pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_continuation.py Log: W_Eval is base class for objects which are not evaluating to self; eval_cf evals object and create continuation frame for it; interactive interpreter handles ContinuationReturn Modified: pypy/dist/pypy/lang/scheme/interactive.py ============================================================================== --- pypy/dist/pypy/lang/scheme/interactive.py (original) +++ pypy/dist/pypy/lang/scheme/interactive.py Thu Aug 9 20:53:30 2007 @@ -3,7 +3,8 @@ scheme interpreter """ import autopath -from pypy.lang.scheme.object import SchemeException, SchemeQuit +from pypy.lang.scheme.object import SchemeException, SchemeQuit,\ + ContinuationReturn from pypy.lang.scheme.execution import ExecutionContext from pypy.lang.scheme.ssparser import parse from pypy.rlib.parsing.makepackrat import BacktrackException @@ -34,10 +35,12 @@ print parse(to_exec)[0].eval(ctx).to_string() except SchemeQuit, e: break - except BacktrackException, e: - print "syntax error" + except ContinuationReturn, e: + print e.result.to_string() except SchemeException, e: print "error: %s" % e + except BacktrackException, e: + print "syntax error" to_exec = "" cont = False Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Thu Aug 9 20:53:30 2007 @@ -40,6 +40,9 @@ def __repr__(self): return "" + def eval_cf(self, ctx, caller, cont, elst=[]): + return self.eval(ctx) + def eval(self, ctx): w_expr = self while ctx is not None: @@ -171,13 +174,37 @@ def to_float(self): return float(self.intval) -class W_List(W_Root): +class W_Eval(W_Root): + #this class is for objects which does more than + # evaluate to themselves + def eval_cf(self, ctx, caller, cont, elst=[]): + #eval with continuation frame! + ctx.cont_stack.append(ContinuationFrame(caller, cont, elst)) + result = self.eval(ctx) + ctx.cont_stack.pop() + return result + + def continue_tr(self, ctx, lst, elst, cnt=True): + raise NotImplementedError + +class W_List(W_Eval): pass class W_Nil(W_List): + def __repr__(self): + return "" + def to_string(self): return "()" + def eval_cf(self, ctx, caller, cont, elst=[]): + #XXX not tests here + raise SchemeSyntaxError + + def eval_tr(self, ctx): + #XXX not tests here + raise SchemeSyntaxError + w_nil = W_Nil() class W_Pair(W_List): @@ -233,9 +260,7 @@ return cont.run(ctx, result) def eval_tr(self, ctx): - ctx.cont_stack.append(ContinuationFrame(self, self.cdr)) - oper = self.car.eval(ctx) - ctx.cont_stack.pop() + oper = self.car.eval_cf(ctx, self, self.cdr) if not isinstance(oper, W_Callable): raise NotCallable(oper) @@ -259,7 +284,7 @@ raise SchemeSyntaxError return res -class W_Callable(W_Root): +class W_Callable(W_Eval): def call_tr(self, ctx, lst): #usually tail-recursive call is normal call # which returns tuple with no further ExecutionContext @@ -268,7 +293,7 @@ def call(self, ctx, lst): raise NotImplementedError -class Body(W_Root): +class Body(W_Eval): def __init__(self, body): self.body = body @@ -294,10 +319,7 @@ return cont.run(ctx, result) else: - ctx.cont_stack.append( - ContinuationFrame(self, body_expression.cdr)) - body_expression.car.eval(ctx) - ctx.cont_stack.pop() + body_expression.car.eval_cf(ctx, self, body_expression.cdr) body_expression = body_expression.cdr @@ -324,9 +346,7 @@ # - arg (W_Pair) = arg.cdr as a pointer to not evaluated # arguments # - actual context - ctx.cont_stack.append(ContinuationFrame(self, arg.cdr, arg_lst)) - w_obj = arg.car.eval(ctx) - ctx.cont_stack.pop() + w_obj = arg.car.eval_cf(ctx, self, arg.cdr, arg_lst) arg_lst.append(w_obj) arg = arg.cdr Modified: pypy/dist/pypy/lang/scheme/test/test_continuation.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_continuation.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_continuation.py Thu Aug 9 20:53:30 2007 @@ -9,21 +9,6 @@ except ContinuationReturn, e: return e.result -def test_callcc_callcc(): - ctx = ExecutionContext() - w_procedure = eval_(ctx, "(call/cc call/cc)") - assert isinstance(w_procedure, W_Procedure) - print w_procedure - - eval_(ctx, "(define cont 'none)") - w_result = eval_(ctx, """((call/cc call/cc) (lambda (k) - (set! cont k) - 'done))""") - assert w_result.to_string() == "done" - assert isinstance(eval_(ctx, "cont"), W_Procedure) - eval_(ctx, "(cont +)") - assert eval_(ctx, "cont") is ctx.get("+") - def test_callcc(): ctx = ExecutionContext() @@ -41,6 +26,21 @@ w_result = eval_(ctx, "(+ 1 (cont #t))") assert w_result.to_boolean() is True +def test_callcc_callcc(): + ctx = ExecutionContext() + w_procedure = eval_(ctx, "(call/cc call/cc)") + assert isinstance(w_procedure, W_Procedure) + print w_procedure + + eval_(ctx, "(define cont 'none)") + w_result = eval_(ctx, """((call/cc call/cc) (lambda (k) + (set! cont k) + 'done))""") + assert w_result.to_string() == "done" + assert isinstance(eval_(ctx, "cont"), W_Procedure) + eval_(ctx, "(cont +)") + assert eval_(ctx, "cont") is ctx.get("+") + def test_simple_multi_shot(): ctx = ExecutionContext() From fijal at codespeak.net Fri Aug 10 11:38:11 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 10 Aug 2007 11:38:11 +0200 (CEST) Subject: [pypy-svn] r45580 - pypy/extradoc/talk/dresden Message-ID: <20070810093811.708388136@code0.codespeak.net> Author: fijal Date: Fri Aug 10 11:38:09 2007 New Revision: 45580 Added: pypy/extradoc/talk/dresden/ pypy/extradoc/talk/dresden/talk.txt (contents, props changed) Log: Add a draft of the Dresden talk Added: pypy/extradoc/talk/dresden/talk.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dresden/talk.txt Fri Aug 10 11:38:09 2007 @@ -0,0 +1,114 @@ +What is PyPy? +============== + +- multiplatform compiler toolchain + +- flexible interpreter + +- an open source project + +- STReP + +Python - quick summary +====================== + +- interpreted language + +- very dynamic and introspective + +- diversity of implementations + (platforms, features, JIT) + +- (?)complex + +Our goal +======== + +- write (runnable) specification in high-level + language (RPython) + +- use python as a meta-programming language + for RPython + +- reason: C is to low level to analyze + efficiently + +Single source approach +====================== + +- multiple backends (C, CLI, JVM coming...) [m] + +- multiple interpreter (Python, Javascript, scheme...) [n] + +- multiple different approaches + (JIT, stackless, gc, threading, ...) [o] + +- in summary m+n+o code, not m*n*o + +Forest of flow graphs/translation +================================= + +XXX interactive demo of pygame viewer + +Transformation approach +======================= + +- most of our optimisations/safety checks + are done as a graph transformation + +- example - stack checks + +- example - gc (modeled after Jikes MMtk) + +XXX side-by-side comparison of CPython and PyPy source code +XXX string formatting sounds like a candidate + +Objspace concept +================ + +- single place where operations on objects + are performed + +Taint objspace +============== + +XXX (picture probably is worth thousand words here) + +Multiple object implementation +============================== + +- variety of different implementations per + interpreter type + +- example: multidict + +- example: ropes + +Transparent proxies +=================== + +- works as a different object implementation + +- intercepts all operations on objects + and calls app-level code + +- very much like .NET transparent proxy + +Custom persistance scheme +========================= + +- can be implemented on top of tproxy + +- using whatever storage mechanism + +- XXX + +Sandboxing +========== + +- replace all external calls by stream writing methods + +- create a custom library to cope with that + +- some demo? + From jlg at codespeak.net Fri Aug 10 15:06:44 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 10 Aug 2007 15:06:44 +0200 (CEST) Subject: [pypy-svn] r45582 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070810130644.AF83B817E@code0.codespeak.net> Author: jlg Date: Fri Aug 10 15:06:43 2007 New Revision: 45582 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_continuation.py Log: creation of ContinuationFrame is no longer copying elst; define is continuation friendly now Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Fri Aug 10 15:06:43 2007 @@ -40,7 +40,7 @@ def __repr__(self): return "" - def eval_cf(self, ctx, caller, cont, elst=[]): + def eval_cf(self, ctx, caller, cont, elst=[], enum=0): return self.eval(ctx) def eval(self, ctx): @@ -177,9 +177,9 @@ class W_Eval(W_Root): #this class is for objects which does more than # evaluate to themselves - def eval_cf(self, ctx, caller, cont, elst=[]): + def eval_cf(self, ctx, caller, cont, elst=[], enum=0): #eval with continuation frame! - ctx.cont_stack.append(ContinuationFrame(caller, cont, elst)) + ctx.cont_stack.append(ContinuationFrame(caller, cont, elst, enum)) result = self.eval(ctx) ctx.cont_stack.pop() return result @@ -197,7 +197,7 @@ def to_string(self): return "()" - def eval_cf(self, ctx, caller, cont, elst=[]): + def eval_cf(self, ctx, caller, cont, elst=[], enum=0): #XXX not tests here raise SchemeSyntaxError @@ -338,6 +338,7 @@ def continue_tr(self, ctx, lst, elst, cnt=True): #evaluate all arguments into list arg_lst = elst + arg_num = 0 arg = lst while isinstance(arg, W_Pair): #this is non tail-call, it should create continuation frame @@ -346,8 +347,9 @@ # - arg (W_Pair) = arg.cdr as a pointer to not evaluated # arguments # - actual context - w_obj = arg.car.eval_cf(ctx, self, arg.cdr, arg_lst) + w_obj = arg.car.eval_cf(ctx, self, arg.cdr, arg_lst, arg_num) + arg_num += 1 arg_lst.append(w_obj) arg = arg.cdr @@ -740,13 +742,25 @@ class Define(W_Macro): _symbol_name = "define" + def continue_tr(self, ctx, lst, elst, cnt=True): + w_first = elst[0] + w_val = elst[1] + if isinstance(w_first, W_Symbol): + ctx.set(w_first.name, w_val) + return (w_val, None) + elif isinstance(w_first, W_Pair): + #XXX no tests here + raise NotImplementedError + + raise SchemeSyntaxError + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError w_first = lst.car w_second = lst.get_cdr_as_pair() if isinstance(w_first, W_Symbol): - w_val = w_second.car.eval(ctx) + w_val = w_second.car.eval_cf(ctx, self, w_first, [w_first], 1) ctx.set(w_first.name, w_val) return w_val #undefined elif isinstance(w_first, W_Pair): @@ -760,8 +774,8 @@ w_lambda = W_Lambda(formals, body, ctx, pname=w_name.name) ctx.set(w_name.name, w_lambda) return w_lambda #undefined - else: - raise SchemeSyntaxError + + raise SchemeSyntaxError class Sete(W_Macro): _symbol_name = "set!" @@ -1397,25 +1411,24 @@ self.result = result class ContinuationFrame(object): - def __init__(self, callable, continuation, evaluated_args = []): + def __init__(self, callable, continuation, evaluated_args = [], enum=0): assert hasattr(callable, "continue_tr") self.callable = callable assert isinstance(continuation, W_Root) self.continuation = continuation assert isinstance(evaluated_args, list) - #XXX copying of evaluated_args here is SLOW, - # it should ocur only on continuation capture - self.evaluated_args = evaluated_args[:] + self.evaluated_args = evaluated_args + self.evaluated_args_num = enum def run(self, ctx, arg): - elst = self.evaluated_args[:] + elst = self.evaluated_args[:self.evaluated_args_num] elst.append(arg) print self.callable.to_string(), elst, self.continuation return self.callable.continue_tr(ctx, self.continuation, elst, True) class Continuation(W_Procedure): def __init__(self, ctx, continuation): - self.closure = ctx #XXX to .copy() ot not to .copy() + self.closure = ctx #to .copy() ot not to .copy() #copy of continuation stack self.cont_stack = continuation[:] try: Modified: pypy/dist/pypy/lang/scheme/test/test_continuation.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_continuation.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_continuation.py Fri Aug 10 15:06:43 2007 @@ -88,7 +88,7 @@ (define (test) (let ((i 0)) (call/cc (lambda (k) (set! con k))) - ; The next time tc is called, we start here. + ; The next time con is called, we start here. (set! i (+ i 1)) i))""") @@ -136,3 +136,46 @@ assert w_result.to_string() == "odd" assert eval_(ctx, "ret-failed").to_boolean() == False +def test_loop(): + ctx = ExecutionContext() + + eval_(ctx, "(define k 'none)") + eval_(ctx, "(define num 'none)") + w_result = eval_(ctx, """ + (call/cc + (lambda (return) + (letrec ((loop + (lambda (n) + (if (zero? n) + 0 + (begin + (call/cc (lambda (cc) + (set! k cc) + (return n))) + (set! num n) + (loop (- n 1))))))) + (loop 10))))""") + + assert w_result.to_number() == 10 + assert isinstance(ctx.get("k"), Continuation) + assert ctx.get("num").to_string() == "none" + + for i in range(9, -1, -1): + w_result = eval_(ctx, "(k)") + assert w_result.to_number() == i + assert ctx.get("num").to_number() == i+1 + + w_result = eval_(ctx, "(k)") + assert w_result.to_number() == 0 + assert ctx.get("num").to_number() == 1 + +def test_let_define(): + ctx = ExecutionContext() + + eval_(ctx, """(define oo + (let ((cont (call/cc (lambda (k) k)))) + cont))""") + assert isinstance(ctx.get("oo"), Continuation) + eval_(ctx, "(oo +)") + assert ctx.get("oo") is ctx.get("+") + From cfbolz at codespeak.net Fri Aug 10 15:17:09 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 10 Aug 2007 15:17:09 +0200 (CEST) Subject: [pypy-svn] r45583 - in pypy/dist/pypy/lang/prolog: builtin interpreter/test Message-ID: <20070810131709.7F7A08180@code0.codespeak.net> Author: cfbolz Date: Fri Aug 10 15:17:06 2007 New Revision: 45583 Modified: pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py pypy/dist/pypy/lang/prolog/interpreter/test/test_arithmetic.py Log: fix problem of comparisons Modified: pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py ============================================================================== --- pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py (original) +++ pypy/dist/pypy/lang/prolog/builtin/arithmeticbuiltin.py Fri Aug 10 15:17:06 2007 @@ -41,10 +41,20 @@ eq = False if isinstance(num1, term.Number): if isinstance(num2, term.Number): - eq = num1.num %s num2.num - elif isinstance(num1, term.Float): - if isinstance(num2, term.Float): - eq = num1.floatval %s num2.floatval + if not (num1.num %s num2.num): + raise error.UnificationFailed() + else: + return + n1 = num1.num + else: + assert isinstance(num1, term.Float) + n1 = num1.floatval + if isinstance(num2, term.Number): + n2 = num2.num + else: + assert isinstance(num2, term.Float) + n2 = num2.floatval + eq = n1 %s n2 if not eq: raise error.UnificationFailed()""" % (ext, python, python)).compile() expose_builtin(globals()["impl_arith_%s" % (ext, )], prolog, Modified: pypy/dist/pypy/lang/prolog/interpreter/test/test_arithmetic.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/test/test_arithmetic.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/test/test_arithmetic.py Fri Aug 10 15:17:06 2007 @@ -99,5 +99,6 @@ assert_true("1 + 0.001 >= 1 + 0.001.") assert_true("1 + 0.001 =< 1 + 0.001.") assert_false("1 > 1.") + assert_true("1.1 > 1.") assert_false("1 =\\= 1.0.") assert_true("1 =\\= 32.") From antocuni at codespeak.net Fri Aug 10 21:10:54 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 10 Aug 2007 21:10:54 +0200 (CEST) Subject: [pypy-svn] r45589 - in pypy/dist/pypy/translator: cli cli/test js jvm oosupport Message-ID: <20070810191054.31DAF8167@code0.codespeak.net> Author: antocuni Date: Fri Aug 10 21:10:52 2007 New Revision: 45589 Modified: pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_exception.py pypy/dist/pypy/translator/js/function.py pypy/dist/pypy/translator/jvm/node.py pypy/dist/pypy/translator/oosupport/function.py Log: let .NET to propagate automatically not catched exceptions. Probably this should be enabled also for genjvm. Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Fri Aug 10 21:10:52 2007 @@ -20,10 +20,15 @@ class Function(OOFunction, Node, CLIBaseGenerator): + auto_propagate_exceptions = True + def __init__(self, *args, **kwargs): OOFunction.__init__(self, *args, **kwargs) + + if hasattr(self.db.genoo, 'exceptiontransformer'): + self.auto_propagate_exceptions = False + namespace = getattr(self.graph.func, '_namespace_', None) - str if namespace: if '.' in namespace: self.namespace, self.classname = namespace.rsplit('.', 1) @@ -94,12 +99,16 @@ self.load(return_var) self.ilasm.opcode('ret') - def begin_try(self): - self.ilasm.begin_try() - - def end_try(self, target_label): - self.ilasm.leave(target_label) - self.ilasm.end_try() + def begin_try(self, cond): + if cond: + self.ilasm.begin_try() + + def end_try(self, target_label, cond): + if cond: + self.ilasm.leave(target_label) + self.ilasm.end_try() + else: + self.ilasm.branch(target_label) def begin_catch(self, llexitcase): ll_meta_exc = llexitcase Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Fri Aug 10 21:10:52 2007 @@ -274,10 +274,10 @@ raise res return res - def interpret_raises(self, exception, fn, args, exctrans=False): + def interpret_raises(self, exception, fn, args, backendopt=True, exctrans=False): import exceptions # needed by eval try: - self.interpret(fn, args, exctrans=exctrans) + self.interpret(fn, args, backendopt=backendopt, exctrans=exctrans) except ExceptionWrapper, ex: assert issubclass(eval(ex.class_name), exception) else: Modified: pypy/dist/pypy/translator/cli/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_exception.py (original) +++ pypy/dist/pypy/translator/cli/test/test_exception.py Fri Aug 10 21:10:52 2007 @@ -62,5 +62,20 @@ return obj.foo() assert self.interpret(fn, [0]) == 42 + def test_missing_handler(self): + def foo(x): + if x: + raise ValueError + + def fn(x): + try: + foo(x) + except ValueError: + raise + return 42 + assert self.interpret(fn, [0], backendopt=False) == 42 + self.interpret_raises(ValueError, fn, [1], backendopt=False) + + class TestCliExceptionTransformer(TestCliException): use_exception_transformer = True Modified: pypy/dist/pypy/translator/js/function.py ============================================================================== --- pypy/dist/pypy/translator/js/function.py (original) +++ pypy/dist/pypy/translator/js/function.py Fri Aug 10 21:10:52 2007 @@ -195,9 +195,10 @@ def render_raise_block(self, block): self.ilasm.throw(block.inputargs[1]) - def end_try(self, target_label): + def end_try(self, target_label, cond): self.ilasm.jump_block(self.block_map[target_label]) - self.ilasm.catch() + if cond: + self.ilasm.catch() #self.ilasm.close_branch() def record_ll_meta_exc(self, ll_meta_exc): @@ -226,8 +227,9 @@ self.ilasm.write_case(self.block_map[label]) #self.ilasm.label(label) - def begin_try(self): - self.ilasm.begin_try() + def begin_try(self, cond): + if cond: + self.ilasm.begin_try() def clean_stack(self): self.ilasm.clean_stack() Modified: pypy/dist/pypy/translator/jvm/node.py ============================================================================== --- pypy/dist/pypy/translator/jvm/node.py (original) +++ pypy/dist/pypy/translator/jvm/node.py Fri Aug 10 21:10:52 2007 @@ -280,12 +280,14 @@ def set_label(self, blocklbl): self.ilasm.mark(blocklbl) - def begin_try(self): - self.ilasm.begin_try() + def begin_try(self, cond): + if cond: + self.ilasm.begin_try() - def end_try(self, exit_label): + def end_try(self, exit_label, cond): self.ilasm.branch_unconditionally(exit_label) - self.ilasm.end_try() + if cond: + self.ilasm.end_try() def begin_catch(self, llexitcase): ll_meta_exc = llexitcase Modified: pypy/dist/pypy/translator/oosupport/function.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/function.py (original) +++ pypy/dist/pypy/translator/oosupport/function.py Fri Aug 10 21:10:52 2007 @@ -11,6 +11,8 @@ class Function(object): + + auto_propagate_exceptions = False def __init__(self, db, graph, name = None, is_method = False, is_entrypoint = False): self.db = db @@ -140,9 +142,17 @@ for op in block.operations[:-1]: self._render_op(op) + anyHandler = False + for link in block.exits: + if link.exitcase is None: + continue + if not self._is_raise_block(link.target): + anyHandler = True + anyHandler = anyHandler or not self.auto_propagate_exceptions + # render the last one (if any!) and prepend a .try if block.operations: - self.begin_try() + self.begin_try(anyHandler) self._render_op(block.operations[-1]) # search for the "default" block to be executed when no @@ -150,7 +160,7 @@ for link in block.exits: if link.exitcase is None: self._setup_link(link) - self.end_try(self._get_block_name(link.target)) + self.end_try(self._get_block_name(link.target), anyHandler) break else: assert False, "No non-exceptional case from exc_handling block" @@ -160,6 +170,8 @@ if link.exitcase is None: continue # see above assert issubclass(link.exitcase, py.builtin.BaseException) + if self._is_raise_block(link.target) and self.auto_propagate_exceptions: + continue # let the exception propagate ll_meta_exc = link.llexitcase self.record_ll_meta_exc(ll_meta_exc) self.begin_catch(link.llexitcase) From fijal at codespeak.net Sat Aug 11 11:46:22 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 11 Aug 2007 11:46:22 +0200 (CEST) Subject: [pypy-svn] r45595 - in pypy/dist/pypy/module/thread: . test Message-ID: <20070811094622.E5DF5819C@code0.codespeak.net> Author: fijal Date: Sat Aug 11 11:46:22 2007 New Revision: 45595 Modified: pypy/dist/pypy/module/thread/ll_thread.py pypy/dist/pypy/module/thread/test/test_ll_thread.py Log: * skip non-working test * fix include_dirs problem Modified: pypy/dist/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/ll_thread.py (original) +++ pypy/dist/pypy/module/thread/ll_thread.py Sat Aug 11 11:46:22 2007 @@ -17,12 +17,12 @@ def __init__(self, msg): self.msg = msg -includes = ['unistd.h', 'src/thread.h'] +from pypy.tool.autopath import pypydir +pypydir = py.path.local(pypydir) +srcdir = pypydir.join('translator', 'c', 'src') +includes = ['unistd.h', 'thread.h'] def setup_thread_so(): - from pypy.tool.autopath import pypydir - pypydir = py.path.local(pypydir) - srcdir = pypydir.join('translator', 'c', 'src') files = [srcdir.join('thread.c')] modname = '_thread' cache_c_module(files, modname, include_dirs=[str(srcdir)]) @@ -31,7 +31,7 @@ def llexternal(name, args, result): return rffi.llexternal(name, args, result, includes=includes, - libraries=libraries) + libraries=libraries, include_dirs=[str(srcdir)]) CALLBACK = lltype.Ptr(lltype.FuncType([rffi.VOIDP], rffi.VOIDP)) c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT) Modified: pypy/dist/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/dist/pypy/module/thread/test/test_ll_thread.py Sat Aug 11 11:46:22 2007 @@ -47,6 +47,7 @@ assert fn() == False def test_prebuilt_lock(): + py.test.skip("Does not work (prebuilt opaque object)") l = allocate_lock() def f(): From fijal at codespeak.net Sat Aug 11 11:58:09 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 11 Aug 2007 11:58:09 +0200 (CEST) Subject: [pypy-svn] r45596 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20070811095809.7DBD481A9@code0.codespeak.net> Author: fijal Date: Sat Aug 11 11:58:08 2007 New Revision: 45596 Modified: pypy/dist/pypy/rpython/lltypesystem/rfficache.py Log: Don't modify argument. Modified: pypy/dist/pypy/rpython/lltypesystem/rfficache.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rfficache.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rfficache.py Sat Aug 11 11:58:08 2007 @@ -35,6 +35,7 @@ # always include pypy include dir pypypath = py.path.local(pypydir) + include_dirs = include_dirs[:] include_dirs.append(str(pypypath.join('translator', 'c', 'src'))) c_exec = build_executable([str(c_file)], include_dirs=include_dirs, From lucio at codespeak.net Sat Aug 11 16:30:29 2007 From: lucio at codespeak.net (lucio at codespeak.net) Date: Sat, 11 Aug 2007 16:30:29 +0200 (CEST) Subject: [pypy-svn] r45598 - in pypy/branch/flex-backend/pypy/translator/flex: . jssrc modules sandbox sandbox/ll_os_path sandbox/py Message-ID: <20070811143029.A069F81AA@code0.codespeak.net> Author: lucio Date: Sat Aug 11 16:30:27 2007 New Revision: 45598 Added: pypy/branch/flex-backend/pypy/translator/flex/sandbox/ll_os_path/ pypy/branch/flex-backend/pypy/translator/flex/sandbox/ll_os_path/ll_join.as Modified: pypy/branch/flex-backend/pypy/translator/flex/_class.py pypy/branch/flex-backend/pypy/translator/flex/asmgen.py pypy/branch/flex-backend/pypy/translator/flex/database.py pypy/branch/flex-backend/pypy/translator/flex/function.py pypy/branch/flex-backend/pypy/translator/flex/js.py pypy/branch/flex-backend/pypy/translator/flex/jsbuiltin.py pypy/branch/flex-backend/pypy/translator/flex/jssrc/misc.as pypy/branch/flex-backend/pypy/translator/flex/metavm.py pypy/branch/flex-backend/pypy/translator/flex/modules/flex.py pypy/branch/flex-backend/pypy/translator/flex/sandbox/chimp.py pypy/branch/flex-backend/pypy/translator/flex/sandbox/fun.py pypy/branch/flex-backend/pypy/translator/flex/sandbox/misc.as pypy/branch/flex-backend/pypy/translator/flex/sandbox/output.mxml pypy/branch/flex-backend/pypy/translator/flex/sandbox/py/StringBuilder.as Log: chimp.py compiles!! Modified: pypy/branch/flex-backend/pypy/translator/flex/_class.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/_class.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/_class.py Sat Aug 11 16:30:27 2007 @@ -47,7 +47,7 @@ self.ilasm = ilasm ilasm.push_gen("py/%s.as"%self.name) - + ilasm.set_push(False) if not self.is_root(self.classdef): basename = self.basename(self.classdef._superclass._name) if basename != 'Root': @@ -57,16 +57,16 @@ else: ilasm.begin_class(self.name) - ilasm.begin_function(self.name, [], push=False) + ilasm.begin_function(self.name, []) # we need to copy here all the arguments self.copy_class_attributes(ilasm) - ilasm.end_function(pop=False) + ilasm.end_function() # begin to_String method - ilasm.begin_method("toString", self.name, [], push=False) + ilasm.begin_method("toString", self.name, []) ilasm.load_str("'<%s object>'" % self.real_name) ilasm.ret() - ilasm.end_function(pop=False) + ilasm.end_function() #for f_name, (f_type, f_default) in self.classdef._fields.iteritems(): # cts_type = self.cts.lltype_to_cts(f_type) @@ -77,6 +77,7 @@ for m_name, m_meth in self.classdef._methods.iteritems(): graph = getattr(m_meth, 'graph', None) + if m_name=="o__init__": continue if graph: f = self.db.genoo.Function(self.db, graph, m_name, is_method = True, _class = self.name) f.render(ilasm) @@ -87,7 +88,9 @@ self.db.record_class(self.classdef, self.name) + ilasm.set_push(True) ilasm.end_class() + ilasm.pop_gen() def copy_class_attributes(self, ilasm): Modified: pypy/branch/flex-backend/pypy/translator/flex/asmgen.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/asmgen.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/asmgen.py Sat Aug 11 16:30:27 2007 @@ -75,6 +75,10 @@ self.right_hand = Queue([], self.subst_table) self.codegenerator = CodeGenerator(outfile) self.gen_stack = [] + self.push = True + + def set_push(self, value): + self.push = value def push_gen(self, generator): self.gen_stack.append( self.codegenerator ) @@ -89,32 +93,34 @@ def close(self): self.outfile.close() - def begin_function(self, name, arglist, push=True): - if push: + def begin_function(self, name, arglist): + if self.push: self.push_gen("py/"+name+".as") self.codegenerator.write("package py ") self.codegenerator.openblock() - self.codegenerator.writeline("import py.__consts_0;") - + self.codegenerator.writeline("import py._consts_0;") + self.codegenerator.writeline("import ll_os_path.ll_join;") + args = ",".join([i[1] for i in arglist]) self.codegenerator.write("public function %s (%s) "%(name, args)) self.codegenerator.openblock() - def begin_method(self, name, _class, arglist, push=True): - if push: + def begin_method(self, name, _class, arglist): + if self.push: self.push_gen("py/"+name+".as") self.codegenerator.write("package py ") self.codegenerator.openblock() - self.codegenerator.writeline("import py.__consts_0;") - + self.codegenerator.writeline("import py._consts_0;") + self.codegenerator.writeline("import ll_os_path.ll_join;") + args = ",".join(arglist) self.codegenerator.write("%s.prototype.%s = function (%s)"%(_class, name, args)) self.codegenerator.openblock() - def end_function(self, pop=True): + def end_function(self): self.codegenerator.closeblock() self.codegenerator.writeline("") - if pop: + if self.push: self.codegenerator.closeblock() self.pop_gen() @@ -123,7 +129,8 @@ self.codegenerator.write("package py ") self.codegenerator.openblock() - self.codegenerator.writeline("import py.__consts_0;") + self.codegenerator.writeline("import py._consts_0;") + self.codegenerator.writeline("import ll_os_path.ll_join;") self.codegenerator.write("dynamic public class %s extends %s "%(name, base)) self.codegenerator.openblock() @@ -343,7 +350,7 @@ def throw_real(self, s): # use throwit wrapper function... because of compiler weirdness with flex compiler. - self.codegenerator.writeline("__consts_0.throwit(%s);"%s) + self.codegenerator.writeline("_consts_0.throwit(%s);"%s) def clean_stack(self): self.right_hand.empty() Modified: pypy/branch/flex-backend/pypy/translator/flex/database.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/database.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/database.py Sat Aug 11 16:30:27 2007 @@ -37,7 +37,7 @@ self.reverse_consts = {} self.const_names = set() self.rendered = set() - self.const_var = Variable("__consts") + self.const_var = Variable("_consts") self.name_manager = JavascriptNameManager(self) self.pending_consts = [] self.cts = self.genoo.TypeSystem(self) Modified: pypy/branch/flex-backend/pypy/translator/flex/function.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/function.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/function.py Sat Aug 11 16:30:27 2007 @@ -205,7 +205,7 @@ def begin_catch(self, llexitcase): real_name = self.cts.lltype_to_cts(llexitcase._inst.class_._INSTANCE) - s = "__consts_0.isinstanceof(exc, %s)"%real_name + s = "_consts_0.isinstanceof(exc, %s)"%real_name self.ilasm.branch_if_string(s) def end_catch(self, target_label): Modified: pypy/branch/flex-backend/pypy/translator/flex/js.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/js.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/js.py Sat Aug 11 16:30:27 2007 @@ -101,10 +101,10 @@ self.ilasm = self.create_assembler() self.fix_names() self.gen_entrypoint() - constants_code_generator = asmgen.CodeGenerator(open("py/__consts_0.as", "w")) + constants_code_generator = asmgen.CodeGenerator(open("py/_consts_0.as", "w")) constants_code_generator.write("package py ") constants_code_generator.openblock() - constants_code_generator.writeline("public var __consts_0 = {};") + constants_code_generator.writeline("public var _consts_0 = {};") constants_code_generator.closeblock() constants_code_generator = asmgen.CodeGenerator(open("py/__load_consts_flex.as", "w")) constants_code_generator.write("package py ") Modified: pypy/branch/flex-backend/pypy/translator/flex/jsbuiltin.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/jsbuiltin.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/jsbuiltin.py Sat Aug 11 16:30:27 2007 @@ -28,7 +28,7 @@ 'll_math.ll_math_fmod' : InstructionList([_PushAllArgs(slice(1, None)), '%']), 'll_time_time' : CallBuiltin('time'), 'll_time_clock' : CallBuiltin('clock'), - 'll_os_write' : CallBuiltin('print'), + 'll_os_write' : CallBuiltin('_consts_0.flexTrace'), } self.builtin_obj_map = { ootype.String.__class__: { Modified: pypy/branch/flex-backend/pypy/translator/flex/jssrc/misc.as ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/jssrc/misc.as (original) +++ pypy/branch/flex-backend/pypy/translator/flex/jssrc/misc.as Sat Aug 11 16:30:27 2007 @@ -5,7 +5,7 @@ import py.*; -import py.__consts_0; +import py._consts_0; //import py.f.DictIter; @@ -38,19 +38,19 @@ try { py.__load_consts_flex() } catch (exc) { - __consts_0.flexTrace("consts error"); - __consts_0.flexTrace(String(exc)); + localFlexTrace("consts error"); + localFlexTrace(String(exc)); } try { flash_main(1) } catch (exc) { - __consts_0.flexTrace("flash_main error"); - __consts_0.flexTrace(String(exc)); - __consts_0.flexTrace(String(exc.message)); - __consts_0.flexTrace(exc.getStackTrace()); + localFlexTrace("flash_main error"); + localFlexTrace(String(exc)); + localFlexTrace(String(exc.message)); + localFlexTrace(exc.getStackTrace()); } - __consts_0.flexTrace("Exit"); + localFlexTrace("Exit"); } Modified: pypy/branch/flex-backend/pypy/translator/flex/metavm.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/metavm.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/metavm.py Sat Aug 11 16:30:27 2007 @@ -77,6 +77,7 @@ class CallBuiltin(_Call): def __init__(self, builtin): + if builtin == "": raise "foo" self.builtin = builtin def render(self, generator, op): @@ -217,7 +218,7 @@ # FIXME: just temporary hack generator.load(op.args[0]) generator.ilasm.load_const(op.args[1].value._name.replace('.', '_'))#[-1]) - generator.cast_function("__consts_0.isinstanceof", 2) + generator.cast_function("_consts_0.isinstanceof", 2) class _IndirectCall(MicroInstruction): def render(self, generator, op): @@ -277,7 +278,7 @@ IsInstance = _IsInstance() CallMethod = _CallMethod() CopyName = [PushAllArgs, _SameAs ()] -CastString = _CastFun("__consts_0.convertToString", 1) +CastString = _CastFun("_consts_0.convertToString", 1) SameAs = CopyName DiscardStack = _DiscardStack() Modified: pypy/branch/flex-backend/pypy/translator/flex/modules/flex.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/modules/flex.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/modules/flex.py Sat Aug 11 16:30:27 2007 @@ -4,5 +4,5 @@ def flexTrace(s): pass -register_external(flexTrace, args=[str], export_name="__consts_0.flexTrace") +register_external(flexTrace, args=[str], export_name="_consts_0.flexTrace") Modified: pypy/branch/flex-backend/pypy/translator/flex/sandbox/chimp.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/sandbox/chimp.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/sandbox/chimp.py Sat Aug 11 16:30:27 2007 @@ -122,7 +122,7 @@ self.original = self.image -def flash_main(): +def flash_main(a=0): """this function is called when the program starts. it initializes everything it needs, then runs in a loop until the function returns.""" Modified: pypy/branch/flex-backend/pypy/translator/flex/sandbox/fun.py ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/sandbox/fun.py (original) +++ pypy/branch/flex-backend/pypy/translator/flex/sandbox/fun.py Sat Aug 11 16:30:27 2007 @@ -2,7 +2,7 @@ class Bar: def __init__(self, arg): - self.arg = arg + self.arg = arg +"(!)" def setValue(self, arg): self.arg = arg @@ -11,17 +11,19 @@ class Foo: def __init__(self, arg): - self.arg = Bar(arg) + self.arg = Bar(arg + "@") def setValue(self, arg): - self.arg = Bar(arg) + self.arg = Bar(arg +"#") def value(self): return self.arg.value() def flash_main(a=1): flexTrace("Starting! python") - f = Bar("hola") + + f = Foo("hola") + for x in range(20): - f.setValue( "doing number "+str(x)+"!!" ) + f.setValue( "doing number "+str(x)+" !!" ) flexTrace(f.value()) flexTrace("Im done!") Added: pypy/branch/flex-backend/pypy/translator/flex/sandbox/ll_os_path/ll_join.as ============================================================================== --- (empty file) +++ pypy/branch/flex-backend/pypy/translator/flex/sandbox/ll_os_path/ll_join.as Sat Aug 11 16:30:27 2007 @@ -0,0 +1,5 @@ +package ll_os_path { + public function ll_join ( arg1, arg2 ) { + return "/path/"; + } +} Modified: pypy/branch/flex-backend/pypy/translator/flex/sandbox/misc.as ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/sandbox/misc.as (original) +++ pypy/branch/flex-backend/pypy/translator/flex/sandbox/misc.as Sat Aug 11 16:30:27 2007 @@ -233,4 +233,4 @@ } -var __consts_0 = {}; +var _consts_0 = {}; Modified: pypy/branch/flex-backend/pypy/translator/flex/sandbox/output.mxml ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/sandbox/output.mxml (original) +++ pypy/branch/flex-backend/pypy/translator/flex/sandbox/output.mxml Sat Aug 11 16:30:27 2007 @@ -17,7 +17,7 @@ import py.*; -import py.__consts_0; +import py._consts_0; //import py.f.DictIter; @@ -50,19 +50,19 @@ try { py.__load_consts_flex() } catch (exc) { - __consts_0.flexTrace("consts error"); - __consts_0.flexTrace(String(exc)); + localFlexTrace("consts error"); + localFlexTrace(String(exc)); } try { flash_main(1) } catch (exc) { - __consts_0.flexTrace("flash_main error"); - __consts_0.flexTrace(String(exc)); - __consts_0.flexTrace(String(exc.message)); - __consts_0.flexTrace(exc.getStackTrace()); + localFlexTrace("flash_main error"); + localFlexTrace(String(exc)); + localFlexTrace(String(exc.message)); + localFlexTrace(exc.getStackTrace()); } - __consts_0.flexTrace("Exit"); + localFlexTrace("Exit"); } Modified: pypy/branch/flex-backend/pypy/translator/flex/sandbox/py/StringBuilder.as ============================================================================== --- pypy/branch/flex-backend/pypy/translator/flex/sandbox/py/StringBuilder.as (original) +++ pypy/branch/flex-backend/pypy/translator/flex/sandbox/py/StringBuilder.as Sat Aug 11 16:30:27 2007 @@ -1,7 +1,7 @@ package py { -public class StringBuilder { +dynamic public class StringBuilder { public function StringBuilder() { this.l = []; From fijal at codespeak.net Sat Aug 11 16:50:56 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 11 Aug 2007 16:50:56 +0200 (CEST) Subject: [pypy-svn] r45601 - pypy/extradoc/talk/dresden Message-ID: <20070811145056.B4DBA8190@code0.codespeak.net> Author: fijal Date: Sat Aug 11 16:50:48 2007 New Revision: 45601 Added: pypy/extradoc/talk/dresden/interpreterarch.png - copied unchanged from r45423, pypy/extradoc/talk/dzug2007/interpreterarch.png Modified: pypy/extradoc/talk/dresden/talk.txt Log: * update a bit * add an architecture pic Modified: pypy/extradoc/talk/dresden/talk.txt ============================================================================== --- pypy/extradoc/talk/dresden/talk.txt (original) +++ pypy/extradoc/talk/dresden/talk.txt Sat Aug 11 16:50:48 2007 @@ -60,9 +60,6 @@ - example - gc (modeled after Jikes MMtk) -XXX side-by-side comparison of CPython and PyPy source code -XXX string formatting sounds like a candidate - Objspace concept ================ @@ -72,7 +69,9 @@ Taint objspace ============== -XXX (picture probably is worth thousand words here) +- intercepts all operations performed on objects + +.. image:: interpreterarch.png Multiple object implementation ============================== @@ -101,7 +100,7 @@ - using whatever storage mechanism -- XXX +- with desired granularity Sandboxing ========== From fijal at codespeak.net Sat Aug 11 17:42:50 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 11 Aug 2007 17:42:50 +0200 (CEST) Subject: [pypy-svn] r45602 - pypy/dist/pypy/translator/js/test Message-ID: <20070811154250.6822381AC@code0.codespeak.net> Author: fijal Date: Sat Aug 11 17:42:49 2007 New Revision: 45602 Modified: pypy/dist/pypy/translator/js/test/runtest.py Log: fix --use-browser Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Sat Aug 11 17:42:49 2007 @@ -94,6 +94,7 @@ assert out[1] == 'undefined' or out[1] == "" output = out[0] port += 1 + return self.reinterpret(output) else: # cmd = 'echo "load(\'%s\'); print(%s)" | js 2>&1' % (self.js.filename, function_call) # log(cmd) From jlg at codespeak.net Mon Aug 13 15:34:33 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 13 Aug 2007 15:34:33 +0200 (CEST) Subject: [pypy-svn] r45625 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070813133433.738178163@code0.codespeak.net> Author: jlg Date: Mon Aug 13 15:34:32 2007 New Revision: 45625 Modified: pypy/dist/pypy/lang/scheme/TODO.txt pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_continuation.py Log: define continuation related bugfix; continuation pitfall tests added; LetStar is continuation friendly Modified: pypy/dist/pypy/lang/scheme/TODO.txt ============================================================================== --- pypy/dist/pypy/lang/scheme/TODO.txt (original) +++ pypy/dist/pypy/lang/scheme/TODO.txt Mon Aug 13 15:34:32 2007 @@ -3,7 +3,7 @@ - continuations -continuation frame must be saved fot every non tail-call +continuation frame must be saved for every non tail-call (for tail calls there is no cc) Do next @@ -22,5 +22,7 @@ - lambda called with wrong number of arguments issue - macros *are* not first-class objects +- input/output operations +- missing datatypes: chars, strings, vectors - switch to byte-code generation + eval instead of evaluating AST Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Mon Aug 13 15:34:32 2007 @@ -297,6 +297,12 @@ def __init__(self, body): self.body = body + def __repr__(self): + return "" + + def to_string(self): + return self.body.to_string() + def eval_tr(self, ctx): return self.continue_tr(ctx, self.body, [], False) @@ -743,14 +749,15 @@ _symbol_name = "define" def continue_tr(self, ctx, lst, elst, cnt=True): - w_first = elst[0] - w_val = elst[1] + w_first = lst + w_val = elst[0] if isinstance(w_first, W_Symbol): ctx.set(w_first.name, w_val) - return (w_val, None) - elif isinstance(w_first, W_Pair): - #XXX no tests here - raise NotImplementedError + if len(ctx.cont_stack) == 0: + raise ContinuationReturn(w_val) + + cont = ctx.cont_stack.pop() + return cont.run(ctx, w_val) raise SchemeSyntaxError @@ -760,7 +767,7 @@ w_first = lst.car w_second = lst.get_cdr_as_pair() if isinstance(w_first, W_Symbol): - w_val = w_second.car.eval_cf(ctx, self, w_first, [w_first], 1) + w_val = w_second.car.eval_cf(ctx, self, w_first) ctx.set(w_first.name, w_val) return w_val #undefined elif isinstance(w_first, W_Pair): @@ -771,7 +778,10 @@ formals = w_first.cdr #isinstance of W_List body = w_second + #remember this! ContinuationFrame creation + ctx.cont_stack.append(ContinuationFrame(self, w_first)) w_lambda = W_Lambda(formals, body, ctx, pname=w_name.name) + ctx.cont_stack.pop() ctx.set(w_name.name, w_lambda) return w_lambda #undefined @@ -848,20 +858,43 @@ class LetStar(W_Macro): _symbol_name = "let*" + def continue_tr(self, ctx, lst, elst, cnt=True): + ctx = ctx.copy() + (body, w_def, w_val) = elst + ctx.sput(w_def, w_val) + w_formal = lst + while isinstance(w_formal, W_Pair): + w_def = w_formal.get_car_as_pair() + #evaluate the values in local ctx + w_val = w_def.get_cdr_as_pair().car.eval_cf(ctx, \ + self, lst.cdr, [elst[0], w_def.car], 2) + ctx.sput(w_def.car, w_val) + w_formal = w_formal.cdr + + w_result = body.eval(ctx) + + if len(ctx.cont_stack) == 0: + raise ContinuationReturn(w_result) + + cont = ctx.cont_stack.pop() + return cont.run(ctx, w_result) + def call_tr(self, ctx, lst): #let* uses eval_body, so it is tail-recursive aware if not isinstance(lst, W_Pair): raise SchemeSyntaxError local_ctx = ctx.copy() + body = Body(lst.cdr) w_formal = lst.car while isinstance(w_formal, W_Pair): w_def = w_formal.get_car_as_pair() #evaluate the values in local ctx - w_val = w_def.get_cdr_as_pair().car.eval(local_ctx) + w_val = w_def.get_cdr_as_pair().car.eval_cf(local_ctx, \ + self, w_formal.cdr, [body, w_def.car], 2) local_ctx.sput(w_def.car, w_val) w_formal = w_formal.cdr - return Body(lst.cdr).eval_tr(local_ctx) + return body.eval_tr(local_ctx) class Letrec(W_Macro): _symbol_name = "letrec" Modified: pypy/dist/pypy/lang/scheme/test/test_continuation.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_continuation.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_continuation.py Mon Aug 13 15:34:32 2007 @@ -179,3 +179,101 @@ eval_(ctx, "(oo +)") assert ctx.get("oo") is ctx.get("+") +def test_lambda_call(): + ctx = ExecutionContext() + + eval_(ctx, "(define c1 'none)") + eval_(ctx, "(define c2 'none)") + eval_(ctx, """(define fun (lambda (x y z) + (call/cc (lambda (k) + (set! c1 k))) + (+ x y z)))""") + + assert ctx.get("c1").to_string() == "none" + assert ctx.get("c2").to_string() == "none" + + eval_(ctx, """(fun (call/cc (lambda (k) + (set! c2 k) + 1)) + 2 3)""") + + w_result = eval_(ctx, "(c1)") + assert w_result.to_number() == 6 + + w_result = eval_(ctx, "(c2 0)") + assert w_result.to_number() == 5 + w_result = eval_(ctx, "(c1)") + assert w_result.to_number() == 5 + + w_result = eval_(ctx, "(c2 5)") + assert w_result.to_number() == 10 + w_result = eval_(ctx, "(c1)") + assert w_result.to_number() == 10 + +def test_pitfall_1_1(): + ctx = ExecutionContext() + w_result = eval_(ctx, """ + (let ((cont #f)) + (letrec ((x (call/cc (lambda (c) (set! cont c) 0))) + (y (call/cc (lambda (c) (set! cont c) 0)))) + (if cont + (let ((c cont)) + (set! cont #f) + (set! x 1) + (set! y 1) + (c 0)) + (+ x y))))""") + + assert w_result.to_number() == 0 + +def test_pitfall_1_2(): + py.test.skip("(cond ...) and (procedure? ...) not implemented") + ctx = ExecutionContext() + w_result = eval_(ctx, """ + (letrec ((x (call/cc list)) (y (call/cc list))) + (cond ((procedure? x) (x (pair? y))) + ((procedure? y) (y (pair? x)))) + (let ((x (car x)) (y (car y))) + (and (call/cc x) (call/cc y) (call/cc x)))))""") + + assert isinstance(w_result, W_Boolean) + assert w_result.to_boolean() is True + +def test_pitfall_1_3(): + py.test.skip("(eq? ...) not implemented, letrec not cf") + ctx = ExecutionContext() + w_result = eval_(ctx, """ + (letrec ((x (call/cc + (lambda (c) + (list #t c))))) + (if (car x) + ((car (cdr x)) (list #f (lambda () x))) + (eq? x ((car (cdr x))))))""") + + assert isinstance(w_result, W_Boolean) + assert w_result.to_boolean() is True + +def test_pitfall_7_4(): + ctx = ExecutionContext() + w_result = eval_(ctx, """ + (let ((x '()) + (y 0)) + (call/cc + (lambda (escape) + (let* ((yin ((lambda (foo) + (set! x (cons y x)) + (if (= y 10) + (escape x) + (begin + (set! y 0) + foo))) + (call/cc (lambda (bar) bar)))) + (yang ((lambda (foo) + (set! y (+ y 1)) + foo) + (call/cc (lambda (baz) baz))))) + (yin yang)))))""") + + assert isinstance(w_result, W_Pair) + assert w_result.to_string() == "(10 9 8 7 6 5 4 3 2 1 0)" + From fijal at codespeak.net Mon Aug 13 17:34:14 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 13 Aug 2007 17:34:14 +0200 (CEST) Subject: [pypy-svn] r45631 - pypy/dist/pypy/rpython/module/test Message-ID: <20070813153414.E3D188187@code0.codespeak.net> Author: fijal Date: Mon Aug 13 17:34:13 2007 New Revision: 45631 Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py pypy/dist/pypy/rpython/module/test/test_posix.py Log: Move test to be interpreted Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_os.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_os.py Mon Aug 13 17:34:13 2007 @@ -106,16 +106,6 @@ compared_with.sort() assert result == compared_with -def test_os_wstar(): - from pypy.rpython.module.ll_os import RegisterOs - for name in RegisterOs.w_star: - def fun(s): - return getattr(os, name)(s) - - fn = compile(fun, [int]) - for value in [0, 1, 127, 128, 255]: - assert fn(value) == fun(value) - class ExpectTestOs: def setup_class(cls): if not hasattr(os, 'ttyname'): Modified: pypy/dist/pypy/rpython/module/test/test_posix.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_posix.py (original) +++ pypy/dist/pypy/rpython/module/test/test_posix.py Mon Aug 13 17:34:13 2007 @@ -122,6 +122,15 @@ assert realfile.read() == 'xxx' self.interpret(f2, [fd]) + def test_os_wstar(self): + from pypy.rpython.module.ll_os import RegisterOs + for name in RegisterOs.w_star: + def fun(s): + return getattr(os, name)(s) + + for value in [0, 1, 127, 128, 255]: + assert self.interpret(fun, [value]) == fun(value) + def test_tmpfile_translate(): from pypy.rlib import ros def f(): From fijal at codespeak.net Mon Aug 13 17:34:30 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 13 Aug 2007 17:34:30 +0200 (CEST) Subject: [pypy-svn] r45632 - pypy/dist/pypy/rpython/module Message-ID: <20070813153430.B433681B8@code0.codespeak.net> Author: fijal Date: Mon Aug 13 17:34:30 2007 New Revision: 45632 Modified: pypy/dist/pypy/rpython/module/ll_os.py Log: Explain (although it should be fixed) Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Mon Aug 13 17:34:30 2007 @@ -25,7 +25,8 @@ UNISTD_INCL = ['unistd.h', 'sys/types.h'] def __init__(self): - pass # XXX fijal: why do I need this? + pass # We need this, because we override __init__ with raising, + # and we want to do it on an instance level, rather than class # a simple, yet usefull factory def register_os_function_returning_int(self, fun, name, **kwds): From jlg at codespeak.net Mon Aug 13 17:57:41 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 13 Aug 2007 17:57:41 +0200 (CEST) Subject: [pypy-svn] r45633 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070813155741.2902C817E@code0.codespeak.net> Author: jlg Date: Mon Aug 13 17:57:40 2007 New Revision: 45633 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_continuation.py Log: cleanup Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Mon Aug 13 17:57:40 2007 @@ -845,6 +845,7 @@ if not isinstance(lst, W_Pair): raise SchemeSyntaxError local_ctx = ctx.copy() + body = Body(lst.cdr) w_formal = lst.car while isinstance(w_formal, W_Pair): w_def = w_formal.get_car_as_pair() @@ -853,7 +854,7 @@ local_ctx.sput(w_def.car, w_val) w_formal = w_formal.cdr - return Body(lst.cdr).eval_tr(local_ctx) + return body.eval_tr(local_ctx) class LetStar(W_Macro): _symbol_name = "let*" @@ -865,7 +866,6 @@ w_formal = lst while isinstance(w_formal, W_Pair): w_def = w_formal.get_car_as_pair() - #evaluate the values in local ctx w_val = w_def.get_cdr_as_pair().car.eval_cf(ctx, \ self, lst.cdr, [elst[0], w_def.car], 2) ctx.sput(w_def.car, w_val) @@ -904,6 +904,7 @@ if not isinstance(lst, W_Pair): raise SchemeSyntaxError local_ctx = ctx.copy() + body = Body(lst.cdr) map_name_expr = {} map_name_symb = {} w_formal = lst.car @@ -922,7 +923,7 @@ for (name, w_val) in map_name_val.items(): local_ctx.ssete(map_name_symb[name], w_val) - return Body(lst.cdr).eval_tr(local_ctx) + return body.eval_tr(local_ctx) def quote(sexpr): return W_Pair(W_Symbol('quote'), W_Pair(sexpr, w_nil)) Modified: pypy/dist/pypy/lang/scheme/test/test_continuation.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_continuation.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_continuation.py Mon Aug 13 17:57:40 2007 @@ -211,6 +211,7 @@ assert w_result.to_number() == 10 def test_pitfall_1_1(): + py.test.skip("letrec not cf") ctx = ExecutionContext() w_result = eval_(ctx, """ (let ((cont #f)) @@ -222,9 +223,9 @@ (set! x 1) (set! y 1) (c 0)) - (+ x y))))""") + (+ x y 1))))""") - assert w_result.to_number() == 0 + assert w_result.to_number() == 1 def test_pitfall_1_2(): py.test.skip("(cond ...) and (procedure? ...) not implemented") From fijal at codespeak.net Mon Aug 13 18:09:35 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 13 Aug 2007 18:09:35 +0200 (CEST) Subject: [pypy-svn] r45634 - pypy/dist/pypy/translator/goal Message-ID: <20070813160935.B943481B4@code0.codespeak.net> Author: fijal Date: Mon Aug 13 18:09:35 2007 New Revision: 45634 Modified: pypy/dist/pypy/translator/goal/targetscheme.py Log: Fix imports Modified: pypy/dist/pypy/translator/goal/targetscheme.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetscheme.py (original) +++ pypy/dist/pypy/translator/goal/targetscheme.py Mon Aug 13 18:09:35 2007 @@ -6,7 +6,8 @@ import sys from pypy.rlib.streamio import open_file_as_stream from pypy.lang.scheme.ssparser import parse -from pypy.lang.scheme.object import SchemeQuit, ExecutionContext +from pypy.lang.scheme.object import SchemeQuit +from pypy.lang.scheme.execution import ExecutionContext # __________ Entry point __________ From fijal at codespeak.net Mon Aug 13 18:33:33 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 13 Aug 2007 18:33:33 +0200 (CEST) Subject: [pypy-svn] r45635 - pypy/dist/pypy/lang/test Message-ID: <20070813163333.00E69817B@code0.codespeak.net> Author: fijal Date: Mon Aug 13 18:33:33 2007 New Revision: 45635 Added: pypy/dist/pypy/lang/test/ pypy/dist/pypy/lang/test/__init__.py (contents, props changed) pypy/dist/pypy/lang/test/test_translation.py (contents, props changed) Log: Introduce tests whether frontend build or not, useful for checking. Added: pypy/dist/pypy/lang/test/__init__.py ============================================================================== Added: pypy/dist/pypy/lang/test/test_translation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lang/test/test_translation.py Mon Aug 13 18:33:33 2007 @@ -0,0 +1,33 @@ + +""" Tests whether each interpreter translates itself +""" + +#def base_translation_test(targetname): + +import sys, py +from pypy.translator import driver +from pypy.translator import translator +from pypy.config.translationoption import get_combined_translation_config +from pypy.translator.goal.translate import load_target + +class TestTranslation: + def translate(self, targetname): + config = get_combined_translation_config(translating=True) + config.translation.backend = 'c' + targetspec = 'pypy.translator.goal.' + targetname + mod = __import__(targetspec) + targetspec_dic = sys.modules[targetspec].__dict__ + t = translator.TranslationContext() + drv = driver.TranslationDriver.from_targetspec(targetspec_dic, config, [], + empty_translator=t) + drv.proceed('compile') + + def test_scheme(self): + py.test.skip("Doesn't work and this is a known issue") + self.translate('targetscheme') + + def test_js(self): + self.translate('targetjsstandalone') + + def test_prolog(self): + self.translate('targetprologstandalone') From fijal at codespeak.net Mon Aug 13 18:58:36 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 13 Aug 2007 18:58:36 +0200 (CEST) Subject: [pypy-svn] r45636 - pypy/dist/pypy/lang/test Message-ID: <20070813165836.EE1EE81B8@code0.codespeak.net> Author: fijal Date: Mon Aug 13 18:58:36 2007 New Revision: 45636 Modified: pypy/dist/pypy/lang/test/test_translation.py Log: use boehm by default, disallow creating targets in current dir Modified: pypy/dist/pypy/lang/test/test_translation.py ============================================================================== --- pypy/dist/pypy/lang/test/test_translation.py (original) +++ pypy/dist/pypy/lang/test/test_translation.py Mon Aug 13 18:58:36 2007 @@ -14,12 +14,14 @@ def translate(self, targetname): config = get_combined_translation_config(translating=True) config.translation.backend = 'c' + config.translation.gc = 'boehm' targetspec = 'pypy.translator.goal.' + targetname mod = __import__(targetspec) targetspec_dic = sys.modules[targetspec].__dict__ t = translator.TranslationContext() drv = driver.TranslationDriver.from_targetspec(targetspec_dic, config, [], empty_translator=t) + drv.exe_name = None drv.proceed('compile') def test_scheme(self): From jlg at codespeak.net Mon Aug 13 19:00:47 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 13 Aug 2007 19:00:47 +0200 (CEST) Subject: [pypy-svn] r45637 - pypy/dist/pypy/lang/scheme Message-ID: <20070813170047.87C2781B8@code0.codespeak.net> Author: jlg Date: Mon Aug 13 19:00:46 2007 New Revision: 45637 Modified: pypy/dist/pypy/lang/scheme/object.py Log: translation fixed Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Mon Aug 13 19:00:46 2007 @@ -867,7 +867,7 @@ while isinstance(w_formal, W_Pair): w_def = w_formal.get_car_as_pair() w_val = w_def.get_cdr_as_pair().car.eval_cf(ctx, \ - self, lst.cdr, [elst[0], w_def.car], 2) + self, w_formal.cdr, [elst[0], w_def.car], 2) ctx.sput(w_def.car, w_val) w_formal = w_formal.cdr @@ -1446,7 +1446,7 @@ class ContinuationFrame(object): def __init__(self, callable, continuation, evaluated_args = [], enum=0): - assert hasattr(callable, "continue_tr") + #assert hasattr(callable, "continue_tr") self.callable = callable assert isinstance(continuation, W_Root) self.continuation = continuation From jlg at codespeak.net Mon Aug 13 19:06:20 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 13 Aug 2007 19:06:20 +0200 (CEST) Subject: [pypy-svn] r45638 - pypy/dist/pypy/lang/test Message-ID: <20070813170620.42A0280CD@code0.codespeak.net> Author: jlg Date: Mon Aug 13 19:06:19 2007 New Revision: 45638 Modified: pypy/dist/pypy/lang/test/test_translation.py Log: scheme does translate Modified: pypy/dist/pypy/lang/test/test_translation.py ============================================================================== --- pypy/dist/pypy/lang/test/test_translation.py (original) +++ pypy/dist/pypy/lang/test/test_translation.py Mon Aug 13 19:06:19 2007 @@ -25,7 +25,6 @@ drv.proceed('compile') def test_scheme(self): - py.test.skip("Doesn't work and this is a known issue") self.translate('targetscheme') def test_js(self): From jlg at codespeak.net Mon Aug 13 19:25:44 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 13 Aug 2007 19:25:44 +0200 (CEST) Subject: [pypy-svn] r45639 - pypy/dist/pypy/lang/scheme Message-ID: <20070813172544.E4A3581BB@code0.codespeak.net> Author: jlg Date: Mon Aug 13 19:25:43 2007 New Revision: 45639 Modified: pypy/dist/pypy/lang/scheme/object.py Log: 2/4 translation warnings removed Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Mon Aug 13 19:25:43 2007 @@ -1270,6 +1270,7 @@ lst = lst.cdr if w_cdr is not None: + assert isinstance(last_cons, W_Pair) last_cons.cdr = w_cdr return first_cons @@ -1494,6 +1495,8 @@ raise SchemeSyntaxError w_lambda = lst[0] + if not isinstance(w_lambda, W_Procedure): + raise SchemeSyntaxError cc = Continuation(ctx, ctx.cont_stack) return w_lambda.call_tr(ctx, W_Pair(cc, w_nil)) From jlg at codespeak.net Tue Aug 14 12:38:45 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Tue, 14 Aug 2007 12:38:45 +0200 (CEST) Subject: [pypy-svn] r45651 - pypy/dist/pypy/translator/goal Message-ID: <20070814103845.4D479811B@code0.codespeak.net> Author: jlg Date: Tue Aug 14 12:38:44 2007 New Revision: 45651 Modified: pypy/dist/pypy/translator/goal/targetscheme.py Log: parser should return list or raise assertion; no translation warnings Modified: pypy/dist/pypy/translator/goal/targetscheme.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetscheme.py (original) +++ pypy/dist/pypy/translator/goal/targetscheme.py Tue Aug 14 12:38:44 2007 @@ -6,7 +6,8 @@ import sys from pypy.rlib.streamio import open_file_as_stream from pypy.lang.scheme.ssparser import parse -from pypy.lang.scheme.object import SchemeQuit +from pypy.rlib.parsing.makepackrat import BacktrackException +from pypy.lang.scheme.object import SchemeQuit, ContinuationReturn from pypy.lang.scheme.execution import ExecutionContext # __________ Entry point __________ @@ -14,13 +15,26 @@ def entry_point(argv): if len(argv) == 2: - f = open_file_as_stream(argv[1]) - t = parse(f.readall()) + code = open_file_as_stream(argv[1]).readall() + try: + t = parse(code) + except BacktrackException: + #(line, col) = e.error.get_line_column(code) + #expected = " ".join(e.error.expected) + print "parse error" + return 1 + + #this should not be necessary here + assert isinstance(t, list) ctx = ExecutionContext() try: for sexpr in t: - w_retval = sexpr.eval(ctx) - print w_retval.to_string() + try: + w_retval = sexpr.eval(ctx) + print w_retval.to_string() + except ContinuationReturn, e: + print e.result.to_string() + except SchemeQuit, e: return 0 From jlg at codespeak.net Tue Aug 14 12:39:44 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Tue, 14 Aug 2007 12:39:44 +0200 (CEST) Subject: [pypy-svn] r45652 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070814103944.A24DA811B@code0.codespeak.net> Author: jlg Date: Tue Aug 14 12:39:43 2007 New Revision: 45652 Modified: pypy/dist/pypy/lang/scheme/interactive.py pypy/dist/pypy/lang/scheme/test/test_interactive.py Log: nice parsing errors for interactive interpreter Modified: pypy/dist/pypy/lang/scheme/interactive.py ============================================================================== --- pypy/dist/pypy/lang/scheme/interactive.py (original) +++ pypy/dist/pypy/lang/scheme/interactive.py Tue Aug 14 12:39:43 2007 @@ -40,7 +40,10 @@ except SchemeException, e: print "error: %s" % e except BacktrackException, e: - print "syntax error" + (line, col) = e.error.get_line_column(to_exec) + expected = " ".join(e.error.expected) + print "parse error: in line %s, column %s expected: %s" % \ + (line, col, expected) to_exec = "" cont = False Modified: pypy/dist/pypy/lang/scheme/test/test_interactive.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_interactive.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_interactive.py Tue Aug 14 12:39:43 2007 @@ -48,7 +48,7 @@ child = self.spawn() child.expect("-> ") child.sendline(")(") - child.expect("syntax error") + child.expect("parse error") child.expect("-> ") def test_multiline_enter(self): From arigo at codespeak.net Tue Aug 14 18:10:46 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Aug 2007 18:10:46 +0200 (CEST) Subject: [pypy-svn] r45656 - in pypy/branch/pypy-more-rtti-inprogress: . module/posix rlib rpython rpython/lltypesystem rpython/lltypesystem/module rpython/module rpython/module/test rpython/ootypesystem/module rpython/test translator translator/c translator/c/src translator/c/test translator/sandbox translator/sandbox/test Message-ID: <20070814161046.E284280E8@code0.codespeak.net> Author: arigo Date: Tue Aug 14 18:10:44 2007 New Revision: 45656 Added: pypy/branch/pypy-more-rtti-inprogress/ - copied from r45507, pypy/dist/pypy/ Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py pypy/branch/pypy-more-rtti-inprogress/rlib/ros.py pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_math.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_path.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/support.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os_path.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/rbuiltin.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rptr.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_math.h pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/interact.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py pypy/branch/pypy-more-rtti-inprogress/translator/translator.py Log: For backup purposes, in-progress: convert more of the os module to rtti and try to get rid of the rllib.ros module by making the native interfaces RPythonic. This looks quite good in my opinion - seems that we've finally learned a reasonable way to do external functions. Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Tue Aug 14 18:10:44 2007 @@ -445,7 +445,7 @@ """ if space.is_w(w_tuple, space.w_None): try: - ros.utime_null(path) + os.utime(path, None) return except OSError, e: raise wrap_oserror(space, e) @@ -456,7 +456,7 @@ raise OperationError(space.w_TypeError, space.wrap(msg)) actime = space.float_w(args_w[0]) modtime = space.float_w(args_w[1]) - ros.utime_tuple(path, (actime, modtime)) + os.utime(path, (actime, modtime)) except OSError, e: raise wrap_oserror(space, e) except OperationError, e: Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/ros.py ============================================================================== --- pypy/dist/pypy/rlib/ros.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/ros.py Tue Aug 14 18:10:44 2007 @@ -54,11 +54,3 @@ def opendir(dirname): return DIR(dirname) opendir._annenforceargs_ = (str,) - -# probably we can get an annotation support for not having both implementations -# here, but let's leave it for now -def utime_null(path): - os.utime(path, None) - -def utime_tuple(path, tp): - os.utime(path, tp) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/dist/pypy/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Tue Aug 14 18:10:44 2007 @@ -88,31 +88,13 @@ def compute_result_annotation(self, *args_s): if hasattr(self, 'ann_hook'): self.ann_hook() - if self.signature_args is not None: - assert len(args_s) == len(self.signature_args),\ - "Argument number mismatch" - for i, expected in enumerate(self.signature_args): - arg = unionof(args_s[i], expected) - if not expected.contains(arg): - name = getattr(self, 'name', None) - if not name: - try: - name = self.instance.__name__ - except AttributeError: - name = '?' - raise Exception("In call to external function %r:\n" - "arg %d must be %s,\n" - " got %s" % ( - name, i+1, expected, args_s[i])) + self.normalize_args(*args_s) # check arguments return self.signature_result def specialize_call(self, hop): rtyper = hop.rtyper - if self.signature_args is None: - iter_args = hop.args_s - else: - iter_args = self.signature_args - args_r = [rtyper.getrepr(s_arg) for s_arg in iter_args] + signature_args = self.normalize_args(*hop.args_s) + args_r = [rtyper.getrepr(s_arg) for s_arg in signature_args] args_ll = [r_arg.lowleveltype for r_arg in args_r] r_result = rtyper.getrepr(hop.s_result) ll_result = r_result.lowleveltype @@ -123,8 +105,12 @@ fakeimpl = getattr(self, fake_method_name, self.instance) if impl: obj = rtyper.getannmixlevel().delayedfunction( - impl, self.signature_args, hop.s_result) + impl, signature_args, hop.s_result) else: + #if not self.safe_not_sandboxed: + # print '>>>>>>>>>>>>>-----------------------------------' + # print name, self.name + # print '<<<<<<<<<<<<<-----------------------------------' obj = rtyper.type_system.getexternalcallable(args_ll, ll_result, name, _external_name=self.name, _callable=fakeimpl, _safe_not_sandboxed=self.safe_not_sandboxed) @@ -151,10 +137,36 @@ class FunEntry(ExtFuncEntry): _about_ = function safe_not_sandboxed = sandboxsafe + if args is None: - signature_args = None + def normalize_args(self, *args_s): + return args_s # accept any argument unmodified + + elif callable(args): + # custom annotation normalizer (see e.g. os.utime()) + normalize_args = staticmethod(args) + else: - signature_args = [annotation(arg, None) for arg in args] + # common case: args is a list of annotation or types + def normalize_args(self, *args_s): + signature_args = [annotation(arg, None) for arg in args] + assert len(args_s) == len(signature_args),\ + "Argument number mismatch" + for i, expected in enumerate(signature_args): + arg = unionof(args_s[i], expected) + if not expected.contains(arg): + name = getattr(self, 'name', None) + if not name: + try: + name = self.instance.__name__ + except AttributeError: + name = '?' + raise Exception("In call to external function %r:\n" + "arg %d must be %s,\n" + " got %s" % ( + name, i+1, expected, args_s[i])) + return signature_args + signature_result = annotation(result, None) name=export_name if llimpl: Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py ============================================================================== --- pypy/dist/pypy/rpython/extfuncregistry.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py Tue Aug 14 18:10:44 2007 @@ -27,35 +27,22 @@ _register_external(getattr(math, name), [float], float, "ll_math.ll_math_%s" % name, sandboxsafe=True) -def frexp_hook(): - from pypy.rpython.extfunctable import record_call - from pypy.annotation.model import SomeInteger, SomeTuple, SomeFloat - from pypy.rpython.lltypesystem.module.ll_math import ll_frexp_result - record_call(ll_frexp_result, (SomeFloat(), SomeInteger()), 'MATH_FREXP') - -def modf_hook(): - from pypy.rpython.extfunctable import record_call - from pypy.annotation.model import SomeTuple, SomeFloat - from pypy.rpython.lltypesystem.module.ll_math import ll_modf_result - record_call(ll_modf_result, (SomeFloat(), SomeFloat()), 'MATH_MODF') - complex_math_functions = [ - ('frexp', [float], (float, int), frexp_hook), - ('atan2', [float, float], float, None), - ('fmod', [float, float], float, None), - ('ldexp', [float, int], float, None), - ('modf', [float], (float, float), modf_hook), - ('hypot', [float, float], float, None), - ('pow', [float, float], float, None), + ('frexp', [float], (float, int)), + ('atan2', [float, float], float), + ('fmod', [float, float], float), + ('ldexp', [float, int], float), + ('modf', [float], (float, float)), + ('hypot', [float, float], float), + ('pow', [float, float], float), ] -for name, args, res, hook in complex_math_functions: +for name, args, res in complex_math_functions: func = getattr(math, name) - llfake = getattr(ll_math, 'll_math_%s' % name, None) + llimpl = getattr(ll_math, 'll_math_%s' % name, None) oofake = getattr(oo_math, 'll_math_%s' % name, None) _register_external(func, args, res, 'll_math.ll_math_%s' % name, - llfakeimpl=llfake, oofakeimpl=oofake, - annotation_hook = hook, + llimpl=llimpl, oofakeimpl=oofake, sandboxsafe=True) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Tue Aug 14 18:10:44 2007 @@ -137,16 +137,6 @@ # _____________________________________________________________ -def record_call(func, args_s, symbol): - from pypy.annotation import bookkeeper - bk = bookkeeper.getbookkeeper() - # this would be nice! - #bk.pbc_call(bk.immutablevalue(func), - # bk.build_args("simple_call", args_s), - # emulated=True) - bk.annotator.translator._implicitly_called_by_externals.append( - (func, args_s, symbol)) - def noneannotation(*args): return None @@ -154,25 +144,6 @@ from pypy.annotation.model import SomeInteger return SomeInteger(nonneg=True) -def statannotation(*args): - from pypy.rpython.lltypesystem.module.ll_os import Implementation - from pypy.annotation.model import SomeInteger, SomeTuple - record_call(Implementation.ll_stat_result, [SomeInteger()]*10, 'OS_STAT') - return SomeTuple((SomeInteger(),)*10) - -def pipeannotation(*args): - from pypy.rpython.lltypesystem.module.ll_os import Implementation - from pypy.annotation.model import SomeInteger, SomeTuple - record_call(Implementation.ll_pipe_result, [SomeInteger()]*2, 'OS_PIPE') - return SomeTuple((SomeInteger(),)*2) - -def waitpidannotation(*args): - from pypy.rpython.lltypesystem.module.ll_os import Implementation - from pypy.annotation.model import SomeInteger, SomeTuple - record_call(Implementation.ll_waitpid_result, [SomeInteger()]*2, - 'OS_WAITPID') - return SomeTuple((SomeInteger(),)*2) - def strnullannotation(*args): from pypy.annotation.model import SomeString return SomeString(can_be_None=True) @@ -183,9 +154,6 @@ declare(os.isatty , bool , 'll_os/isatty') if hasattr(posix, 'ftruncate'): declare(os.ftruncate, noneannotation, 'll_os/ftruncate') -declare(os.fstat , statannotation, 'll_os/fstat') -declare(os.stat , statannotation, 'll_os/stat') -declare(os.lstat , statannotation, 'll_os/lstat') declare(os.system , int , 'll_os/system') declare(os.strerror , str , 'll_os/strerror') declare(os.unlink , noneannotation, 'll_os/unlink') @@ -194,7 +162,6 @@ declare(os.rmdir , noneannotation, 'll_os/rmdir') if hasattr(posix, 'unsetenv'): # note: faked in os declare(os.unsetenv , noneannotation, 'll_os/unsetenv') -declare(os.pipe , pipeannotation, 'll_os/pipe') declare(os.chmod , noneannotation, 'll_os/chmod') declare(os.rename , noneannotation, 'll_os/rename') declare(os.umask , int , 'll_os/umask') @@ -205,14 +172,10 @@ declare(os.link , noneannotation, 'll_os/link') if hasattr(os, 'symlink'): declare(os.symlink , noneannotation, 'll_os/symlink') -if hasattr(os, 'readlink'): - declare(os.readlink , str, 'll_os/readlink') if hasattr(os, 'fork'): declare(os.fork , int, 'll_os/fork') if hasattr(os, 'spawnv'): declare(os.spawnv, int, 'll_os/spawnv') -if hasattr(os, 'waitpid'): - declare(os.waitpid , waitpidannotation, 'll_os/waitpid') #if hasattr(os, 'execv'): # declare(os.execv, noneannotation, 'll_os/execv') # declare(os.execve, noneannotation, 'll_os/execve') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py Tue Aug 14 18:10:44 2007 @@ -439,8 +439,12 @@ return obj._callable(*args) except LLException, e: raise - except Exception: + except Exception, e: if getattr(obj, '_debugexc', False): + log.ERROR('The llinterpreter got an ' + 'unexpected exception when calling') + log.ERROR('the external function %r:' % (fptr,)) + log.ERROR('%s: %s' % (e.__class__.__name__, e)) import sys from pypy.translator.tool.pdbplus import PdbPlusShow PdbPlusShow(None).post_mortem(sys.exc_info()[2]) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py Tue Aug 14 18:10:44 2007 @@ -449,7 +449,7 @@ if cfunc is None: # function name not found in any of the libraries if not libraries: - place = 'the standard C library' + place = 'the standard C library (missing libraries=...?)' elif len(libraries) == 1: place = 'library %r' % (libraries[0],) else: Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_math.py Tue Aug 14 18:10:44 2007 @@ -1,25 +1,21 @@ import math -from pypy.rpython.lltypesystem import lltype, rtupletype +from pypy.rpython.lltypesystem import lltype, rffi -FREXP_RESULT = rtupletype.TUPLE_TYPE([lltype.Float, lltype.Signed]).TO -MODF_RESULT = rtupletype.TUPLE_TYPE([lltype.Float, lltype.Float]).TO - -def ll_frexp_result(mantissa, exponent): - tup = lltype.malloc(FREXP_RESULT) - tup.item0 = mantissa - tup.item1 = exponent - return tup - -def ll_modf_result(fracpart, intpart): - tup = lltype.malloc(MODF_RESULT) - tup.item0 = fracpart - tup.item1 = intpart - return tup +math_frexp = rffi.llexternal('frexp', [rffi.DOUBLE, rffi.INTP], rffi.DOUBLE, + sandboxsafe=True) +math_modf = rffi.llexternal('modf', [rffi.DOUBLE, rffi.DOUBLEP], rffi.DOUBLE, + sandboxsafe=True) def ll_math_frexp(x): - mantissa, exponent = math.frexp(x) - return ll_frexp_result(mantissa, exponent) + exp_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') + mantissa = math_frexp(x, exp_p) + exponent = rffi.cast(lltype.Signed, exp_p[0]) + lltype.free(exp_p, flavor='raw') + return (mantissa, exponent) def ll_math_modf(x): - fracpart, intpart = math.modf(x) - return ll_modf_result(fracpart, intpart) + intpart_p = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw') + fracpart = math_modf(x, intpart_p) + intpart = intpart_p[0] + lltype.free(intpart_p, flavor='raw') + return (fracpart, intpart) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_os.py Tue Aug 14 18:10:44 2007 @@ -1,55 +1,7 @@ -import os, errno +# mostly-deprecated module + from pypy.rpython.module.support import LLSupport -from pypy.rpython.module.support import ll_strcpy from pypy.rpython.module.ll_os import BaseOS -from pypy.rpython.lltypesystem import lltype, rtupletype -from pypy.rlib.rarithmetic import intmask - -STAT_RESULT = rtupletype.TUPLE_TYPE([lltype.Signed]*10).TO -PIPE_RESULT = rtupletype.TUPLE_TYPE([lltype.Signed]*2).TO -WAITPID_RESULT = rtupletype.TUPLE_TYPE([lltype.Signed]*2).TO class Implementation(BaseOS, LLSupport): - - def ll_stat_result(stat0, stat1, stat2, stat3, stat4, - stat5, stat6, stat7, stat8, stat9): - tup = lltype.malloc(STAT_RESULT) - tup.item0 = intmask(stat0) - tup.item1 = intmask(stat1) - tup.item2 = intmask(stat2) - tup.item3 = intmask(stat3) - tup.item4 = intmask(stat4) - tup.item5 = intmask(stat5) - tup.item6 = intmask(stat6) - tup.item7 = intmask(stat7) - tup.item8 = intmask(stat8) - tup.item9 = intmask(stat9) - return tup - ll_stat_result = staticmethod(ll_stat_result) - - def ll_pipe_result(fd1, fd2): - tup = lltype.malloc(PIPE_RESULT) - tup.item0 = fd1 - tup.item1 = fd2 - return tup - ll_pipe_result = staticmethod(ll_pipe_result) - - def ll_os_readlink(cls, path): - from pypy.rpython.lltypesystem.rstr import mallocstr - bufsize = 1023 - while 1: - buffer = mallocstr(bufsize) - n = cls.ll_readlink_into(cls, path, buffer) - if n < bufsize: - break - bufsize *= 4 # overflow, try again with a bigger buffer - s = mallocstr(n) - ll_strcpy(s, buffer, n) - return s - - def ll_waitpid_result(fd1, fd2): - tup = lltype.malloc(WAITPID_RESULT) - tup.item0 = fd1 - tup.item1 = fd2 - return tup - ll_waitpid_result = staticmethod(ll_waitpid_result) + pass Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Tue Aug 14 18:10:44 2007 @@ -22,14 +22,16 @@ return self.TP def llexternal(name, args, result, _callable=None, sources=[], includes=[], - libraries=[], include_dirs=[]): + libraries=[], include_dirs=[], sandboxsafe=False): ext_type = lltype.FuncType(args, result) funcptr = lltype.functionptr(ext_type, name, external='C', sources=tuple(sources), includes=tuple(includes), libraries=tuple(libraries), include_dirs=tuple(include_dirs), - _callable=_callable) + _callable=_callable, + _safe_not_sandboxed=sandboxsafe, + _debugexc=True) # on top of llinterp if _callable is None: ll2ctypes.make_callable_via_ctypes(funcptr) return funcptr @@ -145,6 +147,9 @@ # int * INTP = lltype.Ptr(lltype.Array(lltype.Signed, hints={'nolength': True})) +# double * +DOUBLEP = lltype.Ptr(lltype.Array(DOUBLE, hints={'nolength': True})) + # various type mapping # str -> char* def str2charp(s): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Tue Aug 14 18:10:44 2007 @@ -6,16 +6,16 @@ # might be found in doc/rffi.txt import os, sys, errno -from pypy.rpython.module.support import ll_strcpy, _ll_strfill, OOSupport +from pypy.rpython.module.support import ll_strcpy, OOSupport from pypy.rpython.module.support import to_opaque_object, from_opaque_object +from pypy.tool.sourcetools import func_with_new_name from pypy.rlib import ros from pypy.rlib.rarithmetic import r_longlong from pypy.tool.staticmethods import ClassMethods import stat from pypy.rpython.extfunc import BaseLazyRegistering, registering -from pypy.annotation.model import SomeString, SomeInteger +from pypy.annotation.model import SomeInteger, SomeString, SomeTuple, SomeFloat from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool -from pypy.annotation.listdef import s_list_of_strings from pypy.rpython.lltypesystem import rffi from pypy.rpython.lltypesystem.rffi import platform from pypy.rpython.lltypesystem import lltype @@ -89,37 +89,57 @@ ('modtime', TIME_T)) # XXX sys/types.h is not portable at all - ros_utime = rffi.llexternal('utime', [rffi.CCHARP, UTIMEBUFP], - rffi.INT, - includes=['utime.h', 'sys/types.h']) + os_utime = rffi.llexternal('utime', [rffi.CCHARP, UTIMEBUFP], + rffi.INT, + includes=['utime.h', 'sys/types.h']) - def utime_null_lltypeimpl(path): - l_path = rffi.str2charp(path) - error = rffi.cast(lltype.Signed, ros_utime(l_path, - lltype.nullptr(UTIMEBUFP.TO))) - rffi.free_charp(l_path) - if error == -1: - raise OSError(rffi.get_errno(), "utime_null failed") - - self.register(ros.utime_null, [str], s_None, "ll_os.utime_null", - llimpl=utime_null_lltypeimpl) - - def utime_tuple_lltypeimpl(path, tp): + def os_utime_lltypeimpl(path, tp): # XXX right now they're all ints, might change in future # XXX does not use utimes, even when available + # NB. this function is specialized; we get one version where + # tp is known to be None, and one version where it is known + # to be a tuple of 2 floats. l_path = rffi.str2charp(path) - l_utimebuf = lltype.malloc(UTIMEBUFP.TO, flavor='raw') - actime, modtime = tp - l_utimebuf.c_actime, l_utimebuf.c_modtime = int(actime), int(modtime) - error = rffi.cast(lltype.Signed, ros_utime(l_path, l_utimebuf)) + if tp is None: + l_utimebuf = lltype.nullptr(UTIMEBUFP.TO) + else: + l_utimebuf = lltype.malloc(UTIMEBUFP.TO, flavor='raw') + actime, modtime = tp + l_utimebuf.c_actime = int(actime) + l_utimebuf.c_modtime = int(modtime) + error = rffi.cast(lltype.Signed, os_utime(l_path, l_utimebuf)) + if tp is not None: + lltype.free(l_utimebuf, flavor='raw') rffi.free_charp(l_path) - lltype.free(l_utimebuf, flavor='raw') if error == -1: - raise OSError(rffi.get_errno(), "utime_tuple failed") - - self.register(ros.utime_tuple, [str, (float, float)], s_None, - "ll_os.utime_tuple", - llimpl=utime_tuple_lltypeimpl) + raise OSError(rffi.get_errno(), "os_utime failed") + os_utime_lltypeimpl._annspecialcase_ = 'specialize:argtype(1)' + + s_string = SomeString() + s_tuple_of_2_floats = SomeTuple([SomeFloat(), SomeFloat()]) + + def os_utime_normalize_args(s_path, s_times): + # special handling of the arguments: they can be either + # [str, (float, float)] or [str, s_None], and get normalized + # to exactly one of these two. + if not s_string.contains(s_path): + raise Exception("os.utime() arg 1 must be a string, got %s" % ( + s_path,)) + case1 = s_None.contains(s_times) + case2 = s_tuple_of_2_floats.contains(s_times) + if case1 and case2: + return [s_string, s_ImpossibleValue] #don't know which case yet + elif case1: + return [s_string, s_None] + elif case2: + return [s_string, s_tuple_of_2_floats] + else: + raise Exception("os.utime() arg 2 must be None or a tuple of " + "2 floats, got %s" % (s_times,)) + + self.register(os.utime, os_utime_normalize_args, s_None, + "ll_os.ll_os_utime", + llimpl=os_utime_lltypeimpl) if hasattr(os, 'setsid'): @registering(os.setsid) @@ -353,7 +373,7 @@ def os_getcwd_oofakeimpl(): return OOSupport.to_rstr(os.getcwd()) - self.register(os.getcwd, [], SomeString(), + self.register(os.getcwd, [], str, "ll_os.ll_os_getcwd", llimpl=os_getcwd_lltypeimpl, oofakeimpl=os_getcwd_oofakeimpl) @@ -417,10 +437,190 @@ raise OSError(error, "os_readdir failed") return result - self.register(os.listdir, [str], s_list_of_strings, + self.register(os.listdir, + [str], # a single argument which is a str + [str], # returns a list of strings "ll_os.ll_os_listdir", llimpl=os_listdir_lltypeimpl) + @registering(os.pipe) + def register_os_pipe(self): + # we need a different approach on Windows and on Posix + if sys.platform.startswith('win'): + XXX # CreatePipe, _open_osfhandle + else: + INT_ARRAY_P = lltype.Ptr(lltype.FixedSizeArray(rffi.INT, 2)) + os_pipe = rffi.llexternal('pipe', [INT_ARRAY_P], rffi.INT, + includes=['unistd.h']) + + def os_pipe_lltypeimpl(): + filedes = lltype.malloc(INT_ARRAY_P.TO, flavor='raw') + error = os_pipe(filedes) + read_fd = filedes[0] + write_fd = filedes[1] + lltype.free(filedes, flavor='raw') + if error != 0: + raise OSError(rffi.get_errno(), "os_pipe failed") + return (read_fd, write_fd) + + self.register(os.pipe, [], (int, int), + "ll_os.ll_os_pipe", + llimpl=os_pipe_lltypeimpl) + + if hasattr(os, 'readlink'): + @registering(os.readlink) + def register_os_readlink(self): + os_readlink = rffi.llexternal('readlink', + [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], + rffi.INT) # XXX SSIZE_T in POSIX.1-2001 + + def os_readlink_lltypeimpl(path): + l_path = rffi.str2charp(path) + try: + bufsize = 1023 + while True: + buf = lltype.malloc(rffi.CCHARP.TO, bufsize, + flavor='raw') + res = os_readlink(l_path, buf, + rffi.cast(rffi.SIZE_T, bufsize)) + if res < 0: + error = rffi.get_errno() # failed + lltype.free(buf, flavor='raw') + raise OSError(error, "readlink failed") + elif res < bufsize: + break # ok + else: + # buf too small, try again with a larger buffer + lltype.free(buf, flavor='raw') + bufsize *= 4 + # convert the result to a string + res = rffi.cast(lltype.Signed, res) + l = [buf[i] for i in range(res)] + result = ''.join(l) + lltype.free(buf, flavor='raw') + finally: + rffi.free_charp(l_path) + return result + + self.register(os.readlink, [str], str, + "ll_os.ll_os_readlink", + llimpl=os_readlink_lltypeimpl) + + @registering(os.waitpid) + def register_os_waitpid(self): + if sys.platform.startswith('win'): + # emulate waitpid() with the _cwait() of Microsoft's compiler + os__cwait = rffi.llexternal('_cwait', + [rffi.INTP, rffi.PID_T, rffi.INT], + rffi.PID_T) + def os_waitpid(pid, status_p, options): + result = os__cwait(status_p, pid, options) + # shift the status left a byte so this is more + # like the POSIX waitpid + status_p[0] <<= 8 + return result + else: + # Posix + os_waitpid = rffi.llexternal('waitpid', + [rffi.PID_T, rffi.INTP, rffi.INT], + rffi.PID_T) + + def os_waitpid_lltypeimpl(pid, options): + status_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') + status_p[0] = 0 + result = os_waitpid(rffi.cast(rffi.PID_T, pid), + status_p, + rffi.cast(rffi.INT, options)) + status = status_p[0] + lltype.free(status_p, flavor='raw') + if result == -1: + raise OSError(rffi.get_errno(), "os_waitpid failed") + return (rffi.cast(lltype.Signed, result), + rffi.cast(lltype.Signed, status)) + + self.register(os.waitpid, [int, int], (int, int), + "ll_os.ll_os_waitpid", + llimpl=os_waitpid_lltypeimpl) + +# --------------------------- os.stat & variants --------------------------- + + def register_stat_variant(self, name): + if sys.platform.startswith('win'): + struct_stat = '_stati64' + functions = {'stat': '_stati64', + 'fstat': '_fstati64', + 'lstat': '_stati64'} # no lstat on Windows + c_func_name = functions[name] + INCLUDES = [] + else: + struct_stat = 'stat' + c_func_name = name + INCLUDES = self.UNISTD_INCL + ['sys/stat.h'] + # XXX all fields are lltype.Signed for now, which is wrong + STRUCT_STAT = rffi.CStruct(struct_stat, + ('st_mode', lltype.Signed), + ('st_ino', lltype.Signed), + ('st_dev', lltype.Signed), + ('st_nlink', lltype.Signed), + ('st_uid', lltype.Signed), + ('st_gid', lltype.Signed), + ('st_size', lltype.Signed), + ('st_atime', lltype.Signed), + ('st_mtime', lltype.Signed), + ('st_ctime', lltype.Signed), + ) + arg_is_path = (name != 'fstat') + if arg_is_path: + ARG1 = rffi.CCHARP + else: + ARG1 = rffi.INT + os_mystat = rffi.llexternal(name, [ARG1, STRUCT_STAT], rffi.INT, + includes=INCLUDES) + + def os_mystat_lltypeimpl(arg): + stresult = lltype.malloc(STRUCT_STAT.TO, flavor='raw') + try: + if arg_is_path: + arg = rffi.str2charp(arg) + error = os_mystat(arg, stresult) + if arg_is_path: + rffi.free_charp(arg) + if error != 0: + raise OSError(rffi.get_errno(), "os_stat failed") + return (stresult.c_st_mode, + stresult.c_st_ino, + stresult.c_st_dev, + stresult.c_st_nlink, + stresult.c_st_uid, + stresult.c_st_gid, + stresult.c_st_size, + stresult.c_st_atime, + stresult.c_st_mtime, + stresult.c_st_ctime) + finally: + lltype.free(stresult, flavor='raw') + + if arg_is_path: + s_arg = str + else: + s_arg = int + self.register(getattr(os, name), [s_arg], (int,) * 10, + "ll_os.ll_os_%s" % (name,), + llimpl=func_with_new_name(os_mystat_lltypeimpl, + 'os_%s_lltypeimpl' % (name,))) + + @registering(os.fstat) + def register_os_fstat(self): + self.register_stat_variant('fstat') + + @registering(os.stat) + def register_os_stat(self): + self.register_stat_variant('stat') + + @registering(os.lstat) + def register_os_lstat(self): + self.register_stat_variant('lstat') + # ------------------------------- os.W* --------------------------------- w_star = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED', @@ -472,7 +672,25 @@ self.register(os.ttyname, [int], str, "ll_os.ttyname", llimpl=ttyname_lltypeimpl) +# ____________________________________________________________ +# Support for os.environ + +# XXX only for systems where os.environ is an instance of _Environ, +# which should cover Unix and Windows at least +assert type(os.environ) is not dict + +from pypy.rpython.controllerentry import ControllerEntryForPrebuilt + +class EnvironExtRegistry(ControllerEntryForPrebuilt): + _about_ = os.environ + + def getcontroller(self): + from pypy.rpython.module.ll_os_environ import OsEnvironController + return OsEnvironController() + + class BaseOS: + # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods def ll_os_lseek(cls, fd,pos,how): @@ -487,27 +705,6 @@ return os.ftruncate(fd,len) ll_os_ftruncate.suggested_primitive = True - def ll_os_fstat(cls, fd): - (stat0, stat1, stat2, stat3, stat4, - stat5, stat6, stat7, stat8, stat9) = os.fstat(fd) - return cls.ll_stat_result(stat0, stat1, stat2, stat3, stat4, - stat5, stat6, stat7, stat8, stat9) - ll_os_fstat.suggested_primitive = True - - def ll_os_stat(cls, path): - (stat0, stat1, stat2, stat3, stat4, - stat5, stat6, stat7, stat8, stat9) = os.stat(cls.from_rstr(path)) - return cls.ll_stat_result(stat0, stat1, stat2, stat3, stat4, - stat5, stat6, stat7, stat8, stat9) - ll_os_stat.suggested_primitive = True - - def ll_os_lstat(cls, path): - (stat0, stat1, stat2, stat3, stat4, - stat5, stat6, stat7, stat8, stat9) = os.lstat(cls.from_rstr(path)) - return cls.ll_stat_result(stat0, stat1, stat2, stat3, stat4, - stat5, stat6, stat7, stat8, stat9) - ll_os_lstat.suggested_primitive = True - def ll_os_strerror(cls, errnum): return cls.to_rstr(os.strerror(errnum)) ll_os_strerror.suggested_primitive = True @@ -546,11 +743,6 @@ return ros.environ(idx) ll_os_environ.suggested_primitive = True - def ll_os_pipe(cls): - fd1, fd2 = os.pipe() - return cls.ll_pipe_result(fd1, fd2) - ll_os_pipe.suggested_primitive = True - def ll_os_chmod(cls, path, mode): os.chmod(cls.from_rstr(path), mode) ll_os_chmod.suggested_primitive = True @@ -575,14 +767,6 @@ os.symlink(cls.from_rstr(path1), cls.from_rstr(path2)) ll_os_symlink.suggested_primitive = True - def ll_readlink_into(cls, path, buffer): - data = os.readlink(cls.from_rstr(path)) - if len(data) < len(buffer.chars): # safely no overflow - _ll_strfill(buffer, data, len(data)) - return len(data) - ll_readlink_into.suggested_primitive = True - ll_readlink_into = staticmethod(ll_readlink_into) - def ll_os_fork(cls): return os.fork() ll_os_fork.suggested_primitive = True @@ -591,11 +775,6 @@ return os.spawnv(mode, path, args) ll_os_spawnv.suggested_primitive = True - def ll_os_waitpid(cls, pid, options): - pid, status = os.waitpid(pid, options) - return cls.ll_waitpid_result(pid, status) - ll_os_waitpid.suggested_primitive = True - def ll_os__exit(cls, status): os._exit(status) ll_os__exit.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_path.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os_path.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_path.py Tue Aug 14 18:10:44 2007 @@ -17,16 +17,15 @@ def ll_os_path_exists(cls, path): """Test whether a path exists""" try: - st = os.stat(cls.from_rstr(path)) + st = os.stat(cls.from_rstr_nonnull(path)) except OSError: return False return True def ll_os_path_isdir(cls, path): try: - (stat0, stat1, stat2, stat3, stat4, - stat5, stat6, stat7, stat8, stat9) = os.stat(cls.from_rstr(path)) + st = os.stat(cls.from_rstr_nonnull(path)) except OSError: return False - return stat.S_ISDIR(stat0) + return stat.S_ISDIR(st[0]) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/support.py ============================================================================== --- pypy/dist/pypy/rpython/module/support.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/support.py Tue Aug 14 18:10:44 2007 @@ -36,6 +36,11 @@ return ''.join([rs.chars[i] for i in range(len(rs.chars))]) from_rstr = staticmethod(from_rstr) + def from_rstr_nonnull(rs): + assert rs + return ''.join([rs.chars[i] for i in range(len(rs.chars))]) + from_rstr_nonnull = staticmethod(from_rstr_nonnull) + class OOSupport: _mixin_ = True @@ -50,6 +55,11 @@ return "".join([rs.ll_stritem_nonneg(i) for i in range(rs.ll_strlen())]) from_rstr = staticmethod(from_rstr) + def from_rstr_nonnull(rs): + assert rs + return "".join([rs.ll_stritem_nonneg(i) for i in range(rs.ll_strlen())]) + from_rstr_nonnull = staticmethod(from_rstr_nonnull) + def ll_strcpy(dst_s, src_s, n): dstchars = dst_s.chars Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os_path.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_os_path.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os_path.py Tue Aug 14 18:10:44 2007 @@ -33,6 +33,7 @@ interpret(f, []) def test_isdir(): + import py; py.test.skip("XXX cannot run os.stat() on the llinterp yet") s = str(udir.join('test_isdir')) def f(): return os.path.isdir(s) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py Tue Aug 14 18:10:44 2007 @@ -24,6 +24,7 @@ assert type(func) == int def test_fstat(self): + import py; py.test.skip("XXX cannot run os.stat() on the llinterp yet") def fo(fi): g = posix.fstat(fi) return g Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py Tue Aug 14 18:10:44 2007 @@ -1,8 +1,8 @@ -import os +# mostly-deprecated module + from pypy.rpython.module.support import OOSupport from pypy.rpython.module.ll_os import BaseOS from pypy.rpython.ootypesystem import ootype -from pypy.rlib.rarithmetic import intmask def _make_tuple(FIELDS): n = len(FIELDS) @@ -11,41 +11,6 @@ return ootype.Record(fields) STAT_RESULT = _make_tuple([ootype.Signed]*10) -PIPE_RESULT = _make_tuple([ootype.Signed]*2) -WAITPID_RESULT = _make_tuple([ootype.Signed]*2) class Implementation(BaseOS, OOSupport): - - def ll_stat_result(stat0, stat1, stat2, stat3, stat4, - stat5, stat6, stat7, stat8, stat9): - tup = ootype.new(STAT_RESULT) - tup.item0 = intmask(stat0) - tup.item1 = intmask(stat1) - tup.item2 = intmask(stat2) - tup.item3 = intmask(stat3) - tup.item4 = intmask(stat4) - tup.item5 = intmask(stat5) - tup.item6 = intmask(stat6) - tup.item7 = intmask(stat7) - tup.item8 = intmask(stat8) - tup.item9 = intmask(stat9) - return tup - ll_stat_result = staticmethod(ll_stat_result) - - def ll_pipe_result(fd1, fd2): - tup = ootype.new(PIPE_RESULT) - tup.item0 = fd1 - tup.item1 = fd2 - return tup - ll_pipe_result = staticmethod(ll_pipe_result) - - def ll_os_readlink(cls, path): - return cls.to_rstr(os.readlink(path)) - ll_os_readlink.suggested_primitive = True - - def ll_waitpid_result(fd1, fd2): - tup = ootype.new(WAITPID_RESULT) - tup.item0 = fd1 - tup.item1 = fd2 - return tup - ll_waitpid_result = staticmethod(ll_waitpid_result) + pass Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/rbuiltin.py Tue Aug 14 18:10:44 2007 @@ -352,6 +352,8 @@ v = r_tup.getitem(hop.llops, v_extra_args, n) vlist.append(v) + hop.has_implicit_exception(MemoryError) # record that we know about it + hop.exception_is_here() return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype) def rtype_free(hop, i_flavor): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rptr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rptr.py Tue Aug 14 18:10:44 2007 @@ -1,4 +1,4 @@ -import py +import py, sys from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.annlowlevel import annotate_lowlevel_helper, LowLevelAnnotatorPolicy from pypy.rpython.lltypesystem.lltype import * @@ -183,6 +183,24 @@ res = interpret(fn, [23]) assert res == 23 +def test_memoryerror(): + A = Array(Signed) + def fn(n): + try: + a = malloc(A, n, flavor='raw') + except MemoryError: + return -42 + else: + res = len(a) + free(a, flavor='raw') + return res + + res = interpret(fn, [123]) + assert res == 123 + + res = interpret(fn, [sys.maxint]) + assert res == -42 + def test_call_ptr(): def f(x,y,z): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Tue Aug 14 18:10:44 2007 @@ -7,9 +7,7 @@ from pypy.rpython.lltypesystem import rlist from pypy.rpython.module import ll_time, ll_os from pypy.rpython.module import ll_stackless, ll_stack -from pypy.rpython.lltypesystem.module.ll_os import STAT_RESULT, PIPE_RESULT -from pypy.rpython.lltypesystem.module.ll_os import WAITPID_RESULT -from pypy.rpython.lltypesystem.module.ll_os import Implementation as impl +from pypy.rpython.module.ll_os import BaseOS as impl from pypy.rpython.lltypesystem.module import ll_strtod from pypy.rlib import ros @@ -23,9 +21,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_stat.im_func: 'LL_os_stat', - impl.ll_os_fstat.im_func: 'LL_os_fstat', - impl.ll_os_lstat.im_func: 'LL_os_lstat', impl.ll_os_lseek.im_func: 'LL_os_lseek', impl.ll_os_isatty.im_func: 'LL_os_isatty', impl.ll_os_ftruncate.im_func:'LL_os_ftruncate', @@ -41,17 +36,14 @@ impl.ll_os_opendir.im_func: 'LL_os_opendir', impl.ll_os_readdir.im_func: 'LL_os_readdir', impl.ll_os_closedir.im_func:'LL_os_closedir', - impl.ll_os_pipe.im_func: 'LL_os_pipe', impl.ll_os_chmod.im_func: 'LL_os_chmod', impl.ll_os_rename.im_func: 'LL_os_rename', impl.ll_os_umask.im_func: 'LL_os_umask', impl.ll_os_kill.im_func: 'LL_os_kill', impl.ll_os_link.im_func: 'LL_os_link', impl.ll_os_symlink.im_func: 'LL_os_symlink', - impl.ll_readlink_into: 'LL_readlink_into', impl.ll_os_fork.im_func: 'LL_os_fork', impl.ll_os_spawnv.im_func: 'LL_os_spawnv', - impl.ll_os_waitpid.im_func: 'LL_os_waitpid', impl.ll_os__exit.im_func: 'LL_os__exit', ll_time.ll_time_clock: 'LL_time_clock', ll_time.ll_time_sleep: 'LL_time_sleep', @@ -85,8 +77,9 @@ math_functions = [ 'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs', 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', - 'frexp', 'pow', 'atan2', 'fmod', 'ldexp', 'modf', 'hypot' + 'pow', 'atan2', 'fmod', 'ldexp', 'hypot' ] +# frexp and modf have been ported to the new rffi style already import math for name in math_functions: @@ -109,11 +102,6 @@ LIST_OF_STR = find_list_of_str(rtyper) if LIST_OF_STR is not None: yield ('RPyListOfString', LIST_OF_STR) - yield ('RPyFREXP_RESULT', ll_math.FREXP_RESULT) - yield ('RPyMODF_RESULT', ll_math.MODF_RESULT) - yield ('RPySTAT_RESULT', STAT_RESULT) - yield ('RPyPIPE_RESULT', PIPE_RESULT) - yield ('RPyWAITPID_RESULT', WAITPID_RESULT) def predeclare_utility_functions(db, rtyper): # Common utility functions @@ -161,24 +149,6 @@ yield (fname, graph) -def get_extfunc_helper_ptrs(db, rtyper): - - def annotate(func, args): - fptr = rtyper.annotate_helper(func, args) - db.helper2ptr[func] = fptr - return (func.__name__, fptr) - - for func, args, symb in db.translator._implicitly_called_by_externals: - yield annotate(func, args) - -def predeclare_extfunc_helpers(db, rtyper): - def decl(func): - return (func.__name__, db.helper2ptr[func]) - - for func, args, symb in db.translator._implicitly_called_by_externals: - yield decl(func) - yield ('LL_NEED_' + symb, 1) - def predeclare_extfuncs(db, rtyper): modules = {} def module_name(c_name): @@ -234,7 +204,6 @@ for fn in [predeclare_common_types, predeclare_utility_functions, predeclare_exception_data, - predeclare_extfunc_helpers, predeclare_extfuncs, ]: for t in fn(db, rtyper): @@ -245,7 +214,6 @@ for fn in [predeclare_common_types, predeclare_utility_functions, predeclare_exception_data, - get_extfunc_helper_ptrs, predeclare_extfuncs, ]: for t in fn(db, rtyper): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py Tue Aug 14 18:10:44 2007 @@ -705,11 +705,19 @@ # 'fnobj' is one of the ll_xyz() functions with the suggested_primitive # flag in pypy.rpython.module.*. The corresponding C wrappers are # written by hand in src/ll_*.h, and declared in extfunc.EXTERNALS. - assert (not sandbox - or fnobj._name.startswith('ll_strtod_') # XXX!! TEMPORARY! + if sandbox and not ( + fnobj._name.startswith('ll_strtod_') # XXX!! TEMPORARY! or fnobj._name.startswith('ll_time_') # XXX!! TEMPORARY! or fnobj._name.startswith('ll_stack_') # XXX!! TEMPORARY! - ) + ): + # deprecated case: apply the sandbox transformation but don't + # try to support these extfuncs properly (we just build a + # "Not Implemented" stub). To support these functions, port them + # to the new style registry (e.g. rpython.module.ll_os.RegisterOs). + from pypy.translator.sandbox import rsandbox + graph = rsandbox.get_external_function_sandbox_graph(fnobj, db, + force_stub=True) + return [FunctionCodeGenerator(graph, db)] db.externalfuncs[fnobj._callable] = fnobj return [] elif getattr(fnobj._callable, 'suggested_primitive', False): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_math.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_math.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_math.h Tue Aug 14 18:10:44 2007 @@ -25,12 +25,10 @@ int ll_math_is_error(double x); double LL_math_pow(double x, double y); -RPyFREXP_RESULT* LL_math_frexp(double x); double LL_math_atan2(double x, double y); double LL_math_fmod(double x, double y); double LL_math_ldexp(double x, long y); double LL_math_hypot(double x, double y); -RPyMODF_RESULT* LL_math_modf(double x); double LL_math_acos(double x); double LL_math_asin(double x); double LL_math_atan(double x); @@ -72,19 +70,6 @@ return r; } -#ifdef LL_NEED_MATH_FREXP - -RPyFREXP_RESULT* LL_math_frexp(double x) { - int expo; - double m; - LL_MATH_ERROR_RESET; - m= frexp(x, &expo); - LL_MATH_CHECK_ERROR(m, NULL); - return ll_frexp_result(m, expo); -} - -#endif - double LL_math_atan2(double x, double y) { double r; LL_MATH_ERROR_RESET; @@ -118,18 +103,6 @@ } -#ifdef LL_NEED_MATH_MODF - -RPyMODF_RESULT* LL_math_modf(double x) { - double intpart, fracpart; - LL_MATH_ERROR_RESET; - fracpart = modf(x, &intpart); - LL_MATH_CHECK_ERROR(fracpart, NULL); - return ll_modf_result(fracpart, intpart); -} - -#endif - /* simple math function */ double LL_math_acos(double x) { Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Tue Aug 14 18:10:44 2007 @@ -4,7 +4,6 @@ #if !(defined(MS_WIN64) || defined(MS_WINDOWS)) # include # include -# include #endif #include @@ -32,30 +31,13 @@ */ -/* just do what CPython is doing... */ - -#if defined(MS_WIN64) || defined(MS_WINDOWS) -# define STAT _stati64 -# define FSTAT _fstati64 -# define STRUCT_STAT struct _stati64 -# define LSTAT STAT -#else -# define STAT stat -# define FSTAT fstat -# define STRUCT_STAT struct stat -/* plus some approximate guesses */ -# define LSTAT lstat +#if !(defined(MS_WIN64) || defined(MS_WINDOWS)) # define HAVE_FILESYSTEM_WITH_LINKS #endif /* prototypes */ -RPySTAT_RESULT* _stat_construct_result_helper(STRUCT_STAT st); -RPySTAT_RESULT* LL_os_stat(RPyString * fname); -RPySTAT_RESULT* LL_os_lstat(RPyString * fname); -RPySTAT_RESULT* LL_os_fstat(long fd); -RPyPIPE_RESULT* LL_os_pipe(void); long LL_os_lseek(long fd, long pos, long how); int LL_os_isatty(long fd); RPyString *LL_os_strerror(int errnum); @@ -70,12 +52,10 @@ void LL_os_kill(int pid, int sig); void LL_os_link(RPyString * path1, RPyString * path2); void LL_os_symlink(RPyString * path1, RPyString * path2); -long LL_readlink_into(RPyString *path, RPyString *buffer); long LL_os_fork(void); #if defined(HAVE_SPAWNV) && defined(HAVE_RPY_LIST_OF_STRING) /* argh */ long LL_os_spawnv(int mode, RPyString *path, RPyListOfString *args); #endif -RPyWAITPID_RESULT* LL_os_waitpid(long pid, long options); void LL_os__exit(long status); void LL_os_putenv(RPyString * name_eq_value); void LL_os_unsetenv(RPyString * name); @@ -96,86 +76,6 @@ #include "ll_osdefs.h" -#ifdef LL_NEED_OS_STAT - -RPySTAT_RESULT* _stat_construct_result_helper(STRUCT_STAT st) { - long res0, res1, res2, res3, res4, res5, res6, res7, res8, res9; - res0 = (long)st.st_mode; - res1 = (long)st.st_ino; /*XXX HAVE_LARGEFILE_SUPPORT!*/ - res2 = (long)st.st_dev; /*XXX HAVE_LONG_LONG!*/ - res3 = (long)st.st_nlink; - res4 = (long)st.st_uid; - res5 = (long)st.st_gid; - res6 = (long)st.st_size; /*XXX HAVE_LARGEFILE_SUPPORT!*/ - res7 = (long)st.st_atime; /*XXX ignoring quite a lot of things for time here */ - res8 = (long)st.st_mtime; /*XXX ignoring quite a lot of things for time here */ - res9 = (long)st.st_ctime; /*XXX ignoring quite a lot of things for time here */ - /*XXX ignoring BLOCK info here*/ - - return ll_stat_result(res0, res1, res2, res3, res4, - res5, res6, res7, res8, res9); -} - - -RPySTAT_RESULT* LL_os_stat(RPyString * fname) { - STRUCT_STAT st; - int error = STAT(RPyString_AsString(fname), &st); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - return NULL; - } - return _stat_construct_result_helper(st); -} - -RPySTAT_RESULT* LL_os_lstat(RPyString * fname) { - STRUCT_STAT st; - int error = LSTAT(RPyString_AsString(fname), &st); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - return NULL; - } - return _stat_construct_result_helper(st); -} - -RPySTAT_RESULT* LL_os_fstat(long fd) { - STRUCT_STAT st; - int error = FSTAT(fd, &st); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - return NULL; - } - return _stat_construct_result_helper(st); -} - -#endif - -#ifdef LL_NEED_OS_PIPE - -RPyPIPE_RESULT* LL_os_pipe(void) { -#if !defined(MS_WINDOWS) - int filedes[2]; - int error = pipe(filedes); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - return NULL; - } - return ll_pipe_result(filedes[0], filedes[1]); -#else - HANDLE read, write; - int read_fd, write_fd; - BOOL ok = CreatePipe(&read, &write, NULL, 0); - if (!ok) { - RPYTHON_RAISE_OSERROR(errno); - return NULL; - } - read_fd = _open_osfhandle((long)read, 0); - write_fd = _open_osfhandle((long)write, 1); - return ll_pipe_result(read_fd, write_fd); -#endif -} - -#endif - long LL_os_lseek(long fd, long pos, long how) { #if defined(MS_WIN64) || defined(MS_WINDOWS) PY_LONG_LONG res; @@ -304,16 +204,6 @@ RPYTHON_RAISE_OSERROR(errno); } } - -long LL_readlink_into(RPyString *path, RPyString *buffer) -{ - long n = readlink(RPyString_AsString(path), - RPyString_AsString(buffer), RPyString_Size(buffer)); - if (n < 0) - RPYTHON_RAISE_OSERROR(errno); - return n; -} - #endif #ifdef HAVE_FORK @@ -352,36 +242,6 @@ } #endif -#ifdef LL_NEED_OS_WAITPID -/* note: LL_NEED_ is computed in extfunc.py, can't grep */ - -#ifdef HAVE_WAITPID -RPyWAITPID_RESULT* LL_os_waitpid(long pid, long options) { - int status; - pid = waitpid(pid, &status, options); - if (pid == -1) { - RPYTHON_RAISE_OSERROR(errno); - return NULL; - } - return ll_waitpid_result(pid, status); -} - -#elif defined(HAVE_CWAIT) - -RPyWAITPID_RESULT* LL_os_waitpid(long pid, long options) { - int status; - pid = _cwait(&status, pid, options); - if (pid == -1) { - RPYTHON_RAISE_OSERROR(errno); - return NULL; - } - /* shift the status left a byte so this is more like the - POSIX waitpid */ - return ll_waitpid_result(pid, status << 8); -} -#endif /* HAVE_WAITPID || HAVE_CWAIT */ -#endif - void LL_os__exit(long status) { _exit((int)status); } Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Tue Aug 14 18:10:44 2007 @@ -659,11 +659,13 @@ s = func(len(keys)) if not s: break - keys.append(s) + name, value = s.split('=', 1) + keys.append(name) expected = _real_envkeys() keys.sort() expected.sort() - return keys == expected + py.test.skip("XXX fails for me, $OLDPWD doesn't show up in the subprocess") + assert keys == expected posix = __import__(os.name) if hasattr(posix, "unsetenv"): @@ -678,7 +680,28 @@ f() assert _real_getenv('ABCDEF') is None + +def test_dictlike_environ_getitem(): + def fn(s): + res = os.environ[s] + if res is None: + res = '--missing--' + return res + func = compile(fn, [str]) + os.environ.setdefault('USER', 'UNNAMED_USER') + result = func('USER') + assert result == os.environ['USER'] + +def test_dictlike_environ_setitem(): + def fn(s, t): + os.environ[s] = t + func = compile(fn, [str, str]) + func('PYPY_TEST_DICTLIKE_ENVIRON', '42') + assert os.environ['PYPY_TEST_DICTLIKE_ENVIRON'] == '42' + + def test_opendir_readdir(): + py.test.skip("deprecated") def mylistdir(s): result = [] dir = ros.opendir(s) @@ -775,16 +798,14 @@ t0 = time() sleep(1) - def does_stuff(): - ros.utime_null(path) + def does_stuff(flag): + if flag: + os.utime(path, None) + else: + os.utime(path, (int(t0), int(t0))) - func = compile(does_stuff, []) - func() + func = compile(does_stuff, [int]) + func(1) assert os.stat(path).st_atime > t0 - - def utime_tuple(): - ros.utime_tuple(path, (int(t0), int(t0))) - - func = compile(utime_tuple, []) - func() + func(0) assert int(os.stat(path).st_atime) == int(t0) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/interact.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/interact.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/interact.py Tue Aug 14 18:10:44 2007 @@ -12,6 +12,6 @@ if __name__ == '__main__': if len(sys.argv) < 2: - print >> sys.stderr, __doc_ + print >> sys.stderr, __doc__ sys.exit(2) SimpleIOSandboxedProc(sys.argv[1:]).interact() Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/rsandbox.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py Tue Aug 14 18:10:44 2007 @@ -97,9 +97,9 @@ cache[FUNCTYPE] = marshal_input return marshal_input -def unmarshal_int(msg, *args): return msg.nextnum() -def unmarshal_size_t(msg, *args): return msg.nextsize_t() -def unmarshal_void(msg, *args): pass +def unmarshal_int(msg): return msg.nextnum() +def unmarshal_size_t(msg): return msg.nextsize_t() +def unmarshal_void(msg): pass def build_default_unmarshal_output(FUNCTYPE, namehint, cache={rffi.INT : unmarshal_int, @@ -150,7 +150,7 @@ raise RuntimeError(msg) # XXX in RPython, the msg is ignored at the moment not_implemented_stub._annenforceargs_ = [str] -def get_external_function_sandbox_graph(fnobj, db): +def get_external_function_sandbox_graph(fnobj, db, force_stub=False): """Build the graph of a helper trampoline function to be used in place of real calls to the external function 'fnobj'. The trampoline marshals its input arguments, dumps them to STDOUT, @@ -162,14 +162,27 @@ FUNCTYPE = lltype.typeOf(fnobj) fnname = fnobj._name try: + if force_stub: # old case - don't try to support suggested_primitive + raise NotImplementedError("external function '%s' using " + "deprecated 'suggested_primitive'" % ( + fnname,)) if hasattr(fnobj, '_marshal_input'): marshal_input = fnobj._marshal_input else: marshal_input = build_default_marshal_input(FUNCTYPE, fnname) if hasattr(fnobj, '_unmarshal_output'): + # _unmarshal_output() also receives the input arguments of the + # original call because some functions need them to decode the + # result properly. unmarshal_output = fnobj._unmarshal_output + unmarshal_takes_input_args = True else: + # The default unmarshal_output do not receive the original input + # arguments because they would cause annotation troubles + # (see e.g. test_sandbox_3). unmarshal_output = build_default_unmarshal_output(FUNCTYPE, fnname) + unmarshal_takes_input_args = False + except NotImplementedError, e: msg = 'Not Implemented: %s' % (e,) log.WARNING(msg) @@ -189,7 +202,10 @@ errcode = msg.nextnum() if errcode != 0: raise IOError - result = unmarshal_output(msg, *args) + if unmarshal_takes_input_args: + result = unmarshal_output(msg, *args) + else: + result = unmarshal_output(msg) finally: lltype.free(msg.value, flavor='raw') return result Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Tue Aug 14 18:10:44 2007 @@ -28,6 +28,12 @@ return self.popen.wait() def handle_forever(self): + returncode = self.handle_until_return() + if returncode != 0: + raise OSError("the sandboxed subprocess exited with code %d" % ( + returncode,)) + + def handle_until_return(self): while True: try: msg = read_message(self.popen.stdout) @@ -36,9 +42,7 @@ answer = self.handle_message(msg) self.popen.stdin.write(answer) returncode = self.popen.wait() - if returncode != 0: - raise OSError("the sandboxed subprocess exited with code %d" % ( - returncode,)) + return returncode def handle_message(self, msg): fn = msg.nextstring() @@ -99,7 +103,10 @@ self._input = stdin or sys.stdin self._output = stdout or sys.stdout self._error = stderr or sys.stderr - self.handle_forever() + returncode = self.handle_until_return() + if returncode != 0: + print >> self._error, "[Subprocess exit code: %d]" % ( + returncode,) self._input = None self._output = None self._error = None Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py ============================================================================== --- pypy/dist/pypy/translator/sandbox/test/test_sandbox.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py Tue Aug 14 18:10:44 2007 @@ -131,6 +131,43 @@ f.close() assert tail == "" +def test_sandbox_3(): + def entry_point(argv): + os.dup2(34, 56) + y = os.access("spam", 77) + return 1 - y + + t = Translation(entry_point, backend='c', standalone=True, sandbox=True) + exe = t.compile() + g, f = os.popen2(exe, "t", 0) + + msg = read_message(f, timeout=10.0) + m1 = msg.nextstring() + assert m1 == "dup2" + m2 = msg.nextnum() + assert m2 == 34 + m3 = msg.nextnum() + assert m3 == 56 + assert msg.end() + + g.write(MessageBuilder().packnum(0).packnum(0).getvalue()) + + msg = read_message(f, timeout=10.0) + m1 = msg.nextstring() + assert m1 == "access" + m2 = msg.nextstring() + assert m2 == "spam" + m3 = msg.nextnum() + assert m3 == 77 + assert msg.end() + + g.write(MessageBuilder().packnum(0).packnum(0).getvalue()) + + g.close() + tail = f.read() + f.close() + assert tail == "" + class TestPrintedResults: def run(self, entry_point, args, expected): @@ -150,6 +187,10 @@ print int(math.floor(a - 0.2)), print int(math.ceil(a)), print int(100.0 * math.sin(a)), + mantissa, exponent = math.frexp(a) + print int(100.0 * mantissa), exponent, + fracpart, intpart = math.modf(a) + print int(100.0 * fracpart), int(intpart), print return 0 - self.run(entry_point, ["3.011"], "2 4 13\n") + self.run(entry_point, ["3.011"], "2 4 13 75 2 1 3\n") Modified: pypy/branch/pypy-more-rtti-inprogress/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/translator.py Tue Aug 14 18:10:44 2007 @@ -44,8 +44,6 @@ self.callgraph = {} # {opaque_tag: (caller-graph, callee-graph)} self._prebuilt_graphs = {} # only used by the pygame viewer - self._implicitly_called_by_externals = [] - def create_flowspace_config(self): # XXX this is a hack: we create a new config, which is only used # for the flow object space. The problem is that the flow obj space From jlg at codespeak.net Tue Aug 14 18:19:44 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Tue, 14 Aug 2007 18:19:44 +0200 (CEST) Subject: [pypy-svn] r45657 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070814161944.2C32C8135@code0.codespeak.net> Author: jlg Date: Tue Aug 14 18:19:43 2007 New Revision: 45657 Added: pypy/dist/pypy/lang/scheme/r5rs_derived_expr.ss Modified: pypy/dist/pypy/lang/scheme/execution.py pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_continuation.py pypy/dist/pypy/lang/scheme/test/test_eval.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: letrec is continuation friendly, achived in wierd way; macros ellipsis corner-case fixed, still some to be done; added r4rs_derived_expr.ss which defines syntax for (cond...), (and ...) and (or ...) using macros while ExecutionContext init Modified: pypy/dist/pypy/lang/scheme/execution.py ============================================================================== --- pypy/dist/pypy/lang/scheme/execution.py (original) +++ pypy/dist/pypy/lang/scheme/execution.py Tue Aug 14 18:19:43 2007 @@ -1,5 +1,6 @@ import pypy.lang.scheme.object as ssobject -#from pypy.lang.scheme.object import * +from pypy.lang.scheme.ssparser import parse +import py class Location(object): def __init__(self, w_obj=None): @@ -14,6 +15,10 @@ except (TypeError, AttributeError): pass +de_file = py.magic.autopath().dirpath().join("r5rs_derived_expr.ss") +de_code = de_file.read() +de_expr_lst = parse(de_code) + class ExecutionContext(object): """Execution context implemented as a dict. @@ -21,14 +26,6 @@ """ def __init__(self, globalscope=None, scope=None, closure=False, cont_stack=None): - if globalscope is None: - self.globalscope = {} - for name, oper in OPERATION_MAP.items(): - self.globalscope[name] = Location(oper) - - else: - self.globalscope = globalscope - if scope is None: self.scope = {} else: @@ -41,6 +38,17 @@ else: self.cont_stack = cont_stack + if globalscope is None: + self.globalscope = {} + for name, oper in OPERATION_MAP.items(): + self.globalscope[name] = Location(oper) + + for expr in de_expr_lst: + expr.eval(self) + + else: + self.globalscope = globalscope + def _dispatch(self, symb): if isinstance(symb, ssobject.SymbolClosure): return (symb.closure, symb.name) Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Tue Aug 14 18:19:43 2007 @@ -198,11 +198,9 @@ return "()" def eval_cf(self, ctx, caller, cont, elst=[], enum=0): - #XXX not tests here raise SchemeSyntaxError def eval_tr(self, ctx): - #XXX not tests here raise SchemeSyntaxError w_nil = W_Nil() @@ -648,6 +646,16 @@ return w_promise.force(ctx) +#XXX no tests in eval +class EqP(W_Procedure): + _symbol_name = "eq?" + + def procedure(self, ctx, lst): + if len(lst) != 2: + raise WrongArgsNumber + + return W_Boolean(lst[0] is lst[1]) + ## # Predicate ## @@ -728,7 +736,10 @@ return w_obj.round() % 2 == 0 -#XXX no tests for it +## +# Type Pradicates +## + class PairP(W_Procedure): _symbol_name = "pair?" @@ -736,11 +747,16 @@ if len(lst) != 1: raise WrongArgsNumber - w_obj = lst[0] - if isinstance(w_obj, W_Pair): - return W_Boolean(True) + return W_Boolean(isinstance(lst[0], W_Pair)) + +class ProcedureP(W_Procedure): + _symbol_name = "procedure?" + + def procedure(self, ctx, lst): + if len(lst) != 1: + raise WrongArgsNumber - return W_Boolean(False) + return W_Boolean(isinstance(lst[0], W_Procedure)) ## # Macro @@ -896,9 +912,35 @@ return body.eval_tr(local_ctx) +class DictWrapper(W_Root): + def __init__(self, w_dict): + self.d = w_dict + class Letrec(W_Macro): _symbol_name = "letrec" + def continue_tr(self, ctx, lst, elst, cnt=True): + ctx = ctx.copy() + (body, name_symb, name_val, cont_val) = elst + assert isinstance(name_symb, DictWrapper) + assert isinstance(name_val, DictWrapper) + assert isinstance(lst, W_Symbol) + + cont_name = lst.name + for (name, w_val) in name_val.d.items(): + if name == cont_name: + ctx.ssete(lst, cont_val) + else: + ctx.ssete(name_symb.d[name], w_val) + + w_result = body.eval(ctx) + + if len(ctx.cont_stack) == 0: + raise ContinuationReturn(w_result) + + cont = ctx.cont_stack.pop() + return cont.run(ctx, w_result) + def call_tr(self, ctx, lst): """let uses eval_body, so it is tail-recursive aware""" if not isinstance(lst, W_Pair): @@ -907,6 +949,7 @@ body = Body(lst.cdr) map_name_expr = {} map_name_symb = {} + w_name_symb = DictWrapper(map_name_symb) w_formal = lst.car while isinstance(w_formal, W_Pair): w_def = w_formal.get_car_as_pair() @@ -917,8 +960,12 @@ w_formal = w_formal.cdr map_name_val = {} + w_name_val = DictWrapper(map_name_val) for (name, expr) in map_name_expr.items(): - map_name_val[name] = expr.eval(local_ctx) + #map_name_val[name] = expr.eval(local_ctx) + map_name_val[name] = expr.eval_cf(local_ctx, self, + map_name_symb[name], + [body, w_name_symb, w_name_val], 3) for (name, w_val) in map_name_val.items(): local_ctx.ssete(map_name_symb[name], w_val) @@ -1116,14 +1163,16 @@ return self.matchr(ctx, self.pattern.cdr, w_expr.cdr) def matchr(self, ctx, w_patt, w_expr): + print " >", w_patt.to_string(), w_expr.to_string() if isinstance(w_patt, W_Pair): w_pattcar = w_patt.car + w_pattcdr = w_patt.cdr if isinstance(w_expr, W_Pair): mdict_car = self.matchr(ctx, w_pattcar, w_expr.car) try: #we catch EllipsisPattern here because in car # we dont know how to deal with it - mdict_cdr = self.matchr(ctx, w_patt.cdr, w_expr.cdr) + mdict_cdr = self.matchr(ctx, w_pattcdr, w_expr.cdr) except EllipsisPattern: print "ellipsis matched", w_patt, w_expr @@ -1144,8 +1193,19 @@ mdict_car.update(mdict_cdr) return mdict_car - if w_pattcar is w_ellipsis and w_expr is w_nil: - raise EllipsisPattern + if w_expr is w_nil: + #one matched to ellipsis + if w_pattcar is w_ellipsis: + raise EllipsisPattern + + #zero matched to ellipsis + if isinstance(w_pattcdr, W_Pair) and \ + w_pattcdr.car is w_ellipsis: + if not isinstance(w_pattcar, W_Symbol): + #XXX this must be added + #print w_patt, "matched to ()" + raise NotImplementedError + return {w_pattcar.name: Ellipsis([])} if w_patt is w_ellipsis: raise EllipsisPattern @@ -1224,6 +1284,7 @@ def match(self, ctx, w_expr): for rule in self.syntax_lst: try: + print "m>", rule.pattern.to_string() match_dict = rule.match(ctx, w_expr) return (rule.template, match_dict) except MatchError: @@ -1233,6 +1294,7 @@ def expand(self, ctx, w_expr): try: + print w_expr.to_string() (template, match_dict) = self.match(ctx, w_expr) except MatchError: raise SchemeSyntaxError Added: pypy/dist/pypy/lang/scheme/r5rs_derived_expr.ss ============================================================================== --- (empty file) +++ pypy/dist/pypy/lang/scheme/r5rs_derived_expr.ss Tue Aug 14 18:19:43 2007 @@ -0,0 +1,41 @@ +(define-syntax cond + (syntax-rules (else =>) + ((cond (else result1 result2 ...)) + (begin result1 result2 ...)) + ((cond (test => result)) + (let ((temp test)) + (if temp (result temp)))) + ((cond (test => result) clause1 clause2 ...) + (let ((temp test)) + (if temp + (result temp) + (cond clause1 clause2 ...)))) + ((cond (test)) test) + ((cond (test) clause1 clause2 ...) + (let ((temp test)) + (if temp + temp + (cond clause1 clause2 ...)))) + ((cond (test result1 result2 ...)) + (if test (begin result1 result2 ...))) + ((cond (test result1 result2 ...) + clause1 clause2 ...) + (if test + (begin result1 result2 ...) + (cond clause1 clause2 ...))))) + +(define-syntax and + (syntax-rules () + ((and) #t) + ((and test) test) + ((and test1 test2 ...) + (if test1 (and test2 ...) #f)))) + +(define-syntax or + (syntax-rules () + ((or) #f) + ((or test) test) + ((or test1 test2 ...) + (let ((x test1)) + (if x x (or test2 ...)))))) + Modified: pypy/dist/pypy/lang/scheme/test/test_continuation.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_continuation.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_continuation.py Tue Aug 14 18:19:43 2007 @@ -211,7 +211,6 @@ assert w_result.to_number() == 10 def test_pitfall_1_1(): - py.test.skip("letrec not cf") ctx = ExecutionContext() w_result = eval_(ctx, """ (let ((cont #f)) @@ -228,20 +227,20 @@ assert w_result.to_number() == 1 def test_pitfall_1_2(): - py.test.skip("(cond ...) and (procedure? ...) not implemented") + #py.test.skip("(cond ...), (and ...) not implemented") ctx = ExecutionContext() + w_result = eval_(ctx, """ (letrec ((x (call/cc list)) (y (call/cc list))) (cond ((procedure? x) (x (pair? y))) - ((procedure? y) (y (pair? x)))) + ((procedure? y) (y (pair? x)))) (let ((x (car x)) (y (car y))) - (and (call/cc x) (call/cc y) (call/cc x)))))""") + (and (call/cc x) (call/cc y) (call/cc x))))""") assert isinstance(w_result, W_Boolean) assert w_result.to_boolean() is True def test_pitfall_1_3(): - py.test.skip("(eq? ...) not implemented, letrec not cf") ctx = ExecutionContext() w_result = eval_(ctx, """ (letrec ((x (call/cc Modified: pypy/dist/pypy/lang/scheme/test/test_eval.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_eval.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_eval.py Tue Aug 14 18:19:43 2007 @@ -8,7 +8,7 @@ W_Pair(W_Integer(4), W_Pair(W_Integer(5), w_nil))) assert w_num.eval(ExecutionContext()).to_number() == 9 -def eval_expr(ctx, expr): +def eval_(ctx, expr): return parse(expr)[0].eval(ctx) def eval_noctx(expr): @@ -67,73 +67,73 @@ ctx.put("v1", W_Integer(4)) ctx.put("v2", W_Integer(5)) - w_num = eval_expr(ctx, "(+ 1 v1 v2)") + w_num = eval_(ctx, "(+ 1 v1 v2)") assert w_num.to_number() == 10 ctx.put("v2", W_Real(3.2)) - w_num = eval_expr(ctx, "(+ 1 v1 v2)") + w_num = eval_(ctx, "(+ 1 v1 v2)") assert w_num.to_number() == 8.2 def test_ctx_define(): ctx = ExecutionContext() - eval_expr(ctx, "(define v1 42)") + eval_(ctx, "(define v1 42)") assert ctx.get("v1").to_number() == 42 - w_num = eval_expr(ctx, "v1") + w_num = eval_(ctx, "v1") assert w_num.to_number() == 42 - eval_expr(ctx, "(define v2 2.1)") + eval_(ctx, "(define v2 2.1)") assert ctx.get("v2").to_number() == 2.1 - w_num = eval_expr(ctx, "(+ 1 v1 v2)") + w_num = eval_(ctx, "(+ 1 v1 v2)") assert w_num.to_number() == 45.1 - eval_expr(ctx, "(define v2 3.1)") - w_num = eval_expr(ctx, "(+ 1 v1 v2)") + eval_(ctx, "(define v2 3.1)") + w_num = eval_(ctx, "(+ 1 v1 v2)") assert w_num.to_number() == 46.1 def text_unbound(): ctx = ExecutionContext() - py.test.raises(UnboundVariable, eval_expr, ctx, "y") + py.test.raises(UnboundVariable, eval_, ctx, "y") def test_sete(): ctx = ExecutionContext() - eval_expr(ctx, "(define x 42)") + eval_(ctx, "(define x 42)") loc1 = ctx.get_location("x") - eval_expr(ctx, "(set! x 43)") + eval_(ctx, "(set! x 43)") loc2 = ctx.get_location("x") assert ctx.get("x").to_number() == 43 assert loc1 is loc2 - py.test.raises(UnboundVariable, eval_expr, ctx, "(set! y 42)") + py.test.raises(UnboundVariable, eval_, ctx, "(set! y 42)") def test_func(): ctx = ExecutionContext() - w_func = eval_expr(ctx, "+") + w_func = eval_(ctx, "+") assert isinstance(w_func, W_Procedure) def test_if_simple(): ctx = ExecutionContext() - w_t = eval_expr(ctx, "(if #t #t #f)") + w_t = eval_(ctx, "(if #t #t #f)") assert w_t.to_boolean() is True - w_f = eval_expr(ctx, "(if #f #t #f)") + w_f = eval_(ctx, "(if #f #t #f)") assert w_f.to_boolean() is False - w_f = eval_expr(ctx, "(if 1 #f #t)") + w_f = eval_(ctx, "(if 1 #f #t)") assert w_f.to_boolean() is False - w_f = eval_expr(ctx, "(if #t #t)") + w_f = eval_(ctx, "(if #t #t)") assert w_f.to_boolean() is True - w_f = eval_expr(ctx, "(if #f #t)") + w_f = eval_(ctx, "(if #f #t)") assert w_f.to_boolean() is False def test_if_evaluation(): ctx = ExecutionContext() - eval_expr(ctx, "(define then #f)") - eval_expr(ctx, "(define else #f)") - eval_expr(ctx, "(if #t (define then #t) (define else #t))") + eval_(ctx, "(define then #f)") + eval_(ctx, "(define else #f)") + eval_(ctx, "(if #t (define then #t) (define else #t))") assert ctx.get("then").to_boolean() is True assert ctx.get("else").to_boolean() is False - eval_expr(ctx, "(define then #f)") - eval_expr(ctx, "(define else #f)") - eval_expr(ctx, "(if #f (define then #t) (define else #t))") + eval_(ctx, "(define then #f)") + eval_(ctx, "(define else #f)") + eval_(ctx, "(if #f (define then #t) (define else #t))") assert ctx.get("then").to_boolean() is False assert ctx.get("else").to_boolean() is True @@ -205,81 +205,81 @@ def test_lambda_noargs(): ctx = ExecutionContext() - w_lambda = eval_expr(ctx, "(lambda () 12)") + w_lambda = eval_(ctx, "(lambda () 12)") assert isinstance(w_lambda, W_Procedure) assert isinstance(w_lambda, W_Lambda) ctx.put("f1", w_lambda) - w_result = eval_expr(ctx, "(f1)") + w_result = eval_(ctx, "(f1)") assert isinstance(w_result, W_Integer) assert w_result.to_number() == 12 def test_lambda_args(): ctx = ExecutionContext() - w_lam = eval_expr(ctx, "(define f1 (lambda (n) n))") + w_lam = eval_(ctx, "(define f1 (lambda (n) n))") assert isinstance(w_lam, W_Lambda) - w_result = eval_expr(ctx, "(f1 42)") + w_result = eval_(ctx, "(f1 42)") assert isinstance(w_result, W_Integer) assert w_result.to_number() == 42 - w_result = eval_expr(ctx, "((lambda (n m) (+ n m)) 42 -42)") + w_result = eval_(ctx, "((lambda (n m) (+ n m)) 42 -42)") assert isinstance(w_result, W_Integer) assert w_result.to_number() == 0 def test_lambda_top_ctx(): ctx = ExecutionContext() - eval_expr(ctx, "(define n 42)") - eval_expr(ctx, "(define f1 (lambda (m) (+ n m)))") - w_result = eval_expr(ctx, "(f1 -42)") + eval_(ctx, "(define n 42)") + eval_(ctx, "(define f1 (lambda (m) (+ n m)))") + w_result = eval_(ctx, "(f1 -42)") assert isinstance(w_result, W_Integer) assert w_result.to_number() == 0 - eval_expr(ctx, "(define n 84)") - w_result = eval_expr(ctx, "(f1 -42)") + eval_(ctx, "(define n 84)") + w_result = eval_(ctx, "(f1 -42)") assert isinstance(w_result, W_Integer) assert w_result.to_number() == 42 def test_lambda_fac(): ctx = ExecutionContext() - eval_expr(ctx, """ + eval_(ctx, """ (define fac (lambda (n) (if (= n 1) n (* (fac (- n 1)) n))))""") assert isinstance(ctx.get("fac"), W_Lambda) - w_result = eval_expr(ctx, "(fac 4)") + w_result = eval_(ctx, "(fac 4)") assert w_result.to_number() == 24 - w_result = eval_expr(ctx, "(fac 5)") + w_result = eval_(ctx, "(fac 5)") assert w_result.to_number() == 120 def test_lambda2(): ctx = ExecutionContext() - eval_expr(ctx, """(define adder (lambda (x) (lambda (y) (+ x y))))""") - w_lambda = eval_expr(ctx, "(adder 6)") + eval_(ctx, """(define adder (lambda (x) (lambda (y) (+ x y))))""") + w_lambda = eval_(ctx, "(adder 6)") assert isinstance(w_lambda, W_Lambda) - eval_expr(ctx, """(define add6 (adder 6))""") - w_result = eval_expr(ctx, "(add6 5)") + eval_(ctx, """(define add6 (adder 6))""") + w_result = eval_(ctx, "(add6 5)") assert isinstance(w_result, W_Integer) assert w_result.to_number() == 11 - w_result = eval_expr(ctx, "((adder 6) 5)") + w_result = eval_(ctx, "((adder 6) 5)") assert isinstance(w_result, W_Integer) assert w_result.to_number() == 11 def test_lambda_long_body(): ctx = ExecutionContext() - eval_expr(ctx, """(define long_body (lambda () (define x 42) (+ x 1)))""") - w_result = eval_expr(ctx, "(long_body)") + eval_(ctx, """(define long_body (lambda () (define x 42) (+ x 1)))""") + w_result = eval_(ctx, "(long_body)") assert w_result.to_number() == 43 py.test.raises(UnboundVariable, ctx.get, "x") def test_lambda_lstarg(): ctx = ExecutionContext() - w_result = eval_expr(ctx, """((lambda x x) 1 2 3)""") + w_result = eval_(ctx, """((lambda x x) 1 2 3)""") assert isinstance(w_result, W_Pair) assert w_result.car.to_number() == 1 assert w_result.cdr.car.to_number() == 2 @@ -287,10 +287,10 @@ def test_lambda_dotted_lstarg(): ctx = ExecutionContext() - w_result = eval_expr(ctx, """((lambda (x y . z) z) 3 4)""") + w_result = eval_(ctx, """((lambda (x y . z) z) 3 4)""") assert w_result is w_nil - w_result = eval_expr(ctx, """((lambda (x y . z) z) 3 4 5 6)""") + w_result = eval_(ctx, """((lambda (x y . z) z) 3 4 5 6)""") assert isinstance(w_result, W_Pair) assert w_result.car.to_number() == 5 assert w_result.cdr.car.to_number() == 6 @@ -298,24 +298,24 @@ def test_define_lambda_sugar(): ctx = ExecutionContext() - eval_expr(ctx, """(define (f x) (+ x 1))""") - w_result = eval_expr(ctx, "(f 1)") + eval_(ctx, """(define (f x) (+ x 1))""") + w_result = eval_(ctx, "(f 1)") assert isinstance(w_result, W_Integer) assert w_result.to_number() == 2 - eval_expr(ctx, """(define (f2) (+ 1 1))""") - w_result = eval_expr(ctx, "(f2)") + eval_(ctx, """(define (f2) (+ 1 1))""") + w_result = eval_(ctx, "(f2)") assert isinstance(w_result, W_Integer) assert w_result.to_number() == 2 - eval_expr(ctx, """(define (f3 . x) x)""") - w_result = eval_expr(ctx, "(f3 1 2)") + eval_(ctx, """(define (f3 . x) x)""") + w_result = eval_(ctx, "(f3 1 2)") assert isinstance(w_result, W_Pair) assert w_result.car.to_number() == 1 assert w_result.cdr.car.to_number() == 2 - eval_expr(ctx, """(define (f4 x . y) x y)""") - w_result = eval_expr(ctx, "(f4 1 2)") + eval_(ctx, """(define (f4 x . y) x y)""") + w_result = eval_(ctx, "(f4 1 2)") assert isinstance(w_result, W_Pair) assert w_result.car.to_number() == 2 assert w_result.cdr is w_nil @@ -379,7 +379,7 @@ def test_list(): ctx = ExecutionContext() ctx.put("var", W_Integer(42)) - w_lst = eval_expr(ctx, "(list 1 var (+ 2 1) 'a)") + w_lst = eval_(ctx, "(list 1 var (+ 2 1) 'a)") assert isinstance(w_lst, W_Pair) assert w_lst.car.to_number() == 1 assert w_lst.cdr.car.to_number() == 42 @@ -391,7 +391,7 @@ ctx = ExecutionContext() w_global = W_Integer(0) ctx.put("var", w_global) - w_result = eval_expr(ctx, "(begin (set! var 11) (+ var 33))") + w_result = eval_(ctx, "(begin (set! var 11) (+ var 33))") assert w_result.to_number() == 44 assert ctx.get("var").to_number() == 11 @@ -399,11 +399,11 @@ ctx = ExecutionContext() w_global = W_Integer(0) ctx.put("var", w_global) - w_result = eval_expr(ctx, "(let ((var 42) (x (+ 2 var))) (+ var x))") + w_result = eval_(ctx, "(let ((var 42) (x (+ 2 var))) (+ var x))") assert w_result.to_number() == 44 assert ctx.get("var") is w_global - w_result = eval_expr(ctx, """ + w_result = eval_(ctx, """ (let ((x (lambda () 1))) (let ((y (lambda () (x))) (x (lambda () 2))) (y)))""") @@ -413,7 +413,7 @@ def test_letrec(): ctx = ExecutionContext() - w_result = eval_expr(ctx, """ + w_result = eval_(ctx, """ (letrec ((even? (lambda (n) (if (= n 0) @@ -427,7 +427,7 @@ (even? 2000))""") assert w_result.to_boolean() is True - w_result = eval_expr(ctx, """ + w_result = eval_(ctx, """ (let ((x (lambda () 1))) (letrec ((y (lambda () (x))) (x (lambda () 2))) (y)))""") @@ -493,40 +493,40 @@ def test_delay_promise_force(): ctx = ExecutionContext() - w_promise = eval_expr(ctx, "(delay (+ 1 2))") + w_promise = eval_(ctx, "(delay (+ 1 2))") assert isinstance(w_promise, W_Promise) ctx.put("d", w_promise) - w_promise2 = eval_expr(ctx, "d") + w_promise2 = eval_(ctx, "d") assert w_promise2 is w_promise - py.test.raises(NotCallable, eval_expr, ctx, "(d)") + py.test.raises(NotCallable, eval_, ctx, "(d)") - w_value = eval_expr(ctx, "(force d)") + w_value = eval_(ctx, "(force d)") assert w_value.to_number() == 3 py.test.raises(WrongArgType, eval_noctx, "(force 'a)") - eval_expr(ctx, "(define d2 (delay (+ 1 x)))") - eval_expr(ctx, "(define x 42)") - w_result = eval_expr(ctx, "(force d2)") + eval_(ctx, "(define d2 (delay (+ 1 x)))") + eval_(ctx, "(define x 42)") + w_result = eval_(ctx, "(force d2)") assert w_result.to_number() == 43 - eval_expr(ctx, "(set! x 0)") - w_result = eval_expr(ctx, "(force d2)") + eval_(ctx, "(set! x 0)") + w_result = eval_(ctx, "(force d2)") assert w_result.to_number() == 43 def test_lambda_context(): ctx = ExecutionContext() - eval_expr(ctx, """ + eval_(ctx, """ (define b (lambda () (define lam (lambda () (set! a 42))) (define a 12) (lam) a)) """) - w_num = eval_expr(ctx, "(b)") + w_num = eval_(ctx, "(b)") assert w_num.to_number() == 42 def test_evaluator(): ctx = ExecutionContext() - eval_expr(ctx, "(define a 0)") + eval_(ctx, "(define a 0)") w_obj = parse("(let () (set! a 42) a)")[0] (w_expr, new_ctx) = w_obj.eval_tr(ctx) assert ctx.get("a").to_number() == 42 @@ -540,43 +540,43 @@ def test_deep_recursion(): ctx = ExecutionContext() - eval_expr(ctx, "(define a 0)") - eval_expr(ctx, """ + eval_(ctx, "(define a 0)") + eval_(ctx, """ (define loop (lambda (n) (set! a (+ a 1)) (if (= n 0) n (loop (- n 1)))))""") - eval_expr(ctx, "(loop 2000)") + eval_(ctx, "(loop 2000)") assert ctx.get("a").to_number() == 2001 def test_setcar(): ctx = ExecutionContext() - w_pair = eval_expr(ctx, "(define lst '(1 2 3 4))") - eval_expr(ctx, "(set-car! lst 11)") - assert w_pair is eval_expr(ctx, "lst") - assert eval_expr(ctx, "(car lst)").to_number() == 11 + w_pair = eval_(ctx, "(define lst '(1 2 3 4))") + eval_(ctx, "(set-car! lst 11)") + assert w_pair is eval_(ctx, "lst") + assert eval_(ctx, "(car lst)").to_number() == 11 - eval_expr(ctx, "(set-car! (cdr lst) 12)") - assert eval_expr(ctx, "(car (cdr lst))").to_number() == 12 + eval_(ctx, "(set-car! (cdr lst) 12)") + assert eval_(ctx, "(car (cdr lst))").to_number() == 12 def test_setcdr(): ctx = ExecutionContext() - w_pair = eval_expr(ctx, "(define lst '(1 2 3 4))") - eval_expr(ctx, "(set-cdr! lst (cdr (cdr lst)))") - w_lst = eval_expr(ctx, "lst") + w_pair = eval_(ctx, "(define lst '(1 2 3 4))") + eval_(ctx, "(set-cdr! lst (cdr (cdr lst)))") + w_lst = eval_(ctx, "lst") assert w_pair is w_lst assert w_lst.to_string() == "(1 3 4)" - eval_expr(ctx, "(set-cdr! (cdr lst) '(12))") - w_lst = eval_expr(ctx, "lst") + eval_(ctx, "(set-cdr! (cdr lst) '(12))") + w_lst = eval_(ctx, "lst") assert w_lst.to_string() == "(1 3 12)" #warning circural list - eval_expr(ctx, "(set-cdr! (cdr (cdr lst)) lst)") - w_lst = eval_expr(ctx, "lst") - assert w_lst is eval_expr(ctx, "(cdr (cdr (cdr lst)))") + eval_(ctx, "(set-cdr! (cdr (cdr lst)) lst)") + w_lst = eval_(ctx, "lst") + assert w_lst is eval_(ctx, "(cdr (cdr (cdr lst)))") def test_quasiquote(): w_res = eval_noctx("(quasiquote (list (unquote (+ 1 2)) 4))") @@ -632,3 +632,30 @@ assert w_res.to_string() == \ "(1 (quasiquote (2 (unquote-splicing (list 3 4 5 6 7)))))" +def test_nil_eval(): + ctx = ExecutionContext() + py.test.raises(SchemeSyntaxError, eval_, ctx, "()") + +def test_type_predicates(): + ctx = ExecutionContext() + + assert eval_(ctx, "(pair? 1)").to_boolean() is False + assert eval_(ctx, "(pair? '())").to_boolean() is False + assert eval_(ctx, "(pair? +)").to_boolean() is False + assert eval_(ctx, "(pair? (lambda () 1))").to_boolean() is False + assert eval_(ctx, "(pair? '(1))").to_boolean() is True + assert eval_(ctx, "(pair? (list 1))").to_boolean() is True + assert eval_(ctx, "(pair? (cons 1 2))").to_boolean() is True + + assert eval_(ctx, "(procedure? 1)").to_boolean() is False + assert eval_(ctx, "(procedure? '())").to_boolean() is False + assert eval_(ctx, "(procedure? '(1))").to_boolean() is False + assert eval_(ctx, "(procedure? (list 1))").to_boolean() is False + assert eval_(ctx, "(procedure? (cons 1 2))").to_boolean() is False + assert eval_(ctx, "(procedure? +)").to_boolean() is True + assert eval_(ctx, "(procedure? (lambda () 1))").to_boolean() is True + +def test_eq(): + #XXX must be added soon! + py.test.skip("to lazy to write it now") + Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Tue Aug 14 18:19:43 2007 @@ -464,9 +464,10 @@ assert w_result.to_number() == 4 def test_pitfall_3_2(): - py.test.skip("(cond ...) not implemented yet") + ctx = ExecutionContext() + #define inside macors can and sometimes can not introduce new binding - w_result = eval_noctx("""(let-syntax ((foo (syntax-rules () + w_result = eval_(ctx, """(let-syntax ((foo (syntax-rules () ((_ var) (define var 1))))) (let ((x 2)) (begin (define foo +)) From arigo at codespeak.net Tue Aug 14 19:23:33 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Aug 2007 19:23:33 +0200 (CEST) Subject: [pypy-svn] r45660 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070814172333.05450815B@code0.codespeak.net> Author: arigo Date: Tue Aug 14 19:23:32 2007 New Revision: 45660 Added: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py (contents, props changed) Log: Forgot to add this to the previously-created branch. Added: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py Tue Aug 14 19:23:32 2007 @@ -0,0 +1,68 @@ +import os +from pypy.annotation import model as annmodel +from pypy.rpython.controllerentry import Controller +from pypy.rpython.extfunc import _register_external +from pypy.rpython.lltypesystem import rffi, lltype + +# ____________________________________________________________ +# +# Annotation support to control access to 'os.environ' in the RPython program + +class OsEnvironController(Controller): + knowntype = os.environ.__class__ + + def convert(self, obj): + return None # 'None' is good enough, there is only one os.environ + + def getitem(self, obj, key): + # in the RPython program reads of 'os.environ[key]' are redirected here + return r_getenv(key) + + def setitem(self, obj, key, value): + # in the RPython program, 'os.environ[key] = value' is redirected here + r_putenv(key, value) + + +# ____________________________________________________________ +# +# Lower-level interface: dummy placeholders and external registations + +def r_getenv(name): + just_a_placeholder + +os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP) + +def getenv_lltypeimpl(name): + l_name = rffi.str2charp(name) + l_result = os_getenv(l_name) + if l_result: + result = rffi.charp2str(l_result) + else: + result = None + rffi.free_charp(l_name) + return result + +_register_external(r_getenv, [str], annmodel.SomeString(can_be_None=True), + export_name='ll_os.ll_os_getenv', + llimpl=getenv_lltypeimpl) + +# ____________________________________________________________ + +def r_putenv(name, value): + just_a_placeholder + +os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) + +def putenv_lltypeimpl(name, value): + l_string = rffi.str2charp('%s=%s' % (name, value)) + l_result = os_putenv(l_name) + if l_result: + result = rffi.charp2str(l_result) + else: + result = None + rffi.free_charp(l_string) <-------! + return result + +_register_external(r_putenv, [str, str], annmodel.s_None, + export_name='ll_os.ll_os_putenv', + llimpl=putenv_lltypeimpl) From cfbolz at codespeak.net Wed Aug 15 12:55:09 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 15 Aug 2007 12:55:09 +0200 (CEST) Subject: [pypy-svn] r45672 - pypy/dist/pypy/translator/c/test Message-ID: <20070815105509.BF3EA8137@code0.codespeak.net> Author: cfbolz Date: Wed Aug 15 12:55:09 2007 New Revision: 45672 Modified: pypy/dist/pypy/translator/c/test/test_boehm.py Log: Test that I expected to fail with boehm about id(obj) not keeping obj alive. Modified: pypy/dist/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_boehm.py (original) +++ pypy/dist/pypy/translator/c/test/test_boehm.py Wed Aug 15 12:55:09 2007 @@ -95,6 +95,49 @@ # it might be the test's fault though. assert 0 < res <= 84 + def test_id_is_weak(self): + # test that id(obj) does not keep obj alive + from pypy.rpython.lltypesystem.lloperation import llop + class State: + pass + s = State() + class A(object): + def __del__(self): + s.a_dels += 1 + class B(A): + def __del__(self): + s.b_dels += 1 + class C(A): + pass + def f(): + s.a_dels = 0 + s.b_dels = 0 + a = A() + ida = id(a) + b = B() + idb = id(b) + c = C() + idc = id(c) + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + + # the strange additions at the end are to keep ida, idb alive + return s.a_dels * 10 + s.b_dels + ida + idb - idb - ida + fn = self.getcompiled(f) + # we can't demand that boehm has collected all of the objects, + # even with the gc__collect call. calling the compiled + # function twice seems to help, though. + res = 0 + res += fn() + res += fn() + # if res is still 0, then we haven't tested anything so fail. + # it might be the test's fault though. + assert 0 < res <= 44 + print res + + + def test_weakgcaddress_is_weak(self): py.test.skip("weakgcaddress as we know it is fragile") from pypy.rpython.lltypesystem.lloperation import llop From arigo at codespeak.net Wed Aug 15 13:20:28 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Aug 2007 13:20:28 +0200 (CEST) Subject: [pypy-svn] r45673 - pypy/dist/pypy/translator/c/test Message-ID: <20070815112028.3C724810B@code0.codespeak.net> Author: arigo Date: Wed Aug 15 13:20:27 2007 New Revision: 45673 Modified: pypy/dist/pypy/translator/c/test/test_boehm.py Log: Make this test fail. Pfew, not an easy task to outguess both Boehm, gcc and our translation toolchain. Modified: pypy/dist/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_boehm.py (original) +++ pypy/dist/pypy/translator/c/test/test_boehm.py Wed Aug 15 13:20:27 2007 @@ -97,6 +97,7 @@ def test_id_is_weak(self): # test that id(obj) does not keep obj alive + py.test.skip("fails") from pypy.rpython.lltypesystem.lloperation import llop class State: pass @@ -109,9 +110,7 @@ s.b_dels += 1 class C(A): pass - def f(): - s.a_dels = 0 - s.b_dels = 0 + def run_once(): a = A() ida = id(a) b = B() @@ -121,22 +120,31 @@ llop.gc__collect(lltype.Void) llop.gc__collect(lltype.Void) llop.gc__collect(lltype.Void) - - # the strange additions at the end are to keep ida, idb alive - return s.a_dels * 10 + s.b_dels + ida + idb - idb - ida - fn = self.getcompiled(f) + return ida, idb, idc + def f(n): + s.a_dels = 0 + s.b_dels = 0 + a1, b1, c1 = run_once() + a2, b2, c2 = run_once() + a3, b3, c3 = run_once() + a4, b4, c4 = run_once() + a5, b5, c5 = run_once() + return (s.a_dels, s.b_dels, + a1, b1, c1, + a2, b2, c2, + a3, b3, c3, + a4, b4, c4, + a5, b5, c5) + fn = self.getcompiled(f, [int]) # we can't demand that boehm has collected all of the objects, - # even with the gc__collect call. calling the compiled - # function twice seems to help, though. - res = 0 - res += fn() - res += fn() - # if res is still 0, then we haven't tested anything so fail. + # even with the gc__collect call. + res = fn(50) + res1, res2 = res[:2] + # if res1 or res2 is still 0, then we haven't tested anything so fail. # it might be the test's fault though. - assert 0 < res <= 44 - print res - - + print res1, res2 + assert 0 < res1 <= 10 + assert 0 < res2 <= 5 def test_weakgcaddress_is_weak(self): py.test.skip("weakgcaddress as we know it is fragile") From arigo at codespeak.net Wed Aug 15 13:33:36 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Aug 2007 13:33:36 +0200 (CEST) Subject: [pypy-svn] r45674 - in pypy/branch/pypy-more-rtti-inprogress: rpython/module translator/c/test Message-ID: <20070815113336.CAAA2813E@code0.codespeak.net> Author: arigo Date: Wed Aug 15 13:33:35 2007 New Revision: 45674 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_genc.py Log: Finish os.putenv(). Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py Wed Aug 15 13:33:35 2007 @@ -51,17 +51,24 @@ def r_putenv(name, value): just_a_placeholder +class EnvKeepalive: + pass +envkeepalive = EnvKeepalive() +envkeepalive.byname = {} + os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) def putenv_lltypeimpl(name, value): l_string = rffi.str2charp('%s=%s' % (name, value)) - l_result = os_putenv(l_name) - if l_result: - result = rffi.charp2str(l_result) - else: - result = None - rffi.free_charp(l_string) <-------! - return result + error = os_putenv(l_string) + if error: + raise OSError(rffi.get_errno(), "os_putenv failed") + # keep 'l_string' alive - we know that the C library needs it + # until the next call to putenv() with the same 'name'. + l_oldstring = envkeepalive.byname.get(name, lltype.nullptr(rffi.CCHARP.TO)) + envkeepalive.byname[name] = l_string + if l_oldstring: + rffi.free_charp(l_oldstring) _register_external(r_putenv, [str, str], annmodel.s_None, export_name='ll_os.ll_os_putenv', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Wed Aug 15 13:33:35 2007 @@ -693,11 +693,16 @@ assert result == os.environ['USER'] def test_dictlike_environ_setitem(): - def fn(s, t): - os.environ[s] = t - func = compile(fn, [str, str]) - func('PYPY_TEST_DICTLIKE_ENVIRON', '42') - assert os.environ['PYPY_TEST_DICTLIKE_ENVIRON'] == '42' + def fn(s, t1, t2, t3, t4, t5): + os.environ[s] = t1 + os.environ[s] = t2 + os.environ[s] = t3 + os.environ[s] = t4 + os.environ[s] = t5 + func = compile(fn, [str, str, str, str, str, str]) + func('PYPY_TEST_DICTLIKE_ENVIRON', 'a', 'b', 'c', 'FOOBAR', '42', + expected_extra_mallocs = (1, 2, 3, 4)) # at least one, less than 5 + assert _real_getenv('PYPY_TEST_DICTLIKE_ENVIRON') == '42' def test_opendir_readdir(): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_genc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_genc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_genc.py Wed Aug 15 13:33:35 2007 @@ -51,7 +51,10 @@ expected_extra_mallocs = 0 res = compiled_fn(*args, **kwds) mallocs, frees = module.malloc_counters() - assert mallocs - frees == expected_extra_mallocs + if isinstance(expected_extra_mallocs, int): + assert mallocs - frees == expected_extra_mallocs + else: + assert mallocs - frees in expected_extra_mallocs return res return checking_fn From cfbolz at codespeak.net Wed Aug 15 13:58:31 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 15 Aug 2007 13:58:31 +0200 (CEST) Subject: [pypy-svn] r45675 - pypy/dist/pypy/doc Message-ID: <20070815115831.D085A814E@code0.codespeak.net> Author: cfbolz Date: Wed Aug 15 13:58:29 2007 New Revision: 45675 Modified: pypy/dist/pypy/doc/cleanup-todo.txt Log: add a note about id mess Modified: pypy/dist/pypy/doc/cleanup-todo.txt ============================================================================== --- pypy/dist/pypy/doc/cleanup-todo.txt (original) +++ pypy/dist/pypy/doc/cleanup-todo.txt Wed Aug 15 13:58:29 2007 @@ -23,7 +23,9 @@ we can have more than one translator/annotator around (with the timeshifter) - unicode strings in RPython - - finish rctypes rewrite (some of items of this list depend on it) + - finish rctypes removal + - think about approaches to id, especially concerning boehm, where the id will + keep the object alive and concerning a moving GC interpreter ----------- From arigo at codespeak.net Wed Aug 15 14:09:46 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Aug 2007 14:09:46 +0200 (CEST) Subject: [pypy-svn] r45676 - in pypy/branch/pypy-more-rtti-inprogress: rpython/module translator/c/test Message-ID: <20070815120946.810C0809A@code0.codespeak.net> Author: arigo Date: Wed Aug 15 14:09:44 2007 New Revision: 45676 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: Support for os.environ.keys() and os.environ.items(). Not tested on OS/X. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py Wed Aug 15 14:09:44 2007 @@ -22,6 +22,14 @@ # in the RPython program, 'os.environ[key] = value' is redirected here r_putenv(key, value) + def get_keys(self, obj): + # 'os.environ.keys' is redirected here - note that it's the getattr + # that arrives here, not the actual method call! + return r_envkeys + + def get_items(self, obj): + # 'os.environ.items' is redirected here (not the actual method call!) + return r_envitems # ____________________________________________________________ # @@ -73,3 +81,58 @@ _register_external(r_putenv, [str, str], annmodel.s_None, export_name='ll_os.ll_os_putenv', llimpl=putenv_lltypeimpl) + +# ____________________________________________________________ +# Access to the 'environ' external variable + +if os.name.startswith('darwin'): + CCHARPPP = lltype.Ptr(lltype.FixedSizeArray(rffi.CCHARPP, 1)) + _os_NSGetEnviron = rffi.llexternal('_NSGetEnviron', [], CCHARPPP, + includes=['crt_externs.h']) + def os_get_environ(): + return _os_NSGetEnviron()[0] +else: + os_get_environ, _os_set_environ = rffi.CExternVariable(rffi.CCHARPP, + 'environ') + +# ____________________________________________________________ + +def r_envkeys(): + just_a_placeholder + +def envkeys_lltypeimpl(): + environ = os_get_environ() + result = [] + i = 0 + while environ[i]: + name_value = rffi.charp2str(environ[i]) + p = name_value.find('=') + if p >= 0: + result.append(name_value[:p]) + i += 1 + return result + +_register_external(r_envkeys, [], [str], # returns a list of strings + export_name='ll_os.ll_os_envkeys', + llimpl=envkeys_lltypeimpl) + +# ____________________________________________________________ + +def r_envitems(): + just_a_placeholder + +def envitems_lltypeimpl(): + environ = os_get_environ() + result = [] + i = 0 + while environ[i]: + name_value = rffi.charp2str(environ[i]) + p = name_value.find('=') + if p >= 0: + result.append((name_value[:p], name_value[p+1:])) + i += 1 + return result + +_register_external(r_envitems, [], [(str, str)], + export_name='ll_os.ll_os_envitems', + llimpl=envitems_lltypeimpl) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Wed Aug 15 14:09:44 2007 @@ -704,6 +704,39 @@ expected_extra_mallocs = (1, 2, 3, 4)) # at least one, less than 5 assert _real_getenv('PYPY_TEST_DICTLIKE_ENVIRON') == '42' +def test_dictlike_environ_keys(): + def fn(): + return '\x00'.join(os.environ.keys()) + func = compile(fn, []) + os.environ.setdefault('USER', 'UNNAMED_USER') + try: + del os.environ['PYPY_TEST_DICTLIKE_ENVKEYS'] + except: + pass + result1 = func().split('\x00') + os.environ['PYPY_TEST_DICTLIKE_ENVKEYS'] = '42' + result2 = func().split('\x00') + assert 'USER' in result1 + assert 'PYPY_TEST_DICTLIKE_ENVKEYS' not in result1 + assert 'USER' in result2 + assert 'PYPY_TEST_DICTLIKE_ENVKEYS' in result2 + +def test_dictlike_environ_items(): + def fn(): + result = [] + for key, value in os.environ.items(): + result.append('%s/%s' % (key, value)) + return '\x00'.join(result) + func = compile(fn, []) + os.environ.setdefault('USER', 'UNNAMED_USER') + result1 = func().split('\x00') + os.environ['PYPY_TEST_DICTLIKE_ENVITEMS'] = '783' + result2 = func().split('\x00') + assert ('USER/%s' % (os.environ['USER'],)) in result1 + assert 'PYPY_TEST_DICTLIKE_ENVITEMS/783' not in result1 + assert ('USER/%s' % (os.environ['USER'],)) in result2 + assert 'PYPY_TEST_DICTLIKE_ENVITEMS/783' in result2 + def test_opendir_readdir(): py.test.skip("deprecated") From arigo at codespeak.net Wed Aug 15 14:29:34 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Aug 2007 14:29:34 +0200 (CEST) Subject: [pypy-svn] r45677 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c/test Message-ID: <20070815122934.23DE38123@code0.codespeak.net> Author: arigo Date: Wed Aug 15 14:29:32 2007 New Revision: 45677 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/controllerentry.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py pypy/branch/pypy-more-rtti-inprogress/rpython/rcontrollerentry.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: Support for del os.environ[name] Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/controllerentry.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/controllerentry.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/controllerentry.py Wed Aug 15 14:29:32 2007 @@ -117,6 +117,13 @@ from pypy.rpython.rcontrollerentry import rtypedelegate return rtypedelegate(self.setitem, hop) + def ctrl_delitem(self, s_obj, s_key): + return delegate(self.delitem, s_obj, s_key) + + def rtype_delitem(self, hop): + from pypy.rpython.rcontrollerentry import rtypedelegate + return rtypedelegate(self.delitem, hop) + def ctrl_is_true(self, s_obj): return delegate(self.is_true, s_obj) @@ -237,6 +244,9 @@ def setitem((s_cin, s_key), s_value): s_cin.controller.ctrl_setitem(s_cin.s_real_obj, s_key, s_value) + def delitem((s_cin, s_key)): + s_cin.controller.ctrl_delitem(s_cin.s_real_obj, s_key) + class __extend__(pairtype(SomeControlledInstance, SomeControlledInstance)): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py Wed Aug 15 14:29:32 2007 @@ -22,6 +22,10 @@ # in the RPython program, 'os.environ[key] = value' is redirected here r_putenv(key, value) + def delitem(self, obj, key): + # in the RPython program, 'del os.environ[key]' is redirected here + r_unsetenv(key) + def get_keys(self, obj): # 'os.environ.keys' is redirected here - note that it's the getattr # that arrives here, not the actual method call! @@ -70,6 +74,7 @@ l_string = rffi.str2charp('%s=%s' % (name, value)) error = os_putenv(l_string) if error: + rffi.free_charp(l_string) raise OSError(rffi.get_errno(), "os_putenv failed") # keep 'l_string' alive - we know that the C library needs it # until the next call to putenv() with the same 'name'. @@ -83,6 +88,34 @@ llimpl=putenv_lltypeimpl) # ____________________________________________________________ + +def r_unsetenv(name): + # default implementation for platforms without a real unsetenv() + r_putenv(name, '') + +if hasattr(__import__(os.name), 'unsetenv'): + + os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) + + def unsetenv_lltypeimpl(name): + l_name = rffi.str2charp(name) + error = os_unsetenv(l_name) + rffi.free_charp(l_name) + if error: + raise OSError(rffi.get_errno(), "os_unsetenv failed") + try: + l_oldstring = envkeepalive.byname[name] + except KeyError: + pass + else: + del envkeepalive.byname[name] + rffi.free_charp(l_oldstring) + + _register_external(r_unsetenv, [str], annmodel.s_None, + export_name='ll_os.ll_os_unsetenv', + llimpl=unsetenv_lltypeimpl) + +# ____________________________________________________________ # Access to the 'environ' external variable if os.name.startswith('darwin'): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rcontrollerentry.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/rcontrollerentry.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/rcontrollerentry.py Wed Aug 15 14:29:32 2007 @@ -40,6 +40,9 @@ def rtype_setitem((r_controlled, r_key), hop): return r_controlled.controller.rtype_setitem(hop) + def rtype_delitem((r_controlled, r_key), hop): + return r_controlled.controller.rtype_delitem(hop) + def rtypedelegate(callable, hop, revealargs=[0], revealresult=False): bk = hop.rtyper.annotator.bookkeeper Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Wed Aug 15 14:29:32 2007 @@ -701,9 +701,44 @@ os.environ[s] = t5 func = compile(fn, [str, str, str, str, str, str]) func('PYPY_TEST_DICTLIKE_ENVIRON', 'a', 'b', 'c', 'FOOBAR', '42', - expected_extra_mallocs = (1, 2, 3, 4)) # at least one, less than 5 + expected_extra_mallocs = (2, 3, 4)) # at least two, less than 5 assert _real_getenv('PYPY_TEST_DICTLIKE_ENVIRON') == '42' +def test_dictlike_environ_delitem(): + def fn(s1, s2, s3, s4, s5): + for n in range(10): + os.environ[s1] = 't1' + os.environ[s2] = 't2' + os.environ[s3] = 't3' + os.environ[s4] = 't4' + os.environ[s5] = 't5' + del os.environ[s3] + del os.environ[s1] + del os.environ[s2] + del os.environ[s4] + # os.environ[s5] stays + func = compile(fn, [str, str, str, str, str]) + if hasattr(__import__(os.name), 'unsetenv'): + expected_extra_mallocs = range(2, 10) + # at least 2, less than 10: memory for s1, s2, s3, s4 should be freed + # (each kept-alive entry counts as two: the RPython string used as + # key in 'envkeepalive.byname' and the raw-allocated char* as value) + else: + expected_extra_mallocs = range(10, 18) + # at least 10, less than 18: memory for the initial s1, s2, s3, s4 + # should be freed, but replaced by new buffers for empty strings + func('PYPY_TEST_DICTLIKE_ENVDEL1', + 'PYPY_TEST_DICTLIKE_ENVDEL_X', + 'PYPY_TEST_DICTLIKE_ENVDELFOO', + 'PYPY_TEST_DICTLIKE_ENVDELBAR', + 'PYPY_TEST_DICTLIKE_ENVDEL5', + expected_extra_mallocs = expected_extra_mallocs) + assert not _real_getenv('PYPY_TEST_DICTLIKE_ENVDEL1') + assert not _real_getenv('PYPY_TEST_DICTLIKE_ENVDEL_X') + assert not _real_getenv('PYPY_TEST_DICTLIKE_ENVDELFOO') + assert not _real_getenv('PYPY_TEST_DICTLIKE_ENVDELBAR') + assert _real_getenv('PYPY_TEST_DICTLIKE_ENVDEL5') == 't5' + def test_dictlike_environ_keys(): def fn(): return '\x00'.join(os.environ.keys()) From jlg at codespeak.net Wed Aug 15 14:54:18 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Wed, 15 Aug 2007 14:54:18 +0200 (CEST) Subject: [pypy-svn] r45678 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070815125418.215DF8126@code0.codespeak.net> Author: jlg Date: Wed Aug 15 14:54:14 2007 New Revision: 45678 Modified: pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_eval.py Log: eq? and eqv? procedures implemented Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Wed Aug 15 14:54:14 2007 @@ -54,6 +54,11 @@ def eval_tr(self, ctx): return (self, None) + def eqv(self, w_obj): + return self is w_obj + + eq = eqv + class W_Undefined(W_Root): def to_string(self): return "#" @@ -77,9 +82,6 @@ w_obj = ctx.get(self.name) return (w_obj, None) - def eq_symbol(self, w_symb): - return w_symb is self - w_ellipsis = W_Symbol("...") def symbol(name): @@ -110,6 +112,13 @@ def __repr__(self): return "" + def eqv(self, w_obj): + if isinstance(w_obj, W_Boolean): + return self.boolval is w_obj.boolval + return False + + eq = eqv + class W_String(W_Root): def __init__(self, val): self.strval = val @@ -154,6 +163,11 @@ def is_integer(self): return self.realval == self.round() + def eqv(self, w_obj): + return isinstance(w_obj, W_Real) \ + and self.exact is w_obj.exact \ + and self.realval == w_obj.realval + W_Number = W_Real class W_Integer(W_Real): @@ -646,7 +660,6 @@ return w_promise.force(ctx) -#XXX no tests in eval class EqP(W_Procedure): _symbol_name = "eq?" @@ -654,7 +667,18 @@ if len(lst) != 2: raise WrongArgsNumber - return W_Boolean(lst[0] is lst[1]) + (a, b) = lst + return W_Boolean(a.eq(b)) + +class EqvP(W_Procedure): + _symbol_name = "eqv?" + + def procedure(self, ctx, lst): + if len(lst) != 2: + raise WrongArgsNumber + + (a, b) = lst + return W_Boolean(a.eqv(b)) ## # Predicate @@ -1202,7 +1226,7 @@ if isinstance(w_pattcdr, W_Pair) and \ w_pattcdr.car is w_ellipsis: if not isinstance(w_pattcar, W_Symbol): - #XXX this must be added + #XXX this must be added (with tests) #print w_patt, "matched to ()" raise NotImplementedError return {w_pattcar.name: Ellipsis([])} Modified: pypy/dist/pypy/lang/scheme/test/test_eval.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_eval.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_eval.py Wed Aug 15 14:54:14 2007 @@ -655,7 +655,71 @@ assert eval_(ctx, "(procedure? +)").to_boolean() is True assert eval_(ctx, "(procedure? (lambda () 1))").to_boolean() is True +def test_eqv(): + ctx = ExecutionContext() + + assert eval_(ctx, "(eqv? #t #t)").to_boolean() is True + assert eval_(ctx, "(eqv? #f #f)").to_boolean() is True + assert eval_(ctx, "(eqv? 'symb 'symb)").to_boolean() is True + assert eval_(ctx, "(eqv? 'symb 'SYMB)").to_boolean() is True + assert eval_(ctx, "(eqv? 42 42)").to_boolean() is True + assert eval_(ctx, "(eqv? 42.1 42.1)").to_boolean() is True + #assert eval_(ctx, "(eqv? #\a #\a)").to_boolean() is True + assert eval_(ctx, "(eqv? '() '())").to_boolean() is True + assert eval_(ctx, """(let ((p (cons 1 2))) + (eqv? p p))""").to_boolean() is True + #assert eval_(ctx, """(let ((p "a string")) + # (eqv? p p))""").to_boolean() is True + assert eval_(ctx, """(let ((p (lambda (x) x))) + (eqv? p p))""").to_boolean() is True + + assert eval_(ctx, "(eqv? #t 'symb)").to_boolean() is False + assert eval_(ctx, "(eqv? #f 42)").to_boolean() is False + assert eval_(ctx, "(eqv? #t #f)").to_boolean() is False + assert eval_(ctx, "(eqv? 'symb1 'symb2)").to_boolean() is False + assert eval_(ctx, "(eqv? 42 42.0)").to_boolean() is False + assert eval_(ctx, "(eqv? 42.0 42)").to_boolean() is False + assert eval_(ctx, "(eqv? 42 43)").to_boolean() is False + assert eval_(ctx, "(eqv? 42.1 42.2)").to_boolean() is False + #assert eval_(ctx, "(eqv? #\a #\b)").to_boolean() is False + assert eval_(ctx, "(eqv? (cons 1 2) (cons 1 2))").to_boolean() is False + #assert eval_(ctx, """(eqv? "a string" + # "a string")""").to_boolean() is False + assert eval_(ctx, """(eqv? (lambda () 1) + (lambda () 2))""").to_boolean() is False + def test_eq(): - #XXX must be added soon! - py.test.skip("to lazy to write it now") + ctx = ExecutionContext() + + assert eval_(ctx, "(eq? #t #t)").to_boolean() is True + assert eval_(ctx, "(eq? #f #f)").to_boolean() is True + assert eval_(ctx, "(eq? 'symb 'symb)").to_boolean() is True + assert eval_(ctx, "(eq? 'symb 'SYMB)").to_boolean() is True + assert eval_(ctx, "(eq? '() '())").to_boolean() is True + assert eval_(ctx, """(let ((n 42)) + (eq? n n))""").to_boolean() is True + assert eval_(ctx, """(let ((p (cons 1 2))) + (eq? p p))""").to_boolean() is True + #assert eval_(ctx, """(let ((p "a string")) + # (eq? p p))""").to_boolean() is True + assert eval_(ctx, """(let ((p (lambda (x) x))) + (eq? p p))""").to_boolean() is True + + assert eval_(ctx, "(eq? #t 'symb)").to_boolean() is False + assert eval_(ctx, "(eq? #f 42)").to_boolean() is False + assert eval_(ctx, "(eq? #t #f)").to_boolean() is False + assert eval_(ctx, "(eq? 'symb1 'symb2)").to_boolean() is False + assert eval_(ctx, "(eq? 42 42)").to_boolean() is False + assert eval_(ctx, "(eq? 42.1 42.1)").to_boolean() is False + #assert eval_(ctx, "(eq? #\a #\a)").to_boolean() is False + assert eval_(ctx, "(eq? 42 42.0)").to_boolean() is False + assert eval_(ctx, "(eq? 42.0 42)").to_boolean() is False + assert eval_(ctx, "(eq? 42 43)").to_boolean() is False + assert eval_(ctx, "(eq? 42.1 42.2)").to_boolean() is False + #assert eval_(ctx, "(eq? #\a #\b)").to_boolean() is False + assert eval_(ctx, "(eq? (cons 1 2) (cons 1 2))").to_boolean() is False + #assert eval_(ctx, """(eq? "a string" + # "a string")""").to_boolean() is False + assert eval_(ctx, """(eq? (lambda () 1) + (lambda () 2))""").to_boolean() is False From arigo at codespeak.net Wed Aug 15 15:03:45 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Aug 2007 15:03:45 +0200 (CEST) Subject: [pypy-svn] r45679 - in pypy/branch/pypy-more-rtti-inprogress: jit/codegen/demo jit/codegen/i386 jit/codegen/llvm module/posix module/sys rlib rpython rpython/module rpython/module/test translator/c translator/c/test translator/llvm/test Message-ID: <20070815130345.6E8C08101@code0.codespeak.net> Author: arigo Date: Wed Aug 15 15:03:44 2007 New Revision: 45679 Removed: pypy/branch/pypy-more-rtti-inprogress/rlib/ros.py Modified: pypy/branch/pypy-more-rtti-inprogress/jit/codegen/demo/support.py pypy/branch/pypy-more-rtti-inprogress/jit/codegen/i386/codebuf.py pypy/branch/pypy-more-rtti-inprogress/jit/codegen/llvm/logger.py pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py pypy/branch/pypy-more-rtti-inprogress/module/sys/state.py pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/llvm/test/test_extfunc.py Log: - support for 'os.environ.get(name)'. - kill rlib/ros.py. Yay! Modified: pypy/branch/pypy-more-rtti-inprogress/jit/codegen/demo/support.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/jit/codegen/demo/support.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/jit/codegen/demo/support.py Wed Aug 15 15:03:44 2007 @@ -1,7 +1,6 @@ import os, sys import py from pypy.tool.udir import udir -from pypy.rlib.ros import putenv from pypy.jit.codegen.graph2rgenop import rcompile from pypy.rpython.lltypesystem import lltype @@ -83,7 +82,7 @@ os.unlink(logfile) except OSError: pass - putenv('PYPYJITLOG=' + logfile) + os.environ['PYPYJITLOG'] = logfile if benchmark: py.test.skip("benchmarking: working in progress") Modified: pypy/branch/pypy-more-rtti-inprogress/jit/codegen/i386/codebuf.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/jit/codegen/i386/codebuf.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/jit/codegen/i386/codebuf.py Wed Aug 15 15:03:44 2007 @@ -78,8 +78,7 @@ def open(self): if self.log_fd < 0: # check the environment for a file name - from pypy.rlib.ros import getenv - s = getenv('PYPYJITLOG') + s = os.environ.get('PYPYJITLOG') if not s: self.enabled = False return False Modified: pypy/branch/pypy-more-rtti-inprogress/jit/codegen/llvm/logger.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/jit/codegen/llvm/logger.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/jit/codegen/llvm/logger.py Wed Aug 15 15:03:44 2007 @@ -23,8 +23,7 @@ return False if self.log_fd < 0: # check the environment for a file name - from pypy.rlib.ros import getenv - s = getenv('PYPYJITLOG') + s = os.environ.get('PYPYJITLOG') if not s: self.enabled = False return False Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Wed Aug 15 15:03:44 2007 @@ -1,6 +1,5 @@ from pypy.interpreter.baseobjspace import ObjSpace, W_Root from pypy.rlib.rarithmetic import intmask -from pypy.rlib import ros from pypy.interpreter.error import OperationError, wrap_oserror from pypy.rpython.module.ll_os import RegisterOs @@ -243,7 +242,6 @@ class State: def __init__(self, space): - self.posix_putenv_garbage = {} self.w_environ = space.newdict() def startup(self, space): _convertenviron(space, self.w_environ) @@ -252,38 +250,23 @@ return space.fromcache(State) def _convertenviron(space, w_env): - idx = 0 - while 1: - s = ros.environ(idx) - if s is None: - break - p = s.find('=') - if p >= 0: - key = s[:p] - value = s[p+1:] - space.setitem(w_env, space.wrap(key), space.wrap(value)) - idx += 1 + for key, value in os.environ.items(): + space.setitem(w_env, space.wrap(key), space.wrap(value)) def putenv(space, name, value): """Change or add an environment variable.""" - txt = '%s=%s' % (name, value) - ros.putenv(txt) - # Install the first arg and newstr in posix_putenv_garbage; - # this will cause previous value to be collected. This has to - # happen after the real putenv() call because the old value - # was still accessible until then. - get(space).posix_putenv_garbage[name] = txt + try: + os.environ[name] = value + except OSError, e: + raise wrap_oserror(space, e) putenv.unwrap_spec = [ObjSpace, str, str] def unsetenv(space, name): """Delete an environment variable.""" - if name in get(space).posix_putenv_garbage: + try: os.unsetenv(name) - # Remove the key from posix_putenv_garbage; - # this will cause it to be collected. This has to - # happen after the real unsetenv() call because the - # old value was still accessible until then. - del get(space).posix_putenv_garbage[name] + except OSError, e: + raise wrap_oserror(space, e) unsetenv.unwrap_spec = [ObjSpace, str] Modified: pypy/branch/pypy-more-rtti-inprogress/module/sys/state.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/sys/state.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/sys/state.py Wed Aug 15 15:03:44 2007 @@ -36,7 +36,6 @@ # build the initial path from the srcdir, which is the path of # the "dist" directory of a PyPy checkout. from pypy.module.sys.version import CPYTHON_VERSION - from pypy.rlib import ros dirname = '%d.%d.%d' % (CPYTHON_VERSION[0], CPYTHON_VERSION[1], @@ -52,7 +51,7 @@ checkdir(pypy_lib) importlist = [''] - pythonpath = ros.getenv('PYTHONPATH') + pythonpath = os.environ.get('PYTHONPATH') if pythonpath: for p in pythonpath.split(os.pathsep): if p: Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Wed Aug 15 15:03:44 2007 @@ -204,16 +204,6 @@ declare(rarithmetic.formatd, str, 'll_strtod/formatd') # ___________________________________________________________ -# special helpers for os with no equivalent -from pypy.rlib import ros -declare(ros.putenv, noneannotation, 'll_os/putenv') -declare(ros.environ, strnullannotation, 'll_os/environ') -declare(ros.opendir, ros.DIR, 'll_os/opendir') -declareptrtype(ros.DIR, "DIR", - readdir = (strnullannotation, 'll_os/readdir'), - closedir = (noneannotation, 'll_os/closedir')) - -# ___________________________________________________________ # stackless from pypy.rlib import rstack declare(rstack.stack_frames_depth, int, 'll_stackless/stack_frames_depth') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Wed Aug 15 15:03:44 2007 @@ -9,7 +9,6 @@ from pypy.rpython.module.support import ll_strcpy, OOSupport from pypy.rpython.module.support import to_opaque_object, from_opaque_object from pypy.tool.sourcetools import func_with_new_name -from pypy.rlib import ros from pypy.rlib.rarithmetic import r_longlong from pypy.tool.staticmethods import ClassMethods import stat @@ -729,20 +728,6 @@ os.rmdir(cls.from_rstr(path)) ll_os_rmdir.suggested_primitive = True - # this function is not really the os thing, but the internal one. - def ll_os_putenv(cls, name_eq_value): - ros.putenv(cls.from_rstr(name_eq_value)) - ll_os_putenv.suggested_primitive = True - - def ll_os_unsetenv(cls, name): - os.unsetenv(cls.from_rstr(name)) - ll_os_unsetenv.suggested_primitive = True - - # get the initial environment by indexing - def ll_os_environ(cls, idx): - return ros.environ(idx) - ll_os_environ.suggested_primitive = True - def ll_os_chmod(cls, path, mode): os.chmod(cls.from_rstr(path), mode) ll_os_chmod.suggested_primitive = True @@ -778,22 +763,3 @@ def ll_os__exit(cls, status): os._exit(status) ll_os__exit.suggested_primitive = True - - # ____________________________________________________________ - # opendir/readdir - - def ll_os_opendir(cls, dirname): - dir = ros.opendir(cls.from_rstr(dirname)) - return to_opaque_object(dir) - ll_os_opendir.suggested_primitive = True - - def ll_os_readdir(cls, opaquedir): - dir = from_opaque_object(opaquedir) - nextentry = dir.readdir() - return cls.to_rstr(nextentry) - ll_os_readdir.suggested_primitive = True - - def ll_os_closedir(cls, opaquedir): - dir = from_opaque_object(opaquedir) - dir.closedir() - ll_os_closedir.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py Wed Aug 15 15:03:44 2007 @@ -16,7 +16,10 @@ def getitem(self, obj, key): # in the RPython program reads of 'os.environ[key]' are redirected here - return r_getenv(key) + result = r_getenv(key) + if result is None: + raise KeyError + return result def setitem(self, obj, key, value): # in the RPython program, 'os.environ[key] = value' is redirected here @@ -35,12 +38,16 @@ # 'os.environ.items' is redirected here (not the actual method call!) return r_envitems + def get_get(self, obj): + # 'os.environ.get' is redirected here (not the actual method call!) + return r_getenv + # ____________________________________________________________ # # Lower-level interface: dummy placeholders and external registations def r_getenv(name): - just_a_placeholder + just_a_placeholder # should return None if name not found os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py Wed Aug 15 15:03:44 2007 @@ -37,75 +37,6 @@ assert file(filename).read().strip() == '2' os.unlink(filename) -def test_putenv_unsetenv(): - filename = str(udir.join('test_putenv.txt')) - arg = impl.to_rstr('abcdefgh=12345678') - impl.ll_os_putenv(arg) - cmd = '''python -c "import os; print os.environ['abcdefgh']" > %s''' % filename - os.system(cmd) - f = file(filename) - result = f.read().strip() - assert result == '12345678' - f.close() - os.unlink(filename) - posix = __import__(os.name) - if hasattr(posix, "unsetenv"): - impl.ll_os_unsetenv(impl.to_rstr("abcdefgh")) - cmd = '''python -c "import os; print repr(os.getenv('abcdefgh'))" > %s''' % filename - os.system(cmd) - f = file(filename) - result = f.read().strip() - assert result == 'None' - f.close() - os.unlink(filename) - -test_src = """ -import os -from pypy.tool.udir import udir -#from pypy.rpython.module.ll_os import - -def test_environ(): - count = 0 - while 1: - l - if not impl.ll_os_environ(count): - break - count += 1 - channel.send(count == len(os.environ.keys())) -test_environ() -""" - -def test_environ(): - import py - py.test.skip("Test hangs, should be rewritten to new-style") - gw = py.execnet.PopenGateway() - chan = gw.remote_exec(py.code.Source(test_src)) - res = chan.receive() - assert res - chan.close() - -def test_opendir_readdir(): - dirname = str(udir) - rsdirname = impl.to_rstr(dirname) - result = [] - DIR = impl.ll_os_opendir(rsdirname) - try: - while True: - nextentry = impl.ll_os_readdir(DIR) - if not nextentry: # null pointer check - break - result.append(impl.from_rstr(nextentry)) - finally: - impl.ll_os_closedir(DIR) - assert '.' in result - assert '..' in result - result.remove('.') - result.remove('..') - result.sort() - compared_with = os.listdir(dirname) - compared_with.sort() - assert result == compared_with - def test_os_wstar(): from pypy.rpython.module.ll_os import RegisterOs for name in RegisterOs.w_star: Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Wed Aug 15 15:03:44 2007 @@ -9,7 +9,6 @@ from pypy.rpython.module import ll_stackless, ll_stack from pypy.rpython.module.ll_os import BaseOS as impl from pypy.rpython.lltypesystem.module import ll_strtod -from pypy.rlib import ros try: from pypy.module.thread.rpython import ll_thread @@ -30,12 +29,6 @@ impl.ll_os_chdir.im_func: 'LL_os_chdir', impl.ll_os_mkdir.im_func: 'LL_os_mkdir', impl.ll_os_rmdir.im_func: 'LL_os_rmdir', - impl.ll_os_putenv.im_func: 'LL_os_putenv', - impl.ll_os_unsetenv.im_func:'LL_os_unsetenv', - impl.ll_os_environ.im_func: 'LL_os_environ', - impl.ll_os_opendir.im_func: 'LL_os_opendir', - impl.ll_os_readdir.im_func: 'LL_os_readdir', - impl.ll_os_closedir.im_func:'LL_os_closedir', impl.ll_os_chmod.im_func: 'LL_os_chmod', impl.ll_os_rename.im_func: 'LL_os_rename', impl.ll_os_umask.im_func: 'LL_os_umask', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Wed Aug 15 15:03:44 2007 @@ -4,7 +4,7 @@ from pypy.tool.udir import udir from pypy.translator.c.test.test_genc import compile from pypy.translator.c.extfunc import EXTERNALS -from pypy.rlib import ros +posix = __import__(os.name) def test_all_suggested_primitives(): for modulename in ['ll_os', 'll_os_path', 'll_time']: @@ -629,68 +629,30 @@ else: raise ValueError, 'probing for env var returned %r' % (output,) -def _real_envkeys(): - cmd = '''%s -c "import os; print os.environ.keys()"''' % sys.executable - g = os.popen(cmd, 'r') - output = g.read().strip() - g.close() - if output.startswith('[') and output.endswith(']'): - return eval(output) - else: - raise ValueError, 'probing for all env vars returned %r' % (output,) - -def test_putenv(): - def put(s): - ros.putenv(s) - func = compile(put, [str]) - func('abcdefgh=12345678') - assert _real_getenv('abcdefgh') == '12345678' - -def test_environ(): - def env(idx): - # need to as if the result is NULL, or we crash - ret = ros.environ(idx) - if ret is None: - return False - return ret - func = compile(env, [int]) - keys = [] - while 1: - s = func(len(keys)) - if not s: - break - name, value = s.split('=', 1) - keys.append(name) - expected = _real_envkeys() - keys.sort() - expected.sort() - py.test.skip("XXX fails for me, $OLDPWD doesn't show up in the subprocess") - assert keys == expected - -posix = __import__(os.name) -if hasattr(posix, "unsetenv"): - def test_unsetenv(): - def unsetenv(): - os.unsetenv("ABCDEF") - f = compile(unsetenv, []) - os.putenv("ABCDEF", "a") - assert _real_getenv('ABCDEF') == 'a' - f() - assert _real_getenv('ABCDEF') is None - f() - assert _real_getenv('ABCDEF') is None - - def test_dictlike_environ_getitem(): def fn(s): - res = os.environ[s] - if res is None: - res = '--missing--' + try: + return os.environ[s] + except KeyError: + return '--missing--' + func = compile(fn, [str]) + os.environ.setdefault('USER', 'UNNAMED_USER') + result = func('USER') + assert result == os.environ['USER'] + result = func('PYPY_TEST_DICTLIKE_MISSING') + assert result == '--missing--' + +def test_dictlike_environ_get(): + def fn(s): + res = os.environ.get(s) + if res is None: res = '--missing--' return res func = compile(fn, [str]) os.environ.setdefault('USER', 'UNNAMED_USER') result = func('USER') assert result == os.environ['USER'] + result = func('PYPY_TEST_DICTLIKE_MISSING') + assert result == '--missing--' def test_dictlike_environ_setitem(): def fn(s, t1, t2, t3, t4, t5): @@ -772,33 +734,6 @@ assert ('USER/%s' % (os.environ['USER'],)) in result2 assert 'PYPY_TEST_DICTLIKE_ENVITEMS/783' in result2 - -def test_opendir_readdir(): - py.test.skip("deprecated") - def mylistdir(s): - result = [] - dir = ros.opendir(s) - try: - while True: - nextentry = dir.readdir() - if nextentry is None: - break - result.append(nextentry) - finally: - dir.closedir() - return '\x00'.join(result) - func = compile(mylistdir, [str]) - result = func(str(udir)) - result = result.split('\x00') - assert '.' in result - assert '..' in result - result.remove('.') - result.remove('..') - result.sort() - compared_with = os.listdir(str(udir)) - compared_with.sort() - assert result == compared_with - def test_listdir(): def mylistdir(s): try: Modified: pypy/branch/pypy-more-rtti-inprogress/translator/llvm/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/llvm/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/llvm/test/test_extfunc.py Wed Aug 15 15:03:44 2007 @@ -6,9 +6,9 @@ import py from pypy.tool.udir import udir from pypy.rlib.rarithmetic import r_uint -from pypy.rlib import ros py.test.skip("Extfunc support in llvm needs refactoring") +# XXX in particular, try to share the tests from c/test/test_extfunc! from pypy.translator.llvm.test.runtest import * @@ -320,80 +320,6 @@ # more from translator/c/test/test_extfunc.py Revision: 19054 -def _real_getenv(var): - cmd = '''%s -c "import os; x=os.environ.get('%s'); print (x is None) and 'F' or ('T'+x)"''' % ( - sys.executable, var) - g = os.popen(cmd, 'r') - output = g.read().strip() - g.close() - if output == 'F': - return None - elif output.startswith('T'): - return output[1:] - else: - raise ValueError, 'probing for env var returned %r' % (output,) - -def _real_envkeys(): - cmd = '''%s -c "import os; print os.environ.keys()"''' % sys.executable - g = os.popen(cmd, 'r') - output = g.read().strip() - g.close() - if output.startswith('[') and output.endswith(']'): - return eval(output) - else: - raise ValueError, 'probing for all env vars returned %r' % (output,) - -def test_putenv(): - s = 'abcdefgh=12345678' - def put(): - ros.putenv(s) - return 0 - func = compile_function(put, [], isolate=False) - func() - assert _real_getenv('abcdefgh') == '12345678' - -posix = __import__(os.name) -if hasattr(posix, "unsetenv"): - def test_unsetenv(): - def unsetenv(): - os.unsetenv("ABCDEF") - return 0 - f = compile_function(unsetenv, [], isolate=False) - os.putenv("ABCDEF", "a") - assert _real_getenv('ABCDEF') == 'a' - f() - assert _real_getenv('ABCDEF') is None - f() - assert _real_getenv('ABCDEF') is None - -def test_opendir_readdir(): - s = str(udir) - result = [] - def mylistdir(): - dir = ros.opendir(s) - try: - while True: - nextentry = dir.readdir() - if nextentry is None: - break - result.append(nextentry) - finally: - dir.closedir() - return 0 - func = compile_function(mylistdir, []) - result = func() - py.test.skip("XXX need to check result - somehow") - - result = result.split('\x00') - assert '.' in result - assert '..' in result - result.remove('.') - result.remove('..') - result.sort() - compared_with = os.listdir(str(udir)) - compared_with.sort() - assert result == compared_with - def test_lock(): py.test.skip("XXX does not work with exception transform (why not?)") import thread From arigo at codespeak.net Wed Aug 15 15:35:52 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Aug 2007 15:35:52 +0200 (CEST) Subject: [pypy-svn] r45680 - in pypy/branch/pypy-more-rtti-inprogress: module/posix rpython/module translator/c/test Message-ID: <20070815133552.60F898103@code0.codespeak.net> Author: arigo Date: Wed Aug 15 15:35:51 2007 New Revision: 45680 Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: Missed the KeyError on del os.environ['unknown_name'] Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Wed Aug 15 15:35:51 2007 @@ -264,7 +264,9 @@ def unsetenv(space, name): """Delete an environment variable.""" try: - os.unsetenv(name) + del os.environ[name] + except KeyError: + pass except OSError, e: raise wrap_oserror(space, e) unsetenv.unwrap_spec = [ObjSpace, str] Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py Wed Aug 15 15:35:51 2007 @@ -27,6 +27,8 @@ def delitem(self, obj, key): # in the RPython program, 'del os.environ[key]' is redirected here + if r_getenv(key) is None: + raise KeyError r_unsetenv(key) def get_keys(self, obj): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Wed Aug 15 15:35:51 2007 @@ -678,6 +678,12 @@ del os.environ[s1] del os.environ[s2] del os.environ[s4] + try: + del os.environ[s2] + except KeyError: + pass + else: + raise Exception("should have raised!") # os.environ[s5] stays func = compile(fn, [str, str, str, str, str]) if hasattr(__import__(os.name), 'unsetenv'): From jlg at codespeak.net Wed Aug 15 16:10:29 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Wed, 15 Aug 2007 16:10:29 +0200 (CEST) Subject: [pypy-svn] r45681 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070815141029.6F41F80FA@code0.codespeak.net> Author: jlg Date: Wed Aug 15 16:10:28 2007 New Revision: 45681 Modified: pypy/dist/pypy/lang/scheme/TODO.txt pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: macros handles now zero length match for ellipsis Modified: pypy/dist/pypy/lang/scheme/TODO.txt ============================================================================== --- pypy/dist/pypy/lang/scheme/TODO.txt (original) +++ pypy/dist/pypy/lang/scheme/TODO.txt Wed Aug 15 16:10:28 2007 @@ -25,4 +25,5 @@ - input/output operations - missing datatypes: chars, strings, vectors - switch to byte-code generation + eval instead of evaluating AST +- random code stress test Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Wed Aug 15 16:10:28 2007 @@ -1218,18 +1218,15 @@ return mdict_car if w_expr is w_nil: - #one matched to ellipsis + #one matched to ellipsis, previous (up) w_expr.car if w_pattcar is w_ellipsis: raise EllipsisPattern #zero matched to ellipsis if isinstance(w_pattcdr, W_Pair) and \ w_pattcdr.car is w_ellipsis: - if not isinstance(w_pattcar, W_Symbol): - #XXX this must be added (with tests) - #print w_patt, "matched to ()" - raise NotImplementedError - return {w_pattcar.name: Ellipsis([])} + #all symbols from w_pattcar match zero length Ellipsis + return self.dict_traverse_expr(w_pattcar, Ellipsis([])) if w_patt is w_ellipsis: raise EllipsisPattern @@ -1260,6 +1257,18 @@ # or w_patt is W_Pair but w_expr is not raise MatchError + def dict_traverse_expr(self, expr, val=None): + if isinstance(expr, W_Pair): + dict_car = self.dict_traverse_expr(expr.car, val) + dict_cdr = self.dict_traverse_expr(expr.cdr, val) + dict_car.update(dict_cdr) + return dict_car + + if isinstance(expr, W_Symbol) and not expr is w_ellipsis: + return {expr.name: val} + + return {} + class SymbolClosure(W_Symbol): def __init__(self, ctx, symbol): assert isinstance(symbol, W_Symbol) @@ -1344,6 +1353,8 @@ return {} def plst_append(self, plst, w_cdr=None): + if len(plst) == 0: + return w_cdr first_cons = plst[0] last_cons = None Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Wed Aug 15 16:10:28 2007 @@ -332,6 +332,7 @@ assert eval_(ctx, "(or 12)").to_number() == 12 assert eval_(ctx, "(or 12 42)").to_number() == 12 + assert eval_(ctx, "(or #f 42)").to_number() == 42 assert eval_(ctx, "(or #f #f 82)").to_number() == 82 assert eval_(ctx, "(or #f #f #f 162)").to_number() == 162 @@ -455,6 +456,49 @@ # pattern should be ignored during matching and not be a pattern # variable. But MIT-Scheme disagrees with me... +def test_ellipsis_nil(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax or (syntax-rules () + ((or) #f) + ((or e1 e2 ...) + (let ((temp e1)) + (if temp + temp + (or e2 ...))))))""") + + #here should match zero elements + assert eval_(ctx, "(or 12)").to_number() == 12 + assert eval_(ctx, "(or #f)").to_boolean() is False + assert eval_(ctx, "(or #f 42)").to_number() == 42 + assert eval_(ctx, "(or #f #f 82)").to_number() == 82 + assert eval_(ctx, "(or #f #f #f 162)").to_number() == 162 + +def test_ellipsis_nested_nil(): + ctx = ExecutionContext() + eval_(ctx, """(define-syntax or (syntax-rules () + ((or) #f) + ((or (e1) (e2 ...) ...) + (let ((temp e1)) + (if temp + temp + (or (e2) ... ...))))))""") + + assert eval_(ctx, "(or (12))").to_number() == 12 + assert eval_(ctx, "(or (#f))").to_boolean() is False + assert eval_(ctx, "(or (#f) (42))").to_number() == 42 + assert eval_(ctx, "(or (#f) (#f) (82))").to_number() == 82 + assert eval_(ctx, "(or (#f) (#f) (#f) (162))").to_number() == 162 + + #here scheme48 does not agree with me, it expands to: + # (let ((temp #f)) + # (if temp + # temp + # (or (#f #f 162)))) + # ^ this should be (my and mzscheme opinion) + # (or (#f) (#f) (162)))) + assert eval_(ctx, "(or (#f) (#f #f 162))").to_number() == 162 + assert eval_(ctx, "(or (#f) (#f #f) (#f #f 322))").to_number() == 322 + # some tests from http://sisc-scheme.org/r5rs_pitfall.scm def test_pitfall_3_1(): w_result = eval_noctx("""(let-syntax ((foo (syntax-rules () @@ -490,4 +534,3 @@ def test_pitfall_3_4(): w_result = eval_noctx("(let-syntax ((x (syntax-rules ()))) 1)") assert w_result.to_number() == 1 - From fijal at codespeak.net Wed Aug 15 16:15:02 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 15 Aug 2007 16:15:02 +0200 (CEST) Subject: [pypy-svn] r45682 - pypy/branch/pypy-more-rtti-inprogress/rpython/tool Message-ID: <20070815141502.2F39B813B@code0.codespeak.net> Author: fijal Date: Wed Aug 15 16:15:01 2007 New Revision: 45682 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/genrffi.py (props changed) pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py (props changed) Log: Those files are not executable From arigo at codespeak.net Wed Aug 15 16:29:21 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Aug 2007 16:29:21 +0200 (CEST) Subject: [pypy-svn] r45683 - pypy/branch/pypy-more-rtti-inprogress/translator/c/src Message-ID: <20070815142921.2289A8126@code0.codespeak.net> Author: arigo Date: Wed Aug 15 16:29:20 2007 New Revision: 45683 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: Kill dead code. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Wed Aug 15 16:29:20 2007 @@ -57,12 +57,6 @@ long LL_os_spawnv(int mode, RPyString *path, RPyListOfString *args); #endif void LL_os__exit(long status); -void LL_os_putenv(RPyString * name_eq_value); -void LL_os_unsetenv(RPyString * name); -RPyString* LL_os_environ(int idx); -struct RPyOpaque_DIR *LL_os_opendir(RPyString *dirname); -RPyString *LL_os_readdir(struct RPyOpaque_DIR *dir); -void LL_os_closedir(struct RPyOpaque_DIR *dir); static int geterrno(void) { @@ -246,154 +240,4 @@ _exit((int)status); } -#ifdef HAVE_PUTENV -/* Note that this doesn't map to os.putenv, it is the name=value - * version of C. See ros.py for the fake implementation. - * Also note that we are responsible to keep the - * value alive. This is done in interp_posix.py - */ -void LL_os_putenv(RPyString * name_eq_value) { - int error = putenv(RPyString_AsString(name_eq_value)); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} -#endif - -#ifdef HAVE_UNSETENV -void LL_os_unsetenv(RPyString * name) { - unsetenv(RPyString_AsString(name)); -} -#endif - -/* Return a dictionary corresponding to the POSIX environment table */ -/*** actually, we create a string list here and do the rest in posix */ - -RPyString* LL_os_environ(int idx) { - RPyString *rs = NULL; - char *s; -#ifdef WITH_NEXT_FRAMEWORK - if (environ == NULL) - environ = *_NSGetEnviron(); -#endif - if (environ != NULL && (s = environ[idx]) != NULL) { - rs = RPyString_FromString(s); - } - return rs; -} - -/******************** opendir/readdir/closedir ********************/ -/* XXX old interface no longer used in PyPy, will be removed at some point */ -#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) - -/* emulation of opendir, readdir, closedir */ - -/* - the problem is that Windows does not have something like - opendir. Instead, FindFirstFile creates a handle and - yields the first entry found. Furthermore, we need - to mangle the filename. - To keep the rpython interface, we need to buffer the - first result and let readdir return this first time. - Drawback of this approach: we need to use malloc, - and the way I'm emulating dirent is maybe somewhat hackish. - - XXX we are lacking unicode support, completely. - Might need a different interface. - */ - -#undef dirent - -typedef struct dirent { - HANDLE hFind; - WIN32_FIND_DATA FileData; - char *d_name; /* faking dirent */ - char arg[1]; /*also used as flag */ -} DIR; - -/* XXX old interface no longer used in PyPy, will be removed at some point */ -static DIR *opendir(char *dirname) -{ - int lng = strlen(dirname); - DIR *d = malloc(sizeof(DIR) + lng + 4); - - if (d != NULL) { - char *ptr = (char*)d->arg; - strcpy(ptr, dirname); - strcpy(ptr + lng, "\\*.*" + (*(ptr + lng - 1) == '\\')); - d->hFind = FindFirstFile(ptr, &d->FileData); - d->d_name = d->FileData.cFileName; - if (d->hFind == INVALID_HANDLE_VALUE) { - d->d_name = NULL; - if (GetLastError() != ERROR_FILE_NOT_FOUND) { - errno = GetLastError(); - free(d); - d = NULL; - } - } - } - return d; -} - -/* XXX old interface no longer used in PyPy, will be removed at some point */ -static struct dirent *readdir(DIR *d) -{ - if (d->arg[0]) - d->arg[0] = 0; /* use existing result first time */ - else { - if (FindNextFile(d->hFind, &d->FileData)) - d->d_name = d->FileData.cFileName; - else { - d->d_name = NULL; - if (GetLastError() != ERROR_NO_MORE_FILES) - errno = GetLastError(); - } - } - return d->d_name ? d : NULL; -} - -/* XXX old interface no longer used in PyPy, will be removed at some point */ -static int closedir(DIR *d) -{ - HANDLE hFind = d->hFind; - - free(d); - if (FindClose(hFind) == 0) { - errno = GetLastError(); - return -1; - } - return 0; -} - -#endif /* defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) */ - -/* XXX old interface no longer used in PyPy, will be removed at some point */ -struct RPyOpaque_DIR *LL_os_opendir(RPyString *dirname) -{ - DIR *dir = opendir(RPyString_AsString(dirname)); - if (dir == NULL) - RPYTHON_RAISE_OSERROR(errno); - return (struct RPyOpaque_DIR *) dir; -} - -/* XXX old interface no longer used in PyPy, will be removed at some point */ -RPyString *LL_os_readdir(struct RPyOpaque_DIR *dir) -{ - struct dirent *d; - errno = 0; - d = readdir((DIR *) dir); - if (d != NULL) - return RPyString_FromString(d->d_name); - if (errno) - RPYTHON_RAISE_OSERROR(errno); - return NULL; -} - -/* XXX old interface no longer used in PyPy, will be removed at some point */ -void LL_os_closedir(struct RPyOpaque_DIR *dir) -{ - if (closedir((DIR *) dir) < 0) - RPYTHON_RAISE_OSERROR(errno); -} - #endif /* PYPY_NOT_MAIN_FILE */ From fijal at codespeak.net Wed Aug 15 16:44:28 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 15 Aug 2007 16:44:28 +0200 (CEST) Subject: [pypy-svn] r45684 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070815144428.AB70A8121@code0.codespeak.net> Author: fijal Date: Wed Aug 15 16:44:27 2007 New Revision: 45684 Removed: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/genrffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_genrffi.py Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py Log: Cleanup of the tool. We don't need two slightly different sources by now, just one should be fine Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py Wed Aug 15 16:44:27 2007 @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import ctypes import py @@ -21,8 +19,6 @@ ctypes.c_uint : 'rffi.UINT', ctypes.c_int32 : 'rffi.INT', ctypes.c_uint32 : 'rffi.UINT', - #ctypes.c_long : 'rffi.LONG', # same as c_int.. - #ctypes.c_ulong : 'rffi.ULONG', ctypes.c_longlong : 'rffi.LONGLONG', ctypes.c_ulonglong : 'rffi.ULONGLONG', ctypes.c_int64 : 'rffi.LONGLONG', @@ -114,7 +110,12 @@ print "skipped:", value #print value, value.__class__.__name__ - - - - + def compiled(self): + # not caching! + globs = {} + src = py.code.Source(""" + from pypy.rpython.lltypesystem import lltype + from pypy.rpython.lltypesystem import rffi + """, self.source) + exec src.compile() in globs + return globs Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py Wed Aug 15 16:44:27 2007 @@ -19,6 +19,7 @@ rffi_source = RffiSource() assert rffi_source.proc_tp(ctypes.c_int) == 'rffi.INT' assert rffi_source.proc_tp(ctypes.c_void_p) == 'rffi.VOIDP' + assert rffi_source.compiled() def test_proc_tp_complicated(): rffi_source = RffiSource() @@ -30,6 +31,7 @@ """) src = rffi_source.source assert src.strip() == _src.strip(), str(src) + "\n" + str(_src) + assert rffi_source.compiled() class TestMkrffi(TestBasic): def test_single_func(self): @@ -44,6 +46,7 @@ """) assert src.source == _src, str(src) + "\n" + str(_src) + assert src.compiled() def test_struct_return(self): func = self.lib.int_int_to_struct_p @@ -59,3 +62,4 @@ """) src = rffi_source.source assert src.strip() == _src.strip(), str(src) + "\n" + str(_src) + assert rffi_source.compiled() From fijal at codespeak.net Wed Aug 15 16:48:52 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 15 Aug 2007 16:48:52 +0200 (CEST) Subject: [pypy-svn] r45685 - in pypy/branch/pypy-more-rtti-inprogress/rpython: lltypesystem lltypesystem/test tool tool/test Message-ID: <20070815144852.5A4DA8126@code0.codespeak.net> Author: fijal Date: Wed Aug 15 16:48:52 2007 New Revision: 45685 Added: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/ctypes_platform.py - copied unchanged from r45676, pypy/branch/pypy-more-rtti-inprogress/rpython/rctypes/tool/ctypes_platform.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py - copied unchanged from r45676, pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rfficache.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rfficache.py - copied, changed from r45676, pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rfficache.py Removed: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rfficache.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rfficache.py Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: A bit of shuffling around to keep rfficache in rpython/tool Fixed imports Copied ctypes_platform as intermediate checkin for a merge attempt Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Wed Aug 15 16:48:52 2007 @@ -36,7 +36,7 @@ ll2ctypes.make_callable_via_ctypes(funcptr) return funcptr -from pypy.rpython.lltypesystem.rfficache import platform +from pypy.rpython.tool.rfficache import platform TYPES = [] for _name in 'short int long'.split(): From fijal at codespeak.net Wed Aug 15 17:00:09 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 15 Aug 2007 17:00:09 +0200 (CEST) Subject: [pypy-svn] r45686 - pypy/branch/pypy-more-rtti-inprogress/rpython/tool Message-ID: <20070815150009.9D5BF812E@code0.codespeak.net> Author: fijal Date: Wed Aug 15 17:00:08 2007 New Revision: 45686 Added: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py - copied unchanged from r45685, pypy/branch/pypy-more-rtti-inprogress/rpython/tool/ctypes_platform.py Removed: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/ctypes_platform.py Log: Rename in a separate commit, to avoid confusion From arigo at codespeak.net Thu Aug 16 09:15:32 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 09:15:32 +0200 (CEST) Subject: [pypy-svn] r45697 - in pypy/branch/pypy-more-rtti-inprogress: module/posix module/posix/test rpython/module translator/c/test Message-ID: <20070816071532.20C5D8105@code0.codespeak.net> Author: arigo Date: Thu Aug 16 09:15:31 2007 New Revision: 45697 Added: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py (contents, props changed) Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py pypy/branch/pypy-more-rtti-inprogress/module/posix/app_posix.py pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: A more complete support for os.stat(). The RPython one now returns a Controlled object that supports both tuple-like indexing and the st_xxx attributes. The extra attributes are then exposed at app-level. Note that support for sub-second timestamps is there, but possibly a bit fragile. I disabled it because in CPython 2.4 by default we don't get sub-second timestamps out of os.stat() either. Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py Thu Aug 16 09:15:31 2007 @@ -50,6 +50,7 @@ #'getuid' : 'interp_posix.getuid', #'geteuid' : 'interp_posix.geteuid', 'utime' : 'interp_posix.utime', + '_statfields': 'interp_posix.getstatfields(space)', } if hasattr(os, 'ftruncate'): interpleveldefs['ftruncate'] = 'interp_posix.ftruncate' Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/app_posix.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/app_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/app_posix.py Thu Aug 16 09:15:31 2007 @@ -2,6 +2,15 @@ from _structseq import structseqtype, structseqfield +# XXX we need a way to access the current module's globals more directly... +import sys +if 'posix' in sys.builtin_module_names: + import posix +elif 'nt' in sys.builtin_module_names: + import nt as posix +else: + raise ImportError("XXX") + error = OSError @@ -15,10 +24,28 @@ st_uid = structseqfield(4, "user ID of owner") st_gid = structseqfield(5, "group ID of owner") st_size = structseqfield(6, "total size, in bytes") - st_atime = structseqfield(7, "time of last access (XXX as an int)") - st_mtime = structseqfield(8, "time of last modification (XXX as an int)") - st_ctime = structseqfield(9, "time of last change (XXX as an int)") - # XXX no extra fields for now + + # NOTE: float times are disabled for now, for compatibility with CPython. + + # access to indices 7 to 9 gives the timestamps as integers: + #_integer_atime = structseqfield(7) + #_integer_mtime = structseqfield(8) + #_integer_ctime = structseqfield(9) + + st_atime = structseqfield(7, "time of last access") + st_mtime = structseqfield(8, "time of last modification") + st_ctime = structseqfield(9, "time of last status change") + + # further fields, not accessible by index (the numbers are still needed + # but not visible because they are no longer consecutive) + if "st_blksize" in posix._statfields: + st_blksize = structseqfield(20, "blocksize for filesystem I/O") + if "st_blocks" in posix._statfields: + st_blocks = structseqfield(21, "number of blocks allocated") + if "st_rdev" in posix._statfields: + st_rdev = structseqfield(22, "device ID (if special file)") + if "st_flags" in posix._statfields: + st_flags = structseqfield(23, "user defined flags for file") def fdopen(fd, mode='r', buffering=-1): Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Thu Aug 16 09:15:31 2007 @@ -1,7 +1,9 @@ from pypy.interpreter.baseobjspace import ObjSpace, W_Root -from pypy.rlib.rarithmetic import intmask +from pypy.rlib.unroll import unrolling_iterable from pypy.interpreter.error import OperationError, wrap_oserror from pypy.rpython.module.ll_os import RegisterOs +from pypy.rpython.module import ll_os_stat +from pypy.rpython.lltypesystem import lltype import os @@ -75,14 +77,33 @@ raise wrap_oserror(space, e) ftruncate.unwrap_spec = [ObjSpace, int, int] +# ____________________________________________________________ + +STAT_FIELDS = unrolling_iterable(enumerate(ll_os_stat.STAT_FIELDS)) + def build_stat_result(space, st): - # cannot index tuples with a variable... - lst = [st[0], st[1], st[2], st[3], st[4], - st[5], st[6], st[7], st[8], st[9]] - w_tuple = space.newtuple([space.wrap(intmask(x)) for x in lst]) + lst = [] + w_keywords = space.newdict() + for i, (name, TYPE) in STAT_FIELDS: + value = getattr(st, name) + #if name in ('st_atime', 'st_mtime', 'st_ctime'): + # value = int(value) # rounded to an integer for indexed access + w_value = space.wrap(value) + if i < ll_os_stat.N_INDEXABLE_FIELDS: + lst.append(w_value) + else: + space.setitem(w_keywords, space.wrap(name), w_value) + + # NOTE: float times are disabled for now, for compatibility with CPython + # non-rounded values for name-based access + #space.setitem(w_keywords, space.wrap('st_atime'), space.wrap(st.st_atime)) + #space.setitem(w_keywords, space.wrap('st_mtime'), space.wrap(st.st_mtime)) + #space.setitem(w_keywords, space.wrap('st_ctime'), space.wrap(st.st_ctime)) + + w_tuple = space.newtuple(lst) w_stat_result = space.getattr(space.getbuiltinmodule(os.name), space.wrap('stat_result')) - return space.call_function(w_stat_result, w_tuple) + return space.call_function(w_stat_result, w_tuple, w_keywords) def fstat(space, fd): """Perform a stat system call on the file referenced to by an open @@ -235,10 +256,14 @@ return space.wrap(text) strerror.unwrap_spec = [ObjSpace, int] +# ____________________________________________________________ + +def getstatfields(space): + # for app_posix.py: export the list of 'st_xxx' names that we know + # about at RPython level + return space.newlist( + [space.wrap(name) for name in ll_os_stat.STAT_FIELD_NAMES]) -# this is a particular case, because we need to supply -# the storage for the environment variables, at least -# for some OSes. class State: def __init__(self, space): Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py Thu Aug 16 09:15:31 2007 @@ -41,11 +41,39 @@ posix.lseek(fd, 5, 0) s = posix.read(fd, 1) assert s == 'i' - stat = posix.fstat(fd) - assert stat # XXX + st = posix.fstat(fd) posix.close(fd2) posix.close(fd) + import sys, stat + assert st[0] == st.st_mode + assert st[1] == st.st_ino + assert st[2] == st.st_dev + assert st[3] == st.st_nlink + assert st[4] == st.st_uid + assert st[5] == st.st_gid + assert st[6] == st.st_size + assert st[7] == int(st.st_atime) + assert st[8] == int(st.st_mtime) + assert st[9] == int(st.st_ctime) + + assert stat.S_IMODE(st.st_mode) & stat.S_IRUSR + assert stat.S_IMODE(st.st_mode) & stat.S_IWUSR + if not sys.platform.startswith('win'): + assert not (stat.S_IMODE(st.st_mode) & stat.S_IXUSR) + + assert st.st_size == 14 + assert st.st_nlink == 1 + + #if sys.platform.startswith('linux2'): + # # expects non-integer timestamps - it's unlikely that they are + # # all three integers + # assert ((st.st_atime, st.st_mtime, st.st_ctime) != + # (st[7], st[8], st[9])) + # assert st.st_blksize * st.st_blocks >= st.st_size + if sys.platform.startswith('linux2'): + assert hasattr(st, 'st_rdev') + def test_pickle(self): import pickle, os st = self.posix.stat(os.curdir) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 09:15:31 2007 @@ -11,7 +11,6 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.rarithmetic import r_longlong from pypy.tool.staticmethods import ClassMethods -import stat from pypy.rpython.extfunc import BaseLazyRegistering, registering from pypy.annotation.model import SomeInteger, SomeString, SomeTuple, SomeFloat from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool @@ -543,82 +542,20 @@ # --------------------------- os.stat & variants --------------------------- - def register_stat_variant(self, name): - if sys.platform.startswith('win'): - struct_stat = '_stati64' - functions = {'stat': '_stati64', - 'fstat': '_fstati64', - 'lstat': '_stati64'} # no lstat on Windows - c_func_name = functions[name] - INCLUDES = [] - else: - struct_stat = 'stat' - c_func_name = name - INCLUDES = self.UNISTD_INCL + ['sys/stat.h'] - # XXX all fields are lltype.Signed for now, which is wrong - STRUCT_STAT = rffi.CStruct(struct_stat, - ('st_mode', lltype.Signed), - ('st_ino', lltype.Signed), - ('st_dev', lltype.Signed), - ('st_nlink', lltype.Signed), - ('st_uid', lltype.Signed), - ('st_gid', lltype.Signed), - ('st_size', lltype.Signed), - ('st_atime', lltype.Signed), - ('st_mtime', lltype.Signed), - ('st_ctime', lltype.Signed), - ) - arg_is_path = (name != 'fstat') - if arg_is_path: - ARG1 = rffi.CCHARP - else: - ARG1 = rffi.INT - os_mystat = rffi.llexternal(name, [ARG1, STRUCT_STAT], rffi.INT, - includes=INCLUDES) - - def os_mystat_lltypeimpl(arg): - stresult = lltype.malloc(STRUCT_STAT.TO, flavor='raw') - try: - if arg_is_path: - arg = rffi.str2charp(arg) - error = os_mystat(arg, stresult) - if arg_is_path: - rffi.free_charp(arg) - if error != 0: - raise OSError(rffi.get_errno(), "os_stat failed") - return (stresult.c_st_mode, - stresult.c_st_ino, - stresult.c_st_dev, - stresult.c_st_nlink, - stresult.c_st_uid, - stresult.c_st_gid, - stresult.c_st_size, - stresult.c_st_atime, - stresult.c_st_mtime, - stresult.c_st_ctime) - finally: - lltype.free(stresult, flavor='raw') - - if arg_is_path: - s_arg = str - else: - s_arg = int - self.register(getattr(os, name), [s_arg], (int,) * 10, - "ll_os.ll_os_%s" % (name,), - llimpl=func_with_new_name(os_mystat_lltypeimpl, - 'os_%s_lltypeimpl' % (name,))) - @registering(os.fstat) def register_os_fstat(self): - self.register_stat_variant('fstat') + from pypy.rpython.module import ll_os_stat + ll_os_stat.register_stat_variant('fstat') @registering(os.stat) def register_os_stat(self): - self.register_stat_variant('stat') + from pypy.rpython.module import ll_os_stat + ll_os_stat.register_stat_variant('stat') @registering(os.lstat) def register_os_lstat(self): - self.register_stat_variant('lstat') + from pypy.rpython.module import ll_os_stat + ll_os_stat.register_stat_variant('lstat') # ------------------------------- os.W* --------------------------------- Added: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py Thu Aug 16 09:15:31 2007 @@ -0,0 +1,192 @@ +"""Annotation and rtyping support for the result of os.stat(), os.lstat() +and os.fstat(). In RPython like in plain Python the stat result can be +indexed like a tuple but also exposes the st_xxx attributes. +""" +import os, sys +from pypy.annotation import model as annmodel +from pypy.tool.sourcetools import func_with_new_name +from pypy.rpython.controllerentry import Controller, SomeControlledInstance +from pypy.rpython.extfunc import _register_external +from pypy.rpython.lltypesystem import rffi, lltype + +if sys.platform.startswith('win'): + # XXX on Windows, stat() is flawed; see CPython's posixmodule.c for + # an implementation based on the Win32 API + LongLongIfNotWindows = lltype.Signed +else: + LongLongIfNotWindows = lltype.SignedLongLong + +# NOTE: float times are disabled for now, for compatibility with CPython +if 0: #sys.platform.startswith('linux2'): + # XXX assume the tv_nsec way of accessing the sub-second timestamps + # XXX also assume, as in Linux, that it's in a 'struct timespec' + TIMESPEC = rffi.CStruct('timespec', + ('tv_sec', lltype.Signed), + ('tv_nsec', lltype.Signed)) + ModTime = rffi.DOUBLE +else: + # XXX add support for more platforms + TIMESPEC = None + ModTime = lltype.Signed + +# all possible fields - some of them are not available on all platforms +ALL_STAT_FIELDS = [ + ("st_mode", lltype.Signed), + ("st_ino", lltype.SignedLongLong), + ("st_dev", LongLongIfNotWindows), + ("st_nlink", lltype.Signed), + ("st_uid", lltype.Signed), + ("st_gid", lltype.Signed), + ("st_size", lltype.SignedLongLong), + ("st_atime", ModTime), + ("st_mtime", ModTime), + ("st_ctime", ModTime), + ("st_blksize", lltype.Signed), + ("st_blocks", lltype.Signed), + ("st_rdev", lltype.Signed), + ("st_flags", lltype.Signed), + #("st_gen", lltype.Signed), -- new in CPy 2.5, not implemented + #("st_birthtime", ModTime), -- new in CPy 2.5, not implemented + ] +N_INDEXABLE_FIELDS = 10 + +# for now, check the host Python to know which st_xxx fields exist +STAT_FIELDS = [(_name, _TYPE) for (_name, _TYPE) in ALL_STAT_FIELDS + if hasattr(os.stat_result, _name)] + +STAT_FIELD_TYPES = dict(STAT_FIELDS) # {'st_xxx': TYPE} + +STAT_FIELD_NAMES = [_name for (_name, _TYPE) in ALL_STAT_FIELDS + if _name in STAT_FIELD_TYPES] + +def _expand(lst, originalname, timespecname): + if TIMESPEC is not None: + for i, (_name, _TYPE) in enumerate(lst): + if _name == originalname: + # replace the 'st_atime' field of type rffi.DOUBLE + # with a field 'st_atim' of type 'struct timespec' + lst[i] = (timespecname, TIMESPEC.TO) + break + +LL_STAT_FIELDS = STAT_FIELDS[:] +_expand(LL_STAT_FIELDS, 'st_atime', 'st_atim') +_expand(LL_STAT_FIELDS, 'st_mtime', 'st_mtim') +_expand(LL_STAT_FIELDS, 'st_ctime', 'st_ctim') + +del _expand, _name, _TYPE + +# ____________________________________________________________ +# +# Annotation support + +class StatResultController(Controller): + """Controls a stat_result object in RPython: internally it is just a + tuple, but the Controller adds the support for the st_xxx attributes. + """ + knowntype = os.stat_result + + def getitem(self, obj, index): + if 0 <= index < N_INDEXABLE_FIELDS: + return obj[index] + else: + raise IndexError + getitem._annspecialcase_ = 'specialize:arg(2)' # 'index' must be constant + + def install_getter(cls, name): + # def get_st_mode(), def get_st_ino(), etc... + index = STAT_FIELD_NAMES.index(name) + def get_st_xxx(self, obj): + return obj[index] + method_name = 'get_%s' % (name,) + setattr(cls, method_name, func_with_new_name(get_st_xxx, method_name)) + install_getter = classmethod(install_getter) + +for _name in STAT_FIELD_NAMES: + StatResultController.install_getter(_name) + +stat_controller = StatResultController() +s_tuple_StatResult = annmodel.SomeTuple([annmodel.lltype_to_annotation(_TYPE) + for _name, _TYPE in STAT_FIELDS]) +s_StatResult = SomeControlledInstance(s_tuple_StatResult, + controller = stat_controller) + +# ____________________________________________________________ +# +# RFFI support + +if sys.platform.startswith('win'): + _name_struct_stat = '_stati64' + INCLUDES = [] +else: + _name_struct_stat = 'stat' + INCLUDES = ['sys/types.h', 'sys/stat.h', 'unistd.h'] +STRUCT_STAT = rffi.CStruct(_name_struct_stat, *LL_STAT_FIELDS) + + +def build_stat_result(st): + if TIMESPEC is not None: + atim = st.c_st_atim; atime = atim.c_tv_sec + 1E-9 * atim.c_tv_nsec + mtim = st.c_st_mtim; mtime = mtim.c_tv_sec + 1E-9 * mtim.c_tv_nsec + ctim = st.c_st_ctim; ctime = ctim.c_tv_sec + 1E-9 * ctim.c_tv_nsec + else: + atime = st.c_st_atime + mtime = st.c_st_mtime + ctime = st.c_st_ctime + + result = (st.c_st_mode, + st.c_st_ino, + st.c_st_dev, + st.c_st_nlink, + st.c_st_uid, + st.c_st_gid, + st.c_st_size, + atime, + mtime, + ctime) + + if "st_blksize" in STAT_FIELD_TYPES: result += (st.c_st_blksize,) + if "st_blocks" in STAT_FIELD_TYPES: result += (st.c_st_blocks,) + if "st_rdev" in STAT_FIELD_TYPES: result += (st.c_st_rdev,) + if "st_flags" in STAT_FIELD_TYPES: result += (st.c_st_flags,) + + return stat_controller.box(result) + + +def register_stat_variant(name): + if sys.platform.startswith('win'): + _functions = {'stat': '_stati64', + 'fstat': '_fstati64', + 'lstat': '_stati64'} # no lstat on Windows + c_func_name = _functions[name] + else: + c_func_name = name + arg_is_path = (name != 'fstat') + if arg_is_path: + ARG1 = rffi.CCHARP + else: + ARG1 = rffi.INT + os_mystat = rffi.llexternal(name, [ARG1, STRUCT_STAT], rffi.INT, + includes=INCLUDES) + + def os_mystat_lltypeimpl(arg): + stresult = lltype.malloc(STRUCT_STAT.TO, flavor='raw') + try: + if arg_is_path: + arg = rffi.str2charp(arg) + error = os_mystat(arg, stresult) + if arg_is_path: + rffi.free_charp(arg) + if error != 0: + raise OSError(rffi.get_errno(), "os_?stat failed") + return build_stat_result(stresult) + finally: + lltype.free(stresult, flavor='raw') + + if arg_is_path: + s_arg = str + else: + s_arg = int + _register_external(getattr(os, name), [s_arg], s_StatResult, + "ll_os.ll_os_%s" % (name,), + llimpl=func_with_new_name(os_mystat_lltypeimpl, + 'os_%s_lltypeimpl' % (name,))) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Thu Aug 16 09:15:31 2007 @@ -132,14 +132,27 @@ def test_os_stat(): filename = str(py.magic.autopath()) + has_blksize = hasattr(os.stat_result, 'st_blksize') + has_blocks = hasattr(os.stat_result, 'st_blocks') def call_stat(): st = os.stat(filename) - return st + res = (st[0], st.st_ino, st.st_ctime) + if has_blksize: res += (st.st_blksize,) + if has_blocks: res += (st.st_blocks,) + return res f = compile(call_stat, []) - result = f() - assert result[0] == os.stat(filename)[0] - assert result[1] == os.stat(filename)[1] - assert result[2] == os.stat(filename)[2] + res = f() + assert res[0] == os.stat(filename).st_mode + assert res[1] == os.stat(filename).st_ino + st_ctime = res[2] + if isinstance(st_ctime, float): + assert st_ctime == os.stat(filename).st_ctime + else: + assert st_ctime == int(os.stat(filename).st_ctime) + if has_blksize: + assert res[3] == os.stat(filename).st_blksize + if has_blocks: + assert res[4] == os.stat(filename).st_blocks def test_os_fstat(): if os.environ.get('PYPY_CC', '').startswith('tcc'): @@ -148,18 +161,17 @@ fd = os.open(filename, os.O_RDONLY, 0777) def call_fstat(fd): st = os.fstat(fd) - return st + return (st.st_mode, st[1], st.st_mtime) f = compile(call_fstat, [int]) osstat = os.stat(filename) - result = f(fd) + st_mode, st_ino, st_mtime = f(fd) os.close(fd) - import stat - for i in range(len(result)): - if i == stat.ST_DEV: - continue # does give 3 instead of 0 for windows - elif i == stat.ST_ATIME: - continue # access time will vary - assert (i, result[i]) == (i, osstat[i]) + assert st_mode == osstat.st_mode + assert st_ino == osstat.st_ino + if isinstance(st_mtime, float): + assert st_mtime == osstat.st_mtime + else: + assert st_mtime == int(osstat.st_mtime) def test_os_isatty(): def call_isatty(fd): From arigo at codespeak.net Thu Aug 16 10:52:02 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 10:52:02 +0200 (CEST) Subject: [pypy-svn] r45699 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070816085202.9EFC080E6@code0.codespeak.net> Author: arigo Date: Thu Aug 16 10:52:01 2007 New Revision: 45699 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rfficache.py Log: The same cache is used for various purposes, which can occasionally collide. Make the key more precise. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py Thu Aug 16 10:52:01 2007 @@ -62,10 +62,10 @@ def create_cache_access_method(acc_func, meth_name): def method(self, name, **kwds): try: - return self.cache[name] + return self.cache[meth_name, name] except KeyError: res = acc_func(name, **kwds) - self.cache[name] = res + self.cache[meth_name, name] = res self._store_cache() return res method.func_name = meth_name @@ -91,7 +91,7 @@ def _build_types(self): for name, (c_name, signed) in self.type_names.items(): - bits = self.cache[c_name] + bits = self.cache['bits', c_name] inttype = rarithmetic.build_int('r_' + name, signed, bits) tp = lltype.build_number(name, inttype) self.numbertype_to_rclass[tp] = inttype @@ -104,7 +104,7 @@ except KeyError: bits = sizeof_c_type(c_name, **kwds) * 8 inttype = rarithmetic.build_int('r_' + name, signed, bits) - self.cache[c_name] = bits + self.cache['bits', c_name] = bits self.type_names[name] = (c_name, signed) tp = lltype.build_number(name, inttype) self.numbertype_to_rclass[tp] = inttype Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rfficache.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rfficache.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rfficache.py Thu Aug 16 10:52:01 2007 @@ -28,6 +28,8 @@ assert cache.defined('STUFF') assert cache.inttype('uchar', 'unsigned char', False, compiler_exe='xxx')._type.BITS == 8 assert cache.sizeof('short', compiler_exe='xxx') == 2 + assert cache.intdefined('STUFFZ', add_source='#define STUFFZ 0') == 0 + assert cache.defined('STUFFZ', add_source='#define STUFFZ 0') def test_types_present(): for name in rffi.TYPES: From arigo at codespeak.net Thu Aug 16 11:40:31 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 11:40:31 +0200 (CEST) Subject: [pypy-svn] r45700 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816094031.E38238149@code0.codespeak.net> Author: arigo Date: Thu Aug 16 11:40:30 2007 New Revision: 45700 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.lseek -> rffi Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 11:40:30 2007 @@ -150,7 +150,6 @@ # external function declarations posix = __import__(os.name) -declare(os.lseek , r_longlong , 'll_os/lseek') declare(os.isatty , bool , 'll_os/isatty') if hasattr(posix, 'ftruncate'): declare(os.ftruncate, noneannotation, 'll_os/ftruncate') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 11:40:30 2007 @@ -323,6 +323,55 @@ self.register(os.close, [int], s_None, llimpl=close_lltypeimpl, export_name="ll_os.ll_os_close", oofakeimpl=os.close) + @registering(os.lseek) + def register_os_lseek(self): + if sys.platform.startswith('win'): + funcname = '_lseeki64' + INCLUDES = [] + else: + funcname = 'lseek' + INCLUDES = self.UNISTD_INCL + if platform.defined('SEEK_SET', includes=INCLUDES): + SEEK_SET = platform.intdefined('SEEK_SET', includes=INCLUDES) + SEEK_CUR = platform.intdefined('SEEK_CUR', includes=INCLUDES) + SEEK_END = platform.intdefined('SEEK_END', includes=INCLUDES) + else: + SEEK_SET, SEEK_CUR, SEEK_END = 0, 1, 2 + if (SEEK_SET, SEEK_CUR, SEEK_END) != (0, 1, 2): + # Turn 0, 1, 2 into SEEK_{SET,CUR,END} + def fix_seek_arg(n): + if n == 0: return SEEK_SET + if n == 1: return SEEK_CUR + if n == 2: return SEEK_END + return n + else: + def fix_seek_arg(n): + return n + + os_lseek = rffi.llexternal(funcname, + [rffi.INT, rffi.LONGLONG, rffi.INT], + rffi.LONGLONG) + + def lseek_lltypeimpl(fd, pos, how): + how = fix_seek_arg(how) + res = os_lseek(rffi.cast(rffi.INT, fd), + rffi.cast(rffi.LONGLONG, pos), + rffi.cast(rffi.INT, how)) + res = rffi.cast(lltype.SignedLongLong, res) + if res < 0: + raise OSError(rffi.get_errno(), "os_lseek failed") + return res + + def os_lseek_oofakeimpl(fd, pos, how): + res = os.lseek(fd, pos, how) + return r_longlong(res) + + self.register(os.lseek, [int, r_longlong, int], + r_longlong, + llimpl = lseek_lltypeimpl, + export_name = "ll_os.ll_os_lseek", + oofakeimpl = os_lseek_oofakeimpl) + @registering(os.access) def register_os_access(self): os_access = rffi.llexternal('access', @@ -629,10 +678,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_lseek(cls, fd,pos,how): - return r_longlong(os.lseek(fd,pos,how)) - ll_os_lseek.suggested_primitive = True - def ll_os_isatty(cls, fd): return os.isatty(fd) ll_os_isatty.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 11:40:30 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_lseek.im_func: 'LL_os_lseek', impl.ll_os_isatty.im_func: 'LL_os_isatty', impl.ll_os_ftruncate.im_func:'LL_os_ftruncate', impl.ll_os_strerror.im_func: 'LL_os_strerror', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 11:40:30 2007 @@ -38,7 +38,6 @@ /* prototypes */ -long LL_os_lseek(long fd, long pos, long how); int LL_os_isatty(long fd); RPyString *LL_os_strerror(int errnum); long LL_os_system(RPyString * fname); @@ -70,30 +69,6 @@ #include "ll_osdefs.h" -long LL_os_lseek(long fd, long pos, long how) { -#if defined(MS_WIN64) || defined(MS_WINDOWS) - PY_LONG_LONG res; -#else - off_t res; -#endif -#ifdef SEEK_SET - /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ - switch (how) { - case 0: how = SEEK_SET; break; - case 1: how = SEEK_CUR; break; - case 2: how = SEEK_END; break; - } -#endif /* SEEK_END */ -#if defined(MS_WIN64) || defined(MS_WINDOWS) - res = _lseeki64(fd, pos, how); -#else - res = lseek(fd, pos, how); -#endif - if (res < 0) - RPYTHON_RAISE_OSERROR(errno); - return res; -} - int LL_os_isatty(long fd) { return isatty((int)fd); } From fijal at codespeak.net Thu Aug 16 12:52:35 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 12:52:35 +0200 (CEST) Subject: [pypy-svn] r45704 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070816105235.E99ED815C@code0.codespeak.net> Author: fijal Date: Thu Aug 16 12:52:35 2007 New Revision: 45704 Added: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py - copied, changed from r45676, pypy/branch/pypy-more-rtti-inprogress/rpython/rctypes/tool/test/test_ctypes_platform.py Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Log: First test passes. Most of functions in rffi_platform.py are disabled by now and will be re-enabled as we'll have more tests passing. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Thu Aug 16 12:52:35 2007 @@ -1,7 +1,9 @@ #! /usr/bin/env python import os, py, sys -import ctypes +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import llmemory from pypy.translator.tool.cbuild import build_executable from pypy.tool.udir import udir @@ -15,7 +17,7 @@ STRUCT = Struct(name, interesting_fields) return configure(CConfig)['STRUCT'] -def getsimpletype(name, c_header_source, ctype_hint=ctypes.c_int): +def getsimpletype(name, c_header_source, ctype_hint=rffi.INT): class CConfig: _header_ = c_header_source TYPE = SimpleType(name, ctype_hint) @@ -129,19 +131,19 @@ def prepare_code(self): if self.ifdef is not None: yield '#ifdef %s' % (self.ifdef,) - yield 'typedef %s ctypesplatcheck_t;' % (self.name,) + yield 'typedef %s platcheck_t;' % (self.name,) yield 'typedef struct {' yield ' char c;' - yield ' ctypesplatcheck_t s;' - yield '} ctypesplatcheck2_t;' + yield ' platcheck_t s;' + yield '} platcheck2_t;' yield '' - yield 'ctypesplatcheck_t s;' + yield 'platcheck_t s;' if self.ifdef is not None: yield 'dump("defined", 1);' - yield 'dump("align", offsetof(ctypesplatcheck2_t, s));' - yield 'dump("size", sizeof(ctypesplatcheck_t));' + yield 'dump("align", offsetof(platcheck2_t, s));' + yield 'dump("size", sizeof(platcheck_t));' for fieldname, fieldtype in self.interesting_fields: - yield 'dump("fldofs %s", offsetof(ctypesplatcheck_t, %s));'%( + yield 'dump("fldofs %s", offsetof(platcheck_t, %s));'%( fieldname, fieldname) yield 'dump("fldsize %s", sizeof(s.%s));' % ( fieldname, fieldname) @@ -160,7 +162,6 @@ if self.ifdef is not None: if not info['defined']: return None - alignment = 1 layout = [None] * info['size'] for fieldname, fieldtype in self.interesting_fields: if isinstance(fieldtype, Struct): @@ -168,7 +169,6 @@ size = info['fldsize ' + fieldname] c_fieldtype = config_result.get_entry_result(fieldtype) layout_addfield(layout, offset, c_fieldtype, fieldname) - alignment = max(alignment, ctype_alignment(c_fieldtype)) else: offset = info['fldofs ' + fieldname] size = info['fldsize ' + fieldname] @@ -176,33 +176,15 @@ if (size, sign) != size_and_sign(fieldtype): fieldtype = fixup_ctype(fieldtype, fieldname, (size, sign)) layout_addfield(layout, offset, fieldtype, fieldname) - alignment = max(alignment, ctype_alignment(fieldtype)) - - # try to enforce the same alignment as the one of the original - # structure - if alignment < info['align']: - choices = [ctype for ctype in alignment_types - if ctype_alignment(ctype) == info['align']] - assert choices, "unsupported alignment %d" % (info['align'],) - choices = [(ctypes.sizeof(ctype), i, ctype) - for i, ctype in enumerate(choices)] - csize, _, ctype = min(choices) - for i in range(0, info['size'] - csize + 1, info['align']): - if layout[i:i+csize] == [None] * csize: - layout_addfield(layout, i, ctype, '_alignment') - break - else: - raise AssertionError("unenforceable alignment %d" % ( - info['align'],)) n = 0 for i, cell in enumerate(layout): if cell is not None: continue - layout_addfield(layout, i, ctypes.c_char, '_pad%d' % (n,)) + layout_addfield(layout, i, rffi.UCHAR, '_pad%d' % (n,)) n += 1 - # build the ctypes Structure + # build the lltype Structure seen = {} fields = [] for cell in layout: @@ -211,20 +193,18 @@ fields.append((cell.name, cell.ctype)) seen[cell] = True - class S(ctypes.Structure): - _fields_ = fields name = self.name if name.startswith('struct '): name = name[7:] - S.__name__ = name - return S - + kwds = {'hints':{'align':info['align'], + 'size':info['size']}} + return rffi.CStruct(name, *fields, **kwds).TO class SimpleType(CConfigEntry): """An entry in a CConfig class that stands for an externally defined simple numeric type. """ - def __init__(self, name, ctype_hint=ctypes.c_int, ifdef=None): + def __init__(self, name, ctype_hint=rffi.INT, ifdef=None): self.name = name self.ctype_hint = ctype_hint self.ifdef = ifdef @@ -232,12 +212,12 @@ def prepare_code(self): if self.ifdef is not None: yield '#ifdef %s' % (self.ifdef,) - yield 'typedef %s ctypesplatcheck_t;' % (self.name,) + yield 'typedef %s platcheck_t;' % (self.name,) yield '' - yield 'ctypesplatcheck_t x;' + yield 'platcheck_t x;' if self.ifdef is not None: yield 'dump("defined", 1);' - yield 'dump("size", sizeof(ctypesplatcheck_t));' + yield 'dump("size", sizeof(platcheck_t));' if self.ctype_hint in integer_class: yield 'x = 0; x = ~x;' yield 'dump("unsigned", x > 0);' @@ -354,9 +334,10 @@ class Library(CConfigEntry): - """The loaded CTypes library object. + """The loaded library object. """ def __init__(self, name): + XXX # uh self.name = name def prepare_code(self): @@ -382,6 +363,7 @@ # internal helpers def ctype_alignment(c_type): + xxxx if issubclass(c_type, ctypes.Structure): return max([ctype_alignment(fld_type) for fld_name, fld_type in c_type._fields_]) @@ -391,28 +373,16 @@ def uniquefilepath(LAST=[0]): i = LAST[0] LAST[0] += 1 - return udir.join('ctypesplatcheck_%d.c' % i) + return udir.join('platcheck_%d.c' % i) -alignment_types = [ - ctypes.c_short, - ctypes.c_int, - ctypes.c_long, - ctypes.c_float, - ctypes.c_double, - ctypes.c_char_p, - ctypes.c_void_p, - ctypes.c_longlong, - ctypes.c_wchar, - ctypes.c_wchar_p, - ] - -integer_class = [ctypes.c_byte, ctypes.c_ubyte, - ctypes.c_short, ctypes.c_ushort, - ctypes.c_int, ctypes.c_uint, - ctypes.c_long, ctypes.c_ulong, - ctypes.c_longlong, ctypes.c_ulonglong, - ] -float_class = [ctypes.c_float, ctypes.c_double] +integer_class = [rffi.SIGNEDCHAR, rffi.CHAR, + rffi.SHORT, rffi.USHORT, + rffi.INT, rffi.UINT, + rffi.LONG, rffi.ULONG, + rffi.LONGLONG, rffi.ULONGLONG] +# XXX SIZE_T? + +float_class = [rffi.DOUBLE] class Field(object): def __init__(self, name, ctype): @@ -422,7 +392,7 @@ return '' % (self.name, self.ctype) def layout_addfield(layout, offset, ctype, prefix): - size = ctypes.sizeof(ctype) + size = _sizeof(ctype) name = prefix i = 0 while name in layout: @@ -434,9 +404,16 @@ layout[i] = field return field +def _sizeof(ctype): + return ctype._type.BITS / 8 + def size_and_sign(ctype): - return (ctypes.sizeof(ctype), - ctype in integer_class and ctype(-1).value > 0) + # XXX uh, dirty hack + if ctype is lltype.Char: + return 1, 1 + assert isinstance(ctype, lltype.Number) + r_type = ctype._type + return _sizeof(ctype), not r_type.SIGNED def fixup_ctype(fieldtype, fieldname, expected_size_and_sign): for typeclass in [integer_class, float_class]: @@ -444,12 +421,13 @@ for ctype in typeclass: if size_and_sign(ctype) == expected_size_and_sign: return ctype + xxxx if (hasattr(fieldtype, '_length_') - and getattr(fieldtype, '_type_', None) == ctypes.c_char): + and getattr(fieldtype, '_type_', None) == rffi.UCHAR): # for now, assume it is an array of chars; otherwise we'd also # have to check the exact integer type of the elements of the array size, sign = expected_size_and_sign - return ctypes.c_char * size + return rffi.UCHAR * size if (hasattr(fieldtype, '_length_') and getattr(fieldtype, '_type_', None) == ctypes.c_ubyte): # grumble, fields of type 'c_char array' have automatic cast-to- @@ -497,9 +475,9 @@ if __name__ == '__main__': doc = """Example: - ctypes_platform.py -h sys/types.h -h netinet/in.h + rffi_platform.py -h sys/types.h -h netinet/in.h 'struct sockaddr_in' - sin_port c_int + sin_port INT """ import sys, getopt opts, args = getopt.gnu_getopt(sys.argv[1:], 'h:') @@ -514,7 +492,7 @@ name = args[0] fields = [] for i in range(1, len(args), 2): - ctype = getattr(ctypes, args[i+1]) + ctype = getattr(rffi, args[i+1]) fields.append((args[i], ctype)) S = getstruct(name, '\n'.join(headers), fields) From arigo at codespeak.net Thu Aug 16 13:01:40 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 13:01:40 +0200 (CEST) Subject: [pypy-svn] r45706 - in pypy/branch/pypy-more-rtti-inprogress/rlib: . test Message-ID: <20070816110140.095AD815C@code0.codespeak.net> Author: arigo Date: Thu Aug 16 13:01:40 2007 New Revision: 45706 Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rbigint.py pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rbigint.py Log: Added rbigint.tolonglong(). Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rbigint.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/rbigint.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/rbigint.py Thu Aug 16 13:01:40 2007 @@ -1,4 +1,5 @@ -from pypy.rlib.rarithmetic import LONG_BIT, intmask, r_uint, r_ulonglong, ovfcheck +from pypy.rlib.rarithmetic import LONG_BIT, intmask, r_uint, r_ulonglong +from pypy.rlib.rarithmetic import ovfcheck, r_longlong import math, sys @@ -174,6 +175,9 @@ def toint(self): return _AsLong(self) + def tolonglong(self): + return _AsLongLong(self) + def tobool(self): return self.sign != 0 @@ -194,16 +198,7 @@ def toulonglong(self): if self.sign == -1: raise ValueError("cannot convert negative integer to unsigned int") - x = r_ulonglong(0) - i = len(self.digits) - 1 - while i >= 0: - prev = x - x = (x << SHIFT) + self.digits[i] - if (x >> SHIFT) != prev: - raise OverflowError( - "long int too large to convert to unsigned long long int") - i -= 1 - return x + return _AsULonglong_ignore_sign(self) def tofloat(self): return _AsDouble(self) @@ -1557,6 +1552,39 @@ raise OverflowError return intmask(x * sign) +ULONGLONG_BOUND = r_ulonglong(1L << (r_longlong.BITS-1)) +LONGLONG_MIN = r_longlong(-(1L << (r_longlong.BITS-1))) + +def _AsLongLong(v): + """ + Get a r_longlong integer from a bigint object. + Raises OverflowError if overflow occurs. + """ + x = _AsULonglong_ignore_sign(v) + # grr grr grr + if x >= ULONGLONG_BOUND: + if x == ULONGLONG_BOUND and v.sign < 0: + x = LONGLONG_MIN + else: + raise OverflowError + else: + x = r_longlong(x) + if v.sign < 0: + x = -x + return x + +def _AsULonglong_ignore_sign(v): + x = r_ulonglong(0) + i = len(v.digits) - 1 + while i >= 0: + prev = x + x = (x << SHIFT) + v.digits[i] + if (x >> SHIFT) != prev: + raise OverflowError( + "long int too large to convert to unsigned long long int") + i -= 1 + return x + def _hash(v): # This is designed so that Python ints and longs with the # same value hash to the same value, otherwise comparisons Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rbigint.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rbigint.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rbigint.py Thu Aug 16 13:01:40 2007 @@ -3,7 +3,7 @@ from random import random, randint from pypy.rlib.rbigint import rbigint, SHIFT, MASK from pypy.rlib import rbigint as lobj -from pypy.rlib.rarithmetic import r_uint +from pypy.rlib.rarithmetic import r_uint, r_longlong import operator, sys class TestRLong(object): @@ -408,7 +408,16 @@ ret = lobj._k_lopsided_mul(f1, f2) assert ret.tolong() == f1.tolong() * f2.tolong() - + def test_longlong(self): + max = 1L << (r_longlong.BITS-1) + f1 = rbigint.fromlong(max-1) # fits in r_longlong + f2 = rbigint.fromlong(-max) # fits in r_longlong + f3 = rbigint.fromlong(max) # overflows + f4 = rbigint.fromlong(-max-1) # overflows + assert f1.tolonglong() == max-1 + assert f2.tolonglong() == -max + py.test.raises(OverflowError, f3.tolonglong) + py.test.raises(OverflowError, f4.tolonglong) class TestTranslatable(object): From arigo at codespeak.net Thu Aug 16 13:03:07 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 13:03:07 +0200 (CEST) Subject: [pypy-svn] r45708 - in pypy/branch/pypy-more-rtti-inprogress/interpreter: . test Message-ID: <20070816110307.1714D815C@code0.codespeak.net> Author: arigo Date: Thu Aug 16 13:03:06 2007 New Revision: 45708 Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/baseobjspace.py pypy/branch/pypy-more-rtti-inprogress/interpreter/test/test_objspace.py Log: space.r_longlong_w(). Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/interpreter/baseobjspace.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/interpreter/baseobjspace.py Thu Aug 16 13:03:06 2007 @@ -837,6 +837,14 @@ else: return index + def r_longlong_w(self, w_obj): + bigint = self.bigint_w(w_obj) + try: + return bigint.tolonglong() + except OverflowError: + raise OperationError(self.w_OverflowError, + self.wrap('integer too large')) + class AppExecCache(SpaceCache): def build(cache, source): Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/test/test_objspace.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/interpreter/test/test_objspace.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/interpreter/test/test_objspace.py Thu Aug 16 13:03:06 2007 @@ -2,6 +2,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.function import Function from pypy.interpreter.pycode import PyCode +from pypy.rlib.rarithmetic import r_longlong import sys # this test isn't so much to test that the objspace interface *works* @@ -164,6 +165,16 @@ else: assert 0, "should have raised" + def test_r_longlong_w(self): + w_value = self.space.wrap(12) + res = self.space.r_longlong_w(w_value) + assert res == 12 + assert type(res) is r_longlong + w_value = self.space.wrap(r_longlong(-sys.maxint * 42)) + res = self.space.r_longlong_w(w_value) + assert res == -sys.maxint * 42 + assert type(res) is r_longlong + class TestModuleMinimal: def test_sys_exists(self): From arigo at codespeak.net Thu Aug 16 13:05:03 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 13:05:03 +0200 (CEST) Subject: [pypy-svn] r45709 - in pypy/branch/pypy-more-rtti-inprogress/interpreter: . test Message-ID: <20070816110503.8CEBE815D@code0.codespeak.net> Author: arigo Date: Thu Aug 16 13:05:03 2007 New Revision: 45709 Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/gateway.py pypy/branch/pypy-more-rtti-inprogress/interpreter/test/test_gateway.py Log: Gateway support for 'r_longlong' in unwrap_spec. Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/gateway.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/interpreter/gateway.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/interpreter/gateway.py Thu Aug 16 13:05:03 2007 @@ -20,6 +20,7 @@ from pypy.interpreter.argument import Arguments, AbstractArguments from pypy.tool.sourcetools import NiceCompile, compile2 from pypy.rlib.jit import hint +from pypy.rlib.rarithmetic import r_longlong # internal non-translatable parts: import py @@ -163,7 +164,7 @@ app_sig.varargname = argname[2:] def visit__object(self, typ, app_sig): - if typ not in (int, str, float): + if typ not in (int, str, float, r_longlong): assert False, "unsupported basic type in unwrap_spec" self.checked_space_method(typ.__name__, app_sig) @@ -209,7 +210,7 @@ self.run_args.append(self.scopenext()) def visit__object(self, typ): - if typ not in (int, str, float): + if typ not in (int, str, float, r_longlong): assert False, "unsupported basic type in uwnrap_spec" self.run_args.append("space.%s_w(%s)" % (typ.__name__, self.scopenext())) @@ -322,7 +323,7 @@ raise FastFuncNotSupported def visit__object(self, typ): - if typ not in (int, str, float): + if typ not in (int, str, float, r_longlong): assert False, "unsupported basic type in uwnrap_spec" self.unwrap.append("space.%s_w(%s)" % (typ.__name__, self.nextarg())) Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/test/test_gateway.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/interpreter/test/test_gateway.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/interpreter/test/test_gateway.py Thu Aug 16 13:05:03 2007 @@ -209,6 +209,28 @@ space.call_function(w_app_g3_if, w(1), w(1.0)), w(2.0)) + def test_interp2app_unwrap_spec_r_longlong(self): + space = self.space + w = space.wrap + def g3_ll(space, n): + return space.wrap(n * 3) + app_g3_ll = gateway.interp2app_temp(g3_ll, + unwrap_spec=[gateway.ObjSpace, + gateway.r_longlong]) + w_app_g3_ll = space.wrap(app_g3_ll) + w_big = w(gateway.r_longlong(10**10)) + assert space.eq_w( + space.call(w_app_g3_ll, + space.newtuple([w_big]), + space.newdict()), + w(gateway.r_longlong(3 * 10**10))) + assert space.eq_w( + space.call_function(w_app_g3_ll, w_big), + w(gateway.r_longlong(3 * 10**10))) + w_huge = w(10L**100) + space.raises_w(space.w_OverflowError, + space.call_function, w_app_g3_ll, w_huge) + def test_interp2app_unwrap_spec_index(self): space = self.space w = space.wrap From arigo at codespeak.net Thu Aug 16 13:09:55 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 13:09:55 +0200 (CEST) Subject: [pypy-svn] r45710 - in pypy/branch/pypy-more-rtti-inprogress/module/posix: . test Message-ID: <20070816110955.54057815F@code0.codespeak.net> Author: arigo Date: Thu Aug 16 13:09:54 2007 New Revision: 45710 Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py Log: Some more large file support: os.ftruncate(), os.lseek(). Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Thu Aug 16 13:09:54 2007 @@ -1,4 +1,5 @@ from pypy.interpreter.baseobjspace import ObjSpace, W_Root +from pypy.rlib.rarithmetic import r_longlong from pypy.rlib.unroll import unrolling_iterable from pypy.interpreter.error import OperationError, wrap_oserror from pypy.rpython.module.ll_os import RegisterOs @@ -27,7 +28,7 @@ raise wrap_oserror(space, e) else: return space.wrap(pos) -lseek.unwrap_spec = [ObjSpace, int, int, int] +lseek.unwrap_spec = [ObjSpace, int, r_longlong, int] def isatty(space, fd): """Return True if 'fd' is an open file descriptor connected to the @@ -75,7 +76,7 @@ os.ftruncate(fd, length) except OSError, e: raise wrap_oserror(space, e) -ftruncate.unwrap_spec = [ObjSpace, int, int] +ftruncate.unwrap_spec = [ObjSpace, int, r_longlong] # ____________________________________________________________ Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py Thu Aug 16 13:09:54 2007 @@ -11,6 +11,7 @@ mod.space = gettestobjspace(usemodules=['posix']) mod.path = udir.join('posixtestfile.txt') mod.path.write("this is a test") + mod.path2 = udir.join('posixtestlargefile') pdir = udir.ensure('posixtestdir', dir=True) pdir.join('file1').write("test1") os.chmod(str(pdir.join('file1')), 0600) @@ -23,6 +24,7 @@ cls.space = space cls.w_posix = space.appexec([], "(): import %s as m ; return m" % os.name) cls.w_path = space.wrap(str(path)) + cls.w_path2 = space.wrap(str(path2)) cls.w_pdir = space.wrap(str(pdir)) cls.w_getuid = space.wrap(os.getuid()) cls.w_geteuid = space.wrap(os.geteuid()) @@ -258,6 +260,23 @@ os.getuid() == self.getuid os.geteuid() == self.geteuid + def test_largefile(self): + os = self.posix + if os.__name__ == 'nt': + skip("no sparse files on Windows") + fd = os.open(self.path2, os.O_RDWR | os.O_CREAT, 0666) + os.ftruncate(fd, 10000000000L) + res = os.lseek(fd, 9900000000L, 0) + assert res == 9900000000L + res = os.lseek(fd, -5000000000L, 1) + assert res == 4900000000L + res = os.lseek(fd, -5200000000L, 2) + assert res == 4800000000L + os.close(fd) + + st = os.stat(self.path2) + assert st.st_size == 10000000000L + class AppTestEnvironment(object): def setup_class(cls): cls.space = space From fijal at codespeak.net Thu Aug 16 13:36:28 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 13:36:28 +0200 (CEST) Subject: [pypy-svn] r45711 - in pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem: . test Message-ID: <20070816113628.26AA1815D@code0.codespeak.net> Author: fijal Date: Thu Aug 16 13:36:27 2007 New Revision: 45711 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Log: Some random sizeof() and size_and_sign(), probably too tight in some sense. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Thu Aug 16 13:36:27 2007 @@ -196,4 +196,24 @@ lltype.free(ref, flavor='raw') cast = ll2ctypes.force_cast # a forced, no-checking cast - + +def size_and_sign(tp): + if tp is lltype.Char: + return 1, True + assert isinstance(tp, lltype.Number) + if tp is lltype.Signed: + sign = True + else: + sign = tp._type.SIGNED + return sizeof(tp), sign + +def sizeof(tp): + # works only for int types! + if tp is lltype.Char: + return 1 + if tp is lltype.Float: + return 8 + assert isinstance(tp, lltype.Number) + if tp is lltype.Signed: + return ULONG._type.BITS/8 + return tp._type.BITS/8 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Thu Aug 16 13:36:27 2007 @@ -242,3 +242,16 @@ f1 = compile(f, []) assert f1() == 'a' + +def test_rffi_sizeof(): + try: + import ctypes + except ImportError: + py.test.skip("Cannot test without ctypes") + from pypy.rpython.lltypesystem import ll2ctypes + ll2ctypes._setup_ctypes_cache() + for ll, ctp in ll2ctypes._ctypes_cache.items(): + assert sizeof(ll) == ctypes.sizeof(ctp) + assert size_and_sign(lltype.Signed)[1] + assert size_and_sign(lltype.Char)[1] + assert not size_and_sign(UINT)[1] From fijal at codespeak.net Thu Aug 16 13:38:39 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 13:38:39 +0200 (CEST) Subject: [pypy-svn] r45712 - in pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem: . test Message-ID: <20070816113839.F1BBC815D@code0.codespeak.net> Author: fijal Date: Thu Aug 16 13:38:39 2007 New Revision: 45712 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Log: Move it to return unsigned flag (negated sign), because rffi_platform expects this Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Thu Aug 16 13:38:39 2007 @@ -199,13 +199,13 @@ def size_and_sign(tp): if tp is lltype.Char: - return 1, True + return 1, False assert isinstance(tp, lltype.Number) if tp is lltype.Signed: - sign = True + unsigned = False else: - sign = tp._type.SIGNED - return sizeof(tp), sign + unsigned = not tp._type.SIGNED + return sizeof(tp), unsigned def sizeof(tp): # works only for int types! Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Thu Aug 16 13:38:39 2007 @@ -252,6 +252,6 @@ ll2ctypes._setup_ctypes_cache() for ll, ctp in ll2ctypes._ctypes_cache.items(): assert sizeof(ll) == ctypes.sizeof(ctp) - assert size_and_sign(lltype.Signed)[1] - assert size_and_sign(lltype.Char)[1] - assert not size_and_sign(UINT)[1] + assert not size_and_sign(lltype.Signed)[1] + assert not size_and_sign(lltype.Char)[1] + assert size_and_sign(UINT)[1] From fijal at codespeak.net Thu Aug 16 13:48:23 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 13:48:23 +0200 (CEST) Subject: [pypy-svn] r45714 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070816114823.8502380FD@code0.codespeak.net> Author: fijal Date: Thu Aug 16 13:48:23 2007 New Revision: 45714 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: return whatever for float, we really need to think how to handle that Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Thu Aug 16 13:48:23 2007 @@ -200,6 +200,8 @@ def size_and_sign(tp): if tp is lltype.Char: return 1, False + if tp is lltype.Float: + return 8, False assert isinstance(tp, lltype.Number) if tp is lltype.Signed: unsigned = False From fijal at codespeak.net Thu Aug 16 13:48:44 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 13:48:44 +0200 (CEST) Subject: [pypy-svn] r45715 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070816114844.3035B80FD@code0.codespeak.net> Author: fijal Date: Thu Aug 16 13:48:43 2007 New Revision: 45715 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Log: Another test passes Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Thu Aug 16 13:48:43 2007 @@ -173,7 +173,7 @@ offset = info['fldofs ' + fieldname] size = info['fldsize ' + fieldname] sign = info.get('fldunsigned ' + fieldname, False) - if (size, sign) != size_and_sign(fieldtype): + if (size, sign) != rffi.size_and_sign(fieldtype): fieldtype = fixup_ctype(fieldtype, fieldname, (size, sign)) layout_addfield(layout, offset, fieldtype, fieldname) @@ -232,7 +232,7 @@ size = info['size'] sign = info.get('unsigned', False) ctype = self.ctype_hint - if (size, sign) != size_and_sign(ctype): + if (size, sign) != rffi.size_and_sign(ctype): ctype = fixup_ctype(ctype, self.name, (size, sign)) return ctype @@ -375,7 +375,7 @@ LAST[0] += 1 return udir.join('platcheck_%d.c' % i) -integer_class = [rffi.SIGNEDCHAR, rffi.CHAR, +integer_class = [rffi.CHAR, rffi.UCHAR, rffi.SHORT, rffi.USHORT, rffi.INT, rffi.UINT, rffi.LONG, rffi.ULONG, @@ -392,7 +392,7 @@ return '' % (self.name, self.ctype) def layout_addfield(layout, offset, ctype, prefix): - size = _sizeof(ctype) + size = rffi.sizeof(ctype) name = prefix i = 0 while name in layout: @@ -404,22 +404,11 @@ layout[i] = field return field -def _sizeof(ctype): - return ctype._type.BITS / 8 - -def size_and_sign(ctype): - # XXX uh, dirty hack - if ctype is lltype.Char: - return 1, 1 - assert isinstance(ctype, lltype.Number) - r_type = ctype._type - return _sizeof(ctype), not r_type.SIGNED - def fixup_ctype(fieldtype, fieldname, expected_size_and_sign): for typeclass in [integer_class, float_class]: if fieldtype in typeclass: for ctype in typeclass: - if size_and_sign(ctype) == expected_size_and_sign: + if rffi.size_and_sign(ctype) == expected_size_and_sign: return ctype xxxx if (hasattr(fieldtype, '_length_') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Thu Aug 16 13:48:43 2007 @@ -37,8 +37,7 @@ assert dirent._flds['c_d_reclen'] is rffi.USHORT def test_fit_type(): - py.test.skip("Next to go") - S = ctypes_platform.getstruct("struct S", + S = rffi_platform.getstruct("struct S", """ struct S { signed char c; @@ -51,36 +50,35 @@ unsigned long ul; long long ll; unsigned long long ull; - float f; double d; }; """, - [("c", ctypes.c_int), - ("uc", ctypes.c_int), - ("s", ctypes.c_uint), - ("us", ctypes.c_int), - ("i", ctypes.c_int), - ("ui", ctypes.c_int), - ("l", ctypes.c_int), - ("ul", ctypes.c_int), - ("ll", ctypes.c_int), - ("ull", ctypes.c_int), - ("f", ctypes.c_double), - ("d", ctypes.c_float)]) - assert issubclass(S, ctypes.Structure) - fields = dict(S._fields_) - assert fields["c"] == ctypes.c_byte - assert fields["uc"] == ctypes.c_ubyte - assert fields["s"] == ctypes.c_short - assert fields["us"] == ctypes.c_ushort - assert fields["i"] == ctypes.c_int - assert fields["ui"] == ctypes.c_uint - assert fields["l"] == ctypes.c_long - assert fields["ul"] == ctypes.c_ulong - assert fields["ll"] == ctypes.c_longlong - assert fields["ull"] == ctypes.c_ulonglong - assert fields["f"] == ctypes.c_float - assert fields["d"] == ctypes.c_double + [("c", rffi.INT), + ("uc", rffi.INT), + ("s", rffi.UINT), + ("us", rffi.INT), + ("i", rffi.INT), + ("ui", rffi.INT), + ("l", rffi.INT), + ("ul", rffi.INT), + ("ll", rffi.INT), + ("ull", rffi.INT), + ("d", rffi.DOUBLE)]) + # XXX we need to have a float here as well as soon as we'll + # have support + assert isinstance(S, lltype.Struct) + fields = dict(S._flds) + assert fields["c_c"] == rffi.CHAR + assert fields["c_uc"] == rffi.UCHAR + assert fields["c_s"] == rffi.SHORT + assert fields["c_us"] == rffi.USHORT + assert fields["c_i"] == rffi.INT + assert fields["c_ui"] == rffi.UINT + assert fields["c_l"] == rffi.LONG + assert fields["c_ul"] == rffi.ULONG + assert fields["c_ll"] == rffi.LONGLONG + assert fields["c_ull"] == rffi.ULONGLONG + assert fields["c_d"] == rffi.DOUBLE def test_simple_type(): py.test.skip("Next to go") From fijal at codespeak.net Thu Aug 16 14:06:46 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 14:06:46 +0200 (CEST) Subject: [pypy-svn] r45716 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070816120646.050CE8150@code0.codespeak.net> Author: fijal Date: Thu Aug 16 14:06:45 2007 New Revision: 45716 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Log: Most of tests are passing, although there are still some cases where there are xxxs and so on. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Thu Aug 16 14:06:45 2007 @@ -384,6 +384,11 @@ float_class = [rffi.DOUBLE] +def _sizeof(tp): + if isinstance(tp, lltype.Struct): + return sum([_sizeof(i) for i in tp._flds.values()]) + return rffi.sizeof(tp) + class Field(object): def __init__(self, name, ctype): self.name = name @@ -392,7 +397,7 @@ return '' % (self.name, self.ctype) def layout_addfield(layout, offset, ctype, prefix): - size = rffi.sizeof(ctype) + size = _sizeof(ctype) name = prefix i = 0 while name in layout: Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Thu Aug 16 14:06:45 2007 @@ -81,34 +81,30 @@ assert fields["c_d"] == rffi.DOUBLE def test_simple_type(): - py.test.skip("Next to go") - ctype = ctypes_platform.getsimpletype('test_t', - 'typedef unsigned short test_t;', - ctypes.c_int) - assert ctype == ctypes.c_ushort + ctype = rffi_platform.getsimpletype('test_t', + 'typedef unsigned short test_t;', + rffi.INT) + assert ctype == rffi.USHORT def test_constant_integer(): - py.test.skip("Next to go") - value = ctypes_platform.getconstantinteger('BLAH', + value = rffi_platform.getconstantinteger('BLAH', '#define BLAH (6*7)') assert value == 42 - value = ctypes_platform.getconstantinteger('BLAH', + value = rffi_platform.getconstantinteger('BLAH', '#define BLAH (-2147483648LL)') assert value == -2147483648 - value = ctypes_platform.getconstantinteger('BLAH', + value = rffi_platform.getconstantinteger('BLAH', '#define BLAH (3333333333ULL)') assert value == 3333333333 def test_defined(): - py.test.skip("Next to go") - res = ctypes_platform.getdefined('ALFKJLKJFLKJFKLEJDLKEWMECEE', '') + res = rffi_platform.getdefined('ALFKJLKJFLKJFKLEJDLKEWMECEE', '') assert not res - res = ctypes_platform.getdefined('ALFKJLKJFLKJFKLEJDLKEWMECEE', + res = rffi_platform.getdefined('ALFKJLKJFLKJFKLEJDLKEWMECEE', '#define ALFKJLKJFLKJFKLEJDLKEWMECEE') assert res def test_configure(): - py.test.skip("Next to go") test_h = udir.join('test_ctypes_platform.h') test_h.write('#define XYZZY 42\n') @@ -119,18 +115,17 @@ """ _include_dirs_ = [str(udir)] - FILE = ctypes_platform.Struct('FILE', []) - ushort = ctypes_platform.SimpleType('unsigned short') - XYZZY = ctypes_platform.ConstantInteger('XYZZY') + FILE = rffi_platform.Struct('FILE', []) + ushort = rffi_platform.SimpleType('unsigned short') + XYZZY = rffi_platform.ConstantInteger('XYZZY') - res = ctypes_platform.configure(CConfig) - assert issubclass(res['FILE'], ctypes.Structure) + res = rffi_platform.configure(CConfig) + assert isinstance(res['FILE'], lltype.Struct) assert res == {'FILE': res['FILE'], - 'ushort': ctypes.c_ushort, + 'ushort': rffi.USHORT, 'XYZZY': 42} def test_ifdef(): - py.test.skip("Next to go") class CConfig: _header_ = """ /* a C comment */ #define XYZZY 42 @@ -141,22 +136,21 @@ }; """ - s = ctypes_platform.Struct('struct s', [('i', ctypes.c_int)], + s = rffi_platform.Struct('struct s', [('i', rffi.INT)], ifdef='XYZZY') - z = ctypes_platform.Struct('struct z', [('i', ctypes.c_int)], + z = rffi_platform.Struct('struct z', [('i', rffi.INT)], ifdef='FOOBAR') - foo = ctypes_platform.SimpleType('foo', ifdef='XYZZY') - bar = ctypes_platform.SimpleType('bar', ifdef='FOOBAR') + foo = rffi_platform.SimpleType('foo', ifdef='XYZZY') + bar = rffi_platform.SimpleType('bar', ifdef='FOOBAR') - res = ctypes_platform.configure(CConfig) + res = rffi_platform.configure(CConfig) assert res['s'] is not None assert res['z'] is None assert res['foo'] is not None assert res['bar'] is None def test_nested_structs(): - py.test.skip("Next to go") class CConfig: _header_ = """ struct x { @@ -168,20 +162,20 @@ struct x x; }; """ - x = ctypes_platform.Struct("struct x", [("bar", ctypes.c_short)]) - y = ctypes_platform.Struct("struct y", [("x", x)]) + x = rffi_platform.Struct("struct x", [("bar", rffi.SHORT)]) + y = rffi_platform.Struct("struct y", [("x", x)]) - res = ctypes_platform.configure(CConfig) + res = rffi_platform.configure(CConfig) c_x = res["x"] c_y = res["y"] - c_y_fields = dict(c_y._fields_) - assert issubclass(c_x , ctypes.Structure) - assert issubclass(c_y, ctypes.Structure) - assert c_y_fields["x"] is c_x + c_y_fields = dict(c_y._flds) + assert isinstance(c_x , lltype.Struct) + assert isinstance(c_y, lltype.Struct) + assert c_y_fields["c_x"] is c_x def test_array(): py.test.skip("Next to go") - dirent = ctypes_platform.getstruct("struct dirent", + dirent = rffi_platform.getstruct("struct dirent", """ struct dirent /* for this example only, not the exact dirent */ { @@ -191,5 +185,5 @@ char d_name[32]; }; """, - [("d_name", ctypes.c_char * 0)]) + [("d_name", rffi.CArray(rffi.CHAR).TO)]) assert dirent.d_name.size == 32 From arigo at codespeak.net Thu Aug 16 14:08:16 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 14:08:16 +0200 (CEST) Subject: [pypy-svn] r45717 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src translator/c/test Message-ID: <20070816120816.349018150@code0.codespeak.net> Author: arigo Date: Thu Aug 16 14:08:13 2007 New Revision: 45717 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: os.ftruncate(). Test large files when translated to C too. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 14:08:13 2007 @@ -151,8 +151,6 @@ # external function declarations posix = __import__(os.name) declare(os.isatty , bool , 'll_os/isatty') -if hasattr(posix, 'ftruncate'): - declare(os.ftruncate, noneannotation, 'll_os/ftruncate') declare(os.system , int , 'll_os/system') declare(os.strerror , str , 'll_os/strerror') declare(os.unlink , noneannotation, 'll_os/unlink') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 14:08:13 2007 @@ -372,6 +372,22 @@ export_name = "ll_os.ll_os_lseek", oofakeimpl = os_lseek_oofakeimpl) + if hasattr(os, 'ftruncate'): + @registering(os.ftruncate) + def register_os_ftruncate(self): + os_ftruncate = rffi.llexternal('ftruncate', + [rffi.INT, rffi.LONGLONG], rffi.INT) + + def ftruncate_lltypeimpl(fd, length): + res = os_ftruncate(rffi.cast(rffi.INT, fd), + rffi.cast(rffi.LONGLONG, length)) + if res < 0: + raise OSError(rffi.get_errno(), "os_lseek failed") + + self.register(os.ftruncate, [int, r_longlong], s_None, + llimpl = ftruncate_lltypeimpl, + export_name = "ll_os.ll_os_ftruncate") + @registering(os.access) def register_os_access(self): os_access = rffi.llexternal('access', @@ -682,10 +698,6 @@ return os.isatty(fd) ll_os_isatty.suggested_primitive = True - def ll_os_ftruncate(cls, fd,len): - return os.ftruncate(fd,len) - ll_os_ftruncate.suggested_primitive = True - def ll_os_strerror(cls, errnum): return cls.to_rstr(os.strerror(errnum)) ll_os_strerror.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 14:08:13 2007 @@ -21,7 +21,6 @@ EXTERNALS = { impl.ll_os_isatty.im_func: 'LL_os_isatty', - impl.ll_os_ftruncate.im_func:'LL_os_ftruncate', impl.ll_os_strerror.im_func: 'LL_os_strerror', impl.ll_os_system.im_func: 'LL_os_system', impl.ll_os_unlink.im_func: 'LL_os_unlink', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 14:08:13 2007 @@ -73,16 +73,6 @@ return isatty((int)fd); } -#ifdef HAVE_FTRUNCATE -void LL_os_ftruncate(long fd, long length) { /*XXX add longfile support */ - int res; - res = ftruncate((int)fd, (off_t)length); - if (res < 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} -#endif - RPyString *LL_os_strerror(int errnum) { char *res; res = strerror(errnum); Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Thu Aug 16 14:08:13 2007 @@ -2,6 +2,7 @@ import py import os, time, sys from pypy.tool.udir import udir +from pypy.rlib.rarithmetic import r_longlong from pypy.translator.c.test.test_genc import compile from pypy.translator.c.extfunc import EXTERNALS posix = __import__(os.name) @@ -120,6 +121,35 @@ f1() os.unlink(filename) +def test_largefile(): + if not hasattr(os, 'ftruncate'): + py.test.skip("this os has no ftruncate :-(") + if os.name == 'nt': + py.test.skip("no sparse files on Windows") + filename = str(udir.join('test_largefile')) + r4800000000 = r_longlong(4800000000L) + r4900000000 = r_longlong(4900000000L) + r5000000000 = r_longlong(5000000000L) + r5200000000 = r_longlong(5200000000L) + r9900000000 = r_longlong(9900000000L) + r10000000000 = r_longlong(10000000000L) + def does_stuff(): + fd = os.open(filename, os.O_RDWR | os.O_CREAT, 0666) + os.ftruncate(fd, r10000000000) + res = os.lseek(fd, r9900000000, 0) + assert res == r9900000000 + res = os.lseek(fd, -r5000000000, 1) + assert res == r4900000000 + res = os.lseek(fd, -r5200000000, 2) + assert res == r4800000000 + os.close(fd) + st = os.stat(filename) + assert st.st_size == r10000000000 + does_stuff() + os.unlink(filename) + f1 = compile(does_stuff, []) + f1() + os.unlink(filename) def test_os_access(): filename = str(py.magic.autopath()) From arigo at codespeak.net Thu Aug 16 15:45:17 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 15:45:17 +0200 (CEST) Subject: [pypy-svn] r45719 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070816134517.75B398169@code0.codespeak.net> Author: arigo Date: Thu Aug 16 15:45:15 2007 New Revision: 45719 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Log: * prefer rffi.SIGNEDCHAR over the ambigous rffi.CHAR * minor cleanups in the test Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Thu Aug 16 15:45:15 2007 @@ -375,7 +375,7 @@ LAST[0] += 1 return udir.join('platcheck_%d.c' % i) -integer_class = [rffi.CHAR, rffi.UCHAR, +integer_class = [rffi.SIGNEDCHAR, rffi.UCHAR, rffi.CHAR, rffi.SHORT, rffi.USHORT, rffi.INT, rffi.UINT, rffi.LONG, rffi.ULONG, Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Thu Aug 16 15:45:15 2007 @@ -4,12 +4,12 @@ from pypy.rpython.lltypesystem import rffi from pypy.tool.udir import udir -def setup_module(mod): +def import_ctypes(): try: import ctypes - mod.ctypes = ctypes except ImportError: - py.test.skip("Cannot test rffi_platform without ctypes") + py.test.skip("this test requires ctypes") + return ctypes def test_dirent(): dirent = rffi_platform.getstruct("struct dirent", @@ -25,7 +25,10 @@ [("d_reclen", rffi.USHORT)]) assert isinstance(dirent, lltype.Struct) + # check that we have the desired field + assert dirent.c_d_reclen is rffi.USHORT + ctypes = import_ctypes() class CTypesDirent(ctypes.Structure): _fields_ = [('d_ino', ctypes.c_long), ('d_off', ctypes.c_int), @@ -33,8 +36,6 @@ ('d_name', ctypes.c_char * 32)] assert dirent._hints['size'] == ctypes.sizeof(CTypesDirent) - # check if we have a desired field - assert dirent._flds['c_d_reclen'] is rffi.USHORT def test_fit_type(): S = rffi_platform.getstruct("struct S", @@ -67,18 +68,17 @@ # XXX we need to have a float here as well as soon as we'll # have support assert isinstance(S, lltype.Struct) - fields = dict(S._flds) - assert fields["c_c"] == rffi.CHAR - assert fields["c_uc"] == rffi.UCHAR - assert fields["c_s"] == rffi.SHORT - assert fields["c_us"] == rffi.USHORT - assert fields["c_i"] == rffi.INT - assert fields["c_ui"] == rffi.UINT - assert fields["c_l"] == rffi.LONG - assert fields["c_ul"] == rffi.ULONG - assert fields["c_ll"] == rffi.LONGLONG - assert fields["c_ull"] == rffi.ULONGLONG - assert fields["c_d"] == rffi.DOUBLE + assert S.c_c == rffi.SIGNEDCHAR + assert S.c_uc == rffi.UCHAR + assert S.c_s == rffi.SHORT + assert S.c_us == rffi.USHORT + assert S.c_i == rffi.INT + assert S.c_ui == rffi.UINT + assert S.c_l == rffi.LONG + assert S.c_ul == rffi.ULONG + assert S.c_ll == rffi.LONGLONG + assert S.c_ull == rffi.ULONGLONG + assert S.c_d == rffi.DOUBLE def test_simple_type(): ctype = rffi_platform.getsimpletype('test_t', @@ -168,10 +168,9 @@ res = rffi_platform.configure(CConfig) c_x = res["x"] c_y = res["y"] - c_y_fields = dict(c_y._flds) - assert isinstance(c_x , lltype.Struct) + assert isinstance(c_x, lltype.Struct) assert isinstance(c_y, lltype.Struct) - assert c_y_fields["c_x"] is c_x + assert c_y.c_x is c_x def test_array(): py.test.skip("Next to go") From arigo at codespeak.net Thu Aug 16 15:46:37 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 15:46:37 +0200 (CEST) Subject: [pypy-svn] r45720 - pypy/branch/pypy-more-rtti-inprogress/rpython/tool Message-ID: <20070816134637.2E0FC8169@code0.codespeak.net> Author: arigo Date: Thu Aug 16 15:46:36 2007 New Revision: 45720 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Log: Fix example code. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Thu Aug 16 15:46:36 2007 @@ -491,5 +491,5 @@ S = getstruct(name, '\n'.join(headers), fields) - for key, value in S._fields_: - print key, value + for name in S._names: + print name, getattr(S, name) From arigo at codespeak.net Thu Aug 16 15:54:47 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 15:54:47 +0200 (CEST) Subject: [pypy-svn] r45721 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816135447.658898169@code0.codespeak.net> Author: arigo Date: Thu Aug 16 15:54:46 2007 New Revision: 45721 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.isatty()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 15:54:46 2007 @@ -150,7 +150,6 @@ # external function declarations posix = __import__(os.name) -declare(os.isatty , bool , 'll_os/isatty') declare(os.system , int , 'll_os/system') declare(os.strerror , str , 'll_os/strerror') declare(os.unlink , noneannotation, 'll_os/unlink') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 15:54:46 2007 @@ -605,6 +605,17 @@ "ll_os.ll_os_waitpid", llimpl=os_waitpid_lltypeimpl) + @registering(os.isatty) + def register_os_isatty(self): + os_isatty = rffi.llexternal('isatty', [rffi.INT], rffi.INT) + + def isatty_lltypeimpl(fd): + res = os_isatty(rffi.cast(rffi.INT, fd)) + return res != 0 + + self.register(os.isatty, [int], bool, llimpl=isatty_lltypeimpl, + export_name="ll_os.ll_os_isatty") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -694,10 +705,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_isatty(cls, fd): - return os.isatty(fd) - ll_os_isatty.suggested_primitive = True - def ll_os_strerror(cls, errnum): return cls.to_rstr(os.strerror(errnum)) ll_os_strerror.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 15:54:46 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_isatty.im_func: 'LL_os_isatty', impl.ll_os_strerror.im_func: 'LL_os_strerror', impl.ll_os_system.im_func: 'LL_os_system', impl.ll_os_unlink.im_func: 'LL_os_unlink', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 15:54:46 2007 @@ -57,7 +57,7 @@ #endif void LL_os__exit(long status); -static int geterrno(void) +static int geterrno(void) /* XXX only for rpython.rctypes, kill me */ { return errno; } @@ -69,10 +69,6 @@ #include "ll_osdefs.h" -int LL_os_isatty(long fd) { - return isatty((int)fd); -} - RPyString *LL_os_strerror(int errnum) { char *res; res = strerror(errnum); From arigo at codespeak.net Thu Aug 16 15:59:07 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 15:59:07 +0200 (CEST) Subject: [pypy-svn] r45722 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816135907.DE3D08173@code0.codespeak.net> Author: arigo Date: Thu Aug 16 15:59:07 2007 New Revision: 45722 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.strerror()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 15:59:07 2007 @@ -151,7 +151,6 @@ # external function declarations posix = __import__(os.name) declare(os.system , int , 'll_os/system') -declare(os.strerror , str , 'll_os/strerror') declare(os.unlink , noneannotation, 'll_os/unlink') declare(os.chdir , noneannotation, 'll_os/chdir') declare(os.mkdir , noneannotation, 'll_os/mkdir') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 15:59:07 2007 @@ -616,6 +616,19 @@ self.register(os.isatty, [int], bool, llimpl=isatty_lltypeimpl, export_name="ll_os.ll_os_isatty") + @registering(os.strerror) + def register_os_strerror(self): + os_strerror = rffi.llexternal('strerror', [rffi.INT], rffi.CCHARP) + + def strerror_lltypeimpl(errnum): + res = os_strerror(rffi.cast(rffi.INT, errnum)) + if not res: + raise ValueError("os_strerror failed") + return rffi.charp2str(res) + + self.register(os.strerror, [int], str, llimpl=strerror_lltypeimpl, + export_name="ll_os.ll_os_strerror") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -705,10 +718,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_strerror(cls, errnum): - return cls.to_rstr(os.strerror(errnum)) - ll_os_strerror.suggested_primitive = True - def ll_os_system(cls, cmd): return os.system(cls.from_rstr(cmd)) ll_os_system.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 15:59:07 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_strerror.im_func: 'LL_os_strerror', impl.ll_os_system.im_func: 'LL_os_system', impl.ll_os_unlink.im_func: 'LL_os_unlink', impl.ll_os_chdir.im_func: 'LL_os_chdir', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 15:59:07 2007 @@ -39,7 +39,6 @@ /* prototypes */ int LL_os_isatty(long fd); -RPyString *LL_os_strerror(int errnum); long LL_os_system(RPyString * fname); void LL_os_unlink(RPyString * fname); void LL_os_chdir(RPyString * path); @@ -69,17 +68,6 @@ #include "ll_osdefs.h" -RPyString *LL_os_strerror(int errnum) { - char *res; - res = strerror(errnum); - if (res == NULL) { - RPyRaiseSimpleException(PyExc_ValueError, - "strerror() argument out of range"); - return NULL; - } - return RPyString_FromString(res); -} - long LL_os_system(RPyString * fname) { return system(RPyString_AsString(fname)); } From arigo at codespeak.net Thu Aug 16 16:04:44 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:04:44 +0200 (CEST) Subject: [pypy-svn] r45723 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src translator/c/test Message-ID: <20070816140444.89317815F@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:04:43 2007 New Revision: 45723 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: os.system()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:04:43 2007 @@ -150,7 +150,6 @@ # external function declarations posix = __import__(os.name) -declare(os.system , int , 'll_os/system') declare(os.unlink , noneannotation, 'll_os/unlink') declare(os.chdir , noneannotation, 'll_os/chdir') declare(os.mkdir , noneannotation, 'll_os/mkdir') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:04:43 2007 @@ -629,6 +629,19 @@ self.register(os.strerror, [int], str, llimpl=strerror_lltypeimpl, export_name="ll_os.ll_os_strerror") + @registering(os.system) + def register_os_system(self): + os_system = rffi.llexternal('system', [rffi.CCHARP], rffi.INT) + + def system_lltypeimpl(command): + l_command = rffi.str2charp(command) + res = os_system(l_command) + rffi.free_charp(l_command) + return res + + self.register(os.system, [str], int, llimpl=system_lltypeimpl, + export_name="ll_os.ll_os_system") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -718,10 +731,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_system(cls, cmd): - return os.system(cls.from_rstr(cmd)) - ll_os_system.suggested_primitive = True - def ll_os_unlink(cls, path): os.unlink(cls.from_rstr(path)) ll_os_unlink.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:04:43 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_system.im_func: 'LL_os_system', impl.ll_os_unlink.im_func: 'LL_os_unlink', impl.ll_os_chdir.im_func: 'LL_os_chdir', impl.ll_os_mkdir.im_func: 'LL_os_mkdir', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:04:43 2007 @@ -68,10 +68,6 @@ #include "ll_osdefs.h" -long LL_os_system(RPyString * fname) { - return system(RPyString_AsString(fname)); -} - void LL_os_unlink(RPyString * fname) { int error = unlink(RPyString_AsString(fname)); if (error != 0) { Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Thu Aug 16 16:04:43 2007 @@ -225,6 +225,13 @@ res = f1() assert res == os.strerror(2) +def test_system(): + def does_stuff(cmd): + return os.system(cmd) + f1 = compile(does_stuff, [str]) + res = f1("echo hello") + assert res == 0 + def test_math_pow(): import math def fn(x, y): From arigo at codespeak.net Thu Aug 16 16:06:43 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:06:43 +0200 (CEST) Subject: [pypy-svn] r45724 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816140643.3EDEF8164@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:06:42 2007 New Revision: 45724 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.unlink()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:06:42 2007 @@ -150,7 +150,6 @@ # external function declarations posix = __import__(os.name) -declare(os.unlink , noneannotation, 'll_os/unlink') declare(os.chdir , noneannotation, 'll_os/chdir') declare(os.mkdir , noneannotation, 'll_os/mkdir') declare(os.rmdir , noneannotation, 'll_os/rmdir') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:06:42 2007 @@ -642,6 +642,20 @@ self.register(os.system, [str], int, llimpl=system_lltypeimpl, export_name="ll_os.ll_os_system") + @registering(os.unlink) + def register_os_unlink(self): + os_unlink = rffi.llexternal('unlink', [rffi.CCHARP], rffi.INT) + + def unlink_lltypeimpl(pathname): + l_pathname = rffi.str2charp(pathname) + res = os_unlink(l_pathname) + rffi.free_charp(l_pathname) + if res < 0: + raise OSError(rffi.get_errno(), "os_unlink failed") + + self.register(os.unlink, [str], s_None, llimpl=unlink_lltypeimpl, + export_name="ll_os.ll_os_unlink") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -731,10 +745,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_unlink(cls, path): - os.unlink(cls.from_rstr(path)) - ll_os_unlink.suggested_primitive = True - def ll_os_chdir(cls, path): os.chdir(cls.from_rstr(path)) ll_os_chdir.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:06:42 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_unlink.im_func: 'LL_os_unlink', impl.ll_os_chdir.im_func: 'LL_os_chdir', impl.ll_os_mkdir.im_func: 'LL_os_mkdir', impl.ll_os_rmdir.im_func: 'LL_os_rmdir', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:06:42 2007 @@ -68,13 +68,6 @@ #include "ll_osdefs.h" -void LL_os_unlink(RPyString * fname) { - int error = unlink(RPyString_AsString(fname)); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} - void LL_os_chdir(RPyString * path) { int error = chdir(RPyString_AsString(path)); if (error != 0) { From arigo at codespeak.net Thu Aug 16 16:15:02 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:15:02 +0200 (CEST) Subject: [pypy-svn] r45725 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816141502.B27308164@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:15:01 2007 New Revision: 45725 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.chdir()... os.mkdir()... os.rmdir()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:15:01 2007 @@ -150,9 +150,6 @@ # external function declarations posix = __import__(os.name) -declare(os.chdir , noneannotation, 'll_os/chdir') -declare(os.mkdir , noneannotation, 'll_os/mkdir') -declare(os.rmdir , noneannotation, 'll_os/rmdir') if hasattr(posix, 'unsetenv'): # note: faked in os declare(os.unsetenv , noneannotation, 'll_os/unsetenv') declare(os.chmod , noneannotation, 'll_os/chmod') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:15:01 2007 @@ -656,6 +656,69 @@ self.register(os.unlink, [str], s_None, llimpl=unlink_lltypeimpl, export_name="ll_os.ll_os_unlink") + @registering(os.chdir) + def register_os_chdir(self): + if sys.platform.startswith('win'): + INCLUDES = [] + else: + INCLUDES = ['unistd.h'] + os_chdir = rffi.llexternal('chdir', [rffi.CCHARP], rffi.INT, + includes=INCLUDES) + + def chdir_lltypeimpl(path): + l_path = rffi.str2charp(path) + res = os_chdir(l_path) + rffi.free_charp(l_path) + if res < 0: + raise OSError(rffi.get_errno(), "os_chdir failed") + + self.register(os.chdir, [str], s_None, llimpl=chdir_lltypeimpl, + export_name="ll_os.ll_os_chdir") + + @registering(os.mkdir) + def register_os_mkdir(self): + if os.name == 'nt': + INCLUDES = [] + ARG2 = [] # no 'mode' argument on Windows + arg2 = [] + else: + INCLUDES = ['sys/stat.h', 'sys/types.h'] + ARG2 = [rffi.MODE_T] + arg2 = [int] + os_mkdir = rffi.llexternal('mkdir', [rffi.CCHARP]+ARG2, rffi.INT, + includes=INCLUDES) + + def mkdir_lltypeimpl(pathname, *opt_mode): + l_pathname = rffi.str2charp(pathname) + if opt_mode: + opt_mode = (rffi.cast(rffi.MODE_T, opt_mode[0]),) + res = os_mkdir(l_pathname, *opt_mode) + rffi.free_charp(l_pathname) + if res < 0: + raise OSError(rffi.get_errno(), "os_mkdir failed") + + self.register(os.mkdir, [str]+arg2, s_None, llimpl=mkdir_lltypeimpl, + export_name="ll_os.ll_os_mkdir") + + @registering(os.rmdir) + def register_os_rmdir(self): + if sys.platform.startswith('win'): + INCLUDES = [] + else: + INCLUDES = ['unistd.h'] + os_rmdir = rffi.llexternal('rmdir', [rffi.CCHARP], rffi.INT, + includes=INCLUDES) + + def rmdir_lltypeimpl(pathname): + l_pathname = rffi.str2charp(pathname) + res = os_rmdir(l_pathname) + rffi.free_charp(l_pathname) + if res < 0: + raise OSError(rffi.get_errno(), "os_rmdir failed") + + self.register(os.rmdir, [str], s_None, llimpl=rmdir_lltypeimpl, + export_name="ll_os.ll_os_rmdir") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -745,18 +808,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_chdir(cls, path): - os.chdir(cls.from_rstr(path)) - ll_os_chdir.suggested_primitive = True - - def ll_os_mkdir(cls, path, mode): - os.mkdir(cls.from_rstr(path), mode) - ll_os_mkdir.suggested_primitive = True - - def ll_os_rmdir(cls, path): - os.rmdir(cls.from_rstr(path)) - ll_os_rmdir.suggested_primitive = True - def ll_os_chmod(cls, path, mode): os.chmod(cls.from_rstr(path), mode) ll_os_chmod.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:15:01 2007 @@ -20,9 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_chdir.im_func: 'LL_os_chdir', - impl.ll_os_mkdir.im_func: 'LL_os_mkdir', - impl.ll_os_rmdir.im_func: 'LL_os_rmdir', impl.ll_os_chmod.im_func: 'LL_os_chmod', impl.ll_os_rename.im_func: 'LL_os_rename', impl.ll_os_umask.im_func: 'LL_os_umask', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:15:01 2007 @@ -68,32 +68,6 @@ #include "ll_osdefs.h" -void LL_os_chdir(RPyString * path) { - int error = chdir(RPyString_AsString(path)); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} - -void LL_os_mkdir(RPyString * path, int mode) { -#if defined(MS_WIN64) || defined(MS_WINDOWS) - /* no mode support on Windows */ - int error = mkdir(RPyString_AsString(path)); -#else - int error = mkdir(RPyString_AsString(path), mode); -#endif - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} - -void LL_os_rmdir(RPyString * path) { - int error = rmdir(RPyString_AsString(path)); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} - void LL_os_chmod(RPyString * path, int mode) { int error = chmod(RPyString_AsString(path), mode); if (error != 0) { From arigo at codespeak.net Thu Aug 16 16:17:58 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:17:58 +0200 (CEST) Subject: [pypy-svn] r45726 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816141758.3F60B8166@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:17:57 2007 New Revision: 45726 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.chmod()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:17:57 2007 @@ -150,9 +150,6 @@ # external function declarations posix = __import__(os.name) -if hasattr(posix, 'unsetenv'): # note: faked in os - declare(os.unsetenv , noneannotation, 'll_os/unsetenv') -declare(os.chmod , noneannotation, 'll_os/chmod') declare(os.rename , noneannotation, 'll_os/rename') declare(os.umask , int , 'll_os/umask') declare(os._exit , noneannotation, 'll_os/_exit') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:17:57 2007 @@ -719,6 +719,27 @@ self.register(os.rmdir, [str], s_None, llimpl=rmdir_lltypeimpl, export_name="ll_os.ll_os_rmdir") + @registering(os.chmod) + def register_os_chmod(self): + if os.name == 'nt': + INCLUDES = [] + MODE_T = rffi.INT + else: + INCLUDES = ['sys/stat.h', 'sys/types.h'] + MODE_T = rffi.MODE_T + os_chmod = rffi.llexternal('chmod', [rffi.CCHARP, MODE_T], rffi.INT, + includes=INCLUDES) + + def chmod_lltypeimpl(path, mode): + l_path = rffi.str2charp(path) + res = os_chmod(l_path, rffi.cast(MODE_T, mode)) + rffi.free_charp(l_path) + if res < 0: + raise OSError(rffi.get_errno(), "os_chmod failed") + + self.register(os.chmod, [str, int], s_None, llimpl=chmod_lltypeimpl, + export_name="ll_os.ll_os_chmod") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -808,10 +829,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_chmod(cls, path, mode): - os.chmod(cls.from_rstr(path), mode) - ll_os_chmod.suggested_primitive = True - def ll_os_rename(cls, path1, path2): os.rename(cls.from_rstr(path1), cls.from_rstr(path2)) ll_os_rename.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:17:57 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_chmod.im_func: 'LL_os_chmod', impl.ll_os_rename.im_func: 'LL_os_rename', impl.ll_os_umask.im_func: 'LL_os_umask', impl.ll_os_kill.im_func: 'LL_os_kill', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:17:57 2007 @@ -68,13 +68,6 @@ #include "ll_osdefs.h" -void LL_os_chmod(RPyString * path, int mode) { - int error = chmod(RPyString_AsString(path), mode); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} - void LL_os_rename(RPyString * path1, RPyString * path2) { int error = rename(RPyString_AsString(path1), RPyString_AsString(path2)); if (error != 0) { From arigo at codespeak.net Thu Aug 16 16:19:34 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:19:34 +0200 (CEST) Subject: [pypy-svn] r45727 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816141934.D4CFF8169@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:19:34 2007 New Revision: 45727 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.rename()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:19:34 2007 @@ -150,7 +150,6 @@ # external function declarations posix = __import__(os.name) -declare(os.rename , noneannotation, 'll_os/rename') declare(os.umask , int , 'll_os/umask') declare(os._exit , noneannotation, 'll_os/_exit') if hasattr(os, 'kill'): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:19:34 2007 @@ -740,6 +740,23 @@ self.register(os.chmod, [str, int], s_None, llimpl=chmod_lltypeimpl, export_name="ll_os.ll_os_chmod") + @registering(os.rename) + def register_os_rename(self): + os_rename = rffi.llexternal('rename', [rffi.CCHARP, rffi.CCHARP], + rffi.INT) + + def rename_lltypeimpl(oldpath, newpath): + l_oldpath = rffi.str2charp(oldpath) + l_newpath = rffi.str2charp(newpath) + res = os_rename(l_oldpath, l_newpath) + rffi.free_charp(l_newpath) + rffi.free_charp(l_oldpath) + if res < 0: + raise OSError(rffi.get_errno(), "os_rename failed") + + self.register(os.rename, [str, str], s_None, llimpl=rename_lltypeimpl, + export_name="ll_os.ll_os_rename") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -829,10 +846,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_rename(cls, path1, path2): - os.rename(cls.from_rstr(path1), cls.from_rstr(path2)) - ll_os_rename.suggested_primitive = True - def ll_os_umask(cls, mask): return os.umask(mask) ll_os_umask.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:19:34 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_rename.im_func: 'LL_os_rename', impl.ll_os_umask.im_func: 'LL_os_umask', impl.ll_os_kill.im_func: 'LL_os_kill', impl.ll_os_link.im_func: 'LL_os_link', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:19:34 2007 @@ -68,13 +68,6 @@ #include "ll_osdefs.h" -void LL_os_rename(RPyString * path1, RPyString * path2) { - int error = rename(RPyString_AsString(path1), RPyString_AsString(path2)); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} - int LL_os_umask(int mode) { return umask(mode); } From arigo at codespeak.net Thu Aug 16 16:21:08 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:21:08 +0200 (CEST) Subject: [pypy-svn] r45728 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816142108.062BB8168@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:21:08 2007 New Revision: 45728 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.umask()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:21:08 2007 @@ -150,7 +150,6 @@ # external function declarations posix = __import__(os.name) -declare(os.umask , int , 'll_os/umask') declare(os._exit , noneannotation, 'll_os/_exit') if hasattr(os, 'kill'): declare(os.kill , noneannotation, 'll_os/kill') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:21:08 2007 @@ -757,6 +757,21 @@ self.register(os.rename, [str, str], s_None, llimpl=rename_lltypeimpl, export_name="ll_os.ll_os_rename") + @registering(os.umask) + def register_os_umask(self): + if os.name == 'nt': + mode_t = rffi.INT + else: + mode_t = rffi.MODE_T + os_umask = rffi.llexternal('umask', [mode_t], mode_t) + + def umask_lltypeimpl(fd): + res = os_umask(rffi.cast(mode_t, fd)) + return rffi.cast(lltype.Signed, res) + + self.register(os.umask, [int], int, llimpl=umask_lltypeimpl, + export_name="ll_os.ll_os_umask") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -846,10 +861,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_umask(cls, mask): - return os.umask(mask) - ll_os_umask.suggested_primitive = True - def ll_os_kill(cls, pid, sig): os.kill(pid, sig) ll_os_kill.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:21:08 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_umask.im_func: 'LL_os_umask', impl.ll_os_kill.im_func: 'LL_os_kill', impl.ll_os_link.im_func: 'LL_os_link', impl.ll_os_symlink.im_func: 'LL_os_symlink', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:21:08 2007 @@ -68,10 +68,6 @@ #include "ll_osdefs.h" -int LL_os_umask(int mode) { - return umask(mode); -} - #ifdef HAVE_KILL void LL_os_kill(int pid, int sig) { int error = kill(pid, sig); From arigo at codespeak.net Thu Aug 16 16:27:23 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:27:23 +0200 (CEST) Subject: [pypy-svn] r45729 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src translator/c/test Message-ID: <20070816142723.2C1288169@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:27:20 2007 New Revision: 45729 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: os.kill()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:27:20 2007 @@ -151,8 +151,6 @@ # external function declarations posix = __import__(os.name) declare(os._exit , noneannotation, 'll_os/_exit') -if hasattr(os, 'kill'): - declare(os.kill , noneannotation, 'll_os/kill') if hasattr(os, 'link'): declare(os.link , noneannotation, 'll_os/link') if hasattr(os, 'symlink'): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:27:20 2007 @@ -772,6 +772,22 @@ self.register(os.umask, [int], int, llimpl=umask_lltypeimpl, export_name="ll_os.ll_os_umask") + if hasattr(os, 'kill'): + @registering(os.kill) + def register_os_kill(self): + os_kill = rffi.llexternal('kill', [rffi.PID_T, rffi.INT], + rffi.INT, + includes=['sys/types.h', 'signal.h']) + + def kill_lltypeimpl(pid, sig): + res = os_kill(rffi.cast(rffi.PID_T, pid), + rffi.cast(rffi.INT, sig)) + if res < 0: + raise OSError(rffi.get_errno(), "os_kill failed") + + self.register(os.kill, [int, int], s_None, llimpl=kill_lltypeimpl, + export_name="ll_os.ll_os_kill") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -861,10 +877,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_kill(cls, pid, sig): - os.kill(pid, sig) - ll_os_kill.suggested_primitive = True - def ll_os_link(cls, path1, path2): os.link(cls.from_rstr(path1), cls.from_rstr(path2)) ll_os_link.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:27:20 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_kill.im_func: 'LL_os_kill', impl.ll_os_link.im_func: 'LL_os_link', impl.ll_os_symlink.im_func: 'LL_os_symlink', impl.ll_os_fork.im_func: 'LL_os_fork', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:27:20 2007 @@ -68,15 +68,6 @@ #include "ll_osdefs.h" -#ifdef HAVE_KILL -void LL_os_kill(int pid, int sig) { - int error = kill(pid, sig); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} -#endif - #ifdef HAVE_FILESYSTEM_WITH_LINKS void LL_os_link(RPyString * path1, RPyString * path2) { Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Thu Aug 16 16:27:20 2007 @@ -641,6 +641,22 @@ status1 = f1() assert os.WIFEXITED(status1) assert os.WEXITSTATUS(status1) == 4 + if hasattr(os, 'kill'): + def test_kill(): + import signal + def does_stuff(): + pid = os.fork() + if pid == 0: # child + time.sleep(5) + os._exit(4) + os.kill(pid, signal.SIGTERM) # in the parent + pid1, status1 = os.waitpid(pid, 0) + assert pid1 == pid + return status1 + f1 = compile(does_stuff, []) + status1 = f1() + assert os.WIFSIGNALED(status1) + assert os.WTERMSIG(status1) == signal.SIGTERM elif hasattr(os, 'waitpid'): # windows has no fork but some waitpid to be emulated def test_waitpid(): From arigo at codespeak.net Thu Aug 16 16:32:52 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:32:52 +0200 (CEST) Subject: [pypy-svn] r45730 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816143252.6EA658169@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:32:52 2007 New Revision: 45730 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.link()... os.symlink()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:32:52 2007 @@ -151,10 +151,6 @@ # external function declarations posix = __import__(os.name) declare(os._exit , noneannotation, 'll_os/_exit') -if hasattr(os, 'link'): - declare(os.link , noneannotation, 'll_os/link') -if hasattr(os, 'symlink'): - declare(os.symlink , noneannotation, 'll_os/symlink') if hasattr(os, 'fork'): declare(os.fork , int, 'll_os/fork') if hasattr(os, 'spawnv'): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:32:52 2007 @@ -788,6 +788,45 @@ self.register(os.kill, [int, int], s_None, llimpl=kill_lltypeimpl, export_name="ll_os.ll_os_kill") + if hasattr(os, 'link'): + @registering(os.link) + def register_os_link(self): + os_link = rffi.llexternal('link', [rffi.CCHARP, rffi.CCHARP], + rffi.INT, + includes = ['unistd.h']) + + def link_lltypeimpl(oldpath, newpath): + l_oldpath = rffi.str2charp(oldpath) + l_newpath = rffi.str2charp(newpath) + res = os_link(l_oldpath, l_newpath) + rffi.free_charp(l_newpath) + rffi.free_charp(l_oldpath) + if res < 0: + raise OSError(rffi.get_errno(), "os_link failed") + + self.register(os.link, [str, str], s_None, llimpl=link_lltypeimpl, + export_name="ll_os.ll_os_link") + + if hasattr(os, 'symlink'): + @registering(os.symlink) + def register_os_symlink(self): + os_symlink = rffi.llexternal('symlink', [rffi.CCHARP, rffi.CCHARP], + rffi.INT, + includes = ['unistd.h']) + + def symlink_lltypeimpl(oldpath, newpath): + l_oldpath = rffi.str2charp(oldpath) + l_newpath = rffi.str2charp(newpath) + res = os_symlink(l_oldpath, l_newpath) + rffi.free_charp(l_newpath) + rffi.free_charp(l_oldpath) + if res < 0: + raise OSError(rffi.get_errno(), "os_symlink failed") + + self.register(os.symlink, [str, str], s_None, + llimpl=symlink_lltypeimpl, + export_name="ll_os.ll_os_symlink") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -877,14 +916,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_link(cls, path1, path2): - os.link(cls.from_rstr(path1), cls.from_rstr(path2)) - ll_os_link.suggested_primitive = True - - def ll_os_symlink(cls, path1, path2): - os.symlink(cls.from_rstr(path1), cls.from_rstr(path2)) - ll_os_symlink.suggested_primitive = True - def ll_os_fork(cls): return os.fork() ll_os_fork.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:32:52 2007 @@ -20,8 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_link.im_func: 'LL_os_link', - impl.ll_os_symlink.im_func: 'LL_os_symlink', impl.ll_os_fork.im_func: 'LL_os_fork', impl.ll_os_spawnv.im_func: 'LL_os_spawnv', impl.ll_os__exit.im_func: 'LL_os__exit', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:32:52 2007 @@ -22,34 +22,11 @@ #endif #endif /* MAXPATHLEN */ -/* The functions below are mapped to functions from pypy.rpython.module.* - by the pypy.translator.c.extfunc.EXTERNALS dictionary. - They should correspond to the functions with the suggested_primitive - flag set, and NOT necessarily directly to the ll_os_*() functions. - See for example ll_read_into(), which is called by ll_os_read(). - The latter would be messy to write here, but LL_read_into() is quite easy. +/* NOTE NOTE NOTE: This whole file is going away... */ - -#if !(defined(MS_WIN64) || defined(MS_WINDOWS)) -# define HAVE_FILESYSTEM_WITH_LINKS -#endif - - /* prototypes */ -int LL_os_isatty(long fd); -long LL_os_system(RPyString * fname); -void LL_os_unlink(RPyString * fname); -void LL_os_chdir(RPyString * path); -void LL_os_mkdir(RPyString * path, int mode); -void LL_os_rmdir(RPyString * path); -void LL_os_chmod(RPyString * path, int mode); -void LL_os_rename(RPyString * path1, RPyString * path2); -int LL_os_umask(int mode); -void LL_os_kill(int pid, int sig); -void LL_os_link(RPyString * path1, RPyString * path2); -void LL_os_symlink(RPyString * path1, RPyString * path2); long LL_os_fork(void); #if defined(HAVE_SPAWNV) && defined(HAVE_RPY_LIST_OF_STRING) /* argh */ long LL_os_spawnv(int mode, RPyString *path, RPyListOfString *args); @@ -68,23 +45,6 @@ #include "ll_osdefs.h" -#ifdef HAVE_FILESYSTEM_WITH_LINKS - -void LL_os_link(RPyString * path1, RPyString * path2) { - int error = link(RPyString_AsString(path1), RPyString_AsString(path2)); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} - -void LL_os_symlink(RPyString * path1, RPyString * path2) { - int error = symlink(RPyString_AsString(path1), RPyString_AsString(path2)); - if (error != 0) { - RPYTHON_RAISE_OSERROR(errno); - } -} -#endif - #ifdef HAVE_FORK long LL_os_fork(void) { int pid = fork(); From arigo at codespeak.net Thu Aug 16 16:34:59 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:34:59 +0200 (CEST) Subject: [pypy-svn] r45731 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src Message-ID: <20070816143459.CF21C813E@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:34:59 2007 New Revision: 45731 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os.fork()... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:34:59 2007 @@ -151,8 +151,6 @@ # external function declarations posix = __import__(os.name) declare(os._exit , noneannotation, 'll_os/_exit') -if hasattr(os, 'fork'): - declare(os.fork , int, 'll_os/fork') if hasattr(os, 'spawnv'): declare(os.spawnv, int, 'll_os/spawnv') #if hasattr(os, 'execv'): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:34:59 2007 @@ -827,6 +827,21 @@ llimpl=symlink_lltypeimpl, export_name="ll_os.ll_os_symlink") + if hasattr(os, 'fork'): + @registering(os.fork) + def register_os_fork(self): + os_fork = rffi.llexternal('fork', [], rffi.PID_T, + includes = ['sys/types.h', 'unistd.h']) + + def fork_lltypeimpl(): + childpid = os_fork() + if childpid == -1: + raise OSError(rffi.get_errno(), "os_fork failed") + return rffi.cast(lltype.Signed, childpid) + + self.register(os.fork, [], int, llimpl=fork_lltypeimpl, + export_name="ll_os.ll_os_fork") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -916,10 +931,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_fork(cls): - return os.fork() - ll_os_fork.suggested_primitive = True - def ll_os_spawnv(cls, mode, path, args): return os.spawnv(mode, path, args) ll_os_spawnv.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:34:59 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_fork.im_func: 'LL_os_fork', impl.ll_os_spawnv.im_func: 'LL_os_spawnv', impl.ll_os__exit.im_func: 'LL_os__exit', ll_time.ll_time_clock: 'LL_time_clock', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:34:59 2007 @@ -27,7 +27,6 @@ /* prototypes */ -long LL_os_fork(void); #if defined(HAVE_SPAWNV) && defined(HAVE_RPY_LIST_OF_STRING) /* argh */ long LL_os_spawnv(int mode, RPyString *path, RPyListOfString *args); #endif @@ -45,15 +44,6 @@ #include "ll_osdefs.h" -#ifdef HAVE_FORK -long LL_os_fork(void) { - int pid = fork(); - if (pid == -1) - RPYTHON_RAISE_OSERROR(errno); - return pid; -} -#endif - /* The following code is only generated if spawnv exists and if RPyListOfString exists. The latter is a bit tricky: From arigo at codespeak.net Thu Aug 16 16:46:49 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:46:49 +0200 (CEST) Subject: [pypy-svn] r45732 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c translator/c/src translator/c/test Message-ID: <20070816144649.AC514816F@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:46:47 2007 New Revision: 45732 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: os.spawnv()... with a new test which I cannot run on Linux, so well, untested Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:46:47 2007 @@ -149,13 +149,7 @@ return SomeString(can_be_None=True) # external function declarations -posix = __import__(os.name) declare(os._exit , noneannotation, 'll_os/_exit') -if hasattr(os, 'spawnv'): - declare(os.spawnv, int, 'll_os/spawnv') -#if hasattr(os, 'execv'): -# declare(os.execv, noneannotation, 'll_os/execv') -# declare(os.execve, noneannotation, 'll_os/execve') declare(os.path.exists, bool , 'll_os_path/exists') declare(os.path.isdir, bool , 'll_os_path/isdir') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:46:47 2007 @@ -17,6 +17,7 @@ from pypy.rpython.lltypesystem import rffi from pypy.rpython.lltypesystem.rffi import platform from pypy.rpython.lltypesystem import lltype +posix = __import__(os.name) class RegisterOs(BaseLazyRegistering): UNISTD_INCL = ['unistd.h', 'sys/types.h'] @@ -54,6 +55,27 @@ self.register(os.execv, [str, [str]], s_ImpossibleValue, llimpl= execv_lltypeimpl, export_name="ll_os.ll_os_execv") + if hasattr(posix, 'spawnv'): + @registering(os.spawnv) + def register_os_spawnv(self): + os_spawnv = rffi.llexternal('spawnv', + [rffi.INT, rffi.CCHARP, rffi.CCHARPP], + rffi.INT) + + def spawnv_lltypeimpl(mode, path, args): + mode = rffi.cast(rffi.INT, mode) + l_path = rffi.str2charp(path) + l_args = rffi.liststr2charpp(args) + childpid = os_spawnv(mode, l_path, l_args) + rffi.free_charpp(l_args) + rffi.free_charp(l_path) + if childpid == -1: + raise OSError(rffi.get_errno(), "os_spawnv failed") + return rffi.cast(lltype.Signed, childpid) + + self.register(os.spawnv, [int, str, [str]], int, llimpl= + spawnv_lltypeimpl, export_name="ll_os.ll_os_spawnv") + @registering(os.dup) def register_os_dup(self): os_dup = rffi.llexternal('dup', [rffi.INT], rffi.INT) @@ -931,10 +953,6 @@ # XXX deprecated style, this is all waiting to be converted to rffi __metaclass__ = ClassMethods - def ll_os_spawnv(cls, mode, path, args): - return os.spawnv(mode, path, args) - ll_os_spawnv.suggested_primitive = True - def ll_os__exit(cls, status): os._exit(status) ll_os__exit.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:46:47 2007 @@ -20,7 +20,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os_spawnv.im_func: 'LL_os_spawnv', impl.ll_os__exit.im_func: 'LL_os__exit', ll_time.ll_time_clock: 'LL_time_clock', ll_time.ll_time_sleep: 'LL_time_sleep', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:46:47 2007 @@ -27,9 +27,6 @@ /* prototypes */ -#if defined(HAVE_SPAWNV) && defined(HAVE_RPY_LIST_OF_STRING) /* argh */ -long LL_os_spawnv(int mode, RPyString *path, RPyListOfString *args); -#endif void LL_os__exit(long status); static int geterrno(void) /* XXX only for rpython.rctypes, kill me */ @@ -44,33 +41,6 @@ #include "ll_osdefs.h" -/* - The following code is only generated if spawnv exists and - if RPyListOfString exists. The latter is a bit tricky: - The RPyListOfString is necessary to correctly declare this function. - For this to work, the test code must be properly written in a way - that RPyListOfString is really annotated as such. - Please see the test in test_extfunc.py - creating the correct - argument string type is not obvious and error prone. - */ -#if defined(HAVE_SPAWNV) && defined(HAVE_RPY_LIST_OF_STRING) -long LL_os_spawnv(int mode, RPyString *path, RPyListOfString *args) { - int pid, i, nargs = args->l_length; - char **slist = malloc((nargs+1) * sizeof(char*)); - pid = -1; - if (slist) { - for (i=0; il_items->items[i]); - slist[nargs] = NULL; - pid = spawnv(mode, RPyString_AsString(path), slist); - free(slist); - } - if (pid == -1) - RPYTHON_RAISE_OSERROR(errno); - return pid; -} -#endif - void LL_os__exit(long status) { _exit((int)status); } Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Thu Aug 16 16:46:47 2007 @@ -870,6 +870,18 @@ func() assert open(filename).read() == "42" +if hasattr(posix, 'spawnv'): + def test_spawnv(): + filename = str(udir.join('test_spawnv.txt')) + progname = str(sys.executable) + def does_stuff(): + l = [progname, '-c', 'open("%s","w").write("2")' % filename] + pid = os.spawnv(os.P_NOWAIT, progname, l) + os.waitpid(pid, 0) + func = compile(does_stuff, []) + func() + assert open(filename).read() == "2" + def test_utime(): # XXX utimes & float support path = str(udir.ensure("test_utime.txt")) From arigo at codespeak.net Thu Aug 16 16:56:09 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:56:09 +0200 (CEST) Subject: [pypy-svn] r45733 - pypy/branch/pypy-more-rtti-inprogress/rpython/module/test Message-ID: <20070816145609.C6CD88165@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:56:09 2007 New Revision: 45733 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py Log: Forgot to fix these tests. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py Thu Aug 16 16:56:09 2007 @@ -1,10 +1,8 @@ import os from pypy.tool.udir import udir -from pypy.tool.pytest.modcheck import skipimporterror from pypy.translator.c.test.test_genc import compile from pypy.rpython import extregistry -from pypy.rpython.lltypesystem.module.ll_os import Implementation as impl import sys import py @@ -26,13 +24,13 @@ assert data == os.getcwd() def test_strerror(): - data = impl.ll_os_strerror(2) - assert impl.from_rstr(data) == os.strerror(2) + data = getllimpl(os.strerror)(2) + assert data == os.strerror(2) def test_system(): filename = str(udir.join('test_system.txt')) - arg = impl.to_rstr('python -c "print 1+1" > %s' % filename) - data = impl.ll_os_system(arg) + arg = 'python -c "print 1+1" > %s' % filename + data = getllimpl(os.system)(arg) assert data == 0 assert file(filename).read().strip() == '2' os.unlink(filename) From arigo at codespeak.net Thu Aug 16 16:56:52 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 16:56:52 +0200 (CEST) Subject: [pypy-svn] r45734 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/lltypesystem/module rpython/module rpython/ootypesystem/module translator/c translator/c/src Message-ID: <20070816145652.AB9EA8165@code0.codespeak.net> Author: arigo Date: Thu Aug 16 16:56:52 2007 New Revision: 45734 Removed: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_osdefs.h Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Log: os._exit(). That was the last one, kill a couple of unnecessary files, yay! Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Thu Aug 16 16:56:52 2007 @@ -149,8 +149,6 @@ return SomeString(can_be_None=True) # external function declarations -declare(os._exit , noneannotation, 'll_os/_exit') - declare(os.path.exists, bool , 'll_os_path/exists') declare(os.path.isdir, bool , 'll_os_path/isdir') declare(time.time , float , 'll_time/time') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 16:56:52 2007 @@ -10,7 +10,6 @@ from pypy.rpython.module.support import to_opaque_object, from_opaque_object from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.rarithmetic import r_longlong -from pypy.tool.staticmethods import ClassMethods from pypy.rpython.extfunc import BaseLazyRegistering, registering from pypy.annotation.model import SomeInteger, SomeString, SomeTuple, SomeFloat from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool @@ -864,6 +863,16 @@ self.register(os.fork, [], int, llimpl=fork_lltypeimpl, export_name="ll_os.ll_os_fork") + @registering(os._exit) + def register_os__exit(self): + os__exit = rffi.llexternal('_exit', [rffi.INT], lltype.Void) + + def _exit_lltypeimpl(status): + os__exit(rffi.cast(rffi.INT, status)) + + self.register(os._exit, [int], s_None, llimpl=_exit_lltypeimpl, + export_name="ll_os.ll_os__exit") + # --------------------------- os.stat & variants --------------------------- @registering(os.fstat) @@ -947,12 +956,3 @@ def getcontroller(self): from pypy.rpython.module.ll_os_environ import OsEnvironController return OsEnvironController() - - -class BaseOS: - # XXX deprecated style, this is all waiting to be converted to rffi - __metaclass__ = ClassMethods - - def ll_os__exit(cls, status): - os._exit(status) - ll_os__exit.suggested_primitive = True Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py Thu Aug 16 16:56:52 2007 @@ -1,7 +1,5 @@ # mostly-deprecated module -from pypy.rpython.module.support import OOSupport -from pypy.rpython.module.ll_os import BaseOS from pypy.rpython.ootypesystem import ootype def _make_tuple(FIELDS): @@ -11,6 +9,3 @@ return ootype.Record(fields) STAT_RESULT = _make_tuple([ootype.Signed]*10) - -class Implementation(BaseOS, OOSupport): - pass Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Thu Aug 16 16:56:52 2007 @@ -7,7 +7,6 @@ from pypy.rpython.lltypesystem import rlist from pypy.rpython.module import ll_time, ll_os from pypy.rpython.module import ll_stackless, ll_stack -from pypy.rpython.module.ll_os import BaseOS as impl from pypy.rpython.lltypesystem.module import ll_strtod try: @@ -20,7 +19,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - impl.ll_os__exit.im_func: 'LL_os__exit', ll_time.ll_time_clock: 'LL_time_clock', ll_time.ll_time_sleep: 'LL_time_sleep', ll_time.ll_time_time: 'LL_time_time', Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h Thu Aug 16 16:56:52 2007 @@ -1,48 +1,10 @@ /************************************************************/ /*** C header subsection: os module ***/ -#if !(defined(MS_WIN64) || defined(MS_WINDOWS)) -# include -# include -#endif - -#include -#include -#include -#ifndef PATH_MAX - /* assume windows */ -# define PATH_MAX 254 -#endif - -#ifndef MAXPATHLEN -#if defined(PATH_MAX) && PATH_MAX > 1024 -#define MAXPATHLEN PATH_MAX -#else -#define MAXPATHLEN 1024 -#endif -#endif /* MAXPATHLEN */ - /* NOTE NOTE NOTE: This whole file is going away... */ -/* prototypes */ - -void LL_os__exit(long status); - static int geterrno(void) /* XXX only for rpython.rctypes, kill me */ { return errno; } - - -/* implementations */ - -#ifndef PYPY_NOT_MAIN_FILE - -#include "ll_osdefs.h" - -void LL_os__exit(long status) { - _exit((int)status); -} - -#endif /* PYPY_NOT_MAIN_FILE */ From fijal at codespeak.net Thu Aug 16 17:14:03 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 17:14:03 +0200 (CEST) Subject: [pypy-svn] r45735 - in pypy/branch/pypy-more-rtti-inprogress/rpython: lltypesystem lltypesystem/test module Message-ID: <20070816151403.08E208169@code0.codespeak.net> Author: fijal Date: Thu Aug 16 17:14:03 2007 New Revision: 45735 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_termios.py Log: Rename CXxx to CXxxPtr and make Cxx return xx (CStruct now returns a struct, not a pointer to this and so on) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Thu Aug 16 17:14:03 2007 @@ -94,7 +94,16 @@ # Hack: prefix all attribute names with 'c_' to cope with names starting # with '_'. The genc backend removes the 'c_' prefixes... c_fields = [('c_' + key, value) for key, value in fields] - return lltype.Ptr(lltype.Struct(name, *c_fields, **kwds)) + return lltype.Struct(name, *c_fields, **kwds) + +def CStructPtr(*args, **kwds): + return lltype.Ptr(CStruct(*args, **kwds)) + +#def CArray(field): +# return lltype.Array(field, hints={'nolength':True}) + +#def CArrayPtr(field): +# return lltype.Ptr(CArray(fld)) def COpaque(name, hints=None, **kwds): if hints is None: @@ -109,7 +118,10 @@ result.append(size) return result[0] hints['getsize'] = lazy_getsize - return lltype.Ptr(lltype.OpaqueType(name, hints)) + return lltype.OpaqueType(name, hints) + +def COpaquePtr(*args, **kwds): + return lltype.Ptr(COpaque(*args, **kwds)) def CExternVariable(TYPE, name): """Return a pair of functions - a getter and a setter - to access Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py Thu Aug 16 17:14:03 2007 @@ -228,8 +228,8 @@ def test_opaque_obj(self): includes = ['sys/time.h', 'time.h'] - TIMEVALP = rffi.COpaque('struct timeval', includes=includes) - TIMEZONEP = rffi.COpaque('struct timezone', includes=includes) + TIMEVALP = rffi.COpaquePtr('struct timeval', includes=includes) + TIMEZONEP = rffi.COpaquePtr('struct timezone', includes=includes) gettimeofday = rffi.llexternal('gettimeofday', [TIMEVALP, TIMEZONEP], rffi.INT, includes=includes) ll_timevalp = lltype.malloc(TIMEVALP.TO, flavor='raw') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Thu Aug 16 17:14:03 2007 @@ -125,7 +125,7 @@ return (z->one + z->three); } """ - TP = CStruct('xx', ('one', Signed), ('two', Char), ('three', Signed)) + TP = CStructPtr('xx', ('one', Signed), ('two', Char), ('three', Signed)) c_file = udir.join("structxx.c") c_file.write(c_source) @@ -228,7 +228,7 @@ h_file = udir.join("opaque.h") h_file.write(h_source) - STUFFP = COpaque('struct stuff', includes=['opaque.h'], + STUFFP = COpaquePtr('struct stuff', includes=['opaque.h'], include_dirs=[str(udir)]) ll_get = llexternal('get', [STUFFP], lltype.Char, includes=['opaque.h'], @@ -248,9 +248,25 @@ import ctypes except ImportError: py.test.skip("Cannot test without ctypes") - from pypy.rpython.lltypesystem import ll2ctypes - ll2ctypes._setup_ctypes_cache() - for ll, ctp in ll2ctypes._ctypes_cache.items(): + cache = { + lltype.Signed: ctypes.c_long, + lltype.Unsigned: ctypes.c_ulong, + lltype.Char: ctypes.c_ubyte, + DOUBLE: ctypes.c_double, + SIGNEDCHAR: ctypes.c_byte, + UCHAR: ctypes.c_ubyte, + SHORT: ctypes.c_short, + USHORT: ctypes.c_ushort, + INT: ctypes.c_int, + UINT: ctypes.c_uint, + LONG: ctypes.c_long, + ULONG: ctypes.c_ulong, + LONGLONG: ctypes.c_longlong, + ULONGLONG: ctypes.c_ulonglong, + SIZE_T: ctypes.c_size_t, + } + + for ll, ctp in cache.items(): assert sizeof(ll) == ctypes.sizeof(ctp) assert not size_and_sign(lltype.Signed)[1] assert not size_and_sign(lltype.Char)[1] Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 16 17:14:03 2007 @@ -104,8 +104,8 @@ @registering(os.utime) def register_os_utime(self): TIME_T = rffi.INT # XXX do the right thing - UTIMEBUFP = rffi.CStruct('utimbuf', ('actime', TIME_T), - ('modtime', TIME_T)) + UTIMEBUFP = rffi.CStructPtr('utimbuf', ('actime', TIME_T), + ('modtime', TIME_T)) # XXX sys/types.h is not portable at all os_utime = rffi.llexternal('utime', [rffi.CCHARP, UTIMEBUFP], @@ -187,7 +187,7 @@ ('version', UTCHARP), ('machine', UTCHARP), ('domainname', UTCHARP)] - UTSNAMEP = rffi.CStruct('utsname', *fields) + UTSNAMEP = rffi.CStructPtr('utsname', *fields) os_uname = rffi.llexternal('uname', [UTSNAMEP], rffi.INT, includes=['sys/utsname.h']) @@ -485,9 +485,9 @@ XXX # FindFirstFile, FindNextFile else: INCL = ['sys/types.h', 'dirent.h'] - DIRP = rffi.COpaque('DIR', includes=INCL) + DIRP = rffi.COpaquePtr('DIR', includes=INCL) NAME_MAX = platform.intdefined('NAME_MAX', includes=INCL) - DIRENTP = rffi.CStruct('dirent', + DIRENTP = rffi.CStructPtr('dirent', ('d_name', lltype.FixedSizeArray(lltype.Char, NAME_MAX+1)), ) # XXX so far, DIRENTP cannot be handled by ll2ctypes because Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py Thu Aug 16 17:14:03 2007 @@ -20,9 +20,9 @@ if 0: #sys.platform.startswith('linux2'): # XXX assume the tv_nsec way of accessing the sub-second timestamps # XXX also assume, as in Linux, that it's in a 'struct timespec' - TIMESPEC = rffi.CStruct('timespec', - ('tv_sec', lltype.Signed), - ('tv_nsec', lltype.Signed)) + TIMESPEC = rffi.CStructPtr('timespec', + ('tv_sec', lltype.Signed), + ('tv_nsec', lltype.Signed)) ModTime = rffi.DOUBLE else: # XXX add support for more platforms @@ -120,7 +120,7 @@ else: _name_struct_stat = 'stat' INCLUDES = ['sys/types.h', 'sys/stat.h', 'unistd.h'] -STRUCT_STAT = rffi.CStruct(_name_struct_stat, *LL_STAT_FIELDS) +STRUCT_STAT = rffi.CStructPtr(_name_struct_stat, *LL_STAT_FIELDS) def build_stat_result(st): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_termios.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_termios.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_termios.py Thu Aug 16 17:14:03 2007 @@ -29,9 +29,9 @@ termios.error.__init__ = termios_error_init -TERMIOSP = rffi.CStruct('termios', ('c_iflag', TCFLAG_T), ('c_oflag', TCFLAG_T), - ('c_cflag', TCFLAG_T), ('c_lflag', TCFLAG_T), - ('c_cc', lltype.FixedSizeArray(CC_T, NCCS))) +TERMIOSP = rffi.CStructPtr('termios', ('c_iflag', TCFLAG_T), ('c_oflag', TCFLAG_T), + ('c_cflag', TCFLAG_T), ('c_lflag', TCFLAG_T), + ('c_cc', lltype.FixedSizeArray(CC_T, NCCS))) def c_external(name, args, result): return rffi.llexternal(name, args, result, includes=includes) From fijal at codespeak.net Thu Aug 16 17:49:20 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 17:49:20 +0200 (CEST) Subject: [pypy-svn] r45737 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070816154920.00EFA8164@code0.codespeak.net> Author: fijal Date: Thu Aug 16 17:49:19 2007 New Revision: 45737 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Log: Test passes Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Thu Aug 16 17:49:19 2007 @@ -198,7 +198,7 @@ name = name[7:] kwds = {'hints':{'align':info['align'], 'size':info['size']}} - return rffi.CStruct(name, *fields, **kwds).TO + return rffi.CStruct(name, *fields, **kwds) class SimpleType(CConfigEntry): """An entry in a CConfig class that stands for an externally @@ -415,20 +415,9 @@ for ctype in typeclass: if rffi.size_and_sign(ctype) == expected_size_and_sign: return ctype - xxxx - if (hasattr(fieldtype, '_length_') - and getattr(fieldtype, '_type_', None) == rffi.UCHAR): - # for now, assume it is an array of chars; otherwise we'd also - # have to check the exact integer type of the elements of the array - size, sign = expected_size_and_sign - return rffi.UCHAR * size - if (hasattr(fieldtype, '_length_') - and getattr(fieldtype, '_type_', None) == ctypes.c_ubyte): - # grumble, fields of type 'c_char array' have automatic cast-to- - # Python-string behavior in ctypes, which may not be what you - # want, so here is the same with c_ubytes instead... - size, sign = expected_size_and_sign - return ctypes.c_ubyte * size + if isinstance(fieldtype, lltype.FixedSizeArray): + size, _ = expected_size_and_sign + return lltype.FixedSizeArray(fieldtype.OF, size/_sizeof(fieldtype.OF)) raise TypeError("conflicting field type %r for %r" % (fieldtype, fieldname)) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Thu Aug 16 17:49:19 2007 @@ -173,7 +173,6 @@ assert c_y.c_x is c_x def test_array(): - py.test.skip("Next to go") dirent = rffi_platform.getstruct("struct dirent", """ struct dirent /* for this example only, not the exact dirent */ @@ -184,5 +183,5 @@ char d_name[32]; }; """, - [("d_name", rffi.CArray(rffi.CHAR).TO)]) - assert dirent.d_name.size == 32 + [("d_name", lltype.FixedSizeArray(rffi.CHAR, 1))]) + assert dirent.c_d_name.length == 32 From fijal at codespeak.net Thu Aug 16 17:51:48 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 17:51:48 +0200 (CEST) Subject: [pypy-svn] r45738 - pypy/branch/pypy-more-rtti-inprogress/rpython/tool Message-ID: <20070816155148.3684C8167@code0.codespeak.net> Author: fijal Date: Thu Aug 16 17:51:47 2007 New Revision: 45738 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Log: Kill unused code Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Thu Aug 16 17:51:47 2007 @@ -362,14 +362,6 @@ # # internal helpers -def ctype_alignment(c_type): - xxxx - if issubclass(c_type, ctypes.Structure): - return max([ctype_alignment(fld_type) - for fld_name, fld_type in c_type._fields_]) - - return ctypes.alignment(c_type) - def uniquefilepath(LAST=[0]): i = LAST[0] LAST[0] += 1 From fijal at codespeak.net Thu Aug 16 18:28:43 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 16 Aug 2007 18:28:43 +0200 (CEST) Subject: [pypy-svn] r45739 - in pypy/branch/pypy-more-rtti-inprogress/module/thread: . rpython test Message-ID: <20070816162843.BD4C6815E@code0.codespeak.net> Author: fijal Date: Thu Aug 16 18:28:42 2007 New Revision: 45739 Removed: pypy/branch/pypy-more-rtti-inprogress/module/thread/rpython/ Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/gil.py pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py pypy/branch/pypy-more-rtti-inprogress/module/thread/os_local.py pypy/branch/pypy-more-rtti-inprogress/module/thread/os_lock.py pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_thread.py pypy/branch/pypy-more-rtti-inprogress/module/thread/threadlocals.py Log: Move threads from extfunctable to rffi Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/gil.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/gil.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/gil.py Thu Aug 16 18:28:42 2007 @@ -7,11 +7,10 @@ # all but one will be blocked. The other threads get a chance to run # from time to time, using the executioncontext's XXX -import thread +from pypy.module.thread import ll_thread as thread from pypy.interpreter.miscutils import Action from pypy.module.thread.threadlocals import OSThreadLocals - class GILThreadLocals(OSThreadLocals): """A version of OSThreadLocals that enforces a GIL.""" Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py Thu Aug 16 18:28:42 2007 @@ -47,7 +47,7 @@ c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT) c_thread_get_ident = llexternal('RPyThreadGetIdent', [], lltype.Void) -TLOCKP = rffi.COpaque('struct RPyOpaque_ThreadLock', includes=includes) +TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock', includes=includes) c_thread_lock_init = llexternal('RPyThreadLockInit', [TLOCKP], lltype.Void) c_thread_acuirelock = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT], Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_local.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/os_local.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/os_local.py Thu Aug 16 18:28:42 2007 @@ -1,4 +1,4 @@ -import thread +from pypy.module.thread import ll_thread as thread from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.typedef import TypeDef, interp2app @@ -6,9 +6,6 @@ from pypy.interpreter.typedef import descr_set_dict from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments -# Force the declaration of thread.start_new_thread() & co. for RPython -import pypy.module.thread.rpython.exttable - class Local(Wrappable): """Thread-local data""" Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_lock.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/os_lock.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/os_lock.py Thu Aug 16 18:28:42 2007 @@ -2,14 +2,14 @@ Python locks, based on true threading locks provided by the OS. """ -import thread +from pypy.module.thread import ll_thread as thread from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.gateway import ObjSpace, interp2app from pypy.interpreter.typedef import TypeDef # Force the declaration of the type 'thread.LockType' for RPython -import pypy.module.thread.rpython.exttable +#import pypy.module.thread.rpython.exttable ##import sys Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Thu Aug 16 18:28:42 2007 @@ -2,19 +2,17 @@ Thread support based on OS-level threads. """ -import thread +from pypy.module.thread import ll_thread as thread from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import NoneNotWrapped from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments -# Force the declaration of thread.start_new_thread() & co. for RPython -import pypy.module.thread.rpython.exttable - - THREAD_STARTUP_LOCK = thread.allocate_lock() class Bootstrapper: + _alloc_flavor_ = 'raw' + def bootstrap(self): space = self.space THREAD_STARTUP_LOCK.release() @@ -35,6 +33,7 @@ # clean up space.threadlocals to remove the ExecutionContext # entry corresponding to the current thread space.threadlocals.leave_thread(space) + # free self here? def run(self): space = self.space Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_thread.py Thu Aug 16 18:28:42 2007 @@ -1,6 +1,5 @@ from pypy.module.thread.test.support import GenericTestThread - class AppTestThread(GenericTestThread): def test_start_new_thread(self): Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/threadlocals.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/threadlocals.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/threadlocals.py Thu Aug 16 18:28:42 2007 @@ -1,8 +1,4 @@ -import thread - -# Force the declaration of thread.start_new_thread() & co. for RPython -import pypy.module.thread.rpython.exttable - +from pypy.module.thread import ll_thread as thread class OSThreadLocals: """Thread-local storage for OS-level threads. From arigo at codespeak.net Thu Aug 16 18:36:12 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Aug 2007 18:36:12 +0200 (CEST) Subject: [pypy-svn] r45741 - pypy/branch/pypy-more-rtti-inprogress/rpython/test Message-ID: <20070816163612.D34EF815E@code0.codespeak.net> Author: arigo Date: Thu Aug 16 18:36:12 2007 New Revision: 45741 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rbuiltin.py Log: Fixes, and skip two tests. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rbuiltin.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rbuiltin.py Thu Aug 16 18:36:12 2007 @@ -248,6 +248,7 @@ assert count == 1 def test_os_path_exists(self): + py.test.skip("cannot call os.stat() on the llinterp yet") import os def f(fn): return os.path.exists(fn) @@ -257,6 +258,7 @@ self.string_to_ll("strange_filename_that_looks_improbable.sde")]) == False def test_os_isdir(self): + py.test.skip("cannot call os.stat() on the llinterp yet") import os def f(fn): return os.path.isdir(fn) @@ -363,7 +365,6 @@ assert res == os.path.join('a', 'b') class TestLLtype(BaseTestRbuiltin, LLRtypeMixin): - from pypy.rpython.lltypesystem.module import ll_os def test_isinstance_obj(self): _1 = lltype.pyobjectptr(1) @@ -421,7 +422,6 @@ class TestOOtype(BaseTestRbuiltin, OORtypeMixin): - from pypy.rpython.ootypesystem.module import ll_os def test_instantiate_meta(self): class A: From jlg at codespeak.net Thu Aug 16 20:54:25 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Thu, 16 Aug 2007 20:54:25 +0200 (CEST) Subject: [pypy-svn] r45750 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070816185425.BA6B8816F@code0.codespeak.net> Author: jlg Date: Thu Aug 16 20:54:24 2007 New Revision: 45750 Modified: pypy/dist/pypy/lang/scheme/TODO.txt pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_continuation.py Log: set! is continuation friendly; s/callable/caller/ in ContinuationFrame; lambda procedure now gets cont_stack from ctx instead of closure, this makes new tests passable Modified: pypy/dist/pypy/lang/scheme/TODO.txt ============================================================================== --- pypy/dist/pypy/lang/scheme/TODO.txt (original) +++ pypy/dist/pypy/lang/scheme/TODO.txt Thu Aug 16 20:54:24 2007 @@ -12,7 +12,7 @@ - implement key functions (apply, map and so on) -- comparison: < > eq? eqv? +- comparison: < > Do in some future ----------------- Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Thu Aug 16 20:54:24 2007 @@ -440,6 +440,8 @@ #ctx is a caller context, which is joyfully ignored local_ctx = self.closure.copy() + #if lambda procedure should keep caller cont_stack + local_ctx.cont_stack = ctx.cont_stack #[:] #set lambda arguments for idx in range(len(self.args)): @@ -470,6 +472,7 @@ def force(self, ctx): if self.result is None: + #XXX cont_stack copy to be cont. friendly self.result = self.expr.eval(self.closure.copy()) return self.result @@ -783,6 +786,24 @@ return W_Boolean(isinstance(lst[0], W_Procedure)) ## +# Input/Output procedures +## +#class Display(W_Procedure): +# _symbol_name = "display" +# +# def procedure(self, ctx, lst): +# if len(lst) == 1: +# obj = lst[0] +# elif len(lst) == 2: +# (obj, port) = lst +# raise NotImplementedError +# else: +# raise WrongArgsNumber +# +# print obj.to_string() +# return w_undefined + +## # Macro ## class Define(W_Macro): @@ -830,13 +851,24 @@ class Sete(W_Macro): _symbol_name = "set!" + def continue_tr(self, ctx, lst, elst, cnt=True): + assert cnt == True + w_symbol = lst + w_val = elst[0] + ctx.ssete(w_symbol, w_val) + if len(ctx.cont_stack) == 0: + raise ContinuationReturn(w_val) + + cont = ctx.cont_stack.pop() + return cont.run(ctx, w_val) + def call(self, ctx, lst): if not isinstance(lst, W_Pair): raise SchemeSyntaxError - w_identifier = lst.car + w_symbol = lst.car - w_val = lst.get_cdr_as_pair().car.eval(ctx) - ctx.ssete(w_identifier, w_val) + w_val = lst.get_cdr_as_pair().car.eval_cf(ctx, self, w_symbol) + ctx.ssete(w_symbol, w_val) return w_val #undefined class MacroIf(W_Macro): @@ -1187,7 +1219,7 @@ return self.matchr(ctx, self.pattern.cdr, w_expr.cdr) def matchr(self, ctx, w_patt, w_expr): - print " >", w_patt.to_string(), w_expr.to_string() + #print " >", w_patt.to_string(), w_expr.to_string() if isinstance(w_patt, W_Pair): w_pattcar = w_patt.car w_pattcdr = w_patt.cdr @@ -1198,7 +1230,7 @@ # we dont know how to deal with it mdict_cdr = self.matchr(ctx, w_pattcdr, w_expr.cdr) except EllipsisPattern: - print "ellipsis matched", w_patt, w_expr + #print "ellipsis matched", w_patt, w_expr mdict_lst = [] w_pair = w_expr @@ -1317,7 +1349,7 @@ def match(self, ctx, w_expr): for rule in self.syntax_lst: try: - print "m>", rule.pattern.to_string() + #print "m>", rule.pattern.to_string() match_dict = rule.match(ctx, w_expr) return (rule.template, match_dict) except MatchError: @@ -1327,7 +1359,7 @@ def expand(self, ctx, w_expr): try: - print w_expr.to_string() + #print w_expr.to_string() (template, match_dict) = self.match(ctx, w_expr) except MatchError: raise SchemeSyntaxError @@ -1378,7 +1410,7 @@ try: w_cdr = self.substituter(ctx, sexpr.cdr, match_dict) except EllipsisTemplate: - print "ellipsis expand", sexpr + #print "ellipsis expand", sexpr sexprcdr = sexpr.get_cdr_as_pair() try: #we can still have something behind ellipsis @@ -1543,9 +1575,9 @@ self.result = result class ContinuationFrame(object): - def __init__(self, callable, continuation, evaluated_args = [], enum=0): - #assert hasattr(callable, "continue_tr") - self.callable = callable + def __init__(self, caller, continuation, evaluated_args = [], enum=0): + #assert hasattr(caller, "continue_tr") + self.caller = caller assert isinstance(continuation, W_Root) self.continuation = continuation assert isinstance(evaluated_args, list) @@ -1555,13 +1587,14 @@ def run(self, ctx, arg): elst = self.evaluated_args[:self.evaluated_args_num] elst.append(arg) - print self.callable.to_string(), elst, self.continuation - return self.callable.continue_tr(ctx, self.continuation, elst, True) + #print 'c>', self.caller, elst, self.continuation + return self.caller.continue_tr(ctx, self.continuation, elst, True) class Continuation(W_Procedure): def __init__(self, ctx, continuation): - self.closure = ctx #to .copy() ot not to .copy() - #copy of continuation stack + self.closure = ctx + #copy of continuation stack this means that cont_stack is not + # global, so watch out with closures self.cont_stack = continuation[:] try: self.continuation = self.cont_stack.pop() @@ -1569,14 +1602,18 @@ #continuation captured on top-level self.continuation = None + def __repr__(self): + return self.to_string() + def to_string(self): return "# %s>" % (self.continuation,) def procedure_tr(self, ctx, lst): + #caller ctx is ignored if len(lst) == 0: lst.append(w_undefined) - print "Continuation called", self.cont_stack + #print "Continuation called", self.cont_stack self.closure.cont_stack = self.cont_stack[:] cont = self.continuation if cont is None: @@ -1589,6 +1626,7 @@ def procedure_tr(self, ctx, lst): if len(lst) != 1 or not isinstance(lst[0], W_Procedure): + #print lst[0] raise SchemeSyntaxError w_lambda = lst[0] Modified: pypy/dist/pypy/lang/scheme/test/test_continuation.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_continuation.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_continuation.py Thu Aug 16 20:54:24 2007 @@ -277,3 +277,74 @@ assert isinstance(w_result, W_Pair) assert w_result.to_string() == "(10 9 8 7 6 5 4 3 2 1 0)" +def test_hefty1_computation(): + ctx = ExecutionContext() + + eval_(ctx, "(define side-effects '())") + eval_(ctx, """ + (define (hefty-computation do-other-stuff) + (letrec + ((loop (lambda (n) + (set! side-effects (cons (list 'hefty-a n) side-effects)) + (set! do-other-stuff (call/cc do-other-stuff)) + (set! side-effects (cons (list 'hefty-b n) side-effects)) + (set! do-other-stuff (call/cc do-other-stuff)) + (set! side-effects (cons (list 'hefty-c n) side-effects)) + (set! do-other-stuff (call/cc do-other-stuff)) + (if (zero? n) + '() + (loop (- n 1)))))) + (loop 1)))""") + + eval_(ctx, """ + (define (superfluous-computation do-other-stuff) + (letrec + ((loop (lambda () + (set! side-effects (cons 'break side-effects)) + (set! do-other-stuff (call/cc do-other-stuff)) + (loop)))) + (loop)))""") + + eval_(ctx, "(hefty-computation superfluous-computation)") + + assert ctx.get("side-effects").to_string() == \ + """(break (hefty-c 0) break (hefty-b 0) break (hefty-a 0) break (hefty-c 1) break (hefty-b 1) break (hefty-a 1))""" + +def test_hefty2_computation(): + ctx = ExecutionContext() + + eval_(ctx, "(define side-effects '())") + eval_(ctx, """ + (define (hefty-computation do-other-stuff) + (letrec + ((loop (lambda (n) + (set! side-effects (cons (list 'hefty-a n) side-effects)) + (set! do-other-stuff (call/cc do-other-stuff)) + (set! side-effects (cons (list 'hefty-b n) side-effects)) + (set! do-other-stuff (call/cc do-other-stuff)) + (set! side-effects (cons (list 'hefty-c n) side-effects)) + (set! do-other-stuff (call/cc do-other-stuff)) + (if (zero? n) + '() + (loop (- n 1)))))) + (loop 1)))""") + + eval_(ctx, """ + (define (superfluous-computation do-other-stuff) + (letrec + ((loop (lambda () + (lst-loop '(straight quarter-past half quarter-til)) + (loop))) + (lst-loop (lambda (lst) + (if (pair? lst) + (let ((graphic (car lst))) + (set! side-effects (cons graphic side-effects)) + (set! do-other-stuff (call/cc do-other-stuff)) + (lst-loop (cdr lst))))))) + (loop)))""") + + + eval_(ctx, "(hefty-computation superfluous-computation)") + assert ctx.get("side-effects").to_string() == \ + """(quarter-past (hefty-c 0) straight (hefty-b 0) quarter-til (hefty-a 0) half (hefty-c 1) quarter-past (hefty-b 1) straight (hefty-a 1))""" + From arigo at codespeak.net Fri Aug 17 09:17:28 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 09:17:28 +0200 (CEST) Subject: [pypy-svn] r45780 - in pypy/branch/pypy-more-rtti-inprogress/rlib: . test Message-ID: <20070817071728.8B1EC8183@code0.codespeak.net> Author: arigo Date: Fri Aug 17 09:17:27 2007 New Revision: 45780 Added: pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py (contents, props changed) pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py (contents, props changed) Log: Playing with a limited version of marshall/unmarshall for RPython programs. Added: pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py Fri Aug 17 09:17:27 2007 @@ -0,0 +1,157 @@ +"""A way to serialize data in the same format as the 'marshal' module +but accessible to RPython programs. +""" + +from pypy.annotation import model as annmodel +from pypy.annotation.signature import annotation +from pypy.annotation.listdef import ListDef, TooLateForChange +from pypy.annotation.pairtype import pair, pairtype +from pypy.rlib.rarithmetic import formatd +from pypy.rlib.unroll import unrolling_iterable + +class CannotMarshal(Exception): + pass + +def get_marshaller(type): + s_obj = annotation(type, None) + try: + # look for a marshaller in the 'dumpers' dictionary + return find_dumper(s_obj) + except CannotMarshal: + # ask the annotation to produce an appropriate dumper + pair(_tag, s_obj).install_marshaller() + return find_dumper(s_obj) +get_marshaller._annspecialcase_ = 'specialize:memo' + +def get_unmarshaller(type): + xxx +get_unmarshaller._annspecialcase_ = 'specialize:memo' + +# ____________________________________________________________ +# +# Dumpers and loaders + +TYPE_NONE = 'N' +TYPE_INT = 'i' +TYPE_FLOAT = 'f' +#TYPE_LONG = 'l' +TYPE_STRING = 's' +TYPE_TUPLE = '(' +TYPE_LIST = '[' + +dumpers = [] +s_list_of_chars = ListDef(None, annmodel.SomeChar(), + mutated=True, resized=True) + +def add_dumper(s_obj, dumper): + dumpers.append((s_obj, dumper)) + dumper._annenforceargs_ = [s_list_of_chars, s_obj] + +def get_dumper_annotation(dumper): + return dumper._annenforceargs_[1] + +def find_dumper(s_obj): + for s_cond, dumper in dumpers: + if weakly_contains(s_cond, s_obj): + return dumper + raise CannotMarshal(s_obj) + +def w_long(buf, x): + buf.append(chr(x & 0xff)) + x >>= 8 + buf.append(chr(x & 0xff)) + x >>= 8 + buf.append(chr(x & 0xff)) + x >>= 8 + buf.append(chr(x & 0xff)) +w_long._annenforceargs_ = [None, int] + +def dump_none(buf, x): + buf.append(TYPE_NONE) +add_dumper(annmodel.s_None, dump_none) + +def dump_int(buf, x): + buf.append(TYPE_INT) + w_long(buf, x) +add_dumper(annmodel.SomeInteger(), dump_int) + +def dump_float(buf, x): + buf.append(TYPE_FLOAT) + s = formatd("%.17g", x) + buf.append(chr(len(s))) + buf += s +add_dumper(annmodel.SomeFloat(), dump_float) + +def dump_string_or_none(buf, x): + if x is None: + dump_none(buf, x) + else: + buf.append(TYPE_STRING) + w_long(buf, len(x)) + buf += x +add_dumper(annmodel.SomeString(can_be_None=True), dump_string_or_none) + +# ____________________________________________________________ +# +# Annotations => dumpers and loaders + +class MTag(object): + """Tag for pairtype(), for the purpose of making the get_marshaller() + and get_unmarshaller() methods of SomeObject only locally visible.""" +_tag = MTag() + +def weakly_contains(s_bigger, s_smaller): + # a special version of s_bigger.contains(s_smaller). Warning, to + # support ListDefs properly, this works by trying to produce a side-effect + # on s_bigger. It relies on the fact that s_bigger was created with + # an expression like 'annotation([s_item])' which returns a ListDef with + # no bookkeeper, on which side-effects are not allowed. + try: + s_union = annmodel.unionof(s_bigger, s_smaller) + return s_bigger.contains(s_union) + except (annmodel.UnionError, TooLateForChange): + return False + + +class __extend__(pairtype(MTag, annmodel.SomeObject)): + + def install_marshaller((tag, s_obj)): + raise CannotMarshal(s_obj) + + +class __extend__(pairtype(MTag, annmodel.SomeList)): + + def install_marshaller((tag, s_list)): + def dump_list_or_none(buf, x): + if x is None: + dump_none(buf, x) + else: + buf.append(TYPE_LIST) + w_long(buf, len(x)) + for item in x: + itemdumper(buf, item) + + itemdumper = get_marshaller(s_list.listdef.listitem.s_value) + if s_list.listdef.listitem.dont_change_any_more: + s_general_list = s_list + else: + s_item = get_dumper_annotation(itemdumper) + s_general_list = annotation([s_item]) + add_dumper(s_general_list, dump_list_or_none) + + +class __extend__(pairtype(MTag, annmodel.SomeTuple)): + + def install_marshaller((tag, s_tuple)): + def dump_tuple(buf, x): + buf.append(TYPE_TUPLE) + w_long(buf, len(x)) + for i, itemdumper in unroll_item_dumpers: + itemdumper(buf, x[i]) + + itemdumpers = [get_marshaller(s_item) for s_item in s_tuple.items] + unroll_item_dumpers = unrolling_iterable(enumerate(itemdumpers)) + dumper_annotations = [get_dumper_annotation(itemdumper) + for itemdumper in itemdumpers] + s_general_tuple = annmodel.SomeTuple(dumper_annotations) + add_dumper(s_general_tuple, dump_tuple) Added: pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py Fri Aug 17 09:17:27 2007 @@ -0,0 +1,25 @@ +import marshal +from pypy.rlib.rmarshal import * + + +def test_marshaller(): + buf = [] + get_marshaller(int)(buf, 5) + assert marshal.loads(''.join(buf)) == 5 + + buf = [] + get_marshaller(float)(buf, 3.25) + assert marshal.loads(''.join(buf)) == 3.25 + + buf = [] + get_marshaller(str)(buf, "hello, world") + assert marshal.loads(''.join(buf)) == "hello, world" + + buf = [] + get_marshaller([int])(buf, [2, 5, -7]) + assert marshal.loads(''.join(buf)) == [2, 5, -7] + + buf = [] + get_marshaller((int, float, (str, ())))(buf, (7, -1.5, ("foo", ()))) + assert marshal.loads(''.join(buf)) == (7, -1.5, ("foo", ())) + From arigo at codespeak.net Fri Aug 17 09:59:01 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 09:59:01 +0200 (CEST) Subject: [pypy-svn] r45797 - in pypy/branch/pypy-more-rtti-inprogress/rlib: . test Message-ID: <20070817075901.1C1258193@code0.codespeak.net> Author: arigo Date: Fri Aug 17 09:59:00 2007 New Revision: 45797 Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py Log: Unmarshalling. Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py Fri Aug 17 09:59:00 2007 @@ -12,10 +12,13 @@ class CannotMarshal(Exception): pass +class CannotUnmarshall(Exception): + pass + def get_marshaller(type): s_obj = annotation(type, None) try: - # look for a marshaller in the 'dumpers' dictionary + # look for a marshaller in the 'dumpers' list return find_dumper(s_obj) except CannotMarshal: # ask the annotation to produce an appropriate dumper @@ -23,9 +26,28 @@ return find_dumper(s_obj) get_marshaller._annspecialcase_ = 'specialize:memo' +def get_loader(type): + s_obj = annotation(type, None) + try: + # look for a marshaller in the 'loaders' list + return find_loader(s_obj) + except CannotUnmarshall: + # ask the annotation to produce an appropriate loader + pair(_tag, s_obj).install_unmarshaller() + return find_loader(s_obj) + def get_unmarshaller(type): - xxx + loader = get_loader(type) + # wrap the loader into a more convenient interface + try: + return _unmarshaller_cache[loader] + except KeyError: + def unmarshaller(buf): + return loader(Loader(buf)) + _unmarshaller_cache[loader] = unmarshaller + return unmarshaller get_unmarshaller._annspecialcase_ = 'specialize:memo' +_unmarshaller_cache = {} # ____________________________________________________________ # @@ -40,6 +62,7 @@ TYPE_LIST = '[' dumpers = [] +loaders = [] s_list_of_chars = ListDef(None, annmodel.SomeChar(), mutated=True, resized=True) @@ -47,15 +70,31 @@ dumpers.append((s_obj, dumper)) dumper._annenforceargs_ = [s_list_of_chars, s_obj] +def add_loader(s_obj, loader): + loaders.append((s_obj, loader)) + def get_dumper_annotation(dumper): return dumper._annenforceargs_[1] def find_dumper(s_obj): + # select a suitable dumper - the condition is that the dumper must + # accept an input that is at least as general as the requested s_obj for s_cond, dumper in dumpers: if weakly_contains(s_cond, s_obj): return dumper raise CannotMarshal(s_obj) +def find_loader(s_obj): + # select a suitable loader - note that we need more loaders than + # dumpers in general, because the condition is that the loader should + # return something that is contained within the requested s_obj + for s_cond, loader in loaders[::-1]: + if s_obj.contains(s_cond): + return loader + if s_obj == annmodel.s_None: + return load_none + raise CannotUnmarshall(s_obj) + def w_long(buf, x): buf.append(chr(x & 0xff)) x >>= 8 @@ -70,11 +109,31 @@ buf.append(TYPE_NONE) add_dumper(annmodel.s_None, dump_none) +def load_none(loader): + if loader.readchr() != TYPE_NONE: + raise ValueError("expected a None") + return None +#add_loader(annmodel.s_None, load_none) -- cannot install it as a regular +# loader, because it will also match any annotation that can be None + def dump_int(buf, x): buf.append(TYPE_INT) w_long(buf, x) add_dumper(annmodel.SomeInteger(), dump_int) +def load_int_nonneg(loader): + x = load_int(loader) + if x < 0: + raise ValueError("expected a non-negative int") + return x +add_loader(annmodel.SomeInteger(nonneg=True), load_int_nonneg) + +def load_int(loader): + if loader.readchr() != TYPE_INT: + raise ValueError("expected an int") + return loader.r_long() +add_loader(annmodel.SomeInteger(), load_int) + def dump_float(buf, x): buf.append(TYPE_FLOAT) s = formatd("%.17g", x) @@ -82,6 +141,14 @@ buf += s add_dumper(annmodel.SomeFloat(), dump_float) +##def load_float(loader): +## if loader.readchr() != TYPE_FLOAT: +## raise ValueError("expected a float") +## length = ord(loader.readchr()) +## s = loader.read(length) +## return ...mess... +##add_loader(annmodel.SomeFloat(), load_float) + def dump_string_or_none(buf, x): if x is None: dump_none(buf, x) @@ -91,6 +158,64 @@ buf += x add_dumper(annmodel.SomeString(can_be_None=True), dump_string_or_none) +def load_single_char(loader): + if loader.readchr() != TYPE_STRING or loader.r_long() != 1: + raise ValueError("expected a character") + return loader.readchr() +add_loader(annmodel.SomeChar(), load_single_char) + +def load_string(loader): + if loader.readchr() != TYPE_STRING: + raise ValueError("expected a string") + length = loader.r_long() + return loader.read(length) +add_loader(annmodel.SomeString(can_be_None=False), load_string) + +def load_string_or_none(loader): + t = loader.readchr() + if t == TYPE_STRING: + length = loader.r_long() + return loader.read(length) + elif t == TYPE_NONE: + return None + else: + raise ValueError("expected a string or None") +add_loader(annmodel.SomeString(can_be_None=True), load_string_or_none) + +# ____________________________________________________________ +# +# Loader support class + +class Loader(object): + + def __init__(self, buf): + self.buf = buf + self.pos = 0 + + def read(self, count): + pos = self.pos + end = pos + count + if end > len(self.buf): + raise ValueError("not enough data") + self.pos = end + return self.buf[pos:end] + + def readchr(self): + pos = self.pos + if pos >= len(self.buf): + raise ValueError("not enough data") + self.pos = pos + 1 + return self.buf[pos] + + def r_long(self): + a = ord(self.readchr()) + b = ord(self.readchr()) + c = ord(self.readchr()) + d = ord(self.readchr()) + if d >= 0x80: + d -= 0x100 + return a | (b<<8) | (c<<16) | (d<<24) + # ____________________________________________________________ # # Annotations => dumpers and loaders @@ -118,6 +243,9 @@ def install_marshaller((tag, s_obj)): raise CannotMarshal(s_obj) + def install_unmarshaller((tag, s_obj)): + raise CannotUnmarshall(s_obj) + class __extend__(pairtype(MTag, annmodel.SomeList)): @@ -139,6 +267,23 @@ s_general_list = annotation([s_item]) add_dumper(s_general_list, dump_list_or_none) + def install_unmarshaller((tag, s_list)): + def load_list_or_none(loader): + t = loader.readchr() + if t == TYPE_LIST: + length = loader.r_long() + result = [] + for i in range(length): + result.append(itemloader(loader)) + return result + elif t == TYPE_NONE: + return None + else: + raise ValueError("expected a list or None") + + itemloader = get_loader(s_list.listdef.listitem.s_value) + add_loader(s_list, load_list_or_none) + class __extend__(pairtype(MTag, annmodel.SomeTuple)): @@ -155,3 +300,19 @@ for itemdumper in itemdumpers] s_general_tuple = annmodel.SomeTuple(dumper_annotations) add_dumper(s_general_tuple, dump_tuple) + + def install_unmarshaller((tag, s_tuple)): + def load_tuple(loader): + if loader.readchr() != TYPE_TUPLE: + raise ValueError("expected a tuple") + if loader.r_long() != expected_length: + raise ValueError("wrong tuple length") + result = () + for i, itemloader in unroll_item_loaders: + result += (itemloader(loader),) + return result + + itemloaders = [get_loader(s_item) for s_item in s_tuple.items] + expected_length = len(itemloaders) + unroll_item_loaders = unrolling_iterable(enumerate(itemloaders)) + add_loader(s_tuple, load_tuple) Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py Fri Aug 17 09:59:00 2007 @@ -1,5 +1,13 @@ +import py import marshal from pypy.rlib.rmarshal import * +from pypy.annotation import model as annmodel + +types_that_can_be_none = [ + [int], + annmodel.SomeString(can_be_None=True), + annmodel.s_None, + ] def test_marshaller(): @@ -23,3 +31,37 @@ get_marshaller((int, float, (str, ())))(buf, (7, -1.5, ("foo", ()))) assert marshal.loads(''.join(buf)) == (7, -1.5, ("foo", ())) + for typ in types_that_can_be_none: + buf = [] + get_marshaller(typ)(buf, None) + assert marshal.loads(''.join(buf)) is None + + +def test_unmarshaller(): + buf = 'i\x05\x00\x00\x00' + assert get_unmarshaller(int)(buf) == 5 + +## buf = 'f\x043.25' +## assert get_unmarshaller(float)(buf) == 3.25 + + buf = 's\x0c\x00\x00\x00hello, world' + assert get_unmarshaller(str)(buf) == "hello, world" + + buf = 's\x01\x00\x00\x00X' + assert get_unmarshaller(annmodel.SomeChar())(buf) == "X" + + buf = 'i\x05\x00\x00\x00' + py.test.raises(ValueError, get_unmarshaller(str), buf) + + buf = ('[\x03\x00\x00\x00i\x02\x00\x00\x00i\x05\x00\x00\x00' + 'i\xf9\xff\xff\xff') + assert get_unmarshaller([int])(buf) == [2, 5, -7] + + buf = ('(\x02\x00\x00\x00i\x07\x00\x00\x00(\x02\x00\x00\x00' + 's\x03\x00\x00\x00foo(\x00\x00\x00\x00') + res = get_unmarshaller((int, (str, ())))(buf) + assert res == (7, ("foo", ())) + + for typ in types_that_can_be_none: + buf = 'N' + assert get_unmarshaller(typ)(buf) is None From arigo at codespeak.net Fri Aug 17 10:02:45 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 10:02:45 +0200 (CEST) Subject: [pypy-svn] r45799 - pypy/branch/pypy-more-rtti-inprogress/rlib Message-ID: <20070817080245.8135A8193@code0.codespeak.net> Author: arigo Date: Fri Aug 17 10:02:44 2007 New Revision: 45799 Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py Log: Document the interface. Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py Fri Aug 17 10:02:44 2007 @@ -16,6 +16,11 @@ pass def get_marshaller(type): + """Return a marshaller function. + The marshaller takes two arguments: a buffer and an object of + type 'type'. The buffer is list of characters that gets extended + with new data when the marshaller is called. + """ s_obj = annotation(type, None) try: # look for a marshaller in the 'dumpers' list @@ -37,6 +42,11 @@ return find_loader(s_obj) def get_unmarshaller(type): + """Return an unmarshaller function. + The unmarshaller takes a string as argument, and return an object + of type 'type'. It raises ValueError if the marshalled data is + invalid or contains an object of a different type. + """ loader = get_loader(type) # wrap the loader into a more convenient interface try: From arigo at codespeak.net Fri Aug 17 14:59:01 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 14:59:01 +0200 (CEST) Subject: [pypy-svn] r45810 - in pypy/branch/pypy-more-rtti-inprogress/rlib: . test Message-ID: <20070817125901.C6BA88197@code0.codespeak.net> Author: arigo Date: Fri Aug 17 14:58:59 2007 New Revision: 45810 Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py Log: - add support for more types - make translatable. Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py Fri Aug 17 14:58:59 2007 @@ -6,8 +6,9 @@ from pypy.annotation.signature import annotation from pypy.annotation.listdef import ListDef, TooLateForChange from pypy.annotation.pairtype import pair, pairtype -from pypy.rlib.rarithmetic import formatd +from pypy.rlib.rarithmetic import formatd, r_longlong, intmask from pypy.rlib.unroll import unrolling_iterable +from pypy.rpython import controllerentry class CannotMarshal(Exception): pass @@ -47,14 +48,17 @@ of type 'type'. It raises ValueError if the marshalled data is invalid or contains an object of a different type. """ - loader = get_loader(type) - # wrap the loader into a more convenient interface + loaditem = get_loader(type) + # wrap the loaditem into a more convenient interface try: - return _unmarshaller_cache[loader] + return _unmarshaller_cache[loaditem] except KeyError: def unmarshaller(buf): - return loader(Loader(buf)) - _unmarshaller_cache[loader] = unmarshaller + loader = Loader(buf) + result = loaditem(loader) + loader.check_finished() + return result + _unmarshaller_cache[loaditem] = unmarshaller return unmarshaller get_unmarshaller._annspecialcase_ = 'specialize:memo' _unmarshaller_cache = {} @@ -64,27 +68,30 @@ # Dumpers and loaders TYPE_NONE = 'N' +TYPE_FALSE = 'F' +TYPE_TRUE = 'T' TYPE_INT = 'i' +TYPE_INT64 = 'I' TYPE_FLOAT = 'f' -#TYPE_LONG = 'l' TYPE_STRING = 's' TYPE_TUPLE = '(' TYPE_LIST = '[' dumpers = [] loaders = [] -s_list_of_chars = ListDef(None, annmodel.SomeChar(), - mutated=True, resized=True) +s_list_of_chars = annmodel.SomeList(ListDef(None, annmodel.SomeChar(), + mutated=True, resized=True)) def add_dumper(s_obj, dumper): dumpers.append((s_obj, dumper)) + dumper.s_obj = s_obj dumper._annenforceargs_ = [s_list_of_chars, s_obj] def add_loader(s_obj, loader): loaders.append((s_obj, loader)) def get_dumper_annotation(dumper): - return dumper._annenforceargs_[1] + return dumper.s_obj def find_dumper(s_obj): # select a suitable dumper - the condition is that the dumper must @@ -120,12 +127,29 @@ add_dumper(annmodel.s_None, dump_none) def load_none(loader): - if loader.readchr() != TYPE_NONE: + if readchr(loader) != TYPE_NONE: raise ValueError("expected a None") return None #add_loader(annmodel.s_None, load_none) -- cannot install it as a regular # loader, because it will also match any annotation that can be None +def dump_bool(buf, x): + if x: + buf.append(TYPE_TRUE) + else: + buf.append(TYPE_FALSE) +add_dumper(annmodel.s_Bool, dump_bool) + +def load_bool(loader): + t = readchr(loader) + if t == TYPE_TRUE: + return True + elif t == TYPE_FALSE: + return False + else: + raise ValueError("expected a bool") +add_loader(annmodel.s_Bool, load_bool) + def dump_int(buf, x): buf.append(TYPE_INT) w_long(buf, x) @@ -139,11 +163,27 @@ add_loader(annmodel.SomeInteger(nonneg=True), load_int_nonneg) def load_int(loader): - if loader.readchr() != TYPE_INT: + if readchr(loader) != TYPE_INT: raise ValueError("expected an int") - return loader.r_long() + return readlong(loader) add_loader(annmodel.SomeInteger(), load_int) +def dump_longlong(buf, x): + buf.append(TYPE_INT64) + w_long(buf, intmask(x)) + w_long(buf, intmask(x>>32)) +add_dumper(annotation(r_longlong), dump_longlong) + +r_32bits_mask = r_longlong(0xFFFFFFFF) + +def load_longlong(loader): + if readchr(loader) != TYPE_INT64: + raise ValueError("expected a longlong") + x = r_longlong(readlong(loader)) & r_32bits_mask + x |= (r_longlong(readlong(loader)) << 32) + return x +add_loader(annotation(r_longlong), load_longlong) + def dump_float(buf, x): buf.append(TYPE_FLOAT) s = formatd("%.17g", x) @@ -151,13 +191,13 @@ buf += s add_dumper(annmodel.SomeFloat(), dump_float) -##def load_float(loader): -## if loader.readchr() != TYPE_FLOAT: -## raise ValueError("expected a float") -## length = ord(loader.readchr()) -## s = loader.read(length) -## return ...mess... -##add_loader(annmodel.SomeFloat(), load_float) +def load_float(loader): + if loader.readchr() != TYPE_FLOAT: + raise ValueError("expected a float") + length = ord(loader.readchr()) + s = loader.read(length) + return xxx # ...mess... +add_loader(annmodel.SomeFloat(), load_float) def dump_string_or_none(buf, x): if x is None: @@ -169,23 +209,23 @@ add_dumper(annmodel.SomeString(can_be_None=True), dump_string_or_none) def load_single_char(loader): - if loader.readchr() != TYPE_STRING or loader.r_long() != 1: + if readchr(loader) != TYPE_STRING or readlong(loader) != 1: raise ValueError("expected a character") - return loader.readchr() + return readchr(loader) add_loader(annmodel.SomeChar(), load_single_char) def load_string(loader): - if loader.readchr() != TYPE_STRING: + if readchr(loader) != TYPE_STRING: raise ValueError("expected a string") - length = loader.r_long() - return loader.read(length) + length = readlong(loader) + return readstr(loader, length) add_loader(annmodel.SomeString(can_be_None=False), load_string) def load_string_or_none(loader): - t = loader.readchr() + t = readchr(loader) if t == TYPE_STRING: - length = loader.r_long() - return loader.read(length) + length = readlong(loader) + return readstr(loader, length) elif t == TYPE_NONE: return None else: @@ -202,29 +242,41 @@ self.buf = buf self.pos = 0 - def read(self, count): - pos = self.pos - end = pos + count - if end > len(self.buf): - raise ValueError("not enough data") - self.pos = end - return self.buf[pos:end] - - def readchr(self): - pos = self.pos - if pos >= len(self.buf): - raise ValueError("not enough data") - self.pos = pos + 1 - return self.buf[pos] - - def r_long(self): - a = ord(self.readchr()) - b = ord(self.readchr()) - c = ord(self.readchr()) - d = ord(self.readchr()) - if d >= 0x80: - d -= 0x100 - return a | (b<<8) | (c<<16) | (d<<24) + def check_finished(self): + if self.pos != len(self.buf): + raise ValueError("not all data consumed") + + def need_more_data(self): + raise ValueError("not enough data") # can be overridden + +# the rest are not method on the Loader class, because it causes troubles +# in pypy.translator.rsandbox if new methods are discovered after some +# sandboxed-enabled graphs are produced +def readstr(loader, count): + if count < 0: + raise ValueError("negative count") + pos = loader.pos + end = pos + count + while end > len(loader.buf): + loader.need_more_data() + loader.pos = end + return loader.buf[pos:end] + +def readchr(loader): + pos = loader.pos + while pos >= len(loader.buf): + loader.need_more_data() + loader.pos = pos + 1 + return loader.buf[pos] + +def readlong(loader): + a = ord(readchr(loader)) + b = ord(readchr(loader)) + c = ord(readchr(loader)) + d = ord(readchr(loader)) + if d >= 0x80: + d -= 0x100 + return a | (b<<8) | (c<<16) | (d<<24) # ____________________________________________________________ # @@ -279,9 +331,9 @@ def install_unmarshaller((tag, s_list)): def load_list_or_none(loader): - t = loader.readchr() + t = readchr(loader) if t == TYPE_LIST: - length = loader.r_long() + length = readlong(loader) result = [] for i in range(length): result.append(itemloader(loader)) @@ -313,9 +365,9 @@ def install_unmarshaller((tag, s_tuple)): def load_tuple(loader): - if loader.readchr() != TYPE_TUPLE: + if readchr(loader) != TYPE_TUPLE: raise ValueError("expected a tuple") - if loader.r_long() != expected_length: + if readlong(loader) != expected_length: raise ValueError("wrong tuple length") result = () for i, itemloader in unroll_item_loaders: @@ -326,3 +378,25 @@ expected_length = len(itemloaders) unroll_item_loaders = unrolling_iterable(enumerate(itemloaders)) add_loader(s_tuple, load_tuple) + + +class __extend__(pairtype(MTag, controllerentry.SomeControlledInstance)): + # marshal a ControlledInstance by marshalling the underlying object + + def install_marshaller((tag, s_obj)): + def dump_controlled_instance(buf, x): + real_obj = controllerentry.controlled_instance_unbox(controller, x) + realdumper(buf, real_obj) + + controller = s_obj.controller + realdumper = get_marshaller(s_obj.s_real_obj) + add_dumper(s_obj, dump_controlled_instance) + + def install_unmarshaller((tag, s_obj)): + def load_controlled_instance(loader): + real_obj = realloader(loader) + return controllerentry.controlled_instance_box(controller, + real_obj) + controller = s_obj.controller + realloader = get_loader(s_obj.s_real_obj) + add_loader(s_obj, load_controlled_instance) Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py Fri Aug 17 14:58:59 2007 @@ -24,6 +24,18 @@ assert marshal.loads(''.join(buf)) == "hello, world" buf = [] + get_marshaller(bool)(buf, False) + assert marshal.loads(''.join(buf)) is False + + buf = [] + get_marshaller(bool)(buf, True) + assert marshal.loads(''.join(buf)) is True + + buf = [] + get_marshaller(r_longlong)(buf, r_longlong(0x12380000007)) + assert marshal.loads(''.join(buf)) == 0x12380000007 + + buf = [] get_marshaller([int])(buf, [2, 5, -7]) assert marshal.loads(''.join(buf)) == [2, 5, -7] @@ -53,6 +65,15 @@ buf = 'i\x05\x00\x00\x00' py.test.raises(ValueError, get_unmarshaller(str), buf) + buf = 'F' + assert get_unmarshaller(bool)(buf) is False + + buf = 'T' + assert get_unmarshaller(bool)(buf) is True + + buf = 'I\x07\x00\x00\x80\x23\x01\x00\x00' + assert get_unmarshaller(r_longlong)(buf) == 0x12380000007 + buf = ('[\x03\x00\x00\x00i\x02\x00\x00\x00i\x05\x00\x00\x00' 'i\xf9\xff\xff\xff') assert get_unmarshaller([int])(buf) == [2, 5, -7] @@ -65,3 +86,70 @@ for typ in types_that_can_be_none: buf = 'N' assert get_unmarshaller(typ)(buf) is None + + +def test_llinterp_marshal(): + from pypy.rpython.test.test_llinterp import interpret + marshaller = get_marshaller([(int, str)]) + def f(): + buf = [] + marshaller(buf, [(5, "hello"), (7, "world")]) + return ''.join(buf) + res = interpret(f, []) + res = ''.join(res.chars) + assert res == ('[\x02\x00\x00\x00(\x02\x00\x00\x00i\x05\x00\x00\x00' + 's\x05\x00\x00\x00hello(\x02\x00\x00\x00i\x07\x00\x00\x00' + 's\x05\x00\x00\x00world') + +def test_llinterp_unmarshal(): + from pypy.rpython.test.test_llinterp import interpret + unmarshaller = get_unmarshaller([(int, str)]) + buf = ('[\x02\x00\x00\x00(\x02\x00\x00\x00i\x05\x00\x00\x00' + 's\x05\x00\x00\x00hello(\x02\x00\x00\x00i\x07\x00\x00\x00' + 's\x05\x00\x00\x00world') + def f(): + result = '' + for num, string in unmarshaller(buf): + result += '%d=%s;' % (num, string) + return result + res = interpret(f, []) + res = ''.join(res.chars) + assert res == '5=hello;7=world;' + +def test_tuple_stat_result(): + from pypy.rpython.module.ll_os_stat import STAT_FIELDS, s_tuple_StatResult + marshaller = get_marshaller(s_tuple_StatResult) + unmarshaller = get_unmarshaller(s_tuple_StatResult) + + sttuple = (0,) * len(STAT_FIELDS) + buf = [] + marshaller(buf, sttuple) + res = unmarshaller(''.join(buf)) + assert res == sttuple + +def test_stat_result(): + import os + from pypy.translator.c.test.test_genc import compile + from pypy.rpython.module.ll_os_stat import STAT_FIELDS, s_StatResult + marshal_stat_result = get_marshaller(s_StatResult) + unmarshal_stat_result = get_unmarshaller(s_StatResult) + def f(path): + st = os.stat(path) + buf = [] + marshal_stat_result(buf, st) + buf = ''.join(buf) + st2 = unmarshal_stat_result(buf) + assert st2.st_mode == st.st_mode + assert st2[9] == st[9] + return buf + fn = compile(f, [str]) + res = fn('.') + st = os.stat('.') + sttuple = marshal.loads(res) + assert sttuple[0] == st[0] + assert sttuple[1] == st[1] + assert sttuple[2] == st[2] + assert sttuple[3] == st[3] + assert sttuple[4] == st[4] + assert sttuple[5] == st[5] + assert len(sttuple) == len(STAT_FIELDS) From arigo at codespeak.net Fri Aug 17 15:02:32 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 15:02:32 +0200 (CEST) Subject: [pypy-svn] r45811 - in pypy/branch/pypy-more-rtti-inprogress/annotation: . test Message-ID: <20070817130232.BA2A68199@code0.codespeak.net> Author: arigo Date: Fri Aug 17 15:02:32 2007 New Revision: 45811 Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/signature.py pypy/branch/pypy-more-rtti-inprogress/annotation/test/test_annrpython.py Log: Adapt a technique used in extfunc.py to allow list types in _annenforceargs_. Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/signature.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/annotation/signature.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/annotation/signature.py Fri Aug 17 15:02:32 2007 @@ -2,7 +2,8 @@ import types from pypy.annotation.model import SomeBool, SomeInteger, SomeString,\ SomeFloat, SomeList, SomeDict, s_None, SomeExternalObject,\ - SomeObject, SomeInstance, SomeTuple, lltype_to_annotation + SomeObject, SomeInstance, SomeTuple, lltype_to_annotation,\ + unionof from pypy.annotation.classdef import ClassDef, InstanceSource from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF @@ -129,6 +130,7 @@ len(args_s), len(inputcells))) for i, (s_arg, s_input) in enumerate(zip(args_s, inputcells)): + s_input = unionof(s_input, s_arg) if not s_arg.contains(s_input): raise Exception("%r argument %d:\n" "expected %s,\n" Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/test/test_annrpython.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/annotation/test/test_annrpython.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/annotation/test/test_annrpython.py Fri Aug 17 15:02:32 2007 @@ -2466,6 +2466,19 @@ s = a.build_types(fun, [int]) assert not s.is_constant() + def test_sig_list(self): + def g(buf): + buf.append(5) + g._annenforceargs_ = ([int],) + def fun(): + lst = [] + g(lst) + return lst[0] + a = self.RPythonAnnotator() + s = a.build_types(fun, []) + assert s.knowntype is int + assert not s.is_constant() + def test_slots_check(self): class Base(object): __slots__ = 'x' From arigo at codespeak.net Fri Aug 17 15:05:56 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 15:05:56 +0200 (CEST) Subject: [pypy-svn] r45812 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/lltypesystem rpython/module translator/c translator/sandbox translator/sandbox/test Message-ID: <20070817130556.EC2EE8189@code0.codespeak.net> Author: arigo Date: Fri Aug 17 15:05:56 2007 New Revision: 45812 Removed: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandboxmsg.py Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/annlowlevel.py pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rstr.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandlib.py Log: Change the level at which --sandbox'ing occurs. Now, by default the functions registered by _register_external() are replaced with a sandboxing version, so that the low-level external functions should no longer be seen at all. The _register_external()'ed functions operate at a slightly higher level - they have regular RPython objects as arguments and result. This is a more natural level that can be processed directly by pypy.rlib.rmarshal with no special-casing needed. This allows us to get rid of the strange marshal_input/unmarshal_output hacks in ll_os.py. As an extra bonus, the protocol used between the sandboxed process and its parent is now based on the regular CPython marshal format. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/annlowlevel.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/annlowlevel.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/annlowlevel.py Fri Aug 17 15:05:56 2007 @@ -156,7 +156,8 @@ self.pending.append((ll_function, graph, args_s, s_result)) return graph - def delayedfunction(self, ll_function, args_s, s_result, needtype=False): + def delayedfunction(self, ll_function, args_s, s_result, needtype=False, + **fnobjattrs): # get a delayed pointer to the low-level function, annotated as # specified. The pointer is only valid after finish() was called. graph = self.getgraph(ll_function, args_s, s_result) @@ -167,13 +168,13 @@ FUNCTYPE = lltype.FuncType(ARGS, RESULT) else: FUNCTYPE = None - return self.graph2delayed(graph, FUNCTYPE) + return self.graph2delayed(graph, FUNCTYPE, **fnobjattrs) def constfunc(self, ll_function, args_s, s_result): p = self.delayedfunction(ll_function, args_s, s_result) return Constant(p, lltype.typeOf(p)) - def graph2delayed(self, graph, FUNCTYPE=None): + def graph2delayed(self, graph, FUNCTYPE=None, **fnobjattrs): if FUNCTYPE is None: FUNCTYPE = lltype.ForwardReference() # obscure hack: embed the name of the function in the string, so @@ -181,7 +182,7 @@ # is really computed name = "delayed!%s" % (graph.name,) delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), name, solid=True) - self.delayedfuncs.append((delayedptr, graph)) + self.delayedfuncs.append((delayedptr, graph, fnobjattrs)) return delayedptr def graph2const(self, graph): @@ -259,8 +260,10 @@ for p, repr, obj in self.delayedconsts: p._become(repr.convert_const(obj)) rtyper.call_all_setups() - for p, graph in self.delayedfuncs: + for p, graph, fnobjattrs in self.delayedfuncs: real_p = rtyper.getcallable(graph) + for key, value in fnobjattrs.items(): + setattr(rtyper.type_system.deref(real_p), key, value) REAL = lltype.typeOf(real_p).TO FUNCTYPE = lltype.typeOf(p).TO if isinstance(FUNCTYPE, lltype.ForwardReference): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Fri Aug 17 15:05:56 2007 @@ -104,8 +104,12 @@ impl = getattr(self, method_name, None) fakeimpl = getattr(self, fake_method_name, self.instance) if impl: + if rtyper.annotator.translator.config.translation.sandbox: + impl.dont_inline = True obj = rtyper.getannmixlevel().delayedfunction( - impl, signature_args, hop.s_result) + impl, signature_args, hop.s_result, + _name=self.name, + _safe_not_sandboxed=self.safe_not_sandboxed) else: #if not self.safe_not_sandboxed: # print '>>>>>>>>>>>>>-----------------------------------' Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rstr.py Fri Aug 17 15:05:56 2007 @@ -167,6 +167,7 @@ debug_assert(i>=0, "negative str getitem index") debug_assert(i rffi.cast(lltype.Signed, size): - raise OverflowError - for i in range(len(data)): - buf[i] = data[i] - return rffi.cast(rffi.SIZE_T, len(data)) - os_read._obj._marshal_input = os_read_marshal_input - os_read._obj._unmarshal_output = os_read_unmarshal_output - @registering(os.write) def register_os_write(self): os_write = rffi.llexternal('write', [rffi.INT, rffi.VOIDP, @@ -326,12 +312,6 @@ "ll_os.ll_os_write", llimpl=os_write_lltypeimpl, oofakeimpl=os_write_oofakeimpl) - # '--sandbox' support - def os_write_marshal_input(msg, fd, buf, size): - msg.packnum(rffi.cast(lltype.Signed, fd)) - msg.packbuf(buf, 0, rffi.cast(lltype.Signed, size)) - os_write._obj._marshal_input = os_write_marshal_input - @registering(os.close) def register_os_close(self): os_close = rffi.llexternal('close', [rffi.INT], rffi.INT) @@ -461,23 +441,6 @@ "ll_os.ll_os_getcwd", llimpl=os_getcwd_lltypeimpl, oofakeimpl=os_getcwd_oofakeimpl) - # '--sandbox' support - def os_getcwd_marshal_input(msg, buf, bufsize): - msg.packsize_t(bufsize) - def os_getcwd_unmarshal_output(msg, buf, bufsize): - # the outside process should not send a result larger than - # the requested 'bufsize' - result = msg.nextstring() - n = len(result) - if rffi.cast(rffi.SIZE_T, n) >= bufsize: - raise OverflowError - for i in range(n): - buf[i] = result[i] - buf[n] = '\x00' - return buf - os_getcwd._obj._marshal_input = os_getcwd_marshal_input - os_getcwd._obj._unmarshal_output = os_getcwd_unmarshal_output - @registering(os.listdir) def register_os_listdir(self): # we need a different approach on Windows and on Posix Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py Fri Aug 17 15:05:56 2007 @@ -363,5 +363,9 @@ return result def need_sandboxing(self, fnobj): - return self.sandbox and ( - not getattr(fnobj, '_safe_not_sandboxed', False)) + if not self.sandbox: + return False + if hasattr(fnobj, '_safe_not_sandboxed'): + return not fnobj._safe_not_sandboxed + else: + return "if_external" Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py Fri Aug 17 15:05:56 2007 @@ -694,10 +694,28 @@ del bodyiter funcgen.implementation_end() +def sandbox_stub(fnobj, db): + # unexpected external function for --sandbox translation: replace it + # with a "Not Implemented" stub. To support these functions, port them + # to the new style registry (e.g. rpython.module.ll_os.RegisterOs). + from pypy.translator.sandbox import rsandbox + graph = rsandbox.get_external_function_sandbox_graph(fnobj, db, + force_stub=True) + return [FunctionCodeGenerator(graph, db)] + +def sandbox_transform(fnobj, db): + # for --sandbox: replace a function like os_open_lltypeimpl() with + # code that communicates with the external process to ask it to + # perform the operation. + from pypy.translator.sandbox import rsandbox + graph = rsandbox.get_external_function_sandbox_graph(fnobj, db) + return [FunctionCodeGenerator(graph, db)] + def select_function_code_generators(fnobj, db, functionname): sandbox = db.need_sandboxing(fnobj) if hasattr(fnobj, '_external_name'): - assert not sandbox + if sandbox: + return sandbox_stub(fnobj, db) db.externalfuncs[fnobj._external_name] = fnobj return [] elif fnobj._callable in extfunc.EXTERNALS: @@ -710,35 +728,26 @@ or fnobj._name.startswith('ll_time_') # XXX!! TEMPORARY! or fnobj._name.startswith('ll_stack_') # XXX!! TEMPORARY! ): - # deprecated case: apply the sandbox transformation but don't - # try to support these extfuncs properly (we just build a - # "Not Implemented" stub). To support these functions, port them - # to the new style registry (e.g. rpython.module.ll_os.RegisterOs). - from pypy.translator.sandbox import rsandbox - graph = rsandbox.get_external_function_sandbox_graph(fnobj, db, - force_stub=True) - return [FunctionCodeGenerator(graph, db)] + return sandbox_stub(fnobj, db) db.externalfuncs[fnobj._callable] = fnobj return [] elif getattr(fnobj._callable, 'suggested_primitive', False): raise ValueError, "trying to compile suggested primitive %r" % ( fnobj._callable,) elif hasattr(fnobj, 'graph'): + if sandbox and sandbox != "if_external": + # apply the sandbox transformation + return sandbox_transform(fnobj, db) exception_policy = getattr(fnobj, 'exception_policy', None) return [FunctionCodeGenerator(fnobj.graph, db, exception_policy, functionname)] elif getattr(fnobj, 'external', None) == 'C': + if sandbox: + return sandbox_stub(fnobj, db) if hasattr(fnobj, 'includes'): - # apply the sandbox transformation - if sandbox: - from pypy.translator.sandbox import rsandbox - graph = rsandbox.get_external_function_sandbox_graph(fnobj, db) - return [FunctionCodeGenerator(graph, db)] - else: - return [] # assume no wrapper needed + return [] # assume no wrapper needed else: # deprecated case - assert not sandbox return [CExternalFunctionCodeGenerator(fnobj, db)] else: raise ValueError, "don't know how to generate code for %r" % (fnobj,) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py Fri Aug 17 15:05:56 2007 @@ -3,7 +3,7 @@ trampolines that marshal their input arguments, dump them to STDOUT, and wait for an answer on STDIN. Enable with 'translate.py --sandbox'. """ -from pypy.translator.sandbox.sandboxmsg import MessageBuilder, LLMessage +from pypy.rlib import rmarshal # ____________________________________________________________ # @@ -45,102 +45,61 @@ buf = rffi.cast(rffi.CCHARP, buf) writeall_not_sandboxed._annenforceargs_ = [int, rffi.CCHARP, int] -def readall_not_sandboxed(fd, length): - buf = lltype.malloc(rffi.CCHARP.TO, length, flavor='raw') - p = buf - got = 0 - while got < length: - size1 = rffi.cast(rffi.SIZE_T, length - got) - count = rffi.cast(lltype.Signed, ll_read_not_sandboxed(fd, p, size1)) +##def readall_not_sandboxed(fd, length): +## buf = lltype.malloc(rffi.CCHARP.TO, length, flavor='raw') +## p = buf +## got = 0 +## while got < length: +## size1 = rffi.cast(rffi.SIZE_T, length - got) +## count = rffi.cast(lltype.Signed, ll_read_not_sandboxed(fd, p, size1)) +## if count <= 0: +## raise IOError +## got += count +## p = lltype.direct_ptradd(lltype.direct_arrayitems(p), count) +## p = rffi.cast(rffi.CCHARP, p) +## return buf +##readall_not_sandboxed._annenforceargs_ = [int, int] + + +class FdLoader(rmarshal.Loader): + def __init__(self, fd): + rmarshal.Loader.__init__(self, "") + self.fd = fd + self.buflen = 4096 + + def need_more_data(self): + buflen = self.buflen + buf = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw') + buflen = rffi.cast(rffi.SIZE_T, buflen) + count = ll_read_not_sandboxed(self.fd, buf, buflen) + count = rffi.cast(lltype.Signed, count) if count <= 0: raise IOError - got += count - p = lltype.direct_ptradd(lltype.direct_arrayitems(p), count) - p = rffi.cast(rffi.CCHARP, p) - return buf -readall_not_sandboxed._annenforceargs_ = [int, int] - -def buf2num(buf, index=0): - c0 = ord(buf[index ]) - c1 = ord(buf[index+1]) - c2 = ord(buf[index+2]) - c3 = ord(buf[index+3]) - if c0 >= 0x80: - c0 -= 0x100 - return (c0 << 24) | (c1 << 16) | (c2 << 8) | c3 + self.buf += ''.join([buf[i] for i in range(count)]) + self.buflen *= 2 -def build_default_marshal_input(FUNCTYPE, namehint, cache={}): - # return a default 'marshal_input' function - try: - return cache[FUNCTYPE] - except KeyError: - pass - unroll_args = [] - for i, ARG in enumerate(FUNCTYPE.ARGS): - if ARG == rffi.INT: # 'int' argument - methodname = "packnum" - elif ARG == rffi.SIZE_T: # 'size_t' argument - methodname = "packsize_t" - elif ARG == rffi.CCHARP: # 'char*' argument, assumed zero-terminated - methodname = "packccharp" - else: - raise NotImplementedError("external function %r argument type %s" % - (namehint, ARG)) - unroll_args.append((i, methodname)) - unroll_args = unrolling_iterable(unroll_args) - - def marshal_input(msg, *args): - assert len(args) == len(FUNCTYPE.ARGS) - for index, methodname in unroll_args: - getattr(msg, methodname)(args[index]) - - cache[FUNCTYPE] = marshal_input - return marshal_input - -def unmarshal_int(msg): return msg.nextnum() -def unmarshal_size_t(msg): return msg.nextsize_t() -def unmarshal_void(msg): pass - -def build_default_unmarshal_output(FUNCTYPE, namehint, - cache={rffi.INT : unmarshal_int, - rffi.SIZE_T: unmarshal_size_t, - lltype.Void: unmarshal_void}): - try: - return cache[FUNCTYPE.RESULT] - except KeyError: - raise NotImplementedError("external function %r return type %s" % ( - namehint, FUNCTYPE.RESULT)) - -CFalse = CDefinedIntSymbolic('0') # hack hack +##CFalse = CDefinedIntSymbolic('0') # hack hack -def sandboxed_io(msg): +def sandboxed_io(buf): STDIN = 0 STDOUT = 1 - buf = msg.as_rffi_buf() - if CFalse: # hack hack to force a method to be properly annotated/rtyped - msg.packstring(chr(CFalse) + chr(CFalse)) - msg.packsize_t(rffi.cast(rffi.SIZE_T, CFalse)) - msg.packbuf(buf, CFalse * 5, CFalse * 6) - msg.packccharp(rffi.str2charp(str(CFalse))) - try: - writeall_not_sandboxed(STDOUT, buf, msg.getlength()) - finally: - lltype.free(buf, flavor='raw') - # wait for the answer - buf = readall_not_sandboxed(STDIN, 4) + # send the buffer with the marshalled fnname and input arguments to STDOUT + p = lltype.malloc(rffi.CCHARP.TO, len(buf), flavor='raw') try: - length = buf2num(buf) + for i in range(len(buf)): + p[i] = buf[i] + writeall_not_sandboxed(STDOUT, p, len(buf)) finally: - lltype.free(buf, flavor='raw') - length -= 4 # the original length includes the header - if length < 0: - raise IOError - buf = readall_not_sandboxed(STDIN, length) - msg = LLMessage(buf, 0, length) - if CFalse: # hack hack to force a method to be properly annotated/rtyped - msg.nextstring() - msg.nextsize_t() - return msg + lltype.free(p, flavor='raw') + # build a Loader that will get the answer from STDIN + loader = FdLoader(STDIN) + # check for errors + error = load_int(loader) + if error != 0: + raise IOError # XXX add support to raise the correct exception + else: + # no exception; the caller will decode the actual result + return loader def not_implemented_stub(msg): STDERR = 2 @@ -150,40 +109,40 @@ raise RuntimeError(msg) # XXX in RPython, the msg is ignored at the moment not_implemented_stub._annenforceargs_ = [str] +dump_string = rmarshal.get_marshaller(str) +load_int = rmarshal.get_loader(int) + def get_external_function_sandbox_graph(fnobj, db, force_stub=False): """Build the graph of a helper trampoline function to be used in place of real calls to the external function 'fnobj'. The trampoline marshals its input arguments, dumps them to STDOUT, and waits for an answer on STDIN. """ - # XXX for now, only supports function with int and string arguments - # and returning an int or void. Other cases need a custom - # _marshal_input and/or _unmarshal_output function on fnobj. - FUNCTYPE = lltype.typeOf(fnobj) fnname = fnobj._name + if hasattr(fnobj, 'graph'): + # get the annotation of the input arguments and the result + graph = fnobj.graph + annotator = db.translator.annotator + args_s = [annotator.binding(v) for v in graph.getargs()] + s_result = annotator.binding(graph.getreturnvar()) + else: + # pure external function - fall back to the annotations + # corresponding to the ll types + FUNCTYPE = lltype.typeOf(fnobj) + args_s = [annmodel.lltype_to_annotation(ARG) for ARG in FUNCTYPE.ARGS] + s_result = annmodel.lltype_to_annotation(FUNCTYPE.RESULT) + try: if force_stub: # old case - don't try to support suggested_primitive - raise NotImplementedError("external function '%s' using " - "deprecated 'suggested_primitive'" % ( - fnname,)) - if hasattr(fnobj, '_marshal_input'): - marshal_input = fnobj._marshal_input - else: - marshal_input = build_default_marshal_input(FUNCTYPE, fnname) - if hasattr(fnobj, '_unmarshal_output'): - # _unmarshal_output() also receives the input arguments of the - # original call because some functions need them to decode the - # result properly. - unmarshal_output = fnobj._unmarshal_output - unmarshal_takes_input_args = True - else: - # The default unmarshal_output do not receive the original input - # arguments because they would cause annotation troubles - # (see e.g. test_sandbox_3). - unmarshal_output = build_default_unmarshal_output(FUNCTYPE, fnname) - unmarshal_takes_input_args = False + raise NotImplementedError("sandboxing for external function '%s'" + % (fnname,)) + + dump_arguments = rmarshal.get_marshaller(tuple(args_s)) + load_result = rmarshal.get_loader(s_result) - except NotImplementedError, e: + except (NotImplementedError, + rmarshal.CannotMarshal, + rmarshal.CannotUnmarshall), e: msg = 'Not Implemented: %s' % (e,) log.WARNING(msg) def execute(*args): @@ -191,29 +150,19 @@ else: def execute(*args): - # marshal the input arguments - msg = MessageBuilder() - msg.packstring(fnname) - marshal_input(msg, *args) + # marshal the function name and input arguments + buf = [] + dump_string(buf, fnname) + dump_arguments(buf, args) # send the buffer and wait for the answer - msg = sandboxed_io(msg) - try: - # decode the answer - errcode = msg.nextnum() - if errcode != 0: - raise IOError - if unmarshal_takes_input_args: - result = unmarshal_output(msg, *args) - else: - result = unmarshal_output(msg) - finally: - lltype.free(msg.value, flavor='raw') + loader = sandboxed_io(buf) + # decode the answer + result = load_result(loader) + loader.check_finished() return result execute = func_with_new_name(execute, 'sandboxed_' + fnname) ann = MixLevelHelperAnnotator(db.translator.rtyper) - args_s = [annmodel.lltype_to_annotation(ARG) for ARG in FUNCTYPE.ARGS] - s_result = annmodel.lltype_to_annotation(FUNCTYPE.RESULT) graph = ann.getgraph(execute, args_s, s_result) ann.finish() return graph Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Fri Aug 17 15:05:56 2007 @@ -4,9 +4,27 @@ for the outer process, which can run CPython or PyPy. """ +import marshal, sys from py.compat import subprocess -from pypy.translator.sandbox.sandboxmsg import Message, encode_message -from pypy.translator.sandbox.sandboxmsg import read_message + +def read_message(f, timeout=None): + # warning: 'timeout' is not really reliable and should only be used + # for testing. Also, it doesn't work if the file f does any buffering. + if timeout is not None: + import select + iwtd, owtd, ewtd = select.select([f], [], [], timeout) + if not iwtd: + raise EOFError("timed out waiting for data") + return marshal.load(f) + +if sys.version_info < (2, 4): + def write_message(g, msg): + marshal.dump(msg, g) + g.flush() +else: + def write_message(g, msg): + marshal.dump(msg, g, 0) + g.flush() class SandboxedProc(object): """Base class to control a sandboxed subprocess. @@ -36,38 +54,21 @@ def handle_until_return(self): while True: try: - msg = read_message(self.popen.stdout) + fnname = read_message(self.popen.stdout) + args = read_message(self.popen.stdout) except EOFError, e: break - answer = self.handle_message(msg) - self.popen.stdin.write(answer) + answer = self.handle_message(fnname, *args) + write_message(self.popen.stdin, 0) # error code - always 0 for now + write_message(self.popen.stdin, answer) returncode = self.popen.wait() return returncode - def handle_message(self, msg): - fn = msg.nextstring() - try: - argtypes, restypes = self.TYPES[fn] - except KeyError: - raise IOError("trying to invoke unknown external function %r" % ( - fn,)) - handler = getattr(self, 'do_' + fn) - answers = handler(*msg.decode(argtypes)) - if len(restypes) == 0: - assert answers is None - answers = (0,) - elif len(restypes) == 1: - answers = (0, answers) - else: - answers = (0,) + answers - return encode_message("i" + restypes, answers) - - TYPES = { - "open": ("sii", "i"), - "read": ("iI", "s"), - "write": ("is", "I"), - "close": ("i", "i"), - } + def handle_message(self, fnname, *args): + if '__' in fnname: + raise ValueError("unsafe fnname") + handler = getattr(self, 'do_' + fnname.replace('.', '__')) + return handler(*args) class SimpleIOSandboxedProc(SandboxedProc): @@ -111,7 +112,7 @@ self._output = None self._error = None - def do_read(self, fd, size): + def do_ll_os__ll_os_read(self, fd, size): if fd == 0: if self._input is None: return "" @@ -119,7 +120,7 @@ return self._input.read(size) raise OSError("trying to read from fd %d" % (fd,)) - def do_write(self, fd, data): + def do_ll_os__ll_os_write(self, fd, data): if fd == 1: self._output.write(data) return len(data) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py Fri Aug 17 15:05:56 2007 @@ -1,34 +1,28 @@ +import py import sys, os import struct from pypy.rpython.lltypesystem import rffi -from pypy.translator.sandbox.sandboxmsg import Message, MessageBuilder -from pypy.translator.sandbox.sandboxmsg import read_message from pypy.translator.interactive import Translation +from pypy.translator.sandbox.sandlib import read_message, write_message +def expect(f, g, fnname, args, result, resulttype=None): + msg = read_message(f, timeout=10.0) + assert msg == fnname + msg = read_message(f, timeout=10.0) + assert msg == args + write_message(g, 0) + if resulttype is None: + write_message(g, result) + else: + # use the exact result type for encoding + from pypy.rlib.rmarshal import get_marshaller + buf = [] + get_marshaller(resulttype)(buf, result) + g.write(''.join(buf)) -def test_sandbox_message(): - def num(n): - return struct.pack("!i", n) - msg = MessageBuilder() - msg.packstring("open") - msg.packccharp(rffi.str2charp("/tmp/foobar")) - msg.packnum(123) - res = msg.getvalue() - assert res == (num(len(res)) + - "s" + num(4) + "open" + - "s" + num(11) + "/tmp/foobar" + - "i" + num(123)) - - msg = Message(res[4:]) - m1 = msg.nextstring() - assert m1 == "open" - m2 = msg.nextstring() - assert m2 == "/tmp/foobar" - m3 = msg.nextnum() - assert m3 == 123 -def test_sandbox(): +def test_sandbox_1(): def entry_point(argv): fd = os.open("/tmp/foobar", os.O_RDONLY, 0777) assert fd == 77 @@ -39,29 +33,8 @@ t = Translation(entry_point, backend='c', standalone=True, sandbox=True) exe = t.compile() g, f = os.popen2(exe, "t", 0) - - msg = read_message(f, timeout=10.0) - m1 = msg.nextstring() - assert m1 == "open" - m2 = msg.nextstring() - assert m2 == "/tmp/foobar" - m3 = msg.nextnum() - assert m3 == os.O_RDONLY - m4 = msg.nextnum() - assert m4 == 0777 - assert msg.end() - - g.write(MessageBuilder().packnum(0).packnum(77).getvalue()) - - msg = read_message(f, timeout=10.0) - m1 = msg.nextstring() - assert m1 == "dup" - m2 = msg.nextnum() - assert m2 == 77 - assert msg.end() - - g.write(MessageBuilder().packnum(0).packnum(78).getvalue()) - + expect(f, g, "ll_os.ll_os_open", ("/tmp/foobar", os.O_RDONLY, 0777), 77) + expect(f, g, "ll_os.ll_os_dup", (77,), 78) g.close() tail = f.read() f.close() @@ -81,51 +54,10 @@ t = Translation(entry_point, backend='c', standalone=True, sandbox=True) exe = t.compile() g, f = os.popen2(exe, "t", 0) - - msg = read_message(f, timeout=10.0) - m1 = msg.nextstring() - assert m1 == "open" - m2 = msg.nextstring() - assert m2 == "/tmp/foobar" - m3 = msg.nextnum() - assert m3 == os.O_RDONLY - m4 = msg.nextnum() - assert m4 == 0777 - assert msg.end() - - g.write(MessageBuilder().packnum(0).packnum(77).getvalue()) - - msg = read_message(f, timeout=10.0) - m1 = msg.nextstring() - assert m1 == "read" - m2 = msg.nextnum() - assert m2 == 77 - m3 = msg.nextsize_t() - assert m3 == 123 - assert msg.end() - - g.write(MessageBuilder().packnum(0).packstring("he\x00llo").getvalue()) - - msg = read_message(f, timeout=10.0) - m1 = msg.nextstring() - assert m1 == "write" - m2 = msg.nextnum() - assert m2 == 77 - m3 = msg.nextstring() - assert m3 == "world\x00!\x00" - assert msg.end() - - g.write(MessageBuilder().packnum(0).packsize_t(42).getvalue()) - - msg = read_message(f, timeout=10.0) - m1 = msg.nextstring() - assert m1 == "close" - m2 = msg.nextnum() - assert m2 == 77 - assert msg.end() - - g.write(MessageBuilder().packnum(0).packnum(0).getvalue()) - + expect(f, g, "ll_os.ll_os_open", ("/tmp/foobar", os.O_RDONLY, 0777), 77) + expect(f, g, "ll_os.ll_os_read", (77, 123), "he\x00llo") + expect(f, g, "ll_os.ll_os_write", (77, "world\x00!\x00"), 42) + expect(f, g, "ll_os.ll_os_close", (77,), None) g.close() tail = f.read() f.close() @@ -140,29 +72,31 @@ t = Translation(entry_point, backend='c', standalone=True, sandbox=True) exe = t.compile() g, f = os.popen2(exe, "t", 0) + expect(f, g, "ll_os.ll_os_dup2", (34, 56), None) + expect(f, g, "ll_os.ll_os_access", ("spam", 77), True) + g.close() + tail = f.read() + f.close() + assert tail == "" - msg = read_message(f, timeout=10.0) - m1 = msg.nextstring() - assert m1 == "dup2" - m2 = msg.nextnum() - assert m2 == 34 - m3 = msg.nextnum() - assert m3 == 56 - assert msg.end() - - g.write(MessageBuilder().packnum(0).packnum(0).getvalue()) - - msg = read_message(f, timeout=10.0) - m1 = msg.nextstring() - assert m1 == "access" - m2 = msg.nextstring() - assert m2 == "spam" - m3 = msg.nextnum() - assert m3 == 77 - assert msg.end() +def test_sandbox_4(): + from pypy.rpython.module.ll_os_stat import STAT_FIELDS, s_tuple_StatResult + from pypy.rlib.rarithmetic import r_longlong + r0x12380000007 = r_longlong(0x12380000007) - g.write(MessageBuilder().packnum(0).packnum(0).getvalue()) + def entry_point(argv): + st = os.stat("somewhere") + os.ftruncate(st.st_mode, st.st_size) # nonsense, just to see outside + return 0 + t = Translation(entry_point, backend='c', standalone=True, sandbox=True) + exe = t.compile() + g, f = os.popen2(exe, "t", 0) + sttuple = (55, 0, 0, 0, 0, 0, 0x12380000007, 0, 0, 0) + sttuple += (0,) * (len(STAT_FIELDS)-len(sttuple)) + expect(f, g, "ll_os.ll_os_stat", ("somewhere",), sttuple, + resulttype = s_tuple_StatResult) + expect(f, g, "ll_os.ll_os_ftruncate", (55, 0x12380000007), None) g.close() tail = f.read() f.close() Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandlib.py Fri Aug 17 15:05:56 2007 @@ -1,3 +1,4 @@ +import py import os, StringIO from pypy.tool.sourcetools import func_with_new_name from pypy.rpython.lltypesystem import rffi @@ -23,14 +24,10 @@ return output return func_with_new_name(do_xxx, 'do_%s' % name) - do_open = _make_method("open") - do_read = _make_method("read") - do_write = _make_method("write") - do_close = _make_method("close") - do_foobar = _make_method("foobar") - - TYPES = SandboxedProc.TYPES.copy() - TYPES["foobar"] = "s", "i" + do_ll_os__ll_os_open = _make_method("open") + do_ll_os__ll_os_read = _make_method("read") + do_ll_os__ll_os_write = _make_method("write") + do_ll_os__ll_os_close = _make_method("close") def test_lib(): @@ -56,12 +53,13 @@ ("write", (77, exe), 61), ("write", (77, "x1"), 61), ("write", (77, "y2"), 61), - ("close", (77,), 0), + ("close", (77,), None), ]) proc.handle_forever() assert proc.seen == len(proc.expected) def test_foobar(): + py.test.skip("to be updated") foobar = rffi.llexternal("foobar", [rffi.CCHARP], rffi.LONG) def entry_point(argv): s = rffi.str2charp(argv[1]); n = foobar(s); rffi.free_charp(s) From jlg at codespeak.net Fri Aug 17 15:06:56 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 17 Aug 2007 15:06:56 +0200 (CEST) Subject: [pypy-svn] r45813 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070817130656.C7BA38189@code0.codespeak.net> Author: jlg Date: Fri Aug 17 15:06:56 2007 New Revision: 45813 Modified: pypy/dist/pypy/lang/scheme/TODO.txt pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_eval.py Log: apply procedure introduced Modified: pypy/dist/pypy/lang/scheme/TODO.txt ============================================================================== --- pypy/dist/pypy/lang/scheme/TODO.txt (original) +++ pypy/dist/pypy/lang/scheme/TODO.txt Fri Aug 17 15:06:56 2007 @@ -23,7 +23,9 @@ - macros *are* not first-class objects - input/output operations -- missing datatypes: chars, strings, vectors +- missing datatypes: chars, vectors +- datatypes manipulation procedures + - switch to byte-code generation + eval instead of evaluating AST - random code stress test Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Fri Aug 17 15:06:56 2007 @@ -644,6 +644,22 @@ w_pair.cdr = w_obj return w_undefined +class Apply(W_Procedure): + _symbol_name = "apply" + + def procedure_tr(self, ctx, lst): + if len(lst) != 2: + raise WrongArgsNumber + + (w_procedure, w_lst) = lst + if not isinstance(w_procedure, W_Procedure): + raise WrongArgType(w_procedure, "Procedure") + + if not isinstance(w_lst, W_List): + raise WrongArgType(w_lst, "List") + + return w_procedure.call_tr(ctx, w_lst) + class Quit(W_Procedure): _symbol_name = "quit" @@ -693,7 +709,7 @@ w_obj = lst[0] if not isinstance(w_obj, W_Number): - raise WrongArgType(w_obj, 'Number') + raise WrongArgType(w_obj, "Number") return W_Boolean(self.predicate(w_obj)) @@ -1018,7 +1034,6 @@ map_name_val = {} w_name_val = DictWrapper(map_name_val) for (name, expr) in map_name_expr.items(): - #map_name_val[name] = expr.eval(local_ctx) map_name_val[name] = expr.eval_cf(local_ctx, self, map_name_symb[name], [body, w_name_symb, w_name_val], 3) @@ -1576,7 +1591,6 @@ class ContinuationFrame(object): def __init__(self, caller, continuation, evaluated_args = [], enum=0): - #assert hasattr(caller, "continue_tr") self.caller = caller assert isinstance(continuation, W_Root) self.continuation = continuation Modified: pypy/dist/pypy/lang/scheme/test/test_eval.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_eval.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_eval.py Fri Aug 17 15:06:56 2007 @@ -723,3 +723,19 @@ assert eval_(ctx, """(eq? (lambda () 1) (lambda () 2))""").to_boolean() is False +def test_apply(): + ctx = ExecutionContext() + assert eval_(ctx, "(apply + (list 3 4))").to_number() == 7 + + eval_(ctx, """(define compose + (lambda (f g) + (lambda args + (f (apply g args)))))""") + w_result = eval_(ctx, "((compose (lambda (x) (* x x)) +) 3 5)") + assert w_result.to_number() == 64 + + assert eval_(ctx, "(apply + '())").to_number() == 0 + py.test.raises(WrongArgsNumber, eval_, ctx, "(apply 1)") + py.test.raises(WrongArgType, eval_, ctx, "(apply 1 '(1))") + py.test.raises(WrongArgType, eval_, ctx, "(apply + 42)") + From jlg at codespeak.net Fri Aug 17 16:17:35 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 17 Aug 2007 16:17:35 +0200 (CEST) Subject: [pypy-svn] r45815 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070817141735.ED4028194@code0.codespeak.net> Author: jlg Date: Fri Aug 17 16:17:35 2007 New Revision: 45815 Modified: pypy/dist/pypy/lang/scheme/TODO.txt pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_eval.py Log: type-predicates procedures and equal? added Modified: pypy/dist/pypy/lang/scheme/TODO.txt ============================================================================== --- pypy/dist/pypy/lang/scheme/TODO.txt (original) +++ pypy/dist/pypy/lang/scheme/TODO.txt Fri Aug 17 16:17:35 2007 @@ -9,10 +9,7 @@ Do next ------- -- implement key functions - (apply, map and so on) - -- comparison: < > +- implement key procedures Do in some future ----------------- @@ -24,8 +21,19 @@ - input/output operations - missing datatypes: chars, vectors -- datatypes manipulation procedures + + manipulation procedures - switch to byte-code generation + eval instead of evaluating AST - random code stress test +Missing procedures +------------------ + #number: +< > <= >= quotient reminder modulo numberator denominator floor ceiling truncate round exp log sin cos tan asin acos atan sqrt expt make-rectangular make-polar real-part imag-part magnitude angle exact->inexact inexact->exact + +dynamic-wind +call-with-values +values +eval +scheme-report-environment +null-environment Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Fri Aug 17 16:17:35 2007 @@ -54,10 +54,10 @@ def eval_tr(self, ctx): return (self, None) - def eqv(self, w_obj): + def eq(self, w_obj): return self is w_obj - - eq = eqv + eqv = eq + equal = eqv class W_Undefined(W_Root): def to_string(self): @@ -116,8 +116,8 @@ if isinstance(w_obj, W_Boolean): return self.boolval is w_obj.boolval return False - eq = eqv + equal = eqv class W_String(W_Root): def __init__(self, val): @@ -167,6 +167,7 @@ return isinstance(w_obj, W_Real) \ and self.exact is w_obj.exact \ and self.realval == w_obj.realval + equal = eqv W_Number = W_Real @@ -296,6 +297,11 @@ raise SchemeSyntaxError return res + def equal(self, w_obj): + return isinstance(w_obj, W_Pair) and \ + self.car.equal(w_obj.car) and \ + self.cdr.equal(w_obj.cdr) + class W_Callable(W_Eval): def call_tr(self, ctx, lst): #usually tail-recursive call is normal call @@ -699,6 +705,15 @@ (a, b) = lst return W_Boolean(a.eqv(b)) +class EqualP(W_Procedure): + _symbol_name = "equal?" + + def procedure(self, ctx, lst): + if len(lst) != 2: + raise WrongArgsNumber + + (a, b) = lst + return W_Boolean(a.equal(b)) ## # Predicate ## @@ -782,24 +797,36 @@ ## # Type Pradicates ## - -class PairP(W_Procedure): - _symbol_name = "pair?" - +class TypePredicate(W_Procedure): def procedure(self, ctx, lst): if len(lst) != 1: raise WrongArgsNumber - return W_Boolean(isinstance(lst[0], W_Pair)) + return W_Boolean(self.predicate(lst[0])) -class ProcedureP(W_Procedure): - _symbol_name = "procedure?" +class BooleanP(TypePredicate): + _symbol_name = "boolean?" - def procedure(self, ctx, lst): - if len(lst) != 1: - raise WrongArgsNumber + def predicate(self, w_obj): + return isinstance(w_obj, W_Boolean) + +class SymbolP(TypePredicate): + _symbol_name = "symbol?" + + def predicate(self, w_obj): + return isinstance(w_obj, W_Symbol) - return W_Boolean(isinstance(lst[0], W_Procedure)) +class PairP(TypePredicate): + _symbol_name = "pair?" + + def predicate(self, w_obj): + return isinstance(w_obj, W_Pair) + +class ProcedureP(TypePredicate): + _symbol_name = "procedure?" + + def predicate(self, w_obj): + return isinstance(w_obj, W_Procedure) ## # Input/Output procedures @@ -1560,6 +1587,7 @@ return w_macro #undefined class LetSyntax(W_Macro): + #XXX letrec-syntax missing _symbol_name = "let-syntax" def call_tr(self, ctx, lst): Modified: pypy/dist/pypy/lang/scheme/test/test_eval.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_eval.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_eval.py Fri Aug 17 16:17:35 2007 @@ -640,6 +640,8 @@ ctx = ExecutionContext() assert eval_(ctx, "(pair? 1)").to_boolean() is False + assert eval_(ctx, "(pair? 'symb)").to_boolean() is False + assert eval_(ctx, "(pair? #f)").to_boolean() is False assert eval_(ctx, "(pair? '())").to_boolean() is False assert eval_(ctx, "(pair? +)").to_boolean() is False assert eval_(ctx, "(pair? (lambda () 1))").to_boolean() is False @@ -648,6 +650,8 @@ assert eval_(ctx, "(pair? (cons 1 2))").to_boolean() is True assert eval_(ctx, "(procedure? 1)").to_boolean() is False + assert eval_(ctx, "(procedure? 'symb)").to_boolean() is False + assert eval_(ctx, "(procedure? #f)").to_boolean() is False assert eval_(ctx, "(procedure? '())").to_boolean() is False assert eval_(ctx, "(procedure? '(1))").to_boolean() is False assert eval_(ctx, "(procedure? (list 1))").to_boolean() is False @@ -655,6 +659,27 @@ assert eval_(ctx, "(procedure? +)").to_boolean() is True assert eval_(ctx, "(procedure? (lambda () 1))").to_boolean() is True + assert eval_(ctx, "(symbol? 1)").to_boolean() is False + assert eval_(ctx, "(symbol? 'symb)").to_boolean() is True + assert eval_(ctx, "(symbol? #f)").to_boolean() is False + assert eval_(ctx, "(symbol? '())").to_boolean() is False + assert eval_(ctx, "(symbol? '(1))").to_boolean() is False + assert eval_(ctx, "(symbol? (list 1))").to_boolean() is False + assert eval_(ctx, "(symbol? (cons 1 2))").to_boolean() is False + assert eval_(ctx, "(symbol? +)").to_boolean() is False + assert eval_(ctx, "(symbol? (lambda () 1))").to_boolean() is False + + assert eval_(ctx, "(boolean? 1)").to_boolean() is False + assert eval_(ctx, "(boolean? 'symb)").to_boolean() is False + assert eval_(ctx, "(boolean? #f)").to_boolean() is True + assert eval_(ctx, "(boolean? #t)").to_boolean() is True + assert eval_(ctx, "(boolean? '())").to_boolean() is False + assert eval_(ctx, "(boolean? '(1))").to_boolean() is False + assert eval_(ctx, "(boolean? (list 1))").to_boolean() is False + assert eval_(ctx, "(boolean? (cons 1 2))").to_boolean() is False + assert eval_(ctx, "(boolean? +)").to_boolean() is False + assert eval_(ctx, "(boolean? (lambda () 1))").to_boolean() is False + def test_eqv(): ctx = ExecutionContext() @@ -723,6 +748,41 @@ assert eval_(ctx, """(eq? (lambda () 1) (lambda () 2))""").to_boolean() is False +def test_equal(): + ctx = ExecutionContext() + + assert eval_(ctx, "(equal? #t #t)").to_boolean() is True + assert eval_(ctx, "(equal? #f #f)").to_boolean() is True + assert eval_(ctx, "(equal? 'symb 'symb)").to_boolean() is True + assert eval_(ctx, "(equal? 'symb 'SYMB)").to_boolean() is True + assert eval_(ctx, "(equal? 42 42)").to_boolean() is True + assert eval_(ctx, "(equal? 42.1 42.1)").to_boolean() is True + #assert eval_(ctx, "(equal? #\a #\a)").to_boolean() is True + assert eval_(ctx, "(equal? '() '())").to_boolean() is True + assert eval_(ctx, """(let ((p (cons 1 2))) + (equal? p p))""").to_boolean() is True + #assert eval_(ctx, """(let ((p "a string")) + # (equal? p p))""").to_boolean() is True + assert eval_(ctx, """(let ((p (lambda (x) x))) + (equal? p p))""").to_boolean() is True + + assert eval_(ctx, "(equal? #t 'symb)").to_boolean() is False + assert eval_(ctx, "(equal? #f 42)").to_boolean() is False + assert eval_(ctx, "(equal? #t #f)").to_boolean() is False + assert eval_(ctx, "(equal? 'symb1 'symb2)").to_boolean() is False + assert eval_(ctx, "(equal? 42 42.0)").to_boolean() is False + assert eval_(ctx, "(equal? 42.0 42)").to_boolean() is False + assert eval_(ctx, "(equal? 42 43)").to_boolean() is False + assert eval_(ctx, "(equal? 42.1 42.2)").to_boolean() is False + #assert eval_(ctx, "(equal? #\a #\b)").to_boolean() is False + assert eval_(ctx, "(equal? (cons 1 2) (cons 1 2))").to_boolean() is True + #assert eval_(ctx, """(equal? "a string" + # "a string")""").to_boolean() is True + assert eval_(ctx, """(equal? (lambda () 1) + (lambda () 2))""").to_boolean() is False + assert eval_(ctx, "(equal? '(a (b) c) '(a (b) c))").to_boolean() is True + assert eval_(ctx, "(equal? '(a (b) c) '(a (e) c))").to_boolean() is False + def test_apply(): ctx = ExecutionContext() assert eval_(ctx, "(apply + (list 3 4))").to_number() == 7 @@ -738,4 +798,3 @@ py.test.raises(WrongArgsNumber, eval_, ctx, "(apply 1)") py.test.raises(WrongArgType, eval_, ctx, "(apply 1 '(1))") py.test.raises(WrongArgType, eval_, ctx, "(apply + 42)") - From jlg at codespeak.net Fri Aug 17 16:48:10 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 17 Aug 2007 16:48:10 +0200 (CEST) Subject: [pypy-svn] r45817 - pypy/dist/pypy/lang/scheme Message-ID: <20070817144810.086148197@code0.codespeak.net> Author: jlg Date: Fri Aug 17 16:48:10 2007 New Revision: 45817 Modified: pypy/dist/pypy/lang/scheme/object.py Log: s/PredicateNumber/NumberPredicate/; EquivalencePredicade as base class for eq? eqv? and equal? Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Fri Aug 17 16:48:10 2007 @@ -685,39 +685,38 @@ return w_promise.force(ctx) -class EqP(W_Procedure): - _symbol_name = "eq?" - +## +# Equivalnece Predicates +## +class EquivalnecePredicate(W_Procedure): def procedure(self, ctx, lst): if len(lst) != 2: raise WrongArgsNumber - (a, b) = lst - return W_Boolean(a.eq(b)) + return W_Boolean(self.predicate(a, b)) -class EqvP(W_Procedure): - _symbol_name = "eqv?" +class EqP(EquivalnecePredicate): + _symbol_name = "eq?" - def procedure(self, ctx, lst): - if len(lst) != 2: - raise WrongArgsNumber + def predicate(self, a, b): + return a.eq(b) - (a, b) = lst - return W_Boolean(a.eqv(b)) +class EqvP(EquivalnecePredicate): + _symbol_name = "eqv?" + + def predicate(self, a, b): + return a.eqv(b) -class EqualP(W_Procedure): +class EqualP(EquivalnecePredicate): _symbol_name = "equal?" - def procedure(self, ctx, lst): - if len(lst) != 2: - raise WrongArgsNumber + def predicate(self, a, b): + return a.equal(b) - (a, b) = lst - return W_Boolean(a.equal(b)) ## -# Predicate +# Number Predicates ## -class PredicateNumber(W_Procedure): +class NumberPredicate(W_Procedure): def procedure(self, ctx, lst): if len(lst) != 1: raise WrongArgsNumber @@ -731,7 +730,7 @@ def predicate(self, w_obj): raise NotImplementedError -class IntegerP(PredicateNumber): +class IntegerP(NumberPredicate): _symbol_name = "integer?" def predicate(self, w_obj): @@ -740,7 +739,7 @@ return True -class RealP(PredicateNumber): +class RealP(NumberPredicate): _symbol_name = "real?" def predicate(self, w_obj): @@ -749,7 +748,7 @@ class RationalP(RealP): _symbol_name = "rational?" -class NumberP(PredicateNumber): +class NumberP(NumberPredicate): _symbol_name = "number?" def predicate(self, w_obj): @@ -758,25 +757,25 @@ class ComplexP(NumberP): _symbol_name = "complex?" -class ExactP(PredicateNumber): +class ExactP(NumberPredicate): _symbol_name = "exact?" def predicate(self, w_obj): return w_obj.exact -class InexactP(PredicateNumber): +class InexactP(NumberPredicate): _symbol_name = "inexact?" def predicate(self, w_obj): return not w_obj.exact -class ZeroP(PredicateNumber): +class ZeroP(NumberPredicate): _symbol_name = "zero?" def predicate(self, w_obj): return w_obj.to_number() == 0.0 -class OddP(PredicateNumber): +class OddP(NumberPredicate): _symbol_name = "odd?" def predicate(self, w_obj): @@ -785,7 +784,7 @@ return w_obj.round() % 2 != 0 -class EvenP(PredicateNumber): +class EvenP(NumberPredicate): _symbol_name = "even?" def predicate(self, w_obj): From arigo at codespeak.net Fri Aug 17 16:59:47 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 16:59:47 +0200 (CEST) Subject: [pypy-svn] r45818 - in pypy/branch/pypy-more-rtti-inprogress/translator/sandbox: . test Message-ID: <20070817145947.9DE4080D8@code0.codespeak.net> Author: arigo Date: Fri Aug 17 16:59:47 2007 New Revision: 45818 Added: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py - copied, changed from r45812, pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/interact.py Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py Log: * starting a general virtual-paths-mapping class for sandboxed processes * pypy-c-sandbox compiles but there are still issues * add pypy_interact.py, specifically to run pypy-c-sandbox Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Fri Aug 17 16:59:47 2007 @@ -4,7 +4,8 @@ for the outer process, which can run CPython or PyPy. """ -import marshal, sys +import marshal, sys, os, posixpath +from pypy.rpython.module.ll_os_stat import STAT_FIELDS, s_tuple_StatResult from py.compat import subprocess def read_message(f, timeout=None): @@ -17,25 +18,31 @@ raise EOFError("timed out waiting for data") return marshal.load(f) -if sys.version_info < (2, 4): - def write_message(g, msg): - marshal.dump(msg, g) - g.flush() -else: - def write_message(g, msg): - marshal.dump(msg, g, 0) - g.flush() +def write_message(g, msg, resulttype=None): + if resulttype is None: + if sys.version_info < (2, 4): + marshal.dump(msg, g) + else: + marshal.dump(msg, g, 0) + else: + # use the exact result type for encoding + from pypy.rlib.rmarshal import get_marshaller + buf = [] + get_marshaller(resulttype)(buf, msg) + g.write(''.join(buf)) + g.flush() + class SandboxedProc(object): """Base class to control a sandboxed subprocess. Inherit from this class and implement all the do_xxx() methods for the external functions xxx that you want to support. """ - def __init__(self, args): + def __init__(self, args, executable=None): """'args' should a sequence of argument for the subprocess, starting with the full path of the executable. """ - self.popen = subprocess.Popen(args, + self.popen = subprocess.Popen(args, executable=executable, stdin=subprocess.PIPE, stdout=subprocess.PIPE) @@ -58,9 +65,9 @@ args = read_message(self.popen.stdout) except EOFError, e: break - answer = self.handle_message(fnname, *args) + answer, resulttype = self.handle_message(fnname, *args) write_message(self.popen.stdin, 0) # error code - always 0 for now - write_message(self.popen.stdin, answer) + write_message(self.popen.stdin, answer, resulttype) returncode = self.popen.wait() return returncode @@ -68,7 +75,8 @@ if '__' in fnname: raise ValueError("unsafe fnname") handler = getattr(self, 'do_' + fnname.replace('.', '__')) - return handler(*args) + resulttype = getattr(handler, 'resulttype', None) + return handler(*args), resulttype class SimpleIOSandboxedProc(SandboxedProc): @@ -128,3 +136,48 @@ self._error.write(data) return len(data) raise OSError("trying to write to fd %d" % (fd,)) + + +class VirtualOSError(Exception): + pass + +class VirtualizedSandboxedProc(SandboxedProc): + """Control a virtualized sandboxed process, which is given a custom + view on the filesystem and a custom environment. + """ + virtual_env = {} + virtual_cwd = '/tmp' + path_mapping = {} # maps virtual paths to real paths or None + + def do_ll_os__ll_os_envitems(self): + return self.virtual_env.items() + + def translate_path(self, vpath): + # XXX this assumes posix vpaths for now, but os-specific real paths + vpath = posixpath.join(self.virtual_cwd, vpath) + components = [component for component in vpath.split('/') if component] + # find the longest match in self.path_mapping + for i in range(len(components), -1, -1): + test = '/' + '/'.join(components[:i]) + if test in self.path_mapping: + break # found + else: + raise VirtualOSError("no access to vpath %r" % (vpath,)) + result = self.path_mapping[test] + if i < len(components): + result = os.path.join(result, *components[i:]) + if vpath.endswith(os.sep): + result += os.sep # re-add a trailing '/' if one was specified + print 'VPATH:', vpath, '=>', result + return result + + def build_stat_result(self, st): + result = tuple(st) + result += (0,) * (len(STAT_FIELDS) - len(result)) + return result + + def do_ll_os__ll_os_lstat(self, vpathname): + pathname = self.translate_path(vpathname) + st = os.lstat(pathname) + return self.build_stat_result(st) + do_ll_os__ll_os_lstat.resulttype = s_tuple_StatResult Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py Fri Aug 17 16:59:47 2007 @@ -12,14 +12,7 @@ msg = read_message(f, timeout=10.0) assert msg == args write_message(g, 0) - if resulttype is None: - write_message(g, result) - else: - # use the exact result type for encoding - from pypy.rlib.rmarshal import get_marshaller - buf = [] - get_marshaller(resulttype)(buf, result) - g.write(''.join(buf)) + write_message(g, result, resulttype) def test_sandbox_1(): From arigo at codespeak.net Fri Aug 17 17:04:58 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 17:04:58 +0200 (CEST) Subject: [pypy-svn] r45819 - in pypy/branch/pypy-more-rtti-inprogress: rpython translator/sandbox/test Message-ID: <20070817150458.5E44B819C@code0.codespeak.net> Author: arigo Date: Fri Aug 17 17:04:57 2007 New Revision: 45819 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py Log: os.path.join() is safe. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py Fri Aug 17 17:04:57 2007 @@ -70,4 +70,5 @@ for name, args, res in path_functions: func = getattr(os.path, name) llimpl = func_with_new_name(func, name) - _register_external(func, args, res, 'll_os_path.ll_%s' % name, llimpl=llimpl) + _register_external(func, args, res, 'll_os_path.ll_%s' % name, + llimpl=llimpl, sandboxsafe=True) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py Fri Aug 17 17:04:57 2007 @@ -121,3 +121,9 @@ print return 0 self.run(entry_point, ["3.011"], "2 4 13 75 2 1 3\n") + + def test_os_path_safe(self): + def entry_point(argv): + print os.path.join('tmp', argv[1]) + return 0 + self.run(entry_point, ["spam"], os.path.join("tmp", "spam")+'\n') From arigo at codespeak.net Fri Aug 17 18:01:15 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 18:01:15 +0200 (CEST) Subject: [pypy-svn] r45822 - pypy/branch/pypy-more-rtti-inprogress/translator/sandbox Message-ID: <20070817160115.C274E81A5@code0.codespeak.net> Author: arigo Date: Fri Aug 17 18:01:14 2007 New Revision: 45822 Added: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/autopath.py - copied unchanged from r45812, pypy/branch/pypy-more-rtti-inprogress/translator/autopath.py Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Log: Some progress. Now we need a way to report OSErrors back inside. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py Fri Aug 17 18:01:14 2007 @@ -6,20 +6,29 @@ pypy_interact.py """ -import sys +import sys, os +import autopath +from pypy.tool.udir import udir from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc from pypy.translator.sandbox.sandlib import VirtualizedSandboxedProc class PyPySandboxedProc(VirtualizedSandboxedProc, SimpleIOSandboxedProc): - argv0 = '/usr/bin/pypy-c' + argv0 = '/opt/pypy-c' virtual_cwd = '/tmp' virtual_env = {} def __init__(self, executable, arguments): super(PyPySandboxedProc, self).__init__([self.argv0] + arguments, executable=executable) + pypydist = os.path.dirname(os.path.abspath(autopath.pypydir)) self.path_mapping = { - self.argv0: executable, # can access its own executable + # can access its own executable + self.argv0: executable, + # can access the pure Python libraries + '/opt/lib-python': os.path.join(pypydist, 'lib-python'), + '/opt/pypy/lib': os.path.join(pypydist, 'pypy', 'lib'), + # can access the temporary usession directory as /tmp + self.virtual_cwd: str(udir), } Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Fri Aug 17 18:01:14 2007 @@ -147,14 +147,17 @@ """ virtual_env = {} virtual_cwd = '/tmp' - path_mapping = {} # maps virtual paths to real paths or None + path_mapping = {} # maps virtual paths to real paths def do_ll_os__ll_os_envitems(self): return self.virtual_env.items() + def do_ll_os__ll_os_getenv(self, name): + return self.virtual_env.get(name) + def translate_path(self, vpath): # XXX this assumes posix vpaths for now, but os-specific real paths - vpath = posixpath.join(self.virtual_cwd, vpath) + vpath = posixpath.normpath(posixpath.join(self.virtual_cwd, vpath)) components = [component for component in vpath.split('/') if component] # find the longest match in self.path_mapping for i in range(len(components), -1, -1): @@ -165,7 +168,11 @@ raise VirtualOSError("no access to vpath %r" % (vpath,)) result = self.path_mapping[test] if i < len(components): - result = os.path.join(result, *components[i:]) + # forbid escapes via '..' + remaining_components = components[i:] + if os.pardir in remaining_components: + raise VirtualOSError("dangerous '..' in %r" % (vpath,)) + result = os.path.join(result, *remaining_components) if vpath.endswith(os.sep): result += os.sep # re-add a trailing '/' if one was specified print 'VPATH:', vpath, '=>', result @@ -176,6 +183,12 @@ result += (0,) * (len(STAT_FIELDS) - len(result)) return result + def do_ll_os__ll_os_stat(self, vpathname): + pathname = self.translate_path(vpathname) + st = os.stat(pathname) + return self.build_stat_result(st) + do_ll_os__ll_os_stat.resulttype = s_tuple_StatResult + def do_ll_os__ll_os_lstat(self, vpathname): pathname = self.translate_path(vpathname) st = os.lstat(pathname) From arigo at codespeak.net Fri Aug 17 18:22:58 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 18:22:58 +0200 (CEST) Subject: [pypy-svn] r45823 - in pypy/branch/pypy-more-rtti-inprogress/translator/sandbox: . test Message-ID: <20070817162258.611FF8076@code0.codespeak.net> Author: arigo Date: Fri Aug 17 18:22:56 2007 New Revision: 45823 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py Log: Support for sending RPython exceptions of common classes into the sandboxed process. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py Fri Aug 17 18:22:56 2007 @@ -96,11 +96,22 @@ # check for errors error = load_int(loader) if error != 0: - raise IOError # XXX add support to raise the correct exception + reraise_error(error, loader) else: # no exception; the caller will decode the actual result return loader +def reraise_error(error, loader): + if error == 1: raise OSError(load_int(loader), "external error") + elif error == 2: raise IOError + elif error == 3: raise OverflowError + elif error == 4: raise ValueError + elif error == 5: raise ZeroDivisionError + elif error == 6: raise MemoryError + elif error == 7: raise KeyError + elif error == 8: raise IndexError + else: raise RuntimeError + def not_implemented_stub(msg): STDERR = 2 buf = rffi.str2charp(msg + '\n') Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Fri Aug 17 18:22:56 2007 @@ -32,6 +32,30 @@ g.write(''.join(buf)) g.flush() +# keep the table in sync with rsandbox.reraise_error() +EXCEPTION_TABLE = [ + (1, OSError), + (2, IOError), + (3, OverflowError), + (4, ValueError), + (5, ZeroDivisionError), + (6, MemoryError), + (7, KeyError), + (8, IndexError), + (9, RuntimeError), + ] + +def write_exception(g, exception): + for i, excclass in EXCEPTION_TABLE: + if isinstance(exception, excclass): + write_message(g, i) + if excclass is OSError: + write_message(g, exception.errno) + break + else: + raise Exception("cannot report %s exception to the subprocess" % ( + exception.__class__.__name__,)) + class SandboxedProc(object): """Base class to control a sandboxed subprocess. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py Fri Aug 17 18:22:56 2007 @@ -5,14 +5,18 @@ from pypy.rpython.lltypesystem import rffi from pypy.translator.interactive import Translation from pypy.translator.sandbox.sandlib import read_message, write_message +from pypy.translator.sandbox.sandlib import write_exception def expect(f, g, fnname, args, result, resulttype=None): msg = read_message(f, timeout=10.0) assert msg == fnname msg = read_message(f, timeout=10.0) assert msg == args - write_message(g, 0) - write_message(g, result, resulttype) + if isinstance(result, Exception): + write_exception(g, result) + else: + write_message(g, 0) + write_message(g, result, resulttype) def test_sandbox_1(): @@ -95,6 +99,24 @@ f.close() assert tail == "" +def test_oserror(): + def entry_point(argv): + try: + os.stat("somewhere") + except OSError, e: + os.close(e.errno) # nonsense, just to see outside + return 0 + + t = Translation(entry_point, backend='c', standalone=True, sandbox=True) + exe = t.compile() + g, f = os.popen2(exe, "t", 0) + expect(f, g, "ll_os.ll_os_stat", ("somewhere",), OSError(6321, "egg")) + expect(f, g, "ll_os.ll_os_close", (6321,), None) + g.close() + tail = f.read() + f.close() + assert tail == "" + class TestPrintedResults: def run(self, entry_point, args, expected): From arigo at codespeak.net Fri Aug 17 19:52:21 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 19:52:21 +0200 (CEST) Subject: [pypy-svn] r45824 - in pypy/branch/pypy-more-rtti-inprogress/translator/sandbox: . test Message-ID: <20070817175221.5536A8194@code0.codespeak.net> Author: arigo Date: Fri Aug 17 19:52:19 2007 New Revision: 45824 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandlib.py Log: Works! works! At least enough to start pypy-c-sandbox interactively and type stuff in it. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py Fri Aug 17 19:52:19 2007 @@ -13,9 +13,11 @@ from pypy.translator.sandbox.sandlib import VirtualizedSandboxedProc class PyPySandboxedProc(VirtualizedSandboxedProc, SimpleIOSandboxedProc): + debug = True argv0 = '/opt/pypy-c' virtual_cwd = '/tmp' - virtual_env = {} + virtual_env = {'PYTHONSTARTUP': ''} + virtual_console_isatty = True def __init__(self, executable, arguments): super(PyPySandboxedProc, self).__init__([self.argv0] + arguments, Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Fri Aug 17 19:52:19 2007 @@ -4,10 +4,24 @@ for the outer process, which can run CPython or PyPy. """ -import marshal, sys, os, posixpath +import py +import marshal, sys, os, posixpath, errno from pypy.rpython.module.ll_os_stat import STAT_FIELDS, s_tuple_StatResult +from pypy.tool.ansi_print import AnsiLog from py.compat import subprocess +class MyAnsiLog(AnsiLog): + KW_TO_COLOR = { + 'call': ((34,), False), + 'result': ((34,), False), + 'exception': ((34,), False), + 'vpath': ((35,), False), + } + +log = py.log.Producer("sandlib") +py.log.setconsumer("sandlib", MyAnsiLog()) + + def read_message(f, timeout=None): # warning: 'timeout' is not really reliable and should only be used # for testing. Also, it doesn't work if the file f does any buffering. @@ -45,16 +59,25 @@ (9, RuntimeError), ] -def write_exception(g, exception): +def write_exception(g, exception, tb=None): for i, excclass in EXCEPTION_TABLE: if isinstance(exception, excclass): write_message(g, i) if excclass is OSError: - write_message(g, exception.errno) + error = exception.errno + if error is None: + error = errno.EPERM + write_message(g, error) break else: - raise Exception("cannot report %s exception to the subprocess" % ( - exception.__class__.__name__,)) + # just re-raise the exception + raise exception.__class__, exception, tb + +def shortrepr(x): + r = repr(x) + if len(r) >= 80: + r = r[:20] + '...' + r[-8:] + return r class SandboxedProc(object): @@ -62,6 +85,8 @@ Inherit from this class and implement all the do_xxx() methods for the external functions xxx that you want to support. """ + debug = False + def __init__(self, args, executable=None): """'args' should a sequence of argument for the subprocess, starting with the full path of the executable. @@ -89,9 +114,24 @@ args = read_message(self.popen.stdout) except EOFError, e: break - answer, resulttype = self.handle_message(fnname, *args) - write_message(self.popen.stdin, 0) # error code - always 0 for now - write_message(self.popen.stdin, answer, resulttype) + if self.debug: + log.call('%s(%s)' % (fnname, + ', '.join([shortrepr(x) for x in args]))) + try: + answer, resulttype = self.handle_message(fnname, *args) + except Exception, e: + tb = sys.exc_info()[2] + write_exception(self.popen.stdin, e, tb) + if self.debug: + if str(e): + log.exception('%s: %s' % (e.__class__.__name__, e)) + else: + log.exception('%s' % (e.__class__.__name__,)) + else: + if self.debug: + log.result(shortrepr(answer)) + write_message(self.popen.stdin, 0) # error code - 0 for ok + write_message(self.popen.stdin, answer, resulttype) returncode = self.popen.wait() return returncode @@ -148,6 +188,11 @@ if fd == 0: if self._input is None: return "" + elif self._input.isatty(): + # don't wait for all 'size' chars if reading from a tty, + # to avoid blocking + # (XXX slow, but should not matter for interactive usage) + return self._input.read(1) else: return self._input.read(size) raise OSError("trying to read from fd %d" % (fd,)) @@ -171,8 +216,14 @@ """ virtual_env = {} virtual_cwd = '/tmp' + virtual_console_isatty = False + virtual_fd_range = range(3, 50) path_mapping = {} # maps virtual paths to real paths + def __init__(self, *args, **kwds): + super(VirtualizedSandboxedProc, self).__init__(*args, **kwds) + self.open_fds = {} # {virtual_fd: real_file_object} + def do_ll_os__ll_os_envitems(self): return self.virtual_env.items() @@ -199,7 +250,7 @@ result = os.path.join(result, *remaining_components) if vpath.endswith(os.sep): result += os.sep # re-add a trailing '/' if one was specified - print 'VPATH:', vpath, '=>', result + log.vpath('%s => %s' % (vpath, result)) return result def build_stat_result(self, st): @@ -218,3 +269,41 @@ st = os.lstat(pathname) return self.build_stat_result(st) do_ll_os__ll_os_lstat.resulttype = s_tuple_StatResult + + def do_ll_os__ll_os_isatty(self, fd): + return self.virtual_console_isatty and fd in (0, 1, 2) + + def allocate_fd(self, f): + for fd in self.virtual_fd_range: + if fd not in self.open_fds: + self.open_fds[fd] = f + return fd + else: + raise VirtualOSError("trying to open too many files") + + def do_ll_os__ll_os_open(self, vpathname, flags, mode): + pathname = self.translate_path(vpathname) + if flags & (os.O_RDONLY|os.O_WRONLY|os.O_RDWR) != os.O_RDONLY: + raise OSError(errno.EPERM, "write access denied") + # all other flags are ignored + f = open(pathname, "rb") + return self.allocate_fd(f) + + def do_ll_os__ll_os_close(self, fd): + try: + f = self.open_fds.pop(fd) + except KeyError: + raise OSError(errno.EBADF, "closing a bad file descriptor") + else: + f.close() + + def do_ll_os__ll_os_read(self, fd, size): + try: + f = self.open_fds[fd] + except KeyError: + return super(VirtualizedSandboxedProc, self).do_ll_os__ll_os_read( + fd, size) + else: + if not (0 <= size <= sys.maxint): + raise VirtualOSError("invalid read size") + return f.read(size) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandlib.py Fri Aug 17 19:52:19 2007 @@ -21,6 +21,8 @@ assert name == expectedmsg assert input == expectedinput self.seen += 1 + if isinstance(output, Exception): + raise output return output return func_with_new_name(do_xxx, 'do_%s' % name) @@ -96,3 +98,20 @@ output, error = proc.communicate("21\n") assert output == "Please enter a number:\nThe double is: 42\n" assert error == "" + +def test_oserror(): + def entry_point(argv): + try: + os.open("/tmp/foobar", os.O_RDONLY, 0777) + except OSError, e: + os.close(e.errno) # nonsense, just to see outside + return 0 + t = Translation(entry_point, backend='c', standalone=True, sandbox=True) + exe = t.compile() + + proc = MySandboxedProc([exe], expected = [ + ("open", ("/tmp/foobar", os.O_RDONLY, 0777), OSError(-42, "baz")), + ("close", (-42,), None), + ]) + proc.handle_forever() + assert proc.seen == len(proc.expected) From arigo at codespeak.net Fri Aug 17 19:58:03 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 19:58:03 +0200 (CEST) Subject: [pypy-svn] r45825 - pypy/branch/pypy-more-rtti-inprogress/translator/sandbox Message-ID: <20070817175803.4037A8194@code0.codespeak.net> Author: arigo Date: Fri Aug 17 19:58:02 2007 New Revision: 45825 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Log: just remembered about the readline(size) method of files in Python. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Fri Aug 17 19:58:02 2007 @@ -190,9 +190,8 @@ return "" elif self._input.isatty(): # don't wait for all 'size' chars if reading from a tty, - # to avoid blocking - # (XXX slow, but should not matter for interactive usage) - return self._input.read(1) + # to avoid blocking. Instead, stop after reading a line. + return self._input.readline(size) else: return self._input.read(size) raise OSError("trying to read from fd %d" % (fd,)) From arigo at codespeak.net Fri Aug 17 20:03:24 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 20:03:24 +0200 (CEST) Subject: [pypy-svn] r45826 - pypy/branch/pypy-more-rtti-inprogress/translator/sandbox Message-ID: <20070817180324.E47DD80C0@code0.codespeak.net> Author: arigo Date: Fri Aug 17 20:03:24 2007 New Revision: 45826 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Log: Some more functions. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Fri Aug 17 20:03:24 2007 @@ -285,7 +285,10 @@ if flags & (os.O_RDONLY|os.O_WRONLY|os.O_RDWR) != os.O_RDONLY: raise OSError(errno.EPERM, "write access denied") # all other flags are ignored - f = open(pathname, "rb") + try: + f = open(pathname, "rb") + except IOError, e: + raise OSError(e.errno, "open failed") return self.allocate_fd(f) def do_ll_os__ll_os_close(self, fd): @@ -306,3 +309,10 @@ if not (0 <= size <= sys.maxint): raise VirtualOSError("invalid read size") return f.read(size) + + def do_ll_os__ll_os_getcwd(self): + return self.virtual_cwd + + def do_ll_os__ll_os_strerror(self, errnum): + # unsure if this shouldn't be considered safeboxsafe + return os.strerror(errnum) or ('Unknown error %d' % (errnum,)) From fijal at codespeak.net Fri Aug 17 20:07:35 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 17 Aug 2007 20:07:35 +0200 (CEST) Subject: [pypy-svn] r45827 - pypy/branch/pypy-more-rtti-inprogress/rpython/tool Message-ID: <20070817180735.8972A8182@code0.codespeak.net> Author: fijal Date: Fri Aug 17 20:07:34 2007 New Revision: 45827 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py Log: Port fix from trunk. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py Fri Aug 17 20:07:34 2007 @@ -35,6 +35,7 @@ # always include pypy include dir pypypath = py.path.local(pypydir) + include_dirs = include_dirs[:] include_dirs.append(str(pypypath.join('translator', 'c', 'src'))) c_exec = build_executable([str(c_file)], include_dirs=include_dirs, From arigo at codespeak.net Fri Aug 17 20:12:49 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 20:12:49 +0200 (CEST) Subject: [pypy-svn] r45828 - pypy/branch/pypy-more-rtti-inprogress/module/posix Message-ID: <20070817181249.A4C7B819B@code0.codespeak.net> Author: arigo Date: Fri Aug 17 20:12:49 2007 New Revision: 45828 Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Log: don't capture the environment in the translated pypy Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Fri Aug 17 20:12:49 2007 @@ -268,14 +268,20 @@ class State: def __init__(self, space): + self.space = space self.w_environ = space.newdict() def startup(self, space): _convertenviron(space, self.w_environ) + def _freeze_(self): + # don't capture the environment in the translated pypy + self.space.call_method(self.w_environ, 'clear') + return True def get(space): return space.fromcache(State) def _convertenviron(space, w_env): + space.call_method(w_env, 'clear') for key, value in os.environ.items(): space.setitem(w_env, space.wrap(key), space.wrap(value)) From arigo at codespeak.net Fri Aug 17 20:13:18 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 20:13:18 +0200 (CEST) Subject: [pypy-svn] r45829 - pypy/branch/pypy-more-rtti-inprogress/translator/sandbox Message-ID: <20070817181318.70770819B@code0.codespeak.net> Author: arigo Date: Fri Aug 17 20:13:17 2007 New Revision: 45829 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py Log: Improve pypy_interact.py; added the --tmp=DIR option. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py Fri Aug 17 20:13:17 2007 @@ -3,12 +3,15 @@ """Interacts with a PyPy subprocess translated with --sandbox. Usage: - pypy_interact.py + pypy_interact.py [options] + +Options: + --tmp=DIR the real directory that corresponds to the virtual /tmp, + which is the virtual current dir (always read-only for now) """ import sys, os import autopath -from pypy.tool.udir import udir from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc from pypy.translator.sandbox.sandlib import VirtualizedSandboxedProc @@ -16,10 +19,10 @@ debug = True argv0 = '/opt/pypy-c' virtual_cwd = '/tmp' - virtual_env = {'PYTHONSTARTUP': ''} + virtual_env = {} virtual_console_isatty = True - def __init__(self, executable, arguments): + def __init__(self, executable, arguments, tmpdir): super(PyPySandboxedProc, self).__init__([self.argv0] + arguments, executable=executable) pypydist = os.path.dirname(os.path.abspath(autopath.pypydir)) @@ -30,13 +33,36 @@ '/opt/lib-python': os.path.join(pypydist, 'lib-python'), '/opt/pypy/lib': os.path.join(pypydist, 'pypy', 'lib'), # can access the temporary usession directory as /tmp - self.virtual_cwd: str(udir), + self.virtual_cwd: tmpdir, } if __name__ == '__main__': - if len(sys.argv) < 2: + from getopt import getopt # and not gnu_getopt! + options, arguments = getopt(sys.argv[1:], 't:h', ['tmp=', 'help']) + tmpdir = None + + def help(): print >> sys.stderr, __doc__ sys.exit(2) - sandproc = PyPySandboxedProc(sys.argv[1], sys.argv[2:]) + + for option, value in options: + if option in ['-t', '--tmp']: + value = os.path.abspath(value) + if not os.path.isdir(value): + raise OSError("%r is not a directory" % (value,)) + tmpdir = value + elif option in ['-h', '--help']: + help() + else: + raise ValueError(option) + + if len(arguments) < 1: + help() + + if tmpdir is None: + from pypy.tool.udir import udir + tmpdir = str(udir) + + sandproc = PyPySandboxedProc(arguments[0], arguments[1:], tmpdir=tmpdir) sandproc.interact() From arigo at codespeak.net Fri Aug 17 20:18:35 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 20:18:35 +0200 (CEST) Subject: [pypy-svn] r45830 - pypy/branch/pypy-more-rtti-inprogress/translator/sandbox Message-ID: <20070817181835.BA21A819B@code0.codespeak.net> Author: arigo Date: Fri Aug 17 20:18:35 2007 New Revision: 45830 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Log: os.listdir() Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Fri Aug 17 20:18:35 2007 @@ -316,3 +316,7 @@ def do_ll_os__ll_os_strerror(self, errnum): # unsure if this shouldn't be considered safeboxsafe return os.strerror(errnum) or ('Unknown error %d' % (errnum,)) + + def do_ll_os__ll_os_listdir(self, vpathname): + pathname = self.translate_path(vpathname) + return os.listdir(pathname) From arigo at codespeak.net Fri Aug 17 20:19:47 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 20:19:47 +0200 (CEST) Subject: [pypy-svn] r45831 - pypy/branch/pypy-more-rtti-inprogress/translator/sandbox Message-ID: <20070817181947.788F680B8@code0.codespeak.net> Author: arigo Date: Fri Aug 17 20:19:47 2007 New Revision: 45831 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py Log: Paranoia++ Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py Fri Aug 17 20:19:47 2007 @@ -62,7 +62,7 @@ if tmpdir is None: from pypy.tool.udir import udir - tmpdir = str(udir) + tmpdir = str(udir.ensure('sandbox', dir=1)) sandproc = PyPySandboxedProc(arguments[0], arguments[1:], tmpdir=tmpdir) sandproc.interact() From arigo at codespeak.net Fri Aug 17 20:29:36 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Aug 2007 20:29:36 +0200 (CEST) Subject: [pypy-svn] r45832 - pypy/branch/pypy-more-rtti-inprogress/translator/sandbox Message-ID: <20070817182936.D5C788191@code0.codespeak.net> Author: arigo Date: Fri Aug 17 20:29:35 2007 New Revision: 45832 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Log: Seems better to report a regular OSError for vpaths we don't know about. It allows e.g. 'import random' to succeed - otherwise it crashes trying to open '/dev/urandom'. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Fri Aug 17 20:29:35 2007 @@ -239,7 +239,7 @@ if test in self.path_mapping: break # found else: - raise VirtualOSError("no access to vpath %r" % (vpath,)) + raise OSError(errno.ENOENT, "no access to vpath %r" % (vpath,)) result = self.path_mapping[test] if i < len(components): # forbid escapes via '..' From arigo at codespeak.net Sat Aug 18 13:09:31 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 18 Aug 2007 13:09:31 +0200 (CEST) Subject: [pypy-svn] r45847 - pypy/branch/pypy-more-rtti-inprogress/translator/sandbox Message-ID: <20070818110931.705198203@code0.codespeak.net> Author: arigo Date: Sat Aug 18 13:09:31 2007 New Revision: 45847 Added: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/vfs.py (contents, props changed) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Log: A cleaner "virutal file system" approach for sandboxing. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/pypy_interact.py Sat Aug 18 13:09:31 2007 @@ -14,27 +14,41 @@ import autopath from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc from pypy.translator.sandbox.sandlib import VirtualizedSandboxedProc +from pypy.translator.sandbox.vfs import Dir, RealDir, RealFile class PyPySandboxedProc(VirtualizedSandboxedProc, SimpleIOSandboxedProc): debug = True - argv0 = '/opt/pypy-c' + argv0 = '/bin/pypy-c' virtual_cwd = '/tmp' virtual_env = {} virtual_console_isatty = True def __init__(self, executable, arguments, tmpdir): - super(PyPySandboxedProc, self).__init__([self.argv0] + arguments, - executable=executable) + # build a virtual file system: + # * can access its own executable + # * can access the pure Python libraries + # * can access the temporary usession directory as /tmp + executable = os.path.abspath(executable) + if tmpdir is None: + tmpdirnode = Dir({}) + else: + tmpdirnode = RealDir(tmpdir) pypydist = os.path.dirname(os.path.abspath(autopath.pypydir)) - self.path_mapping = { - # can access its own executable - self.argv0: executable, - # can access the pure Python libraries - '/opt/lib-python': os.path.join(pypydist, 'lib-python'), - '/opt/pypy/lib': os.path.join(pypydist, 'pypy', 'lib'), - # can access the temporary usession directory as /tmp - self.virtual_cwd: tmpdir, - } + + virtual_root = Dir({ + 'bin': Dir({ + 'pypy-c': RealFile(executable), + 'lib-python': RealDir(os.path.join(pypydist, 'lib-python')), + 'pypy': Dir({ + 'lib': RealDir(os.path.join(pypydist, 'pypy', 'lib')), + }), + }), + 'tmp': tmpdirnode, + }) + + super(PyPySandboxedProc, self).__init__(virtual_root, + [self.argv0] + arguments, + executable=executable) if __name__ == '__main__': @@ -60,9 +74,5 @@ if len(arguments) < 1: help() - if tmpdir is None: - from pypy.tool.udir import udir - tmpdir = str(udir.ensure('sandbox', dir=1)) - sandproc = PyPySandboxedProc(arguments[0], arguments[1:], tmpdir=tmpdir) sandproc.interact() Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py Sat Aug 18 13:09:31 2007 @@ -5,9 +5,10 @@ """ import py -import marshal, sys, os, posixpath, errno +import marshal, sys, os, posixpath, errno, stat from pypy.rpython.module.ll_os_stat import STAT_FIELDS, s_tuple_StatResult from pypy.tool.ansi_print import AnsiLog +from pypy.rlib.rarithmetic import r_longlong from py.compat import subprocess class MyAnsiLog(AnsiLog): @@ -79,6 +80,13 @@ r = r[:20] + '...' + r[-8:] return r +def signal_name(n): + import signal + for key, value in signal.__dict__.items(): + if key.startswith('SIG') and not key.startswith('SIG_') and value == n: + return key + return 'signal %d' % (n,) + class SandboxedProc(object): """Base class to control a sandboxed subprocess. @@ -86,14 +94,18 @@ for the external functions xxx that you want to support. """ debug = False + os_level_sandboxing = False # Linux only: /proc/PID/seccomp def __init__(self, args, executable=None): """'args' should a sequence of argument for the subprocess, starting with the full path of the executable. """ self.popen = subprocess.Popen(args, executable=executable, + bufsize=-1, stdin=subprocess.PIPE, - stdout=subprocess.PIPE) + stdout=subprocess.PIPE, + close_fds=True, + env={}) def poll(self): return self.popen.poll() @@ -108,6 +120,16 @@ returncode,)) def handle_until_return(self): + if self.os_level_sandboxing and sys.platform.startswith('linux2'): + # rationale: we wait until the child process started completely, + # letting the C library do any system calls it wants for + # initialization. When the RPython code starts up, it quickly + # does its first system call. At this point we turn seccomp on. + import select + select.select([self.popen.stdout], [], []) + f = open('/proc/%d/seccomp' % self.popen.pid, 'w') + print >> f, 1 + f.close() while True: try: fnname = read_message(self.popen.stdout) @@ -178,8 +200,12 @@ self._error = stderr or sys.stderr returncode = self.handle_until_return() if returncode != 0: - print >> self._error, "[Subprocess exit code: %d]" % ( - returncode,) + if os.name == 'posix' and returncode < 0: + print >> self._error, "[Subprocess killed by %s]" % ( + signal_name(-returncode),) + else: + print >> self._error, "[Subprocess exit code: %d]" % ( + returncode,) self._input = None self._output = None self._error = None @@ -206,9 +232,6 @@ raise OSError("trying to write to fd %d" % (fd,)) -class VirtualOSError(Exception): - pass - class VirtualizedSandboxedProc(SandboxedProc): """Control a virtualized sandboxed process, which is given a custom view on the filesystem and a custom environment. @@ -217,10 +240,10 @@ virtual_cwd = '/tmp' virtual_console_isatty = False virtual_fd_range = range(3, 50) - path_mapping = {} # maps virtual paths to real paths - def __init__(self, *args, **kwds): + def __init__(self, virtual_root, *args, **kwds): super(VirtualizedSandboxedProc, self).__init__(*args, **kwds) + self.virtual_root = virtual_root self.open_fds = {} # {virtual_fd: real_file_object} def do_ll_os__ll_os_envitems(self): @@ -232,25 +255,23 @@ def translate_path(self, vpath): # XXX this assumes posix vpaths for now, but os-specific real paths vpath = posixpath.normpath(posixpath.join(self.virtual_cwd, vpath)) - components = [component for component in vpath.split('/') if component] - # find the longest match in self.path_mapping - for i in range(len(components), -1, -1): - test = '/' + '/'.join(components[:i]) - if test in self.path_mapping: - break # found + dirnode = self.virtual_root + components = [component for component in vpath.split('/')] + for component in components[:-1]: + if component: + dirnode = dirnode.join(component) + if dirnode.kind != stat.S_IFDIR: + raise OSError(errno.ENOTDIR, component) + return dirnode, components[-1] + + def get_node(self, vpath): + dirnode, name = self.translate_path(vpath) + if name: + node = dirnode.join(name) else: - raise OSError(errno.ENOENT, "no access to vpath %r" % (vpath,)) - result = self.path_mapping[test] - if i < len(components): - # forbid escapes via '..' - remaining_components = components[i:] - if os.pardir in remaining_components: - raise VirtualOSError("dangerous '..' in %r" % (vpath,)) - result = os.path.join(result, *remaining_components) - if vpath.endswith(os.sep): - result += os.sep # re-add a trailing '/' if one was specified - log.vpath('%s => %s' % (vpath, result)) - return result + node = dirnode + log.vpath('%r => %r' % (vpath, node)) + return node def build_stat_result(self, st): result = tuple(st) @@ -258,16 +279,12 @@ return result def do_ll_os__ll_os_stat(self, vpathname): - pathname = self.translate_path(vpathname) - st = os.stat(pathname) + node = self.get_node(vpathname) + st = node.stat() return self.build_stat_result(st) do_ll_os__ll_os_stat.resulttype = s_tuple_StatResult - def do_ll_os__ll_os_lstat(self, vpathname): - pathname = self.translate_path(vpathname) - st = os.lstat(pathname) - return self.build_stat_result(st) - do_ll_os__ll_os_lstat.resulttype = s_tuple_StatResult + do_ll_os__ll_os_lstat = do_ll_os__ll_os_stat def do_ll_os__ll_os_isatty(self, fd): return self.virtual_console_isatty and fd in (0, 1, 2) @@ -278,26 +295,26 @@ self.open_fds[fd] = f return fd else: - raise VirtualOSError("trying to open too many files") + raise OSError(errno.EMFILE, "trying to open too many files") + + def get_file(self, fd): + try: + return self.open_fds[fd] + except KeyError: + raise OSError(errno.EBADF, "bad file descriptor") def do_ll_os__ll_os_open(self, vpathname, flags, mode): - pathname = self.translate_path(vpathname) + node = self.get_node(vpathname) if flags & (os.O_RDONLY|os.O_WRONLY|os.O_RDWR) != os.O_RDONLY: raise OSError(errno.EPERM, "write access denied") # all other flags are ignored - try: - f = open(pathname, "rb") - except IOError, e: - raise OSError(e.errno, "open failed") + f = node.open() return self.allocate_fd(f) def do_ll_os__ll_os_close(self, fd): - try: - f = self.open_fds.pop(fd) - except KeyError: - raise OSError(errno.EBADF, "closing a bad file descriptor") - else: - f.close() + f = self.get_file(fd) + del self.open_fds[fd] + f.close() def do_ll_os__ll_os_read(self, fd, size): try: @@ -307,8 +324,15 @@ fd, size) else: if not (0 <= size <= sys.maxint): - raise VirtualOSError("invalid read size") - return f.read(size) + raise OSError(errno.EINVAL, "invalid read size") + # don't try to read more than 256KB at once here + return f.read(min(size, 256*1024)) + + def do_ll_os__ll_os_lseek(self, fd, pos, how): + f = self.get_file(fd) + f.seek(pos, how) + return f.tell() + do_ll_os__ll_os_lseek.resulttype = r_longlong def do_ll_os__ll_os_getcwd(self): return self.virtual_cwd @@ -318,5 +342,5 @@ return os.strerror(errnum) or ('Unknown error %d' % (errnum,)) def do_ll_os__ll_os_listdir(self, vpathname): - pathname = self.translate_path(vpathname) - return os.listdir(pathname) + node = self.get_node(vpathname) + return node.keys() Added: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/vfs.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/vfs.py Sat Aug 18 13:09:31 2007 @@ -0,0 +1,110 @@ +import os +import stat, errno + +UID = 1000 +GID = 1000 +ATIME = MTIME = CTIME = 0 +INO_COUNTER = 0 + + +class FSObject(object): + read_only = True + + def stat(self): + try: + st_ino = self._st_ino + except AttributeError: + global INO_COUNTER + INO_COUNTER += 1 + st_ino = self._st_ino = INO_COUNTER + st_dev = 1 + st_nlink = 1 + st_size = self.getsize() + st_mode = self.kind + st_mode |= stat.S_IWUSR | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH + if self.kind == stat.S_IFDIR: + st_mode |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH + if self.read_only: + st_uid = 0 # read-only files are virtually owned by root + st_gid = 0 + else: + st_uid = UID # read-write files are owned by this virtual user + st_gid = GID + st_atime = ATIME + st_mtime = MTIME + st_ctime = CTIME + return os.stat_result( + (st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid, + st_size, st_atime, st_mtime, st_ctime)) + + def keys(self): + raise OSError(errno.ENOTDIR, self) + + def open(self): + raise OSError(errno.EACCES, self) + + def getsize(self): + return 0 + + +class Dir(FSObject): + kind = stat.S_IFDIR + def __init__(self, entries={}): + self.entries = entries + def keys(self): + return self.entries.keys() + def join(self, name): + try: + return self.entries[name] + except KeyError: + raise OSError(errno.ENOENT, name) + +class RealDir(Dir): + # If show_dotfiles=False, we pretend that all files whose name starts + # with '.' simply don't exist. If follow_links=True, then symlinks are + # transparently followed (they look like a regular file or directory to + # the sandboxed process). If follow_links=False, the subprocess is + # not allowed to access them at all. + def __init__(self, path, show_dotfiles=False, follow_links=False): + self.path = path + self.show_dotfiles = show_dotfiles + self.follow_links = follow_links + def __repr__(self): + return '' % (self.path,) + def keys(self): + names = os.listdir(self.path) + if not self.show_dotfiles: + names = [name for name in names if not name.startswith('.')] + return names + def join(self, name): + if name.startswith('.') and not self.show_dotfiles: + raise OSError(errno.ENOENT, name) + path = os.path.join(self.path, name) + if self.follow_links: + st = os.stat(path) + else: + st = os.lstat(path) + if stat.S_ISDIR(st.st_mode): + return RealDir(path, show_dotfiles = self.show_dotfiles, + follow_links = self.follow_links) + elif stat.S_ISREG(st.st_mode): + return RealFile(path) + else: + # don't allow access to symlinks and other special files + raise OSError(errno.EACCES, path) + +class File(FSObject): + kind = stat.S_IFREG + +class RealFile(File): + def __init__(self, path): + self.path = path + def __repr__(self): + return '' % (self.path,) + def getsize(self): + return os.stat(self.path).st_size + def open(self): + try: + return open(self.path, "rb") + except IOError, e: + raise OSError(e.errno, "open failed") From fijal at codespeak.net Sat Aug 18 13:23:19 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 18 Aug 2007 13:23:19 +0200 (CEST) Subject: [pypy-svn] r45848 - pypy/dist/pypy/doc Message-ID: <20070818112319.D5818820A@code0.codespeak.net> Author: fijal Date: Sat Aug 18 13:23:18 2007 New Revision: 45848 Added: pypy/dist/pypy/doc/maintainers.txt (contents, props changed) Log: A rough list of parts of pypy to fill with maintainers Added: pypy/dist/pypy/doc/maintainers.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/maintainers.txt Sat Aug 18 13:23:18 2007 @@ -0,0 +1,58 @@ +Please fill in yourself in any part which you would like to help +maintaining: + +* Jit: + * codegens + * x86 + * ppc + * ... more stuff follows +* Backends: + * C + * LLVM + * CLI + * JVM + * JavaScript + * CL + * Squeak + * ?Flex? +* Different frontends: + * prolog + * JavaScript + * scheme +* Objspaces: + * flow + * std + * ?logic? + * taint + * proxy + * ... +* Interpreter: + ... +* Transformations: + * stackless + * ... +* Library: + * aop + * distribution + * app-level stackless + * constraints + * ontology + * pyrepl +* Modules: + * general + * clr +* RPython: + * lltypesystem + * ootypesystem + * rffi +* Rlib: + * cairo + * sdl + * parsing + * ... +* Others: + * extension compiler + * config + * dotviewer + +... \ No newline at end of file From pedronis at codespeak.net Sat Aug 18 16:55:03 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 18 Aug 2007 16:55:03 +0200 (CEST) Subject: [pypy-svn] r45854 - pypy/dist/pypy/doc Message-ID: <20070818145503.E011182B0@code0.codespeak.net> Author: pedronis Date: Sat Aug 18 16:55:01 2007 New Revision: 45854 Removed: pypy/dist/pypy/doc/maintainers.txt Log: remove for now From arigo at codespeak.net Sun Aug 19 19:32:24 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Aug 2007 19:32:24 +0200 (CEST) Subject: [pypy-svn] r45871 - pypy/dist/pypy/translator/goal Message-ID: <20070819173224.84A7681E1@code0.codespeak.net> Author: arigo Date: Sun Aug 19 19:32:24 2007 New Revision: 45871 Removed: pypy/dist/pypy/translator/goal/app_basic_example.py Modified: pypy/dist/pypy/translator/goal/targetmultiplespaces.py pypy/dist/pypy/translator/goal/targetpypystandalone.py Log: Kill the execution of app_basic_example.py at the start of a translation. This causes problems like pre-importing the 'site' module. Modified: pypy/dist/pypy/translator/goal/targetmultiplespaces.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetmultiplespaces.py (original) +++ pypy/dist/pypy/translator/goal/targetmultiplespaces.py Sun Aug 19 19:32:24 2007 @@ -79,12 +79,6 @@ space2.exec_(open(filename).read(), w_dict, w_dict) w_entry_point_2 = space2.getitem(w_dict, space2.wrap('entry_point')) - # sanity-check: call the entry point - res = entry_point(["pypy", "app_basic_example.py"]) - assert res == 0 - res = entry_point(["pypy", "--space2", "app_basic_example.py"]) - assert res == 0 - return entry_point, None, PyPyAnnotatorPolicy() Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetpypystandalone.py Sun Aug 19 19:32:24 2007 @@ -10,7 +10,6 @@ from pypy.tool.option import make_objspace thisdir = py.magic.autopath().dirpath() -app_basic_example_path = str(thisdir.join("app_basic_example.py")) try: this_dir = os.path.dirname(__file__) @@ -171,10 +170,6 @@ space.exec_(open(filename).read(), w_dict, w_dict) entry_point = create_entry_point(space, w_dict) - # sanity-check: call the entry point - res = entry_point(["pypy", app_basic_example_path]) - assert res == 0 - return entry_point, None, PyPyAnnotatorPolicy(single_space = space) def interface(self, ns): From fijal at codespeak.net Mon Aug 20 15:55:59 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 20 Aug 2007 15:55:59 +0200 (CEST) Subject: [pypy-svn] r45877 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070820135559.799A581DA@code0.codespeak.net> Author: fijal Date: Mon Aug 20 15:55:57 2007 New Revision: 45877 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: A proper support for CConstant (right now only ints). Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py Mon Aug 20 15:55:57 2007 @@ -2,6 +2,7 @@ import ctypes import ctypes.util import os +import py from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.extfunc import ExtRegistryEntry from pypy.rlib.objectmodel import Symbolic @@ -425,14 +426,20 @@ # ____________________________________________ def get_ctypes_callable(funcptr): - if getattr(funcptr._obj, 'source', None) is not None: - # give up - for tests with an inlined bit of C code - raise NotImplementedError("cannot call a C function defined in " - "a custom C source snippet") FUNCTYPE = lltype.typeOf(funcptr).TO funcname = funcptr._obj._name libraries = getattr(funcptr._obj, 'libraries', None) - if not libraries: + if getattr(funcptr._obj, 'sources', None): + # compile the library + from pypy.translator.tool.cbuild import compile_c_module + obj = funcptr._obj + name = 'ctypes_' + obj._name + d = py.path.local(obj.sources[0]).dirpath() + compile_c_module(obj.sources, name, obj.include_dirs, obj.libraries) + # ARGH! win issues here + clib = ctypes.cdll.LoadLibrary(str(d.join(name)) + '.so') + cfunc = getattr(clib, funcname, None) + elif not libraries: cfunc = getattr(standard_c_lib, funcname, None) else: cfunc = None Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Mon Aug 20 15:55:57 2007 @@ -6,20 +6,8 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic from pypy.rlib import rarithmetic -import os - -class CConstant(Symbolic): - """ A C-level constant, maybe #define, rendered directly. - """ - def __init__(self, c_name, TP): - self.c_name = c_name - self.TP = TP - - def annotation(self): - return lltype_to_annotation(self.TP) - - def lltype(self): - return self.TP +import os, py +from pypy.tool.udir import udir def llexternal(name, args, result, _callable=None, sources=[], includes=[], libraries=[], include_dirs=[], sandboxsafe=False): @@ -99,12 +87,6 @@ def CStructPtr(*args, **kwds): return lltype.Ptr(CStruct(*args, **kwds)) -#def CArray(field): -# return lltype.Array(field, hints={'nolength':True}) - -#def CArrayPtr(field): -# return lltype.Ptr(CArray(fld)) - def COpaque(name, hints=None, **kwds): if hints is None: hints = {} @@ -123,23 +105,30 @@ def COpaquePtr(*args, **kwds): return lltype.Ptr(COpaque(*args, **kwds)) -def CExternVariable(TYPE, name): +def CExternVariable(TYPE, name, **kwds): """Return a pair of functions - a getter and a setter - to access the given global C variable. """ - # XXX THIS IS ONLY A QUICK HACK TO MAKE IT WORK - # In general, we need to re-think a few things to be more consistent, - # e.g. what if a CStruct, COpaque or CExternVariable requires - # some #include... - assert not isinstance(TYPE, lltype.ContainerType) - CTYPE = lltype.FixedSizeArray(TYPE, 1) - c_variable_ref = CConstant('(&%s)' % (name,), lltype.Ptr(CTYPE)) - def getter(): - return c_variable_ref[0] - def setter(newvalue): - c_variable_ref[0] = newvalue - return (func_with_new_name(getter, '%s_getter' % (name,)), - func_with_new_name(setter, '%s_setter' % (name,))) + assert TYPE is lltype.Signed # we need to-c-mapping for that + src = py.code.Source(""" + #include + int _rffi_get_%(name)s() + { + return %(name)s; + } + void _rffi_set_%(name)s(int arg) + { + %(name)s = arg; + } + """ % {'name':name}) + csrc = udir.join(name + "_getset.c") + csrc.write(str(src)) + getter = llexternal('_rffi_get_' + name, [], TYPE, sources=[str(csrc)], + **kwds) + setter = llexternal('_rffi_set_' + name, [TYPE], lltype.Void, + sources=[str(csrc)], **kwds) + + return getter, setter get_errno, set_errno = CExternVariable(lltype.Signed, 'errno') @@ -210,19 +199,19 @@ cast = ll2ctypes.force_cast # a forced, no-checking cast def size_and_sign(tp): - if tp is lltype.Char: - return 1, False - if tp is lltype.Float: - return 8, False - assert isinstance(tp, lltype.Number) - if tp is lltype.Signed: - unsigned = False - else: + size = sizeof(tp) + try: unsigned = not tp._type.SIGNED - return sizeof(tp), unsigned + except AttributeError: + if tp in [lltype.Char, lltype.Float, lltype.Signed]: + unsigned = False + else: + unsigned = True + return size, unsigned def sizeof(tp): - # works only for int types! + if isinstance(tp, lltype.FixedSizeArray): + return sizeof(tp.OF) * tp.length if tp is lltype.Char: return 1 if tp is lltype.Float: From arigo at codespeak.net Mon Aug 20 16:08:40 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Aug 2007 16:08:40 +0200 (CEST) Subject: [pypy-svn] r45878 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070820140840.9ECEA81DA@code0.codespeak.net> Author: arigo Date: Mon Aug 20 16:08:40 2007 New Revision: 45878 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: Revert r45877: there are issues that should be fixed first. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py Mon Aug 20 16:08:40 2007 @@ -2,7 +2,6 @@ import ctypes import ctypes.util import os -import py from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.extfunc import ExtRegistryEntry from pypy.rlib.objectmodel import Symbolic @@ -426,20 +425,14 @@ # ____________________________________________ def get_ctypes_callable(funcptr): + if getattr(funcptr._obj, 'source', None) is not None: + # give up - for tests with an inlined bit of C code + raise NotImplementedError("cannot call a C function defined in " + "a custom C source snippet") FUNCTYPE = lltype.typeOf(funcptr).TO funcname = funcptr._obj._name libraries = getattr(funcptr._obj, 'libraries', None) - if getattr(funcptr._obj, 'sources', None): - # compile the library - from pypy.translator.tool.cbuild import compile_c_module - obj = funcptr._obj - name = 'ctypes_' + obj._name - d = py.path.local(obj.sources[0]).dirpath() - compile_c_module(obj.sources, name, obj.include_dirs, obj.libraries) - # ARGH! win issues here - clib = ctypes.cdll.LoadLibrary(str(d.join(name)) + '.so') - cfunc = getattr(clib, funcname, None) - elif not libraries: + if not libraries: cfunc = getattr(standard_c_lib, funcname, None) else: cfunc = None Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Mon Aug 20 16:08:40 2007 @@ -6,8 +6,20 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic from pypy.rlib import rarithmetic -import os, py -from pypy.tool.udir import udir +import os + +class CConstant(Symbolic): + """ A C-level constant, maybe #define, rendered directly. + """ + def __init__(self, c_name, TP): + self.c_name = c_name + self.TP = TP + + def annotation(self): + return lltype_to_annotation(self.TP) + + def lltype(self): + return self.TP def llexternal(name, args, result, _callable=None, sources=[], includes=[], libraries=[], include_dirs=[], sandboxsafe=False): @@ -87,6 +99,12 @@ def CStructPtr(*args, **kwds): return lltype.Ptr(CStruct(*args, **kwds)) +#def CArray(field): +# return lltype.Array(field, hints={'nolength':True}) + +#def CArrayPtr(field): +# return lltype.Ptr(CArray(fld)) + def COpaque(name, hints=None, **kwds): if hints is None: hints = {} @@ -105,30 +123,23 @@ def COpaquePtr(*args, **kwds): return lltype.Ptr(COpaque(*args, **kwds)) -def CExternVariable(TYPE, name, **kwds): +def CExternVariable(TYPE, name): """Return a pair of functions - a getter and a setter - to access the given global C variable. """ - assert TYPE is lltype.Signed # we need to-c-mapping for that - src = py.code.Source(""" - #include - int _rffi_get_%(name)s() - { - return %(name)s; - } - void _rffi_set_%(name)s(int arg) - { - %(name)s = arg; - } - """ % {'name':name}) - csrc = udir.join(name + "_getset.c") - csrc.write(str(src)) - getter = llexternal('_rffi_get_' + name, [], TYPE, sources=[str(csrc)], - **kwds) - setter = llexternal('_rffi_set_' + name, [TYPE], lltype.Void, - sources=[str(csrc)], **kwds) - - return getter, setter + # XXX THIS IS ONLY A QUICK HACK TO MAKE IT WORK + # In general, we need to re-think a few things to be more consistent, + # e.g. what if a CStruct, COpaque or CExternVariable requires + # some #include... + assert not isinstance(TYPE, lltype.ContainerType) + CTYPE = lltype.FixedSizeArray(TYPE, 1) + c_variable_ref = CConstant('(&%s)' % (name,), lltype.Ptr(CTYPE)) + def getter(): + return c_variable_ref[0] + def setter(newvalue): + c_variable_ref[0] = newvalue + return (func_with_new_name(getter, '%s_getter' % (name,)), + func_with_new_name(setter, '%s_setter' % (name,))) get_errno, set_errno = CExternVariable(lltype.Signed, 'errno') @@ -199,19 +210,19 @@ cast = ll2ctypes.force_cast # a forced, no-checking cast def size_and_sign(tp): - size = sizeof(tp) - try: + if tp is lltype.Char: + return 1, False + if tp is lltype.Float: + return 8, False + assert isinstance(tp, lltype.Number) + if tp is lltype.Signed: + unsigned = False + else: unsigned = not tp._type.SIGNED - except AttributeError: - if tp in [lltype.Char, lltype.Float, lltype.Signed]: - unsigned = False - else: - unsigned = True - return size, unsigned + return sizeof(tp), unsigned def sizeof(tp): - if isinstance(tp, lltype.FixedSizeArray): - return sizeof(tp.OF) * tp.length + # works only for int types! if tp is lltype.Char: return 1 if tp is lltype.Float: From arigo at codespeak.net Mon Aug 20 16:57:25 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Aug 2007 16:57:25 +0200 (CEST) Subject: [pypy-svn] r45879 - in pypy/branch/pypy-more-rtti-inprogress/rpython: . lltypesystem Message-ID: <20070820145725.17E6F8157@code0.codespeak.net> Author: arigo Date: Mon Aug 20 16:57:24 2007 New Revision: 45879 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/annlowlevel.py pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lltype.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/typesystem.py Log: Fix for an issue where multiple _func objects have the same graph. They were created by multiple calls to rtyper.getcallable(), once without particular arguments, and once from annlowlevel.py with extra **fnobjattrs. In details: * getcallable() now always reads extra fnobj attributes from the Python function object's '_fnobjattrs_' attribute, if any, so that it always return an equal _func object. * this allows us to revert the recently-introduced **fnobjattrs arguments in annlowlevel.py. * make _func objects really immutable, to avoid surprizes with hash(). * shuffle things around in ll2ctypes to cope with this. translator/c/test/test_newgc is now passing. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/annlowlevel.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/annlowlevel.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/annlowlevel.py Mon Aug 20 16:57:24 2007 @@ -156,8 +156,7 @@ self.pending.append((ll_function, graph, args_s, s_result)) return graph - def delayedfunction(self, ll_function, args_s, s_result, needtype=False, - **fnobjattrs): + def delayedfunction(self, ll_function, args_s, s_result, needtype=False): # get a delayed pointer to the low-level function, annotated as # specified. The pointer is only valid after finish() was called. graph = self.getgraph(ll_function, args_s, s_result) @@ -168,13 +167,13 @@ FUNCTYPE = lltype.FuncType(ARGS, RESULT) else: FUNCTYPE = None - return self.graph2delayed(graph, FUNCTYPE, **fnobjattrs) + return self.graph2delayed(graph, FUNCTYPE) def constfunc(self, ll_function, args_s, s_result): p = self.delayedfunction(ll_function, args_s, s_result) return Constant(p, lltype.typeOf(p)) - def graph2delayed(self, graph, FUNCTYPE=None, **fnobjattrs): + def graph2delayed(self, graph, FUNCTYPE=None): if FUNCTYPE is None: FUNCTYPE = lltype.ForwardReference() # obscure hack: embed the name of the function in the string, so @@ -182,7 +181,7 @@ # is really computed name = "delayed!%s" % (graph.name,) delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), name, solid=True) - self.delayedfuncs.append((delayedptr, graph, fnobjattrs)) + self.delayedfuncs.append((delayedptr, graph)) return delayedptr def graph2const(self, graph): @@ -260,10 +259,8 @@ for p, repr, obj in self.delayedconsts: p._become(repr.convert_const(obj)) rtyper.call_all_setups() - for p, graph, fnobjattrs in self.delayedfuncs: + for p, graph in self.delayedfuncs: real_p = rtyper.getcallable(graph) - for key, value in fnobjattrs.items(): - setattr(rtyper.type_system.deref(real_p), key, value) REAL = lltype.typeOf(real_p).TO FUNCTYPE = lltype.typeOf(p).TO if isinstance(FUNCTYPE, lltype.ForwardReference): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Mon Aug 20 16:57:24 2007 @@ -106,10 +106,15 @@ if impl: if rtyper.annotator.translator.config.translation.sandbox: impl.dont_inline = True + # store some attributes to the 'impl' function, where + # the eventual call to rtyper.getcallable() will find them + # and transfer them to the final lltype.functionptr(). + impl._llfnobjattrs_ = { + '_name': self.name, + '_safe_not_sandboxed': self.safe_not_sandboxed, + } obj = rtyper.getannmixlevel().delayedfunction( - impl, signature_args, hop.s_result, - _name=self.name, - _safe_not_sandboxed=self.safe_not_sandboxed) + impl, signature_args, hop.s_result) else: #if not self.safe_not_sandboxed: # print '>>>>>>>>>>>>>-----------------------------------' Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py Mon Aug 20 16:57:24 2007 @@ -377,9 +377,9 @@ else: raise NotImplementedError("array with an explicit length") elif isinstance(T.TO, lltype.FuncType): - funcptr = lltype.functionptr(T.TO, getattr(cobj, '__name__', '?')) - make_callable_via_ctypes(funcptr, cfunc=cobj) - return funcptr + _callable = get_ctypes_trampoline(T.TO, cobj) + return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), + _callable=_callable) elif isinstance(T.TO, lltype.OpaqueType): container = lltype._opaque(T.TO) else: @@ -465,25 +465,29 @@ cfunc.restype = get_ctypes_type(FUNCTYPE.RESULT) return cfunc -def make_callable_via_ctypes(funcptr, cfunc=None): - RESULT = lltype.typeOf(funcptr).TO.RESULT - if cfunc is None: - cfunc1 = [] - else: - cfunc1 = [cfunc] +class LL2CtypesCallable(object): + # a special '_callable' object that invokes ctypes - def invoke_via_ctypes(*argvalues): - if cfunc1: - cfunc = cfunc1[0] - else: + def __init__(self, FUNCTYPE): + self.FUNCTYPE = FUNCTYPE + self.trampoline = None + #self.funcptr = ... set later + + def __call__(self, *argvalues): + if self.trampoline is None: # lazily build the corresponding ctypes function object - cfunc = get_ctypes_callable(funcptr) - cfunc1.append(cfunc) # cache + cfunc = get_ctypes_callable(self.funcptr) + self.trampoline = get_ctypes_trampoline(self.FUNCTYPE, cfunc) # perform the call + return self.trampoline(*argvalues) + +def get_ctypes_trampoline(FUNCTYPE, cfunc): + RESULT = FUNCTYPE.RESULT + def invoke_via_ctypes(*argvalues): cargs = [lltype2ctypes(value) for value in argvalues] cres = cfunc(*cargs) return ctypes2lltype(RESULT, cres) - funcptr._obj._callable = invoke_via_ctypes + return invoke_via_ctypes def force_cast(RESTYPE, value): """Cast a value to a result type, trying to use the same rules as C.""" Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lltype.py Mon Aug 20 16:57:24 2007 @@ -1538,9 +1538,9 @@ class _func(_container): def __init__(self, TYPE, **attrs): - self._TYPE = TYPE - self._name = "?" - self._callable = None + attrs.setdefault('_TYPE', TYPE) + attrs.setdefault('_name', '?') + attrs.setdefault('_callable', None) self.__dict__.update(attrs) def __repr__(self): @@ -1567,6 +1567,9 @@ else: return id(self) + def __setattr__(self, attr, value): + raise AttributeError("cannot change the attributes of %r" % (self,)) + class _opaque(_parentable): def __init__(self, TYPE, parent=None, parentindex=None, **attrs): _parentable.__init__(self, TYPE) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Mon Aug 20 16:57:24 2007 @@ -24,6 +24,8 @@ def llexternal(name, args, result, _callable=None, sources=[], includes=[], libraries=[], include_dirs=[], sandboxsafe=False): ext_type = lltype.FuncType(args, result) + if _callable is None: + _callable = ll2ctypes.LL2CtypesCallable(ext_type) funcptr = lltype.functionptr(ext_type, name, external='C', sources=tuple(sources), includes=tuple(includes), @@ -32,8 +34,8 @@ _callable=_callable, _safe_not_sandboxed=sandboxsafe, _debugexc=True) # on top of llinterp - if _callable is None: - ll2ctypes.make_callable_via_ctypes(funcptr) + if isinstance(_callable, ll2ctypes.LL2CtypesCallable): + _callable.funcptr = funcptr return funcptr from pypy.rpython.tool.rfficache import platform Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/typesystem.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/typesystem.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/typesystem.py Mon Aug 20 16:57:24 2007 @@ -57,9 +57,22 @@ FT = typ(llinputs, lloutput) if hasattr(graph, 'func') and callable(graph.func): - return constr(FT, graph.name, graph = graph, _callable = graph.func) + # the Python function object can have _llfnobjattrs_, specifying + # attributes that are forced upon the functionptr(). The idea + # for not passing these extra attributes as arguments to + # getcallable() itself is that multiple calls to getcallable() + # for the same graph should return equal functionptr() objects. + name = graph.name + if hasattr(graph.func, '_llfnobjattrs_'): + fnobjattrs = graph.func._llfnobjattrs_.copy() + # can specify a '_name', but use graph.name by default + name = fnobjattrs.pop('_name', name) + else: + fnobjattrs = {} + return constr(FT, name, graph = graph, _callable = graph.func, + **fnobjattrs) else: - return constr(FT, graph.name, graph = graph) + return constr(FT, name, graph = graph, **fnobjattrs) def getexternalcallable(self, ll_args, ll_result, name, **kwds): typ, constr = self.callable_trait From arigo at codespeak.net Mon Aug 20 17:15:38 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Aug 2007 17:15:38 +0200 (CEST) Subject: [pypy-svn] r45882 - pypy/branch/pypy-more-rtti-inprogress/translator/c/test Message-ID: <20070820151538.71DCE816E@code0.codespeak.net> Author: arigo Date: Mon Aug 20 17:15:37 2007 New Revision: 45882 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: Old thread tests still there... Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Mon Aug 20 17:15:37 2007 @@ -390,6 +390,7 @@ assert eval(res) == 1.5 def test_lock(): + py.test.skip("XXX out-of-date, and should not be here") import thread import pypy.module.thread.rpython.exttable # for declare()/declaretype() def fn(): @@ -409,6 +410,7 @@ assert res is True def test_simple_start_new_thread(): + py.test.skip("XXX out-of-date, and should not be here") import thread import pypy.module.thread.rpython.exttable # for declare()/declaretype() class Arg: @@ -437,6 +439,7 @@ assert res == 42 def test_start_new_thread(): + py.test.skip("XXX out-of-date, and should not be here") import thread import pypy.module.thread.rpython.exttable # for declare()/declaretype() class Arg: @@ -460,6 +463,7 @@ assert res == 42 def test_prebuilt_lock(): + py.test.skip("XXX out-of-date, and should not be here") import thread import pypy.module.thread.rpython.exttable # for declare()/declaretype() lock0 = thread.allocate_lock() From arigo at codespeak.net Mon Aug 20 17:23:12 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Aug 2007 17:23:12 +0200 (CEST) Subject: [pypy-svn] r45883 - in pypy/branch/pypy-more-rtti-inprogress/translator/c: . src Message-ID: <20070820152312.03484816E@code0.codespeak.net> Author: arigo Date: Mon Aug 20 17:23:10 2007 New Revision: 45883 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/funcgen.py pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h Log: A new debugging macro, RPY_LL_ASSERT, which enables checks for pointer low-level operations (pointer-non-null, array index out of bounds...). This differs from RPY_ASSERT in the level at which the checks are made. See comments. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/funcgen.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/funcgen.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/funcgen.py Mon Aug 20 17:23:10 2007 @@ -469,29 +469,26 @@ def OP_GETARRAYITEM(self, op): ARRAY = self.lltypemap(op.args[0]).TO - items = self.expr(op.args[0]) - if not isinstance(ARRAY, FixedSizeArray): - items += '->items' - return self.generic_get(op, '%s[%s]' % (items, - self.expr(op.args[1]))) + ptr = self.expr(op.args[0]) + index = self.expr(op.args[1]) + arraydef = self.db.gettypedefnode(ARRAY) + return self.generic_get(op, arraydef.itemindex_access_expr(ptr, index)) def OP_SETARRAYITEM(self, op): ARRAY = self.lltypemap(op.args[0]).TO - items = self.expr(op.args[0]) - if not isinstance(ARRAY, FixedSizeArray): - items += '->items' - return self.generic_set(op, '%s[%s]' % (items, - self.expr(op.args[1]))) + ptr = self.expr(op.args[0]) + index = self.expr(op.args[1]) + arraydef = self.db.gettypedefnode(ARRAY) + return self.generic_set(op, arraydef.itemindex_access_expr(ptr, index)) OP_BARE_SETARRAYITEM = OP_SETARRAYITEM def OP_GETARRAYSUBSTRUCT(self, op): ARRAY = self.lltypemap(op.args[0]).TO - items = self.expr(op.args[0]) - if not isinstance(ARRAY, FixedSizeArray): - items += '->items' - return '%s = %s + %s;' % (self.expr(op.result), - items, - self.expr(op.args[1])) + ptr = self.expr(op.args[0]) + index = self.expr(op.args[1]) + arraydef = self.db.gettypedefnode(ARRAY) + return '%s = &%s;' % (self.expr(op.result), + arraydef.itemindex_access_expr(ptr, index)) def OP_PTR_NONZERO(self, op): return '%s = (%s != NULL);' % (self.expr(op.result), Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py Mon Aug 20 17:23:10 2007 @@ -888,6 +888,9 @@ debug_mem: \tmake CFLAGS="-g -DRPY_ASSERT -DNO_OBMALLOC" +llsafer: +\tmake CFLAGS="-O2 -DRPY_LL_ASSERT" + profile: \tmake CFLAGS="-g -pg $(CFLAGS)" LDFLAGS="-pg $(LDFLAGS)" Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py Mon Aug 20 17:23:10 2007 @@ -145,7 +145,7 @@ return '(*(%s) %s)' % (cdecl(self.db.gettype(FIRST), '*'), baseexpr) fldname = self.c_struct_field_name(fldname) - return '%s->%s' % (baseexpr, fldname) + return 'RPyField(%s, %s)' % (baseexpr, fldname) def definition(self): if self.fields is None: # external definition only @@ -240,7 +240,14 @@ return '%s.items[%d]' % (baseexpr, index) def ptr_access_expr(self, baseexpr, index): - return '%s->items[%d]' % (baseexpr, index) + assert 0 <= index <= sys.maxint, "invalid constant index %r" % (index,) + return self.itemindex_access_expr(baseexpr, index) + + def itemindex_access_expr(self, baseexpr, indexexpr): + if self.ARRAY._hints.get('nolength', False): + return 'RPyNLenItem(%s, %s)' % (baseexpr, indexexpr) + else: + return 'RPyItem(%s, %s)' % (baseexpr, indexexpr) def definition(self): gcpolicy = self.db.gcpolicy @@ -321,10 +328,17 @@ if not isinstance(index, int): assert index.startswith('item') index = int(index[4:]) + if not (0 <= index < self.FIXEDARRAY.length): + raise IndexError("refusing to generate a statically out-of-bounds" + " array indexing") return '%s[%d]' % (baseexpr, index) ptr_access_expr = access_expr + def itemindex_access_expr(self, baseexpr, indexexpr): + return 'RPyFxItem(%s, %s, %d)' % (baseexpr, indexexpr, + self.FIXEDARRAY.length) + def definition(self): return [] # no declaration is needed Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h Mon Aug 20 17:23:10 2007 @@ -25,6 +25,16 @@ memcpy(itemsarray->items, PyString_AS_STRING(s), \ itemsarray->length) +/* Extra checks can be enabled with the RPY_ASSERT or RPY_LL_ASSERT + * macros. They differ in the level at which the tests are made. + * Remember that RPython lists, for example, are implemented as a + * GcStruct pointing to an over-allocated GcArray. With RPY_ASSERT you + * get list index out of bound checks from rlist.py; such tests must be + * manually written so made we've forgotten a case. Conversely, with + * RPY_LL_ASSERT, all GcArray indexing are checked, which is safer + * against attacks and segfaults - but less precise in the case of + * lists, because of the overallocated bit. + */ #ifdef RPY_ASSERT # define RPyAssert(x, msg) \ if (!(x)) RPyAssertFailed(__FILE__, __LINE__, __FUNCTION__, msg) @@ -45,6 +55,31 @@ # define RPyAssert(x, msg) /* nothing */ #endif +#ifdef RPY_LL_ASSERT +/* obscure macros that can be used as expressions and lvalues to refer + * to a field of a structure or an item in an array in a "safe" way -- + * they abort() in case of null pointer or out-of-bounds index. As a + * speed trade-off, RPyItem actually segfaults if the array is null, but + * it's a "guaranteed" segfault and not one that can be used by + * attackers. + */ +# define RPyCHECK(x) ((x) || (abort(), 0)) +# define RPyField(ptr, name) ((RPyCHECK(ptr), (ptr))->name) +# define RPyItem(array, index) \ + ((RPyCHECK((index) >= 0 && (index) < (array)->length), \ + (array))->items[index]) +# define RPyFxItem(ptr, index, fixedsize) \ + ((RPyCHECK((ptr) && (index) >= 0 && (index) < (fixedsize)), \ + (ptr))[index]) +# define RPyNLenItem(array, index) \ + ((RPyCHECK((array) && (index) >= 0), (array))->items[index]) +#else +# define RPyField(ptr, name) ((ptr)->name) +# define RPyItem(array, index) ((array)->items[index]) +# define RPyFxItem(ptr, index, fixedsize) ((ptr)[index]) +# define RPyNLenItem(array, index) ((array)->items[index]) +#endif + #ifdef _RPyListOfString_New /* :-( */ # define HAVE_RPY_LIST_OF_STRING #endif From fijal at codespeak.net Mon Aug 20 17:27:43 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 20 Aug 2007 17:27:43 +0200 (CEST) Subject: [pypy-svn] r45884 - pypy/branch/pypy-more-rtti-inprogress/translator/c/src Message-ID: <20070820152743.DAB92816E@code0.codespeak.net> Author: fijal Date: Mon Aug 20 17:27:43 2007 New Revision: 45884 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h Log: Kill HAVE_RPY_LIST_OF_STRINGS Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h Mon Aug 20 17:27:43 2007 @@ -80,10 +80,6 @@ # define RPyNLenItem(array, index) ((array)->items[index]) #endif -#ifdef _RPyListOfString_New /* :-( */ -# define HAVE_RPY_LIST_OF_STRING -#endif - #ifndef PYPY_STANDALONE /* prototypes */ From arigo at codespeak.net Mon Aug 20 17:39:01 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Aug 2007 17:39:01 +0200 (CEST) Subject: [pypy-svn] r45885 - pypy/branch/pypy-more-rtti-inprogress/translator/sandbox Message-ID: <20070820153901.6DC888171@code0.codespeak.net> Author: arigo Date: Mon Aug 20 17:39:00 2007 New Revision: 45885 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py Log: Oups. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py Mon Aug 20 17:39:00 2007 @@ -26,13 +26,13 @@ # by the sandboxing mechanism ll_read_not_sandboxed = rffi.llexternal('read', [rffi.INT, rffi.CCHARP, rffi.SIZE_T], - rffi.SIZE_T) -ll_read_not_sandboxed._obj._safe_not_sandboxed = True + rffi.SIZE_T, + sandboxsafe = True) ll_write_not_sandboxed = rffi.llexternal('write', [rffi.INT, rffi.CCHARP, rffi.SIZE_T], - rffi.SIZE_T) -ll_write_not_sandboxed._obj._safe_not_sandboxed = True + rffi.SIZE_T, + sandboxsafe = True) def writeall_not_sandboxed(fd, buf, length): while length > 0: From arigo at codespeak.net Mon Aug 20 17:39:42 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Aug 2007 17:39:42 +0200 (CEST) Subject: [pypy-svn] r45886 - in pypy/branch/pypy-more-rtti-inprogress/translator/c: . src Message-ID: <20070820153942.7C9AC81E1@code0.codespeak.net> Author: arigo Date: Mon Aug 20 17:39:41 2007 New Revision: 45886 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h Log: While we're at it, let's always enable RPY_LL_ASSERT in a sandboxed program. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py Mon Aug 20 17:39:41 2007 @@ -127,6 +127,8 @@ defines = defines.copy() if self.config.translation.countmallocs: defines['COUNT_OP_MALLOCS'] = 1 + if self.config.translation.sandbox: + defines['RPY_SANDBOXED'] = 1 if CBuilder.have___thread is None: CBuilder.have___thread = check_under_under_thread() if not self.standalone: Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h Mon Aug 20 17:39:41 2007 @@ -34,6 +34,10 @@ * RPY_LL_ASSERT, all GcArray indexing are checked, which is safer * against attacks and segfaults - but less precise in the case of * lists, because of the overallocated bit. + * + * For extra safety, in programs translated with --sandbox we always + * assume that we want RPY_LL_ASSERT. You can change it below to trade + * safety for performance, though the hit is not huge (~10%?). */ #ifdef RPY_ASSERT # define RPyAssert(x, msg) \ @@ -55,7 +59,7 @@ # define RPyAssert(x, msg) /* nothing */ #endif -#ifdef RPY_LL_ASSERT +#if defined(RPY_LL_ASSERT) || defined(RPY_SANDBOXED) /* obscure macros that can be used as expressions and lvalues to refer * to a field of a structure or an item in an array in a "safe" way -- * they abort() in case of null pointer or out-of-bounds index. As a From arigo at codespeak.net Mon Aug 20 21:24:52 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Aug 2007 21:24:52 +0200 (CEST) Subject: [pypy-svn] r45888 - pypy/branch/pypy-more-rtti-inprogress/rpython Message-ID: <20070820192452.59387813E@code0.codespeak.net> Author: arigo Date: Mon Aug 20 21:24:50 2007 New Revision: 45888 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/typesystem.py Log: Oups. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/typesystem.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/typesystem.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/typesystem.py Mon Aug 20 21:24:50 2007 @@ -56,13 +56,13 @@ typ, constr = self.callable_trait FT = typ(llinputs, lloutput) + name = graph.name if hasattr(graph, 'func') and callable(graph.func): # the Python function object can have _llfnobjattrs_, specifying # attributes that are forced upon the functionptr(). The idea # for not passing these extra attributes as arguments to # getcallable() itself is that multiple calls to getcallable() # for the same graph should return equal functionptr() objects. - name = graph.name if hasattr(graph.func, '_llfnobjattrs_'): fnobjattrs = graph.func._llfnobjattrs_.copy() # can specify a '_name', but use graph.name by default @@ -72,7 +72,7 @@ return constr(FT, name, graph = graph, _callable = graph.func, **fnobjattrs) else: - return constr(FT, name, graph = graph, **fnobjattrs) + return constr(FT, name, graph = graph) def getexternalcallable(self, ll_args, ll_result, name, **kwds): typ, constr = self.callable_trait From fijal at codespeak.net Mon Aug 20 21:34:15 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 20 Aug 2007 21:34:15 +0200 (CEST) Subject: [pypy-svn] r45889 - pypy/branch/pypy-more-rtti-inprogress/translator/c/src Message-ID: <20070820193415.BD1B58155@code0.codespeak.net> Author: fijal Date: Mon Aug 20 21:34:15 2007 New Revision: 45889 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread.h Log: avoid including this file twice (fix from dist) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread.h Mon Aug 20 21:34:15 2007 @@ -1,6 +1,9 @@ /* #ifdef logic from CPython */ +#ifndef __PYPY_THREAD_H +#define __PYPY_THREAD_H + #ifndef _POSIX_THREADS /* This means pthreads are not implemented in libc headers, hence the macro not present in unistd.h. But they still can be implemented as an external @@ -35,3 +38,5 @@ #define RPyThreadStaticTLS_Set(key, value) RPyThreadTLS_Set(key, value) #endif + +#endif From fijal at codespeak.net Mon Aug 20 21:34:58 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 20 Aug 2007 21:34:58 +0200 (CEST) Subject: [pypy-svn] r45890 - in pypy/branch/pypy-more-rtti-inprogress/module/thread: . test Message-ID: <20070820193458.76D4F8155@code0.codespeak.net> Author: fijal Date: Mon Aug 20 21:34:58 2007 New Revision: 45890 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py Log: Move ll_thread from dist here. This includes mostly API-refactoring for being more cpython thread-like on RPython level. Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py Mon Aug 20 21:34:58 2007 @@ -3,49 +3,39 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.rffi import platform from pypy.rpython.extfunc import genericcallable -from pypy.module.thread.os_thread import Bootstrapper +from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.translator.tool.cbuild import cache_c_module -from pypy.rpython.annlowlevel import cast_instance_to_base_ptr,\ - cast_base_ptr_to_instance +from pypy.rpython.lltypesystem import llmemory import thread, py from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem.lltype import typeOf +from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.nonconst import NonConstant -class BaseBootstrapper: - def bootstrap(self): - pass - -class ThreadError(Exception): +class error(Exception): def __init__(self, msg): self.msg = msg -class Lock(object): - """ Container for low-level implementation - of a lock object - """ - def __init__(self, ll_lock): - self._lock = ll_lock - +from pypy.tool.autopath import pypydir +pypydir = py.path.local(pypydir) +srcdir = pypydir.join('translator', 'c', 'src') includes = ['unistd.h', 'thread.h'] def setup_thread_so(): - from pypy.tool.autopath import pypydir - pypydir = py.path.local(pypydir) - srcdir = pypydir.join('translator', 'c', 'src') - modname = '_thread' files = [srcdir.join('thread.c')] + modname = '_thread' cache_c_module(files, modname, include_dirs=[str(srcdir)]) return str(pypydir.join('_cache', modname)) + '.so' libraries = [setup_thread_so()] def llexternal(name, args, result): return rffi.llexternal(name, args, result, includes=includes, - libraries=libraries) + libraries=libraries, include_dirs=[str(srcdir)]) -CALLBACK = lltype.FuncType([rffi.VOIDP], rffi.VOIDP) +CALLBACK = lltype.Ptr(lltype.FuncType([rffi.VOIDP], rffi.VOIDP)) c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT) -c_thread_get_ident = llexternal('RPyThreadGetIdent', [], lltype.Void) +c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT) TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock', includes=includes) @@ -54,63 +44,86 @@ rffi.INT) c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void) -def ll_allocate_lock(): +def allocate_lock(): ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') res = c_thread_lock_init(ll_lock) if res == -1: - raise ThreadError("out of resources") + raise error("out of resources") return Lock(ll_lock) -def ll_acquire_lock(lock, waitflag): - return c_thread_acuirelock(lock._lock, waitflag) - -def ll_release_lock(lock): - try: - if ll_acquire_lock(lock, 0): - raise ThreadError("bad lock") - finally: - c_thread_releaselock(lock._lock) +def _start_new_thread(x, y): + return thread.start_new_thread(x, (y,)) def ll_start_new_thread(l_func, arg): l_arg = cast_instance_to_base_ptr(arg) + l_arg = rffi.cast(rffi.VOIDP, l_arg) ident = c_thread_start(l_func, l_arg) if ident == -1: - raise ThreadError("can't start new thread") + raise error("can't start new thread") return ident class LLStartNewThread(ExtRegistryEntry): - _about_ = ll_start_new_thread - + _about_ = _start_new_thread + def compute_result_annotation(self, s_func, s_arg): bookkeeper = self.bookkeeper - assert s_func.is_constant(), "Cannot call ll_start_new_thread with non-constant function" s_result = bookkeeper.emulate_pbc_call(bookkeeper.position_key, s_func, [s_arg]) - assert annmodel.s_None.contains(s_result), ( - """thread.start_new_thread(f, arg): f() should return None""") + assert annmodel.s_None.contains(s_result) return annmodel.SomeInteger() - - def compute_annotation_bk(self, bookkeeper): - return annmodel.SomePBC([bookkeeper.getdesc(self.instance)]) - + def specialize_call(self, hop): rtyper = hop.rtyper - bookkeeper = rtyper.annotator.bookkeeper - _callable = hop.args_s[0].const + bk = rtyper.annotator.bookkeeper + r_result = rtyper.getrepr(hop.s_result) + hop.exception_is_here() args_r = [rtyper.getrepr(s_arg) for s_arg in hop.args_s] - ll_arg = args_r[1].lowleveltype - _type = lltype.FuncType([ll_arg], lltype.Void) - funcptr = lltype.functionptr(_type, _callable.func_name, + _callable = hop.args_s[0].const + funcptr = lltype.functionptr(CALLBACK.TO, _callable.func_name, _callable=_callable) - r_result = rtyper.getrepr(hop.s_result) - ll_result = r_result.lowleveltype - args_s = [bookkeeper.immutablevalue(i) for i in [funcptr, ll_arg]] + func_s = bk.immutablevalue(funcptr) + s_args = [func_s, hop.args_s[1]] obj = rtyper.getannmixlevel().delayedfunction( - ll_start_new_thread, args_s, annmodel.SomeInteger()) - vlist = [hop.inputconst(typeOf(obj), obj)] + hop.inputargs(*args_r) - hop.exception_is_here() + ll_start_new_thread, s_args, annmodel.SomeInteger()) + bootstrap = rtyper.getannmixlevel().delayedfunction( + _callable, [hop.args_s[1]], annmodel.s_None) + vlist = [hop.inputconst(typeOf(obj), obj), + hop.inputconst(typeOf(bootstrap), bootstrap), + #hop.inputarg(args_r[0], 0), + hop.inputarg(args_r[1], 1)] return hop.genop('direct_call', vlist, r_result) -# a simple wrapper, not to expose C functions (is this really necessary?) -def ll_get_ident(): +# wrappers... + +def get_ident(): return c_thread_get_ident() + +def start_new_thread(x, y): + return _start_new_thread(x, y[0]) + +class Lock(object): + """ Container for low-level implementation + of a lock object + """ + def __init__(self, ll_lock): + self._lock = ll_lock + + def acquire(self, flag): + return bool(c_thread_acuirelock(self._lock, int(flag))) + + def release(self): + try: + if self.acquire(False): + # XXX the annotator trick to annotate it with non-const + # string, probably should be put into bltn-analyzers + raise error(NonConstant("bad lock")) + finally: + c_thread_releaselock(self._lock) + + def fused_release_acquire(self): + self.release() + self.acquire(True) + + def __del__(self): + lltype.free(self._lock, flavor='raw') + Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py Mon Aug 20 21:34:58 2007 @@ -1,40 +1,60 @@ from pypy.module.thread.ll_thread import * from pypy.translator.c.test.test_genc import compile +from pypy.rpython.lltypesystem import lltype import py def test_lock(): - l = ll_allocate_lock() - ok1 = ll_acquire_lock(l, 1) - ok2 = ll_acquire_lock(l, 0) - ll_release_lock(l) - ok3 = ll_acquire_lock(l, 0) + l = allocate_lock() + ok1 = l.acquire(True) + ok2 = l.acquire(False) + l.release() + ok3 = l.acquire(False) res = ok1 and not ok2 and ok3 assert res == 1 def test_thread_error(): - l = ll_allocate_lock() - py.test.raises(ThreadError, ll_release_lock, l) + l = allocate_lock() + try: + l.release() + except error: + pass + else: + py.test.fail("Did not raise") -def test_thread_init_new(): - """ This test works only after translation - """ - py.test.skip("does not work") +def test_start_new_thread(): import time - import thread - - class X(BaseBootstrapper): + class Y: + _alloc_flavor_ = 'raw' + def __init__(self): self.top = [] def bootstrap(self): - self.top.append(1) - + self.top.append(get_ident()) + def f(): - x = X() - ll_start_new_thread(X.bootstrap, x) + y = Y() + start_new_thread(Y.bootstrap, (y,)) time.sleep(.3) - return len(x.top) + res = len(y.top) + lltype.free(y, flavor='raw') + return 1 == get_ident() + + # for some reason, refcounting does not handle _alloc_flavor_ = 'raw' + # XXX is this testable on top of llinterp at all? + fn = compile(f, [], gcpolicy='boehm') + assert fn() == False + +def test_prebuilt_lock(): + py.test.skip("Does not work (prebuilt opaque object)") + l = allocate_lock() - fn = compile(f, []) - assert fn() == 1 + def f(): + l.acquire(True) + l.release() + + fn = compile(f, [], gcpolicy='boehm') + fn() + + From fijal at codespeak.net Mon Aug 20 21:43:50 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 20 Aug 2007 21:43:50 +0200 (CEST) Subject: [pypy-svn] r45891 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070820194350.61FA281EE@code0.codespeak.net> Author: fijal Date: Mon Aug 20 21:43:48 2007 New Revision: 45891 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: This part was commited/reverted together with other stuff, needs to stay. Helpers for rffi_platform. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Mon Aug 20 21:43:48 2007 @@ -101,12 +101,6 @@ def CStructPtr(*args, **kwds): return lltype.Ptr(CStruct(*args, **kwds)) -#def CArray(field): -# return lltype.Array(field, hints={'nolength':True}) - -#def CArrayPtr(field): -# return lltype.Ptr(CArray(fld)) - def COpaque(name, hints=None, **kwds): if hints is None: hints = {} @@ -211,20 +205,21 @@ cast = ll2ctypes.force_cast # a forced, no-checking cast + def size_and_sign(tp): - if tp is lltype.Char: - return 1, False - if tp is lltype.Float: - return 8, False - assert isinstance(tp, lltype.Number) - if tp is lltype.Signed: - unsigned = False - else: + size = sizeof(tp) + try: unsigned = not tp._type.SIGNED - return sizeof(tp), unsigned + except AttributeError: + if tp in [lltype.Char, lltype.Float, lltype.Signed]: + unsigned = False + else: + unsigned = True + return size, unsigned def sizeof(tp): - # works only for int types! + if isinstance(tp, lltype.FixedSizeArray): + return sizeof(tp.OF) * tp.length if tp is lltype.Char: return 1 if tp is lltype.Float: From arigo at codespeak.net Tue Aug 21 16:17:35 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 21 Aug 2007 16:17:35 +0200 (CEST) Subject: [pypy-svn] r45895 - pypy/branch/pypy-more-rtti-inprogress/translator/c/src Message-ID: <20070821141735.7F4008159@code0.codespeak.net> Author: arigo Date: Tue Aug 21 16:17:34 2007 New Revision: 45895 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread_pthread.h Log: A missing #include. I don't know why it didn't hurt before. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread_pthread.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread_pthread.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread_pthread.h Tue Aug 21 16:17:34 2007 @@ -2,6 +2,7 @@ /* Posix threads interface (from CPython) */ #include +#include #include /* The POSIX spec says that implementations supporting the sem_* From arigo at codespeak.net Tue Aug 21 16:19:53 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 21 Aug 2007 16:19:53 +0200 (CEST) Subject: [pypy-svn] r45896 - pypy/branch/pypy-more-rtti-inprogress/module/thread Message-ID: <20070821141953.29F638159@code0.codespeak.net> Author: arigo Date: Tue Aug 21 16:19:52 2007 New Revision: 45896 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/__init__.py pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Log: Only set up the GIL the first time the app-level start_new_thread() is called. This should be enough to remove the need for a prebuilt lock object during translation. Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/__init__.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/__init__.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/__init__.py Tue Aug 21 16:19:52 2007 @@ -19,20 +19,3 @@ '_local': 'os_local.getlocaltype(space)', '_please_provide_import_lock': '(space.w_True)', # for imp.py } - - def __init__(self, space, *args): - "NOT_RPYTHON: patches space.threadlocals to use real threadlocals" - from pypy.module.thread import gil - MixedModule.__init__(self, space, *args) - prev = space.threadlocals.getvalue() - space.threadlocals = gil.GILThreadLocals() - space.threadlocals.setvalue(prev) - space.threadlocals.enter_thread(space) # setup the main thread - # add the GIL-releasing callback as an action on the space - space.pending_actions.append(gil.GILReleaseAction(space.threadlocals)) - - def setup_after_space_initialization(self): - # the import lock is in imp.py. Import it after the space is fully - # initialized. - from pypy.module.__builtin__.importing import importhook - importhook(self.space, 'imp') Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Tue Aug 21 16:19:52 2007 @@ -49,6 +49,22 @@ e.clear(space) +def setup_threads(space): + """Enable threads in the object space, if they haven't already been.""" + from pypy.module.thread.gil import GILThreadLocals, GILReleaseAction + from pypy.module.__builtin__.importing import importhook + if not isinstance(space.threadlocals, GILThreadLocals): + # patches space.threadlocals to use real threadlocals + prev = space.threadlocals.getvalue() + space.threadlocals = GILThreadLocals() + space.threadlocals.setvalue(prev) + space.threadlocals.enter_thread(space) # setup the main thread + # add the GIL-releasing callback as an action on the space + space.pending_actions.append(GILReleaseAction(space.threadlocals)) + # the import lock is in imp.py, which registers a custom import + # hook with this lock. + importhook(space, 'imp') + def start_new_thread(space, w_callable, w_args, w_kwargs=NoneNotWrapped): """Start a new thread and return its identifier. The thread will call the function with positional arguments from the tuple args and keyword arguments @@ -56,6 +72,7 @@ function returns; the return value is ignored. The thread will also exit when the function raises an unhandled exception; a stack trace will be printed unless the exception is SystemExit.""" + setup_threads(space) if not space.is_true(space.isinstance(w_args, space.w_tuple)): raise OperationError(space.w_TypeError, space.wrap("2nd arg must be a tuple")) From arigo at codespeak.net Tue Aug 21 16:57:52 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 21 Aug 2007 16:57:52 +0200 (CEST) Subject: [pypy-svn] r45899 - pypy/branch/pypy-more-rtti-inprogress/module/thread Message-ID: <20070821145752.092D281F6@code0.codespeak.net> Author: arigo Date: Tue Aug 21 16:57:52 2007 New Revision: 45899 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/__init__.py pypy/branch/pypy-more-rtti-inprogress/module/thread/gil.py pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Log: More subtle: we can't change space.threadlocals at run-time because the space is frozen. But we can put a GILThreadLocals with an initial GIL=None. Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/__init__.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/__init__.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/__init__.py Tue Aug 21 16:57:52 2007 @@ -19,3 +19,11 @@ '_local': 'os_local.getlocaltype(space)', '_please_provide_import_lock': '(space.w_True)', # for imp.py } + + def __init__(self, space, *args): + "NOT_RPYTHON: patches space.threadlocals to use real threadlocals" + from pypy.module.thread import gil + MixedModule.__init__(self, space, *args) + prev = space.threadlocals.getvalue() + space.threadlocals = gil.GILThreadLocals() + space.threadlocals.setvalue(prev) Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/gil.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/gil.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/gil.py Tue Aug 21 16:57:52 2007 @@ -13,10 +13,18 @@ class GILThreadLocals(OSThreadLocals): """A version of OSThreadLocals that enforces a GIL.""" + GIL = None - def __init__(self): - OSThreadLocals.__init__(self) - self.GIL = thread.allocate_lock() + def setup_threads(self, space): + """Enable threads in the object space, if they haven't already been.""" + if self.GIL is None: + self.GIL = thread.allocate_lock() + self.enter_thread(space) # setup the main thread + # add the GIL-releasing callback as an action on the space + space.pending_actions.append(GILReleaseAction(self)) + return True + else: + return False # already set up def enter_thread(self, space): "Notification that the current thread is just starting: grab the GIL." Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Tue Aug 21 16:57:52 2007 @@ -50,21 +50,13 @@ def setup_threads(space): - """Enable threads in the object space, if they haven't already been.""" - from pypy.module.thread.gil import GILThreadLocals, GILReleaseAction - from pypy.module.__builtin__.importing import importhook - if not isinstance(space.threadlocals, GILThreadLocals): - # patches space.threadlocals to use real threadlocals - prev = space.threadlocals.getvalue() - space.threadlocals = GILThreadLocals() - space.threadlocals.setvalue(prev) - space.threadlocals.enter_thread(space) # setup the main thread - # add the GIL-releasing callback as an action on the space - space.pending_actions.append(GILReleaseAction(space.threadlocals)) + if space.threadlocals.setup_threads(space): # the import lock is in imp.py, which registers a custom import # hook with this lock. + from pypy.module.__builtin__.importing import importhook importhook(space, 'imp') + def start_new_thread(space, w_callable, w_args, w_kwargs=NoneNotWrapped): """Start a new thread and return its identifier. The thread will call the function with positional arguments from the tuple args and keyword arguments From fijal at codespeak.net Wed Aug 22 12:06:04 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 22 Aug 2007 12:06:04 +0200 (CEST) Subject: [pypy-svn] r45903 - in pypy/branch/pypy-more-rtti-inprogress: rpython/lltypesystem/test translator/c Message-ID: <20070822100604.C43908117@code0.codespeak.net> Author: fijal Date: Wed Aug 22 12:06:03 2007 New Revision: 45903 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py Log: * Move sources=[] attribute from having files into having direct source * Include all the includes of current node into the same source Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Wed Aug 22 12:06:03 2007 @@ -8,15 +8,13 @@ from pypy.rpython.test.test_llinterp import interpret def test_basic(): - c_source = """ + c_source = py.code.Source(""" int z(int x) { return (x + 3); } - """ - c_file = udir.join("stuff.c") - c_file.write(c_source) - z = llexternal('z', [Signed], Signed, sources=[str(c_file)]) + """) + z = llexternal('z', [Signed], Signed, sources=[c_source]) def f(): return z(8) @@ -64,9 +62,7 @@ return ret; } """) - c_file = udir.join("stringrev.c") - c_file.write(c_source) - z = llexternal('f', [CCHARP], CCHARP, sources=[str(c_file)]) + z = llexternal('f', [CCHARP], CCHARP, sources=[c_source]) def f(): s = str2charp("xxx") @@ -93,9 +89,7 @@ return (l); } """ - c_file = udir.join("stringstar.c") - c_file.write(c_source) - z = llexternal('f', [CCHARPP], Signed, sources=[str(c_file)]) + z = llexternal('f', [CCHARPP], Signed, sources=[c_source]) def f(): l = ["xxx", "x", "xxxx"] @@ -119,7 +113,6 @@ h_file.write(h_source) c_source = """ - #include "structxx.h" int f(struct xx* z) { return (z->one + z->three); @@ -127,10 +120,8 @@ """ TP = CStructPtr('xx', ('one', Signed), ('two', Char), ('three', Signed)) - c_file = udir.join("structxx.c") - c_file.write(c_source) - z = llexternal('f', [TP], Signed, sources=[str(c_file)], - includes=[str(h_file)]) + z = llexternal('f', [TP], Signed, sources=[c_source], + includes=[str(h_file)], include_dirs=[udir]) def f(): struct = lltype.malloc(TP.TO, flavor='raw') @@ -178,16 +169,14 @@ def test_extra_include_dirs(): udir.ensure("incl", dir=True) udir.join("incl", "incl.h").write("#define C 3") - c_file = udir.join("test_extra_include_dirs.c") - c_source = """ + c_source = py.code.Source(""" #include int fun () { return (C); } - """ - c_file.write(c_source) - z = llexternal('fun', [], Signed, sources=[str(c_file)], include_dirs= + """) + z = llexternal('fun', [], Signed, sources=[c_source], include_dirs= [str(udir.join("incl"))]) def f(): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py Wed Aug 22 12:06:03 2007 @@ -373,6 +373,15 @@ # graph.optimize() # self.funcnodes = graph.ordered_funcnodes() + def write_extra_sources(self, sources): + basename = 'additional_node.c' + retval = [] + for source in sorted(sources.keys()): + f = self.makefile(self.uniquecname(basename)) + for include in sources[source]: + print >>f, "#include <%s>" % (include,) + print >>f, str(source) + def uniquecname(self, name): assert name.endswith('.c') return self.namespace.uniquename(name[:-2]) + '.c' @@ -620,14 +629,12 @@ includes[include] = True if hasattr(node, 'sources'): for source in node.sources: - sources[source] = True + sources[source] = getattr(node, 'includes', []) if hasattr(node, 'include_dirs'): for include_dir in node.include_dirs: include_dirs[include_dir] = True includes = includes.keys() includes.sort() - sources = sources.keys() - sources.sort() return includes, sources, include_dirs def gen_source_standalone(database, modulename, targetdir, @@ -674,6 +681,7 @@ sg = SourceGenerator(database, preimplementationlines) sg.set_strategy(targetdir) sg.gen_readable_parts_of_source(f) + sg.write_extra_sources(sources) # 3) start-up code print >> f @@ -687,7 +695,7 @@ print >>fi, "#define INSTRUMENT_NCOUNTER %d" % n fi.close() - return filename, sg.getextrafiles() + sources, include_dirs + return filename, sg.getextrafiles(), include_dirs def gen_source(database, modulename, targetdir, defines={}, exports={}, @@ -735,6 +743,7 @@ sg = SourceGenerator(database, preimplementationlines) sg.set_strategy(targetdir) sg.gen_readable_parts_of_source(f) + sg.write_extra_sources(sources) # # Debugging info @@ -848,7 +857,7 @@ f.write(SETUP_PY % locals()) f.close() - return filename, sg.getextrafiles() + sources, include_dirs + return filename, sg.getextrafiles(), include_dirs SETUP_PY = ''' From fijal at codespeak.net Wed Aug 22 13:40:30 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 22 Aug 2007 13:40:30 +0200 (CEST) Subject: [pypy-svn] r45905 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070822114030.8F841813E@code0.codespeak.net> Author: fijal Date: Wed Aug 22 13:40:28 2007 New Revision: 45905 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py Log: Fix error reporting Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py Wed Aug 22 13:40:28 2007 @@ -425,7 +425,7 @@ # ____________________________________________ def get_ctypes_callable(funcptr): - if getattr(funcptr._obj, 'source', None) is not None: + if getattr(funcptr._obj, 'sources', None): # give up - for tests with an inlined bit of C code raise NotImplementedError("cannot call a C function defined in " "a custom C source snippet") From fijal at codespeak.net Wed Aug 22 14:31:03 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 22 Aug 2007 14:31:03 +0200 (CEST) Subject: [pypy-svn] r45906 - in pypy/branch/pypy-more-rtti-inprogress: rpython/lltypesystem rpython/lltypesystem/test translator/c Message-ID: <20070822123103.C8156813B@code0.codespeak.net> Author: fijal Date: Wed Aug 22 14:31:01 2007 New Revision: 45906 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py Log: whack, whack, whack until it works. * move all additional-c-snippets into one .h file, so it could be included * slight simplification here and there probably this needs to be simplified at some point :-( Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Wed Aug 22 14:31:01 2007 @@ -6,23 +6,11 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic from pypy.rlib import rarithmetic -import os - -class CConstant(Symbolic): - """ A C-level constant, maybe #define, rendered directly. - """ - def __init__(self, c_name, TP): - self.c_name = c_name - self.TP = TP - - def annotation(self): - return lltype_to_annotation(self.TP) - - def lltype(self): - return self.TP +import os, py def llexternal(name, args, result, _callable=None, sources=[], includes=[], - libraries=[], include_dirs=[], sandboxsafe=False): + libraries=[], include_dirs=[], extra_exports=[], + sandboxsafe=False): ext_type = lltype.FuncType(args, result) if _callable is None: _callable = ll2ctypes.LL2CtypesCallable(ext_type) @@ -119,25 +107,34 @@ def COpaquePtr(*args, **kwds): return lltype.Ptr(COpaque(*args, **kwds)) -def CExternVariable(TYPE, name): +def CExternVariable(TYPE, name, **kwds): """Return a pair of functions - a getter and a setter - to access the given global C variable. """ - # XXX THIS IS ONLY A QUICK HACK TO MAKE IT WORK - # In general, we need to re-think a few things to be more consistent, - # e.g. what if a CStruct, COpaque or CExternVariable requires - # some #include... assert not isinstance(TYPE, lltype.ContainerType) - CTYPE = lltype.FixedSizeArray(TYPE, 1) - c_variable_ref = CConstant('(&%s)' % (name,), lltype.Ptr(CTYPE)) - def getter(): - return c_variable_ref[0] - def setter(newvalue): - c_variable_ref[0] = newvalue - return (func_with_new_name(getter, '%s_getter' % (name,)), - func_with_new_name(setter, '%s_setter' % (name,))) - -get_errno, set_errno = CExternVariable(lltype.Signed, 'errno') + try: + tp = lltype_to_c_mapping[TYPE] + except KeyError: + raise NotImplementedError("Don't know how to handle %s" % TYPE) + src = py.code.Source(""" + #include + %(tp)s _rffi_get_%(name)s() + { + return %(name)s; + } + void _rffi_set_%(name)s(%(tp)s arg) + { + %(name)s = arg; + } + """ % {'name':name, 'tp':tp}) + kwds = kwds.copy() + if 'sources' in kwds: + kwds['sources'].append(src) + else: + kwds['sources'] = [src] + getter = llexternal('_rffi_get_' + name, [], TYPE, **kwds) + setter = llexternal('_rffi_set_' + name, [TYPE], lltype.Void, **kwds) + return getter, setter # char, represented as a Python character # (use SIGNEDCHAR or UCHAR for the small integer types) @@ -158,6 +155,19 @@ # double * DOUBLEP = lltype.Ptr(lltype.Array(DOUBLE, hints={'nolength': True})) +# char** +CCHARPP = lltype.Ptr(lltype.Array(CCHARP, hints={'nolength': True})) + +# HAAAAAAAAAAAAAACK +lltype_to_c_mapping = { + lltype.Signed: 'int', + CCHARP: 'char*', + lltype.Char: 'char', + CCHARPP: 'char**', + } + +get_errno, set_errno = CExternVariable(lltype.Signed, 'errno') + # various type mapping # str -> char* def str2charp(s): @@ -182,9 +192,6 @@ i += 1 return "".join(l) -# char** -CCHARPP = lltype.Ptr(lltype.Array(CCHARP, hints={'nolength': True})) - def liststr2charpp(l): """ list[str] -> char**, NULL terminated """ @@ -228,3 +235,4 @@ if tp is lltype.Signed: return ULONG._type.BITS/8 return tp._type.BITS/8 + Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Wed Aug 22 14:31:01 2007 @@ -103,11 +103,14 @@ def test_struct(): h_source = """ + #ifndef _STRUCT_XX + #define _STRUCT_XX struct xx { int one; char two; int three; }; + #endif """ h_file = udir.join("structxx.h") h_file.write(h_source) @@ -260,3 +263,38 @@ assert not size_and_sign(lltype.Signed)[1] assert not size_and_sign(lltype.Char)[1] assert size_and_sign(UINT)[1] + +def test_prebuild_constant(): + h_source = py.code.Source(""" + #ifndef _CONSTANTS + #define _CONSTANTS + int x = 3; + char** z = NULL; + #endif + """) + h_include = udir.join('constants.h') + h_include.write(h_source) + + kwds = {'includes':['constants.h'], 'include_dirs':[str(udir)]} + get_x, set_x = CExternVariable(lltype.Signed, 'x', **kwds) + get_z, set_z = CExternVariable(CCHARPP, 'z', **kwds) + + def f(): + one = get_x() + set_x(13) + return one + get_x() + + def g(): + l = liststr2charpp(["a", "b", "c"]) + try: + set_z(l) + return charp2str(get_z()[2]) + finally: + free_charpp(l) + + fn = compile(f, []) + assert fn() == 16 + gn = compile(g, []) + assert gn() == "c" + + Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py Wed Aug 22 14:31:01 2007 @@ -4,7 +4,6 @@ ContainerType, OpaqueType, FixedSizeArray, _uninitialized from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.llmemory import Address -from pypy.rpython.lltypesystem.rffi import CConstant from pypy.tool.sourcetools import valid_identifier from pypy.translator.c.primitive import PrimitiveName, PrimitiveType from pypy.translator.c.primitive import PrimitiveErrorValue @@ -169,8 +168,6 @@ else: raise Exception("don't know about %r" % (T,)) else: - if isinstance(obj, CConstant): - return obj.c_name # without further checks T = typeOf(obj) if isinstance(T, Primitive): return PrimitiveName[T](obj, self) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py Wed Aug 22 14:31:01 2007 @@ -374,13 +374,22 @@ # self.funcnodes = graph.ordered_funcnodes() def write_extra_sources(self, sources): - basename = 'additional_node.c' - retval = [] + name = 'additional_source.h' + + includes = {} for source in sorted(sources.keys()): - f = self.makefile(self.uniquecname(basename)) for include in sources[source]: - print >>f, "#include <%s>" % (include,) - print >>f, str(source) + includes[include] = True + + f = self.path.join(name).open("w") + print >>f, "#ifndef _ADDITIONAL_SOURCE" + print >>f, "#define _ADDITIONAL_SOURCE" + for include in includes.keys(): + print >>f, "#include <%s>" % (include,) + if sources: + print >>f, str(py.code.Source(*sources)) + print >>f, "#endif" + f.close() def uniquecname(self, name): assert name.endswith('.c') @@ -624,17 +633,14 @@ sources = {} include_dirs = {} for node in database.globalcontainers(): - if hasattr(node, 'includes'): - for include in node.includes: - includes[include] = True - if hasattr(node, 'sources'): - for source in node.sources: - sources[source] = getattr(node, 'includes', []) - if hasattr(node, 'include_dirs'): - for include_dir in node.include_dirs: - include_dirs[include_dir] = True - includes = includes.keys() - includes.sort() + for include in getattr(node, 'includes', []): + includes[include] = True + for source in getattr(node, 'sources', []): + sources[source] = getattr(node, 'includes', []) + for include_dir in getattr(node, 'include_dirs', []): + include_dirs[include_dir] = True + includes = sorted(includes.keys()) + includes.append("additional_source.h") return includes, sources, include_dirs def gen_source_standalone(database, modulename, targetdir, @@ -668,7 +674,7 @@ includes, sources, include_dirs = extra_information(database) for include in includes: - print >> fi, '#include <%s>' % (include,) + print >> fi, '#include "%s"' % (include,) fi.close() preimplementationlines = list( @@ -727,7 +733,7 @@ includes, sources, include_dirs = extra_information(database) for include in includes: - print >> fi, '#include <%s>' % (include,) + print >> fi, '#include "%s"' % (include,) fi.close() if database.translator is None or database.translator.rtyper is None: From fijal at codespeak.net Wed Aug 22 15:27:44 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 22 Aug 2007 15:27:44 +0200 (CEST) Subject: [pypy-svn] r45910 - in pypy/branch/pypy-more-rtti-inprogress: rpython/lltypesystem rpython/lltypesystem/test translator/c Message-ID: <20070822132744.ECBF68139@code0.codespeak.net> Author: fijal Date: Wed Aug 22 15:27:43 2007 New Revision: 45910 Added: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py - copied unchanged from r45905, pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py - copied unchanged from r45905, pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py - copied unchanged from r45905, pypy/branch/pypy-more-rtti-inprogress/translator/c/database.py pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py - copied unchanged from r45905, pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py Log: Revert last commit. From lucio at codespeak.net Wed Aug 22 16:41:14 2007 From: lucio at codespeak.net (lucio at codespeak.net) Date: Wed, 22 Aug 2007 16:41:14 +0200 (CEST) Subject: [pypy-svn] r45911 - pypy/branch/flex-backend/pypy/translator/flex/jssrc Message-ID: <20070822144114.E0C648174@code0.codespeak.net> Author: lucio Date: Wed Aug 22 16:41:14 2007 New Revision: 45911 Added: pypy/branch/flex-backend/pypy/translator/flex/jssrc/library.as Log: missing file Added: pypy/branch/flex-backend/pypy/translator/flex/jssrc/library.as ============================================================================== --- (empty file) +++ pypy/branch/flex-backend/pypy/translator/flex/jssrc/library.as Wed Aug 22 16:41:14 2007 @@ -0,0 +1,197 @@ +_consts_0.convertToString = function (stuff) { + if (stuff === undefined) { + return ("undefined"); + } + return (stuff.toString()); + } +_consts_0.flexTrace = function ( text:String ):void { + var myUrl:URLRequest = new URLRequest("javascript:console.log('" + text + "');void(0);"); + sendToURL(myUrl); +} + +// wrapper for throw, because flex compiler weirdness. +_consts_0.throwit = function (e) { + throw(e); +} + +_consts_0.inherits = function (child, parent) { + child.parent = parent; + for (var i in parent.prototype) { + if (!child.prototype[i]) { + child.prototype[i] = parent.prototype[i]; + } + } +} + +_consts_0.isinstanceof = function (self, what) { + + //return self instanceof what; + + + if (!self) { + return (false); + } + var t = self.constructor; + while ( t ) { + if (t == what) { + return (true); + } + t = t.parent; + } + return (false); +} + +/*function delitem(fn, l, i) { + for(var j = i; j < l.length-1; ++j) { + l[j] = l[j+1]; + } + l.length--; +}*/ + +_consts_0.strcmp = function (s1, s2) { + if ( s1 < s2 ) { + return ( -1 ); + } else if ( s1 == s2 ) { + return ( 0 ); + } + return (1); +} + +_consts_0.startswith = function (s1, s2) { + if (s1.length < s2.length) { + return(false); + } + for (var i = 0; i < s2.length; ++i){ + if (s1.charAt(i) != s2.charAt(i)) { + return(false); + } + } + return(true); +} + +_consts_0.endswith = function (s1, s2) { + if (s2.length > s1.length) { + return(false); + } + for (var i = s1.length-s2.length; i < s1.length; ++i) { + if (s1.charAt(i) != s2.charAt(i - s1.length + s2.length)) { + return(false); + } + } + return(true); +} + +_consts_0.splitchr = function (s, ch) { + var i, lst, next; + lst = []; + next = ""; + for (var i = 0; i end || start > s1.length) { + return -1; + } + s1 = s1.substr(start, end-start); + var res = s1.indexOf(s2); + if (res == -1) { + return -1; + } + return res + start; +} + +_consts_0.findIndexOfTrue = function (s1, s2) { + return _consts_0.findIndexOf(s1, s2, 0, s1.length) != -1; +} + +_consts_0.countCharOf = function (s, c, start, end) { + s = s.substring(start, end); + var i = 0; + for (var c1 in s) { + if (s[c1] == c) { + i++; + } + } + return(i); +} + +_consts_0.countOf = function (s, s1, start, end) { + var ret = _consts_0.findIndexOf(s, s1, start, end); + var i = 0; + var lgt = 1; + if (s1.length > 0) { + lgt = s1.length; + } + while (ret != -1) { + i++; + ret = _consts_0.findIndexOf(s, s1, ret + lgt, end); + } + return (i); +} + From fijal at codespeak.net Wed Aug 22 17:50:04 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 22 Aug 2007 17:50:04 +0200 (CEST) Subject: [pypy-svn] r45913 - pypy/branch/pypy-more-rtti-inprogress/module/thread Message-ID: <20070822155004.16CAE80C7@code0.codespeak.net> Author: fijal Date: Wed Aug 22 17:50:03 2007 New Revision: 45913 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py Log: avoid leaking in case of errors Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py Wed Aug 22 17:50:03 2007 @@ -48,6 +48,7 @@ ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') res = c_thread_lock_init(ll_lock) if res == -1: + lltype.free(ll_lock, flavor='raw') raise error("out of resources") return Lock(ll_lock) From fijal at codespeak.net Wed Aug 22 17:50:30 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 22 Aug 2007 17:50:30 +0200 (CEST) Subject: [pypy-svn] r45914 - pypy/branch/pypy-more-rtti-inprogress/module/thread Message-ID: <20070822155030.C69FD812E@code0.codespeak.net> Author: fijal Date: Wed Aug 22 17:50:30 2007 New Revision: 45914 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Log: remove thread startup lock Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Wed Aug 22 17:50:30 2007 @@ -7,15 +7,11 @@ from pypy.interpreter.gateway import NoneNotWrapped from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments -THREAD_STARTUP_LOCK = thread.allocate_lock() - - class Bootstrapper: _alloc_flavor_ = 'raw' def bootstrap(self): space = self.space - THREAD_STARTUP_LOCK.release() space.threadlocals.enter_thread(space) try: self.run() @@ -81,15 +77,10 @@ boot.w_callable = w_callable boot.args = args - THREAD_STARTUP_LOCK.acquire(True) - ident = thread.start_new_thread(Bootstrapper.bootstrap, (boot,)) # wait until the thread has really started and acquired a reference to # 'boot'. - THREAD_STARTUP_LOCK.acquire(True) - THREAD_STARTUP_LOCK.release() - return space.wrap(ident) From simonb at codespeak.net Wed Aug 22 20:01:20 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Wed, 22 Aug 2007 20:01:20 +0200 (CEST) Subject: [pypy-svn] r45915 - pypy/dist/pypy/rpython/numpy/test Message-ID: <20070822180120.08869814E@code0.codespeak.net> Author: simonb Date: Wed Aug 22 20:01:17 2007 New Revision: 45915 Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py Log: remove this junk test code, i think it was there because i could not get pygame to work Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Wed Aug 22 20:01:17 2007 @@ -117,15 +117,4 @@ assert fn(0) == 1 assert fn(1) == 99 - t = TranslationContext() - t.buildannotator().build_types(access_array, [int]) - t.buildrtyper().specialize() - graph = t.buildflowgraph(access_array) - - from pypy.translator.tool.make_dot import make_dot - filename = make_dot('access_array', graph) - - from pypy.translator.c.genc import CExtModuleBuilder - b = CExtModuleBuilder(t, access_array) - filename = b.generate_source() From mwh at codespeak.net Wed Aug 22 20:07:57 2007 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 22 Aug 2007 20:07:57 +0200 (CEST) Subject: [pypy-svn] r45916 - pypy/extradoc/talk/pyconuk07 Message-ID: <20070822180757.1810F8135@code0.codespeak.net> Author: mwh Date: Wed Aug 22 20:07:57 2007 New Revision: 45916 Added: pypy/extradoc/talk/pyconuk07/ Log: a directory for my pycon 2007 talk. From xoraxax at codespeak.net Wed Aug 22 21:48:28 2007 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Wed, 22 Aug 2007 21:48:28 +0200 (CEST) Subject: [pypy-svn] r45917 - pypy/branch/pypy-more-rtti-inprogress/interpreter Message-ID: <20070822194828.703918165@code0.codespeak.net> Author: xoraxax Date: Wed Aug 22 21:48:26 2007 New Revision: 45917 Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/typedef.py Log: Add some sane repr to typedef to get more usable warnings. Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/typedef.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/interpreter/typedef.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/interpreter/typedef.py Wed Aug 22 21:48:26 2007 @@ -42,6 +42,9 @@ # hint for the annotator: track individual constant instances of TypeDef return True + def __repr__(self): + return "<%s name=%r>" % (self.__class__.__name__, self.name) + # ____________________________________________________________ # Hash support From mwh at codespeak.net Wed Aug 22 23:14:06 2007 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 22 Aug 2007 23:14:06 +0200 (CEST) Subject: [pypy-svn] r45923 - in pypy/extradoc/talk/pyconuk07: . pyconuk07.key pyconuk07.key/Contents pyconuk07.key/thumbs Message-ID: <20070822211406.7EDA981A1@code0.codespeak.net> Author: mwh Date: Wed Aug 22 23:14:06 2007 New Revision: 45923 Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/ pypy/extradoc/talk/pyconuk07/pyconuk07.key/.typeAttributes.dict pypy/extradoc/talk/pyconuk07/pyconuk07.key/Contents/ pypy/extradoc/talk/pyconuk07/pyconuk07.key/Contents/PkgInfo pypy/extradoc/talk/pyconuk07/pyconuk07.key/White_photo-bullets.pdf (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/White_photo-h.pdf pypy/extradoc/talk/pyconuk07/pyconuk07.key/White_photo-v.pdf (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/index.apxl.gz (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/py-web1.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/ pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-0.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-10.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-11.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-12.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-13.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-14.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-15.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-16.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-17.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-4.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-5.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-6.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-8.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-9.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st0.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st1.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st10-1.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st11-1.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st17.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st18.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st19.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st2-1.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st2.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st20.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st21.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st22.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st23.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st24.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st25.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st26.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st3.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st4.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st5-1.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st5.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st6.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st7.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st8.tiff (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_blue.jpg (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_gray.jpg (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_green.jpg (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_purple.jpg (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_red.jpg (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_yellow.jpg (contents, props changed) pypy/extradoc/talk/pyconuk07/pyconuk07.pdf (contents, props changed) Log: first draft of my pycon talk, very much unfinished Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/.typeAttributes.dict ============================================================================== Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/Contents/PkgInfo ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pyconuk07/pyconuk07.key/Contents/PkgInfo Wed Aug 22 23:14:06 2007 @@ -0,0 +1 @@ +???????? \ No newline at end of file Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/White_photo-bullets.pdf ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/White_photo-h.pdf ============================================================================== Files (empty file) and pypy/extradoc/talk/pyconuk07/pyconuk07.key/White_photo-h.pdf Wed Aug 22 23:14:06 2007 differ Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/White_photo-v.pdf ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/index.apxl.gz ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/py-web1.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-0.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-10.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-11.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-12.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-13.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-14.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-15.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-16.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-17.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-4.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-5.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-6.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-8.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/mt0-9.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st0.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st1.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st10-1.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st11-1.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st17.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st18.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st19.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st2-1.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st2.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st20.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st21.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st22.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st23.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st24.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st25.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st26.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st3.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st4.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st5-1.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st5.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st6.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st7.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/thumbs/st8.tiff ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_blue.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_gray.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_green.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_purple.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_red.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.key/tile_paper_yellow.jpg ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/pyconuk07/pyconuk07.pdf ============================================================================== Binary file. No diff available. From simonb at codespeak.net Thu Aug 23 01:25:45 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Thu, 23 Aug 2007 01:25:45 +0200 (CEST) Subject: [pypy-svn] r45924 - in pypy/dist/pypy/rpython/numpy: . test Message-ID: <20070822232545.D88A38123@code0.codespeak.net> Author: simonb Date: Thu Aug 23 01:25:43 2007 New Revision: 45924 Modified: pypy/dist/pypy/rpython/numpy/aarray.py pypy/dist/pypy/rpython/numpy/test/test_array.py Log: switch rnumpy to use rffi types Modified: pypy/dist/pypy/rpython/numpy/aarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/aarray.py (original) +++ pypy/dist/pypy/rpython/numpy/aarray.py Thu Aug 23 01:25:43 2007 @@ -3,25 +3,24 @@ from pypy.annotation.model import SomeExternalObject, SomeList, SomeImpossibleValue from pypy.annotation.model import SomeInteger, SomeFloat, SomeString, SomeChar from pypy.annotation.listdef import ListDef -from pypy.rpython.rctypes import rcarithmetic from pypy.tool.error import AnnotatorError +from pypy.rpython.lltypesystem import rffi import numpy class SomeArray(SomeExternalObject): """Stands for an object from the numpy module.""" - from pypy.rpython.rctypes import rcarithmetic typecode_to_item = { - 'b' : SomeInteger(knowntype=rcarithmetic.rcbyte), - 'h' : SomeInteger(knowntype=rcarithmetic.rcshort), - 'i' : SomeInteger(knowntype=rcarithmetic.rcint), - 'l' : SomeInteger(knowntype=rcarithmetic.rclong), - 'q' : SomeInteger(knowntype=rcarithmetic.rclonglong), - 'B' : SomeInteger(knowntype=rcarithmetic.rcubyte), - 'H' : SomeInteger(knowntype=rcarithmetic.rcushort), - 'I' : SomeInteger(knowntype=rcarithmetic.rcuint), - 'L' : SomeInteger(knowntype=rcarithmetic.rculong), - 'Q' : SomeInteger(knowntype=rcarithmetic.rculonglong), + 'b' : SomeInteger(knowntype=rffi.r_signedchar), + 'h' : SomeInteger(knowntype=rffi.r_uchar), + 'i' : SomeInteger(knowntype=rffi.r_int), + 'l' : SomeInteger(knowntype=rffi.r_long), + 'q' : SomeInteger(knowntype=rffi.r_longlong), + 'B' : SomeInteger(knowntype=rffi.r_uchar), + 'H' : SomeInteger(knowntype=rffi.r_ushort), + 'I' : SomeInteger(knowntype=rffi.r_uint), + 'L' : SomeInteger(knowntype=rffi.r_ulong), + 'Q' : SomeInteger(knowntype=rffi.r_ulonglong), 'f' : SomeFloat(), # XX single precision float XX 'd' : SomeFloat(), } @@ -61,21 +60,20 @@ return s_cto.get_item_type() numpy_typedict = { - (SomeInteger, rcarithmetic.rcbyte) : 'b', - (SomeInteger, rcarithmetic.rcshort) : 'h', - (SomeInteger, rcarithmetic.rcint) : 'i', - (SomeInteger, rcarithmetic.rclong) : 'l', + (SomeInteger, rffi.r_signedchar) : 'b', + (SomeInteger, rffi.r_short) : 'h', + (SomeInteger, rffi.r_int) : 'i', + (SomeInteger, rffi.r_long) : 'l', (SomeInteger, int) : 'l', - (SomeInteger, rcarithmetic.rclonglong) : 'q', - (SomeInteger, rcarithmetic.rcubyte) : 'B', - (SomeInteger, rcarithmetic.rcushort) : 'H', - (SomeInteger, rcarithmetic.rcuint) : 'I', - (SomeInteger, rcarithmetic.rculong) : 'L', - (SomeInteger, rcarithmetic.rculonglong) : 'Q', + (SomeInteger, rffi.r_longlong) : 'q', + (SomeInteger, rffi.r_uchar) : 'B', + (SomeInteger, rffi.r_ushort) : 'H', + (SomeInteger, rffi.r_uint) : 'I', + (SomeInteger, rffi.r_ulong) : 'L', + (SomeInteger, rffi.r_ulonglong) : 'Q', (SomeFloat, float) : 'f', (SomeFloat, float) : 'd', } - valid_typecodes='bhilqBHILQfd' class CallEntry(ExtRegistryEntry): Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Thu Aug 23 01:25:43 2007 @@ -10,7 +10,7 @@ from pypy import conftest import sys from pypy.rpython.test.test_llinterp import interpret -from pypy.rpython.rctypes import rcarithmetic +from pypy.rpython.lltypesystem import rffi from pypy.rpython.rint import IntegerRepr from pypy.rpython.numpy.rarray import ArrayRepr @@ -28,7 +28,7 @@ t = TranslationContext() a = t.buildannotator() s = a.build_types(access_array, [int]) - assert s.knowntype == rcarithmetic.rcint + assert s.knowntype == rffi.r_int def test_annotate_array_access_float(self): t = TranslationContext() @@ -65,7 +65,7 @@ t = TranslationContext() a = t.buildannotator() s = a.build_types(access_with_variable, []) - assert s.knowntype == rcarithmetic.rcint + assert s.knowntype == rffi.r_int class Test_specialization: def test_specialize_array_create(self): From antocuni at codespeak.net Thu Aug 23 11:37:48 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 23 Aug 2007 11:37:48 +0200 (CEST) Subject: [pypy-svn] r45925 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20070823093748.39905821E@code0.codespeak.net> Author: antocuni Date: Thu Aug 23 11:37:46 2007 New Revision: 45925 Modified: pypy/dist/pypy/translator/cli/cts.py pypy/dist/pypy/translator/cli/test/test_snippet.py Log: mark "ole" as a keyword for ilasm Modified: pypy/dist/pypy/translator/cli/cts.py ============================================================================== --- pypy/dist/pypy/translator/cli/cts.py (original) +++ pypy/dist/pypy/translator/cli/cts.py Thu Aug 23 11:37:46 2007 @@ -122,7 +122,8 @@ "readonly", "refanytype", "refanyval", "rem", "ret", "rethrow", "shl", "shr", "sizeof", "starg", "stelem", "stfld", "stind", "stloc", "stobj", "stsfld", "sub", "switch", "tail", "throw", - "unaligned", "unbox", "volatile", "xor"]) + "unaligned", "unbox", "volatile", "xor", "ole"]) + # ole is not a keyword, but mono ilasm fails if you use it as a field/method name def __init__(self, db): self.db = db @@ -235,7 +236,7 @@ METH = meth._TYPE virtual = getattr(meth, '_virtual', True) class_name = self.db.class_name(TYPE) - full_name = 'class %s::%s' % (class_name, name) + full_name = 'class %s::%s' % (class_name, self.escape_name(name)) returntype = self.lltype_to_cts(METH.RESULT) arg_types = [self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void] arg_list = ', '.join(arg_types) Modified: pypy/dist/pypy/translator/cli/test/test_snippet.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_snippet.py (original) +++ pypy/dist/pypy/translator/cli/test/test_snippet.py Thu Aug 23 11:37:46 2007 @@ -13,3 +13,13 @@ res = self.ll_to_list(self.interpret(fn, [])) assert res == [52, 53, 54] + def test_mangle(self): + class Foo: + def le(self): + return 42 + + def fn(): + f = Foo() + return f.le() + res = self.interpret(fn, [], backendopt=False) + From arigo at codespeak.net Thu Aug 23 14:25:37 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Aug 2007 14:25:37 +0200 (CEST) Subject: [pypy-svn] r45928 - in pypy/branch/pypy-more-rtti-inprogress: config module/thread Message-ID: <20070823122537.5359F8165@code0.codespeak.net> Author: arigo Date: Thu Aug 23 14:25:34 2007 New Revision: 45928 Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py pypy/branch/pypy-more-rtti-inprogress/module/thread/os_lock.py pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Log: Try to clarify the memory allocation situation around thread.start_new_thread(). Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py Thu Aug 23 14:25:34 2007 @@ -43,7 +43,9 @@ ["boehm", "ref", "framework", "none", "stacklessgc", "exact_boehm"], "ref", requires={ - "stacklessgc": [("translation.stackless", True)]}, + "stacklessgc": [("translation.stackless", True), + ("translation.thread", False)], + "framework": [("translation.thread", False)]}, cmdline="--gc"), BoolOption("thread", "enable use of threading primitives", default=False, cmdline="--thread"), Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_lock.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/os_lock.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/os_lock.py Thu Aug 23 14:25:34 2007 @@ -42,10 +42,12 @@ # XXX Usage of threadlocals.GIL in this function is considered hackish. # Ideally, all GIL knowledge should be in gil.py. mylock = self.lock - GIL = space.threadlocals.GIL - GIL.release() + GIL = space.threadlocals.getGIL() + if GIL is not None: + GIL.release() result = mylock.acquire(bool(waitflag)) - GIL.acquire(True) + if GIL is not None: + GIL.acquire(True) return space.newbool(result) def descr_lock_release(self, space): Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Thu Aug 23 14:25:34 2007 @@ -6,8 +6,15 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import NoneNotWrapped from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments +from pypy.rlib.objectmodel import free_non_gc_object -class Bootstrapper: +# This code has subtle memory management issues in order to start +# a new thread. It should work correctly with Boehm and refcounting, +# but the framework GC will not see the references stored in the +# raw-malloced Bootstrapper instances => crash. + + +class Bootstrapper(object): _alloc_flavor_ = 'raw' def bootstrap(self): @@ -16,20 +23,17 @@ try: self.run() finally: - # release ownership of these objects before we release the GIL + # release ownership of these objects before we release the GIL. + # (for the refcounting gc it is necessary to reset the fields to + # None before we use free_non_gc_object(), because the latter + # doesn't know that it needs to decref the fields) self.args = None self.w_callable = None - # at this point the thread should only have a reference to - # an empty 'self'. We hold the last reference to 'self'; indeed, - # the parent thread already forgot about it because the above - # enter_thread() must have blocked until long after the call to - # start_new_thread() below returned. - # (be careful of resetting *all* local variables to None here!) - + # we can free the empty 'self' structure now + free_non_gc_object(self) # clean up space.threadlocals to remove the ExecutionContext - # entry corresponding to the current thread + # entry corresponding to the current thread and release the GIL space.threadlocals.leave_thread(space) - # free self here? def run(self): space = self.space @@ -76,11 +80,7 @@ boot.space = space boot.w_callable = w_callable boot.args = args - ident = thread.start_new_thread(Bootstrapper.bootstrap, (boot,)) - - # wait until the thread has really started and acquired a reference to - # 'boot'. return space.wrap(ident) From antocuni at codespeak.net Thu Aug 23 15:02:17 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 23 Aug 2007 15:02:17 +0200 (CEST) Subject: [pypy-svn] r45929 - in pypy/dist/pypy/translator/cli: src test Message-ID: <20070823130217.CFFDB8186@code0.codespeak.net> Author: antocuni Date: Thu Aug 23 15:02:16 2007 New Revision: 45929 Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/test_string.py Log: I really hate .NET. String.Compare has cultural-specific behaviour by default. Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Thu Aug 23 15:02:16 2007 @@ -201,7 +201,7 @@ public static int ll_strcmp(string s1, string s2) { - return string.Compare(s1, s2); + return string.Compare(s1, s2, StringComparison.Ordinal); } public static bool ll_startswith(string s1, string s2) Modified: pypy/dist/pypy/translator/cli/test/test_string.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_string.py (original) +++ pypy/dist/pypy/translator/cli/test/test_string.py Thu Aug 23 15:02:16 2007 @@ -24,3 +24,8 @@ def test_getitem_exc(self): py.test.skip('fixme!') + def test_compare(self): + strings = ['aa', 'ZZ'] + def fn(i, j): + return strings[i] < strings[j] + assert self.interpret(fn, [0, 1], backendopt=False) == fn(0, 1) From arigo at codespeak.net Thu Aug 23 15:07:21 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Aug 2007 15:07:21 +0200 (CEST) Subject: [pypy-svn] r45930 - pypy/branch/pypy-more-rtti-inprogress/module/thread Message-ID: <20070823130721.47F8B820E@code0.codespeak.net> Author: arigo Date: Thu Aug 23 15:07:20 2007 New Revision: 45930 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py Log: Don't put the 'translator/c/src' directory in the include dirs directly. So far we always put only 'translator/c' and include 'src/xyz.h'. Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py Thu Aug 23 15:07:20 2007 @@ -19,19 +19,19 @@ from pypy.tool.autopath import pypydir pypydir = py.path.local(pypydir) -srcdir = pypydir.join('translator', 'c', 'src') -includes = ['unistd.h', 'thread.h'] +c_dir = pypydir.join('translator', 'c') +includes = ['unistd.h', 'src/thread.h'] def setup_thread_so(): - files = [srcdir.join('thread.c')] + files = [c_dir.join('src', 'thread.c')] modname = '_thread' - cache_c_module(files, modname, include_dirs=[str(srcdir)]) + cache_c_module(files, modname, include_dirs=[str(c_dir)]) return str(pypydir.join('_cache', modname)) + '.so' libraries = [setup_thread_so()] def llexternal(name, args, result): return rffi.llexternal(name, args, result, includes=includes, - libraries=libraries, include_dirs=[str(srcdir)]) + libraries=libraries, include_dirs=[str(c_dir)]) CALLBACK = lltype.Ptr(lltype.FuncType([rffi.VOIDP], rffi.VOIDP)) c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT) From arigo at codespeak.net Thu Aug 23 15:33:50 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Aug 2007 15:33:50 +0200 (CEST) Subject: [pypy-svn] r45931 - pypy/branch/pypy-more-rtti-inprogress/rpython/memory/gctransform/test Message-ID: <20070823133350.781BE8202@code0.codespeak.net> Author: arigo Date: Thu Aug 23 15:33:49 2007 New Revision: 45931 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/memory/gctransform/test/test_refcounting.py Log: A non-test. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/memory/gctransform/test/test_refcounting.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/memory/gctransform/test/test_refcounting.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/memory/gctransform/test/test_refcounting.py Thu Aug 23 15:33:49 2007 @@ -1,3 +1,4 @@ +import py from pypy.rpython.memory.gctransform.test.test_transform import rtype, rtype_and_transform, getops from pypy.rpython.memory.gctransform.test.test_transform import LLInterpedTranformerTests from pypy.rpython.memory.gctransform.refcounting import RefcountingGCTransformer @@ -43,6 +44,36 @@ res = llinterp.eval_graph(graph, [0]) assert res == 3 + def test_raw_instance_flavor(self): + # crashes for now because X() is not initialized with zeroes when + # it is allocated, but it's probably illegal to try to store + # references into a raw-malloced instance + py.test.skip("a probably-illegal test") + class State: + pass + state = State() + class Y: + def __del__(self): + state.freed_counter += 1 + class X: + _alloc_flavor_ = 'raw' + def g(): + x = X() + x.y = Y() + return x + def f(): + from pypy.rlib.objectmodel import free_non_gc_object + state.freed_counter = 0 + x = g() + assert state.freed_counter == 0 + x.y = None + assert state.freed_counter == 1 + free_non_gc_object(x) + # for now we have no automatic decref when free_non_gc_object() is + # called + llinterp, graph = self.llinterpreter_for_transformed_graph(f, []) + llinterp.eval_graph(graph, []) + def test_simple_barrier(): S = lltype.GcStruct("S", ('x', lltype.Signed)) T = lltype.GcStruct("T", ('s', lltype.Ptr(S))) From arigo at codespeak.net Thu Aug 23 15:40:59 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Aug 2007 15:40:59 +0200 (CEST) Subject: [pypy-svn] r45932 - pypy/branch/pypy-more-rtti-inprogress/module/thread Message-ID: <20070823134059.AAEB68209@code0.codespeak.net> Author: arigo Date: Thu Aug 23 15:40:59 2007 New Revision: 45932 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Log: Documented non-fix. Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/os_thread.py Thu Aug 23 15:40:59 2007 @@ -9,10 +9,11 @@ from pypy.rlib.objectmodel import free_non_gc_object # This code has subtle memory management issues in order to start -# a new thread. It should work correctly with Boehm and refcounting, -# but the framework GC will not see the references stored in the -# raw-malloced Bootstrapper instances => crash. - +# a new thread. It should work correctly with Boehm, but the framework +# GC will not see the references stored in the raw-malloced Bootstrapper +# instances => crash. It crashes with refcounting too +# (see the skipped test_raw_instance_flavor in +# rpython/memory/gctransformer/test/test_refcounting). class Bootstrapper(object): _alloc_flavor_ = 'raw' From arigo at codespeak.net Thu Aug 23 15:41:45 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Aug 2007 15:41:45 +0200 (CEST) Subject: [pypy-svn] r45933 - pypy/branch/pypy-more-rtti-inprogress/config Message-ID: <20070823134145.DAC828209@code0.codespeak.net> Author: arigo Date: Thu Aug 23 15:41:45 2007 New Revision: 45933 Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py Log: So, --thread forces gc=boehm for now. Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py Thu Aug 23 15:41:45 2007 @@ -43,12 +43,11 @@ ["boehm", "ref", "framework", "none", "stacklessgc", "exact_boehm"], "ref", requires={ - "stacklessgc": [("translation.stackless", True), - ("translation.thread", False)], - "framework": [("translation.thread", False)]}, + "stacklessgc": [("translation.stackless", True)]}, cmdline="--gc"), BoolOption("thread", "enable use of threading primitives", - default=False, cmdline="--thread"), + default=False, cmdline="--thread", + requires=[("translation.gc", "boehm")]), BoolOption("verbose", "Print extra information", default=False), BoolOption("debug", "Record extra annotation information", cmdline="-d --debug", default=False), From arigo at codespeak.net Thu Aug 23 15:42:58 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Aug 2007 15:42:58 +0200 (CEST) Subject: [pypy-svn] r45934 - pypy/branch/pypy-more-rtti-inprogress/module/thread/test Message-ID: <20070823134258.C5556821E@code0.codespeak.net> Author: arigo Date: Thu Aug 23 15:42:58 2007 New Revision: 45934 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py Log: Write test_start_new_thread in the same style as os_thread.py. Check that the references held to other objects don't leak. Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py Thu Aug 23 15:42:58 2007 @@ -2,6 +2,8 @@ from pypy.module.thread.ll_thread import * from pypy.translator.c.test.test_genc import compile from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rlib.objectmodel import free_non_gc_object import py def test_lock(): @@ -24,27 +26,56 @@ def test_start_new_thread(): import time + + + class State: + pass + state = State() + + class Z: + def __init__(self, value): + self.value = value + def __del__(self): + state.freed_counter += 1 + class Y: _alloc_flavor_ = 'raw' - - def __init__(self): - self.top = [] def bootstrap(self): - self.top.append(get_ident()) + state.my_thread_ident = get_ident() + assert state.my_thread_ident == get_ident() + state.seen_value = self.z.value + self.z = None + free_non_gc_object(self) + state.done = 1 - def f(): + def g(i): y = Y() + y.z = Z(i) start_new_thread(Y.bootstrap, (y,)) - time.sleep(.3) - res = len(y.top) - lltype.free(y, flavor='raw') - return 1 == get_ident() + g.dont_inline = True + + def f(): + main_ident = get_ident() + assert main_ident == get_ident() + state.freed_counter = 0 + for i in range(50): + state.done = 0 + state.seen_value = 0 + g(i) + while not state.done: + time.sleep(0.01) + assert state.my_thread_ident != main_ident + assert state.seen_value == i + # try to force Boehm to do some freeing + for i in range(3): + llop.gc__collect(lltype.Void) + return state.freed_counter - # for some reason, refcounting does not handle _alloc_flavor_ = 'raw' - # XXX is this testable on top of llinterp at all? fn = compile(f, [], gcpolicy='boehm') - assert fn() == False + freed_counter = fn() + print freed_counter + assert freed_counter > 0 def test_prebuilt_lock(): py.test.skip("Does not work (prebuilt opaque object)") From arigo at codespeak.net Thu Aug 23 15:47:04 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Aug 2007 15:47:04 +0200 (CEST) Subject: [pypy-svn] r45935 - pypy/branch/pypy-more-rtti-inprogress/module/thread/test Message-ID: <20070823134704.A6B278150@code0.codespeak.net> Author: arigo Date: Thu Aug 23 15:47:03 2007 New Revision: 45935 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py Log: Avoid an infinite loop if the test fails by not starting the thread. Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/test/test_ll_thread.py Thu Aug 23 15:47:03 2007 @@ -63,7 +63,11 @@ state.done = 0 state.seen_value = 0 g(i) + willing_to_wait_more = 1000 while not state.done: + willing_to_wait_more -= 1 + if not willing_to_wait_more: + raise Exception("thread didn't start?") time.sleep(0.01) assert state.my_thread_ident != main_ident assert state.seen_value == i From xoraxax at codespeak.net Thu Aug 23 17:56:38 2007 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Thu, 23 Aug 2007 17:56:38 +0200 (CEST) Subject: [pypy-svn] r45936 - pypy/branch/pypy-more-rtti-inprogress/translator/c/src Message-ID: <20070823155638.CD6468222@code0.codespeak.net> Author: xoraxax Date: Thu Aug 23 17:56:37 2007 New Revision: 45936 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/stack.h Log: Added a non-inlining hint for the stack growing stack to avoid gcc breaking it on ppc. Thanks to Anton Korobeynikov. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/stack.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/stack.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/stack.h Thu Aug 23 17:56:37 2007 @@ -11,12 +11,21 @@ #ifndef PYPY_NOT_MAIN_FILE +#ifndef PYPY_NOINLINE +# if defined __GNUC__ +# define PYPY_NOINLINE __attribute__((noinline)) +# else +// add hints for other compilers here ... +# define PYPY_NOINLINE +# endif +#endif + void LL_stack_unwind(void) { RPyRaiseSimpleException(PyExc_RuntimeError, "Recursion limit exceeded"); } -long _LL_stack_growing_direction(char *parent) +long PYPY_NOINLINE _LL_stack_growing_direction(char *parent) { char local; if (parent == NULL) From xoraxax at codespeak.net Thu Aug 23 17:57:05 2007 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Thu, 23 Aug 2007 17:57:05 +0200 (CEST) Subject: [pypy-svn] r45937 - pypy/branch/pypy-more-rtti-inprogress/interpreter Message-ID: <20070823155705.C16F78223@code0.codespeak.net> Author: xoraxax Date: Thu Aug 23 17:57:05 2007 New Revision: 45937 Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/gateway.py Log: Added __repr__ for ApplevelClass Modified: pypy/branch/pypy-more-rtti-inprogress/interpreter/gateway.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/interpreter/gateway.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/interpreter/gateway.py Thu Aug 23 17:57:05 2007 @@ -757,6 +757,9 @@ else: self.can_use_geninterp = True + def __repr__(self): + return "" % (self.filename, self.can_use_geninterp) + def getwdict(self, space): return space.fromcache(ApplevelCache).getorbuild(self) From xoraxax at codespeak.net Thu Aug 23 20:05:43 2007 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Thu, 23 Aug 2007 20:05:43 +0200 (CEST) Subject: [pypy-svn] r45939 - pypy/dist/pypy/translator/c/src Message-ID: <20070823180543.3FAE48167@code0.codespeak.net> Author: xoraxax Date: Thu Aug 23 20:05:41 2007 New Revision: 45939 Modified: pypy/dist/pypy/translator/c/src/g_include.h Log: Fix gc=ref builds on AVR. Modified: pypy/dist/pypy/translator/c/src/g_include.h ============================================================================== --- pypy/dist/pypy/translator/c/src/g_include.h (original) +++ pypy/dist/pypy/translator/c/src/g_include.h Thu Aug 23 20:05:41 2007 @@ -31,9 +31,9 @@ #include "src/int.h" #include "src/char.h" #include "src/float.h" +#include "src/address.h" #ifndef AVR #include "src/unichar.h" -#include "src/address.h" #endif #include "src/instrument.h" From fijal at codespeak.net Fri Aug 24 11:48:41 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 11:48:41 +0200 (CEST) Subject: [pypy-svn] r45945 - in pypy/branch/pypy-more-rtti-inprogress: annotation rpython rpython/lltypesystem rpython/test Message-ID: <20070824094841.143858197@code0.codespeak.net> Author: fijal Date: Fri Aug 24 11:48:40 2007 New Revision: 45945 Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py Log: Implement float % float Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py Fri Aug 24 11:48:40 2007 @@ -419,7 +419,7 @@ def union((flt1, flt2)): return SomeFloat() - add = sub = mul = div = truediv = union + mod = add = sub = mul = div = truediv = union def pow((flt1, flt2), obj3): return SomeFloat() Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py Fri Aug 24 11:48:40 2007 @@ -234,6 +234,7 @@ 'float_gt': LLOp(canfold=True), 'float_ge': LLOp(canfold=True), 'float_pow': LLOp(canfold=True), + 'float_mod': LLOp(canfold=True), 'llong_is_true': LLOp(canfold=True), 'llong_neg': LLOp(canfold=True), Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py Fri Aug 24 11:48:40 2007 @@ -47,6 +47,11 @@ rtype_inplace_truediv = rtype_truediv + def rtype_mod(_, hop): + return _rtype_template(hop, 'mod') + + rtype_inplace_mod = rtype_mod + # turn 'div' on floats into 'truediv' rtype_div = rtype_truediv rtype_inplace_div = rtype_inplace_truediv Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py Fri Aug 24 11:48:40 2007 @@ -108,6 +108,12 @@ res = self.interpret(fn, [2.0, 3.0]) assert res == 8.0 + def test_float_mod(self): + def fn(x, y): + return x % y + res = self.interpret(fn, [2.33, 1.0]) + assert res - 0.33 < 0.00000000001 + class TestLLtype(BaseTestRfloat, LLRtypeMixin): def test_hash(self): From fijal at codespeak.net Fri Aug 24 11:57:54 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 11:57:54 +0200 (CEST) Subject: [pypy-svn] r45946 - pypy/branch/pypy-more-rtti-inprogress/translator/c/src Message-ID: <20070824095754.BF7E78220@code0.codespeak.net> Author: fijal Date: Fri Aug 24 11:57:54 2007 New Revision: 45946 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/float.h Log: Implement float_mod Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/float.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/float.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/float.h Fri Aug 24 11:57:54 2007 @@ -28,6 +28,7 @@ #define OP_FLOAT_MUL(x,y,r) r = x * y #define OP_FLOAT_TRUEDIV(x,y,r) r = x / y #define OP_FLOAT_POW(x,y,r) r = pow(x, y) +#define OP_FLOAT_MOD(x,y,r) r = fmod(x, y) /*** conversions ***/ From antocuni at codespeak.net Fri Aug 24 12:31:08 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 24 Aug 2007 12:31:08 +0200 (CEST) Subject: [pypy-svn] r45947 - in pypy/dist/pypy/translator: cli/test oosupport Message-ID: <20070824103108.9346F8228@code0.codespeak.net> Author: antocuni Date: Fri Aug 24 12:31:07 2007 New Revision: 45947 Modified: pypy/dist/pypy/translator/cli/test/test_snippet.py pypy/dist/pypy/translator/oosupport/function.py Log: finally found the bug. See the comments for more info. Modified: pypy/dist/pypy/translator/cli/test/test_snippet.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_snippet.py (original) +++ pypy/dist/pypy/translator/cli/test/test_snippet.py Fri Aug 24 12:31:07 2007 @@ -23,3 +23,21 @@ return f.le() res = self.interpret(fn, [], backendopt=False) + def test_link_vars_overlapping(self): + from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift + def fn(maxofs): + lastofs = 0 + ofs = 1 + while ofs < maxofs: + lastofs = ofs + try: + ofs = ovfcheck_lshift(ofs, 1) + except OverflowError: + ofs = maxofs + else: + ofs = ofs + 1 + return lastofs + res = self.interpret(fn, [64]) + expected = fn(64) + assert res == expected + Modified: pypy/dist/pypy/translator/oosupport/function.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/function.py (original) +++ pypy/dist/pypy/translator/oosupport/function.py Fri Aug 24 12:31:07 2007 @@ -245,13 +245,22 @@ def _setup_link(self, link): target = link.target + linkvars = [] for to_load, to_store in zip(link.args, target.inputargs): if isinstance(to_load, flowmodel.Variable) and to_load.name == to_store.name: continue if to_load.concretetype is ootype.Void: continue - self.generator.add_comment("%r --> %r" % (to_load, to_store)) + linkvars.append((to_load, to_store)) + + # after SSI_to_SSA it can happen to have to_load = [a, b] and + # to_store = [b, c]. If we store each variable sequentially, + # 'b' would be overwritten before being read. To solve, we + # first load all the values on the stack, then store in the + # appropriate places. + for to_load, to_store in linkvars: self.generator.load(to_load) + for to_load, to_store in reversed(linkvars): self.generator.store(to_store) def _trace_enabled(self): From fijal at codespeak.net Fri Aug 24 12:49:55 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 12:49:55 +0200 (CEST) Subject: [pypy-svn] r45948 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module rpython/module/test translator/c Message-ID: <20070824104955.18D268220@code0.codespeak.net> Author: fijal Date: Fri Aug 24 12:49:55 2007 New Revision: 45948 Added: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_time.py (contents, props changed) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Log: Move time.{time, clock, sleep} into rffi. Only posix version, I need to set up window machine to finish those. Leave ll_time.c as a reference for windows impl. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py Fri Aug 24 12:49:55 2007 @@ -10,6 +10,7 @@ from pypy.rpython.lltypesystem.module import ll_math from pypy.rpython.ootypesystem.module import ll_math as oo_math from pypy.rpython.module import ll_os +from pypy.rpython.module import ll_time try: import termios except ImportError: Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py Fri Aug 24 12:49:55 2007 @@ -151,9 +151,6 @@ # external function declarations declare(os.path.exists, bool , 'll_os_path/exists') declare(os.path.isdir, bool , 'll_os_path/isdir') -declare(time.time , float , 'll_time/time') -declare(time.clock , float , 'll_time/clock') -declare(time.sleep , noneannotation, 'll_time/sleep') # ___________________________________________________________ # win/NT hack: patch ntpath.isabs() to be RPythonic Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Fri Aug 24 12:49:55 2007 @@ -1,20 +1,140 @@ """ -Dummy low-level implementations for the external functions of the 'time' module. +Low-level implementations for the external functions of the 'time' module. """ -# See ll_os.py. - -import time - - -def ll_time_time(): - return time.time() -ll_time_time.suggested_primitive = True - -def ll_time_clock(): - return time.clock() -ll_time_clock.suggested_primitive = True - -def ll_time_sleep(t): - time.sleep(t) -ll_time_sleep.suggested_primitive = True +import time, sys, math +from pypy.rpython.lltypesystem import rffi +from pypy.rpython.tool import rffi_platform as platform +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.extfunc import BaseLazyRegistering, registering + +class CConfig: + if sys.platform.startswith('win'): + includes = ['sys/time.h', 'windows.h'] + else: + includes = ['time.h', 'errno.h', 'sys/select.h', 'sys/types.h', + 'unistd.h', 'sys/timeb.h'] + # XXX argh, argh, argh, should be automatic + _header_ = "\n".join(["#include <%s>" % name for name in includes]) + CLOCK_T = platform.SimpleType('clock_t', rffi.INT) + TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.INT), + ('tv_usec', rffi.INT)]) + TIMEB = platform.Struct('struct timeb', [('time', rffi.INT), + ('millitm', rffi.INT)]) + TIME_T = platform.SimpleType('time_t', rffi.INT) + +constant_names = ['CLOCKS_PER_SEC', 'CLK_TCK', 'EINTR'] +for const in constant_names: + setattr(CConfig, const, platform.DefinedConstantInteger(const)) +defs_names = ['HAVE_FTIME', 'HAVE_GETTIMEOFDAY', 'GETTIMEOFDAY_NO_TZ'] +for const in defs_names: + setattr(CConfig, const, platform.Defined(const)) + +class RegisterTime(BaseLazyRegistering): + def __init__(self): + self.__dict__.update(platform.configure(CConfig)) + if self.CLOCKS_PER_SEC is None: + if self.CLK_TCK is None: + self.CLOCKS_PER_SEC = 1000000 + else: + self.CLOCKS_PER_SEC = self.CLK_TCK + # XXX another to-be-automated issue + self.includes = CConfig.includes + self.TIMEVALP = lltype.Ptr(self.TIMEVAL) + self.TIMEBP = lltype.Ptr(self.TIMEB) + + @registering(time.time) + def register_time_time(self): + if sys.platform == 'win32': + xxx + else: + # AWFUL + if self.HAVE_GETTIMEOFDAY: + if self.GETTIMEOFDAY_NO_TZ: + c_gettimeofday = rffi.llexternal('gettimeofday', + [self.TIMEVALP], rffi.INT, + includes=self.includes) + else: + c_gettimeofday = rffi.llexternal('gettimeofday', + [self.TIMEVALP, rffi.VOIDP], rffi.INT, + includes=self.includes) + else: + c_gettimeofday = None + + if self.HAVE_FTIME: + c_ftime = rffi.llexternal('ftime', [self.TIMEB], rffi.VOID, + includes=self.includes) + else: + c_ftime = None # not to confuse flow objspace + + c_time = rffi.llexternal('time', [rffi.VOIDP], self.TIME_T, + includes=self.includes) + + def time_time_llimpl(): + void = lltype.nullptr(rffi.VOIDP.TO) + result = -1.0 + if self.HAVE_GETTIMEOFDAY: + t = lltype.malloc(self.TIMEVAL, flavor='raw') + + if self.GETTIMEOFDAY_NO_TZ: + if c_gettimeofday(t) == 0: + result = float(t.c_tv_sec) + \ + float(t.c_tv_usec) * 0.000001 + else: + if c_gettimeofday(t, void) == 0: + result = float(t.c_tv_sec) + \ + float(t.c_tv_usec) * 0.000001 + lltype.free(t, flavor='raw') + if result != -1: + return result + if self.HAVE_FTIME: + t = lltype.malloc(self.TIMEB, flavor='raw') + c_ftime(t) + result = float(t.c_time) + float(t.c_millitm) * 0.001 + lltype.free(t, flavor='raw') + return result + return float(c_time(void)) + self.register(time.time, [], float, llimpl=time_time_llimpl, + export_name='ll_time.time') + + @registering(time.clock) + def register_time_clock(self): + c_clock = rffi.llexternal('clock', [], self.CLOCK_T, + includes=self.includes) + + if sys.platform == 'win32': + xxx + else: + def time_clock_llimpl(): + result = c_clock() + return float(result) / self.CLOCKS_PER_SEC + self.register(time.clock, [], float, llimpl=time_clock_llimpl, + export_name='ll_time.clock') + + @registering(time.sleep) + def register_time_sleep(self): + if sys.platform == 'win32': + xxx + else: + c_select = rffi.llexternal('select', [rffi.INT, rffi.VOIDP, + rffi.VOIDP, rffi.VOIDP, + self.TIMEVALP], + rffi.INT, includes=self.includes) + + def time_sleep_llimpl(secs): + # XXX cannot put it into try: finally: because + # someone forgotten to call hop.exception_is_here + void = lltype.nullptr(rffi.VOIDP.TO) + t = lltype.malloc(self.TIMEVAL, flavor='raw') + #try: + frac = secs % 1.0 + t.c_tv_sec = int(secs) + t.c_tv_usec = int(frac*1000000.0) + if c_select(0, void, void, void, t) != 0: + # XXX EINTR + lltype.free(t, flavor='raw') + raise IOError("Select failed") + #finally: + lltype.free(t, flavor='raw') + self.register(time.sleep, [float], None, llimpl=time_sleep_llimpl, + export_name='ll_time.sleep') Added: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_time.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_time.py Fri Aug 24 12:49:55 2007 @@ -0,0 +1,48 @@ + +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +#from pypy.translator.c.test.test_genc import compile + +import time + +class BaseTestTime(BaseRtypingTest): + def test_time_time(self): + def fn(): + return time.time() + + t0 = time.time() + res = self.interpret(fn, []) + t1 = time.time() + assert t0 <= res <= t1 + + def test_time_clock(self): + def f(): + return time.clock() + t0 = time.clock() + t1 = self.interpret(f, []) + t2 = time.clock() + t3 = self.interpret(f, []) + t4 = time.clock() + t5 = self.interpret(f, []) + t6 = time.clock() + # time.clock() and t1() might have a different notion of zero, so + # we can only subtract two numbers returned by the same function. + assert 0 <= t2-t0 + assert 0 <= t3-t1 <= t4-t0 + assert 0 <= t4-t2 <= t5-t1 <= t6-t0 + assert 0 <= t5-t3 <= t6-t2 + assert 0 <= t6-t4 + + def test_time_sleep(self): + def does_nothing(): + time.sleep(0.19) + t0 = time.time() + self.interpret(does_nothing, []) + t1 = time.time() + assert t0 <= t1 + assert t1 - t0 >= 0.15 + +class TestLLType(BaseTestTime, LLRtypeMixin): + pass + +class TestOOType(BaseTestTime, OORtypeMixin): + pass Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Fri Aug 24 12:49:55 2007 @@ -19,9 +19,6 @@ # references to functions, so we cannot insert classmethods here. EXTERNALS = { - ll_time.ll_time_clock: 'LL_time_clock', - ll_time.ll_time_sleep: 'LL_time_sleep', - ll_time.ll_time_time: 'LL_time_time', ll_strtod.Implementation.ll_strtod_parts_to_float: 'LL_strtod_parts_to_float', ll_strtod.Implementation.ll_strtod_formatd: From fijal at codespeak.net Fri Aug 24 12:56:03 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 12:56:03 +0200 (CEST) Subject: [pypy-svn] r45949 - pypy/branch/pypy-more-rtti-inprogress/translator/c Message-ID: <20070824105603.4F7FD8228@code0.codespeak.net> Author: fijal Date: Fri Aug 24 12:56:03 2007 New Revision: 45949 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Log: Kill Kill Kill Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py Fri Aug 24 12:56:03 2007 @@ -9,11 +9,6 @@ from pypy.rpython.module import ll_stackless, ll_stack from pypy.rpython.lltypesystem.module import ll_strtod -try: - from pypy.module.thread.rpython import ll_thread -except ImportError: - ll_thread = None - # table of functions hand-written in src/ll_*.h # Note about *.im_func: The annotator and the rtyper expect direct # references to functions, so we cannot insert classmethods here. @@ -29,15 +24,6 @@ ll_stack.ll_stack_too_big: 'LL_stack_too_big', } -if ll_thread: EXTERNALS.update({ - ll_thread.ll_newlock: 'LL_thread_newlock', - ll_thread.ll_acquirelock: 'LL_thread_acquirelock', - ll_thread.ll_releaselock: 'LL_thread_releaselock', - ll_thread.ll_fused_releaseacquirelock: 'LL_thread_fused_releaseacquirelock', - ll_thread.ll_thread_start: 'LL_thread_start', - ll_thread.ll_thread_get_ident: 'LL_thread_get_ident', - }) - #______________________________________________________ # insert 'simple' math functions into EXTERNALs table: From fijal at codespeak.net Fri Aug 24 14:20:39 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 14:20:39 +0200 (CEST) Subject: [pypy-svn] r45950 - pypy/branch/pypy-more-rtti-inprogress/translator/cli/test Message-ID: <20070824122039.0FE3A8210@code0.codespeak.net> Author: fijal Date: Fri Aug 24 14:20:38 2007 New Revision: 45950 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py Log: Add time tests. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py Fri Aug 24 14:20:38 2007 @@ -5,6 +5,7 @@ from pypy.tool import udir from pypy.translator.cli.test.runtest import CliTest from pypy.rpython.test.test_rbuiltin import BaseTestRbuiltin +from pypy.rpython.module.test.test_ll_time import BaseTestTime def skip_os(self): py.test.skip("CLI doesn't support the os module, yet") @@ -123,3 +124,6 @@ return os.path.join(a, b) res = self.ll_to_string(self.interpret(fn, ['a', 'b'])) assert res == os.path.join('a', 'b') + +class TestCliTime(CliTest, BaseTestTime): + pass From fijal at codespeak.net Fri Aug 24 14:29:41 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 14:29:41 +0200 (CEST) Subject: [pypy-svn] r45951 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070824122941.B5B2C8225@code0.codespeak.net> Author: fijal Date: Fri Aug 24 14:29:40 2007 New Revision: 45951 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Log: Fix names for cli backend Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Fri Aug 24 14:29:40 2007 @@ -95,7 +95,7 @@ return result return float(c_time(void)) self.register(time.time, [], float, llimpl=time_time_llimpl, - export_name='ll_time.time') + export_name='ll_time.ll_time_time') @registering(time.clock) def register_time_clock(self): @@ -109,7 +109,7 @@ result = c_clock() return float(result) / self.CLOCKS_PER_SEC self.register(time.clock, [], float, llimpl=time_clock_llimpl, - export_name='ll_time.clock') + export_name='ll_time.ll_time_clock') @registering(time.sleep) def register_time_sleep(self): @@ -137,4 +137,4 @@ #finally: lltype.free(t, flavor='raw') self.register(time.sleep, [float], None, llimpl=time_sleep_llimpl, - export_name='ll_time.sleep') + export_name='ll_time.ll_time_sleep') From antocuni at codespeak.net Fri Aug 24 14:36:47 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 24 Aug 2007 14:36:47 +0200 (CEST) Subject: [pypy-svn] r45952 - pypy/branch/pypy-more-rtti-inprogress/translator/cli/test Message-ID: <20070824123647.34D518224@code0.codespeak.net> Author: antocuni Date: Fri Aug 24 14:36:44 2007 New Revision: 45952 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py Log: the original test_clock() can't work for cli, because each 'interpret' starts a new process and we really can't compare the results. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py Fri Aug 24 14:36:44 2007 @@ -126,4 +126,12 @@ assert res == os.path.join('a', 'b') class TestCliTime(CliTest, BaseTestTime): - pass + + def test_time_clock(self): + import time + def f(): + return time.clock(), time.clock(), time.clock() + res = self.interpret(f, []) + t1, t2, t3 = self.ll_to_tuple(res) + assert 0 <= t1 <= t2 <= t3 + From fijal at codespeak.net Fri Aug 24 16:41:43 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 16:41:43 +0200 (CEST) Subject: [pypy-svn] r45954 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070824144143.D27F68225@code0.codespeak.net> Author: fijal Date: Fri Aug 24 16:41:42 2007 New Revision: 45954 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py Log: Minor improvements Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py Fri Aug 24 16:41:42 2007 @@ -86,15 +86,21 @@ return "lltype.Ptr(%s)" % self.proc_tp(tp._type_) elif issubclass(tp, ctypes.Structure): return self.proc_struct(tp) + elif issubclass(tp, ctypes.Array): + return "lltype.Ptr(lltype.Array(%s, hints={'nolength': True}))" % \ + self.proc_tp(tp._type_) raise NotImplementedError("Not implemented mapping for %s" % tp) def proc_func(self, func): - print "proc_func", func name = func.__name__ + if not self.extra_args: + extra_args = "" + else: + extra_args = ", " + self.extra_args src = py.code.Source(""" - %s = rffi.llexternal('%s', [%s], %s, %s) + %s = rffi.llexternal('%s', [%s], %s%s) """%(name, name, ", ".join([self.proc_tp(arg) for arg in func.argtypes]), - self.proc_tp(func.restype), self.extra_args)) + self.proc_tp(func.restype), extra_args)) self.source = py.code.Source(self.source, src) def proc_namespace(self, ns): @@ -103,11 +109,7 @@ if id(value) in exempt: continue if isinstance(value, ctypes._CFuncPtr): - print "func", key, value - try: - self.proc_func(value) - except NotImplementedError: - print "skipped:", value + self.proc_func(value) #print value, value.__class__.__name__ def compiled(self): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py Fri Aug 24 16:41:42 2007 @@ -25,7 +25,7 @@ rffi_source = RffiSource() assert rffi_source.proc_tp(ctypes.POINTER(ctypes.c_uint)) == \ "lltype.Ptr(lltype.Array(rffi.UINT, hints={'nolength': True}))" - rffi_source.proc_tp(random_structure) + src = rffi_source.proc_tp(random_structure) _src = py.code.Source(""" random_structure = lltype.Struct('random_structure', ('one', rffi.INT), ('two', lltype.Ptr(lltype.Array(rffi.INT, hints={'nolength': True}))), hints={'external':'C'}) """) @@ -33,6 +33,12 @@ assert src.strip() == _src.strip(), str(src) + "\n" + str(_src) assert rffi_source.compiled() +def test_proc_tp_array(): + rffi_source = RffiSource() + src = rffi_source.proc_tp(ctypes.c_uint * 12) + _src = "lltype.Ptr(lltype.Array(rffi.UINT, hints={'nolength': True}))" + assert src == _src + class TestMkrffi(TestBasic): def test_single_func(self): func = self.lib.int_to_void_p @@ -42,7 +48,7 @@ src = RffiSource() src.proc_func(func) _src = py.code.Source(""" - int_to_void_p = rffi.llexternal('int_to_void_p', [rffi.INT], rffi.VOIDP, ) + int_to_void_p = rffi.llexternal('int_to_void_p', [rffi.INT], rffi.VOIDP) """) assert src.source == _src, str(src) + "\n" + str(_src) @@ -58,8 +64,9 @@ _src = py.code.Source(""" random_structure = lltype.Struct('random_structure', ('one', rffi.INT), ('two', lltype.Ptr(lltype.Array(rffi.INT, hints={'nolength': True}))), hints={'external':'C'}) - int_int_to_struct_p = rffi.llexternal('int_int_to_struct_p', [rffi.INT, rffi.INT], lltype.Ptr(random_structure), ) + int_int_to_struct_p = rffi.llexternal('int_int_to_struct_p', [rffi.INT, rffi.INT], lltype.Ptr(random_structure)) """) src = rffi_source.source assert src.strip() == _src.strip(), str(src) + "\n" + str(_src) assert rffi_source.compiled() + From antocuni at codespeak.net Fri Aug 24 17:44:32 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 24 Aug 2007 17:44:32 +0200 (CEST) Subject: [pypy-svn] r45955 - in pypy/dist/pypy/translator: cli oosupport oosupport/test_template Message-ID: <20070824154432.57E7B8229@code0.codespeak.net> Author: antocuni Date: Fri Aug 24 17:44:30 2007 New Revision: 45955 Modified: pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/oosupport/function.py pypy/dist/pypy/translator/oosupport/test_template/snippets.py Log: "how can it ever worked": when evaluating a link we must set the corresponding variables only if the condition is true. Else, we might modify a variable even if we should not. Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Fri Aug 24 17:44:30 2007 @@ -373,6 +373,9 @@ def branch_if_equal(self, target_label): self.ilasm.opcode('beq', target_label) + def branch_if_not_equal(self, target_label): + self.ilasm.opcode('bne.un', target_label) + def push_primitive_constant(self, TYPE, value): ilasm = self.ilasm if TYPE is ootype.Void: Modified: pypy/dist/pypy/translator/oosupport/function.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/function.py (original) +++ pypy/dist/pypy/translator/oosupport/function.py Fri Aug 24 17:44:30 2007 @@ -230,13 +230,17 @@ def render_numeric_switch_naive(self, block): for link in block.exits: target_label = self._get_block_name(link.target) - self._setup_link(link) if link.exitcase == 'default': + self._setup_link(link) self.generator.branch_unconditionally(target_label) else: + next_case = self.next_label('next_case') self.generator.push_primitive_constant(block.exitswitch.concretetype, link.exitcase) self.generator.load(block.exitswitch) - self.generator.branch_if_equal(target_label) + self.generator.branch_if_not_equal(next_case) + self._setup_link(link) + self.generator.branch_unconditionally(target_label) + self.set_label(next_case) def _follow_link(self, link): target_label = self._get_block_name(link.target) @@ -258,6 +262,13 @@ # 'b' would be overwritten before being read. To solve, we # first load all the values on the stack, then store in the # appropriate places. + + if self._trace_enabled(): + self._trace('link', writeline=True) + for to_load, to_store in linkvars: + self._trace_value('%s <-- %s' % (to_store, to_load), to_load) + self._trace('', writeline=True) + for to_load, to_store in linkvars: self.generator.load(to_load) for to_load, to_store in reversed(linkvars): Modified: pypy/dist/pypy/translator/oosupport/test_template/snippets.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/test_template/snippets.py (original) +++ pypy/dist/pypy/translator/oosupport/test_template/snippets.py Fri Aug 24 17:44:30 2007 @@ -48,3 +48,16 @@ obj.x = x + y return obj.x assert self.interpret(fn, [1,3]) == 4 + + def test_link(self): + def fn(): + plus = False + for c in 'a': + if c == 'b': + plus = True + elif c == 'c': + binary = True + return plus + res = self.interpret(fn, []) + expected = fn() + assert res == expected From antocuni at codespeak.net Fri Aug 24 17:53:05 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 24 Aug 2007 17:53:05 +0200 (CEST) Subject: [pypy-svn] r45956 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20070824155305.8C3FB80C2@code0.codespeak.net> Author: antocuni Date: Fri Aug 24 17:53:05 2007 New Revision: 45956 Modified: pypy/dist/pypy/translator/cli/class_.py pypy/dist/pypy/translator/cli/constant.py pypy/dist/pypy/translator/cli/cts.py pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/metavm.py pypy/dist/pypy/translator/cli/record.py pypy/dist/pypy/translator/cli/test/runtest.py Log: refactor how gencli represent .NET types: instead of using strings, use instances of our own class hierarchy; this add an additional layer between ootype's types and .NET types which will allow for much more flexibility in the future. Modified: pypy/dist/pypy/translator/cli/class_.py ============================================================================== --- pypy/dist/pypy/translator/cli/class_.py (original) +++ pypy/dist/pypy/translator/cli/class_.py Fri Aug 24 17:53:05 2007 @@ -84,7 +84,7 @@ for f_name, (f_type, f_default) in self.INSTANCE._fields.iteritems(): cts_type = self.cts.lltype_to_cts(f_type) f_name = self.cts.escape_name(f_name) - if cts_type != 'void': + if cts_type != CTS.types.void: ilasm.field(f_name, cts_type) self._ctor() @@ -134,7 +134,7 @@ INSTANCE_DEF, _ = self.INSTANCE._lookup_field(f_name) cts_type = self.cts.lltype_to_cts(F_TYPE) f_name = self.cts.escape_name(f_name) - if cts_type != 'void': + if cts_type != CTS.types.void: self.ilasm.opcode('ldarg.0') push_constant(self.db, F_TYPE, f_default, self.gen) class_name = self.db.class_name(INSTANCE_DEF) Modified: pypy/dist/pypy/translator/cli/constant.py ============================================================================== --- pypy/dist/pypy/translator/cli/constant.py (original) +++ pypy/dist/pypy/translator/cli/constant.py Fri Aug 24 17:53:05 2007 @@ -265,9 +265,9 @@ class CLIBaseConstMixin(object): """ A mix-in with a few extra methods the CLI backend uses """ - def get_type(self, include_class=True): + def get_type(self): """ Returns the CLI type for this constant's representation """ - return self.cts.lltype_to_cts(self.value._TYPE, include_class) + return self.cts.lltype_to_cts(self.value._TYPE) def push_inline(self, gen, TYPE): """ Overload the oosupport version so that we use the CLI opcode Modified: pypy/dist/pypy/translator/cli/cts.py ============================================================================== --- pypy/dist/pypy/translator/cli/cts.py (original) +++ pypy/dist/pypy/translator/cli/cts.py Fri Aug 24 17:53:05 2007 @@ -4,61 +4,146 @@ import exceptions -from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong +from py.builtin import set from pypy.rpython.lltypesystem import lltype from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.llmemory import WeakGcAddress from pypy.translator.cli.option import getoption from pypy.translator.cli import oopspec -try: - set -except NameError: - from sets import Set as set - from pypy.tool.ansi_print import ansi_log import py log = py.log.Producer("cli") py.log.setconsumer("cli", ansi_log) -WEAKREF = '[mscorlib]System.WeakReference' -PYPY_LIST = '[pypylib]pypy.runtime.List`1<%s>' -PYPY_LIST_OF_VOID = '[pypylib]pypy.runtime.ListOfVoid' -PYPY_DICT = '[pypylib]pypy.runtime.Dict`2<%s, %s>' +class CliType(object): + def typename(self): + raise NotImplementedError + + def __str__(self): + return self.typename() + + def __hash__(self): + return hash(self.typename()) + + def __eq__(self, other): + return self.typename() == other.typename() + + def __ne__(self, other): + return self.typename() != other.typename() + + +class CliPrimitiveType(CliType): + def __init__(self, name): + self.name = name + + def typename(self): + return self.name + + +class CliReferenceType(CliType): + def typename(self): + return 'class ' + self.classname() + + def classname(self): + raise NotImplementedError + + +class CliClassType(CliReferenceType): + def __init__(self, assembly, name): + self.assembly = assembly + self.name = name + + def classname(self): + if self.assembly: + return '[%s]%s' % (self.assembly, self.name) + else: + return self.name + + +class CliGenericType(CliReferenceType): + def __init__(self, assembly, name, numparam): + self.assembly = assembly + self.name = name + self.numparam = numparam + + def classname(self): + paramtypes = [self.paramtype(i) for i in range(self.numparam)] + thistype = self.specialize(*paramtypes) + return thistype.classname() + + def specialize(self, *types): + assert len(types) == self.numparam + return CliSpecializedType(self, types) + + def paramtype(self, num): + assert 0 <= num < self.numparam + return CliPrimitiveType('!%d' % num) + +class CliSpecializedType(CliReferenceType): + def __init__(self, generic_type, arg_types): + self.generic_type = generic_type + self.arg_types = arg_types + + def classname(self): + assembly = self.generic_type.assembly + name = self.generic_type.name + numparam = self.generic_type.numparam + arglist = ', '.join([arg.typename() for arg in self.arg_types]) + return '[%s]%s`%d<%s>' % (assembly, name, numparam, arglist) + + +T = CliPrimitiveType +class types: + void = T('void') + int32 = T('int32') + uint32 = T('unsigned int32') + int64 = T('int64') + uint64 = T('unsigned int64') + bool = T('bool') + float64 = T('float64') + char = T('char') + string = T('string') + + weakref = CliClassType('mscorlib', 'System.WeakReference') + type = CliClassType('mscorlib', 'System.Type') + object = CliClassType('mscorlib', 'System.Object') + list = CliGenericType('pypylib', 'pypy.runtime.List', 1) + list_of_void = CliClassType('pypylib', 'pypy.runtime.ListOfVoid') + dict = CliGenericType('pypylib', 'pypy.runtime.Dict', 2) + dict_void_void = CliClassType('pypylib', 'pypy.runtime.DictVoidVoid') + dict_items_iterator = CliGenericType('pypylib', 'pypy.runtime.DictItemsIterator', 2) + string_builder = CliClassType('pypylib', 'pypy.runtime.StringBuilder') +del T + +WEAKREF = types.weakref.classname() PYPY_DICT_OF_VOID = '[pypylib]pypy.runtime.DictOfVoid`2<%s, int32>' -PYPY_DICT_VOID_VOID = '[pypylib]pypy.runtime.DictVoidVoid' -PYPY_DICT_ITEMS_ITERATOR = '[pypylib]pypy.runtime.DictItemsIterator`2<%s, %s>' -PYPY_STRING_BUILDER = '[pypylib]pypy.runtime.StringBuilder' + _lltype_to_cts = { - ootype.Void: 'void', - ootype.Signed: 'int32', - ootype.Unsigned: 'unsigned int32', - SignedLongLong: 'int64', - UnsignedLongLong: 'unsigned int64', - ootype.Bool: 'bool', - ootype.Float: 'float64', - ootype.Char: 'char', - ootype.UniChar: 'char', - ootype.Class: 'class [mscorlib]System.Type', - ootype.String: 'string', - ootype.StringBuilder: 'class ' + PYPY_STRING_BUILDER, - WeakGcAddress: 'class ' + WEAKREF, + ootype.Void: types.void, + ootype.Signed: types.int32, + ootype.Unsigned: types.uint32, + ootype.SignedLongLong: types.int64, + ootype.UnsignedLongLong: types.uint64, + ootype.Bool: types.bool, + ootype.Float: types.float64, + ootype.Char: types.char, + ootype.UniChar: types.char, + ootype.Class: types.type, + ootype.String: types.string, + ootype.StringBuilder: types.string_builder, + WeakGcAddress: types.weakref, # maps generic types to their ordinal - ootype.List.SELFTYPE_T: 'class ' + (PYPY_LIST % '!0'), - ootype.List.ITEMTYPE_T: '!0', - ootype.Dict.SELFTYPE_T: 'class ' + (PYPY_DICT % ('!0', '!1')), - ootype.Dict.KEYTYPE_T: '!0', - ootype.Dict.VALUETYPE_T: '!1', - ootype.DictItemsIterator.SELFTYPE_T: 'class ' + (PYPY_DICT_ITEMS_ITERATOR % ('!0', '!1')), - ootype.DictItemsIterator.KEYTYPE_T: '!0', - ootype.DictItemsIterator.VALUETYPE_T: '!1', - } - -_pyexception_to_cts = { - exceptions.Exception: '[mscorlib]System.Exception', - exceptions.OverflowError: '[mscorlib]System.OverflowException' + ootype.List.SELFTYPE_T: types.list, + ootype.List.ITEMTYPE_T: types.list.paramtype(0), + ootype.Dict.SELFTYPE_T: types.dict, + ootype.Dict.KEYTYPE_T: types.dict.paramtype(0), + ootype.Dict.VALUETYPE_T: types.dict.paramtype(1), + ootype.DictItemsIterator.SELFTYPE_T: types.dict_items_iterator, + ootype.DictItemsIterator.KEYTYPE_T: types.dict_items_iterator.paramtype(0), + ootype.DictItemsIterator.VALUETYPE_T: types.dict_items_iterator.paramtype(1), } @@ -125,15 +210,11 @@ "unaligned", "unbox", "volatile", "xor", "ole"]) # ole is not a keyword, but mono ilasm fails if you use it as a field/method name + types = types # for convenience + def __init__(self, db): self.db = db - def __class(self, result, include_class): - if include_class: - return 'class ' + result - else: - return result - def escape_name(self, name): """Mangle then name if it's a ilasm reserved word""" if name in self.ILASM_KEYWORDS: @@ -141,46 +222,47 @@ else: return name - def lltype_to_cts(self, t, include_class=True): + def lltype_to_cts(self, t): if t is ootype.ROOT: - return self.__class('[mscorlib]System.Object', include_class) + return types.object elif isinstance(t, lltype.Ptr) and isinstance(t.TO, lltype.OpaqueType): - return self.__class('[mscorlib]System.Object', include_class) + return types.object elif isinstance(t, ootype.Instance): NATIVE_INSTANCE = t._hints.get('NATIVE_INSTANCE', None) if NATIVE_INSTANCE: - return self.__class(NATIVE_INSTANCE._name, include_class) + return CliClassType(None, NATIVE_INSTANCE._name) else: name = self.db.pending_class(t) - return self.__class(name, include_class) + return CliClassType(None, name) elif isinstance(t, ootype.Record): name = self.db.pending_record(t) - return self.__class(name, include_class) + return CliClassType(None, name) elif isinstance(t, ootype.StaticMethod): delegate = self.db.record_delegate(t) - return self.__class(delegate, include_class) + return CliClassType(None, delegate) elif isinstance(t, ootype.List): item_type = self.lltype_to_cts(t._ITEMTYPE) - if item_type == 'void': # special case: List of Void - return self.__class(PYPY_LIST_OF_VOID, include_class) - return self.__class(PYPY_LIST % item_type, include_class) + if item_type == types.void: # special case: List of Void + return types.list_of_void + return types.list.specialize(item_type) elif isinstance(t, ootype.Dict): key_type = self.lltype_to_cts(t._KEYTYPE) value_type = self.lltype_to_cts(t._VALUETYPE) - if value_type == 'void': # special cases: Dict with voids - if key_type == 'void': - return self.__class(PYPY_DICT_VOID_VOID, include_class) + if value_type == types.void: # special cases: Dict with voids + if key_type == types.void: + return types.dict_void_void else: - return self.__class(PYPY_DICT_OF_VOID % key_type, include_class) - return self.__class(PYPY_DICT % (key_type, value_type), include_class) + # XXX + return CliClassType(None, PYPY_DICT_OF_VOID % key_type) + return types.dict.specialize(key_type, value_type) elif isinstance(t, ootype.DictItemsIterator): key_type = self.lltype_to_cts(t._KEYTYPE) value_type = self.lltype_to_cts(t._VALUETYPE) - if key_type == 'void': - key_type = 'int32' # placeholder - if value_type == 'void': - value_type = 'int32' # placeholder - return self.__class(PYPY_DICT_ITEMS_ITERATOR % (key_type, value_type), include_class) + if key_type == types.void: + key_type = types.int32 # placeholder + if value_type == types.void: + value_type = types.int32 # placeholder + return types.dict_items_iterator.specialize(key_type, value_type) return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t) @@ -205,7 +287,7 @@ if is_method: args = args[1:] - arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args] + arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (ret_type, func_name, arg_list) @@ -217,7 +299,7 @@ args = [arg for arg in op.args[1:] if arg.concretetype is not ootype.Void] - arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args] + arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (ret_type, func_name, arg_list) @@ -238,7 +320,7 @@ class_name = self.db.class_name(TYPE) full_name = 'class %s::%s' % (class_name, self.escape_name(name)) returntype = self.lltype_to_cts(METH.RESULT) - arg_types = [self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void] + arg_types = [self.lltype_to_cts(ARG).typename() for ARG in METH.ARGS if ARG is not ootype.Void] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (returntype, full_name, arg_list), virtual @@ -256,16 +338,16 @@ name = name_or_desc if KEY is ootype.Void and VALUE is ootype.Void and name == 'll_get_items_iterator': # ugly, ugly special case - ret_type = 'class ' + PYPY_DICT_ITEMS_ITERATOR % ('int32', 'int32') + ret_type = types.dict_items_iterator.specialize(types.int32, types.int32) elif VALUE is ootype.Void and METH.RESULT is ootype.Dict.VALUETYPE_T: - ret_type = 'void' + ret_type = types.void else: ret_type = self.lltype_to_cts(METH.RESULT) ret_type = dict_of_void_ll_copy_hack(TYPE, ret_type) else: ret_type = self.lltype_to_cts(METH.RESULT) generic_types = getattr(TYPE, '_generic_types', {}) - arg_types = [self.lltype_to_cts(arg) for arg in METH.ARGS if + arg_types = [self.lltype_to_cts(arg).typename() for arg in METH.ARGS if arg is not ootype.Void and \ generic_types.get(arg, arg) is not ootype.Void] arg_list = ', '.join(arg_types) @@ -278,6 +360,6 @@ # XXX: ugly hack to make the ll_copy signature correct when # CustomDict is special-cased to DictOfVoid. if isinstance(TYPE, ootype.CustomDict) and TYPE._VALUETYPE is ootype.Void: - return ret_type.replace('Dict`2', 'DictOfVoid`2') + return ret_type.typename().replace('Dict`2', 'DictOfVoid`2') else: return ret_type Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Fri Aug 24 17:53:05 2007 @@ -113,8 +113,8 @@ def begin_catch(self, llexitcase): ll_meta_exc = llexitcase ll_exc = ll_meta_exc._inst.class_._INSTANCE - cts_exc = self.cts.lltype_to_cts(ll_exc, False) - self.ilasm.begin_catch(cts_exc) + cts_exc = self.cts.lltype_to_cts(ll_exc) + self.ilasm.begin_catch(cts_exc.classname()) def end_catch(self, target_label): self.ilasm.leave(target_label) Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Fri Aug 24 17:53:05 2007 @@ -322,8 +322,8 @@ self.ilasm.call(signature) def cast_to(self, lltype): - cts_type = self.cts.lltype_to_cts(lltype, False) - self.ilasm.opcode('castclass', cts_type) + cts_type = self.cts.lltype_to_cts(lltype) + self.ilasm.opcode('castclass', cts_type.classname()) def new(self, obj): self.ilasm.new(self.cts.ctor_name(obj)) Modified: pypy/dist/pypy/translator/cli/metavm.py ============================================================================== --- pypy/dist/pypy/translator/cli/metavm.py (original) +++ pypy/dist/pypy/translator/cli/metavm.py Fri Aug 24 17:53:05 2007 @@ -38,7 +38,9 @@ self._load_arg_or_null(generator, func_arg) cts = generator.cts ret_type = cts.lltype_to_cts(funcdesc._TYPE.RESULT) - arg_types = [cts.lltype_to_cts(arg) for arg in funcdesc._TYPE.ARGS if arg is not ootype.Void] + arg_types = [cts.lltype_to_cts(arg).typename() + for arg in funcdesc._TYPE.ARGS + if arg is not ootype.Void] arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, funcdesc._cls._name, funcdesc._name, arg_list) generator.call_signature(signature) @@ -70,8 +72,10 @@ METH = this.concretetype._METHODS[method_name] cts = generator.cts ret_type = cts.lltype_to_cts(METH.RESULT) - arg_types = [cts.lltype_to_cts(arg) for arg in METH.ARGS if arg is not ootype.Void] - arg_types.insert(0, cts.lltype_to_cts(ootype.String)) + arg_types = [cts.lltype_to_cts(arg).typename() + for arg in METH.ARGS + if arg is not ootype.Void] + arg_types.insert(0, cts.lltype_to_cts(ootype.String).typename()) arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list) generator.call_signature(signature) Modified: pypy/dist/pypy/translator/cli/record.py ============================================================================== --- pypy/dist/pypy/translator/cli/record.py (original) +++ pypy/dist/pypy/translator/cli/record.py Fri Aug 24 17:53:05 2007 @@ -30,7 +30,7 @@ for f_name, (FIELD_TYPE, f_default) in self.record._fields.iteritems(): f_name = self.cts.escape_name(f_name) cts_type = self.cts.lltype_to_cts(FIELD_TYPE) - if cts_type != 'void': + if cts_type != CTS.types.void: ilasm.field(f_name, cts_type) self._ctor() self._toString() @@ -74,13 +74,12 @@ def _equals(self): # field by field comparison - record_type = self.cts.lltype_to_cts(self.record, include_class=False) - class_record_type = self.cts.lltype_to_cts(self.record, include_class=True) + record_type = self.cts.lltype_to_cts(self.record) self.ilasm.begin_function('Equals', [('object', 'obj')], 'bool', False, 'virtual', 'instance', 'default') - self.ilasm.locals([(class_record_type, 'self')]) + self.ilasm.locals([(record_type, 'self')]) self.ilasm.opcode('ldarg.1') - self.ilasm.opcode('castclass', record_type) + self.ilasm.opcode('castclass', record_type.classname()) self.ilasm.opcode('stloc.0') equal = 'bool [pypylib]pypy.runtime.Utils::Equal<%s>(!!0, !!0)' @@ -91,9 +90,9 @@ f_type = self.cts.lltype_to_cts(FIELD_TYPE) f_name = self.cts.escape_name(f_name) self.ilasm.opcode('ldarg.0') - self.ilasm.get_field((f_type, record_type, f_name)) + self.ilasm.get_field((f_type, record_type.classname(), f_name)) self.ilasm.opcode('ldloc.0') - self.ilasm.get_field((f_type, record_type, f_name)) + self.ilasm.get_field((f_type, record_type.classname(), f_name)) self.ilasm.call(equal % f_type) self.ilasm.opcode('and') @@ -102,7 +101,7 @@ def _getHashCode(self): # return the hash of the first field. XXX: it can lead to a bad distribution - record_type = self.cts.lltype_to_cts(self.record, include_class=False) + record_type = self.cts.lltype_to_cts(self.record) self.ilasm.begin_function('GetHashCode', [], 'int32', False, 'virtual', 'instance', 'default') gethash = 'int32 [pypylib]pypy.runtime.Utils::GetHashCode<%s>(!!0)' if self.record._fields: @@ -113,7 +112,7 @@ f_name = self.cts.escape_name(f_name) f_type = self.cts.lltype_to_cts(FIELD_TYPE) self.ilasm.opcode('ldarg.0') - self.ilasm.get_field((f_type, record_type, f_name)) + self.ilasm.get_field((f_type, record_type.classname(), f_name)) self.ilasm.call(gethash % f_type) else: self.ilasm.opcode('ldc.i4.0') Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Fri Aug 24 17:53:05 2007 @@ -53,7 +53,7 @@ RETURN_TYPE = self.graph.getreturnvar().concretetype return_type = self.cts.lltype_to_cts(RETURN_TYPE) - if return_type != 'void': + if return_type != CTS.types.void: ilasm.locals([(return_type, 'res')]) if self.wrap_exceptions: @@ -70,7 +70,7 @@ # call the function and convert the result to a string containing a valid python expression ilasm.call(self.cts.graph_to_signature(self.graph)) - if return_type != 'void': + if return_type != CTS.types.void: ilasm.opcode('stloc', 'res') if self.wrap_exceptions: ilasm.leave('check_etrafo_exception') @@ -103,7 +103,7 @@ ilasm.opcode('br', 'print_result') ilasm.label('print_result') - if return_type != 'void': + if return_type != CTS.types.void: ilasm.opcode('ldloc', 'res') format_object(RETURN_TYPE, self.cts, ilasm) ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') @@ -115,13 +115,13 @@ def __convert_method(self, arg_type): _conv = { - 'int32': 'ToInt32', - 'unsigned int32': 'ToUInt32', - 'int64': 'ToInt64', - 'unsigned int64': 'ToUInt64', - 'bool': 'ToBoolean', - 'float64': 'ToDouble', - 'char': 'ToChar', + CTS.types.int32: 'ToInt32', + CTS.types.uint32: 'ToUInt32', + CTS.types.int64: 'ToInt64', + CTS.types.uint64: 'ToUInt64', + CTS.types.bool: 'ToBoolean', + CTS.types.float64: 'ToDouble', + CTS.types.char: 'ToChar', } try: From fijal at codespeak.net Fri Aug 24 17:58:13 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 17:58:13 +0200 (CEST) Subject: [pypy-svn] r45957 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070824155813.3902F822C@code0.codespeak.net> Author: fijal Date: Fri Aug 24 17:58:12 2007 New Revision: 45957 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py Log: Support for cyclic references in structures Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/mkrffi.py Fri Aug 24 17:58:12 2007 @@ -46,6 +46,15 @@ include_dirs = include_dirs and \ "include_dirs=%s, " % repr(tuple(include_dirs)) or '' self.extra_args = includes+libraries+include_dirs + self.seen = {} + self.forward_refs = 0 + self.forward_refs_to_consider = {} + + def next_forward_reference(self): + try: + return "forward_ref%d" % self.forward_refs + finally: + self.forward_refs += 1 def __str__(self): return str(self.source) @@ -71,9 +80,22 @@ src = py.code.Source( "%s = lltype.Struct('%s', %s hints={'external':'C'})"%( name, name, fields_repr)) - self.source = py.code.Source(self.source, src) + forward_ref = self.forward_refs_to_consider.get(tp, None) + l = [self.source, src] + if forward_ref: + l.append(py.code.Source("\n%s.become(%s)\n" % (forward_ref, name))) + self.source = py.code.Source(*l) return name + def proc_forward_ref(self, tp): + name = self.next_forward_reference() + src = py.code.Source(""" + %s = lltype.ForwardReference() + """ % (name,) ) + self.source = py.code.Source(self.source, src) + self.forward_refs_to_consider[tp] = name + return name + def proc_tp(self, tp): try: return SIMPLE_TYPE_MAPPING[tp] @@ -85,6 +107,10 @@ % self.proc_tp(tp._type_) return "lltype.Ptr(%s)" % self.proc_tp(tp._type_) elif issubclass(tp, ctypes.Structure): + if tp in self.seen: + # recursive struct + return self.proc_forward_ref(tp) + self.seen[tp] = True return self.proc_struct(tp) elif issubclass(tp, ctypes.Array): return "lltype.Ptr(lltype.Array(%s, hints={'nolength': True}))" % \ Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_mkrffi.py Fri Aug 24 17:58:12 2007 @@ -39,6 +39,21 @@ _src = "lltype.Ptr(lltype.Array(rffi.UINT, hints={'nolength': True}))" assert src == _src +def test_proc_cyclic_structure(): + rffi_source = RffiSource() + x_ptr = ctypes.POINTER('x') + class x(ctypes.Structure): + _fields_ = [('x', x_ptr)] + x_ptr._type_ = x + rffi_source.proc_tp(x) + _src = py.code.Source(""" + forward_ref0 = lltype.ForwardReference() + x = lltype.Struct('x', ('x', lltype.Ptr(forward_ref0)), hints={'external':'C'}) + + forward_ref0.become(x) + """) + assert rffi_source.source.strip() == _src.strip() + class TestMkrffi(TestBasic): def test_single_func(self): func = self.lib.int_to_void_p From fijal at codespeak.net Fri Aug 24 18:35:35 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 18:35:35 +0200 (CEST) Subject: [pypy-svn] r45958 - pypy/branch/pypy-more-rtti-inprogress/rlib/parsing/test Message-ID: <20070824163535.B34D681A7@code0.codespeak.net> Author: fijal Date: Fri Aug 24 18:35:34 2007 New Revision: 45958 Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/parsing/test/test_translate.py Log: Don't pop up pygame window at me! Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/parsing/test/test_translate.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/parsing/test/test_translate.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/parsing/test/test_translate.py Fri Aug 24 18:35:34 2007 @@ -5,7 +5,7 @@ from pypy.rlib.parsing.parsing import * from pypy.rlib.parsing import deterministic from pypy.rlib.parsing.pypackrat import BacktrackException, Status - +from pypy.conftest import option class TestTranslateLexer(object): def get_lexer(self, rexs, names, ignore=None): @@ -153,7 +153,8 @@ t.annotate([str]) t.rtype() t.backendopt() - t.view() + if option.view: + t.view() func = t.compile_c() res = func("5-5-5") assert res == '((5 - 5) - 5)' @@ -175,7 +176,8 @@ t.annotate([str]) t.rtype() t.backendopt() - t.view() + if option.view: + t.view() func = t.compile_c() res = func("12345") assert res == '12345' From fijal at codespeak.net Fri Aug 24 18:37:40 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 18:37:40 +0200 (CEST) Subject: [pypy-svn] r45959 - pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test Message-ID: <20070824163740.A850581B3@code0.codespeak.net> Author: fijal Date: Fri Aug 24 18:37:40 2007 New Revision: 45959 Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test/test_ll_cairo.py Log: Improve message a bit Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test/test_ll_cairo.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test/test_ll_cairo.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test/test_ll_cairo.py Fri Aug 24 18:37:40 2007 @@ -13,7 +13,7 @@ from pypy.rlib.rcairo._cairo import CAIRO_FORMAT_ARGB32 from pypy.rlib.rcairo.ll_cairo import * except distutils.errors.CompileError, e: - py.test.skip(str(e)) + py.test.skip("Probably cairo not found: " + str(e)) def demo(filename): width = 800 From fijal at codespeak.net Fri Aug 24 18:42:05 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 18:42:05 +0200 (CEST) Subject: [pypy-svn] r45960 - in pypy/branch/pypy-more-rtti-inprogress: annotation rpython rpython/lltypesystem rpython/test translator/c/src Message-ID: <20070824164205.B740481B3@code0.codespeak.net> Author: fijal Date: Fri Aug 24 18:42:05 2007 New Revision: 45960 Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py pypy/branch/pypy-more-rtti-inprogress/translator/c/src/float.h Log: Revert float % float, as arigo suggested Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py Fri Aug 24 18:42:05 2007 @@ -419,7 +419,7 @@ def union((flt1, flt2)): return SomeFloat() - mod = add = sub = mul = div = truediv = union + add = sub = mul = div = truediv = union def pow((flt1, flt2), obj3): return SomeFloat() Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py Fri Aug 24 18:42:05 2007 @@ -234,7 +234,6 @@ 'float_gt': LLOp(canfold=True), 'float_ge': LLOp(canfold=True), 'float_pow': LLOp(canfold=True), - 'float_mod': LLOp(canfold=True), 'llong_is_true': LLOp(canfold=True), 'llong_neg': LLOp(canfold=True), Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py Fri Aug 24 18:42:05 2007 @@ -47,11 +47,6 @@ rtype_inplace_truediv = rtype_truediv - def rtype_mod(_, hop): - return _rtype_template(hop, 'mod') - - rtype_inplace_mod = rtype_mod - # turn 'div' on floats into 'truediv' rtype_div = rtype_truediv rtype_inplace_div = rtype_inplace_truediv Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py Fri Aug 24 18:42:05 2007 @@ -108,12 +108,6 @@ res = self.interpret(fn, [2.0, 3.0]) assert res == 8.0 - def test_float_mod(self): - def fn(x, y): - return x % y - res = self.interpret(fn, [2.33, 1.0]) - assert res - 0.33 < 0.00000000001 - class TestLLtype(BaseTestRfloat, LLRtypeMixin): def test_hash(self): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/float.h ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/float.h (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/float.h Fri Aug 24 18:42:05 2007 @@ -28,7 +28,6 @@ #define OP_FLOAT_MUL(x,y,r) r = x * y #define OP_FLOAT_TRUEDIV(x,y,r) r = x / y #define OP_FLOAT_POW(x,y,r) r = pow(x, y) -#define OP_FLOAT_MOD(x,y,r) r = fmod(x, y) /*** conversions ***/ From simonb at codespeak.net Fri Aug 24 18:42:53 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Fri, 24 Aug 2007 18:42:53 +0200 (CEST) Subject: [pypy-svn] r45961 - pypy/dist/pypy/rpython/tool Message-ID: <20070824164253.1ABBB81B3@code0.codespeak.net> Author: simonb Date: Fri Aug 24 18:42:52 2007 New Revision: 45961 Modified: pypy/dist/pypy/rpython/tool/genrffi.py Log: fix c_name, use softwrapping to do some simple type coercion Modified: pypy/dist/pypy/rpython/tool/genrffi.py ============================================================================== --- pypy/dist/pypy/rpython/tool/genrffi.py (original) +++ pypy/dist/pypy/rpython/tool/genrffi.py Fri Aug 24 18:42:52 2007 @@ -3,6 +3,7 @@ import ctypes from pypy.rpython.lltypesystem import rffi from pypy.rpython.lltypesystem import lltype +from pypy.rlib.unroll import unrolling_iterable import py @@ -10,7 +11,7 @@ #rffi.UCHAR = lltype.Char # XXX # XXX any automatic stuff here? -SIMPLE_TYPE_MAPPING = { +_TYPE_MAPPING = { ctypes.c_ubyte : rffi.UCHAR, ctypes.c_byte : rffi.CHAR, ctypes.c_char : rffi.CHAR, @@ -35,6 +36,22 @@ ctypes.c_double : rffi.lltype.Float, # XXX make a type in rffi } + +def softwrapper(funcptr, arg_tps): + # Here we wrap with a function that does some simple type coercion. + unrolling_arg_tps = unrolling_iterable(enumerate(arg_tps)) + def softfunc(*args): + real_args = () + for i, tp in unrolling_arg_tps: + if tp == rffi.lltype.Float: + real_args = real_args + (float(args[i]),) + else: + real_args = real_args + (args[i],) + result = funcptr(*real_args) + return result + return softfunc + + class RffiBuilder(object): def __init__(self, ns=None, includes=[], libraries=[], include_dirs=[]): if ns is None: @@ -58,13 +75,13 @@ raise NotImplementedError("field length") name_, field_tp = field fields.append((name_, self.proc_tp(field_tp))) - struct = lltype.Struct(name, *fields, **{'hints':{'external':'C'}}) + struct = lltype.Struct(name, *fields, **{'hints':{'external':'C', 'c_name':name}}) self.ns[name] = struct return struct def proc_tp(self, tp): try: - return SIMPLE_TYPE_MAPPING[tp] + return _TYPE_MAPPING[tp] except KeyError: pass if issubclass(tp, ctypes._Pointer): @@ -77,17 +94,20 @@ ll_tp = self.proc_struct(tp) else: raise NotImplementedError("Not implemented mapping for %s" % tp) - return ll_tp # store in SIMPLE_TYPE_MAPPING ? + _TYPE_MAPPING[tp] = ll_tp + return ll_tp def proc_func(self, func): name = func.__name__ + arg_tps = [self.proc_tp(arg) for arg in func.argtypes] ll_item = rffi.llexternal( - name, [self.proc_tp(arg) for arg in func.argtypes], + name, arg_tps, self.proc_tp(func.restype), includes=self.includes, libraries=self.libraries, include_dirs=self.include_dirs) - self.ns[name] = ll_item - return ll_item + soft = softwrapper(ll_item, arg_tps) + self.ns[name] = soft + return soft def proc_namespace(self, ns): exempt = set(id(value) for value in ctypes.__dict__.values()) From fijal at codespeak.net Fri Aug 24 18:51:51 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 18:51:51 +0200 (CEST) Subject: [pypy-svn] r45962 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070824165151.85FE381B3@code0.codespeak.net> Author: fijal Date: Fri Aug 24 18:51:50 2007 New Revision: 45962 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py Log: Comment regarding implementing float_mod Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/lloperation.py Fri Aug 24 18:51:50 2007 @@ -234,6 +234,7 @@ 'float_gt': LLOp(canfold=True), 'float_ge': LLOp(canfold=True), 'float_pow': LLOp(canfold=True), + # don't implement float_mod, use math.fmod instead 'llong_is_true': LLOp(canfold=True), 'llong_neg': LLOp(canfold=True), From simonb at codespeak.net Fri Aug 24 18:57:31 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Fri, 24 Aug 2007 18:57:31 +0200 (CEST) Subject: [pypy-svn] r45963 - pypy/dist/pypy/rlib/rcairo Message-ID: <20070824165731.4E476821F@code0.codespeak.net> Author: simonb Date: Fri Aug 24 18:57:31 2007 New Revision: 45963 Modified: pypy/dist/pypy/rlib/rcairo/ll_cairo.py Log: add include dir Modified: pypy/dist/pypy/rlib/rcairo/ll_cairo.py ============================================================================== --- pypy/dist/pypy/rlib/rcairo/ll_cairo.py (original) +++ pypy/dist/pypy/rlib/rcairo/ll_cairo.py Fri Aug 24 18:57:31 2007 @@ -8,7 +8,7 @@ builder = genrffi.RffiBuilder( includes=['cairo.h'], libraries=['cairo'], - include_dirs=['/usr/local/include/cairo']) + include_dirs=['/usr/local/include/cairo', '/usr/include/cairo']) ns = _cairo.__dict__ builder.proc_namespace(ns) From arigo at codespeak.net Fri Aug 24 18:59:55 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Aug 2007 18:59:55 +0200 (CEST) Subject: [pypy-svn] r45964 - in pypy/branch/pypy-more-rtti-inprogress: annotation rpython/test Message-ID: <20070824165955.74A7C80BB@code0.codespeak.net> Author: arigo Date: Fri Aug 24 18:59:54 2007 New Revision: 45964 Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py Log: Test and fix: float division doesn't raise ZeroDivisionError in RPython. Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py Fri Aug 24 18:59:54 2007 @@ -419,11 +419,21 @@ def union((flt1, flt2)): return SomeFloat() - add = sub = mul = div = truediv = union + add = sub = mul = union + + def div((flt1, flt2)): + return SomeFloat() + div.can_only_throw = [] + truediv = div def pow((flt1, flt2), obj3): return SomeFloat() - pow.can_only_throw = [ZeroDivisionError, ValueError, OverflowError] + pow.can_only_throw = [ZeroDivisionError, ValueError, OverflowError] + + # repeat these in order to copy the 'can_only_throw' attribute + inplace_div = div + inplace_truediv = truediv + inplace_pow = pow class __extend__(pairtype(SomeList, SomeList)): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rfloat.py Fri Aug 24 18:59:54 2007 @@ -108,6 +108,16 @@ res = self.interpret(fn, [2.0, 3.0]) assert res == 8.0 + def test_exceptions(self): + def fn(x, y, z): + try: + # '/', when float-based, cannot raise in RPython! + # the try:finally: only tests an annotation bug. + x /= (y / z) + finally: + return x + self.interpret(fn, [1.0, 2.0, 3.0]) + class TestLLtype(BaseTestRfloat, LLRtypeMixin): def test_hash(self): From fijal at codespeak.net Fri Aug 24 19:01:25 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 19:01:25 +0200 (CEST) Subject: [pypy-svn] r45965 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070824170125.778B3821D@code0.codespeak.net> Author: fijal Date: Fri Aug 24 19:01:25 2007 New Revision: 45965 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: Simple helpers Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Fri Aug 24 19:01:25 2007 @@ -101,6 +101,12 @@ def CStructPtr(*args, **kwds): return lltype.Ptr(CStruct(*args, **kwds)) +def CArray(name, tp): + return lltype.Array(tp, hints={'nolength':True}) + +def CArrayPtr(name, tp): + return lltype.Ptr(CArray(tp)) + def COpaque(name, hints=None, **kwds): if hints is None: hints = {} From fijal at codespeak.net Fri Aug 24 19:02:41 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 24 Aug 2007 19:02:41 +0200 (CEST) Subject: [pypy-svn] r45966 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070824170241.9DC98821D@code0.codespeak.net> Author: fijal Date: Fri Aug 24 19:02:41 2007 New Revision: 45966 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: Argh. This was meant to be that way Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Fri Aug 24 19:02:41 2007 @@ -102,10 +102,7 @@ return lltype.Ptr(CStruct(*args, **kwds)) def CArray(name, tp): - return lltype.Array(tp, hints={'nolength':True}) - -def CArrayPtr(name, tp): - return lltype.Ptr(CArray(tp)) + return lltype.FixedSizeArray(tp) def COpaque(name, hints=None, **kwds): if hints is None: From arigo at codespeak.net Fri Aug 24 19:06:27 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Aug 2007 19:06:27 +0200 (CEST) Subject: [pypy-svn] r45967 - in pypy/branch/pypy-more-rtti-inprogress/rpython: . test Message-ID: <20070824170627.7ED39821D@code0.codespeak.net> Author: arigo Date: Fri Aug 24 19:06:27 2007 New Revision: 45967 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rbool.py pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py pypy/branch/pypy-more-rtti-inprogress/rpython/rint.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rbuiltin.py Log: Test and fixes for missing exception_cannot_occur() in calls to int(). Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rbool.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/rbool.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/rbool.py Fri Aug 24 19:06:27 2007 @@ -29,6 +29,7 @@ def rtype_int(_, hop): vlist = hop.inputargs(Signed) + hop.exception_cannot_occur() return vlist[0] def rtype_float(_, hop): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/rfloat.py Fri Aug 24 19:06:27 2007 @@ -138,6 +138,9 @@ def rtype_int(_, hop): vlist = hop.inputargs(Float) + # int(x) never raises in RPython, you need to use + # rarithmetic.ovfcheck_float_to_int() if you want this + hop.exception_cannot_occur() return hop.genop('cast_float_to_int', vlist, resulttype=Signed) rtype_float = rtype_pos Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rint.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/rint.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/rint.py Fri Aug 24 19:06:27 2007 @@ -369,6 +369,7 @@ if self.lowleveltype in (Unsigned, UnsignedLongLong): raise TyperError("use intmask() instead of int(r_uint(...))") vlist = hop.inputargs(Signed) + hop.exception_cannot_occur() return vlist[0] def rtype_float(_, hop): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rbuiltin.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rbuiltin.py Fri Aug 24 19:06:27 2007 @@ -364,6 +364,16 @@ res = self.ll_to_string(self.interpret(fn, ['a', 'b'])) assert res == os.path.join('a', 'b') + def test_exceptions(self): + def fn(a): + try: + a += int(str(int(a))) + a += int(int(a > 5)) + finally: + return a + res = self.interpret(fn, [3.25]) + assert res == 7.25 + class TestLLtype(BaseTestRbuiltin, LLRtypeMixin): def test_isinstance_obj(self): From simonb at codespeak.net Fri Aug 24 19:28:16 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Fri, 24 Aug 2007 19:28:16 +0200 (CEST) Subject: [pypy-svn] r45968 - pypy/branch/pypy-more-rtti-inprogress/rpython/tool Message-ID: <20070824172816.993C28210@code0.codespeak.net> Author: simonb Date: Fri Aug 24 19:28:14 2007 New Revision: 45968 Added: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/genrffi.py - copied unchanged from r45965, pypy/dist/pypy/rpython/tool/genrffi.py Log: copy from trunk From fijal at codespeak.net Sat Aug 25 10:46:06 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 25 Aug 2007 10:46:06 +0200 (CEST) Subject: [pypy-svn] r45971 - pypy/branch/pypy-more-rtti-inprogress/annotation Message-ID: <20070825084606.88F5E81CF@code0.codespeak.net> Author: fijal Date: Sat Aug 25 10:46:04 2007 New Revision: 45971 Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py Log: Bad armin, didn't run the tests Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py Sat Aug 25 10:46:04 2007 @@ -287,6 +287,12 @@ pow.can_only_throw = [ZeroDivisionError] pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError]) + def inplace_pow((int1, int2)): + knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype) + return SomeInteger(nonneg = int1.nonneg, + knowntype=knowntype) + inplace_pow.can_only_throw = [ZeroDivisionError] + def _compare_helper((int1, int2), opname, operation): r = SomeBool() if int1.is_immutable_constant() and int2.is_immutable_constant(): @@ -413,7 +419,6 @@ getbookkeeper().count('strformat', str, args) return SomeString() - class __extend__(pairtype(SomeFloat, SomeFloat)): def union((flt1, flt2)): @@ -433,8 +438,10 @@ # repeat these in order to copy the 'can_only_throw' attribute inplace_div = div inplace_truediv = truediv - inplace_pow = pow + def inplace_pow((flt1, flt2)): + return SomeFloat() + inplace_pow.can_only_throw = [ZeroDivisionError, ValueError, OverflowError] class __extend__(pairtype(SomeList, SomeList)): From fijal at codespeak.net Sat Aug 25 10:49:23 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 25 Aug 2007 10:49:23 +0200 (CEST) Subject: [pypy-svn] r45972 - in pypy/branch/pypy-more-rtti-inprogress/annotation: . test Message-ID: <20070825084923.11A8181CF@code0.codespeak.net> Author: fijal Date: Sat Aug 25 10:49:23 2007 New Revision: 45972 Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py pypy/branch/pypy-more-rtti-inprogress/annotation/test/test_annrpython.py Log: Inplace div of two ints should not return float, thanks exarkun for spotting Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/annotation/binaryop.py Sat Aug 25 10:49:23 2007 @@ -259,6 +259,9 @@ truediv.can_only_throw = [ZeroDivisionError] truediv_ovf = _clone(truediv, [ZeroDivisionError, OverflowError]) + inplace_div = div + inplace_truediv = truediv + def sub((int1, int2)): knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype) return SomeInteger(knowntype=knowntype) Modified: pypy/branch/pypy-more-rtti-inprogress/annotation/test/test_annrpython.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/annotation/test/test_annrpython.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/annotation/test/test_annrpython.py Sat Aug 25 10:49:23 2007 @@ -1316,6 +1316,14 @@ # result should be an integer assert s.knowntype == int + def test_inplace_div(self): + def f(n): + n /= 2 + return n / 2 + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert s.knowntype == int + def test_prime(self): a = self.RPythonAnnotator() s = a.build_types(snippet.prime, [int]) From pedronis at codespeak.net Sat Aug 25 12:45:19 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 25 Aug 2007 12:45:19 +0200 (CEST) Subject: [pypy-svn] r45973 - in pypy/branch/pypy-more-rtti-inprogress: module/_curses rpython rpython/module rpython/ootypesystem/test rpython/test translator/js/modules Message-ID: <20070825104519.7A59181BE@code0.codespeak.net> Author: pedronis Date: Sat Aug 25 12:45:17 2007 New Revision: 45973 Modified: pypy/branch/pypy-more-rtti-inprogress/module/_curses/fficurses.py pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_termios.py pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/test/test_bltann.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfunc.py pypy/branch/pypy-more-rtti-inprogress/translator/js/modules/dom.py pypy/branch/pypy-more-rtti-inprogress/translator/js/modules/mochikit.py Log: - given how much is used: make _register_external -> register_external - fix test_extfunc.py, by making ExtFuncEntry more backward compatible Modified: pypy/branch/pypy-more-rtti-inprogress/module/_curses/fficurses.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/_curses/fficurses.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/_curses/fficurses.py Sat Aug 25 12:45:17 2007 @@ -5,7 +5,7 @@ import sys from pypy.rpython.lltypesystem import rffi from pypy.rpython.lltypesystem import lltype -from pypy.rpython.extfunc import _register_external as register_external +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 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Sat Aug 25 12:45:17 2007 @@ -85,6 +85,27 @@ class ExtFuncEntry(ExtRegistryEntry): safe_not_sandboxed = False + # common case: args is a list of annotation or types + def normalize_args(self, *args_s): + args = self.signature_args + signature_args = [annotation(arg, None) for arg in args] + assert len(args_s) == len(signature_args),\ + "Argument number mismatch" + for i, expected in enumerate(signature_args): + arg = unionof(args_s[i], expected) + if not expected.contains(arg): + name = getattr(self, 'name', None) + if not name: + try: + name = self.instance.__name__ + except AttributeError: + name = '?' + raise Exception("In call to external function %r:\n" + "arg %d must be %s,\n" + " got %s" % ( + name, i+1, expected, args_s[i])) + return signature_args + def compute_result_annotation(self, *args_s): if hasattr(self, 'ann_hook'): self.ann_hook() @@ -127,7 +148,7 @@ hop.exception_is_here() return hop.genop('direct_call', vlist, r_result) -def _register_external(function, args, result=None, export_name=None, +def register_external(function, args, result=None, export_name=None, llimpl=None, ooimpl=None, llfakeimpl=None, oofakeimpl=None, annotation_hook=None, @@ -150,31 +171,11 @@ if args is None: def normalize_args(self, *args_s): return args_s # accept any argument unmodified - elif callable(args): # custom annotation normalizer (see e.g. os.utime()) normalize_args = staticmethod(args) - - else: - # common case: args is a list of annotation or types - def normalize_args(self, *args_s): - signature_args = [annotation(arg, None) for arg in args] - assert len(args_s) == len(signature_args),\ - "Argument number mismatch" - for i, expected in enumerate(signature_args): - arg = unionof(args_s[i], expected) - if not expected.contains(arg): - name = getattr(self, 'name', None) - if not name: - try: - name = self.instance.__name__ - except AttributeError: - name = '?' - raise Exception("In call to external function %r:\n" - "arg %d must be %s,\n" - " got %s" % ( - name, i+1, expected, args_s[i])) - return signature_args + else: # use common case behavior + signature_args = args signature_result = annotation(result, None) name=export_name @@ -194,7 +195,7 @@ else: FunEntry.__name__ = function.func_name -BaseLazyRegistering.register = staticmethod(_register_external) +BaseLazyRegistering.register = staticmethod(register_external) def is_external(func): if hasattr(func, 'value'): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py Sat Aug 25 12:45:17 2007 @@ -1,7 +1,7 @@ # this registry use the new interface for external functions # all the above declarations in extfunctable should be moved here at some point. -from extfunc import _register_external +from extfunc import register_external # ___________________________ # math functions @@ -25,7 +25,8 @@ 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' ] for name in simple_math_functions: - _register_external(getattr(math, name), [float], float, "ll_math.ll_math_%s" % name, + register_external(getattr(math, name), [float], float, + "ll_math.ll_math_%s" % name, sandboxsafe=True) complex_math_functions = [ @@ -42,9 +43,9 @@ func = getattr(math, name) llimpl = getattr(ll_math, 'll_math_%s' % name, None) oofake = getattr(oo_math, 'll_math_%s' % name, None) - _register_external(func, args, res, 'll_math.ll_math_%s' % name, - llimpl=llimpl, oofakeimpl=oofake, - sandboxsafe=True) + register_external(func, args, res, 'll_math.ll_math_%s' % name, + llimpl=llimpl, oofakeimpl=oofake, + sandboxsafe=True) # ___________________________ @@ -71,5 +72,5 @@ for name, args, res in path_functions: func = getattr(os.path, name) llimpl = func_with_new_name(func, name) - _register_external(func, args, res, 'll_os_path.ll_%s' % name, - llimpl=llimpl, sandboxsafe=True) + register_external(func, args, res, 'll_os_path.ll_%s' % name, + llimpl=llimpl, sandboxsafe=True) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py Sat Aug 25 12:45:17 2007 @@ -1,7 +1,7 @@ import os from pypy.annotation import model as annmodel from pypy.rpython.controllerentry import Controller -from pypy.rpython.extfunc import _register_external +from pypy.rpython.extfunc import register_external from pypy.rpython.lltypesystem import rffi, lltype # ____________________________________________________________ @@ -63,9 +63,9 @@ rffi.free_charp(l_name) return result -_register_external(r_getenv, [str], annmodel.SomeString(can_be_None=True), - export_name='ll_os.ll_os_getenv', - llimpl=getenv_lltypeimpl) +register_external(r_getenv, [str], annmodel.SomeString(can_be_None=True), + export_name='ll_os.ll_os_getenv', + llimpl=getenv_lltypeimpl) # ____________________________________________________________ @@ -92,9 +92,9 @@ if l_oldstring: rffi.free_charp(l_oldstring) -_register_external(r_putenv, [str, str], annmodel.s_None, - export_name='ll_os.ll_os_putenv', - llimpl=putenv_lltypeimpl) +register_external(r_putenv, [str, str], annmodel.s_None, + export_name='ll_os.ll_os_putenv', + llimpl=putenv_lltypeimpl) # ____________________________________________________________ @@ -120,9 +120,9 @@ del envkeepalive.byname[name] rffi.free_charp(l_oldstring) - _register_external(r_unsetenv, [str], annmodel.s_None, - export_name='ll_os.ll_os_unsetenv', - llimpl=unsetenv_lltypeimpl) + register_external(r_unsetenv, [str], annmodel.s_None, + export_name='ll_os.ll_os_unsetenv', + llimpl=unsetenv_lltypeimpl) # ____________________________________________________________ # Access to the 'environ' external variable @@ -154,9 +154,9 @@ i += 1 return result -_register_external(r_envkeys, [], [str], # returns a list of strings - export_name='ll_os.ll_os_envkeys', - llimpl=envkeys_lltypeimpl) +register_external(r_envkeys, [], [str], # returns a list of strings + export_name='ll_os.ll_os_envkeys', + llimpl=envkeys_lltypeimpl) # ____________________________________________________________ @@ -175,6 +175,6 @@ i += 1 return result -_register_external(r_envitems, [], [(str, str)], - export_name='ll_os.ll_os_envitems', - llimpl=envitems_lltypeimpl) +register_external(r_envitems, [], [(str, str)], + export_name='ll_os.ll_os_envitems', + llimpl=envitems_lltypeimpl) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py Sat Aug 25 12:45:17 2007 @@ -6,7 +6,7 @@ from pypy.annotation import model as annmodel from pypy.tool.sourcetools import func_with_new_name from pypy.rpython.controllerentry import Controller, SomeControlledInstance -from pypy.rpython.extfunc import _register_external +from pypy.rpython.extfunc import register_external from pypy.rpython.lltypesystem import rffi, lltype if sys.platform.startswith('win'): @@ -186,7 +186,7 @@ s_arg = str else: s_arg = int - _register_external(getattr(os, name), [s_arg], s_StatResult, - "ll_os.ll_os_%s" % (name,), - llimpl=func_with_new_name(os_mystat_lltypeimpl, - 'os_%s_lltypeimpl' % (name,))) + register_external(getattr(os, name), [s_arg], s_StatResult, + "ll_os.ll_os_%s" % (name,), + llimpl=func_with_new_name(os_mystat_lltypeimpl, + 'os_%s_lltypeimpl' % (name,))) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_termios.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_termios.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_termios.py Sat Aug 25 12:45:17 2007 @@ -8,7 +8,7 @@ import termios from pypy.rpython.lltypesystem import rffi from pypy.rpython.lltypesystem import lltype -from pypy.rpython.extfunc import lazy_register, _register_external +from pypy.rpython.extfunc import lazy_register, register_external from pypy.rlib.rarithmetic import intmask from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel @@ -68,7 +68,7 @@ finally: lltype.free(c_struct, flavor='raw') -_register_external(rtermios.tcgetattr, [int], (int, int, int, int, int, int, [str]), +register_external(rtermios.tcgetattr, [int], (int, int, int, int, int, int, [str]), llimpl=tcgetattr_llimpl, export_name='termios.tcgetattr') def tcsetattr_llimpl(fd, when, attributes): @@ -91,7 +91,7 @@ lltype.free(c_struct, flavor='raw') r_uint = rffi.r_uint -_register_external(rtermios.tcsetattr, [int, int, (r_uint, r_uint, r_uint, +register_external(rtermios.tcsetattr, [int, int, (r_uint, r_uint, r_uint, r_uint, r_uint, r_uint, [str])], llimpl=tcsetattr_llimpl, export_name='termios.tcsetattr') @@ -101,7 +101,7 @@ error = c_tcsendbreak(fd, duration) if error == -1: raise termios.error(error, 'tcsendbreak failed') -_register_external(termios.tcsendbreak, [int, int], +register_external(termios.tcsendbreak, [int, int], llimpl=tcsendbreak_llimpl, export_name='termios.tcsendbreak') @@ -109,19 +109,19 @@ error = c_tcdrain(fd) if error == -1: raise termios.error(error, 'tcdrain failed') -_register_external(termios.tcdrain, [int], llimpl=tcdrain_llimpl, +register_external(termios.tcdrain, [int], llimpl=tcdrain_llimpl, export_name='termios.tcdrain') def tcflush_llimpl(fd, queue_selector): error = c_tcflush(fd, queue_selector) if error == -1: raise termios.error(error, 'tcflush failed') -_register_external(termios.tcflush, [int, int], llimpl=tcflush_llimpl, +register_external(termios.tcflush, [int, int], llimpl=tcflush_llimpl, export_name='termios.tcflush') def tcflow_llimpl(fd, action): error = c_tcflow(fd, action) if error == -1: raise termios.error(error, 'tcflow failed') -_register_external(termios.tcflow, [int, int], llimpl=tcflow_llimpl, +register_external(termios.tcflow, [int, int], llimpl=tcflow_llimpl, export_name='termios.tcflow') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/test/test_bltann.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/test/test_bltann.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/test/test_bltann.py Sat Aug 25 12:45:17 2007 @@ -168,7 +168,7 @@ assert res == 8.3 def test_mixed_classes(): - from pypy.rpython.extfunc import _register_external + from pypy.rpython.extfunc import register_external class One(BasicExternal): pass @@ -177,7 +177,7 @@ def g(one): return 3 - _register_external(g, args=[One], result=int) + register_external(g, args=[One], result=int) def f(x): if x: Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfunc.py Sat Aug 25 12:45:17 2007 @@ -1,5 +1,5 @@ -from pypy.rpython.extfunc import ExtFuncEntry, _register_external,\ +from pypy.rpython.extfunc import ExtFuncEntry, register_external,\ is_external, lazy_register from pypy.annotation import model as annmodel from pypy.annotation.annrpython import RPythonAnnotator @@ -79,7 +79,7 @@ def dd(): pass -_register_external(dd, [int], int) +register_external(dd, [int], int) def test_register_external_signature(): def f(): @@ -98,7 +98,7 @@ an argument so that register_external's behavior for tuple-taking functions can be verified. """ -_register_external(function_with_tuple_arg, [(int,)], int) +register_external(function_with_tuple_arg, [(int,)], int) def test_register_external_tuple_args(): """ @@ -118,11 +118,11 @@ def function_with_list(): pass -_register_external(function_with_list, [[int]], int) +register_external(function_with_list, [[int]], int) def function_returning_list(): pass -_register_external(function_returning_list, [], [int]) +register_external(function_returning_list, [], [int]) def test_register_external_return_goes_back(): """ @@ -141,7 +141,7 @@ def function_withspecialcase(arg): return repr(arg) -_register_external(function_withspecialcase, args=None, result=str) +register_external(function_withspecialcase, args=None, result=str) def test_register_external_specialcase(): def f(): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/js/modules/dom.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/js/modules/dom.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/js/modules/dom.py Sat Aug 25 12:45:17 2007 @@ -22,7 +22,7 @@ from pypy.rlib.nonconst import NonConstant from pypy.rpython.extfunc import genericcallable -from pypy.rpython.extfunc import _register_external as register_external +from pypy.rpython.extfunc import register_external from xml.dom import minidom from pypy.annotation.signature import annotation Modified: pypy/branch/pypy-more-rtti-inprogress/translator/js/modules/mochikit.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/js/modules/mochikit.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/js/modules/mochikit.py Sat Aug 25 12:45:17 2007 @@ -3,7 +3,7 @@ """ from pypy.rpython.extfunc import genericcallable -from pypy.rpython.extfunc import _register_external as register_external +from pypy.rpython.extfunc import register_external from pypy.rpython.ootypesystem.bltregistry import BasicExternal, MethodDesc from pypy.translator.js.modules import dom From fijal at codespeak.net Sat Aug 25 12:49:31 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 25 Aug 2007 12:49:31 +0200 (CEST) Subject: [pypy-svn] r45974 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070825104931.1CA5881BE@code0.codespeak.net> Author: fijal Date: Sat Aug 25 12:49:29 2007 New Revision: 45974 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Log: Fix slightly ll_time. the problem now is that HAVE_XXX is always false, next in my todo list. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Sat Aug 25 12:49:29 2007 @@ -3,6 +3,7 @@ """ import time, sys, math +from errno import EINTR from pypy.rpython.lltypesystem import rffi from pypy.rpython.tool import rffi_platform as platform from pypy.rpython.lltypesystem import lltype @@ -10,12 +11,13 @@ class CConfig: if sys.platform.startswith('win'): - includes = ['sys/time.h', 'windows.h'] + includes = ['time.h', 'windows.h'] else: - includes = ['time.h', 'errno.h', 'sys/select.h', 'sys/types.h', - 'unistd.h', 'sys/timeb.h'] + includes = ['sys/time.h', 'time.h', 'errno.h', 'sys/select.h', + 'sys/types.h', 'unistd.h', 'sys/timeb.h'] # XXX argh, argh, argh, should be automatic _header_ = "\n".join(["#include <%s>" % name for name in includes]) + CLOCK_T = platform.SimpleType('clock_t', rffi.INT) TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.INT), ('tv_usec', rffi.INT)]) @@ -126,15 +128,15 @@ # someone forgotten to call hop.exception_is_here void = lltype.nullptr(rffi.VOIDP.TO) t = lltype.malloc(self.TIMEVAL, flavor='raw') - #try: - frac = secs % 1.0 - t.c_tv_sec = int(secs) - t.c_tv_usec = int(frac*1000000.0) - if c_select(0, void, void, void, t) != 0: - # XXX EINTR + try: + frac = math.fmod(secs, 1.0) + t.c_tv_sec = int(secs) + t.c_tv_usec = int(frac*1000000.0) + if c_select(0, void, void, void, t) != 0: + errno = rffi.get_errno() + if errno != EINTR: + raise OSError(rffi.get_errno(), "Select failed") + finally: lltype.free(t, flavor='raw') - raise IOError("Select failed") - #finally: - lltype.free(t, flavor='raw') self.register(time.sleep, [float], None, llimpl=time_sleep_llimpl, export_name='ll_time.ll_time_sleep') From arigo at codespeak.net Sat Aug 25 12:51:03 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Aug 2007 12:51:03 +0200 (CEST) Subject: [pypy-svn] r45975 - pypy/branch/pypy-more-rtti-inprogress/rpython/tool Message-ID: <20070825105103.4F12F81C2@code0.codespeak.net> Author: arigo Date: Sat Aug 25 12:51:02 2007 New Revision: 45975 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py Log: Don't put translator/c/src in the include_dirs. The files in there include each other by saying '#include "src/foo.h"'. In other words the directory that is meant to be in the include_dirs is 'translator/c'. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py Sat Aug 25 12:51:02 2007 @@ -36,7 +36,7 @@ # always include pypy include dir pypypath = py.path.local(pypydir) include_dirs = include_dirs[:] - include_dirs.append(str(pypypath.join('translator', 'c', 'src'))) + include_dirs.append(str(pypypath.join('translator', 'c'))) c_exec = build_executable([str(c_file)], include_dirs=include_dirs, compiler_exe=compiler_exe) From pedronis at codespeak.net Sat Aug 25 12:51:46 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 25 Aug 2007 12:51:46 +0200 (CEST) Subject: [pypy-svn] r45976 - in pypy/branch/pypy-more-rtti-inprogress: rpython/module translator/c Message-ID: <20070825105146.9529981C2@code0.codespeak.net> Author: pedronis Date: Sat Aug 25 12:51:46 2007 New Revision: 45976 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py Log: shorter names: lltypeimpl -> llimpl Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Sat Aug 25 12:51:46 2007 @@ -27,14 +27,14 @@ # a simple, yet usefull factory def register_os_function_returning_int(self, fun, name, **kwds): c_func = rffi.llexternal(name, [], rffi.INT, **kwds) - def c_func_lltypeimpl(): + def c_func_llimpl(): res = c_func() if res == -1: raise OSError(rffi.get_errno(), "%s failed" % name) return res - c_func_lltypeimpl.func_name = name + '_llimpl' + c_func_llimpl.func_name = name + '_llimpl' - self.register(fun, [], int, llimpl=c_func_lltypeimpl, + self.register(fun, [], int, llimpl=c_func_llimpl, export_name='ll_os.ll_os_' + name) if hasattr(os, 'execv'): @@ -43,7 +43,7 @@ os_execv = rffi.llexternal('execv', [rffi.CCHARP, rffi.CCHARPP], rffi.INT) - def execv_lltypeimpl(path, args): + def execv_llimpl(path, args): l_path = rffi.str2charp(path) l_args = rffi.liststr2charpp(args) os_execv(l_path, l_args) @@ -52,7 +52,7 @@ raise OSError(rffi.get_errno(), "execv failed") self.register(os.execv, [str, [str]], s_ImpossibleValue, llimpl= - execv_lltypeimpl, export_name="ll_os.ll_os_execv") + execv_llimpl, export_name="ll_os.ll_os_execv") if hasattr(posix, 'spawnv'): @registering(os.spawnv) @@ -61,7 +61,7 @@ [rffi.INT, rffi.CCHARP, rffi.CCHARPP], rffi.INT) - def spawnv_lltypeimpl(mode, path, args): + def spawnv_llimpl(mode, path, args): mode = rffi.cast(rffi.INT, mode) l_path = rffi.str2charp(path) l_args = rffi.liststr2charpp(args) @@ -73,32 +73,32 @@ return rffi.cast(lltype.Signed, childpid) self.register(os.spawnv, [int, str, [str]], int, llimpl= - spawnv_lltypeimpl, export_name="ll_os.ll_os_spawnv") + spawnv_llimpl, export_name="ll_os.ll_os_spawnv") @registering(os.dup) def register_os_dup(self): os_dup = rffi.llexternal('dup', [rffi.INT], rffi.INT) - def dup_lltypeimpl(fd): + def dup_llimpl(fd): newfd = rffi.cast(lltype.Signed, os_dup(rffi.cast(rffi.INT, fd))) if newfd == -1: raise OSError(rffi.get_errno(), "dup failed") return newfd - self.register(os.dup, [int], int, llimpl=dup_lltypeimpl, + self.register(os.dup, [int], int, llimpl=dup_llimpl, export_name="ll_os.ll_os_dup", oofakeimpl=os.dup) @registering(os.dup2) def register_os_dup2(self): os_dup2 = rffi.llexternal('dup2', [rffi.INT, rffi.INT], rffi.INT) - def dup2_lltypeimpl(fd, newfd): + def dup2_llimpl(fd, newfd): error = rffi.cast(lltype.Signed, os_dup2(rffi.cast(rffi.INT, fd), rffi.cast(rffi.INT, newfd))) if error == -1: raise OSError(rffi.get_errno(), "dup2 failed") - self.register(os.dup2, [int, int], s_None, llimpl=dup2_lltypeimpl, + self.register(os.dup2, [int, int], s_None, llimpl=dup2_llimpl, export_name="ll_os.ll_os_dup2") @registering(os.utime) @@ -112,7 +112,7 @@ rffi.INT, includes=['utime.h', 'sys/types.h']) - def os_utime_lltypeimpl(path, tp): + def os_utime_llimpl(path, tp): # XXX right now they're all ints, might change in future # XXX does not use utimes, even when available # NB. this function is specialized; we get one version where @@ -132,7 +132,7 @@ rffi.free_charp(l_path) if error == -1: raise OSError(rffi.get_errno(), "os_utime failed") - os_utime_lltypeimpl._annspecialcase_ = 'specialize:argtype(1)' + os_utime_llimpl._annspecialcase_ = 'specialize:argtype(1)' s_string = SomeString() s_tuple_of_2_floats = SomeTuple([SomeFloat(), SomeFloat()]) @@ -158,7 +158,7 @@ self.register(os.utime, os_utime_normalize_args, s_None, "ll_os.ll_os_utime", - llimpl=os_utime_lltypeimpl) + llimpl=os_utime_llimpl) if hasattr(os, 'setsid'): @registering(os.setsid) @@ -166,14 +166,14 @@ os_setsid = rffi.llexternal('setsid', [], rffi.PID_T, includes=['unistd.h']) - def setsid_lltypeimpl(): + def setsid_llimpl(): result = rffi.cast(lltype.Signed, os_setsid()) if result == -1: raise OSError(rffi.get_errno(), "os_setsid failed") return result self.register(os.setsid, [], int, export_name="ll_os.ll_os_setsid", - llimpl=setsid_lltypeimpl) + llimpl=setsid_llimpl) if False and hasattr(os, 'uname'): # make it more portable @registering(os.uname) @@ -200,7 +200,7 @@ i += 1 return "".join(l) - def uname_lltypeimpl(): + def uname_llimpl(): l_utsbuf = lltype.malloc(UTSNAMEP.TO, flavor='raw') result = os_uname(l_utsbuf) if result == -1: @@ -214,7 +214,7 @@ return retval self.register(os.uname, [], (str, str, str, str, str), - "ll_os.ll_uname", llimpl=uname_lltypeimpl) + "ll_os.ll_uname", llimpl=uname_llimpl) @registering(os.getuid) def register_os_getuid(self): @@ -241,7 +241,7 @@ os_open = rffi.llexternal('open', [rffi.CCHARP, rffi.INT, mode_t], rffi.INT) - def os_open_lltypeimpl(path, flags, mode): + def os_open_llimpl(path, flags, mode): l_path = rffi.str2charp(path) result = rffi.cast(lltype.Signed, os_open(l_path, rffi.cast(rffi.INT, flags), @@ -255,7 +255,7 @@ return os.open(o_path._str, flags, mode) self.register(os.open, [str, int, int], int, "ll_os.ll_os_open", - llimpl=os_open_lltypeimpl, oofakeimpl=os_open_oofakeimpl) + llimpl=os_open_llimpl, oofakeimpl=os_open_oofakeimpl) # ------------------------------- os.read ------------------------------- @@ -264,7 +264,7 @@ os_read = rffi.llexternal('read', [rffi.INT, rffi.VOIDP, rffi.SIZE_T], rffi.SIZE_T) - def os_read_lltypeimpl(fd, count): + def os_read_llimpl(fd, count): if count < 0: raise OSError(errno.EINVAL, None) inbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') @@ -283,14 +283,14 @@ return OOSupport.to_rstr(os.read(fd, count)) self.register(os.read, [int, int], str, "ll_os.ll_os_read", - llimpl=os_read_lltypeimpl, oofakeimpl=os_read_oofakeimpl) + llimpl=os_read_llimpl, oofakeimpl=os_read_oofakeimpl) @registering(os.write) def register_os_write(self): os_write = rffi.llexternal('write', [rffi.INT, rffi.VOIDP, rffi.SIZE_T], rffi.SIZE_T) - def os_write_lltypeimpl(fd, data): + def os_write_llimpl(fd, data): count = len(data) outbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') try: @@ -309,19 +309,19 @@ return os.write(fd, OOSupport.from_rstr(data)) self.register(os.write, [int, str], SomeInteger(nonneg=True), - "ll_os.ll_os_write", llimpl=os_write_lltypeimpl, + "ll_os.ll_os_write", llimpl=os_write_llimpl, oofakeimpl=os_write_oofakeimpl) @registering(os.close) def register_os_close(self): os_close = rffi.llexternal('close', [rffi.INT], rffi.INT) - def close_lltypeimpl(fd): + def close_llimpl(fd): error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd))) if error == -1: raise OSError(rffi.get_errno(), "close failed") - self.register(os.close, [int], s_None, llimpl=close_lltypeimpl, + self.register(os.close, [int], s_None, llimpl=close_llimpl, export_name="ll_os.ll_os_close", oofakeimpl=os.close) @registering(os.lseek) @@ -353,7 +353,7 @@ [rffi.INT, rffi.LONGLONG, rffi.INT], rffi.LONGLONG) - def lseek_lltypeimpl(fd, pos, how): + def lseek_llimpl(fd, pos, how): how = fix_seek_arg(how) res = os_lseek(rffi.cast(rffi.INT, fd), rffi.cast(rffi.LONGLONG, pos), @@ -369,7 +369,7 @@ self.register(os.lseek, [int, r_longlong, int], r_longlong, - llimpl = lseek_lltypeimpl, + llimpl = lseek_llimpl, export_name = "ll_os.ll_os_lseek", oofakeimpl = os_lseek_oofakeimpl) @@ -379,14 +379,14 @@ os_ftruncate = rffi.llexternal('ftruncate', [rffi.INT, rffi.LONGLONG], rffi.INT) - def ftruncate_lltypeimpl(fd, length): + def ftruncate_llimpl(fd, length): res = os_ftruncate(rffi.cast(rffi.INT, fd), rffi.cast(rffi.LONGLONG, length)) if res < 0: raise OSError(rffi.get_errno(), "os_lseek failed") self.register(os.ftruncate, [int, r_longlong], s_None, - llimpl = ftruncate_lltypeimpl, + llimpl = ftruncate_llimpl, export_name = "ll_os.ll_os_ftruncate") @registering(os.access) @@ -395,7 +395,7 @@ [rffi.CCHARP, rffi.INT], rffi.INT) - def access_lltypeimpl(path, mode): + def access_llimpl(path, mode): path = rffi.str2charp(path) mode = rffi.cast(rffi.INT, mode) error = rffi.cast(lltype.Signed, os_access(path, mode)) @@ -405,7 +405,7 @@ def os_access_oofakeimpl(path, mode): return os.access(OOSupport.from_rstr(path), mode) - self.register(os.access, [str, int], s_Bool, llimpl=access_lltypeimpl, + self.register(os.access, [str, int], s_Bool, llimpl=access_llimpl, export_name="ll_os.ll_os_access", oofakeimpl=os_access_oofakeimpl) @@ -415,7 +415,7 @@ [rffi.CCHARP, rffi.SIZE_T], rffi.CCHARP) - def os_getcwd_lltypeimpl(): + def os_getcwd_llimpl(): bufsize = 256 while True: buf = lltype.malloc(rffi.CCHARP.TO, bufsize, flavor='raw') @@ -438,7 +438,7 @@ return OOSupport.to_rstr(os.getcwd()) self.register(os.getcwd, [], str, - "ll_os.ll_os_getcwd", llimpl=os_getcwd_lltypeimpl, + "ll_os.ll_os_getcwd", llimpl=os_getcwd_llimpl, oofakeimpl=os_getcwd_oofakeimpl) @registering(os.listdir) @@ -462,7 +462,7 @@ os_closedir = rffi.llexternal('closedir', [DIRP], rffi.INT, includes = INCL) - def os_listdir_lltypeimpl(path): + def os_listdir_llimpl(path): path = rffi.str2charp(path) dirp = os_opendir(path) rffi.free_charp(path) @@ -488,7 +488,7 @@ [str], # a single argument which is a str [str], # returns a list of strings "ll_os.ll_os_listdir", - llimpl=os_listdir_lltypeimpl) + llimpl=os_listdir_llimpl) @registering(os.pipe) def register_os_pipe(self): @@ -500,7 +500,7 @@ os_pipe = rffi.llexternal('pipe', [INT_ARRAY_P], rffi.INT, includes=['unistd.h']) - def os_pipe_lltypeimpl(): + def os_pipe_llimpl(): filedes = lltype.malloc(INT_ARRAY_P.TO, flavor='raw') error = os_pipe(filedes) read_fd = filedes[0] @@ -512,7 +512,7 @@ self.register(os.pipe, [], (int, int), "ll_os.ll_os_pipe", - llimpl=os_pipe_lltypeimpl) + llimpl=os_pipe_llimpl) if hasattr(os, 'readlink'): @registering(os.readlink) @@ -521,7 +521,7 @@ [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], rffi.INT) # XXX SSIZE_T in POSIX.1-2001 - def os_readlink_lltypeimpl(path): + def os_readlink_llimpl(path): l_path = rffi.str2charp(path) try: bufsize = 1023 @@ -551,7 +551,7 @@ self.register(os.readlink, [str], str, "ll_os.ll_os_readlink", - llimpl=os_readlink_lltypeimpl) + llimpl=os_readlink_llimpl) @registering(os.waitpid) def register_os_waitpid(self): @@ -572,7 +572,7 @@ [rffi.PID_T, rffi.INTP, rffi.INT], rffi.PID_T) - def os_waitpid_lltypeimpl(pid, options): + def os_waitpid_llimpl(pid, options): status_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') status_p[0] = 0 result = os_waitpid(rffi.cast(rffi.PID_T, pid), @@ -587,57 +587,57 @@ self.register(os.waitpid, [int, int], (int, int), "ll_os.ll_os_waitpid", - llimpl=os_waitpid_lltypeimpl) + llimpl=os_waitpid_llimpl) @registering(os.isatty) def register_os_isatty(self): os_isatty = rffi.llexternal('isatty', [rffi.INT], rffi.INT) - def isatty_lltypeimpl(fd): + def isatty_llimpl(fd): res = os_isatty(rffi.cast(rffi.INT, fd)) return res != 0 - self.register(os.isatty, [int], bool, llimpl=isatty_lltypeimpl, + self.register(os.isatty, [int], bool, llimpl=isatty_llimpl, export_name="ll_os.ll_os_isatty") @registering(os.strerror) def register_os_strerror(self): os_strerror = rffi.llexternal('strerror', [rffi.INT], rffi.CCHARP) - def strerror_lltypeimpl(errnum): + def strerror_llimpl(errnum): res = os_strerror(rffi.cast(rffi.INT, errnum)) if not res: raise ValueError("os_strerror failed") return rffi.charp2str(res) - self.register(os.strerror, [int], str, llimpl=strerror_lltypeimpl, + self.register(os.strerror, [int], str, llimpl=strerror_llimpl, export_name="ll_os.ll_os_strerror") @registering(os.system) def register_os_system(self): os_system = rffi.llexternal('system', [rffi.CCHARP], rffi.INT) - def system_lltypeimpl(command): + def system_llimpl(command): l_command = rffi.str2charp(command) res = os_system(l_command) rffi.free_charp(l_command) return res - self.register(os.system, [str], int, llimpl=system_lltypeimpl, + self.register(os.system, [str], int, llimpl=system_llimpl, export_name="ll_os.ll_os_system") @registering(os.unlink) def register_os_unlink(self): os_unlink = rffi.llexternal('unlink', [rffi.CCHARP], rffi.INT) - def unlink_lltypeimpl(pathname): + def unlink_llimpl(pathname): l_pathname = rffi.str2charp(pathname) res = os_unlink(l_pathname) rffi.free_charp(l_pathname) if res < 0: raise OSError(rffi.get_errno(), "os_unlink failed") - self.register(os.unlink, [str], s_None, llimpl=unlink_lltypeimpl, + self.register(os.unlink, [str], s_None, llimpl=unlink_llimpl, export_name="ll_os.ll_os_unlink") @registering(os.chdir) @@ -649,14 +649,14 @@ os_chdir = rffi.llexternal('chdir', [rffi.CCHARP], rffi.INT, includes=INCLUDES) - def chdir_lltypeimpl(path): + def chdir_llimpl(path): l_path = rffi.str2charp(path) res = os_chdir(l_path) rffi.free_charp(l_path) if res < 0: raise OSError(rffi.get_errno(), "os_chdir failed") - self.register(os.chdir, [str], s_None, llimpl=chdir_lltypeimpl, + self.register(os.chdir, [str], s_None, llimpl=chdir_llimpl, export_name="ll_os.ll_os_chdir") @registering(os.mkdir) @@ -672,7 +672,7 @@ os_mkdir = rffi.llexternal('mkdir', [rffi.CCHARP]+ARG2, rffi.INT, includes=INCLUDES) - def mkdir_lltypeimpl(pathname, *opt_mode): + def mkdir_llimpl(pathname, *opt_mode): l_pathname = rffi.str2charp(pathname) if opt_mode: opt_mode = (rffi.cast(rffi.MODE_T, opt_mode[0]),) @@ -681,7 +681,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_mkdir failed") - self.register(os.mkdir, [str]+arg2, s_None, llimpl=mkdir_lltypeimpl, + self.register(os.mkdir, [str]+arg2, s_None, llimpl=mkdir_llimpl, export_name="ll_os.ll_os_mkdir") @registering(os.rmdir) @@ -693,14 +693,14 @@ os_rmdir = rffi.llexternal('rmdir', [rffi.CCHARP], rffi.INT, includes=INCLUDES) - def rmdir_lltypeimpl(pathname): + def rmdir_llimpl(pathname): l_pathname = rffi.str2charp(pathname) res = os_rmdir(l_pathname) rffi.free_charp(l_pathname) if res < 0: raise OSError(rffi.get_errno(), "os_rmdir failed") - self.register(os.rmdir, [str], s_None, llimpl=rmdir_lltypeimpl, + self.register(os.rmdir, [str], s_None, llimpl=rmdir_llimpl, export_name="ll_os.ll_os_rmdir") @registering(os.chmod) @@ -714,14 +714,14 @@ os_chmod = rffi.llexternal('chmod', [rffi.CCHARP, MODE_T], rffi.INT, includes=INCLUDES) - def chmod_lltypeimpl(path, mode): + def chmod_llimpl(path, mode): l_path = rffi.str2charp(path) res = os_chmod(l_path, rffi.cast(MODE_T, mode)) rffi.free_charp(l_path) if res < 0: raise OSError(rffi.get_errno(), "os_chmod failed") - self.register(os.chmod, [str, int], s_None, llimpl=chmod_lltypeimpl, + self.register(os.chmod, [str, int], s_None, llimpl=chmod_llimpl, export_name="ll_os.ll_os_chmod") @registering(os.rename) @@ -729,7 +729,7 @@ os_rename = rffi.llexternal('rename', [rffi.CCHARP, rffi.CCHARP], rffi.INT) - def rename_lltypeimpl(oldpath, newpath): + def rename_llimpl(oldpath, newpath): l_oldpath = rffi.str2charp(oldpath) l_newpath = rffi.str2charp(newpath) res = os_rename(l_oldpath, l_newpath) @@ -738,7 +738,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_rename failed") - self.register(os.rename, [str, str], s_None, llimpl=rename_lltypeimpl, + self.register(os.rename, [str, str], s_None, llimpl=rename_llimpl, export_name="ll_os.ll_os_rename") @registering(os.umask) @@ -749,11 +749,11 @@ mode_t = rffi.MODE_T os_umask = rffi.llexternal('umask', [mode_t], mode_t) - def umask_lltypeimpl(fd): + def umask_llimpl(fd): res = os_umask(rffi.cast(mode_t, fd)) return rffi.cast(lltype.Signed, res) - self.register(os.umask, [int], int, llimpl=umask_lltypeimpl, + self.register(os.umask, [int], int, llimpl=umask_llimpl, export_name="ll_os.ll_os_umask") if hasattr(os, 'kill'): @@ -763,13 +763,13 @@ rffi.INT, includes=['sys/types.h', 'signal.h']) - def kill_lltypeimpl(pid, sig): + def kill_llimpl(pid, sig): res = os_kill(rffi.cast(rffi.PID_T, pid), rffi.cast(rffi.INT, sig)) if res < 0: raise OSError(rffi.get_errno(), "os_kill failed") - self.register(os.kill, [int, int], s_None, llimpl=kill_lltypeimpl, + self.register(os.kill, [int, int], s_None, llimpl=kill_llimpl, export_name="ll_os.ll_os_kill") if hasattr(os, 'link'): @@ -779,7 +779,7 @@ rffi.INT, includes = ['unistd.h']) - def link_lltypeimpl(oldpath, newpath): + def link_llimpl(oldpath, newpath): l_oldpath = rffi.str2charp(oldpath) l_newpath = rffi.str2charp(newpath) res = os_link(l_oldpath, l_newpath) @@ -788,7 +788,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_link failed") - self.register(os.link, [str, str], s_None, llimpl=link_lltypeimpl, + self.register(os.link, [str, str], s_None, llimpl=link_llimpl, export_name="ll_os.ll_os_link") if hasattr(os, 'symlink'): @@ -798,7 +798,7 @@ rffi.INT, includes = ['unistd.h']) - def symlink_lltypeimpl(oldpath, newpath): + def symlink_llimpl(oldpath, newpath): l_oldpath = rffi.str2charp(oldpath) l_newpath = rffi.str2charp(newpath) res = os_symlink(l_oldpath, l_newpath) @@ -808,7 +808,7 @@ raise OSError(rffi.get_errno(), "os_symlink failed") self.register(os.symlink, [str, str], s_None, - llimpl=symlink_lltypeimpl, + llimpl=symlink_llimpl, export_name="ll_os.ll_os_symlink") if hasattr(os, 'fork'): @@ -817,23 +817,23 @@ os_fork = rffi.llexternal('fork', [], rffi.PID_T, includes = ['sys/types.h', 'unistd.h']) - def fork_lltypeimpl(): + def fork_llimpl(): childpid = os_fork() if childpid == -1: raise OSError(rffi.get_errno(), "os_fork failed") return rffi.cast(lltype.Signed, childpid) - self.register(os.fork, [], int, llimpl=fork_lltypeimpl, + self.register(os.fork, [], int, llimpl=fork_llimpl, export_name="ll_os.ll_os_fork") @registering(os._exit) def register_os__exit(self): os__exit = rffi.llexternal('_exit', [rffi.INT], lltype.Void) - def _exit_lltypeimpl(status): + def _exit_llimpl(status): os__exit(rffi.cast(rffi.INT, status)) - self.register(os._exit, [int], s_None, llimpl=_exit_lltypeimpl, + self.register(os._exit, [int], s_None, llimpl=_exit_llimpl, export_name="ll_os.ll_os__exit") # --------------------------- os.stat & variants --------------------------- @@ -874,16 +874,16 @@ includes=["sys/wait.h", "sys/types.h"]) if name in self.w_star_returning_int: - def lltypeimpl(status): + def llimpl(status): return os_c_func(status) resulttype = int else: - def lltypeimpl(status): + def llimpl(status): return bool(os_c_func(status)) resulttype = bool - lltypeimpl.func_name = name + '_lltypeimpl' + llimpl.func_name = name + '_llimpl' self.register(getattr(os, name), [int], resulttype, "ll_os."+name, - llimpl=lltypeimpl) + llimpl=llimpl) for name in w_star: if hasattr(os, name): @@ -895,14 +895,14 @@ def register_os_ttyname(self): os_ttyname = rffi.llexternal('ttyname', [lltype.Signed], rffi.CCHARP) - def ttyname_lltypeimpl(fd): + def ttyname_llimpl(fd): l_name = os_ttyname(fd) if not l_name: raise OSError(rffi.get_errno(), "ttyname raised") return rffi.charp2str(l_name) self.register(os.ttyname, [int], str, "ll_os.ttyname", - llimpl=ttyname_lltypeimpl) + llimpl=ttyname_llimpl) # ____________________________________________________________ # Support for os.environ Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py Sat Aug 25 12:51:46 2007 @@ -53,7 +53,7 @@ os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP) -def getenv_lltypeimpl(name): +def getenv_llimpl(name): l_name = rffi.str2charp(name) l_result = os_getenv(l_name) if l_result: @@ -65,7 +65,7 @@ register_external(r_getenv, [str], annmodel.SomeString(can_be_None=True), export_name='ll_os.ll_os_getenv', - llimpl=getenv_lltypeimpl) + llimpl=getenv_llimpl) # ____________________________________________________________ @@ -79,7 +79,7 @@ os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) -def putenv_lltypeimpl(name, value): +def putenv_llimpl(name, value): l_string = rffi.str2charp('%s=%s' % (name, value)) error = os_putenv(l_string) if error: @@ -94,7 +94,7 @@ register_external(r_putenv, [str, str], annmodel.s_None, export_name='ll_os.ll_os_putenv', - llimpl=putenv_lltypeimpl) + llimpl=putenv_llimpl) # ____________________________________________________________ @@ -106,7 +106,7 @@ os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) - def unsetenv_lltypeimpl(name): + def unsetenv_llimpl(name): l_name = rffi.str2charp(name) error = os_unsetenv(l_name) rffi.free_charp(l_name) @@ -122,7 +122,7 @@ register_external(r_unsetenv, [str], annmodel.s_None, export_name='ll_os.ll_os_unsetenv', - llimpl=unsetenv_lltypeimpl) + llimpl=unsetenv_llimpl) # ____________________________________________________________ # Access to the 'environ' external variable @@ -142,7 +142,7 @@ def r_envkeys(): just_a_placeholder -def envkeys_lltypeimpl(): +def envkeys_llimpl(): environ = os_get_environ() result = [] i = 0 @@ -156,14 +156,14 @@ register_external(r_envkeys, [], [str], # returns a list of strings export_name='ll_os.ll_os_envkeys', - llimpl=envkeys_lltypeimpl) + llimpl=envkeys_llimpl) # ____________________________________________________________ def r_envitems(): just_a_placeholder -def envitems_lltypeimpl(): +def envitems_llimpl(): environ = os_get_environ() result = [] i = 0 @@ -177,4 +177,4 @@ register_external(r_envitems, [], [(str, str)], export_name='ll_os.ll_os_envitems', - llimpl=envitems_lltypeimpl) + llimpl=envitems_llimpl) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py Sat Aug 25 12:51:46 2007 @@ -168,7 +168,7 @@ os_mystat = rffi.llexternal(name, [ARG1, STRUCT_STAT], rffi.INT, includes=INCLUDES) - def os_mystat_lltypeimpl(arg): + def os_mystat_llimpl(arg): stresult = lltype.malloc(STRUCT_STAT.TO, flavor='raw') try: if arg_is_path: @@ -188,5 +188,5 @@ s_arg = int register_external(getattr(os, name), [s_arg], s_StatResult, "ll_os.ll_os_%s" % (name,), - llimpl=func_with_new_name(os_mystat_lltypeimpl, - 'os_%s_lltypeimpl' % (name,))) + llimpl=func_with_new_name(os_mystat_llimpl, + 'os_%s_llimpl' % (name,))) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py Sat Aug 25 12:51:46 2007 @@ -718,7 +718,7 @@ return [FunctionCodeGenerator(graph, db)] def sandbox_transform(fnobj, db): - # for --sandbox: replace a function like os_open_lltypeimpl() with + # for --sandbox: replace a function like os_open_llimpl() with # code that communicates with the external process to ask it to # perform the operation. from pypy.translator.sandbox import rsandbox From arigo at codespeak.net Sat Aug 25 12:52:36 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Aug 2007 12:52:36 +0200 (CEST) Subject: [pypy-svn] r45977 - pypy/branch/pypy-more-rtti-inprogress/module/thread Message-ID: <20070825105236.5880A81BE@code0.codespeak.net> Author: arigo Date: Sat Aug 25 12:52:36 2007 New Revision: 45977 Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py Log: Fix typo. Modified: pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/thread/ll_thread.py Sat Aug 25 12:52:36 2007 @@ -40,8 +40,8 @@ TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock', includes=includes) c_thread_lock_init = llexternal('RPyThreadLockInit', [TLOCKP], lltype.Void) -c_thread_acuirelock = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT], - rffi.INT) +c_thread_acquirelock = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT], + rffi.INT) c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void) def allocate_lock(): @@ -110,7 +110,7 @@ self._lock = ll_lock def acquire(self, flag): - return bool(c_thread_acuirelock(self._lock, int(flag))) + return bool(c_thread_acquirelock(self._lock, int(flag))) def release(self): try: From pedronis at codespeak.net Sat Aug 25 12:55:01 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 25 Aug 2007 12:55:01 +0200 (CEST) Subject: [pypy-svn] r45978 - pypy/branch/pypy-more-rtti-inprogress/rpython Message-ID: <20070825105501.4129881BE@code0.codespeak.net> Author: pedronis Date: Sat Aug 25 12:55:00 2007 New Revision: 45978 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Log: better var names, I was confused reading this one the first time Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Sat Aug 25 12:55:00 2007 @@ -40,26 +40,26 @@ class LazyRegisteringMeta(type): def __new__(self, _name, _type, _vars): - retval = type.__new__(self, _name, _type, _vars) + RegisteringClass = type.__new__(self, _name, _type, _vars) allfuncs = [] for varname in _vars: - attr = getattr(retval, varname) + attr = getattr(RegisteringClass, varname) f = getattr(attr, '_registering_func', None) if f: allfuncs.append(f) - instance = lazy_register(allfuncs, retval) - if instance is not None: + registering_inst = lazy_register(allfuncs, RegisteringClass) + if registering_inst is not None: for varname in _vars: - attr = getattr(instance, varname) + attr = getattr(registering_inst, varname) f = getattr(attr, '_registering_func', None) if f: lazy_register(f, attr) - retval.instance = instance + RegisteringClass.instance = registering_inst # override __init__ to avoid confusion def raising(self): raise TypeError("Cannot call __init__ directly, use cls.instance to access singleton") - retval.__init__ = raising - return retval + RegisteringClass.__init__ = raising + return RegisteringClass class BaseLazyRegistering(object): __metaclass__ = LazyRegisteringMeta From pedronis at codespeak.net Sat Aug 25 13:19:17 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 25 Aug 2007 13:19:17 +0200 (CEST) Subject: [pypy-svn] r45979 - in pypy/branch/pypy-more-rtti-inprogress/rpython: . module test Message-ID: <20070825111917.0925781BE@code0.codespeak.net> Author: pedronis Date: Sat Aug 25 13:19:16 2007 New Revision: 45979 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfuncregister.py Log: registering_if convenience decorator for the pattern: if hasattr(ns, name): @registering_if(ns.name) def ... Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Sat Aug 25 13:19:16 2007 @@ -38,6 +38,14 @@ return method return decorator +def registering_if(ns, name): + try: + func = getattr(ns, name) + except AttributeError: + return lambda method: None + else: + return registering(func) + class LazyRegisteringMeta(type): def __new__(self, _name, _type, _vars): RegisteringClass = type.__new__(self, _name, _type, _vars) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Sat Aug 25 13:19:16 2007 @@ -10,7 +10,8 @@ from pypy.rpython.module.support import to_opaque_object, from_opaque_object from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.rarithmetic import r_longlong -from pypy.rpython.extfunc import BaseLazyRegistering, registering +from pypy.rpython.extfunc import BaseLazyRegistering +from pypy.rpython.extfunc import registering, registering_if from pypy.annotation.model import SomeInteger, SomeString, SomeTuple, SomeFloat from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool from pypy.rpython.lltypesystem import rffi @@ -37,43 +38,41 @@ self.register(fun, [], int, llimpl=c_func_llimpl, export_name='ll_os.ll_os_' + name) - if hasattr(os, 'execv'): - @registering(os.execv) - def register_os_execv(self): - os_execv = rffi.llexternal('execv', [rffi.CCHARP, rffi.CCHARPP], - rffi.INT) - - def execv_llimpl(path, args): - l_path = rffi.str2charp(path) - l_args = rffi.liststr2charpp(args) - os_execv(l_path, l_args) - rffi.free_charpp(l_args) - rffi.free_charp(l_path) - raise OSError(rffi.get_errno(), "execv failed") + @registering_if(os, 'execv') + def register_os_execv(self): + os_execv = rffi.llexternal('execv', [rffi.CCHARP, rffi.CCHARPP], + rffi.INT) + + def execv_llimpl(path, args): + l_path = rffi.str2charp(path) + l_args = rffi.liststr2charpp(args) + os_execv(l_path, l_args) + rffi.free_charpp(l_args) + rffi.free_charp(l_path) + raise OSError(rffi.get_errno(), "execv failed") - self.register(os.execv, [str, [str]], s_ImpossibleValue, llimpl= - execv_llimpl, export_name="ll_os.ll_os_execv") + self.register(os.execv, [str, [str]], s_ImpossibleValue, llimpl= + execv_llimpl, export_name="ll_os.ll_os_execv") - if hasattr(posix, 'spawnv'): - @registering(os.spawnv) - def register_os_spawnv(self): - os_spawnv = rffi.llexternal('spawnv', - [rffi.INT, rffi.CCHARP, rffi.CCHARPP], - rffi.INT) - - def spawnv_llimpl(mode, path, args): - mode = rffi.cast(rffi.INT, mode) - l_path = rffi.str2charp(path) - l_args = rffi.liststr2charpp(args) - childpid = os_spawnv(mode, l_path, l_args) - rffi.free_charpp(l_args) - rffi.free_charp(l_path) - if childpid == -1: - raise OSError(rffi.get_errno(), "os_spawnv failed") - return rffi.cast(lltype.Signed, childpid) + @registering_if(posix, 'spawnv') + def register_os_spawnv(self): + os_spawnv = rffi.llexternal('spawnv', + [rffi.INT, rffi.CCHARP, rffi.CCHARPP], + rffi.INT) - self.register(os.spawnv, [int, str, [str]], int, llimpl= - spawnv_llimpl, export_name="ll_os.ll_os_spawnv") + def spawnv_llimpl(mode, path, args): + mode = rffi.cast(rffi.INT, mode) + l_path = rffi.str2charp(path) + l_args = rffi.liststr2charpp(args) + childpid = os_spawnv(mode, l_path, l_args) + rffi.free_charpp(l_args) + rffi.free_charp(l_path) + if childpid == -1: + raise OSError(rffi.get_errno(), "os_spawnv failed") + return rffi.cast(lltype.Signed, childpid) + + self.register(os.spawnv, [int, str, [str]], int, llimpl= + spawnv_llimpl, export_name="ll_os.ll_os_spawnv") @registering(os.dup) def register_os_dup(self): @@ -160,23 +159,22 @@ "ll_os.ll_os_utime", llimpl=os_utime_llimpl) - if hasattr(os, 'setsid'): - @registering(os.setsid) - def register_os_setsid(self): - os_setsid = rffi.llexternal('setsid', [], rffi.PID_T, - includes=['unistd.h']) + @registering_if(os, 'setsid') + def register_os_setsid(self): + os_setsid = rffi.llexternal('setsid', [], rffi.PID_T, + includes=['unistd.h']) - def setsid_llimpl(): - result = rffi.cast(lltype.Signed, os_setsid()) - if result == -1: - raise OSError(rffi.get_errno(), "os_setsid failed") - return result + def setsid_llimpl(): + result = rffi.cast(lltype.Signed, os_setsid()) + if result == -1: + raise OSError(rffi.get_errno(), "os_setsid failed") + return result - self.register(os.setsid, [], int, export_name="ll_os.ll_os_setsid", - llimpl=setsid_llimpl) + self.register(os.setsid, [], int, export_name="ll_os.ll_os_setsid", + llimpl=setsid_llimpl) - if False and hasattr(os, 'uname'): # make it more portable - @registering(os.uname) + if False: + @registering_if(os, 'uname') def register_os_uname(self): lgt = platform.intdefined('_UTSNAME_LENGTH', includes=['sys/utsname.h']) @@ -226,11 +224,10 @@ self.register_os_function_returning_int(os.geteuid, 'geteuid', includes=self.UNISTD_INCL) - if hasattr(os, 'getpid'): - @registering(os.getpid) - def register_os_getpid(self): - self.register_os_function_returning_int(os.getpid, 'getpid', - includes=self.UNISTD_INCL) + @registering_if(os, 'getpid') + def register_os_getpid(self): + self.register_os_function_returning_int(os.getpid, 'getpid', + includes=self.UNISTD_INCL) @registering(os.open) def register_os_open(self): @@ -373,21 +370,20 @@ export_name = "ll_os.ll_os_lseek", oofakeimpl = os_lseek_oofakeimpl) - if hasattr(os, 'ftruncate'): - @registering(os.ftruncate) - def register_os_ftruncate(self): - os_ftruncate = rffi.llexternal('ftruncate', - [rffi.INT, rffi.LONGLONG], rffi.INT) - - def ftruncate_llimpl(fd, length): - res = os_ftruncate(rffi.cast(rffi.INT, fd), - rffi.cast(rffi.LONGLONG, length)) - if res < 0: - raise OSError(rffi.get_errno(), "os_lseek failed") - - self.register(os.ftruncate, [int, r_longlong], s_None, - llimpl = ftruncate_llimpl, - export_name = "ll_os.ll_os_ftruncate") + @registering_if(os, 'ftruncate') + def register_os_ftruncate(self): + os_ftruncate = rffi.llexternal('ftruncate', + [rffi.INT, rffi.LONGLONG], rffi.INT) + + def ftruncate_llimpl(fd, length): + res = os_ftruncate(rffi.cast(rffi.INT, fd), + rffi.cast(rffi.LONGLONG, length)) + if res < 0: + raise OSError(rffi.get_errno(), "os_lseek failed") + + self.register(os.ftruncate, [int, r_longlong], s_None, + llimpl = ftruncate_llimpl, + export_name = "ll_os.ll_os_ftruncate") @registering(os.access) def register_os_access(self): @@ -514,44 +510,43 @@ "ll_os.ll_os_pipe", llimpl=os_pipe_llimpl) - if hasattr(os, 'readlink'): - @registering(os.readlink) - def register_os_readlink(self): - os_readlink = rffi.llexternal('readlink', - [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], - rffi.INT) # XXX SSIZE_T in POSIX.1-2001 - - def os_readlink_llimpl(path): - l_path = rffi.str2charp(path) - try: - bufsize = 1023 - while True: - buf = lltype.malloc(rffi.CCHARP.TO, bufsize, - flavor='raw') - res = os_readlink(l_path, buf, - rffi.cast(rffi.SIZE_T, bufsize)) - if res < 0: - error = rffi.get_errno() # failed - lltype.free(buf, flavor='raw') - raise OSError(error, "readlink failed") - elif res < bufsize: - break # ok - else: - # buf too small, try again with a larger buffer - lltype.free(buf, flavor='raw') - bufsize *= 4 - # convert the result to a string - res = rffi.cast(lltype.Signed, res) - l = [buf[i] for i in range(res)] - result = ''.join(l) - lltype.free(buf, flavor='raw') - finally: - rffi.free_charp(l_path) - return result + @registering_if(os, 'readlink') + def register_os_readlink(self): + os_readlink = rffi.llexternal('readlink', + [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], + rffi.INT) # XXX SSIZE_T in POSIX.1-2001 + + def os_readlink_llimpl(path): + l_path = rffi.str2charp(path) + try: + bufsize = 1023 + while True: + buf = lltype.malloc(rffi.CCHARP.TO, bufsize, + flavor='raw') + res = os_readlink(l_path, buf, + rffi.cast(rffi.SIZE_T, bufsize)) + if res < 0: + error = rffi.get_errno() # failed + lltype.free(buf, flavor='raw') + raise OSError(error, "readlink failed") + elif res < bufsize: + break # ok + else: + # buf too small, try again with a larger buffer + lltype.free(buf, flavor='raw') + bufsize *= 4 + # convert the result to a string + res = rffi.cast(lltype.Signed, res) + l = [buf[i] for i in range(res)] + result = ''.join(l) + lltype.free(buf, flavor='raw') + finally: + rffi.free_charp(l_path) + return result - self.register(os.readlink, [str], str, - "ll_os.ll_os_readlink", - llimpl=os_readlink_llimpl) + self.register(os.readlink, [str], str, + "ll_os.ll_os_readlink", + llimpl=os_readlink_llimpl) @registering(os.waitpid) def register_os_waitpid(self): @@ -756,75 +751,71 @@ self.register(os.umask, [int], int, llimpl=umask_llimpl, export_name="ll_os.ll_os_umask") - if hasattr(os, 'kill'): - @registering(os.kill) - def register_os_kill(self): - os_kill = rffi.llexternal('kill', [rffi.PID_T, rffi.INT], - rffi.INT, - includes=['sys/types.h', 'signal.h']) - - def kill_llimpl(pid, sig): - res = os_kill(rffi.cast(rffi.PID_T, pid), - rffi.cast(rffi.INT, sig)) - if res < 0: - raise OSError(rffi.get_errno(), "os_kill failed") - - self.register(os.kill, [int, int], s_None, llimpl=kill_llimpl, - export_name="ll_os.ll_os_kill") - - if hasattr(os, 'link'): - @registering(os.link) - def register_os_link(self): - os_link = rffi.llexternal('link', [rffi.CCHARP, rffi.CCHARP], - rffi.INT, - includes = ['unistd.h']) - - def link_llimpl(oldpath, newpath): - l_oldpath = rffi.str2charp(oldpath) - l_newpath = rffi.str2charp(newpath) - res = os_link(l_oldpath, l_newpath) - rffi.free_charp(l_newpath) - rffi.free_charp(l_oldpath) - if res < 0: - raise OSError(rffi.get_errno(), "os_link failed") - - self.register(os.link, [str, str], s_None, llimpl=link_llimpl, - export_name="ll_os.ll_os_link") - - if hasattr(os, 'symlink'): - @registering(os.symlink) - def register_os_symlink(self): - os_symlink = rffi.llexternal('symlink', [rffi.CCHARP, rffi.CCHARP], - rffi.INT, - includes = ['unistd.h']) - - def symlink_llimpl(oldpath, newpath): - l_oldpath = rffi.str2charp(oldpath) - l_newpath = rffi.str2charp(newpath) - res = os_symlink(l_oldpath, l_newpath) - rffi.free_charp(l_newpath) - rffi.free_charp(l_oldpath) - if res < 0: - raise OSError(rffi.get_errno(), "os_symlink failed") - - self.register(os.symlink, [str, str], s_None, - llimpl=symlink_llimpl, - export_name="ll_os.ll_os_symlink") - - if hasattr(os, 'fork'): - @registering(os.fork) - def register_os_fork(self): - os_fork = rffi.llexternal('fork', [], rffi.PID_T, - includes = ['sys/types.h', 'unistd.h']) - - def fork_llimpl(): - childpid = os_fork() - if childpid == -1: - raise OSError(rffi.get_errno(), "os_fork failed") - return rffi.cast(lltype.Signed, childpid) + @registering_if(os, 'kill') + def register_os_kill(self): + os_kill = rffi.llexternal('kill', [rffi.PID_T, rffi.INT], + rffi.INT, + includes=['sys/types.h', 'signal.h']) + + def kill_llimpl(pid, sig): + res = os_kill(rffi.cast(rffi.PID_T, pid), + rffi.cast(rffi.INT, sig)) + if res < 0: + raise OSError(rffi.get_errno(), "os_kill failed") + + self.register(os.kill, [int, int], s_None, llimpl=kill_llimpl, + export_name="ll_os.ll_os_kill") - self.register(os.fork, [], int, llimpl=fork_llimpl, - export_name="ll_os.ll_os_fork") + @registering_if(os, 'link') + def register_os_link(self): + os_link = rffi.llexternal('link', [rffi.CCHARP, rffi.CCHARP], + rffi.INT, + includes = ['unistd.h']) + + def link_llimpl(oldpath, newpath): + l_oldpath = rffi.str2charp(oldpath) + l_newpath = rffi.str2charp(newpath) + res = os_link(l_oldpath, l_newpath) + rffi.free_charp(l_newpath) + rffi.free_charp(l_oldpath) + if res < 0: + raise OSError(rffi.get_errno(), "os_link failed") + + self.register(os.link, [str, str], s_None, llimpl=link_llimpl, + export_name="ll_os.ll_os_link") + + @registering_if(os, 'symlink') + def register_os_symlink(self): + os_symlink = rffi.llexternal('symlink', [rffi.CCHARP, rffi.CCHARP], + rffi.INT, + includes = ['unistd.h']) + + def symlink_llimpl(oldpath, newpath): + l_oldpath = rffi.str2charp(oldpath) + l_newpath = rffi.str2charp(newpath) + res = os_symlink(l_oldpath, l_newpath) + rffi.free_charp(l_newpath) + rffi.free_charp(l_oldpath) + if res < 0: + raise OSError(rffi.get_errno(), "os_symlink failed") + + self.register(os.symlink, [str, str], s_None, + llimpl=symlink_llimpl, + export_name="ll_os.ll_os_symlink") + + @registering_if(os, 'fork') + def register_os_fork(self): + os_fork = rffi.llexternal('fork', [], rffi.PID_T, + includes = ['sys/types.h', 'unistd.h']) + + def fork_llimpl(): + childpid = os_fork() + if childpid == -1: + raise OSError(rffi.get_errno(), "os_fork failed") + return rffi.cast(lltype.Signed, childpid) + + self.register(os.fork, [], int, llimpl=fork_llimpl, + export_name="ll_os.ll_os_fork") @registering(os._exit) def register_os__exit(self): @@ -886,23 +877,21 @@ llimpl=llimpl) for name in w_star: - if hasattr(os, name): - locals()['register_w_' + name] = registering(getattr(os, name))( - lambda self, xname=name : self.declare_new_w_star(xname)) - - if hasattr(os, 'ttyname'): - @registering(os.ttyname) - def register_os_ttyname(self): - os_ttyname = rffi.llexternal('ttyname', [lltype.Signed], rffi.CCHARP) - - def ttyname_llimpl(fd): - l_name = os_ttyname(fd) - if not l_name: - raise OSError(rffi.get_errno(), "ttyname raised") - return rffi.charp2str(l_name) + locals()['register_w_' + name] = registering_if(os, name)( + lambda self, xname=name : self.declare_new_w_star(xname)) + + @registering_if(os, 'ttyname') + def register_os_ttyname(self): + os_ttyname = rffi.llexternal('ttyname', [lltype.Signed], rffi.CCHARP) + + def ttyname_llimpl(fd): + l_name = os_ttyname(fd) + if not l_name: + raise OSError(rffi.get_errno(), "ttyname raised") + return rffi.charp2str(l_name) - self.register(os.ttyname, [int], str, "ll_os.ttyname", - llimpl=ttyname_llimpl) + self.register(os.ttyname, [int], str, "ll_os.ttyname", + llimpl=ttyname_llimpl) # ____________________________________________________________ # Support for os.environ Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfuncregister.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfuncregister.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfuncregister.py Sat Aug 25 13:19:16 2007 @@ -5,7 +5,7 @@ import py from pypy.rpython.extfunc import lazy_register, BaseLazyRegistering, \ - registering + registering, registering_if from pypy.rpython.test.test_llinterp import interpret def test_lazy_register(): @@ -70,4 +70,22 @@ py.test.raises(ZeroDivisionError, interpret, lambda : f(), []) py.test.raises(ZeroDivisionError, interpret, lambda : g(), []) + +def test_registering_if(): + class A: + @staticmethod + def f(): + pass + + @registering_if(A, 'f') + def foo(): + pass + + assert foo._registering_func is A.f + @registering_if(A, 'g') + def bar(): + pass + + assert bar is None + From pedronis at codespeak.net Sat Aug 25 13:58:21 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 25 Aug 2007 13:58:21 +0200 (CEST) Subject: [pypy-svn] r45980 - in pypy/branch/pypy-more-rtti-inprogress/rpython: . module test Message-ID: <20070825115821.9229681C4@code0.codespeak.net> Author: pedronis Date: Sat Aug 25 13:58:18 2007 New Revision: 45980 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfuncregister.py Log: support an idiom such that in the best case the original function needs to specified only in the @registering decorator Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Sat Aug 25 13:58:18 2007 @@ -7,6 +7,12 @@ import py, sys +class extdef(object): + + def __init__(self, *args, **kwds): + self.def_args = args + self.def_kwds = kwds + def lazy_register(func_or_list, register_func): """ Lazily register external function. Will create a function, which explodes when llinterpd/translated, but does not explode @@ -17,7 +23,14 @@ else: funcs = [func_or_list] try: - return register_func() + val = register_func() + if isinstance(val, extdef): + assert len(funcs) == 1 + register_external(funcs[0], *val.def_args, **val.def_kwds) + return + return val + except (SystemExit, MemoryError, KeyboardInterrupt), e: + raise except: exc, exc_inst, tb = sys.exc_info() for func in funcs: Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Sat Aug 25 13:58:18 2007 @@ -11,7 +11,7 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.rarithmetic import r_longlong from pypy.rpython.extfunc import BaseLazyRegistering -from pypy.rpython.extfunc import registering, registering_if +from pypy.rpython.extfunc import registering, registering_if, extdef from pypy.annotation.model import SomeInteger, SomeString, SomeTuple, SomeFloat from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool from pypy.rpython.lltypesystem import rffi @@ -26,7 +26,7 @@ pass # XXX fijal: why do I need this? # a simple, yet usefull factory - def register_os_function_returning_int(self, fun, name, **kwds): + def extdef_for__os_function_returning_int(self, name, **kwds): c_func = rffi.llexternal(name, [], rffi.INT, **kwds) def c_func_llimpl(): res = c_func() @@ -35,7 +35,7 @@ return res c_func_llimpl.func_name = name + '_llimpl' - self.register(fun, [], int, llimpl=c_func_llimpl, + return extdef([], int, llimpl=c_func_llimpl, export_name='ll_os.ll_os_' + name) @registering_if(os, 'execv') @@ -51,8 +51,8 @@ rffi.free_charp(l_path) raise OSError(rffi.get_errno(), "execv failed") - self.register(os.execv, [str, [str]], s_ImpossibleValue, llimpl= - execv_llimpl, export_name="ll_os.ll_os_execv") + return extdef([str, [str]], s_ImpossibleValue, llimpl=execv_llimpl, + export_name="ll_os.ll_os_execv") @registering_if(posix, 'spawnv') def register_os_spawnv(self): @@ -71,8 +71,8 @@ raise OSError(rffi.get_errno(), "os_spawnv failed") return rffi.cast(lltype.Signed, childpid) - self.register(os.spawnv, [int, str, [str]], int, llimpl= - spawnv_llimpl, export_name="ll_os.ll_os_spawnv") + return extdef([int, str, [str]], int, llimpl=spawnv_llimpl, + export_name="ll_os.ll_os_spawnv") @registering(os.dup) def register_os_dup(self): @@ -84,7 +84,7 @@ raise OSError(rffi.get_errno(), "dup failed") return newfd - self.register(os.dup, [int], int, llimpl=dup_llimpl, + return extdef([int], int, llimpl=dup_llimpl, export_name="ll_os.ll_os_dup", oofakeimpl=os.dup) @registering(os.dup2) @@ -97,7 +97,7 @@ if error == -1: raise OSError(rffi.get_errno(), "dup2 failed") - self.register(os.dup2, [int, int], s_None, llimpl=dup2_llimpl, + return extdef([int, int], s_None, llimpl=dup2_llimpl, export_name="ll_os.ll_os_dup2") @registering(os.utime) @@ -155,7 +155,7 @@ raise Exception("os.utime() arg 2 must be None or a tuple of " "2 floats, got %s" % (s_times,)) - self.register(os.utime, os_utime_normalize_args, s_None, + return extdef(os_utime_normalize_args, s_None, "ll_os.ll_os_utime", llimpl=os_utime_llimpl) @@ -170,7 +170,7 @@ raise OSError(rffi.get_errno(), "os_setsid failed") return result - self.register(os.setsid, [], int, export_name="ll_os.ll_os_setsid", + return extdef([], int, export_name="ll_os.ll_os_setsid", llimpl=setsid_llimpl) if False: @@ -211,23 +211,23 @@ lltype.free(l_utsbuf, flavor='raw') return retval - self.register(os.uname, [], (str, str, str, str, str), + return extdef([], (str, str, str, str, str), "ll_os.ll_uname", llimpl=uname_llimpl) @registering(os.getuid) def register_os_getuid(self): - self.register_os_function_returning_int(os.getuid, 'getuid', - includes=self.UNISTD_INCL) + return self.extdef_for_os_function_returning_int('getuid', + includes=self.UNISTD_INCL) @registering(os.geteuid) def register_os_geteuid(self): - self.register_os_function_returning_int(os.geteuid, 'geteuid', - includes=self.UNISTD_INCL) + return self.extdef_for_os_function_returning_int('geteuid', + includes=self.UNISTD_INCL) @registering_if(os, 'getpid') def register_os_getpid(self): - self.register_os_function_returning_int(os.getpid, 'getpid', - includes=self.UNISTD_INCL) + return self.extdef_for_os_function_returning_int('getpid', + includes=self.UNISTD_INCL) @registering(os.open) def register_os_open(self): @@ -251,7 +251,7 @@ def os_open_oofakeimpl(o_path, flags, mode): return os.open(o_path._str, flags, mode) - self.register(os.open, [str, int, int], int, "ll_os.ll_os_open", + return extdef([str, int, int], int, "ll_os.ll_os_open", llimpl=os_open_llimpl, oofakeimpl=os_open_oofakeimpl) # ------------------------------- os.read ------------------------------- @@ -279,7 +279,7 @@ def os_read_oofakeimpl(fd, count): return OOSupport.to_rstr(os.read(fd, count)) - self.register(os.read, [int, int], str, "ll_os.ll_os_read", + return extdef([int, int], str, "ll_os.ll_os_read", llimpl=os_read_llimpl, oofakeimpl=os_read_oofakeimpl) @registering(os.write) @@ -305,7 +305,7 @@ def os_write_oofakeimpl(fd, data): return os.write(fd, OOSupport.from_rstr(data)) - self.register(os.write, [int, str], SomeInteger(nonneg=True), + return extdef([int, str], SomeInteger(nonneg=True), "ll_os.ll_os_write", llimpl=os_write_llimpl, oofakeimpl=os_write_oofakeimpl) @@ -318,7 +318,7 @@ if error == -1: raise OSError(rffi.get_errno(), "close failed") - self.register(os.close, [int], s_None, llimpl=close_llimpl, + return extdef([int], s_None, llimpl=close_llimpl, export_name="ll_os.ll_os_close", oofakeimpl=os.close) @registering(os.lseek) @@ -364,7 +364,7 @@ res = os.lseek(fd, pos, how) return r_longlong(res) - self.register(os.lseek, [int, r_longlong, int], + return extdef([int, r_longlong, int], r_longlong, llimpl = lseek_llimpl, export_name = "ll_os.ll_os_lseek", @@ -381,7 +381,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_lseek failed") - self.register(os.ftruncate, [int, r_longlong], s_None, + return extdef([int, r_longlong], s_None, llimpl = ftruncate_llimpl, export_name = "ll_os.ll_os_ftruncate") @@ -401,7 +401,7 @@ def os_access_oofakeimpl(path, mode): return os.access(OOSupport.from_rstr(path), mode) - self.register(os.access, [str, int], s_Bool, llimpl=access_llimpl, + return extdef([str, int], s_Bool, llimpl=access_llimpl, export_name="ll_os.ll_os_access", oofakeimpl=os_access_oofakeimpl) @@ -433,7 +433,7 @@ def os_getcwd_oofakeimpl(): return OOSupport.to_rstr(os.getcwd()) - self.register(os.getcwd, [], str, + return extdef([], str, "ll_os.ll_os_getcwd", llimpl=os_getcwd_llimpl, oofakeimpl=os_getcwd_oofakeimpl) @@ -480,8 +480,7 @@ raise OSError(error, "os_readdir failed") return result - self.register(os.listdir, - [str], # a single argument which is a str + return extdef([str], # a single argument which is a str [str], # returns a list of strings "ll_os.ll_os_listdir", llimpl=os_listdir_llimpl) @@ -506,7 +505,7 @@ raise OSError(rffi.get_errno(), "os_pipe failed") return (read_fd, write_fd) - self.register(os.pipe, [], (int, int), + return extdef([], (int, int), "ll_os.ll_os_pipe", llimpl=os_pipe_llimpl) @@ -544,7 +543,7 @@ rffi.free_charp(l_path) return result - self.register(os.readlink, [str], str, + return extdef([str], str, "ll_os.ll_os_readlink", llimpl=os_readlink_llimpl) @@ -580,7 +579,7 @@ return (rffi.cast(lltype.Signed, result), rffi.cast(lltype.Signed, status)) - self.register(os.waitpid, [int, int], (int, int), + return extdef([int, int], (int, int), "ll_os.ll_os_waitpid", llimpl=os_waitpid_llimpl) @@ -592,7 +591,7 @@ res = os_isatty(rffi.cast(rffi.INT, fd)) return res != 0 - self.register(os.isatty, [int], bool, llimpl=isatty_llimpl, + return extdef([int], bool, llimpl=isatty_llimpl, export_name="ll_os.ll_os_isatty") @registering(os.strerror) @@ -605,7 +604,7 @@ raise ValueError("os_strerror failed") return rffi.charp2str(res) - self.register(os.strerror, [int], str, llimpl=strerror_llimpl, + return extdef([int], str, llimpl=strerror_llimpl, export_name="ll_os.ll_os_strerror") @registering(os.system) @@ -618,7 +617,7 @@ rffi.free_charp(l_command) return res - self.register(os.system, [str], int, llimpl=system_llimpl, + return extdef([str], int, llimpl=system_llimpl, export_name="ll_os.ll_os_system") @registering(os.unlink) @@ -632,7 +631,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_unlink failed") - self.register(os.unlink, [str], s_None, llimpl=unlink_llimpl, + return extdef([str], s_None, llimpl=unlink_llimpl, export_name="ll_os.ll_os_unlink") @registering(os.chdir) @@ -651,7 +650,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_chdir failed") - self.register(os.chdir, [str], s_None, llimpl=chdir_llimpl, + return extdef([str], s_None, llimpl=chdir_llimpl, export_name="ll_os.ll_os_chdir") @registering(os.mkdir) @@ -676,7 +675,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_mkdir failed") - self.register(os.mkdir, [str]+arg2, s_None, llimpl=mkdir_llimpl, + return extdef([str]+arg2, s_None, llimpl=mkdir_llimpl, export_name="ll_os.ll_os_mkdir") @registering(os.rmdir) @@ -695,7 +694,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_rmdir failed") - self.register(os.rmdir, [str], s_None, llimpl=rmdir_llimpl, + return extdef([str], s_None, llimpl=rmdir_llimpl, export_name="ll_os.ll_os_rmdir") @registering(os.chmod) @@ -716,7 +715,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_chmod failed") - self.register(os.chmod, [str, int], s_None, llimpl=chmod_llimpl, + return extdef([str, int], s_None, llimpl=chmod_llimpl, export_name="ll_os.ll_os_chmod") @registering(os.rename) @@ -733,7 +732,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_rename failed") - self.register(os.rename, [str, str], s_None, llimpl=rename_llimpl, + return extdef([str, str], s_None, llimpl=rename_llimpl, export_name="ll_os.ll_os_rename") @registering(os.umask) @@ -748,7 +747,7 @@ res = os_umask(rffi.cast(mode_t, fd)) return rffi.cast(lltype.Signed, res) - self.register(os.umask, [int], int, llimpl=umask_llimpl, + return extdef([int], int, llimpl=umask_llimpl, export_name="ll_os.ll_os_umask") @registering_if(os, 'kill') @@ -763,7 +762,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_kill failed") - self.register(os.kill, [int, int], s_None, llimpl=kill_llimpl, + return extdef([int, int], s_None, llimpl=kill_llimpl, export_name="ll_os.ll_os_kill") @registering_if(os, 'link') @@ -781,7 +780,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_link failed") - self.register(os.link, [str, str], s_None, llimpl=link_llimpl, + return extdef([str, str], s_None, llimpl=link_llimpl, export_name="ll_os.ll_os_link") @registering_if(os, 'symlink') @@ -799,8 +798,7 @@ if res < 0: raise OSError(rffi.get_errno(), "os_symlink failed") - self.register(os.symlink, [str, str], s_None, - llimpl=symlink_llimpl, + return extdef([str, str], s_None, llimpl=symlink_llimpl, export_name="ll_os.ll_os_symlink") @registering_if(os, 'fork') @@ -814,7 +812,7 @@ raise OSError(rffi.get_errno(), "os_fork failed") return rffi.cast(lltype.Signed, childpid) - self.register(os.fork, [], int, llimpl=fork_llimpl, + return extdef([], int, llimpl=fork_llimpl, export_name="ll_os.ll_os_fork") @registering(os._exit) @@ -824,7 +822,7 @@ def _exit_llimpl(status): os__exit(rffi.cast(rffi.INT, status)) - self.register(os._exit, [int], s_None, llimpl=_exit_llimpl, + return extdef([int], s_None, llimpl=_exit_llimpl, export_name="ll_os.ll_os__exit") # --------------------------- os.stat & variants --------------------------- @@ -873,7 +871,7 @@ return bool(os_c_func(status)) resulttype = bool llimpl.func_name = name + '_llimpl' - self.register(getattr(os, name), [int], resulttype, "ll_os."+name, + return extdef([int], resulttype, "ll_os."+name, llimpl=llimpl) for name in w_star: @@ -890,7 +888,7 @@ raise OSError(rffi.get_errno(), "ttyname raised") return rffi.charp2str(l_name) - self.register(os.ttyname, [int], str, "ll_os.ttyname", + return extdef([int], str, "ll_os.ttyname", llimpl=ttyname_llimpl) # ____________________________________________________________ Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Sat Aug 25 13:58:18 2007 @@ -7,7 +7,7 @@ from pypy.rpython.lltypesystem import rffi from pypy.rpython.tool import rffi_platform as platform from pypy.rpython.lltypesystem import lltype -from pypy.rpython.extfunc import BaseLazyRegistering, registering +from pypy.rpython.extfunc import BaseLazyRegistering, registering, extdef class CConfig: if sys.platform.startswith('win'): @@ -96,7 +96,8 @@ lltype.free(t, flavor='raw') return result return float(c_time(void)) - self.register(time.time, [], float, llimpl=time_time_llimpl, + + return extdef([], float, llimpl=time_time_llimpl, export_name='ll_time.ll_time_time') @registering(time.clock) @@ -110,7 +111,8 @@ def time_clock_llimpl(): result = c_clock() return float(result) / self.CLOCKS_PER_SEC - self.register(time.clock, [], float, llimpl=time_clock_llimpl, + + return extdef([], float, llimpl=time_clock_llimpl, export_name='ll_time.ll_time_clock') @registering(time.sleep) @@ -138,5 +140,6 @@ raise OSError(rffi.get_errno(), "Select failed") finally: lltype.free(t, flavor='raw') - self.register(time.sleep, [float], None, llimpl=time_sleep_llimpl, + + return extdef([float], None, llimpl=time_sleep_llimpl, export_name='ll_time.ll_time_sleep') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfuncregister.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfuncregister.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_extfuncregister.py Sat Aug 25 13:58:18 2007 @@ -5,7 +5,7 @@ import py from pypy.rpython.extfunc import lazy_register, BaseLazyRegistering, \ - registering, registering_if + registering, registering_if, extdef from pypy.rpython.test.test_llinterp import interpret def test_lazy_register(): @@ -49,6 +49,22 @@ py.test.raises(ZeroDivisionError, interpret, lambda : f(), []) assert interpret(lambda : g(), []) == 8 +def test_lazy_register_extdef(): + def g(): + return 3 + + x = [] + + def register_g(): + x.append('g') + return extdef([], int, llimpl=lambda : 21) + + nothing = lazy_register(g, register_g) + + assert x == ['g'] + assert nothing is None + assert interpret(lambda : g(), []) == 21 + def test_lazy_register_raising_init(): def f(): return 3 From fijal at codespeak.net Sat Aug 25 14:32:58 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 25 Aug 2007 14:32:58 +0200 (CEST) Subject: [pypy-svn] r45981 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070825123258.7AD7D81DD@code0.codespeak.net> Author: fijal Date: Sat Aug 25 14:32:54 2007 New Revision: 45981 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Log: Fix name Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Sat Aug 25 14:32:54 2007 @@ -26,7 +26,7 @@ pass # XXX fijal: why do I need this? # a simple, yet usefull factory - def extdef_for__os_function_returning_int(self, name, **kwds): + def extdef_for_os_function_returning_int(self, name, **kwds): c_func = rffi.llexternal(name, [], rffi.INT, **kwds) def c_func_llimpl(): res = c_func() @@ -163,7 +163,6 @@ def register_os_setsid(self): os_setsid = rffi.llexternal('setsid', [], rffi.PID_T, includes=['unistd.h']) - def setsid_llimpl(): result = rffi.cast(lltype.Signed, os_setsid()) if result == -1: From antocuni at codespeak.net Sat Aug 25 15:57:37 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 25 Aug 2007 15:57:37 +0200 (CEST) Subject: [pypy-svn] r45982 - pypy/dist/pypy/translator Message-ID: <20070825135737.98F868192@code0.codespeak.net> Author: antocuni Date: Sat Aug 25 15:57:36 2007 New Revision: 45982 Modified: pypy/dist/pypy/translator/driver.py Log: don't use mono but run main.exe directly when running under cygwin Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Sat Aug 25 15:57:36 2007 @@ -683,7 +683,8 @@ newexename = basename f = file(newexename, 'w') f.write("""#!/bin/bash -mono "$(dirname $0)/$(basename $0)-data/%s" "$@" # XXX doesn't work if it's placed in PATH +if [ `uname -o` = 'Cygwin' ]; then MONO=; else MONO=mono; fi +$MONO "$(dirname $0)/$(basename $0)-data/%s" "$@" # XXX doesn't work if it's placed in PATH """ % main_exe_name) f.close() os.chmod(newexename, 0755) From fijal at codespeak.net Sat Aug 25 15:58:38 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 25 Aug 2007 15:58:38 +0200 (CEST) Subject: [pypy-svn] r45983 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070825135838.A73AE819B@code0.codespeak.net> Author: fijal Date: Sat Aug 25 15:58:38 2007 New Revision: 45983 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rfficache.py Log: Add platform.has('xxx') Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rfficache.py Sat Aug 25 15:58:38 2007 @@ -5,6 +5,7 @@ import py import os +import distutils from pypy.translator.tool.cbuild import build_executable from pypy.tool.udir import udir from pypy.tool.autopath import pypydir @@ -60,6 +61,16 @@ question = 'printf("%%d", %s);' % (c_def,) return int(ask_gcc(question, **kwds)) +def have_c_obj(c_obj, **kwds): + question = c_obj + ';' + try: + ask_gcc(question, **kwds) + return True + except distutils.errors.CompileError: + # parsing errors here and trying to deduce whether + # it's this or not sounds like an overkill + return False + def create_cache_access_method(acc_func, meth_name): def method(self, name, **kwds): try: @@ -116,6 +127,7 @@ defined = create_cache_access_method(c_ifdefined, 'defined') intdefined = create_cache_access_method(c_defined_int, 'intdefined') sizeof = create_cache_access_method(sizeof_c_type, 'sizeof') + has = create_cache_access_method(have_c_obj, 'has') # optimal way of caching it, would be to store file on __del__, # but since we cannot rely on __del__ having all modules, let's Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rfficache.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rfficache.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rfficache.py Sat Aug 25 15:58:38 2007 @@ -14,6 +14,10 @@ def test_c_defined_int(): assert c_defined_int('X', add_source='#define X 3') == 3 +def test_c_existing_symbol(): + assert have_c_obj('X', add_source='int X(int, int, int);') + assert not have_c_obj('xxx') + def test_rfficache(): cache = RffiCache(udir.join('cache.py')) assert cache.inttype('uchar', 'unsigned char', False)._type.BITS == 8 @@ -38,3 +42,4 @@ name = name.replace(' ', '') assert hasattr(rffi, 'r_' + name) assert hasattr(rffi, name.upper()) + From fijal at codespeak.net Sat Aug 25 16:13:36 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 25 Aug 2007 16:13:36 +0200 (CEST) Subject: [pypy-svn] r45984 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070825141336.4B73C8193@code0.codespeak.net> Author: fijal Date: Sat Aug 25 16:13:35 2007 New Revision: 45984 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Log: Fix ll_time to use platform.has('xx') instead of HAS_XXX, this will help us get rid of using Python.h Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Sat Aug 25 16:13:35 2007 @@ -28,7 +28,7 @@ constant_names = ['CLOCKS_PER_SEC', 'CLK_TCK', 'EINTR'] for const in constant_names: setattr(CConfig, const, platform.DefinedConstantInteger(const)) -defs_names = ['HAVE_FTIME', 'HAVE_GETTIMEOFDAY', 'GETTIMEOFDAY_NO_TZ'] +defs_names = ['GETTIMEOFDAY_NO_TZ'] for const in defs_names: setattr(CConfig, const, platform.Defined(const)) @@ -44,6 +44,9 @@ self.includes = CConfig.includes self.TIMEVALP = lltype.Ptr(self.TIMEVAL) self.TIMEBP = lltype.Ptr(self.TIMEB) + self.HAVE_GETTIMEOFDAY = rffi.platform.has('gettimeofday', + includes=self.includes) + self.HAVE_FTIME = rffi.platform.has('ftime', includes=self.includes) @registering(time.time) def register_time_time(self): @@ -64,7 +67,7 @@ c_gettimeofday = None if self.HAVE_FTIME: - c_ftime = rffi.llexternal('ftime', [self.TIMEB], rffi.VOID, + c_ftime = rffi.llexternal('ftime', [self.TIMEBP], lltype.Void, includes=self.includes) else: c_ftime = None # not to confuse flow objspace @@ -92,7 +95,7 @@ if self.HAVE_FTIME: t = lltype.malloc(self.TIMEB, flavor='raw') c_ftime(t) - result = float(t.c_time) + float(t.c_millitm) * 0.001 + result = float(int(t.c_time)) + float(int(t.c_millitm)) * 0.001 lltype.free(t, flavor='raw') return result return float(c_time(void)) From fijal at codespeak.net Sat Aug 25 16:47:48 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 25 Aug 2007 16:47:48 +0200 (CEST) Subject: [pypy-svn] r45985 - pypy/branch/pypy-more-rtti-inprogress/module/time Message-ID: <20070825144748.A34318195@code0.codespeak.net> Author: fijal Date: Sat Aug 25 16:47:47 2007 New Revision: 45985 Modified: pypy/branch/pypy-more-rtti-inprogress/module/time/interp_time.py Log: Kill GIL usage here, as it segfaults anyway Modified: pypy/branch/pypy-more-rtti-inprogress/module/time/interp_time.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/time/interp_time.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/time/interp_time.py Sat Aug 25 16:47:47 2007 @@ -16,10 +16,5 @@ def sleep(space, seconds): """Delay execution for a given number of seconds. The argument may be a floating point number for subsecond precision.""" - # XXX Temporary hack: we need to make sure the GIL is released while - # sleeping. XXX should be done differently !!! - GIL = space.threadlocals.getGIL() - if GIL is not None: GIL.release() time.sleep(seconds) - if GIL is not None: GIL.acquire(True) sleep.unwrap_spec = [ObjSpace, float] From exarkun at codespeak.net Sat Aug 25 17:05:20 2007 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Sat, 25 Aug 2007 17:05:20 +0200 (CEST) Subject: [pypy-svn] r45986 - in pypy/branch/pypy-more-rtti-inprogress: module/posix module/posix/test rpython/module rpython/module/test Message-ID: <20070825150520.BBDB18195@code0.codespeak.net> Author: exarkun Date: Sat Aug 25 17:05:20 2007 New Revision: 45986 Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py Log: implement os.times for posix Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py Sat Aug 25 17:05:20 2007 @@ -32,6 +32,7 @@ 'dup' : 'interp_posix.dup', 'dup2' : 'interp_posix.dup2', 'access' : 'interp_posix.access', + 'times' : 'interp_posix.times', 'system' : 'interp_posix.system', 'unlink' : 'interp_posix.unlink', 'remove' : 'interp_posix.remove', Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Sat Aug 25 17:05:20 2007 @@ -187,6 +187,21 @@ return space.wrap(ok) access.unwrap_spec = [ObjSpace, str, int] + +def times(space): + """ + times() -> (utime, stime, cutime, cstime, elapsed_time) + + Return a tuple of floating point numbers indicating process times. + """ + try: + times = os.times() + except OSError, e: + raise wrap_oserror(space, e) + else: + return space.wrap(times) +times.unwrap_spec = [ObjSpace] + def system(space, cmd): """Execute the command (a string) in a subshell.""" try: Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py Sat Aug 25 17:05:20 2007 @@ -146,6 +146,19 @@ assert not posix.access(pdir, posix.X_OK) + def test_times(self): + """ + posix.times() should return a five-tuple giving float-representations + (seconds, effectively) of the four fields from the underlying struct + tms and the return value. + """ + result = self.posix.times() + assert isinstance(result, tuple) + assert len(result) == 5 + for value in result: + assert isinstance(value, float) + + def test_strerror(self): assert isinstance(self.posix.strerror(0), str) assert isinstance(self.posix.strerror(1), str) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Sat Aug 25 17:05:20 2007 @@ -17,14 +17,47 @@ from pypy.rpython.lltypesystem import rffi from pypy.rpython.lltypesystem.rffi import platform from pypy.rpython.lltypesystem import lltype +from pypy.rpython.tool import rffi_platform posix = __import__(os.name) +class CConfig: + """ + Definitions for platform integration. + + Note: this must be processed through rffi_platform.configure() to provide + usable objects. For example:: + + CLOCK_T = rffi_platform.configure(CConfig)['CLOCK_T'] + register(function, [CLOCK_T], ...) + + """ + includes = ['sys/times.h'] + # XXX argh, argh, argh, should be automatic + _header_ = "\n".join(["#include <%s>" % name for name in includes]) + + CLOCK_T = rffi_platform.SimpleType('clock_t', rffi.INT) + + TMS = rffi_platform.Struct( + 'struct tms', [('tms_utime', rffi.INT), + ('tms_stime', rffi.INT), + ('tms_cutime', rffi.INT), + ('tms_cstime', rffi.INT)]) + + class RegisterOs(BaseLazyRegistering): UNISTD_INCL = ['unistd.h', 'sys/types.h'] def __init__(self): - pass # XXX fijal: why do I need this? - + # Grab all of the platform type definitions and stash them as instance + # attributes (this is quite a hack, what a lazy programmer I must be). + self.__dict__.update(rffi_platform.configure(CConfig)) + # Make some pointer types too + self.TMSP = lltype.Ptr(self.TMS) + # Here is a random extra platform parameter which is important. + # Strictly speaking, this should probably be retrieved at runtime, not + # at translation time. + self.CLOCK_TICKS_PER_SECOND = float(os.sysconf('SC_CLK_TCK')) + # a simple, yet usefull factory def extdef_for_os_function_returning_int(self, name, **kwds): c_func = rffi.llexternal(name, [], rffi.INT, **kwds) @@ -159,6 +192,31 @@ "ll_os.ll_os_utime", llimpl=os_utime_llimpl) + + @registering(os.times) + def register_os_times(self): + # XXX sys/times.h isn't so portable, maybe. + os_times = rffi.llexternal('times', [self.TMSP], self.CLOCK_T, + includes=['sys/times.h']) + + def times_lltypeimpl(): + l_tmsbuf = lltype.malloc(self.TMSP.TO, flavor='raw') + try: + result = os_times(l_tmsbuf) + if result == -1: + raise OSError(rffi.get_errno(), "times failed") + return ( + l_tmsbuf.c_tms_utime / self.CLOCK_TICKS_PER_SECOND, + l_tmsbuf.c_tms_stime / self.CLOCK_TICKS_PER_SECOND, + l_tmsbuf.c_tms_cutime / self.CLOCK_TICKS_PER_SECOND, + l_tmsbuf.c_tms_cstime / self.CLOCK_TICKS_PER_SECOND, + result / self.CLOCK_TICKS_PER_SECOND) + finally: + lltype.free(l_tmsbuf, flavor='raw') + self.register(os.times, [], (float, float, float, float, float), + "ll_os.ll_times", llimpl=times_lltypeimpl) + + @registering_if(os, 'setsid') def register_os_setsid(self): os_setsid = rffi.llexternal('setsid', [], rffi.PID_T, Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os.py Sat Aug 25 17:05:20 2007 @@ -19,6 +19,19 @@ assert result == os.access(filename, mode) +def test_times(): + """ + posix.times should compile as an RPython function and should return a + five-tuple giving float-representations (seconds, effectively) of the four + fields from the underlying struct tms and the return value. + """ + times = compile(lambda: os.times(), ())() + assert isinstance(times, tuple) + assert len(times) == 5 + for value in times: + assert isinstance(value, float) + + def test_getcwd(): data = getllimpl(os.getcwd)() assert data == os.getcwd() Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py Sat Aug 25 17:05:20 2007 @@ -35,6 +35,17 @@ stat0 = getattr(func, 'item%d' % i) assert stat0 == stat[i] + + def test_times(self): + import py; py.test.skip("llinterp does not like tuple returns") + from pypy.rpython.test.test_llinterp import interpret + times = interpret(lambda: posix.times(), ()) + assert isinstance(times, tuple) + assert len(times) == 5 + for value in times: + assert isinstance(value, int) + + def test_lseek(self): def f(fi,pos): posix.lseek(fi,pos,0) From pedronis at codespeak.net Sun Aug 26 13:47:59 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 26 Aug 2007 13:47:59 +0200 (CEST) Subject: [pypy-svn] r45992 - pypy/branch/pypy-more-rtti-inprogress/translator/c/test Message-ID: <20070826114759.DF0AE8173@code0.codespeak.net> Author: pedronis Date: Sun Aug 26 13:47:59 2007 New Revision: 45992 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py Log: show the problem with the wrong assumption of exception transform vs. llexternals Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py Sun Aug 26 13:47:59 2007 @@ -2,7 +2,7 @@ from pypy.translator.translator import TranslationContext, graphof from pypy.translator.simplify import join_blocks from pypy.translator.c import exceptiontransform, genc, gc -from pypy.objspace.flow.model import c_last_exception +from pypy.objspace.flow.model import c_last_exception, summary from pypy.rpython.test.test_llinterp import get_interpreter from pypy.translator.c.test.test_genc import compile from pypy import conftest @@ -201,3 +201,21 @@ etrafo.create_exception_handling(g) ops = dict.fromkeys([o.opname for b, o in g.iterblockops()]) assert 'zero_gc_pointers_inside' in ops + + +def test_llexternal(): + py.test.skip("WIP") + from pypy.rpython.lltypesystem.rffi import llexternal + from pypy.rpython.lltypesystem import lltype + z = llexternal('z', [lltype.Signed], lltype.Signed) + def f(x): + y = -1 + if x > 0: + y = z(x) + return y + x + + t,g = transform_func(f, [int]) + # llexternals normally should not raise, the graph should have no exception + # checking + assert summary(g) == {'int_gt': 1, 'int_add': 1, 'direct_call': 1} + From fijal at codespeak.net Sun Aug 26 16:39:39 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 26 Aug 2007 16:39:39 +0200 (CEST) Subject: [pypy-svn] r45995 - pypy/branch/pypy-more-rtti-inprogress/rlib Message-ID: <20070826143939.9AF3B8171@code0.codespeak.net> Author: fijal Date: Sun Aug 26 16:39:38 2007 New Revision: 45995 Added: pypy/branch/pypy-more-rtti-inprogress/rlib/_rsocket_rffi.py (contents, props changed) Log: Half-by-hand translated version of _rsocket_ctypes Added: pypy/branch/pypy-more-rtti-inprogress/rlib/_rsocket_rffi.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/_rsocket_rffi.py Sun Aug 26 16:39:38 2007 @@ -0,0 +1,585 @@ + +from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.tool import rffi_platform as platform +from pypy.rpython.lltypesystem.rffi import CCHARP + +from pypy.rlib.rarithmetic import intmask, r_uint +import os + +_POSIX = os.name == "posix" +_MS_WINDOWS = os.name == "nt" + + +if _POSIX: + includes = ('sys/types.h', + 'sys/socket.h', + 'sys/un.h', + 'sys/poll.h', + 'sys/select.h', + 'netinet/in.h', + 'netinet/tcp.h', + 'unistd.h', + 'fcntl.h', + 'stdio.h', + 'netdb.h', + 'arpa/inet.h', + 'stdint.h', + 'errno.h', + ) + cond_includes = [('AF_NETLINK', 'linux/netlink.h')] + HEADER = ''.join(['#include <%s>\n' % filename for filename in includes]) + COND_HEADER = ''.join(['#ifdef %s\n#include <%s>\n#endif\n' % cond_include + for cond_include in cond_includes]) +if _MS_WINDOWS: + HEADER = '\n'.join([ + '#include ', + '#include ', + # winsock2 defines AF_UNIX, but not sockaddr_un + '#undef AF_UNIX', + # these types do not exist on windows + 'typedef int ssize_t;', + 'typedef unsigned __int16 uint16_t;', + 'typedef unsigned __int32 uint32_t;', + ]) + COND_HEADER = '' +constants = {} + + +class CConfig: + _header_ = HEADER + COND_HEADER + # constants + linux = platform.Defined('linux') + MS_WINDOWS = platform.Defined('_WIN32') + + O_NONBLOCK = platform.DefinedConstantInteger('O_NONBLOCK') + F_GETFL = platform.DefinedConstantInteger('F_GETFL') + F_SETFL = platform.DefinedConstantInteger('F_SETFL') + FIONBIO = platform.DefinedConstantInteger('FIONBIO') + + INVALID_SOCKET = platform.DefinedConstantInteger('INVALID_SOCKET') + INET_ADDRSTRLEN = platform.DefinedConstantInteger('INET_ADDRSTRLEN') + INET6_ADDRSTRLEN= platform.DefinedConstantInteger('INET6_ADDRSTRLEN') + EINPROGRESS = platform.DefinedConstantInteger('EINPROGRESS') + WSAEINPROGRESS = platform.DefinedConstantInteger('WSAEINPROGRESS') + EWOULDBLOCK = platform.DefinedConstantInteger('EWOULDBLOCK') + WSAEWOULDBLOCK = platform.DefinedConstantInteger('WSAEWOULDBLOCK') + EAFNOSUPPORT = platform.DefinedConstantInteger('EAFNOSUPPORT') + WSAEAFNOSUPPORT = platform.DefinedConstantInteger('WSAEAFNOSUPPORT') +constant_names = ''' +AF_AAL5 AF_APPLETALK AF_ASH AF_ATMPVC AF_ATMSVC AF_AX25 AF_BLUETOOTH AF_BRIDGE +AD_DECnet AF_ECONET AF_INET AF_INET6 AF_IPX AF_IRDA AF_KEY AF_LLC AF_NETBEUI +AF_NETLINK AF_NETROM AF_PACKET AF_PPPOX AF_ROSE AF_ROUTE AF_SECURITY AF_SNA +AF_UNIX AF_WANPIPE AF_X25 AF_UNSPEC + +AI_ADDRCONFIG AI_ALL AI_CANONNAME AI_DEFAULT AI_MASK AI_NUMERICHOST +AI_NUMERICSERV AI_PASSIVE AI_V4MAPPED AI_V4MAPPED_CFG + +BTPROTO_L2CAP BTPROTO_SCO BTPROTO_RFCOMM + +EAI_ADDRFAMILY EAI_AGAIN EAI_BADFLAGS EAI_BADHINTS EAI_FAIL EAI_FAMILY EAI_MAX +EAI_MEMORY EAI_NODATA EAI_NONAME EAI_OVERFLOW EAI_PROTOCOL EAI_SERVICE +EAI_SOCKTYPE EAI_SYSTEM + +IPPROTO_AH IPPROTO_BIP IPPROTO_DSTOPTS IPPROTO_EGP IPPROTO_EON IPPROTO_ESP +IPPROTO_FRAGMENT IPPROTO_GGP IPPROTO_GRE IPPROTO_HELLO IPPROTO_HOPOPTS +IPPROTO_ICMPV6 IPPROTO_IDP IPPROTO_IGMP IPPROTO_IPCOMP IPPROTO_IPIP +IPPROTO_IPV4 IPPROTO_IPV6 IPPROTO_MAX IPPROTO_MOBILE IPPROTO_ND IPPROTO_NONE +IPPROTO_PIM IPPROTO_PUP IPPROTO_ROUTING IPPROTO_RSVP IPPROTO_TCP IPPROTO_TP +IPPROTO_VRRP IPPROTO_XTP + +IPV6_CHECKSUM IPV6_DONTFRAG IPV6_DSTOPTS IPV6_HOPLIMIT IPV6_HOPOPTS +IPV6_JOIN_GROUP IPV6_LEAVE_GROUP IPV6_MULTICAST_HOPS IPV6_MULTICAST_IF +IPV6_MULTICAST_LOOP IPV6_NEXTHOP IPV6_PATHMTU IPV6_PKTINFO IPV6_RECVDSTOPTS +IPV6_RECVHOPLIMIT IPV6_RECVHOPOPTS IPV6_RECVPATHMTU IPV6_RECVPKTINFO +IPV6_RECVRTHDR IPV6_RECVTCLASS IPV6_RTHDR IPV6_RTHDRDSTOPTS IPV6_RTHDR_TYPE_0 +IPV6_TCLASS IPV6_UNICAST_HOPS IPV6_USE_MIN_MTU IPV6_V6ONLY + +IP_ADD_MEMBERSHIP IP_DEFAULT_MULTICAST_LOOP IP_DEFAULT_MULTICAST_TTL +IP_DROP_MEMBERSHIP IP_HDRINCL IP_MAX_MEMBERSHIPS IP_MULTICAST_IF +IP_MULTICAST_LOOP IP_MULTICAST_TTL IP_OPTIONS IP_RECVDSTADDR IP_RECVOPTS +IP_RECVRETOPTS IP_RETOPTS IP_TOS IP_TTL + +MSG_BTAG MSG_ETAG MSG_CTRUNC MSG_DONTROUTE MSG_DONTWAIT MSG_EOR MSG_OOB +MSG_PEEK MSG_TRUNC MSG_WAITALL + +NI_DGRAM NI_MAXHOST NI_MAXSERV NI_NAMEREQD NI_NOFQDN NI_NUMERICHOST +NI_NUMERICSERV + +NETLINK_ROUTE NETLINK_SKIP NETLINK_W1 NETLINK_USERSOCK NETLINK_FIREWALL +NETLINK_TCPDIAG NETLINK_NFLOG NETLINK_XFRM NETLINK_ARPD NETLINK_ROUTE6 +NETLINK_IP6_FW NETLINK_DNRTMSG NETLINK_TAPBASE + + +PACKET_HOST PACKET_BROADCAST PACKET_MULTICAST PACKET_OTHERHOST PACKET_OUTGOING +PACKET_LOOPBACK PACKET_FASTROUTE + + +SOCK_DGRAM SOCK_RAW SOCK_RDM SOCK_SEQPACKET SOCK_STREAM + +SOL_SOCKET SOL_IPX SOL_AX25 SOL_ATALK SOL_NETROM SOL_ROSE + +SO_ACCEPTCONN SO_BROADCAST SO_DEBUG SO_DONTROUTE SO_ERROR SO_EXCLUSIVEADDRUSE +SO_KEEPALIVE SO_LINGER SO_OOBINLINE SO_RCVBUF SO_RCVLOWAT SO_RCVTIMEO +SO_REUSEADDR SO_REUSEPORT SO_SNDBUF SO_SNDLOWAT SO_SNDTIMEO SO_TYPE +SO_USELOOPBACK + +TCP_CORK TCP_DEFER_ACCEPT TCP_INFO TCP_KEEPCNT TCP_KEEPIDLE TCP_KEEPINTVL +TCP_LINGER2 TCP_MAXSEG TCP_NODELAY TCP_QUICKACK TCP_SYNCNT TCP_WINDOW_CLAMP + +IPX_TYPE + +POLLIN POLLPRI POLLOUT POLLERR POLLHUP POLLNVAL +POLLRDNORM POLLRDBAND POLLWRNORM POLLWEBAND POLLMSG + +FD_READ FD_WRITE FD_ACCEPT FD_CONNECT FD_CLOSE +WSA_WAIT_TIMEOUT WSA_WAIT_FAILED INFINITE +FD_CONNECT_BIT FD_CLOSE_BIT +WSA_IO_PENDING WSA_IO_INCOMPLETE WSA_INVALID_HANDLE +WSA_INVALID_PARAMETER WSA_NOT_ENOUGH_MEMORY WSA_OPERATION_ABORTED +'''.split() + +for name in constant_names: + setattr(CConfig, name, platform.DefinedConstantInteger(name)) + +constants["BDADDR_ANY"] = "00:00:00:00:00:00" +constants["BDADDR_LOCAL"] = "00:00:00:FF:FF:FF" + +constants_w_defaults = [('SOL_IP', 0), + ('SOL_TCP', 6), + ('SOL_UDP', 17), + ('SOMAXCONN', 5), + ('IPPROTO_IP', 6), + ('IPPROTO_ICMP', 1), + ('IPPROTO_TCP', 6), + ('IPPROTO_UDP', 17), + ('IPPROTO_RAW', 255), + ('IPPORT_RESERVED', 1024), + ('IPPORT_USERRESERVED', 5000), + ('INADDR_ANY', 0x00000000), + ('INADDR_BROADCAST', 0xffffffff), + ('INADDR_LOOPBACK', 0x7F000001), + ('INADDR_UNSPEC_GROUP', 0xe0000000), + ('INADDR_ALLHOSTS_GROUP', 0xe0000001), + ('INADDR_MAX_LOCAL_GROUP', 0xe00000ff), + ('INADDR_NONE', 0xffffffff), + ('SHUT_RD', 0), + ('SHUT_WR', 1), + ('SHUT_RDWR', 2), + ('POLLIN', 1), + ('POLLPRI', 2), + ('POLLOUT', 4), + ('POLLERR', 8), + ('POLLHUP', 16), + ] +for name, default in constants_w_defaults: + setattr(CConfig, name, platform.DefinedConstantInteger(name)) + +# types +if _MS_WINDOWS: + socketfd_type = rffi.UINT +else: + socketfd_type = rffi.INT + +CConfig.uint16_t = platform.SimpleType('uint16_t', rffi.USHORT) +CConfig.uint32_t = platform.SimpleType('uint32_t', rffi.UINT) +CConfig.size_t = platform.SimpleType('size_t', rffi.INT) +CConfig.ssize_t = platform.SimpleType('ssize_t', rffi.INT) +CConfig.socklen_t = platform.SimpleType('socklen_t', rffi.INT) +sockaddr_ptr = rffi.CStructPtr('sockaddr') +addrinfo_ptr = rffi.CStructPtr('addrinfo') + +# struct types +CConfig.sockaddr = platform.Struct('struct sockaddr', + [('sa_family', rffi.INT), + ('sa_data', rffi.CFixedArray(rffi.CHAR, 1))]) +CConfig.in_addr = platform.Struct('struct in_addr', + [('s_addr', rffi.UINT)]) +CConfig.in6_addr = platform.Struct('struct in6_addr', + []) +CConfig.sockaddr_in = platform.Struct('struct sockaddr_in', + [('sin_family', rffi.INT), + ('sin_port', rffi.USHORT), + ('sin_addr', CConfig.in_addr)]) + +CConfig.sockaddr_in6 = platform.Struct('struct sockaddr_in6', + [('sin6_family', rffi.INT), + ('sin6_port', rffi.USHORT), + ('sin6_addr', CConfig.in6_addr), + ('sin6_flowinfo', rffi.INT), + ('sin6_scope_id', rffi.INT)]) + +CConfig.sockaddr_un = platform.Struct('struct sockaddr_un', + [('sun_family', rffi.INT), + ('sun_path', rffi.CFixedArray(rffi.UCHAR, 1))], + ifdef='AF_UNIX') + +CConfig.sockaddr_nl = platform.Struct('struct sockaddr_nl', + [('nl_family', rffi.INT), + ('nl_pid', rffi.INT), + ('nl_groups', rffi.INT)], + ifdef='AF_NETLINK') + +CConfig.addrinfo = platform.Struct('struct addrinfo', + [('ai_flags', rffi.INT), + ('ai_family', rffi.INT), + ('ai_socktype', rffi.INT), + ('ai_protocol', rffi.INT), + ('ai_addrlen', rffi.INT), + ('ai_addr', sockaddr_ptr), + ('ai_canonname', CCHARP), + ('ai_next', addrinfo_ptr)]) + +CConfig.hostent = platform.Struct('struct hostent', + [('h_name', CCHARP), + ('h_aliases', rffi.CCHARPP), + ('h_addrtype', rffi.INT), + ('h_length', rffi.INT), + ('h_addr_list', rffi.VOIDP), + ]) + + +CConfig.servent = platform.Struct('struct servent', + [('s_name', CCHARP), + ('s_port', rffi.INT), + ('s_proto', CCHARP), + ]) + +CConfig.protoent = platform.Struct('struct protoent', + [('p_proto', rffi.INT), + ]) + +if _POSIX: + CConfig.nfds_t = platform.SimpleType('nfds_t') + CConfig.pollfd = platform.Struct('struct pollfd', + [('fd', socketfd_type), + ('events', rffi.SHORT), + ('revents', rffi.SHORT)]) +if _MS_WINDOWS: + CConfig.WSAEVENT = platform.SimpleType('WSAEVENT', rffi.VOIDP) + CConfig.WSANETWORKEVENTS = platform.Struct( + 'struct _WSANETWORKEVENTS', + [('lNetworkEvents', rffi.LONG), + ('iErrorCode', rffi.CFixedArray(rffi.INT, 10)), #FD_MAX_EVENTS + ]) + +CConfig.timeval = platform.Struct('struct timeval', + [('tv_sec', rffi.LONG), + ('tv_usec', rffi.LONG)]) + +if _MS_WINDOWS: + CConfig.fd_set = platform.Struct('struct fd_set', + [('fd_count', rffi.UINT), + # XXX use FD_SETSIZE + ('fd_array', rffi.CFixedArray(socketfd_type, 64))]) + +if _MS_WINDOWS: + CConfig.WSAData = platform.Struct('struct WSAData', + [('wVersion', rffi.USHORT), + ('wHighVersion', rffi.USHORT), + ('szDescription', rffi.CFixedArray(lltype.Char, 1)), # (WSADESCRIPTION_LEN+1) + ('szSystemStatus', rffi.CFixedArray(lltype.Char, 1)), # (WSASYS_STATUS_LEN+1) + ('iMaxSockets', rffi.USHORT), + ('iMaxUdpDg', rffi.USHORT), + ('lpVendorInfo', CCHARP)]) + + +class cConfig: + pass +cConfig.__dict__.update(platform.configure(CConfig)) + +sockaddr_ptr = lltype.Ptr(cConfig.sockaddr) +addrinfo_ptr = lltype.Ptr(cConfig.addrinfo) + +# HACK HACK HACK +if _MS_WINDOWS: + XXX + from ctypes import Structure + for struct in cConfig.__dict__.values(): + if isinstance(struct, type) and issubclass(struct, Structure): + if struct.__name__ == 'in6_addr': + struct.__name__ = '_in6_addr' + else: + struct._external_ = True # hack to avoid redeclaration of the struct in C + +# fill in missing constants with reasonable defaults +cConfig.NI_MAXHOST = cConfig.NI_MAXHOST or 1025 +cConfig.NI_MAXSERV = cConfig.NI_MAXSERV or 32 +cConfig.INET_ADDRSTRLEN = cConfig.INET_ADDRSTRLEN or 16 + +for name in constant_names: + value = getattr(cConfig, name) + if value is not None: + constants[name] = value +for name, default in constants_w_defaults: + value = getattr(cConfig, name) + if value is not None: + constants[name] = value + else: + constants[name] = default + +constants['has_ipv6'] = True # This is a configuration option in CPython +for name, value in constants.items(): + if isinstance(value, long): + if r_uint(value) == value: + constants[name] = intmask(value) + +locals().update(constants) + +O_NONBLOCK = cConfig.O_NONBLOCK +F_GETFL = cConfig.F_GETFL +F_SETFL = cConfig.F_SETFL +FIONBIO = cConfig.FIONBIO +INET_ADDRSTRLEN = cConfig.INET_ADDRSTRLEN +INET6_ADDRSTRLEN = cConfig.INET6_ADDRSTRLEN +EINPROGRESS = cConfig.EINPROGRESS or cConfig.WSAEINPROGRESS +EWOULDBLOCK = cConfig.EWOULDBLOCK or cConfig.WSAEWOULDBLOCK +EAFNOSUPPORT = cConfig.EAFNOSUPPORT or cConfig.WSAEAFNOSUPPORT + +linux = cConfig.linux +MS_WINDOWS = cConfig.MS_WINDOWS +assert MS_WINDOWS == _MS_WINDOWS + +if MS_WINDOWS: + def invalid_socket(fd): + return fd == INVALID_SOCKET + INVALID_SOCKET = cConfig.INVALID_SOCKET +else: + def invalid_socket(fd): + return fd < 0 + INVALID_SOCKET = -1 + +uint16_t = cConfig.uint16_t +uint32_t = cConfig.uint32_t +size_t = cConfig.size_t +ssize_t = cConfig.ssize_t +socklen_t = cConfig.socklen_t +sockaddr = cConfig.sockaddr +#sockaddr_size = sizeof(sockaddr) +sockaddr_in = cConfig.sockaddr_in +sockaddr_in6 = cConfig.sockaddr_in6 +sockaddr_un = cConfig.sockaddr_un +if cConfig.sockaddr_nl is not None: + sockaddr_nl = cConfig.sockaddr_nl +in_addr = cConfig.in_addr +#in_addr_size = sizeof(in_addr) +in6_addr = cConfig.in6_addr +addrinfo = cConfig.addrinfo +if _POSIX: + nfds_t = cConfig.nfds_t + pollfd = cConfig.pollfd +if MS_WINDOWS: + WSAEVENT = cConfig.WSAEVENT + WSANETWORKEVENTS = cConfig.WSANETWORKEVENTS +timeval = cConfig.timeval +if MS_WINDOWS: + fd_set = cConfig.fd_set + +#c_int_size = sizeof(rffi.INT) +external = rffi.llexternal + +if _POSIX: + strerror = external('strerror', [rffi.INT], CCHARP) + gai_strerror = external('gai_strerror', [rffi.INT], CCHARP) + +#h_errno = c_int.in_dll(socketdll, 'h_errno') +# +#hstrerror = socketdll.hstrerror +#hstrerror.argtypes = [c_int] +#hstrerror.restype = c_char_p + +socket = external('socket', [rffi.INT, rffi.INT, rffi.INT], socketfd_type) + +socketclose = external('close', [socketfd_type], rffi.INT) + +socketconnect = external('connect', [socketfd_type, sockaddr_ptr, socklen_t], rffi.INT) + +if not MS_WINDOWS: + getaddrinfo = external('getaddrinfo', [CCHARP, CCHARP, + addrinfo_ptr, rffi.CArray(addrinfo_ptr)], rffi.INT) + freeaddrinfo = external('freeaddrinfo', [addrinfo_ptr], lltype.Void) + getnameinfo = external('getnameinfo', [sockaddr_ptr, socklen_t, CCHARP, + size_t, CCHARP, size_t, rffi.INT], rffi.INT) + +htonl = external('htonl', [rffi.UINT], rffi.UINT) +htons = external('htons', [rffi.USHORT], rffi.USHORT) +ntohl = external('ntohl', [rffi.UINT], rffi.UINT) +ntohs = external('ntohs', [rffi.USHORT], rffi.USHORT) + +if _POSIX: + inet_aton = external('inet_aton', [CCHARP, lltype.Ptr(in_addr)], + rffi.INT) + +inet_ntoa = external('inet_ntoa', [in_addr], rffi.CCHARP) + +if _POSIX: + inet_pton = external('inet_pton', [rffi.INT, rffi.CCHARP, + rffi.VOIDP], rffi.INT) + + inet_ntop = external('inet_ntop', [rffi.INT, rffi.VOIDP, CCHARP, + socklen_t], CCHARP) + +inet_addr = external('inet_addr', [rffi.CCHARP], rffi.UINT) +socklen_t_ptr = rffi.CArray(socklen_t) +socketaccept = external('accept', [socketfd_type, sockaddr_ptr, + socklen_t_ptr], rffi.INT) +bind = external('bind', [rffi.INT, socketfd_type, socklen_t], rffi.INT) +socketlisten = external('listen', [socketfd_type, rffi.INT], rffi.INT) +socketgetpeername = external('getpeername', [socketfd_type, + sockaddr_ptr, socklen_t_ptr], rffi.INT) +socketgetsockname = external('getsockname', [socketfd_type, + sockaddr_ptr, socklen_t_ptr], rffi.INT) +socketgetsockopt = external('getsockopt', [socketfd_type, rffi.INT, + rffi.INT, rffi.VOIDP, socklen_t_ptr], rffi.INT) +socketsetsockopt = external('setsockopt', [socketfd_type, rffi.INT, + rffi.INT, rffi.VOIDP, socklen_t], rffi.INT) +socketrecv = external('recv', [socketfd_type, rffi.VOIDP, rffi.INT, + rffi.INT], ssize_t) +recvfrom = external('recvfrom', [socketfd_type, rffi.VOIDP, size_t, + rffi.INT, sockaddr_ptr, socklen_t_ptr], rffi.INT) +send = external('send', [socketfd_type, rffi.VOIDP, size_t, rffi.INT], + ssize_t) +sendto = external('sendto', [socketfd_type, rffi.VOIDP, size_t, rffi.INT, + sockaddr_ptr, socklen_t], ssize_t) +shutdown = external('shutdown', [socketfd_type, rffi.INT], rffi.INT) +gethostname = external('gethostname', [rffi.CCHARP, rffi.INT], rffi.INT) +gethostbyname = external('gethostbyname', [rffi.CCHARP], + lltype.Ptr(cConfig.hostent)) +gethostbyaddr = external('gethostbyaddr', [rffi.VOIDP, rffi.INT, rffi.INT], lltype.Ptr(cConfig.hostent)) +getservbyname = external('getservbyname', [rffi.CCHARP, rffi.CCHARP], lltype.Ptr(cConfig.servent)) +getservbyport = external('getservbyport', [rffi.INT, rffi.CCHARP], lltype.Ptr(cConfig.servent)) +getprotobyname = external('getprotobyname', [rffi.CCHARP], lltype.Ptr(cConfig.protoent)) + +if _POSIX: + fcntl = external('fcntl', [socketfd_type, rffi.INT, rffi.INT], rffi.INT) + socketpair_t = rffi.CFixedArray(socketfd_type, 2) + socketpair = external('socketpair', [rffi.INT, rffi.INT, rffi.INT, + lltype.Ptr(socketpair_t)], rffi.INT) + +if _MS_WINDOWS: + XXX + ioctlsocket = socketdll.ioctlsocket + ioctlsocket.argtypes = [socketfd_type, rffi.LONG, POINTER(c_ulong)] + ioctlsocket.restype = c_int + +shutdown = external('shutdown', [rffi.INT, rffi.INT], rffi.INT) + +if _POSIX: + poll = external('poll', [lltype.Ptr(pollfd), nfds_t, rffi.INT], rffi.INT) +elif MS_WINDOWS: + XXX + select = socketdll.select + select.argtypes = [c_int, + POINTER(fd_set), POINTER(fd_set), POINTER(fd_set), + POINTER(timeval)] + select.restype = c_int + + WSACreateEvent = socketdll.WSACreateEvent + WSACreateEvent.argtypes = [] + WSACreateEvent.restype = WSAEVENT + + WSACloseEvent = socketdll.WSACloseEvent + WSACloseEvent.argtypes = [WSAEVENT] + WSACloseEvent.restype = c_int + + WSAEventSelect = socketdll.WSAEventSelect + WSAEventSelect.argtypes = [socketfd_type, WSAEVENT, rffi.LONG] + WSAEventSelect.restype = c_int + + WSAWaitForMultipleEvents = socketdll.WSAWaitForMultipleEvents + WSAWaitForMultipleEvents.argtypes = [rffi.LONG, POINTER(WSAEVENT), + c_int, rffi.LONG, c_int] + WSAWaitForMultipleEvents.restype = c_long + + WSAEnumNetworkEvents = socketdll.WSAEnumNetworkEvents + WSAEnumNetworkEvents.argtypes = [socketfd_type, WSAEVENT, + POINTER(WSANETWORKEVENTS)] + WSAEnumNetworkEvents.restype = c_int + +if MS_WINDOWS: + WSAData = cConfig.WSAData + WSAStartup = socketdll.WSAStartup + WSAStartup.argtypes = [c_int, POINTER(WSAData)] + WSAStartup.restype = c_int + WSAStartup.libraries = ('ws2_32',) + + WSAGetLastError = socketdll.WSAGetLastError + WSAGetLastError.argtypes = [] + WSAGetLastError.restype = c_int + geterrno = WSAGetLastError + + import errno + WIN32_ERROR_MESSAGES = { + errno.WSAEINTR: "Interrupted system call", + errno.WSAEBADF: "Bad file descriptor", + errno.WSAEACCES: "Permission denied", + errno.WSAEFAULT: "Bad address", + errno.WSAEINVAL: "Invalid argument", + errno.WSAEMFILE: "Too many open files", + errno.WSAEWOULDBLOCK: + "The socket operation could not complete without blocking", + errno.WSAEINPROGRESS: "Operation now in progress", + errno.WSAEALREADY: "Operation already in progress", + errno.WSAENOTSOCK: "Socket operation on non-socket", + errno.WSAEDESTADDRREQ: "Destination address required", + errno.WSAEMSGSIZE: "Message too long", + errno.WSAEPROTOTYPE: "Protocol wrong type for socket", + errno.WSAENOPROTOOPT: "Protocol not available", + errno.WSAEPROTONOSUPPORT: "Protocol not supported", + errno.WSAESOCKTNOSUPPORT: "Socket type not supported", + errno.WSAEOPNOTSUPP: "Operation not supported", + errno.WSAEPFNOSUPPORT: "Protocol family not supported", + errno.WSAEAFNOSUPPORT: "Address family not supported", + errno.WSAEADDRINUSE: "Address already in use", + errno.WSAEADDRNOTAVAIL: "Can't assign requested address", + errno.WSAENETDOWN: "Network is down", + errno.WSAENETUNREACH: "Network is unreachable", + errno.WSAENETRESET: "Network dropped connection on reset", + errno.WSAECONNABORTED: "Software caused connection abort", + errno.WSAECONNRESET: "Connection reset by peer", + errno.WSAENOBUFS: "No buffer space available", + errno.WSAEISCONN: "Socket is already connected", + errno.WSAENOTCONN: "Socket is not connected", + errno.WSAESHUTDOWN: "Can't send after socket shutdown", + errno.WSAETOOMANYREFS: "Too many references: can't splice", + errno.WSAETIMEDOUT: "Operation timed out", + errno.WSAECONNREFUSED: "Connection refused", + errno.WSAELOOP: "Too many levels of symbolic links", + errno.WSAENAMETOOLONG: "File name too long", + errno.WSAEHOSTDOWN: "Host is down", + errno.WSAEHOSTUNREACH: "No route to host", + errno.WSAENOTEMPTY: "Directory not empty", + errno.WSAEPROCLIM: "Too many processes", + errno.WSAEUSERS: "Too many users", + errno.WSAEDQUOT: "Disc quota exceeded", + errno.WSAESTALE: "Stale NFS file handle", + errno.WSAEREMOTE: "Too many levels of remote in path", + errno.WSASYSNOTREADY: "Network subsystem is unvailable", + errno.WSAVERNOTSUPPORTED: "WinSock version is not supported", + errno.WSANOTINITIALISED: "Successful WSAStartup() not yet performed", + errno.WSAEDISCON: "Graceful shutdown in progress", + + # Resolver errors + # XXX Not exported by errno. Replace by the values in winsock.h + # errno.WSAHOST_NOT_FOUND: "No such host is known", + # errno.WSATRY_AGAIN: "Host not found, or server failed", + # errno.WSANO_RECOVERY: "Unexpected server error encountered", + # errno.WSANO_DATA: "Valid name without requested data", + # errno.WSANO_ADDRESS: "No address, look for MX record", + + # select() errors + WSA_IO_PENDING: "WSA_IO_PENDING", + WSA_IO_INCOMPLETE: "WSA_IO_INCOMPLETE", + WSA_INVALID_HANDLE: "WSA_INVALID_HANDLE", + WSA_INVALID_PARAMETER: "WSA_INVALID_PARAMETER", + WSA_NOT_ENOUGH_MEMORY: "WSA_NOT_ENOUGH_MEMORY", + WSA_OPERATION_ABORTED: "WSA_OPERATION_ABORTED", + } + + assert len(WIN32_ERROR_MESSAGES) == 53 # detect duplicates + + def socket_strerror(errno): + return WIN32_ERROR_MESSAGES.get(errno, "winsock error %d" % errno) +else: + def socket_strerror(errno): + return strerror(errno) From fijal at codespeak.net Sun Aug 26 16:54:49 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 26 Aug 2007 16:54:49 +0200 (CEST) Subject: [pypy-svn] r45996 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070826145449.08B628157@code0.codespeak.net> Author: fijal Date: Sun Aug 26 16:54:49 2007 New Revision: 45996 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: Few helpers Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Sun Aug 26 16:54:49 2007 @@ -101,8 +101,11 @@ def CStructPtr(*args, **kwds): return lltype.Ptr(CStruct(*args, **kwds)) -def CArray(name, tp): - return lltype.FixedSizeArray(tp) +def CFixedArray(tp, size): + return lltype.FixedSizeArray(tp, size) + +def CArray(tp): + return lltype.Array(tp, hints={'nolength': True}) def COpaque(name, hints=None, **kwds): if hints is None: @@ -214,15 +217,18 @@ try: unsigned = not tp._type.SIGNED except AttributeError: - if tp in [lltype.Char, lltype.Float, lltype.Signed]: + if tp in [lltype.Char, lltype.Float, lltype.Signed] or\ + isinstance(tp, lltype.Ptr): unsigned = False else: - unsigned = True + unsigned = False return size, unsigned def sizeof(tp): if isinstance(tp, lltype.FixedSizeArray): return sizeof(tp.OF) * tp.length + if isinstance(tp, lltype.Ptr): + tp = ULONG if tp is lltype.Char: return 1 if tp is lltype.Float: From pedronis at codespeak.net Sun Aug 26 18:13:28 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 26 Aug 2007 18:13:28 +0200 (CEST) Subject: [pypy-svn] r45997 - in pypy/branch/pypy-more-rtti-inprogress: rpython/lltypesystem translator/backendopt translator/backendopt/test translator/c/test Message-ID: <20070826161328.C3B6F8124@code0.codespeak.net> Author: pedronis Date: Sun Aug 26 18:13:26 2007 New Revision: 45997 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/canraise.py pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_canraise.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py Log: llexternals typically should not raise. have a canraise flag on them for the benefit of the raise analyzer and exception transform. this changeset will be fun to merge because on the trunk the exception transform has been generalized to work with ootype and has moved. be careful. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Sun Aug 26 18:13:26 2007 @@ -22,7 +22,8 @@ return self.TP def llexternal(name, args, result, _callable=None, sources=[], includes=[], - libraries=[], include_dirs=[], sandboxsafe=False): + libraries=[], include_dirs=[], sandboxsafe=False, + canraise=False): ext_type = lltype.FuncType(args, result) if _callable is None: _callable = ll2ctypes.LL2CtypesCallable(ext_type) @@ -33,7 +34,8 @@ include_dirs=tuple(include_dirs), _callable=_callable, _safe_not_sandboxed=sandboxsafe, - _debugexc=True) # on top of llinterp + _debugexc=True, # on top of llinterp + canraise=canraise) if isinstance(_callable, ll2ctypes.LL2CtypesCallable): _callable.funcptr = funcptr return funcptr Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/canraise.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/canraise.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/canraise.py Sun Aug 26 18:13:26 2007 @@ -16,6 +16,12 @@ log.WARNING("Unknown operation: %s" % op.opname) return True + + def analyze_external_call(self, op): + deref = self.translator.rtyper.type_system_deref + fnobj = deref(op.args[0].value) + return getattr(fnobj, 'canraise', True) + def analyze_exceptblock(self, block, seen=None): return True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_canraise.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_canraise.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_canraise.py Sun Aug 26 18:13:26 2007 @@ -64,13 +64,29 @@ result = ra.can_raise(hgraph.startblock.operations[0]) assert result -def test_external(): - import os.path +def test_llexternal(): + from pypy.rpython.lltypesystem.rffi import llexternal + from pypy.rpython.lltypesystem import lltype + z = llexternal('z', [lltype.Signed], lltype.Signed) def f(x): - return os.path.isdir(str(x)) + return z(x) t, ra = translate(f, [int]) fgraph = graphof(t, f) + + assert fgraph.startblock.operations[0].opname == 'direct_call' + result = ra.can_raise(fgraph.startblock.operations[0]) + assert not result + + z = llexternal('z', [lltype.Signed], lltype.Signed, canraise=True) + def g(x): + return z(x) + t, ra = translate(g, [int]) + ggraph = graphof(t, g) + + assert ggraph.startblock.operations[0].opname == 'direct_call' + + result = ra.can_raise(ggraph.startblock.operations[0]) assert result def test_instantiate(): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py Sun Aug 26 18:13:26 2007 @@ -204,7 +204,6 @@ def test_llexternal(): - py.test.skip("WIP") from pypy.rpython.lltypesystem.rffi import llexternal from pypy.rpython.lltypesystem import lltype z = llexternal('z', [lltype.Signed], lltype.Signed) From fijal at codespeak.net Sun Aug 26 22:09:36 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 26 Aug 2007 22:09:36 +0200 (CEST) Subject: [pypy-svn] r45998 - in pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem: . test Message-ID: <20070826200936.1659A81B1@code0.codespeak.net> Author: fijal Date: Sun Aug 26 22:09:35 2007 New Revision: 45998 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Log: Add rffi.make(STRUCT, **kwds) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Sun Aug 26 22:09:35 2007 @@ -1,4 +1,5 @@ +from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.lltypesystem import ll2ctypes @@ -6,6 +7,8 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic from pypy.rlib import rarithmetic +from pypy.rpython.rbuiltin import parse_kwds +from pypy.rpython.extregistry import ExtRegistryEntry import os class CConstant(Symbolic): @@ -239,3 +242,38 @@ if tp is lltype.Signed: return ULONG._type.BITS/8 return tp._type.BITS/8 + +# ********************** some helpers ******************* + +def make(STRUCT, **fields): + """ Malloc a structure and populate it's fields + """ + ptr = lltype.malloc(STRUCT, flavor='raw') + for name, value in fields.items(): + setattr(ptr, name, value) + return ptr + +class MakeEntry(ExtRegistryEntry): + _about_ = make + + def compute_result_annotation(self, s_type, **s_fields): + TP = s_type.const + if not isinstance(TP, lltype.Struct): + raise TypeError("make called with %s instead of Struct as first argument" % TP) + return annmodel.SomePtr(lltype.Ptr(TP)) + + def specialize_call(self, hop, **fields): + assert hop.args_s[0].is_constant() + hop.exception_cannot_occur() + vlist = [hop.inputarg(lltype.Void, arg=0)] + flags = {'flavor':'raw'} + vlist.append(hop.inputconst(lltype.Void, flags)) + v_ptr = hop.genop('malloc', vlist, resulttype=hop.r_result.lowleveltype) + hop.has_implicit_exception(MemoryError) # record that we know about it + hop.exception_is_here() + for name, i in fields.items(): + name = name[2:] + v_arg = hop.inputarg(hop.args_r[i], arg=i) + v_name = hop.inputconst(lltype.Void, name) + hop.genop('setfield', [v_ptr, v_name, v_arg]) + return v_ptr Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Sun Aug 26 22:09:35 2007 @@ -260,3 +260,45 @@ assert not size_and_sign(lltype.Signed)[1] assert not size_and_sign(lltype.Char)[1] assert size_and_sign(UINT)[1] + +def test_prebuild_constant(): + py.test.skip("WIP") + h_source = py.code.Source(""" + #ifndef _CONSTANTS + #define _CONSTANTS + int x = 3; + char** z = NULL; + #endif + """) + h_include = udir.join('constants.h') + h_include.write(h_source) + + kwds = {'includes':['constants.h'], 'include_dirs':[str(udir)]} + get_x, set_x = CExternVariable(lltype.Signed, 'x', **kwds) + get_z, set_z = CExternVariable(CCHARPP, 'z', **kwds) + + def f(): + one = get_x() + set_x(13) + return one + get_x() + + def g(): + l = liststr2charpp(["a", "b", "c"]) + try: + set_z(l) + return charp2str(get_z()[2]) + finally: + free_charpp(l) + + fn = compile(f, []) + assert fn() == 16 + gn = compile(g, []) + assert gn() == "c" + +def test_struct_create(): + X = CStruct('xx', ('one', INT)) + def f(): + p = make(X, c_one=3) + return p.c_one + assert f() == 3 + assert interpret(f, []) == 3 From fijal at codespeak.net Sun Aug 26 22:16:49 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 26 Aug 2007 22:16:49 +0200 (CEST) Subject: [pypy-svn] r45999 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070826201649.1313C81B8@code0.codespeak.net> Author: fijal Date: Sun Aug 26 22:16:48 2007 New Revision: 45999 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: Kill exception_cannot_occur, thank samuele Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Sun Aug 26 22:16:48 2007 @@ -264,7 +264,6 @@ def specialize_call(self, hop, **fields): assert hop.args_s[0].is_constant() - hop.exception_cannot_occur() vlist = [hop.inputarg(lltype.Void, arg=0)] flags = {'flavor':'raw'} vlist.append(hop.inputconst(lltype.Void, flags)) From pedronis at codespeak.net Sun Aug 26 23:20:01 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 26 Aug 2007 23:20:01 +0200 (CEST) Subject: [pypy-svn] r46000 - in pypy/branch/pypy-more-rtti-inprogress: module/posix/test translator/c/test Message-ID: <20070826212001.373868163@code0.codespeak.net> Author: pedronis Date: Sun Aug 26 23:19:59 2007 New Revision: 46000 Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Log: hfs+ (default os x fs) has no sparse files Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py Sun Aug 26 23:19:59 2007 @@ -275,6 +275,9 @@ def test_largefile(self): os = self.posix + import sys + if sys.platform == 'darwin': + skip("no sparse files on default Mac OS X file system") if os.__name__ == 'nt': skip("no sparse files on Windows") fd = os.open(self.path2, os.O_RDWR | os.O_CREAT, 0666) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py Sun Aug 26 23:19:59 2007 @@ -122,6 +122,8 @@ os.unlink(filename) def test_largefile(): + if sys.platform == 'darwin': + skip("no sparse files on default Mac OS X file system") if not hasattr(os, 'ftruncate'): py.test.skip("this os has no ftruncate :-(") if os.name == 'nt': From pedronis at codespeak.net Sun Aug 26 23:20:57 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 26 Aug 2007 23:20:57 +0200 (CEST) Subject: [pypy-svn] r46001 - pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test Message-ID: <20070826212057.480C58171@code0.codespeak.net> Author: pedronis Date: Sun Aug 26 23:20:56 2007 New Revision: 46001 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_inline.py Log: don't stress ll2ctypes here, makes little sense Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_inline.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_inline.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_inline.py Sun Aug 26 23:20:56 2007 @@ -451,14 +451,6 @@ result = eval_func([54]) assert result == 55 - def test_auto_inline_os_path_isdir(self): - directory = "./." - def f(): - return os.path.isdir(directory) - eval_func, _ = self.check_auto_inlining(f, []) - result = eval_func([]) - assert result is True - def test_inline_raiseonly(self): def f2(x): raise CustomError1 From fijal at codespeak.net Sun Aug 26 23:45:36 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 26 Aug 2007 23:45:36 +0200 (CEST) Subject: [pypy-svn] r46002 - in pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem: . test Message-ID: <20070826214536.C0C9181A2@code0.codespeak.net> Author: fijal Date: Sun Aug 26 23:45:35 2007 New Revision: 46002 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Log: A preliminary version of implicit casting in llexternal. More types should go there Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Sun Aug 26 23:45:35 2007 @@ -9,6 +9,8 @@ from pypy.rlib import rarithmetic from pypy.rpython.rbuiltin import parse_kwds from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.rlib.unroll import unrolling_iterable +from pypy.tool.sourcetools import func_with_new_name import os class CConstant(Symbolic): @@ -41,7 +43,17 @@ canraise=canraise) if isinstance(_callable, ll2ctypes.LL2CtypesCallable): _callable.funcptr = funcptr - return funcptr + + unrolling_arg_tps = unrolling_iterable(enumerate(args)) + def wrapper(*args): + real_args = () + for i, tp in unrolling_arg_tps: + if tp is USHORT: + real_args = real_args + (cast(tp, args[i]),) + else: + real_args = real_args + (args[i],) + return funcptr(*real_args) + return func_with_new_name(wrapper, name) from pypy.rpython.tool.rfficache import platform Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Sun Aug 26 23:45:35 2007 @@ -6,6 +6,12 @@ from pypy.rpython.lltypesystem import lltype from pypy.tool.udir import udir from pypy.rpython.test.test_llinterp import interpret +from pypy.annotation.annrpython import RPythonAnnotator +from pypy.rpython.rtyper import RPythonTyper +from pypy.translator.backendopt.all import backend_optimizations +from pypy.translator.translator import graphof +from pypy.conftest import option +from pypy.objspace.flow.model import summary def test_basic(): c_source = py.code.Source(""" @@ -302,3 +308,22 @@ return p.c_one assert f() == 3 assert interpret(f, []) == 3 + +def test_implicit_cast(): + z = llexternal('z', [USHORT], USHORT) + + def f(): + return z(3) + + a = RPythonAnnotator() + r = a.build_types(f, []) + rtyper = RPythonTyper(a) + rtyper.specialize() + a.translator.rtyper = rtyper + backend_optimizations(a.translator) + if option.view: + a.translator.view() + graph = graphof(a.translator, f) + s = summary(graph) + # there should be not too many operations here by now + assert s.keys() == ['direct_call'] From fijal at codespeak.net Mon Aug 27 09:49:23 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 27 Aug 2007 09:49:23 +0200 (CEST) Subject: [pypy-svn] r46004 - in pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem: . test Message-ID: <20070827074923.D81EE81E2@code0.codespeak.net> Author: fijal Date: Mon Aug 27 09:49:22 2007 New Revision: 46004 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Log: I think test is not working, checkin right test. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Mon Aug 27 09:49:22 2007 @@ -48,7 +48,7 @@ def wrapper(*args): real_args = () for i, tp in unrolling_arg_tps: - if tp is USHORT: + if isinstance(tp, lltype.Number): real_args = real_args + (cast(tp, args[i]),) else: real_args = real_args + (args[i],) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Mon Aug 27 09:49:22 2007 @@ -310,20 +310,24 @@ assert interpret(f, []) == 3 def test_implicit_cast(): + py.test.skip("Does not work") z = llexternal('z', [USHORT], USHORT) - def f(): - return z(3) + def f(x): + return z(x) a = RPythonAnnotator() - r = a.build_types(f, []) + r = a.build_types(f, [int]) rtyper = RPythonTyper(a) rtyper.specialize() a.translator.rtyper = rtyper + if option.view: + a.translator.view() backend_optimizations(a.translator) if option.view: a.translator.view() graph = graphof(a.translator, f) s = summary(graph) # there should be not too many operations here by now - assert s.keys() == ['direct_call'] + assert sorted(s.keys()) == ['cast_primitive', 'direct_call'] + From fijal at codespeak.net Mon Aug 27 10:26:29 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 27 Aug 2007 10:26:29 +0200 (CEST) Subject: [pypy-svn] r46005 - pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test Message-ID: <20070827082629.0073781C4@code0.codespeak.net> Author: fijal Date: Mon Aug 27 10:26:28 2007 New Revision: 46005 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_canraise.py Log: Insert backendopts here, as direct_call is a direct_call to helper Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_canraise.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_canraise.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_canraise.py Mon Aug 27 10:26:28 2007 @@ -1,5 +1,6 @@ from pypy.translator.translator import TranslationContext, graphof from pypy.translator.backendopt.canraise import RaiseAnalyzer +from pypy.translator.backendopt.all import backend_optimizations from pypy.conftest import option def translate(func, sig): @@ -72,7 +73,7 @@ return z(x) t, ra = translate(f, [int]) fgraph = graphof(t, f) - + backend_optimizations(t) assert fgraph.startblock.operations[0].opname == 'direct_call' result = ra.can_raise(fgraph.startblock.operations[0]) From fijal at codespeak.net Mon Aug 27 10:27:13 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 27 Aug 2007 10:27:13 +0200 (CEST) Subject: [pypy-svn] r46006 - in pypy/branch/pypy-more-rtti-inprogress/translator/backendopt: . test Message-ID: <20070827082713.EF00481C4@code0.codespeak.net> Author: fijal Date: Mon Aug 27 10:27:13 2007 New Revision: 46006 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/inline.py pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_inline.py Log: Have _always_inline_ attribute, useful for externals Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/inline.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/inline.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/inline.py Mon Aug 27 10:27:13 2007 @@ -694,7 +694,10 @@ while heap: weight, _, graph = heap[0] if not valid_weight.get(graph): - weight, fixed = heuristic(graph) + if getattr(graph.func, '_always_inline_', None): + weight, fixed = 0.0, True + else: + weight, fixed = heuristic(graph) #print ' + cost %7.2f %50s' % (weight, graph.name) heapreplace(heap, (weight, -len(callers[graph]), graph)) valid_weight[graph] = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_inline.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_inline.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_inline.py Mon Aug 27 10:27:13 2007 @@ -18,6 +18,7 @@ from pypy.translator.backendopt.all import INLINE_THRESHOLD_FOR_TEST from pypy.conftest import option from pypy.translator.backendopt import removenoops +from pypy.objspace.flow.model import summary def no_missing_concretetype(node): if isinstance(node, Block): @@ -194,6 +195,20 @@ result = eval_func([42]) assert result == g(42) + def test_always_inline(self): + def f(x, y, z, k): + p = (((x, y), z), k) + return p[0][0][0] + p[-1] + f._always_inline_ = True + + def g(x, y, z, k): + a = f(x, y, z, k) + return a + eval_func, t = self.check_auto_inlining(g, [int, int, int, int], multiplier=0.1) + graph = graphof(t, g) + s = summary(graph) + assert len(s) > 3 + def test_inline_exceptions(self): def f(x): if x == 0: From fijal at codespeak.net Mon Aug 27 10:28:40 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 27 Aug 2007 10:28:40 +0200 (CEST) Subject: [pypy-svn] r46007 - in pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem: . test Message-ID: <20070827082840.E3DE281C7@code0.codespeak.net> Author: fijal Date: Mon Aug 27 10:28:40 2007 New Revision: 46007 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Log: Always inline helpers here. Add float case Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Mon Aug 27 10:28:40 2007 @@ -50,9 +50,12 @@ for i, tp in unrolling_arg_tps: if isinstance(tp, lltype.Number): real_args = real_args + (cast(tp, args[i]),) + elif tp is lltype.Float: + real_args = real_args + (float(args[i]),) else: real_args = real_args + (args[i],) return funcptr(*real_args) + wrapper._always_inline_ = True return func_with_new_name(wrapper, name) from pypy.rpython.tool.rfficache import platform Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Mon Aug 27 10:28:40 2007 @@ -310,24 +310,21 @@ assert interpret(f, []) == 3 def test_implicit_cast(): - py.test.skip("Does not work") - z = llexternal('z', [USHORT], USHORT) + z = llexternal('z', [USHORT, ULONG, USHORT], USHORT) - def f(x): - return z(x) + def f(x, y, xx): + return z(x, y, xx) a = RPythonAnnotator() - r = a.build_types(f, [int]) + r = a.build_types(f, [int, int, int]) rtyper = RPythonTyper(a) rtyper.specialize() a.translator.rtyper = rtyper - if option.view: - a.translator.view() backend_optimizations(a.translator) if option.view: a.translator.view() graph = graphof(a.translator, f) s = summary(graph) # there should be not too many operations here by now - assert sorted(s.keys()) == ['cast_primitive', 'direct_call'] + assert s == {'cast_int_to_uint': 1, 'direct_call': 1, 'cast_primitive': 2} From fijal at codespeak.net Mon Aug 27 10:29:43 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 27 Aug 2007 10:29:43 +0200 (CEST) Subject: [pypy-svn] r46008 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test Message-ID: <20070827082943.5C1A181E6@code0.codespeak.net> Author: fijal Date: Mon Aug 27 10:29:43 2007 New Revision: 46008 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Log: Be ultra-paranoid with testing Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Mon Aug 27 10:29:43 2007 @@ -310,13 +310,13 @@ assert interpret(f, []) == 3 def test_implicit_cast(): - z = llexternal('z', [USHORT, ULONG, USHORT], USHORT) + z = llexternal('z', [USHORT, ULONG, USHORT, DOUBLE], USHORT) - def f(x, y, xx): - return z(x, y, xx) + def f(x, y, xx, yy): + return z(x, y, xx, yy) a = RPythonAnnotator() - r = a.build_types(f, [int, int, int]) + r = a.build_types(f, [int, int, int, int]) rtyper = RPythonTyper(a) rtyper.specialize() a.translator.rtyper = rtyper @@ -326,5 +326,6 @@ graph = graphof(a.translator, f) s = summary(graph) # there should be not too many operations here by now - assert s == {'cast_int_to_uint': 1, 'direct_call': 1, 'cast_primitive': 2} + assert s == {'cast_int_to_uint': 1, 'direct_call': 1, 'cast_primitive': 2, + 'cast_int_to_float': 1} From fijal at codespeak.net Mon Aug 27 11:25:05 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 27 Aug 2007 11:25:05 +0200 (CEST) Subject: [pypy-svn] r46012 - pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test Message-ID: <20070827092505.7197F81E9@code0.codespeak.net> Author: fijal Date: Mon Aug 27 11:25:02 2007 New Revision: 46012 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_mallocprediction.py Log: This test probably makes little sense now. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_mallocprediction.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_mallocprediction.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/test/test_mallocprediction.py Mon Aug 27 11:25:02 2007 @@ -133,6 +133,7 @@ assert total0 + total == 10 def test_richards(): + py.test.skip("Unsure if this makes any sense any more") from pypy.translator.goal.richards import entry_point t, graph = rtype(entry_point, [int]) total0 = preparation(t, t.graphs) From arigo at codespeak.net Mon Aug 27 13:46:53 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 27 Aug 2007 13:46:53 +0200 (CEST) Subject: [pypy-svn] r46018 - in pypy/branch/pypy-more-rtti-inprogress: rpython/module rpython/ootypesystem/module translator/cli/test Message-ID: <20070827114653.9322C8204@code0.codespeak.net> Author: arigo Date: Mon Aug 27 13:46:51 2007 New Revision: 46018 Added: pypy/branch/pypy-more-rtti-inprogress/rpython/module/r_os_stat.py (contents, props changed) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py Log: Custom annotation and rtyping support for os.stat_result objects. They are rtyped just like a tuple of the correct length supporting only indexing and the st_xxx attributes. We need a custom StatResultRepr because when rtyping for LL backends we have extra platform-dependent items at the end of the tuple, but for OO backends we only want the portable items. This allows the OO backends to assume a fixed shape for the tuples returned by os.stat(). The gencli os.stat() tests pass. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py Mon Aug 27 13:46:51 2007 @@ -4,36 +4,27 @@ """ import os, sys from pypy.annotation import model as annmodel +from pypy.annotation.pairtype import pairtype from pypy.tool.sourcetools import func_with_new_name -from pypy.rpython.controllerentry import Controller, SomeControlledInstance +from pypy.rpython import extregistry from pypy.rpython.extfunc import register_external from pypy.rpython.lltypesystem import rffi, lltype -if sys.platform.startswith('win'): - # XXX on Windows, stat() is flawed; see CPython's posixmodule.c for - # an implementation based on the Win32 API - LongLongIfNotWindows = lltype.Signed -else: - LongLongIfNotWindows = lltype.SignedLongLong +# XXX on Windows, stat() is flawed; see CPython's posixmodule.c for +# an implementation based on the Win32 API -# NOTE: float times are disabled for now, for compatibility with CPython -if 0: #sys.platform.startswith('linux2'): - # XXX assume the tv_nsec way of accessing the sub-second timestamps - # XXX also assume, as in Linux, that it's in a 'struct timespec' - TIMESPEC = rffi.CStructPtr('timespec', - ('tv_sec', lltype.Signed), - ('tv_nsec', lltype.Signed)) - ModTime = rffi.DOUBLE -else: - # XXX add support for more platforms - TIMESPEC = None - ModTime = lltype.Signed +# NOTE: float times are disabled for now, for simplicity. They make the life +# of OO backends more complicated because for them we try to not depend on +# the details of the platform on which we do the translation. Also, they +# seem not essential because they are disabled by default in CPython. +TIMESPEC = None +ModTime = lltype.Signed # all possible fields - some of them are not available on all platforms ALL_STAT_FIELDS = [ ("st_mode", lltype.Signed), ("st_ino", lltype.SignedLongLong), - ("st_dev", LongLongIfNotWindows), + ("st_dev", lltype.SignedLongLong), ("st_nlink", lltype.Signed), ("st_uid", lltype.Signed), ("st_gid", lltype.Signed), @@ -61,6 +52,7 @@ def _expand(lst, originalname, timespecname): if TIMESPEC is not None: + XXX # code not used right now for i, (_name, _TYPE) in enumerate(lst): if _name == originalname: # replace the 'st_atime' field of type rffi.DOUBLE @@ -75,40 +67,56 @@ del _expand, _name, _TYPE +# For OO backends, expose only the portable fields (the first 10). +PORTABLE_STAT_FIELDS = STAT_FIELDS[:N_INDEXABLE_FIELDS] + # ____________________________________________________________ # # Annotation support -class StatResultController(Controller): - """Controls a stat_result object in RPython: internally it is just a - tuple, but the Controller adds the support for the st_xxx attributes. - """ +class SomeStatResult(annmodel.SomeObject): knowntype = os.stat_result - def getitem(self, obj, index): - if 0 <= index < N_INDEXABLE_FIELDS: - return obj[index] - else: - raise IndexError - getitem._annspecialcase_ = 'specialize:arg(2)' # 'index' must be constant - - def install_getter(cls, name): - # def get_st_mode(), def get_st_ino(), etc... - index = STAT_FIELD_NAMES.index(name) - def get_st_xxx(self, obj): - return obj[index] - method_name = 'get_%s' % (name,) - setattr(cls, method_name, func_with_new_name(get_st_xxx, method_name)) - install_getter = classmethod(install_getter) - -for _name in STAT_FIELD_NAMES: - StatResultController.install_getter(_name) - -stat_controller = StatResultController() -s_tuple_StatResult = annmodel.SomeTuple([annmodel.lltype_to_annotation(_TYPE) - for _name, _TYPE in STAT_FIELDS]) -s_StatResult = SomeControlledInstance(s_tuple_StatResult, - controller = stat_controller) + def rtyper_makerepr(self, rtyper): + from pypy.rpython.module import r_os_stat + return r_os_stat.StatResultRepr(rtyper) + + def rtyper_makekey_ex(self, rtyper): + return self.__class__, + + def getattr(self, s_attr): + assert s_attr.is_constant(), "non-constant attr name in getattr()" + attrname = s_attr.const + TYPE = STAT_FIELD_TYPES[attrname] + return annmodel.lltype_to_annotation(TYPE) + +class __extend__(pairtype(SomeStatResult, annmodel.SomeInteger)): + def getitem((s_sta, s_int)): + assert s_int.is_constant(), "os.stat()[index]: index must be constant" + index = s_int.const + assert 0 <= index < N_INDEXABLE_FIELDS, "os.stat()[index] out of range" + name, TYPE = STAT_FIELDS[index] + return annmodel.lltype_to_annotation(TYPE) + +s_StatResult = SomeStatResult() + +def make_stat_result(tup): + """Turn a tuple into an os.stat_result object.""" + positional = tup[:N_INDEXABLE_FIELDS] + kwds = {} + for i, name in enumerate(STAT_FIELD_NAMES[N_INDEXABLE_FIELDS:]): + kwds[name] = tup[N_INDEXABLE_FIELDS + i] + return os.stat_result(positional, kwds) + +class MakeStatResultEntry(extregistry.ExtRegistryEntry): + _about_ = make_stat_result + + def compute_result_annotation(self, s_tup): + return s_StatResult + + def specialize_call(self, hop): + from pypy.rpython.module import r_os_stat + return r_os_stat.specialize_make_stat_result(hop) # ____________________________________________________________ # @@ -124,6 +132,7 @@ def build_stat_result(st): + # only for LL backends if TIMESPEC is not None: atim = st.c_st_atim; atime = atim.c_tv_sec + 1E-9 * atim.c_tv_nsec mtim = st.c_st_mtim; mtime = mtim.c_tv_sec + 1E-9 * mtim.c_tv_nsec @@ -149,7 +158,7 @@ if "st_rdev" in STAT_FIELD_TYPES: result += (st.c_st_rdev,) if "st_flags" in STAT_FIELD_TYPES: result += (st.c_st_flags,) - return stat_controller.box(result) + return make_stat_result(result) def register_stat_variant(name): Added: pypy/branch/pypy-more-rtti-inprogress/rpython/module/r_os_stat.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/r_os_stat.py Mon Aug 27 13:46:51 2007 @@ -0,0 +1,68 @@ +""" +RTyping support for os.stat_result objects. +They are rtyped just like a tuple of the correct length supporting +only indexing and the st_xxx attributes. We need a custom StatResultRepr +because when rtyping for LL backends we have extra platform-dependent +items at the end of the tuple, but for OO backends we only want the +portable items. This allows the OO backends to assume a fixed shape for +the tuples returned by os.stat(). +""" +from pypy.annotation import model as annmodel +from pypy.objspace.flow.model import Constant +from pypy.tool.pairtype import pairtype +from pypy.rpython.rmodel import Repr, IntegerRepr +from pypy.rpython.error import TyperError +from pypy.rpython.module import ll_os_stat + + +class StatResultRepr(Repr): + + def __init__(self, rtyper): + self.rtyper = rtyper + if rtyper.type_system.name == "lltypesystem": + self.stat_fields = ll_os_stat.STAT_FIELDS + else: + self.stat_fields = ll_os_stat.PORTABLE_STAT_FIELDS + + self.stat_field_indexes = {} + for i, (name, TYPE) in enumerate(self.stat_fields): + self.stat_field_indexes[name] = i + + self.s_tuple = annmodel.SomeTuple([annmodel.lltype_to_annotation(TYPE) + for name, TYPE in self.stat_fields]) + self.r_tuple = rtyper.getrepr(self.s_tuple) + self.lowleveltype = self.r_tuple.lowleveltype + + def redispatch_getfield(self, hop, index): + rtyper = self.rtyper + s_index = rtyper.annotator.bookkeeper.immutablevalue(index) + hop2 = hop.copy() + hop2.forced_opname = 'getitem' + hop2.args_v = [hop2.args_v[0], Constant(index)] + hop2.args_s = [self.s_tuple, s_index] + hop2.args_r = [self.r_tuple, rtyper.getrepr(s_index)] + return hop2.dispatch() + + def rtype_getattr(self, hop): + s_attr = hop.args_s[1] + attr = s_attr.const + try: + index = self.stat_field_indexes[attr] + except KeyError: + raise TyperError("os.stat().%s: field not available" % (attr,)) + return self.redispatch_getfield(hop, index) + + +class __extend__(pairtype(StatResultRepr, IntegerRepr)): + + def rtype_getitem((r_sta, r_int), hop): + s_int = hop.args_s[1] + index = s_int.const + return r_sta.redispatch_getfield(hop, index) + + +def specialize_make_stat_result(hop): + r_StatResult = hop.rtyper.getrepr(ll_os_stat.s_StatResult) + [v_result] = hop.inputargs(r_StatResult.r_tuple) + # no-op conversion from r_StatResult.r_tuple to r_StatResult + return v_result Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py Mon Aug 27 13:46:51 2007 @@ -8,4 +8,6 @@ fields = dict(zip(fieldnames, FIELDS)) return ootype.Record(fields) -STAT_RESULT = _make_tuple([ootype.Signed]*10) +from pypy.rpython.module.ll_os_stat import PORTABLE_STAT_FIELDS + +STAT_RESULT = _make_tuple([_TYPE for _name, _TYPE in PORTABLE_STAT_FIELDS]) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py Mon Aug 27 13:46:51 2007 @@ -91,9 +91,14 @@ assert contents == long2str(MAGIC) def test_os_stat(self): - def fn(): - return os.stat('.')[0] - mode = self.interpret(fn, []) + def fn(flag): + if flag: + return os.stat('.')[0] + else: + return os.stat('.').st_mode + mode = self.interpret(fn, [0]) + assert stat.S_ISDIR(mode) + mode = self.interpret(fn, [1]) assert stat.S_ISDIR(mode) def test_os_stat_oserror(self): From arigo at codespeak.net Mon Aug 27 14:01:40 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 27 Aug 2007 14:01:40 +0200 (CEST) Subject: [pypy-svn] r46019 - pypy/branch/pypy-more-rtti-inprogress/module/posix Message-ID: <20070827120140.6247F8205@code0.codespeak.net> Author: arigo Date: Mon Aug 27 14:01:38 2007 New Revision: 46019 Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Log: In object spaces used during translation to OO backends, only expose the portable os.stat_result fields. Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py Mon Aug 27 14:01:38 2007 @@ -80,12 +80,20 @@ # ____________________________________________________________ +# For LL backends, expose all fields. +# For OO backends, only the portable fields (the first 10). STAT_FIELDS = unrolling_iterable(enumerate(ll_os_stat.STAT_FIELDS)) +PORTABLE_STAT_FIELDS = unrolling_iterable( + enumerate(ll_os_stat.PORTABLE_STAT_FIELDS)) def build_stat_result(space, st): + if space.config.translation.type_system == 'ootype': + FIELDS = PORTABLE_STAT_FIELDS + else: + FIELDS = STAT_FIELDS # also when not translating at all lst = [] w_keywords = space.newdict() - for i, (name, TYPE) in STAT_FIELDS: + for i, (name, TYPE) in FIELDS: value = getattr(st, name) #if name in ('st_atime', 'st_mtime', 'st_ctime'): # value = int(value) # rounded to an integer for indexed access @@ -277,8 +285,11 @@ def getstatfields(space): # for app_posix.py: export the list of 'st_xxx' names that we know # about at RPython level - return space.newlist( - [space.wrap(name) for name in ll_os_stat.STAT_FIELD_NAMES]) + if space.config.translation.type_system == 'ootype': + FIELDS = PORTABLE_STAT_FIELDS + else: + FIELDS = STAT_FIELDS # also when not translating at all + return space.newlist([space.wrap(name) for name, _ in FIELDS]) class State: From antocuni at codespeak.net Mon Aug 27 14:55:29 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 14:55:29 +0200 (CEST) Subject: [pypy-svn] r46021 - in pypy/branch/pypy-more-rtti-inprogress: config translator/cli translator/cli/src translator/cli/test translator/oosupport translator/oosupport/test_template Message-ID: <20070827125529.E62588207@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 14:55:29 2007 New Revision: 46021 Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py Log: merge dist to branch (only gencli-related changes) Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py Mon Aug 27 14:55:29 2007 @@ -196,7 +196,8 @@ OptionDescription("cli", "GenCLI options", [ BoolOption("trace_calls", "Trace function calls", default=False, - cmdline="--cli-trace-calls") + cmdline="--cli-trace-calls"), + BoolOption("exception_transformer", "Use exception transformer", default=False), ]), ]) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py Mon Aug 27 14:55:29 2007 @@ -84,7 +84,7 @@ for f_name, (f_type, f_default) in self.INSTANCE._fields.iteritems(): cts_type = self.cts.lltype_to_cts(f_type) f_name = self.cts.escape_name(f_name) - if cts_type != 'void': + if cts_type != CTS.types.void: ilasm.field(f_name, cts_type) self._ctor() @@ -134,7 +134,7 @@ INSTANCE_DEF, _ = self.INSTANCE._lookup_field(f_name) cts_type = self.cts.lltype_to_cts(F_TYPE) f_name = self.cts.escape_name(f_name) - if cts_type != 'void': + if cts_type != CTS.types.void: self.ilasm.opcode('ldarg.0') push_constant(self.db, F_TYPE, f_default, self.gen) class_name = self.db.class_name(INSTANCE_DEF) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py Mon Aug 27 14:55:29 2007 @@ -265,9 +265,9 @@ class CLIBaseConstMixin(object): """ A mix-in with a few extra methods the CLI backend uses """ - def get_type(self, include_class=True): + def get_type(self): """ Returns the CLI type for this constant's representation """ - return self.cts.lltype_to_cts(self.value._TYPE, include_class) + return self.cts.lltype_to_cts(self.value._TYPE) def push_inline(self, gen, TYPE): """ Overload the oosupport version so that we use the CLI opcode Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py Mon Aug 27 14:55:29 2007 @@ -4,61 +4,146 @@ import exceptions -from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong +from py.builtin import set from pypy.rpython.lltypesystem import lltype from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.llmemory import WeakGcAddress from pypy.translator.cli.option import getoption from pypy.translator.cli import oopspec -try: - set -except NameError: - from sets import Set as set - from pypy.tool.ansi_print import ansi_log import py log = py.log.Producer("cli") py.log.setconsumer("cli", ansi_log) -WEAKREF = '[mscorlib]System.WeakReference' -PYPY_LIST = '[pypylib]pypy.runtime.List`1<%s>' -PYPY_LIST_OF_VOID = '[pypylib]pypy.runtime.ListOfVoid' -PYPY_DICT = '[pypylib]pypy.runtime.Dict`2<%s, %s>' +class CliType(object): + def typename(self): + raise NotImplementedError + + def __str__(self): + return self.typename() + + def __hash__(self): + return hash(self.typename()) + + def __eq__(self, other): + return self.typename() == other.typename() + + def __ne__(self, other): + return self.typename() != other.typename() + + +class CliPrimitiveType(CliType): + def __init__(self, name): + self.name = name + + def typename(self): + return self.name + + +class CliReferenceType(CliType): + def typename(self): + return 'class ' + self.classname() + + def classname(self): + raise NotImplementedError + + +class CliClassType(CliReferenceType): + def __init__(self, assembly, name): + self.assembly = assembly + self.name = name + + def classname(self): + if self.assembly: + return '[%s]%s' % (self.assembly, self.name) + else: + return self.name + + +class CliGenericType(CliReferenceType): + def __init__(self, assembly, name, numparam): + self.assembly = assembly + self.name = name + self.numparam = numparam + + def classname(self): + paramtypes = [self.paramtype(i) for i in range(self.numparam)] + thistype = self.specialize(*paramtypes) + return thistype.classname() + + def specialize(self, *types): + assert len(types) == self.numparam + return CliSpecializedType(self, types) + + def paramtype(self, num): + assert 0 <= num < self.numparam + return CliPrimitiveType('!%d' % num) + +class CliSpecializedType(CliReferenceType): + def __init__(self, generic_type, arg_types): + self.generic_type = generic_type + self.arg_types = arg_types + + def classname(self): + assembly = self.generic_type.assembly + name = self.generic_type.name + numparam = self.generic_type.numparam + arglist = ', '.join([arg.typename() for arg in self.arg_types]) + return '[%s]%s`%d<%s>' % (assembly, name, numparam, arglist) + + +T = CliPrimitiveType +class types: + void = T('void') + int32 = T('int32') + uint32 = T('unsigned int32') + int64 = T('int64') + uint64 = T('unsigned int64') + bool = T('bool') + float64 = T('float64') + char = T('char') + string = T('string') + + weakref = CliClassType('mscorlib', 'System.WeakReference') + type = CliClassType('mscorlib', 'System.Type') + object = CliClassType('mscorlib', 'System.Object') + list = CliGenericType('pypylib', 'pypy.runtime.List', 1) + list_of_void = CliClassType('pypylib', 'pypy.runtime.ListOfVoid') + dict = CliGenericType('pypylib', 'pypy.runtime.Dict', 2) + dict_void_void = CliClassType('pypylib', 'pypy.runtime.DictVoidVoid') + dict_items_iterator = CliGenericType('pypylib', 'pypy.runtime.DictItemsIterator', 2) + string_builder = CliClassType('pypylib', 'pypy.runtime.StringBuilder') +del T + +WEAKREF = types.weakref.classname() PYPY_DICT_OF_VOID = '[pypylib]pypy.runtime.DictOfVoid`2<%s, int32>' -PYPY_DICT_VOID_VOID = '[pypylib]pypy.runtime.DictVoidVoid' -PYPY_DICT_ITEMS_ITERATOR = '[pypylib]pypy.runtime.DictItemsIterator`2<%s, %s>' -PYPY_STRING_BUILDER = '[pypylib]pypy.runtime.StringBuilder' + _lltype_to_cts = { - ootype.Void: 'void', - ootype.Signed: 'int32', - ootype.Unsigned: 'unsigned int32', - SignedLongLong: 'int64', - UnsignedLongLong: 'unsigned int64', - ootype.Bool: 'bool', - ootype.Float: 'float64', - ootype.Char: 'char', - ootype.UniChar: 'char', - ootype.Class: 'class [mscorlib]System.Type', - ootype.String: 'string', - ootype.StringBuilder: 'class ' + PYPY_STRING_BUILDER, - WeakGcAddress: 'class ' + WEAKREF, + ootype.Void: types.void, + ootype.Signed: types.int32, + ootype.Unsigned: types.uint32, + ootype.SignedLongLong: types.int64, + ootype.UnsignedLongLong: types.uint64, + ootype.Bool: types.bool, + ootype.Float: types.float64, + ootype.Char: types.char, + ootype.UniChar: types.char, + ootype.Class: types.type, + ootype.String: types.string, + ootype.StringBuilder: types.string_builder, + WeakGcAddress: types.weakref, # maps generic types to their ordinal - ootype.List.SELFTYPE_T: 'class ' + (PYPY_LIST % '!0'), - ootype.List.ITEMTYPE_T: '!0', - ootype.Dict.SELFTYPE_T: 'class ' + (PYPY_DICT % ('!0', '!1')), - ootype.Dict.KEYTYPE_T: '!0', - ootype.Dict.VALUETYPE_T: '!1', - ootype.DictItemsIterator.SELFTYPE_T: 'class ' + (PYPY_DICT_ITEMS_ITERATOR % ('!0', '!1')), - ootype.DictItemsIterator.KEYTYPE_T: '!0', - ootype.DictItemsIterator.VALUETYPE_T: '!1', - } - -_pyexception_to_cts = { - exceptions.Exception: '[mscorlib]System.Exception', - exceptions.OverflowError: '[mscorlib]System.OverflowException' + ootype.List.SELFTYPE_T: types.list, + ootype.List.ITEMTYPE_T: types.list.paramtype(0), + ootype.Dict.SELFTYPE_T: types.dict, + ootype.Dict.KEYTYPE_T: types.dict.paramtype(0), + ootype.Dict.VALUETYPE_T: types.dict.paramtype(1), + ootype.DictItemsIterator.SELFTYPE_T: types.dict_items_iterator, + ootype.DictItemsIterator.KEYTYPE_T: types.dict_items_iterator.paramtype(0), + ootype.DictItemsIterator.VALUETYPE_T: types.dict_items_iterator.paramtype(1), } @@ -122,17 +207,14 @@ "readonly", "refanytype", "refanyval", "rem", "ret", "rethrow", "shl", "shr", "sizeof", "starg", "stelem", "stfld", "stind", "stloc", "stobj", "stsfld", "sub", "switch", "tail", "throw", - "unaligned", "unbox", "volatile", "xor"]) + "unaligned", "unbox", "volatile", "xor", "ole"]) + # ole is not a keyword, but mono ilasm fails if you use it as a field/method name + + types = types # for convenience def __init__(self, db): self.db = db - def __class(self, result, include_class): - if include_class: - return 'class ' + result - else: - return result - def escape_name(self, name): """Mangle then name if it's a ilasm reserved word""" if name in self.ILASM_KEYWORDS: @@ -140,46 +222,47 @@ else: return name - def lltype_to_cts(self, t, include_class=True): + def lltype_to_cts(self, t): if t is ootype.ROOT: - return self.__class('[mscorlib]System.Object', include_class) + return types.object elif isinstance(t, lltype.Ptr) and isinstance(t.TO, lltype.OpaqueType): - return self.__class('[mscorlib]System.Object', include_class) + return types.object elif isinstance(t, ootype.Instance): NATIVE_INSTANCE = t._hints.get('NATIVE_INSTANCE', None) if NATIVE_INSTANCE: - return self.__class(NATIVE_INSTANCE._name, include_class) + return CliClassType(None, NATIVE_INSTANCE._name) else: name = self.db.pending_class(t) - return self.__class(name, include_class) + return CliClassType(None, name) elif isinstance(t, ootype.Record): name = self.db.pending_record(t) - return self.__class(name, include_class) + return CliClassType(None, name) elif isinstance(t, ootype.StaticMethod): delegate = self.db.record_delegate(t) - return self.__class(delegate, include_class) + return CliClassType(None, delegate) elif isinstance(t, ootype.List): item_type = self.lltype_to_cts(t._ITEMTYPE) - if item_type == 'void': # special case: List of Void - return self.__class(PYPY_LIST_OF_VOID, include_class) - return self.__class(PYPY_LIST % item_type, include_class) + if item_type == types.void: # special case: List of Void + return types.list_of_void + return types.list.specialize(item_type) elif isinstance(t, ootype.Dict): key_type = self.lltype_to_cts(t._KEYTYPE) value_type = self.lltype_to_cts(t._VALUETYPE) - if value_type == 'void': # special cases: Dict with voids - if key_type == 'void': - return self.__class(PYPY_DICT_VOID_VOID, include_class) + if value_type == types.void: # special cases: Dict with voids + if key_type == types.void: + return types.dict_void_void else: - return self.__class(PYPY_DICT_OF_VOID % key_type, include_class) - return self.__class(PYPY_DICT % (key_type, value_type), include_class) + # XXX + return CliClassType(None, PYPY_DICT_OF_VOID % key_type) + return types.dict.specialize(key_type, value_type) elif isinstance(t, ootype.DictItemsIterator): key_type = self.lltype_to_cts(t._KEYTYPE) value_type = self.lltype_to_cts(t._VALUETYPE) - if key_type == 'void': - key_type = 'int32' # placeholder - if value_type == 'void': - value_type = 'int32' # placeholder - return self.__class(PYPY_DICT_ITEMS_ITERATOR % (key_type, value_type), include_class) + if key_type == types.void: + key_type = types.int32 # placeholder + if value_type == types.void: + value_type = types.int32 # placeholder + return types.dict_items_iterator.specialize(key_type, value_type) return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t) @@ -204,7 +287,7 @@ if is_method: args = args[1:] - arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args] + arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (ret_type, func_name, arg_list) @@ -216,7 +299,7 @@ args = [arg for arg in op.args[1:] if arg.concretetype is not ootype.Void] - arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args] + arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (ret_type, func_name, arg_list) @@ -235,9 +318,9 @@ METH = meth._TYPE virtual = getattr(meth, '_virtual', True) class_name = self.db.class_name(TYPE) - full_name = 'class %s::%s' % (class_name, name) + full_name = 'class %s::%s' % (class_name, self.escape_name(name)) returntype = self.lltype_to_cts(METH.RESULT) - arg_types = [self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void] + arg_types = [self.lltype_to_cts(ARG).typename() for ARG in METH.ARGS if ARG is not ootype.Void] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (returntype, full_name, arg_list), virtual @@ -255,16 +338,16 @@ name = name_or_desc if KEY is ootype.Void and VALUE is ootype.Void and name == 'll_get_items_iterator': # ugly, ugly special case - ret_type = 'class ' + PYPY_DICT_ITEMS_ITERATOR % ('int32', 'int32') + ret_type = types.dict_items_iterator.specialize(types.int32, types.int32) elif VALUE is ootype.Void and METH.RESULT is ootype.Dict.VALUETYPE_T: - ret_type = 'void' + ret_type = types.void else: ret_type = self.lltype_to_cts(METH.RESULT) ret_type = dict_of_void_ll_copy_hack(TYPE, ret_type) else: ret_type = self.lltype_to_cts(METH.RESULT) generic_types = getattr(TYPE, '_generic_types', {}) - arg_types = [self.lltype_to_cts(arg) for arg in METH.ARGS if + arg_types = [self.lltype_to_cts(arg).typename() for arg in METH.ARGS if arg is not ootype.Void and \ generic_types.get(arg, arg) is not ootype.Void] arg_list = ', '.join(arg_types) @@ -277,6 +360,6 @@ # XXX: ugly hack to make the ll_copy signature correct when # CustomDict is special-cased to DictOfVoid. if isinstance(TYPE, ootype.CustomDict) and TYPE._VALUETYPE is ootype.Void: - return ret_type.replace('Dict`2', 'DictOfVoid`2') + return ret_type.typename().replace('Dict`2', 'DictOfVoid`2') else: return ret_type Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py Mon Aug 27 14:55:29 2007 @@ -227,6 +227,49 @@ self.load(return_var) self.ilasm.opcode('ret') + def begin_try(self, cond): + if cond: + self.ilasm.begin_try() + + def end_try(self, target_label, cond): + if cond: + self.ilasm.leave(target_label) + self.ilasm.end_try() + else: + self.ilasm.branch(target_label) + + def begin_catch(self, llexitcase): + ll_meta_exc = llexitcase + ll_exc = ll_meta_exc._inst.class_._INSTANCE + cts_exc = self.cts.lltype_to_cts(ll_exc) + self.ilasm.begin_catch(cts_exc.classname()) + + def end_catch(self, target_label): + self.ilasm.leave(target_label) + self.ilasm.end_catch() + + def render_raise_block(self, block): + exc = block.inputargs[1] + self.load(exc) + self.ilasm.opcode('throw') + + def store_exception_and_link(self, link): + if self._is_raise_block(link.target): + # the exception value is on the stack, use it as the 2nd target arg + assert len(link.args) == 2 + assert len(link.target.inputargs) == 2 + self.store(link.target.inputargs[1]) + else: + # the exception value is on the stack, store it in the proper place + if isinstance(link.last_exception, flowmodel.Variable): + self.ilasm.opcode('dup') + self.store(link.last_exc_value) + self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) + self.store(link.last_exception) + else: + self.store(link.last_exc_value) + self._setup_link(link) + # XXX: this method should be moved into oosupport, but other # backends are not ready :-( def render_bool_switch(self, block): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py Mon Aug 27 14:55:29 2007 @@ -313,8 +313,8 @@ self.ilasm.call(signature) def cast_to(self, lltype): - cts_type = self.cts.lltype_to_cts(lltype, False) - self.ilasm.opcode('castclass', cts_type) + cts_type = self.cts.lltype_to_cts(lltype) + self.ilasm.opcode('castclass', cts_type.classname()) def new(self, obj): self.ilasm.new(self.cts.ctor_name(obj)) @@ -364,6 +364,9 @@ def branch_if_equal(self, target_label): self.ilasm.opcode('beq', target_label) + def branch_if_not_equal(self, target_label): + self.ilasm.opcode('bne.un', target_label) + def push_primitive_constant(self, TYPE, value): ilasm = self.ilasm if TYPE is ootype.Void: Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py Mon Aug 27 14:55:29 2007 @@ -38,7 +38,9 @@ self._load_arg_or_null(generator, func_arg) cts = generator.cts ret_type = cts.lltype_to_cts(funcdesc._TYPE.RESULT) - arg_types = [cts.lltype_to_cts(arg) for arg in funcdesc._TYPE.ARGS if arg is not ootype.Void] + arg_types = [cts.lltype_to_cts(arg).typename() + for arg in funcdesc._TYPE.ARGS + if arg is not ootype.Void] arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, funcdesc._cls._name, funcdesc._name, arg_list) generator.call_signature(signature) @@ -70,8 +72,10 @@ METH = this.concretetype._METHODS[method_name] cts = generator.cts ret_type = cts.lltype_to_cts(METH.RESULT) - arg_types = [cts.lltype_to_cts(arg) for arg in METH.ARGS if arg is not ootype.Void] - arg_types.insert(0, cts.lltype_to_cts(ootype.String)) + arg_types = [cts.lltype_to_cts(arg).typename() + for arg in METH.ARGS + if arg is not ootype.Void] + arg_types.insert(0, cts.lltype_to_cts(ootype.String).typename()) arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list) generator.call_signature(signature) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py Mon Aug 27 14:55:29 2007 @@ -30,7 +30,7 @@ for f_name, (FIELD_TYPE, f_default) in self.record._fields.iteritems(): f_name = self.cts.escape_name(f_name) cts_type = self.cts.lltype_to_cts(FIELD_TYPE) - if cts_type != 'void': + if cts_type != CTS.types.void: ilasm.field(f_name, cts_type) self._ctor() self._toString() @@ -74,13 +74,12 @@ def _equals(self): # field by field comparison - record_type = self.cts.lltype_to_cts(self.record, include_class=False) - class_record_type = self.cts.lltype_to_cts(self.record, include_class=True) + record_type = self.cts.lltype_to_cts(self.record) self.ilasm.begin_function('Equals', [('object', 'obj')], 'bool', False, 'virtual', 'instance', 'default') - self.ilasm.locals([(class_record_type, 'self')]) + self.ilasm.locals([(record_type, 'self')]) self.ilasm.opcode('ldarg.1') - self.ilasm.opcode('castclass', record_type) + self.ilasm.opcode('castclass', record_type.classname()) self.ilasm.opcode('stloc.0') equal = 'bool [pypylib]pypy.runtime.Utils::Equal<%s>(!!0, !!0)' @@ -91,9 +90,9 @@ f_type = self.cts.lltype_to_cts(FIELD_TYPE) f_name = self.cts.escape_name(f_name) self.ilasm.opcode('ldarg.0') - self.ilasm.get_field((f_type, record_type, f_name)) + self.ilasm.get_field((f_type, record_type.classname(), f_name)) self.ilasm.opcode('ldloc.0') - self.ilasm.get_field((f_type, record_type, f_name)) + self.ilasm.get_field((f_type, record_type.classname(), f_name)) self.ilasm.call(equal % f_type) self.ilasm.opcode('and') @@ -102,7 +101,7 @@ def _getHashCode(self): # return the hash of the first field. XXX: it can lead to a bad distribution - record_type = self.cts.lltype_to_cts(self.record, include_class=False) + record_type = self.cts.lltype_to_cts(self.record) self.ilasm.begin_function('GetHashCode', [], 'int32', False, 'virtual', 'instance', 'default') gethash = 'int32 [pypylib]pypy.runtime.Utils::GetHashCode<%s>(!!0)' if self.record._fields: @@ -113,7 +112,7 @@ f_name = self.cts.escape_name(f_name) f_type = self.cts.lltype_to_cts(FIELD_TYPE) self.ilasm.opcode('ldarg.0') - self.ilasm.get_field((f_type, record_type, f_name)) + self.ilasm.get_field((f_type, record_type.classname(), f_name)) self.ilasm.call(gethash % f_type) else: self.ilasm.opcode('ldc.i4.0') Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs Mon Aug 27 14:55:29 2007 @@ -201,7 +201,7 @@ public static int ll_strcmp(string s1, string s2) { - return string.Compare(s1, s2); + return string.Compare(s1, s2, StringComparison.Ordinal); } public static bool ll_startswith(string s1, string s2) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py Mon Aug 27 14:55:29 2007 @@ -53,7 +53,7 @@ RETURN_TYPE = self.graph.getreturnvar().concretetype return_type = self.cts.lltype_to_cts(RETURN_TYPE) - if return_type != 'void': + if return_type != CTS.types.void: ilasm.locals([(return_type, 'res')]) if self.wrap_exceptions: @@ -70,7 +70,7 @@ # call the function and convert the result to a string containing a valid python expression ilasm.call(self.cts.graph_to_signature(self.graph)) - if return_type != 'void': + if return_type != CTS.types.void: ilasm.opcode('stloc', 'res') if self.wrap_exceptions: ilasm.leave('check_last_exception') @@ -100,7 +100,7 @@ ilasm.opcode('br', 'return') ilasm.label('print_result') - if return_type != 'void': + if return_type != CTS.types.void: ilasm.opcode('ldloc', 'res') format_object(RETURN_TYPE, self.cts, ilasm) ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') @@ -112,13 +112,13 @@ def __convert_method(self, arg_type): _conv = { - 'int32': 'ToInt32', - 'unsigned int32': 'ToUInt32', - 'int64': 'ToInt64', - 'unsigned int64': 'ToUInt64', - 'bool': 'ToBoolean', - 'float64': 'ToDouble', - 'char': 'ToChar', + CTS.types.int32: 'ToInt32', + CTS.types.uint32: 'ToUInt32', + CTS.types.int64: 'ToInt64', + CTS.types.uint64: 'ToUInt64', + CTS.types.bool: 'ToBoolean', + CTS.types.float64: 'ToDouble', + CTS.types.char: 'ToChar', } try: Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py Mon Aug 27 14:55:29 2007 @@ -13,3 +13,31 @@ res = self.ll_to_list(self.interpret(fn, [])) assert res == [52, 53, 54] + def test_mangle(self): + class Foo: + def le(self): + return 42 + + def fn(): + f = Foo() + return f.le() + res = self.interpret(fn, [], backendopt=False) + + def test_link_vars_overlapping(self): + from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift + def fn(maxofs): + lastofs = 0 + ofs = 1 + while ofs < maxofs: + lastofs = ofs + try: + ofs = ovfcheck_lshift(ofs, 1) + except OverflowError: + ofs = maxofs + else: + ofs = ofs + 1 + return lastofs + res = self.interpret(fn, [64]) + expected = fn(64) + assert res == expected + Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py Mon Aug 27 14:55:29 2007 @@ -24,3 +24,8 @@ def test_getitem_exc(self): py.test.skip('fixme!') + def test_compare(self): + strings = ['aa', 'ZZ'] + def fn(i, j): + return strings[i] < strings[j] + assert self.interpret(fn, [0, 1], backendopt=False) == fn(0, 1) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py Mon Aug 27 14:55:29 2007 @@ -11,6 +11,8 @@ class Function(object): + + auto_propagate_exceptions = False def __init__(self, db, graph, name = None, is_method = False, is_entrypoint = False): self.db = db @@ -140,9 +142,17 @@ for op in block.operations[:-1]: self._render_op(op) + anyHandler = False + for link in block.exits: + if link.exitcase is None: + continue + if not self._is_raise_block(link.target): + anyHandler = True + anyHandler = anyHandler or not self.auto_propagate_exceptions + # render the last one (if any!) and prepend a .try if block.operations: - self.begin_try() + self.begin_try(anyHandler) self._render_op(block.operations[-1]) # search for the "default" block to be executed when no @@ -150,7 +160,7 @@ for link in block.exits: if link.exitcase is None: self._setup_link(link) - self.end_try(self._get_block_name(link.target)) + self.end_try(self._get_block_name(link.target), anyHandler) break else: assert False, "No non-exceptional case from exc_handling block" @@ -160,6 +170,8 @@ if link.exitcase is None: continue # see above assert issubclass(link.exitcase, py.builtin.BaseException) + if self._is_raise_block(link.target) and self.auto_propagate_exceptions: + continue # let the exception propagate ll_meta_exc = link.llexitcase self.record_ll_meta_exc(ll_meta_exc) self.begin_catch(link.llexitcase) @@ -218,13 +230,17 @@ def render_numeric_switch_naive(self, block): for link in block.exits: target_label = self._get_block_name(link.target) - self._setup_link(link) if link.exitcase == 'default': + self._setup_link(link) self.generator.branch_unconditionally(target_label) else: + next_case = self.next_label('next_case') self.generator.push_primitive_constant(block.exitswitch.concretetype, link.exitcase) self.generator.load(block.exitswitch) - self.generator.branch_if_equal(target_label) + self.generator.branch_if_not_equal(next_case) + self._setup_link(link) + self.generator.branch_unconditionally(target_label) + self.set_label(next_case) def _follow_link(self, link): target_label = self._get_block_name(link.target) @@ -233,20 +249,54 @@ def _setup_link(self, link): target = link.target + linkvars = [] for to_load, to_store in zip(link.args, target.inputargs): if isinstance(to_load, flowmodel.Variable) and to_load.name == to_store.name: continue if to_load.concretetype is ootype.Void: continue - self.generator.add_comment("%r --> %r" % (to_load, to_store)) + linkvars.append((to_load, to_store)) + + # after SSI_to_SSA it can happen to have to_load = [a, b] and + # to_store = [b, c]. If we store each variable sequentially, + # 'b' would be overwritten before being read. To solve, we + # first load all the values on the stack, then store in the + # appropriate places. + + if self._trace_enabled(): + self._trace('link', writeline=True) + for to_load, to_store in linkvars: + self._trace_value('%s <-- %s' % (to_store, to_load), to_load) + self._trace('', writeline=True) + + for to_load, to_store in linkvars: self.generator.load(to_load) + for to_load, to_store in reversed(linkvars): self.generator.store(to_store) + def _trace_enabled(self): + return False + + def _trace(self, s): + raise NotImplementedError + + def _trace_value(self, prompt, v): + raise NotImplementedError + def _render_op(self, op): instr_list = self.db.genoo.opcodes.get(op.opname, None) assert instr_list is not None, 'Unknown opcode: %s ' % op assert isinstance(instr_list, InstructionList) + + if self._trace_enabled(): + self._trace(str(op), writeline=True) + for i, arg in enumerate(op.args): + self._trace_value('Arg %02d' % i, arg) + instr_list.render(self.generator, op) + + if self._trace_enabled(): + self._trace_value('Result', op.result) def _render_sub_op(self, sub_op): op = sub_op.op Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py Mon Aug 27 14:55:29 2007 @@ -48,3 +48,16 @@ obj.x = x + y return obj.x assert self.interpret(fn, [1,3]) == 4 + + def test_link(self): + def fn(): + plus = False + for c in 'a': + if c == 'b': + plus = True + elif c == 'c': + binary = True + return plus + res = self.interpret(fn, []) + expected = fn() + assert res == expected From arigo at codespeak.net Mon Aug 27 15:23:58 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 27 Aug 2007 15:23:58 +0200 (CEST) Subject: [pypy-svn] r46022 - pypy/branch/pypy-more-rtti-inprogress/translator/c/test Message-ID: <20070827132358.E240781F2@code0.codespeak.net> Author: arigo Date: Mon Aug 27 15:23:56 2007 New Revision: 46022 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_lltyped.py Log: A (passing) test about the low-level cast_primitive operation. Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_lltyped.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_lltyped.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_lltyped.py Mon Aug 27 15:23:56 2007 @@ -305,3 +305,16 @@ fn = self.getcompiled(f, [int]) res = fn(10) assert res == 0 + + def test_cast_primitive(self): + def f(x): + x = cast_primitive(UnsignedLongLong, x) + x <<= 60 + x /= 3 + x <<= 1 + x = cast_primitive(SignedLongLong, x) + x >>= 32 + return cast_primitive(Signed, x) + fn = self.getcompiled(f, [int]) + res = fn(14) + assert res == -1789569707 From fijal at codespeak.net Mon Aug 27 15:30:16 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 27 Aug 2007 15:30:16 +0200 (CEST) Subject: [pypy-svn] r46023 - pypy/branch/pypy-more-rtti-inprogress/translator/c/test Message-ID: <20070827133016.5E93681F2@code0.codespeak.net> Author: fijal Date: Mon Aug 27 15:30:16 2007 New Revision: 46023 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py Log: Fix test Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py Mon Aug 27 15:30:16 2007 @@ -5,6 +5,7 @@ from pypy.objspace.flow.model import c_last_exception, summary from pypy.rpython.test.test_llinterp import get_interpreter from pypy.translator.c.test.test_genc import compile +from pypy.translator.backendopt.all import backend_optimizations from pypy import conftest import sys @@ -15,12 +16,14 @@ if not hasattr(sys, 'gettotalrefcount') and not conftest.option.view: py.test.skip("test needs a debug build of Python") -def transform_func(fn, inputtypes): +def transform_func(fn, inputtypes, backendopt=False): t = TranslationContext() t.buildannotator().build_types(fn, inputtypes) t.buildrtyper().specialize() if conftest.option.view: t.view() + if backendopt: + backend_optimizations(t) g = graphof(t, fn) etrafo = exceptiontransform.ExceptionTransformer(t) etrafo.create_exception_handling(g) @@ -213,7 +216,7 @@ y = z(x) return y + x - t,g = transform_func(f, [int]) + t,g = transform_func(f, [int], True) # llexternals normally should not raise, the graph should have no exception # checking assert summary(g) == {'int_gt': 1, 'int_add': 1, 'direct_call': 1} From antocuni at codespeak.net Mon Aug 27 15:51:15 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 15:51:15 +0200 (CEST) Subject: [pypy-svn] r46028 - in pypy/branch/pypy-more-rtti-inprogress: config jit/timeshifter rpython rpython/memory/gctransform/test rpython/test translator translator/c translator/c/test Message-ID: <20070827135115.A4E1081FC@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 15:51:13 2007 New Revision: 46028 Added: pypy/branch/pypy-more-rtti-inprogress/translator/exceptiontransform.py - copied, changed from r45508, pypy/dist/pypy/translator/exceptiontransform.py Removed: pypy/branch/pypy-more-rtti-inprogress/translator/c/exceptiontransform.py pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py pypy/branch/pypy-more-rtti-inprogress/jit/timeshifter/oop.py pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py pypy/branch/pypy-more-rtti-inprogress/rpython/memory/gctransform/test/test_transform.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_llinterp.py pypy/branch/pypy-more-rtti-inprogress/translator/translator.py Log: merge exceptiontransform from dist Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py Mon Aug 27 15:51:13 2007 @@ -196,8 +196,7 @@ OptionDescription("cli", "GenCLI options", [ BoolOption("trace_calls", "Trace function calls", default=False, - cmdline="--cli-trace-calls"), - BoolOption("exception_transformer", "Use exception transformer", default=False), + cmdline="--cli-trace-calls") ]), ]) Modified: pypy/branch/pypy-more-rtti-inprogress/jit/timeshifter/oop.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/jit/timeshifter/oop.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/jit/timeshifter/oop.py Mon Aug 27 15:51:13 2007 @@ -2,7 +2,7 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.jit.timeshifter.rcontainer import cachedtype from pypy.jit.timeshifter import rvalue, rtimeshift -from pypy.translator.c import exceptiontransform +from pypy.translator import exceptiontransform from pypy.rlib.unroll import unrolling_iterable from pypy.tool.sourcetools import func_with_new_name Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py Mon Aug 27 15:51:13 2007 @@ -312,7 +312,7 @@ tracer.dump('raise') exc_data.exc_type = lltype.typeOf(etype )._defl() exc_data.exc_value = lltype.typeOf(evalue)._defl() - from pypy.translator.c import exceptiontransform + from pypy.translator import exceptiontransform T = resultvar.concretetype errvalue = exceptiontransform.error_value(T) # check that the exc-transformed graph returns the error @@ -402,7 +402,7 @@ evalue = e.args[1] exc_data.exc_type = etype exc_data.exc_value = evalue - from pypy.translator.c import exceptiontransform + from pypy.translator import exceptiontransform retval = exceptiontransform.error_value( operation.result.concretetype) else: Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/memory/gctransform/test/test_transform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/memory/gctransform/test/test_transform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/memory/gctransform/test/test_transform.py Mon Aug 27 15:51:13 2007 @@ -3,7 +3,7 @@ from pypy.rpython.memory.gctransform.support import var_ispyobj from pypy.translator.backendopt.support import var_needsgc from pypy.translator.translator import TranslationContext, graphof -from pypy.translator.c.exceptiontransform import ExceptionTransformer +from pypy.translator.exceptiontransform import ExceptionTransformer from pypy.rpython.lltypesystem import lltype from pypy.objspace.flow.model import Variable from pypy.annotation import model as annmodel Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_llinterp.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_llinterp.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_llinterp.py Mon Aug 27 15:51:13 2007 @@ -514,7 +514,7 @@ res = interp.eval_graph(graph, [1]) def test_half_exceptiontransformed_graphs(): - from pypy.translator.c import exceptiontransform + from pypy.translator import exceptiontransform def f1(x): if x < 0: raise ValueError @@ -564,7 +564,7 @@ assert res == 7 def test_exceptiontransformed_add_ovf(): - from pypy.translator.c import exceptiontransform + from pypy.translator import exceptiontransform def f(x, y): try: return ovfcheck(x + y) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/translator.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/translator.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/translator.py Mon Aug 27 15:51:13 2007 @@ -111,7 +111,7 @@ raise ValueError("no rtyper") if self.exceptiontransformer is not None: return self.exceptiontransformer - from pypy.translator.c.exceptiontransform import ExceptionTransformer + from pypy.translator.exceptiontransform import ExceptionTransformer self.exceptiontransformer = ExceptionTransformer(self) return self.exceptiontransformer From antocuni at codespeak.net Mon Aug 27 16:00:57 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 16:00:57 +0200 (CEST) Subject: [pypy-svn] r46029 - pypy/branch/pypy-more-rtti-inprogress/translator/test Message-ID: <20070827140057.25FA281EF@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 16:00:56 2007 New Revision: 46029 Added: pypy/branch/pypy-more-rtti-inprogress/translator/test/test_exceptiontransform.py - copied unchanged from r46023, pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_exceptiontransform.py Log: restore this "poor test, lost in the dark" (cit.) From antocuni at codespeak.net Mon Aug 27 16:02:58 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 16:02:58 +0200 (CEST) Subject: [pypy-svn] r46030 - in pypy/branch/pypy-more-rtti-inprogress/translator: cli cli/src cli/test oosupport oosupport/test_template Message-ID: <20070827140258.2DE7E81EF@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 16:02:57 2007 New Revision: 46030 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py Log: revert commit 46021: I started merging from the wrong revision Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py Mon Aug 27 16:02:57 2007 @@ -84,7 +84,7 @@ for f_name, (f_type, f_default) in self.INSTANCE._fields.iteritems(): cts_type = self.cts.lltype_to_cts(f_type) f_name = self.cts.escape_name(f_name) - if cts_type != CTS.types.void: + if cts_type != 'void': ilasm.field(f_name, cts_type) self._ctor() @@ -134,7 +134,7 @@ INSTANCE_DEF, _ = self.INSTANCE._lookup_field(f_name) cts_type = self.cts.lltype_to_cts(F_TYPE) f_name = self.cts.escape_name(f_name) - if cts_type != CTS.types.void: + if cts_type != 'void': self.ilasm.opcode('ldarg.0') push_constant(self.db, F_TYPE, f_default, self.gen) class_name = self.db.class_name(INSTANCE_DEF) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py Mon Aug 27 16:02:57 2007 @@ -265,9 +265,9 @@ class CLIBaseConstMixin(object): """ A mix-in with a few extra methods the CLI backend uses """ - def get_type(self): + def get_type(self, include_class=True): """ Returns the CLI type for this constant's representation """ - return self.cts.lltype_to_cts(self.value._TYPE) + return self.cts.lltype_to_cts(self.value._TYPE, include_class) def push_inline(self, gen, TYPE): """ Overload the oosupport version so that we use the CLI opcode Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py Mon Aug 27 16:02:57 2007 @@ -4,146 +4,61 @@ import exceptions -from py.builtin import set +from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong from pypy.rpython.lltypesystem import lltype from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.llmemory import WeakGcAddress from pypy.translator.cli.option import getoption from pypy.translator.cli import oopspec +try: + set +except NameError: + from sets import Set as set + from pypy.tool.ansi_print import ansi_log import py log = py.log.Producer("cli") py.log.setconsumer("cli", ansi_log) -class CliType(object): - def typename(self): - raise NotImplementedError - - def __str__(self): - return self.typename() - - def __hash__(self): - return hash(self.typename()) - - def __eq__(self, other): - return self.typename() == other.typename() - - def __ne__(self, other): - return self.typename() != other.typename() - - -class CliPrimitiveType(CliType): - def __init__(self, name): - self.name = name - - def typename(self): - return self.name - - -class CliReferenceType(CliType): - def typename(self): - return 'class ' + self.classname() - - def classname(self): - raise NotImplementedError - - -class CliClassType(CliReferenceType): - def __init__(self, assembly, name): - self.assembly = assembly - self.name = name - - def classname(self): - if self.assembly: - return '[%s]%s' % (self.assembly, self.name) - else: - return self.name - - -class CliGenericType(CliReferenceType): - def __init__(self, assembly, name, numparam): - self.assembly = assembly - self.name = name - self.numparam = numparam - - def classname(self): - paramtypes = [self.paramtype(i) for i in range(self.numparam)] - thistype = self.specialize(*paramtypes) - return thistype.classname() - - def specialize(self, *types): - assert len(types) == self.numparam - return CliSpecializedType(self, types) - - def paramtype(self, num): - assert 0 <= num < self.numparam - return CliPrimitiveType('!%d' % num) - -class CliSpecializedType(CliReferenceType): - def __init__(self, generic_type, arg_types): - self.generic_type = generic_type - self.arg_types = arg_types - - def classname(self): - assembly = self.generic_type.assembly - name = self.generic_type.name - numparam = self.generic_type.numparam - arglist = ', '.join([arg.typename() for arg in self.arg_types]) - return '[%s]%s`%d<%s>' % (assembly, name, numparam, arglist) - - -T = CliPrimitiveType -class types: - void = T('void') - int32 = T('int32') - uint32 = T('unsigned int32') - int64 = T('int64') - uint64 = T('unsigned int64') - bool = T('bool') - float64 = T('float64') - char = T('char') - string = T('string') - - weakref = CliClassType('mscorlib', 'System.WeakReference') - type = CliClassType('mscorlib', 'System.Type') - object = CliClassType('mscorlib', 'System.Object') - list = CliGenericType('pypylib', 'pypy.runtime.List', 1) - list_of_void = CliClassType('pypylib', 'pypy.runtime.ListOfVoid') - dict = CliGenericType('pypylib', 'pypy.runtime.Dict', 2) - dict_void_void = CliClassType('pypylib', 'pypy.runtime.DictVoidVoid') - dict_items_iterator = CliGenericType('pypylib', 'pypy.runtime.DictItemsIterator', 2) - string_builder = CliClassType('pypylib', 'pypy.runtime.StringBuilder') -del T - -WEAKREF = types.weakref.classname() +WEAKREF = '[mscorlib]System.WeakReference' +PYPY_LIST = '[pypylib]pypy.runtime.List`1<%s>' +PYPY_LIST_OF_VOID = '[pypylib]pypy.runtime.ListOfVoid' +PYPY_DICT = '[pypylib]pypy.runtime.Dict`2<%s, %s>' PYPY_DICT_OF_VOID = '[pypylib]pypy.runtime.DictOfVoid`2<%s, int32>' - +PYPY_DICT_VOID_VOID = '[pypylib]pypy.runtime.DictVoidVoid' +PYPY_DICT_ITEMS_ITERATOR = '[pypylib]pypy.runtime.DictItemsIterator`2<%s, %s>' +PYPY_STRING_BUILDER = '[pypylib]pypy.runtime.StringBuilder' _lltype_to_cts = { - ootype.Void: types.void, - ootype.Signed: types.int32, - ootype.Unsigned: types.uint32, - ootype.SignedLongLong: types.int64, - ootype.UnsignedLongLong: types.uint64, - ootype.Bool: types.bool, - ootype.Float: types.float64, - ootype.Char: types.char, - ootype.UniChar: types.char, - ootype.Class: types.type, - ootype.String: types.string, - ootype.StringBuilder: types.string_builder, - WeakGcAddress: types.weakref, + ootype.Void: 'void', + ootype.Signed: 'int32', + ootype.Unsigned: 'unsigned int32', + SignedLongLong: 'int64', + UnsignedLongLong: 'unsigned int64', + ootype.Bool: 'bool', + ootype.Float: 'float64', + ootype.Char: 'char', + ootype.UniChar: 'char', + ootype.Class: 'class [mscorlib]System.Type', + ootype.String: 'string', + ootype.StringBuilder: 'class ' + PYPY_STRING_BUILDER, + WeakGcAddress: 'class ' + WEAKREF, # maps generic types to their ordinal - ootype.List.SELFTYPE_T: types.list, - ootype.List.ITEMTYPE_T: types.list.paramtype(0), - ootype.Dict.SELFTYPE_T: types.dict, - ootype.Dict.KEYTYPE_T: types.dict.paramtype(0), - ootype.Dict.VALUETYPE_T: types.dict.paramtype(1), - ootype.DictItemsIterator.SELFTYPE_T: types.dict_items_iterator, - ootype.DictItemsIterator.KEYTYPE_T: types.dict_items_iterator.paramtype(0), - ootype.DictItemsIterator.VALUETYPE_T: types.dict_items_iterator.paramtype(1), + ootype.List.SELFTYPE_T: 'class ' + (PYPY_LIST % '!0'), + ootype.List.ITEMTYPE_T: '!0', + ootype.Dict.SELFTYPE_T: 'class ' + (PYPY_DICT % ('!0', '!1')), + ootype.Dict.KEYTYPE_T: '!0', + ootype.Dict.VALUETYPE_T: '!1', + ootype.DictItemsIterator.SELFTYPE_T: 'class ' + (PYPY_DICT_ITEMS_ITERATOR % ('!0', '!1')), + ootype.DictItemsIterator.KEYTYPE_T: '!0', + ootype.DictItemsIterator.VALUETYPE_T: '!1', + } + +_pyexception_to_cts = { + exceptions.Exception: '[mscorlib]System.Exception', + exceptions.OverflowError: '[mscorlib]System.OverflowException' } @@ -207,14 +122,17 @@ "readonly", "refanytype", "refanyval", "rem", "ret", "rethrow", "shl", "shr", "sizeof", "starg", "stelem", "stfld", "stind", "stloc", "stobj", "stsfld", "sub", "switch", "tail", "throw", - "unaligned", "unbox", "volatile", "xor", "ole"]) - # ole is not a keyword, but mono ilasm fails if you use it as a field/method name - - types = types # for convenience + "unaligned", "unbox", "volatile", "xor"]) def __init__(self, db): self.db = db + def __class(self, result, include_class): + if include_class: + return 'class ' + result + else: + return result + def escape_name(self, name): """Mangle then name if it's a ilasm reserved word""" if name in self.ILASM_KEYWORDS: @@ -222,47 +140,46 @@ else: return name - def lltype_to_cts(self, t): + def lltype_to_cts(self, t, include_class=True): if t is ootype.ROOT: - return types.object + return self.__class('[mscorlib]System.Object', include_class) elif isinstance(t, lltype.Ptr) and isinstance(t.TO, lltype.OpaqueType): - return types.object + return self.__class('[mscorlib]System.Object', include_class) elif isinstance(t, ootype.Instance): NATIVE_INSTANCE = t._hints.get('NATIVE_INSTANCE', None) if NATIVE_INSTANCE: - return CliClassType(None, NATIVE_INSTANCE._name) + return self.__class(NATIVE_INSTANCE._name, include_class) else: name = self.db.pending_class(t) - return CliClassType(None, name) + return self.__class(name, include_class) elif isinstance(t, ootype.Record): name = self.db.pending_record(t) - return CliClassType(None, name) + return self.__class(name, include_class) elif isinstance(t, ootype.StaticMethod): delegate = self.db.record_delegate(t) - return CliClassType(None, delegate) + return self.__class(delegate, include_class) elif isinstance(t, ootype.List): item_type = self.lltype_to_cts(t._ITEMTYPE) - if item_type == types.void: # special case: List of Void - return types.list_of_void - return types.list.specialize(item_type) + if item_type == 'void': # special case: List of Void + return self.__class(PYPY_LIST_OF_VOID, include_class) + return self.__class(PYPY_LIST % item_type, include_class) elif isinstance(t, ootype.Dict): key_type = self.lltype_to_cts(t._KEYTYPE) value_type = self.lltype_to_cts(t._VALUETYPE) - if value_type == types.void: # special cases: Dict with voids - if key_type == types.void: - return types.dict_void_void + if value_type == 'void': # special cases: Dict with voids + if key_type == 'void': + return self.__class(PYPY_DICT_VOID_VOID, include_class) else: - # XXX - return CliClassType(None, PYPY_DICT_OF_VOID % key_type) - return types.dict.specialize(key_type, value_type) + return self.__class(PYPY_DICT_OF_VOID % key_type, include_class) + return self.__class(PYPY_DICT % (key_type, value_type), include_class) elif isinstance(t, ootype.DictItemsIterator): key_type = self.lltype_to_cts(t._KEYTYPE) value_type = self.lltype_to_cts(t._VALUETYPE) - if key_type == types.void: - key_type = types.int32 # placeholder - if value_type == types.void: - value_type = types.int32 # placeholder - return types.dict_items_iterator.specialize(key_type, value_type) + if key_type == 'void': + key_type = 'int32' # placeholder + if value_type == 'void': + value_type = 'int32' # placeholder + return self.__class(PYPY_DICT_ITEMS_ITERATOR % (key_type, value_type), include_class) return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t) @@ -287,7 +204,7 @@ if is_method: args = args[1:] - arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args] + arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (ret_type, func_name, arg_list) @@ -299,7 +216,7 @@ args = [arg for arg in op.args[1:] if arg.concretetype is not ootype.Void] - arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args] + arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (ret_type, func_name, arg_list) @@ -318,9 +235,9 @@ METH = meth._TYPE virtual = getattr(meth, '_virtual', True) class_name = self.db.class_name(TYPE) - full_name = 'class %s::%s' % (class_name, self.escape_name(name)) + full_name = 'class %s::%s' % (class_name, name) returntype = self.lltype_to_cts(METH.RESULT) - arg_types = [self.lltype_to_cts(ARG).typename() for ARG in METH.ARGS if ARG is not ootype.Void] + arg_types = [self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (returntype, full_name, arg_list), virtual @@ -338,16 +255,16 @@ name = name_or_desc if KEY is ootype.Void and VALUE is ootype.Void and name == 'll_get_items_iterator': # ugly, ugly special case - ret_type = types.dict_items_iterator.specialize(types.int32, types.int32) + ret_type = 'class ' + PYPY_DICT_ITEMS_ITERATOR % ('int32', 'int32') elif VALUE is ootype.Void and METH.RESULT is ootype.Dict.VALUETYPE_T: - ret_type = types.void + ret_type = 'void' else: ret_type = self.lltype_to_cts(METH.RESULT) ret_type = dict_of_void_ll_copy_hack(TYPE, ret_type) else: ret_type = self.lltype_to_cts(METH.RESULT) generic_types = getattr(TYPE, '_generic_types', {}) - arg_types = [self.lltype_to_cts(arg).typename() for arg in METH.ARGS if + arg_types = [self.lltype_to_cts(arg) for arg in METH.ARGS if arg is not ootype.Void and \ generic_types.get(arg, arg) is not ootype.Void] arg_list = ', '.join(arg_types) @@ -360,6 +277,6 @@ # XXX: ugly hack to make the ll_copy signature correct when # CustomDict is special-cased to DictOfVoid. if isinstance(TYPE, ootype.CustomDict) and TYPE._VALUETYPE is ootype.Void: - return ret_type.typename().replace('Dict`2', 'DictOfVoid`2') + return ret_type.replace('Dict`2', 'DictOfVoid`2') else: return ret_type Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py Mon Aug 27 16:02:57 2007 @@ -227,49 +227,6 @@ self.load(return_var) self.ilasm.opcode('ret') - def begin_try(self, cond): - if cond: - self.ilasm.begin_try() - - def end_try(self, target_label, cond): - if cond: - self.ilasm.leave(target_label) - self.ilasm.end_try() - else: - self.ilasm.branch(target_label) - - def begin_catch(self, llexitcase): - ll_meta_exc = llexitcase - ll_exc = ll_meta_exc._inst.class_._INSTANCE - cts_exc = self.cts.lltype_to_cts(ll_exc) - self.ilasm.begin_catch(cts_exc.classname()) - - def end_catch(self, target_label): - self.ilasm.leave(target_label) - self.ilasm.end_catch() - - def render_raise_block(self, block): - exc = block.inputargs[1] - self.load(exc) - self.ilasm.opcode('throw') - - def store_exception_and_link(self, link): - if self._is_raise_block(link.target): - # the exception value is on the stack, use it as the 2nd target arg - assert len(link.args) == 2 - assert len(link.target.inputargs) == 2 - self.store(link.target.inputargs[1]) - else: - # the exception value is on the stack, store it in the proper place - if isinstance(link.last_exception, flowmodel.Variable): - self.ilasm.opcode('dup') - self.store(link.last_exc_value) - self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) - self.store(link.last_exception) - else: - self.store(link.last_exc_value) - self._setup_link(link) - # XXX: this method should be moved into oosupport, but other # backends are not ready :-( def render_bool_switch(self, block): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py Mon Aug 27 16:02:57 2007 @@ -313,8 +313,8 @@ self.ilasm.call(signature) def cast_to(self, lltype): - cts_type = self.cts.lltype_to_cts(lltype) - self.ilasm.opcode('castclass', cts_type.classname()) + cts_type = self.cts.lltype_to_cts(lltype, False) + self.ilasm.opcode('castclass', cts_type) def new(self, obj): self.ilasm.new(self.cts.ctor_name(obj)) @@ -364,9 +364,6 @@ def branch_if_equal(self, target_label): self.ilasm.opcode('beq', target_label) - def branch_if_not_equal(self, target_label): - self.ilasm.opcode('bne.un', target_label) - def push_primitive_constant(self, TYPE, value): ilasm = self.ilasm if TYPE is ootype.Void: Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py Mon Aug 27 16:02:57 2007 @@ -38,9 +38,7 @@ self._load_arg_or_null(generator, func_arg) cts = generator.cts ret_type = cts.lltype_to_cts(funcdesc._TYPE.RESULT) - arg_types = [cts.lltype_to_cts(arg).typename() - for arg in funcdesc._TYPE.ARGS - if arg is not ootype.Void] + arg_types = [cts.lltype_to_cts(arg) for arg in funcdesc._TYPE.ARGS if arg is not ootype.Void] arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, funcdesc._cls._name, funcdesc._name, arg_list) generator.call_signature(signature) @@ -72,10 +70,8 @@ METH = this.concretetype._METHODS[method_name] cts = generator.cts ret_type = cts.lltype_to_cts(METH.RESULT) - arg_types = [cts.lltype_to_cts(arg).typename() - for arg in METH.ARGS - if arg is not ootype.Void] - arg_types.insert(0, cts.lltype_to_cts(ootype.String).typename()) + arg_types = [cts.lltype_to_cts(arg) for arg in METH.ARGS if arg is not ootype.Void] + arg_types.insert(0, cts.lltype_to_cts(ootype.String)) arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list) generator.call_signature(signature) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py Mon Aug 27 16:02:57 2007 @@ -30,7 +30,7 @@ for f_name, (FIELD_TYPE, f_default) in self.record._fields.iteritems(): f_name = self.cts.escape_name(f_name) cts_type = self.cts.lltype_to_cts(FIELD_TYPE) - if cts_type != CTS.types.void: + if cts_type != 'void': ilasm.field(f_name, cts_type) self._ctor() self._toString() @@ -74,12 +74,13 @@ def _equals(self): # field by field comparison - record_type = self.cts.lltype_to_cts(self.record) + record_type = self.cts.lltype_to_cts(self.record, include_class=False) + class_record_type = self.cts.lltype_to_cts(self.record, include_class=True) self.ilasm.begin_function('Equals', [('object', 'obj')], 'bool', False, 'virtual', 'instance', 'default') - self.ilasm.locals([(record_type, 'self')]) + self.ilasm.locals([(class_record_type, 'self')]) self.ilasm.opcode('ldarg.1') - self.ilasm.opcode('castclass', record_type.classname()) + self.ilasm.opcode('castclass', record_type) self.ilasm.opcode('stloc.0') equal = 'bool [pypylib]pypy.runtime.Utils::Equal<%s>(!!0, !!0)' @@ -90,9 +91,9 @@ f_type = self.cts.lltype_to_cts(FIELD_TYPE) f_name = self.cts.escape_name(f_name) self.ilasm.opcode('ldarg.0') - self.ilasm.get_field((f_type, record_type.classname(), f_name)) + self.ilasm.get_field((f_type, record_type, f_name)) self.ilasm.opcode('ldloc.0') - self.ilasm.get_field((f_type, record_type.classname(), f_name)) + self.ilasm.get_field((f_type, record_type, f_name)) self.ilasm.call(equal % f_type) self.ilasm.opcode('and') @@ -101,7 +102,7 @@ def _getHashCode(self): # return the hash of the first field. XXX: it can lead to a bad distribution - record_type = self.cts.lltype_to_cts(self.record) + record_type = self.cts.lltype_to_cts(self.record, include_class=False) self.ilasm.begin_function('GetHashCode', [], 'int32', False, 'virtual', 'instance', 'default') gethash = 'int32 [pypylib]pypy.runtime.Utils::GetHashCode<%s>(!!0)' if self.record._fields: @@ -112,7 +113,7 @@ f_name = self.cts.escape_name(f_name) f_type = self.cts.lltype_to_cts(FIELD_TYPE) self.ilasm.opcode('ldarg.0') - self.ilasm.get_field((f_type, record_type.classname(), f_name)) + self.ilasm.get_field((f_type, record_type, f_name)) self.ilasm.call(gethash % f_type) else: self.ilasm.opcode('ldc.i4.0') Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs Mon Aug 27 16:02:57 2007 @@ -201,7 +201,7 @@ public static int ll_strcmp(string s1, string s2) { - return string.Compare(s1, s2, StringComparison.Ordinal); + return string.Compare(s1, s2); } public static bool ll_startswith(string s1, string s2) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py Mon Aug 27 16:02:57 2007 @@ -53,7 +53,7 @@ RETURN_TYPE = self.graph.getreturnvar().concretetype return_type = self.cts.lltype_to_cts(RETURN_TYPE) - if return_type != CTS.types.void: + if return_type != 'void': ilasm.locals([(return_type, 'res')]) if self.wrap_exceptions: @@ -70,7 +70,7 @@ # call the function and convert the result to a string containing a valid python expression ilasm.call(self.cts.graph_to_signature(self.graph)) - if return_type != CTS.types.void: + if return_type != 'void': ilasm.opcode('stloc', 'res') if self.wrap_exceptions: ilasm.leave('check_last_exception') @@ -100,7 +100,7 @@ ilasm.opcode('br', 'return') ilasm.label('print_result') - if return_type != CTS.types.void: + if return_type != 'void': ilasm.opcode('ldloc', 'res') format_object(RETURN_TYPE, self.cts, ilasm) ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') @@ -112,13 +112,13 @@ def __convert_method(self, arg_type): _conv = { - CTS.types.int32: 'ToInt32', - CTS.types.uint32: 'ToUInt32', - CTS.types.int64: 'ToInt64', - CTS.types.uint64: 'ToUInt64', - CTS.types.bool: 'ToBoolean', - CTS.types.float64: 'ToDouble', - CTS.types.char: 'ToChar', + 'int32': 'ToInt32', + 'unsigned int32': 'ToUInt32', + 'int64': 'ToInt64', + 'unsigned int64': 'ToUInt64', + 'bool': 'ToBoolean', + 'float64': 'ToDouble', + 'char': 'ToChar', } try: Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py Mon Aug 27 16:02:57 2007 @@ -13,31 +13,3 @@ res = self.ll_to_list(self.interpret(fn, [])) assert res == [52, 53, 54] - def test_mangle(self): - class Foo: - def le(self): - return 42 - - def fn(): - f = Foo() - return f.le() - res = self.interpret(fn, [], backendopt=False) - - def test_link_vars_overlapping(self): - from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift - def fn(maxofs): - lastofs = 0 - ofs = 1 - while ofs < maxofs: - lastofs = ofs - try: - ofs = ovfcheck_lshift(ofs, 1) - except OverflowError: - ofs = maxofs - else: - ofs = ofs + 1 - return lastofs - res = self.interpret(fn, [64]) - expected = fn(64) - assert res == expected - Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py Mon Aug 27 16:02:57 2007 @@ -24,8 +24,3 @@ def test_getitem_exc(self): py.test.skip('fixme!') - def test_compare(self): - strings = ['aa', 'ZZ'] - def fn(i, j): - return strings[i] < strings[j] - assert self.interpret(fn, [0, 1], backendopt=False) == fn(0, 1) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py Mon Aug 27 16:02:57 2007 @@ -11,8 +11,6 @@ class Function(object): - - auto_propagate_exceptions = False def __init__(self, db, graph, name = None, is_method = False, is_entrypoint = False): self.db = db @@ -142,17 +140,9 @@ for op in block.operations[:-1]: self._render_op(op) - anyHandler = False - for link in block.exits: - if link.exitcase is None: - continue - if not self._is_raise_block(link.target): - anyHandler = True - anyHandler = anyHandler or not self.auto_propagate_exceptions - # render the last one (if any!) and prepend a .try if block.operations: - self.begin_try(anyHandler) + self.begin_try() self._render_op(block.operations[-1]) # search for the "default" block to be executed when no @@ -160,7 +150,7 @@ for link in block.exits: if link.exitcase is None: self._setup_link(link) - self.end_try(self._get_block_name(link.target), anyHandler) + self.end_try(self._get_block_name(link.target)) break else: assert False, "No non-exceptional case from exc_handling block" @@ -170,8 +160,6 @@ if link.exitcase is None: continue # see above assert issubclass(link.exitcase, py.builtin.BaseException) - if self._is_raise_block(link.target) and self.auto_propagate_exceptions: - continue # let the exception propagate ll_meta_exc = link.llexitcase self.record_ll_meta_exc(ll_meta_exc) self.begin_catch(link.llexitcase) @@ -230,17 +218,13 @@ def render_numeric_switch_naive(self, block): for link in block.exits: target_label = self._get_block_name(link.target) + self._setup_link(link) if link.exitcase == 'default': - self._setup_link(link) self.generator.branch_unconditionally(target_label) else: - next_case = self.next_label('next_case') self.generator.push_primitive_constant(block.exitswitch.concretetype, link.exitcase) self.generator.load(block.exitswitch) - self.generator.branch_if_not_equal(next_case) - self._setup_link(link) - self.generator.branch_unconditionally(target_label) - self.set_label(next_case) + self.generator.branch_if_equal(target_label) def _follow_link(self, link): target_label = self._get_block_name(link.target) @@ -249,54 +233,20 @@ def _setup_link(self, link): target = link.target - linkvars = [] for to_load, to_store in zip(link.args, target.inputargs): if isinstance(to_load, flowmodel.Variable) and to_load.name == to_store.name: continue if to_load.concretetype is ootype.Void: continue - linkvars.append((to_load, to_store)) - - # after SSI_to_SSA it can happen to have to_load = [a, b] and - # to_store = [b, c]. If we store each variable sequentially, - # 'b' would be overwritten before being read. To solve, we - # first load all the values on the stack, then store in the - # appropriate places. - - if self._trace_enabled(): - self._trace('link', writeline=True) - for to_load, to_store in linkvars: - self._trace_value('%s <-- %s' % (to_store, to_load), to_load) - self._trace('', writeline=True) - - for to_load, to_store in linkvars: + self.generator.add_comment("%r --> %r" % (to_load, to_store)) self.generator.load(to_load) - for to_load, to_store in reversed(linkvars): self.generator.store(to_store) - def _trace_enabled(self): - return False - - def _trace(self, s): - raise NotImplementedError - - def _trace_value(self, prompt, v): - raise NotImplementedError - def _render_op(self, op): instr_list = self.db.genoo.opcodes.get(op.opname, None) assert instr_list is not None, 'Unknown opcode: %s ' % op assert isinstance(instr_list, InstructionList) - - if self._trace_enabled(): - self._trace(str(op), writeline=True) - for i, arg in enumerate(op.args): - self._trace_value('Arg %02d' % i, arg) - instr_list.render(self.generator, op) - - if self._trace_enabled(): - self._trace_value('Result', op.result) def _render_sub_op(self, sub_op): op = sub_op.op Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py Mon Aug 27 16:02:57 2007 @@ -48,16 +48,3 @@ obj.x = x + y return obj.x assert self.interpret(fn, [1,3]) == 4 - - def test_link(self): - def fn(): - plus = False - for c in 'a': - if c == 'b': - plus = True - elif c == 'c': - binary = True - return plus - res = self.interpret(fn, []) - expected = fn() - assert res == expected From antocuni at codespeak.net Mon Aug 27 16:08:53 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 16:08:53 +0200 (CEST) Subject: [pypy-svn] r46032 - in pypy/branch/pypy-more-rtti-inprogress: config translator/cli translator/cli/src translator/cli/test translator/jvm translator/oosupport translator/oosupport/test_template Message-ID: <20070827140853.9D76A81F6@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 16:08:52 2007 New Revision: 46032 Removed: pypy/branch/pypy-more-rtti-inprogress/translator/cli/stackopt.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_stackopt.py Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/conftest.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/gencli.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/option.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/prebuiltnodes.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_dotnet.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_exception.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_runtest.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py pypy/branch/pypy-more-rtti-inprogress/translator/jvm/node.py pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py Log: merge translator/{cli,jvm,oosupport} and config from dist Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py Mon Aug 27 16:08:52 2007 @@ -196,7 +196,8 @@ OptionDescription("cli", "GenCLI options", [ BoolOption("trace_calls", "Trace function calls", default=False, - cmdline="--cli-trace-calls") + cmdline="--cli-trace-calls"), + BoolOption("exception_transformer", "Use exception transformer", default=False), ]), ]) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py Mon Aug 27 16:08:52 2007 @@ -84,7 +84,7 @@ for f_name, (f_type, f_default) in self.INSTANCE._fields.iteritems(): cts_type = self.cts.lltype_to_cts(f_type) f_name = self.cts.escape_name(f_name) - if cts_type != 'void': + if cts_type != CTS.types.void: ilasm.field(f_name, cts_type) self._ctor() @@ -134,7 +134,7 @@ INSTANCE_DEF, _ = self.INSTANCE._lookup_field(f_name) cts_type = self.cts.lltype_to_cts(F_TYPE) f_name = self.cts.escape_name(f_name) - if cts_type != 'void': + if cts_type != CTS.types.void: self.ilasm.opcode('ldarg.0') push_constant(self.db, F_TYPE, f_default, self.gen) class_name = self.db.class_name(INSTANCE_DEF) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/conftest.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/conftest.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/conftest.py Mon Aug 27 16:08:52 2007 @@ -26,8 +26,8 @@ Option('--norun', action='store_true', dest="norun", default=False, help="don't run the compiled executable"), - Option('--nostackopt', action='store_true', dest='nostackopt', default=False, - help="don't optimize stack load/store operations"), + Option('--trace', action='store_true', dest='trace', default=False, + help='Trace execution of generated code'), ) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py Mon Aug 27 16:08:52 2007 @@ -265,9 +265,9 @@ class CLIBaseConstMixin(object): """ A mix-in with a few extra methods the CLI backend uses """ - def get_type(self, include_class=True): + def get_type(self): """ Returns the CLI type for this constant's representation """ - return self.cts.lltype_to_cts(self.value._TYPE, include_class) + return self.cts.lltype_to_cts(self.value._TYPE) def push_inline(self, gen, TYPE): """ Overload the oosupport version so that we use the CLI opcode Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py Mon Aug 27 16:08:52 2007 @@ -4,61 +4,146 @@ import exceptions -from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong +from py.builtin import set from pypy.rpython.lltypesystem import lltype from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.llmemory import WeakGcAddress from pypy.translator.cli.option import getoption from pypy.translator.cli import oopspec -try: - set -except NameError: - from sets import Set as set - from pypy.tool.ansi_print import ansi_log import py log = py.log.Producer("cli") py.log.setconsumer("cli", ansi_log) -WEAKREF = '[mscorlib]System.WeakReference' -PYPY_LIST = '[pypylib]pypy.runtime.List`1<%s>' -PYPY_LIST_OF_VOID = '[pypylib]pypy.runtime.ListOfVoid' -PYPY_DICT = '[pypylib]pypy.runtime.Dict`2<%s, %s>' +class CliType(object): + def typename(self): + raise NotImplementedError + + def __str__(self): + return self.typename() + + def __hash__(self): + return hash(self.typename()) + + def __eq__(self, other): + return self.typename() == other.typename() + + def __ne__(self, other): + return self.typename() != other.typename() + + +class CliPrimitiveType(CliType): + def __init__(self, name): + self.name = name + + def typename(self): + return self.name + + +class CliReferenceType(CliType): + def typename(self): + return 'class ' + self.classname() + + def classname(self): + raise NotImplementedError + + +class CliClassType(CliReferenceType): + def __init__(self, assembly, name): + self.assembly = assembly + self.name = name + + def classname(self): + if self.assembly: + return '[%s]%s' % (self.assembly, self.name) + else: + return self.name + + +class CliGenericType(CliReferenceType): + def __init__(self, assembly, name, numparam): + self.assembly = assembly + self.name = name + self.numparam = numparam + + def classname(self): + paramtypes = [self.paramtype(i) for i in range(self.numparam)] + thistype = self.specialize(*paramtypes) + return thistype.classname() + + def specialize(self, *types): + assert len(types) == self.numparam + return CliSpecializedType(self, types) + + def paramtype(self, num): + assert 0 <= num < self.numparam + return CliPrimitiveType('!%d' % num) + +class CliSpecializedType(CliReferenceType): + def __init__(self, generic_type, arg_types): + self.generic_type = generic_type + self.arg_types = arg_types + + def classname(self): + assembly = self.generic_type.assembly + name = self.generic_type.name + numparam = self.generic_type.numparam + arglist = ', '.join([arg.typename() for arg in self.arg_types]) + return '[%s]%s`%d<%s>' % (assembly, name, numparam, arglist) + + +T = CliPrimitiveType +class types: + void = T('void') + int32 = T('int32') + uint32 = T('unsigned int32') + int64 = T('int64') + uint64 = T('unsigned int64') + bool = T('bool') + float64 = T('float64') + char = T('char') + string = T('string') + + weakref = CliClassType('mscorlib', 'System.WeakReference') + type = CliClassType('mscorlib', 'System.Type') + object = CliClassType('mscorlib', 'System.Object') + list = CliGenericType('pypylib', 'pypy.runtime.List', 1) + list_of_void = CliClassType('pypylib', 'pypy.runtime.ListOfVoid') + dict = CliGenericType('pypylib', 'pypy.runtime.Dict', 2) + dict_void_void = CliClassType('pypylib', 'pypy.runtime.DictVoidVoid') + dict_items_iterator = CliGenericType('pypylib', 'pypy.runtime.DictItemsIterator', 2) + string_builder = CliClassType('pypylib', 'pypy.runtime.StringBuilder') +del T + +WEAKREF = types.weakref.classname() PYPY_DICT_OF_VOID = '[pypylib]pypy.runtime.DictOfVoid`2<%s, int32>' -PYPY_DICT_VOID_VOID = '[pypylib]pypy.runtime.DictVoidVoid' -PYPY_DICT_ITEMS_ITERATOR = '[pypylib]pypy.runtime.DictItemsIterator`2<%s, %s>' -PYPY_STRING_BUILDER = '[pypylib]pypy.runtime.StringBuilder' + _lltype_to_cts = { - ootype.Void: 'void', - ootype.Signed: 'int32', - ootype.Unsigned: 'unsigned int32', - SignedLongLong: 'int64', - UnsignedLongLong: 'unsigned int64', - ootype.Bool: 'bool', - ootype.Float: 'float64', - ootype.Char: 'char', - ootype.UniChar: 'char', - ootype.Class: 'class [mscorlib]System.Type', - ootype.String: 'string', - ootype.StringBuilder: 'class ' + PYPY_STRING_BUILDER, - WeakGcAddress: 'class ' + WEAKREF, + ootype.Void: types.void, + ootype.Signed: types.int32, + ootype.Unsigned: types.uint32, + ootype.SignedLongLong: types.int64, + ootype.UnsignedLongLong: types.uint64, + ootype.Bool: types.bool, + ootype.Float: types.float64, + ootype.Char: types.char, + ootype.UniChar: types.char, + ootype.Class: types.type, + ootype.String: types.string, + ootype.StringBuilder: types.string_builder, + WeakGcAddress: types.weakref, # maps generic types to their ordinal - ootype.List.SELFTYPE_T: 'class ' + (PYPY_LIST % '!0'), - ootype.List.ITEMTYPE_T: '!0', - ootype.Dict.SELFTYPE_T: 'class ' + (PYPY_DICT % ('!0', '!1')), - ootype.Dict.KEYTYPE_T: '!0', - ootype.Dict.VALUETYPE_T: '!1', - ootype.DictItemsIterator.SELFTYPE_T: 'class ' + (PYPY_DICT_ITEMS_ITERATOR % ('!0', '!1')), - ootype.DictItemsIterator.KEYTYPE_T: '!0', - ootype.DictItemsIterator.VALUETYPE_T: '!1', - } - -_pyexception_to_cts = { - exceptions.Exception: '[mscorlib]System.Exception', - exceptions.OverflowError: '[mscorlib]System.OverflowException' + ootype.List.SELFTYPE_T: types.list, + ootype.List.ITEMTYPE_T: types.list.paramtype(0), + ootype.Dict.SELFTYPE_T: types.dict, + ootype.Dict.KEYTYPE_T: types.dict.paramtype(0), + ootype.Dict.VALUETYPE_T: types.dict.paramtype(1), + ootype.DictItemsIterator.SELFTYPE_T: types.dict_items_iterator, + ootype.DictItemsIterator.KEYTYPE_T: types.dict_items_iterator.paramtype(0), + ootype.DictItemsIterator.VALUETYPE_T: types.dict_items_iterator.paramtype(1), } @@ -122,17 +207,14 @@ "readonly", "refanytype", "refanyval", "rem", "ret", "rethrow", "shl", "shr", "sizeof", "starg", "stelem", "stfld", "stind", "stloc", "stobj", "stsfld", "sub", "switch", "tail", "throw", - "unaligned", "unbox", "volatile", "xor"]) + "unaligned", "unbox", "volatile", "xor", "ole"]) + # ole is not a keyword, but mono ilasm fails if you use it as a field/method name + + types = types # for convenience def __init__(self, db): self.db = db - def __class(self, result, include_class): - if include_class: - return 'class ' + result - else: - return result - def escape_name(self, name): """Mangle then name if it's a ilasm reserved word""" if name in self.ILASM_KEYWORDS: @@ -140,46 +222,47 @@ else: return name - def lltype_to_cts(self, t, include_class=True): + def lltype_to_cts(self, t): if t is ootype.ROOT: - return self.__class('[mscorlib]System.Object', include_class) + return types.object elif isinstance(t, lltype.Ptr) and isinstance(t.TO, lltype.OpaqueType): - return self.__class('[mscorlib]System.Object', include_class) + return types.object elif isinstance(t, ootype.Instance): NATIVE_INSTANCE = t._hints.get('NATIVE_INSTANCE', None) if NATIVE_INSTANCE: - return self.__class(NATIVE_INSTANCE._name, include_class) + return CliClassType(None, NATIVE_INSTANCE._name) else: name = self.db.pending_class(t) - return self.__class(name, include_class) + return CliClassType(None, name) elif isinstance(t, ootype.Record): name = self.db.pending_record(t) - return self.__class(name, include_class) + return CliClassType(None, name) elif isinstance(t, ootype.StaticMethod): delegate = self.db.record_delegate(t) - return self.__class(delegate, include_class) + return CliClassType(None, delegate) elif isinstance(t, ootype.List): item_type = self.lltype_to_cts(t._ITEMTYPE) - if item_type == 'void': # special case: List of Void - return self.__class(PYPY_LIST_OF_VOID, include_class) - return self.__class(PYPY_LIST % item_type, include_class) + if item_type == types.void: # special case: List of Void + return types.list_of_void + return types.list.specialize(item_type) elif isinstance(t, ootype.Dict): key_type = self.lltype_to_cts(t._KEYTYPE) value_type = self.lltype_to_cts(t._VALUETYPE) - if value_type == 'void': # special cases: Dict with voids - if key_type == 'void': - return self.__class(PYPY_DICT_VOID_VOID, include_class) + if value_type == types.void: # special cases: Dict with voids + if key_type == types.void: + return types.dict_void_void else: - return self.__class(PYPY_DICT_OF_VOID % key_type, include_class) - return self.__class(PYPY_DICT % (key_type, value_type), include_class) + # XXX + return CliClassType(None, PYPY_DICT_OF_VOID % key_type) + return types.dict.specialize(key_type, value_type) elif isinstance(t, ootype.DictItemsIterator): key_type = self.lltype_to_cts(t._KEYTYPE) value_type = self.lltype_to_cts(t._VALUETYPE) - if key_type == 'void': - key_type = 'int32' # placeholder - if value_type == 'void': - value_type = 'int32' # placeholder - return self.__class(PYPY_DICT_ITEMS_ITERATOR % (key_type, value_type), include_class) + if key_type == types.void: + key_type = types.int32 # placeholder + if value_type == types.void: + value_type = types.int32 # placeholder + return types.dict_items_iterator.specialize(key_type, value_type) return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t) @@ -204,7 +287,7 @@ if is_method: args = args[1:] - arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args] + arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (ret_type, func_name, arg_list) @@ -216,7 +299,7 @@ args = [arg for arg in op.args[1:] if arg.concretetype is not ootype.Void] - arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args] + arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (ret_type, func_name, arg_list) @@ -235,9 +318,9 @@ METH = meth._TYPE virtual = getattr(meth, '_virtual', True) class_name = self.db.class_name(TYPE) - full_name = 'class %s::%s' % (class_name, name) + full_name = 'class %s::%s' % (class_name, self.escape_name(name)) returntype = self.lltype_to_cts(METH.RESULT) - arg_types = [self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void] + arg_types = [self.lltype_to_cts(ARG).typename() for ARG in METH.ARGS if ARG is not ootype.Void] arg_list = ', '.join(arg_types) return '%s %s(%s)' % (returntype, full_name, arg_list), virtual @@ -255,16 +338,16 @@ name = name_or_desc if KEY is ootype.Void and VALUE is ootype.Void and name == 'll_get_items_iterator': # ugly, ugly special case - ret_type = 'class ' + PYPY_DICT_ITEMS_ITERATOR % ('int32', 'int32') + ret_type = types.dict_items_iterator.specialize(types.int32, types.int32) elif VALUE is ootype.Void and METH.RESULT is ootype.Dict.VALUETYPE_T: - ret_type = 'void' + ret_type = types.void else: ret_type = self.lltype_to_cts(METH.RESULT) ret_type = dict_of_void_ll_copy_hack(TYPE, ret_type) else: ret_type = self.lltype_to_cts(METH.RESULT) generic_types = getattr(TYPE, '_generic_types', {}) - arg_types = [self.lltype_to_cts(arg) for arg in METH.ARGS if + arg_types = [self.lltype_to_cts(arg).typename() for arg in METH.ARGS if arg is not ootype.Void and \ generic_types.get(arg, arg) is not ootype.Void] arg_list = ', '.join(arg_types) @@ -277,6 +360,6 @@ # XXX: ugly hack to make the ll_copy signature correct when # CustomDict is special-cased to DictOfVoid. if isinstance(TYPE, ootype.CustomDict) and TYPE._VALUETYPE is ootype.Void: - return ret_type.replace('Dict`2', 'DictOfVoid`2') + return ret_type.typename().replace('Dict`2', 'DictOfVoid`2') else: return ret_type Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py Mon Aug 27 16:08:52 2007 @@ -18,163 +18,17 @@ from pypy.translator.cli.support import log from pypy.translator.cli.ilgenerator import CLIBaseGenerator -USE_LAST = False +class Function(OOFunction, Node, CLIBaseGenerator): -class NativeExceptionHandler(object): - def begin_try(self): - self.ilasm.begin_try() - - def end_try(self, target_label): - self.ilasm.leave(target_label) - self.ilasm.end_try() - - def begin_catch(self, llexitcase): - ll_meta_exc = llexitcase - ll_exc = ll_meta_exc._inst.class_._INSTANCE - cts_exc = self.cts.lltype_to_cts(ll_exc, False) - self.ilasm.begin_catch(cts_exc) - - def end_catch(self, target_label): - self.ilasm.leave(target_label) - self.ilasm.end_catch() - - def render_raise_block(self, block): - exc = block.inputargs[1] - self.load(exc) - self.ilasm.opcode('throw') - - def store_exception_and_link(self, link): - if self._is_raise_block(link.target): - # the exception value is on the stack, use it as the 2nd target arg - assert len(link.args) == 2 - assert len(link.target.inputargs) == 2 - self.store(link.target.inputargs[1]) - else: - # the exception value is on the stack, store it in the proper place - if isinstance(link.last_exception, flowmodel.Variable): - self.ilasm.opcode('dup') - self.store(link.last_exc_value) - self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) - self.store(link.last_exception) - else: - self.store(link.last_exc_value) - self._setup_link(link) - -class LastExceptionHandler(object): - in_try = False - - def begin_try(self): - self.in_try = True - self.ilasm.opcode('// begin_try') - - def end_try(self, target_label): - self.ilasm.opcode('ldsfld', 'object last_exception') - self.ilasm.opcode('brnull', target_label) - self.ilasm.opcode('// end try') - self.in_try = False - - def begin_catch(self, llexitcase): - self.ilasm.label(self.current_label('catch')) - ll_meta_exc = llexitcase - ll_exc = ll_meta_exc._inst.class_._INSTANCE - cts_exc = self.cts.lltype_to_cts(ll_exc, False) - self.ilasm.opcode('ldsfld', 'object last_exception') - self.isinstance(cts_exc) - self.ilasm.opcode('dup') - self.ilasm.opcode('brtrue.s', 6) - self.ilasm.opcode('pop') - self.ilasm.opcode('br', self.next_label('catch')) - # here is the target of the above brtrue.s - self.ilasm.opcode('ldnull') - self.ilasm.opcode('stsfld', 'object last_exception') - - def end_catch(self, target_label): - self.ilasm.opcode('br', target_label) - - def store_exception_and_link(self, link): - if self._is_raise_block(link.target): - # the exception value is on the stack, use it as the 2nd target arg - assert len(link.args) == 2 - assert len(link.target.inputargs) == 2 - self.store(link.target.inputargs[1]) - else: - # the exception value is on the stack, store it in the proper place - if isinstance(link.last_exception, flowmodel.Variable): - self.ilasm.opcode('dup') - self.store(link.last_exc_value) - self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) - self.store(link.last_exception) - else: - self.store(link.last_exc_value) - self._setup_link(link) - - def before_last_blocks(self): - self.ilasm.label(self.current_label('catch')) - self.ilasm.opcode('nop') - - def render_raise_block(self, block): - exc = block.inputargs[1] - self.load(exc) - self.ilasm.opcode('stsfld', 'object last_exception') - if not self.return_block: # must be a void function - TYPE = self.graph.getreturnvar().concretetype - default = TYPE._defl() - if default is not None: # concretetype is Void - try: - self.db.constant_generator.push_primitive_constant(self, TYPE, default) - except AssertionError: - self.ilasm.opcode('ldnull') # :-( - self.ilasm.opcode('ret') - else: - self.ilasm.opcode('br', self._get_block_name(self.return_block)) - - def _render_op(self, op): - OOFunction._render_op(self, op) - if op.opname in ('direct_call', 'oosend', 'indirect_call') and not self.in_try: - self._premature_return() - - def _render_sub_op(self, sub_op): - OOFunction._render_sub_op(self, sub_op) - if sub_op.op.opname in ('direct_call', 'oosend', 'indirect_call') and not self.in_try: - self._premature_return(need_pop=sub_op.op.result is not ootype.Void) - - - def _premature_return(self, need_pop=False): - try: - return_block = self._get_block_name(self.graph.returnblock) - except KeyError: - self.ilasm.opcode('//premature return') - self.ilasm.opcode('ldsfld', 'object last_exception') - TYPE = self.graph.getreturnvar().concretetype - default = TYPE._defl() - if default is None: # concretetype is Void - self.ilasm.opcode('brfalse.s', 1) - self.ilasm.opcode('ret') - else: - self.ilasm.opcode('brfalse.s', 3) # ?? - try: - self.db.constant_generator.push_primitive_constant(self, TYPE, default) - except AssertionError: - self.ilasm.opcode('ldnull') # :-( - self.ilasm.opcode('ret') - else: - self.ilasm.opcode('ldsfld', 'object last_exception') - self.ilasm.opcode('brtrue', return_block) - - -if USE_LAST: - ExceptionHandler = LastExceptionHandler -else: - ExceptionHandler = NativeExceptionHandler - -class Function(ExceptionHandler, OOFunction, Node, CLIBaseGenerator): + auto_propagate_exceptions = True def __init__(self, *args, **kwargs): OOFunction.__init__(self, *args, **kwargs) - self._set_args() - self._set_locals() + + if hasattr(self.db.genoo, 'exceptiontransformer'): + self.auto_propagate_exceptions = False + namespace = getattr(self.graph.func, '_namespace_', None) - str if namespace: if '.' in namespace: self.namespace, self.classname = namespace.rsplit('.', 1) @@ -195,7 +49,25 @@ if NATIVE_INSTANCE is None: OOFunction.record_ll_meta_exc(self, ll_meta_exc) + def _trace_enabled(self): + return getoption('trace') + + def _trace(self, s, writeline=False): + self.ilasm.stderr(s, writeline=writeline) + + def _trace_value(self, prompt, v): + self.ilasm.stderr(' ' + prompt + ': ', writeline=False) + self.ilasm.load_stderr() + self.load(v) + if v.concretetype is not ootype.String: + from pypy.translator.cli.test.runtest import format_object + format_object(v.concretetype, self.cts, self.ilasm) + self.ilasm.write_stderr() + def begin_render(self): + self._set_args() + self._set_locals() + returntype, returnvar = self.cts.llvar_to_cts(self.graph.getreturnvar()) if self.is_method: args = self.args[1:] # self is implicit @@ -227,6 +99,49 @@ self.load(return_var) self.ilasm.opcode('ret') + def begin_try(self, cond): + if cond: + self.ilasm.begin_try() + + def end_try(self, target_label, cond): + if cond: + self.ilasm.leave(target_label) + self.ilasm.end_try() + else: + self.ilasm.branch(target_label) + + def begin_catch(self, llexitcase): + ll_meta_exc = llexitcase + ll_exc = ll_meta_exc._inst.class_._INSTANCE + cts_exc = self.cts.lltype_to_cts(ll_exc) + self.ilasm.begin_catch(cts_exc.classname()) + + def end_catch(self, target_label): + self.ilasm.leave(target_label) + self.ilasm.end_catch() + + def render_raise_block(self, block): + exc = block.inputargs[1] + self.load(exc) + self.ilasm.opcode('throw') + + def store_exception_and_link(self, link): + if self._is_raise_block(link.target): + # the exception value is on the stack, use it as the 2nd target arg + assert len(link.args) == 2 + assert len(link.target.inputargs) == 2 + self.store(link.target.inputargs[1]) + else: + # the exception value is on the stack, store it in the proper place + if isinstance(link.last_exception, flowmodel.Variable): + self.ilasm.opcode('dup') + self.store(link.last_exc_value) + self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) + self.store(link.last_exception) + else: + self.store(link.last_exc_value) + self._setup_link(link) + # XXX: this method should be moved into oosupport, but other # backends are not ready :-( def render_bool_switch(self, block): @@ -239,7 +154,7 @@ true_label = self.next_label('link_true') self.generator.load(block.exitswitch) - self.generator.branch_conditionally(link.exitcase, true_label) + self.generator.branch_conditionally(True, true_label) self._follow_link(link_false) # if here, the exitswitch is false self.set_label(true_label) self._follow_link(link_true) # if here, the exitswitch is true Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/gencli.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/gencli.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/gencli.py Mon Aug 27 16:08:52 2007 @@ -19,7 +19,6 @@ from pypy.translator.cli.rte import get_pypy_dll from pypy.translator.cli.support import Tee from pypy.translator.cli.prebuiltnodes import get_prebuilt_nodes -from pypy.translator.cli.stackopt import StackOptGenerator from pypy.translator.cli import query from pypy.translator.cli import constant @@ -28,10 +27,6 @@ except NameError: from sets import Set as set -#USE_STACKOPT = True and not getoption('nostackopt') -USE_STACKOPT = False - - class GenCli(GenOO): TypeSystem = CTS Function = Function @@ -49,14 +44,23 @@ DictConst = constant.CLIDictConst WeakRefConst = constant.CLIWeakRefConst - def __init__(self, tmpdir, translator, entrypoint, config=None): + def __init__(self, tmpdir, translator, entrypoint, config=None, exctrans=False): GenOO.__init__(self, tmpdir, translator, entrypoint, config) + exctrans = exctrans or translator.config.translation.cli.exception_transformer + if exctrans: + self.db.exceptiontransformer = translator.getexceptiontransformer() + for node in get_prebuilt_nodes(translator, self.db): self.db.pending_node(node) self.assembly_name = entrypoint.get_name() self.tmpfile = tmpdir.join(self.assembly_name + '.il') self.const_stat = str(tmpdir.join('const_stat')) + if exctrans: + etrafo = self.db.exceptiontransformer + for graph in translator.graphs: + etrafo.create_exception_handling(graph) + if translator.config.translation.backendopt.stack_optimization: for graph in translator.graphs: SSI_to_SSA(graph) @@ -72,12 +76,8 @@ out = self.tmpfile.open('w') if getoption('stdout'): out = Tee(sys.stdout, out) - - if USE_STACKOPT: - return StackOptGenerator(out, self.assembly_name, self.config) - else: - isnetmodule = self.entrypoint.isnetmodule - return IlasmGenerator(out, self.assembly_name, self.config, isnetmodule) + isnetmodule = self.entrypoint.isnetmodule + return IlasmGenerator(out, self.assembly_name, self.config, isnetmodule) def build_exe(self): if getoption('source'): Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py Mon Aug 27 16:08:52 2007 @@ -58,7 +58,6 @@ self.code.writeline('.module %s.netmodule' % name) else: self.code.writeline('.assembly %s {}' % name) - self.code.writeline('.field static object last_exception') # XXX def close(self): self.out.close() @@ -252,12 +251,22 @@ self.code.write(opcode + ' ') self.code.writeline(' '.join(map(str, args))) - def stderr(self, msg, cond=True): + def stderr(self, msg, cond=True, writeline=True): from pypy.translator.cli.support import string_literal if cond: - self.call('class [mscorlib]System.IO.TextWriter class [mscorlib]System.Console::get_Error()') + self.load_stderr() self.opcode('ldstr', string_literal(msg)) - self.call_method('void class [mscorlib]System.IO.TextWriter::WriteLine(string)', virtual=True) + self.write_stderr(writeline) + + def load_stderr(self): + self.call('class [mscorlib]System.IO.TextWriter class [mscorlib]System.Console::get_Error()') + + def write_stderr(self, writeline=True): + if writeline: + meth = 'WriteLine' + else: + meth = 'Write' + self.call_method('void class [mscorlib]System.IO.TextWriter::%s(string)' % meth, virtual=True) def add_comment(self, text): self.code.writeline('// %s' % text) @@ -313,8 +322,8 @@ self.ilasm.call(signature) def cast_to(self, lltype): - cts_type = self.cts.lltype_to_cts(lltype, False) - self.ilasm.opcode('castclass', cts_type) + cts_type = self.cts.lltype_to_cts(lltype) + self.ilasm.opcode('castclass', cts_type.classname()) def new(self, obj): self.ilasm.new(self.cts.ctor_name(obj)) @@ -364,6 +373,9 @@ def branch_if_equal(self, target_label): self.ilasm.opcode('beq', target_label) + def branch_if_not_equal(self, target_label): + self.ilasm.opcode('bne.un', target_label) + def push_primitive_constant(self, TYPE, value): ilasm = self.ilasm if TYPE is ootype.Void: Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py Mon Aug 27 16:08:52 2007 @@ -38,7 +38,9 @@ self._load_arg_or_null(generator, func_arg) cts = generator.cts ret_type = cts.lltype_to_cts(funcdesc._TYPE.RESULT) - arg_types = [cts.lltype_to_cts(arg) for arg in funcdesc._TYPE.ARGS if arg is not ootype.Void] + arg_types = [cts.lltype_to_cts(arg).typename() + for arg in funcdesc._TYPE.ARGS + if arg is not ootype.Void] arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, funcdesc._cls._name, funcdesc._name, arg_list) generator.call_signature(signature) @@ -70,8 +72,10 @@ METH = this.concretetype._METHODS[method_name] cts = generator.cts ret_type = cts.lltype_to_cts(METH.RESULT) - arg_types = [cts.lltype_to_cts(arg) for arg in METH.ARGS if arg is not ootype.Void] - arg_types.insert(0, cts.lltype_to_cts(ootype.String)) + arg_types = [cts.lltype_to_cts(arg).typename() + for arg in METH.ARGS + if arg is not ootype.Void] + arg_types.insert(0, cts.lltype_to_cts(ootype.String).typename()) arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list) generator.call_signature(signature) @@ -159,13 +163,6 @@ self.mapping = mapping def render(self, generator, op): - from pypy.translator.cli.function import LastExceptionHandler - if isinstance(generator, LastExceptionHandler): - self.render_last(generator, op) - else: - self.render_native(generator, op) - - def render_native(self, generator, op): ilasm = generator.ilasm label = '__check_block_%d' % MapException.COUNT MapException.COUNT += 1 @@ -181,25 +178,6 @@ ilasm.label(label) ilasm.opcode('nop') - def render_last(self, generator, op): - ilasm = generator.ilasm - stdflow = '__check_block_%d' % MapException.COUNT - MapException.COUNT += 1 - premature_return = '__check_block_%d' % MapException.COUNT - MapException.COUNT += 1 - ilasm.begin_try() - self.instr.render(generator, op) - ilasm.leave(stdflow) - ilasm.end_try() - for cli_exc, py_exc in self.mapping: - ilasm.begin_catch(cli_exc) - ilasm.new('instance void class %s::.ctor()' % py_exc) - ilasm.opcode('stsfld', 'object last_exception') - ilasm.leave(stdflow) - ilasm.end_catch() - ilasm.label(stdflow) - ilasm.opcode('nop') - class _Box(MicroInstruction): def render(self, generator, op): generator.load(op.args[0]) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/option.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/option.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/option.py Mon Aug 27 16:08:52 2007 @@ -1,6 +1,6 @@ from pypy.translator.cli.conftest import option -_defaultopt = dict(wd = False, source = False, nostop = False, stdout = False, nostackopt = False) +_defaultopt = dict(wd = False, source = False, nostop = False, stdout = False) def getoption(name): return getattr(option, name, _defaultopt.get(name)) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/prebuiltnodes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/prebuiltnodes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/prebuiltnodes.py Mon Aug 27 16:08:52 2007 @@ -50,4 +50,17 @@ prebuilt_nodes = _build_helpers(translator, db) raise_OSError_graph = translator.rtyper.exceptiondata.fn_raise_OSError.graph prebuilt_nodes.append(Helper(db, raise_OSError_graph, 'raise_OSError')) + + try: + etrafo = db.exceptiontransformer + except AttributeError: + pass + else: + for name in ('rpyexc_clear', + 'rpyexc_fetch_type', + 'rpyexc_fetch_value', + 'rpyexc_occured', + 'rpyexc_raise'): + sm = getattr(etrafo, name+'_ptr').value + prebuilt_nodes.append(Function(db, sm.graph, name)) return prebuilt_nodes Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py Mon Aug 27 16:08:52 2007 @@ -30,7 +30,7 @@ for f_name, (FIELD_TYPE, f_default) in self.record._fields.iteritems(): f_name = self.cts.escape_name(f_name) cts_type = self.cts.lltype_to_cts(FIELD_TYPE) - if cts_type != 'void': + if cts_type != CTS.types.void: ilasm.field(f_name, cts_type) self._ctor() self._toString() @@ -74,13 +74,12 @@ def _equals(self): # field by field comparison - record_type = self.cts.lltype_to_cts(self.record, include_class=False) - class_record_type = self.cts.lltype_to_cts(self.record, include_class=True) + record_type = self.cts.lltype_to_cts(self.record) self.ilasm.begin_function('Equals', [('object', 'obj')], 'bool', False, 'virtual', 'instance', 'default') - self.ilasm.locals([(class_record_type, 'self')]) + self.ilasm.locals([(record_type, 'self')]) self.ilasm.opcode('ldarg.1') - self.ilasm.opcode('castclass', record_type) + self.ilasm.opcode('castclass', record_type.classname()) self.ilasm.opcode('stloc.0') equal = 'bool [pypylib]pypy.runtime.Utils::Equal<%s>(!!0, !!0)' @@ -91,9 +90,9 @@ f_type = self.cts.lltype_to_cts(FIELD_TYPE) f_name = self.cts.escape_name(f_name) self.ilasm.opcode('ldarg.0') - self.ilasm.get_field((f_type, record_type, f_name)) + self.ilasm.get_field((f_type, record_type.classname(), f_name)) self.ilasm.opcode('ldloc.0') - self.ilasm.get_field((f_type, record_type, f_name)) + self.ilasm.get_field((f_type, record_type.classname(), f_name)) self.ilasm.call(equal % f_type) self.ilasm.opcode('and') @@ -102,7 +101,7 @@ def _getHashCode(self): # return the hash of the first field. XXX: it can lead to a bad distribution - record_type = self.cts.lltype_to_cts(self.record, include_class=False) + record_type = self.cts.lltype_to_cts(self.record) self.ilasm.begin_function('GetHashCode', [], 'int32', False, 'virtual', 'instance', 'default') gethash = 'int32 [pypylib]pypy.runtime.Utils::GetHashCode<%s>(!!0)' if self.record._fields: @@ -113,7 +112,7 @@ f_name = self.cts.escape_name(f_name) f_type = self.cts.lltype_to_cts(FIELD_TYPE) self.ilasm.opcode('ldarg.0') - self.ilasm.get_field((f_type, record_type, f_name)) + self.ilasm.get_field((f_type, record_type.classname(), f_name)) self.ilasm.call(gethash % f_type) else: self.ilasm.opcode('ldc.i4.0') Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs Mon Aug 27 16:08:52 2007 @@ -201,7 +201,7 @@ public static int ll_strcmp(string s1, string s2) { - return string.Compare(s1, s2); + return string.Compare(s1, s2, StringComparison.Ordinal); } public static bool ll_startswith(string s1, string s2) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py Mon Aug 27 16:08:52 2007 @@ -53,7 +53,7 @@ RETURN_TYPE = self.graph.getreturnvar().concretetype return_type = self.cts.lltype_to_cts(RETURN_TYPE) - if return_type != 'void': + if return_type != CTS.types.void: ilasm.locals([(return_type, 'res')]) if self.wrap_exceptions: @@ -70,10 +70,10 @@ # call the function and convert the result to a string containing a valid python expression ilasm.call(self.cts.graph_to_signature(self.graph)) - if return_type != 'void': + if return_type != CTS.types.void: ilasm.opcode('stloc', 'res') if self.wrap_exceptions: - ilasm.leave('check_last_exception') + ilasm.leave('check_etrafo_exception') else: ilasm.leave('print_result') @@ -90,17 +90,20 @@ ilasm.leave('return') ilasm.end_catch() - ilasm.label('check_last_exception') - ilasm.opcode('ldsfld', 'object last_exception') - ilasm.opcode('brnull', 'print_result') - # there is a pending exception - ilasm.opcode('ldsfld', 'object last_exception') - ilasm.call('string class [pypylib]pypy.test.Result::FormatException(object)') - ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') - ilasm.opcode('br', 'return') + # check for exception tranformer exceptions + ilasm.label('check_etrafo_exception') + if hasattr(self.db, 'exceptiontransformer'): + ilasm.opcode('call', 'bool rpyexc_occured()') + ilasm.opcode('brfalse', 'print_result') # no exceptions + ilasm.opcode('call', 'Object rpyexc_fetch_value()') + ilasm.call('string class [pypylib]pypy.test.Result::FormatException(object)') + ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') + ilasm.opcode('br', 'return') + else: + ilasm.opcode('br', 'print_result') ilasm.label('print_result') - if return_type != 'void': + if return_type != CTS.types.void: ilasm.opcode('ldloc', 'res') format_object(RETURN_TYPE, self.cts, ilasm) ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') @@ -112,13 +115,13 @@ def __convert_method(self, arg_type): _conv = { - 'int32': 'ToInt32', - 'unsigned int32': 'ToUInt32', - 'int64': 'ToInt64', - 'unsigned int64': 'ToUInt64', - 'bool': 'ToBoolean', - 'float64': 'ToDouble', - 'char': 'ToChar', + CTS.types.int32: 'ToInt32', + CTS.types.uint32: 'ToUInt32', + CTS.types.int64: 'ToInt64', + CTS.types.uint64: 'ToUInt64', + CTS.types.bool: 'ToBoolean', + CTS.types.float64: 'ToDouble', + CTS.types.char: 'ToChar', } try: @@ -127,15 +130,16 @@ assert False, 'Input type %s not supported' % arg_type -def compile_function(func, annotation=[], graph=None, backendopt=True): +def compile_function(func, annotation=[], graph=None, backendopt=True, + auto_raise_exc=False, exctrans=False): olddefs = patch() - gen = _build_gen(func, annotation, graph, backendopt) + gen = _build_gen(func, annotation, graph, backendopt, exctrans) gen.generate_source() exe_name = gen.build_exe() unpatch(*olddefs) # restore original values - return CliFunctionWrapper(exe_name) + return CliFunctionWrapper(exe_name, func.__name__, auto_raise_exc) -def _build_gen(func, annotation, graph=None, backendopt=True): +def _build_gen(func, annotation, graph=None, backendopt=True, exctrans=False): try: func = func.im_func except AttributeError: @@ -169,11 +173,13 @@ else: tmpdir = udir - return GenCli(tmpdir, t, TestEntryPoint(main_graph, True)) + return GenCli(tmpdir, t, TestEntryPoint(main_graph, True), exctrans=exctrans) class CliFunctionWrapper(object): - def __init__(self, exe_name): + def __init__(self, exe_name, name=None, auto_raise_exc=False): self._exe = exe_name + self.__name__ = name or exe_name + self.auto_raise_exc = auto_raise_exc def run(self, *args): if self._exe is None: @@ -199,6 +205,13 @@ res = StructTuple(res) # so tests can access tuple elements with .item0, .item1, etc. elif isinstance(res, list): res = OOList(res) + elif self.auto_raise_exc and isinstance(res, ExceptionWrapper): + excname = res.class_name + if excname.startswith('exceptions.'): + import exceptions + raise eval(excname) + else: + raise res # probably it's a .NET exception with no RPython equivalent return res class StructTuple(tuple): @@ -233,13 +246,15 @@ self._ann = None self._cli_func = None - def _compile(self, fn, args, ann=None, backendopt=True): + def _compile(self, fn, args, ann=None, backendopt=True, auto_raise_exc=False, exctrans=False): if ann is None: ann = [lltype_to_annotation(typeOf(x)) for x in args] if self._func is fn and self._ann == ann: return self._cli_func else: - self._cli_func = compile_function(fn, ann, backendopt=backendopt) + self._cli_func = compile_function(fn, ann, backendopt=backendopt, + auto_raise_exc=auto_raise_exc, + exctrans=exctrans) self._func = fn self._ann = ann return self._cli_func @@ -252,17 +267,17 @@ if platform.processor() == 'powerpc': py.test.skip('PowerPC --> %s' % reason) - def interpret(self, fn, args, annotation=None, backendopt=True): - f = self._compile(fn, args, annotation, backendopt) + def interpret(self, fn, args, annotation=None, backendopt=True, exctrans=False): + f = self._compile(fn, args, annotation, backendopt=backendopt, exctrans=exctrans) res = f(*args) if isinstance(res, ExceptionWrapper): raise res return res - def interpret_raises(self, exception, fn, args): + def interpret_raises(self, exception, fn, args, backendopt=True, exctrans=False): import exceptions # needed by eval try: - self.interpret(fn, args) + self.interpret(fn, args, backendopt=backendopt, exctrans=exctrans) except ExceptionWrapper, ex: assert issubclass(eval(ex.class_name), exception) else: Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_dotnet.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_dotnet.py Mon Aug 27 16:08:52 2007 @@ -174,11 +174,6 @@ def _skip_pythonnet(self, msg): pass - def _skip_exception(self): - from pypy.translator.cli import function - if function.USE_LAST: - py.test.skip("Fixme!") - def test_staticmeth_call(self): def fn(x): return Math.Abs(x) @@ -292,7 +287,6 @@ assert self.interpret(fn, []) is None def test_native_exception_precise(self): - self._skip_exception() ArgumentOutOfRangeException = NativeException(CLR.System.ArgumentOutOfRangeException) def fn(): x = ArrayList() @@ -304,7 +298,6 @@ assert self.interpret(fn, []) == True def test_native_exception_superclass(self): - self._skip_exception() SystemException = NativeException(CLR.System.Exception) def fn(): x = ArrayList() @@ -316,7 +309,6 @@ assert self.interpret(fn, []) == True def test_native_exception_object(self): - self._skip_exception() SystemException = NativeException(CLR.System.Exception) def fn(): x = ArrayList() @@ -330,7 +322,6 @@ assert res.startswith("Index is less than 0") def test_native_exception_invoke(self): - self._skip_exception() TargetInvocationException = NativeException(CLR.System.Reflection.TargetInvocationException) def fn(): x = ArrayList() Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_exception.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_exception.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_exception.py Mon Aug 27 16:08:52 2007 @@ -3,6 +3,12 @@ from pypy.rpython.test.test_exception import BaseTestException class TestCliException(CliTest, BaseTestException): + use_exception_transformer = False + + def interpret(self, *args, **kwds): + kwds['exctrans'] = self.use_exception_transformer + return CliTest.interpret(self, *args, **kwds) + def test_nested_try(self): def helper(x): if x == 0: @@ -55,3 +61,21 @@ obj = Derived() return obj.foo() assert self.interpret(fn, [0]) == 42 + + def test_missing_handler(self): + def foo(x): + if x: + raise ValueError + + def fn(x): + try: + foo(x) + except ValueError: + raise + return 42 + assert self.interpret(fn, [0], backendopt=False) == 42 + self.interpret_raises(ValueError, fn, [1], backendopt=False) + + +class TestCliExceptionTransformer(TestCliException): + use_exception_transformer = True Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_runtest.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_runtest.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_runtest.py Mon Aug 27 16:08:52 2007 @@ -1,3 +1,4 @@ +import py from pypy.translator.cli.test.runtest import CliTest from pypy.translator.cli.test.runtest import FLOAT_PRECISION from pypy.annotation.listdef import s_list_of_strings @@ -64,3 +65,10 @@ else: return None assert self.interpret(fn, [False]) is None + + def test_auto_raise_exc(self): + def fn(): + raise ValueError + f = self._compile(fn, [], auto_raise_exc=True) + py.test.raises(ValueError, f) + Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py Mon Aug 27 16:08:52 2007 @@ -13,3 +13,31 @@ res = self.ll_to_list(self.interpret(fn, [])) assert res == [52, 53, 54] + def test_mangle(self): + class Foo: + def le(self): + return 42 + + def fn(): + f = Foo() + return f.le() + res = self.interpret(fn, [], backendopt=False) + + def test_link_vars_overlapping(self): + from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift + def fn(maxofs): + lastofs = 0 + ofs = 1 + while ofs < maxofs: + lastofs = ofs + try: + ofs = ovfcheck_lshift(ofs, 1) + except OverflowError: + ofs = maxofs + else: + ofs = ofs + 1 + return lastofs + res = self.interpret(fn, [64]) + expected = fn(64) + assert res == expected + Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py Mon Aug 27 16:08:52 2007 @@ -24,3 +24,8 @@ def test_getitem_exc(self): py.test.skip('fixme!') + def test_compare(self): + strings = ['aa', 'ZZ'] + def fn(i, j): + return strings[i] < strings[j] + assert self.interpret(fn, [0, 1], backendopt=False) == fn(0, 1) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/jvm/node.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/jvm/node.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/jvm/node.py Mon Aug 27 16:08:52 2007 @@ -280,12 +280,14 @@ def set_label(self, blocklbl): self.ilasm.mark(blocklbl) - def begin_try(self): - self.ilasm.begin_try() + def begin_try(self, cond): + if cond: + self.ilasm.begin_try() - def end_try(self, exit_label): + def end_try(self, exit_label, cond): self.ilasm.branch_unconditionally(exit_label) - self.ilasm.end_try() + if cond: + self.ilasm.end_try() def begin_catch(self, llexitcase): ll_meta_exc = llexitcase @@ -337,7 +339,9 @@ self.ilasm.throw() - def _trace(self, str): + def _trace(self, str, writeline=False): + if writeline: + str += '\n' jvmgen.SYSTEMERR.load(self.generator) self.generator.load_string(str) jvmgen.PRINTSTREAMPRINTSTR.invoke(self.generator) @@ -381,19 +385,13 @@ self.generator.emit(jvmgen.PRINTSTREAMPRINTSTR) self._trace("\n") + def _trace_enabled(self): + return getoption('trace') + def _render_op(self, op): self.generator.add_comment(str(op)) - - if getoption('trace'): - self._trace(str(op)+"\n") - - for i, arg in enumerate(op.args): - self._trace_value('Arg %02d' % i, arg) - OOFunction._render_op(self, op) - if getoption('trace'): - self._trace_value('Result', op.result) class StaticMethodInterface(Node, JvmClassType): """ Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py Mon Aug 27 16:08:52 2007 @@ -11,6 +11,8 @@ class Function(object): + + auto_propagate_exceptions = False def __init__(self, db, graph, name = None, is_method = False, is_entrypoint = False): self.db = db @@ -140,9 +142,17 @@ for op in block.operations[:-1]: self._render_op(op) + anyHandler = False + for link in block.exits: + if link.exitcase is None: + continue + if not self._is_raise_block(link.target): + anyHandler = True + anyHandler = anyHandler or not self.auto_propagate_exceptions + # render the last one (if any!) and prepend a .try if block.operations: - self.begin_try() + self.begin_try(anyHandler) self._render_op(block.operations[-1]) # search for the "default" block to be executed when no @@ -150,7 +160,7 @@ for link in block.exits: if link.exitcase is None: self._setup_link(link) - self.end_try(self._get_block_name(link.target)) + self.end_try(self._get_block_name(link.target), anyHandler) break else: assert False, "No non-exceptional case from exc_handling block" @@ -160,6 +170,8 @@ if link.exitcase is None: continue # see above assert issubclass(link.exitcase, py.builtin.BaseException) + if self._is_raise_block(link.target) and self.auto_propagate_exceptions: + continue # let the exception propagate ll_meta_exc = link.llexitcase self.record_ll_meta_exc(ll_meta_exc) self.begin_catch(link.llexitcase) @@ -218,13 +230,17 @@ def render_numeric_switch_naive(self, block): for link in block.exits: target_label = self._get_block_name(link.target) - self._setup_link(link) if link.exitcase == 'default': + self._setup_link(link) self.generator.branch_unconditionally(target_label) else: + next_case = self.next_label('next_case') self.generator.push_primitive_constant(block.exitswitch.concretetype, link.exitcase) self.generator.load(block.exitswitch) - self.generator.branch_if_equal(target_label) + self.generator.branch_if_not_equal(next_case) + self._setup_link(link) + self.generator.branch_unconditionally(target_label) + self.set_label(next_case) def _follow_link(self, link): target_label = self._get_block_name(link.target) @@ -233,20 +249,54 @@ def _setup_link(self, link): target = link.target + linkvars = [] for to_load, to_store in zip(link.args, target.inputargs): if isinstance(to_load, flowmodel.Variable) and to_load.name == to_store.name: continue if to_load.concretetype is ootype.Void: continue - self.generator.add_comment("%r --> %r" % (to_load, to_store)) + linkvars.append((to_load, to_store)) + + # after SSI_to_SSA it can happen to have to_load = [a, b] and + # to_store = [b, c]. If we store each variable sequentially, + # 'b' would be overwritten before being read. To solve, we + # first load all the values on the stack, then store in the + # appropriate places. + + if self._trace_enabled(): + self._trace('link', writeline=True) + for to_load, to_store in linkvars: + self._trace_value('%s <-- %s' % (to_store, to_load), to_load) + self._trace('', writeline=True) + + for to_load, to_store in linkvars: self.generator.load(to_load) + for to_load, to_store in reversed(linkvars): self.generator.store(to_store) + def _trace_enabled(self): + return False + + def _trace(self, s): + raise NotImplementedError + + def _trace_value(self, prompt, v): + raise NotImplementedError + def _render_op(self, op): instr_list = self.db.genoo.opcodes.get(op.opname, None) assert instr_list is not None, 'Unknown opcode: %s ' % op assert isinstance(instr_list, InstructionList) + + if self._trace_enabled(): + self._trace(str(op), writeline=True) + for i, arg in enumerate(op.args): + self._trace_value('Arg %02d' % i, arg) + instr_list.render(self.generator, op) + + if self._trace_enabled(): + self._trace_value('Result', op.result) def _render_sub_op(self, sub_op): op = sub_op.op Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py Mon Aug 27 16:08:52 2007 @@ -48,3 +48,16 @@ obj.x = x + y return obj.x assert self.interpret(fn, [1,3]) == 4 + + def test_link(self): + def fn(): + plus = False + for c in 'a': + if c == 'b': + plus = True + elif c == 'c': + binary = True + return plus + res = self.interpret(fn, []) + expected = fn() + assert res == expected From jlg at codespeak.net Mon Aug 27 17:39:03 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 27 Aug 2007 17:39:03 +0200 (CEST) Subject: [pypy-svn] r46043 - in pypy/dist/pypy/lang/scheme: . test Message-ID: <20070827153903.CA0FE8168@code0.codespeak.net> Author: jlg Date: Mon Aug 27 17:39:03 2007 New Revision: 46043 Added: pypy/dist/pypy/lang/scheme/macro.py - copied, changed from r46033, pypy/dist/pypy/lang/scheme/object.py Modified: pypy/dist/pypy/lang/scheme/execution.py pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/test/test_macro.py Log: object.py split part 1 - derived macros -> macro.py Modified: pypy/dist/pypy/lang/scheme/execution.py ============================================================================== --- pypy/dist/pypy/lang/scheme/execution.py (original) +++ pypy/dist/pypy/lang/scheme/execution.py Mon Aug 27 17:39:03 2007 @@ -1,4 +1,5 @@ import pypy.lang.scheme.object as ssobject +import pypy.lang.scheme.macro as ssmacro from pypy.lang.scheme.ssparser import parse import py @@ -7,13 +8,14 @@ self.obj = w_obj OPERATION_MAP = {} -for obj_name in dir(ssobject): - obj = getattr(ssobject, obj_name) - try: - issubclass(obj, ssobject.W_Callable) - OPERATION_MAP[obj._symbol_name] = obj(obj._symbol_name) - except (TypeError, AttributeError): - pass +for mod in (ssobject, ssmacro): + for obj_name in dir(mod): + obj = getattr(mod, obj_name) + try: + issubclass(obj, ssobject.W_Callable) + OPERATION_MAP[obj._symbol_name] = obj(obj._symbol_name) + except (TypeError, AttributeError): + pass de_file = py.magic.autopath().dirpath().join("r5rs_derived_expr.ss") de_code = de_file.read() @@ -50,7 +52,7 @@ self.globalscope = globalscope def _dispatch(self, symb): - if isinstance(symb, ssobject.SymbolClosure): + if isinstance(symb, ssmacro.SymbolClosure): return (symb.closure, symb.name) elif isinstance(symb, ssobject.W_Symbol): Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Mon Aug 27 17:39:03 2007 @@ -716,7 +716,7 @@ ## # Number Predicates ## -class NumberPredicate(W_Procedure): +class PredicateNumber(W_Procedure): def procedure(self, ctx, lst): if len(lst) != 1: raise WrongArgsNumber @@ -730,7 +730,7 @@ def predicate(self, w_obj): raise NotImplementedError -class IntegerP(NumberPredicate): +class IntegerP(PredicateNumber): _symbol_name = "integer?" def predicate(self, w_obj): @@ -739,7 +739,7 @@ return True -class RealP(NumberPredicate): +class RealP(PredicateNumber): _symbol_name = "real?" def predicate(self, w_obj): @@ -748,7 +748,7 @@ class RationalP(RealP): _symbol_name = "rational?" -class NumberP(NumberPredicate): +class NumberP(PredicateNumber): _symbol_name = "number?" def predicate(self, w_obj): @@ -757,25 +757,25 @@ class ComplexP(NumberP): _symbol_name = "complex?" -class ExactP(NumberPredicate): +class ExactP(PredicateNumber): _symbol_name = "exact?" def predicate(self, w_obj): return w_obj.exact -class InexactP(NumberPredicate): +class InexactP(PredicateNumber): _symbol_name = "inexact?" def predicate(self, w_obj): return not w_obj.exact -class ZeroP(NumberPredicate): +class ZeroP(PredicateNumber): _symbol_name = "zero?" def predicate(self, w_obj): return w_obj.to_number() == 0.0 -class OddP(NumberPredicate): +class OddP(PredicateNumber): _symbol_name = "odd?" def predicate(self, w_obj): @@ -784,7 +784,7 @@ return w_obj.round() % 2 != 0 -class EvenP(NumberPredicate): +class EvenP(PredicateNumber): _symbol_name = "even?" def predicate(self, w_obj): @@ -1180,438 +1180,8 @@ return W_Promise(lst.car, ctx) ## -# DerivedMacros +# Continuations ## -class SyntaxRules(W_Macro): - _symbol_name = "syntax-rules" - - def call(self, ctx, lst): - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - - w_literals = lst.car - if not isinstance(w_literals, W_List): - raise SchemeSyntaxError - - literals_map = {} - while isinstance(w_literals, W_Pair): - if not isinstance(w_literals.car, W_Symbol): - raise SchemeSyntaxError - - #XXX locations here - literal_name = w_literals.car.to_string() - w_temp = ctx.get_location(literal_name) - - literals_map[literal_name] = w_temp - - w_literals = w_literals.cdr - - w_syntax_lst = lst.cdr - syntax_lst = [] - while isinstance(w_syntax_lst, W_Pair): - w_syntax = w_syntax_lst.car - if not isinstance(w_syntax, W_Pair): - raise SchemeSyntaxError - - w_pattern = w_syntax.car - w_template = w_syntax.get_cdr_as_pair().car - - #do stuff with w_syntax rules - syntax_lst.append(SyntaxRule(w_pattern, w_template, literals_map)) - - w_syntax_lst = w_syntax_lst.cdr - - #closes template in syntactic enviroment at the point of definition - return W_Transformer(syntax_lst, ctx) - -class Ellipsis(W_Root): - def __init__(self, mdict_lst): - self.mdict_lst = mdict_lst - - def __repr__(self): - return "#" - -class EllipsisException(SchemeException): - def __init__(self, length): - self.length = length - -class EllipsisTemplate(SchemeException): - pass - -class EllipsisPattern(SchemeException): - pass - -class MatchError(SchemeException): - pass - -class SyntaxRule(object): - def __init__(self, pattern, template, literals): - assert isinstance(pattern, W_Pair) - self.pattern = pattern - self.template = template - self.literals = literals - - def __str__(self): - return self.pattern.to_string() + " -> " + self.template.to_string() - - def match(self, ctx, w_expr): - #we use .cdr here, because keyword should not be a macro variable - assert isinstance(w_expr, W_Pair) - return self.matchr(ctx, self.pattern.cdr, w_expr.cdr) - - def matchr(self, ctx, w_patt, w_expr): - #print " >", w_patt.to_string(), w_expr.to_string() - if isinstance(w_patt, W_Pair): - w_pattcar = w_patt.car - w_pattcdr = w_patt.cdr - if isinstance(w_expr, W_Pair): - mdict_car = self.matchr(ctx, w_pattcar, w_expr.car) - try: - #we catch EllipsisPattern here because in car - # we dont know how to deal with it - mdict_cdr = self.matchr(ctx, w_pattcdr, w_expr.cdr) - except EllipsisPattern: - #print "ellipsis matched", w_patt, w_expr - - mdict_lst = [] - w_pair = w_expr - while isinstance(w_pair, W_Pair): - mdict = self.matchr(ctx, w_pattcar, w_pair.car) - mdict_lst.append(mdict) - w_pair = w_pair.cdr - - mdict_cdr = {} - ellipsis = Ellipsis(mdict_lst) - for name in mdict_lst[0].keys(): - mdict_cdr[name] = ellipsis - - return mdict_cdr - - mdict_car.update(mdict_cdr) - return mdict_car - - if w_expr is w_nil: - #one matched to ellipsis, previous (up) w_expr.car - if w_pattcar is w_ellipsis: - raise EllipsisPattern - - #zero matched to ellipsis - if isinstance(w_pattcdr, W_Pair) and \ - w_pattcdr.car is w_ellipsis: - #all symbols from w_pattcar match zero length Ellipsis - return self.dict_traverse_expr(w_pattcar, Ellipsis([])) - - if w_patt is w_ellipsis: - raise EllipsisPattern - - if isinstance(w_patt, W_Symbol): - try: - w_literal = self.literals[w_patt.name] - if not isinstance(w_expr, W_Symbol): - raise MatchError - - if w_patt.name != w_expr.name: - raise MatchError - - w_form = ctx.get_location(w_expr.name) - - if w_form is not w_literal: - raise MatchError - - except KeyError: - pass - - return {w_patt.name: w_expr} - - if w_patt is w_nil and w_expr is w_nil: - return {} - - #w_patt is w_nil, but w_expr is not - # or w_patt is W_Pair but w_expr is not - raise MatchError - - def dict_traverse_expr(self, expr, val=None): - if isinstance(expr, W_Pair): - dict_car = self.dict_traverse_expr(expr.car, val) - dict_cdr = self.dict_traverse_expr(expr.cdr, val) - dict_car.update(dict_cdr) - return dict_car - - if isinstance(expr, W_Symbol) and not expr is w_ellipsis: - return {expr.name: val} - - return {} - -class SymbolClosure(W_Symbol): - def __init__(self, ctx, symbol): - assert isinstance(symbol, W_Symbol) - assert not isinstance(symbol, SymbolClosure) - self.symbol = symbol - self.name = symbol.name - self.closure = ctx - - def eval_tr(self, ctx): - #this symbol is in Syntactic Closure - return self.symbol.eval_tr(self.closure) - - def to_string(self): - #return "#" - return self.symbol.to_string() - - def __repr__(self): - return "" - -class PairClosure(W_Pair): - def __init__(self, ctx, pair): - assert isinstance(pair, W_Pair) - assert not isinstance(pair, PairClosure) - self.pair = pair - self.car = pair.car - self.cdr = pair.cdr - self.closure = ctx - - def eval_tr(self, ctx): - #this pair is in Syntactic Closure - return self.pair.eval_tr(self.closure) - - def to_string(self): - #return "#" - return self.pair.to_string() - - def __repr__(self): - return "" - -class W_Transformer(W_Procedure): - def __init__(self, syntax_lst, ctx, pname=""): - self.pname = pname - self.syntax_lst = syntax_lst - self.closure = ctx - - def match(self, ctx, w_expr): - for rule in self.syntax_lst: - try: - #print "m>", rule.pattern.to_string() - match_dict = rule.match(ctx, w_expr) - return (rule.template, match_dict) - except MatchError: - pass - - raise MatchError - - def expand(self, ctx, w_expr): - try: - #print w_expr.to_string() - (template, match_dict) = self.match(ctx, w_expr) - except MatchError: - raise SchemeSyntaxError - - return self.substitute(ctx, template, match_dict) - - def find_elli(self, expr, mdict): - #filter mdict, returning only ellipsis which appear in expr - if isinstance(expr, W_Pair): - edict_car = self.find_elli(expr.car, mdict) - edict_cdr = self.find_elli(expr.cdr, mdict) - edict_car.update(edict_cdr) - return edict_car - - if isinstance(expr, W_Symbol): - val = mdict.get(expr.name, None) - if val is None: - return {} - - if isinstance(val, Ellipsis): - return {expr.name: val} - - return {} - - def plst_append(self, plst, w_cdr=None): - if len(plst) == 0: - return w_cdr - first_cons = plst[0] - - last_cons = None - for lst in plst: - if last_cons is not None: - last_cons.cdr = lst - - while isinstance(lst, W_Pair): - last_cons = lst - lst = lst.cdr - - if w_cdr is not None: - assert isinstance(last_cons, W_Pair) - last_cons.cdr = w_cdr - - return first_cons - - def substituter(self, ctx, sexpr, match_dict, flatten=False): - if isinstance(sexpr, W_Pair): - w_car = self.substituter(ctx, sexpr.car, match_dict) - try: - w_cdr = self.substituter(ctx, sexpr.cdr, match_dict) - except EllipsisTemplate: - #print "ellipsis expand", sexpr - sexprcdr = sexpr.get_cdr_as_pair() - try: - #we can still have something behind ellipsis - w_cdr = self.substituter(ctx, sexprcdr.cdr, match_dict) - except EllipsisTemplate: - #it can also be ellipsis - # lets pretend its usual <(obj ...) ...> - # instead of - # we will *flatten* the result later - w_inner = W_Pair(sexpr.car, W_Pair(sexprcdr.car, w_nil)) - w_outer = W_Pair(w_inner, sexprcdr.cdr) - return self.substituter(ctx, w_outer, match_dict, True) - - plst = [] - #find_elli gets ellipses from match_dict relevant to sexpr.car - mdict_elli = self.find_elli(sexpr.car, match_dict) - elli_len = 0 - for (key, val) in mdict_elli.items(): - if elli_len == 0 or elli_len == len(val.mdict_lst): - elli_len = len(val.mdict_lst) - else: - #we can treat is as an error if ellipsis has - # different match length - # # or get the shortest one - raise SchemeSyntaxError - - #generate elli_len substitutions for ellipsis - for i in range(elli_len): - #one level of ellipsis nesting lower - new_mdict = match_dict.copy() - for (key, val) in mdict_elli.items(): - new_mdict[key] = val.mdict_lst[i][key] - - sub = self.substituter(ctx, sexpr.car, new_mdict) - plst.append(sub) - - if flatten: - #we have to flatten these list, it means append them - # together, and remember about w_cdr - w_lst = self.plst_append(plst, w_cdr) - - else: - w_lst = plst2lst(plst, w_cdr) - - return w_lst - - w_pair = W_Pair(w_car, w_cdr) - if isinstance(w_car, W_Symbol): - try: - w_macro = ctx.get(w_car.name) - # recursive macro expansion - if isinstance(w_macro, W_DerivedMacro): - if w_macro.transformer is self: - return w_macro.expand(ctx, w_pair) - except UnboundVariable: - pass - - return w_pair - - if isinstance(sexpr, W_Symbol): - if sexpr is w_ellipsis: - raise EllipsisTemplate - - w_sub = match_dict.get(sexpr.name, None) - if w_sub is not None: - #Hygenic macros close their input forms in the syntactic - # enviroment at the point of use - - if isinstance(w_sub, Ellipsis): - return w_sub - - #not always needed, because w_sub can have no W_Symbol inside - if isinstance(w_sub, W_Symbol) and \ - not isinstance(w_sub, SymbolClosure): - return SymbolClosure(ctx, w_sub) - - if isinstance(w_sub, W_Pair) and \ - not isinstance(w_sub, PairClosure): - return PairClosure(ctx, w_sub) - - return w_sub - - return sexpr - - substitute = substituter - - def expand_eval(self, ctx, sexpr): - #we have lexical scopes: - # 1. macro was defined - self.closure - # 2. macro is called - ctx - # 3. macro is expanded, can introduce new bindings - expand_ctx - expanded = self.expand(ctx, sexpr) - expand_ctx = self.closure.copy() - return expanded.eval(expand_ctx) - - def procedure(self, ctx, lst): - return self.expand_eval(ctx, lst[0]) - -class W_DerivedMacro(W_Macro): - def __init__(self, name, transformer): - self.name = name - self.transformer = transformer - - def to_string(self): - return "#" % (self.name,) - - def call(self, ctx, lst): - return self.transformer.expand_eval(ctx, - W_Pair(W_Symbol(self.name), lst)) - - def expand(self, ctx, lst): - return self.transformer.expand(ctx, lst) - -class DefineSyntax(W_Macro): - _symbol_name = "define-syntax" - - def call(self, ctx, lst): - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - - w_def = lst.car - if not isinstance(w_def, W_Symbol): - raise SchemeSyntaxError - - w_syntax_rules = lst.get_cdr_as_pair().car - w_transformer = w_syntax_rules.eval(ctx) - if not isinstance(w_transformer, W_Transformer): - raise SchemeSyntaxError - - w_macro = W_DerivedMacro(w_def.name, w_transformer) - ctx.set(w_def.name, w_macro) - return w_macro #undefined - -class LetSyntax(W_Macro): - #XXX letrec-syntax missing - _symbol_name = "let-syntax" - - def call_tr(self, ctx, lst): - #let uses eval_body, so it is tail-recursive aware - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - local_ctx = ctx.copy() - w_formal = lst.car - while isinstance(w_formal, W_Pair): - w_def = w_formal.get_car_as_pair() - w_transformer = w_def.get_cdr_as_pair().car.eval(ctx) - if not isinstance(w_transformer, W_Transformer): - raise SchemeSyntaxError - - w_name = w_def.car - if not isinstance(w_name, W_Symbol): - raise SchemeSyntaxError - - w_macro = W_DerivedMacro(w_name.name, w_transformer) - - local_ctx.put(w_name.name, w_macro) - w_formal = w_formal.cdr - - return Body(lst.cdr).eval_tr(local_ctx) - class ContinuationReturn(SchemeException): def __init__(self, result): self.result = result Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py ============================================================================== --- pypy/dist/pypy/lang/scheme/test/test_macro.py (original) +++ pypy/dist/pypy/lang/scheme/test/test_macro.py Mon Aug 27 17:39:03 2007 @@ -2,6 +2,7 @@ from pypy.lang.scheme.ssparser import parse from pypy.lang.scheme.execution import ExecutionContext from pypy.lang.scheme.object import * +from pypy.lang.scheme.macro import * def eval_(ctx, expr): return parse(expr)[0].eval(ctx) From simonb at codespeak.net Mon Aug 27 17:51:39 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Mon, 27 Aug 2007 17:51:39 +0200 (CEST) Subject: [pypy-svn] r46044 - pypy/branch/pypy-more-rtti-inprogress/rpython/tool Message-ID: <20070827155139.590DB81B5@code0.codespeak.net> Author: simonb Date: Mon Aug 27 17:51:38 2007 New Revision: 46044 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/genrffi.py Log: wrapper is now in llexternal Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/genrffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/genrffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/genrffi.py Mon Aug 27 17:51:38 2007 @@ -37,21 +37,6 @@ } -def softwrapper(funcptr, arg_tps): - # Here we wrap with a function that does some simple type coercion. - unrolling_arg_tps = unrolling_iterable(enumerate(arg_tps)) - def softfunc(*args): - real_args = () - for i, tp in unrolling_arg_tps: - if tp == rffi.lltype.Float: - real_args = real_args + (float(args[i]),) - else: - real_args = real_args + (args[i],) - result = funcptr(*real_args) - return result - return softfunc - - class RffiBuilder(object): def __init__(self, ns=None, includes=[], libraries=[], include_dirs=[]): if ns is None: @@ -105,9 +90,8 @@ self.proc_tp(func.restype), includes=self.includes, libraries=self.libraries, include_dirs=self.include_dirs) - soft = softwrapper(ll_item, arg_tps) - self.ns[name] = soft - return soft + self.ns[name] = ll_item + return ll_item def proc_namespace(self, ns): exempt = set(id(value) for value in ctypes.__dict__.values()) From antocuni at codespeak.net Mon Aug 27 17:55:41 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 17:55:41 +0200 (CEST) Subject: [pypy-svn] r46045 - in pypy/branch/pypy-more-rtti-inprogress/translator: cli jvm/test oosupport/test_template Message-ID: <20070827155541.A071481BD@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 17:55:41 2007 New Revision: 46045 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/opcodes.py pypy/branch/pypy-more-rtti-inprogress/translator/jvm/test/test_cast.py pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/cast.py Log: implement cast_primitive and ullong_lshift for gencli Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py Mon Aug 27 17:55:41 2007 @@ -231,6 +231,18 @@ generator.ilasm.opcode('ldtoken', fullname) generator.ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)') +OOTYPE_TO_MNEMONIC = { + ootype.Signed: 'i4', + ootype.SignedLongLong: 'i8', + ootype.Unsigned: 'u4', + ootype.UnsignedLongLong: 'u8', + } + +class _CastPrimitive(MicroInstruction): + def render(self, generator, op): + TO = op.result.concretetype + mnemonic = OOTYPE_TO_MNEMONIC[TO] + generator.ilasm.opcode('conv.%s' % mnemonic) Call = _Call() CallMethod = _CallMethod() @@ -245,3 +257,4 @@ GetArrayElem = _GetArrayElem() SetArrayElem = _SetArrayElem() TypeOf = _TypeOf() +CastPrimitive = _CastPrimitive() Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/opcodes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/opcodes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/opcodes.py Mon Aug 27 17:55:41 2007 @@ -1,7 +1,7 @@ from pypy.translator.cli.metavm import Call, CallMethod, \ IndirectCall, GetField, SetField, OOString, DownCast, NewCustomDict,\ CastWeakAdrToPtr, MapException, Box, Unbox, NewArray, GetArrayElem, SetArrayElem,\ - TypeOf + TypeOf, CastPrimitive from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\ New, RuntimeNew, CastTo, PushPrimitive from pypy.translator.cli.cts import WEAKREF @@ -210,6 +210,7 @@ 'ullong_ne': _not('ceq'), 'ullong_gt': 'cgt.un', 'ullong_ge': _not('clt.un'), + 'ullong_lshift': [PushAllArgs, 'conv.u4', 'shl', 'conv.u8'], # when casting from bool we want that every truth value is casted # to 1: we can't simply DoNothing, because the CLI stack could @@ -231,6 +232,7 @@ 'cast_float_to_uint': 'conv.u4', 'cast_longlong_to_float': 'conv.r8', 'cast_float_to_longlong': 'conv.i8', + 'cast_primitive': [PushAllArgs, CastPrimitive], 'truncate_longlong_to_int': 'conv.i4', 'is_early_constant': [PushPrimitive(ootype.Bool, False)] } Modified: pypy/branch/pypy-more-rtti-inprogress/translator/jvm/test/test_cast.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/jvm/test/test_cast.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/jvm/test/test_cast.py Mon Aug 27 17:55:41 2007 @@ -7,3 +7,6 @@ def test_uint_to_float(self): # This is most likely with how we render uints when we print them, and they get parsed. py.test.skip('Same issue seen in other tests with uints... 2147450880.0 == 2147483648.0') + + def test_cast_primitive(self): + py.test.skip('fixme!') Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/cast.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/cast.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/cast.py Mon Aug 27 17:55:41 2007 @@ -52,3 +52,17 @@ def test_uint_to_float(self): self.check(to_float, [r_uint(sys.maxint+1)]) + + def test_cast_primitive(self): + from pypy.rpython.lltypesystem.lltype import cast_primitive, \ + UnsignedLongLong, SignedLongLong, Signed + def f(x): + x = cast_primitive(UnsignedLongLong, x) + x <<= 60 + x /= 3 + x <<= 1 + x = cast_primitive(SignedLongLong, x) + x >>= 32 + return cast_primitive(Signed, x) + res = self.interpret(f, [14]) + assert res == -1789569707 From simonb at codespeak.net Mon Aug 27 18:04:53 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Mon, 27 Aug 2007 18:04:53 +0200 (CEST) Subject: [pypy-svn] r46046 - pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test Message-ID: <20070827160453.460D181EC@code0.codespeak.net> Author: simonb Date: Mon Aug 27 18:04:52 2007 New Revision: 46046 Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test/test_ll_cairo.py Log: show off fancy implicit casting Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test/test_ll_cairo.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test/test_ll_cairo.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rlib/rcairo/test/test_ll_cairo.py Mon Aug 27 18:04:52 2007 @@ -20,22 +20,22 @@ height = 600 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,width,height) cr = cairo_create(surface) - cairo_scale(cr, 1.*width, 1.*height) + cairo_scale(cr, width, height) cairo_set_line_width(cr, 0.04) - cairo_arc(cr, 0.5, 0.5, 0.3, 0., 2 * pi) + cairo_arc(cr, 0.5, 0.5, 0.3, 0, 2 * pi) cairo_clip(cr) cairo_new_path(cr) # current path is not # consumed by cairo_clip() - cairo_rectangle(cr, 0., 0., 1., 1.) + cairo_rectangle(cr, 0, 0, 1, 1) cairo_fill(cr) - cairo_set_source_rgb(cr, 0., 1., 0.) - cairo_move_to(cr, 0., 0.) - cairo_line_to(cr, 1., 1.) - cairo_move_to(cr, 1., 0.) - cairo_line_to(cr, 0., 1.) + cairo_set_source_rgb(cr, 0, 1, 0) + cairo_move_to(cr, 0, 0) + cairo_line_to(cr, 1, 1) + cairo_move_to(cr, 1, 0) + cairo_line_to(cr, 0, 1) cairo_stroke(cr) #_cairo_surface_write_to_png(surface, 'foo.png') # XXX why does this fail to compile ?? From antocuni at codespeak.net Mon Aug 27 18:31:32 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 18:31:32 +0200 (CEST) Subject: [pypy-svn] r46047 - pypy/branch/pypy-more-rtti-inprogress/translator/cli Message-ID: <20070827163132.BD2A481BD@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 18:31:31 2007 New Revision: 46047 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/opcodes.py Log: - remove an unneeded conv from ullong_lshift - implement ullong_rshift Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/opcodes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/opcodes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/opcodes.py Mon Aug 27 18:31:31 2007 @@ -210,7 +210,8 @@ 'ullong_ne': _not('ceq'), 'ullong_gt': 'cgt.un', 'ullong_ge': _not('clt.un'), - 'ullong_lshift': [PushAllArgs, 'conv.u4', 'shl', 'conv.u8'], + 'ullong_lshift': [PushAllArgs, 'conv.u4', 'shl'], + 'ullong_rshift': [PushAllArgs, 'conv.i4', 'shr'], # when casting from bool we want that every truth value is casted # to 1: we can't simply DoNothing, because the CLI stack could From jlg at codespeak.net Mon Aug 27 18:51:23 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 27 Aug 2007 18:51:23 +0200 (CEST) Subject: [pypy-svn] r46048 - pypy/dist/pypy/lang/scheme Message-ID: <20070827165123.A684E81E1@code0.codespeak.net> Author: jlg Date: Mon Aug 27 18:51:22 2007 New Revision: 46048 Added: pypy/dist/pypy/lang/scheme/procedure.py - copied, changed from r46043, pypy/dist/pypy/lang/scheme/object.py pypy/dist/pypy/lang/scheme/syntax.py - copied, changed from r46043, pypy/dist/pypy/lang/scheme/object.py Modified: pypy/dist/pypy/lang/scheme/execution.py pypy/dist/pypy/lang/scheme/object.py Log: object.py split part 2 - prcedures -> procedure.py; syntax/macros -> syntax.py Modified: pypy/dist/pypy/lang/scheme/execution.py ============================================================================== --- pypy/dist/pypy/lang/scheme/execution.py (original) +++ pypy/dist/pypy/lang/scheme/execution.py Mon Aug 27 18:51:22 2007 @@ -1,5 +1,7 @@ import pypy.lang.scheme.object as ssobject -import pypy.lang.scheme.macro as ssmacro +import pypy.lang.scheme.syntax as procedure +import pypy.lang.scheme.procedure as syntax +import pypy.lang.scheme.macro as macro from pypy.lang.scheme.ssparser import parse import py @@ -8,7 +10,7 @@ self.obj = w_obj OPERATION_MAP = {} -for mod in (ssobject, ssmacro): +for mod in (ssobject, syntax, procedure, macro): for obj_name in dir(mod): obj = getattr(mod, obj_name) try: @@ -52,7 +54,7 @@ self.globalscope = globalscope def _dispatch(self, symb): - if isinstance(symb, ssmacro.SymbolClosure): + if isinstance(symb, macro.SymbolClosure): return (symb.closure, symb.name) elif isinstance(symb, ssobject.W_Symbol): Modified: pypy/dist/pypy/lang/scheme/object.py ============================================================================== --- pypy/dist/pypy/lang/scheme/object.py (original) +++ pypy/dist/pypy/lang/scheme/object.py Mon Aug 27 18:51:22 2007 @@ -412,6 +412,22 @@ def to_string(self): return "#" % (self.pname,) +class W_Promise(W_Root): + def __init__(self, expr, ctx): + self.expr = expr + self.result = None + self.closure = ctx + + def to_string(self): + return "#" % self.expr.to_string() + + def force(self, ctx): + if self.result is None: + #XXX cont_stack copy to be cont. friendly + self.result = self.expr.eval(self.closure.copy()) + + return self.result + class Formal(object): def __init__(self, name, islist=False): self.name = name @@ -459,616 +475,9 @@ return self.body.eval_tr(local_ctx) -def plst2lst(plst, w_cdr=w_nil): - """coverts python list() of W_Root into W_Pair scheme list""" - plst.reverse() - for w_obj in plst: - w_cdr = W_Pair(w_obj, w_cdr) - - return w_cdr - -class W_Promise(W_Root): - def __init__(self, expr, ctx): - self.expr = expr - self.result = None - self.closure = ctx - - def to_string(self): - return "#" % self.expr.to_string() - - def force(self, ctx): - if self.result is None: - #XXX cont_stack copy to be cont. friendly - self.result = self.expr.eval(self.closure.copy()) - - return self.result - -## -# operations -## -class ListOper(W_Procedure): - def procedure(self, ctx, lst): - if len(lst) == 0: - if self.default_result is None: - raise WrongArgsNumber() - - return self.default_result - - if len(lst) == 1: - if not isinstance(lst[0], W_Number): - raise WrongArgType(lst[0], "Number") - return self.unary_oper(lst[0]) - - acc = None - for arg in lst: - if not isinstance(arg, W_Number): - raise WrongArgType(arg, "Number") - if acc is None: - acc = arg - else: - acc = self.oper(acc, arg) - - return acc - - def unary_oper(self, x): - if isinstance(x, W_Integer): - return W_Integer(self.do_unary_oper(x.to_fixnum())) - elif isinstance(x, W_Number): - return W_Real(self.do_unary_oper(x.to_float())) - else: - raise WrongArgType(x, "Number") - - def oper(self, x, y): - if isinstance(x, W_Integer) and isinstance(y, W_Integer): - return W_Integer(self.do_oper(x.to_fixnum(), y.to_fixnum())) - elif isinstance(x, W_Number) or isinstance(y, W_Number): - return W_Real(self.do_oper(x.to_float(), y.to_float())) - else: - raise WrongArgType(x, "Number") - - def do_oper(self, x, y): - raise NotImplementedError - - def do_unary_oper(self, x): - raise NotImplementedError - -def create_op_class(oper, unary_oper, title, default_result=None): - class Op(ListOper): - pass - - local_locals = {} - attr_name = "do_oper" - - code = py.code.Source(""" - def %s(self, x, y): - return x %s y - """ % (attr_name, oper)) - - exec code.compile() in local_locals - local_locals[attr_name]._annspecialcase_ = 'specialize:argtype(1)' - setattr(Op, attr_name, local_locals[attr_name]) - - attr_name = "do_unary_oper" - code = py.code.Source(""" - def %s(self, x): - return %s x - """ % (attr_name, unary_oper)) - - exec code.compile() in local_locals - local_locals[attr_name]._annspecialcase_ = 'specialize:argtype(1)' - setattr(Op, attr_name, local_locals[attr_name]) - - if default_result is None: - Op.default_result = None - else: - Op.default_result = W_Integer(default_result) - - Op.__name__ = "Op" + title - Op._symbol_name = oper - return Op - -Add = create_op_class('+', '', "Add", 0) -Sub = create_op_class('-', '-', "Sub") -Mul = create_op_class('*', '', "Mul", 1) -Div = create_op_class('/', '1 /', "Div") - -class Equal(W_Procedure): - _symbol_name = "=" - - def procedure(self, ctx, lst): - if len(lst) < 2: - return W_Boolean(True) - - prev = lst[0] - if not isinstance(prev, W_Number): - raise WrongArgType(prev, "Number") - - for arg in lst[1:]: - if not isinstance(arg, W_Number): - raise WrongArgType(arg, "Number") - - if prev.to_number() != arg.to_number(): - return W_Boolean(False) - prev = arg - - return W_Boolean(True) - -class List(W_Procedure): - _symbol_name = "list" - - def procedure(self, ctx, lst): - return plst2lst(lst) - -class Cons(W_Procedure): - _symbol_name = "cons" - - def procedure(self, ctx, lst): - w_car = lst[0] - w_cdr = lst[1] - #cons is always creating a new pair - return W_Pair(w_car, w_cdr) - -class Car(W_Procedure): - _symbol_name = "car" - - def procedure(self, ctx, lst): - w_pair = lst[0] - if not isinstance(w_pair, W_Pair): - raise WrongArgType(w_pair, "Pair") - return w_pair.car - -class Cdr(W_Procedure): - _symbol_name = "cdr" - - def procedure(self, ctx, lst): - w_pair = lst[0] - if not isinstance(w_pair, W_Pair): - raise WrongArgType(w_pair, "Pair") - return w_pair.cdr - -class SetCar(W_Procedure): - _symbol_name = "set-car!" - - def procedure(self, ctx, lst): - w_pair = lst[0] - w_obj = lst[1] - if not isinstance(w_pair, W_Pair): - raise WrongArgType(w_pair, "Pair") - - w_pair.car = w_obj - return w_undefined - -class SetCdr(W_Procedure): - _symbol_name = "set-cdr!" - - def procedure(self, ctx, lst): - w_pair = lst[0] - w_obj = lst[1] - if not isinstance(w_pair, W_Pair): - raise WrongArgType(w_pair, "Pair") - - w_pair.cdr = w_obj - return w_undefined - -class Apply(W_Procedure): - _symbol_name = "apply" - - def procedure_tr(self, ctx, lst): - if len(lst) != 2: - raise WrongArgsNumber - - (w_procedure, w_lst) = lst - if not isinstance(w_procedure, W_Procedure): - raise WrongArgType(w_procedure, "Procedure") - - if not isinstance(w_lst, W_List): - raise WrongArgType(w_lst, "List") - - return w_procedure.call_tr(ctx, w_lst) - -class Quit(W_Procedure): - _symbol_name = "quit" - - def procedure(self, ctx, lst): - raise SchemeQuit - -class Force(W_Procedure): - _symbol_name = "force" - - def procedure(self, ctx, lst): - if len(lst) != 1: - raise WrongArgsNumber - - w_promise = lst[0] - if not isinstance(w_promise, W_Promise): - raise WrongArgType(w_promise, "Promise") - - return w_promise.force(ctx) - -## -# Equivalnece Predicates -## -class EquivalnecePredicate(W_Procedure): - def procedure(self, ctx, lst): - if len(lst) != 2: - raise WrongArgsNumber - (a, b) = lst - return W_Boolean(self.predicate(a, b)) - -class EqP(EquivalnecePredicate): - _symbol_name = "eq?" - - def predicate(self, a, b): - return a.eq(b) - -class EqvP(EquivalnecePredicate): - _symbol_name = "eqv?" - - def predicate(self, a, b): - return a.eqv(b) - -class EqualP(EquivalnecePredicate): - _symbol_name = "equal?" - - def predicate(self, a, b): - return a.equal(b) - -## -# Number Predicates -## -class PredicateNumber(W_Procedure): - def procedure(self, ctx, lst): - if len(lst) != 1: - raise WrongArgsNumber - - w_obj = lst[0] - if not isinstance(w_obj, W_Number): - raise WrongArgType(w_obj, "Number") - - return W_Boolean(self.predicate(w_obj)) - - def predicate(self, w_obj): - raise NotImplementedError - -class IntegerP(PredicateNumber): - _symbol_name = "integer?" - - def predicate(self, w_obj): - if not w_obj.exact: - return w_obj.is_integer() - - return True - -class RealP(PredicateNumber): - _symbol_name = "real?" - - def predicate(self, w_obj): - return isinstance(w_obj, W_Real) - -class RationalP(RealP): - _symbol_name = "rational?" - -class NumberP(PredicateNumber): - _symbol_name = "number?" - - def predicate(self, w_obj): - return isinstance(w_obj, W_Number) - -class ComplexP(NumberP): - _symbol_name = "complex?" - -class ExactP(PredicateNumber): - _symbol_name = "exact?" - - def predicate(self, w_obj): - return w_obj.exact - -class InexactP(PredicateNumber): - _symbol_name = "inexact?" - - def predicate(self, w_obj): - return not w_obj.exact - -class ZeroP(PredicateNumber): - _symbol_name = "zero?" - - def predicate(self, w_obj): - return w_obj.to_number() == 0.0 - -class OddP(PredicateNumber): - _symbol_name = "odd?" - - def predicate(self, w_obj): - if not w_obj.is_integer(): - raise WrongArgType(w_obj, "Integer") - - return w_obj.round() % 2 != 0 - -class EvenP(PredicateNumber): - _symbol_name = "even?" - - def predicate(self, w_obj): - if not w_obj.is_integer(): - raise WrongArgType(w_obj, "Integer") - - return w_obj.round() % 2 == 0 - ## -# Type Pradicates +# Parser helpers ## -class TypePredicate(W_Procedure): - def procedure(self, ctx, lst): - if len(lst) != 1: - raise WrongArgsNumber - - return W_Boolean(self.predicate(lst[0])) - -class BooleanP(TypePredicate): - _symbol_name = "boolean?" - - def predicate(self, w_obj): - return isinstance(w_obj, W_Boolean) - -class SymbolP(TypePredicate): - _symbol_name = "symbol?" - - def predicate(self, w_obj): - return isinstance(w_obj, W_Symbol) - -class PairP(TypePredicate): - _symbol_name = "pair?" - - def predicate(self, w_obj): - return isinstance(w_obj, W_Pair) - -class ProcedureP(TypePredicate): - _symbol_name = "procedure?" - - def predicate(self, w_obj): - return isinstance(w_obj, W_Procedure) - -## -# Input/Output procedures -## -#class Display(W_Procedure): -# _symbol_name = "display" -# -# def procedure(self, ctx, lst): -# if len(lst) == 1: -# obj = lst[0] -# elif len(lst) == 2: -# (obj, port) = lst -# raise NotImplementedError -# else: -# raise WrongArgsNumber -# -# print obj.to_string() -# return w_undefined - -## -# Macro -## -class Define(W_Macro): - _symbol_name = "define" - - def continue_tr(self, ctx, lst, elst, cnt=True): - w_first = lst - w_val = elst[0] - if isinstance(w_first, W_Symbol): - ctx.set(w_first.name, w_val) - if len(ctx.cont_stack) == 0: - raise ContinuationReturn(w_val) - - cont = ctx.cont_stack.pop() - return cont.run(ctx, w_val) - - raise SchemeSyntaxError - - def call(self, ctx, lst): - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - w_first = lst.car - w_second = lst.get_cdr_as_pair() - if isinstance(w_first, W_Symbol): - w_val = w_second.car.eval_cf(ctx, self, w_first) - ctx.set(w_first.name, w_val) - return w_val #undefined - elif isinstance(w_first, W_Pair): - #we have lambda definition here! - w_name = w_first.car - if not isinstance(w_name, W_Symbol): - raise SchemeSyntaxError - - formals = w_first.cdr #isinstance of W_List - body = w_second - #remember this! ContinuationFrame creation - ctx.cont_stack.append(ContinuationFrame(self, w_first)) - w_lambda = W_Lambda(formals, body, ctx, pname=w_name.name) - ctx.cont_stack.pop() - ctx.set(w_name.name, w_lambda) - return w_lambda #undefined - - raise SchemeSyntaxError - -class Sete(W_Macro): - _symbol_name = "set!" - - def continue_tr(self, ctx, lst, elst, cnt=True): - assert cnt == True - w_symbol = lst - w_val = elst[0] - ctx.ssete(w_symbol, w_val) - if len(ctx.cont_stack) == 0: - raise ContinuationReturn(w_val) - - cont = ctx.cont_stack.pop() - return cont.run(ctx, w_val) - - def call(self, ctx, lst): - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - w_symbol = lst.car - - w_val = lst.get_cdr_as_pair().car.eval_cf(ctx, self, w_symbol) - ctx.ssete(w_symbol, w_val) - return w_val #undefined - -class MacroIf(W_Macro): - _symbol_name = "if" - - def call_tr(self, ctx, lst): - #if needs to be tail-recursive aware - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - w_condition = lst.car - lst_cdr = lst.get_cdr_as_pair() - w_then = lst_cdr.car - if lst_cdr.cdr is w_nil: - w_else = W_Boolean(False) - else: - w_else = lst_cdr.get_cdr_as_pair().car - - w_cond_val = w_condition.eval(ctx) - if w_cond_val.to_boolean() is True: - return (w_then, ctx) - else: - return (w_else, ctx) - -class Lambda(W_Macro): - _symbol_name = "lambda" - - def call(self, ctx, lst): - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError(lst, "Pair") - w_args = lst.car - w_body = lst.cdr - return W_Lambda(w_args, w_body, ctx) - -class Begin(W_Macro): - _symbol_name = "begin" - - def call_tr(self, ctx, lst): - #begin uses eval_body, so it is tail-recursive aware - return Body(lst).eval_tr(ctx) - -class Let(W_Macro): - _symbol_name = "let" - - def call_tr(self, ctx, lst): - #let uses eval_body, so it is tail-recursive aware - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - local_ctx = ctx.copy() - body = Body(lst.cdr) - w_formal = lst.car - while isinstance(w_formal, W_Pair): - w_def = w_formal.get_car_as_pair() - #evaluate the values in caller ctx - w_val = w_def.get_cdr_as_pair().car.eval(ctx) - local_ctx.sput(w_def.car, w_val) - w_formal = w_formal.cdr - - return body.eval_tr(local_ctx) - -class LetStar(W_Macro): - _symbol_name = "let*" - - def continue_tr(self, ctx, lst, elst, cnt=True): - ctx = ctx.copy() - (body, w_def, w_val) = elst - ctx.sput(w_def, w_val) - w_formal = lst - while isinstance(w_formal, W_Pair): - w_def = w_formal.get_car_as_pair() - w_val = w_def.get_cdr_as_pair().car.eval_cf(ctx, \ - self, w_formal.cdr, [elst[0], w_def.car], 2) - ctx.sput(w_def.car, w_val) - w_formal = w_formal.cdr - - w_result = body.eval(ctx) - - if len(ctx.cont_stack) == 0: - raise ContinuationReturn(w_result) - - cont = ctx.cont_stack.pop() - return cont.run(ctx, w_result) - - def call_tr(self, ctx, lst): - #let* uses eval_body, so it is tail-recursive aware - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - local_ctx = ctx.copy() - body = Body(lst.cdr) - w_formal = lst.car - while isinstance(w_formal, W_Pair): - w_def = w_formal.get_car_as_pair() - #evaluate the values in local ctx - w_val = w_def.get_cdr_as_pair().car.eval_cf(local_ctx, \ - self, w_formal.cdr, [body, w_def.car], 2) - local_ctx.sput(w_def.car, w_val) - w_formal = w_formal.cdr - - return body.eval_tr(local_ctx) - -class DictWrapper(W_Root): - def __init__(self, w_dict): - self.d = w_dict - -class Letrec(W_Macro): - _symbol_name = "letrec" - - def continue_tr(self, ctx, lst, elst, cnt=True): - ctx = ctx.copy() - (body, name_symb, name_val, cont_val) = elst - assert isinstance(name_symb, DictWrapper) - assert isinstance(name_val, DictWrapper) - assert isinstance(lst, W_Symbol) - - cont_name = lst.name - for (name, w_val) in name_val.d.items(): - if name == cont_name: - ctx.ssete(lst, cont_val) - else: - ctx.ssete(name_symb.d[name], w_val) - - w_result = body.eval(ctx) - - if len(ctx.cont_stack) == 0: - raise ContinuationReturn(w_result) - - cont = ctx.cont_stack.pop() - return cont.run(ctx, w_result) - - def call_tr(self, ctx, lst): - """let uses eval_body, so it is tail-recursive aware""" - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - local_ctx = ctx.copy() - body = Body(lst.cdr) - map_name_expr = {} - map_name_symb = {} - w_name_symb = DictWrapper(map_name_symb) - w_formal = lst.car - while isinstance(w_formal, W_Pair): - w_def = w_formal.get_car_as_pair() - name = w_def.car.to_string() - map_name_expr[name] = w_def.get_cdr_as_pair().car - map_name_symb[name] = w_def.car - local_ctx.sbind(w_def.car) - w_formal = w_formal.cdr - - map_name_val = {} - w_name_val = DictWrapper(map_name_val) - for (name, expr) in map_name_expr.items(): - map_name_val[name] = expr.eval_cf(local_ctx, self, - map_name_symb[name], - [body, w_name_symb, w_name_val], 3) - - for (name, w_val) in map_name_val.items(): - local_ctx.ssete(map_name_symb[name], w_val) - - return body.eval_tr(local_ctx) - def quote(sexpr): return W_Pair(W_Symbol('quote'), W_Pair(sexpr, w_nil)) @@ -1081,103 +490,17 @@ def unquote_splicing(sexpr): return W_Pair(W_Symbol('unquote-splicing'), W_Pair(sexpr, w_nil)) -class Quote(W_Macro): - _symbol_name = "quote" - - def call(self, ctx, lst): - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - - return lst.car - -class QuasiQuote(W_Macro): - _symbol_name = "quasiquote" - - def call(self, ctx, lst): - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError - - w_lst = self.unquote(ctx, lst.car, 1) - return w_lst - - def unquote(self, ctx, w_lst, deep): - if deep < 1: - raise SchemeSyntaxError - - if isinstance(w_lst, W_Pair): - w_oper = w_lst.car - if isinstance(w_oper, W_Symbol): - if w_oper.to_string() == "unquote": - - #simply unquote - if deep == 1: - return w_lst.get_cdr_as_pair().car.eval(ctx) - - #not first level, look deeper, with lower nesting level - if deep > 1: - w_unq = self.unquote(ctx, - w_lst.get_cdr_as_pair().car, - deep-1) - - return W_Pair(w_oper, W_Pair(w_unq, w_nil)) - - #increment nesting level - if w_oper.to_string() == "quasiquote": - w_unq = self.unquote(ctx, - w_lst.get_cdr_as_pair().car, - deep+1) - return W_Pair(w_oper, W_Pair(w_unq, w_nil)) - - #not first level, look deeper, with lower nesting level - if deep > 1 and w_oper.to_string() == "unquote-splicing": - w_unq = self.unquote(ctx, - w_lst.get_cdr_as_pair().car, - deep-1) - - return W_Pair(w_oper, W_Pair(w_unq, w_nil)) - - #for unquote-splice we need to check one level earlier - #cond = if we have w_oper = (unquote-splice ) - if deep == 1 and isinstance(w_oper, W_Pair) and \ - isinstance(w_oper.car, W_Symbol) and \ - w_oper.car.to_string() == "unquote-splicing": - - #rest of list, needed for "stripping away" closing parens - w_unq_cdr = self.unquote(ctx, w_lst.cdr, deep) - - #unquote into list - w_unq = w_oper.get_cdr_as_pair().car.eval(ctx) - #w_unq must be proper list - if w_unq is w_nil: - #if nil: reeturn only rest of list - return w_unq_cdr - - #traverse w_unq to find last cdr and set it to w_cdr - w_pair = w_unq - while isinstance(w_pair, W_Pair): - if w_pair.cdr is w_nil: - w_pair.cdr = w_unq_cdr - break - - w_pair = w_pair.cdr - - return w_unq - - #no special cases, traverse tree - return W_Pair(self.unquote(ctx, w_oper, deep), - self.unquote(ctx, w_lst.cdr, deep)) - - #trivial case, just return - return w_lst - -class Delay(W_Macro): - _symbol_name = "delay" - def call(self, ctx, lst): - if not isinstance(lst, W_Pair): - raise SchemeSyntaxError +## +# General helpers +## +def plst2lst(plst, w_cdr=w_nil): + """coverts python list() of W_Root into W_Pair scheme list""" + plst.reverse() + for w_obj in plst: + w_cdr = W_Pair(w_obj, w_cdr) - return W_Promise(lst.car, ctx) + return w_cdr ## # Continuations From jlg at codespeak.net Mon Aug 27 19:48:46 2007 From: jlg at codespeak.net (jlg at codespeak.net) Date: Mon, 27 Aug 2007 19:48:46 +0200 (CEST) Subject: [pypy-svn] r46054 - pypy/dist/pypy/lang/scheme Message-ID: <20070827174846.106C4811C@code0.codespeak.net> Author: jlg Date: Mon Aug 27 19:48:39 2007 New Revision: 46054 Modified: pypy/dist/pypy/lang/scheme/procedure.py Log: predicates have default predicate method raising NotImplementedError -> rpythonic Modified: pypy/dist/pypy/lang/scheme/procedure.py ============================================================================== --- pypy/dist/pypy/lang/scheme/procedure.py (original) +++ pypy/dist/pypy/lang/scheme/procedure.py Mon Aug 27 19:48:39 2007 @@ -216,6 +216,9 @@ (a, b) = lst return W_Boolean(self.predicate(a, b)) + def predicate(self, a, b): + raise NotImplementedError + class EqP(EquivalnecePredicate): _symbol_name = "eq?" @@ -324,6 +327,9 @@ return W_Boolean(self.predicate(lst[0])) + def predicate(self, w_obj): + raise NotImplementedError + class BooleanP(TypePredicate): _symbol_name = "boolean?" From simonb at codespeak.net Mon Aug 27 20:29:39 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Mon, 27 Aug 2007 20:29:39 +0200 (CEST) Subject: [pypy-svn] r46058 - in pypy/dist/pypy/rpython/numpy: . test Message-ID: <20070827182939.2A761815F@code0.codespeak.net> Author: simonb Date: Mon Aug 27 20:29:37 2007 New Revision: 46058 Modified: pypy/dist/pypy/rpython/numpy/aarray.py pypy/dist/pypy/rpython/numpy/test/test_array.py Log: hacking on numpy, implement some coercion, ran into problem with SomeExternalObject method annotation Modified: pypy/dist/pypy/rpython/numpy/aarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/aarray.py (original) +++ pypy/dist/pypy/rpython/numpy/aarray.py Mon Aug 27 20:29:37 2007 @@ -1,10 +1,10 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation.pairtype import pairtype from pypy.annotation.model import SomeExternalObject, SomeList, SomeImpossibleValue -from pypy.annotation.model import SomeInteger, SomeFloat, SomeString, SomeChar -from pypy.annotation.listdef import ListDef +from pypy.annotation.model import SomeObject, SomeInteger, SomeFloat, SomeString, SomeChar from pypy.tool.error import AnnotatorError from pypy.rpython.lltypesystem import rffi +from pypy.rlib import rarithmetic import numpy @@ -21,13 +21,13 @@ 'I' : SomeInteger(knowntype=rffi.r_uint), 'L' : SomeInteger(knowntype=rffi.r_ulong), 'Q' : SomeInteger(knowntype=rffi.r_ulonglong), - 'f' : SomeFloat(), # XX single precision float XX + #'f' : SomeFloat(), # XX single precision float XX 'd' : SomeFloat(), } - def __init__(self, knowntype, typecode): - self.knowntype = knowntype + def __init__(self, knowntype, typecode, rank=1): + self.knowntype = knowntype # == numpy.ndarray (do we need this for anything?) self.typecode = typecode - self.rank = 1 + self.rank = rank def can_be_none(self): return True @@ -47,9 +47,24 @@ return self.typecode_to_item[self.typecode] class __extend__(pairtype(SomeArray, SomeArray)): - def add((s_arr1,s_arr2)): - # TODO: coerce the array types - return SomeArray(s_arr1.knowntype, s_arr1.typecode) + + def union((s_arr1, s_arr2)): + item1 = s_arr1.get_item_type() + item2 = s_arr2.get_item_type() + typecode = None + if float in (item1.knowntype, item2.knowntype): + typecode = 'd' + else: + item_knowntype = rarithmetic.compute_restype(item1.knowntype, item2.knowntype) + for typecode, s_item in SomeArray.typecode_to_item.items(): + if s_item.knowntype == item_knowntype: + break + if typecode is None: + raise AnnotatorError() + return SomeArray(s_arr1.knowntype, typecode) + + add = sub = mul = div = truediv = union + class __extend__(pairtype(SomeArray, SomeInteger)): def setitem((s_cto, s_index), s_value): @@ -71,7 +86,7 @@ (SomeInteger, rffi.r_uint) : 'I', (SomeInteger, rffi.r_ulong) : 'L', (SomeInteger, rffi.r_ulonglong) : 'Q', - (SomeFloat, float) : 'f', + #(SomeFloat, float) : 'f', (SomeFloat, float) : 'd', } valid_typecodes='bhilqBHILQfd' @@ -87,7 +102,7 @@ # First guess type from input list listitem = arg_list.listdef.listitem key = type(listitem.s_value), listitem.s_value.knowntype - typecode = numpy_typedict.get( key, None ) + typecode = numpy_typedict.get(key, None) # now see if the dtype arg over-rides the typecode dtype = None @@ -119,6 +134,11 @@ from pypy.rpython.numpy.rarray import ArrayRepr return ArrayRepr(rtyper, s_array) + def get_field_annotation(self, knowntype, fieldname): + if fieldname in ('transpose',): + # XX knowntype is not enough to learn annotation from XX + return SomeArray() + # Importing for side effect of registering types with extregistry Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Mon Aug 27 20:29:37 2007 @@ -13,6 +13,7 @@ from pypy.rpython.lltypesystem import rffi from pypy.rpython.rint import IntegerRepr from pypy.rpython.numpy.rarray import ArrayRepr +from pypy.rpython.numpy.aarray import SomeArray import numpy @@ -24,13 +25,13 @@ return my_array[0] class Test_annotation: - def test_annotate_array_access_int(self): + def test_array_access_int(self): t = TranslationContext() a = t.buildannotator() s = a.build_types(access_array, [int]) assert s.knowntype == rffi.r_int - def test_annotate_array_access_float(self): + def test_array_access_float(self): t = TranslationContext() a = t.buildannotator() s = a.build_types(access_array, [float]) @@ -39,9 +40,9 @@ if conftest.option.view: t.view() - def test_annotate_array_access_bytype(self): + def test_array_access_bytype(self): def access_array_bytype(dummy): - my_array = numpy.array([1],'f') + my_array = numpy.array([1],'d') return my_array[0] t = TranslationContext() @@ -52,7 +53,7 @@ if conftest.option.view: t.view() - def test_annotate_array_access_variable(self): + def test_array_access_variable(self): def access_with_variable(): my_array = numpy.array(range(10)) my_array[2] = 2 @@ -67,6 +68,40 @@ s = a.build_types(access_with_variable, []) assert s.knowntype == rffi.r_int + def test_array_add(self): + def f(): + a1 = numpy.array([1,2]) + a2 = numpy.array([6,9]) + return a1 + a2 + + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(f, []) + assert s.typecode == 'i' + + def test_array_add_coerce(self): + def f(): + a1 = numpy.array([1,2]) + a2 = numpy.array([6.,9.]) + return a1 + a2 + + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(f, []) + assert s.typecode == 'd' + + def test_array_method(self): + def f(): + a1 = numpy.array([1,2]) + return a1.transpose() + + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(f, []) + assert type(s) == SomeArray + + + class Test_specialization: def test_specialize_array_create(self): def create_array(): From antocuni at codespeak.net Mon Aug 27 20:41:36 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 20:41:36 +0200 (CEST) Subject: [pypy-svn] r46059 - pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template Message-ID: <20070827184136.C46518177@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 20:41:36 2007 New Revision: 46059 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/operations.py Log: forgot to checkin this Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/operations.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/operations.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/operations.py Mon Aug 27 20:41:36 2007 @@ -199,3 +199,9 @@ return 0 assert self.interpret(f, [5]) == 0 + def test_ullong_rshift(self): + def f(x): + return x >> 1 + x = sys.maxint+1 + assert self.interpret(f, [r_ulonglong(x)]) == x >> 1 + From simonb at codespeak.net Mon Aug 27 20:58:44 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Mon, 27 Aug 2007 20:58:44 +0200 (CEST) Subject: [pypy-svn] r46061 - pypy/dist/pypy/rpython/numpy Message-ID: <20070827185844.D4F638180@code0.codespeak.net> Author: simonb Date: Mon Aug 27 20:58:44 2007 New Revision: 46061 Modified: pypy/dist/pypy/rpython/numpy/aarray.py Log: fix annotation of numpy attribute access Modified: pypy/dist/pypy/rpython/numpy/aarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/aarray.py (original) +++ pypy/dist/pypy/rpython/numpy/aarray.py Mon Aug 27 20:58:44 2007 @@ -1,7 +1,8 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation.pairtype import pairtype from pypy.annotation.model import SomeExternalObject, SomeList, SomeImpossibleValue -from pypy.annotation.model import SomeObject, SomeInteger, SomeFloat, SomeString, SomeChar +from pypy.annotation.model import SomeObject, SomeInteger, SomeFloat, SomeString, SomeChar,\ + SomeGenericCallable from pypy.tool.error import AnnotatorError from pypy.rpython.lltypesystem import rffi from pypy.rlib import rarithmetic @@ -46,6 +47,19 @@ def get_item_type(self): return self.typecode_to_item[self.typecode] + def getattr(s_array, s_attr): + s = None + if s_attr.is_constant() and isinstance(s_attr.const, str): + attr = s_attr.const + if attr in ('transpose',): + s_result = SomeArray(s_array.knowntype, s_array.typecode, s_array.rank) + s = SomeGenericCallable([], s_result) + elif attr == 'shape': + s = SomeTuple([SomeInteger()]*s_array.rank) + if s is None: + return SomeObject() + return s + class __extend__(pairtype(SomeArray, SomeArray)): def union((s_arr1, s_arr2)): @@ -134,11 +148,6 @@ from pypy.rpython.numpy.rarray import ArrayRepr return ArrayRepr(rtyper, s_array) - def get_field_annotation(self, knowntype, fieldname): - if fieldname in ('transpose',): - # XX knowntype is not enough to learn annotation from XX - return SomeArray() - # Importing for side effect of registering types with extregistry From antocuni at codespeak.net Mon Aug 27 21:03:11 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 21:03:11 +0200 (CEST) Subject: [pypy-svn] r46062 - in pypy/branch/pypy-more-rtti-inprogress/translator/cli: . src test Message-ID: <20070827190311.8E2318180@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 21:03:10 2007 New Revision: 46062 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/database.py pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/ll_os.cs pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py Log: make os.environ work again with gencli Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/database.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/database.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/database.py Mon Aug 27 21:03:10 2007 @@ -29,6 +29,9 @@ ootype.Record({"item0": ootype.Float, "item1": ootype.Float}): '[pypylib]pypy.runtime.Record_Float_Float', + ootype.Record({"item0": ootype.String, "item1": ootype.String}): + '[pypylib]pypy.runtime.Record_String_String', + ll_os.STAT_RESULT: '[pypylib]pypy.runtime.Record_Stat_Result', } Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/ll_os.cs ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/ll_os.cs (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/ll_os.cs Mon Aug 27 21:03:10 2007 @@ -145,7 +145,6 @@ private static Dictionary FileDescriptors; private static int fdcount; private static Dictionary ErrorMessages; - private static SortedList MyEnviron; // NB: these values are those used by Windows and they differs // from the Unix ones; the os module is patched with these @@ -167,8 +166,6 @@ static ll_os() { ErrorMessages = new Dictionary(); - MyEnviron = new SortedList(Environment.GetEnvironmentVariables()); - FileDescriptors = new Dictionary(); // XXX: what about CRLF conversion for stdin, stdout and stderr? // It seems that Posix let you read from stdout and @@ -347,29 +344,41 @@ File.Delete(path); } - public static string ll_os_environ(int index) + public static void ll_os_putenv(string key, string value) { - try { - string key = (string)MyEnviron.GetKey(index); - string value = (string)MyEnviron.GetByIndex(index); - return string.Format("{0}={1}", key, value); - } - catch(ArgumentOutOfRangeException) { - return null; - } + Environment.SetEnvironmentVariable(key, value); } - public static void ll_os_putenv(string s) + public static string ll_os_getenv(string key) { - char[] delim = {'='}; - string[] parts = s.Split(delim, 2); - Environment.SetEnvironmentVariable(parts[0], parts[1]); + return Environment.GetEnvironmentVariable(key); } public static void ll_os_unsetenv(string s) { Environment.SetEnvironmentVariable(s, null); } + + public static pypy.runtime.List ll_os_envitems() + { + pypy.runtime.List env = new pypy.runtime.List(); + foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables()) + { + Record_String_String var = new Record_String_String(); + var.item0 = (string)entry.Key; + var.item1 = (string)entry.Value; + env.Add(var); + } + return env; + } + + public static pypy.runtime.List ll_os_envkeys() + { + pypy.runtime.List keys = new pypy.runtime.List(); + foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables()) + keys.Add((string)entry.Key); + return keys; + } public static long ll_os_lseek(int fd, int offset, int whence) { Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs Mon Aug 27 21:03:10 2007 @@ -588,6 +588,18 @@ public override int GetHashCode() { return item0.GetHashCode(); } } + public class Record_String_String { + public string item0; + public string item1; + public override string ToString() { return string.Format("({0}, {1},)", item0, item1); } + public override bool Equals(object obj) + { + Record_String_String x = (Record_String_String)obj; + return item0 == x.item0 && item1 == x.item1; + } + public override int GetHashCode() { return item0.GetHashCode(); } + } + public class Record_Stat_Result { public int item0, item1, item2, item3, item4, item5, item6, item7, item8, item9; public override string ToString() Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py Mon Aug 27 21:03:10 2007 @@ -112,6 +112,21 @@ res = self.ll_to_string(self.interpret(fn, [])) # XXX assert something about res + def test_environ(self): + def fn(): + os.environ['PYPY_TEST_ENVIRON'] = '42' + return os.environ['PYPY_TEST_ENVIRON'] + assert self.interpret(fn, []) == '42' + + def test_environ_items(self): + def fn(): + env = os.environ.items() + env2 = [] + for key in os.environ.keys(): + env2.append((key, os.environ[key])) + assert env == env2 + self.interpret(fn, []) + def test_os_listdir(self): def fn(): return os.listdir('.') From antocuni at codespeak.net Mon Aug 27 21:17:48 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 27 Aug 2007 21:17:48 +0200 (CEST) Subject: [pypy-svn] r46063 - pypy/branch/pypy-more-rtti-inprogress/translator/cli/src Message-ID: <20070827191748.4E5E381C7@code0.codespeak.net> Author: antocuni Date: Mon Aug 27 21:17:46 2007 New Revision: 46063 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/ll_os.cs pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs Log: fix some signature mismatch. pypy-cli works again on the branch/ Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/ll_os.cs ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/ll_os.cs (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/ll_os.cs Mon Aug 27 21:17:46 2007 @@ -380,7 +380,7 @@ return keys; } - public static long ll_os_lseek(int fd, int offset, int whence) + public static long ll_os_lseek(int fd, long offset, int whence) { SeekOrigin origin = SeekOrigin.Begin; switch(whence) Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs Mon Aug 27 21:17:46 2007 @@ -601,7 +601,8 @@ } public class Record_Stat_Result { - public int item0, item1, item2, item3, item4, item5, item6, item7, item8, item9; + public int item0, item3, item4, item5, item7, item8, item9; + public long item1, item2, item6; public override string ToString() { return string.Format("({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9},)", From pedronis at codespeak.net Mon Aug 27 23:33:19 2007 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 27 Aug 2007 23:33:19 +0200 (CEST) Subject: [pypy-svn] r46064 - pypy/branch/pypy-more-rtti-inprogress/translator/c/src Message-ID: <20070827213319.973238185@code0.codespeak.net> Author: pedronis Date: Mon Aug 27 23:33:17 2007 New Revision: 46064 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread.c Log: fix the include, this make some of module/thread test pass on Mac OS X Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread.c ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread.c (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/thread.c Mon Aug 27 23:33:17 2007 @@ -1,2 +1,2 @@ #include -#include +#include From simonb at codespeak.net Tue Aug 28 02:30:38 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Tue, 28 Aug 2007 02:30:38 +0200 (CEST) Subject: [pypy-svn] r46065 - in pypy/dist/pypy/rpython/numpy: . test Message-ID: <20070828003038.03D70813D@code0.codespeak.net> Author: simonb Date: Tue Aug 28 02:30:36 2007 New Revision: 46065 Modified: pypy/dist/pypy/rpython/numpy/aarray.py pypy/dist/pypy/rpython/numpy/rarray.py pypy/dist/pypy/rpython/numpy/test/test_array.py Log: numpy: fix method handling, add attribute lookup Modified: pypy/dist/pypy/rpython/numpy/aarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/aarray.py (original) +++ pypy/dist/pypy/rpython/numpy/aarray.py Tue Aug 28 02:30:36 2007 @@ -2,14 +2,14 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation.model import SomeExternalObject, SomeList, SomeImpossibleValue from pypy.annotation.model import SomeObject, SomeInteger, SomeFloat, SomeString, SomeChar,\ - SomeGenericCallable + SomeTuple from pypy.tool.error import AnnotatorError from pypy.rpython.lltypesystem import rffi from pypy.rlib import rarithmetic import numpy -class SomeArray(SomeExternalObject): +class SomeArray(SomeObject): """Stands for an object from the numpy module.""" typecode_to_item = { 'b' : SomeInteger(knowntype=rffi.r_signedchar), @@ -25,10 +25,10 @@ #'f' : SomeFloat(), # XX single precision float XX 'd' : SomeFloat(), } - def __init__(self, knowntype, typecode, rank=1): + def __init__(self, knowntype, typecode, ndim=1): self.knowntype = knowntype # == numpy.ndarray (do we need this for anything?) self.typecode = typecode - self.rank = rank + self.ndim = ndim def can_be_none(self): return True @@ -51,15 +51,17 @@ s = None if s_attr.is_constant() and isinstance(s_attr.const, str): attr = s_attr.const - if attr in ('transpose',): - s_result = SomeArray(s_array.knowntype, s_array.typecode, s_array.rank) - s = SomeGenericCallable([], s_result) - elif attr == 'shape': - s = SomeTuple([SomeInteger()]*s_array.rank) + if attr == 'shape': + s = SomeTuple([SomeInteger()]*s_array.ndim) + elif attr == 'ndim': + s = SomeInteger() if s is None: - return SomeObject() + return SomeObject.getattr(s_array, s_attr) return s + def method_transpose(self): + return SomeArray(self.knowntype, self.typecode, self.ndim) + class __extend__(pairtype(SomeArray, SomeArray)): def union((s_arr1, s_arr2)): @@ -85,7 +87,7 @@ pass def getitem((s_cto, s_index)): - # TODO: higher ranked arrays have getitem returns SomeArray + # TODO: higher ndimed arrays have getitem returns SomeArray return s_cto.get_item_type() numpy_typedict = { Modified: pypy/dist/pypy/rpython/numpy/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/rarray.py (original) +++ pypy/dist/pypy/rpython/numpy/rarray.py Tue Aug 28 02:30:36 2007 @@ -6,7 +6,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.lltypesystem.lltype import \ GcArray, GcStruct, Signed, Ptr, Unsigned, malloc, Void -from pypy.annotation.model import SomeInteger +from pypy.annotation.model import SomeObject, SomeInteger from pypy.rpython.numpy.aarray import SomeArray from pypy.annotation.pairtype import pairtype @@ -17,16 +17,39 @@ self.item_repr = rtyper.getrepr(self.s_value) ITEM = self.item_repr.lowleveltype ITEMARRAY = GcArray(ITEM) + SIZEARRAY = GcArray(Signed) self.ARRAY = Ptr( - GcStruct( "array", -# ("length", Signed), - ("data", Ptr(ITEMARRAY)))) + GcStruct("array", + ("data", Ptr(ITEMARRAY)), # pointer to raw data buffer + ("nd", Signed), # number of dimensions, also called ndim + ("dimensions", Ptr(SIZEARRAY)), # size in each dimension + ("strides", Ptr(SIZEARRAY)), # bytes to jump to get to the + # next element in each dimension + )) self.lowleveltype = self.ARRAY def allocate_instance(self, llops, v_array): c1 = inputconst(lltype.Void, self.lowleveltype.TO) return llops.gendirectcall(ll_allocate, c1, v_array) + def rtype_method_transpose(self, hop): + [v_self] = hop.inputargs(self) + cARRAY = hop.inputconst(Void, hop.r_result.ARRAY.TO) + return hop.gendirectcall(ll_transpose, cARRAY, v_self) + + def rtype_getattr(self, hop): + s_attr = hop.args_s[1] + if s_attr.is_constant() and isinstance(s_attr.const, str): + attr = s_attr.const + s_obj = hop.args_s[0] + vobj, vattr = hop.inputargs(self, Void) + llops = hop.llops + if attr == 'ndim': + cname = inputconst(Void, 'nd') + return llops.genop('getfield', [vobj, cname], resulttype=Signed) + return Repr.rtype_getattr(self, hop) + + class __extend__(SomeArray): def rtyper_makerepr(self, rtyper): return ArrayRepr( rtyper, self ) @@ -34,14 +57,15 @@ def rtyper_makekey(self): return self.__class__, self.knowntype -class __extend__(pairtype(ArrayRepr,ArrayRepr)): + +class __extend__(pairtype(ArrayRepr, ArrayRepr)): def rtype_add((r_arr1,r_arr2), hop): v_arr1, v_arr2 = hop.inputargs(r_arr1, r_arr2) cARRAY = hop.inputconst(Void, hop.r_result.ARRAY.TO) return hop.gendirectcall(ll_add, cARRAY, v_arr1, v_arr2) -class __extend__(pairtype(ArrayRepr,IntegerRepr)): +class __extend__(pairtype(ArrayRepr, IntegerRepr)): def rtype_setitem((r_arr,r_int), hop): v_array, v_index, v_item = hop.inputargs(r_arr, Signed, r_arr.item_repr) return hop.gendirectcall(ll_setitem, v_array, v_index, v_item) @@ -72,11 +96,13 @@ while i < size: data[i] = lst.ll_getitem_fast(i) i += 1 + array.nd = 1 return array def ll_allocate(ARRAY, array): new_array = malloc(ARRAY) - new_array.data = array.data + new_array.data = array.data # alias data + new_array.nd = array.nd return new_array def ll_setitem(l, index, item): @@ -97,5 +123,10 @@ i += 1 return array +def ll_transpose(ARRAY, a1): + a2 = ll_allocate(ARRAY, a1) + # XX do something to a2 + return a2 + Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Tue Aug 28 02:30:36 2007 @@ -5,6 +5,7 @@ import py import pypy.rpython.numpy.implementation from pypy.annotation import model as annmodel +from pypy.annotation.model import SomeTuple from pypy.annotation.annrpython import RPythonAnnotator from pypy.translator.translator import TranslationContext from pypy import conftest @@ -25,13 +26,13 @@ return my_array[0] class Test_annotation: - def test_array_access_int(self): + def test_annotate_array_access_int(self): t = TranslationContext() a = t.buildannotator() s = a.build_types(access_array, [int]) assert s.knowntype == rffi.r_int - def test_array_access_float(self): + def test_annotate_array_access_float(self): t = TranslationContext() a = t.buildannotator() s = a.build_types(access_array, [float]) @@ -40,7 +41,7 @@ if conftest.option.view: t.view() - def test_array_access_bytype(self): + def test_annotate_array_access_bytype(self): def access_array_bytype(dummy): my_array = numpy.array([1],'d') return my_array[0] @@ -53,7 +54,7 @@ if conftest.option.view: t.view() - def test_array_access_variable(self): + def test_annotate_array_access_variable(self): def access_with_variable(): my_array = numpy.array(range(10)) my_array[2] = 2 @@ -68,7 +69,7 @@ s = a.build_types(access_with_variable, []) assert s.knowntype == rffi.r_int - def test_array_add(self): + def test_annotate_array_add(self): def f(): a1 = numpy.array([1,2]) a2 = numpy.array([6,9]) @@ -79,7 +80,7 @@ s = a.build_types(f, []) assert s.typecode == 'i' - def test_array_add_coerce(self): + def test_annotate_array_add_coerce(self): def f(): a1 = numpy.array([1,2]) a2 = numpy.array([6.,9.]) @@ -90,7 +91,17 @@ s = a.build_types(f, []) assert s.typecode == 'd' - def test_array_method(self): + def test_annotate_array_attr(self): + def f(): + a1 = numpy.array([1,2]) + return a1.shape + + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(f, []) + assert type(s) == SomeTuple + + def test_annotate_array_method(self): def f(): a1 = numpy.array([1,2]) return a1.transpose() @@ -134,6 +145,23 @@ assert res.data[0] == 7 assert res.data[1] == 11 + def test_specialize_array_attr(self): + def create_array(): + a = numpy.array([1,2]) + return a.ndim + + res = interpret(create_array, []) + assert res == 1 + + def test_specialize_array_method(self): + def create_array(): + a = numpy.array([1,2]) + return a.transpose() + + res = interpret(create_array, []) + assert res.data[0] == 1 + assert res.data[1] == 2 + class Test_compile: def setup_class(self): if not test_c_compile: From fijal at codespeak.net Tue Aug 28 12:54:53 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 12:54:53 +0200 (CEST) Subject: [pypy-svn] r46086 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070828105453.E0CD2813A@code0.codespeak.net> Author: fijal Date: Tue Aug 28 12:54:53 2007 New Revision: 46086 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: Stick pointer to function object for debugging Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Tue Aug 28 12:54:53 2007 @@ -56,6 +56,8 @@ real_args = real_args + (args[i],) return funcptr(*real_args) wrapper._always_inline_ = True + # for debugging, stick ll func ptr to that + wrapper._ptr = funcptr return func_with_new_name(wrapper, name) from pypy.rpython.tool.rfficache import platform From fijal at codespeak.net Tue Aug 28 12:55:49 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 12:55:49 +0200 (CEST) Subject: [pypy-svn] r46087 - in pypy/branch/pypy-more-rtti-inprogress/rpython: . test Message-ID: <20070828105549.12A8C813A@code0.codespeak.net> Author: fijal Date: Tue Aug 28 12:55:48 2007 New Revision: 46087 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_llinterp.py Log: Add malloc checking feature to llinterpreter, only works for malloc='raw', not sure if debugging info stored there makes sense, but well... we'll see. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py Tue Aug 28 12:55:48 2007 @@ -42,7 +42,8 @@ class LLInterpreter(object): """ low level interpreter working with concrete values. """ - def __init__(self, typer, heap=llheap, tracing=True, exc_data_ptr=None): + def __init__(self, typer, heap=llheap, tracing=True, exc_data_ptr=None, + malloc_check=True): self.bindings = {} self.typer = typer self.heap = heap #module that provides malloc, etc for lltypes @@ -52,7 +53,9 @@ # prepare_graphs_and_create_gc might already use the llinterpreter! self.gc = None self.tracer = None + self.malloc_check = malloc_check self.frame_class = LLFrame + self.mallocs = {} if hasattr(heap, "prepare_graphs_and_create_gc"): flowgraphs = typer.annotator.translator.graphs self.gc = heap.prepare_graphs_and_create_gc(self, flowgraphs) @@ -158,6 +161,12 @@ return self.exc_data_ptr return None + def remember_malloc(self, ptr, llframe): + # err.... + self.mallocs[ptr._obj] = llframe + + def remember_free(self, ptr): + del self.mallocs[ptr._obj] def checkptr(ptr): assert isinstance(lltype.typeOf(ptr), lltype.Ptr) @@ -633,8 +642,11 @@ return result else: raise ValueError("cannot allocate variable-sized things on the stack") - - return self.heap.malloc(obj, zero=zero, flavor=flavor) + + ptr = self.heap.malloc(obj, zero=zero, flavor=flavor) + if flavor == 'raw' and self.llinterpreter.malloc_check: + self.llinterpreter.remember_malloc(ptr, self) + return ptr # only after gc transform def op_cpy_malloc(self, obj, cpytype): # xxx @@ -654,12 +666,17 @@ return self.llinterpreter.gc.adjust_result_malloc(result, obj, size) assert flavor in ('gc', 'raw') try: - return self.heap.malloc(obj, size, zero=zero, flavor=flavor) + ptr = self.heap.malloc(obj, size, zero=zero, flavor=flavor) + if flavor == 'raw' and self.llinterpreter.malloc_check: + self.llinterpreter.remember_malloc(ptr, self) + return ptr except MemoryError: self.make_llexception() def op_free(self, obj, flavor): assert isinstance(flavor, str) + if flavor == 'raw' and self.llinterpreter.malloc_check: + self.llinterpreter.remember_free(obj) self.heap.free(obj, flavor=flavor) def op_zero_gc_pointers_inside(self, obj): Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_llinterp.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_llinterp.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_llinterp.py Tue Aug 28 12:55:48 2007 @@ -1,6 +1,7 @@ import py import sys -from pypy.rpython.lltypesystem.lltype import typeOf, pyobjectptr, Ptr, PyObject, Void +from pypy.rpython.lltypesystem.lltype import typeOf, pyobjectptr, Ptr,\ + PyObject, Void, malloc, free from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.llinterp import LLInterpreter, LLException, log from pypy.rpython.rmodel import inputconst @@ -14,6 +15,9 @@ # switch on logging of interp to show more info on failing tests +class MallocMismatch(Exception): + pass + def setup_module(mod): mod.logstate = py.log._getstate() py.log.setconsumer("llinterp", py.log.STDOUT) @@ -62,7 +66,8 @@ _tcache.clear() def get_interpreter(func, values, view='auto', viewbefore='auto', policy=None, - someobjects=False, type_system="lltype", backendopt=False, config=None): + someobjects=False, type_system="lltype", backendopt=False, + config=None, malloc_check=True): key = (func,) + tuple([typeOf(x) for x in values])+ (someobjects, backendopt) try: @@ -85,7 +90,7 @@ t, typer, graph = gengraph(func, [annotation(x) for x in values], viewbefore, policy, type_system=type_system, backendopt=backendopt, config=config) - interp = LLInterpreter(typer) + interp = LLInterpreter(typer, malloc_check=malloc_check) _tcache[key] = (t, interp, graph) # keep the cache small _lastinterpreted.append(key) @@ -98,11 +103,16 @@ return interp, graph def interpret(func, values, view='auto', viewbefore='auto', policy=None, - someobjects=False, type_system="lltype", backendopt=False, config=None): + someobjects=False, type_system="lltype", backendopt=False, + config=None, malloc_check=True): interp, graph = get_interpreter(func, values, view, viewbefore, policy, someobjects, type_system=type_system, - backendopt=backendopt, config=config) - return interp.eval_graph(graph, values) + backendopt=backendopt, config=config, + malloc_check=malloc_check) + result = interp.eval_graph(graph, values) + if malloc_check and interp.mallocs: + raise MallocMismatch(interp.mallocs) + return result def interpret_raises(exc, func, values, view='auto', viewbefore='auto', policy=None, someobjects=False, type_system="lltype", @@ -581,3 +591,21 @@ assert res == -63 res = interp.eval_graph(graph, [1, sys.maxint]) assert res == -42 + +def test_malloc_checker(): + T = lltype.Struct('x') + def f(x): + t = malloc(T, flavor='raw') + if x: + free(t, flavor='raw') + interpret(f, [1]) + py.test.raises(MallocMismatch, "interpret(f, [0])") + + def f(): + t1 = malloc(T, flavor='raw') + t2 = malloc(T, flavor='raw') + free(t1, flavor='raw') + free(t2, flavor='raw') + + interpret(f, []) + From fijal at codespeak.net Tue Aug 28 13:16:37 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 13:16:37 +0200 (CEST) Subject: [pypy-svn] r46089 - pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test Message-ID: <20070828111637.6199480DB@code0.codespeak.net> Author: fijal Date: Tue Aug 28 13:16:36 2007 New Revision: 46089 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test/test_llinterpsim.py Log: Malloc checking here makes little sense Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test/test_llinterpsim.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test/test_llinterpsim.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test/test_llinterpsim.py Tue Aug 28 13:16:36 2007 @@ -39,7 +39,7 @@ t, typer, graph = gengraph(func, [annotation(x) for x in values], viewbefore, policy) - interp = LLInterpreter(typer, heap=gclltype) + interp = LLInterpreter(typer, heap=gclltype, malloc_check=False) _tcache[key] = (t, interp, graph) # keep the cache small _lastinterpreted.append(key) From fijal at codespeak.net Tue Aug 28 13:16:56 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 13:16:56 +0200 (CEST) Subject: [pypy-svn] r46090 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test Message-ID: <20070828111656.71EE58169@code0.codespeak.net> Author: fijal Date: Tue Aug 28 13:16:55 2007 New Revision: 46090 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Log: Free this, catched by malloc checking :) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Tue Aug 28 13:16:55 2007 @@ -305,7 +305,9 @@ X = CStruct('xx', ('one', INT)) def f(): p = make(X, c_one=3) - return p.c_one + res = p.c_one + lltype.free(p, flavor='raw') + return res assert f() == 3 assert interpret(f, []) == 3 From fijal at codespeak.net Tue Aug 28 13:22:44 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 13:22:44 +0200 (CEST) Subject: [pypy-svn] r46091 - pypy/branch/pypy-more-rtti-inprogress/rpython/test Message-ID: <20070828112244.5FE53813D@code0.codespeak.net> Author: fijal Date: Tue Aug 28 13:22:43 2007 New Revision: 46091 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_nongc.py Log: Unsure what to do here, but skip checking in this case. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_nongc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_nongc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_nongc.py Tue Aug 28 13:22:43 2007 @@ -4,7 +4,10 @@ from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.rtyper import RPythonTyper from pypy.rlib.objectmodel import free_non_gc_object -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret as llinterpret + +def interpret(f, args): + return llinterpret(f, args, malloc_check=False) def test_free_non_gc_object(): class TestClass(object): From fijal at codespeak.net Tue Aug 28 13:23:41 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 13:23:41 +0200 (CEST) Subject: [pypy-svn] r46092 - pypy/branch/pypy-more-rtti-inprogress/rpython/test Message-ID: <20070828112341.3F7808157@code0.codespeak.net> Author: fijal Date: Tue Aug 28 13:23:40 2007 New Revision: 46092 Removed: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rexternalobj.py Log: This test is no longer needed From fijal at codespeak.net Tue Aug 28 13:25:27 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 13:25:27 +0200 (CEST) Subject: [pypy-svn] r46093 - pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test Message-ID: <20070828112527.093FC8177@code0.codespeak.net> Author: fijal Date: Tue Aug 28 13:25:26 2007 New Revision: 46093 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test/test_array.py Log: Skip this test if numpy is not there Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test/test_array.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test/test_array.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test/test_array.py Tue Aug 28 13:25:26 2007 @@ -14,7 +14,12 @@ from pypy.rpython.rint import IntegerRepr from pypy.rpython.numpy.rarray import ArrayRepr -import numpy +def setup_module(mod): + try: + import numpy + except ImportError: + py.test.skip("numpy not found") + mod.numpy = numpy test_c_compile = True test_llvm_compile = False From fijal at codespeak.net Tue Aug 28 13:28:34 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 13:28:34 +0200 (CEST) Subject: [pypy-svn] r46094 - pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test Message-ID: <20070828112834.0C19F8169@code0.codespeak.net> Author: fijal Date: Tue Aug 28 13:28:33 2007 New Revision: 46094 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test/test_support.py Log: Don't do malloc check here Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test/test_support.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test/test_support.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/memory/test/test_support.py Tue Aug 28 13:28:33 2007 @@ -94,5 +94,5 @@ assert f() from pypy.rpython.memory.lladdress import raw_malloc, raw_free AddressLinkedList = get_address_linked_list() - res = interpret(f, []) + res = interpret(f, [], malloc_check=False) assert res From fijal at codespeak.net Tue Aug 28 13:31:22 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 13:31:22 +0200 (CEST) Subject: [pypy-svn] r46095 - pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test Message-ID: <20070828113122.7B4D58157@code0.codespeak.net> Author: fijal Date: Tue Aug 28 13:31:21 2007 New Revision: 46095 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test/test_array.py Log: *really* skip Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test/test_array.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test/test_array.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/numpy/test/test_array.py Tue Aug 28 13:31:21 2007 @@ -12,7 +12,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.rctypes import rcarithmetic from pypy.rpython.rint import IntegerRepr -from pypy.rpython.numpy.rarray import ArrayRepr def setup_module(mod): try: @@ -21,6 +20,8 @@ py.test.skip("numpy not found") mod.numpy = numpy +from pypy.rpython.numpy.rarray import ArrayRepr + test_c_compile = True test_llvm_compile = False From fijal at codespeak.net Tue Aug 28 14:35:03 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 28 Aug 2007 14:35:03 +0200 (CEST) Subject: [pypy-svn] r46096 - in pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem: . test Message-ID: <20070828123503.DCD718138@code0.codespeak.net> Author: fijal Date: Tue Aug 28 14:34:59 2007 New Revision: 46096 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Log: An experiment with custom policy to strings. Can automatically cast strings to ll_ptrs and free them (but not the other way around yet!) This function is getting really obscure TBH Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Tue Aug 28 14:34:59 2007 @@ -28,7 +28,15 @@ def llexternal(name, args, result, _callable=None, sources=[], includes=[], libraries=[], include_dirs=[], sandboxsafe=False, - canraise=False): + canraise=False, stringpolicy='noauto'): + """ String policies: + autocast - automatically cast to ll_string, but don't delete it + fullauto - automatically cast + delete is afterwards + noauto - don't do anything + + WARNING: It's likely that in future we'll decide to use fullauto by + default + """ ext_type = lltype.FuncType(args, result) if _callable is None: _callable = ll2ctypes.LL2CtypesCallable(ext_type) @@ -40,21 +48,38 @@ _callable=_callable, _safe_not_sandboxed=sandboxsafe, _debugexc=True, # on top of llinterp - canraise=canraise) + canraise=canraise) if isinstance(_callable, ll2ctypes.LL2CtypesCallable): _callable.funcptr = funcptr unrolling_arg_tps = unrolling_iterable(enumerate(args)) def wrapper(*args): real_args = () + if stringpolicy == 'fullauto': + to_free = () for i, tp in unrolling_arg_tps: + ll_str = None if isinstance(tp, lltype.Number): real_args = real_args + (cast(tp, args[i]),) elif tp is lltype.Float: real_args = real_args + (float(args[i]),) + elif tp is CCHARP and (stringpolicy == 'fullauto' or + stringpolicy == 'autocast'): + ll_str = str2charp(args[i]) + real_args = real_args + (ll_str,) else: real_args = real_args + (args[i],) - return funcptr(*real_args) + if stringpolicy == 'fullauto': + if tp is CCHARP: + to_free = to_free + (ll_str,) + else: + to_free = to_free = (None,) + result = funcptr(*real_args) + if stringpolicy == 'fullauto': + for i, tp in unrolling_arg_tps: + if tp is CCHARP: + lltype.free(to_free[i], flavor='raw') + return result wrapper._always_inline_ = True # for debugging, stick ll func ptr to that wrapper._ptr = funcptr Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_rffi.py Tue Aug 28 14:34:59 2007 @@ -5,7 +5,7 @@ from pypy.rpython.lltypesystem.lltype import Signed, Ptr, Char, malloc from pypy.rpython.lltypesystem import lltype from pypy.tool.udir import udir -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret, MallocMismatch from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.rtyper import RPythonTyper from pypy.translator.backendopt.all import backend_optimizations @@ -45,7 +45,8 @@ assert xf() == 8+3 def test_string(): - z = llexternal('strlen', [CCHARP], Signed, includes=['string.h']) + z = llexternal('strlen', [CCHARP], Signed, includes=['string.h'], + stringpolicy='noauto') def f(): s = str2charp("xxx") @@ -68,7 +69,8 @@ return ret; } """) - z = llexternal('f', [CCHARP], CCHARP, sources=[c_source]) + z = llexternal('f', [CCHARP], CCHARP, sources=[c_source], + stringpolicy='noauto') def f(): s = str2charp("xxx") @@ -331,3 +333,29 @@ assert s == {'cast_int_to_uint': 1, 'direct_call': 1, 'cast_primitive': 2, 'cast_int_to_float': 1} + +def test_stringpolicy1(): + strlen = llexternal('strlen', [CCHARP], INT, includes=['string.h'], + stringpolicy='fullauto') + def f(): + return strlen("Xxx") + assert interpret(f, [], backendopt=True) == 3 + +def test_stringpolicy2(): + def f(): + return strlen("Xxx") + strlen = llexternal('strlen', [CCHARP], INT, + includes=['string.h'], stringpolicy='autocast') + py.test.raises(MallocMismatch, interpret, f, [], backendopt=True) + +def test_stringpolicy3(): + strlen = llexternal('strlen', [CCHARP], INT, + includes=['string.h'], stringpolicy='noauto') + def f(): + ll_str = str2charp("Xxx") + res = strlen(ll_str) + lltype.free(ll_str, flavor='raw') + return res + + assert interpret(f, [], backendopt=True) == 3 + From simonb at codespeak.net Wed Aug 29 02:33:27 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Wed, 29 Aug 2007 02:33:27 +0200 (CEST) Subject: [pypy-svn] r46124 - in pypy/dist/pypy/rpython/numpy: . test Message-ID: <20070829003327.ABF4280A8@code0.codespeak.net> Author: simonb Date: Wed Aug 29 02:33:26 2007 New Revision: 46124 Modified: pypy/dist/pypy/rpython/numpy/aarray.py pypy/dist/pypy/rpython/numpy/rarray.py pypy/dist/pypy/rpython/numpy/test/test_array.py Log: build multi dimensional arrays, annotating of multi-indexes Modified: pypy/dist/pypy/rpython/numpy/aarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/aarray.py (original) +++ pypy/dist/pypy/rpython/numpy/aarray.py Wed Aug 29 02:33:26 2007 @@ -1,11 +1,11 @@ from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.annotation.pairtype import pairtype +from pypy.annotation.pairtype import pair, pairtype from pypy.annotation.model import SomeExternalObject, SomeList, SomeImpossibleValue -from pypy.annotation.model import SomeObject, SomeInteger, SomeFloat, SomeString, SomeChar,\ - SomeTuple +from pypy.annotation.model import SomeObject, SomeInteger, SomeFloat, SomeString, SomeChar, SomeTuple, SomeSlice from pypy.tool.error import AnnotatorError from pypy.rpython.lltypesystem import rffi from pypy.rlib import rarithmetic +from pypy.annotation import listdef import numpy @@ -25,25 +25,15 @@ #'f' : SomeFloat(), # XX single precision float XX 'd' : SomeFloat(), } - def __init__(self, knowntype, typecode, ndim=1): - self.knowntype = knowntype # == numpy.ndarray (do we need this for anything?) + def __init__(self, typecode, ndim=1): + if not typecode in self.typecode_to_item: + raise AnnotatorError("bad typecode: %r"%typecode) self.typecode = typecode self.ndim = ndim def can_be_none(self): return True - def return_annotation(self): - """Returns either 'self' or the annotation of the unwrapped version - of this ctype, following the logic used when ctypes operations - return a value. - """ - from pypy.rpython import extregistry - assert extregistry.is_registered_type(self.knowntype) - entry = extregistry.lookup_type(self.knowntype) - # special case for returning primitives or c_char_p - return getattr(entry, 's_return_trick', self) - def get_item_type(self): return self.typecode_to_item[self.typecode] @@ -60,7 +50,7 @@ return s def method_transpose(self): - return SomeArray(self.knowntype, self.typecode, self.ndim) + return SomeArray(self.typecode, self.ndim) class __extend__(pairtype(SomeArray, SomeArray)): @@ -77,18 +67,53 @@ break if typecode is None: raise AnnotatorError() - return SomeArray(s_arr1.knowntype, typecode) + return SomeArray(typecode) add = sub = mul = div = truediv = union class __extend__(pairtype(SomeArray, SomeInteger)): - def setitem((s_cto, s_index), s_value): - pass + def setitem((s_array, s_index), s_value): + if s_array.ndim == 0: + raise AnnotatorError() + if isinstance(s_value, SomeArray): + assert s_array.ndim == s_value.ndim + 1 - def getitem((s_cto, s_index)): - # TODO: higher ndimed arrays have getitem returns SomeArray - return s_cto.get_item_type() + def getitem((s_array, s_index)): + if s_array.ndim == 0: + raise AnnotatorError() + if s_array.ndim > 1: + return SomeArray(s_array.typecode, s_array.ndim-1) + return s_array.get_item_type() + +class __extend__(pairtype(SomeArray, SomeTuple)): + def get_leftover_dim((s_array, s_index)): + ndim = s_array.ndim + for s_item in s_index.items: + if isinstance(s_item, SomeInteger): + ndim -= 1 + elif isinstance(s_item, SomeSlice): + pass + else: + raise AnnotatorError("cannot index with %s"%s_item) + return ndim + + def setitem((s_array, s_index), s_value): + ndim = pair(s_array, s_index).get_leftover_dim() + if isinstance(s_value, SomeArray): + if s_value.ndim + ndim != s_array.ndim: + # XX allow broadcasting.. + raise AnnotatorError("shape mismatch") + elif ndim > 0: + raise AnnotatorError("need to set from array") + + def getitem((s_array, s_index)): + ndim = pair(s_array, s_index).get_leftover_dim() + if s_array.ndim == 0 and len(s_index.items): + raise AnnotatorError("indexing rank zero array with nonempty tuple") + if ndim > 0: + return SomeArray(s_array.typecode, ndim) + return s_array.get_item_type() numpy_typedict = { (SomeInteger, rffi.r_signedchar) : 'b', @@ -107,48 +132,78 @@ } valid_typecodes='bhilqBHILQfd' -class CallEntry(ExtRegistryEntry): - "Annotation and rtyping of calls to numpy.array." +class ArrayCallEntry(ExtRegistryEntry): + "Annotation and rtyping of calls to numpy.array" _about_ = numpy.array - def compute_result_annotation(self, arg_list, *args_s, **kwds_s): - if not isinstance(arg_list, SomeList): - raise AnnotatorError("numpy.array expects SomeList") - - # First guess type from input list - listitem = arg_list.listdef.listitem - key = type(listitem.s_value), listitem.s_value.knowntype - typecode = numpy_typedict.get(key, None) + def compute_result_annotation(self, s_list, s_dtype=None): + if isinstance(s_list, SomeList): + # First guess type from input list + listitem = s_list.listdef.listitem + key = type(listitem.s_value), listitem.s_value.knowntype + typecode = numpy_typedict.get(key, None) + ndim = 1 + elif isinstance(s_list, SomeArray): + typecode = s_list.typecode + ndim = s_list.ndim + else: + raise AnnotatorError("cannot build array from %s"%s_list) # now see if the dtype arg over-rides the typecode - dtype = None - if len(args_s)>0: - dtype = args_s[0] - if "dtype" in kwds_s: - dtype = kwds_s["dtype"] - if isinstance(dtype,SomeChar) and dtype.is_constant(): - typecode = dtype.const - dtype = None - if dtype is not None: + if isinstance(s_dtype, SomeChar) and s_dtype.is_constant(): + typecode = s_dtype.const + s_dtype = None + if s_dtype is not None: raise AnnotatorError("dtype is not a valid type specification") if typecode is None or typecode not in valid_typecodes: raise AnnotatorError("List item type not supported") - knowntype = numpy.ndarray - return SomeArray(knowntype, typecode) + return SomeArray(typecode, ndim) def specialize_call(self, hop): r_array = hop.r_result - [v_lst] = hop.inputargs(r_array) - v_result = r_array.allocate_instance(hop.llops, v_lst) + [v_lst] = hop.inputargs(r_array) # coerce list arg to array arg + v_result = r_array.build_from_array(hop.llops, v_lst) return v_result -class NumpyObjEntry(ExtRegistryEntry): - "Annotation and rtyping of numpy array instances." - _type_ = numpy.ndarray - - def get_repr(self, rtyper, s_array): - from pypy.rpython.numpy.rarray import ArrayRepr - return ArrayRepr(rtyper, s_array) + +class ZeroesCallEntry(ExtRegistryEntry): + "Annotation and rtyping of calls to numpy.zeroes" + _about_ = numpy.zeros + + def compute_result_annotation(self, s_tuple, s_dtype=None): + if isinstance(s_tuple, SomeTuple): + for s_item in s_tuple.items: + if not isinstance(s_item, SomeInteger): + raise AnnotatorError("shape must be tuple of integers") + ndim = len(s_tuple.items) + else: + # XX also build from single int arg + raise AnnotatorError("could not build array shape from %s"%s_list) + + typecode = 'd' + if isinstance(s_dtype, SomeChar) and s_dtype.is_constant(): + typecode = s_dtype.const + s_dtype = None + return SomeArray(typecode, ndim) + +# def specialize_call(self, hop): +# ldef = listdef.ListDef(None, SomeInteger()) +# r_lst = hop.rtyper.getrepr(SomeList(ldef)) +# # XX TyperError: don't know how to convert from +# # to +# # +# [v_lst] = hop.inputargs(r_lst) +# r_array = hop.r_result +# v_result = r_array.build_from_shape(hop.llops, r_lst, v_lst) +# return v_result + + def specialize_call(self, hop): + r_tpl = hop.args_r[0] + # XX also call with single int arg + [v_tpl] = hop.inputargs(r_tpl) + r_array = hop.r_result + v_result = r_array.build_from_shape(hop.llops, r_tpl, v_tpl) + return v_result Modified: pypy/dist/pypy/rpython/numpy/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/rarray.py (original) +++ pypy/dist/pypy/rpython/numpy/rarray.py Wed Aug 29 02:33:26 2007 @@ -4,58 +4,129 @@ from pypy.rpython.rlist import AbstractBaseListRepr from pypy.rpython.error import TyperError from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE from pypy.rpython.lltypesystem.lltype import \ GcArray, GcStruct, Signed, Ptr, Unsigned, malloc, Void from pypy.annotation.model import SomeObject, SomeInteger from pypy.rpython.numpy.aarray import SomeArray from pypy.annotation.pairtype import pairtype +from pypy.rlib.unroll import unrolling_iterable +from pypy.annotation import listdef +from pypy.rpython.memory.lltypelayout import sizeof + +def gen_build_from_shape(ndim): + unrolling_dims = unrolling_iterable(reversed(range(ndim))) + def ll_build_from_shape(ARRAY, shape): + array = ll_allocate(ARRAY, ndim) + itemsize = 1 + for i in unrolling_dims: + attr = 'item%d'%i + size = getattr(shape, attr) + array.shape[i] = size + array.strides[i] = itemsize + itemsize *= size + array.data = malloc(ARRAY.data.TO, itemsize) + return array + return ll_build_from_shape + +def gen_get_shape(ndim): + unrolling_dims = unrolling_iterable(range(ndim)) + def ll_get_shape(ARRAY, TUPLE, array): + shape = malloc(TUPLE) + for i in unrolling_dims: + size = array.shape[i] + attr = 'item%d'%i + setattr(shape, attr, size) + return shape + return ll_get_shape class ArrayRepr(Repr): def __init__(self, rtyper, s_array): + self.s_array = s_array self.s_value = s_array.get_item_type() self.item_repr = rtyper.getrepr(self.s_value) ITEM = self.item_repr.lowleveltype - ITEMARRAY = GcArray(ITEM) - SIZEARRAY = GcArray(Signed) + ITEMARRAY = GcArray(ITEM, hints={'nolength':True}) + SIZEARRAY = GcArray(Signed, hints={'nolength':True}) + self.PTR_SIZEARRAY = Ptr(SIZEARRAY) + self.itemsize = sizeof(ITEM) + self.ndim = s_array.ndim self.ARRAY = Ptr( GcStruct("array", ("data", Ptr(ITEMARRAY)), # pointer to raw data buffer - ("nd", Signed), # number of dimensions, also called ndim - ("dimensions", Ptr(SIZEARRAY)), # size in each dimension - ("strides", Ptr(SIZEARRAY)), # bytes to jump to get to the - # next element in each dimension + ("ndim", Signed), # number of dimensions + ("shape", self.PTR_SIZEARRAY), # size in each dimension + ("strides", self.PTR_SIZEARRAY), # bytes (?) to jump to get to the + # next element in each dimension )) self.lowleveltype = self.ARRAY - def allocate_instance(self, llops, v_array): - c1 = inputconst(lltype.Void, self.lowleveltype.TO) - return llops.gendirectcall(ll_allocate, c1, v_array) + def build_from_array(self, llops, v_array): + cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) + return llops.gendirectcall(ll_build_alias, cARRAY, v_array) + +# def build_from_shape(self, llops, r_tuple, v_tuple): +# cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) +# cTUPLE = inputconst(lltype.Void, r_tuple.lowleveltype.TO) +# ndim = self.ndim +# c_ndim = inputconst(lltype.Signed, ndim) +# assert ndim == len(r_tuple.items_r) +# v_array = llops.gendirectcall(ll_allocate, cARRAY, c_ndim) +# c_attr = inputconst(lltype.Void, 'shape') +# v_shape = llops.genop('getfield', [v_array, c_attr], self.PTR_SIZEARRAY) +# for i in range(ndim): +# v_size = r_tuple.getitem_internal(llops, v_tuple, i) +# v_i = inputconst(lltype.Signed, i) +# llops.genop('setarrayitem', [v_shape, v_i, v_size]) +# return v_array + + def build_from_shape(self, llops, r_tuple, v_tuple): + cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) + cTUPLE = inputconst(lltype.Void, r_tuple.lowleveltype.TO) + ndim = self.s_array.ndim + ll_build_from_shape = gen_build_from_shape(ndim) + c_ndim = inputconst(lltype.Signed, ndim) + assert ndim == len(r_tuple.items_r) + rval = llops.gendirectcall(ll_build_from_shape, cARRAY, v_tuple) + return rval def rtype_method_transpose(self, hop): [v_self] = hop.inputargs(self) cARRAY = hop.inputconst(Void, hop.r_result.ARRAY.TO) return hop.gendirectcall(ll_transpose, cARRAY, v_self) + def get_ndim(self, hop, v_array): + cname = inputconst(Void, 'ndim') + return hop.llops.genop('getfield', [v_array, cname], resulttype=Signed) + + def get_shape(self, hop, v_array): + cname = inputconst(Void, 'shape') + TUPLE = TUPLE_TYPE([Signed]*self.ndim) + cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) + cTUPLE = inputconst(lltype.Void, TUPLE.TO) + ll_get_shape = gen_get_shape(self.ndim) + return hop.llops.gendirectcall(ll_get_shape, cARRAY, cTUPLE, v_array) + return llops.genop('getfield', [v_array, cname], resulttype=TUPLE) + def rtype_getattr(self, hop): s_attr = hop.args_s[1] if s_attr.is_constant() and isinstance(s_attr.const, str): attr = s_attr.const s_obj = hop.args_s[0] - vobj, vattr = hop.inputargs(self, Void) - llops = hop.llops - if attr == 'ndim': - cname = inputconst(Void, 'nd') - return llops.genop('getfield', [vobj, cname], resulttype=Signed) + v_array, vattr = hop.inputargs(self, Void) + getter = getattr(self, 'get_'+attr, None) + if getter: + return getter(hop, v_array) return Repr.rtype_getattr(self, hop) class __extend__(SomeArray): def rtyper_makerepr(self, rtyper): - return ArrayRepr( rtyper, self ) + return ArrayRepr(rtyper, self) def rtyper_makekey(self): - return self.__class__, self.knowntype + return self.__class__, self.typecode, self.ndim class __extend__(pairtype(ArrayRepr, ArrayRepr)): @@ -79,30 +150,42 @@ if r_lst.listitem is None: return NotImplemented if r_lst.item_repr != r_arr.item_repr: + assert 0, (r_lst, r_arr.item_repr) return NotImplemented - c1 = inputconst(lltype.Void, r_arr.lowleveltype.TO) - return llops.gendirectcall(ll_build_array, c1, v) + cARRAY = inputconst(lltype.Void, r_arr.lowleveltype.TO) + return llops.gendirectcall(ll_build_from_list, cARRAY, v) class __extend__(pairtype(AbstractRangeRepr, ArrayRepr)): def convert_from_to((r_rng, r_arr), v, llops): - c1 = inputconst(lltype.Void, r_arr.lowleveltype.TO) - return llops.gendirectcall(ll_build_array, c1, v) + cARRAY = inputconst(lltype.Void, r_arr.lowleveltype.TO) + return llops.gendirectcall(ll_build_from_list, cARRAY, v) -def ll_build_array(ARRAY, lst): - size = lst.ll_length() +def ll_allocate(ARRAY, ndim): array = malloc(ARRAY) + array.ndim = ndim + array.shape = malloc(ARRAY.shape.TO, array.ndim) + array.strides = malloc(ARRAY.strides.TO, array.ndim) + return array + +def ll_build_from_list(ARRAY, lst): + size = lst.ll_length() + array = ll_allocate(ARRAY, 1) + for i in range(array.ndim): + array.shape[i] = size + array.strides[i] = 1 data = array.data = malloc(ARRAY.data.TO, size) i = 0 while i < size: data[i] = lst.ll_getitem_fast(i) i += 1 - array.nd = 1 return array -def ll_allocate(ARRAY, array): - new_array = malloc(ARRAY) +def ll_build_alias(ARRAY, array): + new_array = ll_allocate(ARRAY, array.ndim) new_array.data = array.data # alias data - new_array.nd = array.nd + for i in range(array.ndim): + new_array.shape[i] = array.shape[i] + new_array.strides[i] = array.strides[i] return new_array def ll_setitem(l, index, item): @@ -112,8 +195,8 @@ return l.data[index] def ll_add(ARRAY, a1, a2): - size = len(a1.data) - if size != len(a2.data): + size = a1.shape[0] + if size != a2.shape[0]: raise ValueError array = malloc(ARRAY) array.data = malloc(ARRAY.data.TO, size) @@ -124,7 +207,7 @@ return array def ll_transpose(ARRAY, a1): - a2 = ll_allocate(ARRAY, a1) + a2 = ll_build_alias(ARRAY, a1) # XX do something to a2 return a2 Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Wed Aug 29 02:33:26 2007 @@ -5,8 +5,9 @@ import py import pypy.rpython.numpy.implementation from pypy.annotation import model as annmodel -from pypy.annotation.model import SomeTuple +from pypy.annotation.model import SomeObject, SomeTuple from pypy.annotation.annrpython import RPythonAnnotator +from pypy.tool.error import AnnotatorError from pypy.translator.translator import TranslationContext from pypy import conftest import sys @@ -69,6 +70,30 @@ s = a.build_types(access_with_variable, []) assert s.knowntype == rffi.r_int + def test_annotate_zeros(self): + def f(): + a = numpy.zeros((3,4,5)) + return a + + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(f, []) + assert s.typecode == 'd' + assert s.ndim == 3 + + def test_annotate_indexing(self): + def f(): + a = numpy.zeros((3,4,5)) + b = a[0] + a[0,1,2] = 1. + b[0,1] = a[2] + return b + + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(f, []) + assert s.ndim == 2 + def test_annotate_array_add(self): def f(): a1 = numpy.array([1,2]) @@ -91,6 +116,27 @@ s = a.build_types(f, []) assert s.typecode == 'd' + def test_annotate_array_dtype(self): + def f(): + a1 = numpy.array([1,2], dtype='d') + return a1 + + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(f, []) + assert s.typecode == 'd' + + def test_annotate_array_array(self): + def f(): + a1 = numpy.array([1,2], dtype='d') + a2 = numpy.array(a1) + return a2 + + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(f, []) + assert s.typecode == 'd' + def test_annotate_array_attr(self): def f(): a1 = numpy.array([1,2]) @@ -116,11 +162,21 @@ class Test_specialization: def test_specialize_array_create(self): def create_array(): - return numpy.array([1,2]) + a = numpy.array([1,20]) + b = numpy.array(a) + return b res = interpret(create_array, []) assert res.data[0] == 1 - assert res.data[1] == 2 + assert res.data[1] == 20 + + def test_specialize_array_zeros(self): + def create_array(n, m): + a = numpy.zeros((n, m)) + return a + + res = interpret(create_array, [3, 4]) + assert res.ndim == 2 def test_specialize_array_access(self): def access_with_variable(): @@ -137,7 +193,7 @@ def test_specialize_array_add(self): def create_array(): - a1 = numpy.array([1,2]) + a1 = numpy.array([1.,2.]) a2 = numpy.array([6,9]) return a1 + a2 @@ -153,6 +209,26 @@ res = interpret(create_array, []) assert res == 1 + def test_specialize_array_attr_shape(self): + def create_array(): + a = numpy.zeros((2,3)) + return list(a.shape) + + res = interpret(create_array, []) + assert res[0] == 2 + assert res[1] == 3 + + def test_specialize_array_strides(self): + def create_array(): + a = numpy.zeros((3,4,5)) + return a + + res = interpret(create_array, []) + assert res.strides[0] == 20 + assert res.strides[1] == 5 + assert res.strides[2] == 1 + #assert len(res.data) == 3*4*5 # GcArray has nolength + def test_specialize_array_method(self): def create_array(): a = numpy.array([1,2]) @@ -162,6 +238,14 @@ assert res.data[0] == 1 assert res.data[1] == 2 + def X_test_specialize_view(self): + t = TranslationContext() + a = t.buildannotator() + a = a.build_types(f, []) + r = t.buildrtyper() + r.specialize() + t.view() + class Test_compile: def setup_class(self): if not test_c_compile: @@ -172,12 +256,20 @@ def test_compile_array_access(self): def access_array(index): - my_array = numpy.array([3,99,2]) - my_array[0] = 1 - return my_array[index] + a = numpy.array([3,99,2]) + a[0] = 1 + return a[index] fn = self.compile(access_array, [int]) assert fn(0) == 1 assert fn(1) == 99 + def test_compile_2d(self): + def access_array(index): + a = numpy.zeros((5,6)) + a[0,0] = 2 + return 0 + + fn = self.compile(access_array, [int]) + From arigo at codespeak.net Wed Aug 29 12:17:12 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 29 Aug 2007 12:17:12 +0200 (CEST) Subject: [pypy-svn] r46142 - pypy/branch/pypy-more-rtti-inprogress/translator/tool Message-ID: <20070829101712.0FFEA812B@code0.codespeak.net> Author: arigo Date: Wed Aug 29 12:17:11 2007 New Revision: 46142 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/tool/cbuild.py Log: Win/Py2.4: workaround for a distutils bugs where some env vars can become longer and longer every time it is used Modified: pypy/branch/pypy-more-rtti-inprogress/translator/tool/cbuild.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/tool/cbuild.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/tool/cbuild.py Wed Aug 29 12:17:11 2007 @@ -346,7 +346,9 @@ def build(self, noerr=False): basename = self.outputfilename.new(ext='') + data = '' try: + saved_environ = os.environ.copy() try: c = stdoutcapture.Capture(mixed_out_err = True) if self.profbased is None: @@ -362,6 +364,11 @@ profdrv.probe(str(self.outputfilename),args) profdrv.after() finally: + # workaround for a distutils bugs where some env vars can + # become longer and longer every time it is used + for key, value in saved_environ.items(): + if os.environ.get(key) != value: + os.environ[key] = value foutput, foutput = c.done() data = foutput.read() if data: From arigo at codespeak.net Wed Aug 29 13:13:23 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 29 Aug 2007 13:13:23 +0200 (CEST) Subject: [pypy-svn] r46146 - in pypy/branch/pypy-more-rtti-inprogress: module/posix rpython/module Message-ID: <20070829111323.DC01280FE@code0.codespeak.net> Author: arigo Date: Wed Aug 29 13:13:22 2007 New Revision: 46146 Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Log: No os.getuid()/geteuid() on Windows. Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/__init__.py Wed Aug 29 13:13:22 2007 @@ -48,8 +48,6 @@ 'rename' : 'interp_posix.rename', 'umask' : 'interp_posix.umask', '_exit' : 'interp_posix._exit', - #'getuid' : 'interp_posix.getuid', - #'geteuid' : 'interp_posix.geteuid', 'utime' : 'interp_posix.utime', '_statfields': 'interp_posix.getstatfields(space)', } Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Wed Aug 29 13:13:22 2007 @@ -271,12 +271,12 @@ return extdef([], (str, str, str, str, str), "ll_os.ll_uname", llimpl=uname_llimpl) - @registering(os.getuid) + @registering_if(os, 'getuid') def register_os_getuid(self): return self.extdef_for_os_function_returning_int('getuid', includes=self.UNISTD_INCL) - @registering(os.geteuid) + @registering_if(os, 'geteuid') def register_os_geteuid(self): return self.extdef_for_os_function_returning_int('geteuid', includes=self.UNISTD_INCL) From arigo at codespeak.net Wed Aug 29 13:45:12 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 29 Aug 2007 13:45:12 +0200 (CEST) Subject: [pypy-svn] r46154 - in pypy/branch/pypy-more-rtti-inprogress/rpython: . module Message-ID: <20070829114512.7DE2C8129@code0.codespeak.net> Author: arigo Date: Wed Aug 29 13:45:11 2007 New Revision: 46154 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Log: In-progress Windowsification. I hope I didn't break it on Linux. Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Wed Aug 29 13:45:11 2007 @@ -32,6 +32,11 @@ except (SystemExit, MemoryError, KeyboardInterrupt), e: raise except: + if 0: + import sys, traceback + print >> sys.stderr, 'WARNING: cannot register', func_or_list, ':' + traceback.print_exc() + import pdb; pdb.set_trace() exc, exc_inst, tb = sys.exc_info() for func in funcs: # if the function has already been registered and we got Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Wed Aug 29 13:45:11 2007 @@ -20,43 +20,12 @@ from pypy.rpython.tool import rffi_platform posix = __import__(os.name) -class CConfig: - """ - Definitions for platform integration. - - Note: this must be processed through rffi_platform.configure() to provide - usable objects. For example:: - - CLOCK_T = rffi_platform.configure(CConfig)['CLOCK_T'] - register(function, [CLOCK_T], ...) - - """ - includes = ['sys/times.h'] - # XXX argh, argh, argh, should be automatic - _header_ = "\n".join(["#include <%s>" % name for name in includes]) - - CLOCK_T = rffi_platform.SimpleType('clock_t', rffi.INT) - - TMS = rffi_platform.Struct( - 'struct tms', [('tms_utime', rffi.INT), - ('tms_stime', rffi.INT), - ('tms_cutime', rffi.INT), - ('tms_cstime', rffi.INT)]) - class RegisterOs(BaseLazyRegistering): UNISTD_INCL = ['unistd.h', 'sys/types.h'] def __init__(self): - # Grab all of the platform type definitions and stash them as instance - # attributes (this is quite a hack, what a lazy programmer I must be). - self.__dict__.update(rffi_platform.configure(CConfig)) - # Make some pointer types too - self.TMSP = lltype.Ptr(self.TMS) - # Here is a random extra platform parameter which is important. - # Strictly speaking, this should probably be retrieved at runtime, not - # at translation time. - self.CLOCK_TICKS_PER_SECOND = float(os.sysconf('SC_CLK_TCK')) + pass # a simple, yet usefull factory def extdef_for_os_function_returning_int(self, name, **kwds): @@ -135,6 +104,9 @@ @registering(os.utime) def register_os_utime(self): + #START + #print rffi.platform.has('utimes'), rffi.platform.has('utime') + #STOP TIME_T = rffi.INT # XXX do the right thing UTIMEBUFP = rffi.CStructPtr('utimbuf', ('actime', TIME_T), ('modtime', TIME_T)) @@ -195,22 +167,56 @@ @registering(os.times) def register_os_times(self): - # XXX sys/times.h isn't so portable, maybe. - os_times = rffi.llexternal('times', [self.TMSP], self.CLOCK_T, + # XXX sys/times.h isn't portable + class CConfig: + """ + Definitions for platform integration. + + Note: this must be processed through rffi_platform.configure() to + provide usable objects. For example:: + + CLOCK_T = rffi_platform.configure(CConfig)['CLOCK_T'] + register(function, [CLOCK_T], ...) + + """ + includes = ['sys/times.h'] + # XXX argh, argh, argh, should be automatic + _header_ = "\n".join(["#include <%s>" % name for name in includes]) + + CLOCK_T = rffi_platform.SimpleType('clock_t', rffi.INT) + + TMS = rffi_platform.Struct( + 'struct tms', [('tms_utime', rffi.INT), + ('tms_stime', rffi.INT), + ('tms_cutime', rffi.INT), + ('tms_cstime', rffi.INT)]) + + # Grab all of the platform type definitions + config = rffi_platform.configure(CConfig) + CLOCK_T = config['CLOCK_T'] + TMS = config['TMS'] + # Make some pointer types too + TMSP = lltype.Ptr(TMS) + # Here is a random extra platform parameter which is important. + # Strictly speaking, this should probably be retrieved at runtime, not + # at translation time. + CLOCK_TICKS_PER_SECOND = float(os.sysconf('SC_CLK_TCK')) + + os_times = rffi.llexternal('times', [TMSP], CLOCK_T, includes=['sys/times.h']) def times_lltypeimpl(): - l_tmsbuf = lltype.malloc(self.TMSP.TO, flavor='raw') + l_tmsbuf = lltype.malloc(TMSP.TO, flavor='raw') try: result = os_times(l_tmsbuf) if result == -1: raise OSError(rffi.get_errno(), "times failed") return ( - l_tmsbuf.c_tms_utime / self.CLOCK_TICKS_PER_SECOND, - l_tmsbuf.c_tms_stime / self.CLOCK_TICKS_PER_SECOND, - l_tmsbuf.c_tms_cutime / self.CLOCK_TICKS_PER_SECOND, - l_tmsbuf.c_tms_cstime / self.CLOCK_TICKS_PER_SECOND, - result / self.CLOCK_TICKS_PER_SECOND) + l_tmsbuf.c_tms_utime / CLOCK_TICKS_PER_SECOND, + l_tmsbuf.c_tms_stime / CLOCK_TICKS_PER_SECOND, + l_tmsbuf.c_tms_cutime / CLOCK_TICKS_PER_SECOND, + l_tmsbuf.c_tms_cstime / CLOCK_TICKS_PER_SECOND, + result / CLOCK_TICKS_PER_SECOND) finally: lltype.free(l_tmsbuf, flavor='raw') self.register(os.times, [], (float, float, float, float, float), From arigo at codespeak.net Wed Aug 29 19:42:53 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 29 Aug 2007 19:42:53 +0200 (CEST) Subject: [pypy-svn] r46167 - pypy/extradoc/talk/dyla2007/demo Message-ID: <20070829174253.397C78149@code0.codespeak.net> Author: arigo Date: Wed Aug 29 19:42:51 2007 New Revision: 46167 Added: pypy/extradoc/talk/dyla2007/demo/dynlang.png - copied, changed from r45426, pypy/extradoc/talk/ep2007/interpreter/dynlang.png Log: An image I forgot to check in. From fijal at codespeak.net Wed Aug 29 23:07:43 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 29 Aug 2007 23:07:43 +0200 (CEST) Subject: [pypy-svn] r46176 - pypy/branch/pypy-more-rtti-inprogress/translator/backendopt Message-ID: <20070829210743.417D68196@code0.codespeak.net> Author: fijal Date: Wed Aug 29 23:07:41 2007 New Revision: 46176 Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/inline.py Log: Oops. Check if this argument is there Modified: pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/inline.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/inline.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/translator/backendopt/inline.py Wed Aug 29 23:07:41 2007 @@ -694,7 +694,8 @@ while heap: weight, _, graph = heap[0] if not valid_weight.get(graph): - if getattr(graph.func, '_always_inline_', None): + if hasattr(graph, 'func') and \ + getattr(graph.func, '_always_inline_', None): weight, fixed = 0.0, True else: weight, fixed = heuristic(graph) From simonb at codespeak.net Thu Aug 30 02:59:56 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Thu, 30 Aug 2007 02:59:56 +0200 (CEST) Subject: [pypy-svn] r46178 - in pypy/dist/pypy/rpython/numpy: . test Message-ID: <20070830005956.34804819D@code0.codespeak.net> Author: simonb Date: Thu Aug 30 02:59:54 2007 New Revision: 46178 Modified: pypy/dist/pypy/rpython/numpy/aarray.py pypy/dist/pypy/rpython/numpy/rarray.py pypy/dist/pypy/rpython/numpy/test/test_array.py Log: numpy: progress with indexing, iterators dissapear with malloc removal Modified: pypy/dist/pypy/rpython/numpy/aarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/aarray.py (original) +++ pypy/dist/pypy/rpython/numpy/aarray.py Thu Aug 30 02:59:54 2007 @@ -72,20 +72,6 @@ add = sub = mul = div = truediv = union -class __extend__(pairtype(SomeArray, SomeInteger)): - def setitem((s_array, s_index), s_value): - if s_array.ndim == 0: - raise AnnotatorError() - if isinstance(s_value, SomeArray): - assert s_array.ndim == s_value.ndim + 1 - - def getitem((s_array, s_index)): - if s_array.ndim == 0: - raise AnnotatorError() - if s_array.ndim > 1: - return SomeArray(s_array.typecode, s_array.ndim-1) - return s_array.get_item_type() - class __extend__(pairtype(SomeArray, SomeTuple)): def get_leftover_dim((s_array, s_index)): ndim = s_array.ndim @@ -100,8 +86,10 @@ def setitem((s_array, s_index), s_value): ndim = pair(s_array, s_index).get_leftover_dim() + if len(s_index.items)>s_array.ndim: + raise AnnotatorError("invalid index") if isinstance(s_value, SomeArray): - if s_value.ndim + ndim != s_array.ndim: + if s_value.ndim != ndim: # XX allow broadcasting.. raise AnnotatorError("shape mismatch") elif ndim > 0: @@ -109,12 +97,33 @@ def getitem((s_array, s_index)): ndim = pair(s_array, s_index).get_leftover_dim() + if len(s_index.items)>s_array.ndim: + raise AnnotatorError("invalid index") if s_array.ndim == 0 and len(s_index.items): raise AnnotatorError("indexing rank zero array with nonempty tuple") if ndim > 0: return SomeArray(s_array.typecode, ndim) return s_array.get_item_type() +# These two up-cast the index to SomeTuple and call above. +class __extend__(pairtype(SomeArray, SomeSlice)): + def setitem((s_array, s_index), s_value): + s_tuple = SomeTuple([s_index]) + return pair(s_array, s_tuple).setitem(s_value) + + def getitem((s_array, s_index)): + s_tuple = SomeTuple([s_index]) + return pair(s_array, s_tuple).getitem() + +class __extend__(pairtype(SomeArray, SomeInteger)): + def setitem((s_array, s_index), s_value): + s_tuple = SomeTuple([s_index]) + return pair(s_array, s_tuple).setitem(s_value) + + def getitem((s_array, s_index)): + s_tuple = SomeTuple([s_index]) + return pair(s_array, s_tuple).getitem() + numpy_typedict = { (SomeInteger, rffi.r_signedchar) : 'b', (SomeInteger, rffi.r_short) : 'h', @@ -159,9 +168,9 @@ raise AnnotatorError("List item type not supported") return SomeArray(typecode, ndim) - def specialize_call(self, hop): + def specialize_call(self, hop, i_dtype=None): r_array = hop.r_result - [v_lst] = hop.inputargs(r_array) # coerce list arg to array arg + v_lst = hop.inputarg(r_array, 0) # coerce list arg to array arg v_result = r_array.build_from_array(hop.llops, v_lst) return v_result @@ -197,10 +206,10 @@ # v_result = r_array.build_from_shape(hop.llops, r_lst, v_lst) # return v_result - def specialize_call(self, hop): + def specialize_call(self, hop, i_dtype=None): r_tpl = hop.args_r[0] # XX also call with single int arg - [v_tpl] = hop.inputargs(r_tpl) + v_tpl = hop.inputarg(r_tpl, 0) r_array = hop.r_result v_result = r_array.build_from_shape(hop.llops, r_tpl, v_tpl) return v_result Modified: pypy/dist/pypy/rpython/numpy/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/rarray.py (original) +++ pypy/dist/pypy/rpython/numpy/rarray.py Thu Aug 30 02:59:54 2007 @@ -2,14 +2,18 @@ from pypy.rpython.rrange import AbstractRangeRepr from pypy.rpython.rint import IntegerRepr from pypy.rpython.rlist import AbstractBaseListRepr +from pypy.rpython.rtuple import AbstractTupleRepr from pypy.rpython.error import TyperError from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE +from pypy.rpython.rslice import AbstractSliceRepr from pypy.rpython.lltypesystem.lltype import \ - GcArray, GcStruct, Signed, Ptr, Unsigned, malloc, Void + GcArray, GcStruct, Signed, Ptr, Unsigned, Void, FixedSizeArray, Bool,\ + malloc, direct_arrayitems, direct_ptradd +from pypy.rpython.lltypesystem.rtuple import TupleRepr from pypy.annotation.model import SomeObject, SomeInteger from pypy.rpython.numpy.aarray import SomeArray -from pypy.annotation.pairtype import pairtype +from pypy.annotation.pairtype import pairtype, pair from pypy.rlib.unroll import unrolling_iterable from pypy.annotation import listdef from pypy.rpython.memory.lltypelayout import sizeof @@ -40,47 +44,110 @@ return shape return ll_get_shape +NPY_INTP = Signed # index type (see Py_intptr_t) +def ARRAY_ITER(ARRAY, INDEXARRAY): + ITER = Ptr( + GcStruct("array_iter", + ("nd_m1", Signed), # number of dimensions - 1 + ("index", NPY_INTP), + ("size", NPY_INTP), + ("coordinates", INDEXARRAY), + ("dims_m1", INDEXARRAY), + ("strides", INDEXARRAY), + ("backstrides", INDEXARRAY), + #("factors", INDEXARRAY), + ("ao", ARRAY), + ("dataptr", Ptr(FixedSizeArray(ARRAY.TO.data.TO.OF, 1))), # pointer to current item + #("contiguous", Bool), + )) + return ITER + +def ll_mul_list(items, n): + result = 1 + while n: + result *= items[n-1] + n -= 1 + return result + +def gen_iter_funcs(ndim): + unroll_ndim = unrolling_iterable(range(ndim)) + unroll_ndim_rev = unrolling_iterable(reversed(range(ndim))) + + def ll_iter_reset(it): + it.index = 0 + it.dataptr = direct_arrayitems(it.ao.data) + for i in unroll_ndim: + it.coordinates[i] = 0 + + def ll_iter_new(ITER, ao): + it = malloc(ITER) + it.nd_m1 = ndim - 1 + it.size = ll_mul_list(ao.shape, ndim) + it.ao = ao + #it.factors[nd-1] = 1 + for i in unroll_ndim: + it.dims_m1[i] = ao.shape[i]-1 + it.strides[i] = ao.strides[i] + it.backstrides[i] = it.strides[i] * it.dims_m1[i] + #if i > 0: + #it.factors[nd-i-1] = it.factors[nd]*ao.shape[nd-i] + # ll_iter_reset(it) + it.index = 0 + it.dataptr = direct_arrayitems(it.ao.data) + for i in unroll_ndim: + it.coordinates[i] = 0 + return it + ll_iter_new._always_inline_ = True + + def ll_iter_next(it): + it.index += 1 + for i in unroll_ndim_rev: + if it.coordinates[i] < it.dims_m1[i]: + it.coordinates[i] += 1 + it.dataptr = direct_ptradd(it.dataptr, it.strides[i]) + break + it.coordinates[i] = 0 + it.dataptr = direct_ptradd(it.dataptr, -it.backstrides[i]) + i -= 1 + ll_iter_next._always_inline_ = True + + return ll_iter_new, ll_iter_next + +def ll_setitem_from_array(iter_new0, iter_next0, ITER0, array0, + slice, + iter_new1, iter_next1, ITER1, array1): + it0 = iter_new0(ITER0, array0) + it1 = iter_new1(ITER1, array1) + while it0.index < it0.size: + it0.dataptr[0] = it1.dataptr[0] + iter_next0(it0) + iter_next1(it1) class ArrayRepr(Repr): def __init__(self, rtyper, s_array): self.s_array = s_array self.s_value = s_array.get_item_type() - self.item_repr = rtyper.getrepr(self.s_value) - ITEM = self.item_repr.lowleveltype - ITEMARRAY = GcArray(ITEM, hints={'nolength':True}) - SIZEARRAY = GcArray(Signed, hints={'nolength':True}) - self.PTR_SIZEARRAY = Ptr(SIZEARRAY) - self.itemsize = sizeof(ITEM) self.ndim = s_array.ndim + self.item_repr = rtyper.getrepr(self.s_value) + self.ITEM = self.item_repr.lowleveltype + ITEMARRAY = GcArray(self.ITEM, hints={'nolength':True}) + self.INDEXARRAY = FixedSizeArray(NPY_INTP, self.ndim) + self.itemsize = sizeof(self.ITEM) self.ARRAY = Ptr( GcStruct("array", ("data", Ptr(ITEMARRAY)), # pointer to raw data buffer - ("ndim", Signed), # number of dimensions - ("shape", self.PTR_SIZEARRAY), # size in each dimension - ("strides", self.PTR_SIZEARRAY), # bytes (?) to jump to get to the + ("ndim", Signed), # number of dimensions (do we need this ?) + ("shape", self.INDEXARRAY), # size in each dimension + ("strides", self.INDEXARRAY), # elements to jump to get to the # next element in each dimension )) self.lowleveltype = self.ARRAY + self.ITER = ARRAY_ITER(self.ARRAY, self.INDEXARRAY) def build_from_array(self, llops, v_array): cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) return llops.gendirectcall(ll_build_alias, cARRAY, v_array) -# def build_from_shape(self, llops, r_tuple, v_tuple): -# cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) -# cTUPLE = inputconst(lltype.Void, r_tuple.lowleveltype.TO) -# ndim = self.ndim -# c_ndim = inputconst(lltype.Signed, ndim) -# assert ndim == len(r_tuple.items_r) -# v_array = llops.gendirectcall(ll_allocate, cARRAY, c_ndim) -# c_attr = inputconst(lltype.Void, 'shape') -# v_shape = llops.genop('getfield', [v_array, c_attr], self.PTR_SIZEARRAY) -# for i in range(ndim): -# v_size = r_tuple.getitem_internal(llops, v_tuple, i) -# v_i = inputconst(lltype.Signed, i) -# llops.genop('setarrayitem', [v_shape, v_i, v_size]) -# return v_array - def build_from_shape(self, llops, r_tuple, v_tuple): cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) cTUPLE = inputconst(lltype.Void, r_tuple.lowleveltype.TO) @@ -130,21 +197,57 @@ class __extend__(pairtype(ArrayRepr, ArrayRepr)): - def rtype_add((r_arr1,r_arr2), hop): + def rtype_add((r_arr1, r_arr2), hop): v_arr1, v_arr2 = hop.inputargs(r_arr1, r_arr2) cARRAY = hop.inputconst(Void, hop.r_result.ARRAY.TO) return hop.gendirectcall(ll_add, cARRAY, v_arr1, v_arr2) class __extend__(pairtype(ArrayRepr, IntegerRepr)): - def rtype_setitem((r_arr,r_int), hop): + def rtype_setitem((r_arr, r_int), hop): v_array, v_index, v_item = hop.inputargs(r_arr, Signed, r_arr.item_repr) return hop.gendirectcall(ll_setitem, v_array, v_index, v_item) - def rtype_getitem((r_arr,r_int), hop): + def rtype_getitem((r_arr, r_int), hop): v_array, v_index = hop.inputargs(r_arr, Signed) return hop.gendirectcall(ll_getitem, v_array, v_index) +#class __extend__(pairtype(ArrayRepr, AbstractTupleRepr)): +# def rtype_setitem((r_arr, r_tpl), hop): +# v_array, v_tuple, v_item = hop.inputargs(r_arr, r_tpl, r_arr) +# return hop.gendirectcall(ll_setitem_from_array, v_array, v_tuple, v_item) +# +# def rtype_getitem((r_arr, r_tpl), hop): +# return NotImplemented + + +class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)): + def rtype_setitem((r_arr, r_slc), hop): + r_item = hop.args_r[2] + v_array, v_slc, v_item = hop.inputargs(r_arr, r_slc, r_item) + cITER0 = hop.inputconst(Void, r_arr.ITER.TO) + cITER1 = hop.inputconst(Void, r_item.ITER.TO) + iter_new0, iter_next0 = gen_iter_funcs(r_arr.ndim) + iter_new1, iter_next1 = gen_iter_funcs(r_item.ndim) + cnew0 = hop.inputconst(Void, iter_new0) + cnext0 = hop.inputconst(Void, iter_next0) + cnew1 = hop.inputconst(Void, iter_new1) + cnext1 = hop.inputconst(Void, iter_next1) +# return hop.gendirectcall(ll_setitem_from_array, cnext, cITER0, v_array, v_slc, cITER1, v_item) + return hop.gendirectcall(ll_setitem_from_array, + cnew0, cnext0, cITER0, v_array, v_slc, cnew1, cnext1, cITER1, v_item) + + +#class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)): +# # promote and delegate XX doesn't work +# def rtype_setitem((r_arr, r_slc), hop): +# r_tpl = TupleRepr(hop.rtyper, [r_slc]) +# return pair(r_arr, r_tpl).rtype_setitem(hop) +# +# def rtype_getitem((r_arr, r_slc), hop): +# r_tpl = TupleRepr(hop.rtyper, [r_slc]) +# return pair(r_arr, r_tpl).rtype_getitem(hop) + class __extend__(pairtype(AbstractBaseListRepr, ArrayRepr)): def convert_from_to((r_lst, r_arr), v, llops): if r_lst.listitem is None: @@ -163,8 +266,8 @@ def ll_allocate(ARRAY, ndim): array = malloc(ARRAY) array.ndim = ndim - array.shape = malloc(ARRAY.shape.TO, array.ndim) - array.strides = malloc(ARRAY.strides.TO, array.ndim) + #array.shape = malloc(ARRAY.shape.TO, array.ndim) + #array.strides = malloc(ARRAY.strides.TO, array.ndim) return array def ll_build_from_list(ARRAY, lst): Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Thu Aug 30 02:59:54 2007 @@ -86,7 +86,10 @@ a = numpy.zeros((3,4,5)) b = a[0] a[0,1,2] = 1. - b[0,1] = a[2] + b[0,1] = 2. + b[:] = a[1] + b[:,:] = a[1] + b[0,:] = a[1,2] return b t = TranslationContext() @@ -180,7 +183,7 @@ def test_specialize_array_access(self): def access_with_variable(): - my_array = numpy.array(range(10)) + my_array = numpy.array(range(10), dtype='i') my_array[2] = 2 sum = 0 for idx in range(10): @@ -238,14 +241,41 @@ assert res.data[0] == 1 assert res.data[1] == 2 - def X_test_specialize_view(self): + def test_specialize_indexing(self): + def f(): + a = numpy.zeros((3,), dtype='i') + b = numpy.array([5,55,555]) + a[:] = b + return a + #self.specialize_view(f) + res = interpret(f, []) + assert res.data[0] == 5 + assert res.data[1] == 55 + assert res.data[2] == 555 + + def specialize_view(self, f, args=[]): t = TranslationContext() a = t.buildannotator() - a = a.build_types(f, []) + a = a.build_types(f, args) r = t.buildrtyper() r.specialize() + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(t, inline=True) t.view() +#from pypy.rlib.unroll import unrolling_iterable, unrolling_zero +#unroller = unrolling_iterable((1,2,3)) +#def deep_f(result, i): +# result += 1 +# if i<5: +# result *= deep_f(result, i+1) +# return result +# +#def deep_unroll(): +## i = unrolling_zero +# i = 0 +# return deep_f(0, i) + class Test_compile: def setup_class(self): if not test_c_compile: @@ -265,6 +295,7 @@ assert fn(1) == 99 def test_compile_2d(self): + py.test.skip() def access_array(index): a = numpy.zeros((5,6)) a[0,0] = 2 From fijal at codespeak.net Thu Aug 30 09:57:38 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 09:57:38 +0200 (CEST) Subject: [pypy-svn] r46179 - in pypy/branch/pypy-more-rtti-inprogress/rpython/tool: . test Message-ID: <20070830075738.C41A08116@code0.codespeak.net> Author: fijal Date: Thu Aug 30 09:57:36 2007 New Revision: 46179 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Log: Add the "has" function to rffi_platform, right now if we give up caching, we can simply move to rffi_platform from rfficache Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/rffi_platform.py Thu Aug 30 09:57:36 2007 @@ -6,6 +6,7 @@ from pypy.rpython.lltypesystem import llmemory from pypy.translator.tool.cbuild import build_executable from pypy.tool.udir import udir +import distutils # ____________________________________________________________ # @@ -35,6 +36,12 @@ DEFINED = Defined(macro) return configure(CConfig)['DEFINED'] +def has(name, c_header_source): + class CConfig: + _header_ = c_header_source + HAS = Has(name) + return configure(CConfig)['HAS'] + # ____________________________________________________________ # # General interface @@ -58,7 +65,56 @@ def get_result(self): return dict([(name, self.result[entry]) for entry, name in self.entries.iteritems()]) - + +class _CWriter(object): + """ A simple class which aggregates config parts + """ + def __init__(self, CConfig): + self.path = uniquefilepath() + self.f = self.path.open("w") + self.config = CConfig + + def write_header(self): + f = self.f + CConfig = self.config + print >> f, C_HEADER + print >> f + for path in getattr(CConfig, '_includes_', ()): # optional + print >> f, '#include <%s>' % (path,) + print >> f, getattr(CConfig, '_header_', '') # optional + print >> f + + def write_entry(self, key, entry): + f = self.f + print >> f, 'void dump_section_%s(void) {' % (key,) + for line in entry.prepare_code(): + if line and line[0] != '#': + line = '\t' + line + print >> f, line + print >> f, '}' + print >> f + + def write_entry_main(self, key): + print >> self.f, '\tprintf("-+- %s\\n");' % (key,) + print >> self.f, '\tdump_section_%s();' % (key,) + print >> self.f, '\tprintf("---\\n");' + + def start_main(self): + print >> self.f, 'int main(int argc, char *argv[]) {' + + def close(self): + f = self.f + print >> f, '\treturn 0;' + print >> f, '}' + f.close() + + def ask_gcc(self, question): + self.start_main() + self.f.write(question + "\n") + self.close() + include_dirs = getattr(self.config, '_include_dirs_', []) + build_executable([self.path], include_dirs=include_dirs) + def configure(CConfig): """Examine the local system by running the C compiler. The CConfig class contains CConfigEntry attribues that describe @@ -69,36 +125,21 @@ for key in dir(CConfig): value = getattr(CConfig, key) if isinstance(value, CConfigEntry): - entries.append((key, value)) + entries.append((key, value)) - filepath = uniquefilepath() - f = filepath.open('w') - print >> f, C_HEADER - print >> f - for path in getattr(CConfig, '_includes_', ()): # optional - print >> f, '#include <%s>' % (path,) - print >> f, getattr(CConfig, '_header_', '') # optional - print >> f + writer = _CWriter(CConfig) + writer.write_header() for key, entry in entries: - print >> f, 'void dump_section_%s(void) {' % (key,) - for line in entry.prepare_code(): - if line and line[0] != '#': - line = '\t' + line - print >> f, line - print >> f, '}' - print >> f + writer.write_entry(key, entry) - print >> f, 'int main(int argc, char *argv[]) {' + f = writer.f + writer.start_main() for key, entry in entries: - print >> f, '\tprintf("-+- %s\\n");' % (key,) - print >> f, '\tdump_section_%s();' % (key,) - print >> f, '\tprintf("---\\n");' - print >> f, '\treturn 0;' - print >> f, '}' - f.close() + writer.write_entry_main(key) + writer.close() include_dirs = getattr(CConfig, '_include_dirs_', []) - infolist = list(run_example_code(filepath, include_dirs)) + infolist = list(run_example_code(writer.path, include_dirs)) assert len(infolist) == len(entries) resultinfo = {} @@ -110,6 +151,15 @@ result = ConfigResult(CConfig, resultinfo, resultentries) for name, entry in entries: result.get_entry_result(entry) + + for key in dir(CConfig): + value = getattr(CConfig, key) + if isinstance(value, CConfigSingleEntry): + writer = _CWriter(CConfig) + writer.write_header() + result.result[value] = value.question(writer.ask_gcc) + result.entries[value] = key + return result.get_result() # ____________________________________________________________ @@ -332,31 +382,22 @@ def build_result(self, info, config_result): return bool(info['defined']) - -class Library(CConfigEntry): - """The loaded library object. +class CConfigSingleEntry(object): + """ An abstract class of type which requires + gcc succeeding/failing instead of only asking """ + pass + +class Has(CConfigSingleEntry): def __init__(self, name): - XXX # uh self.name = name - - def prepare_code(self): - # XXX should check that we can link against the lib - return [] - - def build_result(self, info, config_result): - from pypy.rpython.rctypes.tool import util - path = util.find_library(self.name) - mylib = ctypes.cdll.LoadLibrary(path) - - class _FuncPtr(ctypes._CFuncPtr): - _flags_ = ctypes._FUNCFLAG_CDECL - _restype_ = ctypes.c_int # default, can be overridden in instances - includes = tuple(config_result.CConfig._includes_) - libraries = (self.name,) - - mylib._FuncPtr = _FuncPtr - return mylib + + def question(self, ask_gcc): + try: + ask_gcc(self.name + ';') + return True + except distutils.errors.CompileError: + return False # ____________________________________________________________ # Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/tool/test/test_rffi_platform.py Thu Aug 30 09:57:36 2007 @@ -185,3 +185,7 @@ """, [("d_name", lltype.FixedSizeArray(rffi.CHAR, 1))]) assert dirent.c_d_name.length == 32 + +def test_has(): + assert rffi_platform.has("x", "int x = 3;") + assert not rffi_platform.has("x", "") From fijal at codespeak.net Thu Aug 30 12:09:38 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 12:09:38 +0200 (CEST) Subject: [pypy-svn] r46183 - pypy/branch/pypy-more-rtti-inprogress/rpython Message-ID: <20070830100938.3AFF381CB@code0.codespeak.net> Author: fijal Date: Thu Aug 30 12:09:37 2007 New Revision: 46183 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Log: * Few helpers for configuration * Be more verbose when raising exception for lazy_register Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Thu Aug 30 12:09:37 2007 @@ -47,7 +47,9 @@ raise exc, exc_inst, tb class ExtRaisingEntry(ExtRegistryEntry): _about_ = func - def compute_result_annotation(self, *args_s): + def __getattr__(self, attr): + if attr == '_about_' or attr == '__dict__': + return super(ExtRegistryEntry, self).__getattr__(attr) raise exc, exc_inst, tb def registering(func): @@ -90,6 +92,27 @@ class BaseLazyRegistering(object): __metaclass__ = LazyRegisteringMeta + __ATTRIBUTES = ['includes', 'include_dirs'] + + def configure(self, CConfig): + from pypy.rpython.tool import rffi_platform as platform + # copy some stuff + for item in self.__ATTRIBUTES: + value = getattr(CConfig, '_%s_' % item, None) + if value: + setattr(self, '_%s_' % item, value) + self.__dict__.update(platform.configure(CConfig)) + + def llexternal(self, *args, **kwds): + from pypy.rpython.lltypesystem import rffi + + for item in self.__ATTRIBUTES: + if item not in kwds: + kwds[item] = getattr(self, '_%s_' % item, []) + else: + kwds[item] += getattr(self, '_%s_' % item, []) + return rffi.llexternal(*args, **kwds) + class genericcallable(object): """ A way to specify the callable annotation, but deferred until we have bookkeeper From fijal at codespeak.net Thu Aug 30 12:13:22 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 12:13:22 +0200 (CEST) Subject: [pypy-svn] r46184 - pypy/branch/pypy-more-rtti-inprogress/rpython Message-ID: <20070830101322.A13B481D0@code0.codespeak.net> Author: fijal Date: Thu Aug 30 12:13:21 2007 New Revision: 46184 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Log: Uh :-/ Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Thu Aug 30 12:13:21 2007 @@ -33,7 +33,7 @@ raise except: if 0: - import sys, traceback + import traceback print >> sys.stderr, 'WARNING: cannot register', func_or_list, ':' traceback.print_exc() import pdb; pdb.set_trace() From fijal at codespeak.net Thu Aug 30 12:15:03 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 12:15:03 +0200 (CEST) Subject: [pypy-svn] r46185 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070830101503.32E3781D0@code0.codespeak.net> Author: fijal Date: Thu Aug 30 12:15:02 2007 New Revision: 46185 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Log: Use cool helpers Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 30 12:15:02 2007 @@ -15,21 +15,48 @@ from pypy.annotation.model import SomeInteger, SomeString, SomeTuple, SomeFloat from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool from pypy.rpython.lltypesystem import rffi -from pypy.rpython.lltypesystem.rffi import platform from pypy.rpython.lltypesystem import lltype -from pypy.rpython.tool import rffi_platform +from pypy.rpython.tool import rffi_platform as platform posix = __import__(os.name) +class CConfig: + """ + Definitions for platform integration. + + Note: this must be processed through platform.configure() to provide + usable objects. For example:: + + CLOCK_T = platform.configure(CConfig)['CLOCK_T'] + register(function, [CLOCK_T], ...) + + """ + _includes_ = ['sys/times.h', 'utime.h', 'sys/types.h', 'unistd.h', + 'signal.h', 'wait.h'] + if not sys.platform.startswith('win'): + _includes_ += ['dirent.h', 'sys/stat.h'] + + CLOCK_T = platform.SimpleType('clock_t', rffi.INT) + + NAME_MAX = platform.DefinedConstantInteger('NAME_MAX') + + SEEK_SET = platform.DefinedConstantInteger('SEEK_SET') + SEEK_CUR = platform.DefinedConstantInteger('SEEK_CUR') + SEEK_END = platform.DefinedConstantInteger('SEEK_END') + + TMS = platform.Struct( + 'struct tms', [('tms_utime', rffi.INT), + ('tms_stime', rffi.INT), + ('tms_cutime', rffi.INT), + ('tms_cstime', rffi.INT)]) -class RegisterOs(BaseLazyRegistering): - UNISTD_INCL = ['unistd.h', 'sys/types.h'] +class RegisterOs(BaseLazyRegistering): def __init__(self): - pass + self.configure(CConfig) # a simple, yet usefull factory def extdef_for_os_function_returning_int(self, name, **kwds): - c_func = rffi.llexternal(name, [], rffi.INT, **kwds) + c_func = self.llexternal(name, [], rffi.INT, **kwds) def c_func_llimpl(): res = c_func() if res == -1: @@ -42,7 +69,7 @@ @registering_if(os, 'execv') def register_os_execv(self): - os_execv = rffi.llexternal('execv', [rffi.CCHARP, rffi.CCHARPP], + os_execv = self.llexternal('execv', [rffi.CCHARP, rffi.CCHARPP], rffi.INT) def execv_llimpl(path, args): @@ -58,7 +85,7 @@ @registering_if(posix, 'spawnv') def register_os_spawnv(self): - os_spawnv = rffi.llexternal('spawnv', + os_spawnv = self.llexternal('spawnv', [rffi.INT, rffi.CCHARP, rffi.CCHARPP], rffi.INT) @@ -78,7 +105,7 @@ @registering(os.dup) def register_os_dup(self): - os_dup = rffi.llexternal('dup', [rffi.INT], rffi.INT) + os_dup = self.llexternal('dup', [rffi.INT], rffi.INT) def dup_llimpl(fd): newfd = rffi.cast(lltype.Signed, os_dup(rffi.cast(rffi.INT, fd))) @@ -91,7 +118,7 @@ @registering(os.dup2) def register_os_dup2(self): - os_dup2 = rffi.llexternal('dup2', [rffi.INT, rffi.INT], rffi.INT) + os_dup2 = self.llexternal('dup2', [rffi.INT, rffi.INT], rffi.INT) def dup2_llimpl(fd, newfd): error = rffi.cast(lltype.Signed, os_dup2(rffi.cast(rffi.INT, fd), @@ -104,17 +131,12 @@ @registering(os.utime) def register_os_utime(self): - #START - #print rffi.platform.has('utimes'), rffi.platform.has('utime') - #STOP TIME_T = rffi.INT # XXX do the right thing UTIMEBUFP = rffi.CStructPtr('utimbuf', ('actime', TIME_T), ('modtime', TIME_T)) # XXX sys/types.h is not portable at all - os_utime = rffi.llexternal('utime', [rffi.CCHARP, UTIMEBUFP], - rffi.INT, - includes=['utime.h', 'sys/types.h']) + os_utime = self.llexternal('utime', [rffi.CCHARP, UTIMEBUFP], rffi.INT) def os_utime_llimpl(path, tp): # XXX right now they're all ints, might change in future @@ -167,56 +189,26 @@ @registering(os.times) def register_os_times(self): - # XXX sys/times.h isn't portable - class CConfig: - """ - Definitions for platform integration. - - Note: this must be processed through rffi_platform.configure() to - provide usable objects. For example:: - - CLOCK_T = rffi_platform.configure(CConfig)['CLOCK_T'] - register(function, [CLOCK_T], ...) - - """ - includes = ['sys/times.h'] - # XXX argh, argh, argh, should be automatic - _header_ = "\n".join(["#include <%s>" % name for name in includes]) - - CLOCK_T = rffi_platform.SimpleType('clock_t', rffi.INT) - - TMS = rffi_platform.Struct( - 'struct tms', [('tms_utime', rffi.INT), - ('tms_stime', rffi.INT), - ('tms_cutime', rffi.INT), - ('tms_cstime', rffi.INT)]) - - # Grab all of the platform type definitions - config = rffi_platform.configure(CConfig) - CLOCK_T = config['CLOCK_T'] - TMS = config['TMS'] - # Make some pointer types too - TMSP = lltype.Ptr(TMS) + self.TMSP = lltype.Ptr(self.TMS) + os_times = self.llexternal('times', [self.TMSP], self.CLOCK_T) + # Here is a random extra platform parameter which is important. # Strictly speaking, this should probably be retrieved at runtime, not # at translation time. - CLOCK_TICKS_PER_SECOND = float(os.sysconf('SC_CLK_TCK')) - - os_times = rffi.llexternal('times', [TMSP], CLOCK_T, - includes=['sys/times.h']) + self.CLOCK_TICKS_PER_SECOND = float(os.sysconf('SC_CLK_TCK')) def times_lltypeimpl(): - l_tmsbuf = lltype.malloc(TMSP.TO, flavor='raw') + l_tmsbuf = lltype.malloc(self.TMSP.TO, flavor='raw') try: result = os_times(l_tmsbuf) if result == -1: raise OSError(rffi.get_errno(), "times failed") return ( - l_tmsbuf.c_tms_utime / CLOCK_TICKS_PER_SECOND, - l_tmsbuf.c_tms_stime / CLOCK_TICKS_PER_SECOND, - l_tmsbuf.c_tms_cutime / CLOCK_TICKS_PER_SECOND, - l_tmsbuf.c_tms_cstime / CLOCK_TICKS_PER_SECOND, - result / CLOCK_TICKS_PER_SECOND) + l_tmsbuf.c_tms_utime / self.CLOCK_TICKS_PER_SECOND, + l_tmsbuf.c_tms_stime / self.CLOCK_TICKS_PER_SECOND, + l_tmsbuf.c_tms_cutime / self.CLOCK_TICKS_PER_SECOND, + l_tmsbuf.c_tms_cstime / self.CLOCK_TICKS_PER_SECOND, + result / self.CLOCK_TICKS_PER_SECOND) finally: lltype.free(l_tmsbuf, flavor='raw') self.register(os.times, [], (float, float, float, float, float), @@ -225,8 +217,7 @@ @registering_if(os, 'setsid') def register_os_setsid(self): - os_setsid = rffi.llexternal('setsid', [], rffi.PID_T, - includes=['unistd.h']) + os_setsid = self.llexternal('setsid', [], rffi.PID_T) def setsid_llimpl(): result = rffi.cast(lltype.Signed, os_setsid()) if result == -1: @@ -250,7 +241,7 @@ ('domainname', UTCHARP)] UTSNAMEP = rffi.CStructPtr('utsname', *fields) - os_uname = rffi.llexternal('uname', [UTSNAMEP], rffi.INT, + os_uname = self.llexternal('uname', [UTSNAMEP], rffi.INT, includes=['sys/utsname.h']) def utcharp2str(cp): @@ -277,20 +268,17 @@ return extdef([], (str, str, str, str, str), "ll_os.ll_uname", llimpl=uname_llimpl) - @registering_if(os, 'getuid') + @registering(os.getuid) def register_os_getuid(self): - return self.extdef_for_os_function_returning_int('getuid', - includes=self.UNISTD_INCL) + return self.extdef_for_os_function_returning_int('getuid') - @registering_if(os, 'geteuid') + @registering(os.geteuid) def register_os_geteuid(self): - return self.extdef_for_os_function_returning_int('geteuid', - includes=self.UNISTD_INCL) + return self.extdef_for_os_function_returning_int('geteuid') @registering_if(os, 'getpid') def register_os_getpid(self): - return self.extdef_for_os_function_returning_int('getpid', - includes=self.UNISTD_INCL) + return self.extdef_for_os_function_returning_int('getpid') @registering(os.open) def register_os_open(self): @@ -298,7 +286,7 @@ mode_t = rffi.INT else: mode_t = rffi.MODE_T - os_open = rffi.llexternal('open', [rffi.CCHARP, rffi.INT, mode_t], + os_open = self.llexternal('open', [rffi.CCHARP, rffi.INT, mode_t], rffi.INT) def os_open_llimpl(path, flags, mode): @@ -321,7 +309,7 @@ @registering(os.read) def register_os_read(self): - os_read = rffi.llexternal('read', [rffi.INT, rffi.VOIDP, rffi.SIZE_T], + os_read = self.llexternal('read', [rffi.INT, rffi.VOIDP, rffi.SIZE_T], rffi.SIZE_T) def os_read_llimpl(fd, count): @@ -347,7 +335,7 @@ @registering(os.write) def register_os_write(self): - os_write = rffi.llexternal('write', [rffi.INT, rffi.VOIDP, + os_write = self.llexternal('write', [rffi.INT, rffi.VOIDP, rffi.SIZE_T], rffi.SIZE_T) def os_write_llimpl(fd, data): @@ -374,7 +362,7 @@ @registering(os.close) def register_os_close(self): - os_close = rffi.llexternal('close', [rffi.INT], rffi.INT) + os_close = self.llexternal('close', [rffi.INT], rffi.INT) def close_llimpl(fd): error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd))) @@ -388,14 +376,12 @@ def register_os_lseek(self): if sys.platform.startswith('win'): funcname = '_lseeki64' - INCLUDES = [] else: funcname = 'lseek' - INCLUDES = self.UNISTD_INCL - if platform.defined('SEEK_SET', includes=INCLUDES): - SEEK_SET = platform.intdefined('SEEK_SET', includes=INCLUDES) - SEEK_CUR = platform.intdefined('SEEK_CUR', includes=INCLUDES) - SEEK_END = platform.intdefined('SEEK_END', includes=INCLUDES) + if self.SEEK_SET is not None: + SEEK_SET = self.SEEK_SET + SEEK_CUR = self.SEEK_CUR + SEEK_END = self.SEEK_END else: SEEK_SET, SEEK_CUR, SEEK_END = 0, 1, 2 if (SEEK_SET, SEEK_CUR, SEEK_END) != (0, 1, 2): @@ -409,7 +395,7 @@ def fix_seek_arg(n): return n - os_lseek = rffi.llexternal(funcname, + os_lseek = self.llexternal(funcname, [rffi.INT, rffi.LONGLONG, rffi.INT], rffi.LONGLONG) @@ -435,7 +421,7 @@ @registering_if(os, 'ftruncate') def register_os_ftruncate(self): - os_ftruncate = rffi.llexternal('ftruncate', + os_ftruncate = self.llexternal('ftruncate', [rffi.INT, rffi.LONGLONG], rffi.INT) def ftruncate_llimpl(fd, length): @@ -450,7 +436,7 @@ @registering(os.access) def register_os_access(self): - os_access = rffi.llexternal('access', + os_access = self.llexternal('access', [rffi.CCHARP, rffi.INT], rffi.INT) @@ -470,7 +456,7 @@ @registering(os.getcwd) def register_os_getcwd(self): - os_getcwd = rffi.llexternal('getcwd', + os_getcwd = self.llexternal('getcwd', [rffi.CCHARP, rffi.SIZE_T], rffi.CCHARP) @@ -506,20 +492,15 @@ if sys.platform.startswith('win'): XXX # FindFirstFile, FindNextFile else: - INCL = ['sys/types.h', 'dirent.h'] - DIRP = rffi.COpaquePtr('DIR', includes=INCL) - NAME_MAX = platform.intdefined('NAME_MAX', includes=INCL) + DIRP = rffi.COpaquePtr('DIR') DIRENTP = rffi.CStructPtr('dirent', - ('d_name', lltype.FixedSizeArray(lltype.Char, NAME_MAX+1)), + ('d_name', lltype.FixedSizeArray(lltype.Char, self.NAME_MAX+1)), ) # XXX so far, DIRENTP cannot be handled by ll2ctypes because # it contains other fields before 'd_name', at least on Linux - os_opendir = rffi.llexternal('opendir', [rffi.CCHARP], DIRP, - includes = INCL) - os_readdir = rffi.llexternal('readdir', [DIRP], DIRENTP, - includes = INCL) - os_closedir = rffi.llexternal('closedir', [DIRP], rffi.INT, - includes = INCL) + os_opendir = self.llexternal('opendir', [rffi.CCHARP], DIRP) + os_readdir = self.llexternal('readdir', [DIRP], DIRENTP) + os_closedir = self.llexternal('closedir', [DIRP], rffi.INT) def os_listdir_llimpl(path): path = rffi.str2charp(path) @@ -555,8 +536,7 @@ XXX # CreatePipe, _open_osfhandle else: INT_ARRAY_P = lltype.Ptr(lltype.FixedSizeArray(rffi.INT, 2)) - os_pipe = rffi.llexternal('pipe', [INT_ARRAY_P], rffi.INT, - includes=['unistd.h']) + os_pipe = self.llexternal('pipe', [INT_ARRAY_P], rffi.INT) def os_pipe_llimpl(): filedes = lltype.malloc(INT_ARRAY_P.TO, flavor='raw') @@ -574,7 +554,7 @@ @registering_if(os, 'readlink') def register_os_readlink(self): - os_readlink = rffi.llexternal('readlink', + os_readlink = self.llexternal('readlink', [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], rffi.INT) # XXX SSIZE_T in POSIX.1-2001 @@ -614,7 +594,7 @@ def register_os_waitpid(self): if sys.platform.startswith('win'): # emulate waitpid() with the _cwait() of Microsoft's compiler - os__cwait = rffi.llexternal('_cwait', + os__cwait = self.llexternal('_cwait', [rffi.INTP, rffi.PID_T, rffi.INT], rffi.PID_T) def os_waitpid(pid, status_p, options): @@ -625,7 +605,7 @@ return result else: # Posix - os_waitpid = rffi.llexternal('waitpid', + os_waitpid = self.llexternal('waitpid', [rffi.PID_T, rffi.INTP, rffi.INT], rffi.PID_T) @@ -648,7 +628,7 @@ @registering(os.isatty) def register_os_isatty(self): - os_isatty = rffi.llexternal('isatty', [rffi.INT], rffi.INT) + os_isatty = self.llexternal('isatty', [rffi.INT], rffi.INT) def isatty_llimpl(fd): res = os_isatty(rffi.cast(rffi.INT, fd)) @@ -659,7 +639,7 @@ @registering(os.strerror) def register_os_strerror(self): - os_strerror = rffi.llexternal('strerror', [rffi.INT], rffi.CCHARP) + os_strerror = self.llexternal('strerror', [rffi.INT], rffi.CCHARP) def strerror_llimpl(errnum): res = os_strerror(rffi.cast(rffi.INT, errnum)) @@ -672,7 +652,7 @@ @registering(os.system) def register_os_system(self): - os_system = rffi.llexternal('system', [rffi.CCHARP], rffi.INT) + os_system = self.llexternal('system', [rffi.CCHARP], rffi.INT) def system_llimpl(command): l_command = rffi.str2charp(command) @@ -685,7 +665,7 @@ @registering(os.unlink) def register_os_unlink(self): - os_unlink = rffi.llexternal('unlink', [rffi.CCHARP], rffi.INT) + os_unlink = self.llexternal('unlink', [rffi.CCHARP], rffi.INT) def unlink_llimpl(pathname): l_pathname = rffi.str2charp(pathname) @@ -699,12 +679,7 @@ @registering(os.chdir) def register_os_chdir(self): - if sys.platform.startswith('win'): - INCLUDES = [] - else: - INCLUDES = ['unistd.h'] - os_chdir = rffi.llexternal('chdir', [rffi.CCHARP], rffi.INT, - includes=INCLUDES) + os_chdir = self.llexternal('chdir', [rffi.CCHARP], rffi.INT) def chdir_llimpl(path): l_path = rffi.str2charp(path) @@ -719,15 +694,12 @@ @registering(os.mkdir) def register_os_mkdir(self): if os.name == 'nt': - INCLUDES = [] ARG2 = [] # no 'mode' argument on Windows arg2 = [] else: - INCLUDES = ['sys/stat.h', 'sys/types.h'] ARG2 = [rffi.MODE_T] arg2 = [int] - os_mkdir = rffi.llexternal('mkdir', [rffi.CCHARP]+ARG2, rffi.INT, - includes=INCLUDES) + os_mkdir = self.llexternal('mkdir', [rffi.CCHARP]+ARG2, rffi.INT) def mkdir_llimpl(pathname, *opt_mode): l_pathname = rffi.str2charp(pathname) @@ -743,12 +715,7 @@ @registering(os.rmdir) def register_os_rmdir(self): - if sys.platform.startswith('win'): - INCLUDES = [] - else: - INCLUDES = ['unistd.h'] - os_rmdir = rffi.llexternal('rmdir', [rffi.CCHARP], rffi.INT, - includes=INCLUDES) + os_rmdir = self.llexternal('rmdir', [rffi.CCHARP], rffi.INT) def rmdir_llimpl(pathname): l_pathname = rffi.str2charp(pathname) @@ -763,13 +730,10 @@ @registering(os.chmod) def register_os_chmod(self): if os.name == 'nt': - INCLUDES = [] MODE_T = rffi.INT else: - INCLUDES = ['sys/stat.h', 'sys/types.h'] MODE_T = rffi.MODE_T - os_chmod = rffi.llexternal('chmod', [rffi.CCHARP, MODE_T], rffi.INT, - includes=INCLUDES) + os_chmod = self.llexternal('chmod', [rffi.CCHARP, MODE_T], rffi.INT) def chmod_llimpl(path, mode): l_path = rffi.str2charp(path) @@ -783,7 +747,7 @@ @registering(os.rename) def register_os_rename(self): - os_rename = rffi.llexternal('rename', [rffi.CCHARP, rffi.CCHARP], + os_rename = self.llexternal('rename', [rffi.CCHARP, rffi.CCHARP], rffi.INT) def rename_llimpl(oldpath, newpath): @@ -804,7 +768,7 @@ mode_t = rffi.INT else: mode_t = rffi.MODE_T - os_umask = rffi.llexternal('umask', [mode_t], mode_t) + os_umask = self.llexternal('umask', [mode_t], mode_t) def umask_llimpl(fd): res = os_umask(rffi.cast(mode_t, fd)) @@ -815,9 +779,8 @@ @registering_if(os, 'kill') def register_os_kill(self): - os_kill = rffi.llexternal('kill', [rffi.PID_T, rffi.INT], - rffi.INT, - includes=['sys/types.h', 'signal.h']) + os_kill = self.llexternal('kill', [rffi.PID_T, rffi.INT], + rffi.INT) def kill_llimpl(pid, sig): res = os_kill(rffi.cast(rffi.PID_T, pid), @@ -830,9 +793,8 @@ @registering_if(os, 'link') def register_os_link(self): - os_link = rffi.llexternal('link', [rffi.CCHARP, rffi.CCHARP], - rffi.INT, - includes = ['unistd.h']) + os_link = self.llexternal('link', [rffi.CCHARP, rffi.CCHARP], + rffi.INT) def link_llimpl(oldpath, newpath): l_oldpath = rffi.str2charp(oldpath) @@ -848,9 +810,8 @@ @registering_if(os, 'symlink') def register_os_symlink(self): - os_symlink = rffi.llexternal('symlink', [rffi.CCHARP, rffi.CCHARP], - rffi.INT, - includes = ['unistd.h']) + os_symlink = self.llexternal('symlink', [rffi.CCHARP, rffi.CCHARP], + rffi.INT) def symlink_llimpl(oldpath, newpath): l_oldpath = rffi.str2charp(oldpath) @@ -866,8 +827,7 @@ @registering_if(os, 'fork') def register_os_fork(self): - os_fork = rffi.llexternal('fork', [], rffi.PID_T, - includes = ['sys/types.h', 'unistd.h']) + os_fork = self.llexternal('fork', [], rffi.PID_T) def fork_llimpl(): childpid = os_fork() @@ -880,7 +840,7 @@ @registering(os._exit) def register_os__exit(self): - os__exit = rffi.llexternal('_exit', [rffi.INT], lltype.Void) + os__exit = self.llexternal('_exit', [rffi.INT], lltype.Void) def _exit_llimpl(status): os__exit(rffi.cast(rffi.INT, status)) @@ -921,9 +881,8 @@ return int(getattr(os, name)(status)) fake.func_name = 'fake_' + name - os_c_func = rffi.llexternal(name, [lltype.Signed], - lltype.Signed, _callable=fake, - includes=["sys/wait.h", "sys/types.h"]) + os_c_func = self.llexternal(name, [lltype.Signed], + lltype.Signed, _callable=fake) if name in self.w_star_returning_int: def llimpl(status): @@ -943,7 +902,7 @@ @registering_if(os, 'ttyname') def register_os_ttyname(self): - os_ttyname = rffi.llexternal('ttyname', [lltype.Signed], rffi.CCHARP) + os_ttyname = self.llexternal('ttyname', [lltype.Signed], rffi.CCHARP) def ttyname_llimpl(fd): l_name = os_ttyname(fd) From fijal at codespeak.net Thu Aug 30 12:25:08 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 12:25:08 +0200 (CEST) Subject: [pypy-svn] r46186 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem Message-ID: <20070830102508.1809481D3@code0.codespeak.net> Author: fijal Date: Thu Aug 30 12:25:07 2007 New Revision: 46186 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Log: "typo" Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py Thu Aug 30 12:25:07 2007 @@ -73,7 +73,7 @@ if tp is CCHARP: to_free = to_free + (ll_str,) else: - to_free = to_free = (None,) + to_free = to_free + (None,) result = funcptr(*real_args) if stringpolicy == 'fullauto': for i, tp in unrolling_arg_tps: From fijal at codespeak.net Thu Aug 30 12:31:53 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 12:31:53 +0200 (CEST) Subject: [pypy-svn] r46187 - pypy/branch/pypy-more-rtti-inprogress/rpython Message-ID: <20070830103153.ACF3181E8@code0.codespeak.net> Author: fijal Date: Thu Aug 30 12:31:52 2007 New Revision: 46187 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Log: * Have a default stringpolicy (eventually) * always copy kwds Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py Thu Aug 30 12:31:52 2007 @@ -104,6 +104,7 @@ self.__dict__.update(platform.configure(CConfig)) def llexternal(self, *args, **kwds): + kwds = kwds.copy() from pypy.rpython.lltypesystem import rffi for item in self.__ATTRIBUTES: @@ -111,6 +112,9 @@ kwds[item] = getattr(self, '_%s_' % item, []) else: kwds[item] += getattr(self, '_%s_' % item, []) + stringpolicy = getattr(self, '_stringpolicy_', None) + if stringpolicy and 'stringpolicy' not in kwds: + kwds['stringpolicy'] = stringpolicy return rffi.llexternal(*args, **kwds) class genericcallable(object): From fijal at codespeak.net Thu Aug 30 12:36:39 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 12:36:39 +0200 (CEST) Subject: [pypy-svn] r46188 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070830103639.88C0E81E3@code0.codespeak.net> Author: fijal Date: Thu Aug 30 12:36:38 2007 New Revision: 46188 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Log: Use more cool helpers Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 30 12:36:38 2007 @@ -51,6 +51,8 @@ class RegisterOs(BaseLazyRegistering): + _stringpolicy_ = 'fullauto' + def __init__(self): self.configure(CConfig) @@ -73,11 +75,9 @@ rffi.INT) def execv_llimpl(path, args): - l_path = rffi.str2charp(path) l_args = rffi.liststr2charpp(args) - os_execv(l_path, l_args) + os_execv(path, l_args) rffi.free_charpp(l_args) - rffi.free_charp(l_path) raise OSError(rffi.get_errno(), "execv failed") return extdef([str, [str]], s_ImpossibleValue, llimpl=execv_llimpl, @@ -91,11 +91,9 @@ def spawnv_llimpl(mode, path, args): mode = rffi.cast(rffi.INT, mode) - l_path = rffi.str2charp(path) l_args = rffi.liststr2charpp(args) childpid = os_spawnv(mode, l_path, l_args) rffi.free_charpp(l_args) - rffi.free_charp(l_path) if childpid == -1: raise OSError(rffi.get_errno(), "os_spawnv failed") return rffi.cast(lltype.Signed, childpid) @@ -144,7 +142,6 @@ # NB. this function is specialized; we get one version where # tp is known to be None, and one version where it is known # to be a tuple of 2 floats. - l_path = rffi.str2charp(path) if tp is None: l_utimebuf = lltype.nullptr(UTIMEBUFP.TO) else: @@ -155,7 +152,6 @@ error = rffi.cast(lltype.Signed, os_utime(l_path, l_utimebuf)) if tp is not None: lltype.free(l_utimebuf, flavor='raw') - rffi.free_charp(l_path) if error == -1: raise OSError(rffi.get_errno(), "os_utime failed") os_utime_llimpl._annspecialcase_ = 'specialize:argtype(1)' @@ -290,11 +286,7 @@ rffi.INT) def os_open_llimpl(path, flags, mode): - l_path = rffi.str2charp(path) - result = rffi.cast(lltype.Signed, os_open(l_path, - rffi.cast(rffi.INT, flags), - rffi.cast(mode_t, mode))) - rffi.free_charp(l_path) + result = os_open(path, flags, mode) if result == -1: raise OSError(rffi.get_errno(), "os_open failed") return result @@ -436,15 +428,11 @@ @registering(os.access) def register_os_access(self): - os_access = self.llexternal('access', - [rffi.CCHARP, rffi.INT], + os_access = self.llexternal('access', [rffi.CCHARP, rffi.INT], rffi.INT) def access_llimpl(path, mode): - path = rffi.str2charp(path) - mode = rffi.cast(rffi.INT, mode) - error = rffi.cast(lltype.Signed, os_access(path, mode)) - rffi.free_charp(path) + error = os_access(path, mode) return error == 0 def os_access_oofakeimpl(path, mode): @@ -458,7 +446,7 @@ def register_os_getcwd(self): os_getcwd = self.llexternal('getcwd', [rffi.CCHARP, rffi.SIZE_T], - rffi.CCHARP) + rffi.CCHARP, stringpolicy='noauto') def os_getcwd_llimpl(): bufsize = 256 @@ -503,9 +491,7 @@ os_closedir = self.llexternal('closedir', [DIRP], rffi.INT) def os_listdir_llimpl(path): - path = rffi.str2charp(path) dirp = os_opendir(path) - rffi.free_charp(path) if not dirp: raise OSError(rffi.get_errno(), "os_opendir failed") rffi.set_errno(0) @@ -556,34 +542,29 @@ def register_os_readlink(self): os_readlink = self.llexternal('readlink', [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], - rffi.INT) # XXX SSIZE_T in POSIX.1-2001 + rffi.INT) + # XXX SSIZE_T in POSIX.1-2001 def os_readlink_llimpl(path): - l_path = rffi.str2charp(path) - try: - bufsize = 1023 - while True: - buf = lltype.malloc(rffi.CCHARP.TO, bufsize, - flavor='raw') - res = os_readlink(l_path, buf, - rffi.cast(rffi.SIZE_T, bufsize)) - if res < 0: - error = rffi.get_errno() # failed - lltype.free(buf, flavor='raw') - raise OSError(error, "readlink failed") - elif res < bufsize: - break # ok - else: - # buf too small, try again with a larger buffer - lltype.free(buf, flavor='raw') - bufsize *= 4 - # convert the result to a string - res = rffi.cast(lltype.Signed, res) - l = [buf[i] for i in range(res)] - result = ''.join(l) - lltype.free(buf, flavor='raw') - finally: - rffi.free_charp(l_path) + bufsize = 1023 + while True: + buf = lltype.malloc(rffi.CCHARP.TO, bufsize, + flavor='raw') + res = os_readlink(path, buf, bufsize) + if res < 0: + error = rffi.get_errno() # failed + lltype.free(buf, flavor='raw') + raise OSError(error, "readlink failed") + elif res < bufsize: + break # ok + else: + # buf too small, try again with a larger buffer + lltype.free(buf, flavor='raw') + bufsize *= 4 + # convert the result to a string + l = [buf[i] for i in range(res)] + result = ''.join(l) + lltype.free(buf, flavor='raw') return result return extdef([str], str, @@ -655,9 +636,7 @@ os_system = self.llexternal('system', [rffi.CCHARP], rffi.INT) def system_llimpl(command): - l_command = rffi.str2charp(command) - res = os_system(l_command) - rffi.free_charp(l_command) + res = os_system(command) return res return extdef([str], int, llimpl=system_llimpl, @@ -668,9 +647,7 @@ os_unlink = self.llexternal('unlink', [rffi.CCHARP], rffi.INT) def unlink_llimpl(pathname): - l_pathname = rffi.str2charp(pathname) - res = os_unlink(l_pathname) - rffi.free_charp(l_pathname) + res = os_unlink(pathname) if res < 0: raise OSError(rffi.get_errno(), "os_unlink failed") @@ -682,9 +659,7 @@ os_chdir = self.llexternal('chdir', [rffi.CCHARP], rffi.INT) def chdir_llimpl(path): - l_path = rffi.str2charp(path) - res = os_chdir(l_path) - rffi.free_charp(l_path) + res = os_chdir(path) if res < 0: raise OSError(rffi.get_errno(), "os_chdir failed") @@ -702,11 +677,9 @@ os_mkdir = self.llexternal('mkdir', [rffi.CCHARP]+ARG2, rffi.INT) def mkdir_llimpl(pathname, *opt_mode): - l_pathname = rffi.str2charp(pathname) if opt_mode: - opt_mode = (rffi.cast(rffi.MODE_T, opt_mode[0]),) - res = os_mkdir(l_pathname, *opt_mode) - rffi.free_charp(l_pathname) + opt_mode = opt_mode[0] + res = os_mkdir(pathname, *opt_mode) if res < 0: raise OSError(rffi.get_errno(), "os_mkdir failed") @@ -718,9 +691,7 @@ os_rmdir = self.llexternal('rmdir', [rffi.CCHARP], rffi.INT) def rmdir_llimpl(pathname): - l_pathname = rffi.str2charp(pathname) - res = os_rmdir(l_pathname) - rffi.free_charp(l_pathname) + res = os_rmdir(pathname) if res < 0: raise OSError(rffi.get_errno(), "os_rmdir failed") @@ -736,9 +707,7 @@ os_chmod = self.llexternal('chmod', [rffi.CCHARP, MODE_T], rffi.INT) def chmod_llimpl(path, mode): - l_path = rffi.str2charp(path) - res = os_chmod(l_path, rffi.cast(MODE_T, mode)) - rffi.free_charp(l_path) + res = os_chmod(path, rffi.cast(MODE_T, mode)) if res < 0: raise OSError(rffi.get_errno(), "os_chmod failed") @@ -751,11 +720,7 @@ rffi.INT) def rename_llimpl(oldpath, newpath): - l_oldpath = rffi.str2charp(oldpath) - l_newpath = rffi.str2charp(newpath) - res = os_rename(l_oldpath, l_newpath) - rffi.free_charp(l_newpath) - rffi.free_charp(l_oldpath) + res = os_rename(oldpath, newpath) if res < 0: raise OSError(rffi.get_errno(), "os_rename failed") @@ -797,11 +762,7 @@ rffi.INT) def link_llimpl(oldpath, newpath): - l_oldpath = rffi.str2charp(oldpath) - l_newpath = rffi.str2charp(newpath) - res = os_link(l_oldpath, l_newpath) - rffi.free_charp(l_newpath) - rffi.free_charp(l_oldpath) + res = os_link(oldpath, newpath) if res < 0: raise OSError(rffi.get_errno(), "os_link failed") @@ -814,11 +775,7 @@ rffi.INT) def symlink_llimpl(oldpath, newpath): - l_oldpath = rffi.str2charp(oldpath) - l_newpath = rffi.str2charp(newpath) - res = os_symlink(l_oldpath, l_newpath) - rffi.free_charp(l_newpath) - rffi.free_charp(l_oldpath) + res = os_symlink(oldpath, newpath) if res < 0: raise OSError(rffi.get_errno(), "os_symlink failed") From fijal at codespeak.net Thu Aug 30 12:40:08 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 12:40:08 +0200 (CEST) Subject: [pypy-svn] r46189 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070830104008.8737A81E3@code0.codespeak.net> Author: fijal Date: Thu Aug 30 12:40:07 2007 New Revision: 46189 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Log: use cool helpers here as well Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Thu Aug 30 12:40:07 2007 @@ -11,12 +11,10 @@ class CConfig: if sys.platform.startswith('win'): - includes = ['time.h', 'windows.h'] + _includes_ = ['time.h', 'windows.h'] else: - includes = ['sys/time.h', 'time.h', 'errno.h', 'sys/select.h', - 'sys/types.h', 'unistd.h', 'sys/timeb.h'] - # XXX argh, argh, argh, should be automatic - _header_ = "\n".join(["#include <%s>" % name for name in includes]) + _includes_ = ['sys/time.h', 'time.h', 'errno.h', 'sys/select.h', + 'sys/types.h', 'unistd.h', 'sys/timeb.h'] CLOCK_T = platform.SimpleType('clock_t', rffi.INT) TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.INT), @@ -24,6 +22,8 @@ TIMEB = platform.Struct('struct timeb', [('time', rffi.INT), ('millitm', rffi.INT)]) TIME_T = platform.SimpleType('time_t', rffi.INT) + HAVE_GETTIMEOFDAY = platform.Has('gettimeofday') + HAVE_FTIME = platform.Has('ftime') constant_names = ['CLOCKS_PER_SEC', 'CLK_TCK', 'EINTR'] for const in constant_names: @@ -40,13 +40,8 @@ self.CLOCKS_PER_SEC = 1000000 else: self.CLOCKS_PER_SEC = self.CLK_TCK - # XXX another to-be-automated issue - self.includes = CConfig.includes self.TIMEVALP = lltype.Ptr(self.TIMEVAL) self.TIMEBP = lltype.Ptr(self.TIMEB) - self.HAVE_GETTIMEOFDAY = rffi.platform.has('gettimeofday', - includes=self.includes) - self.HAVE_FTIME = rffi.platform.has('ftime', includes=self.includes) @registering(time.time) def register_time_time(self): @@ -56,24 +51,20 @@ # AWFUL if self.HAVE_GETTIMEOFDAY: if self.GETTIMEOFDAY_NO_TZ: - c_gettimeofday = rffi.llexternal('gettimeofday', - [self.TIMEVALP], rffi.INT, - includes=self.includes) + c_gettimeofday = self.llexternal('gettimeofday', + [self.TIMEVALP], rffi.INT) else: - c_gettimeofday = rffi.llexternal('gettimeofday', - [self.TIMEVALP, rffi.VOIDP], rffi.INT, - includes=self.includes) + c_gettimeofday = self.llexternal('gettimeofday', + [self.TIMEVALP, rffi.VOIDP], rffi.INT) else: c_gettimeofday = None if self.HAVE_FTIME: - c_ftime = rffi.llexternal('ftime', [self.TIMEBP], lltype.Void, - includes=self.includes) + c_ftime = self.llexternal('ftime', [self.TIMEBP], lltype.Void) else: c_ftime = None # not to confuse flow objspace - c_time = rffi.llexternal('time', [rffi.VOIDP], self.TIME_T, - includes=self.includes) + c_time = self.llexternal('time', [rffi.VOIDP], self.TIME_T) def time_time_llimpl(): void = lltype.nullptr(rffi.VOIDP.TO) @@ -105,8 +96,7 @@ @registering(time.clock) def register_time_clock(self): - c_clock = rffi.llexternal('clock', [], self.CLOCK_T, - includes=self.includes) + c_clock = self.llexternal('clock', [], self.CLOCK_T) if sys.platform == 'win32': xxx @@ -123,10 +113,9 @@ if sys.platform == 'win32': xxx else: - c_select = rffi.llexternal('select', [rffi.INT, rffi.VOIDP, + c_select = self.llexternal('select', [rffi.INT, rffi.VOIDP, rffi.VOIDP, rffi.VOIDP, - self.TIMEVALP], - rffi.INT, includes=self.includes) + self.TIMEVALP], rffi.INT) def time_sleep_llimpl(secs): # XXX cannot put it into try: finally: because From fijal at codespeak.net Thu Aug 30 14:36:55 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 14:36:55 +0200 (CEST) Subject: [pypy-svn] r46192 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test Message-ID: <20070830123655.6CF9681C8@code0.codespeak.net> Author: fijal Date: Thu Aug 30 14:36:51 2007 New Revision: 46192 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py Log: Add a broken test to showcase recursive struct problem (help!) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py Thu Aug 30 14:36:51 2007 @@ -404,3 +404,12 @@ assert s1ac.contents.x == 59 assert s.s1a.x == 59 lltype.free(s, flavor='raw') + + def test_recursive_struct(self): + # XXX sucky way of creating those + py.test.skip("HELP! I don't know how to make this work") + SX = lltype.Struct('y') + S1 = lltype.Struct('S1', ('x', lltype.Ptr(SX))) + S1._flds['x'] = lltype.Ptr(S1) + s = lltype.malloc(S1, flavor='raw') + sc = lltype2ctypes(s) From fijal at codespeak.net Thu Aug 30 14:39:50 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 14:39:50 +0200 (CEST) Subject: [pypy-svn] r46193 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070830123950.02A6281DF@code0.codespeak.net> Author: fijal Date: Thu Aug 30 14:39:49 2007 New Revision: 46193 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Log: Fix translation Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py Thu Aug 30 14:39:49 2007 @@ -149,7 +149,7 @@ actime, modtime = tp l_utimebuf.c_actime = int(actime) l_utimebuf.c_modtime = int(modtime) - error = rffi.cast(lltype.Signed, os_utime(l_path, l_utimebuf)) + error = os_utime(path, l_utimebuf) if tp is not None: lltype.free(l_utimebuf, flavor='raw') if error == -1: @@ -542,15 +542,17 @@ def register_os_readlink(self): os_readlink = self.llexternal('readlink', [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], - rffi.INT) + rffi.INT, stringpolicy='noauto') # XXX SSIZE_T in POSIX.1-2001 def os_readlink_llimpl(path): bufsize = 1023 while True: + l_path = rffi.str2charp(path) buf = lltype.malloc(rffi.CCHARP.TO, bufsize, flavor='raw') - res = os_readlink(path, buf, bufsize) + res = os_readlink(l_path, buf, bufsize) + lltype.free(l_path, flavor='raw') if res < 0: error = rffi.get_errno() # failed lltype.free(buf, flavor='raw') @@ -678,7 +680,7 @@ def mkdir_llimpl(pathname, *opt_mode): if opt_mode: - opt_mode = opt_mode[0] + opt_mode = (opt_mode[0],) res = os_mkdir(pathname, *opt_mode) if res < 0: raise OSError(rffi.get_errno(), "os_mkdir failed") From antocuni at codespeak.net Thu Aug 30 15:46:50 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 30 Aug 2007 15:46:50 +0200 (CEST) Subject: [pypy-svn] r46195 - in pypy/dist/pypy: rpython/test translator/jvm translator/jvm/src/pypy translator/jvm/test Message-ID: <20070830134650.7314B80C5@code0.codespeak.net> Author: antocuni Date: Thu Aug 30 15:46:47 2007 New Revision: 46195 Modified: pypy/dist/pypy/rpython/test/test_rfloat.py pypy/dist/pypy/translator/jvm/generator.py pypy/dist/pypy/translator/jvm/opcodes.py pypy/dist/pypy/translator/jvm/prebuiltnodes.py pypy/dist/pypy/translator/jvm/src/pypy/Interlink.java pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java pypy/dist/pypy/translator/jvm/test/runtest.py pypy/dist/pypy/translator/jvm/test/test_float.py pypy/dist/pypy/translator/jvm/test/test_int.py Log: make all the float tests passing on genjvm Modified: pypy/dist/pypy/rpython/test/test_rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rfloat.py (original) +++ pypy/dist/pypy/rpython/test/test_rfloat.py Thu Aug 30 15:46:47 2007 @@ -90,9 +90,9 @@ return float(r_uint(n)) / 2 res = self.interpret(fn, [41]) - assert res == 20.5 + assert self.float_eq(res, 20.5) res = self.interpret(fn, [-9]) - assert res == 0.5 * ((sys.maxint+1)*2 - 9) + assert self.float_eq(res, 0.5 * ((sys.maxint+1)*2 - 9)) def test_float_constant_conversions(self): DIV = r_longlong(10 ** 10) @@ -100,7 +100,7 @@ return 420000000000.0 / DIV res = self.interpret(fn, []) - assert res == 42.0 + assert self.float_eq(res, 42.0) def test_pow(self): def fn(x, y): Modified: pypy/dist/pypy/translator/jvm/generator.py ============================================================================== --- pypy/dist/pypy/translator/jvm/generator.py (original) +++ pypy/dist/pypy/translator/jvm/generator.py Thu Aug 30 15:46:47 2007 @@ -416,6 +416,7 @@ PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject) PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray) PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList) +PYPYOOPARSEFLOAT = Method.s(jPyPy, 'ooparse_float', (jString,), jDouble) OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass) CLASSGETNAME = Method.v(jClass, 'getName', (), jString) CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make', Modified: pypy/dist/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/opcodes.py (original) +++ pypy/dist/pypy/translator/jvm/opcodes.py Thu Aug 30 15:46:47 2007 @@ -54,7 +54,7 @@ 'oohash': [PushAllArgs, jvmgen.OBJHASHCODE, StoreResult], 'oostring': [OOString, StoreResult], #'ooparse_int': [PushAllArgs, 'call int32 [pypylib]pypy.runtime.Utils::OOParseInt(string, int32)'], - #'ooparse_float': [PushAllArgs, 'call float64 [pypylib]pypy.runtime.Utils::OOParseFloat(string)'], + 'ooparse_float': jvmgen.PYPYOOPARSEFLOAT, 'oonewcustomdict': [NewCustomDict, StoreResult], # 'same_as': DoNothing, Modified: pypy/dist/pypy/translator/jvm/prebuiltnodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/prebuiltnodes.py (original) +++ pypy/dist/pypy/translator/jvm/prebuiltnodes.py Thu Aug 30 15:46:47 2007 @@ -11,6 +11,9 @@ def throwOverflowError(): raise OverflowError +def throwValueError(): + raise ValueError + # ___________________________________________________________________________ def create_interlink_node(db): Modified: pypy/dist/pypy/translator/jvm/src/pypy/Interlink.java ============================================================================== --- pypy/dist/pypy/translator/jvm/src/pypy/Interlink.java (original) +++ pypy/dist/pypy/translator/jvm/src/pypy/Interlink.java Thu Aug 30 15:46:47 2007 @@ -13,4 +13,5 @@ public void throwZeroDivisionError(); public void throwIndexError(); public void throwOverflowError(); + public void throwValueError(); } 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 Thu Aug 30 15:46:47 2007 @@ -103,10 +103,9 @@ if (value >= 0) return value; else { - int loword = value & 0xFFFF; - double result = loword; - int hiword = value >>> 16; - result += hiword * BITS16; + long loword = value & 0xFFFF; + long hiword = value >>> 16; + double result = (hiword << 16) | loword; return result; } } @@ -115,11 +114,10 @@ if (value <= Integer.MAX_VALUE) return (int)value; - int loword = (int)(value % BITS16); - int hiword = (int)(Math.floor(value / BITS16)); - assert (loword & 0xFFFF0000) == 0; - assert (hiword & 0xFFFF0000) == 0; - return (hiword << 16) + loword; + long v = (long)value; + int loword = (int)(v & 0xFFFF); + int hiword = (int)(v >>> 16); + return (hiword << 16) | loword; } public static long double_to_long(double value) @@ -193,6 +191,15 @@ } } + public static double ooparse_float(String s) { + try { + return Double.parseDouble(s); + } catch(NumberFormatException ex) { + interlink.throwValueError(); + return 0.0; // not reached + } + } + public static char str_to_char(String s) { if (s.length() != 1) throw new RuntimeException("String not single character: '"+s+"'"); @@ -222,9 +229,9 @@ if (i >= 0) return Integer.toString(i); else { - int loword = i & 0xFFFF; - int hiword = i >>> 16; - long res = loword + (hiword*0xFFFF); + long loword = i & 0xFFFF; + long hiword = i >>> 16; + long res = (hiword << 16) | loword; return Long.toString(res); } } @@ -842,6 +849,10 @@ public static void throwOverflowError() { interlink.throwOverflowError(); } + + public static void throwValueError() { + interlink.throwValueError(); + } // ---------------------------------------------------------------------- // Self Test Modified: pypy/dist/pypy/translator/jvm/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/runtest.py (original) +++ pypy/dist/pypy/translator/jvm/test/runtest.py Thu Aug 30 15:46:47 2007 @@ -13,7 +13,7 @@ generate_source_for_function, JvmError, detect_missing_support_programs from pypy.translator.jvm.option import getoption -FLOAT_PRECISION = 8 +FLOAT_PRECISION = 5 class StructTuple(tuple): def __getattr__(self, name): @@ -128,6 +128,9 @@ def float_eq(self, x, y): return round(x, FLOAT_PRECISION) == round(y, FLOAT_PRECISION) + def is_of_type(self, x, type_): + return True # we can't really test the type + def ll_to_string(self, s): return s Modified: pypy/dist/pypy/translator/jvm/test/test_float.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_float.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_float.py Thu Aug 30 15:46:47 2007 @@ -2,44 +2,20 @@ from pypy.translator.jvm.test.runtest import JvmTest from pypy.rpython.test.test_rfloat import BaseTestRfloat +# ====> ../../../rpython/test/test_rfloat.py + class TestJvmFloat(JvmTest, BaseTestRfloat): - def test_parse_float(self): - py.test.skip("JVM backend unknown opcode ooparse_float with ll_str_0") -# ex = ['', ' ', '0', '1', '-1.5', '1.5E2', '2.5e-1', ' 0 ', '?'] -# def fn(i): -# s = ex[i] -# try: -# return float(s) -# except ValueError: -# return -999.0 -# -# for i in range(len(ex)): -# expected = fn(i) -# res = self.interpret(fn, [i]) -# assert res == expected - - #Works, answer is correct, but not of type r_longlong. - def test_longlong_conversion(self): - py.test.skip("JVM backend unknown opcode cast_float_to_longlong") - - def test_float_constant_conversions(self): - py.test.skip("JVM backend lacks appropriate percision; 42.000000614400001 == 42.0") - - #The JVM doesn't even have uints, these numbers are totally off, I need to see if it's the way they - # are being rendered to standard out and parsed. see http://rafb.net/p/hsaV4b55.html for more info. - # Also, look below at the test_r_uint. - def test_from_r_uint(self): - py.test.skip("JVM backend lacks appropriate percision") - - #The jvm doesn't even have uints, these numbers are totally off - def test_to_r_uint(self): - py.test.skip("JVM backend lacks appropriate percision") - - def test_r_uint(self): - py.test.skip("This illustrates the issue with parsing and handling of uints") - #import sys - #from pypy.rlib.rarithmetic import r_uint - #def ident(i): return i - #res = self.interpret(ident, [r_uint(sys.maxint + 1)]) - #assert res == sys.maxint+1 + def test_parse_float(self): + ex = ['', ' ', '0', '1', '-1.5', '1.5E2', '2.5e-1', ' 0 ', '?'] + def fn(i): + s = ex[i] + try: + return float(s) + except ValueError: + return -999.0 + + for i in range(len(ex)): + expected = fn(i) + res = self.interpret(fn, [i]) + assert res == expected Modified: pypy/dist/pypy/translator/jvm/test/test_int.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_int.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_int.py Thu Aug 30 15:46:47 2007 @@ -10,9 +10,6 @@ return chr(i) res = self.interpret(dummyfn, [ord(' ')]) assert res == ' ' - # Is the following test supported by JVM? -## res = self.interpret(dummyfn, [0]) -## assert res == '\0' res = self.interpret(dummyfn, [ord('a')]) assert res == 'a' From fijal at codespeak.net Thu Aug 30 15:53:35 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 15:53:35 +0200 (CEST) Subject: [pypy-svn] r46196 - pypy/branch/pypy-more-rtti-inprogress/rpython/module Message-ID: <20070830135335.87E8C80C5@code0.codespeak.net> Author: fijal Date: Thu Aug 30 15:53:34 2007 New Revision: 46196 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Log: "Typo" Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_time.py Thu Aug 30 15:53:34 2007 @@ -34,7 +34,7 @@ class RegisterTime(BaseLazyRegistering): def __init__(self): - self.__dict__.update(platform.configure(CConfig)) + self.configure(CConfig) if self.CLOCKS_PER_SEC is None: if self.CLK_TCK is None: self.CLOCKS_PER_SEC = 1000000 From fijal at codespeak.net Thu Aug 30 16:05:50 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 16:05:50 +0200 (CEST) Subject: [pypy-svn] r46197 - pypy/branch/pypy-more-rtti-inprogress/module/posix/test Message-ID: <20070830140550.C228981EA@code0.codespeak.net> Author: fijal Date: Thu Aug 30 16:05:49 2007 New Revision: 46197 Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py Log: Damn. Make this check anything. Thanks xoraxax Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/module/posix/test/test_posix2.py Thu Aug 30 16:05:49 2007 @@ -270,8 +270,8 @@ def test_os_getuid(self): os = self.posix - os.getuid() == self.getuid - os.geteuid() == self.geteuid + assert os.getuid() == self.getuid + assert os.geteuid() == self.geteuid def test_largefile(self): os = self.posix From fijal at codespeak.net Thu Aug 30 16:10:36 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 16:10:36 +0200 (CEST) Subject: [pypy-svn] r46198 - in pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem: . test Message-ID: <20070830141036.003EA81EB@code0.codespeak.net> Author: fijal Date: Thu Aug 30 16:10:36 2007 New Revision: 46198 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py Log: A test and a fix for recursive types (test probably should check for sth else as well...) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py Thu Aug 30 16:10:36 2007 @@ -43,6 +43,8 @@ FIELDTYPE = S._flds[fieldname] if max_n is not None and fieldname == S._arrayfld: cls = build_ctypes_array(FIELDTYPE, max_n) + elif isinstance(FIELDTYPE, lltype.Ptr) and FIELDTYPE.TO is S: + cls = ctypes.POINTER(S._name) else: cls = get_ctypes_type(FIELDTYPE) fields.append((fieldname, cls)) Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py Thu Aug 30 16:10:36 2007 @@ -407,9 +407,8 @@ def test_recursive_struct(self): # XXX sucky way of creating those - py.test.skip("HELP! I don't know how to make this work") - SX = lltype.Struct('y') + SX = lltype.ForwardReference() S1 = lltype.Struct('S1', ('x', lltype.Ptr(SX))) - S1._flds['x'] = lltype.Ptr(S1) + S1._flds['x'].TO.become(S1) s = lltype.malloc(S1, flavor='raw') sc = lltype2ctypes(s) From fijal at codespeak.net Thu Aug 30 17:00:17 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 30 Aug 2007 17:00:17 +0200 (CEST) Subject: [pypy-svn] r46199 - pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test Message-ID: <20070830150017.C1A1481E8@code0.codespeak.net> Author: fijal Date: Thu Aug 30 17:00:16 2007 New Revision: 46199 Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py Log: don't use _flds of struct directly Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/test/test_ll2ctypes.py Thu Aug 30 17:00:16 2007 @@ -409,6 +409,6 @@ # XXX sucky way of creating those SX = lltype.ForwardReference() S1 = lltype.Struct('S1', ('x', lltype.Ptr(SX))) - S1._flds['x'].TO.become(S1) + S1.x.TO.become(S1) s = lltype.malloc(S1, flavor='raw') sc = lltype2ctypes(s) From simonb at codespeak.net Thu Aug 30 21:35:43 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Thu, 30 Aug 2007 21:35:43 +0200 (CEST) Subject: [pypy-svn] r46200 - pypy/dist/pypy/rpython/numpy/test Message-ID: <20070830193543.A5CFE81F8@code0.codespeak.net> Author: simonb Date: Thu Aug 30 21:35:42 2007 New Revision: 46200 Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py Log: check for malloc removal Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Thu Aug 30 21:35:42 2007 @@ -8,7 +8,7 @@ from pypy.annotation.model import SomeObject, SomeTuple from pypy.annotation.annrpython import RPythonAnnotator from pypy.tool.error import AnnotatorError -from pypy.translator.translator import TranslationContext +from pypy.translator.translator import TranslationContext, graphof from pypy import conftest import sys from pypy.rpython.test.test_llinterp import interpret @@ -160,7 +160,8 @@ s = a.build_types(f, []) assert type(s) == SomeArray - +from pypy.objspace.flow.model import checkgraph, flatten, Block, mkentrymap +from pypy.translator.backendopt.malloc import LLTypeMallocRemover class Test_specialization: def test_specialize_array_create(self): @@ -247,7 +248,6 @@ b = numpy.array([5,55,555]) a[:] = b return a - #self.specialize_view(f) res = interpret(f, []) assert res.data[0] == 5 assert res.data[1] == 55 @@ -260,21 +260,29 @@ r = t.buildrtyper() r.specialize() from pypy.translator.backendopt.all import backend_optimizations - backend_optimizations(t, inline=True) + backend_optimizations(t) t.view() -#from pypy.rlib.unroll import unrolling_iterable, unrolling_zero -#unroller = unrolling_iterable((1,2,3)) -#def deep_f(result, i): -# result += 1 -# if i<5: -# result *= deep_f(result, i+1) -# return result -# -#def deep_unroll(): -## i = unrolling_zero -# i = 0 -# return deep_f(0, i) + def test_malloc_remove(self): + def f(): + a = numpy.zeros((3,), dtype='i') + b = numpy.array([5,55,555]) + a[:] = b + return a + t = TranslationContext() + a = t.buildannotator() + a = a.build_types(f, []) + r = t.buildrtyper() + r.specialize() + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(t) + from pypy.rpython.numpy.rarray import ll_setitem_from_array + graph = graphof(t, ll_setitem_from_array) + #graph.show() + from pypy.translator.backendopt.test.test_malloc import TestLLTypeMallocRemoval + TestLLTypeMallocRemoval.check_malloc_removed(graph) + + class Test_compile: def setup_class(self): @@ -286,13 +294,16 @@ def test_compile_array_access(self): def access_array(index): - a = numpy.array([3,99,2]) + a = numpy.zeros((3,), dtype='i') + b = numpy.array([5,55,555]) + a[:] = b a[0] = 1 return a[index] fn = self.compile(access_array, [int]) assert fn(0) == 1 - assert fn(1) == 99 + assert fn(1) == 55 + assert fn(2) == 555 def test_compile_2d(self): py.test.skip() From simonb at codespeak.net Fri Aug 31 02:15:40 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Fri, 31 Aug 2007 02:15:40 +0200 (CEST) Subject: [pypy-svn] r46203 - in pypy/dist/pypy/rpython/numpy: . test Message-ID: <20070831001540.4CB2C81C3@code0.codespeak.net> Author: simonb Date: Fri Aug 31 02:15:39 2007 New Revision: 46203 Modified: pypy/dist/pypy/rpython/numpy/aarray.py pypy/dist/pypy/rpython/numpy/rarray.py pypy/dist/pypy/rpython/numpy/test/test_array.py Log: add base attr, cannot figure out how to set a struct attribute to NULL (?????) Modified: pypy/dist/pypy/rpython/numpy/aarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/aarray.py (original) +++ pypy/dist/pypy/rpython/numpy/aarray.py Fri Aug 31 02:15:39 2007 @@ -25,11 +25,15 @@ #'f' : SomeFloat(), # XX single precision float XX 'd' : SomeFloat(), } - def __init__(self, typecode, ndim=1): + def __init__(self, typecode, ndim=1, s_base=None): if not typecode in self.typecode_to_item: raise AnnotatorError("bad typecode: %r"%typecode) self.typecode = typecode self.ndim = ndim + self.s_base = s_base # we are a view into this + + def get_base_annotation(self): + return self.s_base or self def can_be_none(self): return True @@ -45,6 +49,8 @@ s = SomeTuple([SomeInteger()]*s_array.ndim) elif attr == 'ndim': s = SomeInteger() + elif attr == 'base': + s = s_array.get_base_annotation() if s is None: return SomeObject.getattr(s_array, s_attr) return s @@ -102,7 +108,7 @@ if s_array.ndim == 0 and len(s_index.items): raise AnnotatorError("indexing rank zero array with nonempty tuple") if ndim > 0: - return SomeArray(s_array.typecode, ndim) + return SomeArray(s_array.typecode, ndim, s_array.get_base_annotation()) return s_array.get_item_type() # These two up-cast the index to SomeTuple and call above. Modified: pypy/dist/pypy/rpython/numpy/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/rarray.py (original) +++ pypy/dist/pypy/rpython/numpy/rarray.py Fri Aug 31 02:15:39 2007 @@ -9,7 +9,7 @@ from pypy.rpython.rslice import AbstractSliceRepr from pypy.rpython.lltypesystem.lltype import \ GcArray, GcStruct, Signed, Ptr, Unsigned, Void, FixedSizeArray, Bool,\ - malloc, direct_arrayitems, direct_ptradd + GcForwardReference, malloc, direct_arrayitems, direct_ptradd, _cast_whatever from pypy.rpython.lltypesystem.rtuple import TupleRepr from pypy.annotation.model import SomeObject, SomeInteger from pypy.rpython.numpy.aarray import SomeArray @@ -78,12 +78,13 @@ it.dataptr = direct_arrayitems(it.ao.data) for i in unroll_ndim: it.coordinates[i] = 0 + ll_iter_reset._always_inline_ = True - def ll_iter_new(ITER, ao): + def ll_iter_new(ITER, ao, iter_reset=ll_iter_reset): it = malloc(ITER) + it.ao = ao it.nd_m1 = ndim - 1 it.size = ll_mul_list(ao.shape, ndim) - it.ao = ao #it.factors[nd-1] = 1 for i in unroll_ndim: it.dims_m1[i] = ao.shape[i]-1 @@ -91,14 +92,10 @@ it.backstrides[i] = it.strides[i] * it.dims_m1[i] #if i > 0: #it.factors[nd-i-1] = it.factors[nd]*ao.shape[nd-i] - # ll_iter_reset(it) - it.index = 0 - it.dataptr = direct_arrayitems(it.ao.data) - for i in unroll_ndim: - it.coordinates[i] = 0 + iter_reset(it) return it ll_iter_new._always_inline_ = True - + def ll_iter_next(it): it.index += 1 for i in unroll_ndim_rev: @@ -108,18 +105,23 @@ break it.coordinates[i] = 0 it.dataptr = direct_ptradd(it.dataptr, -it.backstrides[i]) - i -= 1 ll_iter_next._always_inline_ = True return ll_iter_new, ll_iter_next -def ll_setitem_from_array(iter_new0, iter_next0, ITER0, array0, - slice, - iter_new1, iter_next1, ITER1, array1): +def ll_unary_op(p0, p1, op=lambda x:x): + p0[0] = op(p1[0]) + +def ll_binary_op(p0, p1, p2, op=lambda x,y:x+y): + p0[0] = op(p1[0], p2[0]) + +def ll_array_unary_op(iter_new0, iter_next0, ITER0, array0, + iter_new1, iter_next1, ITER1, array1,): +# op=ll_unary_op): it0 = iter_new0(ITER0, array0) it1 = iter_new1(ITER1, array1) while it0.index < it0.size: - it0.dataptr[0] = it1.dataptr[0] + ll_unary_op(it0.dataptr, it1.dataptr) iter_next0(it0) iter_next1(it1) @@ -133,14 +135,17 @@ ITEMARRAY = GcArray(self.ITEM, hints={'nolength':True}) self.INDEXARRAY = FixedSizeArray(NPY_INTP, self.ndim) self.itemsize = sizeof(self.ITEM) - self.ARRAY = Ptr( - GcStruct("array", - ("data", Ptr(ITEMARRAY)), # pointer to raw data buffer - ("ndim", Signed), # number of dimensions (do we need this ?) - ("shape", self.INDEXARRAY), # size in each dimension - ("strides", self.INDEXARRAY), # elements to jump to get to the - # next element in each dimension - )) + FORWARD = GcForwardReference() + STRUCT = GcStruct("array", + ("data", Ptr(ITEMARRAY)), # pointer to raw data buffer + ("ndim", Signed), # number of dimensions + ("shape", self.INDEXARRAY), # size in each dimension + ("strides", self.INDEXARRAY), # elements to jump to get to the + # next element in each dimension + ("base", Ptr(FORWARD)), # we are a view into this array + ) + self.ARRAY = Ptr(STRUCT) + STRUCT.base.TO.become(STRUCT) self.lowleveltype = self.ARRAY self.ITER = ARRAY_ITER(self.ARRAY, self.INDEXARRAY) @@ -167,14 +172,17 @@ cname = inputconst(Void, 'ndim') return hop.llops.genop('getfield', [v_array, cname], resulttype=Signed) + def get_base(self, hop, v_array): + cname = inputconst(Void, 'base') + v_base = hop.llops.genop('getfield', [v_array, cname], resulttype=self.ARRAY) + return v_base + def get_shape(self, hop, v_array): - cname = inputconst(Void, 'shape') TUPLE = TUPLE_TYPE([Signed]*self.ndim) cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) cTUPLE = inputconst(lltype.Void, TUPLE.TO) ll_get_shape = gen_get_shape(self.ndim) return hop.llops.gendirectcall(ll_get_shape, cARRAY, cTUPLE, v_array) - return llops.genop('getfield', [v_array, cname], resulttype=TUPLE) def rtype_getattr(self, hop): s_attr = hop.args_s[1] @@ -203,6 +211,7 @@ return hop.gendirectcall(ll_add, cARRAY, v_arr1, v_arr2) +#class __extend__(pairtype(ArrayRepr, Repr)): # <------ USE THIS ?? class __extend__(pairtype(ArrayRepr, IntegerRepr)): def rtype_setitem((r_arr, r_int), hop): v_array, v_index, v_item = hop.inputargs(r_arr, Signed, r_arr.item_repr) @@ -234,8 +243,8 @@ cnew1 = hop.inputconst(Void, iter_new1) cnext1 = hop.inputconst(Void, iter_next1) # return hop.gendirectcall(ll_setitem_from_array, cnext, cITER0, v_array, v_slc, cITER1, v_item) - return hop.gendirectcall(ll_setitem_from_array, - cnew0, cnext0, cITER0, v_array, v_slc, cnew1, cnext1, cITER1, v_item) + return hop.gendirectcall(ll_array_unary_op, + cnew0, cnext0, cITER0, v_array, cnew1, cnext1, cITER1, v_item) #class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)): @@ -263,11 +272,11 @@ cARRAY = inputconst(lltype.Void, r_arr.lowleveltype.TO) return llops.gendirectcall(ll_build_from_list, cARRAY, v) +from pypy.rpython.memory.lladdress import NULL def ll_allocate(ARRAY, ndim): array = malloc(ARRAY) array.ndim = ndim - #array.shape = malloc(ARRAY.shape.TO, array.ndim) - #array.strides = malloc(ARRAY.strides.TO, array.ndim) + #array.base = NULL # how to do this ????? return array def ll_build_from_list(ARRAY, lst): @@ -286,6 +295,8 @@ def ll_build_alias(ARRAY, array): new_array = ll_allocate(ARRAY, array.ndim) new_array.data = array.data # alias data +# new_array.base = array.base or array # this is broken until we set base to NULL above + new_array.base = array for i in range(array.ndim): new_array.shape[i] = array.shape[i] new_array.strides[i] = array.strides[i] Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Fri Aug 31 02:15:39 2007 @@ -164,22 +164,33 @@ from pypy.translator.backendopt.malloc import LLTypeMallocRemover class Test_specialization: + def specialize_view(self, f, args=[], opt=False): + t = TranslationContext() + a = t.buildannotator() + a = a.build_types(f, args) + r = t.buildrtyper() + r.specialize() + if opt: + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(t) + t.view() + def test_specialize_array_create(self): - def create_array(): + def f(): a = numpy.array([1,20]) b = numpy.array(a) return b - res = interpret(create_array, []) + res = interpret(f, []) assert res.data[0] == 1 assert res.data[1] == 20 def test_specialize_array_zeros(self): - def create_array(n, m): + def f(n, m): a = numpy.zeros((n, m)) return a - res = interpret(create_array, [3, 4]) + res = interpret(f, [3, 4]) assert res.ndim == 2 def test_specialize_array_access(self): @@ -196,49 +207,58 @@ assert res == 45 def test_specialize_array_add(self): - def create_array(): + def f(): a1 = numpy.array([1.,2.]) a2 = numpy.array([6,9]) return a1 + a2 - res = interpret(create_array, []) + res = interpret(f, []) assert res.data[0] == 7 assert res.data[1] == 11 def test_specialize_array_attr(self): - def create_array(): + def f(): a = numpy.array([1,2]) return a.ndim - res = interpret(create_array, []) + res = interpret(f, []) assert res == 1 + def test_specialize_base(self): + def f(): + a = numpy.array([1,2]) + b = numpy.array(a) + return b.base is a + + res = interpret(f, []) + assert res + def test_specialize_array_attr_shape(self): - def create_array(): + def f(): a = numpy.zeros((2,3)) return list(a.shape) - res = interpret(create_array, []) + res = interpret(f, []) assert res[0] == 2 assert res[1] == 3 def test_specialize_array_strides(self): - def create_array(): + def f(): a = numpy.zeros((3,4,5)) return a - res = interpret(create_array, []) + res = interpret(f, []) assert res.strides[0] == 20 assert res.strides[1] == 5 assert res.strides[2] == 1 #assert len(res.data) == 3*4*5 # GcArray has nolength def test_specialize_array_method(self): - def create_array(): + def f(): a = numpy.array([1,2]) return a.transpose() - res = interpret(create_array, []) + res = interpret(f, []) assert res.data[0] == 1 assert res.data[1] == 2 @@ -253,16 +273,6 @@ assert res.data[1] == 55 assert res.data[2] == 555 - def specialize_view(self, f, args=[]): - t = TranslationContext() - a = t.buildannotator() - a = a.build_types(f, args) - r = t.buildrtyper() - r.specialize() - from pypy.translator.backendopt.all import backend_optimizations - backend_optimizations(t) - t.view() - def test_malloc_remove(self): def f(): a = numpy.zeros((3,), dtype='i') @@ -276,8 +286,8 @@ r.specialize() from pypy.translator.backendopt.all import backend_optimizations backend_optimizations(t) - from pypy.rpython.numpy.rarray import ll_setitem_from_array - graph = graphof(t, ll_setitem_from_array) + from pypy.rpython.numpy.rarray import ll_array_unary_op + graph = graphof(t, ll_array_unary_op) #graph.show() from pypy.translator.backendopt.test.test_malloc import TestLLTypeMallocRemoval TestLLTypeMallocRemoval.check_malloc_removed(graph) From simonb at codespeak.net Fri Aug 31 03:15:16 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Fri, 31 Aug 2007 03:15:16 +0200 (CEST) Subject: [pypy-svn] r46204 - in pypy/dist/pypy/rpython/numpy: . test Message-ID: <20070831011516.6D2DD81DB@code0.codespeak.net> Author: simonb Date: Fri Aug 31 03:15:14 2007 New Revision: 46204 Modified: pypy/dist/pypy/rpython/numpy/aarray.py pypy/dist/pypy/rpython/numpy/rarray.py pypy/dist/pypy/rpython/numpy/test/test_array.py Log: multi dimensional get/set item with integer indices Modified: pypy/dist/pypy/rpython/numpy/aarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/aarray.py (original) +++ pypy/dist/pypy/rpython/numpy/aarray.py Fri Aug 31 03:15:14 2007 @@ -181,9 +181,9 @@ return v_result -class ZeroesCallEntry(ExtRegistryEntry): - "Annotation and rtyping of calls to numpy.zeroes" - _about_ = numpy.zeros +class EmptyCallEntry(ExtRegistryEntry): + "Annotation and rtyping of calls to numpy.empty" + _about_ = numpy.empty def compute_result_annotation(self, s_tuple, s_dtype=None): if isinstance(s_tuple, SomeTuple): Modified: pypy/dist/pypy/rpython/numpy/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/rarray.py (original) +++ pypy/dist/pypy/rpython/numpy/rarray.py Fri Aug 31 03:15:14 2007 @@ -215,20 +215,42 @@ class __extend__(pairtype(ArrayRepr, IntegerRepr)): def rtype_setitem((r_arr, r_int), hop): v_array, v_index, v_item = hop.inputargs(r_arr, Signed, r_arr.item_repr) - return hop.gendirectcall(ll_setitem, v_array, v_index, v_item) + return hop.gendirectcall(ll_setitem1, v_array, v_index, v_item) def rtype_getitem((r_arr, r_int), hop): v_array, v_index = hop.inputargs(r_arr, Signed) - return hop.gendirectcall(ll_getitem, v_array, v_index) - -#class __extend__(pairtype(ArrayRepr, AbstractTupleRepr)): -# def rtype_setitem((r_arr, r_tpl), hop): -# v_array, v_tuple, v_item = hop.inputargs(r_arr, r_tpl, r_arr) -# return hop.gendirectcall(ll_setitem_from_array, v_array, v_tuple, v_item) -# -# def rtype_getitem((r_arr, r_tpl), hop): -# return NotImplemented + return hop.gendirectcall(ll_getitem1, v_array, v_index) +def gen_getset_item(ndim): + unrolling_dims = unrolling_iterable(range(ndim)) + def ll_get_item(ARRAY, ao, tpl): + array = ll_allocate(ARRAY, ndim) + idx = 0 + for i in unrolling_dims: + idx += ao.strides[i] * getattr(tpl, 'item%d'%i) + return ao.data[idx] + + def ll_set_item(ARRAY, ao, tpl, value): + array = ll_allocate(ARRAY, ndim) + idx = 0 + for i in unrolling_dims: + idx += ao.strides[i] * getattr(tpl, 'item%d'%i) + ao.data[idx] = value + + return ll_get_item, ll_set_item + +class __extend__(pairtype(ArrayRepr, AbstractTupleRepr)): + def rtype_getitem((r_arr, r_tpl), hop): + v_array, v_tuple = hop.inputargs(r_arr, r_tpl) + cARRAY = hop.inputconst(Void, r_arr.ARRAY.TO) + get_item, set_item = gen_getset_item(r_arr.ndim) + return hop.gendirectcall(get_item, cARRAY, v_array, v_tuple) + + def rtype_setitem((r_arr, r_tpl), hop): + v_array, v_tuple, v_item = hop.inputargs(r_arr, r_tpl, hop.args_r[2]) + cARRAY = hop.inputconst(Void, r_arr.ARRAY.TO) + get_item, set_item = gen_getset_item(r_arr.ndim) + return hop.gendirectcall(set_item, cARRAY, v_array, v_tuple, v_item) class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)): def rtype_setitem((r_arr, r_slc), hop): @@ -242,7 +264,6 @@ cnext0 = hop.inputconst(Void, iter_next0) cnew1 = hop.inputconst(Void, iter_new1) cnext1 = hop.inputconst(Void, iter_next1) -# return hop.gendirectcall(ll_setitem_from_array, cnext, cITER0, v_array, v_slc, cITER1, v_item) return hop.gendirectcall(ll_array_unary_op, cnew0, cnext0, cITER0, v_array, cnew1, cnext1, cITER1, v_item) @@ -302,10 +323,10 @@ new_array.strides[i] = array.strides[i] return new_array -def ll_setitem(l, index, item): +def ll_setitem1(l, index, item): l.data[index] = item -def ll_getitem(l, index): +def ll_getitem1(l, index): return l.data[index] def ll_add(ARRAY, a1, a2): Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Fri Aug 31 03:15:14 2007 @@ -70,9 +70,9 @@ s = a.build_types(access_with_variable, []) assert s.knowntype == rffi.r_int - def test_annotate_zeros(self): + def test_annotate_empty(self): def f(): - a = numpy.zeros((3,4,5)) + a = numpy.empty((3,4,5)) return a t = TranslationContext() @@ -83,7 +83,7 @@ def test_annotate_indexing(self): def f(): - a = numpy.zeros((3,4,5)) + a = numpy.empty((3,4,5)) b = a[0] a[0,1,2] = 1. b[0,1] = 2. @@ -185,9 +185,9 @@ assert res.data[0] == 1 assert res.data[1] == 20 - def test_specialize_array_zeros(self): + def test_specialize_array_empty(self): def f(n, m): - a = numpy.zeros((n, m)) + a = numpy.empty((n, m)) return a res = interpret(f, [3, 4]) @@ -235,7 +235,7 @@ def test_specialize_array_attr_shape(self): def f(): - a = numpy.zeros((2,3)) + a = numpy.empty((2,3)) return list(a.shape) res = interpret(f, []) @@ -244,7 +244,7 @@ def test_specialize_array_strides(self): def f(): - a = numpy.zeros((3,4,5)) + a = numpy.empty((3,4,5)) return a res = interpret(f, []) @@ -264,7 +264,7 @@ def test_specialize_indexing(self): def f(): - a = numpy.zeros((3,), dtype='i') + a = numpy.empty((3,), dtype='i') b = numpy.array([5,55,555]) a[:] = b return a @@ -273,9 +273,19 @@ assert res.data[1] == 55 assert res.data[2] == 555 + def test_specialize_multi(self): + def f(ii, jj): + a = numpy.empty((4, 5), dtype='i') + for i in range(4): + for j in range(5): + a[i, j] = i*j + return a[ii, jj] + assert interpret(f, [0, 0]) == 0 + assert interpret(f, [3, 4]) == 12 + def test_malloc_remove(self): def f(): - a = numpy.zeros((3,), dtype='i') + a = numpy.empty((3,), dtype='i') b = numpy.array([5,55,555]) a[:] = b return a @@ -304,7 +314,7 @@ def test_compile_array_access(self): def access_array(index): - a = numpy.zeros((3,), dtype='i') + a = numpy.empty((3,), dtype='i') b = numpy.array([5,55,555]) a[:] = b a[0] = 1 @@ -316,12 +326,14 @@ assert fn(2) == 555 def test_compile_2d(self): - py.test.skip() - def access_array(index): - a = numpy.zeros((5,6)) - a[0,0] = 2 - return 0 + def f(ii, jj): + a = numpy.empty((4, 5), dtype='i') + for i in range(4): + for j in range(5): + a[i, j] = i*j + return a[ii, jj] - fn = self.compile(access_array, [int]) + fn = self.compile(f, [int, int]) + assert fn(2,3) == 2*3 From simonb at codespeak.net Fri Aug 31 03:16:21 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Fri, 31 Aug 2007 03:16:21 +0200 (CEST) Subject: [pypy-svn] r46205 - pypy/dist/pypy/rpython/numpy Message-ID: <20070831011621.1B31D81DB@code0.codespeak.net> Author: simonb Date: Fri Aug 31 03:16:20 2007 New Revision: 46205 Modified: pypy/dist/pypy/rpython/numpy/rarray.py Log: broadcast iterator (not ready for this yet) Modified: pypy/dist/pypy/rpython/numpy/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/rarray.py (original) +++ pypy/dist/pypy/rpython/numpy/rarray.py Fri Aug 31 03:16:20 2007 @@ -96,6 +96,34 @@ return it ll_iter_new._always_inline_ = True + def ll_iter_broadcast_to_shape(ITER, ao, shape, iter_reset=ll_iter_reset): + if ao.ndim > ndim: + raise Exception("array is not broadcastable to correct shape") # XX raise here ? + diff = j = ndim - ao.ndim + for i in range(ao.ndim): + if ao.shape[i] != 1 and ao.shape[i] != shape[j]: + raise Exception("array is not broadcastable to correct shape") # XX raise here ? + j += 1 + it = malloc(ITER) + it.ao = ao + it.size = ll_mul_list(ao.shape, ndim) + it.nd_m1 = ndim - 1 + #it.factors[nd-1] = 1 + for i in unroll_ndim: + it.dims_m1[i] = ao.shape[i]-1 + k = i - diff + if k<0 or ao.shape[k] != shape[i]: + #it.contiguous = False + it.strides[i] = 0 + else: + it.strides[i] = ao.strides[k] + it.backstrides[i] = it.strides[i] * it.dims_m1[i] + #if i > 0: + #it.factors[nd-i-1] = it.factors[nd-i]*shape[nd-i] + iter_reset(it) + return it + ll_iter_broadcast_to_shape._always_inline_ = True + def ll_iter_next(it): it.index += 1 for i in unroll_ndim_rev: @@ -107,6 +135,7 @@ it.dataptr = direct_ptradd(it.dataptr, -it.backstrides[i]) ll_iter_next._always_inline_ = True +# return ll_iter_new, ll_iter_broadcast_to_shape, ll_iter_next return ll_iter_new, ll_iter_next def ll_unary_op(p0, p1, op=lambda x:x): From antocuni at codespeak.net Fri Aug 31 11:24:07 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 31 Aug 2007 11:24:07 +0200 (CEST) Subject: [pypy-svn] r46213 - in pypy/dist/pypy/translator/jvm: . test Message-ID: <20070831092407.BB39381CE@code0.codespeak.net> Author: antocuni Date: Fri Aug 31 11:24:06 2007 New Revision: 46213 Modified: pypy/dist/pypy/translator/jvm/opcodes.py pypy/dist/pypy/translator/jvm/test/test_op.py Log: make some tests in test_op passing. llong_rshift caused the verifier to complain because LSHR's second operand needs to be integer, not long. Modified: pypy/dist/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/opcodes.py (original) +++ pypy/dist/pypy/translator/jvm/opcodes.py Fri Aug 31 11:24:06 2007 @@ -33,6 +33,8 @@ def _check_ovf(op): return op + +Ignore = [] # This table maps the opcodes to micro-ops for processing them. @@ -65,7 +67,7 @@ 'cast_ptr_to_weakadr': [CastPtrToWeakAddress], 'cast_weakadr_to_ptr': CastWeakAddressToPtr, #'gc__collect': 'call void class [mscorlib]System.GC::Collect()', - #'resume_point': Ignore, + 'resume_point': Ignore, 'debug_assert': [], # TODO: implement? @@ -197,7 +199,7 @@ 'llong_and': jvmgen.LAND, 'llong_or': jvmgen.LOR, 'llong_lshift': jvmgen.LSHL, - 'llong_rshift': jvmgen.LSHR, + 'llong_rshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHR, StoreResult], 'llong_xor': jvmgen.LXOR, 'llong_floordiv_ovf': jvmgen.LDIV, # these can't overflow! 'llong_mod_ovf': jvmgen.LREMOVF, Modified: pypy/dist/pypy/translator/jvm/test/test_op.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_op.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_op.py Fri Aug 31 11:24:06 2007 @@ -5,18 +5,7 @@ # ====> ../../oosupport/test_template/operations.py class TestOperations(JvmTest, BaseTestOperations): - def test_two_overflows(self): - py.test.skip("Backend lacks appropriate precision") - - def test_ignore_resume_point(self): - py.test.skip("Unknown opcode resume_point") - - def test_rshift(self): - py.test.skip("VerifyError happens. Expecting int on the stack") - - def test_uint_neg(self): - py.test.skip("Backend lacks appropriate precision") - + def test_eq(self): py.test.skip("Str to long is not implemented, needed for test") @@ -46,4 +35,4 @@ def test_is_early_constant(self): py.test.skip("Unknown opcode is_early_constant") - \ No newline at end of file + From antocuni at codespeak.net Fri Aug 31 11:43:58 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 31 Aug 2007 11:43:58 +0200 (CEST) Subject: [pypy-svn] r46214 - in pypy/dist/pypy/translator/jvm: src/pypy test Message-ID: <20070831094358.8856D81FE@code0.codespeak.net> Author: antocuni Date: Fri Aug 31 11:43:57 2007 New Revision: 46214 Modified: pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java pypy/dist/pypy/translator/jvm/test/test_op.py Log: implement str_to_ulong and make these tests passing 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 Aug 31 11:43:57 2007 @@ -163,8 +163,15 @@ } public static long str_to_ulong(String s) { - // oh bother - throw new RuntimeException("TODO--- str to ulong"); + long res = 0; + s = s.trim(); + for(int i=0; i Author: antocuni Date: Fri Aug 31 13:54:57 2007 New Revision: 46215 Modified: pypy/dist/pypy/translator/jvm/generator.py pypy/dist/pypy/translator/jvm/opcodes.py pypy/dist/pypy/translator/jvm/test/test_op.py Log: don't forget to StoreResult after having computed it. This makes test_and_or passing Modified: pypy/dist/pypy/translator/jvm/generator.py ============================================================================== --- pypy/dist/pypy/translator/jvm/generator.py (original) +++ pypy/dist/pypy/translator/jvm/generator.py Fri Aug 31 13:54:57 2007 @@ -1342,7 +1342,7 @@ return str(arg) strargs = [jasmin_syntax(arg) for arg in args] instr_text = '%s %s' % (jvmstr, " ".join(strargs)) - self.curclass.out(' .line %d\n' % self.curfunc.instr_counter) + #self.curclass.out(' .line %d\n' % self.curfunc.instr_counter) self.curclass.out(' %-60s\n' % (instr_text,)) self.curfunc.instr_counter+=1 Modified: pypy/dist/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/opcodes.py (original) +++ pypy/dist/pypy/translator/jvm/opcodes.py Fri Aug 31 13:54:57 2007 @@ -154,9 +154,7 @@ 'uint_rshift': jvmgen.IUSHR, 'uint_xor': jvmgen.IXOR, - 'float_is_true': [PushAllArgs, - jvmgen.DCONST_0, - 'dbl_not_equals'], + 'float_is_true': [PushAllArgs, jvmgen.DCONST_0, 'dbl_not_equals', StoreResult], 'float_neg': jvmgen.DNEG, 'float_abs': 'dbl_abs', @@ -172,9 +170,7 @@ 'float_gt': 'dbl_greater_than', 'float_ge': 'dbl_greater_equals', - 'llong_is_true': [PushAllArgs, - jvmgen.LCONST_0, - 'long_not_equals'], + 'llong_is_true': [PushAllArgs, jvmgen.LCONST_0, 'long_not_equals', StoreResult], 'llong_neg': jvmgen.LNEG, 'llong_neg_ovf': jvmgen.LNEGOVF, 'llong_abs': jvmgen.MATHLABS, @@ -205,9 +201,7 @@ 'llong_mod_ovf': jvmgen.LREMOVF, 'llong_lshift_ovf': jvmgen.LSHLOVF, - 'ullong_is_true': [PushAllArgs, - jvmgen.LCONST_0, - 'long_not_equals'], + 'ullong_is_true': [PushAllArgs, jvmgen.LCONST_0, 'long_not_equals', StoreResult], 'ullong_invert': jvmgen.PYPYLONGBITWISENEGATE, 'ullong_add': jvmgen.LADD, Modified: pypy/dist/pypy/translator/jvm/test/test_op.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_op.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_op.py Fri Aug 31 13:54:57 2007 @@ -6,9 +6,6 @@ class TestOperations(JvmTest, BaseTestOperations): - def test_and_not(self): - py.test.skip("VerifyError happens. Accessing uninit reg") - def test_modulo(self): py.test.skip("Backend lacks appropriate precision") From antocuni at codespeak.net Fri Aug 31 14:12:12 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 31 Aug 2007 14:12:12 +0200 (CEST) Subject: [pypy-svn] r46216 - in pypy/dist/pypy/translator/jvm: . src/pypy test Message-ID: <20070831121212.F21A1821A@code0.codespeak.net> Author: antocuni Date: Fri Aug 31 14:12:10 2007 New Revision: 46216 Modified: pypy/dist/pypy/translator/jvm/generator.py pypy/dist/pypy/translator/jvm/opcodes.py pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java pypy/dist/pypy/translator/jvm/test/test_op.py Log: fix uint_mod. The simplest way is to convert the args to double and use Math.IEEERemainder. Not sure if it's the most efficient way, though. Modified: pypy/dist/pypy/translator/jvm/generator.py ============================================================================== --- pypy/dist/pypy/translator/jvm/generator.py (original) +++ pypy/dist/pypy/translator/jvm/generator.py Fri Aug 31 14:12:10 2007 @@ -393,6 +393,7 @@ (jStringBuilder, jString), jVoid) PYPYUINTCMP = Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt) PYPYULONGCMP = Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt) +PYPYUINTMOD = Method.s(jPyPy, 'uint_mod', (jInt, jInt), jInt) PYPYUINTTODOUBLE = Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble) PYPYDOUBLETOUINT = Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt) PYPYDOUBLETOLONG = Method.s(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL Modified: pypy/dist/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/opcodes.py (original) +++ pypy/dist/pypy/translator/jvm/opcodes.py Fri Aug 31 14:12:10 2007 @@ -141,7 +141,7 @@ 'uint_div': jvmgen.IDIV, # valid? 'uint_truediv': None, # TODO 'uint_floordiv': jvmgen.IDIV, # valid? - 'uint_mod': jvmgen.IREM, # valid? + 'uint_mod': jvmgen.PYPYUINTMOD, 'uint_lt': 'u_less_than', 'uint_le': 'u_less_equals', 'uint_eq': 'u_equals', 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 Aug 31 14:12:10 2007 @@ -66,6 +66,12 @@ return VALUE2BIGGER; } + public static int uint_mod(int x, int y) { + double dx = uint_to_double(x); + double modulo = Math.IEEEremainder(dx, y); + return (int)modulo; + } + public static int ulong_cmp(long value1, long value2) { final int VALUE2BIGGER = -1; final int VALUE1BIGGER = 1; Modified: pypy/dist/pypy/translator/jvm/test/test_op.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_op.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_op.py Fri Aug 31 14:12:10 2007 @@ -6,9 +6,6 @@ class TestOperations(JvmTest, BaseTestOperations): - def test_modulo(self): - py.test.skip("Backend lacks appropriate precision") - def test_operations(self): py.test.skip("Backend lacks appropriate precision") From simonb at codespeak.net Fri Aug 31 20:26:45 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Fri, 31 Aug 2007 20:26:45 +0200 (CEST) Subject: [pypy-svn] r46225 - in pypy/dist/pypy/rpython/numpy: . test Message-ID: <20070831182645.21EE3819B@code0.codespeak.net> Author: simonb Date: Fri Aug 31 20:26:44 2007 New Revision: 46225 Modified: pypy/dist/pypy/rpython/numpy/rarray.py pypy/dist/pypy/rpython/numpy/test/test_array.py Log: found out how to make a null pointer, solved base attr bug Modified: pypy/dist/pypy/rpython/numpy/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/rarray.py (original) +++ pypy/dist/pypy/rpython/numpy/rarray.py Fri Aug 31 20:26:44 2007 @@ -9,7 +9,7 @@ from pypy.rpython.rslice import AbstractSliceRepr from pypy.rpython.lltypesystem.lltype import \ GcArray, GcStruct, Signed, Ptr, Unsigned, Void, FixedSizeArray, Bool,\ - GcForwardReference, malloc, direct_arrayitems, direct_ptradd, _cast_whatever + GcForwardReference, malloc, direct_arrayitems, direct_ptradd, nullptr from pypy.rpython.lltypesystem.rtuple import TupleRepr from pypy.annotation.model import SomeObject, SomeInteger from pypy.rpython.numpy.aarray import SomeArray @@ -322,11 +322,10 @@ cARRAY = inputconst(lltype.Void, r_arr.lowleveltype.TO) return llops.gendirectcall(ll_build_from_list, cARRAY, v) -from pypy.rpython.memory.lladdress import NULL def ll_allocate(ARRAY, ndim): array = malloc(ARRAY) array.ndim = ndim - #array.base = NULL # how to do this ????? + array.base = nullptr(ARRAY) return array def ll_build_from_list(ARRAY, lst): @@ -345,8 +344,9 @@ def ll_build_alias(ARRAY, array): new_array = ll_allocate(ARRAY, array.ndim) new_array.data = array.data # alias data -# new_array.base = array.base or array # this is broken until we set base to NULL above new_array.base = array + if array.base: + new_array.base = array.base for i in range(array.ndim): new_array.shape[i] = array.shape[i] new_array.strides[i] = array.strides[i] Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Fri Aug 31 20:26:44 2007 @@ -228,7 +228,9 @@ def f(): a = numpy.array([1,2]) b = numpy.array(a) - return b.base is a + # Aha: a.base is a phantom array we made + # when converting from a list. + return b.base is a.base res = interpret(f, []) assert res From simonb at codespeak.net Fri Aug 31 22:41:47 2007 From: simonb at codespeak.net (simonb at codespeak.net) Date: Fri, 31 Aug 2007 22:41:47 +0200 (CEST) Subject: [pypy-svn] r46230 - in pypy/dist/pypy/rpython/numpy: . test Message-ID: <20070831204147.1BD7F8206@code0.codespeak.net> Author: simonb Date: Fri Aug 31 22:41:45 2007 New Revision: 46230 Modified: pypy/dist/pypy/rpython/numpy/rarray.py pypy/dist/pypy/rpython/numpy/test/test_array.py Log: add a dataptr attribute that points inside a GcArray Modified: pypy/dist/pypy/rpython/numpy/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/rarray.py (original) +++ pypy/dist/pypy/rpython/numpy/rarray.py Fri Aug 31 22:41:45 2007 @@ -30,6 +30,7 @@ array.strides[i] = itemsize itemsize *= size array.data = malloc(ARRAY.data.TO, itemsize) + array.dataptr = direct_arrayitems(array.data) return array return ll_build_from_shape @@ -44,7 +45,8 @@ return shape return ll_get_shape -NPY_INTP = Signed # index type (see Py_intptr_t) +NPY_INTP = Signed # XX index type (see Py_intptr_t) + def ARRAY_ITER(ARRAY, INDEXARRAY): ITER = Ptr( GcStruct("array_iter", @@ -57,7 +59,7 @@ ("backstrides", INDEXARRAY), #("factors", INDEXARRAY), ("ao", ARRAY), - ("dataptr", Ptr(FixedSizeArray(ARRAY.TO.data.TO.OF, 1))), # pointer to current item + ("dataptr", ARRAY.TO.dataptr), # pointer to current item #("contiguous", Bool), )) return ITER @@ -75,12 +77,13 @@ def ll_iter_reset(it): it.index = 0 - it.dataptr = direct_arrayitems(it.ao.data) + it.dataptr = it.ao.dataptr for i in unroll_ndim: it.coordinates[i] = 0 ll_iter_reset._always_inline_ = True def ll_iter_new(ITER, ao, iter_reset=ll_iter_reset): + assert ao.dataptr it = malloc(ITER) it.ao = ao it.nd_m1 = ndim - 1 @@ -165,8 +168,10 @@ self.INDEXARRAY = FixedSizeArray(NPY_INTP, self.ndim) self.itemsize = sizeof(self.ITEM) FORWARD = GcForwardReference() + DATA_PTR = Ptr(FixedSizeArray(self.ITEM, 1)) STRUCT = GcStruct("array", ("data", Ptr(ITEMARRAY)), # pointer to raw data buffer + ("dataptr", DATA_PTR), # pointer to first element ("ndim", Signed), # number of dimensions ("shape", self.INDEXARRAY), # size in each dimension ("strides", self.INDEXARRAY), # elements to jump to get to the @@ -326,31 +331,34 @@ array = malloc(ARRAY) array.ndim = ndim array.base = nullptr(ARRAY) + array.data = nullptr(ARRAY.data.TO) + array.dataptr = nullptr(ARRAY.dataptr.TO) return array def ll_build_from_list(ARRAY, lst): size = lst.ll_length() array = ll_allocate(ARRAY, 1) - for i in range(array.ndim): - array.shape[i] = size - array.strides[i] = 1 - data = array.data = malloc(ARRAY.data.TO, size) + array.shape[0] = size + array.strides[0] = 1 + array.data = malloc(ARRAY.data.TO, size) i = 0 while i < size: - data[i] = lst.ll_getitem_fast(i) + array.data[i] = lst.ll_getitem_fast(i) i += 1 + array.dataptr = direct_arrayitems(array.data) return array -def ll_build_alias(ARRAY, array): - new_array = ll_allocate(ARRAY, array.ndim) - new_array.data = array.data # alias data - new_array.base = array - if array.base: - new_array.base = array.base - for i in range(array.ndim): - new_array.shape[i] = array.shape[i] - new_array.strides[i] = array.strides[i] - return new_array +def ll_build_alias(ARRAY, ao): + array = ll_allocate(ARRAY, ao.ndim) + array.data = ao.data # alias data + array.base = ao + if ao.base: + array.base = ao.base + for i in range(ao.ndim): + array.shape[i] = ao.shape[i] + array.strides[i] = ao.strides[i] + array.dataptr = ao.dataptr + return array def ll_setitem1(l, index, item): l.data[index] = item @@ -368,6 +376,7 @@ while i < size: array.data[i] = a1.data[i] + a2.data[i] i += 1 + array.dataptr = direct_arrayitems(array.data) return array def ll_transpose(ARRAY, a1): Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py ============================================================================== --- pypy/dist/pypy/rpython/numpy/test/test_array.py (original) +++ pypy/dist/pypy/rpython/numpy/test/test_array.py Fri Aug 31 22:41:45 2007 @@ -250,6 +250,8 @@ return a res = interpret(f, []) + # Note that the real numpy defines strides to be a byte-count + # but we return an element count ATM. assert res.strides[0] == 20 assert res.strides[1] == 5 assert res.strides[2] == 1