1 #!/usr/bin/env python 2 3 """ 4 RSVP instruction classes. 5 6 Copyright (C) 2007, 2008 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.common import Label 23 from micropython.data import Attr, Class, Const, Function 24 25 def raw(code, objtable, paramtable): 26 new_code = [] 27 for item in code: 28 if isinstance(item, Attr): 29 new_code.append(( 30 item.context and item.context.location, 31 item.value and item.value.location # no useful context is provided 32 )) 33 elif isinstance(item, Class): 34 # NOTE: Need initialiser details! 35 new_code.append(( 36 objtable.as_list().get_code(item.full_name()), 37 objtable.get_index(item.full_name()), 38 item.get_instantiator().code_location, 39 ( 40 len(item.get_instantiator().positional_names), 41 len(item.get_instantiator().defaults) 42 ))) 43 elif isinstance(item, Const): 44 # NOTE: Need class details! 45 new_code.append(( 46 None, #objtable.as_list().get_code(item.full_name()), 47 None, #objtable.get_index(item.full_name()), 48 None, None 49 )) 50 elif isinstance(item, Function): 51 # NOTE: Need class and parameter details! Should arguably be types.FunctionType. 52 new_code.append(( 53 objtable.as_list().get_code("__builtins__.function"), 54 objtable.get_index("__builtins__.function"), 55 item.code_location, 56 ( 57 len(item.positional_names), 58 len(item.defaults) 59 ))) 60 else: 61 new_code.append(item) 62 return new_code 63 64 def name(attr): 65 if isinstance(attr, Attr): 66 return attr.name or "<unnamed>" 67 else: 68 return attr or "<unnamed>" 69 70 class Instruction: 71 72 "A generic instruction." 73 74 def __init__(self, attr=None): 75 self.attr = attr 76 self.input = None 77 self.source = None # for storage instructions 78 79 def copy(self): 80 return self.__class__(self.attr) 81 82 def __repr__(self): 83 if self.attr is not None: 84 return "%s(%r)%s" % (self.__class__.__name__, self.attr, self.show_input()) 85 else: 86 return "%s()%s" % (self.__class__.__name__, self.show_input()) 87 88 def show_input(self): 89 if self.input is not None: 90 if self.source is not None: 91 return " <- (%r, %r)" % (self.input, self.source) 92 else: 93 return " <- %r" % self.input 94 elif self.source is not None: 95 return " <-- %r" % self.source 96 else: 97 return "" 98 99 def get_operand(self): 100 return None 101 102 class FrameRelativeInstruction(Instruction): 103 104 "An instruction operating on the current frame." 105 106 def __repr__(self): 107 return "%s(%r)%s" % (self.__class__.__name__, self.get_operand(), self.show_input()) 108 109 def get_operand(self): 110 return self.attr.position 111 112 FR = FrameRelativeInstruction 113 114 class AddressRelativeInstruction(Instruction): 115 116 "An instruction accessing an object's attribute." 117 118 def __repr__(self): 119 position = self.get_operand() 120 if position is not None: 121 return "%s(%r)%s # %s" % (self.__class__.__name__, position, self.show_input(), name(self.attr)) 122 else: 123 return "%s(%r)%s" % (self.__class__.__name__, name(self.attr), self.show_input()) 124 125 def get_operand(self): 126 return self.attr.position 127 128 AR = AddressRelativeInstruction 129 130 class AddressInstruction(Instruction): 131 132 "An instruction loading an address directly." 133 134 def __repr__(self): 135 location, position, result = self.get_operands() 136 if location is not None: 137 return "%s(%r)%s # %r, %r (%s)" % ( 138 self.__class__.__name__, result, self.show_input(), location, position, name(self.attr)) 139 elif result is not None: 140 return "%s(%r)%s # %s" % ( 141 self.__class__.__name__, result, self.show_input(), name(self.attr)) 142 else: 143 return "%s(...)%s # %s" % ( 144 self.__class__.__name__, self.show_input(), name(self.attr)) 145 146 def get_operands(self): 147 if isinstance(self.attr, Attr): 148 position = self.attr.position 149 location = self.attr.parent.location 150 151 # NOTE: Unpositioned attributes are handled here. 152 153 if location is not None and position is not None: 154 result = location + position + 1 155 else: 156 location = self.attr.parent.name 157 position = self.attr.name 158 result = None 159 return location, position, result 160 elif isinstance(self.attr, Label): 161 return None, None, self.attr.location 162 else: 163 return None, None, self.attr.location 164 165 def get_operand(self): 166 return self.get_operands()[-1] 167 168 Address = AddressInstruction 169 170 class ImmediateInstruction(Instruction): 171 172 "An instruction employing a constant." 173 174 def __repr__(self): 175 return "%s(%r)%s" % (self.__class__.__name__, self.attr, self.show_input()) 176 177 def get_operand(self): 178 return self.attr 179 180 Immediate = ImmediateInstruction 181 182 # Access to stored constant data. 183 184 class LoadConst(Address): "Load the constant, class, function, module from the specified location." 185 186 # Access within an invocation frame. 187 188 class LoadName(FR): "Load the current value from the given local attribute/variable." 189 class StoreName(FR): "Store the source value into the given local attribute/variable." 190 class LoadTemp(Immediate): "Load the current value from the given temporary location." 191 class StoreTemp(Immediate): "Store the current value into the given temporary location." 192 193 # Access to static data. 194 195 class LoadAddress(Address): "Load the current value from the given fixed attribute address." 196 class StoreAddress(Address): "Store the source value into the given fixed attribute address." 197 class LoadAddressContext(Address): "Load the current value from the given fixed attribute address, making the current value the context." 198 class MakeObject(Immediate): "Make a new object. There isn't a complementary DropObject." 199 200 # Access to address-relative data. 201 202 class LoadAttr(AR): "Load into the current value the given attribute of the object referenced by the current value." 203 class StoreAttr(AR): "Store the source value into the given attribute of the object referenced by the current value." 204 class LoadAttrIndex(Immediate): "Load into the current value the attribute of the current value with the given index." 205 class StoreAttrIndex(Immediate): "Store an object in the attribute with the given index." 206 207 # Access to object details. 208 209 class LoadCallable(Instruction): "Load the target of an invocation." 210 class StoreCallable(Instruction): "Store the source value into the object referenced by the current value." 211 212 # Access to invocation frames in preparation. 213 214 class MakeFrame(Immediate): "Make a new invocation frame." 215 class DropFrame(Instruction): "Drop an invocation frame." 216 class RecoverFrame(Instruction): "Recover the current frame as an invocation frame." 217 class StoreFrame(Immediate): "Store the current value as an argument for the parameter with the given position." 218 class StoreFrameIndex(Immediate): "Store the current value as an argument for the parameter with the given index." 219 class LoadContext(Instruction): "Load the context of an invocation." 220 class CheckFrame(Immediate): "Check the invocation frame and context for the target." 221 class CheckSelf(Instruction): "Check the first argument of an invocation against the target." 222 223 # Invocation-related instructions, using a special result "register". 224 225 class JumpWithFrame(Instruction): "Jump, adopting the invocation frame, to the current callable." 226 class ExtendFrame(Immediate): "Extend the current frame for temporary storage use." 227 class AdjustFrame(Immediate): "Adjust the current frame for corrected invocations." 228 class Return(Instruction): "Return from a subprogram." 229 class LoadResult(Instruction): "Load into the current value a returned value." 230 class StoreResult(Instruction): "Store the current value as a value to be returned." 231 232 # Branch-related instructions. 233 234 class Jump(Address): "Jump unconditionally." 235 class JumpIfFalse(Address): "Jump if the last evaluation gave a false result." 236 class JumpIfTrue(Address): "Jump if the last evaluation gave a true result." 237 238 # Exception-related instructions, using a special exception "register". 239 240 class LoadException(Instruction): "Load the raised exception." 241 class StoreException(Instruction): "Store the current object in the exception register." 242 class RaiseException(Instruction): "Raise an exception, jumping to the active handler." 243 class PushHandler(Address): "Push an exception handler onto the handler stack." 244 class PopHandler(Instruction): "Pop an exception handler from the handler stack." 245 class CheckException(Instruction): "Check the raised exception against another." 246 247 # Test instructions, operating on the boolean status register. 248 249 class TestIdentity(Instruction): "Test whether the current value is identical to the source value, setting the boolean status." 250 class TestIdentityAddress(Address): "Test whether the current value is identical to the given address, setting the boolean status." 251 class InvertBoolean(Instruction): "Invert the boolean status." 252 253 # vim: tabstop=4 expandtab shiftwidth=4