@@ -58,10 +58,11 @@ def parse_atom(token: str) -> Atom:
5858 except ValueError :
5959 return Symbol (token )
6060
61+
6162################ Global Environment
6263
6364# tag::ENV_CLASS[]
64- class Environment (ChainMap ):
65+ class Environment (ChainMap [ Symbol , Any ] ):
6566 "A ChainMap that allows changing an item in-place."
6667
6768 def change (self , key : Symbol , value : object ) -> None :
@@ -119,11 +120,11 @@ def standard_env() -> Environment:
119120################ Interaction: A REPL
120121
121122# tag::REPL[]
122- def repl () -> NoReturn :
123+ def repl (prompt : str = 'lis.py> ' ) -> NoReturn :
123124 "A prompt-read-eval-print loop."
124125 global_env = standard_env ()
125126 while True :
126- ast = parse (input ('lis.py> ' ))
127+ ast = parse (input (prompt ))
127128 val = evaluate (ast , global_env )
128129 if val is not None :
129130 print (lispstr (val ))
@@ -140,7 +141,10 @@ def lispstr(exp: object) -> str:
140141################ Evaluator
141142
142143# tag::EVALUATE[]
143- KEYWORDS = ['quote' , 'if' , 'lambda' , 'define' , 'set!' ]
144+ KEYWORDS = {'quote' , 'if' , 'lambda' , 'define' , 'set!' }
145+
146+ def is_keyword (s : Any ) -> bool :
147+ return isinstance (s , Symbol ) and s in KEYWORDS
144148
145149def evaluate (exp : Expression , env : Environment ) -> Any :
146150 "Evaluate an expression in an environment."
@@ -149,8 +153,6 @@ def evaluate(exp: Expression, env: Environment) -> Any:
149153 return x
150154 case Symbol (var ):
151155 return env [var ]
152- case []:
153- return []
154156 case ['quote' , x ]:
155157 return x
156158 case ['if' , test , consequence , alternative ]:
@@ -166,8 +168,8 @@ def evaluate(exp: Expression, env: Environment) -> Any:
166168 env [name ] = Procedure (parms , body , env )
167169 case ['set!' , Symbol (var ), value_exp ]:
168170 env .change (var , evaluate (value_exp , env ))
169- case [op , * args ] if op not in KEYWORDS :
170- proc = evaluate (op , env )
171+ case [func_exp , * args ] if not is_keyword ( func_exp ) :
172+ proc = evaluate (func_exp , env )
171173 values = [evaluate (arg , env ) for arg in args ]
172174 return proc (* values )
173175 case _:
0 commit comments