From 322d714305af9229b9cd05ee05f384d2b084e28e Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 8 Mar 2022 23:38:27 +0100 Subject: [PATCH] Dev (#404) Remove 'errtype' name and reduce Expr / TypeInfo memory footprint. --- resources/examples/base64.c3 | 2 +- src/compiler/ast.c | 2 +- src/compiler/compiler.c | 32 ++++---- src/compiler/compiler_internal.h | 29 ++++---- src/compiler/copying.c | 1 - src/compiler/enums.h | 2 - src/compiler/parse_expr.c | 31 +++++++- src/compiler/parse_global.c | 74 ++++++++++--------- src/compiler/parse_stmt.c | 2 - src/compiler/parser_internal.h | 1 + src/compiler/sema_decls.c | 28 +++---- src/compiler/sema_expr.c | 42 +---------- src/compiler/sema_stmts.c | 17 +++-- src/compiler/sema_types.c | 16 ++-- src/compiler/symtab.c | 4 +- src/compiler/tokens.c | 5 -- test/test_suite/cast/cast_to_failable.c3 | 2 +- test/test_suite/distinct/distinct_invalid.c3 | 2 +- test/test_suite/errors/anyerr_void.c3t | 2 +- test/test_suite/errors/error_decl_ok.c3 | 6 +- test/test_suite/errors/failable_inits.c3t | 2 +- .../errors/failable_taddr_and_access.c3t | 2 +- .../errors/general_error_regression.c3t | 4 +- .../errors/simple_static_failable.c3t | 2 +- test/test_suite/errors/try_assign.c3t | 2 +- test/test_suite/errors/try_catch_if.c3t | 2 +- .../errors/try_catch_unwrapping_while_if.c3 | 2 +- test/test_suite/errors/try_with_unwrapper.c3t | 2 +- test/test_suite/expressions/addr_of_fails.c3 | 2 +- .../expressions/casts/cast_failable.c3 | 2 +- .../from_docs/examples_if_catch.c3t | 2 +- .../functions/default_param_fail.c3 | 2 +- test/test_suite/functions/test_regression.c3t | 2 +- .../methods/enum_distinct_err_methods.c3t | 2 +- test/test_suite/statements/switch_errors.c3 | 2 +- .../statements/various_switching.c3t | 4 +- test/test_suite/switch/failable_switch.c3 | 2 +- 37 files changed, 167 insertions(+), 171 deletions(-) diff --git a/resources/examples/base64.c3 b/resources/examples/base64.c3 index 6542ac9e7..cb47a4bc8 100644 --- a/resources/examples/base64.c3 +++ b/resources/examples/base64.c3 @@ -2,7 +2,7 @@ module base64; // Based on the C2 version. -errtype DecodingError +optenum DecodingError { INVALID_CHARACTER } diff --git a/src/compiler/ast.c b/src/compiler/ast.c index 5ae5d6ccc..3cdabe73e 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -69,7 +69,7 @@ const char *decl_to_name(Decl *decl) case DECL_OPTVALUE: return "err value"; case DECL_OPTENUM: - return "errtype"; + return "optenum"; case DECL_FUNC: return "function"; case DECL_GENERIC: diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index a0c1e7035..64c21afe5 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -14,9 +14,6 @@ BuildTarget active_target; Vmem ast_arena; Vmem expr_arena; -Vmem sourceloc_arena; -Vmem toktype_arena; -Vmem tokdata_arena; Vmem decl_arena; Vmem type_info_arena; @@ -40,9 +37,6 @@ void compiler_init(const char *std_lib_dir) vmem_init(&ast_arena, 4 * 1024); vmem_init(&expr_arena, 4 * 1024); vmem_init(&decl_arena, 1024); - vmem_init(&sourceloc_arena, 4 * 1024); - vmem_init(&toktype_arena, 4 * 1024); - vmem_init(&tokdata_arena, 4 * 1024); vmem_init(&type_info_arena, 1024); // Create zero index value. if (std_lib_dir) @@ -129,14 +123,24 @@ static void free_arenas(void) { if (debug_stats) { - printf("-- AST/EXPR INFO -- \n"); - printf(" * Ast memory use: %llukb\n", (unsigned long long)ast_arena.allocated / 1024); - printf(" * Decl memory use: %llukb\n", (unsigned long long)decl_arena.allocated / 1024); - printf(" * Expr memory use: %llukb\n", (unsigned long long)expr_arena.allocated / 1024); - printf(" * TypeInfo memory use: %llukb\n", (unsigned long long)type_info_arena.allocated / 1024); - printf(" * Token memory use: %llukb\n", (unsigned long long)(toktype_arena.allocated) / 1024); - printf(" * Sourceloc memory use: %llukb\n", (unsigned long long)(sourceloc_arena.allocated) / 1024); - printf(" * Token data memory use: %llukb\n", (unsigned long long)(tokdata_arena.allocated) / 1024); + printf("-- AST/EXPR/TYPE INFO -- \n"); + printf(" * Ast size: %u bytes\n", (unsigned)sizeof(Ast)); + printf(" * Decl size: %u bytes\n", (unsigned)sizeof(Decl)); + printf(" * Expr size: %u bytes\n", (unsigned)sizeof(Expr)); + printf(" * TypeInfo size: %u bytes\n", (unsigned)sizeof(TypeInfo)); + printf(" * Ast memory use: %llukb (%u elements)\n", + (unsigned long long)ast_arena.allocated / 1024, + (unsigned)(ast_arena.allocated / sizeof(Ast))); + printf(" * Decl memory use: %llukb (%u elements)\n", + (unsigned long long)decl_arena.allocated / 1024, + (unsigned)(decl_arena.allocated / sizeof(Decl))); + printf(" * Expr memory use: %llukb (%u elements)\n", + (unsigned long long)expr_arena.allocated / 1024, + (unsigned)(expr_arena.allocated / sizeof(Expr))); + printf(" * TypeInfo memory use: %llukb (%u elements)\n", + (unsigned long long)type_info_arena.allocated / 1024, + (unsigned)(type_info_arena.allocated / sizeof(TypeInfo))); + } ast_arena_free(); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index a74ab9cae..a953b734b 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -214,12 +214,6 @@ typedef struct unsigned pref_alignment : 8; } TypeBuiltin; -typedef struct -{ - const char *name; - SourceSpan span; - Path *path; -} TypeUnresolved; typedef struct { @@ -265,13 +259,18 @@ struct Type_ struct TypeInfo_ { ResolveStatus resolve_status : 3; + TypeInfoKind kind : 6; bool failable : 1; Type *type; - TypeInfoKind kind; SourceSpan span; + union { - TypeUnresolved unresolved; + struct + { + const char *name; + Path *path; + } unresolved; Expr *unresolved_type_expr; struct { @@ -287,7 +286,7 @@ typedef struct { Path *path; const char *name; - SourceSpan name_span; + SourceSpan span; union { Expr *expr; @@ -607,7 +606,7 @@ typedef struct Decl_ Decl **methods; union { - // Unions, Errtype and Struct use strukt + // Unions, Optenum and Struct use strukt StructDecl strukt; EnumDecl enums; DistinctDecl distinct_decl; @@ -693,7 +692,6 @@ typedef struct }; Expr **arguments; Decl **body_arguments; - Attr **attributes; } ExprCall; typedef struct @@ -926,9 +924,9 @@ typedef struct struct Expr_ { + SourceSpan span; ExprKind expr_kind : 8; ResolveStatus resolve_status : 4; - SourceSpan span; Type *type; union { ExprVariantSwitch variant_switch; // 32 @@ -946,7 +944,7 @@ struct Expr_ ExprUnary unary_expr; // 16 Expr** try_unwrap_chain_expr; // 8 ExprTryUnwrap try_unwrap_expr; // 24 - ExprCall call_expr; // 40 + ExprCall call_expr; // 32 ExprSlice slice_expr; // 32 Expr *inner_expr; // 8 ExprCatchUnwrap catch_unwrap_expr; // 24 @@ -972,9 +970,9 @@ struct Expr_ ExprBuiltin builtin_expr; // 16 }; }; -static_assert(sizeof(ExprCall) == 40, "Ooops"); +//static_assert(sizeof(ExprCall) == 32, "Ooops"); -static_assert(sizeof(Expr) == 64, "Ooops"); +//static_assert(sizeof(Expr) == 56, "Ooops"); typedef struct { @@ -1599,6 +1597,7 @@ extern const char *kw_elementref; extern const char *kw_elementset; extern const char *kw_len; extern const char *kw_nan; +extern const char *kw_noinline; extern const char *kw_main; extern const char *kw_ordinal; extern const char *kw_reqparse; diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 4384012fa..4595c9a43 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -287,7 +287,6 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) MACRO_COPY_ASTID(expr->call_expr.body); MACRO_COPY_DECL_LIST(expr->call_expr.body_arguments); MACRO_COPY_EXPR_LIST(expr->call_expr.arguments); - if (expr->call_expr.attributes) REMINDER("Copy attributes?"); return expr; case EXPR_SUBSCRIPT: case EXPR_SUBSCRIPT_ADDR: diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 392cb792b..96bd5f1f2 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -438,7 +438,6 @@ typedef enum TOKEN_DO, TOKEN_ELSE, TOKEN_ENUM, - TOKEN_ERRTYPE, TOKEN_EXTERN, TOKEN_FALSE, TOKEN_FOR, @@ -467,7 +466,6 @@ typedef enum TOKEN_ERRNUM, TOKEN_OPTNUM, TOKEN_OPTENUM, - TOKEN_RESNUM, TOKEN_CT_ALIGNOF, // $alignof TOKEN_CT_ASSERT, // $assert diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index bf5c346da..858a53fdc 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -711,7 +711,34 @@ static Expr *parse_call_expr(ParseContext *c, Expr *left) { ASSIGN_ASTID_OR_RET(call->call_expr.body, parse_compound_stmt(c), poisoned_expr); } - if (!parse_attributes(c, &call->call_expr.attributes)) return false; + Attr *attr; + int force_inline = -1; + while (1) + { + if (!parse_attribute(c, &attr)) return poisoned_expr; + if (!attr) break; + if (attr->name != kw_inline && attr->name != kw_noinline) + { + SEMA_ERROR(attr, "Only '@inline' and '@noinline' are valid attributes for calls."); + return poisoned_expr; + } + int new_inline = attr->name == kw_inline; + if (new_inline == force_inline) + { + SEMA_ERROR(attr, "Repeat of the same attribute is not allowed."); + return poisoned_expr; + } + if (force_inline != -1) + { + SEMA_ERROR(attr, "@inline and @noinline cannot be combined"); + } + force_inline = new_inline; + } + if (force_inline != -1) + { + call->call_expr.force_inline = force_inline == 1; + call->call_expr.force_noinline = force_inline == 0; + } return call; } @@ -909,7 +936,6 @@ static Expr *parse_type_or_expression_with_path(ParseContext *c, Path *path, Typ { type = type_info_new(TYPE_INFO_IDENTIFIER, path->span); type->unresolved.path = path; - type->unresolved.span = c->span; type->unresolved.name = symstr(c); advance_and_verify(c, TOKEN_TYPE_IDENT); RANGE_EXTEND_PREV(type); @@ -1654,7 +1680,6 @@ Expr *parse_type_expression_with_path(ParseContext *c, Path *path) { type = type_info_new(TYPE_INFO_IDENTIFIER, path->span); type->unresolved.path = path; - type->unresolved.span = c->span; type->unresolved.name = symstr(c); advance_and_verify(c, TOKEN_TYPE_IDENT); RANGE_EXTEND_PREV(type); diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 863b4d5a1..7a3738471 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -38,11 +38,9 @@ void recover_top_level(ParseContext *c) case TOKEN_ENUM: case TOKEN_GENERIC: case TOKEN_DEFINE: - case TOKEN_ERRTYPE: case TOKEN_OPTENUM: case TOKEN_OPTNUM: case TOKEN_ERRNUM: - case TOKEN_RESNUM: return; case TOKEN_IDENT: // Incr arrays only case TOKEN_CONST: @@ -514,7 +512,6 @@ static inline TypeInfo *parse_base_type(ParseContext *c) TypeInfo *type_info = type_info_new(TYPE_INFO_IDENTIFIER, range); type_info->unresolved.path = path; type_info->unresolved.name = symstr(c); - type_info->unresolved.span = c->span; if (!consume_type_name(c, "type")) return poisoned_type_info; RANGE_EXTEND_PREV(type_info); return type_info; @@ -527,12 +524,10 @@ static inline TypeInfo *parse_base_type(ParseContext *c) case TOKEN_TYPE_IDENT: type_info = type_info_new_curr(c, TYPE_INFO_IDENTIFIER); type_info->unresolved.name = symstr(c); - type_info->unresolved.span = c->span; break; case TOKEN_CT_TYPE_IDENT: type_info = type_info_new_curr(c, TYPE_INFO_CT_IDENTIFIER); type_info->unresolved.name = symstr(c); - type_info->unresolved.span = c->span; break; case TYPE_TOKENS: type_found = type_from_token(c->tok); @@ -819,7 +814,40 @@ Decl *parse_var_decl(ParseContext *c) // --- Parse parameters & throws & attributes +bool parse_attribute(ParseContext *c, Attr **attribute_ref) +{ + if (!try_consume(c, TOKEN_AT)) + { + *attribute_ref = NULL; + return true; + } + bool had_error; + Path *path = parse_path_prefix(c, &had_error); + if (had_error) return false; + Attr *attr = CALLOCS(Attr); + + attr->name = symstr(c); + attr->span = c->span; + attr->path = path; + + if (tok_is(c, TOKEN_TYPE_IDENT) || tok_is(c, TOKEN_TYPE_IDENT)) + { + advance(c); + } + else + { + TRY_CONSUME_OR_RET(TOKEN_IDENT, "Expected an attribute", false); + } + + if (tok_is(c, TOKEN_LPAREN)) + { + ASSIGN_EXPR_OR_RET(attr->expr, parse_const_paren_expr(c), false); + } + + *attribute_ref = attr; + return true; +} /** * attribute_list * : attribute @@ -839,38 +867,18 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref) { *attributes_ref = NULL; - while (try_consume(c, TOKEN_AT)) + while (1) { - bool had_error; - Path *path = parse_path_prefix(c, &had_error); - if (had_error) return false; - - Attr *attr = CALLOCS(Attr); - - attr->name = symstr(c); - attr->name_span = c->span; - attr->path = path; - - if (tok_is(c, TOKEN_TYPE_IDENT) || tok_is(c, TOKEN_TYPE_IDENT)) - { - advance(c); - } - else - { - TRY_CONSUME_OR_RET(TOKEN_IDENT, "Expected an attribute", false); - } - - if (tok_is(c, TOKEN_LPAREN)) - { - ASSIGN_EXPR_OR_RET(attr->expr, parse_const_paren_expr(c), false); - } + Attr *attr; + if (!parse_attribute(c, &attr)) return false; + if (!attr) return true; const char *name = attr->name; VECEACH(*attributes_ref, i) { Attr *other_attr = *attributes_ref[i]; if (other_attr->name == name) { - sema_error_at(attr->name_span, "Repeat of attribute '%s' here.", name); + SEMA_ERROR(attr, "Repeat of attribute '%s' here.", name); return false; } } @@ -1734,8 +1742,8 @@ static inline Decl *parse_macro_declaration(ParseContext *c, Visibility visibili /** * error_declaration - * : ERRTYPE TYPE_IDENT ';' - * | ERRTYPE TYPE_IDENT '{' error_data '}' + * : OPTENUM TYPE_IDENT ';' + * | OPTENUM TYPE_IDENT '{' error_data '}' * ; */ static inline Decl *parse_optenum_declaration(ParseContext *c, Visibility visibility) @@ -2336,8 +2344,6 @@ Decl *parse_top_level_statement(ParseContext *c) case TOKEN_OPTENUM: case TOKEN_OPTNUM: case TOKEN_ERRNUM: - case TOKEN_RESNUM: - case TOKEN_ERRTYPE: { ASSIGN_DECL_OR_RET(decl, parse_optenum_declaration(c, visibility), poisoned_decl); break; diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index b8f11ff1a..66c7e1959 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -994,11 +994,9 @@ Ast *parse_stmt(ParseContext *c) case TOKEN_MODULE: case TOKEN_EXTERN: case TOKEN_STRUCT: - case TOKEN_ERRTYPE: case TOKEN_OPTENUM: case TOKEN_OPTNUM: case TOKEN_ERRNUM: - case TOKEN_RESNUM: case TOKEN_UNION: case TOKEN_DEFINE: case TOKEN_DOCS_START: diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index b95dd84de..9aac0ef1f 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -34,6 +34,7 @@ Expr *parse_cond(ParseContext *c); Expr *parse_assert_expr(ParseContext *c); Ast* parse_compound_stmt(ParseContext *c); Ast *parse_jump_stmt_no_eos(ParseContext *c); +bool parse_attribute(ParseContext *c, Attr **attribute_ref); bool parse_attributes(ParseContext *c, Attr ***attributes_ref); bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type, bool allow_multiple_values); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index b1a14edfe..20afddade 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -395,7 +395,7 @@ static bool sema_analyse_struct_union(SemaContext *context, Decl *decl) #undef SET_ATTR if (had) { - sema_error_at(attr->name_span, "Attribute occurred twice, please remove one."); + sema_error_at(attr->span, "Attribute occurred twice, please remove one."); return decl_poison(decl); } } @@ -549,14 +549,14 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl) case ATTRIBUTE_BIGENDIAN: if (decl->bitstruct.little_endian) { - sema_error_at(attr->name_span, "Attribute cannot be combined with @littleendian"); + sema_error_at(attr->span, "Attribute cannot be combined with @littleendian"); return decl_poison(decl); } SET_ATTR(big_endian); case ATTRIBUTE_LITTLEENDIAN: if (decl->bitstruct.big_endian) { - sema_error_at(attr->name_span, "Attribute cannot be combined with @bigendian"); + sema_error_at(attr->span, "Attribute cannot be combined with @bigendian"); return decl_poison(decl); } SET_ATTR(little_endian); @@ -566,7 +566,7 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl) #undef SET_ATTR if (had) { - sema_error_at(attr->name_span, "Attribute occurred twice, please remove one."); + sema_error_at(attr->span, "Attribute occurred twice, please remove one."); return decl_poison(decl); } } @@ -1154,7 +1154,7 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute AttributeType type = attribute_by_name(attr); if (type == ATTRIBUTE_NONE) { - sema_error_at(attr->name_span, "There is no attribute with the name '%s', did you mistype?", attr->name); + sema_error_at(attr->span, "There is no attribute with the name '%s', did you mistype?", attr->name); return ATTRIBUTE_NONE; } static AttributeDomain attribute_domain[NUMBER_OF_ATTRIBUTES] = { @@ -1185,7 +1185,7 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute if ((attribute_domain[type] & domain) != domain) { - sema_error_at(attr->name_span, "'%s' is not a valid %s attribute.", attr->name, attribute_domain_to_string(domain)); + sema_error_at(attr->span, "'%s' is not a valid %s attribute.", attr->name, attribute_domain_to_string(domain)); return ATTRIBUTE_NONE; } switch (type) @@ -1230,7 +1230,7 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute case ATTRIBUTE_ALIGN: if (!attr->expr) { - sema_error_at(attr->name_span, "'align' requires an power-of-2 argument, e.g. align(8)."); + sema_error_at(attr->span, "'align' requires an power-of-2 argument, e.g. align(8)."); return ATTRIBUTE_NONE; } if (!sema_analyse_expr(context, attr->expr)) return false; @@ -1264,12 +1264,12 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute case ATTRIBUTE_EXTNAME: if (context->unit->module->is_generic) { - sema_error_at(attr->name_span, "'extname' attributes are not allowed in generic modules."); + sema_error_at(attr->span, "'extname' attributes are not allowed in generic modules."); return false; } if (!attr->expr) { - sema_error_at(attr->name_span, "'%s' requires a string argument, e.g. %s(\"foo\").", attr->name, attr->name); + sema_error_at(attr->span, "'%s' requires a string argument, e.g. %s(\"foo\").", attr->name, attr->name); return ATTRIBUTE_NONE; } if (!sema_analyse_expr(context, attr->expr)) return false; @@ -1579,12 +1579,12 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl) #undef SET_ATTR if (had) { - sema_error_at(attr->name_span, "Attribute occurred twice, please remove one."); + sema_error_at(attr->span, "Attribute occurred twice, please remove one."); return decl_poison(decl); } if (decl->func_decl.attr_inline && decl->func_decl.attr_noinline) { - sema_error_at(attr->name_span, "A function cannot be 'inline' and 'noinline' at the same time."); + sema_error_at(attr->span, "A function cannot be 'inline' and 'noinline' at the same time."); return decl_poison(decl); } } @@ -1679,7 +1679,7 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) } if (had) { - sema_error_at(attr->name_span, "Attribute occurred twice, please remove one."); + sema_error_at(attr->span, "Attribute occurred twice, please remove one."); return decl_poison(decl); } } @@ -1828,7 +1828,7 @@ static bool sema_analyse_attributes_for_var(SemaContext *context, Decl *decl) #undef SET_ATTR if (had) { - sema_error_at(attr->name_span, "Attribute occurred twice, please remove one."); + sema_error_at(attr->span, "Attribute occurred twice, please remove one."); return decl_poison(decl); } } @@ -2098,7 +2098,7 @@ static bool sema_analyse_parameterized_define(SemaContext *c, Decl *decl) } decl_path = define_type->unresolved.path; name = define_type->unresolved.name; - span = define_type->unresolved.span; + span = define_type->span; break; } case DEFINE_ATTRIBUTE: diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index acda6c1c0..96bde3a80 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -667,7 +667,7 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr) SEMA_ERROR(expr, "Expected enum name followed by '.' and an enum value."); return expr_poison(expr); case DECL_OPTENUM: - SEMA_ERROR(expr, "Expected errtype name followed by '.' and an error value."); + SEMA_ERROR(expr, "Expected optenum name followed by '.' and an error value."); return expr_poison(expr); case DECL_IMPORT: case DECL_CT_IF: @@ -2117,47 +2117,9 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call) return success; } -static inline bool sema_analyse_call_attributes(SemaContext *context, Decl *decl, Expr *call_expr) -{ - Attr **attributes = call_expr->call_expr.attributes; - int force_inline = -1; - VECEACH(attributes, i) - { - Attr *attr = attributes[i]; - AttributeType attribute = sema_analyse_attribute(context, attr, ATTR_CALL); - if (attribute == ATTRIBUTE_NONE) return false; - switch (attribute) - { - case ATTRIBUTE_INLINE: - case ATTRIBUTE_NOINLINE: - if (decl && decl->decl_kind != DECL_FUNC) - { - sema_error_at(attr->name_span, - "Inline / noinline attribute is only allowed for direct function/method calls"); - return false; - } - if (force_inline != -1) - { - sema_error_at(attr->name_span, "Only a single inline / noinline attribute is allowed on a call."); - return false; - } - force_inline = attribute == ATTRIBUTE_INLINE ? 1 : 0; - break; - default: - UNREACHABLE; - } - } - if (force_inline != -1) - { - call_expr->call_expr.force_inline = force_inline == 1; - call_expr->call_expr.force_noinline = force_inline == 0; - } - return true; -} bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool is_macro, bool failable) { expr->call_expr.is_type_method = struct_var != NULL; - if (!sema_analyse_call_attributes(context, decl, expr)) return expr_poison(expr); if (decl == NULL) { return sema_expr_analyse_var_call(context, expr, type_flatten_distinct_failable(exprptr(expr->call_expr.function)->type), failable); @@ -6633,7 +6595,7 @@ RETRY: { case TOKEN_TYPE_IDENT: type_info->unresolved.name = ident; - type_info->unresolved.span = expr->span; + type_info->span = expr->span; type_info->unresolved.path = path; type_info->kind = TYPE_INFO_IDENTIFIER; goto RETRY; diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 4bd30be54..44d34557c 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -768,16 +768,21 @@ static inline bool sema_analyse_for_cond(SemaContext *context, ExprId *cond_ref, cond = context_pop_defers_and_wrap_expr(context, cond); // If this is const true, then set this to infinite and remove the expression. - if (cond->expr_kind == EXPR_CONST && cond->const_expr.b) + Expr *cond_last = cond->expr_kind == EXPR_COND ? VECLAST(cond->cond_expr) : cond; + assert(cond_last); + if (cond_last->expr_kind == EXPR_CONST && cond_last->const_expr.b) { - cond = NULL; + if (cond->expr_kind != EXPR_COND || vec_size(cond->cond_expr) == 1) + { + cond = NULL; + } *infinite = true; } else { *infinite = false; } - *cond_ref = exprid(cond); + *cond_ref = cond ? exprid(cond) : 0; return true; } static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement) @@ -809,8 +814,8 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement) Ast *body = astptr(statement->for_stmt.body); PUSH_BREAKCONT(statement); - success = sema_analyse_statement(context, body); - statement->for_stmt.flow.no_exit = context->active_scope.jump_end; + success = sema_analyse_statement(context, body); + statement->for_stmt.flow.no_exit = context->active_scope.jump_end; POP_BREAKCONT(); // End for body scope @@ -846,7 +851,7 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement) SCOPE_OUTER_END; - if (statement->for_stmt.flow.no_exit && is_infinite && !statement->for_stmt.flow.has_break) + if (statement->for_stmt.flow.no_exit || (is_infinite && !statement->for_stmt.flow.has_break)) { context->active_scope.jump_end = true; } diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index 0a3961bf2..55b9f5e8e 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -121,7 +121,7 @@ static inline bool sema_resolve_array_type(SemaContext *context, TypeInfo *type, static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_info) { - Decl *decl = sema_resolve_symbol(context, type_info->unresolved.name, type_info->unresolved.path, type_info->unresolved.span); + Decl *decl = sema_resolve_symbol(context, type_info->unresolved.name, type_info->unresolved.path, type_info->span); // Already handled if (!decl_ok(decl)) @@ -172,7 +172,7 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in case DECL_GENERIC: case DECL_LABEL: case DECL_ATTRIBUTE: - SEMA_ERROR(&type_info->unresolved, "This is not a type."); + SEMA_ERROR(type_info, "This is not a type."); return type_info_poison(type_info); case DECL_CT_ELSE: case DECL_CT_IF: @@ -235,7 +235,7 @@ bool sema_resolve_type_shallow(SemaContext *context, TypeInfo *type_info, bool a if (type_info->resolve_status == RESOLVE_RUNNING) { // TODO this is incorrect for unresolved expressions - SEMA_ERROR(&type_info->unresolved, + SEMA_ERROR(type_info, "Circular dependency resolving type '%s'.", type_info->unresolved.name); return type_info_poison(type_info); @@ -262,7 +262,7 @@ RETRY: { case TOKEN_TYPE_IDENT: type_info->unresolved.name = ident; - type_info->unresolved.span = expr->span; + type_info->span = expr->span; type_info->unresolved.path = path; type_info->kind = TYPE_INFO_IDENTIFIER; goto RETRY; @@ -273,7 +273,7 @@ RETRY: return false; } type_info->type = type_from_token(type); - return true; + goto APPEND_QUALIFIERS; default: SEMA_ERROR(expr, "Only type names may be resolved with $evaltype."); return type_info_poison(type_info); @@ -289,7 +289,7 @@ RETRY: type_info->type = expr->type; type_info->resolve_status = RESOLVE_DONE; assert(!type_info->failable); - return true; + goto APPEND_QUALIFIERS; } case TYPE_INFO_INFERRED_ARRAY: if (!allow_inferred_type) @@ -307,9 +307,11 @@ RETRY: if (!sema_resolve_ptr_type(context, type_info)) return false; break; } +APPEND_QUALIFIERS: if (type_info->failable) { - type_info->type = type_get_failable(type_info->type); + Type *type = type_info->type; + if (!type_is_failable(type)) type_info->type = type_get_failable(type); } return true; } diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 143bc2f1d..225da31fb 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -67,6 +67,7 @@ const char *kw_main; const char *kw_max; const char *kw_min; const char *kw_nan; +const char *kw_noinline; const char *kw_ordinal; const char *kw_param; const char *kw_ptr; @@ -162,6 +163,7 @@ void symtab_init(uint32_t capacity) kw_max = KW_DEF("max"); kw_min = KW_DEF("min"); kw_nan = KW_DEF("nan"); + kw_noinline = KW_DEF("noinline"); kw_ordinal = KW_DEF("ordinal"); kw_param = KW_DEF("param"); kw_ptr = KW_DEF("ptr"); @@ -203,7 +205,7 @@ void symtab_init(uint32_t capacity) } attribute_list[ATTRIBUTE_INLINE] = kw_inline; - attribute_list[ATTRIBUTE_NOINLINE] = KW_DEF("noinline"); + attribute_list[ATTRIBUTE_NOINLINE] = kw_noinline; attribute_list[ATTRIBUTE_BIGENDIAN] = KW_DEF("bigendian"); attribute_list[ATTRIBUTE_LITTLEENDIAN] = KW_DEF("littleendian"); attribute_list[ATTRIBUTE_NORETURN] = KW_DEF("noreturn"); diff --git a/src/compiler/tokens.c b/src/compiler/tokens.c index ddcd314b0..24f74be1f 100644 --- a/src/compiler/tokens.c +++ b/src/compiler/tokens.c @@ -216,8 +216,6 @@ const char *token_type_to_string(TokenType type) return "enum"; case TOKEN_EXTERN: return "extern"; - case TOKEN_ERRTYPE: - return "errtype"; case TOKEN_FALSE: return "false"; case TOKEN_FOR: @@ -273,9 +271,6 @@ const char *token_type_to_string(TokenType type) return "optnum"; case TOKEN_ERRNUM: return "errnum"; - case TOKEN_RESNUM: - return "resnum"; - // Named types case TOKEN_VOID: diff --git a/test/test_suite/cast/cast_to_failable.c3 b/test/test_suite/cast/cast_to_failable.c3 index dc1e8620b..fc2d16a19 100644 --- a/test/test_suite/cast/cast_to_failable.c3 +++ b/test/test_suite/cast/cast_to_failable.c3 @@ -1,4 +1,4 @@ -errtype MyErr +optenum MyErr { FOO } diff --git a/test/test_suite/distinct/distinct_invalid.c3 b/test/test_suite/distinct/distinct_invalid.c3 index 6295e183c..e21cfb375 100644 --- a/test/test_suite/distinct/distinct_invalid.c3 +++ b/test/test_suite/distinct/distinct_invalid.c3 @@ -1,4 +1,4 @@ -errtype Error +optenum Error {} define Foo1 = distinct Error; // #error: You cannot create a distinct type from an error diff --git a/test/test_suite/errors/anyerr_void.c3t b/test/test_suite/errors/anyerr_void.c3t index 3b4916078..979b25ea7 100644 --- a/test/test_suite/errors/anyerr_void.c3t +++ b/test/test_suite/errors/anyerr_void.c3t @@ -1,4 +1,4 @@ -errtype MyError +optenum MyError { FOO, BAR diff --git a/test/test_suite/errors/error_decl_ok.c3 b/test/test_suite/errors/error_decl_ok.c3 index 81188ebe4..bfaac243d 100644 --- a/test/test_suite/errors/error_decl_ok.c3 +++ b/test/test_suite/errors/error_decl_ok.c3 @@ -1,17 +1,17 @@ module errors; -errtype TheError +optenum TheError { A } -errtype TheError2 +optenum TheError2 { A, B } -errtype TheError3 +optenum TheError3 { C, D } diff --git a/test/test_suite/errors/failable_inits.c3t b/test/test_suite/errors/failable_inits.c3t index cf065855b..a6450d78a 100644 --- a/test/test_suite/errors/failable_inits.c3t +++ b/test/test_suite/errors/failable_inits.c3t @@ -2,7 +2,7 @@ module test; import std::io; -errtype Foo +optenum Foo { MY_VAL1, MY_VAL2, diff --git a/test/test_suite/errors/failable_taddr_and_access.c3t b/test/test_suite/errors/failable_taddr_and_access.c3t index e7275c8a7..c1e3e454f 100644 --- a/test/test_suite/errors/failable_taddr_and_access.c3t +++ b/test/test_suite/errors/failable_taddr_and_access.c3t @@ -6,7 +6,7 @@ struct Foo int x, y; } -errtype MyErr +optenum MyErr { FOO } diff --git a/test/test_suite/errors/general_error_regression.c3t b/test/test_suite/errors/general_error_regression.c3t index fb8338389..d91c9280a 100644 --- a/test/test_suite/errors/general_error_regression.c3t +++ b/test/test_suite/errors/general_error_regression.c3t @@ -1,7 +1,7 @@ module foo; import std::io; -errtype Foo +optenum Foo { X, Y, @@ -12,7 +12,7 @@ errtype Foo } -errtype Foob +optenum Foob { X1, Y2 diff --git a/test/test_suite/errors/simple_static_failable.c3t b/test/test_suite/errors/simple_static_failable.c3t index 6d3cf7c3b..8c9a099c4 100644 --- a/test/test_suite/errors/simple_static_failable.c3t +++ b/test/test_suite/errors/simple_static_failable.c3t @@ -2,7 +2,7 @@ module foo; -errtype Blurg +optenum Blurg { Y } diff --git a/test/test_suite/errors/try_assign.c3t b/test/test_suite/errors/try_assign.c3t index 711b6f629..ed7365b62 100644 --- a/test/test_suite/errors/try_assign.c3t +++ b/test/test_suite/errors/try_assign.c3t @@ -1,7 +1,7 @@ // #target: x64-darwin extern fn int! err(); -errtype FooErr { QBERT } +optenum FooErr { QBERT } extern fn int printf(char* fmt, ...); fn void main() diff --git a/test/test_suite/errors/try_catch_if.c3t b/test/test_suite/errors/try_catch_if.c3t index 2cff186db..052009f07 100644 --- a/test/test_suite/errors/try_catch_if.c3t +++ b/test/test_suite/errors/try_catch_if.c3t @@ -13,7 +13,7 @@ fn int! tester() return 222; } -errtype Foo +optenum Foo { A } diff --git a/test/test_suite/errors/try_catch_unwrapping_while_if.c3 b/test/test_suite/errors/try_catch_unwrapping_while_if.c3 index 06794efcd..64f804b2d 100644 --- a/test/test_suite/errors/try_catch_unwrapping_while_if.c3 +++ b/test/test_suite/errors/try_catch_unwrapping_while_if.c3 @@ -1,7 +1,7 @@ extern fn int printf(char* fmt, ...); extern fn int! err(); -errtype FooErr +optenum FooErr { X } diff --git a/test/test_suite/errors/try_with_unwrapper.c3t b/test/test_suite/errors/try_with_unwrapper.c3t index 394d0c5ce..09f17d763 100644 --- a/test/test_suite/errors/try_with_unwrapper.c3t +++ b/test/test_suite/errors/try_with_unwrapper.c3t @@ -13,7 +13,7 @@ fn int! tester() return 222; } -errtype Foo +optenum Foo { A } diff --git a/test/test_suite/expressions/addr_of_fails.c3 b/test/test_suite/expressions/addr_of_fails.c3 index fa830c6a3..90e3be3d2 100644 --- a/test/test_suite/expressions/addr_of_fails.c3 +++ b/test/test_suite/expressions/addr_of_fails.c3 @@ -62,7 +62,7 @@ fn void test6() define Baz = Foo; define Bar = distinct int; -errtype Err { FOO } +optenum Err { FOO } union Un { int x; } enum MyEnum { BAR } diff --git a/test/test_suite/expressions/casts/cast_failable.c3 b/test/test_suite/expressions/casts/cast_failable.c3 index 28cb23aeb..7dc829abd 100644 --- a/test/test_suite/expressions/casts/cast_failable.c3 +++ b/test/test_suite/expressions/casts/cast_failable.c3 @@ -1,4 +1,4 @@ -errtype MyErr +optenum MyErr { FOO } diff --git a/test/test_suite/from_docs/examples_if_catch.c3t b/test/test_suite/from_docs/examples_if_catch.c3t index 4045ead10..71d4208a5 100644 --- a/test/test_suite/from_docs/examples_if_catch.c3t +++ b/test/test_suite/from_docs/examples_if_catch.c3t @@ -2,7 +2,7 @@ module demo; import std::io; -errtype MathError +optenum MathError { DIVISION_BY_ZERO } diff --git a/test/test_suite/functions/default_param_fail.c3 b/test/test_suite/functions/default_param_fail.c3 index 8872acfca..e3328c40a 100644 --- a/test/test_suite/functions/default_param_fail.c3 +++ b/test/test_suite/functions/default_param_fail.c3 @@ -1,7 +1,7 @@ int z; -errtype MyError +optenum MyError { FOO, } diff --git a/test/test_suite/functions/test_regression.c3t b/test/test_suite/functions/test_regression.c3t index 0804af236..906b6aa73 100644 --- a/test/test_suite/functions/test_regression.c3t +++ b/test/test_suite/functions/test_regression.c3t @@ -203,7 +203,7 @@ fn Type getMult(Type a) } Type argh = 234; -errtype MyErr +optenum MyErr { X, Y diff --git a/test/test_suite/methods/enum_distinct_err_methods.c3t b/test/test_suite/methods/enum_distinct_err_methods.c3t index 43d171c38..3eed42e4f 100644 --- a/test/test_suite/methods/enum_distinct_err_methods.c3t +++ b/test/test_suite/methods/enum_distinct_err_methods.c3t @@ -3,7 +3,7 @@ module foo; import std::io; -errtype Foo +optenum Foo { X } diff --git a/test/test_suite/statements/switch_errors.c3 b/test/test_suite/statements/switch_errors.c3 index c67b45469..aa2317d69 100644 --- a/test/test_suite/statements/switch_errors.c3 +++ b/test/test_suite/statements/switch_errors.c3 @@ -135,7 +135,7 @@ fn void test_missing_no_cases(Baz x) } } -errtype MathError +optenum MathError { DIVISION_BY_ZERO } diff --git a/test/test_suite/statements/various_switching.c3t b/test/test_suite/statements/various_switching.c3t index 166b6f3eb..6f27af2ad 100644 --- a/test/test_suite/statements/various_switching.c3t +++ b/test/test_suite/statements/various_switching.c3t @@ -2,11 +2,11 @@ module mymodule; extern fn void printf(char *, ...); -errtype HelloErr +optenum HelloErr { FOO, } -errtype ByeErr +optenum ByeErr { BAR, BAZ diff --git a/test/test_suite/switch/failable_switch.c3 b/test/test_suite/switch/failable_switch.c3 index 587e4e0cf..68963012a 100644 --- a/test/test_suite/switch/failable_switch.c3 +++ b/test/test_suite/switch/failable_switch.c3 @@ -1,4 +1,4 @@ -errtype MyError +optenum MyError { FOO }