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