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; } }