-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdatatypes.py
165 lines (140 loc) · 3.87 KB
/
datatypes.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
from collections import namedtuple
class Boolean:
def __new__(cls, v):
if v is True:
return true
else:
return false
def __init__(self, v):
self.v = v
def eval(self, env):
return self
def __eq__(self, other):
return self is other
def __repr__(self):
return 'Boolean({!r})'.format(self.v)
class TrueType(Boolean):
def __new__(cls, v):
return object.__new__(cls)
def __str__(self):
return '#t'
class FalseType(Boolean):
def __new__(cls, v):
return object.__new__(cls)
def __str__(self):
return '#f'
true = TrueType(True)
false = FalseType(False)
class Symbol:
def __init__(self, name):
self.name = name
def __eq__(self, other):
if isinstance(other, Symbol):
return self.name == other.name
else:
return super().__eq__(other)
def __repr__(self):
return 'Symbol({!r})'.format(self.name)
def __str__(self):
return self.name
def eval(self, env):
return env.lookup(self.name)
def set(self, env, value):
return env.set(self.name, value)
def add(self, env, value):
return env.add(self.name, value)
class String:
def __init__(self, string):
self.string = string
def __eq__(self, other):
if isinstance(other, String):
return self.string == other.string
return False
def __repr__(self):
return 'String({!r})'.format(self.string)
def __str__(self):
return '"{}"'.format(self.string)
def eval(self, env):
return self
class Inexact:
def __init__(self, string):
self.value = float(string)
def __eq__(self, other):
if isinstance(other, float):
return self.value == other
elif isinstance(other, Inexact):
return self.value == other.value
else:
return super().__eq__(other)
def __repr__(self):
return 'Inexact({!r})'.format(self.value)
def __str__(self):
return '#i{}'.format(self.value)
def eval(self, env):
return self
class Exact:
def __init__(self, string):
self.value = int(string)
def __eq__(self, other):
if isinstance(other, int):
return self.value == other
elif isinstance(other, Exact):
return self.value == other.value
else:
return super().__eq__(other)
def __repr__(self):
return 'Exact({!r})'.format(self.value)
def __str__(self):
return '#e{}'.format(self.value)
def eval(self, env):
return self
def cons(car, cdr):
return Cons(car, cdr)
def to_cons(iterator):
return make_list(list(iterator))
def from_cons(cons):
if cons == nil:
return
yield cons.car
if cons.cdr is not nil:
yield from from_cons(cons.cdr)
class BaseCons: pass
class Cons(BaseCons):
def __init__(self, car, cdr):
self.car = car
self.cdr = cdr
def __repr__(self):
return 'Cons({!r}, {!r})'.format(
self.car, self.cdr)
def __str__(self):
return '({})'.format(
' '.join(map(str, from_cons(self))))
def __eq__(self, other):
if isinstance(other, Cons):
return self.car == other.car and self.cdr == other.cdr
else:
return super().__eq__(other)
class Nil(BaseCons):
def __repr__(self):
return 'Nil()'
def __str__(self):
return '()'
@property
def car(self):
return nil
@property
def cdr(self):
return nil
nil = Nil()
class Ignore:
pass
ignore = Ignore()
def make_dotted(exprs, final):
if len(exprs) == 0:
return final
if len(exprs) == 1:
return cons(exprs[0], final)
else:
return cons(exprs[0], make_dotted(exprs[1:], final))
def make_list(exprs):
return make_dotted(exprs, nil)