|
25 | 25 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | 26 | # ***************************************************************************** |
27 | 27 |
|
| 28 | +from textwrap import dedent |
| 29 | + |
28 | 30 | from numba import types |
29 | | -from numba.extending import (intrinsic, ) |
| 31 | +from numba.extending import intrinsic |
30 | 32 | from numba.core.typing.templates import (signature, ) |
31 | 33 |
|
| 34 | +from sdc.utilities.utils import sdc_overload |
| 35 | + |
32 | 36 |
|
33 | 37 | @intrinsic |
34 | 38 | def sdc_tuple_map(typingctx, func, data, *args): |
@@ -205,3 +209,69 @@ def codegen(context, builder, sig, args): |
205 | 209 | return context.make_tuple(builder, ret_type, [first_tup, second_tup]) |
206 | 210 |
|
207 | 211 | return ret_type(data_type), codegen |
| 212 | + |
| 213 | + |
| 214 | +@sdc_overload(zip) |
| 215 | +def zip_tuples_spec_ovld(x, y): |
| 216 | + print("DEBUG: overload_zip x, y: ", x, y) |
| 217 | + |
| 218 | + if not (isinstance(x, types.BaseAnonymousTuple) and isinstance(y, types.BaseAnonymousTuple)): |
| 219 | + return None |
| 220 | + |
| 221 | + res_size = min(len(x), len(y)) |
| 222 | + func_impl_name = 'zip_tuples_spec_impl' |
| 223 | + tup_elements = ', '.join([f"(x[{i}], y[{i}])" for i in range(res_size)]) |
| 224 | + func_text = dedent(f""" |
| 225 | + def {func_impl_name}(x, y): |
| 226 | + return ({tup_elements}{',' if res_size else ''}) |
| 227 | + """) |
| 228 | + use_globals, use_locals = {}, {} |
| 229 | + # print("DEBUG: func_text:", func_text) |
| 230 | + exec(func_text, use_globals, use_locals) |
| 231 | + return use_locals[func_impl_name] |
| 232 | + |
| 233 | + # FIXME_Numba#6533: alternatively we could have used sdc_tuple_map_elementwise |
| 234 | + # to avoid another use of exec, but due to @intrinsic-s not supporting |
| 235 | + # prefer_literal option below implementation looses literaly of args! |
| 236 | + # from sdc.functions.tuple_utils import sdc_tuple_map_elementwise |
| 237 | + # def zip_tuples_spec_impl(x, y): |
| 238 | + # return sdc_tuple_map_elementwise( |
| 239 | + # lambda a, b: (a, b), |
| 240 | + # x, |
| 241 | + # y |
| 242 | + # ) |
| 243 | + # |
| 244 | + # return zip_tuples_spec_impl |
| 245 | + |
| 246 | + |
| 247 | +@sdc_overload(dict) |
| 248 | +def dict_from_tuples_ovld(x): |
| 249 | + print("DEBUG: entered custom dict typing: x=", x) |
| 250 | + |
| 251 | + accepted_tuple_types = (types.Tuple, types.UniTuple) |
| 252 | + if not isinstance (x, accepted_tuple_types): |
| 253 | + return None |
| 254 | + |
| 255 | + def check_tuple_element(ty): |
| 256 | + return (isinstance(ty, accepted_tuple_types) |
| 257 | + and len(ty) == 2 |
| 258 | + and isinstance(ty[0], types.StringLiteral)) |
| 259 | + |
| 260 | + # below checks that elements are tuples with size 2 and first element is literal string |
| 261 | + if not (len(x) != 0 and all(map(check_tuple_element, x))): |
| 262 | + assert False, f"Creating LiteralStrKeyDict not supported from pairs of: {x}" |
| 263 | + |
| 264 | + # numba type-infers {'A': [1, 2, 3]} i.e. const dict of size 1 not as LiteralStrKeyDict |
| 265 | + # but as non literal dict! TO-DO: add special branch here and call literal dict ctor directly |
| 266 | + func_impl_name = 'dict_from_tuples_impl' |
| 267 | + dict_elements = ', '.join([f"x[{i}][0]:x[{i}][1]" for i in range(len(x))]) |
| 268 | + func_text = dedent(f""" |
| 269 | + def {func_impl_name}(x): |
| 270 | + res = {{{dict_elements}}} |
| 271 | + return res |
| 272 | + """) |
| 273 | + use_globals, use_locals = {}, {} |
| 274 | + # print("DEBUG: dict func_text:\n", func_text) |
| 275 | + exec(func_text, use_globals, use_locals) |
| 276 | + return use_locals[func_impl_name] |
| 277 | + |
0 commit comments