QMBasic - Expressions and Operators
A QMBasic expression consists of one or more data items (constants or variables) linked by operators.
In all cases above, var may be a matrix reference, for example
where r and c are expressions which evaluate to the desired matrix row and column index values.
There is also a special conditional item of the form
IF conditional.expr THEN expr.1 ELSE expr.2
where conditional.expr is evaluated to determine whether the overall value is that of expr.1 or expr.2.
The Boolean (True/False) values used by QMBasic are stored internally as a Boolean data type, however, use of a Boolean value in an operation that requires a numeric value converts True to one and False to zero.
The Boolean constant values are available as @TRUE and @FALSE for use in programs and dictionary I-type expressions.
The substring extraction operation x[s,n] extracts n characters starting at character s of the string x. Character positions are numbered from one. Thus
A = "abcdefghijkl"
Z = A[5,3]
sets Z to the string "efg".
If the bounds of the substring extend beyond the end of the string from which it is to be extracted, the result is truncated. Trailing spaces are not added to make up the shortfall. A start position of less than one is treated as one.
Specifying the number of characters, n, as an asterisk extracts from character s onwards, regardless of the length of the string.
A = "abcdefghijkl"
Z = A[5,*]
sets Z to the string "efghijkl".
The trailing substring extraction operation x[n] extracts the last n characters of the string x. Thus
A = "abcdefghijkl"
Z = A
sets Z to the string "jkl".
If the length of the substring to be extracted is greater than the length of the source string, the entire source string is returned.
The third form of substring extraction, known as group extraction, is of the form var[d,s,n]. It treats var as being made up of a series of sections delimited by character d and returns n consecutive sections, starting at section s. See the FIELD() function for an alternative syntax.
The field extraction operator x<f,v,s> extracts field f, value v, subvalue s from the source string x. If s is omitted or zero, field f, value v is extracted. If v is omitted or zero, field f is extracted. Thus
The operators of QMBasic are set out in the table below. The numbers in the right hand column are the operator precedence, the lower valued operators taking precedence in execution. Operations of equal precedence are processed left to right. Round brackets may be used to alter the order of execution or to improve readability of complex expressions.
The following alternative logical and relational operator formats may be used
The relational operators are defined such that, if the two items to be compared can both be treated as numbers, a simple numeric comparison is performed. If one or both items cannot be treated as numbers, they are compared as left aligned character strings. The COMPARE() function can be used to force a string comparison that returns a value indicating the collating sequence relationship of the two items being compared.
If a program is compiled using the $NOCASE.STRINGS directive, string comparisons are case insensitive. The == operator can be used to force a case sensitive comparison. Conversely, in program compiled without this directive, the ~= operator can be used to force a case insensitive comparison.
Note: The language syntax includes an ambiguity with the use of the < and > characters as both relational operators and in dynamic array references. For example, the statement
A = B<C> + 0
could be extracting field C from dynamic array B and adding zero to it (to force it to be stored as a numeric value) or it could be testing whether B is less than C and the result of this comparison is greater than zero. In cases such as this, the compiler looks at the overall structure of the statement and takes the most appropriate view. Use of brackets when mixing relational operators with field references will always avoid possible misinterpretation.
The MATCHES operator matches a string against a pattern consisting of one or more concatenated items from the following list.
The values n and m are integers with any number of digits. m must be greater than or equal to n.
The 0A, nA, 0N, nN and "string" patterns may be preceded by a tilde (~) to invert the match condition. For example, ~4N matches four non-numeric characters such as ABCD (not a string which is not four numeric characters such as 12C4).
A null string matches patterns ..., 0A, 0X, 0N, their inverses (~0A, etc) and "".
The 0X and n-mX patterns match against as few characters as necessary before control passes to the next pattern. For example, the string ABC123DEF matched against the pattern 0X2N0X matches the pattern components as ABC, 12 and 3DEF.
The 0N, n-mN, 0A, and n-mA patterns match against as many characters as possible. For example, the string ABC123DEF matched against the pattern 0X2-3N0X matches the pattern components as ABC, 123 and DEF.
The pattern string may contain alternative templates separated by value marks. The MATCHES operator tries each template in turn until one is a successful match against the string. If a match is found, the INMAT() function can be used to retrieve the value position within the pattern that matched.
As an example of the MATCHES operator, the statement
IF S MATCHES "1N0N'-'1N0N" THEN PRINT "OK"
would print OK when S contains one or more digits followed by a hyphen and one or more digits. Note the use of 1N0N to ensure that at least one digit is present.
MAT matrix1 = MAT matrix2
as a Boolean element in, for example, an IF statement. The only valid relational operators in this usage are equals and not equals.
Partial Expression Evaluation
The default behaviour of QM, in common with many other multivalue database products, is that a logical expression is always completely evaluated before taking any action conditioned by it. For example,
IF IDX MATCHES '1-2N' AND S<IDX> # 0 THEN ...
will test the value of S<IDX> regardless of whether the value in IDX is numeric or not. This would lead to a run time error if IDX is not numeric.
Use of the PARTIAL.EXPRESSIONS setting of the $MODE compiler directive causes logical expression evaluation to terminate as soon as the result can be determined. For a non-numeric value in IDX, the above example would skip the test of S<IDX>.
The difference between these two methods of evaluation is also important if the expression includes a reference to a function that has a side effect. For example,
IF X = 1 AND REMOVE(STR, CODE)
In the default mode of operation, the REMOVE() function is executed regardless of the content of X. With the PARTIAL.EXPRESSIONS mode, the REMOVE() function is only executed if X is 1.