Lines that are only run sometimes
if, else, end, and same. IF TAKES A COMMAND, which is one rule rather than two and is why comparing values needs no syntax of its own: "same" is an ordinary command that fails when its two words differ, so "if same $a $b" falls out of the rule instead of being an exception to it. Anything else that can fail is a question too - "if load Snake.sbx" is a perfectly good one. The shell already had the other half. LineFailed exists because a script stops at the first line that did not work, so every command was already saying whether it had, for a different reason entirely. A BLOCK HAS TWO KINDS OF NOT-RUNNING. One where an else would turn it on, and one where it would not - which is what an if pushes when something above it is already being skipped. That is what makes nesting need no looking down the stack: the top of it says everything. A branch nobody is taking is not even looked at. The skipping happens BEFORE the names are filled in, so a variable mentioned in a branch that is not running is not an error - a line nobody runs must not be able to fail. AND LINES MAY BE INDENTED, which they could not be before there was anything to indent inside. Nobody writes an if inside an if without indenting what is in them, and a leading space used to make the first word empty and match nothing. Found by writing the test script the way anybody would write one. CALL commandFailed became BRI commandFailed in nine places. It never returns - it marks the line and branches to the prompt - so calling it was a lie that cost a Stack frame each time, and fourteen other sites already branched. THE LINT RULE FOUND THIS, three days after I wrote the rule and on my own code: two false positives that were really the linter being right about a CALL that is not one. It does not fix the leak on its own, since a failure inside any called routine still abandons that frame, but it removes the cause of the commonest case and makes the code true. The mechanical edit then left a BRI prompt stranded behind one of them, and the linter caught that too. 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
4b109f704c
commit
16f8232a35
@@ -116,6 +116,35 @@ an installed library and a copy of the source.
|
||||
The disk is rebuilt from scratch when its applications change, so its contents describe
|
||||
the current source tree rather than accumulating files left by older builds.
|
||||
|
||||
## Lines Run Sometimes:
|
||||
|
||||
```text
|
||||
#! script
|
||||
set colour red
|
||||
if same $colour red
|
||||
echo it is red
|
||||
else
|
||||
echo it is not
|
||||
end
|
||||
```
|
||||
|
||||
**`if` takes a command**, and what follows runs only if that command worked. That is one rule
|
||||
rather than two, and it is why comparing values needs no syntax of its own: `same` is an
|
||||
ordinary command that fails when its two words differ, so `if same $a $b` falls out of the
|
||||
rule instead of being an exception to it. Anything else that can fail can be asked about the
|
||||
same way - `if load Snake.sbx` is a perfectly good question.
|
||||
|
||||
The shell already had the other half. `LineFailed` exists because a script stops at the first
|
||||
line that did not work, so every command in the system was already saying whether it had
|
||||
worked, for a different reason.
|
||||
|
||||
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.
|
||||
|
||||
**Lines may be indented**, which they could not be before there was anything to indent
|
||||
inside. Leading spaces are taken off before anything looks at the line.
|
||||
|
||||
## Names For Things:
|
||||
|
||||
`set name value` writes one down, and `$name` anywhere on a later line stands for it.
|
||||
@@ -273,6 +302,10 @@ CosmOS currently provides these built-in commands:
|
||||
| `delete <file>` | Remove a file from the filesystem and release its blocks. |
|
||||
| `rename <file> <to>` | Give a file a different name without moving its contents. |
|
||||
| `set [name [value]]` | Give a name a value, or say what the names are. See Names For Things. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `exit` | Leave monitor mode if in it, and otherwise halt the machine. |
|
||||
|
||||
Reference in New Issue
Block a user