Mercurial > repo
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 } |