# HG changeset patch # User Paul Boddie # Date 1217804750 -7200 # Node ID 051b57229757e3afb4e77f77efa08159050c223f # Parent c3eaefd1e52041aa302a9788f5716debf3fab687 Changed local_usage to include parameters (ie. all_locals). Attempted to support the inclusion of the frame size in MakeFrame instructions. Attempted to update the rsvp module according to the revised architecture. diff -r c3eaefd1e520 -r 051b57229757 micropython/ast.py --- a/micropython/ast.py Sun Aug 03 00:19:51 2008 +0200 +++ b/micropython/ast.py Mon Aug 04 01:05:50 2008 +0200 @@ -85,11 +85,13 @@ self.exception_labels = [] # The code itself. This is limited to the code for a particular block - # being processed. Also retained is information about temporary values. + # being processed. Also retained is information about temporary values + # and instructions which construct frames. self.code = None self.temp_positions = set() self.max_temp_position = -1 + self.frame_makers = [] def __repr__(self): return "Translation(%r)" % self.module @@ -222,8 +224,9 @@ """ temp_position = self.reserve_temp() - self.new_op(StoreTemp(temp_position)) - return LoadTemp(temp_position) + position_in_frame = self.unit.local_usage + temp_position + self.new_op(StoreTemp(position_in_frame)) + return LoadTemp(position_in_frame) def reserve_temp(self): if not self.temp_positions: @@ -236,10 +239,8 @@ def discard_temp(self, instruction=None): if isinstance(instruction, LoadTemp): - self.temp_positions.remove(instruction.attr) - - def cancel_temp(self, temp_position): - self.temp_positions.remove(temp_position) + position_in_frame = instruction.attr - self.unit.local_usage + self.temp_positions.remove(position_in_frame) # Code writing methods. @@ -659,7 +660,9 @@ "Record the location of the invocation." - self.new_op(MakeFrame()) # records the start of the frame + op = MakeFrame() + self.new_op(op) # records the start of the frame + self.frame_makers.append(op) def _generateCallFunc(self, args, node): @@ -878,19 +881,29 @@ self._generateCallFuncDefaultArgs(target, temp, nargs_min, nargs_max, employed_positions) + # Set the frame size. + + self.frame_makers[-1].attr = nargs_max + self.frame_makers.pop() + # Or generate instructions to do this at run-time. # NOTE: CheckFrame has to check the number of arguments and to fill in # NOTE: defaults; it also has to shift the invocation frame according to # NOTE: the context in use. else: + max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1) # Only check non-empty frames. - if employed_positions or max_keyword_pos >= 0: - max_pos = max(max(employed_positions), max_keyword_pos, frame_pos - 1) + if employed_positions or max_pos >= 0: self.new_op(CheckFrame(max_pos + 1)) + # Set the frame size. + + self.frame_makers[-1].attr = max_pos + 1 + self.frame_makers.pop() + def _generateCallFuncDefaultArgs(self, target, temp, nargs_min, nargs_max, employed_positions): """ diff -r c3eaefd1e520 -r 051b57229757 micropython/data.py --- a/micropython/data.py Sun Aug 03 00:19:51 2008 +0200 +++ b/micropython/data.py Mon Aug 04 01:05:50 2008 +0200 @@ -791,7 +791,7 @@ for i, attr in enumerate(self.locals().values()): attr.position = i + j - self.local_usage = i + self.local_usage = i + j self.finalised = 1 def function_from_method(self): diff -r c3eaefd1e520 -r 051b57229757 micropython/rsvp.py --- a/micropython/rsvp.py Sun Aug 03 00:19:51 2008 +0200 +++ b/micropython/rsvp.py Mon Aug 04 01:05:50 2008 +0200 @@ -173,7 +173,7 @@ # Access to invocation frames in preparation. -class MakeFrame(Instruction): "Make a new invocation frame." +class MakeFrame(Immediate): "Make a new invocation frame." class DropFrame(Instruction): "Drop an invocation frame." class StoreFrame(Immediate): "Store the current value as an argument for the parameter with the given position." class StoreFrameIndex(Immediate): "Store the current value as an argument for the parameter with the given index." diff -r c3eaefd1e520 -r 051b57229757 rsvp.py --- a/rsvp.py Sun Aug 03 00:19:51 2008 +0200 +++ b/rsvp.py Mon Aug 04 01:05:50 2008 +0200 @@ -26,19 +26,20 @@ * Memory * PC (program counter) stack - * Value stack - * Frame stack (containing pointers to the value stack) - * Current frame and arguments pointers + * Frame stack (containing invocation frames in use and in preparation plus + temporary storage) + * Local frame pointer stack + * Invocation frame pointer stack + * Exception handler stack + * Registers: current value, boolean status value, source value, result, + current exception The memory contains constants, global variable references and program code. The PC stack contains the return address associated with each function invocation. -The value stack contains references to objects that are being manipulated, along -with pointers to previous stack frames. - -The frame stack tracks the position of stack frames within the value stack. +The frame pointer stack tracks the position of frames within the frame stack. """ class IllegalInstruction(Exception): @@ -67,10 +68,22 @@ self.memory = memory self.pc = pc or 0 self.debug = debug + + # Stacks. + self.pc_stack = [] - self.value_stack = [] self.frame_stack = [] - self.frame_sp = 0 + self.local_sp_stack = [] + self.invocation_sp_stack = [] + self.handler_stack = [] + + # Registers. + + self.value = None + self.status = None + self.source = None + self.result = None + self.exception = None def load(self, address): @@ -101,18 +114,6 @@ self.memory.append(None) return addr - def stack_save(self, n, data): - - "Save to location 'n' on the value stack the given 'data'." - - self.value_stack.append(data) - - def stack_load(self, n): - - "Load a value from the value stack at location 'n'." - - return self.value_stack.pop() - def push_pc(self, data): "Push 'data' onto the PC stack." @@ -128,29 +129,6 @@ except IndexError: raise EmptyPCStack - def add_frame(self, data): - - "Add 'data' to the frame stack without updating the stack pointer." - - self.frame_stack.append(data) - - def push_frame(self, data): - - "Push 'data' onto the frame stack." - - self.frame_stack.append(data) - self.frame_sp += 1 - - def pull_frame(self): - - "Pull a value from the frame stack and return it." - - try: - self.frame_sp -= 1 - return self.frame_stack.pop() - except IndexError: - raise EmptyFrameStack - def run(self): "Execute code in the memory, starting from the current PC address." @@ -192,80 +170,36 @@ # Instructions. def LoadConst(self): - - """ - LoadConst addr - Load the reference to memory: get the address addr, push the value onto - the stack as a value without context. - - This is useful for loading constants. - NOTE: This assumes that constants are encoded with context. - """ - op = self.load(self.pc) addr = op.get_operand() - value = (addr, None) - for result in op.results: - self.stack_save(result.level, value) + self.value = (None, addr) self.pc += 1 def LoadName(self): - - """ - LoadName #n - Load from position n in frame: get position n from the current stack - frame, push the retrieved value onto the stack. - """ - n = self.load(self.pc).get_operand() - frame = self.frame_stack[self.frame_sp] - self.push(self.value_stack[frame + n]) + frame = self.local_sp_stack[-1] + self.value = self.frame_stack[frame + n] self.pc += 1 def StoreName(self): - - """ - StoreName #n - Save to position n in frame: pull a value from the stack and set it as - position n in the current stack frame. - """ - n = self.load(self.pc).get_operand() - frame = self.frame_stack[self.frame_sp] - self.value_stack[frame + n] = self.pull() + frame = self.local_sp_stack[-1] + self.frame_stack[frame + n] = self.value self.pc += 1 LoadTemp = LoadName StoreTemp = StoreName def LoadAttr(self): - - """ - LoadAttr #n - Load from position n in reference: get the contents of position n in the - memory referenced by the value on the top of the stack, replacing the - value on the top of the stack with the retrieved value. - """ - n = self.load(self.pc).get_operand() - context, ref = self.pull() - value = self.load(ref + n) - self.push(value) + context, ref = self.value + self.value = self.load(ref + n) self.pc += 1 def StoreAttr(self): - - """ - StoreAttr #n - Save to position n in reference: pull a value from the stack and save it - to position n in the memory referenced by the next value on the stack, - also removing the next value on the stack. - """ - n = self.load(self.pc).get_operand() - value = self.pull() - context, ref = self.pull() - self.save(ref + n, value) + context, ref = self.value + self.save(ref + n, self.source) self.pc += 1 def LoadAttrIndex(self): pass @@ -273,164 +207,95 @@ def StoreAttrIndex(self): pass def LoadAddress(self): + addr = self.load(self.pc).get_operand() + self.value = self.load(addr) + self.pc += 1 - """ - LoadAddress addr - Load from addr: get the contents of the location in memory referenced by - addr, adding the retrieved value to the top of the stack. - """ - + def LoadAddressContext(self): addr = self.load(self.pc).get_operand() value = self.load(addr) - self.push(value) + self.value = (self.value, value[1]) # replace the context with the current value self.pc += 1 def StoreAddress(self): + addr = self.load(self.pc).get_operand() + self.save(addr, self.value) + self.pc += 1 - """ - StoreAddress addr - Save to addr: pull a value from the stack and save it to the location in - memory referenced by addr, also removing the value on the top of the - stack. - """ - - addr = self.load(self.pc).get_operand() - value = self.pull() - self.save(addr, value) + def MakeObject(self): + n = self.load(self.pc).get_operand() + self.value = self.new(n) self.pc += 1 def MakeFrame(self): n = self.load(self.pc).get_operand() - top = len(self.value_stack) - self.add_frame(top) - while n > 0: - self.push(None) - n -= 1 + self.invocation_sp_stack.append(len(self.frame_stack)) + self.frame_stack.extend([None] * n) self.pc += 1 + def JumpWithFrame(self): + self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame + context, ref = self.value + self.jump(ref.code_location, self.pc + 1) # return to the instruction after this one + def DropFrame(self): result = self.pull() - frame = self.pull_frame() - self.value_stack = self.value_stack[:frame] # reset stack before call - self.push(result) + self.local_sp_stack.pop() + frame = self.invocation_sp_stack.pop() + self.frame_stack = self.frame_stack[:frame] # reset stack before call self.pc += 1 + def CheckFrame(self): pass + def LoadCallable(self): pass def LoadContext(self): - - """ - LoadContext - Load context from top of stack: get the context from the value on the - top of the stack, pushing it onto the stack. - """ - - attr = self.value_stack[-1] - self.push((attr[1], None)) + context, ref = self.value + self.push((None, context)) self.pc += 1 - def CheckFrame(self): pass - def CheckSelf(self): pass - def CheckContext(self): - - """ - CheckContext - Check the context: check the context on the top of the stack - """ - - attr = self.value_stack[-1] - # NOTE: To be written. - self.pc += 1 - - def JumpWithFrame(self): - attr = self.pull() - self.frame_sp += 1 # adopt the added frame - target_location = attr[0] - target = self.load(target_location) - self.jump(target.code_location, self.pc + 1) # return to the instruction after this one + def CheckContext(self): pass def Return(self): - - """ - Return - Return to the address of the caller: pull a value from the PC stack and - set it in the PC. - """ - self.pc = self.pull_pc() - def LoadResult(self): pass + def LoadResult(self): + self.value = self.result + + def StoreResult(self): + self.result = self.value + + def LoadException(self): + self.value = self.exception + + def StoreException(self): + self.exception = self.value + + def LoadBoolean(self): + self.value = self.status def Jump(self): pass def JumpIfTrue(self): - - """ - JumpIfTrue addr - Jump to address addr if true: pull a value from the stack and if it - represents a true value, jump to address addr. - """ - addr = self.load(self.pc).get_operand() - value = self.pull() - if value: + if self.status: self.pc = addr else: self.pc += 1 def JumpIfFalse(self): - - """ - JumpIfFalse addr - Jump to address addr if false: pull a value from the stack and if it - represents a false value, jump to address addr. - """ - addr = self.load(self.pc).get_operand() - value = self.pull() - if not value: + if not self.status: self.pc = addr else: self.pc += 1 def StoreFrame(self): - - """ - StoreFrame #n - Move the value from the top of the stack to the argument in position n: - pull a value from the stack and store it in the argument frame at the - given position. - """ - pos = self.load(self.pc).get_operand() - value = self.pull() - frame = self.frame_stack[-1] # different from the current frame after MakeFrame - self.value_stack[frame + pos] = value + frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame + self.frame_stack[frame + pos] = self.value self.pc += 1 - # Library functions. - - def rsvp___printnl(self): - print self.load(self.value_stack[-1]) - - def rsvp___print(self): - print self.load(self.value_stack[-1]), - - def int_____gt__(self): - self.push(self.load(self.value_stack[-2]) > self.load(self.value_stack[-1])) - - def int_____sub__(self): - result = self.load(self.value_stack[-2]) - self.load(self.value_stack[-1]) - addr = self.new(1) - self.push(addr) - self.save(addr, result) - - def int_____mul__(self): - result = self.load(self.value_stack[-2]) * self.load(self.value_stack[-1]) - addr = self.new(1) - self.push(addr) - self.save(addr, result) - # vim: tabstop=4 expandtab shiftwidth=4