Major fixes and new features
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -0,0 +1,732 @@
|
||||
-- Test cases for always defined attributes.
|
||||
--
|
||||
-- If class C has attributes x and y that are always defined, the output will
|
||||
-- have a line like this:
|
||||
--
|
||||
-- C: [x, y]
|
||||
|
||||
[case testAlwaysDefinedSimple]
|
||||
class C:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
[out]
|
||||
C: [x]
|
||||
|
||||
[case testAlwaysDefinedFail]
|
||||
class MethodCall:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.f()
|
||||
self.x = x
|
||||
|
||||
def f(self) -> None:
|
||||
pass
|
||||
|
||||
class FuncCall:
|
||||
def __init__(self, x: int) -> None:
|
||||
f(x)
|
||||
self.x = x
|
||||
f(self)
|
||||
self.y = x
|
||||
|
||||
class GetAttr:
|
||||
x: int
|
||||
def __init__(self, x: int) -> None:
|
||||
a = self.x
|
||||
self.x = x
|
||||
|
||||
class _Base:
|
||||
def __init__(self) -> None:
|
||||
f(self)
|
||||
|
||||
class CallSuper(_Base):
|
||||
def __init__(self, x: int) -> None:
|
||||
super().__init__()
|
||||
self.x = x
|
||||
|
||||
class Lambda:
|
||||
def __init__(self, x: int) -> None:
|
||||
f = lambda x: x + 1
|
||||
self.x = x
|
||||
g = lambda x: self
|
||||
self.y = x
|
||||
|
||||
class If:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.a = 1
|
||||
if x:
|
||||
self.x = x
|
||||
else:
|
||||
self.y = 1
|
||||
|
||||
class Deletable:
|
||||
__deletable__ = ('x', 'y')
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.x = 0
|
||||
self.y = 1
|
||||
self.z = 2
|
||||
|
||||
class PrimitiveWithSelf:
|
||||
def __init__(self, s: str) -> None:
|
||||
self.x = getattr(self, s)
|
||||
|
||||
def f(a) -> None: pass
|
||||
[out]
|
||||
MethodCall: []
|
||||
FuncCall: [x]
|
||||
GetAttr: []
|
||||
CallSuper: []
|
||||
Lambda: []
|
||||
If: [a]
|
||||
Deletable: [z]
|
||||
PrimitiveWithSelf: []
|
||||
|
||||
[case testAlwaysDefinedConditional]
|
||||
class IfAlways:
|
||||
def __init__(self, x: int, y: int) -> None:
|
||||
if x:
|
||||
self.x = x
|
||||
self.y = y
|
||||
elif y:
|
||||
self.x = y
|
||||
self.y = x
|
||||
else:
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.z = 0
|
||||
|
||||
class IfSometimes1:
|
||||
def __init__(self, x: int, y: int) -> None:
|
||||
if x:
|
||||
self.x = x
|
||||
self.y = y
|
||||
elif y:
|
||||
self.z = y
|
||||
self.y = x
|
||||
else:
|
||||
self.y = 0
|
||||
self.a = 0
|
||||
|
||||
class IfSometimes2:
|
||||
def __init__(self, x: int, y: int) -> None:
|
||||
if x:
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
class IfStopAnalysis1:
|
||||
def __init__(self, x: int, y: int) -> None:
|
||||
if x:
|
||||
self.x = x
|
||||
f(self)
|
||||
else:
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
class IfStopAnalysis2:
|
||||
def __init__(self, x: int, y: int) -> None:
|
||||
if x:
|
||||
self.x = x
|
||||
else:
|
||||
self.x = x
|
||||
f(self)
|
||||
self.y = y
|
||||
|
||||
class IfStopAnalysis3:
|
||||
def __init__(self, x: int, y: int) -> None:
|
||||
if x:
|
||||
self.x = x
|
||||
else:
|
||||
f(self)
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
class IfConditionalAndNonConditional1:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = 0
|
||||
if x:
|
||||
self.x = x
|
||||
|
||||
class IfConditionalAndNonConditional2:
|
||||
def __init__(self, x: int) -> None:
|
||||
# x is not considered always defined, since the second assignment may
|
||||
# either initialize or update.
|
||||
if x:
|
||||
self.x = x
|
||||
self.x = 0
|
||||
|
||||
def f(a) -> None: pass
|
||||
[out]
|
||||
IfAlways: [x, y, z]
|
||||
IfSometimes1: [y]
|
||||
IfSometimes2: [y]
|
||||
IfStopAnalysis1: [x]
|
||||
IfStopAnalysis2: [x]
|
||||
IfStopAnalysis3: []
|
||||
IfConditionalAndNonConditional1: [x]
|
||||
IfConditionalAndNonConditional2: []
|
||||
|
||||
[case testAlwaysDefinedExpressions]
|
||||
from typing import Dict, List, Set, Optional, cast
|
||||
from typing_extensions import Final
|
||||
|
||||
import other
|
||||
|
||||
class C: pass
|
||||
|
||||
class Collections:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.l = [x]
|
||||
self.d: Dict[str, str] = {}
|
||||
self.s: Set[int] = set()
|
||||
self.d2 = {'x': x}
|
||||
self.s2 = {x}
|
||||
self.l2 = [f(), None] * x
|
||||
self.t = tuple(self.l2)
|
||||
|
||||
class Comparisons:
|
||||
def __init__(self, y: int, c: C, s: str, o: Optional[str]) -> None:
|
||||
self.n1 = y < 5
|
||||
self.n2 = y == 5
|
||||
self.c1 = y is c
|
||||
self.c2 = y is not c
|
||||
self.o1 = o is None
|
||||
self.o2 = o is not None
|
||||
self.s = s < 'x'
|
||||
|
||||
class BinaryOps:
|
||||
def __init__(self, x: int, s: str) -> None:
|
||||
self.a = x + 2
|
||||
self.b = x & 2
|
||||
self.c = x * 2
|
||||
self.d = -x
|
||||
self.e = 'x' + s
|
||||
self.f = x << x
|
||||
|
||||
g = 2
|
||||
|
||||
class LocalsAndGlobals:
|
||||
def __init__(self, x: int) -> None:
|
||||
t = x + 1
|
||||
self.a = t - t
|
||||
self.g = g
|
||||
|
||||
class Booleans:
|
||||
def __init__(self, x: int, b: bool) -> None:
|
||||
self.a = True
|
||||
self.b = False
|
||||
self.c = not b
|
||||
self.d = b or b
|
||||
self.e = b and b
|
||||
|
||||
F: Final = 3
|
||||
|
||||
class ModuleFinal:
|
||||
def __init__(self) -> None:
|
||||
self.a = F
|
||||
self.b = other.Y
|
||||
|
||||
class ClassFinal:
|
||||
F: Final = 3
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.a = ClassFinal.F
|
||||
|
||||
class Literals:
|
||||
def __init__(self) -> None:
|
||||
self.a = 'x'
|
||||
self.b = b'x'
|
||||
self.c = 2.2
|
||||
|
||||
class ListComprehension:
|
||||
def __init__(self, x: List[int]) -> None:
|
||||
self.a = [i + 1 for i in x]
|
||||
|
||||
class Helper:
|
||||
def __init__(self, arg) -> None:
|
||||
self.x = 0
|
||||
|
||||
def foo(self, arg) -> int:
|
||||
return 1
|
||||
|
||||
class AttrAccess:
|
||||
def __init__(self, o: Helper) -> None:
|
||||
self.x = o.x
|
||||
o.x = o.x + 1
|
||||
self.y = o.foo(self.x)
|
||||
o.foo(self)
|
||||
self.z = 1
|
||||
|
||||
class Construct:
|
||||
def __init__(self) -> None:
|
||||
self.x = Helper(1)
|
||||
self.y = Helper(self)
|
||||
|
||||
class IsInstance:
|
||||
def __init__(self, x: object) -> None:
|
||||
if isinstance(x, str):
|
||||
self.x = 0
|
||||
elif isinstance(x, Helper):
|
||||
self.x = 1
|
||||
elif isinstance(x, (list, tuple)):
|
||||
self.x = 2
|
||||
else:
|
||||
self.x = 3
|
||||
|
||||
class Cast:
|
||||
def __init__(self, x: object) -> None:
|
||||
self.x = cast(int, x)
|
||||
self.s = cast(str, x)
|
||||
self.c = cast(Cast, x)
|
||||
|
||||
class PropertyAccessGetter:
|
||||
def __init__(self, other: PropertyAccessGetter) -> None:
|
||||
self.x = other.p
|
||||
self.y = 1
|
||||
self.z = self.p
|
||||
|
||||
@property
|
||||
def p(self) -> int:
|
||||
return 0
|
||||
|
||||
class PropertyAccessSetter:
|
||||
def __init__(self, other: PropertyAccessSetter) -> None:
|
||||
other.p = 1
|
||||
self.y = 1
|
||||
self.z = self.p
|
||||
|
||||
@property
|
||||
def p(self) -> int:
|
||||
return 0
|
||||
|
||||
@p.setter
|
||||
def p(self, x: int) -> None:
|
||||
pass
|
||||
|
||||
def f() -> int:
|
||||
return 0
|
||||
|
||||
[file other.py]
|
||||
# Not compiled
|
||||
from typing_extensions import Final
|
||||
|
||||
Y: Final = 3
|
||||
|
||||
[out]
|
||||
C: []
|
||||
Collections: [d, d2, l, l2, s, s2, t]
|
||||
Comparisons: [c1, c2, n1, n2, o1, o2, s]
|
||||
BinaryOps: [a, b, c, d, e, f]
|
||||
LocalsAndGlobals: [a, g]
|
||||
Booleans: [a, b, c, d, e]
|
||||
ModuleFinal: [a, b]
|
||||
ClassFinal: [F, a]
|
||||
Literals: [a, b, c]
|
||||
ListComprehension: [a]
|
||||
Helper: [x]
|
||||
AttrAccess: [x, y]
|
||||
Construct: [x]
|
||||
IsInstance: [x]
|
||||
Cast: [c, s, x]
|
||||
PropertyAccessGetter: [x, y]
|
||||
PropertyAccessSetter: [y]
|
||||
|
||||
[case testAlwaysDefinedExpressions2]
|
||||
from typing import List, Tuple
|
||||
|
||||
class C:
|
||||
def __init__(self) -> None:
|
||||
self.x = 0
|
||||
|
||||
class AttributeRef:
|
||||
def __init__(self, c: C) -> None:
|
||||
self.aa = c.x
|
||||
self.bb = self.aa
|
||||
if c is not None:
|
||||
self.z = 0
|
||||
self.cc = 0
|
||||
self.dd = self.z
|
||||
|
||||
class ListOps:
|
||||
def __init__(self, x: List[int], n: int) -> None:
|
||||
self.a = len(x)
|
||||
self.b = x[n]
|
||||
self.c = [y + 1 for y in x]
|
||||
|
||||
class TupleOps:
|
||||
def __init__(self, t: Tuple[int, str]) -> None:
|
||||
x, y = t
|
||||
self.x = x
|
||||
self.y = t[0]
|
||||
s = x, y
|
||||
self.z = s
|
||||
|
||||
class IfExpr:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.a = 1 if x < 5 else 2
|
||||
|
||||
class Base:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
class Derived1(Base):
|
||||
def __init__(self, y: int) -> None:
|
||||
self.aa = y
|
||||
super().__init__(y)
|
||||
self.bb = y
|
||||
|
||||
class Derived2(Base):
|
||||
pass
|
||||
|
||||
class Conditionals:
|
||||
def __init__(self, b: bool, n: int) -> None:
|
||||
if not (n == 5 or n >= n + 1):
|
||||
self.a = b
|
||||
else:
|
||||
self.a = not b
|
||||
if b:
|
||||
self.b = 2
|
||||
else:
|
||||
self.b = 4
|
||||
|
||||
[out]
|
||||
C: [x]
|
||||
AttributeRef: [aa, bb, cc, dd]
|
||||
ListOps: [a, b, c]
|
||||
TupleOps: [x, y, z]
|
||||
IfExpr: [a]
|
||||
Base: [x]
|
||||
Derived1: [aa, bb, x]
|
||||
Derived2: [x]
|
||||
Conditionals: [a, b]
|
||||
|
||||
[case testAlwaysDefinedStatements]
|
||||
from typing import Any, List, Optional, Iterable
|
||||
|
||||
class Return:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
if x > 5:
|
||||
self.y = 1
|
||||
return
|
||||
self.y = 2
|
||||
self.z = x
|
||||
|
||||
class While:
|
||||
def __init__(self, x: int) -> None:
|
||||
n = 2
|
||||
while x > 0:
|
||||
n *=2
|
||||
x -= 1
|
||||
self.a = n
|
||||
while x < 5:
|
||||
self.b = 1
|
||||
self.b += 1
|
||||
|
||||
class Try:
|
||||
def __init__(self, x: List[int]) -> None:
|
||||
self.a = 0
|
||||
try:
|
||||
self.b = x[0]
|
||||
except:
|
||||
self.c = x
|
||||
self.d = 0
|
||||
try:
|
||||
self.e = x[0]
|
||||
except:
|
||||
self.e = 1
|
||||
|
||||
class TryFinally:
|
||||
def __init__(self, x: List[int]) -> None:
|
||||
self.a = 0
|
||||
try:
|
||||
self.b = x[0]
|
||||
finally:
|
||||
self.c = x
|
||||
self.d = 0
|
||||
try:
|
||||
self.e = x[0]
|
||||
finally:
|
||||
self.e = 1
|
||||
|
||||
class Assert:
|
||||
def __init__(self, x: Optional[str], y: int) -> None:
|
||||
assert x is not None
|
||||
assert y < 5
|
||||
self.a = x
|
||||
|
||||
class For:
|
||||
def __init__(self, it: Iterable[int]) -> None:
|
||||
self.x = 0
|
||||
for x in it:
|
||||
self.x += x
|
||||
for x in it:
|
||||
self.y = x
|
||||
|
||||
class Assignment1:
|
||||
def __init__(self, other: Assignment1) -> None:
|
||||
self.x = 0
|
||||
self = other # Give up after assignment to self
|
||||
self.y = 1
|
||||
|
||||
class Assignment2:
|
||||
def __init__(self) -> None:
|
||||
self.x = 0
|
||||
other = self # Give up after self is aliased
|
||||
self.y = other.x
|
||||
|
||||
class With:
|
||||
def __init__(self, x: Any) -> None:
|
||||
self.a = 0
|
||||
with x:
|
||||
self.b = 1
|
||||
self.c = 2
|
||||
|
||||
def f() -> None:
|
||||
pass
|
||||
|
||||
[out]
|
||||
Return: [x, y]
|
||||
While: [a]
|
||||
-- We could infer 'e' as always defined, but this is tricky, since always defined attribute
|
||||
-- analysis must be performed earlier than exception handling transform. This would be
|
||||
-- easy to infer *after* exception handling transform.
|
||||
Try: [a, d]
|
||||
-- Again, 'e' could be always defined, but it would be a bit tricky to do it.
|
||||
TryFinally: [a, c, d]
|
||||
Assert: [a]
|
||||
For: [x]
|
||||
Assignment1: [x]
|
||||
Assignment2: [x]
|
||||
-- TODO: Why is not 'b' included?
|
||||
With: [a, c]
|
||||
|
||||
[case testAlwaysDefinedAttributeDefaults]
|
||||
class Basic:
|
||||
x = 0
|
||||
|
||||
class ClassBodyAndInit:
|
||||
x = 0
|
||||
s = 'x'
|
||||
|
||||
def __init__(self, n: int) -> None:
|
||||
self.n = 0
|
||||
|
||||
class AttrWithDefaultAndInit:
|
||||
x = 0
|
||||
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
class Base:
|
||||
x = 0
|
||||
y = 1
|
||||
|
||||
class Derived(Base):
|
||||
y = 2
|
||||
z = 3
|
||||
[out]
|
||||
Basic: [x]
|
||||
ClassBodyAndInit: [n, s, x]
|
||||
AttrWithDefaultAndInit: [x]
|
||||
Base: [x, y]
|
||||
Derived: [x, y, z]
|
||||
|
||||
[case testAlwaysDefinedWithInheritance]
|
||||
class Base:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
class Deriv1(Base):
|
||||
def __init__(self, x: int, y: str) -> None:
|
||||
super().__init__(x)
|
||||
self.y = y
|
||||
|
||||
class Deriv2(Base):
|
||||
def __init__(self, x: int, y: str) -> None:
|
||||
self.y = y
|
||||
super().__init__(x)
|
||||
|
||||
class Deriv22(Deriv2):
|
||||
def __init__(self, x: int, y: str, z: bool) -> None:
|
||||
super().__init__(x, y)
|
||||
self.z = False
|
||||
|
||||
class Deriv3(Base):
|
||||
def __init__(self) -> None:
|
||||
super().__init__(1)
|
||||
|
||||
class Deriv4(Base):
|
||||
def __init__(self) -> None:
|
||||
self.y = 1
|
||||
self.x = 2
|
||||
|
||||
def f(a): pass
|
||||
|
||||
class BaseUnsafe:
|
||||
def __init__(self, x: int, y: int) -> None:
|
||||
self.x = x
|
||||
f(self) # Unknown function
|
||||
self.y = y
|
||||
|
||||
class DerivUnsafe(BaseUnsafe):
|
||||
def __init__(self, z: int, zz: int) -> None:
|
||||
self.z = z
|
||||
super().__init__(1, 2) # Calls unknown function
|
||||
self.zz = zz
|
||||
|
||||
class BaseWithDefault:
|
||||
x = 1
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.y = 1
|
||||
|
||||
class DerivedWithDefault(BaseWithDefault):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.z = 1
|
||||
|
||||
class AlwaysDefinedInBase:
|
||||
def __init__(self) -> None:
|
||||
self.x = 1
|
||||
self.y = 1
|
||||
|
||||
class UndefinedInDerived(AlwaysDefinedInBase):
|
||||
def __init__(self, x: bool) -> None:
|
||||
self.x = 1
|
||||
if x:
|
||||
self.y = 2
|
||||
|
||||
class UndefinedInDerived2(UndefinedInDerived):
|
||||
def __init__(self, x: bool):
|
||||
if x:
|
||||
self.y = 2
|
||||
[out]
|
||||
Base: [x]
|
||||
Deriv1: [x, y]
|
||||
Deriv2: [x, y]
|
||||
Deriv22: [x, y, z]
|
||||
Deriv3: [x]
|
||||
Deriv4: [x, y]
|
||||
BaseUnsafe: [x]
|
||||
DerivUnsafe: [x, z]
|
||||
BaseWithDefault: [x, y]
|
||||
DerivedWithDefault: [x, y, z]
|
||||
AlwaysDefinedInBase: []
|
||||
UndefinedInDerived: []
|
||||
UndefinedInDerived2: []
|
||||
|
||||
[case testAlwaysDefinedWithInheritance2]
|
||||
from mypy_extensions import trait, mypyc_attr
|
||||
|
||||
from interpreted import PythonBase
|
||||
|
||||
class BasePartiallyDefined:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.a = 0
|
||||
if x:
|
||||
self.x = x
|
||||
|
||||
class Derived1(BasePartiallyDefined):
|
||||
def __init__(self, x: int) -> None:
|
||||
super().__init__(x)
|
||||
self.y = x
|
||||
|
||||
class BaseUndefined:
|
||||
x: int
|
||||
|
||||
class DerivedAlwaysDefined(BaseUndefined):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.z = 0
|
||||
self.x = 2
|
||||
|
||||
@trait
|
||||
class MyTrait:
|
||||
def f(self) -> None: pass
|
||||
|
||||
class SimpleTraitImpl(MyTrait):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.x = 0
|
||||
|
||||
@trait
|
||||
class TraitWithAttr:
|
||||
x: int
|
||||
y: str
|
||||
|
||||
class TraitWithAttrImpl(TraitWithAttr):
|
||||
def __init__(self) -> None:
|
||||
self.y = 'x'
|
||||
|
||||
@trait
|
||||
class TraitWithAttr2:
|
||||
z: int
|
||||
|
||||
class TraitWithAttrImpl2(TraitWithAttr, TraitWithAttr2):
|
||||
def __init__(self) -> None:
|
||||
self.y = 'x'
|
||||
self.z = 2
|
||||
|
||||
@mypyc_attr(allow_interpreted_subclasses=True)
|
||||
class BaseWithGeneralSubclassing:
|
||||
x = 0
|
||||
y: int
|
||||
def __init__(self, s: str) -> None:
|
||||
self.s = s
|
||||
|
||||
class Derived2(BaseWithGeneralSubclassing):
|
||||
def __init__(self) -> None:
|
||||
super().__init__('x')
|
||||
self.z = 0
|
||||
|
||||
class SubclassPythonclass(PythonBase):
|
||||
def __init__(self) -> None:
|
||||
self.y = 1
|
||||
|
||||
class BaseWithSometimesDefined:
|
||||
def __init__(self, b: bool) -> None:
|
||||
if b:
|
||||
self.x = 0
|
||||
|
||||
class Derived3(BaseWithSometimesDefined):
|
||||
def __init__(self, b: bool) -> None:
|
||||
super().__init__(b)
|
||||
self.x = 1
|
||||
|
||||
[file interpreted.py]
|
||||
class PythonBase:
|
||||
def __init__(self) -> None:
|
||||
self.x = 0
|
||||
|
||||
[out]
|
||||
BasePartiallyDefined: [a]
|
||||
Derived1: [a, y]
|
||||
BaseUndefined: []
|
||||
DerivedAlwaysDefined: [x, z]
|
||||
MyTrait: []
|
||||
SimpleTraitImpl: [x]
|
||||
TraitWithAttr: []
|
||||
TraitWithAttrImpl: [y]
|
||||
TraitWithAttr2: []
|
||||
TraitWithAttrImpl2: [y, z]
|
||||
BaseWithGeneralSubclassing: []
|
||||
-- TODO: 's' could also be always defined
|
||||
Derived2: [x, z]
|
||||
-- Always defined attribute analysis is turned off when inheriting a non-native class.
|
||||
SubclassPythonclass: []
|
||||
BaseWithSometimesDefined: []
|
||||
-- TODO: 'x' could also be always defined, but it is a bit tricky to support
|
||||
Derived3: []
|
||||
|
||||
[case testAlwaysDefinedWithNesting]
|
||||
class NestedFunc:
|
||||
def __init__(self) -> None:
|
||||
self.x = 0
|
||||
def f() -> None:
|
||||
self.y = 0
|
||||
f()
|
||||
self.z = 1
|
||||
[out]
|
||||
-- TODO: Support nested functions.
|
||||
NestedFunc: []
|
||||
f___init___NestedFunc_obj: []
|
||||
603
venv/lib/python3.12/site-packages/mypyc/test-data/analysis.test
Normal file
603
venv/lib/python3.12/site-packages/mypyc/test-data/analysis.test
Normal file
@@ -0,0 +1,603 @@
|
||||
-- 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} {}
|
||||
@@ -0,0 +1,245 @@
|
||||
-- Test cases for invoking mypyc on the command line
|
||||
--
|
||||
-- These are slow -- do not add test cases unless you have a very good reason to do so.
|
||||
|
||||
[case testCompileMypyc]
|
||||
# cmd: a.py b.py p/__init__.py p/q.py
|
||||
import os.path
|
||||
import p
|
||||
import p.q
|
||||
import a
|
||||
import b
|
||||
print('<main>', b.g(a.A()))
|
||||
try:
|
||||
a.f('')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
for x in [a, b, p, p.q]:
|
||||
assert os.path.splitext(x.__file__)[1] != '.py'
|
||||
[file z.py]
|
||||
|
||||
[file a.py]
|
||||
import b
|
||||
import c
|
||||
from p import s
|
||||
from typing import NamedTuple
|
||||
|
||||
print('<a>', ord('A') == 65) # Test full builtins
|
||||
|
||||
class A:
|
||||
def __init__(self) -> None:
|
||||
self.x = 4
|
||||
|
||||
def f(x: int) -> b.B:
|
||||
return b.B(x)
|
||||
|
||||
class B:
|
||||
def __init__(self, x: int, y: str) -> None:
|
||||
self.x = x
|
||||
|
||||
print('<a>', f(5).x)
|
||||
print('<c>', c.foo())
|
||||
assert s.bar(10) == 20
|
||||
|
||||
class NT(NamedTuple):
|
||||
x: int
|
||||
|
||||
print(NT(2))
|
||||
|
||||
[file b.py]
|
||||
import a
|
||||
import p.q
|
||||
|
||||
class B:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
def g(z: 'a.A') -> int:
|
||||
return p.q.foo(z.x)
|
||||
|
||||
print('<b>', 'here')
|
||||
|
||||
[file c.py]
|
||||
def foo() -> int:
|
||||
return 10
|
||||
|
||||
[file p/__init__.py]
|
||||
|
||||
[file p/q.py]
|
||||
import p.r
|
||||
def foo(x: int) -> int:
|
||||
return x*p.r.foo(x)
|
||||
|
||||
[file p/r.py]
|
||||
def foo(x: int) -> int:
|
||||
return x
|
||||
|
||||
[file p/s.py]
|
||||
def bar(x: int) -> int:
|
||||
return x*2
|
||||
|
||||
[out]
|
||||
<b> here
|
||||
<a> True
|
||||
<a> 5
|
||||
<c> 10
|
||||
NT(x=2)
|
||||
<main> 16
|
||||
|
||||
-- This test is here so we can turn it on when we get nervous about
|
||||
-- this case, but is disabled for speed reasons.
|
||||
[case testCompileMypycOne-skip]
|
||||
# cmd: a.py
|
||||
import os.path
|
||||
import a
|
||||
assert os.path.splitext(a.__file__)[1] != '.py'
|
||||
assert a.f(10) == 100
|
||||
|
||||
[file a.py]
|
||||
def f(x: int) -> int:
|
||||
return x*x
|
||||
|
||||
[case testErrorOutput]
|
||||
# cmd: test.py
|
||||
|
||||
[file test.py]
|
||||
from typing import List, Any, AsyncIterable
|
||||
from typing_extensions import Final
|
||||
from mypy_extensions import trait, mypyc_attr
|
||||
from functools import singledispatch
|
||||
|
||||
def busted(b: bool) -> None:
|
||||
for i in range(1, 10, 0): # E: range() step can't be zero
|
||||
try:
|
||||
if i == 5:
|
||||
break # E: break inside try/finally block is unimplemented
|
||||
elif i == 4:
|
||||
continue # E: continue inside try/finally block is unimplemented
|
||||
finally:
|
||||
print('oops')
|
||||
|
||||
print(sum([1,2,3]))
|
||||
|
||||
x = [1,2]
|
||||
|
||||
class Foo:
|
||||
a, b = (10, 20) # E: Only assignment to variables is supported in class bodies
|
||||
x[0] = 10 # E: Only assignment to variables is supported in class bodies
|
||||
lol = 20
|
||||
l = [10] # W: Unsupported default attribute value
|
||||
c = d = 50 # E: Multiple assignment in class bodies not supported
|
||||
|
||||
if 1+1 == 2: # E: Unsupported statement in class body
|
||||
x = 10
|
||||
|
||||
Foo.lol = 50 # E: Only class variables defined as ClassVar can be assigned to
|
||||
|
||||
def decorator(x: Any) -> Any:
|
||||
return x
|
||||
|
||||
class NeverMetaclass(type): # E: Inheriting from most builtin types is unimplemented
|
||||
pass
|
||||
|
||||
class Concrete1:
|
||||
pass
|
||||
|
||||
@trait
|
||||
class PureTrait:
|
||||
pass
|
||||
|
||||
@trait
|
||||
class Trait1:
|
||||
pass
|
||||
|
||||
class Concrete2:
|
||||
pass
|
||||
|
||||
@trait
|
||||
class Trait2(Concrete2):
|
||||
pass
|
||||
|
||||
@decorator
|
||||
class NonExt(Concrete1): # E: Non-extension classes may not inherit from extension classes
|
||||
pass
|
||||
|
||||
|
||||
class NopeMultipleInheritance(Concrete1, Concrete2): # E: Multiple inheritance is not supported (except for traits)
|
||||
pass
|
||||
|
||||
class NopeMultipleInheritanceAndBadOrder(Concrete1, Trait1, Concrete2): # E: Multiple inheritance is not supported (except for traits)
|
||||
pass
|
||||
|
||||
class NopeMultipleInheritanceAndBadOrder2(Concrete1, Concrete2, Trait1): # E: Multiple inheritance is not supported (except for traits)
|
||||
pass
|
||||
|
||||
class NopeMultipleInheritanceAndBadOrder3(Trait1, Concrete1, Concrete2): # E: Non-trait base must appear first in parent list # E: Multiple inheritance is not supported (except for traits)
|
||||
pass
|
||||
|
||||
class NopeBadOrder(Trait1, Concrete2): # E: Non-trait base must appear first in parent list
|
||||
pass
|
||||
|
||||
|
||||
@decorator
|
||||
class NonExt2:
|
||||
@property # E: Property setters not supported in non-extension classes
|
||||
def test(self) -> int:
|
||||
return 0
|
||||
|
||||
@test.setter
|
||||
def test(self, x: int) -> None:
|
||||
pass
|
||||
|
||||
iterator_warning = (i+1 for i in range(10)) # W: Treating generator comprehension as list
|
||||
|
||||
# But we don't want warnings for these cases:
|
||||
tup = tuple(i+1 for i in range(10))
|
||||
a_str = " ".join(str(i) for i in range(10))
|
||||
wtvr = next(i for i in range(10) if i == 5)
|
||||
|
||||
d1 = {1: 2}
|
||||
|
||||
# Make sure we can produce an error when we hit the awful None case
|
||||
def f(l: List[object]) -> None:
|
||||
x = None # E: Local variable "x" has inferred type None; add an annotation
|
||||
for i in l:
|
||||
if x is None:
|
||||
x = i
|
||||
|
||||
@mypyc_attr(allow_interpreted_subclasses=True)
|
||||
class AllowInterp1(Concrete1): # E: Base class "test.Concrete1" does not allow interpreted subclasses
|
||||
pass
|
||||
|
||||
@mypyc_attr(allow_interpreted_subclasses=True)
|
||||
class AllowInterp2(PureTrait): # E: Base class "test.PureTrait" does not allow interpreted subclasses
|
||||
pass
|
||||
|
||||
async def async_generators() -> AsyncIterable[int]:
|
||||
yield 1 # E: async generators are unimplemented
|
||||
|
||||
@singledispatch
|
||||
def a(arg) -> None:
|
||||
pass
|
||||
|
||||
@decorator # E: Calling decorator after registering function not supported
|
||||
@a.register
|
||||
def g(arg: int) -> None:
|
||||
pass
|
||||
|
||||
@a.register
|
||||
@decorator
|
||||
def h(arg: str) -> None:
|
||||
pass
|
||||
|
||||
@decorator
|
||||
@decorator # E: Calling decorator after registering function not supported
|
||||
@a.register
|
||||
def i(arg: Foo) -> None:
|
||||
pass
|
||||
|
||||
[case testOnlyWarningOutput]
|
||||
# cmd: test.py
|
||||
|
||||
[file test.py]
|
||||
names = (str(v) for v in [1, 2, 3]) # W: Treating generator comprehension as list
|
||||
@@ -0,0 +1,48 @@
|
||||
"""Default driver for run tests (run-*.test).
|
||||
|
||||
This imports the 'native' module (containing the compiled test cases)
|
||||
and calls each function starting with test_, and reports any
|
||||
exceptions as failures.
|
||||
|
||||
Test cases can provide a custom driver.py that overrides this file.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import native
|
||||
|
||||
failures = []
|
||||
|
||||
for name in dir(native):
|
||||
if name.startswith('test_'):
|
||||
test_func = getattr(native, name)
|
||||
try:
|
||||
test_func()
|
||||
except Exception as e:
|
||||
failures.append((name, sys.exc_info()))
|
||||
|
||||
if failures:
|
||||
from traceback import print_exception, format_tb
|
||||
import re
|
||||
|
||||
def extract_line(tb):
|
||||
formatted = '\n'.join(format_tb(tb))
|
||||
m = re.search('File "(native|driver).py", line ([0-9]+), in (test_|<module>)', formatted)
|
||||
if m is None:
|
||||
return "0"
|
||||
return m.group(1)
|
||||
|
||||
# Sort failures by line number of test function.
|
||||
failures = sorted(failures, key=lambda e: extract_line(e[1][2]))
|
||||
|
||||
# If there are multiple failures, print stack traces of all but the final failure.
|
||||
for name, e in failures[:-1]:
|
||||
print(f'<< {name} >>')
|
||||
sys.stdout.flush()
|
||||
print_exception(*e)
|
||||
print()
|
||||
sys.stdout.flush()
|
||||
|
||||
# Raise exception for the last failure. Test runner will show the traceback.
|
||||
print(f'<< {failures[-1][0]} >>')
|
||||
sys.stdout.flush()
|
||||
raise failures[-1][1][1]
|
||||
@@ -0,0 +1,125 @@
|
||||
-- Test cases for basic block execution frequency analysis.
|
||||
--
|
||||
-- These test cases are using exception transform test machinery for convenience.
|
||||
--
|
||||
-- NOTE: These must all have the _freq suffix
|
||||
|
||||
[case testSimpleError_freq]
|
||||
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
|
||||
hot blocks: [0, 1, 2]
|
||||
|
||||
[case testHotBranch_freq]
|
||||
from typing import List
|
||||
def f(x: bool) -> None:
|
||||
if x:
|
||||
y = 1
|
||||
else:
|
||||
y = 2
|
||||
[out]
|
||||
def f(x):
|
||||
x :: bool
|
||||
y :: int
|
||||
L0:
|
||||
if x goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
y = 2
|
||||
dec_ref y :: int
|
||||
goto L3
|
||||
L2:
|
||||
y = 4
|
||||
dec_ref y :: int
|
||||
L3:
|
||||
return 1
|
||||
hot blocks: [0, 1, 2, 3]
|
||||
|
||||
[case testGoto_freq]
|
||||
from typing import List
|
||||
def f(x: bool) -> int:
|
||||
if x:
|
||||
y = 1
|
||||
else:
|
||||
return 2
|
||||
return y
|
||||
[out]
|
||||
def f(x):
|
||||
x :: bool
|
||||
y :: int
|
||||
L0:
|
||||
if x goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
y = 2
|
||||
goto L3
|
||||
L2:
|
||||
return 4
|
||||
L3:
|
||||
return y
|
||||
hot blocks: [0, 1, 2, 3]
|
||||
|
||||
[case testFalseOnError_freq]
|
||||
from typing import List
|
||||
def f(x: List[int]) -> None:
|
||||
x[0] = 1
|
||||
[out]
|
||||
def f(x):
|
||||
x :: list
|
||||
r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: None
|
||||
L0:
|
||||
r0 = object 1
|
||||
inc_ref r0
|
||||
r1 = CPyList_SetItem(x, 0, r0)
|
||||
if not r1 goto L2 (error at f:3) else goto L1 :: bool
|
||||
L1:
|
||||
return 1
|
||||
L2:
|
||||
r2 = <error> :: None
|
||||
return r2
|
||||
hot blocks: [0, 1]
|
||||
|
||||
[case testRareBranch_freq]
|
||||
from typing_extensions import Final
|
||||
|
||||
x: Final = str()
|
||||
|
||||
def f() -> str:
|
||||
return x
|
||||
[out]
|
||||
def f():
|
||||
r0 :: str
|
||||
r1 :: bool
|
||||
r2 :: str
|
||||
L0:
|
||||
r0 = __main__.x :: static
|
||||
if is_error(r0) goto L1 else goto L3
|
||||
L1:
|
||||
r1 = raise NameError('value for final name "x" was not set')
|
||||
if not r1 goto L4 (error at f:6) else goto L2 :: bool
|
||||
L2:
|
||||
unreachable
|
||||
L3:
|
||||
inc_ref r0
|
||||
return r0
|
||||
L4:
|
||||
r2 = <error> :: str
|
||||
return r2
|
||||
hot blocks: [0, 3]
|
||||
@@ -0,0 +1,713 @@
|
||||
-- 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 :: i32
|
||||
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 :: bit
|
||||
r5 :: int
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = x == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return 2
|
||||
L2:
|
||||
r2 = borrow cast(__main__.A, x)
|
||||
if is_error(r2) goto L6 (error at f:8) else goto L3
|
||||
L3:
|
||||
r3 = load_address _Py_NoneStruct
|
||||
r4 = r2 != r3
|
||||
if r4 goto L4 else goto L5 :: bool
|
||||
L4:
|
||||
return 4
|
||||
L5:
|
||||
return 6
|
||||
L6:
|
||||
r5 = <error> :: int
|
||||
return r5
|
||||
|
||||
[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_GetItemBorrow(a, i)
|
||||
if is_error(r6) goto L11 (error at sum:6) else goto L6
|
||||
L6:
|
||||
r7 = unbox(int, 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 = '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 = 'weeee'
|
||||
r6 = builtins :: module
|
||||
r7 = '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 = '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 L19
|
||||
L3:
|
||||
r4 = '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 = 'goodbye!'
|
||||
r11 = builtins :: module
|
||||
r12 = 'print'
|
||||
r13 = CPyObject_GetAttr(r11, r12)
|
||||
if is_error(r13) goto L20 (error at a:6) else goto L7
|
||||
L7:
|
||||
r14 = PyObject_CallFunctionObjArgs(r13, r10, 0)
|
||||
dec_ref r13
|
||||
if is_error(r14) goto L20 (error at a:6) else goto L21
|
||||
L8:
|
||||
if is_error(r7) goto L11 else goto L22
|
||||
L9:
|
||||
CPy_Reraise()
|
||||
if not 0 goto L13 else goto L23 :: bool
|
||||
L10:
|
||||
unreachable
|
||||
L11:
|
||||
if is_error(r5) goto L17 else goto L12
|
||||
L12:
|
||||
return r5
|
||||
L13:
|
||||
if is_error(r7) goto L15 else goto L14
|
||||
L14:
|
||||
CPy_RestoreExcInfo(r7)
|
||||
xdec_ref r7
|
||||
L15:
|
||||
r15 = CPy_KeepPropagating()
|
||||
if not r15 goto L18 else goto L16 :: bool
|
||||
L16:
|
||||
unreachable
|
||||
L17:
|
||||
unreachable
|
||||
L18:
|
||||
r16 = <error> :: str
|
||||
return r16
|
||||
L19:
|
||||
dec_ref r3
|
||||
goto L3
|
||||
L20:
|
||||
xdec_ref r5
|
||||
goto L13
|
||||
L21:
|
||||
dec_ref r14
|
||||
goto L8
|
||||
L22:
|
||||
xdec_ref r5
|
||||
goto L9
|
||||
L23:
|
||||
xdec_ref r7
|
||||
goto L10
|
||||
|
||||
[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 = '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 = ''
|
||||
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 = 'foo'
|
||||
r3 = CPyObject_GetAttr(x, r2)
|
||||
if is_error(r3) goto L4 (error at lol:4) else goto L15
|
||||
L2:
|
||||
a = r3
|
||||
r4 = '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 = 'a'
|
||||
inc_ref r1
|
||||
u = r1
|
||||
L1:
|
||||
if b goto L10 else goto L11 :: bool
|
||||
L2:
|
||||
r2 = '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 = '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
|
||||
|
||||
[case testExceptionWithOverlappingErrorValue]
|
||||
from mypy_extensions import i64
|
||||
|
||||
def f() -> i64:
|
||||
return 0
|
||||
|
||||
def g() -> i64:
|
||||
return f()
|
||||
[out]
|
||||
def f():
|
||||
L0:
|
||||
return 0
|
||||
def g():
|
||||
r0 :: i64
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
r3 :: i64
|
||||
L0:
|
||||
r0 = f()
|
||||
r1 = r0 == -113
|
||||
if r1 goto L2 else goto L1 :: bool
|
||||
L1:
|
||||
return r0
|
||||
L2:
|
||||
r2 = PyErr_Occurred()
|
||||
if not is_error(r2) goto L3 (error at g:7) else goto L1
|
||||
L3:
|
||||
r3 = <error> :: i64
|
||||
return r3
|
||||
|
||||
[case testExceptionWithNativeAttributeGetAndSet]
|
||||
class C:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
def foo(c: C, x: int) -> None:
|
||||
c.x = x - c.x
|
||||
[out]
|
||||
def C.__init__(self, x):
|
||||
self :: __main__.C
|
||||
x :: int
|
||||
L0:
|
||||
inc_ref x :: int
|
||||
self.x = x
|
||||
return 1
|
||||
def foo(c, x):
|
||||
c :: __main__.C
|
||||
x, r0, r1 :: int
|
||||
r2 :: bool
|
||||
L0:
|
||||
r0 = borrow c.x
|
||||
r1 = CPyTagged_Subtract(x, r0)
|
||||
c.x = r1
|
||||
return 1
|
||||
|
||||
[case testExceptionWithOverlappingFloatErrorValue]
|
||||
def f() -> float:
|
||||
return 0.0
|
||||
|
||||
def g() -> float:
|
||||
return f()
|
||||
[out]
|
||||
def f():
|
||||
L0:
|
||||
return 0.0
|
||||
def g():
|
||||
r0 :: float
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
r3 :: float
|
||||
L0:
|
||||
r0 = f()
|
||||
r1 = r0 == -113.0
|
||||
if r1 goto L2 else goto L1 :: bool
|
||||
L1:
|
||||
return r0
|
||||
L2:
|
||||
r2 = PyErr_Occurred()
|
||||
if not is_error(r2) goto L3 (error at g:5) else goto L1
|
||||
L3:
|
||||
r3 = <error> :: float
|
||||
return r3
|
||||
|
||||
[case testExceptionWithLowLevelIntAttribute]
|
||||
from mypy_extensions import i32, i64
|
||||
|
||||
class C:
|
||||
def __init__(self, x: i32, y: i64) -> None:
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def f(c: C) -> None:
|
||||
c.x
|
||||
c.y
|
||||
[out]
|
||||
def C.__init__(self, x, y):
|
||||
self :: __main__.C
|
||||
x :: i32
|
||||
y :: i64
|
||||
L0:
|
||||
self.x = x
|
||||
self.y = y
|
||||
return 1
|
||||
def f(c):
|
||||
c :: __main__.C
|
||||
r0 :: i32
|
||||
r1 :: i64
|
||||
L0:
|
||||
r0 = c.x
|
||||
r1 = c.y
|
||||
return 1
|
||||
|
||||
[case testConditionallyUndefinedI64]
|
||||
from mypy_extensions import i64
|
||||
|
||||
def f(x: i64) -> i64:
|
||||
if x:
|
||||
y: i64 = 2
|
||||
return y
|
||||
[out]
|
||||
def f(x):
|
||||
x, r0, y :: i64
|
||||
__locals_bitmap0 :: u32
|
||||
r1 :: bit
|
||||
r2, r3 :: u32
|
||||
r4 :: bit
|
||||
r5 :: bool
|
||||
r6 :: i64
|
||||
L0:
|
||||
r0 = <error> :: i64
|
||||
y = r0
|
||||
__locals_bitmap0 = 0
|
||||
r1 = x != 0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
y = 2
|
||||
r2 = __locals_bitmap0 | 1
|
||||
__locals_bitmap0 = r2
|
||||
L2:
|
||||
r3 = __locals_bitmap0 & 1
|
||||
r4 = r3 == 0
|
||||
if r4 goto L3 else goto L5 :: bool
|
||||
L3:
|
||||
r5 = raise UnboundLocalError('local variable "y" referenced before assignment')
|
||||
if not r5 goto L6 (error at f:-1) else goto L4 :: bool
|
||||
L4:
|
||||
unreachable
|
||||
L5:
|
||||
return y
|
||||
L6:
|
||||
r6 = <error> :: i64
|
||||
return r6
|
||||
|
||||
[case testExceptionWithFloatAttribute]
|
||||
class C:
|
||||
def __init__(self, x: float, y: float) -> None:
|
||||
self.x = x
|
||||
if x:
|
||||
self.y = y
|
||||
|
||||
def f(c: C) -> float:
|
||||
return c.x + c.y
|
||||
[out]
|
||||
def C.__init__(self, x, y):
|
||||
self :: __main__.C
|
||||
x, y :: float
|
||||
r0 :: bit
|
||||
L0:
|
||||
self.x = x
|
||||
r0 = x != 0.0
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
self.y = y
|
||||
L2:
|
||||
return 1
|
||||
def f(c):
|
||||
c :: __main__.C
|
||||
r0, r1 :: float
|
||||
r2 :: bit
|
||||
r3 :: float
|
||||
r4 :: object
|
||||
r5 :: float
|
||||
L0:
|
||||
r0 = c.x
|
||||
r1 = c.y
|
||||
r2 = r1 == -113.0
|
||||
if r2 goto L2 else goto L1 :: bool
|
||||
L1:
|
||||
r3 = r0 + r1
|
||||
return r3
|
||||
L2:
|
||||
r4 = PyErr_Occurred()
|
||||
if not is_error(r4) goto L3 (error at f:8) else goto L1
|
||||
L3:
|
||||
r5 = <error> :: float
|
||||
return r5
|
||||
373
venv/lib/python3.12/site-packages/mypyc/test-data/fixtures/ir.py
Normal file
373
venv/lib/python3.12/site-packages/mypyc/test-data/fixtures/ir.py
Normal file
@@ -0,0 +1,373 @@
|
||||
# These builtins stubs are used implicitly in AST to IR generation
|
||||
# test cases.
|
||||
|
||||
import _typeshed
|
||||
from typing import (
|
||||
TypeVar, Generic, List, Iterator, Iterable, Dict, Optional, Tuple, Any, Set,
|
||||
overload, Mapping, Union, Callable, Sequence, FrozenSet, Protocol
|
||||
)
|
||||
|
||||
T = TypeVar('T')
|
||||
T_co = TypeVar('T_co', covariant=True)
|
||||
T_contra = TypeVar('T_contra', contravariant=True)
|
||||
S = TypeVar('S')
|
||||
K = TypeVar('K') # for keys in mapping
|
||||
V = TypeVar('V') # for values in mapping
|
||||
|
||||
class __SupportsAbs(Protocol[T_co]):
|
||||
def __abs__(self) -> T_co: pass
|
||||
|
||||
class __SupportsDivMod(Protocol[T_contra, T_co]):
|
||||
def __divmod__(self, other: T_contra) -> T_co: ...
|
||||
|
||||
class __SupportsRDivMod(Protocol[T_contra, T_co]):
|
||||
def __rdivmod__(self, other: T_contra) -> T_co: ...
|
||||
|
||||
_M = TypeVar("_M", contravariant=True)
|
||||
|
||||
class __SupportsPow2(Protocol[T_contra, T_co]):
|
||||
def __pow__(self, other: T_contra) -> T_co: ...
|
||||
|
||||
class __SupportsPow3NoneOnly(Protocol[T_contra, T_co]):
|
||||
def __pow__(self, other: T_contra, modulo: None = ...) -> T_co: ...
|
||||
|
||||
class __SupportsPow3(Protocol[T_contra, _M, T_co]):
|
||||
def __pow__(self, other: T_contra, modulo: _M) -> T_co: ...
|
||||
|
||||
__SupportsSomeKindOfPow = Union[
|
||||
__SupportsPow2[Any, Any], __SupportsPow3NoneOnly[Any, Any] | __SupportsPow3[Any, Any, Any]
|
||||
]
|
||||
|
||||
class object:
|
||||
def __init__(self) -> None: pass
|
||||
def __eq__(self, x: object) -> bool: pass
|
||||
def __ne__(self, x: object) -> bool: pass
|
||||
|
||||
class type:
|
||||
def __init__(self, o: object) -> None: ...
|
||||
__name__ : str
|
||||
__annotations__: Dict[str, Any]
|
||||
|
||||
class ellipsis: pass
|
||||
|
||||
# Primitive types are special in generated code.
|
||||
|
||||
class int:
|
||||
@overload
|
||||
def __init__(self) -> None: pass
|
||||
@overload
|
||||
def __init__(self, x: object, base: int = 10) -> None: pass
|
||||
def __add__(self, n: int) -> int: pass
|
||||
def __sub__(self, n: int) -> int: pass
|
||||
def __mul__(self, n: int) -> int: pass
|
||||
def __pow__(self, n: int, modulo: Optional[int] = None) -> int: pass
|
||||
def __floordiv__(self, x: int) -> int: pass
|
||||
def __truediv__(self, x: float) -> float: pass
|
||||
def __mod__(self, x: int) -> int: pass
|
||||
def __divmod__(self, x: float) -> Tuple[float, float]: pass
|
||||
def __neg__(self) -> int: pass
|
||||
def __pos__(self) -> int: pass
|
||||
def __abs__(self) -> int: pass
|
||||
def __invert__(self) -> int: pass
|
||||
def __and__(self, n: int) -> int: pass
|
||||
def __or__(self, n: int) -> int: pass
|
||||
def __xor__(self, n: int) -> int: pass
|
||||
def __lshift__(self, x: int) -> int: pass
|
||||
def __rshift__(self, x: int) -> int: pass
|
||||
def __eq__(self, n: object) -> bool: pass
|
||||
def __ne__(self, n: object) -> bool: pass
|
||||
def __lt__(self, n: int) -> bool: pass
|
||||
def __gt__(self, n: int) -> bool: pass
|
||||
def __le__(self, n: int) -> bool: pass
|
||||
def __ge__(self, n: int) -> bool: pass
|
||||
|
||||
class str:
|
||||
@overload
|
||||
def __init__(self) -> None: pass
|
||||
@overload
|
||||
def __init__(self, x: object) -> None: pass
|
||||
def __add__(self, x: str) -> str: pass
|
||||
def __mul__(self, x: int) -> str: pass
|
||||
def __rmul__(self, x: int) -> str: pass
|
||||
def __eq__(self, x: object) -> bool: pass
|
||||
def __ne__(self, x: object) -> bool: pass
|
||||
def __lt__(self, x: str) -> bool: ...
|
||||
def __le__(self, x: str) -> bool: ...
|
||||
def __gt__(self, x: str) -> bool: ...
|
||||
def __ge__(self, x: str) -> bool: ...
|
||||
@overload
|
||||
def __getitem__(self, i: int) -> str: pass
|
||||
@overload
|
||||
def __getitem__(self, i: slice) -> str: pass
|
||||
def __contains__(self, item: str) -> bool: pass
|
||||
def __iter__(self) -> Iterator[str]: ...
|
||||
def split(self, sep: Optional[str] = None, max: Optional[int] = None) -> List[str]: pass
|
||||
def strip (self, item: str) -> str: pass
|
||||
def join(self, x: Iterable[str]) -> str: pass
|
||||
def format(self, *args: Any, **kwargs: Any) -> str: ...
|
||||
def upper(self) -> str: ...
|
||||
def startswith(self, x: str, start: int=..., end: int=...) -> bool: ...
|
||||
def endswith(self, x: str, start: int=..., end: int=...) -> bool: ...
|
||||
def replace(self, old: str, new: str, maxcount: int=...) -> str: ...
|
||||
def encode(self, x: str=..., y: str=...) -> bytes: ...
|
||||
|
||||
class float:
|
||||
def __init__(self, x: object) -> None: pass
|
||||
def __add__(self, n: float) -> float: pass
|
||||
def __radd__(self, n: float) -> float: pass
|
||||
def __sub__(self, n: float) -> float: pass
|
||||
def __rsub__(self, n: float) -> float: pass
|
||||
def __mul__(self, n: float) -> float: pass
|
||||
def __truediv__(self, n: float) -> float: pass
|
||||
def __floordiv__(self, n: float) -> float: pass
|
||||
def __mod__(self, n: float) -> float: pass
|
||||
def __pow__(self, n: float) -> float: pass
|
||||
def __neg__(self) -> float: pass
|
||||
def __pos__(self) -> float: pass
|
||||
def __abs__(self) -> float: pass
|
||||
def __invert__(self) -> float: pass
|
||||
def __eq__(self, x: object) -> bool: pass
|
||||
def __ne__(self, x: object) -> bool: pass
|
||||
def __lt__(self, x: float) -> bool: ...
|
||||
def __le__(self, x: float) -> bool: ...
|
||||
def __gt__(self, x: float) -> bool: ...
|
||||
def __ge__(self, x: float) -> bool: ...
|
||||
|
||||
class complex:
|
||||
def __init__(self, x: object, y: object = None) -> None: pass
|
||||
def __add__(self, n: complex) -> complex: pass
|
||||
def __radd__(self, n: float) -> complex: pass
|
||||
def __sub__(self, n: complex) -> complex: pass
|
||||
def __rsub__(self, n: float) -> complex: pass
|
||||
def __mul__(self, n: complex) -> complex: pass
|
||||
def __truediv__(self, n: complex) -> complex: pass
|
||||
def __neg__(self) -> complex: pass
|
||||
|
||||
class bytes:
|
||||
@overload
|
||||
def __init__(self) -> None: ...
|
||||
@overload
|
||||
def __init__(self, x: object) -> None: ...
|
||||
def __add__(self, x: bytes) -> bytes: ...
|
||||
def __mul__(self, x: int) -> bytes: ...
|
||||
def __rmul__(self, x: int) -> bytes: ...
|
||||
def __eq__(self, x: object) -> bool: ...
|
||||
def __ne__(self, x: object) -> bool: ...
|
||||
@overload
|
||||
def __getitem__(self, i: int) -> int: ...
|
||||
@overload
|
||||
def __getitem__(self, i: slice) -> bytes: ...
|
||||
def join(self, x: Iterable[object]) -> bytes: ...
|
||||
def decode(self, x: str=..., y: str=...) -> str: ...
|
||||
|
||||
class bytearray:
|
||||
@overload
|
||||
def __init__(self) -> None: pass
|
||||
@overload
|
||||
def __init__(self, x: object) -> None: pass
|
||||
@overload
|
||||
def __init__(self, string: str, encoding: str, err: str = ...) -> None: pass
|
||||
def __add__(self, s: bytes) -> bytearray: ...
|
||||
def __setitem__(self, i: int, o: int) -> None: ...
|
||||
def __getitem__(self, i: int) -> int: ...
|
||||
def decode(self, x: str = ..., y: str = ...) -> str: ...
|
||||
|
||||
class bool(int):
|
||||
def __init__(self, o: object = ...) -> None: ...
|
||||
@overload
|
||||
def __and__(self, n: bool) -> bool: ...
|
||||
@overload
|
||||
def __and__(self, n: int) -> int: ...
|
||||
@overload
|
||||
def __or__(self, n: bool) -> bool: ...
|
||||
@overload
|
||||
def __or__(self, n: int) -> int: ...
|
||||
@overload
|
||||
def __xor__(self, n: bool) -> bool: ...
|
||||
@overload
|
||||
def __xor__(self, n: int) -> int: ...
|
||||
|
||||
class tuple(Generic[T_co], Sequence[T_co], Iterable[T_co]):
|
||||
def __init__(self, i: Iterable[T_co]) -> None: pass
|
||||
@overload
|
||||
def __getitem__(self, i: int) -> T_co: pass
|
||||
@overload
|
||||
def __getitem__(self, i: slice) -> Tuple[T_co, ...]: pass
|
||||
def __len__(self) -> int: pass
|
||||
def __iter__(self) -> Iterator[T_co]: ...
|
||||
def __contains__(self, item: object) -> int: ...
|
||||
|
||||
class function: pass
|
||||
|
||||
class list(Generic[T], Sequence[T], Iterable[T]):
|
||||
def __init__(self, i: Optional[Iterable[T]] = None) -> None: pass
|
||||
@overload
|
||||
def __getitem__(self, i: int) -> T: ...
|
||||
@overload
|
||||
def __getitem__(self, s: slice) -> List[T]: ...
|
||||
def __setitem__(self, i: int, o: T) -> None: pass
|
||||
def __delitem__(self, i: int) -> None: pass
|
||||
def __mul__(self, i: int) -> List[T]: pass
|
||||
def __rmul__(self, i: int) -> List[T]: pass
|
||||
def __iter__(self) -> Iterator[T]: pass
|
||||
def __len__(self) -> int: pass
|
||||
def __contains__(self, item: object) -> int: ...
|
||||
def __add__(self, x: List[T]) -> List[T]: ...
|
||||
def append(self, x: T) -> None: pass
|
||||
def pop(self, i: int = -1) -> T: pass
|
||||
def count(self, T) -> int: pass
|
||||
def extend(self, l: Iterable[T]) -> None: pass
|
||||
def insert(self, i: int, x: T) -> None: pass
|
||||
def sort(self) -> None: pass
|
||||
def reverse(self) -> None: pass
|
||||
def remove(self, o: T) -> None: pass
|
||||
def index(self, o: T) -> int: pass
|
||||
|
||||
class dict(Mapping[K, V]):
|
||||
@overload
|
||||
def __init__(self, **kwargs: K) -> None: ...
|
||||
@overload
|
||||
def __init__(self, map: Mapping[K, V], **kwargs: V) -> None: ...
|
||||
@overload
|
||||
def __init__(self, iterable: Iterable[Tuple[K, V]], **kwargs: V) -> None: ...
|
||||
def __getitem__(self, key: K) -> V: pass
|
||||
def __setitem__(self, k: K, v: V) -> None: pass
|
||||
def __delitem__(self, k: K) -> None: pass
|
||||
def __contains__(self, item: object) -> int: pass
|
||||
def __iter__(self) -> Iterator[K]: pass
|
||||
def __len__(self) -> int: pass
|
||||
@overload
|
||||
def update(self, __m: Mapping[K, V], **kwargs: V) -> None: pass
|
||||
@overload
|
||||
def update(self, __m: Iterable[Tuple[K, V]], **kwargs: V) -> None: ...
|
||||
@overload
|
||||
def update(self, **kwargs: V) -> None: ...
|
||||
def pop(self, x: int) -> K: pass
|
||||
def keys(self) -> Iterable[K]: pass
|
||||
def values(self) -> Iterable[V]: pass
|
||||
def items(self) -> Iterable[Tuple[K, V]]: pass
|
||||
def clear(self) -> None: pass
|
||||
def copy(self) -> Dict[K, V]: pass
|
||||
def setdefault(self, key: K, val: V = ...) -> V: pass
|
||||
|
||||
class set(Generic[T]):
|
||||
def __init__(self, i: Optional[Iterable[T]] = None) -> None: pass
|
||||
def __iter__(self) -> Iterator[T]: pass
|
||||
def __len__(self) -> int: pass
|
||||
def add(self, x: T) -> None: pass
|
||||
def remove(self, x: T) -> None: pass
|
||||
def discard(self, x: T) -> None: pass
|
||||
def clear(self) -> None: pass
|
||||
def pop(self) -> T: pass
|
||||
def update(self, x: Iterable[S]) -> None: pass
|
||||
def __or__(self, s: Union[Set[S], FrozenSet[S]]) -> Set[Union[T, S]]: ...
|
||||
def __xor__(self, s: Union[Set[S], FrozenSet[S]]) -> Set[Union[T, S]]: ...
|
||||
|
||||
class frozenset(Generic[T]):
|
||||
def __init__(self, i: Optional[Iterable[T]] = None) -> None: pass
|
||||
def __iter__(self) -> Iterator[T]: pass
|
||||
def __len__(self) -> int: pass
|
||||
def __or__(self, s: Union[Set[S], FrozenSet[S]]) -> FrozenSet[Union[T, S]]: ...
|
||||
def __xor__(self, s: Union[Set[S], FrozenSet[S]]) -> FrozenSet[Union[T, S]]: ...
|
||||
|
||||
class slice: pass
|
||||
|
||||
class range(Iterable[int]):
|
||||
def __init__(self, x: int, y: int = ..., z: int = ...) -> None: pass
|
||||
def __iter__(self) -> Iterator[int]: pass
|
||||
def __len__(self) -> int: pass
|
||||
def __next__(self) -> int: pass
|
||||
|
||||
class property:
|
||||
def __init__(self, fget: Optional[Callable[[Any], Any]] = ...,
|
||||
fset: Optional[Callable[[Any, Any], None]] = ...,
|
||||
fdel: Optional[Callable[[Any], None]] = ...,
|
||||
doc: Optional[str] = ...) -> None: ...
|
||||
def getter(self, fget: Callable[[Any], Any]) -> property: ...
|
||||
def setter(self, fset: Callable[[Any, Any], None]) -> property: ...
|
||||
def deleter(self, fdel: Callable[[Any], None]) -> property: ...
|
||||
def __get__(self, obj: Any, type: Optional[type] = ...) -> Any: ...
|
||||
def __set__(self, obj: Any, value: Any) -> None: ...
|
||||
def __delete__(self, obj: Any) -> None: ...
|
||||
def fget(self) -> Any: ...
|
||||
def fset(self, value: Any) -> None: ...
|
||||
def fdel(self) -> None: ...
|
||||
|
||||
class BaseException: pass
|
||||
|
||||
class Exception(BaseException):
|
||||
def __init__(self, message: Optional[str] = None) -> None: pass
|
||||
|
||||
class Warning(Exception): pass
|
||||
class UserWarning(Warning): pass
|
||||
class TypeError(Exception): pass
|
||||
class ValueError(Exception): pass
|
||||
class AttributeError(Exception): pass
|
||||
class ImportError(Exception): pass
|
||||
class NameError(Exception): pass
|
||||
class UnboundLocalError(NameError): pass
|
||||
class LookupError(Exception): pass
|
||||
class KeyError(LookupError): pass
|
||||
class IndexError(LookupError): pass
|
||||
class RuntimeError(Exception): pass
|
||||
class UnicodeEncodeError(RuntimeError): pass
|
||||
class UnicodeDecodeError(RuntimeError): pass
|
||||
class NotImplementedError(RuntimeError): pass
|
||||
|
||||
class StopIteration(Exception):
|
||||
value: Any
|
||||
|
||||
class ArithmeticError(Exception): pass
|
||||
class ZeroDivisionError(ArithmeticError): pass
|
||||
class OverflowError(ArithmeticError): pass
|
||||
|
||||
class GeneratorExit(BaseException): pass
|
||||
|
||||
def any(i: Iterable[T]) -> bool: pass
|
||||
def all(i: Iterable[T]) -> bool: pass
|
||||
def sum(i: Iterable[T]) -> int: pass
|
||||
def reversed(object: Sequence[T]) -> Iterator[T]: ...
|
||||
def id(o: object) -> int: pass
|
||||
# This type is obviously wrong but the test stubs don't have Sized anymore
|
||||
def len(o: object) -> int: pass
|
||||
def print(*object) -> None: pass
|
||||
def isinstance(x: object, t: object) -> bool: pass
|
||||
def iter(i: Iterable[T]) -> Iterator[T]: pass
|
||||
@overload
|
||||
def next(i: Iterator[T]) -> T: pass
|
||||
@overload
|
||||
def next(i: Iterator[T], default: T) -> T: pass
|
||||
def hash(o: object) -> int: ...
|
||||
def globals() -> Dict[str, Any]: ...
|
||||
def getattr(obj: object, name: str, default: Any = None) -> Any: ...
|
||||
def setattr(obj: object, name: str, value: Any) -> None: ...
|
||||
def enumerate(x: Iterable[T]) -> Iterator[Tuple[int, T]]: ...
|
||||
@overload
|
||||
def zip(x: Iterable[T], y: Iterable[S]) -> Iterator[Tuple[T, S]]: ...
|
||||
@overload
|
||||
def zip(x: Iterable[T], y: Iterable[S], z: Iterable[V]) -> Iterator[Tuple[T, S, V]]: ...
|
||||
def eval(e: str) -> Any: ...
|
||||
def abs(x: __SupportsAbs[T]) -> T: ...
|
||||
@overload
|
||||
def divmod(x: __SupportsDivMod[T_contra, T_co], y: T_contra) -> T_co: ...
|
||||
@overload
|
||||
def divmod(x: T_contra, y: __SupportsRDivMod[T_contra, T_co]) -> T_co: ...
|
||||
@overload
|
||||
def pow(base: __SupportsPow2[T_contra, T_co], exp: T_contra, mod: None = None) -> T_co: ...
|
||||
@overload
|
||||
def pow(base: __SupportsPow3NoneOnly[T_contra, T_co], exp: T_contra, mod: None = None) -> T_co: ...
|
||||
@overload
|
||||
def pow(base: __SupportsPow3[T_contra, _M, T_co], exp: T_contra, mod: _M) -> T_co: ...
|
||||
def exit() -> None: ...
|
||||
def min(x: T, y: T) -> T: ...
|
||||
def max(x: T, y: T) -> T: ...
|
||||
def repr(o: object) -> str: ...
|
||||
def ascii(o: object) -> str: ...
|
||||
def ord(o: object) -> int: ...
|
||||
def chr(i: int) -> str: ...
|
||||
|
||||
# Dummy definitions.
|
||||
class classmethod: pass
|
||||
class staticmethod: pass
|
||||
|
||||
NotImplemented: Any = ...
|
||||
@@ -0,0 +1,103 @@
|
||||
# Simple support library for our run tests.
|
||||
|
||||
from contextlib import contextmanager
|
||||
from collections.abc import Iterator
|
||||
import math
|
||||
from typing import (
|
||||
Any, Iterator, TypeVar, Generator, Optional, List, Tuple, Sequence,
|
||||
Union, Callable, Awaitable,
|
||||
)
|
||||
from typing import Final
|
||||
|
||||
FLOAT_MAGIC: Final = -113.0
|
||||
|
||||
# Various different float values
|
||||
float_vals = [
|
||||
float(n) * 0.25 for n in range(-10, 10)
|
||||
] + [
|
||||
-0.0,
|
||||
1.0/3.0,
|
||||
math.sqrt(2.0),
|
||||
1.23e200,
|
||||
-2.34e200,
|
||||
5.43e-100,
|
||||
-6.532e-200,
|
||||
float('inf'),
|
||||
-float('inf'),
|
||||
float('nan'),
|
||||
FLOAT_MAGIC,
|
||||
math.pi,
|
||||
2.0 * math.pi,
|
||||
math.pi / 2.0,
|
||||
-math.pi / 2.0,
|
||||
-1.7976931348623158e+308, # Smallest finite value
|
||||
-2.2250738585072014e-308, # Closest to zero negative normal value
|
||||
-7.5491e-312, # Arbitrary negative subnormal value
|
||||
-5e-324, # Closest to zero negative subnormal value
|
||||
1.7976931348623158e+308, # Largest finite value
|
||||
2.2250738585072014e-308, # Closest to zero positive normal value
|
||||
-6.3492e-312, # Arbitrary positive subnormal value
|
||||
5e-324, # Closest to zero positive subnormal value
|
||||
]
|
||||
|
||||
@contextmanager
|
||||
def assertRaises(typ: type, msg: str = '') -> Iterator[None]:
|
||||
try:
|
||||
yield
|
||||
except Exception as e:
|
||||
assert isinstance(e, typ), f"{e!r} is not a {typ.__name__}"
|
||||
assert msg in str(e), f'Message "{e}" does not match "{msg}"'
|
||||
else:
|
||||
assert False, f"Expected {typ.__name__} but got no exception"
|
||||
|
||||
def assertDomainError() -> Any:
|
||||
return assertRaises(ValueError, "math domain error")
|
||||
|
||||
def assertMathRangeError() -> Any:
|
||||
return assertRaises(OverflowError, "math range error")
|
||||
|
||||
T = TypeVar('T')
|
||||
U = TypeVar('U')
|
||||
V = TypeVar('V')
|
||||
|
||||
def run_generator(gen: Generator[T, V, U],
|
||||
inputs: Optional[List[V]] = None,
|
||||
p: bool = False) -> Tuple[Sequence[T], Union[U, str]]:
|
||||
res: List[T] = []
|
||||
i = -1
|
||||
while True:
|
||||
try:
|
||||
if i >= 0 and inputs:
|
||||
# ... fixtures don't have send
|
||||
val = gen.send(inputs[i]) # type: ignore
|
||||
elif not hasattr(gen, '__next__'): # type: ignore
|
||||
val = gen.send(None) # type: ignore
|
||||
else:
|
||||
val = next(gen)
|
||||
except StopIteration as e:
|
||||
return (tuple(res), e.value)
|
||||
except Exception as e:
|
||||
return (tuple(res), str(e))
|
||||
if p:
|
||||
print(val)
|
||||
res.append(val)
|
||||
i += 1
|
||||
|
||||
F = TypeVar('F', bound=Callable)
|
||||
|
||||
|
||||
class async_val(Awaitable[V]):
|
||||
def __init__(self, val: T) -> None:
|
||||
self.val = val
|
||||
|
||||
def __await__(self) -> Generator[T, V, V]:
|
||||
z = yield self.val
|
||||
return z
|
||||
|
||||
|
||||
# Wrap a mypyc-generated function in a real python function, to allow it to be
|
||||
# stuck into classes and the like.
|
||||
def make_python_function(f: F) -> F:
|
||||
def g(*args: Any, **kwargs: Any) -> Any:
|
||||
return f(*args, **kwargs)
|
||||
return g # type: ignore
|
||||
@@ -0,0 +1,169 @@
|
||||
# More complete stub for typing module.
|
||||
#
|
||||
# Use [typing fixtures/typing-full.pyi] to use this instead of lib-stub/typing.pyi
|
||||
# in a particular test case.
|
||||
#
|
||||
# Many of the definitions have special handling in the type checker, so they
|
||||
# can just be initialized to anything.
|
||||
|
||||
from abc import abstractmethod, ABCMeta
|
||||
|
||||
class GenericMeta(type): pass
|
||||
|
||||
cast = 0
|
||||
overload = 0
|
||||
Any = 0
|
||||
Union = 0
|
||||
Optional = 0
|
||||
TypeVar = 0
|
||||
Generic = 0
|
||||
Protocol = 0
|
||||
Tuple = 0
|
||||
Callable = 0
|
||||
_promote = 0
|
||||
NamedTuple = 0
|
||||
Type = 0
|
||||
no_type_check = 0
|
||||
ClassVar = 0
|
||||
Final = 0
|
||||
Literal = 0
|
||||
TypedDict = 0
|
||||
NoReturn = 0
|
||||
NewType = 0
|
||||
|
||||
T = TypeVar('T')
|
||||
T_co = TypeVar('T_co', covariant=True)
|
||||
T_contra = TypeVar('T_contra', contravariant=True)
|
||||
U = TypeVar('U')
|
||||
V = TypeVar('V')
|
||||
S = TypeVar('S')
|
||||
|
||||
# Note: definitions below are different from typeshed, variances are declared
|
||||
# to silence the protocol variance checks. Maybe it is better to use type: ignore?
|
||||
|
||||
@runtime_checkable
|
||||
class Container(Protocol[T_co]):
|
||||
@abstractmethod
|
||||
# Use int because bool isn't in the default test builtins
|
||||
def __contains__(self, arg: object) -> int: pass
|
||||
|
||||
@runtime_checkable
|
||||
class Sized(Protocol):
|
||||
@abstractmethod
|
||||
def __len__(self) -> int: pass
|
||||
|
||||
@runtime_checkable
|
||||
class Iterable(Protocol[T_co]):
|
||||
@abstractmethod
|
||||
def __iter__(self) -> 'Iterator[T_co]': pass
|
||||
|
||||
@runtime_checkable
|
||||
class Iterator(Iterable[T_co], Protocol):
|
||||
@abstractmethod
|
||||
def __next__(self) -> T_co: pass
|
||||
|
||||
class Generator(Iterator[T], Generic[T, U, V]):
|
||||
@abstractmethod
|
||||
def send(self, value: U) -> T: pass
|
||||
|
||||
@abstractmethod
|
||||
def throw(self, typ: Any, val: Any=None, tb: Any=None) -> None: pass
|
||||
|
||||
@abstractmethod
|
||||
def close(self) -> None: pass
|
||||
|
||||
@abstractmethod
|
||||
def __iter__(self) -> 'Generator[T, U, V]': pass
|
||||
|
||||
class AsyncGenerator(AsyncIterator[T], Generic[T, U]):
|
||||
@abstractmethod
|
||||
def __anext__(self) -> Awaitable[T]: pass
|
||||
|
||||
@abstractmethod
|
||||
def asend(self, value: U) -> Awaitable[T]: pass
|
||||
|
||||
@abstractmethod
|
||||
def athrow(self, typ: Any, val: Any=None, tb: Any=None) -> Awaitable[T]: pass
|
||||
|
||||
@abstractmethod
|
||||
def aclose(self) -> Awaitable[T]: pass
|
||||
|
||||
@abstractmethod
|
||||
def __aiter__(self) -> 'AsyncGenerator[T, U]': pass
|
||||
|
||||
@runtime_checkable
|
||||
class Awaitable(Protocol[T]):
|
||||
@abstractmethod
|
||||
def __await__(self) -> Generator[Any, Any, T]: pass
|
||||
|
||||
class AwaitableGenerator(Generator[T, U, V], Awaitable[V], Generic[T, U, V, S], metaclass=ABCMeta):
|
||||
pass
|
||||
|
||||
class Coroutine(Awaitable[V], Generic[T, U, V]):
|
||||
@abstractmethod
|
||||
def send(self, value: U) -> T: pass
|
||||
|
||||
@abstractmethod
|
||||
def throw(self, typ: Any, val: Any=None, tb: Any=None) -> None: pass
|
||||
|
||||
@abstractmethod
|
||||
def close(self) -> None: pass
|
||||
|
||||
@runtime_checkable
|
||||
class AsyncIterable(Protocol[T]):
|
||||
@abstractmethod
|
||||
def __aiter__(self) -> 'AsyncIterator[T]': pass
|
||||
|
||||
@runtime_checkable
|
||||
class AsyncIterator(AsyncIterable[T], Protocol):
|
||||
def __aiter__(self) -> 'AsyncIterator[T]': return self
|
||||
@abstractmethod
|
||||
def __anext__(self) -> Awaitable[T]: pass
|
||||
|
||||
class Sequence(Iterable[T_co], Container[T_co]):
|
||||
@abstractmethod
|
||||
def __getitem__(self, n: Any) -> T_co: pass
|
||||
|
||||
class Mapping(Iterable[T], Generic[T, T_co], metaclass=ABCMeta):
|
||||
def keys(self) -> Iterable[T]: pass # Approximate return type
|
||||
def __getitem__(self, key: T) -> T_co: pass
|
||||
@overload
|
||||
def get(self, k: T) -> Optional[T_co]: pass
|
||||
@overload
|
||||
def get(self, k: T, default: Union[T_co, V]) -> Union[T_co, V]: pass
|
||||
def values(self) -> Iterable[T_co]: pass # Approximate return type
|
||||
def items(self) -> Iterable[Tuple[T, T_co]]: pass # Approximate return type
|
||||
def __len__(self) -> int: ...
|
||||
def __contains__(self, arg: object) -> int: pass
|
||||
|
||||
class MutableMapping(Mapping[T, U], metaclass=ABCMeta):
|
||||
def __setitem__(self, k: T, v: U) -> None: pass
|
||||
|
||||
class SupportsInt(Protocol):
|
||||
def __int__(self) -> int: pass
|
||||
|
||||
class SupportsFloat(Protocol):
|
||||
def __float__(self) -> float: pass
|
||||
|
||||
def runtime_checkable(cls: T) -> T:
|
||||
return cls
|
||||
|
||||
class ContextManager(Generic[T]):
|
||||
def __enter__(self) -> T: pass
|
||||
# Use Any because not all the precise types are in the fixtures.
|
||||
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> Any: pass
|
||||
|
||||
TYPE_CHECKING = 1
|
||||
|
||||
# Fallback type for all typed dicts (does not exist at runtime).
|
||||
class _TypedDict(Mapping[str, object]):
|
||||
# Needed to make this class non-abstract. It is explicitly declared abstract in
|
||||
# typeshed, but we don't want to import abc here, as it would slow down the tests.
|
||||
def __iter__(self) -> Iterator[str]: ...
|
||||
def copy(self: T) -> T: ...
|
||||
# Using NoReturn so that only calls using the plugin hook can go through.
|
||||
def setdefault(self, k: NoReturn, default: object) -> object: ...
|
||||
# Mypy expects that 'default' has a type variable type.
|
||||
def pop(self, k: NoReturn, default: T = ...) -> object: ...
|
||||
def update(self: T, __m: T) -> None: ...
|
||||
def __delitem__(self, k: NoReturn) -> None: ...
|
||||
@@ -0,0 +1,238 @@
|
||||
-- Generate ops related to Any types
|
||||
|
||||
|
||||
[case testCoerceAnyInCallsAndReturn]
|
||||
from typing import Any
|
||||
def f(x: Any) -> Any:
|
||||
return g(x)
|
||||
def g(x: int) -> int:
|
||||
return f(x)
|
||||
[out]
|
||||
def f(x):
|
||||
x :: object
|
||||
r0, r1 :: int
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = unbox(int, x)
|
||||
r1 = g(r0)
|
||||
r2 = box(int, r1)
|
||||
return r2
|
||||
def g(x):
|
||||
x :: int
|
||||
r0, r1 :: object
|
||||
r2 :: int
|
||||
L0:
|
||||
r0 = box(int, x)
|
||||
r1 = f(r0)
|
||||
r2 = unbox(int, r1)
|
||||
return r2
|
||||
|
||||
[case testCoerceAnyInAssignment]
|
||||
from typing import Any, Tuple
|
||||
class C:
|
||||
a: Any
|
||||
n: int
|
||||
def f(a: Any, n: int, c: C) -> None:
|
||||
c.a = n
|
||||
c.n = a
|
||||
a = n
|
||||
n = a
|
||||
a.a = n
|
||||
[out]
|
||||
def f(a, n, c):
|
||||
a :: object
|
||||
n :: int
|
||||
c :: __main__.C
|
||||
r0 :: object
|
||||
r1 :: bool
|
||||
r2 :: int
|
||||
r3 :: bool
|
||||
r4 :: object
|
||||
r5 :: int
|
||||
r6 :: str
|
||||
r7 :: object
|
||||
r8 :: i32
|
||||
r9 :: bit
|
||||
L0:
|
||||
r0 = box(int, n)
|
||||
c.a = r0; r1 = is_error
|
||||
r2 = unbox(int, a)
|
||||
c.n = r2; r3 = is_error
|
||||
r4 = box(int, n)
|
||||
a = r4
|
||||
r5 = unbox(int, a)
|
||||
n = r5
|
||||
r6 = 'a'
|
||||
r7 = box(int, n)
|
||||
r8 = PyObject_SetAttr(a, r6, r7)
|
||||
r9 = r8 >= 0 :: signed
|
||||
return 1
|
||||
|
||||
[case testCoerceAnyInOps]
|
||||
from typing import Any, List
|
||||
def f1(a: Any, n: int) -> None:
|
||||
a + n
|
||||
n + a
|
||||
def f2(a: Any, n: int, l: List[int]) -> None:
|
||||
a[n]
|
||||
l[a]
|
||||
a[n] = n
|
||||
l[a] = n
|
||||
l[n] = a
|
||||
[a, n]
|
||||
def f3(a: Any, n: int) -> None:
|
||||
a += n
|
||||
n += a
|
||||
[out]
|
||||
def f1(a, n):
|
||||
a :: object
|
||||
n :: int
|
||||
r0, r1, r2, r3 :: object
|
||||
L0:
|
||||
r0 = box(int, n)
|
||||
r1 = PyNumber_Add(a, r0)
|
||||
r2 = box(int, n)
|
||||
r3 = PyNumber_Add(r2, a)
|
||||
return 1
|
||||
def f2(a, n, l):
|
||||
a :: object
|
||||
n :: int
|
||||
l :: list
|
||||
r0, r1, r2, r3, r4 :: object
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
r7 :: object
|
||||
r8 :: i32
|
||||
r9, r10 :: bit
|
||||
r11 :: list
|
||||
r12 :: object
|
||||
r13, r14, r15 :: ptr
|
||||
L0:
|
||||
r0 = box(int, n)
|
||||
r1 = PyObject_GetItem(a, r0)
|
||||
r2 = PyObject_GetItem(l, a)
|
||||
r3 = box(int, n)
|
||||
r4 = box(int, n)
|
||||
r5 = PyObject_SetItem(a, r3, r4)
|
||||
r6 = r5 >= 0 :: signed
|
||||
r7 = box(int, n)
|
||||
r8 = PyObject_SetItem(l, a, r7)
|
||||
r9 = r8 >= 0 :: signed
|
||||
r10 = CPyList_SetItem(l, n, a)
|
||||
r11 = PyList_New(2)
|
||||
r12 = box(int, n)
|
||||
r13 = get_element_ptr r11 ob_item :: PyListObject
|
||||
r14 = load_mem r13 :: ptr*
|
||||
set_mem r14, a :: builtins.object*
|
||||
r15 = r14 + WORD_SIZE*1
|
||||
set_mem r15, r12 :: builtins.object*
|
||||
keep_alive r11
|
||||
return 1
|
||||
def f3(a, n):
|
||||
a :: object
|
||||
n :: int
|
||||
r0, r1, r2, r3 :: object
|
||||
r4 :: int
|
||||
L0:
|
||||
r0 = box(int, n)
|
||||
r1 = PyNumber_InPlaceAdd(a, r0)
|
||||
a = r1
|
||||
r2 = box(int, n)
|
||||
r3 = PyNumber_InPlaceAdd(r2, a)
|
||||
r4 = unbox(int, r3)
|
||||
n = r4
|
||||
return 1
|
||||
|
||||
[case testCoerceAnyInConditionalExpr]
|
||||
from typing import Any
|
||||
def f4(a: Any, n: int, b: bool) -> None:
|
||||
a = a if b else n
|
||||
n = n if b else a
|
||||
[out]
|
||||
def f4(a, n, b):
|
||||
a :: object
|
||||
n :: int
|
||||
b :: bool
|
||||
r0, r1, r2, r3 :: object
|
||||
r4 :: int
|
||||
L0:
|
||||
if b goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r0 = a
|
||||
goto L3
|
||||
L2:
|
||||
r1 = box(int, n)
|
||||
r0 = r1
|
||||
L3:
|
||||
a = r0
|
||||
if b goto L4 else goto L5 :: bool
|
||||
L4:
|
||||
r2 = box(int, n)
|
||||
r3 = r2
|
||||
goto L6
|
||||
L5:
|
||||
r3 = a
|
||||
L6:
|
||||
r4 = unbox(int, r3)
|
||||
n = r4
|
||||
return 1
|
||||
|
||||
[case testAbsSpecialization]
|
||||
# Specialization of native classes that implement __abs__ is checked in
|
||||
# irbuild-dunders.test
|
||||
def f() -> None:
|
||||
a = abs(1)
|
||||
b = abs(1.1)
|
||||
[out]
|
||||
def f():
|
||||
r0, r1 :: object
|
||||
r2, a :: int
|
||||
r3, b :: float
|
||||
L0:
|
||||
r0 = object 1
|
||||
r1 = PyNumber_Absolute(r0)
|
||||
r2 = unbox(int, r1)
|
||||
a = r2
|
||||
r3 = fabs(1.1)
|
||||
b = r3
|
||||
return 1
|
||||
|
||||
[case testFunctionBasedOps]
|
||||
def f() -> None:
|
||||
a = divmod(5, 2)
|
||||
def f2() -> int:
|
||||
return pow(2, 5)
|
||||
def f3() -> float:
|
||||
return pow(2, 5, 3)
|
||||
[out]
|
||||
def f():
|
||||
r0, r1, r2 :: object
|
||||
r3, a :: tuple[float, float]
|
||||
L0:
|
||||
r0 = object 5
|
||||
r1 = object 2
|
||||
r2 = PyNumber_Divmod(r0, r1)
|
||||
r3 = unbox(tuple[float, float], r2)
|
||||
a = r3
|
||||
return 1
|
||||
def f2():
|
||||
r0, r1, r2 :: object
|
||||
r3 :: int
|
||||
L0:
|
||||
r0 = object 2
|
||||
r1 = object 5
|
||||
r2 = CPyNumber_Power(r0, r1)
|
||||
r3 = unbox(int, r2)
|
||||
return r3
|
||||
def f3():
|
||||
r0, r1, r2, r3 :: object
|
||||
r4 :: int
|
||||
r5 :: float
|
||||
L0:
|
||||
r0 = object 2
|
||||
r1 = object 5
|
||||
r2 = object 3
|
||||
r3 = PyNumber_Power(r0, r1, r2)
|
||||
r4 = unbox(int, r3)
|
||||
r5 = CPyFloat_FromTagged(r4)
|
||||
return r5
|
||||
3707
venv/lib/python3.12/site-packages/mypyc/test-data/irbuild-basic.test
Normal file
3707
venv/lib/python3.12/site-packages/mypyc/test-data/irbuild-basic.test
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,463 @@
|
||||
[case testBoolToAndFromInt]
|
||||
from mypy_extensions import i64
|
||||
|
||||
def bool_to_int(b: bool) -> int:
|
||||
return b
|
||||
def int_to_bool(n: int) -> bool:
|
||||
return bool(n)
|
||||
def bool_to_i64(b: bool) -> i64:
|
||||
return b
|
||||
def i64_to_bool(n: i64) -> bool:
|
||||
return bool(n)
|
||||
def bit_to_int(n1: i64, n2: i64) -> int:
|
||||
return bool(n1 == n2)
|
||||
def bit_to_i64(n1: i64, n2: i64) -> i64:
|
||||
return bool(n1 == n2)
|
||||
[out]
|
||||
def bool_to_int(b):
|
||||
b, r0 :: bool
|
||||
r1 :: int
|
||||
L0:
|
||||
r0 = b << 1
|
||||
r1 = extend r0: builtins.bool to builtins.int
|
||||
return r1
|
||||
def int_to_bool(n):
|
||||
n :: int
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = n != 0
|
||||
return r0
|
||||
def bool_to_i64(b):
|
||||
b :: bool
|
||||
r0 :: i64
|
||||
L0:
|
||||
r0 = extend b: builtins.bool to i64
|
||||
return r0
|
||||
def i64_to_bool(n):
|
||||
n :: i64
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = n != 0
|
||||
return r0
|
||||
def bit_to_int(n1, n2):
|
||||
n1, n2 :: i64
|
||||
r0 :: bit
|
||||
r1 :: bool
|
||||
r2 :: int
|
||||
L0:
|
||||
r0 = n1 == n2
|
||||
r1 = r0 << 1
|
||||
r2 = extend r1: builtins.bool to builtins.int
|
||||
return r2
|
||||
def bit_to_i64(n1, n2):
|
||||
n1, n2 :: i64
|
||||
r0 :: bit
|
||||
r1 :: i64
|
||||
L0:
|
||||
r0 = n1 == n2
|
||||
r1 = extend r0: bit to i64
|
||||
return r1
|
||||
|
||||
[case testConversionToBool]
|
||||
from typing import List, Optional
|
||||
|
||||
class C: pass
|
||||
class D:
|
||||
def __bool__(self) -> bool:
|
||||
return True
|
||||
|
||||
def list_to_bool(l: List[str]) -> bool:
|
||||
return bool(l)
|
||||
|
||||
def always_truthy_instance_to_bool(o: C) -> bool:
|
||||
return bool(o)
|
||||
|
||||
def instance_to_bool(o: D) -> bool:
|
||||
return bool(o)
|
||||
|
||||
def optional_truthy_to_bool(o: Optional[C]) -> bool:
|
||||
return bool(o)
|
||||
|
||||
def optional_maybe_falsey_to_bool(o: Optional[D]) -> bool:
|
||||
return bool(o)
|
||||
[out]
|
||||
def D.__bool__(self):
|
||||
self :: __main__.D
|
||||
L0:
|
||||
return 1
|
||||
def list_to_bool(l):
|
||||
l :: list
|
||||
r0 :: ptr
|
||||
r1 :: native_int
|
||||
r2 :: short_int
|
||||
r3 :: bit
|
||||
L0:
|
||||
r0 = get_element_ptr l ob_size :: PyVarObject
|
||||
r1 = load_mem r0 :: native_int*
|
||||
keep_alive l
|
||||
r2 = r1 << 1
|
||||
r3 = r2 != 0
|
||||
return r3
|
||||
def always_truthy_instance_to_bool(o):
|
||||
o :: __main__.C
|
||||
r0 :: i32
|
||||
r1 :: bit
|
||||
r2 :: bool
|
||||
L0:
|
||||
r0 = PyObject_IsTrue(o)
|
||||
r1 = r0 >= 0 :: signed
|
||||
r2 = truncate r0: i32 to builtins.bool
|
||||
return r2
|
||||
def instance_to_bool(o):
|
||||
o :: __main__.D
|
||||
r0 :: bool
|
||||
L0:
|
||||
r0 = o.__bool__()
|
||||
return r0
|
||||
def optional_truthy_to_bool(o):
|
||||
o :: union[__main__.C, None]
|
||||
r0 :: object
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = o != r0
|
||||
return r1
|
||||
def optional_maybe_falsey_to_bool(o):
|
||||
o :: union[__main__.D, None]
|
||||
r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: __main__.D
|
||||
r3 :: bool
|
||||
r4 :: bit
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = o != r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r2 = cast(__main__.D, o)
|
||||
r3 = r2.__bool__()
|
||||
r4 = r3
|
||||
goto L3
|
||||
L2:
|
||||
r4 = 0
|
||||
L3:
|
||||
return r4
|
||||
|
||||
[case testBoolComparisons]
|
||||
def eq(x: bool, y: bool) -> bool:
|
||||
return x == y
|
||||
|
||||
def neq(x: bool, y: bool) -> bool:
|
||||
return x != y
|
||||
|
||||
def lt(x: bool, y: bool) -> bool:
|
||||
return x < y
|
||||
|
||||
def le(x: bool, y: bool) -> bool:
|
||||
return x <= y
|
||||
|
||||
def gt(x: bool, y: bool) -> bool:
|
||||
return x > y
|
||||
|
||||
def ge(x: bool, y: bool) -> bool:
|
||||
return x >= y
|
||||
[out]
|
||||
def eq(x, y):
|
||||
x, y :: bool
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = x == y
|
||||
return r0
|
||||
def neq(x, y):
|
||||
x, y :: bool
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = x != y
|
||||
return r0
|
||||
def lt(x, y):
|
||||
x, y :: bool
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = x < y :: signed
|
||||
return r0
|
||||
def le(x, y):
|
||||
x, y :: bool
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = x <= y :: signed
|
||||
return r0
|
||||
def gt(x, y):
|
||||
x, y :: bool
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = x > y :: signed
|
||||
return r0
|
||||
def ge(x, y):
|
||||
x, y :: bool
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = x >= y :: signed
|
||||
return r0
|
||||
|
||||
[case testBoolMixedComparisons1]
|
||||
from mypy_extensions import i64
|
||||
|
||||
def eq1(x: int, y: bool) -> bool:
|
||||
return x == y
|
||||
|
||||
def eq2(x: bool, y: int) -> bool:
|
||||
return x == y
|
||||
|
||||
def neq1(x: i64, y: bool) -> bool:
|
||||
return x != y
|
||||
|
||||
def neq2(x: bool, y: i64) -> bool:
|
||||
return x != y
|
||||
[out]
|
||||
def eq1(x, y):
|
||||
x :: int
|
||||
y, r0 :: bool
|
||||
r1 :: int
|
||||
r2 :: bit
|
||||
L0:
|
||||
r0 = y << 1
|
||||
r1 = extend r0: builtins.bool to builtins.int
|
||||
r2 = x == r1
|
||||
return r2
|
||||
def eq2(x, y):
|
||||
x :: bool
|
||||
y :: int
|
||||
r0 :: bool
|
||||
r1 :: int
|
||||
r2 :: bit
|
||||
L0:
|
||||
r0 = x << 1
|
||||
r1 = extend r0: builtins.bool to builtins.int
|
||||
r2 = r1 == y
|
||||
return r2
|
||||
def neq1(x, y):
|
||||
x :: i64
|
||||
y :: bool
|
||||
r0 :: i64
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = extend y: builtins.bool to i64
|
||||
r1 = x != r0
|
||||
return r1
|
||||
def neq2(x, y):
|
||||
x :: bool
|
||||
y, r0 :: i64
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = extend x: builtins.bool to i64
|
||||
r1 = r0 != y
|
||||
return r1
|
||||
|
||||
[case testBoolMixedComparisons2]
|
||||
from mypy_extensions import i64
|
||||
|
||||
def lt1(x: bool, y: int) -> bool:
|
||||
return x < y
|
||||
|
||||
def lt2(x: int, y: bool) -> bool:
|
||||
return x < y
|
||||
|
||||
def gt1(x: bool, y: i64) -> bool:
|
||||
return x < y
|
||||
|
||||
def gt2(x: i64, y: bool) -> bool:
|
||||
return x < y
|
||||
[out]
|
||||
def lt1(x, y):
|
||||
x :: bool
|
||||
y :: int
|
||||
r0 :: bool
|
||||
r1 :: short_int
|
||||
r2 :: native_int
|
||||
r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6, r7 :: bit
|
||||
r8 :: bool
|
||||
r9 :: bit
|
||||
L0:
|
||||
r0 = x << 1
|
||||
r1 = extend r0: builtins.bool to short_int
|
||||
r2 = r1 & 1
|
||||
r3 = r2 == 0
|
||||
r4 = y & 1
|
||||
r5 = r4 == 0
|
||||
r6 = r3 & r5
|
||||
if r6 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r7 = r1 < y :: signed
|
||||
r8 = r7
|
||||
goto L3
|
||||
L2:
|
||||
r9 = CPyTagged_IsLt_(r1, y)
|
||||
r8 = r9
|
||||
L3:
|
||||
return r8
|
||||
def lt2(x, y):
|
||||
x :: int
|
||||
y, r0 :: bool
|
||||
r1 :: short_int
|
||||
r2 :: native_int
|
||||
r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6, r7 :: bit
|
||||
r8 :: bool
|
||||
r9 :: bit
|
||||
L0:
|
||||
r0 = y << 1
|
||||
r1 = extend r0: builtins.bool to short_int
|
||||
r2 = x & 1
|
||||
r3 = r2 == 0
|
||||
r4 = r1 & 1
|
||||
r5 = r4 == 0
|
||||
r6 = r3 & r5
|
||||
if r6 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r7 = x < r1 :: signed
|
||||
r8 = r7
|
||||
goto L3
|
||||
L2:
|
||||
r9 = CPyTagged_IsLt_(x, r1)
|
||||
r8 = r9
|
||||
L3:
|
||||
return r8
|
||||
def gt1(x, y):
|
||||
x :: bool
|
||||
y, r0 :: i64
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = extend x: builtins.bool to i64
|
||||
r1 = r0 < y :: signed
|
||||
return r1
|
||||
def gt2(x, y):
|
||||
x :: i64
|
||||
y :: bool
|
||||
r0 :: i64
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = extend y: builtins.bool to i64
|
||||
r1 = x < r0 :: signed
|
||||
return r1
|
||||
|
||||
[case testBoolBitwise]
|
||||
from mypy_extensions import i64
|
||||
def bitand(x: bool, y: bool) -> bool:
|
||||
b = x & y
|
||||
return b
|
||||
def bitor(x: bool, y: bool) -> bool:
|
||||
b = x | y
|
||||
return b
|
||||
def bitxor(x: bool, y: bool) -> bool:
|
||||
b = x ^ y
|
||||
return b
|
||||
def invert(x: bool) -> int:
|
||||
return ~x
|
||||
def mixed_bitand(x: i64, y: bool) -> i64:
|
||||
return x & y
|
||||
[out]
|
||||
def bitand(x, y):
|
||||
x, y, r0, b :: bool
|
||||
L0:
|
||||
r0 = x & y
|
||||
b = r0
|
||||
return b
|
||||
def bitor(x, y):
|
||||
x, y, r0, b :: bool
|
||||
L0:
|
||||
r0 = x | y
|
||||
b = r0
|
||||
return b
|
||||
def bitxor(x, y):
|
||||
x, y, r0, b :: bool
|
||||
L0:
|
||||
r0 = x ^ y
|
||||
b = r0
|
||||
return b
|
||||
def invert(x):
|
||||
x, r0 :: bool
|
||||
r1, r2 :: int
|
||||
L0:
|
||||
r0 = x << 1
|
||||
r1 = extend r0: builtins.bool to builtins.int
|
||||
r2 = CPyTagged_Invert(r1)
|
||||
return r2
|
||||
def mixed_bitand(x, y):
|
||||
x :: i64
|
||||
y :: bool
|
||||
r0, r1 :: i64
|
||||
L0:
|
||||
r0 = extend y: builtins.bool to i64
|
||||
r1 = x & r0
|
||||
return r1
|
||||
|
||||
[case testBoolArithmetic]
|
||||
def add(x: bool, y: bool) -> int:
|
||||
z = x + y
|
||||
return z
|
||||
def mixed(b: bool, n: int) -> int:
|
||||
z = b + n
|
||||
z -= b
|
||||
z = z * b
|
||||
return z
|
||||
def negate(b: bool) -> int:
|
||||
return -b
|
||||
def unary_plus(b: bool) -> int:
|
||||
x = +b
|
||||
return x
|
||||
[out]
|
||||
def add(x, y):
|
||||
x, y, r0 :: bool
|
||||
r1 :: int
|
||||
r2 :: bool
|
||||
r3, r4, z :: int
|
||||
L0:
|
||||
r0 = x << 1
|
||||
r1 = extend r0: builtins.bool to builtins.int
|
||||
r2 = y << 1
|
||||
r3 = extend r2: builtins.bool to builtins.int
|
||||
r4 = CPyTagged_Add(r1, r3)
|
||||
z = r4
|
||||
return z
|
||||
def mixed(b, n):
|
||||
b :: bool
|
||||
n :: int
|
||||
r0 :: bool
|
||||
r1, r2, z :: int
|
||||
r3 :: bool
|
||||
r4, r5 :: int
|
||||
r6 :: bool
|
||||
r7, r8 :: int
|
||||
L0:
|
||||
r0 = b << 1
|
||||
r1 = extend r0: builtins.bool to builtins.int
|
||||
r2 = CPyTagged_Add(r1, n)
|
||||
z = r2
|
||||
r3 = b << 1
|
||||
r4 = extend r3: builtins.bool to builtins.int
|
||||
r5 = CPyTagged_Subtract(z, r4)
|
||||
z = r5
|
||||
r6 = b << 1
|
||||
r7 = extend r6: builtins.bool to builtins.int
|
||||
r8 = CPyTagged_Multiply(z, r7)
|
||||
z = r8
|
||||
return z
|
||||
def negate(b):
|
||||
b, r0 :: bool
|
||||
r1, r2 :: int
|
||||
L0:
|
||||
r0 = b << 1
|
||||
r1 = extend r0: builtins.bool to builtins.int
|
||||
r2 = CPyTagged_Negate(r1)
|
||||
return r2
|
||||
def unary_plus(b):
|
||||
b, r0 :: bool
|
||||
r1, x :: int
|
||||
L0:
|
||||
r0 = b << 1
|
||||
r1 = extend r0: builtins.bool to builtins.int
|
||||
x = r1
|
||||
return x
|
||||
@@ -0,0 +1,184 @@
|
||||
[case testBytesBasics]
|
||||
def f(num: int, l: list, d: dict, s: str) -> None:
|
||||
b1 = bytes()
|
||||
b2 = bytes(num)
|
||||
b3 = bytes(l)
|
||||
b4 = bytes(d)
|
||||
b5 = bytes(s)
|
||||
[out]
|
||||
def f(num, l, d, s):
|
||||
num :: int
|
||||
l :: list
|
||||
d :: dict
|
||||
s :: str
|
||||
r0, r1 :: object
|
||||
r2, b1 :: bytes
|
||||
r3, r4, r5 :: object
|
||||
r6, b2, r7, b3, r8, b4, r9, b5 :: bytes
|
||||
L0:
|
||||
r0 = load_address PyBytes_Type
|
||||
r1 = PyObject_CallFunctionObjArgs(r0, 0)
|
||||
r2 = cast(bytes, r1)
|
||||
b1 = r2
|
||||
r3 = load_address PyBytes_Type
|
||||
r4 = box(int, num)
|
||||
r5 = PyObject_CallFunctionObjArgs(r3, r4, 0)
|
||||
r6 = cast(bytes, r5)
|
||||
b2 = r6
|
||||
r7 = PyBytes_FromObject(l)
|
||||
b3 = r7
|
||||
r8 = PyBytes_FromObject(d)
|
||||
b4 = r8
|
||||
r9 = PyBytes_FromObject(s)
|
||||
b5 = r9
|
||||
return 1
|
||||
|
||||
[case testBytearrayBasics]
|
||||
def f(s: str, num: int) -> None:
|
||||
a = bytearray()
|
||||
b = bytearray(s)
|
||||
c = bytearray(num)
|
||||
[out]
|
||||
def f(s, num):
|
||||
s :: str
|
||||
num :: int
|
||||
r0 :: object
|
||||
r1 :: str
|
||||
r2, r3, a :: object
|
||||
r4 :: bytes
|
||||
b, r5 :: object
|
||||
r6 :: bytes
|
||||
c :: object
|
||||
L0:
|
||||
r0 = builtins :: module
|
||||
r1 = 'bytearray'
|
||||
r2 = CPyObject_GetAttr(r0, r1)
|
||||
r3 = PyObject_CallFunctionObjArgs(r2, 0)
|
||||
a = r3
|
||||
r4 = PyByteArray_FromObject(s)
|
||||
b = r4
|
||||
r5 = box(int, num)
|
||||
r6 = PyByteArray_FromObject(r5)
|
||||
c = r6
|
||||
return 1
|
||||
|
||||
[case testBytesEquality]
|
||||
def eq(x: bytes, y: bytes) -> bool:
|
||||
return x == y
|
||||
|
||||
def neq(x: bytes, y: bytes) -> bool:
|
||||
return x != y
|
||||
[out]
|
||||
def eq(x, y):
|
||||
x, y :: bytes
|
||||
r0 :: i32
|
||||
r1, r2 :: bit
|
||||
L0:
|
||||
r0 = CPyBytes_Compare(x, y)
|
||||
r1 = r0 >= 0 :: signed
|
||||
r2 = r0 == 1
|
||||
return r2
|
||||
def neq(x, y):
|
||||
x, y :: bytes
|
||||
r0 :: i32
|
||||
r1, r2 :: bit
|
||||
L0:
|
||||
r0 = CPyBytes_Compare(x, y)
|
||||
r1 = r0 >= 0 :: signed
|
||||
r2 = r0 != 1
|
||||
return r2
|
||||
|
||||
[case testBytesSlicing]
|
||||
def f(a: bytes, start: int, end: int) -> bytes:
|
||||
return a[start:end]
|
||||
[out]
|
||||
def f(a, start, end):
|
||||
a :: bytes
|
||||
start, end :: int
|
||||
r0 :: bytes
|
||||
L0:
|
||||
r0 = CPyBytes_GetSlice(a, start, end)
|
||||
return r0
|
||||
|
||||
[case testBytesIndex]
|
||||
def f(a: bytes, i: int) -> int:
|
||||
return a[i]
|
||||
[out]
|
||||
def f(a, i):
|
||||
a :: bytes
|
||||
i, r0 :: int
|
||||
L0:
|
||||
r0 = CPyBytes_GetItem(a, i)
|
||||
return r0
|
||||
|
||||
[case testBytesConcat]
|
||||
def f(a: bytes, b: bytes) -> bytes:
|
||||
return a + b
|
||||
[out]
|
||||
def f(a, b):
|
||||
a, b, r0 :: bytes
|
||||
L0:
|
||||
r0 = CPyBytes_Concat(a, b)
|
||||
return r0
|
||||
|
||||
[case testBytesJoin]
|
||||
from typing import List
|
||||
def f(b: List[bytes]) -> bytes:
|
||||
return b" ".join(b)
|
||||
[out]
|
||||
def f(b):
|
||||
b :: list
|
||||
r0, r1 :: bytes
|
||||
L0:
|
||||
r0 = b' '
|
||||
r1 = CPyBytes_Join(r0, b)
|
||||
return r1
|
||||
|
||||
[case testBytesLen]
|
||||
def f(b: bytes) -> int:
|
||||
return len(b)
|
||||
[out]
|
||||
def f(b):
|
||||
b :: bytes
|
||||
r0 :: ptr
|
||||
r1 :: native_int
|
||||
r2 :: short_int
|
||||
L0:
|
||||
r0 = get_element_ptr b ob_size :: PyVarObject
|
||||
r1 = load_mem r0 :: native_int*
|
||||
keep_alive b
|
||||
r2 = r1 << 1
|
||||
return r2
|
||||
|
||||
[case testBytesFormatting]
|
||||
def f(var: bytes, num: int) -> None:
|
||||
b1 = b'aaaa%bbbbb%s' % (var, var)
|
||||
b2 = b'aaaa%bbbbb%s%d' % (var, var, num)
|
||||
b3 = b'%b' % var
|
||||
b4 = b'%ssss' % var
|
||||
[typing fixtures/typing-full.pyi]
|
||||
[out]
|
||||
def f(var, num):
|
||||
var :: bytes
|
||||
num :: int
|
||||
r0, r1, r2, b1, r3 :: bytes
|
||||
r4 :: tuple[bytes, bytes, int]
|
||||
r5, r6 :: object
|
||||
r7, b2, r8, b3, r9, r10, b4 :: bytes
|
||||
L0:
|
||||
r0 = b'aaaa'
|
||||
r1 = b'bbbb'
|
||||
r2 = CPyBytes_Build(4, r0, var, r1, var)
|
||||
b1 = r2
|
||||
r3 = b'aaaa%bbbbb%s%d'
|
||||
r4 = (var, var, num)
|
||||
r5 = box(tuple[bytes, bytes, int], r4)
|
||||
r6 = PyNumber_Remainder(r3, r5)
|
||||
r7 = cast(bytes, r6)
|
||||
b2 = r7
|
||||
r8 = CPyBytes_Build(1, var)
|
||||
b3 = r8
|
||||
r9 = b'sss'
|
||||
r10 = CPyBytes_Build(2, var, r9)
|
||||
b4 = r10
|
||||
return 1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,480 @@
|
||||
[case testIntConstantFolding]
|
||||
def bin_ops() -> None:
|
||||
add = 15 + 47
|
||||
add_mul = (2 + 3) * 5
|
||||
sub = 7 - 11
|
||||
div = 3 / 2
|
||||
bit_and = 6 & 10
|
||||
bit_or = 6 | 10
|
||||
bit_xor = 6 ^ 10
|
||||
lshift = 5 << 2
|
||||
rshift = 13 >> 2
|
||||
lshift0 = 5 << 0
|
||||
rshift0 = 13 >> 0
|
||||
def unary_ops() -> None:
|
||||
neg1 = -5
|
||||
neg2 = --1
|
||||
neg3 = -0
|
||||
pos = +5
|
||||
inverted1 = ~0
|
||||
inverted2 = ~5
|
||||
inverted3 = ~3
|
||||
def pow() -> None:
|
||||
p0 = 3**0
|
||||
p1 = 3**5
|
||||
p2 = (-5)**3
|
||||
p3 = 0**0
|
||||
[out]
|
||||
def bin_ops():
|
||||
add, add_mul, sub :: int
|
||||
div :: float
|
||||
bit_and, bit_or, bit_xor, lshift, rshift, lshift0, rshift0 :: int
|
||||
L0:
|
||||
add = 124
|
||||
add_mul = 50
|
||||
sub = -8
|
||||
div = 1.5
|
||||
bit_and = 4
|
||||
bit_or = 28
|
||||
bit_xor = 24
|
||||
lshift = 40
|
||||
rshift = 6
|
||||
lshift0 = 10
|
||||
rshift0 = 26
|
||||
return 1
|
||||
def unary_ops():
|
||||
neg1, neg2, neg3, pos, inverted1, inverted2, inverted3 :: int
|
||||
L0:
|
||||
neg1 = -10
|
||||
neg2 = 2
|
||||
neg3 = 0
|
||||
pos = 10
|
||||
inverted1 = -2
|
||||
inverted2 = -12
|
||||
inverted3 = -8
|
||||
return 1
|
||||
def pow():
|
||||
p0, p1, p2, p3 :: int
|
||||
L0:
|
||||
p0 = 2
|
||||
p1 = 486
|
||||
p2 = -250
|
||||
p3 = 2
|
||||
return 1
|
||||
|
||||
[case testIntConstantFoldingDivMod]
|
||||
def div() -> None:
|
||||
div1 = 25 // 5
|
||||
div2 = 24 // 5
|
||||
div3 = 29 // 5
|
||||
div4 = 30 // 5
|
||||
div_zero = 0 // 5
|
||||
neg1 = -1 // 3
|
||||
neg2 = -2 // 3
|
||||
neg3 = -3 // 3
|
||||
neg4 = -4 // 3
|
||||
neg_neg = -765467 // -234
|
||||
pos_neg = 983745 // -7864
|
||||
def mod() -> None:
|
||||
mod1 = 25 % 5
|
||||
mod2 = 24 % 5
|
||||
mod3 = 29 % 5
|
||||
mod4 = 30 % 5
|
||||
mod_zero = 0 % 5
|
||||
neg1 = -4 % 3
|
||||
neg2 = -5 % 3
|
||||
neg3 = -6 % 3
|
||||
neg4 = -7 % 3
|
||||
neg_neg = -765467 % -234
|
||||
pos_neg = 983745 % -7864
|
||||
[out]
|
||||
def div():
|
||||
div1, div2, div3, div4, div_zero, neg1, neg2, neg3, neg4, neg_neg, pos_neg :: int
|
||||
L0:
|
||||
div1 = 10
|
||||
div2 = 8
|
||||
div3 = 10
|
||||
div4 = 12
|
||||
div_zero = 0
|
||||
neg1 = -2
|
||||
neg2 = -2
|
||||
neg3 = -2
|
||||
neg4 = -4
|
||||
neg_neg = 6542
|
||||
pos_neg = -252
|
||||
return 1
|
||||
def mod():
|
||||
mod1, mod2, mod3, mod4, mod_zero, neg1, neg2, neg3, neg4, neg_neg, pos_neg :: int
|
||||
L0:
|
||||
mod1 = 0
|
||||
mod2 = 8
|
||||
mod3 = 8
|
||||
mod4 = 0
|
||||
mod_zero = 0
|
||||
neg1 = 4
|
||||
neg2 = 2
|
||||
neg3 = 0
|
||||
neg4 = 4
|
||||
neg_neg = -106
|
||||
pos_neg = -14238
|
||||
return 1
|
||||
|
||||
[case testIntConstantFoldingUnsupportedCases]
|
||||
def error_cases() -> None:
|
||||
div_by_zero = 5 / 0
|
||||
floor_div_by_zero = 5 // 0
|
||||
mod_by_zero = 5 % 0
|
||||
lshift_neg = 6 << -1
|
||||
rshift_neg = 7 >> -1
|
||||
def unsupported_pow() -> None:
|
||||
p = 3 ** (-1)
|
||||
[out]
|
||||
def error_cases():
|
||||
r0, div_by_zero :: float
|
||||
r1, floor_div_by_zero, r2, mod_by_zero, r3, lshift_neg, r4, rshift_neg :: int
|
||||
L0:
|
||||
r0 = CPyTagged_TrueDivide(10, 0)
|
||||
div_by_zero = r0
|
||||
r1 = CPyTagged_FloorDivide(10, 0)
|
||||
floor_div_by_zero = r1
|
||||
r2 = CPyTagged_Remainder(10, 0)
|
||||
mod_by_zero = r2
|
||||
r3 = CPyTagged_Lshift(12, -2)
|
||||
lshift_neg = r3
|
||||
r4 = CPyTagged_Rshift(14, -2)
|
||||
rshift_neg = r4
|
||||
return 1
|
||||
def unsupported_pow():
|
||||
r0, r1, r2 :: object
|
||||
r3, p :: float
|
||||
L0:
|
||||
r0 = object 3
|
||||
r1 = object -1
|
||||
r2 = CPyNumber_Power(r0, r1)
|
||||
r3 = unbox(float, r2)
|
||||
p = r3
|
||||
return 1
|
||||
|
||||
[case testIntConstantFoldingBigIntResult_64bit]
|
||||
def long_and_short() -> None:
|
||||
# The smallest and largest representable short integers
|
||||
short1 = 0x3ffffffffffffff0 + 0xf # (1 << 62) - 1
|
||||
short2 = -0x3fffffffffffffff - 1 # -(1 << 62)
|
||||
short3 = -0x4000000000000000
|
||||
# Smallest big integers by absolute value
|
||||
big1 = 1 << 62
|
||||
big2 = 0x4000000000000000 # 1 << 62
|
||||
big3 = -(1 << 62) - 1
|
||||
big4 = -0x4000000000000001 # -(1 << 62) - 1
|
||||
big5 = 123**41
|
||||
[out]
|
||||
def long_and_short():
|
||||
short1, short2, short3, r0, big1, r1, big2, r2, big3, r3, big4, r4, big5 :: int
|
||||
L0:
|
||||
short1 = 9223372036854775806
|
||||
short2 = -9223372036854775808
|
||||
short3 = -9223372036854775808
|
||||
r0 = object 4611686018427387904
|
||||
big1 = r0
|
||||
r1 = object 4611686018427387904
|
||||
big2 = r1
|
||||
r2 = object -4611686018427387905
|
||||
big3 = r2
|
||||
r3 = object -4611686018427387905
|
||||
big4 = r3
|
||||
r4 = object 48541095000524544750127162673405880068636916264012200797813591925035550682238127143323
|
||||
big5 = r4
|
||||
return 1
|
||||
|
||||
[case testIntConstantFoldingFinal]
|
||||
from typing_extensions import Final
|
||||
X: Final = 5
|
||||
Y: Final = 2 + 4
|
||||
|
||||
def f() -> None:
|
||||
a = X + 1
|
||||
a = Y + 1
|
||||
[out]
|
||||
def f():
|
||||
a :: int
|
||||
L0:
|
||||
a = 12
|
||||
a = 14
|
||||
return 1
|
||||
|
||||
[case testIntConstantFoldingClassFinal]
|
||||
from typing_extensions import Final
|
||||
class C:
|
||||
X: Final = 5
|
||||
|
||||
def f() -> None:
|
||||
a = C.X + 1
|
||||
[out]
|
||||
def C.__mypyc_defaults_setup(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.C
|
||||
L0:
|
||||
__mypyc_self__.X = 10
|
||||
return 1
|
||||
def f():
|
||||
a :: int
|
||||
L0:
|
||||
a = 12
|
||||
return 1
|
||||
|
||||
[case testFloatConstantFolding]
|
||||
from typing_extensions import Final
|
||||
|
||||
N: Final = 1.5
|
||||
N2: Final = 1.5 * 2
|
||||
|
||||
def bin_ops() -> None:
|
||||
add = 0.5 + 0.5
|
||||
add_mul = (1.5 + 3.5) * 5.0
|
||||
sub = 7.0 - 7.5
|
||||
div = 3.0 / 2.0
|
||||
floor_div = 3.0 // 2.0
|
||||
def bin_ops_neg() -> None:
|
||||
add = 0.5 + -0.5
|
||||
add_mul = (-1.5 + 3.5) * -5.0
|
||||
add_mul2 = (1.5 + -3.5) * -5.0
|
||||
sub = 7.0 - -7.5
|
||||
div = 3.0 / -2.0
|
||||
floor_div = 3.0 // -2.0
|
||||
def unary_ops() -> None:
|
||||
neg1 = -5.5
|
||||
neg2 = --1.5
|
||||
neg3 = -0.0
|
||||
pos = +5.5
|
||||
def pow() -> None:
|
||||
p0 = 16.0**0
|
||||
p1 = 16.0**0.5
|
||||
p2 = (-5.0)**3
|
||||
p3 = 16.0**(-0)
|
||||
p4 = 16.0**(-0.5)
|
||||
p5 = (-2.0)**(-1)
|
||||
def error_cases() -> None:
|
||||
div = 2.0 / 0.0
|
||||
floor_div = 2.0 // 0.0
|
||||
power_imag = (-2.0)**0.5
|
||||
power_imag2 = (-2.0)**(-0.5)
|
||||
power_overflow = 2.0**10000.0
|
||||
def final_floats() -> None:
|
||||
add1 = N + 1.2
|
||||
add2 = N + N2
|
||||
add3 = -1.2 + N2
|
||||
[out]
|
||||
def bin_ops():
|
||||
add, add_mul, sub, div, floor_div :: float
|
||||
L0:
|
||||
add = 1.0
|
||||
add_mul = 25.0
|
||||
sub = -0.5
|
||||
div = 1.5
|
||||
floor_div = 1.0
|
||||
return 1
|
||||
def bin_ops_neg():
|
||||
add, add_mul, add_mul2, sub, div, floor_div :: float
|
||||
L0:
|
||||
add = 0.0
|
||||
add_mul = -10.0
|
||||
add_mul2 = 10.0
|
||||
sub = 14.5
|
||||
div = -1.5
|
||||
floor_div = -2.0
|
||||
return 1
|
||||
def unary_ops():
|
||||
neg1, neg2, neg3, pos :: float
|
||||
L0:
|
||||
neg1 = -5.5
|
||||
neg2 = 1.5
|
||||
neg3 = -0.0
|
||||
pos = 5.5
|
||||
return 1
|
||||
def pow():
|
||||
p0, p1, p2, p3, p4, p5 :: float
|
||||
L0:
|
||||
p0 = 1.0
|
||||
p1 = 4.0
|
||||
p2 = -125.0
|
||||
p3 = 1.0
|
||||
p4 = 0.25
|
||||
p5 = -0.5
|
||||
return 1
|
||||
def error_cases():
|
||||
r0 :: bit
|
||||
r1 :: bool
|
||||
r2, div, r3, floor_div :: float
|
||||
r4, r5, r6 :: object
|
||||
r7, power_imag :: float
|
||||
r8, r9, r10 :: object
|
||||
r11, power_imag2 :: float
|
||||
r12, r13, r14 :: object
|
||||
r15, power_overflow :: float
|
||||
L0:
|
||||
r0 = 0.0 == 0.0
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r1 = raise ZeroDivisionError('float division by zero')
|
||||
unreachable
|
||||
L2:
|
||||
r2 = 2.0 / 0.0
|
||||
div = r2
|
||||
r3 = CPyFloat_FloorDivide(2.0, 0.0)
|
||||
floor_div = r3
|
||||
r4 = box(float, -2.0)
|
||||
r5 = box(float, 0.5)
|
||||
r6 = CPyNumber_Power(r4, r5)
|
||||
r7 = unbox(float, r6)
|
||||
power_imag = r7
|
||||
r8 = box(float, -2.0)
|
||||
r9 = box(float, -0.5)
|
||||
r10 = CPyNumber_Power(r8, r9)
|
||||
r11 = unbox(float, r10)
|
||||
power_imag2 = r11
|
||||
r12 = box(float, 2.0)
|
||||
r13 = box(float, 10000.0)
|
||||
r14 = CPyNumber_Power(r12, r13)
|
||||
r15 = unbox(float, r14)
|
||||
power_overflow = r15
|
||||
return 1
|
||||
def final_floats():
|
||||
add1, add2, add3 :: float
|
||||
L0:
|
||||
add1 = 2.7
|
||||
add2 = 4.5
|
||||
add3 = 1.8
|
||||
return 1
|
||||
|
||||
[case testMixedFloatIntConstantFolding]
|
||||
def bin_ops() -> None:
|
||||
add = 1 + 0.5
|
||||
sub = 1 - 0.5
|
||||
mul = 0.5 * 5
|
||||
div = 5 / 0.5
|
||||
floor_div = 9.5 // 5
|
||||
def error_cases() -> None:
|
||||
div = 2.0 / 0
|
||||
floor_div = 2.0 // 0
|
||||
power_overflow = 2.0**10000
|
||||
[out]
|
||||
def bin_ops():
|
||||
add, sub, mul, div, floor_div :: float
|
||||
L0:
|
||||
add = 1.5
|
||||
sub = 0.5
|
||||
mul = 2.5
|
||||
div = 10.0
|
||||
floor_div = 1.0
|
||||
return 1
|
||||
def error_cases():
|
||||
r0 :: bit
|
||||
r1 :: bool
|
||||
r2, div, r3, floor_div :: float
|
||||
r4, r5, r6 :: object
|
||||
r7, power_overflow :: float
|
||||
L0:
|
||||
r0 = 0.0 == 0.0
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r1 = raise ZeroDivisionError('float division by zero')
|
||||
unreachable
|
||||
L2:
|
||||
r2 = 2.0 / 0.0
|
||||
div = r2
|
||||
r3 = CPyFloat_FloorDivide(2.0, 0.0)
|
||||
floor_div = r3
|
||||
r4 = box(float, 2.0)
|
||||
r5 = box(float, 10000.0)
|
||||
r6 = CPyNumber_Power(r4, r5)
|
||||
r7 = unbox(float, r6)
|
||||
power_overflow = r7
|
||||
return 1
|
||||
|
||||
[case testStrConstantFolding]
|
||||
from typing_extensions import Final
|
||||
|
||||
S: Final = 'z'
|
||||
N: Final = 2
|
||||
|
||||
def f() -> None:
|
||||
x = 'foo' + 'bar'
|
||||
y = 'x' + 'y' + S
|
||||
mul = "foobar" * 2
|
||||
mul2 = N * "foobar"
|
||||
[out]
|
||||
def f():
|
||||
r0, x, r1, y, r2, mul, r3, mul2 :: str
|
||||
L0:
|
||||
r0 = 'foobar'
|
||||
x = r0
|
||||
r1 = 'xyz'
|
||||
y = r1
|
||||
r2 = 'foobarfoobar'
|
||||
mul = r2
|
||||
r3 = 'foobarfoobar'
|
||||
mul2 = r3
|
||||
return 1
|
||||
|
||||
[case testBytesConstantFolding]
|
||||
from typing_extensions import Final
|
||||
|
||||
N: Final = 2
|
||||
|
||||
def f() -> None:
|
||||
# Unfortunately, mypy doesn't store the bytes value of final refs.
|
||||
x = b'foo' + b'bar'
|
||||
mul = b"foobar" * 2
|
||||
mul2 = N * b"foobar"
|
||||
[out]
|
||||
def f():
|
||||
r0, x, r1, mul, r2, mul2 :: bytes
|
||||
L0:
|
||||
r0 = b'foobar'
|
||||
x = r0
|
||||
r1 = b'foobarfoobar'
|
||||
mul = r1
|
||||
r2 = b'foobarfoobar'
|
||||
mul2 = r2
|
||||
return 1
|
||||
|
||||
[case testComplexConstantFolding]
|
||||
from typing_extensions import Final
|
||||
|
||||
N: Final = 1
|
||||
FLOAT_N: Final = 1.5
|
||||
|
||||
def integral() -> None:
|
||||
pos = 1+2j
|
||||
pos_2 = 2j+N
|
||||
neg = 1-2j
|
||||
neg_2 = 2j-N
|
||||
def floating() -> None:
|
||||
pos = 1.5+2j
|
||||
pos_2 = 2j+FLOAT_N
|
||||
neg = 1.5-2j
|
||||
neg_2 = 2j-FLOAT_N
|
||||
[out]
|
||||
def integral():
|
||||
r0, pos, r1, pos_2, r2, neg, r3, neg_2 :: object
|
||||
L0:
|
||||
r0 = (1+2j)
|
||||
pos = r0
|
||||
r1 = (1+2j)
|
||||
pos_2 = r1
|
||||
r2 = (1-2j)
|
||||
neg = r2
|
||||
r3 = (-1+2j)
|
||||
neg_2 = r3
|
||||
return 1
|
||||
def floating():
|
||||
r0, pos, r1, pos_2, r2, neg, r3, neg_2 :: object
|
||||
L0:
|
||||
r0 = (1.5+2j)
|
||||
pos = r0
|
||||
r1 = (1.5+2j)
|
||||
pos_2 = r1
|
||||
r2 = (1.5-2j)
|
||||
neg = r2
|
||||
r3 = (-1.5+2j)
|
||||
neg_2 = r3
|
||||
return 1
|
||||
@@ -0,0 +1,585 @@
|
||||
[case testDictGet]
|
||||
from typing import Dict
|
||||
def f(d: Dict[int, bool]) -> bool:
|
||||
return d[0]
|
||||
[out]
|
||||
def f(d):
|
||||
d :: dict
|
||||
r0, r1 :: object
|
||||
r2 :: bool
|
||||
L0:
|
||||
r0 = object 0
|
||||
r1 = CPyDict_GetItem(d, r0)
|
||||
r2 = unbox(bool, r1)
|
||||
return r2
|
||||
|
||||
[case testDictSet]
|
||||
from typing import Dict
|
||||
def f(d: Dict[int, bool]) -> None:
|
||||
d[0] = False
|
||||
[out]
|
||||
def f(d):
|
||||
d :: dict
|
||||
r0, r1 :: object
|
||||
r2 :: i32
|
||||
r3 :: bit
|
||||
L0:
|
||||
r0 = object 0
|
||||
r1 = box(bool, 0)
|
||||
r2 = CPyDict_SetItem(d, r0, r1)
|
||||
r3 = r2 >= 0 :: signed
|
||||
return 1
|
||||
|
||||
[case testNewEmptyDict]
|
||||
from typing import Dict
|
||||
def f() -> None:
|
||||
d = {} # type: Dict[bool, int]
|
||||
[out]
|
||||
def f():
|
||||
r0, d :: dict
|
||||
L0:
|
||||
r0 = PyDict_New()
|
||||
d = r0
|
||||
return 1
|
||||
|
||||
[case testNewEmptyDictViaFunc]
|
||||
from typing import Dict
|
||||
def f() -> None:
|
||||
d: Dict[bool, int] = dict()
|
||||
|
||||
[out]
|
||||
def f():
|
||||
r0, d :: dict
|
||||
L0:
|
||||
r0 = PyDict_New()
|
||||
d = r0
|
||||
return 1
|
||||
|
||||
[case testNewDictWithValues]
|
||||
def f(x: object) -> None:
|
||||
d = {1: 2, '': x}
|
||||
[out]
|
||||
def f(x):
|
||||
x :: object
|
||||
r0 :: str
|
||||
r1, r2 :: object
|
||||
r3, d :: dict
|
||||
L0:
|
||||
r0 = ''
|
||||
r1 = object 1
|
||||
r2 = object 2
|
||||
r3 = CPyDict_Build(2, r1, r2, r0, x)
|
||||
d = r3
|
||||
return 1
|
||||
|
||||
[case testInDict]
|
||||
from typing import Dict
|
||||
def f(d: Dict[int, int]) -> bool:
|
||||
if 4 in d:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
[out]
|
||||
def f(d):
|
||||
d :: dict
|
||||
r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3 :: bool
|
||||
L0:
|
||||
r0 = object 4
|
||||
r1 = PyDict_Contains(d, r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
if r3 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return 1
|
||||
L2:
|
||||
return 0
|
||||
L3:
|
||||
unreachable
|
||||
|
||||
[case testNotInDict]
|
||||
from typing import Dict
|
||||
def f(d: Dict[int, int]) -> bool:
|
||||
if 4 not in d:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
[out]
|
||||
def f(d):
|
||||
d :: dict
|
||||
r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3, r4 :: bool
|
||||
L0:
|
||||
r0 = object 4
|
||||
r1 = PyDict_Contains(d, r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
r4 = r3 ^ 1
|
||||
if r4 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return 1
|
||||
L2:
|
||||
return 0
|
||||
L3:
|
||||
unreachable
|
||||
|
||||
[case testDictUpdate]
|
||||
from typing import Dict
|
||||
def f(a: Dict[int, int], b: Dict[int, int]) -> None:
|
||||
a.update(b)
|
||||
[out]
|
||||
def f(a, b):
|
||||
a, b :: dict
|
||||
r0 :: i32
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = CPyDict_Update(a, b)
|
||||
r1 = r0 >= 0 :: signed
|
||||
return 1
|
||||
|
||||
[case testDictKeyLvalue]
|
||||
from typing import Dict
|
||||
def increment(d: Dict[str, int]) -> Dict[str, int]:
|
||||
for k in d:
|
||||
d[k] += 1
|
||||
return d
|
||||
[out]
|
||||
def increment(d):
|
||||
d :: dict
|
||||
r0 :: short_int
|
||||
r1 :: native_int
|
||||
r2 :: short_int
|
||||
r3 :: object
|
||||
r4 :: tuple[bool, short_int, object]
|
||||
r5 :: short_int
|
||||
r6 :: bool
|
||||
r7 :: object
|
||||
r8, k :: str
|
||||
r9, r10, r11 :: object
|
||||
r12 :: i32
|
||||
r13, r14, r15 :: bit
|
||||
L0:
|
||||
r0 = 0
|
||||
r1 = PyDict_Size(d)
|
||||
r2 = r1 << 1
|
||||
r3 = CPyDict_GetKeysIter(d)
|
||||
L1:
|
||||
r4 = CPyDict_NextKey(r3, r0)
|
||||
r5 = r4[1]
|
||||
r0 = r5
|
||||
r6 = r4[0]
|
||||
if r6 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r7 = r4[2]
|
||||
r8 = cast(str, r7)
|
||||
k = r8
|
||||
r9 = CPyDict_GetItem(d, k)
|
||||
r10 = object 1
|
||||
r11 = PyNumber_InPlaceAdd(r9, r10)
|
||||
r12 = CPyDict_SetItem(d, k, r11)
|
||||
r13 = r12 >= 0 :: signed
|
||||
L3:
|
||||
r14 = CPyDict_CheckSize(d, r2)
|
||||
goto L1
|
||||
L4:
|
||||
r15 = CPy_NoErrOccured()
|
||||
L5:
|
||||
return d
|
||||
|
||||
[case testDictDisplay]
|
||||
from typing import Dict
|
||||
def f(x: str, y: Dict[str, int]) -> Dict[str, int]:
|
||||
return {x: 2, **y, 'z': 3}
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: str
|
||||
y :: dict
|
||||
r0 :: str
|
||||
r1 :: object
|
||||
r2 :: dict
|
||||
r3 :: i32
|
||||
r4 :: bit
|
||||
r5 :: object
|
||||
r6 :: i32
|
||||
r7 :: bit
|
||||
L0:
|
||||
r0 = 'z'
|
||||
r1 = object 2
|
||||
r2 = CPyDict_Build(1, x, r1)
|
||||
r3 = CPyDict_UpdateInDisplay(r2, y)
|
||||
r4 = r3 >= 0 :: signed
|
||||
r5 = object 3
|
||||
r6 = CPyDict_SetItem(r2, r0, r5)
|
||||
r7 = r6 >= 0 :: signed
|
||||
return r2
|
||||
|
||||
[case testDictIterationMethods]
|
||||
from typing import Dict, Union
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
class Person(TypedDict):
|
||||
name: str
|
||||
age: int
|
||||
|
||||
def print_dict_methods(d1: Dict[int, int], d2: Dict[int, int]) -> None:
|
||||
for v in d1.values():
|
||||
if v in d2:
|
||||
return
|
||||
for k, v in d2.items():
|
||||
d2[k] += v
|
||||
def union_of_dicts(d: Union[Dict[str, int], Dict[str, str]]) -> None:
|
||||
new = {}
|
||||
for k, v in d.items():
|
||||
new[k] = int(v)
|
||||
def typeddict(d: Person) -> None:
|
||||
for k, v in d.items():
|
||||
if k == "name":
|
||||
name = v
|
||||
[out]
|
||||
def print_dict_methods(d1, d2):
|
||||
d1, d2 :: dict
|
||||
r0 :: short_int
|
||||
r1 :: native_int
|
||||
r2 :: short_int
|
||||
r3 :: object
|
||||
r4 :: tuple[bool, short_int, object]
|
||||
r5 :: short_int
|
||||
r6 :: bool
|
||||
r7 :: object
|
||||
r8, v :: int
|
||||
r9 :: object
|
||||
r10 :: i32
|
||||
r11 :: bit
|
||||
r12 :: bool
|
||||
r13, r14 :: bit
|
||||
r15 :: short_int
|
||||
r16 :: native_int
|
||||
r17 :: short_int
|
||||
r18 :: object
|
||||
r19 :: tuple[bool, short_int, object, object]
|
||||
r20 :: short_int
|
||||
r21 :: bool
|
||||
r22, r23 :: object
|
||||
r24, r25, k :: int
|
||||
r26, r27, r28, r29, r30 :: object
|
||||
r31 :: i32
|
||||
r32, r33, r34 :: bit
|
||||
L0:
|
||||
r0 = 0
|
||||
r1 = PyDict_Size(d1)
|
||||
r2 = r1 << 1
|
||||
r3 = CPyDict_GetValuesIter(d1)
|
||||
L1:
|
||||
r4 = CPyDict_NextValue(r3, r0)
|
||||
r5 = r4[1]
|
||||
r0 = r5
|
||||
r6 = r4[0]
|
||||
if r6 goto L2 else goto L6 :: bool
|
||||
L2:
|
||||
r7 = r4[2]
|
||||
r8 = unbox(int, r7)
|
||||
v = r8
|
||||
r9 = box(int, v)
|
||||
r10 = PyDict_Contains(d2, r9)
|
||||
r11 = r10 >= 0 :: signed
|
||||
r12 = truncate r10: i32 to builtins.bool
|
||||
if r12 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
return 1
|
||||
L4:
|
||||
L5:
|
||||
r13 = CPyDict_CheckSize(d1, r2)
|
||||
goto L1
|
||||
L6:
|
||||
r14 = CPy_NoErrOccured()
|
||||
L7:
|
||||
r15 = 0
|
||||
r16 = PyDict_Size(d2)
|
||||
r17 = r16 << 1
|
||||
r18 = CPyDict_GetItemsIter(d2)
|
||||
L8:
|
||||
r19 = CPyDict_NextItem(r18, r15)
|
||||
r20 = r19[1]
|
||||
r15 = r20
|
||||
r21 = r19[0]
|
||||
if r21 goto L9 else goto L11 :: bool
|
||||
L9:
|
||||
r22 = r19[2]
|
||||
r23 = r19[3]
|
||||
r24 = unbox(int, r22)
|
||||
r25 = unbox(int, r23)
|
||||
k = r24
|
||||
v = r25
|
||||
r26 = box(int, k)
|
||||
r27 = CPyDict_GetItem(d2, r26)
|
||||
r28 = box(int, v)
|
||||
r29 = PyNumber_InPlaceAdd(r27, r28)
|
||||
r30 = box(int, k)
|
||||
r31 = CPyDict_SetItem(d2, r30, r29)
|
||||
r32 = r31 >= 0 :: signed
|
||||
L10:
|
||||
r33 = CPyDict_CheckSize(d2, r17)
|
||||
goto L8
|
||||
L11:
|
||||
r34 = CPy_NoErrOccured()
|
||||
L12:
|
||||
return 1
|
||||
def union_of_dicts(d):
|
||||
d, r0, new :: dict
|
||||
r1 :: short_int
|
||||
r2 :: native_int
|
||||
r3 :: short_int
|
||||
r4 :: object
|
||||
r5 :: tuple[bool, short_int, object, object]
|
||||
r6 :: short_int
|
||||
r7 :: bool
|
||||
r8, r9 :: object
|
||||
r10 :: str
|
||||
r11 :: union[int, str]
|
||||
k :: str
|
||||
v :: union[int, str]
|
||||
r12, r13 :: object
|
||||
r14 :: int
|
||||
r15 :: object
|
||||
r16 :: i32
|
||||
r17, r18, r19 :: bit
|
||||
L0:
|
||||
r0 = PyDict_New()
|
||||
new = r0
|
||||
r1 = 0
|
||||
r2 = PyDict_Size(d)
|
||||
r3 = r2 << 1
|
||||
r4 = CPyDict_GetItemsIter(d)
|
||||
L1:
|
||||
r5 = CPyDict_NextItem(r4, r1)
|
||||
r6 = r5[1]
|
||||
r1 = r6
|
||||
r7 = r5[0]
|
||||
if r7 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r8 = r5[2]
|
||||
r9 = r5[3]
|
||||
r10 = cast(str, r8)
|
||||
r11 = cast(union[int, str], r9)
|
||||
k = r10
|
||||
v = r11
|
||||
r12 = load_address PyLong_Type
|
||||
r13 = PyObject_CallFunctionObjArgs(r12, v, 0)
|
||||
r14 = unbox(int, r13)
|
||||
r15 = box(int, r14)
|
||||
r16 = CPyDict_SetItem(new, k, r15)
|
||||
r17 = r16 >= 0 :: signed
|
||||
L3:
|
||||
r18 = CPyDict_CheckSize(d, r3)
|
||||
goto L1
|
||||
L4:
|
||||
r19 = CPy_NoErrOccured()
|
||||
L5:
|
||||
return 1
|
||||
def typeddict(d):
|
||||
d :: dict
|
||||
r0 :: short_int
|
||||
r1 :: native_int
|
||||
r2 :: short_int
|
||||
r3 :: object
|
||||
r4 :: tuple[bool, short_int, object, object]
|
||||
r5 :: short_int
|
||||
r6 :: bool
|
||||
r7, r8 :: object
|
||||
r9, k :: str
|
||||
v :: object
|
||||
r10 :: str
|
||||
r11 :: i32
|
||||
r12 :: bit
|
||||
r13 :: object
|
||||
r14, r15, r16 :: bit
|
||||
name :: object
|
||||
r17, r18 :: bit
|
||||
L0:
|
||||
r0 = 0
|
||||
r1 = PyDict_Size(d)
|
||||
r2 = r1 << 1
|
||||
r3 = CPyDict_GetItemsIter(d)
|
||||
L1:
|
||||
r4 = CPyDict_NextItem(r3, r0)
|
||||
r5 = r4[1]
|
||||
r0 = r5
|
||||
r6 = r4[0]
|
||||
if r6 goto L2 else goto L9 :: bool
|
||||
L2:
|
||||
r7 = r4[2]
|
||||
r8 = r4[3]
|
||||
r9 = cast(str, r7)
|
||||
k = r9
|
||||
v = r8
|
||||
r10 = 'name'
|
||||
r11 = PyUnicode_Compare(k, r10)
|
||||
r12 = r11 == -1
|
||||
if r12 goto L3 else goto L5 :: bool
|
||||
L3:
|
||||
r13 = PyErr_Occurred()
|
||||
r14 = r13 != 0
|
||||
if r14 goto L4 else goto L5 :: bool
|
||||
L4:
|
||||
r15 = CPy_KeepPropagating()
|
||||
L5:
|
||||
r16 = r11 == 0
|
||||
if r16 goto L6 else goto L7 :: bool
|
||||
L6:
|
||||
name = v
|
||||
L7:
|
||||
L8:
|
||||
r17 = CPyDict_CheckSize(d, r2)
|
||||
goto L1
|
||||
L9:
|
||||
r18 = CPy_NoErrOccured()
|
||||
L10:
|
||||
return 1
|
||||
|
||||
[case testDictLoadAddress]
|
||||
def f() -> None:
|
||||
x = dict
|
||||
[out]
|
||||
def f():
|
||||
r0, x :: object
|
||||
L0:
|
||||
r0 = load_address PyDict_Type
|
||||
x = r0
|
||||
return 1
|
||||
|
||||
[case testDictClear]
|
||||
from typing import Dict
|
||||
def f(d: Dict[int, int]) -> None:
|
||||
return d.clear()
|
||||
[out]
|
||||
def f(d):
|
||||
d :: dict
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = CPyDict_Clear(d)
|
||||
return 1
|
||||
|
||||
[case testDictCopy]
|
||||
from typing import Dict
|
||||
def f(d: Dict[int, int]) -> Dict[int, int]:
|
||||
return d.copy()
|
||||
[out]
|
||||
def f(d):
|
||||
d, r0 :: dict
|
||||
L0:
|
||||
r0 = CPyDict_Copy(d)
|
||||
return r0
|
||||
|
||||
[case testDictSetdefault]
|
||||
from typing import Dict
|
||||
def f(d: Dict[object, object]) -> object:
|
||||
return d.setdefault('a', 'b')
|
||||
|
||||
def f2(d: Dict[object, object], flag: bool) -> object:
|
||||
if flag:
|
||||
return d.setdefault('a', set())
|
||||
else:
|
||||
return d.setdefault('a', set('b'))
|
||||
|
||||
def f3(d: Dict[object, object], flag: bool) -> object:
|
||||
if flag:
|
||||
return d.setdefault('a', [])
|
||||
else:
|
||||
return d.setdefault('a', [1])
|
||||
|
||||
def f4(d: Dict[object, object], flag: bool) -> object:
|
||||
if flag:
|
||||
return d.setdefault('a', {})
|
||||
else:
|
||||
return d.setdefault('a', {'c': 1})
|
||||
[out]
|
||||
def f(d):
|
||||
d :: dict
|
||||
r0, r1 :: str
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = 'a'
|
||||
r1 = 'b'
|
||||
r2 = CPyDict_SetDefault(d, r0, r1)
|
||||
return r2
|
||||
def f2(d, flag):
|
||||
d :: dict
|
||||
flag :: bool
|
||||
r0 :: str
|
||||
r1 :: object
|
||||
r2, r3 :: str
|
||||
r4 :: set
|
||||
r5, r6 :: object
|
||||
L0:
|
||||
if flag goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r0 = 'a'
|
||||
r1 = CPyDict_SetDefaultWithEmptyDatatype(d, r0, 3)
|
||||
return r1
|
||||
L2:
|
||||
r2 = 'a'
|
||||
r3 = 'b'
|
||||
r4 = PySet_New(r3)
|
||||
r5 = CPyDict_SetDefault(d, r2, r4)
|
||||
return r5
|
||||
L3:
|
||||
r6 = box(None, 1)
|
||||
return r6
|
||||
def f3(d, flag):
|
||||
d :: dict
|
||||
flag :: bool
|
||||
r0 :: str
|
||||
r1 :: object
|
||||
r2 :: str
|
||||
r3 :: list
|
||||
r4 :: object
|
||||
r5, r6 :: ptr
|
||||
r7, r8 :: object
|
||||
L0:
|
||||
if flag goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r0 = 'a'
|
||||
r1 = CPyDict_SetDefaultWithEmptyDatatype(d, r0, 1)
|
||||
return r1
|
||||
L2:
|
||||
r2 = 'a'
|
||||
r3 = PyList_New(1)
|
||||
r4 = object 1
|
||||
r5 = get_element_ptr r3 ob_item :: PyListObject
|
||||
r6 = load_mem r5 :: ptr*
|
||||
set_mem r6, r4 :: builtins.object*
|
||||
keep_alive r3
|
||||
r7 = CPyDict_SetDefault(d, r2, r3)
|
||||
return r7
|
||||
L3:
|
||||
r8 = box(None, 1)
|
||||
return r8
|
||||
def f4(d, flag):
|
||||
d :: dict
|
||||
flag :: bool
|
||||
r0 :: str
|
||||
r1 :: object
|
||||
r2, r3 :: str
|
||||
r4 :: object
|
||||
r5 :: dict
|
||||
r6, r7 :: object
|
||||
L0:
|
||||
if flag goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r0 = 'a'
|
||||
r1 = CPyDict_SetDefaultWithEmptyDatatype(d, r0, 2)
|
||||
return r1
|
||||
L2:
|
||||
r2 = 'a'
|
||||
r3 = 'c'
|
||||
r4 = object 1
|
||||
r5 = CPyDict_Build(1, r3, r4)
|
||||
r6 = CPyDict_SetDefault(d, r2, r5)
|
||||
return r6
|
||||
L3:
|
||||
r7 = box(None, 1)
|
||||
return r7
|
||||
@@ -0,0 +1,223 @@
|
||||
# Test cases for (some) dunder methods
|
||||
|
||||
[case testDundersLen]
|
||||
class C:
|
||||
def __len__(self) -> int:
|
||||
return 2
|
||||
|
||||
def f(c: C) -> int:
|
||||
return len(c)
|
||||
[out]
|
||||
def C.__len__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 4
|
||||
def f(c):
|
||||
c :: __main__.C
|
||||
r0 :: int
|
||||
r1 :: native_int
|
||||
r2, r3, r4 :: bit
|
||||
r5 :: bool
|
||||
L0:
|
||||
r0 = c.__len__()
|
||||
r1 = r0 & 1
|
||||
r2 = r1 != 0
|
||||
if r2 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r3 = CPyTagged_IsLt_(r0, 0)
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L2:
|
||||
r4 = r0 >= 0 :: signed
|
||||
if r4 goto L4 else goto L3 :: bool
|
||||
L3:
|
||||
r5 = raise ValueError('__len__() should return >= 0')
|
||||
unreachable
|
||||
L4:
|
||||
return r0
|
||||
|
||||
[case testDundersSetItem]
|
||||
class C:
|
||||
def __setitem__(self, key: int, value: int) -> None:
|
||||
pass
|
||||
|
||||
def f(c: C) -> None:
|
||||
c[3] = 4
|
||||
[out]
|
||||
def C.__setitem__(self, key, value):
|
||||
self :: __main__.C
|
||||
key, value :: int
|
||||
L0:
|
||||
return 1
|
||||
def f(c):
|
||||
c :: __main__.C
|
||||
r0 :: None
|
||||
L0:
|
||||
r0 = c.__setitem__(6, 8)
|
||||
return 1
|
||||
|
||||
[case testDundersContains]
|
||||
from typing import Any
|
||||
|
||||
class C:
|
||||
def __contains__(self, x: int) -> bool:
|
||||
return False
|
||||
|
||||
def f(c: C) -> bool:
|
||||
return 7 in c
|
||||
|
||||
def g(c: C) -> bool:
|
||||
return 7 not in c
|
||||
|
||||
class D:
|
||||
def __contains__(self, x: int) -> Any:
|
||||
return 'x'
|
||||
|
||||
def h(d: D) -> bool:
|
||||
return 7 not in d
|
||||
[out]
|
||||
def C.__contains__(self, x):
|
||||
self :: __main__.C
|
||||
x :: int
|
||||
L0:
|
||||
return 0
|
||||
def f(c):
|
||||
c :: __main__.C
|
||||
r0 :: bool
|
||||
L0:
|
||||
r0 = c.__contains__(14)
|
||||
return r0
|
||||
def g(c):
|
||||
c :: __main__.C
|
||||
r0, r1 :: bool
|
||||
L0:
|
||||
r0 = c.__contains__(14)
|
||||
r1 = r0 ^ 1
|
||||
return r1
|
||||
def D.__contains__(self, x):
|
||||
self :: __main__.D
|
||||
x :: int
|
||||
r0 :: str
|
||||
L0:
|
||||
r0 = 'x'
|
||||
return r0
|
||||
def h(d):
|
||||
d :: __main__.D
|
||||
r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3, r4 :: bool
|
||||
L0:
|
||||
r0 = d.__contains__(14)
|
||||
r1 = PyObject_IsTrue(r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
r4 = r3 ^ 1
|
||||
return r4
|
||||
|
||||
[case testDundersDelItem]
|
||||
class C:
|
||||
def __delitem__(self, x: int) -> None:
|
||||
pass
|
||||
|
||||
def f(c: C) -> None:
|
||||
del c[5]
|
||||
[out]
|
||||
def C.__delitem__(self, x):
|
||||
self :: __main__.C
|
||||
x :: int
|
||||
L0:
|
||||
return 1
|
||||
def f(c):
|
||||
c :: __main__.C
|
||||
r0 :: None
|
||||
L0:
|
||||
r0 = c.__delitem__(10)
|
||||
return 1
|
||||
|
||||
[case testDundersUnary]
|
||||
class C:
|
||||
def __neg__(self) -> int:
|
||||
return 1
|
||||
|
||||
def __invert__(self) -> int:
|
||||
return 2
|
||||
|
||||
def __int__(self) -> int:
|
||||
return 3
|
||||
|
||||
def __float__(self) -> float:
|
||||
return 4.0
|
||||
|
||||
def __pos__(self) -> int:
|
||||
return 5
|
||||
|
||||
def __abs__(self) -> int:
|
||||
return 6
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return False
|
||||
|
||||
def __complex__(self) -> complex:
|
||||
return 7j
|
||||
|
||||
def f(c: C) -> None:
|
||||
-c
|
||||
~c
|
||||
int(c)
|
||||
float(c)
|
||||
+c
|
||||
abs(c)
|
||||
bool(c)
|
||||
complex(c)
|
||||
[out]
|
||||
def C.__neg__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 2
|
||||
def C.__invert__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 4
|
||||
def C.__int__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 6
|
||||
def C.__float__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 4.0
|
||||
def C.__pos__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 10
|
||||
def C.__abs__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 12
|
||||
def C.__bool__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 0
|
||||
def C.__complex__(self):
|
||||
self :: __main__.C
|
||||
r0 :: object
|
||||
L0:
|
||||
r0 = 7j
|
||||
return r0
|
||||
def f(c):
|
||||
c :: __main__.C
|
||||
r0, r1, r2 :: int
|
||||
r3 :: float
|
||||
r4, r5 :: int
|
||||
r6 :: bool
|
||||
r7 :: object
|
||||
L0:
|
||||
r0 = c.__neg__()
|
||||
r1 = c.__invert__()
|
||||
r2 = c.__int__()
|
||||
r3 = c.__float__()
|
||||
r4 = c.__pos__()
|
||||
r5 = c.__abs__()
|
||||
r6 = c.__bool__()
|
||||
r7 = c.__complex__()
|
||||
return 1
|
||||
@@ -0,0 +1,497 @@
|
||||
[case testFloatAdd]
|
||||
def f(x: float, y: float) -> float:
|
||||
return x + y
|
||||
def g(x: float) -> float:
|
||||
z = x - 1.5
|
||||
return 2.5 * z
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y, r0 :: float
|
||||
L0:
|
||||
r0 = x + y
|
||||
return r0
|
||||
def g(x):
|
||||
x, r0, z, r1 :: float
|
||||
L0:
|
||||
r0 = x - 1.5
|
||||
z = r0
|
||||
r1 = 2.5 * z
|
||||
return r1
|
||||
|
||||
[case testFloatBoxAndUnbox]
|
||||
from typing import Any
|
||||
def f(x: float) -> object:
|
||||
return x
|
||||
def g(x: Any) -> float:
|
||||
return x
|
||||
[out]
|
||||
def f(x):
|
||||
x :: float
|
||||
r0 :: object
|
||||
L0:
|
||||
r0 = box(float, x)
|
||||
return r0
|
||||
def g(x):
|
||||
x :: object
|
||||
r0 :: float
|
||||
L0:
|
||||
r0 = unbox(float, x)
|
||||
return r0
|
||||
|
||||
[case testFloatNegAndPos]
|
||||
def f(x: float) -> float:
|
||||
y = +x * -0.5
|
||||
return -y
|
||||
[out]
|
||||
def f(x):
|
||||
x, r0, y, r1 :: float
|
||||
L0:
|
||||
r0 = x * -0.5
|
||||
y = r0
|
||||
r1 = -y
|
||||
return r1
|
||||
|
||||
[case testFloatCoerceFromInt]
|
||||
def from_int(x: int) -> float:
|
||||
return x
|
||||
|
||||
def from_literal() -> float:
|
||||
return 5
|
||||
|
||||
def from_literal_neg() -> float:
|
||||
return -2
|
||||
[out]
|
||||
def from_int(x):
|
||||
x :: int
|
||||
r0 :: float
|
||||
L0:
|
||||
r0 = CPyFloat_FromTagged(x)
|
||||
return r0
|
||||
def from_literal():
|
||||
L0:
|
||||
return 5.0
|
||||
def from_literal_neg():
|
||||
L0:
|
||||
return -2.0
|
||||
|
||||
[case testConvertBetweenFloatAndInt]
|
||||
def to_int(x: float) -> int:
|
||||
return int(x)
|
||||
def from_int(x: int) -> float:
|
||||
return float(x)
|
||||
[out]
|
||||
def to_int(x):
|
||||
x :: float
|
||||
r0 :: int
|
||||
L0:
|
||||
r0 = CPyTagged_FromFloat(x)
|
||||
return r0
|
||||
def from_int(x):
|
||||
x :: int
|
||||
r0 :: float
|
||||
L0:
|
||||
r0 = CPyFloat_FromTagged(x)
|
||||
return r0
|
||||
|
||||
[case testFloatOperatorAssignment]
|
||||
def f(x: float, y: float) -> float:
|
||||
x += y
|
||||
x -= 5.0
|
||||
return x
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y, r0, r1 :: float
|
||||
L0:
|
||||
r0 = x + y
|
||||
x = r0
|
||||
r1 = x - 5.0
|
||||
x = r1
|
||||
return x
|
||||
|
||||
[case testFloatOperatorAssignmentWithInt]
|
||||
def f(x: float, y: int) -> None:
|
||||
x += y
|
||||
x -= 5
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: float
|
||||
y :: int
|
||||
r0, r1, r2 :: float
|
||||
L0:
|
||||
r0 = CPyFloat_FromTagged(y)
|
||||
r1 = x + r0
|
||||
x = r1
|
||||
r2 = x - 5.0
|
||||
x = r2
|
||||
return 1
|
||||
|
||||
[case testFloatComparison]
|
||||
def lt(x: float, y: float) -> bool:
|
||||
return x < y
|
||||
def eq(x: float, y: float) -> bool:
|
||||
return x == y
|
||||
[out]
|
||||
def lt(x, y):
|
||||
x, y :: float
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = x < y
|
||||
return r0
|
||||
def eq(x, y):
|
||||
x, y :: float
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = x == y
|
||||
return r0
|
||||
|
||||
[case testFloatOpWithLiteralInt]
|
||||
def f(x: float) -> None:
|
||||
y = x * 2
|
||||
z = 1 - y
|
||||
b = z < 3
|
||||
c = 0 == z
|
||||
[out]
|
||||
def f(x):
|
||||
x, r0, y, r1, z :: float
|
||||
r2 :: bit
|
||||
b :: bool
|
||||
r3 :: bit
|
||||
c :: bool
|
||||
L0:
|
||||
r0 = x * 2.0
|
||||
y = r0
|
||||
r1 = 1.0 - y
|
||||
z = r1
|
||||
r2 = z < 3.0
|
||||
b = r2
|
||||
r3 = 0.0 == z
|
||||
c = r3
|
||||
return 1
|
||||
|
||||
[case testFloatCallFunctionWithLiteralInt]
|
||||
def f(x: float) -> None: pass
|
||||
|
||||
def g() -> None:
|
||||
f(3)
|
||||
f(-2)
|
||||
[out]
|
||||
def f(x):
|
||||
x :: float
|
||||
L0:
|
||||
return 1
|
||||
def g():
|
||||
r0, r1 :: None
|
||||
L0:
|
||||
r0 = f(3.0)
|
||||
r1 = f(-2.0)
|
||||
return 1
|
||||
|
||||
[case testFloatAsBool]
|
||||
def f(x: float) -> int:
|
||||
if x:
|
||||
return 2
|
||||
else:
|
||||
return 5
|
||||
[out]
|
||||
def f(x):
|
||||
x :: float
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = x != 0.0
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return 4
|
||||
L2:
|
||||
return 10
|
||||
L3:
|
||||
unreachable
|
||||
|
||||
[case testCallSqrtViaMathModule]
|
||||
import math
|
||||
|
||||
def f(x: float) -> float:
|
||||
return math.sqrt(x)
|
||||
[out]
|
||||
def f(x):
|
||||
x, r0 :: float
|
||||
L0:
|
||||
r0 = CPyFloat_Sqrt(x)
|
||||
return r0
|
||||
|
||||
[case testFloatFinalConstant]
|
||||
from typing_extensions import Final
|
||||
|
||||
X: Final = 123.0
|
||||
Y: Final = -1.0
|
||||
|
||||
def f() -> float:
|
||||
a = X
|
||||
return a + Y
|
||||
[out]
|
||||
def f():
|
||||
a, r0 :: float
|
||||
L0:
|
||||
a = 123.0
|
||||
r0 = a + -1.0
|
||||
return r0
|
||||
|
||||
[case testFloatDefaultArg]
|
||||
def f(x: float = 1.5) -> float:
|
||||
return x
|
||||
[out]
|
||||
def f(x, __bitmap):
|
||||
x :: float
|
||||
__bitmap, r0 :: u32
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = __bitmap & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
x = 1.5
|
||||
L2:
|
||||
return x
|
||||
|
||||
[case testFloatMixedOperations]
|
||||
def f(x: float, y: int) -> None:
|
||||
if x < y:
|
||||
z = x + y
|
||||
x -= y
|
||||
z = y + z
|
||||
if y == x:
|
||||
x -= 1
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: float
|
||||
y :: int
|
||||
r0 :: float
|
||||
r1 :: bit
|
||||
r2, r3, z, r4, r5, r6, r7, r8 :: float
|
||||
r9 :: bit
|
||||
r10 :: float
|
||||
L0:
|
||||
r0 = CPyFloat_FromTagged(y)
|
||||
r1 = x < r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r2 = CPyFloat_FromTagged(y)
|
||||
r3 = x + r2
|
||||
z = r3
|
||||
r4 = CPyFloat_FromTagged(y)
|
||||
r5 = x - r4
|
||||
x = r5
|
||||
r6 = CPyFloat_FromTagged(y)
|
||||
r7 = r6 + z
|
||||
z = r7
|
||||
L2:
|
||||
r8 = CPyFloat_FromTagged(y)
|
||||
r9 = r8 == x
|
||||
if r9 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r10 = x - 1.0
|
||||
x = r10
|
||||
L4:
|
||||
return 1
|
||||
|
||||
[case testFloatDivideSimple]
|
||||
def f(x: float, y: float) -> float:
|
||||
z = x / y
|
||||
z = z / 2.0
|
||||
return z / 3
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y :: float
|
||||
r0 :: bit
|
||||
r1 :: bool
|
||||
r2, z, r3, r4 :: float
|
||||
L0:
|
||||
r0 = y == 0.0
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r1 = raise ZeroDivisionError('float division by zero')
|
||||
unreachable
|
||||
L2:
|
||||
r2 = x / y
|
||||
z = r2
|
||||
r3 = z / 2.0
|
||||
z = r3
|
||||
r4 = z / 3.0
|
||||
return r4
|
||||
|
||||
[case testFloatDivideIntOperand]
|
||||
def f(n: int, m: int) -> float:
|
||||
return n / m
|
||||
[out]
|
||||
def f(n, m):
|
||||
n, m :: int
|
||||
r0 :: float
|
||||
L0:
|
||||
r0 = CPyTagged_TrueDivide(n, m)
|
||||
return r0
|
||||
|
||||
[case testFloatResultOfIntDivide]
|
||||
def f(f: float, n: int) -> float:
|
||||
x = f / n
|
||||
return n / x
|
||||
[out]
|
||||
def f(f, n):
|
||||
f :: float
|
||||
n :: int
|
||||
r0 :: float
|
||||
r1 :: bit
|
||||
r2 :: bool
|
||||
r3, x, r4 :: float
|
||||
r5 :: bit
|
||||
r6 :: bool
|
||||
r7 :: float
|
||||
L0:
|
||||
r0 = CPyFloat_FromTagged(n)
|
||||
r1 = r0 == 0.0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r2 = raise ZeroDivisionError('float division by zero')
|
||||
unreachable
|
||||
L2:
|
||||
r3 = f / r0
|
||||
x = r3
|
||||
r4 = CPyFloat_FromTagged(n)
|
||||
r5 = x == 0.0
|
||||
if r5 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r6 = raise ZeroDivisionError('float division by zero')
|
||||
unreachable
|
||||
L4:
|
||||
r7 = r4 / x
|
||||
return r7
|
||||
|
||||
[case testFloatExplicitConversions]
|
||||
def f(f: float, n: int) -> int:
|
||||
x = float(n)
|
||||
y = float(x) # no-op
|
||||
return int(y)
|
||||
[out]
|
||||
def f(f, n):
|
||||
f :: float
|
||||
n :: int
|
||||
r0, x, y :: float
|
||||
r1 :: int
|
||||
L0:
|
||||
r0 = CPyFloat_FromTagged(n)
|
||||
x = r0
|
||||
y = x
|
||||
r1 = CPyTagged_FromFloat(y)
|
||||
return r1
|
||||
|
||||
[case testFloatModulo]
|
||||
def f(x: float, y: float) -> float:
|
||||
return x % y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y :: float
|
||||
r0 :: bit
|
||||
r1 :: bool
|
||||
r2, r3 :: float
|
||||
r4, r5, r6, r7 :: bit
|
||||
r8, r9 :: float
|
||||
L0:
|
||||
r0 = y == 0.0
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r1 = raise ZeroDivisionError('float modulo')
|
||||
unreachable
|
||||
L2:
|
||||
r2 = x % y
|
||||
r3 = r2
|
||||
r4 = r3 == 0.0
|
||||
if r4 goto L5 else goto L3 :: bool
|
||||
L3:
|
||||
r5 = x < 0.0
|
||||
r6 = y < 0.0
|
||||
r7 = r5 == r6
|
||||
if r7 goto L6 else goto L4 :: bool
|
||||
L4:
|
||||
r8 = r3 + y
|
||||
r3 = r8
|
||||
goto L6
|
||||
L5:
|
||||
r9 = copysign(0.0, y)
|
||||
r3 = r9
|
||||
L6:
|
||||
return r3
|
||||
|
||||
[case testFloatFloorDivide]
|
||||
def f(x: float, y: float) -> float:
|
||||
return x // y
|
||||
def g(x: float, y: int) -> float:
|
||||
return x // y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y, r0 :: float
|
||||
L0:
|
||||
r0 = CPyFloat_FloorDivide(x, y)
|
||||
return r0
|
||||
def g(x, y):
|
||||
x :: float
|
||||
y :: int
|
||||
r0, r1 :: float
|
||||
L0:
|
||||
r0 = CPyFloat_FromTagged(y)
|
||||
r1 = CPyFloat_FloorDivide(x, r0)
|
||||
return r1
|
||||
|
||||
[case testFloatNarrowToIntDisallowed]
|
||||
class C:
|
||||
x: float
|
||||
|
||||
def narrow_local(x: float, n: int) -> int:
|
||||
x = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
|
||||
return x
|
||||
|
||||
def narrow_tuple_lvalue(x: float, y: float, n: int) -> int:
|
||||
x, y = 1.0, n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
|
||||
return y
|
||||
|
||||
def narrow_multiple_lvalues(x: float, y: float, n: int) -> int:
|
||||
x = a = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
|
||||
a = y = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
|
||||
return x + y
|
||||
|
||||
def narrow_attribute(c: C, n: int) -> int:
|
||||
c.x = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
|
||||
return c.x
|
||||
|
||||
def narrow_using_int_literal(x: float) -> int:
|
||||
x = 1 # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
|
||||
return x
|
||||
|
||||
def narrow_using_declaration(n: int) -> int:
|
||||
x: float
|
||||
x = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
|
||||
return x
|
||||
|
||||
[case testFloatInitializeFromInt]
|
||||
def init(n: int) -> None:
|
||||
# These are strictly speaking safe, since these don't narrow, but for consistency with
|
||||
# narrowing assignments, generate errors here
|
||||
x: float = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
|
||||
y: float = 5 # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
|
||||
|
||||
[case testFloatCoerceTupleFromIntValues]
|
||||
from __future__ import annotations
|
||||
|
||||
def f(x: int) -> None:
|
||||
t: tuple[float, float, float] = (x, 2.5, -7)
|
||||
[out]
|
||||
def f(x):
|
||||
x :: int
|
||||
r0 :: tuple[int, float, int]
|
||||
r1 :: int
|
||||
r2 :: float
|
||||
r3, t :: tuple[float, float, float]
|
||||
L0:
|
||||
r0 = (x, 2.5, -14)
|
||||
r1 = r0[0]
|
||||
r2 = CPyFloat_FromTagged(r1)
|
||||
r3 = (r2, 2.5, -7.0)
|
||||
t = r3
|
||||
return 1
|
||||
@@ -0,0 +1,151 @@
|
||||
[case testGenericFunction]
|
||||
from typing import TypeVar, List
|
||||
T = TypeVar('T')
|
||||
def f(x: T) -> T:
|
||||
return x
|
||||
def g(x: List[T]) -> List[T]:
|
||||
return [x[0]]
|
||||
def h(x: int, y: List[int]) -> None:
|
||||
x = f(x)
|
||||
y = g(y)
|
||||
[out]
|
||||
def f(x):
|
||||
x :: object
|
||||
L0:
|
||||
return x
|
||||
def g(x):
|
||||
x :: list
|
||||
r0 :: object
|
||||
r1 :: list
|
||||
r2, r3 :: ptr
|
||||
L0:
|
||||
r0 = CPyList_GetItemShort(x, 0)
|
||||
r1 = PyList_New(1)
|
||||
r2 = get_element_ptr r1 ob_item :: PyListObject
|
||||
r3 = load_mem r2 :: ptr*
|
||||
set_mem r3, r0 :: builtins.object*
|
||||
keep_alive r1
|
||||
return r1
|
||||
def h(x, y):
|
||||
x :: int
|
||||
y :: list
|
||||
r0, r1 :: object
|
||||
r2 :: int
|
||||
r3 :: list
|
||||
L0:
|
||||
r0 = box(int, x)
|
||||
r1 = f(r0)
|
||||
r2 = unbox(int, r1)
|
||||
x = r2
|
||||
r3 = g(y)
|
||||
y = r3
|
||||
return 1
|
||||
|
||||
[case testGenericAttrAndTypeApplication]
|
||||
from typing import TypeVar, Generic
|
||||
T = TypeVar('T')
|
||||
class C(Generic[T]):
|
||||
x: T
|
||||
def f() -> None:
|
||||
c = C[int]()
|
||||
c.x = 1
|
||||
2 + c.x
|
||||
[out]
|
||||
def f():
|
||||
r0, c :: __main__.C
|
||||
r1 :: object
|
||||
r2 :: bool
|
||||
r3 :: object
|
||||
r4, r5 :: int
|
||||
L0:
|
||||
r0 = C()
|
||||
c = r0
|
||||
r1 = object 1
|
||||
c.x = r1; r2 = is_error
|
||||
r3 = borrow c.x
|
||||
r4 = unbox(int, r3)
|
||||
r5 = CPyTagged_Add(4, r4)
|
||||
keep_alive c
|
||||
return 1
|
||||
|
||||
[case testGenericMethod]
|
||||
from typing import TypeVar, Generic
|
||||
T = TypeVar('T')
|
||||
class C(Generic[T]):
|
||||
x: T
|
||||
def __init__(self, x: T) -> None:
|
||||
self.x = x
|
||||
def get(self) -> T:
|
||||
return self.x
|
||||
def set(self, y: T) -> None:
|
||||
self.x = y
|
||||
def f(x: C[int]) -> None:
|
||||
y = x.get()
|
||||
x.set(y + 1)
|
||||
x = C(2)
|
||||
[out]
|
||||
def C.__init__(self, x):
|
||||
self :: __main__.C
|
||||
x :: object
|
||||
r0 :: bool
|
||||
L0:
|
||||
self.x = x; r0 = is_error
|
||||
return 1
|
||||
def C.get(self):
|
||||
self :: __main__.C
|
||||
r0 :: object
|
||||
L0:
|
||||
r0 = self.x
|
||||
return r0
|
||||
def C.set(self, y):
|
||||
self :: __main__.C
|
||||
y :: object
|
||||
r0 :: bool
|
||||
L0:
|
||||
self.x = y; r0 = is_error
|
||||
return 1
|
||||
def f(x):
|
||||
x :: __main__.C
|
||||
r0 :: object
|
||||
r1, y, r2 :: int
|
||||
r3 :: object
|
||||
r4 :: None
|
||||
r5 :: object
|
||||
r6 :: __main__.C
|
||||
L0:
|
||||
r0 = x.get()
|
||||
r1 = unbox(int, r0)
|
||||
y = r1
|
||||
r2 = CPyTagged_Add(y, 2)
|
||||
r3 = box(int, r2)
|
||||
r4 = x.set(r3)
|
||||
r5 = object 2
|
||||
r6 = C(r5)
|
||||
x = r6
|
||||
return 1
|
||||
|
||||
[case testMax]
|
||||
from typing import TypeVar
|
||||
T = TypeVar('T')
|
||||
def f(x: T, y: T) -> T:
|
||||
return max(x, y)
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y, r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3 :: bool
|
||||
r4 :: object
|
||||
L0:
|
||||
r0 = PyObject_RichCompare(y, x, 4)
|
||||
r1 = PyObject_IsTrue(r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
if r3 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r4 = y
|
||||
goto L3
|
||||
L2:
|
||||
r4 = x
|
||||
L3:
|
||||
return r4
|
||||
@@ -0,0 +1,437 @@
|
||||
# Test cases for glue methods.
|
||||
#
|
||||
# These are used when subclass method signature has a different representation
|
||||
# compared to the base class.
|
||||
|
||||
[case testSubclassSpecialize2]
|
||||
class A:
|
||||
def foo(self, x: int) -> object:
|
||||
return str(x)
|
||||
class B(A):
|
||||
def foo(self, x: object) -> object:
|
||||
return x
|
||||
class C(B):
|
||||
def foo(self, x: object) -> int:
|
||||
return id(x)
|
||||
|
||||
def use_a(x: A, y: int) -> object:
|
||||
return x.foo(y)
|
||||
|
||||
def use_b(x: B, y: object) -> object:
|
||||
return x.foo(y)
|
||||
|
||||
def use_c(x: C, y: object) -> int:
|
||||
return x.foo(y)
|
||||
[out]
|
||||
def A.foo(self, x):
|
||||
self :: __main__.A
|
||||
x :: int
|
||||
r0 :: str
|
||||
L0:
|
||||
r0 = CPyTagged_Str(x)
|
||||
return r0
|
||||
def B.foo(self, x):
|
||||
self :: __main__.B
|
||||
x :: object
|
||||
L0:
|
||||
return x
|
||||
def B.foo__A_glue(self, x):
|
||||
self :: __main__.B
|
||||
x :: int
|
||||
r0, r1 :: object
|
||||
L0:
|
||||
r0 = box(int, x)
|
||||
r1 = B.foo(self, r0)
|
||||
return r1
|
||||
def C.foo(self, x):
|
||||
self :: __main__.C
|
||||
x :: object
|
||||
r0 :: int
|
||||
L0:
|
||||
r0 = CPyTagged_Id(x)
|
||||
return r0
|
||||
def C.foo__B_glue(self, x):
|
||||
self :: __main__.C
|
||||
x :: object
|
||||
r0 :: int
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = C.foo(self, x)
|
||||
r1 = box(int, r0)
|
||||
return r1
|
||||
def C.foo__A_glue(self, x):
|
||||
self :: __main__.C
|
||||
x :: int
|
||||
r0 :: object
|
||||
r1 :: int
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = box(int, x)
|
||||
r1 = C.foo(self, r0)
|
||||
r2 = box(int, r1)
|
||||
return r2
|
||||
def use_a(x, y):
|
||||
x :: __main__.A
|
||||
y :: int
|
||||
r0 :: object
|
||||
L0:
|
||||
r0 = x.foo(y)
|
||||
return r0
|
||||
def use_b(x, y):
|
||||
x :: __main__.B
|
||||
y, r0 :: object
|
||||
L0:
|
||||
r0 = x.foo(y)
|
||||
return r0
|
||||
def use_c(x, y):
|
||||
x :: __main__.C
|
||||
y :: object
|
||||
r0 :: int
|
||||
L0:
|
||||
r0 = x.foo(y)
|
||||
return r0
|
||||
|
||||
[case testPropertyDerivedGen]
|
||||
from typing import Callable
|
||||
class BaseProperty:
|
||||
@property
|
||||
def value(self) -> object:
|
||||
return self._incrementer
|
||||
|
||||
@property
|
||||
def bad_value(self) -> object:
|
||||
return self._incrementer
|
||||
|
||||
@property
|
||||
def next(self) -> BaseProperty:
|
||||
return BaseProperty(self._incrementer + 1)
|
||||
|
||||
def __init__(self, value: int) -> None:
|
||||
self._incrementer = value
|
||||
|
||||
class DerivedProperty(BaseProperty):
|
||||
@property
|
||||
def value(self) -> int:
|
||||
return self._incrementer
|
||||
|
||||
@property
|
||||
def bad_value(self) -> object:
|
||||
return self._incrementer
|
||||
|
||||
@property
|
||||
def next(self) -> DerivedProperty:
|
||||
return DerivedProperty(self._incr_func, self._incr_func(self.value))
|
||||
|
||||
def __init__(self, incr_func: Callable[[int], int], value: int) -> None:
|
||||
BaseProperty.__init__(self, value)
|
||||
self._incr_func = incr_func
|
||||
|
||||
|
||||
class AgainProperty(DerivedProperty):
|
||||
@property
|
||||
def next(self) -> AgainProperty:
|
||||
return AgainProperty(self._incr_func, self._incr_func(self._incr_func(self.value)))
|
||||
|
||||
@property
|
||||
def bad_value(self) -> int:
|
||||
return self._incrementer
|
||||
[out]
|
||||
def BaseProperty.value(self):
|
||||
self :: __main__.BaseProperty
|
||||
r0 :: int
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = self._incrementer
|
||||
r1 = box(int, r0)
|
||||
return r1
|
||||
def BaseProperty.bad_value(self):
|
||||
self :: __main__.BaseProperty
|
||||
r0 :: int
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = self._incrementer
|
||||
r1 = box(int, r0)
|
||||
return r1
|
||||
def BaseProperty.next(self):
|
||||
self :: __main__.BaseProperty
|
||||
r0, r1 :: int
|
||||
r2 :: __main__.BaseProperty
|
||||
L0:
|
||||
r0 = borrow self._incrementer
|
||||
r1 = CPyTagged_Add(r0, 2)
|
||||
keep_alive self
|
||||
r2 = BaseProperty(r1)
|
||||
return r2
|
||||
def BaseProperty.__init__(self, value):
|
||||
self :: __main__.BaseProperty
|
||||
value :: int
|
||||
L0:
|
||||
self._incrementer = value
|
||||
return 1
|
||||
def DerivedProperty.value(self):
|
||||
self :: __main__.DerivedProperty
|
||||
r0 :: int
|
||||
L0:
|
||||
r0 = self._incrementer
|
||||
return r0
|
||||
def DerivedProperty.value__BaseProperty_glue(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.DerivedProperty
|
||||
r0 :: int
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = __mypyc_self__.value
|
||||
r1 = box(int, r0)
|
||||
return r1
|
||||
def DerivedProperty.bad_value(self):
|
||||
self :: __main__.DerivedProperty
|
||||
r0 :: int
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = self._incrementer
|
||||
r1 = box(int, r0)
|
||||
return r1
|
||||
def DerivedProperty.next(self):
|
||||
self :: __main__.DerivedProperty
|
||||
r0 :: object
|
||||
r1 :: int
|
||||
r2, r3, r4 :: object
|
||||
r5 :: int
|
||||
r6 :: __main__.DerivedProperty
|
||||
L0:
|
||||
r0 = self._incr_func
|
||||
r1 = self.value
|
||||
r2 = self._incr_func
|
||||
r3 = box(int, r1)
|
||||
r4 = PyObject_CallFunctionObjArgs(r2, r3, 0)
|
||||
r5 = unbox(int, r4)
|
||||
r6 = DerivedProperty(r0, r5)
|
||||
return r6
|
||||
def DerivedProperty.next__BaseProperty_glue(__mypyc_self__):
|
||||
__mypyc_self__, r0 :: __main__.DerivedProperty
|
||||
L0:
|
||||
r0 = __mypyc_self__.next
|
||||
return r0
|
||||
def DerivedProperty.__init__(self, incr_func, value):
|
||||
self :: __main__.DerivedProperty
|
||||
incr_func :: object
|
||||
value :: int
|
||||
r0 :: None
|
||||
L0:
|
||||
r0 = BaseProperty.__init__(self, value)
|
||||
self._incr_func = incr_func
|
||||
return 1
|
||||
def AgainProperty.next(self):
|
||||
self :: __main__.AgainProperty
|
||||
r0 :: object
|
||||
r1 :: int
|
||||
r2, r3, r4 :: object
|
||||
r5 :: int
|
||||
r6, r7, r8 :: object
|
||||
r9 :: int
|
||||
r10 :: __main__.AgainProperty
|
||||
L0:
|
||||
r0 = self._incr_func
|
||||
r1 = self.value
|
||||
r2 = self._incr_func
|
||||
r3 = box(int, r1)
|
||||
r4 = PyObject_CallFunctionObjArgs(r2, r3, 0)
|
||||
r5 = unbox(int, r4)
|
||||
r6 = self._incr_func
|
||||
r7 = box(int, r5)
|
||||
r8 = PyObject_CallFunctionObjArgs(r6, r7, 0)
|
||||
r9 = unbox(int, r8)
|
||||
r10 = AgainProperty(r0, r9)
|
||||
return r10
|
||||
def AgainProperty.next__DerivedProperty_glue(__mypyc_self__):
|
||||
__mypyc_self__, r0 :: __main__.AgainProperty
|
||||
L0:
|
||||
r0 = __mypyc_self__.next
|
||||
return r0
|
||||
def AgainProperty.next__BaseProperty_glue(__mypyc_self__):
|
||||
__mypyc_self__, r0 :: __main__.AgainProperty
|
||||
L0:
|
||||
r0 = __mypyc_self__.next
|
||||
return r0
|
||||
def AgainProperty.bad_value(self):
|
||||
self :: __main__.AgainProperty
|
||||
r0 :: int
|
||||
L0:
|
||||
r0 = self._incrementer
|
||||
return r0
|
||||
def AgainProperty.bad_value__DerivedProperty_glue(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.AgainProperty
|
||||
r0 :: int
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = __mypyc_self__.bad_value
|
||||
r1 = box(int, r0)
|
||||
return r1
|
||||
def AgainProperty.bad_value__BaseProperty_glue(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.AgainProperty
|
||||
r0 :: int
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = __mypyc_self__.bad_value
|
||||
r1 = box(int, r0)
|
||||
return r1
|
||||
|
||||
[case testPropertyTraitSubclassing]
|
||||
from mypy_extensions import trait
|
||||
@trait
|
||||
class SubclassedTrait:
|
||||
@property
|
||||
def this(self) -> SubclassedTrait:
|
||||
return self
|
||||
|
||||
@property
|
||||
def boxed(self) -> object:
|
||||
return 3
|
||||
|
||||
class DerivingObject(SubclassedTrait):
|
||||
@property
|
||||
def this(self) -> DerivingObject:
|
||||
return self
|
||||
|
||||
@property
|
||||
def boxed(self) -> int:
|
||||
return 5
|
||||
[out]
|
||||
def SubclassedTrait.this(self):
|
||||
self :: __main__.SubclassedTrait
|
||||
L0:
|
||||
return self
|
||||
def SubclassedTrait.boxed(self):
|
||||
self :: __main__.SubclassedTrait
|
||||
r0 :: object
|
||||
L0:
|
||||
r0 = object 3
|
||||
return r0
|
||||
def DerivingObject.this(self):
|
||||
self :: __main__.DerivingObject
|
||||
L0:
|
||||
return self
|
||||
def DerivingObject.this__SubclassedTrait_glue(__mypyc_self__):
|
||||
__mypyc_self__, r0 :: __main__.DerivingObject
|
||||
L0:
|
||||
r0 = __mypyc_self__.this
|
||||
return r0
|
||||
def DerivingObject.boxed(self):
|
||||
self :: __main__.DerivingObject
|
||||
L0:
|
||||
return 10
|
||||
def DerivingObject.boxed__SubclassedTrait_glue(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.DerivingObject
|
||||
r0 :: int
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = __mypyc_self__.boxed
|
||||
r1 = box(int, r0)
|
||||
return r1
|
||||
|
||||
[case testI64GlueWithExtraDefaultArg]
|
||||
from mypy_extensions import i64
|
||||
|
||||
class C:
|
||||
def f(self) -> None: pass
|
||||
|
||||
class D(C):
|
||||
def f(self, x: i64 = 44) -> None: pass
|
||||
[out]
|
||||
def C.f(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 1
|
||||
def D.f(self, x, __bitmap):
|
||||
self :: __main__.D
|
||||
x :: i64
|
||||
__bitmap, r0 :: u32
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = __bitmap & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
x = 44
|
||||
L2:
|
||||
return 1
|
||||
def D.f__C_glue(self):
|
||||
self :: __main__.D
|
||||
r0 :: None
|
||||
L0:
|
||||
r0 = D.f(self, 0, 0)
|
||||
return r0
|
||||
|
||||
[case testI64GlueWithSecondDefaultArg]
|
||||
from mypy_extensions import i64
|
||||
|
||||
class C:
|
||||
def f(self, x: i64 = 11) -> None: pass
|
||||
class D(C):
|
||||
def f(self, x: i64 = 12, y: i64 = 13) -> None: pass
|
||||
[out]
|
||||
def C.f(self, x, __bitmap):
|
||||
self :: __main__.C
|
||||
x :: i64
|
||||
__bitmap, r0 :: u32
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = __bitmap & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
x = 11
|
||||
L2:
|
||||
return 1
|
||||
def D.f(self, x, y, __bitmap):
|
||||
self :: __main__.D
|
||||
x, y :: i64
|
||||
__bitmap, r0 :: u32
|
||||
r1 :: bit
|
||||
r2 :: u32
|
||||
r3 :: bit
|
||||
L0:
|
||||
r0 = __bitmap & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
x = 12
|
||||
L2:
|
||||
r2 = __bitmap & 2
|
||||
r3 = r2 == 0
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
y = 13
|
||||
L4:
|
||||
return 1
|
||||
def D.f__C_glue(self, x, __bitmap):
|
||||
self :: __main__.D
|
||||
x :: i64
|
||||
__bitmap :: u32
|
||||
r0 :: None
|
||||
L0:
|
||||
r0 = D.f(self, x, 0, __bitmap)
|
||||
return r0
|
||||
|
||||
[case testI64GlueWithInvalidOverride]
|
||||
from mypy_extensions import i64
|
||||
|
||||
class C:
|
||||
def f(self, x: i64, y: i64 = 5) -> None: pass
|
||||
def ff(self, x: int) -> None: pass
|
||||
class CC(C):
|
||||
def f(self, x: i64 = 12, y: i64 = 5) -> None: pass # Line 7
|
||||
def ff(self, x: int = 12) -> None: pass
|
||||
|
||||
class D:
|
||||
def f(self, x: int) -> None: pass
|
||||
class DD(D):
|
||||
def f(self, x: i64) -> None: pass # Line 13
|
||||
|
||||
class E:
|
||||
def f(self, x: i64) -> None: pass
|
||||
class EE(E):
|
||||
def f(self, x: int) -> None: pass # Line 18
|
||||
[out]
|
||||
main:7: error: An argument with type "i64" cannot be given a default value in a method override
|
||||
main:13: error: Incompatible argument type "i64" (base class has type "int")
|
||||
main:18: error: Incompatible argument type "int" (base class has type "i64")
|
||||
@@ -0,0 +1,526 @@
|
||||
# Test cases for i16 native ints. Focus on things that are different from i64; no need to
|
||||
# duplicate all i64 test cases here.
|
||||
|
||||
[case testI16BinaryOp]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def add_op(x: i16, y: i16) -> i16:
|
||||
x = y + x
|
||||
y = x + 5
|
||||
y += x
|
||||
y += 7
|
||||
x = 5 + y
|
||||
return x
|
||||
def compare(x: i16, y: i16) -> None:
|
||||
a = x == y
|
||||
b = x == -5
|
||||
c = x < y
|
||||
d = x < -5
|
||||
e = -5 == x
|
||||
f = -5 < x
|
||||
[out]
|
||||
def add_op(x, y):
|
||||
x, y, r0, r1, r2, r3, r4 :: i16
|
||||
L0:
|
||||
r0 = y + x
|
||||
x = r0
|
||||
r1 = x + 5
|
||||
y = r1
|
||||
r2 = y + x
|
||||
y = r2
|
||||
r3 = y + 7
|
||||
y = r3
|
||||
r4 = 5 + y
|
||||
x = r4
|
||||
return x
|
||||
def compare(x, y):
|
||||
x, y :: i16
|
||||
r0 :: bit
|
||||
a :: bool
|
||||
r1 :: bit
|
||||
b :: bool
|
||||
r2 :: bit
|
||||
c :: bool
|
||||
r3 :: bit
|
||||
d :: bool
|
||||
r4 :: bit
|
||||
e :: bool
|
||||
r5 :: bit
|
||||
f :: bool
|
||||
L0:
|
||||
r0 = x == y
|
||||
a = r0
|
||||
r1 = x == -5
|
||||
b = r1
|
||||
r2 = x < y :: signed
|
||||
c = r2
|
||||
r3 = x < -5 :: signed
|
||||
d = r3
|
||||
r4 = -5 == x
|
||||
e = r4
|
||||
r5 = -5 < x :: signed
|
||||
f = r5
|
||||
return 1
|
||||
|
||||
[case testI16UnaryOp]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def unary(x: i16) -> i16:
|
||||
y = -x
|
||||
x = ~y
|
||||
y = +x
|
||||
return y
|
||||
[out]
|
||||
def unary(x):
|
||||
x, r0, y, r1 :: i16
|
||||
L0:
|
||||
r0 = 0 - x
|
||||
y = r0
|
||||
r1 = y ^ -1
|
||||
x = r1
|
||||
y = x
|
||||
return y
|
||||
|
||||
[case testI16DivisionByConstant]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def div_by_constant(x: i16) -> i16:
|
||||
x = x // 5
|
||||
x //= 17
|
||||
return x
|
||||
[out]
|
||||
def div_by_constant(x):
|
||||
x, r0, r1 :: i16
|
||||
r2, r3, r4 :: bit
|
||||
r5 :: i16
|
||||
r6 :: bit
|
||||
r7, r8, r9 :: i16
|
||||
r10, r11, r12 :: bit
|
||||
r13 :: i16
|
||||
r14 :: bit
|
||||
r15 :: i16
|
||||
L0:
|
||||
r0 = x / 5
|
||||
r1 = r0
|
||||
r2 = x < 0 :: signed
|
||||
r3 = 5 < 0 :: signed
|
||||
r4 = r2 == r3
|
||||
if r4 goto L3 else goto L1 :: bool
|
||||
L1:
|
||||
r5 = r1 * 5
|
||||
r6 = r5 == x
|
||||
if r6 goto L3 else goto L2 :: bool
|
||||
L2:
|
||||
r7 = r1 - 1
|
||||
r1 = r7
|
||||
L3:
|
||||
x = r1
|
||||
r8 = x / 17
|
||||
r9 = r8
|
||||
r10 = x < 0 :: signed
|
||||
r11 = 17 < 0 :: signed
|
||||
r12 = r10 == r11
|
||||
if r12 goto L6 else goto L4 :: bool
|
||||
L4:
|
||||
r13 = r9 * 17
|
||||
r14 = r13 == x
|
||||
if r14 goto L6 else goto L5 :: bool
|
||||
L5:
|
||||
r15 = r9 - 1
|
||||
r9 = r15
|
||||
L6:
|
||||
x = r9
|
||||
return x
|
||||
|
||||
[case testI16ModByConstant]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def mod_by_constant(x: i16) -> i16:
|
||||
x = x % 5
|
||||
x %= 17
|
||||
return x
|
||||
[out]
|
||||
def mod_by_constant(x):
|
||||
x, r0, r1 :: i16
|
||||
r2, r3, r4, r5 :: bit
|
||||
r6, r7, r8 :: i16
|
||||
r9, r10, r11, r12 :: bit
|
||||
r13 :: i16
|
||||
L0:
|
||||
r0 = x % 5
|
||||
r1 = r0
|
||||
r2 = x < 0 :: signed
|
||||
r3 = 5 < 0 :: signed
|
||||
r4 = r2 == r3
|
||||
if r4 goto L3 else goto L1 :: bool
|
||||
L1:
|
||||
r5 = r1 == 0
|
||||
if r5 goto L3 else goto L2 :: bool
|
||||
L2:
|
||||
r6 = r1 + 5
|
||||
r1 = r6
|
||||
L3:
|
||||
x = r1
|
||||
r7 = x % 17
|
||||
r8 = r7
|
||||
r9 = x < 0 :: signed
|
||||
r10 = 17 < 0 :: signed
|
||||
r11 = r9 == r10
|
||||
if r11 goto L6 else goto L4 :: bool
|
||||
L4:
|
||||
r12 = r8 == 0
|
||||
if r12 goto L6 else goto L5 :: bool
|
||||
L5:
|
||||
r13 = r8 + 17
|
||||
r8 = r13
|
||||
L6:
|
||||
x = r8
|
||||
return x
|
||||
|
||||
[case testI16DivModByVariable]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def divmod(x: i16, y: i16) -> i16:
|
||||
a = x // y
|
||||
return a % y
|
||||
[out]
|
||||
def divmod(x, y):
|
||||
x, y, r0, a, r1 :: i16
|
||||
L0:
|
||||
r0 = CPyInt16_Divide(x, y)
|
||||
a = r0
|
||||
r1 = CPyInt16_Remainder(a, y)
|
||||
return r1
|
||||
|
||||
[case testI16BinaryOperationWithOutOfRangeOperand]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def out_of_range(x: i16) -> None:
|
||||
x + (-32769)
|
||||
(-32770) + x
|
||||
x * 32768
|
||||
x + 32767 # OK
|
||||
(-32768) + x # OK
|
||||
[out]
|
||||
main:4: error: Value -32769 is out of range for "i16"
|
||||
main:5: error: Value -32770 is out of range for "i16"
|
||||
main:6: error: Value 32768 is out of range for "i16"
|
||||
|
||||
[case testI16BoxAndUnbox]
|
||||
from typing import Any
|
||||
from mypy_extensions import i16
|
||||
|
||||
def f(x: Any) -> Any:
|
||||
y: i16 = x
|
||||
return y
|
||||
[out]
|
||||
def f(x):
|
||||
x :: object
|
||||
r0, y :: i16
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = unbox(i16, x)
|
||||
y = r0
|
||||
r1 = box(i16, y)
|
||||
return r1
|
||||
|
||||
[case testI16MixedCompare1]
|
||||
from mypy_extensions import i16
|
||||
def f(x: int, y: i16) -> bool:
|
||||
return x == y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: int
|
||||
y :: i16
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6 :: i16
|
||||
r7 :: bit
|
||||
L0:
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = x < 65536 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = x >= -65536 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = x >> 1
|
||||
r5 = truncate r4: native_int to i16
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt16_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
r7 = r6 == y
|
||||
return r7
|
||||
|
||||
[case testI16MixedCompare2]
|
||||
from mypy_extensions import i16
|
||||
def f(x: i16, y: int) -> bool:
|
||||
return x == y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: i16
|
||||
y :: int
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6 :: i16
|
||||
r7 :: bit
|
||||
L0:
|
||||
r0 = y & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = y < 65536 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = y >= -65536 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = y >> 1
|
||||
r5 = truncate r4: native_int to i16
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt16_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
r7 = x == r6
|
||||
return r7
|
||||
|
||||
[case testI16ConvertToInt]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def i16_to_int(a: i16) -> int:
|
||||
return a
|
||||
[out]
|
||||
def i16_to_int(a):
|
||||
a :: i16
|
||||
r0 :: native_int
|
||||
r1 :: int
|
||||
L0:
|
||||
r0 = extend signed a: i16 to native_int
|
||||
r1 = r0 << 1
|
||||
return r1
|
||||
|
||||
[case testI16OperatorAssignmentMixed]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def f(a: i16) -> None:
|
||||
x = 0
|
||||
x += a
|
||||
[out]
|
||||
def f(a):
|
||||
a :: i16
|
||||
x :: int
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6, r7 :: i16
|
||||
r8 :: native_int
|
||||
r9 :: int
|
||||
L0:
|
||||
x = 0
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = x < 65536 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = x >= -65536 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = x >> 1
|
||||
r5 = truncate r4: native_int to i16
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt16_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
r7 = r6 + a
|
||||
r8 = extend signed r7: i16 to native_int
|
||||
r9 = r8 << 1
|
||||
x = r9
|
||||
return 1
|
||||
|
||||
[case testI16InitializeFromLiteral]
|
||||
from mypy_extensions import i16, i64
|
||||
|
||||
def f() -> None:
|
||||
x: i16 = 0
|
||||
y: i16 = -127
|
||||
z: i16 = 5 + 7
|
||||
[out]
|
||||
def f():
|
||||
x, y, z :: i16
|
||||
L0:
|
||||
x = 0
|
||||
y = -127
|
||||
z = 12
|
||||
return 1
|
||||
|
||||
[case testI16ExplicitConversionFromNativeInt]
|
||||
from mypy_extensions import i64, i32, i16
|
||||
|
||||
def from_i16(x: i16) -> i16:
|
||||
return i16(x)
|
||||
|
||||
def from_i32(x: i32) -> i16:
|
||||
return i16(x)
|
||||
|
||||
def from_i64(x: i64) -> i16:
|
||||
return i16(x)
|
||||
[out]
|
||||
def from_i16(x):
|
||||
x :: i16
|
||||
L0:
|
||||
return x
|
||||
def from_i32(x):
|
||||
x :: i32
|
||||
r0 :: i16
|
||||
L0:
|
||||
r0 = truncate x: i32 to i16
|
||||
return r0
|
||||
def from_i64(x):
|
||||
x :: i64
|
||||
r0 :: i16
|
||||
L0:
|
||||
r0 = truncate x: i64 to i16
|
||||
return r0
|
||||
|
||||
[case testI16ExplicitConversionFromInt]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def f(x: int) -> i16:
|
||||
return i16(x)
|
||||
[out]
|
||||
def f(x):
|
||||
x :: int
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6 :: i16
|
||||
L0:
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = x < 65536 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = x >= -65536 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = x >> 1
|
||||
r5 = truncate r4: native_int to i16
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt16_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
return r6
|
||||
|
||||
[case testI16ExplicitConversionFromLiteral]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def f() -> None:
|
||||
x = i16(0)
|
||||
y = i16(11)
|
||||
z = i16(-3)
|
||||
a = i16(32767)
|
||||
b = i16(32768) # Truncate
|
||||
c = i16(-32768)
|
||||
d = i16(-32769) # Truncate
|
||||
[out]
|
||||
def f():
|
||||
x, y, z, a, b, c, d :: i16
|
||||
L0:
|
||||
x = 0
|
||||
y = 11
|
||||
z = -3
|
||||
a = 32767
|
||||
b = -32768
|
||||
c = -32768
|
||||
d = 32767
|
||||
return 1
|
||||
|
||||
[case testI16ExplicitConversionFromVariousTypes]
|
||||
from mypy_extensions import i16
|
||||
|
||||
def bool_to_i16(b: bool) -> i16:
|
||||
return i16(b)
|
||||
|
||||
def str_to_i16(s: str) -> i16:
|
||||
return i16(s)
|
||||
|
||||
class C:
|
||||
def __int__(self) -> i16:
|
||||
return 5
|
||||
|
||||
def instance_to_i16(c: C) -> i16:
|
||||
return i16(c)
|
||||
|
||||
def float_to_i16(x: float) -> i16:
|
||||
return i16(x)
|
||||
[out]
|
||||
def bool_to_i16(b):
|
||||
b :: bool
|
||||
r0 :: i16
|
||||
L0:
|
||||
r0 = extend b: builtins.bool to i16
|
||||
return r0
|
||||
def str_to_i16(s):
|
||||
s :: str
|
||||
r0 :: object
|
||||
r1 :: i16
|
||||
L0:
|
||||
r0 = CPyLong_FromStr(s)
|
||||
r1 = unbox(i16, r0)
|
||||
return r1
|
||||
def C.__int__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 5
|
||||
def instance_to_i16(c):
|
||||
c :: __main__.C
|
||||
r0 :: i16
|
||||
L0:
|
||||
r0 = c.__int__()
|
||||
return r0
|
||||
def float_to_i16(x):
|
||||
x :: float
|
||||
r0 :: int
|
||||
r1 :: native_int
|
||||
r2, r3, r4 :: bit
|
||||
r5 :: native_int
|
||||
r6, r7 :: i16
|
||||
L0:
|
||||
r0 = CPyTagged_FromFloat(x)
|
||||
r1 = r0 & 1
|
||||
r2 = r1 == 0
|
||||
if r2 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r3 = r0 < 65536 :: signed
|
||||
if r3 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r4 = r0 >= -65536 :: signed
|
||||
if r4 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r5 = r0 >> 1
|
||||
r6 = truncate r5: native_int to i16
|
||||
r7 = r6
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt16_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
return r7
|
||||
@@ -0,0 +1,598 @@
|
||||
# Test cases for i32 native ints. Focus on things that are different from i64; no need to
|
||||
# duplicate all i64 test cases here.
|
||||
|
||||
[case testI32BinaryOp]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def add_op(x: i32, y: i32) -> i32:
|
||||
x = y + x
|
||||
y = x + 5
|
||||
y += x
|
||||
y += 7
|
||||
x = 5 + y
|
||||
return x
|
||||
def compare(x: i32, y: i32) -> None:
|
||||
a = x == y
|
||||
b = x == -5
|
||||
c = x < y
|
||||
d = x < -5
|
||||
e = -5 == x
|
||||
f = -5 < x
|
||||
[out]
|
||||
def add_op(x, y):
|
||||
x, y, r0, r1, r2, r3, r4 :: i32
|
||||
L0:
|
||||
r0 = y + x
|
||||
x = r0
|
||||
r1 = x + 5
|
||||
y = r1
|
||||
r2 = y + x
|
||||
y = r2
|
||||
r3 = y + 7
|
||||
y = r3
|
||||
r4 = 5 + y
|
||||
x = r4
|
||||
return x
|
||||
def compare(x, y):
|
||||
x, y :: i32
|
||||
r0 :: bit
|
||||
a :: bool
|
||||
r1 :: bit
|
||||
b :: bool
|
||||
r2 :: bit
|
||||
c :: bool
|
||||
r3 :: bit
|
||||
d :: bool
|
||||
r4 :: bit
|
||||
e :: bool
|
||||
r5 :: bit
|
||||
f :: bool
|
||||
L0:
|
||||
r0 = x == y
|
||||
a = r0
|
||||
r1 = x == -5
|
||||
b = r1
|
||||
r2 = x < y :: signed
|
||||
c = r2
|
||||
r3 = x < -5 :: signed
|
||||
d = r3
|
||||
r4 = -5 == x
|
||||
e = r4
|
||||
r5 = -5 < x :: signed
|
||||
f = r5
|
||||
return 1
|
||||
|
||||
[case testI32UnaryOp]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def unary(x: i32) -> i32:
|
||||
y = -x
|
||||
x = ~y
|
||||
y = +x
|
||||
return y
|
||||
[out]
|
||||
def unary(x):
|
||||
x, r0, y, r1 :: i32
|
||||
L0:
|
||||
r0 = 0 - x
|
||||
y = r0
|
||||
r1 = y ^ -1
|
||||
x = r1
|
||||
y = x
|
||||
return y
|
||||
|
||||
[case testI32DivisionByConstant]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def div_by_constant(x: i32) -> i32:
|
||||
x = x // 5
|
||||
x //= 17
|
||||
return x
|
||||
[out]
|
||||
def div_by_constant(x):
|
||||
x, r0, r1 :: i32
|
||||
r2, r3, r4 :: bit
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
r7, r8, r9 :: i32
|
||||
r10, r11, r12 :: bit
|
||||
r13 :: i32
|
||||
r14 :: bit
|
||||
r15 :: i32
|
||||
L0:
|
||||
r0 = x / 5
|
||||
r1 = r0
|
||||
r2 = x < 0 :: signed
|
||||
r3 = 5 < 0 :: signed
|
||||
r4 = r2 == r3
|
||||
if r4 goto L3 else goto L1 :: bool
|
||||
L1:
|
||||
r5 = r1 * 5
|
||||
r6 = r5 == x
|
||||
if r6 goto L3 else goto L2 :: bool
|
||||
L2:
|
||||
r7 = r1 - 1
|
||||
r1 = r7
|
||||
L3:
|
||||
x = r1
|
||||
r8 = x / 17
|
||||
r9 = r8
|
||||
r10 = x < 0 :: signed
|
||||
r11 = 17 < 0 :: signed
|
||||
r12 = r10 == r11
|
||||
if r12 goto L6 else goto L4 :: bool
|
||||
L4:
|
||||
r13 = r9 * 17
|
||||
r14 = r13 == x
|
||||
if r14 goto L6 else goto L5 :: bool
|
||||
L5:
|
||||
r15 = r9 - 1
|
||||
r9 = r15
|
||||
L6:
|
||||
x = r9
|
||||
return x
|
||||
|
||||
[case testI32ModByConstant]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def mod_by_constant(x: i32) -> i32:
|
||||
x = x % 5
|
||||
x %= 17
|
||||
return x
|
||||
[out]
|
||||
def mod_by_constant(x):
|
||||
x, r0, r1 :: i32
|
||||
r2, r3, r4, r5 :: bit
|
||||
r6, r7, r8 :: i32
|
||||
r9, r10, r11, r12 :: bit
|
||||
r13 :: i32
|
||||
L0:
|
||||
r0 = x % 5
|
||||
r1 = r0
|
||||
r2 = x < 0 :: signed
|
||||
r3 = 5 < 0 :: signed
|
||||
r4 = r2 == r3
|
||||
if r4 goto L3 else goto L1 :: bool
|
||||
L1:
|
||||
r5 = r1 == 0
|
||||
if r5 goto L3 else goto L2 :: bool
|
||||
L2:
|
||||
r6 = r1 + 5
|
||||
r1 = r6
|
||||
L3:
|
||||
x = r1
|
||||
r7 = x % 17
|
||||
r8 = r7
|
||||
r9 = x < 0 :: signed
|
||||
r10 = 17 < 0 :: signed
|
||||
r11 = r9 == r10
|
||||
if r11 goto L6 else goto L4 :: bool
|
||||
L4:
|
||||
r12 = r8 == 0
|
||||
if r12 goto L6 else goto L5 :: bool
|
||||
L5:
|
||||
r13 = r8 + 17
|
||||
r8 = r13
|
||||
L6:
|
||||
x = r8
|
||||
return x
|
||||
|
||||
[case testI32DivModByVariable]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def divmod(x: i32, y: i32) -> i32:
|
||||
a = x // y
|
||||
return a % y
|
||||
[out]
|
||||
def divmod(x, y):
|
||||
x, y, r0, a, r1 :: i32
|
||||
L0:
|
||||
r0 = CPyInt32_Divide(x, y)
|
||||
a = r0
|
||||
r1 = CPyInt32_Remainder(a, y)
|
||||
return r1
|
||||
|
||||
[case testI32BoxAndUnbox]
|
||||
from typing import Any
|
||||
from mypy_extensions import i32
|
||||
|
||||
def f(x: Any) -> Any:
|
||||
y: i32 = x
|
||||
return y
|
||||
[out]
|
||||
def f(x):
|
||||
x :: object
|
||||
r0, y :: i32
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = unbox(i32, x)
|
||||
y = r0
|
||||
r1 = box(i32, y)
|
||||
return r1
|
||||
|
||||
[case testI32MixedCompare1_64bit]
|
||||
from mypy_extensions import i32
|
||||
def f(x: int, y: i32) -> bool:
|
||||
return x == y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: int
|
||||
y :: i32
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6 :: i32
|
||||
r7 :: bit
|
||||
L0:
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = x < 4294967296 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = x >= -4294967296 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = x >> 1
|
||||
r5 = truncate r4: native_int to i32
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt32_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
r7 = r6 == y
|
||||
return r7
|
||||
|
||||
[case testI32MixedCompare2_64bit]
|
||||
from mypy_extensions import i32
|
||||
def f(x: i32, y: int) -> bool:
|
||||
return x == y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: i32
|
||||
y :: int
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6 :: i32
|
||||
r7 :: bit
|
||||
L0:
|
||||
r0 = y & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = y < 4294967296 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = y >= -4294967296 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = y >> 1
|
||||
r5 = truncate r4: native_int to i32
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt32_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
r7 = x == r6
|
||||
return r7
|
||||
|
||||
[case testI32MixedCompare_32bit]
|
||||
from mypy_extensions import i32
|
||||
def f(x: int, y: i32) -> bool:
|
||||
return x == y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: int
|
||||
y :: i32
|
||||
r0 :: native_int
|
||||
r1 :: bit
|
||||
r2, r3 :: i32
|
||||
r4 :: ptr
|
||||
r5 :: c_ptr
|
||||
r6 :: i32
|
||||
r7 :: bit
|
||||
L0:
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r2 = x >> 1
|
||||
r3 = r2
|
||||
goto L3
|
||||
L2:
|
||||
r4 = x ^ 1
|
||||
r5 = r4
|
||||
r6 = CPyLong_AsInt32(r5)
|
||||
r3 = r6
|
||||
keep_alive x
|
||||
L3:
|
||||
r7 = r3 == y
|
||||
return r7
|
||||
|
||||
[case testI32ConvertToInt_64bit]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def i32_to_int(a: i32) -> int:
|
||||
return a
|
||||
[out]
|
||||
def i32_to_int(a):
|
||||
a :: i32
|
||||
r0 :: native_int
|
||||
r1 :: int
|
||||
L0:
|
||||
r0 = extend signed a: i32 to native_int
|
||||
r1 = r0 << 1
|
||||
return r1
|
||||
|
||||
[case testI32ConvertToInt_32bit]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def i32_to_int(a: i32) -> int:
|
||||
return a
|
||||
[out]
|
||||
def i32_to_int(a):
|
||||
a :: i32
|
||||
r0, r1 :: bit
|
||||
r2, r3, r4 :: int
|
||||
L0:
|
||||
r0 = a <= 1073741823 :: signed
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r1 = a >= -1073741824 :: signed
|
||||
if r1 goto L3 else goto L2 :: bool
|
||||
L2:
|
||||
r2 = CPyTagged_FromSsize_t(a)
|
||||
r3 = r2
|
||||
goto L4
|
||||
L3:
|
||||
r4 = a << 1
|
||||
r3 = r4
|
||||
L4:
|
||||
return r3
|
||||
|
||||
[case testI32OperatorAssignmentMixed_64bit]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def f(a: i32) -> None:
|
||||
x = 0
|
||||
x += a
|
||||
[out]
|
||||
def f(a):
|
||||
a :: i32
|
||||
x :: int
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6, r7 :: i32
|
||||
r8 :: native_int
|
||||
r9 :: int
|
||||
L0:
|
||||
x = 0
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = x < 4294967296 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = x >= -4294967296 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = x >> 1
|
||||
r5 = truncate r4: native_int to i32
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt32_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
r7 = r6 + a
|
||||
r8 = extend signed r7: i32 to native_int
|
||||
r9 = r8 << 1
|
||||
x = r9
|
||||
return 1
|
||||
|
||||
[case testI32InitializeFromLiteral]
|
||||
from mypy_extensions import i32, i64
|
||||
|
||||
def f() -> None:
|
||||
x: i32 = 0
|
||||
y: i32 = -127
|
||||
z: i32 = 5 + 7
|
||||
[out]
|
||||
def f():
|
||||
x, y, z :: i32
|
||||
L0:
|
||||
x = 0
|
||||
y = -127
|
||||
z = 12
|
||||
return 1
|
||||
|
||||
[case testI32ExplicitConversionFromNativeInt]
|
||||
from mypy_extensions import i64, i32, i16
|
||||
|
||||
def from_i16(x: i16) -> i32:
|
||||
return i32(x)
|
||||
|
||||
def from_i32(x: i32) -> i32:
|
||||
return i32(x)
|
||||
|
||||
def from_i64(x: i64) -> i32:
|
||||
return i32(x)
|
||||
[out]
|
||||
def from_i16(x):
|
||||
x :: i16
|
||||
r0 :: i32
|
||||
L0:
|
||||
r0 = extend signed x: i16 to i32
|
||||
return r0
|
||||
def from_i32(x):
|
||||
x :: i32
|
||||
L0:
|
||||
return x
|
||||
def from_i64(x):
|
||||
x :: i64
|
||||
r0 :: i32
|
||||
L0:
|
||||
r0 = truncate x: i64 to i32
|
||||
return r0
|
||||
|
||||
[case testI32ExplicitConversionFromInt_64bit]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def f(x: int) -> i32:
|
||||
return i32(x)
|
||||
[out]
|
||||
def f(x):
|
||||
x :: int
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6 :: i32
|
||||
L0:
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = x < 4294967296 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = x >= -4294967296 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = x >> 1
|
||||
r5 = truncate r4: native_int to i32
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt32_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
return r6
|
||||
|
||||
[case testI32ExplicitConversionFromLiteral_64bit]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def f() -> None:
|
||||
x = i32(0)
|
||||
y = i32(11)
|
||||
z = i32(-3)
|
||||
a = i32(2**31)
|
||||
[out]
|
||||
def f():
|
||||
x, y, z, a :: i32
|
||||
L0:
|
||||
x = 0
|
||||
y = 11
|
||||
z = -3
|
||||
a = -2147483648
|
||||
return 1
|
||||
|
||||
[case testI32ExplicitConversionFromVariousTypes_64bit]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def bool_to_i32(b: bool) -> i32:
|
||||
return i32(b)
|
||||
|
||||
def str_to_i32(s: str) -> i32:
|
||||
return i32(s)
|
||||
|
||||
class C:
|
||||
def __int__(self) -> i32:
|
||||
return 5
|
||||
|
||||
def instance_to_i32(c: C) -> i32:
|
||||
return i32(c)
|
||||
|
||||
def float_to_i32(x: float) -> i32:
|
||||
return i32(x)
|
||||
[out]
|
||||
def bool_to_i32(b):
|
||||
b :: bool
|
||||
r0 :: i32
|
||||
L0:
|
||||
r0 = extend b: builtins.bool to i32
|
||||
return r0
|
||||
def str_to_i32(s):
|
||||
s :: str
|
||||
r0 :: object
|
||||
r1 :: i32
|
||||
L0:
|
||||
r0 = CPyLong_FromStr(s)
|
||||
r1 = unbox(i32, r0)
|
||||
return r1
|
||||
def C.__int__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 5
|
||||
def instance_to_i32(c):
|
||||
c :: __main__.C
|
||||
r0 :: i32
|
||||
L0:
|
||||
r0 = c.__int__()
|
||||
return r0
|
||||
def float_to_i32(x):
|
||||
x :: float
|
||||
r0 :: int
|
||||
r1 :: native_int
|
||||
r2, r3, r4 :: bit
|
||||
r5 :: native_int
|
||||
r6, r7 :: i32
|
||||
L0:
|
||||
r0 = CPyTagged_FromFloat(x)
|
||||
r1 = r0 & 1
|
||||
r2 = r1 == 0
|
||||
if r2 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r3 = r0 < 4294967296 :: signed
|
||||
if r3 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r4 = r0 >= -4294967296 :: signed
|
||||
if r4 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r5 = r0 >> 1
|
||||
r6 = truncate r5: native_int to i32
|
||||
r7 = r6
|
||||
goto L5
|
||||
L4:
|
||||
CPyInt32_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
return r7
|
||||
|
||||
[case testI32ExplicitConversionFromFloat_32bit]
|
||||
from mypy_extensions import i32
|
||||
|
||||
def float_to_i32(x: float) -> i32:
|
||||
return i32(x)
|
||||
[out]
|
||||
def float_to_i32(x):
|
||||
x :: float
|
||||
r0 :: int
|
||||
r1 :: native_int
|
||||
r2 :: bit
|
||||
r3, r4 :: i32
|
||||
r5 :: ptr
|
||||
r6 :: c_ptr
|
||||
r7 :: i32
|
||||
L0:
|
||||
r0 = CPyTagged_FromFloat(x)
|
||||
r1 = r0 & 1
|
||||
r2 = r1 == 0
|
||||
if r2 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r3 = r0 >> 1
|
||||
r4 = r3
|
||||
goto L3
|
||||
L2:
|
||||
r5 = r0 ^ 1
|
||||
r6 = r5
|
||||
r7 = CPyLong_AsInt32(r6)
|
||||
r4 = r7
|
||||
keep_alive r0
|
||||
L3:
|
||||
return r4
|
||||
2164
venv/lib/python3.12/site-packages/mypyc/test-data/irbuild-i64.test
Normal file
2164
venv/lib/python3.12/site-packages/mypyc/test-data/irbuild-i64.test
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,235 @@
|
||||
[case testIntNeq]
|
||||
def f(x: int, y: int) -> bool:
|
||||
return x != y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y :: int
|
||||
r0 :: native_int
|
||||
r1, r2 :: bit
|
||||
r3 :: bool
|
||||
r4, r5 :: bit
|
||||
L0:
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r2 = x != y
|
||||
r3 = r2
|
||||
goto L3
|
||||
L2:
|
||||
r4 = CPyTagged_IsEq_(x, y)
|
||||
r5 = r4 ^ 1
|
||||
r3 = r5
|
||||
L3:
|
||||
return r3
|
||||
|
||||
[case testShortIntComparisons]
|
||||
def f(x: int) -> int:
|
||||
if x == 3:
|
||||
return 1
|
||||
elif x != 4:
|
||||
return 2
|
||||
elif 5 == x:
|
||||
return 3
|
||||
elif 6 != x:
|
||||
return 4
|
||||
elif x < 4:
|
||||
return 5
|
||||
return 6
|
||||
[out]
|
||||
def f(x):
|
||||
x :: int
|
||||
r0, r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6, r7 :: bit
|
||||
L0:
|
||||
r0 = x == 6
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return 2
|
||||
L2:
|
||||
r1 = x != 8
|
||||
if r1 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
return 4
|
||||
L4:
|
||||
r2 = 10 == x
|
||||
if r2 goto L5 else goto L6 :: bool
|
||||
L5:
|
||||
return 6
|
||||
L6:
|
||||
r3 = 12 != x
|
||||
if r3 goto L7 else goto L8 :: bool
|
||||
L7:
|
||||
return 8
|
||||
L8:
|
||||
r4 = x & 1
|
||||
r5 = r4 != 0
|
||||
if r5 goto L9 else goto L10 :: bool
|
||||
L9:
|
||||
r6 = CPyTagged_IsLt_(x, 8)
|
||||
if r6 goto L11 else goto L12 :: bool
|
||||
L10:
|
||||
r7 = x < 8 :: signed
|
||||
if r7 goto L11 else goto L12 :: bool
|
||||
L11:
|
||||
return 10
|
||||
L12:
|
||||
L13:
|
||||
L14:
|
||||
L15:
|
||||
L16:
|
||||
return 12
|
||||
|
||||
[case testIntMin]
|
||||
def f(x: int, y: int) -> int:
|
||||
return min(x, y)
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y :: int
|
||||
r0 :: native_int
|
||||
r1 :: bit
|
||||
r2 :: native_int
|
||||
r3, r4, r5 :: bit
|
||||
r6 :: bool
|
||||
r7 :: bit
|
||||
r8 :: int
|
||||
L0:
|
||||
r0 = y & 1
|
||||
r1 = r0 == 0
|
||||
r2 = x & 1
|
||||
r3 = r2 == 0
|
||||
r4 = r1 & r3
|
||||
if r4 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r5 = y < x :: signed
|
||||
r6 = r5
|
||||
goto L3
|
||||
L2:
|
||||
r7 = CPyTagged_IsLt_(y, x)
|
||||
r6 = r7
|
||||
L3:
|
||||
if r6 goto L4 else goto L5 :: bool
|
||||
L4:
|
||||
r8 = y
|
||||
goto L6
|
||||
L5:
|
||||
r8 = x
|
||||
L6:
|
||||
return r8
|
||||
|
||||
[case testIntFloorDivideByPowerOfTwo]
|
||||
def divby1(x: int) -> int:
|
||||
return x // 1
|
||||
def divby2(x: int) -> int:
|
||||
return x // 2
|
||||
def divby3(x: int) -> int:
|
||||
return x // 3
|
||||
def divby4(x: int) -> int:
|
||||
return x // 4
|
||||
def divby8(x: int) -> int:
|
||||
return x // 8
|
||||
[out]
|
||||
def divby1(x):
|
||||
x, r0 :: int
|
||||
L0:
|
||||
r0 = CPyTagged_FloorDivide(x, 2)
|
||||
return r0
|
||||
def divby2(x):
|
||||
x, r0 :: int
|
||||
L0:
|
||||
r0 = CPyTagged_Rshift(x, 2)
|
||||
return r0
|
||||
def divby3(x):
|
||||
x, r0 :: int
|
||||
L0:
|
||||
r0 = CPyTagged_FloorDivide(x, 6)
|
||||
return r0
|
||||
def divby4(x):
|
||||
x, r0 :: int
|
||||
L0:
|
||||
r0 = CPyTagged_Rshift(x, 4)
|
||||
return r0
|
||||
def divby8(x):
|
||||
x, r0 :: int
|
||||
L0:
|
||||
r0 = CPyTagged_Rshift(x, 6)
|
||||
return r0
|
||||
|
||||
[case testFinalConstantFolding]
|
||||
from typing_extensions import Final
|
||||
|
||||
X: Final = -1
|
||||
Y: Final = -(1 + 3*2)
|
||||
Z: Final = Y + 1
|
||||
|
||||
class C:
|
||||
A: Final = 1
|
||||
B: Final = -1
|
||||
|
||||
def f1() -> int:
|
||||
return X
|
||||
|
||||
def f2() -> int:
|
||||
return X + Y
|
||||
|
||||
def f3() -> int:
|
||||
return Z
|
||||
|
||||
def f4() -> int:
|
||||
return C.A
|
||||
|
||||
def f5() -> int:
|
||||
return C.B
|
||||
[out]
|
||||
def C.__mypyc_defaults_setup(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.C
|
||||
L0:
|
||||
__mypyc_self__.A = 2
|
||||
__mypyc_self__.B = -2
|
||||
return 1
|
||||
def f1():
|
||||
L0:
|
||||
return -2
|
||||
def f2():
|
||||
L0:
|
||||
return -16
|
||||
def f3():
|
||||
L0:
|
||||
return -12
|
||||
def f4():
|
||||
L0:
|
||||
return 2
|
||||
def f5():
|
||||
L0:
|
||||
return -2
|
||||
|
||||
[case testConvertIntegralToInt]
|
||||
def bool_to_int(b: bool) -> int:
|
||||
return int(b)
|
||||
|
||||
def int_to_int(n: int) -> int:
|
||||
return int(n)
|
||||
[out]
|
||||
def bool_to_int(b):
|
||||
b, r0 :: bool
|
||||
r1 :: int
|
||||
L0:
|
||||
r0 = b << 1
|
||||
r1 = extend r0: builtins.bool to builtins.int
|
||||
return r1
|
||||
def int_to_int(n):
|
||||
n :: int
|
||||
L0:
|
||||
return n
|
||||
|
||||
[case testIntUnaryPlus]
|
||||
def unary_plus(n: int) -> int:
|
||||
x = +n
|
||||
return x
|
||||
[out]
|
||||
def unary_plus(n):
|
||||
n, x :: int
|
||||
L0:
|
||||
x = n
|
||||
return x
|
||||
@@ -0,0 +1,109 @@
|
||||
[case testIsinstanceInt]
|
||||
def is_int(value: object) -> bool:
|
||||
return isinstance(value, int)
|
||||
|
||||
[out]
|
||||
def is_int(value):
|
||||
value, r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3 :: bool
|
||||
L0:
|
||||
r0 = load_address PyLong_Type
|
||||
r1 = PyObject_IsInstance(value, r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
return r3
|
||||
|
||||
[case testIsinstanceNotBool1]
|
||||
def is_not_bool(value: object) -> bool:
|
||||
return not isinstance(value, bool)
|
||||
|
||||
[out]
|
||||
def is_not_bool(value):
|
||||
value, r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3, r4 :: bool
|
||||
L0:
|
||||
r0 = load_address PyBool_Type
|
||||
r1 = PyObject_IsInstance(value, r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
r4 = r3 ^ 1
|
||||
return r4
|
||||
|
||||
[case testIsinstanceIntAndNotBool]
|
||||
# This test is to ensure that 'value' doesn't get coerced to int when we are
|
||||
# checking if it's a bool, since an int can never be an instance of a bool
|
||||
def is_not_bool_and_is_int(value: object) -> bool:
|
||||
return isinstance(value, int) and not isinstance(value, bool)
|
||||
|
||||
[out]
|
||||
def is_not_bool_and_is_int(value):
|
||||
value, r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3, r4 :: bool
|
||||
r5 :: object
|
||||
r6 :: i32
|
||||
r7 :: bit
|
||||
r8, r9 :: bool
|
||||
L0:
|
||||
r0 = load_address PyLong_Type
|
||||
r1 = PyObject_IsInstance(value, r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
if r3 goto L2 else goto L1 :: bool
|
||||
L1:
|
||||
r4 = r3
|
||||
goto L3
|
||||
L2:
|
||||
r5 = load_address PyBool_Type
|
||||
r6 = PyObject_IsInstance(value, r5)
|
||||
r7 = r6 >= 0 :: signed
|
||||
r8 = truncate r6: i32 to builtins.bool
|
||||
r9 = r8 ^ 1
|
||||
r4 = r9
|
||||
L3:
|
||||
return r4
|
||||
|
||||
[case testBorrowSpecialCaseWithIsinstance]
|
||||
class C:
|
||||
s: str
|
||||
|
||||
def g() -> object:
|
||||
pass
|
||||
|
||||
def f() -> None:
|
||||
x = g()
|
||||
if isinstance(x, C):
|
||||
x.s
|
||||
[out]
|
||||
def g():
|
||||
r0 :: object
|
||||
L0:
|
||||
r0 = box(None, 1)
|
||||
return r0
|
||||
def f():
|
||||
r0, x, r1 :: object
|
||||
r2 :: ptr
|
||||
r3 :: object
|
||||
r4 :: bit
|
||||
r5 :: __main__.C
|
||||
r6 :: str
|
||||
L0:
|
||||
r0 = g()
|
||||
x = r0
|
||||
r1 = __main__.C :: type
|
||||
r2 = get_element_ptr x ob_type :: PyObject
|
||||
r3 = load_mem r2 :: builtins.object*
|
||||
keep_alive x
|
||||
r4 = r3 == r1
|
||||
if r4 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r5 = borrow cast(__main__.C, x)
|
||||
r6 = r5.s
|
||||
keep_alive x
|
||||
L2:
|
||||
return 1
|
||||
@@ -0,0 +1,547 @@
|
||||
[case testListGet]
|
||||
from typing import List
|
||||
def f(x: List[int]) -> int:
|
||||
return x[0]
|
||||
[out]
|
||||
def f(x):
|
||||
x :: list
|
||||
r0 :: object
|
||||
r1 :: int
|
||||
L0:
|
||||
r0 = CPyList_GetItemShort(x, 0)
|
||||
r1 = unbox(int, r0)
|
||||
return r1
|
||||
|
||||
[case testListOfListGet]
|
||||
from typing import List
|
||||
def f(x: List[List[int]]) -> List[int]:
|
||||
return x[0]
|
||||
[out]
|
||||
def f(x):
|
||||
x :: list
|
||||
r0 :: object
|
||||
r1 :: list
|
||||
L0:
|
||||
r0 = CPyList_GetItemShort(x, 0)
|
||||
r1 = cast(list, r0)
|
||||
return r1
|
||||
|
||||
[case testListOfListGet2]
|
||||
from typing import List
|
||||
def f(x: List[List[int]]) -> int:
|
||||
return x[0][1]
|
||||
[out]
|
||||
def f(x):
|
||||
x :: list
|
||||
r0 :: object
|
||||
r1 :: list
|
||||
r2 :: object
|
||||
r3 :: int
|
||||
L0:
|
||||
r0 = CPyList_GetItemShortBorrow(x, 0)
|
||||
r1 = borrow cast(list, r0)
|
||||
r2 = CPyList_GetItemShort(r1, 2)
|
||||
r3 = unbox(int, r2)
|
||||
keep_alive x, r0
|
||||
return r3
|
||||
|
||||
[case testListSet]
|
||||
from typing import List
|
||||
def f(x: List[int]) -> None:
|
||||
x[0] = 1
|
||||
[out]
|
||||
def f(x):
|
||||
x :: list
|
||||
r0 :: object
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = object 1
|
||||
r1 = CPyList_SetItem(x, 0, r0)
|
||||
return 1
|
||||
|
||||
[case testNewListEmpty]
|
||||
from typing import List
|
||||
def f() -> None:
|
||||
x = [] # type: List[int]
|
||||
[out]
|
||||
def f():
|
||||
r0, x :: list
|
||||
L0:
|
||||
r0 = PyList_New(0)
|
||||
x = r0
|
||||
return 1
|
||||
|
||||
[case testNewListEmptyViaFunc]
|
||||
from typing import List
|
||||
def f() -> None:
|
||||
x: List[int] = list()
|
||||
|
||||
[out]
|
||||
def f():
|
||||
r0, x :: list
|
||||
L0:
|
||||
r0 = PyList_New(0)
|
||||
x = r0
|
||||
return 1
|
||||
|
||||
[case testNewListEmptyViaAlias]
|
||||
from typing import List
|
||||
|
||||
ListAlias = list
|
||||
|
||||
def f() -> None:
|
||||
x: List[int] = ListAlias()
|
||||
|
||||
[out]
|
||||
def f():
|
||||
r0, x :: list
|
||||
L0:
|
||||
r0 = PyList_New(0)
|
||||
x = r0
|
||||
return 1
|
||||
|
||||
[case testNewListTwoItems]
|
||||
from typing import List
|
||||
def f() -> None:
|
||||
x: List[int] = [1, 2]
|
||||
[out]
|
||||
def f():
|
||||
r0 :: list
|
||||
r1, r2 :: object
|
||||
r3, r4, r5 :: ptr
|
||||
x :: list
|
||||
L0:
|
||||
r0 = PyList_New(2)
|
||||
r1 = object 1
|
||||
r2 = object 2
|
||||
r3 = get_element_ptr r0 ob_item :: PyListObject
|
||||
r4 = load_mem r3 :: ptr*
|
||||
set_mem r4, r1 :: builtins.object*
|
||||
r5 = r4 + WORD_SIZE*1
|
||||
set_mem r5, r2 :: builtins.object*
|
||||
keep_alive r0
|
||||
x = r0
|
||||
return 1
|
||||
|
||||
[case testNewListTenItems]
|
||||
from typing import List
|
||||
def f() -> None:
|
||||
x: List[str] = ['a', 'b', 'c', 'd', 'e',
|
||||
'f', 'g', 'h', 'i', 'j']
|
||||
[out]
|
||||
def f():
|
||||
r0, r1, r2, r3, r4, r5, r6, r7, r8, r9 :: str
|
||||
r10, x :: list
|
||||
L0:
|
||||
r0 = 'a'
|
||||
r1 = 'b'
|
||||
r2 = 'c'
|
||||
r3 = 'd'
|
||||
r4 = 'e'
|
||||
r5 = 'f'
|
||||
r6 = 'g'
|
||||
r7 = 'h'
|
||||
r8 = 'i'
|
||||
r9 = 'j'
|
||||
r10 = CPyList_Build(10, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9)
|
||||
x = r10
|
||||
return 1
|
||||
|
||||
[case testListMultiply]
|
||||
from typing import List
|
||||
def f(a: List[int]) -> None:
|
||||
b = a * 2
|
||||
b = 3 * [4]
|
||||
[out]
|
||||
def f(a):
|
||||
a, r0, b, r1 :: list
|
||||
r2 :: object
|
||||
r3, r4 :: ptr
|
||||
r5 :: list
|
||||
L0:
|
||||
r0 = CPySequence_Multiply(a, 4)
|
||||
b = r0
|
||||
r1 = PyList_New(1)
|
||||
r2 = object 4
|
||||
r3 = get_element_ptr r1 ob_item :: PyListObject
|
||||
r4 = load_mem r3 :: ptr*
|
||||
set_mem r4, r2 :: builtins.object*
|
||||
keep_alive r1
|
||||
r5 = CPySequence_RMultiply(6, r1)
|
||||
b = r5
|
||||
return 1
|
||||
|
||||
[case testListLen]
|
||||
from typing import List
|
||||
def f(a: List[int]) -> int:
|
||||
return len(a)
|
||||
[out]
|
||||
def f(a):
|
||||
a :: list
|
||||
r0 :: ptr
|
||||
r1 :: native_int
|
||||
r2 :: short_int
|
||||
L0:
|
||||
r0 = get_element_ptr a ob_size :: PyVarObject
|
||||
r1 = load_mem r0 :: native_int*
|
||||
keep_alive a
|
||||
r2 = r1 << 1
|
||||
return r2
|
||||
|
||||
[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:
|
||||
r0 = box(int, x)
|
||||
r1 = PyList_Append(a, r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
return 1
|
||||
|
||||
[case testIndexLvalue]
|
||||
from typing import List
|
||||
def increment(l: List[int]) -> List[int]:
|
||||
for i in range(len(l)):
|
||||
l[i] += 1
|
||||
return l
|
||||
[out]
|
||||
def increment(l):
|
||||
l :: list
|
||||
r0 :: ptr
|
||||
r1 :: native_int
|
||||
r2, r3 :: short_int
|
||||
i :: int
|
||||
r4 :: bit
|
||||
r5, r6, r7 :: object
|
||||
r8 :: bit
|
||||
r9 :: short_int
|
||||
L0:
|
||||
r0 = get_element_ptr l ob_size :: PyVarObject
|
||||
r1 = load_mem r0 :: native_int*
|
||||
keep_alive l
|
||||
r2 = r1 << 1
|
||||
r3 = 0
|
||||
i = r3
|
||||
L1:
|
||||
r4 = r3 < r2 :: signed
|
||||
if r4 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r5 = CPyList_GetItem(l, i)
|
||||
r6 = object 1
|
||||
r7 = PyNumber_InPlaceAdd(r5, r6)
|
||||
r8 = CPyList_SetItem(l, i, r7)
|
||||
L3:
|
||||
r9 = r3 + 2
|
||||
r3 = r9
|
||||
i = r9
|
||||
goto L1
|
||||
L4:
|
||||
return l
|
||||
|
||||
[case testListDisplay]
|
||||
from typing import List
|
||||
def f(x: List[int], y: List[int]) -> List[int]:
|
||||
return [1, 2, *x, *y, 3]
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y, r0 :: list
|
||||
r1, r2 :: object
|
||||
r3, r4, r5 :: ptr
|
||||
r6, r7, r8 :: object
|
||||
r9 :: i32
|
||||
r10 :: bit
|
||||
L0:
|
||||
r0 = PyList_New(2)
|
||||
r1 = object 1
|
||||
r2 = object 2
|
||||
r3 = get_element_ptr r0 ob_item :: PyListObject
|
||||
r4 = load_mem r3 :: ptr*
|
||||
set_mem r4, r1 :: builtins.object*
|
||||
r5 = r4 + WORD_SIZE*1
|
||||
set_mem r5, r2 :: builtins.object*
|
||||
keep_alive r0
|
||||
r6 = CPyList_Extend(r0, x)
|
||||
r7 = CPyList_Extend(r0, y)
|
||||
r8 = object 3
|
||||
r9 = PyList_Append(r0, r8)
|
||||
r10 = r9 >= 0 :: signed
|
||||
return r0
|
||||
|
||||
[case testListIn]
|
||||
from typing import List
|
||||
def f(x: List[int], y: int) -> bool:
|
||||
return y in x
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: list
|
||||
y :: int
|
||||
r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3 :: bool
|
||||
L0:
|
||||
r0 = box(int, y)
|
||||
r1 = PySequence_Contains(x, r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
return r3
|
||||
|
||||
[case testListInsert]
|
||||
from typing import List
|
||||
def f(x: List[int], y: int) -> None:
|
||||
x.insert(0, y)
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: list
|
||||
y :: int
|
||||
r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
L0:
|
||||
r0 = box(int, y)
|
||||
r1 = CPyList_Insert(x, 0, r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
return 1
|
||||
|
||||
[case testListBuiltFromGenerator]
|
||||
from typing import List
|
||||
def f(source: List[int]) -> None:
|
||||
a = list(x + 1 for x in source)
|
||||
b = [x + 1 for x in source]
|
||||
[out]
|
||||
def f(source):
|
||||
source :: list
|
||||
r0 :: ptr
|
||||
r1 :: native_int
|
||||
r2 :: list
|
||||
r3 :: short_int
|
||||
r4 :: ptr
|
||||
r5 :: native_int
|
||||
r6 :: short_int
|
||||
r7 :: bit
|
||||
r8 :: object
|
||||
r9, x, r10 :: int
|
||||
r11 :: object
|
||||
r12 :: bit
|
||||
r13 :: short_int
|
||||
a :: list
|
||||
r14 :: ptr
|
||||
r15 :: native_int
|
||||
r16 :: list
|
||||
r17 :: short_int
|
||||
r18 :: ptr
|
||||
r19 :: native_int
|
||||
r20 :: short_int
|
||||
r21 :: bit
|
||||
r22 :: object
|
||||
r23, x_2, r24 :: int
|
||||
r25 :: object
|
||||
r26 :: bit
|
||||
r27 :: short_int
|
||||
b :: list
|
||||
L0:
|
||||
r0 = get_element_ptr source ob_size :: PyVarObject
|
||||
r1 = load_mem r0 :: native_int*
|
||||
keep_alive source
|
||||
r2 = PyList_New(r1)
|
||||
r3 = 0
|
||||
L1:
|
||||
r4 = get_element_ptr source ob_size :: PyVarObject
|
||||
r5 = load_mem r4 :: native_int*
|
||||
keep_alive source
|
||||
r6 = r5 << 1
|
||||
r7 = r3 < r6 :: signed
|
||||
if r7 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r8 = CPyList_GetItemUnsafe(source, r3)
|
||||
r9 = unbox(int, r8)
|
||||
x = r9
|
||||
r10 = CPyTagged_Add(x, 2)
|
||||
r11 = box(int, r10)
|
||||
r12 = CPyList_SetItemUnsafe(r2, r3, r11)
|
||||
L3:
|
||||
r13 = r3 + 2
|
||||
r3 = r13
|
||||
goto L1
|
||||
L4:
|
||||
a = r2
|
||||
r14 = get_element_ptr source ob_size :: PyVarObject
|
||||
r15 = load_mem r14 :: native_int*
|
||||
keep_alive source
|
||||
r16 = PyList_New(r15)
|
||||
r17 = 0
|
||||
L5:
|
||||
r18 = get_element_ptr source ob_size :: PyVarObject
|
||||
r19 = load_mem r18 :: native_int*
|
||||
keep_alive source
|
||||
r20 = r19 << 1
|
||||
r21 = r17 < r20 :: signed
|
||||
if r21 goto L6 else goto L8 :: bool
|
||||
L6:
|
||||
r22 = CPyList_GetItemUnsafe(source, r17)
|
||||
r23 = unbox(int, r22)
|
||||
x_2 = r23
|
||||
r24 = CPyTagged_Add(x_2, 2)
|
||||
r25 = box(int, r24)
|
||||
r26 = CPyList_SetItemUnsafe(r16, r17, r25)
|
||||
L7:
|
||||
r27 = r17 + 2
|
||||
r17 = r27
|
||||
goto L5
|
||||
L8:
|
||||
b = r16
|
||||
return 1
|
||||
[case testGeneratorNext]
|
||||
from typing import List, Optional
|
||||
|
||||
def test(x: List[int]) -> None:
|
||||
res = next((i for i in x), None)
|
||||
[out]
|
||||
def test(x):
|
||||
x :: list
|
||||
r0 :: short_int
|
||||
r1 :: ptr
|
||||
r2 :: native_int
|
||||
r3 :: short_int
|
||||
r4 :: bit
|
||||
r5 :: object
|
||||
r6, i :: int
|
||||
r7 :: object
|
||||
r8 :: union[int, None]
|
||||
r9 :: short_int
|
||||
r10 :: object
|
||||
res :: union[int, None]
|
||||
L0:
|
||||
r0 = 0
|
||||
L1:
|
||||
r1 = get_element_ptr x ob_size :: PyVarObject
|
||||
r2 = load_mem r1 :: native_int*
|
||||
keep_alive x
|
||||
r3 = r2 << 1
|
||||
r4 = r0 < r3 :: signed
|
||||
if r4 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r5 = CPyList_GetItemUnsafe(x, r0)
|
||||
r6 = unbox(int, r5)
|
||||
i = r6
|
||||
r7 = box(int, i)
|
||||
r8 = r7
|
||||
goto L5
|
||||
L3:
|
||||
r9 = r0 + 2
|
||||
r0 = r9
|
||||
goto L1
|
||||
L4:
|
||||
r10 = box(None, 1)
|
||||
r8 = r10
|
||||
L5:
|
||||
res = r8
|
||||
return 1
|
||||
|
||||
[case testSimplifyListUnion]
|
||||
from typing import List, Union, Optional
|
||||
|
||||
def narrow(a: Union[List[str], List[bytes], int]) -> int:
|
||||
if isinstance(a, list):
|
||||
return len(a)
|
||||
return a
|
||||
def loop(a: Union[List[str], List[bytes]]) -> None:
|
||||
for x in a:
|
||||
pass
|
||||
def nested_union(a: Union[List[str], List[Optional[str]]]) -> None:
|
||||
for x in a:
|
||||
pass
|
||||
[out]
|
||||
def narrow(a):
|
||||
a :: union[list, int]
|
||||
r0 :: object
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3 :: bool
|
||||
r4 :: list
|
||||
r5 :: ptr
|
||||
r6 :: native_int
|
||||
r7 :: short_int
|
||||
r8 :: int
|
||||
L0:
|
||||
r0 = load_address PyList_Type
|
||||
r1 = PyObject_IsInstance(a, r0)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
if r3 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r4 = borrow cast(list, a)
|
||||
r5 = get_element_ptr r4 ob_size :: PyVarObject
|
||||
r6 = load_mem r5 :: native_int*
|
||||
keep_alive r4
|
||||
r7 = r6 << 1
|
||||
keep_alive a
|
||||
return r7
|
||||
L2:
|
||||
r8 = unbox(int, a)
|
||||
return r8
|
||||
def loop(a):
|
||||
a :: list
|
||||
r0 :: short_int
|
||||
r1 :: ptr
|
||||
r2 :: native_int
|
||||
r3 :: short_int
|
||||
r4 :: bit
|
||||
r5 :: object
|
||||
r6, x :: union[str, bytes]
|
||||
r7 :: short_int
|
||||
L0:
|
||||
r0 = 0
|
||||
L1:
|
||||
r1 = get_element_ptr a ob_size :: PyVarObject
|
||||
r2 = load_mem r1 :: native_int*
|
||||
keep_alive a
|
||||
r3 = r2 << 1
|
||||
r4 = r0 < r3 :: signed
|
||||
if r4 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r5 = CPyList_GetItemUnsafe(a, r0)
|
||||
r6 = cast(union[str, bytes], r5)
|
||||
x = r6
|
||||
L3:
|
||||
r7 = r0 + 2
|
||||
r0 = r7
|
||||
goto L1
|
||||
L4:
|
||||
return 1
|
||||
def nested_union(a):
|
||||
a :: list
|
||||
r0 :: short_int
|
||||
r1 :: ptr
|
||||
r2 :: native_int
|
||||
r3 :: short_int
|
||||
r4 :: bit
|
||||
r5 :: object
|
||||
r6, x :: union[str, None]
|
||||
r7 :: short_int
|
||||
L0:
|
||||
r0 = 0
|
||||
L1:
|
||||
r1 = get_element_ptr a ob_size :: PyVarObject
|
||||
r2 = load_mem r1 :: native_int*
|
||||
keep_alive a
|
||||
r3 = r2 << 1
|
||||
r4 = r0 < r3 :: signed
|
||||
if r4 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r5 = CPyList_GetItemUnsafe(a, r0)
|
||||
r6 = cast(union[str, None], r5)
|
||||
x = r6
|
||||
L3:
|
||||
r7 = r0 + 2
|
||||
r0 = r7
|
||||
goto L1
|
||||
L4:
|
||||
return 1
|
||||
1708
venv/lib/python3.12/site-packages/mypyc/test-data/irbuild-match.test
Normal file
1708
venv/lib/python3.12/site-packages/mypyc/test-data/irbuild-match.test
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
[case testMathLiteralsAreInlined]
|
||||
import math
|
||||
from math import pi, e, tau, inf, nan
|
||||
|
||||
def f1() -> float:
|
||||
return pi
|
||||
|
||||
def f2() -> float:
|
||||
return math.pi
|
||||
|
||||
def f3() -> float:
|
||||
return math.e
|
||||
|
||||
def f4() -> float:
|
||||
return math.e
|
||||
|
||||
def f5() -> float:
|
||||
return math.tau
|
||||
|
||||
def f6() -> float:
|
||||
return math.tau
|
||||
|
||||
def f7() -> float:
|
||||
return math.inf
|
||||
def f8() -> float:
|
||||
return math.inf
|
||||
|
||||
def f9() -> float:
|
||||
return math.nan
|
||||
|
||||
def f10() -> float:
|
||||
return math.nan
|
||||
|
||||
[out]
|
||||
def f1():
|
||||
L0:
|
||||
return 3.141592653589793
|
||||
def f2():
|
||||
L0:
|
||||
return 3.141592653589793
|
||||
def f3():
|
||||
L0:
|
||||
return 2.718281828459045
|
||||
def f4():
|
||||
L0:
|
||||
return 2.718281828459045
|
||||
def f5():
|
||||
L0:
|
||||
return 6.283185307179586
|
||||
def f6():
|
||||
L0:
|
||||
return 6.283185307179586
|
||||
def f7():
|
||||
L0:
|
||||
return inf
|
||||
def f8():
|
||||
L0:
|
||||
return inf
|
||||
def f9():
|
||||
L0:
|
||||
return nan
|
||||
def f10():
|
||||
L0:
|
||||
return nan
|
||||
@@ -0,0 +1,861 @@
|
||||
[case testNestedFunctions]
|
||||
from typing import Callable
|
||||
|
||||
def a() -> Callable[[], object]:
|
||||
def inner() -> object:
|
||||
return None
|
||||
return inner
|
||||
|
||||
def b() -> Callable[[], Callable[[], str]]:
|
||||
def first() -> Callable[[], str]:
|
||||
def second() -> str:
|
||||
return 'b.first.second: nested function'
|
||||
return second
|
||||
return first
|
||||
|
||||
def c(num: float) -> Callable[[str], str]:
|
||||
def inner(s: str) -> str:
|
||||
return s + '!'
|
||||
return inner
|
||||
|
||||
def d(num: float) -> str:
|
||||
def inner(s: str) -> str:
|
||||
return s + '?'
|
||||
a = inner('one')
|
||||
b = inner('two')
|
||||
return a
|
||||
|
||||
def inner() -> str:
|
||||
return 'inner: normal function'
|
||||
|
||||
def first() -> str:
|
||||
return 'first: normal function'
|
||||
|
||||
def second() -> str:
|
||||
return 'second: normal function'
|
||||
[out]
|
||||
def inner_a_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def inner_a_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.inner_a_obj
|
||||
r0 :: __main__.a_env
|
||||
r1, inner, r2 :: object
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.inner
|
||||
inner = r1
|
||||
r2 = box(None, 1)
|
||||
return r2
|
||||
def a():
|
||||
r0 :: __main__.a_env
|
||||
r1 :: __main__.inner_a_obj
|
||||
r2, r3 :: bool
|
||||
r4 :: object
|
||||
L0:
|
||||
r0 = a_env()
|
||||
r1 = inner_a_obj()
|
||||
r1.__mypyc_env__ = r0; r2 = is_error
|
||||
r0.inner = r1; r3 = is_error
|
||||
r4 = r0.inner
|
||||
return r4
|
||||
def second_b_first_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def second_b_first_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.second_b_first_obj
|
||||
r0 :: __main__.first_b_env
|
||||
r1 :: __main__.b_env
|
||||
r2, second :: object
|
||||
r3 :: str
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.__mypyc_env__
|
||||
r2 = r0.second
|
||||
second = r2
|
||||
r3 = 'b.first.second: nested function'
|
||||
return r3
|
||||
def first_b_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def first_b_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.first_b_obj
|
||||
r0 :: __main__.b_env
|
||||
r1, first :: object
|
||||
r2 :: __main__.first_b_env
|
||||
r3 :: bool
|
||||
r4 :: __main__.second_b_first_obj
|
||||
r5, r6 :: bool
|
||||
r7 :: object
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.first
|
||||
first = r1
|
||||
r2 = first_b_env()
|
||||
r2.__mypyc_env__ = r0; r3 = is_error
|
||||
r4 = second_b_first_obj()
|
||||
r4.__mypyc_env__ = r2; r5 = is_error
|
||||
r2.second = r4; r6 = is_error
|
||||
r7 = r2.second
|
||||
return r7
|
||||
def b():
|
||||
r0 :: __main__.b_env
|
||||
r1 :: __main__.first_b_obj
|
||||
r2, r3 :: bool
|
||||
r4 :: object
|
||||
L0:
|
||||
r0 = b_env()
|
||||
r1 = first_b_obj()
|
||||
r1.__mypyc_env__ = r0; r2 = is_error
|
||||
r0.first = r1; r3 = is_error
|
||||
r4 = r0.first
|
||||
return r4
|
||||
def inner_c_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def inner_c_obj.__call__(__mypyc_self__, s):
|
||||
__mypyc_self__ :: __main__.inner_c_obj
|
||||
s :: str
|
||||
r0 :: __main__.c_env
|
||||
r1, inner :: object
|
||||
r2, r3 :: str
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.inner
|
||||
inner = r1
|
||||
r2 = '!'
|
||||
r3 = PyUnicode_Concat(s, r2)
|
||||
return r3
|
||||
def c(num):
|
||||
num :: float
|
||||
r0 :: __main__.c_env
|
||||
r1 :: __main__.inner_c_obj
|
||||
r2, r3 :: bool
|
||||
r4 :: object
|
||||
L0:
|
||||
r0 = c_env()
|
||||
r1 = inner_c_obj()
|
||||
r1.__mypyc_env__ = r0; r2 = is_error
|
||||
r0.inner = r1; r3 = is_error
|
||||
r4 = r0.inner
|
||||
return r4
|
||||
def inner_d_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def inner_d_obj.__call__(__mypyc_self__, s):
|
||||
__mypyc_self__ :: __main__.inner_d_obj
|
||||
s :: str
|
||||
r0 :: __main__.d_env
|
||||
r1, inner :: object
|
||||
r2, r3 :: str
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.inner
|
||||
inner = r1
|
||||
r2 = '?'
|
||||
r3 = PyUnicode_Concat(s, r2)
|
||||
return r3
|
||||
def d(num):
|
||||
num :: float
|
||||
r0 :: __main__.d_env
|
||||
r1 :: __main__.inner_d_obj
|
||||
r2, r3 :: bool
|
||||
r4 :: str
|
||||
r5, r6 :: object
|
||||
r7, a, r8 :: str
|
||||
r9, r10 :: object
|
||||
r11, b :: str
|
||||
L0:
|
||||
r0 = d_env()
|
||||
r1 = inner_d_obj()
|
||||
r1.__mypyc_env__ = r0; r2 = is_error
|
||||
r0.inner = r1; r3 = is_error
|
||||
r4 = 'one'
|
||||
r5 = r0.inner
|
||||
r6 = PyObject_CallFunctionObjArgs(r5, r4, 0)
|
||||
r7 = cast(str, r6)
|
||||
a = r7
|
||||
r8 = 'two'
|
||||
r9 = r0.inner
|
||||
r10 = PyObject_CallFunctionObjArgs(r9, r8, 0)
|
||||
r11 = cast(str, r10)
|
||||
b = r11
|
||||
return a
|
||||
def inner():
|
||||
r0 :: str
|
||||
L0:
|
||||
r0 = 'inner: normal function'
|
||||
return r0
|
||||
def first():
|
||||
r0 :: str
|
||||
L0:
|
||||
r0 = 'first: normal function'
|
||||
return r0
|
||||
def second():
|
||||
r0 :: str
|
||||
L0:
|
||||
r0 = 'second: normal function'
|
||||
return r0
|
||||
|
||||
[case testFreeVars]
|
||||
from typing import Callable
|
||||
|
||||
def a(num: int) -> int:
|
||||
def inner() -> int:
|
||||
return num
|
||||
return inner()
|
||||
|
||||
def b() -> int:
|
||||
num = 3
|
||||
def inner() -> int:
|
||||
nonlocal num
|
||||
num = 4
|
||||
foo = 6
|
||||
return num
|
||||
return inner() + num
|
||||
|
||||
def c(flag: bool) -> str:
|
||||
if flag:
|
||||
def inner() -> str:
|
||||
return 'f.inner: first definition'
|
||||
else:
|
||||
def inner() -> str:
|
||||
return 'f.inner: second definition'
|
||||
return inner()
|
||||
|
||||
[out]
|
||||
def inner_a_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def inner_a_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.inner_a_obj
|
||||
r0 :: __main__.a_env
|
||||
r1, inner :: object
|
||||
r2 :: int
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.inner
|
||||
inner = r1
|
||||
r2 = r0.num
|
||||
return r2
|
||||
def a(num):
|
||||
num :: int
|
||||
r0 :: __main__.a_env
|
||||
r1 :: bool
|
||||
r2 :: __main__.inner_a_obj
|
||||
r3, r4 :: bool
|
||||
r5, r6 :: object
|
||||
r7 :: int
|
||||
L0:
|
||||
r0 = a_env()
|
||||
r0.num = num; r1 = is_error
|
||||
r2 = inner_a_obj()
|
||||
r2.__mypyc_env__ = r0; r3 = is_error
|
||||
r0.inner = r2; r4 = is_error
|
||||
r5 = r0.inner
|
||||
r6 = PyObject_CallFunctionObjArgs(r5, 0)
|
||||
r7 = unbox(int, r6)
|
||||
return r7
|
||||
def inner_b_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def inner_b_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.inner_b_obj
|
||||
r0 :: __main__.b_env
|
||||
r1, inner :: object
|
||||
r2 :: bool
|
||||
foo, r3 :: int
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.inner
|
||||
inner = r1
|
||||
r0.num = 8; r2 = is_error
|
||||
foo = 12
|
||||
r3 = r0.num
|
||||
return r3
|
||||
def b():
|
||||
r0 :: __main__.b_env
|
||||
r1 :: bool
|
||||
r2 :: __main__.inner_b_obj
|
||||
r3, r4 :: bool
|
||||
r5, r6 :: object
|
||||
r7, r8, r9 :: int
|
||||
L0:
|
||||
r0 = b_env()
|
||||
r0.num = 6; r1 = is_error
|
||||
r2 = inner_b_obj()
|
||||
r2.__mypyc_env__ = r0; r3 = is_error
|
||||
r0.inner = r2; r4 = is_error
|
||||
r5 = r0.inner
|
||||
r6 = PyObject_CallFunctionObjArgs(r5, 0)
|
||||
r7 = unbox(int, r6)
|
||||
r8 = r0.num
|
||||
r9 = CPyTagged_Add(r7, r8)
|
||||
return r9
|
||||
def inner_c_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def inner_c_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.inner_c_obj
|
||||
r0 :: __main__.c_env
|
||||
r1, inner :: object
|
||||
r2 :: str
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.inner
|
||||
inner = r1
|
||||
r2 = 'f.inner: first definition'
|
||||
return r2
|
||||
def inner_c_obj_0.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def inner_c_obj_0.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.inner_c_obj_0
|
||||
r0 :: __main__.c_env
|
||||
r1, inner :: object
|
||||
r2 :: str
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.inner
|
||||
inner = r1
|
||||
r2 = 'f.inner: second definition'
|
||||
return r2
|
||||
def c(flag):
|
||||
flag :: bool
|
||||
r0 :: __main__.c_env
|
||||
r1 :: __main__.inner_c_obj
|
||||
r2, r3 :: bool
|
||||
r4 :: __main__.inner_c_obj_0
|
||||
r5, r6 :: bool
|
||||
r7, r8 :: object
|
||||
r9 :: str
|
||||
L0:
|
||||
r0 = c_env()
|
||||
if flag goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r1 = inner_c_obj()
|
||||
r1.__mypyc_env__ = r0; r2 = is_error
|
||||
r0.inner = r1; r3 = is_error
|
||||
goto L3
|
||||
L2:
|
||||
r4 = inner_c_obj_0()
|
||||
r4.__mypyc_env__ = r0; r5 = is_error
|
||||
r0.inner = r4; r6 = is_error
|
||||
L3:
|
||||
r7 = r0.inner
|
||||
r8 = PyObject_CallFunctionObjArgs(r7, 0)
|
||||
r9 = cast(str, r8)
|
||||
return r9
|
||||
|
||||
[case testSpecialNested]
|
||||
def a() -> int:
|
||||
x = 1
|
||||
def b() -> int:
|
||||
x += 1
|
||||
def c() -> int:
|
||||
return x
|
||||
return c()
|
||||
return b()
|
||||
|
||||
[out]
|
||||
def c_a_b_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def c_a_b_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.c_a_b_obj
|
||||
r0 :: __main__.b_a_env
|
||||
r1 :: __main__.a_env
|
||||
r2, c :: object
|
||||
r3 :: int
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.__mypyc_env__
|
||||
r2 = r0.c
|
||||
c = r2
|
||||
r3 = r1.x
|
||||
return r3
|
||||
def b_a_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def b_a_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.b_a_obj
|
||||
r0 :: __main__.a_env
|
||||
r1, b :: object
|
||||
r2 :: __main__.b_a_env
|
||||
r3 :: bool
|
||||
r4, r5 :: int
|
||||
r6 :: bool
|
||||
r7 :: __main__.c_a_b_obj
|
||||
r8, r9 :: bool
|
||||
r10, r11 :: object
|
||||
r12 :: int
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.b
|
||||
b = r1
|
||||
r2 = b_a_env()
|
||||
r2.__mypyc_env__ = r0; r3 = is_error
|
||||
r4 = r0.x
|
||||
r5 = CPyTagged_Add(r4, 2)
|
||||
r0.x = r5; r6 = is_error
|
||||
r7 = c_a_b_obj()
|
||||
r7.__mypyc_env__ = r2; r8 = is_error
|
||||
r2.c = r7; r9 = is_error
|
||||
r10 = r2.c
|
||||
r11 = PyObject_CallFunctionObjArgs(r10, 0)
|
||||
r12 = unbox(int, r11)
|
||||
return r12
|
||||
def a():
|
||||
r0 :: __main__.a_env
|
||||
r1 :: bool
|
||||
r2 :: __main__.b_a_obj
|
||||
r3, r4 :: bool
|
||||
r5, r6 :: object
|
||||
r7 :: int
|
||||
L0:
|
||||
r0 = a_env()
|
||||
r0.x = 2; r1 = is_error
|
||||
r2 = b_a_obj()
|
||||
r2.__mypyc_env__ = r0; r3 = is_error
|
||||
r0.b = r2; r4 = is_error
|
||||
r5 = r0.b
|
||||
r6 = PyObject_CallFunctionObjArgs(r5, 0)
|
||||
r7 = unbox(int, r6)
|
||||
return r7
|
||||
|
||||
[case testNestedFunctionInsideStatements]
|
||||
def f(flag: bool) -> str:
|
||||
if flag:
|
||||
def inner() -> str:
|
||||
return 'f.inner: first definition'
|
||||
else:
|
||||
def inner() -> str:
|
||||
return 'f.inner: second definition'
|
||||
return inner()
|
||||
[out]
|
||||
def inner_f_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def inner_f_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.inner_f_obj
|
||||
r0 :: __main__.f_env
|
||||
r1, inner :: object
|
||||
r2 :: str
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.inner
|
||||
inner = r1
|
||||
r2 = 'f.inner: first definition'
|
||||
return r2
|
||||
def inner_f_obj_0.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def inner_f_obj_0.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.inner_f_obj_0
|
||||
r0 :: __main__.f_env
|
||||
r1, inner :: object
|
||||
r2 :: str
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.inner
|
||||
inner = r1
|
||||
r2 = 'f.inner: second definition'
|
||||
return r2
|
||||
def f(flag):
|
||||
flag :: bool
|
||||
r0 :: __main__.f_env
|
||||
r1 :: __main__.inner_f_obj
|
||||
r2, r3 :: bool
|
||||
r4 :: __main__.inner_f_obj_0
|
||||
r5, r6 :: bool
|
||||
r7, r8 :: object
|
||||
r9 :: str
|
||||
L0:
|
||||
r0 = f_env()
|
||||
if flag goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r1 = inner_f_obj()
|
||||
r1.__mypyc_env__ = r0; r2 = is_error
|
||||
r0.inner = r1; r3 = is_error
|
||||
goto L3
|
||||
L2:
|
||||
r4 = inner_f_obj_0()
|
||||
r4.__mypyc_env__ = r0; r5 = is_error
|
||||
r0.inner = r4; r6 = is_error
|
||||
L3:
|
||||
r7 = r0.inner
|
||||
r8 = PyObject_CallFunctionObjArgs(r7, 0)
|
||||
r9 = cast(str, r8)
|
||||
return r9
|
||||
|
||||
[case testNestedFunctionsCallEachOther]
|
||||
from typing import Callable, List
|
||||
|
||||
def f(a: int) -> int:
|
||||
def foo() -> int:
|
||||
return a + 1
|
||||
|
||||
def bar() -> int:
|
||||
return foo()
|
||||
|
||||
def baz(n: int) -> int:
|
||||
if n == 0:
|
||||
return 0
|
||||
return n + baz(n - 1)
|
||||
|
||||
return bar() + baz(a)
|
||||
|
||||
[out]
|
||||
def foo_f_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def foo_f_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.foo_f_obj
|
||||
r0 :: __main__.f_env
|
||||
r1, foo :: object
|
||||
r2, r3 :: int
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.foo
|
||||
foo = r1
|
||||
r2 = r0.a
|
||||
r3 = CPyTagged_Add(r2, 2)
|
||||
return r3
|
||||
def bar_f_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def bar_f_obj.__call__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.bar_f_obj
|
||||
r0 :: __main__.f_env
|
||||
r1, bar, r2, r3 :: object
|
||||
r4 :: int
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.bar
|
||||
bar = r1
|
||||
r2 = r0.foo
|
||||
r3 = PyObject_CallFunctionObjArgs(r2, 0)
|
||||
r4 = unbox(int, r3)
|
||||
return r4
|
||||
def baz_f_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def baz_f_obj.__call__(__mypyc_self__, n):
|
||||
__mypyc_self__ :: __main__.baz_f_obj
|
||||
n :: int
|
||||
r0 :: __main__.f_env
|
||||
r1, baz :: object
|
||||
r2 :: bit
|
||||
r3 :: int
|
||||
r4, r5 :: object
|
||||
r6, r7 :: int
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.baz
|
||||
baz = r1
|
||||
r2 = n == 0
|
||||
if r2 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return 0
|
||||
L2:
|
||||
r3 = CPyTagged_Subtract(n, 2)
|
||||
r4 = box(int, r3)
|
||||
r5 = PyObject_CallFunctionObjArgs(baz, r4, 0)
|
||||
r6 = unbox(int, r5)
|
||||
r7 = CPyTagged_Add(n, r6)
|
||||
return r7
|
||||
def f(a):
|
||||
a :: int
|
||||
r0 :: __main__.f_env
|
||||
r1 :: bool
|
||||
r2 :: __main__.foo_f_obj
|
||||
r3, r4 :: bool
|
||||
r5 :: __main__.bar_f_obj
|
||||
r6, r7 :: bool
|
||||
r8 :: __main__.baz_f_obj
|
||||
r9, r10 :: bool
|
||||
r11, r12 :: object
|
||||
r13, r14 :: int
|
||||
r15, r16, r17 :: object
|
||||
r18, r19 :: int
|
||||
L0:
|
||||
r0 = f_env()
|
||||
r0.a = a; r1 = is_error
|
||||
r2 = foo_f_obj()
|
||||
r2.__mypyc_env__ = r0; r3 = is_error
|
||||
r0.foo = r2; r4 = is_error
|
||||
r5 = bar_f_obj()
|
||||
r5.__mypyc_env__ = r0; r6 = is_error
|
||||
r0.bar = r5; r7 = is_error
|
||||
r8 = baz_f_obj()
|
||||
r8.__mypyc_env__ = r0; r9 = is_error
|
||||
r0.baz = r8; r10 = is_error
|
||||
r11 = r0.bar
|
||||
r12 = PyObject_CallFunctionObjArgs(r11, 0)
|
||||
r13 = unbox(int, r12)
|
||||
r14 = r0.a
|
||||
r15 = r0.baz
|
||||
r16 = box(int, r14)
|
||||
r17 = PyObject_CallFunctionObjArgs(r15, r16, 0)
|
||||
r18 = unbox(int, r17)
|
||||
r19 = CPyTagged_Add(r13, r18)
|
||||
return r19
|
||||
|
||||
[case testLambdas]
|
||||
def f(x: int, y: int) -> None:
|
||||
s = lambda a, b: a + b
|
||||
t = lambda a, b: s(a, b)
|
||||
return t(x, y)
|
||||
|
||||
[out]
|
||||
def __mypyc_lambda__0_f_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def __mypyc_lambda__0_f_obj.__call__(__mypyc_self__, a, b):
|
||||
__mypyc_self__ :: __main__.__mypyc_lambda__0_f_obj
|
||||
a, b :: object
|
||||
r0 :: __main__.f_env
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = PyNumber_Add(a, b)
|
||||
return r1
|
||||
def __mypyc_lambda__1_f_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def __mypyc_lambda__1_f_obj.__call__(__mypyc_self__, a, b):
|
||||
__mypyc_self__ :: __main__.__mypyc_lambda__1_f_obj
|
||||
a, b :: object
|
||||
r0 :: __main__.f_env
|
||||
r1, r2 :: object
|
||||
L0:
|
||||
r0 = __mypyc_self__.__mypyc_env__
|
||||
r1 = r0.s
|
||||
r2 = PyObject_CallFunctionObjArgs(r1, a, b, 0)
|
||||
return r2
|
||||
def f(x, y):
|
||||
x, y :: int
|
||||
r0 :: __main__.f_env
|
||||
r1 :: __main__.__mypyc_lambda__0_f_obj
|
||||
r2, r3 :: bool
|
||||
r4 :: __main__.__mypyc_lambda__1_f_obj
|
||||
r5 :: bool
|
||||
t, r6, r7, r8 :: object
|
||||
r9 :: None
|
||||
L0:
|
||||
r0 = f_env()
|
||||
r1 = __mypyc_lambda__0_f_obj()
|
||||
r1.__mypyc_env__ = r0; r2 = is_error
|
||||
r0.s = r1; r3 = is_error
|
||||
r4 = __mypyc_lambda__1_f_obj()
|
||||
r4.__mypyc_env__ = r0; r5 = is_error
|
||||
t = r4
|
||||
r6 = box(int, x)
|
||||
r7 = box(int, y)
|
||||
r8 = PyObject_CallFunctionObjArgs(t, r6, r7, 0)
|
||||
r9 = unbox(None, r8)
|
||||
return r9
|
||||
|
||||
[case testRecursiveFunction]
|
||||
from typing import Callable
|
||||
|
||||
def baz(n: int) -> int:
|
||||
if n == 0:
|
||||
return 0
|
||||
return n + baz(n - 1)
|
||||
|
||||
[out]
|
||||
def baz(n):
|
||||
n :: int
|
||||
r0 :: bit
|
||||
r1, r2, r3 :: int
|
||||
L0:
|
||||
r0 = n == 0
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return 0
|
||||
L2:
|
||||
r1 = CPyTagged_Subtract(n, 2)
|
||||
r2 = baz(r1)
|
||||
r3 = CPyTagged_Add(n, r2)
|
||||
return r3
|
||||
@@ -0,0 +1,536 @@
|
||||
[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 :: i32
|
||||
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: i32 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 :: i32
|
||||
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: i32 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 :: i32
|
||||
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 :: object
|
||||
r0 :: str
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = 'x'
|
||||
r1 = CPyObject_GetAttr(o, r0)
|
||||
return 1
|
||||
@@ -0,0 +1,838 @@
|
||||
[case testNewSet]
|
||||
from typing import Set
|
||||
def f() -> Set[int]:
|
||||
return {1, 2, 3}
|
||||
[out]
|
||||
def f():
|
||||
r0 :: set
|
||||
r1 :: object
|
||||
r2 :: i32
|
||||
r3 :: bit
|
||||
r4 :: object
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
r7 :: object
|
||||
r8 :: i32
|
||||
r9 :: bit
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
r1 = object 1
|
||||
r2 = PySet_Add(r0, r1)
|
||||
r3 = r2 >= 0 :: signed
|
||||
r4 = object 2
|
||||
r5 = PySet_Add(r0, r4)
|
||||
r6 = r5 >= 0 :: signed
|
||||
r7 = object 3
|
||||
r8 = PySet_Add(r0, r7)
|
||||
r9 = r8 >= 0 :: signed
|
||||
return r0
|
||||
|
||||
[case testNewEmptySet]
|
||||
from typing import Set
|
||||
def f() -> Set[int]:
|
||||
return set()
|
||||
[out]
|
||||
def f():
|
||||
r0 :: set
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
return r0
|
||||
|
||||
[case testNewSetFromIterable]
|
||||
from typing import Set, List
|
||||
def f(l: List[T]) -> Set[T]:
|
||||
return set(l)
|
||||
[out]
|
||||
def f(l):
|
||||
l :: list
|
||||
r0 :: set
|
||||
L0:
|
||||
r0 = PySet_New(l)
|
||||
return r0
|
||||
|
||||
[case testNewSetFromIterable2]
|
||||
def f(x: int) -> int:
|
||||
return x
|
||||
|
||||
def test1() -> None:
|
||||
tmp_list = [1, 3, 5]
|
||||
a = set(f(x) for x in tmp_list)
|
||||
|
||||
def test2() -> None:
|
||||
tmp_tuple = (1, 3, 5)
|
||||
b = set(f(x) for x in tmp_tuple)
|
||||
|
||||
def test3() -> None:
|
||||
tmp_dict = {1: '1', 3: '3', 5: '5'}
|
||||
c = set(f(x) for x in tmp_dict)
|
||||
|
||||
def test4() -> None:
|
||||
d = set(f(x) for x in range(1, 6, 2))
|
||||
|
||||
def test5() -> None:
|
||||
e = set((f(x) for x in range(1, 6, 2)))
|
||||
[out]
|
||||
def f(x):
|
||||
x :: int
|
||||
L0:
|
||||
return x
|
||||
def test1():
|
||||
r0 :: list
|
||||
r1, r2, r3 :: object
|
||||
r4, r5, r6, r7 :: ptr
|
||||
tmp_list :: list
|
||||
r8 :: set
|
||||
r9 :: short_int
|
||||
r10 :: ptr
|
||||
r11 :: native_int
|
||||
r12 :: short_int
|
||||
r13 :: bit
|
||||
r14 :: object
|
||||
r15, x, r16 :: int
|
||||
r17 :: object
|
||||
r18 :: i32
|
||||
r19 :: bit
|
||||
r20 :: short_int
|
||||
a :: set
|
||||
L0:
|
||||
r0 = PyList_New(3)
|
||||
r1 = object 1
|
||||
r2 = object 3
|
||||
r3 = object 5
|
||||
r4 = get_element_ptr r0 ob_item :: PyListObject
|
||||
r5 = load_mem r4 :: ptr*
|
||||
set_mem r5, r1 :: builtins.object*
|
||||
r6 = r5 + WORD_SIZE*1
|
||||
set_mem r6, r2 :: builtins.object*
|
||||
r7 = r5 + WORD_SIZE*2
|
||||
set_mem r7, r3 :: builtins.object*
|
||||
keep_alive r0
|
||||
tmp_list = r0
|
||||
r8 = PySet_New(0)
|
||||
r9 = 0
|
||||
L1:
|
||||
r10 = get_element_ptr tmp_list ob_size :: PyVarObject
|
||||
r11 = load_mem r10 :: native_int*
|
||||
keep_alive tmp_list
|
||||
r12 = r11 << 1
|
||||
r13 = r9 < r12 :: signed
|
||||
if r13 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r14 = CPyList_GetItemUnsafe(tmp_list, r9)
|
||||
r15 = unbox(int, r14)
|
||||
x = r15
|
||||
r16 = f(x)
|
||||
r17 = box(int, r16)
|
||||
r18 = PySet_Add(r8, r17)
|
||||
r19 = r18 >= 0 :: signed
|
||||
L3:
|
||||
r20 = r9 + 2
|
||||
r9 = r20
|
||||
goto L1
|
||||
L4:
|
||||
a = r8
|
||||
return 1
|
||||
def test2():
|
||||
r0, tmp_tuple :: tuple[int, int, int]
|
||||
r1 :: set
|
||||
r2, r3, r4 :: object
|
||||
r5, x, r6 :: int
|
||||
r7 :: object
|
||||
r8 :: i32
|
||||
r9, r10 :: bit
|
||||
b :: set
|
||||
L0:
|
||||
r0 = (2, 6, 10)
|
||||
tmp_tuple = r0
|
||||
r1 = PySet_New(0)
|
||||
r2 = box(tuple[int, int, int], tmp_tuple)
|
||||
r3 = PyObject_GetIter(r2)
|
||||
L1:
|
||||
r4 = PyIter_Next(r3)
|
||||
if is_error(r4) goto L4 else goto L2
|
||||
L2:
|
||||
r5 = unbox(int, r4)
|
||||
x = r5
|
||||
r6 = f(x)
|
||||
r7 = box(int, r6)
|
||||
r8 = PySet_Add(r1, r7)
|
||||
r9 = r8 >= 0 :: signed
|
||||
L3:
|
||||
goto L1
|
||||
L4:
|
||||
r10 = CPy_NoErrOccured()
|
||||
L5:
|
||||
b = r1
|
||||
return 1
|
||||
def test3():
|
||||
r0, r1, r2 :: str
|
||||
r3, r4, r5 :: object
|
||||
r6, tmp_dict :: dict
|
||||
r7 :: set
|
||||
r8 :: short_int
|
||||
r9 :: native_int
|
||||
r10 :: short_int
|
||||
r11 :: object
|
||||
r12 :: tuple[bool, short_int, object]
|
||||
r13 :: short_int
|
||||
r14 :: bool
|
||||
r15 :: object
|
||||
r16, x, r17 :: int
|
||||
r18 :: object
|
||||
r19 :: i32
|
||||
r20, r21, r22 :: bit
|
||||
c :: set
|
||||
L0:
|
||||
r0 = '1'
|
||||
r1 = '3'
|
||||
r2 = '5'
|
||||
r3 = object 1
|
||||
r4 = object 3
|
||||
r5 = object 5
|
||||
r6 = CPyDict_Build(3, r3, r0, r4, r1, r5, r2)
|
||||
tmp_dict = r6
|
||||
r7 = PySet_New(0)
|
||||
r8 = 0
|
||||
r9 = PyDict_Size(tmp_dict)
|
||||
r10 = r9 << 1
|
||||
r11 = CPyDict_GetKeysIter(tmp_dict)
|
||||
L1:
|
||||
r12 = CPyDict_NextKey(r11, r8)
|
||||
r13 = r12[1]
|
||||
r8 = r13
|
||||
r14 = r12[0]
|
||||
if r14 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r15 = r12[2]
|
||||
r16 = unbox(int, r15)
|
||||
x = r16
|
||||
r17 = f(x)
|
||||
r18 = box(int, r17)
|
||||
r19 = PySet_Add(r7, r18)
|
||||
r20 = r19 >= 0 :: signed
|
||||
L3:
|
||||
r21 = CPyDict_CheckSize(tmp_dict, r10)
|
||||
goto L1
|
||||
L4:
|
||||
r22 = CPy_NoErrOccured()
|
||||
L5:
|
||||
c = r7
|
||||
return 1
|
||||
def test4():
|
||||
r0 :: set
|
||||
r1 :: short_int
|
||||
x :: int
|
||||
r2 :: bit
|
||||
r3 :: int
|
||||
r4 :: object
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
r7 :: short_int
|
||||
d :: set
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
r1 = 2
|
||||
x = r1
|
||||
L1:
|
||||
r2 = r1 < 12 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = f(x)
|
||||
r4 = box(int, r3)
|
||||
r5 = PySet_Add(r0, r4)
|
||||
r6 = r5 >= 0 :: signed
|
||||
L3:
|
||||
r7 = r1 + 4
|
||||
r1 = r7
|
||||
x = r7
|
||||
goto L1
|
||||
L4:
|
||||
d = r0
|
||||
return 1
|
||||
def test5():
|
||||
r0 :: set
|
||||
r1 :: short_int
|
||||
x :: int
|
||||
r2 :: bit
|
||||
r3 :: int
|
||||
r4 :: object
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
r7 :: short_int
|
||||
e :: set
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
r1 = 2
|
||||
x = r1
|
||||
L1:
|
||||
r2 = r1 < 12 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = f(x)
|
||||
r4 = box(int, r3)
|
||||
r5 = PySet_Add(r0, r4)
|
||||
r6 = r5 >= 0 :: signed
|
||||
L3:
|
||||
r7 = r1 + 4
|
||||
r1 = r7
|
||||
x = r7
|
||||
goto L1
|
||||
L4:
|
||||
e = r0
|
||||
return 1
|
||||
|
||||
[case testNewSetFromIterable3]
|
||||
def f1(x: int) -> int:
|
||||
return x
|
||||
|
||||
def f2(x: int) -> int:
|
||||
return x * 10
|
||||
|
||||
def f3(x: int) -> int:
|
||||
return x + 1
|
||||
|
||||
def test() -> None:
|
||||
tmp_list = [1, 2, 3, 4, 5]
|
||||
a = set(f3(x) for x in (f2(y) for y in (f1(z) for z in tmp_list if z < 4)))
|
||||
[out]
|
||||
def f1(x):
|
||||
x :: int
|
||||
L0:
|
||||
return x
|
||||
def f2(x):
|
||||
x, r0 :: int
|
||||
L0:
|
||||
r0 = CPyTagged_Multiply(x, 20)
|
||||
return r0
|
||||
def f3(x):
|
||||
x, r0 :: int
|
||||
L0:
|
||||
r0 = CPyTagged_Add(x, 2)
|
||||
return r0
|
||||
def test():
|
||||
r0 :: list
|
||||
r1, r2, r3, r4, r5 :: object
|
||||
r6, r7, r8, r9, r10, r11 :: ptr
|
||||
tmp_list :: list
|
||||
r12 :: set
|
||||
r13, r14 :: list
|
||||
r15 :: short_int
|
||||
r16 :: ptr
|
||||
r17 :: native_int
|
||||
r18 :: short_int
|
||||
r19 :: bit
|
||||
r20 :: object
|
||||
r21, z :: int
|
||||
r22 :: native_int
|
||||
r23 :: bit
|
||||
r24 :: native_int
|
||||
r25, r26, r27 :: bit
|
||||
r28 :: bool
|
||||
r29 :: bit
|
||||
r30 :: int
|
||||
r31 :: object
|
||||
r32 :: i32
|
||||
r33 :: bit
|
||||
r34 :: short_int
|
||||
r35, r36, r37 :: object
|
||||
r38, y, r39 :: int
|
||||
r40 :: object
|
||||
r41 :: i32
|
||||
r42, r43 :: bit
|
||||
r44, r45, r46 :: object
|
||||
r47, x, r48 :: int
|
||||
r49 :: object
|
||||
r50 :: i32
|
||||
r51, r52 :: bit
|
||||
a :: set
|
||||
L0:
|
||||
r0 = PyList_New(5)
|
||||
r1 = object 1
|
||||
r2 = object 2
|
||||
r3 = object 3
|
||||
r4 = object 4
|
||||
r5 = object 5
|
||||
r6 = get_element_ptr r0 ob_item :: PyListObject
|
||||
r7 = load_mem r6 :: ptr*
|
||||
set_mem r7, r1 :: builtins.object*
|
||||
r8 = r7 + WORD_SIZE*1
|
||||
set_mem r8, r2 :: builtins.object*
|
||||
r9 = r7 + WORD_SIZE*2
|
||||
set_mem r9, r3 :: builtins.object*
|
||||
r10 = r7 + WORD_SIZE*3
|
||||
set_mem r10, r4 :: builtins.object*
|
||||
r11 = r7 + WORD_SIZE*4
|
||||
set_mem r11, r5 :: builtins.object*
|
||||
keep_alive r0
|
||||
tmp_list = r0
|
||||
r12 = PySet_New(0)
|
||||
r13 = PyList_New(0)
|
||||
r14 = PyList_New(0)
|
||||
r15 = 0
|
||||
L1:
|
||||
r16 = get_element_ptr tmp_list ob_size :: PyVarObject
|
||||
r17 = load_mem r16 :: native_int*
|
||||
keep_alive tmp_list
|
||||
r18 = r17 << 1
|
||||
r19 = r15 < r18 :: signed
|
||||
if r19 goto L2 else goto L9 :: bool
|
||||
L2:
|
||||
r20 = CPyList_GetItemUnsafe(tmp_list, r15)
|
||||
r21 = unbox(int, r20)
|
||||
z = r21
|
||||
r22 = z & 1
|
||||
r23 = r22 == 0
|
||||
r24 = 8 & 1
|
||||
r25 = r24 == 0
|
||||
r26 = r23 & r25
|
||||
if r26 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r27 = z < 8 :: signed
|
||||
r28 = r27
|
||||
goto L5
|
||||
L4:
|
||||
r29 = CPyTagged_IsLt_(z, 8)
|
||||
r28 = r29
|
||||
L5:
|
||||
if r28 goto L7 else goto L6 :: bool
|
||||
L6:
|
||||
goto L8
|
||||
L7:
|
||||
r30 = f1(z)
|
||||
r31 = box(int, r30)
|
||||
r32 = PyList_Append(r14, r31)
|
||||
r33 = r32 >= 0 :: signed
|
||||
L8:
|
||||
r34 = r15 + 2
|
||||
r15 = r34
|
||||
goto L1
|
||||
L9:
|
||||
r35 = PyObject_GetIter(r14)
|
||||
r36 = PyObject_GetIter(r35)
|
||||
L10:
|
||||
r37 = PyIter_Next(r36)
|
||||
if is_error(r37) goto L13 else goto L11
|
||||
L11:
|
||||
r38 = unbox(int, r37)
|
||||
y = r38
|
||||
r39 = f2(y)
|
||||
r40 = box(int, r39)
|
||||
r41 = PyList_Append(r13, r40)
|
||||
r42 = r41 >= 0 :: signed
|
||||
L12:
|
||||
goto L10
|
||||
L13:
|
||||
r43 = CPy_NoErrOccured()
|
||||
L14:
|
||||
r44 = PyObject_GetIter(r13)
|
||||
r45 = PyObject_GetIter(r44)
|
||||
L15:
|
||||
r46 = PyIter_Next(r45)
|
||||
if is_error(r46) goto L18 else goto L16
|
||||
L16:
|
||||
r47 = unbox(int, r46)
|
||||
x = r47
|
||||
r48 = f3(x)
|
||||
r49 = box(int, r48)
|
||||
r50 = PySet_Add(r12, r49)
|
||||
r51 = r50 >= 0 :: signed
|
||||
L17:
|
||||
goto L15
|
||||
L18:
|
||||
r52 = CPy_NoErrOccured()
|
||||
L19:
|
||||
a = r12
|
||||
return 1
|
||||
|
||||
[case testSetSize]
|
||||
from typing import Set
|
||||
def f() -> int:
|
||||
return len({1, 2, 3})
|
||||
[out]
|
||||
def f():
|
||||
r0 :: set
|
||||
r1 :: object
|
||||
r2 :: i32
|
||||
r3 :: bit
|
||||
r4 :: object
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
r7 :: object
|
||||
r8 :: i32
|
||||
r9 :: bit
|
||||
r10 :: ptr
|
||||
r11 :: native_int
|
||||
r12 :: short_int
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
r1 = object 1
|
||||
r2 = PySet_Add(r0, r1)
|
||||
r3 = r2 >= 0 :: signed
|
||||
r4 = object 2
|
||||
r5 = PySet_Add(r0, r4)
|
||||
r6 = r5 >= 0 :: signed
|
||||
r7 = object 3
|
||||
r8 = PySet_Add(r0, r7)
|
||||
r9 = r8 >= 0 :: signed
|
||||
r10 = get_element_ptr r0 used :: PySetObject
|
||||
r11 = load_mem r10 :: native_int*
|
||||
keep_alive r0
|
||||
r12 = r11 << 1
|
||||
return r12
|
||||
|
||||
[case testSetContains]
|
||||
from typing import Set
|
||||
def f() -> bool:
|
||||
x = {3, 4}
|
||||
return (5 in x)
|
||||
[out]
|
||||
def f():
|
||||
r0 :: set
|
||||
r1 :: object
|
||||
r2 :: i32
|
||||
r3 :: bit
|
||||
r4 :: object
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
x :: set
|
||||
r7 :: object
|
||||
r8 :: i32
|
||||
r9 :: bit
|
||||
r10 :: bool
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
r1 = object 3
|
||||
r2 = PySet_Add(r0, r1)
|
||||
r3 = r2 >= 0 :: signed
|
||||
r4 = object 4
|
||||
r5 = PySet_Add(r0, r4)
|
||||
r6 = r5 >= 0 :: signed
|
||||
x = r0
|
||||
r7 = object 5
|
||||
r8 = PySet_Contains(x, r7)
|
||||
r9 = r8 >= 0 :: signed
|
||||
r10 = truncate r8: i32 to builtins.bool
|
||||
return r10
|
||||
|
||||
[case testSetRemove]
|
||||
from typing import Set
|
||||
def f() -> Set[int]:
|
||||
x = set() # type: Set[int]
|
||||
x.remove(1)
|
||||
return x
|
||||
[out]
|
||||
def f():
|
||||
r0, x :: set
|
||||
r1 :: object
|
||||
r2 :: bit
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
x = r0
|
||||
r1 = object 1
|
||||
r2 = CPySet_Remove(x, r1)
|
||||
return x
|
||||
|
||||
[case testSetDiscard]
|
||||
from typing import Set
|
||||
def f() -> Set[int]:
|
||||
x = set() # type: Set[int]
|
||||
x.discard(1)
|
||||
return x
|
||||
[out]
|
||||
def f():
|
||||
r0, x :: set
|
||||
r1 :: object
|
||||
r2 :: i32
|
||||
r3 :: bit
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
x = r0
|
||||
r1 = object 1
|
||||
r2 = PySet_Discard(x, r1)
|
||||
r3 = r2 >= 0 :: signed
|
||||
return x
|
||||
|
||||
[case testSetAdd]
|
||||
from typing import Set
|
||||
def f() -> Set[int]:
|
||||
x = set() # type: Set[int]
|
||||
x.add(1)
|
||||
return x
|
||||
[out]
|
||||
def f():
|
||||
r0, x :: set
|
||||
r1 :: object
|
||||
r2 :: i32
|
||||
r3 :: bit
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
x = r0
|
||||
r1 = object 1
|
||||
r2 = PySet_Add(x, r1)
|
||||
r3 = r2 >= 0 :: signed
|
||||
return x
|
||||
|
||||
[case testSetClear]
|
||||
from typing import Set
|
||||
def f() -> Set[int]:
|
||||
x = set() # type: Set[int]
|
||||
x.clear()
|
||||
return x
|
||||
[out]
|
||||
def f():
|
||||
r0, x :: set
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
x = r0
|
||||
r1 = PySet_Clear(x)
|
||||
r2 = r1 >= 0 :: signed
|
||||
return x
|
||||
|
||||
[case testSetPop]
|
||||
from typing import Set
|
||||
def f(s : Set[int]) -> int:
|
||||
return s.pop()
|
||||
[out]
|
||||
def f(s):
|
||||
s :: set
|
||||
r0 :: object
|
||||
r1 :: int
|
||||
L0:
|
||||
r0 = PySet_Pop(s)
|
||||
r1 = unbox(int, r0)
|
||||
return r1
|
||||
|
||||
[case testSetUpdate]
|
||||
from typing import Set, List
|
||||
def update(s: Set[int], x: List[int]) -> None:
|
||||
s.update(x)
|
||||
[out]
|
||||
def update(s, x):
|
||||
s :: set
|
||||
x :: list
|
||||
r0 :: i32
|
||||
r1 :: bit
|
||||
L0:
|
||||
r0 = _PySet_Update(s, x)
|
||||
r1 = r0 >= 0 :: signed
|
||||
return 1
|
||||
|
||||
[case testSetDisplay]
|
||||
from typing import Set
|
||||
def f(x: Set[int], y: Set[int]) -> Set[int]:
|
||||
return {1, 2, *x, *y, 3}
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y, r0 :: set
|
||||
r1 :: object
|
||||
r2 :: i32
|
||||
r3 :: bit
|
||||
r4 :: object
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
r7 :: i32
|
||||
r8 :: bit
|
||||
r9 :: i32
|
||||
r10 :: bit
|
||||
r11 :: object
|
||||
r12 :: i32
|
||||
r13 :: bit
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
r1 = object 1
|
||||
r2 = PySet_Add(r0, r1)
|
||||
r3 = r2 >= 0 :: signed
|
||||
r4 = object 2
|
||||
r5 = PySet_Add(r0, r4)
|
||||
r6 = r5 >= 0 :: signed
|
||||
r7 = _PySet_Update(r0, x)
|
||||
r8 = r7 >= 0 :: signed
|
||||
r9 = _PySet_Update(r0, y)
|
||||
r10 = r9 >= 0 :: signed
|
||||
r11 = object 3
|
||||
r12 = PySet_Add(r0, r11)
|
||||
r13 = r12 >= 0 :: signed
|
||||
return r0
|
||||
|
||||
[case testOperatorInSetLiteral]
|
||||
from typing_extensions import Final
|
||||
|
||||
CONST: Final = "daylily"
|
||||
non_const = 10
|
||||
|
||||
def precomputed(i: object) -> bool:
|
||||
return i in {1, 2.0, 1 +2, 4j, "foo", b"bar", CONST, (None, (27,)), (), False}
|
||||
def not_precomputed_non_final_name(i: int) -> bool:
|
||||
return i in {non_const}
|
||||
def not_precomputed_nested_set(i: int) -> bool:
|
||||
return i in {frozenset({1}), 2}
|
||||
[out]
|
||||
def precomputed(i):
|
||||
i :: object
|
||||
r0 :: set
|
||||
r1 :: i32
|
||||
r2 :: bit
|
||||
r3 :: bool
|
||||
L0:
|
||||
r0 = frozenset({(), (None, (27,)), 1, 2.0, 3, 4j, False, b'bar', 'daylily', 'foo'})
|
||||
r1 = PySet_Contains(r0, i)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = truncate r1: i32 to builtins.bool
|
||||
return r3
|
||||
def not_precomputed_non_final_name(i):
|
||||
i :: int
|
||||
r0 :: dict
|
||||
r1 :: str
|
||||
r2 :: object
|
||||
r3 :: int
|
||||
r4 :: set
|
||||
r5 :: object
|
||||
r6 :: i32
|
||||
r7 :: bit
|
||||
r8 :: object
|
||||
r9 :: i32
|
||||
r10 :: bit
|
||||
r11 :: bool
|
||||
L0:
|
||||
r0 = __main__.globals :: static
|
||||
r1 = 'non_const'
|
||||
r2 = CPyDict_GetItem(r0, r1)
|
||||
r3 = unbox(int, r2)
|
||||
r4 = PySet_New(0)
|
||||
r5 = box(int, r3)
|
||||
r6 = PySet_Add(r4, r5)
|
||||
r7 = r6 >= 0 :: signed
|
||||
r8 = box(int, i)
|
||||
r9 = PySet_Contains(r4, r8)
|
||||
r10 = r9 >= 0 :: signed
|
||||
r11 = truncate r9: i32 to builtins.bool
|
||||
return r11
|
||||
def not_precomputed_nested_set(i):
|
||||
i :: int
|
||||
r0 :: set
|
||||
r1 :: object
|
||||
r2 :: i32
|
||||
r3 :: bit
|
||||
r4 :: object
|
||||
r5 :: set
|
||||
r6 :: i32
|
||||
r7 :: bit
|
||||
r8 :: object
|
||||
r9 :: i32
|
||||
r10 :: bit
|
||||
r11 :: object
|
||||
r12 :: i32
|
||||
r13 :: bit
|
||||
r14 :: bool
|
||||
L0:
|
||||
r0 = PySet_New(0)
|
||||
r1 = object 1
|
||||
r2 = PySet_Add(r0, r1)
|
||||
r3 = r2 >= 0 :: signed
|
||||
r4 = PyFrozenSet_New(r0)
|
||||
r5 = PySet_New(0)
|
||||
r6 = PySet_Add(r5, r4)
|
||||
r7 = r6 >= 0 :: signed
|
||||
r8 = object 2
|
||||
r9 = PySet_Add(r5, r8)
|
||||
r10 = r9 >= 0 :: signed
|
||||
r11 = box(int, i)
|
||||
r12 = PySet_Contains(r5, r11)
|
||||
r13 = r12 >= 0 :: signed
|
||||
r14 = truncate r12: i32 to builtins.bool
|
||||
return r14
|
||||
|
||||
[case testForSetLiteral]
|
||||
from typing_extensions import Final
|
||||
|
||||
CONST: Final = 10
|
||||
non_const = 20
|
||||
|
||||
def precomputed() -> None:
|
||||
for _ in {"None", "True", "False"}:
|
||||
pass
|
||||
|
||||
def precomputed2() -> None:
|
||||
for _ in {None, False, 1, 2.0, "4", b"5", (6,), 7j, CONST, CONST + 1}:
|
||||
pass
|
||||
|
||||
def not_precomputed() -> None:
|
||||
for not_optimized in {non_const}:
|
||||
pass
|
||||
|
||||
[out]
|
||||
def precomputed():
|
||||
r0 :: set
|
||||
r1, r2 :: object
|
||||
r3 :: str
|
||||
_ :: object
|
||||
r4 :: bit
|
||||
L0:
|
||||
r0 = frozenset({'False', 'None', 'True'})
|
||||
r1 = PyObject_GetIter(r0)
|
||||
L1:
|
||||
r2 = PyIter_Next(r1)
|
||||
if is_error(r2) goto L4 else goto L2
|
||||
L2:
|
||||
r3 = cast(str, r2)
|
||||
_ = r3
|
||||
L3:
|
||||
goto L1
|
||||
L4:
|
||||
r4 = CPy_NoErrOccured()
|
||||
L5:
|
||||
return 1
|
||||
def precomputed2():
|
||||
r0 :: set
|
||||
r1, r2, _ :: object
|
||||
r3 :: bit
|
||||
L0:
|
||||
r0 = frozenset({(6,), 1, 10, 11, 2.0, '4', 7j, False, None, b'5'})
|
||||
r1 = PyObject_GetIter(r0)
|
||||
L1:
|
||||
r2 = PyIter_Next(r1)
|
||||
if is_error(r2) goto L4 else goto L2
|
||||
L2:
|
||||
_ = r2
|
||||
L3:
|
||||
goto L1
|
||||
L4:
|
||||
r3 = CPy_NoErrOccured()
|
||||
L5:
|
||||
return 1
|
||||
def not_precomputed():
|
||||
r0 :: dict
|
||||
r1 :: str
|
||||
r2 :: object
|
||||
r3 :: int
|
||||
r4 :: set
|
||||
r5 :: object
|
||||
r6 :: i32
|
||||
r7 :: bit
|
||||
r8, r9 :: object
|
||||
r10, not_optimized :: int
|
||||
r11 :: bit
|
||||
L0:
|
||||
r0 = __main__.globals :: static
|
||||
r1 = 'non_const'
|
||||
r2 = CPyDict_GetItem(r0, r1)
|
||||
r3 = unbox(int, r2)
|
||||
r4 = PySet_New(0)
|
||||
r5 = box(int, r3)
|
||||
r6 = PySet_Add(r4, r5)
|
||||
r7 = r6 >= 0 :: signed
|
||||
r8 = PyObject_GetIter(r4)
|
||||
L1:
|
||||
r9 = PyIter_Next(r8)
|
||||
if is_error(r9) goto L4 else goto L2
|
||||
L2:
|
||||
r10 = unbox(int, r9)
|
||||
not_optimized = r10
|
||||
L3:
|
||||
goto L1
|
||||
L4:
|
||||
r11 = CPy_NoErrOccured()
|
||||
L5:
|
||||
return 1
|
||||
@@ -0,0 +1,257 @@
|
||||
[case testNativeCallsUsedInDispatchFunction]
|
||||
from functools import singledispatch
|
||||
@singledispatch
|
||||
def f(arg) -> bool:
|
||||
return False
|
||||
|
||||
@f.register
|
||||
def g(arg: int) -> bool:
|
||||
return True
|
||||
[out]
|
||||
def __mypyc_singledispatch_main_function_f__(arg):
|
||||
arg :: object
|
||||
L0:
|
||||
return 0
|
||||
def f_obj.__init__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.f_obj
|
||||
r0, r1 :: dict
|
||||
r2 :: str
|
||||
r3 :: i32
|
||||
r4 :: bit
|
||||
L0:
|
||||
r0 = PyDict_New()
|
||||
__mypyc_self__.registry = r0
|
||||
r1 = PyDict_New()
|
||||
r2 = 'dispatch_cache'
|
||||
r3 = PyObject_SetAttr(__mypyc_self__, r2, r1)
|
||||
r4 = r3 >= 0 :: signed
|
||||
return 1
|
||||
def f_obj.__call__(__mypyc_self__, arg):
|
||||
__mypyc_self__ :: __main__.f_obj
|
||||
arg :: object
|
||||
r0 :: ptr
|
||||
r1 :: object
|
||||
r2 :: dict
|
||||
r3, r4 :: object
|
||||
r5 :: bit
|
||||
r6, r7 :: object
|
||||
r8 :: str
|
||||
r9 :: object
|
||||
r10 :: dict
|
||||
r11 :: object
|
||||
r12 :: i32
|
||||
r13 :: bit
|
||||
r14 :: object
|
||||
r15 :: ptr
|
||||
r16 :: object
|
||||
r17 :: bit
|
||||
r18 :: int
|
||||
r19 :: bit
|
||||
r20 :: int
|
||||
r21 :: bool
|
||||
r22 :: object
|
||||
r23 :: bool
|
||||
L0:
|
||||
r0 = get_element_ptr arg ob_type :: PyObject
|
||||
r1 = load_mem r0 :: builtins.object*
|
||||
keep_alive arg
|
||||
r2 = __mypyc_self__.dispatch_cache
|
||||
r3 = CPyDict_GetWithNone(r2, r1)
|
||||
r4 = load_address _Py_NoneStruct
|
||||
r5 = r3 != r4
|
||||
if r5 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r6 = r3
|
||||
goto L3
|
||||
L2:
|
||||
r7 = functools :: module
|
||||
r8 = '_find_impl'
|
||||
r9 = CPyObject_GetAttr(r7, r8)
|
||||
r10 = __mypyc_self__.registry
|
||||
r11 = PyObject_CallFunctionObjArgs(r9, r1, r10, 0)
|
||||
r12 = CPyDict_SetItem(r2, r1, r11)
|
||||
r13 = r12 >= 0 :: signed
|
||||
r6 = r11
|
||||
L3:
|
||||
r14 = load_address PyLong_Type
|
||||
r15 = get_element_ptr r6 ob_type :: PyObject
|
||||
r16 = load_mem r15 :: builtins.object*
|
||||
keep_alive r6
|
||||
r17 = r16 == r14
|
||||
if r17 goto L4 else goto L7 :: bool
|
||||
L4:
|
||||
r18 = unbox(int, r6)
|
||||
r19 = r18 == 0
|
||||
if r19 goto L5 else goto L6 :: bool
|
||||
L5:
|
||||
r20 = unbox(int, arg)
|
||||
r21 = g(r20)
|
||||
return r21
|
||||
L6:
|
||||
unreachable
|
||||
L7:
|
||||
r22 = PyObject_CallFunctionObjArgs(r6, arg, 0)
|
||||
r23 = unbox(bool, r22)
|
||||
return r23
|
||||
def f_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def f_obj.register(__mypyc_self__, cls, func):
|
||||
__mypyc_self__ :: __main__.f_obj
|
||||
cls, func, r0 :: object
|
||||
L0:
|
||||
r0 = CPySingledispatch_RegisterFunction(__mypyc_self__, cls, func)
|
||||
return r0
|
||||
def f(arg):
|
||||
arg :: object
|
||||
r0 :: dict
|
||||
r1 :: str
|
||||
r2 :: object
|
||||
r3 :: bool
|
||||
L0:
|
||||
r0 = __main__.globals :: static
|
||||
r1 = 'f'
|
||||
r2 = CPyDict_GetItem(r0, r1)
|
||||
r3 = f_obj.__call__(r2, arg)
|
||||
return r3
|
||||
def g(arg):
|
||||
arg :: int
|
||||
L0:
|
||||
return 1
|
||||
|
||||
|
||||
[case testCallsToSingledispatchFunctionsAreNative]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def f(x: object) -> None:
|
||||
pass
|
||||
|
||||
def test():
|
||||
f('a')
|
||||
[out]
|
||||
def __mypyc_singledispatch_main_function_f__(x):
|
||||
x :: object
|
||||
L0:
|
||||
return 1
|
||||
def f_obj.__init__(__mypyc_self__):
|
||||
__mypyc_self__ :: __main__.f_obj
|
||||
r0, r1 :: dict
|
||||
r2 :: str
|
||||
r3 :: i32
|
||||
r4 :: bit
|
||||
L0:
|
||||
r0 = PyDict_New()
|
||||
__mypyc_self__.registry = r0
|
||||
r1 = PyDict_New()
|
||||
r2 = 'dispatch_cache'
|
||||
r3 = PyObject_SetAttr(__mypyc_self__, r2, r1)
|
||||
r4 = r3 >= 0 :: signed
|
||||
return 1
|
||||
def f_obj.__call__(__mypyc_self__, x):
|
||||
__mypyc_self__ :: __main__.f_obj
|
||||
x :: object
|
||||
r0 :: ptr
|
||||
r1 :: object
|
||||
r2 :: dict
|
||||
r3, r4 :: object
|
||||
r5 :: bit
|
||||
r6, r7 :: object
|
||||
r8 :: str
|
||||
r9 :: object
|
||||
r10 :: dict
|
||||
r11 :: object
|
||||
r12 :: i32
|
||||
r13 :: bit
|
||||
r14 :: object
|
||||
r15 :: ptr
|
||||
r16 :: object
|
||||
r17 :: bit
|
||||
r18 :: int
|
||||
r19 :: object
|
||||
r20 :: None
|
||||
L0:
|
||||
r0 = get_element_ptr x ob_type :: PyObject
|
||||
r1 = load_mem r0 :: builtins.object*
|
||||
keep_alive x
|
||||
r2 = __mypyc_self__.dispatch_cache
|
||||
r3 = CPyDict_GetWithNone(r2, r1)
|
||||
r4 = load_address _Py_NoneStruct
|
||||
r5 = r3 != r4
|
||||
if r5 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r6 = r3
|
||||
goto L3
|
||||
L2:
|
||||
r7 = functools :: module
|
||||
r8 = '_find_impl'
|
||||
r9 = CPyObject_GetAttr(r7, r8)
|
||||
r10 = __mypyc_self__.registry
|
||||
r11 = PyObject_CallFunctionObjArgs(r9, r1, r10, 0)
|
||||
r12 = CPyDict_SetItem(r2, r1, r11)
|
||||
r13 = r12 >= 0 :: signed
|
||||
r6 = r11
|
||||
L3:
|
||||
r14 = load_address PyLong_Type
|
||||
r15 = get_element_ptr r6 ob_type :: PyObject
|
||||
r16 = load_mem r15 :: builtins.object*
|
||||
keep_alive r6
|
||||
r17 = r16 == r14
|
||||
if r17 goto L4 else goto L5 :: bool
|
||||
L4:
|
||||
r18 = unbox(int, r6)
|
||||
unreachable
|
||||
L5:
|
||||
r19 = PyObject_CallFunctionObjArgs(r6, x, 0)
|
||||
r20 = unbox(None, r19)
|
||||
return r20
|
||||
def f_obj.__get__(__mypyc_self__, instance, owner):
|
||||
__mypyc_self__, instance, owner, r0 :: object
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = load_address _Py_NoneStruct
|
||||
r1 = instance == r0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return __mypyc_self__
|
||||
L2:
|
||||
r2 = PyMethod_New(__mypyc_self__, instance)
|
||||
return r2
|
||||
def f_obj.register(__mypyc_self__, cls, func):
|
||||
__mypyc_self__ :: __main__.f_obj
|
||||
cls, func, r0 :: object
|
||||
L0:
|
||||
r0 = CPySingledispatch_RegisterFunction(__mypyc_self__, cls, func)
|
||||
return r0
|
||||
def f(x):
|
||||
x :: object
|
||||
r0 :: dict
|
||||
r1 :: str
|
||||
r2 :: object
|
||||
r3 :: None
|
||||
L0:
|
||||
r0 = __main__.globals :: static
|
||||
r1 = 'f'
|
||||
r2 = CPyDict_GetItem(r0, r1)
|
||||
r3 = f_obj.__call__(r2, x)
|
||||
return r3
|
||||
def test():
|
||||
r0 :: str
|
||||
r1 :: None
|
||||
r2 :: object
|
||||
L0:
|
||||
r0 = 'a'
|
||||
r1 = f(r0)
|
||||
r2 = box(None, 1)
|
||||
return r2
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,314 @@
|
||||
[case testStrSplit]
|
||||
from typing import Optional, List
|
||||
|
||||
def do_split(s: str, sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]:
|
||||
if sep is not None:
|
||||
if max_split is not None:
|
||||
return s.split(sep, max_split)
|
||||
else:
|
||||
return s.split(sep)
|
||||
return s.split()
|
||||
[out]
|
||||
def do_split(s, sep, max_split):
|
||||
s :: str
|
||||
sep :: union[str, None]
|
||||
max_split :: union[int, None]
|
||||
r0, r1, r2 :: object
|
||||
r3 :: bit
|
||||
r4 :: object
|
||||
r5 :: bit
|
||||
r6 :: str
|
||||
r7 :: int
|
||||
r8 :: list
|
||||
r9 :: str
|
||||
r10, r11 :: list
|
||||
L0:
|
||||
if is_error(sep) goto L1 else goto L2
|
||||
L1:
|
||||
r0 = box(None, 1)
|
||||
sep = r0
|
||||
L2:
|
||||
if is_error(max_split) goto L3 else goto L4
|
||||
L3:
|
||||
r1 = box(None, 1)
|
||||
max_split = r1
|
||||
L4:
|
||||
r2 = load_address _Py_NoneStruct
|
||||
r3 = sep != r2
|
||||
if r3 goto L5 else goto L9 :: bool
|
||||
L5:
|
||||
r4 = load_address _Py_NoneStruct
|
||||
r5 = max_split != r4
|
||||
if r5 goto L6 else goto L7 :: bool
|
||||
L6:
|
||||
r6 = cast(str, sep)
|
||||
r7 = unbox(int, max_split)
|
||||
r8 = CPyStr_Split(s, r6, r7)
|
||||
return r8
|
||||
L7:
|
||||
r9 = cast(str, sep)
|
||||
r10 = PyUnicode_Split(s, r9, -1)
|
||||
return r10
|
||||
L8:
|
||||
L9:
|
||||
r11 = PyUnicode_Split(s, 0, -1)
|
||||
return r11
|
||||
|
||||
|
||||
[case testStrEquality]
|
||||
def eq(x: str, y: str) -> bool:
|
||||
return x == y
|
||||
|
||||
def neq(x: str, y: str) -> bool:
|
||||
return x != y
|
||||
|
||||
[out]
|
||||
def eq(x, y):
|
||||
x, y :: str
|
||||
r0 :: i32
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
r3, r4, r5 :: bit
|
||||
L0:
|
||||
r0 = PyUnicode_Compare(x, y)
|
||||
r1 = r0 == -1
|
||||
if r1 goto L1 else goto L3 :: bool
|
||||
L1:
|
||||
r2 = PyErr_Occurred()
|
||||
r3 = r2 != 0
|
||||
if r3 goto L2 else goto L3 :: bool
|
||||
L2:
|
||||
r4 = CPy_KeepPropagating()
|
||||
L3:
|
||||
r5 = r0 == 0
|
||||
return r5
|
||||
def neq(x, y):
|
||||
x, y :: str
|
||||
r0 :: i32
|
||||
r1 :: bit
|
||||
r2 :: object
|
||||
r3, r4, r5 :: bit
|
||||
L0:
|
||||
r0 = PyUnicode_Compare(x, y)
|
||||
r1 = r0 == -1
|
||||
if r1 goto L1 else goto L3 :: bool
|
||||
L1:
|
||||
r2 = PyErr_Occurred()
|
||||
r3 = r2 != 0
|
||||
if r3 goto L2 else goto L3 :: bool
|
||||
L2:
|
||||
r4 = CPy_KeepPropagating()
|
||||
L3:
|
||||
r5 = r0 != 0
|
||||
return r5
|
||||
|
||||
[case testStrReplace]
|
||||
from typing import Optional
|
||||
|
||||
def do_replace(s: str, old_substr: str, new_substr: str, max_count: Optional[int] = None) -> str:
|
||||
if max_count is not None:
|
||||
return s.replace(old_substr, new_substr, max_count)
|
||||
else:
|
||||
return s.replace(old_substr, new_substr)
|
||||
[out]
|
||||
def do_replace(s, old_substr, new_substr, max_count):
|
||||
s, old_substr, new_substr :: str
|
||||
max_count :: union[int, None]
|
||||
r0, r1 :: object
|
||||
r2 :: bit
|
||||
r3 :: int
|
||||
r4, r5 :: str
|
||||
L0:
|
||||
if is_error(max_count) goto L1 else goto L2
|
||||
L1:
|
||||
r0 = box(None, 1)
|
||||
max_count = r0
|
||||
L2:
|
||||
r1 = load_address _Py_NoneStruct
|
||||
r2 = max_count != r1
|
||||
if r2 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r3 = unbox(int, max_count)
|
||||
r4 = CPyStr_Replace(s, old_substr, new_substr, r3)
|
||||
return r4
|
||||
L4:
|
||||
r5 = PyUnicode_Replace(s, old_substr, new_substr, -1)
|
||||
return r5
|
||||
L5:
|
||||
unreachable
|
||||
|
||||
[case testStrToBool]
|
||||
def is_true(x: str) -> bool:
|
||||
if x:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
[out]
|
||||
def is_true(x):
|
||||
x :: str
|
||||
r0 :: bit
|
||||
L0:
|
||||
r0 = CPyStr_IsTrue(x)
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
return 1
|
||||
L2:
|
||||
return 0
|
||||
L3:
|
||||
unreachable
|
||||
|
||||
[case testStringFormatMethod]
|
||||
def f(s: str, num: int) -> None:
|
||||
s1 = "Hi! I'm {}, and I'm {} years old.".format(s, num)
|
||||
s2 = ''.format()
|
||||
s3 = 'abc'.format()
|
||||
s4 = '}}{}{{{}}}{{{}'.format(num, num, num)
|
||||
[out]
|
||||
def f(s, num):
|
||||
s :: str
|
||||
num :: int
|
||||
r0, r1, r2, r3, r4, s1, r5, s2, r6, s3, r7, r8, r9, r10, r11, r12, r13, s4 :: str
|
||||
L0:
|
||||
r0 = CPyTagged_Str(num)
|
||||
r1 = "Hi! I'm "
|
||||
r2 = ", and I'm "
|
||||
r3 = ' years old.'
|
||||
r4 = CPyStr_Build(5, r1, s, r2, r0, r3)
|
||||
s1 = r4
|
||||
r5 = ''
|
||||
s2 = r5
|
||||
r6 = 'abc'
|
||||
s3 = r6
|
||||
r7 = CPyTagged_Str(num)
|
||||
r8 = CPyTagged_Str(num)
|
||||
r9 = CPyTagged_Str(num)
|
||||
r10 = '}'
|
||||
r11 = '{'
|
||||
r12 = '}{'
|
||||
r13 = CPyStr_Build(6, r10, r7, r11, r8, r12, r9)
|
||||
s4 = r13
|
||||
return 1
|
||||
|
||||
[case testFStrings]
|
||||
def f(var: str, num: int) -> None:
|
||||
s1 = f"Hi! I'm {var}. I am {num} years old."
|
||||
s2 = f'Hello {var:>{num}}'
|
||||
s3 = f''
|
||||
s4 = f'abc'
|
||||
[out]
|
||||
def f(var, num):
|
||||
var :: str
|
||||
num :: int
|
||||
r0, r1, r2, r3, r4, s1, r5, r6, r7, r8, r9, r10, r11 :: str
|
||||
r12 :: object
|
||||
r13 :: str
|
||||
r14 :: list
|
||||
r15, r16, r17 :: ptr
|
||||
r18, s2, r19, s3, r20, s4 :: str
|
||||
L0:
|
||||
r0 = "Hi! I'm "
|
||||
r1 = '. I am '
|
||||
r2 = CPyTagged_Str(num)
|
||||
r3 = ' years old.'
|
||||
r4 = CPyStr_Build(5, r0, var, r1, r2, r3)
|
||||
s1 = r4
|
||||
r5 = ''
|
||||
r6 = 'Hello '
|
||||
r7 = '{:{}}'
|
||||
r8 = '>'
|
||||
r9 = CPyTagged_Str(num)
|
||||
r10 = CPyStr_Build(2, r8, r9)
|
||||
r11 = 'format'
|
||||
r12 = CPyObject_CallMethodObjArgs(r7, r11, var, r10, 0)
|
||||
r13 = cast(str, r12)
|
||||
r14 = PyList_New(2)
|
||||
r15 = get_element_ptr r14 ob_item :: PyListObject
|
||||
r16 = load_mem r15 :: ptr*
|
||||
set_mem r16, r6 :: builtins.object*
|
||||
r17 = r16 + WORD_SIZE*1
|
||||
set_mem r17, r13 :: builtins.object*
|
||||
keep_alive r14
|
||||
r18 = PyUnicode_Join(r5, r14)
|
||||
s2 = r18
|
||||
r19 = ''
|
||||
s3 = r19
|
||||
r20 = 'abc'
|
||||
s4 = r20
|
||||
return 1
|
||||
|
||||
[case testStringFormattingCStyle]
|
||||
def f(var: str, num: int) -> None:
|
||||
s1 = "Hi! I'm %s." % var
|
||||
s2 = "I am %d years old." % num
|
||||
s3 = "Hi! I'm %s. I am %d years old." % (var, num)
|
||||
s4 = "Float: %f" % num
|
||||
[typing fixtures/typing-full.pyi]
|
||||
[out]
|
||||
def f(var, num):
|
||||
var :: str
|
||||
num :: int
|
||||
r0, r1, r2, s1, r3, r4, r5, r6, s2, r7, r8, r9, r10, r11, s3, r12 :: str
|
||||
r13, r14 :: object
|
||||
r15, s4 :: str
|
||||
L0:
|
||||
r0 = "Hi! I'm "
|
||||
r1 = '.'
|
||||
r2 = CPyStr_Build(3, r0, var, r1)
|
||||
s1 = r2
|
||||
r3 = CPyTagged_Str(num)
|
||||
r4 = 'I am '
|
||||
r5 = ' years old.'
|
||||
r6 = CPyStr_Build(3, r4, r3, r5)
|
||||
s2 = r6
|
||||
r7 = CPyTagged_Str(num)
|
||||
r8 = "Hi! I'm "
|
||||
r9 = '. I am '
|
||||
r10 = ' years old.'
|
||||
r11 = CPyStr_Build(5, r8, var, r9, r7, r10)
|
||||
s3 = r11
|
||||
r12 = 'Float: %f'
|
||||
r13 = box(int, num)
|
||||
r14 = PyNumber_Remainder(r12, r13)
|
||||
r15 = cast(str, r14)
|
||||
s4 = r15
|
||||
return 1
|
||||
|
||||
[case testDecode]
|
||||
def f(b: bytes) -> None:
|
||||
b.decode()
|
||||
b.decode('utf-8')
|
||||
b.decode('utf-8', 'backslashreplace')
|
||||
[out]
|
||||
def f(b):
|
||||
b :: bytes
|
||||
r0, r1, r2, r3, r4, r5 :: str
|
||||
L0:
|
||||
r0 = CPy_Decode(b, 0, 0)
|
||||
r1 = 'utf-8'
|
||||
r2 = CPy_Decode(b, r1, 0)
|
||||
r3 = 'utf-8'
|
||||
r4 = 'backslashreplace'
|
||||
r5 = CPy_Decode(b, r3, r4)
|
||||
return 1
|
||||
|
||||
[case testEncode]
|
||||
def f(s: str) -> None:
|
||||
s.encode()
|
||||
s.encode('utf-8')
|
||||
s.encode('ascii', 'backslashreplace')
|
||||
[out]
|
||||
def f(s):
|
||||
s :: str
|
||||
r0 :: bytes
|
||||
r1 :: str
|
||||
r2 :: bytes
|
||||
r3, r4 :: str
|
||||
r5 :: bytes
|
||||
L0:
|
||||
r0 = CPy_Encode(s, 0, 0)
|
||||
r1 = 'utf-8'
|
||||
r2 = CPy_Encode(s, r1, 0)
|
||||
r3 = 'ascii'
|
||||
r4 = 'backslashreplace'
|
||||
r5 = CPy_Encode(s, r3, r4)
|
||||
return 1
|
||||
@@ -0,0 +1,12 @@
|
||||
[case testStripAssert1]
|
||||
def g():
|
||||
x = 1 + 2
|
||||
assert x < 5
|
||||
return x
|
||||
[out]
|
||||
def g():
|
||||
r0, x :: object
|
||||
L0:
|
||||
r0 = object 3
|
||||
x = r0
|
||||
return x
|
||||
@@ -0,0 +1,523 @@
|
||||
[case testTryExcept1]
|
||||
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
|
||||
L0:
|
||||
L1:
|
||||
r0 = builtins :: module
|
||||
r1 = 'object'
|
||||
r2 = CPyObject_GetAttr(r0, r1)
|
||||
r3 = PyObject_CallFunctionObjArgs(r2, 0)
|
||||
goto L5
|
||||
L2: (handler for L1)
|
||||
r4 = CPy_CatchError()
|
||||
r5 = 'weeee'
|
||||
r6 = builtins :: module
|
||||
r7 = 'print'
|
||||
r8 = CPyObject_GetAttr(r6, r7)
|
||||
r9 = PyObject_CallFunctionObjArgs(r8, r5, 0)
|
||||
L3:
|
||||
CPy_RestoreExcInfo(r4)
|
||||
goto L5
|
||||
L4: (handler for L2)
|
||||
CPy_RestoreExcInfo(r4)
|
||||
r10 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L5:
|
||||
return 1
|
||||
|
||||
[case testTryExcept2]
|
||||
def g(b: bool) -> None:
|
||||
try:
|
||||
if b:
|
||||
object()
|
||||
else:
|
||||
str('hi')
|
||||
except:
|
||||
print("weeee")
|
||||
[out]
|
||||
def g(b):
|
||||
b :: bool
|
||||
r0 :: object
|
||||
r1 :: str
|
||||
r2, r3 :: object
|
||||
r4, r5 :: str
|
||||
r6 :: tuple[object, object, object]
|
||||
r7 :: str
|
||||
r8 :: object
|
||||
r9 :: str
|
||||
r10, r11 :: object
|
||||
r12 :: bit
|
||||
L0:
|
||||
L1:
|
||||
if b goto L2 else goto L3 :: bool
|
||||
L2:
|
||||
r0 = builtins :: module
|
||||
r1 = 'object'
|
||||
r2 = CPyObject_GetAttr(r0, r1)
|
||||
r3 = PyObject_CallFunctionObjArgs(r2, 0)
|
||||
goto L4
|
||||
L3:
|
||||
r4 = 'hi'
|
||||
r5 = PyObject_Str(r4)
|
||||
L4:
|
||||
goto L8
|
||||
L5: (handler for L1, L2, L3, L4)
|
||||
r6 = CPy_CatchError()
|
||||
r7 = 'weeee'
|
||||
r8 = builtins :: module
|
||||
r9 = 'print'
|
||||
r10 = CPyObject_GetAttr(r8, r9)
|
||||
r11 = PyObject_CallFunctionObjArgs(r10, r7, 0)
|
||||
L6:
|
||||
CPy_RestoreExcInfo(r6)
|
||||
goto L8
|
||||
L7: (handler for L5)
|
||||
CPy_RestoreExcInfo(r6)
|
||||
r12 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L8:
|
||||
return 1
|
||||
|
||||
[case testTryExcept3]
|
||||
def g() -> None:
|
||||
try:
|
||||
print('a')
|
||||
try:
|
||||
object()
|
||||
except AttributeError as e:
|
||||
print('b', e)
|
||||
except:
|
||||
print("weeee")
|
||||
[out]
|
||||
def g():
|
||||
r0 :: str
|
||||
r1 :: object
|
||||
r2 :: str
|
||||
r3, r4, r5 :: object
|
||||
r6 :: str
|
||||
r7, r8 :: object
|
||||
r9 :: tuple[object, object, object]
|
||||
r10 :: object
|
||||
r11 :: str
|
||||
r12 :: object
|
||||
r13 :: bit
|
||||
r14, e :: object
|
||||
r15 :: str
|
||||
r16 :: object
|
||||
r17 :: str
|
||||
r18, r19 :: object
|
||||
r20 :: bit
|
||||
r21 :: tuple[object, object, object]
|
||||
r22 :: str
|
||||
r23 :: object
|
||||
r24 :: str
|
||||
r25, r26 :: object
|
||||
r27 :: bit
|
||||
L0:
|
||||
L1:
|
||||
r0 = 'a'
|
||||
r1 = builtins :: module
|
||||
r2 = 'print'
|
||||
r3 = CPyObject_GetAttr(r1, r2)
|
||||
r4 = PyObject_CallFunctionObjArgs(r3, r0, 0)
|
||||
L2:
|
||||
r5 = builtins :: module
|
||||
r6 = 'object'
|
||||
r7 = CPyObject_GetAttr(r5, r6)
|
||||
r8 = PyObject_CallFunctionObjArgs(r7, 0)
|
||||
goto L8
|
||||
L3: (handler for L2)
|
||||
r9 = CPy_CatchError()
|
||||
r10 = builtins :: module
|
||||
r11 = 'AttributeError'
|
||||
r12 = CPyObject_GetAttr(r10, r11)
|
||||
r13 = CPy_ExceptionMatches(r12)
|
||||
if r13 goto L4 else goto L5 :: bool
|
||||
L4:
|
||||
r14 = CPy_GetExcValue()
|
||||
e = r14
|
||||
r15 = 'b'
|
||||
r16 = builtins :: module
|
||||
r17 = 'print'
|
||||
r18 = CPyObject_GetAttr(r16, r17)
|
||||
r19 = PyObject_CallFunctionObjArgs(r18, r15, e, 0)
|
||||
goto L6
|
||||
L5:
|
||||
CPy_Reraise()
|
||||
unreachable
|
||||
L6:
|
||||
CPy_RestoreExcInfo(r9)
|
||||
goto L8
|
||||
L7: (handler for L3, L4, L5)
|
||||
CPy_RestoreExcInfo(r9)
|
||||
r20 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L8:
|
||||
goto L12
|
||||
L9: (handler for L1, L6, L7, L8)
|
||||
r21 = CPy_CatchError()
|
||||
r22 = 'weeee'
|
||||
r23 = builtins :: module
|
||||
r24 = 'print'
|
||||
r25 = CPyObject_GetAttr(r23, r24)
|
||||
r26 = PyObject_CallFunctionObjArgs(r25, r22, 0)
|
||||
L10:
|
||||
CPy_RestoreExcInfo(r21)
|
||||
goto L12
|
||||
L11: (handler for L9)
|
||||
CPy_RestoreExcInfo(r21)
|
||||
r27 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L12:
|
||||
return 1
|
||||
|
||||
[case testTryExcept4]
|
||||
def g() -> None:
|
||||
try:
|
||||
pass
|
||||
except KeyError:
|
||||
print("weeee")
|
||||
except IndexError:
|
||||
print("yo")
|
||||
[out]
|
||||
def g():
|
||||
r0 :: tuple[object, object, object]
|
||||
r1 :: object
|
||||
r2 :: str
|
||||
r3 :: object
|
||||
r4 :: bit
|
||||
r5 :: str
|
||||
r6 :: object
|
||||
r7 :: str
|
||||
r8, r9, r10 :: object
|
||||
r11 :: str
|
||||
r12 :: object
|
||||
r13 :: bit
|
||||
r14 :: str
|
||||
r15 :: object
|
||||
r16 :: str
|
||||
r17, r18 :: object
|
||||
r19 :: bit
|
||||
L0:
|
||||
L1:
|
||||
goto L9
|
||||
L2: (handler for L1)
|
||||
r0 = CPy_CatchError()
|
||||
r1 = builtins :: module
|
||||
r2 = 'KeyError'
|
||||
r3 = CPyObject_GetAttr(r1, r2)
|
||||
r4 = CPy_ExceptionMatches(r3)
|
||||
if r4 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r5 = 'weeee'
|
||||
r6 = builtins :: module
|
||||
r7 = 'print'
|
||||
r8 = CPyObject_GetAttr(r6, r7)
|
||||
r9 = PyObject_CallFunctionObjArgs(r8, r5, 0)
|
||||
goto L7
|
||||
L4:
|
||||
r10 = builtins :: module
|
||||
r11 = 'IndexError'
|
||||
r12 = CPyObject_GetAttr(r10, r11)
|
||||
r13 = CPy_ExceptionMatches(r12)
|
||||
if r13 goto L5 else goto L6 :: bool
|
||||
L5:
|
||||
r14 = 'yo'
|
||||
r15 = builtins :: module
|
||||
r16 = 'print'
|
||||
r17 = CPyObject_GetAttr(r15, r16)
|
||||
r18 = PyObject_CallFunctionObjArgs(r17, r14, 0)
|
||||
goto L7
|
||||
L6:
|
||||
CPy_Reraise()
|
||||
unreachable
|
||||
L7:
|
||||
CPy_RestoreExcInfo(r0)
|
||||
goto L9
|
||||
L8: (handler for L2, L3, L4, L5, L6)
|
||||
CPy_RestoreExcInfo(r0)
|
||||
r19 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L9:
|
||||
return 1
|
||||
|
||||
[case testTryFinally]
|
||||
def a(b: bool) -> None:
|
||||
try:
|
||||
if b:
|
||||
raise Exception('hi')
|
||||
finally:
|
||||
print('finally')
|
||||
[out]
|
||||
def a(b):
|
||||
b :: bool
|
||||
r0 :: str
|
||||
r1 :: object
|
||||
r2 :: str
|
||||
r3, r4 :: object
|
||||
r5, r6, r7 :: tuple[object, object, object]
|
||||
r8 :: str
|
||||
r9 :: object
|
||||
r10 :: str
|
||||
r11, r12 :: object
|
||||
r13 :: bit
|
||||
L0:
|
||||
L1:
|
||||
if b goto L2 else goto L3 :: bool
|
||||
L2:
|
||||
r0 = 'hi'
|
||||
r1 = builtins :: module
|
||||
r2 = 'Exception'
|
||||
r3 = CPyObject_GetAttr(r1, r2)
|
||||
r4 = PyObject_CallFunctionObjArgs(r3, r0, 0)
|
||||
CPy_Raise(r4)
|
||||
unreachable
|
||||
L3:
|
||||
L4:
|
||||
L5:
|
||||
r5 = <error> :: tuple[object, object, object]
|
||||
r6 = r5
|
||||
goto L7
|
||||
L6: (handler for L1, L2, L3)
|
||||
r7 = CPy_CatchError()
|
||||
r6 = r7
|
||||
L7:
|
||||
r8 = 'finally'
|
||||
r9 = builtins :: module
|
||||
r10 = 'print'
|
||||
r11 = CPyObject_GetAttr(r9, r10)
|
||||
r12 = PyObject_CallFunctionObjArgs(r11, r8, 0)
|
||||
if is_error(r6) goto L9 else goto L8
|
||||
L8:
|
||||
CPy_Reraise()
|
||||
unreachable
|
||||
L9:
|
||||
goto L13
|
||||
L10: (handler for L7, L8)
|
||||
if is_error(r6) goto L12 else goto L11
|
||||
L11:
|
||||
CPy_RestoreExcInfo(r6)
|
||||
L12:
|
||||
r13 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L13:
|
||||
return 1
|
||||
|
||||
[case testWith]
|
||||
from typing import Any
|
||||
def foo(x: Any) -> None:
|
||||
with x() as y:
|
||||
print('hello')
|
||||
[out]
|
||||
def foo(x):
|
||||
x, r0, r1 :: object
|
||||
r2 :: str
|
||||
r3 :: object
|
||||
r4 :: str
|
||||
r5, r6 :: object
|
||||
r7 :: bool
|
||||
y :: object
|
||||
r8 :: str
|
||||
r9 :: object
|
||||
r10 :: str
|
||||
r11, r12 :: object
|
||||
r13, r14 :: tuple[object, object, object]
|
||||
r15, r16, r17, r18 :: object
|
||||
r19 :: i32
|
||||
r20 :: bit
|
||||
r21 :: bool
|
||||
r22 :: bit
|
||||
r23, r24, r25 :: tuple[object, object, object]
|
||||
r26, r27 :: object
|
||||
r28 :: bit
|
||||
L0:
|
||||
r0 = PyObject_CallFunctionObjArgs(x, 0)
|
||||
r1 = PyObject_Type(r0)
|
||||
r2 = '__exit__'
|
||||
r3 = CPyObject_GetAttr(r1, r2)
|
||||
r4 = '__enter__'
|
||||
r5 = CPyObject_GetAttr(r1, r4)
|
||||
r6 = PyObject_CallFunctionObjArgs(r5, r0, 0)
|
||||
r7 = 1
|
||||
L1:
|
||||
L2:
|
||||
y = r6
|
||||
r8 = 'hello'
|
||||
r9 = builtins :: module
|
||||
r10 = 'print'
|
||||
r11 = CPyObject_GetAttr(r9, r10)
|
||||
r12 = PyObject_CallFunctionObjArgs(r11, r8, 0)
|
||||
goto L8
|
||||
L3: (handler for L2)
|
||||
r13 = CPy_CatchError()
|
||||
r7 = 0
|
||||
r14 = CPy_GetExcInfo()
|
||||
r15 = r14[0]
|
||||
r16 = r14[1]
|
||||
r17 = r14[2]
|
||||
r18 = PyObject_CallFunctionObjArgs(r3, r0, r15, r16, r17, 0)
|
||||
r19 = PyObject_IsTrue(r18)
|
||||
r20 = r19 >= 0 :: signed
|
||||
r21 = truncate r19: i32 to builtins.bool
|
||||
if r21 goto L5 else goto L4 :: bool
|
||||
L4:
|
||||
CPy_Reraise()
|
||||
unreachable
|
||||
L5:
|
||||
L6:
|
||||
CPy_RestoreExcInfo(r13)
|
||||
goto L8
|
||||
L7: (handler for L3, L4, L5)
|
||||
CPy_RestoreExcInfo(r13)
|
||||
r22 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L8:
|
||||
L9:
|
||||
L10:
|
||||
r23 = <error> :: tuple[object, object, object]
|
||||
r24 = r23
|
||||
goto L12
|
||||
L11: (handler for L1, L6, L7, L8)
|
||||
r25 = CPy_CatchError()
|
||||
r24 = r25
|
||||
L12:
|
||||
if r7 goto L13 else goto L14 :: bool
|
||||
L13:
|
||||
r26 = load_address _Py_NoneStruct
|
||||
r27 = PyObject_CallFunctionObjArgs(r3, r0, r26, r26, r26, 0)
|
||||
L14:
|
||||
if is_error(r24) goto L16 else goto L15
|
||||
L15:
|
||||
CPy_Reraise()
|
||||
unreachable
|
||||
L16:
|
||||
goto L20
|
||||
L17: (handler for L12, L13, L14, L15)
|
||||
if is_error(r24) goto L19 else goto L18
|
||||
L18:
|
||||
CPy_RestoreExcInfo(r24)
|
||||
L19:
|
||||
r28 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L20:
|
||||
return 1
|
||||
|
||||
[case testWithNativeSimple]
|
||||
class DummyContext:
|
||||
def __enter__(self) -> None:
|
||||
pass
|
||||
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
||||
pass
|
||||
|
||||
def foo(x: DummyContext) -> None:
|
||||
with x:
|
||||
print('hello')
|
||||
[out]
|
||||
def DummyContext.__enter__(self):
|
||||
self :: __main__.DummyContext
|
||||
L0:
|
||||
return 1
|
||||
def DummyContext.__exit__(self, exc_type, exc_val, exc_tb):
|
||||
self :: __main__.DummyContext
|
||||
exc_type, exc_val, exc_tb :: object
|
||||
L0:
|
||||
return 1
|
||||
def foo(x):
|
||||
x :: __main__.DummyContext
|
||||
r0 :: None
|
||||
r1 :: bool
|
||||
r2 :: str
|
||||
r3 :: object
|
||||
r4 :: str
|
||||
r5, r6 :: object
|
||||
r7, r8 :: tuple[object, object, object]
|
||||
r9, r10, r11 :: object
|
||||
r12 :: None
|
||||
r13 :: object
|
||||
r14 :: i32
|
||||
r15 :: bit
|
||||
r16 :: bool
|
||||
r17 :: bit
|
||||
r18, r19, r20 :: tuple[object, object, object]
|
||||
r21 :: object
|
||||
r22 :: None
|
||||
r23 :: bit
|
||||
L0:
|
||||
r0 = x.__enter__()
|
||||
r1 = 1
|
||||
L1:
|
||||
L2:
|
||||
r2 = 'hello'
|
||||
r3 = builtins :: module
|
||||
r4 = 'print'
|
||||
r5 = CPyObject_GetAttr(r3, r4)
|
||||
r6 = PyObject_CallFunctionObjArgs(r5, r2, 0)
|
||||
goto L8
|
||||
L3: (handler for L2)
|
||||
r7 = CPy_CatchError()
|
||||
r1 = 0
|
||||
r8 = CPy_GetExcInfo()
|
||||
r9 = r8[0]
|
||||
r10 = r8[1]
|
||||
r11 = r8[2]
|
||||
r12 = x.__exit__(r9, r10, r11)
|
||||
r13 = box(None, r12)
|
||||
r14 = PyObject_IsTrue(r13)
|
||||
r15 = r14 >= 0 :: signed
|
||||
r16 = truncate r14: i32 to builtins.bool
|
||||
if r16 goto L5 else goto L4 :: bool
|
||||
L4:
|
||||
CPy_Reraise()
|
||||
unreachable
|
||||
L5:
|
||||
L6:
|
||||
CPy_RestoreExcInfo(r7)
|
||||
goto L8
|
||||
L7: (handler for L3, L4, L5)
|
||||
CPy_RestoreExcInfo(r7)
|
||||
r17 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L8:
|
||||
L9:
|
||||
L10:
|
||||
r18 = <error> :: tuple[object, object, object]
|
||||
r19 = r18
|
||||
goto L12
|
||||
L11: (handler for L1, L6, L7, L8)
|
||||
r20 = CPy_CatchError()
|
||||
r19 = r20
|
||||
L12:
|
||||
if r1 goto L13 else goto L14 :: bool
|
||||
L13:
|
||||
r21 = load_address _Py_NoneStruct
|
||||
r22 = x.__exit__(r21, r21, r21)
|
||||
L14:
|
||||
if is_error(r19) goto L16 else goto L15
|
||||
L15:
|
||||
CPy_Reraise()
|
||||
unreachable
|
||||
L16:
|
||||
goto L20
|
||||
L17: (handler for L12, L13, L14, L15)
|
||||
if is_error(r19) goto L19 else goto L18
|
||||
L18:
|
||||
CPy_RestoreExcInfo(r19)
|
||||
L19:
|
||||
r23 = CPy_KeepPropagating()
|
||||
unreachable
|
||||
L20:
|
||||
return 1
|
||||
@@ -0,0 +1,462 @@
|
||||
[case testTupleGet]
|
||||
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]
|
||||
return r1
|
||||
|
||||
[case testTupleNew]
|
||||
from typing import Tuple
|
||||
|
||||
def f() -> int:
|
||||
t = (True, 1)
|
||||
return t[1]
|
||||
[out]
|
||||
def f():
|
||||
r0, t :: tuple[bool, int]
|
||||
r1 :: int
|
||||
L0:
|
||||
r0 = (1, 2)
|
||||
t = r0
|
||||
r1 = t[1]
|
||||
return r1
|
||||
|
||||
[case testTupleLen]
|
||||
from typing import Tuple
|
||||
def f(x: Tuple[bool, bool, int]) -> int:
|
||||
return len(x)
|
||||
[out]
|
||||
def f(x):
|
||||
x :: tuple[bool, bool, int]
|
||||
L0:
|
||||
return 6
|
||||
|
||||
[case testSequenceTuple]
|
||||
from typing import List
|
||||
def f(x: List[bool]) -> bool:
|
||||
return tuple(x)[1]
|
||||
[out]
|
||||
def f(x):
|
||||
x :: list
|
||||
r0 :: tuple
|
||||
r1 :: object
|
||||
r2 :: bool
|
||||
L0:
|
||||
r0 = PyList_AsTuple(x)
|
||||
r1 = CPySequenceTuple_GetItem(r0, 2)
|
||||
r2 = unbox(bool, r1)
|
||||
return r2
|
||||
|
||||
[case testSequenceTupleLen]
|
||||
from typing import Tuple
|
||||
def f(x: Tuple[int, ...]) -> int:
|
||||
return len(x)
|
||||
[out]
|
||||
def f(x):
|
||||
x :: tuple
|
||||
r0 :: ptr
|
||||
r1 :: native_int
|
||||
r2 :: short_int
|
||||
L0:
|
||||
r0 = get_element_ptr x ob_size :: PyVarObject
|
||||
r1 = load_mem r0 :: native_int*
|
||||
keep_alive x
|
||||
r2 = r1 << 1
|
||||
return r2
|
||||
|
||||
[case testSequenceTupleForced]
|
||||
from typing import Tuple
|
||||
def f() -> int:
|
||||
t = (1, 2) # type: Tuple[int, ...]
|
||||
return t[1]
|
||||
[out]
|
||||
def f():
|
||||
r0 :: tuple[int, int]
|
||||
r1 :: object
|
||||
t :: tuple
|
||||
r2 :: object
|
||||
r3 :: int
|
||||
L0:
|
||||
r0 = (2, 4)
|
||||
r1 = box(tuple[int, int], r0)
|
||||
t = r1
|
||||
r2 = CPySequenceTuple_GetItem(t, 2)
|
||||
r3 = unbox(int, r2)
|
||||
return r3
|
||||
|
||||
[case testTupleDisplay]
|
||||
from typing import Sequence, Tuple
|
||||
def f(x: Sequence[int], y: Sequence[int]) -> Tuple[int, ...]:
|
||||
return (1, 2, *x, *y, 3)
|
||||
[out]
|
||||
def f(x, y):
|
||||
x, y :: object
|
||||
r0 :: list
|
||||
r1, r2 :: object
|
||||
r3, r4, r5 :: ptr
|
||||
r6, r7, r8 :: object
|
||||
r9 :: i32
|
||||
r10 :: bit
|
||||
r11 :: tuple
|
||||
L0:
|
||||
r0 = PyList_New(2)
|
||||
r1 = object 1
|
||||
r2 = object 2
|
||||
r3 = get_element_ptr r0 ob_item :: PyListObject
|
||||
r4 = load_mem r3 :: ptr*
|
||||
set_mem r4, r1 :: builtins.object*
|
||||
r5 = r4 + WORD_SIZE*1
|
||||
set_mem r5, r2 :: builtins.object*
|
||||
keep_alive r0
|
||||
r6 = CPyList_Extend(r0, x)
|
||||
r7 = CPyList_Extend(r0, y)
|
||||
r8 = object 3
|
||||
r9 = PyList_Append(r0, r8)
|
||||
r10 = r9 >= 0 :: signed
|
||||
r11 = PyList_AsTuple(r0)
|
||||
return r11
|
||||
|
||||
[case testTupleFor]
|
||||
from typing import Tuple, List
|
||||
def f(xs: Tuple[str, ...]) -> None:
|
||||
for x in xs:
|
||||
pass
|
||||
[out]
|
||||
def f(xs):
|
||||
xs :: tuple
|
||||
r0 :: short_int
|
||||
r1 :: ptr
|
||||
r2 :: native_int
|
||||
r3 :: short_int
|
||||
r4 :: bit
|
||||
r5 :: object
|
||||
r6, x :: str
|
||||
r7 :: short_int
|
||||
L0:
|
||||
r0 = 0
|
||||
L1:
|
||||
r1 = get_element_ptr xs ob_size :: PyVarObject
|
||||
r2 = load_mem r1 :: native_int*
|
||||
keep_alive xs
|
||||
r3 = r2 << 1
|
||||
r4 = r0 < r3 :: signed
|
||||
if r4 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r5 = CPySequenceTuple_GetItem(xs, r0)
|
||||
r6 = cast(str, r5)
|
||||
x = r6
|
||||
L3:
|
||||
r7 = r0 + 2
|
||||
r0 = r7
|
||||
goto L1
|
||||
L4:
|
||||
return 1
|
||||
|
||||
[case testNamedTupleAttribute]
|
||||
from typing import NamedTuple
|
||||
|
||||
NT = NamedTuple('NT', [('x', int), ('y', int)])
|
||||
|
||||
def f(nt: NT, b: bool) -> int:
|
||||
if b:
|
||||
return nt.x
|
||||
return nt.y
|
||||
[out]
|
||||
def f(nt, b):
|
||||
nt :: tuple
|
||||
b :: bool
|
||||
r0 :: object
|
||||
r1 :: int
|
||||
r2 :: object
|
||||
r3 :: int
|
||||
L0:
|
||||
if b goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r0 = CPySequenceTuple_GetItem(nt, 0)
|
||||
r1 = unbox(int, r0)
|
||||
return r1
|
||||
L2:
|
||||
r2 = CPySequenceTuple_GetItem(nt, 2)
|
||||
r3 = unbox(int, r2)
|
||||
return r3
|
||||
|
||||
|
||||
[case testTupleOperatorIn]
|
||||
def f(i: int) -> bool:
|
||||
return i in [1, 2, 3]
|
||||
[out]
|
||||
def f(i):
|
||||
i :: int
|
||||
r0 :: native_int
|
||||
r1, r2 :: bit
|
||||
r3 :: bool
|
||||
r4 :: bit
|
||||
r5 :: bool
|
||||
r6 :: native_int
|
||||
r7, r8 :: bit
|
||||
r9 :: bool
|
||||
r10 :: bit
|
||||
r11 :: bool
|
||||
r12 :: native_int
|
||||
r13, r14 :: bit
|
||||
r15 :: bool
|
||||
r16 :: bit
|
||||
L0:
|
||||
r0 = i & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r2 = i == 2
|
||||
r3 = r2
|
||||
goto L3
|
||||
L2:
|
||||
r4 = CPyTagged_IsEq_(i, 2)
|
||||
r3 = r4
|
||||
L3:
|
||||
if r3 goto L4 else goto L5 :: bool
|
||||
L4:
|
||||
r5 = r3
|
||||
goto L9
|
||||
L5:
|
||||
r6 = i & 1
|
||||
r7 = r6 == 0
|
||||
if r7 goto L6 else goto L7 :: bool
|
||||
L6:
|
||||
r8 = i == 4
|
||||
r9 = r8
|
||||
goto L8
|
||||
L7:
|
||||
r10 = CPyTagged_IsEq_(i, 4)
|
||||
r9 = r10
|
||||
L8:
|
||||
r5 = r9
|
||||
L9:
|
||||
if r5 goto L10 else goto L11 :: bool
|
||||
L10:
|
||||
r11 = r5
|
||||
goto L15
|
||||
L11:
|
||||
r12 = i & 1
|
||||
r13 = r12 == 0
|
||||
if r13 goto L12 else goto L13 :: bool
|
||||
L12:
|
||||
r14 = i == 6
|
||||
r15 = r14
|
||||
goto L14
|
||||
L13:
|
||||
r16 = CPyTagged_IsEq_(i, 6)
|
||||
r15 = r16
|
||||
L14:
|
||||
r11 = r15
|
||||
L15:
|
||||
return r11
|
||||
|
||||
|
||||
[case testTupleBuiltFromList]
|
||||
def f(val: int) -> bool:
|
||||
return val % 2 == 0
|
||||
|
||||
def test() -> None:
|
||||
source = [1, 2, 3]
|
||||
a = tuple(f(x) for x in source)
|
||||
[out]
|
||||
def f(val):
|
||||
val, r0 :: int
|
||||
r1 :: native_int
|
||||
r2, r3 :: bit
|
||||
r4 :: bool
|
||||
r5 :: bit
|
||||
L0:
|
||||
r0 = CPyTagged_Remainder(val, 4)
|
||||
r1 = r0 & 1
|
||||
r2 = r1 == 0
|
||||
if r2 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r3 = r0 == 0
|
||||
r4 = r3
|
||||
goto L3
|
||||
L2:
|
||||
r5 = CPyTagged_IsEq_(r0, 0)
|
||||
r4 = r5
|
||||
L3:
|
||||
return r4
|
||||
def test():
|
||||
r0 :: list
|
||||
r1, r2, r3 :: object
|
||||
r4, r5, r6, r7 :: ptr
|
||||
source :: list
|
||||
r8 :: ptr
|
||||
r9 :: native_int
|
||||
r10 :: tuple
|
||||
r11 :: short_int
|
||||
r12 :: ptr
|
||||
r13 :: native_int
|
||||
r14 :: short_int
|
||||
r15 :: bit
|
||||
r16 :: object
|
||||
r17, x :: int
|
||||
r18 :: bool
|
||||
r19 :: object
|
||||
r20 :: bit
|
||||
r21 :: short_int
|
||||
a :: tuple
|
||||
L0:
|
||||
r0 = PyList_New(3)
|
||||
r1 = object 1
|
||||
r2 = object 2
|
||||
r3 = object 3
|
||||
r4 = get_element_ptr r0 ob_item :: PyListObject
|
||||
r5 = load_mem r4 :: ptr*
|
||||
set_mem r5, r1 :: builtins.object*
|
||||
r6 = r5 + WORD_SIZE*1
|
||||
set_mem r6, r2 :: builtins.object*
|
||||
r7 = r5 + WORD_SIZE*2
|
||||
set_mem r7, r3 :: builtins.object*
|
||||
keep_alive r0
|
||||
source = r0
|
||||
r8 = get_element_ptr source ob_size :: PyVarObject
|
||||
r9 = load_mem r8 :: native_int*
|
||||
keep_alive source
|
||||
r10 = PyTuple_New(r9)
|
||||
r11 = 0
|
||||
L1:
|
||||
r12 = get_element_ptr source ob_size :: PyVarObject
|
||||
r13 = load_mem r12 :: native_int*
|
||||
keep_alive source
|
||||
r14 = r13 << 1
|
||||
r15 = r11 < r14 :: signed
|
||||
if r15 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r16 = CPyList_GetItemUnsafe(source, r11)
|
||||
r17 = unbox(int, r16)
|
||||
x = r17
|
||||
r18 = f(x)
|
||||
r19 = box(bool, r18)
|
||||
r20 = CPySequenceTuple_SetItemUnsafe(r10, r11, r19)
|
||||
L3:
|
||||
r21 = r11 + 2
|
||||
r11 = r21
|
||||
goto L1
|
||||
L4:
|
||||
a = r10
|
||||
return 1
|
||||
|
||||
[case testTupleBuiltFromStr]
|
||||
def f2(val: str) -> str:
|
||||
return val + "f2"
|
||||
|
||||
def test() -> None:
|
||||
source = "abc"
|
||||
a = tuple(f2(x) for x in source)
|
||||
[out]
|
||||
def f2(val):
|
||||
val, r0, r1 :: str
|
||||
L0:
|
||||
r0 = 'f2'
|
||||
r1 = PyUnicode_Concat(val, r0)
|
||||
return r1
|
||||
def test():
|
||||
r0, source :: str
|
||||
r1 :: native_int
|
||||
r2 :: bit
|
||||
r3 :: tuple
|
||||
r4 :: short_int
|
||||
r5 :: native_int
|
||||
r6 :: bit
|
||||
r7 :: short_int
|
||||
r8 :: bit
|
||||
r9, x, r10 :: str
|
||||
r11 :: bit
|
||||
r12 :: short_int
|
||||
a :: tuple
|
||||
L0:
|
||||
r0 = 'abc'
|
||||
source = r0
|
||||
r1 = CPyStr_Size_size_t(source)
|
||||
r2 = r1 >= 0 :: signed
|
||||
r3 = PyTuple_New(r1)
|
||||
r4 = 0
|
||||
L1:
|
||||
r5 = CPyStr_Size_size_t(source)
|
||||
r6 = r5 >= 0 :: signed
|
||||
r7 = r5 << 1
|
||||
r8 = r4 < r7 :: signed
|
||||
if r8 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r9 = CPyStr_GetItem(source, r4)
|
||||
x = r9
|
||||
r10 = f2(x)
|
||||
r11 = CPySequenceTuple_SetItemUnsafe(r3, r4, r10)
|
||||
L3:
|
||||
r12 = r4 + 2
|
||||
r4 = r12
|
||||
goto L1
|
||||
L4:
|
||||
a = r3
|
||||
return 1
|
||||
|
||||
[case testTupleBuiltFromVariableLengthTuple]
|
||||
from typing import Tuple
|
||||
|
||||
def f(val: bool) -> bool:
|
||||
return not val
|
||||
|
||||
def test(source: Tuple[bool, ...]) -> None:
|
||||
a = tuple(f(x) for x in source)
|
||||
[out]
|
||||
def f(val):
|
||||
val, r0 :: bool
|
||||
L0:
|
||||
r0 = val ^ 1
|
||||
return r0
|
||||
def test(source):
|
||||
source :: tuple
|
||||
r0 :: ptr
|
||||
r1 :: native_int
|
||||
r2 :: tuple
|
||||
r3 :: short_int
|
||||
r4 :: ptr
|
||||
r5 :: native_int
|
||||
r6 :: short_int
|
||||
r7 :: bit
|
||||
r8 :: object
|
||||
r9, x, r10 :: bool
|
||||
r11 :: object
|
||||
r12 :: bit
|
||||
r13 :: short_int
|
||||
a :: tuple
|
||||
L0:
|
||||
r0 = get_element_ptr source ob_size :: PyVarObject
|
||||
r1 = load_mem r0 :: native_int*
|
||||
keep_alive source
|
||||
r2 = PyTuple_New(r1)
|
||||
r3 = 0
|
||||
L1:
|
||||
r4 = get_element_ptr source ob_size :: PyVarObject
|
||||
r5 = load_mem r4 :: native_int*
|
||||
keep_alive source
|
||||
r6 = r5 << 1
|
||||
r7 = r3 < r6 :: signed
|
||||
if r7 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r8 = CPySequenceTuple_GetItem(source, r3)
|
||||
r9 = unbox(bool, r8)
|
||||
x = r9
|
||||
r10 = f(x)
|
||||
r11 = box(bool, r10)
|
||||
r12 = CPySequenceTuple_SetItemUnsafe(r2, r3, r11)
|
||||
L3:
|
||||
r13 = r3 + 2
|
||||
r3 = r13
|
||||
goto L1
|
||||
L4:
|
||||
a = r2
|
||||
return 1
|
||||
@@ -0,0 +1,543 @@
|
||||
# Test cases for u8 native ints. Focus on things that are different from i64; no need to
|
||||
# duplicate all i64 test cases here.
|
||||
|
||||
[case testU8BinaryOp]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def add_op(x: u8, y: u8) -> u8:
|
||||
x = y + x
|
||||
y = x + 5
|
||||
y += x
|
||||
y += 7
|
||||
x = 5 + y
|
||||
return x
|
||||
def compare(x: u8, y: u8) -> None:
|
||||
a = x == y
|
||||
b = x == 5
|
||||
c = x < y
|
||||
d = x < 5
|
||||
e = 5 == x
|
||||
f = 5 < x
|
||||
[out]
|
||||
def add_op(x, y):
|
||||
x, y, r0, r1, r2, r3, r4 :: u8
|
||||
L0:
|
||||
r0 = y + x
|
||||
x = r0
|
||||
r1 = x + 5
|
||||
y = r1
|
||||
r2 = y + x
|
||||
y = r2
|
||||
r3 = y + 7
|
||||
y = r3
|
||||
r4 = 5 + y
|
||||
x = r4
|
||||
return x
|
||||
def compare(x, y):
|
||||
x, y :: u8
|
||||
r0 :: bit
|
||||
a :: bool
|
||||
r1 :: bit
|
||||
b :: bool
|
||||
r2 :: bit
|
||||
c :: bool
|
||||
r3 :: bit
|
||||
d :: bool
|
||||
r4 :: bit
|
||||
e :: bool
|
||||
r5 :: bit
|
||||
f :: bool
|
||||
L0:
|
||||
r0 = x == y
|
||||
a = r0
|
||||
r1 = x == 5
|
||||
b = r1
|
||||
r2 = x < y :: unsigned
|
||||
c = r2
|
||||
r3 = x < 5 :: unsigned
|
||||
d = r3
|
||||
r4 = 5 == x
|
||||
e = r4
|
||||
r5 = 5 < x :: unsigned
|
||||
f = r5
|
||||
return 1
|
||||
|
||||
[case testU8UnaryOp]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def unary(x: u8) -> u8:
|
||||
y = -x
|
||||
x = ~y
|
||||
y = +x
|
||||
return y
|
||||
[out]
|
||||
def unary(x):
|
||||
x, r0, y, r1 :: u8
|
||||
L0:
|
||||
r0 = 0 - x
|
||||
y = r0
|
||||
r1 = y ^ 255
|
||||
x = r1
|
||||
y = x
|
||||
return y
|
||||
|
||||
[case testU8DivisionByConstant]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def div_by_constant(x: u8) -> u8:
|
||||
x = x // 5
|
||||
x //= 17
|
||||
return x
|
||||
[out]
|
||||
def div_by_constant(x):
|
||||
x, r0, r1 :: u8
|
||||
L0:
|
||||
r0 = x / 5
|
||||
x = r0
|
||||
r1 = x / 17
|
||||
x = r1
|
||||
return x
|
||||
|
||||
[case testU8ModByConstant]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def mod_by_constant(x: u8) -> u8:
|
||||
x = x % 5
|
||||
x %= 17
|
||||
return x
|
||||
[out]
|
||||
def mod_by_constant(x):
|
||||
x, r0, r1 :: u8
|
||||
L0:
|
||||
r0 = x % 5
|
||||
x = r0
|
||||
r1 = x % 17
|
||||
x = r1
|
||||
return x
|
||||
|
||||
[case testU8DivModByVariable]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def divmod(x: u8, y: u8) -> u8:
|
||||
a = x // y
|
||||
return a % y
|
||||
[out]
|
||||
def divmod(x, y):
|
||||
x, y :: u8
|
||||
r0 :: bit
|
||||
r1 :: bool
|
||||
r2, a :: u8
|
||||
r3 :: bit
|
||||
r4 :: bool
|
||||
r5 :: u8
|
||||
L0:
|
||||
r0 = y == 0
|
||||
if r0 goto L1 else goto L2 :: bool
|
||||
L1:
|
||||
r1 = raise ZeroDivisionError('integer division or modulo by zero')
|
||||
unreachable
|
||||
L2:
|
||||
r2 = x / y
|
||||
a = r2
|
||||
r3 = y == 0
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = raise ZeroDivisionError('integer division or modulo by zero')
|
||||
unreachable
|
||||
L4:
|
||||
r5 = a % y
|
||||
return r5
|
||||
|
||||
[case testU8BinaryOperationWithOutOfRangeOperand]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def out_of_range(x: u8) -> None:
|
||||
x + (-1)
|
||||
(-2) + x
|
||||
x * 256
|
||||
-1 < x
|
||||
x > -5
|
||||
x == 1000
|
||||
x + 255 # OK
|
||||
255 + x # OK
|
||||
[out]
|
||||
main:4: error: Value -1 is out of range for "u8"
|
||||
main:5: error: Value -2 is out of range for "u8"
|
||||
main:6: error: Value 256 is out of range for "u8"
|
||||
main:7: error: Value -1 is out of range for "u8"
|
||||
main:8: error: Value -5 is out of range for "u8"
|
||||
main:9: error: Value 1000 is out of range for "u8"
|
||||
|
||||
[case testU8DetectMoreOutOfRangeLiterals]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def out_of_range() -> None:
|
||||
a: u8 = 256
|
||||
b: u8 = -1
|
||||
f(256)
|
||||
# The following are ok
|
||||
c: u8 = 0
|
||||
d: u8 = 255
|
||||
f(0)
|
||||
f(255)
|
||||
|
||||
def f(x: u8) -> None: pass
|
||||
[out]
|
||||
main:4: error: Value 256 is out of range for "u8"
|
||||
main:5: error: Value -1 is out of range for "u8"
|
||||
main:6: error: Value 256 is out of range for "u8"
|
||||
|
||||
[case testU8BoxAndUnbox]
|
||||
from typing import Any
|
||||
from mypy_extensions import u8
|
||||
|
||||
def f(x: Any) -> Any:
|
||||
y: u8 = x
|
||||
return y
|
||||
[out]
|
||||
def f(x):
|
||||
x :: object
|
||||
r0, y :: u8
|
||||
r1 :: object
|
||||
L0:
|
||||
r0 = unbox(u8, x)
|
||||
y = r0
|
||||
r1 = box(u8, y)
|
||||
return r1
|
||||
|
||||
[case testU8MixedCompare1]
|
||||
from mypy_extensions import u8
|
||||
def f(x: int, y: u8) -> bool:
|
||||
return x == y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: int
|
||||
y :: u8
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6 :: u8
|
||||
r7 :: bit
|
||||
L0:
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = x < 512 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = x >= 0 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = x >> 1
|
||||
r5 = truncate r4: native_int to u8
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyUInt8_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
r7 = r6 == y
|
||||
return r7
|
||||
|
||||
[case testU8MixedCompare2]
|
||||
from mypy_extensions import u8
|
||||
def f(x: u8, y: int) -> bool:
|
||||
return x == y
|
||||
[out]
|
||||
def f(x, y):
|
||||
x :: u8
|
||||
y :: int
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6 :: u8
|
||||
r7 :: bit
|
||||
L0:
|
||||
r0 = y & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = y < 512 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = y >= 0 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = y >> 1
|
||||
r5 = truncate r4: native_int to u8
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyUInt8_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
r7 = x == r6
|
||||
return r7
|
||||
|
||||
[case testU8ConvertToInt]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def u8_to_int(a: u8) -> int:
|
||||
return a
|
||||
[out]
|
||||
def u8_to_int(a):
|
||||
a :: u8
|
||||
r0 :: native_int
|
||||
r1 :: int
|
||||
L0:
|
||||
r0 = extend a: u8 to native_int
|
||||
r1 = r0 << 1
|
||||
return r1
|
||||
|
||||
[case testU8OperatorAssignmentMixed]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def f(a: u8) -> None:
|
||||
x = 0
|
||||
x += a
|
||||
[out]
|
||||
def f(a):
|
||||
a :: u8
|
||||
x :: int
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6, r7 :: u8
|
||||
r8 :: native_int
|
||||
r9 :: int
|
||||
L0:
|
||||
x = 0
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = x < 512 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = x >= 0 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = x >> 1
|
||||
r5 = truncate r4: native_int to u8
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyUInt8_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
r7 = r6 + a
|
||||
r8 = extend r7: u8 to native_int
|
||||
r9 = r8 << 1
|
||||
x = r9
|
||||
return 1
|
||||
|
||||
[case testU8InitializeFromLiteral]
|
||||
from mypy_extensions import u8, i64
|
||||
|
||||
def f() -> None:
|
||||
x: u8 = 0
|
||||
y: u8 = 255
|
||||
z: u8 = 5 + 7
|
||||
[out]
|
||||
def f():
|
||||
x, y, z :: u8
|
||||
L0:
|
||||
x = 0
|
||||
y = 255
|
||||
z = 12
|
||||
return 1
|
||||
|
||||
[case testU8ExplicitConversionFromNativeInt]
|
||||
from mypy_extensions import i64, i32, i16, u8
|
||||
|
||||
def from_u8(x: u8) -> u8:
|
||||
return u8(x)
|
||||
|
||||
def from_i16(x: i16) -> u8:
|
||||
return u8(x)
|
||||
|
||||
def from_i32(x: i32) -> u8:
|
||||
return u8(x)
|
||||
|
||||
def from_i64(x: i64) -> u8:
|
||||
return u8(x)
|
||||
[out]
|
||||
def from_u8(x):
|
||||
x :: u8
|
||||
L0:
|
||||
return x
|
||||
def from_i16(x):
|
||||
x :: i16
|
||||
r0 :: u8
|
||||
L0:
|
||||
r0 = truncate x: i16 to u8
|
||||
return r0
|
||||
def from_i32(x):
|
||||
x :: i32
|
||||
r0 :: u8
|
||||
L0:
|
||||
r0 = truncate x: i32 to u8
|
||||
return r0
|
||||
def from_i64(x):
|
||||
x :: i64
|
||||
r0 :: u8
|
||||
L0:
|
||||
r0 = truncate x: i64 to u8
|
||||
return r0
|
||||
|
||||
[case testU8ExplicitConversionToNativeInt]
|
||||
from mypy_extensions import i64, i32, i16, u8
|
||||
|
||||
def to_i16(x: u8) -> i16:
|
||||
return i16(x)
|
||||
|
||||
def to_i32(x: u8) -> i32:
|
||||
return i32(x)
|
||||
|
||||
def to_i64(x: u8) -> i64:
|
||||
return i64(x)
|
||||
[out]
|
||||
def to_i16(x):
|
||||
x :: u8
|
||||
r0 :: i16
|
||||
L0:
|
||||
r0 = extend x: u8 to i16
|
||||
return r0
|
||||
def to_i32(x):
|
||||
x :: u8
|
||||
r0 :: i32
|
||||
L0:
|
||||
r0 = extend x: u8 to i32
|
||||
return r0
|
||||
def to_i64(x):
|
||||
x :: u8
|
||||
r0 :: i64
|
||||
L0:
|
||||
r0 = extend x: u8 to i64
|
||||
return r0
|
||||
|
||||
[case testU8ExplicitConversionFromInt]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def f(x: int) -> u8:
|
||||
return u8(x)
|
||||
[out]
|
||||
def f(x):
|
||||
x :: int
|
||||
r0 :: native_int
|
||||
r1, r2, r3 :: bit
|
||||
r4 :: native_int
|
||||
r5, r6 :: u8
|
||||
L0:
|
||||
r0 = x & 1
|
||||
r1 = r0 == 0
|
||||
if r1 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r2 = x < 512 :: signed
|
||||
if r2 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r3 = x >= 0 :: signed
|
||||
if r3 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r4 = x >> 1
|
||||
r5 = truncate r4: native_int to u8
|
||||
r6 = r5
|
||||
goto L5
|
||||
L4:
|
||||
CPyUInt8_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
return r6
|
||||
|
||||
[case testU8ExplicitConversionFromLiteral]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def f() -> None:
|
||||
x = u8(0)
|
||||
y = u8(11)
|
||||
z = u8(-3) # Truncate
|
||||
zz = u8(258) # Truncate
|
||||
a = u8(255)
|
||||
[out]
|
||||
def f():
|
||||
x, y, z, zz, a :: u8
|
||||
L0:
|
||||
x = 0
|
||||
y = 11
|
||||
z = 253
|
||||
zz = 2
|
||||
a = 255
|
||||
return 1
|
||||
|
||||
[case testU8ExplicitConversionFromVariousTypes]
|
||||
from mypy_extensions import u8
|
||||
|
||||
def bool_to_u8(b: bool) -> u8:
|
||||
return u8(b)
|
||||
|
||||
def str_to_u8(s: str) -> u8:
|
||||
return u8(s)
|
||||
|
||||
class C:
|
||||
def __int__(self) -> u8:
|
||||
return 5
|
||||
|
||||
def instance_to_u8(c: C) -> u8:
|
||||
return u8(c)
|
||||
|
||||
def float_to_u8(x: float) -> u8:
|
||||
return u8(x)
|
||||
[out]
|
||||
def bool_to_u8(b):
|
||||
b :: bool
|
||||
r0 :: u8
|
||||
L0:
|
||||
r0 = extend b: builtins.bool to u8
|
||||
return r0
|
||||
def str_to_u8(s):
|
||||
s :: str
|
||||
r0 :: object
|
||||
r1 :: u8
|
||||
L0:
|
||||
r0 = CPyLong_FromStr(s)
|
||||
r1 = unbox(u8, r0)
|
||||
return r1
|
||||
def C.__int__(self):
|
||||
self :: __main__.C
|
||||
L0:
|
||||
return 5
|
||||
def instance_to_u8(c):
|
||||
c :: __main__.C
|
||||
r0 :: u8
|
||||
L0:
|
||||
r0 = c.__int__()
|
||||
return r0
|
||||
def float_to_u8(x):
|
||||
x :: float
|
||||
r0 :: int
|
||||
r1 :: native_int
|
||||
r2, r3, r4 :: bit
|
||||
r5 :: native_int
|
||||
r6, r7 :: u8
|
||||
L0:
|
||||
r0 = CPyTagged_FromFloat(x)
|
||||
r1 = r0 & 1
|
||||
r2 = r1 == 0
|
||||
if r2 goto L1 else goto L4 :: bool
|
||||
L1:
|
||||
r3 = r0 < 512 :: signed
|
||||
if r3 goto L2 else goto L4 :: bool
|
||||
L2:
|
||||
r4 = r0 >= 0 :: signed
|
||||
if r4 goto L3 else goto L4 :: bool
|
||||
L3:
|
||||
r5 = r0 >> 1
|
||||
r6 = truncate r5: native_int to u8
|
||||
r7 = r6
|
||||
goto L5
|
||||
L4:
|
||||
CPyUInt8_Overflow()
|
||||
unreachable
|
||||
L5:
|
||||
return r7
|
||||
@@ -0,0 +1,106 @@
|
||||
# Test cases for unreachable expressions
|
||||
|
||||
[case testUnreachableMemberExpr]
|
||||
import sys
|
||||
|
||||
def f() -> None:
|
||||
y = sys.platform == "x" and sys.version_info > (3, 5)
|
||||
[out]
|
||||
def f():
|
||||
r0 :: object
|
||||
r1 :: str
|
||||
r2 :: object
|
||||
r3, r4 :: str
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
r7 :: object
|
||||
r8, r9, r10 :: bit
|
||||
r11, r12 :: bool
|
||||
r13 :: object
|
||||
r14 :: str
|
||||
r15 :: object
|
||||
r16 :: tuple[int, int]
|
||||
r17, r18 :: object
|
||||
r19, y :: bool
|
||||
L0:
|
||||
r0 = sys :: module
|
||||
r1 = 'platform'
|
||||
r2 = CPyObject_GetAttr(r0, r1)
|
||||
r3 = cast(str, r2)
|
||||
r4 = 'x'
|
||||
r5 = PyUnicode_Compare(r3, r4)
|
||||
r6 = r5 == -1
|
||||
if r6 goto L1 else goto L3 :: bool
|
||||
L1:
|
||||
r7 = PyErr_Occurred()
|
||||
r8 = r7 != 0
|
||||
if r8 goto L2 else goto L3 :: bool
|
||||
L2:
|
||||
r9 = CPy_KeepPropagating()
|
||||
L3:
|
||||
r10 = r5 == 0
|
||||
if r10 goto L5 else goto L4 :: bool
|
||||
L4:
|
||||
r11 = r10
|
||||
goto L6
|
||||
L5:
|
||||
r12 = raise RuntimeError('mypyc internal error: should be unreachable')
|
||||
r13 = box(None, 1)
|
||||
r14 = 'version_info'
|
||||
r15 = CPyObject_GetAttr(r13, r14)
|
||||
r16 = (6, 10)
|
||||
r17 = box(tuple[int, int], r16)
|
||||
r18 = PyObject_RichCompare(r15, r17, 4)
|
||||
r19 = unbox(bool, r18)
|
||||
r11 = r19
|
||||
L6:
|
||||
y = r11
|
||||
return 1
|
||||
|
||||
[case testUnreachableNameExpr]
|
||||
import sys
|
||||
|
||||
def f() -> None:
|
||||
y = sys.platform == 'x' and foobar
|
||||
[out]
|
||||
def f():
|
||||
r0 :: object
|
||||
r1 :: str
|
||||
r2 :: object
|
||||
r3, r4 :: str
|
||||
r5 :: i32
|
||||
r6 :: bit
|
||||
r7 :: object
|
||||
r8, r9, r10 :: bit
|
||||
r11, r12 :: bool
|
||||
r13 :: object
|
||||
r14, y :: bool
|
||||
L0:
|
||||
r0 = sys :: module
|
||||
r1 = 'platform'
|
||||
r2 = CPyObject_GetAttr(r0, r1)
|
||||
r3 = cast(str, r2)
|
||||
r4 = 'x'
|
||||
r5 = PyUnicode_Compare(r3, r4)
|
||||
r6 = r5 == -1
|
||||
if r6 goto L1 else goto L3 :: bool
|
||||
L1:
|
||||
r7 = PyErr_Occurred()
|
||||
r8 = r7 != 0
|
||||
if r8 goto L2 else goto L3 :: bool
|
||||
L2:
|
||||
r9 = CPy_KeepPropagating()
|
||||
L3:
|
||||
r10 = r5 == 0
|
||||
if r10 goto L5 else goto L4 :: bool
|
||||
L4:
|
||||
r11 = r10
|
||||
goto L6
|
||||
L5:
|
||||
r12 = raise RuntimeError('mypyc internal error: should be unreachable')
|
||||
r13 = box(None, 1)
|
||||
r14 = unbox(bool, r13)
|
||||
r11 = r14
|
||||
L6:
|
||||
y = r11
|
||||
return 1
|
||||
@@ -0,0 +1,153 @@
|
||||
-- Test cases for calls using the vectorcall API (Python 3.8+)
|
||||
--
|
||||
-- Vectorcalls are faster than the legacy API, especially with keyword arguments,
|
||||
-- since there is no need to allocate a temporary dictionary for keyword args.
|
||||
|
||||
[case testeVectorcallBasic_python3_8]
|
||||
from typing import Any
|
||||
|
||||
def f(c: Any) -> None:
|
||||
c()
|
||||
c('x', 'y')
|
||||
[out]
|
||||
def f(c):
|
||||
c, r0 :: object
|
||||
r1, r2 :: str
|
||||
r3 :: object[2]
|
||||
r4 :: object_ptr
|
||||
r5 :: object
|
||||
L0:
|
||||
r0 = _PyObject_Vectorcall(c, 0, 0, 0)
|
||||
r1 = 'x'
|
||||
r2 = 'y'
|
||||
r3 = [r1, r2]
|
||||
r4 = load_address r3
|
||||
r5 = _PyObject_Vectorcall(c, r4, 2, 0)
|
||||
keep_alive r1, r2
|
||||
return 1
|
||||
|
||||
[case testVectorcallKeywords_python3_8]
|
||||
from typing import Any
|
||||
|
||||
def f(c: Any) -> None:
|
||||
c(x='a')
|
||||
c('x', a='y', b='z')
|
||||
[out]
|
||||
def f(c):
|
||||
c :: object
|
||||
r0 :: str
|
||||
r1 :: object[1]
|
||||
r2 :: object_ptr
|
||||
r3, r4 :: object
|
||||
r5, r6, r7 :: str
|
||||
r8 :: object[3]
|
||||
r9 :: object_ptr
|
||||
r10, r11 :: object
|
||||
L0:
|
||||
r0 = 'a'
|
||||
r1 = [r0]
|
||||
r2 = load_address r1
|
||||
r3 = ('x',)
|
||||
r4 = _PyObject_Vectorcall(c, r2, 0, r3)
|
||||
keep_alive r0
|
||||
r5 = 'x'
|
||||
r6 = 'y'
|
||||
r7 = 'z'
|
||||
r8 = [r5, r6, r7]
|
||||
r9 = load_address r8
|
||||
r10 = ('a', 'b')
|
||||
r11 = _PyObject_Vectorcall(c, r9, 1, r10)
|
||||
keep_alive r5, r6, r7
|
||||
return 1
|
||||
|
||||
[case testVectorcallMethod_python3_8]
|
||||
from typing import Any
|
||||
|
||||
def f(o: Any) -> None:
|
||||
# On Python 3.8 vectorcalls are only faster with keyword args
|
||||
o.m('x')
|
||||
o.m('x', a='y')
|
||||
[out]
|
||||
def f(o):
|
||||
o :: object
|
||||
r0, r1 :: str
|
||||
r2 :: object
|
||||
r3, r4, r5 :: str
|
||||
r6 :: object
|
||||
r7 :: object[2]
|
||||
r8 :: object_ptr
|
||||
r9, r10 :: object
|
||||
L0:
|
||||
r0 = 'x'
|
||||
r1 = 'm'
|
||||
r2 = CPyObject_CallMethodObjArgs(o, r1, r0, 0)
|
||||
r3 = 'x'
|
||||
r4 = 'y'
|
||||
r5 = 'm'
|
||||
r6 = CPyObject_GetAttr(o, r5)
|
||||
r7 = [r3, r4]
|
||||
r8 = load_address r7
|
||||
r9 = ('a',)
|
||||
r10 = _PyObject_Vectorcall(r6, r8, 1, r9)
|
||||
keep_alive r3, r4
|
||||
return 1
|
||||
|
||||
[case testVectorcallMethod_python3_9_64bit]
|
||||
from typing import Any
|
||||
|
||||
def f(o: Any) -> None:
|
||||
# Python 3.9 has a new API for calling methods
|
||||
o.m('x')
|
||||
o.m('x', 'y', a='z')
|
||||
[out]
|
||||
def f(o):
|
||||
o :: object
|
||||
r0, r1 :: str
|
||||
r2 :: object[2]
|
||||
r3 :: object_ptr
|
||||
r4 :: object
|
||||
r5, r6, r7, r8 :: str
|
||||
r9 :: object[4]
|
||||
r10 :: object_ptr
|
||||
r11, r12 :: object
|
||||
L0:
|
||||
r0 = 'x'
|
||||
r1 = 'm'
|
||||
r2 = [o, r0]
|
||||
r3 = load_address r2
|
||||
r4 = PyObject_VectorcallMethod(r1, r3, 9223372036854775810, 0)
|
||||
keep_alive o, r0
|
||||
r5 = 'x'
|
||||
r6 = 'y'
|
||||
r7 = 'z'
|
||||
r8 = 'm'
|
||||
r9 = [o, r5, r6, r7]
|
||||
r10 = load_address r9
|
||||
r11 = ('a',)
|
||||
r12 = PyObject_VectorcallMethod(r8, r10, 9223372036854775811, r11)
|
||||
keep_alive o, r5, r6, r7
|
||||
return 1
|
||||
|
||||
[case testVectorcallMethod_python3_9_32bit]
|
||||
from typing import Any
|
||||
|
||||
def f(o: Any) -> None:
|
||||
# The IR is slightly different on 32-bit platforms
|
||||
o.m('x', a='y')
|
||||
[out]
|
||||
def f(o):
|
||||
o :: object
|
||||
r0, r1, r2 :: str
|
||||
r3 :: object[3]
|
||||
r4 :: object_ptr
|
||||
r5, r6 :: object
|
||||
L0:
|
||||
r0 = 'x'
|
||||
r1 = 'y'
|
||||
r2 = 'm'
|
||||
r3 = [o, r0, r1]
|
||||
r4 = load_address r3
|
||||
r5 = ('a',)
|
||||
r6 = PyObject_VectorcallMethod(r2, r4, 2147483650, r5)
|
||||
keep_alive o, r0, r1
|
||||
return 1
|
||||
1528
venv/lib/python3.12/site-packages/mypyc/test-data/refcount.test
Normal file
1528
venv/lib/python3.12/site-packages/mypyc/test-data/refcount.test
Normal file
File diff suppressed because it is too large
Load Diff
145
venv/lib/python3.12/site-packages/mypyc/test-data/run-async.test
Normal file
145
venv/lib/python3.12/site-packages/mypyc/test-data/run-async.test
Normal file
@@ -0,0 +1,145 @@
|
||||
# async test cases (compile and run)
|
||||
|
||||
[case testAsync]
|
||||
import asyncio
|
||||
|
||||
async def h() -> int:
|
||||
return 1
|
||||
|
||||
async def g() -> int:
|
||||
await asyncio.sleep(0)
|
||||
return await h()
|
||||
|
||||
async def f() -> int:
|
||||
return await g()
|
||||
|
||||
[file asyncio/__init__.pyi]
|
||||
async def sleep(t: float) -> None: ...
|
||||
|
||||
[typing fixtures/typing-full.pyi]
|
||||
|
||||
[file driver.py]
|
||||
from native import f
|
||||
import asyncio
|
||||
|
||||
result = asyncio.run(f())
|
||||
assert result == 1
|
||||
|
||||
[case testAsyncWith]
|
||||
from testutil import async_val
|
||||
|
||||
class async_ctx:
|
||||
async def __aenter__(self) -> str:
|
||||
await async_val("enter")
|
||||
return "test"
|
||||
|
||||
async def __aexit__(self, x, y, z) -> None:
|
||||
await async_val("exit")
|
||||
|
||||
|
||||
async def async_with() -> str:
|
||||
async with async_ctx() as x:
|
||||
return await async_val("body")
|
||||
|
||||
|
||||
[file driver.py]
|
||||
from native import async_with
|
||||
from testutil import run_generator
|
||||
|
||||
yields, val = run_generator(async_with(), [None, 'x', None])
|
||||
assert yields == ('enter', 'body', 'exit'), yields
|
||||
assert val == 'x', val
|
||||
|
||||
|
||||
[case testAsyncReturn]
|
||||
from testutil import async_val
|
||||
|
||||
async def async_return() -> str:
|
||||
try:
|
||||
return 'test'
|
||||
finally:
|
||||
await async_val('foo')
|
||||
|
||||
[file driver.py]
|
||||
from native import async_return
|
||||
from testutil import run_generator
|
||||
|
||||
yields, val = run_generator(async_return())
|
||||
assert yields == ('foo',)
|
||||
assert val == 'test', val
|
||||
|
||||
|
||||
[case testAsyncFor]
|
||||
from typing import AsyncIterable, List, Set, Dict
|
||||
|
||||
async def async_iter(xs: AsyncIterable[int]) -> List[int]:
|
||||
ys = []
|
||||
async for x in xs:
|
||||
ys.append(x)
|
||||
return ys
|
||||
|
||||
async def async_comp(xs: AsyncIterable[int]) -> List[int]:
|
||||
ys = [x async for x in xs]
|
||||
return ys
|
||||
|
||||
async def async_comp_set(xs: AsyncIterable[int]) -> Set[int]:
|
||||
return {x async for x in xs}
|
||||
|
||||
async def async_comp_dict(xs: AsyncIterable[int]) -> Dict[int, str]:
|
||||
return {x: str(x) async for x in xs}
|
||||
|
||||
[typing fixtures/typing-full.pyi]
|
||||
|
||||
[file driver.py]
|
||||
from native import async_iter, async_comp, async_comp_set, async_comp_dict
|
||||
from testutil import run_generator, async_val
|
||||
from typing import AsyncIterable, List
|
||||
|
||||
# defined here since we couldn't do it inside the test yet...
|
||||
async def foo() -> AsyncIterable[int]:
|
||||
for x in range(3):
|
||||
await async_val(x)
|
||||
yield x
|
||||
|
||||
yields, val = run_generator(async_iter(foo()))
|
||||
assert val == [0,1,2], val
|
||||
assert yields == (0,1,2), yields
|
||||
|
||||
yields, val = run_generator(async_comp(foo()))
|
||||
assert val == [0,1,2], val
|
||||
assert yields == (0,1,2), yields
|
||||
|
||||
yields, val = run_generator(async_comp_set(foo()))
|
||||
assert val == {0,1,2}, val
|
||||
assert yields == (0,1,2), yields
|
||||
|
||||
yields, val = run_generator(async_comp_dict(foo()))
|
||||
assert val == {0: '0',1: '1', 2: '2'}, val
|
||||
assert yields == (0,1,2), yields
|
||||
|
||||
[case testAsyncFor2]
|
||||
from typing import AsyncIterable, List
|
||||
|
||||
async def async_iter(xs: AsyncIterable[int]) -> List[int]:
|
||||
ys = []
|
||||
async for x in xs:
|
||||
ys.append(x)
|
||||
return ys
|
||||
|
||||
[typing fixtures/typing-full.pyi]
|
||||
|
||||
[file driver.py]
|
||||
from native import async_iter
|
||||
from testutil import run_generator, async_val
|
||||
from typing import AsyncIterable, List
|
||||
|
||||
# defined here since we couldn't do it inside the test yet...
|
||||
async def foo() -> AsyncIterable[int]:
|
||||
for x in range(3):
|
||||
await async_val(x)
|
||||
yield x
|
||||
raise Exception('lol no')
|
||||
|
||||
yields, val = run_generator(async_iter(foo()))
|
||||
assert yields == (0,1,2), yields
|
||||
assert val == 'lol no', val
|
||||
318
venv/lib/python3.12/site-packages/mypyc/test-data/run-attrs.test
Normal file
318
venv/lib/python3.12/site-packages/mypyc/test-data/run-attrs.test
Normal file
@@ -0,0 +1,318 @@
|
||||
-- Test cases for dataclasses based on the attrs library, where auto_attribs=True
|
||||
|
||||
[case testRunAttrsclass]
|
||||
import attr
|
||||
from typing import Set, List, Callable, Any
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class Person1:
|
||||
age : int
|
||||
name : str
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.name == 'robot'
|
||||
|
||||
def testBool(p: Person1) -> bool:
|
||||
if p:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class Person1b(Person1):
|
||||
id: str = '000'
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class Person2:
|
||||
age : int
|
||||
name : str = attr.ib(default='robot')
|
||||
|
||||
@attr.s(auto_attribs=True, order=True)
|
||||
class Person3:
|
||||
age : int = attr.ib(default = 6)
|
||||
friendIDs : List[int] = attr.ib(factory = list)
|
||||
|
||||
def get_age(self) -> int:
|
||||
return (self.age)
|
||||
|
||||
def set_age(self, new_age : int) -> None:
|
||||
self.age = new_age
|
||||
|
||||
def add_friendID(self, fid : int) -> None:
|
||||
self.friendIDs.append(fid)
|
||||
|
||||
def get_friendIDs(self) -> List[int]:
|
||||
return self.friendIDs
|
||||
|
||||
def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]:
|
||||
def f(a: Any) -> int:
|
||||
return g(a) + 1
|
||||
return f
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class Person4:
|
||||
age : int
|
||||
_name : str = 'Bot'
|
||||
|
||||
@get_next_age
|
||||
def get_age(self) -> int:
|
||||
return self.age
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class Point:
|
||||
x : int = attr.ib(converter=int)
|
||||
y : int = attr.ib(init=False)
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
self.y = self.x + 1
|
||||
|
||||
|
||||
[file other.py]
|
||||
from native import Person1, Person1b, Person2, Person3, Person4, testBool, Point
|
||||
i1 = Person1(age = 5, name = 'robot')
|
||||
assert i1.age == 5
|
||||
assert i1.name == 'robot'
|
||||
assert testBool(i1) == True
|
||||
assert testBool(Person1(age = 5, name = 'robo')) == False
|
||||
i1b = Person1b(age = 5, name = 'robot')
|
||||
assert i1b.age == 5
|
||||
assert i1b.name == 'robot'
|
||||
assert i1b.id == '000'
|
||||
assert testBool(i1b) == True
|
||||
assert testBool(Person1b(age = 5, name = 'robo')) == False
|
||||
i1c = Person1b(age = 20, name = 'robot', id = 'test')
|
||||
assert i1c.age == 20
|
||||
assert i1c.id == 'test'
|
||||
|
||||
i2 = Person2(age = 5)
|
||||
assert i2.age == 5
|
||||
assert i2.name == 'robot'
|
||||
i3 = Person2(age = 5, name = 'new_robot')
|
||||
assert i3.age == 5
|
||||
assert i3.name == 'new_robot'
|
||||
i4 = Person3()
|
||||
assert i4.age == 6
|
||||
assert i4.friendIDs == []
|
||||
i5 = Person3(age = 5)
|
||||
assert i5.age == 5
|
||||
assert i5.friendIDs == []
|
||||
i6 = Person3(age = 5, friendIDs = [1,2,3])
|
||||
assert i6.age == 5
|
||||
assert i6.friendIDs == [1,2,3]
|
||||
assert i6.get_age() == 5
|
||||
i6.set_age(10)
|
||||
assert i6.get_age() == 10
|
||||
i6.add_friendID(4)
|
||||
assert i6.get_friendIDs() == [1,2,3,4]
|
||||
i7 = Person4(age = 5)
|
||||
assert i7.get_age() == 6
|
||||
i7.age += 3
|
||||
assert i7.age == 8
|
||||
assert i7.name == 'Bot'
|
||||
i8 = Person3(age = 1, friendIDs = [1,2])
|
||||
i9 = Person3(age = 1, friendIDs = [1,2])
|
||||
assert i8 == i9
|
||||
i8.age = 2
|
||||
assert i8 > i9
|
||||
|
||||
assert Person1.__annotations__ == {'age': int, 'name': str}
|
||||
assert Person2.__annotations__ == {'age': int, 'name': str}
|
||||
|
||||
p1 = Point(2)
|
||||
assert p1.x == 2
|
||||
assert p1.y == 3
|
||||
p2 = Point('2')
|
||||
assert p2.x == 2
|
||||
assert p2.y == 3
|
||||
|
||||
assert Point.__annotations__ == {'x': int, 'y': int}
|
||||
|
||||
[file driver.py]
|
||||
import sys
|
||||
|
||||
# PEP 526 introduced in 3.6
|
||||
version = sys.version_info[:2]
|
||||
if version[0] < 3 or version[1] < 6:
|
||||
exit()
|
||||
|
||||
# Run the tests in both interpreted and compiled mode
|
||||
import other
|
||||
import other_interpreted
|
||||
|
||||
# Test for an exceptional cases
|
||||
from testutil import assertRaises
|
||||
from native import Person1, Person1b, Person3
|
||||
from types import BuiltinMethodType
|
||||
|
||||
with assertRaises(TypeError, "missing 1 required positional argument"):
|
||||
Person1(0)
|
||||
|
||||
with assertRaises(TypeError, "missing 2 required positional arguments"):
|
||||
Person1b()
|
||||
|
||||
with assertRaises(TypeError, "int object expected; got str"):
|
||||
Person1('nope', 'test')
|
||||
|
||||
p = Person1(0, 'test')
|
||||
with assertRaises(TypeError, "int object expected; got str"):
|
||||
p.age = 'nope'
|
||||
|
||||
assert isinstance(Person3().get_age, BuiltinMethodType)
|
||||
|
||||
|
||||
[case testRunAttrsclassNonAuto]
|
||||
import attr
|
||||
from typing import Set, List, Callable, Any
|
||||
|
||||
@attr.s
|
||||
class Person1:
|
||||
age = attr.ib(type=int)
|
||||
name = attr.ib(type=str)
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.name == 'robot'
|
||||
|
||||
def testBool(p: Person1) -> bool:
|
||||
if p:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@attr.s
|
||||
class Person1b(Person1):
|
||||
id = attr.ib(type=str, default='000')
|
||||
|
||||
@attr.s
|
||||
class Person2:
|
||||
age = attr.ib(type=int)
|
||||
name = attr.ib(type=str, default='robot')
|
||||
|
||||
@attr.s(order=True)
|
||||
class Person3:
|
||||
age = attr.ib(type=int, default=6)
|
||||
friendIDs = attr.ib(factory=list, type=List[int])
|
||||
|
||||
def get_age(self) -> int:
|
||||
return (self.age)
|
||||
|
||||
def set_age(self, new_age : int) -> None:
|
||||
self.age = new_age
|
||||
|
||||
def add_friendID(self, fid : int) -> None:
|
||||
self.friendIDs.append(fid)
|
||||
|
||||
def get_friendIDs(self) -> List[int]:
|
||||
return self.friendIDs
|
||||
|
||||
def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]:
|
||||
def f(a: Any) -> int:
|
||||
return g(a) + 1
|
||||
return f
|
||||
|
||||
@attr.s
|
||||
class Person4:
|
||||
age = attr.ib(type=int)
|
||||
_name = attr.ib(type=str, default='Bot')
|
||||
|
||||
@get_next_age
|
||||
def get_age(self) -> int:
|
||||
return self.age
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@attr.s
|
||||
class Point:
|
||||
x = attr.ib(type=int, converter=int)
|
||||
y = attr.ib(type=int, init=False)
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
self.y = self.x + 1
|
||||
|
||||
|
||||
[file other.py]
|
||||
from native import Person1, Person1b, Person2, Person3, Person4, testBool, Point
|
||||
i1 = Person1(age = 5, name = 'robot')
|
||||
assert i1.age == 5
|
||||
assert i1.name == 'robot'
|
||||
assert testBool(i1) == True
|
||||
assert testBool(Person1(age = 5, name = 'robo')) == False
|
||||
i1b = Person1b(age = 5, name = 'robot')
|
||||
assert i1b.age == 5
|
||||
assert i1b.name == 'robot'
|
||||
assert i1b.id == '000'
|
||||
assert testBool(i1b) == True
|
||||
assert testBool(Person1b(age = 5, name = 'robo')) == False
|
||||
i1c = Person1b(age = 20, name = 'robot', id = 'test')
|
||||
assert i1c.age == 20
|
||||
assert i1c.id == 'test'
|
||||
|
||||
i2 = Person2(age = 5)
|
||||
assert i2.age == 5
|
||||
assert i2.name == 'robot'
|
||||
i3 = Person2(age = 5, name = 'new_robot')
|
||||
assert i3.age == 5
|
||||
assert i3.name == 'new_robot'
|
||||
i4 = Person3()
|
||||
assert i4.age == 6
|
||||
assert i4.friendIDs == []
|
||||
i5 = Person3(age = 5)
|
||||
assert i5.age == 5
|
||||
assert i5.friendIDs == []
|
||||
i6 = Person3(age = 5, friendIDs = [1,2,3])
|
||||
assert i6.age == 5
|
||||
assert i6.friendIDs == [1,2,3]
|
||||
assert i6.get_age() == 5
|
||||
i6.set_age(10)
|
||||
assert i6.get_age() == 10
|
||||
i6.add_friendID(4)
|
||||
assert i6.get_friendIDs() == [1,2,3,4]
|
||||
i7 = Person4(age = 5)
|
||||
assert i7.get_age() == 6
|
||||
i7.age += 3
|
||||
assert i7.age == 8
|
||||
assert i7.name == 'Bot'
|
||||
i8 = Person3(age = 1, friendIDs = [1,2])
|
||||
i9 = Person3(age = 1, friendIDs = [1,2])
|
||||
assert i8 == i9
|
||||
i8.age = 2
|
||||
assert i8 > i9
|
||||
|
||||
p1 = Point(2)
|
||||
assert p1.x == 2
|
||||
assert p1.y == 3
|
||||
p2 = Point('2')
|
||||
assert p2.x == 2
|
||||
assert p2.y == 3
|
||||
|
||||
[file driver.py]
|
||||
import sys
|
||||
|
||||
# Run the tests in both interpreted and compiled mode
|
||||
import other
|
||||
import other_interpreted
|
||||
|
||||
# Test for an exceptional cases
|
||||
from testutil import assertRaises
|
||||
from native import Person1, Person1b, Person3
|
||||
from types import BuiltinMethodType
|
||||
|
||||
with assertRaises(TypeError, "missing 1 required positional argument"):
|
||||
Person1(0)
|
||||
|
||||
with assertRaises(TypeError, "missing 2 required positional arguments"):
|
||||
Person1b()
|
||||
|
||||
with assertRaises(TypeError, "int object expected; got str"):
|
||||
Person1('nope', 'test')
|
||||
|
||||
p = Person1(0, 'test')
|
||||
with assertRaises(TypeError, "int object expected; got str"):
|
||||
p.age = 'nope'
|
||||
|
||||
assert isinstance(Person3().get_age, BuiltinMethodType)
|
||||
196
venv/lib/python3.12/site-packages/mypyc/test-data/run-bench.test
Normal file
196
venv/lib/python3.12/site-packages/mypyc/test-data/run-bench.test
Normal file
@@ -0,0 +1,196 @@
|
||||
-- TODO: build some generic benchmark harness
|
||||
[case testBenchmarkTree]
|
||||
from typing import Optional
|
||||
class Node:
|
||||
def __init__(self, value: int) -> None:
|
||||
self.value = value
|
||||
self.left = None # type: Optional[Node]
|
||||
self.right = None # type: Optional[Node]
|
||||
def sum(self) -> int:
|
||||
left = 0
|
||||
if self.left is not None:
|
||||
left = self.left.sum()
|
||||
right = 0
|
||||
if self.right is not None:
|
||||
right = self.right.sum()
|
||||
return self.value + left + right
|
||||
def sum_tree(x: Optional[Node]) -> int:
|
||||
if x is None:
|
||||
return 0
|
||||
return x.value + sum_tree(x.left) + sum_tree(x.right)
|
||||
def build(n: int) -> Optional[Node]:
|
||||
if n == 0:
|
||||
return None
|
||||
x = Node(n)
|
||||
x.left = build(n - 1)
|
||||
x.right = x.left
|
||||
return x
|
||||
|
||||
def bench_sum(x: Optional[Node]) -> None:
|
||||
for i in range(1000000):
|
||||
sum_tree(x)
|
||||
def bench_sum_method(x: Node) -> None:
|
||||
for i in range(1000000):
|
||||
x.sum()
|
||||
[file driver.py]
|
||||
from typing import Optional
|
||||
import native
|
||||
import interpreted
|
||||
from timeit import timeit
|
||||
from time import time
|
||||
import os
|
||||
|
||||
def dumb_time(f):
|
||||
t0 = time()
|
||||
f()
|
||||
t1 = time()
|
||||
return t1 - t0
|
||||
|
||||
def basic_test(m):
|
||||
tree = m.build(5)
|
||||
assert(m.sum_tree(tree) == 57)
|
||||
assert(tree.sum() == 57)
|
||||
return tree
|
||||
|
||||
def test(m):
|
||||
tree = basic_test(m)
|
||||
|
||||
g = {**globals(), **locals()}
|
||||
sum = timeit('m.sum_tree(tree)', globals=g)
|
||||
sum2 = timeit('tree.sum()', globals=g)
|
||||
fsum = dumb_time(lambda: m.bench_sum(tree))
|
||||
fsum2 = dumb_time(lambda: m.bench_sum_method(tree))
|
||||
build = timeit('m.build(5)', globals=g)
|
||||
return (sum, sum2, fsum, fsum2, build)
|
||||
|
||||
# Basic functionality test
|
||||
basic_test(native)
|
||||
|
||||
# Benchmark if we are benchmarking
|
||||
if os.environ.get('MYPYC_RUN_BENCH') == '1':
|
||||
nsum, nsum2, nfsum, nfsum2, nbuild = test(native)
|
||||
isum, isum2, ifsum, ifsum2, ibuild = test(interpreted)
|
||||
print(nsum, nsum2, nfsum, nbuild)
|
||||
print("Sum speedup:", isum/nsum)
|
||||
print("Sum method speedup:", isum2/nsum2)
|
||||
print("Sum (fast) speedup:", ifsum/nfsum)
|
||||
print("Sum (fast) method speedup:", ifsum2/nfsum2)
|
||||
print("Build speedup:", ibuild/nbuild)
|
||||
|
||||
[case testBenchmarkVisitorTree]
|
||||
from mypy_extensions import trait
|
||||
from typing import cast, Generic, TypeVar, Any
|
||||
|
||||
T = TypeVar('T')
|
||||
class Tree:
|
||||
def accept(self, v: 'TreeVisitor[T]') -> T:
|
||||
pass
|
||||
class Leaf(Tree):
|
||||
def accept(self, v: 'TreeVisitor[T]') -> T:
|
||||
return v.visit_leaf(self)
|
||||
class Node(Tree):
|
||||
def __init__(self, value: int, left: Tree, right: Tree) -> None:
|
||||
self.value = value
|
||||
self.left = left
|
||||
self.right = right
|
||||
def accept(self, v: 'TreeVisitor[T]') -> T:
|
||||
return v.visit_node(self)
|
||||
|
||||
@trait
|
||||
class TreeVisitor(Generic[T]):
|
||||
def visit_leaf(self, x: Leaf) -> T: return cast(T, None)
|
||||
def visit_node(self, x: Node) -> T: return cast(T, None)
|
||||
|
||||
class SumVisitor(TreeVisitor[int]):
|
||||
def sum(self, x: Tree) -> int:
|
||||
return x.accept(self)
|
||||
def visit_leaf(self, x: Leaf) -> int:
|
||||
return 0
|
||||
def visit_node(self, x: Node) -> int:
|
||||
return x.value + self.sum(x.left) + self.sum(x.right)
|
||||
|
||||
def equal(x: Tree, y: Tree) -> bool:
|
||||
return EqualVisitor(x).equal(y)
|
||||
|
||||
class EqualVisitor(TreeVisitor[bool]):
|
||||
def __init__(self, left: Tree) -> None:
|
||||
self.left = left
|
||||
def equal(self, right: Tree) -> bool:
|
||||
return right.accept(self)
|
||||
def visit_leaf(self, right: Leaf) -> bool:
|
||||
return isinstance(self.left, Leaf)
|
||||
def visit_node(self, right: Node) -> bool:
|
||||
if isinstance(self.left, Node):
|
||||
# our boolean stuff is crap
|
||||
if (self.left.value == right.value and equal(self.left.left, right.left)
|
||||
and equal(self.left.right, right.right)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def sum_tree(x: Tree) -> int:
|
||||
return SumVisitor().sum(x)
|
||||
|
||||
def build(n: int) -> Tree:
|
||||
if n == 0:
|
||||
return Leaf()
|
||||
return Node(n, build(n - 1), build(n - 1))
|
||||
|
||||
def bench_sum_tree(x: Tree) -> None:
|
||||
for i in range(100000):
|
||||
sum_tree(x)
|
||||
def bench_equal_tree(x: Tree, y: Tree) -> None:
|
||||
for i in range(100000):
|
||||
equal(x, y)
|
||||
|
||||
[file driver.py]
|
||||
from typing import Optional
|
||||
import interpreted
|
||||
import native
|
||||
from timeit import timeit
|
||||
from time import time
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Side test: some stuff about MROs and generics
|
||||
if sys.version_info[:3] > (3, 5, 2):
|
||||
assert tuple(x.__name__ for x in interpreted.SumVisitor.mro()) == ('SumVisitor', 'TreeVisitor', 'Generic', 'object')
|
||||
assert tuple(x.__name__ for x in native.SumVisitor.mro()) == ('SumVisitor', 'TreeVisitor', 'Generic', 'object')
|
||||
assert str(native.TreeVisitor[native.T]) == "native.TreeVisitor[~T]"
|
||||
|
||||
assert native.TreeVisitor.__name__ == "TreeVisitor"
|
||||
assert native.SumVisitor.__name__ == "SumVisitor"
|
||||
|
||||
def dumb_time(f):
|
||||
t0 = time()
|
||||
f()
|
||||
t1 = time()
|
||||
return t1 - t0
|
||||
|
||||
def basic_test(m):
|
||||
tree = m.build(5)
|
||||
tree2 = m.build(5)
|
||||
tree2.right.right.right.value = 10
|
||||
assert m.sum_tree(tree) == 57
|
||||
assert m.equal(tree, tree)
|
||||
assert not m.equal(tree, tree2)
|
||||
|
||||
assert isinstance(native.SumVisitor(), native.TreeVisitor)
|
||||
|
||||
return tree
|
||||
|
||||
def test(m):
|
||||
tree = basic_test(m)
|
||||
|
||||
g = {**globals(), **locals()}
|
||||
fsum = dumb_time(lambda: m.bench_sum_tree(tree))
|
||||
feq = dumb_time(lambda: m.bench_equal_tree(tree, tree))
|
||||
return fsum, feq
|
||||
|
||||
basic_test(native)
|
||||
|
||||
if os.environ.get('MYPYC_RUN_BENCH') == '1':
|
||||
nfsum, nfeq = test(native)
|
||||
ifsum, ifeq = test(interpreted)
|
||||
print(nfsum)
|
||||
print("Sum speedup:", ifsum/nfsum)
|
||||
print("Equal speedup:", ifeq/nfeq)
|
||||
229
venv/lib/python3.12/site-packages/mypyc/test-data/run-bools.test
Normal file
229
venv/lib/python3.12/site-packages/mypyc/test-data/run-bools.test
Normal file
@@ -0,0 +1,229 @@
|
||||
# Test cases for booleans (compile and run)
|
||||
|
||||
[case testTrueAndFalse]
|
||||
def t() -> bool:
|
||||
return True
|
||||
|
||||
def f() -> bool:
|
||||
return False
|
||||
[file driver.py]
|
||||
from native import t, f
|
||||
print(t())
|
||||
print(f())
|
||||
[out]
|
||||
True
|
||||
False
|
||||
|
||||
[case testBoolOps]
|
||||
from typing import Optional, Any
|
||||
MYPY = False
|
||||
if MYPY:
|
||||
from mypy_extensions import i64
|
||||
|
||||
def f(x: bool) -> bool:
|
||||
if x:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def test_if() -> None:
|
||||
assert f(True) is False
|
||||
assert f(False) is True
|
||||
|
||||
def test_bitwise_and() -> None:
|
||||
# Use eval() to avoid constand folding
|
||||
t: bool = eval('True')
|
||||
f: bool = eval('False')
|
||||
assert t & t == True
|
||||
assert t & f == False
|
||||
assert f & t == False
|
||||
assert f & f == False
|
||||
t &= t
|
||||
assert t == True
|
||||
t &= f
|
||||
assert t == False
|
||||
|
||||
def test_bitwise_or() -> None:
|
||||
# Use eval() to avoid constand folding
|
||||
t: bool = eval('True')
|
||||
f: bool = eval('False')
|
||||
assert t | t == True
|
||||
assert t | f == True
|
||||
assert f | t == True
|
||||
assert f | f == False
|
||||
t |= f
|
||||
assert t == True
|
||||
f |= t
|
||||
assert f == True
|
||||
|
||||
def test_bitwise_xor() -> None:
|
||||
# Use eval() to avoid constand folding
|
||||
t: bool = eval('True')
|
||||
f: bool = eval('False')
|
||||
assert t ^ t == False
|
||||
assert t ^ f == True
|
||||
assert f ^ t == True
|
||||
assert f ^ f == False
|
||||
t ^= f
|
||||
assert t == True
|
||||
t ^= t
|
||||
assert t == False
|
||||
f ^= f
|
||||
assert f == False
|
||||
|
||||
def test_isinstance_bool() -> None:
|
||||
a = True
|
||||
b = 1.0
|
||||
c = 1
|
||||
d = False
|
||||
assert isinstance(a, bool) == True
|
||||
assert isinstance(b, bool) == False
|
||||
assert isinstance(c, bool) == False
|
||||
assert isinstance(d, bool) == True
|
||||
|
||||
class C: pass
|
||||
class D:
|
||||
def __init__(self, b: bool) -> None:
|
||||
self.b = b
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.b
|
||||
|
||||
class E: pass
|
||||
class F(E):
|
||||
def __init__(self, b: bool) -> None:
|
||||
self.b = b
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.b
|
||||
|
||||
def optional_to_bool1(o: Optional[C]) -> bool:
|
||||
return bool(o)
|
||||
|
||||
def optional_to_bool2(o: Optional[D]) -> bool:
|
||||
return bool(o)
|
||||
|
||||
def optional_to_bool3(o: Optional[E]) -> bool:
|
||||
return bool(o)
|
||||
|
||||
def test_optional_to_bool() -> None:
|
||||
assert not optional_to_bool1(None)
|
||||
assert optional_to_bool1(C())
|
||||
assert not optional_to_bool2(None)
|
||||
assert not optional_to_bool2(D(False))
|
||||
assert optional_to_bool2(D(True))
|
||||
assert not optional_to_bool3(None)
|
||||
assert optional_to_bool3(E())
|
||||
assert not optional_to_bool3(F(False))
|
||||
assert optional_to_bool3(F(True))
|
||||
|
||||
def test_any_to_bool() -> None:
|
||||
a: Any = int()
|
||||
b: Any = a + 1
|
||||
assert not bool(a)
|
||||
assert bool(b)
|
||||
|
||||
def eq(x: bool, y: bool) -> bool:
|
||||
return x == y
|
||||
|
||||
def ne(x: bool, y: bool) -> bool:
|
||||
return x != y
|
||||
|
||||
def lt(x: bool, y: bool) -> bool:
|
||||
return x < y
|
||||
|
||||
def le(x: bool, y: bool) -> bool:
|
||||
return x <= y
|
||||
|
||||
def gt(x: bool, y: bool) -> bool:
|
||||
return x > y
|
||||
|
||||
def ge(x: bool, y: bool) -> bool:
|
||||
return x >= y
|
||||
|
||||
def test_comparisons() -> None:
|
||||
for x in True, False:
|
||||
for y in True, False:
|
||||
x2: Any = x
|
||||
y2: Any = y
|
||||
assert eq(x, y) == (x2 == y2)
|
||||
assert ne(x, y) == (x2 != y2)
|
||||
assert lt(x, y) == (x2 < y2)
|
||||
assert le(x, y) == (x2 <= y2)
|
||||
assert gt(x, y) == (x2 > y2)
|
||||
assert ge(x, y) == (x2 >= y2)
|
||||
|
||||
def eq_mixed(x: bool, y: int) -> bool:
|
||||
return x == y
|
||||
|
||||
def neq_mixed(x: int, y: bool) -> bool:
|
||||
return x != y
|
||||
|
||||
def lt_mixed(x: bool, y: int) -> bool:
|
||||
return x < y
|
||||
|
||||
def gt_mixed(x: int, y: bool) -> bool:
|
||||
return x > y
|
||||
|
||||
def test_mixed_comparisons() -> None:
|
||||
for x in True, False:
|
||||
for n in -(1 << 70), -123, 0, 1, 1753, 1 << 70:
|
||||
assert eq_mixed(x, n) == (int(x) == n)
|
||||
assert neq_mixed(n, x) == (n != int(x))
|
||||
assert lt_mixed(x, n) == (int(x) < n)
|
||||
assert gt_mixed(n, x) == (n > int(x))
|
||||
|
||||
def add(x: bool, y: bool) -> int:
|
||||
return x + y
|
||||
|
||||
def add_mixed(b: bool, n: int) -> int:
|
||||
return b + n
|
||||
|
||||
def sub_mixed(n: int, b: bool) -> int:
|
||||
return n - b
|
||||
|
||||
def test_arithmetic() -> None:
|
||||
for x in True, False:
|
||||
for y in True, False:
|
||||
assert add(x, y) == int(x) + int(y)
|
||||
for n in -(1 << 70), -123, 0, 1, 1753, 1 << 70:
|
||||
assert add_mixed(x, n) == int(x) + n
|
||||
assert sub_mixed(n, x) == n - int(x)
|
||||
|
||||
def add_mixed_i64(b: bool, n: i64) -> i64:
|
||||
return b + n
|
||||
|
||||
def sub_mixed_i64(n: i64, b: bool) -> i64:
|
||||
return n - b
|
||||
|
||||
def test_arithmetic_i64() -> None:
|
||||
for x in True, False:
|
||||
for n in -(1 << 62), -123, 0, 1, 1753, 1 << 62:
|
||||
assert add_mixed_i64(x, n) == int(x) + n
|
||||
assert sub_mixed_i64(n, x) == n - int(x)
|
||||
|
||||
def eq_mixed_i64(x: bool, y: i64) -> bool:
|
||||
return x == y
|
||||
|
||||
def neq_mixed_i64(x: i64, y: bool) -> bool:
|
||||
return x != y
|
||||
|
||||
def lt_mixed_i64(x: bool, y: i64) -> bool:
|
||||
return x < y
|
||||
|
||||
def gt_mixed_i64(x: i64, y: bool) -> bool:
|
||||
return x > y
|
||||
|
||||
def test_mixed_comparisons_i64() -> None:
|
||||
for x in True, False:
|
||||
for n in -(1 << 62), -123, 0, 1, 1753, 1 << 62:
|
||||
assert eq_mixed_i64(x, n) == (int(x) == n)
|
||||
assert neq_mixed_i64(n, x) == (n != int(x))
|
||||
assert lt_mixed_i64(x, n) == (int(x) < n)
|
||||
assert gt_mixed_i64(n, x) == (n > int(x))
|
||||
|
||||
[case testBoolMixInt]
|
||||
y = False
|
||||
print((y or 0) and True)
|
||||
[out]
|
||||
0
|
||||
302
venv/lib/python3.12/site-packages/mypyc/test-data/run-bytes.test
Normal file
302
venv/lib/python3.12/site-packages/mypyc/test-data/run-bytes.test
Normal file
@@ -0,0 +1,302 @@
|
||||
# Bytes test cases (compile and run)
|
||||
|
||||
[case testBytesBasics]
|
||||
# Note: Add tests for additional operations to testBytesOps or in a new test case
|
||||
|
||||
def f(x: bytes) -> bytes:
|
||||
return x
|
||||
|
||||
def eq(a: bytes, b: bytes) -> bool:
|
||||
return a == b
|
||||
|
||||
def neq(a: bytes, b: bytes) -> bool:
|
||||
return a != b
|
||||
[file driver.py]
|
||||
from native import f, eq, neq
|
||||
assert f(b'123') == b'123'
|
||||
assert f(b'\x07 \x0b " \t \x7f \xf0') == b'\x07 \x0b " \t \x7f \xf0'
|
||||
assert eq(b'123', b'123')
|
||||
assert not eq(b'123', b'1234')
|
||||
assert not eq(b'123', b'124')
|
||||
assert not eq(b'123', b'223')
|
||||
assert neq(b'123', b'1234')
|
||||
try:
|
||||
f('x')
|
||||
assert False
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
[case testBytesInit]
|
||||
def test_bytes_init() -> None:
|
||||
b1 = bytes([5])
|
||||
assert b1 == b'\x05'
|
||||
b2 = bytes([5, 10, 12])
|
||||
assert b2 == b'\x05\n\x0c'
|
||||
b3 = bytes(bytearray(b'foo'))
|
||||
assert b3 == b'foo'
|
||||
b4 = bytes(b'aaa')
|
||||
assert b4 == b'aaa'
|
||||
b5 = bytes(5)
|
||||
assert b5 == b'\x00\x00\x00\x00\x00'
|
||||
try:
|
||||
bytes('x')
|
||||
assert False
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
[case testBytesOps]
|
||||
from testutil import assertRaises
|
||||
|
||||
def test_indexing() -> None:
|
||||
# Use bytes() to avoid constant folding
|
||||
b = b'asdf' + bytes()
|
||||
assert b[0] == 97
|
||||
assert b[1] == 115
|
||||
assert b[3] == 102
|
||||
assert b[-1] == 102
|
||||
b = b'\xae\x80\xfe\x15' + bytes()
|
||||
assert b[0] == 174
|
||||
assert b[1] == 128
|
||||
assert b[2] == 254
|
||||
assert b[3] == 21
|
||||
assert b[-4] == 174
|
||||
with assertRaises(IndexError, "index out of range"):
|
||||
b[4]
|
||||
with assertRaises(IndexError, "index out of range"):
|
||||
b[-5]
|
||||
with assertRaises(IndexError, "index out of range"):
|
||||
b[2**26]
|
||||
|
||||
def test_concat() -> None:
|
||||
b1 = b'123' + bytes()
|
||||
b2 = b'456' + bytes()
|
||||
assert b1 + b2 == b'123456'
|
||||
b3 = b1 + b2
|
||||
b3 = b3 + b1
|
||||
assert b3 == b'123456123'
|
||||
assert b1 == b'123'
|
||||
assert b2 == b'456'
|
||||
assert type(b1) == bytes
|
||||
assert type(b2) == bytes
|
||||
assert type(b3) == bytes
|
||||
brr1: bytes = bytearray(3)
|
||||
brr2: bytes = bytearray(range(5))
|
||||
b4 = b1 + brr1
|
||||
assert b4 == b'123\x00\x00\x00'
|
||||
assert type(brr1) == bytearray
|
||||
assert type(b4) == bytes
|
||||
brr3 = brr1 + brr2
|
||||
assert brr3 == bytearray(b'\x00\x00\x00\x00\x01\x02\x03\x04')
|
||||
assert len(brr3) == 8
|
||||
assert type(brr3) == bytearray
|
||||
brr3 = brr3 + bytearray([10])
|
||||
assert brr3 == bytearray(b'\x00\x00\x00\x00\x01\x02\x03\x04\n')
|
||||
b5 = brr2 + b2
|
||||
assert b5 == bytearray(b'\x00\x01\x02\x03\x04456')
|
||||
assert type(b5) == bytearray
|
||||
b5 = b2 + brr2
|
||||
assert b5 == b'456\x00\x01\x02\x03\x04'
|
||||
assert type(b5) == bytes
|
||||
|
||||
def test_join() -> None:
|
||||
seq = (b'1', b'"', b'\xf0')
|
||||
assert b'\x07'.join(seq) == b'1\x07"\x07\xf0'
|
||||
assert b', '.join(()) == b''
|
||||
assert b', '.join([bytes() + b'ab']) == b'ab'
|
||||
assert b', '.join([bytes() + b'ab', b'cd']) == b'ab, cd'
|
||||
|
||||
def test_len() -> None:
|
||||
# Use bytes() to avoid constant folding
|
||||
b = b'foo' + bytes()
|
||||
assert len(b) == 3
|
||||
assert len(bytes()) == 0
|
||||
|
||||
[case testBytesSlicing]
|
||||
def test_bytes_slicing() -> None:
|
||||
b = b'abcdefg'
|
||||
zero = int()
|
||||
ten = 10 + zero
|
||||
two = 2 + zero
|
||||
five = 5 + zero
|
||||
seven = 7 + zero
|
||||
assert b[:ten] == b'abcdefg'
|
||||
assert b[0:seven] == b'abcdefg'
|
||||
assert b[0:(len(b)+1)] == b'abcdefg'
|
||||
assert b[two:five] == b'cde'
|
||||
assert b[two:two] == b''
|
||||
assert b[-two:-two] == b''
|
||||
assert b[-ten:(-ten+1)] == b''
|
||||
assert b[:-two] == b'abcde'
|
||||
assert b[:two] == b'ab'
|
||||
assert b[:] == b'abcdefg'
|
||||
assert b[-two:] == b'fg'
|
||||
assert b[zero:] == b'abcdefg'
|
||||
assert b[:zero] == b''
|
||||
assert b[-ten:] == b'abcdefg'
|
||||
assert b[-ten:ten] == b'abcdefg'
|
||||
big_ints = [1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, 2**24, 2**63]
|
||||
for big_int in big_ints:
|
||||
assert b[1:big_int] == b'bcdefg'
|
||||
assert b[big_int:] == b''
|
||||
assert b[-big_int:-1] == b'abcdef'
|
||||
assert b[-big_int:big_int] == b'abcdefg'
|
||||
assert type(b[-big_int:-1]) == bytes
|
||||
assert type(b[-ten:]) == bytes
|
||||
assert type(b[:]) == bytes
|
||||
|
||||
[case testBytearrayBasics]
|
||||
from typing import Any
|
||||
|
||||
def test_basics() -> None:
|
||||
brr1: bytes = bytearray(3)
|
||||
assert brr1 == bytearray(b'\x00\x00\x00')
|
||||
assert brr1 == b'\x00\x00\x00'
|
||||
l = [10, 20, 30, 40]
|
||||
brr2: bytes = bytearray(l)
|
||||
assert brr2 == bytearray(b'\n\x14\x1e(')
|
||||
assert brr2 == b'\n\x14\x1e('
|
||||
brr3: bytes = bytearray(range(5))
|
||||
assert brr3 == bytearray(b'\x00\x01\x02\x03\x04')
|
||||
assert brr3 == b'\x00\x01\x02\x03\x04'
|
||||
brr4: bytes = bytearray('string', 'utf-8')
|
||||
assert brr4 == bytearray(b'string')
|
||||
assert brr4 == b'string'
|
||||
assert len(brr1) == 3
|
||||
assert len(brr2) == 4
|
||||
|
||||
def f(b: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def test_bytearray_passed_into_bytes() -> None:
|
||||
assert f(bytearray(3))
|
||||
brr1: Any = bytearray()
|
||||
assert f(brr1)
|
||||
|
||||
[case testBytearraySlicing]
|
||||
def test_bytearray_slicing() -> None:
|
||||
b: bytes = bytearray(b'abcdefg')
|
||||
zero = int()
|
||||
ten = 10 + zero
|
||||
two = 2 + zero
|
||||
five = 5 + zero
|
||||
seven = 7 + zero
|
||||
assert b[:ten] == b'abcdefg'
|
||||
assert b[0:seven] == b'abcdefg'
|
||||
assert b[two:five] == b'cde'
|
||||
assert b[two:two] == b''
|
||||
assert b[-two:-two] == b''
|
||||
assert b[-ten:(-ten+1)] == b''
|
||||
assert b[:-two] == b'abcde'
|
||||
assert b[:two] == b'ab'
|
||||
assert b[:] == b'abcdefg'
|
||||
assert b[-two:] == b'fg'
|
||||
assert b[zero:] == b'abcdefg'
|
||||
assert b[:zero] == b''
|
||||
assert b[-ten:] == b'abcdefg'
|
||||
assert b[-ten:ten] == b'abcdefg'
|
||||
big_ints = [1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, 2**24, 2**63]
|
||||
for big_int in big_ints:
|
||||
assert b[1:big_int] == b'bcdefg'
|
||||
assert b[big_int:] == b''
|
||||
assert b[-big_int:-1] == b'abcdef'
|
||||
assert b[-big_int:big_int] == b'abcdefg'
|
||||
assert type(b[-big_int:-1]) == bytearray
|
||||
assert type(b[-ten:]) == bytearray
|
||||
assert type(b[:]) == bytearray
|
||||
|
||||
[case testBytearrayIndexing]
|
||||
from testutil import assertRaises
|
||||
|
||||
def test_bytearray_indexing() -> None:
|
||||
b: bytes = bytearray(b'\xae\x80\xfe\x15')
|
||||
assert b[0] == 174
|
||||
assert b[1] == 128
|
||||
assert b[2] == 254
|
||||
assert b[3] == 21
|
||||
assert b[-4] == 174
|
||||
with assertRaises(IndexError, "index out of range"):
|
||||
b[4]
|
||||
with assertRaises(IndexError, "index out of range"):
|
||||
b[-5]
|
||||
b2 = bytearray([175, 255, 128, 22])
|
||||
assert b2[0] == 175
|
||||
assert b2[1] == 255
|
||||
assert b2[-1] == 22
|
||||
assert b2[2] == 128
|
||||
with assertRaises(ValueError, "byte must be in range(0, 256)"):
|
||||
b2[0] = -1
|
||||
with assertRaises(ValueError, "byte must be in range(0, 256)"):
|
||||
b2[0] = 256
|
||||
|
||||
[case testBytesJoin]
|
||||
from typing import Any
|
||||
from testutil import assertRaises
|
||||
from a import bytes_subclass
|
||||
|
||||
def test_bytes_join() -> None:
|
||||
assert b' '.join([b'a', b'b']) == b'a b'
|
||||
assert b' '.join([]) == b''
|
||||
|
||||
x: bytes = bytearray(b' ')
|
||||
assert x.join([b'a', b'b']) == b'a b'
|
||||
assert type(x.join([b'a', b'b'])) == bytearray
|
||||
|
||||
y: bytes = bytes_subclass()
|
||||
assert y.join([]) == b'spook'
|
||||
|
||||
n: Any = 5
|
||||
with assertRaises(TypeError, "can only join an iterable"):
|
||||
assert b' '.join(n)
|
||||
|
||||
[file a.py]
|
||||
class bytes_subclass(bytes):
|
||||
def join(self, iter):
|
||||
return b'spook'
|
||||
|
||||
[case testBytesFormatting]
|
||||
[typing fixtures/typing-full.pyi]
|
||||
from testutil import assertRaises
|
||||
|
||||
# https://www.python.org/dev/peps/pep-0461/
|
||||
def test_bytes_formatting() -> None:
|
||||
val = 10
|
||||
assert b"%x" % val == b'a'
|
||||
assert b'%4x' % val == b' a'
|
||||
assert b'%#4x' % val == b' 0xa'
|
||||
assert b'%04X' % val == b'000A'
|
||||
|
||||
assert b'%c' % 48 == b'0'
|
||||
assert b'%c' % b'a' == b'a'
|
||||
assert b'%c%c' % (48, b'a') == b'0a'
|
||||
|
||||
assert b'%b' % b'abc' == b'abc'
|
||||
assert b'%b' % 'some string'.encode('utf8') == b'some string'
|
||||
|
||||
assert b'%a' % 3.14 == b'3.14'
|
||||
assert b'%a' % b'abc' == b"b'abc'"
|
||||
assert b'%a' % 'def' == b"'def'"
|
||||
|
||||
def test_bytes_formatting_2() -> None:
|
||||
var = b'bb'
|
||||
num = 10
|
||||
assert b'aaa%bbbb%s' % (var, var) == b'aaabbbbbbb'
|
||||
assert b'aaa%dbbb%b' % (num, var) == b'aaa10bbbbb'
|
||||
assert b'%s%b' % (var, var) == b'bbbb'
|
||||
assert b'%b' % bytes() == b''
|
||||
assert b'%b' % b'' == b''
|
||||
|
||||
assert b'\xff%s' % b'\xff' == b'\xff\xff'
|
||||
assert b'\xff%b' % '你好'.encode() == b'\xff\xe4\xbd\xa0\xe5\xa5\xbd'
|
||||
|
||||
aa = b'\xe4\xbd\xa0\xe5\xa5\xbd%b' % b'\xe4\xbd\xa0\xe5\xa5\xbd'
|
||||
assert aa == b'\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd'
|
||||
assert aa.decode() == '你好你好'
|
||||
|
||||
|
||||
class A:
|
||||
def __bytes__(self):
|
||||
return b'aaa'
|
||||
|
||||
def test_bytes_dunder() -> None:
|
||||
assert b'%b' % A() == b'aaa'
|
||||
assert b'%s' % A() == b'aaa'
|
||||
2505
venv/lib/python3.12/site-packages/mypyc/test-data/run-classes.test
Normal file
2505
venv/lib/python3.12/site-packages/mypyc/test-data/run-classes.test
Normal file
File diff suppressed because it is too large
Load Diff
334
venv/lib/python3.12/site-packages/mypyc/test-data/run-dicts.test
Normal file
334
venv/lib/python3.12/site-packages/mypyc/test-data/run-dicts.test
Normal file
@@ -0,0 +1,334 @@
|
||||
# Test cases for dicts (compile and run)
|
||||
|
||||
[case testDictStuff]
|
||||
from typing import Dict, Any, List, Set, Tuple
|
||||
from defaultdictwrap import make_dict
|
||||
|
||||
def f(x: int) -> int:
|
||||
dict1 = {} # type: Dict[int, int]
|
||||
dict1[1] = 1
|
||||
dict2 = {} # type: Dict[int, int]
|
||||
dict2[x] = 2
|
||||
dict1.update(dict2)
|
||||
|
||||
l = [(5, 2)] # type: Any
|
||||
dict1.update(l)
|
||||
d2 = {6: 4} # type: Any
|
||||
dict1.update(d2)
|
||||
|
||||
return dict1[1]
|
||||
|
||||
def g() -> int:
|
||||
d = make_dict()
|
||||
d['a'] = 10
|
||||
d['a'] += 10
|
||||
d['b'] += 10
|
||||
l = [('c', 2)] # type: Any
|
||||
d.update(l)
|
||||
d2 = {'d': 4} # type: Any
|
||||
d.update(d2)
|
||||
return d['a'] + d['b']
|
||||
|
||||
def h() -> None:
|
||||
d = {} # type: Dict[Any, Any]
|
||||
d[{}]
|
||||
|
||||
def update_dict(x: Dict[Any, Any], y: Any):
|
||||
x.update(y)
|
||||
|
||||
def make_dict1(x: Any) -> Dict[Any, Any]:
|
||||
return dict(x)
|
||||
|
||||
def make_dict2(x: Dict[Any, Any]) -> Dict[Any, Any]:
|
||||
return dict(x)
|
||||
|
||||
def u(x: int) -> int:
|
||||
d = {} # type: Dict[str, int]
|
||||
d.update(x=x)
|
||||
return d['x']
|
||||
|
||||
def get_content(d: Dict[int, int]) -> Tuple[List[int], List[int], List[Tuple[int, int]]]:
|
||||
return list(d.keys()), list(d.values()), list(d.items())
|
||||
|
||||
def get_content_set(d: Dict[int, int]) -> Tuple[Set[int], Set[int], Set[Tuple[int, int]]]:
|
||||
return set(d.keys()), set(d.values()), set(d.items())
|
||||
[file defaultdictwrap.py]
|
||||
from typing import Dict
|
||||
from collections import defaultdict # type: ignore
|
||||
def make_dict() -> Dict[str, int]:
|
||||
return defaultdict(int)
|
||||
|
||||
[file driver.py]
|
||||
from collections import OrderedDict
|
||||
from native import (
|
||||
f, g, h, u, make_dict1, make_dict2, update_dict, get_content, get_content_set
|
||||
)
|
||||
assert f(1) == 2
|
||||
assert f(2) == 1
|
||||
assert g() == 30
|
||||
# Make sure we get a TypeError from indexing with unhashable and not KeyError
|
||||
try:
|
||||
h()
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
d = {'a': 1, 'b': 2}
|
||||
assert make_dict1(d) == d
|
||||
assert make_dict1(d.items()) == d
|
||||
assert make_dict2(d) == d
|
||||
# object.__dict__ is a "mappingproxy" and not a dict
|
||||
assert make_dict1(object.__dict__) == dict(object.__dict__)
|
||||
d = {}
|
||||
update_dict(d, object.__dict__)
|
||||
assert d == dict(object.__dict__)
|
||||
|
||||
assert u(10) == 10
|
||||
assert get_content({1: 2}) == ([1], [2], [(1, 2)])
|
||||
od = OrderedDict([(1, 2), (3, 4)])
|
||||
assert get_content(od) == ([1, 3], [2, 4], [(1, 2), (3, 4)])
|
||||
od.move_to_end(1)
|
||||
assert get_content(od) == ([3, 1], [4, 2], [(3, 4), (1, 2)])
|
||||
assert get_content_set({1: 2}) == ({1}, {2}, {(1, 2)})
|
||||
assert get_content_set(od) == ({1, 3}, {2, 4}, {(1, 2), (3, 4)})
|
||||
|
||||
[typing fixtures/typing-full.pyi]
|
||||
|
||||
[case testDictIterationMethodsRun]
|
||||
from typing import Dict, Union
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
class ExtensionDict(TypedDict):
|
||||
python: str
|
||||
c: str
|
||||
|
||||
def print_dict_methods(d1: Dict[int, int],
|
||||
d2: Dict[int, int],
|
||||
d3: Dict[int, int]) -> None:
|
||||
for k in d1.keys():
|
||||
print(k)
|
||||
for k, v in d2.items():
|
||||
print(k)
|
||||
print(v)
|
||||
for v in d3.values():
|
||||
print(v)
|
||||
|
||||
def print_dict_methods_special(d1: Union[Dict[int, int], Dict[str, str]],
|
||||
d2: ExtensionDict) -> None:
|
||||
for k in d1.keys():
|
||||
print(k)
|
||||
for k, v in d1.items():
|
||||
print(k)
|
||||
print(v)
|
||||
for v2 in d2.values():
|
||||
print(v2)
|
||||
for k2, v2 in d2.items():
|
||||
print(k2)
|
||||
print(v2)
|
||||
|
||||
|
||||
def clear_during_iter(d: Dict[int, int]) -> None:
|
||||
for k in d:
|
||||
d.clear()
|
||||
|
||||
class Custom(Dict[int, int]): pass
|
||||
[file driver.py]
|
||||
from native import print_dict_methods, print_dict_methods_special, Custom, clear_during_iter
|
||||
from collections import OrderedDict
|
||||
print_dict_methods({}, {}, {})
|
||||
print_dict_methods({1: 2}, {3: 4, 5: 6}, {7: 8})
|
||||
print('==')
|
||||
c = Custom({0: 1})
|
||||
print_dict_methods(c, c, c)
|
||||
print('==')
|
||||
d = OrderedDict([(1, 2), (3, 4)])
|
||||
print_dict_methods(d, d, d)
|
||||
print('==')
|
||||
print_dict_methods_special({1: 2}, {"python": ".py", "c": ".c"})
|
||||
d.move_to_end(1)
|
||||
print_dict_methods(d, d, d)
|
||||
clear_during_iter({}) # OK
|
||||
try:
|
||||
clear_during_iter({1: 2, 3: 4})
|
||||
except RuntimeError as e:
|
||||
assert str(e) == "dictionary changed size during iteration"
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
clear_during_iter(d)
|
||||
except RuntimeError as e:
|
||||
assert str(e) == "OrderedDict changed size during iteration"
|
||||
else:
|
||||
assert False
|
||||
|
||||
class CustomMad(dict):
|
||||
def __iter__(self):
|
||||
return self
|
||||
def __next__(self):
|
||||
raise ValueError
|
||||
m = CustomMad()
|
||||
try:
|
||||
clear_during_iter(m)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
class CustomBad(dict):
|
||||
def items(self):
|
||||
return [(1, 2, 3)] # Oops
|
||||
b = CustomBad()
|
||||
try:
|
||||
print_dict_methods(b, b, b)
|
||||
except TypeError as e:
|
||||
assert str(e) == "a tuple of length 2 expected"
|
||||
else:
|
||||
assert False
|
||||
[out]
|
||||
1
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
8
|
||||
==
|
||||
0
|
||||
0
|
||||
1
|
||||
1
|
||||
==
|
||||
1
|
||||
3
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
2
|
||||
4
|
||||
==
|
||||
1
|
||||
1
|
||||
2
|
||||
.py
|
||||
.c
|
||||
python
|
||||
.py
|
||||
c
|
||||
.c
|
||||
3
|
||||
1
|
||||
3
|
||||
4
|
||||
1
|
||||
2
|
||||
4
|
||||
2
|
||||
|
||||
[case testDictMethods]
|
||||
from collections import defaultdict
|
||||
from typing import Dict, Optional, List, Set
|
||||
|
||||
def test_dict_clear() -> None:
|
||||
d = {'a': 1, 'b': 2}
|
||||
d.clear()
|
||||
assert d == {}
|
||||
dd: Dict[str, int] = defaultdict(int)
|
||||
dd['a'] = 1
|
||||
dd.clear()
|
||||
assert dd == {}
|
||||
|
||||
def test_dict_copy() -> None:
|
||||
d: Dict[str, int] = {}
|
||||
assert d.copy() == d
|
||||
d = {'a': 1, 'b': 2}
|
||||
assert d.copy() == d
|
||||
assert d.copy() is not d
|
||||
dd: Dict[str, int] = defaultdict(int)
|
||||
dd['a'] = 1
|
||||
assert dd.copy() == dd
|
||||
assert isinstance(dd.copy(), defaultdict)
|
||||
|
||||
class MyDict(dict):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.update(*args, **kwargs)
|
||||
|
||||
def setdefault(self, k, v=None):
|
||||
if v is None:
|
||||
if k in self.keys():
|
||||
return self[k]
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return super().setdefault(k, v) + 10
|
||||
|
||||
def test_dict_setdefault() -> None:
|
||||
d: Dict[str, Optional[int]] = {'a': 1, 'b': 2}
|
||||
assert d.setdefault('a', 2) == 1
|
||||
assert d.setdefault('b', 2) == 2
|
||||
assert d.setdefault('c', 3) == 3
|
||||
assert d['a'] == 1
|
||||
assert d['c'] == 3
|
||||
assert d.setdefault('a') == 1
|
||||
assert d.setdefault('e') == None
|
||||
assert d.setdefault('e', 100) == None
|
||||
|
||||
def test_dict_subclass_setdefault() -> None:
|
||||
d = MyDict()
|
||||
d['a'] = 1
|
||||
assert d.setdefault('a', 2) == 11
|
||||
assert d.setdefault('b', 2) == 12
|
||||
assert d.setdefault('c', 3) == 13
|
||||
assert d['a'] == 1
|
||||
assert d['c'] == 3
|
||||
assert d.setdefault('a') == 1
|
||||
assert d.setdefault('e') == None
|
||||
assert d.setdefault('e', 100) == 110
|
||||
|
||||
def test_dict_empty_collection_setdefault() -> None:
|
||||
d1: Dict[str, List[int]] = {'a': [1, 2, 3]}
|
||||
assert d1.setdefault('a', []) == [1, 2, 3]
|
||||
assert d1.setdefault('b', []) == []
|
||||
assert 'b' in d1
|
||||
d1.setdefault('b', []).append(3)
|
||||
assert d1['b'] == [3]
|
||||
assert d1.setdefault('c', [1]) == [1]
|
||||
|
||||
d2: Dict[str, Dict[str, int]] = {'a': {'a': 1}}
|
||||
assert d2.setdefault('a', {}) == {'a': 1}
|
||||
assert d2.setdefault('b', {}) == {}
|
||||
assert 'b' in d2
|
||||
d2.setdefault('b', {})['aa'] = 2
|
||||
d2.setdefault('b', {})['bb'] = 3
|
||||
assert d2['b'] == {'aa': 2, 'bb': 3}
|
||||
assert d2.setdefault('c', {'cc': 1}) == {'cc': 1}
|
||||
|
||||
d3: Dict[str, Set[str]] = {'a': set('a')}
|
||||
assert d3.setdefault('a', set()) == {'a'}
|
||||
assert d3.setdefault('b', set()) == set()
|
||||
d3.setdefault('b', set()).add('b')
|
||||
d3.setdefault('b', set()).add('c')
|
||||
assert d3['b'] == {'b', 'c'}
|
||||
assert d3.setdefault('c', set('d')) == {'d'}
|
||||
|
||||
[case testDictToBool]
|
||||
from typing import Dict, List
|
||||
|
||||
def is_true(x: dict) -> bool:
|
||||
if x:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_false(x: dict) -> bool:
|
||||
if not x:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def test_dict_to_bool() -> None:
|
||||
assert is_false({})
|
||||
assert not is_true({})
|
||||
tmp_list: List[Dict] = [{2: bool}, {'a': 'b'}]
|
||||
for x in tmp_list:
|
||||
assert is_true(x)
|
||||
assert not is_false(x)
|
||||
@@ -0,0 +1,945 @@
|
||||
# Test cases for (some) dunder methods (compile and run)
|
||||
|
||||
[case testDundersMisc]
|
||||
# Legacy test case for dunders (don't add more here)
|
||||
|
||||
from typing import Any
|
||||
class Item:
|
||||
def __init__(self, value: str) -> None:
|
||||
self.value = value
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.value)
|
||||
|
||||
def __eq__(self, rhs: object) -> bool:
|
||||
return isinstance(rhs, Item) and self.value == rhs.value
|
||||
|
||||
def __lt__(self, x: 'Item') -> bool:
|
||||
return self.value < x.value
|
||||
|
||||
class Subclass1(Item):
|
||||
def __bool__(self) -> bool:
|
||||
return bool(self.value)
|
||||
|
||||
class NonBoxedThing:
|
||||
def __getitem__(self, index: Item) -> Item:
|
||||
return Item("2 * " + index.value + " + 1")
|
||||
|
||||
class BoxedThing:
|
||||
def __getitem__(self, index: int) -> int:
|
||||
return 2 * index + 1
|
||||
|
||||
class Subclass2(BoxedThing):
|
||||
pass
|
||||
|
||||
class UsesNotImplemented:
|
||||
def __eq__(self, b: object) -> bool:
|
||||
return NotImplemented
|
||||
|
||||
def index_into(x : Any, y : Any) -> Any:
|
||||
return x[y]
|
||||
|
||||
def internal_index_into() -> None:
|
||||
x = BoxedThing()
|
||||
print (x[3])
|
||||
y = NonBoxedThing()
|
||||
z = Item("3")
|
||||
print(y[z].value)
|
||||
|
||||
def is_truthy(x: Item) -> bool:
|
||||
return True if x else False
|
||||
|
||||
[file driver.py]
|
||||
from native import *
|
||||
x = BoxedThing()
|
||||
y = 3
|
||||
print(x[y], index_into(x, y))
|
||||
|
||||
x = Subclass2()
|
||||
y = 3
|
||||
print(x[y], index_into(x, y))
|
||||
|
||||
z = NonBoxedThing()
|
||||
w = Item("3")
|
||||
print(z[w].value, index_into(z, w).value)
|
||||
|
||||
i1 = Item('lolol')
|
||||
i2 = Item('lol' + 'ol')
|
||||
i3 = Item('xyzzy')
|
||||
assert hash(i1) == hash(i2)
|
||||
|
||||
assert i1 == i2
|
||||
assert not i1 != i2
|
||||
assert not i1 == i3
|
||||
assert i1 != i3
|
||||
assert i2 < i3
|
||||
assert not i1 < i2
|
||||
assert i1 == Subclass1('lolol')
|
||||
|
||||
assert is_truthy(Item(''))
|
||||
assert is_truthy(Item('a'))
|
||||
assert not is_truthy(Subclass1(''))
|
||||
assert is_truthy(Subclass1('a'))
|
||||
|
||||
assert UsesNotImplemented() != object()
|
||||
|
||||
internal_index_into()
|
||||
[out]
|
||||
7 7
|
||||
7 7
|
||||
2 * 3 + 1 2 * 3 + 1
|
||||
7
|
||||
2 * 3 + 1
|
||||
|
||||
[case testDundersContainer]
|
||||
# Sequence/mapping dunder methods
|
||||
|
||||
from typing import Any
|
||||
|
||||
class Seq:
|
||||
def __init__(self) -> None:
|
||||
self.key = 0
|
||||
self.value = 0
|
||||
|
||||
def __len__(self) -> int:
|
||||
return 5
|
||||
|
||||
def __setitem__(self, key: int, value: int) -> None:
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
||||
def __contains__(self, x: int) -> bool:
|
||||
return x == 3
|
||||
|
||||
def __delitem__(self, key: int) -> None:
|
||||
self.key = key
|
||||
|
||||
class Plain: pass
|
||||
|
||||
def any_seq() -> Any:
|
||||
"""Return Any-typed Seq."""
|
||||
return Seq()
|
||||
|
||||
def any_plain() -> Any:
|
||||
"""Return Any-typed Seq."""
|
||||
return Plain()
|
||||
|
||||
def test_len() -> None:
|
||||
assert len(any_seq()) == 5
|
||||
assert len(Seq()) == 5
|
||||
|
||||
def test_len_error() -> None:
|
||||
try:
|
||||
len(any_plain())
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
def test_set_item() -> None:
|
||||
s = any_seq()
|
||||
s[44] = 66
|
||||
assert s.key == 44 and s.value == 66
|
||||
ss = Seq()
|
||||
ss[33] = 55
|
||||
assert ss.key == 33 and ss.value == 55
|
||||
|
||||
def test_contains() -> None:
|
||||
assert 3 in any_seq()
|
||||
assert 4 not in any_seq()
|
||||
assert 2 not in any_seq()
|
||||
assert 3 in Seq()
|
||||
assert 4 not in Seq()
|
||||
assert 2 not in Seq()
|
||||
|
||||
def test_delitem() -> None:
|
||||
s = any_seq()
|
||||
del s[55]
|
||||
assert s.key == 55
|
||||
|
||||
class SeqAny:
|
||||
def __contains__(self, x: Any) -> Any:
|
||||
return x == 3
|
||||
|
||||
def __setitem__(self, x: Any, y: Any) -> Any:
|
||||
self.x = x
|
||||
return 'x'
|
||||
|
||||
def test_contains_any() -> None:
|
||||
assert (3 in SeqAny()) is True
|
||||
assert (2 in SeqAny()) is False
|
||||
assert (3 not in SeqAny()) is False
|
||||
assert (2 not in SeqAny()) is True
|
||||
s = SeqAny() # type: Any
|
||||
assert (3 in s) is True
|
||||
assert (2 in s) is False
|
||||
assert (3 not in s) is False
|
||||
assert (2 not in s) is True
|
||||
|
||||
def test_set_item_any() -> None:
|
||||
s = SeqAny()
|
||||
s[4] = 6
|
||||
assert s.x == 4
|
||||
ss = SeqAny() # type: Any
|
||||
ss[5] = 7
|
||||
assert ss.x == 5
|
||||
|
||||
class SeqError:
|
||||
def __setitem__(self, key: int, value: int) -> None:
|
||||
raise RuntimeError()
|
||||
|
||||
def __contains__(self, x: int) -> bool:
|
||||
raise RuntimeError()
|
||||
|
||||
def __len__(self):
|
||||
return -5
|
||||
|
||||
def any_seq_error() -> Any:
|
||||
return SeqError()
|
||||
|
||||
def test_set_item_error_propagate() -> None:
|
||||
s = any_seq_error()
|
||||
try:
|
||||
s[44] = 66
|
||||
except RuntimeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
def test_contains_error_propagate() -> None:
|
||||
s = any_seq_error()
|
||||
try:
|
||||
3 in s
|
||||
except RuntimeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
def test_negative_len() -> None:
|
||||
try:
|
||||
len(SeqError())
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
class DelItemNoSetItem:
|
||||
def __delitem__(self, x: int) -> None:
|
||||
self.key = x
|
||||
|
||||
def test_del_item_with_no_set_item() -> None:
|
||||
o = DelItemNoSetItem()
|
||||
del o[22]
|
||||
assert o.key == 22
|
||||
a = o # type: Any
|
||||
del a[12]
|
||||
assert a.key == 12
|
||||
try:
|
||||
a[1] = 2
|
||||
except TypeError as e:
|
||||
assert str(e) == "'DelItemNoSetItem' object does not support item assignment"
|
||||
else:
|
||||
assert False
|
||||
|
||||
class SetItemOverride(dict):
|
||||
# Only override __setitem__, __delitem__ comes from dict
|
||||
|
||||
def __setitem__(self, x: int, y: int) -> None:
|
||||
self.key = x
|
||||
self.value = y
|
||||
|
||||
def test_set_item_override() -> None:
|
||||
o = SetItemOverride({'x': 12, 'y': 13})
|
||||
o[2] = 3
|
||||
assert o.key == 2 and o.value == 3
|
||||
a = o # type: Any
|
||||
o[4] = 5
|
||||
assert o.key == 4 and o.value == 5
|
||||
assert o['x'] == 12
|
||||
assert o['y'] == 13
|
||||
del o['x']
|
||||
assert 'x' not in o and 'y' in o
|
||||
del a['y']
|
||||
assert 'y' not in a and 'x' not in a
|
||||
|
||||
class DelItemOverride(dict):
|
||||
# Only override __delitem__, __setitem__ comes from dict
|
||||
|
||||
def __delitem__(self, x: int) -> None:
|
||||
self.key = x
|
||||
|
||||
def test_del_item_override() -> None:
|
||||
o = DelItemOverride()
|
||||
del o[2]
|
||||
assert o.key == 2
|
||||
a = o # type: Any
|
||||
del o[5]
|
||||
assert o.key == 5
|
||||
o['x'] = 12
|
||||
assert o['x'] == 12
|
||||
a['y'] = 13
|
||||
assert a['y'] == 13
|
||||
|
||||
class SetItemOverrideNative(Seq):
|
||||
def __setitem__(self, key: int, value: int) -> None:
|
||||
self.key = key + 1
|
||||
self.value = value + 1
|
||||
|
||||
def test_native_set_item_override() -> None:
|
||||
o = SetItemOverrideNative()
|
||||
o[1] = 4
|
||||
assert o.key == 2 and o.value == 5
|
||||
del o[6]
|
||||
assert o.key == 6
|
||||
a = o # type: Any
|
||||
a[10] = 12
|
||||
assert a.key == 11 and a.value == 13
|
||||
del a[16]
|
||||
assert a.key == 16
|
||||
|
||||
class DelItemOverrideNative(Seq):
|
||||
def __delitem__(self, key: int) -> None:
|
||||
self.key = key + 2
|
||||
|
||||
def test_native_del_item_override() -> None:
|
||||
o = DelItemOverrideNative()
|
||||
o[1] = 4
|
||||
assert o.key == 1 and o.value == 4
|
||||
del o[6]
|
||||
assert o.key == 8
|
||||
a = o # type: Any
|
||||
a[10] = 12
|
||||
assert a.key == 10 and a.value == 12
|
||||
del a[16]
|
||||
assert a.key == 18
|
||||
|
||||
[case testDundersNumber]
|
||||
from typing import Any
|
||||
|
||||
class C:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
def __neg__(self) -> int:
|
||||
return self.x + 1
|
||||
|
||||
def __invert__(self) -> int:
|
||||
return self.x + 2
|
||||
|
||||
def __int__(self) -> int:
|
||||
return self.x + 3
|
||||
|
||||
def __float__(self) -> float:
|
||||
return float(self.x + 4)
|
||||
|
||||
def __pos__(self) -> int:
|
||||
return self.x + 5
|
||||
|
||||
def __abs__(self) -> int:
|
||||
return abs(self.x) + 6
|
||||
|
||||
|
||||
def test_unary_dunders_generic() -> None:
|
||||
a: Any = C(10)
|
||||
|
||||
assert -a == 11
|
||||
assert ~a == 12
|
||||
assert int(a) == 13
|
||||
assert float(a) == 14.0
|
||||
assert +a == 15
|
||||
assert abs(a) == 16
|
||||
|
||||
def test_unary_dunders_native() -> None:
|
||||
c = C(10)
|
||||
|
||||
assert -c == 11
|
||||
assert ~c == 12
|
||||
assert int(c) == 13
|
||||
assert float(c) == 14.0
|
||||
assert +c == 15
|
||||
assert abs(c) == 16
|
||||
|
||||
[case testDundersBinarySimple]
|
||||
from typing import Any
|
||||
|
||||
class C:
|
||||
def __init__(self) -> None:
|
||||
self.x = 5
|
||||
|
||||
def __add__(self, y: int) -> int:
|
||||
return self.x + y
|
||||
|
||||
def __sub__(self, y: int) -> int:
|
||||
return self.x - y
|
||||
|
||||
def __mul__(self, y: int) -> int:
|
||||
return self.x * y
|
||||
|
||||
def __mod__(self, y: int) -> int:
|
||||
return self.x % y
|
||||
|
||||
def __lshift__(self, y: int) -> int:
|
||||
return self.x << y
|
||||
|
||||
def __rshift__(self, y: int) -> int:
|
||||
return self.x >> y
|
||||
|
||||
def __and__(self, y: int) -> int:
|
||||
return self.x & y
|
||||
|
||||
def __or__(self, y: int) -> int:
|
||||
return self.x | y
|
||||
|
||||
def __xor__(self, y: int) -> int:
|
||||
return self.x ^ y
|
||||
|
||||
def __matmul__(self, y: int) -> int:
|
||||
return self.x + y + 10
|
||||
|
||||
def __truediv__(self, y: int) -> int:
|
||||
return self.x + y + 20
|
||||
|
||||
def __floordiv__(self, y: int) -> int:
|
||||
return self.x + y + 30
|
||||
|
||||
def __divmod__(self, y: int) -> int:
|
||||
return self.x + y + 40
|
||||
|
||||
def __pow__(self, y: int) -> int:
|
||||
return self.x + y + 50
|
||||
|
||||
def test_generic() -> None:
|
||||
a: Any = C()
|
||||
assert a + 3 == 8
|
||||
assert a - 3 == 2
|
||||
assert a * 5 == 25
|
||||
assert a % 2 == 1
|
||||
assert a << 4 == 80
|
||||
assert a >> 0 == 5
|
||||
assert a >> 1 == 2
|
||||
assert a & 1 == 1
|
||||
assert a | 3 == 7
|
||||
assert a ^ 3 == 6
|
||||
assert a @ 3 == 18
|
||||
assert a / 2 == 27
|
||||
assert a // 2 == 37
|
||||
assert divmod(a, 2) == 47
|
||||
assert a ** 2 == 57
|
||||
|
||||
def test_native() -> None:
|
||||
c = C()
|
||||
assert c + 3 == 8
|
||||
assert c - 3 == 2
|
||||
assert divmod(c, 3) == 48
|
||||
assert c ** 3 == 58
|
||||
|
||||
def test_error() -> None:
|
||||
a: Any = C()
|
||||
try:
|
||||
a + 'x'
|
||||
except TypeError as e:
|
||||
assert str(e) == "unsupported operand type(s) for +: 'C' and 'str'"
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
a - 'x'
|
||||
except TypeError as e:
|
||||
assert str(e) == "unsupported operand type(s) for -: 'C' and 'str'"
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
a ** 'x'
|
||||
except TypeError as e:
|
||||
assert str(e) == "unsupported operand type(s) for **: 'C' and 'str'"
|
||||
else:
|
||||
assert False
|
||||
|
||||
[case testDundersBinaryReverse]
|
||||
from typing import Any
|
||||
|
||||
class C:
|
||||
def __init__(self) -> None:
|
||||
self.x = 5
|
||||
|
||||
def __add__(self, y: int) -> int:
|
||||
return self.x + y
|
||||
|
||||
def __radd__(self, y: int) -> int:
|
||||
return self.x + y + 1
|
||||
|
||||
def __sub__(self, y: int) -> int:
|
||||
return self.x - y
|
||||
|
||||
def __rsub__(self, y: int) -> int:
|
||||
return self.x - y - 1
|
||||
|
||||
def __pow__(self, y: int) -> int:
|
||||
return self.x**y
|
||||
|
||||
def __rpow__(self, y: int) -> int:
|
||||
return self.x**y + 1
|
||||
|
||||
def test_generic() -> None:
|
||||
a: Any = C()
|
||||
assert a + 3 == 8
|
||||
assert 4 + a == 10
|
||||
assert a - 3 == 2
|
||||
assert 4 - a == 0
|
||||
assert a**3 == 125
|
||||
assert 4**a == 626
|
||||
|
||||
def test_native() -> None:
|
||||
c = C()
|
||||
assert c + 3 == 8
|
||||
assert 4 + c == 10
|
||||
assert c - 3 == 2
|
||||
assert 4 - c == 0
|
||||
assert c**3 == 125
|
||||
assert 4**c == 626
|
||||
|
||||
def test_errors() -> None:
|
||||
a: Any = C()
|
||||
try:
|
||||
a + 'x'
|
||||
except TypeError as e:
|
||||
assert str(e) == "unsupported operand type(s) for +: 'C' and 'str'"
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
a - 'x'
|
||||
except TypeError as e:
|
||||
assert str(e) == "unsupported operand type(s) for -: 'C' and 'str'"
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
'x' + a
|
||||
except TypeError as e:
|
||||
assert str(e) in ('can only concatenate str (not "C") to str',
|
||||
'must be str, not C')
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
'x' ** a
|
||||
except TypeError as e:
|
||||
assert str(e) == "unsupported operand type(s) for ** or pow(): 'str' and 'C'"
|
||||
else:
|
||||
assert False
|
||||
|
||||
|
||||
class F:
|
||||
def __add__(self, x: int) -> int:
|
||||
return 5
|
||||
|
||||
def __pow__(self, x: int) -> int:
|
||||
return -5
|
||||
|
||||
class G:
|
||||
def __add__(self, x: int) -> int:
|
||||
return 33
|
||||
|
||||
def __pow__(self, x: int) -> int:
|
||||
return -33
|
||||
|
||||
def __radd__(self, x: F) -> int:
|
||||
return 6
|
||||
|
||||
def __rpow__(self, x: F) -> int:
|
||||
return -6
|
||||
|
||||
def test_type_mismatch_fall_back_to_reverse() -> None:
|
||||
assert F() + G() == 6
|
||||
assert F()**G() == -6
|
||||
|
||||
[case testDundersBinaryNotImplemented]
|
||||
from typing import Any, Union
|
||||
from testutil import assertRaises
|
||||
|
||||
class C:
|
||||
def __init__(self, v: int) -> None:
|
||||
self.v = v
|
||||
|
||||
def __add__(self, y: int) -> Union[int, Any]:
|
||||
if y == 1:
|
||||
return self.v
|
||||
return NotImplemented
|
||||
|
||||
def test_any_add() -> None:
|
||||
a: Any = C(4)
|
||||
assert a + 1 == 4
|
||||
try:
|
||||
a + 2
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
class D:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
def __add__(self, e: E) -> Union[int, Any]:
|
||||
if e.x == 1:
|
||||
return 2
|
||||
return NotImplemented
|
||||
|
||||
class E:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
def __radd__(self, d: D) -> Union[int, Any]:
|
||||
if d.x == 3:
|
||||
return 4
|
||||
return NotImplemented
|
||||
|
||||
def test_any_radd() -> None:
|
||||
d1: Any = D(1)
|
||||
d3: Any = D(3)
|
||||
e1: Any = E(1)
|
||||
e3: Any = E(3)
|
||||
assert d1 + e1 == 2
|
||||
assert d3 + e1 == 2
|
||||
assert d3 + e3 == 4
|
||||
|
||||
class F:
|
||||
def __init__(self, v):
|
||||
self.v = v
|
||||
|
||||
def __add__(self, x):
|
||||
if isinstance(x, int):
|
||||
return self.v + x
|
||||
return NotImplemented
|
||||
|
||||
class G:
|
||||
def __radd__(self, x):
|
||||
if isinstance(x, F):
|
||||
return x.v + 1
|
||||
if isinstance(x, str):
|
||||
return 'a'
|
||||
return NotImplemented
|
||||
|
||||
def test_unannotated_add() -> None:
|
||||
o = F(4)
|
||||
assert o + 5 == 9
|
||||
with assertRaises(TypeError, "unsupported operand type(s) for +: 'F' and 'str'"):
|
||||
o + 'x'
|
||||
|
||||
def test_unannotated_add_and_radd_1() -> None:
|
||||
o = F(4)
|
||||
assert o + G() == 5
|
||||
|
||||
def test_unannotated_radd() -> None:
|
||||
assert 'x' + G() == 'a'
|
||||
with assertRaises(TypeError, "unsupported operand type(s) for +: 'int' and 'G'"):
|
||||
1 + G()
|
||||
|
||||
class H:
|
||||
def __add__(self, x):
|
||||
if isinstance(x, int):
|
||||
return x + 1
|
||||
return NotImplemented
|
||||
|
||||
def __radd__(self, x):
|
||||
if isinstance(x, str):
|
||||
return 22
|
||||
return NotImplemented
|
||||
|
||||
def test_unannotated_add_and_radd_2() -> None:
|
||||
h = H()
|
||||
assert h + 5 == 6
|
||||
assert 'x' + h == 22
|
||||
with assertRaises(TypeError, "unsupported operand type(s) for +: 'int' and 'H'"):
|
||||
1 + h
|
||||
|
||||
# TODO: Inheritance
|
||||
|
||||
[case testDifferentReverseDunders]
|
||||
class C:
|
||||
# __radd__ and __rsub__ are tested elsewhere
|
||||
|
||||
def __rmul__(self, x):
|
||||
return 1
|
||||
|
||||
def __rtruediv__(self, x):
|
||||
return 2
|
||||
|
||||
def __rmod__(self, x):
|
||||
return 3
|
||||
|
||||
def __rfloordiv__(self, x):
|
||||
return 4
|
||||
|
||||
def __rlshift__(self, x):
|
||||
return 5
|
||||
|
||||
def __rrshift__(self, x):
|
||||
return 6
|
||||
|
||||
def __rand__(self, x):
|
||||
return 7
|
||||
|
||||
def __ror__(self, x):
|
||||
return 8
|
||||
|
||||
def __rxor__(self, x):
|
||||
return 9
|
||||
|
||||
def __rmatmul__(self, x):
|
||||
return 10
|
||||
|
||||
def test_reverse_dunders() -> None:
|
||||
x = 0
|
||||
c = C()
|
||||
assert x * c == 1
|
||||
assert x / c == 2
|
||||
assert x % c == 3
|
||||
assert x // c == 4
|
||||
assert x << c == 5
|
||||
assert x >> c == 6
|
||||
assert x & c == 7
|
||||
assert x | c == 8
|
||||
assert x ^ c == 9
|
||||
assert x @ c == 10
|
||||
|
||||
[case testDundersInplace]
|
||||
from typing import Any
|
||||
from testutil import assertRaises
|
||||
|
||||
class C:
|
||||
def __init__(self) -> None:
|
||||
self.x = 5
|
||||
|
||||
def __iadd__(self, y: int) -> C:
|
||||
self.x += y
|
||||
return self
|
||||
|
||||
def __isub__(self, y: int) -> C:
|
||||
self.x -= y
|
||||
return self
|
||||
|
||||
def __imul__(self, y: int) -> C:
|
||||
self.x *= y
|
||||
return self
|
||||
|
||||
def __imod__(self, y: int) -> C:
|
||||
self.x %= y
|
||||
return self
|
||||
|
||||
def __itruediv__(self, y: int) -> C:
|
||||
self.x += y + 10
|
||||
return self
|
||||
|
||||
def __ifloordiv__(self, y: int) -> C:
|
||||
self.x += y + 20
|
||||
return self
|
||||
|
||||
def __ilshift__(self, y: int) -> C:
|
||||
self.x <<= y
|
||||
return self
|
||||
|
||||
def __irshift__(self, y: int) -> C:
|
||||
self.x >>= y
|
||||
return self
|
||||
|
||||
def __iand__(self, y: int) -> C:
|
||||
self.x &= y
|
||||
return self
|
||||
|
||||
def __ior__(self, y: int) -> C:
|
||||
self.x |= y
|
||||
return self
|
||||
|
||||
def __ixor__(self, y: int) -> C:
|
||||
self.x ^= y
|
||||
return self
|
||||
|
||||
def __imatmul__(self, y: int) -> C:
|
||||
self.x += y + 5
|
||||
return self
|
||||
|
||||
def __ipow__(self, y: int, __mod_throwaway: None = None) -> C:
|
||||
self.x **= y
|
||||
return self
|
||||
|
||||
def test_generic_1() -> None:
|
||||
c: Any = C()
|
||||
c += 3
|
||||
assert c.x == 8
|
||||
c -= 5
|
||||
assert c.x == 3
|
||||
c *= 3
|
||||
assert c.x == 9
|
||||
c %= 4
|
||||
assert c.x == 1
|
||||
c /= 5
|
||||
assert c.x == 16
|
||||
c //= 4
|
||||
assert c.x == 40
|
||||
c **= 2
|
||||
assert c.x == 1600
|
||||
|
||||
def test_generic_2() -> None:
|
||||
c: Any = C()
|
||||
c <<= 4
|
||||
assert c.x == 80
|
||||
c >>= 3
|
||||
assert c.x == 10
|
||||
c &= 3
|
||||
assert c.x == 2
|
||||
c |= 6
|
||||
assert c.x == 6
|
||||
c ^= 12
|
||||
assert c.x == 10
|
||||
c @= 3
|
||||
assert c.x == 18
|
||||
|
||||
def test_native() -> None:
|
||||
c = C()
|
||||
c += 3
|
||||
assert c.x == 8
|
||||
c -= 5
|
||||
assert c.x == 3
|
||||
c *= 3
|
||||
assert c.x == 9
|
||||
c **= 2
|
||||
assert c.x == 81
|
||||
|
||||
def test_error() -> None:
|
||||
c: Any = C()
|
||||
with assertRaises(TypeError, "int object expected; got str"):
|
||||
c += 'x'
|
||||
|
||||
class BadInplaceAdd:
|
||||
def __init__(self):
|
||||
self.x = 0
|
||||
|
||||
def __iadd__(self, x):
|
||||
self.x += x
|
||||
|
||||
def test_in_place_operator_returns_none() -> None:
|
||||
o = BadInplaceAdd()
|
||||
with assertRaises(TypeError, "native.BadInplaceAdd object expected; got None"):
|
||||
o += 5
|
||||
|
||||
[case testDunderMinMax]
|
||||
class SomeItem:
|
||||
def __init__(self, val: int) -> None:
|
||||
self.val = val
|
||||
|
||||
def __lt__(self, x: 'SomeItem') -> bool:
|
||||
return self.val < x.val
|
||||
|
||||
def __gt__(self, x: 'SomeItem') -> bool:
|
||||
return self.val > x.val
|
||||
|
||||
class AnotherItem:
|
||||
def __init__(self, val: str) -> None:
|
||||
self.val = val
|
||||
|
||||
def __lt__(self, x: 'AnotherItem') -> bool:
|
||||
return True
|
||||
|
||||
def __gt__(self, x: 'AnotherItem') -> bool:
|
||||
return True
|
||||
|
||||
def test_dunder_min() -> None:
|
||||
x = SomeItem(5)
|
||||
y = SomeItem(10)
|
||||
z = SomeItem(15)
|
||||
assert min(x, y).val == 5
|
||||
assert min(y, z).val == 10
|
||||
assert max(x, y).val == 10
|
||||
assert max(y, z).val == 15
|
||||
x2 = AnotherItem('xxx')
|
||||
y2 = AnotherItem('yyy')
|
||||
z2 = AnotherItem('zzz')
|
||||
assert min(x2, y2).val == 'yyy'
|
||||
assert min(y2, x2).val == 'xxx'
|
||||
assert max(x2, y2).val == 'yyy'
|
||||
assert max(y2, x2).val == 'xxx'
|
||||
assert min(y2, z2).val == 'zzz'
|
||||
assert max(x2, z2).val == 'zzz'
|
||||
|
||||
|
||||
[case testDundersPowerSpecial]
|
||||
import sys
|
||||
from typing import Any, Optional
|
||||
from testutil import assertRaises
|
||||
|
||||
class Forward:
|
||||
def __pow__(self, exp: int, mod: Optional[int] = None) -> int:
|
||||
if mod is None:
|
||||
return 2**exp
|
||||
else:
|
||||
return 2**exp % mod
|
||||
|
||||
class ForwardModRequired:
|
||||
def __pow__(self, exp: int, mod: int) -> int:
|
||||
return 2**exp % mod
|
||||
|
||||
class ForwardNotImplemented:
|
||||
def __pow__(self, exp: int, mod: Optional[object] = None) -> Any:
|
||||
return NotImplemented
|
||||
|
||||
class Reverse:
|
||||
def __rpow__(self, exp: int) -> int:
|
||||
return 2**exp + 1
|
||||
|
||||
class Both:
|
||||
def __pow__(self, exp: int, mod: Optional[int] = None) -> int:
|
||||
if mod is None:
|
||||
return 2**exp
|
||||
else:
|
||||
return 2**exp % mod
|
||||
|
||||
def __rpow__(self, exp: int) -> int:
|
||||
return 2**exp + 1
|
||||
|
||||
class Child(ForwardNotImplemented):
|
||||
def __rpow__(self, exp: object) -> int:
|
||||
return 50
|
||||
|
||||
class Inplace:
|
||||
value = 2
|
||||
|
||||
def __ipow__(self, exp: int, mod: Optional[int] = None) -> "Inplace":
|
||||
self.value **= exp - (mod or 0)
|
||||
return self
|
||||
|
||||
def test_native() -> None:
|
||||
f = Forward()
|
||||
assert f**3 == 8
|
||||
assert pow(f, 3) == 8
|
||||
assert pow(f, 3, 3) == 2
|
||||
assert pow(ForwardModRequired(), 3, 3) == 2
|
||||
b = Both()
|
||||
assert b**3 == 8
|
||||
assert 3**b == 9
|
||||
assert pow(b, 3) == 8
|
||||
assert pow(b, 3, 3) == 2
|
||||
i = Inplace()
|
||||
i **= 2
|
||||
assert i.value == 4
|
||||
|
||||
def test_errors() -> None:
|
||||
if sys.version_info[0] >= 3 and sys.version_info[1] >= 10:
|
||||
op = "** or pow()"
|
||||
else:
|
||||
op = "pow()"
|
||||
|
||||
f = Forward()
|
||||
with assertRaises(TypeError, f"unsupported operand type(s) for {op}: 'Forward', 'int', 'str'"):
|
||||
pow(f, 3, "x") # type: ignore
|
||||
with assertRaises(TypeError, "unsupported operand type(s) for **: 'Forward' and 'str'"):
|
||||
f**"x" # type: ignore
|
||||
r = Reverse()
|
||||
with assertRaises(TypeError, "unsupported operand type(s) for ** or pow(): 'str' and 'Reverse'"):
|
||||
"x"**r # type: ignore
|
||||
with assertRaises(TypeError, f"unsupported operand type(s) for {op}: 'int', 'Reverse', 'int'"):
|
||||
# Ternary pow() does not fallback to __rpow__ if LHS's __pow__ returns NotImplemented.
|
||||
pow(3, r, 3) # type: ignore
|
||||
with assertRaises(TypeError, f"unsupported operand type(s) for {op}: 'ForwardNotImplemented', 'Child', 'int'"):
|
||||
# Ternary pow() does not try RHS's __rpow__ first when it's a subclass and redefines
|
||||
# __rpow__ unlike other ops.
|
||||
pow(ForwardNotImplemented(), Child(), 3) # type: ignore
|
||||
with assertRaises(TypeError, "unsupported operand type(s) for ** or pow(): 'ForwardModRequired' and 'int'"):
|
||||
ForwardModRequired()**3 # type: ignore
|
||||
@@ -0,0 +1,448 @@
|
||||
# Test cases for exceptions (compile and run)
|
||||
|
||||
[case testException]
|
||||
from typing import List
|
||||
def f(x: List[int]) -> None:
|
||||
g(x)
|
||||
|
||||
def g(x: List[int]) -> bool:
|
||||
x[5] = 2
|
||||
return True
|
||||
|
||||
def r1() -> None:
|
||||
q1()
|
||||
|
||||
def q1() -> None:
|
||||
raise Exception("test")
|
||||
|
||||
def r2() -> None:
|
||||
q2()
|
||||
|
||||
def q2() -> None:
|
||||
raise Exception
|
||||
|
||||
class A:
|
||||
def __init__(self) -> None:
|
||||
raise Exception
|
||||
|
||||
def hey() -> None:
|
||||
A()
|
||||
|
||||
[file driver.py]
|
||||
from native import f, r1, r2, hey
|
||||
import traceback
|
||||
try:
|
||||
f([])
|
||||
except IndexError:
|
||||
traceback.print_exc()
|
||||
try:
|
||||
r1()
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
try:
|
||||
r2()
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
try:
|
||||
hey()
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
[out]
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 4, in <module>
|
||||
f([])
|
||||
File "native.py", line 3, in f
|
||||
g(x)
|
||||
File "native.py", line 6, in g
|
||||
x[5] = 2
|
||||
IndexError: list assignment index out of range
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 8, in <module>
|
||||
r1()
|
||||
File "native.py", line 10, in r1
|
||||
q1()
|
||||
File "native.py", line 13, in q1
|
||||
raise Exception("test")
|
||||
Exception: test
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 12, in <module>
|
||||
r2()
|
||||
File "native.py", line 16, in r2
|
||||
q2()
|
||||
File "native.py", line 19, in q2
|
||||
raise Exception
|
||||
Exception
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 16, in <module>
|
||||
hey()
|
||||
File "native.py", line 26, in hey
|
||||
A()
|
||||
File "native.py", line 23, in __init__
|
||||
raise Exception
|
||||
Exception
|
||||
|
||||
[case testTryExcept]
|
||||
from typing import Any, Iterator
|
||||
import wrapsys
|
||||
def g(b: bool) -> None:
|
||||
try:
|
||||
if b:
|
||||
x = [0]
|
||||
x[1]
|
||||
else:
|
||||
raise Exception('hi')
|
||||
except:
|
||||
print("caught!")
|
||||
|
||||
def r(x: int) -> None:
|
||||
if x == 0:
|
||||
[0][1]
|
||||
elif x == 1:
|
||||
raise Exception('hi')
|
||||
elif x == 2:
|
||||
{1: 1}[0]
|
||||
elif x == 3:
|
||||
a = object() # type: Any
|
||||
a.lol
|
||||
|
||||
def f(b: bool) -> None:
|
||||
try:
|
||||
r(int(b))
|
||||
except AttributeError:
|
||||
print('no')
|
||||
except:
|
||||
print(str(wrapsys.exc_info()[1]))
|
||||
print(str(wrapsys.exc_info()[1]))
|
||||
|
||||
def h() -> None:
|
||||
while True:
|
||||
try:
|
||||
raise Exception('gonna break')
|
||||
except:
|
||||
print(str(wrapsys.exc_info()[1]))
|
||||
break
|
||||
print(str(wrapsys.exc_info()[1]))
|
||||
|
||||
def i() -> None:
|
||||
try:
|
||||
r(0)
|
||||
except:
|
||||
print(type(wrapsys.exc_info()[1]))
|
||||
raise
|
||||
|
||||
def j(n: int) -> None:
|
||||
try:
|
||||
r(n)
|
||||
except (IndexError, KeyError):
|
||||
print("lookup!")
|
||||
except AttributeError as e:
|
||||
print("attr! --", e)
|
||||
|
||||
def k() -> None:
|
||||
try:
|
||||
r(1)
|
||||
except:
|
||||
r(0)
|
||||
|
||||
def l() -> None:
|
||||
try:
|
||||
r(0)
|
||||
except IndexError:
|
||||
try:
|
||||
r(2)
|
||||
except KeyError as e:
|
||||
print("key! --", e)
|
||||
|
||||
def m(x: object) -> int:
|
||||
try:
|
||||
st = id(x)
|
||||
except Exception:
|
||||
return -1
|
||||
return st + 1
|
||||
|
||||
def iter_exception() -> Iterator[str]:
|
||||
try:
|
||||
r(0)
|
||||
except KeyError as e:
|
||||
yield 'lol'
|
||||
|
||||
[file wrapsys.py]
|
||||
# This is a gross hack around some limitations of the test system/mypyc.
|
||||
from typing import Any
|
||||
import sys
|
||||
def exc_info() -> Any:
|
||||
return sys.exc_info() # type: ignore
|
||||
|
||||
[file driver.py]
|
||||
import sys, traceback
|
||||
from native import g, f, h, i, j, k, l, m, iter_exception
|
||||
from testutil import assertRaises
|
||||
print("== i ==")
|
||||
try:
|
||||
i()
|
||||
except:
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
|
||||
print("== k ==")
|
||||
try:
|
||||
k()
|
||||
except:
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
|
||||
print("== g ==")
|
||||
g(True)
|
||||
g(False)
|
||||
|
||||
print("== f ==")
|
||||
f(True)
|
||||
f(False)
|
||||
|
||||
print("== h ==")
|
||||
h()
|
||||
|
||||
print("== j ==")
|
||||
j(0)
|
||||
j(2)
|
||||
j(3)
|
||||
try:
|
||||
j(1)
|
||||
except:
|
||||
print("out!")
|
||||
|
||||
print("== l ==")
|
||||
l()
|
||||
|
||||
m('lol')
|
||||
|
||||
with assertRaises(IndexError):
|
||||
list(iter_exception())
|
||||
|
||||
[out]
|
||||
== i ==
|
||||
<class 'IndexError'>
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 6, in <module>
|
||||
i()
|
||||
File "native.py", line 44, in i
|
||||
r(0)
|
||||
File "native.py", line 15, in r
|
||||
[0][1]
|
||||
IndexError: list index out of range
|
||||
== k ==
|
||||
Traceback (most recent call last):
|
||||
File "native.py", line 59, in k
|
||||
r(1)
|
||||
File "native.py", line 17, in r
|
||||
raise Exception('hi')
|
||||
Exception: hi
|
||||
|
||||
During handling of the above exception, another exception occurred:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 12, in <module>
|
||||
k()
|
||||
File "native.py", line 61, in k
|
||||
r(0)
|
||||
File "native.py", line 15, in r
|
||||
[0][1]
|
||||
IndexError: list index out of range
|
||||
== g ==
|
||||
caught!
|
||||
caught!
|
||||
== f ==
|
||||
hi
|
||||
None
|
||||
list index out of range
|
||||
None
|
||||
== h ==
|
||||
gonna break
|
||||
None
|
||||
== j ==
|
||||
lookup!
|
||||
lookup!
|
||||
attr! -- 'object' object has no attribute 'lol'
|
||||
out!
|
||||
== l ==
|
||||
key! -- 0
|
||||
|
||||
[case testTryFinally]
|
||||
from typing import Any
|
||||
import wrapsys
|
||||
|
||||
def a(b1: bool, b2: int) -> None:
|
||||
try:
|
||||
if b1:
|
||||
raise Exception('hi')
|
||||
finally:
|
||||
print('finally:', str(wrapsys.exc_info()[1]))
|
||||
if b2 == 2:
|
||||
return
|
||||
if b2 == 1:
|
||||
raise Exception('again!')
|
||||
|
||||
def b(b1: int, b2: int) -> str:
|
||||
try:
|
||||
if b1 == 1:
|
||||
raise Exception('hi')
|
||||
elif b1 == 2:
|
||||
[0][1]
|
||||
elif b1 == 3:
|
||||
return 'try'
|
||||
except IndexError:
|
||||
print('except')
|
||||
finally:
|
||||
print('finally:', str(wrapsys.exc_info()[1]))
|
||||
if b2 == 2:
|
||||
return 'finally'
|
||||
if b2 == 1:
|
||||
raise Exception('again!')
|
||||
return 'outer'
|
||||
|
||||
def c() -> str:
|
||||
try:
|
||||
try:
|
||||
return 'wee'
|
||||
finally:
|
||||
print("out a")
|
||||
finally:
|
||||
print("out b")
|
||||
|
||||
|
||||
[file wrapsys.py]
|
||||
# This is a gross hack around some limitations of the test system/mypyc.
|
||||
from typing import Any
|
||||
import sys
|
||||
def exc_info() -> Any:
|
||||
return sys.exc_info() # type: ignore
|
||||
|
||||
[file driver.py]
|
||||
import traceback
|
||||
import sys
|
||||
from native import a, b, c
|
||||
|
||||
def run(f):
|
||||
try:
|
||||
x = f()
|
||||
if x:
|
||||
print("returned:", x)
|
||||
except Exception as e:
|
||||
print("caught:", type(e).__name__ + ": " + str(e))
|
||||
|
||||
print("== a ==")
|
||||
for i in range(3):
|
||||
for b1 in [False, True]:
|
||||
run(lambda: a(b1, i))
|
||||
|
||||
print("== b ==")
|
||||
for i in range(4):
|
||||
for j in range(3):
|
||||
run(lambda: b(i, j))
|
||||
|
||||
print("== b ==")
|
||||
print(c())
|
||||
|
||||
[out]
|
||||
== a ==
|
||||
finally: None
|
||||
finally: hi
|
||||
caught: Exception: hi
|
||||
finally: None
|
||||
caught: Exception: again!
|
||||
finally: hi
|
||||
caught: Exception: again!
|
||||
finally: None
|
||||
finally: hi
|
||||
== b ==
|
||||
finally: None
|
||||
returned: outer
|
||||
finally: None
|
||||
caught: Exception: again!
|
||||
finally: None
|
||||
returned: finally
|
||||
finally: hi
|
||||
caught: Exception: hi
|
||||
finally: hi
|
||||
caught: Exception: again!
|
||||
finally: hi
|
||||
returned: finally
|
||||
except
|
||||
finally: None
|
||||
returned: outer
|
||||
except
|
||||
finally: None
|
||||
caught: Exception: again!
|
||||
except
|
||||
finally: None
|
||||
returned: finally
|
||||
finally: None
|
||||
returned: try
|
||||
finally: None
|
||||
caught: Exception: again!
|
||||
finally: None
|
||||
returned: finally
|
||||
== b ==
|
||||
out a
|
||||
out b
|
||||
wee
|
||||
|
||||
[case testCustomException]
|
||||
from typing import List
|
||||
|
||||
class ListOutOfBounds(IndexError):
|
||||
pass
|
||||
|
||||
class UserListWarning(UserWarning):
|
||||
pass
|
||||
|
||||
def f(l: List[int], k: int) -> int:
|
||||
try:
|
||||
return l[k]
|
||||
except IndexError:
|
||||
raise ListOutOfBounds("Ruh-roh from f!")
|
||||
|
||||
def g(l: List[int], k: int) -> int:
|
||||
try:
|
||||
return f([1,2,3], 3)
|
||||
except ListOutOfBounds:
|
||||
raise ListOutOfBounds("Ruh-roh from g!")
|
||||
|
||||
def k(l: List[int], k: int) -> int:
|
||||
try:
|
||||
return g([1,2,3], 3)
|
||||
except IndexError:
|
||||
raise UserListWarning("Ruh-roh from k!")
|
||||
|
||||
def h() -> int:
|
||||
try:
|
||||
return k([1,2,3], 3)
|
||||
except UserWarning:
|
||||
return -1
|
||||
|
||||
[file driver.py]
|
||||
from native import h
|
||||
assert h() == -1
|
||||
|
||||
[case testExceptionAtModuleTopLevel]
|
||||
from typing import Any
|
||||
|
||||
def f(x: int) -> None: pass
|
||||
|
||||
y: Any = ''
|
||||
f(y)
|
||||
|
||||
[file driver.py]
|
||||
import traceback
|
||||
try:
|
||||
import native
|
||||
except TypeError:
|
||||
traceback.print_exc()
|
||||
else:
|
||||
assert False
|
||||
|
||||
[out]
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 3, in <module>
|
||||
import native
|
||||
File "native.py", line 6, in <module>
|
||||
f(y)
|
||||
TypeError: int object expected; got str
|
||||
@@ -0,0 +1,516 @@
|
||||
# Test cases for floats (compile and run)
|
||||
|
||||
[case testFloatOps]
|
||||
from __future__ import annotations
|
||||
from typing import Any, cast
|
||||
from typing_extensions import Final
|
||||
from testutil import assertRaises, float_vals, FLOAT_MAGIC
|
||||
import math
|
||||
|
||||
def test_arithmetic() -> None:
|
||||
zero = float(0.0)
|
||||
one = zero + 1.0
|
||||
x = one + one / 2.0
|
||||
assert x == 1.5
|
||||
assert x - one == 0.5
|
||||
assert x * x == 2.25
|
||||
assert x / 2.0 == 0.75
|
||||
assert x * (-0.5) == -0.75
|
||||
assert -x == -1.5
|
||||
for x in float_vals:
|
||||
assert repr(-x) == repr(getattr(x, "__neg__")())
|
||||
|
||||
for y in float_vals:
|
||||
assert repr(x + y) == repr(getattr(x, "__add__")(y))
|
||||
assert repr(x - y) == repr(getattr(x, "__sub__")(y))
|
||||
assert repr(x * y) == repr(getattr(x, "__mul__")(y))
|
||||
if y != 0:
|
||||
assert repr(x / y) == repr(getattr(x, "__truediv__")(y))
|
||||
|
||||
def test_mod() -> None:
|
||||
zero = float(0.0)
|
||||
one = zero + 1.0
|
||||
x = one + one / 2.0
|
||||
assert x % 0.4 == 0.29999999999999993
|
||||
assert (-x) % 0.4 == 0.10000000000000009
|
||||
assert x % -0.4 == -0.10000000000000009
|
||||
assert (-x) % -0.4 == -0.29999999999999993
|
||||
for x in float_vals:
|
||||
for y in float_vals:
|
||||
if y != 0:
|
||||
assert repr(x % y) == repr(getattr(x, "__mod__")(y))
|
||||
|
||||
def test_floor_div() -> None:
|
||||
for x in float_vals:
|
||||
for y in float_vals:
|
||||
if y != 0:
|
||||
assert repr(x // y) == repr(getattr(x, "__floordiv__")(y))
|
||||
else:
|
||||
with assertRaises(ZeroDivisionError, "float floor division by zero"):
|
||||
x // y
|
||||
|
||||
def test_mixed_arithmetic() -> None:
|
||||
zf = float(0.0)
|
||||
zn = int()
|
||||
assert (zf + 5.5) + (zn + 1) == 6.5
|
||||
assert (zn - 2) - (zf - 5.5) == 3.5
|
||||
x = zf + 3.4
|
||||
x += zn + 2
|
||||
assert x == 5.4
|
||||
|
||||
def test_arithmetic_errors() -> None:
|
||||
zero = float(0.0)
|
||||
one = zero + 1.0
|
||||
with assertRaises(ZeroDivisionError, "float division by zero"):
|
||||
print(one / zero)
|
||||
with assertRaises(ZeroDivisionError, "float modulo"):
|
||||
print(one % zero)
|
||||
|
||||
def test_comparisons() -> None:
|
||||
zero = float(0.0)
|
||||
one = zero + 1.0
|
||||
x = one + one / 2.0
|
||||
assert x < (1.51 + zero)
|
||||
assert not (x < (1.49 + zero))
|
||||
assert x > (1.49 + zero)
|
||||
assert not (x > (1.51 + zero))
|
||||
assert x <= (1.5 + zero)
|
||||
assert not (x <= (1.49 + zero))
|
||||
assert x >= (1.5 + zero)
|
||||
assert not (x >= (1.51 + zero))
|
||||
for x in float_vals:
|
||||
for y in float_vals:
|
||||
assert (x <= y) == getattr(x, "__le__")(y)
|
||||
assert (x < y) == getattr(x, "__lt__")(y)
|
||||
assert (x >= y) == getattr(x, "__ge__")(y)
|
||||
assert (x > y) == getattr(x, "__gt__")(y)
|
||||
assert (x == y) == getattr(x, "__eq__")(y)
|
||||
assert (x != y) == getattr(x, "__ne__")(y)
|
||||
|
||||
def test_mixed_comparisons() -> None:
|
||||
zf = float(0.0)
|
||||
zn = int()
|
||||
if (zf + 1.0) == (zn + 1):
|
||||
assert True
|
||||
else:
|
||||
assert False
|
||||
if (zf + 1.1) == (zn + 1):
|
||||
assert False
|
||||
else:
|
||||
assert True
|
||||
assert (zf + 1.1) != (zn + 1)
|
||||
assert (zf + 1.1) > (zn + 1)
|
||||
assert not (zf + 0.9) > (zn + 1)
|
||||
assert (zn + 1) < (zf + 1.1)
|
||||
|
||||
def test_boxing_and_unboxing() -> None:
|
||||
x = 1.5
|
||||
boxed: Any = x
|
||||
assert repr(boxed) == "1.5"
|
||||
assert type(boxed) is float
|
||||
y: float = boxed
|
||||
assert y == x
|
||||
boxed_int: Any = 5
|
||||
assert [type(boxed_int)] == [int] # Avoid mypy type narrowing
|
||||
z: float = boxed_int
|
||||
assert z == 5.0
|
||||
for xx in float_vals:
|
||||
bb: Any = xx
|
||||
yy: float = bb
|
||||
assert repr(xx) == repr(bb)
|
||||
assert repr(xx) == repr(yy)
|
||||
for b in True, False:
|
||||
boxed_bool: Any = b
|
||||
assert type(boxed_bool) is bool
|
||||
zz: float = boxed_bool
|
||||
assert zz == int(b)
|
||||
|
||||
def test_unboxing_failure() -> None:
|
||||
boxed: Any = '1.5'
|
||||
with assertRaises(TypeError):
|
||||
x: float = boxed
|
||||
|
||||
def identity(x: float) -> float:
|
||||
return x
|
||||
|
||||
def test_coerce_from_int_literal() -> None:
|
||||
assert identity(34) == 34.0
|
||||
assert identity(-1) == -1.0
|
||||
|
||||
def test_coerce_from_short_tagged_int() -> None:
|
||||
n = int() - 17
|
||||
assert identity(n) == -17.0
|
||||
for i in range(-300, 300):
|
||||
assert identity(i) == float(i)
|
||||
|
||||
def test_coerce_from_long_tagged_int() -> None:
|
||||
n = int() + 2**100
|
||||
x = identity(n)
|
||||
assert repr(x) == '1.2676506002282294e+30'
|
||||
n = int() - 2**100
|
||||
y = identity(n)
|
||||
assert repr(y) == '-1.2676506002282294e+30'
|
||||
|
||||
def test_coerce_from_very_long_tagged_int() -> None:
|
||||
n = int() + 10**1000
|
||||
with assertRaises(OverflowError, "int too large to convert to float"):
|
||||
identity(n)
|
||||
with assertRaises(OverflowError, "int too large to convert to float"):
|
||||
identity(int(n))
|
||||
n = int() - 10**1000
|
||||
with assertRaises(OverflowError, "int too large to convert to float"):
|
||||
identity(n)
|
||||
with assertRaises(OverflowError, "int too large to convert to float"):
|
||||
identity(int(n))
|
||||
|
||||
def test_explicit_conversion_from_int() -> None:
|
||||
float_any: Any = float
|
||||
a = [0, 1, 2, 3, -1, -2, 13257, -928745]
|
||||
for n in range(1, 100):
|
||||
for delta in -1, 0, 1, 2342345:
|
||||
a.append(2**n + delta)
|
||||
a.append(-2**n + delta)
|
||||
for x in a:
|
||||
assert repr(float(x)) == repr(float_any(x))
|
||||
|
||||
def test_explicit_conversion_to_int() -> None:
|
||||
int_any: Any = int
|
||||
for x in float_vals:
|
||||
if math.isinf(x):
|
||||
with assertRaises(OverflowError, "cannot convert float infinity to integer"):
|
||||
int(x)
|
||||
elif math.isnan(x):
|
||||
with assertRaises(ValueError, "cannot convert float NaN to integer"):
|
||||
int(x)
|
||||
else:
|
||||
assert repr(int(x)) == repr(int_any(x))
|
||||
|
||||
# Test some edge cases
|
||||
assert 2**30 == int(2.0**30 + int())
|
||||
assert 2**30 - 1 == int(1073741823.9999999 + int()) # math.nextafter(2.0**30, 0))
|
||||
assert -2**30 - 1 == int(-2.0**30 - 1 + int())
|
||||
assert -2**30 == int(-1073741824.9999998 + int()) # math.nextafter(-2.0**30 - 1, 0)
|
||||
assert 2**62 == int(2.0**62 + int())
|
||||
assert 2**62 == int(2.0**62 - 1 + int())
|
||||
assert -2**62 == int(-2.0**62 + int())
|
||||
assert -2**62 == int(-2.0**62 - 1 + int())
|
||||
|
||||
def str_to_float(x: str) -> float:
|
||||
return float(x)
|
||||
|
||||
def test_str_to_float() -> None:
|
||||
assert str_to_float("1") == 1.0
|
||||
assert str_to_float("1.234567") == 1.234567
|
||||
assert str_to_float("44324") == 44324.0
|
||||
assert str_to_float("23.4") == 23.4
|
||||
assert str_to_float("-43.44e-4") == -43.44e-4
|
||||
assert str_to_float("-43.44e-4") == -43.44e-4
|
||||
assert math.isinf(str_to_float("inf"))
|
||||
assert math.isinf(str_to_float("-inf"))
|
||||
assert str_to_float("inf") > 0.0
|
||||
assert str_to_float("-inf") < 0.0
|
||||
assert math.isnan(str_to_float("nan"))
|
||||
assert math.isnan(str_to_float("NaN"))
|
||||
assert repr(str_to_float("-0.0")) == "-0.0"
|
||||
|
||||
def test_abs() -> None:
|
||||
assert abs(0.0) == 0.0
|
||||
assert abs(-1.234567) == 1.234567
|
||||
assert abs(44324.732) == 44324.732
|
||||
assert abs(-23.4) == 23.4
|
||||
assert abs(-43.44e-4) == 43.44e-4
|
||||
abs_any: Any = abs
|
||||
for x in float_vals:
|
||||
assert repr(abs(x)) == repr(abs_any(x))
|
||||
|
||||
def test_float_min_max() -> None:
|
||||
for x in float_vals:
|
||||
for y in float_vals:
|
||||
min_any: Any = min
|
||||
assert repr(min(x, y)) == repr(min_any(x, y))
|
||||
max_any: Any = max
|
||||
assert repr(max(x, y)) == repr(max_any(x, y))
|
||||
|
||||
def default(x: float = 2) -> float:
|
||||
return x + 1
|
||||
|
||||
def test_float_default_value() -> None:
|
||||
assert default(1.2) == 2.2
|
||||
for i in range(-200, 200):
|
||||
assert default(float(i)) == i + 1
|
||||
assert default() == 3.0
|
||||
|
||||
def test_float_default_value_wrapper() -> None:
|
||||
f: Any = default
|
||||
assert f(1.2) == 2.2
|
||||
for i in range(-200, 200):
|
||||
assert f(float(i)) == i + 1
|
||||
assert f() == 3.0
|
||||
|
||||
class C:
|
||||
def __init__(self, x: float) -> None:
|
||||
self.x = x
|
||||
|
||||
def test_float_attr() -> None:
|
||||
for i in range(-200, 200):
|
||||
f = float(i)
|
||||
c = C(f)
|
||||
assert c.x == f
|
||||
a: Any = c
|
||||
assert a.x == f
|
||||
c.x = FLOAT_MAGIC
|
||||
assert c.x == FLOAT_MAGIC
|
||||
assert a.x == FLOAT_MAGIC
|
||||
a.x = 1.0
|
||||
assert a.x == 1.0
|
||||
a.x = FLOAT_MAGIC
|
||||
assert a.x == FLOAT_MAGIC
|
||||
|
||||
class D:
|
||||
def __init__(self, x: float) -> None:
|
||||
if x:
|
||||
self.x = x
|
||||
|
||||
def test_float_attr_maybe_undefned() -> None:
|
||||
for i in range(-200, 200):
|
||||
if i == 0:
|
||||
d = D(0.0)
|
||||
with assertRaises(AttributeError):
|
||||
d.x
|
||||
a: Any = d
|
||||
with assertRaises(AttributeError):
|
||||
a.x
|
||||
d.x = FLOAT_MAGIC
|
||||
assert d.x == FLOAT_MAGIC
|
||||
assert a.x == FLOAT_MAGIC
|
||||
d.x = 0.0
|
||||
assert d.x == 0.0
|
||||
assert a.x == 0.0
|
||||
a.x = FLOAT_MAGIC
|
||||
assert a.x == FLOAT_MAGIC
|
||||
d = D(0.0)
|
||||
a = cast(Any, d)
|
||||
a.x = FLOAT_MAGIC
|
||||
assert d.x == FLOAT_MAGIC
|
||||
else:
|
||||
f = float(i)
|
||||
d = D(f)
|
||||
assert d.x == f
|
||||
a2: Any = d
|
||||
assert a2.x == f
|
||||
|
||||
def f(x: float) -> float:
|
||||
return x + 1
|
||||
|
||||
def test_return_values() -> None:
|
||||
a: Any = f
|
||||
for i in range(-200, 200):
|
||||
x = float(i)
|
||||
assert f(x) == x + 1
|
||||
assert a(x) == x + 1
|
||||
for x in float_vals:
|
||||
if not math.isnan(x):
|
||||
assert f(x) == x + 1
|
||||
else:
|
||||
assert math.isnan(f(x))
|
||||
|
||||
def exc() -> float:
|
||||
raise IndexError('x')
|
||||
|
||||
def test_exception() -> None:
|
||||
with assertRaises(IndexError):
|
||||
exc()
|
||||
a: Any = exc
|
||||
with assertRaises(IndexError):
|
||||
a()
|
||||
|
||||
def test_undefined_local_var() -> None:
|
||||
if not int():
|
||||
x = -113.0
|
||||
assert x == -113.0
|
||||
if int():
|
||||
y = -113.0
|
||||
with assertRaises(UnboundLocalError, 'local variable "y" referenced before assignment'):
|
||||
print(y)
|
||||
if not int():
|
||||
x2 = -1.0
|
||||
assert x2 == -1.0
|
||||
if int():
|
||||
y2 = -1.0
|
||||
with assertRaises(UnboundLocalError, 'local variable "y2" referenced before assignment'):
|
||||
print(y2)
|
||||
|
||||
def test_tuples() -> None:
|
||||
t1: tuple[float, float] = (1.5, 2.5)
|
||||
assert t1 == tuple([1.5, 2.5])
|
||||
n = int() + 5
|
||||
t2: tuple[float, float, float, float] = (n, 1.5, -7, -113)
|
||||
assert t2 == tuple([5.0, 1.5, -7.0, -113.0])
|
||||
|
||||
[case testFloatGlueMethodsAndInheritance]
|
||||
from typing import Any
|
||||
from typing_extensions import Final
|
||||
|
||||
from mypy_extensions import trait
|
||||
|
||||
from testutil import assertRaises
|
||||
|
||||
MAGIC: Final = -113.0
|
||||
|
||||
class Base:
|
||||
def foo(self) -> float:
|
||||
return 5.0
|
||||
|
||||
def bar(self, x: float = 2.0) -> float:
|
||||
return x + 1
|
||||
|
||||
def hoho(self, x: float) -> float:
|
||||
return x - 1
|
||||
|
||||
class Derived(Base):
|
||||
def foo(self, x: float = 5.0) -> float:
|
||||
return x + 10
|
||||
|
||||
def bar(self, x: float = 3, y: float = 20) -> float:
|
||||
return x + y + 2
|
||||
|
||||
def hoho(self, x: float = 7) -> float:
|
||||
return x - 2
|
||||
|
||||
def test_derived_adds_bitmap() -> None:
|
||||
b: Base = Derived()
|
||||
assert b.foo() == 15
|
||||
|
||||
def test_derived_adds_another_default_arg() -> None:
|
||||
b: Base = Derived()
|
||||
assert b.bar() == 25
|
||||
assert b.bar(1) == 23
|
||||
assert b.bar(MAGIC) == MAGIC + 22
|
||||
|
||||
def test_derived_switches_arg_to_have_default() -> None:
|
||||
b: Base = Derived()
|
||||
assert b.hoho(5) == 3
|
||||
assert b.hoho(MAGIC) == MAGIC - 2
|
||||
|
||||
@trait
|
||||
class T:
|
||||
@property
|
||||
def x(self) -> float: ...
|
||||
@property
|
||||
def y(self) -> float: ...
|
||||
|
||||
class C(T):
|
||||
x: float = 1.0
|
||||
y: float = 4
|
||||
|
||||
def test_read_only_property_in_trait_implemented_as_attribute() -> None:
|
||||
c = C()
|
||||
c.x = 5.5
|
||||
assert c.x == 5.5
|
||||
c.x = MAGIC
|
||||
assert c.x == MAGIC
|
||||
assert c.y == 4
|
||||
c.y = 6.5
|
||||
assert c.y == 6.5
|
||||
t: T = C()
|
||||
assert t.y == 4
|
||||
t = c
|
||||
assert t.x == MAGIC
|
||||
c.x = 55.5
|
||||
assert t.x == 55.5
|
||||
assert t.y == 6.5
|
||||
a: Any = c
|
||||
assert a.x == 55.5
|
||||
assert a.y == 6.5
|
||||
a.x = 7.0
|
||||
a.y = 8.0
|
||||
assert a.x == 7
|
||||
assert a.y == 8
|
||||
|
||||
class D(T):
|
||||
xx: float
|
||||
|
||||
@property
|
||||
def x(self) -> float:
|
||||
return self.xx
|
||||
|
||||
@property
|
||||
def y(self) -> float:
|
||||
raise TypeError
|
||||
|
||||
def test_read_only_property_in_trait_implemented_as_property() -> None:
|
||||
d = D()
|
||||
d.xx = 5.0
|
||||
assert d.x == 5
|
||||
d.xx = MAGIC
|
||||
assert d.x == MAGIC
|
||||
with assertRaises(TypeError):
|
||||
d.y
|
||||
t: T = d
|
||||
assert t.x == MAGIC
|
||||
d.xx = 6.0
|
||||
assert t.x == 6
|
||||
with assertRaises(TypeError):
|
||||
t.y
|
||||
|
||||
@trait
|
||||
class T2:
|
||||
x: float
|
||||
y: float
|
||||
|
||||
class C2(T2):
|
||||
pass
|
||||
|
||||
def test_inherit_trait_attribute() -> None:
|
||||
c = C2()
|
||||
c.x = 5.0
|
||||
assert c.x == 5
|
||||
c.x = MAGIC
|
||||
assert c.x == MAGIC
|
||||
with assertRaises(AttributeError):
|
||||
c.y
|
||||
c.y = 6.0
|
||||
assert c.y == 6.0
|
||||
t: T2 = C2()
|
||||
with assertRaises(AttributeError):
|
||||
t.y
|
||||
t = c
|
||||
assert t.x == MAGIC
|
||||
c.x = 55.0
|
||||
assert t.x == 55
|
||||
assert t.y == 6
|
||||
a: Any = c
|
||||
assert a.x == 55
|
||||
assert a.y == 6
|
||||
a.x = 7.0
|
||||
a.y = 8.0
|
||||
assert a.x == 7
|
||||
assert a.y == 8
|
||||
|
||||
class D2(T2):
|
||||
x: float
|
||||
y: float = 4
|
||||
|
||||
def test_implement_trait_attribute() -> None:
|
||||
d = D2()
|
||||
d.x = 5.0
|
||||
assert d.x == 5
|
||||
d.x = MAGIC
|
||||
assert d.x == MAGIC
|
||||
assert d.y == 4
|
||||
d.y = 6.0
|
||||
assert d.y == 6
|
||||
t: T2 = D2()
|
||||
assert t.y == 4
|
||||
t = d
|
||||
assert t.x == MAGIC
|
||||
d.x = 55.0
|
||||
assert t.x == 55
|
||||
assert t.y == 6
|
||||
a: Any = d
|
||||
assert a.x == 55
|
||||
assert a.y == 6
|
||||
a.x = 7.0
|
||||
a.y = 8.0
|
||||
assert a.x == 7
|
||||
assert a.y == 8
|
||||
1258
venv/lib/python3.12/site-packages/mypyc/test-data/run-functions.test
Normal file
1258
venv/lib/python3.12/site-packages/mypyc/test-data/run-functions.test
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,681 @@
|
||||
# Test cases for generators and yield (compile and run)
|
||||
|
||||
[case testYield]
|
||||
from typing import Generator, Iterable, Union, Tuple, Dict
|
||||
|
||||
def yield_three_times() -> Iterable[int]:
|
||||
yield 1
|
||||
yield 2
|
||||
yield 3
|
||||
|
||||
def yield_twice_and_return() -> Generator[int, None, int]:
|
||||
yield 1
|
||||
yield 2
|
||||
return 4
|
||||
|
||||
def yield_while_loop() -> Generator[int, None, int]:
|
||||
i = 0
|
||||
while i < 5:
|
||||
if i == 3:
|
||||
return i
|
||||
yield i
|
||||
i += 1
|
||||
return -1
|
||||
|
||||
def yield_for_loop() -> Iterable[int]:
|
||||
l = [i for i in range(3)]
|
||||
for i in l:
|
||||
yield i
|
||||
|
||||
d = {k: None for k in range(3)}
|
||||
for k in d:
|
||||
yield k
|
||||
|
||||
for i in range(3):
|
||||
yield i
|
||||
|
||||
for i in range(three()):
|
||||
yield i
|
||||
|
||||
def yield_with_except() -> Generator[int, None, None]:
|
||||
yield 10
|
||||
try:
|
||||
return
|
||||
except:
|
||||
print('Caught exception inside generator function')
|
||||
|
||||
def complex_yield(a: int, b: str, c: float) -> Generator[Union[str, int], None, float]:
|
||||
x = 2
|
||||
while x < a:
|
||||
if x % 2 == 0:
|
||||
dummy_var = 1
|
||||
yield str(x) + ' ' + b
|
||||
dummy_var = 1
|
||||
else:
|
||||
dummy_var = 1
|
||||
yield x
|
||||
dummy_var = 1
|
||||
x += 1
|
||||
return c
|
||||
|
||||
def yield_with_default(x: bool = False) -> Iterable[int]:
|
||||
if x:
|
||||
yield 0
|
||||
|
||||
def yield_dict_methods(d1: Dict[int, int],
|
||||
d2: Dict[int, int],
|
||||
d3: Dict[int, int]) -> Iterable[int]:
|
||||
for k in d1.keys():
|
||||
yield k
|
||||
for k, v in d2.items():
|
||||
yield k
|
||||
yield v
|
||||
for v in d3.values():
|
||||
yield v
|
||||
|
||||
def three() -> int:
|
||||
return 3
|
||||
|
||||
class A(object):
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
def generator(self) -> Iterable[int]:
|
||||
yield self.x
|
||||
|
||||
def return_tuple() -> Generator[int, None, Tuple[int, int]]:
|
||||
yield 0
|
||||
return 1, 2
|
||||
|
||||
[file driver.py]
|
||||
from native import (
|
||||
yield_three_times,
|
||||
yield_twice_and_return,
|
||||
yield_while_loop,
|
||||
yield_for_loop,
|
||||
yield_with_except,
|
||||
complex_yield,
|
||||
yield_with_default,
|
||||
A,
|
||||
return_tuple,
|
||||
yield_dict_methods,
|
||||
)
|
||||
from testutil import run_generator
|
||||
from collections import defaultdict
|
||||
|
||||
assert run_generator(yield_three_times()) == ((1, 2, 3), None)
|
||||
assert run_generator(yield_twice_and_return()) == ((1, 2), 4)
|
||||
assert run_generator(yield_while_loop()) == ((0, 1, 2), 3)
|
||||
assert run_generator(yield_for_loop()) == (tuple(4 * [i for i in range(3)]), None)
|
||||
assert run_generator(yield_with_except()) == ((10,), None)
|
||||
assert run_generator(complex_yield(5, 'foo', 1.0)) == (('2 foo', 3, '4 foo'), 1.0)
|
||||
assert run_generator(yield_with_default()) == ((), None)
|
||||
assert run_generator(A(0).generator()) == ((0,), None)
|
||||
assert run_generator(return_tuple()) == ((0,), (1, 2))
|
||||
assert run_generator(yield_dict_methods({}, {}, {})) == ((), None)
|
||||
assert run_generator(yield_dict_methods({1: 2}, {3: 4}, {5: 6})) == ((1, 3, 4, 6), None)
|
||||
dd = defaultdict(int, {0: 1})
|
||||
assert run_generator(yield_dict_methods(dd, dd, dd)) == ((0, 0, 1, 1), None)
|
||||
|
||||
for i in yield_twice_and_return():
|
||||
print(i)
|
||||
|
||||
for i in yield_while_loop():
|
||||
print(i)
|
||||
|
||||
[out]
|
||||
1
|
||||
2
|
||||
0
|
||||
1
|
||||
2
|
||||
|
||||
[case testYieldTryFinallyWith]
|
||||
from typing import Generator, Any
|
||||
|
||||
class Thing:
|
||||
def __init__(self, x: str) -> None:
|
||||
self.x = x
|
||||
def __enter__(self) -> str:
|
||||
print('enter!', self.x)
|
||||
if self.x == 'crash':
|
||||
raise Exception('ohno')
|
||||
return self.x
|
||||
def __exit__(self, x: Any, y: Any, z: Any) -> None:
|
||||
print('exit!', self.x, y)
|
||||
|
||||
def yield_try_finally() -> Generator[int, None, str]:
|
||||
try:
|
||||
yield 1
|
||||
yield 2
|
||||
return 'lol'
|
||||
except Exception:
|
||||
raise
|
||||
finally:
|
||||
print('goodbye!')
|
||||
|
||||
def yield_with(i: int) -> Generator[int, None, int]:
|
||||
with Thing('a') as x:
|
||||
yield 1
|
||||
print("yooo?", x)
|
||||
if i == 0:
|
||||
yield 2
|
||||
return 10
|
||||
elif i == 1:
|
||||
raise Exception('exception!')
|
||||
return -1
|
||||
|
||||
[file driver.py]
|
||||
from native import yield_try_finally, yield_with
|
||||
from testutil import run_generator
|
||||
|
||||
print(run_generator(yield_try_finally(), p=True))
|
||||
print(run_generator(yield_with(0), p=True))
|
||||
print(run_generator(yield_with(1), p=True))
|
||||
[out]
|
||||
1
|
||||
2
|
||||
goodbye!
|
||||
((1, 2), 'lol')
|
||||
enter! a
|
||||
1
|
||||
yooo? a
|
||||
2
|
||||
exit! a None
|
||||
((1, 2), 10)
|
||||
enter! a
|
||||
1
|
||||
yooo? a
|
||||
exit! a exception!
|
||||
((1,), 'exception!')
|
||||
|
||||
[case testYieldNested]
|
||||
from typing import Callable, Generator
|
||||
|
||||
def normal(a: int, b: float) -> Callable:
|
||||
def generator(x: int, y: str) -> Generator:
|
||||
yield a
|
||||
yield b
|
||||
yield x
|
||||
yield y
|
||||
return generator
|
||||
|
||||
def generator(a: int) -> Generator:
|
||||
def normal(x: int) -> int:
|
||||
return a + x
|
||||
for i in range(3):
|
||||
yield normal(i)
|
||||
|
||||
def triple() -> Callable:
|
||||
def generator() -> Generator:
|
||||
x = 0
|
||||
def inner() -> int:
|
||||
x += 1
|
||||
return x
|
||||
while x < 3:
|
||||
yield inner()
|
||||
return generator
|
||||
|
||||
def another_triple() -> Callable:
|
||||
def generator() -> Generator:
|
||||
x = 0
|
||||
def inner_generator() -> Generator:
|
||||
x += 1
|
||||
yield x
|
||||
yield next(inner_generator())
|
||||
return generator
|
||||
|
||||
def outer() -> Generator:
|
||||
def recursive(n: int) -> Generator:
|
||||
if n < 10:
|
||||
for i in range(n):
|
||||
yield i
|
||||
return
|
||||
for i in recursive(5):
|
||||
yield i
|
||||
return recursive(10)
|
||||
|
||||
[file driver.py]
|
||||
from native import normal, generator, triple, another_triple, outer
|
||||
from testutil import run_generator
|
||||
|
||||
assert run_generator(normal(1, 2.0)(3, '4.00')) == ((1, 2.0, 3, '4.00'), None)
|
||||
assert run_generator(generator(1)) == ((1, 2, 3), None)
|
||||
assert run_generator(triple()()) == ((1, 2, 3), None)
|
||||
assert run_generator(another_triple()()) == ((1,), None)
|
||||
assert run_generator(outer()) == ((0, 1, 2, 3, 4), None)
|
||||
|
||||
[case testYieldThrow]
|
||||
from typing import Generator, Iterable, Any
|
||||
from traceback import print_tb
|
||||
from contextlib import contextmanager
|
||||
import wrapsys
|
||||
|
||||
def generator() -> Iterable[int]:
|
||||
try:
|
||||
yield 1
|
||||
yield 2
|
||||
yield 3
|
||||
except Exception as e:
|
||||
print_tb(wrapsys.exc_info()[2])
|
||||
s = str(e)
|
||||
if s:
|
||||
print('caught exception with value ' + s)
|
||||
else:
|
||||
print('caught exception without value')
|
||||
return 0
|
||||
|
||||
def no_except() -> Iterable[int]:
|
||||
yield 1
|
||||
yield 2
|
||||
|
||||
def raise_something() -> Iterable[int]:
|
||||
yield 1
|
||||
yield 2
|
||||
raise Exception('failure')
|
||||
|
||||
def wrapper(x: Any) -> Any:
|
||||
return (yield from x)
|
||||
|
||||
def foo() -> Generator[int, None, None]:
|
||||
try:
|
||||
yield 1
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
finally:
|
||||
print('goodbye')
|
||||
|
||||
ctx_manager = contextmanager(foo)
|
||||
|
||||
[file wrapsys.py]
|
||||
# This is a gross hack around some limitations of the test system/mypyc.
|
||||
from typing import Any
|
||||
import sys
|
||||
def exc_info() -> Any:
|
||||
return sys.exc_info() # type: ignore
|
||||
|
||||
[file driver.py]
|
||||
import sys
|
||||
from typing import Generator, Tuple, TypeVar, Sequence
|
||||
from native import generator, ctx_manager, wrapper, no_except, raise_something
|
||||
|
||||
T = TypeVar('T')
|
||||
U = TypeVar('U')
|
||||
|
||||
def run_generator_and_throw(gen: Generator[T, None, U],
|
||||
num_times: int,
|
||||
value: object = None,
|
||||
traceback: object = None) -> Tuple[Sequence[T], U]:
|
||||
res = []
|
||||
try:
|
||||
for i in range(num_times):
|
||||
res.append(next(gen))
|
||||
if value is not None and traceback is not None:
|
||||
gen.throw(Exception, value, traceback)
|
||||
elif value is not None:
|
||||
gen.throw(Exception, value)
|
||||
else:
|
||||
gen.throw(Exception)
|
||||
except StopIteration as e:
|
||||
return (tuple(res), e.value)
|
||||
except Exception as e:
|
||||
return (tuple(res), str(e))
|
||||
|
||||
assert run_generator_and_throw(generator(), 0, 'hello') == ((), 'hello')
|
||||
assert run_generator_and_throw(generator(), 3) == ((1, 2, 3), 0)
|
||||
assert run_generator_and_throw(generator(), 2, 'some string') == ((1, 2), 0)
|
||||
try:
|
||||
raise Exception
|
||||
except Exception as e:
|
||||
tb = sys.exc_info()[2]
|
||||
assert run_generator_and_throw(generator(), 1, 'some other string', tb) == ((1,), 0)
|
||||
|
||||
assert run_generator_and_throw(wrapper(generator()), 0, 'hello') == ((), 'hello')
|
||||
assert run_generator_and_throw(wrapper(generator()), 3) == ((1, 2, 3), 0)
|
||||
assert run_generator_and_throw(wrapper(generator()), 2, 'some string') == ((1, 2), 0)
|
||||
# Make sure we aren't leaking exc_info
|
||||
assert sys.exc_info()[0] is None
|
||||
|
||||
assert run_generator_and_throw(wrapper([1, 2, 3]), 3, 'lol') == ((1, 2, 3), 'lol')
|
||||
assert run_generator_and_throw(wrapper(no_except()), 2, 'lol') == ((1, 2), 'lol')
|
||||
|
||||
assert run_generator_and_throw(wrapper(raise_something()), 3) == ((1, 2), 'failure')
|
||||
|
||||
with ctx_manager() as c:
|
||||
raise Exception('exception')
|
||||
|
||||
[out]
|
||||
File "native.py", line 10, in generator
|
||||
yield 3
|
||||
File "native.py", line 9, in generator
|
||||
yield 2
|
||||
File "native.py", line 8, in generator
|
||||
yield 1
|
||||
File "driver.py", line 31, in <module>
|
||||
raise Exception
|
||||
File "native.py", line 10, in generator
|
||||
yield 3
|
||||
File "native.py", line 30, in wrapper
|
||||
return (yield from x)
|
||||
File "native.py", line 9, in generator
|
||||
yield 2
|
||||
File "native.py", line 30, in wrapper
|
||||
return (yield from x)
|
||||
caught exception without value
|
||||
caught exception with value some string
|
||||
caught exception with value some other string
|
||||
caught exception without value
|
||||
caught exception with value some string
|
||||
exception
|
||||
goodbye
|
||||
|
||||
[case testYieldSend]
|
||||
from typing import Generator
|
||||
|
||||
def basic() -> Generator[int, int, int]:
|
||||
x = yield 1
|
||||
y = yield (x + 1)
|
||||
return y
|
||||
|
||||
def use_from() -> Generator[int, int, int]:
|
||||
return (yield from basic())
|
||||
|
||||
[file driver.py]
|
||||
from native import basic, use_from
|
||||
from testutil import run_generator
|
||||
|
||||
assert run_generator(basic(), [5, 50]) == ((1, 6), 50)
|
||||
assert run_generator(use_from(), [5, 50]) == ((1, 6), 50)
|
||||
|
||||
[case testYieldFrom]
|
||||
from typing import Generator, Iterator, List
|
||||
|
||||
def basic() -> Iterator[int]:
|
||||
yield from [1, 2, 3]
|
||||
|
||||
def call_next() -> int:
|
||||
x = [] # type: List[int]
|
||||
return next(iter(x))
|
||||
|
||||
def inner(b: bool) -> Generator[int, None, int]:
|
||||
if b:
|
||||
yield from [1, 2, 3]
|
||||
return 10
|
||||
|
||||
def with_return(b: bool) -> Generator[int, None, int]:
|
||||
x = yield from inner(b)
|
||||
for a in [1, 2]:
|
||||
pass
|
||||
return x
|
||||
|
||||
[file driver.py]
|
||||
from native import basic, call_next, with_return
|
||||
from testutil import run_generator, assertRaises
|
||||
|
||||
assert run_generator(basic()) == ((1, 2, 3), None)
|
||||
|
||||
with assertRaises(StopIteration):
|
||||
call_next()
|
||||
|
||||
assert run_generator(with_return(True)) == ((1, 2, 3), 10)
|
||||
assert run_generator(with_return(False)) == ((), 10)
|
||||
|
||||
[case testNextGenerator]
|
||||
from typing import Iterable
|
||||
|
||||
def f(x: int) -> int:
|
||||
print(x)
|
||||
return x
|
||||
|
||||
def call_next_loud(l: Iterable[int], val: int) -> int:
|
||||
return next(i for i in l if f(i) == val)
|
||||
|
||||
def call_next_default(l: Iterable[int], val: int) -> int:
|
||||
return next((i*2 for i in l if i == val), -1)
|
||||
|
||||
def call_next_default_list(l: Iterable[int], val: int) -> int:
|
||||
return next((i*2 for i in l if i == val), -1)
|
||||
[file driver.py]
|
||||
from native import call_next_loud, call_next_default, call_next_default_list
|
||||
from testutil import assertRaises
|
||||
|
||||
assert call_next_default([0, 1, 2], 0) == 0
|
||||
assert call_next_default([0, 1, 2], 1) == 2
|
||||
assert call_next_default([0, 1, 2], 2) == 4
|
||||
assert call_next_default([0, 1, 2], 3) == -1
|
||||
assert call_next_default([], 0) == -1
|
||||
assert call_next_default_list([0, 1, 2], 0) == 0
|
||||
assert call_next_default_list([0, 1, 2], 1) == 2
|
||||
assert call_next_default_list([0, 1, 2], 2) == 4
|
||||
assert call_next_default_list([0, 1, 2], 3) == -1
|
||||
assert call_next_default_list([], 0) == -1
|
||||
|
||||
assert call_next_loud([0, 1, 2], 0) == 0
|
||||
assert call_next_loud([0, 1, 2], 1) == 1
|
||||
assert call_next_loud([0, 1, 2], 2) == 2
|
||||
with assertRaises(StopIteration):
|
||||
call_next_loud([42], 3)
|
||||
with assertRaises(StopIteration):
|
||||
call_next_loud([], 3)
|
||||
|
||||
[out]
|
||||
0
|
||||
0
|
||||
1
|
||||
0
|
||||
1
|
||||
2
|
||||
42
|
||||
|
||||
[case testGeneratorSuper]
|
||||
from typing import Iterator, Callable, Any
|
||||
|
||||
class A():
|
||||
def testA(self) -> int:
|
||||
return 2
|
||||
|
||||
class B(A):
|
||||
def testB(self) -> Iterator[int]:
|
||||
x = super().testA()
|
||||
while True:
|
||||
yield x
|
||||
|
||||
def testAsserts():
|
||||
b = B()
|
||||
b_gen = b.testB()
|
||||
assert next(b_gen) == 2
|
||||
|
||||
[file driver.py]
|
||||
from native import testAsserts
|
||||
|
||||
testAsserts()
|
||||
|
||||
[case testNameClashIssues]
|
||||
class A:
|
||||
def foo(self) -> object:
|
||||
yield
|
||||
class B:
|
||||
def foo(self) -> object:
|
||||
yield
|
||||
|
||||
class C:
|
||||
def foo(self) -> None:
|
||||
def bar(self) -> None:
|
||||
pass
|
||||
|
||||
def C___foo() -> None: pass
|
||||
|
||||
class D:
|
||||
def foo(self) -> None:
|
||||
def bar(self) -> None:
|
||||
pass
|
||||
|
||||
class E:
|
||||
default: int
|
||||
switch: int
|
||||
|
||||
[file driver.py]
|
||||
# really I only care it builds
|
||||
|
||||
[case testCloseStopIterationRaised]
|
||||
def g() -> object:
|
||||
try:
|
||||
yield 1
|
||||
except GeneratorExit:
|
||||
raise
|
||||
|
||||
[file driver.py]
|
||||
from native import g
|
||||
|
||||
gen = g()
|
||||
next(gen)
|
||||
gen.close()
|
||||
|
||||
[case testCloseGeneratorExitRaised]
|
||||
def g() -> object:
|
||||
yield 1
|
||||
|
||||
[file driver.py]
|
||||
from native import g
|
||||
|
||||
gen = g()
|
||||
next(gen)
|
||||
gen.close()
|
||||
|
||||
[case testCloseGeneratorExitIgnored]
|
||||
def g() -> object:
|
||||
try:
|
||||
yield 1
|
||||
except GeneratorExit:
|
||||
pass
|
||||
|
||||
yield 2
|
||||
|
||||
[file driver.py]
|
||||
from native import g
|
||||
|
||||
gen = g()
|
||||
next(gen)
|
||||
try:
|
||||
gen.close()
|
||||
except RuntimeError as e:
|
||||
assert str(e) == 'generator ignored GeneratorExit'
|
||||
else:
|
||||
assert False
|
||||
|
||||
[case testCloseGeneratorRaisesAnotherException]
|
||||
def g() -> object:
|
||||
try:
|
||||
yield 1
|
||||
except GeneratorExit:
|
||||
raise RuntimeError("error")
|
||||
|
||||
[file driver.py]
|
||||
from native import g
|
||||
|
||||
gen = g()
|
||||
next(gen)
|
||||
try:
|
||||
gen.close()
|
||||
except RuntimeError as e:
|
||||
assert str(e) == 'error'
|
||||
else:
|
||||
assert False
|
||||
|
||||
[case testBorrowingInGeneratorNearYield]
|
||||
from typing import Iterator
|
||||
|
||||
class Foo:
|
||||
flag: bool
|
||||
|
||||
class C:
|
||||
foo: Foo
|
||||
|
||||
def genf(self) -> Iterator[None]:
|
||||
self.foo.flag = True
|
||||
yield
|
||||
self.foo.flag = False
|
||||
|
||||
[case testGeneratorEarlyReturnWithBorrows]
|
||||
from typing import Iterator
|
||||
class Bar:
|
||||
bar = 0
|
||||
class Foo:
|
||||
bar = Bar()
|
||||
def f(self) -> Iterator[int]:
|
||||
if self:
|
||||
self.bar.bar += 1
|
||||
return
|
||||
yield 0
|
||||
|
||||
[case testBorrowingInGeneratorInTupleAssignment]
|
||||
from typing import Iterator
|
||||
|
||||
class Foo:
|
||||
flag1: bool
|
||||
flag2: bool
|
||||
|
||||
class C:
|
||||
foo: Foo
|
||||
|
||||
def genf(self) -> Iterator[None]:
|
||||
self.foo.flag1, self.foo.flag2 = True, True
|
||||
yield
|
||||
self.foo.flag1, self.foo.flag2 = False, False
|
||||
|
||||
def test_generator() -> None:
|
||||
c = C()
|
||||
c.foo = Foo()
|
||||
gen = c.genf()
|
||||
next(gen)
|
||||
assert c.foo.flag1 == c.foo.flag2 == True
|
||||
assert list(gen) == []
|
||||
assert c.foo.flag1 == c.foo.flag2 == False
|
||||
|
||||
|
||||
[case testYieldInFinally]
|
||||
from typing import Generator
|
||||
|
||||
def finally_yield() -> Generator[str, None, str]:
|
||||
try:
|
||||
return 'test'
|
||||
finally:
|
||||
yield 'x'
|
||||
|
||||
|
||||
[file driver.py]
|
||||
from native import finally_yield
|
||||
from testutil import run_generator
|
||||
|
||||
yields, val = run_generator(finally_yield())
|
||||
assert yields == ('x',)
|
||||
assert val == 'test', val
|
||||
|
||||
[case testUnreachableComprehensionNoCrash]
|
||||
from typing import List
|
||||
|
||||
def list_comp() -> List[int]:
|
||||
if True:
|
||||
return [5]
|
||||
return [i for i in [5]]
|
||||
|
||||
[file driver.py]
|
||||
from native import list_comp
|
||||
assert list_comp() == [5]
|
||||
|
||||
[case testWithNative]
|
||||
class DummyContext:
|
||||
def __init__(self) -> None:
|
||||
self.x = 0
|
||||
|
||||
def __enter__(self) -> None:
|
||||
self.x += 1
|
||||
|
||||
def __exit__(self, exc_type, exc_value, exc_tb) -> None:
|
||||
self.x -= 1
|
||||
|
||||
def test_basic() -> None:
|
||||
context = DummyContext()
|
||||
with context:
|
||||
assert context.x == 1
|
||||
assert context.x == 0
|
||||
338
venv/lib/python3.12/site-packages/mypyc/test-data/run-i16.test
Normal file
338
venv/lib/python3.12/site-packages/mypyc/test-data/run-i16.test
Normal file
@@ -0,0 +1,338 @@
|
||||
[case testI16BasicOps]
|
||||
from typing import Any, Tuple
|
||||
|
||||
from mypy_extensions import i16, i32, i64
|
||||
|
||||
from testutil import assertRaises
|
||||
|
||||
def test_box_and_unbox() -> None:
|
||||
values = (list(range(-2**15, -2**15 + 100)) +
|
||||
list(range(-1000, 1000)) +
|
||||
list(range(2**15 - 100, 2**15)))
|
||||
for i in values:
|
||||
o: Any = i
|
||||
x: i16 = o
|
||||
o2: Any = x
|
||||
assert o == o2
|
||||
assert x == i
|
||||
with assertRaises(OverflowError, "int too large to convert to i16"):
|
||||
o = 2**15
|
||||
x2: i16 = o
|
||||
with assertRaises(OverflowError, "int too large to convert to i16"):
|
||||
o = -2**15 - 1
|
||||
x3: i16 = o
|
||||
|
||||
def div_by_7(x: i16) -> i16:
|
||||
return x // 7
|
||||
def div_by_neg_7(x: i16) -> i16:
|
||||
return x // -7
|
||||
|
||||
def div(x: i16, y: i16) -> i16:
|
||||
return x // y
|
||||
|
||||
def test_divide_by_constant() -> None:
|
||||
for i in range(-1000, 1000):
|
||||
assert div_by_7(i) == i // 7
|
||||
for i in range(-2**15, -2**15 + 1000):
|
||||
assert div_by_7(i) == i // 7
|
||||
for i in range(2**15 - 1000, 2**15):
|
||||
assert div_by_7(i) == i // 7
|
||||
|
||||
def test_divide_by_negative_constant() -> None:
|
||||
for i in range(-1000, 1000):
|
||||
assert div_by_neg_7(i) == i // -7
|
||||
for i in range(-2**15, -2**15 + 1000):
|
||||
assert div_by_neg_7(i) == i // -7
|
||||
for i in range(2**15 - 1000, 2**15):
|
||||
assert div_by_neg_7(i) == i // -7
|
||||
|
||||
def test_divide_by_variable() -> None:
|
||||
values = (list(range(-50, 50)) +
|
||||
list(range(-2**15, -2**15 + 10)) +
|
||||
list(range(2**15 - 10, 2**15)))
|
||||
for x in values:
|
||||
for y in values:
|
||||
if y != 0:
|
||||
if x // y == 2**15:
|
||||
with assertRaises(OverflowError, "integer division overflow"):
|
||||
div(x, y)
|
||||
else:
|
||||
assert div(x, y) == x // y
|
||||
else:
|
||||
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
|
||||
div(x, y)
|
||||
|
||||
def mod_by_7(x: i16) -> i16:
|
||||
return x % 7
|
||||
|
||||
def mod_by_neg_7(x: i16) -> i16:
|
||||
return x // -7
|
||||
|
||||
def mod(x: i16, y: i16) -> i16:
|
||||
return x % y
|
||||
|
||||
def test_mod_by_constant() -> None:
|
||||
for i in range(-1000, 1000):
|
||||
assert mod_by_7(i) == i % 7
|
||||
for i in range(-2**15, -2**15 + 1000):
|
||||
assert mod_by_7(i) == i % 7
|
||||
for i in range(2**15 - 1000, 2**15):
|
||||
assert mod_by_7(i) == i % 7
|
||||
|
||||
def test_mod_by_negative_constant() -> None:
|
||||
for i in range(-1000, 1000):
|
||||
assert mod_by_neg_7(i) == i // -7
|
||||
for i in range(-2**15, -2**15 + 1000):
|
||||
assert mod_by_neg_7(i) == i // -7
|
||||
for i in range(2**15 - 1000, 2**15):
|
||||
assert mod_by_neg_7(i) == i // -7
|
||||
|
||||
def test_mod_by_variable() -> None:
|
||||
values = (list(range(-50, 50)) +
|
||||
list(range(-2**15, -2**15 + 10)) +
|
||||
list(range(2**15 - 10, 2**15)))
|
||||
for x in values:
|
||||
for y in values:
|
||||
if y != 0:
|
||||
assert mod(x, y) == x % y
|
||||
else:
|
||||
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
|
||||
mod(x, y)
|
||||
|
||||
def test_simple_arithmetic_ops() -> None:
|
||||
zero: i16 = int()
|
||||
one: i16 = zero + 1
|
||||
two: i16 = one + 1
|
||||
neg_one: i16 = -one
|
||||
assert one + one == 2
|
||||
assert one + two == 3
|
||||
assert one + neg_one == 0
|
||||
assert one - one == 0
|
||||
assert one - two == -1
|
||||
assert one * one == 1
|
||||
assert one * two == 2
|
||||
assert two * two == 4
|
||||
assert two * neg_one == -2
|
||||
assert neg_one * one == -1
|
||||
assert neg_one * neg_one == 1
|
||||
assert two * 0 == 0
|
||||
assert 0 * two == 0
|
||||
assert -one == -1
|
||||
assert -two == -2
|
||||
assert -neg_one == 1
|
||||
assert -zero == 0
|
||||
|
||||
def test_bitwise_ops() -> None:
|
||||
x: i16 = 13855 + int()
|
||||
y: i16 = 367 + int()
|
||||
z: i16 = -11091 + int()
|
||||
zero: i16 = int()
|
||||
one: i16 = zero + 1
|
||||
two: i16 = zero + 2
|
||||
neg_one: i16 = -one
|
||||
|
||||
assert x & y == 15
|
||||
assert x & z == 5133
|
||||
assert z & z == z
|
||||
assert x & zero == 0
|
||||
|
||||
assert x | y == 14207
|
||||
assert x | z == -2369
|
||||
assert z | z == z
|
||||
assert x | 0 == x
|
||||
|
||||
assert x ^ y == 14192
|
||||
assert x ^ z == -7502
|
||||
assert z ^ z == 0
|
||||
assert z ^ 0 == z
|
||||
|
||||
assert x << one == 27710
|
||||
assert x << two == -10116
|
||||
assert z << two == 21172
|
||||
assert z << 0 == z
|
||||
|
||||
assert x >> one == 6927
|
||||
assert x >> two == 3463
|
||||
assert z >> two == -2773
|
||||
assert z >> 0 == z
|
||||
|
||||
assert ~x == -13856
|
||||
assert ~z == 11090
|
||||
assert ~zero == -1
|
||||
assert ~neg_one == 0
|
||||
|
||||
def eq(x: i16, y: i16) -> bool:
|
||||
return x == y
|
||||
|
||||
def test_eq() -> None:
|
||||
assert eq(int(), int())
|
||||
assert eq(5 + int(), 5 + int())
|
||||
assert eq(-5 + int(), -5 + int())
|
||||
assert not eq(int(), 1 + int())
|
||||
assert not eq(5 + int(), 6 + int())
|
||||
assert not eq(-5 + int(), -6 + int())
|
||||
assert not eq(-5 + int(), 5 + int())
|
||||
|
||||
def test_comparisons() -> None:
|
||||
one: i16 = 1 + int()
|
||||
one2: i16 = 1 + int()
|
||||
two: i16 = 2 + int()
|
||||
assert one < two
|
||||
assert not (one < one2)
|
||||
assert not (two < one)
|
||||
assert two > one
|
||||
assert not (one > one2)
|
||||
assert not (one > two)
|
||||
assert one <= two
|
||||
assert one <= one2
|
||||
assert not (two <= one)
|
||||
assert two >= one
|
||||
assert one >= one2
|
||||
assert not (one >= two)
|
||||
assert one == one2
|
||||
assert not (one == two)
|
||||
assert one != two
|
||||
assert not (one != one2)
|
||||
|
||||
def test_mixed_comparisons() -> None:
|
||||
i16_3: i16 = int() + 3
|
||||
int_5 = int() + 5
|
||||
assert i16_3 < int_5
|
||||
assert int_5 > i16_3
|
||||
b = i16_3 > int_5
|
||||
assert not b
|
||||
|
||||
int_largest = int() + (1 << 15) - 1
|
||||
assert int_largest > i16_3
|
||||
int_smallest = int() - (1 << 15)
|
||||
assert i16_3 > int_smallest
|
||||
|
||||
int_too_big = int() + (1 << 15)
|
||||
int_too_small = int() - (1 << 15) - 1
|
||||
with assertRaises(OverflowError):
|
||||
assert i16_3 < int_too_big
|
||||
with assertRaises(OverflowError):
|
||||
assert int_too_big < i16_3
|
||||
with assertRaises(OverflowError):
|
||||
assert i16_3 > int_too_small
|
||||
with assertRaises(OverflowError):
|
||||
assert int_too_small < i16_3
|
||||
|
||||
def test_mixed_arithmetic_and_bitwise_ops() -> None:
|
||||
i16_3: i16 = int() + 3
|
||||
int_5 = int() + 5
|
||||
assert i16_3 + int_5 == 8
|
||||
assert int_5 - i16_3 == 2
|
||||
assert i16_3 << int_5 == 96
|
||||
assert int_5 << i16_3 == 40
|
||||
assert i16_3 ^ int_5 == 6
|
||||
assert int_5 | i16_3 == 7
|
||||
|
||||
int_largest = int() + (1 << 15) - 1
|
||||
assert int_largest - i16_3 == 32764
|
||||
int_smallest = int() - (1 << 15)
|
||||
assert int_smallest + i16_3 == -32765
|
||||
|
||||
int_too_big = int() + (1 << 15)
|
||||
int_too_small = int() - (1 << 15) - 1
|
||||
with assertRaises(OverflowError):
|
||||
assert i16_3 & int_too_big
|
||||
with assertRaises(OverflowError):
|
||||
assert int_too_small & i16_3
|
||||
|
||||
def test_coerce_to_and_from_int() -> None:
|
||||
for shift in range(0, 16):
|
||||
for sign in 1, -1:
|
||||
for delta in range(-5, 5):
|
||||
n = sign * (1 << shift) + delta
|
||||
if -(1 << 15) <= n < (1 << 15):
|
||||
x: i16 = n
|
||||
m: int = x
|
||||
assert m == n
|
||||
|
||||
def test_explicit_conversion_to_i16() -> None:
|
||||
x = i16(5)
|
||||
assert x == 5
|
||||
y = int() - 113
|
||||
x = i16(y)
|
||||
assert x == -113
|
||||
n64: i64 = 1733
|
||||
x = i16(n64)
|
||||
assert x == 1733
|
||||
n32: i32 = -1733
|
||||
x = i16(n32)
|
||||
assert x == -1733
|
||||
z = i16(x)
|
||||
assert z == -1733
|
||||
|
||||
def test_explicit_conversion_overflow() -> None:
|
||||
max_i16 = int() + 2**15 - 1
|
||||
x = i16(max_i16)
|
||||
assert x == 2**15 - 1
|
||||
assert int(x) == max_i16
|
||||
|
||||
min_i16 = int() - 2**15
|
||||
y = i16(min_i16)
|
||||
assert y == -2**15
|
||||
assert int(y) == min_i16
|
||||
|
||||
too_big = int() + 2**15
|
||||
with assertRaises(OverflowError):
|
||||
x = i16(too_big)
|
||||
|
||||
too_small = int() - 2**15 - 1
|
||||
with assertRaises(OverflowError):
|
||||
x = i16(too_small)
|
||||
|
||||
def test_i16_from_large_small_literal() -> None:
|
||||
x = i16(2**15 - 1)
|
||||
assert x == 2**15 - 1
|
||||
x = i16(-2**15)
|
||||
assert x == -2**15
|
||||
|
||||
def test_i16_truncate_from_i64() -> None:
|
||||
large = i64(2**32 + 65536 + 157 + int())
|
||||
x = i16(large)
|
||||
assert x == 157
|
||||
small = i64(-2**32 - 65536 - 157 + int())
|
||||
x = i16(small)
|
||||
assert x == -157
|
||||
large2 = i64(2**15 + int())
|
||||
x = i16(large2)
|
||||
assert x == -2**15
|
||||
small2 = i64(-2**15 - 1 - int())
|
||||
x = i16(small2)
|
||||
assert x == 2**15 - 1
|
||||
|
||||
def test_i16_truncate_from_i32() -> None:
|
||||
large = i32(2**16 + 2**30 + 5 + int())
|
||||
assert i16(large) == 5
|
||||
small = i32(-2**16 - 2**30 - 1 + int())
|
||||
assert i16(small) == -1
|
||||
|
||||
def from_float(x: float) -> i16:
|
||||
return i16(x)
|
||||
|
||||
def test_explicit_conversion_from_float() -> None:
|
||||
assert from_float(0.0) == 0
|
||||
assert from_float(1.456) == 1
|
||||
assert from_float(-1234.567) == -1234
|
||||
assert from_float(2**15 - 1) == 2**15 - 1
|
||||
assert from_float(-2**15) == -2**15
|
||||
# The error message could be better, but this is acceptable
|
||||
with assertRaises(OverflowError, "int too large to convert to i16"):
|
||||
assert from_float(float(2**15))
|
||||
with assertRaises(OverflowError, "int too large to convert to i16"):
|
||||
# One ulp below the lowest valid i64 value
|
||||
from_float(float(-2**15 - 1))
|
||||
|
||||
def test_tuple_i16() -> None:
|
||||
a: i16 = 1
|
||||
b: i16 = 2
|
||||
t = (a, b)
|
||||
a, b = t
|
||||
assert a == 1
|
||||
assert b == 2
|
||||
x: Any = t
|
||||
tt: Tuple[i16, i16] = x
|
||||
assert tt == (1, 2)
|
||||
336
venv/lib/python3.12/site-packages/mypyc/test-data/run-i32.test
Normal file
336
venv/lib/python3.12/site-packages/mypyc/test-data/run-i32.test
Normal file
@@ -0,0 +1,336 @@
|
||||
[case testI32BasicOps]
|
||||
from typing import Any, Tuple
|
||||
|
||||
from mypy_extensions import i16, i32, i64
|
||||
|
||||
from testutil import assertRaises
|
||||
|
||||
def test_box_and_unbox() -> None:
|
||||
values = (list(range(-2**31, -2**31 + 100)) +
|
||||
list(range(-1000, 1000)) +
|
||||
list(range(2**31 - 100, 2**31)))
|
||||
for i in values:
|
||||
o: Any = i
|
||||
x: i32 = o
|
||||
o2: Any = x
|
||||
assert o == o2
|
||||
assert x == i
|
||||
with assertRaises(OverflowError, "int too large to convert to i32"):
|
||||
o = 2**31
|
||||
x2: i32 = o
|
||||
with assertRaises(OverflowError, "int too large to convert to i32"):
|
||||
o = -2**32 - 1
|
||||
x3: i32 = o
|
||||
|
||||
def div_by_7(x: i32) -> i32:
|
||||
return x // 7
|
||||
def div_by_neg_7(x: i32) -> i32:
|
||||
return x // -7
|
||||
|
||||
def div(x: i32, y: i32) -> i32:
|
||||
return x // y
|
||||
|
||||
def test_divide_by_constant() -> None:
|
||||
for i in range(-1000, 1000):
|
||||
assert div_by_7(i) == i // 7
|
||||
for i in range(-2**31, -2**31 + 1000):
|
||||
assert div_by_7(i) == i // 7
|
||||
for i in range(2**31 - 1000, 2**31):
|
||||
assert div_by_7(i) == i // 7
|
||||
|
||||
def test_divide_by_negative_constant() -> None:
|
||||
for i in range(-1000, 1000):
|
||||
assert div_by_neg_7(i) == i // -7
|
||||
for i in range(-2**31, -2**31 + 1000):
|
||||
assert div_by_neg_7(i) == i // -7
|
||||
for i in range(2**31 - 1000, 2**31):
|
||||
assert div_by_neg_7(i) == i // -7
|
||||
|
||||
def test_divide_by_variable() -> None:
|
||||
values = (list(range(-50, 50)) +
|
||||
list(range(-2**31, -2**31 + 10)) +
|
||||
list(range(2**31 - 10, 2**31)))
|
||||
for x in values:
|
||||
for y in values:
|
||||
if y != 0:
|
||||
if x // y == 2**31:
|
||||
with assertRaises(OverflowError, "integer division overflow"):
|
||||
div(x, y)
|
||||
else:
|
||||
assert div(x, y) == x // y
|
||||
else:
|
||||
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
|
||||
div(x, y)
|
||||
|
||||
def mod_by_7(x: i32) -> i32:
|
||||
return x % 7
|
||||
|
||||
def mod_by_neg_7(x: i32) -> i32:
|
||||
return x // -7
|
||||
|
||||
def mod(x: i32, y: i32) -> i32:
|
||||
return x % y
|
||||
|
||||
def test_mod_by_constant() -> None:
|
||||
for i in range(-1000, 1000):
|
||||
assert mod_by_7(i) == i % 7
|
||||
for i in range(-2**31, -2**31 + 1000):
|
||||
assert mod_by_7(i) == i % 7
|
||||
for i in range(2**31 - 1000, 2**31):
|
||||
assert mod_by_7(i) == i % 7
|
||||
|
||||
def test_mod_by_negative_constant() -> None:
|
||||
for i in range(-1000, 1000):
|
||||
assert mod_by_neg_7(i) == i // -7
|
||||
for i in range(-2**31, -2**31 + 1000):
|
||||
assert mod_by_neg_7(i) == i // -7
|
||||
for i in range(2**31 - 1000, 2**31):
|
||||
assert mod_by_neg_7(i) == i // -7
|
||||
|
||||
def test_mod_by_variable() -> None:
|
||||
values = (list(range(-50, 50)) +
|
||||
list(range(-2**31, -2**31 + 10)) +
|
||||
list(range(2**31 - 10, 2**31)))
|
||||
for x in values:
|
||||
for y in values:
|
||||
if y != 0:
|
||||
assert mod(x, y) == x % y
|
||||
else:
|
||||
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
|
||||
mod(x, y)
|
||||
|
||||
def test_simple_arithmetic_ops() -> None:
|
||||
zero: i32 = int()
|
||||
one: i32 = zero + 1
|
||||
two: i32 = one + 1
|
||||
neg_one: i32 = -one
|
||||
assert one + one == 2
|
||||
assert one + two == 3
|
||||
assert one + neg_one == 0
|
||||
assert one - one == 0
|
||||
assert one - two == -1
|
||||
assert one * one == 1
|
||||
assert one * two == 2
|
||||
assert two * two == 4
|
||||
assert two * neg_one == -2
|
||||
assert neg_one * one == -1
|
||||
assert neg_one * neg_one == 1
|
||||
assert two * 0 == 0
|
||||
assert 0 * two == 0
|
||||
assert -one == -1
|
||||
assert -two == -2
|
||||
assert -neg_one == 1
|
||||
assert -zero == 0
|
||||
|
||||
def test_bitwise_ops() -> None:
|
||||
x: i32 = 1920687484 + int()
|
||||
y: i32 = 383354614 + int()
|
||||
z: i32 = -1879040563 + int()
|
||||
zero: i32 = int()
|
||||
one: i32 = zero + 1
|
||||
two: i32 = zero + 2
|
||||
neg_one: i32 = -one
|
||||
|
||||
assert x & y == 307823732
|
||||
assert x & z == 268442956
|
||||
assert z & z == z
|
||||
assert x & zero == 0
|
||||
|
||||
assert x | y == 1996218366
|
||||
assert x | z == -226796035
|
||||
assert z | z == z
|
||||
assert x | 0 == x
|
||||
|
||||
assert x ^ y == 1688394634
|
||||
assert x ^ z == -495238991
|
||||
assert z ^ z == 0
|
||||
assert z ^ 0 == z
|
||||
|
||||
assert x << one == -453592328
|
||||
assert x << two == -907184656
|
||||
assert z << two == 1073772340
|
||||
assert z << 0 == z
|
||||
|
||||
assert x >> one == 960343742
|
||||
assert x >> two == 480171871
|
||||
assert z >> two == -469760141
|
||||
assert z >> 0 == z
|
||||
|
||||
assert ~x == -1920687485
|
||||
assert ~z == 1879040562
|
||||
assert ~zero == -1
|
||||
assert ~neg_one == 0
|
||||
|
||||
def eq(x: i32, y: i32) -> bool:
|
||||
return x == y
|
||||
|
||||
def test_eq() -> None:
|
||||
assert eq(int(), int())
|
||||
assert eq(5 + int(), 5 + int())
|
||||
assert eq(-5 + int(), -5 + int())
|
||||
assert not eq(int(), 1 + int())
|
||||
assert not eq(5 + int(), 6 + int())
|
||||
assert not eq(-5 + int(), -6 + int())
|
||||
assert not eq(-5 + int(), 5 + int())
|
||||
|
||||
def test_comparisons() -> None:
|
||||
one: i32 = 1 + int()
|
||||
one2: i32 = 1 + int()
|
||||
two: i32 = 2 + int()
|
||||
assert one < two
|
||||
assert not (one < one2)
|
||||
assert not (two < one)
|
||||
assert two > one
|
||||
assert not (one > one2)
|
||||
assert not (one > two)
|
||||
assert one <= two
|
||||
assert one <= one2
|
||||
assert not (two <= one)
|
||||
assert two >= one
|
||||
assert one >= one2
|
||||
assert not (one >= two)
|
||||
assert one == one2
|
||||
assert not (one == two)
|
||||
assert one != two
|
||||
assert not (one != one2)
|
||||
|
||||
def test_mixed_comparisons() -> None:
|
||||
i32_3: i32 = int() + 3
|
||||
int_5 = int() + 5
|
||||
assert i32_3 < int_5
|
||||
assert int_5 > i32_3
|
||||
b = i32_3 > int_5
|
||||
assert not b
|
||||
|
||||
int_largest = int() + (1 << 31) - 1
|
||||
assert int_largest > i32_3
|
||||
int_smallest = int() - (1 << 31)
|
||||
assert i32_3 > int_smallest
|
||||
|
||||
int_too_big = int() + (1 << 31)
|
||||
int_too_small = int() - (1 << 31) - 1
|
||||
with assertRaises(OverflowError):
|
||||
assert i32_3 < int_too_big
|
||||
with assertRaises(OverflowError):
|
||||
assert int_too_big < i32_3
|
||||
with assertRaises(OverflowError):
|
||||
assert i32_3 > int_too_small
|
||||
with assertRaises(OverflowError):
|
||||
assert int_too_small < i32_3
|
||||
|
||||
def test_mixed_arithmetic_and_bitwise_ops() -> None:
|
||||
i32_3: i32 = int() + 3
|
||||
int_5 = int() + 5
|
||||
assert i32_3 + int_5 == 8
|
||||
assert int_5 - i32_3 == 2
|
||||
assert i32_3 << int_5 == 96
|
||||
assert int_5 << i32_3 == 40
|
||||
assert i32_3 ^ int_5 == 6
|
||||
assert int_5 | i32_3 == 7
|
||||
|
||||
int_largest = int() + (1 << 31) - 1
|
||||
assert int_largest - i32_3 == 2147483644
|
||||
int_smallest = int() - (1 << 31)
|
||||
assert int_smallest + i32_3 == -2147483645
|
||||
|
||||
int_too_big = int() + (1 << 31)
|
||||
int_too_small = int() - (1 << 31) - 1
|
||||
with assertRaises(OverflowError):
|
||||
assert i32_3 & int_too_big
|
||||
with assertRaises(OverflowError):
|
||||
assert int_too_small & i32_3
|
||||
|
||||
def test_coerce_to_and_from_int() -> None:
|
||||
for shift in range(0, 32):
|
||||
for sign in 1, -1:
|
||||
for delta in range(-5, 5):
|
||||
n = sign * (1 << shift) + delta
|
||||
if -(1 << 31) <= n < (1 << 31):
|
||||
x: i32 = n
|
||||
m: int = x
|
||||
assert m == n
|
||||
|
||||
def test_explicit_conversion_to_i32() -> None:
|
||||
x = i32(5)
|
||||
assert x == 5
|
||||
y = int() - 113
|
||||
x = i32(y)
|
||||
assert x == -113
|
||||
n64: i64 = 1733
|
||||
x = i32(n64)
|
||||
assert x == 1733
|
||||
n32: i32 = -1733
|
||||
x = i32(n32)
|
||||
assert x == -1733
|
||||
z = i32(x)
|
||||
assert z == -1733
|
||||
a: i16 = int() + 19764
|
||||
assert i32(a) == 19764
|
||||
a = int() - 1
|
||||
assert i32(a) == -1
|
||||
|
||||
def test_explicit_conversion_overflow() -> None:
|
||||
max_i32 = int() + 2**31 - 1
|
||||
x = i32(max_i32)
|
||||
assert x == 2**31 - 1
|
||||
assert int(x) == max_i32
|
||||
|
||||
min_i32 = int() - 2**31
|
||||
y = i32(min_i32)
|
||||
assert y == -2**31
|
||||
assert int(y) == min_i32
|
||||
|
||||
too_big = int() + 2**31
|
||||
with assertRaises(OverflowError):
|
||||
x = i32(too_big)
|
||||
|
||||
too_small = int() - 2**31 - 1
|
||||
with assertRaises(OverflowError):
|
||||
x = i32(too_small)
|
||||
|
||||
def test_i32_from_large_small_literal() -> None:
|
||||
x = i32(2**31 - 1)
|
||||
assert x == 2**31 - 1
|
||||
x = i32(-2**31)
|
||||
assert x == -2**31
|
||||
|
||||
def test_i32_truncate_from_i64() -> None:
|
||||
large = i64(2**32 + 157 + int())
|
||||
x = i32(large)
|
||||
assert x == 157
|
||||
small = i64(-2**32 - 157 + int())
|
||||
x = i32(small)
|
||||
assert x == -157
|
||||
large2 = i64(2**31 + int())
|
||||
x = i32(large2)
|
||||
assert x == -2**31
|
||||
small2 = i64(-2**31 - 1 - int())
|
||||
x = i32(small2)
|
||||
assert x == 2**31 - 1
|
||||
|
||||
def from_float(x: float) -> i32:
|
||||
return i32(x)
|
||||
|
||||
def test_explicit_conversion_from_float() -> None:
|
||||
assert from_float(0.0) == 0
|
||||
assert from_float(1.456) == 1
|
||||
assert from_float(-1234.567) == -1234
|
||||
assert from_float(2**31 - 1) == 2**31 - 1
|
||||
assert from_float(-2**31) == -2**31
|
||||
# The error message could be better, but this is acceptable
|
||||
with assertRaises(OverflowError, "int too large to convert to i32"):
|
||||
assert from_float(float(2**31))
|
||||
with assertRaises(OverflowError, "int too large to convert to i32"):
|
||||
# One ulp below the lowest valid i64 value
|
||||
from_float(float(-2**31 - 2048))
|
||||
|
||||
def test_tuple_i32() -> None:
|
||||
a: i32 = 1
|
||||
b: i32 = 2
|
||||
t = (a, b)
|
||||
a, b = t
|
||||
assert a == 1
|
||||
assert b == 2
|
||||
x: Any = t
|
||||
tt: Tuple[i32, i32] = x
|
||||
assert tt == (1, 2)
|
||||
1519
venv/lib/python3.12/site-packages/mypyc/test-data/run-i64.test
Normal file
1519
venv/lib/python3.12/site-packages/mypyc/test-data/run-i64.test
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,265 @@
|
||||
# Test cases for imports and related features (compile and run)
|
||||
|
||||
[case testImports]
|
||||
import testmodule
|
||||
import pkg2.mod
|
||||
import pkg2.mod2 as mm2
|
||||
|
||||
def f(x: int) -> int:
|
||||
return testmodule.factorial(5)
|
||||
|
||||
def g(x: int) -> int:
|
||||
from welp import foo
|
||||
return foo(x)
|
||||
|
||||
def test_import_basics() -> None:
|
||||
assert f(5) == 120
|
||||
assert g(5) == 5
|
||||
assert "pkg2.mod" not in globals(), "the root module should be in globals!"
|
||||
assert pkg2.mod.x == 1
|
||||
assert "mod2" not in globals(), "pkg2.mod2 is aliased to mm2!"
|
||||
assert mm2.y == 2
|
||||
|
||||
def test_import_submodule_within_function() -> None:
|
||||
import pkg.mod
|
||||
assert pkg.x == 1
|
||||
assert pkg.mod.y == 2
|
||||
assert "pkg.mod" not in globals(), "the root module should be in globals!"
|
||||
|
||||
def test_import_as_submodule_within_function() -> None:
|
||||
import pkg.mod as mm
|
||||
assert mm.y == 2
|
||||
assert "pkg.mod" not in globals(), "the root module should be in globals!"
|
||||
|
||||
# TODO: Don't add local imports to globals()
|
||||
#
|
||||
# def test_local_import_not_in_globals() -> None:
|
||||
# import nob
|
||||
# assert 'nob' not in globals()
|
||||
|
||||
def test_import_module_without_stub_in_function() -> None:
|
||||
# 'psutil' must not have a stub in typeshed for this test case
|
||||
import psutil # type: ignore
|
||||
# TODO: We shouldn't add local imports to globals()
|
||||
# assert 'psutil' not in globals()
|
||||
assert isinstance(psutil.__name__, str)
|
||||
|
||||
def test_import_as_module_without_stub_in_function() -> None:
|
||||
# 'psutil' must not have a stub in typeshed for this test case
|
||||
import psutil as pp # type: ignore
|
||||
assert 'psutil' not in globals()
|
||||
# TODO: We shouldn't add local imports to globals()
|
||||
# assert 'pp' not in globals()
|
||||
assert isinstance(pp.__name__, str)
|
||||
|
||||
[file testmodule.py]
|
||||
def factorial(x: int) -> int:
|
||||
if x == 0:
|
||||
return 1
|
||||
else:
|
||||
return x * factorial(x-1)
|
||||
[file welp.py]
|
||||
def foo(x: int) -> int:
|
||||
return x
|
||||
[file pkg/__init__.py]
|
||||
x = 1
|
||||
[file pkg/mod.py]
|
||||
y = 2
|
||||
[file pkg2/__init__.py]
|
||||
[file pkg2/mod.py]
|
||||
x = 1
|
||||
[file pkg2/mod2.py]
|
||||
y = 2
|
||||
[file nob.py]
|
||||
z = 3
|
||||
|
||||
[case testImportMissing]
|
||||
# The unchecked module is configured by the test harness to not be
|
||||
# picked up by mypy, so we can test that we do that right thing when
|
||||
# calling library modules without stubs.
|
||||
import unchecked # type: ignore
|
||||
import unchecked as lol # type: ignore
|
||||
assert unchecked.x == 10
|
||||
assert lol.x == 10
|
||||
[file unchecked.py]
|
||||
x = 10
|
||||
|
||||
[file driver.py]
|
||||
import native
|
||||
|
||||
[case testFromImport]
|
||||
from testmodule import g
|
||||
|
||||
def f(x: int) -> int:
|
||||
return g(x)
|
||||
[file testmodule.py]
|
||||
def g(x: int) -> int:
|
||||
return x + 1
|
||||
[file driver.py]
|
||||
from native import f
|
||||
assert f(1) == 2
|
||||
|
||||
[case testFromImportWithUntypedModule]
|
||||
|
||||
# avoid including an __init__.py and use type: ignore to test what happens
|
||||
# if mypy can't tell if mod isn't a module
|
||||
from pkg import mod # type: ignore
|
||||
|
||||
def test_import() -> None:
|
||||
assert mod.h(8) == 24
|
||||
|
||||
[file pkg/mod.py]
|
||||
def h(x):
|
||||
return x * 3
|
||||
|
||||
[case testFromImportWithKnownModule]
|
||||
from pkg import mod1
|
||||
from pkg import mod2 as modmod
|
||||
from pkg.mod2 import g as gg
|
||||
from pkg.mod3 import h as h2, g as g2
|
||||
|
||||
def test_import() -> None:
|
||||
assert mod1.h(8) == 24
|
||||
assert modmod.g(1) == 1
|
||||
assert gg(2) == 2
|
||||
assert h2(10) == 12
|
||||
assert g2(10) == 13
|
||||
|
||||
[file pkg/__init__.py]
|
||||
[file pkg/mod1.py]
|
||||
def h(x: int) -> int:
|
||||
return x * 3
|
||||
|
||||
[file pkg/mod2.py]
|
||||
def g(x: int) -> int:
|
||||
return x
|
||||
|
||||
[file pkg/mod3.py]
|
||||
def h(x: int) -> int:
|
||||
return x + 2
|
||||
|
||||
def g(x: int) -> int:
|
||||
return x + 3
|
||||
|
||||
[case testFromImportWithUnKnownModule]
|
||||
def test_import() -> None:
|
||||
try:
|
||||
from pkg import a # type: ignore
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
[file pkg/__init__.py]
|
||||
|
||||
[case testMultipleFromImportsWithSamePackageButDifferentModules]
|
||||
from pkg import a
|
||||
from pkg import b
|
||||
|
||||
def test_import() -> None:
|
||||
assert a.g() == 4
|
||||
assert b.h() == 39
|
||||
|
||||
[file pkg/__init__.py]
|
||||
[file pkg/a.py]
|
||||
|
||||
def g() -> int:
|
||||
return 4
|
||||
|
||||
[file pkg/b.py]
|
||||
|
||||
def h() -> int:
|
||||
return 39
|
||||
|
||||
[case testReexport]
|
||||
# Test that we properly handle accessing values that have been reexported
|
||||
import a
|
||||
def f(x: int) -> int:
|
||||
return a.g(x) + a.foo + a.b.foo
|
||||
|
||||
whatever = a.A()
|
||||
|
||||
[file a.py]
|
||||
from b import g as g, A as A, foo as foo
|
||||
import b
|
||||
|
||||
[file b.py]
|
||||
def g(x: int) -> int:
|
||||
return x + 1
|
||||
|
||||
class A:
|
||||
pass
|
||||
|
||||
foo = 20
|
||||
|
||||
[file driver.py]
|
||||
from native import f, whatever
|
||||
import b
|
||||
|
||||
assert f(20) == 61
|
||||
assert isinstance(whatever, b.A)
|
||||
|
||||
[case testAssignModule]
|
||||
import a
|
||||
assert a.x == 20
|
||||
a.x = 10
|
||||
[file a.py]
|
||||
x = 20
|
||||
[file driver.py]
|
||||
import native
|
||||
|
||||
[case testLazyImport]
|
||||
import shared
|
||||
|
||||
def do_import() -> None:
|
||||
import a
|
||||
|
||||
assert shared.counter == 0
|
||||
do_import()
|
||||
assert shared.counter == 1
|
||||
|
||||
[file a.py]
|
||||
import shared
|
||||
shared.counter += 1
|
||||
|
||||
[file shared.py]
|
||||
counter = 0
|
||||
|
||||
[case testDelayedImport]
|
||||
import a
|
||||
print("inbetween")
|
||||
import b
|
||||
|
||||
[file a.py]
|
||||
print("first")
|
||||
|
||||
[file b.py]
|
||||
print("last")
|
||||
|
||||
[out]
|
||||
first
|
||||
inbetween
|
||||
last
|
||||
|
||||
[case testImportErrorLineNumber]
|
||||
try:
|
||||
import enum
|
||||
import dataclasses, missing # type: ignore[import]
|
||||
except ImportError as e:
|
||||
line = e.__traceback__.tb_lineno # type: ignore[attr-defined]
|
||||
assert line == 3, f"traceback's line number is {line}, expected 3"
|
||||
|
||||
[case testImportGroupIsolation]
|
||||
def func() -> None:
|
||||
import second
|
||||
|
||||
import first
|
||||
func()
|
||||
|
||||
[file first.py]
|
||||
print("first")
|
||||
|
||||
[file second.py]
|
||||
print("second")
|
||||
|
||||
[out]
|
||||
first
|
||||
second
|
||||
@@ -0,0 +1,540 @@
|
||||
# Test cases for integers (compile and run)
|
||||
|
||||
[case testInc]
|
||||
def inc(x: int) -> int:
|
||||
return x + 1
|
||||
[file driver.py]
|
||||
from native import inc
|
||||
print(inc(3))
|
||||
print(inc(-5))
|
||||
print(inc(10**20))
|
||||
[out]
|
||||
4
|
||||
-4
|
||||
100000000000000000001
|
||||
|
||||
[case testCount]
|
||||
def count(n: int) -> int:
|
||||
i = 1
|
||||
while i <= n:
|
||||
i = i + 1
|
||||
return i
|
||||
[file driver.py]
|
||||
from native import count
|
||||
print(count(0))
|
||||
print(count(1))
|
||||
print(count(5))
|
||||
[out]
|
||||
1
|
||||
2
|
||||
6
|
||||
|
||||
[case testIntMathOps]
|
||||
# This tests integer math things that are either easier to test in Python than
|
||||
# in our C tests or are tested here because (for annoying reasons) we don't run
|
||||
# the C unit tests in our 32-bit CI.
|
||||
def multiply(x: int, y: int) -> int:
|
||||
return x * y
|
||||
|
||||
# these stringify their outputs because that will catch if exceptions are mishandled
|
||||
def floor_div(x: int, y: int) -> str:
|
||||
return str(x // y)
|
||||
def remainder(x: int, y: int) -> str:
|
||||
return str(x % y)
|
||||
|
||||
[file driver.py]
|
||||
from native import multiply, floor_div, remainder
|
||||
|
||||
def test_multiply(x, y):
|
||||
assert multiply(x, y) == x * y
|
||||
def test_floor_div(x, y):
|
||||
assert floor_div(x, y) == str(x // y)
|
||||
def test_remainder(x, y):
|
||||
assert remainder(x, y) == str(x % y)
|
||||
|
||||
test_multiply(10**6, 10**6)
|
||||
test_multiply(2**15, 2**15-1)
|
||||
test_multiply(2**14, 2**14)
|
||||
|
||||
test_multiply(10**12, 10**12)
|
||||
test_multiply(2**30, 2**30-1)
|
||||
test_multiply(2**29, 2**29)
|
||||
|
||||
test_floor_div(-2**62, -1)
|
||||
test_floor_div(-2**30, -1)
|
||||
try:
|
||||
floor_div(10, 0)
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, "Expected ZeroDivisionError"
|
||||
|
||||
test_remainder(-2**62, -1)
|
||||
test_remainder(-2**30, -1)
|
||||
try:
|
||||
remainder(10, 0)
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, "Expected ZeroDivisionError"
|
||||
|
||||
[case testBigIntLiteral]
|
||||
def big_int() -> None:
|
||||
a_62_bit = 4611686018427387902
|
||||
max_62_bit = 4611686018427387903
|
||||
b_63_bit = 4611686018427387904
|
||||
c_63_bit = 9223372036854775806
|
||||
max_63_bit = 9223372036854775807
|
||||
d_64_bit = 9223372036854775808
|
||||
max_32_bit = 2147483647
|
||||
max_32_bit_plus1 = 2147483648
|
||||
max_31_bit = 1073741823
|
||||
max_31_bit_plus1 = 1073741824
|
||||
neg = -1234567
|
||||
min_signed_63_bit = -4611686018427387904
|
||||
underflow = -4611686018427387905
|
||||
min_signed_64_bit = -9223372036854775808
|
||||
min_signed_31_bit = -1073741824
|
||||
min_signed_31_bit_plus1 = -1073741823
|
||||
min_signed_31_bit_minus1 = -1073741825
|
||||
min_signed_32_bit = -2147483648
|
||||
print(a_62_bit)
|
||||
print(max_62_bit)
|
||||
print(b_63_bit)
|
||||
print(c_63_bit)
|
||||
print(max_63_bit)
|
||||
print(d_64_bit)
|
||||
print('==')
|
||||
print(max_32_bit)
|
||||
print(max_32_bit_plus1)
|
||||
print(max_31_bit)
|
||||
print(max_31_bit_plus1)
|
||||
print(neg)
|
||||
print(min_signed_63_bit)
|
||||
print(underflow)
|
||||
print(min_signed_64_bit)
|
||||
print(min_signed_31_bit)
|
||||
print(min_signed_31_bit_plus1)
|
||||
print(min_signed_31_bit_minus1)
|
||||
print(min_signed_32_bit)
|
||||
[file driver.py]
|
||||
from native import big_int
|
||||
big_int()
|
||||
[out]
|
||||
4611686018427387902
|
||||
4611686018427387903
|
||||
4611686018427387904
|
||||
9223372036854775806
|
||||
9223372036854775807
|
||||
9223372036854775808
|
||||
==
|
||||
2147483647
|
||||
2147483648
|
||||
1073741823
|
||||
1073741824
|
||||
-1234567
|
||||
-4611686018427387904
|
||||
-4611686018427387905
|
||||
-9223372036854775808
|
||||
-1073741824
|
||||
-1073741823
|
||||
-1073741825
|
||||
-2147483648
|
||||
|
||||
[case testNeg]
|
||||
def neg(x: int) -> int:
|
||||
return -x
|
||||
[file driver.py]
|
||||
from native import neg
|
||||
assert neg(5) == -5
|
||||
assert neg(-5) == 5
|
||||
assert neg(1073741823) == -1073741823
|
||||
assert neg(-1073741823) == 1073741823
|
||||
assert neg(1073741824) == -1073741824
|
||||
assert neg(-1073741824) == 1073741824
|
||||
assert neg(2147483647) == -2147483647
|
||||
assert neg(-2147483647) == 2147483647
|
||||
assert neg(2147483648) == -2147483648
|
||||
assert neg(-2147483648) == 2147483648
|
||||
assert neg(4611686018427387904) == -4611686018427387904
|
||||
assert neg(-4611686018427387904) == 4611686018427387904
|
||||
assert neg(9223372036854775807) == -9223372036854775807
|
||||
assert neg(-9223372036854775807) == 9223372036854775807
|
||||
assert neg(9223372036854775808) == -9223372036854775808
|
||||
assert neg(-9223372036854775808) == 9223372036854775808
|
||||
|
||||
[case testIsinstanceIntAndNotBool]
|
||||
def test_isinstance_int_and_not_bool(value: object) -> bool:
|
||||
return isinstance(value, int) and not isinstance(value, bool)
|
||||
[file driver.py]
|
||||
from native import test_isinstance_int_and_not_bool
|
||||
assert test_isinstance_int_and_not_bool(True) == False
|
||||
assert test_isinstance_int_and_not_bool(1) == True
|
||||
|
||||
[case testIntOps]
|
||||
from typing import Any
|
||||
from testutil import assertRaises
|
||||
|
||||
def check_and(x: int, y: int) -> None:
|
||||
# eval() can be trusted to calculate expected result
|
||||
expected = eval('{} & {}'.format(x, y))
|
||||
actual = x & y
|
||||
assert actual == expected, '{} & {}: got {}, expected {}'.format(x, y, actual, expected)
|
||||
|
||||
def check_or(x: int, y: int) -> None:
|
||||
# eval() can be trusted to calculate expected result
|
||||
expected = eval('{} | {}'.format(x, y))
|
||||
actual = x | y
|
||||
assert actual == expected, '{} | {}: got {}, expected {}'.format(x, y, actual, expected)
|
||||
|
||||
def check_xor(x: int, y: int) -> None:
|
||||
# eval() can be trusted to calculate expected result
|
||||
expected = eval('{} ^ {}'.format(x, y))
|
||||
actual = x ^ y
|
||||
assert actual == expected, '{} ^ {}: got {}, expected {}'.format(x, y, actual, expected)
|
||||
|
||||
def check_bitwise(x: int, y: int) -> None:
|
||||
for l, r in (x, y), (y, x):
|
||||
for ll, rr in (l, r), (-l, r), (l, -r), (-l, -r):
|
||||
check_and(ll, rr)
|
||||
check_or(ll, rr)
|
||||
check_xor(ll, rr)
|
||||
|
||||
SHIFT = 30
|
||||
DIGIT0a = 615729753
|
||||
DIGIT0b = 832796681
|
||||
DIGIT1a = 744342356 << SHIFT
|
||||
DIGIT1b = 321006080 << SHIFT
|
||||
DIGIT2a = 643582106 << (SHIFT * 2)
|
||||
DIGIT2b = 656420725 << (SHIFT * 2)
|
||||
DIGIT50 = 315723472 << (SHIFT * 50)
|
||||
DIGIT100a = 1020652627 << (SHIFT * 100)
|
||||
DIGIT100b = 923752451 << (SHIFT * 100)
|
||||
BIG_SHORT = 3491190729721336556
|
||||
MAX_SHORT = (1 << 62) - 1
|
||||
MIN_SHORT = -(1 << 62)
|
||||
MAX_SHORT_32 = (1 << 30) - 1
|
||||
MIN_SHORT_32 = -(1 << 30)
|
||||
|
||||
def test_and_or_xor() -> None:
|
||||
check_bitwise(0, 0)
|
||||
check_bitwise(0, 1)
|
||||
check_bitwise(1, 1)
|
||||
check_bitwise(DIGIT0a, DIGIT0b)
|
||||
check_bitwise(DIGIT1a, DIGIT1b)
|
||||
check_bitwise(DIGIT2a, DIGIT2b)
|
||||
check_bitwise(DIGIT100a, DIGIT100b)
|
||||
check_bitwise(DIGIT0a, DIGIT0b + DIGIT2a)
|
||||
check_bitwise(DIGIT0a, DIGIT0b + DIGIT50)
|
||||
check_bitwise(DIGIT50 + DIGIT1a, DIGIT100a + DIGIT2b)
|
||||
check_bitwise(BIG_SHORT, DIGIT0a)
|
||||
check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a)
|
||||
check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a + DIGIT2a)
|
||||
check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a + DIGIT2a + DIGIT50)
|
||||
|
||||
for x in range(-25, 25):
|
||||
for y in range(-25, 25):
|
||||
check_bitwise(x, y)
|
||||
|
||||
def test_bitwise_inplace() -> None:
|
||||
# Basic sanity checks; these should use the same code as the non-in-place variants
|
||||
for x, y in (DIGIT0a, DIGIT1a), (DIGIT2a, DIGIT0a + DIGIT2b):
|
||||
n = x
|
||||
n &= y
|
||||
assert n == x & y
|
||||
n = x
|
||||
n |= y
|
||||
assert n == x | y
|
||||
n = x
|
||||
n ^= y
|
||||
assert n == x ^ y
|
||||
|
||||
def check_invert(x: int) -> None:
|
||||
# Use eval() as the source of truth
|
||||
assert ~x == eval('~{}'.format(x))
|
||||
assert ~(-x) == eval('~({})'.format(-x))
|
||||
|
||||
def test_invert() -> None:
|
||||
check_invert(0)
|
||||
check_invert(1)
|
||||
check_invert(DIGIT0a)
|
||||
check_invert(DIGIT0a + DIGIT1a)
|
||||
check_invert(DIGIT0a + DIGIT1a + DIGIT2a)
|
||||
check_invert(DIGIT0a + DIGIT1a + DIGIT2a + DIGIT50)
|
||||
check_invert(BIG_SHORT)
|
||||
for delta in -1, 0, 1:
|
||||
check_invert(MAX_SHORT + delta)
|
||||
check_invert(MIN_SHORT + delta)
|
||||
check_invert(MAX_SHORT_32 + delta)
|
||||
check_invert(MIN_SHORT_32 + delta)
|
||||
|
||||
def check_right_shift(x: int, n: int) -> None:
|
||||
if n < 0:
|
||||
try:
|
||||
x >> n
|
||||
except ValueError:
|
||||
return
|
||||
assert False, "no exception raised"
|
||||
# Use eval() as the source of truth
|
||||
expected = eval('{} >> {}'.format(x, n))
|
||||
actual = x >> n
|
||||
assert actual == expected, "{} >> {}: got {}, expected {}".format(x, n, actual, expected)
|
||||
|
||||
def test_right_shift() -> None:
|
||||
for x in 0, 1, 1235, DIGIT0a, DIGIT0a + DIGIT1a, DIGIT0a + DIGIT50:
|
||||
for n in 0, 1, 2, 3, 4, 10, 40, 10000, DIGIT1a, -1, -1334444, -DIGIT1a:
|
||||
check_right_shift(x, n)
|
||||
check_right_shift(-x, n)
|
||||
x = DIGIT0a
|
||||
x >>= 1
|
||||
assert x == DIGIT0a >> 1
|
||||
x = DIGIT50
|
||||
x >>= 5
|
||||
assert x == DIGIT50 >> 5
|
||||
for i in range(256):
|
||||
check_right_shift(1, i)
|
||||
check_right_shift(137, i)
|
||||
check_right_shift(MAX_SHORT, i)
|
||||
check_right_shift(MAX_SHORT_32, i)
|
||||
check_right_shift(MAX_SHORT + 1, i)
|
||||
check_right_shift(MAX_SHORT_32 + 1, i)
|
||||
for x in 1, DIGIT50:
|
||||
try:
|
||||
# It's okay if this raises an exception
|
||||
assert x >> DIGIT2a == 0
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
x >> -DIGIT2a
|
||||
assert False
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def check_left_shift(x: int, n: int) -> None:
|
||||
if n < 0:
|
||||
try:
|
||||
x << n
|
||||
except ValueError:
|
||||
return
|
||||
assert False, "no exception raised"
|
||||
# Use eval() as the source of truth
|
||||
expected = eval('{} << {}'.format(x, n))
|
||||
actual = x << n
|
||||
assert actual == expected, "{} << {}: got {}, expected {}".format(x, n, actual, expected)
|
||||
|
||||
def test_left_shift() -> None:
|
||||
for x in 0, 1, 1235, DIGIT0a, DIGIT0a + DIGIT1a, DIGIT0a + DIGIT50:
|
||||
for n in 0, 1, 2, 10, 40, 10000, -1, -1334444:
|
||||
check_left_shift(x, n)
|
||||
check_left_shift(-x, n)
|
||||
x = DIGIT0a
|
||||
x <<= 1
|
||||
assert x == DIGIT0a << 1
|
||||
x = DIGIT50
|
||||
x <<= 5
|
||||
assert x == DIGIT50 << 5
|
||||
for shift in range(256):
|
||||
check_left_shift(1, shift)
|
||||
check_left_shift(137, shift)
|
||||
for x in 1, DIGIT50:
|
||||
try:
|
||||
x << DIGIT50
|
||||
assert False
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
x << -DIGIT50
|
||||
assert False
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def is_true(x: int) -> bool:
|
||||
if x:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_true2(x: int) -> bool:
|
||||
return bool(x)
|
||||
|
||||
def is_false(x: int) -> bool:
|
||||
if not x:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def test_int_as_bool() -> None:
|
||||
assert not is_true(0)
|
||||
assert not is_true2(0)
|
||||
assert is_false(0)
|
||||
for x in 1, 55, -1, -7, 1 << 50, 1 << 101, -(1 << 50), -(1 << 101):
|
||||
assert is_true(x)
|
||||
assert is_true2(x)
|
||||
assert not is_false(x)
|
||||
|
||||
def bool_as_int(b: bool) -> int:
|
||||
return b
|
||||
|
||||
def bool_as_int2(b: bool) -> int:
|
||||
return int(b)
|
||||
|
||||
def test_bool_as_int() -> None:
|
||||
assert bool_as_int(False) == 0
|
||||
assert bool_as_int(True) == 1
|
||||
assert bool_as_int2(False) == 0
|
||||
assert bool_as_int2(True) == 1
|
||||
|
||||
def no_op_conversion(n: int) -> int:
|
||||
return int(n)
|
||||
|
||||
def test_no_op_conversion() -> None:
|
||||
for x in 1, 55, -1, -7, 1 << 50, 1 << 101, -(1 << 50), -(1 << 101):
|
||||
assert no_op_conversion(x) == x
|
||||
|
||||
def test_floor_divide() -> None:
|
||||
for x in range(-100, 100):
|
||||
for y in range(-100, 100):
|
||||
if y != 0:
|
||||
assert x // y == getattr(x, "__floordiv__")(y)
|
||||
|
||||
def test_mod() -> None:
|
||||
for x in range(-100, 100):
|
||||
for y in range(-100, 100):
|
||||
if y != 0:
|
||||
assert x % y == getattr(x, "__mod__")(y)
|
||||
|
||||
def test_constant_fold() -> None:
|
||||
assert str(-5 + 3) == "-2"
|
||||
assert str(15 - 3) == "12"
|
||||
assert str(1000 * 1000) == "1000000"
|
||||
assert str(12325 // 12 ) == "1027"
|
||||
assert str(87645 % 321) == "12"
|
||||
assert str(674253 | 76544) == "748493"
|
||||
assert str(765 ^ 82) == "687"
|
||||
assert str(6546 << 3) == "52368"
|
||||
assert str(6546 >> 7) == "51"
|
||||
assert str(3**5) == "243"
|
||||
assert str(~76) == "-77"
|
||||
try:
|
||||
2 / 0
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, "no exception raised"
|
||||
|
||||
x = int()
|
||||
y = int() - 1
|
||||
assert x == -1 or y != -3
|
||||
assert -1 <= x
|
||||
assert -1 == y
|
||||
|
||||
# Use int() to avoid constant propagation
|
||||
i30 = (1 << 30) + int()
|
||||
assert i30 == 1 << 30
|
||||
i31 = (1 << 31) + int()
|
||||
assert i31 == 1 << 31
|
||||
i32 = (1 << 32) + int()
|
||||
assert i32 == 1 << 32
|
||||
i62 = (1 << 62) + int()
|
||||
assert i62 == 1 << 62
|
||||
i63 = (1 << 63) + int()
|
||||
assert i63 == 1 << 63
|
||||
i64 = (1 << 64) + int()
|
||||
assert i64 == 1 << 64
|
||||
|
||||
n30 = -(1 << 30) + int()
|
||||
assert n30 == -(1 << 30)
|
||||
n31 = -(1 << 31) + int()
|
||||
assert n31 == -(1 << 31)
|
||||
n32 = -(1 << 32) + int()
|
||||
assert n32 == -(1 << 32)
|
||||
n62 = -(1 << 62) + int()
|
||||
assert n62 == -(1 << 62)
|
||||
n63 = -(1 << 63) + int()
|
||||
assert n63 == -(1 << 63)
|
||||
n64 = -(1 << 64) + int()
|
||||
assert n64 == -(1 << 64)
|
||||
|
||||
def div_by_2(x: int) -> int:
|
||||
return x // 2
|
||||
|
||||
def div_by_3(x: int) -> int:
|
||||
return x // 3
|
||||
|
||||
def div_by_4(x: int) -> int:
|
||||
return x // 4
|
||||
|
||||
def test_floor_divide_by_literal() -> None:
|
||||
for i in range(-100, 100):
|
||||
i_boxed: Any = i
|
||||
assert div_by_2(i) == i_boxed // int('2')
|
||||
assert div_by_3(i) == i_boxed // int('3')
|
||||
assert div_by_4(i) == i_boxed // int('4')
|
||||
|
||||
def test_true_divide() -> None:
|
||||
for x in range(-150, 100):
|
||||
for y in range(-150, 100):
|
||||
if y != 0:
|
||||
assert x / y == getattr(x, "__truediv__")(y)
|
||||
large1 = (123 + int())**123
|
||||
large2 = (121 + int())**121
|
||||
assert large1 / large2 == getattr(large1, "__truediv__")(large2)
|
||||
assert large1 / 135 == getattr(large1, "__truediv__")(135)
|
||||
assert large1 / -2 == getattr(large1, "__truediv__")(-2)
|
||||
assert 17 / large2 == getattr(17, "__truediv__")(large2)
|
||||
|
||||
huge = 10**1000 + int()
|
||||
with assertRaises(OverflowError, "integer division result too large for a float"):
|
||||
huge / 2
|
||||
with assertRaises(OverflowError, "integer division result too large for a float"):
|
||||
huge / -2
|
||||
assert 1 / huge == 0.0
|
||||
|
||||
[case testIntMinMax]
|
||||
def test_int_min_max() -> None:
|
||||
x: int = 200
|
||||
y: int = 30
|
||||
assert min(x, y) == 30
|
||||
assert max(x, y) == 200
|
||||
assert min(y, x) == 30
|
||||
assert max(y, x) == 200
|
||||
|
||||
def test_int_hybrid_min_max() -> None:
|
||||
from typing import Any
|
||||
|
||||
x: object = 30
|
||||
y: Any = 20.0
|
||||
assert min(x, y) == 20.0
|
||||
assert max(x, y) == 30
|
||||
|
||||
u: object = 20
|
||||
v: float = 30.0
|
||||
assert min(u, v) == 20
|
||||
assert max(u, v) == 30.0
|
||||
|
||||
def test_int_incompatible_min_max() -> None:
|
||||
x: int = 2
|
||||
y: str = 'aaa'
|
||||
try:
|
||||
print(min(x, y))
|
||||
except TypeError as e:
|
||||
assert str(e) == "'<' not supported between instances of 'str' and 'int'"
|
||||
try:
|
||||
print(max(x, y))
|
||||
except TypeError as e:
|
||||
assert str(e) == "'>' not supported between instances of 'str' and 'int'"
|
||||
|
||||
def test_int_bool_min_max() -> None:
|
||||
x: int = 2
|
||||
y: bool = False
|
||||
z: bool = True
|
||||
assert min(x, y) == False
|
||||
assert min(x, z) == True
|
||||
assert max(x, y) == 2
|
||||
assert max(x, z) == 2
|
||||
|
||||
u: int = -10
|
||||
assert min(u, y) == -10
|
||||
assert min(u, z) == -10
|
||||
assert max(u, y) == False
|
||||
assert max(u, z) == True
|
||||
411
venv/lib/python3.12/site-packages/mypyc/test-data/run-lists.test
Normal file
411
venv/lib/python3.12/site-packages/mypyc/test-data/run-lists.test
Normal file
@@ -0,0 +1,411 @@
|
||||
# Test cases for lists (compile and run)
|
||||
|
||||
[case testListPlusEquals]
|
||||
from typing import Any
|
||||
def append(x: Any) -> None:
|
||||
x += [1]
|
||||
|
||||
[file driver.py]
|
||||
from native import append
|
||||
x = []
|
||||
append(x)
|
||||
assert x == [1]
|
||||
|
||||
[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
|
||||
[file driver.py]
|
||||
from native import sum
|
||||
print(sum([], 0))
|
||||
print(sum([3], 1))
|
||||
print(sum([5, 6, -4], 3))
|
||||
print(sum([2**128 + 5, -2**127 - 8], 2))
|
||||
[out]
|
||||
0
|
||||
3
|
||||
7
|
||||
170141183460469231731687303715884105725
|
||||
|
||||
[case testListSet]
|
||||
from typing import List
|
||||
def copy(a: List[int], b: List[int], l: int) -> int:
|
||||
i = 0
|
||||
while i < l:
|
||||
a[i] = b[i]
|
||||
i = i + 1
|
||||
return 0
|
||||
[file driver.py]
|
||||
from native import copy
|
||||
a = [0, '']
|
||||
copy(a, [-1, 5], 2)
|
||||
print(1, a)
|
||||
copy(a, [2**128 + 5, -2**127 - 8], 2)
|
||||
print(2, a)
|
||||
[out]
|
||||
1 [-1, 5]
|
||||
2 [340282366920938463463374607431768211461, -170141183460469231731687303715884105736]
|
||||
|
||||
[case testSieve]
|
||||
from typing import List
|
||||
|
||||
def primes(n: int) -> List[int]:
|
||||
a = [1] * (n + 1)
|
||||
a[0] = 0
|
||||
a[1] = 0
|
||||
i = 0
|
||||
while i < n:
|
||||
if a[i] == 1:
|
||||
j = i * i
|
||||
while j < n:
|
||||
a[j] = 0
|
||||
j = j + i
|
||||
i = i + 1
|
||||
return a
|
||||
[file driver.py]
|
||||
from native import primes
|
||||
print(primes(3))
|
||||
print(primes(13))
|
||||
[out]
|
||||
\[0, 0, 1, 1]
|
||||
\[0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1]
|
||||
|
||||
[case testListBuild]
|
||||
def test_list_build() -> None:
|
||||
# Currently LIST_BUILDING_EXPANSION_THRESHOLD equals to 10
|
||||
# long list built by list_build_op
|
||||
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
l1.pop()
|
||||
l1.append(100)
|
||||
assert l1 == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
|
||||
# short list built by Setmem
|
||||
l2 = [1, 2]
|
||||
l2.append(3)
|
||||
l2.pop()
|
||||
l2.pop()
|
||||
assert l2 == [1]
|
||||
# empty list
|
||||
l3 = []
|
||||
l3.append('a')
|
||||
assert l3 == ['a']
|
||||
|
||||
[case testListPrims]
|
||||
from typing import List
|
||||
|
||||
def test_append() -> None:
|
||||
l = [1, 2]
|
||||
l.append(10)
|
||||
assert l == [1, 2, 10]
|
||||
l.append(3)
|
||||
l.append(4)
|
||||
l.append(5)
|
||||
assert l == [1, 2, 10, 3, 4, 5]
|
||||
|
||||
def test_pop_last() -> None:
|
||||
l = [1, 2, 10, 3, 4, 5]
|
||||
l.pop()
|
||||
l.pop()
|
||||
assert l == [1, 2, 10, 3]
|
||||
|
||||
def test_pop_index() -> None:
|
||||
l = [1, 2, 10, 3]
|
||||
l.pop(2)
|
||||
assert l == [1, 2, 3]
|
||||
l.pop(-2)
|
||||
assert l == [1, 3]
|
||||
|
||||
def test_count() -> None:
|
||||
l = [1, 3]
|
||||
assert l.count(1) == 1
|
||||
assert l.count(2) == 0
|
||||
|
||||
def test_insert() -> None:
|
||||
l = [1, 3]
|
||||
l.insert(0, 0)
|
||||
assert l == [0, 1, 3]
|
||||
l.insert(2, 2)
|
||||
assert l == [0, 1, 2, 3]
|
||||
l.insert(4, 4)
|
||||
assert l == [0, 1, 2, 3, 4]
|
||||
l.insert(-1, 5)
|
||||
assert l == [0, 1, 2, 3, 5, 4]
|
||||
l = [1, 3]
|
||||
l.insert(100, 5)
|
||||
assert l == [1, 3, 5]
|
||||
l.insert(-100, 6)
|
||||
assert l == [6, 1, 3, 5]
|
||||
for long_int in 1 << 100, -(1 << 100):
|
||||
try:
|
||||
l.insert(long_int, 5)
|
||||
except Exception as e:
|
||||
# The error message is used by CPython
|
||||
assert type(e).__name__ == 'OverflowError'
|
||||
assert str(e) == 'Python int too large to convert to C ssize_t'
|
||||
else:
|
||||
assert False
|
||||
|
||||
def test_sort() -> None:
|
||||
l = [1, 4, 3, 6, -1]
|
||||
l.sort()
|
||||
assert l == [-1, 1, 3, 4, 6]
|
||||
l.sort()
|
||||
assert l == [-1, 1, 3, 4, 6]
|
||||
l = []
|
||||
l.sort()
|
||||
assert l == []
|
||||
|
||||
def test_reverse() -> None:
|
||||
l = [1, 4, 3, 6, -1]
|
||||
l.reverse()
|
||||
assert l == [-1, 6, 3, 4, 1]
|
||||
l.reverse()
|
||||
assert l == [1, 4, 3, 6, -1]
|
||||
l = []
|
||||
l.reverse()
|
||||
assert l == []
|
||||
|
||||
def test_remove() -> None:
|
||||
l = [1, 3, 4, 3]
|
||||
l.remove(3)
|
||||
assert l == [1, 4, 3]
|
||||
l.remove(3)
|
||||
assert l == [1, 4]
|
||||
try:
|
||||
l.remove(3)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
def test_index() -> None:
|
||||
l = [1, 3, 4, 3]
|
||||
assert l.index(1) == 0
|
||||
assert l.index(3) == 1
|
||||
assert l.index(4) == 2
|
||||
try:
|
||||
l.index(0)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
[case testListOfUserDefinedClass]
|
||||
class C:
|
||||
x: int
|
||||
|
||||
def f() -> int:
|
||||
c = C()
|
||||
c.x = 5
|
||||
a = [c]
|
||||
d = a[0]
|
||||
return d.x + 1
|
||||
|
||||
def g() -> int:
|
||||
a = [C()]
|
||||
a[0].x = 3
|
||||
return a[0].x + 4
|
||||
[file driver.py]
|
||||
from native import f, g
|
||||
print(f())
|
||||
print(g())
|
||||
[out]
|
||||
6
|
||||
7
|
||||
|
||||
[case testListOps]
|
||||
def test_slicing() -> None:
|
||||
# Use dummy adds to avoid constant folding
|
||||
zero = int()
|
||||
two = zero + 2
|
||||
s = ["f", "o", "o", "b", "a", "r"]
|
||||
assert s[two:] == ["o", "b", "a", "r"]
|
||||
assert s[:two] == ["f", "o"]
|
||||
assert s[two:-two] == ["o", "b"]
|
||||
assert s[two:two] == []
|
||||
assert s[two:two + 1] == ["o"]
|
||||
assert s[-two:] == ["a", "r"]
|
||||
assert s[:-two] == ["f", "o", "o", "b"]
|
||||
assert s[:] == ["f", "o", "o", "b", "a", "r"]
|
||||
assert s[two:333] == ["o", "b", "a", "r"]
|
||||
assert s[333:two] == []
|
||||
assert s[two:-333] == []
|
||||
assert s[-333:two] == ["f", "o"]
|
||||
long_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000
|
||||
assert s[1:long_int] == ["o", "o", "b", "a", "r"]
|
||||
assert s[long_int:] == []
|
||||
assert s[-long_int:-1] == ["f", "o", "o", "b", "a"]
|
||||
|
||||
[case testOperatorInExpression]
|
||||
|
||||
def tuple_in_int0(i: int) -> bool:
|
||||
return i in []
|
||||
|
||||
def tuple_in_int1(i: int) -> bool:
|
||||
return i in (1,)
|
||||
|
||||
def tuple_in_int3(i: int) -> bool:
|
||||
return i in (1, 2, 3)
|
||||
|
||||
def tuple_not_in_int0(i: int) -> bool:
|
||||
return i not in []
|
||||
|
||||
def tuple_not_in_int1(i: int) -> bool:
|
||||
return i not in (1,)
|
||||
|
||||
def tuple_not_in_int3(i: int) -> bool:
|
||||
return i not in (1, 2, 3)
|
||||
|
||||
def tuple_in_str(s: "str") -> bool:
|
||||
return s in ("foo", "bar", "baz")
|
||||
|
||||
def tuple_not_in_str(s: "str") -> bool:
|
||||
return s not in ("foo", "bar", "baz")
|
||||
|
||||
def list_in_int0(i: int) -> bool:
|
||||
return i in []
|
||||
|
||||
def list_in_int1(i: int) -> bool:
|
||||
return i in (1,)
|
||||
|
||||
def list_in_int3(i: int) -> bool:
|
||||
return i in (1, 2, 3)
|
||||
|
||||
def list_not_in_int0(i: int) -> bool:
|
||||
return i not in []
|
||||
|
||||
def list_not_in_int1(i: int) -> bool:
|
||||
return i not in (1,)
|
||||
|
||||
def list_not_in_int3(i: int) -> bool:
|
||||
return i not in (1, 2, 3)
|
||||
|
||||
def list_in_str(s: "str") -> bool:
|
||||
return s in ("foo", "bar", "baz")
|
||||
|
||||
def list_not_in_str(s: "str") -> bool:
|
||||
return s not in ("foo", "bar", "baz")
|
||||
|
||||
def list_in_mixed(i: object):
|
||||
return i in [[], (), "", 0, 0.0, False, 0j, {}, set(), type]
|
||||
|
||||
[file driver.py]
|
||||
|
||||
from native import *
|
||||
|
||||
assert not tuple_in_int0(0)
|
||||
assert not tuple_in_int1(0)
|
||||
assert tuple_in_int1(1)
|
||||
assert not tuple_in_int3(0)
|
||||
assert tuple_in_int3(1)
|
||||
assert tuple_in_int3(2)
|
||||
assert tuple_in_int3(3)
|
||||
assert not tuple_in_int3(4)
|
||||
|
||||
assert tuple_not_in_int0(0)
|
||||
assert tuple_not_in_int1(0)
|
||||
assert not tuple_not_in_int1(1)
|
||||
assert tuple_not_in_int3(0)
|
||||
assert not tuple_not_in_int3(1)
|
||||
assert not tuple_not_in_int3(2)
|
||||
assert not tuple_not_in_int3(3)
|
||||
assert tuple_not_in_int3(4)
|
||||
|
||||
assert tuple_in_str("foo")
|
||||
assert tuple_in_str("bar")
|
||||
assert tuple_in_str("baz")
|
||||
assert not tuple_in_str("apple")
|
||||
assert not tuple_in_str("pie")
|
||||
assert not tuple_in_str("\0")
|
||||
assert not tuple_in_str("")
|
||||
|
||||
assert not list_in_int0(0)
|
||||
assert not list_in_int1(0)
|
||||
assert list_in_int1(1)
|
||||
assert not list_in_int3(0)
|
||||
assert list_in_int3(1)
|
||||
assert list_in_int3(2)
|
||||
assert list_in_int3(3)
|
||||
assert not list_in_int3(4)
|
||||
|
||||
assert list_not_in_int0(0)
|
||||
assert list_not_in_int1(0)
|
||||
assert not list_not_in_int1(1)
|
||||
assert list_not_in_int3(0)
|
||||
assert not list_not_in_int3(1)
|
||||
assert not list_not_in_int3(2)
|
||||
assert not list_not_in_int3(3)
|
||||
assert list_not_in_int3(4)
|
||||
|
||||
assert list_in_str("foo")
|
||||
assert list_in_str("bar")
|
||||
assert list_in_str("baz")
|
||||
assert not list_in_str("apple")
|
||||
assert not list_in_str("pie")
|
||||
assert not list_in_str("\0")
|
||||
assert not list_in_str("")
|
||||
|
||||
assert list_in_mixed(0)
|
||||
assert list_in_mixed([])
|
||||
assert list_in_mixed({})
|
||||
assert list_in_mixed(())
|
||||
assert list_in_mixed(False)
|
||||
assert list_in_mixed(0.0)
|
||||
assert not list_in_mixed([1])
|
||||
assert not list_in_mixed(object)
|
||||
assert list_in_mixed(type)
|
||||
|
||||
[case testListBuiltFromGenerator]
|
||||
def test() -> None:
|
||||
source_a = ["a", "b", "c"]
|
||||
a = list(x + "f2" for x in source_a)
|
||||
assert a == ["af2", "bf2", "cf2"]
|
||||
source_b = [1, 2, 3, 4, 5]
|
||||
b = [x * 2 for x in source_b]
|
||||
assert b == [2, 4, 6, 8, 10]
|
||||
source_c = [10, 20, 30]
|
||||
c = [x + "f4" for x in (str(y) + "yy" for y in source_c)]
|
||||
assert c == ["10yyf4", "20yyf4", "30yyf4"]
|
||||
source_d = [True, False]
|
||||
d = [not x for x in source_d]
|
||||
assert d == [False, True]
|
||||
source_e = [0, 1, 2]
|
||||
e = list((x ** 2) for x in (y + 2 for y in source_e))
|
||||
assert e == [4, 9, 16]
|
||||
source_str = "abcd"
|
||||
f = list("str:" + x for x in source_str)
|
||||
assert f == ["str:a", "str:b", "str:c", "str:d"]
|
||||
|
||||
[case testNextBug]
|
||||
from typing import List, Optional
|
||||
|
||||
def test(x: List[int]) -> None:
|
||||
res = next((i for i in x), None)
|
||||
|
||||
[case testListGetItemWithBorrow]
|
||||
from typing import List
|
||||
|
||||
class D:
|
||||
def __init__(self, n: int) -> None:
|
||||
self.n = n
|
||||
|
||||
class C:
|
||||
def __init__(self, d: D) -> None:
|
||||
self.d = d
|
||||
|
||||
def test_index_with_literal() -> None:
|
||||
d1 = D(1)
|
||||
d2 = D(2)
|
||||
a = [C(d1), C(d2)]
|
||||
d = a[0].d
|
||||
assert d is d1
|
||||
d = a[1].d
|
||||
assert d is d2
|
||||
d = a[-1].d
|
||||
assert d is d2
|
||||
d = a[-2].d
|
||||
assert d is d1
|
||||
485
venv/lib/python3.12/site-packages/mypyc/test-data/run-loops.test
Normal file
485
venv/lib/python3.12/site-packages/mypyc/test-data/run-loops.test
Normal file
@@ -0,0 +1,485 @@
|
||||
# Test cases for "range" objects, "for" and "while" loops (compile and run)
|
||||
|
||||
[case testFor]
|
||||
from typing import List, Tuple
|
||||
def count(n: int) -> None:
|
||||
for i in range(n):
|
||||
print(i)
|
||||
def count_between(n: int, k: int) -> None:
|
||||
for i in range(n, k):
|
||||
print(i)
|
||||
print('n=', n)
|
||||
def count_down(n: int, k: int) -> None:
|
||||
for i in range(n, k, -1):
|
||||
print(i)
|
||||
def count_double(n: int, k: int) -> None:
|
||||
for i in range(n, k, 2):
|
||||
print(i)
|
||||
def list_iter(l: List[int]) -> None:
|
||||
for i in l:
|
||||
print(i)
|
||||
def tuple_iter(l: Tuple[int, ...]) -> None:
|
||||
for i in l:
|
||||
print(i)
|
||||
def str_iter(l: str) -> None:
|
||||
for i in l:
|
||||
print(i)
|
||||
def list_rev_iter(l: List[int]) -> None:
|
||||
for i in reversed(l):
|
||||
print(i)
|
||||
def list_rev_iter_lol(l: List[int]) -> None:
|
||||
for i in reversed(l):
|
||||
print(i)
|
||||
if i == 3:
|
||||
while l:
|
||||
l.pop()
|
||||
def count_down_short() -> None:
|
||||
for i in range(10, 0, -1):
|
||||
print(i)
|
||||
[file driver.py]
|
||||
from native import (
|
||||
count, list_iter, list_rev_iter, list_rev_iter_lol, count_between, count_down, count_double,
|
||||
count_down_short, tuple_iter, str_iter,
|
||||
)
|
||||
count(5)
|
||||
list_iter(list(reversed(range(5))))
|
||||
list_rev_iter(list(reversed(range(5))))
|
||||
count_between(11, 15)
|
||||
count_between(10**20, 10**20+3)
|
||||
count_down(20, 10)
|
||||
count_double(10, 15)
|
||||
count_down_short()
|
||||
print('==')
|
||||
list_rev_iter_lol(list(reversed(range(5))))
|
||||
tuple_iter((1, 2, 3))
|
||||
str_iter("abc")
|
||||
[out]
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
4
|
||||
3
|
||||
2
|
||||
1
|
||||
0
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
n= 11
|
||||
100000000000000000000
|
||||
100000000000000000001
|
||||
100000000000000000002
|
||||
n= 100000000000000000000
|
||||
20
|
||||
19
|
||||
18
|
||||
17
|
||||
16
|
||||
15
|
||||
14
|
||||
13
|
||||
12
|
||||
11
|
||||
10
|
||||
12
|
||||
14
|
||||
10
|
||||
9
|
||||
8
|
||||
7
|
||||
6
|
||||
5
|
||||
4
|
||||
3
|
||||
2
|
||||
1
|
||||
==
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
1
|
||||
2
|
||||
3
|
||||
a
|
||||
b
|
||||
c
|
||||
|
||||
[case testLoopElse]
|
||||
from typing import Iterator
|
||||
def run_for_range(n: int) -> None:
|
||||
for i in range(n):
|
||||
if i == 3:
|
||||
break
|
||||
print(i)
|
||||
else:
|
||||
print(n+1)
|
||||
|
||||
def run_for_list(n: int) -> None:
|
||||
for i in list(range(n)):
|
||||
if i == 3:
|
||||
break
|
||||
print(i)
|
||||
else:
|
||||
print(n+1)
|
||||
|
||||
def run_for_iter(n: int) -> None:
|
||||
def identity(x: Iterator[int]) -> Iterator[int]:
|
||||
return x
|
||||
for i in identity(range(n)):
|
||||
if i == 3:
|
||||
break
|
||||
print(i)
|
||||
else:
|
||||
print(n+1)
|
||||
|
||||
def count(n: int) -> int:
|
||||
i = 1
|
||||
while i <= n:
|
||||
i = i + 1
|
||||
if i == 5:
|
||||
break
|
||||
else:
|
||||
i *= -1
|
||||
return i
|
||||
|
||||
def nested_while() -> int:
|
||||
while True:
|
||||
while False:
|
||||
pass
|
||||
else:
|
||||
break
|
||||
else:
|
||||
return -1
|
||||
return 0
|
||||
|
||||
def nested_for() -> int:
|
||||
for x in range(1000):
|
||||
for y in [1,2,3]:
|
||||
pass
|
||||
else:
|
||||
break
|
||||
else:
|
||||
return -1
|
||||
return 0
|
||||
|
||||
[file driver.py]
|
||||
from native import run_for_range, run_for_list, run_for_iter, count, nested_while, nested_for
|
||||
assert nested_while() == 0
|
||||
assert nested_for() == 0
|
||||
assert count(0) == -1
|
||||
assert count(1) == -2
|
||||
assert count(5) == 5
|
||||
assert count(6) == 5
|
||||
run_for_range(3)
|
||||
run_for_range(5)
|
||||
print('==')
|
||||
run_for_list(3)
|
||||
run_for_list(5)
|
||||
print('==')
|
||||
run_for_iter(3)
|
||||
run_for_iter(5)
|
||||
[out]
|
||||
0
|
||||
1
|
||||
2
|
||||
4
|
||||
0
|
||||
1
|
||||
2
|
||||
==
|
||||
0
|
||||
1
|
||||
2
|
||||
4
|
||||
0
|
||||
1
|
||||
2
|
||||
==
|
||||
0
|
||||
1
|
||||
2
|
||||
4
|
||||
0
|
||||
1
|
||||
2
|
||||
|
||||
[case testNestedLoopSameIdx]
|
||||
from typing import List, Generator
|
||||
|
||||
def nested_enumerate() -> None:
|
||||
l1 = [0,1,2]
|
||||
l2 = [0,1,2]
|
||||
outer_seen = []
|
||||
outer = 0
|
||||
for i, j in enumerate(l1):
|
||||
assert i == outer
|
||||
outer_seen.append(i)
|
||||
inner = 0
|
||||
for i, k in enumerate(l2):
|
||||
assert i == inner
|
||||
inner += 1
|
||||
outer += 1
|
||||
assert outer_seen == l1
|
||||
|
||||
def nested_range() -> None:
|
||||
outer = 0
|
||||
outer_seen = []
|
||||
for i in range(3):
|
||||
assert i == outer
|
||||
outer_seen.append(i)
|
||||
inner = 0
|
||||
for i in range(3):
|
||||
assert i == inner
|
||||
inner += 1
|
||||
outer += 1
|
||||
assert outer_seen == [0,1,2]
|
||||
|
||||
def nested_list() -> None:
|
||||
l1 = [0,1,2]
|
||||
l2 = [0,1,2]
|
||||
outer_seen = []
|
||||
outer = 0
|
||||
for i in l1:
|
||||
assert i == outer
|
||||
outer_seen.append(i)
|
||||
inner = 0
|
||||
for i in l2:
|
||||
assert i == inner
|
||||
inner += 1
|
||||
outer += 1
|
||||
assert outer_seen == l1
|
||||
|
||||
def nested_yield() -> Generator:
|
||||
for i in range(3):
|
||||
for i in range(3):
|
||||
yield i
|
||||
yield i
|
||||
|
||||
|
||||
[file driver.py]
|
||||
from native import nested_enumerate, nested_range, nested_list, nested_yield
|
||||
nested_enumerate()
|
||||
nested_range()
|
||||
nested_list()
|
||||
gen = nested_yield()
|
||||
for k in range(12):
|
||||
assert next(gen) == k % 4
|
||||
[out]
|
||||
|
||||
[case testForIterable]
|
||||
from typing import Iterable, Dict, Any, Tuple
|
||||
def iterate_over_any(a: Any) -> None:
|
||||
for element in a:
|
||||
print(element)
|
||||
|
||||
def iterate_over_iterable(iterable: Iterable[T]) -> None:
|
||||
for element in iterable:
|
||||
print(element)
|
||||
|
||||
def iterate_and_delete(d: Dict[int, int]) -> None:
|
||||
for key in d:
|
||||
d.pop(key)
|
||||
|
||||
def sum_over_values(d: Dict[int, int]) -> int:
|
||||
s = 0
|
||||
for key in d:
|
||||
s = s + d[key]
|
||||
return s
|
||||
|
||||
def sum_over_even_values(d: Dict[int, int]) -> int:
|
||||
s = 0
|
||||
for key in d:
|
||||
if d[key] % 2:
|
||||
continue
|
||||
s = s + d[key]
|
||||
return s
|
||||
|
||||
def sum_over_two_values(d: Dict[int, int]) -> int:
|
||||
s = 0
|
||||
i = 0
|
||||
for key in d:
|
||||
if i == 2:
|
||||
break
|
||||
s = s + d[key]
|
||||
i = i + 1
|
||||
return s
|
||||
|
||||
def iterate_over_tuple(iterable: Tuple[int, int, int]) -> None:
|
||||
for element in iterable:
|
||||
print(element)
|
||||
|
||||
[file driver.py]
|
||||
from native import iterate_over_any, iterate_over_iterable, iterate_and_delete, sum_over_values, sum_over_even_values, sum_over_two_values, iterate_over_tuple
|
||||
import traceback
|
||||
def broken_generator(n):
|
||||
num = 0
|
||||
while num < n:
|
||||
yield num
|
||||
num += 1
|
||||
raise Exception('Exception Manually Raised')
|
||||
|
||||
d = {1:1, 2:2, 3:3, 4:4, 5:5}
|
||||
print(sum_over_values(d))
|
||||
print(sum_over_even_values(d))
|
||||
print(sum_over_two_values(d))
|
||||
|
||||
try:
|
||||
iterate_over_any(5)
|
||||
except TypeError:
|
||||
traceback.print_exc()
|
||||
try:
|
||||
iterate_over_iterable(broken_generator(5))
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
try:
|
||||
iterate_and_delete(d)
|
||||
except RuntimeError:
|
||||
traceback.print_exc()
|
||||
|
||||
iterate_over_tuple((1, 2, 3))
|
||||
[out]
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 16, in <module>
|
||||
iterate_over_any(5)
|
||||
File "native.py", line 3, in iterate_over_any
|
||||
for element in a:
|
||||
TypeError: 'int' object is not iterable
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 20, in <module>
|
||||
iterate_over_iterable(broken_generator(5))
|
||||
File "native.py", line 7, in iterate_over_iterable
|
||||
for element in iterable:
|
||||
File "driver.py", line 8, in broken_generator
|
||||
raise Exception('Exception Manually Raised')
|
||||
Exception: Exception Manually Raised
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 24, in <module>
|
||||
iterate_and_delete(d)
|
||||
File "native.py", line 11, in iterate_and_delete
|
||||
for key in d:
|
||||
RuntimeError: dictionary changed size during iteration
|
||||
15
|
||||
6
|
||||
3
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
1
|
||||
2
|
||||
3
|
||||
|
||||
[case testContinueFor]
|
||||
def f() -> None:
|
||||
for n in range(5):
|
||||
continue
|
||||
[file driver.py]
|
||||
from native import f
|
||||
f()
|
||||
|
||||
[case testMultipleVarsWithLoops]
|
||||
# Test comprehensions and for loops with multiple index variables
|
||||
l = [(1, 2, 'a'), (3, 4, 'b'), (5, 6, 'c')]
|
||||
l2 = [str(a*100+b)+' '+c for a, b, c in l]
|
||||
l3 = []
|
||||
for a, b, c in l:
|
||||
l3.append(str(a*1000+b)+' '+c)
|
||||
[file driver.py]
|
||||
from native import l, l2, l3
|
||||
for a in l2 + l3:
|
||||
print(a)
|
||||
[out]
|
||||
102 a
|
||||
304 b
|
||||
506 c
|
||||
1002 a
|
||||
3004 b
|
||||
5006 c
|
||||
|
||||
[case testForZipAndEnumerate]
|
||||
from typing import Iterable, List, Any
|
||||
def f(a: Iterable[int], b: List[int]) -> List[Any]:
|
||||
res = []
|
||||
for (x, y), z in zip(enumerate(a), b):
|
||||
res.append((x, y, z))
|
||||
return res
|
||||
def g(a: Iterable[int], b: Iterable[str]) -> List[Any]:
|
||||
res = []
|
||||
for x, (y, z) in enumerate(zip(a, b)):
|
||||
res.append((x, y, z))
|
||||
return res
|
||||
|
||||
[file driver.py]
|
||||
from native import f, g
|
||||
|
||||
assert f([6, 7], [8, 9]) == [(0, 6, 8), (1, 7, 9)]
|
||||
assert g([6, 7], ['a', 'b']) == [(0, 6, 'a'), (1, 7, 'b')]
|
||||
assert f([6, 7], [8]) == [(0, 6, 8)]
|
||||
assert f([6], [8, 9]) == [(0, 6, 8)]
|
||||
|
||||
[case testIterTypeTrickiness]
|
||||
# Test inferring the type of a for loop body doesn't cause us grief
|
||||
# Extracted from somethings that broke in mypy
|
||||
|
||||
from typing import Optional
|
||||
|
||||
# really I only care that this one build
|
||||
def foo(x: object) -> None:
|
||||
if isinstance(x, dict):
|
||||
for a in x:
|
||||
pass
|
||||
|
||||
def bar(x: Optional[str]) -> None:
|
||||
vars = (
|
||||
("a", 'lol'),
|
||||
("b", 'asdf'),
|
||||
("lol", x),
|
||||
("an int", 10),
|
||||
)
|
||||
for name, value in vars:
|
||||
pass
|
||||
|
||||
[file driver.py]
|
||||
from native import bar
|
||||
bar(None)
|
||||
|
||||
[case testRangeObject]
|
||||
from typing import Any
|
||||
|
||||
def f(x: range) -> int:
|
||||
sum = 0
|
||||
for i in x:
|
||||
sum += i
|
||||
return sum
|
||||
|
||||
def test_range_object() -> None:
|
||||
r1 = range(4, 12, 2)
|
||||
tmp_list = [x for x in r1]
|
||||
assert tmp_list == [4, 6, 8, 10]
|
||||
assert f(r1) == 28
|
||||
r2: Any = range(10)
|
||||
assert f(r2) == 45
|
||||
r3: Any = 'x'
|
||||
try:
|
||||
f(r3)
|
||||
except TypeError as e:
|
||||
assert "range object expected; got str" in str(e)
|
||||
try:
|
||||
ff: Any = f
|
||||
ff(r3)
|
||||
except TypeError as e:
|
||||
assert "range object expected; got str" in str(e)
|
||||
try:
|
||||
r4 = range(4, 12, 0)
|
||||
except ValueError as e:
|
||||
assert "range() arg 3 must not be zero" in str(e)
|
||||
283
venv/lib/python3.12/site-packages/mypyc/test-data/run-match.test
Normal file
283
venv/lib/python3.12/site-packages/mypyc/test-data/run-match.test
Normal file
@@ -0,0 +1,283 @@
|
||||
[case testTheBigMatch_python3_10]
|
||||
class Person:
|
||||
__match_args__ = ("name", "age")
|
||||
|
||||
name: str
|
||||
age: int
|
||||
|
||||
def __init__(self, name: str, age: int) -> None:
|
||||
self.name = name
|
||||
self.age = age
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Person(name={self.name!r}, age={self.age})"
|
||||
|
||||
|
||||
def f(x: object) -> None:
|
||||
match x:
|
||||
case 123:
|
||||
print("test 1")
|
||||
|
||||
case 456 | 789:
|
||||
print("test 2")
|
||||
|
||||
case True | False | None:
|
||||
print("test 3")
|
||||
|
||||
case Person("bob" as name, age):
|
||||
print(f"test 4 ({name=}, {age=})")
|
||||
|
||||
case num if num == 5:
|
||||
print("test 5")
|
||||
|
||||
case 6 as num:
|
||||
print(f"test 6 ({num=})")
|
||||
|
||||
case (7 | "7") as value:
|
||||
print(f"test 7 ({value=})")
|
||||
|
||||
case Person("alice", age=123):
|
||||
print("test 8")
|
||||
|
||||
case Person("charlie", age=123 | 456):
|
||||
print("test 9")
|
||||
|
||||
case Person("dave", 123) as dave:
|
||||
print(f"test 10 {dave}")
|
||||
|
||||
case {"test": 11}:
|
||||
print("test 11")
|
||||
|
||||
case {"test": 12, **rest}:
|
||||
print(f"test 12 (rest={rest})")
|
||||
|
||||
case {}:
|
||||
print("test map final")
|
||||
|
||||
case ["test", 13]:
|
||||
print("test 13")
|
||||
|
||||
case ["test", 13, _]:
|
||||
print("test 13b")
|
||||
|
||||
case ["test", 14, *_]:
|
||||
print("test 14")
|
||||
|
||||
# TODO: Fix "rest" being used here coliding with above "rest"
|
||||
case ["test", 15, *rest2]:
|
||||
print(f"test 15 ({rest2})")
|
||||
|
||||
case ["test", *rest3, 16]:
|
||||
print(f"test 16 ({rest3})")
|
||||
|
||||
case [*rest4, "test", 17]:
|
||||
print(f"test 17 ({rest4})")
|
||||
|
||||
case [*rest4, "test", 18, "some", "fluff"]:
|
||||
print(f"test 18 ({rest4})")
|
||||
|
||||
case str("test 19"):
|
||||
print("test 19")
|
||||
|
||||
case str(test_20) if test_20.startswith("test 20"):
|
||||
print(f"test 20 ({test_20[7:]!r})")
|
||||
|
||||
case ("test 21" as value) | ("test 21 as well" as value):
|
||||
print(f"test 21 ({value[7:]!r})")
|
||||
|
||||
case []:
|
||||
print("test sequence final")
|
||||
|
||||
case _:
|
||||
print("test final")
|
||||
[file driver.py]
|
||||
from native import f, Person
|
||||
|
||||
# test 1
|
||||
f(123)
|
||||
|
||||
# test 2
|
||||
f(456)
|
||||
f(789)
|
||||
|
||||
# test 3
|
||||
f(True)
|
||||
f(False)
|
||||
f(None)
|
||||
|
||||
# test 4
|
||||
f(Person("bob", 123))
|
||||
|
||||
# test 5
|
||||
f(5)
|
||||
|
||||
# test 6
|
||||
f(6)
|
||||
|
||||
# test 7
|
||||
f(7)
|
||||
f("7")
|
||||
|
||||
# test 8
|
||||
f(Person("alice", 123))
|
||||
|
||||
# test 9
|
||||
f(Person("charlie", 123))
|
||||
f(Person("charlie", 456))
|
||||
|
||||
# test 10
|
||||
f(Person("dave", 123))
|
||||
|
||||
# test 11
|
||||
f({"test": 11})
|
||||
f({"test": 11, "some": "key"})
|
||||
|
||||
# test 12
|
||||
f({"test": 12})
|
||||
f({"test": 12, "key": "value"})
|
||||
f({"test": 12, "key": "value", "abc": "123"})
|
||||
|
||||
# test map final
|
||||
f({})
|
||||
|
||||
# test 13
|
||||
f(["test", 13])
|
||||
|
||||
# test 13b
|
||||
f(["test", 13, "fail"])
|
||||
|
||||
# test 14
|
||||
f(["test", 14])
|
||||
f(["test", 14, "something"])
|
||||
|
||||
# test 15
|
||||
f(["test", 15])
|
||||
f(["test", 15, "something"])
|
||||
|
||||
# test 16
|
||||
f(["test", 16])
|
||||
f(["test", "filler", 16])
|
||||
f(["test", "more", "filler", 16])
|
||||
|
||||
# test 17
|
||||
f(["test", 17])
|
||||
f(["stuff", "test", 17])
|
||||
f(["more", "stuff", "test", 17])
|
||||
|
||||
# test 18
|
||||
f(["test", 18, "some", "fluff"])
|
||||
f(["stuff", "test", 18, "some", "fluff"])
|
||||
f(["more", "stuff", "test", 18, "some", "fluff"])
|
||||
|
||||
# test 19
|
||||
f("test 19")
|
||||
|
||||
# test 20
|
||||
f("test 20")
|
||||
f("test 20 something else")
|
||||
|
||||
# test 21
|
||||
f("test 21")
|
||||
f("test 21 as well")
|
||||
|
||||
# test sequence final
|
||||
f([])
|
||||
|
||||
# test final
|
||||
f("")
|
||||
|
||||
[out]
|
||||
test 1
|
||||
test 2
|
||||
test 2
|
||||
test 3
|
||||
test 3
|
||||
test 3
|
||||
test 4 (name='bob', age=123)
|
||||
test 5
|
||||
test 6 (num=6)
|
||||
test 7 (value=7)
|
||||
test 7 (value='7')
|
||||
test 8
|
||||
test 9
|
||||
test 9
|
||||
test 10 Person(name='dave', age=123)
|
||||
test 11
|
||||
test 11
|
||||
test 12 (rest={})
|
||||
test 12 (rest={'key': 'value'})
|
||||
test 12 (rest={'key': 'value', 'abc': '123'})
|
||||
test map final
|
||||
test 13
|
||||
test 13b
|
||||
test 14
|
||||
test 14
|
||||
test 15 ([])
|
||||
test 15 (['something'])
|
||||
test 16 ([])
|
||||
test 16 (['filler'])
|
||||
test 16 (['more', 'filler'])
|
||||
test 17 ([])
|
||||
test 17 (['stuff'])
|
||||
test 17 (['more', 'stuff'])
|
||||
test 18 ([])
|
||||
test 18 (['stuff'])
|
||||
test 18 (['more', 'stuff'])
|
||||
test 19
|
||||
test 20 ('')
|
||||
test 20 (' something else')
|
||||
test 21 ('')
|
||||
test 21 (' as well')
|
||||
test sequence final
|
||||
test final
|
||||
[case testCustomMappingAndSequenceObjects_python3_10]
|
||||
def f(x: object) -> None:
|
||||
match x:
|
||||
case {"key": "value", **rest}:
|
||||
print(rest, type(rest))
|
||||
|
||||
case [1, 2, *rest2]:
|
||||
print(rest2, type(rest2))
|
||||
|
||||
[file driver.py]
|
||||
from collections.abc import Mapping, Sequence
|
||||
|
||||
from native import f
|
||||
|
||||
class CustomMapping(Mapping):
|
||||
inner: dict
|
||||
|
||||
def __init__(self, inner: dict) -> None:
|
||||
self.inner = inner
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.inner[key]
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.inner)
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.inner)
|
||||
|
||||
|
||||
class CustomSequence(Sequence):
|
||||
inner: list
|
||||
|
||||
def __init__(self, inner: list) -> None:
|
||||
self.inner = inner
|
||||
|
||||
def __getitem__(self, index: int) -> None:
|
||||
return self.inner[index]
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.inner)
|
||||
|
||||
mapping = CustomMapping({"key": "value", "some": "data"})
|
||||
sequence = CustomSequence([1, 2, 3])
|
||||
|
||||
f(mapping)
|
||||
f(sequence)
|
||||
|
||||
[out]
|
||||
{'some': 'data'} <class 'dict'>
|
||||
[3] <class 'list'>
|
||||
106
venv/lib/python3.12/site-packages/mypyc/test-data/run-math.test
Normal file
106
venv/lib/python3.12/site-packages/mypyc/test-data/run-math.test
Normal file
@@ -0,0 +1,106 @@
|
||||
# Test cases for the math module (compile and run)
|
||||
|
||||
[case testMathOps]
|
||||
from typing import Any, Callable
|
||||
from typing_extensions import Final
|
||||
import math
|
||||
from math import pi, e, tau, inf, nan
|
||||
from testutil import assertRaises, float_vals, assertDomainError, assertMathRangeError
|
||||
|
||||
pymath: Any = math
|
||||
|
||||
def validate_one_arg(test: Callable[[float], float], validate: Callable[[float], float]) -> None:
|
||||
"""Ensure that test and validate behave the same for various float args."""
|
||||
for x in float_vals:
|
||||
try:
|
||||
expected = validate(x)
|
||||
except Exception as e:
|
||||
try:
|
||||
test(x)
|
||||
assert False, f"no exception raised for {x!r}, expected {e!r}"
|
||||
except Exception as e2:
|
||||
assert repr(e) == repr(e2), f"actual for {x!r}: {e2!r}, expected: {e!r}"
|
||||
continue
|
||||
actual = test(x)
|
||||
assert repr(actual) == repr(expected), (
|
||||
f"actual for {x!r}: {actual!r}, expected {expected!r}")
|
||||
|
||||
def validate_two_arg(test: Callable[[float, float], float],
|
||||
validate: Callable[[float, float], float]) -> None:
|
||||
"""Ensure that test and validate behave the same for various float args."""
|
||||
for x in float_vals:
|
||||
for y in float_vals:
|
||||
args = f"({x!r}, {y!r})"
|
||||
try:
|
||||
expected = validate(x, y)
|
||||
except Exception as e:
|
||||
try:
|
||||
test(x, y)
|
||||
assert False, f"no exception raised for {args}, expected {e!r}"
|
||||
except Exception as e2:
|
||||
assert repr(e) == repr(e2), f"actual for {args}: {e2!r}, expected: {e!r}"
|
||||
continue
|
||||
try:
|
||||
actual = test(x, y)
|
||||
except Exception as e:
|
||||
assert False, f"no exception expected for {args}, got {e!r}"
|
||||
assert repr(actual) == repr(expected), (
|
||||
f"actual for {args}: {actual!r}, expected {expected!r}")
|
||||
|
||||
def test_sqrt() -> None:
|
||||
validate_one_arg(lambda x: math.sqrt(x), pymath.sqrt)
|
||||
|
||||
def test_sin() -> None:
|
||||
validate_one_arg(lambda x: math.sin(x), pymath.sin)
|
||||
|
||||
def test_cos() -> None:
|
||||
validate_one_arg(lambda x: math.cos(x), pymath.cos)
|
||||
|
||||
def test_tan() -> None:
|
||||
validate_one_arg(lambda x: math.tan(x), pymath.tan)
|
||||
|
||||
def test_exp() -> None:
|
||||
validate_one_arg(lambda x: math.exp(x), pymath.exp)
|
||||
|
||||
def test_log() -> None:
|
||||
validate_one_arg(lambda x: math.log(x), pymath.log)
|
||||
|
||||
def test_floor() -> None:
|
||||
validate_one_arg(lambda x: math.floor(x), pymath.floor)
|
||||
|
||||
def test_ceil() -> None:
|
||||
validate_one_arg(lambda x: math.ceil(x), pymath.ceil)
|
||||
|
||||
def test_fabs() -> None:
|
||||
validate_one_arg(lambda x: math.fabs(x), pymath.fabs)
|
||||
|
||||
def test_pow() -> None:
|
||||
validate_two_arg(lambda x, y: math.pow(x, y), pymath.pow)
|
||||
|
||||
def test_copysign() -> None:
|
||||
validate_two_arg(lambda x, y: math.copysign(x, y), pymath.copysign)
|
||||
|
||||
def test_isinf() -> None:
|
||||
for x in float_vals:
|
||||
assert repr(math.isinf(x)) == repr(pymath.isinf(x))
|
||||
|
||||
def test_isnan() -> None:
|
||||
for x in float_vals:
|
||||
assert repr(math.isnan(x)) == repr(pymath.isnan(x))
|
||||
|
||||
|
||||
def test_pi_is_inlined_correctly() -> None:
|
||||
assert math.pi == pi == 3.141592653589793
|
||||
|
||||
def test_e_is_inlined_correctly() -> None:
|
||||
assert math.e == e == 2.718281828459045
|
||||
|
||||
def test_tau_is_inlined_correctly() -> None:
|
||||
assert math.tau == tau == 6.283185307179586
|
||||
|
||||
def test_inf_is_inlined_correctly() -> None:
|
||||
assert math.inf == inf == float("inf")
|
||||
|
||||
def test_nan_is_inlined_correctly() -> None:
|
||||
assert math.isnan(math.nan)
|
||||
assert math.isnan(nan)
|
||||
1172
venv/lib/python3.12/site-packages/mypyc/test-data/run-misc.test
Normal file
1172
venv/lib/python3.12/site-packages/mypyc/test-data/run-misc.test
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,887 @@
|
||||
-- These test cases compile two or more modules at a time.
|
||||
-- Any file prefixed with "other" is compiled.
|
||||
--
|
||||
-- Note that these are run in three compilation modes: regular,
|
||||
-- multi-file and separate. See the docstrings of
|
||||
-- mypyc.test.test_run.TestRunMultiFile and
|
||||
-- mypyc.test.test_run.TestRunSeparate for more information.
|
||||
--
|
||||
-- Some of these files perform multiple incremental runs. See
|
||||
-- test-data/unit/check-incremental.test for more information
|
||||
-- about how this is specified (e.g. .2 file name suffixes).
|
||||
|
||||
[case testMultiModulePackage]
|
||||
from p.other import g, _i as i
|
||||
def f(x: int) -> int:
|
||||
from p.other import h
|
||||
return i(h(g(x + 1)))
|
||||
[file p/__init__.py]
|
||||
[file p/other.py]
|
||||
def g(x: int) -> int:
|
||||
return x + 2
|
||||
def h(x: int) -> int:
|
||||
return x + 1
|
||||
def _i(x: int) -> int:
|
||||
return x + 3
|
||||
[file driver.py]
|
||||
import native
|
||||
from native import f
|
||||
from p.other import g
|
||||
assert f(3) == 10
|
||||
assert g(2) == 4
|
||||
try:
|
||||
f(1.1)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
g(1.1)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
[case testMultiModuleFastpaths]
|
||||
[file other_main.py]
|
||||
|
||||
[file other_main.py.2]
|
||||
from other_b import A, func
|
||||
|
||||
class B(A):
|
||||
pass
|
||||
|
||||
def test() -> None:
|
||||
a = A()
|
||||
assert func() == 12
|
||||
assert a.method() == "test"
|
||||
|
||||
test()
|
||||
|
||||
[file other_b.py]
|
||||
class A:
|
||||
def method(self) -> str:
|
||||
return "test"
|
||||
|
||||
def func() -> int:
|
||||
return 12
|
||||
|
||||
# Remove all the methods and functions from globals to ensure that
|
||||
# they get called via the fastpaths even when doing incremental
|
||||
# compilation.
|
||||
setattr(A, 'method', None)
|
||||
setattr(A, '__init__', None)
|
||||
globals()['func'] = None
|
||||
globals()['A'] = None
|
||||
|
||||
[file driver.py]
|
||||
import other_main
|
||||
|
||||
[case testMultiModuleSameNames]
|
||||
# Use same names in both modules
|
||||
import other
|
||||
def f() -> int:
|
||||
return 0
|
||||
class C:
|
||||
x: int
|
||||
def __init__(self) -> None:
|
||||
self.x = 1
|
||||
def f(self, x: int) -> int:
|
||||
return self.x + x
|
||||
class D(C): pass
|
||||
|
||||
def g(x: 'other.C') -> None:
|
||||
pass
|
||||
|
||||
[file other.py]
|
||||
def f(x: int) -> int:
|
||||
return x + 1
|
||||
class C:
|
||||
x: int
|
||||
def __init__(self) -> None:
|
||||
self.x = 2
|
||||
def f(self, x: int) -> int:
|
||||
return self.x + x + 1
|
||||
class D(C): pass
|
||||
[file driver.py]
|
||||
import native, other
|
||||
assert native.f() == 0
|
||||
assert other.f(3) == 4
|
||||
c1 = native.C()
|
||||
c1.x += 3
|
||||
c2 = other.C()
|
||||
c2.x += 6
|
||||
assert c1.f(9) == 1 + 3 + 9
|
||||
assert c2.f(7) == 2 + 6 + 7 + 1
|
||||
assert isinstance(native.D(), native.C)
|
||||
assert isinstance(other.D(), other.C)
|
||||
assert not isinstance(native.D(), other.C)
|
||||
assert not isinstance(other.D(), native.C)
|
||||
|
||||
[case testMultiModuleInitializeImportedModules]
|
||||
from other import f
|
||||
|
||||
def g() -> int:
|
||||
return f(1)
|
||||
[file other.py]
|
||||
def f(x: int) -> int:
|
||||
return x + 4
|
||||
[file driver.py]
|
||||
import sys
|
||||
assert 'other' not in sys.modules
|
||||
from native import g
|
||||
assert 'other' in sys.modules
|
||||
assert g() == 5
|
||||
f = sys.modules['other'].f
|
||||
assert f(1) == 5
|
||||
try:
|
||||
f(1.1)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
[case testMultiModuleImportClass]
|
||||
from typing import cast
|
||||
from other import C, a_global
|
||||
|
||||
class D(C):
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
def f(c: C) -> int:
|
||||
d = D(3)
|
||||
o: object = c
|
||||
c = cast(C, o)
|
||||
return a_global + c.x + c.f() + d.x + d.f() + 1
|
||||
[file other.py]
|
||||
from typing_extensions import Final
|
||||
a_global: Final = int('5')
|
||||
|
||||
class C:
|
||||
x: int
|
||||
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return self.x
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self.x)
|
||||
|
||||
def f(self) -> int:
|
||||
return 2
|
||||
|
||||
def check(self) -> None:
|
||||
assert isinstance(self, C)
|
||||
|
||||
[file driver.py]
|
||||
from native import f, D
|
||||
from other import C
|
||||
c = C(4)
|
||||
assert f(c) == 5 + 4 + 2 + 3 + 2 + 1
|
||||
assert str(D(10)) == '10'
|
||||
assert hash(10) == 10
|
||||
try:
|
||||
f(1)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
assert isinstance(D(10), C)
|
||||
|
||||
c.check()
|
||||
D(10).check()
|
||||
|
||||
[case testMultiModuleSpecialize]
|
||||
from other import A
|
||||
|
||||
class B(A):
|
||||
def foo(self, x: object) -> int:
|
||||
print(2)
|
||||
return id(x)
|
||||
[file other.py]
|
||||
class A:
|
||||
def foo(self, x: int) -> object:
|
||||
print(1)
|
||||
return str(x)
|
||||
|
||||
def use_a(x: A, y: int) -> object:
|
||||
return x.foo(y)
|
||||
|
||||
[file driver.py]
|
||||
from native import B
|
||||
from other import A, use_a
|
||||
a = A()
|
||||
b = B()
|
||||
o = object()
|
||||
i = 10
|
||||
assert a.foo(10) == '10'
|
||||
assert b.foo(o) == id(o)
|
||||
assert use_a(a, 10) == '10'
|
||||
assert use_a(b, i) == id(i)
|
||||
[out]
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
||||
|
||||
[case testMultiModuleLiterals]
|
||||
from other import gs, gi, gf
|
||||
|
||||
def fs() -> str:
|
||||
return 'f' + gs()
|
||||
def fi() -> int:
|
||||
return 10001000100010001000 + gi()
|
||||
def ff() -> float:
|
||||
return 2.0 + gf()
|
||||
[file other.py]
|
||||
def gi() -> int:
|
||||
return 20001000100010001000
|
||||
def gs() -> str:
|
||||
return 'g'
|
||||
def gf() -> float:
|
||||
return 3.0
|
||||
[file driver.py]
|
||||
from native import fs, fi, ff
|
||||
assert fs() == 'fg'
|
||||
assert fi() == 30002000200020002000
|
||||
assert ff() == 5.0
|
||||
|
||||
[case testMultiModuleTraceback]
|
||||
from other import fail2
|
||||
|
||||
def fail() -> None:
|
||||
fail2()
|
||||
[file other.py]
|
||||
def fail2() -> None:
|
||||
x = [1]
|
||||
x[2] = 2
|
||||
[file driver.py]
|
||||
import traceback
|
||||
import sys
|
||||
import native
|
||||
import other
|
||||
try:
|
||||
other.fail2()
|
||||
except IndexError:
|
||||
tb = sys.exc_info()[2]
|
||||
assert tb.tb_next.tb_frame.f_globals is other.__dict__
|
||||
traceback.print_exc()
|
||||
try:
|
||||
native.fail()
|
||||
except IndexError:
|
||||
tb = sys.exc_info()[2]
|
||||
assert tb.tb_next.tb_frame.f_globals is native.__dict__
|
||||
traceback.print_exc()
|
||||
[out]
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 6, in <module>
|
||||
other.fail2()
|
||||
File "other.py", line 3, in fail2
|
||||
x[2] = 2
|
||||
IndexError: list assignment index out of range
|
||||
Traceback (most recent call last):
|
||||
File "driver.py", line 12, in <module>
|
||||
native.fail()
|
||||
File "native.py", line 4, in fail
|
||||
fail2()
|
||||
File "other.py", line 3, in fail2
|
||||
x[2] = 2
|
||||
IndexError: list assignment index out of range
|
||||
|
||||
[case testMultiModuleCycle]
|
||||
if False:
|
||||
from typing import Final
|
||||
import other
|
||||
|
||||
x = int('0') # type: Final
|
||||
|
||||
def f1() -> int:
|
||||
return other.f2() + other.x
|
||||
|
||||
def f3() -> int:
|
||||
return 5
|
||||
[file other.py]
|
||||
if False:
|
||||
from typing import Final
|
||||
import native
|
||||
|
||||
x = int('0') # type: Final
|
||||
|
||||
def f2() -> int:
|
||||
return native.f3() + native.x
|
||||
[file driver.py]
|
||||
from native import f1
|
||||
assert f1() == 5
|
||||
|
||||
[case testMultiModuleCycleWithClasses]
|
||||
import other
|
||||
|
||||
class D: pass
|
||||
|
||||
def f() -> other.C:
|
||||
return other.C()
|
||||
|
||||
def g(c: other.C) -> D:
|
||||
return c.d
|
||||
|
||||
[file other.py]
|
||||
import native
|
||||
|
||||
class C:
|
||||
def __init__(self) -> None:
|
||||
self.d = native.D()
|
||||
|
||||
def h(d: native.D) -> None:
|
||||
pass
|
||||
|
||||
[file driver.py]
|
||||
from native import f, g
|
||||
from other import C, h
|
||||
|
||||
c = f()
|
||||
assert isinstance(c, C)
|
||||
assert g(c) is c.d
|
||||
h(c.d)
|
||||
|
||||
try:
|
||||
g(1)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
try:
|
||||
h(1)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
[case testMultiModuleCycleWithInheritance]
|
||||
import other
|
||||
|
||||
class Deriv1(other.Base1):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
class Base2:
|
||||
y: int
|
||||
def __init__(self) -> None:
|
||||
self.y = 2
|
||||
|
||||
[file other.py]
|
||||
from typing import Tuple
|
||||
import native
|
||||
|
||||
class Base1:
|
||||
a: Tuple[int, int]
|
||||
x: int
|
||||
def __init__(self) -> None:
|
||||
self.x = 1
|
||||
|
||||
def make_2() -> native.Base2:
|
||||
return native.Base2()
|
||||
|
||||
[file driver.py]
|
||||
from native import Deriv1
|
||||
from other import make_2
|
||||
a = Deriv1()
|
||||
assert a.x == 1
|
||||
b = make_2()
|
||||
assert b.y == 2
|
||||
|
||||
[case testMultiModuleTraitInheritance]
|
||||
from other import Base1, Base2
|
||||
|
||||
class Deriv1(Base1, Base2):
|
||||
pass
|
||||
|
||||
[file other.py]
|
||||
from mypy_extensions import trait
|
||||
|
||||
@trait
|
||||
class Base1:
|
||||
def foo(self) -> int: return 10
|
||||
@trait
|
||||
class Base2:
|
||||
def bar(self) -> int: return 12
|
||||
|
||||
[file driver.py]
|
||||
from native import Deriv1
|
||||
a = Deriv1()
|
||||
assert a.foo() == 10 and a.bar() == 12
|
||||
|
||||
|
||||
[case testImportCycleWithNonCompiledModule]
|
||||
import m
|
||||
|
||||
class C: pass
|
||||
|
||||
def f1() -> int:
|
||||
m.D()
|
||||
return m.f2()
|
||||
|
||||
def f3() -> int:
|
||||
return 2
|
||||
|
||||
[file m.py]
|
||||
# This module is NOT compiled
|
||||
import native
|
||||
|
||||
class D: pass
|
||||
|
||||
def f2() -> int:
|
||||
native.C()
|
||||
return native.f3()
|
||||
|
||||
[file driver.py]
|
||||
from native import f1
|
||||
|
||||
assert f1() == 2
|
||||
|
||||
[case testImportCycleWithTopLevelStatements]
|
||||
import other
|
||||
x = 1
|
||||
print(x)
|
||||
|
||||
[file other.py]
|
||||
import native
|
||||
x = 2
|
||||
print(x)
|
||||
|
||||
[file driver.py]
|
||||
import other
|
||||
print('-')
|
||||
import native
|
||||
print('>', native.x)
|
||||
print('>', other.x)
|
||||
|
||||
[out]
|
||||
1
|
||||
2
|
||||
-
|
||||
> 1
|
||||
> 2
|
||||
|
||||
[case testMultiModuleCycleIfMypy1]
|
||||
from other import foo, bar
|
||||
|
||||
class Foo:
|
||||
def foo(self) -> None:
|
||||
foo(self)
|
||||
class Bar:
|
||||
def bar(self) -> None:
|
||||
bar(self)
|
||||
|
||||
[file other.py]
|
||||
from typing_extensions import TYPE_CHECKING
|
||||
MYPY = False
|
||||
if MYPY:
|
||||
from native import Foo
|
||||
if TYPE_CHECKING:
|
||||
from native import Bar
|
||||
|
||||
def foo(x: 'Foo') -> None:
|
||||
pass
|
||||
def bar(x: 'Bar') -> None:
|
||||
pass
|
||||
|
||||
[file driver.py]
|
||||
from native import Foo, Bar
|
||||
Foo().foo()
|
||||
Bar().bar()
|
||||
|
||||
[case testMultiModuleCycleIfMypy2]
|
||||
MYPY = False
|
||||
if MYPY:
|
||||
from other import C
|
||||
|
||||
class D:
|
||||
def __init__(self) -> None:
|
||||
self.y = 1
|
||||
|
||||
def f(c: 'C') -> int:
|
||||
return c.x
|
||||
|
||||
[file other.py]
|
||||
from typing_extensions import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from native import D
|
||||
|
||||
class C:
|
||||
def __init__(self) -> None:
|
||||
self.x = 2
|
||||
|
||||
def g(d: 'D') -> int:
|
||||
return d.y
|
||||
|
||||
[file driver.py]
|
||||
from native import f, D
|
||||
from other import g, C
|
||||
|
||||
assert f(C()) == 2
|
||||
assert g(D()) == 1
|
||||
|
||||
try:
|
||||
f(D())
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
try:
|
||||
g(C())
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
[case testMultiModuleRelative]
|
||||
from package.a import f
|
||||
[file package/__init__.py]
|
||||
[file package/a.py]
|
||||
from . import b
|
||||
from .c import c3
|
||||
def f() -> None:
|
||||
print("Hello " + b.b2())
|
||||
print("Hello " + c3())
|
||||
[file package/b.py]
|
||||
def b2() -> str:
|
||||
return "moon!"
|
||||
[file package/c.py]
|
||||
def c3() -> str:
|
||||
return "sun!"
|
||||
|
||||
[file driver.py]
|
||||
from native import f
|
||||
f()
|
||||
[out]
|
||||
Hello moon!
|
||||
Hello sun!
|
||||
|
||||
[case testMultiModuleCrash]
|
||||
b = False
|
||||
if b:
|
||||
import other
|
||||
|
||||
def foo() -> None:
|
||||
try:
|
||||
other.x
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
[file other.py]
|
||||
x = 10
|
||||
|
||||
[file driver.py]
|
||||
from native import foo
|
||||
foo()
|
||||
|
||||
[case testTrivialIncremental]
|
||||
# separate: [(["other.py", "other_b.py"], "stuff")]
|
||||
from other import x
|
||||
from other_b import z
|
||||
y = x + z
|
||||
[file other.py]
|
||||
x = 1
|
||||
[file other.py.2]
|
||||
x = 2
|
||||
[file other_b.py]
|
||||
z = 1
|
||||
|
||||
[file driver.py]
|
||||
from native import y
|
||||
print(y)
|
||||
[out]
|
||||
2
|
||||
[out2]
|
||||
3
|
||||
[rechecked other, other_b]
|
||||
|
||||
[case testIncrementalCompilation1]
|
||||
import non_native
|
||||
from other_a import A
|
||||
from other_b import z
|
||||
|
||||
a = A()
|
||||
assert a.y == z
|
||||
|
||||
assert non_native.foo() == 0
|
||||
|
||||
[file other_a.py]
|
||||
from other_b import z
|
||||
from typing import Iterable
|
||||
|
||||
class A:
|
||||
def __init__(self) -> None:
|
||||
self.y = z
|
||||
[file other_a.py.2]
|
||||
from other_b import z
|
||||
from typing import Iterable
|
||||
|
||||
class A:
|
||||
def __init__(self) -> None:
|
||||
self.x = 'test'
|
||||
self.y = z
|
||||
[file other_b.py]
|
||||
import other_a
|
||||
|
||||
z = 10
|
||||
|
||||
def foo() -> 'other_a.A':
|
||||
return other_a.A()
|
||||
[file other_b.py.3]
|
||||
import other_a
|
||||
|
||||
z = 20
|
||||
|
||||
def foo() -> 'other_a.A':
|
||||
return other_a.A()
|
||||
|
||||
[file non_native.py]
|
||||
import other_a
|
||||
|
||||
def foo() -> int:
|
||||
return 0
|
||||
|
||||
[file non_native.py.4]
|
||||
import other_a
|
||||
|
||||
def foo() -> float:
|
||||
return 0
|
||||
|
||||
[file driver.py]
|
||||
from native import a
|
||||
print(a.y, getattr(a, 'x', None))
|
||||
|
||||
[out]
|
||||
10 None
|
||||
[out2]
|
||||
10 test
|
||||
[out3]
|
||||
20 test
|
||||
[out4]
|
||||
20 test
|
||||
|
||||
[rechecked other_a, other_b, native, non_native]
|
||||
[rechecked2 other_a, other_b]
|
||||
[rechecked3 native, non_native]
|
||||
|
||||
|
||||
-- This one tests a group that is not an SCC.
|
||||
[case testIncrementalCompilation2]
|
||||
# separate: [(["other_a.py", "other_b.py"], "stuff")]
|
||||
from other_a import A
|
||||
from other_b import z
|
||||
|
||||
a = A()
|
||||
assert a.y == z
|
||||
|
||||
[file other_a.py]
|
||||
from other_b import z
|
||||
|
||||
class A:
|
||||
def __init__(self) -> None:
|
||||
self.y = z
|
||||
[file other_a.py.2]
|
||||
from other_b import z
|
||||
|
||||
class A:
|
||||
def __init__(self) -> None:
|
||||
self.x = 'test'
|
||||
self.y = z
|
||||
|
||||
[file other_b.py]
|
||||
z = 10
|
||||
|
||||
[file driver.py]
|
||||
from native import a
|
||||
print(a.y, getattr(a, 'x', None))
|
||||
|
||||
[out]
|
||||
10 None
|
||||
[out2]
|
||||
10 test
|
||||
|
||||
[rechecked other_a, other_b, native]
|
||||
|
||||
[case testIncrementalCompilation3]
|
||||
from other import X
|
||||
Y = X
|
||||
def foo() -> int:
|
||||
return X
|
||||
|
||||
[file other.py]
|
||||
from typing_extensions import Final
|
||||
X: Final = 10
|
||||
|
||||
[file other.py.2]
|
||||
from typing_extensions import Final
|
||||
X: Final = 20
|
||||
|
||||
[file driver.py]
|
||||
import native
|
||||
import other
|
||||
assert native.Y == other.X
|
||||
assert native.foo() == other.X
|
||||
|
||||
[rechecked native, other]
|
||||
|
||||
-- This one tests a group changing
|
||||
[case testIncrementalCompilation4]
|
||||
# separate: [(["other_a.py", "other_b.py"], "stuff")]
|
||||
# separate2: []
|
||||
from other_a import A
|
||||
from other_b import z
|
||||
|
||||
a = A()
|
||||
assert a.y == z
|
||||
|
||||
[file other_a.py]
|
||||
from other_b import z
|
||||
|
||||
class A:
|
||||
def __init__(self) -> None:
|
||||
self.y = z
|
||||
|
||||
[file other_b.py]
|
||||
z = 10
|
||||
|
||||
[file wtvr.py.2]
|
||||
|
||||
[file driver.py]
|
||||
from native import a
|
||||
print(a.y, getattr(a, 'x', None))
|
||||
|
||||
[out]
|
||||
10 None
|
||||
[out2]
|
||||
10 None
|
||||
|
||||
[rechecked other_a, other_b, native]
|
||||
|
||||
-- This one tests cases where other modules *do not* need rechecked
|
||||
[case testIncrementalCompilation5]
|
||||
import other_a
|
||||
[file other_a.py]
|
||||
from other_b import f
|
||||
assert f(10) == 20
|
||||
[file other_a.py.2]
|
||||
from other_b import f
|
||||
assert f(20) == 40
|
||||
|
||||
[file other_b.py]
|
||||
def f(x: int) -> int:
|
||||
return x * 2
|
||||
|
||||
[file driver.py]
|
||||
import native
|
||||
|
||||
[rechecked other_a]
|
||||
|
||||
-- Delete one of the C files and make sure this forces recompilation
|
||||
[case testIncrementalCompilation6]
|
||||
import other_a
|
||||
assert other_a.foo() == 10
|
||||
[file other_a.py]
|
||||
def foo() -> int: return 10
|
||||
|
||||
[file build/__native_other_a.c]
|
||||
|
||||
[delete build/__native_other_a.c.2]
|
||||
|
||||
[file driver.py]
|
||||
import native
|
||||
|
||||
[rechecked native, other_a]
|
||||
|
||||
[case testSeparateCompilationWithUndefinedAttribute]
|
||||
from other_a import A
|
||||
|
||||
def f() -> None:
|
||||
a = A()
|
||||
if a.x == 5:
|
||||
print(a.y)
|
||||
print(a.m())
|
||||
else:
|
||||
assert a.x == 6
|
||||
try:
|
||||
print(a.y)
|
||||
except AttributeError:
|
||||
print('y undefined')
|
||||
else:
|
||||
assert False
|
||||
|
||||
try:
|
||||
print(a.m())
|
||||
except AttributeError:
|
||||
print('y undefined')
|
||||
else:
|
||||
assert False
|
||||
|
||||
[file other_a.py]
|
||||
from other_b import B
|
||||
|
||||
class A(B):
|
||||
def __init__(self) -> None:
|
||||
self.y = 9
|
||||
|
||||
[file other_a.py.2]
|
||||
from other_b import B
|
||||
|
||||
class A(B):
|
||||
x = 6
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
[file other_b.py]
|
||||
class B:
|
||||
x = 5
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.y = 7
|
||||
|
||||
def m(self) -> int:
|
||||
return self.y
|
||||
|
||||
[file driver.py]
|
||||
from native import f
|
||||
f()
|
||||
|
||||
[rechecked native, other_a]
|
||||
|
||||
[out]
|
||||
9
|
||||
9
|
||||
[out2]
|
||||
y undefined
|
||||
y undefined
|
||||
|
||||
[case testIncrementalCompilationWithDeletable]
|
||||
import other_a
|
||||
[file other_a.py]
|
||||
from other_b import C
|
||||
[file other_a.py.2]
|
||||
from other_b import C
|
||||
c = C()
|
||||
print(getattr(c, 'x', None))
|
||||
del c.x
|
||||
print(getattr(c, 'x', None))
|
||||
[file other_b.py]
|
||||
class C:
|
||||
__deletable__ = ['x']
|
||||
def __init__(self) -> None:
|
||||
self.x = 0
|
||||
[file driver.py]
|
||||
import native
|
||||
[out]
|
||||
[out2]
|
||||
0
|
||||
None
|
||||
@@ -0,0 +1,138 @@
|
||||
-- Some test code that tries to simulate important/interesting parts of mypy itself!
|
||||
[case testSimulateMypy]
|
||||
from mypy_extensions import trait
|
||||
from typing import List, TypeVar, cast, Generic
|
||||
from abc import abstractmethod
|
||||
import other_strconv as strconv
|
||||
#from other_visitor import ExpressionVisitor, StatementVisitor, NodeVisitor
|
||||
import other_visitor as visitor
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
############ nodes.py
|
||||
|
||||
class Context:
|
||||
def __init__(self) -> None:
|
||||
self.line = -1
|
||||
def set_line(self, line: int) -> None:
|
||||
self.line = line
|
||||
|
||||
class Node(Context):
|
||||
def accept(self, visitor: visitor.NodeVisitor[T]) -> T: return cast(T, None)
|
||||
def to_str(self) -> str:
|
||||
return self.accept(strconv.StrConv())
|
||||
|
||||
@trait
|
||||
class Statement(Node):
|
||||
def accept(self, visitor: visitor.StatementVisitor[T]) -> T: return cast(T, None)
|
||||
|
||||
@trait
|
||||
class Expression(Node):
|
||||
def accept(self, visitor: visitor.ExpressionVisitor[T]) -> T: return cast(T, None)
|
||||
|
||||
@trait
|
||||
class SymbolNode(Node):
|
||||
"""Nodes that can be stored in a symbol table."""
|
||||
@abstractmethod
|
||||
def name(self) -> str: return cast(str, None)
|
||||
|
||||
class FuncBase(Node):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.is_static = False
|
||||
|
||||
class Block(Statement):
|
||||
def __init__(self, stmts: List[Statement]) -> None:
|
||||
self.stmts = stmts
|
||||
|
||||
def accept(self, visitor: visitor.StatementVisitor[T]) -> T:
|
||||
return visitor.visit_block(self)
|
||||
|
||||
class ExprStmt(Statement):
|
||||
def __init__(self, expr: Expression) -> None:
|
||||
self.expr = expr
|
||||
|
||||
def accept(self, visitor: visitor.StatementVisitor[T]) -> T:
|
||||
return visitor.visit_expr_stmt(self)
|
||||
|
||||
class FuncItem(FuncBase):
|
||||
def __init__(self, body: Block) -> None:
|
||||
self.body = body
|
||||
|
||||
class FuncDef(FuncItem, SymbolNode, Statement):
|
||||
def __init__(self, name: str, body: Block) -> None:
|
||||
super().__init__(body)
|
||||
self._name = name
|
||||
def accept(self, visitor: visitor.StatementVisitor[T]) -> T:
|
||||
return visitor.visit_func_def(self)
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
class LambdaExpr(FuncItem, Expression):
|
||||
def accept(self, visitor: visitor.ExpressionVisitor[T]) -> T:
|
||||
return visitor.visit_lambda_expr(self)
|
||||
|
||||
def lol(x: Statement) -> int:
|
||||
return x.line
|
||||
|
||||
[file other_visitor.py]
|
||||
from mypy_extensions import trait
|
||||
from typing import TypeVar, cast, Generic
|
||||
from abc import abstractmethod
|
||||
import native as nodes
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
@trait
|
||||
class ExpressionVisitor(Generic[T]):
|
||||
@abstractmethod
|
||||
def visit_lambda_expr(self, o: 'nodes.LambdaExpr') -> T:
|
||||
return cast(T, None)
|
||||
|
||||
@trait
|
||||
class StatementVisitor(Generic[T]):
|
||||
@abstractmethod
|
||||
def visit_block(self, o: 'nodes.Block') -> T:
|
||||
return cast(T, None)
|
||||
|
||||
@abstractmethod
|
||||
def visit_func_def(self, o: 'nodes.FuncDef') -> T:
|
||||
return cast(T, None)
|
||||
|
||||
@abstractmethod
|
||||
def visit_expr_stmt(self, o: 'nodes.ExprStmt') -> T:
|
||||
return cast(T, None)
|
||||
|
||||
@trait
|
||||
class NodeVisitor(Generic[T], ExpressionVisitor[T], StatementVisitor[T]):
|
||||
pass
|
||||
|
||||
[file other_strconv.py]
|
||||
from typing import List
|
||||
import native as nodes
|
||||
from other_visitor import NodeVisitor
|
||||
|
||||
class StrConv(NodeVisitor[str]):
|
||||
def visit_block(self, b: nodes.Block) -> str:
|
||||
# we really need comprehensions!
|
||||
# TODO: PartialType unsupported
|
||||
things = [] # type: List[str]
|
||||
for s in b.stmts:
|
||||
things.append(s.accept(self))
|
||||
return "{" + "; ".join(things) + "}"
|
||||
|
||||
def visit_func_def(self, f: nodes.FuncDef) -> str:
|
||||
return "def " + f.name() + "(): " + f.body.accept(self)
|
||||
|
||||
def visit_expr_stmt(self, e: nodes.ExprStmt) -> str:
|
||||
return e.expr.accept(self)
|
||||
|
||||
def visit_lambda_expr(self, b: nodes.LambdaExpr) -> str:
|
||||
return "(fn: " + b.body.accept(self) + ")"
|
||||
|
||||
[file driver.py]
|
||||
from native import *
|
||||
|
||||
block = Block([Block([]), ExprStmt(LambdaExpr(Block([])))])
|
||||
fn = FuncDef('test', block)
|
||||
assert fn.to_str() == "def test(): {{}; (fn: {})}"
|
||||
@@ -0,0 +1,375 @@
|
||||
# Test cases for misc primitives (compile and run)
|
||||
#
|
||||
# Please only add tests that don't have an obvious place in type-specific test
|
||||
# files such as run-strings.test, run-lists.test, etc.
|
||||
|
||||
[case testGenericEquality]
|
||||
def eq(a: object, b: object) -> bool:
|
||||
if a == b:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def ne(a: object, b: object) -> bool:
|
||||
if a != b:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def f(o: object) -> bool:
|
||||
if [1, 2] == o:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
[file driver.py]
|
||||
from native import eq, ne, f
|
||||
assert eq('xz', 'x' + 'z')
|
||||
assert not eq('x', 'y')
|
||||
assert not ne('xz', 'x' + 'z')
|
||||
assert ne('x', 'y')
|
||||
assert f([1, 2])
|
||||
assert not f([2, 2])
|
||||
assert not f(1)
|
||||
|
||||
[case testGenericBinaryOps]
|
||||
from typing import Any
|
||||
def add(x: Any, y: Any) -> Any:
|
||||
return x + y
|
||||
def subtract(x: Any, y: Any) -> Any:
|
||||
return x - y
|
||||
def multiply(x: Any, y: Any) -> Any:
|
||||
return x * y
|
||||
def floor_div(x: Any, y: Any) -> Any:
|
||||
return x // y
|
||||
def true_div(x: Any, y: Any) -> Any:
|
||||
return x / y
|
||||
def remainder(x: Any, y: Any) -> Any:
|
||||
return x % y
|
||||
def power(x: Any, y: Any) -> Any:
|
||||
return x ** y
|
||||
def lshift(x: Any, y: Any) -> Any:
|
||||
return x << y
|
||||
def rshift(x: Any, y: Any) -> Any:
|
||||
return x >> y
|
||||
def num_and(x: Any, y: Any) -> Any:
|
||||
return x & y
|
||||
def num_xor(x: Any, y: Any) -> Any:
|
||||
return x ^ y
|
||||
def num_or(x: Any, y: Any) -> Any:
|
||||
return x | y
|
||||
def lt(x: Any, y: Any) -> Any:
|
||||
if x < y:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def le(x: Any, y: Any) -> Any:
|
||||
if x <= y:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def gt(x: Any, y: Any) -> Any:
|
||||
if x > y:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def ge(x: Any, y: Any) -> Any:
|
||||
if x >= y:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def contains(x: Any, y: Any) -> Any:
|
||||
if x in y:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def identity(x: Any, y: Any) -> Any:
|
||||
if x is y:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def disidentity(x: Any, y: Any) -> Any:
|
||||
if x is not y:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def not_eq_cond(a: Any, b: Any) -> bool:
|
||||
if not (a == b):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def eq2(a: Any, b: Any) -> bool:
|
||||
return a == b
|
||||
def slice1(x: Any) -> Any:
|
||||
return x[:]
|
||||
def slice2(x: Any, y: Any) -> Any:
|
||||
return x[y:]
|
||||
def slice3(x: Any, y: Any) -> Any:
|
||||
return x[:y]
|
||||
def slice4(x: Any, y: Any, z: Any) -> Any:
|
||||
return x[y:z]
|
||||
def slice5(x: Any, y: Any, z: Any, zz: Any) -> Any:
|
||||
return x[y:z:zz]
|
||||
[file driver.py]
|
||||
from native import *
|
||||
assert add(5, 6) == 11
|
||||
assert add('x', 'y') == 'xy'
|
||||
assert subtract(8, 3) == 5
|
||||
assert multiply(8, 3) == 24
|
||||
assert floor_div(8, 3) == 2
|
||||
assert true_div(7, 2) == 3.5
|
||||
assert remainder(11, 4) == 3
|
||||
assert remainder('%.3d', 5) == '005'
|
||||
assert remainder('%d-%s', (5, 'xy')) == '5-xy'
|
||||
assert power(3, 4) == 81
|
||||
assert lshift(5, 3) == 40
|
||||
assert rshift(41, 3) == 5
|
||||
assert num_and(99, 56) == 32
|
||||
assert num_xor(99, 56) == 91
|
||||
assert num_or(99, 56) == 123
|
||||
assert lt('a', 'b')
|
||||
assert not lt('a', 'a')
|
||||
assert not lt('b', 'a')
|
||||
assert not gt('a', 'b')
|
||||
assert not gt('a', 'a')
|
||||
assert gt('b', 'a')
|
||||
assert le('a', 'b')
|
||||
assert le('a', 'a')
|
||||
assert not le('b', 'a')
|
||||
assert not ge('a', 'b')
|
||||
assert ge('a', 'a')
|
||||
assert ge('b', 'a')
|
||||
assert contains('x', 'axb')
|
||||
assert not contains('X', 'axb')
|
||||
assert contains('x', {'x', 'y'})
|
||||
a = [1, 3, 5]
|
||||
assert slice1(a) == a
|
||||
assert slice1(a) is not a
|
||||
assert slice2(a, 1) == [3, 5]
|
||||
assert slice3(a, -1) == [1, 3]
|
||||
assert slice4(a, 1, -1) == [3]
|
||||
assert slice5(a, 2, 0, -1) == [5, 3]
|
||||
o1, o2 = object(), object()
|
||||
assert identity(o1, o1)
|
||||
assert not identity(o1, o2)
|
||||
assert not disidentity(o1, o1)
|
||||
assert disidentity(o1, o2)
|
||||
assert eq2('xz', 'x' + 'z')
|
||||
assert not eq2('x', 'y')
|
||||
assert not not_eq_cond('xz', 'x' + 'z')
|
||||
assert not_eq_cond('x', 'y')
|
||||
|
||||
[case testGenericMiscOps]
|
||||
from typing import Any
|
||||
def neg(x: Any) -> Any:
|
||||
return -x
|
||||
def pos(x: Any) -> Any:
|
||||
return +x
|
||||
def invert(x: Any) -> Any:
|
||||
return ~x
|
||||
def get_item(o: Any, k: Any) -> Any:
|
||||
return o[k]
|
||||
def set_item(o: Any, k: Any, v: Any) -> Any:
|
||||
o[k] = v
|
||||
[file driver.py]
|
||||
from native import *
|
||||
assert neg(6) == -6
|
||||
assert pos(6) == 6
|
||||
assert invert(6) == -7
|
||||
d = {'x': 5}
|
||||
assert get_item(d, 'x') == 5
|
||||
set_item(d, 'y', 6)
|
||||
assert d['y'] == 6
|
||||
|
||||
[case testAnyAttributeAndMethodAccess]
|
||||
from typing import Any, List
|
||||
class C:
|
||||
a: int
|
||||
def m(self, x: int, a: List[int]) -> int:
|
||||
return self.a + x + a[0]
|
||||
def get_a(x: Any) -> Any:
|
||||
return x.a
|
||||
def set_a(x: Any, y: Any) -> None:
|
||||
x.a = y
|
||||
def call_m(x: Any) -> Any:
|
||||
return x.m(1, [3])
|
||||
[file driver.py]
|
||||
from native import C, get_a, set_a, call_m
|
||||
class D:
|
||||
def m(self, x, a):
|
||||
return self.a + x + a[0]
|
||||
|
||||
c = C()
|
||||
c.a = 6
|
||||
d = D()
|
||||
d.a = 2
|
||||
assert get_a(c) == 6
|
||||
assert get_a(d) == 2
|
||||
assert call_m(c) == 10
|
||||
assert call_m(d) == 6
|
||||
set_a(c, 5)
|
||||
assert c.a == 5
|
||||
set_a(d, 4)
|
||||
assert d.a == 4
|
||||
try:
|
||||
get_a(object())
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
call_m(object())
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
set_a(object(), 5)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
[case testFloat]
|
||||
def assign_and_return_float_sum() -> float:
|
||||
f1 = 1.0
|
||||
f2 = 2.0
|
||||
f3 = 3.0
|
||||
return f1 * f2 + f3
|
||||
|
||||
def from_int(i: int) -> float:
|
||||
return float(i)
|
||||
|
||||
def to_int(x: float) -> int:
|
||||
return int(x)
|
||||
|
||||
def get_complex() -> complex:
|
||||
return 5.2j + 3.5 + 1j
|
||||
|
||||
[file driver.py]
|
||||
from native import assign_and_return_float_sum, from_int, to_int, get_complex
|
||||
sum = 0.0
|
||||
for i in range(10):
|
||||
sum += assign_and_return_float_sum()
|
||||
assert sum == 50.0
|
||||
|
||||
assert str(from_int(10)) == '10.0'
|
||||
assert str(to_int(3.14)) == '3'
|
||||
assert str(to_int(3)) == '3'
|
||||
assert get_complex() == 3.5 + 6.2j
|
||||
|
||||
[case testDel]
|
||||
from typing import List
|
||||
from testutil import assertRaises
|
||||
|
||||
def printDict(dict) -> None:
|
||||
l = list(dict.keys()) # type: List[str]
|
||||
l.sort()
|
||||
for key in l:
|
||||
print(key, dict[key])
|
||||
print("#########")
|
||||
|
||||
def delList() -> None:
|
||||
l = [1, 2, 3]
|
||||
print(tuple(l))
|
||||
del l[1]
|
||||
print(tuple(l))
|
||||
|
||||
def delDict() -> None:
|
||||
d = {"one":1, "two":2}
|
||||
printDict(d)
|
||||
del d["one"]
|
||||
printDict(d)
|
||||
|
||||
def delListMultiple() -> None:
|
||||
l = [1, 2, 3, 4, 5, 6, 7]
|
||||
print(tuple(l))
|
||||
del l[1], l[2], l[3]
|
||||
print(tuple(l))
|
||||
|
||||
def delDictMultiple() -> None:
|
||||
d = {"one":1, "two":2, "three":3, "four":4}
|
||||
printDict(d)
|
||||
del d["two"], d["four"]
|
||||
printDict(d)
|
||||
|
||||
class Dummy():
|
||||
__deletable__ = ('x', 'y')
|
||||
|
||||
def __init__(self, x: int, y: int) -> None:
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def delAttribute() -> None:
|
||||
dummy = Dummy(1, 2)
|
||||
del dummy.x
|
||||
with assertRaises(AttributeError):
|
||||
dummy.x
|
||||
|
||||
def delAttributeMultiple() -> None:
|
||||
dummy = Dummy(1, 2)
|
||||
del dummy.x, dummy.y
|
||||
with assertRaises(AttributeError):
|
||||
dummy.x
|
||||
with assertRaises(AttributeError):
|
||||
dummy.y
|
||||
|
||||
def delLocal(b: bool) -> int:
|
||||
dummy = 10
|
||||
if b:
|
||||
del dummy
|
||||
return dummy
|
||||
|
||||
def delLocalLoop() -> None:
|
||||
# Try deleting a local in a loop to make sure the control flow analysis works
|
||||
dummy = 1
|
||||
for i in range(10):
|
||||
print(dummy)
|
||||
dummy *= 2
|
||||
if i == 4:
|
||||
del dummy
|
||||
|
||||
global_var = 10
|
||||
del global_var
|
||||
|
||||
[file driver.py]
|
||||
from native import (
|
||||
delList, delDict, delListMultiple, delDictMultiple, delAttribute,
|
||||
delAttributeMultiple, delLocal, delLocalLoop,
|
||||
)
|
||||
import native
|
||||
from testutil import assertRaises
|
||||
|
||||
delList()
|
||||
delDict()
|
||||
delListMultiple()
|
||||
delDictMultiple()
|
||||
delAttribute()
|
||||
delAttributeMultiple()
|
||||
with assertRaises(AttributeError):
|
||||
native.global_var
|
||||
with assertRaises(NameError, 'local variable "dummy" referenced before assignment'):
|
||||
delLocal(True)
|
||||
assert delLocal(False) == 10
|
||||
with assertRaises(NameError, 'local variable "dummy" referenced before assignment'):
|
||||
delLocalLoop()
|
||||
[out]
|
||||
(1, 2, 3)
|
||||
(1, 3)
|
||||
one 1
|
||||
two 2
|
||||
#########
|
||||
two 2
|
||||
#########
|
||||
(1, 2, 3, 4, 5, 6, 7)
|
||||
(1, 3, 5, 7)
|
||||
four 4
|
||||
one 1
|
||||
three 3
|
||||
two 2
|
||||
#########
|
||||
one 1
|
||||
three 3
|
||||
#########
|
||||
1
|
||||
2
|
||||
4
|
||||
8
|
||||
16
|
||||
@@ -0,0 +1,159 @@
|
||||
-- Test cases for Python 3.7 features
|
||||
|
||||
[case testRunDataclass]
|
||||
import dataclasses
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Set, FrozenSet, List, Callable, Any
|
||||
|
||||
@dataclass
|
||||
class Person1:
|
||||
age : int
|
||||
name : str
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.name == 'robot'
|
||||
|
||||
def testBool(p: Person1) -> bool:
|
||||
if p:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@dataclass
|
||||
class Person1b(Person1):
|
||||
id: str = '000'
|
||||
|
||||
@dataclass
|
||||
class Person2:
|
||||
age : int
|
||||
name : str = field(default='robot')
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Person2b:
|
||||
age : int
|
||||
name : str = dataclasses.field(default='robot')
|
||||
|
||||
@dataclass(order = True)
|
||||
class Person3:
|
||||
age : int = field(default = 6)
|
||||
friendIDs : List[int] = field(default_factory = list)
|
||||
|
||||
def get_age(self) -> int:
|
||||
return (self.age)
|
||||
|
||||
def set_age(self, new_age : int) -> None:
|
||||
self.age = new_age
|
||||
|
||||
def add_friendID(self, fid : int) -> None:
|
||||
self.friendIDs.append(fid)
|
||||
|
||||
def get_friendIDs(self) -> List[int]:
|
||||
return self.friendIDs
|
||||
|
||||
def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]:
|
||||
def f(a: Any) -> int:
|
||||
return g(a) + 1
|
||||
return f
|
||||
|
||||
@dataclass
|
||||
class Person4:
|
||||
age : int
|
||||
_name : str = 'Bot'
|
||||
|
||||
@get_next_age
|
||||
def get_age(self) -> int:
|
||||
return self.age
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@dataclass
|
||||
class Person5:
|
||||
weight: float
|
||||
friends: Set[str] = field(default_factory=set)
|
||||
parents: FrozenSet[str] = frozenset()
|
||||
|
||||
[file other.py]
|
||||
from native import Person1, Person1b, Person2, Person3, Person4, Person5, testBool
|
||||
i1 = Person1(age = 5, name = 'robot')
|
||||
assert i1.age == 5
|
||||
assert i1.name == 'robot'
|
||||
assert testBool(i1) == True
|
||||
assert testBool(Person1(age = 5, name = 'robo')) == False
|
||||
i1b = Person1b(age = 5, name = 'robot')
|
||||
assert i1b.age == 5
|
||||
assert i1b.name == 'robot'
|
||||
assert testBool(i1b) == True
|
||||
assert testBool(Person1b(age = 5, name = 'robo')) == False
|
||||
i1c = Person1b(age = 20, name = 'robot', id = 'test')
|
||||
assert i1c.age == 20
|
||||
assert i1c.id == 'test'
|
||||
|
||||
i2 = Person2(age = 5)
|
||||
assert i2.age == 5
|
||||
assert i2.name == 'robot'
|
||||
i3 = Person2(age = 5, name = 'new_robot')
|
||||
assert i3.age == 5
|
||||
assert i3.name == 'new_robot'
|
||||
i4 = Person3()
|
||||
assert i4.age == 6
|
||||
assert i4.friendIDs == []
|
||||
i5 = Person3(age = 5)
|
||||
assert i5.age == 5
|
||||
assert i5.friendIDs == []
|
||||
i6 = Person3(age = 5, friendIDs = [1,2,3])
|
||||
assert i6.age == 5
|
||||
assert i6.friendIDs == [1,2,3]
|
||||
assert i6.get_age() == 5
|
||||
i6.set_age(10)
|
||||
assert i6.get_age() == 10
|
||||
i6.add_friendID(4)
|
||||
assert i6.get_friendIDs() == [1,2,3,4]
|
||||
i7 = Person4(age = 5)
|
||||
assert i7.get_age() == 6
|
||||
i7.age += 3
|
||||
assert i7.age == 8
|
||||
assert i7.name == 'Bot'
|
||||
i8 = Person3(age = 1, friendIDs = [1,2])
|
||||
i9 = Person3(age = 1, friendIDs = [1,2])
|
||||
assert i8 == i9
|
||||
i8.age = 2
|
||||
assert i8 > i9
|
||||
|
||||
assert Person1.__annotations__ == {'age': int, 'name': str}
|
||||
assert Person2.__annotations__ == {'age': int, 'name': str}
|
||||
assert Person5.__annotations__ == {'weight': float, 'friends': set,
|
||||
'parents': frozenset}
|
||||
|
||||
[file driver.py]
|
||||
import sys
|
||||
|
||||
# Dataclasses introduced in 3.7
|
||||
version = sys.version_info[:2]
|
||||
if version[0] < 3 or version[1] < 7:
|
||||
exit()
|
||||
|
||||
# Run the tests in both interpreted and compiled mode
|
||||
import other
|
||||
import other_interpreted
|
||||
|
||||
# Test for an exceptional cases
|
||||
from testutil import assertRaises
|
||||
from native import Person1, Person1b, Person3
|
||||
from types import BuiltinMethodType
|
||||
|
||||
with assertRaises(TypeError, "missing 1 required positional argument"):
|
||||
Person1(0)
|
||||
|
||||
with assertRaises(TypeError, "missing 2 required positional arguments"):
|
||||
Person1b()
|
||||
|
||||
with assertRaises(TypeError, "int object expected; got str"):
|
||||
Person1('nope', 'test')
|
||||
|
||||
p = Person1(0, 'test')
|
||||
with assertRaises(TypeError, "int object expected; got str"):
|
||||
p.age = 'nope'
|
||||
|
||||
assert isinstance(Person3().get_age, BuiltinMethodType)
|
||||
@@ -0,0 +1,88 @@
|
||||
-- Test cases for Python 3.8 features
|
||||
|
||||
[case testWalrus1]
|
||||
from typing import Optional
|
||||
|
||||
def foo(x: int) -> Optional[int]:
|
||||
if x < 0:
|
||||
return None
|
||||
return x
|
||||
|
||||
def test(x: int) -> str:
|
||||
if (n := foo(x)) is not None:
|
||||
return str(x)
|
||||
else:
|
||||
return "<fail>"
|
||||
|
||||
[file driver.py]
|
||||
from native import test
|
||||
|
||||
assert test(10) == "10"
|
||||
assert test(-1) == "<fail>"
|
||||
|
||||
|
||||
[case testWalrus2]
|
||||
from typing import Optional, Tuple, List
|
||||
|
||||
class Node:
|
||||
def __init__(self, val: int, next: Optional['Node']) -> None:
|
||||
self.val = val
|
||||
self.next = next
|
||||
|
||||
def pairs(nobe: Optional[Node]) -> List[Tuple[int, int]]:
|
||||
if nobe is None:
|
||||
return []
|
||||
l = []
|
||||
while next := nobe.next:
|
||||
l.append((nobe.val, next.val))
|
||||
nobe = next
|
||||
return l
|
||||
|
||||
def make(l: List[int]) -> Optional[Node]:
|
||||
cur: Optional[Node] = None
|
||||
for x in reversed(l):
|
||||
cur = Node(x, cur)
|
||||
return cur
|
||||
|
||||
[file driver.py]
|
||||
from native import Node, make, pairs
|
||||
|
||||
assert pairs(make([1,2,3])) == [(1,2), (2,3)]
|
||||
assert pairs(make([1])) == []
|
||||
assert pairs(make([])) == []
|
||||
|
||||
[case testFStrings]
|
||||
from datetime import datetime
|
||||
|
||||
def test_fstring_equal_sign() -> None:
|
||||
today = datetime(year=2017, month=1, day=27)
|
||||
assert f"{today=:%B %d, %Y}" == 'today=January 27, 2017' # using date format specifier and debugging
|
||||
|
||||
foo = "bar"
|
||||
assert f"{ foo = }" == " foo = 'bar'" # preserves whitespace
|
||||
|
||||
line = "The mill's closed"
|
||||
assert f"{line = }" == 'line = "The mill\'s closed"'
|
||||
assert f"{line = :20}" == "line = The mill's closed "
|
||||
assert f"{line = !r:20}" == 'line = "The mill\'s closed" '
|
||||
|
||||
[case testMethodOverrideDefaultPosOnly1]
|
||||
class Foo:
|
||||
def f(self, x: int=20, /, *, z: int=10) -> None:
|
||||
pass
|
||||
|
||||
class Bar(Foo):
|
||||
def f(self, *args: int, **kwargs: int) -> None:
|
||||
print("stuff", args, kwargs)
|
||||
|
||||
z: Foo = Bar()
|
||||
z.f(1, z=50)
|
||||
z.f()
|
||||
z.f(1)
|
||||
z.f(z=50)
|
||||
|
||||
[out]
|
||||
stuff (1,) {'z': 50}
|
||||
stuff () {}
|
||||
stuff (1,) {}
|
||||
stuff () {'z': 50}
|
||||
150
venv/lib/python3.12/site-packages/mypyc/test-data/run-sets.test
Normal file
150
venv/lib/python3.12/site-packages/mypyc/test-data/run-sets.test
Normal file
@@ -0,0 +1,150 @@
|
||||
# Test cases for sets (compile and run)
|
||||
|
||||
[case testSets]
|
||||
from typing import Set, List
|
||||
def instantiateLiteral() -> Set[int]:
|
||||
return {1, 2, 3, 5, 8}
|
||||
|
||||
def fromIterator() -> List[Set[int]]:
|
||||
a = set([1, 3, 5])
|
||||
b = set((1, 3, 5))
|
||||
c = set({1: '1', 3: '3', 5: '5'})
|
||||
d = set(x for x in range(1, 6, 2))
|
||||
e = set((x for x in range(1, 6, 2)))
|
||||
return [a, b, c, d, e]
|
||||
|
||||
def fromIterator2() -> Set[int]:
|
||||
tmp_list = [1, 2, 3, 4, 5]
|
||||
return set((x + 1) for x in ((y * 10) for y in (z for z in tmp_list if z < 4)))
|
||||
|
||||
def addIncrementing(s : Set[int]) -> None:
|
||||
for a in [1, 2, 3]:
|
||||
if a not in s:
|
||||
s.add(a)
|
||||
return
|
||||
|
||||
def replaceWith1(s : Set[int]) -> None:
|
||||
s.clear()
|
||||
s.add(1)
|
||||
|
||||
def remove1(s : Set[int]) -> None:
|
||||
s.remove(1)
|
||||
|
||||
def discard1(s: Set[int]) -> None:
|
||||
s.discard(1)
|
||||
|
||||
def pop(s : Set[int]) -> int:
|
||||
return s.pop()
|
||||
|
||||
def update(s: Set[int], x: List[int]) -> None:
|
||||
s.update(x)
|
||||
|
||||
[file driver.py]
|
||||
from native import instantiateLiteral
|
||||
from testutil import assertRaises
|
||||
|
||||
val = instantiateLiteral()
|
||||
assert 1 in val
|
||||
assert 2 in val
|
||||
assert 3 in val
|
||||
assert 5 in val
|
||||
assert 8 in val
|
||||
assert len(val) == 5
|
||||
assert val == {1, 2, 3, 5, 8}
|
||||
s = 0
|
||||
for i in val:
|
||||
s += i
|
||||
assert s == 19
|
||||
|
||||
from native import fromIterator
|
||||
sets = fromIterator()
|
||||
for s in sets:
|
||||
assert s == {1, 3, 5}
|
||||
|
||||
from native import fromIterator2
|
||||
s = fromIterator2()
|
||||
assert s == {11, 21, 31}
|
||||
|
||||
from native import addIncrementing
|
||||
s = set()
|
||||
addIncrementing(s)
|
||||
assert s == {1}
|
||||
addIncrementing(s)
|
||||
assert s == {1, 2}
|
||||
addIncrementing(s)
|
||||
assert s == {1, 2, 3}
|
||||
|
||||
from native import replaceWith1
|
||||
s = {3, 7, 12}
|
||||
replaceWith1(s)
|
||||
assert s == {1}
|
||||
|
||||
from native import remove1
|
||||
import traceback
|
||||
s = {1, 4, 6}
|
||||
remove1(s)
|
||||
assert s == {4, 6}
|
||||
with assertRaises(KeyError, '1'):
|
||||
remove1(s)
|
||||
|
||||
from native import discard1
|
||||
s = {1, 4, 6}
|
||||
discard1(s)
|
||||
assert s == {4, 6}
|
||||
discard1(s)
|
||||
assert s == {4, 6}
|
||||
|
||||
from native import pop
|
||||
s = {1, 2, 3}
|
||||
x = pop(s)
|
||||
assert len(s) == 2
|
||||
assert x in [1, 2, 3]
|
||||
y = pop(s)
|
||||
assert len(s) == 1
|
||||
assert y in [1, 2, 3]
|
||||
assert x != y
|
||||
z = pop(s)
|
||||
assert len(s) == 0
|
||||
assert z in [1, 2, 3]
|
||||
assert x != z
|
||||
assert y != z
|
||||
with assertRaises(KeyError, 'pop from an empty set'):
|
||||
pop(s)
|
||||
|
||||
from native import update
|
||||
s = {1, 2, 3}
|
||||
update(s, [5, 4, 3])
|
||||
assert s == {1, 2, 3, 4, 5}
|
||||
|
||||
[case testPrecomputedFrozenSets]
|
||||
from typing import Any
|
||||
from typing_extensions import Final
|
||||
|
||||
CONST: Final = "CONST"
|
||||
non_const = "non_const"
|
||||
|
||||
def main_set(item: Any) -> bool:
|
||||
return item in {None, False, 1, 2.0, "3", b"4", 5j, (6,), ((7,),), (), CONST}
|
||||
|
||||
def main_negated_set(item: Any) -> bool:
|
||||
return item not in {None, False, 1, 2.0, "3", b"4", 5j, (6,), ((7,),), (), CONST}
|
||||
|
||||
def non_final_name_set(item: Any) -> bool:
|
||||
return item in {non_const}
|
||||
|
||||
s = set()
|
||||
for i in {None, False, 1, 2.0, "3", b"4", 5j, (6,), CONST}:
|
||||
s.add(i)
|
||||
|
||||
def test_in_set() -> None:
|
||||
for item in (None, False, 1, 2.0, "3", b"4", 5j, (6,), ((7,),), (), CONST):
|
||||
assert main_set(item), f"{item!r} should be in set_main"
|
||||
assert not main_negated_set(item), item
|
||||
|
||||
global non_const
|
||||
assert non_final_name_set(non_const)
|
||||
non_const = "updated"
|
||||
assert non_final_name_set("updated")
|
||||
|
||||
def test_for_set() -> None:
|
||||
assert not s ^ {None, False, 1, 2.0, "3", b"4", 5j, (6,), CONST}, s
|
||||
@@ -0,0 +1,698 @@
|
||||
# Test cases related to the functools.singledispatch decorator
|
||||
# Most of these tests are marked as xfails because mypyc doesn't support singledispatch yet
|
||||
# (These tests will be re-enabled when mypyc supports singledispatch)
|
||||
|
||||
[case testSpecializedImplementationUsed]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
return False
|
||||
|
||||
@fun.register
|
||||
def fun_specialized(arg: str) -> bool:
|
||||
return True
|
||||
|
||||
def test_specialize() -> None:
|
||||
assert fun('a')
|
||||
assert not fun(3)
|
||||
|
||||
[case testSubclassesOfExpectedTypeUseSpecialized]
|
||||
from functools import singledispatch
|
||||
class A: pass
|
||||
class B(A): pass
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
return False
|
||||
|
||||
@fun.register
|
||||
def fun_specialized(arg: A) -> bool:
|
||||
return True
|
||||
|
||||
def test_specialize() -> None:
|
||||
assert fun(B())
|
||||
assert fun(A())
|
||||
|
||||
[case testSuperclassImplementationNotUsedWhenSubclassHasImplementation]
|
||||
from functools import singledispatch
|
||||
class A: pass
|
||||
class B(A): pass
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
# shouldn't be using this
|
||||
assert False
|
||||
|
||||
@fun.register
|
||||
def fun_specialized(arg: A) -> bool:
|
||||
return False
|
||||
|
||||
@fun.register
|
||||
def fun_specialized2(arg: B) -> bool:
|
||||
return True
|
||||
|
||||
def test_specialize() -> None:
|
||||
assert fun(B())
|
||||
assert not fun(A())
|
||||
|
||||
[case testMultipleUnderscoreFunctionsIsntError]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> str:
|
||||
return 'default'
|
||||
|
||||
@fun.register
|
||||
def _(arg: str) -> str:
|
||||
return 'str'
|
||||
|
||||
@fun.register
|
||||
def _(arg: int) -> str:
|
||||
return 'int'
|
||||
|
||||
# extra function to make sure all 3 underscore functions aren't treated as one OverloadedFuncDef
|
||||
def a(b): pass
|
||||
|
||||
@fun.register
|
||||
def _(arg: list) -> str:
|
||||
return 'list'
|
||||
|
||||
def test_singledispatch() -> None:
|
||||
assert fun(0) == 'int'
|
||||
assert fun('a') == 'str'
|
||||
assert fun([1, 2]) == 'list'
|
||||
assert fun({'a': 'b'}) == 'default'
|
||||
|
||||
[case testCanRegisterCompiledClasses]
|
||||
from functools import singledispatch
|
||||
class A: pass
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
return False
|
||||
@fun.register
|
||||
def fun_specialized(arg: A) -> bool:
|
||||
return True
|
||||
|
||||
def test_singledispatch() -> None:
|
||||
assert fun(A())
|
||||
assert not fun(1)
|
||||
|
||||
[case testTypeUsedAsArgumentToRegister]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
return False
|
||||
|
||||
@fun.register(int)
|
||||
def fun_specialized(arg) -> bool:
|
||||
return True
|
||||
|
||||
def test_singledispatch() -> None:
|
||||
assert fun(1)
|
||||
assert not fun('a')
|
||||
|
||||
[case testUseRegisterAsAFunction]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
return False
|
||||
|
||||
def fun_specialized_impl(arg) -> bool:
|
||||
return True
|
||||
|
||||
fun.register(int, fun_specialized_impl)
|
||||
|
||||
def test_singledispatch() -> None:
|
||||
assert fun(0)
|
||||
assert not fun('a')
|
||||
|
||||
[case testRegisterDoesntChangeFunction]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
return False
|
||||
|
||||
@fun.register(int)
|
||||
def fun_specialized(arg) -> bool:
|
||||
return True
|
||||
|
||||
def test_singledispatch() -> None:
|
||||
assert fun_specialized('a')
|
||||
|
||||
# TODO: turn this into a mypy error
|
||||
[case testNoneIsntATypeWhenUsedAsArgumentToRegister]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
return False
|
||||
|
||||
try:
|
||||
@fun.register
|
||||
def fun_specialized(arg: None) -> bool:
|
||||
return True
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
[case testRegisteringTheSameFunctionSeveralTimes]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
return False
|
||||
|
||||
@fun.register(int)
|
||||
@fun.register(str)
|
||||
def fun_specialized(arg) -> bool:
|
||||
return True
|
||||
|
||||
def test_singledispatch() -> None:
|
||||
assert fun(0)
|
||||
assert fun('a')
|
||||
assert not fun([1, 2])
|
||||
|
||||
[case testTypeIsAnABC]
|
||||
from functools import singledispatch
|
||||
from collections.abc import Mapping
|
||||
|
||||
@singledispatch
|
||||
def fun(arg) -> bool:
|
||||
return False
|
||||
|
||||
@fun.register
|
||||
def fun_specialized(arg: Mapping) -> bool:
|
||||
return True
|
||||
|
||||
def test_singledispatch() -> None:
|
||||
assert not fun(1)
|
||||
assert fun({'a': 'b'})
|
||||
|
||||
[case testSingleDispatchMethod-xfail]
|
||||
from functools import singledispatchmethod
|
||||
class A:
|
||||
@singledispatchmethod
|
||||
def fun(self, arg) -> str:
|
||||
return 'default'
|
||||
|
||||
@fun.register
|
||||
def fun_int(self, arg: int) -> str:
|
||||
return 'int'
|
||||
|
||||
@fun.register
|
||||
def fun_str(self, arg: str) -> str:
|
||||
return 'str'
|
||||
|
||||
def test_singledispatchmethod() -> None:
|
||||
x = A()
|
||||
assert x.fun(5) == 'int'
|
||||
assert x.fun('a') == 'str'
|
||||
assert x.fun([1, 2]) == 'default'
|
||||
|
||||
[case testSingleDispatchMethodWithOtherDecorator-xfail]
|
||||
from functools import singledispatchmethod
|
||||
class A:
|
||||
@singledispatchmethod
|
||||
@staticmethod
|
||||
def fun(arg) -> str:
|
||||
return 'default'
|
||||
|
||||
@fun.register
|
||||
@staticmethod
|
||||
def fun_int(arg: int) -> str:
|
||||
return 'int'
|
||||
|
||||
@fun.register
|
||||
@staticmethod
|
||||
def fun_str(arg: str) -> str:
|
||||
return 'str'
|
||||
|
||||
def test_singledispatchmethod() -> None:
|
||||
x = A()
|
||||
assert x.fun(5) == 'int'
|
||||
assert x.fun('a') == 'str'
|
||||
assert x.fun([1, 2]) == 'default'
|
||||
|
||||
[case testSingledispatchTreeSumAndEqual]
|
||||
from functools import singledispatch
|
||||
|
||||
class Tree:
|
||||
pass
|
||||
class Leaf(Tree):
|
||||
pass
|
||||
class Node(Tree):
|
||||
def __init__(self, value: int, left: Tree, right: Tree) -> None:
|
||||
self.value = value
|
||||
self.left = left
|
||||
self.right = right
|
||||
|
||||
@singledispatch
|
||||
def calc_sum(x: Tree) -> int:
|
||||
raise TypeError('invalid type for x')
|
||||
|
||||
@calc_sum.register
|
||||
def _(x: Leaf) -> int:
|
||||
return 0
|
||||
|
||||
@calc_sum.register
|
||||
def _(x: Node) -> int:
|
||||
return x.value + calc_sum(x.left) + calc_sum(x.right)
|
||||
|
||||
@singledispatch
|
||||
def equal(to_compare: Tree, known: Tree) -> bool:
|
||||
raise TypeError('invalid type for x')
|
||||
|
||||
@equal.register
|
||||
def _(to_compare: Leaf, known: Tree) -> bool:
|
||||
return isinstance(known, Leaf)
|
||||
|
||||
@equal.register
|
||||
def _(to_compare: Node, known: Tree) -> bool:
|
||||
if isinstance(known, Node):
|
||||
if to_compare.value != known.value:
|
||||
return False
|
||||
else:
|
||||
return equal(to_compare.left, known.left) and equal(to_compare.right, known.right)
|
||||
return False
|
||||
|
||||
def build(n: int) -> Tree:
|
||||
if n == 0:
|
||||
return Leaf()
|
||||
return Node(n, build(n - 1), build(n - 1))
|
||||
|
||||
def test_sum_and_equal():
|
||||
tree = build(5)
|
||||
tree2 = build(5)
|
||||
tree2.right.right.right.value = 10
|
||||
assert calc_sum(tree) == 57
|
||||
assert calc_sum(tree2) == 65
|
||||
assert equal(tree, tree)
|
||||
assert not equal(tree, tree2)
|
||||
tree3 = build(4)
|
||||
assert not equal(tree, tree3)
|
||||
|
||||
[case testSimulateMypySingledispatch]
|
||||
from functools import singledispatch
|
||||
from mypy_extensions import trait
|
||||
from typing import Iterator, Union, TypeVar, Any, List, Type
|
||||
# based on use of singledispatch in stubtest.py
|
||||
class Error:
|
||||
def __init__(self, msg: str) -> None:
|
||||
self.msg = msg
|
||||
|
||||
@trait
|
||||
class Node: pass
|
||||
|
||||
class MypyFile(Node): pass
|
||||
class TypeInfo(Node): pass
|
||||
|
||||
|
||||
@trait
|
||||
class SymbolNode(Node): pass
|
||||
@trait
|
||||
class Expression(Node): pass
|
||||
class TypeVarLikeExpr(SymbolNode, Expression): pass
|
||||
class TypeVarExpr(TypeVarLikeExpr): pass
|
||||
class TypeAlias(SymbolNode): pass
|
||||
|
||||
class Missing: pass
|
||||
MISSING = Missing()
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
MaybeMissing = Union[T, Missing]
|
||||
|
||||
@singledispatch
|
||||
def verify(stub: Node, a: MaybeMissing[Any], b: List[str]) -> Iterator[Error]:
|
||||
yield Error('unknown node type')
|
||||
|
||||
@verify.register(MypyFile)
|
||||
def verify_mypyfile(stub: MypyFile, a: MaybeMissing[int], b: List[str]) -> Iterator[Error]:
|
||||
if isinstance(a, Missing):
|
||||
yield Error("shouldn't be missing")
|
||||
return
|
||||
if not isinstance(a, int):
|
||||
# this check should be unnecessary because of the type signature and the previous check,
|
||||
# but stubtest.py has this check
|
||||
yield Error("should be an int")
|
||||
return
|
||||
yield from verify(TypeInfo(), str, ['abc', 'def'])
|
||||
|
||||
@verify.register(TypeInfo)
|
||||
def verify_typeinfo(stub: TypeInfo, a: MaybeMissing[Type[Any]], b: List[str]) -> Iterator[Error]:
|
||||
yield Error('in TypeInfo')
|
||||
yield Error('hello')
|
||||
|
||||
@verify.register(TypeVarExpr)
|
||||
def verify_typevarexpr(stub: TypeVarExpr, a: MaybeMissing[Any], b: List[str]) -> Iterator[Error]:
|
||||
if False:
|
||||
yield None
|
||||
|
||||
def verify_list(stub, a, b) -> List[str]:
|
||||
"""Helper function that converts iterator of errors to list of messages"""
|
||||
return list(err.msg for err in verify(stub, a, b))
|
||||
|
||||
def test_verify() -> None:
|
||||
assert verify_list(TypeAlias(), 'a', ['a', 'b']) == ['unknown node type']
|
||||
assert verify_list(MypyFile(), MISSING, ['a', 'b']) == ["shouldn't be missing"]
|
||||
assert verify_list(MypyFile(), 5, ['a', 'b']) == ['in TypeInfo', 'hello']
|
||||
assert verify_list(TypeInfo(), str, ['a', 'b']) == ['in TypeInfo', 'hello']
|
||||
assert verify_list(TypeVarExpr(), 'a', ['x', 'y']) == []
|
||||
|
||||
|
||||
[case testArgsInRegisteredImplNamedDifferentlyFromMainFunction]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def f(a) -> bool:
|
||||
return False
|
||||
|
||||
@f.register
|
||||
def g(b: int) -> bool:
|
||||
return True
|
||||
|
||||
def test_singledispatch():
|
||||
assert f(5)
|
||||
assert not f('a')
|
||||
|
||||
[case testKeywordArguments]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def f(arg, *, kwarg: int = 0) -> int:
|
||||
return kwarg + 10
|
||||
|
||||
@f.register
|
||||
def g(arg: int, *, kwarg: int = 5) -> int:
|
||||
return kwarg - 10
|
||||
|
||||
def test_keywords():
|
||||
assert f('a') == 10
|
||||
assert f('a', kwarg=3) == 13
|
||||
assert f('a', kwarg=7) == 17
|
||||
|
||||
assert f(1) == -5
|
||||
assert f(1, kwarg=4) == -6
|
||||
assert f(1, kwarg=6) == -4
|
||||
|
||||
[case testGeneratorAndMultipleTypesOfIterable]
|
||||
from functools import singledispatch
|
||||
from typing import *
|
||||
|
||||
@singledispatch
|
||||
def f(arg: Any) -> Iterable[int]:
|
||||
yield 1
|
||||
|
||||
@f.register
|
||||
def g(arg: str) -> Iterable[int]:
|
||||
return [0]
|
||||
|
||||
def test_iterables():
|
||||
assert f(1) != [1]
|
||||
assert list(f(1)) == [1]
|
||||
assert f('a') == [0]
|
||||
|
||||
[case testRegisterUsedAtSameTimeAsOtherDecorators]
|
||||
from functools import singledispatch
|
||||
from typing import TypeVar
|
||||
|
||||
class A: pass
|
||||
class B: pass
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
def decorator(f: T) -> T:
|
||||
return f
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> int:
|
||||
return 0
|
||||
|
||||
@f.register
|
||||
@decorator
|
||||
def h(arg: str) -> int:
|
||||
return 2
|
||||
|
||||
def test_singledispatch():
|
||||
assert f(1) == 0
|
||||
assert f('a') == 2
|
||||
|
||||
[case testDecoratorModifiesFunction]
|
||||
from functools import singledispatch
|
||||
from typing import Callable, Any
|
||||
|
||||
class A: pass
|
||||
|
||||
def decorator(f: Callable[[Any], int]) -> Callable[[Any], int]:
|
||||
def wrapper(x) -> int:
|
||||
return f(x) * 7
|
||||
return wrapper
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> int:
|
||||
return 10
|
||||
|
||||
@f.register
|
||||
@decorator
|
||||
def h(arg: str) -> int:
|
||||
return 5
|
||||
|
||||
|
||||
def test_singledispatch():
|
||||
assert f('a') == 35
|
||||
assert f(A()) == 10
|
||||
|
||||
[case testMoreSpecificTypeBeforeLessSpecificType]
|
||||
from functools import singledispatch
|
||||
class A: pass
|
||||
class B(A): pass
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> str:
|
||||
return 'default'
|
||||
|
||||
@f.register
|
||||
def g(arg: B) -> str:
|
||||
return 'b'
|
||||
|
||||
@f.register
|
||||
def h(arg: A) -> str:
|
||||
return 'a'
|
||||
|
||||
def test_singledispatch():
|
||||
assert f(B()) == 'b'
|
||||
assert f(A()) == 'a'
|
||||
assert f(5) == 'default'
|
||||
|
||||
[case testMultipleRelatedClassesBeingRegistered]
|
||||
from functools import singledispatch
|
||||
|
||||
class A: pass
|
||||
class B(A): pass
|
||||
class C(B): pass
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> str: return 'default'
|
||||
|
||||
@f.register
|
||||
def _(arg: A) -> str: return 'a'
|
||||
|
||||
@f.register
|
||||
def _(arg: C) -> str: return 'c'
|
||||
|
||||
@f.register
|
||||
def _(arg: B) -> str: return 'b'
|
||||
|
||||
def test_singledispatch():
|
||||
assert f(A()) == 'a'
|
||||
assert f(B()) == 'b'
|
||||
assert f(C()) == 'c'
|
||||
assert f(1) == 'default'
|
||||
|
||||
[case testRegisteredImplementationsInDifferentFiles]
|
||||
from other_a import f, A, B, C
|
||||
@f.register
|
||||
def a(arg: A) -> int:
|
||||
return 2
|
||||
|
||||
@f.register
|
||||
def _(arg: C) -> int:
|
||||
return 3
|
||||
|
||||
def test_singledispatch():
|
||||
assert f(B()) == 1
|
||||
assert f(A()) == 2
|
||||
assert f(C()) == 3
|
||||
assert f(1) == 0
|
||||
|
||||
[file other_a.py]
|
||||
from functools import singledispatch
|
||||
|
||||
class A: pass
|
||||
class B(A): pass
|
||||
class C(B): pass
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> int:
|
||||
return 0
|
||||
|
||||
@f.register
|
||||
def g(arg: B) -> int:
|
||||
return 1
|
||||
|
||||
[case testOrderCanOnlyBeDeterminedFromMRONotIsinstanceChecks]
|
||||
from mypy_extensions import trait
|
||||
from functools import singledispatch
|
||||
|
||||
@trait
|
||||
class A: pass
|
||||
@trait
|
||||
class B: pass
|
||||
class AB(A, B): pass
|
||||
class BA(B, A): pass
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> str:
|
||||
return "default"
|
||||
pass
|
||||
|
||||
@f.register
|
||||
def fa(arg: A) -> str:
|
||||
return "a"
|
||||
|
||||
@f.register
|
||||
def fb(arg: B) -> str:
|
||||
return "b"
|
||||
|
||||
def test_singledispatch():
|
||||
assert f(AB()) == "a"
|
||||
assert f(BA()) == "b"
|
||||
|
||||
[case testCallingFunctionBeforeAllImplementationsRegistered]
|
||||
from functools import singledispatch
|
||||
|
||||
class A: pass
|
||||
class B(A): pass
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> str:
|
||||
return 'default'
|
||||
|
||||
assert f(A()) == 'default'
|
||||
assert f(B()) == 'default'
|
||||
assert f(1) == 'default'
|
||||
|
||||
@f.register
|
||||
def g(arg: A) -> str:
|
||||
return 'a'
|
||||
|
||||
assert f(A()) == 'a'
|
||||
assert f(B()) == 'a'
|
||||
assert f(1) == 'default'
|
||||
|
||||
@f.register
|
||||
def _(arg: B) -> str:
|
||||
return 'b'
|
||||
|
||||
assert f(A()) == 'a'
|
||||
assert f(B()) == 'b'
|
||||
assert f(1) == 'default'
|
||||
|
||||
|
||||
[case testDynamicallyRegisteringFunctionFromInterpretedCode]
|
||||
from functools import singledispatch
|
||||
|
||||
class A: pass
|
||||
class B(A): pass
|
||||
class C(B): pass
|
||||
class D(C): pass
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> str:
|
||||
return "default"
|
||||
|
||||
@f.register
|
||||
def _(arg: B) -> str:
|
||||
return 'b'
|
||||
|
||||
[file register_impl.py]
|
||||
from native import f, A, B, C
|
||||
|
||||
@f.register(A)
|
||||
def a(arg) -> str:
|
||||
return 'a'
|
||||
|
||||
@f.register
|
||||
def c(arg: C) -> str:
|
||||
return 'c'
|
||||
|
||||
[file driver.py]
|
||||
from native import f, A, B, C
|
||||
from register_impl import a, c
|
||||
# We need a custom driver here because register_impl has to be run before we test this (so that the
|
||||
# additional implementations are registered)
|
||||
assert f(C()) == 'c'
|
||||
assert f(A()) == 'a'
|
||||
assert f(B()) == 'b'
|
||||
assert a(C()) == 'a'
|
||||
assert c(A()) == 'c'
|
||||
|
||||
[case testMalformedDynamicRegisterCall]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> None:
|
||||
pass
|
||||
[file register.py]
|
||||
from native import f
|
||||
from testutil import assertRaises
|
||||
|
||||
with assertRaises(TypeError, 'Invalid first argument to `register()`'):
|
||||
@f.register
|
||||
def _():
|
||||
pass
|
||||
|
||||
[file driver.py]
|
||||
import register
|
||||
|
||||
[case testCacheClearedWhenNewFunctionRegistered]
|
||||
from functools import singledispatch
|
||||
|
||||
@singledispatch
|
||||
def f(arg) -> str:
|
||||
return 'default'
|
||||
|
||||
[file register.py]
|
||||
from native import f
|
||||
class A: pass
|
||||
class B: pass
|
||||
class C: pass
|
||||
|
||||
# annotated function
|
||||
assert f(A()) == 'default'
|
||||
@f.register
|
||||
def _(arg: A) -> str:
|
||||
return 'a'
|
||||
assert f(A()) == 'a'
|
||||
|
||||
# type passed as argument
|
||||
assert f(B()) == 'default'
|
||||
@f.register(B)
|
||||
def _(arg: B) -> str:
|
||||
return 'b'
|
||||
assert f(B()) == 'b'
|
||||
|
||||
# 2 argument form
|
||||
assert f(C()) == 'default'
|
||||
def c(arg) -> str:
|
||||
return 'c'
|
||||
f.register(C, c)
|
||||
assert f(C()) == 'c'
|
||||
|
||||
|
||||
[file driver.py]
|
||||
import register
|
||||
@@ -0,0 +1,641 @@
|
||||
# Test cases for strings (compile and run)
|
||||
|
||||
[case testStrBasics]
|
||||
from typing import Tuple
|
||||
def f() -> str:
|
||||
return 'some string'
|
||||
def g() -> str:
|
||||
return 'some\a \v \t \x7f " \n \0string 🐍'
|
||||
def tostr(x: int) -> str:
|
||||
return str(x)
|
||||
def booltostr(x: bool) -> str:
|
||||
return str(x)
|
||||
def concat(x: str, y: str) -> str:
|
||||
return x + y
|
||||
def eq(x: str) -> int:
|
||||
if x == 'foo':
|
||||
return 0
|
||||
elif x != 'bar':
|
||||
return 1
|
||||
return 2
|
||||
def match(x: str, y: str) -> Tuple[bool, bool]:
|
||||
return (x.startswith(y), x.endswith(y))
|
||||
|
||||
[file driver.py]
|
||||
from native import f, g, tostr, booltostr, concat, eq, match
|
||||
import sys
|
||||
|
||||
assert f() == 'some string'
|
||||
assert f() is sys.intern('some string')
|
||||
assert g() == 'some\a \v \t \x7f " \n \0string 🐍'
|
||||
assert tostr(57) == '57'
|
||||
assert concat('foo', 'bar') == 'foobar'
|
||||
assert booltostr(True) == 'True'
|
||||
assert booltostr(False) == 'False'
|
||||
assert eq('foo') == 0
|
||||
assert eq('zar') == 1
|
||||
assert eq('bar') == 2
|
||||
|
||||
assert int(tostr(0)) == 0
|
||||
assert int(tostr(20)) == 20
|
||||
assert match('', '') == (True, True)
|
||||
assert match('abc', '') == (True, True)
|
||||
assert match('abc', 'a') == (True, False)
|
||||
assert match('abc', 'c') == (False, True)
|
||||
assert match('', 'abc') == (False, False)
|
||||
|
||||
[case testStringOps]
|
||||
from typing import List, Optional
|
||||
|
||||
def do_split(s: str, sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]:
|
||||
if sep is not None:
|
||||
if max_split is not None:
|
||||
return s.split(sep, max_split)
|
||||
else:
|
||||
return s.split(sep)
|
||||
return s.split()
|
||||
|
||||
ss = "abc abcd abcde abcdef"
|
||||
|
||||
def test_split() -> None:
|
||||
assert do_split(ss) == ["abc", "abcd", "abcde", "abcdef"]
|
||||
assert do_split(ss, " ") == ["abc", "abcd", "abcde", "abcdef"]
|
||||
assert do_split(ss, "-") == ["abc abcd abcde abcdef"]
|
||||
assert do_split(ss, " ", -1) == ["abc", "abcd", "abcde", "abcdef"]
|
||||
assert do_split(ss, " ", 0) == ["abc abcd abcde abcdef"]
|
||||
assert do_split(ss, " ", 1) == ["abc", "abcd abcde abcdef"]
|
||||
assert do_split(ss, " ", 2) == ["abc", "abcd", "abcde abcdef"]
|
||||
|
||||
def getitem(s: str, index: int) -> str:
|
||||
return s[index]
|
||||
|
||||
from testutil import assertRaises
|
||||
|
||||
s = "abc"
|
||||
|
||||
def test_getitem() -> None:
|
||||
assert getitem(s, 0) == "a"
|
||||
assert getitem(s, 1) == "b"
|
||||
assert getitem(s, 2) == "c"
|
||||
assert getitem(s, -3) == "a"
|
||||
assert getitem(s, -2) == "b"
|
||||
assert getitem(s, -1) == "c"
|
||||
with assertRaises(IndexError, "string index out of range"):
|
||||
getitem(s, 4)
|
||||
with assertRaises(IndexError, "string index out of range"):
|
||||
getitem(s, -4)
|
||||
|
||||
def str_to_int(s: str, base: Optional[int] = None) -> int:
|
||||
if base:
|
||||
return int(s, base)
|
||||
else:
|
||||
return int(s)
|
||||
|
||||
def test_str_to_int() -> None:
|
||||
assert str_to_int("1") == 1
|
||||
assert str_to_int("10") == 10
|
||||
assert str_to_int("a", 16) == 10
|
||||
assert str_to_int("1a", 16) == 26
|
||||
with assertRaises(ValueError, "invalid literal for int() with base 10: 'xyz'"):
|
||||
str_to_int("xyz")
|
||||
|
||||
def test_slicing() -> None:
|
||||
# Use dummy adds to avoid constant folding
|
||||
zero = int()
|
||||
two = zero + 2
|
||||
s = "foobar" + str()
|
||||
assert s[two:] == "obar"
|
||||
assert s[:two] == "fo"
|
||||
assert s[two:-two] == "ob"
|
||||
assert s[two:two] == ""
|
||||
assert s[two:two + 1] == "o"
|
||||
assert s[-two:] == "ar"
|
||||
assert s[:-two] == "foob"
|
||||
assert s[:] == "foobar"
|
||||
assert s[two:333] == "obar"
|
||||
assert s[333:two] == ""
|
||||
assert s[two:-333] == ""
|
||||
assert s[-333:two] == "fo"
|
||||
big_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000
|
||||
assert s[1:big_int] == "oobar"
|
||||
assert s[big_int:] == ""
|
||||
assert s[-big_int:-1] == "fooba"
|
||||
|
||||
def test_str_replace() -> None:
|
||||
a = "foofoofoo"
|
||||
assert a.replace("foo", "bar") == "barbarbar"
|
||||
assert a.replace("foo", "bar", -1) == "barbarbar"
|
||||
assert a.replace("foo", "bar", 1) == "barfoofoo"
|
||||
assert a.replace("foo", "bar", 4) == "barbarbar"
|
||||
assert a.replace("aaa", "bar") == "foofoofoo"
|
||||
assert a.replace("ofo", "xyzw") == "foxyzwxyzwo"
|
||||
|
||||
def is_true(x: str) -> bool:
|
||||
if x:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_true2(x: str) -> bool:
|
||||
return bool(x)
|
||||
|
||||
def is_false(x: str) -> bool:
|
||||
if not x:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def test_str_to_bool() -> None:
|
||||
assert is_false('')
|
||||
assert not is_true('')
|
||||
assert not is_true2('')
|
||||
for x in 'a', 'foo', 'bar', 'some string':
|
||||
assert is_true(x)
|
||||
assert is_true2(x)
|
||||
assert not is_false(x)
|
||||
|
||||
def test_str_min_max() -> None:
|
||||
x: str = 'aaa'
|
||||
y: str = 'bbb'
|
||||
z: str = 'aa'
|
||||
assert min(x, y) == 'aaa'
|
||||
assert min(x, z) == 'aa'
|
||||
assert max(x, y) == 'bbb'
|
||||
assert max(x, z) == 'aaa'
|
||||
|
||||
[case testStringFormattingCStyle]
|
||||
[typing fixtures/typing-full.pyi]
|
||||
from typing import Tuple
|
||||
|
||||
var = 'mypyc'
|
||||
num = 20
|
||||
|
||||
def test_basics() -> None:
|
||||
assert 'Hello %s, this is a test' % var == "Hello mypyc, this is a test"
|
||||
assert 'Hello %s %d, this is a test' % (var, num) == "Hello mypyc 20, this is a test"
|
||||
t: Tuple[str, int] = (var, num)
|
||||
assert 'Hello %s %d, this is a test' % t == "Hello mypyc 20, this is a test"
|
||||
|
||||
large_num = 2**65
|
||||
assert 'number: %d' % large_num == 'number: 36893488147419103232'
|
||||
neg_num = -3
|
||||
assert 'negative integer: %d' % neg_num == 'negative integer: -3'
|
||||
assert 'negative integer: %d' % (-large_num) == 'negative integer: -36893488147419103232'
|
||||
|
||||
bool_var1 = True
|
||||
bool_var2 = False
|
||||
assert 'bool: %s, %s' % (bool_var1, bool_var2) == 'bool: True, False'
|
||||
|
||||
float_num = 123.4
|
||||
assert '%f' % float_num == '123.400000'
|
||||
assert '%.2f' % float_num == '123.40'
|
||||
assert '%.5f' % float_num == '123.40000'
|
||||
assert '%10.2f' % float_num == ' 123.40'
|
||||
assert '%10.5f' % float_num == ' 123.40000'
|
||||
assert '%010.5f' % float_num == '0123.40000'
|
||||
assert '%015.5f' % float_num == '000000123.40000'
|
||||
assert '%e' % float_num == '1.234000e+02'
|
||||
large_float = 1.23e30
|
||||
large_float2 = 1234123412341234123400000000000000000
|
||||
small_float = 1.23e-20
|
||||
assert '%f, %f, %f' % (small_float, large_float, large_float2) == \
|
||||
'0.000000, 1229999999999999959718843908096.000000, 1234123412341234169005079998930878464.000000'
|
||||
assert '%s, %s, %s' % (small_float, large_float, large_float2) == \
|
||||
'1.23e-20, 1.23e+30, 1234123412341234123400000000000000000'
|
||||
assert '%d, %d, %d' % (small_float, large_float, large_float2) == \
|
||||
'0, 1229999999999999959718843908096, 1234123412341234123400000000000000000'
|
||||
|
||||
nan_num = float('nan')
|
||||
inf_num = float('inf')
|
||||
assert '%s, %s' % (nan_num, inf_num) == 'nan, inf'
|
||||
assert '%f, %f' % (nan_num, inf_num) == 'nan, inf'
|
||||
|
||||
[case testFStrings]
|
||||
import decimal
|
||||
from datetime import datetime
|
||||
|
||||
var = 'mypyc'
|
||||
num = 20
|
||||
|
||||
def test_fstring_basics() -> None:
|
||||
assert f'Hello {var}, this is a test' == "Hello mypyc, this is a test"
|
||||
|
||||
large_num = 2**65
|
||||
assert f'number: {large_num}' == 'number: 36893488147419103232'
|
||||
neg_num = -3
|
||||
assert f'negative integer: {neg_num}' == 'negative integer: -3'
|
||||
assert f'negative integer: {-large_num}' == 'negative integer: -36893488147419103232'
|
||||
|
||||
bool_var1 = True
|
||||
bool_var2 = False
|
||||
assert f'bool: {bool_var1}, {bool_var2}' == 'bool: True, False'
|
||||
|
||||
x = bytes([1, 2, 3, 4])
|
||||
# assert f'bytes: {x}' == "bytes: b'\\x01\\x02\\x03\\x04'"
|
||||
# error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes
|
||||
|
||||
float_num = 123.4
|
||||
assert f'{float_num}' == '123.4'
|
||||
assert f'{float_num:.2f}' == '123.40'
|
||||
assert f'{float_num:.5f}' == '123.40000'
|
||||
assert f'{float_num:>10.2f}' == ' 123.40'
|
||||
assert f'{float_num:>10.5f}' == ' 123.40000'
|
||||
assert f'{float_num:>010.5f}' == '0123.40000'
|
||||
assert f'{float_num:>015.5f}' == '000000123.40000'
|
||||
assert f'{float_num:e}' == '1.234000e+02'
|
||||
|
||||
large_float = 1.23e30
|
||||
large_float2 = 1234123412341234123400000000000000000
|
||||
small_float = 1.23e-20
|
||||
assert f'{small_float}, {large_float}, {large_float2}' == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000'
|
||||
nan_num = float('nan')
|
||||
inf_num = float('inf')
|
||||
assert f'{nan_num}, {inf_num}' == 'nan, inf'
|
||||
|
||||
# F-strings would be translated into ''.join[string literals, format method call, ...] in mypy AST.
|
||||
# Currently we are using a str.join specializer for f-string speed up. We might not cover all cases
|
||||
# and the rest ones should fall back to a normal str.join method call.
|
||||
# TODO: Once we have a new pipeline for f-strings, this test case can be moved to testStringOps.
|
||||
def test_str_join() -> None:
|
||||
var = 'mypyc'
|
||||
num = 10
|
||||
assert ''.join(['a', 'b', '{}'.format(var), 'c']) == 'abmypycc'
|
||||
assert ''.join(['a', 'b', '{:{}}'.format(var, ''), 'c']) == 'abmypycc'
|
||||
assert ''.join(['a', 'b', '{:{}}'.format(var, '>10'), 'c']) == 'ab mypycc'
|
||||
assert ''.join(['a', 'b', '{:{}}'.format(var, '>{}'.format(num)), 'c']) == 'ab mypycc'
|
||||
assert var.join(['a', '{:{}}'.format(var, ''), 'b']) == 'amypycmypycmypycb'
|
||||
assert ','.join(['a', '{:{}}'.format(var, ''), 'b']) == 'a,mypyc,b'
|
||||
assert ''.join(['x', var]) == 'xmypyc'
|
||||
|
||||
class A:
|
||||
def __init__(self, name, age):
|
||||
self.name = name
|
||||
self.age = age
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self.name} is {self.age} years old.'
|
||||
|
||||
def test_fstring_datatype() -> None:
|
||||
u = A('John Doe', 14)
|
||||
assert f'{u}' == 'John Doe is 14 years old.'
|
||||
d = {'name': 'John Doe', 'age': 14}
|
||||
assert f'{d}' == "{'name': 'John Doe', 'age': 14}"
|
||||
|
||||
def test_fstring_escape() -> None:
|
||||
assert f"{'inside'}" == 'inside'
|
||||
assert f'{"inside"}' == 'inside'
|
||||
assert f"""inside""" == 'inside'
|
||||
assert f'''inside''' == 'inside'
|
||||
assert f"\"{'inside'}\"" == '"inside"'
|
||||
assert f'\'{"inside"}\'' == "'inside'"
|
||||
|
||||
assert f'{{10}}' == '{10}'
|
||||
assert f'{{10 + 10}}' == '{10 + 10}'
|
||||
assert f'{{{10 + 10}}}' == '{20}'
|
||||
assert f'{{{{10 + 10}}}}' == '{{10 + 10}}'
|
||||
|
||||
def test_fstring_conversion() -> None:
|
||||
assert f'Hello {var!r}' == "Hello 'mypyc'"
|
||||
# repr() is equivalent to !r
|
||||
assert f'Hello {repr(var)}' == "Hello 'mypyc'"
|
||||
|
||||
assert f'Hello {var!a}' == "Hello 'mypyc'"
|
||||
# ascii() is equivalent to !a
|
||||
assert f'Hello {ascii(var)}' == "Hello 'mypyc'"
|
||||
|
||||
tmp_str = """this
|
||||
is a new line."""
|
||||
assert f'Test: {tmp_str!a}' == "Test: 'this\\n is a new line.'"
|
||||
|
||||
s = 'test: āĀēĒčČ..šŠūŪžŽ'
|
||||
assert f'{s}' == 'test: āĀēĒčČ..šŠūŪžŽ'
|
||||
assert f'{s!a}' == "'test: \\u0101\\u0100\\u0113\\u0112\\u010d\\u010c..\\u0161\\u0160\\u016b\\u016a\\u017e\\u017d'"
|
||||
|
||||
assert f'Hello {var!s}' == 'Hello mypyc'
|
||||
assert f'Hello {num!s}' == 'Hello 20'
|
||||
|
||||
def test_fstring_align() -> None:
|
||||
assert f'Hello {var:>20}' == "Hello mypyc"
|
||||
assert f'Hello {var!r:>20}' == "Hello 'mypyc'"
|
||||
assert f'Hello {var:>{num}}' == "Hello mypyc"
|
||||
assert f'Hello {var!r:>{num}}' == "Hello 'mypyc'"
|
||||
|
||||
def test_fstring_multi() -> None:
|
||||
assert f'Hello {var}, hello again {var}' == "Hello mypyc, hello again mypyc"
|
||||
a = 'py'
|
||||
s = f'my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}'
|
||||
assert s == 'mypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypy'
|
||||
|
||||
def test_fstring_python_doc() -> None:
|
||||
name = 'Fred'
|
||||
assert f"He said his name is {name!r}." == "He said his name is 'Fred'."
|
||||
assert f"He said his name is {repr(name)}." == "He said his name is 'Fred'."
|
||||
|
||||
width = 10
|
||||
precision = 4
|
||||
value = decimal.Decimal('12.34567')
|
||||
assert f'result: {value:{width}.{precision}}' == 'result: 12.35' # nested field
|
||||
|
||||
today = datetime(year=2017, month=1, day=27)
|
||||
assert f'{today:%B %d, %Y}' == 'January 27, 2017' # using date format specifier
|
||||
|
||||
number = 1024
|
||||
assert f'{number:#0x}' == '0x400' # using integer format specifier
|
||||
|
||||
[case testStringFormatMethod]
|
||||
from typing import Tuple
|
||||
|
||||
def test_format_method_basics() -> None:
|
||||
x = str()
|
||||
assert 'x{}'.format(x) == 'x'
|
||||
assert 'ā{}'.format(x) == 'ā'
|
||||
assert '😀{}'.format(x) == '😀'
|
||||
assert ''.format() == ''
|
||||
assert 'abc'.format() == 'abc'
|
||||
assert '{}{}'.format(1, 2) == '12'
|
||||
|
||||
name = 'Eric'
|
||||
age = 14
|
||||
assert "My name is {name}, I'm {age}.".format(name=name, age=age) == "My name is Eric, I'm 14."
|
||||
assert "My name is {A}, I'm {B}.".format(A=name, B=age) == "My name is Eric, I'm 14."
|
||||
assert "My name is {}, I'm {B}.".format(name, B=age) == "My name is Eric, I'm 14."
|
||||
|
||||
bool_var1 = True
|
||||
bool_var2 = False
|
||||
assert 'bool: {}, {}'.format(bool_var1, bool_var2) == 'bool: True, False'
|
||||
|
||||
def test_format_method_empty_braces() -> None:
|
||||
name = 'Eric'
|
||||
age = 14
|
||||
|
||||
assert 'Hello, {}!'.format(name) == 'Hello, Eric!'
|
||||
assert '{}'.format(name) == 'Eric'
|
||||
assert '{}! Hi!'.format(name) == 'Eric! Hi!'
|
||||
assert '{}, Hi, {}'.format(name, name) == 'Eric, Hi, Eric'
|
||||
assert 'Hi! {}'.format(name) == 'Hi! Eric'
|
||||
assert "Hi, I'm {}. I'm {}.".format(name, age) == "Hi, I'm Eric. I'm 14."
|
||||
|
||||
assert '{{}}'.format() == '{}'
|
||||
assert '{{{{}}}}'.format() == '{{}}'
|
||||
assert '{{}}{}'.format(name) == '{}Eric'
|
||||
assert 'Hi! {{{}}}'.format(name) == 'Hi! {Eric}'
|
||||
assert 'Hi! {{ {}'.format(name) == 'Hi! { Eric'
|
||||
assert 'Hi! {{ {} }}}}'.format(name) == 'Hi! { Eric }}'
|
||||
|
||||
def test_format_method_numbers() -> None:
|
||||
s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-233)
|
||||
assert s == 'int: -233; hex: -e9; oct: -351; bin: -11101001'
|
||||
num = 2**65
|
||||
s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(num)
|
||||
assert s == 'int: 36893488147419103232; hex: 20000000000000000; oct: 4000000000000000000000; bin: 100000000000000000000000000000000000000000000000000000000000000000'
|
||||
s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-num)
|
||||
assert s == 'int: -36893488147419103232; hex: -20000000000000000; oct: -4000000000000000000000; bin: -100000000000000000000000000000000000000000000000000000000000000000'
|
||||
|
||||
large_num = 2**65
|
||||
assert 'number: {}'.format(large_num) == 'number: 36893488147419103232'
|
||||
neg_num = -3
|
||||
assert 'negative integer: {}'.format(neg_num) == 'negative integer: -3'
|
||||
assert 'negative integer: {}'.format(-large_num) == 'negative integer: -36893488147419103232'
|
||||
|
||||
large_float = 1.23e30
|
||||
large_float2 = 1234123412341234123400000000000000000
|
||||
small_float = 1.23e-20
|
||||
assert '{}, {}, {}'.format(small_float, large_float, large_float2) == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000'
|
||||
nan_num = float('nan')
|
||||
inf_num = float('inf')
|
||||
assert '{}, {}'.format(nan_num, inf_num) == 'nan, inf'
|
||||
|
||||
def format_args(*args: int) -> str:
|
||||
return 'x{}y{}'.format(*args)
|
||||
def format_kwargs(**kwargs: int) -> str:
|
||||
return 'c{x}d{y}'.format(**kwargs)
|
||||
def format_args_self(*args: int) -> str:
|
||||
return '{}'.format(args)
|
||||
def format_kwargs_self(**kwargs: int) -> str:
|
||||
return '{}'.format(kwargs)
|
||||
|
||||
def test_format_method_args() -> None:
|
||||
assert format_args(10, 2) == 'x10y2'
|
||||
assert format_args_self(10, 2) == '(10, 2)'
|
||||
assert format_kwargs(x=10, y=2) == 'c10d2'
|
||||
assert format_kwargs(x=10, y=2, z=1) == 'c10d2'
|
||||
assert format_kwargs_self(x=10, y=2, z=1) == "{'x': 10, 'y': 2, 'z': 1}"
|
||||
|
||||
def test_format_method_different_kind() -> None:
|
||||
s1 = "Literal['😀']"
|
||||
assert 'Revealed type is {}'.format(s1) == "Revealed type is Literal['😀']"
|
||||
s2 = "Revealed type is"
|
||||
assert "{} Literal['😀']".format(s2) == "Revealed type is Literal['😀']"
|
||||
s3 = "测试:"
|
||||
assert "{}{} {}".format(s3, s2, s1) == "测试:Revealed type is Literal['😀']"
|
||||
assert "Test: {}{}".format(s3, s1) == "Test: 测试:Literal['😀']"
|
||||
assert "Test: {}{}".format(s3, s2) == "Test: 测试:Revealed type is"
|
||||
|
||||
def test_format_method_nested() -> None:
|
||||
var = 'mypyc'
|
||||
num = 10
|
||||
assert '{:{}}'.format(var, '') == 'mypyc'
|
||||
assert '{:{}}'.format(var, '>10') == ' mypyc'
|
||||
assert '{:{}}'.format(var, '>{}'.format(num)) == ' mypyc'
|
||||
|
||||
class Point:
|
||||
def __init__(self, x, y):
|
||||
self.x, self.y = x, y
|
||||
def __str__(self):
|
||||
return 'Point({self.x}, {self.y})'.format(self=self)
|
||||
|
||||
# Format examples from Python doc
|
||||
# https://docs.python.org/3/library/string.html#formatexamples
|
||||
def test_format_method_python_doc() -> None:
|
||||
# Accessing arguments by position:
|
||||
assert '{0}, {1}, {2}'.format('a', 'b', 'c') == 'a, b, c'
|
||||
assert '{}, {}, {}'.format('a', 'b', 'c') == 'a, b, c'
|
||||
assert '{2}, {1}, {0}'.format('a', 'b', 'c') == 'c, b, a'
|
||||
assert '{2}, {1}, {0}'.format(*'abc') == 'c, b, a' # unpacking argument sequence
|
||||
# assert '{0}{1}{0}'.format('abra', 'cad') = 'abracadabra' # arguments' indices can be repeated
|
||||
|
||||
# Accessing arguments by name:
|
||||
s = 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
|
||||
assert s == 'Coordinates: 37.24N, -115.81W'
|
||||
coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
|
||||
assert 'Coordinates: {latitude}, {longitude}'.format(**coord) == 'Coordinates: 37.24N, -115.81W'
|
||||
|
||||
# Accessing arguments’ attributes:
|
||||
assert str(Point(4, 2)) == 'Point(4, 2)'
|
||||
|
||||
# Accessing arguments’ items:
|
||||
coord2 = (3, 5)
|
||||
assert 'X: {0[0]}; Y: {0[1]}'.format(coord2) == 'X: 3; Y: 5'
|
||||
|
||||
# Replacing %s and %r:
|
||||
s = "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
|
||||
assert s == "repr() shows quotes: 'test1'; str() doesn't: test2"
|
||||
|
||||
# Aligning the text and specifying a width:
|
||||
assert '{:<30}'.format('left aligned') == 'left aligned '
|
||||
assert '{:>30}'.format('right aligned') == ' right aligned'
|
||||
assert '{:^30}'.format('centered') == ' centered '
|
||||
assert '{:*^30}'.format('centered') == '***********centered***********' # use '*' as a fill char
|
||||
|
||||
# Replacing %+f, %-f, and % f and specifying a sign:
|
||||
assert '{:+f}; {:+f}'.format(3.14, -3.14) == '+3.140000; -3.140000' # show it always
|
||||
assert '{: f}; {: f}'.format(3.14, -3.14) == ' 3.140000; -3.140000' # show a space for positive numbers
|
||||
assert '{:-f}; {:-f}'.format(3.14, -3.14) == '3.140000; -3.140000' # show only the minus -- same as '{:f}; {:f}'
|
||||
|
||||
# Replacing %x and %o and converting the value to different bases:
|
||||
s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(42) # format also supports binary numbers
|
||||
assert s == 'int: 42; hex: 2a; oct: 52; bin: 101010'
|
||||
s = 'int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}'.format(42) # with 0x, 0o, or 0b as prefix:
|
||||
assert s == 'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010'
|
||||
|
||||
# Using the comma as a thousands separator:
|
||||
assert '{:,}'.format(1234567890) == '1,234,567,890'
|
||||
|
||||
# Expressing a percentage:
|
||||
points = 19.0
|
||||
total = 22.0
|
||||
assert 'Correct answers: {:.2%}'.format(points/total) == 'Correct answers: 86.36%'
|
||||
|
||||
# Using type-specific formatting:
|
||||
import datetime
|
||||
d = datetime.datetime(2010, 7, 4, 12, 15, 58)
|
||||
assert '{:%Y-%m-%d %H:%M:%S}'.format(d) == '2010-07-04 12:15:58'
|
||||
|
||||
# Nesting arguments and more complex examples:
|
||||
tmp_strs = []
|
||||
for align, text in zip('<^>', ['left', 'center', 'right']):
|
||||
tmp_strs.append('{0:{fill}{align}16}'.format(text, fill=align, align=align))
|
||||
assert tmp_strs == ['left<<<<<<<<<<<<', '^^^^^center^^^^^', '>>>>>>>>>>>right']
|
||||
|
||||
octets = [192, 168, 0, 1]
|
||||
assert '{:02X}{:02X}{:02X}{:02X}'.format(*octets) == 'C0A80001'
|
||||
|
||||
width = 5
|
||||
tmp_strs = []
|
||||
for num in range(5,12):
|
||||
tmp_str = ''
|
||||
for base in 'dXob':
|
||||
tmp_str += ('{0:{width}{base}}'.format(num, base=base, width=width))
|
||||
tmp_strs.append(tmp_str)
|
||||
assert tmp_strs == [' 5 5 5 101',\
|
||||
' 6 6 6 110',\
|
||||
' 7 7 7 111',\
|
||||
' 8 8 10 1000',\
|
||||
' 9 9 11 1001',\
|
||||
' 10 A 12 1010',\
|
||||
' 11 B 13 1011']
|
||||
|
||||
[case testChr]
|
||||
# Some test cases are from https://docs.python.org/3/howto/unicode.html
|
||||
|
||||
def try_invalid(x: int) -> bool:
|
||||
try:
|
||||
chr(x + int())
|
||||
return False
|
||||
except ValueError:
|
||||
return True
|
||||
|
||||
def test_chr() -> None:
|
||||
assert chr(57344) == '\ue000'
|
||||
assert chr(0) == '\x00'
|
||||
assert chr(65) == 'A'
|
||||
assert chr(150) == '\x96'
|
||||
try:
|
||||
chr(-1)
|
||||
assert False
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
chr(1114112)
|
||||
assert False
|
||||
except ValueError:
|
||||
pass
|
||||
assert chr(1114111) == '\U0010ffff'
|
||||
x = 0
|
||||
assert chr(x + int()) == '\x00'
|
||||
x = 100
|
||||
assert chr(x + int()) == 'd'
|
||||
x = 150
|
||||
assert chr(x + int()) == '\x96'
|
||||
x = 257
|
||||
assert chr(x + int()) == 'ā'
|
||||
x = 65537
|
||||
assert chr(x + int()) == '𐀁'
|
||||
assert try_invalid(-1)
|
||||
assert try_invalid(1114112)
|
||||
|
||||
[case testOrd]
|
||||
def test_ord() -> None:
|
||||
assert ord('\ue000') == 57344
|
||||
s = "a\xac\u1234\u20ac\U00008000"
|
||||
# ^^^^ two-digit hex escape
|
||||
# ^^^^^^ four-digit Unicode escape
|
||||
# ^^^^^^^^^^ eight-digit Unicode escape
|
||||
l1 = [ord(c) for c in s]
|
||||
assert l1 == [97, 172, 4660, 8364, 32768]
|
||||
u = 'abcdé'
|
||||
assert ord(u[-1]) == 233
|
||||
assert ord(b'a') == 97
|
||||
assert ord(b'a' + bytes()) == 97
|
||||
u2 = '\U0010ffff'
|
||||
assert ord(u2) == 1114111
|
||||
try:
|
||||
ord('aa')
|
||||
assert False
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
[case testDecode]
|
||||
def test_decode() -> None:
|
||||
assert "\N{GREEK CAPITAL LETTER DELTA}" == '\u0394'
|
||||
assert "\u0394" == "\u0394"
|
||||
assert "\U00000394" == '\u0394'
|
||||
assert b'\x80abc'.decode('utf-8', 'replace') == '\ufffdabc'
|
||||
assert b'\x80abc'.decode('utf-8', 'backslashreplace') == '\\x80abc'
|
||||
assert b'abc'.decode() == 'abc'
|
||||
assert b'abc'.decode('utf-8') == 'abc'
|
||||
assert b'\x80abc'.decode('utf-8', 'ignore') == 'abc'
|
||||
assert b'\x80abc'.decode('UTF-8', 'ignore') == 'abc'
|
||||
assert b'\x80abc'.decode('Utf-8', 'ignore') == 'abc'
|
||||
assert b'\x80abc'.decode('utf_8', 'ignore') == 'abc'
|
||||
assert b'\x80abc'.decode('latin1', 'ignore') == '\x80abc'
|
||||
assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('gbk', 'ignore') == '一二三'
|
||||
assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('latin1', 'ignore') == 'Ò»¶þÈý'
|
||||
assert b'Z\xc3\xbcrich'.decode("utf-8") == 'Zürich'
|
||||
try:
|
||||
b'Z\xc3\xbcrich'.decode('ascii')
|
||||
assert False
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
assert bytearray(range(5)).decode() == '\x00\x01\x02\x03\x04'
|
||||
b = bytearray(b'\xe4\xbd\xa0\xe5\xa5\xbd')
|
||||
assert b.decode() == '你好'
|
||||
assert b.decode('gbk') == '浣犲ソ'
|
||||
assert b.decode('latin1') == 'ä½\xa0好'
|
||||
|
||||
[case testEncode]
|
||||
from testutil import assertRaises
|
||||
|
||||
def test_encode() -> None:
|
||||
u = chr(40960) + 'abcd' + chr(1972)
|
||||
assert u.encode() == b'\xea\x80\x80abcd\xde\xb4'
|
||||
assert u.encode('utf-8') == b'\xea\x80\x80abcd\xde\xb4'
|
||||
with assertRaises(UnicodeEncodeError):
|
||||
u.encode('ascii')
|
||||
with assertRaises(LookupError):
|
||||
u.encode('aaa')
|
||||
assert u.encode('utf-8', 'aaaaaa') == b'\xea\x80\x80abcd\xde\xb4'
|
||||
assert u.encode('ascii', 'ignore') == b'abcd'
|
||||
assert u.encode('ASCII', 'ignore') == b'abcd'
|
||||
assert u.encode('ascii', 'replace') == b'?abcd?'
|
||||
assert u.encode('ascii', 'xmlcharrefreplace') == b'ꀀabcd޴'
|
||||
assert u.encode('ascii', 'backslashreplace') == b'\\ua000abcd\\u07b4'
|
||||
assert u.encode('ascii', 'namereplace') == b'\\N{YI SYLLABLE IT}abcd\\u07b4'
|
||||
assert 'pythön!'.encode() == b'pyth\xc3\xb6n!'
|
||||
assert '一二三'.encode('gbk') == b'\xd2\xbb\xb6\xfe\xc8\xfd'
|
||||
assert u.encode('UTF-8', 'ignore') == b'\xea\x80\x80abcd\xde\xb4'
|
||||
assert u.encode('Utf_8') == b'\xea\x80\x80abcd\xde\xb4'
|
||||
assert u.encode('UTF_8') == b'\xea\x80\x80abcd\xde\xb4'
|
||||
assert u'\u00E1'.encode('latin1') == b'\xe1'
|
||||
with assertRaises(UnicodeEncodeError):
|
||||
u.encode('latin1')
|
||||
@@ -0,0 +1,411 @@
|
||||
[case testTraitBasic1]
|
||||
from mypy_extensions import trait
|
||||
|
||||
class A:
|
||||
line: int
|
||||
def foo(self) -> None:
|
||||
print("foo")
|
||||
|
||||
@trait
|
||||
class T:
|
||||
def bar(self) -> None:
|
||||
print("bar")
|
||||
def baz(self) -> object:
|
||||
return None
|
||||
|
||||
class C(A, T):
|
||||
def baz(self) -> int:
|
||||
return 10
|
||||
|
||||
def use_t(t: T) -> object:
|
||||
t.bar()
|
||||
return t.baz()
|
||||
|
||||
def use_c(c: C) -> int:
|
||||
use_t(c)
|
||||
c.foo()
|
||||
c.bar()
|
||||
return c.baz()
|
||||
|
||||
use_t(C())
|
||||
|
||||
# This trait is dead code but there's no reason it shouldn't compile
|
||||
@trait
|
||||
class ChildlessTrait:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
[file driver.py]
|
||||
from native import A, T, C, use_c, use_t
|
||||
c = C()
|
||||
c.foo()
|
||||
c.bar()
|
||||
assert c.baz() == 10
|
||||
assert use_c(c) == 10
|
||||
assert use_t(c) == 10
|
||||
[out]
|
||||
bar
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
|
||||
[case testTraitBasic2]
|
||||
from mypy_extensions import trait
|
||||
|
||||
class A:
|
||||
line: int
|
||||
def foo(self) -> None:
|
||||
print("foo")
|
||||
|
||||
@trait
|
||||
class T:
|
||||
def bar(self) -> None:
|
||||
print("bar", self.baz())
|
||||
def baz(self) -> int:
|
||||
return -1
|
||||
|
||||
@trait
|
||||
class T2:
|
||||
line: int
|
||||
def baz(self) -> int:
|
||||
return -2
|
||||
|
||||
class C(A, T):
|
||||
def __init__(self) -> None:
|
||||
self.line = 1337
|
||||
self.x = 12
|
||||
def baz(self) -> int:
|
||||
return self.x
|
||||
|
||||
class D(C, T2):
|
||||
def __init__(self) -> None:
|
||||
self.line = 1337
|
||||
self.x = 13
|
||||
|
||||
@trait
|
||||
class T3:
|
||||
def baz(self) -> int:
|
||||
return -2
|
||||
|
||||
class E(T3):
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def use_t(t: T) -> None:
|
||||
t.bar()
|
||||
def use_t2(t: T2) -> int:
|
||||
t.line = t.line
|
||||
return t.line
|
||||
|
||||
def use_c(c: C) -> int:
|
||||
use_t(c)
|
||||
c.foo()
|
||||
c.bar()
|
||||
return c.line
|
||||
|
||||
def use_d(d: D) -> int:
|
||||
return d.baz()
|
||||
|
||||
[file driver.py]
|
||||
from native import A, T, C, D, use_c, use_t, use_d, use_t2
|
||||
c = C()
|
||||
d = D()
|
||||
c.foo()
|
||||
c.bar()
|
||||
print("baz", c.baz())
|
||||
print("baz", d.baz())
|
||||
use_c(c)
|
||||
use_t(c)
|
||||
use_c(d)
|
||||
use_t(d)
|
||||
assert use_d(d) == 13
|
||||
print(d.line)
|
||||
assert d.line == 1337
|
||||
assert use_t2(d) == 1337
|
||||
[out]
|
||||
foo
|
||||
bar 12
|
||||
baz 12
|
||||
baz 13
|
||||
bar 12
|
||||
foo
|
||||
bar 12
|
||||
bar 12
|
||||
bar 13
|
||||
foo
|
||||
bar 13
|
||||
bar 13
|
||||
1337
|
||||
|
||||
[case testTrait3]
|
||||
from mypy_extensions import trait
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
@trait
|
||||
class T1: pass
|
||||
@trait
|
||||
class T2: pass
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
class C(Generic[T], T1, T2):
|
||||
pass
|
||||
|
||||
@trait
|
||||
class S1(Generic[T]):
|
||||
def foo(self) -> None: pass
|
||||
def bar(self, x: T) -> T: raise Exception
|
||||
|
||||
@trait
|
||||
class S2(S1[T]):
|
||||
def bar(self, x: T) -> T: return x
|
||||
|
||||
@trait
|
||||
class S3(S2[T]):
|
||||
def bar(self, x: T) -> T: return x
|
||||
|
||||
class D(S3[bool]):
|
||||
def bar(self, x: bool) -> bool: return x
|
||||
|
||||
|
||||
[file driver.py]
|
||||
import native
|
||||
|
||||
[case testTrait4]
|
||||
from mypy_extensions import trait
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
@trait
|
||||
class S1(Generic[T]):
|
||||
def bar(self) -> T: raise Exception
|
||||
|
||||
class S2(S1[bool]):
|
||||
def bar(self) -> bool: return False
|
||||
|
||||
class D(S2):
|
||||
pass
|
||||
|
||||
def lol(x: S1) -> None:
|
||||
x.bar()
|
||||
|
||||
[file driver.py]
|
||||
import native
|
||||
native.lol(native.D())
|
||||
|
||||
[case testTraitOrdering]
|
||||
import other_b
|
||||
# Regression test for a bug where inheriting from a class that
|
||||
# inherited from a trait that got processed later on the command line
|
||||
# filed to compile.
|
||||
[file other_b.py]
|
||||
from other_c import Plugin
|
||||
|
||||
class Whatever(Plugin):
|
||||
pass
|
||||
|
||||
[file other_c.py]
|
||||
from mypy_extensions import trait
|
||||
|
||||
@trait
|
||||
class Base:
|
||||
x = None # type: int
|
||||
|
||||
class Plugin(Base):
|
||||
def __init__(self) -> None:
|
||||
self.x = 10
|
||||
|
||||
[file driver.py]
|
||||
from native import *
|
||||
|
||||
[case testDiamond]
|
||||
from mypy_extensions import trait
|
||||
|
||||
@trait
|
||||
class Base:
|
||||
def get_value(self) -> str:
|
||||
return "Base"
|
||||
|
||||
@trait
|
||||
class Trait(Base):
|
||||
def get_value(self) -> str:
|
||||
return "Trait"
|
||||
|
||||
class Message(Base):
|
||||
def show_message(self) -> None:
|
||||
print("I am a " + self.get_value())
|
||||
|
||||
class DerivedMessage(Message, Trait):
|
||||
pass
|
||||
|
||||
[file driver.py]
|
||||
from native import *
|
||||
a = Message()
|
||||
a.show_message()
|
||||
b = DerivedMessage()
|
||||
b.show_message()
|
||||
|
||||
[out]
|
||||
I am a Base
|
||||
I am a Trait
|
||||
|
||||
[case testTraitAttrsSubTrait]
|
||||
from mypy_extensions import trait
|
||||
|
||||
class A:
|
||||
a: int
|
||||
|
||||
@trait
|
||||
class T1:
|
||||
x: int
|
||||
|
||||
@trait
|
||||
class T2(T1):
|
||||
y: int
|
||||
|
||||
class C(A, T2):
|
||||
c: int
|
||||
|
||||
def f(t1: T1, t2: T2) -> None:
|
||||
t1.x, t2.x = t2.x, t1.x
|
||||
|
||||
def g(t1: T1, t2: T2) -> None:
|
||||
t2.y = t1.x
|
||||
|
||||
def get_x(c: C) -> int:
|
||||
return c.x
|
||||
|
||||
def get_y(c: C) -> int:
|
||||
return c.y
|
||||
|
||||
[file driver.py]
|
||||
from native import C, f, g, get_x, get_y
|
||||
|
||||
c1 = C()
|
||||
c2 = C()
|
||||
|
||||
c1.x = 1
|
||||
c1.y = 0
|
||||
c2.x = 2
|
||||
c2.y = 0
|
||||
|
||||
f(c1, c2)
|
||||
assert c1.x == 2
|
||||
assert c2.x == 1
|
||||
assert get_x(c1) == 2
|
||||
assert get_x(c2) == 1
|
||||
|
||||
assert get_y(c2) == 0
|
||||
g(c1, c2)
|
||||
assert get_y(c2) == 2
|
||||
[out]
|
||||
|
||||
[case testTraitAttrsTriangle]
|
||||
from mypy_extensions import trait
|
||||
|
||||
class A:
|
||||
a: int
|
||||
|
||||
@trait
|
||||
class T(A):
|
||||
x: int
|
||||
def meth(self) -> int:
|
||||
return self.a
|
||||
|
||||
class B(A):
|
||||
b: int
|
||||
|
||||
class C(B, T):
|
||||
pass
|
||||
|
||||
def take_t(t: T) -> int:
|
||||
return t.x + t.meth()
|
||||
|
||||
def take_c(c: C) -> int:
|
||||
return c.x + c.meth()
|
||||
|
||||
[file driver.py]
|
||||
from native import C, take_t, take_c
|
||||
|
||||
c = C()
|
||||
c.a = 1
|
||||
c.x = 10
|
||||
|
||||
assert take_t(c) == take_c(c) == 11
|
||||
[out]
|
||||
|
||||
[case testTraitAttrsTree]
|
||||
from mypy_extensions import trait
|
||||
|
||||
class A:
|
||||
a: int
|
||||
|
||||
@trait
|
||||
class T1:
|
||||
x: int
|
||||
|
||||
class B(A, T1):
|
||||
b: int
|
||||
|
||||
@trait
|
||||
class T2:
|
||||
x: int
|
||||
|
||||
class C(B, T2):
|
||||
pass
|
||||
|
||||
def f(t1: T1, t2: T2) -> None:
|
||||
t1.x, t2.x = t2.x, t1.x
|
||||
|
||||
def g(c1: C, c2: C) -> None:
|
||||
c1.x, c2.x = c2.x, c1.x
|
||||
|
||||
[file driver.py]
|
||||
from native import C, f, g
|
||||
|
||||
c1 = C()
|
||||
c2 = C()
|
||||
|
||||
c1.x = 1
|
||||
c2.x = 2
|
||||
|
||||
f(c1, c2)
|
||||
assert c1.x == 2
|
||||
assert c2.x == 1
|
||||
|
||||
g(c1, c2)
|
||||
assert c1.x == 1
|
||||
assert c2.x == 2
|
||||
[out]
|
||||
|
||||
[case testTraitErrorMessages]
|
||||
from mypy_extensions import trait
|
||||
|
||||
@trait
|
||||
class Trait:
|
||||
pass
|
||||
|
||||
def create() -> Trait:
|
||||
return Trait()
|
||||
|
||||
[file driver.py]
|
||||
from native import Trait, create
|
||||
from testutil import assertRaises
|
||||
|
||||
with assertRaises(TypeError, "traits may not be directly created"):
|
||||
Trait()
|
||||
|
||||
with assertRaises(TypeError, "traits may not be directly created"):
|
||||
create()
|
||||
|
||||
class Sub(Trait):
|
||||
pass
|
||||
|
||||
with assertRaises(TypeError, "interpreted classes cannot inherit from compiled traits"):
|
||||
Sub()
|
||||
@@ -0,0 +1,258 @@
|
||||
# Test cases for tuples (compile and run)
|
||||
|
||||
[case testTuple]
|
||||
from typing import List, Optional, Tuple
|
||||
from typing import Tuple
|
||||
def f(x: Tuple[int, int]) -> Tuple[int,int]:
|
||||
return x
|
||||
|
||||
def lurr(x: List[Optional[Tuple[int, str]]]) -> object:
|
||||
return x[0]
|
||||
|
||||
def asdf(x: Tuple[int, str]) -> None:
|
||||
pass
|
||||
[file driver.py]
|
||||
from testutil import assertRaises
|
||||
from native import f, lurr, asdf
|
||||
|
||||
assert f((1,2)) == (1, 2)
|
||||
assert lurr([(1, '2')]) == (1, '2')
|
||||
|
||||
with assertRaises(TypeError):
|
||||
print(lurr([(1, 2)]))
|
||||
|
||||
with assertRaises(TypeError):
|
||||
asdf((1, 2))
|
||||
|
||||
[case testTupleGet]
|
||||
from typing import Tuple
|
||||
def f(x: Tuple[Tuple[int, bool], int]) -> int:
|
||||
return x[0][0]
|
||||
[file driver.py]
|
||||
from native import f
|
||||
print(f(((1,True),2)))
|
||||
big_number = pow(2, 80)
|
||||
print(f(((big_number,True),2)))
|
||||
[out]
|
||||
1
|
||||
1208925819614629174706176
|
||||
|
||||
[case testSequenceTupleArg]
|
||||
from typing import Tuple
|
||||
def f(x: Tuple[int, ...]) -> int:
|
||||
return x[1]
|
||||
[file driver.py]
|
||||
from native import f
|
||||
print(f((1,2,3,4)))
|
||||
[out]
|
||||
2
|
||||
|
||||
[case testTupleAttr]
|
||||
from typing import Tuple
|
||||
class C:
|
||||
b: Tuple[Tuple[Tuple[int, int], int], int, str, object]
|
||||
c: Tuple[()]
|
||||
def f() -> None:
|
||||
c = C()
|
||||
c.b = (((1, 2), 2), 1, 'hi', 'hi2')
|
||||
print(c.b)
|
||||
|
||||
def g() -> None:
|
||||
try:
|
||||
h()
|
||||
except Exception:
|
||||
print('caught the exception')
|
||||
|
||||
def h() -> Tuple[Tuple[Tuple[int, int], int], int, str, object]:
|
||||
raise Exception('Intentional exception')
|
||||
[file driver.py]
|
||||
from native import f, g, C
|
||||
f()
|
||||
g()
|
||||
assert not hasattr(C(), 'c')
|
||||
[out]
|
||||
(((1, 2), 2), 1, 'hi', 'hi2')
|
||||
caught the exception
|
||||
|
||||
[case testNamedTupleAttributeRun]
|
||||
from typing import NamedTuple
|
||||
|
||||
NT = NamedTuple('NT', [('x', int), ('y', int)])
|
||||
|
||||
def f(nt: NT) -> int:
|
||||
if nt.x > nt.y:
|
||||
return nt.x
|
||||
return nt.y
|
||||
|
||||
nt = NT(1, 2)
|
||||
[file driver.py]
|
||||
from native import NT, nt, f
|
||||
|
||||
assert f(nt) == 2
|
||||
assert f(NT(3, 2)) == 3
|
||||
|
||||
class Sub(NT):
|
||||
pass
|
||||
assert f(Sub(3, 2)) == 3
|
||||
|
||||
-- Ref: https://github.com/mypyc/mypyc/issues/924
|
||||
[case testNamedTupleClassSyntax]
|
||||
from typing import Dict, List, NamedTuple, Optional, Tuple, Union
|
||||
from typing_extensions import final
|
||||
|
||||
class FuncIR: pass
|
||||
|
||||
StealsDescription = Union[bool, List[bool]]
|
||||
|
||||
class Record(NamedTuple):
|
||||
st_mtime: float
|
||||
st_size: int
|
||||
is_borrowed: bool
|
||||
hash: str
|
||||
python_path: Tuple[str, ...]
|
||||
type: 'ClassIR'
|
||||
method: FuncIR
|
||||
shadow_method: Optional[FuncIR]
|
||||
classes: Dict[str, 'ClassIR']
|
||||
steals: StealsDescription
|
||||
ordering: Optional[List[int]]
|
||||
extra_int_constants: List[Tuple[int]]
|
||||
|
||||
# Make sure mypyc loads the annotation string for this forward reference.
|
||||
# Ref: https://github.com/mypyc/mypyc/issues/938
|
||||
class ClassIR: pass
|
||||
|
||||
# Ref: https://github.com/mypyc/mypyc/issues/927
|
||||
@final
|
||||
class Inextensible(NamedTuple):
|
||||
x: int
|
||||
|
||||
[file driver.py]
|
||||
from typing import ForwardRef, Optional
|
||||
from native import ClassIR, FuncIR, Record
|
||||
|
||||
assert Record.__annotations__ == {
|
||||
'st_mtime': float,
|
||||
'st_size': int,
|
||||
'is_borrowed': bool,
|
||||
'hash': str,
|
||||
'python_path': tuple,
|
||||
'type': ForwardRef('ClassIR'),
|
||||
'method': FuncIR,
|
||||
'shadow_method': type,
|
||||
'classes': dict,
|
||||
'steals': type,
|
||||
'ordering': type,
|
||||
'extra_int_constants': list,
|
||||
}, Record.__annotations__
|
||||
|
||||
[case testTupleOps]
|
||||
from typing import Tuple, List, Any, Optional
|
||||
from typing_extensions import Final
|
||||
|
||||
def f() -> Tuple[()]:
|
||||
return ()
|
||||
|
||||
def test_empty_tuple() -> None:
|
||||
assert f() == ()
|
||||
|
||||
def f2() -> Any:
|
||||
return ()
|
||||
|
||||
def test_empty_tuple_with_any_type():
|
||||
assert f2() == ()
|
||||
|
||||
def f3() -> int:
|
||||
x = (False, 1)
|
||||
return x[1]
|
||||
|
||||
def test_new_tuple() -> None:
|
||||
assert f3() == 1
|
||||
|
||||
def f4(y: int) -> int:
|
||||
x = (False, y)
|
||||
return x[1]
|
||||
|
||||
def test_new_tuple_boxed_int() -> None:
|
||||
big_number = 1208925819614629174706176
|
||||
assert f4(big_number) == big_number
|
||||
|
||||
def f5(x: List[int]) -> int:
|
||||
return tuple(x)[1]
|
||||
|
||||
def test_sequence_tuple() -> None:
|
||||
assert f5([1,2,3,4]) == 2
|
||||
|
||||
def f6(x: List[int]) -> int:
|
||||
return len(tuple(x))
|
||||
|
||||
def test_sequence_tuple_len() -> None:
|
||||
assert f6([1,2,3,4]) == 4
|
||||
|
||||
def f7(x: List[Tuple[int, int]]) -> int:
|
||||
a, b = x[0]
|
||||
return a + b
|
||||
|
||||
def test_unbox_tuple() -> None:
|
||||
assert f7([(5, 6)]) == 11
|
||||
|
||||
# Test that order is irrelevant to unions. Really I only care that this builds.
|
||||
|
||||
class A:
|
||||
pass
|
||||
|
||||
def lol() -> A:
|
||||
return A()
|
||||
|
||||
def foo(x: bool, y: bool) -> Tuple[Optional[A], bool]:
|
||||
z = lol()
|
||||
|
||||
return None if y else z, x
|
||||
|
||||
def test_slicing() -> None:
|
||||
# Use dummy adds to avoid constant folding
|
||||
zero = int()
|
||||
two = zero + 2
|
||||
s: Tuple[str, ...] = ("f", "o", "o", "b", "a", "r")
|
||||
assert s[two:] == ("o", "b", "a", "r")
|
||||
assert s[:two] == ("f", "o")
|
||||
assert s[two:-two] == ("o", "b")
|
||||
assert s[two:two] == ()
|
||||
assert s[two:two + 1] == ("o",)
|
||||
assert s[-two:] == ("a", "r")
|
||||
assert s[:-two] == ("f", "o", "o", "b")
|
||||
assert s[:] == ("f", "o", "o", "b", "a", "r")
|
||||
assert s[two:333] == ("o", "b", "a", "r")
|
||||
assert s[333:two] == ()
|
||||
assert s[two:-333] == ()
|
||||
assert s[-333:two] == ("f", "o")
|
||||
long_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000
|
||||
assert s[1:long_int] == ("o", "o", "b", "a", "r")
|
||||
assert s[long_int:] == ()
|
||||
assert s[-long_int:-1] == ("f", "o", "o", "b", "a")
|
||||
|
||||
def f8(val: int) -> bool:
|
||||
return val % 2 == 0
|
||||
|
||||
def test_sequence_generator() -> None:
|
||||
source_list = [1, 2, 3]
|
||||
a = tuple(f8(x) for x in source_list)
|
||||
assert a == (False, True, False)
|
||||
|
||||
source_tuple: Tuple[int, ...] = (1, 2, 3)
|
||||
a = tuple(f8(x) for x in source_tuple)
|
||||
assert a == (False, True, False)
|
||||
|
||||
source_fixed_length_tuple = (1, 2, 3, 4)
|
||||
a = tuple(f8(x) for x in source_fixed_length_tuple)
|
||||
assert a == (False, True, False, True)
|
||||
|
||||
source_str = 'abbc'
|
||||
b = tuple('s:' + x for x in source_str)
|
||||
assert b == ('s:a', 's:b', 's:b', 's:c')
|
||||
|
||||
TUPLE: Final[Tuple[str, ...]] = ('x', 'y')
|
||||
|
||||
def test_final_boxed_tuple() -> None:
|
||||
t = TUPLE
|
||||
assert t == ('x', 'y')
|
||||
303
venv/lib/python3.12/site-packages/mypyc/test-data/run-u8.test
Normal file
303
venv/lib/python3.12/site-packages/mypyc/test-data/run-u8.test
Normal file
@@ -0,0 +1,303 @@
|
||||
[case testU8BasicOps]
|
||||
from typing import Any, Tuple
|
||||
|
||||
from mypy_extensions import u8, i16, i32, i64
|
||||
from typing_extensions import Final
|
||||
|
||||
from testutil import assertRaises
|
||||
|
||||
ERROR: Final = 239
|
||||
|
||||
def test_box_and_unbox() -> None:
|
||||
for i in range(0, 256):
|
||||
o: Any = i
|
||||
x: u8 = o
|
||||
o2: Any = x
|
||||
assert o == o2
|
||||
assert x == i
|
||||
with assertRaises(OverflowError, "int too large or small to convert to u8"):
|
||||
o = 256
|
||||
x2: u8 = o
|
||||
with assertRaises(OverflowError, "int too large or small to convert to u8"):
|
||||
o = -1
|
||||
x3: u8 = o
|
||||
|
||||
def div_by_7(x: u8) -> u8:
|
||||
return x // 7
|
||||
|
||||
def div(x: u8, y: u8) -> u8:
|
||||
return x // y
|
||||
|
||||
def test_divide_by_constant() -> None:
|
||||
for i in range(0, 256):
|
||||
assert div_by_7(i) == i // 7
|
||||
|
||||
def test_divide_by_variable() -> None:
|
||||
for x in range(0, 256):
|
||||
for y in range(0, 256):
|
||||
if y != 0:
|
||||
assert div(x, y) == x // y
|
||||
else:
|
||||
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
|
||||
div(x, y)
|
||||
|
||||
def mod_by_7(x: u8) -> u8:
|
||||
return x % 7
|
||||
|
||||
def mod(x: u8, y: u8) -> u8:
|
||||
return x % y
|
||||
|
||||
def test_mod_by_constant() -> None:
|
||||
for i in range(0, 256):
|
||||
assert mod_by_7(i) == i % 7
|
||||
|
||||
def test_mod_by_variable() -> None:
|
||||
for x in range(0, 256):
|
||||
for y in range(0, 256):
|
||||
if y != 0:
|
||||
assert mod(x, y) == x % y
|
||||
else:
|
||||
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
|
||||
mod(x, y)
|
||||
|
||||
def test_simple_arithmetic_ops() -> None:
|
||||
zero: u8 = int()
|
||||
one: u8 = zero + 1
|
||||
two: u8 = one + 1
|
||||
neg_one: u8 = -one
|
||||
assert neg_one == 255
|
||||
assert one + one == 2
|
||||
assert one + two == 3
|
||||
assert one + neg_one == 0
|
||||
assert one - one == 0
|
||||
assert one - two == 255
|
||||
assert one * one == 1
|
||||
assert one * two == 2
|
||||
assert two * two == 4
|
||||
assert two * neg_one == 254
|
||||
assert neg_one * one == 255
|
||||
assert neg_one * neg_one == 1
|
||||
assert two * 0 == 0
|
||||
assert 0 * two == 0
|
||||
assert -one == 255
|
||||
assert -two == 254
|
||||
assert -neg_one == 1
|
||||
assert -zero == 0
|
||||
|
||||
def test_bitwise_ops() -> None:
|
||||
x: u8 = 184 + int()
|
||||
y: u8 = 79 + int()
|
||||
z: u8 = 113 + int()
|
||||
zero: u8 = int()
|
||||
one: u8 = zero + 1
|
||||
two: u8 = zero + 2
|
||||
neg_one: u8 = -one
|
||||
|
||||
assert x & y == 8
|
||||
assert x & z == 48
|
||||
assert z & z == z
|
||||
assert x & zero == 0
|
||||
|
||||
assert x | y == 255
|
||||
assert x | z == 249
|
||||
assert z | z == z
|
||||
assert x | 0 == x
|
||||
|
||||
assert x ^ y == 247
|
||||
assert x ^ z == 201
|
||||
assert z ^ z == 0
|
||||
assert z ^ 0 == z
|
||||
|
||||
assert x << one == 112
|
||||
assert x << two == 224
|
||||
assert z << two == 196
|
||||
assert z << 0 == z
|
||||
|
||||
assert x >> one == 92
|
||||
assert x >> two == 46
|
||||
assert z >> two == 28
|
||||
assert z >> 0 == z
|
||||
|
||||
for i in range(256):
|
||||
t: u8 = i
|
||||
assert ~t == (~(i + int()) & 0xff)
|
||||
|
||||
def eq(x: u8, y: u8) -> bool:
|
||||
return x == y
|
||||
|
||||
def test_eq() -> None:
|
||||
assert eq(int(), int())
|
||||
assert eq(5 + int(), 5 + int())
|
||||
assert not eq(int(), 1 + int())
|
||||
assert not eq(5 + int(), 6 + int())
|
||||
|
||||
def test_comparisons() -> None:
|
||||
one: u8 = 1 + int()
|
||||
one2: u8 = 1 + int()
|
||||
two: u8 = 2 + int()
|
||||
assert one < two
|
||||
assert not (one < one2)
|
||||
assert not (two < one)
|
||||
assert two > one
|
||||
assert not (one > one2)
|
||||
assert not (one > two)
|
||||
assert one <= two
|
||||
assert one <= one2
|
||||
assert not (two <= one)
|
||||
assert two >= one
|
||||
assert one >= one2
|
||||
assert not (one >= two)
|
||||
assert one == one2
|
||||
assert not (one == two)
|
||||
assert one != two
|
||||
assert not (one != one2)
|
||||
|
||||
def test_mixed_comparisons() -> None:
|
||||
u8_3: u8 = int() + 3
|
||||
int_5 = int() + 5
|
||||
assert u8_3 < int_5
|
||||
assert int_5 > u8_3
|
||||
b = u8_3 > int_5
|
||||
assert not b
|
||||
|
||||
int_largest = int() + 255
|
||||
assert int_largest > u8_3
|
||||
int_smallest = int()
|
||||
assert u8_3 > int_smallest
|
||||
|
||||
int_too_big = int() + 256
|
||||
int_too_small = int() -1
|
||||
with assertRaises(OverflowError):
|
||||
assert u8_3 < int_too_big
|
||||
with assertRaises(OverflowError):
|
||||
assert int_too_big < u8_3
|
||||
with assertRaises(OverflowError):
|
||||
assert u8_3 > int_too_small
|
||||
with assertRaises(OverflowError):
|
||||
assert int_too_small < u8_3
|
||||
|
||||
def test_mixed_arithmetic_and_bitwise_ops() -> None:
|
||||
u8_3: u8 = int() + 3
|
||||
int_5 = int() + 5
|
||||
assert u8_3 + int_5 == 8
|
||||
assert int_5 - u8_3 == 2
|
||||
assert u8_3 << int_5 == 96
|
||||
assert int_5 << u8_3 == 40
|
||||
assert u8_3 ^ int_5 == 6
|
||||
assert int_5 | u8_3 == 7
|
||||
|
||||
int_largest = int() + 255
|
||||
assert int_largest - u8_3 == 252
|
||||
int_smallest = int()
|
||||
assert int_smallest + u8_3 == 3
|
||||
|
||||
int_too_big = int() + 256
|
||||
int_too_small = int() - 1
|
||||
with assertRaises(OverflowError):
|
||||
assert u8_3 & int_too_big
|
||||
with assertRaises(OverflowError):
|
||||
assert int_too_small & u8_3
|
||||
|
||||
def test_coerce_to_and_from_int() -> None:
|
||||
for n in range(0, 256):
|
||||
x: u8 = n
|
||||
m: int = x
|
||||
assert m == n
|
||||
|
||||
def test_explicit_conversion_to_u8() -> None:
|
||||
x = u8(5)
|
||||
assert x == 5
|
||||
y = int() + ERROR
|
||||
x = u8(y)
|
||||
assert x == ERROR
|
||||
n64: i64 = 233
|
||||
x = u8(n64)
|
||||
assert x == 233
|
||||
n32: i32 = 234
|
||||
x = u8(n32)
|
||||
assert x == 234
|
||||
z = u8(x)
|
||||
assert z == 234
|
||||
n16: i16 = 231
|
||||
x = u8(n16)
|
||||
assert x == 231
|
||||
|
||||
def test_explicit_conversion_overflow() -> None:
|
||||
max_u8 = int() + 255
|
||||
x = u8(max_u8)
|
||||
assert x == 255
|
||||
assert int(x) == max_u8
|
||||
|
||||
min_u8 = int()
|
||||
y = u8(min_u8)
|
||||
assert y == 0
|
||||
assert int(y) == min_u8
|
||||
|
||||
too_big = int() + 256
|
||||
with assertRaises(OverflowError):
|
||||
x = u8(too_big)
|
||||
|
||||
too_small = int() - 1
|
||||
with assertRaises(OverflowError):
|
||||
x = u8(too_small)
|
||||
|
||||
def test_u8_from_large_small_literal() -> None:
|
||||
x = u8(255) # XXX u8(2**15 - 1)
|
||||
assert x == 255
|
||||
x = u8(0)
|
||||
assert x == 0
|
||||
|
||||
def test_u8_truncate_from_i64() -> None:
|
||||
large = i64(2**32 + 256 + 157 + int())
|
||||
x = u8(large)
|
||||
assert x == 157
|
||||
small = i64(-2**32 - 256 - 157 + int())
|
||||
x = u8(small)
|
||||
assert x == 256 - 157
|
||||
large2 = i64(2**8 + int())
|
||||
x = u8(large2)
|
||||
assert x == 0
|
||||
small2 = i64(-2**8 - 1 - int())
|
||||
x = u8(small2)
|
||||
assert x == 255
|
||||
|
||||
def test_u8_truncate_from_i32() -> None:
|
||||
large = i32(2**16 + 2**8 + 5 + int())
|
||||
assert u8(large) == 5
|
||||
small = i32(-2**16 - 2**8 - 1 + int())
|
||||
assert u8(small) == 255
|
||||
|
||||
def from_float(x: float) -> u8:
|
||||
return u8(x)
|
||||
|
||||
def test_explicit_conversion_from_float() -> None:
|
||||
assert from_float(0.0) == 0
|
||||
assert from_float(1.456) == 1
|
||||
assert from_float(234.567) == 234
|
||||
assert from_float(255) == 255
|
||||
assert from_float(0) == 0
|
||||
assert from_float(-0.999) == 0
|
||||
# The error message could be better, but this is acceptable
|
||||
with assertRaises(OverflowError, "int too large or small to convert to u8"):
|
||||
assert from_float(float(256))
|
||||
with assertRaises(OverflowError, "int too large or small to convert to u8"):
|
||||
# One ulp below the lowest valid i64 value
|
||||
from_float(float(-1.0))
|
||||
|
||||
def test_tuple_u8() -> None:
|
||||
a: u8 = 1
|
||||
b: u8 = 2
|
||||
t = (a, b)
|
||||
a, b = t
|
||||
assert a == 1
|
||||
assert b == 2
|
||||
x: Any = t
|
||||
tt: Tuple[u8, u8] = x
|
||||
assert tt == (1, 2)
|
||||
|
||||
def test_convert_u8_to_native_int() -> None:
|
||||
for i in range(256):
|
||||
x: u8 = i
|
||||
assert i16(x) == i
|
||||
assert i32(x) == i
|
||||
assert i64(x) == i
|
||||
Reference in New Issue
Block a user