Remove 'errtype' name and reduce Expr / TypeInfo memory footprint.
This commit is contained in:
Christoffer Lerno
2022-03-08 23:38:27 +01:00
committed by GitHub
parent 069a2d40cb
commit 322d714305
37 changed files with 167 additions and 171 deletions

View File

@@ -2,7 +2,7 @@ module base64;
// Based on the C2 version. // Based on the C2 version.
errtype DecodingError optenum DecodingError
{ {
INVALID_CHARACTER INVALID_CHARACTER
} }

View File

@@ -69,7 +69,7 @@ const char *decl_to_name(Decl *decl)
case DECL_OPTVALUE: case DECL_OPTVALUE:
return "err value"; return "err value";
case DECL_OPTENUM: case DECL_OPTENUM:
return "errtype"; return "optenum";
case DECL_FUNC: case DECL_FUNC:
return "function"; return "function";
case DECL_GENERIC: case DECL_GENERIC:

View File

@@ -14,9 +14,6 @@ BuildTarget active_target;
Vmem ast_arena; Vmem ast_arena;
Vmem expr_arena; Vmem expr_arena;
Vmem sourceloc_arena;
Vmem toktype_arena;
Vmem tokdata_arena;
Vmem decl_arena; Vmem decl_arena;
Vmem type_info_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(&ast_arena, 4 * 1024);
vmem_init(&expr_arena, 4 * 1024); vmem_init(&expr_arena, 4 * 1024);
vmem_init(&decl_arena, 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); vmem_init(&type_info_arena, 1024);
// Create zero index value. // Create zero index value.
if (std_lib_dir) if (std_lib_dir)
@@ -129,14 +123,24 @@ static void free_arenas(void)
{ {
if (debug_stats) if (debug_stats)
{ {
printf("-- AST/EXPR INFO -- \n"); printf("-- AST/EXPR/TYPE INFO -- \n");
printf(" * Ast memory use: %llukb\n", (unsigned long long)ast_arena.allocated / 1024); printf(" * Ast size: %u bytes\n", (unsigned)sizeof(Ast));
printf(" * Decl memory use: %llukb\n", (unsigned long long)decl_arena.allocated / 1024); printf(" * Decl size: %u bytes\n", (unsigned)sizeof(Decl));
printf(" * Expr memory use: %llukb\n", (unsigned long long)expr_arena.allocated / 1024); printf(" * Expr size: %u bytes\n", (unsigned)sizeof(Expr));
printf(" * TypeInfo memory use: %llukb\n", (unsigned long long)type_info_arena.allocated / 1024); printf(" * TypeInfo size: %u bytes\n", (unsigned)sizeof(TypeInfo));
printf(" * Token memory use: %llukb\n", (unsigned long long)(toktype_arena.allocated) / 1024); printf(" * Ast memory use: %llukb (%u elements)\n",
printf(" * Sourceloc memory use: %llukb\n", (unsigned long long)(sourceloc_arena.allocated) / 1024); (unsigned long long)ast_arena.allocated / 1024,
printf(" * Token data memory use: %llukb\n", (unsigned long long)(tokdata_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(); ast_arena_free();

View File

@@ -214,12 +214,6 @@ typedef struct
unsigned pref_alignment : 8; unsigned pref_alignment : 8;
} TypeBuiltin; } TypeBuiltin;
typedef struct
{
const char *name;
SourceSpan span;
Path *path;
} TypeUnresolved;
typedef struct typedef struct
{ {
@@ -265,13 +259,18 @@ struct Type_
struct TypeInfo_ struct TypeInfo_
{ {
ResolveStatus resolve_status : 3; ResolveStatus resolve_status : 3;
TypeInfoKind kind : 6;
bool failable : 1; bool failable : 1;
Type *type; Type *type;
TypeInfoKind kind;
SourceSpan span; SourceSpan span;
union union
{ {
TypeUnresolved unresolved; struct
{
const char *name;
Path *path;
} unresolved;
Expr *unresolved_type_expr; Expr *unresolved_type_expr;
struct struct
{ {
@@ -287,7 +286,7 @@ typedef struct
{ {
Path *path; Path *path;
const char *name; const char *name;
SourceSpan name_span; SourceSpan span;
union union
{ {
Expr *expr; Expr *expr;
@@ -607,7 +606,7 @@ typedef struct Decl_
Decl **methods; Decl **methods;
union union
{ {
// Unions, Errtype and Struct use strukt // Unions, Optenum and Struct use strukt
StructDecl strukt; StructDecl strukt;
EnumDecl enums; EnumDecl enums;
DistinctDecl distinct_decl; DistinctDecl distinct_decl;
@@ -693,7 +692,6 @@ typedef struct
}; };
Expr **arguments; Expr **arguments;
Decl **body_arguments; Decl **body_arguments;
Attr **attributes;
} ExprCall; } ExprCall;
typedef struct typedef struct
@@ -926,9 +924,9 @@ typedef struct
struct Expr_ struct Expr_
{ {
SourceSpan span;
ExprKind expr_kind : 8; ExprKind expr_kind : 8;
ResolveStatus resolve_status : 4; ResolveStatus resolve_status : 4;
SourceSpan span;
Type *type; Type *type;
union { union {
ExprVariantSwitch variant_switch; // 32 ExprVariantSwitch variant_switch; // 32
@@ -946,7 +944,7 @@ struct Expr_
ExprUnary unary_expr; // 16 ExprUnary unary_expr; // 16
Expr** try_unwrap_chain_expr; // 8 Expr** try_unwrap_chain_expr; // 8
ExprTryUnwrap try_unwrap_expr; // 24 ExprTryUnwrap try_unwrap_expr; // 24
ExprCall call_expr; // 40 ExprCall call_expr; // 32
ExprSlice slice_expr; // 32 ExprSlice slice_expr; // 32
Expr *inner_expr; // 8 Expr *inner_expr; // 8
ExprCatchUnwrap catch_unwrap_expr; // 24 ExprCatchUnwrap catch_unwrap_expr; // 24
@@ -972,9 +970,9 @@ struct Expr_
ExprBuiltin builtin_expr; // 16 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 typedef struct
{ {
@@ -1599,6 +1597,7 @@ extern const char *kw_elementref;
extern const char *kw_elementset; extern const char *kw_elementset;
extern const char *kw_len; extern const char *kw_len;
extern const char *kw_nan; extern const char *kw_nan;
extern const char *kw_noinline;
extern const char *kw_main; extern const char *kw_main;
extern const char *kw_ordinal; extern const char *kw_ordinal;
extern const char *kw_reqparse; extern const char *kw_reqparse;

View File

@@ -287,7 +287,6 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
MACRO_COPY_ASTID(expr->call_expr.body); MACRO_COPY_ASTID(expr->call_expr.body);
MACRO_COPY_DECL_LIST(expr->call_expr.body_arguments); MACRO_COPY_DECL_LIST(expr->call_expr.body_arguments);
MACRO_COPY_EXPR_LIST(expr->call_expr.arguments); MACRO_COPY_EXPR_LIST(expr->call_expr.arguments);
if (expr->call_expr.attributes) REMINDER("Copy attributes?");
return expr; return expr;
case EXPR_SUBSCRIPT: case EXPR_SUBSCRIPT:
case EXPR_SUBSCRIPT_ADDR: case EXPR_SUBSCRIPT_ADDR:

View File

@@ -438,7 +438,6 @@ typedef enum
TOKEN_DO, TOKEN_DO,
TOKEN_ELSE, TOKEN_ELSE,
TOKEN_ENUM, TOKEN_ENUM,
TOKEN_ERRTYPE,
TOKEN_EXTERN, TOKEN_EXTERN,
TOKEN_FALSE, TOKEN_FALSE,
TOKEN_FOR, TOKEN_FOR,
@@ -467,7 +466,6 @@ typedef enum
TOKEN_ERRNUM, TOKEN_ERRNUM,
TOKEN_OPTNUM, TOKEN_OPTNUM,
TOKEN_OPTENUM, TOKEN_OPTENUM,
TOKEN_RESNUM,
TOKEN_CT_ALIGNOF, // $alignof TOKEN_CT_ALIGNOF, // $alignof
TOKEN_CT_ASSERT, // $assert TOKEN_CT_ASSERT, // $assert

View File

@@ -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); 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; 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 = type_info_new(TYPE_INFO_IDENTIFIER, path->span);
type->unresolved.path = path; type->unresolved.path = path;
type->unresolved.span = c->span;
type->unresolved.name = symstr(c); type->unresolved.name = symstr(c);
advance_and_verify(c, TOKEN_TYPE_IDENT); advance_and_verify(c, TOKEN_TYPE_IDENT);
RANGE_EXTEND_PREV(type); 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 = type_info_new(TYPE_INFO_IDENTIFIER, path->span);
type->unresolved.path = path; type->unresolved.path = path;
type->unresolved.span = c->span;
type->unresolved.name = symstr(c); type->unresolved.name = symstr(c);
advance_and_verify(c, TOKEN_TYPE_IDENT); advance_and_verify(c, TOKEN_TYPE_IDENT);
RANGE_EXTEND_PREV(type); RANGE_EXTEND_PREV(type);

View File

@@ -38,11 +38,9 @@ void recover_top_level(ParseContext *c)
case TOKEN_ENUM: case TOKEN_ENUM:
case TOKEN_GENERIC: case TOKEN_GENERIC:
case TOKEN_DEFINE: case TOKEN_DEFINE:
case TOKEN_ERRTYPE:
case TOKEN_OPTENUM: case TOKEN_OPTENUM:
case TOKEN_OPTNUM: case TOKEN_OPTNUM:
case TOKEN_ERRNUM: case TOKEN_ERRNUM:
case TOKEN_RESNUM:
return; return;
case TOKEN_IDENT: // Incr arrays only case TOKEN_IDENT: // Incr arrays only
case TOKEN_CONST: 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); TypeInfo *type_info = type_info_new(TYPE_INFO_IDENTIFIER, range);
type_info->unresolved.path = path; type_info->unresolved.path = path;
type_info->unresolved.name = symstr(c); type_info->unresolved.name = symstr(c);
type_info->unresolved.span = c->span;
if (!consume_type_name(c, "type")) return poisoned_type_info; if (!consume_type_name(c, "type")) return poisoned_type_info;
RANGE_EXTEND_PREV(type_info); RANGE_EXTEND_PREV(type_info);
return type_info; return type_info;
@@ -527,12 +524,10 @@ static inline TypeInfo *parse_base_type(ParseContext *c)
case TOKEN_TYPE_IDENT: case TOKEN_TYPE_IDENT:
type_info = type_info_new_curr(c, TYPE_INFO_IDENTIFIER); type_info = type_info_new_curr(c, TYPE_INFO_IDENTIFIER);
type_info->unresolved.name = symstr(c); type_info->unresolved.name = symstr(c);
type_info->unresolved.span = c->span;
break; break;
case TOKEN_CT_TYPE_IDENT: case TOKEN_CT_TYPE_IDENT:
type_info = type_info_new_curr(c, TYPE_INFO_CT_IDENTIFIER); type_info = type_info_new_curr(c, TYPE_INFO_CT_IDENTIFIER);
type_info->unresolved.name = symstr(c); type_info->unresolved.name = symstr(c);
type_info->unresolved.span = c->span;
break; break;
case TYPE_TOKENS: case TYPE_TOKENS:
type_found = type_from_token(c->tok); type_found = type_from_token(c->tok);
@@ -819,7 +814,40 @@ Decl *parse_var_decl(ParseContext *c)
// --- Parse parameters & throws & attributes // --- 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_list
* : attribute * : attribute
@@ -839,38 +867,18 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref)
{ {
*attributes_ref = NULL; *attributes_ref = NULL;
while (try_consume(c, TOKEN_AT)) while (1)
{ {
bool had_error; Attr *attr;
Path *path = parse_path_prefix(c, &had_error); if (!parse_attribute(c, &attr)) return false;
if (had_error) return false; if (!attr) return true;
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);
}
const char *name = attr->name; const char *name = attr->name;
VECEACH(*attributes_ref, i) VECEACH(*attributes_ref, i)
{ {
Attr *other_attr = *attributes_ref[i]; Attr *other_attr = *attributes_ref[i];
if (other_attr->name == name) 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; return false;
} }
} }
@@ -1734,8 +1742,8 @@ static inline Decl *parse_macro_declaration(ParseContext *c, Visibility visibili
/** /**
* error_declaration * error_declaration
* : ERRTYPE TYPE_IDENT ';' * : OPTENUM TYPE_IDENT ';'
* | ERRTYPE TYPE_IDENT '{' error_data '}' * | OPTENUM TYPE_IDENT '{' error_data '}'
* ; * ;
*/ */
static inline Decl *parse_optenum_declaration(ParseContext *c, Visibility visibility) 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_OPTENUM:
case TOKEN_OPTNUM: case TOKEN_OPTNUM:
case TOKEN_ERRNUM: case TOKEN_ERRNUM:
case TOKEN_RESNUM:
case TOKEN_ERRTYPE:
{ {
ASSIGN_DECL_OR_RET(decl, parse_optenum_declaration(c, visibility), poisoned_decl); ASSIGN_DECL_OR_RET(decl, parse_optenum_declaration(c, visibility), poisoned_decl);
break; break;

View File

@@ -994,11 +994,9 @@ Ast *parse_stmt(ParseContext *c)
case TOKEN_MODULE: case TOKEN_MODULE:
case TOKEN_EXTERN: case TOKEN_EXTERN:
case TOKEN_STRUCT: case TOKEN_STRUCT:
case TOKEN_ERRTYPE:
case TOKEN_OPTENUM: case TOKEN_OPTENUM:
case TOKEN_OPTNUM: case TOKEN_OPTNUM:
case TOKEN_ERRNUM: case TOKEN_ERRNUM:
case TOKEN_RESNUM:
case TOKEN_UNION: case TOKEN_UNION:
case TOKEN_DEFINE: case TOKEN_DEFINE:
case TOKEN_DOCS_START: case TOKEN_DOCS_START:

View File

@@ -34,6 +34,7 @@ Expr *parse_cond(ParseContext *c);
Expr *parse_assert_expr(ParseContext *c); Expr *parse_assert_expr(ParseContext *c);
Ast* parse_compound_stmt(ParseContext *c); Ast* parse_compound_stmt(ParseContext *c);
Ast *parse_jump_stmt_no_eos(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_attributes(ParseContext *c, Attr ***attributes_ref);
bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type, bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type,
bool allow_multiple_values); bool allow_multiple_values);

View File

@@ -395,7 +395,7 @@ static bool sema_analyse_struct_union(SemaContext *context, Decl *decl)
#undef SET_ATTR #undef SET_ATTR
if (had) 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); return decl_poison(decl);
} }
} }
@@ -549,14 +549,14 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl)
case ATTRIBUTE_BIGENDIAN: case ATTRIBUTE_BIGENDIAN:
if (decl->bitstruct.little_endian) 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); return decl_poison(decl);
} }
SET_ATTR(big_endian); SET_ATTR(big_endian);
case ATTRIBUTE_LITTLEENDIAN: case ATTRIBUTE_LITTLEENDIAN:
if (decl->bitstruct.big_endian) 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); return decl_poison(decl);
} }
SET_ATTR(little_endian); SET_ATTR(little_endian);
@@ -566,7 +566,7 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl)
#undef SET_ATTR #undef SET_ATTR
if (had) 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); return decl_poison(decl);
} }
} }
@@ -1154,7 +1154,7 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute
AttributeType type = attribute_by_name(attr); AttributeType type = attribute_by_name(attr);
if (type == ATTRIBUTE_NONE) 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; return ATTRIBUTE_NONE;
} }
static AttributeDomain attribute_domain[NUMBER_OF_ATTRIBUTES] = { 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) 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; return ATTRIBUTE_NONE;
} }
switch (type) switch (type)
@@ -1230,7 +1230,7 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute
case ATTRIBUTE_ALIGN: case ATTRIBUTE_ALIGN:
if (!attr->expr) 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; return ATTRIBUTE_NONE;
} }
if (!sema_analyse_expr(context, attr->expr)) return false; 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: case ATTRIBUTE_EXTNAME:
if (context->unit->module->is_generic) 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; return false;
} }
if (!attr->expr) 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; return ATTRIBUTE_NONE;
} }
if (!sema_analyse_expr(context, attr->expr)) return false; 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 #undef SET_ATTR
if (had) 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); return decl_poison(decl);
} }
if (decl->func_decl.attr_inline && decl->func_decl.attr_noinline) 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); return decl_poison(decl);
} }
} }
@@ -1679,7 +1679,7 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl)
} }
if (had) 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); return decl_poison(decl);
} }
} }
@@ -1828,7 +1828,7 @@ static bool sema_analyse_attributes_for_var(SemaContext *context, Decl *decl)
#undef SET_ATTR #undef SET_ATTR
if (had) 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); return decl_poison(decl);
} }
} }
@@ -2098,7 +2098,7 @@ static bool sema_analyse_parameterized_define(SemaContext *c, Decl *decl)
} }
decl_path = define_type->unresolved.path; decl_path = define_type->unresolved.path;
name = define_type->unresolved.name; name = define_type->unresolved.name;
span = define_type->unresolved.span; span = define_type->span;
break; break;
} }
case DEFINE_ATTRIBUTE: case DEFINE_ATTRIBUTE:

View File

@@ -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."); SEMA_ERROR(expr, "Expected enum name followed by '.' and an enum value.");
return expr_poison(expr); return expr_poison(expr);
case DECL_OPTENUM: 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); return expr_poison(expr);
case DECL_IMPORT: case DECL_IMPORT:
case DECL_CT_IF: case DECL_CT_IF:
@@ -2117,47 +2117,9 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call)
return success; 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) 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; expr->call_expr.is_type_method = struct_var != NULL;
if (!sema_analyse_call_attributes(context, decl, expr)) return expr_poison(expr);
if (decl == NULL) if (decl == NULL)
{ {
return sema_expr_analyse_var_call(context, expr, type_flatten_distinct_failable(exprptr(expr->call_expr.function)->type), failable); 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: case TOKEN_TYPE_IDENT:
type_info->unresolved.name = ident; type_info->unresolved.name = ident;
type_info->unresolved.span = expr->span; type_info->span = expr->span;
type_info->unresolved.path = path; type_info->unresolved.path = path;
type_info->kind = TYPE_INFO_IDENTIFIER; type_info->kind = TYPE_INFO_IDENTIFIER;
goto RETRY; goto RETRY;

View File

@@ -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); cond = context_pop_defers_and_wrap_expr(context, cond);
// If this is const true, then set this to infinite and remove the expression. // 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; *infinite = true;
} }
else else
{ {
*infinite = false; *infinite = false;
} }
*cond_ref = exprid(cond); *cond_ref = cond ? exprid(cond) : 0;
return true; return true;
} }
static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement) 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); Ast *body = astptr(statement->for_stmt.body);
PUSH_BREAKCONT(statement); PUSH_BREAKCONT(statement);
success = sema_analyse_statement(context, body); success = sema_analyse_statement(context, body);
statement->for_stmt.flow.no_exit = context->active_scope.jump_end; statement->for_stmt.flow.no_exit = context->active_scope.jump_end;
POP_BREAKCONT(); POP_BREAKCONT();
// End for body scope // End for body scope
@@ -846,7 +851,7 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement)
SCOPE_OUTER_END; 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; context->active_scope.jump_end = true;
} }

View File

@@ -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) 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 // Already handled
if (!decl_ok(decl)) if (!decl_ok(decl))
@@ -172,7 +172,7 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in
case DECL_GENERIC: case DECL_GENERIC:
case DECL_LABEL: case DECL_LABEL:
case DECL_ATTRIBUTE: 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); return type_info_poison(type_info);
case DECL_CT_ELSE: case DECL_CT_ELSE:
case DECL_CT_IF: 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) if (type_info->resolve_status == RESOLVE_RUNNING)
{ {
// TODO this is incorrect for unresolved expressions // TODO this is incorrect for unresolved expressions
SEMA_ERROR(&type_info->unresolved, SEMA_ERROR(type_info,
"Circular dependency resolving type '%s'.", "Circular dependency resolving type '%s'.",
type_info->unresolved.name); type_info->unresolved.name);
return type_info_poison(type_info); return type_info_poison(type_info);
@@ -262,7 +262,7 @@ RETRY:
{ {
case TOKEN_TYPE_IDENT: case TOKEN_TYPE_IDENT:
type_info->unresolved.name = ident; type_info->unresolved.name = ident;
type_info->unresolved.span = expr->span; type_info->span = expr->span;
type_info->unresolved.path = path; type_info->unresolved.path = path;
type_info->kind = TYPE_INFO_IDENTIFIER; type_info->kind = TYPE_INFO_IDENTIFIER;
goto RETRY; goto RETRY;
@@ -273,7 +273,7 @@ RETRY:
return false; return false;
} }
type_info->type = type_from_token(type); type_info->type = type_from_token(type);
return true; goto APPEND_QUALIFIERS;
default: default:
SEMA_ERROR(expr, "Only type names may be resolved with $evaltype."); SEMA_ERROR(expr, "Only type names may be resolved with $evaltype.");
return type_info_poison(type_info); return type_info_poison(type_info);
@@ -289,7 +289,7 @@ RETRY:
type_info->type = expr->type; type_info->type = expr->type;
type_info->resolve_status = RESOLVE_DONE; type_info->resolve_status = RESOLVE_DONE;
assert(!type_info->failable); assert(!type_info->failable);
return true; goto APPEND_QUALIFIERS;
} }
case TYPE_INFO_INFERRED_ARRAY: case TYPE_INFO_INFERRED_ARRAY:
if (!allow_inferred_type) if (!allow_inferred_type)
@@ -307,9 +307,11 @@ RETRY:
if (!sema_resolve_ptr_type(context, type_info)) return false; if (!sema_resolve_ptr_type(context, type_info)) return false;
break; break;
} }
APPEND_QUALIFIERS:
if (type_info->failable) 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; return true;
} }

View File

@@ -67,6 +67,7 @@ const char *kw_main;
const char *kw_max; const char *kw_max;
const char *kw_min; const char *kw_min;
const char *kw_nan; const char *kw_nan;
const char *kw_noinline;
const char *kw_ordinal; const char *kw_ordinal;
const char *kw_param; const char *kw_param;
const char *kw_ptr; const char *kw_ptr;
@@ -162,6 +163,7 @@ void symtab_init(uint32_t capacity)
kw_max = KW_DEF("max"); kw_max = KW_DEF("max");
kw_min = KW_DEF("min"); kw_min = KW_DEF("min");
kw_nan = KW_DEF("nan"); kw_nan = KW_DEF("nan");
kw_noinline = KW_DEF("noinline");
kw_ordinal = KW_DEF("ordinal"); kw_ordinal = KW_DEF("ordinal");
kw_param = KW_DEF("param"); kw_param = KW_DEF("param");
kw_ptr = KW_DEF("ptr"); kw_ptr = KW_DEF("ptr");
@@ -203,7 +205,7 @@ void symtab_init(uint32_t capacity)
} }
attribute_list[ATTRIBUTE_INLINE] = kw_inline; 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_BIGENDIAN] = KW_DEF("bigendian");
attribute_list[ATTRIBUTE_LITTLEENDIAN] = KW_DEF("littleendian"); attribute_list[ATTRIBUTE_LITTLEENDIAN] = KW_DEF("littleendian");
attribute_list[ATTRIBUTE_NORETURN] = KW_DEF("noreturn"); attribute_list[ATTRIBUTE_NORETURN] = KW_DEF("noreturn");

View File

@@ -216,8 +216,6 @@ const char *token_type_to_string(TokenType type)
return "enum"; return "enum";
case TOKEN_EXTERN: case TOKEN_EXTERN:
return "extern"; return "extern";
case TOKEN_ERRTYPE:
return "errtype";
case TOKEN_FALSE: case TOKEN_FALSE:
return "false"; return "false";
case TOKEN_FOR: case TOKEN_FOR:
@@ -273,9 +271,6 @@ const char *token_type_to_string(TokenType type)
return "optnum"; return "optnum";
case TOKEN_ERRNUM: case TOKEN_ERRNUM:
return "errnum"; return "errnum";
case TOKEN_RESNUM:
return "resnum";
// Named types // Named types
case TOKEN_VOID: case TOKEN_VOID:

View File

@@ -1,4 +1,4 @@
errtype MyErr optenum MyErr
{ {
FOO FOO
} }

View File

@@ -1,4 +1,4 @@
errtype Error optenum Error
{} {}
define Foo1 = distinct Error; // #error: You cannot create a distinct type from an error define Foo1 = distinct Error; // #error: You cannot create a distinct type from an error

View File

@@ -1,4 +1,4 @@
errtype MyError optenum MyError
{ {
FOO, FOO,
BAR BAR

View File

@@ -1,17 +1,17 @@
module errors; module errors;
errtype TheError optenum TheError
{ {
A A
} }
errtype TheError2 optenum TheError2
{ {
A, A,
B B
} }
errtype TheError3 optenum TheError3
{ {
C, D C, D
} }

View File

@@ -2,7 +2,7 @@
module test; module test;
import std::io; import std::io;
errtype Foo optenum Foo
{ {
MY_VAL1, MY_VAL1,
MY_VAL2, MY_VAL2,

View File

@@ -6,7 +6,7 @@ struct Foo
int x, y; int x, y;
} }
errtype MyErr optenum MyErr
{ {
FOO FOO
} }

View File

@@ -1,7 +1,7 @@
module foo; module foo;
import std::io; import std::io;
errtype Foo optenum Foo
{ {
X, X,
Y, Y,
@@ -12,7 +12,7 @@ errtype Foo
} }
errtype Foob optenum Foob
{ {
X1, X1,
Y2 Y2

View File

@@ -2,7 +2,7 @@
module foo; module foo;
errtype Blurg optenum Blurg
{ {
Y Y
} }

View File

@@ -1,7 +1,7 @@
// #target: x64-darwin // #target: x64-darwin
extern fn int! err(); extern fn int! err();
errtype FooErr { QBERT } optenum FooErr { QBERT }
extern fn int printf(char* fmt, ...); extern fn int printf(char* fmt, ...);
fn void main() fn void main()

View File

@@ -13,7 +13,7 @@ fn int! tester()
return 222; return 222;
} }
errtype Foo optenum Foo
{ {
A A
} }

View File

@@ -1,7 +1,7 @@
extern fn int printf(char* fmt, ...); extern fn int printf(char* fmt, ...);
extern fn int! err(); extern fn int! err();
errtype FooErr optenum FooErr
{ {
X X
} }

View File

@@ -13,7 +13,7 @@ fn int! tester()
return 222; return 222;
} }
errtype Foo optenum Foo
{ {
A A
} }

View File

@@ -62,7 +62,7 @@ fn void test6()
define Baz = Foo; define Baz = Foo;
define Bar = distinct int; define Bar = distinct int;
errtype Err { FOO } optenum Err { FOO }
union Un { int x; } union Un { int x; }
enum MyEnum { BAR } enum MyEnum { BAR }

View File

@@ -1,4 +1,4 @@
errtype MyErr optenum MyErr
{ {
FOO FOO
} }

View File

@@ -2,7 +2,7 @@
module demo; module demo;
import std::io; import std::io;
errtype MathError optenum MathError
{ {
DIVISION_BY_ZERO DIVISION_BY_ZERO
} }

View File

@@ -1,7 +1,7 @@
int z; int z;
errtype MyError optenum MyError
{ {
FOO, FOO,
} }

View File

@@ -203,7 +203,7 @@ fn Type getMult(Type a)
} }
Type argh = 234; Type argh = 234;
errtype MyErr optenum MyErr
{ {
X, X,
Y Y

View File

@@ -3,7 +3,7 @@
module foo; module foo;
import std::io; import std::io;
errtype Foo optenum Foo
{ {
X X
} }

View File

@@ -135,7 +135,7 @@ fn void test_missing_no_cases(Baz x)
} }
} }
errtype MathError optenum MathError
{ {
DIVISION_BY_ZERO DIVISION_BY_ZERO
} }

View File

@@ -2,11 +2,11 @@ module mymodule;
extern fn void printf(char *, ...); extern fn void printf(char *, ...);
errtype HelloErr optenum HelloErr
{ {
FOO, FOO,
} }
errtype ByeErr optenum ByeErr
{ {
BAR, BAR,
BAZ BAZ

View File

@@ -1,4 +1,4 @@
errtype MyError optenum MyError
{ {
FOO FOO
} }