updated from Atlas

This commit is contained in:
Luciano Ramalho
2021-09-18 13:18:17 -03:00
parent 6527037ae7
commit 3ecfb212c6
6 changed files with 438 additions and 114 deletions

View File

@@ -58,10 +58,11 @@ def parse_atom(token: str) -> Atom:
except ValueError:
return Symbol(token)
################ Global Environment
# tag::ENV_CLASS[]
class Environment(ChainMap):
class Environment(ChainMap[Symbol, Any]):
"A ChainMap that allows changing an item in-place."
def change(self, key: Symbol, value: object) -> None:
@@ -119,11 +120,11 @@ def standard_env() -> Environment:
################ Interaction: A REPL
# tag::REPL[]
def repl() -> NoReturn:
def repl(prompt: str = 'lis.py> ') -> NoReturn:
"A prompt-read-eval-print loop."
global_env = standard_env()
while True:
ast = parse(input('lis.py> '))
ast = parse(input(prompt))
val = evaluate(ast, global_env)
if val is not None:
print(lispstr(val))
@@ -140,7 +141,10 @@ def lispstr(exp: object) -> str:
################ Evaluator
# tag::EVALUATE[]
KEYWORDS = ['quote', 'if', 'lambda', 'define', 'set!']
KEYWORDS = {'quote', 'if', 'lambda', 'define', 'set!'}
def is_keyword(s: Any) -> bool:
return isinstance(s, Symbol) and s in KEYWORDS
def evaluate(exp: Expression, env: Environment) -> Any:
"Evaluate an expression in an environment."
@@ -149,8 +153,6 @@ def evaluate(exp: Expression, env: Environment) -> Any:
return x
case Symbol(var):
return env[var]
case []:
return []
case ['quote', x]:
return x
case ['if', test, consequence, alternative]:
@@ -166,8 +168,8 @@ def evaluate(exp: Expression, env: Environment) -> Any:
env[name] = Procedure(parms, body, env)
case ['set!', Symbol(var), value_exp]:
env.change(var, evaluate(value_exp, env))
case [op, *args] if op not in KEYWORDS:
proc = evaluate(op, env)
case [func_exp, *args] if not is_keyword(func_exp):
proc = evaluate(func_exp, env)
values = [evaluate(arg, env) for arg in args]
return proc(*values)
case _: