Home | History | Annotate | Download | only in threads
      1 # Coroutine example:  general coroutine transfers
      2 #
      3 # The program is a variation of a Simula 67 program due to Dahl & Hoare,
      4 # (Dahl/Dijkstra/Hoare, Structured Programming; Academic Press, 1972)
      5 # who in turn credit the original example to Conway.
      6 #
      7 # We have a number of input lines, terminated by a 0 byte.  The problem
      8 # is to squash them together into output lines containing 72 characters
      9 # each.  A semicolon must be added between input lines.  Runs of blanks
     10 # and tabs in input lines must be squashed into single blanks.
     11 # Occurrences of "**" in input lines must be replaced by "^".
     12 #
     13 # Here's a test case:
     14 
     15 test = """\
     16    d    =   sqrt(b**2  -  4*a*c)
     17 twoa    =   2*a
     18    L    =   -b/twoa
     19    R    =   d/twoa
     20   A1    =   L + R
     21   A2    =   L - R\0
     22 """
     23 
     24 # The program should print:
     25 
     26 # d = sqrt(b^2 - 4*a*c);twoa = 2*a; L = -b/twoa; R = d/twoa; A1 = L + R;
     27 #A2 = L - R
     28 #done
     29 
     30 # getline: delivers the next input line to its invoker
     31 # disassembler: grabs input lines from getline, and delivers them one
     32 #    character at a time to squasher, also inserting a semicolon into
     33 #    the stream between lines
     34 # squasher:  grabs characters from disassembler and passes them on to
     35 #    assembler, first replacing "**" with "^" and squashing runs of
     36 #    whitespace
     37 # assembler: grabs characters from squasher and packs them into lines
     38 #    with 72 character each, delivering each such line to putline;
     39 #    when it sees a null byte, passes the last line to putline and
     40 #    then kills all the coroutines
     41 # putline: grabs lines from assembler, and just prints them
     42 
     43 from Coroutine import *
     44 
     45 def getline(text):
     46     for line in string.splitfields(text, '\n'):
     47         co.tran(codisassembler, line)
     48 
     49 def disassembler():
     50     while 1:
     51         card = co.tran(cogetline)
     52         for i in range(len(card)):
     53             co.tran(cosquasher, card[i])
     54         co.tran(cosquasher, ';')
     55 
     56 def squasher():
     57     while 1:
     58         ch = co.tran(codisassembler)
     59         if ch == '*':
     60             ch2 = co.tran(codisassembler)
     61             if ch2 == '*':
     62                 ch = '^'
     63             else:
     64                 co.tran(coassembler, ch)
     65                 ch = ch2
     66         if ch in ' \t':
     67             while 1:
     68                 ch2 = co.tran(codisassembler)
     69                 if ch2 not in ' \t':
     70                     break
     71             co.tran(coassembler, ' ')
     72             ch = ch2
     73         co.tran(coassembler, ch)
     74 
     75 def assembler():
     76     line = ''
     77     while 1:
     78         ch = co.tran(cosquasher)
     79         if ch == '\0':
     80             break
     81         if len(line) == 72:
     82             co.tran(coputline, line)
     83             line = ''
     84         line = line + ch
     85     line = line + ' ' * (72 - len(line))
     86     co.tran(coputline, line)
     87     co.kill()
     88 
     89 def putline():
     90     while 1:
     91         line = co.tran(coassembler)
     92         print line
     93 
     94 import string
     95 co = Coroutine()
     96 cogetline = co.create(getline, test)
     97 coputline = co.create(putline)
     98 coassembler = co.create(assembler)
     99 codisassembler = co.create(disassembler)
    100 cosquasher = co.create(squasher)
    101 
    102 co.tran(coputline)
    103 print 'done'
    104 
    105 # end of example
    106