#include #include #include #include "ast.h" #include "cibic.tab.h" #define NEW_CNODE ((CNode *)malloc(sizeof(CNode))) CNode *ast_root; void cnode_reverse_chd(CNode *node) { static CNode *chdn[MAX_CHDN]; CNode *p; int n = 0; for (p = node->chd; p; p = p->next) cnode_reverse_chd(p); for (p = node->chd; p; p = p->next) chdn[n++] = p; if (n) { node->chd = chdn[--n]; for (; n; n--) chdn[n]->next = chdn[n - 1]; chdn[0]->next = NULL; } } CNode *cnode_create_ast(CNode *wrapped) { cnode_reverse_chd(wrapped); return wrapped; } CNode *cnode_create_nop(void) { CNode *nop = NEW_CNODE; nop->type = NOP; nop->next = nop->chd = NULL; return nop; } CNode *cnode_create_general(int type, int subtype, int pnum, va_list ap) { int i; CNode *exp = NEW_CNODE; exp->type = type; exp->rec.subtype = subtype; exp->next = exp->chd = NULL; exp->ext.type = NULL; exp->ext.offset = 0; for (i = 0; i < pnum; i++) { CNode *subexp = va_arg(ap, CNode*); #ifdef CIBIC_DEBUG assert(subexp->next == NULL); #endif subexp->next = exp->chd; exp->chd = subexp; } return exp; } CNode *cnode_list_append(CNode *list, CNode *tail) { if (list->type == NOP) { free(list); return tail; } tail->next = list; return tail; } CNode *cnode_create_identifier(char *val) { CNode *exp = NEW_CNODE; exp->type = ID; exp->chd = exp->next = NULL; exp->rec.strval = val; exp->ext.type = NULL; exp->ext.offset = 0; return exp; } CNode *cnode_create_int_const(int val) { /* TODO: overflow checking */ CNode *exp = NEW_CNODE; exp->type = INT; exp->chd = exp->next = NULL; exp->rec.intval = val; exp->ext.type = NULL; return exp; } CNode *cnode_create_char_const(char *val) { /* TODO: overflow checking */ CNode *exp = NEW_CNODE; exp->type = CHAR; exp->chd = exp->next = NULL; exp->rec.strval = val; exp->ext.type = NULL; return exp; } CNode *cnode_create_str_const(char *val) { CNode *exp = NEW_CNODE; exp->type = STR; exp->chd = exp->next = NULL; exp->rec.strval = val; exp->ext.type = NULL; return exp; } CNode *cnode_create_exp(int exp_type, int pnum, ...) { CNode *ret; va_list ap; va_start(ap, pnum); ret = cnode_create_general(EXP, exp_type, pnum, ap); va_end(ap); return ret; } CNode *cnode_create_type_spec(int spec_type, int pnum, ...) { CNode *ret; va_list ap; va_start(ap, pnum); ret = cnode_create_general(TYPE_SPEC, spec_type, pnum, ap); va_end(ap); return ret; } CNode *cnode_create_declr(int declr_type, int pnum, ...) { CNode *ret; va_list ap; va_start(ap, pnum); ret = cnode_create_general(DECLR, declr_type, pnum, ap); va_end(ap); return ret; } CNode *cnode_create_stmt(int stmt_type, int pnum, ...) { CNode *ret; va_list ap; va_start(ap, pnum); ret = cnode_create_general(STMT, stmt_type, pnum, ap); va_end(ap); return ret; } CNode *cnode_create_initr(int initr_type, CNode *body) { CNode *initr = NEW_CNODE; initr->type = INITR; initr->rec.subtype = initr_type; initr->chd = body; initr->next = NULL; initr->ext.type = NULL; return initr; } CNode *cnode_create_decl(CNode *type, CNode *init_declrs) { CNode *decl = NEW_CNODE; #ifdef CIBIC_DEBUG assert(type->next == NULL); assert(init_declrs->next == NULL); #endif decl->type = DECL; decl->next = NULL; decl->ext.type = NULL; decl->chd = init_declrs; init_declrs->next = type; return decl; } CNode *cnode_create_func(CNode *type, CNode *declr, CNode *stmt) { CNode *func = NEW_CNODE; #ifdef CIBIC_DEBUG assert(type->next == NULL); assert(declr->next == NULL); assert(stmt->next == NULL); #endif func->type = FUNC_DEF; func->next = NULL; func->ext.type = NULL; func->chd = stmt; stmt->next = declr; declr->next = type; return func; } CNode *cnode_create_init_declr(CNode *declr, CNode *initr) { CNode *init_declr = NEW_CNODE; #ifdef CIBIC_DEBUG assert(declr->next == NULL); assert(initr->next == NULL); #endif init_declr->type = INIT_DECLR; init_declr->next = NULL; init_declr->ext.type = NULL; init_declr->chd = initr; initr->next = declr; return init_declr; } CNode *cnode_create_struct_field(CNode *type_spec, CNode *declrs) { CNode *field = NEW_CNODE; #ifdef CIBIC_DEBUG assert(type_spec->next == NULL); assert(declrs->next == NULL); #endif field->type = FIELD; field->next = NULL; field->ext.type = NULL; field->chd = declrs; declrs->next = type_spec; return field; } CNode *cnode_create_plain_decl(CNode *type_spec, CNode *declr) { CNode *pdecl = NEW_CNODE; #ifdef CIBIC_DEBUG assert(type_spec->next == NULL); assert(declr->next == NULL); #endif pdecl->type = PLAIN_DECL; pdecl->next = NULL; pdecl->ext.type = NULL; pdecl->chd = declr; declr->next = type_spec; return pdecl; } CNode *cnode_create_typedef(CNode *type, CNode *declrs) { #ifdef CIBIC_DEBUG assert(type->next == NULL); assert(declrs->next == NULL); #endif CNode *def = NEW_CNODE; def->type = TYPEDEF; def->next = NULL; def->ext.type = NULL; def->chd = declrs; declrs->next = type; return def; } CNode *cnode_list_wrap(int type, CNode *list) { CNode *wlist = NEW_CNODE; wlist->type = type; wlist->next = NULL; wlist->ext.type = NULL; wlist->chd = list; return wlist; } char *cnode_debug_type_repr(CNode *ast) { static char buffer[MAX_DEBUG_PRINT_BUFF], abuff[MAX_DEBUG_PRINT_BUFF]; char *type, *aptr = abuff; switch (ast->type) { case PROG: type = "prog"; break; case FUNC_DEF: type = "func_def"; break; case DECLS: type = "prg_decls"; break; case FUNCS: type = "prg_funcs"; break; case DECL: type = "decl"; break; case INIT_DECLR: type = "init_declr"; break; case PLAIN_DECL: type = "p_decl"; break; case COMP_STMTS: type = "blk_stmts"; break; case COMP_DECLS: type = "blk_decls"; break; case DECLRS: type = "declrs"; break; case INIT_DECLRS: type = "init_declrs"; break; case ARGS: type = "args"; break; case PARAMS: type = "params"; break; case TYPEDEF: type = "typedef"; break; case ID: type = "id"; aptr += sprintf(abuff, "%s", ast->rec.strval); break; case INT: type = "int"; aptr += sprintf(abuff, "%d", ast->rec.intval); break; case CHAR: type = "char"; aptr += sprintf(abuff, "%s", ast->rec.strval); break; case STR: type = "str"; aptr += sprintf(abuff, "\"%s\"", ast->rec.strval); break; case FIELD: type = "field"; break; case FIELDS: type = "fields"; break; case NOP: type = "nop"; break; case EXP: case INITR: case TYPE_SPEC: case STMT: case DECLR: type = NULL; break; } if (ast->type == EXP) { switch (ast->rec.subtype) { case ',': type = ","; break; case '=': type = "="; break; case ASS_MUL: type = "*="; break; case ASS_DIV: type = "/="; break; case ASS_MOD: type = "%="; break; case ASS_ADD: type = "+="; break; case ASS_SUB: type = "-="; break; case ASS_SHL: type = "<<="; break; case ASS_SHR: type = ">>="; break; case ASS_AND: type = "&="; break; case ASS_XOR: type = "^="; break; case ASS_OR: type = "|="; break; case OPT_OR: type = "||"; break; case OPT_AND: type = "&&"; break; case '|': type = "|"; break; case '^': type = "^"; break; case '&': type = "&"; break; case OPT_EQ: type = "=="; break; case OPT_NE: type = "!="; break; case '<': type = "<"; break; case '>': type = ">"; break; case OPT_LE: type = "<="; break; case OPT_GE: type = ">="; break; case OPT_SHL: type = "<<"; break; case OPT_SHR: type = ">>"; break; case '+': type = "+"; break; case '-': type = "-"; break; case '*': type = "*"; break; case '/': type = "/"; break; case '%': type = "%"; break; case EXP_CAST: type = "cast"; break; case OPT_INC: type = "++"; break; case OPT_DEC: type = "--"; break; case '~': type = "~"; break; case '!': type = "!"; break; case KW_SIZEOF: type = "sizeof"; break; case EXP_POSTFIX: type = "postfix"; break; case POSTFIX_ARR: type = "arr"; break; case POSTFIX_CALL: type = "call"; break; case POSTFIX_DOT: type = "dot"; break; case POSTFIX_PTR: type = "ptr"; break; default: assert(0); } } else if (ast->type == TYPE_SPEC) { switch (ast->rec.subtype) { case KW_VOID: type = "void"; break; case KW_CHAR: type = "char"; break; case KW_INT: type = "int"; break; case KW_STRUCT: type = "struct"; break; case KW_UNION: type = "union"; break; case USER_TYPE: type = "user_type"; break; default: assert(0); } } else if (ast->type == DECLR) { switch (ast->rec.subtype) { case DECLR_FUNC: type = "func"; break; case DECLR_ARR: type = "arr"; break; case '*': type = "*"; break; case 0: type = "typename"; break; default: assert(0); } } else if (ast->type == STMT) { switch (ast->rec.subtype) { case STMT_EXP: type = "exp"; break; case STMT_COMP: type = "blk"; break; case STMT_IF: type = "if"; break; case STMT_WHILE: type = "while"; break; case STMT_FOR: type = "for"; break; case STMT_CONT: type = "cont"; break; case STMT_BREAK: type = "break"; break; case STMT_RET: type = "ret"; break; default: assert(0); } } else if (ast->type == INITR) { switch (ast->rec.subtype) { case INITR_NORM: type = "initr_n"; break; case INITR_ARR: type = "initr_a"; break; default: assert(0); } } else { if (type == NULL) puts(""); assert(type); } { char *head = buffer; head += sprintf(head, "%s", type); if (aptr != abuff) { *aptr = '\0'; head += sprintf(head, ":%s", abuff); } head += sprintf(head, "(%d:%d)", ast->loc.row, ast->loc.col); if (ast->ext.type) sprintf(head, "->(var:%lx type:%lx ic:%d cv:%ld off:%d)", (size_t)ast->ext.var, (size_t)ast->ext.type, ast->ext.is_const, ast->ext.const_val, ast->ext.offset); } return buffer; } void cnode_debug_print_plain(CNode *ast) { fprintf(stderr, "(%s", cnode_debug_type_repr(ast)); for (ast = ast->chd; ast; ast = ast->next) { fprintf(stderr, " "); cnode_debug_print_plain(ast); } fprintf(stderr, ")"); } void cnode_debug_print_fancy(CNode *ast, int lvl) { static int show[MAX_DEBUG_PRINT_LVL]; int i; show[lvl] = 1; for (i = 0; i < lvl - 1; i++) fprintf(stderr, "%c ", show[i] ? '|' : ' '); if (lvl) fprintf(stderr, "|____"); fprintf(stderr, "[%s]\n", cnode_debug_type_repr(ast)); for (ast = ast->chd; ast; ast = ast->next) { if (!ast->next) show[lvl] = 0; cnode_debug_print_fancy(ast, lvl + 1); } } void cnode_debug_print(CNode *ast, int fancy) { if (fancy) cnode_debug_print_fancy(ast, 0); else cnode_debug_print_plain(ast); puts(""); } CNode *cnode_add_loc(CNode *node, YYLTYPE loc) { node->loc.row = loc.first_line; node->loc.col = loc.first_column; return node; }