Files
c3c/lib/std/sort/sort.c3

132 lines
4.0 KiB
Plaintext

module std::sort;
macro bool @list_is_by_ref(#list) @const
{
return $kindof(#list) == SLICE ||| ($kindof(#list) == POINTER &&& $kindof(*#list) != SLICE);
}
<*
@require @list_is_by_ref(#list) : "Expected the list to be passed by ref or be a slice"
*>
macro bool @is_sortable(#list) @const
{
$switch:
$case $kindof(#list) == SLICE:
return true;
$case !$defined(*#list):
return false;
$case !$defined((*#list)[0]):
return false;
$case !$defined(lengthof(*#list)):
return false;
$case $defined(&(*#list)[0]) &&& $typeof(&(*#list)[0]) != $typeof((*#list)[0])*:
return false;
$default:
return true;
$endswitch
}
macro bool @is_any_sortable(#list) @const
{
$switch $kindof(#list):
$case SLICE:
return true;
$case POINTER:
return @is_sortable(#list);
$default:
return $defined(#list[0]) &&& $defined(lengthof(#list))
&&& !($defined(&#list[0]) &&& $typeof(&#list[0]) != $typeof(#list[0])*);
$endswitch
}
macro bool @is_valid_context(#cmp, #context)
{
return @is_valid_macro_slot(#cmp) || @is_empty_macro_slot(#context);
}
<*
@require @list_is_by_ref(#list) : "Expected the list to be passed by ref or be a slice"
*>
macro bool @is_valid_cmp_fn(#cmp, #list, #context) @const
{
var $Type = $typeof(#cmp);
var $no_context = @is_empty_macro_slot(#context);
$switch:
$case @is_empty_macro_slot(#cmp): return true;
$case $Type.kindof != FUNC ||| $Type.returns.kindof != SIGNED_INT: return false;
$default:
$if $kindof(#list) == SLICE:
$switch:
$case $defined(#cmp((#list)[0], (#list)[0], #context)): return true;
$case $defined(#cmp((#list)[0], (#list)[0])): return $no_context;
$case $defined(#cmp(&(#list)[0], &(#list)[0], #context)): return true;
$case $defined(#cmp(&(#list)[0], &(#list)[0])): return $no_context;
$default: return false;
$endswitch
$else
$switch:
$case $defined(#cmp((*#list)[0], (*#list)[0], #context)): return true;
$case $defined(#cmp((*#list)[0], (*#list)[0])): return $no_context;
$case $defined(#cmp(&(*#list)[0], &(*#list)[0], #context)): return true;
$case $defined(#cmp(&(*#list)[0], &(*#list)[0])): return $no_context;
$default: return false;
$endswitch
$endif
$endswitch
}
macro bool @is_any_valid_cmp_fn(#cmp, #list, #context) @const
{
var $Type = $typeof(#cmp);
var $no_context = @is_empty_macro_slot(#context);
$switch:
$case @is_empty_macro_slot(#cmp): return true;
$case $Type.kindof != FUNC ||| $Type.returns.kindof != SIGNED_INT: return false;
$default:
$if $kindof(#list) != POINTER:
$switch:
$case $defined(#cmp((#list)[0], (#list)[0], #context)): return true;
$case $defined(#cmp((#list)[0], (#list)[0])): return $no_context;
$case $defined(#cmp(&(#list)[0], &(#list)[0], #context)): return true;
$case $defined(#cmp(&(#list)[0], &(#list)[0])): return $no_context;
$default: return false;
$endswitch
$else
$switch:
$case $defined(#cmp((*#list)[0], (*#list)[0], #context)): return true;
$case $defined(#cmp((*#list)[0], (*#list)[0])): return $no_context;
$case $defined(#cmp(&(*#list)[0], &(*#list)[0], #context)): return true;
$case $defined(#cmp(&(*#list)[0], &(*#list)[0])): return $no_context;
$default: return false;
$endswitch
$endif
$endswitch
}
<*
@require @list_is_by_ref(#list) : "Expected the list to be passed by ref or be a slice"
*>
macro bool @is_cmp_key_fn(#key_fn, #list) @const
{
$switch:
$case @is_empty_macro_slot(#key_fn): return true;
$case $kindof(#key_fn) != FUNC: return false;
$case $typeof(#key_fn).returns.kindof != UNSIGNED_INT: return false;
$default:
$if $kindof(#list) == SLICE:
$switch:
$case $defined(#key_fn((#list)[0])): return true;
$case $defined(#key_fn(&&((#list)[0]))): return true;
$default: return false;
$endswitch
$else
$switch:
$case $defined(#key_fn((*#list)[0])): return true;
$case $defined(#key_fn(&&((*#list)[0]))): return true;
$default: return false;
$endswitch
$endif
$endswitch
}