Extracted macro declaration body to separately allocated field.

This commit is contained in:
Christoffer Lerno
2022-03-10 13:37:45 +01:00
committed by Christoffer Lerno
parent 4258fe4d01
commit fc296ea579
4 changed files with 56 additions and 43 deletions

View File

@@ -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_
{

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;