Clean up how References and Instructions work. Needs more tests.
Chris Pressey
10 years ago
189 | 189 | |
190 | 190 | |
191 | 191 | class Reference(object): # abstract |
192 | def get_register_number(self): | |
192 | def get_value(self, state): | |
193 | 193 | raise NotImplementedError |
194 | 194 | |
195 | def set_value(self, state, value): | |
196 | raise NotImplementedError | |
197 | ||
195 | 198 | |
196 | 199 | class ImmediateReference(Reference): |
197 | def __init__(self, number): | |
198 | self.number = number | |
200 | def __init__(self, value): | |
201 | self.value = value | |
202 | ||
203 | def get_value(self, state): | |
204 | return self.value | |
205 | ||
206 | def __str__(self): | |
207 | return str(self.number) | |
199 | 208 | |
200 | 209 | |
201 | 210 | class DirectRegisterReference(Reference): |
202 | def __init__(self, number): | |
203 | self.number = number | |
204 | ||
205 | def get_register_number(self): | |
206 | return self.number | |
211 | def __init__(self, index): | |
212 | self.index = index | |
213 | ||
214 | def get_value(self, state): | |
215 | return state[self.index] | |
216 | ||
217 | def set_value(self, state, value): | |
218 | state[self.index] = value | |
219 | ||
220 | def __str__(self): | |
221 | return "R%d" % self.number | |
207 | 222 | |
208 | 223 | |
209 | 224 | class IndirectRegisterReference(Reference): |
211 | 226 | assert isinstance(ref, Reference) |
212 | 227 | self.ref = ref |
213 | 228 | |
214 | def get_register_number(self): | |
215 | return self.ref.get_register_number() | |
229 | def get_value(self, state): | |
230 | return state[self.ref.get_value(state)] | |
231 | ||
232 | def set_value(self, state, value): | |
233 | state[self.ref.get_value(state)] = value | |
234 | ||
235 | def __str__(self): | |
236 | return "R[%s]" % self.ref | |
216 | 237 | |
217 | 238 | |
218 | 239 | class Scanner(object): |
239 | 260 | self.line = self.line[1:] |
240 | 261 | if self.line[0] == '[': |
241 | 262 | self.line = self.line[1:] |
242 | inner = self.scan_register() | |
263 | inner = self.scan_reference() | |
243 | 264 | self.expect(']') |
244 | 265 | return IndirectRegisterReference(inner) |
245 | 266 | else: |
252 | 273 | |
253 | 274 | class Instruction(object): |
254 | 275 | def __init__(self): |
255 | self.source_register = 0 | |
256 | self.destination_register = 0 | |
257 | self.source_is_immediate = False | |
258 | self.source_is_indirect = False | |
259 | self.destination_is_indirect = False | |
276 | self.source_register = None | |
277 | self.destination_register = None | |
260 | 278 | |
261 | 279 | def parse(self, line): |
262 | 280 | line = line.strip() |
265 | 283 | |
266 | 284 | scanner = Scanner(line) |
267 | 285 | scanner.expect('MOV') |
268 | line = scanner.line | |
269 | ||
270 | dest = scanner.scan_reference() | |
286 | ||
287 | self.destination_register = scanner.scan_reference() | |
288 | ||
289 | assert not isinstance(self.destination_register, ImmediateReference) | |
290 | ||
271 | 291 | scanner.expect(',') |
272 | source = scanner.scan_reference() | |
292 | self.source_register = scanner.scan_reference() | |
273 | 293 | |
274 | 294 | if scanner.line and scanner.line[0] != ';': |
275 | 295 | raise SyntaxError("Expected EOL or comment") |
276 | ||
277 | assert not isinstance(dest, ImmediateReference) | |
278 | ||
279 | if isinstance(source, ImmediateReference): | |
280 | assert isinstance(dest, DirectRegisterReference) | |
281 | ||
282 | self.source_is_immediate = True | |
283 | self.destination_register = dest.get_register_number() | |
284 | self.source_register = source.number | |
285 | return True | |
286 | ||
287 | if isinstance(dest, IndirectRegisterReference): | |
288 | self.destination_is_indirect = True | |
289 | self.destination_register = dest.get_register_number() | |
290 | ||
291 | if isinstance(source, IndirectRegisterReference): | |
292 | self.source_is_indirect = True | |
293 | self.source_register = source.get_register_number() | |
294 | 296 | |
295 | 297 | return True |
296 | 298 | |
297 | 299 | def apply(self, state): |
298 | if self.source_is_indirect: | |
299 | source_register = state[self.source_register] | |
300 | else: | |
301 | source_register = self.source_register | |
302 | ||
303 | if self.source_is_immediate: | |
304 | contents = source_register | |
305 | else: | |
306 | contents = state[source_register] | |
307 | ||
308 | if self.destination_is_indirect: | |
309 | destination_register = state[self.destination_register] | |
310 | else: | |
311 | destination_register = self.destination_register | |
312 | state[destination_register] = contents | |
313 | ||
314 | def __str__(self): | |
315 | dest_fmt = "R%d" | |
316 | if self.destination_is_indirect: | |
317 | dest_fmt = "R[R%d]" | |
318 | src_fmt = "R%d" | |
319 | if self.source_is_indirect: | |
320 | src_fmt = "R[R%d]" | |
321 | if self.source_is_immediate: | |
322 | src_fmt = "%d" | |
323 | return "MOV %s, %s" % (dest_fmt % self.destination_register, | |
324 | src_fmt % self.source_register) | |
300 | value = self.source_register.get_value(state) | |
301 | self.destination_register.set_value(state, value) | |
302 | ||
303 | def __str__(self): | |
304 | return "MOV %s, %s" % (self.destination_register, self.source_register) | |
325 | 305 | |
326 | 306 | |
327 | 307 | class Processor(object): |