mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
[stdlib] Reduce inline code volume from sorting macros (#2831)
* reduce codegen in sorting macros * remove testing file... * Fix and some renaming, removing some sub-modules that should not be in use. --------- Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
@@ -9,11 +9,18 @@ in [0, array.len) where x would be inserted or cmp(i) is true and cmp(j) is true
|
|||||||
@require @is_valid_cmp_fn(#cmp: ...cmp, #list: list, #context: ...context) : "Expected a comparison function which compares values"
|
@require @is_valid_cmp_fn(#cmp: ...cmp, #list: list, #context: ...context) : "Expected a comparison function which compares values"
|
||||||
@require @is_valid_context(...cmp, ...context) : "Expected a valid context"
|
@require @is_valid_context(...cmp, ...context) : "Expected a valid context"
|
||||||
*>
|
*>
|
||||||
macro usz binarysearch(list, x, cmp = ..., context = ...) @builtin
|
macro usz binarysearch(list, element, cmp = ..., context = ...) @builtin
|
||||||
|
{
|
||||||
|
var used_cmp = $defined(cmp) ??? cmp : (TypeNotSet)null;
|
||||||
|
var used_ctx = $defined(context) ??? context : (TypeNotSet)null;
|
||||||
|
return _binarysearch{$typeof(list), $typeof(element), $typeof(used_cmp), $typeof(used_ctx)}(list, element, used_cmp, used_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usz _binarysearch(ListType list, ElementType element, CmpFnType cmp, ContextType context) <ListType, ElementType, CmpFnType, ContextType> @noinline @local
|
||||||
{
|
{
|
||||||
usz i;
|
usz i;
|
||||||
var $no_cmp = !$defined(cmp);
|
var $no_cmp = $typeof(cmp) == TypeNotSet;
|
||||||
var $has_context = $defined(context);
|
var $has_context = $typeof(context) != TypeNotSet;
|
||||||
|
|
||||||
$if $kindof(list) == SLICE:
|
$if $kindof(list) == SLICE:
|
||||||
usz len = lengthof(list);
|
usz len = lengthof(list);
|
||||||
@@ -23,23 +30,23 @@ macro usz binarysearch(list, x, cmp = ..., context = ...) @builtin
|
|||||||
$if $no_cmp:
|
$if $no_cmp:
|
||||||
switch
|
switch
|
||||||
{
|
{
|
||||||
case greater(list[half], x): j = half;
|
case greater(list[half], element): j = half;
|
||||||
case less(list[half], x): i = half + 1;
|
case less(list[half], element): i = half + 1;
|
||||||
default: return half;
|
default: return half;
|
||||||
}
|
}
|
||||||
$else
|
$else
|
||||||
|
|
||||||
$switch:
|
$switch:
|
||||||
$case $defined(cmp(list[0], list[0], context)):
|
$case $defined(cmp(list[0], list[0], context)):
|
||||||
int res = cmp(list[half], x, context);
|
int res = cmp(list[half], element, context);
|
||||||
$case $defined(cmp(list[0], list[0])):
|
$case $defined(cmp(list[0], list[0])):
|
||||||
assert(!$has_context);
|
assert(!$has_context);
|
||||||
int res = cmp(list[half], x);
|
int res = cmp(list[half], element);
|
||||||
$case $defined(cmp(&list[0], &list[0], context)):
|
$case $defined(cmp(&list[0], &list[0], context)):
|
||||||
int res = cmp(&list[half], &x, context);
|
int res = cmp(&list[half], &element, context);
|
||||||
$case $defined(cmp(&list[0], &list[0])):
|
$case $defined(cmp(&list[0], &list[0])):
|
||||||
assert(!$has_context);
|
assert(!$has_context);
|
||||||
int res = cmp(&list[half], &x);
|
int res = cmp(&list[half], &element);
|
||||||
$default:
|
$default:
|
||||||
assert(false, "Invalid comparison function");
|
assert(false, "Invalid comparison function");
|
||||||
$endswitch
|
$endswitch
|
||||||
@@ -59,23 +66,22 @@ macro usz binarysearch(list, x, cmp = ..., context = ...) @builtin
|
|||||||
$if $no_cmp:
|
$if $no_cmp:
|
||||||
switch
|
switch
|
||||||
{
|
{
|
||||||
case greater((*list)[half], x): j = half;
|
case greater((*list)[half], element): j = half;
|
||||||
case less((*list)[half], x): i = half + 1;
|
case less((*list)[half], element): i = half + 1;
|
||||||
default: return half;
|
default: return half;
|
||||||
}
|
}
|
||||||
$else
|
$else
|
||||||
|
|
||||||
$switch:
|
$switch:
|
||||||
$case $defined(cmp((*list)[0], (*list)[0], context)):
|
$case $defined(cmp((*list)[0], (*list)[0], context)):
|
||||||
int res = cmp(list[half], x, context);
|
int res = cmp(list[half], element, context);
|
||||||
$case $defined(cmp((*list)[0], (*list)[0])):
|
$case $defined(cmp((*list)[0], (*list)[0])):
|
||||||
assert(!$has_context);
|
assert(!$has_context);
|
||||||
int res = cmp((*list)[half], x);
|
int res = cmp((*list)[half], element);
|
||||||
$case $defined(cmp(&(*list)[0], &(*list)[0], context)):
|
$case $defined(cmp(&(*list)[0], &(*list)[0], context)):
|
||||||
int res = cmp(&(*list)[half], &x, context);
|
int res = cmp(&(*list)[half], &element, context);
|
||||||
$case $defined(cmp(&(*list)[0], &(*list)[0])):
|
$case $defined(cmp(&(*list)[0], &(*list)[0])):
|
||||||
assert(!$has_context);
|
assert(!$has_context);
|
||||||
int res = cmp(&(*list)[half], &x);
|
int res = cmp(&(*list)[half], &element);
|
||||||
$default:
|
$default:
|
||||||
assert(false, "Invalid comparison function");
|
assert(false, "Invalid comparison function");
|
||||||
$endswitch
|
$endswitch
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
module std::sort;
|
module std::sort;
|
||||||
import std::sort::is;
|
|
||||||
import std::sort::cs @public;
|
|
||||||
import std::sort::qs;
|
|
||||||
|
|
||||||
<*
|
<*
|
||||||
Sort list using the counting sort algorithm.
|
Sort list using the counting sort algorithm.
|
||||||
@@ -15,38 +12,36 @@ macro void countingsort(list, key_fn = ...) @builtin
|
|||||||
var list_length = $kindof(list) == SLICE ??? list.len : lengthof(*list);
|
var list_length = $kindof(list) == SLICE ??? list.len : lengthof(*list);
|
||||||
var $ListType = $kindof(list) == SLICE ??? $typeof(list) : $typeof(*list);
|
var $ListType = $kindof(list) == SLICE ??? $typeof(list) : $typeof(*list);
|
||||||
$if $defined(key_fn):
|
$if $defined(key_fn):
|
||||||
cs::csort{$ListType, $typeof(key_fn)}(list, 0, list_length, key_fn, ~(uint)0);
|
csort{$ListType, $typeof(key_fn)}(list, 0, list_length, key_fn, ~(uint)0);
|
||||||
$else
|
$else
|
||||||
cs::csort{$ListType, void*}(list, 0, list_length, ~(uint)0);
|
csort{$ListType, void*}(list, 0, list_length, ~(uint)0);
|
||||||
$endif
|
$endif
|
||||||
}
|
}
|
||||||
|
|
||||||
macro void insertionsort_indexed(list, start, end, cmp = ..., context = ...) @builtin
|
macro void insertionsort_indexed(list, start, end, cmp = ..., context = ...) @builtin
|
||||||
{
|
{
|
||||||
// When the context or cmp functions are not defined, we can simply use a dummy/default type.
|
var used_cmp = $defined(cmp) ??? cmp : (TypeNotSet)null;
|
||||||
var $CmpFnType = $defined(cmp) ??? $typeof(cmp) : uint;
|
var used_ctx = $defined(context) ??? context : (TypeNotSet)null;
|
||||||
var $ContextType = $defined(context) ??? $typeof(context) : uint;
|
|
||||||
$if $kindof(list) == SLICE:
|
$if $kindof(list) == SLICE:
|
||||||
is::isort{$typeof((list)), $CmpFnType, $ContextType}(list, (usz)start, (usz)end, ...cmp, ...context);
|
isort{$typeof((list)), $typeof(used_cmp), $typeof(used_ctx)}(list, (usz)start, (usz)end, used_cmp, used_ctx);
|
||||||
$else
|
$else
|
||||||
is::isort{$typeof((*list)), $CmpFnType, $ContextType}(list, (usz)start, (usz)end, ...cmp, ...context);
|
isort{$typeof((*list)), $typeof(used_cmp), $typeof(used_ctx)}(list, (usz)start, (usz)end, used_cmp, used_ctx);
|
||||||
$endif
|
$endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro void quicksort_indexed(list, start, end, cmp = ..., context = ...) @builtin
|
macro void quicksort_indexed(list, start, end, cmp = ..., context = ...) @builtin
|
||||||
{
|
{
|
||||||
// When the context or cmp functions are not defined, we can simply use a dummy/default type.
|
var used_cmp = $defined(cmp) ??? cmp : (TypeNotSet)null;
|
||||||
var $CmpFnType = $defined(cmp) ??? $typeof(cmp) : uint;
|
var used_ctx = $defined(context) ??? context : (TypeNotSet)null;
|
||||||
var $ContextType = $defined(context) ??? $typeof(context) : uint;
|
|
||||||
$if $kindof(list) == SLICE:
|
$if $kindof(list) == SLICE:
|
||||||
qs::qsort{$typeof((list)), $CmpFnType, $ContextType}(list, (isz)start, (isz)(end-1), ...cmp, ...context);
|
qsort{$typeof((list)), $typeof(used_cmp), $typeof(used_ctx)}(list, (isz)start, (isz)(end-1), used_cmp, used_ctx);
|
||||||
$else
|
$else
|
||||||
qs::qsort{$typeof((*list)), $CmpFnType, $ContextType}(list, (isz)start, (isz)(end-1), ...cmp, ...context);
|
qsort{$typeof((*list)), $typeof(used_cmp), $typeof(used_ctx)}(list, (isz)start, (isz)(end-1), used_cmp, used_ctx);
|
||||||
$endif
|
$endif
|
||||||
}
|
}
|
||||||
|
|
||||||
module std::sort::cs <Type, KeyFn>;
|
module std::sort <Type, KeyFn> @private;
|
||||||
|
|
||||||
alias Counts @private = usz[256];
|
alias Counts @private = usz[256];
|
||||||
alias Ranges @private = usz[257];
|
alias Ranges @private = usz[257];
|
||||||
@@ -90,7 +85,7 @@ fn void csort(ListType list, usz low, usz high, uint byte_idx) @if (NO_KEY_FN)
|
|||||||
In other words, `csort(a_list, low, high, key_fn: some_fn, byte_idx: index_val)` breaks the existing API
|
In other words, `csort(a_list, low, high, key_fn: some_fn, byte_idx: index_val)` breaks the existing API
|
||||||
since explicitly naming `byte_idx` becomes a requirement.
|
since explicitly naming `byte_idx` becomes a requirement.
|
||||||
*>
|
*>
|
||||||
macro void _csort(ListType list, usz low, usz high, uint byte_idx, KeyFn key_fn = ...) @private
|
macro void _csort(ListType list, usz low, usz high, uint byte_idx, KeyFn key_fn = ...)
|
||||||
{
|
{
|
||||||
if (high <= low) return;
|
if (high <= low) return;
|
||||||
$if NO_KEY_FN:
|
$if NO_KEY_FN:
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
module std::sort;
|
module std::sort;
|
||||||
import std::sort::is;
|
|
||||||
|
|
||||||
<*
|
<*
|
||||||
Sort list using the quick sort algorithm.
|
Sort list using the quick sort algorithm.
|
||||||
@@ -10,17 +9,16 @@ import std::sort::is;
|
|||||||
*>
|
*>
|
||||||
macro void insertionsort(list, cmp = ..., context = ...) @builtin @safemacro
|
macro void insertionsort(list, cmp = ..., context = ...) @builtin @safemacro
|
||||||
{
|
{
|
||||||
// When the context or cmp functions are not defined, we can simply use a dummy/default type.
|
var used_cmp = $defined(cmp) ??? cmp : (TypeNotSet)null;
|
||||||
var $CmpFnType = $defined(cmp) ??? $typeof(cmp) : uint;
|
var used_ctx = $defined(context) ??? context : (TypeNotSet)null;
|
||||||
var $ContextType = $defined(context) ??? $typeof(context) : uint;
|
|
||||||
$if $kindof(list) == SLICE:
|
$if $kindof(list) == SLICE:
|
||||||
is::isort{$typeof(list), $CmpFnType, $ContextType}(list, 0, lengthof(list), ...cmp, ...context);
|
isort{$typeof(list), $typeof(used_cmp), $typeof(used_ctx)}(list, 0, lengthof(list), used_cmp, used_ctx);
|
||||||
$else
|
$else
|
||||||
is::isort{$typeof(*list), $CmpFnType, $ContextType}(list, 0, lengthof(*list), ...cmp, ...context);
|
isort{$typeof(*list), $typeof(used_cmp), $typeof(used_ctx)}(list, 0, lengthof(*list), used_cmp, used_ctx);
|
||||||
$endif
|
$endif
|
||||||
}
|
}
|
||||||
|
|
||||||
module std::sort::is <Type, CmpFn, Context>;
|
module std::sort <Type, CmpFn, Context> @private;
|
||||||
|
|
||||||
alias ElementType = $typeof(((Type){})[0]);
|
alias ElementType = $typeof(((Type){})[0]);
|
||||||
const bool IS_SLICE = Type.kindof == SLICE;
|
const bool IS_SLICE = Type.kindof == SLICE;
|
||||||
@@ -28,10 +26,10 @@ alias ListType = $typefrom(IS_SLICE ??? Type : Type*);
|
|||||||
macro ElementType list_get(ListType l, i) => IS_SLICE ??? l[i] : (*l)[i];
|
macro ElementType list_get(ListType l, i) => IS_SLICE ??? l[i] : (*l)[i];
|
||||||
macro ElementType* list_get_ref(ListType l, i) => IS_SLICE ??? &l[i] : &(*l)[i];
|
macro ElementType* list_get_ref(ListType l, i) => IS_SLICE ??? &l[i] : &(*l)[i];
|
||||||
|
|
||||||
macro void isort(ListType list, usz low, usz high, CmpFn comp = ..., Context context = ...)
|
fn void isort(ListType list, usz low, usz high, CmpFn comp, Context context) @noinline @private
|
||||||
{
|
{
|
||||||
var $has_cmp = $defined(comp);
|
var $has_cmp = $typeof(comp) != TypeNotSet;
|
||||||
var $has_context = $defined(context);
|
var $has_context = $typeof(context) != TypeNotSet;
|
||||||
var $cmp_by_value = $has_cmp &&& $defined($typefrom(CmpFn.paramsof[0].type) p = list_get(list, 0));
|
var $cmp_by_value = $has_cmp &&& $defined($typefrom(CmpFn.paramsof[0].type) p = list_get(list, 0));
|
||||||
var $has_get_ref = IS_SLICE ||| $defined(&(*list)[0]);
|
var $has_get_ref = IS_SLICE ||| $defined(&(*list)[0]);
|
||||||
for (usz i = low; i < high; ++i)
|
for (usz i = low; i < high; ++i)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
module std::sort;
|
module std::sort;
|
||||||
import std::sort::qs;
|
|
||||||
|
|
||||||
<*
|
<*
|
||||||
Sort list using the quick sort algorithm.
|
Sort list using the quick sort algorithm.
|
||||||
@@ -11,13 +10,12 @@ import std::sort::qs;
|
|||||||
*>
|
*>
|
||||||
macro void quicksort(list, cmp = ..., context = ...) @builtin
|
macro void quicksort(list, cmp = ..., context = ...) @builtin
|
||||||
{
|
{
|
||||||
// When the context or cmp functions are not defined, we can simply use a dummy/default type.
|
var used_cmp = $defined(cmp) ??? cmp : (TypeNotSet)null;
|
||||||
var $CmpFnType = $defined(cmp) ??? $typeof(cmp) : uint;
|
var used_ctx = $defined(context) ??? context : (TypeNotSet)null;
|
||||||
var $ContextType = $defined(context) ??? $typeof(context) : uint;
|
|
||||||
$if $kindof(list) == SLICE:
|
$if $kindof(list) == SLICE:
|
||||||
qs::qsort{$typeof(list), $CmpFnType, $ContextType}(list, 0, (isz)list.len - 1, ...cmp, ...context);
|
qsort{$typeof(list), $typeof(used_cmp), $typeof(used_ctx)}(list, 0, (isz)list.len - 1, used_cmp, used_ctx);
|
||||||
$else
|
$else
|
||||||
qs::qsort{$typeof(*list), $CmpFnType, $ContextType}(list, 0, (isz)lengthof(*list) - 1, ...cmp, ...context);
|
qsort{$typeof(*list), $typeof(used_cmp), $typeof(used_ctx)}(list, 0, (isz)lengthof(*list) - 1, used_cmp, used_ctx);
|
||||||
$endif
|
$endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,17 +31,17 @@ macro void quicksort(list, cmp = ..., context = ...) @builtin
|
|||||||
*>
|
*>
|
||||||
macro quickselect(list, isz k, cmp = ..., context = ...) @builtin
|
macro quickselect(list, isz k, cmp = ..., context = ...) @builtin
|
||||||
{
|
{
|
||||||
// When the context or cmp functions are not defined, we can simply use a dummy/default type.
|
var used_cmp = $defined(cmp) ??? cmp : (TypeNotSet)null;
|
||||||
var $CmpFnType = $defined(cmp) ??? $typeof(cmp) : uint;
|
var used_ctx = $defined(context) ??? context : (TypeNotSet)null;
|
||||||
var $ContextType = $defined(context) ??? $typeof(context) : uint;
|
|
||||||
$if $kindof(list) == SLICE:
|
$if $kindof(list) == SLICE:
|
||||||
return qs::qselect{$typeof(list), $CmpFnType, $ContextType}(list, 0, (isz)list.len - 1, k, ...cmp, ...context);
|
return qselect{$typeof(list), $typeof(used_cmp), $typeof(used_ctx)}(list, 0, (isz)list.len - 1, k, used_cmp, used_ctx);
|
||||||
$else
|
$else
|
||||||
return qs::qselect{$typeof(*list), $CmpFnType, $ContextType}(list, 0, (isz)lengthof(*list) - 1, k, ...cmp, ...context);
|
return qselect{$typeof(*list), $typeof(used_cmp), $typeof(used_ctx)}(list, 0, (isz)lengthof(*list) - 1, k, used_cmp, used_ctx);
|
||||||
$endif
|
$endif
|
||||||
}
|
}
|
||||||
|
|
||||||
module std::sort::qs <Type, CmpFn, Context>;
|
|
||||||
|
module std::sort <Type, CmpFn, Context> @private;
|
||||||
|
|
||||||
alias ElementType = $typeof(((Type){})[0]);
|
alias ElementType = $typeof(((Type){})[0]);
|
||||||
const bool IS_SLICE = Type.kindof == SLICE;
|
const bool IS_SLICE = Type.kindof == SLICE;
|
||||||
@@ -65,7 +63,7 @@ alias Stack @private = StackElementItem[64];
|
|||||||
|
|
||||||
// Based on https://alienryderflex.com/quicksort by Darel Rex Finley, Public Domain.
|
// Based on https://alienryderflex.com/quicksort by Darel Rex Finley, Public Domain.
|
||||||
|
|
||||||
macro void qsort(ListType list, isz low, isz high, CmpFn cmp = ..., Context context = ...)
|
fn void qsort(ListType list, isz low, isz high, CmpFn cmp, Context context) @noinline
|
||||||
{
|
{
|
||||||
if (low >= 0 && high >= 0 && low < high)
|
if (low >= 0 && high >= 0 && low < high)
|
||||||
{
|
{
|
||||||
@@ -82,7 +80,7 @@ macro void qsort(ListType list, isz low, isz high, CmpFn cmp = ..., Context cont
|
|||||||
|
|
||||||
if (l < h)
|
if (l < h)
|
||||||
{
|
{
|
||||||
l = @partition(list, l, h, ...cmp, ...context);
|
l = @partition(list, l, h, cmp, context);
|
||||||
stack[i + 1].low = l + 1;
|
stack[i + 1].low = l + 1;
|
||||||
stack[i + 1].high = stack[i].high;
|
stack[i + 1].high = stack[i].high;
|
||||||
stack[i++].high = l;
|
stack[i++].high = l;
|
||||||
@@ -103,7 +101,7 @@ macro void qsort(ListType list, isz low, isz high, CmpFn cmp = ..., Context cont
|
|||||||
@require low <= k : "kth smallest element is smaller than lower bounds"
|
@require low <= k : "kth smallest element is smaller than lower bounds"
|
||||||
@require k <= high : "kth smallest element is larger than upper bounds"
|
@require k <= high : "kth smallest element is larger than upper bounds"
|
||||||
*>
|
*>
|
||||||
macro ElementType? qselect(ListType list, isz low, isz high, isz k, CmpFn cmp = ..., Context context = ...)
|
fn ElementType? qselect(ListType list, isz low, isz high, isz k, CmpFn cmp, Context context) @noinline
|
||||||
{
|
{
|
||||||
if (low >= 0 && high >= 0 && low < high)
|
if (low >= 0 && high >= 0 && low < high)
|
||||||
{
|
{
|
||||||
@@ -114,7 +112,7 @@ macro ElementType? qselect(ListType list, isz low, isz high, isz k, CmpFn cmp =
|
|||||||
usz max_retries = 64;
|
usz max_retries = 64;
|
||||||
while (l <= h && max_retries--)
|
while (l <= h && max_retries--)
|
||||||
{
|
{
|
||||||
pivot = @partition(list, l, h, ...cmp, ...context);
|
pivot = @partition(list, l, h, cmp, context);
|
||||||
if (k == pivot) return list_get(list, k);
|
if (k == pivot) return list_get(list, k);
|
||||||
if (k < pivot)
|
if (k < pivot)
|
||||||
{
|
{
|
||||||
@@ -129,10 +127,10 @@ macro ElementType? qselect(ListType list, isz low, isz high, isz k, CmpFn cmp =
|
|||||||
return NOT_FOUND~;
|
return NOT_FOUND~;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro isz @partition(ListType list, isz l, isz h, CmpFn cmp = ..., Context context = ...)
|
macro isz @partition(ListType list, isz l, isz h, CmpFn cmp, Context context)
|
||||||
{
|
{
|
||||||
var $has_cmp = $defined(cmp);
|
var $has_cmp = $typeof(cmp) != sort::TypeNotSet;
|
||||||
var $has_context = $defined(context);
|
var $has_context = $typeof(context) != sort::TypeNotSet;
|
||||||
var $cmp_by_value = $has_cmp &&& $defined($typefrom(CmpFn.paramsof[0].type) v = list_get(list, 0));
|
var $cmp_by_value = $has_cmp &&& $defined($typefrom(CmpFn.paramsof[0].type) v = list_get(list, 0));
|
||||||
|
|
||||||
ElementType pivot = list_get(list, l);
|
ElementType pivot = list_get(list, l);
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
module std::sort;
|
module std::sort;
|
||||||
|
|
||||||
|
<* Essentially `EmptySlot` but specifically for sorting macro expansions. *>
|
||||||
|
typedef TypeNotSet @private = void*;
|
||||||
|
|
||||||
macro bool @list_is_by_ref(#list) @const
|
macro bool @list_is_by_ref(#list) @const
|
||||||
{
|
{
|
||||||
return $kindof(#list) == SLICE ||| ($kindof(#list) == POINTER &&& $kindof(*#list) != SLICE);
|
return $kindof(#list) == SLICE ||| ($kindof(#list) == POINTER &&& $kindof(*#list) != SLICE);
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
### Changes / improvements
|
### Changes / improvements
|
||||||
|
|
||||||
### Stdlib changes
|
### Stdlib changes
|
||||||
|
- Summarize sort macros as generic function wrappers to reduce the amount of generated code. #2831
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Add error message if directory with output file name already exists
|
- Add error message if directory with output file name already exists
|
||||||
|
- Regression where nested lambdas would be evaluated twice.
|
||||||
|
|
||||||
## 0.7.9 Change list
|
## 0.7.9 Change list
|
||||||
|
|
||||||
|
|||||||
@@ -712,6 +712,7 @@ typedef struct Decl_
|
|||||||
bool no_strip : 1;
|
bool no_strip : 1;
|
||||||
bool is_cond : 1;
|
bool is_cond : 1;
|
||||||
bool is_if : 1;
|
bool is_if : 1;
|
||||||
|
bool is_body_checked : 1;
|
||||||
bool attr_nopadding : 1;
|
bool attr_nopadding : 1;
|
||||||
bool attr_compact : 1;
|
bool attr_compact : 1;
|
||||||
bool resolved_attributes : 1;
|
bool resolved_attributes : 1;
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ static inline bool sema_analyse_assert_stmt(SemaContext *context, Ast *statement
|
|||||||
*/
|
*/
|
||||||
static inline bool sema_analyse_break_stmt(SemaContext *context, Ast *statement)
|
static inline bool sema_analyse_break_stmt(SemaContext *context, Ast *statement)
|
||||||
{
|
{
|
||||||
|
ASSERT(!statement->contbreak_stmt.is_resolved);
|
||||||
// If there is no break target and there is no label,
|
// If there is no break target and there is no label,
|
||||||
// we skip.
|
// we skip.
|
||||||
if (!context->break_jump.target && !statement->contbreak_stmt.is_label)
|
if (!context->break_jump.target && !statement->contbreak_stmt.is_label)
|
||||||
@@ -3430,7 +3431,8 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func)
|
|||||||
{
|
{
|
||||||
// Stop if it's already poisoned.
|
// Stop if it's already poisoned.
|
||||||
if (!decl_ok(func)) return false;
|
if (!decl_ok(func)) return false;
|
||||||
|
if (func->is_body_checked) return true;
|
||||||
|
func->is_body_checked = true;
|
||||||
context->generic_instance = func->is_templated ? declptr(func->instance_id) : NULL;
|
context->generic_instance = func->is_templated ? declptr(func->instance_id) : NULL;
|
||||||
// Check the signature here we test for variadic raw, since we don't support it.
|
// Check the signature here we test for variadic raw, since we don't support it.
|
||||||
Signature *signature = &func->func_decl.signature;
|
Signature *signature = &func->func_decl.signature;
|
||||||
|
|||||||
Reference in New Issue
Block a user