Skip to content
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

initThisGopPkg: overloadNameds; NewOverloadNamed #339

Merged
merged 6 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func toExpr(pkg *Package, val interface{}, src ast.Node) *internal.Elem {
Src: src,
}
case *types.TypeName:
if typ := v.Type(); isType(typ) {
if typ := v.Type(); isTypeType(typ) {
return &internal.Elem{
Val: toType(pkg, typ), Type: NewTypeType(typ), Src: src,
}
Expand Down Expand Up @@ -694,7 +694,7 @@ retry:
} else if t.hasApproxType() {
flags |= instrFlagApproxType
}
case *instructionType:
case *TyInstruction:
return t.instr.Call(pkg, args, flags, fn.Src)
case *types.Named:
fnType = pkg.cb.getUnderlying(t)
Expand Down
32 changes: 29 additions & 3 deletions builtin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,28 @@ func getConf() *Config {
return &Config{Fset: fset, Importer: imp}
}

func TestOverloadNameds(t *testing.T) {
pkg := types.NewPackage("", "")
tn := types.NewTypeName(0, pkg, "foo__1", nil)
named := types.NewNamed(tn, TyByte, nil)
func() {
defer func() {
if e := recover(); e != "overload type foo__1 out of range 0..0\n" {
t.Fatal("TestOverloadFuncs:", e)
}
}()
overloadNameds(5, []*types.Named{named})
}()
func() {
defer func() {
if e := recover(); e != "overload type foo__1 exists?\n" {
t.Fatal("TestOverloadFuncs:", e)
}
}()
overloadNameds(5, []*types.Named{named, named})
}()
}

func TestOverloadFuncs(t *testing.T) {
pkg := types.NewPackage("", "")
fn := types.NewFunc(0, pkg, "foo__1", nil)
Expand Down Expand Up @@ -564,8 +586,8 @@ func TestMethodAutoProperty(t *testing.T) {
}
}

func TestIsType(t *testing.T) {
if isType(sigFuncEx(nil, nil, &TyOverloadFunc{})) {
func TestIsTypeType(t *testing.T) {
if isTypeType(sigFuncEx(nil, nil, &TyOverloadFunc{})) {
t.Fatal("TestIsType: isType(TyOverloadFunc)")
}
}
Expand All @@ -585,7 +607,8 @@ func TestUnderlying(t *testing.T) {
&TyOverloadFunc{},
&TyOverloadMethod{},
&TyTemplateRecvMethod{},
&instructionType{},
&TyInstruction{},
&TyOverloadNamed{},
&TypeType{},
&unboundFuncParam{},
&unboundProxyParam{},
Expand All @@ -609,6 +632,9 @@ func TestUnderlying(t *testing.T) {
if fex, ok := typ.(TyFuncEx); ok {
fex.funcEx()
}
if fex, ok := typ.(TyTypeEx); ok {
fex.typeEx()
}
if typ.Underlying() == typ {
panic("noop Underlying")
}
Expand Down
2 changes: 1 addition & 1 deletion codebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -1820,7 +1820,7 @@ func (p *CodeBuilder) IncDec(op token.Token, src ...ast.Node) *CodeBuilder {
if fn == nil {
panic("TODO: operator not matched")
}
t := fn.Type().(*instructionType)
t := fn.Type().(*TyInstruction)
if _, err := t.instr.Call(pkg, []*Element{arg}, 0, nil); err != nil {
panic(err)
}
Expand Down
4 changes: 0 additions & 4 deletions func.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,4 @@ type Instruction interface {
Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error)
}

func NewInstruction(pos token.Pos, pkg *types.Package, name string, instr Instruction) *types.TypeName {
return types.NewTypeName(pos, pkg, name, &instructionType{instr})
}

// ----------------------------------------------------------------------------
69 changes: 53 additions & 16 deletions import.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,19 @@ func shouldAddGopPkg(pkg *Package) bool {
return pkg.isGopPkg && pkg.Types.Scope().Lookup(gopPackage) == nil
}

func isGopoConst(name string) bool {
return strings.HasPrefix(name, gopoPrefix)
}

func isGopFunc(name string) bool {
return isOverloadFunc(name) || isGoptFunc(name)
return isOverload(name) || isGoptFunc(name)
}

func isGoptFunc(name string) bool {
return strings.HasPrefix(name, goptPrefix)
}

func isGopoFunc(name string) bool {
return strings.HasPrefix(name, gopoPrefix)
}

func isOverloadFunc(name string) bool {
func isOverload(name string) bool {
n := len(name)
return n > 3 && name[n-3:n-1] == "__"
}
Expand All @@ -115,18 +115,18 @@ func initThisGopPkg(pkg *types.Package) {
}
gopos := make([]string, 0, 4)
overloads := make(map[omthd][]types.Object)
onameds := make(map[string][]*types.Named)
names := scope.Names()
for _, name := range names {
if isGopoConst(name) {
gopos = append(gopos, name)
continue
}
o := scope.Lookup(name)
if tn, ok := o.(*types.TypeName); ok && tn.IsAlias() {
continue
}
if isGopoFunc(name) {
gopos = append(gopos, name)
} else if isOverloadFunc(name) { // overload function
key := omthd{nil, name[:len(name)-3]}
overloads[key] = append(overloads[key], o)
} else if named, ok := o.Type().(*types.Named); ok {
if named, ok := o.Type().(*types.Named); ok {
var list methodList
switch t := named.Underlying().(type) {
case *types.Interface:
Expand All @@ -137,12 +137,19 @@ func initThisGopPkg(pkg *types.Package) {
for i, n := 0, list.NumMethods(); i < n; i++ {
m := list.Method(i)
mName := m.Name()
if isOverloadFunc(mName) { // overload method
if isOverload(mName) { // overload method
mthd := mName[:len(mName)-3]
key := omthd{named, mthd}
overloads[key] = append(overloads[key], m)
}
}
if isOverload(name) { // overload named
key := name[:len(name)-3]
onameds[key] = append(onameds[key], named)
}
} else if isOverload(name) { // overload function
key := omthd{nil, name[:len(name)-3]}
overloads[key] = append(overloads[key], o)
} else {
checkTemplateMethod(pkg, name, o)
}
Expand Down Expand Up @@ -170,6 +177,15 @@ func initThisGopPkg(pkg *types.Package) {
fns := overloadFuncs(off, items)
newOverload(pkg, scope, key, fns)
}
for name, items := range onameds {
off := len(name) + 2
nameds := overloadNameds(off, items)
if debugImport {
log.Println("==> NewOverloadNamed", name)
}
on := NewOverloadNamed(token.NoPos, pkg, name, nameds...)
scope.Insert(on)
}
}

// name
Expand Down Expand Up @@ -312,6 +328,22 @@ func overloadFuncs(off int, items []types.Object) []types.Object {
return fns
}

func overloadNameds(off int, items []*types.Named) []*types.Named {
nameds := make([]*types.Named, len(items))
for _, item := range items {
name := item.Obj().Name()
idx := toIndex(name[off])
if idx >= len(items) {
log.Panicf("overload type %v out of range 0..%v\n", name, len(nameds)-1)
}
if nameds[idx] != nil {
log.Panicf("overload type %v exists?\n", name)
}
nameds[idx] = item
}
return nameds
}

func toIndex(c byte) int {
if c >= '0' && c <= '9' {
return int(c - '0')
Expand All @@ -331,18 +363,23 @@ const (
// Context represents all things between packages.
type Context struct {
chkGopImports map[string]bool
stdPkg func(pkgPath string) bool
}

func NewContext() *Context {
func NewContext(isPkgtStandard func(pkgPath string) bool) *Context {
if isPkgtStandard == nil {
isPkgtStandard = isStdPkg
}
return &Context{
chkGopImports: make(map[string]bool),
stdPkg: isPkgtStandard,
}
}

// initGopPkg initializes a Go+ packages.
func (p *Context) initGopPkg(importer types.Importer, pkgImp *types.Package) {
pkgPath := pkgImp.Path()
if stdPkg(pkgPath) || p.chkGopImports[pkgPath] {
if p.stdPkg(pkgPath) || p.chkGopImports[pkgPath] {
return
}
if !pkgImp.Complete() {
Expand All @@ -355,7 +392,7 @@ func (p *Context) initGopPkg(importer types.Importer, pkgImp *types.Package) {
}
}

func stdPkg(pkgPath string) bool {
func isStdPkg(pkgPath string) bool {
return strings.IndexByte(pkgPath, '.') < 0
}

Expand Down
11 changes: 7 additions & 4 deletions package.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ type Config struct {
// Context represents all things between packages (optional).
Context *Context

// IsPkgtStandard checks a pkgPath is a Go standard package or not.
IsPkgtStandard func(pkgPath string) bool

// HandleErr is called to handle errors (optional).
HandleErr func(err error)

Expand Down Expand Up @@ -131,11 +134,11 @@ type Config struct {
// A Recorder records selected objects such as methods, etc (optional).
Recorder Recorder

// NoSkipConstant is to disable optimization of skipping constant (optional).
NoSkipConstant bool

// (internal) only for testing
DbgPositioner dbgPositioner

// NoSkipConstant is to disable optimization of skipping constant (optional).
NoSkipConstant bool
}

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -348,7 +351,7 @@ func NewPackage(pkgPath, name string, conf *Config) *Package {
}
ctx := conf.Context
if ctx == nil {
ctx = NewContext()
ctx = NewContext(conf.IsPkgtStandard)
}
imp := conf.Importer
if imp == nil {
Expand Down
9 changes: 9 additions & 0 deletions package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"go/types"
"log"
"os"
"strings"
"syscall"
"testing"
"unsafe"
Expand Down Expand Up @@ -55,6 +56,12 @@ func (p eventRecorder) Member(id ast.Node, obj types.Object) {
func (p eventRecorder) Call(fn ast.Node, obj types.Object) {
}

func isStdPkg(pkgPath string) bool {
is := pkgPath != "foo" && strings.IndexByte(pkgPath, '.') < 0
log.Println("isStdPkg:", pkgPath, is)
return is
}

func newMainPackage(
implicitCast ...func(pkg *gox.Package, V, T types.Type, pv *gox.Element) bool) *gox.Package {
conf := &gox.Config{
Expand All @@ -63,6 +70,7 @@ func newMainPackage(
Recorder: eventRecorder{},
NodeInterpreter: nodeInterp{},
DbgPositioner: nodeInterp{},
IsPkgtStandard: isStdPkg,
}
if len(implicitCast) > 0 {
conf.CanImplicitCast = implicitCast[0]
Expand Down Expand Up @@ -142,6 +150,7 @@ func (p *goxTest) NewPackage(pkgPath string, name string) *gox.Package {
Importer: p.imp,
NodeInterpreter: nodeInterp{},
DbgPositioner: nodeInterp{},
IsPkgtStandard: isStdPkg,
}
return gox.NewPackage(pkgPath, name, conf)
}
Expand Down
Loading