github.com/goplus/gop@v1.2.6/cl/func_type_and_var.go (about) 1 /* 2 * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package cl 18 19 import ( 20 "go/constant" 21 "go/types" 22 "log" 23 "math/big" 24 "strconv" 25 26 "github.com/goplus/gogen" 27 "github.com/goplus/gop/ast" 28 "github.com/goplus/gop/token" 29 ) 30 31 // ----------------------------------------------------------------------------- 32 33 func toRecv(ctx *blockCtx, recv *ast.FieldList) *types.Var { 34 v := recv.List[0] 35 var name string 36 if len(v.Names) > 0 { 37 name = v.Names[0].Name 38 } 39 typ, star := getRecvType(v.Type) 40 id, ok := typ.(*ast.Ident) 41 if !ok { 42 panic("TODO: getRecvType") 43 } 44 t := toIdentType(ctx, id) 45 if star { 46 t = types.NewPointer(t) 47 } 48 ret := ctx.pkg.NewParam(v.Pos(), name, t) 49 if rec := ctx.recorder(); rec != nil { 50 dRecv := recv.List[0] 51 if names := dRecv.Names; len(names) == 1 { 52 rec.Def(names[0], ret) 53 } 54 } 55 return ret 56 } 57 58 func getRecvTypeName(ctx *pkgCtx, recv *ast.FieldList, handleErr bool) (string, bool) { 59 typ, _ := getRecvType(recv.List[0].Type) 60 if t, ok := typ.(*ast.Ident); ok { 61 return t.Name, true 62 } 63 if handleErr { 64 src := ctx.LoadExpr(typ) 65 ctx.handleErrorf(typ.Pos(), "invalid receiver type %v (%v is not a defined type)", src, src) 66 } 67 return "", false 68 } 69 70 func toResults(ctx *blockCtx, in *ast.FieldList) *types.Tuple { 71 if in == nil { 72 return nil 73 } 74 flds := in.List 75 n := len(flds) 76 args := make([]*types.Var, 0, n) 77 for _, fld := range flds { 78 args = toParam(ctx, fld, args) 79 } 80 return types.NewTuple(args...) 81 } 82 83 func toParams(ctx *blockCtx, flds []*ast.Field) (typ *types.Tuple, variadic bool) { 84 n := len(flds) 85 if n == 0 { 86 return nil, false 87 } 88 args := make([]*types.Var, 0, n) 89 for _, fld := range flds { 90 args = toParam(ctx, fld, args) 91 } 92 _, ok := flds[n-1].Type.(*ast.Ellipsis) 93 return types.NewTuple(args...), ok 94 } 95 96 func toParam(ctx *blockCtx, fld *ast.Field, args []*gogen.Param) []*gogen.Param { 97 typ := toType(ctx, fld.Type) 98 pkg := ctx.pkg 99 if len(fld.Names) == 0 { 100 return append(args, pkg.NewParam(fld.Pos(), "", typ)) 101 } 102 for _, name := range fld.Names { 103 param := pkg.NewParam(name.Pos(), name.Name, typ) 104 args = append(args, param) 105 if rec := ctx.recorder(); rec != nil { 106 rec.Def(name, param) 107 } 108 } 109 return args 110 } 111 112 // ----------------------------------------------------------------------------- 113 114 func toType(ctx *blockCtx, typ ast.Expr) (t types.Type) { 115 if rec := ctx.recorder(); rec != nil { 116 defer func() { 117 rec.recordType(typ, t) 118 }() 119 } 120 switch v := typ.(type) { 121 case *ast.Ident: 122 ctx.idents = append(ctx.idents, v) 123 defer func() { 124 ctx.idents = ctx.idents[:len(ctx.idents)-1] 125 }() 126 typ := toIdentType(ctx, v) 127 if ctx.inInst == 0 { 128 if t, ok := typ.(*types.Named); ok { 129 if namedIsTypeParams(ctx, t) { 130 pos := ctx.idents[0].Pos() 131 for _, i := range ctx.idents { 132 if i.Name == v.Name { 133 pos = i.Pos() 134 break 135 } 136 } 137 ctx.handleErrorf(pos, "cannot use generic type %v without instantiation", t.Obj().Type()) 138 return types.Typ[types.Invalid] 139 } 140 } 141 } 142 return typ 143 case *ast.StarExpr: 144 elem := toType(ctx, v.X) 145 return types.NewPointer(elem) 146 case *ast.ArrayType: 147 return toArrayType(ctx, v) 148 case *ast.InterfaceType: 149 return toInterfaceType(ctx, v) 150 case *ast.Ellipsis: 151 elem := toType(ctx, v.Elt) 152 return types.NewSlice(elem) 153 case *ast.MapType: 154 return toMapType(ctx, v) 155 case *ast.StructType: 156 return toStructType(ctx, v) 157 case *ast.ChanType: 158 return toChanType(ctx, v) 159 case *ast.FuncType: 160 return toFuncType(ctx, v, nil, nil) 161 case *ast.SelectorExpr: 162 typ := toExternalType(ctx, v) 163 if ctx.inInst == 0 { 164 if t, ok := typ.(*types.Named); ok { 165 if namedIsTypeParams(ctx, t) { 166 panic(ctx.newCodeErrorf(v.Pos(), "cannot use generic type %v without instantiation", t.Obj().Type())) 167 } 168 } 169 } 170 return typ 171 case *ast.ParenExpr: 172 return toType(ctx, v.X) 173 case *ast.BinaryExpr: 174 return toBinaryExprType(ctx, v) 175 case *ast.UnaryExpr: 176 return toUnaryExprType(ctx, v) 177 case *ast.IndexExpr: 178 return toIndexType(ctx, v) 179 case *ast.IndexListExpr: 180 return toIndexListType(ctx, v) 181 default: 182 ctx.handleErrorf(v.Pos(), "toType unexpected: %T", v) 183 return types.Typ[types.Invalid] 184 } 185 } 186 187 var ( 188 typesChanDirs = [...]types.ChanDir{ 189 ast.RECV: types.RecvOnly, 190 ast.SEND: types.SendOnly, 191 ast.SEND | ast.RECV: types.SendRecv, 192 } 193 ) 194 195 func toChanType(ctx *blockCtx, v *ast.ChanType) *types.Chan { 196 return types.NewChan(typesChanDirs[v.Dir], toType(ctx, v.Value)) 197 } 198 199 func toExternalType(ctx *blockCtx, v *ast.SelectorExpr) types.Type { 200 id := v.X.(*ast.Ident) 201 name := id.Name 202 if pi, ok := ctx.findImport(name); ok { 203 rec := ctx.recorder() 204 if rec != nil { 205 rec.Use(id, pi.pkgName) 206 } 207 o := pi.TryRef(v.Sel.Name) 208 if t, ok := o.(*types.TypeName); ok { 209 if rec != nil { 210 rec.Use(v.Sel, t) 211 } 212 return t.Type() 213 } 214 ctx.handleErrorf(v.Pos(), "%s.%s is not a type", name, v.Sel.Name) 215 } else { 216 ctx.handleErrorf(v.Pos(), "undefined: %s", name) 217 } 218 return types.Typ[types.Invalid] 219 } 220 221 /*----------------------------------------------------------------------------- 222 223 Name context: 224 - type 225 - pkgRef.type 226 - spx.type 227 228 // ---------------------------------------------------------------------------*/ 229 230 func toIdentType(ctx *blockCtx, ident *ast.Ident) (ret types.Type) { 231 var obj types.Object 232 if rec := ctx.recorder(); rec != nil { 233 defer func() { 234 if obj != nil { 235 rec.recordIdent(ident, obj) 236 } 237 }() 238 } 239 if ctx.tlookup != nil { 240 if typ := ctx.tlookup.Lookup(ident.Name); typ != nil { 241 obj = typ.Obj() 242 return typ 243 } 244 } 245 v, builtin := lookupType(ctx, ident.Name) 246 if isBuiltin(builtin) { 247 ctx.handleErrorf(ident.Pos(), "use of builtin %s not in function call", ident.Name) 248 return types.Typ[types.Invalid] 249 } 250 if t, ok := v.(*types.TypeName); ok { 251 obj = t 252 return t.Type() 253 } 254 if v, _ := lookupPkgRef(ctx, gogen.PkgRef{}, ident, objPkgRef); v != nil { 255 if t, ok := v.(*types.TypeName); ok { 256 obj = t 257 return t.Type() 258 } 259 } 260 ctx.handleErrorf(ident.Pos(), "%s is not a type", ident.Name) 261 return types.Typ[types.Invalid] 262 } 263 264 // TODO: optimization 265 func lookupType(ctx *blockCtx, name string) (types.Object, types.Object) { 266 at, o := ctx.cb.Scope().LookupParent(name, token.NoPos) 267 if o != nil && at != types.Universe { 268 if debugLookup { 269 log.Println("==> LookupParent", name, "=>", o) 270 } 271 return o, nil 272 } 273 if ctx.loadSymbol(name) { 274 if v := ctx.pkg.Types.Scope().Lookup(name); v != nil { 275 if debugLookup { 276 log.Println("==> Lookup (LoadSymbol)", name, "=>", v) 277 } 278 return v, nil 279 } 280 } 281 if obj := ctx.pkg.Builtin().TryRef(name); obj != nil { 282 return obj, o 283 } 284 return o, o 285 } 286 287 type checkRedecl struct { 288 // ctx *blockCtx 289 names map[string]token.Pos 290 } 291 292 func newCheckRedecl() *checkRedecl { 293 p := &checkRedecl{names: make(map[string]token.Pos)} 294 return p 295 } 296 297 func (p *checkRedecl) chkRedecl(ctx *blockCtx, name string, pos token.Pos) bool { 298 if name == "_" { 299 return false 300 } 301 if opos, ok := p.names[name]; ok { 302 ctx.handleErrorf( 303 pos, "%v redeclared\n\t%v other declaration of %v", 304 name, ctx.Position(opos), name) 305 return true 306 } 307 p.names[name] = pos 308 return false 309 } 310 311 func toStructType(ctx *blockCtx, v *ast.StructType) *types.Struct { 312 pkg := ctx.pkg.Types 313 fieldList := v.Fields.List 314 fields := make([]*types.Var, 0, len(fieldList)) 315 tags := make([]string, 0, len(fieldList)) 316 chk := newCheckRedecl() 317 rec := ctx.recorder() 318 for _, field := range fieldList { 319 typ := toType(ctx, field.Type) 320 if len(field.Names) == 0 { // embedded 321 name := getTypeName(typ) 322 if chk.chkRedecl(ctx, name, field.Type.Pos()) { 323 continue 324 } 325 if t, ok := typ.(*types.Named); ok { // #1196: embedded type should ensure loaded 326 ctx.loadNamed(ctx.pkg, t) 327 } 328 ident := parseTypeEmbedName(field.Type) 329 fld := types.NewField(ident.NamePos, pkg, name, typ, true) 330 fields = append(fields, fld) 331 tags = append(tags, toFieldTag(field.Tag)) 332 if rec != nil { 333 rec.Def(ident, fld) 334 } 335 continue 336 } 337 for _, name := range field.Names { 338 if chk.chkRedecl(ctx, name.Name, name.NamePos) { 339 continue 340 } 341 fld := types.NewField(name.NamePos, pkg, name.Name, typ, false) 342 fields = append(fields, fld) 343 tags = append(tags, toFieldTag(field.Tag)) 344 if rec != nil { 345 rec.Def(name, fld) 346 } 347 } 348 } 349 return types.NewStruct(fields, tags) 350 } 351 352 func toFieldTag(v *ast.BasicLit) string { 353 if v != nil { 354 tag, err := strconv.Unquote(v.Value) 355 if err != nil { 356 log.Panicln("TODO: toFieldTag -", err) 357 } 358 return tag 359 } 360 return "" 361 } 362 363 func getTypeName(typ types.Type) string { 364 if t, ok := typ.(*types.Pointer); ok { 365 typ = t.Elem() 366 } 367 switch t := typ.(type) { 368 case *types.Named: 369 return t.Obj().Name() 370 case *types.Basic: 371 return t.Name() 372 default: 373 panic("TODO: getTypeName") 374 } 375 } 376 377 func toMapType(ctx *blockCtx, v *ast.MapType) *types.Map { 378 key := toType(ctx, v.Key) 379 val := toType(ctx, v.Value) 380 return types.NewMap(key, val) 381 } 382 383 func toArrayType(ctx *blockCtx, v *ast.ArrayType) types.Type { 384 elem := toType(ctx, v.Elt) 385 if v.Len == nil { 386 return types.NewSlice(elem) 387 } 388 if _, ok := v.Len.(*ast.Ellipsis); ok { 389 return types.NewArray(elem, -1) // A negative length indicates an unknown length 390 } 391 return types.NewArray(elem, toInt64(ctx, v.Len, "non-constant array bound %s")) 392 } 393 394 func toInt64(ctx *blockCtx, e ast.Expr, emsg string) int64 { 395 cb := ctx.pkg.ConstStart() 396 compileExpr(ctx, e) 397 tv := cb.EndConst() 398 if val := tv.CVal; val != nil { 399 if val.Kind() == constant.Float { 400 if v, ok := constant.Val(val).(*big.Rat); ok && v.IsInt() { 401 return v.Num().Int64() 402 } 403 } else if v, ok := constant.Int64Val(val); ok { 404 return v 405 } 406 } 407 src := ctx.LoadExpr(e) 408 panic(ctx.newCodeErrorf(e.Pos(), emsg, src)) 409 } 410 411 func toInterfaceType(ctx *blockCtx, v *ast.InterfaceType) types.Type { 412 methodsList := v.Methods.List 413 if methodsList == nil { 414 return types.NewInterfaceType(nil, nil) 415 } 416 var rec = ctx.recorder() 417 var pkg = ctx.pkg.Types 418 var methods []*types.Func 419 var embeddeds []types.Type 420 for _, m := range methodsList { 421 if len(m.Names) == 0 { // embedded 422 typ := toType(ctx, m.Type) 423 if t, ok := typ.(*types.Named); ok { // #1198: embedded type should ensure loaded 424 ctx.loadNamed(ctx.pkg, t) 425 } 426 embeddeds = append(embeddeds, typ) 427 continue 428 } 429 name := m.Names[0] 430 sig := toFuncType(ctx, m.Type.(*ast.FuncType), nil, nil) 431 mthd := types.NewFunc(name.NamePos, pkg, name.Name, sig) 432 methods = append(methods, mthd) 433 if rec != nil { 434 rec.Def(name, mthd) 435 } 436 } 437 intf := types.NewInterfaceType(methods, embeddeds).Complete() 438 return intf 439 } 440 441 func instantiate(ctx *blockCtx, exprX ast.Expr, indices ...ast.Expr) types.Type { 442 ctx.inInst++ 443 defer func() { 444 ctx.inInst-- 445 }() 446 447 x := toType(ctx, exprX) 448 idx := make([]types.Type, len(indices)) 449 for i, index := range indices { 450 idx[i] = toType(ctx, index) 451 } 452 typ := ctx.pkg.Instantiate(x, idx, exprX) 453 if rec := ctx.recorder(); rec != nil { 454 rec.instantiate(exprX, x, typ) 455 } 456 return typ 457 } 458 459 func toIndexType(ctx *blockCtx, v *ast.IndexExpr) types.Type { 460 return instantiate(ctx, v.X, v.Index) 461 } 462 463 func toIndexListType(ctx *blockCtx, v *ast.IndexListExpr) types.Type { 464 return instantiate(ctx, v.X, v.Indices...) 465 } 466 467 // ----------------------------------------------------------------------------- 468 469 func toString(l *ast.BasicLit) string { 470 if l.Kind == token.STRING { 471 s, err := strconv.Unquote(l.Value) 472 if err == nil { 473 return s 474 } 475 } 476 panic("TODO: toString - convert ast.BasicLit to string failed") 477 } 478 479 // -----------------------------------------------------------------------------