8f4e is a stack oriented programming language with a visual code editor that I created to perform generative music at algorave events.
Its primary target is the WebAssembly virtual machine, as I wanted an efficient yet portable tool for real time audio signal generation and processing.
Stack oriented programming means that instead of using registers, instructions take their operands from a stack, and push their results back onto the same stack for the next instruction.
I chose this programming paradigm because the WebAssembly virtual machine is itself a stack machine.
Staying native to this execution model avoids costly abstractions and makes it possible to build a simpler and faster compiler.
... 067 push 2 068 push 3 069 ; Pushing values 2 and 3 069 ; onto the stack. 070 add 071 ; After executing the 071 ; add instruction, 072 ; the stack will contain 072 ; the value 5 073 push 10 074 mul 075 ; Now the stack will 075 ; contain the value 50 076 push 10 077 div 078 ; Now 5 again ...
In 8f4e memory addresses are determined by the compiler, therefore dynamic memory allocation is not possible.
One advantage of this design is that memory addresses can be inlined compile time, which allows for faster access and less runtime overhead.
... 003 int result ... 069 push &result 070 ; The variable name 071 ; prefixed with & 072 ; gives its memory address. 073 push 42 074 store 075 ; The store instruction 076 ; takes two values: 077 ; a memory address 078 ; and the value to store. ...
All memory items are laid out sequentially within the memory, so variables declared one after another occupy adjacent memory locations.
They're allocated on a 32-bit grid, which means that every memory item starts at an address that is a multiple of 4 bytes.
003 int a 42 004 005 float b 3.14 006 ; Memory address of b 007 ; is address of a + 4 008 009 int c -5 010 ; Memory address of c 011 ; is address of b + 4
Programs in 8f4e run inside an endless loop. This reflects how real time audio systems operate, where processing consists of continuously reading from and writing to audio buffers.
8f4e removes this control flow boilerplate and allows programs to focus purely on signal generation and transformation.
The code is organized into modules, each containing variable declarations and a sequence of commands.
The execution order of the code modules is determined by their dependencies. If a module's output is needed as input for others, it is executed first.
... 001 module foo 002 003 int a 10 004 int b 20 005 int result 006 007 push &result 008 push a 009 push b 010 add 011 store 012 013 moduleEnd ...
It supports real-time manual modification of variable values while the program is running, without needing recompilation.
This is made possible by the deterministic allocation strategy: because memory addresses are fixed at compile time, the compiler can provide the exact address of every memory item, allowing the editor to locate and update any variable directly in memory.
... 003 int foo 10 004 ; You can change these 005 ; values in the editor 006 ; while the program is running. 007 float bar 3.14 008 ; The editor will trace 009 ; them back in the memory 010 ; and update their values 011 ; without restarting 012 ; or recompiling the program. ...
All variables in 8f4e are inherently public, with no option to modify visibility.
Also, it's not memory safe, pointers can point to anything within the memory space of the program, but the wires help developers to find where their pointers are pointing.
... 003 int* pointer 004 005 push &pointer 006 push pointer 007 push 4 008 push add 009 store 010 ; pointer will iterate through all 011 ; possible memory addresses. ...