Pit
Pit is an Esoteric programming language by user:david.werecat which is designed to be extremely low level.
About The Language
Pit is a language which was supposed to be so low level, it would make most other esoteric languages look like BASIC. It could be a lot more low level (since all devices and memory are pre-initialized and there are no "real" CPU control instructions), but the author decided not to be that sadistic. Source files can be coded in a script format similar to assembler or can be written as a bytecode file using a hex editor. The textual script format must assembled into bytecode before running.
Instructions
Language Basics
Pit bytecode is run in a virtual machine that is hosted by the interpreter. The virtual machine has three major parts: the CPU, the memory controller and the device hub. The CPU executes the program code sequentially until the end of codespace is reached or an OFF
instruction is encountered. The memory controller hosts the VM's memory. All memory in Pit is bitwise. The memory is split into three parts: MemorySpace, CodeSpace and CacheSpace. CodeSpace is a section of memory stored directly before MemorySpace. It contains the program code and can be reached by decrementing the memory pointer until it goes below zero. MemorySpace is where the memory available to the program is stored. MemorySpace is indexed by a pointer bounded by the size of the VM's memory (32mb in the reference implementation). The memory available to the VM can theoretically be infinite, however. CacheSpace is a 16 bit chunk of memory separate from the other memory spaces. The CPU can only perform operations on memory in CacheSpace, although can move memory between CacheSpace and MemorySpace. The final part of the Pit Virtual Machine is the device hub. The device hub maintains a packet queue of messages from the various virtual hardware devices and also acts as an interface to send messages to all attached devices. The device hub automatically sets up, initializes and shuts down all devices.
Pit Assembly Language
Most Pit coding can be done it a more human readable assembly language ("*.pit" files). Each line of source code can either be blank, a comment or a command. To create a comment in the Pit assembly language, prefix the line with a tilde (~). Commands are usually a three letter instruction code followed by a space then followed by one hexadecimal character as a parameter for the command (eg. PUT B
). Every command must have a parameter, even if it is not used. To assemble a Pit assembly language script, call the implementation with the argument a
followed by the source file path and the destination file path of where to write the assembled binary.
Pit Bytecode
All Pit programs must be in their bytecode form in order to run. A Pit bytecode binary consists of several 8 bit instructions. Each 8 bit instruction is divided into two parts: the first 4 bits for the opcode, and the last 4 bits for the parameter. As stated previously, the binary file is loaded into memory before MemorySpace and is executed from there.
Pit Instructions
Pit accepts the following instructions:
Name | OpCode | Description |
---|---|---|
PSH | 0 | Pushes the current instruction's location to the stack specified by the parameter. If the parameter is zero, this instruction acts as a NOP |
POP | 1 | Removes the top element of the stack specified by the parameter. If the parameter is zero, all stacks are cleared. Note that the current instruction is not changed by this instruction. |
JMP | 2 | Peeks the top element of the stack specified by the parameter and jumps to that location. If the parameter is zero, jump to the matching FLG instead.
|
FLG | 3 | Does nothing, a placeholder for the JMP 0 instruction. The parameter is not used.
|
SKP | 4 | Skips the next instruction if the bit at the cache location specified by the parameter is 1. |
NOT | 5 | Toggles the bit at the cache location specified by the parameter. |
GET | 6 | Reads the bit pointed to in the memory to the cache location specified by the parameter. |
PUT | 7 | Writes the bit from the cache location specified by the parameter to the bit pointed to in the memory. |
RET | 8 | Sets the memory pointer to zero. The parameter is not used. |
DEC | 9 | Decrements the memory pointer by the value of the parameter. If the parameter is 0, it represents 16 instead. |
INC | A | Increments the memory pointer by the value of the parameter. If the parameter is 0, it represents 16 instead. |
SND | B | Sends a bit from the cache location specified by the parameter to the device hub. |
RCV | C | Receives a bit from the device hub into the cache location specified by the parameter. If there is no data to receive, a 0 is received. |
ERR | D | Sets the cache location specified by the parameter to the value of the error flag, then sets the error flag to 0. |
HLT | E | Suspends execution for 2^parameter milliseconds. |
OFF | F | Powers the VM off. The parameter is not used. |
Devices and Packet Format
Pit supports up to 8 different devices with the default device hub. Currently, the following devices are defined:
- 000 - Console
- 001 - Beep
The device hub communicates with the devices using a standard packet format: {1 bit StartOfPacket, always 1}{3 bits DEVICE_ID}{n tuples DATA}{1 bit EndOfPacket, always 0}
For example, to encode a packet with the message 0011 to device 101, the following packet would be sent: 1 101 10 10 11 11 0
A tuple is two bits, the first representing the packet type (0 for EOP, 1 for DATA), the second being the packet data. The second bit is only included if the first bit is 1.
The following packets are supported:
Device | Type | Size | Description |
---|---|---|---|
000 (console) | RCV | 0 | Represents an EOF. |
000 (console) | RCV | 8 | Represents a keypress, its value is the ASCII code of the keypress. |
000 (console) | SND | 0 | Clears the console. |
000 (console) | SND | 1 | If 0, the cursor is hidden; if 1, the cursor is shown. |
000 (console) | SND | 2 | Moves the cursor by one in the direction indicated by the data: 00=up, 01=right, 10=down, 11=left |
000 (console) | SND | 5 | Sets the console color. The first bit is 0 for the foreground color or 1 for the background color; the other four bits are the color value. |
000 (console) | SND | 8 | Writes a character with the ASCII code specified by the data to the console. |
001 (beep) | SND | 0 | Sounds a beep with the current parameters. The default is Frequency=800hz Duration=250ms |
001 (beep) | SND | 16 | Sets the frequency parameter in hertz to the data value. |
001 (beep) | SND | 20 | Sets the duration parameter in milliseconds to the data value. |
Note that the size is the size of the data, not the size of the packet.
Programming Help
Since Pit defines no methods of logical operators, math or algorithms there is a page to help with basic programming in Pit. Alternatively, you could do it the fun way and figure it out for yourself.
Sample Programs
CAT Program
~The main loop PSH 1 ~Wait for a 1 from the device hub PSH 1 ~Wait for 1ms to keep CPU usage low HLT 0 ~Read a bit from the device hub RCV 0 SKP 0 JMP 1 ~Check for a device_id of 0 (console) ~Set cache(0) to 0 NOT 0 ~Read each bit and update accordingly RCV 1 SKP 1 JMP 0 ~Set the cache(0) to 1 SKP 0 NOT 0 FLG 0 RCV 1 SKP 1 JMP 0 ~Set the cache(0) to 1 SKP 0 NOT 0 FLG 0 RCV 1 SKP 1 JMP 0 ~Set the cache(0) to 1 SKP 0 NOT 0 FLG 0 ~If it wasn't 0, read to the end of the packet and continue waiting for events SKP 0 JMP 0 PSH 1 RCV 2 ~If the bit is a 0, it is EOM, so no more bits NOT 2 SKP 2 RCV 3 SKP 2 JMP 1 POP 1 FLG 0 NOT 0 ~If cache(0) is 0, the device_id was 0 (console), so write the keyval to the console SKP 0 JMP 0 ~Check for EOF (null packet) and exit if EOF RCV 3 SKP 3 POP 1 SKP 3 OFF 0 ~Write packet header for the console (device_id 0) ~Set cache(2) to 1 SKP 2 NOT 2 SND 2 NOT 2 SND 2 SND 2 SND 2 ~Copy the start of the packet SND 3 RCV 3 SND 3 ~Copy packet until EOM PSH 1 RCV 2 SND 2 ~If the bit is a 0, it is EOM, so no more bits NOT 2 SKP 2 RCV 3 SKP 2 SND 3 SKP 2 JMP 1 POP 1 FLG 0 JMP 1 ~Cleanup POP 1 OFF 0
Hello, world!
NOT 1 SND 1 SND 0 SND 0 SND 0 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 SND 2 SND 1 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 0 SND 1 SND 0 SND 0 SND 0 SND 1 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 1 NOT 2 SND 2 SND 1 SND 2 SND 1 SND 2 SND 1 SND 2 SND 1 NOT 2 SND 2 SND 0 OFF 0
Additional Help
If anything isn't clear, there's a bug in the reference implementation, something could be improved, etc... feel free to write a comment in the talk page and I'll get around to it as soon as I can.
External resources
Reference implementation and sample programs (needs .net framework)