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 // ----------------------------------------------------------------------------