-
Notifications
You must be signed in to change notification settings - Fork 6
NamedInterfaceOf/InterfaceOf/NewInterfaceType/SetInterfaceType for llgo #84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,3 @@ | ||
| //go:build !llgo | ||
|
|
||
| package reflectx_test | ||
|
|
||
| import ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -395,3 +395,71 @@ func argsTypeSize(typ reflect.Type, offset bool) (off uintptr) { | |
| } | ||
| return | ||
| } | ||
|
|
||
| func setInterfaceMethods(st *interfaceType, unnamed bool, methods []reflect.Method) { | ||
| st.Methods = nil | ||
| var lastname string | ||
| for _, m := range methods { | ||
| if m.Name == lastname { | ||
| continue | ||
| } | ||
| lastname = m.Name | ||
| isexport := methodIsExported(m.Name) | ||
| var mname nameOff | ||
| if unnamed { | ||
| nm := newNameEx(m.Name, "", isexport, !isexport) | ||
| mname = resolveReflectName(nm) | ||
| if !isexport { | ||
| setPkgPath(nm, m.PkgPath) | ||
| } | ||
| } else { | ||
| mname = resolveReflectName(newName(m.Name, "", isexport)) | ||
| } | ||
| st.Methods = append(st.Methods, imethod{ | ||
| Name: mname, | ||
| Typ: resolveReflectType(totype(m.Type)), | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func (ctx *Context) newInterface(methods []reflect.Method) reflect.Type { | ||
| rt, _ := newType("", "", tyEmptyInterface, 0, 0) | ||
| st := (*interfaceType)(toKindType(rt)) | ||
| st.Methods = nil | ||
| var info []string | ||
| var lastname string | ||
| for _, m := range methods { | ||
| if m.Name == lastname { | ||
| continue | ||
| } | ||
| lastname = m.Name | ||
| isexport := methodIsExported(m.Name) | ||
| var mname nameOff | ||
| nm := newNameEx(m.Name, "", isexport, !isexport) | ||
| mname = resolveReflectName(nm) | ||
| if !isexport { | ||
| setPkgPath(nm, m.PkgPath) | ||
| } | ||
| st.Methods = append(st.Methods, imethod{ | ||
| Name: mname, | ||
| Typ: resolveReflectType(totype(m.Type)), | ||
| }) | ||
| info = append(info, methodStr(m.Name, m.Type)) | ||
| } | ||
| if len(st.Methods) > 0 { | ||
| rt.Equal = interequal | ||
| } | ||
| var str string | ||
| if len(info) > 0 { | ||
| str = fmt.Sprintf("*interface { %v }", strings.Join(info, "; ")) | ||
| } else { | ||
| str = "*interface {}" | ||
| } | ||
| if t, ok := ctx.interfceLookupCache[str]; ok { | ||
| return t | ||
| } | ||
| rt.Str = resolveReflectName(newName(str, "", false)) | ||
| typ := toType(rt) | ||
| ctx.interfceLookupCache[str] = typ | ||
| return typ | ||
| } | ||
|
Comment on lines
+425
to
+465
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The func (ctx *Context) newInterface(methods []reflect.Method) reflect.Type {
var str string
var sb strings.Builder
var lastname string
first := true
for _, m := range methods {
if m.Name == lastname {
continue
}
lastname = m.Name
if first {
sb.WriteString("*interface { ")
first = false
} else {
sb.WriteString("; ")
}
sb.WriteString(methodStr(m.Name, m.Type))
}
if first {
str = "*interface {}"
} else {
sb.WriteString(" }")
str = sb.String()
}
if t, ok := ctx.interfceLookupCache[str]; ok {
return t
}
rt, _ := newType("", "", tyEmptyInterface, 0, 0)
st := (*interfaceType)(toKindType(rt))
st.Methods = nil
lastname = ""
for _, m := range methods {
if m.Name == lastname {
continue
}
lastname = m.Name
isexport := methodIsExported(m.Name)
var mname nameOff
nm := newNameEx(m.Name, "", isexport, !isexport)
mname = resolveReflectName(nm)
if !isexport {
setPkgPath(nm, m.PkgPath)
}
st.Methods = append(st.Methods, imethod{
Name: mname,
Typ: resolveReflectType(totype(m.Type)),
})
}
if len(st.Methods) > 0 {
rt.Equal = interequal
}
rt.Str = resolveReflectName(newName(str, "", false))
typ := toType(rt)
ctx.interfceLookupCache[str] = typ
return typ
} |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,9 +3,12 @@ | |
| package reflectx | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "path" | ||
| "reflect" | ||
| "sort" | ||
| "strconv" | ||
| "strings" | ||
| "unsafe" | ||
| ) | ||
|
|
||
|
|
@@ -131,6 +134,12 @@ func rtypeMethodByNameX(t *rtype, name string) (m reflect.Method, ok bool) { | |
| return reflect.Method{}, false | ||
| } | ||
|
|
||
| //go:linkname interequal github.com/goplus/llgo/runtime/internal/runtime.interequal | ||
| func interequal(p, q unsafe.Pointer) bool | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| //go:linkname haveIdenticalType reflect.haveIdenticalType | ||
| func haveIdenticalType(T, V *rtype, cmpTags bool) bool | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This unconditionally links to |
||
|
|
||
| //go:linkname closureOf reflect.closureOf | ||
| func closureOf(ftyp *funcType) *rtype | ||
|
|
||
|
|
@@ -296,3 +305,96 @@ func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) | |
| func toWord(i interface{}) unsafe.Pointer { | ||
| return (*emptyInterface)(unsafe.Pointer(&i)).word | ||
| } | ||
|
|
||
| func (ctx *Context) Reset() { | ||
| } | ||
|
|
||
| func resetAll() { | ||
| } | ||
|
|
||
| func newMethodSet(styp reflect.Type, maxmfunc, maxpfunc int) reflect.Type { | ||
| // rt, _ := newType("", "", styp, maxmfunc, 0) | ||
| // prt, _ := newType("", "", PtrTo(styp), maxpfunc, 0) | ||
| // rt.PtrToThis = resolveReflectType(prt) | ||
| // (*ptrType)(unsafe.Pointer(prt)).Elem = rt | ||
| // setTypeName(rt, styp.PkgPath(), styp.Name()) | ||
| // prt.Uncommon().PkgPath = resolveReflectName(newName(styp.PkgPath(), "", false)) | ||
| // return toType(rt) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| panic("TODO newMethodSet") | ||
| return nil | ||
| } | ||
|
|
||
| func (ctx *Context) setMethodSet(typ reflect.Type, methods []Method, sortMethods bool) error { | ||
| if sortMethods { | ||
| sort.Slice(methods, func(i, j int) bool { | ||
| n := strings.Compare(methods[i].Name, methods[j].Name) | ||
| if n == 0 && methods[i].PkgPath == methods[j].PkgPath { | ||
| panic(fmt.Sprintf("method redeclared: %v", methods[j].Name)) | ||
| } | ||
| return n < 0 | ||
| }) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
| return nil | ||
| } | ||
|
Comment on lines
+327
to
+338
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The func (ctx *Context) setMethodSet(typ reflect.Type, methods []Method, sortMethods bool) error {
return fmt.Errorf("setMethodSet: not implemented on llgo")
} |
||
|
|
||
| func setInterfaceMethods(st *interfaceType, unnamed bool, methods []reflect.Method) { | ||
| st.Methods = nil | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| var lastname string | ||
| var mname string | ||
| for _, m := range methods { | ||
| if m.Name == lastname { | ||
| continue | ||
| } | ||
| lastname = m.Name | ||
| if !methodIsExported(m.Name) { | ||
| mname = m.PkgPath + "." + m.Name | ||
| } else { | ||
| mname = m.Name | ||
| } | ||
| st.Methods = append(st.Methods, imethod{ | ||
| Name_: mname, | ||
| Typ_: totype(m.Type).FuncType(), | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func (ctx *Context) newInterface(methods []reflect.Method) reflect.Type { | ||
| rt, _ := newType("", "", tyEmptyInterface, 0, 0) | ||
| st := (*interfaceType)(toKindType(rt)) | ||
| st.Methods = nil | ||
| var info []string | ||
| var lastname string | ||
| var mname string | ||
| for _, m := range methods { | ||
| if m.Name == lastname { | ||
| continue | ||
| } | ||
| lastname = m.Name | ||
| if !methodIsExported(m.Name) { | ||
| mname = m.PkgPath + "." + m.Name | ||
| } else { | ||
| mname = m.Name | ||
| } | ||
| st.Methods = append(st.Methods, imethod{ | ||
| Name_: mname, | ||
| Typ_: totype(m.Type).FuncType(), | ||
| }) | ||
| info = append(info, methodStr(m.Name, m.Type)) | ||
| } | ||
| if len(st.Methods) > 0 { | ||
| rt.Equal = interequal | ||
| } | ||
| var str string | ||
| if len(info) > 0 { | ||
| str = fmt.Sprintf("*interface { %v }", strings.Join(info, "; ")) | ||
| } else { | ||
| str = "*interface {}" | ||
| } | ||
| if t, ok := ctx.interfceLookupCache[str]; ok { | ||
| return t | ||
| } | ||
| rt.Str_ = str | ||
| typ := toType(rt) | ||
| ctx.interfceLookupCache[str] = typ | ||
| return typ | ||
| } | ||
|
Comment on lines
+361
to
+400
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the non-llgo implementation, func (ctx *Context) newInterface(methods []reflect.Method) reflect.Type {
var str string
var sb strings.Builder
var lastname string
first := true
for _, m := range methods {
if m.Name == lastname {
continue
}
lastname = m.Name
if first {
sb.WriteString("*interface { ")
first = false
} else {
sb.WriteString("; ")
}
sb.WriteString(methodStr(m.Name, m.Type))
}
if first {
str = "*interface {}"
} else {
sb.WriteString(" }")
str = sb.String()
}
if t, ok := ctx.interfceLookupCache[str]; ok {
return t
}
rt, _ := newType("", "", tyEmptyInterface, 0, 0)
st := (*interfaceType)(toKindType(rt))
st.Methods = nil
lastname = ""
var mname string
for _, m := range methods {
if m.Name == lastname {
continue
}
lastname = m.Name
if !methodIsExported(m.Name) {
mname = m.PkgPath + "." + m.Name
} else {
mname = m.Name
}
st.Methods = append(st.Methods, imethod{
Name_: mname,
Typ_: totype(m.Type).FuncType(),
})
}
if len(st.Methods) > 0 {
rt.Equal = interequal
}
rt.Str_ = str
typ := toType(rt)
ctx.interfceLookupCache[str] = typ
return typ
} |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing
//go:build !llgomeans tests callingreflectx.NewMethodSet(e.g.TestIntMethodOf,TestSliceMethodOf,TestStructMethodOf) will panic under llgo becausenewMethodSetalways panics. Consider splitting llgo-compatible tests into a separate file or addingt.Skipguards for theNewMethodSet-dependent tests until that path is implemented.