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 TargetInstruction(Instruction): 132 133 "An instruction loading the address of an invocation target." 134 135 def __repr__(self): 136 return "%s(%r) # %r" % (self.__class__.__name__, self.get_operand(), name(self.attr)) 137 138 def get_operand(self): 139 return self.attr.get_body_block().location 140 141 Target = TargetInstruction 142 143 class ImmediateInstruction(Instruction): 144 145 "An instruction employing a constant." 146 147 def __repr__(self): 148 return "%s(%r)%s" % (self.__class__.__name__, self.attr, self.show_input()) 149 150 def get_operand(self): 151 return self.attr 152 153 Immediate = ImmediateInstruction 154 155 # Access to stored constant data. 156 157 class LoadConst(Address): "Load the constant or module from the specified location." 158 class LoadClass(Address): "Load the class from the specified location." 159 class LoadFunction(Address): "Load the function from the specified location." 160 161 # Access within an invocation frame. 162 163 class LoadName(FR): "Load the current value from the given local attribute/variable." 164 class StoreName(FR): "Store the source value into the given local attribute/variable." 165 class LoadTemp(Immediate): "Load the current value from the given temporary location." 166 class StoreTemp(Immediate): "Store the current value into the given temporary location." 167 168 # Access to static data. 169 170 class LoadAddress(Address): "Load the current value from the given fixed attribute address." 171 class StoreAddress(Address): "Store the source value into the given fixed attribute address." 172 class LoadAddressContext(Address): "Load the current value from the given fixed attribute address, using the current value as context." 173 class StoreAddressContext(Address): "Store the current value into the given fixed attribute address, using the current value as context." 174 class LoadAddressContextCond(Address): 175 """Load the current value from the given fixed attribute address, only using the current value as 176 context if the attribute is compatible.""" 177 class MakeInstance(Immediate): "Make a new instance." 178 179 # Access to address-relative data. (LoadAttrIndexContext not defined.) 180 181 class LoadAttr(AR): "Load into the current value the given attribute of the object referenced by the current value." 182 class StoreAttr(AR): "Store the source value into the given attribute of the object referenced by the current value." 183 class LoadAttrIndex(Immediate): "Load into the current value the attribute of the current value with the given index." 184 class StoreAttrIndex(Immediate): "Store the source value into the attribute of the current value with the given index." 185 class LoadAttrIndexContextCond(Immediate): 186 """Load into the current value the attribute of the current value with the given index, only making the 187 current value the context if the attribute is compatible.""" 188 189 # Access to object details. 190 191 class LoadCallable(Instruction): "Load the target of an invocation." 192 class StoreCallable(Instruction): "Store the source value into the object referenced by the current value." 193 194 # Access to invocation frames in preparation. 195 196 class MakeFrame(Immediate): "Make a new invocation frame." 197 class AdjustFrame(Immediate): "Adjust the current invocation frame for corrected invocations." 198 class DropFrame(Instruction): "Drop an invocation frame." 199 class StoreFrame(Immediate): "Store the current value as an argument for the parameter with the given position." 200 class StoreFrameIndex(Immediate): "Store the source value as an argument of the current value for the parameter with the given index." 201 class LoadContext(Instruction): "Load the context of an invocation." 202 203 # Context-related tests. 204 205 class CheckContext(Instruction): "Check to see if the context is valid." 206 class CheckClass(Instruction): "Check the current value to determine whether it is a class." 207 class CheckSelf(Instruction): "Check the first argument of an invocation against the target." 208 209 # Access to frames upon invocation. 210 211 class CheckFrame(Immediate): "Check the frame for the correct number of arguments." 212 class FillDefaults(Immediate): "Fill frame positions with defaults, if appropriate." 213 class ExtendFrame(Immediate): "Extend the current frame for temporary storage use." 214 215 # Invocation-related instructions, using a special result "register". 216 217 class JumpInFrame(Instruction): "Jump, using the current locals, to the current callable." 218 class JumpWithFrame(Instruction): "Jump, adopting the invocation frame, to the current callable." 219 class JumpWithFrameDirect(Target): "Jump to the specified address, adopting the invocation frame." 220 class Return(Instruction): "Return from a subprogram." 221 class LoadResult(Instruction): "Load into the current value a returned value." 222 class StoreResult(Instruction): "Store the current value as a value to be returned." 223 224 # Branch-related instructions. 225 226 class Jump(Address): "Jump unconditionally." 227 class JumpIfFalse(Address): "Jump if the last evaluation gave a false result." 228 class JumpIfTrue(Address): "Jump if the last evaluation gave a true result." 229 230 # Exception-related instructions, using a special exception "register". 231 232 class LoadException(Instruction): "Load the raised exception." 233 class StoreException(Instruction): "Store the current object in the exception register." 234 class ClearException(Instruction): "Reset the exception register." 235 class RaiseException(Instruction): "Raise an exception, jumping to the active handler." 236 class PushHandler(Address): "Push an exception handler onto the handler stack." 237 class PopHandler(Instruction): "Pop an exception handler from the handler stack." 238 class CheckException(Instruction): "Check the raised exception against another." 239 240 # Test instructions, operating on the boolean status register. 241 242 class TestIdentity(Instruction): "Test whether the current value is identical to the source value, setting the boolean status." 243 class TestIdentityAddress(Address): "Test whether the current value is identical to the given address, setting the boolean status." 244 class InvertBoolean(Instruction): "Invert the boolean status." 245 246 # Instructions which affect the current value. (LoadAttrIndexContext not defined.) 247 248 current_value_instructions = ( 249 LoadConst, LoadClass, LoadFunction, LoadName, LoadTemp, 250 LoadAddress, LoadAddressContext, LoadAddressContextCond, 251 LoadAttr, LoadAttrIndex, LoadAttrIndexContextCond, 252 LoadCallable, LoadContext, LoadResult, 253 LoadException, MakeInstance 254 ) 255 256 # vim: tabstop=4 expandtab shiftwidth=4