User:Deschutron/E-SNUSP
E-SNUSP is a variant of SNUSP that I am developing. It has a few extra features. The extra features are based on simple enough ideas, but have turned out to have some rather fiddly behaviour.
E-SNUSP is a form of Forking Executive Redirectable Modular SNUSP.
More information about these adjectives can be found on Extensions to SNUSP.
The Forking and Executive features are not as simple as described at Extensions to SNUSP though. In implementing them I tweaked them in certain ways. In this document I try to clarify their behaviours.
Special behaviour of forking
Suppose there is an E-SNUSP process running by itself called root
.
The IO network of root is
stdin → root → stdout
If root executes the FORK instruction, the network becomes
stdin → root → rootCh → stdout
where rootCh
(root-child) is a clone of root
.
Special string markers:
(fork)
a program forks(term)
a program terminates(EOF)
an end-of-file-marker. The thing that is read as-1
when reading for a character.
If root
says "abc(fork)def"
, and rootCh
says "pqr"
, then stdout
receives "abcpqr"
.
root: "abc(fork)def" rootCh: "pqr" output: "abcpqr"
So far so simple.
Let's look at two cases: one where root terminates, and one where rootCh terminates, and see what happens.
When the parent terminates
When root
terminates, the IO network becomes
stdin → rootCh → stdout
Output:
root: "abc(term)" rootCh: "pqr(root.term)stu(term)" output: "pqrstu(EOF...)"
rootCh
intercepts all the output from root
, and rootCh
's output to stdout
is unaffected by root
's termination.
When the child terminates
When rootCh
terminates, the IO network becomes
stdin → root → stdout
The output is like:
root: "abc(rootCh.term)def(term)" rootCh: "pqr(term)" output: "pqr(EOF)def(EOF...)"
Here, the position of the rootCh.term
event in root
's output is determined not by the time when it occurred, but by the number of characters rootCh
reads before terminating. In this example, rootCh
reads three characters.
As you can see, there is a change-over from root
to rootCh
in who writes to stdout
. The change-over is signalled to the downstream process by an end-of-file marker. This is enough to tell a single-file reading program that the file it wants to read has ended.
Some implementations of the readline() function need two EOF markers to cause them to stop reading, if the final character of output to them is not a newline marker. Java's BufferedReader.readline()
is an example of this behaviour. This behaviour causes screw-ups when operating downstream of a chain of E-SNUSP processes, unless the tail E-SNUSP program always ends its output with a newline marker.
Differences to Unix pipe IO chains
In Unix, when a downstream process closes its output, no further output reaches its recipient. This changes the behaviour when the child terminates.
In the case of root
and rootCh, rootCh
terminating, the IO network becomes
stdin → root
stdout
is no longer in the network. stdout
will not receive anything now.
The output is like:
root: "abc(rootCh.term)def(term)" rootCh: "pqr(term)" output: "pqr(EOF...)"
This is something to remember if trying to use default OS pipe behaviour to emulate E-SNUSP pipe behaviour, and if trying to write a shell with piping in E-SNUSP.
Special behaviour in execking
First of all, E-SNUSP is first-level executive, with the Redirectable feature. So the meaning of the tilde and brace notation is
~{blah} SNUSP EXEC. Execute the E-SNUSP program "blah" ~~{blah} nothing ~~~{blah} nothing (if blah doesn't start with ',' or '.') ~~~{,blah} REDIRECT input to "blah" ~~~{.blah} REDIRECT output to "blah"
where blah
is a filename that doesn't contain '}'.
I don't want SHELL EXEC because it is too messy.
There is a special behaviour in E-SNUSP's version of SNUSP EXEC as well, described below.
Execking "-"
If the following sequence is encountered
~{-}
the E-SNUSP program will execute its input as if the input were a SNUSP program. The memory and call stack are cleared as usual and then the input is executed.
Special behaviour of redirection
The description of Redirectable SNUSP on the Extensions to SNUSP page is exactly as the Redirection feature works in E-SNUSP.
Random number feature
I often neglect to mention this characteristic of E-SNUSP, so I make special mention of it here. In the assortment of fetures I have chosen for E-SNUSP, I include the RAND ('%') instruction from Bloated SNUSP. I do not include any of the other Bloated SNUSP features listed on the SNUSP wiki page.
The full instruction set
< LEFT Move the memory pointer to the left > RIGHT Move the memory pointer to the right + INCR Increment current memory cell - DECR Decrement current memory cell , READ Read a byte into current memory cell . WRITE Write a byte from current memory cell \ LURD If going left, go up up, go left right, go down down, go right / RULD If going right, go up up, go right left, go down down, go left ! SKIP Move the instruction pointer forward one step ? SKIPZ If the current memory cell is zero, do a SKIP @ ENTER Push the current direction and IP location on the call-stack # LEAVE Pop direction and IP location off call-stack and advance IP one step % RAND Set the value of the current cell to a random number Y FORK Fork the process and connect the resultant processes by a pipe from parent to child ~{name} EXEC Execute the SNUSP program "name" (name may be "-" for stdin) ~~~{,name} REDIR_IN Redirect the input to the file "name" (name may be "-" for stdin) ~~~{.name} REDIR_OUT Redirect the output to the file "name" (name may be "-" for stdout)