eX version 0.4b User's Manual                         File eXMan08.txt
(C) Copyright 1995, 1996 William E. Wilgus III.   All rights reserved.


Branching and Sub-Programming


Unless otherwise directed, macro execution ceases when the end of the 
currently executing macro is reached; and writing macros was a lot
more difficult before its program execution directives were
implemented! 

All of eX's programming and sub-programming directives have a
conditional execution form, which may be generalized as 

             directive{conditional test} << argument >>

If the test proves true, the directive is executed, otherwise 
it is not.  Argument is given as optional to provide for the
directives chain, EndChain and EndMac which do not take an argument, 
and return, which does not require an argument.  Arguments specify the
directive branch or sub-programming object and may be given either
directly (as a literal) or in-directly.  If the object is given as an
aggregation, an eev filter should be used to provide the correct type
of data to the program branch statement. 

The directives are otherwise inert and may appear almost anywhere. While 
you are permitted to, this is one place you really don't want to play 
around with if ... thens in a test structure unless you absolutely
have to! 


Macro Termination


If executed, the eX directive `EndMac' simulates the end of a macro, 
including its subsequently discussed `implied return'.  It takes no
argument. 

               EndMac<<{conditional test}>>


Macro `Chaining'

Memory resident macros can be made to execute sequentially in the
order of their macro number, beginning with the currently executing
macro, by the use of the eX word `chain'.  Once eX encounters `chain', 
it will transfer execution to the next higher numbered memory resident
macro when it reaches the end of the macro it is currently executing. 
The process will continue until either the highest numbered memory
resident macro has been executed, or the eX word `EndChain' terminates
the process.  The current status of chain may be determined through
the eX word `chaining' which returns false (0) if in-active and true
(-1) if `chaining' is active.  (`Chaining' takes no arguments.)  

                    chaining
                    chain<<{conditional test}
                    EndChain<<{conditional test} 


Inter-Macro Branching

Any macro may branch to another macro or itself at any time via a
program branch.  The eX word `goto' causes execution of its macro to
terminate at the point it appears and re-commence at the beginning of
the branch object macro.  Object macros may be specified by their name
or macro number.  If not memory resident, a named branch object macro
is automatically loaded into memory.   

               goto<<{conditional test}>> ObjectMacro


The eX macro identity function 

                            MacId Macro 

may be used to determine either a macro's name or number.  If the
argument is given as a macro number, the identifier is returned if
that macro data entity is utilized, otherwise the null string "" is
returned.  If the argument Macro is given as a macro identifier, its
macro number is returned if the macro is memory resident, otherwise 0
is returned.  Macro numbers remain constant as long as a macro is
memory resident. 



Inter-Macro Sub-Programming

`Calling' a Sub-Program

Any macro may employ another macro or itself as a sub-program at any
time.  The eX word `gosub' causes execution of its macro to be suspended
at the point it appears while the sub-program object macro is
executed. When execution of the sub-program is completed, execution of
the `calling' macro resumes at the point subsequent to the `gosub'.
Sub-programming `call's may be nested to any depth, and object macros
may be specified by their name or macro number.  If not memory
resident, a named branch object macro is automatically loaded into
memory.   

              gosub<<{conditional test}>> ObjectMacro


Returning from a Sub-Program

A return mechanism is used to terminate execution of a sub-program and
resume execution of the `caller', and returns are implied at the end
of all macros.  (The eX directive `EndMac' also implies a return if
executed.)  The eX word `return' may be used as an explicit return and
can appear anywhere in a macro, including its end.  However, the
ommission of an explicit return at the end of a macro permits use of
the macro as either a sub-programming or branch object.  

eX provides the capability of altering the macro that `return' goes 
back to.  To illustrate by example, accept that a macro named "one" 
did a gosub to a macro named "two", that did a gosub to a macro named
"three".  It would be possible to return from macro "three" to macro 
"one" instead of macro "two" by 

                      return("one")

EX acomplishes this by discarding pending gosub return requirements   
until it reaches one that is to the macro named in the argument 
for `return'.  If no return is pending for the macro specified in the
argument, execution will terminate unless chaining is in effect.    

The syntax for the eX word return, then is   

              return<<{CondtionalTest}>><<(Macro$)>>

Note that if given the argument must be parenthesized and no
whitespace may preceed it's left parens.  

Forgeting, replacing, or modifying a macro that has the return of a
sub-program still pending will almost certainly be disastrous.  A
sub-program `call' saves the macro number and a pointer to the
position in the macro where execution is to resume.  You have to be
either really good or lucky to get away with it, but the preceding
sentence gives you all the necessary information to tackle it. 
(Perhaps someday eX will make this easier to do.)  As a small safety
net, eX will not let you forget the current macro and will abort after
displaying a message to that effect.  (It won't tell you what it
thinks of your mental capacity at that moment, however.)


Intra-Macro Directives

Elements termed `labels' may be placed in a macro to identify that part 
of a macro at which the label appears.  Other than serving to identify
a part of a macro for a branch or sub-programming directive, labels
are inert.  It is important to note that un-like a macro, a label has
no end other than the end of the macro itself.  It might be important
to note that eX scans for labels starting at the beginning of the
macro.  

Labels consist of two parts: 

     1. the label token `:>' (a colon, ASCII code 58, followed by a
        `greater than' symbol, ASCII code 62); and 
     2. an alpha-numeric name, in which alphabetic case is
        significant. 

The name may be given as an un-delimited literal, in which case it
must immediately follow the label token and be followed by whitespace,
or it may be given as a delimited literal or indirectly; and in these
latter two cases the specification must be seperated from the label token 
by whitespace.  

          :>LabelName
          :> "LabelName"
          :> LabelNameTerm$

Any string producing eX language component may be used with the latter
form.  I'll soon describe a situation where indirectly naming a label
isn't as idiotic as it now seems. 

Each label also has an implied label number, and labels are numbered
sequentially, beginning with 1, as they appear in the macro from left
to right, top to bottom.  By definition, the beginning of a macro is
label number 0 whether the macro begins with a label or not.  In the
case a macro begins with a label, the beginning of the macro is in
effect both label number 0 and 1. 


Branching

Any macro may branch to a label within that macro at any time via an 
intra-macro program branch.  The eX word `jump' causes execution to
terminate at the point it appears in a macro and re-commence at the
point in the macro immediately following the branch object label.  
The object label may be given as either the label's name or its 
implied number.  In either case, the object label may be specified
directly or indirectly.  If given both a numeric and a string, `jump' 
uses the numeric (implied label number object), so remember that data
class filters may precede the label specification.  If the object
label is not found and the directive is to be executed, eX aborts.  

                jump<<{condtional test}>> ObjectLabel


The ability to name a label indirectly can be valuable when an 
intra-macro branch or sub-program directive object is specified 
indirectly---naming a label indirectly with the same code used to 
indirectly specify the directive's object provides an opportunity for 
exception handling. 

          jump $LabelName
          :>Label1
               ** Label1 code **
          :> $LabelName
               ** exception handling code **


Sub-Programming

Any macro may execute a sub-program identified by a label within that 
macro at any time via an intra-macro sub-program directive.  The
eX word `call' causes execution of the macro to be suspended at the 
point the `call' appears while the sub-program identified by the object 
label is executed.  When execution of the sub-program is completed,
execution of the macro resumes at the point subsequent to the call.  
Intra-macro sub-program calls may be nested to any depth and may be
mixed with inter-macro sub-programming calls in any combination.  

The object label may be given as either the label's name or its 
implied number.  In either case, the label may be specified directly
or indirectly.  If given both a numeric and a string, call uses the
numeric (implied label number object), so remember that data class
filters may precede the label specification.  If the object label is
not found and the directive is to be executed, eX aborts.  

             call<<{condtional test}>> ObjectLabel


Returning from a Sub-Program

The same mechanism used to return from an inter-macro sub-program is
used to return from an intra-macro sub-program.  Recalling that a
label itself has no end other than the end of the macro, it becomes
apparent that it will be usual to provide an explicit return to
terminate an intra-macro sub-program.  The following macro
illustrates:

     call "Label1"
     call "Label2"
     endmac
     :>Label1
          show "This is Label1"
          return
     :>Label2
          show "This is Label2"

Label2 uses the return implied at the end of the macro.  But since
Label1 does not end until the end of the macro (where Label2 ends),
without the explicit return a call to Label1 would be excutionally
equivalent to the following: 

     :>Label1
          show "This is Label1"
          show "This is Label2"

(Remember, a label only serves to identify a portion of a macro.) 
While there are situations where it is convenient to allow a `call' to
`fall through' to a subsequent label, it should be obvious that the
preceding example was not one of those situations.  

The ability of an explicit return to discard pending returns loses at
least some of its significance with intra-macro sub-programming.  The
problem is, of course, that you must either discard returns until an 
inter-macro return is encountered or not discard them at all!  For
your convenience, the following is repeated: 

               return<<{CondtionalTest}>><<(Macro$)>>


Inter/Intra-Macro Directives

I hope to replace inter/intra-macro branching and sub-programming with
a more awkward term, but until I find one it will have to suffice.  
Regardless, they're simply a branch or sub-program `call' to a
label within a macro other than the one in which the directive
appears.

`LongJump' is the branch directive, and `LongCall' is the sub-program
directive, which uses the same return mechanisms as `gosub' and `call'. 

           LongJump<<{conditional test}>> Macro Label
           LongCall<<{conditional test}>> Macro Label

Macro may be specified in any of the ways available with `goto' or `gosub'
and Label may be specified in any of the ways available with jump or
call.  You might like to note that the following are functionally
equivalent: 

                       LongJump Macro 0
                       goto Macro

As with all the program execution directives, the macro specified may
be the macro in which the directive appears, i.e. any directive may
branch to or call its own macro. 

Another Potential Problem
 
Perhaps you have already realized that in an unusual sense, eX is a
highly structured language.  If not, it is.  The actual structure is
the accumulator array (planes and levels).  

An acceptable method for conditional program branching would seem to
be to place the program branch in a conditional execution statement as
done with the following sub-programming directives: 

          [{_X > 0}
               gosub "Macro2"
          ~]

Recalling the discussion in the conditional tests section, the macro
fragment    

             {_X > 0 gosub "Macro2"}    

is allowed as well.  However, any program branch poses some potential
problems if executed from within a conditional test or a conditional
execution structure, or even an aggregation: the structure is never
exited unless the branch object contains the aggregation ending
delimiter!  `Goto', `jump' and `LongJump' are susceptible, and `gosub', 
`call' and `LongCall' are open to discarded returns.

