| [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 |