eX version 0.4b User's Manual                         File eXMan04.txt 
(C) Copyright 1995, 1996 William E. Wilgus III.   All rights reserved. 
 
 
 
Assignment, Operators and Data Class Filters 
 
 
Data Class Filters 
  
Since as previously stated  
 
     some eX language components either can, or do return a  
     numeric value and a string value simultaneously,   
 
eX provides data class filters to eliminate an un-wanted data class  
returned by a language component.  I sometimes incorrectly call them 
data type filters, and frequently call them eev filters.  (What good 
can a computer language be if it doesn't have at least a few awkward 
and/or obfuscatory... or at least one overly redundant term?)   
 
There are two (2) data class filters, the string filter $ and the 
numeric filter #, and both must be surrounded by whitespace.  They allow 
their name-sake data class (numeric or string) eev to exist and force 
the other data class eev to not exist.  They cannot force a data type 
eev to exist.  You'll see example uses sprinkled throughout the 
manual.  Data class filters are local to the accumulator plane and 
level in which they appear.   
 
 
 
Operators 
 
The language includes arithmetic, logical and relational operators; 
and their representative characters and/or words mirror those of 
BASIC.  (The plus sign +, ASCII code 43 used later in this section 
represents addition.)  eX does not consider assignment to be an 
operation, even though referred to as such.  To a degree, however, 
it does treat `operated' assignments as operations.   
 
Operators are quasi-local to the plane and level in which they appear, 
and I'll discuss the significance of `quasi' in the chapter on 
aggregations.  All operators have equal precedence and are usually 
performed left to right as they are encountered.  The exception 
involves `multiple operators', covered in a subsequent section.  
 
Binary operators employ the appropriate current plane, level 
accumulator(s) as the left-hand operand(s) and the value(s) provided 
by a subsequent term within the operator's plane, level as the  
right-hand operand.  The results of the operation(s) are placed in the 
appropriate current (plane, level) accumulator(s).  The performance of 
an operation does not destroy the data class value(s) provided as the 
operator's right-hand operand(s).  Therefore, the value(s) remain 
available for any preceding task within the plane, level.  I'll show 
you in later chapters how this can be used to advantage with functions 
and output, as well as multiple operators.   
 
Each binary operator has three functions it can perform:  
 
     1. the usual numeric by numeric operation,  
     2. a string by string counterpart, and  
     3. a string by numeric counterpart.  
 
Which of the three is performed is indirectly controlled by the 
programmer.   
 
If a binary operator's right-hand operand provides a numeric value, 
the numeric by numeric operation is performed; if it provides a string 
value, the string by string operation is performed; and if it provides 
both numeric and string values, both operations are performed.  (A 
data class that is provided by a macro component is said to exist.)  
Regarding assignment, however, this is actually mis-leading.  Both 
numeric and string eev's always exist---but are not always valid.  
Assignments are made regardless of whether the data class eev exists  
(or is valid). 
  
With the unary operator negation (-) excepted, all of the operators 
may be modified by the numeric suffix `#' so that they may only perform 
a numeric by numeric operation.  If no numeric value is provided by 
the operator's right-hand term, no operation is performed and the 
operation is in effect cancelled.  Negation again excepted, all of the 
operators may be modified by the string suffix `$' so that they may only 
perform a string operation.  In this case, if the right-hand operand 
provides a string value, the string by string operation is performed; 
but un-like the numeric operator suffix, if a string value is not 
provided but a numeric value is, an equivalent string by numeric 
operation is performed.  (If no data class is provided, the operation 
is in effect cancelled.)  String by numeric operations are rational.   
For example,  
 
                          "abcd" /$ 2 
 
produces the quotient "ab". 
 
Just in case you haven't inferred the term `suffix' implies that no 
whitespace may appear between an operator and its suffix, it does and 
none can.  And note that un-like a data class filter, an operator 
suffix never causes any data class to cease to exist! 
 
Operator suffixes will seem less silly after reading the section on 
multiple operators, and learning about aggregations and functions in 
later chapters.  Too, you may find yourself in the situation of not 
knowing if a data class will be returned to an operation, and at that 
point you'll realize that a suffixed operator can be used as a 
conditional operation.  A numeric suffixed addition operator 

                         +#

might be considered to mean  
 
     If given a numeric, add it; but otherwise, perform no  
     addition operation---cancel it!   
 
But onward to data class filters with operators! 
 
Whitespace must, of course, appear between an operator and a data 
class filter.  Since a data class filter permits its data class to 
exist and prohibits the existance of the opposite data class, filters 
can often be used to similar effect as an operator suffix.  The 
following macro fragments, as far as they go, are functionally 
equivalent: 
 
                    +$ "string" 
                    + $ "string" 
 
The substitution of a string filter for a string suffix, however, can 
get you into trouble.  The following are not functionally equivalent:  
 
                    +$ 65 
                    + $ 65 
 
The first of this pair performs a string by numeric addition---which 
concatenates the rounded to integer numeric right-hand operand modulo 
256 character to the left-hand string.  (65 is an `A'.)  The second of 
the pair does not perform any operation, since no data class value 
exists when the operator recieves the right-hand operand value.  In 
effect, that operation is cancelled.  In fact, anytime you wish to 
ensure a binary operation is cancelled, all you have to do is use both 
data class filters (in either order, of course):  
 
                    # $ 
 
This capability is neither as stupid or as easy to use as it seems.   
The hard part is that the operator, data class filters and returned 
value(s) must all be at the same accumulator plane, level.  I'll let 
it remain a `dumb' thing until you're a proficient eX programmer and 
run into those very rare and probably avoidable instances where it is 
useful.  But to give you a hint, a program branch or sub-program call 
would probably appear after the operator, and the filters might be 
conditionally executed `somewhere else'.   
 
I've already mentioned the `no operation' operator nop that can be  
used to postpone an operation.  The following simple example is the 
easiest way to show what nop does:  
 
                    + nop 5 10 
 
A nop `consumes' the value(s) it recieves and forces eX to continue 
execution until another value is encountered.  In the above, the value 
5 is consumed and the value 10 is added.  It's something that was 
thought necessary in an earlier version of eX but still can be useful. 
 
I'd like to ensure realization of the following before going on to 
multiple operators.  A single (occurance of a) binary operator may be 
made to perform either a numeric by numeric operation or a string by 
string operation, or both simultaneously.  A single (occurance of a) 
string suffixed binary operator can be made to perform a string by 
string operation OR a string by numeric operation, but no other 
operation.  A single (occurance of a) numeric suffixed binary operator 
can only be made to perform a numeric by numeric operation.  
 
 
Multiple Operators 
    
Since an operator does not terminate the existence of a data class,    
or eev, multiple operators may employ a single right-hand operand.   
The only idiosyncracy that must be remembered is that operations in a 
multiple operator sequence are performed in the reverse order of their 
appearance, i.e., right to left.  The macro fragment  
 
                    / + 25 
 
will first add 25 to the accumulator, then divide the accumulator by 
25.  Given that prior to execution the numeric accumulator value was 
75, the accumulated result will be 4.  (75 plus 25 divided by 25 
equals 4.  Therefore, the above is simply short-hand for + 25 / 25.)  
 
Data class filters and string operator suffixes can be used to expand 
the situations where multiple operators are appropriate.  To show 
this, I'll use eX's alphabetic term function  
 
               aTerm(SearchObject$, n#) 
 
It returns both the string value and position of the nth alphabetic 
term in SearchObject$, if it exists.  Otherwise, it returns 0 and the 
null string ("").  (A string term, of course, is delimited by 
whitespace or whitespace and an end of the string.)   
 
Don't know why, but I want to add (concatenate) the term to the 
string accumulator and multiply the numeric accumulator by the term's 
position.  The following code will do this for me (the asterisk *, 
ASCII code 42 is the multiplication operator):  
 
               +$ *# aTerm("123 South Street", 1) 
 
Here, the numeric accumulator will be multiplied by 5 and "South"  
will be added to the string accumulator.  Both the numeric and string 
values are still available for any preceding requirement after the 
operations have been performed.  For example, show, which you've already 
seen in the Preface and Overview---you did read them, didn't you?---can 
appear before the addition operator and will send both the term and its 
position to video.  (Here, it could also appear between the operators, and 
you might want to note that unlike the majority of multiple operator 
occurances, it makes no difference which order the operators occur.) 
 
 
Operated Addresses 
 
Two of eX's three forms of aggregation (discussed in a subsequent 
chapter) always return both a numeric and a string, and 
increment/decrement the accumulator level.  Since there may be times 
when either or both of these aggregation characteristics might be 
inconvenient, eX provides `operated addresses', which at the 
conceptual level, is simply another form of aggregation.  The token to 
perform an operated address is the percent sign `%', ASCII code 37, and 
it must appear between the left-hand operand and the operator.  
Operated addresses may be performed with numeric and/or string data.  
The following operated address returns (only) the numeric value 3:   
 
                         1 % + 2 
 
As expected, operated addresses are performed left to right.  Any 
operator appearing in an operated address may have an operator suffix, 
and you can use data class filters between the operator and its  
right-hand term as well.   
 
Multiple operators may be used in an operated address, but the 
operated address token for the multiple operator group must appear 
only once:  
 
                         4 % * + 5 
 
and the operations that form the multiple operator group are performed 
right to left.  (That example returns 45.  4 + 5 = 9, 9 * 5 = 45.)  
Any number of terms greater than one may be employed in an operated 
address, but each operator or multiple operator group must be preceded 
by an operated address token:    
 
                    1 % * + 2 % * 3 
 
(This one returns 18.  1 + 2 = 3, 3 * 2 = 6, 6 * 3 = 18.  The multiple 
operators are performed right to left, but otherwise the expression is 
performed left to right.)  
 
The data class returned by an operated address is determined by its 
first, or left-hand operand.  If that term provides both a string and 
a numeric---which the parens aggregation in the following does---both 
a string and a numeric are returned by the operated address.   
 
          2 % + "string"           returns   2 
          "string" % *$ 2          returns   "stringstring" 
          (2 + "string") % * 4     returns   8 and "string" 
 
Note that in the last example given above, the left-hand operands are 
the values returned by the aggregation and not the aggregation itself, 
a significant point.  The operated address returns the numeric 8 and 
the string "string".  Since the right-hand operand did not provide a 
string, no string by string operation was performed.  But one more 
thought about the aggregation above.  If it had been preceded by a 
data class filter, the left-hand operand would have been that data 
class only:   
 
          # (2 + "string") % * 4   returns   8 
 
A data class filter `belongs' to the value producing term it preceeds. 
 
This seems a good place to remind you that I'n showing you what eX can 
do---not how eX programs should be written! 
 
The mechanics of an operated address are slightly more complex than 
may be apparent.  The current accumulators are pushed onto the 
internal accumulator stack for later recall and the left-hand operand 
values(s) is (are) placed in the accumulator(s).  Processing then 
continues in the usual manner.  When the operated address is complete, 
the aggregate value(s) is (are) returned and the accumulator values 
are restored from the internal stack.  
 
 
Assignment 
 
I liked Pascal's assignment operator (the combination of a colon, 
ASCII code 58 and an equals sign, ASCII code 61) so much that I `borrowed'
it:  
 
                              := 
 
It may be read as `becomes equal to' and assigns the value produced by 
the assignment operator's right-hand term to the data entity that is 
the assignment operator's left-hand term.  The right-hand term may be 
anything that produces a value: a term, eXpression, function, and in 
some cases, a statement.  The left-hand term is an address to any data 
entity and the value it returns is its post-assignment value.  An 
assignment statement may appear in a macro wherever a data entity may  
appear.  (The real reason := is used is because it's easy to 
interpret.  Thanks, Blaise!) 
 
Assignments in eX are pretty straight-foreward if you keep within the  
confines of traditional programming languages, but you need to know 
that assignments are local to the accumulator plane and level in which 
they appear.  Logically, only whitespace may appear between an 
assignment object and its assignment operator.  As long as the 
assignment operator at least ultimately gets a value, you can do 
almost anything after the operator.  The following assigns the value 
1 to the short integer variable _x:   
 
                              _x := 1 
 
 
An assignment need not have anything to do with the surrounding code;  
one that appears in an eXpression is inert to that eXpression if it is 
not preceded by an binary operator. (A data entity always provides is 
value, or post-assignment value, but that value doesn't need to be 
used.)  In the macro   
 
                         + 25 _X := 25 + 50 
 
_X will have the value 25 and 75 will have been accumulated after 
execution.  An assignment that is preceded by an binary operator is 
not inert to that eXpression.  Changing the macro given above to   
 
                        + 25 + _X := 25 + 50 
 
would change the value accumulated to 100 but 25 would still be   
assigned to _X.  But let's go on to more interesting things.  
 
 
Operated Assignments 
 
 
I liked C's increment operator (++) as well, but thought it a bit  
limited.  So I provided eX with `operated assignments':  
 
                         _x := * 4 
 
I'm sure you see that the above assignment is just `short-hand' for  
 
                      _x := (_x * 4) 
 
Any eX operator, with or without an operator suffix, may be employed 
as the operator, and multiple operators are permitted as well (which 
are performed right to left).  The operator's right-hand operand may 
be any value-producing language component, and data class filters may 
preceed it.  As with an operated address, the pre-assignment value of 
the data entity temporarily displaces the accumulator value(s).  
 
You can use operated addresses on either side of an assignment as 
well:  
 
               _x := * + 5 % * + 5 
               5 % + _x := + 5 % * 6 
 
In fact, you can get pretty crazy with assignments, if you'd like.  In 
the following, _x winds up with the value 15:  
 
                    _x := 5 
                    _x := + (_x := 10) 
 
This is because eX stores the value of a data entity when it is 
encountered in an assignment statement.  The only thing the assignment 
of _x in the parens aggregation had to do with the assignment of _x 
preceding the parens aggregation was to supply the value for the 
operated assignment.  To be sure, the assignment in the aggregation 
was made, but superceded.  
 
eX also stores the data entity identifier.  Recalling the eX word 
forget, which `destroys' a data entity, _x will again equal 15 after  
you run the following:  
 
                    _x := 5 
                    _x := + (10 forget _x) 
 
Since eX stores the identifier even if you've addressed the variable 
by its variable type number, the following works just as well as the 
preceding and demonstrates indirect variable methods as well.  The eX 
function `VarId' seen below returns a variable's name and data type 
number.  
 
                    _VarNo := VarId "_x" 
                    $VarName := VarId "_x" 
                    _(_VarNo) := 5 
                    _#_VarNo := + (10 forget _($VarName) 
 
eX recreates the variable for the assignment, of course.  Just though 
you'd like to know.   
 
 
Multiple Assignments 
 
I also liked C's multiple assignment statements.  eX's go just a step 
further in that any data entity may appear in a multiple assignment 
statement. 
 
          _a := __b := .c := ..d := $e := @ := (5 + "string") 
 
Given the knowledge that the parens aggregation returns the numeric 
value 5 and the string value "string", $e and the string accumulator 
are assigned the value "string" and the numeric accumulator and 
variables are all assigned the value 5.  Had the numeric value 
included a fractional part, the value assigned to the integer 
variables would have been rounded to integer.  (Regrettably, an 
overflow will cause a crash.)  Operated assignments may appear only as 
the last assignment in a multiple assignment statement.   
 
                         _x := _y := * + 5 
 
The pre-assignment value of _y is used as the left-hand operand, of  
course, and _x will be assigned _y's post-assignment value.  
Naturally, `whatever' may be used to provide the assignment value.  
 
I like to say that you can do anything anywhere in eX, but while it 
isn't absolutely true, it comes pretty close.  For example, the 
statement form of the eX word `vPage' (video page) can be used in a 
multiple assignment statement if it appears to the right of an  
assignment operator since other than setting the (active) video page, 
it is inert (returns nothing):   
 
                    _x := vPage 3 _y := 2 
 
_x and _y will equal 2 and the active video page will be 3.  (That 
example is hard for us humans to read correctly.)  But as it returns 
the active video page number, the function form of vPage is not inert, 
and the following is not a multiple assignment statement:  
 
                    _x := vPage# _y := 2 
 
A nop before the function would restore it to a multiple assignment  
statement, and that brings eX knowledge to the point where macros can 
be created with an obscurity level sufficient for entry-level 
sado-masochists.  Obviously the above should be written  
 
                         vPage 3 
                         _x := _y := 2 
 
and  
 
                         _x := vPage# 
                         _y := 2 
 
but then I'm just trying to teach you eX.  
 
 
Radix Operators 
 
Although called operators, the eX radix operators are not really 
operators at all.  More properly considered number base declarations, 
they are implemented as functions that return the base 10 value of the 
radix argument.  But since I call them operators, they're in this 
chapter.  The following returns 255 from the hexadecimal argument:  
 
                              &h "ff" 
 
The radix operators are given in the section `Radix Operators' of the  
reference chapter `Operators'.  
  
eX also provides radian/degree of arc and Celsius/Fahrenheit 
temperature conversion functions that are written as radix operators.  
These are given in the section `Radix Functions' in the  
reference chapter `Data Type Cast & Radix Functions'.  
 
 
 
By Way of Explanation and  
     In Defense of the Reputation of My Mental Health. 
 
(Not required reading.) 
 
 
When I began contemplating eX I thought about strings and operators.  
It seemed to me that since string concatenation is simply the addition 
of a string to another string (indicated in most computer languages by 
the addition operator +), string de-concatenation would simply be the 
reverse process, subtraction (-).  It immediately became apparent that 
un-like numbers, where you can subtract a large number from a small 
number, producing a negative result, strings are like a basket of 
apples---you can remove apples from the basket only if the basket has 
apples in it!  Ergo,  
 
     "concatenated" - "ed"  should yield  "concatenat", and     
     "concatenat"   - "ed"  should yield  "concatenat". 
 
And this led to 
 
           "educated" - "ed"  should yield  "educat", 
           "educate"  - "ed"  should yield  "ucate", 
           "educate"  - "Z"   should yield  "educate", and 
           "educate"  - ""    should yield  "educate". 
 
Completing the simile, the string to be subtracted is a particular 
kind of apple, the string it is to be subtracted from is the basket 
(whose open top is the right side of the string), and you should 
remove the first matching `apple' encountered while reaching down into 
the basket from its top.  If no matching apple is encountered, one 
cannot be removed.  From this, the rest of the string by string 
operations came into being.  
 
Since a number represents a quantity and not a type, it seemed logical 
that string by numeric subtraction should remove the first `number'
apples from the basket, regardless of the type of apple encountered 
(character value).  Again, the maximum number of apples that could be 
removed from the basket would be the number of apples in the basket--- 
regardless of how many apples you wished to remove.  And, the only way 
to define an apple would be to equate an apple to an individual string 
character.  Therefore,  
 
                 "12345" - 0  should yield  "12345", 
                 "12345" - 1  should yield  "1234", 
                 "123"   - 5  should yield  "", and  
                 ""      - 5  should yield  "" 
 
But how should one add a number to a string?  Should number characters 
of the string be concatenated, and if so, which characters of the 
string should be concatenated?  And what if number is larger than the 
length of the string?  Should number characters be concatenated to the 
string, and if so, what would the character values be?  In either of 
these scenarios, how would one cope with a large number or fractional 
part?  What in the world should be done with a negative number?  I 
hate to admit that string by numeric addition was the last operation 
decided upon and have yet to decide how to handle negative numbers.   
(Absolute value, negation, logical not?) 
 
 
I believed that if one could aggregate both  
 
                              (5 + 6)  
and  
                          ("aggr" + "ate"), 
 
it seemed to follow that one should be able to aggregate 
 
                          (5 + "aggregate"). 
 
But while I can put apples and oranges in the same basket and retrieve 
either an apple or an orange as desired, I didn't see any way (let 
alone a simple way) to be able to put numbers and strings in the same 
basket, let alone retrieve them as desired.  Since I was planning on 
using a dimensioned accumulator data entity to perform aggregation and 
serve as the left-hand operand for binary operations, the simple 
solution was to provide an accumulator data entity for both classes of 
data.  I was then able to aggregate (5 + "string"), but I also needed 
to be able to aggregate both 
 
                   ((5 + "aggre") + ("gate" + 6)) 
 and 
                        ((5 + "aggre") + 6). 
 
In order to keep the interpreter as simple as possible, eX was made to 
perform the type or types of operations dictated by the data classes 
presented to its operators---no `look ahead' processes would be 
needed---and this lead to providing string by string and string by 
numeric capabilities for all the operators.   The lack of a look ahead 
process also allows permissiveness that you'll learn about in the 
subsequent text.  
 
