SIGN IN SIGN UP
2024-08-22 06:56:10 +02:00
import traceback
from collections.abc import Mapping, Sequence
import mal_readline
from mal_types import (Error, Fn, Form, List,
Map, Number, Symbol,
Vector, pr_seq)
import reader
2024-08-22 06:56:10 +02:00
Env = Mapping[str, Fn]
2024-08-22 06:56:10 +02:00
def eval_(ast: Form, env: Env) -> Form:
# print(f'EVAL: {ast}', repr(ast)
match ast:
case Symbol():
if (value := env.get(ast)) is not None:
return value
raise Error(f"'{ast}' not found")
case Map():
return Map((k, eval_(v, env)) for k, v in ast.items())
case Vector():
return Vector(eval_(x, env) for x in ast)
case List([first, *args]):
match eval_(first, env):
case Fn(call):
return call(tuple(eval_(x, env) for x in args))
case not_fun:
raise Error(f'cannot apply {not_fun}')
case _:
return ast
2024-08-22 06:56:10 +02:00
def add(args: Sequence[Form]) -> Form:
match args:
case [Number(left), Number(right)]:
return Number(left + right)
case _:
raise Error('+: bad arguments' + pr_seq(args))
def sub(args: Sequence[Form]) -> Form:
match args:
case [Number(left), Number(right)]:
return Number(left - right)
case _:
raise Error('-: bad arguments' + pr_seq(args))
def mul(args: Sequence[Form]) -> Form:
match args:
case [Number(left), Number(right)]:
return Number(left * right)
case _:
raise Error('*: bad arguments' + pr_seq(args))
def floordiv(args: Sequence[Form]) -> Form:
match args:
case [Number(left), Number(right)]:
return Number(left // right)
case _:
raise Error('/: bad arguments' + pr_seq(args))
def rep(source: str, env: Env) -> str:
return str(eval_(reader.read(source), env))
def main() -> None:
repl_env: Env = {
'+': Fn(add), '-': Fn(sub), '*': Fn(mul), '/': Fn(floordiv),
}
while True:
try:
2024-08-22 06:56:10 +02:00
print(rep(mal_readline.input_('user> '), repl_env))
except EOFError:
2024-08-22 06:56:10 +02:00
break
# pylint: disable-next=broad-exception-caught
except Exception as exc:
traceback.print_exception(exc, limit=10)
if __name__ == '__main__':
main()