/* * Printer output is rigid and deterministic so golden tests can diff. */ #include "ww.h" #include Node * newnode(Arena *a, Nkind k, Pos p) { Node *n = amalloc(a, sizeof *n); n->kind = k; n->pos = p; return n; } static const char * nkname(Nkind k) { switch (k) { case N_NONE: return "none"; case N_INTLIT: return "int"; case N_FLOATLIT: return "float"; case N_STRLIT: return "str"; case N_RUNELIT: return "rune"; case N_TRUE: return "true"; case N_FALSE: return "false"; case N_NIL: return "nil"; case N_IDENT: return "id"; case N_BIN: return "bin"; case N_UN: return "un"; case N_CALL: return "call"; case N_INDEX: return "index"; case N_DOT: return "dot"; case N_CAST: return "cast"; case N_STRUCTLIT: return "structlit"; case N_ARRLIT: return "arrlit"; case N_FIELD: return "field"; case N_ASSIGN: return "assign"; case N_ALLOC: return "alloc"; case N_FREE: return "free"; case N_RECV: return "recv"; case N_SLICE: return "slice"; case N_SPREAD: return "spread"; case N_BLOCK: return "block"; case N_EXPRSTMT: return "exprstmt"; case N_LET: return "let"; case N_RETURN: return "return"; case N_IF: return "if"; case N_FOR: return "for"; case N_FORRANGE: return "forrange"; case N_DEFER: return "defer"; case N_BREAK: return "break"; case N_CONTINUE: return "continue"; case N_SWITCH: return "switch"; case N_CASE: return "case"; case N_FILE: return "file"; case N_USE: return "use"; case N_DEF: return "def"; case N_TYPEDECL: return "typedecl"; case N_FNDECL: return "fn"; case N_PARAM: return "param"; case N_TNAME: return "tname"; case N_TPTR: return "tptr"; case N_TSLICE: return "tslice"; case N_TARRAY: return "tarray"; case N_TFN: return "tfn"; case N_TSTRUCT: return "tstruct"; case N_TFIELD: return "tfield"; case N_TCHAN: return "tchan"; case N_ATTR: return "attr"; case N_TTUPLE: return "ttuple"; case N_TTAGGED: return "ttagged"; case N_TUPLE: return "tuple"; case N_MATCH: return "match"; case N_MCASE: return "mcase"; case N_TRYPROP: return "tryprop"; case N_TRYUNW: return "tryunw"; case N_MLET: return "mlet"; case N_MASSIGN: return "massign"; case N_TYPETEST: return "typetest"; case N_TYPEASSERT: return "typeassert"; case N_VOIDLIT: return "voidlit"; case N_TBANG: return "tbang"; case N_YIELD: return "yield"; case N_TENUM: return "tenum"; case N_TENUMMEMBER: return "tenummember"; case N_LAST: return "last"; } return "?"; } static void indent(FILE *f, int d) { for (int i = 0; i < d; i++) fputs(" ", f); } static void printq(FILE *f, const char *s) { fputc('"', f); for (; *s; s++) { unsigned char c = (unsigned char)*s; switch (c) { case '"': fputs("\\\"", f); break; case '\\': fputs("\\\\", f); break; case '\n': fputs("\\n", f); break; case '\t': fputs("\\t", f); break; default: if (c < 0x20) fprintf(f, "\\x%02x", c); else fputc(c, f); } } fputc('"', f); } static void pr(FILE*, Node*, int); static void prlist(FILE *f, const char *tag, Node *head, int d) { indent(f, d); fprintf(f, "(%s\n", tag); for (Node *n = head; n; n = n->next) pr(f, n, d + 1); indent(f, d); fputs(")\n", f); } static void pr(FILE *f, Node *n, int d) { if (n == NULL) { indent(f, d); fputs("()\n", f); return; } indent(f, d); fprintf(f, "(%s", nkname(n->kind)); switch (n->kind) { case N_INTLIT: fprintf(f, " %llu", (unsigned long long)n->uval); break; case N_FLOATLIT: fprintf(f, " %g", n->fval); break; case N_RUNELIT: fprintf(f, " %llu", (unsigned long long)n->uval); break; case N_STRLIT: case N_IDENT: case N_USE: case N_DOT: case N_DEF: case N_TYPEDECL: case N_FNDECL: case N_PARAM: case N_LET: case N_TNAME: case N_TFIELD: case N_TENUMMEMBER: case N_FIELD: case N_ATTR: if (n->str) { fputc(' ', f); printq(f, n->str); } break; case N_BIN: case N_UN: case N_ASSIGN: fprintf(f, " %s", tokname(n->op)); break; default: break; } if (n->kind == N_FNDECL && n->export) fputs(" export", f); if (n->kind == N_DEF && n->export) fputs(" export", f); if (n->kind == N_TYPEDECL && n->export) fputs(" export", f); fputc('\n', f); if (n->attr) prlist(f, "@", n->attr, d + 1); if (n->lhs) pr(f, n->lhs, d + 1); if (n->rhs) pr(f, n->rhs, d + 1); if (n->cond) pr(f, n->cond, d + 1); if (n->body) pr(f, n->body, d + 1); if (n->els) pr(f, n->els, d + 1); if (n->list) prlist(f, "list", n->list, d + 1); indent(f, d); fputs(")\n", f); } void astprint(FILE *f, Node *n) { pr(f, n, 0); }