1.1 --- a/micropython/ast.py Sun Aug 03 00:19:51 2008 +0200
1.2 +++ b/micropython/ast.py Mon Aug 04 01:05:50 2008 +0200
1.3 @@ -85,11 +85,13 @@
1.4 self.exception_labels = []
1.5
1.6 # The code itself. This is limited to the code for a particular block
1.7 - # being processed. Also retained is information about temporary values.
1.8 + # being processed. Also retained is information about temporary values
1.9 + # and instructions which construct frames.
1.10
1.11 self.code = None
1.12 self.temp_positions = set()
1.13 self.max_temp_position = -1
1.14 + self.frame_makers = []
1.15
1.16 def __repr__(self):
1.17 return "Translation(%r)" % self.module
1.18 @@ -222,8 +224,9 @@
1.19 """
1.20
1.21 temp_position = self.reserve_temp()
1.22 - self.new_op(StoreTemp(temp_position))
1.23 - return LoadTemp(temp_position)
1.24 + position_in_frame = self.unit.local_usage + temp_position
1.25 + self.new_op(StoreTemp(position_in_frame))
1.26 + return LoadTemp(position_in_frame)
1.27
1.28 def reserve_temp(self):
1.29 if not self.temp_positions:
1.30 @@ -236,10 +239,8 @@
1.31
1.32 def discard_temp(self, instruction=None):
1.33 if isinstance(instruction, LoadTemp):
1.34 - self.temp_positions.remove(instruction.attr)
1.35 -
1.36 - def cancel_temp(self, temp_position):
1.37 - self.temp_positions.remove(temp_position)
1.38 + position_in_frame = instruction.attr - self.unit.local_usage
1.39 + self.temp_positions.remove(position_in_frame)
1.40
1.41 # Code writing methods.
1.42
1.43 @@ -659,7 +660,9 @@
1.44
1.45 "Record the location of the invocation."
1.46
1.47 - self.new_op(MakeFrame()) # records the start of the frame
1.48 + op = MakeFrame()
1.49 + self.new_op(op) # records the start of the frame
1.50 + self.frame_makers.append(op)
1.51
1.52 def _generateCallFunc(self, args, node):
1.53
1.54 @@ -878,19 +881,29 @@
1.55
1.56 self._generateCallFuncDefaultArgs(target, temp, nargs_min, nargs_max, employed_positions)
1.57
1.58 + # Set the frame size.
1.59 +
1.60 + self.frame_makers[-1].attr = nargs_max
1.61 + self.frame_makers.pop()
1.62 +
1.63 # Or generate instructions to do this at run-time.
1.64 # NOTE: CheckFrame has to check the number of arguments and to fill in
1.65 # NOTE: defaults; it also has to shift the invocation frame according to
1.66 # NOTE: the context in use.
1.67
1.68 else:
1.69 + max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1)
1.70
1.71 # Only check non-empty frames.
1.72
1.73 - if employed_positions or max_keyword_pos >= 0:
1.74 - max_pos = max(max(employed_positions), max_keyword_pos, frame_pos - 1)
1.75 + if employed_positions or max_pos >= 0:
1.76 self.new_op(CheckFrame(max_pos + 1))
1.77
1.78 + # Set the frame size.
1.79 +
1.80 + self.frame_makers[-1].attr = max_pos + 1
1.81 + self.frame_makers.pop()
1.82 +
1.83 def _generateCallFuncDefaultArgs(self, target, temp, nargs_min, nargs_max, employed_positions):
1.84
1.85 """
2.1 --- a/micropython/data.py Sun Aug 03 00:19:51 2008 +0200
2.2 +++ b/micropython/data.py Mon Aug 04 01:05:50 2008 +0200
2.3 @@ -791,7 +791,7 @@
2.4 for i, attr in enumerate(self.locals().values()):
2.5 attr.position = i + j
2.6
2.7 - self.local_usage = i
2.8 + self.local_usage = i + j
2.9 self.finalised = 1
2.10
2.11 def function_from_method(self):
3.1 --- a/micropython/rsvp.py Sun Aug 03 00:19:51 2008 +0200
3.2 +++ b/micropython/rsvp.py Mon Aug 04 01:05:50 2008 +0200
3.3 @@ -173,7 +173,7 @@
3.4
3.5 # Access to invocation frames in preparation.
3.6
3.7 -class MakeFrame(Instruction): "Make a new invocation frame."
3.8 +class MakeFrame(Immediate): "Make a new invocation frame."
3.9 class DropFrame(Instruction): "Drop an invocation frame."
3.10 class StoreFrame(Immediate): "Store the current value as an argument for the parameter with the given position."
3.11 class StoreFrameIndex(Immediate): "Store the current value as an argument for the parameter with the given index."
4.1 --- a/rsvp.py Sun Aug 03 00:19:51 2008 +0200
4.2 +++ b/rsvp.py Mon Aug 04 01:05:50 2008 +0200
4.3 @@ -26,19 +26,20 @@
4.4
4.5 * Memory
4.6 * PC (program counter) stack
4.7 - * Value stack
4.8 - * Frame stack (containing pointers to the value stack)
4.9 - * Current frame and arguments pointers
4.10 + * Frame stack (containing invocation frames in use and in preparation plus
4.11 + temporary storage)
4.12 + * Local frame pointer stack
4.13 + * Invocation frame pointer stack
4.14 + * Exception handler stack
4.15 + * Registers: current value, boolean status value, source value, result,
4.16 + current exception
4.17
4.18 The memory contains constants, global variable references and program code.
4.19
4.20 The PC stack contains the return address associated with each function
4.21 invocation.
4.22
4.23 -The value stack contains references to objects that are being manipulated, along
4.24 -with pointers to previous stack frames.
4.25 -
4.26 -The frame stack tracks the position of stack frames within the value stack.
4.27 +The frame pointer stack tracks the position of frames within the frame stack.
4.28 """
4.29
4.30 class IllegalInstruction(Exception):
4.31 @@ -67,10 +68,22 @@
4.32 self.memory = memory
4.33 self.pc = pc or 0
4.34 self.debug = debug
4.35 +
4.36 + # Stacks.
4.37 +
4.38 self.pc_stack = []
4.39 - self.value_stack = []
4.40 self.frame_stack = []
4.41 - self.frame_sp = 0
4.42 + self.local_sp_stack = []
4.43 + self.invocation_sp_stack = []
4.44 + self.handler_stack = []
4.45 +
4.46 + # Registers.
4.47 +
4.48 + self.value = None
4.49 + self.status = None
4.50 + self.source = None
4.51 + self.result = None
4.52 + self.exception = None
4.53
4.54 def load(self, address):
4.55
4.56 @@ -101,18 +114,6 @@
4.57 self.memory.append(None)
4.58 return addr
4.59
4.60 - def stack_save(self, n, data):
4.61 -
4.62 - "Save to location 'n' on the value stack the given 'data'."
4.63 -
4.64 - self.value_stack.append(data)
4.65 -
4.66 - def stack_load(self, n):
4.67 -
4.68 - "Load a value from the value stack at location 'n'."
4.69 -
4.70 - return self.value_stack.pop()
4.71 -
4.72 def push_pc(self, data):
4.73
4.74 "Push 'data' onto the PC stack."
4.75 @@ -128,29 +129,6 @@
4.76 except IndexError:
4.77 raise EmptyPCStack
4.78
4.79 - def add_frame(self, data):
4.80 -
4.81 - "Add 'data' to the frame stack without updating the stack pointer."
4.82 -
4.83 - self.frame_stack.append(data)
4.84 -
4.85 - def push_frame(self, data):
4.86 -
4.87 - "Push 'data' onto the frame stack."
4.88 -
4.89 - self.frame_stack.append(data)
4.90 - self.frame_sp += 1
4.91 -
4.92 - def pull_frame(self):
4.93 -
4.94 - "Pull a value from the frame stack and return it."
4.95 -
4.96 - try:
4.97 - self.frame_sp -= 1
4.98 - return self.frame_stack.pop()
4.99 - except IndexError:
4.100 - raise EmptyFrameStack
4.101 -
4.102 def run(self):
4.103
4.104 "Execute code in the memory, starting from the current PC address."
4.105 @@ -192,80 +170,36 @@
4.106 # Instructions.
4.107
4.108 def LoadConst(self):
4.109 -
4.110 - """
4.111 - LoadConst addr
4.112 - Load the reference to memory: get the address addr, push the value onto
4.113 - the stack as a value without context.
4.114 -
4.115 - This is useful for loading constants.
4.116 - NOTE: This assumes that constants are encoded with context.
4.117 - """
4.118 -
4.119 op = self.load(self.pc)
4.120 addr = op.get_operand()
4.121 - value = (addr, None)
4.122 - for result in op.results:
4.123 - self.stack_save(result.level, value)
4.124 + self.value = (None, addr)
4.125 self.pc += 1
4.126
4.127 def LoadName(self):
4.128 -
4.129 - """
4.130 - LoadName #n
4.131 - Load from position n in frame: get position n from the current stack
4.132 - frame, push the retrieved value onto the stack.
4.133 - """
4.134 -
4.135 n = self.load(self.pc).get_operand()
4.136 - frame = self.frame_stack[self.frame_sp]
4.137 - self.push(self.value_stack[frame + n])
4.138 + frame = self.local_sp_stack[-1]
4.139 + self.value = self.frame_stack[frame + n]
4.140 self.pc += 1
4.141
4.142 def StoreName(self):
4.143 -
4.144 - """
4.145 - StoreName #n
4.146 - Save to position n in frame: pull a value from the stack and set it as
4.147 - position n in the current stack frame.
4.148 - """
4.149 -
4.150 n = self.load(self.pc).get_operand()
4.151 - frame = self.frame_stack[self.frame_sp]
4.152 - self.value_stack[frame + n] = self.pull()
4.153 + frame = self.local_sp_stack[-1]
4.154 + self.frame_stack[frame + n] = self.value
4.155 self.pc += 1
4.156
4.157 LoadTemp = LoadName
4.158 StoreTemp = StoreName
4.159
4.160 def LoadAttr(self):
4.161 -
4.162 - """
4.163 - LoadAttr #n
4.164 - Load from position n in reference: get the contents of position n in the
4.165 - memory referenced by the value on the top of the stack, replacing the
4.166 - value on the top of the stack with the retrieved value.
4.167 - """
4.168 -
4.169 n = self.load(self.pc).get_operand()
4.170 - context, ref = self.pull()
4.171 - value = self.load(ref + n)
4.172 - self.push(value)
4.173 + context, ref = self.value
4.174 + self.value = self.load(ref + n)
4.175 self.pc += 1
4.176
4.177 def StoreAttr(self):
4.178 -
4.179 - """
4.180 - StoreAttr #n
4.181 - Save to position n in reference: pull a value from the stack and save it
4.182 - to position n in the memory referenced by the next value on the stack,
4.183 - also removing the next value on the stack.
4.184 - """
4.185 -
4.186 n = self.load(self.pc).get_operand()
4.187 - value = self.pull()
4.188 - context, ref = self.pull()
4.189 - self.save(ref + n, value)
4.190 + context, ref = self.value
4.191 + self.save(ref + n, self.source)
4.192 self.pc += 1
4.193
4.194 def LoadAttrIndex(self): pass
4.195 @@ -273,164 +207,95 @@
4.196 def StoreAttrIndex(self): pass
4.197
4.198 def LoadAddress(self):
4.199 + addr = self.load(self.pc).get_operand()
4.200 + self.value = self.load(addr)
4.201 + self.pc += 1
4.202
4.203 - """
4.204 - LoadAddress addr
4.205 - Load from addr: get the contents of the location in memory referenced by
4.206 - addr, adding the retrieved value to the top of the stack.
4.207 - """
4.208 -
4.209 + def LoadAddressContext(self):
4.210 addr = self.load(self.pc).get_operand()
4.211 value = self.load(addr)
4.212 - self.push(value)
4.213 + self.value = (self.value, value[1]) # replace the context with the current value
4.214 self.pc += 1
4.215
4.216 def StoreAddress(self):
4.217 + addr = self.load(self.pc).get_operand()
4.218 + self.save(addr, self.value)
4.219 + self.pc += 1
4.220
4.221 - """
4.222 - StoreAddress addr
4.223 - Save to addr: pull a value from the stack and save it to the location in
4.224 - memory referenced by addr, also removing the value on the top of the
4.225 - stack.
4.226 - """
4.227 -
4.228 - addr = self.load(self.pc).get_operand()
4.229 - value = self.pull()
4.230 - self.save(addr, value)
4.231 + def MakeObject(self):
4.232 + n = self.load(self.pc).get_operand()
4.233 + self.value = self.new(n)
4.234 self.pc += 1
4.235
4.236 def MakeFrame(self):
4.237 n = self.load(self.pc).get_operand()
4.238 - top = len(self.value_stack)
4.239 - self.add_frame(top)
4.240 - while n > 0:
4.241 - self.push(None)
4.242 - n -= 1
4.243 + self.invocation_sp_stack.append(len(self.frame_stack))
4.244 + self.frame_stack.extend([None] * n)
4.245 self.pc += 1
4.246
4.247 + def JumpWithFrame(self):
4.248 + self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame
4.249 + context, ref = self.value
4.250 + self.jump(ref.code_location, self.pc + 1) # return to the instruction after this one
4.251 +
4.252 def DropFrame(self):
4.253 result = self.pull()
4.254 - frame = self.pull_frame()
4.255 - self.value_stack = self.value_stack[:frame] # reset stack before call
4.256 - self.push(result)
4.257 + self.local_sp_stack.pop()
4.258 + frame = self.invocation_sp_stack.pop()
4.259 + self.frame_stack = self.frame_stack[:frame] # reset stack before call
4.260 self.pc += 1
4.261
4.262 + def CheckFrame(self): pass
4.263 +
4.264 def LoadCallable(self): pass
4.265
4.266 def LoadContext(self):
4.267 -
4.268 - """
4.269 - LoadContext
4.270 - Load context from top of stack: get the context from the value on the
4.271 - top of the stack, pushing it onto the stack.
4.272 - """
4.273 -
4.274 - attr = self.value_stack[-1]
4.275 - self.push((attr[1], None))
4.276 + context, ref = self.value
4.277 + self.push((None, context))
4.278 self.pc += 1
4.279
4.280 - def CheckFrame(self): pass
4.281 -
4.282 def CheckSelf(self): pass
4.283
4.284 - def CheckContext(self):
4.285 -
4.286 - """
4.287 - CheckContext
4.288 - Check the context: check the context on the top of the stack
4.289 - """
4.290 -
4.291 - attr = self.value_stack[-1]
4.292 - # NOTE: To be written.
4.293 - self.pc += 1
4.294 -
4.295 - def JumpWithFrame(self):
4.296 - attr = self.pull()
4.297 - self.frame_sp += 1 # adopt the added frame
4.298 - target_location = attr[0]
4.299 - target = self.load(target_location)
4.300 - self.jump(target.code_location, self.pc + 1) # return to the instruction after this one
4.301 + def CheckContext(self): pass
4.302
4.303 def Return(self):
4.304 -
4.305 - """
4.306 - Return
4.307 - Return to the address of the caller: pull a value from the PC stack and
4.308 - set it in the PC.
4.309 - """
4.310 -
4.311 self.pc = self.pull_pc()
4.312
4.313 - def LoadResult(self): pass
4.314 + def LoadResult(self):
4.315 + self.value = self.result
4.316 +
4.317 + def StoreResult(self):
4.318 + self.result = self.value
4.319 +
4.320 + def LoadException(self):
4.321 + self.value = self.exception
4.322 +
4.323 + def StoreException(self):
4.324 + self.exception = self.value
4.325 +
4.326 + def LoadBoolean(self):
4.327 + self.value = self.status
4.328
4.329 def Jump(self): pass
4.330
4.331 def JumpIfTrue(self):
4.332 -
4.333 - """
4.334 - JumpIfTrue addr
4.335 - Jump to address addr if true: pull a value from the stack and if it
4.336 - represents a true value, jump to address addr.
4.337 - """
4.338 -
4.339 addr = self.load(self.pc).get_operand()
4.340 - value = self.pull()
4.341 - if value:
4.342 + if self.status:
4.343 self.pc = addr
4.344 else:
4.345 self.pc += 1
4.346
4.347 def JumpIfFalse(self):
4.348 -
4.349 - """
4.350 - JumpIfFalse addr
4.351 - Jump to address addr if false: pull a value from the stack and if it
4.352 - represents a false value, jump to address addr.
4.353 - """
4.354 -
4.355 addr = self.load(self.pc).get_operand()
4.356 - value = self.pull()
4.357 - if not value:
4.358 + if not self.status:
4.359 self.pc = addr
4.360 else:
4.361 self.pc += 1
4.362
4.363 def StoreFrame(self):
4.364 -
4.365 - """
4.366 - StoreFrame #n
4.367 - Move the value from the top of the stack to the argument in position n:
4.368 - pull a value from the stack and store it in the argument frame at the
4.369 - given position.
4.370 - """
4.371 -
4.372 pos = self.load(self.pc).get_operand()
4.373 - value = self.pull()
4.374 - frame = self.frame_stack[-1] # different from the current frame after MakeFrame
4.375 - self.value_stack[frame + pos] = value
4.376 + frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
4.377 + self.frame_stack[frame + pos] = self.value
4.378 self.pc += 1
4.379
4.380 - # Library functions.
4.381 -
4.382 - def rsvp___printnl(self):
4.383 - print self.load(self.value_stack[-1])
4.384 -
4.385 - def rsvp___print(self):
4.386 - print self.load(self.value_stack[-1]),
4.387 -
4.388 - def int_____gt__(self):
4.389 - self.push(self.load(self.value_stack[-2]) > self.load(self.value_stack[-1]))
4.390 -
4.391 - def int_____sub__(self):
4.392 - result = self.load(self.value_stack[-2]) - self.load(self.value_stack[-1])
4.393 - addr = self.new(1)
4.394 - self.push(addr)
4.395 - self.save(addr, result)
4.396 -
4.397 - def int_____mul__(self):
4.398 - result = self.load(self.value_stack[-2]) * self.load(self.value_stack[-1])
4.399 - addr = self.new(1)
4.400 - self.push(addr)
4.401 - self.save(addr, result)
4.402 -
4.403 # vim: tabstop=4 expandtab shiftwidth=4