541 lines
9.0 KiB
Plaintext
541 lines
9.0 KiB
Plaintext
[case testIsNone]
|
|
from typing import Optional
|
|
|
|
class A: pass
|
|
|
|
def f(x: Optional[A]) -> int:
|
|
if x is None:
|
|
return 1
|
|
return 2
|
|
[out]
|
|
def f(x):
|
|
x :: union[__main__.A, None]
|
|
r0 :: object
|
|
r1 :: bit
|
|
L0:
|
|
r0 = load_address _Py_NoneStruct
|
|
r1 = x == r0
|
|
if r1 goto L1 else goto L2 :: bool
|
|
L1:
|
|
return 2
|
|
L2:
|
|
return 4
|
|
|
|
[case testIsNotNone]
|
|
from typing import Optional
|
|
|
|
class A: pass
|
|
|
|
def f(x: Optional[A]) -> int:
|
|
if x is not None:
|
|
return 1
|
|
return 2
|
|
[out]
|
|
def f(x):
|
|
x :: union[__main__.A, None]
|
|
r0 :: object
|
|
r1 :: bit
|
|
L0:
|
|
r0 = load_address _Py_NoneStruct
|
|
r1 = x != r0
|
|
if r1 goto L1 else goto L2 :: bool
|
|
L1:
|
|
return 2
|
|
L2:
|
|
return 4
|
|
|
|
[case testIsTruthy]
|
|
from typing import Optional
|
|
|
|
class A: pass
|
|
|
|
def f(x: Optional[A]) -> int:
|
|
if x:
|
|
return 1
|
|
return 2
|
|
[out]
|
|
def f(x):
|
|
x :: union[__main__.A, None]
|
|
r0 :: object
|
|
r1 :: bit
|
|
L0:
|
|
r0 = load_address _Py_NoneStruct
|
|
r1 = x != r0
|
|
if r1 goto L1 else goto L2 :: bool
|
|
L1:
|
|
return 2
|
|
L2:
|
|
return 4
|
|
|
|
[case testIsTruthyOverride]
|
|
from typing import Optional
|
|
|
|
class A: pass
|
|
|
|
class B(A):
|
|
def __bool__(self) -> bool:
|
|
return False
|
|
|
|
|
|
def f(x: Optional[A]) -> int:
|
|
if x:
|
|
return 1
|
|
return 2
|
|
[out]
|
|
def B.__bool__(self):
|
|
self :: __main__.B
|
|
L0:
|
|
return 0
|
|
def f(x):
|
|
x :: union[__main__.A, None]
|
|
r0 :: object
|
|
r1 :: bit
|
|
r2 :: __main__.A
|
|
r3 :: int32
|
|
r4 :: bit
|
|
r5 :: bool
|
|
L0:
|
|
r0 = load_address _Py_NoneStruct
|
|
r1 = x != r0
|
|
if r1 goto L1 else goto L3 :: bool
|
|
L1:
|
|
r2 = cast(__main__.A, x)
|
|
r3 = PyObject_IsTrue(r2)
|
|
r4 = r3 >= 0 :: signed
|
|
r5 = truncate r3: int32 to builtins.bool
|
|
if r5 goto L2 else goto L3 :: bool
|
|
L2:
|
|
return 2
|
|
L3:
|
|
return 4
|
|
|
|
[case testAssignToOptional]
|
|
from typing import Optional
|
|
|
|
class A:
|
|
a: Optional[int]
|
|
|
|
def f(x: Optional[A], y: Optional[A], z: Optional[int]) -> None:
|
|
x = None
|
|
x = A()
|
|
x = y
|
|
z = 1
|
|
a = A()
|
|
a.a = 1
|
|
a.a = None
|
|
[out]
|
|
def f(x, y, z):
|
|
x, y :: union[__main__.A, None]
|
|
z :: union[int, None]
|
|
r0 :: object
|
|
r1 :: __main__.A
|
|
r2 :: object
|
|
r3, a :: __main__.A
|
|
r4 :: object
|
|
r5 :: bool
|
|
r6 :: object
|
|
r7 :: bool
|
|
L0:
|
|
r0 = box(None, 1)
|
|
x = r0
|
|
r1 = A()
|
|
x = r1
|
|
x = y
|
|
r2 = object 1
|
|
z = r2
|
|
r3 = A()
|
|
a = r3
|
|
r4 = object 1
|
|
a.a = r4; r5 = is_error
|
|
r6 = box(None, 1)
|
|
a.a = r6; r7 = is_error
|
|
return 1
|
|
|
|
[case testBoxOptionalListItem]
|
|
from typing import List, Optional
|
|
|
|
def f(x: List[Optional[int]]) -> None:
|
|
x[0] = 0
|
|
x[1] = None
|
|
[out]
|
|
def f(x):
|
|
x :: list
|
|
r0 :: object
|
|
r1 :: bit
|
|
r2 :: object
|
|
r3 :: bit
|
|
L0:
|
|
r0 = object 0
|
|
r1 = CPyList_SetItem(x, 0, r0)
|
|
r2 = box(None, 1)
|
|
r3 = CPyList_SetItem(x, 2, r2)
|
|
return 1
|
|
|
|
[case testNarrowDownFromOptional]
|
|
from typing import Optional
|
|
|
|
class A: pass
|
|
|
|
def f(x: Optional[A]) -> A:
|
|
y = A()
|
|
if x is not None:
|
|
y = x
|
|
return x
|
|
return y
|
|
[out]
|
|
def f(x):
|
|
x :: union[__main__.A, None]
|
|
r0, y :: __main__.A
|
|
r1 :: object
|
|
r2 :: bit
|
|
r3, r4 :: __main__.A
|
|
L0:
|
|
r0 = A()
|
|
y = r0
|
|
r1 = load_address _Py_NoneStruct
|
|
r2 = x != r1
|
|
if r2 goto L1 else goto L2 :: bool
|
|
L1:
|
|
r3 = cast(__main__.A, x)
|
|
y = r3
|
|
r4 = cast(__main__.A, x)
|
|
return r4
|
|
L2:
|
|
return y
|
|
|
|
[case testPartialOptionalType]
|
|
def f(y: int) -> None:
|
|
x = None
|
|
if y == 1:
|
|
x = y
|
|
if x is not None:
|
|
y = x
|
|
[out]
|
|
def f(y):
|
|
y :: int
|
|
r0 :: object
|
|
x :: union[int, None]
|
|
r1 :: bit
|
|
r2, r3 :: object
|
|
r4 :: bit
|
|
r5 :: int
|
|
L0:
|
|
r0 = box(None, 1)
|
|
x = r0
|
|
r1 = y == 2
|
|
if r1 goto L1 else goto L2 :: bool
|
|
L1:
|
|
r2 = box(int, y)
|
|
x = r2
|
|
L2:
|
|
r3 = load_address _Py_NoneStruct
|
|
r4 = x != r3
|
|
if r4 goto L3 else goto L4 :: bool
|
|
L3:
|
|
r5 = unbox(int, x)
|
|
y = r5
|
|
L4:
|
|
return 1
|
|
|
|
[case testUnionType]
|
|
from typing import Union
|
|
|
|
class A:
|
|
a: int
|
|
|
|
def f(x: Union[int, A]) -> int:
|
|
if isinstance(x, int):
|
|
return x + 1
|
|
else:
|
|
return x.a
|
|
[out]
|
|
def f(x):
|
|
x :: union[int, __main__.A]
|
|
r0 :: object
|
|
r1 :: int32
|
|
r2 :: bit
|
|
r3 :: bool
|
|
r4, r5 :: int
|
|
r6 :: __main__.A
|
|
r7 :: int
|
|
L0:
|
|
r0 = load_address PyLong_Type
|
|
r1 = PyObject_IsInstance(x, r0)
|
|
r2 = r1 >= 0 :: signed
|
|
r3 = truncate r1: int32 to builtins.bool
|
|
if r3 goto L1 else goto L2 :: bool
|
|
L1:
|
|
r4 = unbox(int, x)
|
|
r5 = CPyTagged_Add(r4, 2)
|
|
return r5
|
|
L2:
|
|
r6 = borrow cast(__main__.A, x)
|
|
r7 = r6.a
|
|
keep_alive x
|
|
return r7
|
|
L3:
|
|
unreachable
|
|
|
|
[case testUnionTypeInList]
|
|
from typing import List, Union
|
|
|
|
def f(x: List[Union[int, str]]) -> object:
|
|
return x[0]
|
|
[out]
|
|
def f(x):
|
|
x :: list
|
|
r0 :: object
|
|
r1 :: union[int, str]
|
|
L0:
|
|
r0 = CPyList_GetItemShort(x, 0)
|
|
r1 = cast(union[int, str], r0)
|
|
return r1
|
|
|
|
[case testUnionAttributeAccess]
|
|
from typing import Union
|
|
class A:
|
|
a: int
|
|
class B:
|
|
a: object
|
|
def get(o: Union[A, B]) -> None:
|
|
z = o.a
|
|
def set(o: Union[A, B], s: str) -> None:
|
|
o.a = s
|
|
|
|
[out]
|
|
def get(o):
|
|
o :: union[__main__.A, __main__.B]
|
|
r0 :: object
|
|
r1 :: ptr
|
|
r2 :: object
|
|
r3 :: bit
|
|
r4 :: __main__.A
|
|
r5 :: int
|
|
r6, r7 :: object
|
|
r8 :: __main__.B
|
|
r9, z :: object
|
|
L0:
|
|
r0 = __main__.A :: type
|
|
r1 = get_element_ptr o ob_type :: PyObject
|
|
r2 = load_mem r1 :: builtins.object*
|
|
keep_alive o
|
|
r3 = r2 == r0
|
|
if r3 goto L1 else goto L2 :: bool
|
|
L1:
|
|
r4 = cast(__main__.A, o)
|
|
r5 = r4.a
|
|
r6 = box(int, r5)
|
|
r7 = r6
|
|
goto L3
|
|
L2:
|
|
r8 = cast(__main__.B, o)
|
|
r9 = r8.a
|
|
r7 = r9
|
|
L3:
|
|
z = r7
|
|
return 1
|
|
def set(o, s):
|
|
o :: union[__main__.A, __main__.B]
|
|
s, r0 :: str
|
|
r1 :: int32
|
|
r2 :: bit
|
|
L0:
|
|
r0 = 'a'
|
|
r1 = PyObject_SetAttr(o, r0, s)
|
|
r2 = r1 >= 0 :: signed
|
|
return 1
|
|
|
|
[case testUnionMethodCall]
|
|
from typing import Union
|
|
class A:
|
|
def f(self, x: int) -> int:
|
|
return x
|
|
class B:
|
|
def f(self, x: object) -> object:
|
|
return x
|
|
class C:
|
|
def f(self, x: object) -> int:
|
|
return 0
|
|
def g(o: Union[A, B, C]) -> None:
|
|
z = o.f(1)
|
|
|
|
[out]
|
|
def A.f(self, x):
|
|
self :: __main__.A
|
|
x :: int
|
|
L0:
|
|
return x
|
|
def B.f(self, x):
|
|
self :: __main__.B
|
|
x :: object
|
|
L0:
|
|
return x
|
|
def C.f(self, x):
|
|
self :: __main__.C
|
|
x :: object
|
|
L0:
|
|
return 0
|
|
def g(o):
|
|
o :: union[__main__.A, __main__.B, __main__.C]
|
|
r0 :: object
|
|
r1 :: ptr
|
|
r2 :: object
|
|
r3 :: bit
|
|
r4 :: __main__.A
|
|
r5 :: int
|
|
r6, r7, r8 :: object
|
|
r9 :: ptr
|
|
r10 :: object
|
|
r11 :: bit
|
|
r12 :: __main__.B
|
|
r13, r14 :: object
|
|
r15 :: __main__.C
|
|
r16 :: object
|
|
r17 :: int
|
|
r18, z :: object
|
|
L0:
|
|
r0 = __main__.A :: type
|
|
r1 = get_element_ptr o ob_type :: PyObject
|
|
r2 = load_mem r1 :: builtins.object*
|
|
keep_alive o
|
|
r3 = r2 == r0
|
|
if r3 goto L1 else goto L2 :: bool
|
|
L1:
|
|
r4 = cast(__main__.A, o)
|
|
r5 = r4.f(2)
|
|
r6 = box(int, r5)
|
|
r7 = r6
|
|
goto L5
|
|
L2:
|
|
r8 = __main__.B :: type
|
|
r9 = get_element_ptr o ob_type :: PyObject
|
|
r10 = load_mem r9 :: builtins.object*
|
|
keep_alive o
|
|
r11 = r10 == r8
|
|
if r11 goto L3 else goto L4 :: bool
|
|
L3:
|
|
r12 = cast(__main__.B, o)
|
|
r13 = object 1
|
|
r14 = r12.f(r13)
|
|
r7 = r14
|
|
goto L5
|
|
L4:
|
|
r15 = cast(__main__.C, o)
|
|
r16 = object 1
|
|
r17 = r15.f(r16)
|
|
r18 = box(int, r17)
|
|
r7 = r18
|
|
L5:
|
|
z = r7
|
|
return 1
|
|
|
|
[case testUnionWithNonNativeItem]
|
|
from typing import Union
|
|
from m import B
|
|
|
|
class A:
|
|
x: int
|
|
|
|
def f(o: Union[A, B]) -> None:
|
|
o.x
|
|
|
|
def g(o: Union[B, A]) -> None:
|
|
o.x
|
|
|
|
[file m.py]
|
|
class B:
|
|
x: int
|
|
|
|
[out]
|
|
def f(o):
|
|
o :: union[__main__.A, object]
|
|
r0 :: object
|
|
r1 :: ptr
|
|
r2 :: object
|
|
r3 :: bit
|
|
r4 :: __main__.A
|
|
r5, r6 :: int
|
|
r7 :: object
|
|
r8 :: str
|
|
r9 :: object
|
|
r10 :: int
|
|
L0:
|
|
r0 = __main__.A :: type
|
|
r1 = get_element_ptr o ob_type :: PyObject
|
|
r2 = load_mem r1 :: builtins.object*
|
|
keep_alive o
|
|
r3 = r2 == r0
|
|
if r3 goto L1 else goto L2 :: bool
|
|
L1:
|
|
r4 = cast(__main__.A, o)
|
|
r5 = r4.x
|
|
r6 = r5
|
|
goto L3
|
|
L2:
|
|
r7 = o
|
|
r8 = 'x'
|
|
r9 = CPyObject_GetAttr(r7, r8)
|
|
r10 = unbox(int, r9)
|
|
r6 = r10
|
|
L3:
|
|
return 1
|
|
def g(o):
|
|
o :: union[object, __main__.A]
|
|
r0 :: object
|
|
r1 :: ptr
|
|
r2 :: object
|
|
r3 :: bit
|
|
r4 :: __main__.A
|
|
r5, r6 :: int
|
|
r7 :: object
|
|
r8 :: str
|
|
r9 :: object
|
|
r10 :: int
|
|
L0:
|
|
r0 = __main__.A :: type
|
|
r1 = get_element_ptr o ob_type :: PyObject
|
|
r2 = load_mem r1 :: builtins.object*
|
|
keep_alive o
|
|
r3 = r2 == r0
|
|
if r3 goto L1 else goto L2 :: bool
|
|
L1:
|
|
r4 = cast(__main__.A, o)
|
|
r5 = r4.x
|
|
r6 = r5
|
|
goto L3
|
|
L2:
|
|
r7 = o
|
|
r8 = 'x'
|
|
r9 = CPyObject_GetAttr(r7, r8)
|
|
r10 = unbox(int, r9)
|
|
r6 = r10
|
|
L3:
|
|
return 1
|
|
|
|
[case testUnionWithNoNativeItems]
|
|
from typing import Union
|
|
from m import A, B
|
|
|
|
def f(o: Union[A, B]) -> None:
|
|
o.x
|
|
|
|
[file m.py]
|
|
class A:
|
|
x: object
|
|
class B:
|
|
x: int
|
|
|
|
[out]
|
|
def f(o):
|
|
o :: union[object, object]
|
|
r0 :: object
|
|
r1 :: str
|
|
r2, r3 :: object
|
|
L0:
|
|
r0 = o
|
|
r1 = 'x'
|
|
r2 = CPyObject_GetAttr(r0, r1)
|
|
r3 = r2
|
|
L1:
|
|
return 1
|