no list() support for <RangeRepr *>

I have the following code in my interpreter, and I'm getting an error message I haven't seen before: @specialize.call_location() def assoc(self, *kws): new_dict = {} shape = self.get_shape() for k in shape.attr_list(): new_dict[k] = shape.getter_for(k).get_value(self) for idx in unrolling_iterable(range(0, len(kws), 2)): new_dict[kws[idx]] = kws[idx + 1] return DictStruct(new_dict) It's not efficient, but it's fairly simple, we allow for something like struct.assoc(k, v, k2, v2). Specialized by call location, so I assume the *kws size is known. The unrolling_iterable should then give us constant lookup on the input tuple. However I get this error during translation: [translation:ERROR] TyperError: no list() support for <RangeRepr * GcStruct range { start, stop }> .. (rpython.rlib.unroll:27)unrolling_iterable.__init__ .. block@6[self_0...] with 1 exits .. v134 = simple_call((type list), iterable_0) [translation] start debugger...
/home/tbaldrid/oss/pypy/rpython/rtyper/rmodel.py(176)rtype_bltn_list() -> raise TyperError('no list() support for %r' % self)
I've never seen this error before...what should I be doing differently? Thanks! Timothy Baldridge

Hi Timothy, On Tue, 4 Dec 2018 at 02:31, Timothy Baldridge <tbaldridge@gmail.com> wrote:
The problem might be that the call to unrolling_iterable() should not be seen in RPython code, as far as I know. It should only occur outside compiled functions. It might be possible to rewrite your example to do that but it's not completely obvious how. Here's how I would do it instead. Use the fact that any function with ``*args`` is automatically specialized based on the number of arguments (no @specialize needed): def assoc(self, *kws): new_dict = {} shape = self.get_shape() for k in shape.attr_list(): new_dict[k] = shape.getter_for(k).get_value(self) _turn_to_dict(new_dict, kws) return DictStruct(new_dict) def _turn_to_dict(new_dict, *kws): if not kws: return # done new_dict[kws[0]] = kws[1] _turn_to_dict(new_dict, *kws[2:]) This looks like a recursive call, but it isn't: the function "_turn_to_dict_6" calls "_turn_to_dict_4", which calls "_turn_to_dict_2", etc. And at each level the tuple "kws" is replaced with individual arguments: nobody is actually making and inspecting any tuple at runtime. Most or all of the levels of calls are inlined because each function is small enough. A bientôt, Armin.

Hi Timothy, On Tue, 4 Dec 2018 at 02:31, Timothy Baldridge <tbaldridge@gmail.com> wrote:
The problem might be that the call to unrolling_iterable() should not be seen in RPython code, as far as I know. It should only occur outside compiled functions. It might be possible to rewrite your example to do that but it's not completely obvious how. Here's how I would do it instead. Use the fact that any function with ``*args`` is automatically specialized based on the number of arguments (no @specialize needed): def assoc(self, *kws): new_dict = {} shape = self.get_shape() for k in shape.attr_list(): new_dict[k] = shape.getter_for(k).get_value(self) _turn_to_dict(new_dict, kws) return DictStruct(new_dict) def _turn_to_dict(new_dict, *kws): if not kws: return # done new_dict[kws[0]] = kws[1] _turn_to_dict(new_dict, *kws[2:]) This looks like a recursive call, but it isn't: the function "_turn_to_dict_6" calls "_turn_to_dict_4", which calls "_turn_to_dict_2", etc. And at each level the tuple "kws" is replaced with individual arguments: nobody is actually making and inspecting any tuple at runtime. Most or all of the levels of calls are inlined because each function is small enough. A bientôt, Armin.
participants (2)
-
Armin Rigo
-
Timothy Baldridge