module assert_repro;
import assert_repro::macros;

struct ArrayEntry
{
    int x;
}

macro cause_assert()
{
    ArrayEntry[] $slice = {{1}, {2}, {3}};
    $slice = macros::replace {ArrayEntry} ($slice, 0, {4});
}

fn int main()
{
    cause_assert();
    return 0;
}
<*
    This contains macros for working with arrays at compile time
*>
module assert_repro::macros <ValueT>;
alias SliceT = ValueT[];

macro SliceT slice(SliceT $from, usz $start, usz $end = usz.max)
{
    $if $start >= $from.len:
        return (SliceT){};
    $else
        $if $end >= $from.len:
            return $from[$start..];
        $else
            return $from[$start..$end-1];
        $endif
    $endif
}


macro SliceT insert(SliceT $array, usz $position, ValueT $value)
{
    $if $position == $array.len:
        return $array +++ {$value};
    $else
        $if $position == 0:
            return {$value} +++ $array;
        $else
            return slice($array, 0, $position) +++ {$value} +++ slice($array, $position);
        $endif
    $endif
}

macro SliceT remove(SliceT $array, usz $position)
{
    $if $position == $array.len - 1:
        return slice($array, 0, $array.len - 1);
    $else
        $if $position == 0:
            return slice($array, 1);
        $else
            return slice($array, 0, $position) +++ slice($array, $position + 1);
        $endif
    $endif
}

macro SliceT replace(SliceT $array, usz $position, ValueT $value)
{
    return insert(remove($array,$position),$position,$value);
}