# 2ds

2ds (standing for 2-Dimensional Stack) is a language that operates, on, as you could probably tell from the name, a 2-dimensional stack. Its syntax is inspired by Forth.

## Program Structure

Every program consists of a set of tokens divided by spaces, tabs, or newlines. Invalid tokens will throw an error. Comments are notated with a #, which comments out everything until the next newline.

## The 2-Dimensional Stack

The stack of 2ds is two dimensional, and as such you can push and pop in two directions (on the X direction, and on the Y direction). There is a single point called the head, which is basically just the two-dimensional equivalent of a stack pointer. For example, you can push the two numbers 48 and 58 to the stack in the X direction like this: `48x 58x` and then you can pop them by outputting them as chars like this `x. x.` which pops in the X direction then prints. However, you could also do `48x 58y` which would push 48 on the x (putting it in cell 0,0 and moving the head to 1,0) and then pushing 58 on to the stack vertically (putting it in cell 1,0 and moving the head to 1,1). Then, in order to output those two chars, you'd have to do `y. x.`, in reverse order since it's a stack. 2ds also has two registers, A and B, which are used for basic operations. The maximum value for A, B, and anywhere on the stack is 255, and the minimum value is 0. Going above or below these values will cause an underflow or overflow respectively, causing the values to wrap around.

## Valid Tokens

(for convenience, "push onto the stack in the X direction" is written as pushx, same with pushy, popx, and popy)

Token Operation
<integer>x Pushx <integer> onto the stack (ex. 100x pushxs 100 onto the stack)
<integer>y Pushy <integer> onto the stack (ex. 48y pushys 48)
xa Popx a value from the stack and put it in A
ya Popy a value from the stack and put it in A
xb Popx a value from the stack and put in B
yb Popy a value from the stack and put it in B
ax Pushx A onto the stack
ay Pushy A onto the stack
bx Pushx B onto the stack
by Pushy B onto the stack
+ Add A and B and put the result into A
- Subtract A and B and put the result into A
* Multiply A and B and put the result into A
/ Divide A and B and put the result into A
x. Popx a value and print it as an ASCII character
y. Popy a value and print it as an ASCII character
.x Prompt the user for input and pushx that as an ASCII value
.y Prompt the user for input and pushy that as an ASCII value
== Set A to 1 if A equals B, otherwise set A to 0
> Set A to 1 if A > B, otherwise set A to 0
< Set A to 1 if A < B, otherwise set A to 0
>= Set A to 1 if A >= B, otherwise set A to 0
<= Set A to 1 if A <= B, otherwise set A to 0
!= Set A to 1 if A does not equal B, otherwise set A to 0
! If A > 1, set A to 0, otherwise set A to 1
&& If A > 1, and B > 1, set A to 1, otherwise set A to 0
|| If A > 1 or B > 1, set A to 1, otherwise set A to 0
fi Do nothing
swap Swap the values of A and B
'<char>x (char should be a single character) Pushx char as an ascii value (e.x. 'Hx pushxs H)
'<char>y (char should be a single character) Pushy char as an ascii value (e.x. 'ey pushys e)

Tokens are non-case sensitive, that is `WHILE`, `whILE`, and `while` are all valid. Case only matters when using `'`, since it takes the case of that ascii character.

## Example Programs

### Hello, World!

```10x '!x 'dx 'lx 'rx 'ox 'Wx 32x ',x 'ox 'lx 'lx 'ex 'Hx #Add all chars to stack
x. x. x. x. x. x. x. x. x. x. x. x. x. x. #Print them all
```

Or, more condensed `10x '!x 'dx 'lx 'rx 'ox 'Wx 32x ',x 'ox 'lx 'lx 'ex 'Hx x. x. x. x. x. x. x. x. x. x. x. x. x. x.`

### Truth Machine

```'0x xb #pushx 0 to the stack then pop it to B
.x xa #get input, pushx it to the stack, then pop it to A
!= while #while A != B (since B is 0, this would be while A != 0), loop
'1x x. #print 1
elihw #end loop
#if A wasn't B, we'd reach here, otherwise we'd be stuck in the loop
bx x. #print B (which is equal to 0)
```

Condensed version: `'0x xb .x xa != while '1x x. elihw bx x.`

### 99 bottles of beer

```1x xa 99x
while
xa ax 10x xb / 48x xb + ax x. - 10x xb * swap xa ax - 48x xb + ax x. #print two-digit number
32x x. 'bx x. 'ox x. 'tx x. 'tx x. 'lx x. 'ex x. 'sx x. 32x x. 'ox x. 'fx x. 32x x. 'bx x. 'ex x. 'ex x. 'rx x. 32x x. 'ox x. 'nx x. 32x x. 'tx x. 'hx x. 'ex x. 32x x. 'wx x. 'ax x. 'lx x. 'lx x. ',x x.
10x x. #newline
xa ax 10x xb / 48x xb + ax x. - 10x xb * swap xa ax - 48x xb + ax x. #print two-digit number
32x x. 'bx x. 'ox x. 'tx x. 'tx x. 'lx x. 'ex x. 'sx x. 32x x. 'ox x. 'fx x. 32x x. 'bx x. 'ex x. 'ex x. 'rx x. '.x x.
10x x.
'Tx x. 'ax x. 'kx x. 'ex x. 32x x. 'ox x. 'nx x. 'ex x. 32x x. 'dx x. 'ox x. 'wx x. 'nx x. ',x x. 32x x. 'px x. 'ax x. 'sx x. 'sx x. 32x x. 'ix x. 'tx x. 32x x. 'ax x. 'rx x. 'ox x. 'ux x. 'nx x. 'dx x. ',x x.
1x xb xa - ax
10x x.
0x xb !=
if
xa ax 10x xb / 48x xb + ax x. - 10x xb * swap xa ax - 48x xb + ax x. #print two-digit number
32x x. 'bx x. 'ox x. 'tx x. 'tx x. 'lx x. 'ex x. 'sx x. 32x x. 'ox x. 'fx x. 32x x. 'bx x. 'ex x. 'ex x. 'rx x. 32x x. 'ox x. 'nx x. 32x x. 'tx x. 'hx x. 'ex x. 32x x. 'wx x. 'ax x. 'lx x. 'lx x. '.x x.
fi
xa ax ==
if
'Nx x. 'ox x. 32x x. 'bx x. 'ox x. 'tx x. 'tx x. 'lx x. 'ex x. 'sx x. 32x x. 'ox x. 'fx x. 32x x. 'bx x. 'ex x. 'ex x. 'rx x. 32x x. 'ox x. 'nx x. 32x x. 'tx x. 'hx x. 'ex x. 32x x. 'wx x. 'ax x. 'lx x. 'lx x. '.x x.
fi
10x x.
xa ax 0x xb
!=
elihw
```

condensed: `1x xa 99x while xa ax 10x xb / 48x xb + ax x. - 10x xb * swap xa ax - 48x xb + ax x. 32x x. 'bx x. 'ox x. 'tx x. 'tx x. 'lx x. 'ex x. 'sx x. 32x x. 'ox x. 'fx x. 32x x. 'bx x. 'ex x. 'ex x. 'rx x. 32x x. 'ox x. 'nx x. 32x x. 'tx x. 'hx x. 'ex x. 32x x. 'wx x. 'ax x. 'lx x. 'lx x. ',x x. 10x x. xa ax 10x xb / 48x xb + ax x. - 10x xb * swap xa ax - 48x xb + ax x. 32x x. 'bx x. 'ox x. 'tx x. 'tx x. 'lx x. 'ex x. 'sx x. 32x x. 'ox x. 'fx x. 32x x. 'bx x. 'ex x. 'ex x. 'rx x. '.x x. 10x x. 'Tx x. 'ax x. 'kx x. 'ex x. 32x x. 'ox x. 'nx x. 'ex x. 32x x. 'dx x. 'ox x. 'wx x. 'nx x. ',x x. 32x x. 'px x. 'ax x. 'sx x. 'sx x. 32x x. 'ix x. 'tx x. 32x x. 'ax x. 'rx x. 'ox x. 'ux x. 'nx x. 'dx x. ',x x. 1x xb xa - ax 10x x. 0x xb != if xa ax 10x xb / 48x xb + ax x. - 10x xb * swap xa ax - 48x xb + ax x. 32x x. 'bx x. 'ox x. 'tx x. 'tx x. 'lx x. 'ex x. 'sx x. 32x x. 'ox x. 'fx x. 32x x. 'bx x. 'ex x. 'ex x. 'rx x. 32x x. 'ox x. 'nx x. 32x x. 'tx x. 'hx x. 'ex x. 32x x. 'wx x. 'ax x. 'lx x. 'lx x. '.x x. fi xa ax == if 'Nx x. 'ox x. 32x x. 'bx x. 'ox x. 'tx x. 'tx x. 'lx x. 'ex x. 'sx x. 32x x. 'ox x. 'fx x. 32x x. 'bx x. 'ex x. 'ex x. 'rx x. 32x x. 'ox x. 'nx x. 32x x. 'tx x. 'hx x. 'ex x. 32x x. 'wx x. 'ax x. 'lx x. 'lx x. '.x x. fi 10x x. xa ax 0x xb != elihw`

## Interpreter

An interpreter written in C is available Here