StackCell

StackCell is an esoteric programming language that consists of two stacks of integers and some commands to manipulate them. You also get a single cell which can be written to and read from as much as you like.
StackCell is Turing-complete: the reference implementation contains a file bf_to_cel.py, which can compile any program written in Brainfuck into StackCell.
The interpreter can either take a filename as an argument, or programs can be entered into an interactive interface.
In addition to the interpreter, there is also an assembler for a mini-language which compiles to StackCell. It supports all the features of StackCell but with slightly more ergonomic syntax. Both programs can be found in the source repository, although the assembler is undocumented.
By default, all cells are unsigned 8-bit numbers. However, a feature (pre-compiled as a separate executable) enables the use of unsigned 32-bit cells instead.
== The stack ==
The stack is a list of (wrapping) unsigned bytes. The stack is initially empty, and attempting to read elements from an empty stack will give a zero.
== The Cell ==
The cell contains a single (wrapping) unsigned byte. Initially, it contains the value 0, but can be written to to overwrite its value. When it is read from, its value is not cleared.
== Commands ==
 StackCell Commands
Command 	Effect 	Example
' 	Pushes a character to the primary stack1 	'a
" 	Pushes a string to the primary stack12 	"!dlrow olleH"
# 	Pushes a byte to the primary stack13 	#42
Numeral from 1 to 9	Skips the number of characters specified 	'0@-:?6'0+;.:[:'0+;:]
[ 	Starts a zero-sentinel loop4 	:[;:]
] 	Ends a zero-sentinel loop4 	:[;:]
( 	Starts a non-zero sentinel loop4 	:(;:)
) 	Ends a non-zero sentinel loop4 	:(;:)
. 	Terminates the program 	.
: 	Duplicates the top value of the primary stack 	#42:
{ 	Moves the top value of the primary stack to the cell 	#42{
} 	Copies the value of the cell on to the primary stack 	}
` 	Discards the top value of the primary stack with no other side-effects 	#42`
x 	Swaps the top two values of the primary stack 	'a'bx
X 	Swaps the primary and secondary stacks 	X
! 	Logically negates the top value of the primary stack5 	#42!
< 	Compares the top two values7 of the primary stack6 and return 1 if the first is less than the second, otherwise 0 	#42#42<
> 	Compares the top two values7 of the primary stack6 and return 1 if the first is greater than the second, otherwise 0 	#42#42>
= 	Compares the top two values of the primary stack6 and return 1 if they are equal, otherwise 0 	#42#42=
+ 	Adds the top two values of the primary stack6 	#42#42+
- 	Subtracts the top two values7 of the primary stack6 	#42#42-
* 	Multiplys the top two values of the primary stack6 	#42#42*
/ 	Divides, using integer division, the top two values7 of the primary stack6 	#0C#4/
% 	Take the modulus of the top two values of the primary stack7 of the primary stack6 	#42#42%
^ 	Bitwise-XORs the top two values of the primary stack6 	#42#42^
& 	Bitwise-ANDs the top two values of the primary stack6 	#42#42&
| 	Bitwise-ORs the top two values of the primary stack6 	#42#42|
~ 	Bitwise-negates the top value of the primary stack 	#42#42~
? 	Skips the next instruction if the top value of the primary stack is zero (consumes the top value of the primary stack)	#42::?+
; 	Consumes, and outputs as ASCII, the top value of the primary stack 	#42;
@ 	Inputs a character from the keyboard and pushes it to the primary stack 	@
== Examples ==
See the official samples
== Footnotes ==
 1
 ", ', and # are all instructions. This means that they can be skipped by jump operators, such as 1-9, and even the loop operators ([]()).
 2
 Strings are pushed to the stack as a sequence of bytes, in the order the characters are written. This means that to print them correctly, they should be entered in reverse.
 3
 Values pushed to the stack with # must be in two-digit hexadecimal form; however it is case-insensitive.
 4
 Loops started with [ are executed until the stack is empty or the byte at the top of the stack is zero. Loops started with ( are executed until the stack is empty or the byte at the top of the stack is non-zero. Loops may be nested. Loops may be skipped entirely. Both forms of loop consume the top value of the stack when determining whether to run.
 5
 That is to say, transform the top value of the stack such that any non-zero value becomes zero, and zero becomes one
 6
 This operation consumes the top two values of the stack, and places a new one containing the result
 7
 The top value of the stack (i.e. the one pushed later) is considered the left hand side of the operation
Category:Languages
Category:Turing complete
Category:2021
Category:Low-level
Category:Implemented
Category:Stack-based