micropython

micropython/rsvp.py

137:f660fe1aac5c
2008-09-01 Paul Boddie Added notes about calling initialisers and instantiators, adopting a strategy where instantiation detected at compile-time is performed using an initialiser directly, whereas that detected at run-time is done using an instantiator whose code is now generated in the image. Added a finalise method to the Importer in order to set attribute locations before code generation, since some code (use of initialisers) requires details of a different program unit's locals (although this is actually unnecessary, but done because Attr instances are employed in the generated code). Changed class invocation at compile-time to acquire the new object reference from the frame of an already invoked initialiser just before dropping the frame. Added some support for raw image encoding of classes and functions. Changed JumpWithFrame usage to involve the current callable, not the current value. Added RecoverFrame and AdjustFrame instructions. Improved the tests around instantiation.
     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                     len(item.get_instantiator().positional_names)    40                 ))    41         elif isinstance(item, Const):    42             # NOTE: Need class details!    43             new_code.append((    44                 None, #objtable.as_list().get_code(item.full_name()),    45                 None, #objtable.get_index(item.full_name()),    46                 None, None    47                 ))    48         elif isinstance(item, Function):    49             # NOTE: Need class and parameter details! Should arguably be types.FunctionType.    50             new_code.append((    51                 objtable.as_list().get_code("__builtins__.function"),    52                 objtable.get_index("__builtins__.function"),    53                 item.code_location,    54                 len(item.positional_names)    55                 ))    56         else:    57             new_code.append(item)    58     return new_code    59     60 def name(attr):    61     if isinstance(attr, Attr):    62         return attr.name or "<unnamed>"    63     else:    64         return attr or "<unnamed>"    65     66 class Instruction:    67     68     "A generic instruction."    69     70     def __init__(self, attr=None):    71         self.attr = attr    72         self.input = None    73         self.source = None # for storage instructions    74     75     def copy(self):    76         return self.__class__(self.attr)    77     78     def __repr__(self):    79         if self.attr is not None:    80             return "%s(%r)%s" % (self.__class__.__name__, self.attr, self.show_input())    81         else:    82             return "%s()%s" % (self.__class__.__name__, self.show_input())    83     84     def show_input(self):    85         if self.input is not None:    86             if self.source is not None:    87                 return " <- (%r, %r)" % (self.input, self.source)    88             else:    89                 return " <- %r" % self.input    90         elif self.source is not None:    91             return " <-- %r" % self.source    92         else:    93             return ""    94     95     def get_operand(self):    96         return None    97     98 class FrameRelativeInstruction(Instruction):    99    100     "An instruction operating on the current frame."   101    102     def __repr__(self):   103         return "%s(%r)%s" % (self.__class__.__name__, self.get_operand(), self.show_input())   104    105     def get_operand(self):   106         return self.attr.position   107    108 FR = FrameRelativeInstruction   109    110 class AddressRelativeInstruction(Instruction):   111    112     "An instruction accessing an object's attribute."   113    114     def __repr__(self):   115         position = self.get_operand()   116         if position is not None:   117             return "%s(%r)%s # %s" % (self.__class__.__name__, position, self.show_input(), name(self.attr))   118         else:   119             return "%s(%r)%s" % (self.__class__.__name__, name(self.attr), self.show_input())   120    121     def get_operand(self):   122         return self.attr.position   123    124 AR = AddressRelativeInstruction   125    126 class AddressInstruction(Instruction):   127    128     "An instruction loading an address directly."   129    130     def __repr__(self):   131         location, position, result = self.get_operands()   132         if location is not None:   133             return "%s(%r)%s # %r, %r (%s)" % (   134                 self.__class__.__name__, result, self.show_input(), location, position, name(self.attr))   135         elif result is not None:   136             return "%s(%r)%s # %s" % (   137                 self.__class__.__name__, result, self.show_input(), name(self.attr))   138         else:   139             return "%s(...)%s # %s" % (   140                 self.__class__.__name__, self.show_input(), name(self.attr))   141    142     def get_operands(self):   143         if isinstance(self.attr, Attr):   144             position = self.attr.position   145             location = self.attr.parent.location   146    147             # NOTE: Unpositioned attributes are handled here.   148    149             if location is not None and position is not None:   150                 result = location + position + 1   151             else:   152                 location = self.attr.parent.name   153                 position = self.attr.name   154                 result = None   155             return location, position, result   156         elif isinstance(self.attr, Label):   157             return None, None, self.attr.location   158         else:   159             return None, None, self.attr.location   160    161     def get_operand(self):   162         return self.get_operands()[-1]   163    164 Address = AddressInstruction   165    166 class ImmediateInstruction(Instruction):   167    168     "An instruction employing a constant."   169    170     def __repr__(self):   171         return "%s(%r)%s" % (self.__class__.__name__, self.attr, self.show_input())   172    173     def get_operand(self):   174         return self.attr   175    176 Immediate = ImmediateInstruction   177    178 # Access to stored constant data.   179    180 class LoadConst(Address):           "Load the constant, class, function, module from the specified location."   181    182 # Access within an invocation frame.   183    184 class LoadName(FR):                 "Load the current value from the given local attribute/variable."   185 class StoreName(FR):                "Store the source value into the given local attribute/variable."   186 class LoadTemp(Immediate):          "Load the current value from the given temporary location."   187 class StoreTemp(Immediate):         "Store the current value into the given temporary location."   188    189 # Access to static data.   190    191 class LoadAddress(Address):         "Load the current value from the given fixed attribute address."   192 class StoreAddress(Address):        "Store the source value into the given fixed attribute address."   193 class LoadAddressContext(Address):  "Load the current value from the given fixed attribute address, making the current value the context."   194 class MakeObject(Immediate):        "Make a new object. There isn't a complementary DropObject."   195    196 # Access to address-relative data.   197    198 class LoadAttr(AR):                 "Load into the current value the given attribute of the object referenced by the current value."   199 class StoreAttr(AR):                "Store the source value into the given attribute of the object referenced by the current value."   200 class LoadAttrIndex(Immediate):     "Load into the current value the attribute of the current value with the given index."   201 class StoreAttrIndex(Immediate):    "Store an object in the attribute with the given index."   202    203 # Access to invocation frames in preparation.   204    205 class MakeFrame(Immediate):         "Make a new invocation frame."   206 class DropFrame(Instruction):       "Drop an invocation frame."   207 class RecoverFrame(Instruction):    "Recover the current frame as an invocation frame."   208 class StoreFrame(Immediate):        "Store the current value as an argument for the parameter with the given position."   209 class StoreFrameIndex(Immediate):   "Store the current value as an argument for the parameter with the given index."   210 class LoadCallable(Instruction):    "Load the target of an invocation."   211 class StoreCallable(Instruction):   "Store the source value into the object referenced by the current value."   212 class LoadContext(Instruction):     "Load the context of an invocation."   213 class CheckFrame(Immediate):        "Check the invocation frame and context for the target."   214 class CheckSelf(Instruction):       "Check the first argument of an invocation against the target."   215    216 # Invocation-related instructions, using a special result "register".   217    218 class JumpWithFrame(Instruction):   "Jump, adopting the invocation frame, to the current callable."   219 class ExtendFrame(Immediate):       "Extend the current frame for temporary storage use."   220 class AdjustFrame(Immediate):       "Adjust the current frame for corrected invocations."   221 class Return(Instruction):          "Return from a subprogram."   222 class LoadResult(Instruction):      "Load into the current value a returned value."   223 class StoreResult(Instruction):     "Store the current value as a value to be returned."   224    225 # Branch-related instructions.   226    227 class Jump(Address):                "Jump unconditionally."   228 class JumpIfFalse(Address):         "Jump if the last evaluation gave a false result."   229 class JumpIfTrue(Address):          "Jump if the last evaluation gave a true result."   230    231 # Exception-related instructions, using a special exception "register".   232    233 class LoadException(Instruction):   "Load the raised exception."   234 class StoreException(Instruction):  "Store the current object in 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 # vim: tabstop=4 expandtab shiftwidth=4