v1.1 | Call stack update
An esoteric language that is guaranteed to give you a headache.
You will need to take some paracetamol after attempting to code in this, have a look:
eeeeee!e!eeee.e!Eeeeeeeeeeeeeee!e!eeee.Ee.E.e!ee!e!.ee.Ee.E.
e!ee!e!.eeeeeeeeeeeeeeee.Ee.E..e!ee!..Ee.E.e!eeeeee!e!
eeee.Ee.E.e!eeeeeeeeeeeeeeee!e!eeeeeeeeeeeeee.Ee.E.e!ee!..E
e.E.e!ee!.eeeeee.Ee.E.e!ee!e!.eeeeeeeeeeeeeeee.Ee.E.e!ee!e!..
Ee.E.e!eeeeee!.Ee.E.e!
Disgustingly beautiful right?
There now exists a migraine generator to ease the pain! Check it out
- 2 Immediate integer registers
- Where you'll be storing immediate values from functions
- The current usable register can be swapped with
E
- Function index
- Accesses all functions
- Can be traversed with
e
and, when the index is odd,! or .
will execute a goto function - Resets to 0 if the index is larger than the function list
- Program counter
- Keeps track of how far it is within the program
- Can be traversed through the branch function
- """Unlimited""" integer stack
- Lets you store values from registers. Basically makes this entire language functional
- Can be accessed through several stack functions
migraine has only 4 operation characters, but it lets you do everything you need.
Character | Operation | Purpose |
---|---|---|
e |
Function index increment | Iterates through the function list |
. |
Execute function | Executes the current function determined by the function index. Passes the current register to the function as a parameter |
! |
Execute function pass 0 | Very similar to . however this purposefuly passes 0 to the function instead of a register |
E |
Swap register | Swap the current register |
The interpreter has also been setup to ignore all characters following a #
character, this allows for comments in code files. Yipee! Documentation!
migraine uses a function list that you iterate through using the operators above in order to create logic. You might notice, you can only increment!
How do you decrement? This function list has a special function when the function index is an odd number, it has a goto function that allows you to traverse the function list however you fancy. e!
is used quite a bit in programs as it sets the function index back to 0.
Index | Function | Purpose |
---|---|---|
0 | number_0 | Sets the rightmost digit in the current register to 0 |
2 | number_1 | Sets the rightmost digit in the current register to 1 |
4 | number_2 | Sets the rightmost digit in the current register to 2 |
6 | number_3 | Sets the rightmost digit in the current register to 3 |
8 | number_4 | Sets the rightmost digit in the current register to 4 |
10 | number_5 | Sets the rightmost digit in the current register to 5 |
12 | number_6 | Sets the rightmost digit in the current register to 6 |
14 | number_7 | Sets the rightmost digit in the current register to 7 |
16 | number_8 | Sets the rightmost digit in the current register to 8 |
18 | number_9 | Sets the rightmost digit in the current register to 9 |
Okay before we continue. This number function is pretty versatile. You can chain them using .
to assemble numbers.
ee ee ee!
would set the current register to 3. If we were to then do ee.
immediately afterwards, the current register would now be 34.
Say we want to reset the current register back to 0, we can do e!
to reset the function index to 0, and then !
which would set the current register to 0
This works because the number function internally looks something like this:
int number(int intRegister, int digit)
{
return (intRegister * 10) + digit;
}
It will always shift to the left to allow for a new digit, however when you pass 0 through (instead of a register) it resets.
Index | Function | Purpose |
---|---|---|
20 | add | Adds the non-current register to the current register |
22 | subtract | Subtracts the current register from the non-current register |
24 | multiply | Multiplies the non-current register to the current register |
26 | divide | Divides the current register from the non-current register |
28 | input | Gets input from stdin through the console, copies to the current register |
30 | output_int | Output the current register as an integer to the console |
32 | output_char | Output the current register as a character to the console |
34 | compare_equals | Check if the current register is equal to the non-current register, the current register will be overwritten with the result |
36 | compare_greater | Check if the current register is greater than the non-current register, the current register will be overwritten with the result |
38 | branch | If the current register has a value greater than 0, it will set the program counter to the non-current register v1.1 Change Pushes the current address to the call stack before branching |
40 | branch_return | Return to the last address saved on the call stack |
42 | callstack_pop | Pop the last address saved on the call stack. This does NOT return to the current register |
44 | stack_push | Push the current register to the stack |
46 | stack_pop | Pop from the top of the stack and overwrite the current register with the popped value |
48 | stack_read | Read the stack by accessing at an index provided by the current register, the current register will be overwritten with the read value |
50 | stack_write | Write to the stack by accessing at an index provided by the current register, overwrites the stack entry with a new value from the non-current register |
Annnndd, that's all of them! That's the official function list however due to migraine being structured this way, it is completely possible to amend more functions to it. The only issue is, the higher the index, the more e
's are required to access them!!!
All functions listed in the table (notice goto is left out, it's a special little guy) follow this pattern:
currentRegister = function(EITHER currentRegister OR 0);
The result will always be given back to the current register.
I recommend checking out the ./Examples folder as I've included a few usable code demos with documentation!
Ok so.... This change breaks the ABI, v1.0 programs will not run on v1.1. LUCKILY I can guarantee that I am the only individual using this at the minute so I'm allowed to break things :P
We really need a call stack if we want any meaningful programs to be made, it makes sense to group these new functions next to the pre-existing branch function as that is directly involved.