From cf86b463b27c556e77ee18c70dd0f97085af2120 Mon Sep 17 00:00:00 2001 From: rmgr Date: Tue, 5 Apr 2022 17:29:11 +0930 Subject: [PATCH] initial commit --- README.md | 5 ++ rforth.py | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 README.md create mode 100755 rforth.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..62a44e7 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# rforth + +A bare-bones forth interpreter written in Python for the hell of it. + +https://wiki.rmgr.dev/general/tech/rforth.html diff --git a/rforth.py b/rforth.py new file mode 100755 index 0000000..48c7b00 --- /dev/null +++ b/rforth.py @@ -0,0 +1,211 @@ +stack = [] +compiling = False +words = {} +word_name = "" + +def get_next(input_string): + if len(input_string) > 1: + return input_string[1:len(input_string)] + else: + return [] +def get_input(): + i = input() + return i + +def parse_input(input_string, say_ok=True): + while len(input_string) > 0: + string = str(input_string[0]) + if not compiling: + if string.isnumeric(): + add_to_stack(string) + elif string == "stack": + show_stack() + elif string == "+": + add() + elif string == "-": + subtract() + elif string == ".": + output() + elif string == "bye": + exit() + elif string == "emit": + emit() + elif string == ":": + start_compiling() + elif string in words: + parse_input(words[string].split(" "), False) + elif string == "words": + show_words() + elif string == ">": + greater_than() + elif string == "<": + less_than() + elif string == "=": + equals() + elif string == "if": + input_string = _if(input_string) + elif string == "dup": + dup() + elif string == "2dup": + twodup() + elif string == "swap": + swap() + elif string == "rot": + rot() + else: + if string == ";": + stop_compiling() + else: + add_to_new_word(string) + input_string = get_next(input_string) + if say_ok: + print("ok.") + +def rot(): + a = stack.pop(0) + b = stack.pop(0) + c = stack.pop(0) + stack.insert(0,a) + stack.insert(0,b) + stack.insert(0,c) + +def swap(): + a = stack.pop(0) + b = stack.pop(0) + stack.insert(0,a) + stack.insert(0,b) + +def _if(input_string): + a = stack.pop(0) + if int(a) == -1: + then_index = scan_for_then(input_string) + else_index = scan_for_else(input_string[0:then_index], then_index) + if else_index == -1: + return input_string[0:then_index] + else: + return input_string[0: else_index] + input_string[then_index : len(input_string)] + else: + then_index = scan_for_then(input_string) + else_index = scan_for_else(input_string[0:then_index], then_index) + + if else_index == -1: + return input_string[then_index: len(input_string)] + else: + return input_string[else_index : len(input_string)] + return input_string + +def scan_for_else_or_then(input_string): + for index in reversed(range(0, len(input_string))): + if input_string[index] == "then": + return input_string[index : len(input_string) - 1] + elif input_string[index] == "else": + return input_string[index : len(input_string) - 1] + return index + +def scan_for_else(input_string, then_index): + for index in reversed(range(0, then_index)): + if input_string[index] == "else": + return index + return -1 + +def scan_for_then(input_string): + for index in reversed(range(0, len(input_string))): + if input_string[index] == "then": + return index +# return input_string[index : len(input_string) - 1] + return -1 + +def twodup(): + a = stack.pop(0) + stack.insert(0,a) + stack.insert(0,a) + stack.insert(0,a) + +def dup(): + a = stack.pop(0) + stack.insert(0,a) + stack.insert(0,a) + +def greater_than(): + a = stack.pop(0) + b = stack.pop(0) + if a > b: + stack.insert(0,-1) + else: + stack.insert(0,0) + +def less_than(): + a = stack.pop(0) + b = stack.pop(0) + if a < b: + stack.insert(0,-1) + else: + stack.insert(0,0) + +def equals(): + a = stack.pop(0) + b = stack.pop(0) + if a == b: + stack.insert(0,-1) + else: + stack.insert(0,0) + +def show_words(): + print(words) + +def add_to_new_word(value): + global word_name + if word_name == "": + word_name = value + words[word_name] = "" + else: + words[word_name] = words[word_name] + value + " " + +def start_compiling(): + global compiling + compiling = True + +def stop_compiling(): + global compiling + global word_name + compiling = False + words[word_name] = words[word_name].strip() + word_name = "" + +def emit(): + a = stack.pop(0) + print(chr(a),end='') + +def exit(): + print("l8r sk8r") + quit() + +def output(): + a = stack.pop(0) + print(a) + +def subtract(): + a = stack.pop(0) + b = stack.pop(0) + stack.insert(0, a-b) + +def add(): + a = stack.pop(0) + b = stack.pop(0) + stack.insert(0, a+b) + +def show_stack(): + print(stack) + +def add_to_stack(value): + stack.insert(0, int(value)) + + +def main(): + print("Welcome to rforth!") + while True: + i = get_input() + parse_input(i.split(' ')) + +if __name__ == "__main__": + main()