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