123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026 |
- #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,
- ['W'] 8,
- ['X'] 4,
- ['Y'] 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,
- ['3'] 10,
- ['8'] 10,
- };
- int
- fmtsize(Value *v)
- {
- int ret;
- switch(v->fmt) {
- default:
- return fsize[v->fmt];
- case 'i':
- case 'I':
- if(v->type != TINT || machdata == 0)
- error("no size for i fmt pointer ++/--");
- ret = (*machdata->instsize)(cormap, v->ival);
- if(ret < 0) {
- ret = (*machdata->instsize)(symmap, v->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->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->comt = n->sym->lt;
- res->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.ival, l.fmt, res);
- res->comt = l.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.ival, l.fmt, res);
- res->comt = l.comt;
- }
- void
- oframe(Node *n, Node *res)
- {
- char *p;
- Node *lp;
- uvlong ival;
- Frtype *f;
- p = n->sym->name;
- while(*p && *p == '$')
- p++;
- lp = n->left;
- if(localaddr(cormap, p, lp->sym->name, &ival, rget) < 0)
- error("colon: %r");
- res->ival = ival;
- res->op = OCONST;
- res->fmt = 'X';
- res->type = TINT;
- /* Try and set comt */
- for(f = n->sym->local; f; f = f->next) {
- if(f->var == lp->sym) {
- res->comt = f->type;
- res->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.ival+(r.ival*fsize[l.fmt]), l.fmt, res);
- res->comt = l.comt;
- res->fmt = l.fmt;
- break;
- case TLIST:
- nthelem(l.l, r.ival, res);
- break;
- case TSTRING:
- res->ival = 0;
- if(r.ival >= 0 && r.ival < l.string->len) {
- int xx8; /* to get around bug in vc */
- xx8 = r.ival;
- res->ival = l.string->string[xx8];
- }
- res->op = OCONST;
- res->type = TINT;
- res->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.l, r.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.l) {
- res->type = l.l->type;
- res->Store = l.l->Store;
- }
- else {
- res->type = TLIST;
- res->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.l)
- res->l = l.l->next;
- else
- res->l = 0;
- }
- void
- oconst(Node *n, Node *res)
- {
- res->op = OCONST;
- res->type = n->type;
- res->Store = n->Store;
- res->comt = n->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->comt = v->comt;
- }
- void
- octruct(Node *n, Node *res)
- {
- res->op = OCONST;
- res->type = TLIST;
- res->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->comt = v->comt;
- }
- }
- void
- oadd(Node *n, Node *res)
- {
- Node l, r;
- expr(n->left, &l);
- expr(n->right, &r);
- res->fmt = l.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->ival = l.ival+r.ival;
- break;
- case TFLOAT:
- res->fval = l.ival+r.fval;
- break;
- default:
- error("bad rhs type +");
- }
- break;
- case TFLOAT:
- switch(r.type) {
- case TINT:
- res->fval = l.fval+r.ival;
- break;
- case TFLOAT:
- res->fval = l.fval+r.fval;
- break;
- default:
- error("bad rhs type +");
- }
- break;
- case TSTRING:
- if(r.type == TSTRING) {
- res->type = TSTRING;
- res->fmt = 's';
- res->string = stradd(l.string, r.string);
- break;
- }
- if(r.type == TINT) {
- res->type = TSTRING;
- res->fmt = 's';
- res->string = straddrune(l.string, r.ival);
- break;
- }
- error("bad rhs for +");
- case TLIST:
- res->type = TLIST;
- switch(r.type) {
- case TLIST:
- res->l = addlist(l.l, r.l);
- break;
- default:
- r.left = 0;
- r.right = 0;
- res->l = addlist(l.l, construct(&r));
- break;
- }
- }
- }
- void
- osub(Node *n, Node *res)
- {
- Node l, r;
- expr(n->left, &l);
- expr(n->right, &r);
- res->fmt = l.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->ival = l.ival-r.ival;
- break;
- case TFLOAT:
- res->fval = l.ival-r.fval;
- break;
- default:
- error("bad rhs type -");
- }
- break;
- case TFLOAT:
- switch(r.type) {
- case TINT:
- res->fval = l.fval-r.ival;
- break;
- case TFLOAT:
- res->fval = l.fval-r.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->fmt = l.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->ival = l.ival*r.ival;
- break;
- case TFLOAT:
- res->fval = l.ival*r.fval;
- break;
- default:
- error("bad rhs type *");
- }
- break;
- case TFLOAT:
- switch(r.type) {
- case TINT:
- res->fval = l.fval*r.ival;
- break;
- case TFLOAT:
- res->fval = l.fval*r.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->fmt = l.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.ival == 0)
- error("zero divide");
- res->ival = l.ival/r.ival;
- break;
- case TFLOAT:
- if(r.fval == 0)
- error("zero divide");
- res->fval = l.ival/r.fval;
- break;
- default:
- error("bad rhs type /");
- }
- break;
- case TFLOAT:
- switch(r.type) {
- case TINT:
- res->fval = l.fval/r.ival;
- break;
- case TFLOAT:
- res->fval = l.fval/r.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->fmt = l.fmt;
- res->op = OCONST;
- res->type = TINT;
- if(l.type != TINT || r.type != TINT)
- error("bad expr type %");
- res->ival = l.ival%r.ival;
- }
- void
- olsh(Node *n, Node *res)
- {
- Node l, r;
- expr(n->left, &l);
- expr(n->right, &r);
- res->fmt = l.fmt;
- res->op = OCONST;
- res->type = TINT;
- if(l.type != TINT || r.type != TINT)
- error("bad expr type <<");
- res->ival = l.ival<<r.ival;
- }
- void
- orsh(Node *n, Node *res)
- {
- Node l, r;
- expr(n->left, &l);
- expr(n->right, &r);
- res->fmt = l.fmt;
- res->op = OCONST;
- res->type = TINT;
- if(l.type != TINT || r.type != TINT)
- error("bad expr type >>");
- res->ival = (uvlong)l.ival>>r.ival;
- }
- void
- olt(Node *n, Node *res)
- {
- Node l, r;
- expr(n->left, &l);
- expr(n->right, &r);
- res->fmt = l.fmt;
- res->op = OCONST;
- res->type = TINT;
- switch(l.type) {
- default:
- error("bad lhs type <");
- case TINT:
- switch(r.type) {
- case TINT:
- res->ival = l.ival < r.ival;
- break;
- case TFLOAT:
- res->ival = l.ival < r.fval;
- break;
- default:
- error("bad rhs type <");
- }
- break;
- case TFLOAT:
- switch(r.type) {
- case TINT:
- res->ival = l.fval < r.ival;
- break;
- case TFLOAT:
- res->ival = l.fval < r.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->fmt = 'D';
- res->op = OCONST;
- res->type = TINT;
- switch(l.type) {
- default:
- error("bad lhs type >");
- case TINT:
- switch(r.type) {
- case TINT:
- res->ival = l.ival > r.ival;
- break;
- case TFLOAT:
- res->ival = l.ival > r.fval;
- break;
- default:
- error("bad rhs type >");
- }
- break;
- case TFLOAT:
- switch(r.type) {
- case TINT:
- res->ival = l.fval > r.ival;
- break;
- case TFLOAT:
- res->ival = l.fval > r.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->fmt = 'D';
- res->op = OCONST;
- res->type = TINT;
- switch(l.type) {
- default:
- error("bad expr type <=");
- case TINT:
- switch(r.type) {
- case TINT:
- res->ival = l.ival <= r.ival;
- break;
- case TFLOAT:
- res->ival = l.ival <= r.fval;
- break;
- default:
- error("bad expr type <=");
- }
- break;
- case TFLOAT:
- switch(r.type) {
- case TINT:
- res->ival = l.fval <= r.ival;
- break;
- case TFLOAT:
- res->ival = l.fval <= r.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->fmt = 'D';
- res->op = OCONST;
- res->type = TINT;
- switch(l.type) {
- default:
- error("bad lhs type >=");
- case TINT:
- switch(r.type) {
- case TINT:
- res->ival = l.ival >= r.ival;
- break;
- case TFLOAT:
- res->ival = l.ival >= r.fval;
- break;
- default:
- error("bad rhs type >=");
- }
- break;
- case TFLOAT:
- switch(r.type) {
- case TINT:
- res->ival = l.fval >= r.ival;
- break;
- case TFLOAT:
- res->ival = l.fval >= r.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->fmt = 'D';
- res->op = OCONST;
- res->type = TINT;
- res->ival = 0;
- switch(l.type) {
- default:
- break;
- case TINT:
- switch(r.type) {
- case TINT:
- res->ival = l.ival == r.ival;
- break;
- case TFLOAT:
- res->ival = l.ival == r.fval;
- break;
- default:
- break;
- }
- break;
- case TFLOAT:
- switch(r.type) {
- case TINT:
- res->ival = l.fval == r.ival;
- break;
- case TFLOAT:
- res->ival = l.fval == r.fval;
- break;
- default:
- break;
- }
- break;
- case TSTRING:
- if(r.type == TSTRING) {
- res->ival = scmp(r.string, l.string);
- break;
- }
- break;
- case TLIST:
- if(r.type == TLIST) {
- res->ival = listcmp(l.l, r.l);
- break;
- }
- break;
- }
- if(n->op == ONEQ)
- res->ival = !res->ival;
- }
- void
- oland(Node *n, Node *res)
- {
- Node l, r;
- expr(n->left, &l);
- expr(n->right, &r);
- res->fmt = l.fmt;
- res->op = OCONST;
- res->type = TINT;
- if(l.type != TINT || r.type != TINT)
- error("bad expr type &");
- res->ival = l.ival&r.ival;
- }
- void
- oxor(Node *n, Node *res)
- {
- Node l, r;
- expr(n->left, &l);
- expr(n->right, &r);
- res->fmt = l.fmt;
- res->op = OCONST;
- res->type = TINT;
- if(l.type != TINT || r.type != TINT)
- error("bad expr type ^");
- res->ival = l.ival^r.ival;
- }
- void
- olor(Node *n, Node *res)
- {
- Node l, r;
- expr(n->left, &l);
- expr(n->right, &r);
- res->fmt = l.fmt;
- res->op = OCONST;
- res->type = TINT;
- if(l.type != TINT || r.type != TINT)
- error("bad expr type |");
- res->ival = l.ival|r.ival;
- }
- void
- ocand(Node *n, Node *res)
- {
- Node l, r;
- res->fmt = l.fmt;
- res->op = OCONST;
- res->type = TINT;
- res->ival = 0;
- expr(n->left, &l);
- if(bool(&l) == 0)
- return;
- expr(n->right, &r);
- if(bool(&r) == 0)
- return;
- res->ival = 1;
- }
- void
- onot(Node *n, Node *res)
- {
- Node l;
- res->op = OCONST;
- res->type = TINT;
- res->ival = 0;
- expr(n->left, &l);
- if(bool(&l) == 0)
- res->ival = 1;
- }
- void
- ocor(Node *n, Node *res)
- {
- Node l, r;
- res->op = OCONST;
- res->type = TINT;
- res->ival = 0;
- expr(n->left, &l);
- if(bool(&l)) {
- res->ival = 1;
- return;
- }
- expr(n->right, &r);
- if(bool(&r)) {
- res->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->ival -= fmtsize(v);
- else
- v->ival += fmtsize(v);
- break;
- case TFLOAT:
- if(n->op == OEDEC)
- v->fval--;
- else
- v->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->ival -= fmtsize(v);
- else
- v->ival += fmtsize(v);
- break;
- case TFLOAT:
- if(n->op == OPDEC)
- v->fval--;
- else
- v->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->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->fmt = n->right->ival;
- }
- void
- owhat(Node *n, Node *res)
- {
- res->op = OCONST; /* Default return value */
- res->type = TLIST;
- res->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,
- };
|