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:
parent
53a22770a7
commit
ed139c1e37
@ -58,7 +58,10 @@ struct Sig
|
||||
char* name;
|
||||
Sym* sym;
|
||||
uint32 hash;
|
||||
int32 perm;
|
||||
int32 offset;
|
||||
int32 width;
|
||||
int32 elemalg;
|
||||
Sig* link;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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*
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user