micropython

Changeset

563:ca338d9f49bb
2012-06-30 Paul Boddie raw files shortlog changelog graph Added imported name storage (necessary where such names are not constant). Made a convenience method for storing working values as local names. Removed instance-related code where guards test for module types. Changed the _generateName method to perform scope discovery internally.
micropython/ast.py (file) micropython/inspect.py (file) micropython/trans.py (file)
     1.1 --- a/micropython/ast.py	Sat Jun 30 17:06:37 2012 +0200
     1.2 +++ b/micropython/ast.py	Sat Jun 30 21:10:56 2012 +0200
     1.3 @@ -106,8 +106,6 @@
     1.4          if self.module.name == "__main__":
     1.5              self.set_block(handler_block)
     1.6              self.new_op(PopHandler(1))
     1.7 -        else:
     1.8 -            self.new_op(DropFrame())
     1.9  
    1.10          # All modules return if invoked.
    1.11  
    1.12 @@ -604,11 +602,7 @@
    1.13          # Store the name.
    1.14  
    1.15          self.new_op(LoadClass(node.unit))
    1.16 -        self.record_value()
    1.17 -        self.start_target()
    1.18 -        self._visitName(node, self.name_store_instructions)
    1.19 -        self.assign_value()
    1.20 -        self.discard_value()
    1.21 +        self._storeName(node)
    1.22  
    1.23          # Visit the code.
    1.24  
    1.25 @@ -620,19 +614,19 @@
    1.26      def visitDecorators(self, node): raise TranslationNotImplementedError("Decorators")
    1.27  
    1.28      def visitFrom(self, node):
    1.29 +        self._visitImport(node)
    1.30  
    1.31 -        """
    1.32 -        Although imported code already resides in any generated image, the
    1.33 -        code must be invoked.
    1.34 -        """
    1.35 +        # Store each imported name if its reference is not set as a constant
    1.36 +        # module global.
    1.37 +
    1.38 +        module = self.importer.get_module(node.modname)
    1.39  
    1.40 -        modules = self.importer.importers.get(node)
    1.41 -        if modules:
    1.42 -            for module in modules:
    1.43 -                self.new_op(MakeFrame(0))
    1.44 -                self.new_op(LoadConst(module))
    1.45 -                self.new_op(LoadCallable())
    1.46 -                self.new_op(JumpWithFrame())
    1.47 +        for name, alias in node.names:
    1.48 +            if name != "*":
    1.49 +                self._importName(module, name, alias, node)
    1.50 +            else:
    1.51 +                for attrname in module.module_attributes().keys():
    1.52 +                    self._importName(module, attrname, None, node)
    1.53  
    1.54      def visitFunction(self, node):
    1.55          if not used_by_unit(node):
    1.56 @@ -645,12 +639,7 @@
    1.57  
    1.58              # Record the declared function.
    1.59  
    1.60 -            self.record_value()
    1.61 -
    1.62 -            self.start_target()
    1.63 -            self._visitName(node, self.name_store_instructions) # AssName equivalent
    1.64 -            self.assign_value()
    1.65 -            self.discard_value()
    1.66 +            self._storeName(node)
    1.67  
    1.68          # Visiting of the code occurs when get_code is invoked on this node.
    1.69  
    1.70 @@ -659,7 +648,13 @@
    1.71  
    1.72      def visitGlobal(self, node): pass
    1.73  
    1.74 -    visitImport = visitFrom
    1.75 +    def visitImport(self, node):
    1.76 +        self._visitImport(node)
    1.77 +
    1.78 +        for name, alias in node.names:
    1.79 +            module = self.importer.get_module(name)
    1.80 +            self.new_op(LoadConst(module))
    1.81 +            self._storeName(node, alias or name)
    1.82  
    1.83      def visitKeyword(self, node): pass
    1.84  
     2.1 --- a/micropython/inspect.py	Sat Jun 30 17:06:37 2012 +0200
     2.2 +++ b/micropython/inspect.py	Sat Jun 30 21:10:56 2012 +0200
     2.3 @@ -999,6 +999,10 @@
     2.4          #    print >>sys.stderr, "Warning:", node.modname, "not imported."
     2.5  
     2.6          for name, alias in node.names:
     2.7 +
     2.8 +            # For specific names, obtain and store referenced objects using
     2.9 +            # the name or any alias provided in the current namespace.
    2.10 +
    2.11              if name != "*":
    2.12                  if module:
    2.13  
    2.14 @@ -1027,6 +1031,9 @@
    2.15  
    2.16                  self.store(alias or name, UnresolvedName(name, node.modname, self))
    2.17  
    2.18 +            # For wildcards, obtain and store all objects from a module in the
    2.19 +            # current namespace.
    2.20 +
    2.21              else:
    2.22                  if module:
    2.23                      for n in module.keys():
     3.1 --- a/micropython/trans.py	Sat Jun 30 17:06:37 2012 +0200
     3.2 +++ b/micropython/trans.py	Sat Jun 30 21:10:56 2012 +0200
     3.3 @@ -91,14 +91,16 @@
     3.4                  # Where instance attributes are involved, only instances are
     3.5                  # acceptable.
     3.6  
     3.7 -                # Generate isinstance(name, target).
     3.8 +                if not isinstance(obj, Module):
     3.9 +
    3.10 +                    # Generate isinstance(name, target).
    3.11  
    3.12 -                self.dispatch(compiler.ast.Name(name))
    3.13 -                self.new_op(CheckInstance(source="source", target="status"))
    3.14 +                    self.dispatch(compiler.ast.Name(name))
    3.15 +                    self.new_op(CheckInstance(source="source", target="status"))
    3.16  
    3.17 -                # Jump to the next guard or the code if successful.
    3.18 +                    # Jump to the next guard or the code if successful.
    3.19  
    3.20 -                self.new_op(JumpIfTrue(after_test_block, working="status"))
    3.21 +                    self.new_op(JumpIfTrue(after_test_block, working="status"))
    3.22  
    3.23                  # Where the type is inappropriate, raise an exception.
    3.24  
    3.25 @@ -946,6 +948,19 @@
    3.26          else:
    3.27              return None
    3.28  
    3.29 +    def _storeName(self, node, name=None):
    3.30 +
    3.31 +        """
    3.32 +        A convenience method that stores the current working value using the
    3.33 +        name provided by the given 'node' or the specified 'name' if provided.
    3.34 +        """
    3.35 +
    3.36 +        self.record_value()
    3.37 +        self.start_target()
    3.38 +        self._generateName(name or node.name, self.name_store_instructions, node)
    3.39 +        self.assign_value()
    3.40 +        self.discard_value()
    3.41 +
    3.42      def _visitName(self, node, classes):
    3.43  
    3.44          """
    3.45 @@ -954,13 +969,9 @@
    3.46          """
    3.47  
    3.48          name = node.name
    3.49 -
    3.50 -        # Get the expected scope of the name.
    3.51 +        self._generateName(name, classes, node)
    3.52  
    3.53 -        scope = getattr(node, "_scope", None) or self.get_scope(name)
    3.54 -        self._generateName(name, scope, classes, node)
    3.55 -
    3.56 -    def _generateName(self, name, scope, classes, node):
    3.57 +    def _generateName(self, name, classes, node):
    3.58  
    3.59          """
    3.60          Generate code for the access to 'name' in 'scope' using the given
    3.61 @@ -969,6 +980,10 @@
    3.62  
    3.63          NameInstruction, AddressInstruction, AddressContextInstruction = classes
    3.64  
    3.65 +        # Get the expected scope of the name.
    3.66 +
    3.67 +        scope = getattr(node, "_scope", None) or self.get_scope(name)
    3.68 +
    3.69          # Handle names referring to constants.
    3.70  
    3.71          if scope == "constant":
    3.72 @@ -1387,4 +1402,37 @@
    3.73          self._doCallFunc(temp_target, target)
    3.74          self._endCallFunc(temp_target, temp_context)
    3.75  
    3.76 +    def _visitImport(self, node):
    3.77 +
    3.78 +        """
    3.79 +        Although imported code already resides in any generated image, the
    3.80 +        module code must be executed. Module code uses its own frame for any
    3.81 +        temporary storage and thus behaves like a function.
    3.82 +        """
    3.83 +
    3.84 +        modules = self.importer.importers.get(node)
    3.85 +        if modules:
    3.86 +            for module in modules:
    3.87 +                self.new_op(MakeFrame(0))
    3.88 +                self.new_op(LoadConst(module))
    3.89 +                self.new_op(LoadCallable())
    3.90 +                self.new_op(JumpWithFrame())
    3.91 +                self.new_op(DropFrame())
    3.92 +
    3.93 +    def _importName(self, module, name, alias, node):
    3.94 +
    3.95 +        # Get the source of the name.
    3.96 +
    3.97 +        attr = module[name]
    3.98 +        self.new_op(LoadAddress(attr))
    3.99 +
   3.100 +        # Record the object in the current namespace.
   3.101 +
   3.102 +        self.record_value()
   3.103 +
   3.104 +        self.start_target()
   3.105 +        self._generateName(alias or name, self.name_store_instructions, node) # AssName equivalent
   3.106 +        self.assign_value()
   3.107 +        self.discard_value()
   3.108 +
   3.109  # vim: tabstop=4 expandtab shiftwidth=4