We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Negative indexing unsupported in `tuple` type.
- [x] I am using the latest released version of Numba (most recent is visible in
 the change log (https://github.com/numba/numba/blob/master/CHANGE_LOG).
- [x] I have included below a minimal working reproducer (if you are unsure how
 to write one see http://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports).

Negative indexing unsupported in `tuple` type.

From https://stackoverflow.com/questions/52777695/negative-dynamic-index-in-numba

```python
from numba import njit
@njit
def test_fn():
    tup = (3,2,4,6,2)
    total = 0
    for idx in range(5):
        total += tup[-idx]
    return total

test_fn()
```
raises `IndexError: tuple index out of range`


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `numba/targets/tupleobj.py`
Content:
```
1 """
2 Implementation of tuple objects
3 """
4 
5 from llvmlite import ir
6 import llvmlite.llvmpy.core as lc
7 import operator
8 
9 from .imputils import (lower_builtin, lower_getattr_generic, lower_cast,
10                        lower_constant,
11                        iternext_impl, impl_ret_borrowed, impl_ret_untracked)
12 from .. import typing, types, cgutils
13 from ..extending import overload_method
14 
15 
16 @lower_builtin(types.NamedTupleClass, types.VarArg(types.Any))
17 def namedtuple_constructor(context, builder, sig, args):
18     # A namedtuple has the same representation as a regular tuple
19     res = context.make_tuple(builder, sig.return_type, args)
20     # The tuple's contents are borrowed
21     return impl_ret_borrowed(context, builder, sig.return_type, res)
22 
23 @lower_builtin(operator.add, types.BaseTuple, types.BaseTuple)
24 def tuple_add(context, builder, sig, args):
25     left, right = [cgutils.unpack_tuple(builder, x) for x in args]
26     res = context.make_tuple(builder, sig.return_type, left + right)
27     # The tuple's contents are borrowed
28     return impl_ret_borrowed(context, builder, sig.return_type, res)
29 
30 def tuple_cmp_ordered(context, builder, op, sig, args):
31     tu, tv = sig.args
32     u, v = args
33     res = cgutils.alloca_once_value(builder, cgutils.true_bit)
34     bbend = builder.append_basic_block("cmp_end")
35     for i, (ta, tb) in enumerate(zip(tu.types, tv.types)):
36         a = builder.extract_value(u, i)
37         b = builder.extract_value(v, i)
38         not_equal = context.generic_compare(builder, operator.ne, (ta, tb), (a, b))
39         with builder.if_then(not_equal):
40             pred = context.generic_compare(builder, op, (ta, tb), (a, b))
41             builder.store(pred, res)
42             builder.branch(bbend)
43     # Everything matched equal => compare lengths
44     len_compare = op(len(tu.types), len(tv.types))
45     pred = context.get_constant(types.boolean, len_compare)
46     builder.store(pred, res)
47     builder.branch(bbend)
48     builder.position_at_end(bbend)
49     return builder.load(res)
50 
51 @lower_builtin(operator.eq, types.BaseTuple, types.BaseTuple)
52 def tuple_eq(context, builder, sig, args):
53     tu, tv = sig.args
54     u, v = args
55     if len(tu.types) != len(tv.types):
56         res = context.get_constant(types.boolean, False)
57         return impl_ret_untracked(context, builder, sig.return_type, res)
58     res = context.get_constant(types.boolean, True)
59     for i, (ta, tb) in enumerate(zip(tu.types, tv.types)):
60         a = builder.extract_value(u, i)
61         b = builder.extract_value(v, i)
62         pred = context.generic_compare(builder, operator.eq, (ta, tb), (a, b))
63         res = builder.and_(res, pred)
64     return impl_ret_untracked(context, builder, sig.return_type, res)
65 
66 @lower_builtin(operator.ne, types.BaseTuple, types.BaseTuple)
67 def tuple_ne(context, builder, sig, args):
68     res = builder.not_(tuple_eq(context, builder, sig, args))
69     return impl_ret_untracked(context, builder, sig.return_type, res)
70 
71 @lower_builtin(operator.lt, types.BaseTuple, types.BaseTuple)
72 def tuple_lt(context, builder, sig, args):
73     res = tuple_cmp_ordered(context, builder, operator.lt, sig, args)
74     return impl_ret_untracked(context, builder, sig.return_type, res)
75 
76 @lower_builtin(operator.le, types.BaseTuple, types.BaseTuple)
77 def tuple_le(context, builder, sig, args):
78     res = tuple_cmp_ordered(context, builder, operator.le, sig, args)
79     return impl_ret_untracked(context, builder, sig.return_type, res)
80 
81 @lower_builtin(operator.gt, types.BaseTuple, types.BaseTuple)
82 def tuple_gt(context, builder, sig, args):
83     res = tuple_cmp_ordered(context, builder, operator.gt, sig, args)
84     return impl_ret_untracked(context, builder, sig.return_type, res)
85 
86 @lower_builtin(operator.ge, types.BaseTuple, types.BaseTuple)
87 def tuple_ge(context, builder, sig, args):
88     res = tuple_cmp_ordered(context, builder, operator.ge, sig, args)
89     return impl_ret_untracked(context, builder, sig.return_type, res)
90 
91 @lower_builtin(hash, types.BaseTuple)
92 def hash_tuple(context, builder, sig, args):
93     tupty, = sig.args
94     tup, = args
95     lty = context.get_value_type(sig.return_type)
96 
97     h = ir.Constant(lty, 0x345678)
98     mult = ir.Constant(lty, 1000003)
99     n = ir.Constant(lty, len(tupty))
100 
101     for i, ty in enumerate(tupty.types):
102         # h = h * mult
103         h = builder.mul(h, mult)
104         val = builder.extract_value(tup, i)
105         hash_impl = context.get_function(hash,
106                                          typing.signature(sig.return_type, ty))
107         h_val = hash_impl(builder, (val,))
108         # h = h ^ hash(val)
109         h = builder.xor(h, h_val)
110         # Perturb: mult = mult + len(tup)
111         mult = builder.add(mult, n)
112 
113     return h
114 
115 
116 @lower_getattr_generic(types.BaseNamedTuple)
117 def namedtuple_getattr(context, builder, typ, value, attr):
118     """
119     Fetch a namedtuple's field.
120     """
121     index = typ.fields.index(attr)
122     res = builder.extract_value(value, index)
123     return impl_ret_borrowed(context, builder, typ[index], res)
124 
125 
126 @lower_constant(types.UniTuple)
127 @lower_constant(types.NamedUniTuple)
128 def unituple_constant(context, builder, ty, pyval):
129     """
130     Create a homogeneous tuple constant.
131     """
132     consts = [context.get_constant_generic(builder, ty.dtype, v)
133               for v in pyval]
134     return ir.ArrayType(consts[0].type, len(consts))(consts)
135 
136 @lower_constant(types.Tuple)
137 @lower_constant(types.NamedTuple)
138 def unituple_constant(context, builder, ty, pyval):
139     """
140     Create a heterogeneous tuple constant.
141     """
142     consts = [context.get_constant_generic(builder, ty.types[i], v)
143               for i, v in enumerate(pyval)]
144     return ir.Constant.literal_struct(consts)
145 
146 
147 #------------------------------------------------------------------------------
148 # Tuple iterators
149 
150 @lower_builtin('getiter', types.UniTuple)
151 @lower_builtin('getiter', types.NamedUniTuple)
152 def getiter_unituple(context, builder, sig, args):
153     [tupty] = sig.args
154     [tup] = args
155 
156     iterval = context.make_helper(builder, types.UniTupleIter(tupty))
157 
158     index0 = context.get_constant(types.intp, 0)
159     indexptr = cgutils.alloca_once(builder, index0.type)
160     builder.store(index0, indexptr)
161 
162     iterval.index = indexptr
163     iterval.tuple = tup
164 
165     res = iterval._getvalue()
166     return impl_ret_borrowed(context, builder, sig.return_type, res)
167 
168 
169 @lower_builtin('iternext', types.UniTupleIter)
170 @iternext_impl
171 def iternext_unituple(context, builder, sig, args, result):
172     [tupiterty] = sig.args
173     [tupiter] = args
174 
175     iterval = context.make_helper(builder, tupiterty, value=tupiter)
176 
177     tup = iterval.tuple
178     idxptr = iterval.index
179     idx = builder.load(idxptr)
180     count = context.get_constant(types.intp, tupiterty.container.count)
181 
182     is_valid = builder.icmp(lc.ICMP_SLT, idx, count)
183     result.set_valid(is_valid)
184 
185     with builder.if_then(is_valid):
186         getitem_sig = typing.signature(tupiterty.container.dtype,
187                                        tupiterty.container,
188                                        types.intp)
189         getitem_out = getitem_unituple(context, builder, getitem_sig,
190                                        [tup, idx])
191         result.yield_(getitem_out)
192         nidx = builder.add(idx, context.get_constant(types.intp, 1))
193         builder.store(nidx, iterval.index)
194 
195 
196 @lower_builtin('getitem', types.UniTuple, types.intp)
197 @lower_builtin('getitem', types.NamedUniTuple, types.intp)
198 def getitem_unituple(context, builder, sig, args):
199     tupty, _ = sig.args
200     tup, idx = args
201 
202     errmsg_oob = ("tuple index out of range",)
203 
204     if len(tupty) == 0:
205         # Empty tuple.
206 
207         # Always branch and raise IndexError
208         with builder.if_then(cgutils.true_bit):
209             context.call_conv.return_user_exc(builder, IndexError,
210                                               errmsg_oob)
211         # This is unreachable in runtime,
212         # but it exists to not terminate the current basicblock.
213         res = context.get_constant_null(sig.return_type)
214         return impl_ret_untracked(context, builder,
215                                   sig.return_type, res)
216     else:
217         # The tuple is not empty
218         bbelse = builder.append_basic_block("switch.else")
219         bbend = builder.append_basic_block("switch.end")
220         switch = builder.switch(idx, bbelse)
221 
222         with builder.goto_block(bbelse):
223             context.call_conv.return_user_exc(builder, IndexError,
224                                               errmsg_oob)
225 
226         lrtty = context.get_value_type(tupty.dtype)
227         with builder.goto_block(bbend):
228             phinode = builder.phi(lrtty)
229 
230         for i in range(tupty.count):
231             ki = context.get_constant(types.intp, i)
232             bbi = builder.append_basic_block("switch.%d" % i)
233             switch.add_case(ki, bbi)
234             with builder.goto_block(bbi):
235                 value = builder.extract_value(tup, i)
236                 builder.branch(bbend)
237                 phinode.add_incoming(value, bbi)
238 
239         builder.position_at_end(bbend)
240         res = phinode
241         assert sig.return_type == tupty.dtype
242         return impl_ret_borrowed(context, builder, sig.return_type, res)
243 
244 
245 @lower_builtin('static_getitem', types.BaseTuple, types.Const)
246 def static_getitem_tuple(context, builder, sig, args):
247     tupty, _ = sig.args
248     tup, idx = args
249     if isinstance(idx, int):
250         if idx < 0:
251             idx += len(tupty)
252         if not 0 <= idx < len(tupty):
253             raise IndexError("cannot index at %d in %s" % (idx, tupty))
254         res = builder.extract_value(tup, idx)
255     elif isinstance(idx, slice):
256         items = cgutils.unpack_tuple(builder, tup)[idx]
257         res = context.make_tuple(builder, sig.return_type, items)
258     else:
259         raise NotImplementedError("unexpected index %r for %s"
260                                   % (idx, sig.args[0]))
261     return impl_ret_borrowed(context, builder, sig.return_type, res)
262 
263 
264 #------------------------------------------------------------------------------
265 # Implicit conversion
266 
267 @lower_cast(types.BaseTuple, types.BaseTuple)
268 def tuple_to_tuple(context, builder, fromty, toty, val):
269     if (isinstance(fromty, types.BaseNamedTuple)
270         or isinstance(toty, types.BaseNamedTuple)):
271         # Disallowed by typing layer
272         raise NotImplementedError
273 
274     if len(fromty) != len(toty):
275         # Disallowed by typing layer
276         raise NotImplementedError
277 
278     olditems = cgutils.unpack_tuple(builder, val, len(fromty))
279     items = [context.cast(builder, v, f, t)
280              for v, f, t in zip(olditems, fromty, toty)]
281     return context.make_tuple(builder, toty, items)
282 
283 
284 #------------------------------------------------------------------------------
285 # Methods
286 
287 @overload_method(types.BaseTuple, 'index')
288 def tuple_index(tup, value):
289 
290     def tuple_index_impl(tup, value):
291         for i in range(len(tup)):
292             if tup[i] == value:
293                 return i
294         raise ValueError("tuple.index(x): x not in tuple")
295 
296     return tuple_index_impl
297
```
--- 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/numba/targets/tupleobj.py b/numba/targets/tupleobj.py
--- a/numba/targets/tupleobj.py
+++ b/numba/targets/tupleobj.py
@@ -231,6 +231,10 @@
             ki = context.get_constant(types.intp, i)
             bbi = builder.append_basic_block("switch.%d" % i)
             switch.add_case(ki, bbi)
+            # handle negative indexing, create case (-tuple.count + i) to
+            # reference same block as i
+            kin = context.get_constant(types.intp, -tupty.count + i)
+            switch.add_case(kin, bbi)
             with builder.goto_block(bbi):
                 value = builder.extract_value(tup, i)
                 builder.branch(bbend)

{"golden_diff": "diff --git a/numba/targets/tupleobj.py b/numba/targets/tupleobj.py\n--- a/numba/targets/tupleobj.py\n+++ b/numba/targets/tupleobj.py\n@@ -231,6 +231,10 @@\n             ki = context.get_constant(types.intp, i)\n             bbi = builder.append_basic_block(\"switch.%d\" % i)\n             switch.add_case(ki, bbi)\n+            # handle negative indexing, create case (-tuple.count + i) to\n+            # reference same block as i\n+            kin = context.get_constant(types.intp, -tupty.count + i)\n+            switch.add_case(kin, bbi)\n             with builder.goto_block(bbi):\n                 value = builder.extract_value(tup, i)\n                 builder.branch(bbend)\n", "issue": "Negative indexing unsupported in `tuple` type.\n- [x] I am using the latest released version of Numba (most recent is visible in\r\n the change log (https://github.com/numba/numba/blob/master/CHANGE_LOG).\r\n- [x] I have included below a minimal working reproducer (if you are unsure how\r\n to write one see http://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports).\r\n\r\nNegative indexing unsupported in `tuple` type.\r\n\r\nFrom https://stackoverflow.com/questions/52777695/negative-dynamic-index-in-numba\r\n\r\n```python\r\nfrom numba import njit\r\n@njit\r\ndef test_fn():\r\n    tup = (3,2,4,6,2)\r\n    total = 0\r\n    for idx in range(5):\r\n        total += tup[-idx]\r\n    return total\r\n\r\ntest_fn()\r\n```\r\nraises `IndexError: tuple index out of range`\r\n\n", "before_files": [{"content": "\"\"\"\nImplementation of tuple objects\n\"\"\"\n\nfrom llvmlite import ir\nimport llvmlite.llvmpy.core as lc\nimport operator\n\nfrom .imputils import (lower_builtin, lower_getattr_generic, lower_cast,\n                       lower_constant,\n                       iternext_impl, impl_ret_borrowed, impl_ret_untracked)\nfrom .. import typing, types, cgutils\nfrom ..extending import overload_method\n\n\n@lower_builtin(types.NamedTupleClass, types.VarArg(types.Any))\ndef namedtuple_constructor(context, builder, sig, args):\n    # A namedtuple has the same representation as a regular tuple\n    res = context.make_tuple(builder, sig.return_type, args)\n    # The tuple's contents are borrowed\n    return impl_ret_borrowed(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.add, types.BaseTuple, types.BaseTuple)\ndef tuple_add(context, builder, sig, args):\n    left, right = [cgutils.unpack_tuple(builder, x) for x in args]\n    res = context.make_tuple(builder, sig.return_type, left + right)\n    # The tuple's contents are borrowed\n    return impl_ret_borrowed(context, builder, sig.return_type, res)\n\ndef tuple_cmp_ordered(context, builder, op, sig, args):\n    tu, tv = sig.args\n    u, v = args\n    res = cgutils.alloca_once_value(builder, cgutils.true_bit)\n    bbend = builder.append_basic_block(\"cmp_end\")\n    for i, (ta, tb) in enumerate(zip(tu.types, tv.types)):\n        a = builder.extract_value(u, i)\n        b = builder.extract_value(v, i)\n        not_equal = context.generic_compare(builder, operator.ne, (ta, tb), (a, b))\n        with builder.if_then(not_equal):\n            pred = context.generic_compare(builder, op, (ta, tb), (a, b))\n            builder.store(pred, res)\n            builder.branch(bbend)\n    # Everything matched equal => compare lengths\n    len_compare = op(len(tu.types), len(tv.types))\n    pred = context.get_constant(types.boolean, len_compare)\n    builder.store(pred, res)\n    builder.branch(bbend)\n    builder.position_at_end(bbend)\n    return builder.load(res)\n\n@lower_builtin(operator.eq, types.BaseTuple, types.BaseTuple)\ndef tuple_eq(context, builder, sig, args):\n    tu, tv = sig.args\n    u, v = args\n    if len(tu.types) != len(tv.types):\n        res = context.get_constant(types.boolean, False)\n        return impl_ret_untracked(context, builder, sig.return_type, res)\n    res = context.get_constant(types.boolean, True)\n    for i, (ta, tb) in enumerate(zip(tu.types, tv.types)):\n        a = builder.extract_value(u, i)\n        b = builder.extract_value(v, i)\n        pred = context.generic_compare(builder, operator.eq, (ta, tb), (a, b))\n        res = builder.and_(res, pred)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.ne, types.BaseTuple, types.BaseTuple)\ndef tuple_ne(context, builder, sig, args):\n    res = builder.not_(tuple_eq(context, builder, sig, args))\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.lt, types.BaseTuple, types.BaseTuple)\ndef tuple_lt(context, builder, sig, args):\n    res = tuple_cmp_ordered(context, builder, operator.lt, sig, args)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.le, types.BaseTuple, types.BaseTuple)\ndef tuple_le(context, builder, sig, args):\n    res = tuple_cmp_ordered(context, builder, operator.le, sig, args)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.gt, types.BaseTuple, types.BaseTuple)\ndef tuple_gt(context, builder, sig, args):\n    res = tuple_cmp_ordered(context, builder, operator.gt, sig, args)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.ge, types.BaseTuple, types.BaseTuple)\ndef tuple_ge(context, builder, sig, args):\n    res = tuple_cmp_ordered(context, builder, operator.ge, sig, args)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(hash, types.BaseTuple)\ndef hash_tuple(context, builder, sig, args):\n    tupty, = sig.args\n    tup, = args\n    lty = context.get_value_type(sig.return_type)\n\n    h = ir.Constant(lty, 0x345678)\n    mult = ir.Constant(lty, 1000003)\n    n = ir.Constant(lty, len(tupty))\n\n    for i, ty in enumerate(tupty.types):\n        # h = h * mult\n        h = builder.mul(h, mult)\n        val = builder.extract_value(tup, i)\n        hash_impl = context.get_function(hash,\n                                         typing.signature(sig.return_type, ty))\n        h_val = hash_impl(builder, (val,))\n        # h = h ^ hash(val)\n        h = builder.xor(h, h_val)\n        # Perturb: mult = mult + len(tup)\n        mult = builder.add(mult, n)\n\n    return h\n\n\n@lower_getattr_generic(types.BaseNamedTuple)\ndef namedtuple_getattr(context, builder, typ, value, attr):\n    \"\"\"\n    Fetch a namedtuple's field.\n    \"\"\"\n    index = typ.fields.index(attr)\n    res = builder.extract_value(value, index)\n    return impl_ret_borrowed(context, builder, typ[index], res)\n\n\n@lower_constant(types.UniTuple)\n@lower_constant(types.NamedUniTuple)\ndef unituple_constant(context, builder, ty, pyval):\n    \"\"\"\n    Create a homogeneous tuple constant.\n    \"\"\"\n    consts = [context.get_constant_generic(builder, ty.dtype, v)\n              for v in pyval]\n    return ir.ArrayType(consts[0].type, len(consts))(consts)\n\n@lower_constant(types.Tuple)\n@lower_constant(types.NamedTuple)\ndef unituple_constant(context, builder, ty, pyval):\n    \"\"\"\n    Create a heterogeneous tuple constant.\n    \"\"\"\n    consts = [context.get_constant_generic(builder, ty.types[i], v)\n              for i, v in enumerate(pyval)]\n    return ir.Constant.literal_struct(consts)\n\n\n#------------------------------------------------------------------------------\n# Tuple iterators\n\n@lower_builtin('getiter', types.UniTuple)\n@lower_builtin('getiter', types.NamedUniTuple)\ndef getiter_unituple(context, builder, sig, args):\n    [tupty] = sig.args\n    [tup] = args\n\n    iterval = context.make_helper(builder, types.UniTupleIter(tupty))\n\n    index0 = context.get_constant(types.intp, 0)\n    indexptr = cgutils.alloca_once(builder, index0.type)\n    builder.store(index0, indexptr)\n\n    iterval.index = indexptr\n    iterval.tuple = tup\n\n    res = iterval._getvalue()\n    return impl_ret_borrowed(context, builder, sig.return_type, res)\n\n\n@lower_builtin('iternext', types.UniTupleIter)\n@iternext_impl\ndef iternext_unituple(context, builder, sig, args, result):\n    [tupiterty] = sig.args\n    [tupiter] = args\n\n    iterval = context.make_helper(builder, tupiterty, value=tupiter)\n\n    tup = iterval.tuple\n    idxptr = iterval.index\n    idx = builder.load(idxptr)\n    count = context.get_constant(types.intp, tupiterty.container.count)\n\n    is_valid = builder.icmp(lc.ICMP_SLT, idx, count)\n    result.set_valid(is_valid)\n\n    with builder.if_then(is_valid):\n        getitem_sig = typing.signature(tupiterty.container.dtype,\n                                       tupiterty.container,\n                                       types.intp)\n        getitem_out = getitem_unituple(context, builder, getitem_sig,\n                                       [tup, idx])\n        result.yield_(getitem_out)\n        nidx = builder.add(idx, context.get_constant(types.intp, 1))\n        builder.store(nidx, iterval.index)\n\n\n@lower_builtin('getitem', types.UniTuple, types.intp)\n@lower_builtin('getitem', types.NamedUniTuple, types.intp)\ndef getitem_unituple(context, builder, sig, args):\n    tupty, _ = sig.args\n    tup, idx = args\n\n    errmsg_oob = (\"tuple index out of range\",)\n\n    if len(tupty) == 0:\n        # Empty tuple.\n\n        # Always branch and raise IndexError\n        with builder.if_then(cgutils.true_bit):\n            context.call_conv.return_user_exc(builder, IndexError,\n                                              errmsg_oob)\n        # This is unreachable in runtime,\n        # but it exists to not terminate the current basicblock.\n        res = context.get_constant_null(sig.return_type)\n        return impl_ret_untracked(context, builder,\n                                  sig.return_type, res)\n    else:\n        # The tuple is not empty\n        bbelse = builder.append_basic_block(\"switch.else\")\n        bbend = builder.append_basic_block(\"switch.end\")\n        switch = builder.switch(idx, bbelse)\n\n        with builder.goto_block(bbelse):\n            context.call_conv.return_user_exc(builder, IndexError,\n                                              errmsg_oob)\n\n        lrtty = context.get_value_type(tupty.dtype)\n        with builder.goto_block(bbend):\n            phinode = builder.phi(lrtty)\n\n        for i in range(tupty.count):\n            ki = context.get_constant(types.intp, i)\n            bbi = builder.append_basic_block(\"switch.%d\" % i)\n            switch.add_case(ki, bbi)\n            with builder.goto_block(bbi):\n                value = builder.extract_value(tup, i)\n                builder.branch(bbend)\n                phinode.add_incoming(value, bbi)\n\n        builder.position_at_end(bbend)\n        res = phinode\n        assert sig.return_type == tupty.dtype\n        return impl_ret_borrowed(context, builder, sig.return_type, res)\n\n\n@lower_builtin('static_getitem', types.BaseTuple, types.Const)\ndef static_getitem_tuple(context, builder, sig, args):\n    tupty, _ = sig.args\n    tup, idx = args\n    if isinstance(idx, int):\n        if idx < 0:\n            idx += len(tupty)\n        if not 0 <= idx < len(tupty):\n            raise IndexError(\"cannot index at %d in %s\" % (idx, tupty))\n        res = builder.extract_value(tup, idx)\n    elif isinstance(idx, slice):\n        items = cgutils.unpack_tuple(builder, tup)[idx]\n        res = context.make_tuple(builder, sig.return_type, items)\n    else:\n        raise NotImplementedError(\"unexpected index %r for %s\"\n                                  % (idx, sig.args[0]))\n    return impl_ret_borrowed(context, builder, sig.return_type, res)\n\n\n#------------------------------------------------------------------------------\n# Implicit conversion\n\n@lower_cast(types.BaseTuple, types.BaseTuple)\ndef tuple_to_tuple(context, builder, fromty, toty, val):\n    if (isinstance(fromty, types.BaseNamedTuple)\n        or isinstance(toty, types.BaseNamedTuple)):\n        # Disallowed by typing layer\n        raise NotImplementedError\n\n    if len(fromty) != len(toty):\n        # Disallowed by typing layer\n        raise NotImplementedError\n\n    olditems = cgutils.unpack_tuple(builder, val, len(fromty))\n    items = [context.cast(builder, v, f, t)\n             for v, f, t in zip(olditems, fromty, toty)]\n    return context.make_tuple(builder, toty, items)\n\n\n#------------------------------------------------------------------------------\n# Methods\n\n@overload_method(types.BaseTuple, 'index')\ndef tuple_index(tup, value):\n\n    def tuple_index_impl(tup, value):\n        for i in range(len(tup)):\n            if tup[i] == value:\n                return i\n        raise ValueError(\"tuple.index(x): x not in tuple\")\n\n    return tuple_index_impl\n", "path": "numba/targets/tupleobj.py"}], "after_files": [{"content": "\"\"\"\nImplementation of tuple objects\n\"\"\"\n\nfrom llvmlite import ir\nimport llvmlite.llvmpy.core as lc\nimport operator\n\nfrom .imputils import (lower_builtin, lower_getattr_generic, lower_cast,\n                       lower_constant,\n                       iternext_impl, impl_ret_borrowed, impl_ret_untracked)\nfrom .. import typing, types, cgutils\nfrom ..extending import overload_method\n\n\n@lower_builtin(types.NamedTupleClass, types.VarArg(types.Any))\ndef namedtuple_constructor(context, builder, sig, args):\n    # A namedtuple has the same representation as a regular tuple\n    res = context.make_tuple(builder, sig.return_type, args)\n    # The tuple's contents are borrowed\n    return impl_ret_borrowed(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.add, types.BaseTuple, types.BaseTuple)\ndef tuple_add(context, builder, sig, args):\n    left, right = [cgutils.unpack_tuple(builder, x) for x in args]\n    res = context.make_tuple(builder, sig.return_type, left + right)\n    # The tuple's contents are borrowed\n    return impl_ret_borrowed(context, builder, sig.return_type, res)\n\ndef tuple_cmp_ordered(context, builder, op, sig, args):\n    tu, tv = sig.args\n    u, v = args\n    res = cgutils.alloca_once_value(builder, cgutils.true_bit)\n    bbend = builder.append_basic_block(\"cmp_end\")\n    for i, (ta, tb) in enumerate(zip(tu.types, tv.types)):\n        a = builder.extract_value(u, i)\n        b = builder.extract_value(v, i)\n        not_equal = context.generic_compare(builder, operator.ne, (ta, tb), (a, b))\n        with builder.if_then(not_equal):\n            pred = context.generic_compare(builder, op, (ta, tb), (a, b))\n            builder.store(pred, res)\n            builder.branch(bbend)\n    # Everything matched equal => compare lengths\n    len_compare = op(len(tu.types), len(tv.types))\n    pred = context.get_constant(types.boolean, len_compare)\n    builder.store(pred, res)\n    builder.branch(bbend)\n    builder.position_at_end(bbend)\n    return builder.load(res)\n\n@lower_builtin(operator.eq, types.BaseTuple, types.BaseTuple)\ndef tuple_eq(context, builder, sig, args):\n    tu, tv = sig.args\n    u, v = args\n    if len(tu.types) != len(tv.types):\n        res = context.get_constant(types.boolean, False)\n        return impl_ret_untracked(context, builder, sig.return_type, res)\n    res = context.get_constant(types.boolean, True)\n    for i, (ta, tb) in enumerate(zip(tu.types, tv.types)):\n        a = builder.extract_value(u, i)\n        b = builder.extract_value(v, i)\n        pred = context.generic_compare(builder, operator.eq, (ta, tb), (a, b))\n        res = builder.and_(res, pred)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.ne, types.BaseTuple, types.BaseTuple)\ndef tuple_ne(context, builder, sig, args):\n    res = builder.not_(tuple_eq(context, builder, sig, args))\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.lt, types.BaseTuple, types.BaseTuple)\ndef tuple_lt(context, builder, sig, args):\n    res = tuple_cmp_ordered(context, builder, operator.lt, sig, args)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.le, types.BaseTuple, types.BaseTuple)\ndef tuple_le(context, builder, sig, args):\n    res = tuple_cmp_ordered(context, builder, operator.le, sig, args)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.gt, types.BaseTuple, types.BaseTuple)\ndef tuple_gt(context, builder, sig, args):\n    res = tuple_cmp_ordered(context, builder, operator.gt, sig, args)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(operator.ge, types.BaseTuple, types.BaseTuple)\ndef tuple_ge(context, builder, sig, args):\n    res = tuple_cmp_ordered(context, builder, operator.ge, sig, args)\n    return impl_ret_untracked(context, builder, sig.return_type, res)\n\n@lower_builtin(hash, types.BaseTuple)\ndef hash_tuple(context, builder, sig, args):\n    tupty, = sig.args\n    tup, = args\n    lty = context.get_value_type(sig.return_type)\n\n    h = ir.Constant(lty, 0x345678)\n    mult = ir.Constant(lty, 1000003)\n    n = ir.Constant(lty, len(tupty))\n\n    for i, ty in enumerate(tupty.types):\n        # h = h * mult\n        h = builder.mul(h, mult)\n        val = builder.extract_value(tup, i)\n        hash_impl = context.get_function(hash,\n                                         typing.signature(sig.return_type, ty))\n        h_val = hash_impl(builder, (val,))\n        # h = h ^ hash(val)\n        h = builder.xor(h, h_val)\n        # Perturb: mult = mult + len(tup)\n        mult = builder.add(mult, n)\n\n    return h\n\n\n@lower_getattr_generic(types.BaseNamedTuple)\ndef namedtuple_getattr(context, builder, typ, value, attr):\n    \"\"\"\n    Fetch a namedtuple's field.\n    \"\"\"\n    index = typ.fields.index(attr)\n    res = builder.extract_value(value, index)\n    return impl_ret_borrowed(context, builder, typ[index], res)\n\n\n@lower_constant(types.UniTuple)\n@lower_constant(types.NamedUniTuple)\ndef unituple_constant(context, builder, ty, pyval):\n    \"\"\"\n    Create a homogeneous tuple constant.\n    \"\"\"\n    consts = [context.get_constant_generic(builder, ty.dtype, v)\n              for v in pyval]\n    return ir.ArrayType(consts[0].type, len(consts))(consts)\n\n@lower_constant(types.Tuple)\n@lower_constant(types.NamedTuple)\ndef unituple_constant(context, builder, ty, pyval):\n    \"\"\"\n    Create a heterogeneous tuple constant.\n    \"\"\"\n    consts = [context.get_constant_generic(builder, ty.types[i], v)\n              for i, v in enumerate(pyval)]\n    return ir.Constant.literal_struct(consts)\n\n\n#------------------------------------------------------------------------------\n# Tuple iterators\n\n@lower_builtin('getiter', types.UniTuple)\n@lower_builtin('getiter', types.NamedUniTuple)\ndef getiter_unituple(context, builder, sig, args):\n    [tupty] = sig.args\n    [tup] = args\n\n    iterval = context.make_helper(builder, types.UniTupleIter(tupty))\n\n    index0 = context.get_constant(types.intp, 0)\n    indexptr = cgutils.alloca_once(builder, index0.type)\n    builder.store(index0, indexptr)\n\n    iterval.index = indexptr\n    iterval.tuple = tup\n\n    res = iterval._getvalue()\n    return impl_ret_borrowed(context, builder, sig.return_type, res)\n\n\n@lower_builtin('iternext', types.UniTupleIter)\n@iternext_impl\ndef iternext_unituple(context, builder, sig, args, result):\n    [tupiterty] = sig.args\n    [tupiter] = args\n\n    iterval = context.make_helper(builder, tupiterty, value=tupiter)\n\n    tup = iterval.tuple\n    idxptr = iterval.index\n    idx = builder.load(idxptr)\n    count = context.get_constant(types.intp, tupiterty.container.count)\n\n    is_valid = builder.icmp(lc.ICMP_SLT, idx, count)\n    result.set_valid(is_valid)\n\n    with builder.if_then(is_valid):\n        getitem_sig = typing.signature(tupiterty.container.dtype,\n                                       tupiterty.container,\n                                       types.intp)\n        getitem_out = getitem_unituple(context, builder, getitem_sig,\n                                       [tup, idx])\n        result.yield_(getitem_out)\n        nidx = builder.add(idx, context.get_constant(types.intp, 1))\n        builder.store(nidx, iterval.index)\n\n\n@lower_builtin('getitem', types.UniTuple, types.intp)\n@lower_builtin('getitem', types.NamedUniTuple, types.intp)\ndef getitem_unituple(context, builder, sig, args):\n    tupty, _ = sig.args\n    tup, idx = args\n\n    errmsg_oob = (\"tuple index out of range\",)\n\n    if len(tupty) == 0:\n        # Empty tuple.\n\n        # Always branch and raise IndexError\n        with builder.if_then(cgutils.true_bit):\n            context.call_conv.return_user_exc(builder, IndexError,\n                                              errmsg_oob)\n        # This is unreachable in runtime,\n        # but it exists to not terminate the current basicblock.\n        res = context.get_constant_null(sig.return_type)\n        return impl_ret_untracked(context, builder,\n                                  sig.return_type, res)\n    else:\n        # The tuple is not empty\n        bbelse = builder.append_basic_block(\"switch.else\")\n        bbend = builder.append_basic_block(\"switch.end\")\n        switch = builder.switch(idx, bbelse)\n\n        with builder.goto_block(bbelse):\n            context.call_conv.return_user_exc(builder, IndexError,\n                                              errmsg_oob)\n\n        lrtty = context.get_value_type(tupty.dtype)\n        with builder.goto_block(bbend):\n            phinode = builder.phi(lrtty)\n\n        for i in range(tupty.count):\n            ki = context.get_constant(types.intp, i)\n            bbi = builder.append_basic_block(\"switch.%d\" % i)\n            switch.add_case(ki, bbi)\n            # handle negative indexing, create case (-tuple.count + i) to\n            # reference same block as i\n            kin = context.get_constant(types.intp, -tupty.count + i)\n            switch.add_case(kin, bbi)\n            with builder.goto_block(bbi):\n                value = builder.extract_value(tup, i)\n                builder.branch(bbend)\n                phinode.add_incoming(value, bbi)\n\n        builder.position_at_end(bbend)\n        res = phinode\n        assert sig.return_type == tupty.dtype\n        return impl_ret_borrowed(context, builder, sig.return_type, res)\n\n\n@lower_builtin('static_getitem', types.BaseTuple, types.Const)\ndef static_getitem_tuple(context, builder, sig, args):\n    tupty, _ = sig.args\n    tup, idx = args\n    if isinstance(idx, int):\n        if idx < 0:\n            idx += len(tupty)\n        if not 0 <= idx < len(tupty):\n            raise IndexError(\"cannot index at %d in %s\" % (idx, tupty))\n        res = builder.extract_value(tup, idx)\n    elif isinstance(idx, slice):\n        items = cgutils.unpack_tuple(builder, tup)[idx]\n        res = context.make_tuple(builder, sig.return_type, items)\n    else:\n        raise NotImplementedError(\"unexpected index %r for %s\"\n                                  % (idx, sig.args[0]))\n    return impl_ret_borrowed(context, builder, sig.return_type, res)\n\n\n#------------------------------------------------------------------------------\n# Implicit conversion\n\n@lower_cast(types.BaseTuple, types.BaseTuple)\ndef tuple_to_tuple(context, builder, fromty, toty, val):\n    if (isinstance(fromty, types.BaseNamedTuple)\n        or isinstance(toty, types.BaseNamedTuple)):\n        # Disallowed by typing layer\n        raise NotImplementedError\n\n    if len(fromty) != len(toty):\n        # Disallowed by typing layer\n        raise NotImplementedError\n\n    olditems = cgutils.unpack_tuple(builder, val, len(fromty))\n    items = [context.cast(builder, v, f, t)\n             for v, f, t in zip(olditems, fromty, toty)]\n    return context.make_tuple(builder, toty, items)\n\n\n#------------------------------------------------------------------------------\n# Methods\n\n@overload_method(types.BaseTuple, 'index')\ndef tuple_index(tup, value):\n\n    def tuple_index_impl(tup, value):\n        for i in range(len(tup)):\n            if tup[i] == value:\n                return i\n        raise ValueError(\"tuple.index(x): x not in tuple\")\n\n    return tuple_index_impl\n", "path": "numba/targets/tupleobj.py"}]}