From 284dfac6504a35868523fda0c9be5cf5816848dc Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 24 Jan 2024 23:55:29 +0800 Subject: [PATCH] iOverloadType/iSubstType --- builtin_test.go | 40 +++++++++---- func_ext.go | 7 +++ template.go | 22 ++------ type_ext.go | 145 +++++++++++++++++++++++++++--------------------- 4 files changed, 124 insertions(+), 90 deletions(-) diff --git a/builtin_test.go b/builtin_test.go index 45ff736c..83f55b65 100644 --- a/builtin_test.go +++ b/builtin_test.go @@ -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, @@ -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{}, @@ -645,11 +647,6 @@ 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() @@ -657,11 +654,34 @@ func TestUnderlying(t *testing.T) { 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) { diff --git a/func_ext.go b/func_ext.go index 0f13ef67..2f9fdbb2 100644 --- a/func_ext.go +++ b/func_ext.go @@ -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() {} @@ -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() {} @@ -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() {} diff --git a/template.go b/template.go index 621f2327..cf06f3ba 100644 --- a/template.go +++ b/template.go @@ -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) } @@ -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) } @@ -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) } @@ -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 diff --git a/type_ext.go b/type_ext.go index 806836a0..2bcb1461 100644 --- a/type_ext.go +++ b/type_ext.go @@ -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) { @@ -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} @@ -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 ( @@ -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) } @@ -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) } @@ -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) } @@ -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) } @@ -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 -} - -// ----------------------------------------------------------------------------