New faults and syntax (#2034)

- Remove `[?]` syntax.
- Change `int!` to `int?` syntax.
- New `fault` declarations.
- Enum associated values can reference the calling enum.
This commit is contained in:
Christoffer Lerno
2025-03-10 00:11:35 +01:00
committed by GitHub
parent fefce25081
commit 25bccf4883
392 changed files with 3129 additions and 3658 deletions

View File

@@ -62,7 +62,6 @@ static Module *module_instantiate_generic(SemaContext *context, Module *module,
static inline bool sema_analyse_enum_param(SemaContext *context, Decl *param);
static inline bool sema_analyse_enum(SemaContext *context, Decl *decl, bool *erase_decl);
static inline bool sema_analyse_error(SemaContext *context, Decl *decl, bool *erase_decl);
static bool sema_check_section(SemaContext *context, Attr *attr)
{
@@ -237,7 +236,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);
@@ -440,7 +439,6 @@ RETRY:;
case TYPE_FUNC_PTR:
case TYPE_POINTER:
case TYPE_FUNC_RAW:
case TYPE_FAULTTYPE:
case TYPE_SLICE:
return compiler.platform.align_pointer.align / 8;
case TYPE_ENUM:
@@ -511,9 +509,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)
@@ -1021,7 +1019,6 @@ RETRY:
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_BITSTRUCT:
case TYPE_FAULTTYPE:
case TYPE_DISTINCT:
case TYPE_VECTOR:
case TYPE_INFERRED_VECTOR:
@@ -1460,7 +1457,7 @@ static inline bool sema_analyse_enum_param(SemaContext *context, Decl *param)
}
sema_decl_stack_push(param);
ASSERT(!param->var.init_expr);
return sema_set_abi_alignment(context, param->type, &param->alignment);
return true;
}
static inline bool sema_analyse_enum(SemaContext *context, Decl *decl, bool *erase_decl)
@@ -1503,8 +1500,6 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl, bool *era
break;
}
if (!sema_analyse_enum_param(context, value)) goto ERR;
value->resolve_status = RESOLVE_DONE;
}
sema_decl_stack_restore(state);
@@ -1573,6 +1568,31 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl, bool *era
{
RETURN_SEMA_ERROR(enum_value, "Expected %d associated value%s for this enum value.", associated_value_count, associated_value_count != 1 ? "s" : "");
}
}
decl->resolve_status = RESOLVE_DONE;
for (unsigned i = 0; i < associated_value_count; i++)
{
Decl *param = associated_values[i];
if (!sema_set_abi_alignment(context, param->type, &param->alignment)) return false;
param->resolve_status = RESOLVE_DONE;
}
for (unsigned i = 0; i < enums; i++)
{
Decl *enum_value = enum_values[i];
Expr **args = enum_value->enum_constant.args;
unsigned arg_count = vec_size(args);
if (arg_count > associated_value_count)
{
if (!associated_value_count)
{
RETURN_SEMA_ERROR(args[0], "There are no associated values defined for this enum. Did you perhaps want C style gap enums? In that case, try enums with inline associated values.");
}
RETURN_SEMA_ERROR(args[associated_value_count], "You're adding too many values, only %d associated value%s are defined for '%s'.", associated_value_count, associated_value_count != 1 ? "s" : "", decl->name);
}
if (arg_count < associated_value_count)
{
RETURN_SEMA_ERROR(enum_value, "Expected %d associated value%s for this enum value.", associated_value_count, associated_value_count != 1 ? "s" : "");
}
for (unsigned j = 0; j < arg_count; j++)
{
Expr *arg = args[j];
@@ -1591,29 +1611,13 @@ ERR:
return false;
}
static inline bool sema_analyse_error(SemaContext *context, Decl *decl, bool *erase_decl)
static inline bool sema_analyse_fault(SemaContext *context, Decl *decl, bool *erase_decl)
{
if (!sema_analyse_attributes(context, decl, decl->attributes, ATTR_FAULT, erase_decl)) return decl_poison(decl);
if (*erase_decl) return true;
if (!sema_resolve_implemented_interfaces(context, decl, false)) return decl_poison(decl);
bool success = true;
unsigned enums = vec_size(decl->enums.values);
for (unsigned i = 0; i < enums; i++)
{
Decl *enum_value = decl->enums.values[i];
enum_value->type = decl->type;
DEBUG_LOG("* Checking error value %s.", enum_value->name);
enum_value->enum_constant.ordinal = i;
DEBUG_LOG("* Ordinal: %d", i);
ASSERT(enum_value->resolve_status == RESOLVE_NOT_DONE);
ASSERT(enum_value->decl_kind == DECL_FAULTVALUE);
// Start evaluating the constant
enum_value->resolve_status = RESOLVE_DONE;
}
return success;
decl->type = type_anyfault;
decl->alignment = type_abi_alignment(type_string);
return true;
}
static inline const char *method_name_by_decl(Decl *method_like)
@@ -2078,7 +2082,6 @@ static inline Decl *sema_find_interface_for_method(SemaContext *context, Canonic
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_DISTINCT:
case TYPE_FAULTTYPE:
case TYPE_ENUM:
break;
case TYPE_TYPEDEF:
@@ -2243,13 +2246,6 @@ static inline bool sema_analyse_method(SemaContext *context, Decl *decl)
if (d) RETURN_SEMA_ERROR(decl, "%s already has a field with the same name.", type_quoted_error_string(par_type));
break;
}
case TYPE_FAULTTYPE:
if (kw == kw_ordinal || kw == kw_nameof)
{
errname = "a fault";
goto NOT_VALID_NAME;
}
break;
case TYPE_ANYFAULT:
if (kw == kw_type || kw == kw_nameof)
{
@@ -4298,8 +4294,8 @@ static bool sema_generate_parameterized_name_to_scratch(SemaContext *context, Mo
{
if (!sema_analyse_ct_expr(context, param)) return false;
Type *type = param->type->canonical;
bool is_enum_like = type_kind_is_enumlike(type->type_kind);
if (!type_is_integer_or_bool_kind(type) && !is_enum_like)
bool is_enum_or_fault = type_kind_is_enum_or_fault(type->type_kind);
if (!type_is_integer_or_bool_kind(type) && !is_enum_or_fault)
{
SEMA_ERROR(param, "Only integer, bool, fault and enum values may be generic arguments.");
return poisoned_decl;
@@ -4339,7 +4335,7 @@ static bool sema_generate_parameterized_name_to_scratch(SemaContext *context, Mo
else
{
Type *type = param->type->canonical;
bool is_enum_like = type_kind_is_enumlike(type->type_kind);
bool is_enum_or_fault = type_kind_is_enum_or_fault(type->type_kind);
if (type == type_bool)
{
if (mangled)
@@ -4351,12 +4347,19 @@ static bool sema_generate_parameterized_name_to_scratch(SemaContext *context, Mo
scratch_buffer_append(param->const_expr.b ? "true" : "false");
}
}
else if (is_enum_like)
else if (type->type_kind == TYPE_ENUM)
{
Decl *enum_like = param->const_expr.enum_err_val;
type_mangle_introspect_name_to_buffer(enum_like->type->canonical);
Decl *enumm = param->const_expr.enum_err_val;
type_mangle_introspect_name_to_buffer(enumm->type->canonical);
scratch_buffer_append(mangled ? "_" : ":");
scratch_buffer_append(enum_like->name);
scratch_buffer_append(enumm->name);
}
else if (type->type_kind == TYPE_ANYFAULT)
{
Decl *fault = param->const_expr.fault;
type_mangle_introspect_name_to_buffer(fault->type->canonical);
scratch_buffer_append(mangled ? "_" : ":");
scratch_buffer_append(fault->name);
}
else
{
@@ -4603,7 +4606,6 @@ RETRY:
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_BITSTRUCT:
case TYPE_FAULTTYPE:
return sema_analyse_decl(context, type->decl);
case TYPE_POINTER:
case TYPE_FUNC_PTR:
@@ -4704,7 +4706,7 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl)
if (!sema_analyse_enum(context, decl, &erase_decl)) goto FAILED;
break;
case DECL_FAULT:
if (!sema_analyse_error(context, decl, &erase_decl)) goto FAILED;
if (!sema_analyse_fault(context, decl, &erase_decl)) goto FAILED;
break;
case DECL_DEFINE:
if (!sema_analyse_define(context, decl, &erase_decl)) goto FAILED;
@@ -4715,12 +4717,11 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl)
case DECL_LABEL:
case DECL_CT_ASSERT:
case DECL_CT_ECHO:
case DECL_FAULTVALUE:
case DECL_DECLARRAY:
case DECL_BODYPARAM:
case DECL_CT_INCLUDE:
case DECL_CT_EXEC:
case DECL_GLOBALS:
case DECL_GROUP:
UNREACHABLE
}
if (erase_decl)