Tier
Paradigm(s) | Imperative |
---|---|
Designed by | User:BN |
Appeared in | Category:2020 |
Memory system | stack-based |
Computational class | Turing complete |
Reference implementation | GitHub |
File extension(s) | .tier |
Tier is a stack-based, three-dimensional programming language, created in 2019/2020 by BN.
This language is inspired by the Befunge programming language, in the sense that it is stack based and enables unconventional program flow. However unlike Befunge, Tier allows programs to be developed in three dimensions, by stacking tiers of executable files in the same 3D space as each other. Program flow can be directed up and down through these tiers (this behaviour allows the user to write functions with entry and exit points from certain tiers).
Programs
Each program is contained in a single directory (which should be named to identify the program). Program files should be created using the .tier
extension, and should be given names composed of numbers (e.g. 0.tier, 1.tier) for use when referenced in programs.
Environment
Each program will be with the following items:
Item | Description |
---|---|
pc
|
The program counter. This is used to step through the program. Instructions at the current program counter position are executed. pc is updated with current velocity every timestep. |
vel
|
Velocity. This is the current velocity of pc (right, left, up, down). |
ts
|
Temporary storage. This is a storage element which is common and accessible to all tiers, and can only hold one value at a time. Items which are evicted from stacks (e.g. by popping or inserting another item at current position), are evicted into ts, replacing its previous value. |
Programs should begin execution from the 0th tier (i.e. inside 0.tier), with a velocity heading towards the right hand side of the file. If the program counter exceeds the edge of the tier, it will wrap around back to the other side and continue execution. The height and width of all tiers is determined by the largest height and width of all files that make up the program.
Tiers
Programs are made of 'tiers' which can be thought of as flat, bounded planes containing instructions, aligned directly on top of each other in a 3D space. Each tier maintains its own memory stack
, which can store either numbers (float or int) or strings as values at each index. This stack can have indices extending from -infinity to +infinity, and default every index contains the integer value of 0.
Each tier also has its own stack pointer, sp
. This stack pointer does not track the top of the stack, and is instead used by the programmer to traverse the stack. Many instructions are executed with respect to the stack pointer, as outlined below
Instructions
Controlling pc/vel
At every timestep, the pc will first execute the instruction at its current location, and then will take one step in the direction (right, left, up, or down) determined by its velocity.
Instruction | Operation |
---|---|
>
|
velocity right |
<
|
velocity left |
^
|
velocity up |
_
|
velocity down |
@
|
jump to specified tier |
#
|
end program |
Jumping from tier to tier can be done by placing the address of the desired tier after an @
sign.
For example: @413
will jump pc to the corresponding position of the @ sign in tier 413.
Controlling sp
The stack pointer 'sp' for each tier is initialised with a value of 0, and can be modified with the following commands:
Instruction | Operation |
---|---|
[
|
increment sp |
]
|
decrement sp |
Handling ts
The temporary storage location 'ts' for the program is initialised with an integer value of 0, and can be modified in a number of ways.
- ts is used to store any values which are evicted from the stack. Any time a new value is inserted into the stack, the previous value at that index is evicted. (Remember all indices are occupied by an int 0 by default).
- Values can be directly stored into ts by instruction.
The following instructions will affect ts in some way:
Instruction | Operation | Effect on ts |
---|---|---|
~
|
push the value in ts on top of the stack. | ts becomes 0 again, as 0 has been evicted at 'stack top +1' position |
(
|
copy value from current position at stack to ts | ts = stack[sp] |
)
|
copy value from ts to current position at stack | stack[sp] = ts |
,
|
put the value of sp in ts | ts = sp |
!
|
replace value at stack[sp] with its boolean NOT | the initial value at stack[sp] is evicted to ts |
:
|
pop item at current stack pointer. shift any items in stack above sp downwards to fill space | the initial value at stack[sp] is evicted to ts |
$
|
pop the item off the top of the stack* | the popped value is evicted to ts |
'<number>'
|
item will be stored as a number at stack[sp]. stored as either float or int. e.g. '123'
|
the previous value at stack[sp] will be evicted to ts |
"<string>"
|
item stored as a string at stack[sp] e.g. "hello" or "123"
|
the previous value at stack[sp] will be evicted to ts |
*Note that the top of the stack is found as the max(sp, highest inserted value)
Input received from stdin will also evict the previous value of stack[sp] to ts. (see Input/Output section below)
Artithmetic instructions
All of these instructions operate in virtually the same way. The expression is evaluated in the form of: stack[sp] {operator} stack[sp-1]
, and the result of this expression is pushed on top of the stack.
Instruction | Operation |
---|---|
+
|
addition. stack[sp] + stack[sp-1] |
-
|
subtraction. stack[sp] - stack[sp-1] |
*
|
multiplication. stack[sp] * stack[sp-1] |
/
|
division. stack[sp] / stack[sp-1] |
\
|
floor division. stack[sp] // stack[sp-1] |
%
|
modulo. stack[sp] % stack[sp-1] |
&
|
binary AND. stack[sp] & stack[sp-1] |
|
|
binary OR. stack[sp] | stack[sp-1] |
Branching/Conditional execution
The following instructions enable conditional execution to occur:
Instruction | Operation |
---|---|
=
|
check if stack[sp] == 0, and if so, then skip next the next instruction |
`
|
randomly place a 0 or 1 at stack[sp] |
?
|
check if stack[sp] > stack[sp-1] and if so, then skip the next instruction |
Input/Output
I/O is achieved through the following instructions:
Instruction | Operation |
---|---|
{
|
print stack[sp] to stdout |
}
|
read a value from stdin and place this into stack[sp]. evict previous value of stack[sp] to ts |
When input is read, the default type of the value will be a string. Therefore, to allow the user to input numerical types, the user should enclose the input with '
characters. e.g. '1234'
Other characters
Character | Operation |
---|---|
a-z A-Z 0-9
|
these are ignored unless enclosed within '', "" or after @ |
;
|
used to write comments. lines that start with ; should be treated as entirely whitespace by the interpreter/compiler |
SPACE
|
NOP (Non Operational). no effect |
.
|
NOP (Non Operational). no effect, but useful for outlining/indenting relative positions within files |
Example programs
Basic examples
Hello World
0.tier
"hello, world!"{#
Truth machine
If input is integer 0, output 0 and terminate. If input is integer 1, then output 1 forever.
0.tier
}=_{# >^
Cat
Copy input to output.
0.tier
}{#
Fibonacci
Infinitely generate Fibonacci numbers.
0.tier
"1\n"{'1'['1'+{"\n"{)[@1
1.tier
@0
Complex examples
Prime numbers
User inputs a number, program will correctly respond with 'Prime' or 'Not Prime'
0.tier
@1>[)]'1'[-[!=_)]@2:~[%[!=_]]$-$)>?@2[@3 }(^ 1@ < 1
1.tier
"Enter a number to check if prime:\n"{_ @0 >"Not prime\n"{# >
2.tier
........_3@?['2'~<>@0...#{"n\emirP"< > ^
3.tier
#{"n\emirP"<........4@................<
4.tier
>@0
Approximate e
Infinitely output increasingly accurate approximations of the mathematical constant e (2.71828...)
0.tier
![!/[+:]](~[[:~[@1..(]@1~_ 1@[)]$+]:{"n\"{:{" ~ e":[<
1.tier
>$[@0 .....>_....@0 ~=_[_..._< $>_ :]....2@[:]<.@....[ $.] *].2@.('1'_=<2@([<= $.] ^.[~([~:].<...2@[[.< ^$< .>]'1'[-[[[(:]]])?^^
2.tier
..... >@0>@0>_ . _..>...^@_ . _^......1<_ 1@ .....>...^.....<
Boolean XOR function
Outputs the boolean XOR of stack[sp] and stack[sp-1]
0.tier
'0'['1'_ > ](@1[(@1~[{#
1.tier
. ).@0~[_ 2@([&<._|]]< >=_['1'>]]=_[[['1'^ >['0'^ >[[['0'^ ^|<
2.tier
. >@0 _ ^........<
External resources
Implementation
I've made an interpreter for programs written in this language, which is available on my GitHub account[1] - go and check it out!
The interpreter is a single python file, and features helpful tools such as:
- A built-in visual debugger tool which allows fast and easy debugging of Tier programs.
- The option to specify the duration of each timestep when running.
- The option to print out debug information to console at each timestep.