#include #include #include #include #include "paper.h" #include "impl.h" static char *binop[] = { [OMUL] "*", [ODIV] "/", [OMOD] "%", [OADD] "+", [OSUB] "-", [ORSH] ">>", [OLSH] "<<", [OLT] "<", [OGT] ">", [OLEQ] "<=", [OGEQ] ">=", [OEQ] "==", [ONEQ] "!=", [OLAND] "&", [OXOR] "^", [OLOR] "|", [OCAND] "&&", [OCOR] "||", [OASGN] " = ", }; static char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; char *pptypenames[] = { [TINT] "integer", [TFLOAT] "float", [TSTRING] "string", [TLIST] "list", [TCODE] "code", [TPOINTER] "pointer", }; int cmp(const void *va, const void *vb) { char * const *a = va; char * const *b = vb; return strcmp(*a, *b); } void fundefs(void) { Lsym *l; char **vec; int i, j, n, max, col, f, g, s; max = 0; f = 0; g = 100; vec = malloc(sizeof(char*)*g); if(vec == nil) sysfatal("out of memory"); for(i = 0; i < Hashsize; i++) { for(l = hash[i]; l; l = l->hash) { if(l->proc == 0 && l->builtin == 0) continue; n = strlen(l->name); if(n > max) max = n; if(f >= g) { g *= 2; vec = realloc(vec, sizeof(char*)*g); if(vec == nil) sysfatal("out of memory"); } vec[f++] = l->name; } } qsort(vec, f, sizeof(char*), cmp); max++; col = 60/max; s = (f+col-1)/col; for(i = 0; i < s; i++) { for(j = i; j < f; j += s) print("%-*s", max, vec[j]); print("\n"); } free(vec); } void whatis(Lsym *l) { int t; int def; if(l == 0) { fundefs(); return; } def = 0; if(l->v->set) { t = l->v->store.type; print("%s variable\n", pptypenames[t]); def = 1; } if(l->proc) { print("defn %s(", l->name); pexpr(l->proc->left); print(") {\n"); pcode(l->proc->right, 1); print("}\n"); def = 1; } if(l->builtin) { print("builtin function\n"); def = 1; } if(def == 0) print("%s is undefined\n", l->name); } void slist(Node *n, int d) { if(n == 0) return; if(n->op == OLIST) print("%.*s{\n", d-1, tabs); pcode(n, d); if(n->op == OLIST) print("%.*s}\n", d-1, tabs); } void pcode(Node *n, int d) { Node *r, *l; if(n == 0) return; r = n->right; l = n->left; switch(n->op) { default: print("%.*s", d, tabs); pexpr(n); print(";\n"); break; case OLIST: pcode(n->left, d); pcode(n->right, d); break; case OLOCAL: print("%.*slocal", d, tabs); while(l) { print(" %s", l->sym->name); l = l->left; if(l == 0) print(";\n"); else print(","); } break; case OIF: print("%.*sif ", d, tabs); pexpr(l); d++; print(" then\n"); if(r && r->op == OELSE) { slist(r->left, d); print("%.*selse\n", d-1, tabs); slist(r->right, d); } else slist(r, d); break; case OWHILE: print("%.*swhile ", d, tabs); pexpr(l); d++; print(" do\n"); slist(r, d); break; case ORET: print("%.*sreturn ", d, tabs); pexpr(l); print(";\n"); break; case ODO: print("%.*sloop ", d, tabs); pexpr(l->left); print(", "); pexpr(l->right); print(" do\n"); slist(r, d+1); break; case OFOR: print("%.*sfor(", d, tabs); pexpr(l->left); print("; "); pexpr(l->right->left); print("; "); pexpr(l->right->right); print(") \n"); slist(r, d+1); break; case OBREAK: print("%.*sbreak;", d, tabs); break; case OCONTINUE: print("%.*scontinue;", d, tabs); break; } } void pexpr(Node *n) { Node *r, *l; if(n == 0) return; r = n->right; l = n->left; switch(n->op) { case ONAME: print("%s", n->sym->name); break; case OCONST: switch(n->store.type) { case TINT: print("%lld", n->store.ival); break; case TFLOAT: print("%g", n->store.fval); break; case TSTRING: pstr(n->store.string); break; case TLIST: break; } break; case OMUL: case ODIV: case OMOD: case OADD: case OSUB: case ORSH: case OLSH: case OLT: case OGT: case OLEQ: case OGEQ: case OEQ: case ONEQ: case OLAND: case OXOR: case OLOR: case OCAND: case OCOR: print("("); pexpr(l); print(binop[n->op]); pexpr(r); print(")"); break; case OASGN: pexpr(l); print(binop[n->op]); pexpr(r); break; case OINDM: print("*"); pexpr(l); break; case OEDEC: print("--"); pexpr(l); break; case OEINC: print("++"); pexpr(l); break; case OPINC: pexpr(l); print("++"); break; case OPDEC: pexpr(l); print("--"); break; case ONOT: print("!"); pexpr(l); break; case OLIST: pexpr(l); if(r) { print(","); pexpr(r); } break; case OCALL: pexpr(l); print("("); pexpr(r); print(")"); break; case OCTRUCT: print("{"); pexpr(l); print("}"); break; case OHEAD: print("head "); pexpr(l); break; case OTAIL: print("tail "); pexpr(l); break; case OAPPEND2: print("append "); pexpr(l); print(","); pexpr(r); break; case ODELETE: print("delete "); pexpr(l); print(","); pexpr(r); break; case ORET: print("return "); pexpr(l); break; case OINDEX: pexpr(l); print("["); pexpr(r); print("]"); break; case OINDC: print("@"); pexpr(l); break; case ODOT: pexpr(l); print(".%s", n->sym->name); break; case OCAST: print("(%s)", n->sym->name); pexpr(l); break; case OEVAL: print("eval "); pexpr(l); break; case OWHAT: print("whatis"); if(n->sym) print(" %s", n->sym->name); break; } } void pstr(String *s) { int i, c; print("\""); for(i = 0; i < s->len; i++) { c = s->string[i]; switch(c) { case '\0': c = '0'; break; case '\n': c = 'n'; break; case '\r': c = 'r'; break; case '\t': c = 't'; break; case '\b': c = 'b'; break; case '\f': c = 'f'; break; case '\a': c = 'a'; break; case '\v': c = 'v'; break; case '\\': c = '\\'; break; case '"': c = '"'; break; default: print("%c", c); continue; } print("\\%c", c); } print("\""); }