This is an example of a program in EXALT:
Roots of a quadratic equation PRINT ;'&';'Enter A, B, and C: ' INPUT A,B,C . DISC=B*B-4*A*C TEST DISC, Discriminant negative: two complex roots ?< . RD=_SQR(-DISC) PRINT 'Two complex roots:' . X=-B/2*A . Y=_ABS(RD/2*A) PRINT X,'+',Y,'i' PRINT X,'-',Y,'i' ?> , Discriminant zero: one real root ?< PRINT 'One real root:' PRINT -B/2*A ?> , Discriminant positive: two real roots ?< . RD=_SQR(DISC) PRINT 'Two real roots:' PRINT (-B+DISC)/2*A PRINT (-B-DISC)/2*A ?> END
This example program looks much like a program in FORTRAN or BASIC. Obviously, its purpose is to solve for the roots of a quadratic equation. Two distinctive features of EXALT not previously discussed are visible from this example program.
The first line of the program, plus three other lines later in the program that are also not indented, are comment records. Note that such records have no connection with the syntax decoding of the program; they can contain any character, and they may appear, as the latter three do, in the middle of a statement.
Note, however, that this applies only to non-indented records beginning with a letter or an asterisk (*). Line numbers may begin in the first column of a record, or they may be preceded by one or more spaces.
The first statement contains a semicolon separating two arguments of a PRINT statement. Commas are used to separate items in the argument list of a PRINT statement later in the program. In EXALT, the semicolon (;), comma (,), and colon (:) are all used to separate arguments to functions and subroutines, and are used for similar functions in some statements.
The semicolon is a higher-order separator than the comma; it separates arguments of different kinds. In this case, it separates a printer control character (the ampersand (&), indicating that the cursor is to be left at the end of the text to be printed after printing) and the text to be printed. A semicolon precedes that item as well to indicate that the device number is not specified, but is an omitted argument. Since the ampersand is within quote marks, it has no 'escape' function.
The colon is a lower-order separator than the comma; it separates arguments which are associated with each other. In a PRINT statement, a colon can be used to separate the item to be printed from a local format specification telling how that particular item is to be printed.
Almost always, these separators are followed by another argument, or they would not be needed. An omitted argument in the middle of a list can be indicated by two separators with nothing between them, but one at the end of a list needs no separators to show it isn't there. Thus, EXALT is able to allow a break between records to appear after a separator without ending a statement.
It is, however, possible to specify for a function, and it is true of some input/output statements, that where a specific separator is omitted, the argument preceding that separator is to be the one assumed omitted. In the case of a function, the closing parenthesis means there is no problem; in the case of a statement, statement end must be forced using the @/ entity.
Note that 'null statements' are permitted in EXALT: the @/ referred to above need not be followed by a statement on the same line; the symbol ?> in the program above could appear on the line following the last statement of the alternative it delimits rather than, as above, at the end of the line containing that statement; and the text of a program may contain blank records.
The vertical bar (|), with the substitute ?1; , and the backslash (\), with the substitute ?2; , are also separators. The backslash is of higher order than the vertical bar, which is in turn of higher order than the semicolon. Normally, only the substitutes would be used, to avoid memorizing an arbitrary assignment; but these two symbols are useful as separators to allow, for example, alternative notations for the elliptic integrals.
The entities ?3; , ?4; , and so on, indicate separators of successively higher order. Similarly, ?1: , ?2: , and so on indicate separators of lower order than the colon (:).
This leads us to the next fact about EXALT revealed by this example program.
An IF statement in EXALT might look like this:
IF X<Y,10,20
which means, go to statement 10 if X is less than Y, and to statement 20 otherwise.
The Arithmetic IF statement of FORTRAN is represented by the following:
TEST R,10,20,30
which means, go to statement 10 if R is negative, statement 20 if R is zero, and to statement 30 if R is positive.
Because of the rules concerning argument separators, that statement could also be entered in this form:
TEST R, 10, 20, 30
where end-of-record not immediately (except for spaces) preceded by a separator indicates statement end.
In an IF statement, however, a statement number can be replaced by either an asterisk (indicating a fall-through to the next statement: an omitted argument can also indicate this), or a sequence of one or more executable statements enclosed by braces ({ and }) or their substitutes.
Both open and close brace are part of the IF statement, although close brace is encountered when scanning an embedded statement.
Here is a simple example of an IF statement using these features:
IF R, {. M=-1 @/ GOTO 20}, *, {. M=1 @/ GOTO 20}
If R is zero, fall through to the next statement: otherwise, set M to reflect R's sign before going to statement 20.
As illustrated in that example, multiple statements per line (or record) are separated by the symbol @/`.
Undeclared variables in EXALT default as in FORTRAN: to simple REAL variables, unless they begin with a letter from I through N, in which case they default to INTEGER variables. Where an undeclared identifier is followed by parentheses, it is assumed to be the name of an external function with type-ignored argument passing.
The example program contained no type declaration statements, as it did not need them. However, to use types other than REAL and INTEGER, such statements are needed. The basic types available are REAL (floating-point), INTEGER, DECIMAL, COMPLEX, QUATERNION, LOGICAL, and CHARACTER. Many of these types are available in several precisions with different names.
Some information about forming constants in EXALT is required at this point.
In FORTRAN, six times ten to the twenty-third power would be written 6.0E23. In EXALT, letters are not used in such a fashion, to avoid ambiguities in syntax decoding. Instead, the number sign (#) functions as an operator with the following meaning:
A # B is equivalent to A * 10 &PW B
and this operator, like unary plus and minus, is allowed in constants.
The unary operators &I , &J , and &K are used to construct complex and quaternion constants; these operators may be used in prefix or postfix position. (Otherwise, when an operator is described as unary, the reference will be to the prefix use of the operator, and not to the postfix use, if any.) In addition, prefix ! may be used instead of &I ; postfix ! , on the other hand, is the factorial operator.
Since * and / are the only operator symbols used for other purposes in initialization blocks, any constant expression not containing these operators does not have to be enclosed in parentheses in the initialization blocks found in type declaration statements.
A constant containing a decimal point must be REAL (or COMPLEX, or QUATERNION, or DOUBLE__PRECISION, or so on), even if its value is integral. One that does not contain a decimal point may be either INTEGER (or HALFWORD, or LONG) or DECIMAL, or even REAL, if so indicated by context.
In an expression, it is often possible to determine what type conversions are needed, or what types should be given to constants, from context: for example, in the expression D*4.7, the constant 4.7 should have the same type as the variable D, unless D has INTEGER type, in which case the variable D will have to be converted at execution time. This, however, is not always true: FUN(25), where FUN is an undeclared external function, gives no hint as to whether its argument should be an INTEGER with the value 25, or a HALFWORD with that value, or the packed decimal representation of the value 25.
There are two methods of dealing with this; YAL provides a means of indicating the type of a constant explicitly (by using the built-in type conversion function _(type,value)`), and statements that set the default type for constants. Note that _(type,value), if value is a constant, does not cause conversion at execution time; also, it establishes a context for value, thus no significance is lost in value if the default type for constants with the general appearance of value has less precision than the desired type: _(D,3.141592653589793) is as much a valid double precision constant in YAL as 3.141592653589793D+00 is a valid double precision constant in FORTRAN.
Most of the uses of the % symbol relate to the use of constants.
%25 is a constant, and it has as its value the address at which the statement in the program with the line number 25 is stored. %%25 is that statement itself, rather than its address; this is a dangerous entity, but it might be useful as an argument to a core dump program, including the built-in subroutine DUMP.
%Q377 is the number 255; %Q10 is 8. As you may have guessed, %Qn is the number of which n is the octal representation. %X is similarly used to prefix hexadecimal constants, and %B binary constants.
A base-12 constant might look like this: %N(12)3B4, which would stand for the number 3*144+11*12+4, or 567. %N(%B1100)3B4 would even be possible, if you didn't want to specify your base in decimal notation!
A decimal point, although it wouldn't be a 'decimal' point, is allowed in constants expressed to another base: thus, %Q0.1 is equivalent to 1/8th, or 0.125. (%Q.1 is also allowed; in YAL, unlike FORTRAN or COBOL, numeric constants may end or begin with a decimal point) However, as # is an operator, %Q31#5 is 25 times ten to the fifth power, not 25 times eight to the fifth power. # can be replaced by %E, which will follow the base of the number, or you can use
* 8 ^...
explicitly. (Use of %E to replace # in decimal constants is allowed, but should not be necessary as a means of avoiding arithmetic at execution time.) %E is not an operator, and cannot act on variables or other expressions.) Also, note that the number following %E is in the same base as the number preceding it, unless a new base specification follows %E. (i.e. %E%X or %E%N(...)) Base 10 can be indicated with %D.
Hexadecimal notation uses the digits 0 through 9, followed by the letters A through F. %N constants use the digits 0 through 9, followed by the letters A through Z, as needed. This allows bases up to 36. To specify a base-60 number, one uses %M as follows: %M(60)3_11_2 equals 3*3600+11*60+2, or 11,462. As the decimal point is allowed, _COS(%M(60)33.12_15 .DEG) equals the cosine of 33 degrees, 12 minutes, and 15 seconds.
Where %N (or %B, %Q, or %X) follows a %M(...) clause, it applies to all the 'digits' in the %N constant; thus, if you wanted to express each digit of a base-60 number in base-12, just start with %M(60)%N(12).
The 'true' and 'false' values for LOGICAL constants are represented by _T and _F respectively.
Characters enclosed by single quote marks form CHARACTER type constants; for example, 'Hello' is a CHARACTER*5 constant. A constant can be explicitly indicated to have STRING type by using double quotes ("). Since STRING variables have variable length, they are stored in a different manner than CHARACTER constants; this can be important for type-ignored subroutine calls. Elsewhere in expressions, type conversion is automatic, and performed at compile time whenever possible.
%H(5)HELLO is another way of writing 'HELLO' which is useful if all problems with quotation marks are to be avoided (it is especially useful in assisting the automatic generation of YAL programs for this reason).
To create character strings containing control characters, use %T in the following form: %TX2(0330E7) means that Text is to be formed from heXadecimal characters, taken in 2s; thus, a 3-character constant is created, containing the characters with the hexadecimal codes 03, 30, and E7. If 0 (zero) is used, the codes for characters are to be separated by commas: thus, %TD0(3,48,231) refers to the same three-character string. In addition to X and D, B and Q, or N(...) can also be used; %TN(12)3(003040173) is also allowed.
Also, where zero is the length, character strings in quotes can be used as well as numbers to place characters in the resulting string, rather than using the string concatenation operator to create the constant.
Where the CHARACTER*m/n specification is applicable, preface a character constant in quoted, %H, or %T form by %/n to indicate explicitly the type of characters it contains. Thus, %/6%TO2(416077) and %/9%TO3(416077) generate, on appropriate hardware, the same 18-bit memory pattern, but with two different interpretations. On hardware with only one character size supported, they will generate two different memory bit-patterns, the first filling three characters, the second only two.
%T(...) is NOT used to create a default form of coded character string representation; instead, it is used to create type-valued constants; i.e. the statement
IF _CTYP(MV) &EQ %T(REAL), 30
branches to line 30 if the mutable variable MV currently has as its value a REAL number or an array of REAL numbers.