1.1 --- a/rsvp.py Wed Aug 13 19:42:59 2008 +0200
1.2 +++ b/rsvp.py Sun Aug 17 02:16:35 2008 +0200
1.3 @@ -81,6 +81,8 @@
1.4
1.5 # Registers.
1.6
1.7 + self.instruction = None
1.8 + self.operand = None
1.9 self.value = None
1.10 self.status = None
1.11 self.source = None
1.12 @@ -145,35 +147,45 @@
1.13
1.14 "Execute code in the memory at the current PC address."
1.15
1.16 - instruction = self.load(self.pc).__class__.__name__
1.17 + self.instruction = self.load(self.pc)
1.18 + self.operand = self.instruction.get_operand()
1.19 +
1.20 + instruction_name = self.instruction.__class__.__name__
1.21 if self.debug:
1.22 - print "%8d %s" % (self.pc, instruction)
1.23 + print "%8d %s" % (self.pc, instruction_name)
1.24
1.25 - method = self.get_method(instruction)
1.26 + method = self.get_method(instruction_name)
1.27
1.28 # Process any inputs of the instruction.
1.29
1.30 - self.process_inputs(instruction)
1.31 - method()
1.32 + self.process_inputs()
1.33 + next_pc = method()
1.34
1.35 - def get_method(self, instruction):
1.36 + # Update the program counter.
1.37
1.38 - "Return the handler method for the given 'instruction'."
1.39 + if next_pc is None:
1.40 + self.pc += 1
1.41 + else:
1.42 + self.pc = next_pc
1.43
1.44 - method = getattr(self, instruction, None)
1.45 + def get_method(self, instruction_name):
1.46 +
1.47 + "Return the handler method for the given 'instruction_name'."
1.48 +
1.49 + method = getattr(self, instruction_name, None)
1.50 if method is None:
1.51 - raise IllegalInstruction, (self.pc, instruction)
1.52 + raise IllegalInstruction, (self.pc, instruction_name)
1.53 return method
1.54
1.55 - def process_inputs(self, instruction):
1.56 + def process_inputs(self):
1.57
1.58 """
1.59 - Process any inputs of the 'instruction'. This permits any directly
1.60 + Process any inputs of the current instruction. This permits any directly
1.61 connected sub-instructions to produce the effects that separate
1.62 instructions would otherwise have.
1.63 """
1.64
1.65 - for input in (instruction.input, instruction.source):
1.66 + for input in (self.instruction.input, self.instruction.source):
1.67 if input is not None:
1.68 method = self.get_method(input)
1.69 method()
1.70 @@ -188,88 +200,87 @@
1.71
1.72 if isinstance(addr, str):
1.73 getattr(self, addr)()
1.74 - self.pc = next
1.75 + return next
1.76 else:
1.77 self.push_pc(self.pc + 2)
1.78 - self.pc = addr
1.79 + return addr
1.80
1.81 # Instructions.
1.82
1.83 def LoadConst(self):
1.84 - op = self.load(self.pc)
1.85 - addr = op.get_operand()
1.86 - self.value = (None, addr)
1.87 - self.pc += 1
1.88 + self.value = None, self.operand
1.89
1.90 def LoadName(self):
1.91 - n = self.load(self.pc).get_operand()
1.92 frame = self.local_sp_stack[-1]
1.93 - self.value = self.frame_stack[frame + n]
1.94 - self.pc += 1
1.95 + self.value = self.frame_stack[frame + self.operand]
1.96
1.97 def StoreName(self):
1.98 - n = self.load(self.pc).get_operand()
1.99 frame = self.local_sp_stack[-1]
1.100 - self.frame_stack[frame + n] = self.value
1.101 - self.pc += 1
1.102 + self.frame_stack[frame + self.operand] = self.value
1.103
1.104 LoadTemp = LoadName
1.105 StoreTemp = StoreName
1.106
1.107 def LoadAddress(self):
1.108 - addr = self.load(self.pc).get_operand()
1.109 - self.value = self.load(addr)
1.110 - self.pc += 1
1.111 + # Preserve context (potentially null).
1.112 + self.value = self.load(self.operand)
1.113
1.114 def LoadAddressContext(self):
1.115 - addr = self.load(self.pc).get_operand()
1.116 - value = self.load(addr)
1.117 - self.value = (self.value, value[1]) # replace the context with the current value
1.118 - self.pc += 1
1.119 + value = self.load(self.operand)
1.120 + # Replace the context with the current value.
1.121 + self.value = self.value[1], value[1]
1.122
1.123 def StoreAddress(self):
1.124 - addr = self.load(self.pc).get_operand()
1.125 - self.save(addr, self.value)
1.126 - self.pc += 1
1.127 + # Preserve context.
1.128 + self.save(self.operand, self.value)
1.129
1.130 def MakeObject(self):
1.131 - n = self.load(self.pc).get_operand()
1.132 - self.value = self.new(n)
1.133 - self.pc += 1
1.134 + # Introduce null context for new object.
1.135 + self.value = None, self.new(self.operand)
1.136
1.137 def LoadAttr(self):
1.138 - n = self.load(self.pc).get_operand()
1.139 context, ref = self.value
1.140 - self.value = self.load(ref + n)
1.141 - self.pc += 1
1.142 + loaded_context, loaded_ref = self.load(ref + self.operand)
1.143 + if loaded_context is None:
1.144 + # Override null context with owning instance.
1.145 + self.value = ref, loaded_ref
1.146 + else:
1.147 + self.value = loaded_context, loaded_ref
1.148
1.149 def StoreAttr(self):
1.150 - n = self.load(self.pc).get_operand()
1.151 + context, ref = self.value
1.152 + self.save(ref + self.operand, self.source)
1.153 +
1.154 + def LoadAttrIndex(self):
1.155 context, ref = self.value
1.156 - self.save(ref + n, self.source)
1.157 - self.pc += 1
1.158 -
1.159 - def LoadAttrIndex(self): pass
1.160 + code = self.load(ref) # + 0 (the classcode)
1.161 + element = self.objtable[code + self.operand]
1.162 + found_code, found_attr = element
1.163 + if found_code == code:
1.164 + # NOTE: The found context should be tested against the object's context.
1.165 + # NOTE: Compatibility between contexts should be stored in the table, or
1.166 + # NOTE: an incompatible context should be preserved.
1.167 + self.value = ref, found_ref
1.168 + else:
1.169 + # NOTE: This should cause an attribute error.
1.170 + self.value = None
1.171
1.172 def StoreAttrIndex(self): pass
1.173
1.174 def MakeFrame(self):
1.175 - n = self.load(self.pc).get_operand()
1.176 self.invocation_sp_stack.append(len(self.frame_stack))
1.177 - self.frame_stack.extend([None] * n)
1.178 - self.pc += 1
1.179 + self.frame_stack.extend([None] * self.operand)
1.180
1.181 def JumpWithFrame(self):
1.182 self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame
1.183 context, ref = self.value
1.184 - self.jump(ref.code_location, self.pc + 1) # return to the instruction after this one
1.185 + return self.jump(ref.code_location, self.pc + 1) # return to the instruction after this one
1.186
1.187 def DropFrame(self):
1.188 result = self.pull()
1.189 self.local_sp_stack.pop()
1.190 frame = self.invocation_sp_stack.pop()
1.191 self.frame_stack = self.frame_stack[:frame] # reset stack before call
1.192 - self.pc += 1
1.193
1.194 def CheckFrame(self): pass
1.195
1.196 @@ -278,7 +289,6 @@
1.197 def LoadContext(self):
1.198 context, ref = self.value
1.199 self.push((None, context))
1.200 - self.pc += 1
1.201
1.202 def CheckSelf(self): pass
1.203
1.204 @@ -303,27 +313,18 @@
1.205 self.value = self.status
1.206
1.207 def Jump(self):
1.208 - addr = self.load(self.pc).get_operand()
1.209 - self.pc = addr
1.210 + return self.operand
1.211
1.212 def JumpIfTrue(self):
1.213 - addr = self.load(self.pc).get_operand()
1.214 if self.status:
1.215 - self.pc = addr
1.216 - else:
1.217 - self.pc += 1
1.218 + return self.operand
1.219
1.220 def JumpIfFalse(self):
1.221 - addr = self.load(self.pc).get_operand()
1.222 if not self.status:
1.223 - self.pc = addr
1.224 - else:
1.225 - self.pc += 1
1.226 + return self.operand
1.227
1.228 def StoreFrame(self):
1.229 - pos = self.load(self.pc).get_operand()
1.230 frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
1.231 - self.frame_stack[frame + pos] = self.value
1.232 - self.pc += 1
1.233 + self.frame_stack[frame + self.operand] = self.value
1.234
1.235 # vim: tabstop=4 expandtab shiftwidth=4