Commit b379d54d authored by Ken Thompson's avatar Ken Thompson

another step toward interface subtypes

put explicit ./ on some runtime tests

R=r
OCL=17839
CL=17839
parent cc4dc5a2
This diff is collapsed.
......@@ -208,6 +208,7 @@ struct Sym
uchar exported; // exported
uchar sym; // huffman encoding in object file
uchar local; // created in this file
uchar uniq; // imbedded field name first found
char* opackage; // original package name
char* package; // package name
......@@ -398,6 +399,16 @@ struct Io
char* cp; // used for content when bin==nil
};
typedef struct Dlist Dlist;
struct Dlist
{
Sym* sym;
uchar ptr;
int offset;
};
EXTERN Dlist dotlist[10]; // size is max depth of embeddeds
EXTERN Io curio;
EXTERN Io pushedio;
EXTERN int32 lineno;
......@@ -631,6 +642,13 @@ int Nconv(Fmt*);
int Wconv(Fmt*);
int Zconv(Fmt*);
int lookdot0(Sym*, Type*);
int adddot1(Sym*, Type*, int);
Node* adddot(Node*);
void expand0(Type*);
void expand1(Type*, int);
void expandmeth(Sym*, Type*);
/*
* dcl.c
*/
......@@ -748,7 +766,6 @@ Node* arraylit(Node*);
Node* maplit(Node*);
Node* selectas(Node*, Node*);
Node* old2new(Node*, Type*);
Node* adddot(Node*);
/*
* const.c
......
......@@ -2377,3 +2377,251 @@ getinargx(Type *t)
{
return *getinarg(t);
}
/*
* code to resolve elided DOTs
* in embedded types
*/
// search depth 0 --
// return count of fields+methods
// found with a given name
int
lookdot0(Sym *s, Type *t)
{
Type *f, *u;
int c;
u = t;
if(isptr[u->etype])
u = u->type;
c = 0;
if(u->etype == TSTRUCT || u->etype == TINTER) {
for(f=u->type; f!=T; f=f->down)
if(f->sym == s)
c++;
}
u = methtype(t);
if(u != T) {
for(f=u->method; f!=T; f=f->down)
if(f->sym == s && f->embedded == 0)
c++;
}
return c;
}
// search depth d --
// return count of fields+methods
// found at search depth.
// answer is in dotlist array and
// count of number of ways is returned.
int
adddot1(Sym *s, Type *t, int d)
{
Type *f, *u;
int c, a;
if(t->trecur)
return 0;
t->trecur = 1;
if(d == 0) {
c = lookdot0(s, t);
goto out;
}
c = 0;
u = t;
if(isptr[u->etype])
u = u->type;
if(u->etype != TSTRUCT && u->etype != TINTER)
goto out;
d--;
for(f=u->type; f!=T; f=f->down) {
if(!f->embedded)
continue;
if(f->sym == S)
continue;
a = adddot1(s, f->type, d);
if(a != 0 && c == 0) {
dotlist[d].sym = f->sym;
dotlist[d].offset = f->width;
dotlist[d].ptr = 0;
if(isptr[f->type->etype])
dotlist[d].ptr = 1;
}
c += a;
}
out:
t->trecur = 0;
return c;
}
// in T.field
// find missing fields that
// will give shortest unique addressing.
// modify the tree with missing type names.
Node*
adddot(Node *n)
{
Type *t;
Sym *s;
Node *l;
int c, d;
walktype(n->left, Erv);
t = n->left->type;
if(t == T)
return n;
if(n->right->op != ONAME)
return n;
s = n->right->sym;
if(s == S)
return n;
for(d=0; d<nelem(dotlist); d++) {
c = adddot1(s, t, d);
if(c > 0)
goto out;
}
return n;
out:
if(c > 1)
yyerror("ambiguous DOT reference %S", s);
// rebuild elided dots
for(c=d-1; c>=0; c--) {
n = nod(ODOT, n, n->right);
n->left->right = newname(dotlist[c].sym);
}
return n;
}
/*
* code to help generate trampoline
* functions for methods on embedded
* subtypes.
* these are approx the same as
* the corresponding adddot routines
* except that they expect to be called
* with unique tasks and they return
* the actual methods.
*/
typedef struct Symlink Symlink;
struct Symlink
{
Type* field;
uchar good;
Symlink* link;
};
static Symlink* slist;
void
expand0(Type *t)
{
Type *f, *u;
Symlink *sl;
u = t;
if(isptr[u->etype])
u = u->type;
u = methtype(t);
if(u != T) {
for(f=u->method; f!=T; f=f->down) {
if(f->sym->uniq)
continue;
f->sym->uniq = 1;
sl = mal(sizeof(*sl));
sl->field = f;
sl->link = slist;
slist = sl;
}
}
}
void
expand1(Type *t, int d)
{
Type *f, *u;
if(t->trecur)
return;
if(d == 0)
return;
t->trecur = 1;
if(d != nelem(dotlist)-1)
expand0(t);
u = t;
if(isptr[u->etype])
u = u->type;
if(u->etype != TSTRUCT && u->etype != TINTER)
goto out;
for(f=u->type; f!=T; f=f->down) {
if(!f->embedded)
continue;
if(f->sym == S)
continue;
expand1(f->type, d-1);
}
out:
t->trecur = 0;
}
void
expandmeth(Sym *s, Type *t)
{
Symlink *sl;
Type *f;
int c, d;
if(s == S)
return;
if(t == T)
return;
if(strcmp(s->name, "S") != 0)
return;
// generate all reachable methods
slist = nil;
expand1(t, nelem(dotlist)-1);
// check each method to be uniquely reachable
for(sl=slist; sl!=nil; sl=sl->link) {
for(d=0; d<nelem(dotlist); d++) {
c = adddot1(sl->field->sym, t, d);
if(c == 0)
continue;
if(c == 1)
sl->good = 1;
break;
}
}
//print("expand %S: %lT", s, t);
for(sl=slist; sl!=nil; sl=sl->link) {
if(sl->good) {
// add it to the base type method list
f = typ(TFIELD);
*f = *sl->field;
f->embedded = 1; // needs a trampoline
f->down = t->method;
t->method = f;
//print(" %T", f);
}
}
//print("\n");
}
......@@ -3203,116 +3203,3 @@ loop:
r = listnext(&saver);
goto loop;
}
static int prdot = 0;
int
lookdot0(Sym *s, Type *t)
{
Type *f, *u;
int c;
u = t;
if(isptr[u->etype])
u = u->type;
c = 0;
if(u->etype == TSTRUCT || u->etype == TINTER) {
for(f=u->type; f!=T; f=f->down)
if(f->sym == s)
c++;
}
u = methtype(t);
if(u != T) {
for(f=u->method; f!=T; f=f->down)
if(f->sym == s)
{
if(prdot)
print("found method %S\n", s);
c++;
}
}
return c;
}
enum { maxembed = 10 }; // max depth search for embedded types
static Sym* dotlist[maxembed+1]; // maxembed..1
int
adddot1(Sym *s, Type *t, int d)
{
Type *f, *u;
int c, a;
if(d == 0)
return lookdot0(s, t);
u = t;
if(isptr[u->etype])
u = u->type;
if(u->etype != TSTRUCT && u->etype != TINTER)
return 0;
c = 0;
for(f=u->type; f!=T; f=f->down) {
if(!f->embedded)
continue;
if(f->sym == S)
continue;
a = adddot1(s, f->type, d-1);
if(a != 0 && c == 0)
dotlist[d] = f->sym;
c += a;
}
return c;
}
Node*
adddot(Node *n)
{
Type *t;
Sym *s;
Node *l;
int c, d;
walktype(n->left, Erv);
t = n->left->type;
if(t == T)
return n;
if(n->right->op != ONAME)
return n;
s = n->right->sym;
if(s == S)
return n;
for(d=0; d<maxembed; d++) {
c = adddot1(s, t, d);
if(c > 0)
goto out;
}
if(prdot) {
print("missed");
dump("", n);
}
return n;
out:
if(c > 1)
yyerror("ambiguous DOT reference %S", s);
if(prdot)
if(d > 0)
print("add dots:");
// rebuild elided dots
for(c=d; c>0; c--) {
n = nod(ODOT, n, n->right);
n->left->right = newname(dotlist[c]);
if(prdot)
print(" %S", dotlist[c]);
}
if(prdot)
if(d > 0)
print("\n");
return n;
}
......@@ -6,8 +6,9 @@
set -e
xcd() {
builtin cd $1
echo
echo --- cd $1
builtin cd $1
}
(xcd lib/reflect
......@@ -41,7 +42,7 @@ rm -f *.6 6.out
6g printf.go
6g main.go
6l main.6
6.out
./6.out
)
(xcd ../test
......
......@@ -9,7 +9,7 @@ pretty: pretty.6
$(L) -o pretty pretty.6
test: pretty
test.sh
./test.sh
install: pretty
cp pretty $(HOME)/bin/pretty
......
......@@ -61,7 +61,7 @@ cleanup() {
silent() {
cleanup
pretty -s $1 > $TMP1
./pretty -s $1 > $TMP1
if [ $? != 0 ]; then
cat $TMP1
echo "Error (silent mode test): test.sh $1"
......@@ -72,8 +72,8 @@ silent() {
idempotent() {
cleanup
pretty $1 > $TMP1
pretty $TMP1 > $TMP2
./pretty $1 > $TMP1
./pretty $TMP1 > $TMP2
cmp -s $TMP1 $TMP2
if [ $? != 0 ]; then
diff $TMP1 $TMP2
......@@ -85,7 +85,7 @@ idempotent() {
valid() {
cleanup
pretty $1 > $TMP1
./pretty $1 > $TMP1
6g -o /dev/null $TMP1
if [ $? != 0 ]; then
echo "Error (validity test): test.sh $1"
......@@ -122,7 +122,7 @@ runtests() {
# run selftest always
pretty -t selftest.go > $TMP1
./pretty -t selftest.go > $TMP1
if [ $? != 0 ]; then
cat $TMP1
echo "Error (selftest): pretty -t selftest.go"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment