Olus2000

Olus2000 is a Forth-like esoteric programming language created for Code Guessing 64 as an in-joke. The author created Torth to write Olus2000 programs faster. Olus2000 uses a single stack memory system that operates with ternary integers. All binary operations, including addition, multiplication, and comparison, follow the Forth-style approach.
==Grammar==
<Program> ::= <Block>
<Block> ::= <Stmt> <WS> <Block> | ε
<Stmt> ::= <Word> | <PosNumber> | <NegNumber> | <String> | <IfStmt> | <WhileStmt> | <Colon> | <Comment>
<Word> ::= <Letter> { <Letter> | <Base10Digit> | "-" }
<PosNumber> ::= "0lus2000!" <WS> { <OlusNumber> <WS> } "olus2000!"
<NegNumber> ::= "0lus2ooo!" <WS> { <OlusNumber> <WS> } "olus2000!"
<OlusNumber> ::= "olus2" ("0" | "O" | "o") ("0" | "O" | "o") ("0" | "O" | "o")
<String> ::= "\"" { <CHARACTER> } "\""
<IfStmt> ::= "olus2o0O" <WS> <Block> [ "olus2o0o" <WS> <Block> ] "olus2oO0"
<WhileStmt> ::= "olus2oOO" <Block> "olus2oO0"
<Colon> ::= "olus2oOo" <WS> <Word> <WS> <Block> "olus2oo0"
<Comment> ::= "Olus2000!" <WS> { <CHARACTER> } <WS> "olus2000!"
<Letter> ::= "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N"
 | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "a" | "b"
 | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p"
 | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "_" ;
<Base10Digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<SpecialCharacter> ::= "!" | "@" | "#" | "$" | "%" | "^" | "&" | "*" | "(" | ")" | "-"
 | "=" | "+" | "[" | "]" | "{" | "}" | ";" | ":" | "'" | "," | "."
 | "/" | "?" | "<" | ">" | "|" | "\\" | "~" | "`" | " "
<EscapeSequence> ::= "\\" ( "\"" | "\\" | "n" | "t" | "r" | "\'" )
<WhiteSpace> ::= " " | "\t" | "\n"
<WS> ::= <WhiteSpace> { <WhiteSpace> }
<CHARACTER> ::= <Letter> | <Base10Digit> | <SpecialCharacter> | <EscapeSequence>
==Numbers==
When encountered, numbers of Olus2000 are directly pushed onto the stack, just like how it is done in Forth. In Olus2000 a number is represented in an unconventional manner, as triplets of ternary digits encoded as olus2xxx statements where x can be either 0, O or o. When a PosNumber or a NegNumber statement is encountered, the olus2xxx statements are transformed into triplets of ternary digits by mapping 0 to 0, O to 1 and o to 2. The resulting digits are then concatenated to form a single ternary number. Additionally, if the statement is a NegNumber statement, the number is negated. Let's look at an example:
The Statement is "0lus2000! olus20O0 olus2o0O olus2000!"
> olus20O0 represents the triplet "010"
> olus2o0O represents the triplet "201"
> The results are concatenated to obtain the number 010201
> Since this is a PosNumber statement the number above is not negated
 
==Strings==
When a string statement is executed, the content of the string is immediately printed to the console. The program below prints "Hello World!" and inserts a new line
"Hello World!\n"
==Words==
By following Forth, Olus2000 allows creation of custom words. Below, you can find a list of built-in words.
 Olus2000 Words
Word 	Action
olus2000	Pops the top value and prints it to stdout as a ternary integer
olus200O	Reads a ternary integer from the stdin and pushes it onto the stack
olus200o	Pops two ternary integers and pushes their sum
olus20O0	Pops two ternary integers and pushes their difference
olus20OO	Pops two ternary integers and pushes their product
olus20Oo	Pops two ternary integers, applies integer division and pushes the result
olus20o0	Pops two ternary integers, applies modulo operation and pushes the result
olus20oO	Pops two ternary integers and pushes 1 if the second one is less than the first one. Otherwise pushes zero
olus20oo	Pops two ternary integers and pushes 1 if the second one is less than or equal to the first one. Otherwise pushes zero
olus2O00	Pops two ternary integers and pushes 1 if the second one is equal to the first one. Otherwise pushes zero
olus2O0O	Pops two ternary integers and pushes 1 if the second one is not equal to the first one. Otherwise pushes zero
olus2O0o	Pops two ternary integers and pushes 1 if the second one is greater than or equal to the first one. Otherwise pushes zero
olus2OO0	Pops two ternary integers and pushes 1 if the second one is greater than the first one. Otherwise pushes zero
olus2OOO	Reverses the entire stack
olus2OOo	Pops the top value and pushes it back twice
olus2Oo0	Reverses the order of the top two elements on the stack
olus2OoO	Pops the top value
olus2Ooo	Rotates the top three values
olus2o00	Pushes the current length of the stack to the stack itself
olus2o0O	If statement, must be terminated with olus2oO0. Checks, without popping, the top value of the stack. If it is a nonzero executes its body
olus2o0o	Else keyword, must be used between olus2o0O and olus2oO0. Executes its body if the previous if block didn't execute
olus2oO0	Marks the end of olus2o0O or olus2oOO words
olus2oOO	While loop, must be terminated with olus2oO0. Executes its body as long as the top value of the stack is non-zero without removing the value it checks
olus2oOo	Used to create new words, must be terminated with olus2oo0
olus2oo0	Marks the end of olus2oOo
olus2ooO	Pops an index and moves the item at the given index to the top of the stack
olus2ooo	Pops a ternary integer and a stack index. Moves the integer to the specified index
==Olus2000 -> Torth Transpiler==
Here's a nice and simple transpiler that converts any Olus2000 code to equivalent Torth code.
import sys
olus2000_dict = {
 'olus2000': '.',
 'olus200O': ',',
 'olus200o': '+',
 'olus20O0': '-',
 'olus20OO': '*',
 'olus20Oo': '/',
 'olus20o0': '%',
 'olus20oO': '<',
 'olus20oo': '<=',
 'olus2O00': '==',
 'olus2O0O': '!=',
 'olus2O0o': '>=',
 'olus2OO0': '>',
 'olus2OOO': 'REVERSE',
 'olus2OOo': 'DUP',
 'olus2Oo0': 'SWAP',
 'olus2OoO': 'DROP',
 'olus2Ooo': 'ROT',
 'olus2o00': 'DEPTH',
 'olus2o0O': 'IF',
 'olus2o0o': 'ELSE',
 'olus2oO0': 'THEN',
 'olus2oOO': 'WHILE',
 'olus2oOo': ':',
 'olus2oo0': ';',
 'olus2ooO': 'GET',
 'olus2ooo': 'SET',
}
def olus_to_ternary(olus):
 last_three = olus[-3:]
 d = {
 '0': 0,
 'O': 1,
 'o': 2
 }
 return str(d[last_three[0]]) + str(d[last_three[1]]) + str(d[last_three[2]])
def main():
 code = ""
 if len(sys.argv) == 1:
 code = input()
 else:
 file = sys.argv[1]
 with open(file, 'r') as f:
 code = f.read()
 code_as_list = []
 last = 0
 in_string = False
 s = []
 for i, c in enumerate(code):
 if c == '\"':
 code_as_list.append(code[last:i + int(in_string)])
 last = i + int(in_string)
 in_string = not in_string
 s = []
 continue
 s.append(c)
 if last == 0:
 code_as_list.append(code[last:])
 else:
 code_as_list.append(code[last+1:])
 fin = []
 for c in code_as_list:
 if c.startswith('\"'):
 fin.append(c)
 else:
 fin.extend(c.split())
 code = fin
 NUMBER_MODE = 0
 COMMENT_MODE = 1
 NORMAL_MODE = 2
 mode = NORMAL_MODE
 negative_number = False
 result = []
 num = ''
 for op in code:
 prev_mode = mode
 if op == '0lus2000!':
 mode = NUMBER_MODE
 negative_number = False
 elif op == '0lus2ooo!':
 mode = NUMBER_MODE
 negative_number = True
 elif op == 'Olus2000!':
 mode = COMMENT_MODE
 elif op == 'olus2000!':
 mode = NORMAL_MODE
 if mode != NUMBER_MODE and prev_mode == NUMBER_MODE:
 if negative_number:
 num = '-' + num
 result.append(num)
 num = ''
 if mode != prev_mode:
 continue
 if mode == NUMBER_MODE:
 num += olus_to_ternary(op)
 elif mode == NORMAL_MODE:
 try:
 result.append(olus2000_dict[op])
 except KeyError:
 result.append(op)
 if mode == NUMBER_MODE and num != :
 result.append(num)
 print(' '.join(result))
if __name__ == "__main__":
 main()
==Examples==
Some example programs written in Olus2000
===99 Bottles of Beer on The Wall===
olus2oOo WRITE_9 olus2o0O olus2OoO "ERROR" olus2o0o olus2OoO "9" olus2oO0 olus2oo0 olus2oOo WRITE_8 olus2o0O 0lus2000! olus200O olus2000! olus20O0 WRITE_9 olus2o0o olus2OoO "8"
olus2oO0 olus2oo0 olus2oOo WRITE_7 olus2o0O 0lus2000! olus200O olus2000! olus20O0 WRITE_8 olus2o0o olus2OoO "7" olus2oO0 olus2oo0 olus2oOo WRITE_6 olus2o0O 0lus2000! olus200O
olus2000! olus20O0 WRITE_7 olus2o0o olus2OoO "6" olus2oO0 olus2oo0 olus2oOo WRITE_5 olus2o0O 0lus2000! olus200O olus2000! olus20O0 WRITE_6 olus2o0o olus2OoO "5" olus2oO0
olus2oo0 olus2oOo WRITE_4 olus2o0O 0lus2000! olus200O olus2000! olus20O0 WRITE_5 olus2o0o olus2OoO "4" olus2oO0 olus2oo0 olus2oOo WRITE_3 olus2o0O 0lus2000! olus200O olus2000!
olus20O0 WRITE_4 olus2o0o olus2OoO "3" olus2oO0 olus2oo0 olus2oOo WRITE_2 olus2o0O 0lus2000! olus200O olus2000! olus20O0 WRITE_3 olus2o0o olus2OoO "2" olus2oO0 olus2oo0 olus2oOo
WRITE_1 olus2o0O 0lus2000! olus200O olus2000! olus20O0 WRITE_2 olus2o0o olus2OoO "1" olus2oO0 olus2oo0 olus2oOo WRITE_0 olus2o0O 0lus2000! olus200O olus2000! olus20O0 WRITE_1
olus2o0o olus2OoO "0" olus2oO0 olus2oo0 olus2oOo WRITE_HELPER olus2o00 olus2o0O olus2OoO 0lus2000! olus200O olus2000! olus200o olus2o0O 0lus2000! olus200O olus2000! olus20O0
olus2o0o olus2OoO WRITE_0 WRITE_HELPER olus2oO0 olus2o0o olus2OoO olus2oO0 olus2oo0 olus2oOo WRITE_NUM olus2o0O olus2OOo 0lus2000! olus2O0O olus2000! olus20o0 olus2Oo0 0lus2ooo!
olus200O olus2000! olus2Oo0 0lus2000! olus2O0O olus2000! olus20Oo WRITE_NUM olus2o0o olus2OoO WRITE_HELPER olus2oO0 olus2oo0 olus2oOo BOTTLES olus2OOo 0lus2000! olus200O
olus2000! olus20O0 olus2o0O olus2OoO "bottles" olus2o0o olus2OoO "bottle" olus2oO0 olus2oo0 olus2oOo LAST_LINE olus2OOo olus2o0O WRITE_NUM olus2o0o olus2OoO "No more" olus2oO0
" " BOTTLES " of beer on the wall.\n\n" olus2oo0 olus2oOo BEER_REGULAR olus2OOo WRITE_NUM " " BOTTLES " of beer on the wall,\n" olus2OOo WRITE_NUM " " BOTTLES
" of beer.\nTake one down, pass it around\n" 0lus2000! olus200O olus2000! olus20O0 LAST_LINE olus2oo0 olus2oOo BEER olus2OOo olus2o0O BEER_REGULAR BEER olus2oO0 olus2oo0
0lus2000! olus20O0 olus2o00 olus2000! BEER 
===Look And Say Sequence===
olus2oOo OLUS2OOO olus2o0O olus2OoO "ERROR" olus2o0o olus2OoO "3" olus2oO0 olus2oo0 olus2oOo OLUS2ooo olus2o0O 0lus2000! olus200O olus2000! olus20O0 OLUS2OOO olus2o0o olus2OoO
"2" olus2oO0 olus2oo0 olus2oOo OLUS2000 olus2o0O 0lus2000! olus200O olus2000! olus20O0 OLUS2ooo olus2o0o olus2OoO "1" olus2oO0 olus2oo0 olus2oOo OLUS200O 0lus2000! olus200O
olus2000! olus20O0 OLUS2000 olus2oo0 olus2oOo OLUS20O0 olus2OOo olus2Ooo olus2Oo0 olus2OOo olus2Ooo olus2O00 olus2o0O olus2OoO 0lus2000! olus2000 olus2000! olus2ooO 0lus2000!
olus200O olus2000! olus200o 0lus2000! olus2000 olus2000! olus2Oo0 olus2ooo olus2OoO olus2o0o olus2OoO olus2OOo 0lus2000! olus2000 olus2000! olus2Oo0 olus2ooo 0lus2000! olus2000
olus2000! 0lus2000! olus200O olus2000! olus2ooo olus2Oo0 olus2OoO olus2oO0 olus2oo0 olus2oOo OLUS20OO olus2Oo0 olus2OOo 0lus2ooo! olus200O olus2000! olus2O0O olus2oOO olus2OoO
olus2Oo0 OLUS20O0 olus2Oo0 olus2OOo 0lus2ooo! olus200O olus2000! olus2O0O olus2oO0 olus2OoO olus2Oo0 olus2OoO olus2OoO olus2oo0 olus2oOo OLUS20Oo OLUS20OO olus2OOO olus2o00
olus2oOO olus2Oo0 olus2OOo OLUS200O 0lus2000! olus2000 olus2000! olus2Oo0 olus2ooo 0lus2000! olus200O olus2000! olus20O0 olus2oO0 "\n" olus2OoO 0lus2ooo! olus200O olus2000!
olus2OOO 0lus2000! olus2000 olus2000! olus2oo0 0lus2ooo! olus200O olus2000! 0lus2000! olus200O olus2000! 0lus2000! olus2000 olus2000! 0lus2000! olus200O olus2000! OLUS200O "\n"
0lus2000! olus200O olus2000! olus2oOO olus2OoO OLUS20Oo 0lus2000! olus200O olus2000! olus2oO0
Category:Stack-based
Category:Turing complete
Category:2024
Category:Implemented