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



Conditional Tests and Execution

Just like their aggregation forms, these structures `{}' may be nested
and/or span macros. 


Conditional Test Structures
 
Conditional tests are performed within a specialized form of
aggregation that is delimited by paired braces { } and called a
conditional test structure, or test for short.  Either a logical or
relational operator may be used to perform the test. Tests return the
truth of the test (either 0, false or non-zero for true).  
 
Macro code not germane to a test may be included in the structure
since only logical and relational operations that accumulate to the
plane and level of the conditional test structure can set the truth of
the structure.  The usual method of performing a logical or relational
operation not to be associated with the test is to place it in an
aggregation (which, of course, changes the level).  However, the
tactic of changing the plane may alternately be employed.
 

Mechanics  
 
The mechanics associated with tests are only similar to those for 
aggregations.  First, when a test is encountered, eX saves the current
plane and level for later recall and forces the current plane to -1 
and the current level to 0.  Then the new current numeric accumulator
is reset to 0.0 and the new current string accumulator is reset to "".
For internal as well as visual reasons, the current level is then
incremented to become 1 and the new current accumulators are similarly
reset.  If the current plane is -1 when a test is encountered, the 
level is merely incremented.  (Sure need to re-write that!)
 
Next it asserts that an addition operation is pending in the current
plane, level which causes the numeric and/or string value(s) returned
by the first value producing term in the structure to `loaded' in the
accumulator(s) for use as the left-hand operand for the subsequent
operator in the test (if any).  Macro execution then continues unless
a logical or relational operation at the plane and level of the test
is encountered and proves false, or until the right brace test
delimiter `}' is reached.  If a logical or relation operation at the
plane and level of the test has proved false, eX suspends execution
until it reaches the test delimiter by scanning forward.  The
following is to demonstrate `at the plane and level':

                  {1 (1 or 2) and 2}

The logical `and' is at the plane and level of the test; but since the
`standard' aggregation increments the level, the logical `or' is not at
the plane and level of the test.  The `standard' aggregation, which
will return 3 (which also represents true), is un-used in this test.  

When the end of the test symbolized by the right brace delimiter is
reached, the current level is decremented, and then the plane and 
level that was the current plane and level prior to entering the test
is restored as the current plane, level.  The result of the test,
either false (0) or true (non-zero), is returned.  A conditional test
structure never returns any value accumulated within the conditional
test aggregation.  
 

Further Test Capabilities
 
Multiple conditional tests are allowed in a single test structure.  If
a logical or relational operation at the plane and level of the test 
proves true and the test structure ending delimiter `}' does not follow
immediately, the accumulator(s) assume the value(s) provided by the
right-hand operand of the logical or relational operation just
performed and execution in the test then continues.  Therefore,
multiple conditional tests may be written in a natural manner as 
shown by 

                       {0 < _X < 10}

As stated in the previous section, if a logical or relational
operation at the plane and level of the test proves false, macro
execution is suspended until the test's matching ending delimiter `}' is
reached by scanning forward in the macro.  When the test delimiter is
reached, the structure is exited and the result of the test is
returned, both as previously described. 

Since logical and relational operators have both a numeric function
and a string counterpart, a single operator may be used to
simultaneously perform both numeric and string tests.  When this is
done, both the numeric test and the string test must prove true for
the result to be true; if either the numeric test or the string test
proves false, the result must be false.  Because eX operators
automatically perform the form(s) of the operation appropriate to the
data value(s) returned by its right-hand operand in conjunction with
the appropriate accumulator, separate multiple numeric and string
tests may be written in any order.  The following are functionally
equivalent:

                 {(2 + "2") < (4 + "4")}
                 {2 + "2" < 4 < "4"}
                 {2 < 4 + "2" < "4"}

The first is perhaps the most comprehensible to human readers.  As you
suspect, the `less than' symbol `<', ASCII 60, is eX's less than
operator.  

Don't forget that relational and logical operators may have data class
suffixes, and data class filters can be used as well; and the string
suffix `$' can be used to force a string by numeric test to be
performed.  String by numeric LOGICAL operations are the string
character-wise, bit-wise operation with the rounded to integer modulo
256 numeric right-hand operand.  String by numeric RELATIONAL
operations compare the length of the string accumulator to the numeric
right-hand operand.  Since they're more usual and easier to
demonstrate, I'll use a string by numeric relational test as an
example: 

                  {"Test string" < 5}

It are not true t'all! 


If ... Then ... EndIf Statements
 
Conditional execution statements may be implemented in a test, as 
perhaps already surmised.  Recalling that a logical or relational
operation within a test that proves true permits further execution of
the macro within the structure and one that proves false terminates
execution of the macro within the structure, it can be seen that in   

         {_X > 0 show "_X is greater than zero"}

the literal will be displayed only if _X > 0, and the structure 
functions as an if ... then ... endif statement.  Just as multiple
conditional tests can be placed in a single test structure, 
if ... then ... endif statements may be nested in a conditional test
structure, as in

           {0 < _X show; "0 < _X" < 10 show " < 10"}

Just make sure the statements do not alter the accumulators and
therefore invalidate the conditional tests.  Use data class filters
and/or aggregations as necessary.  But it's pretty easy to get into
trouble using a test for conditional execution---I know from
eXperience!  So I don't recommend that you try use them as such.  


Conditional Execution Structures
 
Conditional execution is performed within a specialized form of
aggregation that is delimited by brackets [ ] and formally called a 
`conditional execution structure', or loop for short.  It must contain
at least 1 test at the plane and level of the loop to function as a
conditional execution structure (otherwise it would simply be a
bracket aggregation).  Conditional execution structures are used to
construct both loops (iteration) and if ... then statements, and the
structure is referred to as a loop because eX sets up a bracket
structure to be executed as a loop when it encounters one, regardless
of its use. 
 
Mechanics
 
The mechanics associated with loops are similar to, but more complex 
than those for `standard' aggregations.  eX maintains a loop number 
based upon their nesting depth, and every loop has both an associated
truth called the loop truth and an iteration counter called the loop
counter.  The eX function `cLoop' can be used to obtain the current loop
number, and the loop truth and loop count are accessible via the eX
words `lTruth' and `lCount', respectively.  These latter two act like data
entities insofar as they return their values when addressed and are
assignable.  (Regrettably, provision for loops must be made via an
allocation command unless the default 16 suffices.)  

          lCount<<(LoopNumber#)>> <<:= value#>>

The sans-argument form addresses the current loop. 

When a loop is encountered eX increments the loop number and the level
to which accumulation will occur.  The new level within plane becomes
the current level, and the new current plane, level is both a loop and
the current loop.  Unless `held' by available commands described in
the next paragraph, the loop count and loop truth for the now current
loop are reset to 0.0 (implying the loop truth is false).  Unless held
by an accumulator hold command, the now current plane, level
accumulators are also nulled.  

The accumulator `push' and `pop' commands available in a loop are 
identical to those for a parens aggregation.  But the accumulator hold
command in a loop structure differs: the loop count and loop truth are
additionally held if whitespace immediately follows the semi-colon.   
However, specific `suffixes' may be employed in any combination
immediately after the semi-colon to restrict the data held to that
indicated by the suffix(es).  As expected, push and hold commands in a
loop are executed only once... on entry to the loop.    

Next it asserts that no operation is pending in the (new) current
plane, level and resumes macro execution.  No accumulation occurs in a
loop unless or until an operator (usually addition) is encountered in
the aggegation, and this lack of an automatic addition operation on
entry to an aggregation is necessary, of course, in loops. 
 
When the end of the loop is reached, the action taken depends upon its
truth.  If false, the loop is exited.  If true, the loop counter is
incremented, the loop truth is reset to false, and the portion of the
macro within the loop but subsequent to any accumulator push and/or
hold commands is re-executed.  
 
When a loop is exited, eX decrements the loop number and current loop
number, the current level and level, and the numeric and string values
accumulated in the loop as described in the section covering bracket 
aggregations are made available for pending tasks after any
accumulator `pop' command is executed.  


Iteration

Without a method of setting a loop's truth to true, iteration would
not be possible.  Tests are used in a loop to set the loop truth 
and this is accomplished by modifying the test's behavior to set the 
loop's truth rather than return the truth of the test.  eX performs
the modification on tests that are between the loop delimiters and at
the plane and level of the loop.  It does not perform the modification
on tests that are not at the plane and level of the loop, even if the
test is between the loop delimiters.  To illustrate, the test in  

     [ { conditional test } ]

is at the plane and level of the loop and will set the loop truth;  
the test in  

     [ ( { conditional test } ) ]

is not at the level of the loop and will not set the loop truth, and
the test in the following is not at the plane of the loop and will not
set its truth: 

     [ '|_NewPlane { conditional test } |' ]


When a loop's truth is false after a test in the loop has been
executed, eX suspends execution of the macro within the loop and scans
forward in the macro for a place where it is permitted to resume macro
execution.  When a loop is employed for iteration, that place is the
loop ending delimiter `]'. 
 
The type of loop constructed is determined by the position of the test
within the loop.  A test at the beginning of the loop creates a 
while ... do loop: 

     [{ conditional test }
          ** loop body **
          ]

A do ... while loop is created by placing the test at the end of the
loop. 

     [
           ** loop body ** 
           { conditional test }]


Placing the test in the middle of the loop creates a 
do ... if/exit ... loop structure.  Hybrids of these structures may be
created by using multiple test structures.  


If ... Then Constructions

A ~ (tilde, or ASCII code 126), which to eX is an else token, may be
placed in a loop after a test (and before the loop ending delimiter
and any subsequent test).  It not only specifies a point where macro
execution may resume if the loop truth is false, but also specifies
that the code following the `~' (else token) may not be executed if the
loop truth is true.  In the event an else is encountered and the loop
truth is true, eX suspends macro execution and scans forward until the
loop ending delimiter is found and resets the loop truth to false and
the loop is exited. 
 
The code between an else token and the loop ending delimiter is called
the else clause (suprised?), and it may be null, or empty.  The code
between a test and its else token is called a then clause, and it may
be null, or empty.  If you wish, both clauses may be empty.  

To demonstrate, an if ... then ... endif would be written  

          [{ condition } ** then clause ** ~]

An if ... then ... else ... endif would be written  

          [{ condition } ** then clause ** ~ ** else clause ** ]

Each else within a loop may have a test, and the constructions may be
nested and span macros.  

     [{condition} 
          ** then clause **
     ~ {condition}
          ** then clause ** ~
     ] 

     [{ condition }
          [{ condition }
               ** then clause **
          ~]
     ~]



`Case' Structures... well, kind of
 
A variation of a case structure may be implemented by placing 
else token/test pairs `~{ }' in a single conditional execution
structure.  Using elipses (...) for ommitted condtional tests, the
structure would look like    

          [{ ... }
               ** case clause **
          ~{ ... }
               ** case clause **
          ~]

No whitespace may exist between the else token and the subsequent    
test beginning delimiter--it would be a nested 
if ... then ... else if ... then ... endif. 
 
The structure does have quirks:

1. All `cases' (tests) are evaluated and the macro code between each 
   test that evaluates as true and its matching else is executed.
2. Any code in the `else case' (final `else' token) will executed
   unless the test that precedes it evaluates as true. 
3. If the `else case' (final `else' token) is omitted the structure
   will loop (iterate) under control of the final `case test'.  

While there might be circumstances where you can take advantage of
these quirks, eX's case structure should normally terminate with:  

                           ~]


Just in case you didn't pick up on it, the tests in eX's case are 
independant of each other, as the following shows: 

                    [{_x < 10}
                         show "_x < 10"
                    ~{$y = "test"}
                         show `$y = "test"`
                    ~]

While this aspect creates a bit more coding than a more usual case
structure would (`select case x'), it permits more possibilities.  

