# HG changeset patch # User Paul Boddie # Date 1307917093 -7200 # Node ID f2f566f67b5fd1ea5644566d348012f228cdbb5a # Parent ee5f5b872354bf2aeae1ee1c4b976a1692cba1c7 Renamed LoadResult and StoreResult. Changed the RSVP machine instruction handlers to accept an operand directly; this should assist the direct usage of instructions in the RSVP library. Added a trivial assignment test. diff -r ee5f5b872354 -r f2f566f67b5f micropython/ast.py --- a/micropython/ast.py Sun Jun 12 22:14:36 2011 +0200 +++ b/micropython/ast.py Mon Jun 13 00:18:13 2011 +0200 @@ -195,7 +195,7 @@ # Store the object as the result. self.new_op(LoadTemp(0)) # load the context from the locals - self.new_op(StoreResult()) + self.new_op(LoadValueIntoResult()) self.new_op(Return()) self.unit.blocks = self.blocks @@ -854,7 +854,7 @@ else: self.dispatch(compiler.ast.Name("None")) - self.new_op(StoreResult()) + self.new_op(LoadValueIntoResult()) if self.in_exception_handler: self.new_op(ClearException()) diff -r ee5f5b872354 -r f2f566f67b5f micropython/opt.py --- a/micropython/opt.py Sun Jun 12 22:14:36 2011 +0200 +++ b/micropython/opt.py Mon Jun 13 00:18:13 2011 +0200 @@ -195,7 +195,9 @@ a load operation from a CPU register or special memory location. """ - return isinstance(instruction, (LoadConst, LoadClass, LoadFunction, LoadName, LoadTemp, LoadResult, LoadException, LoadAddress)) + return isinstance(instruction, (LoadConst, LoadClass, LoadFunction, + LoadName, LoadTemp, LoadResultIntoValue, LoadException, LoadAddress + )) def is_simple_input_user(self, instruction): @@ -217,7 +219,7 @@ return ( isinstance(instruction.input, LoadTemp) and isinstance(instruction, StoreTemp) and instruction.input.attr == instruction.attr) or ( - isinstance(instruction.input, LoadResult) and isinstance(instruction, StoreResult) + isinstance(instruction.input, LoadResultIntoValue) and isinstance(instruction, LoadValueIntoResult) ) def is_input(self, instruction): @@ -280,11 +282,11 @@ to a temporary variable retaining the result of the last instruction. """ - # LoadResult cannot be relied upon in general since the result register + # LoadResultIntoValue cannot be relied upon in general since the result register # could be updated since first being referenced. return isinstance(self.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst, LoadClass, LoadFunction)) or \ - isinstance(self.active_value, LoadResult) and self.active_value is self.active or \ + isinstance(self.active_value, LoadResultIntoValue) and self.active_value is self.active or \ isinstance(self.active_value, LoadException) and self.active_value is self.active def have_correct_self_for_target(self, context, unit): diff -r ee5f5b872354 -r f2f566f67b5f micropython/rsvp.py --- a/micropython/rsvp.py Sun Jun 12 22:14:36 2011 +0200 +++ b/micropython/rsvp.py Mon Jun 13 00:18:13 2011 +0200 @@ -602,11 +602,11 @@ "Return from a subprogram." cost = 2 -class LoadResult(Instruction): +class LoadResultIntoValue(Instruction): "Load into the current value a returned value." cost = 1 -class StoreResult(Instruction): +class LoadValueIntoResult(Instruction): "Store the current value as a value to be returned." cost = 1 @@ -674,7 +674,7 @@ LoadConst, LoadClass, LoadFunction, LoadName, LoadTemp, LoadAddress, LoadAddressContext, LoadAddressContextCond, LoadAttr, LoadAttrIndex, LoadAttrIndexContextCond, - LoadCallable, LoadContextIntoValue, LoadResult, + LoadCallable, LoadContextIntoValue, LoadResultIntoValue, LoadException, MakeInstance, MakeFragment, CopyExtra ) @@ -682,7 +682,7 @@ # Instructions which use the current value. (LoadAttrIndexContext not defined.) simple_input_user_instructions = ( - StoreTemp, StoreFrame, StoreResult, StoreException, # as the value being stored + StoreTemp, StoreFrame, LoadValueIntoResult, StoreException, # as the value being stored LoadAddressContext, LoadAddressContextCond, # as the object being referenced LoadAttr, LoadAttrIndex, LoadAttrIndexContextCond, # as the object being referenced StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced diff -r ee5f5b872354 -r f2f566f67b5f micropython/trans.py --- a/micropython/trans.py Sun Jun 12 22:14:36 2011 +0200 +++ b/micropython/trans.py Mon Jun 13 00:18:13 2011 +0200 @@ -3,7 +3,7 @@ """ Translate the AST of a Python program into a more interpretable representation. -Copyright (C) 2007, 2008, 2009, 2010 Paul Boddie +Copyright (C) 2007, 2008, 2009, 2010, 2011 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1012,7 +1012,7 @@ # raise an exception. self.new_op(DropFrame()) - self.new_op(LoadResult()) + self.new_op(LoadResultIntoValue()) self.make_exception("TypeError", node) self.new_op(StoreException()) @@ -1051,7 +1051,7 @@ self.new_op(DropFrame()) if load_result: - self.new_op(LoadResult()) + self.new_op(LoadResultIntoValue()) # Discard any temporary storage instructions. @@ -1156,7 +1156,7 @@ if not fn.is_lambda(): self.dispatch(compiler.ast.Name("None")) - self.new_op(StoreResult()) + self.new_op(LoadValueIntoResult()) self.new_op(Return()) # Make sure that enough frame space is reserved from the start. diff -r ee5f5b872354 -r f2f566f67b5f rsvp.py --- a/rsvp.py Sun Jun 12 22:14:36 2011 +0200 +++ b/rsvp.py Mon Jun 13 00:18:13 2011 +0200 @@ -133,7 +133,6 @@ self.exception = None self.instruction = None - self.operand = None self.status = None self.callable = None @@ -192,7 +191,6 @@ print "Exception", self.exception print print "Instruction", self.instruction - print "Operand", self.operand print "Status", self.status print "Callable", self.callable @@ -389,9 +387,9 @@ if not is_input: self.counter += 1 self.cost += instruction.cost - self.operand = instruction.get_operand() + operand = instruction.get_operand() method = self.get_method(instruction) - return method() + return method(operand) def process_inputs(self): @@ -438,97 +436,101 @@ def LoadContext(self, operand): self.context = operand + def LoadSourceValue(self, operand): + self.source_value = operand + + def LoadSourceContext(self, operand): + self.source_context = operand + # Instructions. - def LoadConst(self): - self.LoadContext(self.operand) - self.LoadValue(self.operand) + def LoadConst(self, operand): + self.LoadContext(operand) + self.LoadValue(operand) - def LoadClass(self): + def LoadClass(self, operand): self.LoadContext(PlaceholderContext) - self.LoadValue(self.operand) + self.LoadValue(operand) - def LoadFunction(self): + def LoadFunction(self, operand): self.LoadContext(ReplaceableContext) - self.LoadValue(self.operand) + self.LoadValue(operand) - def LoadName(self): + def LoadName(self, operand): frame = self.local_sp_stack[-1] - data = self.frame_stack[frame + self.operand] + data = self.frame_stack[frame + operand] self.LoadContext(data.context) self.LoadValue(data.ref) - def StoreName(self): + def StoreName(self, operand): frame = self.local_sp_stack[-1] - self.frame_stack[frame + self.operand] = DataValue(self.source_context, self.source_value) + self.frame_stack[frame + operand] = DataValue(self.source_context, self.source_value) LoadTemp = LoadName - def StoreTemp(self): + def StoreTemp(self, operand): frame = self.local_sp_stack[-1] - self.frame_stack[frame + self.operand] = DataValue(self.context, self.value) + self.frame_stack[frame + operand] = DataValue(self.context, self.value) - def LoadAddress(self): + def LoadAddress(self, operand): # Preserve context (potentially null). - data = self.load(self.operand) + data = self.load(operand) self.LoadContext(data.context) self.LoadValue(data.ref) - def LoadAddressContext(self): + def LoadAddressContext(self, operand): # Value becomes context. - data = self.load(self.operand) + data = self.load(operand) self.LoadContext(self.value) self.LoadValue(data.ref) - def LoadAddressContextCond(self): - data = self.load(self.operand) + def LoadAddressContextCond(self, operand): + data = self.load(operand) data = self._LoadAddressContextCond(data.context, data.ref, self.value) self.LoadContext(data.context) self.LoadValue(data.ref) - def StoreAddress(self): + def StoreAddress(self, operand): # Preserve context. - self.save(self.operand, DataValue(self.source_context, self.source_value)) + self.save(operand, DataValue(self.source_context, self.source_value)) - def StoreAddressContext(self): + def StoreAddressContext(self, operand): # Overwrite context if null. - self._StoreAddressContext(self.operand, self.context, self.value, self.source_context, self.source_value) + self._StoreAddressContext(operand, self.context, self.value, self.source_context, self.source_value) - def MakeInstance(self): - size = self.operand + def MakeInstance(self, size): # NOTE: Referencing the instance template. addr = self._MakeObject(size, self.value - Library.instance_template_size) # Introduce object as context for the new object. self.LoadContext(addr) self.LoadValue(addr) - def MakeFragment(self): - size = self.operand + def MakeFragment(self, size): # Reserve twice the amount of space. addr = self._MakeFragment(size, size * 2) # NOTE: Context is not relevant for fragments. self.LoadContext(None) self.LoadValue(addr) - def LoadAttr(self): + def LoadAttr(self, pos): # Retrieved context should already be appropriate for the instance. # NOTE: Adding 1 to skip any header. - data = self.load(self.value + self.operand + 1) + data = self.load(self.value + pos + 1) self.LoadContext(data.context) self.LoadValue(data.ref) - def StoreAttr(self): + def StoreAttr(self, pos): # Target should already be an instance. # NOTE: Adding 1 to skip any header. - self.save(self.value + self.operand + 1, DataValue(self.source_context, self.source_value)) + self.save(self.value + pos + 1, DataValue(self.source_context, self.source_value)) - def LoadAttrIndex(self): + def LoadAttrIndex(self, index): data = self.load(self.value) - element = self.objlist[data.classcode + self.operand] + element = self.objlist[data.classcode + index] if element is not None: attr_index, static_attr, offset = element - if attr_index == self.operand: + if attr_index == index: if static_attr: data = self.load(offset) # offset is address of class/module attribute else: @@ -542,13 +544,13 @@ # LoadAttrIndexContext not defined. - def LoadAttrIndexContextCond(self): + def LoadAttrIndexContextCond(self, index): data = self.load(self.value) - element = self.objlist[data.classcode + self.operand] + element = self.objlist[data.classcode + index] if element is not None: attr_index, static_attr, offset = element - if attr_index == self.operand: + if attr_index == index: if static_attr: loaded_data = self.load(offset) # offset is address of class/module attribute # Absent attrcode == class/module. @@ -563,13 +565,13 @@ self.exception = self._MakeObject(Library.instance_size, self.attr_error_instance) return self.RaiseException() - def StoreAttrIndex(self): + def StoreAttrIndex(self, index): data = self.load(self.value) - element = self.objlist[data.classcode + self.operand] + element = self.objlist[data.classcode + index] if element is not None: attr_index, static_attr, offset = element - if attr_index == self.operand: + if attr_index == index: if static_attr: self._StoreAddressContext(offset, self.context, self.value, self.source_context, self.source_value) return @@ -582,52 +584,52 @@ # NOTE: LoadAttrIndexContext is a possibility if a particular attribute can always be overridden. - def MakeFrame(self): + def MakeFrame(self, size): self.invocation_sp_stack.append(len(self.frame_stack)) - self.frame_stack.extend([None] * self.operand) + self.frame_stack.extend([None] * size) - def DropFrame(self): + def DropFrame(self, operand=None): self.local_sp_stack.pop() frame = self.invocation_sp_stack.pop() del self.frame_stack[frame:] # reset stack before call - def StoreFrame(self): + def StoreFrame(self, pos): frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame - self.frame_stack[frame + self.operand] = DataValue(self.context, self.value) + self.frame_stack[frame + pos] = DataValue(self.context, self.value) - def StoreFrameIndex(self): + def StoreFrameIndex(self, index): frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame data = self.load(self.value) - element = self.paramlist[data.funccode + self.operand] + element = self.paramlist[data.funccode + index] if element is not None: # NOTE: Need to ensure correct positioning where a context has been generated. param_index, offset = element - if param_index == self.operand: + if param_index == index: self.frame_stack[frame + offset] = DataValue(self.source_context, self.source_value) return self.exception = self._MakeObject(Library.instance_size, self.type_error_instance) return self.RaiseException() - def LoadCallable(self): + def LoadCallable(self, operand=None): data = self.load(self.value) self.callable = data.codeaddr - def StoreCallable(self): + def StoreCallable(self, operand=None): # NOTE: Should improve the representation and permit direct saving. data = self.load(self.value) self.save(self.value, data.with_callable(self.callable)) - def LoadContextIntoValue(self): + def LoadContextIntoValue(self, operand=None): # NOTE: Omission of the context of the context would make things like # NOTE: self() inside methods impossible. self.LoadValue(self.context) - def CheckContext(self): + def CheckContext(self, operand=None): self.status = self.value is not ReplaceableContext - def CheckClass(self): + def CheckClass(self, operand=None): if self.value in (ReplaceableContext, PlaceholderContext): self.status = 0 return @@ -641,8 +643,8 @@ self.status = data.attrcode is None # absent attrcode == class - def CheckFrame(self): - (nargs, ndefaults) = self.operand + def CheckFrame(self, operand): + (nargs, ndefaults) = operand # The frame is actually installed as the locals. # Retrieve the context from the first local. @@ -651,12 +653,11 @@ nlocals = len(self.frame_stack[frame:]) if not ((nargs - ndefaults) <= nlocals): - raise Exception, "CheckFrame %r (%r <= %r <= %r)" % (self.operand, nargs - ndefaults, nlocals, nargs) + raise Exception, "CheckFrame %r (%r <= %r <= %r)" % (operand, nargs - ndefaults, nlocals, nargs) self.exception = self._MakeObject(Library.instance_size, self.type_error_instance) return self.RaiseException() - def CheckExtra(self): - nargs = self.operand + def CheckExtra(self, nargs): # The frame is actually installed as the locals. # Retrieve the context from the first local. @@ -669,8 +670,8 @@ if nlocals == nargs: self.frame_stack.extend([None]) # ExtendFrame(1) - def FillDefaults(self): - (nargs, ndefaults) = self.operand + def FillDefaults(self, operand): + (nargs, ndefaults) = operand # The frame is actually installed as the locals. @@ -689,8 +690,7 @@ default += 1 pos += 1 - def CopyExtra(self): - start = self.operand + def CopyExtra(self, start): # The frame is the source of the extra arguments. @@ -712,64 +712,63 @@ self.LoadContext(ref) self.LoadValue(ref) - def CheckInstance(self): + def CheckInstance(self, operand=None): # For the 'self' parameter in an invoked function, the proposed context # ('self') is checked against the target's context. self.status = self._CheckInstance(self.value, self.source_value) - def JumpInFrame(self): + def JumpInFrame(self, operand=None): codeaddr = self.callable return self.jump(codeaddr, self.pc + 1) # return to the instruction after this one - def JumpWithFrame(self): + def JumpWithFrame(self, operand=None): codeaddr = self.callable self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame return self.jump(codeaddr, self.pc + 1) # return to the instruction after this one - def JumpWithFrameDirect(self): - operand = self.operand + def JumpWithFrameDirect(self, addr): self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame - return self.jump(operand, self.pc + 1) # return to the instruction after this one + return self.jump(addr, self.pc + 1) # return to the instruction after this one - def ExtendFrame(self): - self.frame_stack.extend([None] * self.operand) + def ExtendFrame(self, size): + self.frame_stack.extend([None] * size) - def AdjustFrame(self): - self.invocation_sp_stack[-1] += self.operand + def AdjustFrame(self, size): + self.invocation_sp_stack[-1] += size - def Return(self): + def Return(self, operand=None): return self.pull_pc() - def LoadResult(self): + def LoadResultIntoValue(self, operand=None): self.LoadContext(self.result_context) self.LoadValue(self.result_value) - def StoreResult(self): + def LoadValueIntoResult(self, operand=None): self.result_context = self.context self.result_value = self.value - def Jump(self): - return self.operand + def Jump(self, addr): + return addr - def JumpIfTrue(self): + def JumpIfTrue(self, addr): if self.status: - return self.operand + return addr - def JumpIfFalse(self): + def JumpIfFalse(self, addr): if not self.status: - return self.operand + return addr - def LoadException(self): + def LoadException(self, operand=None): self.LoadContext(self.exception) self.LoadValue(self.exception) - def StoreException(self): + def StoreException(self, operand=None): self.exception = self.value - def ClearException(self): + def ClearException(self, operand=None): self.exception = None - def RaiseException(self): + def RaiseException(self, operand=None): # NOTE: Adding the program counter as the first attribute after __class__. self.save(self.exception + Library.instance_data_offset, self.pc) # Jumping to the current handler. @@ -777,14 +776,13 @@ raise Exception return self.handler_stack[-1] - def PushHandler(self): - self.handler_stack.append(self.operand) + def PushHandler(self, addr): + self.handler_stack.append(addr) self.handler_local_sp_stack.append(len(self.local_sp_stack)) self.handler_invocation_sp_stack.append(len(self.invocation_sp_stack)) self.handler_pc_stack.append(len(self.pc_stack)) - def PopHandler(self): - nframes = self.operand + def PopHandler(self, nframes): # Get the new local frame pointer and PC stack references. local_sp_top = self.handler_local_sp_stack[-nframes] invocation_sp_top = self.handler_invocation_sp_stack[-nframes] @@ -801,19 +799,19 @@ del self.handler_invocation_sp_stack[-nframes:] del self.handler_stack[-nframes:] - def CheckException(self): + def CheckException(self, operand=None): self.status = self.exception is not None and self._CheckInstance(self.exception, self.value) - def TestIdentity(self): + def TestIdentity(self, operand=None): self.status = self.value == self.source_value - def TestIdentityAddress(self): - self.status = self.value == self.operand + def TestIdentityAddress(self, addr): + self.status = self.value == addr # LoadBoolean is implemented in the generated code. # StoreBoolean is implemented by testing against the True value. - def InvertBoolean(self): + def InvertBoolean(self, operand=None): self.status = not self.status # Common implementation details. diff -r ee5f5b872354 -r f2f566f67b5f tests/simple_assign.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/simple_assign.py Mon Jun 13 00:18:13 2011 +0200 @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +result_1 = 1 + +# vim: tabstop=4 expandtab shiftwidth=4