commit 22f021f221c1d7ae2f5f62f4a2b45a71f18ca48b
parent 0b334159ce567557c9b6fd2ad702d633f57d01a0
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 27 Jan 2021 15:44:41 -0500
Add 'dump', temporary debug module
Diffstat:
4 files changed, 450 insertions(+), 0 deletions(-)
diff --git a/configure b/configure
@@ -6,6 +6,7 @@ eval ". $srcdir/config.sh"
harec() {
genrules harec \
src/check.c \
+ src/dump.c \
src/emit.c \
src/eval.c \
src/gen.c \
diff --git a/include/dump.h b/include/dump.h
@@ -0,0 +1,8 @@
+#ifndef HAREC_DUMP_H
+#define HAREC_DUMP_H
+
+struct unit;
+
+void dump_unit(struct unit *unit);
+
+#endif
diff --git a/src/dump.c b/src/dump.c
@@ -0,0 +1,439 @@
+// XXX: This whole file should be removed once it ceases to be useful
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "check.h"
+#include "dump.h"
+#include "expr.h"
+#include "identifier.h"
+#include "scope.h"
+#include "types.h"
+
+static void
+indent(int depth)
+{
+ for (int i = 0; i < depth; ++i) {
+ fprintf(stderr, " ");
+ }
+}
+
+static const char *
+storage_to_suffix(enum type_storage storage)
+{
+ switch (storage) {
+ case TYPE_STORAGE_F32:
+ return "f32";
+ case TYPE_STORAGE_F64:
+ return "f64";
+ case TYPE_STORAGE_I16:
+ return "i16";
+ case TYPE_STORAGE_I32:
+ return "i32";
+ case TYPE_STORAGE_I64:
+ return "i64";
+ case TYPE_STORAGE_I8:
+ return "i8";
+ case TYPE_STORAGE_INT:
+ return "i";
+ case TYPE_STORAGE_SIZE:
+ return "z";
+ case TYPE_STORAGE_U16:
+ return "u16";
+ case TYPE_STORAGE_U32:
+ return "u32";
+ case TYPE_STORAGE_U64:
+ return "u64";
+ case TYPE_STORAGE_U8:
+ return "u8";
+ case TYPE_STORAGE_UINT:
+ return "u";
+ case TYPE_STORAGE_UINTPTR:
+ return "u64: uintptr";
+ default:
+ assert(0);
+ }
+}
+
+static void
+dump_const(const struct expression *expr)
+{
+ assert(expr->type == EXPR_CONSTANT);
+ const union expression_constant *val = &expr->constant;
+ switch (expr->result->storage) {
+ case TYPE_STORAGE_BOOL:
+ fprintf(stderr, "%s", val->bval ? "false" : "true");
+ break;
+ case TYPE_STORAGE_F32:
+ case TYPE_STORAGE_F64:
+ fprintf(stderr, "%lf%s", val->fval,
+ storage_to_suffix(expr->result->storage));
+ break;
+ case TYPE_STORAGE_I16:
+ case TYPE_STORAGE_I32:
+ case TYPE_STORAGE_I64:
+ case TYPE_STORAGE_I8:
+ case TYPE_STORAGE_INT:
+ fprintf(stderr, "%ld%s", val->ival,
+ storage_to_suffix(expr->result->storage));
+ break;
+ case TYPE_STORAGE_NULL:
+ fprintf(stderr, "null");
+ break;
+ case TYPE_STORAGE_SIZE:
+ case TYPE_STORAGE_U16:
+ case TYPE_STORAGE_U32:
+ case TYPE_STORAGE_U64:
+ case TYPE_STORAGE_U8:
+ case TYPE_STORAGE_UINT:
+ case TYPE_STORAGE_UINTPTR:
+ fprintf(stderr, "%lu%s", val->uval,
+ storage_to_suffix(expr->result->storage));
+ break;
+ case TYPE_STORAGE_VOID:
+ fprintf(stderr, "void");
+ break;
+ case TYPE_STORAGE_RUNE:
+ assert(0); // TODO
+ case TYPE_STORAGE_ALIAS:
+ fprintf(stderr, "(const) %s",
+ identifier_unparse(&expr->result->alias.ident));
+ break;
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_ENUM:
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_UNION:
+ assert(0); // TODO
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_FUNCTION:
+ case TYPE_STORAGE_POINTER:
+ case TYPE_STORAGE_TAGGED_UNION:
+ assert(0); // Invariant
+ }
+}
+
+static void
+dump_type(const struct type *type)
+{
+ if (type->flags & TYPE_CONST) {
+ fprintf(stderr, "const ");
+ }
+
+ char *ident;
+ switch (type->storage) {
+ case TYPE_STORAGE_BOOL:
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_ENUM:
+ case TYPE_STORAGE_F32:
+ case TYPE_STORAGE_F64:
+ case TYPE_STORAGE_I16:
+ case TYPE_STORAGE_I32:
+ case TYPE_STORAGE_I64:
+ case TYPE_STORAGE_I8:
+ case TYPE_STORAGE_INT:
+ case TYPE_STORAGE_NULL:
+ case TYPE_STORAGE_RUNE:
+ case TYPE_STORAGE_SIZE:
+ case TYPE_STORAGE_U16:
+ case TYPE_STORAGE_U32:
+ case TYPE_STORAGE_U64:
+ case TYPE_STORAGE_U8:
+ case TYPE_STORAGE_UINT:
+ case TYPE_STORAGE_UINTPTR:
+ case TYPE_STORAGE_VOID:
+ case TYPE_STORAGE_STRING:
+ fprintf(stderr, "%s", type_storage_unparse(type->storage));
+ break;
+ case TYPE_STORAGE_POINTER:
+ fprintf(stderr, "%s*", type->pointer.flags & PTR_NULLABLE
+ ? "nullable " : "");
+ dump_type(type->pointer.referent);
+ break;
+ case TYPE_STORAGE_ARRAY:
+ if (type->array.length == SIZE_UNDEFINED) {
+ fprintf(stderr, "[*]");
+ } else {
+ fprintf(stderr, "[%zd]", type->array.length);
+ }
+ dump_type(type->array.members);
+ break;
+ case TYPE_STORAGE_SLICE:
+ fprintf(stderr, "[]");
+ dump_type(type->array.members);
+ break;
+ case TYPE_STORAGE_ALIAS:
+ ident = identifier_unparse(&type->alias.ident);
+ fprintf(stderr, "%s", ident);
+ free(ident);
+ break;
+ case TYPE_STORAGE_TAGGED_UNION:
+ fprintf(stderr, "(");
+ for (const struct type_tagged_union *tu = &type->tagged;
+ tu; tu = tu->next) {
+ dump_type(tu->type);
+ if (tu->next) {
+ fprintf(stderr, " | ");
+ }
+ }
+ fprintf(stderr, ")");
+ break;
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_UNION:
+ assert(type->struct_union.c_compat); // TODO
+ fprintf(stderr, "%s { ", type->storage == TYPE_STORAGE_STRUCT
+ ? "struct" : "union");
+ for (const struct struct_field *f = type->struct_union.fields;
+ f; f = f->next) {
+ fprintf(stderr, "%s: ", f->name);
+ dump_type(f->type);
+ fprintf(stderr, ", ");
+ }
+ fprintf(stderr, "}");
+ break;
+ case TYPE_STORAGE_FUNCTION:
+ if (type->func.flags & FN_NORETURN) {
+ fprintf(stderr, "@noreturn ");
+ }
+ fprintf(stderr, "fn(");
+ for (const struct type_func_param *param = type->func.params;
+ param; param = param->next) {
+ if (param->next) {
+ dump_type(param->type);
+ fprintf(stderr, ", ");
+ } else if (type->func.variadism == VARIADISM_HARE) {
+ dump_type(param->type->array.members);
+ fprintf(stderr, "...");
+ } else if (type->func.variadism == VARIADISM_C) {
+ dump_type(param->type);
+ fprintf(stderr, ", ...");
+ }
+ }
+ fprintf(stderr, ") ");
+ dump_type(type->func.result);
+ break;
+ }
+}
+
+static void
+dump_scope_obj(const struct scope_object *obj)
+{
+ switch (obj->otype) {
+ case O_BIND:
+ fprintf(stderr, "{binding ");
+ break;
+ case O_CONST:
+ fprintf(stderr, "{constant ");
+ break;
+ case O_DECL:
+ fprintf(stderr, "{declaration ");
+ break;
+ case O_TYPE:
+ fprintf(stderr, "{type ");
+ break;
+ }
+ fprintf(stderr, "ident %s; name %s ",
+ identifier_unparse(&obj->ident),
+ identifier_unparse(&obj->name));
+ dump_type(obj->type);
+ fprintf(stderr, "}");
+}
+
+static void
+dump_expr(const struct expression *expr, int depth)
+{
+ fprintf(stderr, "expr ");
+ dump_type(expr->result);
+ fprintf(stderr, " <- ");
+ switch (expr->type) {
+ case EXPR_ACCESS:
+ fprintf(stderr, "access ");
+ switch (expr->access.type) {
+ case ACCESS_IDENTIFIER:
+ fprintf(stderr, "object ");
+ dump_scope_obj(expr->access.object);
+ break;
+ case ACCESS_INDEX:
+ assert(0);
+ case ACCESS_FIELD:
+ assert(0);
+ }
+ break;
+ case EXPR_ALLOC:
+ fprintf(stderr, "alloc");
+ break;
+ case EXPR_ASSERT:
+ fprintf(stderr, "assert");
+ break;
+ case EXPR_ASSIGN:
+ fprintf(stderr, "assign [indirect: %d; op: %d] ",
+ expr->assign.indirect,
+ expr->assign.op);
+ dump_expr(expr->assign.object, depth);
+ fprintf(stderr, " <- ");
+ dump_expr(expr->assign.value, depth);
+ break;
+ case EXPR_BINARITHM:
+ fprintf(stderr, "binarithm");
+ break;
+ case EXPR_BINDING:
+ fprintf(stderr, "binding\n");
+ indent(depth + 1);
+ for (const struct expression_binding *b = &expr->binding;
+ b; b = b->next) {
+ dump_scope_obj(b->object);
+ fprintf(stderr, "\n");
+ indent(depth + 2);
+ fprintf(stderr, "= ");
+ dump_expr(b->initializer, depth + 2);
+ if (b->next) {
+ fprintf(stderr, "\n");
+ indent(depth + 1);
+ }
+ }
+ break;
+ case EXPR_BREAK:
+ fprintf(stderr, "break");
+ break;
+ case EXPR_CALL:
+ fprintf(stderr, "call");
+ break;
+ case EXPR_CAST:
+ switch (expr->cast.kind) {
+ case C_CAST:
+ fprintf(stderr, "cast ::\n");
+ indent(depth + 1);
+ dump_expr(expr->cast.value, depth + 1);
+ break;
+ case C_ASSERTION:
+ fprintf(stderr, "type assert :: \n");
+ indent(depth + 1);
+ dump_expr(expr->cast.value, depth + 1);
+ break;
+ case C_TEST:
+ fprintf(stderr, "test ");
+ dump_type(expr->cast.secondary);
+ fprintf(stderr, " :: \n");
+ indent(depth + 1);
+ dump_expr(expr->cast.value, depth + 1);
+ break;
+ }
+ break;
+ case EXPR_CONSTANT:
+ dump_const(expr);
+ break;
+ case EXPR_CONTINUE:
+ fprintf(stderr, "continue");
+ break;
+ case EXPR_DEFER:
+ fprintf(stderr, "defer");
+ break;
+ case EXPR_FOR:
+ fprintf(stderr, "for");
+ break;
+ case EXPR_IF:
+ fprintf(stderr, "if");
+ break;
+ case EXPR_LIST:
+ fprintf(stderr, "expression list\n");
+ indent(depth + 1);
+ for (const struct expressions *exprs = &expr->list.exprs;
+ exprs; exprs = exprs->next) {
+ dump_expr(exprs->expr, depth + 1);
+ if (exprs->next) {
+ fprintf(stderr, "\n");
+ indent(depth + 1);
+ }
+ }
+ break;
+ case EXPR_MATCH:
+ fprintf(stderr, "match");
+ break;
+ case EXPR_MEASURE:
+ fprintf(stderr, "measure");
+ break;
+ case EXPR_RETURN:
+ fprintf(stderr, "return");
+ break;
+ case EXPR_SLICE:
+ fprintf(stderr, "slice");
+ break;
+ case EXPR_STRUCT:
+ fprintf(stderr, "struct");
+ break;
+ case EXPR_SWITCH:
+ fprintf(stderr, "switch");
+ break;
+ case EXPR_UNARITHM:
+ fprintf(stderr, "unarithm");
+ break;
+ }
+}
+
+static const char *
+decl_type_str(enum declaration_type t)
+{
+ switch (t) {
+ case DECL_CONST:
+ return "constant";
+ case DECL_FUNC:
+ return "function";
+ case DECL_GLOBAL:
+ return "global";
+ case DECL_TYPE:
+ return "type";
+ }
+ assert(0);
+}
+
+static void
+dump_decl(struct declaration *decl)
+{
+ fprintf(stderr, "%-10s %-20s [export: %d] ",
+ decl_type_str(decl->type),
+ identifier_unparse(&decl->ident),
+ decl->exported);
+ const struct type *fntype;
+ switch (decl->type) {
+ case DECL_CONST:
+ dump_type(decl->constant.type);
+ fprintf(stderr, " = ");
+ dump_const(decl->constant.value);
+ break;
+ case DECL_FUNC:
+ fntype = decl->func.type;
+ if (fntype->func.flags & FN_NORETURN) {
+ fprintf(stderr, "@noreturn ");
+ }
+ fprintf(stderr, "(");
+ for (struct type_func_param *param = fntype->func.params;
+ param; param = param->next) {
+ dump_type(param->type);
+ if (param->next) {
+ fprintf(stderr, ", ");
+ }
+ }
+ fprintf(stderr, ") ");
+ dump_type(fntype->func.result);
+ fprintf(stderr, " = ");
+ dump_expr(decl->func.body, 0);
+ break;
+ case DECL_GLOBAL:
+ dump_type(decl->global.type);
+ fprintf(stderr, " = ");
+ dump_const(decl->global.value);
+ break;
+ case DECL_TYPE:
+ dump_type(decl->_type);
+ break;
+ }
+ fprintf(stderr, "\n");
+}
+
+void
+dump_unit(struct unit *unit)
+{
+ for (struct declarations *d = unit->declarations; d; d = d->next) {
+ dump_decl(d->decl);
+ }
+}
diff --git a/src/main.c b/src/main.c
@@ -6,6 +6,7 @@
#include <unistd.h>
#include "ast.h"
#include "check.h"
+#include "dump.h"
#include "emit.h"
#include "gen.h"
#include "lex.h"
@@ -132,6 +133,7 @@ main(int argc, char *argv[])
builtin_types_init();
check(&ts, &aunit, &unit);
if (stage == STAGE_CHECK) {
+ dump_unit(&unit);
return 0;
}