I've decompiled yet another Pascal compiler for the BESM-6.
While it does not implement the full language (for example, packed records and arrays are not implemented, helper routines SEL
and INS
are offered instead to manipulate parts of words), there is a feature which would have been a good addition to the standard, if Wirth had thought of it in time, namely using its range check feature not only as a "behind the scenes" mechanism, but as a user-accessible predicate.
It is well known that although Pascal allowed to declare "set" types, e.g.
type bits = 0..31; bitset = set of bits;
the maximum capacity of such types was limited. The early implementations restricted a set type to a single word with whatever word size the host computer had. For example, CDC 6600 had 60, BESM-6 had 48.
With set types of limited use, and the language having range subtypes as first-order constructs, one might ask, what would be a better way to succinctly write a check for a value being within an arbitrary range of a discrete type. Suppose, I have
type range = 1000000..2000000;
and I want to check if an integer variable is within that range. The best solution the standard can offer is to write
const rangeLow = 1000000; rangeHigh = 2000000; type range = rangeLow..rangeHigh; function isInRange(i:integer):boolean; begin isInRange := (rangeLow <= i) and (i <= rangeHigh) end;
However, when one has
var r:range;i:integer;
and writes r := i;
, the compiler inserts a range check which makes the program terminate if unsuccessful. There is no way to use that internal range-checking mechanism to a user's advantage.
The solution implemented and employed in the BESM-6 Pascal compiler was:
(*=P-,T-,M-*)
_PROGRAM MAIN;
_TYPE RANGE = 1000000..2000000;
_VAR I,R,S:INTEGER;
_BEGIN
S := 0;
R := 1;
_FOR I := 1 _TO 1000000 _DO _BEGIN
_IF R _IN RANGE _THEN S := S + 1;
R := (R * 1001 + 1234567) _MOD 4294967296
_END;
WRITELN(S/1000000);
_END.
It prints
2.3100Е-04
When the compiler encounters EXPR in TYPE
in an if
operator, it generates code as if EXPR was about to be assigned to a variable of type TYPE, pointing the "failure" target to the else
clause (or beyond the then
clause), as opposed to the PMD routine for the actual range checks.
The range-checking code is then associated with TYPE and is reused if other instances of EXPR in TYPE
are encountered.
This looks more succinct and user-friendly than requiring the user to write the check explicitly, as above.
Has there been another Pascal compiler with such a feature? Or is it only in the USSR where they dared to extend the language in such a way?
_GOTO
and_GO _TO
; as it turns out, supporting that adds a trivial amount of code.