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 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 print_indent(S64 indent){ for(S64 i = 0; i < indent; i++){ lex_print(" "); } } function AST_Node * ast_get_basis_type(AST_Node *node){ switch(node->kind) { case AK_Struct: case AK_Union: case AK_Enum: case AK_BaseType:{return node;} break; case AK_Function:{return node;} break; case AK_Typedef:{return node->typedef_type;} break; case AK_Array: case AK_Pointer:{return ast_get_basis_type(node->pointer);} break; default: invalid_codepath; } return 0; } function void ast_print_pointers(AST_Node *node){ if(node->kind == AK_Pointer){ lex_print("*"); ast_print_pointers(node->pointer); } else if(node->kind == AK_Array){ ast_print_pointers(node->pointer); } } function void ast_print_arrays(AST_Node *node){ if(node->kind == AK_Pointer){ ast_print_arrays(node->pointer); } else if(node->kind == AK_Array){ lex_print("["); expr_print(node->expr); lex_print("]"); ast_print_arrays(node->pointer); } } function void ast_print_var(AST_Node *node); function void ast_print_func_params(AST_Node *node){ for(AST_Node *n = node->first_child; n; n=n->next){ ast_print_var(n); if(n != node->last_child) lex_print(", "); } } function void ast_print_var(AST_Node *node){ AST_Node *basis_type = ast_get_basis_type(node->variable_type); if(basis_type->kind == AK_Function){ lex_print("%s (*%s)(", basis_type->func_return_type->name.s.str, node->name.s.str); ast_print_func_params(basis_type); lex_print(")"); } else{ lex_print("%s ", basis_type->name.s.str); ast_print_pointers(node->variable_type); lex_print("%s", node->name.s.str); ast_print_arrays(node->variable_type); } if(node->expr){ lex_print(" = "); expr_print(node->expr); } } function void ast__print(AST_Node *node, S64 indent){ switch(node->kind){ case AK_List:{ for(AST_Node *n = node->first_child; n; n=n->next){ ast__print(n, indent); lex_print("\n"); } } break; case AK_Union: case AK_Struct:{ const char *type = node->kind == AK_Struct ? "struct":"union"; if(indent == 0) lex_print("typedef %s %s %s;\n", type, node->name.s.str, node->name.s.str); lex_print("%s %s{\n", type, indent == 0 ? node->name.s.str:(U8 *)""); for(AST_Node *n = node->first_child; n; n=n->next){ ast__print(n, indent+2); lex_print("\n"); } lex_print("}"); lex_print("%s;\n", indent == 0 ? (U8 *)"":node->name.s.str?node->name.s.str:(U8*)""); } break; case AK_Variable:{ if(indent == 0) lex_print("global "); ast_print_var(node); lex_print(";"); } break; case AK_Typedef:{ lex_print("typedef "); lex_print("%s;", node->name.s.str); } break; case AK_Enum:{ print_indent(indent); lex_print("enum %s{\n", node->name.s.str); for(AST_Node *n = node->first_child; n; n=n->next){ print_indent(indent+2); lex_print("%s", n->name.s.str); if(n->expr){ lex_print(" = "); expr_print(n->expr); } lex_print(",\n"); } print_indent(indent); lex_print("}\n"); } break; default: invalid_codepath; } } function void ast_print(AST_Node *node){ ast__print(node, 0); }