-
Notifications
You must be signed in to change notification settings - Fork 0
/
env.py
142 lines (107 loc) · 4.96 KB
/
env.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
class GlobalEnv:
""" Implements a "ribcage" data structure that stores bindings of variables and values as lists.
Attributes:
variables (List): the identifiers
values (List): the associated values bound to the variables
prev (GlobalEnv): a reference to a previous GlobalEnv.
Methods to implement:
__init__ Initializes a new instance of a GlobalEnv.
Args:
prev (GlobalEnv): initialize the variables and values lists, the previous environment is
initialized to the argument.
empty_env A static method that returns the empty GlobalEnv.
Args:
none
Returns:
GlobalEnv: A new instance of a GlobalEnv with None as the previous environment.
lookup Looks up the variable passed to it and returns the associated value.
Args:
symbol (string): A string that is a variable (identifier) that is bound to some value in an environment.
Returns:
value: The value that is bound to the symbol passed in. This can be any object that is stored in the
values list associated with the symbol in a "rib" of the ribcage.
extend Creates a new "rib" in an environment.
Args:
variables (List): a list of variable identifiers.
values (List): a list of values that correspond to the identifiers in the variables list.
Returns:
GlobalEnv: A new instance of a GlobalEnv with "self" as the previous environment.
"""
def __init__(self, prev):
self.variables = list()
self.values = list()
self.previous = prev
@staticmethod
def empty_env():
return GlobalEnv(None)
def lookup(self, symbol):
if symbol in self.variables:
return self.values[self.variables.index(symbol)]
elif self.previous is None:
return None
else:
return self.previous.lookup(symbol)
def extend(self, variables, values):
rib = GlobalEnv(self)
rib.variables = variables
rib.values = values
return rib
pass
class LocalEnv:
""" Implements a "local" version of an environment. This class differs from GlobalEnv only in that it
maintains a reference to a GlobalEnv as well as to a previous LocalEnv. All local environments
have a reference to the global environment. It also does not need an empty_env method as all data
required to create an instance will be known at that time.
Attributes:
variables (List): the identifiers
values (List): the associated values bound to the variables
prev (LocalEnv): a reference to a previous LocalEnv.
globalenv (GlobalEnv): a reference to the GlobalEnv.
Methods to implement:
__init__ Initializes a new instance of a LocalEnv.
Args:
prev (LocalEnv): initialize the variables and values lists, the previous environment is
initialized to the argument.
globalenv (GlobalEnv): initialize the reference to this GlobalEnv object.
lookup Looks up the variable passed to it and returns the associated value.
Args:
symbol (string): A string that is a variable (identifier) that is bound to some value in an environment.
Returns:
value: The value that is bound to the symbol passed in. This can be any object that is stored in the
values list associated with the symbol in a "rib" of the ribcage. If the value is not found in the local environment,
lookup tries the global environment.
extend Creates a new "rib" in a local environment. Passes itself and its global env reference to constructor.
Args:
variables (List): a list of variable identifiers.
values (List): a list of values that correspond to the identifiers in the variables list.
Returns:
LocalEnv: A new instance of a LocalEnv with "self" as the previous environment, and
globalenv as the reference to the global environment.
"""
def __init__(self, prev, globalenv):
self.variables = list()
self.values = list()
self.previous = prev
self.globalenv = globalenv
def lookup(self, symbol):
if symbol in self.variables:
return self.values[self.variables.index(symbol)]
elif self.previous is None:
return self.globalenv.lookup(symbol)
else:
return self.previous.lookup(symbol)
def extend(self, variables, values):
rib = LocalEnv(self, self.globalenv)
rib.variables = variables
rib.values = values
return rib
pass
if __name__ == '__main__':
g = GlobalEnv.empty_env()
g = g.extend(['a', 'b'], [1, 2])
print(g.lookup('a'))
l = g.extend(['x', 'y'], [3, 4])
print(l.lookup('a'))
print(l.lookup('b'))
print(l.lookup('x'))
print(l.lookup('y'))