mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user