| -- Test cases for exception handling insertion transform. |
| -- |
| -- The result includes refcount handling since these two transforms interact. |
| |
| [case testListGetAndUnboxError] |
| from typing import List |
| def f(x: List[int]) -> int: |
| return x[0] |
| [out] |
| def f(x): |
| x :: list |
| r0 :: object |
| r1, r2 :: int |
| L0: |
| r0 = CPyList_GetItemShort(x, 0) |
| if is_error(r0) goto L3 (error at f:3) else goto L1 |
| L1: |
| r1 = unbox(int, r0) |
| dec_ref r0 |
| if is_error(r1) goto L3 (error at f:3) else goto L2 |
| L2: |
| return r1 |
| L3: |
| r2 = <error> :: int |
| return r2 |
| |
| [case testListAppendAndSetItemError] |
| from typing import List |
| def f(x: List[int], y: int, z: int) -> None: |
| x.append(y) |
| x[y] = z |
| [out] |
| def f(x, y, z): |
| x :: list |
| y, z :: int |
| r0 :: object |
| r1 :: int32 |
| r2 :: bit |
| r3 :: object |
| r4 :: bit |
| r5 :: None |
| L0: |
| inc_ref y :: int |
| r0 = box(int, y) |
| r1 = PyList_Append(x, r0) |
| dec_ref r0 |
| r2 = r1 >= 0 :: signed |
| if not r2 goto L3 (error at f:3) else goto L1 :: bool |
| L1: |
| inc_ref z :: int |
| r3 = box(int, z) |
| r4 = CPyList_SetItem(x, y, r3) |
| if not r4 goto L3 (error at f:4) else goto L2 :: bool |
| L2: |
| return 1 |
| L3: |
| r5 = <error> :: None |
| return r5 |
| |
| [case testOptionalHandling] |
| from typing import Optional |
| |
| class A: pass |
| |
| def f(x: Optional[A]) -> int: |
| if x is None: |
| return 1 |
| if x is not None: |
| return 2 |
| return 3 |
| [out] |
| def f(x): |
| x :: union[__main__.A, None] |
| r0 :: object |
| r1 :: bit |
| r2 :: __main__.A |
| r3 :: object |
| r4, r5 :: bit |
| r6 :: int |
| L0: |
| r0 = box(None, 1) |
| r1 = x == r0 |
| if r1 goto L1 else goto L2 :: bool |
| L1: |
| return 2 |
| L2: |
| inc_ref x |
| r2 = cast(__main__.A, x) |
| if is_error(r2) goto L6 (error at f:8) else goto L3 |
| L3: |
| r3 = box(None, 1) |
| r4 = r2 == r3 |
| dec_ref r2 |
| r5 = r4 ^ 1 |
| if r5 goto L4 else goto L5 :: bool |
| L4: |
| return 4 |
| L5: |
| return 6 |
| L6: |
| r6 = <error> :: int |
| return r6 |
| |
| [case testListSum] |
| from typing import List |
| def sum(a: List[int], l: int) -> int: |
| sum = 0 |
| i = 0 |
| while i < l: |
| sum = sum + a[i] |
| i = i + 1 |
| return sum |
| [out] |
| def sum(a, l): |
| a :: list |
| l, sum, i :: int |
| r0 :: native_int |
| r1 :: bit |
| r2 :: native_int |
| r3, r4, r5 :: bit |
| r6 :: object |
| r7, r8, r9, r10 :: int |
| L0: |
| sum = 0 |
| i = 0 |
| L1: |
| r0 = i & 1 |
| r1 = r0 != 0 |
| if r1 goto L3 else goto L2 :: bool |
| L2: |
| r2 = l & 1 |
| r3 = r2 != 0 |
| if r3 goto L3 else goto L4 :: bool |
| L3: |
| r4 = CPyTagged_IsLt_(i, l) |
| if r4 goto L5 else goto L10 :: bool |
| L4: |
| r5 = i < l :: signed |
| if r5 goto L5 else goto L10 :: bool |
| L5: |
| r6 = CPyList_GetItem(a, i) |
| if is_error(r6) goto L11 (error at sum:6) else goto L6 |
| L6: |
| r7 = unbox(int, r6) |
| dec_ref r6 |
| if is_error(r7) goto L11 (error at sum:6) else goto L7 |
| L7: |
| r8 = CPyTagged_Add(sum, r7) |
| dec_ref sum :: int |
| dec_ref r7 :: int |
| sum = r8 |
| r9 = CPyTagged_Add(i, 2) |
| dec_ref i :: int |
| i = r9 |
| goto L1 |
| L8: |
| return sum |
| L9: |
| r10 = <error> :: int |
| return r10 |
| L10: |
| dec_ref i :: int |
| goto L8 |
| L11: |
| dec_ref sum :: int |
| dec_ref i :: int |
| goto L9 |
| |
| [case testTryExcept] |
| def g() -> None: |
| try: |
| object() |
| except: |
| print("weeee") |
| [out] |
| def g(): |
| r0 :: object |
| r1 :: str |
| r2, r3 :: object |
| r4 :: tuple[object, object, object] |
| r5 :: str |
| r6 :: object |
| r7 :: str |
| r8, r9 :: object |
| r10 :: bit |
| r11 :: None |
| L0: |
| L1: |
| r0 = builtins :: module |
| r1 = load_global CPyStatic_unicode_1 :: static ('object') |
| r2 = CPyObject_GetAttr(r0, r1) |
| if is_error(r2) goto L3 (error at g:3) else goto L2 |
| L2: |
| r3 = PyObject_CallFunctionObjArgs(r2, 0) |
| dec_ref r2 |
| if is_error(r3) goto L3 (error at g:3) else goto L10 |
| L3: |
| r4 = CPy_CatchError() |
| r5 = load_global CPyStatic_unicode_2 :: static ('weeee') |
| r6 = builtins :: module |
| r7 = load_global CPyStatic_unicode_3 :: static ('print') |
| r8 = CPyObject_GetAttr(r6, r7) |
| if is_error(r8) goto L6 (error at g:5) else goto L4 |
| L4: |
| r9 = PyObject_CallFunctionObjArgs(r8, r5, 0) |
| dec_ref r8 |
| if is_error(r9) goto L6 (error at g:5) else goto L11 |
| L5: |
| CPy_RestoreExcInfo(r4) |
| dec_ref r4 |
| goto L8 |
| L6: |
| CPy_RestoreExcInfo(r4) |
| dec_ref r4 |
| r10 = CPy_KeepPropagating() |
| if not r10 goto L9 else goto L7 :: bool |
| L7: |
| unreachable |
| L8: |
| return 1 |
| L9: |
| r11 = <error> :: None |
| return r11 |
| L10: |
| dec_ref r3 |
| goto L8 |
| L11: |
| dec_ref r9 |
| goto L5 |
| |
| [case testGenopsTryFinally] |
| def a() -> str: |
| try: |
| print() |
| return 'hi' |
| finally: |
| print('goodbye!') |
| [out] |
| def a(): |
| r0 :: object |
| r1 :: str |
| r2, r3 :: object |
| r4, r5 :: str |
| r6, r7 :: tuple[object, object, object] |
| r8 :: str |
| r9 :: tuple[object, object, object] |
| r10 :: str |
| r11 :: object |
| r12 :: str |
| r13, r14 :: object |
| r15 :: bit |
| r16 :: str |
| L0: |
| L1: |
| r0 = builtins :: module |
| r1 = load_global CPyStatic_unicode_1 :: static ('print') |
| r2 = CPyObject_GetAttr(r0, r1) |
| if is_error(r2) goto L5 (error at a:3) else goto L2 |
| L2: |
| r3 = PyObject_CallFunctionObjArgs(r2, 0) |
| dec_ref r2 |
| if is_error(r3) goto L5 (error at a:3) else goto L20 |
| L3: |
| r4 = load_global CPyStatic_unicode_2 :: static ('hi') |
| inc_ref r4 |
| r5 = r4 |
| L4: |
| r6 = <error> :: tuple[object, object, object] |
| r7 = r6 |
| goto L6 |
| L5: |
| r8 = <error> :: str |
| r5 = r8 |
| r9 = CPy_CatchError() |
| r7 = r9 |
| L6: |
| r10 = load_global CPyStatic_unicode_3 :: static ('goodbye!') |
| r11 = builtins :: module |
| r12 = load_global CPyStatic_unicode_1 :: static ('print') |
| r13 = CPyObject_GetAttr(r11, r12) |
| if is_error(r13) goto L13 (error at a:6) else goto L7 |
| L7: |
| r14 = PyObject_CallFunctionObjArgs(r13, r10, 0) |
| dec_ref r13 |
| if is_error(r14) goto L13 (error at a:6) else goto L21 |
| L8: |
| if is_error(r7) goto L11 else goto L9 |
| L9: |
| CPy_Reraise() |
| if not 0 goto L13 else goto L22 :: bool |
| L10: |
| unreachable |
| L11: |
| if is_error(r5) goto L18 else goto L12 |
| L12: |
| return r5 |
| L13: |
| if is_error(r5) goto L14 else goto L23 |
| L14: |
| if is_error(r7) goto L16 else goto L15 |
| L15: |
| CPy_RestoreExcInfo(r7) |
| dec_ref r7 |
| L16: |
| r15 = CPy_KeepPropagating() |
| if not r15 goto L19 else goto L17 :: bool |
| L17: |
| unreachable |
| L18: |
| unreachable |
| L19: |
| r16 = <error> :: str |
| return r16 |
| L20: |
| dec_ref r3 |
| goto L3 |
| L21: |
| dec_ref r14 |
| goto L8 |
| L22: |
| dec_ref r5 |
| dec_ref r7 |
| goto L10 |
| L23: |
| dec_ref r5 |
| goto L14 |
| |
| [case testDocstring1] |
| def lol() -> None: |
| """Hello""" |
| pass |
| [out] |
| def lol(): |
| L0: |
| return 1 |
| |
| [case testExceptUndefined1] |
| from typing import Any |
| def lol(x: Any) -> object: |
| try: |
| st = x.foo |
| except: |
| return '' |
| # No uninit check should be generated, since the exception branch always returns |
| return st |
| [out] |
| def lol(x): |
| x :: object |
| r0 :: str |
| r1, st :: object |
| r2 :: tuple[object, object, object] |
| r3 :: str |
| L0: |
| L1: |
| r0 = load_global CPyStatic_unicode_3 :: static ('foo') |
| r1 = CPyObject_GetAttr(x, r0) |
| if is_error(r1) goto L3 (error at lol:4) else goto L2 |
| L2: |
| st = r1 |
| goto L4 |
| L3: |
| r2 = CPy_CatchError() |
| r3 = load_global CPyStatic_unicode_4 :: static |
| CPy_RestoreExcInfo(r2) |
| dec_ref r2 |
| inc_ref r3 |
| return r3 |
| L4: |
| return st |
| |
| [case testExceptUndefined2] |
| from typing import Any |
| def lol(x: Any) -> object: |
| try: |
| a = x.foo |
| b = x.bar |
| except: |
| pass |
| # uninit checks are needed, since the exception can skip initializing the vars |
| return a + b |
| [out] |
| def lol(x): |
| x, r0, a, r1, b :: object |
| r2 :: str |
| r3 :: object |
| r4 :: str |
| r5 :: object |
| r6 :: tuple[object, object, object] |
| r7, r8 :: bool |
| r9, r10 :: object |
| L0: |
| r0 = <error> :: object |
| a = r0 |
| r1 = <error> :: object |
| b = r1 |
| L1: |
| r2 = load_global CPyStatic_unicode_3 :: static ('foo') |
| r3 = CPyObject_GetAttr(x, r2) |
| if is_error(r3) goto L4 (error at lol:4) else goto L15 |
| L2: |
| a = r3 |
| r4 = load_global CPyStatic_unicode_4 :: static ('bar') |
| r5 = CPyObject_GetAttr(x, r4) |
| if is_error(r5) goto L4 (error at lol:5) else goto L16 |
| L3: |
| b = r5 |
| goto L6 |
| L4: |
| r6 = CPy_CatchError() |
| L5: |
| CPy_RestoreExcInfo(r6) |
| dec_ref r6 |
| L6: |
| if is_error(a) goto L17 else goto L9 |
| L7: |
| r7 = raise UnboundLocalError("local variable 'a' referenced before assignment") |
| if not r7 goto L14 (error at lol:9) else goto L8 :: bool |
| L8: |
| unreachable |
| L9: |
| if is_error(b) goto L18 else goto L12 |
| L10: |
| r8 = raise UnboundLocalError("local variable 'b' referenced before assignment") |
| if not r8 goto L14 (error at lol:9) else goto L11 :: bool |
| L11: |
| unreachable |
| L12: |
| r9 = PyNumber_Add(a, b) |
| xdec_ref a |
| xdec_ref b |
| if is_error(r9) goto L14 (error at lol:9) else goto L13 |
| L13: |
| return r9 |
| L14: |
| r10 = <error> :: object |
| return r10 |
| L15: |
| xdec_ref a |
| goto L2 |
| L16: |
| xdec_ref b |
| goto L3 |
| L17: |
| xdec_ref b |
| goto L7 |
| L18: |
| xdec_ref a |
| goto L10 |
| |
| [case testMaybeUninitVarExc] |
| def f(b: bool) -> None: |
| u = 'a' |
| while b: |
| v = 'b' |
| if v is not u: |
| break |
| print(v) |
| [out] |
| def f(b): |
| b :: bool |
| r0, v, r1, u, r2 :: str |
| r3, r4 :: bit |
| r5 :: object |
| r6 :: str |
| r7 :: object |
| r8 :: bool |
| r9 :: object |
| r10 :: None |
| L0: |
| r0 = <error> :: str |
| v = r0 |
| r1 = load_global CPyStatic_unicode_1 :: static ('a') |
| inc_ref r1 |
| u = r1 |
| L1: |
| if b goto L10 else goto L11 :: bool |
| L2: |
| r2 = load_global CPyStatic_unicode_2 :: static ('b') |
| inc_ref r2 |
| v = r2 |
| r3 = v == u |
| r4 = r3 ^ 1 |
| if r4 goto L11 else goto L1 :: bool |
| L3: |
| r5 = builtins :: module |
| r6 = load_global CPyStatic_unicode_3 :: static ('print') |
| r7 = CPyObject_GetAttr(r5, r6) |
| if is_error(r7) goto L12 (error at f:7) else goto L4 |
| L4: |
| if is_error(v) goto L13 else goto L7 |
| L5: |
| r8 = raise UnboundLocalError("local variable 'v' referenced before assignment") |
| if not r8 goto L9 (error at f:7) else goto L6 :: bool |
| L6: |
| unreachable |
| L7: |
| r9 = PyObject_CallFunctionObjArgs(r7, v, 0) |
| dec_ref r7 |
| xdec_ref v |
| if is_error(r9) goto L9 (error at f:7) else goto L14 |
| L8: |
| return 1 |
| L9: |
| r10 = <error> :: None |
| return r10 |
| L10: |
| xdec_ref v |
| goto L2 |
| L11: |
| dec_ref u |
| goto L3 |
| L12: |
| xdec_ref v |
| goto L9 |
| L13: |
| dec_ref r7 |
| goto L5 |
| L14: |
| dec_ref r9 |
| goto L8 |
| |