global FILE *global_output_file; #define lex_print(...) fprintf(global_output_file, __VA_ARGS__) #define lex_new_line() lex_print("\n") function void tokens_print(Tokens tokens){ lex_print("\n== Token count = %d\n", (S32)tokens.len); for(Token *t = tokens.tokens; t != tokens.tokens + tokens.len; t++){ lex_print("%s \"%.*s\"\n", token_kind_string[t->kind].str, (S32)t->len, t->str); } } function void token_print(Token *token){ lex_print("%.*s", (S32)token->len, token->str); } function Type *type_pointer(Parser *p, Type *base); function void expr_print(Expr *expr); function void type_print(Type *type){ switch(type->kind) { case TK_S64: case TK_U64: case TK_SizeU: case TK_Void: { lex_print("%s", type_kind_string[type->kind].str); } break; case TK_Pointer:{ type_print(type->pointer); lex_print("*"); } break; case TK_Array:{ type_print(type->array.pointer); lex_print("["); expr_print(type->array.size); lex_print("]"); } break; default: {invalid_codepath;} break; } } function void type_test(Parser *p){ Type *t = type_pointer(p, type_s64); t = type_pointer(p, t); type_print(t); } function void expr_print(Expr *expr){ switch(expr->kind) { case EK_Atom: { token_print(expr->token); } break; case EK_Binary:{ lex_print("("); expr_print(expr->binary.left); token_print(expr->token); expr_print(expr->binary.right); lex_print(")"); } break; case EK_Unary:{ lex_print("("); token_print(expr->token); expr_print(expr->unary.expr); lex_print(")"); } break; case EK_Ternary:{ lex_print("("); expr_print(expr->ternary.cond); lex_print("?"); expr_print(expr->ternary.on_true); lex_print(":"); expr_print(expr->ternary.on_false); lex_print(")"); } break; case EK_List:{ lex_print("("); for(Expr *n = expr->list.first; n; n=n->next){ expr_print(n); if(n!=expr->list.last) lex_print(","); } lex_print(")"); }break; case EK_Cast:{ lex_print("("); lex_print("("); type_print(expr->cast.type); lex_print(")"); expr_print(expr->cast.expr); lex_print(")"); } break; case EK_Index:{ expr_print(expr->index.atom); lex_print("["); expr_print(expr->index.index); lex_print("]"); }break; case EK_Call:{ expr_print(expr->call.atom); expr_print(expr->call.list); }break; default: {invalid_codepath;} break; } } function void decl_print(Decl *decl){ switch(decl->kind) { case DK_Enum: { lex_print("enum %s{\n", decl->name.s.str); for(Decl_Enum_Child *n = decl->enum_val.first; n; n=n->next){ lex_print(" "); token_print(n->token); if(n->expr){ lex_print(" = "); expr_print(n->expr); } lex_print(","); lex_new_line(); } lex_print("};\n"); } break; default: {invalid_codepath;} break; } }