harec

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

commit 4216ecda9c9af2de3bee25aac828a5144c745846
parent 79770bae74563dc2b8f75602cf82bf5ce77aca1d
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed,  3 Feb 2021 14:26:15 -0500

Initial riggings for build tags and @test support

Diffstat:
Mconfigure | 1+
Minclude/check.h | 3+++
Ainclude/tags.h | 21+++++++++++++++++++++
Msrc/check.c | 13+++++++++++--
Msrc/main.c | 13++++++++++---
Msrc/mod.c | 2+-
Asrc/tags.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 112 insertions(+), 6 deletions(-)

diff --git a/configure b/configure @@ -19,6 +19,7 @@ harec() { src/qinstr.c \ src/qtype.c \ src/scope.c \ + src/tags.c \ src/trace.c \ src/type_store.c \ src/typedef.c \ diff --git a/include/check.h b/include/check.h @@ -5,6 +5,7 @@ #include "types.h" #include "type_store.h" +struct build_tags; struct expression; struct scope; @@ -12,6 +13,7 @@ struct context { struct type_store *store; const struct type *fntype; struct identifier *ns; + struct build_tags *tags; struct scope *unit; struct scope *scope; bool deferring; @@ -81,6 +83,7 @@ struct ast_expression; struct ast_unit; struct scope *check(struct type_store *ts, + struct build_tags *tags, const struct ast_unit *aunit, struct unit *unit); diff --git a/include/tags.h b/include/tags.h @@ -0,0 +1,21 @@ +#ifndef HARE_TAGS_H +#define HARE_TAGS_H +#include <stdbool.h> + +enum tag_mode { + TAG_INCLUDE, + TAG_EXCLUDE, +}; + +struct build_tags { + const char *tag; + enum tag_mode mode; + struct build_tags *next; +}; + +// Returns NULL on invalid syntax +struct build_tags *parse_tags(char *input); + +bool tag_enabled(struct build_tags *tags, const char *tag); + +#endif diff --git a/src/check.c b/src/check.c @@ -9,6 +9,7 @@ #include "expr.h" #include "mod.h" #include "scope.h" +#include "tags.h" #include "trace.h" #include "type_store.h" #include "types.h" @@ -1568,8 +1569,11 @@ check_function(struct context *ctx, } const struct ast_function_decl *afndecl = &adecl->function; - trenter(TR_CHECK, "function"); + if ((adecl->function.flags & FN_TEST) && !tag_enabled(ctx->tags, "test")) { + return NULL; + } + trenter(TR_CHECK, "function"); const struct ast_type fn_atype = { .storage = TYPE_STORAGE_FUNCTION, .flags = TYPE_CONST, @@ -1788,6 +1792,9 @@ scan_const(struct context *ctx, const struct ast_global_decl *decl) static void scan_function(struct context *ctx, const struct ast_function_decl *decl) { + if ((decl->flags & FN_TEST) && !tag_enabled(ctx->tags, "test")) { + return; + } trenter(TR_SCAN, "function"); const struct ast_type fn_atype = { .storage = TYPE_STORAGE_FUNCTION, @@ -1947,10 +1954,12 @@ load_import(struct ast_imports *import, } struct scope * -check(struct type_store *ts, const struct ast_unit *aunit, struct unit *unit) +check(struct type_store *ts, struct build_tags *tags, + const struct ast_unit *aunit, struct unit *unit) { struct context ctx = {0}; ctx.ns = unit->ns; + ctx.tags = tags; ctx.store = ts; ctx.store->check_context = &ctx; diff --git a/src/main.c b/src/main.c @@ -12,8 +12,9 @@ #include "lex.h" #include "parse.h" #include "qbe.h" -#include "typedef.h" +#include "tags.h" #include "type_store.h" +#include "typedef.h" #include "util.h" static void @@ -57,6 +58,7 @@ int main(int argc, char *argv[]) { char *output = NULL, *typedefs = NULL; + struct build_tags *tags = NULL; struct unit unit = {0}; struct lexer lexer; @@ -67,7 +69,12 @@ main(int argc, char *argv[]) output = optarg; break; case 'T': - assert(0); // TODO: Build tags + tags = parse_tags(optarg); + if (!tags) { + fprintf(stderr, "Invalid tags\n"); + return 1; + } + break; case 't': typedefs = optarg; break; @@ -131,7 +138,7 @@ main(int argc, char *argv[]) struct type_store ts = {0}; builtin_types_init(); - check(&ts, &aunit, &unit); + check(&ts, tags, &aunit, &unit); if (stage == STAGE_CHECK) { dump_unit(&unit); return 0; diff --git a/src/mod.c b/src/mod.c @@ -64,5 +64,5 @@ module_resolve(struct identifier *ident, struct type_store *store) // TODO: Free unused bits struct unit u = {0}; - return check(store, &aunit, &u); + return check(store, NULL, &aunit, &u); } diff --git a/src/tags.c b/src/tags.c @@ -0,0 +1,65 @@ +#include <stdbool.h> +#include <stddef.h> +#include <string.h> +#include "tags.h" +#include "util.h" + +struct build_tags * +parse_tags(char *input) +{ + struct build_tags *tag, **next = &tag; + while (input[0]) { + enum tag_mode mode; + switch (input[0]) { + case '+': + mode = TAG_INCLUDE; + break; + case '-': + mode = TAG_EXCLUDE; + break; + default: + return NULL; + } + ++input; + + char c; + char *tok = NULL; + char *p = strchr(input, '+'), *m = strchr(input, '-'); + if (p && !m) { + tok = p; + } else if (m && !p) { + tok = m; + } else if (m && p) { + tok = m < p ? m : p; + } + + if (tok) { + c = *tok; + *tok = '\0'; + } + + tag = *next = xcalloc(1, sizeof(struct build_tags)); + tag->tag = strdup(input); + tag->mode = mode; + next = &tag->next; + + if (tok) { + *tok = c; + } + + input += strlen(tag->tag); + } + return tag; +} + +bool +tag_enabled(struct build_tags *tags, const char *tag) +{ + while (tags) { + if (strcmp(tags->tag, tag) == 0) { + return tags->mode == TAG_INCLUDE; + } + tags = tags->next; + } + return false; +}