#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#include <mach.h>
#define Extern extern
#include "acid.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 *typenames[] =
{
[TINT] "integer",
[TFLOAT] "float",
[TSTRING] "string",
[TLIST] "list",
[TCODE] "code",
};
int
cmp(void *va, void *vb)
{
char **a = va;
char **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 == 0)
fatal("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 == 0)
fatal("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)
Bprint(bout, "%-*s", max, vec[j]);
Bprint(bout, "\n");
}
}
void
whatis(Lsym *l)
{
int t;
int def;
Type *ti;
if(l == 0) {
fundefs();
return;
}
def = 0;
if(l->v->set) {
t = l->v->type;
Bprint(bout, "%s variable", typenames[t]);
if(t == TINT || t == TFLOAT)
Bprint(bout, " format %c", l->v->fmt);
if(l->v->comt)
Bprint(bout, " complex %s", l->v->comt->base->name);
Bputc(bout, '\n');
def = 1;
}
if(l->lt) {
Bprint(bout, "complex %s {\n", l->name);
for(ti = l->lt; ti; ti = ti->next) {
if(ti->type) {
if(ti->fmt == 'a') {
Bprint(bout, "\t%s %d %s;\n",
ti->type->name, ti->offset,
ti->tag->name);
}
else {
Bprint(bout, "\t'%c' %s %d %s;\n",
ti->fmt, ti->type->name, ti->offset,
ti->tag->name);
}
}
else
Bprint(bout, "\t'%c' %d %s;\n",
ti->fmt, ti->offset, ti->tag->name);
}
Bprint(bout, "};\n");
def = 1;
}
if(l->proc) {
Bprint(bout, "defn %s(", l->name);
pexpr(l->proc->left);
Bprint(bout, ") {\n");
pcode(l->proc->right, 1);
Bprint(bout, "}\n");
def = 1;
}
if(l->builtin) {
Bprint(bout, "builtin function\n");
def = 1;
}
if(def == 0)
Bprint(bout, "%s is undefined\n", l->name);
}
void
slist(Node *n, int d)
{
if(n == 0)
return;
if(n->op == OLIST)
Bprint(bout, "%.*s{\n", d-1, tabs);
pcode(n, d);
if(n->op == OLIST)
Bprint(bout, "%.*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:
Bprint(bout, "%.*s", d, tabs);
pexpr(n);
Bprint(bout, ";\n");
break;
case OLIST:
pcode(n->left, d);
pcode(n->right, d);
break;
case OLOCAL:
Bprint(bout, "%.*slocal", d, tabs);
while(l) {
Bprint(bout, " %s", l->sym->name);
l = l->left;
if(l == 0)
Bprint(bout, ";\n");
else
Bprint(bout, ",");
}
break;
case OCOMPLEX:
Bprint(bout, "%.*scomplex %s %s;\n", d, tabs, n->sym->name, l->sym->name);
break;
case OIF:
Bprint(bout, "%.*sif ", d, tabs);
pexpr(l);
d++;
Bprint(bout, " then\n");
if(r && r->op == OELSE) {
slist(r->left, d);
Bprint(bout, "%.*selse\n", d-1, tabs);
slist(r->right, d);
}
else
slist(r, d);
break;
case OWHILE:
Bprint(bout, "%.*swhile ", d, tabs);
pexpr(l);
d++;
Bprint(bout, " do\n");
slist(r, d);
break;
case ORET:
Bprint(bout, "%.*sreturn ", d, tabs);
pexpr(l);
Bprint(bout, ";\n");
break;
case ODO:
Bprint(bout, "%.*sloop ", d, tabs);
pexpr(l->left);
Bprint(bout, ", ");
pexpr(l->right);
Bprint(bout, " do\n");
slist(r, d+1);
}
}
void
pexpr(Node *n)
{
Node *r, *l;
if(n == 0)
return;
r = n->right;
l = n->left;
switch(n->op) {
case ONAME:
Bprint(bout, "%s", n->sym->name);
break;
case OCONST:
switch(n->type) {
case TINT:
Bprint(bout, "%lld", n->ival);
break;
case TFLOAT:
Bprint(bout, "%g", n->fval);
break;
case TSTRING:
pstr(n->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:
Bputc(bout, '(');
pexpr(l);
Bprint(bout, binop[n->op]);
pexpr(r);
Bputc(bout, ')');
break;
case OASGN:
pexpr(l);
Bprint(bout, binop[n->op]);
pexpr(r);
break;
case OINDM:
Bprint(bout, "*");
pexpr(l);
break;
case OEDEC:
Bprint(bout, "--");
pexpr(l);
break;
case OEINC:
Bprint(bout, "++");
pexpr(l);
break;
case OPINC:
pexpr(l);
Bprint(bout, "++");
break;
case OPDEC:
pexpr(l);
Bprint(bout, "--");
break;
case ONOT:
Bprint(bout, "!");
pexpr(l);
break;
case OLIST:
pexpr(l);
if(r) {
Bprint(bout, ",");
pexpr(r);
}
break;
case OCALL:
pexpr(l);
Bprint(bout, "(");
pexpr(r);
Bprint(bout, ")");
break;
case OCTRUCT:
Bprint(bout, "{");
pexpr(l);
Bprint(bout, "}");
break;
case OHEAD:
Bprint(bout, "head ");
pexpr(l);
break;
case OTAIL:
Bprint(bout, "tail ");
pexpr(l);
break;
case OAPPEND:
Bprint(bout, "append ");
pexpr(l);
Bprint(bout, ",");
pexpr(r);
break;
case ODELETE:
Bprint(bout, "delete ");
pexpr(l);
Bprint(bout, ",");
pexpr(r);
break;
case ORET:
Bprint(bout, "return ");
pexpr(l);
break;
case OINDEX:
pexpr(l);
Bprint(bout, "[");
pexpr(r);
Bprint(bout, "]");
break;
case OINDC:
Bprint(bout, "@");
pexpr(l);
break;
case ODOT:
pexpr(l);
Bprint(bout, ".%s", n->sym->name);
break;
case OFRAME:
Bprint(bout, "%s:%s", n->sym->name, l->sym->name);
break;
case OCAST:
Bprint(bout, "(%s)", n->sym->name);
pexpr(l);
break;
case OFMT:
pexpr(l);
Bprint(bout, "\\%c", (int)r->ival);
break;
case OEVAL:
Bprint(bout, "eval ");
pexpr(l);
break;
case OWHAT:
Bprint(bout, "whatis");
if(n->sym)
Bprint(bout, " %s", n->sym->name);
break;
}
}
void
pstr(String *s)
{
int i, c;
Bputc(bout, '"');
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:
Bputc(bout, c);
continue;
}
Bputc(bout, '\\');
Bputc(bout, c);
}
Bputc(bout, '"');
}
|