/pypy/rpython/lltypesystem/rtuple.py

https://github.com/alemacgo/pypy · Python · 139 lines · 121 code · 7 blank · 11 comment · 5 complexity · f489fce960181a4bc7f9e2f5dcfe5ff1 MD5 · raw file

  1. from pypy.tool.pairtype import pairtype
  2. from pypy.rpython.rmodel import inputconst
  3. from pypy.rpython.robject import PyObjRepr, pyobj_repr
  4. from pypy.rpython.rtuple import AbstractTupleRepr, AbstractTupleIteratorRepr
  5. from pypy.rpython.lltypesystem.lltype import \
  6. Ptr, GcStruct, Void, Signed, malloc, typeOf, nullptr
  7. from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE
  8. from pypy.rpython.lltypesystem import rstr
  9. # ____________________________________________________________
  10. #
  11. # Concrete implementation of RPython tuples:
  12. #
  13. # struct tuple {
  14. # type0 item0;
  15. # type1 item1;
  16. # type2 item2;
  17. # ...
  18. # }
  19. class TupleRepr(AbstractTupleRepr):
  20. rstr_ll = rstr.LLHelpers
  21. def __init__(self, rtyper, items_r):
  22. AbstractTupleRepr.__init__(self, rtyper, items_r)
  23. self.lowleveltype = TUPLE_TYPE(self.lltypes)
  24. def newtuple(cls, llops, r_tuple, items_v):
  25. # items_v should have the lowleveltype of the internal reprs
  26. if len(r_tuple.items_r) == 0:
  27. return inputconst(Void, ()) # a Void empty tuple
  28. c1 = inputconst(Void, r_tuple.lowleveltype.TO)
  29. cflags = inputconst(Void, {'flavor': 'gc'})
  30. v_result = llops.genop('malloc', [c1, cflags],
  31. resulttype = r_tuple.lowleveltype)
  32. for i in range(len(r_tuple.items_r)):
  33. cname = inputconst(Void, r_tuple.fieldnames[i])
  34. llops.genop('setfield', [v_result, cname, items_v[i]])
  35. return v_result
  36. newtuple = classmethod(newtuple)
  37. def instantiate(self):
  38. if len(self.items_r) == 0:
  39. return dum_empty_tuple # PBC placeholder for an empty tuple
  40. else:
  41. return malloc(self.lowleveltype.TO)
  42. def rtype_bltn_list(self, hop):
  43. from pypy.rpython.lltypesystem import rlist
  44. nitems = len(self.items_r)
  45. vtup = hop.inputarg(self, 0)
  46. LIST = hop.r_result.lowleveltype.TO
  47. cno = inputconst(Signed, nitems)
  48. vlist = hop.gendirectcall(LIST.ll_newlist, cno)
  49. v_func = hop.inputconst(Void, rlist.dum_nocheck)
  50. for index in range(nitems):
  51. name = self.fieldnames[index]
  52. ritem = self.items_r[index]
  53. cname = hop.inputconst(Void, name)
  54. vitem = hop.genop('getfield', [vtup, cname], resulttype = ritem)
  55. vitem = hop.llops.convertvar(vitem, ritem, hop.r_result.item_repr)
  56. cindex = inputconst(Signed, index)
  57. hop.gendirectcall(rlist.ll_setitem_nonneg, v_func, vlist, cindex, vitem)
  58. return vlist
  59. def getitem_internal(self, llops, v_tuple, index):
  60. """Return the index'th item, in internal repr."""
  61. name = self.fieldnames[index]
  62. llresult = self.lltypes[index]
  63. cname = inputconst(Void, name)
  64. return llops.genop('getfield', [v_tuple, cname], resulttype = llresult)
  65. def rtype_newtuple(hop):
  66. return TupleRepr._rtype_newtuple(hop)
  67. newtuple = TupleRepr.newtuple
  68. def dum_empty_tuple(): pass
  69. #
  70. # _________________________ Conversions _________________________
  71. class __extend__(pairtype(PyObjRepr, TupleRepr)):
  72. def convert_from_to((r_from, r_to), v, llops):
  73. vlist = []
  74. for i in range(len(r_to.items_r)):
  75. ci = inputconst(Signed, i)
  76. v_item = llops.gencapicall('PyTuple_GetItem_WithIncref', [v, ci],
  77. resulttype = pyobj_repr)
  78. v_converted = llops.convertvar(v_item, pyobj_repr,
  79. r_to.items_r[i])
  80. vlist.append(v_converted)
  81. return r_to.newtuple(llops, r_to, vlist)
  82. class __extend__(pairtype(TupleRepr, PyObjRepr)):
  83. def convert_from_to((r_from, r_to), v, llops):
  84. ci = inputconst(Signed, len(r_from.items_r))
  85. v_result = llops.gencapicall('PyTuple_New', [ci],
  86. resulttype = pyobj_repr)
  87. for i in range(len(r_from.items_r)):
  88. cname = inputconst(Void, r_from.fieldnames[i])
  89. v_item = llops.genop('getfield', [v, cname],
  90. resulttype = r_from.external_items_r[i].lowleveltype)
  91. v_converted = llops.convertvar(v_item, r_from.external_items_r[i],
  92. pyobj_repr)
  93. ci = inputconst(Signed, i)
  94. llops.gencapicall('PyTuple_SetItem_WithIncref', [v_result, ci,
  95. v_converted])
  96. return v_result
  97. # ____________________________________________________________
  98. #
  99. # Iteration.
  100. class Length1TupleIteratorRepr(AbstractTupleIteratorRepr):
  101. def __init__(self, r_tuple):
  102. self.r_tuple = r_tuple
  103. self.lowleveltype = Ptr(GcStruct('tuple1iter',
  104. ('tuple', r_tuple.lowleveltype)))
  105. self.ll_tupleiter = ll_tupleiter
  106. self.ll_tuplenext = ll_tuplenext
  107. TupleRepr.IteratorRepr = Length1TupleIteratorRepr
  108. def ll_tupleiter(ITERPTR, tuple):
  109. iter = malloc(ITERPTR.TO)
  110. iter.tuple = tuple
  111. return iter
  112. def ll_tuplenext(iter):
  113. # for iterating over length 1 tuples only!
  114. t = iter.tuple
  115. if t:
  116. iter.tuple = nullptr(typeOf(t).TO)
  117. return t.item0
  118. else:
  119. raise StopIteration