996
|
1 // Action.cpp
|
|
2
|
|
3 #include "lib.h"
|
|
4 #include "Action.h"
|
|
5 #include "Binding.h"
|
|
6 #include "Dir.h"
|
|
7 #include "Error.h"
|
|
8 #include "ActivationRecord.h"
|
|
9
|
|
10 using namespace std;
|
|
11
|
|
12 namespace
|
|
13 {
|
|
14 struct CharTable
|
|
15 {
|
|
16 CharTable()
|
|
17 {
|
|
18 for (int i = 0; i < 256; ++i)
|
|
19 {
|
|
20 data[i] = &(Nop::v);
|
|
21 }
|
|
22
|
|
23 data['t'] = &(True::v);
|
|
24 data['f'] = &(False::v);
|
|
25
|
|
26 data['>'] = &(EastY::v);
|
|
27 data['<'] = &(WestY::v);
|
|
28 data['^'] = &(NorthY::v);
|
|
29 data['v'] = &(SouthY::v);
|
|
30
|
|
31 data['b'] = &(Boom::v);
|
|
32 data['e'] = &(EofCheck::v);
|
|
33 data['i'] = &(Input::v);
|
|
34 data['o'] = &(Output::v);
|
|
35 data['u'] = &(Underflow::v);
|
|
36 data['?'] = &(TypeP::v);
|
|
37
|
|
38 data['a'] = &(Add::v);
|
|
39 data['d'] = &(Divide::v);
|
|
40 data['m'] = &(Multiply::v);
|
|
41 data['r'] = &(Remainder::v);
|
|
42 data['s'] = &(Subtract::v);
|
|
43 data['0'] = &(Digit::v0);
|
|
44 data['1'] = &(Digit::v1);
|
|
45 data['2'] = &(Digit::v2);
|
|
46 data['3'] = &(Digit::v3);
|
|
47 data['4'] = &(Digit::v4);
|
|
48 data['5'] = &(Digit::v5);
|
|
49 data['6'] = &(Digit::v6);
|
|
50 data['7'] = &(Digit::v7);
|
|
51 data['8'] = &(Digit::v8);
|
|
52 data['9'] = &(Digit::v9);
|
|
53
|
|
54 data['c'] = &(Cut::v);
|
|
55 data['p'] = &(Append::v);
|
|
56 data['z'] = &(Size::v);
|
|
57
|
|
58 data['n'] = &(PushNIL::v);
|
|
59 data[':'] = &(Cons::v);
|
|
60 data['~'] = &(ListBreakup::v);
|
|
61
|
|
62 data['g'] = &(GreaterThan::v);
|
|
63 data['q'] = &(IsEqualTo::v);
|
|
64
|
|
65 data['@'] = &(Reflector::v);
|
|
66 data['&'] = &(Lambda::v);
|
|
67 data['#'] = &(End::v);
|
|
68 }
|
|
69
|
|
70 Action * data[256];
|
|
71 };
|
|
72 }
|
|
73
|
|
74 Action * Action::charToAction(char current)
|
|
75 {
|
|
76 static CharTable result;
|
|
77 return result.data[current];
|
|
78 }
|
|
79
|
|
80 void Action::checkVarCount(list<Binding> const & theStack, int count)
|
|
81 {
|
|
82 if (theStack.size() < static_cast<size_t>(count))
|
|
83 {
|
|
84 throw CrashException(Error::stackUnderflow);
|
|
85 }
|
|
86 }
|
|
87
|
|
88 bool Action::checkBool(Binding var)
|
|
89 {
|
|
90 bool result = true;
|
|
91 string str = checkString(var);
|
|
92 if (str == "0")
|
|
93 {
|
|
94 result = false;
|
|
95 }
|
|
96 else if (str == "1")
|
|
97 {
|
|
98 result = true;
|
|
99 }
|
|
100 else
|
|
101 {
|
|
102 throw CrashException(Error::typeMismatch);
|
|
103 }
|
|
104 return result;
|
|
105 }
|
|
106
|
|
107 int Action::checkNumeric(Binding var)
|
|
108 {
|
|
109 int result = 0;
|
|
110 string str = checkString(var);
|
|
111 bool allDigits = true;
|
|
112 for (size_t i = 0; i < str.size() && allDigits; ++i)
|
|
113 {
|
|
114 allDigits = allDigits && isdigit(str[i]);
|
|
115 }
|
|
116 if (allDigits)
|
|
117 {
|
|
118 istringstream stream(str);
|
|
119 stream >> result;
|
|
120 }
|
|
121 else
|
|
122 {
|
|
123 throw CrashException(Error::typeMismatch);
|
|
124 }
|
|
125 return result;
|
|
126 }
|
|
127
|
|
128 ConsCell Action::checkList(Binding var)
|
|
129 {
|
|
130 ConsCell result;
|
|
131 ListVar * lvar = var->getList();
|
|
132 if (lvar == NULL)
|
|
133 {
|
|
134 throw CrashException(Error::typeMismatch);
|
|
135 }
|
|
136 result = lvar->getCell();
|
|
137 return result;
|
|
138 }
|
|
139
|
|
140 string Action::checkString(Binding var)
|
|
141 {
|
|
142 string result;
|
|
143 StringVar * svar = var->getString();
|
|
144 if (svar == NULL)
|
|
145 {
|
|
146 throw CrashException(Error::typeMismatch);
|
|
147 }
|
|
148 result = svar->get();
|
|
149 return result;
|
|
150 }
|
|
151
|
|
152 bool Action::areEqual(Binding left, Binding right)
|
|
153 {
|
|
154 bool result = false;
|
|
155 if (left->getString() != NULL && right->getString() != NULL)
|
|
156 {
|
|
157 result = (left->getString()->get() == right->getString()->get());
|
|
158 }
|
|
159 else if (left->getList() != NULL && right->getList() != NULL)
|
|
160 {
|
|
161 result = (areEqual(left->getList()->getCar(),
|
|
162 right->getList()->getCar())
|
|
163 && areEqual(left->getList()->getCdr(),
|
|
164 right->getList()->getCdr()));
|
|
165 }
|
|
166 else if (left->getNil() != NULL && right->getNil() != NULL)
|
|
167 {
|
|
168 result = true;
|
|
169 }
|
|
170 else if (left->getClosure() != NULL && right->getClosure() != NULL)
|
|
171 {
|
|
172 Closure & leftClosure = *(left->getClosure());
|
|
173 Closure & rightClosure = *(right->getClosure());
|
|
174 result = &(leftClosure.getFunction()) == &(rightClosure.getFunction())
|
|
175 && leftClosure.getPosition() == rightClosure.getPosition()
|
|
176 && leftClosure.getDirection() == rightClosure.getDirection();
|
|
177 std::map<std::string, Binding>::const_iterator leftPos
|
|
178 = leftClosure.getEnvironment().begin();
|
|
179 std::map<std::string, Binding>::const_iterator leftLimit
|
|
180 = leftClosure.getEnvironment().end();
|
|
181 std::map<std::string, Binding>::const_iterator rightPos
|
|
182 = rightClosure.getEnvironment().begin();
|
|
183 std::map<std::string, Binding>::const_iterator rightLimit
|
|
184 = rightClosure.getEnvironment().end();
|
|
185 for (; leftPos != leftLimit && rightPos != rightLimit && result;
|
|
186 ++leftPos, ++rightPos)
|
|
187 {
|
|
188 result = result && areEqual(leftPos->second, rightPos->second);
|
|
189 }
|
|
190 }
|
|
191 else
|
|
192 {
|
|
193 result = false;
|
|
194 }
|
|
195 return result;
|
|
196 }
|
|
197
|
|
198 // first second and third are the incoming directions of the
|
|
199 // y-junction in counterclockwise order.
|
|
200 void Action::runY(list<Binding> & dataStack,
|
|
201 list<ActivationRecord> & programStack,
|
|
202 Dir::t first, Dir::t second, Dir::t third)
|
|
203 {
|
|
204 checkVarCount(dataStack, 1);
|
|
205 ActivationRecord & current = programStack.front();
|
|
206 bool test = checkBool(dataStack.front());
|
|
207 Dir::t direction = current.getDirection();
|
|
208 if ((direction == second && !test)
|
|
209 || (direction == third && test))
|
|
210 {
|
|
211 current.setDirection(Dir::back(first));
|
|
212 }
|
|
213 else if ((direction == third && !test)
|
|
214 || (direction == first && test))
|
|
215 {
|
|
216 current.setDirection(Dir::back(second));
|
|
217 }
|
|
218 else if ((direction == first && !test)
|
|
219 || (direction == second && test))
|
|
220 {
|
|
221 current.setDirection(Dir::back(third));
|
|
222 }
|
|
223 else
|
|
224 {
|
|
225 throw CrashException(Error::wrongDirectionIntoJunction);
|
|
226 }
|
|
227 dataStack.pop_front();
|
|
228 }
|
|
229
|
|
230 void Action::callFunctionByName(string const & name,
|
|
231 list<ActivationRecord> & programStack,
|
|
232 map<string, Board> const & globals)
|
|
233 {
|
|
234 std::map<std::string, Board>::const_iterator pos
|
|
235 = globals.find(name);
|
|
236 if (pos != globals.end())
|
|
237 {
|
|
238 programStack.push_front(ActivationRecord(pos->second));
|
|
239 }
|
|
240 else
|
|
241 {
|
|
242 throw CrashException(Error::globalBindingNotFound);
|
|
243 }
|
|
244 }
|
|
245
|
|
246 Nop Nop::v;
|
|
247 True True::v;
|
|
248 False False::v;
|
|
249
|
|
250 EastY EastY::v;
|
|
251 WestY WestY::v;
|
|
252 NorthY NorthY::v;
|
|
253 SouthY SouthY::v;
|
|
254
|
|
255 Boom Boom::v;
|
|
256 EofCheck EofCheck::v;
|
|
257 Input Input::v;
|
|
258 Output Output::v;
|
|
259 Underflow Underflow::v;
|
|
260 TypeP TypeP::v;
|
|
261
|
|
262 PushConstant PushConstant::v;
|
|
263 UseVariable UseVariable::v;
|
|
264 BindVariable BindVariable::v;
|
|
265 CallFunction CallFunction::v;
|
|
266
|
|
267 Add Add::v;
|
|
268 Divide Divide::v;
|
|
269 Multiply Multiply::v;
|
|
270 Remainder Remainder::v;
|
|
271 Subtract Subtract::v;
|
|
272 Digit Digit::v0(0);
|
|
273 Digit Digit::v1(1);
|
|
274 Digit Digit::v2(2);
|
|
275 Digit Digit::v3(3);
|
|
276 Digit Digit::v4(4);
|
|
277 Digit Digit::v5(5);
|
|
278 Digit Digit::v6(6);
|
|
279 Digit Digit::v7(7);
|
|
280 Digit Digit::v8(8);
|
|
281 Digit Digit::v9(9);
|
|
282
|
|
283 Cut Cut::v;
|
|
284 Append Append::v;
|
|
285 Size Size::v;
|
|
286
|
|
287 PushNIL PushNIL::v;
|
|
288 Cons Cons::v;
|
|
289 ListBreakup ListBreakup::v;
|
|
290
|
|
291 GreaterThan GreaterThan::v;
|
|
292 IsEqualTo IsEqualTo::v;
|
|
293
|
|
294 Reflector Reflector::v;
|
|
295 Lambda Lambda::v;
|
|
296 End End::v;
|