mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Dev (#404)
Remove 'errtype' name and reduce Expr / TypeInfo memory footprint.
This commit is contained in:
committed by
GitHub
parent
069a2d40cb
commit
322d714305
@@ -2,7 +2,7 @@ module base64;
|
||||
// Based on the C2 version.
|
||||
|
||||
|
||||
errtype DecodingError
|
||||
optenum DecodingError
|
||||
{
|
||||
INVALID_CHARACTER
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
errtype MyErr
|
||||
optenum MyErr
|
||||
{
|
||||
FOO
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
errtype Error
|
||||
optenum Error
|
||||
{}
|
||||
|
||||
define Foo1 = distinct Error; // #error: You cannot create a distinct type from an error
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
errtype MyError
|
||||
optenum MyError
|
||||
{
|
||||
FOO,
|
||||
BAR
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
module errors;
|
||||
|
||||
errtype TheError
|
||||
optenum TheError
|
||||
{
|
||||
A
|
||||
}
|
||||
|
||||
errtype TheError2
|
||||
optenum TheError2
|
||||
{
|
||||
A,
|
||||
B
|
||||
}
|
||||
|
||||
errtype TheError3
|
||||
optenum TheError3
|
||||
{
|
||||
C, D
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
module test;
|
||||
import std::io;
|
||||
errtype Foo
|
||||
optenum Foo
|
||||
{
|
||||
MY_VAL1,
|
||||
MY_VAL2,
|
||||
|
||||
@@ -6,7 +6,7 @@ struct Foo
|
||||
int x, y;
|
||||
}
|
||||
|
||||
errtype MyErr
|
||||
optenum MyErr
|
||||
{
|
||||
FOO
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
module foo;
|
||||
|
||||
errtype Blurg
|
||||
optenum Blurg
|
||||
{
|
||||
Y
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -13,7 +13,7 @@ fn int! tester()
|
||||
return 222;
|
||||
}
|
||||
|
||||
errtype Foo
|
||||
optenum Foo
|
||||
{
|
||||
A
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
extern fn int printf(char* fmt, ...);
|
||||
|
||||
extern fn int! err();
|
||||
errtype FooErr
|
||||
optenum FooErr
|
||||
{
|
||||
X
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ fn int! tester()
|
||||
return 222;
|
||||
}
|
||||
|
||||
errtype Foo
|
||||
optenum Foo
|
||||
{
|
||||
A
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
errtype MyErr
|
||||
optenum MyErr
|
||||
{
|
||||
FOO
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
module demo;
|
||||
import std::io;
|
||||
|
||||
errtype MathError
|
||||
optenum MathError
|
||||
{
|
||||
DIVISION_BY_ZERO
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
int z;
|
||||
|
||||
errtype MyError
|
||||
optenum MyError
|
||||
{
|
||||
FOO,
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ fn Type getMult(Type a)
|
||||
}
|
||||
Type argh = 234;
|
||||
|
||||
errtype MyErr
|
||||
optenum MyErr
|
||||
{
|
||||
X,
|
||||
Y
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
module foo;
|
||||
import std::io;
|
||||
|
||||
errtype Foo
|
||||
optenum Foo
|
||||
{
|
||||
X
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ fn void test_missing_no_cases(Baz x)
|
||||
}
|
||||
}
|
||||
|
||||
errtype MathError
|
||||
optenum MathError
|
||||
{
|
||||
DIVISION_BY_ZERO
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ module mymodule;
|
||||
|
||||
extern fn void printf(char *, ...);
|
||||
|
||||
errtype HelloErr
|
||||
optenum HelloErr
|
||||
{
|
||||
FOO,
|
||||
}
|
||||
errtype ByeErr
|
||||
optenum ByeErr
|
||||
{
|
||||
BAR,
|
||||
BAZ
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
errtype MyError
|
||||
optenum MyError
|
||||
{
|
||||
FOO
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user