1 #!/usr/bin/env python 2 3 """ 4 RSVP instruction classes. 5 6 Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from micropython.data import Attr, Const 23 from micropython.program import Block 24 25 def name(attr): 26 if isinstance(attr, Attr): 27 return attr.name or "<unnamed>" 28 elif isinstance(attr, (Block, Const)): 29 return attr 30 else: 31 return attr.full_name() or "<unnamed>" 32 33 class Instruction: 34 35 "A generic instruction." 36 37 def __init__(self, attr=None): 38 self.attr = attr 39 self.input = None 40 self.source = None # for storage instructions 41 42 def copy(self): 43 return self.__class__(self.attr) 44 45 def __repr__(self): 46 if self.attr is not None: 47 return "%s(%r)%s" % (self.__class__.__name__, self.attr, self.show_input()) 48 else: 49 return "%s()%s" % (self.__class__.__name__, self.show_input()) 50 51 def show_input(self): 52 if self.input is not None: 53 if self.source is not None: 54 return " <- (%r, %r)" % (self.input, self.source) 55 else: 56 return " <- %r" % self.input 57 elif self.source is not None: 58 return " <-- %r" % self.source 59 else: 60 return "" 61 62 def get_operand(self): 63 return None 64 65 class FrameRelativeInstruction(Instruction): 66 67 "An instruction operating on the current frame." 68 69 def __repr__(self): 70 return "%s(%r)%s" % (self.__class__.__name__, self.get_operand(), self.show_input()) 71 72 def get_operand(self): 73 return self.attr.position 74 75 FR = FrameRelativeInstruction 76 77 class AddressRelativeInstruction(Instruction): 78 79 "An instruction accessing an object's attribute." 80 81 def __repr__(self): 82 position = self.get_operand() 83 if position is not None: 84 return "%s(%r)%s # %s" % (self.__class__.__name__, position, self.show_input(), name(self.attr)) 85 else: 86 return "%s(%r)%s" % (self.__class__.__name__, name(self.attr), self.show_input()) 87 88 def get_operand(self): 89 return self.attr.position 90 91 AR = AddressRelativeInstruction 92 93 class AddressInstruction(Instruction): 94 95 "An instruction loading an address directly." 96 97 def __repr__(self): 98 location, position, result = self.get_operands() 99 if location is not None: 100 return "%s(%r)%s # %r, %r (%s)" % ( 101 self.__class__.__name__, result, self.show_input(), location, position, name(self.attr)) 102 elif result is not None: 103 return "%s(%r)%s # %s" % ( 104 self.__class__.__name__, result, self.show_input(), name(self.attr)) 105 else: 106 return "%s(...)%s # %s" % ( 107 self.__class__.__name__, self.show_input(), name(self.attr)) 108 109 def get_operands(self): 110 if isinstance(self.attr, Attr): 111 position = self.attr.position 112 location = self.attr.parent.location 113 114 # NOTE: Unpositioned attributes are handled here. 115 116 if location is not None and position is not None: 117 result = location + position + 1 118 else: 119 location = self.attr.parent.name 120 position = self.attr.name 121 result = None 122 return location, position, result 123 else: 124 return None, None, self.attr.location 125 126 def get_operand(self): 127 return self.get_operands()[-1] 128 129 Address = AddressInstruction 130 131 class ImmediateInstruction(Instruction): 132 133 "An instruction employing a constant." 134 135 def __repr__(self): 136 return "%s(%r)%s" % (self.__class__.__name__, self.attr, self.show_input()) 137 138 def get_operand(self): 139 return self.attr 140 141 Immediate = ImmediateInstruction 142 143 # Access to stored constant data. 144 145 class LoadConst(Address): "Load the constant, class, function, module from the specified location." 146 147 # Access within an invocation frame. 148 149 class LoadName(FR): "Load the current value from the given local attribute/variable." 150 class StoreName(FR): "Store the source value into the given local attribute/variable." 151 class LoadTemp(Immediate): "Load the current value from the given temporary location." 152 class StoreTemp(Immediate): "Store the current value into the given temporary location." 153 154 # Access to static data. 155 156 class LoadAddress(Address): "Load the current value from the given fixed attribute address." 157 class StoreAddress(Address): "Store the source value into the given fixed attribute address." 158 class LoadAddressContext(Address): "Load the current value from the given fixed attribute address, making the current value the context." 159 class LoadAddressContextCond(Address): 160 """Load the current value from the given fixed attribute address, only making the current value the 161 context if the attribute is compatible.""" 162 class MakeObject(Immediate): "Make a new object. There isn't a complementary DropObject." 163 164 # Access to address-relative data. 165 166 class LoadAttr(AR): "Load into the current value the given attribute of the object referenced by the current value." 167 class StoreAttr(AR): "Store the source value into the given attribute of the object referenced by the current value." 168 class LoadAttrIndex(Immediate): "Load into the current value the attribute of the current value with the given index." 169 class StoreAttrIndex(Immediate): "Store the source value into the attribute of the current value with the given index." 170 class LoadAttrIndexContext(Immediate): 171 """Load into the current value the attribute of the current value with the given index, making the 172 current value the context.""" 173 class LoadAttrIndexContextCond(Immediate): 174 """Load into the current value the attribute of the current value with the given index, only making the 175 current value the context if the attribute is compatible.""" 176 177 # Access to object details. 178 179 class LoadCallable(Instruction): "Load the target of an invocation." 180 class StoreCallable(Instruction): "Store the source value into the object referenced by the current value." 181 182 # Access to invocation frames in preparation. 183 184 class MakeFrame(Immediate): "Make a new invocation frame." 185 class DropFrame(Instruction): "Drop an invocation frame." 186 class RecoverFrame(Instruction): "Recover the current frame as an invocation frame." 187 class StoreFrame(Immediate): "Store the current value as an argument for the parameter with the given position." 188 class StoreFrameIndex(Immediate): "Store the source value as an argument of the current value for the parameter with the given index." 189 class LoadContext(Instruction): "Load the context of an invocation." 190 class CheckFrame(Immediate): "Check the invocation frame and context for the target." 191 class CheckSelf(Instruction): "Check the first argument of an invocation against the target." 192 193 # Invocation-related instructions, using a special result "register". 194 195 class JumpWithFrame(Instruction): "Jump, adopting the invocation frame, to the current callable." 196 class ExtendFrame(Immediate): "Extend the current frame for temporary storage use." 197 class AdjustFrame(Immediate): "Adjust the current frame for corrected invocations." 198 class Return(Instruction): "Return from a subprogram." 199 class LoadResult(Instruction): "Load into the current value a returned value." 200 class StoreResult(Instruction): "Store the current value as a value to be returned." 201 202 # Branch-related instructions. 203 204 class Jump(Address): "Jump unconditionally." 205 class JumpIfFalse(Address): "Jump if the last evaluation gave a false result." 206 class JumpIfTrue(Address): "Jump if the last evaluation gave a true result." 207 208 # Exception-related instructions, using a special exception "register". 209 210 class LoadException(Instruction): "Load the raised exception." 211 class StoreException(Instruction): "Store the current object in the exception register." 212 class RaiseException(Instruction): "Raise an exception, jumping to the active handler." 213 class PushHandler(Address): "Push an exception handler onto the handler stack." 214 class PopHandler(Instruction): "Pop an exception handler from the handler stack." 215 class CheckException(Instruction): "Check the raised exception against another." 216 217 # Test instructions, operating on the boolean status register. 218 219 class TestIdentity(Instruction): "Test whether the current value is identical to the source value, setting the boolean status." 220 class TestIdentityAddress(Address): "Test whether the current value is identical to the given address, setting the boolean status." 221 class InvertBoolean(Instruction): "Invert the boolean status." 222 223 # Instructions which affect the current value. 224 225 current_value_instructions = ( 226 LoadConst, LoadName, LoadTemp, 227 LoadAddress, LoadAddressContext, LoadAddressContextCond, 228 LoadAttr, LoadAttrIndex, LoadAttrIndexContext, LoadAttrIndexContextCond, 229 LoadCallable, LoadContext, LoadResult, 230 LoadException, MakeObject 231 ) 232 233 # vim: tabstop=4 expandtab shiftwidth=4