3.5 ExpressionsThis chapter explains the meaning of the elements of expressions in emBASIC. Elements of expressions are one of either literal, variable reference, or another expression, possibly in parenthesis. A variable reference is the name of a simple variable. Reference to an array element is the name of an array followed by a list of expressions in square brackets.
3.5.1 Arithmetic conversionsGenerally, emBASIC performs automatic type conversion and it is not needed
to specify conversion explicitly. Numeric operands are converted to the
same type automatically. Shorter types are converted to longer ones, unsigned
to signed, integer types to float ones LONG and DWORD are converted directly
to DOUBLE. There is no automatic conversion between numbers and strings.
In common cases, the numbers are converted to a common type and then the
operation is applied.
|
/ | The / (division) operator yields the quotient of its arguments. The numeric arguments are first converted to a common type. Plain or long integer division yields an integer of the same type | |
DIV | Integer division. Yields a rounded integer result of the division of two arbitrary numbers. In other words A DIV B is equivalent to (INT)(A/B) | |
% or MOD | Modulo. Valid for all numeric operands. The modulo operator yields the remainder from the division of the first argument by the second. The numeric arguments are first converted to a common type | |
* | The * (multiplication) operator is valid for all numeric operands. It yields the product of its arguments. The arguments must both be numbers. In common case, the numbers are converted to a common type and then multiplied together. | |
+ | The + (addition) operator yields the sum of its arguments. The arguments must either both be numbers or both strings. In the former case, the numbers are converted to a common type and then added together. In the latter case, the strings are concatenated. | |
- | The - (subtraction) operator yields the difference of its arguments. The numeric arguments are first converted to a common type. |
The shift operators have lower priority than the arithmetic operators:
expression >> expression
expression << expression
These operators accept plain or long integers as arguments. The arguments
are converted to a common type. They shift the first argument to the left
or right by the number of bits given by the second argument.
Negative shift counts behavior is defined by hardware. Below the examples
for the TSMCPU32H2:
PRINT 2 >> -1 // produces 0
PRINT 4 >> -1 // produces 0
PRINT 2 << -1 // produces 0
PRINT 4 << -1 // produces 0
PRINT 1 << -1 // produces -32768
Each of the three bitwise operators has a different priority level.
The & (or BAND) operator yields the bitwise AND of its arguments, which must be plain or long integers. The arguments are converted to a common type. This operator has a higher priority then bitwise OR operator, but has the same priority as bitwise XOR operator.
The ^ (or BXOR) operator yields the bitwise XOR (exclusive OR) of its arguments, which must be plain or long integers. The arguments are converted to a common type. This operator has a higher priority then bitwise OR operator, but has the same priority as bitwise AND operator.
The | (or BOR) operator yields the bitwise (inclusive) OR of its arguments, which must be plain or long integers. The arguments are converted to a common type. This operator has a lower priority then AND and XOR operators.
All comparison operators in emBASIC have a left association and a priority lower than that of any arithmetic, shifting or bitwise operation.
"<" ">" "==" ">=" "<=" "<>"
The forms <> and != are equivalent; for consistency with C, != is preferred; where != is mentioned below <> is also accepted. The <> spelling is considered deprecated.
The operators <, >, ==, >=, <=, and != compare the values
of two objects. The objects need not have the same type. If both are numbers,
they are converted to a common type.
Comparison of objects of the same type depends on the type:
Numbers are compared arithmetically, strings are compared lexicographically
using the numeric equivalents.
Boolean operations have the lowest priority of all emBASIC operations:
In the context of Boolean operations, and also when expressions are used
by control flow statements, the following values are interpreted as false:
numeric zero of all types and strings. All other values are interpreted
as true.
The operator ! (or NOT) yields 1 if its argument is false, 0 otherwise.
The expression x && y (or x AND y) first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
The expression x || y (or x
OR y) first evaluates x; if x is true, its value is returned; otherwise,
y is evaluated and the resulting value is returned.
An expression containing at least one comma yields a list. The length of the list is the number of expressions in the list. The expressions are evaluated from left to right:
expression_list ::= [“{“] expression “,” expression * [“}”]
Expression lists are used to assign values to lists of variables and multiple array elements to arrays or ranges within an array. Examples:
var1, var2, name = 10, 300, “Alex”
arr[3..6] = {20, 22.5, 25, 27.5}
Simple statements are comprised within a single logical line. Several simple statements may occur on a single line separated by semicolons.
FOR i = 1 TO 4; a[i] = i*2; NEXT i
Expression statements are used to compute and write a value, or to call
a procedure (a function that returns no meaningful result; in emBASIC,
procedures return the value void
Assignment statements are used to (re)bind names to values and to modify
attributes or values of system variables.
An assignment statement evaluates the expression list (remember that
this can be a single expression or a comma-separated list, the latter
yielding a value list) and assigns the single resulting object to each
of the target lists, from left to right.
Assignment is defined recursively depending on the form of the target (list). When a target is part of a mutable object (an attribute reference, array subscription or slicing), the mutable object must ultimately perform the assignment and decide about its validity, and may raise a parse error if the assignment is unacceptable.
Assignment of inexistent enumeration values to the target raises a runtime error.
Assignment of an object to a target list is recursively defined as follows.
· | If the target list is a single target | The object is assigned to that target |
· | If the target list is a comma-separated list of targets | The object must be an array with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets |
Assignment of an object to a single target is recursively defined as follows:
· | If the target is an identifier (name) | If the name does not occur in a DECL PUBLIC statement in the current
task: the name is bound to the object in the local namespace or the
current task. Otherwise: the name is bound to the object in the global
namespace. The name is rebound if it was already bound. |
· | If the target is an attribute reference | The primary expression in the reference is evaluated. It should
yield an object with assignable attributes; if this is not the case,
error is raised. That object is then asked to assign the assigned
object to the given attribute; if it cannot perform the assignment,
it raises an error. |
· | If the target is a subscript | The primary expression in the reference is evaluated. It should yield an array object. Next, the subscript expression is evaluated: If the primary is an array object, the subscript must yield an unsigned integer. The resulting value must be a nonnegative integer less than the array's length, and the array is asked to assign the assigned object to its item with that index. If the index is out of range, runtime error will be is raised, there are no boundary checks performed in interactive mode (assignment to a subscripted array cannot add new items to it). |
· | If the target is a range | The primary expression in the reference is evaluated. It should
yield an array object. The assigned object should be an array of the
same type. Next, the lower and upper bound expressions are evaluated,
insofar they are present; defaults are zero and the array's length.
The bounds should evaluate to unsigned integers. The resulting bounds
are clipped to lie between zero and the sequence's length, inclusive.
Finally, the sequence object is asked to replace the range with the
items of the assigned array. The length of the range may be different
from the length of the assigned array, but changing the length of
the target array is not allowed and raises an error. |
Examples:
a = 10
b = “string”
a,b = 10, “string”
a[1],b = 12, “string
a[1..3] = {12,13,14}
Combined assignment is the combination, in a single statement, of a binary operation and an assignment statement. Combined operators are:
"+=" "-=" "*=" "/=" "%=" "**=" "&=" "^=" "|="
A combined assignment evaluates the target and the expression list, performs the binary operation specific to the type of assignment on the two operands, and assigns the result to the original target. The target is only evaluated once.