User:Deschutron/E-SNUSP

From Esolang
Jump to navigation Jump to search

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:

  1. (fork) a program forks
  2. (term) a program terminates
  3. (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)