github.com/goplus/gox@v1.14.13-0.20240308130321-6ff7f61cfae8/type_ext.go (about)

     1  /*
     2   Copyright 2024 The GoPlus Authors (goplus.org)
     3   Licensed under the Apache License, Version 2.0 (the "License");
     4   you may not use this file except in compliance with the License.
     5   You may obtain a copy of the License at
     6       http://www.apache.org/licenses/LICENSE-2.0
     7   Unless required by applicable law or agreed to in writing, software
     8   distributed under the License is distributed on an "AS IS" BASIS,
     9   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10   See the License for the specific language governing permissions and
    11   limitations under the License.
    12  */
    13  
    14  package gox
    15  
    16  import (
    17  	"fmt"
    18  	"go/ast"
    19  	"go/token"
    20  	"go/types"
    21  )
    22  
    23  // ----------------------------------------------------------------------------
    24  
    25  // Go+ overload extended types
    26  type OverloadType interface {
    27  	At(i int) types.Object
    28  	Len() int
    29  }
    30  
    31  var (
    32  	_ OverloadType = (*TyOverloadNamed)(nil)
    33  	_ OverloadType = (*TyOverloadFunc)(nil)
    34  	_ OverloadType = (*TyOverloadMethod)(nil)
    35  )
    36  
    37  // ----------------------------------------------------------------------------
    38  
    39  type iSubstType interface {
    40  	Obj() types.Object
    41  }
    42  
    43  var (
    44  	_ iSubstType = (*TyTemplateRecvMethod)(nil)
    45  	_ iSubstType = (*TySubst)(nil)
    46  )
    47  
    48  // ----------------------------------------------------------------------------
    49  
    50  // TyTypeEx is a TypeEx type.
    51  type TyTypeEx interface {
    52  	types.Type
    53  	typeEx()
    54  }
    55  
    56  var (
    57  	_ TyTypeEx = (*TyOverloadNamed)(nil)
    58  	_ TyTypeEx = (*TyInstruction)(nil)
    59  	_ TyTypeEx = (*TySubst)(nil)
    60  )
    61  
    62  // ----------------------------------------------------------------------------
    63  
    64  // IsTypeEx returns if t is a gox extended type or not.
    65  func IsTypeEx(t types.Type) (ok bool) {
    66  	switch v := t.(type) {
    67  	case *types.Signature:
    68  		_, ok = CheckFuncEx(v)
    69  		return
    70  	case TyTypeEx:
    71  		return true
    72  	}
    73  	return false
    74  }
    75  
    76  // ----------------------------------------------------------------------------
    77  
    78  type TyOverloadNamed struct {
    79  	Types []*types.Named
    80  	Obj   *types.TypeName
    81  }
    82  
    83  func (p *TyOverloadNamed) At(i int) types.Object { return p.Types[i].Obj() }
    84  func (p *TyOverloadNamed) Len() int              { return len(p.Types) }
    85  
    86  func (p *TyOverloadNamed) typeEx()                {}
    87  func (p *TyOverloadNamed) Underlying() types.Type { return p }
    88  func (p *TyOverloadNamed) String() string {
    89  	o := p.Obj
    90  	return fmt.Sprintf("TyOverloadNamed{%s.%s}", o.Pkg().Path(), o.Name())
    91  }
    92  
    93  func NewOverloadNamed(pos token.Pos, pkg *types.Package, name string, typs ...*types.Named) *types.TypeName {
    94  	t := &TyOverloadNamed{Types: typs}
    95  	sig := sigFuncEx(pkg, nil, t)
    96  	o := types.NewTypeName(pos, pkg, name, sig)
    97  	t.Obj = o
    98  	return o
    99  }
   100  
   101  // CheckOverloadNamed returns if specified type is a TyOverloadNamed or not.
   102  func CheckOverloadNamed(typ types.Type) (on *TyOverloadNamed, ok bool) {
   103  	if sig, is := typ.(*types.Signature); is {
   104  		if typ, is := CheckSigFuncEx(sig); is {
   105  			on, ok = typ.(*TyOverloadNamed)
   106  		}
   107  	}
   108  	return
   109  }
   110  
   111  type TyInstruction struct {
   112  	instr Instruction
   113  }
   114  
   115  func (p *TyInstruction) typeEx()                {}
   116  func (p *TyInstruction) Underlying() types.Type { return p }
   117  func (p *TyInstruction) String() string {
   118  	return fmt.Sprintf("TyInstruction{%T}", p.instr)
   119  }
   120  
   121  func NewInstruction(pos token.Pos, pkg *types.Package, name string, instr Instruction) *types.TypeName {
   122  	return types.NewTypeName(pos, pkg, name, &TyInstruction{instr})
   123  }
   124  
   125  // Deprecated: use TySubst instead of SubstType.
   126  type SubstType = TySubst
   127  
   128  type TySubst struct {
   129  	Real types.Object
   130  }
   131  
   132  func (p *TySubst) Obj() types.Object { return p.Real }
   133  
   134  func (p *TySubst) typeEx()                {}
   135  func (p *TySubst) Underlying() types.Type { return p }
   136  func (p *TySubst) String() string {
   137  	return fmt.Sprintf("substType{real: %v}", p.Real)
   138  }
   139  
   140  func NewSubst(pos token.Pos, pkg *types.Package, name string, real types.Object) *types.Var {
   141  	return types.NewVar(pos, pkg, name, &TySubst{Real: real})
   142  }
   143  
   144  func LookupParent(scope *types.Scope, name string, pos token.Pos) (at *types.Scope, obj types.Object) {
   145  	if at, obj = scope.LookupParent(name, pos); obj != nil {
   146  		if t, ok := obj.Type().(*TySubst); ok {
   147  			obj = t.Real
   148  		}
   149  	}
   150  	return
   151  }
   152  
   153  func Lookup(scope *types.Scope, name string) (obj types.Object) {
   154  	if obj = scope.Lookup(name); obj != nil {
   155  		if t, ok := obj.Type().(*TySubst); ok {
   156  			obj = t.Real
   157  		}
   158  	}
   159  	return
   160  }
   161  
   162  // ----------------------------------------------------------------------------
   163  
   164  var (
   165  	TyByte = types.Universe.Lookup("byte").Type().(*types.Basic)
   166  	TyRune = types.Universe.Lookup("rune").Type().(*types.Basic)
   167  )
   168  
   169  var (
   170  	TyEmptyInterface = types.NewInterfaceType(nil, nil)
   171  	TyError          = types.Universe.Lookup("error").Type()
   172  )
   173  
   174  // refType: &T
   175  type refType struct {
   176  	typ types.Type
   177  }
   178  
   179  func (p *refType) Elem() types.Type {
   180  	return p.typ
   181  }
   182  
   183  func (p *refType) Underlying() types.Type { return p }
   184  func (p *refType) String() string {
   185  	return fmt.Sprintf("refType{typ: %v}", p.typ)
   186  }
   187  
   188  func DerefType(typ types.Type) (types.Type, bool) {
   189  	switch t := typ.(type) {
   190  	case *refType:
   191  		return t.Elem(), true
   192  	case *bfRefType:
   193  		return t.typ, true
   194  	}
   195  	return typ, false
   196  }
   197  
   198  // bfRefType: bit field refType
   199  type bfRefType struct {
   200  	typ  *types.Basic
   201  	off  int
   202  	bits int
   203  }
   204  
   205  func (p *bfRefType) Underlying() types.Type { return p }
   206  func (p *bfRefType) String() string {
   207  	return fmt.Sprintf("bfRefType{typ: %v:%d off: %d}", p.typ, p.bits, p.off)
   208  }
   209  
   210  // unboundType: unbound type
   211  type unboundType struct {
   212  	tBound types.Type
   213  	ptypes []*ast.Expr
   214  }
   215  
   216  func (p *unboundType) boundTo(pkg *Package, arg types.Type) {
   217  	if p.tBound != nil {
   218  		fatal("TODO: type is already bounded")
   219  	}
   220  	p.tBound = arg
   221  	for _, pt := range p.ptypes {
   222  		*pt = toType(pkg, arg)
   223  	}
   224  	p.ptypes = nil
   225  }
   226  
   227  func (p *unboundType) Underlying() types.Type { return p }
   228  func (p *unboundType) String() string {
   229  	return fmt.Sprintf("unboundType{typ: %v}", p.tBound)
   230  }
   231  
   232  func realType(typ types.Type) types.Type {
   233  	switch t := typ.(type) {
   234  	case *unboundType:
   235  		if t.tBound != nil {
   236  			return t.tBound
   237  		}
   238  	case *types.Named:
   239  		if tn := t.Obj(); tn.IsAlias() {
   240  			return tn.Type()
   241  		}
   242  	}
   243  	return typ
   244  }
   245  
   246  type unboundMapElemType struct {
   247  	key types.Type
   248  	typ *unboundType
   249  }
   250  
   251  func (p *unboundMapElemType) Underlying() types.Type { return p }
   252  func (p *unboundMapElemType) String() string {
   253  	return fmt.Sprintf("unboundMapElemType{key: %v}", p.key)
   254  }
   255  
   256  // ----------------------------------------------------------------------------
   257  
   258  type btiMethodType struct {
   259  	types.Type
   260  	eargs []interface{}
   261  }
   262  
   263  // ----------------------------------------------------------------------------
   264  
   265  type TypeType struct {
   266  	typ types.Type
   267  }
   268  
   269  func NewTypeType(typ types.Type) *TypeType {
   270  	return &TypeType{typ: typ}
   271  }
   272  
   273  func (p *TypeType) Pointer() *TypeType {
   274  	return &TypeType{typ: types.NewPointer(p.typ)}
   275  }
   276  
   277  func (p *TypeType) Type() types.Type {
   278  	return p.typ
   279  }
   280  
   281  func (p *TypeType) Underlying() types.Type { return p }
   282  func (p *TypeType) String() string {
   283  	return fmt.Sprintf("TypeType{typ: %v}", p.typ)
   284  }
   285  
   286  // ----------------------------------------------------------------------------