GASOIL
GASOIL (General Application Stack Oriented Imperative Language) is a postfix notation esoteric programming language invented by User:Morex in 2009.
Description
The main idea was to test a language (and interpreter) that instead of loading the program in a fixed memory, loads the program in a "program stack". This way the program is freeing memory as it is executed (instructions are not available anymore once they are executed (except calling a subroutine more than once)). There is no need for an "Instruction Pointer", meaning recursion is the only way to implement loops.
Inspiration for creating GASOIL was taken from the HP-41C and HP-28S (RPL) languages.
The GASOIL programming language is:
- Imperative
- Structured
- Recursive without a call stack or return stack (Infinite recursive loops do not overflow)
- Stack oriented (with a data stack and a program stack)
- Full postfix (for operators, functions, and control structures too)
- Reflection oriented (code can create code to be run on the fly)
GASOIL has a lot of features: One Program Stack (PS), one Data Stack (DS), one directionable memory area for variable data storing, arithmetic functions, a lot of stack functions, control structures, comments, logic operators, subroutine calls, recursion and a rich instruction set.
Both stacks and the memory area can handle diferent data types in each memory cell. These data types are:
- Floating point numbers
- Strings, enclosed in ""
- Program Instructions
- Program Blocks, enclosed in () with elements delimited by ;
The interpreter environment should let the user interact with the Data Stack, Showing output values, and letting users enter Input values.
Standar I/O functions READ and WRITE are available too.
When running, in each step, the interpreter pops an element from the PS and takes the following actions depending on the data type:
- If the element is a valid Instruction then it is executed.
- If the element is a Number, a String or a Program block, it is pushed to DS.
The execution stops when the program stack is empty.
The PARSE instruction pops a program block from the DS (or a string containing a program block), and after parsing, push the resultant elements backwards on the Program Stack.
Instructions
Literals
- Numbers: 2, -4, 3.1416
- Strings: "Hello"
- Program Blocks: (1; 2; +; NOP Add 1 plus 2)
Flow Control
- PARSE: Pop a program block from the DS (or a string containing a program block), and after parsing, push the resultant elements backwards on the Program Stack.
- CALL: Load a named subroutine pushing it to the PS
- CCALL: Conditional Call - Load a named subroutine pushing it to the PS if condition is true.
- STOP: Stop execution. User can resume.
- NOP: Do Nothing. Ignore rest of element. Could be used to code comment: (1; NOP This is a comment; 2; +; NOP Another comment)
Extended Flow Control
These instructions could be implemented or not in lightweight interpreters. It is possible to write them as GASOIL subroutines based in CCALL.
- ITE (If Then Else): Pop three DS elements: Cond.Value; (then block); (else block); ITE
- WHILE: Pop two DS elements: (Condition expresion); (Block); WHILE
- UNTIL: Pop two DS elements: (Block); (Condition expresion); UNTIL
- FOR: Pop four DS elements: Memory_address; InitialValue; FinalValue; (Block); FOR
Arithmetic
- +
- -
- *
- /
- MOD
- SQRT
- RND: Returns a pseudo-random number less than 1 but greater than or equal to 0
- INT: Truncate a number to integer
Stack
- DROP: Drop the #1 DS element
- DROP2: Drop the #2 DS element
- DROP3: Drop the #3 DS element
- DROP4: Drop the #4 DS element
- DUP: Duplicate the #1 DS element
- DUP2: Duplicate the #1 and #2 DS elements
- DUP3: Duplicate the #1, #2 and #3 DS elements
- DUP4: Duplicate the #1, #2, #3 and #4 DS elements
- SWAP12: Swap DS elements #1 and #2
- SWAP13: Swap DS elements #1 and #3
- SWAP23: Swap DS elements #2 and #3
- SWAP14: Swap DS elements #1 and #4
- SWAP24: Swap DS elements #2 and #4
- SWAP34: Swap DS elements #3 and #4
Logic & comparison
- =: Pop two DS elements: If #1 = #2 then push 1 (true) else push 0 (false)
- >
- >=
- <
- <=
- !=
- NOT
- AND
- OR
- XOR
Memory access
- STO: Pop two DS elements. Store #2 DS value onto memory address pointed by #1 DS value
- RCL: Pop one DS element. Push to DS the value from memory address pointed by #1 DS value
I/O
- READ
- WRITE
String manipulation
- &: Concatenate two strings
- STRLEN: Find the length of a string
- INSTR: Return a number specifying the start position of the first occurrence of one string within another
- SUBSTR: Return a string containing a specified number of characters from a string
- REPLACE: Return a string in which a specified substring has been replaced with another substring
- ASCII: Return a number representing the character code corresponding to a character
- CHR: Return the character associated with the specified character code
- STR2NUM: Return the number contained in a string as a numeric value
- NUM2STR: Return a string representation of a number
Examples
main ("Hello World!"; WRITE)
Endless loop
main (NOP This is a endless loop; "main"; CALL)
Fibonacci numbers up to 100
main (1;1;"suma";CALL) suma (DUP2; +; DUP; 100; < ; "suma"; CCALL)
Add integers up to 20 using CCALL
main (0; 1; 0; STO; "r"; CALL) r (0; RCL; +; 0; RCL; 1; +; DUP; 0; STO; 20; <=; "r"; CCALL)
Add integers up to 20 using WHILE
main (0;1;0;STO;(0;RCL;20;<=);(0;RCL;+;0;RCL;1;+;0;STO);WHILE)
Add integers up to 20 using UNTIL
main (0;0;0;STO;(0;RCL;1;+;0;STO;0;RCL;+);(0;RCL;20;=);UNTIL)
Add integers up to 20 using FOR
main (0;0;1;20;(0;RCL;+);FOR)
Prime number generator up to 50
( 0; NOP Reg 0 for outer loop; 2; NOP from 2; 50; NOP to 50; ( 1; 1; STO; NOP Flag as prime; 2; NOP Reg 2 for inner loop; 2; NOP from 2; 0; RCL; SQRT; INT; NOP to Int(sqrt(Reg 0)); ( 0; RCL; 2; RCL; /; DUP; INT; =; NOP eval (Reg 0 / Reg 2 = int(Reg 0 / Reg 2) ?); (0; 1; STO); NOP Then Flag as No prime; (NOP); ITE ); FOR; 1; RCL; 1; =; NOP Is Prime Flag set?; (0; RCL; " es primo."; &); NOP Push info if Prime; (NOP); ITE ); FOR )
99 Bottles of Beer
main (99; 0; STO; ""; ("e1"; CALL; 0;RCL; 1; -; 0; STO; "e2"; CALL); (0; RCL; 1;<=);UNTIL; "e1"; CALL; "n"; &; "f2"; CALL; &; "f1"; CALL; &; "."; &; 10; CHR; &; "N"; &; "f2"; CALL; &; "f1"; CALL; &; ", n";&;"f2";CALL;&;". Go to the store and buy some more, "; &; 99; 0; STO; "bo"; CALL; &; "f1"; CALL; &; "."; &) e1 ("bo"; CALL; &; "f1"; CALL; &;", "; &; "bo"; CALL; &; ". Take one down and pass it around, ";&) e2 ("bo"; CALL ;&; "f1"; CALL; &; "."; & ;10;CHR;&) bo (0; RCL; " bottle"; &; 0; RCL; 1; =; (""); ("s"); ITE; &; " of beer"; &) f1 (" on the wall") f2 ("o more bottles of beer")
Brainfuck interpreter
main ("Input Brainfuck code"; READ; ""; &; 0; STO; DROP; 1; 1; STO; 2; 3; 100; (0; 2; RCL; STO); FOR; 3; 2; STO; (0; RCL; STRLEN; 1; RCL; >=); (0; RCL; 1; RCL; 1; SUBSTR; CALL; 1; RCL; 1; +; 1; STO); WHILE) > (2; RCL; 1; +; 2; STO) < (2; RCL; 1; -; 2; STO) + (2; RCL; DUP; RCL; 1; +; SWAP12; STO) - (2; RCL; DUP; RCL; 1; -; SWAP12; STO) . (2; RCL;RCL; CHR; WRITE) , (READ; 2; RCL; STO) [ (2; RCL; RCL; 0; =; ((0; RCL; 1; RCL; 1; SUBSTR; "]"; !=); (1; RCL; 1; +; 1;STO); WHILE); (NOP); ITE) ] ((0; RCL; 1; RCL; 1; SUBSTR; "["; !=); (1; RCL; 1; -; 1; STO); WHILE; 1; RCL; 1; -; 1; STO)
External resources
- GASOIL 0.83 - a GASOIL interpreter in Excel. (dead link)