PageRenderTime 45ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/annotator/binaryop.py

https://bitbucket.org/pypy/pypy/
Python | 836 lines | 645 code | 160 blank | 31 comment | 144 complexity | 6a4c7bf26fb8919958bfbc9a20922658 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """
  2. Binary operations between SomeValues.
  3. """
  4. from collections import defaultdict
  5. from rpython.tool.pairtype import pair, pairtype
  6. from rpython.annotator.model import (
  7. SomeObject, SomeInteger, SomeBool, s_Bool, SomeString, SomeChar, SomeList,
  8. SomeDict, SomeUnicodeCodePoint, SomeUnicodeString, SomeException,
  9. SomeTuple, SomeImpossibleValue, s_ImpossibleValue, SomeInstance,
  10. SomeBuiltinMethod, SomeIterator, SomePBC, SomeNone, SomeFloat, s_None,
  11. SomeByteArray, SomeWeakRef, SomeSingleFloat,
  12. SomeLongFloat, SomeType, SomeTypeOf, SomeConstantType, unionof, UnionError,
  13. read_can_only_throw, add_knowntypedata,
  14. merge_knowntypedata,)
  15. from rpython.annotator.bookkeeper import immutablevalue, getbookkeeper
  16. from rpython.flowspace.model import Variable, Constant, const
  17. from rpython.flowspace.operation import op
  18. from rpython.rlib import rarithmetic
  19. from rpython.annotator.model import AnnotatorError
  20. BINARY_OPERATIONS = set([oper.opname for oper in op.__dict__.values()
  21. if oper.dispatch == 2])
  22. @op.is_.register(SomeObject, SomeObject)
  23. def is__default(annotator, obj1, obj2):
  24. r = SomeBool()
  25. s_obj1 = annotator.annotation(obj1)
  26. s_obj2 = annotator.annotation(obj2)
  27. if s_obj2.is_constant():
  28. if s_obj1.is_constant():
  29. r.const = s_obj1.const is s_obj2.const
  30. if s_obj2.const is None and not s_obj1.can_be_none():
  31. r.const = False
  32. elif s_obj1.is_constant():
  33. if s_obj1.const is None and not s_obj2.can_be_none():
  34. r.const = False
  35. knowntypedata = defaultdict(dict)
  36. bk = annotator.bookkeeper
  37. def bind(src_obj, tgt_obj):
  38. s_src = annotator.annotation(src_obj)
  39. s_tgt = annotator.annotation(tgt_obj)
  40. if hasattr(s_tgt, 'is_type_of') and s_src.is_constant():
  41. add_knowntypedata(
  42. knowntypedata, True,
  43. s_tgt.is_type_of,
  44. bk.valueoftype(s_src.const))
  45. add_knowntypedata(knowntypedata, True, [tgt_obj], s_src)
  46. s_nonnone = s_tgt
  47. if (s_src.is_constant() and s_src.const is None and
  48. s_tgt.can_be_none()):
  49. s_nonnone = s_tgt.nonnoneify()
  50. add_knowntypedata(knowntypedata, False, [tgt_obj], s_nonnone)
  51. bind(obj2, obj1)
  52. bind(obj1, obj2)
  53. r.set_knowntypedata(knowntypedata)
  54. return r
  55. def _make_cmp_annotator_default(cmp_op):
  56. @cmp_op.register(SomeObject, SomeObject)
  57. def default_annotate(annotator, obj1, obj2):
  58. s_1, s_2 = annotator.annotation(obj1), annotator.annotation(obj2)
  59. if s_1.is_immutable_constant() and s_2.is_immutable_constant():
  60. return immutablevalue(cmp_op.pyfunc(s_1.const, s_2.const))
  61. else:
  62. return s_Bool
  63. for cmp_op in [op.lt, op.le, op.eq, op.ne, op.gt, op.ge]:
  64. _make_cmp_annotator_default(cmp_op)
  65. @op.getitem.register(SomeObject, SomeObject)
  66. def getitem_default(ann, v_obj, v_index):
  67. return s_ImpossibleValue
  68. def _getitem_can_only_throw(s_c1, s_o2):
  69. impl = op.getitem.get_specialization(s_c1, s_o2)
  70. return read_can_only_throw(impl, s_c1, s_o2)
  71. @op.getitem_idx.register(SomeObject, SomeObject)
  72. def getitem_idx(ann, v_obj, v_index):
  73. s_obj = ann.annotation(v_obj)
  74. s_index = ann.annotation(v_index)
  75. impl = op.getitem.get_specialization(s_obj, s_index)
  76. return impl(ann, v_obj, v_index)
  77. getitem_idx.can_only_throw = _getitem_can_only_throw
  78. class __extend__(pairtype(SomeObject, SomeObject)):
  79. def union((obj1, obj2)):
  80. raise UnionError(obj1, obj2)
  81. # inplace_xxx ---> xxx by default
  82. def inplace_add((obj1, obj2)): return pair(obj1, obj2).add()
  83. def inplace_sub((obj1, obj2)): return pair(obj1, obj2).sub()
  84. def inplace_mul((obj1, obj2)): return pair(obj1, obj2).mul()
  85. def inplace_truediv((obj1, obj2)): return pair(obj1, obj2).truediv()
  86. def inplace_floordiv((obj1, obj2)): return pair(obj1, obj2).floordiv()
  87. def inplace_div((obj1, obj2)): return pair(obj1, obj2).div()
  88. def inplace_mod((obj1, obj2)): return pair(obj1, obj2).mod()
  89. def inplace_lshift((obj1, obj2)): return pair(obj1, obj2).lshift()
  90. def inplace_rshift((obj1, obj2)): return pair(obj1, obj2).rshift()
  91. def inplace_and((obj1, obj2)): return pair(obj1, obj2).and_()
  92. def inplace_or((obj1, obj2)): return pair(obj1, obj2).or_()
  93. def inplace_xor((obj1, obj2)): return pair(obj1, obj2).xor()
  94. for name, func in locals().items():
  95. if name.startswith('inplace_'):
  96. func.can_only_throw = []
  97. inplace_div.can_only_throw = [ZeroDivisionError]
  98. inplace_truediv.can_only_throw = [ZeroDivisionError]
  99. inplace_floordiv.can_only_throw = [ZeroDivisionError]
  100. inplace_mod.can_only_throw = [ZeroDivisionError]
  101. def cmp((obj1, obj2)):
  102. if obj1.is_immutable_constant() and obj2.is_immutable_constant():
  103. return immutablevalue(cmp(obj1.const, obj2.const))
  104. else:
  105. return SomeInteger()
  106. def divmod((obj1, obj2)):
  107. return SomeTuple([pair(obj1, obj2).div(), pair(obj1, obj2).mod()])
  108. def coerce((obj1, obj2)):
  109. return pair(obj1, obj2).union() # reasonable enough
  110. def add((obj1, obj2)):
  111. return s_ImpossibleValue
  112. sub = mul = truediv = floordiv = div = mod = add
  113. lshift = rshift = and_ = or_ = xor = delitem = add
  114. def setitem((obj1, obj2), _):
  115. return s_ImpossibleValue
  116. # approximation of an annotation intersection, the result should be the annotation obj or
  117. # the intersection of obj and improvement
  118. def improve((obj, improvement)):
  119. if not improvement.contains(obj) and obj.contains(improvement):
  120. return improvement
  121. else:
  122. return obj
  123. class __extend__(pairtype(SomeType, SomeType),
  124. pairtype(SomeType, SomeConstantType),
  125. pairtype(SomeConstantType, SomeType),):
  126. def union((obj1, obj2)):
  127. result = SomeType()
  128. if obj1.is_immutable_constant() and obj2.is_immutable_constant() and obj1.const == obj2.const:
  129. result.const = obj1.const
  130. return result
  131. class __extend__(pairtype(SomeTypeOf, SomeTypeOf)):
  132. def union((s_obj1, s_obj2)):
  133. vars = list(set(s_obj1.is_type_of) | set(s_obj2.is_type_of))
  134. result = SomeTypeOf(vars)
  135. if (s_obj1.is_immutable_constant() and s_obj2.is_immutable_constant()
  136. and s_obj1.const == s_obj2.const):
  137. result.const = obj1.const
  138. return result
  139. # cloning a function with identical code, for the can_only_throw attribute
  140. def _clone(f, can_only_throw = None):
  141. newfunc = type(f)(f.func_code, f.func_globals, f.func_name,
  142. f.func_defaults, f.func_closure)
  143. if can_only_throw is not None:
  144. newfunc.can_only_throw = can_only_throw
  145. return newfunc
  146. class __extend__(pairtype(SomeInteger, SomeInteger)):
  147. # unsignedness is considered a rare and contagious disease
  148. def union((int1, int2)):
  149. if int1.unsigned == int2.unsigned:
  150. knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
  151. else:
  152. t1 = int1.knowntype
  153. if t1 is bool:
  154. t1 = int
  155. t2 = int2.knowntype
  156. if t2 is bool:
  157. t2 = int
  158. if t2 is int:
  159. if int2.nonneg == False:
  160. raise UnionError(int1, int2, "RPython cannot prove that these " + \
  161. "integers are of the same signedness")
  162. knowntype = t1
  163. elif t1 is int:
  164. if int1.nonneg == False:
  165. raise UnionError(int1, int2, "RPython cannot prove that these " + \
  166. "integers are of the same signedness")
  167. knowntype = t2
  168. else:
  169. raise UnionError(int1, int2)
  170. return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
  171. knowntype=knowntype)
  172. or_ = xor = add = mul = _clone(union, [])
  173. add_ovf = mul_ovf = _clone(union, [OverflowError])
  174. div = floordiv = mod = _clone(union, [ZeroDivisionError])
  175. div_ovf= floordiv_ovf = mod_ovf = _clone(union, [ZeroDivisionError, OverflowError])
  176. def truediv((int1, int2)):
  177. return SomeFloat()
  178. truediv.can_only_throw = [ZeroDivisionError]
  179. truediv_ovf = _clone(truediv, [ZeroDivisionError, OverflowError])
  180. inplace_div = div
  181. inplace_truediv = truediv
  182. def sub((int1, int2)):
  183. knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
  184. return SomeInteger(knowntype=knowntype)
  185. sub.can_only_throw = []
  186. sub_ovf = _clone(sub, [OverflowError])
  187. def and_((int1, int2)):
  188. knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
  189. return SomeInteger(nonneg=int1.nonneg or int2.nonneg,
  190. knowntype=knowntype)
  191. and_.can_only_throw = []
  192. def lshift((int1, int2)):
  193. if isinstance(int1, SomeBool):
  194. return SomeInteger()
  195. else:
  196. return SomeInteger(knowntype=int1.knowntype)
  197. lshift.can_only_throw = []
  198. lshift_ovf = _clone(lshift, [OverflowError])
  199. def rshift((int1, int2)):
  200. if isinstance(int1, SomeBool):
  201. return SomeInteger(nonneg=True)
  202. else:
  203. return SomeInteger(nonneg=int1.nonneg, knowntype=int1.knowntype)
  204. rshift.can_only_throw = []
  205. def _make_cmp_annotator_int(cmp_op):
  206. @cmp_op.register(SomeInteger, SomeInteger)
  207. def _compare_helper(annotator, int1, int2):
  208. r = SomeBool()
  209. s_int1, s_int2 = annotator.annotation(int1), annotator.annotation(int2)
  210. if s_int1.is_immutable_constant() and s_int2.is_immutable_constant():
  211. r.const = cmp_op.pyfunc(s_int1.const, s_int2.const)
  212. #
  213. # The rest of the code propagates nonneg information between
  214. # the two arguments.
  215. #
  216. # Doing the right thing when int1 or int2 change from signed
  217. # to unsigned (r_uint) is almost impossible. See test_intcmp_bug.
  218. # Instead, we only deduce constrains on the operands in the
  219. # case where they are both signed. In other words, if y is
  220. # nonneg then "assert x>=y" will let the annotator know that
  221. # x is nonneg too, but it will not work if y is unsigned.
  222. #
  223. if not (rarithmetic.signedtype(s_int1.knowntype) and
  224. rarithmetic.signedtype(s_int2.knowntype)):
  225. return r
  226. knowntypedata = defaultdict(dict)
  227. def tointtype(s_int0):
  228. if s_int0.knowntype is bool:
  229. return int
  230. return s_int0.knowntype
  231. if s_int1.nonneg and isinstance(int2, Variable):
  232. case = cmp_op.opname in ('lt', 'le', 'eq')
  233. add_knowntypedata(knowntypedata, case, [int2],
  234. SomeInteger(nonneg=True, knowntype=tointtype(s_int2)))
  235. if s_int2.nonneg and isinstance(int1, Variable):
  236. case = cmp_op.opname in ('gt', 'ge', 'eq')
  237. add_knowntypedata(knowntypedata, case, [int1],
  238. SomeInteger(nonneg=True, knowntype=tointtype(s_int1)))
  239. r.set_knowntypedata(knowntypedata)
  240. # a special case for 'x < 0' or 'x >= 0',
  241. # where 0 is a flow graph Constant
  242. # (in this case we are sure that it cannot become a r_uint later)
  243. if (isinstance(int2, Constant) and
  244. type(int2.value) is int and # filter out Symbolics
  245. int2.value == 0):
  246. if s_int1.nonneg:
  247. if cmp_op.opname == 'lt':
  248. r.const = False
  249. if cmp_op.opname == 'ge':
  250. r.const = True
  251. return r
  252. for cmp_op in [op.lt, op.le, op.eq, op.ne, op.gt, op.ge]:
  253. _make_cmp_annotator_int(cmp_op)
  254. class __extend__(pairtype(SomeBool, SomeBool)):
  255. def union((boo1, boo2)):
  256. s = SomeBool()
  257. if getattr(boo1, 'const', -1) == getattr(boo2, 'const', -2):
  258. s.const = boo1.const
  259. if hasattr(boo1, 'knowntypedata') and \
  260. hasattr(boo2, 'knowntypedata'):
  261. ktd = merge_knowntypedata(boo1.knowntypedata, boo2.knowntypedata)
  262. s.set_knowntypedata(ktd)
  263. return s
  264. def and_((boo1, boo2)):
  265. s = SomeBool()
  266. if boo1.is_constant():
  267. if not boo1.const:
  268. s.const = False
  269. else:
  270. return boo2
  271. if boo2.is_constant():
  272. if not boo2.const:
  273. s.const = False
  274. return s
  275. def or_((boo1, boo2)):
  276. s = SomeBool()
  277. if boo1.is_constant():
  278. if boo1.const:
  279. s.const = True
  280. else:
  281. return boo2
  282. if boo2.is_constant():
  283. if boo2.const:
  284. s.const = True
  285. return s
  286. def xor((boo1, boo2)):
  287. s = SomeBool()
  288. if boo1.is_constant() and boo2.is_constant():
  289. s.const = boo1.const ^ boo2.const
  290. return s
  291. class __extend__(pairtype(SomeString, SomeString)):
  292. def union((str1, str2)):
  293. can_be_None = str1.can_be_None or str2.can_be_None
  294. no_nul = str1.no_nul and str2.no_nul
  295. return SomeString(can_be_None=can_be_None, no_nul=no_nul)
  296. def add((str1, str2)):
  297. # propagate const-ness to help getattr(obj, 'prefix' + const_name)
  298. result = SomeString(no_nul=str1.no_nul and str2.no_nul)
  299. if str1.is_immutable_constant() and str2.is_immutable_constant():
  300. result.const = str1.const + str2.const
  301. return result
  302. class __extend__(pairtype(SomeByteArray, SomeByteArray)):
  303. def union((b1, b2)):
  304. can_be_None = b1.can_be_None or b2.can_be_None
  305. return SomeByteArray(can_be_None=can_be_None)
  306. def add((b1, b2)):
  307. return SomeByteArray()
  308. class __extend__(pairtype(SomeByteArray, SomeInteger)):
  309. def getitem((s_b, s_i)):
  310. return SomeInteger()
  311. def setitem((s_b, s_i), s_i2):
  312. assert isinstance(s_i2, SomeInteger)
  313. class __extend__(pairtype(SomeString, SomeByteArray),
  314. pairtype(SomeByteArray, SomeString),
  315. pairtype(SomeChar, SomeByteArray),
  316. pairtype(SomeByteArray, SomeChar)):
  317. def add((b1, b2)):
  318. return SomeByteArray()
  319. class __extend__(pairtype(SomeChar, SomeChar)):
  320. def union((chr1, chr2)):
  321. no_nul = chr1.no_nul and chr2.no_nul
  322. return SomeChar(no_nul=no_nul)
  323. class __extend__(pairtype(SomeChar, SomeUnicodeCodePoint),
  324. pairtype(SomeUnicodeCodePoint, SomeChar)):
  325. def union((uchr1, uchr2)):
  326. return SomeUnicodeCodePoint()
  327. class __extend__(pairtype(SomeUnicodeCodePoint, SomeUnicodeCodePoint)):
  328. def union((uchr1, uchr2)):
  329. no_nul = uchr1.no_nul and uchr2.no_nul
  330. return SomeUnicodeCodePoint(no_nul=no_nul)
  331. def add((chr1, chr2)):
  332. return SomeUnicodeString()
  333. class __extend__(pairtype(SomeString, SomeUnicodeString),
  334. pairtype(SomeUnicodeString, SomeString)):
  335. def mod((str, unistring)):
  336. raise AnnotatorError(
  337. "string formatting mixing strings and unicode not supported")
  338. class __extend__(pairtype(SomeString, SomeTuple),
  339. pairtype(SomeUnicodeString, SomeTuple)):
  340. def mod((s_string, s_tuple)):
  341. if not s_string.is_constant():
  342. raise AnnotatorError("string formatting requires a constant "
  343. "string/unicode on the left of '%'")
  344. is_string = isinstance(s_string, SomeString)
  345. is_unicode = isinstance(s_string, SomeUnicodeString)
  346. assert is_string or is_unicode
  347. for s_item in s_tuple.items:
  348. if (is_unicode and isinstance(s_item, (SomeChar, SomeString)) or
  349. is_string and isinstance(s_item, (SomeUnicodeCodePoint,
  350. SomeUnicodeString))):
  351. raise AnnotatorError(
  352. "string formatting mixing strings and unicode not supported")
  353. no_nul = s_string.no_nul
  354. for s_item in s_tuple.items:
  355. if isinstance(s_item, SomeFloat):
  356. pass # or s_item is a subclass, like SomeInteger
  357. elif (isinstance(s_item, SomeString) or
  358. isinstance(s_item, SomeUnicodeString)) and s_item.no_nul:
  359. pass
  360. else:
  361. no_nul = False
  362. break
  363. return s_string.__class__(no_nul=no_nul)
  364. class __extend__(pairtype(SomeString, SomeObject),
  365. pairtype(SomeUnicodeString, SomeObject)):
  366. def mod((s_string, s_arg)):
  367. assert not isinstance(s_arg, SomeTuple)
  368. return pair(s_string, SomeTuple([s_arg])).mod()
  369. class __extend__(pairtype(SomeFloat, SomeFloat)):
  370. def union((flt1, flt2)):
  371. return SomeFloat()
  372. add = sub = mul = union
  373. def div((flt1, flt2)):
  374. return SomeFloat()
  375. div.can_only_throw = []
  376. truediv = div
  377. # repeat these in order to copy the 'can_only_throw' attribute
  378. inplace_div = div
  379. inplace_truediv = truediv
  380. class __extend__(pairtype(SomeSingleFloat, SomeSingleFloat)):
  381. def union((flt1, flt2)):
  382. return SomeSingleFloat()
  383. class __extend__(pairtype(SomeLongFloat, SomeLongFloat)):
  384. def union((flt1, flt2)):
  385. return SomeLongFloat()
  386. class __extend__(pairtype(SomeList, SomeList)):
  387. def union((lst1, lst2)):
  388. return SomeList(lst1.listdef.union(lst2.listdef))
  389. def add((lst1, lst2)):
  390. bk = getbookkeeper()
  391. return lst1.listdef.offspring(bk, lst2.listdef)
  392. def eq((lst1, lst2)):
  393. lst1.listdef.agree(getbookkeeper(), lst2.listdef)
  394. return s_Bool
  395. ne = eq
  396. class __extend__(pairtype(SomeList, SomeObject)):
  397. def inplace_add((lst1, obj2)):
  398. lst1.method_extend(obj2)
  399. return lst1
  400. inplace_add.can_only_throw = []
  401. def inplace_mul((lst1, obj2)):
  402. lst1.listdef.resize()
  403. return lst1
  404. inplace_mul.can_only_throw = []
  405. class __extend__(pairtype(SomeTuple, SomeTuple)):
  406. def union((tup1, tup2)):
  407. if len(tup1.items) != len(tup2.items):
  408. raise UnionError(tup1, tup2, "RPython cannot unify tuples of "
  409. "different length: %d versus %d" % \
  410. (len(tup1.items), len(tup2.items)))
  411. else:
  412. unions = [unionof(x,y) for x,y in zip(tup1.items, tup2.items)]
  413. return SomeTuple(items = unions)
  414. def add((tup1, tup2)):
  415. return SomeTuple(items = tup1.items + tup2.items)
  416. def eq(tup1tup2):
  417. tup1tup2.union()
  418. return s_Bool
  419. ne = eq
  420. def lt((tup1, tup2)):
  421. raise Exception("unsupported: (...) < (...)")
  422. def le((tup1, tup2)):
  423. raise Exception("unsupported: (...) <= (...)")
  424. def gt((tup1, tup2)):
  425. raise Exception("unsupported: (...) > (...)")
  426. def ge((tup1, tup2)):
  427. raise Exception("unsupported: (...) >= (...)")
  428. class __extend__(pairtype(SomeDict, SomeDict)):
  429. def union((dic1, dic2)):
  430. assert dic1.__class__ == dic2.__class__
  431. return dic1.__class__(dic1.dictdef.union(dic2.dictdef))
  432. def _dict_can_only_throw_keyerror(s_dct, *ignore):
  433. if s_dct.dictdef.dictkey.custom_eq_hash:
  434. return None # r_dict: can throw anything
  435. return [KeyError]
  436. def _dict_can_only_throw_nothing(s_dct, *ignore):
  437. if s_dct.dictdef.dictkey.custom_eq_hash:
  438. return None # r_dict: can throw anything
  439. return [] # else: no possible exception
  440. @op.getitem.register(SomeDict, SomeObject)
  441. def getitem_SomeDict(annotator, v_dict, v_key):
  442. s_dict = annotator.annotation(v_dict)
  443. s_key = annotator.annotation(v_key)
  444. s_dict.dictdef.generalize_key(s_key)
  445. position = annotator.bookkeeper.position_key
  446. return s_dict.dictdef.read_value(position)
  447. getitem_SomeDict.can_only_throw = _dict_can_only_throw_keyerror
  448. class __extend__(pairtype(SomeDict, SomeObject)):
  449. def setitem((dic1, obj2), s_value):
  450. dic1.dictdef.generalize_key(obj2)
  451. dic1.dictdef.generalize_value(s_value)
  452. setitem.can_only_throw = _dict_can_only_throw_nothing
  453. def delitem((dic1, obj2)):
  454. dic1.dictdef.generalize_key(obj2)
  455. delitem.can_only_throw = _dict_can_only_throw_keyerror
  456. class __extend__(pairtype(SomeTuple, SomeInteger)):
  457. def getitem((tup1, int2)):
  458. if int2.is_immutable_constant():
  459. try:
  460. return tup1.items[int2.const]
  461. except IndexError:
  462. return s_ImpossibleValue
  463. else:
  464. return unionof(*tup1.items)
  465. getitem.can_only_throw = [IndexError]
  466. class __extend__(pairtype(SomeList, SomeInteger)):
  467. def mul((lst1, int2)):
  468. bk = getbookkeeper()
  469. return lst1.listdef.offspring(bk)
  470. def getitem((lst1, int2)):
  471. position = getbookkeeper().position_key
  472. return lst1.listdef.read_item(position)
  473. getitem.can_only_throw = []
  474. def getitem_idx((lst1, int2)):
  475. position = getbookkeeper().position_key
  476. return lst1.listdef.read_item(position)
  477. getitem_idx.can_only_throw = [IndexError]
  478. def setitem((lst1, int2), s_value):
  479. lst1.listdef.mutate()
  480. lst1.listdef.generalize(s_value)
  481. setitem.can_only_throw = [IndexError]
  482. def delitem((lst1, int2)):
  483. lst1.listdef.resize()
  484. delitem.can_only_throw = [IndexError]
  485. class __extend__(pairtype(SomeString, SomeInteger)):
  486. def getitem((str1, int2)):
  487. return SomeChar(no_nul=str1.no_nul)
  488. getitem.can_only_throw = []
  489. def getitem_idx((str1, int2)):
  490. return SomeChar(no_nul=str1.no_nul)
  491. getitem_idx.can_only_throw = [IndexError]
  492. def mul((str1, int2)): # xxx do we want to support this
  493. return SomeString(no_nul=str1.no_nul)
  494. class __extend__(pairtype(SomeUnicodeString, SomeInteger)):
  495. def getitem((str1, int2)):
  496. return SomeUnicodeCodePoint(no_nul=str1.no_nul)
  497. getitem.can_only_throw = []
  498. def getitem_idx((str1, int2)):
  499. return SomeUnicodeCodePoint(no_nul=str1.no_nul)
  500. getitem_idx.can_only_throw = [IndexError]
  501. def mul((str1, int2)): # xxx do we want to support this
  502. return SomeUnicodeString(no_nul=str1.no_nul)
  503. class __extend__(pairtype(SomeInteger, SomeString),
  504. pairtype(SomeInteger, SomeUnicodeString)):
  505. def mul((int1, str2)): # xxx do we want to support this
  506. return str2.basestringclass(no_nul=str2.no_nul)
  507. class __extend__(pairtype(SomeUnicodeCodePoint, SomeUnicodeString),
  508. pairtype(SomeUnicodeString, SomeUnicodeCodePoint),
  509. pairtype(SomeUnicodeString, SomeUnicodeString)):
  510. def union((str1, str2)):
  511. can_be_None = str1.can_be_None or str2.can_be_None
  512. no_nul = str1.no_nul and str2.no_nul
  513. return SomeUnicodeString(can_be_None=can_be_None, no_nul=no_nul)
  514. def add((str1, str2)):
  515. # propagate const-ness to help getattr(obj, 'prefix' + const_name)
  516. result = SomeUnicodeString(no_nul=str1.no_nul and str2.no_nul)
  517. if str1.is_immutable_constant() and str2.is_immutable_constant():
  518. result.const = str1.const + str2.const
  519. return result
  520. class __extend__(pairtype(SomeInteger, SomeList)):
  521. def mul((int1, lst2)):
  522. bk = getbookkeeper()
  523. return lst2.listdef.offspring(bk)
  524. class __extend__(pairtype(SomeInstance, SomeInstance)):
  525. def union((ins1, ins2)):
  526. if ins1.classdef is None or ins2.classdef is None:
  527. # special case only
  528. basedef = None
  529. else:
  530. basedef = ins1.classdef.commonbase(ins2.classdef)
  531. if basedef is None:
  532. raise UnionError(ins1, ins2, "RPython cannot unify instances "
  533. "with no common base class")
  534. flags = ins1.flags
  535. if flags:
  536. flags = flags.copy()
  537. for key, value in flags.items():
  538. if key not in ins2.flags or ins2.flags[key] != value:
  539. del flags[key]
  540. return SomeInstance(basedef,
  541. can_be_None=ins1.can_be_None or ins2.can_be_None,
  542. flags=flags)
  543. def improve((ins1, ins2)):
  544. if ins1.classdef is None:
  545. resdef = ins2.classdef
  546. elif ins2.classdef is None:
  547. resdef = ins1.classdef
  548. else:
  549. basedef = ins1.classdef.commonbase(ins2.classdef)
  550. if basedef is ins1.classdef:
  551. resdef = ins2.classdef
  552. elif basedef is ins2.classdef:
  553. resdef = ins1.classdef
  554. else:
  555. if ins1.can_be_None and ins2.can_be_None:
  556. return s_None
  557. else:
  558. return s_ImpossibleValue
  559. res = SomeInstance(resdef, can_be_None=ins1.can_be_None and ins2.can_be_None)
  560. if ins1.contains(res) and ins2.contains(res):
  561. return res # fine
  562. else:
  563. # this case can occur in the presence of 'const' attributes,
  564. # which we should try to preserve. Fall-back...
  565. thistype = pairtype(SomeInstance, SomeInstance)
  566. return super(thistype, pair(ins1, ins2)).improve()
  567. class __extend__(
  568. pairtype(SomeException, SomeInstance),
  569. pairtype(SomeException, SomeNone)):
  570. def union((s_exc, s_inst)):
  571. return unionof(s_exc.as_SomeInstance(), s_inst)
  572. class __extend__(
  573. pairtype(SomeInstance, SomeException),
  574. pairtype(SomeNone, SomeException)):
  575. def union((s_inst, s_exc)):
  576. return unionof(s_exc.as_SomeInstance(), s_inst)
  577. class __extend__(pairtype(SomeException, SomeException)):
  578. def union((s_exc1, s_exc2)):
  579. return SomeException(s_exc1.classdefs | s_exc2.classdefs)
  580. @op.getitem.register_transform(SomeInstance, SomeObject)
  581. def getitem_SomeInstance(annotator, v_ins, v_idx):
  582. get_getitem = op.getattr(v_ins, const('__getitem__'))
  583. return [get_getitem, op.simple_call(get_getitem.result, v_idx)]
  584. @op.setitem.register_transform(SomeInstance, SomeObject)
  585. def setitem_SomeInstance(annotator, v_ins, v_idx, v_value):
  586. get_setitem = op.getattr(v_ins, const('__setitem__'))
  587. return [get_setitem,
  588. op.simple_call(get_setitem.result, v_idx, v_value)]
  589. class __extend__(pairtype(SomeIterator, SomeIterator)):
  590. def union((iter1, iter2)):
  591. s_cont = unionof(iter1.s_container, iter2.s_container)
  592. if iter1.variant != iter2.variant:
  593. raise UnionError(iter1, iter2,
  594. "RPython cannot unify incompatible iterator variants")
  595. return SomeIterator(s_cont, *iter1.variant)
  596. class __extend__(pairtype(SomeBuiltinMethod, SomeBuiltinMethod)):
  597. def union((bltn1, bltn2)):
  598. if (bltn1.analyser != bltn2.analyser or
  599. bltn1.methodname != bltn2.methodname):
  600. raise UnionError(bltn1, bltn2)
  601. s_self = unionof(bltn1.s_self, bltn2.s_self)
  602. return SomeBuiltinMethod(bltn1.analyser, s_self,
  603. methodname=bltn1.methodname)
  604. @op.is_.register(SomePBC, SomePBC)
  605. def is__PBC_PBC(annotator, pbc1, pbc2):
  606. s = is__default(annotator, pbc1, pbc2)
  607. if not s.is_constant():
  608. s_pbc1 = annotator.annotation(pbc1)
  609. s_pbc2 = annotator.annotation(pbc2)
  610. if not s_pbc1.can_be_None or not s_pbc2.can_be_None:
  611. for desc in s_pbc1.descriptions:
  612. if desc in s_pbc2.descriptions:
  613. break
  614. else:
  615. s.const = False # no common desc in the two sets
  616. return s
  617. class __extend__(pairtype(SomePBC, SomePBC)):
  618. def union((pbc1, pbc2)):
  619. d = pbc1.descriptions.copy()
  620. d.update(pbc2.descriptions)
  621. return SomePBC(d, can_be_None = pbc1.can_be_None or pbc2.can_be_None)
  622. class __extend__(pairtype(SomeImpossibleValue, SomeObject)):
  623. def union((imp1, obj2)):
  624. return obj2
  625. class __extend__(pairtype(SomeObject, SomeImpossibleValue)):
  626. def union((obj1, imp2)):
  627. return obj1
  628. # mixing Nones with other objects
  629. class __extend__(pairtype(SomeObject, SomeNone)):
  630. def union((obj, none)):
  631. return obj.noneify()
  632. class __extend__(pairtype(SomeNone, SomeObject)):
  633. def union((none, obj)):
  634. return obj.noneify()
  635. class __extend__(pairtype(SomeImpossibleValue, SomeNone)):
  636. def union((imp1, none)):
  637. return s_None
  638. class __extend__(pairtype(SomeNone, SomeImpossibleValue)):
  639. def union((none, imp2)):
  640. return s_None
  641. class __extend__(pairtype(SomePBC, SomeObject)):
  642. def getitem((pbc, o)):
  643. raise AnnotatorError("getitem on %r" % pbc)
  644. def setitem((pbc, o), s_value):
  645. raise AnnotatorError("setitem on %r" % pbc)
  646. class __extend__(pairtype(SomeNone, SomeObject)):
  647. def getitem((none, o)):
  648. return s_ImpossibleValue
  649. getitem.can_only_throw = []
  650. def setitem((none, o), s_value):
  651. return None
  652. class __extend__(pairtype(SomePBC, SomeString)):
  653. def add((pbc, o)):
  654. raise AnnotatorError('add on %r' % pbc)
  655. class __extend__(pairtype(SomeNone, SomeString)):
  656. def add((none, o)):
  657. return s_ImpossibleValue
  658. class __extend__(pairtype(SomeString, SomePBC)):
  659. def add((o, pbc)):
  660. raise AnnotatorError('add on %r' % pbc)
  661. class __extend__(pairtype(SomeString, SomeNone)):
  662. def add((o, none)):
  663. return s_ImpossibleValue
  664. #_________________________________________
  665. # weakrefs
  666. class __extend__(pairtype(SomeWeakRef, SomeWeakRef)):
  667. def union((s_wrf1, s_wrf2)):
  668. if s_wrf1.classdef is None:
  669. basedef = s_wrf2.classdef # s_wrf1 is known to be dead
  670. elif s_wrf2.classdef is None:
  671. basedef = s_wrf1.classdef # s_wrf2 is known to be dead
  672. else:
  673. basedef = s_wrf1.classdef.commonbase(s_wrf2.classdef)
  674. if basedef is None: # no common base class! complain...
  675. raise UnionError(s_wrf1, s_wrf2)
  676. return SomeWeakRef(basedef)