diff options
Diffstat (limited to 'src/cmd/gc/dcl.c')
-rw-r--r-- | src/cmd/gc/dcl.c | 1248 |
1 files changed, 0 insertions, 1248 deletions
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c deleted file mode 100644 index 7290f9d3b..000000000 --- a/src/cmd/gc/dcl.c +++ /dev/null @@ -1,1248 +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" -#include "y.tab.h" - -static void funcargs(Node*); - -static int -dflag(void) -{ - if(!debug['d']) - return 0; - if(debug['y']) - return 1; - if(incannedimport) - return 0; - return 1; -} - -/* - * declaration stack & operations - */ - -static void -dcopy(Sym *a, Sym *b) -{ - a->pkg = b->pkg; - a->name = b->name; - a->def = b->def; - a->block = b->block; - a->lastlineno = b->lastlineno; -} - -static Sym* -push(void) -{ - Sym *d; - - d = mal(sizeof(*d)); - d->lastlineno = lineno; - d->link = dclstack; - dclstack = d; - return d; -} - -static Sym* -pushdcl(Sym *s) -{ - Sym *d; - - d = push(); - dcopy(d, s); - if(dflag()) - print("\t%L push %S %p\n", lineno, s, s->def); - return d; -} - -void -popdcl(void) -{ - Sym *d, *s; - int lno; - -// if(dflag()) -// print("revert\n"); - - for(d=dclstack; d!=S; d=d->link) { - if(d->name == nil) - break; - s = pkglookup(d->name, d->pkg); - lno = s->lastlineno; - dcopy(s, d); - d->lastlineno = lno; - if(dflag()) - print("\t%L pop %S %p\n", lineno, s, s->def); - } - if(d == S) - fatal("popdcl: no mark"); - dclstack = d->link; - block = d->block; -} - -void -poptodcl(void) -{ - // pop the old marker and push a new one - // (cannot reuse the existing one) - // because we use the markers to identify blocks - // for the goto restriction checks. - popdcl(); - markdcl(); -} - -void -markdcl(void) -{ - Sym *d; - - d = push(); - d->name = nil; // used as a mark in fifo - d->block = block; - - blockgen++; - block = blockgen; - -// if(dflag()) -// print("markdcl\n"); -} - -void -dumpdcl(char *st) -{ - Sym *s, *d; - int i; - - i = 0; - for(d=dclstack; d!=S; d=d->link) { - i++; - print(" %.2d %p", i, d); - if(d->name == nil) { - print("\n"); - continue; - } - print(" '%s'", d->name); - s = pkglookup(d->name, d->pkg); - print(" %lS\n", s); - } -} - -void -testdclstack(void) -{ - Sym *d; - - for(d=dclstack; d!=S; d=d->link) { - if(d->name == nil) { - yyerror("mark left on the stack"); - continue; - } - } -} - -void -redeclare(Sym *s, char *where) -{ - if(s->lastlineno == 0) - yyerror("%S redeclared %s\n" - "\tprevious declaration during import", - s, where); - else - yyerror("%S redeclared %s\n" - "\tprevious declaration at %L", - s, where, s->lastlineno); -} - -/* - * declare individual names - var, typ, const - */ -void -declare(Node *n, int ctxt) -{ - Sym *s; - int gen; - static int typegen, vargen; - - if(isblank(n)) - return; - - n->lineno = parserline(); - s = n->sym; - gen = 0; - if(ctxt == PEXTERN) { - externdcl = list(externdcl, n); - if(dflag()) - print("\t%L global decl %S %p\n", lineno, s, n); - } else { - if(curfn == nil && ctxt == PAUTO) - fatal("automatic outside function"); - if(curfn != nil) - curfn->dcl = list(curfn->dcl, n); - if(n->op == OTYPE) - gen = ++typegen; - else if(n->op == ONAME) - gen = ++vargen; - pushdcl(s); - n->curfn = curfn; - } - if(ctxt == PAUTO) - n->xoffset = BADWIDTH; - - if(s->block == block) - redeclare(s, "in this block"); - - s->block = block; - s->lastlineno = parserline(); - s->def = n; - n->vargen = gen; - n->funcdepth = funcdepth; - n->class = ctxt; - - autoexport(n, ctxt); -} - -void -addvar(Node *n, Type *t, int ctxt) -{ - if(n==N || n->sym == S || (n->op != ONAME && n->op != ONONAME) || t == T) - fatal("addvar: n=%N t=%T nil", n, t); - - n->op = ONAME; - declare(n, ctxt); - n->type = t; -} - -/* - * declare variables from grammar - * new_name_list (type | [type] = expr_list) - */ -NodeList* -variter(NodeList *vl, Node *t, NodeList *el) -{ - int doexpr; - Node *v, *e, *as2; - NodeList *init; - - init = nil; - doexpr = el != nil; - - if(count(el) == 1 && count(vl) > 1) { - e = el->n; - as2 = nod(OAS2, N, N); - as2->list = vl; - as2->rlist = list1(e); - for(; vl; vl=vl->next) { - v = vl->n; - v->op = ONAME; - declare(v, dclcontext); - v->ntype = t; - v->defn = as2; - if(funcdepth > 0) - init = list(init, nod(ODCL, v, N)); - } - return list(init, as2); - } - - for(; vl; vl=vl->next) { - if(doexpr) { - if(el == nil) { - yyerror("missing expr in var dcl"); - break; - } - e = el->n; - el = el->next; - } else - e = N; - - v = vl->n; - v->op = ONAME; - declare(v, dclcontext); - v->ntype = t; - - if(e != N || funcdepth > 0 || isblank(v)) { - if(funcdepth > 0) - init = list(init, nod(ODCL, v, N)); - e = nod(OAS, v, e); - init = list(init, e); - if(e->right != N) - v->defn = e; - } - } - if(el != nil) - yyerror("extra expr in var dcl"); - return init; -} - -/* - * declare constants from grammar - * new_name_list [[type] = expr_list] - */ -NodeList* -constiter(NodeList *vl, Node *t, NodeList *cl) -{ - Node *v, *c; - NodeList *vv; - - vv = nil; - if(cl == nil) { - if(t != N) - yyerror("constdcl cannot have type without expr"); - cl = lastconst; - t = lasttype; - } else { - lastconst = cl; - lasttype = t; - } - cl = listtreecopy(cl); - - for(; vl; vl=vl->next) { - if(cl == nil) { - yyerror("missing expr in const dcl"); - break; - } - c = cl->n; - cl = cl->next; - - v = vl->n; - v->op = OLITERAL; - declare(v, dclcontext); - - v->ntype = t; - v->defn = c; - - vv = list(vv, nod(ODCLCONST, v, N)); - } - if(cl != nil) - yyerror("extra expr in const dcl"); - iota += 1; - return vv; -} - -/* - * this generates a new name node, - * typically for labels or other one-off names. - */ -Node* -newname(Sym *s) -{ - Node *n; - - if(s == S) - fatal("newname nil"); - - n = nod(ONAME, N, N); - n->sym = s; - n->type = T; - n->addable = 1; - n->ullman = 1; - n->xoffset = 0; - return n; -} - -/* - * this generates a new name node for a name - * being declared. - */ -Node* -dclname(Sym *s) -{ - Node *n; - - n = newname(s); - n->op = ONONAME; // caller will correct it - return n; -} - -Node* -typenod(Type *t) -{ - // if we copied another type with *t = *u - // then t->nod might be out of date, so - // check t->nod->type too - if(t->nod == N || t->nod->type != t) { - t->nod = nod(OTYPE, N, N); - t->nod->type = t; - t->nod->sym = t->sym; - } - return t->nod; -} - - -/* - * this will return an old name - * that has already been pushed on the - * declaration list. a diagnostic is - * generated if no name has been defined. - */ -Node* -oldname(Sym *s) -{ - Node *n; - Node *c; - - n = s->def; - if(n == N) { - // maybe a top-level name will come along - // to give this a definition later. - // walkdef will check s->def again once - // all the input source has been processed. - n = newname(s); - n->op = ONONAME; - n->iota = iota; // save current iota value in const declarations - } - if(curfn != nil && n->funcdepth > 0 && n->funcdepth != funcdepth && n->op == ONAME) { - // inner func is referring to var in outer func. - // - // TODO(rsc): If there is an outer variable x and we - // are parsing x := 5 inside the closure, until we get to - // the := it looks like a reference to the outer x so we'll - // make x a closure variable unnecessarily. - if(n->closure == N || n->closure->funcdepth != funcdepth) { - // create new closure var. - c = nod(ONAME, N, N); - c->sym = s; - c->class = PPARAMREF; - c->isddd = n->isddd; - c->defn = n; - c->addable = 0; - c->ullman = 2; - c->funcdepth = funcdepth; - c->outer = n->closure; - n->closure = c; - c->closure = n; - c->xoffset = 0; - curfn->cvars = list(curfn->cvars, c); - } - // return ref to closure var, not original - return n->closure; - } - return n; -} - -/* - * same for types - */ -Type* -newtype(Sym *s) -{ - Type *t; - - t = typ(TFORW); - t->sym = s; - t->type = T; - return t; -} - - -/* - * := declarations - */ - -static int -colasname(Node *n) -{ - switch(n->op) { - case ONAME: - case ONONAME: - case OPACK: - case OTYPE: - case OLITERAL: - return n->sym != S; - } - return 0; -} - -void -colasdefn(NodeList *left, Node *defn) -{ - int nnew; - NodeList *l; - Node *n; - - nnew = 0; - for(l=left; l; l=l->next) { - n = l->n; - if(isblank(n)) - continue; - if(!colasname(n)) { - yyerror("non-name %#N on left side of :=", n); - continue; - } - if(n->sym->block == block) - continue; - - nnew++; - n = newname(n->sym); - declare(n, dclcontext); - n->defn = defn; - defn->ninit = list(defn->ninit, nod(ODCL, n, N)); - l->n = n; - } - if(nnew == 0) - yyerror("no new variables on left side of :="); -} - -Node* -colas(NodeList *left, NodeList *right) -{ - Node *as; - - as = nod(OAS2, N, N); - as->list = left; - as->rlist = right; - as->colas = 1; - colasdefn(left, as); - - // make the tree prettier; not necessary - if(count(left) == 1 && count(right) == 1) { - as->left = as->list->n; - as->right = as->rlist->n; - as->list = nil; - as->rlist = nil; - as->op = OAS; - } - - return as; -} - -/* - * declare the arguments in an - * interface field declaration. - */ -void -ifacedcl(Node *n) -{ - if(n->op != ODCLFIELD || n->right == N) - fatal("ifacedcl"); - - dclcontext = PAUTO; - markdcl(); - funcdepth++; - n->outer = curfn; - curfn = n; - funcargs(n->right); - - // funcbody is normally called after the parser has - // seen the body of a function but since an interface - // field declaration does not have a body, we must - // call it now to pop the current declaration context. - funcbody(n); -} - -/* - * declare the function proper - * and declare the arguments. - * called in extern-declaration context - * returns in auto-declaration context. - */ -void -funchdr(Node *n) -{ - - if(n->nname != N) { - n->nname->op = ONAME; - declare(n->nname, PFUNC); - n->nname->defn = n; - } - - // change the declaration context from extern to auto - if(funcdepth == 0 && dclcontext != PEXTERN) - fatal("funchdr: dclcontext"); - - dclcontext = PAUTO; - markdcl(); - funcdepth++; - - n->outer = curfn; - curfn = n; - if(n->nname) - funcargs(n->nname->ntype); - else - funcargs(n->ntype); -} - -static void -funcargs(Node *nt) -{ - Node *n; - NodeList *l; - int gen; - - if(nt->op != OTFUNC) - fatal("funcargs %O", nt->op); - - // declare the receiver and in arguments. - // no n->defn because type checking of func header - // will fill in the types before we can demand them. - if(nt->left != N) { - n = nt->left; - if(n->op != ODCLFIELD) - fatal("funcargs1 %O", n->op); - if(n->left != N) { - n->left->op = ONAME; - n->left->ntype = n->right; - declare(n->left, PPARAM); - } - } - for(l=nt->list; l; l=l->next) { - n = l->n; - if(n->op != ODCLFIELD) - fatal("funcargs2 %O", n->op); - if(n->left != N) { - n->left->op = ONAME; - n->left->ntype = n->right; - declare(n->left, PPARAM); - } - } - - // declare the out arguments. - gen = 0; - for(l=nt->rlist; l; l=l->next) { - n = l->n; - if(n->op != ODCLFIELD) - fatal("funcargs3 %O", n->op); - if(n->left != N) { - n->left->op = ONAME; - n->left->ntype = n->right; - if(isblank(n->left)) { - // Give it a name so we can assign to it during return. - snprint(namebuf, sizeof(namebuf), ".anon%d", gen++); - n->left->sym = lookup(namebuf); - } - declare(n->left, PPARAMOUT); - } - } -} - -/* - * finish the body. - * called in auto-declaration context. - * returns in extern-declaration context. - */ -void -funcbody(Node *n) -{ - // change the declaration context from auto to extern - if(dclcontext != PAUTO) - fatal("funcbody: dclcontext"); - popdcl(); - funcdepth--; - curfn = n->outer; - n->outer = N; - if(funcdepth == 0) - dclcontext = PEXTERN; -} - -/* - * new type being defined with name s. - */ -Node* -typedcl0(Sym *s) -{ - Node *n; - - n = dclname(s); - n->op = OTYPE; - declare(n, dclcontext); - return n; -} - -/* - * node n, which was returned by typedcl0 - * is being declared to have uncompiled type t. - * return the ODCLTYPE node to use. - */ -Node* -typedcl1(Node *n, Node *t, int local) -{ - n->ntype = t; - n->local = local; - return nod(ODCLTYPE, n, N); -} - -/* - * typedcl1 but during imports - */ -void -typedcl2(Type *pt, Type *t) -{ - Node *n; - - // override declaration in unsafe.go for Pointer. - // there is no way in Go code to define unsafe.Pointer - // so we have to supply it. - if(incannedimport && - strcmp(importpkg->name, "unsafe") == 0 && - strcmp(pt->nod->sym->name, "Pointer") == 0) { - t = types[TUNSAFEPTR]; - } - - if(pt->etype == TFORW) - goto ok; - if(!eqtype(pt->orig, t)) - yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt->orig, t); - return; - -ok: - n = pt->nod; - copytype(pt->nod, t); - // unzero nod - pt->nod = n; - - pt->sym->lastlineno = parserline(); - declare(n, PEXTERN); - - checkwidth(pt); -} - -/* - * structs, functions, and methods. - * they don't belong here, but where do they belong? - */ - - -/* - * turn a parsed struct into a type - */ -static Type** -stotype(NodeList *l, int et, Type **t, int funarg) -{ - Type *f, *t1, *t2, **t0; - Strlit *note; - int lno; - Node *n, *left; - char *what; - - t0 = t; - lno = lineno; - what = "field"; - if(et == TINTER) - what = "method"; - - for(; l; l=l->next) { - n = l->n; - lineno = n->lineno; - note = nil; - - if(n->op != ODCLFIELD) - fatal("stotype: oops %N\n", n); - left = n->left; - if(funarg && isblank(left)) - left = N; - if(n->right != N) { - if(et == TINTER && left != N) { - // queue resolution of method type for later. - // right now all we need is the name list. - // avoids cycles for recursive interface types. - n->type = typ(TINTERMETH); - n->type->nname = n->right; - n->right = N; - left->type = n->type; - queuemethod(n); - } else { - typecheck(&n->right, Etype); - n->type = n->right->type; - if(n->type == T) { - *t0 = T; - return t0; - } - if(left != N) - left->type = n->type; - n->right = N; - if(n->embedded && n->type != T) { - t1 = n->type; - if(t1->sym == S && isptr[t1->etype]) { - t1 = t1->type; - if(t1->etype == TINTER) - yyerror("embedded type cannot be a pointer to interface"); - } - if(isptr[t1->etype]) - yyerror("embedded type cannot be a pointer"); - else if(t1->etype == TFORW && t1->embedlineno == 0) - t1->embedlineno = lineno; - } - } - } - - if(n->type == T) { - // assume error already printed - continue; - } - - switch(n->val.ctype) { - case CTSTR: - if(et != TSTRUCT) - yyerror("interface method cannot have annotation"); - note = n->val.u.sval; - break; - default: - if(et != TSTRUCT) - yyerror("interface method cannot have annotation"); - else - yyerror("field annotation must be string"); - case CTxxx: - note = nil; - break; - } - - if(et == TINTER && left == N) { - // embedded interface - inline the methods - if(n->type->etype != TINTER) { - if(n->type->etype == TFORW) - yyerror("interface type loop involving %T", n->type); - else - yyerror("interface contains embedded non-interface %T", n->type); - continue; - } - for(t1=n->type->type; t1!=T; t1=t1->down) { - f = typ(TFIELD); - f->type = t1->type; - f->width = BADWIDTH; - f->nname = newname(t1->sym); - f->sym = t1->sym; - for(t2=*t0; t2!=T; t2=t2->down) { - if(t2->sym == f->sym) { - yyerror("duplicate method %s", t2->sym->name); - break; - } - } - *t = f; - t = &f->down; - } - continue; - } - - f = typ(TFIELD); - f->type = n->type; - f->note = note; - f->width = BADWIDTH; - f->isddd = n->isddd; - - if(left != N && left->op == ONAME) { - f->nname = left; - f->embedded = n->embedded; - f->sym = f->nname->sym; - if(importpkg && !exportname(f->sym->name)) - f->sym = pkglookup(f->sym->name, structpkg); - if(f->sym && !isblank(f->nname)) { - for(t1=*t0; t1!=T; t1=t1->down) { - if(t1->sym == f->sym) { - yyerror("duplicate %s %s", what, t1->sym->name); - break; - } - } - } - } - - *t = f; - t = &f->down; - } - - *t = T; - lineno = lno; - return t; -} - -Type* -dostruct(NodeList *l, int et) -{ - Type *t; - int funarg; - - /* - * convert a parsed id/type list into - * a type for struct/interface/arglist - */ - - funarg = 0; - if(et == TFUNC) { - funarg = 1; - et = TSTRUCT; - } - t = typ(et); - t->funarg = funarg; - stotype(l, et, &t->type, funarg); - if(t->type == T && l != nil) { - t->broke = 1; - return t; - } - if(et == TINTER) - t = sortinter(t); - if(!funarg) - checkwidth(t); - return t; -} - - -Node* -embedded(Sym *s) -{ - Node *n; - char *name; - - // Names sometimes have disambiguation junk - // appended after a center dot. Discard it when - // making the name for the embedded struct field. - enum { CenterDot = 0xB7 }; - name = s->name; - if(utfrune(s->name, CenterDot)) { - name = strdup(s->name); - *utfrune(name, CenterDot) = 0; - } - - n = newname(lookup(name)); - n = nod(ODCLFIELD, n, oldname(s)); - n->embedded = 1; - return n; -} - -/* - * check that the list of declarations is either all anonymous or all named - */ - -static Node* -findtype(NodeList *l) -{ - for(; l; l=l->next) - if(l->n->op == OKEY) - return l->n->right; - return N; -} - -NodeList* -checkarglist(NodeList *all, int input) -{ - int named; - Node *n, *t, *nextt; - NodeList *l; - - named = 0; - for(l=all; l; l=l->next) { - if(l->n->op == OKEY) { - named = 1; - break; - } - } - if(named) { - n = N; - for(l=all; l; l=l->next) { - n = l->n; - if(n->op != OKEY && n->sym == S) { - yyerror("mixed named and unnamed function parameters"); - break; - } - } - if(l == nil && n != N && n->op != OKEY) - yyerror("final function parameter must have type"); - } - - nextt = nil; - for(l=all; l; l=l->next) { - // can cache result from findtype to avoid - // quadratic behavior here, but unlikely to matter. - n = l->n; - if(named) { - if(n->op == OKEY) { - t = n->right; - n = n->left; - nextt = nil; - } else { - if(nextt == nil) - nextt = findtype(l); - t = nextt; - } - } else { - t = n; - n = N; - } - if(n != N && n->sym == S) { - t = n; - n = N; - } - if(n != N) - n = newname(n->sym); - n = nod(ODCLFIELD, n, t); - if(n->right != N && n->right->op == ODDD) { - if(!input) - yyerror("cannot use ... in output argument list"); - else if(l->next != nil) - yyerror("can only use ... as final argument in list"); - n->right->op = OTARRAY; - n->right->right = n->right->left; - n->right->left = N; - n->isddd = 1; - if(n->left != N) - n->left->isddd = 1; - } - l->n = n; - } - return all; -} - - -Node* -fakethis(void) -{ - Node *n; - - n = nod(ODCLFIELD, N, typenod(ptrto(typ(TSTRUCT)))); - return n; -} - -/* - * Is this field a method on an interface? - * Those methods have an anonymous - * *struct{} as the receiver. - * (See fakethis above.) - */ -int -isifacemethod(Type *f) -{ - Type *rcvr; - Type *t; - - rcvr = getthisx(f)->type; - if(rcvr->sym != S) - return 0; - t = rcvr->type; - if(!isptr[t->etype]) - return 0; - t = t->type; - if(t->sym != S || t->etype != TSTRUCT || t->type != T) - return 0; - return 1; -} - -/* - * turn a parsed function declaration - * into a type - */ -Type* -functype(Node *this, NodeList *in, NodeList *out) -{ - Type *t; - NodeList *rcvr; - - t = typ(TFUNC); - - rcvr = nil; - if(this) - rcvr = list1(this); - t->type = dostruct(rcvr, TFUNC); - t->type->down = dostruct(out, TFUNC); - t->type->down->down = dostruct(in, TFUNC); - - if(this) - t->thistuple = 1; - t->outtuple = count(out); - t->intuple = count(in); - t->outnamed = t->outtuple > 0 && out->n->left != N; - - return t; -} - -Sym* -methodsym(Sym *nsym, Type *t0, int iface) -{ - Sym *s; - char *p; - Type *t; - char *suffix; - - t = t0; - if(t == T) - goto bad; - s = t->sym; - if(s == S) { - if(!isptr[t->etype]) - goto bad; - t = t->type; - if(t == T) - goto bad; - s = t->sym; - if(s == S) - goto bad; - } - - // if t0 == *t and t0 has a sym, - // we want to see *t, not t0, in the method name. - if(t != t0 && t0->sym) - t0 = ptrto(t); - - suffix = ""; - if(iface) { - dowidth(t0); - if(t0->width < types[tptr]->width) - suffix = "·i"; - } - p = smprint("%#hT·%s%s", t0, nsym->name, suffix); - s = pkglookup(p, s->pkg); - free(p); - return s; - -bad: - yyerror("illegal receiver type: %T", t0); - return S; -} - -Node* -methodname(Node *n, Type *t) -{ - Sym *s; - - s = methodsym(n->sym, t, 0); - if(s == S) - return n; - return newname(s); -} - -Node* -methodname1(Node *n, Node *t) -{ - char *star; - char *p; - - star = ""; - if(t->op == OIND) { - star = "*"; - t = t->left; - } - if(t->sym == S || isblank(n)) - return newname(n->sym); - p = smprint("%s%S·%S", star, t->sym, n->sym); - n = newname(pkglookup(p, t->sym->pkg)); - free(p); - return n; -} - -/* - * add a method, declared as a function, - * n is fieldname, pa is base type, t is function type - */ -void -addmethod(Sym *sf, Type *t, int local) -{ - Type *f, *d, *pa; - Node *n; - - pa = nil; - - // get field sym - if(sf == S) - fatal("no method symbol"); - - // get parent type sym - pa = getthisx(t)->type; // ptr to this structure - if(pa == T) { - yyerror("missing receiver"); - return; - } - - pa = pa->type; - f = methtype(pa); - if(f == T) { - t = pa; - if(t != T) { - if(isptr[t->etype]) { - if(t->sym != S) { - yyerror("invalid receiver type %T (%T is a pointer type)", pa, t); - return; - } - t = t->type; - } - } - if(t != T) { - if(t->sym == S) { - yyerror("invalid receiver type %T (%T is an unnamed type)", pa, t); - return; - } - if(isptr[t->etype]) { - yyerror("invalid receiver type %T (%T is a pointer type)", pa, t); - return; - } - if(t->etype == TINTER) { - yyerror("invalid receiver type %T (%T is an interface type)", pa, t); - return; - } - } - // Should have picked off all the reasons above, - // but just in case, fall back to generic error. - yyerror("invalid receiver type %T", pa); - return; - } - - pa = f; - if(importpkg && !exportname(sf->name)) - sf = pkglookup(sf->name, importpkg); - - n = nod(ODCLFIELD, newname(sf), N); - n->type = t; - - d = T; // last found - for(f=pa->method; f!=T; f=f->down) { - d = f; - if(f->etype != TFIELD) - fatal("addmethod: not TFIELD: %N", f); - if(strcmp(sf->name, f->sym->name) != 0) - continue; - if(!eqtype(t, f->type)) - yyerror("method redeclared: %T.%S\n\t%T\n\t%T", pa, sf, f->type, t); - return; - } - - if(local && !pa->local) { - // defining method on non-local type. - yyerror("cannot define new methods on non-local type %T", pa); - return; - } - - if(d == T) - stotype(list1(n), 0, &pa->method, 0); - else - stotype(list1(n), 0, &d->down, 0); - return; -} - -void -funccompile(Node *n, int isclosure) -{ - stksize = BADWIDTH; - maxarg = 0; - - if(n->type == T) { - if(nerrors == 0) - fatal("funccompile missing type"); - return; - } - - // assign parameter offsets - checkwidth(n->type); - - // record offset to actual frame pointer. - // for closure, have to skip over leading pointers and PC slot. - nodfp->xoffset = 0; - if(isclosure) { - NodeList *l; - for(l=n->nname->ntype->list; l; l=l->next) { - nodfp->xoffset += widthptr; - if(l->n->left == N) // found slot for PC - break; - } - } - - if(curfn) - fatal("funccompile %S inside %S", n->nname->sym, curfn->nname->sym); - - stksize = 0; - dclcontext = PAUTO; - funcdepth = n->funcdepth + 1; - compile(n); - curfn = nil; - funcdepth = 0; - dclcontext = PEXTERN; -} - - - |