MEMORYLEEK
Paradigm(s) | Procedural, imperative |
---|---|
Designed by | User:Aadenboy |
Appeared in | 2024 |
Memory system | Pointer-based dynamic memory |
Computational class | Turing complete |
Major implementations | None |
Influenced by | C |
Influenced | The Sophomores From Tbilsi |
File extension(s) | .meml |
- Not to be confused with memory leaks.
MEMORYLEEK (also called "MEMLEEK" and "MLEEK") is a pointer-based language designed to maximize memory leakage. While the idea was only intended as a gimmick, the language could have reasonable use in learning memory management.
Memory Structure
The memory of MLEEK is split into two arrays: a linear array of integer values and an associative array of pointers to those values.
MLEEK has no garbage collection. Values remain created until explicitly removed with a pointer. All operations and expressions are evaluated eagerly, meaning they are calculated when first encountered. This causes significant bloat in value memory.
Pointers, when first created, are "inactive pointers," meaning they don't point anywhere. They return a value of zero but don't imply any value. Pointers reference a value with an index, which updates automatically if an earlier value is removed or if the referenced value is removed. Dangling pointers and cyclic references are not possible.
The program checks if you have properly managed your memory at certain points:
- At the end of the program's execution
- The program expects that your memory is fully clean and void of any references or values.
- At the end of a function call
- The program expects that any values and references created within the call are removed.
- Before a loop restarts
- The program expects that any values and references created within the loop before the restart are removed.
Handling Expressions
Expressions and operations are evaluated eagerly, meaning they are processed as soon as they are encountered. Values are created when not yet defined, causing significant bloat within value memory.
The steps for performing an equation are as such:
- Go through each value within the equation.
- If the value is a pointer, replace the value with whatever the pointer references.
- If the value is a value, place the value into memory.
- Evaluate operations.
- After completing an operation, leave the original values alone and create a new value with the result, storing it in memory.
- Repeat until no operations are left.
For example, take (a % 5)^2
(where a
points to a value of 7):
(a % 5)^2
— Check and replace values.a
is replaced with 7. 5 and 2 are stored in memory.- Value memory: [7, 5, 2]
(7 % 5)^2
— Compute(7 % 5)
.- The result is 2. Replace the operation with the result and store it in memory.
- Value memory: [7, 5, 2, 2]
2^2
— Compute2^2
.- The result is 4. Replace the operation with the result and store it in memory.
- Value memory: [7, 5, 2, 2, 4]
4
— Finish here.
Instructions
Instructions are separated with semicolons or newlines. An equation on its own will be considered an instruction and computed.
Instruction | Name | Description |
---|---|---|
point [n] |
Make pointer | Creates a new pointer under the name [n] .
|
value [v] |
Make value | Creates a new value with the value [v] .
|
[p] = [o] |
Assign | Syntactic sugar for [o]; [p] ~> -1
|
[p] ~~ [v] |
Reassign | Reassigns the value [p] points to with a new value [v] . This instruction does not create a new value, but also cannot perform operations.
|
[p] ~> [i] |
Point to | Points pointer [p] to the value with index [i] . If [i] is negative, it instead points to the value with index (total values) - [i] . This instruction does not create a new value, but also cannot perform operations.
|
#[p] |
Remove value | Removes the value the pointer [p] is pointing to.
|
:[p] |
Remove pointer | Removes the pointer [p] .
|
}[f] [...] |
Function call | Calls the function [f] . [f] is a value (or pointer pointing to a value) which denotes the line to jump to. [...] are the values to pass.
|
pass |
Pass | Skips instructions until an exit or back loop instruction is met. |
pass [p] |
Named pass | Like the pass instruction, but it also creates a pointer with a value referring to the line it’s at. |
exit |
Exit | Exits a function call or condition. |
expect [n] |
Expect values | Used by functions. Asserts if the amount of values given to a function call equals [n] .
|
until [c] |
Until condition | Creates a condition that checks if [c] is equal to 0. If it is not equal to 0, it skips instructions until an exit or back loop instruction is met.
|
back |
Back loop | Loops back to the previous until condition. |
![v] |
Print number | Prints the value [v] to the screen as a number. This will create a value if possible.
|
?[v] |
Print symbol | Prints the value [v] to the screen as it’s corresponding UTF-8 character. This will create a value if possible.
|
input |
Take input | Asks the user for input. The UTF-8 codes of each character are created. |
input [m] |
Constrained input | Like the take input operation, but the characters that are passed are limited to only [m] characters.
|
vnput [p] |
Value input | Like the take input operation, only it takes in a single number and points the pointer [p] to it.
|
[v1] + [v2] |
Addition operation | Adds [v1] and [v2] together, creating a new value with the result.
|
[v1] - [v2] |
Subtraction operation | Subtracts [v1] against [v2] , creating a new value with the result.
|
[v1] * [v2] |
Multiplication operation | Multiplies [v1] with [v2] , creating a new value with the result.
|
[v1] / [v2] |
Division operation | Divides [v1] against [v2] , creating a new value with the result.
|
[v1] % [v2] |
Modulo operation | Performs modulo on [v1] and [v2] , creating a new value with the result.
|
[v1] ^ [v2] |
Exponentation operation | Raises [v1] to the power of [v2] , creating a new value with the result.
|
$[v1] |
Logical NOT operation | Creates a new value 1 (true) or 0 (false) if [v1] is equal to 0.
|
$$[v1] |
Bitwise NOT operation | Performs bitwise NOT on [v1] , creating a new value with the result.
|
[v1] & [v2] |
Logical AND operation | Creates a new value 1 (true) or 0 (false) if both [v1] and [v2] are not equal to 0.
|
[v1] && [v2] |
Bitwise AND operation | Performs bitwise AND on [v1] and [v2] , creating a new value with the result.
|
[v1] | [v2] |
Logical OR operation | Creates a new value 1 (true) or 0 (false) if [v1] , [v2] or both are not equal to 0.
|
[v1] || [v2] |
Bitwise OR operation | Performs bitwise OR on [v1] and [v2] , creating a new value with the result.
|
[v1] @ [v2] |
Logical XOR operation | Creates a new value 1 (true) or 0 (false) if either [v1] or [v2] does not equal 0, but not both.
|
[v1] @@ [v2] |
Bitwise XOR operation | Performs a bitwise XOR on [v1] and [v2] , creating a new value with the result.
|
[p1] ~= [p2] |
Pointer location operation | Creates a new value 1 (true) or 0 (false) if pointers [p1] and [p2] point to the same location.
|
[v1] == [v2] |
Value equality operation | Creates a new value 1 (true) or 0 (false) if [v1] and [v2] are equal to each other.
|
[v1] > [v2] |
Value greater than operation | Creates a new value 1 (true) or 0 (false) if [v1] is greater than [v2] .
|
[v1] < [v2] |
Value less than operation | Creates a new value 1 (true) or 0 (false) if [v1] is less than [v2] .
|
/[p] |
Inactive pointer operation | Creates a new value 1 (true) or 0 (false) if pointer [p] is inactive.
|
>> |
Value count operation | Creates a new value with the amount of values when this operation was called. |
<< |
Pointer count operation | Creates a new value with the amount of pointers when this operation was called. |
<> |
Inactive pointer count operation | Creates a new value with the amount of inactive pointers when this operation was called. |
~?[p] |
Pointer index operation | Creates a new value with the index of pointer [p] .
|
.[p] |
Protect | Protects a pointer and its value from being checked. Also can be used to remove protection. |
[ ... ] |
Comment | A comment. |
Example Programs
Hello, World! Program
point print print = 72; ?print [H] print ~~ 101; ?print [e] print ~~ 108; ?print; ?print [ll] print ~~ 111; ?print [o] print ~~ 44; ?print [,] print ~~ 32; ?print [ ] print ~~ 87; ?print [W] print ~~ 111; ?print [o] print ~~ 114; ?print [r] print ~~ 108; ?print [l] print ~~ 100; ?print [d] print ~~ 33; ?print [!] #print; :print [cleaning up]
Truth Machine
point d; vnput d until $d point remove; remove ~> 2; #remove; :remove ?d back point remove; remove ~> 2; #remove; :remove ?d; #d; :d
Brainfuck Interpreter
This also serves as a proof for MEMORYLEEK's Turing completeness.
pass remove expect 1 point rem rem ~> -1; rem ~> rem; #rem (get index, go to index, remove) rem ~> -1; #rem; :rem (get input, remove input, clean) exit input [getting input program] point start [of tape] start = >> + 3 [=======> +3 to account for start and end values] }remove -2; }remove -2 point end [of tape] end = start + 99 [one less to account for first tape cell] }remove -2 [creating tape] point i until ~?i == end }remove -1; }remove -1; value 0; i ~> -1 back }remove -1; }remove -1; :i [running program] point symbol point cell symbol ~> 2 cell ~> start until ~?symbol > (start - 3) }remove -1; }remove -1; }remove -1 until $(symbol == 62) [> instruction] cell = ~?cell + 1; cell ~> cell }remove -1; }remove -1; }remove -1; exit }remove -1; }remove -1; }remove -1; until $(symbol == 60) [< instruction] cell = ~?cell - 1; cell ~> cell }remove -1; }remove -1; }remove -1; exit }remove -1; }remove -1; }remove -1; until $(symbol == 43) [+ instruction] point calc; calc = (cell + 1) % 256 cell ~~ calc; :calc }remove -1; }remove -1; }remove -1; }remove -1; }remove -1; exit }remove -1; }remove -1; }remove -1; until $(symbol == 45) [- instruction] point calc; calc = (cell - 1) % 256 cell ~~ calc; :calc }remove -1; }remove -1; }remove -1; }remove -1; }remove -1; exit }remove -1; }remove -1; }remove -1; until $(symbol == 46) [. instruction] ?cell exit }remove -1; }remove -1; }remove -1; until $(symbol == 44) [, instruction] point in; vnput in cell ~~ in; :in }remove -1; exit }remove -1; }remove -1; }remove -1; until $(symbol == 91) | cell [[ instruction] point count [for scope checking] count = 1 until count == 0 | ~?symbol == (start - 3) }remove -1; }remove -1; }remove -1; }remove -1; }remove -1; }remove -1; }remove -1; symbol = ~?symbol + 1; symbol ~> symbol }remove -1; }remove -1; }remove -1; until $(symbol == 91) point calc; calc = count + 1 count ~~ calc; :calc }remove -1; }remove -1; exit until $(symbol == 93) point calc; calc = count - 1 count ~~ calc; :calc }remove -1; }remove -1; exit back }remove -1; }remove -1; }remove -1; }remove -1; }remove -1; #count; :count exit }remove -1; }remove -1; }remove -1; }remove -1; until $(symbol == 93) | $cell [] instruction] point count [for scope checking] count = 1 until count == 0 | ~?symbol == 2 }remove -1; }remove -1; }remove -1; }remove -1; }remove -1; }remove -1; symbol = ~?symbol - 1; symbol ~> symbol }remove -1; }remove -1; }remove -1; until $(symbol == 91) point calc; calc = count - 1 count ~~ calc; :calc }remove -1; }remove -1; exit until $(symbol == 93) point calc; calc = count + 1 count ~~ calc; :calc }remove -1; }remove -1; exit back }remove -1; }remove -1; }remove -1; }remove -1; }remove -1; #count; :count exit }remove -1; }remove -1; }remove -1; symbol = ~?symbol + 1; symbol ~> symbol; }remove -1; }remove -1; }remove -1; until ~?cell < start cell ~> end exit }remove -1; }remove -1; }remove -1; until ~?cell > end cell ~> start exit }remove -1; }remove -1; }remove -1; back [clean up] :remove; :start; :end; :symbol; :cell [remove all values] point i i ~> 1 until /i }remove -1; #i; i ~> 1 back }remove 1; :i