- Typing discipline:
- Versions and implementations (Collapse all | Expand all):
Hack VM is a tiny programming language (though its author calls it “virtual machine for hackers”, it still deserves to be called a language, since it is simple enough to write code by hand).
The main (and only) purpose of this language is to use it in hacker.org challenges: some of the tasks require writing a program which produces a certain result. This makes this language one of the few really used esoteric languages.
A program in Hack VM is a string of single-character commands. Virtual machine starts with the first instruction, executes it, moves on to the next instruction, and so on. The index of the current instruction is called the program counter. The execution is terminated either when end of program is reached, ‘!’ instruction is met or some run-time exception is thrown.
Hack VM is a stack-based language: the virtual machine consists of an operand stack, a memory buffer, and a call stack. Each item on the operand stack or in memory is a cell that can hold a 32-bits signed integer. The call stack is used to push the value of the program counter when jumping to a routine from which we want to return. The memory buffer holds 16384 cells, indexed in 0-based way. By default, the execution starts with empty call stack, empty operand stack and all the cells in the memory buffer set to 0. It is possible to initialize the memory buffer with user-defined values, which can be used to simulate user input.
The commands of the language are the following (here S<n> denotes n-th element off the top of the stack: S0 is the topmost element):
' ': Do nothing (used for readability purposes)
'p': Print S0 as an integer
'P': Print S0 as an ASCII character (only the least significant 7 bits of the value are used)
'0'..'9': Push the value 0..9 on the stack
'+', '-', '*', '/': Push S1+S0, S1-S0, S1*S0, S1/S0
':': Push -1 if S1<S0, 0 if S1=S0, or 1 S1>S0
'g': Add S0 to the program counter
'?': Add S0 to the program counter if S1 is 0
'c': Push the program counter on the call stack and set the program counter to S0
'$': Set the program counter to the value popped from the call stack
'<': Push the value of memory cell S0
'>': Store S1 into memory cell S0
'^': Push a copy of S<S0+1> (ex: 0^ duplicates S0)
'v': Remove S<S0+1> from the stack and push it on top (ex: 1v swaps S0 and S1)
'd': Drop S0
'!': Terminate the program
Note that elements of the stack which are used are removed from it in most commands: thus, ‘+’ command removes its arguments, as well as ‘P’.
Elements of syntax:
This program works in a rather evident way — ASCII-codes of characters of the message are calculated one-by-one and printed out. The only bit of hack used is processing of ‘l’ character — once its ASCII-code is calculated, it is tripled in the stack (using
0^ command), and printed twice immediately and once later.
89*P 45*99*+P 39*99*+0^0^PP 56*99*+P 29+4*P 48*P 92+8*1-P 56*99*+0^P 3+P P 25*0^*P 56*3+P
This example works much like the other Fibonacci numbers in esoteric languages: memory cell 0 stores the number of numbers left to calculate, cells 1 and 2 store ASCII-codes for comma and space, and cells 3 and 4 store two last calculated Fibonacci numbers. In a loop values of cells 3 and 4 are extracted, added together, the new value is printed, and storage cells are updated. After this, the number of numbers left is decremented, and if it’s 0, program counter (equivalent of instruction pointer in Brainfuck) is moved 6 cell forward, otherwise it jumps back to the start of the loop. Finally, three dots are printed.
27*0> 92+4*1> 84*2> 10^p3> 1<P 2<P 10^p4> 1<P 2<P 3< 4< + 0^p 4< 3> 4> 0< 1- 0> 0< 6? 67*c 58*6+0^0^PPP
This example is pretty similar to Fibonacci numbers one, just with more characters to output. Note that data type is 32-bit integers, so 13! overflows: the output look like this:
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
!ERROR: integer overflow
28*0> 56*3+1> 84*2> 78*5+3> 25*4> 05> 16> 5<p1<P2<P3<P2<P6<p4<P 5<1+5> 5<6<*6> 0<1-0> 0<6? 67*c