mirror of
https://github.com/golang/go
synced 2024-11-22 09:44:40 -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:
parent
53a22770a7
commit
ed139c1e37
@ -58,7 +58,10 @@ struct Sig
|
|||||||
char* name;
|
char* name;
|
||||||
Sym* sym;
|
Sym* sym;
|
||||||
uint32 hash;
|
uint32 hash;
|
||||||
|
int32 perm;
|
||||||
int32 offset;
|
int32 offset;
|
||||||
|
int32 width;
|
||||||
|
int32 elemalg;
|
||||||
Sig* link;
|
Sig* link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -580,10 +580,13 @@ dumpsignatures(void)
|
|||||||
a->name = sp+1;
|
a->name = sp+1;
|
||||||
|
|
||||||
a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
|
a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
|
||||||
a->offset = o;
|
a->perm = o;
|
||||||
snprint(namebuf, sizeof(namebuf), "%s_%s",
|
snprint(namebuf, sizeof(namebuf), "%s_%s",
|
||||||
at.sym->name+5, f->sym->name);
|
at.sym->name+5, f->sym->name);
|
||||||
a->sym = lookup(namebuf);
|
a->sym = lookup(namebuf);
|
||||||
|
a->offset = 0;
|
||||||
|
a->elemalg = 0;
|
||||||
|
a->width = 0;
|
||||||
|
|
||||||
o++;
|
o++;
|
||||||
}
|
}
|
||||||
@ -660,7 +663,18 @@ dumpsignatures(void)
|
|||||||
ot += wi;
|
ot += wi;
|
||||||
|
|
||||||
if(et == TINTER) {
|
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);
|
ot = rnd(ot, wi);
|
||||||
p = pc;
|
p = pc;
|
||||||
gins(ADATA, N, N);
|
gins(ADATA, N, N);
|
||||||
@ -670,17 +684,30 @@ dumpsignatures(void)
|
|||||||
p->to = ac;
|
p->to = ac;
|
||||||
p->to.offset = b->offset;
|
p->to.offset = b->offset;
|
||||||
ot += wi;
|
ot += wi;
|
||||||
} else {
|
|
||||||
// leave space for 3 ints
|
// sigt[++].width = type size
|
||||||
// offset, algorithm and width
|
|
||||||
ot = rnd(ot, wi);
|
|
||||||
ot += wi;
|
|
||||||
ot = rnd(ot, wi);
|
|
||||||
ot += wi;
|
|
||||||
ot = rnd(ot, wi);
|
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;
|
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);
|
ot = rnd(ot, widthptr);
|
||||||
p = pc;
|
p = pc;
|
||||||
gins(ADATA, N, N);
|
gins(ADATA, N, N);
|
||||||
|
@ -250,7 +250,6 @@ addmethod(Node *n, Type *t, int local)
|
|||||||
{
|
{
|
||||||
Type *f, *d, *pa;
|
Type *f, *d, *pa;
|
||||||
Sym *st, *sf;
|
Sym *st, *sf;
|
||||||
int ptr;
|
|
||||||
|
|
||||||
// get field sym
|
// get field sym
|
||||||
if(n == N)
|
if(n == N)
|
||||||
@ -272,29 +271,11 @@ addmethod(Node *n, Type *t, int local)
|
|||||||
if(pa == T)
|
if(pa == T)
|
||||||
goto bad;
|
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
|
// and finally the receiver sym
|
||||||
|
f = ismethod(pa);
|
||||||
|
if(f == T)
|
||||||
|
goto bad;
|
||||||
|
pa = f;
|
||||||
st = pa->sym;
|
st = pa->sym;
|
||||||
if(st == S)
|
if(st == S)
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -306,11 +287,6 @@ addmethod(Node *n, Type *t, int local)
|
|||||||
n = nod(ODCLFIELD, newname(sf), N);
|
n = nod(ODCLFIELD, newname(sf), N);
|
||||||
n->type = t;
|
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
|
d = T; // last found
|
||||||
for(f=pa->method; f!=T; f=f->down) {
|
for(f=pa->method; f!=T; f=f->down) {
|
||||||
if(f->etype != TFIELD)
|
if(f->etype != TFIELD)
|
||||||
@ -331,7 +307,7 @@ addmethod(Node *n, Type *t, int local)
|
|||||||
stotype(n, &d->down);
|
stotype(n, &d->down);
|
||||||
|
|
||||||
if(dflag())
|
if(dflag())
|
||||||
print("method %S of type %s%S\n", sf, (ptr? "*":""), st);
|
print("method %S of type %T\n", sf, pa);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
@ -450,8 +426,10 @@ funcargs(Type *ft)
|
|||||||
all |= 2;
|
all |= 2;
|
||||||
t = structnext(&save);
|
t = structnext(&save);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this test is remarkedly similar to checkarglist
|
||||||
if(all == 3)
|
if(all == 3)
|
||||||
yyerror("output parameters are all named or not named");
|
yyerror("cannot mix anonymous and named output arguments");
|
||||||
|
|
||||||
ft->outnamed = 0;
|
ft->outnamed = 0;
|
||||||
if(all == 1)
|
if(all == 1)
|
||||||
|
@ -571,7 +571,7 @@ int isptrto(Type*, int);
|
|||||||
int isptrarray(Type*);
|
int isptrarray(Type*);
|
||||||
int isptrdarray(Type*);
|
int isptrdarray(Type*);
|
||||||
int isinter(Type*);
|
int isinter(Type*);
|
||||||
int ismethod(Type*);
|
Type* ismethod(Type*);
|
||||||
Sym* signame(Type*);
|
Sym* signame(Type*);
|
||||||
int bytearraysz(Type*);
|
int bytearraysz(Type*);
|
||||||
int eqtype(Type*, Type*, int);
|
int eqtype(Type*, Type*, int);
|
||||||
|
@ -1357,18 +1357,59 @@ isinter(Type *t)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
Type*
|
||||||
ismethod(Type *t)
|
ismethod(Type *t)
|
||||||
{
|
{
|
||||||
// OLD WAY
|
int a;
|
||||||
if(isptrto(t, TSTRUCT))
|
Sym *s;
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// NEW WAY - but doesnt work yet
|
if(t == T)
|
||||||
if(t != T && t->method != T)
|
return T;
|
||||||
return 1;
|
|
||||||
return 0;
|
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*
|
Sym*
|
||||||
|
@ -1598,9 +1598,12 @@ ascompat(Type *t1, Type *t2)
|
|||||||
// if(eqtype(t2, nilptr, 0))
|
// if(eqtype(t2, nilptr, 0))
|
||||||
// return 1;
|
// return 1;
|
||||||
|
|
||||||
if(isinter(t1))
|
if(isinter(t1)) {
|
||||||
if(ismethod(t2) || isinter(t2))
|
if(isinter(t2))
|
||||||
return 1;
|
return 1;
|
||||||
|
if(ismethod(t2))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if(isinter(t2))
|
if(isinter(t2))
|
||||||
if(ismethod(t1))
|
if(ismethod(t1))
|
||||||
@ -2445,15 +2448,20 @@ isandss(Type *lt, Node *r)
|
|||||||
|
|
||||||
rt = r->type;
|
rt = r->type;
|
||||||
if(isinter(lt)) {
|
if(isinter(lt)) {
|
||||||
if(ismethod(rt))
|
if(isinter(rt)) {
|
||||||
|
if(!eqtype(rt, lt, 0))
|
||||||
|
return I2I;
|
||||||
|
return Inone;
|
||||||
|
}
|
||||||
|
if(ismethod(rt) != T)
|
||||||
return T2I;
|
return T2I;
|
||||||
if(isinter(rt) && !eqtype(rt, lt, 0))
|
return Inone;
|
||||||
return I2I;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ismethod(lt)) {
|
if(isinter(rt)) {
|
||||||
if(isinter(rt))
|
if(ismethod(lt) != T)
|
||||||
return I2T;
|
return I2T;
|
||||||
|
return Inone;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inone;
|
return Inone;
|
||||||
|
Loading…
Reference in New Issue
Block a user