
In S8, STARS was STAR STAR STAR STAR STAR. That does not scale. Five is bearable; forty is not; and "as many as the number on the stack" is impossible.
A loop does something a counted number of times, and it keeps the count where you can use it.
: STARS 0 DO 42 EMIT LOOP ;
DO takes two numbers from the stack: the limit, and then the start. Everything between DO and LOOP is repeated, with a counter that begins at the start and goes up by one each time round. When the counter reaches the limit, the loop stops - without doing a pass for the limit itself.
So 5 0 DO counts 0, 1, 2, 3, 4: five passes. The easy way to remember it: with a start of 0, the limit is how many times it runs.
In STARS the 0 is written into the word and the limit is left for you to supply, which is why 7 STARS prints seven.
Loops only work inside a definition. Type DO at the keyboard and you get DO? Compilation only, Use in Definition.
Inside a loop, I puts the current value of the counter on the stack.
: TABLE 11 1 DO DUP I * .
LOOP DROP ;
7 TABLE prints the seven times table. The 7 sits on the stack throughout; each time round it is copied, multiplied by I and printed; and the DROP at the end clears away the original. Notice the limit is 11, to get up to 10.
: STARS 0 DO 42 EMIT LOOP ;
7 STARS
: TABLE 11 1 DO DUP I * .
LOOP DROP ;
7 TABLE
Starting from
A fresh boot, with SuperForth just started.
What you should see
7 STARS
*******ok
7 TABLE
7 14 21 28 35 42 49 56 63 70 ok

+LOOP is LOOP with a step you choose. It takes the step from the stack each time round:
: EVENS 21 0 DO I . 2 +LOOP ;
prints 0 2 4 ... 20. The step can be negative, and then the loop counts down, stopping before it gets to the limit just as it does going up:
: LIFTOFF 0 10 DO I . -1 +LOOP ;
prints 10 9 8 ... 1.
LEAVE tells the loop that this pass is the last. It does not jump out on the spot - the rest of the current pass still runs - but when LOOP is reached, the loop ends. It is only useful with a test in front of it, and tests are the business of S13 and S14.
This one will catch you. 0 STARS does not print nothing. It prints one star.
DO does not check whether there is anything to do before the first pass. If the start already equals the limit, you still get one. When a count might be zero, you have to test for that yourself before the loop - which is another job for S14.
A loop can contain another. Each has its own counter, and I always means the innermost one you are in. SuperForth has no word for reaching the outer loop's counter from inside the inner one; if you need it, put it on the stack before the inner loop starts.
TABLE to 13. How far does the table go now?0 STARS. How many stars? Why?EVENS, change the step to 5 and the limit to 51. Predict the last number printed.LIFTOFF's 0 10, keeping the -1, so that it starts at 0 and heads away from a limit of 10. Predict what it prints. Then explain it using what you know about when a loop tests.12.1 Define LAUNCH to print 10 down to 1, and then the text LIFTOFF!
12.2 Using STARS, define TRIANGLE to print a triangle five rows deep: one star, then two, up to five. Compare it with your answer to 8.1.
12.3 Define SUM100 to add up every number from 1 to 100 and print the total.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
DO? Compilation only, Use in Definition | You typed a loop at the keyboard. Put it in a word. |
| One pass too few | The limit is not included. To reach 10, the limit is 11. |
| One pass when you wanted none | A loop always runs at least once. |
| The loop runs once and stops | Limit and start are the wrong way round for the direction you are stepping. It is limit first, then start. |
limit start DO ... LOOP repeats with a counter from start up to, but not including, limit. I gives the counter. +LOOP steps by any amount, either way. LEAVE makes this pass the last. A loop always runs at least once, and loops live only inside definitions.
S13, True And False - how SuperForth compares two numbers, and what it leaves behind when it has.