Tonoco
Tonoco is an Esoteric programming language by user:David.werecat which forms a network of boxes and has only three instructions.
Introduction
Tonoco is a language based on the concept of networking single operation boxes to create structures facilitating complicated functions. In order to achieve this, it provides a series of boxes with defined operations and the framework to connect, disconnect and send data to these boxes.
Language Basics
Getting Started
The basic structure of Tonoco is a series of boxes labeled A to Z with one way connections between them. Each box can receive input and send output to/from the boxes directly connected to itself. All data sent over the network is/are 32 bit signed integers. Since the connections are one way, to bidirectionally connect two boxes two connections would need to be created. The language defines two instructions for the purpose of managing connections between boxes: one for connecting boxes and one for disconnecting boxes. Certain boxes can perform operations other than simple data processing, allowing constructs such as looping, conditional expressions, IO access, and memory access. The language executes by sending data to individual boxes and allowing any output generated from that input to pass through the network. Due to the structure of the language it could be possible to run this language using a network of computers, rather than using a virtual network like the reference interpreter.
Box Operation
Boxes operate on all 32 bit integer input they receive, potentially generating output. When a box receives input, it performs an operation. The operation is broken into two parts, the preprocessing phase and the processing phase. The preprocessing phase occurs even if execution is off or the current instruction is to be skipped. It will generally only adjust program flags, including adjusting the execution state. After the preprocessing phase, if execution is on and the current instruction is not to be skipped the box will run the processing phase. In the processing phase, the input data is used to perform an operation within the box, potentially producing output. If any output is produced, it is then propagated as is explained in the next section.
Network Propagation
Certain boxes produce output after receiving a certain amount of input. If a box generates output and it is connected for output to several other boxes, data propagates depth first in alphabetical order. To simpler terms, this means that a box will send its output to these connected boxes in alphabetical order, stopping and waiting for any output generated by each box to finish propagating through the network. A hypothetical example of this is as follows: a network is created where box 1 is connected for output to boxes 2, 3, and 4. Box 3 is further connected for output to boxes 5 and 6. Boxes 2-4 as well as boxes 5 and 6 are in alphabetical order. Any box that receives input will generate an output. If box 1 receives input, it will output to box 2. Box 2 will generate output, but no other box will receive it. Box 1 will then output to box 3. Box 3 will generate output, thus sending output to boxes 5 and 6 (in that order), neither of which will send their generated output to any other box. Finally, box 1 will send output to box 4, which will generate output but no box will receive it.
It should be noted that if a box receives input that would cause the next instruction to be skipped, all other boxes in the current propagation (even if further up the tree) will not process any received input. Similarly, if a box receives input that would cause execution to be turned off, all boxes further in that propagation (even if further up the tree) will act as such. Execution may be turned on again in the same propagation, and once again the boxes further in that propagation (even if further up the tree) will act as such.
Control Flow
There are three methods of control flow in Tonoco: conditional skipping of the next instruction, turning on/off execution with a depth counter, and defining/jumping to integer labels. Conditional skipping of the next instruction will conditionally (based on input) disable execution for the next instruction (the instruction is not actually skipped). If execution is already disabled, nothing happens. The description of how disabled execution is handled is included with the description of turning on/off execution below in this paragraph. Note that any boxes re-enabling execution in the skipped instruction will not affect the skip. The next method of control flow is turning on/off execution with depth awareness. Certain boxes can enable or disable control flow. Usually the boxes which disable control flow will increase the depth of execution and boxes which enable control flow will decrease the depth of execution, even if execution is disabled. Execution depth starts at zero. Execution may only be turned back on at the same depth as it was turned off. When execution is turned off, send instructions are still processed but connect and disconnect instructions are ignored. As stated above, boxes will only execute their preprocessing sections when execution is off. Therefore, most network operation is disabled when execution if off. The last kind of control flow is defining/jumping to labels. When a label is created, it saves the execution depth and the location of the current instruction and creates a label with an identifier. Labels cannot be jumped to until they are created. When attempting to create a label with an index that has already been created, the label creation is ignored. Jumping to a label will move to the instruction which caused the created the label and set the depth of execution to the stored value. Since labels respect depth of execution and can be created dynamically, labels can be utilized to created advanced control flow structures.
Since it is possible to conditionally cause input to boxes which enable or disable execution based on network propagation, depth imbalance can occur. Therefore, programmers must be careful when using conditional execution state modification based on network propagation. It is recommended to avoid this kind of misuse of control flow.
Memory Access
There are two kinds of accessible memory, a 16 bit memory array and a stack. Both can be accessed through certain boxes and store 32 bit signed integers. Since memory addresses are 32 bits long, addresses are cropped to 16 bits by the memory manager when accessing memory. The memory array is initialized to all zero and the stack is emptied at the start of program execution.
Notes About Connections
No error is generated when attempting to create a connection that already exists or attempting to disconnect a nonexisting connection, the instruction is simply ignored.
Instructions
Syntax
Each instruction is has three parts: one character for the instruction code and two parameters. The connect instruction connects box parameter 1 for output to box parameter 2. The instruction code for connect is C
. Each parameter for the connect instruction is one character long and is the box letter for the connection. The disconnect instruction disconnects a connection made by a previous connect instruction. The instruction code for disconnect is D
and the parameters are the same as the connect instruction. The last instruction is the send instruction. The send instruction sends input parameter 2 to the box parameter 1. The instruction code for send is S
. The first parameter for the send instruction is one character long and is the box letter to send input to. The second parameter for the send instruction is the integer to send to the specified box. The integer is detected by the immediate run of digits and negative signs. Comments start with '
and end with '
. A comment cannot be placed inside an instruction, doing so will result in an error. Whitespace is stripped on program load. All box letters and instruction codes are case insensitive. Any unknown instructions, missing parameters or invalid parameters will generate an error.
Box Reference
Tonoco defines the following boxes:
Box Letter | Operation Type | PreProcessing Description | Processing Description |
---|---|---|---|
A |
Arithmetic | n/a | For each two inputs, input 1 is added to input 2 and the result is output. |
B |
Arithmetic | n/a | For each two inputs, input 1 is bitwise ANDed with input 2 and the result is output. |
C |
Console IO | n/a | Reads a character from the console and outputs the character code. |
D |
Arithmetic | n/a | For each two inputs, input 1 is divided by input 2 and the result is output. |
E |
General | n/a | Delays input, outputting the previous input. The initial output is zero. |
F |
General | n/a | Ends the program. |
G |
Memory | n/a | Outputs the value in the memory array at the input location. |
H |
Console IO | n/a | Writes the input integer to the console. |
I |
Control Flow | n/a | If the input is zero, the next instruction is skipped. |
J |
Control Flow | n/a | Jumps to the label with in index specified by the input. If the label is not found, an error is generated. |
K |
Console IO | n/a | Reads a line from the console and attempts to output the integer value of that line. If the line is unable to be parsed as an integer, -1 is output. |
L |
Control Flow | Creates a label with an identifier of the input integer at the current instruction. | n/a |
M |
Arithmetic | n/a | For each two inputs, input 1 is multiplied by input 2 and the result is output. |
N |
Arithmetic | n/a | Outputs the bitwise inverse of the input. |
O |
Memory | n/a | Pops a value from the stack and outputs that value. If the stack is empty, an exception is generated. |
P |
Arithmetic | n/a | For each two inputs, input 1 modulus input 2 is output. |
Q |
Console IO | n/a | Writes the input character code to the console. |
R |
Arithmetic | n/a | For each two inputs, input 1 is bitwise ORed by input 2 and the result is output. |
S |
Arithmetic | n/a | For each two inputs, input 1 is subtracted by input 2 and the result is output. |
T |
Memory | n/a | For each two inputs, the value of input 2 is stored in the memory array at location specified by input 1. |
U |
Memory | n/a | Pushes the input onto the stack. |
V |
Comparison | n/a | For each two inputs: outputs -1 if input 1 is less than input 2, otherwise outputs 0. |
W |
Comparison | n/a | For each two inputs: outputs -1 if input 1 is greater than input 2, otherwise outputs 0. |
X |
Arithmetic | n/a | For each two inputs, input 1 is bitwise XORed by input 2 and the result is output. |
Y |
Control Flow | Increases the execution depth by 1. | Turns off execution and remembers that the depth that execution was turned off at was the same as before the increase in the preprocessing stage. |
Z |
Control Flow | Decreases the execution depth by 1 and turns on execution if the execution depth after the decrease is the same as when the execution was turned off. | n/a |
Possible Extensions
There are several ways in which it could be possible to extend Tonoco to a second version. Some possible ideas for Tonoco version 2 include:
- Program defined boxes
- Fast connection set definitions and switching
- Generator boxes (boxes which can generate output without input)
Sample Programs
Cat program Program
'Cat in Tonoco' CCN CCU CNI COQ SL0 SC0 SY0 SF0 SZ0 SO0 SJ0
Cat program, using smart propagation
CCNCCQCNISL0SC0SJ0
Hello, World!
SQ72SQ101SQ108SQ108SQ111SQ44SQ32SQ119SQ111SQ114SQ108SQ100SQ33
Fibonacci Sequence
CGACGHCGOCOACATCAWCWICGUSU0ST0ST1SL0ST0SG0SW10000SF0SQ10SJ0
Greeter
CCSCSICCTCOACAUCOT SU0 SQ87SQ104SQ97SQ116SQ32SQ105SQ115SQ32SQ121SQ111SQ117SQ114SQ32SQ110SQ97SQ109SQ101SQ63SQ32 SL0 SO0SA1SC0SS10 SJ0 SO0SA1ST0 SU0 DOTCOACAUCOGCGICGQ SQ72SQ101SQ108SQ108SQ111SQ32 SL1 SA1SO0 SJ1
Deadfish Interpreter
'DEADFISH INTERPRETER IN TONOCO' COISL0 SQ62SQ62SQ32ST1CCTSC0DCT CGSCSUSS115SG1SS111SG1SS105SG1SS100SG1SS-1SG1DGSDSU SO0SY0 SF0 SZ0 SO0SY0 CGSCSTST0SG0SS1DGSDST SZ0 SO0SY0 CGACATST0SG0SA1DGADAT SZ0 SO0SY0 CGHSG0DGHSQ10 SZ0 SO0SY0 CGMCMTST0SG0SG0DGMDMT SZ0 CGSCSBCBISS256SG0SS-1SG0SY0ST0ST0SZ0DGSDSBDBI SL1ST1CCTSC0DCT CGSCSU SS10SG1 SS-1SG1 DGSDSU SO0SY0 SF0 SZ0 SO0SY0 SJ0 SZ0 SJ1
Truth-machine
CCSCSISS49SC0SF0SL0SH1SJ0