
IF, WHILE, REPEAT, FOR, procedures, functions and VAR parameters all work as they did in the Turbo course's S12 to S16. Three things do not: CASE is written differently, a line that starts with a number needs care in XBAS, and recursion - the thing Turbo made you ask for - works without being asked.
Turbo's case had an else for "anything else", and then an end. HiSoft's ELSE takes the place of the END:
CASE P OF
(**) 1:WRITE('LEFT');
(**) 2:WRITE('MIDDLE')
ELSE WRITE('RIGHT')
There is no END after the ELSE statement. Put one there, the Turbo way, and it is taken to close whatever BEGIN comes before the CASE - the compiler only complains a line or two later.
Without an ELSE, a CASE ends with END as usual, and a value that matches none of the labels does nothing at all.
Why the (**) in front of each label? Because of XBAS. When you type
60 1:WRITE('LEFT');
XBAS reads the line number as far as the digits go - spaces make no difference - and stores line 601, :WRITE('LEFT');. It happens to any line whose Pascal starts with a digit: CASE labels, and GOTO labels.
The cure is to put anything else first. (**) is an empty comment: HiSoft Pascal ignores it, and it keeps the number where it belongs. Or put the label at the end of the line before, after the statement it follows.
Both are there. A GOTO label is declared with LABEL and marks a statement - so in XBAS it too wants (**) in front. A FORWARD procedure gives its parameters once, in the FORWARD declaration; the heading of the procedure itself, later, repeats only its name.
The Turbo course's S16 had to warn you: without {$A-}, a routine that called itself shared its parameters between all its calls, and gave wrong answers without a word. HiSoft Pascal needs nothing. Every call has its own parameters, and a routine can call itself thousands of times deep. If it goes too deep, the program stops with Out of RAM at PC=... rather than going wrong.
One limit: a procedure or function cannot be passed as a parameter to another.
The Towers of Hanoi: move a pile of discs from the left peg to the right, one at a time, never a larger on a smaller. To move N discs, move N-1 out of the way, move the biggest, and move the N-1 back on top - a procedure that calls itself twice.
10 PROGRAM HANOI;
20 VAR MOVES:INTEGER;
30 PROCEDURE NAME(P:INTEGER);
40 BEGIN
50 CASE P OF
60 (**) 1:WRITE('LEFT');
70 (**) 2:WRITE('MIDDLE')
80 ELSE WRITE('RIGHT')
90 END;
100 PROCEDURE MOVE(N,FROM,DEST,SPARE:INTEGER);
110 BEGIN
120 IF N>0 THEN
130 BEGIN
140 MOVE(N-1,FROM,SPARE,DEST);
150 MOVES:=MOVES+1;
160 WRITE(MOVES:2,' ');
170 NAME(FROM); WRITE(' TO '); NAME(DEST);
180 WRITELN;
190 MOVE(N-1,SPARE,DEST,FROM)
200 END
210 END;
220 BEGIN
230 MOVES:=0;
240 MOVE(3,1,3,2)
250 END.
Line 90's END belongs to line 40's BEGIN: the CASE needs none.
Starting from
HANOI.ASC saved from XBAS; HPEIN HANOI.
What you should see
1 LEFT TO RIGHT
2 LEFT TO MIDDLE
3 RIGHT TO MIDDLE
4 LEFT TO RIGHT
5 MIDDLE TO LEFT
6 MIDDLE TO RIGHT
7 LEFT TO RIGHT
80 ELSE WRITE('RIGHT') END, the Turbo way. Where does the compiler complain, and why there?70 (**) 2:WRITE('MIDDLE');, 80 (**) 3:WRITE('RIGHT') and a new 85 END. Does anything change in what it prints?10.1 Type line 60 without its (**), LIST the program, and explain what you see.
10.2 Write a recursive function that adds up the numbers from 1 to N, and print it for N = 100.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
| A line has a strange number like 601 | Its Pascal started with a digit. Put (**) in front. |
*ERROR* a line or two after a CASE | It has both ELSE and END. The ELSE ends it. |
Out of RAM at PC=... | A routine called itself too deeply - usually one that never stops. |
CASE ends with END or with ELSE and a statement - not both. In XBAS, a line whose Pascal starts with a number must have (**) or something else in front. GOTO and FORWARD are there. Recursion needs no option and works thousands of calls deep.
S11, Types, Sets, Arrays And Records - the same building blocks, with stricter rules about which arrays go into which.