PageRenderTime 64ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/rtyper/test/test_rclass.py

https://bitbucket.org/pypy/pypy/
Python | 1307 lines | 1186 code | 105 blank | 16 comment | 58 complexity | 0d8316ca09eb4c9ebe2979a483716236 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import sys
  2. import py
  3. from rpython.flowspace.model import summary
  4. from rpython.rlib.rarithmetic import r_longlong
  5. from rpython.rtyper.lltypesystem.lltype import (typeOf, Signed, getRuntimeTypeInfo,
  6. identityhash)
  7. from rpython.rtyper.error import TyperError
  8. from rpython.rtyper.rclass import (IR_IMMUTABLE, IR_IMMUTABLE_ARRAY,
  9. IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY)
  10. from rpython.rtyper.test.tool import BaseRtypingTest
  11. from rpython.translator.translator import TranslationContext, graphof
  12. class EmptyBase(object):
  13. pass
  14. class Random:
  15. xyzzy = 12
  16. yadda = 21
  17. # for method calls
  18. class A:
  19. def f(self):
  20. return self.g()
  21. def g(self):
  22. return 42
  23. class B(A):
  24. def g(self):
  25. return 1
  26. class C(B):
  27. pass
  28. class TestRclass(BaseRtypingTest):
  29. def test_instanceattr(self):
  30. def dummyfn():
  31. x = EmptyBase()
  32. x.a = 5
  33. x.a += 1
  34. return x.a
  35. res = self.interpret(dummyfn, [])
  36. assert res == 6
  37. def test_simple(self):
  38. def dummyfn():
  39. x = EmptyBase()
  40. return x
  41. res = self.interpret(dummyfn, [])
  42. assert self.is_of_instance_type(res)
  43. def test_classattr(self):
  44. def dummyfn():
  45. x = Random()
  46. return x.xyzzy
  47. res = self.interpret(dummyfn, [])
  48. assert res == 12
  49. def test_classattr_both(self):
  50. class A:
  51. a = 1
  52. class B(A):
  53. a = 2
  54. def pick(i):
  55. if i == 0:
  56. return A
  57. else:
  58. return B
  59. def dummyfn(i):
  60. C = pick(i)
  61. i = C()
  62. return C.a + i.a
  63. res = self.interpret(dummyfn, [0])
  64. assert res == 2
  65. res = self.interpret(dummyfn, [1])
  66. assert res == 4
  67. def test_classattr_both2(self):
  68. class Base(object):
  69. a = 0
  70. class A(Base):
  71. a = 1
  72. class B(Base):
  73. a = 2
  74. def pick(i):
  75. if i == 0:
  76. return A
  77. else:
  78. return B
  79. def dummyfn(i):
  80. C = pick(i)
  81. i = C()
  82. return C.a + i.a
  83. res = self.interpret(dummyfn, [0])
  84. assert res == 2
  85. res = self.interpret(dummyfn, [1])
  86. assert res == 4
  87. def test_runtime_exception(self):
  88. class MyExc(Exception):
  89. pass
  90. class Sub1(MyExc):
  91. pass
  92. class Sub2(MyExc):
  93. pass
  94. def pick(flag):
  95. if flag:
  96. return Sub1
  97. else:
  98. return Sub2
  99. def g(flag):
  100. ex = pick(flag)
  101. raise ex()
  102. def f(flag):
  103. try:
  104. g(flag)
  105. except Sub1:
  106. return 1
  107. except Sub2:
  108. return 2
  109. else:
  110. return 3
  111. assert self.interpret(f, [True]) == 1
  112. assert self.interpret(f, [False]) == 2
  113. def test_classattr_as_defaults(self):
  114. def dummyfn():
  115. x = Random()
  116. x.xyzzy += 1
  117. return x.xyzzy
  118. res = self.interpret(dummyfn, [])
  119. assert res == 13
  120. def test_overridden_classattr_as_defaults(self):
  121. class W_Root(object):
  122. pass
  123. class W_Thunk(W_Root):
  124. pass
  125. THUNK_PLACEHOLDER = W_Thunk()
  126. W_Root.w_thunkalias = None
  127. W_Thunk.w_thunkalias = THUNK_PLACEHOLDER
  128. def dummyfn(x):
  129. if x == 1:
  130. t = W_Thunk()
  131. elif x == 2:
  132. t = W_Thunk()
  133. t.w_thunkalias = W_Thunk()
  134. else:
  135. t = W_Root()
  136. return t.w_thunkalias is THUNK_PLACEHOLDER
  137. res = self.interpret(dummyfn, [1])
  138. assert res == True
  139. def test_prebuilt_instance(self):
  140. a = EmptyBase()
  141. a.x = 5
  142. def dummyfn():
  143. a.x += 1
  144. return a.x
  145. self.interpret(dummyfn, [])
  146. def test_recursive_prebuilt_instance(self):
  147. a = EmptyBase()
  148. b = EmptyBase()
  149. a.x = 5
  150. b.x = 6
  151. a.peer = b
  152. b.peer = a
  153. def dummyfn():
  154. return a.peer.peer.peer.x
  155. res = self.interpret(dummyfn, [])
  156. assert res == 6
  157. def test_recursive_prebuilt_instance_classattr(self):
  158. class Base:
  159. def m(self):
  160. return self.d.t.v
  161. class T1(Base):
  162. v = 3
  163. class T2(Base):
  164. v = 4
  165. class D:
  166. def _freeze_(self):
  167. return True
  168. t1 = T1()
  169. t2 = T2()
  170. T1.d = D()
  171. T2.d = D()
  172. T1.d.t = t1
  173. def call_meth(obj):
  174. return obj.m()
  175. def fn():
  176. return call_meth(t1) + call_meth(t2)
  177. assert self.interpret(fn, []) == 6
  178. def test_prebuilt_instances_with_void(self):
  179. def marker():
  180. return 42
  181. a = EmptyBase()
  182. a.nothing_special = marker
  183. def dummyfn():
  184. return a.nothing_special()
  185. res = self.interpret(dummyfn, [])
  186. assert res == 42
  187. def test_simple_method_call(self):
  188. def f(i):
  189. if i:
  190. a = A()
  191. else:
  192. a = B()
  193. return a.f()
  194. res = self.interpret(f, [True])
  195. assert res == 42
  196. res = self.interpret(f, [False])
  197. assert res == 1
  198. def test_isinstance(self):
  199. def f(i):
  200. if i == 0:
  201. o = None
  202. elif i == 1:
  203. o = A()
  204. elif i == 2:
  205. o = B()
  206. else:
  207. o = C()
  208. return 100*isinstance(o, A)+10*isinstance(o, B)+1*isinstance(o ,C)
  209. res = self.interpret(f, [1])
  210. assert res == 100
  211. res = self.interpret(f, [2])
  212. assert res == 110
  213. res = self.interpret(f, [3])
  214. assert res == 111
  215. res = self.interpret(f, [0])
  216. assert res == 0
  217. def test_method_used_in_subclasses_only(self):
  218. class A:
  219. def meth(self):
  220. return 123
  221. class B(A):
  222. pass
  223. def f():
  224. x = B()
  225. return x.meth()
  226. res = self.interpret(f, [])
  227. assert res == 123
  228. def test_method_both_A_and_B(self):
  229. class A:
  230. def meth(self):
  231. return 123
  232. class B(A):
  233. pass
  234. def f():
  235. a = A()
  236. b = B()
  237. return a.meth() + b.meth()
  238. res = self.interpret(f, [])
  239. assert res == 246
  240. def test_method_specialized_with_subclass(self):
  241. class A:
  242. def meth(self, n):
  243. return -1
  244. meth._annspecialcase_ = 'specialize:arg(1)'
  245. class B(A):
  246. pass
  247. def f():
  248. a = A()
  249. b = B()
  250. a.meth(1) # the self of this variant is annotated with A
  251. b.meth(2) # the self of this variant is annotated with B
  252. return 42
  253. res = self.interpret(f, [])
  254. assert res == 42
  255. def test_issubclass_type(self):
  256. class Abstract:
  257. pass
  258. class A(Abstract):
  259. pass
  260. class B(A):
  261. pass
  262. def f(i):
  263. if i == 0:
  264. c1 = A()
  265. else:
  266. c1 = B()
  267. return issubclass(type(c1), B)
  268. assert self.interpret(f, [0]) == False
  269. assert self.interpret(f, [1]) == True
  270. def g(i):
  271. if i == 0:
  272. c1 = A()
  273. else:
  274. c1 = B()
  275. return issubclass(type(c1), A)
  276. assert self.interpret(g, [0]) == True
  277. assert self.interpret(g, [1]) == True
  278. def test_staticmethod(self):
  279. class A(object):
  280. f = staticmethod(lambda x, y: x*y)
  281. def f():
  282. a = A()
  283. return a.f(6, 7)
  284. res = self.interpret(f, [])
  285. assert res == 42
  286. def test_staticmethod2(self):
  287. class A(object):
  288. f = staticmethod(lambda x, y: x*y)
  289. class B(A):
  290. f = staticmethod(lambda x, y: x+y)
  291. def f():
  292. b = B()
  293. return b.f(6, 7)
  294. res = self.interpret(f, [])
  295. assert res == 13
  296. def test_is(self):
  297. class A: pass
  298. class B(A): pass
  299. class C: pass
  300. def f(i):
  301. a = A()
  302. b = B()
  303. c = C()
  304. d = None
  305. e = None
  306. if i == 0:
  307. d = a
  308. elif i == 1:
  309. d = b
  310. elif i == 2:
  311. e = c
  312. return (0x0001*(a is b) | 0x0002*(a is c) | 0x0004*(a is d) |
  313. 0x0008*(a is e) | 0x0010*(b is c) | 0x0020*(b is d) |
  314. 0x0040*(b is e) | 0x0080*(c is d) | 0x0100*(c is e) |
  315. 0x0200*(d is e))
  316. res = self.interpret(f, [0])
  317. assert res == 0x0004
  318. res = self.interpret(f, [1])
  319. assert res == 0x0020
  320. res = self.interpret(f, [2])
  321. assert res == 0x0100
  322. res = self.interpret(f, [3])
  323. assert res == 0x0200
  324. def test_eq(self):
  325. class A: pass
  326. class B(A): pass
  327. class C: pass
  328. def f(i):
  329. a = A()
  330. b = B()
  331. c = C()
  332. d = None
  333. e = None
  334. if i == 0:
  335. d = a
  336. elif i == 1:
  337. d = b
  338. elif i == 2:
  339. e = c
  340. return (0x0001*(a == b) | 0x0002*(a == c) | 0x0004*(a == d) |
  341. 0x0008*(a == e) | 0x0010*(b == c) | 0x0020*(b == d) |
  342. 0x0040*(b == e) | 0x0080*(c == d) | 0x0100*(c == e) |
  343. 0x0200*(d == e))
  344. res = self.interpret(f, [0])
  345. assert res == 0x0004
  346. res = self.interpret(f, [1])
  347. assert res == 0x0020
  348. res = self.interpret(f, [2])
  349. assert res == 0x0100
  350. res = self.interpret(f, [3])
  351. assert res == 0x0200
  352. def test_istrue(self):
  353. class A:
  354. pass
  355. def f(i):
  356. if i == 0:
  357. a = A()
  358. else:
  359. a = None
  360. if a:
  361. return 1
  362. else:
  363. return 2
  364. res = self.interpret(f, [0])
  365. assert res == 1
  366. res = self.interpret(f, [1])
  367. assert res == 2
  368. def test_ne(self):
  369. class A: pass
  370. class B(A): pass
  371. class C: pass
  372. def f(i):
  373. a = A()
  374. b = B()
  375. c = C()
  376. d = None
  377. e = None
  378. if i == 0:
  379. d = a
  380. elif i == 1:
  381. d = b
  382. elif i == 2:
  383. e = c
  384. return (0x0001*(a != b) | 0x0002*(a != c) | 0x0004*(a != d) |
  385. 0x0008*(a != e) | 0x0010*(b != c) | 0x0020*(b != d) |
  386. 0x0040*(b != e) | 0x0080*(c != d) | 0x0100*(c != e) |
  387. 0x0200*(d != e))
  388. res = self.interpret(f, [0])
  389. assert res == ~0x0004 & 0x3ff
  390. res = self.interpret(f, [1])
  391. assert res == ~0x0020 & 0x3ff
  392. res = self.interpret(f, [2])
  393. assert res == ~0x0100 & 0x3ff
  394. res = self.interpret(f, [3])
  395. assert res == ~0x0200 & 0x3ff
  396. def test_class___name__(self):
  397. class ACLS(object): pass
  398. class Bcls(ACLS): pass
  399. class CCls(ACLS): pass
  400. def nameof(cls):
  401. return cls.__name__
  402. nameof._annspecialcase_ = "specialize:memo"
  403. def f(i):
  404. if i == 1: x = ACLS()
  405. elif i == 2: x = Bcls()
  406. else: x = CCls()
  407. return nameof(x.__class__)
  408. res = self.interpret(f, [1])
  409. assert ''.join(res.chars) == 'ACLS'
  410. res = self.interpret(f, [2])
  411. assert ''.join(res.chars) == 'Bcls'
  412. res = self.interpret(f, [3])
  413. assert ''.join(res.chars) == 'CCls'
  414. def test_hash_preservation(self):
  415. from rpython.rlib.objectmodel import current_object_addr_as_int
  416. from rpython.rlib.objectmodel import compute_identity_hash
  417. class C:
  418. pass
  419. class D(C):
  420. pass
  421. c = C()
  422. d = D()
  423. h_c = compute_identity_hash(c)
  424. h_d = compute_identity_hash(d)
  425. #
  426. def f():
  427. d2 = D()
  428. return (compute_identity_hash(d2),
  429. current_object_addr_as_int(d2),
  430. compute_identity_hash(c),
  431. compute_identity_hash(d))
  432. res = self.interpret(f, [])
  433. # xxx the following test is too precise, checking the exact
  434. # implementation. On Python 2.7 it doesn't work anyway, because
  435. # object.__hash__(x) is different from id(x). The test is disabled
  436. # for now, and nobody should rely on compute_identity_hash() returning
  437. # a value that is (or was) the current_object_addr_as_int().
  438. # --- disabled: assert res.item0 == res.item1
  439. # the following property is essential on top of the lltypesystem
  440. # otherwise prebuilt dictionaries are broken.
  441. assert res.item2 == h_c
  442. assert res.item3 == h_d
  443. def test_circular_hash_initialization(self):
  444. class B:
  445. pass
  446. class C(B):
  447. pass
  448. c1 = C()
  449. c1.somedict = {c1: True, C(): False}
  450. def f():
  451. B().somedict = {} # force the attribute up
  452. c1.somedict[c1] = 123
  453. return len(c1.somedict)
  454. res = self.interpret(f, [])
  455. assert res == 2
  456. def test_type(self):
  457. class A:
  458. pass
  459. class B(A):
  460. pass
  461. def g(a):
  462. return type(a)
  463. def f(i):
  464. if i > 0:
  465. a = A()
  466. elif i < 0:
  467. a = B()
  468. else:
  469. a = None
  470. return g(a) is A # should type(None) work? returns None for now
  471. res = self.interpret(f, [1])
  472. assert res is True
  473. res = self.interpret(f, [-1])
  474. assert res is False
  475. res = self.interpret(f, [0])
  476. assert res is False
  477. def test_type_of_constant(self):
  478. class A:
  479. pass
  480. a = A()
  481. def f():
  482. return type(a) is A
  483. res = self.interpret(f, [])
  484. def test_void_fnptr(self):
  485. def g():
  486. return 42
  487. def f():
  488. e = EmptyBase()
  489. e.attr = g
  490. return e.attr()
  491. res = self.interpret(f, [])
  492. assert res == 42
  493. def test_getattr_on_classes(self):
  494. class A:
  495. def meth(self):
  496. return self.value + 42
  497. class B(A):
  498. def meth(self):
  499. shouldnt**be**seen
  500. class C(B):
  501. def meth(self):
  502. return self.value - 1
  503. def pick_class(i):
  504. if i > 0:
  505. return A
  506. else:
  507. return C
  508. def f(i):
  509. meth = pick_class(i).meth
  510. x = C()
  511. x.value = 12
  512. return meth(x) # calls A.meth or C.meth, completely ignores B.meth
  513. res = self.interpret(f, [1])
  514. assert res == 54
  515. res = self.interpret(f, [0])
  516. assert res == 11
  517. def test_constant_bound_method(self):
  518. class C:
  519. value = 1
  520. def meth(self):
  521. return self.value
  522. meth = C().meth
  523. def f():
  524. return meth()
  525. res = self.interpret(f, [])
  526. assert res == 1
  527. def test_mixin(self):
  528. class Mixin(object):
  529. _mixin_ = True
  530. def m(self, v):
  531. return v
  532. class Base(object):
  533. pass
  534. class A(Base, Mixin):
  535. pass
  536. class B(Base, Mixin):
  537. pass
  538. class C(B):
  539. pass
  540. def f():
  541. a = A()
  542. v0 = a.m(2)
  543. b = B()
  544. v1 = b.m('x')
  545. c = C()
  546. v2 = c.m('y')
  547. return v0, v1, v2
  548. res = self.interpret(f, [])
  549. assert typeOf(res.item0) == Signed
  550. def test___class___attribute(self):
  551. class Base(object): pass
  552. class A(Base): pass
  553. class B(Base): pass
  554. class C(A): pass
  555. def seelater():
  556. C()
  557. def f(n):
  558. if n == 1:
  559. x = A()
  560. else:
  561. x = B()
  562. y = B()
  563. result = x.__class__, y.__class__
  564. seelater()
  565. return result
  566. def g():
  567. cls1, cls2 = f(1)
  568. return cls1 is A, cls2 is B
  569. res = self.interpret(g, [])
  570. assert res.item0
  571. assert res.item1
  572. def test_common_class_attribute(self):
  573. class A:
  574. def meth(self):
  575. return self.x
  576. class B(A):
  577. x = 42
  578. class C(A):
  579. x = 43
  580. def call_meth(a):
  581. return a.meth()
  582. def f():
  583. b = B()
  584. c = C()
  585. return call_meth(b) + call_meth(c)
  586. assert self.interpret(f, []) == 85
  587. def test_default_attribute_non_primitive(self):
  588. class A:
  589. x = (1, 2)
  590. def f():
  591. a = A()
  592. a.x = (3, 4)
  593. return a.x[0]
  594. assert self.interpret(f, []) == 3
  595. def test_filter_unreachable_methods(self):
  596. # this creates a family with 20 unreachable methods m(), all
  597. # hidden by a 21st method m().
  598. class Base:
  599. pass
  600. prev = Base
  601. for i in range(20):
  602. class Intermediate(prev):
  603. def m(self, value=i):
  604. return value
  605. prev = Intermediate
  606. class Final(prev):
  607. def m(self):
  608. return -7
  609. def f():
  610. return Final().m()
  611. res = self.interpret(f, [])
  612. assert res == -7
  613. def test_instantiate_despite_abstract_methods(self):
  614. class A:
  615. pass
  616. class B(A):
  617. def foo(self):
  618. return 42
  619. def fn(n):
  620. # Although the code below is a bit strange, there are
  621. # subtle ways in which the same situation could occur.
  622. # One is shown by test_specialize_methods().
  623. if n < 10:
  624. x = B()
  625. else:
  626. x = A()
  627. if n < 7:
  628. return x.foo()
  629. else:
  630. return 100
  631. assert self.interpret(fn, [5]) == 42
  632. assert self.interpret(fn, [15]) == 100
  633. def test_specialize_methods(self):
  634. from rpython.rlib.objectmodel import specialize
  635. class A:
  636. @specialize.arg(1)
  637. def revealconst(self, T):
  638. return 3 * T
  639. revealconst.cls = 'A'
  640. class B(A):
  641. @specialize.arg(1)
  642. def revealconst(self, T):
  643. return 4 * T
  644. revealconst.cls = 'B'
  645. def fn():
  646. a = A()
  647. b = B()
  648. return a.revealconst(1) + b.revealconst(2) + a.revealconst(3)
  649. assert self.interpret(fn, []) == 3 + 8 + 9
  650. def test_hash_of_none(self):
  651. from rpython.rlib.objectmodel import compute_hash
  652. class A:
  653. pass
  654. def fn(x):
  655. if x:
  656. obj = A()
  657. else:
  658. obj = None
  659. return compute_hash(obj)
  660. res = self.interpret(fn, [0])
  661. assert res == 0
  662. def test_hash_of_only_none(self):
  663. from rpython.rlib.objectmodel import compute_hash
  664. def fn():
  665. obj = None
  666. return compute_hash(obj)
  667. res = self.interpret(fn, [])
  668. assert res == 0
  669. def test_immutable(self):
  670. class I(object):
  671. _immutable_ = True
  672. def __init__(self, v):
  673. self.v = v
  674. i = I(3)
  675. def f():
  676. return i.v
  677. t, typer, graph = self.gengraph(f, [], backendopt=True)
  678. assert summary(graph) == {}
  679. def test_immutable_fields(self):
  680. from rpython.jit.metainterp.typesystem import deref
  681. class A(object):
  682. _immutable_fields_ = ["x", "y[*]"]
  683. def __init__(self, x, y):
  684. self.x = x
  685. self.y = y
  686. def f():
  687. return A(3, [])
  688. t, typer, graph = self.gengraph(f, [])
  689. A_TYPE = deref(graph.getreturnvar().concretetype)
  690. accessor = A_TYPE._hints["immutable_fields"]
  691. assert accessor.fields == {"inst_x": IR_IMMUTABLE,
  692. "inst_y": IR_IMMUTABLE_ARRAY}
  693. def test_immutable_fields_subclass_1(self):
  694. from rpython.jit.metainterp.typesystem import deref
  695. class A(object):
  696. _immutable_fields_ = ["x"]
  697. def __init__(self, x):
  698. self.x = x
  699. class B(A):
  700. def __init__(self, x, y):
  701. A.__init__(self, x)
  702. self.y = y
  703. def f():
  704. return B(3, 5)
  705. t, typer, graph = self.gengraph(f, [])
  706. B_TYPE = deref(graph.getreturnvar().concretetype)
  707. accessor = B_TYPE._hints["immutable_fields"]
  708. assert accessor.fields == {"inst_x": IR_IMMUTABLE}
  709. def test_immutable_fields_subclass_2(self):
  710. from rpython.jit.metainterp.typesystem import deref
  711. class A(object):
  712. _immutable_fields_ = ["x"]
  713. def __init__(self, x):
  714. self.x = x
  715. class B(A):
  716. _immutable_fields_ = ["y"]
  717. def __init__(self, x, y):
  718. A.__init__(self, x)
  719. self.y = y
  720. def f():
  721. return B(3, 5)
  722. t, typer, graph = self.gengraph(f, [])
  723. B_TYPE = deref(graph.getreturnvar().concretetype)
  724. accessor = B_TYPE._hints["immutable_fields"]
  725. assert accessor.fields == {"inst_x": IR_IMMUTABLE,
  726. "inst_y": IR_IMMUTABLE}
  727. def test_immutable_fields_only_in_subclass(self):
  728. from rpython.jit.metainterp.typesystem import deref
  729. class A(object):
  730. def __init__(self, x):
  731. self.x = x
  732. class B(A):
  733. _immutable_fields_ = ["y"]
  734. def __init__(self, x, y):
  735. A.__init__(self, x)
  736. self.y = y
  737. def f():
  738. return B(3, 5)
  739. t, typer, graph = self.gengraph(f, [])
  740. B_TYPE = deref(graph.getreturnvar().concretetype)
  741. accessor = B_TYPE._hints["immutable_fields"]
  742. assert accessor.fields == {"inst_y": IR_IMMUTABLE}
  743. def test_immutable_forbidden_inheritance_1(self):
  744. from rpython.rtyper.rclass import ImmutableConflictError
  745. class A(object):
  746. pass
  747. class B(A):
  748. _immutable_fields_ = ['v']
  749. def f():
  750. A().v = 123
  751. B() # crash: class B says 'v' is immutable,
  752. # but it is defined on parent class A
  753. py.test.raises(ImmutableConflictError, self.gengraph, f, [])
  754. def test_immutable_forbidden_inheritance_2(self):
  755. from rpython.rtyper.rclass import ImmutableConflictError
  756. class A(object):
  757. pass
  758. class B(A):
  759. _immutable_ = True
  760. def f():
  761. A().v = 123
  762. B() # crash: class B has _immutable_ = True
  763. # but class A defines 'v' to be mutable
  764. py.test.raises(ImmutableConflictError, self.gengraph, f, [])
  765. def test_immutable_ok_inheritance_2(self):
  766. from rpython.jit.metainterp.typesystem import deref
  767. class A(object):
  768. _immutable_fields_ = ['v']
  769. class B(A):
  770. _immutable_ = True
  771. def f():
  772. A().v = 123
  773. B().w = 456
  774. return B()
  775. t, typer, graph = self.gengraph(f, [])
  776. B_TYPE = deref(graph.getreturnvar().concretetype)
  777. assert B_TYPE._hints["immutable"]
  778. A_TYPE = B_TYPE.super
  779. accessor = A_TYPE._hints["immutable_fields"]
  780. assert accessor.fields == {"inst_v": IR_IMMUTABLE}
  781. def test_immutable_subclass_1(self):
  782. from rpython.rtyper.rclass import ImmutableConflictError
  783. from rpython.jit.metainterp.typesystem import deref
  784. class A(object):
  785. _immutable_ = True
  786. class B(A):
  787. pass
  788. def f():
  789. A()
  790. B().v = 123
  791. return B()
  792. py.test.raises(ImmutableConflictError, self.gengraph, f, [])
  793. def test_immutable_subclass_2(self):
  794. from rpython.jit.metainterp.typesystem import deref
  795. class A(object):
  796. pass
  797. class B(A):
  798. _immutable_ = True
  799. def f():
  800. A()
  801. B().v = 123
  802. return B()
  803. t, typer, graph = self.gengraph(f, [])
  804. B_TYPE = deref(graph.getreturnvar().concretetype)
  805. assert B_TYPE._hints["immutable"]
  806. def test_immutable_subclass_void(self):
  807. from rpython.jit.metainterp.typesystem import deref
  808. class A(object):
  809. pass
  810. class B(A):
  811. _immutable_ = True
  812. def myfunc():
  813. pass
  814. def f():
  815. A().f = myfunc # it's ok to add Void attributes to A
  816. B().v = 123 # even though only B is declared _immutable_
  817. return B()
  818. t, typer, graph = self.gengraph(f, [])
  819. B_TYPE = deref(graph.getreturnvar().concretetype)
  820. assert B_TYPE._hints["immutable"]
  821. def test_quasi_immutable(self):
  822. from rpython.jit.metainterp.typesystem import deref
  823. class A(object):
  824. _immutable_fields_ = ['x', 'y', 'a?', 'b?']
  825. class B(A):
  826. pass
  827. def f():
  828. a = A()
  829. a.x = 42
  830. a.a = 142
  831. b = B()
  832. b.x = 43
  833. b.y = 41
  834. b.a = 44
  835. b.b = 45
  836. return B()
  837. t, typer, graph = self.gengraph(f, [])
  838. B_TYPE = deref(graph.getreturnvar().concretetype)
  839. accessor = B_TYPE._hints["immutable_fields"]
  840. assert accessor.fields == {"inst_y": IR_IMMUTABLE,
  841. "inst_b": IR_QUASIIMMUTABLE}
  842. found = []
  843. for op in graph.startblock.operations:
  844. if op.opname == 'jit_force_quasi_immutable':
  845. found.append(op.args[1].value)
  846. assert found == ['mutate_a', 'mutate_a', 'mutate_b']
  847. def test_quasi_immutable_clashes_with_immutable(self):
  848. from rpython.jit.metainterp.typesystem import deref
  849. class A(object):
  850. _immutable_ = True
  851. _immutable_fields_ = ['a?']
  852. def f():
  853. a = A()
  854. a.x = 42
  855. a.a = 142
  856. return A()
  857. with py.test.raises(TyperError):
  858. self.gengraph(f, [])
  859. def test_quasi_immutable_array(self):
  860. from rpython.jit.metainterp.typesystem import deref
  861. class A(object):
  862. _immutable_fields_ = ['c?[*]']
  863. class B(A):
  864. pass
  865. def f():
  866. a = A()
  867. a.c = [3, 4, 5]
  868. return A()
  869. t, typer, graph = self.gengraph(f, [])
  870. A_TYPE = deref(graph.getreturnvar().concretetype)
  871. accessor = A_TYPE._hints["immutable_fields"]
  872. assert accessor.fields == {"inst_c": IR_QUASIIMMUTABLE_ARRAY}
  873. found = []
  874. for op in graph.startblock.operations:
  875. if op.opname == 'jit_force_quasi_immutable':
  876. found.append(op.args[1].value)
  877. assert found == ['mutate_c']
  878. def test_calling_object_init(self):
  879. class A(object):
  880. pass
  881. class B(A):
  882. def __init__(self):
  883. A.__init__(self)
  884. def f():
  885. B()
  886. self.gengraph(f, [])
  887. def test__del__(self):
  888. class A(object):
  889. def __init__(self):
  890. self.a = 2
  891. def __del__(self):
  892. self.a = 3
  893. def f():
  894. a = A()
  895. return a.a
  896. t = TranslationContext()
  897. t.buildannotator().build_types(f, [])
  898. t.buildrtyper().specialize()
  899. graph = graphof(t, f)
  900. TYPE = graph.startblock.operations[0].args[0].value
  901. RTTI = getRuntimeTypeInfo(TYPE)
  902. RTTI._obj.query_funcptr # should not raise
  903. destrptr = RTTI._obj.destructor_funcptr
  904. assert destrptr is not None
  905. def test_del_inheritance(self):
  906. from rpython.rlib import rgc
  907. class State:
  908. pass
  909. s = State()
  910. s.a_dels = 0
  911. s.b_dels = 0
  912. class A(object):
  913. def __del__(self):
  914. s.a_dels += 1
  915. class B(A):
  916. def __del__(self):
  917. s.b_dels += 1
  918. class C(A):
  919. pass
  920. def f():
  921. A()
  922. B()
  923. C()
  924. A()
  925. B()
  926. C()
  927. rgc.collect()
  928. return s.a_dels * 10 + s.b_dels
  929. res = f()
  930. assert res == 42
  931. t = TranslationContext()
  932. t.buildannotator().build_types(f, [])
  933. t.buildrtyper().specialize()
  934. graph = graphof(t, f)
  935. TYPEA = graph.startblock.operations[0].args[0].value
  936. RTTIA = getRuntimeTypeInfo(TYPEA)
  937. TYPEB = graph.startblock.operations[3].args[0].value
  938. RTTIB = getRuntimeTypeInfo(TYPEB)
  939. TYPEC = graph.startblock.operations[6].args[0].value
  940. RTTIC = getRuntimeTypeInfo(TYPEC)
  941. queryptra = RTTIA._obj.query_funcptr # should not raise
  942. queryptrb = RTTIB._obj.query_funcptr # should not raise
  943. queryptrc = RTTIC._obj.query_funcptr # should not raise
  944. destrptra = RTTIA._obj.destructor_funcptr
  945. destrptrb = RTTIB._obj.destructor_funcptr
  946. destrptrc = RTTIC._obj.destructor_funcptr
  947. assert destrptra == destrptrc
  948. assert typeOf(destrptra).TO.ARGS[0] != typeOf(destrptrb).TO.ARGS[0]
  949. assert destrptra is not None
  950. assert destrptrb is not None
  951. def test_del_forbidden(self):
  952. class A(object):
  953. def __del__(self):
  954. self.foo()
  955. def foo(self):
  956. self.bar()
  957. def bar(self):
  958. pass
  959. bar._dont_reach_me_in_del_ = True
  960. def f():
  961. a = A()
  962. a.foo()
  963. a.bar()
  964. t = TranslationContext()
  965. t.buildannotator().build_types(f, [])
  966. e = py.test.raises(TyperError, t.buildrtyper().specialize)
  967. print e.value
  968. def test_instance_repr(self):
  969. from rpython.rlib.objectmodel import current_object_addr_as_int
  970. class FooBar(object):
  971. pass
  972. def f():
  973. x = FooBar()
  974. # on lltype, the RPython-level repr of an instance contains the
  975. # current object address
  976. return current_object_addr_as_int(x), str(x)
  977. res = self.interpret(f, [])
  978. xid, xstr = self.ll_unpack_tuple(res, 2)
  979. xstr = self.ll_to_string(xstr)
  980. print xid, xstr
  981. assert 'FooBar' in xstr
  982. from rpython.rlib.rarithmetic import r_uint
  983. expected = hex(r_uint(xid)).lower().replace('l', '')
  984. assert expected in xstr
  985. def test_hash_via_type(self):
  986. from rpython.annotator import model as annmodel
  987. from rpython.rtyper import extregistry
  988. from rpython.rtyper.annlowlevel import cast_object_to_ptr
  989. from rpython.rlib.objectmodel import compute_identity_hash
  990. class Z(object):
  991. pass
  992. def my_gethash(z):
  993. not_implemented
  994. def ll_my_gethash(ptr):
  995. return identityhash(ptr) # from lltype
  996. class MyGetHashEntry(extregistry.ExtRegistryEntry):
  997. _about_ = my_gethash
  998. def compute_result_annotation(self, s_instance):
  999. return annmodel.SomeInteger()
  1000. def specialize_call(self, hop):
  1001. [v_instance] = hop.inputargs(*hop.args_r)
  1002. hop.exception_is_here()
  1003. return hop.gendirectcall(ll_my_gethash, v_instance)
  1004. def f(n):
  1005. z = Z()
  1006. got = my_gethash(z)
  1007. expected = compute_identity_hash(z)
  1008. return got - expected
  1009. res = self.interpret(f, [5])
  1010. assert res == 0
  1011. def test_order_of_fields(self):
  1012. class A(object):
  1013. pass
  1014. def f(n):
  1015. a = A()
  1016. a.as_int = n
  1017. a.as_char = chr(n)
  1018. a.as_unichar = unichr(n)
  1019. a.as_double = n + 0.5
  1020. a.as_bool = bool(n)
  1021. a.as_void = None
  1022. a.as_longlong = r_longlong(n)
  1023. a.as_reference = A()
  1024. return a
  1025. res = self.interpret(f, [5])
  1026. names = list(typeOf(res).TO._names)
  1027. i = names.index('inst_as_int')
  1028. c = names.index('inst_as_char')
  1029. u = names.index('inst_as_unichar')
  1030. d = names.index('inst_as_double')
  1031. b = names.index('inst_as_bool')
  1032. v = names.index('inst_as_void')
  1033. l = names.index('inst_as_longlong')
  1034. r = names.index('inst_as_reference')
  1035. assert v == 1 # void fields are first
  1036. assert sorted([c, b]) == [7, 8]
  1037. if sys.maxint == 2147483647:
  1038. assert sorted([u, i, r]) == [4, 5, 6] # 32-bit types
  1039. assert sorted([d, l]) == [2, 3] # 64-bit types
  1040. else:
  1041. assert sorted([u]) == [6] # 32-bit types
  1042. assert sorted([i, r, d, l]) == [2, 3, 4, 5] # 64-bit types
  1043. def test_iter(self):
  1044. class Iterable(object):
  1045. def __init__(self):
  1046. self.counter = 0
  1047. def __iter__(self):
  1048. return self
  1049. def next(self):
  1050. if self.counter == 5:
  1051. raise StopIteration
  1052. self.counter += 1
  1053. return self.counter - 1
  1054. def f():
  1055. i = Iterable()
  1056. s = 0
  1057. for elem in i:
  1058. s += elem
  1059. return s
  1060. assert self.interpret(f, []) == f()
  1061. def test_iter_2_kinds(self):
  1062. class BaseIterable(object):
  1063. def __init__(self):
  1064. self.counter = 0
  1065. def __iter__(self):
  1066. return self
  1067. def next(self):
  1068. if self.counter >= 5:
  1069. raise StopIteration
  1070. self.counter += self.step
  1071. return self.counter - 1
  1072. class Iterable(BaseIterable):
  1073. step = 1
  1074. class OtherIter(BaseIterable):
  1075. step = 2
  1076. def f(k):
  1077. if k:
  1078. i = Iterable()
  1079. else:
  1080. i = OtherIter()
  1081. s = 0
  1082. for elem in i:
  1083. s += elem
  1084. return s
  1085. assert self.interpret(f, [True]) == f(True)
  1086. assert self.interpret(f, [False]) == f(False)
  1087. def test_indexing(self):
  1088. class A(object):
  1089. def __init__(self, data):
  1090. self.data = data
  1091. def __getitem__(self, i):
  1092. return self.data[i]
  1093. def __setitem__(self, i, v):
  1094. self.data[i] = v
  1095. def __getslice__(self, start, stop):
  1096. assert start >= 0
  1097. assert stop >= 0
  1098. return self.data[start:stop]
  1099. def __setslice__(self, start, stop, v):
  1100. assert start >= 0
  1101. assert stop >= 0
  1102. i = 0
  1103. for n in range(start, stop):
  1104. self.data[n] = v[i]
  1105. i += 1
  1106. def getitem(i):
  1107. a = A("abcdefg")
  1108. return a[i]
  1109. def setitem(i, v):
  1110. a = A([0] * 5)
  1111. a[i] = v
  1112. return a[i]
  1113. def getslice(start, stop):
  1114. a = A([1, 2, 3, 4, 5, 6])
  1115. sum = 0
  1116. for i in a[start:stop]:
  1117. sum += i
  1118. return sum
  1119. def setslice(start, stop, i):
  1120. a = A([0] * stop)
  1121. a[start:stop] = range(start, stop)
  1122. return a[i]
  1123. assert self.interpret(getitem, [0]) == getitem(0)
  1124. assert self.interpret(getitem, [1]) == getitem(1)
  1125. assert self.interpret(setitem, [0, 5]) == setitem(0, 5)
  1126. assert self.interpret(getslice, [0, 4]) == getslice(0, 4)
  1127. assert self.interpret(getslice, [1, 4]) == getslice(1, 4)
  1128. assert self.interpret(setslice, [4, 6, 5]) == setslice(4, 6, 5)
  1129. def test_len(self):
  1130. class A(object):
  1131. def __len__(self):
  1132. return 5
  1133. def fn():
  1134. a = A()
  1135. return len(a)
  1136. assert self.interpret(fn, []) == fn()
  1137. def test_init_with_star_args(self):
  1138. class Base(object):
  1139. def __init__(self, a, b):
  1140. self.a = a
  1141. self.b = b
  1142. class A(Base):
  1143. def __init__(self, *args):
  1144. Base.__init__(self, *args)
  1145. self.c = -1
  1146. cls = [Base, A]
  1147. def f(k, a, b):
  1148. return cls[k](a, b).b
  1149. assert self.interpret(f, [1, 4, 7]) == 7
  1150. def test_flatten_convert_const(self):
  1151. # check that we can convert_const() a chain of more than 1000
  1152. # instances
  1153. class A(object):
  1154. def __init__(self, next):
  1155. self.next = next
  1156. a = None
  1157. for i in range(1500):
  1158. a = A(a)
  1159. def f():
  1160. return a.next.next.next.next is not None
  1161. assert self.interpret(f, []) == True