github.com/goplus/gogen@v1.16.0/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 gogen
    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 gogen 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  // TODO(xsw): check only c2go uses this function.
   141  func NewSubst(pos token.Pos, pkg *types.Package, name string, real types.Object) *types.Var {
   142  	return types.NewVar(pos, pkg, name, &TySubst{Real: real})
   143  }
   144  
   145  func LookupParent(scope *types.Scope, name string, pos token.Pos) (at *types.Scope, obj types.Object) {
   146  	if at, obj = scope.LookupParent(name, pos); obj != nil {
   147  		if t, ok := obj.Type().(*TySubst); ok {
   148  			obj = t.Real
   149  		}
   150  	}
   151  	return
   152  }
   153  
   154  func Lookup(scope *types.Scope, name string) (obj types.Object) {
   155  	if obj = scope.Lookup(name); obj != nil {
   156  		if t, ok := obj.Type().(*TySubst); ok {
   157  			obj = t.Real
   158  		}
   159  	}
   160  	return
   161  }
   162  
   163  // ----------------------------------------------------------------------------
   164  
   165  var (
   166  	TyByte = types.Universe.Lookup("byte").Type().(*types.Basic)
   167  	TyRune = types.Universe.Lookup("rune").Type().(*types.Basic)
   168  )
   169  
   170  var (
   171  	TyEmptyInterface = types.NewInterfaceType(nil, nil)
   172  	TyError          = types.Universe.Lookup("error").Type()
   173  )
   174  
   175  // refType: &T
   176  type refType struct {
   177  	typ types.Type
   178  }
   179  
   180  func (p *refType) Elem() types.Type {
   181  	return p.typ
   182  }
   183  
   184  func (p *refType) Underlying() types.Type { return p }
   185  func (p *refType) String() string {
   186  	return fmt.Sprintf("refType{typ: %v}", p.typ)
   187  }
   188  
   189  func DerefType(typ types.Type) (types.Type, bool) {
   190  	switch t := typ.(type) {
   191  	case *refType:
   192  		return t.Elem(), true
   193  	}
   194  	return typ, false
   195  }
   196  
   197  // unboundType: unbound type
   198  type unboundType struct {
   199  	tBound types.Type
   200  	ptypes []*ast.Expr
   201  }
   202  
   203  func (p *unboundType) boundTo(pkg *Package, arg types.Type) {
   204  	if p.tBound != nil {
   205  		fatal("TODO: type is already bounded")
   206  	}
   207  	p.tBound = arg
   208  	for _, pt := range p.ptypes {
   209  		*pt = toType(pkg, arg)
   210  	}
   211  	p.ptypes = nil
   212  }
   213  
   214  func (p *unboundType) Underlying() types.Type { return p }
   215  func (p *unboundType) String() string {
   216  	return fmt.Sprintf("unboundType{typ: %v}", p.tBound)
   217  }
   218  
   219  func realType(typ types.Type) types.Type {
   220  	switch t := typ.(type) {
   221  	case *unboundType:
   222  		if t.tBound != nil {
   223  			return t.tBound
   224  		}
   225  	case *types.Named:
   226  		if tn := t.Obj(); tn.IsAlias() {
   227  			return tn.Type()
   228  		}
   229  	}
   230  	return typ
   231  }
   232  
   233  type unboundMapElemType struct {
   234  	key types.Type
   235  	typ *unboundType
   236  }
   237  
   238  func (p *unboundMapElemType) Underlying() types.Type { return p }
   239  func (p *unboundMapElemType) String() string {
   240  	return fmt.Sprintf("unboundMapElemType{key: %v}", p.key)
   241  }
   242  
   243  // ----------------------------------------------------------------------------
   244  
   245  type btiMethodType struct {
   246  	types.Type
   247  	eargs []interface{}
   248  }
   249  
   250  // ----------------------------------------------------------------------------
   251  
   252  type TypeType struct {
   253  	typ types.Type
   254  }
   255  
   256  func NewTypeType(typ types.Type) *TypeType {
   257  	return &TypeType{typ: typ}
   258  }
   259  
   260  func (p *TypeType) Pointer() *TypeType {
   261  	return &TypeType{typ: types.NewPointer(p.typ)}
   262  }
   263  
   264  func (p *TypeType) Type() types.Type {
   265  	return p.typ
   266  }
   267  
   268  func (p *TypeType) Underlying() types.Type { return p }
   269  func (p *TypeType) String() string {
   270  	return fmt.Sprintf("TypeType{typ: %v}", p.typ)
   271  }
   272  
   273  // ----------------------------------------------------------------------------