Loops, and the scripting language is a language
while and for. Both only mean anything in a script, because a loop goes back to the line that opened it and a prompt has no line to go back to - and both say so rather than doing something surprising. THE SCRIPT READER KEEPS THE POSITION OF EVERY LINE before reading it, which is what makes any of this possible: by the time a line has been read the reader is past it, and a line is not a fixed size to subtract. Three words per line, and the block is read again on the way back so the pointer into it means what it meant - the same thing nesting one script inside another already did, for a different reason. THE TWO LOOPS END DIFFERENTLY, and that is the design rather than an accident. A while is taken away at its end and its own line asks the question again, so nothing has to be remembered. A for is not: how many words it has used is kept in the block, and its line reads itself again and counts one more off the front. That is a byte in a block instead of a copy of the word list in every one of them. Blocks grew from a byte to a record of sixteen - state, kind, words used, and where the line that opened it was - and sixteen because A and B are a shift register, so four rotations turn a block number into its offset. The history and the variables are addressed the same way for the same reason. Nested loops, an if inside a loop, a loop inside a branch nobody takes, and a for with no words: the last two run no times rather than once, which is the case worth having a test for. Three things found by running it: textSame asks whether two WHOLE strings are the same, so "in red green blue" is not "in". The word has to be split off before it is compared. A for typed at a prompt complained about while, because both arrive at the same place. One message that names neither is better than one that names the wrong one. And docs.sh caught a naming convention nobody had written down: it recognises a packed name by its label ending in "Name", so ForName2 was silently not counted. It failed the right way round - saying the run was shorter than the count claims rather than passing - but the convention now lives where the names are and not only in the checker. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
16f8232a35
commit
2abc8281df
@@ -138,6 +138,32 @@ The shell already had the other half. `LineFailed` exists because a script stops
|
||||
line that did not work, so every command in the system was already saying whether it had
|
||||
worked, for a different reason.
|
||||
|
||||
**And two loops, which only mean anything in a script**, because a loop goes back to the line
|
||||
that opened it and a prompt has no line to go back to.
|
||||
|
||||
```text
|
||||
#! script
|
||||
for colour in red green blue
|
||||
echo it is $colour
|
||||
end
|
||||
|
||||
set n go
|
||||
while same $n go
|
||||
echo round once
|
||||
set n stop
|
||||
end
|
||||
```
|
||||
|
||||
The script reader keeps the position of **every** line before reading it, which is what makes
|
||||
that possible: by the time a line has been read the reader is past it, and a line is not a
|
||||
fixed size to subtract.
|
||||
|
||||
A `while` is taken away at its `end` and its line asks the question again. A `for` is not:
|
||||
how many words it has used is kept in the block, and its line reads itself again and counts
|
||||
one more off the front - a byte in a block rather than a copy of the list in every one of
|
||||
them. A `for` with no words runs no times, and a loop inside a branch nobody is taking runs
|
||||
no times either.
|
||||
|
||||
Blocks nest eight deep. A branch that is not being taken is **not even looked at**: the
|
||||
skipping happens before names are filled in, so `$whatever` inside a branch nobody is running
|
||||
is not a mistake, and a line nobody is running cannot fail.
|
||||
@@ -305,6 +331,8 @@ CosmOS currently provides these built-in commands:
|
||||
| `if <command>` | Run the lines after it only if that command worked. See Lines Run Sometimes. |
|
||||
| `else` | Run them only if it did not. |
|
||||
| `end` | Close the block. |
|
||||
| `while <command>` | Run the lines after it for as long as that command keeps working. |
|
||||
| `for <name> in <words>` | Run them once for each word, with the name set to it. |
|
||||
| `same <a> <b>` | Fails when the two are different, which is how `if` asks about a value. |
|
||||
| `monitor` | Enter monitor mode, in which the prompt becomes `*` and the commands below are also available. |
|
||||
| `help` | Show the built-in command summary. |
|
||||
|
||||
Reference in New Issue
Block a user