aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/acid/expr.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-04-19 19:32:07 +0000
committerrsc <devnull@localhost>2004-04-19 19:32:07 +0000
commit564ca709d0e20d4fc46744bd858f14cff94ab382 (patch)
tree47bf49710238a6cb7112682e7bd0885f82544759 /src/cmd/acid/expr.c
parent22a7368ef24d5c530a275dd0db0bd4f23b1c3ce3 (diff)
downloadplan9port-564ca709d0e20d4fc46744bd858f14cff94ab382.tar.gz
plan9port-564ca709d0e20d4fc46744bd858f14cff94ab382.tar.bz2
plan9port-564ca709d0e20d4fc46744bd858f14cff94ab382.zip
acid
Diffstat (limited to 'src/cmd/acid/expr.c')
-rw-r--r--src/cmd/acid/expr.c1018
1 files changed, 1018 insertions, 0 deletions
diff --git a/src/cmd/acid/expr.c b/src/cmd/acid/expr.c
new file mode 100644
index 00000000..46e522bf
--- /dev/null
+++ b/src/cmd/acid/expr.c
@@ -0,0 +1,1018 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+#include <mach.h>
+#define Extern extern
+#include "acid.h"
+
+static int fsize[] =
+{
+ ['A'] 4,
+ ['B'] 4,
+ ['C'] 1,
+ ['D'] 4,
+ ['F'] 8,
+ ['G'] 8,
+ ['O'] 4,
+ ['Q'] 4,
+ ['R'] 4,
+ ['S'] 4,
+ ['U'] 4,
+ ['V'] 8,
+ ['X'] 4,
+ ['Y'] 8,
+ ['W'] 8,
+ ['Z'] 8,
+ ['a'] 4,
+ ['b'] 1,
+ ['c'] 1,
+ ['d'] 2,
+ ['f'] 4,
+ ['g'] 4,
+ ['o'] 2,
+ ['q'] 2,
+ ['r'] 2,
+ ['s'] 4,
+ ['u'] 2,
+ ['x'] 2,
+};
+
+int
+fmtsize(Value *v)
+{
+ int ret;
+
+ switch(v->store.fmt) {
+ default:
+ return fsize[(unsigned char)v->store.fmt];
+ case 'i':
+ case 'I':
+ if(v->type != TINT || mach == 0)
+ error("no size for i fmt pointer ++/--");
+ ret = (*mach->instsize)(symmap, v->store.u.ival);
+ if(ret < 0) {
+ ret = (*mach->instsize)(symmap, v->store.u.ival);
+ if(ret < 0)
+ error("%r");
+ }
+ return ret;
+ }
+}
+
+void
+chklval(Node *lp)
+{
+ if(lp->op != ONAME)
+ error("need l-value");
+}
+
+void
+olist(Node *n, Node *res)
+{
+ expr(n->left, res);
+ expr(n->right, res);
+}
+
+void
+oeval(Node *n, Node *res)
+{
+ expr(n->left, res);
+ if(res->type != TCODE)
+ error("bad type for eval");
+ expr(res->store.u.cc, res);
+}
+
+void
+ocast(Node *n, Node *res)
+{
+ if(n->sym->lt == 0)
+ error("%s is not a complex type", n->sym->name);
+
+ expr(n->left, res);
+ res->store.comt = n->sym->lt;
+ res->store.fmt = 'a';
+}
+
+void
+oindm(Node *n, Node *res)
+{
+ Map *m;
+ Node l;
+
+ m = cormap;
+ if(m == 0)
+ m = symmap;
+ expr(n->left, &l);
+ if(l.type != TINT)
+ error("bad type for *");
+ if(m == 0)
+ error("no map for *");
+ indir(m, l.store.u.ival, l.store.fmt, res);
+ res->store.comt = l.store.comt;
+}
+
+void
+oindc(Node *n, Node *res)
+{
+ Map *m;
+ Node l;
+
+ m = symmap;
+ if(m == 0)
+ m = cormap;
+ expr(n->left, &l);
+ if(l.type != TINT)
+ error("bad type for @");
+ if(m == 0)
+ error("no map for @");
+ indir(m, l.store.u.ival, l.store.fmt, res);
+ res->store.comt = l.store.comt;
+}
+
+void
+oframe(Node *n, Node *res)
+{
+ char *p;
+ Node *lp;
+ ulong ival;
+ Frtype *f;
+
+ p = n->sym->name;
+ while(*p && *p == '$')
+ p++;
+ lp = n->left;
+ if(localaddr(cormap, correg, p, lp->sym->name, &ival) < 0)
+ error("colon: %r");
+
+ res->store.u.ival = ival;
+ res->op = OCONST;
+ res->store.fmt = 'X';
+ res->type = TINT;
+
+ /* Try and set comt */
+ for(f = n->sym->local; f; f = f->next) {
+ if(f->var == lp->sym) {
+ res->store.comt = f->type;
+ res->store.fmt = 'a';
+ break;
+ }
+ }
+}
+
+void
+oindex(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+
+ if(r.type != TINT)
+ error("bad type for []");
+
+ switch(l.type) {
+ default:
+ error("lhs[] has bad type");
+ case TINT:
+ indir(cormap, l.store.u.ival+(r.store.u.ival*fsize[(unsigned char)l.store.fmt]), l.store.fmt, res);
+ res->store.comt = l.store.comt;
+ res->store.fmt = l.store.fmt;
+ break;
+ case TLIST:
+ nthelem(l.store.u.l, r.store.u.ival, res);
+ break;
+ case TSTRING:
+ res->store.u.ival = 0;
+ if(r.store.u.ival >= 0 && r.store.u.ival < l.store.u.string->len) {
+ int xx8; /* to get around bug in vc */
+ xx8 = r.store.u.ival;
+ res->store.u.ival = l.store.u.string->string[xx8];
+ }
+ res->op = OCONST;
+ res->type = TINT;
+ res->store.fmt = 'c';
+ break;
+ }
+}
+
+void
+oappend(Node *n, Node *res)
+{
+ Node r, l;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ if(l.type != TLIST)
+ error("must append to list");
+ append(res, &l, &r);
+}
+
+void
+odelete(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ if(l.type != TLIST)
+ error("must delete from list");
+ if(r.type != TINT)
+ error("delete index must be integer");
+
+ delete(l.store.u.l, r.store.u.ival, res);
+}
+
+void
+ohead(Node *n, Node *res)
+{
+ Node l;
+
+ expr(n->left, &l);
+ if(l.type != TLIST)
+ error("head needs list");
+ res->op = OCONST;
+ if(l.store.u.l) {
+ res->type = l.store.u.l->type;
+ res->store = l.store.u.l->store;
+ }
+ else {
+ res->type = TLIST;
+ res->store.u.l = 0;
+ }
+}
+
+void
+otail(Node *n, Node *res)
+{
+ Node l;
+
+ expr(n->left, &l);
+ if(l.type != TLIST)
+ error("tail needs list");
+ res->op = OCONST;
+ res->type = TLIST;
+ if(l.store.u.l)
+ res->store.u.l = l.store.u.l->next;
+ else
+ res->store.u.l = 0;
+}
+
+void
+oconst(Node *n, Node *res)
+{
+ res->op = OCONST;
+ res->type = n->type;
+ res->store = n->store;
+ res->store.comt = n->store.comt;
+}
+
+void
+oname(Node *n, Node *res)
+{
+ Value *v;
+
+ v = n->sym->v;
+ if(v->set == 0)
+ error("%s used but not set", n->sym->name);
+ res->op = OCONST;
+ res->type = v->type;
+ res->store = v->store;
+ res->store.comt = v->store.comt;
+}
+
+void
+octruct(Node *n, Node *res)
+{
+ res->op = OCONST;
+ res->type = TLIST;
+ res->store.u.l = construct(n->left);
+}
+
+void
+oasgn(Node *n, Node *res)
+{
+ Node *lp, r;
+ Value *v;
+
+ lp = n->left;
+ switch(lp->op) {
+ case OINDM:
+ windir(cormap, lp->left, n->right, res);
+ break;
+ case OINDC:
+ windir(symmap, lp->left, n->right, res);
+ break;
+ default:
+ chklval(lp);
+ v = lp->sym->v;
+ expr(n->right, &r);
+ v->set = 1;
+ v->type = r.type;
+ v->store = r.store;
+ res->op = OCONST;
+ res->type = v->type;
+ res->store = v->store;
+ res->store.comt = v->store.comt;
+ }
+}
+
+void
+oadd(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TFLOAT;
+ switch(l.type) {
+ default:
+ error("bad lhs type +");
+ case TINT:
+ switch(r.type) {
+ case TINT:
+ res->type = TINT;
+ res->store.u.ival = l.store.u.ival+r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.fval = l.store.u.ival+r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type +");
+ }
+ break;
+ case TFLOAT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.fval = l.store.u.fval+r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.fval = l.store.u.fval+r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type +");
+ }
+ break;
+ case TSTRING:
+ if(r.type == TSTRING) {
+ res->type = TSTRING;
+ res->store.fmt = 's';
+ res->store.u.string = stradd(l.store.u.string, r.store.u.string);
+ break;
+ }
+ error("bad rhs for +");
+ case TLIST:
+ res->type = TLIST;
+ switch(r.type) {
+ case TLIST:
+ res->store.u.l = addlist(l.store.u.l, r.store.u.l);
+ break;
+ default:
+ r.left = 0;
+ r.right = 0;
+ res->store.u.l = addlist(l.store.u.l, construct(&r));
+ break;
+ }
+ }
+}
+
+void
+osub(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TFLOAT;
+ switch(l.type) {
+ default:
+ error("bad lhs type -");
+ case TINT:
+ switch(r.type) {
+ case TINT:
+ res->type = TINT;
+ res->store.u.ival = l.store.u.ival-r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.fval = l.store.u.ival-r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type -");
+ }
+ break;
+ case TFLOAT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.fval = l.store.u.fval-r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.fval = l.store.u.fval-r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type -");
+ }
+ break;
+ }
+}
+
+void
+omul(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TFLOAT;
+ switch(l.type) {
+ default:
+ error("bad lhs type *");
+ case TINT:
+ switch(r.type) {
+ case TINT:
+ res->type = TINT;
+ res->store.u.ival = l.store.u.ival*r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.fval = l.store.u.ival*r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type *");
+ }
+ break;
+ case TFLOAT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.fval = l.store.u.fval*r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.fval = l.store.u.fval*r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type *");
+ }
+ break;
+ }
+}
+
+void
+odiv(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TFLOAT;
+ switch(l.type) {
+ default:
+ error("bad lhs type /");
+ case TINT:
+ switch(r.type) {
+ case TINT:
+ res->type = TINT;
+ if(r.store.u.ival == 0)
+ error("zero divide");
+ res->store.u.ival = l.store.u.ival/r.store.u.ival;
+ break;
+ case TFLOAT:
+ if(r.store.u.fval == 0)
+ error("zero divide");
+ res->store.u.fval = l.store.u.ival/r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type /");
+ }
+ break;
+ case TFLOAT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.fval = l.store.u.fval/r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.fval = l.store.u.fval/r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type /");
+ }
+ break;
+ }
+}
+
+void
+omod(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TINT;
+ if(l.type != TINT || r.type != TINT)
+ error("bad expr type %");
+ res->store.u.ival = l.store.u.ival%r.store.u.ival;
+}
+
+void
+olsh(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TINT;
+ if(l.type != TINT || r.type != TINT)
+ error("bad expr type <<");
+ res->store.u.ival = l.store.u.ival<<r.store.u.ival;
+}
+
+void
+orsh(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TINT;
+ if(l.type != TINT || r.type != TINT)
+ error("bad expr type >>");
+ res->store.u.ival = (unsigned)l.store.u.ival>>r.store.u.ival;
+}
+
+void
+olt(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TINT;
+ switch(l.type) {
+ default:
+ error("bad lhs type <");
+ case TINT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.ival < r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.ival < r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type <");
+ }
+ break;
+ case TFLOAT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.fval < r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.fval < r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type <");
+ }
+ break;
+ }
+}
+
+void
+ogt(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = 'D';
+ res->op = OCONST;
+ res->type = TINT;
+ switch(l.type) {
+ default:
+ error("bad lhs type >");
+ case TINT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.ival > r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.ival > r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type >");
+ }
+ break;
+ case TFLOAT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.fval > r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.fval > r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type >");
+ }
+ break;
+ }
+}
+
+void
+oleq(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = 'D';
+ res->op = OCONST;
+ res->type = TINT;
+ switch(l.type) {
+ default:
+ error("bad expr type <=");
+ case TINT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.ival <= r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.ival <= r.store.u.fval;
+ break;
+ default:
+ error("bad expr type <=");
+ }
+ break;
+ case TFLOAT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.fval <= r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.fval <= r.store.u.fval;
+ break;
+ default:
+ error("bad expr type <=");
+ }
+ break;
+ }
+}
+
+void
+ogeq(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = 'D';
+ res->op = OCONST;
+ res->type = TINT;
+ switch(l.type) {
+ default:
+ error("bad lhs type >=");
+ case TINT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.ival >= r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.ival >= r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type >=");
+ }
+ break;
+ case TFLOAT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.fval >= r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.fval >= r.store.u.fval;
+ break;
+ default:
+ error("bad rhs type >=");
+ }
+ break;
+ }
+}
+
+void
+oeq(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = 'D';
+ res->op = OCONST;
+ res->type = TINT;
+ res->store.u.ival = 0;
+ switch(l.type) {
+ default:
+ break;
+ case TINT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.ival == r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.ival == r.store.u.fval;
+ break;
+ default:
+ break;
+ }
+ break;
+ case TFLOAT:
+ switch(r.type) {
+ case TINT:
+ res->store.u.ival = l.store.u.fval == r.store.u.ival;
+ break;
+ case TFLOAT:
+ res->store.u.ival = l.store.u.fval == r.store.u.fval;
+ break;
+ default:
+ break;
+ }
+ break;
+ case TSTRING:
+ if(r.type == TSTRING) {
+ res->store.u.ival = scmp(r.store.u.string, l.store.u.string);
+ break;
+ }
+ break;
+ case TLIST:
+ if(r.type == TLIST) {
+ res->store.u.ival = listcmp(l.store.u.l, r.store.u.l);
+ break;
+ }
+ break;
+ }
+ if(n->op == ONEQ)
+ res->store.u.ival = !res->store.u.ival;
+}
+
+
+void
+oland(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TINT;
+ if(l.type != TINT || r.type != TINT)
+ error("bad expr type &");
+ res->store.u.ival = l.store.u.ival&r.store.u.ival;
+}
+
+void
+oxor(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TINT;
+ if(l.type != TINT || r.type != TINT)
+ error("bad expr type ^");
+ res->store.u.ival = l.store.u.ival^r.store.u.ival;
+}
+
+void
+olor(Node *n, Node *res)
+{
+ Node l, r;
+
+ expr(n->left, &l);
+ expr(n->right, &r);
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TINT;
+ if(l.type != TINT || r.type != TINT)
+ error("bad expr type |");
+ res->store.u.ival = l.store.u.ival|r.store.u.ival;
+}
+
+void
+ocand(Node *n, Node *res)
+{
+ Node l, r;
+
+ res->store.fmt = l.store.fmt;
+ res->op = OCONST;
+ res->type = TINT;
+ res->store.u.ival = 0;
+ expr(n->left, &l);
+ if(bool(&l) == 0)
+ return;
+ expr(n->right, &r);
+ if(bool(&r) == 0)
+ return;
+ res->store.u.ival = 1;
+}
+
+void
+onot(Node *n, Node *res)
+{
+ Node l;
+
+ res->op = OCONST;
+ res->type = TINT;
+ res->store.u.ival = 0;
+ expr(n->left, &l);
+ if(bool(&l) == 0)
+ res->store.u.ival = 1;
+}
+
+void
+ocor(Node *n, Node *res)
+{
+ Node l, r;
+
+ res->op = OCONST;
+ res->type = TINT;
+ res->store.u.ival = 0;
+ expr(n->left, &l);
+ if(bool(&l)) {
+ res->store.u.ival = 1;
+ return;
+ }
+ expr(n->right, &r);
+ if(bool(&r)) {
+ res->store.u.ival = 1;
+ return;
+ }
+}
+
+void
+oeinc(Node *n, Node *res)
+{
+ Value *v;
+
+ chklval(n->left);
+ v = n->left->sym->v;
+ res->op = OCONST;
+ res->type = v->type;
+ switch(v->type) {
+ case TINT:
+ if(n->op == OEDEC)
+ v->store.u.ival -= fmtsize(v);
+ else
+ v->store.u.ival += fmtsize(v);
+ break;
+ case TFLOAT:
+ if(n->op == OEDEC)
+ v->store.u.fval--;
+ else
+ v->store.u.fval++;
+ break;
+ default:
+ error("bad type for pre --/++");
+ }
+ res->store = v->store;
+}
+
+void
+opinc(Node *n, Node *res)
+{
+ Value *v;
+
+ chklval(n->left);
+ v = n->left->sym->v;
+ res->op = OCONST;
+ res->type = v->type;
+ res->store = v->store;
+ switch(v->type) {
+ case TINT:
+ if(n->op == OPDEC)
+ v->store.u.ival -= fmtsize(v);
+ else
+ v->store.u.ival += fmtsize(v);
+ break;
+ case TFLOAT:
+ if(n->op == OPDEC)
+ v->store.u.fval--;
+ else
+ v->store.u.fval++;
+ break;
+ default:
+ error("bad type for post --/++");
+ }
+}
+
+void
+ocall(Node *n, Node *res)
+{
+ Lsym *s;
+ Rplace *rsav;
+
+ res->op = OCONST; /* Default return value */
+ res->type = TLIST;
+ res->store.u.l = 0;
+
+ chklval(n->left);
+ s = n->left->sym;
+
+ if(n->builtin && !s->builtin){
+ error("no builtin %s", s->name);
+ return;
+ }
+ if(s->builtin && (n->builtin || s->proc == 0)) {
+ (*s->builtin)(res, n->right);
+ return;
+ }
+ if(s->proc == 0)
+ error("no function %s", s->name);
+
+ rsav = ret;
+ call(s->name, n->right, s->proc->left, s->proc->right, res);
+ ret = rsav;
+}
+
+void
+ofmt(Node *n, Node *res)
+{
+ expr(n->left, res);
+ res->store.fmt = n->right->store.u.ival;
+}
+
+void
+owhat(Node *n, Node *res)
+{
+ res->op = OCONST; /* Default return value */
+ res->type = TLIST;
+ res->store.u.l = 0;
+ whatis(n->sym);
+}
+
+void (*expop[])(Node*, Node*) =
+{
+ [ONAME] oname,
+ [OCONST] oconst,
+ [OMUL] omul,
+ [ODIV] odiv,
+ [OMOD] omod,
+ [OADD] oadd,
+ [OSUB] osub,
+ [ORSH] orsh,
+ [OLSH] olsh,
+ [OLT] olt,
+ [OGT] ogt,
+ [OLEQ] oleq,
+ [OGEQ] ogeq,
+ [OEQ] oeq,
+ [ONEQ] oeq,
+ [OLAND] oland,
+ [OXOR] oxor,
+ [OLOR] olor,
+ [OCAND] ocand,
+ [OCOR] ocor,
+ [OASGN] oasgn,
+ [OINDM] oindm,
+ [OEDEC] oeinc,
+ [OEINC] oeinc,
+ [OPINC] opinc,
+ [OPDEC] opinc,
+ [ONOT] onot,
+ [OIF] 0,
+ [ODO] 0,
+ [OLIST] olist,
+ [OCALL] ocall,
+ [OCTRUCT] octruct,
+ [OWHILE] 0,
+ [OELSE] 0,
+ [OHEAD] ohead,
+ [OTAIL] otail,
+ [OAPPEND] oappend,
+ [ORET] 0,
+ [OINDEX] oindex,
+ [OINDC] oindc,
+ [ODOT] odot,
+ [OLOCAL] 0,
+ [OFRAME] oframe,
+ [OCOMPLEX] 0,
+ [ODELETE] odelete,
+ [OCAST] ocast,
+ [OFMT] ofmt,
+ [OEVAL] oeval,
+ [OWHAT] owhat,
+};