Abuse filter log

Abuse Filter navigation (Home | Recent filter changes | Examine past edits | Abuse log)
Jump to navigation Jump to search
Details for log entry 8,856

08:58, 8 January 2025: Galvandi (talk | contribs) triggered filter 10, performing the action "edit" on DominoScript. Actions taken: Disallow; Filter description: disallow non-administrators from making very large additions to pages (examine)

Changes made in edit

{{infobox proglang
|image=File:Dominoscript-logo.png
|name=DominoScript
|author=[[User:Galvandi]]
|year=[[:Category:2024|2024]]
|paradigms=imperative
|memsys=[[:Category:Stack-based|Stack-based]]
|dimensions=[[:Category:Two-dimensional languages|two-dimensional]]
|class=[[:Category:Turing complete|Turing complete]]
|majorimpl=[https://github.com/andreas-schoch/dominoscript Github Repo]
|files=<code>.ds</code> recommended
}}'''DominoScript''' is a two-dimensional self-modifying [[esoteric programming language]] that uses the dots on domino pieces to represent code.

== Core Concepts ==
'''<code>Domino Pieces</code>''':
* A domino piece can be placed either horizontally or vertically.
* DominoScript by default uses Double-Six (aka <code>D6</code>) dominos to represent code. Double-six here means that each domino has 2 sides with up to 6 dots each. Essentially Base7.
* Using the [[#Base|BASE]] instruction, you can tell the interpreter to parse dominos with up to 16 dots on each side. Allowing you to represent larger numbers with fewer dominos.
'''<code>Stack-Oriented</code>''':
* There is a global data stack that all instructions operate on.
* By default, the stack size is limited to 512 items (Up to the implementation to make this configurable. The default of the reference interpreter might become significantly larger with a future version).
* At its core, DS is just another concatenative [[Postfix notation|reverse-polish]] language. The following code: <code style="border-color:gray;">0—1 0—5 0—1 0—6 1—0 0—3 1—2 5—1</code> is the same as <code style="border-color:gray;">5 6 + dup * .</code> in [[Forth]].
* Internally every item on the stack is a signed 32-bit integer.
* Strings are just null-terminated sequences of integers representing Unicode char codes.
* Floats are not supported ''(Fixed-point-arithmetic might be supported in future versions)''.
* No other data structures exist.

'''<code>Two-Dimensional</code>''':
* The code is represented on a rectangle grid of cells. The top-left cell is address 0. The bottom-right cell is address <code>cols * rows - 1</code>.
* Any implementation needs to support a grid of at least 65408 total cells to be spec compliant. That allows a square grid of up to `256x256` cols and rows or any smaller rectangular grid within the cell limit. Each cell needs to be indexable using an <code>int32</code> popped from the data stack, so well optimized implementations may support crazy amounts of cells.
* The Instruction Pointer (IP) can move in any cardinal direction. Direction changes are performed by placing dominos in a certain way (IP always moves from one half to the other half of the same domino) as well as the current Navigation Mode. See: [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]].

'''<code>Self-Modifying</code>''':
* The code can override itself somewhat similar to befunge. See [[#Get|GET]] and [[#Set|SET]] instructions.
* Getting and setting can be done using different encodings:
** '''domino''': get or set single domino
** '''unsigned number''': get or set a number within the int32 range ''(why not uint32? Because the stack only supports int32 so there is no point)''. Up to 7 dominos can be parsed per get/set.
** '''signed number''': get or set a number within the int32 range. Up to 7 dominos can be parsed per get/set. The only different to unsigned number encoding is that here the first half of the first domino is sacrificed to encode the "sign bit" (if first half is anything but 0, sign bit is on).
** '''string''': Get or set a whole string.
* Can be used as a secondary data store ''(to act somewhat similar to registers or variables)'' besides the stack.

'''<code>Multiple Files</code>''':
* You can split up DS code into multiple files and include them in the main file using the [[#Import|IMPORT]] instruction.
* Each import has its own grid of cells.
* The data stack is shared between the main and all imported files.
* Defining a label within an imported file during the import phase, allows the parent to call functions within the child. Giving the parent essentially an interface to use the imported file as a library. ''(See the [[#Label|LABEL]] instruction for more info)''.

== Text Format ==
The dots on dominos are represented using a text based format:
* The digits <code>0</code> to <code>f</code> represent the dots on half of a domino. To indicate an empty cell, use a dot <code>.</code>
* The “long hyphen” character <code>—</code> indicates a horizontal domino ''(regular hyphen <code>-</code> also accepted to make it easier to type)''. It can only appear on '''even''' columns and '''odd''' rows.
* The “pipe” character <code>|</code> indicates a vertical domino. It can only appear on '''odd''' columns and '''even''' rows.
* Any other line <ins>before</ins> and <ins>after</ins> the actual code is ignored. ''(Tip: Make use of this to add extensive comments. You will inevitable forget what your dominoscript code does, so consider including a 1:1 pseudocode implementation of the dominoscript code)''

The following DominoScript code ''(which prints "Hello world")'':

<pre style="letter-spacing:4px;line-height:1.1;display:inline-block;border-color: black;">
. . . . . . . . . . . . . . .
. . . . . . . . 0—2 1 . 0—3 .
|
. 1 0—3 2—1 4—4 . . 2 . 2 1 .
| | |
. 2 . . . . . 0 . . 0—6 1 2 .
|
. 1—6 1—2 2 . 1 6—1 . . . 1 .
| |
. . . . . 2 . . . 2 . . . 3 .
|
. 1 3—1 2—1 . . . 1 3—1 2—1 .
|
. 2 0—2 0 . . . . . . . . . .
|
. . . . 0 5—3 . . . . . . . .
</pre>

Is the equivalent of the following dominos:

<br>[[File:DominoScript-Example-003-flow.png|400px|Hello world 2d]]


The grid doesn’t have to be a square but it must have a consistent number of columns and rows, otherwise an <code>InvalidGridError</code> will be thrown before execution starts:

<table class="wikitable">
<tr><th>GOOD ✅</th><th>BAD ❌</th></tr>
<tr><td>
<pre>. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .</pre>
</td>
<td>
<pre> . . . . . . .

. . . . . . . .

. . . . .

. . . . . . .</pre>
</td>
</tr>
</table>
Connecting to a domino half which is already connected results in <code>MultiConnectionError</code>:

<table class="wikitable">
<tr><th>GOOD ✅</th><th>BAD ❌</th></tr>
<tr><td>
<pre>6—6 6—6 .

6 6—6 . .
|
6 . . . .</pre>
</td>
<td>
<pre>6—6—6—6 .

6—6 . . .
|
6 . . . .</pre>
</td>
</tr>
</table>
Having a domino half that is not connected to anything results in <code>MissingConnectionError</code>:

<table class="wikitable">
<tr><th>GOOD ✅</th><th>BAD ❌</th></tr>
<tr><td>
<pre>. . 6—6 .

. 6 . . .
|
. 6 . . .</pre>
</td>
<td>
<pre>. . 6 6 .

. 6 . . .
. 6 . . .</pre>
</td>
</tr>
</table>
Having a connection where 1 or both ends are empty results in a <code>ConnectionToEmptyCellError</code>:

<table class="wikitable">
<tr><th>GOOD ✅</th><th>BAD ❌</th></tr>
<tr><td>
<pre>6—6 . 6—6

6 . . . 6
| |
6 . . . 6</pre>
</td>
<td>
<pre>6—. . .—6

6 . . . .
| |
. . . . 6</pre>
</td>
</tr>
</table>

== How Dominos are parsed into Numbers ==
It is important to understand that '''internally''' everything in DominoScript is represented as signed 32-bit Integers and '''externally''' everything is represented by the dots on the domino pieces.

'''Every domino is part of either''':
* An opcode - decides which instruction to execute next. By default, one domino represents one opcode unless you tell the interpreter to use 2 dominos per opcode using the [[#Ext|EXT]] instruction.
* A number literal - the [[#Num|NUM]] instruction is used to push a single Integer onto the stack.
* A string literal - the [[#Str|STR]] instruction is used to push a sequence of Integers onto the stack which represent unicode char codes.

'''Furthermore, you should also be aware of the following things''':
* The number base system that is currently set influences how dots are parsed into numbers. The base can be changed using the [[#Base|BASE]] instruction. (Default: Base 7 - because double-six dominos are the most common).
* The "LiteralParseMode" tells the interpreter how many dominos will be part of a literal. It can be changed using the [[#Lit|LIT]] instruction (Default: dynamic - first half of first domino decides how many more are part of a number literal).
* Once a literal is pushed on the stack, it is your job as the developer to keep track of which items are numbers and which ones are characters of a string. You can use any instruction on characters of a “string” but only the following ones will treat them as such: [[#Str|STR]], [[#Eqlstr|EQLSTR]], [[#Strin|STRIN]], [[#Strout|STROUT]] as well as [[#Get|GET]] and [[#Set|SET]] when used with the "string" encoding type.

In examples, you might see stack items that are meant to be char codes, represented in the following way:”

<pre>[..., 1, 2, 3 'NUL', 's', 'e', 'y']</pre>
But in reality, the stack will store them as integers and look like this:

<pre>[..., 1, 2, 3, 0, 115, 101, 121]</pre>

'''What about floats?'''

Floats don’t exist in DominoScript. I’d suggest scaling up numbers by a factor of 10, 100, 1000 or whatever precision you need.

''(I know that pico-8 uses 32-bits for numbers but treats them as 16.16 fixed point numbers. I am not quite sure if that is just a convention or if pico8’s API actually treats them as fixed-point numbers. I would like to eventually add some trigonometry instructions to DominoScript but am unsure what the most practical way would be)''

== How the Instruction Pointer Moves ==
The Instruction Pointer (<code>IP</code>) keeps track of the current cell address that will be used for the next instruction. Since DominoScript is 2D, it isn’t obvious where the IP will move to without understanding the fundamental rules and the Navigation Modes.

'''Before the program starts:'''
# The interpreter will scan the grid from '''top-left to top-right''', move down and repeat until it finds the first domino.
# Upon reaching the first domino, the IP is placed at the address of the first found domino half.
# If no domino could be found, the program is considered finished.

'''During the program execution:'''<br>
The IP will adhere to the following rules:
* The IP can move in cardinal directions, never diagonally. How dominos are parsed, is all relative to that. For example, the horizontal domino <code>3—5</code> can be interpreted as the base7 number <code>35</code> (IP moves eastwards) or <code>53</code> (IP moves westwards). Same thing for vertical dominos.
* The IP will always move from one half (entry) of the same domino to the other half (exit) of the same domino.
* If the IP cannot move to a new domino, the program is considered finished.
* At the exit half of a domino, the IP will never move back to the entry half. It will always try to move to a new domino. That means, there are at most 0 to 3 potential options for the IP to move.
* When the IP needs to move to a new domino, it is possible that there are no valid moves despite there being dominos around. The [[#Navigation_Modes|Navigation Mode]] decides where the IP can and cannot move next.

'''Understanding Navigation Modes:'''<br>
Navigation Modes are predefined priority patterns which are used when the Instruction Pointer needs to decide to which domino to move to next. The [[#Navm|NAVM]] instruction can be used to change the current Navigation Mode.

Understanding the following concepts will become very important:
* '''Priority Directions''': Primary, Secondary, Tertiary
* '''Relative Directions''': Forward, Left, Right
* '''Cardinal Directions''': North, East, South, West

The Cardinal directions don’t matter much. It is all about the '''direction in relation to the exit half''' of the current domino ''(If you ever did any kind of GameDev you probably know the difference between world space and local space. It’s kind of like that)''

When the IP moves to a new domino, the half it enters to is called the “'''entry'''” while the other half is called the “'''exit'''”. Now from the perspective of the exit half, the IP can potentially move in 3 directions: Forward, Left, Right. These are the '''Relative Directions'''.

Which relative direction the IP chooses, depends on the current Navigation Mode. Below you will see the mapping of the very basic nav modes:

{| class="wikitable"
|-
! Index !! <code>Primary</code> !! <code>Secondary</code> !! <code>Tertiary</code>
|-
| 0 || Forward || Left || Right
|-
| 1 || Forward || Right || Left
|-
| 2 || Left || Forward || Right
|-
| 3 || Left || Right || Forward
|-
| 4 || Right || Forward || Left
|-
| 5 || Right || Left || Forward
|-
| ... || ... || ... || ...
|}
''The “index” here is the argument for the <code>NAVM</code>instruction.''

<br>

'''If we imagine the <code>6</code> to be the exit half, what will be the next domino the IP moves to?:'''

<table class="wikitable" style="line-height:1.1;letter-spacing:4px;">
<tr>
<th>East</th>
<th>West</th>
<th>South</th>
<th>North</th>
</tr>
<tr>
<td>
<pre>
. 2 . . .
|
. 2 . . .

5—6 1—1 .

. 3 . . .
|
. 3 . . .
</pre>
</td>
<td>
<pre>
. . . 3 .
|
. . . 3 .

. 1—1 6—5

. . . 2 .
|
. . . 2 .
</pre>
</td>
<td>
<pre>
. . 5 . .
|
3—3 6 2—2

. . 1 . .
|
. . 1 . .

. . . . .
</pre>
</td>
<td>
<pre>
. . . . .

. . 1 . .
|
. . 1 . .

2—2 6 3—3
|
. . 5 . .
</pre>
</td>
</tr>
</table>
''All 4 snippets are exactly the same code with the difference that they are all flipped differently. This is what I mean by the cardinal direction not mattering much in DominoScript.''

* When <code>index 0</code>, the IP will move to <code>1—1</code> (Primary, Forward)
* When <code>index 1</code>, the IP will move to <code>1—1</code> (Primary, Forward)
* When <code>index 2</code>, the IP will move to <code>2—2</code> (Primary, Left)
* When <code>index 3</code>, the IP will move to <code>2—2</code> (Primary, Left)
* When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right)
* When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right)

<br>

'''What if we remove the <code>1—1</code> domino? Where will the IP go to then?:'''

<table class="wikitable" style="line-height:1.1;letter-spacing:4px;">
<tr>
<th>East</th>
<th>West</th>
<th>South</th>
<th>North</th>
</tr>
<tr>
<td>
<pre>. 2 . . .
|
. 2 . . .

5—6 . . .

. 3 . . .
|
. 3 . . .</pre>
</td>
<td>
<pre>. . . 3 .
|
. . . 3 .

. . . 6—5

. . . 2 .
|
. . . 2 .</pre>
</td>
<td>
<pre>. . 5 . .
|
3—3 6 2—2

. . . . .
. . . . .

. . . . .</pre>
</td>
<td>
<pre>. . . . .

. . . . .
. . . . .

2—2 6 3—3
|
. . 5 . .</pre>
</td>
</tr>
</table>
* When <code>index 0</code>, the IP will move to <code>2—2</code> (Secondary, Left)
* When <code>index 1</code>, the IP will move to <code>3—3</code> (Secondary, Right)
* When <code>index 2</code>, the IP will move to <code>2—2</code> (Primary, Left)
* When <code>index 3</code>, the IP will move to <code>2—2</code> (Primary, Left)
* When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right)
* When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right)

<br>

'''And what if we remove both the <code>1—1</code> and the <code>2—2</code> domino?:'''

<table class="wikitable" style="line-height:1.1;letter-spacing:4px;">
<tr>
<th>East</th>
<th>West</th>
<th>South</th>
<th>North</th>
</tr>
<tr>
<td>
<pre>. . . . .
. . . . .

5—6 . . .

. 3 . . .
|
. 3 . . .</pre>
</td>
<td>
<pre>. . . 3 .
|
. . . 3 .

. . . 6—5

. . . . .
. . . . .</pre>
</td>
<td>
<pre>. . 5 . .
|
3—3 6 . .

. . . . .
. . . . .

. . . . .</pre>
</td>
<td>
<pre>. . . . .

. . . . .
. . . . .

. . 6 3—3
|
. . 5 . .</pre>
</td>
</tr>
</table>
* When <code>index 0</code>, the IP will move to <code>3—3</code> (Tertiary, Right)
* When <code>index 1</code>, the IP will move to <code>3—3</code> (Secondary, Right)
* When <code>index 2</code>, the IP will move to <code>3—3</code> (Tertiary, Right)
* When <code>index 3</code>, the IP will move to <code>3—3</code> (Secondary, Right)
* When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right)
* When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right)

<br>

These are only variations of the “Basic-Three-Way” kind of NavModes. See the [[#Navigation_Modes|Reference]] for a full list of available modes.

== Instructions ==

Instructions are mapped to opcodes behind the scenes:

* '''0-48''': Are the “core” instructions ''(2 have yet to be mapped)'' and are meant to fit within the value range a single “double-six” domino can represent.
* '''49-99''': Reserved for future extensions of the language ''(e.g. fixed-point-arithmetic, helpers for more advanced string manipulation and such)''
* '''100+''': Allow you as developer to extend the language yourself with non-standard behaviour. These opcodes are essentially alternative ways of calling by label. To learn more, see: [[#Call|CALL]], [[#Label|LABEL]] and [[#Import|IMPORT]] instructions.

To know which domino represents which opcode, you have to know the currently active [[#Base|base]]. For example, to represent opcode 48...:
* in '''base7''' you use a '''<code>6—6</code>''' domino (default)
* in '''base10''' you use a '''<code>4—8</code>''' domino
* in '''base16''' you use a '''<code>3—0</code>''' domino

<br>

The core instructions are grouped in 7 categories of 7 instructions each. Below, you will see them listed all.
''(The numbers on the right beside the instruction titles are the corresponding opcode)''

<br>
=== Stack Management ===

<span id="Pop"></span>
==== POP - 0 ====
Discards the top of the stack.

<span id="Num"></span>
==== NUM - 1 ====
Switch to “number mode”. By default, the first half of the next domino will indicate how many dominos to read as a number. Then the other halfs will all be read as base7 digits (in D6 mode) to form the number that will be pushed to the stack.

With 7 dominos, 13 out of 14 halfs are used for the number. You can theoretically represent a number much larger than the max int32 value. However, if the number exceeds the maximum int32 value, it will wrap around from the minimum value, and vice versa ''(exactly the same as when doing bitwise operations in JS –&gt; <code>(96889010406 | 0) === -1895237402</code>)''.

You might think that since internally numbers are int32s, that we parse from base7 to two’s complement. That is not the case. We simple push the decimal version of the positive base7 number to the stack

'''For example:'''

* <code>0—0</code> represents the number <code>0</code> in both decimal and base7
* <code>0—6</code> represents the number <code>6</code> in both decimal and base7
* <code>1—6 6—6</code> represents the number <code>342</code> in decimal and <code>666</code> in base7
* <code>2—6 6—6 6—6</code> represents the number <code>16,806</code> in decimal and <code>6,666</code> in base7
* <code>6—6 6—6 6—6 6—6 6—6 6—6</code> represents the number <code>1,977,326,742</code> in decimal and <code>66,666,666,666</code> in base7 (about 92.1% of the max int32 value)
* <code>6—0 1—0 4—1 3—4 2—1 1—1 6—1</code> represents the number <code>2,147,483,647</code> in decimal and <code>104,134,211,161</code> in base7 (exactly the max int32 value)
* <code>6—6 6—6 6—6 6—6 6—6 6—6 6—6</code> represents the number -1,895,237,402. '''WHY?''': The actual decimal number the dominos represent is <code>96,889,010,406</code> which is ~45x larger than the max int32 value. It wraps around about that many times before it reaches the final value.

'''What if numbers are read from the other directions?'''

* <code>1—1 1—1</code>, <code>2—2 2—2 2—2</code> for example will be exactly the same numbers (216 in decimal) eastwards and westwards.
* <code>1—2 3—1</code> when parsed backwards is <code>1—3 2—1</code> and can therefore represent different numbers if the IP moves to the east or to the west.
* <code>1—6 6—6</code> represents 666 in base7 (342 in decimal) but when parsed backwards the interpreter will raise an <code>UnexpectedEndOfNumberError</code>. Remember that the first half of the first domino indicates how many more will follow. In this case it expects to read 6 more dominos but the number ends prematurely after 1 domino.

'''What if I want to use a fixed amount of dominos for each number?'''

Use the [[#Lit|LIT]] instruction to permanently change how literals are parsed. For example with parse mode <code>2</code> it will use 2 dominos for each number. While <code>6—6 6—6</code> in default parse mode 0 results in <code>UnexpectedEndOfNumberError</code> (because it expects 6 more dominos to follow but only got 1 more), in parse mode <code>2</code> it represents the decimal number <code>2400</code>.

<span id="Str"></span>
==== STR - 2 ====
With <code>STR</code> you switch to “string mode” and can push multiple integers to the stack to represent Unicode characters.

The way the dominos are parsed to numbers is identical to <code>NUM</code>: First half of first domino indicates how many more will follow for a single number.

The difference is that it doesn’t stop with just one number. It will keep reading numbers until it encounters the NULL character represented by domino <code>0—0</code>.

Only once the interpreter does encounter the NULL character, will it push the characters to the stack in <ins>reverse</ins> order.

''(Note: I decided to parse strings like this because I wanted a single int32 based stack and, out of all options I could think of, this one felt the least annoying. If you can think of better ways, I am open for suggestions!)''

This is how you push the string <code>&quot;hi!&quot;</code> to the stack and output it:

<pre>0—2 1—2 0—6 1—2 1—0 1—0 4—5 0—0 5—3</pre>
It equals the following pseudo code: <code>STR &quot;hi!&quot; STROUT</code>

* <code>0—2</code> is the <code>STR</code> instruction
* <code>1—2 0—6</code> is the Unicode value 105 representing the character <code>h</code>
* <code>1—2 1—0</code> is the Unicode value 105 representing the character <code>i</code>
* <code>0—0 4—5</code> is the Unicode value 33 representing the character <code>!</code>
* <code>0—0</code> is the Unicode value for the NULL character which terminates the string.
* <code>5—3</code> is the [[#Strout|STROUT]] instruction. It will pop items from the stack, parse them as Unicode chars and once it encounters the NULL character, it will output the string to stdout all at once.

This is the resulting stack:

<table class="wikitable">
<tr>
<th>
Imaginative
</th>
<th>
Reality
</th>
</tr>
<tr>
<td>
<pre>[..., 'NUL', '!', 'i', 'h']</pre>
</td>
<td>
<pre>[..., 0, 33, 105, 104]</pre>
</td>
</tr>
</table>
Keep in mind that the IP can move in 4 cardinal direction so the following variations would also push the string <code>&quot;hi!&quot;</code> to the stack:

IP moves right to left:

<pre>3—5 0—0 5—4 0—1 0—1 2—1 6—0 2—1 2—0</pre>
IP moves in multiple directions:

<pre>0 . . . . 0 4—5
| |
2 . . . . 1 . 0
|
1 . . 2 1—0 . 0
| |
2 0—6 1 . . 3—5</pre>

<span id="Dupe"></span>
==== DUPE - 3 ====
Duplicate the top item on the stack.

<span id="Roll"></span>
==== ROLL - 4 ====
Pops one argument from the stack to be used as “depth”.

* With a negative depth, the item at the <ins>top</ins> is moved to the <ins>nth depth</ins>
* With a positive depth, the item at the <ins>nth depth</ins> is moved to the <ins>top</ins>

With roll you can implement common stack operations like <code>SWAP</code> and <code>ROT</code>:

{| class="wikitable"
! Roll Depth
! Equivalent to
! Stack Before
! Stack After
|-
| -3
| -
| <code>[a, b, c, d]</code>
| <code>[d, a, b, c]</code>
|-
| -2
| ROTR
| <code>[a, b, c]</code>
| <code>[c, a, b]</code>
|-
| -1
| SWAP
| <code>[a, b]</code>
| <code>[b, a]</code>
|-
| 0
| NOOP
| <code>[a]</code>
| <code>[a]</code>
|-
| 1
| SWAP
| <code>[a, b]</code>
| <code>[b, a]</code>
|-
| 2
| ROTL
| <code>[a, b, c]</code>
| <code>[b, c, a]</code>
|-
| 3
| -
| <code>[a, b, c, d]</code>
| <code>[b, c, d, a]</code>
|}

<span id="Len"></span>
==== LEN - 5 ====
Pushes the number of items on the stack.

<span id="Clr"></span>
==== CLR - 6 ====
Removes all items from the stack.

<br>
=== Arithmetic ===

<span id="Add"></span>
==== ADD - 7 ====
Pops 2 numbers from the stack. The sum is pushed to the stack.

<span id="Sub"></span>
==== SUB - 8 ====
Pops 2 numbers from the stack. The result of <code>numberA - numberB</code> is pushed to the stack.

<span id="Mult"></span>
==== MULT - 9 ====
Pops 2 numbers to multiply. The result is pushed to the stack.

<span id="Div"></span>
==== DIV - 10 ====
Pops 2 numbers. The result of the division of numberA by numberB is pushed to the stack. (Keep in mind that DominoScript is integer based and any remainder is discarded.)

<span id="Mod"></span>
==== MOD - 11 ====
Pops 2 numbers. The remainder of division of <code>numberA / numberB</code> is pushed to the stack.

Note: When numberA is positive modulo behaves identical in most languages (afaik). However, there are some differences across programming languages when numberA is negative. In DominoScript modulo behaves like in JavaScript, Java, C++ and Go and <ins>NOT</ins> like in Python or Ruby!

<span id="Neg"></span>
==== NEG - 12 ====
Negate the top of the stack.

<span id="Clamp"></span>
==== CLAMP -13 ====
Pops 3 numbers from the stack:

<pre>[..., value, min, max]</pre>

And pushes back the clamped value onto the stack.

<br>
=== Comparison &amp; Logical ===

<span id="Not"></span>
==== NOT - 14 ====
Pops the top item off the stack. If it is <code>0</code>, it pushes <code>1</code>. Otherwise it pushes <code>0</code> to the stack.

<span id="And"></span>
==== AND - 15 ====
Pops the top 2 items off the stack, performs the logical AND operation and pushes the result back onto the stack.

<span id="Or"></span>
==== OR - 16 ====
Pops the top 2 items off the stack, performs the logical OR operation and push the result back onto the stack.

<span id="Eql"></span>
==== EQL - 17 ====
Pops the top 2 items off the stack, compares them and pushes the result back onto the stack. If the items are equal, it pushes <code>1</code> to the stack, otherwise <code>0</code>.

<span id="Gtr"></span>
==== GTR - 18 ====
Pops the top 2 items off the stack, compares them and pushes the result back onto the stack. If the first item is greater than the second, it pushes <code>1</code> to the stack, otherwise <code>0</code>.

<span id="Eqlstr"></span>
==== EQLSTR -19 ====
Assumes that 2 strings are on the stack. It pops them, compares them and pushes <code>1</code> to the stack if equal, otherwise <code>0</code>.

'''<ins>For example:<ins>'''<br />
You push the strings <code>&quot;AC&quot;</code> then <code>&quot;DC&quot;</code>. They are represented on the stack as <code>[NULL, C, A, NULL, C, D]</code> (In reality it is <code>[0, 67, 65, 0, 67, 68]</code>). Since the strings are not equal, it will push <code>0</code> to the stack. It is now <code>[0]</code>.

'''<ins>Another example:<ins>'''<br />
Imagine you want to check if the user pressed arrow left. You execute the <code>KEY</code> instruction after which the stack looks like <code>[&lt;existing&gt;, 0, 68, 91, 27]</code> then you push the <ins>escape sequence</ins> which represents the left arrow key. The stack is now <code>[&lt;existing&gt;, 0, 68, 91, 27, 0, 68, 91, 27]</code>. You then execute the <code>EQLSTR</code> instruction which will pop the top 2 strings and since the strings are equal, it will push <code>1</code> to the stack. It is now <code>[&lt;existing&gt;, 1]</code> ''(See the [[#Key|KEY]] instruction for more info about escape sequences)''.

<span id="Reserved_20"></span>
==== RESERVED - 20 ====
Unmapped opcode. Will throw <code>InvalidInstructionError</code> if executed.

<br>
=== Bitwise ===

<span id="Bnot"></span>
==== BNOT - 21 ====
Bitwise NOT. Pops the top item off the stack, inverts all bits and pushes the result back onto the stack.

<span id="Band"></span>
==== BAND - 22 ====
Bitwise AND. Pops the top 2 items off the stack, performs bitwise AND and pushes the result back onto the stack.

<span id="Bor"></span>
==== BOR - 23 ====
Bitwise OR. Pops the top 2 items off the stack, performs bitwise OR and pushes the result back onto the stack.

<span id="Bxor"></span>
==== BXOR -24 ====
Bitwise XOR. Pops the top 2 items off the stack, performs bitwise XOR and pushes the result back onto the stack.

<span id="Lsl"></span>
==== LSL - 25 ====
Logical Shift Left. Performs the equivalent of <code>argA &lt;&lt; argB</code> and pushes the result back onto the stack.

<span id="Lsr"></span>
==== LSR - 26 ====
Logical Shift Right. Performs the equivalent of <code>argA &gt;&gt;&gt; argB</code> and pushes the result back onto the stack.

<span id="Asr"></span>
==== ASR - 27 ====
Arithmetic Shift Right. Performs the equivalent of <code>argA &gt;&gt; argB</code> and pushes the result back onto the stack.

<br>
=== Control Flow ===

<span id="Navm"></span>
==== NAVM - 28 ====
Changes the Navigation Mode. The default Mode is <code>0</code>.

See [[#Navigation_Modes|Navigation Modes]] to see all possible nav modes and their indexes.

If you don't know what navigation modes are and how they influence the Instruction Pointer, I'd recommend reading the relevant section in [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]].

<span id="Branch"></span>
==== BRANCH - 29 ====
Like an IF-ELSE statement.

It pops the top of the stack as a condition and then:

<pre style="letter-spacing:4px;line-height:1.1;">
. . . . . 6 . .
|
. . . . . 6 . .

0—1 0—1 4—1 . .
. . . . . 5 . .
|
. . . . . 5 . .
</pre>

* If popped value is a non-zero number: The IP will move to the relative '''LEFT''' (the <code>6-6</code>domino)
* If popped value is zero: The IP will move to the relative '''RIGHT''' (the <code>5-5</code>domino)

When using branch, the current Navigation Mode is ignored. You can always be assured that the IP will either move to the relative left or right.

<span id="Label"></span>
==== LABEL - 30 ====
Label are like a bookmarks or an alternative identifier of a specific Cell address. They can be used by the <code>JUMP</code>, <code>CALL</code>, <code>GET</code> and <code>SET</code> instructions (although these also work directly with addresses, so labels are not mandatory)

'''Labels are probably not what you expect them to be.'''
* They are '''NOT''' strings, but negative numbers.
* They are auto generated and self decrementing: <code>-1</code>, <code>-2</code>, <code>-3</code>, etc.
* You can kind of imagine them as pointers to a specific cell address.

Executing the LABEL instruction pops the address of the cell you want to label and assigns it to the next available negative number.

The negative number will '''NOT''' be pushed to the stack. First label will be <code>-1</code>, second label will be <code>-2</code> and so on. You need to keep track of them yourself.

For clarity, I’d generally recommend adding comments like the following to your source files:

<pre>
| Label | Address | Function name |
|-------|---------|---------------|
| -1 | 340 | main |
| -2 | 675 | update |
| -3 | 704 | render |
</pre>

'''About Labels in imported files:'''
DominoScript has an <code>IMPORT</code> instruction that allows source files to be imported into others. The imported functions can only be called via labels, so in that regard a label also acts like an export. If the parent file doesn’t define labels of their own, the label values will be the same in both parent and child. However if the parent file creates labels <ins>before</ins> importing a child file, the exported child labels will have a different value in the parent. For example:<br />
# Parent creates label <code>-1</code>, <code>-2</code>, <code>-3</code> and then imports the child file
# The child file defines labels <code>-1</code>, <code>-2</code>, <code>-3</code> and gives back control to parent
# The parent file will now have the labels <code>-1</code>, <code>-2</code>, <code>-3</code> and the child labels will be <code>-4</code>, <code>-5</code>, <code>-6</code>
# Now when the parent wants to call a child function which internally is labelled with <code>-1</code>, it needs to use label <code>-4</code> instead.

<span id="Jump"></span>
==== JUMP - 31 ====
Moves the IP to an address on the grid. You can either use a label or an address as an argument.

If the IP cannot move anymore, the interpreter will throw a <code>StepToEmptyCellError</code>.
If label is unknown it will throw an <code>UnknownLabelError</code>.

<span id="Call"></span>
==== CALL - 32 ====
Like the name suggests, it is similar to a function call. When The IP cannot move anymore, it will return to the address from where it was called from.

You can do recursive calls. An implementation should support a depth of at least 512 to be spec compliant.

'''Alternative way to CALL''' Instead of doing <code>ǸUM 1 NEG CALL</code> to call by label, you can just do <code>OPCODE_100</code>. Why? Because labels are mapped to opcodes 100+. So when you create the labels <code>-1</code>, <code>-2</code>, <code>-3</code>, etc. they are automatically mapped to opcodes <code>100</code>, <code>101</code>, <code>102</code>.

<span id="Import"></span>
==== IMPORT - 33 ====
Pop a “string” from the stack to indicate the file name of the source file to import.

On import the interpreter will load the file and start running it until its Instruction Pointer cannot move anymore.

Labels defined in the imported file are accessible from the file which imports it. That means you can call functions from the imported file via the <code>CALL</code> instruction.

If the importing file defined a label before the import, the labels from the imported file will have different identifiers. For example:
* <code>FileChild.ds</code> defines a label <code>-1</code>.
* <code>FileAParent.ds</code> defines labels <code>-1</code>, <code>-2</code>, then imports FileChilds.ds.s

The <ins>internal</ins> label <code>-1</code> in <code>FileChild.ds</code> will be <code>-3</code> <ins>externally</ins> in <code>FileAParent.ds</code> because labels are always auto decrementing. '''Why?''' Because it is the simplest way to avoid conflicts and be able to use labels internally and externally.

The data stack is shared between parent and all imported files. Apart from that, the parent and child imports run in their own contexts. Imported files can have imports themselves but you should avoid circular dependencies.

If you import the same file into more than one other file, it will result in multiple instances of the imported file. This is probably not a problem as long as you are aware of it ''(It might even be useful if you treat imports of the same file as "objects instances")''.

<span id="Wait"></span>
==== WAIT - 34 ====
Pops the top item off the stack and waits for that many milliseconds before continuing.

''Within DominoScript, you could simulate a delay with a ‘busy loop’ by using the TIME, GTR and BRANCH instructions within a loop. Internally an implementation is free to implement WAIT using a busy loop to avoid having to deal with asynchronous code. However, to be spec compliant it should ideally add some form of interrupt handling so the interpreter can be stopped when the user tries to exit (via e.g. Ctrl+C) even if the code is stuck in an infinite loop.''

<br>
=== Input &amp; Output ===

<span id="Numin"></span>
==== NUMIN - 35 ====
Prompt the user for a number. The user input will be pushed to the stack.

<span id="Numout"></span>
==== NUMOUT - 36 ====
Pop the top item from the stack and output it to stdout.

<span id="Strin"></span>
==== STRIN - 37 ====
Prompt the user for a string. The user input will be pushed to the stack as individual Unicode characters in reverse order.

So if the user inputs <code>&quot;yes&quot;</code>, the stack will look like this:

<pre>[..., 0, 115, 101, 121]</pre>
For convenience you might often see the stack represented But remember that in reality it just stores int32s.

<pre>[..., NUL 's', 'e', 'y']</pre>

''Note: Since each char is pushed to the stack, the max input string length is limited to the available stack space. By default, the max stack size is 512 for the reference interpreter. This limit will likely be increased to ~64k''

<span id="Strout"></span>
==== STROUT - 38 ====
Pops numbers (representing Unicode char codes) from the stack until it encounters a null terminator (number 0). It will then output the string to stdout.

<ins>
'''There is one special case:'''
</ins>
If the parser encounters the <code>Unit Separator</code> (ascii 31), it stringifies the <ins>next</ins> number instead of treating it as a unicode char code. This is very useful to generate ANSI escape sequences like <code>\x1b[15;20H[-]</code> which tells the terminal to draw <code>[-]</code> at row 15 and column 20. Without the <code>Unit Separator</code> you would have to push the char code for 1, 5 and 2, 0 individually. This is a pain if you are dealing with dynamic numbers. The [[./examples/023_input_controls_advanced.md|example_023]] uses this to create an escape sequence.

<span id="Key"></span>
==== KEY - 39 ====
Check if the user pressed a specific key since the last reset with <code>KEYRES</code>. If the key was pressed, it pushes <code>1</code> to the stack, otherwise <code>0</code>.

It pops a <ins>string sequence</ins> of the stack to represent the key you want to check for.

Unlike <code>NUMIN</code> and <code>STRIN</code> it doesn’t block the program, so you can use it in a loop to check for user input.

'''<ins>What string sequence?:</ins>''' - If a key is a printable character, the sequence is the Unicode value of the key. For example, to check if the user pressed the <code>a</code> key, you would push the string <code>a</code>. - If a key is a special key like arrow left, right etc, the sequence is an escape sequence. For example, to check if the user pressed the left arrow key, you would push the escape sequence <code>\u001b[D</code> to the stack.

'''<ins>What is an escape sequence?:</ins>'''

Escape sequences are sequences of characters that are used to represent special non-printable keyboard keys like arrow keys but can also be used to control terminal behavior, such as cursor position, text color and more. You can google them. Then just transform them to the correct domino sequence.

<span id="Keyres"></span>
==== KEYRES - 40 ====
Resets the state of all keys to “not pressed”. It is used in combination with <code>KEY</code> to check if a key was pressed since the last reset. It has no effect on the stack.

Imagine you have a game running at 20fps. Every 50ms you check if the user pressed any of the arrow keys and act accordingly. Then at the end of the frame you reset the state of all keys to “not pressed” with <code>KEYRES</code>.

<span id="Reserved_41"></span>
==== RESERVED - 41 ====
Unmapped opcode. Will throw <code>InvalidInstructionError</code> if executed.

''(Might be used as opcode for a <code>MOUSE</code> instruction which pushes the clickX and clickY position of the mouse since the last KEYRES reset)''

<br>
=== Misc ===

<span id="Get"></span>
==== GET - 42 ====
Reads data from the board and pushes it to the stack. Takes 2 arguments from the stack:
* The type Index to parse it as. It indicates the type and the direction of the data.
* The address of the first domino half

'''There are essentially 4 types you can parse it as''':
* '''Domino''': The value of the cell at the address and its connection. Essentially a single domino
* '''Unsigned Number''': A number between 0 to 2147483647 ''(Hold on! Why not 4294967295? Because the data stack uses int32 and 2147483647 is the max value you can have in the stack. “Unsigned” here doesn’t mean uint32, just that we don’t “waste” half a domino to represent the sign)''.
* '''Signed Number''': A number between -2147483648 to 2147483647 (int32 range).
* '''String''': A string is a sequence of null terminated unicode char codes.

<ins>
'''And the following directions'''
</ins>
:

* '''SingleStraightLine''': The IP moves in a straight line towards the <ins>connection direction of the cell at the address</ins>. No wrap around like in “RawIncrement” mode. If you have a 10x20 grid you can get at most 5 dominos in horizontal direction or 10 dominos in vertical direction.
* '''RawIncrement''' (to be implemented): Reads domino halfs using incrementing addresses. It disregards the grids bounds and wraps around from right edge left edge on the next line ''(Remember that addresses are essentially the indices to a 1D array of Cells which represent the Grid. Address 0 is at the top left of the grid. In a 10x10 grid, the largest address is 99 in the bottom right)''

'''Here a table of supported encoding type mappings:'''
{| class="wikitable"
! Type Index
! Type
! Direction
|-
| 0
| Domino
| connection direction
|-
| 1
| Unsigned Number
| SingleStraightLine
|-
| 2
| Signed Number
| SingleStraightLine
|-
| 3
| String
| SingleStraightLine
|-
| 4 (TODO)
| Unsigned Number
| RawIncrement
|-
| 5 (TODO)
| Signed Number
| RawIncrement
|-
| 6 (TODO)
| String
| RawIncrement
|}

<span id="Set"></span>
==== SET - 43 ====
Writes data to the board. Takes <ins>at least</ins> 2 arguments from the stack:
* The type Index to parse it as. It indicates the type and the direction of the data
* The address of the first domino half
* The data to write to the board. This can either be a single item from the stack or multiple if we write a string

<ins>
'''There are essentially 4 types you can write it as'''
</ins>

(See list under [[#Get|GET]]):

<ins>
'''And the following directions'''
</ins>
:

* '''SingleStraightLine''': The IP moves in a straight line towards the <ins>last Instruction Pointer direction</ins>. No wrap around like in “RawIncrement” mode. If you have a 10x20 grid you can set at most 5 dominos in horizontal direction or 10 dominos in vertical direction.
* '''RawIncrement''' (to be implemented): Writes domino halfs using incrementing addresses. It disregards the grids bounds and wraps around from right edge left edge on the next line ''(Remember that addresses are essentially the indices to a 1D array of Cells which represent the Grid. Address 0 is at the top left of the grid. In a 10x10 grid, the largest address is 99 in the bottom right)''

'''Here a table of supported type mappings:'''

(See table under [[#Get|GET]]):

<span id="Lit"></span>
==== LIT - 44 ====
Changes how number and string literals are parsed. It pops a number from the stack to use as the “literal parse mode”. The popped number must be between 0 to 6. If the number is out of bounds, an <code>DSInvalidLiteralParseModeError</code> is thrown.

'''If the popped argument is:'''
* <code>0</code>: Dynamic parse mode. Used by default. The first domino half of every number literal indicates how many more dominos should be parsed as part of the number. For string literals it is exactly the same but for each character.
* <code>1</code> to <code>6</code>: Static parse modes. Uses 1 to 6 dominos for each number literal or each character in a string literal.

In the following 3 examples <code>&quot;Hello world&quot;</code> is encoded in 3 different ways:

In Base7 with Literal Parse Mode 0 (default):

<pre>// Every character requires 2 dominos to be encoded on dominos
0—2 1—2 0—6 1—2 0—3 1—2 1—3 1—2 1—3 1—2 1—6 1—0 4—4 1—2 3—0 1—2 1—6 1—2 2—2 1—2 1—3 1—2 0—2 0—0</pre>
In Base 16 with Literal Parse Mode 0:

<pre>// Still every character requires 2 dominos to be encoded. Considering that we are in base 16, very wasteful!
0—2 1—0 6—8 1—0 6—5 1—0 6—c 1—0 6—c 1—0 6—f 1—0 2—0 1—0 7—7 1—0 6—f 1—0 7—2 1—0 6—c 1—0 6—4 0—0</pre>
In Base 16 with Literal Parse Mode 1:

<pre>// Every character requires 1 domino to be encoded.
// Notice how now it is pretty much just hexadecimal
0—2 6—8 6—5 6—c 6—c 6—f 2—0 7—7 6—f 7—2 6—c 6—4 0—0</pre>
As you can see, <ins>changing the default parse mode can significantly reduce the amount of dominos required to encode strings</ins>. For numbers it is less impactful but can still be significant if you are working mostly within a specific range.

<span id="Base"></span>
==== BASE - 45 ====
Pops one number from the stack to use as the “base” for future parsing of dominos (opcodes, number literals, string literals)

By default, DominoScript uses double six (D6) dominos to represent everything, so the default base is 7.

The max cell value of half of a domino is always 1 less than the Base. So in base 7, the max value is 6. In base 10, the max value is 9. In base 16, the max value is 15 (aka <code>f</code>).

If the number of dots on a domino half exceeds the max amount of possible dots for the current base, it is clamped!

For example: when you are in Base 7 and the interpreter encounters a <code>f—f</code> domino, it will be parsed as <code>6—6</code>. If you are in base 10, it will be parsed as <code>9—9</code> etc.

In below table you can see how the same domino sequence results in different decimal numbers depending on the base:

{| class="wikitable"
! Domino Sequence
! Base 7 (D6)
! Base 10 (D9)
! Base 16 (D15)
|-
| <code>0—6</code>
| 6
| 6
| 6
|-
| <code>0—9</code>
| 6
| 9
| 9
|-
| <code>0—f</code>
| 6
| 9
| 15
|-
| <code>1—6 6—6</code>
| 342
| 666
| 1638
|-
| <code>1—9 9—9</code>
| 342
| 999
| 2457
|-
| <code>1—f f—f</code>
| 342
| 999
| 4095
|-
| <code>2—6 6—6 6—6</code>
| 16806
| 66666
| 419430
|-
| <code>2—9 9—9 9—9</code>
| 16806
| 99999
| 629145
|-
| <code>2—f f—f f—f</code>
| 16806
| 99999
| 1048575
|}

With a higher Base, you have access to higher opcodes without needing to switch to extended mode.

{| class="wikitable"
! Base
! Opcode Range
|-
| 7
| 0 to 48
|-
| 10
| 0 to 99
|-
| 16
| 0 to 255
|}

While the <ins>opcode-to-instruction</ins> mapping never changes, the <ins>domino-to-opcode</ins> mapping is completely different in each base.

<span id="Ext"></span>
==== EXT - 46 ====
Toggle extended mode on or off. If extended mode is active the interpreter will use 2 dominos instead of 1 for each instruction which extends the opcode range from 0-48 to 0-2400 when using Double six dominos.

<span id="Time"></span>
==== TIME - 47 ====
Pushes the milliseconds since program start to the stack.

Useful for things like a gameloop, animations, cooldowns etc.

<span id="Noop"></span>
==== NOOP - 48 ====
No operation. The IP will move to the next domino without doing anything.

Useful to move the IP to a specific address (e.g. start of loop body) or to “reserve” space in case you think that you might need to add more instructions later on and don’t want to move dominos around.

<br>

== Navigation Modes ==

If you don't know what navigation modes are and how they influence the Instruction Pointer, I'd recommend reading the relevant section in [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]].

''(F=Forward, L=Left, R=Right)''

There are <code>49</code> total navigation modes in DominoScript. This section should reference them all.

''To be fully spec compliant an implementation should support all of them. However, when developing an interpreter, this has a rather low priority. With just the default nav mode priority (Forward, Left, Right) you can run any DS code as long as it doesn't execute the NAVM instruction to change it.''

=== Basic Three Way ===
Out of three directions, the IP will prioritize moving to the one with the highest priority.

{| class="wikitable"
! Index
! Priorities
! Domino -&gt;
|-
| 0 (Default)
| <code>Forward</code> <code>Left</code> <code>Right</code>
| <code>0—0</code>
|-
| 1
| <code>Forward</code> <code>Right</code> <code>Left</code>
| <code>0—1</code>
|-
| 2
| <code>Left</code> <code>Forward</code> <code>Right</code>
| <code>0—2</code>
|-
| 3
| <code>Left</code> <code>Right</code> <code>Forward</code>
| <code>0—3</code>
|-
| 4
| <code>Right</code> <code>Forward</code> <code>Left</code>
| <code>0—4</code>
|-
| 5
| <code>Right</code> <code>Left</code> <code>Forward</code>
| <code>0—5</code>
|-
| 6
| <code>RANDOM</code>
| <code>0—6</code>
|}

=== Basic Two Way ===

Out of two directions, the IP will prioritize moving to the one with the highest priority.

{| class="wikitable"
! Index
! Priorities
! Domino -&gt;
|-
| 7
| <code>Forward</code> <code>Left</code>
| <code>1—0</code>
|-
| 8
| <code>Forward</code> <code>Right</code>
| <code>1—1</code>
|-
| 9
| <code>Left</code> <code>Forward</code>
| <code>1—2</code>
|-
| 10
| <code>Left</code> <code>Right</code>
| <code>1—3</code>
|-
| 11
| <code>Right</code> <code>Forward</code>
| <code>1—4</code>
|-
| 12
| <code>Right</code> <code>Left</code>
| <code>1—5</code>
|-
| 13
| <code>RANDOM</code>
| <code>1—6</code>
|}

=== Basic One Way ===
IP can only move in one direction.

{| class="wikitable"
! Index
! Only Direction
! Domino -&gt;
|-
| 14
| <code>Forward</code>
| <code>2—0</code>
|-
| 15
| <code>Forward</code>
| <code>2—1</code>
|-
| 16
| <code>Left</code>
| <code>2—2</code>
|-
| 17
| <code>Left</code>
| <code>2—3</code>
|-
| 18
| <code>Right</code>
| <code>2—4</code>
|-
| 19
| <code>Right</code>
| <code>2—5</code>
|-
| 20
| <code>RANDOM</code>
| <code>2—6</code>
|}

=== Cycle Three Way ===
The direction with the highest priority becomes the least prioritized in the next cycle.

All 3 directions are available in all cycles.

{| class="wikitable"
! Index
! Cycle 1
! Cycle 2
! Cycle 3
! Domino -&gt;
|-
| 21
| <code>F</code> <code>L</code> <code>R</code>
| <code>L</code> <code>R</code> <code>F</code>
| <code>R</code> <code>F</code> <code>L</code>
| <code>3—0</code>
|-
| 22
| <code>F</code> <code>R</code> <code>L</code>
| <code>R</code> <code>F</code> <code>F</code>
| <code>L</code> <code>F</code> <code>R</code>
| <code>3—1</code>
|-
| 23
| <code>L</code> <code>F</code> <code>R</code>
| <code>F</code> <code>R</code> <code>F</code>
| <code>R</code> <code>L</code> <code>F</code>
| <code>3—2</code>
|-
| 24
| <code>L</code> <code>R</code> <code>F</code>
| <code>R</code> <code>F</code> <code>L</code>
| <code>F</code> <code>L</code> <code>R</code>
| <code>3—3</code>
|-
| 25
| <code>R</code> <code>F</code> <code>L</code>
| <code>F</code> <code>L</code> <code>R</code>
| <code>L</code> <code>R</code> <code>F</code>
| <code>3—4</code>
|-
| 26
| <code>R</code> <code>L</code> <code>F</code>
| <code>L</code> <code>F</code> <code>R</code>
| <code>F</code> <code>R</code> <code>L</code>
| <code>3—5</code>
|-
| 27
| (unmapped)
| (unmapped)
| (unmapped)
| <code>3—6</code>
|}

=== Cycle Two Way ===
The direction with the highest priority becomes the least prioritized in the next cycle.

Only 2 directions are available in a single cycle.

{| class="wikitable"
! Index
! Cycle 1
! Cycle 2
! Cycle 3
! Domino -&gt;
|-
| 28
| <code>F</code> <code>L</code>
| <code>L</code> <code>R</code>
| <code>R</code> <code>F</code>
| <code>4—0</code>
|-
| 29
| <code>F</code> <code>R</code>
| <code>R</code> <code>F</code>
| <code>L</code> <code>F</code>
| <code>4—1</code>
|-
| 30
| <code>L</code> <code>F</code>
| <code>F</code> <code>R</code>
| <code>R</code> <code>L</code>
| <code>4—2</code>
|-
| 31
| <code>L</code> <code>R</code>
| <code>R</code> <code>F</code>
| <code>F</code> <code>L</code>
| <code>4—3</code>
|-
| 32
| <code>R</code> <code>F</code>
| <code>F</code> <code>L</code>
| <code>L</code> <code>R</code>
| <code>4—4</code>
|-
| 33
| <code>R</code> <code>L</code>
| <code>L</code> <code>F</code>
| <code>F</code> <code>R</code>
| <code>4—5</code>
|-
| 34
| (unmapped)
| (unmapped)
| (unmapped)
| <code>4—6</code>
|}

=== Cycle One Way ===
The direction with the highest priority becomes the least prioritized in the next cycle.

Only 1 direction is available in a single cycle.

{| class="wikitable"
! Index
! Cycle 1
! Cycle 2
! Cycle 3
! Domino -&gt;
|-
| 35
| <code>F</code>
| <code>L</code>
| <code>R</code>
| <code>5—0</code>
|-
| 36
| <code>F</code>
| <code>R</code>
| <code>L</code>
| <code>5—1</code>
|-
| 37
| <code>L</code>
| <code>F</code>
| <code>R</code>
| <code>5—2</code>
|-
| 38
| <code>L</code>
| <code>R</code>
| <code>F</code>
| <code>5—3</code>
|-
| 39
| <code>R</code>
| <code>F</code>
| <code>L</code>
| <code>5—4</code>
|-
| 40
| <code>R</code>
| <code>L</code>
| <code>F</code>
| <code>5—5</code>
|-
| 41
| (unmapped)
| (unmapped)
| (unmapped)
| <code>5—6</code>
|}

=== Flip Flop ===
The priority flip flops between 2 primary directions.

{| class="wikitable"
! Index
! Flip
! Flop
! Domino -&gt;
|-
| 42
| <code>F</code>
| <code>L</code>
| <code>6—0</code>
|-
| 43
| <code>F</code>
| <code>R</code>
| <code>6—1</code>
|-
| 44
| <code>L</code>
| <code>F</code>
| <code>6—2</code>
|-
| 45
| <code>L</code>
| <code>R</code>
| <code>6—3</code>
|-
| 46
| <code>R</code>
| <code>F</code>
| <code>6—4</code>
|-
| 47
| <code>R</code>
| <code>L</code>
| <code>6—5</code>
|-
| 48
| (unmapped)
| (unmapped)
| <code>6—6</code>
|}

<br>
== Example: Factorial ==

<br>[[File:DominoScript-Example-Factorial-flow.png|thumb|Factorial Example with IP flow visualized]]

'''Pseudocode:'''
<pre style="overflow:auto;>
NUM 12
NUM 42 CALL
NUMOUT // prints 479001600

FUNCTION FACTORIAL: // (address 42)
DUP NUM 0 EQ
IF:
POP
NUM 1
ELSE:
DUP NUM 1 SUB
NUM 42 CALL // recursive call
MUL
</pre>

'''DominoScript:'''
<pre style="letter-spacing:4px;line-height:1.1;overflow:auto;">
0—1 . . . . . 1—0 1—0 0 . . . 2—1 4—4 0
| |
0—1 . . . . . . . . . 0 . . . . . . . 6
1 . 0—3 0—1 0—0 2—3 4—1 . . . . . . . 0
| |
5 . . . . . . . . . . 0 . . . . . . . 1
|
0—1 1—0 6—0 4—4 5—1 . 3 0—1 0—1 1—1 0—1
</pre>

== Example: WASD Controls ==

Demonstrates `WASD` keyboard inputs that move a character around on a 5x7 grid and renders it via stdout.

It could be used as a basis to build a simple game.

[[File:DominoScript-Example-WASD-Input-Example-Flow.png|thumb|WASD Controls example with IP flow visualized]]

'''Pseudocode''':
<pre style="overflow:auto;font-size:0.85em;>
NUM 16 BASE // tell interpreter to use dominos with up to 16 dots per side. Allowing you to use less dominos

// Binding addresses to labels
NUM 116 LABEL // playerX -1
NUM 122 LABEL // playerY -2
NUM 1008 LABEL // topRow = "╭──────────────╮\n" -3
NUM 1080 LABEL // middleRow = "│ │\n" -4
NUM 1152 LABEL // bottomRow = "╰──────────────╯\n" -5
NUM 72 LABEL // function main() -6
NUM 361 LABEL // function update() -7
NUM 505 LABEL // function render() -8
NUM 660 LABEL // loop body start within render() -9

NUM 6 NEG CALL // main()

FUNCTION main:
NUM 1 LIT // tell interpreter that we use exactly 1 domino for each number or character in a string
LOOP_FOREVER:
NUM 50 WAIT // wait 50ms
PUSH 7 NEG CALL // update()
PUSH 8 NEG CALL // render()
NUM 6 NEG JUMP // jump back to start of main

FUNCTION update:
STR "w" KEY IF:
NUM 1 NUM 2 NEG GET NUM 1 SUB NUM 1 NUM 2 NEG SET // y = y - 1
STR "a" KEY IF:
NUM 1 NUM 1 NEG GET NUM 2 SUB NUM 1 NUM 1 NEG SET // x = x - 2
STR "s" KEY IF:
NUM 1 NUM 2 NEG GET NUM 1 ADD NUM 1 NUM 2 NEG SET // y = y + 1
STR "d" KEY IF:
NUM 1 NUM 1 NEG GET NUM 2 ADD NUM 1 NUM 1 NEG SET // x = x + 2

NUM 1 NUM 1 NEG GET NUM 2 NUM 13 CLAMP NUM 1 NUM 1 NEG SET // x = clamp(x, 2, 13)
NUM 1 NUM 2 NEG GET NUM 2 NUM 6 CLAMP NUM 1 NUM 2 NEG SET // y = clamp(y, 2, 6)
KEYRES

FUNCTION render:
STR '\033[2J\033[H' STDOUT // clear screen and move cursor to top left
NUM 0 // iterator = 0;

LOOP:
DUPE NUM 0 EQL IF: // if (iterator === 0)
NUM 3 NUM 3 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Top row string if on row 0
DUPE NUM 8 EQL IF: // if (iterator === 8)
NUM 3 NUM 5 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Bottom row string if on row 8
DUPE DUPE NUM 2 GTR NUM 1 ROLL NUM 7 GTR NOT AND IF: // if (iterator > 2 && iterator < 7)
NUM 3 NUM 4 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Middle row string if on row 1-7

NUM 1 ADD // iterator = iterator + 1

DUPE NUM 8 EQL IF:
// Hacky way to achieve the equivalent of: stdout.write(`\033[${playerY};${playerX}H[]`)
// The string is constructed 1 char at a time in reverse order using NUM
NUM 0 NUM 93 NUM 91 NUM 72 NUM 1 NUM 1 NEG GET NUM 31 NUM 59 NUM 1 NUM 2 NEG GET NUM 31 NUM 91 NUM 27 STROUT
POP // remove iterator from stack
BREAK // exit loop if we've reached the bottom row

NUM 9 NEG JUMP // jump back to start of loop
</pre>

'''DominoScript''':
<pre style="letter-spacing:2px;line-height:1.1;overflow:auto;font-size:0.85em;">
0—1 1—0 2—2 6—3 0—1 1—0 7—4 1—e 0—1 1—0 7—a 1—e 0—1 1—3 f—0 1—e 0—1 1—4 3—8 1—e 0—1 1—4 8—0 1—e 0—1 1—0 4—8 1—e 0—1 1—1 6—9 1—e 0—1 1—2 8—8 1—e
0—1 0—1 2—c 0—1 3—2 2—2 0—1 0—7 0—c 2—0 0—1 0—8 0—c 2—0 0—1 0—6 0—c 1—f . . . . . . 0—0 0—8 . . 0—0 0—4 . . . . 0—2 c—0 6—0 1—0 e—1 4—9 2—1 1—0
0—8 0—1 0—1 0—1 0—2 0—c 2—b 3—0 3 . 0—8 0—1 0—1 0—1 0—1 0—c 2—b 3—0 3 . 0—7 0—1 0—1 0—1 0—2 0—c 2—b 3—0 3 . 0—7 0—1 0—1 0—1 0—1 0—c 2—b 3—0 3 .
| | | |
1 . . . . . . . . . . . . . . . 0 . 2 . . . . . . . . . . . . . . . 0 . 1 . . . . . . . . . . . . . . . 0 . 2 . . . . . . . . . . . . . . . 0 .
| | | |
0 1—0 a—2 c—0 2—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 1—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 2—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 1—0 1—0 1—0 1—0 d 3 .
| | | | | | | |
. 3—0 3—0 3—0 0—2 7—7 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 6—1 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 7—3 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 6—4 0—0 2—7 1 0 3
|
2 0—3 0—3 b—2 c—0 2—0 1—0 1—0 . . 6—0 1—0 2—0 1—0 a—2 c—0 2—0 1—0 . . 0—3 0—3 0—3 b—2 c—0 1—0 1—0 1—0 . . e—0 1—0 2—0 1—0 a—2 c—0 1—0 1—0 . . 0
|
8 . 5—b 3 . 5—b 4 . 0—1 0 . 1—0 d—0 . . 0—1 0—3 0—3 0—c 0—1 0 . 1—0 1—0 0—1 0 . . . 3—0 3—0 1 . . . 1—0 d—0 2—a 0 . 0—2 0 . 1—b 2 . . . 1—0 1—0
| | | | | | | | |
. . b . 2 . b . 8 . 6 . 0 . . 0—0 1—1 1—d 0 c—2 1—0 0—0 1—0 2 2 . 2—a 2—6 . 0 0 . 1—1 . . 0 d 0—1 . . . . . c . 1 . 1 . c . 1 . 6 . . . . . . .
| | | | | | | | | |
0—2 1 . 4—a 1 . 0—0 2 . 0—3 0—1 . . . 3—0 3 . . . . 0—1 0 6 . c 2—c . . . . . 1 . 9 . . 0 1 . . 0 . 0—1 4 . 0 . 1 . 0 . 2 . 0 . 0 . . . . . . .
| | | | | | | | |
. . . . . . . . . . . . . 1 1—1 8—0 1—0 0—3 . . . 0—3 . 4 2 a—2 2 . . 3 0—3 c—2 . 0 . 0 9 . . . 0 . b . 8 . 1 . f . 1 . a . b . 0 . . . . . . .
| | | | | | | |
. 0—3 0—3 0—3 0—3 0—3 0—3 d 0—1 0—3 0—1 0—5 3—0 . 1 . . 0—c 0—1 0 . . 0 . . 0—3 0—1 . c . . . . 0 . 5 . 0 . 0 . 0 . 0 . 0 . 5 . . . . . . . . .
| | | | |
3—0 c—2 1—0 0—0 1—0 6—2 a—2 c—2 2—0 1—0 c—0 0—3 . 0 d 3—0 3—0 3—0 3—0 0—1 . 7 . . . f—1 . . . . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . . . . . . . . .
| | | | | |
0—3 0—1 0—2 1—2 0—1 0—1 0—4 0—1 0—7 1—2 0—e 0—f 3—0 1 . . . . . . . . . 0—1 0 . . . . . . . . . 5—d 0 . 0—1 0 . 3—b 0 . 1—f 0 . . . . . . . . .
2—5 6—d 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 6—e 0—0 0—a 0—0 0—0
2—5 0—2 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 2—5 0—2 0—0 0—a 0—0 0—0
2—5 7—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 6—f 0—0 0—a 0—0 0—0
</pre>

==External resources==
* [https://dominoscript.com Website with code playground]
* [https://github.com/andreas-schoch/dominoscript GitHub Repository containing reference implementations, examples and documentations]


[[Category:Languages]]
[[Category:Stack-based]]
[[Category:Implemented]]
[[Category:Self-modifying]]
[[Category:Turing complete]]
[[Category:Low-level]]
[[Category:Thematic]]
[[Category:2024]]

Action parameters

VariableValue
Edit count of the user (user_editcount)
7
Name of the user account (user_name)
'Galvandi'
Age of the user account (user_age)
14777262
Groups (including implicit) the user is in (user_groups)
[ 0 => '*', 1 => 'user', 2 => 'autoconfirmed' ]
Page ID (page_id)
0
Page namespace (page_namespace)
0
Page title (without namespace) (page_title)
'DominoScript'
Full page title (page_prefixedtitle)
'DominoScript'
Action (action)
'edit'
Edit summary/reason (summary)
'initial dominoscript documentation'
Old content model (old_content_model)
''
New content model (new_content_model)
'wikitext'
Old page wikitext, before the edit (old_wikitext)
''
New page wikitext, after the edit (new_wikitext)
'{{infobox proglang |image=File:Dominoscript-logo.png |name=DominoScript |author=[[User:Galvandi]] |year=[[:Category:2024|2024]] |paradigms=imperative |memsys=[[:Category:Stack-based|Stack-based]] |dimensions=[[:Category:Two-dimensional languages|two-dimensional]] |class=[[:Category:Turing complete|Turing complete]] |majorimpl=[https://github.com/andreas-schoch/dominoscript Github Repo] |files=<code>.ds</code> recommended }}'''DominoScript''' is a two-dimensional self-modifying [[esoteric programming language]] that uses the dots on domino pieces to represent code. == Core Concepts == '''<code>Domino Pieces</code>''': * A domino piece can be placed either horizontally or vertically. * DominoScript by default uses Double-Six (aka <code>D6</code>) dominos to represent code. Double-six here means that each domino has 2 sides with up to 6 dots each. Essentially Base7. * Using the [[#Base|BASE]] instruction, you can tell the interpreter to parse dominos with up to 16 dots on each side. Allowing you to represent larger numbers with fewer dominos. '''<code>Stack-Oriented</code>''': * There is a global data stack that all instructions operate on. * By default, the stack size is limited to 512 items (Up to the implementation to make this configurable. The default of the reference interpreter might become significantly larger with a future version). * At its core, DS is just another concatenative [[Postfix notation|reverse-polish]] language. The following code: <code style="border-color:gray;">0—1 0—5 0—1 0—6 1—0 0—3 1—2 5—1</code> is the same as <code style="border-color:gray;">5 6 + dup * .</code> in [[Forth]]. * Internally every item on the stack is a signed 32-bit integer. * Strings are just null-terminated sequences of integers representing Unicode char codes. * Floats are not supported ''(Fixed-point-arithmetic might be supported in future versions)''. * No other data structures exist. '''<code>Two-Dimensional</code>''': * The code is represented on a rectangle grid of cells. The top-left cell is address 0. The bottom-right cell is address <code>cols * rows - 1</code>. * Any implementation needs to support a grid of at least 65408 total cells to be spec compliant. That allows a square grid of up to `256x256` cols and rows or any smaller rectangular grid within the cell limit. Each cell needs to be indexable using an <code>int32</code> popped from the data stack, so well optimized implementations may support crazy amounts of cells. * The Instruction Pointer (IP) can move in any cardinal direction. Direction changes are performed by placing dominos in a certain way (IP always moves from one half to the other half of the same domino) as well as the current Navigation Mode. See: [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]]. '''<code>Self-Modifying</code>''': * The code can override itself somewhat similar to befunge. See [[#Get|GET]] and [[#Set|SET]] instructions. * Getting and setting can be done using different encodings: ** '''domino''': get or set single domino ** '''unsigned number''': get or set a number within the int32 range ''(why not uint32? Because the stack only supports int32 so there is no point)''. Up to 7 dominos can be parsed per get/set. ** '''signed number''': get or set a number within the int32 range. Up to 7 dominos can be parsed per get/set. The only different to unsigned number encoding is that here the first half of the first domino is sacrificed to encode the "sign bit" (if first half is anything but 0, sign bit is on). ** '''string''': Get or set a whole string. * Can be used as a secondary data store ''(to act somewhat similar to registers or variables)'' besides the stack. '''<code>Multiple Files</code>''': * You can split up DS code into multiple files and include them in the main file using the [[#Import|IMPORT]] instruction. * Each import has its own grid of cells. * The data stack is shared between the main and all imported files. * Defining a label within an imported file during the import phase, allows the parent to call functions within the child. Giving the parent essentially an interface to use the imported file as a library. ''(See the [[#Label|LABEL]] instruction for more info)''. == Text Format == The dots on dominos are represented using a text based format: * The digits <code>0</code> to <code>f</code> represent the dots on half of a domino. To indicate an empty cell, use a dot <code>.</code> * The “long hyphen” character <code>—</code> indicates a horizontal domino ''(regular hyphen <code>-</code> also accepted to make it easier to type)''. It can only appear on '''even''' columns and '''odd''' rows. * The “pipe” character <code>|</code> indicates a vertical domino. It can only appear on '''odd''' columns and '''even''' rows. * Any other line <ins>before</ins> and <ins>after</ins> the actual code is ignored. ''(Tip: Make use of this to add extensive comments. You will inevitable forget what your dominoscript code does, so consider including a 1:1 pseudocode implementation of the dominoscript code)'' The following DominoScript code ''(which prints "Hello world")'': <pre style="letter-spacing:4px;line-height:1.1;display:inline-block;border-color: black;"> . . . . . . . . . . . . . . . . . . . . . . . 0—2 1 . 0—3 . | . 1 0—3 2—1 4—4 . . 2 . 2 1 . | | | . 2 . . . . . 0 . . 0—6 1 2 . | . 1—6 1—2 2 . 1 6—1 . . . 1 . | | . . . . . 2 . . . 2 . . . 3 . | . 1 3—1 2—1 . . . 1 3—1 2—1 . | . 2 0—2 0 . . . . . . . . . . | . . . . 0 5—3 . . . . . . . . </pre> Is the equivalent of the following dominos: <br>[[File:DominoScript-Example-003-flow.png|400px|Hello world 2d]] The grid doesn’t have to be a square but it must have a consistent number of columns and rows, otherwise an <code>InvalidGridError</code> will be thrown before execution starts: <table class="wikitable"> <tr><th>GOOD ✅</th><th>BAD ❌</th></tr> <tr><td> <pre>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .</pre> </td> <td> <pre> . . . . . . . . . . . . . . . . . . . . . . . . . . .</pre> </td> </tr> </table> Connecting to a domino half which is already connected results in <code>MultiConnectionError</code>: <table class="wikitable"> <tr><th>GOOD ✅</th><th>BAD ❌</th></tr> <tr><td> <pre>6—6 6—6 . 6 6—6 . . | 6 . . . .</pre> </td> <td> <pre>6—6—6—6 . 6—6 . . . | 6 . . . .</pre> </td> </tr> </table> Having a domino half that is not connected to anything results in <code>MissingConnectionError</code>: <table class="wikitable"> <tr><th>GOOD ✅</th><th>BAD ❌</th></tr> <tr><td> <pre>. . 6—6 . . 6 . . . | . 6 . . .</pre> </td> <td> <pre>. . 6 6 . . 6 . . . . 6 . . .</pre> </td> </tr> </table> Having a connection where 1 or both ends are empty results in a <code>ConnectionToEmptyCellError</code>: <table class="wikitable"> <tr><th>GOOD ✅</th><th>BAD ❌</th></tr> <tr><td> <pre>6—6 . 6—6 6 . . . 6 | | 6 . . . 6</pre> </td> <td> <pre>6—. . .—6 6 . . . . | | . . . . 6</pre> </td> </tr> </table> == How Dominos are parsed into Numbers == It is important to understand that '''internally''' everything in DominoScript is represented as signed 32-bit Integers and '''externally''' everything is represented by the dots on the domino pieces. '''Every domino is part of either''': * An opcode - decides which instruction to execute next. By default, one domino represents one opcode unless you tell the interpreter to use 2 dominos per opcode using the [[#Ext|EXT]] instruction. * A number literal - the [[#Num|NUM]] instruction is used to push a single Integer onto the stack. * A string literal - the [[#Str|STR]] instruction is used to push a sequence of Integers onto the stack which represent unicode char codes. '''Furthermore, you should also be aware of the following things''': * The number base system that is currently set influences how dots are parsed into numbers. The base can be changed using the [[#Base|BASE]] instruction. (Default: Base 7 - because double-six dominos are the most common). * The "LiteralParseMode" tells the interpreter how many dominos will be part of a literal. It can be changed using the [[#Lit|LIT]] instruction (Default: dynamic - first half of first domino decides how many more are part of a number literal). * Once a literal is pushed on the stack, it is your job as the developer to keep track of which items are numbers and which ones are characters of a string. You can use any instruction on characters of a “string” but only the following ones will treat them as such: [[#Str|STR]], [[#Eqlstr|EQLSTR]], [[#Strin|STRIN]], [[#Strout|STROUT]] as well as [[#Get|GET]] and [[#Set|SET]] when used with the "string" encoding type. In examples, you might see stack items that are meant to be char codes, represented in the following way:” <pre>[..., 1, 2, 3 'NUL', 's', 'e', 'y']</pre> But in reality, the stack will store them as integers and look like this: <pre>[..., 1, 2, 3, 0, 115, 101, 121]</pre> '''What about floats?''' Floats don’t exist in DominoScript. I’d suggest scaling up numbers by a factor of 10, 100, 1000 or whatever precision you need. ''(I know that pico-8 uses 32-bits for numbers but treats them as 16.16 fixed point numbers. I am not quite sure if that is just a convention or if pico8’s API actually treats them as fixed-point numbers. I would like to eventually add some trigonometry instructions to DominoScript but am unsure what the most practical way would be)'' == How the Instruction Pointer Moves == The Instruction Pointer (<code>IP</code>) keeps track of the current cell address that will be used for the next instruction. Since DominoScript is 2D, it isn’t obvious where the IP will move to without understanding the fundamental rules and the Navigation Modes. '''Before the program starts:''' # The interpreter will scan the grid from '''top-left to top-right''', move down and repeat until it finds the first domino. # Upon reaching the first domino, the IP is placed at the address of the first found domino half. # If no domino could be found, the program is considered finished. '''During the program execution:'''<br> The IP will adhere to the following rules: * The IP can move in cardinal directions, never diagonally. How dominos are parsed, is all relative to that. For example, the horizontal domino <code>3—5</code> can be interpreted as the base7 number <code>35</code> (IP moves eastwards) or <code>53</code> (IP moves westwards). Same thing for vertical dominos. * The IP will always move from one half (entry) of the same domino to the other half (exit) of the same domino. * If the IP cannot move to a new domino, the program is considered finished. * At the exit half of a domino, the IP will never move back to the entry half. It will always try to move to a new domino. That means, there are at most 0 to 3 potential options for the IP to move. * When the IP needs to move to a new domino, it is possible that there are no valid moves despite there being dominos around. The [[#Navigation_Modes|Navigation Mode]] decides where the IP can and cannot move next. '''Understanding Navigation Modes:'''<br> Navigation Modes are predefined priority patterns which are used when the Instruction Pointer needs to decide to which domino to move to next. The [[#Navm|NAVM]] instruction can be used to change the current Navigation Mode. Understanding the following concepts will become very important: * '''Priority Directions''': Primary, Secondary, Tertiary * '''Relative Directions''': Forward, Left, Right * '''Cardinal Directions''': North, East, South, West The Cardinal directions don’t matter much. It is all about the '''direction in relation to the exit half''' of the current domino ''(If you ever did any kind of GameDev you probably know the difference between world space and local space. It’s kind of like that)'' When the IP moves to a new domino, the half it enters to is called the “'''entry'''” while the other half is called the “'''exit'''”. Now from the perspective of the exit half, the IP can potentially move in 3 directions: Forward, Left, Right. These are the '''Relative Directions'''. Which relative direction the IP chooses, depends on the current Navigation Mode. Below you will see the mapping of the very basic nav modes: {| class="wikitable" |- ! Index !! <code>Primary</code> !! <code>Secondary</code> !! <code>Tertiary</code> |- | 0 || Forward || Left || Right |- | 1 || Forward || Right || Left |- | 2 || Left || Forward || Right |- | 3 || Left || Right || Forward |- | 4 || Right || Forward || Left |- | 5 || Right || Left || Forward |- | ... || ... || ... || ... |} ''The “index” here is the argument for the <code>NAVM</code>instruction.'' <br> '''If we imagine the <code>6</code> to be the exit half, what will be the next domino the IP moves to?:''' <table class="wikitable" style="line-height:1.1;letter-spacing:4px;"> <tr> <th>East</th> <th>West</th> <th>South</th> <th>North</th> </tr> <tr> <td> <pre> . 2 . . . | . 2 . . . 5—6 1—1 . . 3 . . . | . 3 . . . </pre> </td> <td> <pre> . . . 3 . | . . . 3 . . 1—1 6—5 . . . 2 . | . . . 2 . </pre> </td> <td> <pre> . . 5 . . | 3—3 6 2—2 . . 1 . . | . . 1 . . . . . . . </pre> </td> <td> <pre> . . . . . . . 1 . . | . . 1 . . 2—2 6 3—3 | . . 5 . . </pre> </td> </tr> </table> ''All 4 snippets are exactly the same code with the difference that they are all flipped differently. This is what I mean by the cardinal direction not mattering much in DominoScript.'' * When <code>index 0</code>, the IP will move to <code>1—1</code> (Primary, Forward) * When <code>index 1</code>, the IP will move to <code>1—1</code> (Primary, Forward) * When <code>index 2</code>, the IP will move to <code>2—2</code> (Primary, Left) * When <code>index 3</code>, the IP will move to <code>2—2</code> (Primary, Left) * When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right) * When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right) <br> '''What if we remove the <code>1—1</code> domino? Where will the IP go to then?:''' <table class="wikitable" style="line-height:1.1;letter-spacing:4px;"> <tr> <th>East</th> <th>West</th> <th>South</th> <th>North</th> </tr> <tr> <td> <pre>. 2 . . . | . 2 . . . 5—6 . . . . 3 . . . | . 3 . . .</pre> </td> <td> <pre>. . . 3 . | . . . 3 . . . . 6—5 . . . 2 . | . . . 2 .</pre> </td> <td> <pre>. . 5 . . | 3—3 6 2—2 . . . . . . . . . . . . . . .</pre> </td> <td> <pre>. . . . . . . . . . . . . . . 2—2 6 3—3 | . . 5 . .</pre> </td> </tr> </table> * When <code>index 0</code>, the IP will move to <code>2—2</code> (Secondary, Left) * When <code>index 1</code>, the IP will move to <code>3—3</code> (Secondary, Right) * When <code>index 2</code>, the IP will move to <code>2—2</code> (Primary, Left) * When <code>index 3</code>, the IP will move to <code>2—2</code> (Primary, Left) * When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right) * When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right) <br> '''And what if we remove both the <code>1—1</code> and the <code>2—2</code> domino?:''' <table class="wikitable" style="line-height:1.1;letter-spacing:4px;"> <tr> <th>East</th> <th>West</th> <th>South</th> <th>North</th> </tr> <tr> <td> <pre>. . . . . . . . . . 5—6 . . . . 3 . . . | . 3 . . .</pre> </td> <td> <pre>. . . 3 . | . . . 3 . . . . 6—5 . . . . . . . . . .</pre> </td> <td> <pre>. . 5 . . | 3—3 6 . . . . . . . . . . . . . . . . .</pre> </td> <td> <pre>. . . . . . . . . . . . . . . . . 6 3—3 | . . 5 . .</pre> </td> </tr> </table> * When <code>index 0</code>, the IP will move to <code>3—3</code> (Tertiary, Right) * When <code>index 1</code>, the IP will move to <code>3—3</code> (Secondary, Right) * When <code>index 2</code>, the IP will move to <code>3—3</code> (Tertiary, Right) * When <code>index 3</code>, the IP will move to <code>3—3</code> (Secondary, Right) * When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right) * When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right) <br> These are only variations of the “Basic-Three-Way” kind of NavModes. See the [[#Navigation_Modes|Reference]] for a full list of available modes. == Instructions == Instructions are mapped to opcodes behind the scenes: * '''0-48''': Are the “core” instructions ''(2 have yet to be mapped)'' and are meant to fit within the value range a single “double-six” domino can represent. * '''49-99''': Reserved for future extensions of the language ''(e.g. fixed-point-arithmetic, helpers for more advanced string manipulation and such)'' * '''100+''': Allow you as developer to extend the language yourself with non-standard behaviour. These opcodes are essentially alternative ways of calling by label. To learn more, see: [[#Call|CALL]], [[#Label|LABEL]] and [[#Import|IMPORT]] instructions. To know which domino represents which opcode, you have to know the currently active [[#Base|base]]. For example, to represent opcode 48...: * in '''base7''' you use a '''<code>6—6</code>''' domino (default) * in '''base10''' you use a '''<code>4—8</code>''' domino * in '''base16''' you use a '''<code>3—0</code>''' domino <br> The core instructions are grouped in 7 categories of 7 instructions each. Below, you will see them listed all. ''(The numbers on the right beside the instruction titles are the corresponding opcode)'' <br> === Stack Management === <span id="Pop"></span> ==== POP - 0 ==== Discards the top of the stack. <span id="Num"></span> ==== NUM - 1 ==== Switch to “number mode”. By default, the first half of the next domino will indicate how many dominos to read as a number. Then the other halfs will all be read as base7 digits (in D6 mode) to form the number that will be pushed to the stack. With 7 dominos, 13 out of 14 halfs are used for the number. You can theoretically represent a number much larger than the max int32 value. However, if the number exceeds the maximum int32 value, it will wrap around from the minimum value, and vice versa ''(exactly the same as when doing bitwise operations in JS –&gt; <code>(96889010406 | 0) === -1895237402</code>)''. You might think that since internally numbers are int32s, that we parse from base7 to two’s complement. That is not the case. We simple push the decimal version of the positive base7 number to the stack '''For example:''' * <code>0—0</code> represents the number <code>0</code> in both decimal and base7 * <code>0—6</code> represents the number <code>6</code> in both decimal and base7 * <code>1—6 6—6</code> represents the number <code>342</code> in decimal and <code>666</code> in base7 * <code>2—6 6—6 6—6</code> represents the number <code>16,806</code> in decimal and <code>6,666</code> in base7 * <code>6—6 6—6 6—6 6—6 6—6 6—6</code> represents the number <code>1,977,326,742</code> in decimal and <code>66,666,666,666</code> in base7 (about 92.1% of the max int32 value) * <code>6—0 1—0 4—1 3—4 2—1 1—1 6—1</code> represents the number <code>2,147,483,647</code> in decimal and <code>104,134,211,161</code> in base7 (exactly the max int32 value) * <code>6—6 6—6 6—6 6—6 6—6 6—6 6—6</code> represents the number -1,895,237,402. '''WHY?''': The actual decimal number the dominos represent is <code>96,889,010,406</code> which is ~45x larger than the max int32 value. It wraps around about that many times before it reaches the final value. '''What if numbers are read from the other directions?''' * <code>1—1 1—1</code>, <code>2—2 2—2 2—2</code> for example will be exactly the same numbers (216 in decimal) eastwards and westwards. * <code>1—2 3—1</code> when parsed backwards is <code>1—3 2—1</code> and can therefore represent different numbers if the IP moves to the east or to the west. * <code>1—6 6—6</code> represents 666 in base7 (342 in decimal) but when parsed backwards the interpreter will raise an <code>UnexpectedEndOfNumberError</code>. Remember that the first half of the first domino indicates how many more will follow. In this case it expects to read 6 more dominos but the number ends prematurely after 1 domino. '''What if I want to use a fixed amount of dominos for each number?''' Use the [[#Lit|LIT]] instruction to permanently change how literals are parsed. For example with parse mode <code>2</code> it will use 2 dominos for each number. While <code>6—6 6—6</code> in default parse mode 0 results in <code>UnexpectedEndOfNumberError</code> (because it expects 6 more dominos to follow but only got 1 more), in parse mode <code>2</code> it represents the decimal number <code>2400</code>. <span id="Str"></span> ==== STR - 2 ==== With <code>STR</code> you switch to “string mode” and can push multiple integers to the stack to represent Unicode characters. The way the dominos are parsed to numbers is identical to <code>NUM</code>: First half of first domino indicates how many more will follow for a single number. The difference is that it doesn’t stop with just one number. It will keep reading numbers until it encounters the NULL character represented by domino <code>0—0</code>. Only once the interpreter does encounter the NULL character, will it push the characters to the stack in <ins>reverse</ins> order. ''(Note: I decided to parse strings like this because I wanted a single int32 based stack and, out of all options I could think of, this one felt the least annoying. If you can think of better ways, I am open for suggestions!)'' This is how you push the string <code>&quot;hi!&quot;</code> to the stack and output it: <pre>0—2 1—2 0—6 1—2 1—0 1—0 4—5 0—0 5—3</pre> It equals the following pseudo code: <code>STR &quot;hi!&quot; STROUT</code> * <code>0—2</code> is the <code>STR</code> instruction * <code>1—2 0—6</code> is the Unicode value 105 representing the character <code>h</code> * <code>1—2 1—0</code> is the Unicode value 105 representing the character <code>i</code> * <code>0—0 4—5</code> is the Unicode value 33 representing the character <code>!</code> * <code>0—0</code> is the Unicode value for the NULL character which terminates the string. * <code>5—3</code> is the [[#Strout|STROUT]] instruction. It will pop items from the stack, parse them as Unicode chars and once it encounters the NULL character, it will output the string to stdout all at once. This is the resulting stack: <table class="wikitable"> <tr> <th> Imaginative </th> <th> Reality </th> </tr> <tr> <td> <pre>[..., 'NUL', '!', 'i', 'h']</pre> </td> <td> <pre>[..., 0, 33, 105, 104]</pre> </td> </tr> </table> Keep in mind that the IP can move in 4 cardinal direction so the following variations would also push the string <code>&quot;hi!&quot;</code> to the stack: IP moves right to left: <pre>3—5 0—0 5—4 0—1 0—1 2—1 6—0 2—1 2—0</pre> IP moves in multiple directions: <pre>0 . . . . 0 4—5 | | 2 . . . . 1 . 0 | 1 . . 2 1—0 . 0 | | 2 0—6 1 . . 3—5</pre> <span id="Dupe"></span> ==== DUPE - 3 ==== Duplicate the top item on the stack. <span id="Roll"></span> ==== ROLL - 4 ==== Pops one argument from the stack to be used as “depth”. * With a negative depth, the item at the <ins>top</ins> is moved to the <ins>nth depth</ins> * With a positive depth, the item at the <ins>nth depth</ins> is moved to the <ins>top</ins> With roll you can implement common stack operations like <code>SWAP</code> and <code>ROT</code>: {| class="wikitable" ! Roll Depth ! Equivalent to ! Stack Before ! Stack After |- | -3 | - | <code>[a, b, c, d]</code> | <code>[d, a, b, c]</code> |- | -2 | ROTR | <code>[a, b, c]</code> | <code>[c, a, b]</code> |- | -1 | SWAP | <code>[a, b]</code> | <code>[b, a]</code> |- | 0 | NOOP | <code>[a]</code> | <code>[a]</code> |- | 1 | SWAP | <code>[a, b]</code> | <code>[b, a]</code> |- | 2 | ROTL | <code>[a, b, c]</code> | <code>[b, c, a]</code> |- | 3 | - | <code>[a, b, c, d]</code> | <code>[b, c, d, a]</code> |} <span id="Len"></span> ==== LEN - 5 ==== Pushes the number of items on the stack. <span id="Clr"></span> ==== CLR - 6 ==== Removes all items from the stack. <br> === Arithmetic === <span id="Add"></span> ==== ADD - 7 ==== Pops 2 numbers from the stack. The sum is pushed to the stack. <span id="Sub"></span> ==== SUB - 8 ==== Pops 2 numbers from the stack. The result of <code>numberA - numberB</code> is pushed to the stack. <span id="Mult"></span> ==== MULT - 9 ==== Pops 2 numbers to multiply. The result is pushed to the stack. <span id="Div"></span> ==== DIV - 10 ==== Pops 2 numbers. The result of the division of numberA by numberB is pushed to the stack. (Keep in mind that DominoScript is integer based and any remainder is discarded.) <span id="Mod"></span> ==== MOD - 11 ==== Pops 2 numbers. The remainder of division of <code>numberA / numberB</code> is pushed to the stack. Note: When numberA is positive modulo behaves identical in most languages (afaik). However, there are some differences across programming languages when numberA is negative. In DominoScript modulo behaves like in JavaScript, Java, C++ and Go and <ins>NOT</ins> like in Python or Ruby! <span id="Neg"></span> ==== NEG - 12 ==== Negate the top of the stack. <span id="Clamp"></span> ==== CLAMP -13 ==== Pops 3 numbers from the stack: <pre>[..., value, min, max]</pre> And pushes back the clamped value onto the stack. <br> === Comparison &amp; Logical === <span id="Not"></span> ==== NOT - 14 ==== Pops the top item off the stack. If it is <code>0</code>, it pushes <code>1</code>. Otherwise it pushes <code>0</code> to the stack. <span id="And"></span> ==== AND - 15 ==== Pops the top 2 items off the stack, performs the logical AND operation and pushes the result back onto the stack. <span id="Or"></span> ==== OR - 16 ==== Pops the top 2 items off the stack, performs the logical OR operation and push the result back onto the stack. <span id="Eql"></span> ==== EQL - 17 ==== Pops the top 2 items off the stack, compares them and pushes the result back onto the stack. If the items are equal, it pushes <code>1</code> to the stack, otherwise <code>0</code>. <span id="Gtr"></span> ==== GTR - 18 ==== Pops the top 2 items off the stack, compares them and pushes the result back onto the stack. If the first item is greater than the second, it pushes <code>1</code> to the stack, otherwise <code>0</code>. <span id="Eqlstr"></span> ==== EQLSTR -19 ==== Assumes that 2 strings are on the stack. It pops them, compares them and pushes <code>1</code> to the stack if equal, otherwise <code>0</code>. '''<ins>For example:<ins>'''<br /> You push the strings <code>&quot;AC&quot;</code> then <code>&quot;DC&quot;</code>. They are represented on the stack as <code>[NULL, C, A, NULL, C, D]</code> (In reality it is <code>[0, 67, 65, 0, 67, 68]</code>). Since the strings are not equal, it will push <code>0</code> to the stack. It is now <code>[0]</code>. '''<ins>Another example:<ins>'''<br /> Imagine you want to check if the user pressed arrow left. You execute the <code>KEY</code> instruction after which the stack looks like <code>[&lt;existing&gt;, 0, 68, 91, 27]</code> then you push the <ins>escape sequence</ins> which represents the left arrow key. The stack is now <code>[&lt;existing&gt;, 0, 68, 91, 27, 0, 68, 91, 27]</code>. You then execute the <code>EQLSTR</code> instruction which will pop the top 2 strings and since the strings are equal, it will push <code>1</code> to the stack. It is now <code>[&lt;existing&gt;, 1]</code> ''(See the [[#Key|KEY]] instruction for more info about escape sequences)''. <span id="Reserved_20"></span> ==== RESERVED - 20 ==== Unmapped opcode. Will throw <code>InvalidInstructionError</code> if executed. <br> === Bitwise === <span id="Bnot"></span> ==== BNOT - 21 ==== Bitwise NOT. Pops the top item off the stack, inverts all bits and pushes the result back onto the stack. <span id="Band"></span> ==== BAND - 22 ==== Bitwise AND. Pops the top 2 items off the stack, performs bitwise AND and pushes the result back onto the stack. <span id="Bor"></span> ==== BOR - 23 ==== Bitwise OR. Pops the top 2 items off the stack, performs bitwise OR and pushes the result back onto the stack. <span id="Bxor"></span> ==== BXOR -24 ==== Bitwise XOR. Pops the top 2 items off the stack, performs bitwise XOR and pushes the result back onto the stack. <span id="Lsl"></span> ==== LSL - 25 ==== Logical Shift Left. Performs the equivalent of <code>argA &lt;&lt; argB</code> and pushes the result back onto the stack. <span id="Lsr"></span> ==== LSR - 26 ==== Logical Shift Right. Performs the equivalent of <code>argA &gt;&gt;&gt; argB</code> and pushes the result back onto the stack. <span id="Asr"></span> ==== ASR - 27 ==== Arithmetic Shift Right. Performs the equivalent of <code>argA &gt;&gt; argB</code> and pushes the result back onto the stack. <br> === Control Flow === <span id="Navm"></span> ==== NAVM - 28 ==== Changes the Navigation Mode. The default Mode is <code>0</code>. See [[#Navigation_Modes|Navigation Modes]] to see all possible nav modes and their indexes. If you don't know what navigation modes are and how they influence the Instruction Pointer, I'd recommend reading the relevant section in [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]]. <span id="Branch"></span> ==== BRANCH - 29 ==== Like an IF-ELSE statement. It pops the top of the stack as a condition and then: <pre style="letter-spacing:4px;line-height:1.1;"> . . . . . 6 . . | . . . . . 6 . . 0—1 0—1 4—1 . . . . . . . 5 . . | . . . . . 5 . . </pre> * If popped value is a non-zero number: The IP will move to the relative '''LEFT''' (the <code>6-6</code>domino) * If popped value is zero: The IP will move to the relative '''RIGHT''' (the <code>5-5</code>domino) When using branch, the current Navigation Mode is ignored. You can always be assured that the IP will either move to the relative left or right. <span id="Label"></span> ==== LABEL - 30 ==== Label are like a bookmarks or an alternative identifier of a specific Cell address. They can be used by the <code>JUMP</code>, <code>CALL</code>, <code>GET</code> and <code>SET</code> instructions (although these also work directly with addresses, so labels are not mandatory) '''Labels are probably not what you expect them to be.''' * They are '''NOT''' strings, but negative numbers. * They are auto generated and self decrementing: <code>-1</code>, <code>-2</code>, <code>-3</code>, etc. * You can kind of imagine them as pointers to a specific cell address. Executing the LABEL instruction pops the address of the cell you want to label and assigns it to the next available negative number. The negative number will '''NOT''' be pushed to the stack. First label will be <code>-1</code>, second label will be <code>-2</code> and so on. You need to keep track of them yourself. For clarity, I’d generally recommend adding comments like the following to your source files: <pre> | Label | Address | Function name | |-------|---------|---------------| | -1 | 340 | main | | -2 | 675 | update | | -3 | 704 | render | </pre> '''About Labels in imported files:''' DominoScript has an <code>IMPORT</code> instruction that allows source files to be imported into others. The imported functions can only be called via labels, so in that regard a label also acts like an export. If the parent file doesn’t define labels of their own, the label values will be the same in both parent and child. However if the parent file creates labels <ins>before</ins> importing a child file, the exported child labels will have a different value in the parent. For example:<br /> # Parent creates label <code>-1</code>, <code>-2</code>, <code>-3</code> and then imports the child file # The child file defines labels <code>-1</code>, <code>-2</code>, <code>-3</code> and gives back control to parent # The parent file will now have the labels <code>-1</code>, <code>-2</code>, <code>-3</code> and the child labels will be <code>-4</code>, <code>-5</code>, <code>-6</code> # Now when the parent wants to call a child function which internally is labelled with <code>-1</code>, it needs to use label <code>-4</code> instead. <span id="Jump"></span> ==== JUMP - 31 ==== Moves the IP to an address on the grid. You can either use a label or an address as an argument. If the IP cannot move anymore, the interpreter will throw a <code>StepToEmptyCellError</code>. If label is unknown it will throw an <code>UnknownLabelError</code>. <span id="Call"></span> ==== CALL - 32 ==== Like the name suggests, it is similar to a function call. When The IP cannot move anymore, it will return to the address from where it was called from. You can do recursive calls. An implementation should support a depth of at least 512 to be spec compliant. '''Alternative way to CALL''' Instead of doing <code>ǸUM 1 NEG CALL</code> to call by label, you can just do <code>OPCODE_100</code>. Why? Because labels are mapped to opcodes 100+. So when you create the labels <code>-1</code>, <code>-2</code>, <code>-3</code>, etc. they are automatically mapped to opcodes <code>100</code>, <code>101</code>, <code>102</code>. <span id="Import"></span> ==== IMPORT - 33 ==== Pop a “string” from the stack to indicate the file name of the source file to import. On import the interpreter will load the file and start running it until its Instruction Pointer cannot move anymore. Labels defined in the imported file are accessible from the file which imports it. That means you can call functions from the imported file via the <code>CALL</code> instruction. If the importing file defined a label before the import, the labels from the imported file will have different identifiers. For example: * <code>FileChild.ds</code> defines a label <code>-1</code>. * <code>FileAParent.ds</code> defines labels <code>-1</code>, <code>-2</code>, then imports FileChilds.ds.s The <ins>internal</ins> label <code>-1</code> in <code>FileChild.ds</code> will be <code>-3</code> <ins>externally</ins> in <code>FileAParent.ds</code> because labels are always auto decrementing. '''Why?''' Because it is the simplest way to avoid conflicts and be able to use labels internally and externally. The data stack is shared between parent and all imported files. Apart from that, the parent and child imports run in their own contexts. Imported files can have imports themselves but you should avoid circular dependencies. If you import the same file into more than one other file, it will result in multiple instances of the imported file. This is probably not a problem as long as you are aware of it ''(It might even be useful if you treat imports of the same file as "objects instances")''. <span id="Wait"></span> ==== WAIT - 34 ==== Pops the top item off the stack and waits for that many milliseconds before continuing. ''Within DominoScript, you could simulate a delay with a ‘busy loop’ by using the TIME, GTR and BRANCH instructions within a loop. Internally an implementation is free to implement WAIT using a busy loop to avoid having to deal with asynchronous code. However, to be spec compliant it should ideally add some form of interrupt handling so the interpreter can be stopped when the user tries to exit (via e.g. Ctrl+C) even if the code is stuck in an infinite loop.'' <br> === Input &amp; Output === <span id="Numin"></span> ==== NUMIN - 35 ==== Prompt the user for a number. The user input will be pushed to the stack. <span id="Numout"></span> ==== NUMOUT - 36 ==== Pop the top item from the stack and output it to stdout. <span id="Strin"></span> ==== STRIN - 37 ==== Prompt the user for a string. The user input will be pushed to the stack as individual Unicode characters in reverse order. So if the user inputs <code>&quot;yes&quot;</code>, the stack will look like this: <pre>[..., 0, 115, 101, 121]</pre> For convenience you might often see the stack represented But remember that in reality it just stores int32s. <pre>[..., NUL 's', 'e', 'y']</pre> ''Note: Since each char is pushed to the stack, the max input string length is limited to the available stack space. By default, the max stack size is 512 for the reference interpreter. This limit will likely be increased to ~64k'' <span id="Strout"></span> ==== STROUT - 38 ==== Pops numbers (representing Unicode char codes) from the stack until it encounters a null terminator (number 0). It will then output the string to stdout. <ins> '''There is one special case:''' </ins> If the parser encounters the <code>Unit Separator</code> (ascii 31), it stringifies the <ins>next</ins> number instead of treating it as a unicode char code. This is very useful to generate ANSI escape sequences like <code>\x1b[15;20H[-]</code> which tells the terminal to draw <code>[-]</code> at row 15 and column 20. Without the <code>Unit Separator</code> you would have to push the char code for 1, 5 and 2, 0 individually. This is a pain if you are dealing with dynamic numbers. The [[./examples/023_input_controls_advanced.md|example_023]] uses this to create an escape sequence. <span id="Key"></span> ==== KEY - 39 ==== Check if the user pressed a specific key since the last reset with <code>KEYRES</code>. If the key was pressed, it pushes <code>1</code> to the stack, otherwise <code>0</code>. It pops a <ins>string sequence</ins> of the stack to represent the key you want to check for. Unlike <code>NUMIN</code> and <code>STRIN</code> it doesn’t block the program, so you can use it in a loop to check for user input. '''<ins>What string sequence?:</ins>''' - If a key is a printable character, the sequence is the Unicode value of the key. For example, to check if the user pressed the <code>a</code> key, you would push the string <code>a</code>. - If a key is a special key like arrow left, right etc, the sequence is an escape sequence. For example, to check if the user pressed the left arrow key, you would push the escape sequence <code>\u001b[D</code> to the stack. '''<ins>What is an escape sequence?:</ins>''' Escape sequences are sequences of characters that are used to represent special non-printable keyboard keys like arrow keys but can also be used to control terminal behavior, such as cursor position, text color and more. You can google them. Then just transform them to the correct domino sequence. <span id="Keyres"></span> ==== KEYRES - 40 ==== Resets the state of all keys to “not pressed”. It is used in combination with <code>KEY</code> to check if a key was pressed since the last reset. It has no effect on the stack. Imagine you have a game running at 20fps. Every 50ms you check if the user pressed any of the arrow keys and act accordingly. Then at the end of the frame you reset the state of all keys to “not pressed” with <code>KEYRES</code>. <span id="Reserved_41"></span> ==== RESERVED - 41 ==== Unmapped opcode. Will throw <code>InvalidInstructionError</code> if executed. ''(Might be used as opcode for a <code>MOUSE</code> instruction which pushes the clickX and clickY position of the mouse since the last KEYRES reset)'' <br> === Misc === <span id="Get"></span> ==== GET - 42 ==== Reads data from the board and pushes it to the stack. Takes 2 arguments from the stack: * The type Index to parse it as. It indicates the type and the direction of the data. * The address of the first domino half '''There are essentially 4 types you can parse it as''': * '''Domino''': The value of the cell at the address and its connection. Essentially a single domino * '''Unsigned Number''': A number between 0 to 2147483647 ''(Hold on! Why not 4294967295? Because the data stack uses int32 and 2147483647 is the max value you can have in the stack. “Unsigned” here doesn’t mean uint32, just that we don’t “waste” half a domino to represent the sign)''. * '''Signed Number''': A number between -2147483648 to 2147483647 (int32 range). * '''String''': A string is a sequence of null terminated unicode char codes. <ins> '''And the following directions''' </ins> : * '''SingleStraightLine''': The IP moves in a straight line towards the <ins>connection direction of the cell at the address</ins>. No wrap around like in “RawIncrement” mode. If you have a 10x20 grid you can get at most 5 dominos in horizontal direction or 10 dominos in vertical direction. * '''RawIncrement''' (to be implemented): Reads domino halfs using incrementing addresses. It disregards the grids bounds and wraps around from right edge left edge on the next line ''(Remember that addresses are essentially the indices to a 1D array of Cells which represent the Grid. Address 0 is at the top left of the grid. In a 10x10 grid, the largest address is 99 in the bottom right)'' '''Here a table of supported encoding type mappings:''' {| class="wikitable" ! Type Index ! Type ! Direction |- | 0 | Domino | connection direction |- | 1 | Unsigned Number | SingleStraightLine |- | 2 | Signed Number | SingleStraightLine |- | 3 | String | SingleStraightLine |- | 4 (TODO) | Unsigned Number | RawIncrement |- | 5 (TODO) | Signed Number | RawIncrement |- | 6 (TODO) | String | RawIncrement |} <span id="Set"></span> ==== SET - 43 ==== Writes data to the board. Takes <ins>at least</ins> 2 arguments from the stack: * The type Index to parse it as. It indicates the type and the direction of the data * The address of the first domino half * The data to write to the board. This can either be a single item from the stack or multiple if we write a string <ins> '''There are essentially 4 types you can write it as''' </ins> (See list under [[#Get|GET]]): <ins> '''And the following directions''' </ins> : * '''SingleStraightLine''': The IP moves in a straight line towards the <ins>last Instruction Pointer direction</ins>. No wrap around like in “RawIncrement” mode. If you have a 10x20 grid you can set at most 5 dominos in horizontal direction or 10 dominos in vertical direction. * '''RawIncrement''' (to be implemented): Writes domino halfs using incrementing addresses. It disregards the grids bounds and wraps around from right edge left edge on the next line ''(Remember that addresses are essentially the indices to a 1D array of Cells which represent the Grid. Address 0 is at the top left of the grid. In a 10x10 grid, the largest address is 99 in the bottom right)'' '''Here a table of supported type mappings:''' (See table under [[#Get|GET]]): <span id="Lit"></span> ==== LIT - 44 ==== Changes how number and string literals are parsed. It pops a number from the stack to use as the “literal parse mode”. The popped number must be between 0 to 6. If the number is out of bounds, an <code>DSInvalidLiteralParseModeError</code> is thrown. '''If the popped argument is:''' * <code>0</code>: Dynamic parse mode. Used by default. The first domino half of every number literal indicates how many more dominos should be parsed as part of the number. For string literals it is exactly the same but for each character. * <code>1</code> to <code>6</code>: Static parse modes. Uses 1 to 6 dominos for each number literal or each character in a string literal. In the following 3 examples <code>&quot;Hello world&quot;</code> is encoded in 3 different ways: In Base7 with Literal Parse Mode 0 (default): <pre>// Every character requires 2 dominos to be encoded on dominos 0—2 1—2 0—6 1—2 0—3 1—2 1—3 1—2 1—3 1—2 1—6 1—0 4—4 1—2 3—0 1—2 1—6 1—2 2—2 1—2 1—3 1—2 0—2 0—0</pre> In Base 16 with Literal Parse Mode 0: <pre>// Still every character requires 2 dominos to be encoded. Considering that we are in base 16, very wasteful! 0—2 1—0 6—8 1—0 6—5 1—0 6—c 1—0 6—c 1—0 6—f 1—0 2—0 1—0 7—7 1—0 6—f 1—0 7—2 1—0 6—c 1—0 6—4 0—0</pre> In Base 16 with Literal Parse Mode 1: <pre>// Every character requires 1 domino to be encoded. // Notice how now it is pretty much just hexadecimal 0—2 6—8 6—5 6—c 6—c 6—f 2—0 7—7 6—f 7—2 6—c 6—4 0—0</pre> As you can see, <ins>changing the default parse mode can significantly reduce the amount of dominos required to encode strings</ins>. For numbers it is less impactful but can still be significant if you are working mostly within a specific range. <span id="Base"></span> ==== BASE - 45 ==== Pops one number from the stack to use as the “base” for future parsing of dominos (opcodes, number literals, string literals) By default, DominoScript uses double six (D6) dominos to represent everything, so the default base is 7. The max cell value of half of a domino is always 1 less than the Base. So in base 7, the max value is 6. In base 10, the max value is 9. In base 16, the max value is 15 (aka <code>f</code>). If the number of dots on a domino half exceeds the max amount of possible dots for the current base, it is clamped! For example: when you are in Base 7 and the interpreter encounters a <code>f—f</code> domino, it will be parsed as <code>6—6</code>. If you are in base 10, it will be parsed as <code>9—9</code> etc. In below table you can see how the same domino sequence results in different decimal numbers depending on the base: {| class="wikitable" ! Domino Sequence ! Base 7 (D6) ! Base 10 (D9) ! Base 16 (D15) |- | <code>0—6</code> | 6 | 6 | 6 |- | <code>0—9</code> | 6 | 9 | 9 |- | <code>0—f</code> | 6 | 9 | 15 |- | <code>1—6 6—6</code> | 342 | 666 | 1638 |- | <code>1—9 9—9</code> | 342 | 999 | 2457 |- | <code>1—f f—f</code> | 342 | 999 | 4095 |- | <code>2—6 6—6 6—6</code> | 16806 | 66666 | 419430 |- | <code>2—9 9—9 9—9</code> | 16806 | 99999 | 629145 |- | <code>2—f f—f f—f</code> | 16806 | 99999 | 1048575 |} With a higher Base, you have access to higher opcodes without needing to switch to extended mode. {| class="wikitable" ! Base ! Opcode Range |- | 7 | 0 to 48 |- | 10 | 0 to 99 |- | 16 | 0 to 255 |} While the <ins>opcode-to-instruction</ins> mapping never changes, the <ins>domino-to-opcode</ins> mapping is completely different in each base. <span id="Ext"></span> ==== EXT - 46 ==== Toggle extended mode on or off. If extended mode is active the interpreter will use 2 dominos instead of 1 for each instruction which extends the opcode range from 0-48 to 0-2400 when using Double six dominos. <span id="Time"></span> ==== TIME - 47 ==== Pushes the milliseconds since program start to the stack. Useful for things like a gameloop, animations, cooldowns etc. <span id="Noop"></span> ==== NOOP - 48 ==== No operation. The IP will move to the next domino without doing anything. Useful to move the IP to a specific address (e.g. start of loop body) or to “reserve” space in case you think that you might need to add more instructions later on and don’t want to move dominos around. <br> == Navigation Modes == If you don't know what navigation modes are and how they influence the Instruction Pointer, I'd recommend reading the relevant section in [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]]. ''(F=Forward, L=Left, R=Right)'' There are <code>49</code> total navigation modes in DominoScript. This section should reference them all. ''To be fully spec compliant an implementation should support all of them. However, when developing an interpreter, this has a rather low priority. With just the default nav mode priority (Forward, Left, Right) you can run any DS code as long as it doesn't execute the NAVM instruction to change it.'' === Basic Three Way === Out of three directions, the IP will prioritize moving to the one with the highest priority. {| class="wikitable" ! Index ! Priorities ! Domino -&gt; |- | 0 (Default) | <code>Forward</code> <code>Left</code> <code>Right</code> | <code>0—0</code> |- | 1 | <code>Forward</code> <code>Right</code> <code>Left</code> | <code>0—1</code> |- | 2 | <code>Left</code> <code>Forward</code> <code>Right</code> | <code>0—2</code> |- | 3 | <code>Left</code> <code>Right</code> <code>Forward</code> | <code>0—3</code> |- | 4 | <code>Right</code> <code>Forward</code> <code>Left</code> | <code>0—4</code> |- | 5 | <code>Right</code> <code>Left</code> <code>Forward</code> | <code>0—5</code> |- | 6 | <code>RANDOM</code> | <code>0—6</code> |} === Basic Two Way === Out of two directions, the IP will prioritize moving to the one with the highest priority. {| class="wikitable" ! Index ! Priorities ! Domino -&gt; |- | 7 | <code>Forward</code> <code>Left</code> | <code>1—0</code> |- | 8 | <code>Forward</code> <code>Right</code> | <code>1—1</code> |- | 9 | <code>Left</code> <code>Forward</code> | <code>1—2</code> |- | 10 | <code>Left</code> <code>Right</code> | <code>1—3</code> |- | 11 | <code>Right</code> <code>Forward</code> | <code>1—4</code> |- | 12 | <code>Right</code> <code>Left</code> | <code>1—5</code> |- | 13 | <code>RANDOM</code> | <code>1—6</code> |} === Basic One Way === IP can only move in one direction. {| class="wikitable" ! Index ! Only Direction ! Domino -&gt; |- | 14 | <code>Forward</code> | <code>2—0</code> |- | 15 | <code>Forward</code> | <code>2—1</code> |- | 16 | <code>Left</code> | <code>2—2</code> |- | 17 | <code>Left</code> | <code>2—3</code> |- | 18 | <code>Right</code> | <code>2—4</code> |- | 19 | <code>Right</code> | <code>2—5</code> |- | 20 | <code>RANDOM</code> | <code>2—6</code> |} === Cycle Three Way === The direction with the highest priority becomes the least prioritized in the next cycle. All 3 directions are available in all cycles. {| class="wikitable" ! Index ! Cycle 1 ! Cycle 2 ! Cycle 3 ! Domino -&gt; |- | 21 | <code>F</code> <code>L</code> <code>R</code> | <code>L</code> <code>R</code> <code>F</code> | <code>R</code> <code>F</code> <code>L</code> | <code>3—0</code> |- | 22 | <code>F</code> <code>R</code> <code>L</code> | <code>R</code> <code>F</code> <code>F</code> | <code>L</code> <code>F</code> <code>R</code> | <code>3—1</code> |- | 23 | <code>L</code> <code>F</code> <code>R</code> | <code>F</code> <code>R</code> <code>F</code> | <code>R</code> <code>L</code> <code>F</code> | <code>3—2</code> |- | 24 | <code>L</code> <code>R</code> <code>F</code> | <code>R</code> <code>F</code> <code>L</code> | <code>F</code> <code>L</code> <code>R</code> | <code>3—3</code> |- | 25 | <code>R</code> <code>F</code> <code>L</code> | <code>F</code> <code>L</code> <code>R</code> | <code>L</code> <code>R</code> <code>F</code> | <code>3—4</code> |- | 26 | <code>R</code> <code>L</code> <code>F</code> | <code>L</code> <code>F</code> <code>R</code> | <code>F</code> <code>R</code> <code>L</code> | <code>3—5</code> |- | 27 | (unmapped) | (unmapped) | (unmapped) | <code>3—6</code> |} === Cycle Two Way === The direction with the highest priority becomes the least prioritized in the next cycle. Only 2 directions are available in a single cycle. {| class="wikitable" ! Index ! Cycle 1 ! Cycle 2 ! Cycle 3 ! Domino -&gt; |- | 28 | <code>F</code> <code>L</code> | <code>L</code> <code>R</code> | <code>R</code> <code>F</code> | <code>4—0</code> |- | 29 | <code>F</code> <code>R</code> | <code>R</code> <code>F</code> | <code>L</code> <code>F</code> | <code>4—1</code> |- | 30 | <code>L</code> <code>F</code> | <code>F</code> <code>R</code> | <code>R</code> <code>L</code> | <code>4—2</code> |- | 31 | <code>L</code> <code>R</code> | <code>R</code> <code>F</code> | <code>F</code> <code>L</code> | <code>4—3</code> |- | 32 | <code>R</code> <code>F</code> | <code>F</code> <code>L</code> | <code>L</code> <code>R</code> | <code>4—4</code> |- | 33 | <code>R</code> <code>L</code> | <code>L</code> <code>F</code> | <code>F</code> <code>R</code> | <code>4—5</code> |- | 34 | (unmapped) | (unmapped) | (unmapped) | <code>4—6</code> |} === Cycle One Way === The direction with the highest priority becomes the least prioritized in the next cycle. Only 1 direction is available in a single cycle. {| class="wikitable" ! Index ! Cycle 1 ! Cycle 2 ! Cycle 3 ! Domino -&gt; |- | 35 | <code>F</code> | <code>L</code> | <code>R</code> | <code>5—0</code> |- | 36 | <code>F</code> | <code>R</code> | <code>L</code> | <code>5—1</code> |- | 37 | <code>L</code> | <code>F</code> | <code>R</code> | <code>5—2</code> |- | 38 | <code>L</code> | <code>R</code> | <code>F</code> | <code>5—3</code> |- | 39 | <code>R</code> | <code>F</code> | <code>L</code> | <code>5—4</code> |- | 40 | <code>R</code> | <code>L</code> | <code>F</code> | <code>5—5</code> |- | 41 | (unmapped) | (unmapped) | (unmapped) | <code>5—6</code> |} === Flip Flop === The priority flip flops between 2 primary directions. {| class="wikitable" ! Index ! Flip ! Flop ! Domino -&gt; |- | 42 | <code>F</code> | <code>L</code> | <code>6—0</code> |- | 43 | <code>F</code> | <code>R</code> | <code>6—1</code> |- | 44 | <code>L</code> | <code>F</code> | <code>6—2</code> |- | 45 | <code>L</code> | <code>R</code> | <code>6—3</code> |- | 46 | <code>R</code> | <code>F</code> | <code>6—4</code> |- | 47 | <code>R</code> | <code>L</code> | <code>6—5</code> |- | 48 | (unmapped) | (unmapped) | <code>6—6</code> |} <br> == Example: Factorial == <br>[[File:DominoScript-Example-Factorial-flow.png|thumb|Factorial Example with IP flow visualized]] '''Pseudocode:''' <pre style="overflow:auto;> NUM 12 NUM 42 CALL NUMOUT // prints 479001600 FUNCTION FACTORIAL: // (address 42) DUP NUM 0 EQ IF: POP NUM 1 ELSE: DUP NUM 1 SUB NUM 42 CALL // recursive call MUL </pre> '''DominoScript:''' <pre style="letter-spacing:4px;line-height:1.1;overflow:auto;"> 0—1 . . . . . 1—0 1—0 0 . . . 2—1 4—4 0 | | 0—1 . . . . . . . . . 0 . . . . . . . 6 1 . 0—3 0—1 0—0 2—3 4—1 . . . . . . . 0 | | 5 . . . . . . . . . . 0 . . . . . . . 1 | 0—1 1—0 6—0 4—4 5—1 . 3 0—1 0—1 1—1 0—1 </pre> == Example: WASD Controls == Demonstrates `WASD` keyboard inputs that move a character around on a 5x7 grid and renders it via stdout. It could be used as a basis to build a simple game. [[File:DominoScript-Example-WASD-Input-Example-Flow.png|thumb|WASD Controls example with IP flow visualized]] '''Pseudocode''': <pre style="overflow:auto;font-size:0.85em;> NUM 16 BASE // tell interpreter to use dominos with up to 16 dots per side. Allowing you to use less dominos // Binding addresses to labels NUM 116 LABEL // playerX -1 NUM 122 LABEL // playerY -2 NUM 1008 LABEL // topRow = "╭──────────────╮\n" -3 NUM 1080 LABEL // middleRow = "│ │\n" -4 NUM 1152 LABEL // bottomRow = "╰──────────────╯\n" -5 NUM 72 LABEL // function main() -6 NUM 361 LABEL // function update() -7 NUM 505 LABEL // function render() -8 NUM 660 LABEL // loop body start within render() -9 NUM 6 NEG CALL // main() FUNCTION main: NUM 1 LIT // tell interpreter that we use exactly 1 domino for each number or character in a string LOOP_FOREVER: NUM 50 WAIT // wait 50ms PUSH 7 NEG CALL // update() PUSH 8 NEG CALL // render() NUM 6 NEG JUMP // jump back to start of main FUNCTION update: STR "w" KEY IF: NUM 1 NUM 2 NEG GET NUM 1 SUB NUM 1 NUM 2 NEG SET // y = y - 1 STR "a" KEY IF: NUM 1 NUM 1 NEG GET NUM 2 SUB NUM 1 NUM 1 NEG SET // x = x - 2 STR "s" KEY IF: NUM 1 NUM 2 NEG GET NUM 1 ADD NUM 1 NUM 2 NEG SET // y = y + 1 STR "d" KEY IF: NUM 1 NUM 1 NEG GET NUM 2 ADD NUM 1 NUM 1 NEG SET // x = x + 2 NUM 1 NUM 1 NEG GET NUM 2 NUM 13 CLAMP NUM 1 NUM 1 NEG SET // x = clamp(x, 2, 13) NUM 1 NUM 2 NEG GET NUM 2 NUM 6 CLAMP NUM 1 NUM 2 NEG SET // y = clamp(y, 2, 6) KEYRES FUNCTION render: STR '\033[2J\033[H' STDOUT // clear screen and move cursor to top left NUM 0 // iterator = 0; LOOP: DUPE NUM 0 EQL IF: // if (iterator === 0) NUM 3 NUM 3 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Top row string if on row 0 DUPE NUM 8 EQL IF: // if (iterator === 8) NUM 3 NUM 5 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Bottom row string if on row 8 DUPE DUPE NUM 2 GTR NUM 1 ROLL NUM 7 GTR NOT AND IF: // if (iterator > 2 && iterator < 7) NUM 3 NUM 4 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Middle row string if on row 1-7 NUM 1 ADD // iterator = iterator + 1 DUPE NUM 8 EQL IF: // Hacky way to achieve the equivalent of: stdout.write(`\033[${playerY};${playerX}H[]`) // The string is constructed 1 char at a time in reverse order using NUM NUM 0 NUM 93 NUM 91 NUM 72 NUM 1 NUM 1 NEG GET NUM 31 NUM 59 NUM 1 NUM 2 NEG GET NUM 31 NUM 91 NUM 27 STROUT POP // remove iterator from stack BREAK // exit loop if we've reached the bottom row NUM 9 NEG JUMP // jump back to start of loop </pre> '''DominoScript''': <pre style="letter-spacing:2px;line-height:1.1;overflow:auto;font-size:0.85em;"> 0—1 1—0 2—2 6—3 0—1 1—0 7—4 1—e 0—1 1—0 7—a 1—e 0—1 1—3 f—0 1—e 0—1 1—4 3—8 1—e 0—1 1—4 8—0 1—e 0—1 1—0 4—8 1—e 0—1 1—1 6—9 1—e 0—1 1—2 8—8 1—e 0—1 0—1 2—c 0—1 3—2 2—2 0—1 0—7 0—c 2—0 0—1 0—8 0—c 2—0 0—1 0—6 0—c 1—f . . . . . . 0—0 0—8 . . 0—0 0—4 . . . . 0—2 c—0 6—0 1—0 e—1 4—9 2—1 1—0 0—8 0—1 0—1 0—1 0—2 0—c 2—b 3—0 3 . 0—8 0—1 0—1 0—1 0—1 0—c 2—b 3—0 3 . 0—7 0—1 0—1 0—1 0—2 0—c 2—b 3—0 3 . 0—7 0—1 0—1 0—1 0—1 0—c 2—b 3—0 3 . | | | | 1 . . . . . . . . . . . . . . . 0 . 2 . . . . . . . . . . . . . . . 0 . 1 . . . . . . . . . . . . . . . 0 . 2 . . . . . . . . . . . . . . . 0 . | | | | 0 1—0 a—2 c—0 2—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 1—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 2—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 1—0 1—0 1—0 1—0 d 3 . | | | | | | | | . 3—0 3—0 3—0 0—2 7—7 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 6—1 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 7—3 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 6—4 0—0 2—7 1 0 3 | 2 0—3 0—3 b—2 c—0 2—0 1—0 1—0 . . 6—0 1—0 2—0 1—0 a—2 c—0 2—0 1—0 . . 0—3 0—3 0—3 b—2 c—0 1—0 1—0 1—0 . . e—0 1—0 2—0 1—0 a—2 c—0 1—0 1—0 . . 0 | 8 . 5—b 3 . 5—b 4 . 0—1 0 . 1—0 d—0 . . 0—1 0—3 0—3 0—c 0—1 0 . 1—0 1—0 0—1 0 . . . 3—0 3—0 1 . . . 1—0 d—0 2—a 0 . 0—2 0 . 1—b 2 . . . 1—0 1—0 | | | | | | | | | . . b . 2 . b . 8 . 6 . 0 . . 0—0 1—1 1—d 0 c—2 1—0 0—0 1—0 2 2 . 2—a 2—6 . 0 0 . 1—1 . . 0 d 0—1 . . . . . c . 1 . 1 . c . 1 . 6 . . . . . . . | | | | | | | | | | 0—2 1 . 4—a 1 . 0—0 2 . 0—3 0—1 . . . 3—0 3 . . . . 0—1 0 6 . c 2—c . . . . . 1 . 9 . . 0 1 . . 0 . 0—1 4 . 0 . 1 . 0 . 2 . 0 . 0 . . . . . . . | | | | | | | | | . . . . . . . . . . . . . 1 1—1 8—0 1—0 0—3 . . . 0—3 . 4 2 a—2 2 . . 3 0—3 c—2 . 0 . 0 9 . . . 0 . b . 8 . 1 . f . 1 . a . b . 0 . . . . . . . | | | | | | | | . 0—3 0—3 0—3 0—3 0—3 0—3 d 0—1 0—3 0—1 0—5 3—0 . 1 . . 0—c 0—1 0 . . 0 . . 0—3 0—1 . c . . . . 0 . 5 . 0 . 0 . 0 . 0 . 0 . 5 . . . . . . . . . | | | | | 3—0 c—2 1—0 0—0 1—0 6—2 a—2 c—2 2—0 1—0 c—0 0—3 . 0 d 3—0 3—0 3—0 3—0 0—1 . 7 . . . f—1 . . . . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . . . . . . . . . | | | | | | 0—3 0—1 0—2 1—2 0—1 0—1 0—4 0—1 0—7 1—2 0—e 0—f 3—0 1 . . . . . . . . . 0—1 0 . . . . . . . . . 5—d 0 . 0—1 0 . 3—b 0 . 1—f 0 . . . . . . . . . 2—5 6—d 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 6—e 0—0 0—a 0—0 0—0 2—5 0—2 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 2—5 0—2 0—0 0—a 0—0 0—0 2—5 7—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 6—f 0—0 0—a 0—0 0—0 </pre> ==External resources== * [https://dominoscript.com Website with code playground] * [https://github.com/andreas-schoch/dominoscript GitHub Repository containing reference implementations, examples and documentations] [[Category:Languages]] [[Category:Stack-based]] [[Category:Implemented]] [[Category:Self-modifying]] [[Category:Turing complete]] [[Category:Low-level]] [[Category:Thematic]] [[Category:2024]]'
Unified diff of changes made by edit (edit_diff)
'@@ -1,0 +1,1591 @@ +{{infobox proglang +|image=File:Dominoscript-logo.png +|name=DominoScript +|author=[[User:Galvandi]] +|year=[[:Category:2024|2024]] +|paradigms=imperative +|memsys=[[:Category:Stack-based|Stack-based]] +|dimensions=[[:Category:Two-dimensional languages|two-dimensional]] +|class=[[:Category:Turing complete|Turing complete]] +|majorimpl=[https://github.com/andreas-schoch/dominoscript Github Repo] +|files=<code>.ds</code> recommended +}}'''DominoScript''' is a two-dimensional self-modifying [[esoteric programming language]] that uses the dots on domino pieces to represent code. + +== Core Concepts == +'''<code>Domino Pieces</code>''': +* A domino piece can be placed either horizontally or vertically. +* DominoScript by default uses Double-Six (aka <code>D6</code>) dominos to represent code. Double-six here means that each domino has 2 sides with up to 6 dots each. Essentially Base7. +* Using the [[#Base|BASE]] instruction, you can tell the interpreter to parse dominos with up to 16 dots on each side. Allowing you to represent larger numbers with fewer dominos. +'''<code>Stack-Oriented</code>''': +* There is a global data stack that all instructions operate on. +* By default, the stack size is limited to 512 items (Up to the implementation to make this configurable. The default of the reference interpreter might become significantly larger with a future version). +* At its core, DS is just another concatenative [[Postfix notation|reverse-polish]] language. The following code: <code style="border-color:gray;">0—1 0—5 0—1 0—6 1—0 0—3 1—2 5—1</code> is the same as <code style="border-color:gray;">5 6 + dup * .</code> in [[Forth]]. +* Internally every item on the stack is a signed 32-bit integer. +* Strings are just null-terminated sequences of integers representing Unicode char codes. +* Floats are not supported ''(Fixed-point-arithmetic might be supported in future versions)''. +* No other data structures exist. + +'''<code>Two-Dimensional</code>''': +* The code is represented on a rectangle grid of cells. The top-left cell is address 0. The bottom-right cell is address <code>cols * rows - 1</code>. +* Any implementation needs to support a grid of at least 65408 total cells to be spec compliant. That allows a square grid of up to `256x256` cols and rows or any smaller rectangular grid within the cell limit. Each cell needs to be indexable using an <code>int32</code> popped from the data stack, so well optimized implementations may support crazy amounts of cells. +* The Instruction Pointer (IP) can move in any cardinal direction. Direction changes are performed by placing dominos in a certain way (IP always moves from one half to the other half of the same domino) as well as the current Navigation Mode. See: [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]]. + +'''<code>Self-Modifying</code>''': +* The code can override itself somewhat similar to befunge. See [[#Get|GET]] and [[#Set|SET]] instructions. +* Getting and setting can be done using different encodings: +** '''domino''': get or set single domino +** '''unsigned number''': get or set a number within the int32 range ''(why not uint32? Because the stack only supports int32 so there is no point)''. Up to 7 dominos can be parsed per get/set. +** '''signed number''': get or set a number within the int32 range. Up to 7 dominos can be parsed per get/set. The only different to unsigned number encoding is that here the first half of the first domino is sacrificed to encode the "sign bit" (if first half is anything but 0, sign bit is on). +** '''string''': Get or set a whole string. +* Can be used as a secondary data store ''(to act somewhat similar to registers or variables)'' besides the stack. + +'''<code>Multiple Files</code>''': +* You can split up DS code into multiple files and include them in the main file using the [[#Import|IMPORT]] instruction. +* Each import has its own grid of cells. +* The data stack is shared between the main and all imported files. +* Defining a label within an imported file during the import phase, allows the parent to call functions within the child. Giving the parent essentially an interface to use the imported file as a library. ''(See the [[#Label|LABEL]] instruction for more info)''. + +== Text Format == +The dots on dominos are represented using a text based format: +* The digits <code>0</code> to <code>f</code> represent the dots on half of a domino. To indicate an empty cell, use a dot <code>.</code> +* The “long hyphen” character <code>—</code> indicates a horizontal domino ''(regular hyphen <code>-</code> also accepted to make it easier to type)''. It can only appear on '''even''' columns and '''odd''' rows. +* The “pipe” character <code>|</code> indicates a vertical domino. It can only appear on '''odd''' columns and '''even''' rows. +* Any other line <ins>before</ins> and <ins>after</ins> the actual code is ignored. ''(Tip: Make use of this to add extensive comments. You will inevitable forget what your dominoscript code does, so consider including a 1:1 pseudocode implementation of the dominoscript code)'' + +The following DominoScript code ''(which prints "Hello world")'': + +<pre style="letter-spacing:4px;line-height:1.1;display:inline-block;border-color: black;"> +. . . . . . . . . . . . . . . + +. . . . . . . . 0—2 1 . 0—3 . + | +. 1 0—3 2—1 4—4 . . 2 . 2 1 . + | | | +. 2 . . . . . 0 . . 0—6 1 2 . + | +. 1—6 1—2 2 . 1 6—1 . . . 1 . + | | +. . . . . 2 . . . 2 . . . 3 . + | +. 1 3—1 2—1 . . . 1 3—1 2—1 . + | +. 2 0—2 0 . . . . . . . . . . + | +. . . . 0 5—3 . . . . . . . . +</pre> + +Is the equivalent of the following dominos: + +<br>[[File:DominoScript-Example-003-flow.png|400px|Hello world 2d]] + + +The grid doesn’t have to be a square but it must have a consistent number of columns and rows, otherwise an <code>InvalidGridError</code> will be thrown before execution starts: + +<table class="wikitable"> +<tr><th>GOOD ✅</th><th>BAD ❌</th></tr> +<tr><td> +<pre>. . . . . . . . + +. . . . . . . . + +. . . . . . . . + +. . . . . . . .</pre> +</td> +<td> +<pre> . . . . . . . + +. . . . . . . . + +. . . . . + +. . . . . . .</pre> +</td> +</tr> +</table> +Connecting to a domino half which is already connected results in <code>MultiConnectionError</code>: + +<table class="wikitable"> +<tr><th>GOOD ✅</th><th>BAD ❌</th></tr> +<tr><td> +<pre>6—6 6—6 . + +6 6—6 . . +| +6 . . . .</pre> +</td> +<td> +<pre>6—6—6—6 . + +6—6 . . . +| +6 . . . .</pre> +</td> +</tr> +</table> +Having a domino half that is not connected to anything results in <code>MissingConnectionError</code>: + +<table class="wikitable"> +<tr><th>GOOD ✅</th><th>BAD ❌</th></tr> +<tr><td> +<pre>. . 6—6 . + +. 6 . . . + | +. 6 . . .</pre> +</td> +<td> +<pre>. . 6 6 . + +. 6 . . . + +. 6 . . .</pre> +</td> +</tr> +</table> +Having a connection where 1 or both ends are empty results in a <code>ConnectionToEmptyCellError</code>: + +<table class="wikitable"> +<tr><th>GOOD ✅</th><th>BAD ❌</th></tr> +<tr><td> +<pre>6—6 . 6—6 + +6 . . . 6 +| | +6 . . . 6</pre> +</td> +<td> +<pre>6—. . .—6 + +6 . . . . +| | +. . . . 6</pre> +</td> +</tr> +</table> + +== How Dominos are parsed into Numbers == +It is important to understand that '''internally''' everything in DominoScript is represented as signed 32-bit Integers and '''externally''' everything is represented by the dots on the domino pieces. + +'''Every domino is part of either''': +* An opcode - decides which instruction to execute next. By default, one domino represents one opcode unless you tell the interpreter to use 2 dominos per opcode using the [[#Ext|EXT]] instruction. +* A number literal - the [[#Num|NUM]] instruction is used to push a single Integer onto the stack. +* A string literal - the [[#Str|STR]] instruction is used to push a sequence of Integers onto the stack which represent unicode char codes. + +'''Furthermore, you should also be aware of the following things''': +* The number base system that is currently set influences how dots are parsed into numbers. The base can be changed using the [[#Base|BASE]] instruction. (Default: Base 7 - because double-six dominos are the most common). +* The "LiteralParseMode" tells the interpreter how many dominos will be part of a literal. It can be changed using the [[#Lit|LIT]] instruction (Default: dynamic - first half of first domino decides how many more are part of a number literal). +* Once a literal is pushed on the stack, it is your job as the developer to keep track of which items are numbers and which ones are characters of a string. You can use any instruction on characters of a “string” but only the following ones will treat them as such: [[#Str|STR]], [[#Eqlstr|EQLSTR]], [[#Strin|STRIN]], [[#Strout|STROUT]] as well as [[#Get|GET]] and [[#Set|SET]] when used with the "string" encoding type. + +In examples, you might see stack items that are meant to be char codes, represented in the following way:” + +<pre>[..., 1, 2, 3 'NUL', 's', 'e', 'y']</pre> +But in reality, the stack will store them as integers and look like this: + +<pre>[..., 1, 2, 3, 0, 115, 101, 121]</pre> + +'''What about floats?''' + +Floats don’t exist in DominoScript. I’d suggest scaling up numbers by a factor of 10, 100, 1000 or whatever precision you need. + +''(I know that pico-8 uses 32-bits for numbers but treats them as 16.16 fixed point numbers. I am not quite sure if that is just a convention or if pico8’s API actually treats them as fixed-point numbers. I would like to eventually add some trigonometry instructions to DominoScript but am unsure what the most practical way would be)'' + +== How the Instruction Pointer Moves == +The Instruction Pointer (<code>IP</code>) keeps track of the current cell address that will be used for the next instruction. Since DominoScript is 2D, it isn’t obvious where the IP will move to without understanding the fundamental rules and the Navigation Modes. + +'''Before the program starts:''' +# The interpreter will scan the grid from '''top-left to top-right''', move down and repeat until it finds the first domino. +# Upon reaching the first domino, the IP is placed at the address of the first found domino half. +# If no domino could be found, the program is considered finished. + +'''During the program execution:'''<br> +The IP will adhere to the following rules: +* The IP can move in cardinal directions, never diagonally. How dominos are parsed, is all relative to that. For example, the horizontal domino <code>3—5</code> can be interpreted as the base7 number <code>35</code> (IP moves eastwards) or <code>53</code> (IP moves westwards). Same thing for vertical dominos. +* The IP will always move from one half (entry) of the same domino to the other half (exit) of the same domino. +* If the IP cannot move to a new domino, the program is considered finished. +* At the exit half of a domino, the IP will never move back to the entry half. It will always try to move to a new domino. That means, there are at most 0 to 3 potential options for the IP to move. +* When the IP needs to move to a new domino, it is possible that there are no valid moves despite there being dominos around. The [[#Navigation_Modes|Navigation Mode]] decides where the IP can and cannot move next. + +'''Understanding Navigation Modes:'''<br> +Navigation Modes are predefined priority patterns which are used when the Instruction Pointer needs to decide to which domino to move to next. The [[#Navm|NAVM]] instruction can be used to change the current Navigation Mode. + +Understanding the following concepts will become very important: +* '''Priority Directions''': Primary, Secondary, Tertiary +* '''Relative Directions''': Forward, Left, Right +* '''Cardinal Directions''': North, East, South, West + +The Cardinal directions don’t matter much. It is all about the '''direction in relation to the exit half''' of the current domino ''(If you ever did any kind of GameDev you probably know the difference between world space and local space. It’s kind of like that)'' + +When the IP moves to a new domino, the half it enters to is called the “'''entry'''” while the other half is called the “'''exit'''”. Now from the perspective of the exit half, the IP can potentially move in 3 directions: Forward, Left, Right. These are the '''Relative Directions'''. + +Which relative direction the IP chooses, depends on the current Navigation Mode. Below you will see the mapping of the very basic nav modes: + +{| class="wikitable" +|- +! Index !! <code>Primary</code> !! <code>Secondary</code> !! <code>Tertiary</code> +|- +| 0 || Forward || Left || Right +|- +| 1 || Forward || Right || Left +|- +| 2 || Left || Forward || Right +|- +| 3 || Left || Right || Forward +|- +| 4 || Right || Forward || Left +|- +| 5 || Right || Left || Forward +|- +| ... || ... || ... || ... +|} +''The “index” here is the argument for the <code>NAVM</code>instruction.'' + +<br> + +'''If we imagine the <code>6</code> to be the exit half, what will be the next domino the IP moves to?:''' + +<table class="wikitable" style="line-height:1.1;letter-spacing:4px;"> +<tr> +<th>East</th> +<th>West</th> +<th>South</th> +<th>North</th> +</tr> +<tr> +<td> +<pre> +. 2 . . . + | +. 2 . . . + +5—6 1—1 . + +. 3 . . . + | +. 3 . . . +</pre> +</td> +<td> +<pre> +. . . 3 . + | +. . . 3 . + +. 1—1 6—5 + +. . . 2 . + | +. . . 2 . +</pre> +</td> +<td> +<pre> +. . 5 . . + | +3—3 6 2—2 + +. . 1 . . + | +. . 1 . . + +. . . . . +</pre> +</td> +<td> +<pre> +. . . . . + +. . 1 . . + | +. . 1 . . + +2—2 6 3—3 + | +. . 5 . . +</pre> +</td> +</tr> +</table> +''All 4 snippets are exactly the same code with the difference that they are all flipped differently. This is what I mean by the cardinal direction not mattering much in DominoScript.'' + +* When <code>index 0</code>, the IP will move to <code>1—1</code> (Primary, Forward) +* When <code>index 1</code>, the IP will move to <code>1—1</code> (Primary, Forward) +* When <code>index 2</code>, the IP will move to <code>2—2</code> (Primary, Left) +* When <code>index 3</code>, the IP will move to <code>2—2</code> (Primary, Left) +* When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right) +* When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right) + +<br> + +'''What if we remove the <code>1—1</code> domino? Where will the IP go to then?:''' + +<table class="wikitable" style="line-height:1.1;letter-spacing:4px;"> +<tr> +<th>East</th> +<th>West</th> +<th>South</th> +<th>North</th> +</tr> +<tr> +<td> +<pre>. 2 . . . + | +. 2 . . . + +5—6 . . . + +. 3 . . . + | +. 3 . . .</pre> +</td> +<td> +<pre>. . . 3 . + | +. . . 3 . + +. . . 6—5 + +. . . 2 . + | +. . . 2 .</pre> +</td> +<td> +<pre>. . 5 . . + | +3—3 6 2—2 + +. . . . . + +. . . . . + +. . . . .</pre> +</td> +<td> +<pre>. . . . . + +. . . . . + +. . . . . + +2—2 6 3—3 + | +. . 5 . .</pre> +</td> +</tr> +</table> +* When <code>index 0</code>, the IP will move to <code>2—2</code> (Secondary, Left) +* When <code>index 1</code>, the IP will move to <code>3—3</code> (Secondary, Right) +* When <code>index 2</code>, the IP will move to <code>2—2</code> (Primary, Left) +* When <code>index 3</code>, the IP will move to <code>2—2</code> (Primary, Left) +* When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right) +* When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right) + +<br> + +'''And what if we remove both the <code>1—1</code> and the <code>2—2</code> domino?:''' + +<table class="wikitable" style="line-height:1.1;letter-spacing:4px;"> +<tr> +<th>East</th> +<th>West</th> +<th>South</th> +<th>North</th> +</tr> +<tr> +<td> +<pre>. . . . . + +. . . . . + +5—6 . . . + +. 3 . . . + | +. 3 . . .</pre> +</td> +<td> +<pre>. . . 3 . + | +. . . 3 . + +. . . 6—5 + +. . . . . + +. . . . .</pre> +</td> +<td> +<pre>. . 5 . . + | +3—3 6 . . + +. . . . . + +. . . . . + +. . . . .</pre> +</td> +<td> +<pre>. . . . . + +. . . . . + +. . . . . + +. . 6 3—3 + | +. . 5 . .</pre> +</td> +</tr> +</table> +* When <code>index 0</code>, the IP will move to <code>3—3</code> (Tertiary, Right) +* When <code>index 1</code>, the IP will move to <code>3—3</code> (Secondary, Right) +* When <code>index 2</code>, the IP will move to <code>3—3</code> (Tertiary, Right) +* When <code>index 3</code>, the IP will move to <code>3—3</code> (Secondary, Right) +* When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right) +* When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right) + +<br> + +These are only variations of the “Basic-Three-Way” kind of NavModes. See the [[#Navigation_Modes|Reference]] for a full list of available modes. + +== Instructions == + +Instructions are mapped to opcodes behind the scenes: + +* '''0-48''': Are the “core” instructions ''(2 have yet to be mapped)'' and are meant to fit within the value range a single “double-six” domino can represent. +* '''49-99''': Reserved for future extensions of the language ''(e.g. fixed-point-arithmetic, helpers for more advanced string manipulation and such)'' +* '''100+''': Allow you as developer to extend the language yourself with non-standard behaviour. These opcodes are essentially alternative ways of calling by label. To learn more, see: [[#Call|CALL]], [[#Label|LABEL]] and [[#Import|IMPORT]] instructions. + +To know which domino represents which opcode, you have to know the currently active [[#Base|base]]. For example, to represent opcode 48...: +* in '''base7''' you use a '''<code>6—6</code>''' domino (default) +* in '''base10''' you use a '''<code>4—8</code>''' domino +* in '''base16''' you use a '''<code>3—0</code>''' domino + +<br> + +The core instructions are grouped in 7 categories of 7 instructions each. Below, you will see them listed all. +''(The numbers on the right beside the instruction titles are the corresponding opcode)'' + +<br> +=== Stack Management === + +<span id="Pop"></span> +==== POP - 0 ==== +Discards the top of the stack. + +<span id="Num"></span> +==== NUM - 1 ==== +Switch to “number mode”. By default, the first half of the next domino will indicate how many dominos to read as a number. Then the other halfs will all be read as base7 digits (in D6 mode) to form the number that will be pushed to the stack. + +With 7 dominos, 13 out of 14 halfs are used for the number. You can theoretically represent a number much larger than the max int32 value. However, if the number exceeds the maximum int32 value, it will wrap around from the minimum value, and vice versa ''(exactly the same as when doing bitwise operations in JS –&gt; <code>(96889010406 | 0) === -1895237402</code>)''. + +You might think that since internally numbers are int32s, that we parse from base7 to two’s complement. That is not the case. We simple push the decimal version of the positive base7 number to the stack + +'''For example:''' + +* <code>0—0</code> represents the number <code>0</code> in both decimal and base7 +* <code>0—6</code> represents the number <code>6</code> in both decimal and base7 +* <code>1—6 6—6</code> represents the number <code>342</code> in decimal and <code>666</code> in base7 +* <code>2—6 6—6 6—6</code> represents the number <code>16,806</code> in decimal and <code>6,666</code> in base7 +* <code>6—6 6—6 6—6 6—6 6—6 6—6</code> represents the number <code>1,977,326,742</code> in decimal and <code>66,666,666,666</code> in base7 (about 92.1% of the max int32 value) +* <code>6—0 1—0 4—1 3—4 2—1 1—1 6—1</code> represents the number <code>2,147,483,647</code> in decimal and <code>104,134,211,161</code> in base7 (exactly the max int32 value) +* <code>6—6 6—6 6—6 6—6 6—6 6—6 6—6</code> represents the number -1,895,237,402. '''WHY?''': The actual decimal number the dominos represent is <code>96,889,010,406</code> which is ~45x larger than the max int32 value. It wraps around about that many times before it reaches the final value. + +'''What if numbers are read from the other directions?''' + +* <code>1—1 1—1</code>, <code>2—2 2—2 2—2</code> for example will be exactly the same numbers (216 in decimal) eastwards and westwards. +* <code>1—2 3—1</code> when parsed backwards is <code>1—3 2—1</code> and can therefore represent different numbers if the IP moves to the east or to the west. +* <code>1—6 6—6</code> represents 666 in base7 (342 in decimal) but when parsed backwards the interpreter will raise an <code>UnexpectedEndOfNumberError</code>. Remember that the first half of the first domino indicates how many more will follow. In this case it expects to read 6 more dominos but the number ends prematurely after 1 domino. + +'''What if I want to use a fixed amount of dominos for each number?''' + +Use the [[#Lit|LIT]] instruction to permanently change how literals are parsed. For example with parse mode <code>2</code> it will use 2 dominos for each number. While <code>6—6 6—6</code> in default parse mode 0 results in <code>UnexpectedEndOfNumberError</code> (because it expects 6 more dominos to follow but only got 1 more), in parse mode <code>2</code> it represents the decimal number <code>2400</code>. + +<span id="Str"></span> +==== STR - 2 ==== +With <code>STR</code> you switch to “string mode” and can push multiple integers to the stack to represent Unicode characters. + +The way the dominos are parsed to numbers is identical to <code>NUM</code>: First half of first domino indicates how many more will follow for a single number. + +The difference is that it doesn’t stop with just one number. It will keep reading numbers until it encounters the NULL character represented by domino <code>0—0</code>. + +Only once the interpreter does encounter the NULL character, will it push the characters to the stack in <ins>reverse</ins> order. + +''(Note: I decided to parse strings like this because I wanted a single int32 based stack and, out of all options I could think of, this one felt the least annoying. If you can think of better ways, I am open for suggestions!)'' + +This is how you push the string <code>&quot;hi!&quot;</code> to the stack and output it: + +<pre>0—2 1—2 0—6 1—2 1—0 1—0 4—5 0—0 5—3</pre> +It equals the following pseudo code: <code>STR &quot;hi!&quot; STROUT</code> + +* <code>0—2</code> is the <code>STR</code> instruction +* <code>1—2 0—6</code> is the Unicode value 105 representing the character <code>h</code> +* <code>1—2 1—0</code> is the Unicode value 105 representing the character <code>i</code> +* <code>0—0 4—5</code> is the Unicode value 33 representing the character <code>!</code> +* <code>0—0</code> is the Unicode value for the NULL character which terminates the string. +* <code>5—3</code> is the [[#Strout|STROUT]] instruction. It will pop items from the stack, parse them as Unicode chars and once it encounters the NULL character, it will output the string to stdout all at once. + +This is the resulting stack: + +<table class="wikitable"> +<tr> +<th> +Imaginative +</th> +<th> +Reality +</th> +</tr> +<tr> +<td> +<pre>[..., 'NUL', '!', 'i', 'h']</pre> +</td> +<td> +<pre>[..., 0, 33, 105, 104]</pre> +</td> +</tr> +</table> +Keep in mind that the IP can move in 4 cardinal direction so the following variations would also push the string <code>&quot;hi!&quot;</code> to the stack: + +IP moves right to left: + +<pre>3—5 0—0 5—4 0—1 0—1 2—1 6—0 2—1 2—0</pre> +IP moves in multiple directions: + +<pre>0 . . . . 0 4—5 +| | +2 . . . . 1 . 0 + | +1 . . 2 1—0 . 0 +| | +2 0—6 1 . . 3—5</pre> + +<span id="Dupe"></span> +==== DUPE - 3 ==== +Duplicate the top item on the stack. + +<span id="Roll"></span> +==== ROLL - 4 ==== +Pops one argument from the stack to be used as “depth”. + +* With a negative depth, the item at the <ins>top</ins> is moved to the <ins>nth depth</ins> +* With a positive depth, the item at the <ins>nth depth</ins> is moved to the <ins>top</ins> + +With roll you can implement common stack operations like <code>SWAP</code> and <code>ROT</code>: + +{| class="wikitable" +! Roll Depth +! Equivalent to +! Stack Before +! Stack After +|- +| -3 +| - +| <code>[a, b, c, d]</code> +| <code>[d, a, b, c]</code> +|- +| -2 +| ROTR +| <code>[a, b, c]</code> +| <code>[c, a, b]</code> +|- +| -1 +| SWAP +| <code>[a, b]</code> +| <code>[b, a]</code> +|- +| 0 +| NOOP +| <code>[a]</code> +| <code>[a]</code> +|- +| 1 +| SWAP +| <code>[a, b]</code> +| <code>[b, a]</code> +|- +| 2 +| ROTL +| <code>[a, b, c]</code> +| <code>[b, c, a]</code> +|- +| 3 +| - +| <code>[a, b, c, d]</code> +| <code>[b, c, d, a]</code> +|} + +<span id="Len"></span> +==== LEN - 5 ==== +Pushes the number of items on the stack. + +<span id="Clr"></span> +==== CLR - 6 ==== +Removes all items from the stack. + +<br> +=== Arithmetic === + +<span id="Add"></span> +==== ADD - 7 ==== +Pops 2 numbers from the stack. The sum is pushed to the stack. + +<span id="Sub"></span> +==== SUB - 8 ==== +Pops 2 numbers from the stack. The result of <code>numberA - numberB</code> is pushed to the stack. + +<span id="Mult"></span> +==== MULT - 9 ==== +Pops 2 numbers to multiply. The result is pushed to the stack. + +<span id="Div"></span> +==== DIV - 10 ==== +Pops 2 numbers. The result of the division of numberA by numberB is pushed to the stack. (Keep in mind that DominoScript is integer based and any remainder is discarded.) + +<span id="Mod"></span> +==== MOD - 11 ==== +Pops 2 numbers. The remainder of division of <code>numberA / numberB</code> is pushed to the stack. + +Note: When numberA is positive modulo behaves identical in most languages (afaik). However, there are some differences across programming languages when numberA is negative. In DominoScript modulo behaves like in JavaScript, Java, C++ and Go and <ins>NOT</ins> like in Python or Ruby! + +<span id="Neg"></span> +==== NEG - 12 ==== +Negate the top of the stack. + +<span id="Clamp"></span> +==== CLAMP -13 ==== +Pops 3 numbers from the stack: + +<pre>[..., value, min, max]</pre> + +And pushes back the clamped value onto the stack. + +<br> +=== Comparison &amp; Logical === + +<span id="Not"></span> +==== NOT - 14 ==== +Pops the top item off the stack. If it is <code>0</code>, it pushes <code>1</code>. Otherwise it pushes <code>0</code> to the stack. + +<span id="And"></span> +==== AND - 15 ==== +Pops the top 2 items off the stack, performs the logical AND operation and pushes the result back onto the stack. + +<span id="Or"></span> +==== OR - 16 ==== +Pops the top 2 items off the stack, performs the logical OR operation and push the result back onto the stack. + +<span id="Eql"></span> +==== EQL - 17 ==== +Pops the top 2 items off the stack, compares them and pushes the result back onto the stack. If the items are equal, it pushes <code>1</code> to the stack, otherwise <code>0</code>. + +<span id="Gtr"></span> +==== GTR - 18 ==== +Pops the top 2 items off the stack, compares them and pushes the result back onto the stack. If the first item is greater than the second, it pushes <code>1</code> to the stack, otherwise <code>0</code>. + +<span id="Eqlstr"></span> +==== EQLSTR -19 ==== +Assumes that 2 strings are on the stack. It pops them, compares them and pushes <code>1</code> to the stack if equal, otherwise <code>0</code>. + +'''<ins>For example:<ins>'''<br /> +You push the strings <code>&quot;AC&quot;</code> then <code>&quot;DC&quot;</code>. They are represented on the stack as <code>[NULL, C, A, NULL, C, D]</code> (In reality it is <code>[0, 67, 65, 0, 67, 68]</code>). Since the strings are not equal, it will push <code>0</code> to the stack. It is now <code>[0]</code>. + +'''<ins>Another example:<ins>'''<br /> +Imagine you want to check if the user pressed arrow left. You execute the <code>KEY</code> instruction after which the stack looks like <code>[&lt;existing&gt;, 0, 68, 91, 27]</code> then you push the <ins>escape sequence</ins> which represents the left arrow key. The stack is now <code>[&lt;existing&gt;, 0, 68, 91, 27, 0, 68, 91, 27]</code>. You then execute the <code>EQLSTR</code> instruction which will pop the top 2 strings and since the strings are equal, it will push <code>1</code> to the stack. It is now <code>[&lt;existing&gt;, 1]</code> ''(See the [[#Key|KEY]] instruction for more info about escape sequences)''. + +<span id="Reserved_20"></span> +==== RESERVED - 20 ==== +Unmapped opcode. Will throw <code>InvalidInstructionError</code> if executed. + +<br> +=== Bitwise === + +<span id="Bnot"></span> +==== BNOT - 21 ==== +Bitwise NOT. Pops the top item off the stack, inverts all bits and pushes the result back onto the stack. + +<span id="Band"></span> +==== BAND - 22 ==== +Bitwise AND. Pops the top 2 items off the stack, performs bitwise AND and pushes the result back onto the stack. + +<span id="Bor"></span> +==== BOR - 23 ==== +Bitwise OR. Pops the top 2 items off the stack, performs bitwise OR and pushes the result back onto the stack. + +<span id="Bxor"></span> +==== BXOR -24 ==== +Bitwise XOR. Pops the top 2 items off the stack, performs bitwise XOR and pushes the result back onto the stack. + +<span id="Lsl"></span> +==== LSL - 25 ==== +Logical Shift Left. Performs the equivalent of <code>argA &lt;&lt; argB</code> and pushes the result back onto the stack. + +<span id="Lsr"></span> +==== LSR - 26 ==== +Logical Shift Right. Performs the equivalent of <code>argA &gt;&gt;&gt; argB</code> and pushes the result back onto the stack. + +<span id="Asr"></span> +==== ASR - 27 ==== +Arithmetic Shift Right. Performs the equivalent of <code>argA &gt;&gt; argB</code> and pushes the result back onto the stack. + +<br> +=== Control Flow === + +<span id="Navm"></span> +==== NAVM - 28 ==== +Changes the Navigation Mode. The default Mode is <code>0</code>. + +See [[#Navigation_Modes|Navigation Modes]] to see all possible nav modes and their indexes. + +If you don't know what navigation modes are and how they influence the Instruction Pointer, I'd recommend reading the relevant section in [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]]. + +<span id="Branch"></span> +==== BRANCH - 29 ==== +Like an IF-ELSE statement. + +It pops the top of the stack as a condition and then: + +<pre style="letter-spacing:4px;line-height:1.1;"> +. . . . . 6 . . + | +. . . . . 6 . . + +0—1 0—1 4—1 . . + +. . . . . 5 . . + | +. . . . . 5 . . +</pre> + +* If popped value is a non-zero number: The IP will move to the relative '''LEFT''' (the <code>6-6</code>domino) +* If popped value is zero: The IP will move to the relative '''RIGHT''' (the <code>5-5</code>domino) + +When using branch, the current Navigation Mode is ignored. You can always be assured that the IP will either move to the relative left or right. + +<span id="Label"></span> +==== LABEL - 30 ==== +Label are like a bookmarks or an alternative identifier of a specific Cell address. They can be used by the <code>JUMP</code>, <code>CALL</code>, <code>GET</code> and <code>SET</code> instructions (although these also work directly with addresses, so labels are not mandatory) + +'''Labels are probably not what you expect them to be.''' +* They are '''NOT''' strings, but negative numbers. +* They are auto generated and self decrementing: <code>-1</code>, <code>-2</code>, <code>-3</code>, etc. +* You can kind of imagine them as pointers to a specific cell address. + +Executing the LABEL instruction pops the address of the cell you want to label and assigns it to the next available negative number. + +The negative number will '''NOT''' be pushed to the stack. First label will be <code>-1</code>, second label will be <code>-2</code> and so on. You need to keep track of them yourself. + +For clarity, I’d generally recommend adding comments like the following to your source files: + +<pre> +| Label | Address | Function name | +|-------|---------|---------------| +| -1 | 340 | main | +| -2 | 675 | update | +| -3 | 704 | render | +</pre> + +'''About Labels in imported files:''' +DominoScript has an <code>IMPORT</code> instruction that allows source files to be imported into others. The imported functions can only be called via labels, so in that regard a label also acts like an export. If the parent file doesn’t define labels of their own, the label values will be the same in both parent and child. However if the parent file creates labels <ins>before</ins> importing a child file, the exported child labels will have a different value in the parent. For example:<br /> +# Parent creates label <code>-1</code>, <code>-2</code>, <code>-3</code> and then imports the child file +# The child file defines labels <code>-1</code>, <code>-2</code>, <code>-3</code> and gives back control to parent +# The parent file will now have the labels <code>-1</code>, <code>-2</code>, <code>-3</code> and the child labels will be <code>-4</code>, <code>-5</code>, <code>-6</code> +# Now when the parent wants to call a child function which internally is labelled with <code>-1</code>, it needs to use label <code>-4</code> instead. + +<span id="Jump"></span> +==== JUMP - 31 ==== +Moves the IP to an address on the grid. You can either use a label or an address as an argument. + +If the IP cannot move anymore, the interpreter will throw a <code>StepToEmptyCellError</code>. +If label is unknown it will throw an <code>UnknownLabelError</code>. + +<span id="Call"></span> +==== CALL - 32 ==== +Like the name suggests, it is similar to a function call. When The IP cannot move anymore, it will return to the address from where it was called from. + +You can do recursive calls. An implementation should support a depth of at least 512 to be spec compliant. + +'''Alternative way to CALL''' Instead of doing <code>ǸUM 1 NEG CALL</code> to call by label, you can just do <code>OPCODE_100</code>. Why? Because labels are mapped to opcodes 100+. So when you create the labels <code>-1</code>, <code>-2</code>, <code>-3</code>, etc. they are automatically mapped to opcodes <code>100</code>, <code>101</code>, <code>102</code>. + +<span id="Import"></span> +==== IMPORT - 33 ==== +Pop a “string” from the stack to indicate the file name of the source file to import. + +On import the interpreter will load the file and start running it until its Instruction Pointer cannot move anymore. + +Labels defined in the imported file are accessible from the file which imports it. That means you can call functions from the imported file via the <code>CALL</code> instruction. + +If the importing file defined a label before the import, the labels from the imported file will have different identifiers. For example: +* <code>FileChild.ds</code> defines a label <code>-1</code>. +* <code>FileAParent.ds</code> defines labels <code>-1</code>, <code>-2</code>, then imports FileChilds.ds.s + +The <ins>internal</ins> label <code>-1</code> in <code>FileChild.ds</code> will be <code>-3</code> <ins>externally</ins> in <code>FileAParent.ds</code> because labels are always auto decrementing. '''Why?''' Because it is the simplest way to avoid conflicts and be able to use labels internally and externally. + +The data stack is shared between parent and all imported files. Apart from that, the parent and child imports run in their own contexts. Imported files can have imports themselves but you should avoid circular dependencies. + +If you import the same file into more than one other file, it will result in multiple instances of the imported file. This is probably not a problem as long as you are aware of it ''(It might even be useful if you treat imports of the same file as "objects instances")''. + +<span id="Wait"></span> +==== WAIT - 34 ==== +Pops the top item off the stack and waits for that many milliseconds before continuing. + +''Within DominoScript, you could simulate a delay with a ‘busy loop’ by using the TIME, GTR and BRANCH instructions within a loop. Internally an implementation is free to implement WAIT using a busy loop to avoid having to deal with asynchronous code. However, to be spec compliant it should ideally add some form of interrupt handling so the interpreter can be stopped when the user tries to exit (via e.g. Ctrl+C) even if the code is stuck in an infinite loop.'' + +<br> +=== Input &amp; Output === + +<span id="Numin"></span> +==== NUMIN - 35 ==== +Prompt the user for a number. The user input will be pushed to the stack. + +<span id="Numout"></span> +==== NUMOUT - 36 ==== +Pop the top item from the stack and output it to stdout. + +<span id="Strin"></span> +==== STRIN - 37 ==== +Prompt the user for a string. The user input will be pushed to the stack as individual Unicode characters in reverse order. + +So if the user inputs <code>&quot;yes&quot;</code>, the stack will look like this: + +<pre>[..., 0, 115, 101, 121]</pre> +For convenience you might often see the stack represented But remember that in reality it just stores int32s. + +<pre>[..., NUL 's', 'e', 'y']</pre> + +''Note: Since each char is pushed to the stack, the max input string length is limited to the available stack space. By default, the max stack size is 512 for the reference interpreter. This limit will likely be increased to ~64k'' + +<span id="Strout"></span> +==== STROUT - 38 ==== +Pops numbers (representing Unicode char codes) from the stack until it encounters a null terminator (number 0). It will then output the string to stdout. + +<ins> +'''There is one special case:''' +</ins> +If the parser encounters the <code>Unit Separator</code> (ascii 31), it stringifies the <ins>next</ins> number instead of treating it as a unicode char code. This is very useful to generate ANSI escape sequences like <code>\x1b[15;20H[-]</code> which tells the terminal to draw <code>[-]</code> at row 15 and column 20. Without the <code>Unit Separator</code> you would have to push the char code for 1, 5 and 2, 0 individually. This is a pain if you are dealing with dynamic numbers. The [[./examples/023_input_controls_advanced.md|example_023]] uses this to create an escape sequence. + +<span id="Key"></span> +==== KEY - 39 ==== +Check if the user pressed a specific key since the last reset with <code>KEYRES</code>. If the key was pressed, it pushes <code>1</code> to the stack, otherwise <code>0</code>. + +It pops a <ins>string sequence</ins> of the stack to represent the key you want to check for. + +Unlike <code>NUMIN</code> and <code>STRIN</code> it doesn’t block the program, so you can use it in a loop to check for user input. + +'''<ins>What string sequence?:</ins>''' - If a key is a printable character, the sequence is the Unicode value of the key. For example, to check if the user pressed the <code>a</code> key, you would push the string <code>a</code>. - If a key is a special key like arrow left, right etc, the sequence is an escape sequence. For example, to check if the user pressed the left arrow key, you would push the escape sequence <code>\u001b[D</code> to the stack. + +'''<ins>What is an escape sequence?:</ins>''' + +Escape sequences are sequences of characters that are used to represent special non-printable keyboard keys like arrow keys but can also be used to control terminal behavior, such as cursor position, text color and more. You can google them. Then just transform them to the correct domino sequence. + +<span id="Keyres"></span> +==== KEYRES - 40 ==== +Resets the state of all keys to “not pressed”. It is used in combination with <code>KEY</code> to check if a key was pressed since the last reset. It has no effect on the stack. + +Imagine you have a game running at 20fps. Every 50ms you check if the user pressed any of the arrow keys and act accordingly. Then at the end of the frame you reset the state of all keys to “not pressed” with <code>KEYRES</code>. + +<span id="Reserved_41"></span> +==== RESERVED - 41 ==== +Unmapped opcode. Will throw <code>InvalidInstructionError</code> if executed. + +''(Might be used as opcode for a <code>MOUSE</code> instruction which pushes the clickX and clickY position of the mouse since the last KEYRES reset)'' + +<br> +=== Misc === + +<span id="Get"></span> +==== GET - 42 ==== +Reads data from the board and pushes it to the stack. Takes 2 arguments from the stack: +* The type Index to parse it as. It indicates the type and the direction of the data. +* The address of the first domino half + +'''There are essentially 4 types you can parse it as''': +* '''Domino''': The value of the cell at the address and its connection. Essentially a single domino +* '''Unsigned Number''': A number between 0 to 2147483647 ''(Hold on! Why not 4294967295? Because the data stack uses int32 and 2147483647 is the max value you can have in the stack. “Unsigned” here doesn’t mean uint32, just that we don’t “waste” half a domino to represent the sign)''. +* '''Signed Number''': A number between -2147483648 to 2147483647 (int32 range). +* '''String''': A string is a sequence of null terminated unicode char codes. + +<ins> +'''And the following directions''' +</ins> +: + +* '''SingleStraightLine''': The IP moves in a straight line towards the <ins>connection direction of the cell at the address</ins>. No wrap around like in “RawIncrement” mode. If you have a 10x20 grid you can get at most 5 dominos in horizontal direction or 10 dominos in vertical direction. +* '''RawIncrement''' (to be implemented): Reads domino halfs using incrementing addresses. It disregards the grids bounds and wraps around from right edge left edge on the next line ''(Remember that addresses are essentially the indices to a 1D array of Cells which represent the Grid. Address 0 is at the top left of the grid. In a 10x10 grid, the largest address is 99 in the bottom right)'' + +'''Here a table of supported encoding type mappings:''' +{| class="wikitable" +! Type Index +! Type +! Direction +|- +| 0 +| Domino +| connection direction +|- +| 1 +| Unsigned Number +| SingleStraightLine +|- +| 2 +| Signed Number +| SingleStraightLine +|- +| 3 +| String +| SingleStraightLine +|- +| 4 (TODO) +| Unsigned Number +| RawIncrement +|- +| 5 (TODO) +| Signed Number +| RawIncrement +|- +| 6 (TODO) +| String +| RawIncrement +|} + +<span id="Set"></span> +==== SET - 43 ==== +Writes data to the board. Takes <ins>at least</ins> 2 arguments from the stack: +* The type Index to parse it as. It indicates the type and the direction of the data +* The address of the first domino half +* The data to write to the board. This can either be a single item from the stack or multiple if we write a string + +<ins> +'''There are essentially 4 types you can write it as''' +</ins> + +(See list under [[#Get|GET]]): + +<ins> +'''And the following directions''' +</ins> +: + +* '''SingleStraightLine''': The IP moves in a straight line towards the <ins>last Instruction Pointer direction</ins>. No wrap around like in “RawIncrement” mode. If you have a 10x20 grid you can set at most 5 dominos in horizontal direction or 10 dominos in vertical direction. +* '''RawIncrement''' (to be implemented): Writes domino halfs using incrementing addresses. It disregards the grids bounds and wraps around from right edge left edge on the next line ''(Remember that addresses are essentially the indices to a 1D array of Cells which represent the Grid. Address 0 is at the top left of the grid. In a 10x10 grid, the largest address is 99 in the bottom right)'' + +'''Here a table of supported type mappings:''' + +(See table under [[#Get|GET]]): + +<span id="Lit"></span> +==== LIT - 44 ==== +Changes how number and string literals are parsed. It pops a number from the stack to use as the “literal parse mode”. The popped number must be between 0 to 6. If the number is out of bounds, an <code>DSInvalidLiteralParseModeError</code> is thrown. + +'''If the popped argument is:''' +* <code>0</code>: Dynamic parse mode. Used by default. The first domino half of every number literal indicates how many more dominos should be parsed as part of the number. For string literals it is exactly the same but for each character. +* <code>1</code> to <code>6</code>: Static parse modes. Uses 1 to 6 dominos for each number literal or each character in a string literal. + +In the following 3 examples <code>&quot;Hello world&quot;</code> is encoded in 3 different ways: + +In Base7 with Literal Parse Mode 0 (default): + +<pre>// Every character requires 2 dominos to be encoded on dominos +0—2 1—2 0—6 1—2 0—3 1—2 1—3 1—2 1—3 1—2 1—6 1—0 4—4 1—2 3—0 1—2 1—6 1—2 2—2 1—2 1—3 1—2 0—2 0—0</pre> +In Base 16 with Literal Parse Mode 0: + +<pre>// Still every character requires 2 dominos to be encoded. Considering that we are in base 16, very wasteful! +0—2 1—0 6—8 1—0 6—5 1—0 6—c 1—0 6—c 1—0 6—f 1—0 2—0 1—0 7—7 1—0 6—f 1—0 7—2 1—0 6—c 1—0 6—4 0—0</pre> +In Base 16 with Literal Parse Mode 1: + +<pre>// Every character requires 1 domino to be encoded. +// Notice how now it is pretty much just hexadecimal +0—2 6—8 6—5 6—c 6—c 6—f 2—0 7—7 6—f 7—2 6—c 6—4 0—0</pre> +As you can see, <ins>changing the default parse mode can significantly reduce the amount of dominos required to encode strings</ins>. For numbers it is less impactful but can still be significant if you are working mostly within a specific range. + +<span id="Base"></span> +==== BASE - 45 ==== +Pops one number from the stack to use as the “base” for future parsing of dominos (opcodes, number literals, string literals) + +By default, DominoScript uses double six (D6) dominos to represent everything, so the default base is 7. + +The max cell value of half of a domino is always 1 less than the Base. So in base 7, the max value is 6. In base 10, the max value is 9. In base 16, the max value is 15 (aka <code>f</code>). + +If the number of dots on a domino half exceeds the max amount of possible dots for the current base, it is clamped! + +For example: when you are in Base 7 and the interpreter encounters a <code>f—f</code> domino, it will be parsed as <code>6—6</code>. If you are in base 10, it will be parsed as <code>9—9</code> etc. + +In below table you can see how the same domino sequence results in different decimal numbers depending on the base: + +{| class="wikitable" +! Domino Sequence +! Base 7 (D6) +! Base 10 (D9) +! Base 16 (D15) +|- +| <code>0—6</code> +| 6 +| 6 +| 6 +|- +| <code>0—9</code> +| 6 +| 9 +| 9 +|- +| <code>0—f</code> +| 6 +| 9 +| 15 +|- +| <code>1—6 6—6</code> +| 342 +| 666 +| 1638 +|- +| <code>1—9 9—9</code> +| 342 +| 999 +| 2457 +|- +| <code>1—f f—f</code> +| 342 +| 999 +| 4095 +|- +| <code>2—6 6—6 6—6</code> +| 16806 +| 66666 +| 419430 +|- +| <code>2—9 9—9 9—9</code> +| 16806 +| 99999 +| 629145 +|- +| <code>2—f f—f f—f</code> +| 16806 +| 99999 +| 1048575 +|} + +With a higher Base, you have access to higher opcodes without needing to switch to extended mode. + +{| class="wikitable" +! Base +! Opcode Range +|- +| 7 +| 0 to 48 +|- +| 10 +| 0 to 99 +|- +| 16 +| 0 to 255 +|} + +While the <ins>opcode-to-instruction</ins> mapping never changes, the <ins>domino-to-opcode</ins> mapping is completely different in each base. + +<span id="Ext"></span> +==== EXT - 46 ==== +Toggle extended mode on or off. If extended mode is active the interpreter will use 2 dominos instead of 1 for each instruction which extends the opcode range from 0-48 to 0-2400 when using Double six dominos. + +<span id="Time"></span> +==== TIME - 47 ==== +Pushes the milliseconds since program start to the stack. + +Useful for things like a gameloop, animations, cooldowns etc. + +<span id="Noop"></span> +==== NOOP - 48 ==== +No operation. The IP will move to the next domino without doing anything. + +Useful to move the IP to a specific address (e.g. start of loop body) or to “reserve” space in case you think that you might need to add more instructions later on and don’t want to move dominos around. + +<br> + +== Navigation Modes == + +If you don't know what navigation modes are and how they influence the Instruction Pointer, I'd recommend reading the relevant section in [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]]. + +''(F=Forward, L=Left, R=Right)'' + +There are <code>49</code> total navigation modes in DominoScript. This section should reference them all. + +''To be fully spec compliant an implementation should support all of them. However, when developing an interpreter, this has a rather low priority. With just the default nav mode priority (Forward, Left, Right) you can run any DS code as long as it doesn't execute the NAVM instruction to change it.'' + +=== Basic Three Way === +Out of three directions, the IP will prioritize moving to the one with the highest priority. + +{| class="wikitable" +! Index +! Priorities +! Domino -&gt; +|- +| 0 (Default) +| <code>Forward</code> <code>Left</code> <code>Right</code> +| <code>0—0</code> +|- +| 1 +| <code>Forward</code> <code>Right</code> <code>Left</code> +| <code>0—1</code> +|- +| 2 +| <code>Left</code> <code>Forward</code> <code>Right</code> +| <code>0—2</code> +|- +| 3 +| <code>Left</code> <code>Right</code> <code>Forward</code> +| <code>0—3</code> +|- +| 4 +| <code>Right</code> <code>Forward</code> <code>Left</code> +| <code>0—4</code> +|- +| 5 +| <code>Right</code> <code>Left</code> <code>Forward</code> +| <code>0—5</code> +|- +| 6 +| <code>RANDOM</code> +| <code>0—6</code> +|} + +=== Basic Two Way === + +Out of two directions, the IP will prioritize moving to the one with the highest priority. + +{| class="wikitable" +! Index +! Priorities +! Domino -&gt; +|- +| 7 +| <code>Forward</code> <code>Left</code> +| <code>1—0</code> +|- +| 8 +| <code>Forward</code> <code>Right</code> +| <code>1—1</code> +|- +| 9 +| <code>Left</code> <code>Forward</code> +| <code>1—2</code> +|- +| 10 +| <code>Left</code> <code>Right</code> +| <code>1—3</code> +|- +| 11 +| <code>Right</code> <code>Forward</code> +| <code>1—4</code> +|- +| 12 +| <code>Right</code> <code>Left</code> +| <code>1—5</code> +|- +| 13 +| <code>RANDOM</code> +| <code>1—6</code> +|} + +=== Basic One Way === +IP can only move in one direction. + +{| class="wikitable" +! Index +! Only Direction +! Domino -&gt; +|- +| 14 +| <code>Forward</code> +| <code>2—0</code> +|- +| 15 +| <code>Forward</code> +| <code>2—1</code> +|- +| 16 +| <code>Left</code> +| <code>2—2</code> +|- +| 17 +| <code>Left</code> +| <code>2—3</code> +|- +| 18 +| <code>Right</code> +| <code>2—4</code> +|- +| 19 +| <code>Right</code> +| <code>2—5</code> +|- +| 20 +| <code>RANDOM</code> +| <code>2—6</code> +|} + +=== Cycle Three Way === +The direction with the highest priority becomes the least prioritized in the next cycle. + +All 3 directions are available in all cycles. + +{| class="wikitable" +! Index +! Cycle 1 +! Cycle 2 +! Cycle 3 +! Domino -&gt; +|- +| 21 +| <code>F</code> <code>L</code> <code>R</code> +| <code>L</code> <code>R</code> <code>F</code> +| <code>R</code> <code>F</code> <code>L</code> +| <code>3—0</code> +|- +| 22 +| <code>F</code> <code>R</code> <code>L</code> +| <code>R</code> <code>F</code> <code>F</code> +| <code>L</code> <code>F</code> <code>R</code> +| <code>3—1</code> +|- +| 23 +| <code>L</code> <code>F</code> <code>R</code> +| <code>F</code> <code>R</code> <code>F</code> +| <code>R</code> <code>L</code> <code>F</code> +| <code>3—2</code> +|- +| 24 +| <code>L</code> <code>R</code> <code>F</code> +| <code>R</code> <code>F</code> <code>L</code> +| <code>F</code> <code>L</code> <code>R</code> +| <code>3—3</code> +|- +| 25 +| <code>R</code> <code>F</code> <code>L</code> +| <code>F</code> <code>L</code> <code>R</code> +| <code>L</code> <code>R</code> <code>F</code> +| <code>3—4</code> +|- +| 26 +| <code>R</code> <code>L</code> <code>F</code> +| <code>L</code> <code>F</code> <code>R</code> +| <code>F</code> <code>R</code> <code>L</code> +| <code>3—5</code> +|- +| 27 +| (unmapped) +| (unmapped) +| (unmapped) +| <code>3—6</code> +|} + +=== Cycle Two Way === +The direction with the highest priority becomes the least prioritized in the next cycle. + +Only 2 directions are available in a single cycle. + +{| class="wikitable" +! Index +! Cycle 1 +! Cycle 2 +! Cycle 3 +! Domino -&gt; +|- +| 28 +| <code>F</code> <code>L</code> +| <code>L</code> <code>R</code> +| <code>R</code> <code>F</code> +| <code>4—0</code> +|- +| 29 +| <code>F</code> <code>R</code> +| <code>R</code> <code>F</code> +| <code>L</code> <code>F</code> +| <code>4—1</code> +|- +| 30 +| <code>L</code> <code>F</code> +| <code>F</code> <code>R</code> +| <code>R</code> <code>L</code> +| <code>4—2</code> +|- +| 31 +| <code>L</code> <code>R</code> +| <code>R</code> <code>F</code> +| <code>F</code> <code>L</code> +| <code>4—3</code> +|- +| 32 +| <code>R</code> <code>F</code> +| <code>F</code> <code>L</code> +| <code>L</code> <code>R</code> +| <code>4—4</code> +|- +| 33 +| <code>R</code> <code>L</code> +| <code>L</code> <code>F</code> +| <code>F</code> <code>R</code> +| <code>4—5</code> +|- +| 34 +| (unmapped) +| (unmapped) +| (unmapped) +| <code>4—6</code> +|} + +=== Cycle One Way === +The direction with the highest priority becomes the least prioritized in the next cycle. + +Only 1 direction is available in a single cycle. + +{| class="wikitable" +! Index +! Cycle 1 +! Cycle 2 +! Cycle 3 +! Domino -&gt; +|- +| 35 +| <code>F</code> +| <code>L</code> +| <code>R</code> +| <code>5—0</code> +|- +| 36 +| <code>F</code> +| <code>R</code> +| <code>L</code> +| <code>5—1</code> +|- +| 37 +| <code>L</code> +| <code>F</code> +| <code>R</code> +| <code>5—2</code> +|- +| 38 +| <code>L</code> +| <code>R</code> +| <code>F</code> +| <code>5—3</code> +|- +| 39 +| <code>R</code> +| <code>F</code> +| <code>L</code> +| <code>5—4</code> +|- +| 40 +| <code>R</code> +| <code>L</code> +| <code>F</code> +| <code>5—5</code> +|- +| 41 +| (unmapped) +| (unmapped) +| (unmapped) +| <code>5—6</code> +|} + +=== Flip Flop === +The priority flip flops between 2 primary directions. + +{| class="wikitable" +! Index +! Flip +! Flop +! Domino -&gt; +|- +| 42 +| <code>F</code> +| <code>L</code> +| <code>6—0</code> +|- +| 43 +| <code>F</code> +| <code>R</code> +| <code>6—1</code> +|- +| 44 +| <code>L</code> +| <code>F</code> +| <code>6—2</code> +|- +| 45 +| <code>L</code> +| <code>R</code> +| <code>6—3</code> +|- +| 46 +| <code>R</code> +| <code>F</code> +| <code>6—4</code> +|- +| 47 +| <code>R</code> +| <code>L</code> +| <code>6—5</code> +|- +| 48 +| (unmapped) +| (unmapped) +| <code>6—6</code> +|} + +<br> +== Example: Factorial == + +<br>[[File:DominoScript-Example-Factorial-flow.png|thumb|Factorial Example with IP flow visualized]] + +'''Pseudocode:''' +<pre style="overflow:auto;> +NUM 12 +NUM 42 CALL +NUMOUT // prints 479001600 + +FUNCTION FACTORIAL: // (address 42) + DUP NUM 0 EQ + IF: + POP + NUM 1 + ELSE: + DUP NUM 1 SUB + NUM 42 CALL // recursive call + MUL +</pre> + +'''DominoScript:''' +<pre style="letter-spacing:4px;line-height:1.1;overflow:auto;"> +0—1 . . . . . 1—0 1—0 0 . . . 2—1 4—4 0 + | | +0—1 . . . . . . . . . 0 . . . . . . . 6 + +1 . 0—3 0—1 0—0 2—3 4—1 . . . . . . . 0 +| | +5 . . . . . . . . . . 0 . . . . . . . 1 + | +0—1 1—0 6—0 4—4 5—1 . 3 0—1 0—1 1—1 0—1 +</pre> + +== Example: WASD Controls == + +Demonstrates `WASD` keyboard inputs that move a character around on a 5x7 grid and renders it via stdout. + +It could be used as a basis to build a simple game. + +[[File:DominoScript-Example-WASD-Input-Example-Flow.png|thumb|WASD Controls example with IP flow visualized]] + +'''Pseudocode''': +<pre style="overflow:auto;font-size:0.85em;> +NUM 16 BASE // tell interpreter to use dominos with up to 16 dots per side. Allowing you to use less dominos + +// Binding addresses to labels +NUM 116 LABEL // playerX -1 +NUM 122 LABEL // playerY -2 +NUM 1008 LABEL // topRow = "╭──────────────╮\n" -3 +NUM 1080 LABEL // middleRow = "│ │\n" -4 +NUM 1152 LABEL // bottomRow = "╰──────────────╯\n" -5 +NUM 72 LABEL // function main() -6 +NUM 361 LABEL // function update() -7 +NUM 505 LABEL // function render() -8 +NUM 660 LABEL // loop body start within render() -9 + +NUM 6 NEG CALL // main() + +FUNCTION main: + NUM 1 LIT // tell interpreter that we use exactly 1 domino for each number or character in a string + LOOP_FOREVER: + NUM 50 WAIT // wait 50ms + PUSH 7 NEG CALL // update() + PUSH 8 NEG CALL // render() + NUM 6 NEG JUMP // jump back to start of main + +FUNCTION update: + STR "w" KEY IF: + NUM 1 NUM 2 NEG GET NUM 1 SUB NUM 1 NUM 2 NEG SET // y = y - 1 + STR "a" KEY IF: + NUM 1 NUM 1 NEG GET NUM 2 SUB NUM 1 NUM 1 NEG SET // x = x - 2 + STR "s" KEY IF: + NUM 1 NUM 2 NEG GET NUM 1 ADD NUM 1 NUM 2 NEG SET // y = y + 1 + STR "d" KEY IF: + NUM 1 NUM 1 NEG GET NUM 2 ADD NUM 1 NUM 1 NEG SET // x = x + 2 + + NUM 1 NUM 1 NEG GET NUM 2 NUM 13 CLAMP NUM 1 NUM 1 NEG SET // x = clamp(x, 2, 13) + NUM 1 NUM 2 NEG GET NUM 2 NUM 6 CLAMP NUM 1 NUM 2 NEG SET // y = clamp(y, 2, 6) + KEYRES + +FUNCTION render: + STR '\033[2J\033[H' STDOUT // clear screen and move cursor to top left + NUM 0 // iterator = 0; + + LOOP: + DUPE NUM 0 EQL IF: // if (iterator === 0) + NUM 3 NUM 3 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Top row string if on row 0 + DUPE NUM 8 EQL IF: // if (iterator === 8) + NUM 3 NUM 5 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Bottom row string if on row 8 + DUPE DUPE NUM 2 GTR NUM 1 ROLL NUM 7 GTR NOT AND IF: // if (iterator > 2 && iterator < 7) + NUM 3 NUM 4 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Middle row string if on row 1-7 + + NUM 1 ADD // iterator = iterator + 1 + + DUPE NUM 8 EQL IF: + // Hacky way to achieve the equivalent of: stdout.write(`\033[${playerY};${playerX}H[]`) + // The string is constructed 1 char at a time in reverse order using NUM + NUM 0 NUM 93 NUM 91 NUM 72 NUM 1 NUM 1 NEG GET NUM 31 NUM 59 NUM 1 NUM 2 NEG GET NUM 31 NUM 91 NUM 27 STROUT + POP // remove iterator from stack + BREAK // exit loop if we've reached the bottom row + + NUM 9 NEG JUMP // jump back to start of loop +</pre> + +'''DominoScript''': +<pre style="letter-spacing:2px;line-height:1.1;overflow:auto;font-size:0.85em;"> +0—1 1—0 2—2 6—3 0—1 1—0 7—4 1—e 0—1 1—0 7—a 1—e 0—1 1—3 f—0 1—e 0—1 1—4 3—8 1—e 0—1 1—4 8—0 1—e 0—1 1—0 4—8 1—e 0—1 1—1 6—9 1—e 0—1 1—2 8—8 1—e + +0—1 0—1 2—c 0—1 3—2 2—2 0—1 0—7 0—c 2—0 0—1 0—8 0—c 2—0 0—1 0—6 0—c 1—f . . . . . . 0—0 0—8 . . 0—0 0—4 . . . . 0—2 c—0 6—0 1—0 e—1 4—9 2—1 1—0 + +0—8 0—1 0—1 0—1 0—2 0—c 2—b 3—0 3 . 0—8 0—1 0—1 0—1 0—1 0—c 2—b 3—0 3 . 0—7 0—1 0—1 0—1 0—2 0—c 2—b 3—0 3 . 0—7 0—1 0—1 0—1 0—1 0—c 2—b 3—0 3 . + | | | | +1 . . . . . . . . . . . . . . . 0 . 2 . . . . . . . . . . . . . . . 0 . 1 . . . . . . . . . . . . . . . 0 . 2 . . . . . . . . . . . . . . . 0 . +| | | | +0 1—0 a—2 c—0 2—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 1—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 2—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 1—0 1—0 1—0 1—0 d 3 . + | | | | | | | | +. 3—0 3—0 3—0 0—2 7—7 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 6—1 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 7—3 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 6—4 0—0 2—7 1 0 3 + | +2 0—3 0—3 b—2 c—0 2—0 1—0 1—0 . . 6—0 1—0 2—0 1—0 a—2 c—0 2—0 1—0 . . 0—3 0—3 0—3 b—2 c—0 1—0 1—0 1—0 . . e—0 1—0 2—0 1—0 a—2 c—0 1—0 1—0 . . 0 +| +8 . 5—b 3 . 5—b 4 . 0—1 0 . 1—0 d—0 . . 0—1 0—3 0—3 0—c 0—1 0 . 1—0 1—0 0—1 0 . . . 3—0 3—0 1 . . . 1—0 d—0 2—a 0 . 0—2 0 . 1—b 2 . . . 1—0 1—0 + | | | | | | | | | +. . b . 2 . b . 8 . 6 . 0 . . 0—0 1—1 1—d 0 c—2 1—0 0—0 1—0 2 2 . 2—a 2—6 . 0 0 . 1—1 . . 0 d 0—1 . . . . . c . 1 . 1 . c . 1 . 6 . . . . . . . + | | | | | | | | | | +0—2 1 . 4—a 1 . 0—0 2 . 0—3 0—1 . . . 3—0 3 . . . . 0—1 0 6 . c 2—c . . . . . 1 . 9 . . 0 1 . . 0 . 0—1 4 . 0 . 1 . 0 . 2 . 0 . 0 . . . . . . . + | | | | | | | | | +. . . . . . . . . . . . . 1 1—1 8—0 1—0 0—3 . . . 0—3 . 4 2 a—2 2 . . 3 0—3 c—2 . 0 . 0 9 . . . 0 . b . 8 . 1 . f . 1 . a . b . 0 . . . . . . . + | | | | | | | | +. 0—3 0—3 0—3 0—3 0—3 0—3 d 0—1 0—3 0—1 0—5 3—0 . 1 . . 0—c 0—1 0 . . 0 . . 0—3 0—1 . c . . . . 0 . 5 . 0 . 0 . 0 . 0 . 0 . 5 . . . . . . . . . + | | | | | +3—0 c—2 1—0 0—0 1—0 6—2 a—2 c—2 2—0 1—0 c—0 0—3 . 0 d 3—0 3—0 3—0 3—0 0—1 . 7 . . . f—1 . . . . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . . . . . . . . . + | | | | | | +0—3 0—1 0—2 1—2 0—1 0—1 0—4 0—1 0—7 1—2 0—e 0—f 3—0 1 . . . . . . . . . 0—1 0 . . . . . . . . . 5—d 0 . 0—1 0 . 3—b 0 . 1—f 0 . . . . . . . . . + +2—5 6—d 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 6—e 0—0 0—a 0—0 0—0 + +2—5 0—2 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 2—5 0—2 0—0 0—a 0—0 0—0 + +2—5 7—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 6—f 0—0 0—a 0—0 0—0 +</pre> + +==External resources== +* [https://dominoscript.com Website with code playground] +* [https://github.com/andreas-schoch/dominoscript GitHub Repository containing reference implementations, examples and documentations] + + +[[Category:Languages]] +[[Category:Stack-based]] +[[Category:Implemented]] +[[Category:Self-modifying]] +[[Category:Turing complete]] +[[Category:Low-level]] +[[Category:Thematic]] +[[Category:2024]] '
New page size (new_size)
63816
Old page size (old_size)
0
Lines added in edit (added_lines)
[ 0 => '{{infobox proglang', 1 => '|image=File:Dominoscript-logo.png', 2 => '|name=DominoScript', 3 => '|author=[[User:Galvandi]]', 4 => '|year=[[:Category:2024|2024]]', 5 => '|paradigms=imperative', 6 => '|memsys=[[:Category:Stack-based|Stack-based]]', 7 => '|dimensions=[[:Category:Two-dimensional languages|two-dimensional]]', 8 => '|class=[[:Category:Turing complete|Turing complete]]', 9 => '|majorimpl=[https://github.com/andreas-schoch/dominoscript Github Repo]', 10 => '|files=<code>.ds</code> recommended', 11 => '}}'''DominoScript''' is a two-dimensional self-modifying [[esoteric programming language]] that uses the dots on domino pieces to represent code.', 12 => '', 13 => '== Core Concepts ==', 14 => ''''<code>Domino Pieces</code>''':', 15 => '* A domino piece can be placed either horizontally or vertically.', 16 => '* DominoScript by default uses Double-Six (aka <code>D6</code>) dominos to represent code. Double-six here means that each domino has 2 sides with up to 6 dots each. Essentially Base7.', 17 => '* Using the [[#Base|BASE]] instruction, you can tell the interpreter to parse dominos with up to 16 dots on each side. Allowing you to represent larger numbers with fewer dominos.', 18 => ''''<code>Stack-Oriented</code>''':', 19 => '* There is a global data stack that all instructions operate on.', 20 => '* By default, the stack size is limited to 512 items (Up to the implementation to make this configurable. The default of the reference interpreter might become significantly larger with a future version).', 21 => '* At its core, DS is just another concatenative [[Postfix notation|reverse-polish]] language. The following code: <code style="border-color:gray;">0—1 0—5 0—1 0—6 1—0 0—3 1—2 5—1</code> is the same as <code style="border-color:gray;">5 6 + dup * .</code> in [[Forth]].', 22 => '* Internally every item on the stack is a signed 32-bit integer.', 23 => '* Strings are just null-terminated sequences of integers representing Unicode char codes.', 24 => '* Floats are not supported ''(Fixed-point-arithmetic might be supported in future versions)''.', 25 => '* No other data structures exist.', 26 => '', 27 => ''''<code>Two-Dimensional</code>''':', 28 => '* The code is represented on a rectangle grid of cells. The top-left cell is address 0. The bottom-right cell is address <code>cols * rows - 1</code>.', 29 => '* Any implementation needs to support a grid of at least 65408 total cells to be spec compliant. That allows a square grid of up to `256x256` cols and rows or any smaller rectangular grid within the cell limit. Each cell needs to be indexable using an <code>int32</code> popped from the data stack, so well optimized implementations may support crazy amounts of cells.', 30 => '* The Instruction Pointer (IP) can move in any cardinal direction. Direction changes are performed by placing dominos in a certain way (IP always moves from one half to the other half of the same domino) as well as the current Navigation Mode. See: [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]].', 31 => '', 32 => ''''<code>Self-Modifying</code>''':', 33 => '* The code can override itself somewhat similar to befunge. See [[#Get|GET]] and [[#Set|SET]] instructions.', 34 => '* Getting and setting can be done using different encodings:', 35 => '** '''domino''': get or set single domino', 36 => '** '''unsigned number''': get or set a number within the int32 range ''(why not uint32? Because the stack only supports int32 so there is no point)''. Up to 7 dominos can be parsed per get/set.', 37 => '** '''signed number''': get or set a number within the int32 range. Up to 7 dominos can be parsed per get/set. The only different to unsigned number encoding is that here the first half of the first domino is sacrificed to encode the "sign bit" (if first half is anything but 0, sign bit is on).', 38 => '** '''string''': Get or set a whole string.', 39 => '* Can be used as a secondary data store ''(to act somewhat similar to registers or variables)'' besides the stack.', 40 => '', 41 => ''''<code>Multiple Files</code>''':', 42 => '* You can split up DS code into multiple files and include them in the main file using the [[#Import|IMPORT]] instruction.', 43 => '* Each import has its own grid of cells.', 44 => '* The data stack is shared between the main and all imported files.', 45 => '* Defining a label within an imported file during the import phase, allows the parent to call functions within the child. Giving the parent essentially an interface to use the imported file as a library. ''(See the [[#Label|LABEL]] instruction for more info)''.', 46 => '', 47 => '== Text Format ==', 48 => 'The dots on dominos are represented using a text based format:', 49 => '* The digits <code>0</code> to <code>f</code> represent the dots on half of a domino. To indicate an empty cell, use a dot <code>.</code>', 50 => '* The “long hyphen” character <code>—</code> indicates a horizontal domino ''(regular hyphen <code>-</code> also accepted to make it easier to type)''. It can only appear on '''even''' columns and '''odd''' rows.', 51 => '* The “pipe” character <code>|</code> indicates a vertical domino. It can only appear on '''odd''' columns and '''even''' rows.', 52 => '* Any other line <ins>before</ins> and <ins>after</ins> the actual code is ignored. ''(Tip: Make use of this to add extensive comments. You will inevitable forget what your dominoscript code does, so consider including a 1:1 pseudocode implementation of the dominoscript code)''', 53 => '', 54 => 'The following DominoScript code ''(which prints "Hello world")'':', 55 => '', 56 => '<pre style="letter-spacing:4px;line-height:1.1;display:inline-block;border-color: black;">', 57 => '. . . . . . . . . . . . . . .', 58 => ' ', 59 => '. . . . . . . . 0—2 1 . 0—3 .', 60 => ' | ', 61 => '. 1 0—3 2—1 4—4 . . 2 . 2 1 .', 62 => ' | | | ', 63 => '. 2 . . . . . 0 . . 0—6 1 2 .', 64 => ' | ', 65 => '. 1—6 1—2 2 . 1 6—1 . . . 1 .', 66 => ' | | ', 67 => '. . . . . 2 . . . 2 . . . 3 .', 68 => ' | ', 69 => '. 1 3—1 2—1 . . . 1 3—1 2—1 .', 70 => ' | ', 71 => '. 2 0—2 0 . . . . . . . . . .', 72 => ' | ', 73 => '. . . . 0 5—3 . . . . . . . .', 74 => '</pre>', 75 => '', 76 => 'Is the equivalent of the following dominos:', 77 => '', 78 => '<br>[[File:DominoScript-Example-003-flow.png|400px|Hello world 2d]]', 79 => '', 80 => '', 81 => 'The grid doesn’t have to be a square but it must have a consistent number of columns and rows, otherwise an <code>InvalidGridError</code> will be thrown before execution starts:', 82 => '', 83 => '<table class="wikitable">', 84 => '<tr><th>GOOD ✅</th><th>BAD ❌</th></tr>', 85 => '<tr><td>', 86 => '<pre>. . . . . . . .', 87 => '', 88 => '. . . . . . . .', 89 => '', 90 => '. . . . . . . .', 91 => '', 92 => '. . . . . . . .</pre>', 93 => '</td>', 94 => '<td>', 95 => '<pre> . . . . . . .', 96 => '', 97 => '. . . . . . . .', 98 => '', 99 => '. . . . .', 100 => '', 101 => '. . . . . . .</pre>', 102 => '</td>', 103 => '</tr>', 104 => '</table>', 105 => 'Connecting to a domino half which is already connected results in <code>MultiConnectionError</code>:', 106 => '', 107 => '<table class="wikitable">', 108 => '<tr><th>GOOD ✅</th><th>BAD ❌</th></tr>', 109 => '<tr><td>', 110 => '<pre>6—6 6—6 .', 111 => '', 112 => '6 6—6 . .', 113 => '|', 114 => '6 . . . .</pre>', 115 => '</td>', 116 => '<td>', 117 => '<pre>6—6—6—6 .', 118 => '', 119 => '6—6 . . .', 120 => '|', 121 => '6 . . . .</pre>', 122 => '</td>', 123 => '</tr>', 124 => '</table>', 125 => 'Having a domino half that is not connected to anything results in <code>MissingConnectionError</code>:', 126 => '', 127 => '<table class="wikitable">', 128 => '<tr><th>GOOD ✅</th><th>BAD ❌</th></tr>', 129 => '<tr><td>', 130 => '<pre>. . 6—6 .', 131 => '', 132 => '. 6 . . .', 133 => ' |', 134 => '. 6 . . .</pre>', 135 => '</td>', 136 => '<td>', 137 => '<pre>. . 6 6 .', 138 => '', 139 => '. 6 . . .', 140 => ' ', 141 => '. 6 . . .</pre>', 142 => '</td>', 143 => '</tr>', 144 => '</table>', 145 => 'Having a connection where 1 or both ends are empty results in a <code>ConnectionToEmptyCellError</code>:', 146 => '', 147 => '<table class="wikitable">', 148 => '<tr><th>GOOD ✅</th><th>BAD ❌</th></tr>', 149 => '<tr><td>', 150 => '<pre>6—6 . 6—6', 151 => '', 152 => '6 . . . 6', 153 => '| |', 154 => '6 . . . 6</pre>', 155 => '</td>', 156 => '<td>', 157 => '<pre>6—. . .—6', 158 => '', 159 => '6 . . . .', 160 => '| |', 161 => '. . . . 6</pre>', 162 => '</td>', 163 => '</tr>', 164 => '</table>', 165 => '', 166 => '== How Dominos are parsed into Numbers ==', 167 => 'It is important to understand that '''internally''' everything in DominoScript is represented as signed 32-bit Integers and '''externally''' everything is represented by the dots on the domino pieces.', 168 => '', 169 => ''''Every domino is part of either''':', 170 => '* An opcode - decides which instruction to execute next. By default, one domino represents one opcode unless you tell the interpreter to use 2 dominos per opcode using the [[#Ext|EXT]] instruction.', 171 => '* A number literal - the [[#Num|NUM]] instruction is used to push a single Integer onto the stack.', 172 => '* A string literal - the [[#Str|STR]] instruction is used to push a sequence of Integers onto the stack which represent unicode char codes.', 173 => '', 174 => ''''Furthermore, you should also be aware of the following things''':', 175 => '* The number base system that is currently set influences how dots are parsed into numbers. The base can be changed using the [[#Base|BASE]] instruction. (Default: Base 7 - because double-six dominos are the most common).', 176 => '* The "LiteralParseMode" tells the interpreter how many dominos will be part of a literal. It can be changed using the [[#Lit|LIT]] instruction (Default: dynamic - first half of first domino decides how many more are part of a number literal).', 177 => '* Once a literal is pushed on the stack, it is your job as the developer to keep track of which items are numbers and which ones are characters of a string. You can use any instruction on characters of a “string” but only the following ones will treat them as such: [[#Str|STR]], [[#Eqlstr|EQLSTR]], [[#Strin|STRIN]], [[#Strout|STROUT]] as well as [[#Get|GET]] and [[#Set|SET]] when used with the "string" encoding type.', 178 => '', 179 => 'In examples, you might see stack items that are meant to be char codes, represented in the following way:”', 180 => '', 181 => '<pre>[..., 1, 2, 3 'NUL', 's', 'e', 'y']</pre>', 182 => 'But in reality, the stack will store them as integers and look like this:', 183 => '', 184 => '<pre>[..., 1, 2, 3, 0, 115, 101, 121]</pre>', 185 => '', 186 => ''''What about floats?'''', 187 => '', 188 => 'Floats don’t exist in DominoScript. I’d suggest scaling up numbers by a factor of 10, 100, 1000 or whatever precision you need.', 189 => '', 190 => '''(I know that pico-8 uses 32-bits for numbers but treats them as 16.16 fixed point numbers. I am not quite sure if that is just a convention or if pico8’s API actually treats them as fixed-point numbers. I would like to eventually add some trigonometry instructions to DominoScript but am unsure what the most practical way would be)''', 191 => '', 192 => '== How the Instruction Pointer Moves ==', 193 => 'The Instruction Pointer (<code>IP</code>) keeps track of the current cell address that will be used for the next instruction. Since DominoScript is 2D, it isn’t obvious where the IP will move to without understanding the fundamental rules and the Navigation Modes.', 194 => '', 195 => ''''Before the program starts:'''', 196 => '# The interpreter will scan the grid from '''top-left to top-right''', move down and repeat until it finds the first domino.', 197 => '# Upon reaching the first domino, the IP is placed at the address of the first found domino half.', 198 => '# If no domino could be found, the program is considered finished.', 199 => '', 200 => ''''During the program execution:'''<br>', 201 => 'The IP will adhere to the following rules:', 202 => '* The IP can move in cardinal directions, never diagonally. How dominos are parsed, is all relative to that. For example, the horizontal domino <code>3—5</code> can be interpreted as the base7 number <code>35</code> (IP moves eastwards) or <code>53</code> (IP moves westwards). Same thing for vertical dominos.', 203 => '* The IP will always move from one half (entry) of the same domino to the other half (exit) of the same domino.', 204 => '* If the IP cannot move to a new domino, the program is considered finished.', 205 => '* At the exit half of a domino, the IP will never move back to the entry half. It will always try to move to a new domino. That means, there are at most 0 to 3 potential options for the IP to move.', 206 => '* When the IP needs to move to a new domino, it is possible that there are no valid moves despite there being dominos around. The [[#Navigation_Modes|Navigation Mode]] decides where the IP can and cannot move next.', 207 => '', 208 => ''''Understanding Navigation Modes:'''<br>', 209 => 'Navigation Modes are predefined priority patterns which are used when the Instruction Pointer needs to decide to which domino to move to next. The [[#Navm|NAVM]] instruction can be used to change the current Navigation Mode. ', 210 => '', 211 => 'Understanding the following concepts will become very important:', 212 => '* '''Priority Directions''': Primary, Secondary, Tertiary', 213 => '* '''Relative Directions''': Forward, Left, Right', 214 => '* '''Cardinal Directions''': North, East, South, West', 215 => '', 216 => 'The Cardinal directions don’t matter much. It is all about the '''direction in relation to the exit half''' of the current domino ''(If you ever did any kind of GameDev you probably know the difference between world space and local space. It’s kind of like that)''', 217 => '', 218 => 'When the IP moves to a new domino, the half it enters to is called the “'''entry'''” while the other half is called the “'''exit'''”. Now from the perspective of the exit half, the IP can potentially move in 3 directions: Forward, Left, Right. These are the '''Relative Directions'''.', 219 => '', 220 => 'Which relative direction the IP chooses, depends on the current Navigation Mode. Below you will see the mapping of the very basic nav modes:', 221 => '', 222 => '{| class="wikitable"', 223 => '|-', 224 => '! Index !! <code>Primary</code> !! <code>Secondary</code> !! <code>Tertiary</code>', 225 => '|-', 226 => '| 0 || Forward || Left || Right', 227 => '|-', 228 => '| 1 || Forward || Right || Left', 229 => '|-', 230 => '| 2 || Left || Forward || Right', 231 => '|-', 232 => '| 3 || Left || Right || Forward', 233 => '|-', 234 => '| 4 || Right || Forward || Left', 235 => '|-', 236 => '| 5 || Right || Left || Forward', 237 => '|-', 238 => '| ... || ... || ... || ...', 239 => '|}', 240 => '''The “index” here is the argument for the <code>NAVM</code>instruction.''', 241 => '', 242 => '<br>', 243 => '', 244 => ''''If we imagine the <code>6</code> to be the exit half, what will be the next domino the IP moves to?:'''', 245 => '', 246 => '<table class="wikitable" style="line-height:1.1;letter-spacing:4px;">', 247 => '<tr>', 248 => '<th>East</th>', 249 => '<th>West</th>', 250 => '<th>South</th>', 251 => '<th>North</th>', 252 => '</tr>', 253 => '<tr>', 254 => '<td>', 255 => '<pre>', 256 => '. 2 . . .', 257 => ' |', 258 => '. 2 . . .', 259 => '', 260 => '5—6 1—1 .', 261 => '', 262 => '. 3 . . .', 263 => ' |', 264 => '. 3 . . .', 265 => '</pre>', 266 => '</td>', 267 => '<td>', 268 => '<pre>', 269 => '. . . 3 .', 270 => ' |', 271 => '. . . 3 .', 272 => '', 273 => '. 1—1 6—5', 274 => '', 275 => '. . . 2 .', 276 => ' |', 277 => '. . . 2 .', 278 => '</pre>', 279 => '</td>', 280 => '<td>', 281 => '<pre>', 282 => '. . 5 . .', 283 => ' |', 284 => '3—3 6 2—2', 285 => '', 286 => '. . 1 . .', 287 => ' |', 288 => '. . 1 . .', 289 => '', 290 => '. . . . .', 291 => '</pre>', 292 => '</td>', 293 => '<td>', 294 => '<pre>', 295 => '. . . . .', 296 => '', 297 => '. . 1 . .', 298 => ' |', 299 => '. . 1 . .', 300 => '', 301 => '2—2 6 3—3', 302 => ' |', 303 => '. . 5 . .', 304 => '</pre>', 305 => '</td>', 306 => '</tr>', 307 => '</table>', 308 => '''All 4 snippets are exactly the same code with the difference that they are all flipped differently. This is what I mean by the cardinal direction not mattering much in DominoScript.''', 309 => '', 310 => '* When <code>index 0</code>, the IP will move to <code>1—1</code> (Primary, Forward)', 311 => '* When <code>index 1</code>, the IP will move to <code>1—1</code> (Primary, Forward)', 312 => '* When <code>index 2</code>, the IP will move to <code>2—2</code> (Primary, Left)', 313 => '* When <code>index 3</code>, the IP will move to <code>2—2</code> (Primary, Left)', 314 => '* When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right)', 315 => '* When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right)', 316 => '', 317 => '<br>', 318 => '', 319 => ''''What if we remove the <code>1—1</code> domino? Where will the IP go to then?:'''', 320 => '', 321 => '<table class="wikitable" style="line-height:1.1;letter-spacing:4px;">', 322 => '<tr>', 323 => '<th>East</th>', 324 => '<th>West</th>', 325 => '<th>South</th>', 326 => '<th>North</th>', 327 => '</tr>', 328 => '<tr>', 329 => '<td>', 330 => '<pre>. 2 . . .', 331 => ' |', 332 => '. 2 . . .', 333 => '', 334 => '5—6 . . .', 335 => '', 336 => '. 3 . . .', 337 => ' |', 338 => '. 3 . . .</pre>', 339 => '</td>', 340 => '<td>', 341 => '<pre>. . . 3 .', 342 => ' |', 343 => '. . . 3 .', 344 => '', 345 => '. . . 6—5', 346 => '', 347 => '. . . 2 .', 348 => ' |', 349 => '. . . 2 .</pre>', 350 => '</td>', 351 => '<td>', 352 => '<pre>. . 5 . .', 353 => ' |', 354 => '3—3 6 2—2', 355 => '', 356 => '. . . . .', 357 => ' ', 358 => '. . . . .', 359 => '', 360 => '. . . . .</pre>', 361 => '</td>', 362 => '<td>', 363 => '<pre>. . . . .', 364 => '', 365 => '. . . . .', 366 => ' ', 367 => '. . . . .', 368 => '', 369 => '2—2 6 3—3', 370 => ' |', 371 => '. . 5 . .</pre>', 372 => '</td>', 373 => '</tr>', 374 => '</table>', 375 => '* When <code>index 0</code>, the IP will move to <code>2—2</code> (Secondary, Left)', 376 => '* When <code>index 1</code>, the IP will move to <code>3—3</code> (Secondary, Right)', 377 => '* When <code>index 2</code>, the IP will move to <code>2—2</code> (Primary, Left)', 378 => '* When <code>index 3</code>, the IP will move to <code>2—2</code> (Primary, Left)', 379 => '* When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right)', 380 => '* When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right)', 381 => '', 382 => '<br>', 383 => '', 384 => ''''And what if we remove both the <code>1—1</code> and the <code>2—2</code> domino?:'''', 385 => '', 386 => '<table class="wikitable" style="line-height:1.1;letter-spacing:4px;">', 387 => '<tr>', 388 => '<th>East</th>', 389 => '<th>West</th>', 390 => '<th>South</th>', 391 => '<th>North</th>', 392 => '</tr>', 393 => '<tr>', 394 => '<td>', 395 => '<pre>. . . . .', 396 => ' ', 397 => '. . . . .', 398 => '', 399 => '5—6 . . .', 400 => '', 401 => '. 3 . . .', 402 => ' |', 403 => '. 3 . . .</pre>', 404 => '</td>', 405 => '<td>', 406 => '<pre>. . . 3 .', 407 => ' |', 408 => '. . . 3 .', 409 => '', 410 => '. . . 6—5', 411 => '', 412 => '. . . . .', 413 => ' ', 414 => '. . . . .</pre>', 415 => '</td>', 416 => '<td>', 417 => '<pre>. . 5 . .', 418 => ' |', 419 => '3—3 6 . .', 420 => '', 421 => '. . . . .', 422 => ' ', 423 => '. . . . .', 424 => '', 425 => '. . . . .</pre>', 426 => '</td>', 427 => '<td>', 428 => '<pre>. . . . .', 429 => '', 430 => '. . . . .', 431 => ' ', 432 => '. . . . .', 433 => '', 434 => '. . 6 3—3', 435 => ' |', 436 => '. . 5 . .</pre>', 437 => '</td>', 438 => '</tr>', 439 => '</table>', 440 => '* When <code>index 0</code>, the IP will move to <code>3—3</code> (Tertiary, Right)', 441 => '* When <code>index 1</code>, the IP will move to <code>3—3</code> (Secondary, Right)', 442 => '* When <code>index 2</code>, the IP will move to <code>3—3</code> (Tertiary, Right)', 443 => '* When <code>index 3</code>, the IP will move to <code>3—3</code> (Secondary, Right)', 444 => '* When <code>index 4</code>, the IP will move to <code>3—3</code> (Primary, Right)', 445 => '* When <code>index 5</code>, the IP will move to <code>3—3</code> (Primary, Right)', 446 => '', 447 => '<br>', 448 => '', 449 => 'These are only variations of the “Basic-Three-Way” kind of NavModes. See the [[#Navigation_Modes|Reference]] for a full list of available modes.', 450 => '', 451 => '== Instructions ==', 452 => '', 453 => 'Instructions are mapped to opcodes behind the scenes:', 454 => '', 455 => '* '''0-48''': Are the “core” instructions ''(2 have yet to be mapped)'' and are meant to fit within the value range a single “double-six” domino can represent.', 456 => '* '''49-99''': Reserved for future extensions of the language ''(e.g. fixed-point-arithmetic, helpers for more advanced string manipulation and such)''', 457 => '* '''100+''': Allow you as developer to extend the language yourself with non-standard behaviour. These opcodes are essentially alternative ways of calling by label. To learn more, see: [[#Call|CALL]], [[#Label|LABEL]] and [[#Import|IMPORT]] instructions.', 458 => '', 459 => 'To know which domino represents which opcode, you have to know the currently active [[#Base|base]]. For example, to represent opcode 48...:', 460 => '* in '''base7''' you use a '''<code>6—6</code>''' domino (default)', 461 => '* in '''base10''' you use a '''<code>4—8</code>''' domino', 462 => '* in '''base16''' you use a '''<code>3—0</code>''' domino', 463 => '', 464 => '<br>', 465 => '', 466 => 'The core instructions are grouped in 7 categories of 7 instructions each. Below, you will see them listed all.', 467 => '''(The numbers on the right beside the instruction titles are the corresponding opcode)''', 468 => '', 469 => '<br>', 470 => '=== Stack Management ===', 471 => '', 472 => '<span id="Pop"></span>', 473 => '==== POP - 0 ====', 474 => 'Discards the top of the stack.', 475 => '', 476 => '<span id="Num"></span>', 477 => '==== NUM - 1 ====', 478 => 'Switch to “number mode”. By default, the first half of the next domino will indicate how many dominos to read as a number. Then the other halfs will all be read as base7 digits (in D6 mode) to form the number that will be pushed to the stack.', 479 => '', 480 => 'With 7 dominos, 13 out of 14 halfs are used for the number. You can theoretically represent a number much larger than the max int32 value. However, if the number exceeds the maximum int32 value, it will wrap around from the minimum value, and vice versa ''(exactly the same as when doing bitwise operations in JS –&gt; <code>(96889010406 | 0) === -1895237402</code>)''.', 481 => '', 482 => 'You might think that since internally numbers are int32s, that we parse from base7 to two’s complement. That is not the case. We simple push the decimal version of the positive base7 number to the stack', 483 => '', 484 => ''''For example:'''', 485 => '', 486 => '* <code>0—0</code> represents the number <code>0</code> in both decimal and base7', 487 => '* <code>0—6</code> represents the number <code>6</code> in both decimal and base7', 488 => '* <code>1—6 6—6</code> represents the number <code>342</code> in decimal and <code>666</code> in base7', 489 => '* <code>2—6 6—6 6—6</code> represents the number <code>16,806</code> in decimal and <code>6,666</code> in base7', 490 => '* <code>6—6 6—6 6—6 6—6 6—6 6—6</code> represents the number <code>1,977,326,742</code> in decimal and <code>66,666,666,666</code> in base7 (about 92.1% of the max int32 value)', 491 => '* <code>6—0 1—0 4—1 3—4 2—1 1—1 6—1</code> represents the number <code>2,147,483,647</code> in decimal and <code>104,134,211,161</code> in base7 (exactly the max int32 value)', 492 => '* <code>6—6 6—6 6—6 6—6 6—6 6—6 6—6</code> represents the number -1,895,237,402. '''WHY?''': The actual decimal number the dominos represent is <code>96,889,010,406</code> which is ~45x larger than the max int32 value. It wraps around about that many times before it reaches the final value.', 493 => '', 494 => ''''What if numbers are read from the other directions?'''', 495 => '', 496 => '* <code>1—1 1—1</code>, <code>2—2 2—2 2—2</code> for example will be exactly the same numbers (216 in decimal) eastwards and westwards.', 497 => '* <code>1—2 3—1</code> when parsed backwards is <code>1—3 2—1</code> and can therefore represent different numbers if the IP moves to the east or to the west.', 498 => '* <code>1—6 6—6</code> represents 666 in base7 (342 in decimal) but when parsed backwards the interpreter will raise an <code>UnexpectedEndOfNumberError</code>. Remember that the first half of the first domino indicates how many more will follow. In this case it expects to read 6 more dominos but the number ends prematurely after 1 domino.', 499 => '', 500 => ''''What if I want to use a fixed amount of dominos for each number?'''', 501 => '', 502 => 'Use the [[#Lit|LIT]] instruction to permanently change how literals are parsed. For example with parse mode <code>2</code> it will use 2 dominos for each number. While <code>6—6 6—6</code> in default parse mode 0 results in <code>UnexpectedEndOfNumberError</code> (because it expects 6 more dominos to follow but only got 1 more), in parse mode <code>2</code> it represents the decimal number <code>2400</code>.', 503 => '', 504 => '<span id="Str"></span>', 505 => '==== STR - 2 ====', 506 => 'With <code>STR</code> you switch to “string mode” and can push multiple integers to the stack to represent Unicode characters.', 507 => '', 508 => 'The way the dominos are parsed to numbers is identical to <code>NUM</code>: First half of first domino indicates how many more will follow for a single number.', 509 => '', 510 => 'The difference is that it doesn’t stop with just one number. It will keep reading numbers until it encounters the NULL character represented by domino <code>0—0</code>.', 511 => '', 512 => 'Only once the interpreter does encounter the NULL character, will it push the characters to the stack in <ins>reverse</ins> order.', 513 => '', 514 => '''(Note: I decided to parse strings like this because I wanted a single int32 based stack and, out of all options I could think of, this one felt the least annoying. If you can think of better ways, I am open for suggestions!)''', 515 => '', 516 => 'This is how you push the string <code>&quot;hi!&quot;</code> to the stack and output it:', 517 => '', 518 => '<pre>0—2 1—2 0—6 1—2 1—0 1—0 4—5 0—0 5—3</pre>', 519 => 'It equals the following pseudo code: <code>STR &quot;hi!&quot; STROUT</code>', 520 => '', 521 => '* <code>0—2</code> is the <code>STR</code> instruction', 522 => '* <code>1—2 0—6</code> is the Unicode value 105 representing the character <code>h</code>', 523 => '* <code>1—2 1—0</code> is the Unicode value 105 representing the character <code>i</code>', 524 => '* <code>0—0 4—5</code> is the Unicode value 33 representing the character <code>!</code>', 525 => '* <code>0—0</code> is the Unicode value for the NULL character which terminates the string.', 526 => '* <code>5—3</code> is the [[#Strout|STROUT]] instruction. It will pop items from the stack, parse them as Unicode chars and once it encounters the NULL character, it will output the string to stdout all at once.', 527 => '', 528 => 'This is the resulting stack:', 529 => '', 530 => '<table class="wikitable">', 531 => '<tr>', 532 => '<th>', 533 => 'Imaginative', 534 => '</th>', 535 => '<th>', 536 => 'Reality', 537 => '</th>', 538 => '</tr>', 539 => '<tr>', 540 => '<td>', 541 => '<pre>[..., 'NUL', '!', 'i', 'h']</pre>', 542 => '</td>', 543 => '<td>', 544 => '<pre>[..., 0, 33, 105, 104]</pre>', 545 => '</td>', 546 => '</tr>', 547 => '</table>', 548 => 'Keep in mind that the IP can move in 4 cardinal direction so the following variations would also push the string <code>&quot;hi!&quot;</code> to the stack:', 549 => '', 550 => 'IP moves right to left:', 551 => '', 552 => '<pre>3—5 0—0 5—4 0—1 0—1 2—1 6—0 2—1 2—0</pre>', 553 => 'IP moves in multiple directions:', 554 => '', 555 => '<pre>0 . . . . 0 4—5', 556 => '| |', 557 => '2 . . . . 1 . 0', 558 => ' |', 559 => '1 . . 2 1—0 . 0', 560 => '| | ', 561 => '2 0—6 1 . . 3—5</pre>', 562 => '', 563 => '<span id="Dupe"></span>', 564 => '==== DUPE - 3 ====', 565 => 'Duplicate the top item on the stack.', 566 => '', 567 => '<span id="Roll"></span>', 568 => '==== ROLL - 4 ====', 569 => 'Pops one argument from the stack to be used as “depth”.', 570 => '', 571 => '* With a negative depth, the item at the <ins>top</ins> is moved to the <ins>nth depth</ins>', 572 => '* With a positive depth, the item at the <ins>nth depth</ins> is moved to the <ins>top</ins>', 573 => '', 574 => 'With roll you can implement common stack operations like <code>SWAP</code> and <code>ROT</code>:', 575 => '', 576 => '{| class="wikitable"', 577 => '! Roll Depth', 578 => '! Equivalent to', 579 => '! Stack Before', 580 => '! Stack After', 581 => '|-', 582 => '| -3', 583 => '| -', 584 => '| <code>[a, b, c, d]</code>', 585 => '| <code>[d, a, b, c]</code>', 586 => '|-', 587 => '| -2', 588 => '| ROTR', 589 => '| <code>[a, b, c]</code>', 590 => '| <code>[c, a, b]</code>', 591 => '|-', 592 => '| -1', 593 => '| SWAP', 594 => '| <code>[a, b]</code>', 595 => '| <code>[b, a]</code>', 596 => '|-', 597 => '| 0', 598 => '| NOOP', 599 => '| <code>[a]</code>', 600 => '| <code>[a]</code>', 601 => '|-', 602 => '| 1', 603 => '| SWAP', 604 => '| <code>[a, b]</code>', 605 => '| <code>[b, a]</code>', 606 => '|-', 607 => '| 2', 608 => '| ROTL', 609 => '| <code>[a, b, c]</code>', 610 => '| <code>[b, c, a]</code>', 611 => '|-', 612 => '| 3', 613 => '| -', 614 => '| <code>[a, b, c, d]</code>', 615 => '| <code>[b, c, d, a]</code>', 616 => '|}', 617 => '', 618 => '<span id="Len"></span>', 619 => '==== LEN - 5 ====', 620 => 'Pushes the number of items on the stack.', 621 => '', 622 => '<span id="Clr"></span>', 623 => '==== CLR - 6 ====', 624 => 'Removes all items from the stack.', 625 => '', 626 => '<br>', 627 => '=== Arithmetic ===', 628 => '', 629 => '<span id="Add"></span>', 630 => '==== ADD - 7 ====', 631 => 'Pops 2 numbers from the stack. The sum is pushed to the stack.', 632 => '', 633 => '<span id="Sub"></span>', 634 => '==== SUB - 8 ====', 635 => 'Pops 2 numbers from the stack. The result of <code>numberA - numberB</code> is pushed to the stack.', 636 => '', 637 => '<span id="Mult"></span>', 638 => '==== MULT - 9 ====', 639 => 'Pops 2 numbers to multiply. The result is pushed to the stack.', 640 => '', 641 => '<span id="Div"></span>', 642 => '==== DIV - 10 ====', 643 => 'Pops 2 numbers. The result of the division of numberA by numberB is pushed to the stack. (Keep in mind that DominoScript is integer based and any remainder is discarded.)', 644 => '', 645 => '<span id="Mod"></span>', 646 => '==== MOD - 11 ====', 647 => 'Pops 2 numbers. The remainder of division of <code>numberA / numberB</code> is pushed to the stack.', 648 => '', 649 => 'Note: When numberA is positive modulo behaves identical in most languages (afaik). However, there are some differences across programming languages when numberA is negative. In DominoScript modulo behaves like in JavaScript, Java, C++ and Go and <ins>NOT</ins> like in Python or Ruby!', 650 => '', 651 => '<span id="Neg"></span>', 652 => '==== NEG - 12 ====', 653 => 'Negate the top of the stack.', 654 => '', 655 => '<span id="Clamp"></span>', 656 => '==== CLAMP -13 ====', 657 => 'Pops 3 numbers from the stack:', 658 => '', 659 => '<pre>[..., value, min, max]</pre>', 660 => '', 661 => 'And pushes back the clamped value onto the stack.', 662 => '', 663 => '<br>', 664 => '=== Comparison &amp; Logical ===', 665 => '', 666 => '<span id="Not"></span>', 667 => '==== NOT - 14 ====', 668 => 'Pops the top item off the stack. If it is <code>0</code>, it pushes <code>1</code>. Otherwise it pushes <code>0</code> to the stack.', 669 => '', 670 => '<span id="And"></span>', 671 => '==== AND - 15 ====', 672 => 'Pops the top 2 items off the stack, performs the logical AND operation and pushes the result back onto the stack.', 673 => '', 674 => '<span id="Or"></span>', 675 => '==== OR - 16 ====', 676 => 'Pops the top 2 items off the stack, performs the logical OR operation and push the result back onto the stack.', 677 => '', 678 => '<span id="Eql"></span>', 679 => '==== EQL - 17 ====', 680 => 'Pops the top 2 items off the stack, compares them and pushes the result back onto the stack. If the items are equal, it pushes <code>1</code> to the stack, otherwise <code>0</code>.', 681 => '', 682 => '<span id="Gtr"></span>', 683 => '==== GTR - 18 ====', 684 => 'Pops the top 2 items off the stack, compares them and pushes the result back onto the stack. If the first item is greater than the second, it pushes <code>1</code> to the stack, otherwise <code>0</code>.', 685 => '', 686 => '<span id="Eqlstr"></span>', 687 => '==== EQLSTR -19 ====', 688 => 'Assumes that 2 strings are on the stack. It pops them, compares them and pushes <code>1</code> to the stack if equal, otherwise <code>0</code>.', 689 => '', 690 => ''''<ins>For example:<ins>'''<br />', 691 => 'You push the strings <code>&quot;AC&quot;</code> then <code>&quot;DC&quot;</code>. They are represented on the stack as <code>[NULL, C, A, NULL, C, D]</code> (In reality it is <code>[0, 67, 65, 0, 67, 68]</code>). Since the strings are not equal, it will push <code>0</code> to the stack. It is now <code>[0]</code>.', 692 => '', 693 => ''''<ins>Another example:<ins>'''<br />', 694 => 'Imagine you want to check if the user pressed arrow left. You execute the <code>KEY</code> instruction after which the stack looks like <code>[&lt;existing&gt;, 0, 68, 91, 27]</code> then you push the <ins>escape sequence</ins> which represents the left arrow key. The stack is now <code>[&lt;existing&gt;, 0, 68, 91, 27, 0, 68, 91, 27]</code>. You then execute the <code>EQLSTR</code> instruction which will pop the top 2 strings and since the strings are equal, it will push <code>1</code> to the stack. It is now <code>[&lt;existing&gt;, 1]</code> ''(See the [[#Key|KEY]] instruction for more info about escape sequences)''.', 695 => '', 696 => '<span id="Reserved_20"></span>', 697 => '==== RESERVED - 20 ====', 698 => 'Unmapped opcode. Will throw <code>InvalidInstructionError</code> if executed.', 699 => '', 700 => '<br>', 701 => '=== Bitwise ===', 702 => '', 703 => '<span id="Bnot"></span>', 704 => '==== BNOT - 21 ====', 705 => 'Bitwise NOT. Pops the top item off the stack, inverts all bits and pushes the result back onto the stack.', 706 => '', 707 => '<span id="Band"></span>', 708 => '==== BAND - 22 ====', 709 => 'Bitwise AND. Pops the top 2 items off the stack, performs bitwise AND and pushes the result back onto the stack.', 710 => '', 711 => '<span id="Bor"></span>', 712 => '==== BOR - 23 ====', 713 => 'Bitwise OR. Pops the top 2 items off the stack, performs bitwise OR and pushes the result back onto the stack.', 714 => '', 715 => '<span id="Bxor"></span>', 716 => '==== BXOR -24 ====', 717 => 'Bitwise XOR. Pops the top 2 items off the stack, performs bitwise XOR and pushes the result back onto the stack.', 718 => '', 719 => '<span id="Lsl"></span>', 720 => '==== LSL - 25 ====', 721 => 'Logical Shift Left. Performs the equivalent of <code>argA &lt;&lt; argB</code> and pushes the result back onto the stack.', 722 => '', 723 => '<span id="Lsr"></span>', 724 => '==== LSR - 26 ====', 725 => 'Logical Shift Right. Performs the equivalent of <code>argA &gt;&gt;&gt; argB</code> and pushes the result back onto the stack.', 726 => '', 727 => '<span id="Asr"></span>', 728 => '==== ASR - 27 ====', 729 => 'Arithmetic Shift Right. Performs the equivalent of <code>argA &gt;&gt; argB</code> and pushes the result back onto the stack.', 730 => '', 731 => '<br>', 732 => '=== Control Flow ===', 733 => '', 734 => '<span id="Navm"></span>', 735 => '==== NAVM - 28 ====', 736 => 'Changes the Navigation Mode. The default Mode is <code>0</code>.', 737 => '', 738 => 'See [[#Navigation_Modes|Navigation Modes]] to see all possible nav modes and their indexes.', 739 => '', 740 => 'If you don't know what navigation modes are and how they influence the Instruction Pointer, I'd recommend reading the relevant section in [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]].', 741 => '', 742 => '<span id="Branch"></span>', 743 => '==== BRANCH - 29 ====', 744 => 'Like an IF-ELSE statement.', 745 => '', 746 => 'It pops the top of the stack as a condition and then:', 747 => '', 748 => '<pre style="letter-spacing:4px;line-height:1.1;">', 749 => '. . . . . 6 . .', 750 => ' |', 751 => '. . . . . 6 . .', 752 => '', 753 => '0—1 0—1 4—1 . .', 754 => ' ', 755 => '. . . . . 5 . .', 756 => ' |', 757 => '. . . . . 5 . .', 758 => '</pre>', 759 => '', 760 => '* If popped value is a non-zero number: The IP will move to the relative '''LEFT''' (the <code>6-6</code>domino)', 761 => '* If popped value is zero: The IP will move to the relative '''RIGHT''' (the <code>5-5</code>domino)', 762 => '', 763 => 'When using branch, the current Navigation Mode is ignored. You can always be assured that the IP will either move to the relative left or right.', 764 => '', 765 => '<span id="Label"></span>', 766 => '==== LABEL - 30 ====', 767 => 'Label are like a bookmarks or an alternative identifier of a specific Cell address. They can be used by the <code>JUMP</code>, <code>CALL</code>, <code>GET</code> and <code>SET</code> instructions (although these also work directly with addresses, so labels are not mandatory)', 768 => '', 769 => ''''Labels are probably not what you expect them to be.'''', 770 => '* They are '''NOT''' strings, but negative numbers.', 771 => '* They are auto generated and self decrementing: <code>-1</code>, <code>-2</code>, <code>-3</code>, etc.', 772 => '* You can kind of imagine them as pointers to a specific cell address.', 773 => '', 774 => 'Executing the LABEL instruction pops the address of the cell you want to label and assigns it to the next available negative number.', 775 => '', 776 => 'The negative number will '''NOT''' be pushed to the stack. First label will be <code>-1</code>, second label will be <code>-2</code> and so on. You need to keep track of them yourself.', 777 => '', 778 => 'For clarity, I’d generally recommend adding comments like the following to your source files:', 779 => '', 780 => '<pre>', 781 => '| Label | Address | Function name |', 782 => '|-------|---------|---------------|', 783 => '| -1 | 340 | main |', 784 => '| -2 | 675 | update |', 785 => '| -3 | 704 | render |', 786 => '</pre>', 787 => '', 788 => ''''About Labels in imported files:'''', 789 => 'DominoScript has an <code>IMPORT</code> instruction that allows source files to be imported into others. The imported functions can only be called via labels, so in that regard a label also acts like an export. If the parent file doesn’t define labels of their own, the label values will be the same in both parent and child. However if the parent file creates labels <ins>before</ins> importing a child file, the exported child labels will have a different value in the parent. For example:<br />', 790 => '# Parent creates label <code>-1</code>, <code>-2</code>, <code>-3</code> and then imports the child file', 791 => '# The child file defines labels <code>-1</code>, <code>-2</code>, <code>-3</code> and gives back control to parent', 792 => '# The parent file will now have the labels <code>-1</code>, <code>-2</code>, <code>-3</code> and the child labels will be <code>-4</code>, <code>-5</code>, <code>-6</code>', 793 => '# Now when the parent wants to call a child function which internally is labelled with <code>-1</code>, it needs to use label <code>-4</code> instead.', 794 => '', 795 => '<span id="Jump"></span>', 796 => '==== JUMP - 31 ====', 797 => 'Moves the IP to an address on the grid. You can either use a label or an address as an argument.', 798 => '', 799 => 'If the IP cannot move anymore, the interpreter will throw a <code>StepToEmptyCellError</code>.', 800 => 'If label is unknown it will throw an <code>UnknownLabelError</code>.', 801 => '', 802 => '<span id="Call"></span>', 803 => '==== CALL - 32 ====', 804 => 'Like the name suggests, it is similar to a function call. When The IP cannot move anymore, it will return to the address from where it was called from.', 805 => '', 806 => 'You can do recursive calls. An implementation should support a depth of at least 512 to be spec compliant.', 807 => '', 808 => ''''Alternative way to CALL''' Instead of doing <code>ǸUM 1 NEG CALL</code> to call by label, you can just do <code>OPCODE_100</code>. Why? Because labels are mapped to opcodes 100+. So when you create the labels <code>-1</code>, <code>-2</code>, <code>-3</code>, etc. they are automatically mapped to opcodes <code>100</code>, <code>101</code>, <code>102</code>.', 809 => '', 810 => '<span id="Import"></span>', 811 => '==== IMPORT - 33 ====', 812 => 'Pop a “string” from the stack to indicate the file name of the source file to import.', 813 => '', 814 => 'On import the interpreter will load the file and start running it until its Instruction Pointer cannot move anymore.', 815 => '', 816 => 'Labels defined in the imported file are accessible from the file which imports it. That means you can call functions from the imported file via the <code>CALL</code> instruction.', 817 => '', 818 => 'If the importing file defined a label before the import, the labels from the imported file will have different identifiers. For example:', 819 => '* <code>FileChild.ds</code> defines a label <code>-1</code>.', 820 => '* <code>FileAParent.ds</code> defines labels <code>-1</code>, <code>-2</code>, then imports FileChilds.ds.s', 821 => '', 822 => 'The <ins>internal</ins> label <code>-1</code> in <code>FileChild.ds</code> will be <code>-3</code> <ins>externally</ins> in <code>FileAParent.ds</code> because labels are always auto decrementing. '''Why?''' Because it is the simplest way to avoid conflicts and be able to use labels internally and externally.', 823 => '', 824 => 'The data stack is shared between parent and all imported files. Apart from that, the parent and child imports run in their own contexts. Imported files can have imports themselves but you should avoid circular dependencies.', 825 => '', 826 => 'If you import the same file into more than one other file, it will result in multiple instances of the imported file. This is probably not a problem as long as you are aware of it ''(It might even be useful if you treat imports of the same file as "objects instances")''.', 827 => '', 828 => '<span id="Wait"></span>', 829 => '==== WAIT - 34 ====', 830 => 'Pops the top item off the stack and waits for that many milliseconds before continuing.', 831 => '', 832 => '''Within DominoScript, you could simulate a delay with a ‘busy loop’ by using the TIME, GTR and BRANCH instructions within a loop. Internally an implementation is free to implement WAIT using a busy loop to avoid having to deal with asynchronous code. However, to be spec compliant it should ideally add some form of interrupt handling so the interpreter can be stopped when the user tries to exit (via e.g. Ctrl+C) even if the code is stuck in an infinite loop.''', 833 => '', 834 => '<br>', 835 => '=== Input &amp; Output ===', 836 => '', 837 => '<span id="Numin"></span>', 838 => '==== NUMIN - 35 ====', 839 => 'Prompt the user for a number. The user input will be pushed to the stack.', 840 => '', 841 => '<span id="Numout"></span>', 842 => '==== NUMOUT - 36 ====', 843 => 'Pop the top item from the stack and output it to stdout.', 844 => '', 845 => '<span id="Strin"></span>', 846 => '==== STRIN - 37 ====', 847 => 'Prompt the user for a string. The user input will be pushed to the stack as individual Unicode characters in reverse order.', 848 => '', 849 => 'So if the user inputs <code>&quot;yes&quot;</code>, the stack will look like this:', 850 => '', 851 => '<pre>[..., 0, 115, 101, 121]</pre>', 852 => 'For convenience you might often see the stack represented But remember that in reality it just stores int32s.', 853 => '', 854 => '<pre>[..., NUL 's', 'e', 'y']</pre>', 855 => '', 856 => '''Note: Since each char is pushed to the stack, the max input string length is limited to the available stack space. By default, the max stack size is 512 for the reference interpreter. This limit will likely be increased to ~64k''', 857 => '', 858 => '<span id="Strout"></span>', 859 => '==== STROUT - 38 ====', 860 => 'Pops numbers (representing Unicode char codes) from the stack until it encounters a null terminator (number 0). It will then output the string to stdout.', 861 => '', 862 => '<ins>', 863 => ''''There is one special case:'''', 864 => '</ins>', 865 => 'If the parser encounters the <code>Unit Separator</code> (ascii 31), it stringifies the <ins>next</ins> number instead of treating it as a unicode char code. This is very useful to generate ANSI escape sequences like <code>\x1b[15;20H[-]</code> which tells the terminal to draw <code>[-]</code> at row 15 and column 20. Without the <code>Unit Separator</code> you would have to push the char code for 1, 5 and 2, 0 individually. This is a pain if you are dealing with dynamic numbers. The [[./examples/023_input_controls_advanced.md|example_023]] uses this to create an escape sequence.', 866 => '', 867 => '<span id="Key"></span>', 868 => '==== KEY - 39 ====', 869 => 'Check if the user pressed a specific key since the last reset with <code>KEYRES</code>. If the key was pressed, it pushes <code>1</code> to the stack, otherwise <code>0</code>.', 870 => '', 871 => 'It pops a <ins>string sequence</ins> of the stack to represent the key you want to check for.', 872 => '', 873 => 'Unlike <code>NUMIN</code> and <code>STRIN</code> it doesn’t block the program, so you can use it in a loop to check for user input.', 874 => '', 875 => ''''<ins>What string sequence?:</ins>''' - If a key is a printable character, the sequence is the Unicode value of the key. For example, to check if the user pressed the <code>a</code> key, you would push the string <code>a</code>. - If a key is a special key like arrow left, right etc, the sequence is an escape sequence. For example, to check if the user pressed the left arrow key, you would push the escape sequence <code>\u001b[D</code> to the stack.', 876 => '', 877 => ''''<ins>What is an escape sequence?:</ins>'''', 878 => '', 879 => 'Escape sequences are sequences of characters that are used to represent special non-printable keyboard keys like arrow keys but can also be used to control terminal behavior, such as cursor position, text color and more. You can google them. Then just transform them to the correct domino sequence.', 880 => '', 881 => '<span id="Keyres"></span>', 882 => '==== KEYRES - 40 ====', 883 => 'Resets the state of all keys to “not pressed”. It is used in combination with <code>KEY</code> to check if a key was pressed since the last reset. It has no effect on the stack.', 884 => '', 885 => 'Imagine you have a game running at 20fps. Every 50ms you check if the user pressed any of the arrow keys and act accordingly. Then at the end of the frame you reset the state of all keys to “not pressed” with <code>KEYRES</code>.', 886 => '', 887 => '<span id="Reserved_41"></span>', 888 => '==== RESERVED - 41 ====', 889 => 'Unmapped opcode. Will throw <code>InvalidInstructionError</code> if executed.', 890 => '', 891 => '''(Might be used as opcode for a <code>MOUSE</code> instruction which pushes the clickX and clickY position of the mouse since the last KEYRES reset)''', 892 => '', 893 => '<br>', 894 => '=== Misc ===', 895 => '', 896 => '<span id="Get"></span>', 897 => '==== GET - 42 ====', 898 => 'Reads data from the board and pushes it to the stack. Takes 2 arguments from the stack:', 899 => '* The type Index to parse it as. It indicates the type and the direction of the data.', 900 => '* The address of the first domino half', 901 => '', 902 => ''''There are essentially 4 types you can parse it as''':', 903 => '* '''Domino''': The value of the cell at the address and its connection. Essentially a single domino', 904 => '* '''Unsigned Number''': A number between 0 to 2147483647 ''(Hold on! Why not 4294967295? Because the data stack uses int32 and 2147483647 is the max value you can have in the stack. “Unsigned” here doesn’t mean uint32, just that we don’t “waste” half a domino to represent the sign)''.', 905 => '* '''Signed Number''': A number between -2147483648 to 2147483647 (int32 range).', 906 => '* '''String''': A string is a sequence of null terminated unicode char codes.', 907 => '', 908 => '<ins>', 909 => ''''And the following directions'''', 910 => '</ins>', 911 => ':', 912 => '', 913 => '* '''SingleStraightLine''': The IP moves in a straight line towards the <ins>connection direction of the cell at the address</ins>. No wrap around like in “RawIncrement” mode. If you have a 10x20 grid you can get at most 5 dominos in horizontal direction or 10 dominos in vertical direction.', 914 => '* '''RawIncrement''' (to be implemented): Reads domino halfs using incrementing addresses. It disregards the grids bounds and wraps around from right edge left edge on the next line ''(Remember that addresses are essentially the indices to a 1D array of Cells which represent the Grid. Address 0 is at the top left of the grid. In a 10x10 grid, the largest address is 99 in the bottom right)''', 915 => '', 916 => ''''Here a table of supported encoding type mappings:''' ', 917 => '{| class="wikitable"', 918 => '! Type Index', 919 => '! Type', 920 => '! Direction', 921 => '|-', 922 => '| 0', 923 => '| Domino', 924 => '| connection direction', 925 => '|-', 926 => '| 1', 927 => '| Unsigned Number', 928 => '| SingleStraightLine', 929 => '|-', 930 => '| 2', 931 => '| Signed Number', 932 => '| SingleStraightLine', 933 => '|-', 934 => '| 3', 935 => '| String', 936 => '| SingleStraightLine', 937 => '|-', 938 => '| 4 (TODO)', 939 => '| Unsigned Number', 940 => '| RawIncrement', 941 => '|-', 942 => '| 5 (TODO)', 943 => '| Signed Number', 944 => '| RawIncrement', 945 => '|-', 946 => '| 6 (TODO)', 947 => '| String', 948 => '| RawIncrement', 949 => '|}', 950 => '', 951 => '<span id="Set"></span>', 952 => '==== SET - 43 ====', 953 => 'Writes data to the board. Takes <ins>at least</ins> 2 arguments from the stack:', 954 => '* The type Index to parse it as. It indicates the type and the direction of the data', 955 => '* The address of the first domino half', 956 => '* The data to write to the board. This can either be a single item from the stack or multiple if we write a string', 957 => '', 958 => '<ins>', 959 => ''''There are essentially 4 types you can write it as'''', 960 => '</ins>', 961 => '', 962 => '(See list under [[#Get|GET]]):', 963 => '', 964 => '<ins>', 965 => ''''And the following directions'''', 966 => '</ins>', 967 => ':', 968 => '', 969 => '* '''SingleStraightLine''': The IP moves in a straight line towards the <ins>last Instruction Pointer direction</ins>. No wrap around like in “RawIncrement” mode. If you have a 10x20 grid you can set at most 5 dominos in horizontal direction or 10 dominos in vertical direction.', 970 => '* '''RawIncrement''' (to be implemented): Writes domino halfs using incrementing addresses. It disregards the grids bounds and wraps around from right edge left edge on the next line ''(Remember that addresses are essentially the indices to a 1D array of Cells which represent the Grid. Address 0 is at the top left of the grid. In a 10x10 grid, the largest address is 99 in the bottom right)''', 971 => '', 972 => ''''Here a table of supported type mappings:'''', 973 => '', 974 => '(See table under [[#Get|GET]]):', 975 => '', 976 => '<span id="Lit"></span>', 977 => '==== LIT - 44 ====', 978 => 'Changes how number and string literals are parsed. It pops a number from the stack to use as the “literal parse mode”. The popped number must be between 0 to 6. If the number is out of bounds, an <code>DSInvalidLiteralParseModeError</code> is thrown.', 979 => '', 980 => ''''If the popped argument is:'''', 981 => '* <code>0</code>: Dynamic parse mode. Used by default. The first domino half of every number literal indicates how many more dominos should be parsed as part of the number. For string literals it is exactly the same but for each character.', 982 => '* <code>1</code> to <code>6</code>: Static parse modes. Uses 1 to 6 dominos for each number literal or each character in a string literal.', 983 => '', 984 => 'In the following 3 examples <code>&quot;Hello world&quot;</code> is encoded in 3 different ways:', 985 => '', 986 => 'In Base7 with Literal Parse Mode 0 (default):', 987 => '', 988 => '<pre>// Every character requires 2 dominos to be encoded on dominos', 989 => '0—2 1—2 0—6 1—2 0—3 1—2 1—3 1—2 1—3 1—2 1—6 1—0 4—4 1—2 3—0 1—2 1—6 1—2 2—2 1—2 1—3 1—2 0—2 0—0</pre>', 990 => 'In Base 16 with Literal Parse Mode 0:', 991 => '', 992 => '<pre>// Still every character requires 2 dominos to be encoded. Considering that we are in base 16, very wasteful!', 993 => '0—2 1—0 6—8 1—0 6—5 1—0 6—c 1—0 6—c 1—0 6—f 1—0 2—0 1—0 7—7 1—0 6—f 1—0 7—2 1—0 6—c 1—0 6—4 0—0</pre>', 994 => 'In Base 16 with Literal Parse Mode 1:', 995 => '', 996 => '<pre>// Every character requires 1 domino to be encoded.', 997 => '// Notice how now it is pretty much just hexadecimal', 998 => '0—2 6—8 6—5 6—c 6—c 6—f 2—0 7—7 6—f 7—2 6—c 6—4 0—0</pre>', 999 => 'As you can see, <ins>changing the default parse mode can significantly reduce the amount of dominos required to encode strings</ins>. For numbers it is less impactful but can still be significant if you are working mostly within a specific range.', 1000 => '', 1001 => '<span id="Base"></span>', 1002 => '==== BASE - 45 ====', 1003 => 'Pops one number from the stack to use as the “base” for future parsing of dominos (opcodes, number literals, string literals)', 1004 => '', 1005 => 'By default, DominoScript uses double six (D6) dominos to represent everything, so the default base is 7.', 1006 => '', 1007 => 'The max cell value of half of a domino is always 1 less than the Base. So in base 7, the max value is 6. In base 10, the max value is 9. In base 16, the max value is 15 (aka <code>f</code>).', 1008 => '', 1009 => 'If the number of dots on a domino half exceeds the max amount of possible dots for the current base, it is clamped!', 1010 => '', 1011 => 'For example: when you are in Base 7 and the interpreter encounters a <code>f—f</code> domino, it will be parsed as <code>6—6</code>. If you are in base 10, it will be parsed as <code>9—9</code> etc.', 1012 => '', 1013 => 'In below table you can see how the same domino sequence results in different decimal numbers depending on the base:', 1014 => '', 1015 => '{| class="wikitable"', 1016 => '! Domino Sequence', 1017 => '! Base 7 (D6)', 1018 => '! Base 10 (D9)', 1019 => '! Base 16 (D15)', 1020 => '|-', 1021 => '| <code>0—6</code>', 1022 => '| 6', 1023 => '| 6', 1024 => '| 6', 1025 => '|-', 1026 => '| <code>0—9</code>', 1027 => '| 6', 1028 => '| 9', 1029 => '| 9', 1030 => '|-', 1031 => '| <code>0—f</code>', 1032 => '| 6', 1033 => '| 9', 1034 => '| 15', 1035 => '|-', 1036 => '| <code>1—6 6—6</code>', 1037 => '| 342', 1038 => '| 666', 1039 => '| 1638', 1040 => '|-', 1041 => '| <code>1—9 9—9</code>', 1042 => '| 342', 1043 => '| 999', 1044 => '| 2457', 1045 => '|-', 1046 => '| <code>1—f f—f</code>', 1047 => '| 342', 1048 => '| 999', 1049 => '| 4095', 1050 => '|-', 1051 => '| <code>2—6 6—6 6—6</code>', 1052 => '| 16806', 1053 => '| 66666', 1054 => '| 419430', 1055 => '|-', 1056 => '| <code>2—9 9—9 9—9</code>', 1057 => '| 16806', 1058 => '| 99999', 1059 => '| 629145', 1060 => '|-', 1061 => '| <code>2—f f—f f—f</code>', 1062 => '| 16806', 1063 => '| 99999', 1064 => '| 1048575', 1065 => '|}', 1066 => '', 1067 => 'With a higher Base, you have access to higher opcodes without needing to switch to extended mode.', 1068 => '', 1069 => '{| class="wikitable"', 1070 => '! Base', 1071 => '! Opcode Range', 1072 => '|-', 1073 => '| 7', 1074 => '| 0 to 48', 1075 => '|-', 1076 => '| 10', 1077 => '| 0 to 99', 1078 => '|-', 1079 => '| 16', 1080 => '| 0 to 255', 1081 => '|}', 1082 => '', 1083 => 'While the <ins>opcode-to-instruction</ins> mapping never changes, the <ins>domino-to-opcode</ins> mapping is completely different in each base.', 1084 => '', 1085 => '<span id="Ext"></span>', 1086 => '==== EXT - 46 ====', 1087 => 'Toggle extended mode on or off. If extended mode is active the interpreter will use 2 dominos instead of 1 for each instruction which extends the opcode range from 0-48 to 0-2400 when using Double six dominos.', 1088 => '', 1089 => '<span id="Time"></span>', 1090 => '==== TIME - 47 ====', 1091 => 'Pushes the milliseconds since program start to the stack.', 1092 => '', 1093 => 'Useful for things like a gameloop, animations, cooldowns etc.', 1094 => '', 1095 => '<span id="Noop"></span>', 1096 => '==== NOOP - 48 ====', 1097 => 'No operation. The IP will move to the next domino without doing anything.', 1098 => '', 1099 => 'Useful to move the IP to a specific address (e.g. start of loop body) or to “reserve” space in case you think that you might need to add more instructions later on and don’t want to move dominos around.', 1100 => '', 1101 => '<br>', 1102 => '', 1103 => '== Navigation Modes ==', 1104 => '', 1105 => 'If you don't know what navigation modes are and how they influence the Instruction Pointer, I'd recommend reading the relevant section in [[#How_the_Instruction_Pointer_Moves|How the Instruction Pointer Moves]].', 1106 => '', 1107 => '''(F=Forward, L=Left, R=Right)''', 1108 => '', 1109 => 'There are <code>49</code> total navigation modes in DominoScript. This section should reference them all.', 1110 => '', 1111 => '''To be fully spec compliant an implementation should support all of them. However, when developing an interpreter, this has a rather low priority. With just the default nav mode priority (Forward, Left, Right) you can run any DS code as long as it doesn't execute the NAVM instruction to change it.''', 1112 => '', 1113 => '=== Basic Three Way ===', 1114 => 'Out of three directions, the IP will prioritize moving to the one with the highest priority.', 1115 => '', 1116 => '{| class="wikitable"', 1117 => '! Index', 1118 => '! Priorities', 1119 => '! Domino -&gt;', 1120 => '|-', 1121 => '| 0 (Default)', 1122 => '| <code>Forward</code> <code>Left</code> <code>Right</code>', 1123 => '| <code>0—0</code>', 1124 => '|-', 1125 => '| 1', 1126 => '| <code>Forward</code> <code>Right</code> <code>Left</code>', 1127 => '| <code>0—1</code>', 1128 => '|-', 1129 => '| 2', 1130 => '| <code>Left</code> <code>Forward</code> <code>Right</code>', 1131 => '| <code>0—2</code>', 1132 => '|-', 1133 => '| 3', 1134 => '| <code>Left</code> <code>Right</code> <code>Forward</code>', 1135 => '| <code>0—3</code>', 1136 => '|-', 1137 => '| 4', 1138 => '| <code>Right</code> <code>Forward</code> <code>Left</code>', 1139 => '| <code>0—4</code>', 1140 => '|-', 1141 => '| 5', 1142 => '| <code>Right</code> <code>Left</code> <code>Forward</code>', 1143 => '| <code>0—5</code>', 1144 => '|-', 1145 => '| 6', 1146 => '| <code>RANDOM</code>', 1147 => '| <code>0—6</code>', 1148 => '|}', 1149 => '', 1150 => '=== Basic Two Way ===', 1151 => '', 1152 => 'Out of two directions, the IP will prioritize moving to the one with the highest priority.', 1153 => '', 1154 => '{| class="wikitable"', 1155 => '! Index', 1156 => '! Priorities', 1157 => '! Domino -&gt;', 1158 => '|-', 1159 => '| 7', 1160 => '| <code>Forward</code> <code>Left</code>', 1161 => '| <code>1—0</code>', 1162 => '|-', 1163 => '| 8', 1164 => '| <code>Forward</code> <code>Right</code>', 1165 => '| <code>1—1</code>', 1166 => '|-', 1167 => '| 9', 1168 => '| <code>Left</code> <code>Forward</code>', 1169 => '| <code>1—2</code>', 1170 => '|-', 1171 => '| 10', 1172 => '| <code>Left</code> <code>Right</code>', 1173 => '| <code>1—3</code>', 1174 => '|-', 1175 => '| 11', 1176 => '| <code>Right</code> <code>Forward</code>', 1177 => '| <code>1—4</code>', 1178 => '|-', 1179 => '| 12', 1180 => '| <code>Right</code> <code>Left</code>', 1181 => '| <code>1—5</code>', 1182 => '|-', 1183 => '| 13', 1184 => '| <code>RANDOM</code>', 1185 => '| <code>1—6</code>', 1186 => '|}', 1187 => '', 1188 => '=== Basic One Way ===', 1189 => 'IP can only move in one direction.', 1190 => '', 1191 => '{| class="wikitable"', 1192 => '! Index', 1193 => '! Only Direction', 1194 => '! Domino -&gt;', 1195 => '|-', 1196 => '| 14', 1197 => '| <code>Forward</code>', 1198 => '| <code>2—0</code>', 1199 => '|-', 1200 => '| 15', 1201 => '| <code>Forward</code>', 1202 => '| <code>2—1</code>', 1203 => '|-', 1204 => '| 16', 1205 => '| <code>Left</code>', 1206 => '| <code>2—2</code>', 1207 => '|-', 1208 => '| 17', 1209 => '| <code>Left</code>', 1210 => '| <code>2—3</code>', 1211 => '|-', 1212 => '| 18', 1213 => '| <code>Right</code>', 1214 => '| <code>2—4</code>', 1215 => '|-', 1216 => '| 19', 1217 => '| <code>Right</code>', 1218 => '| <code>2—5</code>', 1219 => '|-', 1220 => '| 20', 1221 => '| <code>RANDOM</code>', 1222 => '| <code>2—6</code>', 1223 => '|}', 1224 => '', 1225 => '=== Cycle Three Way ===', 1226 => 'The direction with the highest priority becomes the least prioritized in the next cycle.', 1227 => '', 1228 => 'All 3 directions are available in all cycles.', 1229 => '', 1230 => '{| class="wikitable"', 1231 => '! Index', 1232 => '! Cycle 1', 1233 => '! Cycle 2', 1234 => '! Cycle 3', 1235 => '! Domino -&gt;', 1236 => '|-', 1237 => '| 21', 1238 => '| <code>F</code> <code>L</code> <code>R</code>', 1239 => '| <code>L</code> <code>R</code> <code>F</code>', 1240 => '| <code>R</code> <code>F</code> <code>L</code>', 1241 => '| <code>3—0</code>', 1242 => '|-', 1243 => '| 22', 1244 => '| <code>F</code> <code>R</code> <code>L</code>', 1245 => '| <code>R</code> <code>F</code> <code>F</code>', 1246 => '| <code>L</code> <code>F</code> <code>R</code>', 1247 => '| <code>3—1</code>', 1248 => '|-', 1249 => '| 23', 1250 => '| <code>L</code> <code>F</code> <code>R</code>', 1251 => '| <code>F</code> <code>R</code> <code>F</code>', 1252 => '| <code>R</code> <code>L</code> <code>F</code>', 1253 => '| <code>3—2</code>', 1254 => '|-', 1255 => '| 24', 1256 => '| <code>L</code> <code>R</code> <code>F</code>', 1257 => '| <code>R</code> <code>F</code> <code>L</code>', 1258 => '| <code>F</code> <code>L</code> <code>R</code>', 1259 => '| <code>3—3</code>', 1260 => '|-', 1261 => '| 25', 1262 => '| <code>R</code> <code>F</code> <code>L</code>', 1263 => '| <code>F</code> <code>L</code> <code>R</code>', 1264 => '| <code>L</code> <code>R</code> <code>F</code>', 1265 => '| <code>3—4</code>', 1266 => '|-', 1267 => '| 26', 1268 => '| <code>R</code> <code>L</code> <code>F</code>', 1269 => '| <code>L</code> <code>F</code> <code>R</code>', 1270 => '| <code>F</code> <code>R</code> <code>L</code>', 1271 => '| <code>3—5</code>', 1272 => '|-', 1273 => '| 27', 1274 => '| (unmapped)', 1275 => '| (unmapped)', 1276 => '| (unmapped)', 1277 => '| <code>3—6</code>', 1278 => '|}', 1279 => '', 1280 => '=== Cycle Two Way ===', 1281 => 'The direction with the highest priority becomes the least prioritized in the next cycle.', 1282 => '', 1283 => 'Only 2 directions are available in a single cycle.', 1284 => '', 1285 => '{| class="wikitable"', 1286 => '! Index', 1287 => '! Cycle 1', 1288 => '! Cycle 2', 1289 => '! Cycle 3', 1290 => '! Domino -&gt;', 1291 => '|-', 1292 => '| 28', 1293 => '| <code>F</code> <code>L</code>', 1294 => '| <code>L</code> <code>R</code>', 1295 => '| <code>R</code> <code>F</code>', 1296 => '| <code>4—0</code>', 1297 => '|-', 1298 => '| 29', 1299 => '| <code>F</code> <code>R</code>', 1300 => '| <code>R</code> <code>F</code>', 1301 => '| <code>L</code> <code>F</code>', 1302 => '| <code>4—1</code>', 1303 => '|-', 1304 => '| 30', 1305 => '| <code>L</code> <code>F</code>', 1306 => '| <code>F</code> <code>R</code>', 1307 => '| <code>R</code> <code>L</code>', 1308 => '| <code>4—2</code>', 1309 => '|-', 1310 => '| 31', 1311 => '| <code>L</code> <code>R</code>', 1312 => '| <code>R</code> <code>F</code>', 1313 => '| <code>F</code> <code>L</code>', 1314 => '| <code>4—3</code>', 1315 => '|-', 1316 => '| 32', 1317 => '| <code>R</code> <code>F</code>', 1318 => '| <code>F</code> <code>L</code>', 1319 => '| <code>L</code> <code>R</code>', 1320 => '| <code>4—4</code>', 1321 => '|-', 1322 => '| 33', 1323 => '| <code>R</code> <code>L</code>', 1324 => '| <code>L</code> <code>F</code>', 1325 => '| <code>F</code> <code>R</code>', 1326 => '| <code>4—5</code>', 1327 => '|-', 1328 => '| 34', 1329 => '| (unmapped)', 1330 => '| (unmapped)', 1331 => '| (unmapped)', 1332 => '| <code>4—6</code>', 1333 => '|}', 1334 => '', 1335 => '=== Cycle One Way ===', 1336 => 'The direction with the highest priority becomes the least prioritized in the next cycle.', 1337 => '', 1338 => 'Only 1 direction is available in a single cycle.', 1339 => '', 1340 => '{| class="wikitable"', 1341 => '! Index', 1342 => '! Cycle 1', 1343 => '! Cycle 2', 1344 => '! Cycle 3', 1345 => '! Domino -&gt;', 1346 => '|-', 1347 => '| 35', 1348 => '| <code>F</code>', 1349 => '| <code>L</code>', 1350 => '| <code>R</code>', 1351 => '| <code>5—0</code>', 1352 => '|-', 1353 => '| 36', 1354 => '| <code>F</code>', 1355 => '| <code>R</code>', 1356 => '| <code>L</code>', 1357 => '| <code>5—1</code>', 1358 => '|-', 1359 => '| 37', 1360 => '| <code>L</code>', 1361 => '| <code>F</code>', 1362 => '| <code>R</code>', 1363 => '| <code>5—2</code>', 1364 => '|-', 1365 => '| 38', 1366 => '| <code>L</code>', 1367 => '| <code>R</code>', 1368 => '| <code>F</code>', 1369 => '| <code>5—3</code>', 1370 => '|-', 1371 => '| 39', 1372 => '| <code>R</code>', 1373 => '| <code>F</code>', 1374 => '| <code>L</code>', 1375 => '| <code>5—4</code>', 1376 => '|-', 1377 => '| 40', 1378 => '| <code>R</code>', 1379 => '| <code>L</code>', 1380 => '| <code>F</code>', 1381 => '| <code>5—5</code>', 1382 => '|-', 1383 => '| 41', 1384 => '| (unmapped)', 1385 => '| (unmapped)', 1386 => '| (unmapped)', 1387 => '| <code>5—6</code>', 1388 => '|}', 1389 => '', 1390 => '=== Flip Flop ===', 1391 => 'The priority flip flops between 2 primary directions.', 1392 => '', 1393 => '{| class="wikitable"', 1394 => '! Index', 1395 => '! Flip', 1396 => '! Flop', 1397 => '! Domino -&gt;', 1398 => '|-', 1399 => '| 42', 1400 => '| <code>F</code>', 1401 => '| <code>L</code>', 1402 => '| <code>6—0</code>', 1403 => '|-', 1404 => '| 43', 1405 => '| <code>F</code>', 1406 => '| <code>R</code>', 1407 => '| <code>6—1</code>', 1408 => '|-', 1409 => '| 44', 1410 => '| <code>L</code>', 1411 => '| <code>F</code>', 1412 => '| <code>6—2</code>', 1413 => '|-', 1414 => '| 45', 1415 => '| <code>L</code>', 1416 => '| <code>R</code>', 1417 => '| <code>6—3</code>', 1418 => '|-', 1419 => '| 46', 1420 => '| <code>R</code>', 1421 => '| <code>F</code>', 1422 => '| <code>6—4</code>', 1423 => '|-', 1424 => '| 47', 1425 => '| <code>R</code>', 1426 => '| <code>L</code>', 1427 => '| <code>6—5</code>', 1428 => '|-', 1429 => '| 48', 1430 => '| (unmapped)', 1431 => '| (unmapped)', 1432 => '| <code>6—6</code>', 1433 => '|}', 1434 => '', 1435 => '<br>', 1436 => '== Example: Factorial ==', 1437 => '', 1438 => '<br>[[File:DominoScript-Example-Factorial-flow.png|thumb|Factorial Example with IP flow visualized]]', 1439 => '', 1440 => ''''Pseudocode:'''', 1441 => '<pre style="overflow:auto;>', 1442 => 'NUM 12', 1443 => 'NUM 42 CALL', 1444 => 'NUMOUT // prints 479001600', 1445 => '', 1446 => 'FUNCTION FACTORIAL: // (address 42)', 1447 => ' DUP NUM 0 EQ', 1448 => ' IF:', 1449 => ' POP', 1450 => ' NUM 1', 1451 => ' ELSE:', 1452 => ' DUP NUM 1 SUB', 1453 => ' NUM 42 CALL // recursive call', 1454 => ' MUL', 1455 => '</pre>', 1456 => '', 1457 => ''''DominoScript:'''', 1458 => '<pre style="letter-spacing:4px;line-height:1.1;overflow:auto;">', 1459 => '0—1 . . . . . 1—0 1—0 0 . . . 2—1 4—4 0', 1460 => ' | |', 1461 => '0—1 . . . . . . . . . 0 . . . . . . . 6', 1462 => ' ', 1463 => '1 . 0—3 0—1 0—0 2—3 4—1 . . . . . . . 0', 1464 => '| |', 1465 => '5 . . . . . . . . . . 0 . . . . . . . 1', 1466 => ' | ', 1467 => '0—1 1—0 6—0 4—4 5—1 . 3 0—1 0—1 1—1 0—1', 1468 => '</pre>', 1469 => '', 1470 => '== Example: WASD Controls ==', 1471 => '', 1472 => 'Demonstrates `WASD` keyboard inputs that move a character around on a 5x7 grid and renders it via stdout.', 1473 => '', 1474 => 'It could be used as a basis to build a simple game.', 1475 => '', 1476 => '[[File:DominoScript-Example-WASD-Input-Example-Flow.png|thumb|WASD Controls example with IP flow visualized]]', 1477 => '', 1478 => ''''Pseudocode''':', 1479 => '<pre style="overflow:auto;font-size:0.85em;>', 1480 => 'NUM 16 BASE // tell interpreter to use dominos with up to 16 dots per side. Allowing you to use less dominos', 1481 => '', 1482 => '// Binding addresses to labels', 1483 => 'NUM 116 LABEL // playerX -1', 1484 => 'NUM 122 LABEL // playerY -2', 1485 => 'NUM 1008 LABEL // topRow = "╭──────────────╮\n" -3', 1486 => 'NUM 1080 LABEL // middleRow = "│ │\n" -4', 1487 => 'NUM 1152 LABEL // bottomRow = "╰──────────────╯\n" -5', 1488 => 'NUM 72 LABEL // function main() -6', 1489 => 'NUM 361 LABEL // function update() -7', 1490 => 'NUM 505 LABEL // function render() -8', 1491 => 'NUM 660 LABEL // loop body start within render() -9', 1492 => '', 1493 => 'NUM 6 NEG CALL // main()', 1494 => '', 1495 => 'FUNCTION main:', 1496 => ' NUM 1 LIT // tell interpreter that we use exactly 1 domino for each number or character in a string', 1497 => ' LOOP_FOREVER:', 1498 => ' NUM 50 WAIT // wait 50ms', 1499 => ' PUSH 7 NEG CALL // update()', 1500 => ' PUSH 8 NEG CALL // render()', 1501 => ' NUM 6 NEG JUMP // jump back to start of main', 1502 => '', 1503 => 'FUNCTION update:', 1504 => ' STR "w" KEY IF:', 1505 => ' NUM 1 NUM 2 NEG GET NUM 1 SUB NUM 1 NUM 2 NEG SET // y = y - 1 ', 1506 => ' STR "a" KEY IF:', 1507 => ' NUM 1 NUM 1 NEG GET NUM 2 SUB NUM 1 NUM 1 NEG SET // x = x - 2', 1508 => ' STR "s" KEY IF:', 1509 => ' NUM 1 NUM 2 NEG GET NUM 1 ADD NUM 1 NUM 2 NEG SET // y = y + 1', 1510 => ' STR "d" KEY IF:', 1511 => ' NUM 1 NUM 1 NEG GET NUM 2 ADD NUM 1 NUM 1 NEG SET // x = x + 2', 1512 => '', 1513 => ' NUM 1 NUM 1 NEG GET NUM 2 NUM 13 CLAMP NUM 1 NUM 1 NEG SET // x = clamp(x, 2, 13)', 1514 => ' NUM 1 NUM 2 NEG GET NUM 2 NUM 6 CLAMP NUM 1 NUM 2 NEG SET // y = clamp(y, 2, 6)', 1515 => ' KEYRES', 1516 => '', 1517 => 'FUNCTION render:', 1518 => ' STR '\033[2J\033[H' STDOUT // clear screen and move cursor to top left', 1519 => ' NUM 0 // iterator = 0;', 1520 => '', 1521 => ' LOOP:', 1522 => ' DUPE NUM 0 EQL IF: // if (iterator === 0)', 1523 => ' NUM 3 NUM 3 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Top row string if on row 0', 1524 => ' DUPE NUM 8 EQL IF: // if (iterator === 8)', 1525 => ' NUM 3 NUM 5 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Bottom row string if on row 8', 1526 => ' DUPE DUPE NUM 2 GTR NUM 1 ROLL NUM 7 GTR NOT AND IF: // if (iterator > 2 && iterator < 7)', 1527 => ' NUM 3 NUM 4 NEG NUM 2 LIT GET STROUT NUM 1 LIT // render Middle row string if on row 1-7', 1528 => '', 1529 => ' NUM 1 ADD // iterator = iterator + 1', 1530 => '', 1531 => ' DUPE NUM 8 EQL IF:', 1532 => ' // Hacky way to achieve the equivalent of: stdout.write(`\033[${playerY};${playerX}H[]`)', 1533 => ' // The string is constructed 1 char at a time in reverse order using NUM', 1534 => ' NUM 0 NUM 93 NUM 91 NUM 72 NUM 1 NUM 1 NEG GET NUM 31 NUM 59 NUM 1 NUM 2 NEG GET NUM 31 NUM 91 NUM 27 STROUT', 1535 => ' POP // remove iterator from stack', 1536 => ' BREAK // exit loop if we've reached the bottom row', 1537 => '', 1538 => ' NUM 9 NEG JUMP // jump back to start of loop', 1539 => '</pre>', 1540 => '', 1541 => ''''DominoScript''':', 1542 => '<pre style="letter-spacing:2px;line-height:1.1;overflow:auto;font-size:0.85em;">', 1543 => '0—1 1—0 2—2 6—3 0—1 1—0 7—4 1—e 0—1 1—0 7—a 1—e 0—1 1—3 f—0 1—e 0—1 1—4 3—8 1—e 0—1 1—4 8—0 1—e 0—1 1—0 4—8 1—e 0—1 1—1 6—9 1—e 0—1 1—2 8—8 1—e', 1544 => ' ', 1545 => '0—1 0—1 2—c 0—1 3—2 2—2 0—1 0—7 0—c 2—0 0—1 0—8 0—c 2—0 0—1 0—6 0—c 1—f . . . . . . 0—0 0—8 . . 0—0 0—4 . . . . 0—2 c—0 6—0 1—0 e—1 4—9 2—1 1—0', 1546 => ' ', 1547 => '0—8 0—1 0—1 0—1 0—2 0—c 2—b 3—0 3 . 0—8 0—1 0—1 0—1 0—1 0—c 2—b 3—0 3 . 0—7 0—1 0—1 0—1 0—2 0—c 2—b 3—0 3 . 0—7 0—1 0—1 0—1 0—1 0—c 2—b 3—0 3 .', 1548 => ' | | | | ', 1549 => '1 . . . . . . . . . . . . . . . 0 . 2 . . . . . . . . . . . . . . . 0 . 1 . . . . . . . . . . . . . . . 0 . 2 . . . . . . . . . . . . . . . 0 .', 1550 => '| | | | ', 1551 => '0 1—0 a—2 c—0 2—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 1—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 2—0 1—0 1—0 1—0 d 3 . 0 1—0 a—2 c—0 1—0 1—0 1—0 1—0 d 3 .', 1552 => ' | | | | | | | | ', 1553 => '. 3—0 3—0 3—0 0—2 7—7 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 6—1 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 7—3 0—0 2—7 1 0 3—0 3—0 3—0 3—0 0—2 6—4 0—0 2—7 1 0 3', 1554 => ' |', 1555 => '2 0—3 0—3 b—2 c—0 2—0 1—0 1—0 . . 6—0 1—0 2—0 1—0 a—2 c—0 2—0 1—0 . . 0—3 0—3 0—3 b—2 c—0 1—0 1—0 1—0 . . e—0 1—0 2—0 1—0 a—2 c—0 1—0 1—0 . . 0', 1556 => '| ', 1557 => '8 . 5—b 3 . 5—b 4 . 0—1 0 . 1—0 d—0 . . 0—1 0—3 0—3 0—c 0—1 0 . 1—0 1—0 0—1 0 . . . 3—0 3—0 1 . . . 1—0 d—0 2—a 0 . 0—2 0 . 1—b 2 . . . 1—0 1—0', 1558 => ' | | | | | | | | | ', 1559 => '. . b . 2 . b . 8 . 6 . 0 . . 0—0 1—1 1—d 0 c—2 1—0 0—0 1—0 2 2 . 2—a 2—6 . 0 0 . 1—1 . . 0 d 0—1 . . . . . c . 1 . 1 . c . 1 . 6 . . . . . . .', 1560 => ' | | | | | | | | | | ', 1561 => '0—2 1 . 4—a 1 . 0—0 2 . 0—3 0—1 . . . 3—0 3 . . . . 0—1 0 6 . c 2—c . . . . . 1 . 9 . . 0 1 . . 0 . 0—1 4 . 0 . 1 . 0 . 2 . 0 . 0 . . . . . . .', 1562 => ' | | | | | | | | | ', 1563 => '. . . . . . . . . . . . . 1 1—1 8—0 1—0 0—3 . . . 0—3 . 4 2 a—2 2 . . 3 0—3 c—2 . 0 . 0 9 . . . 0 . b . 8 . 1 . f . 1 . a . b . 0 . . . . . . .', 1564 => ' | | | | | | | | ', 1565 => '. 0—3 0—3 0—3 0—3 0—3 0—3 d 0—1 0—3 0—1 0—5 3—0 . 1 . . 0—c 0—1 0 . . 0 . . 0—3 0—1 . c . . . . 0 . 5 . 0 . 0 . 0 . 0 . 0 . 5 . . . . . . . . .', 1566 => ' | | | | | ', 1567 => '3—0 c—2 1—0 0—0 1—0 6—2 a—2 c—2 2—0 1—0 c—0 0—3 . 0 d 3—0 3—0 3—0 3—0 0—1 . 7 . . . f—1 . . . . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . . . . . . . . .', 1568 => ' | | | | | | ', 1569 => '0—3 0—1 0—2 1—2 0—1 0—1 0—4 0—1 0—7 1—2 0—e 0—f 3—0 1 . . . . . . . . . 0—1 0 . . . . . . . . . 5—d 0 . 0—1 0 . 3—b 0 . 1—f 0 . . . . . . . . .', 1570 => ' ', 1571 => '2—5 6—d 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 6—e 0—0 0—a 0—0 0—0', 1572 => ' ', 1573 => '2—5 0—2 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 0—0 2—0 2—5 0—2 0—0 0—a 0—0 0—0', 1574 => ' ', 1575 => '2—5 7—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 0—0 2—5 6—f 0—0 0—a 0—0 0—0', 1576 => '</pre>', 1577 => '', 1578 => '==External resources==', 1579 => '* [https://dominoscript.com Website with code playground]', 1580 => '* [https://github.com/andreas-schoch/dominoscript GitHub Repository containing reference implementations, examples and documentations]', 1581 => '', 1582 => '', 1583 => '[[Category:Languages]]', 1584 => '[[Category:Stack-based]] ', 1585 => '[[Category:Implemented]] ', 1586 => '[[Category:Self-modifying]]', 1587 => '[[Category:Turing complete]]', 1588 => '[[Category:Low-level]] ', 1589 => '[[Category:Thematic]]', 1590 => '[[Category:2024]]' ]
Unix timestamp of change (timestamp)
'1736326722'