- Compile time array assignment #1806.

- Allow `+++` to work on all types of arrays.
This commit is contained in:
Christoffer Lerno
2025-01-25 00:48:06 +01:00
parent eda997545a
commit e2b11c17bc
9 changed files with 2335 additions and 91 deletions

View File

@@ -8,6 +8,8 @@
- Error on switch case fallthough if there is more than one newline #1849.
- Added flags to `c3c project view` to filter displayed properties
- VERY experimental `<[ ]>` syntax for generics.
- Compile time array assignment #1806.
- Allow `+++` to work on all types of arrays.
### Fixes
- Fix issue requiring prefix on a generic interface declaration.

View File

@@ -772,6 +772,12 @@ typedef struct
SubscriptIndex index;
} ExprSubscript;
typedef struct
{
Decl *var;
ArrayIndex index;
} ExprCtSubscript;
typedef struct
{
ExprId expr;
@@ -1177,6 +1183,7 @@ struct Expr_
ExprSliceAssign slice_assign_expr; // 8
ExprSubscriptAssign subscript_assign_expr;
ExprSubscript subscript_expr; // 12
ExprCtSubscript ct_subscript_expr;
ExprSlice slice_expr;
ExprSwizzle swizzle_expr;
ExprTernary ternary_expr; // 16
@@ -3281,6 +3288,7 @@ ConstInitializer *const_init_new_zero_array_value(Type *type, ArrayIndex index);
ConstInitializer *const_init_new_array_value(Expr *expr, ArrayIndex index);
bool const_init_is_zero(ConstInitializer *init);
void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value);
void const_init_rewrite_array_at(ConstInitializer *const_init, Expr *value, ArrayIndex index);
void const_init_rewrite_to_zero(ConstInitializer *init, Type *type);
static inline void const_init_set_span(ConstInitializer *init, SourceSpan loc)
@@ -3459,6 +3467,7 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc)
case EXPR_TYPECALL:
case EXPR_MEMBER_GET:
case EXPR_RVALUE:
case EXPR_CT_SUBSCRIPT:
break;
}
}

View File

@@ -296,6 +296,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
{
case EXPR_TYPECALL:
case EXPR_ANYSWITCH:
case EXPR_CT_SUBSCRIPT:
UNREACHABLE
case EXPR_OTHER_CONTEXT:
MACRO_COPY_EXPR(expr->expr_other_context.inner);

View File

@@ -743,6 +743,7 @@ typedef enum
EXPR_CT_EVAL,
EXPR_CT_IDENT,
EXPR_CT_IS_CONST,
EXPR_CT_SUBSCRIPT,
EXPR_DECL,
EXPR_DEFAULT_ARG,
EXPR_DESIGNATED_INITIALIZER_LIST,
@@ -1662,6 +1663,6 @@ case TYPE_U8: case TYPE_U16: case TYPE_U32: case TYPE_U64: case TYPE_U128
#define UNRESOLVED_EXPRS EXPR_TRY_UNRESOLVED: case EXPR_ACCESS_UNRESOLVED: \
case EXPR_CATCH_UNRESOLVED: case EXPR_UNRESOLVED_IDENTIFIER: case EXPR_CAST: \
case EXPR_TYPEID: case EXPR_EMBED: case EXPR_VASPLAT: case EXPR_OTHER_CONTEXT: \
case EXPR_GENERIC_IDENT: case EXPR_COMPOUND_LITERAL: case EXPR_MACRO_BODY
case EXPR_GENERIC_IDENT: case EXPR_COMPOUND_LITERAL: case EXPR_MACRO_BODY: case EXPR_CT_SUBSCRIPT

View File

@@ -363,6 +363,7 @@ bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr *
len = vec_size(left->const_expr.untyped_list);
break;
}
ArraySize len_lhs = len;
switch (right->const_expr.const_kind)
{
case CONST_FLOAT:
@@ -400,7 +401,8 @@ bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr *
{
indexed_type = NULL;
}
len += sema_len_from_const(right);
ArraySize len_rhs = sema_len_from_const(right);
len += len_rhs;
if (!indexed_type)
{
Expr **untyped_exprs = VECNEW(Expr*, len + 1);
@@ -419,15 +421,69 @@ bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr *
ConstInitializer *init = expr_const_initializer_from_expr(single_expr);
// Skip zero arrays from slices.
if (!init) continue;
if (init && init->kind != CONST_INIT_ARRAY_FULL)
switch (init->kind)
{
ASSERT(!init || init->type != type_untypedlist);
RETURN_SEMA_ERROR(single_expr, "Expected a full array here.");
}
FOREACH(ConstInitializer *, val, init->init_array_full)
{
vec_add(untyped_exprs, val->init_value);
case CONST_INIT_UNION:
case CONST_INIT_STRUCT:
case CONST_INIT_ARRAY_VALUE:
case CONST_INIT_VALUE:
UNREACHABLE
case CONST_INIT_ARRAY_FULL:
{
FOREACH(ConstInitializer *, val, init->init_array_full)
{
vec_add(untyped_exprs, val->init_value);
}
continue;
}
case CONST_INIT_ZERO:
{
Type *index_type = type_get_indexed_type(type_flatten(init->type));
ArraySize len_zero = i == 0 ? len_lhs : len_rhs;
for (ArraySize j = 0; j < len_zero; j++)
{
Expr *zero = expr_new_expr(EXPR_CONST, single_expr);
expr_rewrite_to_const_zero(zero, index_type);
vec_add(untyped_exprs, zero);
}
continue;
}
case CONST_INIT_ARRAY:
{
Type *index_type = type_get_indexed_type(type_flatten(init->type));
ArraySize len_zero = i == 0 ? len_lhs : len_rhs;
ArraySize offset = vec_size(untyped_exprs);
for (ArraySize j = 0; j < len_zero; j++)
{
Expr *zero = expr_new_expr(EXPR_CONST, single_expr);
expr_rewrite_to_const_zero(zero, index_type);
vec_add(untyped_exprs, zero);
}
FOREACH(ConstInitializer *, element, init->init_array.elements)
{
ASSERT_SPAN(right, element->kind == CONST_INIT_ARRAY_VALUE);
ConstInitializer *inner_element = element->init_array_value.element;
Expr *inner_expr = untyped_exprs[offset + element->init_array_value.index];
switch (inner_element->kind)
{
case CONST_INIT_ZERO:
continue;
case CONST_INIT_STRUCT:
case CONST_INIT_UNION:
case CONST_INIT_ARRAY:
case CONST_INIT_ARRAY_FULL:
case CONST_INIT_ARRAY_VALUE:
expr_rewrite_const_initializer(inner_expr, index_type, inner_element);
continue;
case CONST_INIT_VALUE:
*inner_expr = *inner_element->init_value;
continue;
}
}
continue;
}
}
UNREACHABLE
}
concat_expr->expr_kind = EXPR_CONST;
concat_expr->type = type_untypedlist;
@@ -438,34 +494,193 @@ bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr *
};
return true;
}
ConstInitializer **inits = VECNEW(ConstInitializer*, len);
Expr *exprs[2] = { left, right };
for (int i = 0; i < 2; i++)
// Zero slice + zero slice => slice
if (len == 0)
{
Expr *element = exprs[i];
ConstInitializer *inititializer = expr_const_initializer_from_expr(element);
// Zero sized slice:
if (!inititializer)
{
ASSERT_SPAN(element, element->const_expr.const_kind == CONST_SLICE);
continue;
}
switch (inititializer->kind)
{
case CONST_INIT_ARRAY_FULL:
break;
case CONST_INIT_ZERO:
if (type_flatten(element->type)->type_kind == TYPE_SLICE) continue;
default:
RETURN_SEMA_ERROR(element, "Only fully initialized arrays may be concatenated.");
}
FOREACH(ConstInitializer *, init, inititializer->init_array_full)
{
vec_add(inits, init);
}
expr_rewrite_to_const_zero(concat_expr, type_get_slice(indexed_type));
}
Type *type = use_array ? type_get_array(indexed_type, len) : type_get_vector(indexed_type, len);
expr_rewrite_const_initializer(concat_expr, type, const_init_new_array_full(type, inits));
ConstInitializer *lhs_init = expr_const_initializer_from_expr(left);
ConstInitializer *rhs_init = expr_const_initializer_from_expr(right);
if (!rhs_init)
{
rhs_init = lhs_init;
lhs_init = NULL;
}
if (!lhs_init)
{
ASSERT(rhs_init);
expr_rewrite_const_initializer(concat_expr, type, rhs_init);
return true;
}
return true;
switch (lhs_init->kind)
{
case CONST_INIT_UNION:
case CONST_INIT_STRUCT:
case CONST_INIT_ARRAY_VALUE:
case CONST_INIT_VALUE:
UNREACHABLE
case CONST_INIT_ZERO:
switch (rhs_init->kind)
{
case CONST_INIT_ZERO:
// { 0, 0, 0 } + { 0, 0, 0 }
expr_rewrite_const_initializer(concat_expr, type, const_init_new_zero(type));
return true;
case CONST_INIT_ARRAY_FULL:
{
// { 0, 0, 0 } + { 1, 2, 3 }
ConstInitializer **inits = VECNEW(ConstInitializer*, len);
for (ArraySize i = 0; i < len_lhs; i++)
{
vec_add(inits, const_init_new_zero(indexed_type));
}
FOREACH(ConstInitializer *, init, rhs_init->init_array_full)
{
vec_add(inits, init);
}
expr_rewrite_const_initializer(concat_expr, type, const_init_new_array_full(type, inits));
return true;
}
case CONST_INIT_ARRAY:
{
// { 0, 0, 0 } + { 1 => 3 }
FOREACH(ConstInitializer *, element, rhs_init->init_array.elements)
{
ASSERT_SPAN(right, element->kind == CONST_INIT_ARRAY_VALUE);
element->init_array_value.index += len_lhs;
}
rhs_init->type = type;
expr_rewrite_const_initializer(concat_expr, type, rhs_init);
return true;
}
case CONST_INIT_STRUCT:
case CONST_INIT_UNION:
case CONST_INIT_VALUE:
case CONST_INIT_ARRAY_VALUE:
UNREACHABLE
}
UNREACHABLE
case CONST_INIT_ARRAY_FULL:
{
switch (rhs_init->kind)
{
case CONST_INIT_UNION:
case CONST_INIT_STRUCT:
case CONST_INIT_ARRAY_VALUE:
case CONST_INIT_VALUE:
UNREACHABLE
case CONST_INIT_ZERO:
{
// { 1, 2, 3 } + { 0, 0, 0 }
ConstInitializer **inits = VECNEW(ConstInitializer*, len);
FOREACH(ConstInitializer *, init, lhs_init->init_array_full)
{
vec_add(inits, init);
}
for (ArraySize i = 0; i < len_rhs; i++)
{
vec_add(inits, const_init_new_zero(indexed_type));
}
expr_rewrite_const_initializer(concat_expr, type, const_init_new_array_full(type, inits));
return true;
}
case CONST_INIT_ARRAY_FULL:
{
// { 1, 2, 3 } + { 1, 2, 3 }
ConstInitializer **inits = VECNEW(ConstInitializer*, len);
FOREACH(ConstInitializer *, init, lhs_init->init_array_full)
{
vec_add(inits, init);
}
FOREACH(ConstInitializer *, init, rhs_init->init_array_full)
{
vec_add(inits, init);
}
expr_rewrite_const_initializer(concat_expr, type, const_init_new_array_full(type, inits));
return true;
}
case CONST_INIT_ARRAY:
{
// { 1, 2, 3 } + { 1 => 3 }
ConstInitializer **inits = VECNEW(ConstInitializer*, len);
FOREACH(ConstInitializer *, init, lhs_init->init_array_full)
{
vec_add(inits, init);
}
for (ArraySize i = 0; i < len_rhs; i++)
{
vec_add(inits, const_init_new_zero(indexed_type));
}
FOREACH(ConstInitializer *, element, rhs_init->init_array.elements)
{
ASSERT_SPAN(right, element->kind == CONST_INIT_ARRAY_VALUE);
inits[element->init_array_value.index + len_lhs] = element->init_array_value.element;
}
expr_rewrite_const_initializer(concat_expr, type, const_init_new_array_full(type, inits));
return true;
}
}
UNREACHABLE
}
case CONST_INIT_ARRAY:
{
switch (rhs_init->kind)
{
case CONST_INIT_UNION:
case CONST_INIT_STRUCT:
case CONST_INIT_ARRAY_VALUE:
case CONST_INIT_VALUE:
UNREACHABLE
case CONST_INIT_ZERO:
{
// { 1 => 3 } + { 0, 0, 0 }
lhs_init->type = type;
expr_rewrite_const_initializer(concat_expr, type, lhs_init);
return true;
}
case CONST_INIT_ARRAY_FULL:
{
// { 1 => 3 } + { 1, 2, 3 }
ConstInitializer **inits = VECNEW(ConstInitializer*, len);
for (ArraySize i = 0; i < len_lhs; i++)
{
vec_add(inits, const_init_new_zero(indexed_type));
}
FOREACH(ConstInitializer *, element, lhs_init->init_array.elements)
{
ASSERT_SPAN(left, element->kind == CONST_INIT_ARRAY_VALUE);
inits[element->init_array_value.index] = element->init_array_value.element;
}
FOREACH(ConstInitializer *, init, rhs_init->init_array_full)
{
vec_add(inits, init);
}
expr_rewrite_const_initializer(concat_expr, type, const_init_new_array_full(type, inits));
return true;
}
case CONST_INIT_ARRAY:
{
// { 1 => 3 } + { 1 => 3 }
ArraySize elements = vec_size(lhs_init->init_array.elements) + vec_size(rhs_init->init_array.elements);
ConstInitializer **inits = VECNEW(ConstInitializer*, elements);
FOREACH(ConstInitializer *, element, lhs_init->init_array.elements)
{
vec_add(inits, element);
}
FOREACH(ConstInitializer *, element, rhs_init->init_array.elements)
{
ASSERT_SPAN(right, element->kind == CONST_INIT_ARRAY_VALUE);
element->init_array_value.index += len_lhs;
vec_add(inits, element);
}
expr_rewrite_const_initializer(concat_expr, type, const_init_new_array(type, inits));
return true;
}
}
UNREACHABLE
}
}
UNREACHABLE
}

View File

@@ -3065,7 +3065,8 @@ static inline bool sema_expr_resolve_subscript_index(SemaContext *context, Expr
}
ArrayIndex size;
bool check_len = !context->call_env.in_no_eval || current_type == type_untypedlist;
if (check_len && expr_is_const_int(index) && (size = sema_len_from_expr(current_expr)) >= 0)
Expr *len_expr = current_expr->expr_kind == EXPR_CT_IDENT ? current_expr->ct_ident_expr.decl->var.init_expr : current_expr;
if (check_len && expr_is_const_int(index) && (size = sema_len_from_expr(len_expr)) >= 0)
{
// 4c. And that it's in range.
if (int_is_neg(index->const_expr.ixx))
@@ -3115,7 +3116,14 @@ static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr
{
// Evaluate the expression to index.
Expr *subscripted = exprptr(expr->subscript_expr.expr);
if (!sema_analyse_expr(context, subscripted)) return false;
if (subscripted->expr_kind == EXPR_CT_IDENT)
{
if (!sema_analyse_expr_lvalue(context, subscripted, NULL)) return false;
}
else
{
if (!sema_analyse_expr(context, subscripted)) return false;
}
if (!sema_expr_check_assign(context, expr, NULL)) return false;
@@ -3142,9 +3150,17 @@ static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr
}
// 4. If we are indexing into a complist
if (current_type == type_untypedlist)
if (current_expr->expr_kind == EXPR_CT_IDENT)
{
TODO;
if (index_value == -1)
{
if (check_valid) goto VALID_FAIL_POISON;
RETURN_SEMA_ERROR(index, "Assigning to a compile time constant requires a constant index.");
}
expr->expr_kind = EXPR_CT_SUBSCRIPT;
expr->ct_subscript_expr = (ExprCtSubscript) { .var = current_expr->ct_ident_expr.decl, .index = index_value };
expr->type = NULL;
return true;
}
if (!sema_cast_rvalue(context, subscripted, true)) return false;
@@ -4955,8 +4971,7 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
static inline bool sema_expr_analyse_swizzle(SemaContext *context, Expr *expr, Expr *parent, Type *flat_type,
const char *kw,
unsigned len, CheckType check, bool is_lvalue)
const char *kw, unsigned len, CheckType check, bool is_lvalue)
{
unsigned vec_len = flat_type->array.len;
Type *indexed_type = type_get_indexed_type(parent->type);
@@ -5825,6 +5840,70 @@ static bool sema_expr_analyse_ct_identifier_assign(SemaContext *context, Expr *e
return true;
}
static bool sema_expr_analyse_ct_subscript_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right)
{
Decl *ct_var = left->ct_subscript_expr.var;
ArrayIndex index = left->ct_subscript_expr.index;
if (ct_var->type == type_untypedlist)
{
if (!sema_analyse_expr(context, right)) return false;
}
else
{
if (!sema_analyse_inferred_expr(context, type_get_indexed_type(ct_var->type), right)) return false;
}
if (!sema_cast_const(right))
{
RETURN_SEMA_ERROR(right, "The argument must be a constant value.");
}
if (context->call_env.in_other)
{
RETURN_SEMA_ERROR(left, "Compile time variables may only be modified in the scope they are defined in.");
}
Expr *original_value = ct_var->var.init_expr;
ASSERT_SPAN(original_value, original_value->expr_kind == EXPR_CONST);
ExprConst *expr_const = &original_value->const_expr;
switch (expr_const->const_kind)
{
case CONST_FLOAT:
case CONST_INTEGER:
case CONST_BOOL:
case CONST_ENUM:
case CONST_ERR:
case CONST_POINTER:
case CONST_TYPEID:
case CONST_REF:
case CONST_MEMBER:
UNREACHABLE
case CONST_BYTES:
case CONST_STRING:
{
unsigned char *copy = MALLOC(expr_const->bytes.len + 1);
memcpy(copy, expr_const->bytes.ptr, expr_const->bytes.len + 1);
assert(right->const_expr.const_kind == CONST_INTEGER);
copy[index] = (unsigned char)right->const_expr.ixx.i.low;
expr_const->bytes.ptr = (char *)copy;
break;
}
case CONST_SLICE:
const_init_rewrite_array_at(expr_const->slice_init, right, index);
break;
case CONST_INITIALIZER:
const_init_rewrite_array_at(expr_const->initializer, right, index);
break;
case CONST_UNTYPED_LIST:
expr_const->untyped_list[index] = right;
break;
}
Expr *original = expr_copy(original_value);
expr_replace(expr, original);
return true;
}
static bool sema_expr_analyse_ct_type_identifier_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right)
{
TypeInfo *info = left->type_expr;
@@ -5884,10 +5963,15 @@ static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *lef
return sema_expr_analyse_ct_type_identifier_assign(context, expr, left, right);
}
if (!sema_analyse_expr_lvalue(context, left, failed_ref)) return false;
if (left->expr_kind == EXPR_CT_IDENT)
switch (left->expr_kind)
{
// $foo = ...
return sema_expr_analyse_ct_identifier_assign(context, expr, left, right);
case EXPR_CT_IDENT:
// $foo = ...
return sema_expr_analyse_ct_identifier_assign(context, expr, left, right);
case EXPR_CT_SUBSCRIPT:
return sema_expr_analyse_ct_subscript_assign(context, expr, left, right);
default:
break;
}
// 2. Check assignability
@@ -9184,6 +9268,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
case EXPR_IDENTIFIER:
case EXPR_NAMED_ARGUMENT:
case EXPR_ACCESS_RESOLVED:
case EXPR_CT_SUBSCRIPT:
UNREACHABLE
case EXPR_BINARY:
main_expr->resolve_status = RESOLVE_RUNNING;
@@ -9661,6 +9746,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
case EXPR_SLICE_TO_VEC_ARRAY:
case EXPR_SCALAR_TO_VECTOR:
case EXPR_MAKE_SLICE:
case EXPR_CT_SUBSCRIPT:
UNREACHABLE
case EXPR_MAKE_ANY:
if (!sema_analyse_expr(context, expr->make_any_expr.typeid)) return false;
@@ -10223,6 +10309,7 @@ IDENT_CHECK:;
case EXPR_BITACCESS:
case EXPR_SUBSCRIPT_ASSIGN:
case EXPR_ACCESS_RESOLVED:
case EXPR_CT_SUBSCRIPT:
UNREACHABLE
}
if (failed_ref) goto FAILED_REF;

View File

@@ -1049,6 +1049,81 @@ static inline void sema_update_const_initializer_with_designator_union(ConstInit
const_init_rewrite_to_value(sub_element, value);
}
static inline ConstInitializer *sema_update_const_initializer_at_index(ConstInitializer *const_init, Type *element_type,
ArraySize array_count, ArrayIndex index,
ArrayIndex *insert_index_ref, Expr *value)
{
ConstInitializer **array_elements = const_init->init_array.elements;
ArrayIndex insert_index = *insert_index_ref;
ASSERT(insert_index >= array_count || array_elements);
// Walk to the insert point or until we reached the end of the array.
while (insert_index < array_count && array_elements[insert_index]->init_array_value.index < index)
{
insert_index++;
}
// Pick up the initializer at the insert point.
ConstInitializer *initializer = insert_index < array_count ? array_elements[insert_index] : NULL;
ConstInitializer *inner_value;
// If we don't have an initializer, the location needs to be at the end.
// Create and append:
if (!initializer)
{
initializer = const_init_new_zero_array_value(element_type, index);
vec_add(array_elements, initializer);
array_count++;
}
else
{
// If we already have an initializer "found"
// it might be after the index. In this case, we
// need to do an insert.
if (initializer->init_array_value.index != insert_index)
{
ASSERT(initializer->init_array_value.index > insert_index);
// First we add a null at the end.
vec_add(array_elements, NULL);
// Shift all values one step up:
for (unsigned i = array_count; i > insert_index; i--)
{
array_elements[i] = array_elements[i - 1];
}
// Then we create our new entry.
initializer = const_init_new_zero_array_value(element_type, index);
// And assign it to the location.
array_elements[insert_index] = initializer;
}
}
const_init->init_array.elements = array_elements;
*insert_index_ref = insert_index;
return initializer->init_array_value.element;
}
void const_init_rewrite_array_at(ConstInitializer *const_init, Expr *value, ArrayIndex index)
{
// Expand zero into array.
if (const_init->kind == CONST_INIT_ZERO)
{
const_init->kind = CONST_INIT_ARRAY;
const_init->init_array.elements = NULL;
}
Type *element_type = type_flatten(const_init->type->array.base);
// Get all the elements in the array
ConstInitializer **array_elements = const_init->init_array.elements;
unsigned array_count = vec_size(array_elements);
ArrayIndex insert_index = 0;
ConstInitializer *inner_value = sema_update_const_initializer_at_index(const_init, element_type,
array_count, index, &insert_index, value);
const_init_rewrite_to_value(inner_value, value);
}
/**
* Update an array { [2] = 1 }
*/
@@ -1074,56 +1149,15 @@ static inline void sema_update_const_initializer_with_designator_array(ConstInit
bool is_last_path_element = next_element == end;
// Get all the elements in the array
ConstInitializer **array_elements = const_init->init_array.elements;
unsigned array_count = vec_size(array_elements);
unsigned array_count = vec_size(const_init->init_array.elements);
ArrayIndex insert_index = 0;
for (ArrayIndex index = low_index; index <= high_index; index++)
{
ASSERT(insert_index >= array_count || array_elements);
// Walk to the insert point or until we reached the end of the array.
while (insert_index < array_count && array_elements[insert_index]->init_array_value.index < index)
{
insert_index++;
}
// Pick up the initializer at the insert point.
ConstInitializer *initializer = insert_index < array_count ? array_elements[insert_index] : NULL;
ConstInitializer *inner_value;
// If we don't have an initializer, the location needs to be at the end.
// Create and append:
if (!initializer)
{
initializer = const_init_new_zero_array_value(element_type, index);
vec_add(array_elements, initializer);
array_count++;
}
else
{
// If we already have an initializer "found"
// it might be after the index. In this case, we
// need to do an insert.
if (initializer->init_array_value.index != insert_index)
{
ASSERT(initializer->init_array_value.index > insert_index);
// First we add a null at the end.
vec_add(array_elements, NULL);
// Shift all values one step up:
for (unsigned i = array_count; i > insert_index; i--)
{
array_elements[i] = array_elements[i - 1];
}
// Then we create our new entry.
initializer = const_init_new_zero_array_value(element_type, index);
// And assign it to the location.
array_elements[insert_index] = initializer;
}
}
const_init->init_array.elements = array_elements;
inner_value = initializer->init_array_value.element;
ConstInitializer *inner_value = sema_update_const_initializer_at_index(const_init, element_type,
array_count, index, &insert_index,
value);
// Update
if (!is_last_path_element)

File diff suppressed because it is too large Load Diff

View File

@@ -9,8 +9,8 @@ fn int main()
$foreach ( $c : $chars)
int $offset = ($c - $from) / BITS;
int $rem = ($c - $from) % BITS;
uint128 $value = $bitmap[$offset];
uint128 $value = $bitmap[$offset]; // #error: is out of range
$value |= 1u128 << $rem;
$bitmap = $bitmap[:$offset] +++ $value +++ $bitmap[$offset+1..]; // #error: Only fully initialized arrays
$bitmap = $bitmap[:$offset] +++ $value +++ $bitmap[$offset+1..]; // #error: End index out of bounds
$endforeach
}