Allow (int[*]) { 1, 2 } cast style initialization. Experimental change from [*] to [?]. Fix issue where compile time declarations in expression list would not be handled properly.

This commit is contained in:
Christoffer Lerno
2025-01-25 22:10:12 +01:00
parent ca91ad4097
commit e40bab2d30
93 changed files with 529 additions and 466 deletions

View File

@@ -289,7 +289,7 @@ struct Type_
Decl *decl;
// int, float, bool
TypeBuiltin builtin;
// Type[], Type[*], Type[123], Type[<123>] or Type<[123]>
// Type[], Type[?], Type[123] or Type[<123>]
TypeArray array;
// fn TypeR Type1(Type2, Type3, ...)
TypeFunction function;

View File

@@ -158,11 +158,11 @@ void print_type(FILE *file, TypeInfo *type)
break;
case TYPE_INFO_INFERRED_ARRAY:
print_type(file, type->array.base);
fputs("[*]", file);
fputs("[?]", file);
break;
case TYPE_INFO_INFERRED_VECTOR:
print_type(file, type->array.base);
fputs("[<*>]", file);
fputs("[<?>]", file);
break;
case TYPE_INFO_SLICE:
print_type(file, type->array.base);

View File

@@ -522,7 +522,7 @@ static inline TypeInfo *parse_array_type_index(ParseContext *c, TypeInfo *type)
ASSERT(type_info_ok(type));
advance_and_verify(c, TOKEN_LBRACKET);
if (try_consume(c, TOKEN_STAR))
if (try_consume(c, TOKEN_STAR) || try_consume(c, TOKEN_QUESTION))
{
CONSUME_OR_RET(TOKEN_RBRACKET, poisoned_type_info);
TypeInfo *inferred_array = type_info_new(TYPE_INFO_INFERRED_ARRAY, type->span);
@@ -582,7 +582,7 @@ static inline TypeInfo *parse_vector_type_index(ParseContext *c, TypeInfo *type)
advance_and_verify(c, TOKEN_LVEC);
TypeInfo *vector = type_info_new(TYPE_INFO_VECTOR, type->span);
vector->array.base = type;
if (try_consume(c, TOKEN_STAR))
if (try_consume(c, TOKEN_STAR) || try_consume(c, TOKEN_QUESTION))
{
CONSUME_OR_RET(TOKEN_RVEC, poisoned_type_info);
vector->kind = TYPE_INFO_INFERRED_VECTOR;
@@ -684,7 +684,7 @@ typedef enum DiscardedSubscript_
static DiscardedSubscript parse_discarded_subscript(ParseContext *c, TokenType end)
{
if (end == TOKEN_RBRACKET && try_consume(c, end)) return DISCARD_SLICE;
if (try_consume(c, TOKEN_STAR))
if (try_consume(c, TOKEN_STAR) || try_consume(c, TOKEN_QUESTION))
{
CONSUME_OR_RET(end, DISCARD_ERR);
return DISCARD_WILDCARD;
@@ -704,7 +704,7 @@ INLINE bool parse_rethrow_bracket(ParseContext *c, SourceSpan start)
case DISCARD_ERR:
return false;
case DISCARD_WILDCARD:
print_error_at(extend_span_with_token(start, c->prev_span), "When declaring an optional array, the '[*]' should appear before the '!', e.g 'Foo[*]!'.");
print_error_at(extend_span_with_token(start, c->prev_span), "When declaring an optional array, the '[?]' should appear before the '!', e.g 'Foo[?]!'.");
return false;
case DISCARD_SLICE:
print_error_at(extend_span_with_token(start, c->prev_span),
@@ -723,7 +723,7 @@ INLINE bool parse_rethrow_bracket(ParseContext *c, SourceSpan start)
case DISCARD_ERR:
return false;
case DISCARD_WILDCARD:
print_error_at(extend_span_with_token(start, c->span), "When declaring an optional vector, the '[<*>]' should appear before the '!', e.g 'Foo[<*>]!'.");
print_error_at(extend_span_with_token(start, c->span), "When declaring an optional vector, the '[<?>]' should appear before the '!', e.g 'Foo[<?>]!'.");
return false;
case DISCARD_SLICE:
UNREACHABLE

View File

@@ -226,10 +226,10 @@ Type *type_infer_len_from_actual_type(Type *to_infer, Type *actual_type)
// if so we assume the original type
if (!type_len_is_inferred(to_infer)) return to_infer;
// Handle int[*]! a = { ... } by stripping the optional.
// Handle int[?]! a = { ... } by stripping the optional.
bool is_optional = type_is_optional(to_infer);
assert((is_optional || !type_is_optional(actual_type)) && "int[*] x = { may_fail } should have been caught.");
assert((is_optional || !type_is_optional(actual_type)) && "int[?] x = { may_fail } should have been caught.");
// Strip the optional
if (is_optional) to_infer = to_infer->optional;
@@ -241,7 +241,7 @@ Type *type_infer_len_from_actual_type(Type *to_infer, Type *actual_type)
if (!actual) return actual_type;
// Grab the underlying indexed type,
// because we can only have [*] [] [<*>] [<>] * here
// because we can only have [?] [] [<?>] [<>] * here
Type *indexed = type_get_indexed_type(to_infer);
// We should always have indexed types.
@@ -251,7 +251,7 @@ Type *type_infer_len_from_actual_type(Type *to_infer, Type *actual_type)
// In this case, infer it.
if (type_len_is_inferred(indexed))
{
// if we have int[*][*] => the inner is int[*], we cast it here.
// if we have int[?][?] => the inner is int[?], we cast it here.
indexed = type_infer_len_from_actual_type(indexed, actual);
}
@@ -259,10 +259,10 @@ Type *type_infer_len_from_actual_type(Type *to_infer, Type *actual_type)
switch (to_infer->type_kind)
{
case TYPE_POINTER:
// The case of int[*]* x = ...
// The case of int[?]* x = ...
return type_add_optional(type_get_ptr(indexed), is_optional);
case TYPE_ARRAY:
// The case of int[*][2] x = ...
// The case of int[?][2] x = ...
return type_add_optional(type_get_array(indexed, to_infer->array.len), is_optional);
case TYPE_INFERRED_ARRAY:
ASSERT(type_is_arraylike(type_flatten(actual_type)));
@@ -273,7 +273,7 @@ Type *type_infer_len_from_actual_type(Type *to_infer, Type *actual_type)
case TYPE_SLICE:
return type_add_optional(type_get_slice(indexed), is_optional);
case TYPE_VECTOR:
// The case of int[*]*[<2>] x = ...
// The case of int[?]*[<2>] x = ...
return type_add_optional(type_get_vector(indexed, to_infer->array.len), is_optional);
default:
UNREACHABLE
@@ -852,7 +852,11 @@ static bool rule_ulist_to_inferred(CastContext *cc, bool is_explicit, bool is_si
Type *base = cc->to->array.base;
FOREACH(Expr *, expr, expressions)
{
if (!may_cast(cc->context, expr, base, false, is_silent)) return false;
if (!may_cast(cc->context, expr, base, false, true))
{
RETURN_CAST_ERROR(cc->expr, "This untyped list contains an element of type %s which cannot be converted to %s.",
type_quoted_error_string(expr->type), type_quoted_error_string(base));
}
}
return true;
}
@@ -2181,7 +2185,7 @@ static void cast_typeid_to_bool(SemaContext *context, Expr *expr, Type *to_type)
#define RINPT &rule_int_to_ptr /* Int -> ptr (explicit + size match) */
#define RPTIN &rule_ptr_to_int /* Ptr -> int (explicit + size match) */
#define RINBS &rule_int_to_bits /* Int -> bits (explicit + int + size match) */
#define RARBS &rule_arr_to_bits /* Char[*] -> bits (explicit + base match) */
#define RARBS &rule_arr_to_bits /* Char[?] -> bits (explicit + base match) */
#define RINEN &rule_int_to_enum /* Int -> enum (explicit, range check const) */
#define RPTPT &rule_ptr_to_ptr /* Ptr -> ptr (explicit or ptr match) */
#define RAPSL &rule_arrptr_to_slice /* Arrptr -> Slice (explicit flattens distinct, pointer match) */

View File

@@ -238,7 +238,7 @@ static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent
{
ASSERT(decl->var.kind == VARDECL_MEMBER);
decl->resolve_status = RESOLVE_RUNNING;
// Inferred types are not strictly allowed, but we use the int[*] for the flexible array member.
// Inferred types are not strictly allowed, but we use the int[?] for the flexible array member.
ASSERT(type_infoptrzero(decl->var.type_info));
TypeInfo *type_info = type_infoptr(decl->var.type_info);
if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_FLEXIBLE)) return decl_poison(decl);
@@ -513,9 +513,9 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl)
Type *member_type = type_flatten(member->type);
// If this is a struct and it has a variable array ending, then it must also be the last struct.
// So this is ok:
// struct Foo { int x; struct { int x; int[*] y; } }
// struct Foo { int x; struct { int x; int[?] y; } }
// But not this:
// struct Bar { struct { int x; int[*] y; } int x; }
// struct Bar { struct { int x; int[?] y; } int x; }
if (member_type->type_kind == TYPE_STRUCT && member_type->decl->has_variable_array)
{
if (i != member_count - 1)

View File

@@ -5660,7 +5660,7 @@ static inline bool sema_expr_analyse_cast(SemaContext *context, Expr *expr, bool
if (invalid_cast_ref) *invalid_cast_ref = false;
Expr *inner = exprptr(expr->cast_expr.expr);
TypeInfo *type_info = type_infoptr(expr->cast_expr.type_info);
bool success = sema_resolve_type_info(context, type_info, RESOLVE_TYPE_DEFAULT);
bool success = sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_INFER);
if (!sema_analyse_expr(context, inner) || !success) return false;
Type *target_type = type_info->type;
@@ -9808,9 +9808,25 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
if (!sema_expr_analyse_ct_stringify(context, expr)) return false;
return true;
case EXPR_DECL:
if (!sema_analyse_var_decl(context, expr->decl_expr, true)) return false;
expr->type = expr->decl_expr->type;
{
Decl *decl = expr->decl_expr;
bool erase = decl->var.kind == VARDECL_LOCAL_CT_TYPE || decl->var.kind == VARDECL_LOCAL_CT;
if (!sema_analyse_var_decl(context, decl, true)) return false;
if (erase)
{
Expr *init = decl->var.init_expr;
if (init)
{
expr_replace(expr, copy_expr_single(decl->var.init_expr));
return true;
}
expr->expr_kind = EXPR_NOP;
expr->type = type_void;
return true;
}
expr->type = decl->type;
return true;
}
case EXPR_LAST_FAULT:
expr->type = type_anyfault;
return true;

View File

@@ -326,7 +326,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
Expr **elements = initializer->initializer_list;
bool inferred_len = type_len_is_inferred(flattened);
// We have the case where "Foo = int[*]"
// We have the case where "Foo = int[?]"
if (inferred_len && !type_len_is_inferred(assigned))
{
ASSERT(assigned->type_kind == TYPE_TYPEDEF);

View File

@@ -145,7 +145,7 @@ void type_append_name_to_scratch(Type *type)
break;
case TYPE_FLEXIBLE_ARRAY:
type_append_name_to_scratch(type->array.base);
scratch_buffer_append("[*]");
scratch_buffer_append("[?]");
break;
case TYPE_VOID:
case TYPE_BOOL:
@@ -277,7 +277,7 @@ const char *type_to_error_string(Type *type)
type_append_func_to_scratch(type->function.prototype);
return scratch_buffer_copy();
case TYPE_INFERRED_VECTOR:
return str_printf("%s[<*>]", type_to_error_string(type->array.base));
return str_printf("%s[<?>]", type_to_error_string(type->array.base));
case TYPE_VECTOR:
return str_printf("%s[<%llu>]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
case TYPE_TYPEINFO:
@@ -293,7 +293,7 @@ const char *type_to_error_string(Type *type)
return str_printf("%s[%llu]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
return str_printf("%s[*]", type_to_error_string(type->array.base));
return str_printf("%s[?]", type_to_error_string(type->array.base));
case TYPE_SLICE:
return str_printf("%s[]", type_to_error_string(type->array.base));
}
@@ -839,7 +839,7 @@ static Type *type_generate_inferred_array(Type *arr_type, bool canonical)
Type *arr = arr_type->type_cache[INFERRED_ARRAY_OFFSET];
if (arr == NULL)
{
arr = type_new(TYPE_INFERRED_ARRAY, str_printf("%s[*]", arr_type->name));
arr = type_new(TYPE_INFERRED_ARRAY, str_printf("%s[?]", arr_type->name));
arr->array.base = arr_type;
arr_type->type_cache[INFERRED_ARRAY_OFFSET] = arr;
if (arr_type == arr_type->canonical)
@@ -865,7 +865,7 @@ static Type *type_generate_inferred_vector(Type *arr_type, bool canonical)
Type *arr = arr_type->type_cache[INFERRED_VECTOR_OFFSET];
if (arr == NULL)
{
arr = type_new(TYPE_INFERRED_VECTOR, str_printf("%s[<*>]", arr_type->name));
arr = type_new(TYPE_INFERRED_VECTOR, str_printf("%s[<?>]", arr_type->name));
arr->array.base = arr_type;
arr_type->type_cache[INFERRED_VECTOR_OFFSET] = arr;
if (arr_type == arr_type->canonical)
@@ -891,7 +891,7 @@ static Type *type_generate_flexible_array(Type *arr_type, bool canonical)
Type *arr = arr_type->type_cache[FLEXIBLE_ARRAY_OFFSET];
if (arr == NULL)
{
arr = type_new(TYPE_FLEXIBLE_ARRAY, str_printf("%s[*]", arr_type->name));
arr = type_new(TYPE_FLEXIBLE_ARRAY, str_printf("%s[?]", arr_type->name));
arr->array.base = arr_type;
arr->array.len = 0;
arr_type->type_cache[FLEXIBLE_ARRAY_OFFSET] = arr;