#!/usr/bin/python3 import argparse stack = [] heap = [0] * 100 next_heap = 0 compiling = False reading_string = 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 and not reading_string: 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 == "swap": swap() elif string == "rot": rot() elif string == "and": _and() elif string == "or": _or() elif string == "!": store() elif string == "@": fetch() elif string == "heap": dump_heap() elif string == "alloc": alloc() elif string == 's"': start_reading_string() elif reading_string: if string == '"': stop_reading_string() else: add_new_word_to_string(string) elif compiling and not reading_string: if string == ";": stop_compiling() else: add_to_new_word(string) input_string = get_next(input_string) if say_ok: print("ok.") def add_new_word_to_string(string): for char in string[::-1]: stack.insert(0, ord(char)) def dump_heap(): print(heap) def alloc(): global next_heap heap[next_heap] = 0 stack.insert(0, next_heap) next_heap += 1 def store(): k = stack.pop(0) v = stack.pop(0) heap[k] = v def fetch(): k = stack.pop(0) v = heap[k] stack.insert(0, v) def rot(): a = stack.pop(0) b = stack.pop(0) c = stack.pop(0) stack.insert(0,b) stack.insert(0,a) 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(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 -1 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_reading_string(): global reading_string reading_string = True def stop_reading_string(): global reading_string reading_string = False 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 _and(): a = stack.pop(0) b = stack.pop(0) if a == -1 and b == -1: stack.insert(0, -1) else: stack.insert(0,0) def _or(): a = stack.pop(0) b = stack.pop(0) if a == -1 or b == -1: stack.insert(0, -1) else: stack.insert(0,0) def show_stack(): print(stack) def add_to_stack(value): stack.insert(0, int(value)) def main(args): if args.preload != None: f = open(args.preload, "r") file_data = f.readlines() preload = [] for line in file_data: split_line = line.split(' ') for word in split_line: preload.append(word) parse_input(preload, False) f.close() print("Welcome to rforth!") while True: i = get_input() parse_input(i.split(' ')) if __name__ == "__main__": parser = argparse.ArgumentParser(description='A weird little Forth implementation') parser.add_argument('-p', '--preload', default="standard-library.f", type=str, help='A file to preload') args = parser.parse_args() main(args)