Commit c3077f76 authored by Russ Cox's avatar Russ Cox

[] and struct in interfaces.

other [] cleanup.

convert() is gone.

R=r
DELTA=352  (144 added, 68 deleted, 140 changed)
OCL=21660
CL=21662
parent 33907d13
...@@ -160,6 +160,8 @@ dowidth(Type *t) ...@@ -160,6 +160,8 @@ dowidth(Type *t)
if(t->funarg) if(t->funarg)
fatal("dowidth fn struct %T", t); fatal("dowidth fn struct %T", t);
w = widstruct(t, 0, 1); w = widstruct(t, 0, 1);
if(w == 0)
w = maxround;
offmod(t); offmod(t);
break; break;
......
...@@ -668,14 +668,11 @@ dumpsigt(Type *t0, Sym *s) ...@@ -668,14 +668,11 @@ dumpsigt(Type *t0, Sym *s)
// first field of an type signature contains // first field of an type signature contains
// the element parameters and is not a real entry // the element parameters and is not a real entry
if(t->methptr & 2)
t = types[tptr];
// sigi[0].hash = elemalg // sigi[0].hash = elemalg
gensatac(wi, algtype(t)); gensatac(wi, algtype(t0));
// sigi[0].offset = width // sigi[0].offset = width
gensatac(wi, t->width); gensatac(wi, t0->width);
// skip the function // skip the function
gensatac(widthptr, 0); gensatac(widthptr, 0);
......
...@@ -311,7 +311,7 @@ enum ...@@ -311,7 +311,7 @@ enum
OINDEX, OINDEXPTR, OSLICE, OINDEX, OINDEXPTR, OSLICE,
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV, ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
OLITERAL, OREGISTER, OINDREG, OLITERAL, OREGISTER, OINDREG,
OCONV, OKEY, OCONV, OCOMP, OKEY,
OBAD, OBAD,
OEND, OEND,
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
%type <node> interfacedcl_list_r interfacedcl %type <node> interfacedcl_list_r interfacedcl
%type <node> structdcl_list_r structdcl embed %type <node> structdcl_list_r structdcl embed
%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody %type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody
%type <node> keyexpr_list braced_keyexpr_list keyval_list_r keyval %type <node> braced_keyexpr_list keyval_list_r keyval
%type <type> typedclname new_type %type <type> typedclname new_type
%type <type> type Atype Btype %type <type> type Atype Btype
...@@ -864,11 +864,6 @@ pexpr: ...@@ -864,11 +864,6 @@ pexpr:
$$ = nod(ONEW, $5, N); $$ = nod(ONEW, $5, N);
$$->type = $3; $$->type = $3;
} }
| LCONVERT '(' type ',' keyexpr_list ')'
{
$$ = nod(OCONV, $5, N);
$$->type = $3;
}
| latype '(' expr ')' | latype '(' expr ')'
{ {
$$ = nod(OCONV, $3, N); $$ = nod(OCONV, $3, N);
...@@ -884,7 +879,7 @@ pexpr: ...@@ -884,7 +879,7 @@ pexpr:
$$ = nod(OEMPTY, N, N); $$ = nod(OEMPTY, N, N);
if(!iscomposite($1)) if(!iscomposite($1))
yyerror("illegal composite literal type %T", $1); yyerror("illegal composite literal type %T", $1);
$$ = nod(OCONV, $$, N); $$ = nod(OCOMP, $$, N);
$$->type = $1; $$->type = $1;
} }
| fnliteral | fnliteral
...@@ -987,7 +982,6 @@ sym3: ...@@ -987,7 +982,6 @@ sym3:
| LNEW | LNEW
| LBASETYPE | LBASETYPE
| LTYPEOF | LTYPEOF
| LCONVERT
/* /*
* keywords that we can * keywords that we can
...@@ -1674,13 +1668,6 @@ keyval_list_r: ...@@ -1674,13 +1668,6 @@ keyval_list_r:
$$ = nod(OLIST, $1, $3); $$ = nod(OLIST, $1, $3);
} }
keyexpr_list:
keyval_list_r
{
$$ = rev($1);
}
| expr_list
/* /*
* have to spell this out using _r lists to avoid yacc conflict * have to spell this out using _r lists to avoid yacc conflict
*/ */
......
...@@ -1051,7 +1051,6 @@ static struct ...@@ -1051,7 +1051,6 @@ static struct
"chan", LCHAN, Txxx, "chan", LCHAN, Txxx,
"const", LCONST, Txxx, "const", LCONST, Txxx,
"continue", LCONTINUE, Txxx, "continue", LCONTINUE, Txxx,
"convert", LCONVERT, Txxx,
"default", LDEFAULT, Txxx, "default", LDEFAULT, Txxx,
"else", LELSE, Txxx, "else", LELSE, Txxx,
"export", LEXPORT, Txxx, "export", LEXPORT, Txxx,
...@@ -1268,7 +1267,6 @@ struct ...@@ -1268,7 +1267,6 @@ struct
LNEW, "NEW", LNEW, "NEW",
LLEN, "LEN", LLEN, "LEN",
LFALL, "FALL", LFALL, "FALL",
LCONVERT, "CONVERT",
LIOTA, "IOTA", LIOTA, "IOTA",
LPRINT, "PRINT", LPRINT, "PRINT",
LPACKAGE, "PACKAGE", LPACKAGE, "PACKAGE",
......
...@@ -649,6 +649,7 @@ opnames[] = ...@@ -649,6 +649,7 @@ opnames[] =
[OFALL] = "FALL", [OFALL] = "FALL",
[OCONV] = "CONV", [OCONV] = "CONV",
[OCOM] = "COM", [OCOM] = "COM",
[OCOMP] = "COMP",
[OCONST] = "CONST", [OCONST] = "CONST",
[OCONTINUE] = "CONTINUE", [OCONTINUE] = "CONTINUE",
[ODCLARG] = "DCLARG", [ODCLARG] = "DCLARG",
...@@ -1657,10 +1658,6 @@ signame(Type *t) ...@@ -1657,10 +1658,6 @@ signame(Type *t)
if(t->etype == TINTER) if(t->etype == TINTER)
e = "sigi"; e = "sigi";
// don't allow arrays in interfaces
if(t->etype == TARRAY)
goto bad;
// name is exported name, like *[]byte or *Struct or Interface // name is exported name, like *[]byte or *Struct or Interface
// (special symbols don't bother the linker). // (special symbols don't bother the linker).
snprint(buf, sizeof(buf), "%#T", t); snprint(buf, sizeof(buf), "%#T", t);
......
...@@ -559,7 +559,6 @@ loop: ...@@ -559,7 +559,6 @@ loop:
if(t == T) if(t == T)
goto ret; goto ret;
if(!iscomposite(t))
convlit1(l, t, 1); convlit1(l, t, 1);
// nil conversion // nil conversion
...@@ -595,26 +594,6 @@ loop: ...@@ -595,26 +594,6 @@ loop:
if(issarray(t) && isdarray(l->type)) if(issarray(t) && isdarray(l->type))
goto ret; goto ret;
// structure literal
if(t->etype == TSTRUCT) {
indir(n, structlit(n));
goto ret;
}
// array literal
if(t->etype == TARRAY) {
r = arraylit(n);
indir(n, r);
goto ret;
}
// map literal
if(isptr[t->etype] && t->type != t && t->type->etype == TMAP) {
r = maplit(n);
indir(n, r);
goto ret;
}
// interface and structure // interface and structure
et = isandss(n->type, l); et = isandss(n->type, l);
if(et != Inone) { if(et != Inone) {
...@@ -642,6 +621,43 @@ loop: ...@@ -642,6 +621,43 @@ loop:
yyerror("cannot convert %T to %T", l->type, t); yyerror("cannot convert %T to %T", l->type, t);
goto ret; goto ret;
case OCOMP:
if(top == Etop)
goto nottop;
l = n->left;
if(l == N)
goto ret;
walktype(l, Erv);
t = n->type;
if(t == T)
goto ret;
// structure literal
if(t->etype == TSTRUCT) {
indir(n, structlit(n));
goto ret;
}
// array literal
if(t->etype == TARRAY) {
r = arraylit(n);
indir(n, r);
goto ret;
}
// map literal
if(isptr[t->etype] && t->type != t && t->type->etype == TMAP) {
r = maplit(n);
indir(n, r);
goto ret;
}
yyerror("bad composite literal %T", t);
goto ret;
case ORETURN: case ORETURN:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
...@@ -944,7 +960,7 @@ loop: ...@@ -944,7 +960,7 @@ loop:
case OADDR: case OADDR:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
if(n->left->op == OCONV && n->left->type != T) if(n->left->op == OCOMP && n->left->type != T)
if(n->left->type->etype == TSTRUCT) { if(n->left->type->etype == TSTRUCT) {
// turn &Point{1, 2} into allocation. // turn &Point{1, 2} into allocation.
// initialize with // initialize with
...@@ -1873,8 +1889,6 @@ ascompat(Type *t1, Type *t2) ...@@ -1873,8 +1889,6 @@ ascompat(Type *t1, Type *t2)
// if(eqtype(t2, nilptr, 0)) // if(eqtype(t2, nilptr, 0))
// return 1; // return 1;
if(issarray(t1))
return 0;
if(isnilinter(t1)) if(isnilinter(t1))
return 1; return 1;
if(isinter(t1)) { if(isinter(t1)) {
...@@ -2722,11 +2736,8 @@ isandss(Type *lt, Node *r) ...@@ -2722,11 +2736,8 @@ isandss(Type *lt, Node *r)
return I2I; return I2I;
return Inone; return Inone;
} }
if(isnilinter(lt)) { if(isnilinter(lt))
if(!issimple[rt->etype] && !isptr[rt->etype])
yyerror("using %T as interface is unimplemented", rt);
return T2I; return T2I;
}
if(ismethod(rt) != T) if(ismethod(rt) != T)
return T2I; return T2I;
return Inone; return Inone;
......
...@@ -26,15 +26,6 @@ type FmtTest struct { ...@@ -26,15 +26,6 @@ type FmtTest struct {
out string; out string;
} }
// TODO(rsc): return []byte, but need to be able to pass as interface.
func Bytes(s string) *[]byte {
b := new([]byte, len(s)+1);
syscall.StringToBytes(b, s);
bp := new(*[]byte);
*bp = b[0:len(s)];
return bp;
}
const B32 uint32 = 1<<32 - 1 const B32 uint32 = 1<<32 - 1
const B64 uint64 = 1<<64 - 1 const B64 uint64 = 1<<64 - 1
...@@ -47,12 +38,12 @@ var fmttests = []FmtTest{ ...@@ -47,12 +38,12 @@ var fmttests = []FmtTest{
FmtTest{ "%q", "abc", `"abc"` }, FmtTest{ "%q", "abc", `"abc"` },
// basic bytes // basic bytes
FmtTest{ "%s", Bytes("abc"), "abc" }, FmtTest{ "%s", io.StringBytes("abc"), "abc" },
FmtTest{ "%x", Bytes("abc"), "616263" }, FmtTest{ "%x", io.StringBytes("abc"), "616263" },
FmtTest{ "% x", Bytes("abc"), "61 62 63" }, FmtTest{ "% x", io.StringBytes("abc"), "61 62 63" },
FmtTest{ "%x", Bytes("xyz"), "78797a" }, FmtTest{ "%x", io.StringBytes("xyz"), "78797a" },
FmtTest{ "%X", Bytes("xyz"), "78797A" }, FmtTest{ "%X", io.StringBytes("xyz"), "78797A" },
FmtTest{ "%q", Bytes("abc"), `"abc"` }, FmtTest{ "%q", io.StringBytes("abc"), `"abc"` },
// escaped strings // escaped strings
FmtTest{ "%#q", `abc`, "`abc`" }, FmtTest{ "%#q", `abc`, "`abc`" },
......
...@@ -253,12 +253,11 @@ func getString(v reflect.Value) (val string, ok bool) { ...@@ -253,12 +253,11 @@ func getString(v reflect.Value) (val string, ok bool) {
switch v.Kind() { switch v.Kind() {
case reflect.StringKind: case reflect.StringKind:
return v.(reflect.StringValue).Get(), true; return v.(reflect.StringValue).Get(), true;
case reflect.PtrKind: case reflect.ArrayKind:
if val, ok := v.Interface().(*[]byte); ok { if val, ok := v.Interface().([]byte); ok {
return string(*val), true; return string(val), true;
} }
} }
// TODO(rsc): check for Interface().([]byte) too.
return "", false; return "", false;
} }
......
...@@ -14,7 +14,7 @@ func IPv4(a, b, c, d byte) []byte { ...@@ -14,7 +14,7 @@ func IPv4(a, b, c, d byte) []byte {
} }
func Equal(a []byte, b []byte) bool { func Equal(a []byte, b []byte) bool {
if a == b { if a == nil && b == nil {
return true return true
} }
if a == nil || b == nil || len(a) != len(b) { if a == nil || b == nil || len(a) != len(b) {
......
...@@ -124,7 +124,6 @@ type StubType struct { ...@@ -124,7 +124,6 @@ type StubType struct {
} }
func NewStubType(name string, typ Type) *StubType { func NewStubType(name string, typ Type) *StubType {
if typ == nil && len(name) > 0 && name[0] == '*' { panicln("NewStubType", name, typ) }
return &StubType{name, typ} return &StubType{name, typ}
} }
......
...@@ -8,10 +8,10 @@ static int32 debug = 0; ...@@ -8,10 +8,10 @@ static int32 debug = 0;
typedef struct Sigt Sigt; typedef struct Sigt Sigt;
typedef struct Sigi Sigi; typedef struct Sigi Sigi;
typedef struct Map Map; typedef struct Itype Itype;
/* /*
* the layout of Sigt and Sigi are known to the compiler * the layout of Iface, Sigt and Sigi are known to the compiler
*/ */
struct Sigt struct Sigt
{ {
...@@ -28,17 +28,17 @@ struct Sigi ...@@ -28,17 +28,17 @@ struct Sigi
uint32 perm; // location of fun in Sigt // first is size uint32 perm; // location of fun in Sigt // first is size
}; };
struct Map struct Itype
{ {
Sigi* sigi; Sigi* sigi;
Sigt* sigt; Sigt* sigt;
Map* link; Itype* link;
int32 bad; int32 bad;
int32 unused; int32 unused;
void (*fun[])(void); void (*fun[])(void);
}; };
static Map* hash[1009]; static Itype* hash[1009];
Sigi sigi·empty[2] = { (byte*)"interface { }" }; Sigi sigi·empty[2] = { (byte*)"interface { }" };
...@@ -50,6 +50,8 @@ printsigi(Sigi *si) ...@@ -50,6 +50,8 @@ printsigi(Sigi *si)
sys·printpointer(si); sys·printpointer(si);
prints("{"); prints("{");
prints((int8*)si[0].name);
prints(":");
for(i=1;; i++) { for(i=1;; i++) {
name = si[i].name; name = si[i].name;
if(name == nil) if(name == nil)
...@@ -74,6 +76,8 @@ printsigt(Sigt *st) ...@@ -74,6 +76,8 @@ printsigt(Sigt *st)
sys·printpointer(st); sys·printpointer(st);
prints("{"); prints("{");
prints((int8*)st[0].name);
prints(":");
sys·printint(st[0].hash); // first element has alg sys·printint(st[0].hash); // first element has alg
prints(","); prints(",");
sys·printint(st[0].offset); // first element has width sys·printint(st[0].offset); // first element has width
...@@ -96,22 +100,28 @@ printsigt(Sigt *st) ...@@ -96,22 +100,28 @@ printsigt(Sigt *st)
} }
static void static void
printiface(Map *im, void *it) printiface(Iface i)
{ {
int32 j;
prints("("); prints("(");
sys·printpointer(im); sys·printpointer(i.type);
prints(","); prints(",");
sys·printpointer(it); for(j=0; j<nelem(i.data); j++) {
if(j > 0)
prints(".");
sys·printpointer(i.data[0]);
}
prints(")"); prints(")");
} }
static Map* static Itype*
hashmap(Sigi *si, Sigt *st, int32 canfail) itype(Sigi *si, Sigt *st, int32 canfail)
{ {
int32 nt, ni; int32 nt, ni;
uint32 ihash, h; uint32 ihash, h;
byte *sname, *iname; byte *sname, *iname;
Map *m; Itype *m;
h = ((uint32)(uint64)si + (uint32)(uint64)st) % nelem(hash); h = ((uint32)(uint64)si + (uint32)(uint64)st) % nelem(hash);
for(m=hash[h]; m!=nil; m=m->link) { for(m=hash[h]; m!=nil; m=m->link) {
...@@ -129,7 +139,7 @@ hashmap(Sigi *si, Sigt *st, int32 canfail) ...@@ -129,7 +139,7 @@ hashmap(Sigi *si, Sigt *st, int32 canfail)
goto throw; goto throw;
} }
} }
// prints("old hashmap\n"); // prints("old itype\n");
return m; return m;
} }
} }
...@@ -177,15 +187,22 @@ throw: ...@@ -177,15 +187,22 @@ throw:
} }
m->link = hash[h]; m->link = hash[h];
hash[h] = m; hash[h] = m;
// prints("new hashmap\n"); // prints("new itype\n");
return m; return m;
} }
// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any); // ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
void void
sys·ifaceT2I(Sigi *si, Sigt *st, void *elem, Map *retim, void *retit) sys·ifaceT2I(Sigi *si, Sigt *st, ...)
{ {
// int32 alg, wid; byte *elem;
Iface *ret;
int32 alg, wid;
elem = (byte*)(&st+1);
wid = st->offset;
ret = (Iface*)(elem + rnd(wid, 8));
ret->type = itype(si, st, 0);
if(debug) { if(debug) {
prints("T2I sigi="); prints("T2I sigi=");
...@@ -193,39 +210,49 @@ sys·ifaceT2I(Sigi *si, Sigt *st, void *elem, Map *retim, void *retit) ...@@ -193,39 +210,49 @@ sys·ifaceT2I(Sigi *si, Sigt *st, void *elem, Map *retim, void *retit)
prints(" sigt="); prints(" sigt=");
printsigt(st); printsigt(st);
prints(" elem="); prints(" elem=");
sys·printpointer(elem); sys·printpointer(*(void**)elem);
prints("\n"); prints("\n");
} }
retim = hashmap(si, st, 0); alg = st->hash;
wid = st->offset;
// alg = st->hash; if(wid <= sizeof ret->data)
// wid = st->offset; algarray[alg].copy(wid, ret->data, elem);
// algarray[alg].copy(wid, &retit, &elem); else{
retit = elem; // for speed could do this ret->data[0] = mal(wid);
if(debug)
printf("T2I mal %d %p\n", wid, ret->data[0]);
algarray[alg].copy(wid, ret->data[0], elem);
}
if(debug) { if(debug) {
prints("T2I ret="); prints("T2I ret=");
printiface(retim, retit); printiface(*ret);
prints("\n"); prints("\n");
} }
FLUSH(&retim); FLUSH(&ret);
FLUSH(&retit);
} }
// ifaceI2T(sigt *byte, iface any) (ret any); // ifaceI2T(sigt *byte, iface any) (ret any);
void void
sys·ifaceI2T(Sigt *st, Map *im, void *it, void *ret) sys·ifaceI2T(Sigt *st, Iface i, ...)
{ {
Itype *im;
byte *ret;
int32 wid, alg;
ret = (byte*)(&i+1);
if(debug) { if(debug) {
prints("I2T sigt="); prints("I2T sigt=");
printsigt(st); printsigt(st);
prints(" iface="); prints(" iface=");
printiface(im, it); printiface(i);
prints("\n"); prints("\n");
} }
im = i.type;
if(im == nil) { if(im == nil) {
prints("interface is nil, not "); prints("interface is nil, not ");
prints((int8*)st[0].name); prints((int8*)st[0].name);
...@@ -243,10 +270,16 @@ sys·ifaceI2T(Sigt *st, Map *im, void *it, void *ret) ...@@ -243,10 +270,16 @@ sys·ifaceI2T(Sigt *st, Map *im, void *it, void *ret)
throw("interface conversion"); throw("interface conversion");
} }
ret = it; alg = st->hash;
wid = st->offset;
if(wid <= sizeof i.data)
algarray[alg].copy(wid, ret, i.data);
else
algarray[alg].copy(wid, ret, i.data[0]);
if(debug) { if(debug) {
prints("I2T ret="); prints("I2T ret=");
sys·printpointer(ret); sys·printpointer(*(void**)ret);
prints("\n"); prints("\n");
} }
FLUSH(&ret); FLUSH(&ret);
...@@ -254,94 +287,113 @@ sys·ifaceI2T(Sigt *st, Map *im, void *it, void *ret) ...@@ -254,94 +287,113 @@ sys·ifaceI2T(Sigt *st, Map *im, void *it, void *ret)
// ifaceI2T2(sigt *byte, iface any) (ret any, ok bool); // ifaceI2T2(sigt *byte, iface any) (ret any, ok bool);
void void
sys·ifaceI2T2(Sigt *st, Map *im, void *it, void *ret, bool ok) sys·ifaceI2T2(Sigt *st, Iface i, ...)
{ {
byte *ret;
bool *ok;
Itype *im;
int32 alg, wid;
ret = (byte*)(&i+1);
alg = st->hash;
wid = st->offset;
ok = (bool*)(ret+rnd(wid, 8));
if(debug) { if(debug) {
prints("I2T2 sigt="); prints("I2T2 sigt=");
printsigt(st); printsigt(st);
prints(" iface="); prints(" iface=");
printiface(im, it); printiface(i);
prints("\n"); prints("\n");
} }
im = i.type;
if(im == nil || im->sigt != st) { if(im == nil || im->sigt != st) {
ret = 0; *ok = false;
ok = 0; sys·memclr(ret, wid);
} else { } else {
ret = it; *ok = true;
ok = 1; if(wid <= sizeof i.data)
algarray[alg].copy(wid, ret, i.data);
else
algarray[alg].copy(wid, ret, i.data[0]);
} }
if(debug) { if(debug) {
prints("I2T2 ret="); prints("I2T2 ret=");
sys·printpointer(ret); sys·printpointer(*(void**)ret);
sys·printbool(ok); sys·printbool(*ok);
prints("\n"); prints("\n");
} }
FLUSH(&ret);
FLUSH(&ok);
} }
// ifaceI2I(sigi *byte, iface any) (ret any); // ifaceI2I(sigi *byte, iface any) (ret any);
void void
sys·ifaceI2I(Sigi *si, Map *im, void *it, Map *retim, void *retit) sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
{ {
Itype *im;
int32 j;
if(debug) { if(debug) {
prints("I2I sigi="); prints("I2I sigi=");
printsigi(si); printsigi(si);
prints(" iface="); prints(" iface=");
printiface(im, it); printiface(i);
prints("\n"); prints("\n");
} }
im = i.type;
if(im == nil) { if(im == nil) {
// If incoming interface is uninitialized (zeroed) // If incoming interface is uninitialized (zeroed)
// make the outgoing interface zeroed as well. // make the outgoing interface zeroed as well.
retim = nil; ret.type = nil;
retit = nil; for(j=0; j<nelem(ret.data); j++)
ret.data[j] = nil;
} else { } else {
retit = it; ret = i;
retim = im;
if(im->sigi != si) if(im->sigi != si)
retim = hashmap(si, im->sigt, 0); ret.type = itype(si, im->sigt, 0);
} }
if(debug) { if(debug) {
prints("I2I ret="); prints("I2I ret=");
printiface(retim, retit); printiface(ret);
prints("\n"); prints("\n");
} }
FLUSH(&retim); FLUSH(&ret);
FLUSH(&retit);
} }
// ifaceI2I2(sigi *byte, iface any) (ret any, ok bool); // ifaceI2I2(sigi *byte, iface any) (ret any, ok bool);
void void
sys·ifaceI2I2(Sigi *si, Map *im, void *it, Map *retim, void *retit, bool ok) sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
{ {
Itype *im;
int32 j;
if(debug) { if(debug) {
prints("I2I2 sigi="); prints("I2I2 sigi=");
printsigi(si); printsigi(si);
prints(" iface="); prints(" iface=");
printiface(im, it); printiface(i);
prints("\n"); prints("\n");
} }
im = i.type;
if(im == nil) { if(im == nil) {
// If incoming interface is uninitialized (zeroed) // If incoming interface is uninitialized (zeroed)
// make the outgoing interface zeroed as well. // make the outgoing interface zeroed as well.
retim = nil; ret.type = nil;
retit = nil; for(j=0; j<nelem(ret.data); j++)
ret.data[j] = nil;
ok = 1; ok = 1;
} else { } else {
retit = it; ret = i;
retim = im;
ok = 1; ok = 1;
if(im->sigi != si) { if(im->sigi != si) {
retim = hashmap(si, im->sigt, 1); ret.type = itype(si, im->sigt, 1);
if(retim == nil) { if(ret.type == nil) {
retit = nil; for(j=0; j<nelem(ret.data); j++)
retim = nil; ret.data[j] = nil;
ok = 0; ok = 0;
} }
} }
...@@ -349,51 +401,55 @@ sys·ifaceI2I2(Sigi *si, Map *im, void *it, Map *retim, void *retit, bool ok) ...@@ -349,51 +401,55 @@ sys·ifaceI2I2(Sigi *si, Map *im, void *it, Map *retim, void *retit, bool ok)
if(debug) { if(debug) {
prints("I2I ret="); prints("I2I ret=");
printiface(retim, retit); printiface(ret);
prints("\n"); prints("\n");
} }
FLUSH(&retim); FLUSH(&ret);
FLUSH(&retit);
FLUSH(&ok); FLUSH(&ok);
} }
// ifaceeq(i1 any, i2 any) (ret bool); // ifaceeq(i1 any, i2 any) (ret bool);
void void
sys·ifaceeq(Map *im1, void *it1, Map *im2, void *it2, byte ret) sys·ifaceeq(Iface i1, Iface i2, bool ret)
{ {
int32 alg, wid; int32 alg, wid;
if(debug) { if(debug) {
prints("Ieq i1="); prints("Ieq i1=");
printiface(im1, it1); printiface(i1);
prints(" i2="); prints(" i2=");
printiface(im2, it2); printiface(i2);
prints("\n"); prints("\n");
} }
ret = false; ret = false;
// are they both nil // are they both nil
if(im1 == nil) { if(i1.type == nil) {
if(im2 == nil) if(i2.type == nil)
goto yes; goto yes;
goto no; goto no;
} }
if(im2 == nil) if(i2.type == nil)
goto no; goto no;
// value // value
alg = im1->sigt->hash; alg = i1.type->sigt->hash;
if(alg != im2->sigt->hash) if(alg != i2.type->sigt->hash)
goto no; goto no;
wid = im1->sigt->offset; wid = i1.type->sigt->offset;
if(wid != im2->sigt->offset) if(wid != i2.type->sigt->offset)
goto no; goto no;
if(!algarray[alg].equal(wid, &it1, &it2)) if(wid <= sizeof i1.data) {
if(!algarray[alg].equal(wid, i1.data, i2.data))
goto no;
} else {
if(!algarray[alg].equal(wid, i1.data[0], i2.data[0]))
goto no; goto no;
}
yes: yes:
ret = true; ret = true;
...@@ -407,13 +463,13 @@ no: ...@@ -407,13 +463,13 @@ no:
} }
void void
sys·printinter(Map *im, void *it) sys·printinter(Iface i)
{ {
printiface(im, it); printiface(i);
} }
void void
sys·reflect(Map *im, void *it, uint64 retit, string rettype) sys·reflect(Itype *im, void *it, uint64 retit, string rettype)
{ {
if(im == nil) { if(im == nil) {
retit = 0; retit = 0;
...@@ -476,13 +532,13 @@ findtype(string type) ...@@ -476,13 +532,13 @@ findtype(string type)
} }
void void
sys·unreflect(uint64 it, string type, Map *retim, void *retit) sys·unreflect(uint64 it, string type, Itype *retim, void *retit)
{ {
if(cmpstring(type, emptystring) == 0) { if(cmpstring(type, emptystring) == 0) {
retim = 0; retim = 0;
retit = 0; retit = 0;
} else { } else {
retim = hashmap(sigi·empty, findtype(type), 0); retim = itype(sigi·empty, findtype(type), 0);
retit = (void*)it; retit = (void*)it;
} }
FLUSH(&retim); FLUSH(&retim);
......
...@@ -50,6 +50,8 @@ typedef struct String *string; ...@@ -50,6 +50,8 @@ typedef struct String *string;
typedef struct Usema Usema; typedef struct Usema Usema;
typedef struct SigTab SigTab; typedef struct SigTab SigTab;
typedef struct MCache MCache; typedef struct MCache MCache;
typedef struct Iface Iface;
typedef struct Itype Itype;
/* /*
* per cpu declaration * per cpu declaration
...@@ -105,6 +107,11 @@ struct String ...@@ -105,6 +107,11 @@ struct String
int32 len; int32 len;
byte str[1]; byte str[1];
}; };
struct Iface
{
Itype *type;
void *data[1]; // could make bigger later
};
struct Array struct Array
{ // must not move anything { // must not move anything
......
...@@ -32,15 +32,16 @@ func arraycmptest() { ...@@ -32,15 +32,16 @@ func arraycmptest() {
if a == nil || nil == a { if a == nil || nil == a {
println("fail3:", a, "== nil"); println("fail3:", a, "== nil");
} }
if a == NIL || NIL == a { }
println("fail4:", a, "==", NIL);
} func SameArray(a, b []int) bool {
if a != a { if len(a) != len(b) || cap(a) != cap(b) {
println("fail5:", a, "!=", a); return false;
} }
if a1 != a { if len(a) > 0 && &a[0] != &b[0] {
println("fail6:", a1, "!=", a); return false;
} }
return true;
} }
var t = T{1.5, 123, "hello", 255} var t = T{1.5, 123, "hello", 255}
...@@ -56,7 +57,7 @@ func maptest() { ...@@ -56,7 +57,7 @@ func maptest() {
ma[1] = a; ma[1] = a;
a1 := ma[1]; a1 := ma[1];
if a1 != a { if !SameArray(a, a1) {
println("fail: map val array", a, a1); println("fail: map val array", a, a1);
} }
} }
...@@ -93,18 +94,49 @@ func chantest() { ...@@ -93,18 +94,49 @@ func chantest() {
t1 := <-ct; t1 := <-ct;
if t1.a != t.a || t1.b != t.b || t1.c != t.c || t1.d != t.d { if t1.a != t.a || t1.b != t.b || t1.c != t.c || t1.d != t.d {
println("fail: chan struct", t1.a, t1.b, t1.c, t1.d); println("fail: map val struct", t1.a, t1.b, t1.c, t1.d);
} }
a1 := <-ca; a1 := <-ca;
if a1 != a { if !SameArray(a, a1) {
println("fail: chan array", a, a1); println("fail: map val array", a, a1);
} }
} }
type E struct { }
var e E
func interfacetest() {
var i interface{};
i = a;
a1 := i.([]int);
if !SameArray(a, a1) {
println("interface <-> []int", a, a1);
}
pa := new(*[]int);
*pa = a;
i = pa;
a1 = *i.(*[]int);
if !SameArray(a, a1) {
println("interface <-> *[]int", a, a1);
}
i = t;
t1 := i.(T);
if t1.a != t.a || t1.b != t.b || t1.c != t.c || t1.d != t.d {
println("interface <-> struct", t1.a, t1.b, t1.c, t1.d);
}
i = e;
e1 := i.(E);
// nothing to check; just verify it doesn't crash
}
func main() { func main() {
arraycmptest(); arraycmptest();
maptest(); maptest();
maptest2(); maptest2();
chantest(); chantest();
interfacetest();
} }
...@@ -22,7 +22,7 @@ var reverse_flag = flag.Bool("r", false, &reverse, "reverse"); ...@@ -22,7 +22,7 @@ var reverse_flag = flag.Bool("r", false, &reverse, "reverse");
var longtest bool; var longtest bool;
var longtest_flag = flag.Bool("l", false, &longtest, "long test"); var longtest_flag = flag.Bool("l", false, &longtest, "long test");
var b *[]*byte; var b []*byte;
var stats = malloc.GetStats(); var stats = malloc.GetStats();
func OkAmount(size, n uint64) bool { func OkAmount(size, n uint64) bool {
......
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