Olus2000
- Not to be confused with User:Olus2000.
Paradigm(s) | Concatenative |
---|---|
Designed by | User:DolphyWind |
Appeared in | 2024 |
Memory system | Stack-based |
Computational class | Turing complete |
Major implementations | Torth |
Influenced by | Forth |
File extension(s) | .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.
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