mal: Step 3ΒΆ
- project:
mal-py
- filename:
step3_env.py
read
mal-py
step3_env.py
import itertools
from env import Env
from reader import S, read_str
def read(ins):
return read_str(ins)
eval
mal-py
step3_env.py
def evaluate(form, env: Env):
match form:
case S(name):
return env.get(name)
case []:
return []
case [*fs]:
match fs[0]:
case S('def!'):
env.set(fs[1].name, v := evaluate(fs[2], env))
return v
case S('let*'):
letenv = Env(env)
for binding, expr in itertools.batched(fs[1], n=2):
letenv.set(binding.name, evaluate(expr, letenv))
return evaluate(fs[2], letenv)
case _:
f, *args = [evaluate(f, env) for f in fs]
return f(*args)
case _:
return form
mal-py
step3_env.py
from printer import print_form
def printit(form):
return print_form(form)
rep
mal-py
step3_env.py
def rep(ins: str, env: Env):
try:
return printit(evaluate(read(ins), env))
except EOFError:
return f"EOF"
except KeyError as e:
return f"{e.args[0]!r} not found"
except Exception as e:
print(f"RuntimeError: {e}")
# import pdb; pdb.post_mortem()
repl
mal-py
step3_env.py
def repl(ins: io.TextIO):
env = Env()
env.set('+', lambda a,b: a+b)
env.set('-', lambda a,b: a-b)
env.set('*', lambda a,b: a*b)
env.set('/', lambda a,b: int(a/b))
print("user> ", end='', flush=True)
while (line := ins.readline()) != "":
print(rep(line, env))
print("user> ", end='', flush=True)
if __name__ == "__main__":
import sys
repl(sys.stdin)