-
Notifications
You must be signed in to change notification settings - Fork 0
/
env.py
125 lines (91 loc) · 3.08 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
'''
XXXENV is a list of dicts, ordered by scopeXXX
ENV contains a pointer to memory
In memory, an env consists of a list:
[ <frame>, <pointer to enclosing env> ],
where a frame is a dictionary
TODO:
* clean up mem imports
* consolidate read/write functions?
* should read_from_address return env, address pair?
* figure out define / defmacro interactions
'''
from reg import fetch, assign, EXPR, ENV, VAL, UNEV, ARGL
from lib import LIBRARY, MACRO
from prim import is_primitive
from mem import ROOT, read_from_address, write_to_address, write_to_free_address
UNBOUND = 'UNBOUND'
def read_env_from_memory():
"read env from memory"
address = fetch(ENV)
return read_from_address(address), address
def write_env_to_new_memory(env):
"write env to memory at the earliest available address"
address = write_to_free_address(env)
assign(ENV, address)
def lookup_expr():
"return the value bound to var (in EXPR) in current env"
var = fetch(EXPR)
if is_primitive(var):
return var
env, _ = read_env_from_memory()
while env:
frame, enclosure = env
if var in frame:
return frame[var]
else:
env = read_from_address(enclosure) if enclosure else None
return UNBOUND
def is_unbound(reg):
return fetch(reg) == UNBOUND
def define_var():
"bind var (in UNEV) to val (in VAL) in the most recent frame"
var, val = fetch(UNEV), fetch(VAL)
env, address = read_env_from_memory()
frame, enclosure = env
frame[var] = val
write_to_address([frame, enclosure], address)
def set_var():
"bind the most recent occurence of var (in UNEV) to val (in VAL)"
var, val = fetch(UNEV), fetch(VAL)
env, address = read_env_from_memory()
while env:
frame, enclosure = env
if var in frame:
frame[var] = val
updated_env = [frame, enclosure]
write_to_address(updated_env, address)
return
else:
env, address = read_from_address(enclosure), enclosure
# raise exception? return dummy val?
def define_macro():
_, macro_name, params, expr = fetch(EXPR)
macro_def = [MACRO, params, expr]
# all macros are assigned to global env
global_frame, enclosure = read_from_address(ROOT)
# add macro name to macro list
global_frame[MACRO].append(macro_name)
# install macro
global_frame[macro_name] = macro_def
write_to_address([global_frame, enclosure], ROOT)
def is_macro(expr):
global_frame, _ = read_from_address(ROOT)
return expr in global_frame[MACRO]
def extend_env():
env_pointer = fetch(ENV)
params = fetch(UNEV)
args = fetch(ARGL)
if isinstance(params, str):
new_frame = dict(zip([params], [args]))
else:
new_frame = dict(zip(params, args))
ext_env = [new_frame, env_pointer]
write_env_to_new_memory(ext_env)
# initialization
def initial_env():
return [LIBRARY, None]
def initialize_env():
write_to_address(initial_env(), ROOT)
def load_global_env():
assign(ENV, ROOT)