initial commit

This commit is contained in:
rmgr 2022-04-05 17:29:11 +09:30
commit cf86b463b2
2 changed files with 216 additions and 0 deletions

5
README.md Normal file
View File

@ -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

211
rforth.py Executable file
View File

@ -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()