1212from collections .abc import MutableMapping
1313from typing import Any , TypeAlias
1414
15- Atom : TypeAlias = float | int | str
15+ Symbol : TypeAlias = str
16+ Atom : TypeAlias = float | int | Symbol
1617Expression : TypeAlias = Atom | list
1718
18- Environment : TypeAlias = MutableMapping [str , object ]
19+ Environment : TypeAlias = MutableMapping [Symbol , object ]
1920
2021
2122class Procedure :
2223 "A user-defined Scheme procedure."
2324
24- def __init__ (self , parms : list [str ], body : Expression , env : Environment ):
25+ def __init__ (self , parms : list [Symbol ], body : Expression , env : Environment ):
2526 self .parms , self .body , self .env = parms , body , env
2627
2728 def __call__ (self , * args : Expression ) -> Any :
@@ -68,14 +69,12 @@ def standard_env() -> Environment:
6869 'number?' : lambda x : isinstance (x , (int , float )),
6970 'procedure?' : callable ,
7071 'round' : round ,
71- 'symbol?' : lambda x : isinstance (x , str ),
72+ 'symbol?' : lambda x : isinstance (x , Symbol ),
7273 }
7374 )
7475 return env
7576
7677
77- global_env : Environment = standard_env ()
78-
7978################ Parsing: parse, tokenize, and read_from_tokens
8079
8180
@@ -114,16 +113,17 @@ def parse_atom(token: str) -> Atom:
114113 try :
115114 return float (token )
116115 except ValueError :
117- return str (token )
116+ return Symbol (token )
118117
119118
120119################ Interaction: A REPL
121120
122121
123122def repl (prompt : str = 'lis.py> ' ) -> None :
124123 "A prompt-read-evaluate-print loop."
124+ global_env : Environment = standard_env ()
125125 while True :
126- val = evaluate (parse (input (prompt )))
126+ val = evaluate (parse (input (prompt )), global_env )
127127 if val is not None :
128128 print (lispstr (val ))
129129
@@ -142,7 +142,7 @@ def lispstr(exp: object) -> str:
142142def evaluate (x : Expression , env : Environment ) -> Any :
143143 "Evaluate an expression in an environment."
144144 match x :
145- case str (var ): # variable reference
145+ case Symbol (var ): # variable reference
146146 return env [var ]
147147 case literal if not isinstance (x , list ): # constant literal
148148 return literal
@@ -151,9 +151,11 @@ def evaluate(x: Expression, env: Environment) -> Any:
151151 case ['if' , test , conseq , alt ]: # (if test conseq alt)
152152 exp = conseq if evaluate (test , env ) else alt
153153 return evaluate (exp , env )
154- case ['define' , var , exp ]: # (define var exp)
154+ case ['define' , Symbol ( var ) , exp ]: # (define var exp)
155155 env [var ] = evaluate (exp , env )
156- case ['lambda' , parms , body ]: # (lambda (var...) body)
156+ case ['define' , [name , * parms ], body ]: # (define (fun parm...) body)
157+ env [name ] = Procedure (parms , body , env )
158+ case ['lambda' , parms , body ]: # (lambda (parm...) body)
157159 return Procedure (parms , body , env )
158160 case [op , * args ]: # (proc arg...)
159161 proc = evaluate (op , env )
0 commit comments