PageRenderTime 63ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/annotation/unaryop.py

https://bitbucket.org/pypy/pypy/
Python | 886 lines | 763 code | 111 blank | 12 comment | 58 complexity | 37ed9eed63f6b5f3cb6e54ae98e1a2f3 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """
  2. Unary operations on SomeValues.
  3. """
  4. from types import MethodType
  5. from pypy.annotation.model import \
  6. SomeObject, SomeInteger, SomeBool, SomeString, SomeChar, SomeList, \
  7. SomeDict, SomeTuple, SomeImpossibleValue, SomeUnicodeCodePoint, \
  8. SomeInstance, SomeBuiltin, SomeFloat, SomeIterator, SomePBC, \
  9. SomeExternalObject, SomeTypedAddressAccess, SomeAddress, \
  10. s_ImpossibleValue, s_Bool, s_None, \
  11. unionof, missing_operation, add_knowntypedata, HarmlesslyBlocked, \
  12. SomeGenericCallable, SomeWeakRef, SomeUnicodeString
  13. from pypy.annotation.bookkeeper import getbookkeeper
  14. from pypy.annotation import builtin
  15. from pypy.annotation.binaryop import _clone ## XXX where to put this?
  16. from pypy.rpython import extregistry
  17. from pypy.tool.error import AnnotatorError
  18. # convenience only!
  19. def immutablevalue(x):
  20. return getbookkeeper().immutablevalue(x)
  21. UNARY_OPERATIONS = set(['len', 'is_true', 'getattr', 'setattr', 'delattr',
  22. 'simple_call', 'call_args', 'str', 'repr',
  23. 'iter', 'next', 'invert', 'type', 'issubtype',
  24. 'pos', 'neg', 'nonzero', 'abs', 'hex', 'oct',
  25. 'ord', 'int', 'float', 'long',
  26. 'hash', 'id', # <== not supported any more
  27. 'getslice', 'setslice', 'delslice',
  28. 'neg_ovf', 'abs_ovf', 'hint', 'unicode', 'unichr'])
  29. for opname in UNARY_OPERATIONS:
  30. missing_operation(SomeObject, opname)
  31. class __extend__(SomeObject):
  32. def type(obj, *moreargs):
  33. if moreargs:
  34. raise Exception, 'type() called with more than one argument'
  35. if obj.is_constant():
  36. if isinstance(obj, SomeInstance):
  37. r = SomePBC([obj.classdef.classdesc])
  38. else:
  39. r = immutablevalue(obj.knowntype)
  40. else:
  41. r = SomeObject()
  42. r.knowntype = type
  43. bk = getbookkeeper()
  44. fn, block, i = bk.position_key
  45. annotator = bk.annotator
  46. op = block.operations[i]
  47. assert op.opname == "type"
  48. assert len(op.args) == 1
  49. assert annotator.binding(op.args[0]) == obj
  50. r.is_type_of = [op.args[0]]
  51. return r
  52. def issubtype(obj, s_cls):
  53. if hasattr(obj, 'is_type_of'):
  54. vars = obj.is_type_of
  55. annotator = getbookkeeper().annotator
  56. return builtin.builtin_isinstance(annotator.binding(vars[0]),
  57. s_cls, vars)
  58. if obj.is_constant() and s_cls.is_constant():
  59. return immutablevalue(issubclass(obj.const, s_cls.const))
  60. return s_Bool
  61. def len(obj):
  62. return SomeInteger(nonneg=True)
  63. def is_true_behavior(obj, s):
  64. if obj.is_immutable_constant():
  65. s.const = bool(obj.const)
  66. else:
  67. s_len = obj.len()
  68. if s_len.is_immutable_constant():
  69. s.const = s_len.const > 0
  70. def is_true(s_obj):
  71. r = SomeBool()
  72. s_obj.is_true_behavior(r)
  73. bk = getbookkeeper()
  74. knowntypedata = r.knowntypedata = {}
  75. fn, block, i = bk.position_key
  76. op = block.operations[i]
  77. assert op.opname == "is_true" or op.opname == "nonzero"
  78. assert len(op.args) == 1
  79. arg = op.args[0]
  80. s_nonnone_obj = s_obj
  81. if s_obj.can_be_none():
  82. s_nonnone_obj = s_obj.nonnoneify()
  83. add_knowntypedata(knowntypedata, True, [arg], s_nonnone_obj)
  84. return r
  85. def nonzero(obj):
  86. return obj.is_true()
  87. def hash(obj):
  88. raise TypeError, ("cannot use hash() in RPython; "
  89. "see objectmodel.compute_xxx()")
  90. def str(obj):
  91. getbookkeeper().count('str', obj)
  92. return SomeString()
  93. def unicode(obj):
  94. getbookkeeper().count('unicode', obj)
  95. return SomeUnicodeString()
  96. def repr(obj):
  97. getbookkeeper().count('repr', obj)
  98. return SomeString()
  99. def hex(obj):
  100. getbookkeeper().count('hex', obj)
  101. return SomeString()
  102. def oct(obj):
  103. getbookkeeper().count('oct', obj)
  104. return SomeString()
  105. def id(obj):
  106. raise Exception("cannot use id() in RPython; "
  107. "see objectmodel.compute_xxx()")
  108. def int(obj):
  109. return SomeInteger()
  110. def float(obj):
  111. return SomeFloat()
  112. def long(obj):
  113. return SomeObject() # XXX
  114. def delattr(obj, s_attr):
  115. if obj.__class__ != SomeObject or obj.knowntype != object:
  116. getbookkeeper().warning(
  117. ("delattr on potentally non-SomeObjects is not RPythonic: delattr(%r,%r)" %
  118. (obj, s_attr)))
  119. def find_method(obj, name):
  120. "Look for a special-case implementation for the named method."
  121. try:
  122. analyser = getattr(obj.__class__, 'method_' + name)
  123. except AttributeError:
  124. return None
  125. else:
  126. return SomeBuiltin(analyser, obj, name)
  127. def getattr(obj, s_attr):
  128. # get a SomeBuiltin if the SomeObject has
  129. # a corresponding method to handle it
  130. if s_attr.is_constant() and isinstance(s_attr.const, str):
  131. attr = s_attr.const
  132. s_method = obj.find_method(attr)
  133. if s_method is not None:
  134. return s_method
  135. # if the SomeObject is itself a constant, allow reading its attrs
  136. if obj.is_immutable_constant() and hasattr(obj.const, attr):
  137. return immutablevalue(getattr(obj.const, attr))
  138. else:
  139. getbookkeeper().warning('getattr(%r, %r) is not RPythonic enough' %
  140. (obj, s_attr))
  141. return SomeObject()
  142. getattr.can_only_throw = []
  143. def bind_callables_under(obj, classdef, name):
  144. return obj # default unbound __get__ implementation
  145. def simple_call(obj, *args_s):
  146. return obj.call(getbookkeeper().build_args("simple_call", args_s))
  147. def call_args(obj, *args_s):
  148. return obj.call(getbookkeeper().build_args("call_args", args_s))
  149. def call(obj, args, implicit_init=False):
  150. #raise Exception, "cannot follow call_args%r" % ((obj, args),)
  151. getbookkeeper().warning("cannot follow call(%r, %r)" % (obj, args))
  152. return SomeObject()
  153. def op_contains(obj, s_element):
  154. return s_Bool
  155. op_contains.can_only_throw = []
  156. def hint(self, *args_s):
  157. return self
  158. class __extend__(SomeFloat):
  159. def pos(flt):
  160. return flt
  161. def neg(flt):
  162. return SomeFloat()
  163. abs = neg
  164. def is_true(self):
  165. if self.is_immutable_constant():
  166. return getbookkeeper().immutablevalue(bool(self.const))
  167. return s_Bool
  168. class __extend__(SomeInteger):
  169. def invert(self):
  170. return SomeInteger(knowntype=self.knowntype)
  171. invert.can_only_throw = []
  172. def pos(self):
  173. return SomeInteger(knowntype=self.knowntype)
  174. pos.can_only_throw = []
  175. int = pos
  176. # these are the only ones which can overflow:
  177. def neg(self):
  178. return SomeInteger(knowntype=self.knowntype)
  179. neg.can_only_throw = []
  180. neg_ovf = _clone(neg, [OverflowError])
  181. def abs(self):
  182. return SomeInteger(nonneg=True, knowntype=self.knowntype)
  183. abs.can_only_throw = []
  184. abs_ovf = _clone(abs, [OverflowError])
  185. class __extend__(SomeBool):
  186. def is_true(self):
  187. return self
  188. def invert(self):
  189. return SomeInteger()
  190. invert.can_only_throw = []
  191. def neg(self):
  192. return SomeInteger()
  193. neg.can_only_throw = []
  194. neg_ovf = _clone(neg, [OverflowError])
  195. def abs(self):
  196. return SomeInteger(nonneg=True)
  197. abs.can_only_throw = []
  198. abs_ovf = _clone(abs, [OverflowError])
  199. def pos(self):
  200. return SomeInteger(nonneg=True)
  201. pos.can_only_throw = []
  202. int = pos
  203. class __extend__(SomeTuple):
  204. def len(tup):
  205. return immutablevalue(len(tup.items))
  206. def iter(tup):
  207. getbookkeeper().count("tuple_iter", tup)
  208. return SomeIterator(tup)
  209. iter.can_only_throw = []
  210. def getanyitem(tup):
  211. return unionof(*tup.items)
  212. def getslice(tup, s_start, s_stop):
  213. assert s_start.is_immutable_constant(),"tuple slicing: needs constants"
  214. assert s_stop.is_immutable_constant(), "tuple slicing: needs constants"
  215. items = tup.items[s_start.const:s_stop.const]
  216. return SomeTuple(items)
  217. class __extend__(SomeList):
  218. def method_append(lst, s_value):
  219. lst.listdef.resize()
  220. lst.listdef.generalize(s_value)
  221. def method_extend(lst, s_iterable):
  222. lst.listdef.resize()
  223. if isinstance(s_iterable, SomeList): # unify the two lists
  224. lst.listdef.agree(s_iterable.listdef)
  225. else:
  226. s_iter = s_iterable.iter()
  227. lst.method_append(s_iter.next())
  228. def method_reverse(lst):
  229. lst.listdef.mutate()
  230. def method_insert(lst, s_index, s_value):
  231. lst.method_append(s_value)
  232. def method_remove(lst, s_value):
  233. lst.listdef.resize()
  234. lst.listdef.generalize(s_value)
  235. def method_pop(lst, s_index=None):
  236. lst.listdef.resize()
  237. return lst.listdef.read_item()
  238. method_pop.can_only_throw = [IndexError]
  239. def method_index(lst, s_value):
  240. getbookkeeper().count("list_index")
  241. lst.listdef.generalize(s_value)
  242. return SomeInteger(nonneg=True)
  243. def len(lst):
  244. s_item = lst.listdef.read_item()
  245. if isinstance(s_item, SomeImpossibleValue):
  246. return immutablevalue(0)
  247. return SomeObject.len(lst)
  248. def iter(lst):
  249. return SomeIterator(lst)
  250. iter.can_only_throw = []
  251. def getanyitem(lst):
  252. return lst.listdef.read_item()
  253. def op_contains(lst, s_element):
  254. lst.listdef.generalize(s_element)
  255. return s_Bool
  256. op_contains.can_only_throw = []
  257. def hint(lst, *args_s):
  258. hints = args_s[-1].const
  259. if 'maxlength' in hints:
  260. # only for iteration over lists or dicts at the moment,
  261. # not over an iterator object (because it has no known length)
  262. s_iterable = args_s[0]
  263. if isinstance(s_iterable, (SomeList, SomeDict)):
  264. lst = SomeList(lst.listdef) # create a fresh copy
  265. lst.known_maxlength = True
  266. lst.listdef.resize()
  267. lst.listdef.listitem.hint_maxlength = True
  268. elif 'fence' in hints:
  269. lst = lst.listdef.offspring()
  270. return lst
  271. def getslice(lst, s_start, s_stop):
  272. check_negative_slice(s_start, s_stop)
  273. return lst.listdef.offspring()
  274. def setslice(lst, s_start, s_stop, s_iterable):
  275. check_negative_slice(s_start, s_stop)
  276. if not isinstance(s_iterable, SomeList):
  277. raise Exception("list[start:stop] = x: x must be a list")
  278. lst.listdef.mutate()
  279. lst.listdef.agree(s_iterable.listdef)
  280. # note that setslice is not allowed to resize a list in RPython
  281. def delslice(lst, s_start, s_stop):
  282. check_negative_slice(s_start, s_stop)
  283. lst.listdef.resize()
  284. def check_negative_slice(s_start, s_stop):
  285. if isinstance(s_start, SomeInteger) and not s_start.nonneg:
  286. raise TypeError("slicing: not proven to have non-negative start")
  287. if isinstance(s_stop, SomeInteger) and not s_stop.nonneg and \
  288. getattr(s_stop, 'const', 0) != -1:
  289. raise TypeError("slicing: not proven to have non-negative stop")
  290. class __extend__(SomeDict):
  291. def _is_empty(dct):
  292. s_key = dct.dictdef.read_key()
  293. s_value = dct.dictdef.read_value()
  294. return (isinstance(s_key, SomeImpossibleValue) or
  295. isinstance(s_value, SomeImpossibleValue))
  296. def len(dct):
  297. if dct._is_empty():
  298. return immutablevalue(0)
  299. return SomeObject.len(dct)
  300. def iter(dct):
  301. return SomeIterator(dct)
  302. iter.can_only_throw = []
  303. def getanyitem(dct, variant='keys'):
  304. if variant == 'keys':
  305. return dct.dictdef.read_key()
  306. elif variant == 'values':
  307. return dct.dictdef.read_value()
  308. elif variant == 'items':
  309. s_key = dct.dictdef.read_key()
  310. s_value = dct.dictdef.read_value()
  311. if (isinstance(s_key, SomeImpossibleValue) or
  312. isinstance(s_value, SomeImpossibleValue)):
  313. return s_ImpossibleValue
  314. else:
  315. return SomeTuple((s_key, s_value))
  316. else:
  317. raise ValueError
  318. def method_get(dct, key, dfl):
  319. dct.dictdef.generalize_key(key)
  320. dct.dictdef.generalize_value(dfl)
  321. return dct.dictdef.read_value()
  322. method_setdefault = method_get
  323. def method_copy(dct):
  324. return SomeDict(dct.dictdef)
  325. def method_update(dct1, dct2):
  326. if s_None.contains(dct2):
  327. return SomeImpossibleValue()
  328. dct1.dictdef.union(dct2.dictdef)
  329. def method_keys(dct):
  330. return getbookkeeper().newlist(dct.dictdef.read_key())
  331. def method_values(dct):
  332. return getbookkeeper().newlist(dct.dictdef.read_value())
  333. def method_items(dct):
  334. return getbookkeeper().newlist(dct.getanyitem('items'))
  335. def method_iterkeys(dct):
  336. return SomeIterator(dct, 'keys')
  337. def method_itervalues(dct):
  338. return SomeIterator(dct, 'values')
  339. def method_iteritems(dct):
  340. return SomeIterator(dct, 'items')
  341. def method_clear(dct):
  342. pass
  343. def method_popitem(dct):
  344. return dct.getanyitem('items')
  345. def method_pop(dct, s_key, s_dfl=None):
  346. dct.dictdef.generalize_key(s_key)
  347. if s_dfl is not None:
  348. dct.dictdef.generalize_value(s_dfl)
  349. return dct.dictdef.read_value()
  350. def _can_only_throw(dic, *ignore):
  351. if dic1.dictdef.dictkey.custom_eq_hash:
  352. return None # r_dict: can throw anything
  353. return [] # else: no possible exception
  354. def op_contains(dct, s_element):
  355. dct.dictdef.generalize_key(s_element)
  356. if dct._is_empty():
  357. s_bool = SomeBool()
  358. s_bool.const = False
  359. return s_bool
  360. return s_Bool
  361. op_contains.can_only_throw = _can_only_throw
  362. class __extend__(SomeString,
  363. SomeUnicodeString):
  364. def method_startswith(str, frag):
  365. return s_Bool
  366. def method_endswith(str, frag):
  367. return s_Bool
  368. def method_find(str, frag, start=None, end=None):
  369. return SomeInteger()
  370. def method_rfind(str, frag, start=None, end=None):
  371. return SomeInteger()
  372. def method_count(str, frag, start=None, end=None):
  373. return SomeInteger(nonneg=True)
  374. def method_strip(str, chr):
  375. return str.basestringclass(no_nul=str.no_nul)
  376. def method_lstrip(str, chr):
  377. return str.basestringclass(no_nul=str.no_nul)
  378. def method_rstrip(str, chr):
  379. return str.basestringclass(no_nul=str.no_nul)
  380. def method_join(str, s_list):
  381. if s_None.contains(s_list):
  382. return SomeImpossibleValue()
  383. getbookkeeper().count("str_join", str)
  384. s_item = s_list.listdef.read_item()
  385. if isinstance(s_item, SomeImpossibleValue):
  386. if isinstance(str, SomeUnicodeString):
  387. return immutablevalue(u"")
  388. return immutablevalue("")
  389. no_nul = str.no_nul and s_item.no_nul
  390. return str.basestringclass(no_nul=no_nul)
  391. def iter(str):
  392. return SomeIterator(str)
  393. iter.can_only_throw = []
  394. def getanyitem(str):
  395. return str.basecharclass()
  396. def method_split(str, patt, max=-1):
  397. getbookkeeper().count("str_split", str, patt)
  398. s_item = str.basestringclass(no_nul=str.no_nul)
  399. return getbookkeeper().newlist(s_item)
  400. def method_rsplit(str, patt, max=-1):
  401. getbookkeeper().count("str_rsplit", str, patt)
  402. s_item = str.basestringclass(no_nul=str.no_nul)
  403. return getbookkeeper().newlist(s_item)
  404. def method_replace(str, s1, s2):
  405. return str.basestringclass()
  406. def getslice(str, s_start, s_stop):
  407. check_negative_slice(s_start, s_stop)
  408. result = str.basestringclass(no_nul=str.no_nul)
  409. return result
  410. class __extend__(SomeUnicodeString):
  411. def method_encode(uni, s_enc):
  412. if not s_enc.is_constant():
  413. raise TypeError("Non-constant encoding not supported")
  414. enc = s_enc.const
  415. if enc not in ('ascii', 'latin-1'):
  416. raise TypeError("Encoding %s not supported for unicode" % (enc,))
  417. return SomeString()
  418. method_encode.can_only_throw = [UnicodeEncodeError]
  419. class __extend__(SomeString):
  420. def method_upper(str):
  421. return SomeString()
  422. def method_lower(str):
  423. return SomeString()
  424. def method_splitlines(str, s_keep_newlines=None):
  425. s_list = getbookkeeper().newlist(str.basestringclass())
  426. # Force the list to be resizable because ll_splitlines doesn't
  427. # preallocate the list.
  428. s_list.listdef.listitem.resize()
  429. return s_list
  430. def method_decode(str, s_enc):
  431. if not s_enc.is_constant():
  432. raise TypeError("Non-constant encoding not supported")
  433. enc = s_enc.const
  434. if enc not in ('ascii', 'latin-1'):
  435. raise TypeError("Encoding %s not supported for strings" % (enc,))
  436. return SomeUnicodeString()
  437. method_decode.can_only_throw = [UnicodeDecodeError]
  438. class __extend__(SomeChar, SomeUnicodeCodePoint):
  439. def len(chr):
  440. return immutablevalue(1)
  441. def ord(str):
  442. return SomeInteger(nonneg=True)
  443. class __extend__(SomeChar):
  444. def method_isspace(chr):
  445. return s_Bool
  446. def method_isdigit(chr):
  447. return s_Bool
  448. def method_isalpha(chr):
  449. return s_Bool
  450. def method_isalnum(chr):
  451. return s_Bool
  452. def method_islower(chr):
  453. return s_Bool
  454. def method_isupper(chr):
  455. return s_Bool
  456. class __extend__(SomeIterator):
  457. def iter(itr):
  458. return itr
  459. iter.can_only_throw = []
  460. def _can_only_throw(itr):
  461. can_throw = [StopIteration]
  462. if isinstance(itr.s_container, SomeDict):
  463. can_throw.append(RuntimeError)
  464. return can_throw
  465. def next(itr):
  466. if itr.variant == ("enumerate",):
  467. s_item = itr.s_container.getanyitem()
  468. return SomeTuple((SomeInteger(nonneg=True), s_item))
  469. return itr.s_container.getanyitem(*itr.variant)
  470. next.can_only_throw = _can_only_throw
  471. method_next = next
  472. class __extend__(SomeInstance):
  473. def getattr(ins, s_attr):
  474. if s_attr.is_constant() and isinstance(s_attr.const, str):
  475. attr = s_attr.const
  476. if attr == '__class__':
  477. return ins.classdef.read_attr__class__()
  478. attrdef = ins.classdef.find_attribute(attr)
  479. position = getbookkeeper().position_key
  480. attrdef.read_locations[position] = True
  481. s_result = attrdef.getvalue()
  482. # hack: if s_result is a set of methods, discard the ones
  483. # that can't possibly apply to an instance of ins.classdef.
  484. # XXX do it more nicely
  485. if isinstance(s_result, SomePBC):
  486. s_result = ins.classdef.lookup_filter(s_result, attr,
  487. ins.flags)
  488. elif isinstance(s_result, SomeImpossibleValue):
  489. ins.classdef.check_missing_attribute_update(attr)
  490. # blocking is harmless if the attribute is explicitly listed
  491. # in the class or a parent class.
  492. for basedef in ins.classdef.getmro():
  493. if basedef.classdesc.all_enforced_attrs is not None:
  494. if attr in basedef.classdesc.all_enforced_attrs:
  495. raise HarmlesslyBlocked("get enforced attr")
  496. elif isinstance(s_result, SomeList):
  497. s_result = ins.classdef.classdesc.maybe_return_immutable_list(
  498. attr, s_result)
  499. return s_result
  500. return SomeObject()
  501. getattr.can_only_throw = []
  502. def setattr(ins, s_attr, s_value):
  503. if s_attr.is_constant() and isinstance(s_attr.const, str):
  504. attr = s_attr.const
  505. # find the (possibly parent) class where this attr is defined
  506. clsdef = ins.classdef.locate_attribute(attr)
  507. attrdef = clsdef.attrs[attr]
  508. attrdef.modified(clsdef)
  509. # if the attrdef is new, this must fail
  510. if attrdef.getvalue().contains(s_value):
  511. return
  512. # create or update the attribute in clsdef
  513. clsdef.generalize_attr(attr, s_value)
  514. def is_true_behavior(ins, s):
  515. if not ins.can_be_None:
  516. s.const = True
  517. class __extend__(SomeBuiltin):
  518. def _can_only_throw(bltn, *args):
  519. analyser_func = getattr(bltn.analyser, 'im_func', None)
  520. can_only_throw = getattr(analyser_func, 'can_only_throw', None)
  521. if can_only_throw is None or isinstance(can_only_throw, list):
  522. return can_only_throw
  523. if bltn.s_self is not None:
  524. return can_only_throw(bltn.s_self, *args)
  525. else:
  526. return can_only_throw(*args)
  527. def simple_call(bltn, *args):
  528. if bltn.s_self is not None:
  529. return bltn.analyser(bltn.s_self, *args)
  530. else:
  531. if bltn.methodname:
  532. getbookkeeper().count(bltn.methodname.replace('.', '_'), *args)
  533. return bltn.analyser(*args)
  534. simple_call.can_only_throw = _can_only_throw
  535. def call(bltn, args, implicit_init=False):
  536. args_s, kwds = args.unpack()
  537. # prefix keyword arguments with 's_'
  538. kwds_s = {}
  539. for key, s_value in kwds.items():
  540. kwds_s['s_'+key] = s_value
  541. if bltn.s_self is not None:
  542. return bltn.analyser(bltn.s_self, *args_s, **kwds_s)
  543. else:
  544. return bltn.analyser(*args_s, **kwds_s)
  545. class __extend__(SomePBC):
  546. def getattr(pbc, s_attr):
  547. bookkeeper = getbookkeeper()
  548. return bookkeeper.pbc_getattr(pbc, s_attr)
  549. getattr.can_only_throw = []
  550. def setattr(pbc, s_attr, s_value):
  551. if not pbc.isNone():
  552. raise AnnotatorError("setattr on %r" % pbc)
  553. def call(pbc, args):
  554. bookkeeper = getbookkeeper()
  555. return bookkeeper.pbc_call(pbc, args)
  556. def bind_callables_under(pbc, classdef, name):
  557. d = [desc.bind_under(classdef, name) for desc in pbc.descriptions]
  558. return SomePBC(d, can_be_None=pbc.can_be_None)
  559. def is_true_behavior(pbc, s):
  560. if pbc.isNone():
  561. s.const = False
  562. elif not pbc.can_be_None:
  563. s.const = True
  564. def len(pbc):
  565. if pbc.isNone():
  566. # this None could later be generalized into an empty list,
  567. # whose length is the constant 0; so let's tentatively answer 0.
  568. return immutablevalue(0)
  569. else:
  570. return SomeObject() # len() on a pbc? no chance
  571. class __extend__(SomeGenericCallable):
  572. def call(self, args):
  573. bookkeeper = getbookkeeper()
  574. for arg, expected in zip(args.unpack()[0], self.args_s):
  575. assert expected.contains(arg)
  576. return self.s_result
  577. class __extend__(SomeExternalObject):
  578. def getattr(p, s_attr):
  579. if s_attr.is_constant() and isinstance(s_attr.const, str):
  580. attr = s_attr.const
  581. entry = extregistry.lookup_type(p.knowntype)
  582. s_value = entry.get_field_annotation(p.knowntype, attr)
  583. return s_value
  584. else:
  585. return SomeObject()
  586. getattr.can_only_throw = []
  587. def setattr(p, s_attr, s_value):
  588. assert s_attr.is_constant()
  589. attr = s_attr.const
  590. entry = extregistry.lookup_type(p.knowntype)
  591. entry.set_field_annotation(p.knowntype, attr, s_value)
  592. def is_true(p):
  593. return s_Bool
  594. # annotation of low-level types
  595. from pypy.annotation.model import SomePtr, SomeLLADTMeth
  596. from pypy.annotation.model import SomeOOInstance, SomeOOBoundMeth, SomeOOStaticMeth
  597. from pypy.annotation.model import ll_to_annotation, lltype_to_annotation, annotation_to_lltype
  598. class __extend__(SomePtr):
  599. def getattr(p, s_attr):
  600. assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % p.ll_ptrtype
  601. example = p.ll_ptrtype._example()
  602. try:
  603. v = example._lookup_adtmeth(s_attr.const)
  604. except AttributeError:
  605. v = getattr(example, s_attr.const)
  606. return ll_to_annotation(v)
  607. else:
  608. if isinstance(v, MethodType):
  609. from pypy.rpython.lltypesystem import lltype
  610. ll_ptrtype = lltype.typeOf(v.im_self)
  611. assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr))
  612. return SomeLLADTMeth(ll_ptrtype, v.im_func)
  613. return getbookkeeper().immutablevalue(v)
  614. getattr.can_only_throw = []
  615. def len(p):
  616. length = p.ll_ptrtype._example()._fixedlength()
  617. if length is None:
  618. return SomeObject.len(p)
  619. else:
  620. return immutablevalue(length)
  621. def setattr(p, s_attr, s_value): # just doing checking
  622. assert s_attr.is_constant(), "setattr on ptr %r with non-constant field-name" % p.ll_ptrtype
  623. example = p.ll_ptrtype._example()
  624. if getattr(example, s_attr.const) is not None: # ignore Void s_value
  625. v_lltype = annotation_to_lltype(s_value)
  626. setattr(example, s_attr.const, v_lltype._defl())
  627. def call(p, args):
  628. args_s, kwds_s = args.unpack()
  629. if kwds_s:
  630. raise Exception("keyword arguments to call to a low-level fn ptr")
  631. info = 'argument to ll function pointer call'
  632. llargs = [annotation_to_lltype(s_arg,info)._defl() for s_arg in args_s]
  633. v = p.ll_ptrtype._example()(*llargs)
  634. return ll_to_annotation(v)
  635. def is_true(p):
  636. return s_Bool
  637. class __extend__(SomeLLADTMeth):
  638. def call(adtmeth, args):
  639. bookkeeper = getbookkeeper()
  640. s_func = bookkeeper.immutablevalue(adtmeth.func)
  641. return s_func.call(args.prepend(lltype_to_annotation(adtmeth.ll_ptrtype)))
  642. from pypy.rpython.ootypesystem import ootype
  643. class __extend__(SomeOOInstance):
  644. def getattr(r, s_attr):
  645. assert s_attr.is_constant(), "getattr on ref %r with non-constant field-name" % r.ootype
  646. v = getattr(r.ootype._example(), s_attr.const)
  647. if isinstance(v, ootype._bound_meth):
  648. return SomeOOBoundMeth(r.ootype, s_attr.const)
  649. return ll_to_annotation(v)
  650. def setattr(r, s_attr, s_value):
  651. assert s_attr.is_constant(), "setattr on ref %r with non-constant field-name" % r.ootype
  652. v = annotation_to_lltype(s_value)
  653. example = r.ootype._example()
  654. if example is not None:
  655. setattr(r.ootype._example(), s_attr.const, v._example())
  656. def is_true(p):
  657. return s_Bool
  658. class __extend__(SomeOOBoundMeth):
  659. def simple_call(m, *args_s):
  660. _, meth = m.ootype._lookup(m.name)
  661. if isinstance(meth, ootype._overloaded_meth):
  662. return meth._resolver.annotate(args_s)
  663. else:
  664. METH = ootype.typeOf(meth)
  665. return lltype_to_annotation(METH.RESULT)
  666. def call(m, args):
  667. args_s, kwds_s = args.unpack()
  668. if kwds_s:
  669. raise Exception("keyword arguments to call to a low-level bound method")
  670. inst = m.ootype._example()
  671. _, meth = ootype.typeOf(inst)._lookup(m.name)
  672. METH = ootype.typeOf(meth)
  673. return lltype_to_annotation(METH.RESULT)
  674. class __extend__(SomeOOStaticMeth):
  675. def call(m, args):
  676. args_s, kwds_s = args.unpack()
  677. if kwds_s:
  678. raise Exception("keyword arguments to call to a low-level static method")
  679. info = 'argument to ll static method call'
  680. llargs = [annotation_to_lltype(s_arg, info)._defl() for s_arg in args_s]
  681. v = m.method._example()(*llargs)
  682. return ll_to_annotation(v)
  683. #_________________________________________
  684. # weakrefs
  685. class __extend__(SomeWeakRef):
  686. def simple_call(s_wrf):
  687. if s_wrf.classdef is None:
  688. return s_None # known to be a dead weakref
  689. else:
  690. return SomeInstance(s_wrf.classdef, can_be_None=True)
  691. #_________________________________________
  692. # memory addresses
  693. from pypy.rpython.lltypesystem import llmemory
  694. class __extend__(SomeAddress):
  695. def getattr(s_addr, s_attr):
  696. assert s_attr.is_constant()
  697. assert isinstance(s_attr, SomeString)
  698. assert s_attr.const in llmemory.supported_access_types
  699. return SomeTypedAddressAccess(
  700. llmemory.supported_access_types[s_attr.const])
  701. getattr.can_only_throw = []
  702. def is_true(s_addr):
  703. return s_Bool