switch(t->etype) {
default:
- fatal("signame: unknown type %T", t);
+ e = "sigs";
+ break;
case TPTR32:
case TPTR64:
t = t->type;
goto loop;
+
case TSTRUCT:
- e = "sigs";
- break;
case TINTER:
e = "sigi";
break;
a = nil;
o = 0;
- for(f=t->type; f!=T; f=f->down) {
+
+ f = t->type;
+ if(et != TINTER)
+ f = t->method;
+
+ for(; f!=T; f=f->down) {
if(f->type->etype != TFUNC)
continue;
a->name = sp+1;
a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
- a->sym = f->sym;
a->offset = o;
+ snprint(namebuf, sizeof(namebuf), "%s_%s",
+ at.sym->name+5, f->sym->name);
+ a->sym = lookup(namebuf);
+
o++;
}
{
Sym *s;
+ if(t == T)
+ goto bad;
+
+ // method receiver must be typename or *typename
s = S;
if(t->sym != S)
s = t->sym;
t = t->type;
if(t->sym != S)
s = t->sym;
-
-// if(t->etype != TSTRUCT)
-// goto bad;
-
if(s == S)
goto bad;
+
snprint(namebuf, sizeof(namebuf), "%s_%s", s->name, n->sym->name);
return newname(lookup(namebuf));
/*
* add a method, declared as a function,
- * into the structure
+ * n is fieldname, pa is base type, t is function type
*/
void
-addmethod(Node *n, Type *pa, Type *t)
+addmethod(Node *n, Type *t, int local)
{
- Type *f, *d, *p;
- Sym *s;
+ Type *f, *d, *pa;
+ Sym *st, *sf;
+ int ptr;
+ // get field sym
+ if(n == N)
+ goto bad;
if(n->op != ONAME)
goto bad;
- s = n->sym;
- if(s == S)
+ sf = n->sym;
+ if(sf == S)
goto bad;
+
+ // get parent type sym
+ pa = *getthis(t); // ptr to this structure
if(pa == T)
goto bad;
- if(!isptr[pa->etype])
- goto bad;
- p = pa->type;
- if(p == T)
- goto bad;
- if(p->etype != TSTRUCT)
+ pa = pa->type; // ptr to this field
+ if(pa == T)
goto bad;
- if(p->sym == S)
+ pa = pa->type; // ptr to this type
+ if(pa == T)
goto bad;
- if(p->type == T) {
- n = nod(ODCLFIELD, newname(s), N);
- n->type = t;
+ // optionally rip off ptr to type
+ ptr = 0;
+ if(isptr[pa->etype]) {
+ if(pa->sym == S || pa->sym->name[0] == '_') {
+ ptr = 1;
+ pa = pa->type;
+ if(pa == T)
+ goto bad;
+ }
+ }
+ if(pa->etype == TINTER)
+ yyerror("no methods on interfaces");
- stotype(n, &p->type);
+ // and finally the receiver sym
+ st = pa->sym;
+ if(st == S)
+ goto bad;
+ if(local && !st->local) {
+ yyerror("method receiver type must be locally defined: %S", st);
return;
}
+ n = nod(ODCLFIELD, newname(sf), N);
+ n->type = t;
+
+ if(pa->method == T)
+ pa->methptr = ptr;
+ if(pa->methptr != ptr)
+ yyerror("combination of direct and ptr receivers of: %S", st);
+
d = T; // last found
- for(f=p->type; f!=T; f=f->down) {
+ for(f=pa->method; f!=T; f=f->down) {
if(f->etype != TFIELD)
fatal("addmethod: not TFIELD: %N", f);
- if(strcmp(s->name, f->sym->name) != 0) {
+ if(strcmp(sf->name, f->sym->name) != 0) {
d = f;
continue;
}
-
- // if a field matches a non-this function
- // then delete it and let it be redeclared
- if(methcmp(t, f->type)) {
- if(d == T) {
- p->type = f->down;
- continue;
- }
- d->down = f->down;
- continue;
- }
if(!eqtype(t, f->type, 0))
- yyerror("field redeclared as method: %S", s);
- return;
+ yyerror("method redeclared: %S of type %S", sf, st);
}
- n = nod(ODCLFIELD, newname(s), N);
- n->type = t;
-
if(d == T)
- stotype(n, &p->type);
+ stotype(n, &pa->method);
else
stotype(n, &d->down);
+
+ if(dflag())
+ print("method %S of type %s%S\n", sf, (ptr? "*":""), st);
return;
bad:
markdcl();
funcargs(n->type);
- if(n->type->thistuple > 0) {
- Type *t;
- t = *getthis(n->type);
- addmethod(n->nname, t->type->type, n->type);
- }
}
void
Bprint(bout, "%lS %d %lS\n", s, t->chan, t->type->sym);
break;
}
+
+ for(f=t->method; f!=T; f=f->down) {
+ if(f->etype != TFIELD)
+ fatal("dumpexporttype: method not field: %lT", f);
+ reexport(f->type);
+ Bprint(bout, "\tfunc %S %lS\n", f->sym, f->type->sym);
+ }
}
void
t->thistuple = importcount(t->type);
t->outtuple = importcount(t->type->down);
t->intuple = importcount(t->type->down->down);
-
dowidth(t);
importfuncnam(t);
importaddtyp(ss, t);
}
+
+/*
+ * LFUNC importsym sym
+ * method type
+ */
+void
+doimport9(Sym *sf, Node *ss)
+{
+ Sym *sfun;
+
+ sfun = getimportsym(ss);
+ addmethod(newname(sf), sfun->otype, 0);
+}
uchar chan;
uchar recur; // to detect loops
uchar trecur; // to detect loops
+ uchar methptr; // all methods are pointers to this type
// TFUNCT
uchar thistuple;
uchar intuple;
uchar outnamed;
+ Type* method;
+
Sym* sym;
int32 vargen; // unique name for OTYPE/ONAME
+ Node* nname;
+ vlong argwid;
+
// most nodes
Type* type;
vlong width; // offset in TFIELD, width in all others
// TPTR
Type* nforw;
- // TFUNCT
- Node* nname;
- vlong argwid;
-
// TARRAY
int32 bound; // negative is dynamic array
};
void dodclconst(Node*, Node*);
void defaultlit(Node*);
int listcount(Node*);
+void addmethod(Node*, Type*, int);
Node* methodname(Node*, Type*);
Type* functype(Node*, Node*, Node*);
char* thistypenam(Node*);
void doimport6(Node*, Node*);
void doimport7(Node*, Node*);
void doimport8(Node*, Val*, Node*);
+void doimport9(Sym*, Node*);
/*
* walk.c
int casebody(Node*);
void walkselect(Node*);
int whatis(Node*);
-void walkdot(Node*, int);
+void walkdot(Node*);
Node* ascompatee(int, Node**, Node**);
Node* ascompatet(int, Node**, Type**, int);
Node* ascompatte(int, Type**, Node**, int);
| '(' oarg_type_list ')' new_name '(' oarg_type_list ')' fnres
{
b0stack = dclstack; // mark base for fn literals
- if($2 == N || $2->op == OLIST)
- yyerror("syntax error in method receiver");
$$ = nod(ODCLFUNC, N, N);
$$->nname = methodname($4, $2->type);
$$->type = functype($2, $6, $8);
funchdr($$);
+
+ addmethod($4, $$->type, 1);
}
fntype:
// type interface
doimport8($2, &$3, $4);
}
+| LFUNC sym1 hidden_importsym
+ {
+ // method
+ doimport9($2, $3);
+ }
isym:
sym1 '.' sym2
walkret(Node *n)
{
- // until gri gets rid
- // of the bugs on this
- return 0;
-
loop:
if(n != N)
switch(n->op) {
case ODOTINTER:
if(top == Etop)
goto nottop;
- walkdot(n, top);
+ walkdot(n);
goto ret;
case OADDR:
* normal binary operations.
*/
Type*
-lookdot(Node *n, Type *t, int d)
+lookdot(Node *n, Type *f)
{
- Type *f, *r, *c;
+ Type *r, *c;
Sym *s;
r = T;
s = n->sym;
- if(d > 0)
- goto deep;
- for(f=t->type; f!=T; f=f->down) {
+ for(; f!=T; f=f->down) {
if(f->sym == S)
continue;
if(f->sym != s)
r = f;
}
return r;
-
-deep:
- /* deeper look after shallow failed */
- for(f=t->type; f!=T; 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 == T)
- continue;
- if(r != T) {
- yyerror("ambiguous unnamed DOT reference %s", s->name);
- break;
- }
- r = c;
- }
- return r;
}
void
-walkdot(Node *n, int top)
+walkdot(Node *n)
{
Node *mn;
Type *t, *f;
- int i;
if(n->left == N || n->right == N)
return;
+ if(n->op == ODOTINTER || n->op == ODOTMETH)
+ return; // already done
walktype(n->left, Erv);
if(n->right->op != ONAME) {
n->op = ODOTPTR;
}
- if(n->right->op != ONAME)
- fatal("walkdot: not name %O", n->right->op);
-
- switch(t->etype) {
- default:
- badtype(ODOT, t, T);
- return;
-
- case TSTRUCT:
- case TINTER:
- for(i=0; i<5; i++) {
- f = lookdot(n->right, t, i);
- if(f != T)
- break;
- }
-
- // look up the field as TYPE_name
- // for a mothod. botch this should
- // be done better.
- if(f == T && t->etype == TSTRUCT) {
- mn = methodname(n->right, t);
- for(i=0; i<5; i++) {
- f = lookdot(mn, t, i);
- if(f != T)
- break;
- }
- }
-
- if(f == T) {
- yyerror("undefined DOT reference %N", n->right);
- break;
- }
-
- n->xoffset = f->width;
- n->right = f->nname; // substitute real name
- n->type = f->type;
- if(n->type->etype == TFUNC) {
- n->op = ODOTMETH;
- if(t->etype == TINTER) {
+ // as a structure field
+ if(t->etype == TSTRUCT || t->etype == TINTER) {
+ f = lookdot(n->right, t->type);
+ if(f != T) {
+ n->xoffset = f->width;
+ n->right = f->nname; // substitute real name
+ n->type = f->type;
+ if(t->etype == TINTER)
n->op = ODOTINTER;
- }
+ return;
}
- break;
}
+
+ f = lookdot(n->right, t->method);
+ if(f == T) {
+ yyerror("undefined DOT reference %N", n->right);
+ return;
+ }
+
+ n->xoffset = f->width;
+ n->right = methodname(n->right, t);
+ n->type = f->type;
+ n->op = ODOTMETH;
}
Node*
Type *t;
t = tm->type;
- if(t == T) {
- fatal("fixmap: t nil");
- return T;
- }
-
- if(t->etype != TMAP) {
- fatal("fixmap: %lT not map", tm);
- return T;
- }
-
- if(t->down == T || t->type == T) {
- fatal("fixmap: map key/value types are nil");
- return T;
- }
+ if(t == T)
+ goto bad;
+ if(t->etype != TMAP)
+ goto bad;
+ if(t->down == T || t->type == T)
+ goto bad;
dowidth(t->down);
dowidth(t->type);
return t;
+
+bad:
+ yyerror("not a map: %lT", tm);
+ return T;
}
Type*
{
Type *t;
+ if(tm == T)
+ goto bad;
t = tm->type;
- if(t == T) {
- fatal("fixchan: t nil");
- return T;
- }
-
- if(t->etype != TCHAN) {
- fatal("fixchan: %lT not chan", tm);
- return T;
- }
-
- if(t->type == T) {
- fatal("fixchan: chan element type is nil");
- return T;
- }
+ if(t == T)
+ goto bad;
+ if(t->etype != TCHAN)
+ goto bad;
+ if(t->type == T)
+ goto bad;
dowidth(t->type);
return t;
+
+bad:
+ yyerror("not a channel: %lT", tm);
+ return T;
}
static int
Type *t;
t = tm->type;
- if(t == T) {
- fatal("fixarray: t nil");
- return T;
- }
-
- if(t->etype != TARRAY) {
- fatal("fixarray: %lT not array", tm);
- return T;
- }
-
- if(t->type == T) {
- fatal("fixarray: array element type is nil");
- return T;
- }
+ if(t == T)
+ goto bad;
+ if(t->etype != TARRAY)
+ goto bad;
+ if(t->type == T)
+ goto bad;
dowidth(t->type);
return t;
+
+bad:
+ yyerror("not an array: %lT", tm);
+ return T;
+
}
Node*
buf[1] = buf[2];
buf[2] = '.';
- buf[n+2] = '+';
+ buf[n+2] = 'e';
+ buf[n+3] = '+';
if(e < 0) {
e = -e;
- buf[n+2] = '-';
+ buf[n+3] = '-';
}
- buf[n+3] = 'e';
+
buf[n+4] = (e/10) + '0';
buf[n+5] = (e%10) + '0';
sys·write(1, buf, n+6);
hash[h] = m;
return nil;
}
+
if(ihash != ss[ns].hash ||
strcmp(sname, iname) != 0) {
ns++;