micropython

Changeset

237:31c5526286ba
2009-06-03 Paul Boddie raw files shortlog changelog graph Introduced replaceable and placeholder contexts, replacing the null context (None) with ReplaceableContext and introducing PlaceholderContext for class value contexts via a new LoadClass instruction, thus permitting instantiators to be called with such contexts.
docs/concepts.txt (file) micropython/ast.py (file) micropython/data.py (file) micropython/opt.py (file) micropython/program.py (file) micropython/rsvp.py (file) micropython/trans.py (file) rsvp.py (file)
     1.1 --- a/docs/concepts.txt	Tue Jun 02 20:17:59 2009 +0200
     1.2 +++ b/docs/concepts.txt	Wed Jun 03 00:48:57 2009 +0200
     1.3 @@ -67,21 +67,47 @@
     1.4  
     1.5  See invocation.txt for details.
     1.6  
     1.7 +Context Value Types
     1.8 +-------------------
     1.9 +
    1.10 +The following types of context value exist:
    1.11 +
    1.12 +    Type            Usage                           Transformations
    1.13 +    ----            -----                           ---------------
    1.14 +
    1.15 +    Replaceable     With functions (not methods)    May be replaced with an
    1.16 +                                                    instance or a class when a
    1.17 +                                                    value is stored on an
    1.18 +                                                    instance or class
    1.19 +
    1.20 +    Placeholder     With classes                    May not be replaced
    1.21 +
    1.22 +    Instance        With instances (and constants)  May not be replaced
    1.23 +                    or functions as methods
    1.24 +
    1.25 +    Class           With functions as methods       May be replaced when a
    1.26 +                                                    value is loaded from a
    1.27 +                                                    class attribute via an
    1.28 +                                                    instance
    1.29 +
    1.30  Contexts in Acquired Values
    1.31  ---------------------------
    1.32  
    1.33 -There are three classes of instructions which provide values:
    1.34 +There are four classes of instructions which provide values:
    1.35  
    1.36      Instruction         Purpose                 Context Operations
    1.37      -----------         -------                 ------------------
    1.38  
    1.39 -1)  LoadConst           Load class, module,     Use loaded object with itself
    1.40 -                        constant                as context
    1.41 +1)  LoadConst           Load module, constant   Use loaded object with itself
    1.42 +                                                as context
    1.43  
    1.44 -2)  LoadFunction        Load function           Combine null context with
    1.45 -                                                loaded object
    1.46 +2)  LoadFunction        Load function           Combine replaceable context
    1.47 +                                                with loaded object
    1.48  
    1.49 -3)  LoadAddress*        Load attribute from     Preserve or override stored
    1.50 +3)  LoadClass           Load class              Combine placeholder context
    1.51 +                                                with loaded object
    1.52 +
    1.53 +4)  LoadAddress*        Load attribute from     Preserve or override stored
    1.54      LoadAttr*           class, module,          context (as described in
    1.55                          instance                assignment.txt)
    1.56  
    1.57 @@ -118,9 +144,9 @@
    1.58                                                  assignments to classes
    1.59  
    1.60  2)  StoreAddressContext Store attribute in a    Override context if appropriate;
    1.61 -                        known object            if the value has a null context,
    1.62 -                                                permit the target to take
    1.63 -                                                ownership of the value
    1.64 +                        known object            if the value has a replaceable
    1.65 +                                                context, permit the target to
    1.66 +                                                take ownership of the value
    1.67  
    1.68  See assignment.txt for details.
    1.69  
     2.1 --- a/micropython/ast.py	Tue Jun 02 20:17:59 2009 +0200
     2.2 +++ b/micropython/ast.py	Wed Jun 03 00:48:57 2009 +0200
     2.3 @@ -552,7 +552,7 @@
     2.4  
     2.5          # Store the name.
     2.6  
     2.7 -        self.new_op(LoadConst(node.unit))
     2.8 +        self.new_op(LoadClass(node.unit))
     2.9          self.record_value()
    2.10          self._visitName(node, self.name_store_instructions)
    2.11          self.set_source()
     3.1 --- a/micropython/data.py	Tue Jun 02 20:17:59 2009 +0200
     3.2 +++ b/micropython/data.py	Wed Jun 03 00:48:57 2009 +0200
     3.3 @@ -44,7 +44,7 @@
     3.4  where each such object is defined.
     3.5  """
     3.6  
     3.7 -from micropython.program import DataObject
     3.8 +from micropython.program import DataObject, ReplaceableContext, PlaceholderContext
     3.9  
    3.10  def shortrepr(obj):
    3.11      if obj is None:
    3.12 @@ -184,17 +184,34 @@
    3.13          attr = self.namespace[name]
    3.14  
    3.15          # Handle attribute assignment as well as assignment of basic objects.
    3.16 +        # Attempt to fix the context if not explicitly defined.
    3.17  
    3.18          if isinstance(attr_or_value, Attr):
    3.19 +            context_values = self.get_updated_context_values(attr_or_value.context_values)
    3.20 +        else:
    3.21 +            context_values = self.get_updated_context_values([self.get_context_and_value(attr_or_value)])
    3.22  
    3.23 -            # Attempt to fix the context if not explicitly defined.
    3.24 +        attr.update(context_values, single_assignment)
    3.25 +
    3.26 +    def get_context_and_value(self, value):
    3.27 +
    3.28 +        "Return a context, value tuple for the given 'value'."
    3.29 +
    3.30 +        # Functions have a replaceable context.
    3.31  
    3.32 -            context_values = self.get_updated_context_values(attr_or_value.context_values)
    3.33 +        if isinstance(value, Function):
    3.34 +            return (ReplaceableContext, value)
    3.35 +
    3.36 +        # Classes use placeholder contexts which cannot be replaced but which
    3.37 +        # do not communicate useful contextual information.
    3.38 +
    3.39 +        elif isinstance(value, Class):
    3.40 +            return (PlaceholderContext, value)
    3.41 +
    3.42 +        # Other values employ themselves as the context.
    3.43  
    3.44          else:
    3.45 -            context_values = self.get_updated_context_values([(None, attr_or_value)])
    3.46 -
    3.47 -        attr.update(context_values, single_assignment)
    3.48 +            return (value, value)
    3.49  
    3.50      def get_updated_context_values(self, context_values):
    3.51  
    3.52 @@ -293,10 +310,16 @@
    3.53          return [v for (c, v) in self.context_values]
    3.54  
    3.55      def get_context(self):
    3.56 -        return len(self.context_values) == 1 and self.get_contexts()[0] or None
    3.57 +        if len(self.context_values) == 1:
    3.58 +            return self.get_contexts()[0]
    3.59 +        else:
    3.60 +            return None
    3.61  
    3.62      def get_value(self):
    3.63 -        return len(self.context_values) == 1 and self.get_values()[0] or None
    3.64 +        if len(self.context_values) == 1:
    3.65 +            return self.get_values()[0]
    3.66 +        else:
    3.67 +            return None
    3.68  
    3.69      def update(self, context_values, single_assignment):
    3.70  
    3.71 @@ -623,7 +646,7 @@
    3.72  
    3.73              # Change the ownership of functions.
    3.74  
    3.75 -            if context is None and value is not None and isinstance(value, Function):
    3.76 +            if context is ReplaceableContext and value is not None and isinstance(value, Function):
    3.77                  results.add((self, value))
    3.78              else:
    3.79                  results.add((context, value))
    3.80 @@ -999,7 +1022,7 @@
    3.81  
    3.82      def store_default(self, value):
    3.83          attr = Attr(None, self, None)
    3.84 -        attr.update([(None, value)], 1)
    3.85 +        attr.update([self.get_context_and_value(value)], 1)
    3.86          self.default_attrs.append(attr)
    3.87  
    3.88      def make_global(self, name):
     4.1 --- a/micropython/opt.py	Tue Jun 02 20:17:59 2009 +0200
     4.2 +++ b/micropython/opt.py	Wed Jun 03 00:48:57 2009 +0200
     4.3 @@ -153,7 +153,7 @@
     4.4          "Return whether 'instruction' provides a constant input."
     4.5  
     4.6          return isinstance(instruction, LoadAddress) and instruction.attr.assignments == 1 or \
     4.7 -            isinstance(instruction, (LoadConst, LoadFunction))
     4.8 +            isinstance(instruction, (LoadConst, LoadClass, LoadFunction))
     4.9  
    4.10      def is_constant_target(self, instruction):
    4.11  
    4.12 @@ -173,7 +173,7 @@
    4.13          a load operation from a CPU register or special memory location.
    4.14          """
    4.15  
    4.16 -        return isinstance(instruction, (LoadConst, LoadFunction, LoadName, LoadTemp, LoadResult, LoadException, LoadAddress))
    4.17 +        return isinstance(instruction, (LoadConst, LoadClass, LoadFunction, LoadName, LoadTemp, LoadResult, LoadException, LoadAddress))
    4.18  
    4.19      def is_simple_input_user(self, instruction):
    4.20  
    4.21 @@ -275,7 +275,7 @@
    4.22          # LoadResult cannot be relied upon in general since the result register
    4.23          # could be updated since first being referenced.
    4.24  
    4.25 -        return isinstance(self.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst, LoadFunction)) or \
    4.26 +        return isinstance(self.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst, LoadClass, LoadFunction)) or \
    4.27              isinstance(self.active_value, LoadResult) and self.active_value is self.active or \
    4.28              isinstance(self.active_value, LoadException) and self.active_value is self.active
    4.29  
     5.1 --- a/micropython/program.py	Tue Jun 02 20:17:59 2009 +0200
     5.2 +++ b/micropython/program.py	Wed Jun 03 00:48:57 2009 +0200
     5.3 @@ -44,4 +44,32 @@
     5.4              (self.classcode, self.attrcode, self.codeaddr, self.funccode, self.size), self.name
     5.5              )
     5.6  
     5.7 +class Context:
     5.8 +
     5.9 +    """
    5.10 +    A representation of a context used in a program, providing the special
    5.11 +    context value types.
    5.12 +    """
    5.13 +
    5.14 +    def __init__(self, truth_value, repr):
    5.15 +        self.truth_value = truth_value
    5.16 +        self.repr = repr
    5.17 +
    5.18 +    def __repr__(self):
    5.19 +        return self.repr
    5.20 +
    5.21 +    def __nonzero__(self):
    5.22 +        return self.truth_value
    5.23 +
    5.24 +# A representation of a context that is replaced upon certain assignment
    5.25 +# operations.
    5.26 +
    5.27 +ReplaceableContext = Context(0, "Replace")
    5.28 +
    5.29 +# A representation of a context that is employed by classes so that
    5.30 +# instantiators have enough slots in the invocation frame, yet does not cause
    5.31 +# testing of the context or adjustment of the frame.
    5.32 +
    5.33 +PlaceholderContext = Context(0, "Placeholder")
    5.34 +
    5.35  # vim: tabstop=4 expandtab shiftwidth=4
     6.1 --- a/micropython/rsvp.py	Tue Jun 02 20:17:59 2009 +0200
     6.2 +++ b/micropython/rsvp.py	Wed Jun 03 00:48:57 2009 +0200
     6.3 @@ -154,7 +154,8 @@
     6.4  
     6.5  # Access to stored constant data.
     6.6  
     6.7 -class LoadConst(Address):           "Load the constant, class, module from the specified location."
     6.8 +class LoadConst(Address):           "Load the constant or module from the specified location."
     6.9 +class LoadClass(Address):           "Load the class from the specified location."
    6.10  class LoadFunction(Address):        "Load the function from the specified location."
    6.11  
    6.12  # Access within an invocation frame.
    6.13 @@ -245,7 +246,7 @@
    6.14  # Instructions which affect the current value. (LoadAttrIndexContext not defined.)
    6.15  
    6.16  current_value_instructions = (
    6.17 -    LoadConst, LoadFunction, LoadName, LoadTemp,
    6.18 +    LoadConst, LoadClass, LoadFunction, LoadName, LoadTemp,
    6.19      LoadAddress, LoadAddressContext, LoadAddressContextCond,
    6.20      LoadAttr, LoadAttrIndex, LoadAttrIndexContextCond,
    6.21      LoadCallable, LoadContext, LoadResult,
     7.1 --- a/micropython/trans.py	Tue Jun 02 20:17:59 2009 +0200
     7.2 +++ b/micropython/trans.py	Wed Jun 03 00:48:57 2009 +0200
     7.3 @@ -826,19 +826,16 @@
     7.4  
     7.5          if target is None:
     7.6  
     7.7 -            # Skip adjustment and tests if a class is being invoked.
     7.8 -
     7.9 -            self.new_op(temp_target)
    7.10 -            self.new_op(CheckClass())
    7.11 -            self.new_op(JumpIfTrue(continue_block))
    7.12 -
    7.13 -            # Adjust the frame is no usable context is provided.
    7.14 +            # Adjust the frame if a replaceable context is provided.
    7.15  
    7.16              self.new_op(temp_context)
    7.17              self.new_op(CheckContext())
    7.18              self.new_op(JumpIfFalse(adjust_block))
    7.19  
    7.20              # Skip adjustment and tests if the context is not a class.
    7.21 +            # Classes themselves employ a placeholder context so that
    7.22 +            # instantiators can be callable with a context which will be
    7.23 +            # overwritten in the frame.
    7.24  
    7.25              self.new_op(temp_context)
    7.26              self.new_op(CheckClass())
     8.1 --- a/rsvp.py	Tue Jun 02 20:17:59 2009 +0200
     8.2 +++ b/rsvp.py	Wed Jun 03 00:48:57 2009 +0200
     8.3 @@ -52,6 +52,7 @@
     8.4                 current callable
     8.5  """
     8.6  
     8.7 +from micropython.program import ReplaceableContext, PlaceholderContext
     8.8  import operator
     8.9  
    8.10  class IllegalInstruction(Exception):
    8.11 @@ -386,8 +387,11 @@
    8.12      def LoadConst(self):
    8.13          self.value = self.operand, self.operand
    8.14  
    8.15 +    def LoadClass(self):
    8.16 +        self.value = PlaceholderContext, self.operand
    8.17 +
    8.18      def LoadFunction(self):
    8.19 -        self.value = None, self.operand
    8.20 +        self.value = ReplaceableContext, self.operand
    8.21  
    8.22      def LoadName(self):
    8.23          frame = self.local_sp_stack[-1]
    8.24 @@ -425,7 +429,7 @@
    8.25          # Overwrite context if null.
    8.26          context_context, context_ref = self.value
    8.27          source_context, source_ref = self.source
    8.28 -        if source_context is None:
    8.29 +        if source_context is ReplaceableContext:
    8.30              context = context_ref
    8.31          else:
    8.32              context = source_context
    8.33 @@ -546,10 +550,14 @@
    8.34          self.value = context, context
    8.35  
    8.36      def CheckContext(self):
    8.37 -        self.status = self.value[1] is not None
    8.38 +        self.status = self.value[1] is not ReplaceableContext
    8.39  
    8.40      def CheckClass(self):
    8.41          context, ref = self.value
    8.42 +        if ref in (ReplaceableContext, PlaceholderContext):
    8.43 +            self.status = 0
    8.44 +            return
    8.45 +
    8.46          data = self.load(ref)
    8.47  
    8.48          # Classes are not themselves usable as the self argument.
    8.49 @@ -721,7 +729,7 @@
    8.50      def _LoadAddressContextCond(self, context, ref, inst_ref):
    8.51          # Check the instance context against the target's context.
    8.52          # This provides the context overriding for methods.
    8.53 -        if context is not None and self._CheckInstance(inst_ref, context):
    8.54 +        if context is not ReplaceableContext and self._CheckInstance(inst_ref, context):
    8.55              # Replace the context with the instance.
    8.56              return inst_ref, ref
    8.57          else: