-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathval.py
140 lines (113 loc) · 3.33 KB
/
val.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
from abc import ABCMeta, abstractmethod
from numbers import Number
'''
Possible final result values of a Lisp expression
'''
class Val:
"""Lisp value type"""
__metaclass__ = ABCMeta
@abstractmethod
def unwrap(self):
pass
def normalize(self):
if issubclass(type(self), PrimFunV) or issubclass(type(self), FunV):
return str(self)
else:
return self.unwrap()
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.__dict__ == other.__dict__
else:
return False
def __ne__(self, other):
return not self.__eq__(other)
@staticmethod
def wrap(prim):
if issubclass(type(prim), Val):
# Anything that's already a valid type
return prim
elif type(prim) is bool:
# Boolean values
return BoolV(prim)
if issubclass(type(prim), Number):
# Numeric types
return NumV(prim)
elif type(prim) is list:
# Cons list
if len(prim) == 0:
return BoolV(False)
else:
return ConsV(Val.wrap(prim[0]), Val.wrap(prim[1:]))
else:
# Lambda functions
return PrimFunV(prim)
class BoolV(Val):
"""Boolean value"""
def __init__(self, state):
self.state = state
def __str__(self):
return "BoolV(" + str(self.state) + ")"
def __repr__(self):
return "t" if self.state else "nil"
def unwrap(self):
return self.state
class NumV(Val):
"""Number value"""
def __init__(self, num):
self.num = num
def __str__(self):
return "NumV(" + str(self.num) + ")"
def __repr__(self):
return str(self.num)
def unwrap(self):
return self.num
class ConsV(Val):
"""Pair of values"""
def __init__(self, head, tail):
self.head, self.tail = head, tail
def __str__(self):
return "ConsV(" + str(self.head) + ", " + str(self.tail) + ")"
def __repr__(self):
return "(cons " + repr(self.head) + " " + repr(self.tail) + ")"
def unwrap(self):
if self.tail.unwrap():
return [self.head] + self.tail.unwrap()
else:
return [self.head]
def normalize(self):
return [
v.normalize() if issubclass(type(v), Val) else v
for v in self.unwrap()
]
class SymV(Val):
"""Symbol value"""
def __init__(self, name):
self.name = name
def __str__(self):
return "SymV(" + str(self.name) + ")"
def __repr__(self):
return "'" + self.name
def unwrap(self):
return "'" + self.name
class FunV(Val):
"""Function value"""
def __init__(self, body, env):
self.body, self.env = body, env
def __str__(self):
return repr(self)
def __repr__(self):
return "[user-defined function]"
def unwrap(self):
return lambda argVal: \
self.body.eval([argVal] + self.env)
class PrimFunV(Val):
"""Primitive (native) function value"""
def __init__(self, thunk):
self.thunk = thunk
def __str__(self):
return repr(self)
def __repr__(self):
return "[native function]"
def unwrap(self):
return lambda argVal: \
Val.wrap(self.thunk(argVal.unwrap()))