-
Notifications
You must be signed in to change notification settings - Fork 0
/
scheme_classes.py
143 lines (110 loc) · 4.41 KB
/
scheme_classes.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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import builtins
from pair import *
class SchemeError(Exception):
"""Exception indicating an error in a Scheme program."""
################
# Environments #
################
class Frame:
"""An environment frame binds Scheme symbols to Scheme values."""
def __init__(self, parent):
"""An empty frame with parent frame PARENT (which may be None)."""
self.bindings = {}
self.parent = parent
def __repr__(self):
if self.parent is None:
return '<Global Frame>'
s = sorted(['{0}: {1}'.format(k, v) for k, v in self.bindings.items()])
return '<{{{0}}} -> {1}>'.format(', '.join(s), repr(self.parent))
def define(self, symbol, value):
"""Define Scheme SYMBOL to have VALUE."""
# BEGIN PROBLEM 1
"*** YOUR CODE HERE ***"
self.bindings[symbol] = value
# END PROBLEM 1
def lookup(self, symbol):
"""Return the value bound to SYMBOL. Errors if SYMBOL is not found."""
# BEGIN PROBLEM 1
"*** YOUR CODE HERE ***"
val = self.bindings.get(symbol)
if val is not None:
return val
if self.parent:
return self.parent.lookup(symbol)
# END PROBLEM 1
raise SchemeError('unknown identifier: {0}'.format(symbol))
def make_child_frame(self, formals, vals):
"""Return a new local frame whose parent is SELF, in which the symbols
in a Scheme list of formal parameters FORMALS are bound to the Scheme
values in the Scheme list VALS. Both FORMALS and VALS are represented
as Pairs. Raise an error if too many or too few vals are given.
>>> env = create_global_frame()
>>> formals, expressions = read_line('(a b c)'), read_line('(1 2 3)')
>>> env.make_child_frame(formals, expressions)
<{a: 1, b: 2, c: 3} -> <Global Frame>>
"""
if len(formals) != len(vals):
raise SchemeError('Incorrect number of arguments to function call')
# BEGIN PROBLEM 8
"*** YOUR CODE HERE ***"
child_frame = Frame(parent=self)
cur_formal = formals
cur_val = vals
while cur_formal != nil:
child_frame.define(symbol=cur_formal.first, value=cur_val.first)
cur_formal = cur_formal.rest
cur_val = cur_val.rest
return child_frame
# END PROBLEM 8
##############
# Procedures #
##############
class Procedure:
"""The the base class for all Procedure classes."""
class BuiltinProcedure(Procedure):
"""A Scheme procedure defined as a Python function."""
def __init__(self, py_func, need_env=False, name='builtin'):
self.name = name
self.py_func = py_func
self.need_env = need_env
def __str__(self):
return '#[{0}]'.format(self.name)
class LambdaProcedure(Procedure):
"""A procedure defined by a lambda expression or a define form."""
def __init__(self, formals, body, env):
"""A procedure with formal parameter list FORMALS (a Scheme list),
whose body is the Scheme list BODY, and whose parent environment
starts with Frame ENV."""
assert isinstance(env, Frame), "env must be of type Frame"
from scheme_utils import validate_type, scheme_listp
validate_type(formals, scheme_listp, 0, 'LambdaProcedure')
validate_type(body, scheme_listp, 1, 'LambdaProcedure')
self.formals = formals
self.body = body
self.env = env
def __str__(self):
return str(Pair('lambda', Pair(self.formals, self.body)))
def __repr__(self):
return 'LambdaProcedure({0}, {1}, {2})'.format(
repr(self.formals), repr(self.body), repr(self.env))
class MuProcedure(Procedure):
"""A procedure defined by a mu expression, which has dynamic scope.
_________________
< Scheme is cool! >
-----------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
"""
def __init__(self, formals, body):
"""A procedure with formal parameter list FORMALS (a Scheme list) and
Scheme list BODY as its definition."""
self.formals = formals
self.body = body
def __str__(self):
return str(Pair('mu', Pair(self.formals, self.body)))
def __repr__(self):
return 'MuProcedure({0}, {1})'.format(
repr(self.formals), repr(self.body))