more on arbitrary receiver types
this CL passes the tests, but should
be considered unstable
R=r
OCL=16390
CL=16390
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index 5a45aca..a6b9bca 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -58,7 +58,10 @@
char* name;
Sym* sym;
uint32 hash;
+ int32 perm;
int32 offset;
+ int32 width;
+ int32 elemalg;
Sig* link;
};
diff --git a/src/cmd/6g/obj.c b/src/cmd/6g/obj.c
index 5b16e71..a44ebdf 100644
--- a/src/cmd/6g/obj.c
+++ b/src/cmd/6g/obj.c
@@ -580,10 +580,13 @@
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 @@
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 @@
p->to = ac;
p->to.offset = b->offset;
ot += wi;
- } else {
- // leave space for 3 ints
- // offset, algorithm and width
+
+ // sigt[++].width = type size
ot = rnd(ot, wi);
- ot += wi;
- ot = rnd(ot, wi);
- 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;
- // 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);
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 5839d4a..d6f1b14 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -250,7 +250,6 @@
{
Type *f, *d, *pa;
Sym *st, *sf;
- int ptr;
// get field sym
if(n == N)
@@ -272,29 +271,11 @@
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 @@
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 @@
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 @@
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)
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index d38c8cb..28a2a62 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -571,7 +571,7 @@
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);
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 4514f39..d2c6a13 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -1357,18 +1357,59 @@
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*
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index cc06abc..f3aafc4 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1598,9 +1598,12 @@
// 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 @@
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;