YREA-SLS/SLS_Python/sls/repl.py

83 lines
2.0 KiB
Python

from .meta import print_version
from .lexer import Lexer
from .interpreter import InterpreterState
from .errors import SlsError
REPL_FILE_NAME = "<STDIN>"
def print_top_of_stack(interpreter: InterpreterState) -> None:
"""Pretty-print top of the stack."""
item = interpreter.top()
if item is None:
print("#0: <STACK IS EMPTY>")
return
t = item.type
if t == "Identifier":
print(f"#0: ::{item.value}")
elif t in {"i64", "i32", "i16", "i8"}:
print(f"#0: {item.value}:{t}")
elif t in {"u64", "u32", "u16", "u8"}:
print(f"#0: {item.value}:{t}")
elif t == "f32":
print(f"#0: {item.value}:f32")
elif t == "f64":
print(f"#0: {item.value}")
elif t == "char":
print(f"#0: {item.value}")
elif t == "bool":
print("#0: TRUE" if item.value else "#0: FALSE")
elif t == "TokenString":
print("#0: <TOKEN STRING>")
elif t == "Callable":
print("#0: <CALLABLE>")
else:
print(f"#0: <UNKNOWN {t}>")
def repl() -> int:
"""Interactive interpreter loop."""
print_version()
print("===== YREA SLS REPL =====")
print("Type `#exit` to exit.")
interpreter = InterpreterState()
while True:
try:
line = input("> ")
except EOFError:
break
if line.strip() == "#exit":
return 0
# Create a fresh lexer each iteration
lexer = Lexer(REPL_FILE_NAME, line)
try:
tokens = lexer.lexical_analysis()
except SlsError as err:
print(err.message)
continue
# Execute tokens in order
for token in tokens:
try:
ok = interpreter.execute(token)
if not ok:
print("A runtime error occurred!")
break
except SlsError as err:
print(err.message)
break
print_top_of_stack(interpreter)
return 1