| -- Test cases for reference count insertion. |
| |
| [case testReturnLiteral] |
| def f() -> int: |
| return 1 |
| [out] |
| def f(): |
| L0: |
| return 2 |
| |
| [case testReturnLocal] |
| def f() -> int: |
| x = 1 |
| return x |
| [out] |
| def f(): |
| x :: int |
| L0: |
| x = 2 |
| return x |
| |
| [case testLocalVars] |
| def f() -> int: |
| x = 1 |
| y = x |
| x = y |
| return x |
| [out] |
| def f(): |
| x, y :: int |
| L0: |
| x = 2 |
| y = x |
| x = y |
| return x |
| |
| [case testLocalVars2] |
| def f() -> int: |
| x = 1 |
| y = x |
| z = x |
| return y + z |
| [out] |
| def f(): |
| x, y, z, r0 :: int |
| L0: |
| x = 2 |
| inc_ref x :: int |
| y = x |
| z = x |
| r0 = CPyTagged_Add(y, z) |
| dec_ref y :: int |
| dec_ref z :: int |
| return r0 |
| |
| [case testFreeAtReturn] |
| def f() -> int: |
| x = 1 |
| y = 2 |
| if x == 1: |
| return x |
| return y |
| [out] |
| def f(): |
| x, y :: int |
| r0 :: bit |
| L0: |
| x = 2 |
| y = 4 |
| r0 = int_eq x, 2 |
| if r0 goto L3 else goto L4 :: bool |
| L1: |
| return x |
| L2: |
| return y |
| L3: |
| dec_ref y :: int |
| goto L1 |
| L4: |
| dec_ref x :: int |
| goto L2 |
| |
| [case testArgumentsInOps] |
| def f(a: int, b: int) -> int: |
| x = a + 1 |
| y = x + a |
| return y |
| [out] |
| def f(a, b): |
| a, b, r0, x, r1, y :: int |
| L0: |
| r0 = CPyTagged_Add(a, 2) |
| x = r0 |
| r1 = CPyTagged_Add(x, a) |
| dec_ref x :: int |
| y = r1 |
| return y |
| |
| [case testArgumentsInAssign] |
| def f(a: int) -> int: |
| x = a |
| y = a |
| x = 1 |
| return x + y |
| [out] |
| def f(a): |
| a, x, y, r0 :: int |
| L0: |
| inc_ref a :: int |
| x = a |
| dec_ref x :: int |
| inc_ref a :: int |
| y = a |
| x = 2 |
| r0 = CPyTagged_Add(x, y) |
| dec_ref x :: int |
| dec_ref y :: int |
| return r0 |
| |
| [case testAssignToArgument1] |
| def f(a: int) -> int: |
| a = 1 |
| y = a |
| return y |
| [out] |
| def f(a): |
| a, y :: int |
| L0: |
| a = 2 |
| y = a |
| return y |
| |
| [case testAssignToArgument2] |
| def f(a: int) -> int: |
| a = 1 |
| a = 2 |
| a = 3 |
| return a |
| [out] |
| def f(a): |
| a :: int |
| L0: |
| a = 2 |
| dec_ref a :: int |
| a = 4 |
| dec_ref a :: int |
| a = 6 |
| return a |
| |
| [case testAssignToArgument3] |
| def f(a: int) -> int: |
| x = 1 |
| a = x |
| y = x |
| return a |
| [out] |
| def f(a): |
| a, x, y :: int |
| L0: |
| x = 2 |
| inc_ref x :: int |
| a = x |
| y = x |
| dec_ref y :: int |
| return a |
| |
| [case testReturnArgument] |
| def f(a: int) -> int: |
| return a |
| [out] |
| def f(a): |
| a :: int |
| L0: |
| inc_ref a :: int |
| return a |
| |
| [case testConditionalAssignToArgument1] |
| def f(a: int) -> int: |
| if a == a: |
| a = 1 |
| else: |
| x = 2 |
| y = a + 1 |
| return y |
| [out] |
| def f(a): |
| a :: int |
| r0 :: bit |
| x, r1, y :: int |
| L0: |
| r0 = int_eq a, a |
| if r0 goto L1 else goto L2 :: bool |
| L1: |
| a = 2 |
| goto L3 |
| L2: |
| x = 4 |
| dec_ref x :: int |
| goto L4 |
| L3: |
| r1 = CPyTagged_Add(a, 2) |
| dec_ref a :: int |
| y = r1 |
| return y |
| L4: |
| inc_ref a :: int |
| goto L3 |
| |
| [case testConditionalAssignToArgument2] |
| def f(a: int) -> int: |
| if a == a: |
| x = 2 |
| else: |
| a = 1 |
| y = a + 1 |
| return y |
| [out] |
| def f(a): |
| a :: int |
| r0 :: bit |
| x, r1, y :: int |
| L0: |
| r0 = int_eq a, a |
| if r0 goto L1 else goto L2 :: bool |
| L1: |
| x = 4 |
| dec_ref x :: int |
| goto L4 |
| L2: |
| a = 2 |
| L3: |
| r1 = CPyTagged_Add(a, 2) |
| dec_ref a :: int |
| y = r1 |
| return y |
| L4: |
| inc_ref a :: int |
| goto L3 |
| |
| [case testConditionalAssignToArgument3] |
| def f(a: int) -> int: |
| if a == a: |
| a = 1 |
| return a |
| [out] |
| def f(a): |
| a :: int |
| r0 :: bit |
| L0: |
| r0 = int_eq a, a |
| if r0 goto L1 else goto L3 :: bool |
| L1: |
| a = 2 |
| L2: |
| return a |
| L3: |
| inc_ref a :: int |
| goto L2 |
| |
| [case testAssignRegisterToItself] |
| def f(a: int) -> int: |
| a = a |
| x = 1 |
| x = x |
| return x + a |
| -- This is correct but bad code |
| [out] |
| def f(a): |
| a, x, r0 :: int |
| L0: |
| inc_ref a :: int |
| a = a |
| x = 2 |
| inc_ref x :: int |
| dec_ref x :: int |
| x = x |
| r0 = CPyTagged_Add(x, a) |
| dec_ref x :: int |
| dec_ref a :: int |
| return r0 |
| |
| [case testIncrement1] |
| def f(a: int) -> int: |
| a = a + 1 |
| x = 1 |
| x = x + 1 |
| return a + x |
| [out] |
| def f(a): |
| a, r0, x, r1, r2 :: int |
| L0: |
| r0 = CPyTagged_Add(a, 2) |
| a = r0 |
| x = 2 |
| r1 = CPyTagged_Add(x, 2) |
| dec_ref x :: int |
| x = r1 |
| r2 = CPyTagged_Add(a, x) |
| dec_ref a :: int |
| dec_ref x :: int |
| return r2 |
| |
| [case testIncrement2] |
| def f() -> None: |
| x = 1 |
| x = x + 1 |
| [out] |
| def f(): |
| x, r0 :: int |
| L0: |
| x = 2 |
| r0 = CPyTagged_Add(x, 2) |
| dec_ref x :: int |
| x = r0 |
| dec_ref x :: int |
| return 1 |
| |
| [case testAdd1] |
| def f() -> None: |
| y = 1 |
| x = y + 1 |
| [out] |
| def f(): |
| y, r0, x :: int |
| L0: |
| y = 2 |
| r0 = CPyTagged_Add(y, 2) |
| dec_ref y :: int |
| x = r0 |
| dec_ref x :: int |
| return 1 |
| |
| [case testAdd2] |
| def f(a: int) -> int: |
| a = a + a |
| x = a |
| x = x + x |
| return x |
| [out] |
| def f(a): |
| a, r0, x, r1 :: int |
| L0: |
| r0 = CPyTagged_Add(a, a) |
| a = r0 |
| x = a |
| r1 = CPyTagged_Add(x, x) |
| dec_ref x :: int |
| x = r1 |
| return x |
| |
| [case testAdd3] |
| def f(a: int) -> int: |
| x = a + a |
| y = x + x |
| return y |
| [out] |
| def f(a): |
| a, r0, x, r1, y :: int |
| L0: |
| r0 = CPyTagged_Add(a, a) |
| x = r0 |
| r1 = CPyTagged_Add(x, x) |
| dec_ref x :: int |
| y = r1 |
| return y |
| |
| [case testAdd4] |
| def f(a: int) -> None: |
| x = a + a |
| y = 1 |
| z = y + y |
| [out] |
| def f(a): |
| a, r0, x, y, r1, z :: int |
| L0: |
| r0 = CPyTagged_Add(a, a) |
| x = r0 |
| dec_ref x :: int |
| y = 2 |
| r1 = CPyTagged_Add(y, y) |
| dec_ref y :: int |
| z = r1 |
| dec_ref z :: int |
| return 1 |
| |
| [case testAdd5] |
| def f(a: int) -> None: |
| a = a + a |
| x = 1 |
| x = x + x |
| [out] |
| def f(a): |
| a, r0, x, r1 :: int |
| L0: |
| r0 = CPyTagged_Add(a, a) |
| a = r0 |
| dec_ref a :: int |
| x = 2 |
| r1 = CPyTagged_Add(x, x) |
| dec_ref x :: int |
| x = r1 |
| dec_ref x :: int |
| return 1 |
| |
| [case testReturnInMiddleOfFunction] |
| def f() -> int: |
| x = 1 |
| y = 2 |
| z = 3 |
| if z == z: |
| return z |
| a = 1 |
| return x + y - a |
| [out] |
| def f(): |
| x, y, z :: int |
| r0 :: bit |
| a, r1, r2 :: int |
| L0: |
| x = 2 |
| y = 4 |
| z = 6 |
| r0 = int_eq z, z |
| if r0 goto L3 else goto L4 :: bool |
| L1: |
| return z |
| L2: |
| a = 2 |
| r1 = CPyTagged_Add(x, y) |
| dec_ref x :: int |
| dec_ref y :: int |
| r2 = CPyTagged_Subtract(r1, a) |
| dec_ref r1 :: int |
| dec_ref a :: int |
| return r2 |
| L3: |
| dec_ref x :: int |
| dec_ref y :: int |
| goto L1 |
| L4: |
| dec_ref z :: int |
| goto L2 |
| |
| [case testLoop] |
| def f(a: int) -> int: |
| sum = 0 |
| i = 0 |
| while i <= a: |
| sum = sum + i |
| i = i + 1 |
| return sum |
| [out] |
| def f(a): |
| a, sum, i :: int |
| r0 :: bit |
| r1, r2 :: int |
| L0: |
| sum = 0 |
| i = 0 |
| L1: |
| r0 = int_le i, a |
| if r0 goto L2 else goto L4 :: bool |
| L2: |
| r1 = CPyTagged_Add(sum, i) |
| dec_ref sum :: int |
| sum = r1 |
| r2 = CPyTagged_Add(i, 2) |
| dec_ref i :: int |
| i = r2 |
| goto L1 |
| L3: |
| return sum |
| L4: |
| dec_ref i :: int |
| goto L3 |
| |
| [case testCall] |
| def f(a: int) -> int: |
| return f(a + 1) |
| [out] |
| def f(a): |
| a, r0, r1 :: int |
| L0: |
| r0 = CPyTagged_Add(a, 2) |
| r1 = f(r0) |
| dec_ref r0 :: int |
| return r1 |
| |
| [case testError] |
| def f(x: List[int]) -> None: pass # E: Name "List" is not defined \ |
| # N: Did you forget to import it from "typing"? (Suggestion: "from typing import List") |
| |
| [case testNewList] |
| def f() -> int: |
| a = [0, 1] |
| return 0 |
| [out] |
| def f(): |
| r0 :: list |
| r1, r2 :: object |
| r3 :: ptr |
| a :: list |
| L0: |
| r0 = PyList_New(2) |
| r1 = object 0 |
| r2 = object 1 |
| r3 = list_items r0 |
| inc_ref r1 |
| buf_init_item r3, 0, r1 |
| inc_ref r2 |
| buf_init_item r3, 1, r2 |
| a = r0 |
| dec_ref a |
| return 0 |
| |
| [case testListSet] |
| from typing import List |
| def f(a: List[int], b: List[int]) -> None: |
| a[0] = b[0] |
| [out] |
| def f(a, b): |
| a, b :: list |
| r0 :: object |
| r1 :: int |
| r2 :: object |
| r3 :: bit |
| L0: |
| r0 = CPyList_GetItemShort(b, 0) |
| r1 = unbox(int, r0) |
| dec_ref r0 |
| r2 = box(int, r1) |
| r3 = CPyList_SetItem(a, 0, r2) |
| return 1 |
| |
| [case testTupleRefcount] |
| from typing import Tuple |
| def f(x: Tuple[Tuple[int, bool], bool]) -> int: |
| return x[0][0] |
| [out] |
| def f(x): |
| x :: tuple[tuple[int, bool], bool] |
| r0 :: tuple[int, bool] |
| r1 :: int |
| L0: |
| r0 = x[0] |
| r1 = r0[0] |
| dec_ref r0 |
| return r1 |
| |
| [case testUserClassRefCount] |
| class C: |
| x: 'C' |
| def f() -> None: |
| c = C() |
| c.x = C() |
| [out] |
| def f(): |
| r0, c, r1 :: __main__.C |
| r2 :: bool |
| L0: |
| r0 = C() |
| c = r0 |
| r1 = C() |
| c.x = r1; r2 = is_error |
| dec_ref c |
| return 1 |
| |
| [case testCastRefCount] |
| class C: pass |
| |
| def f() -> None: |
| a = [C()] |
| d = a[0] |
| [out] |
| def f(): |
| r0 :: __main__.C |
| r1 :: list |
| r2 :: ptr |
| a :: list |
| r3 :: object |
| r4, d :: __main__.C |
| L0: |
| r0 = C() |
| r1 = PyList_New(1) |
| r2 = list_items r1 |
| buf_init_item r2, 0, r0 |
| a = r1 |
| r3 = CPyList_GetItemShort(a, 0) |
| dec_ref a |
| r4 = cast(__main__.C, r3) |
| d = r4 |
| dec_ref d |
| return 1 |
| |
| [case testUnaryBranchSpecialCase] |
| def f(x: bool) -> int: |
| if x: |
| return 1 |
| return 2 |
| [out] |
| def f(x): |
| x :: bool |
| L0: |
| if x goto L1 else goto L2 :: bool |
| L1: |
| return 2 |
| L2: |
| return 4 |
| |
| [case testReturnTuple] |
| from typing import Tuple |
| |
| class C: pass |
| def f() -> Tuple[C, C]: |
| a = C() |
| b = C() |
| return a, b |
| [out] |
| def f(): |
| r0, a, r1, b, r2, r3 :: __main__.C |
| r4 :: tuple[__main__.C, __main__.C] |
| L0: |
| r0 = C() |
| a = r0 |
| r1 = C() |
| b = r1 |
| r2 = a |
| r3 = b |
| r4 = (r2, r3) |
| return r4 |
| |
| [case testDecomposeTuple] |
| from typing import Tuple |
| |
| class C: |
| a: int |
| |
| def f() -> int: |
| x, y = g() |
| return x.a + y.a |
| |
| def g() -> Tuple[C, C]: |
| return C(), C() |
| [out] |
| def f(): |
| r0 :: tuple[__main__.C, __main__.C] |
| r1, r2, r3, x, r4, y :: __main__.C |
| r5, r6, r7 :: int |
| L0: |
| r0 = g() |
| r1 = borrow r0[0] |
| r2 = borrow r0[1] |
| r3 = unborrow r1 |
| x = r3 |
| r4 = unborrow r2 |
| y = r4 |
| r5 = borrow x.a |
| r6 = borrow y.a |
| r7 = CPyTagged_Add(r5, r6) |
| dec_ref x |
| dec_ref y |
| return r7 |
| def g(): |
| r0, r1 :: __main__.C |
| r2 :: tuple[__main__.C, __main__.C] |
| L0: |
| r0 = C() |
| r1 = C() |
| r2 = (r0, r1) |
| return r2 |
| |
| [case testUnicodeLiteral] |
| def f() -> str: |
| return "some string" |
| [out] |
| def f(): |
| r0 :: str |
| L0: |
| r0 = 'some string' |
| inc_ref r0 |
| return r0 |
| |
| [case testPyMethodCall] |
| def g(x: str) -> int: |
| return int(x, base=2) |
| [out] |
| def g(x): |
| x :: str |
| r0, r1 :: object |
| r2 :: object[2] |
| r3 :: object_ptr |
| r4, r5 :: object |
| r6 :: int |
| L0: |
| r0 = load_address PyLong_Type |
| r1 = object 2 |
| r2 = [x, r1] |
| r3 = load_address r2 |
| r4 = ('base',) |
| r5 = PyObject_Vectorcall(r0, r3, 1, r4) |
| r6 = unbox(int, r5) |
| dec_ref r5 |
| return r6 |
| |
| [case testListAppend] |
| from typing import List |
| def f(a: List[int], x: int) -> None: |
| a.append(x) |
| [out] |
| def f(a, x): |
| a :: list |
| x :: int |
| r0 :: object |
| r1 :: i32 |
| r2 :: bit |
| L0: |
| inc_ref x :: int |
| r0 = box(int, x) |
| r1 = PyList_Append(a, r0) |
| dec_ref r0 |
| r2 = r1 >= 0 :: signed |
| return 1 |
| |
| [case testForDict] |
| from typing import Dict |
| |
| def f(d: Dict[int, int]) -> None: |
| for key in d: |
| d[key] |
| [out] |
| def f(d): |
| d :: dict |
| r0 :: short_int |
| r1 :: native_int |
| r2 :: object |
| r3 :: tuple[bool, short_int, object] |
| r4 :: short_int |
| r5 :: bool |
| r6 :: object |
| r7, key :: int |
| r8, r9 :: object |
| r10 :: int |
| r11, r12 :: bit |
| L0: |
| r0 = 0 |
| r1 = PyDict_Size(d) |
| r2 = CPyDict_GetKeysIter(d) |
| L1: |
| r3 = CPyDict_NextKey(r2, r0) |
| r4 = r3[1] |
| r0 = r4 |
| r5 = r3[0] |
| if r5 goto L2 else goto L6 :: bool |
| L2: |
| r6 = r3[2] |
| dec_ref r3 |
| r7 = unbox(int, r6) |
| dec_ref r6 |
| key = r7 |
| r8 = box(int, key) |
| r9 = CPyDict_GetItem(d, r8) |
| dec_ref r8 |
| r10 = unbox(int, r9) |
| dec_ref r9 |
| dec_ref r10 :: int |
| L3: |
| r11 = CPyDict_CheckSize(d, r1) |
| goto L1 |
| L4: |
| r12 = CPy_NoErrOccurred() |
| L5: |
| return 1 |
| L6: |
| dec_ref r2 |
| dec_ref r3 |
| goto L4 |
| |
| [case testBorrowRefs] |
| def make_garbage(arg: object) -> None: |
| b = True |
| while b: |
| arg = None |
| b = False |
| [out] |
| def make_garbage(arg): |
| arg :: object |
| b :: bool |
| r0 :: object |
| L0: |
| b = 1 |
| L1: |
| if b goto L2 else goto L3 :: bool |
| L2: |
| r0 = box(None, 1) |
| inc_ref r0 |
| arg = r0 |
| dec_ref arg |
| b = 0 |
| goto L1 |
| L3: |
| return 1 |
| |
| [case testTupleUnpackUnused] |
| from typing import Tuple |
| |
| def f(x: Tuple[str, int]) -> int: |
| a, xi = x |
| return 0 |
| [out] |
| def f(x): |
| x :: tuple[str, int] |
| r0 :: str |
| r1 :: int |
| r2, a :: str |
| r3, xi :: int |
| L0: |
| r0 = borrow x[0] |
| r1 = borrow x[1] |
| inc_ref x |
| r2 = unborrow r0 |
| a = r2 |
| dec_ref a |
| r3 = unborrow r1 |
| xi = r3 |
| dec_ref xi :: int |
| return 0 |
| |
| [case testGetElementPtrLifeTime] |
| from typing import List |
| |
| def f() -> int: |
| x: List[str] = [] |
| return len(x) |
| [out] |
| def f(): |
| r0, x :: list |
| r1 :: native_int |
| r2 :: short_int |
| L0: |
| r0 = PyList_New(0) |
| x = r0 |
| r1 = var_object_size x |
| dec_ref x |
| r2 = r1 << 1 |
| return r2 |
| |
| [case testSometimesUninitializedVariable] |
| def f(x: bool) -> int: |
| if x: |
| y = 1 |
| else: |
| z = 2 |
| return y + z |
| [out] |
| def f(x): |
| x :: bool |
| r0, y, r1, z :: int |
| r2, r3 :: bool |
| r4 :: int |
| L0: |
| r0 = <error> :: int |
| y = r0 |
| r1 = <error> :: int |
| z = r1 |
| if x goto L8 else goto L9 :: bool |
| L1: |
| y = 2 |
| goto L3 |
| L2: |
| z = 4 |
| L3: |
| if is_error(y) goto L10 else goto L5 |
| L4: |
| r2 = raise UnboundLocalError('local variable "y" referenced before assignment') |
| unreachable |
| L5: |
| if is_error(z) goto L11 else goto L7 |
| L6: |
| r3 = raise UnboundLocalError('local variable "z" referenced before assignment') |
| unreachable |
| L7: |
| r4 = CPyTagged_Add(y, z) |
| xdec_ref y :: int |
| xdec_ref z :: int |
| return r4 |
| L8: |
| xdec_ref y :: int |
| goto L1 |
| L9: |
| xdec_ref z :: int |
| goto L2 |
| L10: |
| xdec_ref z :: int |
| goto L4 |
| L11: |
| xdec_ref y :: int |
| goto L6 |
| |
| [case testVectorcall] |
| from typing import Any |
| |
| def call(f: Any, x: int) -> int: |
| return f(x) |
| [out] |
| def call(f, x): |
| f :: object |
| x :: int |
| r0 :: object |
| r1 :: object[1] |
| r2 :: object_ptr |
| r3 :: object |
| r4 :: int |
| L0: |
| inc_ref x :: int |
| r0 = box(int, x) |
| r1 = [r0] |
| r2 = load_address r1 |
| r3 = PyObject_Vectorcall(f, r2, 1, 0) |
| dec_ref r0 |
| r4 = unbox(int, r3) |
| dec_ref r3 |
| return r4 |
| |
| [case testVectorcallMethod_64bit] |
| from typing import Any |
| |
| def call(o: Any, x: int) -> int: |
| return o.m(x) |
| [out] |
| def call(o, x): |
| o :: object |
| x :: int |
| r0 :: str |
| r1 :: object |
| r2 :: object[2] |
| r3 :: object_ptr |
| r4 :: object |
| r5 :: int |
| L0: |
| r0 = 'm' |
| inc_ref x :: int |
| r1 = box(int, x) |
| r2 = [o, r1] |
| r3 = load_address r2 |
| r4 = PyObject_VectorcallMethod(r0, r3, 9223372036854775810, 0) |
| dec_ref r1 |
| r5 = unbox(int, r4) |
| dec_ref r4 |
| return r5 |
| |
| [case testBorrowAttribute] |
| def g() -> int: |
| d = D() |
| return d.c.x |
| |
| def f(d: D) -> int: |
| return d.c.x |
| |
| class C: |
| x: int |
| class D: |
| c: C |
| [out] |
| def g(): |
| r0, d :: __main__.D |
| r1 :: __main__.C |
| r2 :: int |
| L0: |
| r0 = D() |
| d = r0 |
| r1 = borrow d.c |
| r2 = r1.x |
| dec_ref d |
| return r2 |
| def f(d): |
| d :: __main__.D |
| r0 :: __main__.C |
| r1 :: int |
| L0: |
| r0 = borrow d.c |
| r1 = r0.x |
| return r1 |
| |
| [case testBorrowAttributeTwice] |
| def f(e: E) -> int: |
| return e.d.c.x |
| |
| class C: |
| x: int |
| class D: |
| c: C |
| class E: |
| d: D |
| [out] |
| def f(e): |
| e :: __main__.E |
| r0 :: __main__.D |
| r1 :: __main__.C |
| r2 :: int |
| L0: |
| r0 = borrow e.d |
| r1 = borrow r0.c |
| r2 = r1.x |
| return r2 |
| |
| [case testBorrowAttributeIsNone] |
| from typing import Optional |
| |
| def f(c: C) -> bool: |
| return c.x is not None |
| |
| def g(c: C) -> bool: |
| return c.x is None |
| |
| class C: |
| x: Optional[str] |
| [out] |
| def f(c): |
| c :: __main__.C |
| r0 :: union[str, None] |
| r1 :: object |
| r2 :: bit |
| L0: |
| r0 = borrow c.x |
| r1 = load_address _Py_NoneStruct |
| r2 = r0 != r1 |
| return r2 |
| def g(c): |
| c :: __main__.C |
| r0 :: union[str, None] |
| r1 :: object |
| r2 :: bit |
| L0: |
| r0 = borrow c.x |
| r1 = load_address _Py_NoneStruct |
| r2 = r0 == r1 |
| return r2 |
| |
| [case testBorrowAttributeNarrowOptional] |
| from typing import Optional |
| |
| def f(c: C) -> bool: |
| if c.x is not None: |
| return c.x.b |
| return False |
| |
| class C: |
| x: Optional[D] |
| |
| class D: |
| b: bool |
| [out] |
| def f(c): |
| c :: __main__.C |
| r0 :: union[__main__.D, None] |
| r1 :: object |
| r2 :: bit |
| r3 :: union[__main__.D, None] |
| r4 :: __main__.D |
| r5 :: bool |
| L0: |
| r0 = borrow c.x |
| r1 = load_address _Py_NoneStruct |
| r2 = r0 != r1 |
| if r2 goto L1 else goto L2 :: bool |
| L1: |
| r3 = borrow c.x |
| r4 = borrow cast(__main__.D, r3) |
| r5 = r4.b |
| return r5 |
| L2: |
| return 0 |
| |
| [case testBorrowLenArgument] |
| from typing import List |
| |
| def f(x: C) -> int: |
| return len(x.a) |
| |
| class C: |
| a: List[str] |
| [out] |
| def f(x): |
| x :: __main__.C |
| r0 :: list |
| r1 :: native_int |
| r2 :: short_int |
| L0: |
| r0 = borrow x.a |
| r1 = var_object_size r0 |
| r2 = r1 << 1 |
| return r2 |
| |
| [case testBorrowIsinstanceArgument] |
| from typing import List |
| |
| def f(x: C) -> bool: |
| if isinstance(x.a, D): |
| return x.a.b |
| else: |
| return True |
| |
| class C: |
| a: object |
| |
| class D: |
| b: bool |
| [out] |
| def f(x): |
| x :: __main__.C |
| r0, r1 :: object |
| r2 :: ptr |
| r3 :: object |
| r4 :: bit |
| r5 :: object |
| r6 :: __main__.D |
| r7 :: bool |
| L0: |
| r0 = borrow x.a |
| r1 = __main__.D :: type |
| r2 = get_element_ptr r0 ob_type :: PyObject |
| r3 = borrow load_mem r2 :: builtins.object* |
| r4 = r3 == r1 |
| if r4 goto L1 else goto L2 :: bool |
| L1: |
| r5 = borrow x.a |
| r6 = borrow cast(__main__.D, r5) |
| r7 = r6.b |
| return r7 |
| L2: |
| return 1 |
| |
| [case testBorrowListGetItem1] |
| from typing import List |
| |
| def literal_index(x: C) -> str: |
| return x.a[0] |
| |
| def negative_index(x: C) -> str: |
| return x.a[-1] |
| |
| def lvar_index(x: C, n: int) -> str: |
| return x.a[n] |
| |
| class C: |
| a: List[str] |
| |
| [out] |
| def literal_index(x): |
| x :: __main__.C |
| r0 :: list |
| r1 :: object |
| r2 :: str |
| L0: |
| r0 = borrow x.a |
| r1 = CPyList_GetItemShort(r0, 0) |
| r2 = cast(str, r1) |
| return r2 |
| def negative_index(x): |
| x :: __main__.C |
| r0 :: list |
| r1 :: object |
| r2 :: str |
| L0: |
| r0 = borrow x.a |
| r1 = CPyList_GetItemShort(r0, -2) |
| r2 = cast(str, r1) |
| return r2 |
| def lvar_index(x, n): |
| x :: __main__.C |
| n :: int |
| r0 :: list |
| r1 :: object |
| r2 :: str |
| L0: |
| r0 = borrow x.a |
| r1 = CPyList_GetItem(r0, n) |
| r2 = cast(str, r1) |
| return r2 |
| |
| [case testBorrowListGetItem2] |
| from typing import List |
| |
| def attr_before_index(x: C) -> str: |
| return x.a[x.n] |
| |
| def attr_after_index(a: List[C], i: int) -> int: |
| return a[i].n |
| |
| def attr_after_index_literal(a: List[C]) -> int: |
| return a[0].n |
| |
| class C: |
| a: List[str] |
| n: int |
| [out] |
| def attr_before_index(x): |
| x :: __main__.C |
| r0 :: list |
| r1 :: int |
| r2 :: object |
| r3 :: str |
| L0: |
| r0 = borrow x.a |
| r1 = borrow x.n |
| r2 = CPyList_GetItem(r0, r1) |
| r3 = cast(str, r2) |
| return r3 |
| def attr_after_index(a, i): |
| a :: list |
| i :: int |
| r0 :: object |
| r1 :: __main__.C |
| r2 :: int |
| L0: |
| r0 = CPyList_GetItemBorrow(a, i) |
| r1 = borrow cast(__main__.C, r0) |
| r2 = r1.n |
| return r2 |
| def attr_after_index_literal(a): |
| a :: list |
| r0 :: object |
| r1 :: __main__.C |
| r2 :: int |
| L0: |
| r0 = CPyList_GetItemShortBorrow(a, 0) |
| r1 = borrow cast(__main__.C, r0) |
| r2 = r1.n |
| return r2 |
| |
| [case testCannotBorrowListGetItem] |
| from typing import List |
| |
| def func_index(x: C) -> str: |
| return x.a[f()] |
| |
| def f() -> int: return 0 |
| |
| class C: |
| a: List[str] |
| [out] |
| def func_index(x): |
| x :: __main__.C |
| r0 :: list |
| r1 :: int |
| r2 :: object |
| r3 :: str |
| L0: |
| r0 = x.a |
| r1 = f() |
| r2 = CPyList_GetItem(r0, r1) |
| dec_ref r0 |
| dec_ref r1 :: int |
| r3 = cast(str, r2) |
| return r3 |
| def f(): |
| L0: |
| return 0 |
| |
| [case testBorrowListGetItemKeepAlive] |
| from typing import List |
| |
| def f() -> str: |
| a = [C()] |
| return a[0].s |
| |
| class C: |
| s: str |
| [out] |
| def f(): |
| r0 :: __main__.C |
| r1 :: list |
| r2 :: ptr |
| a :: list |
| r3 :: object |
| r4 :: __main__.C |
| r5 :: str |
| L0: |
| r0 = C() |
| r1 = PyList_New(1) |
| r2 = list_items r1 |
| buf_init_item r2, 0, r0 |
| a = r1 |
| r3 = CPyList_GetItemShortBorrow(a, 0) |
| r4 = borrow cast(__main__.C, r3) |
| r5 = r4.s |
| dec_ref a |
| return r5 |
| |
| [case testBorrowSetAttrObject] |
| from typing import Optional |
| |
| def f(x: Optional[C]) -> None: |
| if x is not None: |
| x.b = True |
| |
| def g(x: D) -> None: |
| x.c.b = False |
| |
| class C: |
| b: bool |
| |
| class D: |
| c: C |
| [out] |
| def f(x): |
| x :: union[__main__.C, None] |
| r0 :: object |
| r1 :: bit |
| r2 :: __main__.C |
| r3 :: bool |
| L0: |
| r0 = load_address _Py_NoneStruct |
| r1 = x != r0 |
| if r1 goto L1 else goto L2 :: bool |
| L1: |
| r2 = borrow cast(__main__.C, x) |
| r2.b = 1; r3 = is_error |
| L2: |
| return 1 |
| def g(x): |
| x :: __main__.D |
| r0 :: __main__.C |
| r1 :: bool |
| L0: |
| r0 = borrow x.c |
| r0.b = 0; r1 = is_error |
| return 1 |
| |
| [case testBorrowIntEquality] |
| def add(c: C) -> bool: |
| return c.x == c.y |
| |
| class C: |
| x: int |
| y: int |
| [out] |
| def add(c): |
| c :: __main__.C |
| r0, r1 :: int |
| r2 :: bit |
| L0: |
| r0 = borrow c.x |
| r1 = borrow c.y |
| r2 = int_eq r0, r1 |
| return r2 |
| |
| [case testBorrowIntLessThan] |
| def add(c: C) -> bool: |
| return c.x < c.y |
| |
| class C: |
| x: int |
| y: int |
| [out] |
| def add(c): |
| c :: __main__.C |
| r0, r1 :: int |
| r2 :: bit |
| L0: |
| r0 = borrow c.x |
| r1 = borrow c.y |
| r2 = int_lt r0, r1 |
| return r2 |
| |
| [case testBorrowIntCompareFinal] |
| from typing import Final |
| |
| X: Final = 10 |
| |
| def add(c: C) -> bool: |
| return c.x == X |
| |
| class C: |
| x: int |
| [out] |
| def add(c): |
| c :: __main__.C |
| r0 :: int |
| r1 :: bit |
| L0: |
| r0 = borrow c.x |
| r1 = int_eq r0, 20 |
| return r1 |
| |
| [case testBorrowIntArithmetic] |
| def add(c: C) -> int: |
| return c.x + c.y |
| |
| def sub(c: C) -> int: |
| return c.x - c.y |
| |
| class C: |
| x: int |
| y: int |
| [out] |
| def add(c): |
| c :: __main__.C |
| r0, r1, r2 :: int |
| L0: |
| r0 = borrow c.x |
| r1 = borrow c.y |
| r2 = CPyTagged_Add(r0, r1) |
| return r2 |
| def sub(c): |
| c :: __main__.C |
| r0, r1, r2 :: int |
| L0: |
| r0 = borrow c.x |
| r1 = borrow c.y |
| r2 = CPyTagged_Subtract(r0, r1) |
| return r2 |
| |
| [case testBorrowIntComparisonInIf] |
| def add(c: C, n: int) -> bool: |
| if c.x == c.y: |
| return True |
| return False |
| |
| class C: |
| x: int |
| y: int |
| [out] |
| def add(c, n): |
| c :: __main__.C |
| n, r0, r1 :: int |
| r2 :: bit |
| L0: |
| r0 = borrow c.x |
| r1 = borrow c.y |
| r2 = int_eq r0, r1 |
| if r2 goto L1 else goto L2 :: bool |
| L1: |
| return 1 |
| L2: |
| return 0 |
| |
| [case testBorrowIntInPlaceOp] |
| def add(c: C, n: int) -> None: |
| c.x += n |
| |
| def sub(c: C, n: int) -> None: |
| c.x -= c.y |
| |
| class C: |
| x: int |
| y: int |
| [out] |
| def add(c, n): |
| c :: __main__.C |
| n, r0, r1 :: int |
| r2 :: bool |
| L0: |
| r0 = borrow c.x |
| r1 = CPyTagged_Add(r0, n) |
| c.x = r1; r2 = is_error |
| return 1 |
| def sub(c, n): |
| c :: __main__.C |
| n, r0, r1, r2 :: int |
| r3 :: bool |
| L0: |
| r0 = borrow c.x |
| r1 = borrow c.y |
| r2 = CPyTagged_Subtract(r0, r1) |
| c.x = r2; r3 = is_error |
| return 1 |
| |
| [case testCoerceIntToI64_64bit] |
| from mypy_extensions import i64 |
| |
| def f(x: int) -> i64: |
| # TODO: On the fast path we shouldn't have a decref. Once we have high-level IR, |
| # coercion from int to i64 can be a single op, which makes it easier to |
| # generate optimal refcount handling for this case. |
| return x + 1 |
| [out] |
| def f(x): |
| x, r0 :: int |
| r1 :: native_int |
| r2 :: bit |
| r3, r4 :: i64 |
| r5 :: ptr |
| r6 :: c_ptr |
| r7 :: i64 |
| L0: |
| r0 = CPyTagged_Add(x, 2) |
| r1 = r0 & 1 |
| r2 = r1 == 0 |
| if r2 goto L1 else goto L2 :: bool |
| L1: |
| r3 = r0 >> 1 |
| dec_ref r0 :: int |
| r4 = r3 |
| goto L3 |
| L2: |
| r5 = r0 ^ 1 |
| r6 = r5 |
| r7 = CPyLong_AsInt64(r6) |
| r4 = r7 |
| dec_ref r0 :: int |
| L3: |
| return r4 |
| |
| [case testVecTSetItem_64bit] |
| from librt.vecs import vec |
| from mypy_extensions import i64 |
| |
| def f(v: vec[str], i: i64, x: str) -> None: |
| v[i] = x |
| [out] |
| def f(v, i, x): |
| v :: vec[str] |
| i :: i64 |
| x :: str |
| r0 :: native_int |
| r1 :: bit |
| r2 :: i64 |
| r3 :: bit |
| r4 :: bool |
| r5 :: i64 |
| r6 :: ptr |
| r7 :: i64 |
| r8 :: ptr |
| r9 :: str |
| L0: |
| r0 = v.len |
| r1 = i < r0 :: unsigned |
| if r1 goto L4 else goto L1 :: bool |
| L1: |
| r2 = i + r0 |
| r3 = r2 < r0 :: unsigned |
| if r3 goto L3 else goto L2 :: bool |
| L2: |
| r4 = raise IndexError |
| unreachable |
| L3: |
| r5 = r2 |
| goto L5 |
| L4: |
| r5 = i |
| L5: |
| r6 = v.items |
| r7 = r5 * 8 |
| r8 = r6 + r7 |
| r9 = borrow load_mem r8 :: builtins.str* |
| dec_ref r9 |
| inc_ref x |
| set_mem r8, x :: builtins.str* |
| return 1 |
| |
| [case testVecTConstructFromListMultiply_64bit] |
| from typing import Optional |
| from librt.vecs import vec |
| from mypy_extensions import i64 |
| |
| def f(n: i64) -> vec[Optional[str]]: |
| return vec[Optional[str]]([None] * n) |
| [out] |
| def f(n): |
| n :: i64 |
| r0, r1 :: object |
| r2, r3 :: ptr |
| r4 :: vec[str | None] |
| r5 :: ptr |
| r6 :: i64 |
| r7, r8 :: ptr |
| r9 :: bit |
| r10 :: ptr |
| L0: |
| r0 = box(None, 1) |
| r1 = load_address PyUnicode_Type |
| r2 = r1 |
| r3 = r2 | 1 |
| r4 = VecTApi.alloc(n, n, r3) |
| r5 = r4.items |
| r6 = n * 8 |
| r7 = r5 + r6 |
| r8 = r5 |
| L1: |
| r9 = r8 < r7 :: unsigned |
| if r9 goto L2 else goto L3 :: bool |
| L2: |
| inc_ref r0 |
| set_mem r8, r0 :: union* |
| r10 = r8 + 8 |
| r8 = r10 |
| goto L1 |
| L3: |
| return r4 |
| |
| [case testVecTForLoop_64bit] |
| from librt.vecs import vec |
| from mypy_extensions import i64 |
| |
| def f(v: vec[str]) -> i64: |
| t: i64 = 0 |
| for s in v: |
| g(s) |
| return t |
| |
| def g(s: str) -> None: pass |
| [out] |
| def f(v): |
| v :: vec[str] |
| t :: i64 |
| r0, r1 :: native_int |
| r2 :: bit |
| r3 :: ptr |
| r4 :: native_int |
| r5 :: ptr |
| r6, s :: str |
| r7 :: None |
| r8 :: native_int |
| L0: |
| t = 0 |
| r0 = 0 |
| L1: |
| r1 = v.len |
| r2 = r0 < r1 :: signed |
| if r2 goto L2 else goto L4 :: bool |
| L2: |
| r3 = v.items |
| r4 = r0 * 8 |
| r5 = r3 + r4 |
| r6 = load_mem r5 :: builtins.str* |
| s = r6 |
| r7 = g(s) |
| dec_ref s |
| L3: |
| r8 = r0 + 1 |
| r0 = r8 |
| goto L1 |
| L4: |
| return t |
| def g(s): |
| s :: str |
| L0: |
| return 1 |
| |
| [case testVecTConstructFromListExpr_64bit] |
| from librt.vecs import vec |
| |
| def f() -> vec[str]: |
| return vec[str](['x', 'y']) |
| [out] |
| def f(): |
| r0, r1 :: str |
| r2 :: object |
| r3 :: ptr |
| r4 :: vec[str] |
| r5, r6, r7 :: ptr |
| L0: |
| r0 = 'x' |
| r1 = 'y' |
| r2 = load_address PyUnicode_Type |
| r3 = r2 |
| r4 = VecTApi.alloc(2, 2, r3) |
| r5 = r4.items |
| inc_ref r0 |
| set_mem r5, r0 :: builtins.str* |
| r6 = r5 + 8 |
| inc_ref r1 |
| set_mem r6, r1 :: builtins.str* |
| r7 = r6 + 8 |
| return r4 |
| |
| [case testVecI64GetItemBorrowVec_64bit] |
| from librt.vecs import vec |
| from mypy_extensions import i64 |
| |
| class C: |
| v: vec[i64] |
| |
| def f(self, x: i64) -> i64: |
| return self.v[x] |
| [out] |
| def C.f(self, x): |
| self :: __main__.C |
| x :: i64 |
| r0 :: vec[i64] |
| r1 :: native_int |
| r2 :: bit |
| r3 :: i64 |
| r4 :: bit |
| r5 :: bool |
| r6 :: i64 |
| r7 :: ptr |
| r8 :: i64 |
| r9 :: ptr |
| r10 :: i64 |
| L0: |
| r0 = borrow self.v |
| r1 = r0.len |
| r2 = x < r1 :: unsigned |
| if r2 goto L4 else goto L1 :: bool |
| L1: |
| r3 = x + r1 |
| r4 = r3 < r1 :: unsigned |
| if r4 goto L3 else goto L2 :: bool |
| L2: |
| r5 = raise IndexError |
| unreachable |
| L3: |
| r6 = r3 |
| goto L5 |
| L4: |
| r6 = x |
| L5: |
| r7 = r0.items |
| r8 = r6 * 8 |
| r9 = r7 + r8 |
| r10 = load_mem r9 :: i64* |
| return r10 |
| |
| [case testVecI64LenBorrowVec_64bit] |
| from librt.vecs import vec |
| from mypy_extensions import i64 |
| |
| class C: |
| v: vec[i64] |
| |
| def f(self, x: i64) -> i64: |
| return len(self.v) |
| [out] |
| def C.f(self, x): |
| self :: __main__.C |
| x :: i64 |
| r0 :: vec[i64] |
| r1 :: native_int |
| L0: |
| r0 = borrow self.v |
| r1 = r0.len |
| return r1 |
| |
| [case testVecNestedAppend] |
| from librt.vecs import vec, append |
| |
| def f(vv: vec[vec[str]], v: vec[str]) -> vec[vec[str]]: |
| return append(vv, v) |
| [out] |
| def f(vv, v): |
| vv :: vec[vec[str]] |
| v :: vec[str] |
| r0 :: native_int |
| r1 :: ptr |
| r2, r3 :: VecNestedBufItem{len:native_int, items:ptr} |
| r4 :: vec[vec[str]] |
| L0: |
| r0 = v.len |
| r1 = v.items |
| r2 = set_element undef VecNestedBufItem, len, r0 |
| r3 = set_element r2, items, r1 |
| inc_ref vv |
| r4 = VecNestedApi.append(vv, r3) |
| return r4 |
| |
| [case testVecTGetItem_64bit] |
| from librt.vecs import vec |
| from mypy_extensions import i64 |
| |
| def f(v: vec[str], n: i64) -> str: |
| return v[n] |
| [out] |
| def f(v, n): |
| v :: vec[str] |
| n :: i64 |
| r0 :: native_int |
| r1 :: bit |
| r2 :: i64 |
| r3 :: bit |
| r4 :: bool |
| r5 :: i64 |
| r6 :: ptr |
| r7 :: i64 |
| r8 :: ptr |
| r9 :: str |
| L0: |
| r0 = v.len |
| r1 = n < r0 :: unsigned |
| if r1 goto L4 else goto L1 :: bool |
| L1: |
| r2 = n + r0 |
| r3 = r2 < r0 :: unsigned |
| if r3 goto L3 else goto L2 :: bool |
| L2: |
| r4 = raise IndexError |
| unreachable |
| L3: |
| r5 = r2 |
| goto L5 |
| L4: |
| r5 = n |
| L5: |
| r6 = v.items |
| r7 = r5 * 8 |
| r8 = r6 + r7 |
| r9 = load_mem r8 :: builtins.str* |
| return r9 |
| |
| [case testVecNestedGetItem_64bit] |
| from librt.vecs import vec |
| from mypy_extensions import i64 |
| |
| def f(v: vec[vec[str]], n: i64) -> None: |
| vv = vec[vec[str]]()[n] |
| [out] |
| def f(v, n): |
| v :: vec[vec[str]] |
| n :: i64 |
| r0 :: object |
| r1 :: ptr |
| r2 :: vec[vec[str]] |
| r3 :: native_int |
| r4 :: bit |
| r5 :: i64 |
| r6 :: bit |
| r7 :: bool |
| r8 :: i64 |
| r9 :: ptr |
| r10 :: i64 |
| r11 :: ptr |
| r12, vv :: vec[str] |
| L0: |
| r0 = load_address PyUnicode_Type |
| r1 = r0 |
| r2 = VecNestedApi.alloc(0, 0, r1, 1) |
| r3 = r2.len |
| r4 = n < r3 :: unsigned |
| if r4 goto L4 else goto L1 :: bool |
| L1: |
| r5 = n + r3 |
| r6 = r5 < r3 :: unsigned |
| if r6 goto L3 else goto L6 :: bool |
| L2: |
| r7 = raise IndexError |
| unreachable |
| L3: |
| r8 = r5 |
| goto L5 |
| L4: |
| r8 = n |
| L5: |
| r9 = r2.items |
| r10 = r8 * 16 |
| r11 = r9 + r10 |
| r12 = load_mem r11 :: vec[str]* |
| dec_ref r2 |
| vv = r12 |
| dec_ref vv |
| return 1 |
| L6: |
| dec_ref r2 |
| goto L2 |
| |
| [case testVecNestedGetItemBorrow_64bit] |
| from librt.vecs import vec |
| from mypy_extensions import i64 |
| |
| def f(v: vec[vec[i64]], n: i64, m: i64) -> i64: |
| return v[n][m] |
| [out] |
| def f(v, n, m): |
| v :: vec[vec[i64]] |
| n, m :: i64 |
| r0 :: native_int |
| r1 :: bit |
| r2 :: i64 |
| r3 :: bit |
| r4 :: bool |
| r5 :: i64 |
| r6 :: ptr |
| r7 :: i64 |
| r8 :: ptr |
| r9 :: vec[i64] |
| r10 :: native_int |
| r11 :: bit |
| r12 :: i64 |
| r13 :: bit |
| r14 :: bool |
| r15 :: i64 |
| r16 :: ptr |
| r17 :: i64 |
| r18 :: ptr |
| r19 :: i64 |
| L0: |
| r0 = v.len |
| r1 = n < r0 :: unsigned |
| if r1 goto L4 else goto L1 :: bool |
| L1: |
| r2 = n + r0 |
| r3 = r2 < r0 :: unsigned |
| if r3 goto L3 else goto L2 :: bool |
| L2: |
| r4 = raise IndexError |
| unreachable |
| L3: |
| r5 = r2 |
| goto L5 |
| L4: |
| r5 = n |
| L5: |
| r6 = v.items |
| r7 = r5 * 16 |
| r8 = r6 + r7 |
| r9 = borrow load_mem r8 :: vec[i64]* |
| r10 = r9.len |
| r11 = m < r10 :: unsigned |
| if r11 goto L9 else goto L6 :: bool |
| L6: |
| r12 = m + r10 |
| r13 = r12 < r10 :: unsigned |
| if r13 goto L8 else goto L7 :: bool |
| L7: |
| r14 = raise IndexError |
| unreachable |
| L8: |
| r15 = r12 |
| goto L10 |
| L9: |
| r15 = m |
| L10: |
| r16 = r9.items |
| r17 = r15 * 8 |
| r18 = r16 + r17 |
| r19 = load_mem r18 :: i64* |
| return r19 |
| |
| [case testVecPop] |
| from librt.vecs import vec, pop, append |
| from mypy_extensions import i64 |
| |
| def f() -> vec[i64]: |
| v = vec[i64]() |
| v = append(v, 7) |
| v, x = pop(v) |
| return v |
| [out] |
| def f(): |
| r0, v, r1 :: vec[i64] |
| r2 :: tuple[vec[i64], i64] |
| r3 :: vec[i64] |
| r4 :: i64 |
| r5 :: vec[i64] |
| r6, x :: i64 |
| L0: |
| r0 = VecI64Api.alloc(0, 0) |
| v = r0 |
| r1 = VecI64Api.append(v, 7) |
| v = r1 |
| r2 = VecI64Api.pop(v, -1) |
| r3 = borrow r2[0] |
| r4 = borrow r2[1] |
| r5 = unborrow r3 |
| v = r5 |
| r6 = unborrow r4 |
| x = r6 |
| return v |
| |
| [case testVecNestedPop] |
| from librt.vecs import vec, pop |
| |
| def f(v: vec[vec[str]]) -> vec[str]: |
| vv, x = pop(v) |
| return x |
| [out] |
| def f(v): |
| v :: vec[vec[str]] |
| r0 :: tuple[vec[vec[str]], VecNestedBufItem{len:native_int, items:ptr}] |
| r1, r2 :: vec[vec[str]] |
| r3, r4 :: VecNestedBufItem{len:native_int, items:ptr} |
| r5 :: native_int |
| r6 :: ptr |
| r7, r8 :: vec[str] |
| r9 :: tuple[vec[vec[str]], vec[str]] |
| r10 :: vec[vec[str]] |
| r11 :: vec[str] |
| r12, vv :: vec[vec[str]] |
| r13, x :: vec[str] |
| L0: |
| inc_ref v |
| r0 = VecNestedApi.pop(v, -1) |
| r1 = borrow r0[0] |
| r2 = unborrow r1 |
| r3 = borrow r0[1] |
| r4 = unborrow r3 |
| r5 = r4.len |
| r6 = r4.items |
| r7 = set_element undef vec[str], len, r5 |
| r8 = set_element r7, items, r6 |
| r9 = (r2, r8) |
| r10 = borrow r9[0] |
| r11 = borrow r9[1] |
| r12 = unborrow r10 |
| vv = r12 |
| dec_ref vv |
| r13 = unborrow r11 |
| x = r13 |
| return x |
| |
| [case testPropertySetterCallWithRefcountedObject] |
| class Foo: |
| def __init__(self) -> None: |
| self.attr = "unmodified" |
| |
| class A: |
| def __init__(self) -> None: |
| self._foo = Foo() |
| |
| @property |
| def foo(self) -> Foo: |
| return self._foo |
| |
| @foo.setter |
| def foo(self, val : Foo) -> None: |
| self._foo = val |
| |
| def f(a: A): |
| a.foo = Foo() |
| [out] |
| def Foo.__init__(self): |
| self :: __main__.Foo |
| r0 :: str |
| L0: |
| r0 = 'unmodified' |
| inc_ref r0 |
| self.attr = r0 |
| return 1 |
| def A.__init__(self): |
| self :: __main__.A |
| r0 :: __main__.Foo |
| L0: |
| r0 = Foo() |
| self._foo = r0 |
| return 1 |
| def A.foo(self): |
| self :: __main__.A |
| r0 :: __main__.Foo |
| L0: |
| r0 = self._foo |
| return r0 |
| def A.__mypyc_setter__foo(self, val): |
| self :: __main__.A |
| val :: __main__.Foo |
| r0 :: bool |
| L0: |
| inc_ref val |
| self._foo = val; r0 = is_error |
| return 1 |
| def f(a): |
| a :: __main__.A |
| r0 :: __main__.Foo |
| r1 :: bool |
| r2 :: object |
| L0: |
| r0 = Foo() |
| a.foo = r0; r1 = is_error |
| dec_ref r0 |
| r2 = box(None, 1) |
| inc_ref r2 |
| return r2 |
| |
| [case testPropertySetterCallWithNonRefcountedObject_64bit] |
| from mypy_extensions import i64 |
| |
| class A: |
| def __init__(self) -> None: |
| self._foo = i64(0) |
| |
| @property |
| def foo(self) -> i64: |
| return self._foo |
| |
| @foo.setter |
| def foo(self, val : i64) -> None: |
| self._foo = val |
| |
| def f(a: A, i: int): |
| a.foo = i64(i) |
| [out] |
| def A.__init__(self): |
| self :: __main__.A |
| L0: |
| self._foo = 0 |
| return 1 |
| def A.foo(self): |
| self :: __main__.A |
| r0 :: i64 |
| L0: |
| r0 = self._foo |
| return r0 |
| def A.__mypyc_setter__foo(self, val): |
| self :: __main__.A |
| val :: i64 |
| r0 :: bool |
| L0: |
| self._foo = val; r0 = is_error |
| return 1 |
| def f(a, i): |
| a :: __main__.A |
| i :: int |
| r0 :: native_int |
| r1 :: bit |
| r2, r3 :: i64 |
| r4 :: ptr |
| r5 :: c_ptr |
| r6 :: i64 |
| r7 :: bool |
| r8 :: object |
| L0: |
| r0 = i & 1 |
| r1 = r0 == 0 |
| if r1 goto L1 else goto L2 :: bool |
| L1: |
| r2 = i >> 1 |
| r3 = r2 |
| goto L3 |
| L2: |
| r4 = i ^ 1 |
| r5 = r4 |
| r6 = CPyLong_AsInt64(r5) |
| r3 = r6 |
| L3: |
| a.foo = r3; r7 = is_error |
| r8 = box(None, 1) |
| inc_ref r8 |
| return r8 |