DStack

From Esolang
Jump to navigation Jump to search

DStack is a stack-based esoteric language created by User:-Dark-Phantom- on November, 2015. The language uses two stacks, a cursor and a register, the four begin with the value zero. It has only one data type: unsigned integers of at least 8 bits. The cursor marks the position in the code of the instruction to be executed. There is also a dictionary which maps numbers to string literals.

Syntax

The only valid characters are:

dstackDSTACK0123456789/@

The program is illegal if it contains an invalid character that is not inside a comment or string literal, is not a new line (\n), a space nor a tab (\t).

Note: the @ symbol can only be used at the beginning of the line (see section String Literals).

The code is read in pairs, but only moves the cursor one character at a time. For example, in the code

0kckt

The instructions are: 0k, kc, ck, kt.

Instructions

The first letter of the pair can be uppercase or lowercase. If the second letter is capitalized then swaps the use of stacks in the operation (or do a different operation if indicated).

Character pair Instruction name Description Equivalent in C++
ds dS Add/Multiply ds: Add the top of the two stacks and stores the result in the register.

dS: Multiply the top of the two stacks and stores the result in the register.

reg = A.top() + B.top();


reg = A.top() * B.top();

dt dT Subtract Subtract the top of the second stack to the first and stores the result in the register.

reg = A.top() - B.top();

da dA Power Raises the top of the first stack to the power of the second and stores the result in the register.

reg = pow(A.top(), B.top());

dc dC Divide Divide the top of the first stack by the second and stores the result in the register. If the top of the second stack is zero, the program terminates with an error.

if (B.top() != 0)

reg = A.top() / B.top();

else

exit(0);
dk dK Remainder Calculates the remainder of the division of the top of the first stack by the second and stores the result in the register. If the top of the second stack is zero, the program terminates with an error.

if (B.top() != 0)

reg = A.top() % B.top();

else

exit(0);
sd sD Zero Sets the register value to zero.

reg = 0;

st sT Equal/Unequal st: If the top of both stacks are equal put a one in the register, else put a zero.

sT: If the top of both stacks are different put a one in the register, else put a zero.

reg = A.top() == B.top();


reg = A.top() != B.top();

sa sA Between Inclusive/Between Exclusive sa: If the register is between the two tops of stacks (inclusive) replace the register with one, else with zero.

sA: If the register is between the two tops of stacks (exclusive) replace the register with one, else with zero.

sc sC Greater If the top of the first stack is greater than the second put a one in the register, else put a zero.

reg = A.top() > B.top();

sk sK Equal or Greater If the top of the first stack is equal or greater than the second put a one in the register, else put a zero.

reg = A.top() >= B.top();

td tD Not If the top of the first stack is zero put a one in the register, else put a zero.

reg = !A.top();

ts tS Or/And ts: If the top of at least one stack is nonzero put a one in the register, else put a zero.

tS: If the top of both stacks is nonzero put a one in the register, else put a zero.

reg = A.top() || B.top();


reg = A.top() && B.top();

ta tA Xor If only the top of a stack is zero put a one in the register, else put a zero.
tc tC Peek Copies the top of the first stack in the register.

reg = A.top();

tk tK Min/Max tk: Compares the top of both stacks and put the lowest in the register.

tK: Compares the top of both stacks and put the largest in the register.

reg = min(A.top(), B.top());


reg = max(A.top(), B.top());

ad aD Print String If there is a string literal with the number indicated by the register, print the string.
as aS Print String Interpolated with Numbers If there is a string literal with the number indicated by the register, prints the string replacing the characters # and $ by the top of the first and second stack in form of numbers, respectively.
at aT Print String Interpolated with Characters If there is a string literal with the number indicated by the register, prints the string replacing the characters # and $ by the top of the first and second stack in form of characters, respectively.
ac aC Push String If there is a string literal with the number indicated by the register, push each character of the string in the first stack.
ak aK Push Reversed String If there is a string literal with the number indicated by the register, push each character of the string in the first stack, starting from the end.
cd cD Send Removes the top of the first stack and push it in the second. If the first stack runs out of numbers, a zero is pushed.

B.push(A.top());

A.pop();

if (A.empty())

A.push(0);
cs cS Pop Removes the top of the first stack, if it runs out of numbers, a zero is pushed.

A.pop();

if (A.empty())

A.push(0);
ct cT Random If the top of the second stack is equal or greater than the first, put a random number on the register from the range of the above (inclusive).

if (B.top() >= A.top())

reg = rand() % (B.top() - A.top() + 1) + A.top();
ca cA Swap Swap the tops of the stacks.
ck cK Print Character/Print Number ck: Displays the ASCII character corresponding to the register number (if it is greater than 255 the remainder of dividing by 256 is used).

cK: Displays the number of the register.

cout << (char)(reg % 256);


cout << reg;

kd kD None Does nothing (Nop).

ks kS Save Push in the first stack the value of cursor + 1.

A.push(cur + 1);

kt kT Jump If the value in register is non-zero, move the cursor to the position indicated by the top of the first stack. After this command, the cursor does not automatically advance.

if (reg != 0)

cur = A.top();
ka kA Reset/Halt ka: If the register is nonzero, restarts the program.

kA: If the register is nonzero, halt the program.

kc kC Read Character/Read Number kc: Reads a character from the keyboard and put it on the register. If several characters are entered, they remain in the buffer and will be available for the next time. The newline character will also be read. EOF = 0.

kC: Read an integer from the keyboard and put it on the register. If it can not parse as a number then keep waiting for one.

char ch;

cin.get(ch);

reg = ch;


// Without check for simplicity

cin >> reg;

dd dD

ss sS

tt tT

cc cC

kk kK

Push Push the value of register in the first stack.

A.push(reg);

?0 Digit ? represents any valid character. 0 represents any digit.

Multiplies by 10 the register value and adds the digit.

reg = reg * 10 + digit;

0x None 0 represents any digit. x represents any valid letter.

Does nothing (Nop).

Pre-Parse

Before the program is interpreted, string literals, comments, new lines, tabs and spaces are removed. The positions of the instructions and the cursor are calculated after this step.

String Literals

The string literals are declared starting the line with @. Then you can put a number identifying the string and finally a new line character. All the lines that continue, will become part of the string, until it finds a @, alone at the beginning of a line.

Note: If there is a string with the same number, then it is concatenated to the end without any separator.

Example:

@123
This string is identified by the number 123.
It contains two lines and even the @ character.
@

Comments

Comments begin with / and finish at the end of the line. They can contain any characters.

There may be comments from multiple lines using a string literal without identification number.

Execution

Each time an instruction is executed the cursor position is advanced (except for kt and kT). If the cursor is at the last character or ahead, the program terminates (Can get those positions advancing or jumping with the Jump instruction).

Examples

Hello, World!

@0
Hello, world!
@
ad

Cat

0kckt

Truth-machine

04KKCKT

Factorial

01kkKCccsd25DDkTsCK999kktCSdttsd25dDkTtcsd1DDcdCSdSScsd47DDkTcStCK

Infinite Loop

skt

Collatz sequence

kCc0sd2ccCCSCstcKdkkdsd44tTkTcscSdcccsd65kktcscSd3DDSsd1DDssstcScScsd1DDKkdcSd10ckKdtkT1cK

99 bottles of beer

@0
# bottles of beer on the wall, # bottles of beer.
Take one down and pass it around, $ bottles of beer on the wall.


@
@1
1 bottle of beer on the wall, 1 bottle of beer.
Take one down and pass it around, no more bottles of beer on the wall.

No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
@
01SSd99CCcscDtTasd9ttkt

Is prime (golfed)

025SSd01kKCccscS0kT0cK1kAsd34SSd1ccd0sd1ddsScsdk0cD0cS0kTcdsKkdtcK

Quine

@100
010SSd64cckdtC0CKdtCk0adtCkdtckdtCk0ad
@
010SSd64cckdtC0CKdtCk0adtCkdtckdtCk0ad

Computational class

DStack is turing complete, as it is possible to translate any brainfuck code to it, using the following table:

Brainfuck DStack
> 0cD
< 0cd
+ 0sd1ddsstcSScscs
- 0sd1ddTtcSScscs
. 0tCk
, 0cSkcC
[ 0sd#ttAktcs (You have to replace the # with the location of the instruction cs in the matching ])
] 0sd#ttC0ktcs (You have to replace the # with the location of the instruction cs in the matching [)

Implementation

C++ Implementation in GitHub

Online interpreter