commit c0407a431c1c2d1fb1878f40fbecd61b357aa35c
parent bceb9b405ce4076fe27d316d9084d518f3eef971
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 19 Dec 2020 20:41:22 -0500
Initial riggings for gen
Diffstat:
6 files changed, 100 insertions(+), 3 deletions(-)
diff --git a/configure b/configure
@@ -5,6 +5,7 @@ eval ". $srcdir/config.sh"
harec() {
genrules harec \
src/check.c \
+ src/gen.c \
src/identifier.c \
src/lex.c \
src/main.c \
diff --git a/include/gen.h b/include/gen.h
@@ -0,0 +1,9 @@
+#ifndef HAREC_GEN_H
+#define HAREC_GEN_H
+#include <stdio.h>
+
+struct unit;
+
+void gen(const struct unit *unit, FILE *out);
+
+#endif
diff --git a/include/trace.h b/include/trace.h
@@ -6,6 +6,7 @@ enum trace_sys {
TR_PARSE,
TR_SCAN,
TR_CHECK,
+ TR_GEN,
TR_MAX,
};
diff --git a/src/gen.c b/src/gen.c
@@ -0,0 +1,84 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "check.h"
+#include "expr.h"
+#include "gen.h"
+#include "identifier.h"
+#include "trace.h"
+#include "types.h"
+
+struct gen_context {
+ FILE *out;
+ struct identifier *ns;
+};
+
+static char *
+ident_to_sym(const struct identifier *ident)
+{
+ if (ident->ns) {
+ char *ns = ident_to_sym(ident->ns);
+ if (!ns) {
+ return NULL;
+ }
+ int n = snprintf(NULL, 0, "%s.%s", ns, ident->name);
+ char *str = calloc(1, n + 1);
+ assert(str);
+ snprintf(str, n + 1, "%s.%s", ns, ident->name);
+ free(ns);
+ return str;
+ }
+ return strdup(ident->name);
+}
+
+static void
+gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
+{
+ assert(decl->type == DECL_FUNC);
+ const struct function_decl *func = &decl->func;
+ const struct type *fntype = func->type;
+ // TODO: All of these cases:
+ assert(func->flags == 0);
+ assert(func->symbol == NULL);
+ assert(fntype->func.result == &builtin_type_void);
+ assert(fntype->func.params == NULL);
+
+ char *sym = ident_to_sym(&decl->ident);
+ fprintf(ctx->out, "%sfunction $%s() {\n",
+ decl->exported ? "export " : "", sym);
+ fprintf(ctx->out, "\t# TODO: Emit function body\n");
+ fprintf(ctx->out, "}\n\n");
+ free(sym);
+}
+
+static void
+gen_decl(struct gen_context *ctx, const struct declaration *decl)
+{
+ switch (decl->type) {
+ case DECL_FUNC:
+ gen_function_decl(ctx, decl);
+ break;
+ case DECL_TYPE:
+ case DECL_GLOBAL:
+ case DECL_CONSTANT:
+ assert(0); // TODO
+ }
+}
+
+void
+gen(const struct unit *unit, FILE *out)
+{
+ struct gen_context ctx = {
+ .out = out,
+ .ns = unit->ns,
+ };
+ const struct declarations *decls = unit->declarations;
+ assert(decls); // At least one is required
+ trenter(TR_GEN, "gen");
+ while (decls) {
+ gen_decl(&ctx, &decls->decl);
+ decls = decls->next;
+ }
+ trleave(TR_GEN, NULL);
+}
diff --git a/src/main.c b/src/main.c
@@ -5,13 +5,13 @@
#include "check.h"
#include "lex.h"
#include "parse.h"
+#include "gen.h"
enum stage {
STAGE_LEX,
STAGE_PARSE,
STAGE_CHECK,
STAGE_GEN,
- STAGE_EMIT,
};
enum stage
@@ -27,8 +27,6 @@ parse_stage(const char *s)
return STAGE_CHECK;
} else if (strcmp(s, "gen") == 0) {
return STAGE_GEN;
- } else if (strcmp(s, "emit") == 0) {
- return STAGE_EMIT;
} else {
fprintf(stderr, "Unknown HA_STAGE value '%s'\n", s);
exit(1);
@@ -61,5 +59,7 @@ main(int argc, char *argv[])
if (stage == STAGE_CHECK) {
return 0;
}
+
+ gen(&unit, stdout);
return 0;
}
diff --git a/src/trace.c b/src/trace.c
@@ -10,6 +10,7 @@ static const char *sysname[] = {
[TR_PARSE] = "parse",
[TR_SCAN] = "scan",
[TR_CHECK] = "check",
+ [TR_GEN] = "gen",
};
static int depth[] = {
@@ -17,6 +18,7 @@ static int depth[] = {
[TR_PARSE] = 0,
[TR_SCAN] = 0,
[TR_CHECK] = 0,
+ [TR_GEN] = 0,
};
static void