harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit dfe1a0078939de5a486a7730ef423061594fa03d
parent b83bbfd0855cc65db0b7b8fd8f03a1a85e4b8a07
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 24 Dec 2020 12:26:46 -0500

Implement prototypes

Diffstat:
Minclude/check.h | 2+-
Msrc/check.c | 36+++++++++++++++++++++++++-----------
Msrc/gen.c | 2+-
Msrc/parse.c | 14++++++++++++--
4 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/include/check.h b/include/check.h @@ -38,7 +38,7 @@ struct declaration { }; struct declarations { - struct declaration decl; + struct declaration *decl; struct declarations *next; }; diff --git a/src/check.c b/src/check.c @@ -421,11 +421,14 @@ check_expression(struct context *ctx, trleave(TR_CHECK, NULL); } -static void +static struct declaration * check_function(struct context *ctx, - const struct ast_decl *adecl, - struct declaration *decl) + const struct ast_decl *adecl) { + if (!adecl->function.body) { + return NULL; // Prototype + } + const struct ast_function_decl *afndecl = &adecl->function; trenter(TR_CHECK, "function"); assert(!afndecl->symbol); // TODO @@ -438,6 +441,8 @@ check_function(struct context *ctx, const struct type *fntype = type_store_lookup_atype( &ctx->store, &fn_atype); assert(fntype); // Invariant + + struct declaration *decl = calloc(1, sizeof(struct declaration)); decl->type = DECL_FUNC; decl->func.type = fntype; // TODO: Rewrite ident to be a member of the unit's namespace @@ -473,10 +478,10 @@ check_function(struct context *ctx, "%s function cannot be exported", flags); } - // TODO: Add declaration to unit scope - + scope_insert(ctx->unit, &decl->ident, decl->func.type); scope_pop(&ctx->scope, TR_CHECK); trleave(TR_CHECK, NULL); + return decl; } static void @@ -486,14 +491,11 @@ check_declarations(struct context *ctx, { trenter(TR_CHECK, "declarations"); while (adecls) { - struct declarations *decls = *next = - calloc(1, sizeof(struct declarations)); - struct declaration *decl = &decls->decl; + struct declaration *decl; const struct ast_decl *adecl = &adecls->decl; - decl->exported = adecl->exported; switch (adecl->decl_type) { case AST_DECL_FUNC: - check_function(ctx, adecl, decl); + decl = check_function(ctx, adecl); break; case AST_DECL_TYPE: assert(0); // TODO @@ -502,8 +504,16 @@ check_declarations(struct context *ctx, case AST_DECL_CONST: assert(0); // TODO } + + if (decl) { + struct declarations *decls = *next = + calloc(1, sizeof(struct declarations)); + decl->exported = adecl->exported; + decls->decl = decl; + next = &decls->next; + } + adecls = adecls->next; - next = &decls->next; } trleave(TR_CHECK, NULL); } @@ -524,6 +534,10 @@ scan_function(struct context *ctx, const struct ast_function_decl *decl) char buf[1024]; identifier_unparse_static(&decl->ident, buf, sizeof(buf)); trleave(TR_SCAN, "func %s", buf); + + if (!decl->body) { + scope_insert(ctx->unit, &decl->ident, fntype); + } } static void diff --git a/src/gen.c b/src/gen.c @@ -574,7 +574,7 @@ gen(const struct unit *unit, struct qbe_program *out) assert(decls); // At least one is required trenter(TR_GEN, "gen"); while (decls) { - gen_decl(&ctx, &decls->decl); + gen_decl(&ctx, decls->decl); decls = decls->next; } trleave(TR_GEN, NULL); diff --git a/src/parse.c b/src/parse.c @@ -1175,8 +1175,18 @@ parse_fn_decl(struct parser *par, struct ast_function_decl *decl) want(par, T_FN, NULL); parse_identifier(par, &decl->ident); parse_prototype(par, &decl->prototype); - want(par, T_EQUAL, NULL); - decl->body = parse_compound_expression(par); + + switch (lex(par->lex, &tok)) { + case T_EQUAL: + decl->body = parse_compound_expression(par); + break; + case T_SEMICOLON: + unlex(par->lex, &tok); + decl->body = NULL; // Prototype + break; + default: + synassert(false, &tok, T_EQUAL, T_SEMICOLON, T_EOF); + } char symbol[1024], buf[1024]; if (decl->symbol) {