1
0
mirror of https://github.com/golang/go synced 2024-11-22 04:14:42 -07:00

more on arbitrary receiver types

this CL passes the tests, but should
be considered unstable

R=r
OCL=16390
CL=16390
This commit is contained in:
Ken Thompson 2008-10-02 20:51:10 -07:00
parent 53a22770a7
commit ed139c1e37
6 changed files with 114 additions and 57 deletions

View File

@ -58,7 +58,10 @@ struct Sig
char* name;
Sym* sym;
uint32 hash;
int32 perm;
int32 offset;
int32 width;
int32 elemalg;
Sig* link;
};

View File

@ -580,10 +580,13 @@ dumpsignatures(void)
a->name = sp+1;
a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
a->offset = o;
a->perm = o;
snprint(namebuf, sizeof(namebuf), "%s_%s",
at.sym->name+5, f->sym->name);
a->sym = lookup(namebuf);
a->offset = 0;
a->elemalg = 0;
a->width = 0;
o++;
}
@ -660,7 +663,18 @@ dumpsignatures(void)
ot += wi;
if(et == TINTER) {
// sigi[++].offset = offset of method
// sigi[++].perm = mapped offset of method
ot = rnd(ot, wi);
p = pc;
gins(ADATA, N, N);
p->from = at;
p->from.offset = ot;
p->from.scale = wi;
p->to = ac;
p->to.offset = b->perm;
ot += wi;
} else {
// sigt[++].offset = of embeded struct
ot = rnd(ot, wi);
p = pc;
gins(ADATA, N, N);
@ -670,17 +684,30 @@ dumpsignatures(void)
p->to = ac;
p->to.offset = b->offset;
ot += wi;
} else {
// leave space for 3 ints
// offset, algorithm and width
ot = rnd(ot, wi);
ot += wi;
ot = rnd(ot, wi);
ot += wi;
// sigt[++].width = type size
ot = rnd(ot, wi);
p = pc;
gins(ADATA, N, N);
p->from = at;
p->from.offset = ot;
p->from.scale = wi;
p->to = ac;
p->to.offset = b->width;
ot += wi;
// sigs[++].fun = &method
// sigt[++].elemalg = type algorithm
ot = rnd(ot, wi);
p = pc;
gins(ADATA, N, N);
p->from = at;
p->from.offset = ot;
p->from.scale = wi;
p->to = ac;
p->to.offset = b->elemalg;
ot += wi;
// sigt[++].fun = &method
ot = rnd(ot, widthptr);
p = pc;
gins(ADATA, N, N);

View File

@ -250,7 +250,6 @@ addmethod(Node *n, Type *t, int local)
{
Type *f, *d, *pa;
Sym *st, *sf;
int ptr;
// get field sym
if(n == N)
@ -272,29 +271,11 @@ addmethod(Node *n, Type *t, int local)
if(pa == T)
goto bad;
switch(algtype(pa)) {
default:
goto bad;
case ASIMP:
case APTR:
case ASTRING:
break;
}
// 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");
// and finally the receiver sym
f = ismethod(pa);
if(f == T)
goto bad;
pa = f;
st = pa->sym;
if(st == S)
goto bad;
@ -306,11 +287,6 @@ addmethod(Node *n, Type *t, int local)
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=pa->method; f!=T; f=f->down) {
if(f->etype != TFIELD)
@ -331,7 +307,7 @@ addmethod(Node *n, Type *t, int local)
stotype(n, &d->down);
if(dflag())
print("method %S of type %s%S\n", sf, (ptr? "*":""), st);
print("method %S of type %T\n", sf, pa);
return;
bad:
@ -450,8 +426,10 @@ funcargs(Type *ft)
all |= 2;
t = structnext(&save);
}
// this test is remarkedly similar to checkarglist
if(all == 3)
yyerror("output parameters are all named or not named");
yyerror("cannot mix anonymous and named output arguments");
ft->outnamed = 0;
if(all == 1)

View File

@ -571,7 +571,7 @@ int isptrto(Type*, int);
int isptrarray(Type*);
int isptrdarray(Type*);
int isinter(Type*);
int ismethod(Type*);
Type* ismethod(Type*);
Sym* signame(Type*);
int bytearraysz(Type*);
int eqtype(Type*, Type*, int);

View File

@ -1357,18 +1357,59 @@ isinter(Type *t)
return 0;
}
int
Type*
ismethod(Type *t)
{
// OLD WAY
if(isptrto(t, TSTRUCT))
return 1;
return 0;
int a;
Sym *s;
// NEW WAY - but doesnt work yet
if(t != T && t->method != T)
return 1;
return 0;
if(t == T)
return T;
a = algtype(t);
// direct receiver
s = t->sym;
if(s != S && s->name[0] != '_') {
if(t->methptr == 2)
goto both;
t->methptr |= 1;
goto out;
}
// pointer receiver
if(!isptr[t->etype])
return T;
t = t->type;
if(t == T)
return T;
s = t->sym;
if(s != S && s->name[0] != '_') {
if(t->methptr == 1)
goto both;
t->methptr |= 2;
goto out;
}
return T;
both:
yyerror("type %T used as both direct and indirect method", t);
t->methptr = 3;
out:
switch(a) {
default:
yyerror("type %T cannot be used as a method", t);
case ASIMP:
case APTR:
case ASTRING:
break;
}
return t;
}
Sym*

View File

@ -1598,9 +1598,12 @@ ascompat(Type *t1, Type *t2)
// if(eqtype(t2, nilptr, 0))
// return 1;
if(isinter(t1))
if(ismethod(t2) || isinter(t2))
if(isinter(t1)) {
if(isinter(t2))
return 1;
if(ismethod(t2))
return 1;
}
if(isinter(t2))
if(ismethod(t1))
@ -2445,15 +2448,20 @@ isandss(Type *lt, Node *r)
rt = r->type;
if(isinter(lt)) {
if(ismethod(rt))
if(isinter(rt)) {
if(!eqtype(rt, lt, 0))
return I2I;
return Inone;
}
if(ismethod(rt) != T)
return T2I;
if(isinter(rt) && !eqtype(rt, lt, 0))
return I2I;
return Inone;
}
if(ismethod(lt)) {
if(isinter(rt))
if(isinter(rt)) {
if(ismethod(lt) != T)
return I2T;
return Inone;
}
return Inone;