internal/runtime: impl ifaceE2I

This commit is contained in:
visualfc
2024-12-17 12:42:30 +08:00
parent 281d29a100
commit d81c5e750d
3 changed files with 140 additions and 4 deletions

View File

@@ -4,6 +4,12 @@
package runtime
import (
"unsafe"
"github.com/goplus/llgo/runtime/abi"
)
// A boundsError represents an indexing or slicing operation gone wrong.
type boundsError struct {
x int64
@@ -114,3 +120,54 @@ func itoa(buf []byte, val uint64) []byte {
func PanicSliceConvert(x int, y int) {
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsConvert})
}
// A TypeAssertionError explains a failed type assertion.
type TypeAssertionError struct {
_interface *_type
concrete *_type
asserted *_type
missingMethod string // one method needed by Interface, missing from Concrete
}
func (*TypeAssertionError) RuntimeError() {}
func (e *TypeAssertionError) Error() string {
inter := "interface"
if e._interface != nil {
inter = e._interface.String()
}
as := e.asserted.String()
if e.concrete == nil {
return "interface conversion: " + inter + " is nil, not " + as
}
cs := e.concrete.String()
if e.missingMethod == "" {
msg := "interface conversion: " + inter + " is " + cs + ", not " + as
if cs == as {
// provide slightly clearer error message
if pkgpath(e.concrete) != pkgpath(e.asserted) {
msg += " (types from different packages)"
} else {
msg += " (types from different scopes)"
}
}
return msg
}
return "interface conversion: " + cs + " is not " + as +
": missing method " + e.missingMethod
}
func pkgpath(t *_type) string {
if u := t.Uncommon(); u != nil {
return u.PkgPath_
}
switch t.Kind() {
case abi.Struct:
st := (*structtype)(unsafe.Pointer(t))
return st.PkgPath_
case abi.Interface:
it := (*interfacetype)(unsafe.Pointer(t))
return it.PkgPath_
}
return ""
}