Skip to content

Commit

Permalink
Merge pull request #350 from xushiwei/imp
Browse files Browse the repository at this point in the history
iOverloadType/iSubstType
  • Loading branch information
xushiwei committed Jan 24, 2024
2 parents 576b08a + 284dfac commit c8def69
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 90 deletions.
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
}

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

0 comments on commit c8def69

Please sign in to comment.