Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#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, '"');
}