aboutsummaryrefslogtreecommitdiff
path: root/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'node.c')
-rw-r--r--node.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/node.c b/node.c
new file mode 100644
index 0000000..b20c38e
--- /dev/null
+++ b/node.c
@@ -0,0 +1,140 @@
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <assert.h>
+#include "node.h"
+
+
+struct node* node_make_0(enum node_type type) {
+ struct node *node = malloc(sizeof(struct node));
+ node->type = type;
+ node->child1 = node->child2 = node->child3 = NULL;
+ node->rtype = NULL;
+ node->name = NULL;
+ node->value = 0;
+ return node;
+}
+
+struct node* node_make_1(enum node_type type, struct node *c1) {
+ struct node *node = node_make_0(type);
+ node->child1 = c1;
+ return node;
+}
+
+struct node* node_make_2(enum node_type type, struct node *c1, struct node *c2) {
+ struct node *node = node_make_1(type, c1);
+ node->child2 = c2;
+ return node;
+}
+
+struct node* node_make_3(enum node_type type, struct node *c1, struct node *c2, struct node *c3) {
+ struct node *node = node_make_2(type, c1, c2);
+ node->child3 = c3;
+ return node;
+}
+
+struct node* node_make_list_(struct node *first, ...) {
+ va_list ap;
+ va_start(ap, first);
+ struct node *cur = node_make_0(N_LIST_END);
+ struct node *root = node_make_2(N_LIST, first, cur);
+ struct node *next;
+ while ((next = va_arg(ap, struct node*))) {
+ cur->type = N_LIST;
+ cur->child1 = next;
+ cur->child2 = node_make_0(N_LIST_END);
+ cur = cur->child2;
+ }
+ return root;
+}
+
+int node_list_length(struct node *node) {
+ if (node->type == N_LIST_END) return 0;
+ assert(node->type == N_LIST);
+ return 1 + node_list_length(node->child2);
+}
+
+void node_delete_recursive(struct node *node) {
+ if (node->child1) node_delete_recursive(node->child1);
+ if (node->child2) node_delete_recursive(node->child2);
+ if (node->child3) node_delete_recursive(node->child3);
+ if (node->name) free(node->name);
+ free(node);
+}
+
+static void write_spaces(int num, FILE *f) {
+ for (int i = 0; i < num; i++) fputc(' ', f);
+}
+
+static const char* node_type_string(enum node_type type) {
+ switch (type) {
+ case N_LIST: return "N_LIST"; break;
+ case N_LIST_END: return "N_LIST_END"; break;
+ case N_BLOCK: return "N_BLOCK"; break;
+ case N_VAR_DECL_INIT: return "N_VAR_DECL_INIT"; break;
+ case N_VAR_DECL: return "N_VAR_DECL"; break;
+ case N_FUNC_DECL: return "N_FUNC_DECL"; break;
+ case N_NUM: return "N_NUM"; break;
+ case N_VAR: return "N_VAR"; break;
+ case N_IF: return "N_IF"; break;
+ case N_WHILE: return "N_WHILE"; break;
+ case N_RETURN: return "N_RETURN"; break;
+ case N_BINOP: return "N_BINOP"; break;
+ case N_UNOP: return "N_UNOP"; break;
+ case N_CALL: return "N_CALL"; break;
+ default: assert(false);
+ }
+}
+
+static const char* oper_string(enum operator oper) {
+ switch (oper) {
+ case OP_ADD: return "OP_ADD";
+ case OP_SUB: return "OP_SUB";
+ case OP_MUL: return "OP_MUL";
+ case OP_DIV: return "OP_DIV";
+ case OP_MOD: return "OP_MOD";
+ case OP_EQ: return "OP_EQ";
+ case OP_NEQ: return "OP_NEQ";
+ case OP_LT: return "OP_LT";
+ case OP_GT: return "OP_GT";
+ case OP_LEQ: return "OP_LEQ";
+ case OP_GEQ: return "OP_GEQ";
+ case OP_AND: return "OP_AND";
+ case OP_OR: return "OP_OR";
+ case OP_ASSIGN: return "OP_ASSIGN";
+ case OP_NEG: return "OP_NEG";
+ case OP_NOT: return "OP_NOT";
+ default: assert(false);
+ }
+}
+
+void node_print(const struct node *node, FILE *f, int indent) {
+ const char *t = node_type_string(node->type);
+ fprintf(f, "(%s", t);
+ if (node->rtype) {
+ fprintf(f, "[rtype=");
+ type_print(node->rtype, f);
+ fprintf(f, "]");
+ }
+ if (node->name) fprintf(f, "[name=%s]", node->name);
+ if (node->type == N_NUM) fprintf(f, "[value=%d]", node->value);
+ if (node->type == N_BINOP || node->type == N_UNOP) {
+ fprintf(f, "[oper=%s]", oper_string(node->oper));
+ }
+ if (node->child1) {
+ fprintf(f, "\n");
+ write_spaces(2 * (indent + 1), f);
+ node_print(node->child1, f, indent + 1);
+ }
+ if (node->child2) {
+ fprintf(f, "\n");
+ write_spaces(2 * (indent + 1), f);
+ node_print(node->child2, f, indent + 1);
+ }
+ if (node->child3) {
+ fprintf(f, "\n");
+ write_spaces(2 * (indent + 1), f);
+ node_print(node->child3, f, indent + 1);
+ }
+ fprintf(f, ")");
+}