diff options
Diffstat (limited to 'src/old/c/walk.c')
-rw-r--r-- | src/old/c/walk.c | 978 |
1 files changed, 0 insertions, 978 deletions
diff --git a/src/old/c/walk.c b/src/old/c/walk.c deleted file mode 100644 index a8552e512..000000000 --- a/src/old/c/walk.c +++ /dev/null @@ -1,978 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "go.h" - -static Node* sw1(Node*, Node*); -static Node* sw2(Node*, Node*); -static Node* sw3(Node*, Node*); -static Node* curfn; - -void -walk(Node *fn) -{ - curfn = fn; - walktype(fn->nbody, 1); -} - -void -walktype(Node *n, int top) -{ - Node *t, *r; - Sym *s; - long lno; - int et; - - /* - * walk the whole tree of the body of a function. - * the types expressions are calculated. - * compile-time constants are evaluated. - */ - - lno = dynlineno; - -loop: - if(n == N) - goto ret; - if(n->op != ONAME) - dynlineno = n->lineno; // for diagnostics - - t = N; - et = Txxx; - - switch(n->op) { - default: - fatal("walktype: switch 1 unknown op %N", n); - goto ret; - - case OPANIC: - case OPRINT: - walktype(n->left, 0); - prcompat(&n->left); - goto ret; - - case OLITERAL: - n->addable = 1; - ullmancalc(n); - goto ret; - - case ONAME: - n->addable = 1; - ullmancalc(n); - if(n->type == N) { - s = n->sym; - if(s->undef == 0) { - yyerror("walktype: %N undeclared", n); - s->undef = 1; - } - } - goto ret; - - case OLIST: - walktype(n->left, top); - n = n->right; - goto loop; - - case OFOR: - if(!top) - goto nottop; - walktype(n->ninit, 1); - walktype(n->ntest, 1); - walktype(n->nincr, 1); - n = n->nbody; - goto loop; - - case OSWITCH: - if(!top) - goto nottop; - - if(n->ntest == N) - n->ntest = booltrue; - walktype(n->ninit, 1); - walktype(n->ntest, 1); - walktype(n->nbody, 1); - - // find common type - if(n->ntest->type == N) - n->ntest->type = walkswitch(n->ntest, n->nbody, sw1); - - // if that fails pick a type - if(n->ntest->type == N) - n->ntest->type = walkswitch(n->ntest, n->nbody, sw2); - - // set the type on all literals - if(n->ntest->type != N) - walkswitch(n->ntest, n->nbody, sw3); - - n = n->nincr; - goto loop; - - case OEMPTY: - if(!top) - goto nottop; - goto ret; - - case OIF: - if(!top) - goto nottop; - walktype(n->ninit, 1); - walktype(n->ntest, 1); - walktype(n->nelse, 1); - n = n->nbody; - goto loop; - - case OCALL: - case OCALLPTR: - case OCALLMETH: - case OCALLINTER: - walktype(n->left, 0); - if(n->left == N) - goto ret; - t = n->left->type; - if(t == N) - goto ret; - - if(n->left->op == ODOTMETH) - n->op = OCALLMETH; - if(n->left->op == ODOTINTER) - n->op = OCALLINTER; - - if(t->etype == TPTR) { - t = t->type; - n->op = OCALLPTR; - } - - if(t->etype != TFUNC) { - yyerror("call of a non-function %T", t); - goto ret; - } - - n->type = *getoutarg(t); - switch(t->outtuple) { - default: - n->kaka = PCALL_MULTI; - if(!top) - yyerror("function call must be single valued (%d)", et); - break; - case 0: - n->kaka = PCALL_NIL; - break; - case 1: - n->kaka = PCALL_SINGLE; - n->type = n->type->type->type; - break; - } - - r = n->right; - walktype(r, 0); - ascompatte(n->op, getinarg(t), &n->right); - goto ret; - - case OAS: - if(!top) - goto nottop; - - n->kaka = PAS_SINGLE; - r = n->left; - if(r != N && r->op == OLIST) - n->kaka = PAS_MULTI; - - walktype(r, 0); - - r = n->right; - if(r == N) - goto ret; - - if(r->op == OCALL && n->kaka == PAS_MULTI) { - walktype(r, 1); - if(r->kaka == PCALL_MULTI) { - ascompatet(n->op, &n->left, &r->type); - n->kaka = PAS_CALLM; - goto ret; - } - } - - walktype(n->right, 0); - ascompatee(n->op, &n->left, &n->right); - - if(n->kaka == PAS_SINGLE) { - t = n->right->type; - if(t != N && t->etype == TSTRUCT) - n->kaka = PAS_STRUCT; - } - goto ret; - - case OBREAK: - case OCONTINUE: - case OGOTO: - case OLABEL: - goto ret; - - case OXCASE: - yyerror("case statement out of place"); - n->op = OCASE; - - case OCASE: - n = n->left; - goto loop; - - case OXFALL: - yyerror("fallthrough statement out of place"); - n->op = OFALL; - - case OFALL: - goto ret; - - case OCONV: - walktype(n->left, 0); - if(n->left == N) - goto ret; - convlit(n->left, n->type); - if(eqtype(n->type, n->left->type, 0)) - *n = *n->left; - goto ret; - - case ORETURN: - walktype(n->left, 0); - ascompatte(n->op, getoutarg(curfn->type), &n->left); - goto ret; - - case ONOT: - walktype(n->left, 0); - if(n->left == N || n->left->type == N) - goto ret; - et = n->left->type->etype; - break; - - case OASOP: - if(!top) - goto nottop; - - case OLSH: - case ORSH: - case OMOD: - case OAND: - case OOR: - case OXOR: - case OANDAND: - case OOROR: - case OEQ: - case ONE: - case OLT: - case OLE: - case OGE: - case OGT: - case OADD: - case OSUB: - case OMUL: - case ODIV: - case OCAT: - walktype(n->left, 0); - walktype(n->right, 0); - if(n->left == N || n->right == N) - goto ret; - convlit(n->left, n->right->type); - convlit(n->right, n->left->type); - evconst(n); - if(n->op == OLITERAL) - goto ret; - if(n->left->type == N || n->right->type == N) - goto ret; - if(!ascompat(n->left->type, n->right->type)) - goto badt; - break; - - case OPLUS: - case OMINUS: - case OCOM: - walktype(n->left, 0); - if(n->left == N) - goto ret; - evconst(n); - ullmancalc(n); - if(n->op == OLITERAL) - goto ret; - break; - - case OLEN: - walktype(n->left, 0); - evconst(n); - ullmancalc(n); - t = n->left->type; - if(t != N && t->etype == TPTR) - t = t->type; - if(t == N) - goto ret; - switch(t->etype) { - default: - goto badt; - case TSTRING: - break; - } - n->type = types[TINT32]; - goto ret; - - case OINDEX: - case OINDEXPTR: - case OINDEXSTR: - case OINDEXMAP: - case OINDEXPTRMAP: - walktype(n->left, 0); - walktype(n->right, 0); - ullmancalc(n); - if(n->left == N || n->right == N) - goto ret; - t = n->left->type; - if(t == N) - goto ret; - - // map - left and right sides must match - if(t->etype == TMAP || isptrto(t, TMAP)) { - n->ullman = UINF; - n->op = OINDEXMAP; - if(isptrto(t, TMAP)) { - n->op = OINDEXPTRMAP; - t = t->type; - if(t == N) - goto ret; - } - convlit(n->right, t->down); - if(!ascompat(t->down, n->right->type)) - goto badt; - n->type = t->type; - goto ret; - } - - // right side must be an int - if(n->right->type == N) - convlit(n->right, types[TINT32]); - if(n->left->type == N || n->right->type == N) - goto ret; - if(!isint[n->right->type->etype]) - goto badt; - - // left side is string - if(isptrto(t, TSTRING)) { - n->op = OINDEXSTR; - n->type = types[TUINT8]; - goto ret; - } - - // left side is ptr to string - if(isptrto(t, TPTR) && isptrto(t->type, TSTRING)) { - n->op = OINDEXPTRSTR; - n->type = types[TUINT8]; - goto ret; - } - - // left side is array - if(t->etype == TPTR) { - t = t->type; - n->op = OINDEXPTR; - } - if(t->etype != TARRAY && t->etype != TDARRAY) - goto badt; - n->type = t->type; - goto ret; - - case OSLICE: - walkslice(n); - goto ret; - - case ODOT: - case ODOTPTR: - case ODOTMETH: - case ODOTINTER: - walkdot(n); - goto ret; - - case OADDR: - walktype(n->left, 0); - if(n->left == N) - goto ret; - t = n->left->type; - if(t == N) - goto ret; - n->type = ptrto(t); - goto ret; - - case OIND: - walktype(n->left, 0); - if(n->left == N) - goto ret; - t = n->left->type; - if(t == N) - goto ret; - if(t->etype != TPTR) - goto badt; - n->type = t->type; - goto ret; - - case ONEW: - if(n->left != N) - yyerror("dont know what new(,e) means"); - goto ret; - } - -/* - * ======== second switch ======== - */ - - switch(n->op) { - default: - fatal("walktype: switch 2 unknown op %N", n); - goto ret; - - case OASOP: - break; - - case ONOT: - case OANDAND: - case OOROR: - et = n->left->type->etype; - if(et != TBOOL) - goto badt; - t = types[TBOOL]; - break; - - case OEQ: - case ONE: - et = n->left->type->etype; - if(!okforeq[et]) - goto badt; - t = types[TBOOL]; - break; - - case OLT: - case OLE: - case OGE: - case OGT: - et = n->left->type->etype; - if(!okforadd[et]) - if(!isptrto(n->left->type, TSTRING)) - goto badt; - t = types[TBOOL]; - break; - - case OCAT: - case OADD: - if(isptrto(n->left->type, TSTRING)) { - n->op = OCAT; - break; - } - - case OSUB: - case OMUL: - case ODIV: - case OPLUS: - case OMINUS: - et = n->left->type->etype; - if(!okforadd[et]) - goto badt; - break; - - case OLSH: - case ORSH: - case OAND: - case OOR: - case OXOR: - case OMOD: - case OCOM: - et = n->left->type->etype; - if(!okforand[et]) - goto badt; - break; - } - - if(t == N) - t = n->left->type; - n->type = t; - ullmancalc(n); - goto ret; - -nottop: - fatal("walktype: not top %O", n->op); - -badt: - if(n->right == N) { - if(n->left == N) { - badtype(n->op, N, N); - goto ret; - } - badtype(n->op, n->left->type, N); - goto ret; - } - badtype(n->op, n->left->type, n->right->type); - goto ret; - -ret: - dynlineno = lno; -} - -/* - * return the first type - */ -Node* -sw1(Node *c, Node *place) -{ - if(place == N) - return c->type; - return place; -} - -/* - * return a suitable type - */ -Node* -sw2(Node *c, Node *place) -{ - return types[TINT32]; // botch -} - -/* - * check that selected type - * is compat with all the cases - */ -Node* -sw3(Node *c, Node *place) -{ - if(place == N) - return c->type; - if(c->type == N) - c->type = place; - convlit(c, place); - if(!ascompat(place, c->type)) - badtype(OSWITCH, place, c->type); - return place; -} - -Node* -walkswitch(Node *test, Node *body, Node*(*call)(Node*, Node*)) -{ - Node *n, *c; - Node *place; - - place = call(test, N); - - n = body; - if(n->op == OLIST) - n = n->left; - - for(; n!=N; n=n->right) { - if(n->op != OCASE) - fatal("walkswitch: not case %O\n", n->op); - for(c=n->left; c!=N; c=c->right) { - if(c->op != OLIST) { - place = call(c, place); - break; - } - place = call(c->left, place); - } - } - return place; -} - -int -casebody(Node *n) -{ - Node *oc, *ot, *t; - Iter save; - - - /* - * look to see if statements at top level have - * case labels attached to them. convert the illegal - * ops XFALL and XCASE into legal ops FALL and CASE. - * all unconverted ops will thus be caught as illegal - */ - - oc = N; // last case statement - ot = N; // last statement (look for XFALL) - - t = listfirst(&save, &n); - - if(t->op != OXCASE) - return 0; - -loop: - if(t == N) { - if(oc == N) - return 0; - return 1; - } - if(t->op == OXCASE) { - /* rewrite and link top level cases */ - t->op = OCASE; - if(oc != N) - oc->right = t; - oc = t; - - /* rewrite top fall that preceed case */ - if(ot != N && ot->op == OXFALL) - ot->op = OFALL; - } - - /* if first statement is not case then return 0 */ - if(oc == N) - return 0; - - ot = t; - t = listnext(&save); - goto loop; -} - -/* - * allowable type combinations for - * normal binary operations. - */ - -Node* -lookdot(Node *n, Node *t, int d) -{ - Node *r, *f, *c; - Sym *s; - int o; - - r = N; - s = n->sym; - if(d > 0) - goto deep; - - o = 0; - for(f=t->type; f!=N; f=f->down) { - f->kaka = o; - o++; - - if(f->sym == S) - continue; - if(f->sym != s) - continue; - if(r != N) { - yyerror("ambiguous DOT reference %s", s->name); - break; - } - r = f; - } - return r; - -deep: - /* deeper look after shallow failed */ - for(f=t->type; f!=N; f=f->down) { - // only look at unnamed sub-structures - // BOTCH no such thing -- all are assigned temp names - if(f->sym != S) - continue; - c = f->type; - if(c->etype != TSTRUCT) - continue; - c = lookdot(n, c, d-1); - if(c == N) - continue; - if(r != N) { - yyerror("ambiguous unnamed DOT reference %s", s->name); - break; - } - r = c; - } - return r; -} - -void -walkdot(Node *n) -{ - Node *t, *f; - int i; - - if(n->left == N || n->right == N) - return; - - walktype(n->left, 0); - if(n->right->op != ONAME) { - yyerror("rhs of . must be a name"); - return; - } - - t = n->left->type; - if(t == N) - return; - - if(t->etype == TPTR) { - t = t->type; - if(t == N) - return; - n->op = ODOTPTR; - } - - if(n->right->op != ONAME) - fatal("walkdot: not name %O", n->right->op); - - switch(t->etype) { - default: - badtype(ODOT, t, N); - return; - - case TSTRUCT: - case TINTER: - for(i=0; i<5; i++) { - f = lookdot(n->right, t, i); - if(f != N) - break; - } - if(f == N) { - yyerror("undefined DOT reference %N", n->right); - break; - } - n->right = f->nname; // substitute real name - n->type = f->type; - if(n->type->etype == TFUNC) { - n->op = ODOTMETH; - if(t->etype == TINTER) { - n->op = ODOTINTER; - n->kaka = f->kaka; - } - } - break; - } -} - -void -walkslice(Node *n) -{ - Node *l, *r; - - if(n->left == N || n->right == N) - return; - if(n->right->op != OLIST) - fatal("slice not a list"); - - walktype(n->left, 0); - if(isptrto(n->left->type, TSTRING)) { - n->op = OSLICESTR; - goto ok; - } - if(isptrto(n->left->type->type, TPTR) && isptrto(n->left->type->type, TSTRING)) { - n->op = OSLICEPTRSTR; - goto ok; - } - - badtype(OSLICE, n->left->type, N); - return; - -ok: - // check for type errors - walktype(n->right, 0); - l = n->right->left; - r = n->right->right; - convlit(l, types[TINT32]); - convlit(r, types[TINT32]); - if(l == N || r == N || - l->type == N || r->type == N) - return; - if(!isint[l->type->etype] || !isint[l->type->etype]) { - badtype(OSLICE, l->type, r->type); - return; - } - - // now convert to int32 - n->right->left = nod(OCONV, n->right->left, N); - n->right->left->type = types[TINT32]; - n->right->right = nod(OCONV, n->right->right, N); - n->right->right->type = types[TINT32]; - walktype(n->right, 0); - - n->type = n->left->type; -} - -/* - * test tuple type list against each other - * called in four contexts - * 1. a,b = c,d ...ee - * 2. a,b = fn() ...et - * 3. call(fn()) ...tt - * 4. call(a,b) ...te - */ -void -ascompatee(int op, Node **nl, Node **nr) -{ - Node *l, *r; - Iter savel, saver; - int sa, na; - - l = listfirst(&savel, nl); - r = listfirst(&saver, nr); - na = 0; // number of assignments - looking for multi - sa = 0; // one of the assignments is a structure assignment - -loop: - if(l == N || r == N) { - if(l != r) - yyerror("error in shape across assignment"); - if(sa != 0 && na > 1) - yyerror("cant do multi-struct assignments"); - return; - } - - convlit(r, l->type); - - if(!ascompat(l->type, r->type)) { - badtype(op, l->type, r->type); - return; - } - if(l->type != N && l->type->etype == TSTRUCT) - sa = 1; - - l = listnext(&savel); - r = listnext(&saver); - na++; - goto loop; -} - -void -ascompatet(int op, Node **nl, Node **nr) -{ - Node *l, *r; - Iter savel, saver; - - l = listfirst(&savel, nl); - r = structfirst(&saver, nr); - -loop: - if(l == N || r == N) { - if(l != r) - yyerror("error in shape across assignment"); - return; - } - - if(!ascompat(l->type, r->type)) { - badtype(op, l->type, r->type); - return; - } - - l = listnext(&savel); - r = structnext(&saver); - - goto loop; -} - -void -ascompatte(int op, Node **nl, Node **nr) -{ - Node *l, *r; - Iter savel, saver; - - l = structfirst(&savel, nl); - r = listfirst(&saver, nr); - -loop: - if(l == N || r == N) { - if(l != r) - yyerror("error in shape across assignment"); - return; - } - - convlit(r, l->type); - - if(!ascompat(l->type, r->type)) { - badtype(op, l->type, r->type); - return; - } - - l = structnext(&savel); - r = listnext(&saver); - - goto loop; -} - -void -ascompattt(int op, Node **nl, Node **nr) -{ - Node *l, *r; - Iter savel, saver; - - l = structfirst(&savel, nl); - r = structfirst(&saver, nr); - -loop: - if(l == N || r == N) { - if(l != r) - yyerror("error in shape across assignment"); - return; - } - - if(!ascompat(l->type, r->type)) { - badtype(op, l->type, r->type); - return; - } - - l = structnext(&savel); - r = structnext(&saver); - - goto loop; -} - -/* - * can we assign var of type t2 to var of type t1 - */ -int -ascompat(Node *t1, Node *t2) -{ - if(eqtype(t1, t2, 0)) - return 1; -// if(eqtype(t1, nilptr, 0)) -// return 1; -// if(eqtype(t2, nilptr, 0)) -// return 1; - if(isinter(t1)) - if(isptrto(t2, TSTRUCT) || isinter(t2)) - return 1; - if(isinter(t2)) - if(isptrto(t1, TSTRUCT)) - return 1; - return 0; -} - -void -prcompat(Node **n) -{ - Node *l, *t; - Iter save; - int w; - - l = listfirst(&save, n); - -loop: - if(l == N) - return; - - t = N; - w = whatis(l); - switch(w) { - default: - badtype((*n)->op, l->type, N); - break; - case Wtint: - case Wtfloat: - case Wtbool: - case Wtstr: - break; - case Wlitint: - t = types[TINT32]; - break; - case Wlitfloat: - t = types[TFLOAT64]; - break; - case Wlitbool: - t = types[TBOOL]; - break; - case Wlitstr: - t = types[TSTRING]; - break; - } - - if(t != N) - convlit(l, t); - - l = listnext(&save); - goto loop; -} |