import math, sys, re
sys.dont_write_bytecode=True 
from go import *

"""
general stuff

"""
#@go
def _2d():
 x=my2d(5,5)
 x[2][3] = 4
 print x


#@go
def _rw():
  f="01jan21.py"
  for line in open(f):
    line = re.sub(r"^[ \t\n]*","",line)
    line = re.sub(r"[ \t\n]*$","",line)
    if line:
      print "[" + line + "]"


def my2d(m,n) :
  out = []
  for row in range(m):
    tmp =[]
    for col in range(n):
      tmp += [None]
    out += [tmp]
  return out


"""
rules of printing

- if things contain nested things
    - then print the nested things, indented according to the level of nesting
- numbers get printed verbatim
- string get surrounded by rabbit ears
- list get printed one per line
- dictionaries get printed ':key = value'
   - sorted on key order
   - if the value is simple, print it on the same line
   - simple = number or string
- otherwise, find a dictionary containing all
  the instance's local variables, then print it
  as a dictionary (surrounded by the class name of the instance)
"""


def say(x):
  sys.stdout.write(x)

#--------------------------------------------------
# here are some structures which will become our
# examples of "stuff to print"

class Person(object):   
    def __init__(i,name,age,shoesize,hobbies=[]):
      i.name = name
      i.age  = age
      i.shoesize = shoesize
      i.hobbies  = hobbies
    def bday(i):
      i.age += 1

class Emp(Person):
  def __init__(i,name,age,shoesize,hobbies,salary=0):
    super(Emp,i).__init__(name,age,shoesize,hobbies)
    i.salary = salary
  def promote(i):
    i.salary *= 1.1

class Point:
  def __init__(i,x=0,y=0):
    i.x=x
    i.y=y
  def rprint(i):
    return 'Point(%s @ %s)' % (i.x,i.y)

x= [Emp("tim",10,10,["reading","writing"],1000),
    [
      [3,"44"],
      5,
      ["66",
       [7,8]
       ]
      ],
    Point(1,100)
    ]

# -----------------------------------------------
# now lets print some stuff

def rprint0(x,dpth=-1):
  "basic recursive print of lists"
  if isinstance(x, list):
    for y in x: 
      rprint0(y,dpth+1)
  else:
    print '   ' * dpth + str(x)

#@go
def _rprint0() : rprint0(x)

# -----------------------------------------------

def rprint1(x,dpth=-1):
  "as above, with rabbit ears around strings"
  def listp(x)  : return isinstance(x,list)
  def stringp(x): return isinstance(x, str)
  def quoted(x) : return '\"%s\"' % x if stringp(x) else  str(x)
  if listp(x):
    for y in x: 
      rprint1(y,dpth+1)
  else:
    print '   ' * dpth + quoted(x)

#@go
def _rprint1() : rprint1(x)

# -----------------------------------------------

def rprint2(x,dpth=-1):
  "as above, but allow instances to control their own printing"
  def listp(x)  : return isinstance(x,list)
  def stringp(x): return isinstance(x, str)
  def quoted(x) : return '\"%s\"' % x if stringp(x) else  str(x)
  def rprintable(x): return hasattr(x,"rprint")
  if listp(x):
    for y in x: 
      rprint2(y,dpth+1)
  elif rprintable(x):
    print ' ' * dpth + ">>" + x.rprint()
  else:
    print ' ' * dpth + quoted(x)

#@go
def _rprint2() : rprint2(x)

# -----------------------------------------------

def rprint(anything,  dpth = 0):
  """
  As above but if an instance has fields f1,f2,...
  then print those fields, but name. also,
  if a dictionary has keys k1,k2,.... then print
  those keys and values.

  Also, define some shortcuts to make the code clean.
  """
  what      = lambda x: ':%s' % x
  tabs      = lambda n: '  ' * n  # or 2 or 8 or...
  quoted    = lambda x: '\"%s\"' % x if stringp(x) else  str(x)
  equals    = lambda x: ' = %s' % quoted(x)
  nump      = lambda x: isinstance(x, (int, long, float, complex))          
  dictp     = lambda x: isinstance(x, dict)
  listp     = lambda x: isinstance(x, list)
  stringp   = lambda x: isinstance(x, str)
  rprintable= lambda x: hasattr(x,"rprint")
  simple    = lambda x: stringp(x) or nump(x)
  className = lambda x: x.__class__.__name__
  if simple(anything):
    print tabs(dpth) + quoted(anything)
  elif rprintable(anything):
    print tabs(dpth) + anything.rprint()
  elif listp(anything):
    for something in anything:
      rprint(something, dpth+1)
  elif dictp(anything):
    for key in sorted(anything.keys()):
      value = anything[key]
      say(tabs(dpth) + what(key))
      if simple(value):
        print equals(value)
      else:
        print ""
        rprint(value, dpth + 1)
  else:
    print tabs(dpth) + className(anything) + '('
    rprint(anything.__dict__, dpth + 1)
    print tabs(dpth) + ')'

#@go
def _rprint() : 
  rprint({ 'key1' : list('abcdef'),
       'key2' : 'value2',
    
       'key3' : { 'key3a': 'value3a' },
       'key4' : { 'key4a': { 'key4aa': list('abcdef'),
                             'key4ab': Point(y=100),
                             'key4ac': Emp("tim",21,10,
                                           ["flying","swimming"],
                                           salary=10000)},
                  'key4b': 100}
       })

