pipes

Ralph Boland rpboland at gmail.com
Sat Oct 22 20:11:29 UTC 2005


I have a problem-solution that I would like to receive comments on. 
Perhaps others
have had similar problem-solutions and can provide me with useful
feedback or even
use my solution.  My solution involves creating a subclass of  Stream.

My application has a window W onto the contents of a parse tree  P.
Currently I convert the parse tree P  into text before passing the
text to window W to be displayed.  Thus with each
modification of the parse tree P  the corresponding complete text
corresponding to  P  is recomputed.
For my application simple user operations (such as cursor right, input
a single character)
in a different window usually causes significant changes to  P  requiring
W to be updated.  Since this implies completely computing the text corresponding
to  P  this could be quite slow if  P  is sufficiently large.

It seems to me that W should only ask for the text that it needs to
display and not all of the text and then only the text that it needs
need be generated.
The cost is then proportional to the size of  W  rather than the size
of the parse tree  P.

To do this I would need a stream S from which  W would request text
when it is updated.
S would then get text from the parse tree as required.  I think  S 
should be usable as
much as possible like other streams.
Thus, ideally,  I should not need to modify the code that puts the text
corresponding to my parse tree into a stream
nor the code where  W  currently fetches text from a stream.

I don't however see how this is possible.
It seems that I need to do the following:

1)  When stream  S is created it must be given a place to send the
data it receives;
     that is  W or some component of  W.  S is created by  W appropriately.
     This is probably done using 2).

2)  W  has to support a method  receiveChar  or  receiveAttributedChar
     and perhaps methods like recieveLineOfText.  This method or methods
     is passed to  S when  S is created by W.
     This is the ugly part because it totally changes the way  W  uses
stream  S.
     Any suggestions on how to avoid (or reduce) this welcome.

3)  To update W  the parse tree is sent a message like 'P  asTextOn: 
S'  or  'P printOn: S'.
     At some point  W decides it has all the text it can display and
sends a message
     'S  stop'.  From then on each time  S  is sent a message  such as
 'nextPut:'
      or 'nextPutAll:'  it returns a value such as  '0'  or nil  or 
#stoppedPrinting to indicate
      that sending it more data is pointless because it will just
discard the data anyway
      and not forward the data to  W  because  W doesn't want anymore data.

4)   The method  asTextOn:  (or printOn:)  in  the classes used to construct  P
      must be modified to check the result of sending the method.  If 
P doesn't want
      anymore data then they send no more data to  P.

Now a call  'P asTextOn:  S'  requires time proportional to the amount
of text displayed
as desired.

Notes:

  1)  In fact  W  is a PluggableTextMorph so that it currently
receives text to be displayed
       not as a Stream but as a Collection.  I will have to change
PluggableTextMorph
       accordingly.

   2)  The class of  S  should support methods that allow connecting
its instances together
        such as:
              S  ||  T  ||  U.
        This means that the output of  S is sent to the input of  T and the
         output of  T  is sent to the input  of  U  where  class(T)
and class(U)
        are subclasses  of  class(S)  which process their input in some way
        before sending the data forward.  If the output of  U is sent
to  W  then
        'P printOn:  S'  would send the string representing  P  to   W
 to be displayed
        but not until the string is processed in some way by  S,  T, 
and  U.  Since  S
        currently does nothing it could have been left out.

   3)  Note 2) strikes me as very useful (like pipes in a Unix shell)
and thus I expect
        someone has done this before.  In any case, perhaps such a
class or family
        of classes like class(S)  should be made a standard part of Squeak.

Comments much appreciated.  If someone has already done this then code much
appreciated.


Ralph Boland



More information about the Squeak-dev mailing list