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""" Operations on Containers.
19
20"""
21
22from .ExpressionBases import (
23    ExpressionChildHavingBase,
24    ExpressionChildrenHavingBase,
25)
26from .NodeBases import StatementChildrenHavingBase
27
28
29class StatementListOperationAppend(StatementChildrenHavingBase):
30    kind = "STATEMENT_LIST_OPERATION_APPEND"
31
32    named_children = ("list_arg", "value")
33
34    def __init__(self, list_arg, value, source_ref):
35        assert list_arg is not None
36        assert value is not None
37
38        StatementChildrenHavingBase.__init__(
39            self, values={"list_arg": list_arg, "value": value}, source_ref=source_ref
40        )
41
42    def computeStatement(self, trace_collection):
43        result, change_tags, change_desc = self.computeStatementSubExpressions(
44            trace_collection=trace_collection
45        )
46
47        if result is not self:
48            return result, change_tags, change_desc
49
50        # TODO: Until we have proper list tracing.
51        trace_collection.removeKnowledge(self.subnode_list_arg)
52
53        return self, None, None
54
55
56class ExpressionListOperationExtend(ExpressionChildrenHavingBase):
57    kind = "EXPRESSION_LIST_OPERATION_EXTEND"
58
59    named_children = ("list_arg", "value")
60
61    def __init__(self, list_arg, value, source_ref):
62        assert list_arg is not None
63        assert value is not None
64
65        ExpressionChildrenHavingBase.__init__(
66            self, values={"list_arg": list_arg, "value": value}, source_ref=source_ref
67        )
68
69    def computeExpression(self, trace_collection):
70        # TODO: Until we have proper list tracing.
71        trace_collection.removeKnowledge(self.subnode_list_arg)
72
73        return self, None, None
74
75
76class ExpressionListOperationExtendForUnpack(ExpressionListOperationExtend):
77    kind = "EXPRESSION_LIST_OPERATION_EXTEND_FOR_UNPACK"
78
79
80class ExpressionListOperationPop(ExpressionChildHavingBase):
81    kind = "EXPRESSION_LIST_OPERATION_POP"
82
83    named_child = "list_arg"
84
85    def __init__(self, list_arg, source_ref):
86        assert list_arg is not None
87
88        ExpressionChildHavingBase.__init__(self, value=list_arg, source_ref=source_ref)
89
90    def computeExpression(self, trace_collection):
91        if not self.subnode_list_arg.isKnownToBeIterableAtMin(1):
92            trace_collection.onExceptionRaiseExit(IndexError)
93
94        # TODO: Until we have proper list tracing.
95        trace_collection.removeKnowledge(self.subnode_list_arg)
96
97        return self, None, None
98
99
100class StatementSetOperationAdd(StatementChildrenHavingBase):
101    kind = "STATEMENT_SET_OPERATION_ADD"
102
103    named_children = ("set_arg", "value")
104
105    def __init__(self, set_arg, value, source_ref):
106        assert set_arg is not None
107        assert value is not None
108
109        StatementChildrenHavingBase.__init__(
110            self, values={"set_arg": set_arg, "value": value}, source_ref=source_ref
111        )
112
113    def computeStatement(self, trace_collection):
114        result, change_tags, change_desc = self.computeStatementSubExpressions(
115            trace_collection=trace_collection
116        )
117
118        if result is not self:
119            return result, change_tags, change_desc
120
121        trace_collection.removeKnowledge(self.subnode_set_arg)
122
123        return self, None, None
124
125
126class ExpressionSetOperationUpdate(ExpressionChildrenHavingBase):
127    kind = "EXPRESSION_SET_OPERATION_UPDATE"
128
129    named_children = ("set_arg", "value")
130
131    def __init__(self, set_arg, value, source_ref):
132        assert set_arg is not None
133        assert value is not None
134
135        ExpressionChildrenHavingBase.__init__(
136            self, values={"set_arg": set_arg, "value": value}, source_ref=source_ref
137        )
138
139    def computeExpression(self, trace_collection):
140        trace_collection.removeKnowledge(self.subnode_set_arg)
141
142        return self, None, None
143