| -- 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 :: short_int | |
| r1 :: object | |
| r2, r3 :: int | |
| L0: | |
| r0 = 0 | |
| r1 = CPyList_GetItemShort(x, r0) | |
| if is_error(r1) goto L3 (error at f:3) else goto L1 | |
| L1: | |
| r2 = unbox(int, r1) | |
| dec_ref r1 | |
| if is_error(r2) goto L3 (error at f:3) else goto L2 | |
| L2: | |
| return r2 | |
| L3: | |
| r3 = <error> :: int | |
| return r3 | |
| [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 :: bool | |
| r2 :: None | |
| r3 :: object | |
| r4 :: bool | |
| r5, r6 :: None | |
| L0: | |
| inc_ref y :: int | |
| r0 = box(int, y) | |
| r1 = x.append(r0) :: list | |
| dec_ref r0 | |
| if not r1 goto L3 (error at f:3) else goto L1 :: bool | |
| L1: | |
| r2 = None | |
| 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: | |
| r5 = None | |
| return r5 | |
| L3: | |
| r6 = <error> :: None | |
| return r6 | |
| [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 :: None | |
| r1 :: object | |
| r2 :: bool | |
| r3 :: short_int | |
| r4 :: __main__.A | |
| r5 :: None | |
| r6 :: object | |
| r7, r8 :: bool | |
| r9, r10 :: short_int | |
| r11 :: int | |
| L0: | |
| r0 = None | |
| r1 = box(None, r0) | |
| r2 = x is r1 | |
| if r2 goto L1 else goto L2 :: bool | |
| L1: | |
| r3 = 1 | |
| return r3 | |
| L2: | |
| inc_ref x | |
| r4 = cast(__main__.A, x) | |
| if is_error(r4) goto L6 (error at f:8) else goto L3 | |
| L3: | |
| r5 = None | |
| r6 = box(None, r5) | |
| r7 = r4 is r6 | |
| dec_ref r4 | |
| r8 = !r7 | |
| if r8 goto L4 else goto L5 :: bool | |
| L4: | |
| r9 = 2 | |
| return r9 | |
| L5: | |
| r10 = 3 | |
| return r10 | |
| L6: | |
| r11 = <error> :: int | |
| return r11 | |
| [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 :: int | |
| r0 :: short_int | |
| sum :: int | |
| r1 :: short_int | |
| i :: int | |
| r2 :: bool | |
| r3 :: object | |
| r4, r5 :: int | |
| r6 :: short_int | |
| r7, r8 :: int | |
| L0: | |
| r0 = 0 | |
| sum = r0 | |
| r1 = 0 | |
| i = r1 | |
| L1: | |
| r2 = CPyTagged_IsLt(i, l) | |
| if r2 goto L2 else goto L7 :: bool | |
| L2: | |
| r3 = CPyList_GetItem(a, i) | |
| if is_error(r3) goto L8 (error at sum:6) else goto L3 | |
| L3: | |
| r4 = unbox(int, r3) | |
| dec_ref r3 | |
| if is_error(r4) goto L8 (error at sum:6) else goto L4 | |
| L4: | |
| r5 = CPyTagged_Add(sum, r4) | |
| dec_ref sum :: int | |
| dec_ref r4 :: int | |
| sum = r5 | |
| r6 = 1 | |
| r7 = CPyTagged_Add(i, r6) | |
| dec_ref i :: int | |
| i = r7 | |
| goto L1 | |
| L5: | |
| return sum | |
| L6: | |
| r8 = <error> :: int | |
| return r8 | |
| L7: | |
| dec_ref i :: int | |
| goto L5 | |
| L8: | |
| dec_ref sum :: int | |
| dec_ref i :: int | |
| goto L6 | |
| [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 :: bool | |
| r11, r12 :: None | |
| L0: | |
| L1: | |
| r0 = builtins :: module | |
| r1 = unicode_1 :: static ('object') | |
| r2 = getattr r0, r1 | |
| if is_error(r2) goto L3 (error at g:3) else goto L2 | |
| L2: | |
| r3 = py_call(r2) | |
| dec_ref r2 | |
| if is_error(r3) goto L3 (error at g:3) else goto L10 | |
| L3: | |
| r4 = error_catch | |
| r5 = unicode_2 :: static ('weeee') | |
| r6 = builtins :: module | |
| r7 = unicode_3 :: static ('print') | |
| r8 = getattr r6, r7 | |
| if is_error(r8) goto L6 (error at g:5) else goto L4 | |
| L4: | |
| r9 = py_call(r8, r5) | |
| dec_ref r8 | |
| if is_error(r9) goto L6 (error at g:5) else goto L11 | |
| L5: | |
| restore_exc_info r4 | |
| dec_ref r4 | |
| goto L8 | |
| L6: | |
| restore_exc_info r4 | |
| dec_ref r4 | |
| r10 = keep_propagating | |
| if not r10 goto L9 else goto L7 :: bool | |
| L7: | |
| unreachable | |
| L8: | |
| r11 = None | |
| return r11 | |
| L9: | |
| r12 = <error> :: None | |
| return r12 | |
| 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 :: tuple[object, object, object] | |
| r7 :: str | |
| r8 :: tuple[object, object, object] | |
| r9 :: str | |
| r10 :: tuple[object, object, object] | |
| r11 :: str | |
| r12 :: object | |
| r13 :: str | |
| r14, r15 :: object | |
| r16, r17 :: bool | |
| r18 :: str | |
| L0: | |
| L1: | |
| r0 = builtins :: module | |
| r1 = unicode_1 :: static ('print') | |
| r2 = getattr r0, r1 | |
| if is_error(r2) goto L5 (error at a:3) else goto L2 | |
| L2: | |
| r3 = py_call(r2) | |
| dec_ref r2 | |
| if is_error(r3) goto L5 (error at a:3) else goto L20 | |
| L3: | |
| r4 = unicode_2 :: static ('hi') | |
| inc_ref r4 | |
| r5 = r4 | |
| L4: | |
| r8 = <error> :: tuple[object, object, object] | |
| r6 = r8 | |
| goto L6 | |
| L5: | |
| r9 = <error> :: str | |
| r5 = r9 | |
| r10 = error_catch | |
| r6 = r10 | |
| L6: | |
| r11 = unicode_3 :: static ('goodbye!') | |
| r12 = builtins :: module | |
| r13 = unicode_1 :: static ('print') | |
| r14 = getattr r12, r13 | |
| if is_error(r14) goto L13 (error at a:6) else goto L7 | |
| L7: | |
| r15 = py_call(r14, r11) | |
| dec_ref r14 | |
| if is_error(r15) goto L13 (error at a:6) else goto L21 | |
| L8: | |
| if is_error(r6) goto L11 else goto L9 | |
| L9: | |
| reraise_exc; r16 = 0 | |
| if not r16 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(r6) goto L16 else goto L15 | |
| L15: | |
| restore_exc_info r6 | |
| dec_ref r6 | |
| L16: | |
| r17 = keep_propagating | |
| if not r17 goto L19 else goto L17 :: bool | |
| L17: | |
| unreachable | |
| L18: | |
| unreachable | |
| L19: | |
| r18 = <error> :: str | |
| return r18 | |
| L20: | |
| dec_ref r3 | |
| goto L3 | |
| L21: | |
| dec_ref r15 | |
| goto L8 | |
| L22: | |
| dec_ref r5 | |
| dec_ref r6 | |
| goto L10 | |
| L23: | |
| dec_ref r5 | |
| goto L14 | |
| [case testDocstring1] | |
| def lol() -> None: | |
| """Hello""" | |
| pass | |
| [out] | |
| def lol(): | |
| r0 :: None | |
| L0: | |
| r0 = None | |
| return r0 | |
| [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 | |
| r4 :: bool | |
| r5 :: object | |
| L0: | |
| L1: | |
| r0 = unicode_3 :: static ('foo') | |
| r1 = getattr x, r0 | |
| if is_error(r1) goto L3 (error at lol:4) else goto L2 | |
| L2: | |
| st = r1 | |
| goto L4 | |
| L3: | |
| r2 = error_catch | |
| r3 = unicode_4 :: static | |
| restore_exc_info 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 :: object | |
| r0 :: str | |
| r1, a :: object | |
| r2 :: str | |
| r3, b :: object | |
| r4 :: tuple[object, object, object] | |
| r5 :: bool | |
| r6 :: object | |
| r7, r8 :: bool | |
| r9 :: object | |
| L0: | |
| L1: | |
| r0 = unicode_3 :: static ('foo') | |
| r1 = getattr x, r0 | |
| if is_error(r1) goto L4 (error at lol:4) else goto L15 | |
| L2: | |
| a = r1 | |
| r2 = unicode_4 :: static ('bar') | |
| r3 = getattr x, r2 | |
| if is_error(r3) goto L4 (error at lol:5) else goto L16 | |
| L3: | |
| b = r3 | |
| goto L6 | |
| L4: | |
| r4 = error_catch | |
| L5: | |
| restore_exc_info r4 | |
| dec_ref r4 | |
| L6: | |
| if is_error(a) goto L17 else goto L9 | |
| L7: | |
| 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: | |
| raise UnboundLocalError("local variable 'b' referenced before assignment") | |
| if not r8 goto L14 (error at lol:9) else goto L11 :: bool | |
| L11: | |
| unreachable | |
| L12: | |
| r6 = a + b | |
| xdec_ref a | |
| xdec_ref b | |
| if is_error(r6) goto L14 (error at lol:9) else goto L13 | |
| L13: | |
| return r6 | |
| L14: | |
| r9 = <error> :: object | |
| return r9 | |
| 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, u, r1, v :: str | |
| r2, r3 :: bool | |
| r4 :: object | |
| r5 :: str | |
| r6, r7 :: object | |
| r8 :: None | |
| r9 :: bool | |
| r10 :: None | |
| L0: | |
| r0 = unicode_1 :: static ('a') | |
| inc_ref r0 | |
| u = r0 | |
| L1: | |
| if b goto L10 else goto L11 :: bool | |
| L2: | |
| r1 = unicode_2 :: static ('b') | |
| inc_ref r1 | |
| v = r1 | |
| r2 = v is u | |
| r3 = !r2 | |
| if r3 goto L11 else goto L1 :: bool | |
| L3: | |
| r4 = builtins :: module | |
| r5 = unicode_3 :: static ('print') | |
| r6 = getattr r4, r5 | |
| if is_error(r6) goto L12 (error at f:7) else goto L4 | |
| L4: | |
| if is_error(v) goto L13 else goto L7 | |
| L5: | |
| raise UnboundLocalError("local variable 'v' referenced before assignment") | |
| if not r9 goto L9 (error at f:7) else goto L6 :: bool | |
| L6: | |
| unreachable | |
| L7: | |
| r7 = py_call(r6, v) | |
| dec_ref r6 | |
| xdec_ref v | |
| if is_error(r7) goto L9 (error at f:7) else goto L14 | |
| L8: | |
| r8 = None | |
| return r8 | |
| 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 r6 | |
| goto L5 | |
| L14: | |
| dec_ref r7 | |
| goto L8 | |