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