cvsuser     05/01/02 16:20:10

  Modified:    .        MANIFEST
               dynclasses pybuiltin.pmc pyclass.pmc pyconsts.h pygen.pmc
                        pyint.pmc pylist.pmc pyobject.pmc pyproxytype.pmc
  Added:       languages/python/t/pie b0.t
  Log:
  Progress towards t/pie/b0.t
  
  Revision  Changes    Path
  1.816     +1 -0      parrot/MANIFEST
  
  Index: MANIFEST
  ===================================================================
  RCS file: /cvs/public/parrot/MANIFEST,v
  retrieving revision 1.815
  retrieving revision 1.816
  diff -u -r1.815 -r1.816
  --- MANIFEST  28 Dec 2004 07:18:27 -0000      1.815
  +++ MANIFEST  3 Jan 2005 00:20:07 -0000       1.816
  @@ -2361,6 +2361,7 @@
   languages/python/t/basic/oo_attr.t                []
   languages/python/t/basic/oo_class.t               []
   languages/python/t/basic/iter.t                   []
  +languages/python/t/pie/b0.t                       []
   languages/python/t/pie/b1.t                       []
   languages/python/t/pie/b2.t                       []
   languages/python/t/pie/b3.t                       []
  
  
  
  1.39      +5 -1      parrot/dynclasses/pybuiltin.pmc
  
  Index: pybuiltin.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/dynclasses/pybuiltin.pmc,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- pybuiltin.pmc     30 Dec 2004 11:46:38 -0000      1.38
  +++ pybuiltin.pmc     3 Jan 2005 00:20:08 -0000       1.39
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: pybuiltin.pmc,v 1.38 2004/12/30 11:46:38 rubys Exp $
  +$Id: pybuiltin.pmc,v 1.39 2005/01/03 00:20:08 rubys Exp $
   
   =head1 NAME
   
  @@ -88,6 +88,7 @@
               PyBuiltin_PyDict       = Parrot_PMC_typenum(INTERP, "PyDict");
               PyBuiltin_PyException  = Parrot_PMC_typenum(INTERP, 
"PyException");
               PyBuiltin_PyFloat      = Parrot_PMC_typenum(INTERP, "PyFloat");
  +            PyBuiltin_PyGen        = Parrot_PMC_typenum(INTERP, "PyGen");
               PyBuiltin_PyInt        = Parrot_PMC_typenum(INTERP, "PyInt");
               PyBuiltin_PyIter       = Parrot_PMC_typenum(INTERP, "PyIter");
               PyBuiltin_PyList       = Parrot_PMC_typenum(INTERP, "PyList");
  @@ -108,6 +109,7 @@
               PyString_call  = const_string(INTERP, "__call__");
               PyString_cmp   = const_string(INTERP, "__cmp__");
               PyString_hex   = const_string(INTERP, "__hex__");
  +            PyString_hash  = const_string(INTERP, "__hash__");
               PyString_init  = const_string(INTERP, "__init__");
               PyString_int   = const_string(INTERP, "__int__");
               PyString_iter  = const_string(INTERP, "__iter__");
  @@ -117,6 +119,8 @@
               PyString_proxy = const_string(INTERP, "__proxy__");
               PyString_repr  = const_string(INTERP, "__repr__");
               PyString_str   = const_string(INTERP, "__str__");
  +
  +            PyString_next  = const_string(INTERP, "next");
           }
       }
   
  
  
  
  1.20      +36 -3     parrot/dynclasses/pyclass.pmc
  
  Index: pyclass.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/dynclasses/pyclass.pmc,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- pyclass.pmc       23 Dec 2004 23:49:32 -0000      1.19
  +++ pyclass.pmc       3 Jan 2005 00:20:08 -0000       1.20
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: pyclass.pmc,v 1.19 2004/12/23 23:49:32 rubys Exp $
  +$Id: pyclass.pmc,v 1.20 2005/01/03 00:20:08 rubys Exp $
   
   =head1 NAME
   
  @@ -256,12 +256,22 @@
   */
   
       PMC* get_iter() {
  -        PMC *iter = VTABLE_find_method(INTERP, SELF, PyString_iter);
  +        PMC *gen, *iter, *next;
  +        iter = VTABLE_find_method(INTERP, SELF, PyString_iter);
           if (!iter || !VTABLE_defined(INTERP, iter))
              real_exception(INTERP, NULL, E_TypeError,
                      "TypeError: iteration over non-sequence");
  -        return Parrot_PyClass_run_meth_fromc_P(INTERP, iter, SELF,
  +        iter = Parrot_PyClass_run_meth_fromc_P(INTERP, iter, SELF,
                PyString_iter);
  +        next = VTABLE_find_method(INTERP, iter, PyString_next);
  +
  +        if (PObj_get_FLAGS(next) & SUB_FLAG_GENERATOR)
  +            return iter;
  +        else {
  +            gen = pmc_new(INTERP, PyBuiltin_PyGen);
  +            VTABLE_set_pmc(INTERP, gen, iter);
  +            return gen;
  +        }
       }
   
   /*
  @@ -327,6 +337,29 @@
   
   /*
   
  +=item C<INTVAL hash()>
  +
  +Returns a unique hash for this value
  +
  +=cut
  +
  +*/
  +
  +    INTVAL hash () {
  +        PMC *hash_method = VTABLE_find_method(INTERP, SELF, PyString_hash);
  +        if (hash_method) {
  +            PMC *ret;
  +            ret = Parrot_PyClass_run_meth_fromc_P(INTERP, hash_method, SELF,
  +                PyString_hash);
  +            return VTABLE_get_integer(INTERP, ret);
  +        }
  +        else {
  +            return (INTVAL)SELF;
  +        }
  +    }
  +
  +/*
  +
   =item C<STRING *name()>
   
   Returns the name of this class.
  
  
  
  1.6       +5 -2      parrot/dynclasses/pyconsts.h
  
  Index: pyconsts.h
  ===================================================================
  RCS file: /cvs/public/parrot/dynclasses/pyconsts.h,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- pyconsts.h        30 Dec 2004 11:46:38 -0000      1.5
  +++ pyconsts.h        3 Jan 2005 00:20:08 -0000       1.6
  @@ -6,19 +6,20 @@
   
   /* Python class types */
   
  -PYVAR_SCOPE INTVAL PyBuiltin_PyObject;
   PYVAR_SCOPE INTVAL PyBuiltin_PyBoolean;
   PYVAR_SCOPE INTVAL PyBuiltin_PyClass;
   PYVAR_SCOPE INTVAL PyBuiltin_PyComplex;
   PYVAR_SCOPE INTVAL PyBuiltin_PyDict;
   PYVAR_SCOPE INTVAL PyBuiltin_PyException;
  +PYVAR_SCOPE INTVAL PyBuiltin_PyFloat;
  +PYVAR_SCOPE INTVAL PyBuiltin_PyGen;
   PYVAR_SCOPE INTVAL PyBuiltin_PyInt;
   PYVAR_SCOPE INTVAL PyBuiltin_PyIter;
  -PYVAR_SCOPE INTVAL PyBuiltin_PyFloat;
   PYVAR_SCOPE INTVAL PyBuiltin_PyList;
   PYVAR_SCOPE INTVAL PyBuiltin_PyLong;
   PYVAR_SCOPE INTVAL PyBuiltin_PyNCI;
   PYVAR_SCOPE INTVAL PyBuiltin_PyNone;
  +PYVAR_SCOPE INTVAL PyBuiltin_PyObject;
   PYVAR_SCOPE INTVAL PyBuiltin_PyProxyClass;
   PYVAR_SCOPE INTVAL PyBuiltin_PyProxyType;
   PYVAR_SCOPE INTVAL PyBuiltin_PySlice;
  @@ -50,11 +51,13 @@
   PYVAR_SCOPE STRING *PyString_class;
   PYVAR_SCOPE STRING *PyString_cmp;
   PYVAR_SCOPE STRING *PyString_hex;
  +PYVAR_SCOPE STRING *PyString_hash;
   PYVAR_SCOPE STRING *PyString_init;
   PYVAR_SCOPE STRING *PyString_int;
   PYVAR_SCOPE STRING *PyString_iter;
   PYVAR_SCOPE STRING *PyString_name;
   PYVAR_SCOPE STRING *PyString_new;
  +PYVAR_SCOPE STRING *PyString_next;
   PYVAR_SCOPE STRING *PyString_oct;
   PYVAR_SCOPE STRING *PyString_proxy;
   PYVAR_SCOPE STRING *PyString_repr;
  
  
  
  1.5       +42 -36    parrot/dynclasses/pygen.pmc
  
  Index: pygen.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/dynclasses/pygen.pmc,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- pygen.pmc 18 Dec 2004 15:08:20 -0000      1.4
  +++ pygen.pmc 3 Jan 2005 00:20:08 -0000       1.5
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: pygen.pmc,v 1.4 2004/12/18 15:08:20 rubys Exp $
  +$Id: pygen.pmc,v 1.5 2005/01/03 00:20:08 rubys Exp $
   
   =head1 NAME
   
  @@ -19,11 +19,28 @@
   */
   
   #include "parrot/parrot.h"
  +#include "pyconsts.h"
   
  -static STRING *NEXT;
   static STRING *STOPITERATION;
   
  -pmclass PyGen dynpmc group python_group {
  +static PMC* PyGen_next(Parrot_Interp interpreter, PMC *self) {
  +    PMC *ret;
  +    PMC *iter = PMC_pmc_val(self);
  +    PMC *next = VTABLE_find_method(interpreter, iter, PyString_next);
  +    if (PObj_get_FLAGS(iter) & KEY_end_slice_FLAG) {
  +        real_exception(interpreter, NULL, E_StopIteration, "StopIteration");
  +    }
  +
  +    PObj_get_FLAGS(iter) |= KEY_end_slice_FLAG;
  +    ret = Parrot_runops_fromc_args(interpreter, next, "PP", iter);
  +    if (iter == ret)
  +        /* XXX: runops ate my exception: presume StopIteration */
  +        real_exception(interpreter, NULL, E_StopIteration, "StopIteration");
  +    PObj_get_FLAGS(iter) &= ~KEY_end_slice_FLAG;
  +    return ret;
  +}
  +
  +pmclass PyGen dynpmc extends PyClass group python_group {
   
   /*
   
  @@ -37,7 +54,6 @@
   
       void class_init() {
           if (pass) {
  -            NEXT = const_string(INTERP, "next");
               STOPITERATION = const_string(INTERP, "StopIteration");
           }
       }
  @@ -55,7 +71,7 @@
       void init () {
           PObj_custom_mark_SET(SELF);
           PMC_struct_val(SELF) = NULL;
  -        PMC_pmc_val(SELF) = NULL;
  +        PMC_pmc_val(SELF) = SELF;
       }
   
   /*
  @@ -77,29 +93,6 @@
   
   /*
   
  -=item C<PMC *find_method(STRING *method_name)>
  -
  -Looks up the method for C<*method_name> and returns it. If no method is
  -found then lookup an attribute by this name, and return it.  If all else
  -fails, return null.
  -
  -=cut
  -
  -*/
  -
  -    PMC* find_method(STRING* method_name) {
  -        PMC *method;
  -
  -        if (0 == string_compare(INTERP, method_name, NEXT))
  -            return PMC_pmc_val(SELF);
  -
  -        method = SUPER(method_name);
  -        if (!method) method = VTABLE_getprop(INTERP, SELF, method_name);
  -        return method;
  -    }
  -
  -/*
  -
   =item C<INTVAL get_bool()>
   
   Returns true if there are more elements to return
  @@ -116,13 +109,11 @@
           new_internal_exception(INTERP);
           push_new_c_exception_handler(INTERP, INTERP->exceptions);
           if (!setjmp(INTERP->exceptions->destination)) {
  -            PMC_struct_val(SELF) =
  -                Parrot_runops_fromc_args(INTERP, PMC_pmc_val(SELF), "P");
  +            PMC_struct_val(SELF) = PyGen_next(INTERP, SELF);
           } else {
  -            PMC *exception = REG_PMC(5);
  -            INTVAL extype = VTABLE_get_integer_keyed_int(INTERP, exception, 
1);
  -            if (extype != E_StopIteration) {
  -                rethrow_exception(INTERP, REG_PMC(5));
  +            Parrot_exception *exception = INTERP->exceptions;
  +            if (exception->error != E_StopIteration) {
  +                rethrow_c_exception(INTERP);
               }
           }
   
  @@ -148,6 +139,22 @@
   
   /*
   
  +=item C<void setprop(STRING *key, PMC *value)>
  +
  +Sets the property for C<*key> to C<*value>.
  +
  +=cut
  +
  +*/
  +
  +    void setprop(STRING* key, PMC* value) {
  +        if (0 == string_compare(INTERP, key, PyString_next))
  +            PObj_get_FLAGS(value) |= SUB_FLAG_GENERATOR;
  +        SUPER(key, value);
  +    }
  +
  +/*
  +
   =item C<void set_pmc(PMC *value)>
   
   Sets the value of the NEXT function.
  @@ -158,7 +165,6 @@
   
       void set_pmc (PMC* value) {
           PMC_pmc_val(SELF) = value;
  -        PObj_get_FLAGS(value) |= SUB_FLAG_GENERATOR;
       }
   
   /*
  @@ -179,7 +185,7 @@
               PMC_struct_val(SELF) = NULL;
           }
           else {
  -            ret = Parrot_runops_fromc_args(INTERP, PMC_pmc_val(SELF), "P");
  +            ret = PyGen_next(INTERP, SELF);
           }
   
           return ret;
  
  
  
  1.19      +17 -1     parrot/dynclasses/pyint.pmc
  
  Index: pyint.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/dynclasses/pyint.pmc,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- pyint.pmc 23 Dec 2004 23:49:32 -0000      1.18
  +++ pyint.pmc 3 Jan 2005 00:20:08 -0000       1.19
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: pyint.pmc,v 1.18 2004/12/23 23:49:32 rubys Exp $
  +$Id: pyint.pmc,v 1.19 2005/01/03 00:20:08 rubys Exp $
   
   =head1 NAME
   
  @@ -53,6 +53,22 @@
   
   /*
   
  +=item C<PMC* clone()>
  +
  +Return a clone of the integer.
  +
  +=cut
  +
  +*/
  +
  +    PMC* clone () {
  +        PMC* ret = pmc_new(INTERP, SELF->vtable->base_type);
  +        PMC_int_val(ret) = PMC_int_val(SELF);
  +        return ret;
  +    }
  +
  +/*
  +
   =item C<PMC* "__hex__"(PMC *self)>
   
   Returns the hex representation of C<self>.
  
  
  
  1.19      +5 -5      parrot/dynclasses/pylist.pmc
  
  Index: pylist.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/dynclasses/pylist.pmc,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- pylist.pmc        30 Dec 2004 11:46:38 -0000      1.18
  +++ pylist.pmc        3 Jan 2005 00:20:08 -0000       1.19
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: pylist.pmc,v 1.18 2004/12/30 11:46:38 rubys Exp $
  +$Id: pylist.pmc,v 1.19 2005/01/03 00:20:08 rubys Exp $
   
   =head1 NAME
   
  @@ -120,15 +120,15 @@
           PMC * ret = pmc_new(INTERP, PyBuiltin_PyList);
   
           if (argc > 1) {
  -            INTVAL n = VTABLE_elements(INTERP, value);
  +            PMC *iter = VTABLE_get_iter(INTERP, value);
               INTVAL j;
   
  -            for (j=0; j<n; j++) {
  -                PMC *item = VTABLE_get_pmc_keyed_int(INTERP, value, j);
  +            for (j=0; VTABLE_get_bool(INTERP, iter); j++) {
  +                PMC *item = VTABLE_shift_pmc(INTERP, iter);
                   VTABLE_set_pmc_keyed_int(INTERP, ret, j, item);
               }
   
  -            VTABLE_set_integer_native(INTERP, ret, n);
  +            VTABLE_set_integer_native(INTERP, ret, j);
           }
   
           return ret;
  
  
  
  1.16      +18 -1     parrot/dynclasses/pyobject.pmc
  
  Index: pyobject.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/dynclasses/pyobject.pmc,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- pyobject.pmc      24 Dec 2004 04:41:56 -0000      1.15
  +++ pyobject.pmc      3 Jan 2005 00:20:08 -0000       1.16
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: pyobject.pmc,v 1.15 2004/12/24 04:41:56 rubys Exp $
  +$Id: pyobject.pmc,v 1.16 2005/01/03 00:20:08 rubys Exp $
   
   =head1 NAME
   
  @@ -205,6 +205,23 @@
   
   /*
   
  +=item C<PMC* "__hash__"(PMC *self)>
  +
  +Returns the hash value of C<self>.
  +
  +=cut
  +
  +*/
  +
  +    METHOD PMC* __hash__(PMC *self) {
  +        PMC * ret = pmc_new(INTERP, PyBuiltin_PyInt);
  +        INTVAL value = VTABLE_hash(INTERP, self);
  +        VTABLE_set_integer_native(INTERP, ret, value);
  +        return ret;
  +    }
  +
  +/*
  +
   =item C<PMC* "__int__"(PMC *self)>
   
   Returns the integer value of C<self>.
  
  
  
  1.9       +6 -5      parrot/dynclasses/pyproxytype.pmc
  
  Index: pyproxytype.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/dynclasses/pyproxytype.pmc,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- pyproxytype.pmc   23 Dec 2004 23:49:33 -0000      1.8
  +++ pyproxytype.pmc   3 Jan 2005 00:20:08 -0000       1.9
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: pyproxytype.pmc,v 1.8 2004/12/23 23:49:33 rubys Exp $
  +$Id: pyproxytype.pmc,v 1.9 2005/01/03 00:20:08 rubys Exp $
   
   =head1 NAME
   
  @@ -108,10 +108,11 @@
               object = pmc_new(INTERP, object_class->vtable->base_type);
           }
   
  -        if (object_class == SELF)
  -            proxy = object;
  -        else {
  -            proxy = pmc_new(interpreter, PyBuiltin_PyClass);
  +        proxy = object;
  +
  +        if (object_class != SELF) {
  +            object = VTABLE_clone(interpreter, proxy);
  +            pmc_reuse(INTERP, proxy, PyBuiltin_PyClass, 0);
               VTABLE_setprop(INTERP, proxy, PyString_class, REG_PMC(0));
               VTABLE_setprop(INTERP, proxy, PyString_proxy, object);
           }
  
  
  
  1.1                  parrot/languages/python/t/pie/b0.t
  
  Index: b0.t
  ===================================================================
  # $Id: b0.t,v 1.1 2005/01/03 00:20:10 rubys Exp $
  
  use strict;
  use lib '../../lib';
  
  use Parrot::Test tests => 3;
  
  sub test {
      language_output_is('python', $_[0], '', $_[1]);
  }
  
  test(<<'CODE', 'MetaToken');
  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')
  
  for t in [EOF, INDENT, DEDENT, NEWLINE, NAME, NUMBER, STRING, OPERATOR]:
    print t, int(t)
  CODE
  
  test(<<'CODE', 'Clone iterator');
  class Scanner(object):
      def tokenize(self):
          yield 5, '5'
          yield 0, ''
  
  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 main():
      s = Scanner()
      it = Clone(s.tokenize())
      it2 = Clone(it)
      L = []
      for pair in it:
          L.append(pair)
      print L
      L2 = list(it2)
      print L2
  
  if __name__ == '__main__':
      main()
  CODE
  
  SKIP: {
    skip("todo", 1);
  test(<<'CODE', 'b0.py');
  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)
  
  #!!! Added two helper functions
  def check2(a, b1, b2):
      if not a == b1 and not a == b2:
          raise AssertionError("%.30r != %.30r or %.30r" % (a, b1, b2))
      
  def checkoutput2(n=0, alt=0):
      outputtext = output.getvalue()
      check2(strhash(outputtext), n, alt)
      
  
  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()
      checkoutput2(1308798191, 2837404767) #!!! unicode repr
      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()
      checkoutput2(3257889492, 1379369348) #!!! unicode repr
      env = Dict()
      eval(root, env, env)
      g = env['pi']()
      digits = []
      for i in range(10):
          digits.append(g.next())
      checkoutput2(3259608361, 1529706333)  #!!! unicode repr
      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()
  CODE
  }
  
  
  

Reply via email to