From: <th...@us...> - 2009-04-01 02:22:21
|
Revision: 6145 http://jython.svn.sourceforge.net/jython/?rev=6145&view=rev Author: thobes Date: 2009-04-01 01:45:35 +0000 (Wed, 01 Apr 2009) Log Message: ----------- Added benchmarks. Added Paths: ----------- trunk/sandbox/tobias/tests/ trunk/sandbox/tobias/tests/functions.py trunk/sandbox/tobias/tests/parrotbench/ trunk/sandbox/tobias/tests/parrotbench/Makefile trunk/sandbox/tobias/tests/parrotbench/README.txt trunk/sandbox/tobias/tests/parrotbench/b.py trunk/sandbox/tobias/tests/parrotbench/b0.py trunk/sandbox/tobias/tests/parrotbench/b1.py trunk/sandbox/tobias/tests/parrotbench/b2.py trunk/sandbox/tobias/tests/parrotbench/b3.py trunk/sandbox/tobias/tests/parrotbench/b4.py trunk/sandbox/tobias/tests/parrotbench/b5.py trunk/sandbox/tobias/tests/parrotbench/b6.py trunk/sandbox/tobias/tests/parrotbench/t.py Added: trunk/sandbox/tobias/tests/functions.py =================================================================== --- trunk/sandbox/tobias/tests/functions.py (rev 0) +++ trunk/sandbox/tobias/tests/functions.py 2009-04-01 01:45:35 UTC (rev 6145) @@ -0,0 +1,23 @@ +def func(x): + z = x + +def bench(times): + for x in xrange(times): + func(x) + +def main(script, times='10000', warmups='20000', reps='3'): + from time import time + warmups = int(warmups); reps = int(reps); times = int(times) + for i in xrange(warmups): + bench(times) + res = [] + for i in xrange(reps): + t = time() + bench(times) + t = time() - t + res.append(t) + print min(res), max(res) + +if __name__ == '__main__': + import sys + main(*sys.argv) Property changes on: trunk/sandbox/tobias/tests/parrotbench ___________________________________________________________________ Added: svn:ignore + *.pyo *.pyc *.class out out? @out Added: trunk/sandbox/tobias/tests/parrotbench/Makefile =================================================================== --- trunk/sandbox/tobias/tests/parrotbench/Makefile (rev 0) +++ trunk/sandbox/tobias/tests/parrotbench/Makefile 2009-04-01 01:45:35 UTC (rev 6145) @@ -0,0 +1,81 @@ +PYTHON= echo SPECIFY PYTHON +DIFF= diff +ECHO= echo +TIME= time +CMP= cmp +SCP= scp +RM= rm + +FILES= README.txt Makefile b.py b[0-9].py t.py out out[0-9] +TARFILE=parrotbench.tgz +TARGET= python.org:~ftp/pub/python/parrotbench/parrotbench.tgz + +time: + $(TIME) $(PYTHON) b.py >@out + $(CMP) @out out + +cmp: + $(PYTHON) -O b.py >@out + $(CMP) @out out + +diff: + $(PYTHON) -O b.py >@out + $(DIFF) @out out + +dist: $(TARFILE) + +$(TARFILE): $(FILES) + tar czf $(TARFILE) $(FILES) + +upload: dist + $(SCP) $(TARFILE) $(TARGET) + +clean: + -$(RM) -f @* *~ *.pyc *.pyo $(TARFILE) + +times: + for i in 0 1 2 3 4 5 6; do \ + $(ECHO) b$$i.py; \ + $(TIME) $(PYTHON) b$$i.py >@out$$i; \ + $(CMP) @out$$i out$$i; \ + done + +cmps: + for i in 0 1 2 3 4 5 6; do \ + $(ECHO) b$$i.py; \ + $(PYTHON) b$$i.py >@out$$i; \ + $(CMP) @out$$i out$$i; \ + done + +diffs: + for i in 0 1 2 3 4 5 6; do \ + $(ECHO) b$$i.py; \ + $(PYTHON) b$$i.py >@out$$i; \ + $(DIFF) @out$$i out$$i; \ + done + +all: out out0 out1 out2 out3 out4 out5 out6 + +out: b.py b?.py + $(PYTHON) -O b.py >out + +out0: b0.py + $(PYTHON) b0.py >out0 + +out1: b1.py + $(PYTHON) b1.py >out1 + +out2: b2.py + $(PYTHON) b2.py >out2 + +out3: b3.py + $(PYTHON) b3.py >out3 + +out4: b4.py b0.py + $(PYTHON) b4.py >out4 + +out5: b5.py + $(PYTHON) b5.py >out5 + +out6: b6.py + $(PYTHON) b6.py >out6 Added: trunk/sandbox/tobias/tests/parrotbench/README.txt =================================================================== --- trunk/sandbox/tobias/tests/parrotbench/README.txt (rev 0) +++ trunk/sandbox/tobias/tests/parrotbench/README.txt 2009-04-01 01:45:35 UTC (rev 6145) @@ -0,0 +1,87 @@ +Parrot benchmark 1.0.4 +====================== + +[This is version 1.0.4, with a bugfix for the Mac OSX issue that Dan +reported, two further bugfixes for the dict ordering problem noted by +Samuele Pedroni, and an updated Makefile and t.py driver for Windows.] + +This is a benchmark to be run in front of a live audience at OSCON +2004 between Python and Parrot. The bytecode must be Python 2.3 +bytecode frozen in December 2003 (which is almost over as I write this +:-). + +For some more background, see the python-dev thread around + http://mail.python.org/pipermail/python-dev/2003-December/040977.html + +The benchmark here is intended to make Dan Sugalski's life difficult: +there are some standard benchmark thingies (simple random algorithms +using basic data types) but also a lot of play with odd corners of the +language definition, and Python's extremely dynamic object model: +funky descriptors, mutable classes, that sort of thing. The benchmark +is supposed to run with either Python 2.3 or Python 2.4. + +Brief description per file: + +Makefile -- Various ways of running the benchmark and sub-benchmarks. + +b.py -- The full benchmark output is defined as "python -O b.py". + +b0.py -- Lots of fun with a parser for a subset of Python (just + because this is a classic OO-heavy application). + +b1.py -- Explore recursion. Unbounded recursion is expected to raise + RuntimeError after about 1000 levels. (If Parrot supports much + more, this part will be slower; the point is to be able to + tweak the recursion limit.) + +b2.py -- Calculate PI using a generator. + +b3.py -- Sorting, and various ways of setting the comparison function + for list.sort(). + +b4.py -- Another test for the code from b0.py, this time with code + derived from Python 2.3's heapq.py. + +b5.py -- Test the standard library, including three standard Unicode + codecs (ASCII, Latin-1 and UTF-8), various descriptors, and + mutable classes. + +b6.py -- Check speed of iterating over several common iterators. + +Note that per agreement I'm not allowed to use any built-in extension +modules, not even __builtin__ or sys. This means there's no access to +sys.args (so no command line arguments), sys.stdout (but we have +"print >>file") or to sys.exc_info(). Dan could save some nanoseconds +by not supporting tracebacks. But that would be cheating. Also +cheating would be to do all the work at compile time (this is +theoretically possible since the program has no input). + +Per agreement the following builtins are out: open(), file(), input(), +raw_input(), compile(), eval(), execfile(), and the exec statement. +But I assume the print statement is okay (the program must communicate +its success or failure *somehow*). + +I'm being nice, and am voluntarily refraining from using __builtins__, +basestring, callable(), __import__(), reload(), dir(), globals(), +locals(), vars(), help(), apply(), buffer(), coerce(), or intern(). +I'm also not digging around in the func_code attribute of function +objects. + +On the use of __debug__: this is a built-in variable, set to True +normally and to False when Python is invoked with -O. I use this to +produce verbose output without -O but minimal output with it. For the +actual benchmark, Python should use -O, and Dan can simply set +__debug__ to False in the builtins if he prefers. + +On timing: there's a requirement that the benchmark runs for at least +30 seconds. It currently runs for nearly a minute on my home box, +which is a four-year-old 650 MHz Pentium box. If the contest hardware +is so fast that it runs under a minute, there's a number in b.py that +can be cranked up to increase the number of runs. (It takes 27 +seconds on my recent work desktop, and on my screaming IBM T40 laptop +it runs in 15 seconds, so I suspect that we should at least double the +number of runs from 2 to 4.) + +December 31, 2003, + +--Guido van Rossum (home page: http://www.python.org/~guido/) Added: trunk/sandbox/tobias/tests/parrotbench/b.py =================================================================== --- trunk/sandbox/tobias/tests/parrotbench/b.py (rev 0) +++ trunk/sandbox/tobias/tests/parrotbench/b.py 2009-04-01 01:45:35 UTC (rev 6145) @@ -0,0 +1,46 @@ +import b0 +import b1 +import b2 +import b3 +import b4 +import b5 +import b6 + +import sys +from time import time + +WARMUP = 0 +TIMES = 3 +NUMBER = 1 +ITERATIONS = 1 + +def run(module, iteration): + print >>sys.stderr, "-->", module.__name__ + res = [] + for i in range(TIMES): + t = time() + for i in range(NUMBER): + module.main() + t = time() - t + res.append(t/NUMBER) + return res + +if 'java' in sys.platform: + def run(module, iteration, run=run): + if not iteration: + for i in range(WARMUP): + module.main() + return run(module, iteration) + +def main(): + t = time() + for i in range(ITERATIONS): + print >>sys.stderr, "--> iteration", i + for module in (b0, b2, b3, b4, b5, b6): # b1 ommitted + mt = min(run(module, i)) + print >>sys.stderr, "best of 3:", mt + t = time() - t + print >>sys.stderr, "--> All done.", t + +if __name__ == '__main__': + main() Added: trunk/sandbox/tobias/tests/parrotbench/b0.py =================================================================== --- trunk/sandbox/tobias/tests/parrotbench/b0.py (rev 0) +++ trunk/sandbox/tobias/tests/parrotbench/b0.py 2009-04-01 01:45:35 UTC (rev 6145) @@ -0,0 +1,938 @@ +def check(a, b): + if not a == b: + raise AssertionError("%.30r != %.30r" % (a, b)) + +def proto___new__(cls, name): + if name in cls.name2num: + return cls.name2num[name] + cls.name2num[name] = obj = int.__new__(cls, cls.next) + cls.num2name[obj] = name + cls.next += 1 + return obj + +def proto___repr__(self): + return self.__class__.num2name[self] + +class MetaToken(type): + def __new__(metacls, name, bases, vars): + cls = type.__new__(metacls, name, bases, vars) + cls.__new__ = staticmethod(proto___new__) + cls.__repr__ = cls.__str__ = proto___repr__ + cls.next = 0 + cls.name2num = {} + cls.num2name = {} + return cls + +Token = MetaToken('Token', (int,), {}) + +EOF = Token('EOF') +INDENT = Token('INDENT') +DEDENT = Token('DEDENT') +NEWLINE = Token('NEWLINE') +NAME = Token('NAME') +NUMBER = Token('NUMBER') +STRING = Token('STRING') +OPERATOR = Token('OPERATOR') + +class Scanner(object): + + # A vaguely Pythonic tokenizer + + def __init__(self, getc): + self.getc = getc + self.indents = [0] + + def tokenize(self, + eolchars = ('', '\r', '\n'), + quotes = ('"', '\''), + hspaces = (' ', '\t'), + longops = dict.fromkeys( + ('<<', '>>', '<=', '>=', '==', '!=', '//', '**'))): + # A generator yielding successive tokens to the parser + # Each token is a (tokentype, value) pair + getc = self.getc + nextc = getc() + while True: + col = 0 + while nextc.isspace(): + if nextc == '\t': + col = ((col//8) + 1)*8 + elif nextc == ' ': + col += 1 + else: + col = 0 # \f, \v, \r, \n all reset the column + nextc = getc() + if nextc == '#': + while nextc not in eolchars: + nextc = getc() + continue + if col != self.indents[-1]: + while col < self.indents[-1]: + yield DEDENT, '' + del self.indents[-1] + # This will yield DEDENT + INDENT for inconsistent dedent + if col > self.indents[-1]: + yield INDENT, '' + self.indents.append(col) + while nextc not in eolchars: + if nextc.isalpha() or nextc == '_': + name = '' + while nextc.isalnum() or nextc == '_': + name += nextc + nextc = getc() + yield NAME, name + elif nextc.isdigit(): + number = '' + while nextc.isdigit(): + number += nextc + nextc = getc() + yield NUMBER, number + elif nextc in quotes: + quote = nextc + s = nextc + nextc = getc() + while nextc != quote: + if nextc in eolchars: + if not nextc: + raise SyntaxError("EOF in string") + raise SyntaxError("unescaped %r in string" % nextc) + s += nextc + if nextc == '\\': + nextc = getc() + s += nextc + nextc = getc() + s += nextc + nextc = getc() + yield STRING, s + elif nextc == '#': + while nextc not in eolchars: + nextc = getc() + elif nextc in hspaces: + nextc = getc() + else: + c1 = nextc + nextc = getc() + if c1+nextc in longops: + c2 = nextc + nextc = getc() + yield OPERATOR, c1+c2 + else: + yield OPERATOR, c1 + yield NEWLINE, '' + nextc = getc() + if not nextc: + while self.indents[-1]: + yield DEDENT, '' + del self.indents[-1] + break + yield EOF, '' + +class Link(object): + __slots__ = ['value', 'next'] + def __init__(self): + self.value = None + self.next = None + +class Clone(object): + __slots__ = ['link', 'itnext'] + def __init__(self, it, link=None): + if isinstance(it, Clone): + self.itnext = it.itnext + self.link = it.link + else: + self.itnext = it.next + self.link = Link() + def __iter__(self): + return self + def next(self): + next = self.link.next + if next is None: + self.link.value = value = self.itnext() + self.link.next = next = Link() + else: + value = self.link.value + self.link = next + return value + +def getcFromString(s): + for c in s: + yield c + while True: + yield '' + +sample = ''' +def pi(): + # Compute digits of Pi. Algorithm due to LGLT Meertens. + k, a, b, a1, b1 = 2, 4, 1, 12, 4 + while 1: + p, q, k = k*k, 2*k+1, k+1 + a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1 + d, d1 = a//b, a1//b1 + while d == d1: + yield d + a, a1 = 10*(a%b), 10*(a1%b1) + d, d1 = a//b, a1//b1 +def strhash(s): + # Python 2.x string hash algorithm + if s == '': + return 0 + x = ord(s[0])<<7 + for c in s: + x = ((1000003*x) ^ ord(c)) & 4294967295 # 0xffffffff + return x^len(s) +''' + +operators = { + '<': 1, + '<=': 1, + '==': 1, + '!=': 1, + '>': 1, + '>=': 1, + '|': 2, + '^': 3, + '&': 4, + '<<': 5, + '>>': 5, + '+': 6, + '-': 6, + '*': 7, + '/': 7, + '//': 7, + '%': 7, + '**': 8, +} + +dispatch = { + '<': lambda x, y: x < y, + '<=': lambda x, y: x <= y, + '==': lambda x, y: x == y, + '!=': lambda x, y: x != y, + '>': lambda x, y: x > y, + '>=': lambda x, y: x >= y, + + '|': lambda x, y: x | y, + '^': lambda x, y: x ^ y, + '&': lambda x, y: x & y, + '<<': lambda x, y: x << y, + '>>': lambda x, y: x >> y, + + '+': lambda x, y: x + y, + '-': lambda x, y: x - y, + + '*': lambda x, y: x * y, + '/': lambda x, y: x / y, + '%': lambda x, y: x % y, + '//': lambda x, y: x // y, + + '**': lambda x, y: x ** y, + } + +class DoReturn(Exception): + def __init__(self, value=None): + self.value = value + +class DoBreak(Exception): + pass + +def eval(body, globals, locals): + for stmt in body: + stmt.eval(globals, locals) + +def geneval(body, globals, locals): + for stmt in body: + for value in stmt.geneval(globals, locals): + yield value + +def isgenerator(body): + for stmt in body: + if stmt.isgenerator(): + return True + return False + +class Dict(dict): + + def __repr__(self): + keys = self.keys() + keys.sort() + L = [] + for key in keys: + L.append(repr(key) + ": " + repr(self[key])) + return "{" + ", ".join(L) + "}" + +class Function(object): + makeLocals = Dict + def __init__(self, name, args, body, globals): + self.name = name + self.args = args + self.body = body + self.globals = globals + def __call__(self, *args): + check(len(args), len(self.args)) + locals = self.makeLocals(zip(self.args, args)) + try: + eval(self.body, self.globals, locals) + except DoReturn, exc: + return exc.value + +class Generator(Function): + def __call__(self, *args): + check(len(args), len(self.args)) + locals = self.makeLocals(zip(self.args, args)) + try: + for value in geneval(self.body, self.globals, locals): + yield value + except DoReturn, exc: + if exc.value is not None: + raise RuntimeError("'return' with argument in generator") + return + +class Node(object): + def isgenerator(self): + return False + def geneval(self, globals, locals): + self.eval(globals, locals) + if False: + yield None +class Define(Node): + def __init__(self, name, args, body): + self.name = name + self.args = args + self.body = body + def __repr__(self): + return "%s(%r, %r, ...)" % (self.__class__.__name__, + self.name, self.args) + def eval(self, globals, locals): + if isgenerator(self.body): + obj = Generator(self.name, self.args, self.body, globals) + else: + obj = Function(self.name, self.args, self.body, globals) + globals[self.name] = obj +class For(Node): + def __init__(self, var, seq, body): + self.var = var + self.seq = seq + self.body = body + def __repr__(self): + return "%s(%r, %r, ...)" % (self.__class__.__name__, + self.var, self.seq) + def eval(self, globals, locals): + for value in self.seq.eval(globals, locals): + self.var.assign(value, globals, locals) + try: + eval(self.body, globals, locals) + except DoBreak: + break + def geneval(self, globals, locals): + for value in self.seq.eval(globals, locals): + self.var.assign(value, globals, locals) + try: + for v in geneval(self.body, globals, locals): + yield v + except DoBreak: + break +class While(Node): + def __init__(self, test, body): + self.test = test + self.body = body + def __repr__(self): + return "%s(%r, ...)" % (self.__class__.__name__, self.test) + def isgenerator(self): + return isgenerator(self.body) + def eval(self, globals, locals): + while self.test.eval(globals, locals): + try: + eval(self.body, globals, locals) + except DoBreak: + break + def geneval(self, globals, locals): + while self.test.eval(globals, locals): + try: + for value in geneval(self.body, globals, locals): + yield value + except DoBreak: + break +class If(Node): + def __init__(self, test, body, elsebody=None): + self.test = test + self.body = body + self.elsebody = elsebody + def __repr__(self): + return "%s(%r, ...)" % (self.__class__.__name__, self.test) + def isgenerator(self): + return isgenerator(self.body) or (self.elsebody is not None and + isgenerator(self.elsebody)) + def eval(self, globals, locals): + if self.test.eval(globals, locals): + eval(self.body, globals, locals) + elif self.elsebody is not None: + eval(self.elsebody, globals, locals) + def geneval(self, globals, locals): + if self.test.eval(globals, locals): + for value in geneval(self.body, globals, locals): + yield value + elif self.elsebody is not None: + for value in geneval(self.elsebody, globals, locals): + yield value +class Return(Node): + def __init__(self, expr=None): + self.expr = expr + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.expr) + def eval(self, globals, locals): + if self.expr is None: + value = None + else: + value = self.expr.eval(globals, locals) + raise DoReturn(value) +class Yield(Node): + def __init__(self, expr): + self.expr = expr + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.expr) + def isgenerator(self): + return True + def geneval(self, globals, locals): + if self.expr is None: + value = None + else: + value = self.expr.eval(globals, locals) + yield value +class Break(Node): + def __repr__(self): + return "%s()" % (self.__class__.__name__,) + def eval(self, globals, locals): + raise DoBreak() +class Print(Node): + def __init__(self, exprs): + if not isinstance(exprs, list): + exprs = [exprs] + self.exprs = exprs + def eval(self, globals, locals): + for e in self.exprs: + print e.eval(globals, locals), + print +class Assign(Node): + def __init__(self, lhs, expr): + self.lhs = lhs + self.expr = expr + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, self.lhs, self.expr) + def eval(self, globals, locals): + value = self.expr.eval(globals, locals) + for v in self.lhs: + v.assign(value, globals, locals) +class Exprs(Node): + def __init__(self, exprs): + self.exprs = exprs + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.exprs) + def eval(self, globals, locals): + return tuple([e.eval(globals, locals) for e in self.exprs]) + def assign(self, value, globals, locals): + if len(self.exprs) != len(value): + raise TypeError("multi-assign length mismatch") + for e, v in zip(self.exprs, value): + e.assign(v, globals, locals) +class Binop(Node): + def __init__(self, left, op, right): + self.left = left + self.op = op + self.right = right + self.opeval = dispatch[self.op] + def __repr__(self): + return "%s(%r, %r, %r)" % (self.__class__.__name__, + self.left, self.op, self.right) + def eval(self, globals, locals): + return self.opeval(self.left.eval(globals, locals), + self.right.eval(globals, locals)) +class Attribute(Node): + def __init__(self, expr, name): + self.expr = expr + self.name = name + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, self.expr, self.name) + def eval(self, globals, locals): + v = self.expr.eval(globals, locals) + return getattr(v, self.name) +class Index(Node): + def __init__(self, expr, index): + self.expr = expr + self.index = index + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, self.expr, self.index) + def eval(self, globals, locals): + v = self.expr.eval(globals, locals) + return v[self.index.eval(globals, locals)] + def assign(self, value, globals, locals): + v = self.expr.eval(globals, locals) + v[self.index.eval(globals, locals)] = value +class Call(Node): + def __init__(self, expr, args): + if not isinstance(args, list): + args = [args] + self.expr = expr + self.args = args + def __repr__(self): + return "%s(%r, %r)" % (self.__class__.__name__, self.expr, self.args) + def eval(self, globals, locals): + f = self.expr.eval(globals, locals) + args = [a.eval(globals, locals) for a in self.args] + return f(*args) +class Literal(Node): + def __init__(self, literal): + self.literal = literal + self.value = self.evalit() + def eval(self, globals, locals): + return self.value + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.literal) +simple_escapes = {"a": "\a", + "b": "\b", + "f": "\f", + "n": "\n", + "r": "\r", + "t": "\t", + "v": "\v", + "'": "'", + '"': '"', + "\\": "\\"} +class String(Literal): + def evalit(self, octals='01234567'): + s = self.literal[1:-1] + if '\\' not in s: + return s + L = [] + it = iter(range(len(s))) + for i in it: + c = s[i] + if c != '\\': + L.append(c) + else: + i = it.next() + c = s[i] + if c == 'x': + if i+2 >= len(s): + raise ValueError("incomplete \\x escape in string") + d1 = s[it.next()] + d2 = s[it.next()] + L.append(chr(int(d1+d2, 16))) + elif c in octals: + if i+1 < len(s) and s[i+1] in octals: + c += s[it.next()] + if i+2 < len(s) and s[i+2] in octals: + c += s[it.next()] + L.append(chr(int(c, 8))) + else: + L.append(simple_escapes.get(c, '\\' + c)) + return "".join(L) +class Number(Literal): + def evalit(self): + return int(self.literal) +class Name(Node): + def __init__(self, name): + self.name = name + def __repr__(self): + return "Name(%r)" % self.name + def eval(self, globals, locals): + if self.name in locals: + return locals[self.name] + if self.name in globals: + return globals[self.name] + if self.name == 'ord': + return ord + if self.name == 'len': + return len + raise NameError(self.name) + def assign(self, value, globals, locals): + locals[self.name] = value + +class Parser(object): + def __init__(self, scanner): + self.scanner = scanner + self.nexttoken() + def nexttoken(self): + self.token, self.value = rv = self.scanner.next() + ##print rv + return rv + def expect(self, token, value=None): + if self.token != token: + raise SyntaxError + if value is not None and self.value != value: + raise SyntaxError + value = self.value + self.nexttoken() + return value + def parse(self): + stmts = [] + while self.token != EOF: + stmts.append(self.parse_stmt()) + return stmts + def parse_stmt(self, + keywords=('def', 'for', 'while', 'if', + 'print', 'return', 'yield', 'break')): + if self.value in keywords: + return getattr(self, 'parse_' + self.value)() + else: + return self.parse_simple() + def parse_def(self): + self.expect(NAME, 'def') + name = self.expect(NAME) + self.expect(OPERATOR, '(') + args = [] + if self.value != ')': + args.append(self.expect(NAME)) + while self.value == ',': + self.nexttoken() + args.append(self.expect(NAME)) + self.expect(OPERATOR, ')') + self.expect(OPERATOR, ':') + self.expect(NEWLINE) + body = self.parse_body() + return Define(name, args, body) + def parse_for(self): + self.expect(NAME, 'for') + var = self.parse_expr() + self.expect(NAME, 'in') + seq = self.parse_expr() + self.expect(OPERATOR, ':') + self.expect(NEWLINE) + body = self.parse_body() + return For(var, seq, body) + def parse_while(self): + self.expect(NAME, 'while') + test = self.parse_expr() + self.expect(OPERATOR, ':') + self.expect(NEWLINE) + body = self.parse_body() + return While(test, body) + def parse_if(self): + self.expect(NAME, 'if') + test = self.parse_expr() + self.expect(OPERATOR, ':') + self.expect(NEWLINE) + body = self.parse_body() + if self.value != 'else': + elsebody = None + else: + self.expect(NAME, 'else') + self.expect(OPERATOR, ':') + self.expect(NEWLINE) + elsebody = self.parse_body() + return If(test, body, elsebody) + def parse_body(self): + self.expect(INDENT) + body = [self.parse_stmt()] + while self.token != DEDENT: + body.append(self.parse_stmt()) + self.expect(DEDENT) + return body + def parse_print(self): + self.expect(NAME, 'print') + exprs = self.parse_exprs() + self.expect(NEWLINE) + return Print(exprs) + def parse_return(self): + self.expect(NAME, 'return') + if self.token == NEWLINE: + e = None + else: + e = self.parse_exprs() + self.expect(NEWLINE) + return Return(e) + def parse_yield(self): + self.expect(NAME, 'yield') + e = self.parse_exprs() + self.expect(NEWLINE) + return Yield(e) + def parse_break(self): + self.expect(NAME, 'break') + self.expect(NEWLINE) + return Break() + def parse_simple(self): + e = self.parse_exprs() + if self.value == '=': + lhs = [] + while self.value == '=': + self.nexttoken() + lhs.append(e) + e = self.parse_exprs() + self.expect(NEWLINE) + return Assign(lhs, e) + else: + self.expect(NEWLINE) + return e + def parse_exprs(self): + e = self.parse_expr() + if self.value != ',': + return e + exprs = [e] + while self.value == ',': + self.nexttoken() + exprs.append(self.parse_expr()) + return Exprs(exprs) + def parse_expr(self, prio=0): + left = self.parse_term() + while self.value in operators and operators[self.value] > prio: + op = self.expect(OPERATOR) + right = self.parse_expr(operators[op]) + left = Binop(left, op, right) + return left + def parse_term(self): + t = self.parse_atom() + while self.value in ('.', '[', '('): + if self.value == '.': + self.nexttoken() + name = self.expect(NAME) + t = Attribute(t, name) + elif self.value == '[': + self.nexttoken() + index = self.parse_exprs() + self.expect(OPERATOR, ']') + t = Index(t, index) + elif self.value == '(': + self.nexttoken() + if self.value == ')': + args = [] + else: + args = self.parse_exprs() + if isinstance(args, Exprs): + args = args.exprs + self.expect(OPERATOR, ')') + t = Call(t, args) + else: + raise AssertionError("shouldn't get here") + return t + def parse_atom(self): + if self.value == '(': + self.nexttoken() + exprs = self.parse_exprs() + self.expect(OPERATOR, ')') + return exprs + if self.token is STRING: + return String(self.expect(STRING)) + if self.token is NAME: + return Name(self.expect(NAME)) + if self.token is NUMBER: + return Number(self.expect(NUMBER)) + raise SyntaxError + +class List(list): + __setitem__ = list.__setitem__ + __getitem__ = list.__getitem__ + +class Str(str): + __getitem__ = str.__getitem__ + +class OutputFile(object): + def __init__(self): + self.data = [] + self.softspace = True + reset = __init__ + def write(self, s): + self.data.append(s) + def getvalue(self): + r = "".join(self.data) + self.data = List() + return r + +output = OutputFile() + +def cleanup(s): + s = str(s).replace('<__main__.', '<').replace('<b0.', '<') + i = s.find(' at 0x') + while i > 0: + j = s.find('>', i+6) + if j < 0: + break + digits = s[i+4:j] + try: + number = int(digits, 0) + except ValueError: + break + else: + s = s[:i+5] + s[j:] + i = s.find(' at 0x') + return s + +def write(s): + s = cleanup(s) + if __debug__: + print s, + print >>output, s, + +def writeln(s=''): + write(str(s) + '\n') + +def myhash(s, ord=ord): + if not s: + return 0 + x = ord(s[0])<<7 + for c in s: + x = ((1000003*x) ^ ord(c)) & 0xffffffffL + return x^len(s) + +def checkoutput(n=0): + outputtext = output.getvalue() + check(strhash(outputtext), n) + +strhash = myhash + +indent = "" + +def instrumentClass(cls): + cname = cls.__name__ + '.' + for name in cls.__dict__: + if name == '__dict__': + continue + descr = cls.__dict__[name] + if hasattr(descr, '__get__'): + setattr(cls, name, instrumentDescriptor(cname+name, descr)) + +def unInstrumentClass(cls): + for name in cls.__dict__: + descr = cls.__dict__[name] + if isinstance(descr, instrumentDescriptor): + setattr(cls, name, descr.obj) + +class instrumentDescriptor(object): + def __init__(self, name, obj): + self.name = name + self.obj = obj + def __get__(self, *args): + result = self.obj.__get__(*args) + if not hasattr(result, '__call__'): + return result + return instrumentCall(self.name, result) + +class instrumentCall(object): + def __init__(self, name, obj): + self.name = name + self.obj = obj + def __call__(self, *args): + global indent + oldindent = indent + try: + indent = indent + " " + argreprs = map(repr, args) + for i, s in enumerate(argreprs): + s = cleanup(s) + if len(s) >= 45: + s = s[:20] + "..." + s[-20:] + argreprs[i] = s + writeln(indent + "%s(%r)" % (self.name, ", ".join(argreprs))) + try: + result = self.obj(*args) + except Exception, exc: + writeln(indent + "raise %r" % (exc,)) + raise + else: + if result is None: + writeln(indent + "return") + else: + writeln(indent + "return %r" % (result,)) + return result + finally: + indent = oldindent + +def instrumentTree(base): + instrumentClass(base) + for cls in base.__subclasses__(): + instrumentTree(cls) + +def unInstrumentTree(base): + unInstrumentClass(base) + for cls in base.__subclasses__(): + unInstrumentTree(cls) + +def main(): + output.reset() + + s = Scanner(getcFromString(sample).next) + it = Clone(s.tokenize()) + it2 = Clone(it) + L = [] + for pair in it: + L.append(pair) + L2 = list(it2) + check(L, L2) + + scanner = Scanner(getcFromString(sample).next).tokenize() + parser = Parser(scanner) + instrumentClass(Parser) + root = parser.parse() + + checkoutput(1413352820) + + env = Dict() + eval(root, env, env) + g = env['pi']() + for i in range(1000): + write(g.next()) + writeln('') + strhash = env['strhash'] + + for x in '', 'x', 'abc', 'abc'*100: + check(strhash(x), myhash(x)) + + strhash = myhash + checkoutput(3960406533) + + it = Clone(getcFromString(unicode(sample, "utf8"))) + it2 = Clone(it) + scanner = Scanner(it.next).tokenize() + parser = Parser(scanner) + root = parser.parse() + checkoutput(3827423707)#checkoutput(1308798191) + env = Dict() + eval(root, env, env) + g = env['pi']() + for i in range(1000): + write(g.next()) + writeln() + checkoutput(3960406533) + + instrumentTree(Node) + scanner = Clone(Scanner(it2.next).tokenize()) + scanner2 = Clone(scanner) + parser = Parser(scanner) + root = parser.parse() + checkoutput(3257889492) + env = Dict() + eval(root, env, env) + g = env['pi']() + digits = [] + for i in range(10): + digits.append(g.next()) + checkoutput(2705414689)#checkoutput(3259608361) + print "".join(map(str, digits)) + + unInstrumentTree(Node) + unInstrumentClass(Parser) + parser = Parser(scanner2) + root = parser.parse() + checkoutput(0) + env = Dict() + eval(root, env, env) + g = env['pi']() + digits = [] + for i in range(10): + digits.append(g.next()) + print "".join(map(str, digits)) + out2 = output.getvalue() + checkoutput(0) + + class TrackingDict(Dict): + def __setitem__(self, *args): + writeln("%s = %.50r" % args) + super(TrackingDict, self).__setitem__(*args) + Function.makeLocals = TrackingDict + g = env['pi']() + digits = [] + for i in range(100): + digits.append(g.next()) + checkoutput(902386495) + Function.makeLocals = Dict + +if __name__ == '__main__': + main() Added: trunk/sandbox/tobias/tests/parrotbench/b1.py =================================================================== --- trunk/sandbox/tobias/tests/parrotbench/b1.py (rev 0) +++ trunk/sandbox/tobias/tests/parrotbench/b1.py 2009-04-01 01:45:35 UTC (rev 6145) @@ -0,0 +1,37 @@ +def depth0(n): + try: + n = depth0(n+1) + except RuntimeError: + pass + return n + +def depth1(n, pea): + p = (pea, pea) + for i in xrange(n): + p = (p, pea) + try: + n, p = depth1(n+1, p) + except RuntimeError: + pass + return n, p + +def main(): + print depth0(0) >= 996 + pea = [] + base, p = depth1(0, pea) + print base >= 996 + pea.append(p) + while p[1] is not pea: + q = p[1] + n = 0 + while p[1] is q: + n += 1 + p = p[0] + if n != base+1: + raise RuntimeError, (n, base) + base -= 1 + print base + del pea[:] + +if __name__ == '__main__': + main() Added: trunk/sandbox/tobias/tests/parrotbench/b2.py =================================================================== --- trunk/sandbox/tobias/tests/parrotbench/b2.py (rev 0) +++ trunk/sandbox/tobias/tests/parrotbench/b2.py 2009-04-01 01:45:35 UTC (rev 6145) @@ -0,0 +1,43 @@ +def izip(*args): + args = map(iter, args) + while 1: + yield tuple([x.next() for x in args]) + +class PI(object): + def __iter__(self): + k, a, b, a1, b1 = 2, 4, 1, 12, 4 + while 1: + p, q, k = k*k, 2*k+1, k+1 + a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1 + d, d1 = a//b, a1//b1 + while d == d1: + yield d + a, a1 = 10*(a%b), 10*(a1%b1) + d, d1 = a//b, a1//b1 + self.a1 = a1 + +tests = { + 99: 44251238236192885942548145627920559612834490019477028496725657079267312460031559302172150714110203307954379217477379106929168768496503354540899921113305213841256909892518928098307564463751633347248940009920269109969147590732355948788056064000000000000000000000000000000000, + 199: 1000596230862142822590229503409372398669386421051058756167623955196210292140473223995201364067656314884093070923379776058593112593572415388874119773448702613069929696236969954099574382312021625484547051647005317079077091903572365445691946982207111619679684359784089545801152269560862321544414943514190096631259179363627029133476495865659666812167626608236901769581685802712761140555948794720353924341042650072696819415055421183957924869318180281662429407332762869255321912813711898750492786968744984544308467386273640507277517829133760299081875243110913120665600000000000000000000000000000000000000000000000000000000000000000, + 299: 21435887192948215614003242240833359745116667655295850182859413191163731683078952650094326080502769326477126925083216343548170734614172935170340269921309820711302999200539819947867212813551107194027554006207604344128185286047718105667902068109038526051946371288160859880626765253522805513232333491975220030085760604224065673379016506268781757490866758397031010384977255107445504115787686395015630645137203786798858795200871880590717053675063928230569710372699708910775901232998621866511805494494875255496291270721486641615650345940568291905806263698337995119757061129615716444504290546816572960918445558805410505143000167480199333531897643812998836381668261331434305825321676717544726859895857274900170645624087291170408290210800888136650695682668742663263729788760787553650802761860581841523193434651375248115751262481847514479478467508156570863734207165375573520453327647345580868727572348946580766720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + 399: 8561869806834798989612544773400323313179941907807794568262440743112858898989689026704576126118595731944427372856665962019724479801384062969795859298394962551328689077803363555807984316902252940902014889926277022833163566635584197843427728248130112186455323888931447608868707068434776186855353396855833436850229162071581300162579548898284489248532968742303181986647234058212952485789589428331561779973912890270787218670895308761530690791268509970600822462460658693835169935042766248145148420454545182598329186640466821688459819069501551463819641554408111110110151692239551586768176506251155525099233988638762885805917822379263713549352362861698409524070686169569736102177070749091831233867352657647277185192372387156966362270318951122024815096048593017226290871189781143762422618457018186519922454408157004798904710507709224018924427721086955924703838793251170380074666507887931281809304737450536142489860864008197549841329444837980614206463968734383477281485253049376604442937718053220015067951581390345559841730246517326234188422995410478560583662283465682728995404843025593838691776410644612449087517702830166590175727603809091974002341560317871295071902646575676785149353532452189474547463794343581915053692213809212940949327454179290314595392041251528682462248960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + 499: 76766108631940210937325132198465864457610296920889901883030849944249491732767613231460026747961565950406551576277982908797232709115573397680840144587889878137072051513231549168224623486940739011824470282874235014299280185292476357855772342908560617765615433859648152443400651562464645577267133565969609608350684571285655853054712724572601634219899681603288076555568556603519768176952205317390973803424356164269999588467102540378584128532600037700811666341008358928602746642205050531572408717173194538376392544677893444983399212894400285344939556094505296780409965886324800278706769664438849417755796690865276144102933659458633433715362955199895852120250371111523601408509601075849463319256275384860431711268141908667883149791804139967338545358206127158990156425480764804297397170597657279674744907448120365194723760375846968550637839625396799787981542068069955660525855300927415620426941417314885401820985001913260101401230309399239801959598342546866307638278153091955749126275448041244876145703346573865766318100310570772620069178810413227974410262538853025115028173981758758325369986648321051017250246765567173447382346682177940131720445933725662183060319023268847648849199144024316405375647697684691770109145226746285626861260128121857903981514928439560981950894568063766637808949718925624322085933716705575498276564370619232206346293654148202964613950060056885972213718288213503135634713342418000998239413319648014225323725957085146390629354204147053598603318165064363587092287902579232811848133423379877761425679796787506376625832936596918827500201870173625427859893528696839243761272981017048564872611531028386533983068887010900245332623360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + 599: 2120272365916624093549573503339645760249925590629691905298380620826238336680485250775748238851715242513568106491781607325637843266230182543159994052803483210198817868787245904539293723939615230218367927170630181008508608682473786334989642773309671087946382125393064054429291378005365307369932354974406782493586482693959468507929142578311374952191246685196652549840632791830721769718961140786765636611636126263231624375986806336404014991356931344468888703169171934706250411475009307785661110741777527324954571089817794240318090318731138065871311050896639596947512824176632981670282022349794742982306588866780679141100000979482012703431996529614153969006965379857532250140411692707925832547131496348527554204126276904033851312192294719407040113066259294928824359144110570802157647067643172691886034509485269315724734491380423529629749223874238867299576969461404272650055836211201773406419214625694511195241201118512536217548368603119794507877569790693417734860149658615068452866115479874379764219274786787905887717695084355702688921163181942859261931462396527992761425892799259213253073620895655262890187342553757398412577032172382168869416402722279336223791913538036339921582169629706204936615017408331600286347593291767969984872197163003714688529499720018226023559039421196525971154371211007274491079331581462202803270308044945895467086216358487714539723075423709132632711104176237158591348264918119231549610638101215271635751068862184966089290055162842592702917037089658541420657556777630476720227083286444062812384078931053717097690428021828828314330897267550018034334466896893522629282170940447351039396227633740743904716345874216287187030893375694818646093977919289909500326805873535353890952168548557367192114315242338374030375201461534835392764765715654233759268109399742689152068054720118040413609079726305828412608467329058007828176699982184798481881032984952414016677410029974950886156526807807461864142760141455419659333722571838033134676308170730229830331659493070917764742995587861083129433623003009634591950055674021412864000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + 699: 54571787430958399400005671895793395810514965360222657069233155257869831245514703898329984842599345345797192550495348877752750716462799995262238897879189712362792599540276947290240369738995122870036473426596166137781512133732841079442335809215673962548136751501962395101508082458022910749004870763777751025686143054266560789699467897488208314352497922931109255090615845989365253963697070552088326927571730238674587343725408556548847027815257453311184273200959063948470485405418687785822617652671609706936044865165112267634536255942342137737568633616435112070199187087675353099732490445262584463118808715533880843287282323502172455874549895164201021082781039664171931972950867328706112021059604060340338606871763348783573247509755207096610318069014034226371127241365822041636184401808035853347524245498756203483212762819194058857286022123510755206330238728338540936417830717262921800876426685863489447721974523840880601732138137563579815785444094205972614263669956513740906383728059662729451143837852557411654864608820606495589950458165214874335528071914274226508583618548221498046257433189345079263951024381261213067438755400772554918420156611989161275819373340626340095277962552853128100524758416265525218190626769969209796740560920753972479878773975562043659464796071536492340776053077906431346958246988865607675041671683462291933241209943247185229400300531069434821908210393754215270727867860747889887039965048681895147820192799637449521165944356200714071125353390157596677223069290303004608406259263260481747075716421783084148765931010321931117509077808771925529544210503591442107960112359151446110353540208471607107935843590192610650273333834161753099980189676608843057569018657095864002224328579690446259626925339472680838762568611923981193711770106009098171810029820020455115170724929203588390317815053369572788421300357832205199443876759544538582639402241883694827090801385537555747373037489025563879252287165075989079784157761408131323383708336366882662138204724992104184118234360573248835518448645547172342375665655653335218281979099552819760633230580536381778069677840715358530867566196795457417775340310424672192141977398974880862555283206621628790868960591215870136675469162920111812154003932444777532696287441691534774646863311895804406055064912499462089287403059782748799895590902455779428144219297715674077436643273687702239680646741926247202392605642085420467071089682849156330161168666278561180452156752478501391564800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + 799: 1165019969951028145448474870606694745628445847100063691175045426809524271280385211025149309439736889668431363205043295468478227885516089826430304252028412665878074268391689531376676369814346541259212014204219732753532556283167763492813491981617042686520428375483043823229347180225027527767892288494222400268347648277077085092324780438909293027666621101974271603717458184633691745699246613625445708958093814173789616468299755424767037016330877693069425266688538600904598289113523091543776886739998104937757229618512461155015780709364046160704463608630709906484636013448672656426886594747044346764985843639265457373603772739772415706169602575546300922342271055004256781082363315561913547648640954959000371679492600850323235849380042831378495135583566599574416729516620087245906062795758387578224336805373895492794645806096068657974185136831114580747646909717985162654700150389838526549868770885629372149350446773860669388038471776557526515910033467628431871878316408982723876203877207112913665539371348724351835198296871265983857890498623536324848877236019869092878781427110113542625110041789002286754615039920319343770043455657828924442170211652589212117516714709894518726603532996156030790024814913146519305169722564850597797774298352669973544466122022123500758687471133096300448171087716127901248915474363042779227724255413335477296839171260050411230913787907606725169016351209025747882086625397286625248376528998919634710302520393941530723973487259019187136668425367426482695231240294671376146585312211926447150542843171266291876037378067256463777431998792250381914496818845072319002851834894280540179694233589184751221721345515353061996569633890293841751623667699605067183984407638732497881628999347219982736106675680165842644133894916782230987223224828685930858657631697327168501437432678530579280064943872275218623486567776580213001821563007802859121520206862366831214550454660201924592069971928484116327345227633650931220240412989380696156101840018564700065411677388328804161110162279193672651278988425644004188569635636717470803677943610275223854671409519817008772946235477341217799495629951132446716193818794636841421507151304976152511616538200203214016457449981017869162192339882870379247422061597402496664647115346984746108902369843975335083490551753570803795438395111351577474760022446140821780548147639308232794984562286077490121188360571079033300272391145791202144846667875284539709679647945779713567130240017333648976286204155043105228295725874012316502327195124092416348347162737242449541649547547864777887315161229040122603297586496999009079092644539172087825680666618082263897443172558909377634579572489890372823889386192559147381373832288039653312458442917119615324859008094386594830981911977813106096806546361863080294950465184145762955879704231094550954751577536624215411479046060449038350499002129406780206980907086223769600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + 899: 1961047400783793689152743738482061418112144594775859100963826903299941791245038595034363753615746408049289952725779309407444199325053710536522401903643581802543713504158806047235695705896380364921365885372696677158825553172792575130365677811577035805389273355225725863414284665498055318575649394451227797767110728923709058788425788790167032831982217805891947591307310391793051324726126078967699521915868839204118521519682024094610098117626863292184721906092521438801341497303557767071828077146885364536554032450624100316867547877010778603956083487035270791818649067384276377414249363983383717773036457804718062695046059095787213719308297709919175747285036636352990899483938970896812239613605956608649083554411609657838220544027128950682327843798882711829991989817881303883990647876969994768271897974773455464646523348820392471256024577102382204328939384060235197563409904986708133897802121211859685551906620747824874847127776411443039694389051592145124635490844378130255642752765693890407120283111284316765000645749180288822505352501861257195960128525960418404774436619529817773459198268065709767064598308082608109337158602927125644880036055446842995394476366770872364117175239884406760485305848864493739499504392963295387516098554438251252486287315978444632100288391159069513665622892184147377430660017269064216314044538754986908504965776567592061950572488346266774840439392992871099154439658791611017807192708601473794082677034875991711712839230126426791071352984543648012937947037753575375040046764495862676093683555226439651695465214815214564045671683209573744703248122302073524235222782011551736047484049940566608761314884952385623657426286984431299387264223494331247251695035920997630045288051985796581735253031855095734994702323372767680434320372371358208514386161807824094211406017077057681618563506824462507672499213262962050653636150604636813302357401076353456780306366770399402263353459513732101609057936629596760862766436204974584026785745826067150601651416509653311312257323521470962454567693169469818165574943846754385013710385609445073226065759614555740278029180864101039640157003847772681461933766608520730602890319871123179941870008811420475967031993019721292183133758093949406939652398599519672662411049142220315039805474111098855767170048770783560759174013367296946638271656238787420981851702619053744806332012493178141602213898668388712998512756036771357385206948329239298807516694953814693720048229647293048056331265195037121054022115441868442670280473506498551412297880384312473713380564764159899942048060356745863908010902230964075673990385182437331505988923117412916700150241837983775128046411352228138119876809545584444570443347872856695813698044037133648970190072128464354669077148179236958137004869599834164764747494805309536229934978506910688264436888356383974787838537387187841566823557909442831563769727985839249267304457033791105118767948473474042809317178565809335268316324420040570235176099114072999727457879465811886218940986224633055296998229833996940360896329868864364653862830780554332074293100857235815847819975826812991652016737242925678140172314816371649578265526072666356756752517107018796020915298198762366163369556351250086487862926783601433251979292229580324497550784524234395521051827588464289592550437275513651200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + 999: 5142120423742675471974126287955809574535357068046529599000560728039399275930931304341705443290300229914422726794668177537968264648144118498487805119226260378528650131991088676902836811857270541513296947526699705880730381294593006898814262085704336473825201541006210955753704810537413120555128907013106764170210420629126960215958541001171658832595950907229541457834088209412944936905053972218397142776849344658277652614892680821674419697222923130014645284479895717056274392491034125201955158674450551217874664620940928171427683754069233736509184926590369183895070592006924781272099864100239363770546451883318349964152398948931966679860602627409906331644763679137682497780242630009822921710929339761344862731457826420617686381968911400073392366124777065987424836126250033579686085082101266467177145863298853308178221540976580228331239763953108737488691493181833643401836558191778626398618442140468218270066858025640661491000558898610528392279711579575345703200785278416348411772675840280709593777527474095922179716471353719960201704105588347086479022160191444830756096400533705391196695396662879167956803453360810349846148441318082659273788717329596246494808484632922731776348571012795857047452180584628986442772443700080676049673819149856254912408951932826185765196259801406717427502413558108931158666261380067455659044728430258922799402098021392057660641081228877422498521314624574441740894508178111385410004911439667702696237159978509689180822381441616419582068514764153876222307554547594732358511527444499897458759372982433792122654903561638842618444515784825627448071849634297643169362409668516222758076203698145001415117323006038425703965914796426427671784982873817168224589258130683058917988733709001146483964613456875437013984505541825689086094075705760437211402385873368677829365976836468858431398089165749482066656712849497341765168981001121722892025503801609269782750165912686412855279381595779876529427944264414478121201023565907692108302876619530698352008605101070206468704706785269261493986427523865931377207048551250785411318329249855779517786463477651967611696076738366693440412084695489984239864456563532165840963582864286049480561230753012702462130127137450345350359359867882547235683710571018784016493910038168014978153353097170254842715035335189179028979337119830781198392063337314155334478636683363262982739406004002266047843272582071916617807353681712781581451680468476890933136639338084566580809048080468359779806934561186367642359343545836729611491944504786419220499142487390760086756065236043333233346060550395020264308177305185193132970079897858502314955851005175681382393415134546851874491465839660269856799739588390788616285622308116117137884072465953587955513347680498150094614231017861871571733053758969929765508087588060032519546969078084262395141708005237055101766716471322442729268007817300289076611523200827716220759305897838985100568942910630581392931521412710812611627780351475138825434194100790648741408739165327268324724814490022832365413572546951682824848375315512140247418809107217287405055515586541323054413736009057491568285635589733988075995955259789133788061014117612372700229521937709121536568616897024085971931708565098241621955888612739889590429896488315826527248677547766604473044643680531889217189519948956302468329241617445146397986279285610720245607340812533508949433972935867033257871847610121142227746914970178327007585588874258396444641885137938545... [truncated message content] |