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:
Anachronaut
2026-09-01 20:50:05 -04:00
co-authored by Claude Opus 5
parent 16f8232a35
commit 2abc8281df
16 changed files with 522 additions and 54 deletions
+2 -1
View File
@@ -25,6 +25,7 @@ Mode.sbx 48
Crash.sbx 632
vars.script 50
blocks.script 343
loops.script 272
tune.sbx 306
notes.txt 21
Apps <dir>
@@ -37,7 +38,7 @@ outer.script 376
inner.script 44
loop.script 35
crossed.txt 560
24 files, 1 directory
25 files, 1 directory
> exit
halted
Execution halted.
+2 -1
View File
@@ -15,6 +15,7 @@ Mode.sbx 48
Crash.sbx 632
vars.script 50
blocks.script 343
loops.script 272
tune.sbx 306
notes.txt 21
Apps <dir>
@@ -26,7 +27,7 @@ nonl.script 38
outer.script 376
inner.script 44
loop.script 35
23 files, 1 directory
24 files, 1 directory
> drive 1
> dir
other.txt 28
+2 -1
View File
@@ -32,6 +32,7 @@ Mode.sbx 48
Crash.sbx 632
vars.script 50
blocks.script 343
loops.script 272
tune.sbx 306
notes.txt 21
Apps <dir>
@@ -43,7 +44,7 @@ nonl.script 38
outer.script 376
inner.script 44
loop.script 35
23 files, 1 directory
24 files, 1 directory
> exit
halted
Execution halted.
+2 -1
View File
@@ -22,6 +22,7 @@ Mode.sbx 48
Crash.sbx 632
vars.script 50
blocks.script 343
loops.script 272
tune.sbx 306
notes.txt 21
Apps <dir>
@@ -33,7 +34,7 @@ nonl.script 38
outer.script 376
inner.script 44
loop.script 35
23 files, 1 directory
24 files, 1 directory
> exit
halted
Execution halted.
+77
View File
@@ -0,0 +1,77 @@
CosmOS
> do loops.script
> for a in 1 2
> for b in x y
> echo $a$b
1x
> end
> for b in x y
> echo $a$b
1y
> end
> for b in x y
> echo $a$b
> end
> end
> for a in 1 2
> for b in x y
> echo $a$b
2x
> end
> for b in x y
> echo $a$b
2y
> end
> for b in x y
> echo $a$b
> end
> end
> for a in 1 2
> for b in x y
> echo $a$b
> end
> end
> set n go
> while same $n go
> echo round
round
> set n stop
> end
> while same $n go
> echo round
> set n stop
> end
> for c in p q
> if same $c p
> echo only p
only p
> end
> end
> for c in p q
> if same $c p
> echo only p
> end
> end
> for c in p q
> if same $c p
> echo only p
> end
> end
> if same 1 2
> for d in never
> echo not this
> end
> end
> for e in
> echo no words
> end
> echo finished
finished
> while same a a
a loop wants a script to go back through
> for x in a b
a loop wants a script to go back through
> exit
halted
Execution halted.
[exit 0]
+2 -1
View File
@@ -108,6 +108,7 @@ Mode.sbx 48
Crash.sbx 632
vars.script 50
blocks.script 343
loops.script 272
tune.sbx 306
notes.txt 21
Apps <dir>
@@ -119,7 +120,7 @@ nonl.script 38
outer.script 376
inner.script 44
loop.script 35
23 files, 1 directory
24 files, 1 directory
> exit
halted
Execution halted.
+2 -1
View File
@@ -27,6 +27,7 @@ Mode.sbx 48
Crash.sbx 632
vars.script 50
blocks.script 343
loops.script 272
tune.sbx 306
notes.txt 21
Apps <dir>
@@ -38,7 +39,7 @@ nonl.script 38
outer.script 376
inner.script 44
loop.script 35
23 files, 1 directory
24 files, 1 directory
> exit
halted
Execution halted.
+2 -1
View File
@@ -15,6 +15,7 @@ Mode.sbx 48
Crash.sbx 632
vars.script 50
blocks.script 343
loops.script 272
tune.sbx 306
notes.txt 21
Apps <dir>
@@ -26,7 +27,7 @@ nonl.script 38
outer.script 376
inner.script 44
loop.script 35
23 files, 1 directory
24 files, 1 directory
> load
load what?
> load nosuch.sbx
+2 -1
View File
@@ -13,6 +13,7 @@ Mode.sbx 48
Crash.sbx 632
vars.script 50
blocks.script 343
loops.script 272
tune.sbx 306
notes.txt 21
Apps <dir>
@@ -24,7 +25,7 @@ nonl.script 38
outer.script 376
inner.script 44
loop.script 35
23 files, 1 directory
24 files, 1 directory
> load Say.sbx
loaded, starting at 5000
> run the disk took its time
+4
View File
@@ -0,0 +1,4 @@
do loops.script
while same a a
for x in a b
exit
+5
View File
@@ -138,6 +138,11 @@ printf '#! script\necho before\necho $nosuchname\necho after\n' > vars.script
printf '#! script\nset colour red\nif same $colour red\n echo it is red\n if same $colour blue\n echo and blue\n else\n echo but not blue\n end\nelse\n echo $neverSetAnywhere\nend\nif same $colour blue\n echo wrong\nelse\n echo right\nend\nif same $colour blue\n if same $colour red\n echo deep wrong\n else\n echo deep also wrong\n end\nend\necho done\n' > blocks.script
"$TOOL" put "$DISKS/cosmos.img" vars.script >/dev/null
"$TOOL" put "$DISKS/cosmos.img" blocks.script >/dev/null
# Loops, which are what a block is for once there is more than one way out of it. Nested, and
# with an if inside one and a loop inside a branch nobody takes - which must run no times at
# all rather than once.
printf '#! script\nfor a in 1 2\n for b in x y\n echo $a$b\n end\nend\nset n go\nwhile same $n go\n echo round\n set n stop\nend\nfor c in p q\n if same $c p\n echo only p\n end\nend\nif same 1 2\n for d in never\n echo not this\n end\nend\nfor e in\n echo no words\nend\necho finished\n' > loops.script
"$TOOL" put "$DISKS/cosmos.img" loops.script >/dev/null
# tune.sbx, which used to be a boot image and is now a program like any other. It brings a
# vector of its own - the screen's, so that it has a beat to play to - which makes it the
# second thing here that the version two format exists for.
+12
View File
@@ -438,6 +438,18 @@ cosmosStack | CosmOS/Source/cosmos.asm | run | cosmosSta
# set, inside the branch that is not taken, and that must not be an error - so the skipping
# happens before the names are filled in, and a line nobody is running cannot fail.
cosmosBlocks | CosmOS/Source/cosmos.asm | run | cosmosBlocks.in | - | disks/cosmos.img
# And the two loops. Both go back to the line that opened them, which is why the script
# reader keeps the position of every line before reading it: 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: what it
# has used is in the block, and the line reads itself again and counts one more word off the
# front - which is a byte in a block rather than a copy of the list in each one.
#
# Nested loops, an if inside a loop, a loop inside a branch nobody takes, and a for with no
# words at all, which runs no times rather than once. Neither loop makes sense typed at a
# prompt, and both say so.
cosmosLoops | CosmOS/Source/cosmos.asm | run | cosmosLoops.in | - | disks/cosmos.img
# The same editing offered to a PROGRAM, through osReadLine. Edit reads its lines that way,
# so a word typed with two letters the wrong way round is put right without starting the line
# again - which is the whole of what A4 buys.