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

iOverloadType/iSubstType #350

Merged
merged 1 commit into from
Jan 24, 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
40 changes: 30 additions & 10 deletions builtin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,12 +614,14 @@ func TestIsTypeType(t *testing.T) {
}
}

func TestUnderlying(t *testing.T) {
subst := &SubstType{}
func TestTypeEx(t *testing.T) {
subst := &TySubst{}
bfReft := &bfRefType{typ: tyInt}
if typ, ok := DerefType(bfReft); !ok || typ != tyInt {
t.Fatal("TestDerefType failed")
}
pkg := NewPackage("example.com/foo", "foo", gblConf)
tyInt := types.Typ[types.Int]
typs := []types.Type{
&refType{},
subst,
Expand All @@ -630,7 +632,7 @@ func TestUnderlying(t *testing.T) {
&TyOverloadMethod{},
&TyTemplateRecvMethod{},
&TyInstruction{},
&TyOverloadNamed{},
&TyOverloadNamed{Obj: types.NewTypeName(0, pkg.Types, "bar", tyInt)},
&TypeType{},
&unboundFuncParam{},
&unboundProxyParam{},
Expand All @@ -645,23 +647,41 @@ func TestUnderlying(t *testing.T) {
}
for _, typ := range typs {
func() {
defer func() {
if e := recover(); e == nil {
t.Fatal("TestUnderlying failed: no error?")
}
}()
log.Println("type:", typ.String())
if fex, ok := typ.(TyFuncEx); ok {
fex.funcEx()
}
if fex, ok := typ.(TyTypeEx); ok {
fex.typeEx()
}
if typ.Underlying() == typ {
panic("noop Underlying")
if fex, ok := typ.(iSubstType); ok {
fex.Obj()
}
if fex, ok := typ.(iOverloadType); ok {
fex.Len()
func() {
defer func() {
if e := recover(); e == nil {
t.Fatal("iOverloadType.At: no error?")
}
}()
fex.At(0)
}()
}
typ.Underlying()
}()
}
bte := &boundTypeError{tyInt, TyByte}
if bte.Error() != "boundType int => byte failed" {
t.Fatal("boundTypeError:", bte)
}
ut := &unboundType{tBound: tyInt}
defer func() {
if e := recover(); e == nil {
t.Fatal("unboundType.boundTo: no error?")
}
}()
ut.boundTo(pkg, TyByte)
}

func TestIsNumeric(t *testing.T) {
Expand Down
7 changes: 7 additions & 0 deletions func_ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ type TyOverloadFunc struct {
Funcs []types.Object
}

func (p *TyOverloadFunc) At(i int) types.Object { return p.Funcs[i] }
func (p *TyOverloadFunc) Len() int { return len(p.Funcs) }

func (p *TyOverloadFunc) Underlying() types.Type { return p }
func (p *TyOverloadFunc) String() string { return "TyOverloadFunc" }
func (p *TyOverloadFunc) funcEx() {}
Expand All @@ -110,6 +113,9 @@ type TyOverloadMethod struct {
Methods []types.Object
}

func (p *TyOverloadMethod) At(i int) types.Object { return p.Methods[i] }
func (p *TyOverloadMethod) Len() int { return len(p.Methods) }

func (p *TyOverloadMethod) Underlying() types.Type { return p }
func (p *TyOverloadMethod) String() string { return "TyOverloadMethod" }
func (p *TyOverloadMethod) funcEx() {}
Expand All @@ -133,6 +139,7 @@ type TyTemplateRecvMethod struct {
Func types.Object
}

func (p *TyTemplateRecvMethod) Obj() types.Object { return p.Func }
func (p *TyTemplateRecvMethod) Underlying() types.Type { return p }
func (p *TyTemplateRecvMethod) String() string { return "TyTemplateRecvMethod" }
func (p *TyTemplateRecvMethod) funcEx() {}
Expand Down
22 changes: 5 additions & 17 deletions template.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ func NewTemplateParamType(idx int, name string, contract Contract) *TemplatePara
return &TemplateParamType{idxFlag: idx, name: name, contract: contract}
}

func (p *TemplateParamType) Underlying() types.Type {
panic("TemplateParamType")
}

func (p *TemplateParamType) Underlying() types.Type { return p }
func (p *TemplateParamType) String() string {
return fmt.Sprintf("TemplateParamType{name: %v}", p.name)
}
Expand Down Expand Up @@ -76,10 +73,7 @@ func (p *unboundFuncParam) boundTo(pkg *Package, t types.Type, parg *internal.El
p.tBound, p.parg = t, parg
}

func (p *unboundFuncParam) Underlying() types.Type {
panic("unboundFuncParam")
}

func (p *unboundFuncParam) Underlying() types.Type { return p }
func (p *unboundFuncParam) String() string {
return fmt.Sprintf("unboundFuncParam{typ: %v}", p.tBound)
}
Expand All @@ -88,10 +82,7 @@ type unboundProxyParam struct {
real types.Type
}

func (p *unboundProxyParam) Underlying() types.Type {
panic("unboundProxyParam")
}

func (p *unboundProxyParam) Underlying() types.Type { return p }
func (p *unboundProxyParam) String() string {
return fmt.Sprintf("unboundProxyParam{typ: %v}", p.real)
}
Expand Down Expand Up @@ -710,12 +701,9 @@ func NewTemplateSignature(
return tsig
}

func (p *TemplateSignature) Underlying() types.Type {
panic("TemplateSignature")
}

func (p *TemplateSignature) Underlying() types.Type { return p }
func (p *TemplateSignature) String() string {
return p.sig.String()
return fmt.Sprintf("TemplateSignature{%v}", p.sig)
}

// TODO: check name
Expand Down
145 changes: 82 additions & 63 deletions type_ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,45 @@ import (

// ----------------------------------------------------------------------------

// Go+ overload extended types
type iOverloadType interface {
At(i int) types.Object
Len() int
}

var (
_ iOverloadType = (*TyOverloadNamed)(nil)
_ iOverloadType = (*TyOverloadFunc)(nil)
_ iOverloadType = (*TyOverloadMethod)(nil)
)

// ----------------------------------------------------------------------------

type iSubstType interface {
Obj() types.Object
}

var (
_ iSubstType = (*TyTemplateRecvMethod)(nil)
_ iSubstType = (*TySubst)(nil)
)

// ----------------------------------------------------------------------------

// TyTypeEx is a TypeEx type.
type TyTypeEx interface {
types.Type
typeEx()
}

var (
_ TyTypeEx = (*TyOverloadNamed)(nil)
_ TyTypeEx = (*TyInstruction)(nil)
_ TyTypeEx = (*TySubst)(nil)
)

// ----------------------------------------------------------------------------

// IsTypeEx returns if t is a gox extended type or not.
func IsTypeEx(t types.Type) (ok bool) {
switch v := t.(type) {
Expand Down Expand Up @@ -60,9 +93,15 @@ type TyOverloadNamed struct {
Obj *types.TypeName
}

func (p *TyOverloadNamed) At(i int) types.Object { return p.Types[i].Obj() }
func (p *TyOverloadNamed) Len() int { return len(p.Types) }

func (p *TyOverloadNamed) typeEx() {}
func (p *TyOverloadNamed) Underlying() types.Type { return p }
func (p *TyOverloadNamed) String() string { return p.Obj.Name() }
func (p *TyOverloadNamed) String() string {
o := p.Obj
return fmt.Sprintf("TyOverloadNamed{%s.%s}", o.Pkg().Path(), o.Name())
}

func NewOverloadNamed(pos token.Pos, pkg *types.Package, name string, typs ...*types.Named) *types.TypeName {
t := &TyOverloadNamed{Types: typs}
Expand All @@ -85,6 +124,43 @@ func NewInstruction(pos token.Pos, pkg *types.Package, name string, instr Instru
return types.NewTypeName(pos, pkg, name, &TyInstruction{instr})
}

// Deprecated: use TySubst instead of SubstType.
type SubstType = TySubst

type TySubst struct {
Real types.Object
}

func (p *TySubst) Obj() types.Object { return p.Real }

func (p *TySubst) typeEx() {}
func (p *TySubst) Underlying() types.Type { return p }
func (p *TySubst) String() string {
return fmt.Sprintf("substType{real: %v}", p.Real)
}

func NewSubst(pos token.Pos, pkg *types.Package, name string, real types.Object) *types.Var {
return types.NewVar(pos, pkg, name, &TySubst{Real: real})
}

func LookupParent(scope *types.Scope, name string, pos token.Pos) (at *types.Scope, obj types.Object) {
if at, obj = scope.LookupParent(name, pos); obj != nil {
if t, ok := obj.Type().(*TySubst); ok {
obj = t.Real
}
}
return
}

func Lookup(scope *types.Scope, name string) (obj types.Object) {
if obj = scope.Lookup(name); obj != nil {
if t, ok := obj.Type().(*TySubst); ok {
obj = t.Real
}
}
return
}

// ----------------------------------------------------------------------------

var (
Expand All @@ -106,11 +182,7 @@ func (p *refType) Elem() types.Type {
return p.typ
}

func (p *refType) Underlying() types.Type {
fatal("ref type")
return nil
}

func (p *refType) Underlying() types.Type { return p }
func (p *refType) String() string {
return fmt.Sprintf("refType{typ: %v}", p.typ)
}
Expand All @@ -132,11 +204,7 @@ type bfRefType struct {
bits int
}

func (p *bfRefType) Underlying() types.Type {
fatal("bit field refType")
return nil
}

func (p *bfRefType) Underlying() types.Type { return p }
func (p *bfRefType) String() string {
return fmt.Sprintf("bfRefType{typ: %v:%d off: %d}", p.typ, p.bits, p.off)
}
Expand All @@ -158,11 +226,7 @@ func (p *unboundType) boundTo(pkg *Package, arg types.Type) {
p.ptypes = nil
}

func (p *unboundType) Underlying() types.Type {
fatal("unbound type")
return nil
}

func (p *unboundType) Underlying() types.Type { return p }
func (p *unboundType) String() string {
return fmt.Sprintf("unboundType{typ: %v}", p.tBound)
}
Expand All @@ -186,11 +250,7 @@ type unboundMapElemType struct {
typ *unboundType
}

func (p *unboundMapElemType) Underlying() types.Type {
fatal("unbound map elem type")
return nil
}

func (p *unboundMapElemType) Underlying() types.Type { return p }
func (p *unboundMapElemType) String() string {
return fmt.Sprintf("unboundMapElemType{key: %v}", p.key)
}
Expand Down Expand Up @@ -220,50 +280,9 @@ func (p *TypeType) Type() types.Type {
return p.typ
}

func (p *TypeType) Underlying() types.Type {
fatal("type of type")
return nil
}

func (p *TypeType) Underlying() types.Type { return p }
func (p *TypeType) String() string {
return fmt.Sprintf("TypeType{typ: %v}", p.typ)
}

// ----------------------------------------------------------------------------

type SubstType struct {
Real types.Object
}

func (p *SubstType) Underlying() types.Type {
fatal("substitute type")
return nil
}

func (p *SubstType) String() string {
return fmt.Sprintf("substType{real: %v}", p.Real)
}

func NewSubst(pos token.Pos, pkg *types.Package, name string, real types.Object) *types.Var {
return types.NewVar(pos, pkg, name, &SubstType{Real: real})
}

func LookupParent(scope *types.Scope, name string, pos token.Pos) (at *types.Scope, obj types.Object) {
if at, obj = scope.LookupParent(name, pos); obj != nil {
if t, ok := obj.Type().(*SubstType); ok {
obj = t.Real
}
}
return
}

func Lookup(scope *types.Scope, name string) (obj types.Object) {
if obj = scope.Lookup(name); obj != nil {
if t, ok := obj.Type().(*SubstType); ok {
obj = t.Real
}
}
return
}

// ----------------------------------------------------------------------------
Loading