diff options
Diffstat (limited to 'src/pkg/runtime/iface.c')
-rw-r--r-- | src/pkg/runtime/iface.c | 208 |
1 files changed, 130 insertions, 78 deletions
diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c index 55a1362c6..35a710eca 100644 --- a/src/pkg/runtime/iface.c +++ b/src/pkg/runtime/iface.c @@ -177,26 +177,26 @@ copyout(Type *t, void **src, void *dst) algarray[alg].copy(wid, dst, *src); } -// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret Iface); +// func convT2I(typ *byte, typ2 *byte, elem any) (ret any) #pragma textflag 7 void -·ifaceT2I(InterfaceType *inter, Type *t, ...) +·convT2I(Type *t, InterfaceType *inter, ...) { byte *elem; Iface *ret; int32 wid; - elem = (byte*)(&t+1); + elem = (byte*)(&inter+1); wid = t->size; ret = (Iface*)(elem + rnd(wid, Structrnd)); ret->tab = itab(inter, t, 0); copyin(t, elem, &ret->data); } -// ifaceT2E(sigt *byte, elem any) (ret Eface); +// func convT2E(typ *byte, elem any) (ret any) #pragma textflag 7 void -·ifaceT2E(Type *t, ...) +·convT2E(Type *t, ...) { byte *elem; Eface *ret; @@ -205,15 +205,14 @@ void elem = (byte*)(&t+1); wid = t->size; ret = (Eface*)(elem + rnd(wid, Structrnd)); - ret->type = t; copyin(t, elem, &ret->data); } -// ifaceI2T(sigt *byte, iface any) (ret any); +// func ifaceI2T(typ *byte, iface any) (ret any) #pragma textflag 7 void -·ifaceI2T(Type *t, Iface i, ...) +·assertI2T(Type *t, Iface i, ...) { Itab *tab; byte *ret; @@ -236,10 +235,10 @@ void copyout(t, &i.data, ret); } -// ifaceI2T2(sigt *byte, i Iface) (ret any, ok bool); +// func ifaceI2T2(typ *byte, iface any) (ret any, ok bool) #pragma textflag 7 void -·ifaceI2T2(Type *t, Iface i, ...) +·assertI2T2(Type *t, Iface i, ...) { byte *ret; bool *ok; @@ -259,10 +258,10 @@ void copyout(t, &i.data, ret); } -// ifaceE2T(sigt *byte, e Eface) (ret any); +// func ifaceE2T(typ *byte, iface any) (ret any) #pragma textflag 7 void -·ifaceE2T(Type *t, Eface e, ...) +·assertE2T(Type *t, Eface e, ...) { byte *ret; Eface err; @@ -284,10 +283,10 @@ void copyout(t, &e.data, ret); } -// ifaceE2T2(sigt *byte, iface any) (ret any, ok bool); +// func ifaceE2T2(sigt *byte, iface any) (ret any, ok bool); #pragma textflag 7 void -·ifaceE2T2(Type *t, Eface e, ...) +·assertE2T2(Type *t, Eface e, ...) { byte *ret; bool *ok; @@ -307,50 +306,82 @@ void copyout(t, &e.data, ret); } -// ifaceI2E(sigi *byte, iface any) (ret any); -// TODO(rsc): Move to back end, throw away function. +// func convI2E(elem any) (ret any) +#pragma textflag 7 void -·ifaceI2E(Iface i, Eface ret) +·convI2E(Iface i, Eface ret) { Itab *tab; ret.data = i.data; - tab = i.tab; - if(tab == nil) + if((tab = i.tab) == nil) ret.type = nil; else ret.type = tab->type; FLUSH(&ret); } -// ifaceI2I(sigi *byte, iface any) (ret any); -// called only for implicit (no type assertion) conversions. -// converting nil is okay. +// func ifaceI2E(typ *byte, iface any) (ret any) +#pragma textflag 7 void -·ifaceI2I(InterfaceType *inter, Iface i, Iface ret) +·assertI2E(InterfaceType* inter, Iface i, Eface ret) { Itab *tab; + Eface err; tab = i.tab; if(tab == nil) { - // If incoming interface is uninitialized (zeroed) - // make the outgoing interface zeroed as well. - ret.tab = nil; - ret.data = nil; + // explicit conversions require non-nil interface value. + ·newTypeAssertionError(nil, nil, inter, + nil, nil, inter->string, + nil, &err); + ·panic(err); + } + ret.data = i.data; + ret.type = tab->type; + FLUSH(&ret); +} + +// func ifaceI2E2(typ *byte, iface any) (ret any, ok bool) +#pragma textflag 7 +void +·assertI2E2(InterfaceType* inter, Iface i, Eface ret, bool ok) +{ + Itab *tab; + + USED(inter); + tab = i.tab; + if(tab == nil) { + ret.type = nil; + ok = 0; } else { - ret = i; - if(tab->inter != inter) - ret.tab = itab(inter, tab->type, 0); + ret.type = tab->type; + ok = 1; } + ret.data = i.data; + FLUSH(&ret); + FLUSH(&ok); +} +// func convI2I(typ *byte, elem any) (ret any) +#pragma textflag 7 +void +·convI2I(InterfaceType* inter, Iface i, Iface ret) +{ + Itab *tab; + + ret.data = i.data; + if((tab = i.tab) == nil) + ret.tab = nil; + else if(tab->inter == inter) + ret.tab = tab; + else + ret.tab = itab(inter, tab->type, 0); FLUSH(&ret); } -// ifaceI2Ix(sigi *byte, iface any) (ret any); -// called only for explicit conversions (with type assertion). -// converting nil is not okay. void -·ifaceI2Ix(InterfaceType *inter, Iface i, Iface ret) +ifaceI2I(InterfaceType *inter, Iface i, Iface *ret) { Itab *tab; Eface err; @@ -362,45 +393,40 @@ void nil, nil, inter->string, nil, &err); ·panic(err); - } else { - ret = i; - if(tab->inter != inter) - ret.tab = itab(inter, tab->type, 0); } + ret->data = i.data; + ret->tab = itab(inter, tab->type, 0); +} - FLUSH(&ret); +// func ifaceI2I(sigi *byte, iface any) (ret any) +#pragma textflag 7 +void +·assertI2I(InterfaceType* inter, Iface i, Iface ret) +{ + ifaceI2I(inter, i, &ret); } -// ifaceI2I2(sigi *byte, iface any) (ret any, ok bool); +// func ifaceI2I2(sigi *byte, iface any) (ret any, ok bool) +#pragma textflag 7 void -·ifaceI2I2(InterfaceType *inter, Iface i, Iface ret, bool ok) +·assertI2I2(InterfaceType *inter, Iface i, Iface ret, bool ok) { Itab *tab; tab = i.tab; - if(tab == nil) { - // If incoming interface is nil, the conversion fails. - ret.tab = nil; - ret.data = nil; - ok = false; + if(tab != nil && (tab->inter == inter || (tab = itab(inter, tab->type, 1)) != nil)) { + ret.data = i.data; + ret.tab = tab; + ok = 1; } else { - ret = i; - ok = true; - if(tab->inter != inter) { - ret.tab = itab(inter, tab->type, 1); - if(ret.tab == nil) { - ret.data = nil; - ok = false; - } - } + ret.data = 0; + ret.tab = 0; + ok = 0; } - FLUSH(&ret); FLUSH(&ok); } -// ifaceE2I(sigi *byte, iface any) (ret any); -// Called only for explicit conversions (with type assertion). void ifaceE2I(InterfaceType *inter, Eface e, Iface *ret) { @@ -414,45 +440,71 @@ ifaceE2I(InterfaceType *inter, Eface e, Iface *ret) nil, nil, inter->string, nil, &err); ·panic(err); - } else { - ret->data = e.data; - ret->tab = itab(inter, t, 0); } + ret->data = e.data; + ret->tab = itab(inter, t, 0); } -// ifaceE2I(sigi *byte, iface any) (ret any); -// Called only for explicit conversions (with type assertion). +// func ifaceE2I(sigi *byte, iface any) (ret any) +#pragma textflag 7 void -·ifaceE2I(InterfaceType *inter, Eface e, Iface ret) +·assertE2I(InterfaceType* inter, Eface e, Iface ret) { ifaceE2I(inter, e, &ret); } -// ifaceE2I2(sigi *byte, iface any) (ret any, ok bool); +// ifaceE2I2(sigi *byte, iface any) (ret any, ok bool) +#pragma textflag 7 void -·ifaceE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok) +·assertE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok) { - Type *t; - - t = e.type; - ok = true; - if(t == nil) { - // If incoming interface is nil, the conversion fails. + if(e.type == nil) { + ok = 0; ret.data = nil; ret.tab = nil; - ok = false; + } else if((ret.tab = itab(inter, e.type, 1)) == nil) { + ok = 0; + ret.data = nil; } else { + ok = 1; ret.data = e.data; - ret.tab = itab(inter, t, 1); - if(ret.tab == nil) { - ret.data = nil; - ok = false; - } } FLUSH(&ret); FLUSH(&ok); } +// func ifaceE2E(typ *byte, iface any) (ret any) +#pragma textflag 7 +void +·assertE2E(InterfaceType* inter, Eface e, Eface ret) +{ + Type *t; + Eface err; + + t = e.type; + if(t == nil) { + // explicit conversions require non-nil interface value. + ·newTypeAssertionError(nil, nil, inter, + nil, nil, inter->string, + nil, &err); + ·panic(err); + } + ret = e; + FLUSH(&ret); +} + +// func ifaceE2E2(iface any) (ret any, ok bool) +#pragma textflag 7 +void +·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok) +{ + USED(inter); + ret = e; + ok = e.type != nil; + FLUSH(&ret); + FLUSH(&ok); +} + static uintptr ifacehash1(void *data, Type *t) { |