aboutsummaryrefslogtreecommitdiff
path: root/node.c
blob: f34061cb9d1aeee9a942a3e2942b83c3b7bb617f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#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);
}

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_RETURNV: return "N_RETURNV"; 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);
	}
}

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, ")");
}