# HG changeset patch # User Paul Boddie # Date 1211149320 -7200 # Node ID b1ef174ec4a23aa3b60885f54689cdc317dbd868 # Parent e83bc6d2e3b40e38dffa2d92e0fafa7f5bdaa855 Moved Label into the common module. Fixed code generation for class storage. Fixed context generation in method invocations. Added stack pop operation for Discard nodes. Tidied the instructions, adding get_operand methods for use in RSVPMachine instances. Improved instruction coverage in RSVPMachine, employing the instruction representations used elsewhere. Added a function which converts the code such that Attr instances become simplified values of the form (context, reference). diff -r e83bc6d2e3b4 -r b1ef174ec4a2 micropython/ast.py --- a/micropython/ast.py Sun May 18 19:59:26 2008 +0200 +++ b/micropython/ast.py Mon May 19 00:22:00 2008 +0200 @@ -25,17 +25,6 @@ import compiler.ast from compiler.visitor import ASTVisitor -class Label: - - "A reference to a location." - - def __init__(self, number, location=None): - self.number = number - self.location = location - - def __repr__(self): - return "Label(%r, location=%r)" % (self.number, self.location) - # Program visitors. class Translation(ASTVisitor): @@ -399,7 +388,7 @@ # NOTE: Fix context for self-accessed methods. - if context is not None: + if context is not None and isinstance(context, Instance): ncontext = 1 else: ncontext = 0 @@ -1015,6 +1004,14 @@ self._endCallFunc(temp) def visitClass(self, node): + + # Store the name. + + self.new_op(LoadConst(node.unit)) + self._visitName(node, (StoreName, StoreAddress)) + + # Visit the code. + unit = self.unit self.unit = node.unit self.unit.code_location = self.module.code_location # class body code is not independently addressable @@ -1048,6 +1045,7 @@ def visitDiscard(self, node): self.dispatch(node.expr) + self.new_op(Pop()) def visitDiv(self, node): self._visitBinary(node, "__div__", "__rdiv__") diff -r e83bc6d2e3b4 -r b1ef174ec4a2 micropython/common.py --- a/micropython/common.py Sun May 18 19:59:26 2008 +0200 +++ b/micropython/common.py Mon May 19 00:22:00 2008 +0200 @@ -65,6 +65,19 @@ pass +# Program code representations. + +class Label: + + "A reference to a location." + + def __init__(self, number, location=None): + self.number = number + self.location = location + + def __repr__(self): + return "Label(%r, location=%r)" % (self.number, self.location) + # Inspection representations. class AtLeast: diff -r e83bc6d2e3b4 -r b1ef174ec4a2 micropython/rsvp.py --- a/micropython/rsvp.py Sun May 18 19:59:26 2008 +0200 +++ b/micropython/rsvp.py Mon May 19 00:22:00 2008 +0200 @@ -19,8 +19,18 @@ this program. If not, see . """ +from micropython.common import Label from micropython.data import Attr, Const, Instance +def raw(code): + new_code = [] + for item in code: + if isinstance(item, Attr): + new_code.append((item.context and item.context.location, item.value and item.value.location)) + else: + new_code.append(item) + return new_code + class Instruction: "A generic instruction." @@ -41,7 +51,10 @@ "An instruction operating on the local value stack." def __repr__(self): - return "%s(%r)" % (self.__class__.__name__, self.attr.position) + return "%s(%r)" % (self.__class__.__name__, self.get_operand()) + + def get_operand(self): + return self.attr.position SR = StackRelativeInstruction @@ -50,10 +63,10 @@ "An instruction accessing an object's attribute." def __repr__(self): - position = self.attr.position - location = "instance" - result = position - return "%s(%r, %r -> %r)" % (self.__class__.__name__, location, position, result) + return "%s(%r)" % (self.__class__.__name__, self.get_operand()) + + def get_operand(self): + return self.attr.position AR = AddressRelativeInstruction @@ -62,6 +75,13 @@ "An instruction loading an address directly." def __repr__(self): + location, position, result = self.get_operands() + if location is not None: + return "%s(%r, %r -> %r)" % (self.__class__.__name__, location, position, result) + else: + return "%s(%r)" % (self.__class__.__name__, result) + + def get_operands(self): if isinstance(self.attr, Attr): position = self.attr.position location = self.attr.parent.location @@ -74,9 +94,14 @@ location = self.attr.parent.name position = self.attr.name result = None - return "%s(%r, %r -> %r)" % (self.__class__.__name__, location, position, result) + return location, position, result + elif isinstance(self.attr, Label): + return None, None, self.attr.location else: - return "%s(%r)" % (self.__class__.__name__, self.attr.location) + return None, None, self.attr.location + + def get_operand(self): + return self.get_operands()[-1] Address = AddressInstruction @@ -87,6 +112,9 @@ def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.attr) + def get_operand(self): + return self.attr + Immediate = ImmediateInstruction # Mix-in classes for stack effects. @@ -143,16 +171,16 @@ class MakeFrame(Instruction): "Make a new invocation frame." class ReserveFrame(Immediate): "Reserve the given number of entries for the invocation frame." class DropFrame(Instruction): "Drop an invocation frame." -class StoreFrame(StackRemove, Instruction): "Store an argument at the given frame location." +class StoreFrame(StackRemove, Immediate): "Store an argument at the given frame location." class StoreFrameIndex(StackRemove, Immediate): "Store an argument for the parameter with the given index." class CheckFrame(Instruction): "Check the invocation frame for the target." -class JumpWithFrame(Instruction): "Jump, adopting the invocation frame." +class JumpWithFrame(Instruction): "Jump, adopting the invocation frame, to the callable found on the stack." # Invocation-related instructions. -class Jump(Instruction): "Jump unconditionally." -class JumpIfFalse(Instruction): "Jump if the last evaluation gave a false result." -class JumpIfTrue(Instruction): "Jump if the last evaluation gave a true result." +class Jump(Address): "Jump unconditionally." +class JumpIfFalse(Address): "Jump if the last evaluation gave a false result." +class JumpIfTrue(Address): "Jump if the last evaluation gave a true result." class LoadCallable(Instruction): "Load the target of an invocation." class LoadContext(Instruction): "Load the context of an invocation." class CheckContext(Instruction): """Check the context of an invocation against the target, diff -r e83bc6d2e3b4 -r b1ef174ec4a2 rsvp.py --- a/rsvp.py Sun May 18 19:59:26 2008 +0200 +++ b/rsvp.py Mon May 19 00:22:00 2008 +0200 @@ -151,23 +151,29 @@ except IndexError: raise EmptyMetadataStack - def execute(self): + def run(self): "Execute code in the memory, starting from the current PC address." try: while 1: - instruction = self.load(self.pc) - if self.debug: - print "%8d %s" % (self.pc, instruction) - method = getattr(self, instruction, None) - if method is None: - raise IllegalInstruction, self.pc - else: - method() + self.execute() except EmptyPCStack: pass + def execute(self): + + "Execute code in the memory at the current PC address." + + instruction = self.load(self.pc).__class__.__name__ + if self.debug: + print "%8d %s" % (self.pc, instruction) + method = getattr(self, instruction, None) + if method is None: + raise IllegalInstruction, self.pc + else: + method() + def jump(self, addr, next): """ @@ -198,9 +204,9 @@ self.pc += 1 def JumpWithFrame(self): - addr = self.load(self.pc + 1) + addr = self.pull() self.frame_sp += 1 # adopt the added frame - self.jump(addr, self.pc + 2) + self.jump(addr, self.pc + 1) # return to the instruction after this one def LoadName(self): @@ -210,10 +216,10 @@ frame, push the retrieved value onto the stack. """ - n = self.load(self.pc + 1) + n = self.load(self.pc).get_operand() frame = self.frame_stack[self.frame_sp] self.push(self.value_stack[frame + n]) - self.pc += 2 + self.pc += 1 def StoreName(self): @@ -223,10 +229,10 @@ position n in the current stack frame. """ - n = self.load(self.pc + 1) + n = self.load(self.pc).get_operand() frame = self.frame_stack[self.frame_sp] self.value_stack[frame + n] = self.pull() - self.pc += 2 + self.pc += 1 LoadTemp = LoadName StoreTemp = StoreName @@ -242,9 +248,10 @@ NOTE: This assumes that constants are encoded with context. """ - addr = self.load(self.pc + 1) - self.push(addr) - self.pc += 2 + addr = self.load(self.pc).get_operand() + value = (None, addr) + self.push(value) + self.pc += 1 def LoadAttr(self): @@ -255,10 +262,11 @@ value on the top of the stack with the retrieved value. """ - n = self.load(self.pc + 1) - ref = self.pull() - self.push(self.load(ref + n)) - self.pc += 2 + n = self.load(self.pc).get_operand() + context, ref = self.pull() + value = self.load(ref + n) + self.push(value) + self.pc += 1 def StoreAttr(self): @@ -269,39 +277,38 @@ also removing the next value on the stack. """ - n = self.load(self.pc + 1) + n = self.load(self.pc).get_operand() value = self.pull() - self.save(self.pull() + n, value) - self.pc += 2 + context, ref = self.pull() + self.save(ref + n, value) + self.pc += 1 def LoadAddress(self): """ - LoadAddress addr, #n - Load from position n in reference at addr: get the contents of position - n in the memory referenced by addr, adding the retrieved value to the - top of the stack. + 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. """ - red = self.load(self.pc + 1) - n = self.load(self.pc + 2) - self.push(self.load(ref + n)) - self.pc += 3 + addr = self.load(self.pc).get_operand() + value = self.load(addr) + self.push(value) + self.pc += 1 def StoreAddress(self): """ - StoreAddress addr, #n - Save to position n in reference at addr: pull a value from the stack and - save it to position n in the memory referenced by addr, also removing - the value on the top of the stack. + 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. """ - ref = self.load(self.pc + 1) - n = self.load(self.pc + 2) + addr = self.load(self.pc).get_operand() value = self.pull() - self.save(ref + n, value) - self.pc += 3 + self.save(addr, value) + self.pc += 1 def Return(self): @@ -321,12 +328,12 @@ represents a true value, jump to address addr. """ - addr = self.load(self.pc + 1) + addr = self.load(self.pc).get_operand() value = self.pull() if value: self.pc = addr else: - self.pc += 2 + self.pc += 1 def JumpIfFalse(self): @@ -336,12 +343,12 @@ represents a false value, jump to address addr. """ - addr = self.load(self.pc + 1) + addr = self.load(self.pc).get_operand() value = self.pull() if not value: self.pc = addr else: - self.pc += 2 + self.pc += 1 def StoreFrame(self): @@ -352,11 +359,11 @@ given position. """ - pos = self.load(self.pc + 1) + 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 - self.pc += 2 + self.pc += 1 # Library functions. diff -r e83bc6d2e3b4 -r b1ef174ec4a2 test.py --- a/test.py Sun May 18 19:59:26 2008 +0200 +++ b/test.py Mon May 19 00:22:00 2008 +0200 @@ -1,17 +1,31 @@ #!/usr/bin/env python import micropython +from micropython.rsvp import raw +import rsvp import sys code = None def show(importer, with_builtins=0, optimisations=None): + make(importer, with_builtins, optimisations) + show_code(code) + +def make(importer, with_builtins=0, optimisations=None): optimisations = optimisations or requested_optimisations global code code = importer.get_image(with_builtins, optimisations) + +def show_code(code): for i, x in enumerate(code): print i, x +def machine(code, code_location): + rc = raw(code) + rm = rsvp.RSVPMachine(rc) + rm.pc = code_location + return rm + def attrs(obj): for name, attr in obj.items(): print name, attr