--
--	testpump.occ - test the dynamic sort pump
--	Copyright (C) 2000 Fred Barnes <frmb2@ukc.ac.uk>
--
--	This program is free software; you can redistribute it and/or modify
--	it under the terms of the GNU General Public License as published by
--	the Free Software Foundation; either version 2 of the License, or
--	(at your option) any later version.
--
--	This program is distributed in the hope that it will be useful,
--	but WITHOUT ANY WARRANTY; without even the implied warranty of
--	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--	GNU General Public License for more details.
--
--	You should have received a copy of the GNU General Public License
--	along with this program; if not, write to the Free Software
--	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--


#INCLUDE "dynproc.module"
#INCLUDE "course.module"


--{{{  PROC sort.pump.process (CHAN OF INT in, CHAN OF BOOL flush, terminate, CHAN OF INT out)
PROC sort.pump.process (CHAN OF INT in, CHAN OF BOOL flush, terminate, CHAN OF INT out)
  DPROCESS p:
  INT lhandle:
  INT res:
  SEQ
    ccsp.openlib ("./sort_pump.so", lhandle)
    ASSERT (lhandle <> 0)
    ccsp.loadproc (lhandle, "sort.pump", p)
    ASSERT (p <> NOTPROCESS.D)
    CHAN OF BOOL bool.in RETYPES in:
    []CHAN OF ANY x.in RETYPES [bool.in, flush, terminate]:
    []CHAN OF ANY x.out RETYPES [out]:
    ccsp.runproc (p, x.in, x.out, res)
    ccsp.freeproc (p)
:
--}}}  

--{{{  PROC term.plex (CHAN OF BOOL in, []CHAN OF BOOL out)
PROC term.plex (CHAN OF BOOL in, []CHAN OF BOOL out)
  BOOL val:
  SEQ
    in ? val
    SEQ i = 0 FOR (SIZE out)
      out[i] ! val
:
--}}}  

--{{{  PROC kbd.feed (CHAN OF BYTE in, CHAN OF BOOL terminate, CHAN OF INT to.pump, CHAN OF BOOL to.flush, done.flush, SHARED CHAN BYTE to.screen!)
PROC kbd.feed (CHAN OF BYTE in, CHAN OF BOOL terminate, CHAN OF INT to.pump, CHAN OF BOOL to.flush, done.flush, SHARED CHAN BYTE to.screen!)
  BYTE ch:
  INITIAL BOOL running IS TRUE:
  INITIAL INT e.count IS 0:
  INITIAL BOOL just.flushed IS TRUE:
  WHILE running
    SEQ
      IF
        just.flushed
          SEQ
            CLAIM to.screen!
              SEQ
                out.string ("to pump:   [", 0, to.screen!)
                to.screen ! FLUSH
            just.flushed := FALSE
        TRUE
          SKIP
      in ? ch
      CLAIM to.screen!
        SEQ
          IF
            ch = '*n'
              to.screen ! ']'
            TRUE
              SKIP
          to.screen ! ch
          to.screen ! FLUSH
      IF
        ch = '*n'
          IF
            e.count = 2
              SEQ
                terminate ! TRUE
                running := FALSE
            TRUE
              SEQ
                to.flush ! TRUE
                BOOL any:
                done.flush ? any
                just.flushed := TRUE
                e.count := (e.count + 1)
        e.count > 0
          SEQ
            e.count := 0
            to.pump ! (INT ch)
        TRUE
          to.pump ! (INT ch)
:
--}}}  

--{{{  PROC collect (CHAN OF INT from.pump, CHAN OF BOOL terminate, done.flush, SHARED CHAN BYTE to.screen!)
PROC collect (CHAN OF INT from.pump, CHAN OF BOOL terminate, done.flush, SHARED CHAN BYTE to.screen!)
  INITIAL BOOL running IS TRUE:
  WHILE running
    PRI ALT
      --{{{  data comming out of pump
      INT count:
      from.pump ? count
        SEQ
          CLAIM to.screen!
            SEQ
              out.string ("from pump: [", 0, to.screen!)
              SEQ i = 0 FOR count
                INT val:
                SEQ
                  from.pump ? val
                  to.screen ! (BYTE (val /\ #FF))
              to.screen ! ']'
              to.screen ! '*n'
          done.flush ! TRUE
      --}}}  
      --{{{  terminate
      BOOL any:
      terminate ? any
        running := FALSE
      --}}}  
:
--}}}  

--{{{  PROC testpump (CHAN BYTE kyb?, SHARED CHAN BYTE scr!)
PROC testpump (CHAN BYTE kyb?, SHARED CHAN BYTE scr!)
  SEQ
    CLAIM scr!
      SEQ
        out.string ("dynamic sort-pump demo:*n", 0, scr!)
        out.string ("    type characters to fill the pump*n", 0, scr!)
        out.string ("    return-key flushes the pump*n", 0, scr!)
        out.string ("    return three times to terminate*n*n", 0, scr!)

    [3]CHAN OF BOOL term.chans:
    CHAN OF INT to.pump, from.pump:
    CHAN OF BOOL pump.flush, done.flush:
    PAR
      kbd.feed (kyb, term.chans[0], to.pump, pump.flush, done.flush, scr!)
      sort.pump.process (to.pump, pump.flush, term.chans[1], from.pump)
      collect (from.pump, term.chans[2], done.flush, scr!)
      term.plex (term.chans[0], [term.chans FROM 1])
:
--}}}  

