[futurebasic] Re: Break ... Until

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : December 1997 : Group Archive : Group : All Groups

From: Rick Brown <rbrown@...>
Date: Sat, 27 Dec 1997 12:17:04 +0000
Peter wrote:
> I did some more experimenting after a sleep.
> 
> Cmd . doesn't work with Do ... Until, or While ... Wend .
> Cmd. does work with Select ..., and If ...
> 
> More importantly, you cannot change a glogal variable based on executing a
> HANDLEEVENTS in some other part of a program and have it influence an
> executing Do ... Until, or While ... Wend loop.
(snip)
> ________________________________
> GLOBALS
> DIM x
> DIM programEnds
> END GLOBALS
> x=0
> programEnds=0
> 
> LOCAL FN beeper3                'cmd . works
>   SELECT x
>     CASE 0
>       BEEP
>   END SELECT
> END FN
> 
> LOCAL FN beeper2                'cmd . works
>   IF x=0 THEN BEEP
> END FN
> 
> LOCAL FN beeper1                'cmd . doesn't work
>   WHILE x=0
>     BEEP
>   WEND
> END FN
> 
> LOCAL FN beeper                 'cmd . doesn't work
>   DO
>     BEEP
>   UNTIL x=1
> END FN
> 
> LOCAL FN handleBreak
>   x=1
>   programEnds=1
> END FN
> 
> LOCAL FN doTimer
>   FN beeper3
> END FN
> 
> ON BREAK FN handleBreak
> ON TIMER(2) FN doTimer
> DO
>   HANDLEEVENTS
> UNTIL programEnds

I think you're mistenterpreting what's happening.  Command-period
"works" (that is, it stores an event in the queue) regardless of what
kind of program structure is executing.  And when you change a global
variable anywhere, it gets changed for everybody, regardless of what
kinds of structures are using it.

What's happening is this:

When your FN doTimer specifies FN beeper2, then things execute like this
(assuming no Cmd-period presses):

   Main loop runs for 2 seconds;
   FN doTimer is called;
     FN beeper2 is called;
     FN beeper2 exits;
   FN doTimer exits;
   Main loop runs for 2 more seconds;
   FN doTimer is called;
     FN beeper2 is called;
     FN beeper2 exits;
   FN doTimer exits;
   Main loop runs for 2 more seconds;
   :
   (etc.)

(A similar diagram applies when you specify FN beeper3).  Note in
particular that control keeps coming back to your Main Loop.

But FN beeper and FN beeper1 are different from the first case.  When
you specify FN beeper, the program flow is like this (again, assuming no
Cmd-period presses):

   Main loop runs for 2 seconds;
   FN doTimer is called;
     FN beeper is called, and NEVER EXITS.

(A similar diagram applies when you specify FN beeper1).

Why are the two diagrams different?  Because FN beeper2 and FN beeper3
"fall through" to the END FN statement, but FN beeper and FN beeper1
don't (because of their loops).

Now suppose we add some Command-period presses.  The vital thing to
remember is that pressing Cmd-period DOES NOT immediately alter the flow
of your program; it DOES NOT immediately cause a jump to FN
handleBreak.  Instead, your program continues along as if nothing
happened, _until_ it gets to the next HANDLEEVENTS statement.

In "Diagram 1," most of the time is spent in the Main Loop.  We're
always guaranteed to come back to the Main Loop, and so we're guaranteed
that, if a HANDLEEVENTS is not executing right now, it soon will be,
within another fraction of a second.  So, regardless of what part of the
diagram is executing at the time we do Cmd-period, quite soon after that
we'll get to the next HANDLEEVENTS statement.  When that happens,
HANDLEEVENTS then calls FN handleBreak, which sets our global
variables.  Then FN handleBreak exits, then HANDLEEVENTS exits, then we
hit the "UNTIL programEnds" statement, and the program ends.

In "Diagram 2," the Main Loop only executes for the first 2 seconds, and
then the program gets stuck in FN beeper.  Suppose we press Cmd-period
five seconds after the program starts (3 seconds after we've been
listening to the maddening beeps).  Remember that our Cmd-period presses
DO NOT have any effect on the program flow UNTIL a subsequent
HANDLEEVENTS is executed.  But no subsequent HANDLEEVENTS is ever
reached, because we can't get back to the Main Loop, because we're stuck
in FN beeper's DO loop (or FN beeper1's WHILE loop)!

The lesson is: If you want your events to be "seen," then you _must_
make sure that you execute HANDLEEVENTS periodically.  When the user
causes an event, it is not acted upon until the _next_ HANDLEEVENTS
statement is reached.

Try changing FN beeper as follows, and notice the difference:

LOCAL FN beeper
  DO
    BEEP
    HANDLEEVENTS
  UNTIL x=1
END FN

- Rick