-
Notifications
You must be signed in to change notification settings - Fork 11
/
special_forms.py
68 lines (60 loc) · 2.48 KB
/
special_forms.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# Kimi language interpreter in Python 3
# Anjana Vakil
# http://www.github.com/vakila/kimi
import evaluator as ev
from environments import Environment
from errors import *
def do(args, env):
do_env = Environment(name="do", outer=env)
if len(args) == 0:
throw_error("syntax", "Incorrect use of (do ...): must take at least one argument.")
result = None
for a in args:
result = ev.evaluate(a, do_env)
return result
def lamb(args, env):
# print("\n")
# print("args (" + str(len(args)) + "):", args)
# print("env: ", env.name)
if len(args) < 2:
throw_error("syntax", "Incorrect use of (lambda ...): must take at least two arguments (at least one variable and a body).")
largs = args[:-1]
lbody = args[-1]
# print("largs (" + str(len(largs)) + "):", largs)
for l in largs:
assert_or_throw(l['type'] == 'symbol', "syntax", "Incorrect use of (lambda ...): the anonymous function's variables must be symbols.")
largs = tuple(la['value'] for la in largs)
# print("lbody:", lbody)
def anonymous(*arguments):
# print("inside anonymous function")
# print("arguments(" + str(len(arguments)) + "):", arguments)
if len(arguments) != len(largs):
throw_error("syntax", "This function takes " + str(len(largs)) + " arguments (" + str(len(arguments)) + " provided).")
lenv = Environment(name="anon_fn", outer=env, variables=largs, values=arguments)
return ev.evaluate(lbody, lenv)
return anonymous
def define(args, env):
if len(args) != 2:
throw_error("syntax", "Incorrect use of (define ...): must take exactly two arguments.")
assert_or_throw(args[0]['type'] == 'symbol', "type", "Incorrect use of (define ...): the variable must be a symbol.")
variable = args[0]['value']
value = ev.evaluate(args[1], env)
env.set(variable, value)
return value
def cond(args, env):
if len(args) != 3:
throw_error("syntax", "Incorrect use of (if ...): must take exactly three arguments (a test, a pass case, and a fail case).")
test = ev.evaluate(args[0], env)
if type(test) != bool:
throw_error("type", "Incorrect use of (if ...): the test must evaluate to a boolean.")
if test:
return ev.evaluate(args[1], env)
else:
return ev.evaluate(args[2], env)
def special_forms():
specials = dict()
specials['do'] = do
specials['lambda'] = lamb
specials['define'] = define
specials['if'] = cond
return specials