1# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com 2# 3# Part of "Nuitka", an optimizing Python compiler that is compatible and 4# integrates with CPython, but also works on its own. 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18""" Reformulation of subscript into slicing. 19 20For Python2, there is a difference between x[a], x[a:b], x[a:b:c] whereas 21Python3 treats the later by making a slice object, Python2 tries to have 22special slice access, if available, or building a slice object only at the 23end. 24 25Consult the developer manual for information. TODO: Add ability to sync 26source code comments with developer manual sections. 27""" 28 29from nuitka.nodes.ConstantRefNodes import ExpressionConstantEllipsisRef 30from nuitka.nodes.SliceNodes import ( 31 ExpressionSliceLookup, 32 makeExpressionBuiltinSlice, 33) 34from nuitka.nodes.SubscriptNodes import ExpressionSubscriptLookup 35from nuitka.PythonVersions import python_version 36 37from .ReformulationAssignmentStatements import buildExtSliceNode 38from .TreeHelpers import buildNode, getKind 39 40 41def buildSubscriptNode(provider, node, source_ref): 42 # Subscript expression nodes, various types are dispatched here. 43 44 assert getKind(node.ctx) == "Load", source_ref 45 46 # The subscript "[]" operator is one of many different things. This is 47 # expressed by this kind, there are "slice" lookups (two values, even if one 48 # is using default), and then "index" lookups. The form with three argument 49 # is really an "index" lookup, with a slice object. And the "..." lookup is 50 # also an index loop-up, with it as the argument. So this splits things into 51 # two different operations, "subscript" with a single "subscript" object. Or 52 # a slice lookup with a lower and higher boundary. These things should 53 # behave similar, but they are different slots. 54 kind = getKind(node.slice) 55 56 if kind == "Index": 57 return ExpressionSubscriptLookup( 58 expression=buildNode(provider, node.value, source_ref), 59 subscript=buildNode(provider, node.slice.value, source_ref), 60 source_ref=source_ref, 61 ) 62 elif kind == "Slice": 63 lower = buildNode( 64 provider=provider, 65 node=node.slice.lower, 66 source_ref=source_ref, 67 allow_none=True, 68 ) 69 upper = buildNode( 70 provider=provider, 71 node=node.slice.upper, 72 source_ref=source_ref, 73 allow_none=True, 74 ) 75 step = buildNode( 76 provider=provider, 77 node=node.slice.step, 78 source_ref=source_ref, 79 allow_none=True, 80 ) 81 82 # For Python3 there is no slicing operation, this is always done 83 # with subscript using a slice object. For Python2, it is only done 84 # if no "step" is provided. 85 use_sliceobj = step is not None or python_version >= 0x300 86 87 if use_sliceobj: 88 return ExpressionSubscriptLookup( 89 expression=buildNode(provider, node.value, source_ref), 90 subscript=makeExpressionBuiltinSlice( 91 start=lower, stop=upper, step=step, source_ref=source_ref 92 ), 93 source_ref=source_ref, 94 ) 95 else: 96 return ExpressionSliceLookup( 97 expression=buildNode(provider, node.value, source_ref), 98 lower=lower, 99 upper=upper, 100 source_ref=source_ref, 101 ) 102 elif kind == "ExtSlice": 103 return ExpressionSubscriptLookup( 104 expression=buildNode(provider, node.value, source_ref), 105 subscript=buildExtSliceNode(provider, node, source_ref), 106 source_ref=source_ref, 107 ) 108 elif kind == "Ellipsis": 109 return ExpressionSubscriptLookup( 110 expression=buildNode(provider, node.value, source_ref), 111 subscript=ExpressionConstantEllipsisRef(source_ref=source_ref), 112 source_ref=source_ref, 113 ) 114 elif python_version >= 0x390: 115 return ExpressionSubscriptLookup( 116 expression=buildNode(provider, node.value, source_ref), 117 subscript=buildNode(provider, node.slice, source_ref), 118 source_ref=source_ref, 119 ) 120 else: 121 assert False, kind 122