comparison interps/rail/src/ActivationRecord.cpp @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
comparison
equal deleted inserted replaced
995:6883f5911eb7 996:859f9b4339e6
1 // ActivationRecord.cpp
2
3 #include "lib.h"
4 #include "ActivationRecord.h"
5 #include "Rail.h"
6 #include "Error.h"
7 #include "MultiLexer.h"
8 #include "StringVar.h"
9 #include "Action.h"
10
11 using namespace std;
12
13 ActivationRecord::ActivationRecord()
14 : function(NULL)
15 , direction(Dir::north)
16 {
17 }
18
19 ActivationRecord::ActivationRecord(Board const & source)
20 : function(&source)
21 , position(0,0)
22 , direction(Dir::southeast)
23 {
24 }
25
26 ActivationRecord::ActivationRecord(Closure const & source)
27 : environment(source.getEnvironment())
28 , function(&(source.getFunction()))
29 , position(source.getPosition())
30 , direction(source.getDirection())
31 {
32 }
33
34 ActivationRecord::~ActivationRecord()
35 {
36 }
37
38 ActivationRecord::ActivationRecord(ActivationRecord const & right)
39 {
40 // This is exception-safe because the environment copy is the only
41 // thing that can fail.
42 environment = right.environment;
43 function = right.function;
44 position = right.position;
45 direction = right.direction;
46 }
47
48 ActivationRecord & ActivationRecord::operator=(ActivationRecord const & right)
49 {
50 environment = right.environment;
51 function = right.function;
52 position = right.position;
53 direction = right.direction;
54 return *this;
55 }
56
57 void ActivationRecord::move(MultiLexer & multi)
58 {
59 if (function == NULL)
60 {
61 throw InternalException("ActivationRecord::move(): No board");
62 }
63 if (multi.isDone())
64 {
65 throw InternalException("ActivationRecord::move(): Move requested when multi is already done");
66 }
67 else if (multi.isStarted())
68 {
69 position = position + Dir::dirToVec(direction);
70 if (position.x < function->getMinX() || position.x > function->getMaxX()
71 || position.y < function->getMinY() || position.y > function->getMaxY())
72 {
73 throw CrashException(Error::multiOutOfBounds);
74 }
75 }
76 else
77 {
78 normalMove();
79 }
80 }
81
82 void ActivationRecord::normalMove(void)
83 {
84 Vec primPos = position + Dir::dirToVec(direction);
85 Vec leftPos = position + Dir::dirToVec(Dir::left(direction));
86 Vec rightPos = position + Dir::dirToVec(Dir::right(direction));
87
88 Rail::t sourceRail = Rail::charToRail(function->at(position));
89 Rail::t primRail = Rail::charToRail(function->at(primPos));
90 Rail::t leftRail = Rail::charToRail(function->at(leftPos));
91 Rail::t rightRail = Rail::charToRail(function->at(rightPos));
92
93 Rail::t resultRail = Rail::rubble;
94
95 if (Rail::isPrimary(sourceRail, primRail, direction))
96 {
97 position = primPos;
98 resultRail = primRail;
99 }
100 else
101 {
102 bool isLeft = Rail::isLeft(sourceRail, leftRail);
103 bool isRight = Rail::isRight(sourceRail, rightRail);
104 if (isLeft && !isRight)
105 {
106 position = leftPos;
107 resultRail = leftRail;
108 }
109 else if (!isLeft && isRight)
110 {
111 position = rightPos;
112 resultRail = rightRail;
113 }
114 else if (isLeft && isRight)
115 {
116 throw CrashException(Error::ambiguousMove);
117 }
118 else
119 {
120 // !isLeft && !isRight
121 // cerr << "orig: '" << function->at(position) << "'" << endl;
122 // cerr << "left: '" << function->at(leftPos) << "'" << endl;
123 // cerr << "prim: '" << function->at(primPos) << "'" << endl;
124 // cerr << "right: '" << function->at(rightPos) << "'" << endl;
125 throw CrashException(Error::noValidMove);
126 }
127 }
128 direction = Rail::correctDirection(resultRail, direction);
129 }
130
131 Action & ActivationRecord::getAction(MultiLexer & multi,
132 list<Binding> & dataStack)
133 {
134 if (function == NULL)
135 {
136 throw InternalException("ActivationRecord::act(): No board");
137 }
138 if (multi.isDone())
139 {
140 throw InternalException("ActivationRecord::getAction(): action requested when multi is already done");
141 }
142 else if (multi.isStarted())
143 {
144 multi.add(function->at(position));
145 if (multi.isFunction())
146 {
147 dataStack.push_front(Binding(new StringVar(multi.getToken())));
148 multi.reset();
149 return CallFunction::v;
150 }
151 else if (multi.isConstant())
152 {
153 dataStack.push_front(Binding(new StringVar(multi.getToken())));
154 multi.reset();
155 return PushConstant::v;
156 }
157 else if (multi.isUse())
158 {
159 dataStack.push_front(Binding(new StringVar(multi.getToken())));
160 multi.reset();
161 return UseVariable::v;
162 }
163 else if (multi.isBind())
164 {
165 dataStack.push_front(Binding(new StringVar(multi.getToken())));
166 multi.reset();
167 return BindVariable::v;
168 }
169 else
170 {
171 return Nop::v;
172 }
173 }
174 else
175 {
176 switch(function->at(position))
177 {
178 case '[':
179 case ']':
180 case '{':
181 case '}':
182 case '(':
183 case ')':
184 multi.add(function->at(position));
185 return Nop::v;
186 default:
187 Action * act = Action::charToAction(function->at(position));
188 if (act == NULL)
189 {
190 throw InternalException("ActivationRecord::act(): NULL action");
191 }
192 return *act;
193 }
194 }
195 }
196
197 std::map<std::string, Binding> const & ActivationRecord::getEnvironment(void)
198 const
199 {
200 return environment;
201 }
202
203 void ActivationRecord::bindVariable(string name, Binding var)
204 {
205 environment[name] = var;
206 }
207
208 Board const * ActivationRecord::getFunction(void) const
209 {
210 return function;
211 }
212
213 Vec ActivationRecord::getPosition(void) const
214 {
215 return position;
216 }
217
218 void ActivationRecord::setPosition(Vec newPosition)
219 {
220 position = newPosition;
221 }
222
223 Dir::t ActivationRecord::getDirection(void) const
224 {
225 return direction;
226 }
227
228 void ActivationRecord::setDirection(Dir::t newDirection)
229 {
230 direction = newDirection;
231 }