A script is given words, and keeps them
"do build.sh cosmos.asm" looked for a file called "build.sh cosmos.asm", because scriptOpen copied the whole rest of the line into the name. So a script could be told nothing, and a launcher - a script whose entire job is to hand on what it was told - could not exist. Now the name is cut off the front and what follows is kept whole. $1 to $9 are the words of it, walked out on demand, and $args is all of them. Nothing is stored per parameter, so there is no limit on how many a script may be handed and no second number to keep in step. Both ways of starting a script pass them on: "do" and typing the name. A word that was not given is an error that stops the script, like every other name this shell does not know. Expanding it to nothing would let a command run with an argument missing and then report success, which is what stop-on-failure exists to prevent. $args is always set inside a script, empty if it was given nothing, so "if same $args" can be asked. ---- And the count that describes the block was already wrong ---- Found while adding a field to it. The state one script keeps for another is saved by a single copy of a fixed number of bytes, and that number was 71 against a block of 77: six bytes of line position had been added in the middle of it years after the count was written. So the tail of every saved script was never saved, and #quiet in a helper stayed behind in the script that called it - the opposite of what this file's own comment promises and the README documents. The unsaved line position turned out not to matter, because a loop keeps its own copy in the block record. Nothing said so. Three numbers describe this block and all three now say so in a comment, and cosmosScriptNest ends on a helper that goes quiet and a caller that must not stay that way. 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
06af7e7fbb
commit
d9ebc76cf5
@@ -46,3 +46,4 @@ Source/Emulator/rom.c
|
|||||||
# The personal disk 'make run-voyager' puts in drive 1. Made on demand, never rebuilt, and
|
# The personal disk 'make run-voyager' puts in drive 1. Made on demand, never rebuilt, and
|
||||||
# not cleaned - it is the one place in here where something made ON the machine can live.
|
# not cleaned - it is the one place in here where something made ON the machine can live.
|
||||||
/Disks/
|
/Disks/
|
||||||
|
*.sym
|
||||||
|
|||||||
@@ -216,6 +216,52 @@ line comes from - the shell splits it, matches it and runs it without knowing th
|
|||||||
a file is reached by its whole name, the way `load` is for a program. See Starting An
|
a file is reached by its whole name, the way `load` is for a program. See Starting An
|
||||||
Application By Name.
|
Application By Name.
|
||||||
|
|
||||||
|
### What A Script Is Given:
|
||||||
|
|
||||||
|
Whatever followed the name reaches the script, whichever way it was started - `do build.sh
|
||||||
|
cosmos.asm` and `build.sh cosmos.asm` hand it the same thing.
|
||||||
|
|
||||||
|
| Name | What it stands for |
|
||||||
|
| -- | -- |
|
||||||
|
| `$1` to `$9` | The words it was given, counted from one. |
|
||||||
|
| `$args` | All of them, exactly as they were typed. |
|
||||||
|
|
||||||
|
```
|
||||||
|
#! script
|
||||||
|
; build.sh <source>
|
||||||
|
echo building $1
|
||||||
|
cd /Source
|
||||||
|
Asm $1
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nothing is stored per parameter.** The line is kept whole and the word wanted is walked out
|
||||||
|
of it, so there is no limit on how many words a script may be handed and nothing to keep in
|
||||||
|
step. `$args` is that line; `$1` is a word copied out of it.
|
||||||
|
|
||||||
|
**A word that was not given is an error**, exactly like any other name the shell does not
|
||||||
|
know: `$2` in a script given one word says `nothing is set called 2` and stops the script.
|
||||||
|
Expanding it to nothing would let a command run with an argument missing and report success,
|
||||||
|
which is the failure the whole stop-on-error rule exists to prevent. A script that genuinely
|
||||||
|
wants to work with or without something can ask `if same $args` - and `$args` is always set
|
||||||
|
inside a script, empty if it was given nothing, so that question can always be asked.
|
||||||
|
|
||||||
|
**At the prompt they mean nothing**, and say so. There is no script there to have been given
|
||||||
|
anything, so `$1` is a name nobody set.
|
||||||
|
|
||||||
|
**A script's own words win over anything `set`.** They are looked at before the eight named
|
||||||
|
slots, so a parameter cannot be shadowed by something left lying about at the prompt.
|
||||||
|
|
||||||
|
**Each script has its own**, saved and restored with the rest of where it had got to. A script
|
||||||
|
that hands different words to a helper still has its own when the helper returns. That is also
|
||||||
|
what makes a **launcher** possible: a script whose whole body is one line handing on what it
|
||||||
|
was told, without knowing what any of it means.
|
||||||
|
|
||||||
|
```
|
||||||
|
#! script
|
||||||
|
; /Apps/Lander - the launcher
|
||||||
|
Packages/app.Lander/Lander $args
|
||||||
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
#! script
|
#! script
|
||||||
; Build the system and put it where the machine will find it.
|
; Build the system and put it where the machine will find it.
|
||||||
@@ -325,7 +371,7 @@ CosmOS currently provides these built-in commands:
|
|||||||
| `dir` | List the files on the mounted disk and their sizes. |
|
| `dir` | List the files on the mounted disk and their sizes. |
|
||||||
| `load <path>` | Read and validate an SBEX application, then place its code and data where its header requests. |
|
| `load <path>` | Read and validate an SBEX application, then place its code and data where its header requests. |
|
||||||
| `run [words]` | Start the loaded application and make the rest of the line available to it as an argument. |
|
| `run [words]` | Start the loaded application and make the rest of the line available to it as an argument. |
|
||||||
| `do <script>` | Run the lines in a file as though they had been typed. See Scripts. |
|
| `do <script> [words]` | Run the lines in a file as though they had been typed, and hand it those words. See Scripts. |
|
||||||
| `echo [words]` | Say the rest of the line, or a blank line with nothing after it. |
|
| `echo [words]` | Say the rest of the line, or a blank line with nothing after it. |
|
||||||
| `clear` | Empty the screen. |
|
| `clear` | Empty the screen. |
|
||||||
| `drive [n]` | Say which disk the shell is on, or go to another. See Several Disks. |
|
| `drive [n]` | Say which disk the shell is on, or go to another. See Several Disks. |
|
||||||
|
|||||||
@@ -133,6 +133,11 @@ bootNoDisk:
|
|||||||
; to ignore it. A file that is THERE and is not a script is the other case entirely: somebody
|
; to ignore it. A file that is THERE and is not a script is the other case entirely: somebody
|
||||||
; meant it to run.
|
; meant it to run.
|
||||||
bootStartup:
|
bootStartup:
|
||||||
|
; Nobody typed this one, so there is nothing to give it.
|
||||||
|
SETD.2 NoText
|
||||||
|
SETD.1 ScriptArgsFrom
|
||||||
|
STD.2.1
|
||||||
|
|
||||||
SETD.0 StartupName
|
SETD.0 StartupName
|
||||||
CALL scriptOpen
|
CALL scriptOpen
|
||||||
BRQ bootReady
|
BRQ bootReady
|
||||||
@@ -2647,10 +2652,18 @@ varExpandNamed:
|
|||||||
varExpandLookUp:
|
varExpandLookUp:
|
||||||
SETD.1 VarKeepLine
|
SETD.1 VarKeepLine
|
||||||
STD.0.1 ; Where the line has got to, across the search.
|
STD.0.1 ; Where the line has got to, across the search.
|
||||||
|
|
||||||
|
; A script's own names are asked about first, so that a parameter cannot be shadowed by
|
||||||
|
; something set at the prompt. Only inside a script: at the prompt "$1" is a name nobody
|
||||||
|
; set, and gets told so like any other.
|
||||||
|
CALL varScriptName
|
||||||
|
BRQ varExpandFound
|
||||||
|
|
||||||
SETD.0 VarName
|
SETD.0 VarName
|
||||||
CALL varFind
|
CALL varFind
|
||||||
BNQ varExpandNoSuch
|
BNQ varExpandNoSuch
|
||||||
CALL varValueOf
|
CALL varValueOf
|
||||||
|
varExpandFound:
|
||||||
SETD.1 VarKeepLine
|
SETD.1 VarKeepLine
|
||||||
LDD.0.1
|
LDD.0.1
|
||||||
|
|
||||||
@@ -2733,6 +2746,139 @@ varExpandLong:
|
|||||||
CALL newLine
|
CALL newLine
|
||||||
BRI commandFailed
|
BRI commandFailed
|
||||||
|
|
||||||
|
; ---- The names a script gets for nothing ----
|
||||||
|
;
|
||||||
|
; "$args" is everything it was given, and "$1" to "$9" are the words of that, counted from
|
||||||
|
; one. Nothing is stored per parameter: the line it was given is kept whole and the word
|
||||||
|
; wanted is walked out of it, so there is no limit on how many a script may be handed and
|
||||||
|
; nothing to keep in step.
|
||||||
|
;
|
||||||
|
; A NAME ONE OF THESE MISSES IS AN ERROR, like every other name this shell does not know.
|
||||||
|
; "$2" in a script given one word says so and stops it, rather than quietly becoming nothing
|
||||||
|
; and letting a command run with an argument missing - which is the rule set.asm's own comment
|
||||||
|
; argues for at length, applied to the names a script did not have to set.
|
||||||
|
;
|
||||||
|
; Q is zero if VarName is one of them, and DP3 is left on the value. DP3 because a RET puts
|
||||||
|
; the others back, which is the same reason varValueOf answers there.
|
||||||
|
varScriptName:
|
||||||
|
SETD.1 ScriptDepth
|
||||||
|
LDA.1
|
||||||
|
BRA varScriptNo ; Not in a script, so these names mean nothing here.
|
||||||
|
|
||||||
|
SETD.0 VarName
|
||||||
|
SETD.1 ArgsWord
|
||||||
|
CALL textSame
|
||||||
|
BRQ varScriptAll
|
||||||
|
|
||||||
|
; One character, and that character a digit from one to nine. Testing the length first is
|
||||||
|
; what keeps "1st" from being read as "1".
|
||||||
|
SETD.0 VarName
|
||||||
|
INCD.0
|
||||||
|
LDA.0
|
||||||
|
BNA varScriptNo
|
||||||
|
SETD.0 VarName
|
||||||
|
LDA.0
|
||||||
|
INIB 0x31
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRC varScriptNo ; Below '1'. There is no word nought.
|
||||||
|
LDA.0
|
||||||
|
INIB 0x3A
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BNC varScriptNo ; Above '9'.
|
||||||
|
|
||||||
|
LDA.0
|
||||||
|
INIB 0x30
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
MVQA ; Which word is wanted, one to nine.
|
||||||
|
CALL varScriptWord
|
||||||
|
RET
|
||||||
|
|
||||||
|
varScriptAll:
|
||||||
|
SETD.3 ScriptArgs
|
||||||
|
RSTA
|
||||||
|
RSTB
|
||||||
|
CCF
|
||||||
|
ADD ; Q is zero: it is one of them.
|
||||||
|
RET
|
||||||
|
|
||||||
|
varScriptNo:
|
||||||
|
INIA 0x01
|
||||||
|
RSTB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
|
; A is which word is wanted. Copies it out into VarWord and leaves DP3 on it, because the
|
||||||
|
; words are separated by spaces rather than ended by zeroes and everything downstream of here
|
||||||
|
; walks a string until it ends.
|
||||||
|
;
|
||||||
|
; Q is one if the script was not given that many, which reads as a name that is not set.
|
||||||
|
varScriptWord:
|
||||||
|
SETD.1 VarWordWanted
|
||||||
|
STA.1
|
||||||
|
SETD.0 ScriptArgs
|
||||||
|
|
||||||
|
varScriptSkip:
|
||||||
|
LDA.0
|
||||||
|
BRA varScriptShort ; The end, and the word wanted is past it.
|
||||||
|
INIB 0x20
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BNQ varScriptWordAt ; Not a space, so a word begins here.
|
||||||
|
INCD.0
|
||||||
|
BRI varScriptSkip
|
||||||
|
|
||||||
|
varScriptWordAt:
|
||||||
|
SETD.1 VarWordWanted
|
||||||
|
LDA.1
|
||||||
|
DECA
|
||||||
|
STA.1
|
||||||
|
BRA varScriptTake ; Counted down to nought, so this is the one.
|
||||||
|
|
||||||
|
varScriptPast:
|
||||||
|
LDA.0
|
||||||
|
BRA varScriptShort
|
||||||
|
INIB 0x20
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRQ varScriptSkip ; The end of this word, so the next one is looked for.
|
||||||
|
INCD.0
|
||||||
|
BRI varScriptPast
|
||||||
|
|
||||||
|
varScriptTake:
|
||||||
|
SETD.1 VarWord
|
||||||
|
varScriptTakeChar:
|
||||||
|
LDA.0
|
||||||
|
BRA varScriptTaken
|
||||||
|
INIB 0x20
|
||||||
|
CCF
|
||||||
|
SUB
|
||||||
|
BRQ varScriptTaken
|
||||||
|
LDA.0
|
||||||
|
STA.1
|
||||||
|
INCD.0
|
||||||
|
INCD.1
|
||||||
|
BRI varScriptTakeChar
|
||||||
|
|
||||||
|
varScriptTaken:
|
||||||
|
RSTA
|
||||||
|
STA.1 ; The zero that makes it a string.
|
||||||
|
SETD.3 VarWord
|
||||||
|
RSTB
|
||||||
|
CCF
|
||||||
|
ADD ; Q is zero, A having been reset above.
|
||||||
|
RET
|
||||||
|
|
||||||
|
varScriptShort:
|
||||||
|
INIA 0x01
|
||||||
|
RSTB
|
||||||
|
CCF
|
||||||
|
ADD
|
||||||
|
RET
|
||||||
|
|
||||||
varExpandNoSuch:
|
varExpandNoSuch:
|
||||||
SETD.0 VarNoSuch
|
SETD.0 VarNoSuch
|
||||||
CALL printString
|
CALL printString
|
||||||
@@ -3521,6 +3667,13 @@ promptAsScript:
|
|||||||
LDA.0
|
LDA.0
|
||||||
CALL sbfsUse
|
CALL sbfsUse
|
||||||
|
|
||||||
|
; Whatever followed the word, which reaches a script the same way it reaches a program.
|
||||||
|
; The line was split before the dispatch chain ran, so this is already the rest of it.
|
||||||
|
SETD.1 TextRest
|
||||||
|
LDD.2.1
|
||||||
|
SETD.1 ScriptArgsFrom
|
||||||
|
STD.2.1
|
||||||
|
|
||||||
SETD.0 ProgramName
|
SETD.0 ProgramName
|
||||||
CALL scriptOpen
|
CALL scriptOpen
|
||||||
BRQ prompt ; It is open, and the next line read will come from it.
|
BRQ prompt ; It is open, and the next line read will come from it.
|
||||||
@@ -4898,6 +5051,17 @@ doScript:
|
|||||||
LDA.0
|
LDA.0
|
||||||
BRA scriptNoName
|
BRA scriptNoName
|
||||||
|
|
||||||
|
; The file, and then whatever else was on the line. textSplit cuts the first word off in
|
||||||
|
; place and leaves TextRest on what follows, and a RET puts DP0 back - so afterwards DP0
|
||||||
|
; names just the file and TextRest names what the script is being given.
|
||||||
|
;
|
||||||
|
; Through DP2, because DP0 is the file and must still be it when scriptOpen is called.
|
||||||
|
CALL textSplit
|
||||||
|
SETD.1 TextRest
|
||||||
|
LDD.2.1
|
||||||
|
SETD.1 ScriptArgsFrom
|
||||||
|
STD.2.1
|
||||||
|
|
||||||
CALL scriptOpen
|
CALL scriptOpen
|
||||||
BRQ prompt ; It is open, and the next line read will come from it.
|
BRQ prompt ; It is open, and the next line read will come from it.
|
||||||
|
|
||||||
@@ -7598,7 +7762,7 @@ HelpCdText:
|
|||||||
mkdir <path> make a directory
|
mkdir <path> make a directory
|
||||||
rmdir <path> remove an empty one"
|
rmdir <path> remove an empty one"
|
||||||
HelpScriptText:
|
HelpScriptText:
|
||||||
"do <file> run the lines in a file, which must start with #!
|
"do <file> [words] run the lines in a file, which must start with #!
|
||||||
echo [words] say them
|
echo [words] say them
|
||||||
clear empty the screen"
|
clear empty the screen"
|
||||||
HelpMoreText:
|
HelpMoreText:
|
||||||
@@ -7809,6 +7973,12 @@ ShellNameCount:
|
|||||||
|
|
||||||
AppsPath:
|
AppsPath:
|
||||||
"/Apps"
|
"/Apps"
|
||||||
|
ArgsWord:
|
||||||
|
"args"
|
||||||
|
; An empty string, for a script the machine started rather than somebody typing, which was
|
||||||
|
; therefore given nothing.
|
||||||
|
NoText:
|
||||||
|
0x00
|
||||||
VarNoSuch:
|
VarNoSuch:
|
||||||
"nothing is set called "
|
"nothing is set called "
|
||||||
VarTooLong:
|
VarTooLong:
|
||||||
@@ -8249,6 +8419,12 @@ VarSlots:
|
|||||||
#Reserve 0d512
|
#Reserve 0d512
|
||||||
VarSlot:
|
VarSlot:
|
||||||
0x00
|
0x00
|
||||||
|
; One word of what a script was given, copied out so that it ends in a zero like every other
|
||||||
|
; value. A whole line of room, because one word can be the whole line.
|
||||||
|
VarWord:
|
||||||
|
#Reserve 0d128
|
||||||
|
VarWordWanted:
|
||||||
|
0x00
|
||||||
VarWanted:
|
VarWanted:
|
||||||
0x00 0x00
|
0x00 0x00
|
||||||
VarKeepValue:
|
VarKeepValue:
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ scriptSlotAt:
|
|||||||
DECA
|
DECA
|
||||||
BRA scriptSlotDone
|
BRA scriptSlotDone
|
||||||
scriptSlotStep:
|
scriptSlotStep:
|
||||||
DPUP.3 0d71
|
DPUP.3 0d205
|
||||||
DECA
|
DECA
|
||||||
BNA scriptSlotStep
|
BNA scriptSlotStep
|
||||||
scriptSlotDone:
|
scriptSlotDone:
|
||||||
@@ -80,7 +80,7 @@ scriptSlotDone:
|
|||||||
|
|
||||||
; Seventy bytes, DP0 to DP1.
|
; Seventy bytes, DP0 to DP1.
|
||||||
scriptCopyState:
|
scriptCopyState:
|
||||||
INIB 0d71
|
INIB 0d205
|
||||||
scriptCopyByte:
|
scriptCopyByte:
|
||||||
LDA.0
|
LDA.0
|
||||||
STA.1
|
STA.1
|
||||||
@@ -154,6 +154,17 @@ scriptOpenFirst:
|
|||||||
INIB 0d63
|
INIB 0d63
|
||||||
CALL copyText
|
CALL copyText
|
||||||
|
|
||||||
|
; ---- And what it was given ----
|
||||||
|
;
|
||||||
|
; After the push, so that what the script one level up was given is already somewhere safe.
|
||||||
|
; A script started with nothing gets an EMPTY one rather than none at all, which is what
|
||||||
|
; makes "$args" always mean something inside a script while "$1" can be missing.
|
||||||
|
SETD.1 ScriptArgsFrom
|
||||||
|
LDD.0.1
|
||||||
|
SETD.1 ScriptArgs
|
||||||
|
INIB 0d128
|
||||||
|
CALL copyText
|
||||||
|
|
||||||
CALL scriptKeepDrive
|
CALL scriptKeepDrive
|
||||||
SETD.0 ScriptName
|
SETD.0 ScriptName
|
||||||
SWI osFileInfo
|
SWI osFileInfo
|
||||||
@@ -584,11 +595,30 @@ ScriptDepth:
|
|||||||
ScriptDrive:
|
ScriptDrive:
|
||||||
0x00
|
0x00
|
||||||
|
|
||||||
; ---- Seventy bytes, and they are next to each other on purpose ----
|
; Where the arguments are, for the length of one call to scriptOpen. A pointer rather than the
|
||||||
|
; text, because the text is still sitting in the line that named the script and copying it
|
||||||
|
; twice would buy nothing.
|
||||||
|
ScriptArgsFrom:
|
||||||
|
0x00 0x00
|
||||||
|
|
||||||
|
; ---- Two hundred and five bytes, and they are next to each other on purpose ----
|
||||||
;
|
;
|
||||||
; Name, blocks left, next block, where in the block, and whether it is echoing: the whole of
|
; Name, blocks left, next block, where in the block, what it was given, and whether it is
|
||||||
; where a script has got to. Saving it is one copy because of this order, and nothing else
|
; echoing: the whole of a running script. Saving it is one copy because of this order, and
|
||||||
; may be put between them.
|
; nothing else may be put between them.
|
||||||
|
;
|
||||||
|
; ---- THREE NUMBERS DESCRIBE THIS BLOCK AND ALL THREE MUST AGREE ----
|
||||||
|
;
|
||||||
|
; scriptCopyState how many bytes one of them is
|
||||||
|
; scriptSlotAt how far apart two saved ones are
|
||||||
|
; ScriptSaved four of them
|
||||||
|
;
|
||||||
|
; They did not agree, and that is what this warning is for. Six bytes of line position were
|
||||||
|
; added in the middle of the block and the count stayed at 71, so the last six bytes of every
|
||||||
|
; saved script were never saved: a nested script's #quiet leaked back out to the script that
|
||||||
|
; called it, which is the opposite of what this file's own comment promises. The line position
|
||||||
|
; that went unsaved with it turned out not to matter - a loop keeps its own copy in the block
|
||||||
|
; record - but nothing said so, and the next field added would have been chosen at random.
|
||||||
ScriptName:
|
ScriptName:
|
||||||
#Reserve 0d64
|
#Reserve 0d64
|
||||||
ScriptBlocks:
|
ScriptBlocks:
|
||||||
@@ -617,10 +647,22 @@ ScriptLineBlocks:
|
|||||||
ScriptQuiet:
|
ScriptQuiet:
|
||||||
0x00
|
0x00
|
||||||
|
|
||||||
|
; ---- What the script was given ----
|
||||||
|
;
|
||||||
|
; The rest of the line that started it, kept whole rather than picked apart, because picking
|
||||||
|
; it apart costs a place to put every piece and a limit on how many there may be. "$1" walks
|
||||||
|
; this and copies out the word it wants; "$args" is this.
|
||||||
|
;
|
||||||
|
; A WHOLE LINE OF ROOM, so that nothing a person can type can be cut short. The line is 127
|
||||||
|
; and the script's own name has already come off the front of it, so this can never be filled
|
||||||
|
; - which is worth 128 bytes a level to never have to explain.
|
||||||
|
ScriptArgs:
|
||||||
|
#Reserve 0d128
|
||||||
|
|
||||||
; Three would do - a save happens on the second script and not the first - but four costs
|
; Three would do - a save happens on the second script and not the first - but four costs
|
||||||
; seventy bytes and removes an off-by-one from the only place it could hide.
|
; one more and removes an off-by-one from the only place it could hide.
|
||||||
ScriptSaved:
|
ScriptSaved:
|
||||||
#Reserve 0d284
|
#Reserve 0d820
|
||||||
ScriptInto:
|
ScriptInto:
|
||||||
0x00 0x00
|
0x00 0x00
|
||||||
ScriptRoom:
|
ScriptRoom:
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ from `make`, not from here.
|
|||||||
### 1. Recorded output
|
### 1. Recorded output
|
||||||
|
|
||||||
`Tests/run.sh` assembles each program named in `Tests/manifest`, runs it, and compares
|
`Tests/run.sh` assembles each program named in `Tests/manifest`, runs it, and compares
|
||||||
everything it printed against a file in `Tests/expected`. 213 tests, of which 151 run, 35
|
everything it printed against a file in `Tests/expected`. 214 tests, of which 152 run, 35
|
||||||
only assemble, 16 are expected to fail to assemble, and 11 boot from ROM with no image
|
only assemble, 16 are expected to fail to assemble, and 11 boot from ROM with no image
|
||||||
given at all.
|
given at all.
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ run [words] start what was loaded, and tell it those words
|
|||||||
cd [path] go to a directory, or to the root with nothing after it
|
cd [path] go to a directory, or to the root with nothing after it
|
||||||
mkdir <path> make a directory
|
mkdir <path> make a directory
|
||||||
rmdir <path> remove an empty one
|
rmdir <path> remove an empty one
|
||||||
do <file> run the lines in a file, which must start with #!
|
do <file> [words] run the lines in a file, which must start with #!
|
||||||
echo [words] say them
|
echo [words] say them
|
||||||
clear empty the screen
|
clear empty the screen
|
||||||
delete <file> take it off the disk
|
delete <file> take it off the disk
|
||||||
|
|||||||
@@ -44,8 +44,13 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
crossed.txt 560
|
crossed.txt 560
|
||||||
32 files, 1 directory
|
37 files, 1 directory
|
||||||
> exit
|
> exit
|
||||||
halted
|
halted
|
||||||
Execution halted.
|
Execution halted.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ run [words] start what was loaded, and tell it those words
|
|||||||
cd [path] go to a directory, or to the root with nothing after it
|
cd [path] go to a directory, or to the root with nothing after it
|
||||||
mkdir <path> make a directory
|
mkdir <path> make a directory
|
||||||
rmdir <path> remove an empty one
|
rmdir <path> remove an empty one
|
||||||
do <file> run the lines in a file, which must start with #!
|
do <file> [words] run the lines in a file, which must start with #!
|
||||||
echo [words] say them
|
echo [words] say them
|
||||||
clear empty the screen
|
clear empty the screen
|
||||||
delete <file> take it off the disk
|
delete <file> take it off the disk
|
||||||
|
|||||||
@@ -34,7 +34,12 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
31 files, 1 directory
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
|
36 files, 1 directory
|
||||||
> drive 1
|
> drive 1
|
||||||
> dir
|
> dir
|
||||||
other.txt 28
|
other.txt 28
|
||||||
|
|||||||
@@ -51,7 +51,12 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
31 files, 1 directory
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
|
36 files, 1 directory
|
||||||
> exit
|
> exit
|
||||||
halted
|
halted
|
||||||
Execution halted.
|
Execution halted.
|
||||||
|
|||||||
@@ -41,7 +41,12 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
31 files, 1 directory
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
|
36 files, 1 directory
|
||||||
> exit
|
> exit
|
||||||
halted
|
halted
|
||||||
Execution halted.
|
Execution halted.
|
||||||
|
|||||||
@@ -41,7 +41,12 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
31 files, 1 directory
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
|
36 files, 1 directory
|
||||||
> exit
|
> exit
|
||||||
halted
|
halted
|
||||||
Execution halted.
|
Execution halted.
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ run [words] start what was loaded, and tell it those words
|
|||||||
cd [path] go to a directory, or to the root with nothing after it
|
cd [path] go to a directory, or to the root with nothing after it
|
||||||
mkdir <path> make a directory
|
mkdir <path> make a directory
|
||||||
rmdir <path> remove an empty one
|
rmdir <path> remove an empty one
|
||||||
do <file> run the lines in a file, which must start with #!
|
do <file> [words] run the lines in a file, which must start with #!
|
||||||
echo [words] say them
|
echo [words] say them
|
||||||
clear empty the screen
|
clear empty the screen
|
||||||
delete <file> take it off the disk
|
delete <file> take it off the disk
|
||||||
|
|||||||
@@ -127,7 +127,12 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
31 files, 1 directory
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
|
36 files, 1 directory
|
||||||
> exit
|
> exit
|
||||||
halted
|
halted
|
||||||
Execution halted.
|
Execution halted.
|
||||||
|
|||||||
@@ -46,7 +46,12 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
31 files, 1 directory
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
|
36 files, 1 directory
|
||||||
> exit
|
> exit
|
||||||
halted
|
halted
|
||||||
Execution halted.
|
Execution halted.
|
||||||
|
|||||||
@@ -34,7 +34,12 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
31 files, 1 directory
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
|
36 files, 1 directory
|
||||||
> load
|
> load
|
||||||
load what?
|
load what?
|
||||||
> load nosuch.sbx
|
> load nosuch.sbx
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
CosmOS
|
||||||
|
> do args.script red green
|
||||||
|
> echo one is $1
|
||||||
|
one is red
|
||||||
|
> echo two is $2
|
||||||
|
two is green
|
||||||
|
> echo all of it is $args
|
||||||
|
all of it is red green
|
||||||
|
> args.script blue yellow
|
||||||
|
> echo one is $1
|
||||||
|
one is blue
|
||||||
|
> echo two is $2
|
||||||
|
two is yellow
|
||||||
|
> echo all of it is $args
|
||||||
|
all of it is blue yellow
|
||||||
|
> pass.script hello there
|
||||||
|
> Say $args
|
||||||
|
it says: hello there
|
||||||
|
finished
|
||||||
|
> do holds.script top level
|
||||||
|
> echo outer has $1
|
||||||
|
outer has top
|
||||||
|
> do args.script deep down
|
||||||
|
> echo one is $1
|
||||||
|
one is deep
|
||||||
|
> echo two is $2
|
||||||
|
two is down
|
||||||
|
> echo all of it is $args
|
||||||
|
all of it is deep down
|
||||||
|
> echo outer still has $1 and $args
|
||||||
|
outer still has top and top level
|
||||||
|
> do args.script only
|
||||||
|
> echo one is $1
|
||||||
|
one is only
|
||||||
|
> echo two is $2
|
||||||
|
nothing is set called 2
|
||||||
|
stopped: that line did not work
|
||||||
|
> $1
|
||||||
|
nothing is set called 1
|
||||||
|
> exit
|
||||||
|
halted
|
||||||
|
Execution halted.
|
||||||
|
[exit 0]
|
||||||
@@ -24,6 +24,13 @@ self
|
|||||||
> do loop.script
|
> do loop.script
|
||||||
do: scripts are only four deep
|
do: scripts are only four deep
|
||||||
stopped: that line did not work
|
stopped: that line did not work
|
||||||
|
> do aloud.script
|
||||||
|
> echo aloud first
|
||||||
|
aloud first
|
||||||
|
> do hush.script
|
||||||
|
the helper is quiet
|
||||||
|
> echo aloud again
|
||||||
|
aloud again
|
||||||
> exit
|
> exit
|
||||||
halted
|
halted
|
||||||
Execution halted.
|
Execution halted.
|
||||||
|
|||||||
@@ -32,7 +32,12 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
31 files, 1 directory
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
|
36 files, 1 directory
|
||||||
> load Say.sbx
|
> load Say.sbx
|
||||||
loaded, starting at 5000
|
loaded, starting at 5000
|
||||||
> run the disk took its time
|
> run the disk took its time
|
||||||
|
|||||||
@@ -41,7 +41,12 @@ nonl.script 38
|
|||||||
outer.script 376
|
outer.script 376
|
||||||
inner.script 44
|
inner.script 44
|
||||||
loop.script 35
|
loop.script 35
|
||||||
31 files, 1 directory
|
hush.script 42
|
||||||
|
aloud.script 59
|
||||||
|
args.script 64
|
||||||
|
pass.script 20
|
||||||
|
holds.script 87
|
||||||
|
36 files, 1 directory
|
||||||
> exit
|
> exit
|
||||||
halted
|
halted
|
||||||
Execution halted.
|
Execution halted.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ run [words] start what was loaded, and tell it those words
|
|||||||
cd [path] go to a directory, or to the root with nothing after it
|
cd [path] go to a directory, or to the root with nothing after it
|
||||||
mkdir <path> make a directory
|
mkdir <path> make a directory
|
||||||
rmdir <path> remove an empty one
|
rmdir <path> remove an empty one
|
||||||
do <file> run the lines in a file, which must start with #!
|
do <file> [words] run the lines in a file, which must start with #!
|
||||||
echo [words] say them
|
echo [words] say them
|
||||||
clear empty the screen
|
clear empty the screen
|
||||||
delete <file> take it off the disk
|
delete <file> take it off the disk
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
do args.script red green
|
||||||
|
args.script blue yellow
|
||||||
|
pass.script hello there
|
||||||
|
do holds.script top level
|
||||||
|
do args.script only
|
||||||
|
$1
|
||||||
|
exit
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
do outer.script
|
do outer.script
|
||||||
do loop.script
|
do loop.script
|
||||||
|
do aloud.script
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -296,6 +296,33 @@ printf '#! script\necho inner one\necho inner two\n' > inner.script
|
|||||||
# A script that runs itself, which is what the depth limit is for.
|
# A script that runs itself, which is what the depth limit is for.
|
||||||
printf '#! script\necho self\ndo loop.script\n' > loop.script
|
printf '#! script\necho self\ndo loop.script\n' > loop.script
|
||||||
"$TOOL" put "$DISKS/cosmos.img" loop.script >/dev/null
|
"$TOOL" put "$DISKS/cosmos.img" loop.script >/dev/null
|
||||||
|
# ---- And what a nested script gives back ----
|
||||||
|
#
|
||||||
|
# hush.script goes quiet and heard.script must not stay that way. The state one script keeps
|
||||||
|
# for another is saved by a single copy of a fixed number of bytes, and that number was six
|
||||||
|
# short of the block it was copying - so the last fields of it, quiet among them, were never
|
||||||
|
# saved at all. Nothing said so: the echo simply stopped, in the caller, after the helper
|
||||||
|
# returned. The check is that "echo aloud again" is ECHOED and not merely obeyed.
|
||||||
|
#
|
||||||
|
# MIND WHAT A NEW NAME HERE BEGINS WITH. Tab is checked against this disk, and a second file
|
||||||
|
# sharing a prefix with one of the words those tests type turns a unique completion into a
|
||||||
|
# list. "heard.script" was the first draft and it shadowed hello.sbx.
|
||||||
|
printf '#! script\n#quiet\necho the helper is quiet\n' > hush.script
|
||||||
|
"$TOOL" put "$DISKS/cosmos.img" hush.script >/dev/null
|
||||||
|
printf '#! script\necho aloud first\ndo hush.script\necho aloud again\n' > aloud.script
|
||||||
|
"$TOOL" put "$DISKS/cosmos.img" aloud.script >/dev/null
|
||||||
|
|
||||||
|
# ---- What a script is given ----
|
||||||
|
#
|
||||||
|
# args.script says what reached it; pass.script is the shape a launcher has, handing on what
|
||||||
|
# it was told without knowing what any of it means; holds.script gives a helper different
|
||||||
|
# words and must still have its own afterwards.
|
||||||
|
printf '#! script\necho one is $1\necho two is $2\necho all of it is $args\n' > args.script
|
||||||
|
"$TOOL" put "$DISKS/cosmos.img" args.script >/dev/null
|
||||||
|
printf '#! script\nSay $args\n' > pass.script
|
||||||
|
"$TOOL" put "$DISKS/cosmos.img" pass.script >/dev/null
|
||||||
|
printf '#! script\necho outer has $1\ndo args.script deep down\necho outer still has $1 and $args\n' > holds.script
|
||||||
|
"$TOOL" put "$DISKS/cosmos.img" holds.script >/dev/null
|
||||||
|
|
||||||
# ---- A disk that starts itself ----
|
# ---- A disk that starts itself ----
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -983,7 +983,23 @@ cosmosScriptEdges | CosmOS/Source/cosmos.asm | run | cosmosScr
|
|||||||
# into the single buffer, so coming back means reading the outer one's again and landing on
|
# into the single buffer, so coming back means reading the outer one's again and landing on
|
||||||
# the byte it left. Then a script that runs itself, which stops at four deep and takes every
|
# the byte it left. Then a script that runs itself, which stops at four deep and takes every
|
||||||
# level with it, because a build whose helper failed should not carry on in its caller.
|
# level with it, because a build whose helper failed should not carry on in its caller.
|
||||||
|
# It also ends on the state a nested script gives back. The saved block is copied by a fixed
|
||||||
|
# count, that count was six bytes short of the block, and quiet was in the six - so a helper
|
||||||
|
# that went quiet left its caller quiet. "echo aloud again" being ECHOED is the check.
|
||||||
cosmosScriptNest | CosmOS/Source/cosmos.asm | run | cosmosScriptNest.in | 200000000 | disks/cosmos.img
|
cosmosScriptNest | CosmOS/Source/cosmos.asm | run | cosmosScriptNest.in | 200000000 | disks/cosmos.img
|
||||||
|
# ---- What a script is given ----
|
||||||
|
#
|
||||||
|
# $1 to $9 are the words it was handed and $args is all of them. Nothing is stored per
|
||||||
|
# parameter: the line is kept whole and the word wanted is walked out of it.
|
||||||
|
#
|
||||||
|
# Five claims in one session. Both ways of starting a script pass words on - "do" and typing
|
||||||
|
# the name. A LAUNCHER can hand on what it was told without knowing what any of it means,
|
||||||
|
# which is the reason this rung is on the ladder at all. A nested script gets its own words
|
||||||
|
# and the caller still has its own afterwards. And a word that was not given is an ERROR that
|
||||||
|
# stops the script, like every other name the shell does not know - not silently nothing,
|
||||||
|
# which would let a command run with an argument missing. At the prompt they are ordinary
|
||||||
|
# unset names, because there is no script to have been given anything.
|
||||||
|
cosmosScriptArgs | CosmOS/Source/cosmos.asm | run | cosmosScriptArgs.in | 200000000 | disks/cosmos.img
|
||||||
# ---- Starting itself ----
|
# ---- Starting itself ----
|
||||||
#
|
#
|
||||||
# /System/Boot/startup.sh runs before anybody can type. This one is also the check on #quiet
|
# /System/Boot/startup.sh runs before anybody can type. This one is also the check on #quiet
|
||||||
|
|||||||
Reference in New Issue
Block a user