Files
c3c/lib/std/core/builtin_comparison.c3
Zack Puhl c8d39251a9 Add compile-time @min and @max (#2378)
* Add compile-time `@min` and `@max`
2025-08-13 17:23:24 +02:00

162 lines
3.1 KiB
Plaintext

// Copyright (c) 2021-2024 Christoffer Lerno and contributors. All rights reserved.
// Use of this source code is governed by the MIT license
// a copy of which can be found in the LICENSE_STDLIB file.
module std::core::builtin;
<*
@require types::@comparable_value(a) && types::@comparable_value(b)
*>
macro less(a, b) @builtin
{
$switch:
$case $defined(a.less):
return a.less(b);
$case $defined(a.compare_to):
return a.compare_to(b) < 0;
$default:
return a < b;
$endswitch
}
<*
@require types::@comparable_value(a) && types::@comparable_value(b)
*>
macro less_eq(a, b) @builtin
{
$switch:
$case $defined(a.less):
return !b.less(a);
$case $defined(a.compare_to):
return a.compare_to(b) <= 0;
$default:
return a <= b;
$endswitch
}
<*
@require types::@comparable_value(a) && types::@comparable_value(b)
*>
macro greater(a, b) @builtin
{
$switch:
$case $defined(a.less):
return b.less(a);
$case $defined(a.compare_to):
return a.compare_to(b) > 0;
$default:
return a > b;
$endswitch
}
<*
@require types::@comparable_value(a) && types::@comparable_value(b)
*>
macro int compare_to(a, b) @builtin
{
$switch:
$case $defined(a.compare_to):
return a.compare_to(b);
$case $defined(a.less):
return (int)b.less(a) - (int)a.less(b);
$default:
return (int)(a > b) - (int)(a < b);
$endswitch
}
<*
@require types::@comparable_value(a) && types::@comparable_value(b)
*>
macro greater_eq(a, b) @builtin
{
$switch:
$case $defined(a.less):
return !a.less(b);
$case $defined(a.compare_to):
return a.compare_to(b) >= 0;
$default:
return a >= b;
$endswitch
}
<*
@require types::@equatable_value(a) && types::@equatable_value(b) : `values must be equatable`
*>
macro bool equals(a, b) @builtin
{
$switch:
$case $defined(a.equals, a.equals(b)):
return a.equals(b);
$case $defined(a.compare_to, a.compare_to(b)):
return a.compare_to(b) == 0;
$case $defined(a.less):
return !a.less(b) && !b.less(a);
$default:
return a == b;
$endswitch
}
macro min(x, ...) @builtin
{
$if $vacount == 1:
return less(x, $vaarg[0]) ? x : $vaarg[0];
$else
var result = x;
$for var $i = 0; $i < $vacount; $i++:
if (less($vaarg[$i], result))
{
result = $vaarg[$i];
}
$endfor
return result;
$endif
}
macro max(x, ...) @builtin
{
$if $vacount == 1:
return greater(x, $vaarg[0]) ? x : $vaarg[0];
$else
var result = x;
$for var $i = 0; $i < $vacount; $i++:
if (greater($vaarg[$i], result))
{
result = $vaarg[$i];
}
$endfor
return result;
$endif
}
<*
@require types::is_numerical($typeof($a))
*>
macro @max($a, ...) @builtin @const
{
$if $vacount == 1:
return $a > $vaconst[0] ? $a : $vaconst[0];
$else
var $result = $a;
$for var $x = 0; $x < $vacount; ++$x:
$if $vaconst[$x] > $result: $result = $vaconst[$x]; $endif
$endfor
return $result;
$endif
}
<*
@require types::is_numerical($typeof($a))
*>
macro @min($a, ...) @builtin @const
{
$if $vacount == 1:
return $a < $vaconst[0] ? $a : $vaconst[0];
$else
var $result = $a;
$for var $x = 0; $x < $vacount; ++$x:
$if $vaconst[$x] < $result: $result = $vaconst[$x]; $endif
$endfor
return $result;
$endif
}