Lichen

Changeset

869:ef74fed1f5c4
2019-01-24 Paul Boddie raw files shortlog changelog graph Merged the tuple-optimisations branch into the default branch.
common.py (file) compiler/ast.py (file)
     1.1 --- a/common.py	Thu Jan 24 19:12:29 2019 +0100
     1.2 +++ b/common.py	Thu Jan 24 19:16:30 2019 +0100
     1.3 @@ -461,8 +461,11 @@
     1.4  
     1.5          for i, node in enumerate(n.nodes):
     1.6              statements.append(
     1.7 -                compiler.ast.Assign([node], compiler.ast.Subscript(
     1.8 -                    compiler.ast.Name(temp), "OP_APPLY", [compiler.ast.Const(i, str(i))]))
     1.9 +                compiler.ast.Assign([node], compiler.ast.CallFunc(
    1.10 +                    compiler.ast.Getattr(compiler.ast.Name(temp),
    1.11 +                                         "__get_single_item_unchecked__",
    1.12 +                                         privileged=True),
    1.13 +                    [compiler.ast.Const(i, str(i))]))
    1.14                  )
    1.15  
    1.16          return self.process_structure_node(compiler.ast.Stmt(statements))
    1.17 @@ -1597,6 +1600,10 @@
    1.18  
    1.19  predefined_constants = "False", "None", "NotImplemented", "True"
    1.20  
    1.21 +privileged_attributes = [
    1.22 +    "__get_single_item_unchecked__",
    1.23 +    ]
    1.24 +
    1.25  unary_operator_functions = {
    1.26  
    1.27      # Unary operations.
     2.1 --- a/compiler/ast.py	Thu Jan 24 19:12:29 2019 +0100
     2.2 +++ b/compiler/ast.py	Thu Jan 24 19:16:30 2019 +0100
     2.3 @@ -868,11 +868,15 @@
     2.4          return "%s %s" % (self.expr, " ".join(map(str, self.quals)))
     2.5  
     2.6  class Getattr(Node):
     2.7 -    def __init__(self, expr, attrname, lineno=None):
     2.8 +    def __init__(self, expr, attrname, lineno=None, privileged=False):
     2.9          self.expr = expr
    2.10          self.attrname = attrname
    2.11          self.lineno = lineno
    2.12  
    2.13 +        # Support privileged internal accesses.
    2.14 +
    2.15 +        self.privileged = privileged
    2.16 +
    2.17      def getChildren(self):
    2.18          return self.expr, self.attrname
    2.19  
     3.1 --- a/inspector.py	Thu Jan 24 19:12:29 2019 +0100
     3.2 +++ b/inspector.py	Thu Jan 24 19:16:30 2019 +0100
     3.3 @@ -21,7 +21,8 @@
     3.4  """
     3.5  
     3.6  from branching import BranchTracker
     3.7 -from common import CommonModule, get_argnames, init_item, predefined_constants
     3.8 +from common import CommonModule, get_argnames, init_item, \
     3.9 +                   predefined_constants, privileged_attributes
    3.10  from modules import BasicModule, CacheWritingModule, InspectionNaming
    3.11  from errors import InspectError
    3.12  from referencing import Reference
    3.13 @@ -358,6 +359,16 @@
    3.14  
    3.15          "Process the given attribute access node 'n'."
    3.16  
    3.17 +        path = self.get_namespace_path()
    3.18 +
    3.19 +        # Test for access to special privileged attributes.
    3.20 +
    3.21 +        if isinstance(n, compiler.ast.Getattr) and \
    3.22 +           n.attrname in privileged_attributes and not n.privileged:
    3.23 +
    3.24 +            raise InspectError("Attribute %s is accessed by an unprivileged operation." %
    3.25 +                               n.attrname, path, n)
    3.26 +
    3.27          # Obtain any completed chain and return the reference to it.
    3.28  
    3.29          name_ref = self.process_attribute_chain(n)
    3.30 @@ -372,8 +383,6 @@
    3.31          # either being name-based and thus an access rooted on a name, or being
    3.32          # based on some other node and thus an anonymous access of some kind.
    3.33  
    3.34 -        path = self.get_namespace_path()
    3.35 -
    3.36          # Start with the the full attribute chain.
    3.37  
    3.38          remaining = self.attrs
     4.1 --- a/lib/__builtins__/list.py	Thu Jan 24 19:12:29 2019 +0100
     4.2 +++ b/lib/__builtins__/list.py	Thu Jan 24 19:16:30 2019 +0100
     4.3 @@ -3,7 +3,7 @@
     4.4  """
     4.5  List objects.
     4.6  
     4.7 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
     4.8 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
     4.9  
    4.10  This program is free software; you can redistribute it and/or modify it under
    4.11  the terms of the GNU General Public License as published by the Free Software
    4.12 @@ -20,11 +20,11 @@
    4.13  """
    4.14  
    4.15  from __builtins__.iteration.iterator import itemiterator
    4.16 -from __builtins__.sequence import sequence, _get_absolute_index
    4.17 +from __builtins__.sequence import unpackable, _get_absolute_index
    4.18  from native import list_append, list_concat, list_element, list_init, \
    4.19                     list_len, list_nonempty, list_setelement, list_setsize
    4.20  
    4.21 -class list(sequence):
    4.22 +class list(unpackable):
    4.23  
    4.24      "Implementation of list."
    4.25  
     5.1 --- a/lib/__builtins__/sequence.py	Thu Jan 24 19:12:29 2019 +0100
     5.2 +++ b/lib/__builtins__/sequence.py	Thu Jan 24 19:16:30 2019 +0100
     5.3 @@ -20,7 +20,7 @@
     5.4  """
     5.5  
     5.6  from __builtins__.int import maxint
     5.7 -from native import isinstance as _isinstance, is_int
     5.8 +from native import isinstance as _isinstance, is_int, list_element
     5.9  
    5.10  class itemaccess:
    5.11  
    5.12 @@ -255,6 +255,22 @@
    5.13  
    5.14      # __iter__(self)
    5.15  
    5.16 +class unpackable(sequence):
    5.17 +
    5.18 +    "Class for list and tuple unpacking."
    5.19 +
    5.20 +    def __get_single_item_unchecked__(self, index):
    5.21 +
    5.22 +        """
    5.23 +        This method is provided by a privileged attribute recorded in the common
    5.24 +        module in the toolchain. Normal programs should not be able to access
    5.25 +        it.
    5.26 +        """
    5.27 +
    5.28 +        # NOTE: This uses implementation-specific access.
    5.29 +
    5.30 +        return list_element(self.__data__, index)
    5.31 +
    5.32  def _get_absolute_index(index, length):
    5.33  
    5.34      """
     6.1 --- a/lib/__builtins__/tuple.py	Thu Jan 24 19:12:29 2019 +0100
     6.2 +++ b/lib/__builtins__/tuple.py	Thu Jan 24 19:16:30 2019 +0100
     6.3 @@ -20,12 +20,12 @@
     6.4  """
     6.5  
     6.6  from __builtins__.iteration.iterator import itemiterator
     6.7 -from __builtins__.sequence import hashable, sequence
     6.8 +from __builtins__.sequence import hashable, unpackable
     6.9  from native import tuple_init, \
    6.10                     list_element, list_len, list_setsize, list_setelement, \
    6.11                     isinstance as _isinstance
    6.12  
    6.13 -class tuple(sequence, hashable):
    6.14 +class tuple(unpackable, hashable):
    6.15  
    6.16      "Implementation of tuple."
    6.17  
    6.18 @@ -66,7 +66,7 @@
    6.19          'step'.
    6.20          """
    6.21  
    6.22 -        return tuple(get_using(sequence.__getslice__, self)(start, end, step))
    6.23 +        return tuple(get_using(unpackable.__getslice__, self)(start, end, step))
    6.24  
    6.25      def __len__(self):
    6.26  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tests/tuple_unpack_bad.py	Thu Jan 24 19:16:30 2019 +0100
     7.3 @@ -0,0 +1,9 @@
     7.4 +def good(t):
     7.5 +    a, b, c = t
     7.6 +
     7.7 +def bad(t):
     7.8 +    a = t.__get_single_item_unchecked__(0)
     7.9 +
    7.10 +t = 1, 2, 3
    7.11 +good(t)
    7.12 +bad(t)