Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions mypyc/irbuild/specialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,27 +186,29 @@ def translate_set_from_generator_call(


@specialize_function('builtins.min')
def faster_min(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]:
@specialize_function('builtins.max')
def faster_min_max(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]:
if expr.arg_kinds == [ARG_POS, ARG_POS]:
x, y = builder.accept(expr.args[0]), builder.accept(expr.args[1])
result = Register(builder.node_type(expr))
comparison = builder.binary_op(y, x, '<', expr.line)
true = BasicBlock()
false = BasicBlock()
next_block = BasicBlock()
# CPython evaluates arguments reversely when calling min(...) or max(...)
if callee.fullname == 'builtins.min':
comparison = builder.binary_op(y, x, '<', expr.line)
else:
comparison = builder.binary_op(y, x, '>', expr.line)

builder.add_bool_branch(comparison, true, false)
true_block, false_block, next_block = BasicBlock(), BasicBlock(), BasicBlock()
builder.add_bool_branch(comparison, true_block, false_block)

builder.activate_block(true)
builder.activate_block(true_block)
builder.assign(result, builder.coerce(y, result.type, expr.line), expr.line)
builder.goto(next_block)

builder.activate_block(false)
builder.activate_block(false_block)
builder.assign(result, builder.coerce(x, result.type, expr.line), expr.line)
builder.goto(next_block)

builder.activate_block(next_block)

return result
return None

Expand Down
1 change: 1 addition & 0 deletions mypyc/test-data/fixtures/ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ def eval(e: str) -> Any: ...
def abs(x: float) -> float: ...
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: ...
Expand Down
26 changes: 26 additions & 0 deletions mypyc/test-data/irbuild-generics.test
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,29 @@ L0:
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 :: int32
r2 :: bit
r3 :: bool
r4 :: object
L0:
r0 = PyObject_RichCompare(y, x, 4)
r1 = PyObject_IsTrue(r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: int32 to builtins.bool
if r3 goto L1 else goto L2 :: bool
L1:
r4 = y
goto L3
L2:
r4 = x
L3:
return r4
14 changes: 13 additions & 1 deletion mypyc/test-data/run-dunders.test
Original file line number Diff line number Diff line change
Expand Up @@ -758,29 +758,41 @@ def test_in_place_operator_returns_none() -> None:
with assertRaises(TypeError, "native.BadInplaceAdd object expected; got None"):
o += 5

[case testDunderMin]
[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'
4 changes: 3 additions & 1 deletion mypyc/test-data/run-floats.test
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ def test_abs() -> None:
assert abs(-23.4) == 23.4
assert abs(-43.44e-4) == 43.44e-4

def test_float_min() -> None:
def test_float_min_max() -> None:
x: float = 20.0
y: float = 30.0
assert min(x, y) == 20.0
assert min(y, x) == 20.0
assert max(x, y) == 30.0
assert max(y, x) == 30.0
28 changes: 18 additions & 10 deletions mypyc/test-data/run-integers.test
Original file line number Diff line number Diff line change
Expand Up @@ -428,43 +428,51 @@ def test_constant_fold() -> None:
n64 = -(1 << 64) + int()
assert n64 == -(1 << 64)

[case testIntMin]
def test_int_min() -> None:
[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_min_2() -> None:
x: int = 30
y: int = 200
assert min(x, y) == 30

def test_int_hybrid_min() -> None:
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() -> None:
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() -> None:
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
4 changes: 3 additions & 1 deletion mypyc/test-data/run-strings.test
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,14 @@ def test_str_to_bool() -> None:
assert is_true(x)
assert not is_false(x)

def test_str_min() -> None:
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]
Expand Down