| -- Test cases for data flow analysis. |
| |
| [case testSimple_MaybeDefined] |
| def f(a: int) -> None: |
| x = 1 |
| if x == a: |
| y = 1 |
| else: |
| z = 1 |
| [out] |
| def f(a): |
| a, x :: int |
| r0 :: native_int |
| r1, r2, r3 :: bit |
| y, z :: int |
| L0: |
| x = 2 |
| r0 = x & 1 |
| r1 = r0 != 0 |
| if r1 goto L1 else goto L2 :: bool |
| L1: |
| r2 = CPyTagged_IsEq_(x, a) |
| if r2 goto L3 else goto L4 :: bool |
| L2: |
| r3 = x == a |
| if r3 goto L3 else goto L4 :: bool |
| L3: |
| y = 2 |
| goto L5 |
| L4: |
| z = 2 |
| L5: |
| return 1 |
| (0, 0) {a} {a, x} |
| (0, 1) {a, x} {a, x} |
| (0, 2) {a, x} {a, x} |
| (0, 3) {a, x} {a, x} |
| (1, 0) {a, x} {a, x} |
| (1, 1) {a, x} {a, x} |
| (2, 0) {a, x} {a, x} |
| (2, 1) {a, x} {a, x} |
| (3, 0) {a, x} {a, x, y} |
| (3, 1) {a, x, y} {a, x, y} |
| (4, 0) {a, x} {a, x, z} |
| (4, 1) {a, x, z} {a, x, z} |
| (5, 0) {a, x, y, z} {a, x, y, z} |
| |
| [case testSimple_Liveness] |
| def f(a: int) -> int: |
| x = 1 |
| if x == 1: |
| return a |
| else: |
| return x |
| [out] |
| def f(a): |
| a, x :: int |
| r0 :: bit |
| L0: |
| x = 2 |
| r0 = x == 2 |
| if r0 goto L1 else goto L2 :: bool |
| L1: |
| return a |
| L2: |
| return x |
| L3: |
| unreachable |
| (0, 0) {a} {a, x} |
| (0, 1) {a, x} {a, r0, x} |
| (0, 2) {a, r0, x} {a, x} |
| (1, 0) {a} {} |
| (2, 0) {x} {} |
| (3, 0) {} {} |
| |
| [case testSpecial_Liveness] |
| def f() -> int: |
| x = 1 |
| y = 1 |
| x = 2 |
| return x |
| [out] |
| def f(): |
| x, y :: int |
| L0: |
| x = 2 |
| y = 2 |
| x = 4 |
| return x |
| (0, 0) {} {} |
| (0, 1) {} {} |
| (0, 2) {} {x} |
| (0, 3) {x} {} |
| |
| [case testSpecial2_Liveness] |
| def f(a: int) -> int: |
| a = 1 |
| a = 2 |
| a = 3 |
| return a |
| [out] |
| def f(a): |
| a :: int |
| L0: |
| a = 2 |
| a = 4 |
| a = 6 |
| return a |
| (0, 0) {} {} |
| (0, 1) {} {} |
| (0, 2) {} {a} |
| (0, 3) {a} {} |
| |
| [case testSimple_MustDefined] |
| def f(a: int) -> None: |
| if a == 1: |
| y = 1 |
| x = 2 |
| else: |
| x = 2 |
| [out] |
| def f(a): |
| a :: int |
| r0 :: bit |
| y, x :: int |
| L0: |
| r0 = a == 2 |
| if r0 goto L1 else goto L2 :: bool |
| L1: |
| y = 2 |
| x = 4 |
| goto L3 |
| L2: |
| x = 4 |
| L3: |
| return 1 |
| (0, 0) {a} {a} |
| (0, 1) {a} {a} |
| (1, 0) {a} {a, y} |
| (1, 1) {a, y} {a, x, y} |
| (1, 2) {a, x, y} {a, x, y} |
| (2, 0) {a} {a, x} |
| (2, 1) {a, x} {a, x} |
| (3, 0) {a, x} {a, x} |
| |
| [case testTwoArgs_MustDefined] |
| def f(x: int, y: int) -> int: |
| return x |
| [out] |
| def f(x, y): |
| x, y :: int |
| L0: |
| return x |
| (0, 0) {x, y} {x, y} |
| |
| [case testLoop_MustDefined] |
| def f(n: int) -> None: |
| while n < 5: |
| n = n + 1 |
| m = n |
| [out] |
| def f(n): |
| n :: int |
| r0 :: native_int |
| r1, r2, r3 :: bit |
| r4, m :: int |
| L0: |
| L1: |
| r0 = n & 1 |
| r1 = r0 != 0 |
| if r1 goto L2 else goto L3 :: bool |
| L2: |
| r2 = CPyTagged_IsLt_(n, 10) |
| if r2 goto L4 else goto L5 :: bool |
| L3: |
| r3 = n < 10 :: signed |
| if r3 goto L4 else goto L5 :: bool |
| L4: |
| r4 = CPyTagged_Add(n, 2) |
| n = r4 |
| m = n |
| goto L1 |
| L5: |
| return 1 |
| (0, 0) {n} {n} |
| (1, 0) {n} {n} |
| (1, 1) {n} {n} |
| (1, 2) {n} {n} |
| (2, 0) {n} {n} |
| (2, 1) {n} {n} |
| (3, 0) {n} {n} |
| (3, 1) {n} {n} |
| (4, 0) {n} {n} |
| (4, 1) {n} {n} |
| (4, 2) {n} {m, n} |
| (4, 3) {m, n} {m, n} |
| (5, 0) {n} {n} |
| |
| [case testMultiPass_Liveness] |
| def f(n: int) -> None: |
| x = 1 |
| y = 1 |
| while n < 1: |
| n = y |
| while n < 2: |
| n = 1 |
| n = x |
| [out] |
| def f(n): |
| n, x, y :: int |
| r0 :: native_int |
| r1, r2, r3 :: bit |
| r4 :: native_int |
| r5, r6, r7 :: bit |
| L0: |
| x = 2 |
| y = 2 |
| L1: |
| r0 = n & 1 |
| r1 = r0 != 0 |
| if r1 goto L2 else goto L3 :: bool |
| L2: |
| r2 = CPyTagged_IsLt_(n, 2) |
| if r2 goto L4 else goto L10 :: bool |
| L3: |
| r3 = n < 2 :: signed |
| if r3 goto L4 else goto L10 :: bool |
| L4: |
| n = y |
| L5: |
| r4 = n & 1 |
| r5 = r4 != 0 |
| if r5 goto L6 else goto L7 :: bool |
| L6: |
| r6 = CPyTagged_IsLt_(n, 4) |
| if r6 goto L8 else goto L9 :: bool |
| L7: |
| r7 = n < 4 :: signed |
| if r7 goto L8 else goto L9 :: bool |
| L8: |
| n = 2 |
| n = x |
| goto L5 |
| L9: |
| goto L1 |
| L10: |
| return 1 |
| (0, 0) {n} {n, x} |
| (0, 1) {n, x} {n, x, y} |
| (0, 2) {n, x, y} {n, x, y} |
| (1, 0) {n, x, y} {n, r0, x, y} |
| (1, 1) {n, r0, x, y} {n, r1, x, y} |
| (1, 2) {n, r1, x, y} {n, x, y} |
| (2, 0) {n, x, y} {r2, x, y} |
| (2, 1) {r2, x, y} {x, y} |
| (3, 0) {n, x, y} {r3, x, y} |
| (3, 1) {r3, x, y} {x, y} |
| (4, 0) {x, y} {n, x, y} |
| (4, 1) {n, x, y} {n, x, y} |
| (5, 0) {n, x, y} {n, r4, x, y} |
| (5, 1) {n, r4, x, y} {n, r5, x, y} |
| (5, 2) {n, r5, x, y} {n, x, y} |
| (6, 0) {n, x, y} {n, r6, x, y} |
| (6, 1) {n, r6, x, y} {n, x, y} |
| (7, 0) {n, x, y} {n, r7, x, y} |
| (7, 1) {n, r7, x, y} {n, x, y} |
| (8, 0) {x, y} {x, y} |
| (8, 1) {x, y} {n, x, y} |
| (8, 2) {n, x, y} {n, x, y} |
| (9, 0) {n, x, y} {n, x, y} |
| (10, 0) {} {} |
| |
| [case testCall_Liveness] |
| def f(x: int) -> int: |
| a = f(1) |
| return f(a) + a |
| [out] |
| def f(x): |
| x, r0, a, r1, r2, r3 :: int |
| L0: |
| r0 = f(2) |
| if is_error(r0) goto L3 (error at f:2) else goto L1 |
| L1: |
| a = r0 |
| r1 = f(a) |
| if is_error(r1) goto L3 (error at f:3) else goto L2 |
| L2: |
| r2 = CPyTagged_Add(r1, a) |
| return r2 |
| L3: |
| r3 = <error> :: int |
| return r3 |
| (0, 0) {} {r0} |
| (0, 1) {r0} {r0} |
| (1, 0) {r0} {a} |
| (1, 1) {a} {a, r1} |
| (1, 2) {a, r1} {a, r1} |
| (2, 0) {a, r1} {r2} |
| (2, 1) {r2} {} |
| (3, 0) {} {r3} |
| (3, 1) {r3} {} |
| |
| [case testLoop_MaybeDefined] |
| def f(a: int) -> None: |
| while a < a: |
| while a < a: |
| y = a |
| x = a |
| [out] |
| def f(a): |
| a :: int |
| r0 :: native_int |
| r1 :: bit |
| r2 :: native_int |
| r3, r4, r5 :: bit |
| r6 :: native_int |
| r7 :: bit |
| r8 :: native_int |
| r9, r10, r11 :: bit |
| y, x :: int |
| L0: |
| L1: |
| r0 = a & 1 |
| r1 = r0 != 0 |
| if r1 goto L3 else goto L2 :: bool |
| L2: |
| r2 = a & 1 |
| r3 = r2 != 0 |
| if r3 goto L3 else goto L4 :: bool |
| L3: |
| r4 = CPyTagged_IsLt_(a, a) |
| if r4 goto L5 else goto L12 :: bool |
| L4: |
| r5 = a < a :: signed |
| if r5 goto L5 else goto L12 :: bool |
| L5: |
| L6: |
| r6 = a & 1 |
| r7 = r6 != 0 |
| if r7 goto L8 else goto L7 :: bool |
| L7: |
| r8 = a & 1 |
| r9 = r8 != 0 |
| if r9 goto L8 else goto L9 :: bool |
| L8: |
| r10 = CPyTagged_IsLt_(a, a) |
| if r10 goto L10 else goto L11 :: bool |
| L9: |
| r11 = a < a :: signed |
| if r11 goto L10 else goto L11 :: bool |
| L10: |
| y = a |
| goto L6 |
| L11: |
| x = a |
| goto L1 |
| L12: |
| return 1 |
| (0, 0) {a} {a} |
| (1, 0) {a, x, y} {a, x, y} |
| (1, 1) {a, x, y} {a, x, y} |
| (1, 2) {a, x, y} {a, x, y} |
| (2, 0) {a, x, y} {a, x, y} |
| (2, 1) {a, x, y} {a, x, y} |
| (2, 2) {a, x, y} {a, x, y} |
| (3, 0) {a, x, y} {a, x, y} |
| (3, 1) {a, x, y} {a, x, y} |
| (4, 0) {a, x, y} {a, x, y} |
| (4, 1) {a, x, y} {a, x, y} |
| (5, 0) {a, x, y} {a, x, y} |
| (6, 0) {a, x, y} {a, x, y} |
| (6, 1) {a, x, y} {a, x, y} |
| (6, 2) {a, x, y} {a, x, y} |
| (7, 0) {a, x, y} {a, x, y} |
| (7, 1) {a, x, y} {a, x, y} |
| (7, 2) {a, x, y} {a, x, y} |
| (8, 0) {a, x, y} {a, x, y} |
| (8, 1) {a, x, y} {a, x, y} |
| (9, 0) {a, x, y} {a, x, y} |
| (9, 1) {a, x, y} {a, x, y} |
| (10, 0) {a, x, y} {a, x, y} |
| (10, 1) {a, x, y} {a, x, y} |
| (11, 0) {a, x, y} {a, x, y} |
| (11, 1) {a, x, y} {a, x, y} |
| (12, 0) {a, x, y} {a, x, y} |
| |
| [case testTrivial_BorrowedArgument] |
| def f(a: int, b: int) -> int: |
| return b |
| [out] |
| def f(a, b): |
| a, b :: int |
| L0: |
| return b |
| (0, 0) {a, b} {a, b} |
| |
| [case testSimple_BorrowedArgument] |
| def f(a: int) -> int: |
| b = a |
| a = 1 |
| return a |
| [out] |
| def f(a): |
| a, b :: int |
| L0: |
| b = a |
| a = 2 |
| return a |
| (0, 0) {a} {a} |
| (0, 1) {a} {} |
| (0, 2) {} {} |
| |
| [case testConditional_BorrowedArgument] |
| def f(a: int) -> int: |
| if a == a: |
| x = 2 |
| a = 1 |
| else: |
| x = 1 |
| return x |
| [out] |
| def f(a): |
| a :: int |
| r0 :: native_int |
| r1, r2, r3 :: bit |
| x :: int |
| L0: |
| r0 = a & 1 |
| r1 = r0 != 0 |
| if r1 goto L1 else goto L2 :: bool |
| L1: |
| r2 = CPyTagged_IsEq_(a, a) |
| if r2 goto L3 else goto L4 :: bool |
| L2: |
| r3 = a == a |
| if r3 goto L3 else goto L4 :: bool |
| L3: |
| x = 4 |
| a = 2 |
| goto L5 |
| L4: |
| x = 2 |
| L5: |
| return x |
| (0, 0) {a} {a} |
| (0, 1) {a} {a} |
| (0, 2) {a} {a} |
| (1, 0) {a} {a} |
| (1, 1) {a} {a} |
| (2, 0) {a} {a} |
| (2, 1) {a} {a} |
| (3, 0) {a} {a} |
| (3, 1) {a} {} |
| (3, 2) {} {} |
| (4, 0) {a} {a} |
| (4, 1) {a} {a} |
| (5, 0) {} {} |
| |
| [case testLoop_BorrowedArgument] |
| 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 :: native_int |
| r1 :: bit |
| r2 :: native_int |
| r3, r4, r5 :: bit |
| r6, r7 :: int |
| L0: |
| sum = 0 |
| i = 0 |
| L1: |
| r0 = i & 1 |
| r1 = r0 != 0 |
| if r1 goto L3 else goto L2 :: bool |
| L2: |
| r2 = a & 1 |
| r3 = r2 != 0 |
| if r3 goto L3 else goto L4 :: bool |
| L3: |
| r4 = CPyTagged_IsLt_(a, i) |
| if r4 goto L6 else goto L5 :: bool |
| L4: |
| r5 = i <= a :: signed |
| if r5 goto L5 else goto L6 :: bool |
| L5: |
| r6 = CPyTagged_Add(sum, i) |
| sum = r6 |
| r7 = CPyTagged_Add(i, 2) |
| i = r7 |
| goto L1 |
| L6: |
| return sum |
| (0, 0) {a} {a} |
| (0, 1) {a} {a} |
| (0, 2) {a} {a} |
| (1, 0) {a} {a} |
| (1, 1) {a} {a} |
| (1, 2) {a} {a} |
| (2, 0) {a} {a} |
| (2, 1) {a} {a} |
| (2, 2) {a} {a} |
| (3, 0) {a} {a} |
| (3, 1) {a} {a} |
| (4, 0) {a} {a} |
| (4, 1) {a} {a} |
| (5, 0) {a} {a} |
| (5, 1) {a} {a} |
| (5, 2) {a} {a} |
| (5, 3) {a} {a} |
| (5, 4) {a} {a} |
| (6, 0) {a} {a} |
| |
| [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 testExceptUndefined_Liveness] |
| def lol(x: object) -> int: |
| try: |
| st = id(x) |
| except Exception: |
| return -1 |
| return st + 1 |
| [out] |
| def lol(x): |
| x :: object |
| r0, st :: int |
| r1 :: tuple[object, object, object] |
| r2 :: object |
| r3 :: str |
| r4 :: object |
| r5, r6 :: bit |
| r7, r8 :: int |
| L0: |
| L1: |
| r0 = CPyTagged_Id(x) |
| st = r0 |
| goto L10 |
| L2: |
| r1 = CPy_CatchError() |
| r2 = builtins :: module |
| r3 = 'Exception' |
| r4 = CPyObject_GetAttr(r2, r3) |
| if is_error(r4) goto L8 (error at lol:4) else goto L3 |
| L3: |
| r5 = CPy_ExceptionMatches(r4) |
| if r5 goto L4 else goto L5 :: bool |
| L4: |
| CPy_RestoreExcInfo(r1) |
| return -2 |
| L5: |
| CPy_Reraise() |
| if not 0 goto L8 else goto L6 :: bool |
| L6: |
| unreachable |
| L7: |
| CPy_RestoreExcInfo(r1) |
| goto L10 |
| L8: |
| CPy_RestoreExcInfo(r1) |
| r6 = CPy_KeepPropagating() |
| if not r6 goto L11 else goto L9 :: bool |
| L9: |
| unreachable |
| L10: |
| r7 = CPyTagged_Add(st, 2) |
| return r7 |
| L11: |
| r8 = <error> :: int |
| return r8 |
| (0, 0) {x} {x} |
| (1, 0) {x} {r0} |
| (1, 1) {r0} {st} |
| (1, 2) {st} {st} |
| (2, 0) {} {r1} |
| (2, 1) {r1} {r1, r2} |
| (2, 2) {r1, r2} {r1, r2, r3} |
| (2, 3) {r1, r2, r3} {r1, r4} |
| (2, 4) {r1, r4} {r1, r4} |
| (3, 0) {r1, r4} {r1, r5} |
| (3, 1) {r1, r5} {r1} |
| (4, 0) {r1} {} |
| (4, 1) {} {} |
| (5, 0) {r1} {r1} |
| (5, 1) {r1} {r1} |
| (6, 0) {} {} |
| (7, 0) {r1, st} {st} |
| (7, 1) {st} {st} |
| (8, 0) {r1} {} |
| (8, 1) {} {r6} |
| (8, 2) {r6} {} |
| (9, 0) {} {} |
| (10, 0) {st} {r7} |
| (10, 1) {r7} {} |
| (11, 0) {} {r8} |
| (11, 1) {r8} {} |