mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[] and struct in interfaces.
other [] cleanup. convert() is gone. R=r DELTA=352 (144 added, 68 deleted, 140 changed) OCL=21660 CL=21662
This commit is contained in:
parent
33907d1346
commit
c3077f7606
15 changed files with 246 additions and 170 deletions
|
|
@ -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)
|
||||||
|
|
||||||
// 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
|
||||||
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 @@
|
||||||
%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:
|
||||||
$$ = 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:
|
||||||
$$ = 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:
|
||||||
| LNEW
|
| LNEW
|
||||||
| LBASETYPE
|
| LBASETYPE
|
||||||
| LTYPEOF
|
| LTYPEOF
|
||||||
| LCONVERT
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* keywords that we can
|
* keywords that we can
|
||||||
|
|
@ -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
|
||||||
"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
|
||||||
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[] =
|
||||||
[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)
|
||||||
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:
|
||||||
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:
|
||||||
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:
|
||||||
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:
|
||||||
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)
|
||||||
// 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)
|
||||||
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 {
|
||||||
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{
|
||||||
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) {
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
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
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
goto throw;
|
goto throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// prints("old hashmap\n");
|
// prints("old itype\n");
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
// 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)
|
||||||
|
|
||||||
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;
|
goto no;
|
||||||
|
} else {
|
||||||
|
if(!algarray[alg].equal(wid, i1.data[0], i2.data[0]))
|
||||||
|
goto no;
|
||||||
|
}
|
||||||
|
|
||||||
yes:
|
yes:
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
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
|
||||||
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() {
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
if a != a {
|
|
||||||
println("fail5:", a, "!=", a);
|
func SameArray(a, b []int) bool {
|
||||||
|
if len(a) != len(b) || cap(a) != cap(b) {
|
||||||
|
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() {
|
||||||
|
|
||||||
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() {
|
||||||
|
|
||||||
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");
|
||||||
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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue