summaryrefslogtreecommitdiff
path: root/src/old/c/walk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/old/c/walk.c')
-rw-r--r--src/old/c/walk.c978
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;
-}