Pipe

From Esolang
Jump to navigation Jump to search

Pipe is a language designed by Programming Puzzles and Code-Golf user RedwolfPrograms. Nonnegative integers can be stored either in a stack or in a value known as the pipe. Putting characters in parentheses makes a scope. Scopes contain their own local stack.

Valid Characters

There are 16 valid characters in Pipe, those being:

#^-+?!:~<>=;()[]

Brackets and parentheses must be balanced and nested properly. All other characters are ignored, and can be used as whitespace

Basics

A program in Pipe has a global stack, which can be accessed at any point in the program. The pipe can be thought of as an operations register. The pipe starts out as 0. The pipe can be incremented with +. It cannot be decremented, though it can be reset to 0 with -.

To push to the stack, use #, which does not change the pipe. To pop from the stack to the pipe, use ^. A simple program in Pipe to push numbers from 1 to 10 to the stack would be:

+#+#+#+#+#+#+#+#+#+#

To get one character of user input, use <. To output one character, use >. A simple program to input five characters, then output them, would be:

<><><><><>

Both of these example programs have been very repetitive. To create a loop in Pipe, use square brackets. An infinite loop would just be:

[]

The only way to stop a loop is to skip the end bracket, or end the program. To skip the next character, use !. A more useful method is to use ?, which will only skip the next character if the pipe is 0. A simple example of this would be a cat program:

[<>?]

This will take one character of input until none is left, in which case < sets the pipe to 0. If the pipe is 0, > does nothing. Because of this, the loop will stop once it outputs all of the given input and tries to output nothing.

Another use of this would be to output the contents of the stack. To get the stack length, use :. Using a stack, here is a simple, uncompressed "Hello, world!" program:

+++++++++++++++++++++++++++++++++#
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
-++++++++++++++++++++++++++++++++#
-++++++++++++++++++++++++++++++++++++++++++++#
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
[^>:?]

Note the final line. That loop will read through the stack, outputting each element.

Skipping the [ in a loop will skip over the entire loop.

Lastly, the = character will set the pipe to 0 if it doesn't equal the top element of the stack, and 1 if it does.

Scopes

If 0 or more characters are enclosed in parentheses, they form a child scope. Each scope has its own stack. To access the stack of the parent scope (or the global scope, if there is no parent scope), use ~ before a character. For example,

<#-((~~^>))

will input a character, store it to the global stack, and then a child-child scope will pop from its stack and output it. If the number of ~ was less than two, it would have attempted to pop from an empty stack (either its parent stack, or its local stack), returning 0. If there were more ~ characters, it would still pop from the global stack as it cannot get any more global.

As with loops, skipping a scope will skip everything in it. This could be used to create an if statement,

x?(y)

where x is a condition and y is some characters to run. Finally, if the ending parenthesis of a scope is skipped, the stack will be "cached", and the next scope within the same parent will start with that stack rather than an empty one:

((+#+#+#!)x(y))z

In the example above, the scope containing y would start with the previous stack [1, 2, 3] instead of an empty stack, but x and z would not be able to access that stack.

A program ends either when it runs out of characters, or when it finds ;.

Interpreter

Javascript: https://github.com/RedwolfPrograms/Pipe/tree/master