From fc296ea5794b8465d5b2115588051ec7027d034b Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 10 Mar 2022 13:37:45 +0100 Subject: [PATCH] Extracted macro declaration body to separately allocated field. --- src/compiler/compiler_internal.h | 12 +++++-- src/compiler/parse_global.c | 56 +++++++++++++++++--------------- src/compiler/sema_decls.c | 10 +++--- src/compiler/sema_expr.c | 21 +++++++----- 4 files changed, 56 insertions(+), 43 deletions(-) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index bacf583ef..1dcce6182 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -85,6 +85,7 @@ typedef enum } ConstInitType; + typedef struct ConstInitializer_ { ConstInitType kind; @@ -293,6 +294,12 @@ struct TypeInfo_ }; }; +typedef struct BodyParam +{ + SourceSpan span; + const char *name; + Decl **params; +} BodyParam; typedef struct { @@ -503,8 +510,7 @@ typedef struct TypeInfoId rtype; // May be 0 AstId body; Decl **parameters; - Decl **body_parameters; - const char *block_parameter; + BodyParam *body_param; struct CompilationUnit_ *unit; struct AstDocDirective_ *docs; } MacroDecl; @@ -1260,7 +1266,7 @@ typedef struct Ast_ } Ast; //static_assert(sizeof(AstContinueBreakStmt) == 24, "Ooops"); -//static_assert(sizeof(Ast) == 56, "Oops"); +//static_assert(sizeof(Ast) == 56, "Not expected size on 64 bit"); typedef struct Module_ { diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 093b8d1f5..ec3b0b701 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -1179,27 +1179,29 @@ bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref */ static inline bool parse_parameter_list(ParseContext *c, Visibility parent_visibility, FunctionSignature *signature, bool is_interface) { + Decl **decls = NULL; CONSUME_OR_RET(TOKEN_LPAREN, false); - Decl **decls; if (!parse_parameters(c, parent_visibility, &decls)) return false; - if (vec_size(decls)) + CONSUME_OR_RET(TOKEN_RPAREN, false); + + signature->params = decls; + Decl *last = VECLAST(decls); + + // The last parameter may hold a vararg + if (last && last->var.vararg) { - Decl *last = VECLAST(decls); - if (last->var.vararg) + // Is it "(foo...)" (any) or "(int... foo)" (typed)? + if (last->var.type_info) { - if (!last->var.type_info) - { - vec_resize(decls, vec_size(decls) - 1); - signature->variadic = VARIADIC_RAW; - } - else - { - signature->variadic = last->var.vararg_implicit ? VARIADIC_ANY : VARIADIC_TYPED; - } + signature->variadic = last->var.vararg_implicit ? VARIADIC_ANY : VARIADIC_TYPED; + } + else + { + // Remove the last element if it's a raw variant, i.e. "(...)" + vec_pop(decls); + signature->variadic = VARIADIC_RAW; } } - signature->params = decls; - CONSUME_OR_RET(TOKEN_RPAREN, false); return true; } @@ -1429,12 +1431,12 @@ static inline Decl *parse_top_level_const_declaration(ParseContext *c, Visibilit * * trailing_block_parameter ::= '@' IDENT ( '(' parameters ')' )? */ -static bool parse_macro_arguments(ParseContext *c, Visibility visibility, Decl ***params_ref, Decl ***body_params, const char **block_parameter) +static bool parse_macro_arguments(ParseContext *c, Visibility visibility, Decl ***params_ref, BodyParam **body_param_ref) { CONSUME_OR_RET(TOKEN_LPAREN, false); *params_ref = NULL; - *body_params = NULL; - *block_parameter = NULL; + *body_param_ref = NULL; + // Parse the regular parameters. if (!parse_parameters(c, visibility, params_ref)) return false; @@ -1442,15 +1444,17 @@ static bool parse_macro_arguments(ParseContext *c, Visibility visibility, Decl * if (try_consume(c, TOKEN_EOS)) { // Consume '@' IDENT - TRY_CONSUME_OR_RET(TOKEN_AT, "Expected a trailing block with the format '@block(...).", false); - *block_parameter = symstr(c); + TRY_CONSUME_OR_RET(TOKEN_AT, "Expected an ending ')' or a block parameter on the format '@block(...).", false); + BodyParam *body_param = CALLOCS(BodyParam); + body_param->name = symstr(c); + body_param->span = c->span; if (!consume_ident(c, "variable name")) return false; if (try_consume(c, TOKEN_LPAREN)) { - if (!parse_parameters(c, visibility, body_params)) return false; + if (!parse_parameters(c, visibility, &body_param->params)) return false; CONSUME_OR_RET(TOKEN_RPAREN, false); } - // TODO use the body param. + *body_param_ref = body_param; } CONSUME_OR_RET(TOKEN_RPAREN, false); return true; @@ -1554,7 +1558,7 @@ static inline Decl *parse_define_type(ParseContext *c, Visibility visibility) */ static inline Decl *parse_define_ident(ParseContext *c, Visibility visibility) { - // 1. Store the beginning of the define. + // 1. Store the beginning of the "define". advance_and_verify(c, TOKEN_DEFINE); // 2. At this point we expect an ident or a const token. @@ -1574,7 +1578,7 @@ static inline Decl *parse_define_ident(ParseContext *c, Visibility visibility) return poisoned_decl; } - // 3. Set up the define. + // 3. Set up the "define". Decl *decl = decl_new(DECL_DEFINE, symstr(c), c->span, visibility); decl->define_decl.define_kind = DEFINE_IDENT_ALIAS; @@ -1772,10 +1776,8 @@ static inline Decl *parse_macro_declaration(ParseContext *c, Visibility visibili TypeInfoId *method_type_ref = &decl->macro_decl.type_parent; if (!parse_func_macro_header(c, true, rtype_ref, method_type_ref, &decl->name, &decl->span)) return poisoned_decl; - const char *block_parameter = NULL; - if (!parse_macro_arguments(c, visibility, &decl->macro_decl.parameters, &decl->macro_decl.body_parameters, &block_parameter)) return poisoned_decl; - decl->macro_decl.block_parameter = block_parameter; + if (!parse_macro_arguments(c, visibility, &decl->macro_decl.parameters, &decl->macro_decl.body_param)) return poisoned_decl; if (!parse_attributes(c, &decl->attributes)) return poisoned_decl; diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 719c2b156..9aa36ec84 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1757,12 +1757,14 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) if (!sema_check_no_duplicate_parameter(parameters, param, i, param_count)) return decl_poison(decl); param->resolve_status = RESOLVE_DONE; } - if (is_generic && vec_size(decl->macro_decl.body_parameters)) + BodyParam *body_param = decl->macro_decl.body_param; + if (is_generic && decl->macro_decl.body_param) { - SEMA_ERROR(decl->macro_decl.body_parameters[0], "Trailing block syntax is not allowed for generic functions."); + SEMA_ERROR(decl->macro_decl.body_param, "Trailing block syntax is not allowed for generic functions."); return decl_poison(decl); } - Decl **body_parameters = decl->macro_decl.body_parameters; + + Decl **body_parameters = body_param ? body_param->params : NULL; unsigned body_param_count = vec_size(body_parameters); for (unsigned i = 0; i < body_param_count; i++) { @@ -1796,7 +1798,7 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) param->resolve_status = RESOLVE_DONE; } bool pure = false; - if (!sema_analyse_doc_header(decl->macro_decl.docs, decl->macro_decl.parameters, decl->macro_decl.body_parameters, &pure)) return decl_poison(decl); + if (!sema_analyse_doc_header(decl->macro_decl.docs, decl->macro_decl.parameters, body_parameters, &pure)) return decl_poison(decl); if (decl->macro_decl.type_parent) { if (!sema_analyse_macro_method(context, decl)) return decl_poison(decl); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index acdd5b954..ef10aafd6 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1013,8 +1013,8 @@ static inline bool sema_expr_analyse_macro_expansion(SemaContext *context, Expr Expr *inner = expr->macro_expansion_expr.inner; if (inner->expr_kind == EXPR_IDENTIFIER) { - const char *body = context->current_macro ? context->current_macro->macro_decl.block_parameter : NULL; - if (body && !inner->identifier_expr.path && inner->identifier_expr.ident == body) + BodyParam *body_param = context->current_macro ? context->current_macro->macro_decl.body_param : NULL; + if (body_param && !inner->identifier_expr.path && inner->identifier_expr.ident == body_param->name) { expr->expr_kind = EXPR_MACRO_BODY_EXPANSION; expr->body_expansion_expr.ast = NULL; @@ -1802,7 +1802,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s Decl **params = decl_copy_list(decl->macro_decl.parameters); CalledDecl callee = { .macro = true, - .block_parameter = decl->macro_decl.block_parameter, + .block_parameter = decl->macro_decl.body_param ? decl->macro_decl.body_param->name : NULL, .params = params, .param_count = vec_size(params), .struct_var = struct_var @@ -1818,7 +1818,8 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s Decl **body_params = call_expr->call_expr.body_arguments; unsigned body_params_count = vec_size(body_params); - unsigned expected_body_params = vec_size(decl->macro_decl.body_parameters); + Decl **macro_body_params = decl->macro_decl.body_param ? decl->macro_decl.body_param->params : NULL; + unsigned expected_body_params = vec_size(macro_body_params); if (expected_body_params > body_params_count) { SEMA_ERROR(call_expr, "Not enough parameters for the macro body, expected %d.", expected_body_params); @@ -1831,7 +1832,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s } for (unsigned i = 0; i < expected_body_params; i++) { - Decl *body_param = decl->macro_decl.body_parameters[i]; + Decl *body_param = macro_body_params[i]; assert(body_param->resolve_status == RESOLVE_DONE); Decl *body_arg = call_expr->call_expr.body_arguments[i]; if (!body_arg->var.type_info) @@ -2096,7 +2097,8 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call) { Decl *macro = macro_context->current_macro; assert(macro); - assert(macro->macro_decl.block_parameter); + BodyParam *body_param = macro->macro_decl.body_param; + assert(body_param); ExprCall *call_expr = &call->call_expr; if (vec_size(call_expr->body_arguments)) @@ -2111,9 +2113,10 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call) } // Theoretically we could support named arguments, but that's unnecessary. unsigned expressions = vec_size(call_expr->arguments); - if (expressions != vec_size(macro->macro_decl.body_parameters)) + Decl **body_parameters = body_param->params; + if (expressions != vec_size(body_parameters)) { - SEMA_ERROR(call, "Expected %d parameter(s).", vec_size(macro->macro_decl.body_parameters)); + SEMA_ERROR(call, "Expected %d parameter(s).", vec_size(body_parameters)); return false; } Expr **args = call_expr->arguments; @@ -7026,7 +7029,7 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr) case EXPR_MACRO_BODY_EXPANSION: if (!expr->body_expansion_expr.ast) { - SEMA_ERROR(expr, "'@%s' must be followed by ().", context->current_macro->macro_decl.block_parameter); + SEMA_ERROR(expr, "'@%s' must be followed by ().", context->current_macro->macro_decl.body_param->name); return false; } break;