We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add support for abi.decode on arrays
Ex:
```solidity
contract C{
        function f(bytes memory b) public{
                uint[2] memory m = abi.decode(b, (uint[2]));
        }
}
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `slither/visitors/slithir/expression_to_slithir.py`
Content:
```
1 import logging
2 
3 from slither.core.declarations import Function
4 from slither.core.expressions import (AssignmentOperationType,
5                                       UnaryOperationType)
6 from slither.slithir.operations import (Assignment, Binary, BinaryType, Delete,
7                                         Index, InitArray, InternalCall, Member,
8                                         NewArray, NewContract,
9                                         TypeConversion, Unary, Unpack, Return)
10 from slither.slithir.tmp_operations.argument import Argument
11 from slither.slithir.tmp_operations.tmp_call import TmpCall
12 from slither.slithir.tmp_operations.tmp_new_array import TmpNewArray
13 from slither.slithir.tmp_operations.tmp_new_contract import TmpNewContract
14 from slither.slithir.tmp_operations.tmp_new_elementary_type import \
15     TmpNewElementaryType
16 from slither.slithir.variables import (Constant, ReferenceVariable,
17                                        TemporaryVariable, TupleVariable)
18 from slither.visitors.expression.expression import ExpressionVisitor
19 
20 from slither.slithir.exceptions import SlithIRError
21 
22 logger = logging.getLogger("VISTIOR:ExpressionToSlithIR")
23 
24 key = 'expressionToSlithIR'
25 
26 def get(expression):
27     val = expression.context[key]
28     # we delete the item to reduce memory use
29     del expression.context[key]
30     return val
31 
32 def set_val(expression, val):
33     expression.context[key] = val
34 
35 def convert_assignment(left, right, t, return_type):
36     if t == AssignmentOperationType.ASSIGN:
37         return Assignment(left, right, return_type)
38     elif t == AssignmentOperationType.ASSIGN_OR:
39         return Binary(left, left, right, BinaryType.OR)
40     elif t == AssignmentOperationType.ASSIGN_CARET:
41         return Binary(left, left, right, BinaryType.CARET)
42     elif t == AssignmentOperationType.ASSIGN_AND:
43         return Binary(left, left, right, BinaryType.AND)
44     elif t == AssignmentOperationType.ASSIGN_LEFT_SHIFT:
45         return Binary(left, left, right, BinaryType.LEFT_SHIFT)
46     elif t == AssignmentOperationType.ASSIGN_RIGHT_SHIFT:
47         return Binary(left, left, right, BinaryType.RIGHT_SHIFT)
48     elif t == AssignmentOperationType.ASSIGN_ADDITION:
49         return Binary(left, left, right, BinaryType.ADDITION)
50     elif t == AssignmentOperationType.ASSIGN_SUBTRACTION:
51         return Binary(left, left, right, BinaryType.SUBTRACTION)
52     elif t == AssignmentOperationType.ASSIGN_MULTIPLICATION:
53         return Binary(left, left, right, BinaryType.MULTIPLICATION)
54     elif t == AssignmentOperationType.ASSIGN_DIVISION:
55         return Binary(left, left, right, BinaryType.DIVISION)
56     elif t == AssignmentOperationType.ASSIGN_MODULO:
57         return Binary(left, left, right, BinaryType.MODULO)
58 
59     raise SlithIRError('Missing type during assignment conversion')
60 
61 class ExpressionToSlithIR(ExpressionVisitor):
62 
63     def __init__(self, expression, node):
64         from slither.core.cfg.node import NodeType
65         self._expression = expression
66         self._node = node
67         self._result = []
68         self._visit_expression(self.expression)
69         if node.type == NodeType.RETURN:
70             r = Return(get(self.expression))
71             r.set_expression(expression)
72             self._result.append(r)
73         for ir in self._result:
74             ir.set_node(node)
75 
76     def result(self):
77         return self._result
78 
79     def _post_assignement_operation(self, expression):
80         left = get(expression.expression_left)
81         right = get(expression.expression_right)
82         if isinstance(left, list): # tuple expression:
83             if isinstance(right, list): # unbox assigment
84                 assert len(left) == len(right)
85                 for idx in range(len(left)):
86                     if not left[idx] is None:
87                         operation = convert_assignment(left[idx], right[idx], expression.type, expression.expression_return_type)
88                         operation.set_expression(expression)
89                         self._result.append(operation)
90                 set_val(expression, None)
91             else:
92                 assert isinstance(right, TupleVariable)
93                 for idx in range(len(left)):
94                     if not left[idx] is None:
95                         operation = Unpack(left[idx], right, idx)
96                         operation.set_expression(expression)
97                         self._result.append(operation)
98                 set_val(expression, None)
99         else:
100             # Init of array, like
101             # uint8[2] var = [1,2];
102             if isinstance(right, list):
103                 operation = InitArray(right, left)
104                 operation.set_expression(expression)
105                 self._result.append(operation)
106                 set_val(expression, left)
107             else:
108                 operation = convert_assignment(left, right, expression.type, expression.expression_return_type)
109                 operation.set_expression(expression)
110                 self._result.append(operation)
111                 # Return left to handle
112                 # a = b = 1; 
113                 set_val(expression, left)
114 
115     def _post_binary_operation(self, expression):
116         left = get(expression.expression_left)
117         right = get(expression.expression_right)
118         val = TemporaryVariable(self._node)
119 
120         operation = Binary(val, left, right, expression.type)
121         operation.set_expression(expression)
122         self._result.append(operation)
123         set_val(expression, val)
124 
125     def _post_call_expression(self, expression):
126         called = get(expression.called)
127         args = [get(a) for a in expression.arguments if a]
128         for arg in args:
129             arg_ = Argument(arg)
130             arg_.set_expression(expression)
131             self._result.append(arg_)
132         if isinstance(called, Function):
133             # internal call
134 
135             # If tuple
136             if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':
137                 val = TupleVariable(self._node)
138             else:
139                 val = TemporaryVariable(self._node)
140             internal_call = InternalCall(called, len(args), val, expression.type_call)
141             internal_call.set_expression(expression)
142             self._result.append(internal_call)
143             set_val(expression, val)
144         else:
145             # If tuple
146             if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':
147                 val = TupleVariable(self._node)
148             else:
149                 val = TemporaryVariable(self._node)
150 
151             message_call = TmpCall(called, len(args), val, expression.type_call)
152             message_call.set_expression(expression)
153             # Gas/value are only accessible here if the syntax {gas: , value: }
154             # Is used over .gas().value()
155             if expression.call_gas:
156                 call_gas = get(expression.call_gas)
157                 message_call.call_gas = call_gas
158             if expression.call_value:
159                 call_value = get(expression.call_value)
160                 message_call.call_value = call_value
161             self._result.append(message_call)
162             set_val(expression, val)
163 
164     def _post_conditional_expression(self, expression):
165         raise Exception('Ternary operator are not convertible to SlithIR {}'.format(expression))
166 
167     def _post_elementary_type_name_expression(self, expression):
168         set_val(expression, expression.type)
169 
170     def _post_identifier(self, expression):
171         set_val(expression, expression.value)
172 
173     def _post_index_access(self, expression):
174         left = get(expression.expression_left)
175         right = get(expression.expression_right)
176         val = ReferenceVariable(self._node)
177         # access to anonymous array
178         # such as [0,1][x]
179         if isinstance(left, list):
180             init_array_val = TemporaryVariable(self._node)
181             init_array_right = left
182             left = init_array_val
183             operation = InitArray(init_array_right, init_array_val)
184             operation.set_expression(expression)
185             self._result.append(operation)
186         operation = Index(val, left, right, expression.type)
187         operation.set_expression(expression)
188         self._result.append(operation)
189         set_val(expression, val)
190 
191     def _post_literal(self, expression):
192         cst = Constant(expression.value, expression.type, expression.subdenomination)
193         set_val(expression, cst)
194 
195     def _post_member_access(self, expression):
196         expr = get(expression.expression)
197         val = ReferenceVariable(self._node)
198         member = Member(expr, Constant(expression.member_name), val)
199         member.set_expression(expression)
200         self._result.append(member)
201         set_val(expression, val)
202 
203     def _post_new_array(self, expression):
204         val = TemporaryVariable(self._node)
205         operation = TmpNewArray(expression.depth, expression.array_type, val)
206         operation.set_expression(expression)
207         self._result.append(operation)
208         set_val(expression, val)
209 
210     def _post_new_contract(self, expression):
211         val = TemporaryVariable(self._node)
212         operation = TmpNewContract(expression.contract_name, val)
213         operation.set_expression(expression)
214         self._result.append(operation)
215         set_val(expression, val)
216 
217     def _post_new_elementary_type(self, expression):
218         # TODO unclear if this is ever used?
219         val = TemporaryVariable(self._node)
220         operation = TmpNewElementaryType(expression.type, val)
221         operation.set_expression(expression)
222         self._result.append(operation)
223         set_val(expression, val)
224 
225     def _post_tuple_expression(self, expression):
226         expressions = [get(e) if e else None for e in expression.expressions]
227         if len(expressions) == 1:
228             val = expressions[0]
229         else:
230             val = expressions
231         set_val(expression, val)
232 
233     def _post_type_conversion(self, expression):
234         expr = get(expression.expression)
235         val = TemporaryVariable(self._node)
236         operation = TypeConversion(val, expr, expression.type)
237         operation.set_expression(expression)
238         self._result.append(operation)
239         set_val(expression, val)
240 
241     def _post_unary_operation(self, expression):
242         value = get(expression.expression)
243         if expression.type in [UnaryOperationType.BANG, UnaryOperationType.TILD]:
244             lvalue = TemporaryVariable(self._node)
245             operation = Unary(lvalue, value, expression.type)
246             operation.set_expression(expression)
247             self._result.append(operation)
248             set_val(expression, lvalue)
249         elif expression.type in [UnaryOperationType.DELETE]:
250             operation = Delete(value, value)
251             operation.set_expression(expression)
252             self._result.append(operation)
253             set_val(expression, value)
254         elif expression.type in [UnaryOperationType.PLUSPLUS_PRE]:
255             operation = Binary(value, value, Constant("1", value.type), BinaryType.ADDITION)
256             operation.set_expression(expression)
257             self._result.append(operation)
258             set_val(expression, value)
259         elif expression.type in [UnaryOperationType.MINUSMINUS_PRE]:
260             operation = Binary(value, value, Constant("1", value.type), BinaryType.SUBTRACTION)
261             operation.set_expression(expression)
262             self._result.append(operation)
263             set_val(expression, value)
264         elif expression.type in [UnaryOperationType.PLUSPLUS_POST]:
265             lvalue = TemporaryVariable(self._node)
266             operation = Assignment(lvalue, value, value.type)
267             operation.set_expression(expression)
268             self._result.append(operation)
269             operation = Binary(value, value, Constant("1", value.type), BinaryType.ADDITION)
270             operation.set_expression(expression)
271             self._result.append(operation)
272             set_val(expression, lvalue)
273         elif expression.type in [UnaryOperationType.MINUSMINUS_POST]:
274             lvalue = TemporaryVariable(self._node)
275             operation = Assignment(lvalue, value, value.type)
276             operation.set_expression(expression)
277             self._result.append(operation)
278             operation = Binary(value, value, Constant("1", value.type), BinaryType.SUBTRACTION)
279             operation.set_expression(expression)
280             self._result.append(operation)
281             set_val(expression, lvalue)
282         elif expression.type in [UnaryOperationType.PLUS_PRE]:
283             set_val(expression, value)
284         elif expression.type in [UnaryOperationType.MINUS_PRE]:
285             lvalue = TemporaryVariable(self._node)
286             operation = Binary(lvalue, Constant("0", value.type), value, BinaryType.SUBTRACTION)
287             operation.set_expression(expression)
288             self._result.append(operation)
289             set_val(expression, lvalue)
290         else:
291             raise SlithIRError('Unary operation to IR not supported {}'.format(expression))
292 
293
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py
--- a/slither/visitors/slithir/expression_to_slithir.py
+++ b/slither/visitors/slithir/expression_to_slithir.py
@@ -3,6 +3,8 @@
 from slither.core.declarations import Function
 from slither.core.expressions import (AssignmentOperationType,
                                       UnaryOperationType)
+from slither.core.solidity_types import ArrayType
+from slither.core.solidity_types.type import Type
 from slither.slithir.operations import (Assignment, Binary, BinaryType, Delete,
                                         Index, InitArray, InternalCall, Member,
                                         NewArray, NewContract,
@@ -173,6 +175,14 @@
     def _post_index_access(self, expression):
         left = get(expression.expression_left)
         right = get(expression.expression_right)
+        # Left can be a type for abi.decode(var, uint[2])
+        if isinstance(left, Type):
+            # Nested type are not yet supported by abi.decode, so the assumption
+            # Is that the right variable must be a constant
+            assert isinstance(right, Constant)
+            t = ArrayType(left, right.value)
+            set_val(expression, t)
+            return
         val = ReferenceVariable(self._node)
         # access to anonymous array
         # such as [0,1][x]

{"golden_diff": "diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py\n--- a/slither/visitors/slithir/expression_to_slithir.py\n+++ b/slither/visitors/slithir/expression_to_slithir.py\n@@ -3,6 +3,8 @@\n from slither.core.declarations import Function\n from slither.core.expressions import (AssignmentOperationType,\n                                       UnaryOperationType)\n+from slither.core.solidity_types import ArrayType\n+from slither.core.solidity_types.type import Type\n from slither.slithir.operations import (Assignment, Binary, BinaryType, Delete,\n                                         Index, InitArray, InternalCall, Member,\n                                         NewArray, NewContract,\n@@ -173,6 +175,14 @@\n     def _post_index_access(self, expression):\n         left = get(expression.expression_left)\n         right = get(expression.expression_right)\n+        # Left can be a type for abi.decode(var, uint[2])\n+        if isinstance(left, Type):\n+            # Nested type are not yet supported by abi.decode, so the assumption\n+            # Is that the right variable must be a constant\n+            assert isinstance(right, Constant)\n+            t = ArrayType(left, right.value)\n+            set_val(expression, t)\n+            return\n         val = ReferenceVariable(self._node)\n         # access to anonymous array\n         # such as [0,1][x]\n", "issue": "Add support for abi.decode on arrays\nEx:\r\n```solidity\r\ncontract C{\r\n        function f(bytes memory b) public{\r\n                uint[2] memory m = abi.decode(b, (uint[2]));\r\n        }\r\n}\r\n```\r\n\n", "before_files": [{"content": "import logging\n\nfrom slither.core.declarations import Function\nfrom slither.core.expressions import (AssignmentOperationType,\n                                      UnaryOperationType)\nfrom slither.slithir.operations import (Assignment, Binary, BinaryType, Delete,\n                                        Index, InitArray, InternalCall, Member,\n                                        NewArray, NewContract,\n                                        TypeConversion, Unary, Unpack, Return)\nfrom slither.slithir.tmp_operations.argument import Argument\nfrom slither.slithir.tmp_operations.tmp_call import TmpCall\nfrom slither.slithir.tmp_operations.tmp_new_array import TmpNewArray\nfrom slither.slithir.tmp_operations.tmp_new_contract import TmpNewContract\nfrom slither.slithir.tmp_operations.tmp_new_elementary_type import \\\n    TmpNewElementaryType\nfrom slither.slithir.variables import (Constant, ReferenceVariable,\n                                       TemporaryVariable, TupleVariable)\nfrom slither.visitors.expression.expression import ExpressionVisitor\n\nfrom slither.slithir.exceptions import SlithIRError\n\nlogger = logging.getLogger(\"VISTIOR:ExpressionToSlithIR\")\n\nkey = 'expressionToSlithIR'\n\ndef get(expression):\n    val = expression.context[key]\n    # we delete the item to reduce memory use\n    del expression.context[key]\n    return val\n\ndef set_val(expression, val):\n    expression.context[key] = val\n\ndef convert_assignment(left, right, t, return_type):\n    if t == AssignmentOperationType.ASSIGN:\n        return Assignment(left, right, return_type)\n    elif t == AssignmentOperationType.ASSIGN_OR:\n        return Binary(left, left, right, BinaryType.OR)\n    elif t == AssignmentOperationType.ASSIGN_CARET:\n        return Binary(left, left, right, BinaryType.CARET)\n    elif t == AssignmentOperationType.ASSIGN_AND:\n        return Binary(left, left, right, BinaryType.AND)\n    elif t == AssignmentOperationType.ASSIGN_LEFT_SHIFT:\n        return Binary(left, left, right, BinaryType.LEFT_SHIFT)\n    elif t == AssignmentOperationType.ASSIGN_RIGHT_SHIFT:\n        return Binary(left, left, right, BinaryType.RIGHT_SHIFT)\n    elif t == AssignmentOperationType.ASSIGN_ADDITION:\n        return Binary(left, left, right, BinaryType.ADDITION)\n    elif t == AssignmentOperationType.ASSIGN_SUBTRACTION:\n        return Binary(left, left, right, BinaryType.SUBTRACTION)\n    elif t == AssignmentOperationType.ASSIGN_MULTIPLICATION:\n        return Binary(left, left, right, BinaryType.MULTIPLICATION)\n    elif t == AssignmentOperationType.ASSIGN_DIVISION:\n        return Binary(left, left, right, BinaryType.DIVISION)\n    elif t == AssignmentOperationType.ASSIGN_MODULO:\n        return Binary(left, left, right, BinaryType.MODULO)\n\n    raise SlithIRError('Missing type during assignment conversion')\n\nclass ExpressionToSlithIR(ExpressionVisitor):\n\n    def __init__(self, expression, node):\n        from slither.core.cfg.node import NodeType\n        self._expression = expression\n        self._node = node\n        self._result = []\n        self._visit_expression(self.expression)\n        if node.type == NodeType.RETURN:\n            r = Return(get(self.expression))\n            r.set_expression(expression)\n            self._result.append(r)\n        for ir in self._result:\n            ir.set_node(node)\n\n    def result(self):\n        return self._result\n\n    def _post_assignement_operation(self, expression):\n        left = get(expression.expression_left)\n        right = get(expression.expression_right)\n        if isinstance(left, list): # tuple expression:\n            if isinstance(right, list): # unbox assigment\n                assert len(left) == len(right)\n                for idx in range(len(left)):\n                    if not left[idx] is None:\n                        operation = convert_assignment(left[idx], right[idx], expression.type, expression.expression_return_type)\n                        operation.set_expression(expression)\n                        self._result.append(operation)\n                set_val(expression, None)\n            else:\n                assert isinstance(right, TupleVariable)\n                for idx in range(len(left)):\n                    if not left[idx] is None:\n                        operation = Unpack(left[idx], right, idx)\n                        operation.set_expression(expression)\n                        self._result.append(operation)\n                set_val(expression, None)\n        else:\n            # Init of array, like\n            # uint8[2] var = [1,2];\n            if isinstance(right, list):\n                operation = InitArray(right, left)\n                operation.set_expression(expression)\n                self._result.append(operation)\n                set_val(expression, left)\n            else:\n                operation = convert_assignment(left, right, expression.type, expression.expression_return_type)\n                operation.set_expression(expression)\n                self._result.append(operation)\n                # Return left to handle\n                # a = b = 1; \n                set_val(expression, left)\n\n    def _post_binary_operation(self, expression):\n        left = get(expression.expression_left)\n        right = get(expression.expression_right)\n        val = TemporaryVariable(self._node)\n\n        operation = Binary(val, left, right, expression.type)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_call_expression(self, expression):\n        called = get(expression.called)\n        args = [get(a) for a in expression.arguments if a]\n        for arg in args:\n            arg_ = Argument(arg)\n            arg_.set_expression(expression)\n            self._result.append(arg_)\n        if isinstance(called, Function):\n            # internal call\n\n            # If tuple\n            if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':\n                val = TupleVariable(self._node)\n            else:\n                val = TemporaryVariable(self._node)\n            internal_call = InternalCall(called, len(args), val, expression.type_call)\n            internal_call.set_expression(expression)\n            self._result.append(internal_call)\n            set_val(expression, val)\n        else:\n            # If tuple\n            if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':\n                val = TupleVariable(self._node)\n            else:\n                val = TemporaryVariable(self._node)\n\n            message_call = TmpCall(called, len(args), val, expression.type_call)\n            message_call.set_expression(expression)\n            # Gas/value are only accessible here if the syntax {gas: , value: }\n            # Is used over .gas().value()\n            if expression.call_gas:\n                call_gas = get(expression.call_gas)\n                message_call.call_gas = call_gas\n            if expression.call_value:\n                call_value = get(expression.call_value)\n                message_call.call_value = call_value\n            self._result.append(message_call)\n            set_val(expression, val)\n\n    def _post_conditional_expression(self, expression):\n        raise Exception('Ternary operator are not convertible to SlithIR {}'.format(expression))\n\n    def _post_elementary_type_name_expression(self, expression):\n        set_val(expression, expression.type)\n\n    def _post_identifier(self, expression):\n        set_val(expression, expression.value)\n\n    def _post_index_access(self, expression):\n        left = get(expression.expression_left)\n        right = get(expression.expression_right)\n        val = ReferenceVariable(self._node)\n        # access to anonymous array\n        # such as [0,1][x]\n        if isinstance(left, list):\n            init_array_val = TemporaryVariable(self._node)\n            init_array_right = left\n            left = init_array_val\n            operation = InitArray(init_array_right, init_array_val)\n            operation.set_expression(expression)\n            self._result.append(operation)\n        operation = Index(val, left, right, expression.type)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_literal(self, expression):\n        cst = Constant(expression.value, expression.type, expression.subdenomination)\n        set_val(expression, cst)\n\n    def _post_member_access(self, expression):\n        expr = get(expression.expression)\n        val = ReferenceVariable(self._node)\n        member = Member(expr, Constant(expression.member_name), val)\n        member.set_expression(expression)\n        self._result.append(member)\n        set_val(expression, val)\n\n    def _post_new_array(self, expression):\n        val = TemporaryVariable(self._node)\n        operation = TmpNewArray(expression.depth, expression.array_type, val)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_new_contract(self, expression):\n        val = TemporaryVariable(self._node)\n        operation = TmpNewContract(expression.contract_name, val)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_new_elementary_type(self, expression):\n        # TODO unclear if this is ever used?\n        val = TemporaryVariable(self._node)\n        operation = TmpNewElementaryType(expression.type, val)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_tuple_expression(self, expression):\n        expressions = [get(e) if e else None for e in expression.expressions]\n        if len(expressions) == 1:\n            val = expressions[0]\n        else:\n            val = expressions\n        set_val(expression, val)\n\n    def _post_type_conversion(self, expression):\n        expr = get(expression.expression)\n        val = TemporaryVariable(self._node)\n        operation = TypeConversion(val, expr, expression.type)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_unary_operation(self, expression):\n        value = get(expression.expression)\n        if expression.type in [UnaryOperationType.BANG, UnaryOperationType.TILD]:\n            lvalue = TemporaryVariable(self._node)\n            operation = Unary(lvalue, value, expression.type)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, lvalue)\n        elif expression.type in [UnaryOperationType.DELETE]:\n            operation = Delete(value, value)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, value)\n        elif expression.type in [UnaryOperationType.PLUSPLUS_PRE]:\n            operation = Binary(value, value, Constant(\"1\", value.type), BinaryType.ADDITION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, value)\n        elif expression.type in [UnaryOperationType.MINUSMINUS_PRE]:\n            operation = Binary(value, value, Constant(\"1\", value.type), BinaryType.SUBTRACTION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, value)\n        elif expression.type in [UnaryOperationType.PLUSPLUS_POST]:\n            lvalue = TemporaryVariable(self._node)\n            operation = Assignment(lvalue, value, value.type)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            operation = Binary(value, value, Constant(\"1\", value.type), BinaryType.ADDITION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, lvalue)\n        elif expression.type in [UnaryOperationType.MINUSMINUS_POST]:\n            lvalue = TemporaryVariable(self._node)\n            operation = Assignment(lvalue, value, value.type)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            operation = Binary(value, value, Constant(\"1\", value.type), BinaryType.SUBTRACTION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, lvalue)\n        elif expression.type in [UnaryOperationType.PLUS_PRE]:\n            set_val(expression, value)\n        elif expression.type in [UnaryOperationType.MINUS_PRE]:\n            lvalue = TemporaryVariable(self._node)\n            operation = Binary(lvalue, Constant(\"0\", value.type), value, BinaryType.SUBTRACTION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, lvalue)\n        else:\n            raise SlithIRError('Unary operation to IR not supported {}'.format(expression))\n\n", "path": "slither/visitors/slithir/expression_to_slithir.py"}], "after_files": [{"content": "import logging\n\nfrom slither.core.declarations import Function\nfrom slither.core.expressions import (AssignmentOperationType,\n                                      UnaryOperationType)\nfrom slither.core.solidity_types import ArrayType\nfrom slither.core.solidity_types.type import Type\nfrom slither.slithir.operations import (Assignment, Binary, BinaryType, Delete,\n                                        Index, InitArray, InternalCall, Member,\n                                        NewArray, NewContract,\n                                        TypeConversion, Unary, Unpack, Return)\nfrom slither.slithir.tmp_operations.argument import Argument\nfrom slither.slithir.tmp_operations.tmp_call import TmpCall\nfrom slither.slithir.tmp_operations.tmp_new_array import TmpNewArray\nfrom slither.slithir.tmp_operations.tmp_new_contract import TmpNewContract\nfrom slither.slithir.tmp_operations.tmp_new_elementary_type import \\\n    TmpNewElementaryType\nfrom slither.slithir.variables import (Constant, ReferenceVariable,\n                                       TemporaryVariable, TupleVariable)\nfrom slither.visitors.expression.expression import ExpressionVisitor\n\nfrom slither.slithir.exceptions import SlithIRError\n\nlogger = logging.getLogger(\"VISTIOR:ExpressionToSlithIR\")\n\nkey = 'expressionToSlithIR'\n\ndef get(expression):\n    val = expression.context[key]\n    # we delete the item to reduce memory use\n    del expression.context[key]\n    return val\n\ndef set_val(expression, val):\n    expression.context[key] = val\n\ndef convert_assignment(left, right, t, return_type):\n    if t == AssignmentOperationType.ASSIGN:\n        return Assignment(left, right, return_type)\n    elif t == AssignmentOperationType.ASSIGN_OR:\n        return Binary(left, left, right, BinaryType.OR)\n    elif t == AssignmentOperationType.ASSIGN_CARET:\n        return Binary(left, left, right, BinaryType.CARET)\n    elif t == AssignmentOperationType.ASSIGN_AND:\n        return Binary(left, left, right, BinaryType.AND)\n    elif t == AssignmentOperationType.ASSIGN_LEFT_SHIFT:\n        return Binary(left, left, right, BinaryType.LEFT_SHIFT)\n    elif t == AssignmentOperationType.ASSIGN_RIGHT_SHIFT:\n        return Binary(left, left, right, BinaryType.RIGHT_SHIFT)\n    elif t == AssignmentOperationType.ASSIGN_ADDITION:\n        return Binary(left, left, right, BinaryType.ADDITION)\n    elif t == AssignmentOperationType.ASSIGN_SUBTRACTION:\n        return Binary(left, left, right, BinaryType.SUBTRACTION)\n    elif t == AssignmentOperationType.ASSIGN_MULTIPLICATION:\n        return Binary(left, left, right, BinaryType.MULTIPLICATION)\n    elif t == AssignmentOperationType.ASSIGN_DIVISION:\n        return Binary(left, left, right, BinaryType.DIVISION)\n    elif t == AssignmentOperationType.ASSIGN_MODULO:\n        return Binary(left, left, right, BinaryType.MODULO)\n\n    raise SlithIRError('Missing type during assignment conversion')\n\nclass ExpressionToSlithIR(ExpressionVisitor):\n\n    def __init__(self, expression, node):\n        from slither.core.cfg.node import NodeType\n        self._expression = expression\n        self._node = node\n        self._result = []\n        self._visit_expression(self.expression)\n        if node.type == NodeType.RETURN:\n            r = Return(get(self.expression))\n            r.set_expression(expression)\n            self._result.append(r)\n        for ir in self._result:\n            ir.set_node(node)\n\n    def result(self):\n        return self._result\n\n    def _post_assignement_operation(self, expression):\n        left = get(expression.expression_left)\n        right = get(expression.expression_right)\n        if isinstance(left, list): # tuple expression:\n            if isinstance(right, list): # unbox assigment\n                assert len(left) == len(right)\n                for idx in range(len(left)):\n                    if not left[idx] is None:\n                        operation = convert_assignment(left[idx], right[idx], expression.type, expression.expression_return_type)\n                        operation.set_expression(expression)\n                        self._result.append(operation)\n                set_val(expression, None)\n            else:\n                assert isinstance(right, TupleVariable)\n                for idx in range(len(left)):\n                    if not left[idx] is None:\n                        operation = Unpack(left[idx], right, idx)\n                        operation.set_expression(expression)\n                        self._result.append(operation)\n                set_val(expression, None)\n        else:\n            # Init of array, like\n            # uint8[2] var = [1,2];\n            if isinstance(right, list):\n                operation = InitArray(right, left)\n                operation.set_expression(expression)\n                self._result.append(operation)\n                set_val(expression, left)\n            else:\n                operation = convert_assignment(left, right, expression.type, expression.expression_return_type)\n                operation.set_expression(expression)\n                self._result.append(operation)\n                # Return left to handle\n                # a = b = 1; \n                set_val(expression, left)\n\n    def _post_binary_operation(self, expression):\n        left = get(expression.expression_left)\n        right = get(expression.expression_right)\n        val = TemporaryVariable(self._node)\n\n        operation = Binary(val, left, right, expression.type)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_call_expression(self, expression):\n        called = get(expression.called)\n        args = [get(a) for a in expression.arguments if a]\n        for arg in args:\n            arg_ = Argument(arg)\n            arg_.set_expression(expression)\n            self._result.append(arg_)\n        if isinstance(called, Function):\n            # internal call\n\n            # If tuple\n            if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':\n                val = TupleVariable(self._node)\n            else:\n                val = TemporaryVariable(self._node)\n            internal_call = InternalCall(called, len(args), val, expression.type_call)\n            internal_call.set_expression(expression)\n            self._result.append(internal_call)\n            set_val(expression, val)\n        else:\n            # If tuple\n            if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':\n                val = TupleVariable(self._node)\n            else:\n                val = TemporaryVariable(self._node)\n\n            message_call = TmpCall(called, len(args), val, expression.type_call)\n            message_call.set_expression(expression)\n            # Gas/value are only accessible here if the syntax {gas: , value: }\n            # Is used over .gas().value()\n            if expression.call_gas:\n                call_gas = get(expression.call_gas)\n                message_call.call_gas = call_gas\n            if expression.call_value:\n                call_value = get(expression.call_value)\n                message_call.call_value = call_value\n            self._result.append(message_call)\n            set_val(expression, val)\n\n    def _post_conditional_expression(self, expression):\n        raise Exception('Ternary operator are not convertible to SlithIR {}'.format(expression))\n\n    def _post_elementary_type_name_expression(self, expression):\n        set_val(expression, expression.type)\n\n    def _post_identifier(self, expression):\n        set_val(expression, expression.value)\n\n    def _post_index_access(self, expression):\n        left = get(expression.expression_left)\n        right = get(expression.expression_right)\n        # Left can be a type for abi.decode(var, uint[2])\n        if isinstance(left, Type):\n            # Nested type are not yet supported by abi.decode, so the assumption\n            # Is that the right variable must be a constant\n            assert isinstance(right, Constant)\n            t = ArrayType(left, right.value)\n            set_val(expression, t)\n            return\n        val = ReferenceVariable(self._node)\n        # access to anonymous array\n        # such as [0,1][x]\n        if isinstance(left, list):\n            init_array_val = TemporaryVariable(self._node)\n            init_array_right = left\n            left = init_array_val\n            operation = InitArray(init_array_right, init_array_val)\n            operation.set_expression(expression)\n            self._result.append(operation)\n        operation = Index(val, left, right, expression.type)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_literal(self, expression):\n        cst = Constant(expression.value, expression.type, expression.subdenomination)\n        set_val(expression, cst)\n\n    def _post_member_access(self, expression):\n        expr = get(expression.expression)\n        val = ReferenceVariable(self._node)\n        member = Member(expr, Constant(expression.member_name), val)\n        member.set_expression(expression)\n        self._result.append(member)\n        set_val(expression, val)\n\n    def _post_new_array(self, expression):\n        val = TemporaryVariable(self._node)\n        operation = TmpNewArray(expression.depth, expression.array_type, val)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_new_contract(self, expression):\n        val = TemporaryVariable(self._node)\n        operation = TmpNewContract(expression.contract_name, val)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_new_elementary_type(self, expression):\n        # TODO unclear if this is ever used?\n        val = TemporaryVariable(self._node)\n        operation = TmpNewElementaryType(expression.type, val)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_tuple_expression(self, expression):\n        expressions = [get(e) if e else None for e in expression.expressions]\n        if len(expressions) == 1:\n            val = expressions[0]\n        else:\n            val = expressions\n        set_val(expression, val)\n\n    def _post_type_conversion(self, expression):\n        expr = get(expression.expression)\n        val = TemporaryVariable(self._node)\n        operation = TypeConversion(val, expr, expression.type)\n        operation.set_expression(expression)\n        self._result.append(operation)\n        set_val(expression, val)\n\n    def _post_unary_operation(self, expression):\n        value = get(expression.expression)\n        if expression.type in [UnaryOperationType.BANG, UnaryOperationType.TILD]:\n            lvalue = TemporaryVariable(self._node)\n            operation = Unary(lvalue, value, expression.type)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, lvalue)\n        elif expression.type in [UnaryOperationType.DELETE]:\n            operation = Delete(value, value)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, value)\n        elif expression.type in [UnaryOperationType.PLUSPLUS_PRE]:\n            operation = Binary(value, value, Constant(\"1\", value.type), BinaryType.ADDITION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, value)\n        elif expression.type in [UnaryOperationType.MINUSMINUS_PRE]:\n            operation = Binary(value, value, Constant(\"1\", value.type), BinaryType.SUBTRACTION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, value)\n        elif expression.type in [UnaryOperationType.PLUSPLUS_POST]:\n            lvalue = TemporaryVariable(self._node)\n            operation = Assignment(lvalue, value, value.type)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            operation = Binary(value, value, Constant(\"1\", value.type), BinaryType.ADDITION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, lvalue)\n        elif expression.type in [UnaryOperationType.MINUSMINUS_POST]:\n            lvalue = TemporaryVariable(self._node)\n            operation = Assignment(lvalue, value, value.type)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            operation = Binary(value, value, Constant(\"1\", value.type), BinaryType.SUBTRACTION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, lvalue)\n        elif expression.type in [UnaryOperationType.PLUS_PRE]:\n            set_val(expression, value)\n        elif expression.type in [UnaryOperationType.MINUS_PRE]:\n            lvalue = TemporaryVariable(self._node)\n            operation = Binary(lvalue, Constant(\"0\", value.type), value, BinaryType.SUBTRACTION)\n            operation.set_expression(expression)\n            self._result.append(operation)\n            set_val(expression, lvalue)\n        else:\n            raise SlithIRError('Unary operation to IR not supported {}'.format(expression))\n\n", "path": "slither/visitors/slithir/expression_to_slithir.py"}]}