Logical versus Arithmetic Operators

Although the operators AND, OR, and NOT are generally used as if they were purely logical, in fact, in A-Shell BASIC they are really arithmetic (bitwise). The apparent logical nature is a side effect of the fact that in an IF statement (which has the general form IF <expression>), after all of the operations which make up the <expression> have been evaluated, reducing the expression to a single value, the IF statement then treats the result as TRUE if non-zero or FALSE if zero.

So, for example, in evaluating the statement IF X AND Y THEN ..., the expression evaluator first performs an arithmetic bitwise AND of the two operands X and Y, and if the result is non-zero, the expression is considered TRUE and the THEN clause will be executed. This is not the same as a truly logical AND, which would return a TRUE value for the expression if either A was TRUE or B was TRUE. To illustrate, consider the case where X=6 and Y=1. In binary form, this is 110 and 001, and the bitwise AND operation returns 000 (FALSE), even though each operand was individually TRUE (non-zero). This is one reason why you should always use -1 rather than 1 to represent the logical value TRUE.

When used properly, the arithmetic bitwise nature of the operators AND, OR, and NOT may be used to advantage when dealing with bit patterns. For example, if X is a bit field (where each bit represents a flag), you can test if a one or more individual bits are set using AND. For example, the statement IF X AND &h0011 will test whether either of the two lowest bit flags are set in the variable X. Similarly, you can use the OR operator to set the bits, e.g.:

BIT1 = &h0001

BIT2 = &h0002

BIT3 = &h0004

FLAGS = FLAGS OR BIT1 OR BIT3   ! sets the first and third bit, leaving the others alone.

 

To reset (clear) a bit, you can use the combination AND NOT:

FLAGS = FLAGS AND NOT BIT2      ! clears the 2nd bit, leaving the other bits alone

 

When creating compound IF statements involving multiple operators, it is wise to use the equals (=) and not equals (#) operators, with parentheses, to force the individual sub-expressions to be converted from bit fields to logical results. For example, instead of:

IF (FLAGS AND BIT1) AND (FLAGS AND BIT3) THEN...        ! this will never be TRUE unless BIT1 and BIT3 overlap

 

you should use:

IF ((FLAGS AND BIT1)  # 0) AND ((FLAGS AND BIT3) # 0) THEN   ! TRUE if both BIT1 and BIT3 are set in FLAGS

 

The parentheses in the first expression above don't really accomplish anything, and the result of the entire expression will only be non-zero (TRUE) if BIT1 and BIT3 overlap each other and one or more "1" bits in FLAGS, which is clearly not the intended meaning. The use of the # (not equal) operators in the second expression converts the arithmetic result of each subexpression into a truth value (i.e. either -1 for TRUE or 0 for FALSE), so that the central AND will actually operate in the expected (logical) fashion.