github.com/traefik/yaegi@v0.15.1/interp/gta.go (about) 1 package interp 2 3 import ( 4 "path" 5 "path/filepath" 6 ) 7 8 // gta performs a global types analysis on the AST, registering types, 9 // variables and functions symbols at package level, prior to CFG. 10 // All function bodies are skipped. GTA is necessary to handle out of 11 // order declarations and multiple source files packages. 12 // rpath is the relative path to the directory containing the source for the package. 13 func (interp *Interpreter) gta(root *node, rpath, importPath, pkgName string) ([]*node, error) { 14 sc := interp.initScopePkg(importPath, pkgName) 15 var err error 16 var revisit []*node 17 18 baseName := filepath.Base(interp.fset.Position(root.pos).Filename) 19 20 root.Walk(func(n *node) bool { 21 if err != nil { 22 return false 23 } 24 if n.scope == nil { 25 n.scope = sc 26 } 27 switch n.kind { 28 case constDecl: 29 // Early parse of constDecl subtree, to compute all constant 30 // values which may be used in further declarations. 31 if _, err = interp.cfg(n, sc, importPath, pkgName); err != nil { 32 // No error processing here, to allow recovery in subtree nodes. 33 // TODO(marc): check for a non recoverable error and return it for better diagnostic. 34 err = nil 35 } 36 37 case blockStmt: 38 if n != root { 39 return false // skip statement block if not the entry point 40 } 41 42 case defineStmt: 43 var ( 44 atyp *itype 45 err2 error 46 ) 47 if n.nleft+n.nright < len(n.child) { 48 // Type is declared explicitly in the assign expression. 49 if atyp, err2 = nodeType(interp, sc, n.child[n.nleft]); err2 != nil { 50 // The type does not exist yet, stash the error and come back 51 // when the type is known. 52 n.meta = err2 53 revisit = append(revisit, n) 54 return false 55 } 56 } 57 58 var sbase int 59 if n.nright > 0 { 60 sbase = len(n.child) - n.nright 61 } 62 63 for i := 0; i < n.nleft; i++ { 64 dest, src := n.child[i], n.child[sbase+i] 65 if isBlank(src) { 66 err = n.cfgErrorf("cannot use _ as value") 67 } 68 val := src.rval 69 if n.anc.kind == constDecl { 70 if _, err2 := interp.cfg(n, sc, importPath, pkgName); err2 != nil { 71 // Constant value can not be computed yet. 72 // Come back when child dependencies are known. 73 revisit = append(revisit, n) 74 return false 75 } 76 } 77 typ := atyp 78 if typ == nil { 79 if typ, err2 = nodeType(interp, sc, src); err2 != nil || typ == nil { 80 // The type does is not known yet, stash the error and come back 81 // when the type is known. 82 n.meta = err2 83 revisit = append(revisit, n) 84 return false 85 } 86 val = src.rval 87 } 88 if !typ.isComplete() { 89 // Come back when type is known. 90 revisit = append(revisit, n) 91 return false 92 } 93 if typ.cat == nilT { 94 err = n.cfgErrorf("use of untyped nil") 95 return false 96 } 97 if typ.isBinMethod { 98 typ = valueTOf(typ.methodCallType(), isBinMethod(), withScope(sc)) 99 } 100 sc.sym[dest.ident] = &symbol{kind: varSym, global: true, index: sc.add(typ), typ: typ, rval: val, node: n} 101 if n.anc.kind == constDecl { 102 sc.sym[dest.ident].kind = constSym 103 if childPos(n) == len(n.anc.child)-1 { 104 sc.iota = 0 105 } else { 106 sc.iota++ 107 } 108 } 109 } 110 return false 111 112 case defineXStmt: 113 err = compDefineX(sc, n) 114 115 case valueSpec: 116 l := len(n.child) - 1 117 if n.typ = n.child[l].typ; n.typ == nil { 118 if n.typ, err = nodeType(interp, sc, n.child[l]); err != nil { 119 return false 120 } 121 if !n.typ.isComplete() { 122 // Come back when type is known. 123 revisit = append(revisit, n) 124 return false 125 } 126 } 127 for _, c := range n.child[:l] { 128 asImportName := filepath.Join(c.ident, baseName) 129 sym, exists := sc.sym[asImportName] 130 if !exists { 131 sc.sym[c.ident] = &symbol{index: sc.add(n.typ), kind: varSym, global: true, typ: n.typ, node: n} 132 continue 133 } 134 c.level = globalFrame 135 136 // redeclaration error 137 if sym.typ.node != nil && sym.typ.node.anc != nil { 138 prevDecl := n.interp.fset.Position(sym.typ.node.anc.pos) 139 err = n.cfgErrorf("%s redeclared in this block\n\tprevious declaration at %v", c.ident, prevDecl) 140 return false 141 } 142 err = n.cfgErrorf("%s redeclared in this block", c.ident) 143 return false 144 } 145 146 case funcDecl: 147 if n.typ, err = nodeType(interp, sc, n.child[2]); err != nil { 148 return false 149 } 150 genericMethod := false 151 ident := n.child[1].ident 152 switch { 153 case isMethod(n): 154 // Add a method symbol in the receiver type name space 155 var rcvrtype *itype 156 n.ident = ident 157 rcvr := n.child[0].child[0] 158 rtn := rcvr.lastChild() 159 typName, typPtr := rtn.ident, false 160 // Identifies the receiver type name. It could be an ident, a 161 // generic type (indexExpr), or a pointer on either lasts. 162 if typName == "" { 163 typName = rtn.child[0].ident 164 switch rtn.kind { 165 case starExpr: 166 typPtr = true 167 switch c := rtn.child[0]; c.kind { 168 case indexExpr, indexListExpr: 169 typName = c.child[0].ident 170 genericMethod = true 171 } 172 case indexExpr, indexListExpr: 173 genericMethod = true 174 } 175 } 176 sym, _, found := sc.lookup(typName) 177 if !found { 178 n.meta = n.cfgErrorf("undefined: %s", typName) 179 revisit = append(revisit, n) 180 return false 181 } 182 if sym.typ.path != pkgName { 183 err = n.cfgErrorf("cannot define new methods on non-local type %s", baseType(sym.typ).id()) 184 return false 185 } 186 rcvrtype = sym.typ 187 if typPtr { 188 elementType := sym.typ 189 rcvrtype = ptrOf(elementType, withNode(rtn), withScope(sc)) 190 rcvrtype.incomplete = elementType.incomplete 191 elementType.addMethod(n) 192 } 193 rcvrtype.addMethod(n) 194 rtn.typ = rcvrtype 195 if rcvrtype.cat == genericT { 196 // generate methods for already instantiated receivers 197 for _, it := range rcvrtype.instance { 198 if err = genMethod(interp, sc, it, n, it.node.anc.param); err != nil { 199 return false 200 } 201 } 202 } 203 case ident == "init": 204 // init functions do not get declared as per the Go spec. 205 default: 206 asImportName := filepath.Join(ident, baseName) 207 if _, exists := sc.sym[asImportName]; exists { 208 // redeclaration error 209 err = n.cfgErrorf("%s redeclared in this block", ident) 210 return false 211 } 212 // Add a function symbol in the package name space except for init 213 sc.sym[ident] = &symbol{kind: funcSym, typ: n.typ, node: n, index: -1} 214 } 215 if !n.typ.isComplete() && !genericMethod { 216 revisit = append(revisit, n) 217 } 218 return false 219 220 case importSpec: 221 var name, ipath string 222 if len(n.child) == 2 { 223 ipath = constToString(n.child[1].rval) 224 name = n.child[0].ident 225 } else { 226 ipath = constToString(n.child[0].rval) 227 } 228 // Try to import a binary package first, or a source package 229 var pkgName string 230 if packageName := path.Base(ipath); path.Dir(ipath) == packageName { 231 ipath = packageName 232 } 233 if pkg := interp.binPkg[ipath]; pkg != nil { 234 switch name { 235 case "_": // no import of symbols 236 case ".": // import symbols in current scope 237 for n, v := range pkg { 238 typ := v.Type() 239 kind := binSym 240 if isBinType(v) { 241 typ = typ.Elem() 242 kind = typeSym 243 } 244 sc.sym[n] = &symbol{kind: kind, typ: valueTOf(typ, withScope(sc)), rval: v} 245 } 246 default: // import symbols in package namespace 247 if name == "" { 248 name = interp.pkgNames[ipath] 249 } 250 251 // If an incomplete type exists, delete it 252 if sym, exists := sc.sym[name]; exists && sym.kind == typeSym && sym.typ.incomplete { 253 delete(sc.sym, name) 254 } 255 256 // Imports of a same package are all mapped in the same scope, so we cannot just 257 // map them by their names, otherwise we could have collisions from same-name 258 // imports in different source files of the same package. Therefore, we suffix 259 // the key with the basename of the source file. 260 name = filepath.Join(name, baseName) 261 if sym, exists := sc.sym[name]; !exists { 262 sc.sym[name] = &symbol{kind: pkgSym, typ: &itype{cat: binPkgT, path: ipath, scope: sc}} 263 break 264 } else if sym.kind == pkgSym && sym.typ.cat == srcPkgT && sym.typ.path == ipath { 265 // ignore re-import of identical package 266 break 267 } 268 269 // redeclaration error. Not caught by the parser. 270 err = n.cfgErrorf("%s redeclared in this block", name) 271 return false 272 } 273 } else if pkgName, err = interp.importSrc(rpath, ipath, NoTest); err == nil { 274 sc.types = interp.universe.types 275 switch name { 276 case "_": // no import of symbols 277 case ".": // import symbols in current namespace 278 for k, v := range interp.srcPkg[ipath] { 279 if canExport(k) { 280 sc.sym[k] = v 281 } 282 } 283 default: // import symbols in package namespace 284 if name == "" { 285 name = pkgName 286 } 287 name = filepath.Join(name, baseName) 288 if sym, exists := sc.sym[name]; !exists { 289 sc.sym[name] = &symbol{kind: pkgSym, typ: &itype{cat: srcPkgT, path: ipath, scope: sc}} 290 break 291 } else if sym.kind == pkgSym && sym.typ.cat == srcPkgT && sym.typ.path == ipath { 292 // ignore re-import of identical package 293 break 294 } 295 296 // redeclaration error 297 err = n.cfgErrorf("%s redeclared as imported package name", name) 298 return false 299 } 300 } else { 301 err = n.cfgErrorf("import %q error: %v", ipath, err) 302 } 303 304 case typeSpec, typeSpecAssign: 305 if isBlank(n.child[0]) { 306 err = n.cfgErrorf("cannot use _ as value") 307 return false 308 } 309 typeName := n.child[0].ident 310 if len(n.child) > 2 { 311 // Handle a generic type: skip definition as parameter is not instantiated yet. 312 n.typ = genericOf(nil, typeName, pkgName, withNode(n.child[0]), withScope(sc)) 313 if _, exists := sc.sym[typeName]; !exists { 314 sc.sym[typeName] = &symbol{kind: typeSym, node: n} 315 } 316 sc.sym[typeName].typ = n.typ 317 return false 318 } 319 var typ *itype 320 if typ, err = nodeType(interp, sc, n.child[1]); err != nil { 321 err = nil 322 revisit = append(revisit, n) 323 return false 324 } 325 326 if n.kind == typeSpecAssign { 327 // Create an aliased type in the current scope 328 sc.sym[typeName] = &symbol{kind: typeSym, node: n, typ: typ} 329 n.typ = typ 330 break 331 } 332 333 // else we are not an alias (typeSpec) 334 335 switch n.child[1].kind { 336 case identExpr, selectorExpr: 337 n.typ = namedOf(typ, pkgName, typeName, withNode(n.child[0]), withScope(sc)) 338 n.typ.incomplete = typ.incomplete 339 n.typ.field = typ.field 340 copy(n.typ.method, typ.method) 341 default: 342 n.typ = typ 343 n.typ.name = typeName 344 n.typ.path = pkgName 345 } 346 n.typ.str = n.typ.path + "." + n.typ.name 347 348 asImportName := filepath.Join(typeName, baseName) 349 if _, exists := sc.sym[asImportName]; exists { 350 // redeclaration error 351 err = n.cfgErrorf("%s redeclared in this block", typeName) 352 return false 353 } 354 sym, exists := sc.sym[typeName] 355 if !exists { 356 sym = &symbol{kind: typeSym, node: n} 357 sc.sym[typeName] = sym 358 } else if sym.typ != nil && (len(sym.typ.method) > 0) { 359 // Type has already been seen as a receiver in a method function 360 for _, m := range sym.typ.method { 361 n.typ.addMethod(m) 362 } 363 } 364 sym.typ = n.typ 365 if !n.typ.isComplete() { 366 revisit = append(revisit, n) 367 } 368 return false 369 } 370 return true 371 }, nil) 372 373 if sc != interp.universe { 374 sc.pop() 375 } 376 return revisit, err 377 } 378 379 func baseType(t *itype) *itype { 380 for { 381 switch t.cat { 382 case ptrT, linkedT: 383 t = t.val 384 default: 385 return t 386 } 387 } 388 } 389 390 // gtaRetry (re)applies gta until all global constants and types are defined. 391 func (interp *Interpreter) gtaRetry(nodes []*node, importPath, pkgName string) error { 392 revisit := []*node{} 393 for { 394 for _, n := range nodes { 395 list, err := interp.gta(n, importPath, importPath, pkgName) 396 if err != nil { 397 return err 398 } 399 revisit = append(revisit, list...) 400 } 401 402 if len(revisit) == 0 || equalNodes(nodes, revisit) { 403 break 404 } 405 406 nodes = revisit 407 revisit = []*node{} 408 } 409 410 if len(revisit) > 0 { 411 n := revisit[0] 412 switch n.kind { 413 case typeSpec, typeSpecAssign: 414 if err := definedType(n.typ); err != nil { 415 return err 416 } 417 case defineStmt, funcDecl: 418 if err, ok := n.meta.(error); ok { 419 return err 420 } 421 } 422 return n.cfgErrorf("constant definition loop") 423 } 424 return nil 425 } 426 427 func definedType(typ *itype) error { 428 if !typ.incomplete { 429 return nil 430 } 431 switch typ.cat { 432 case interfaceT, structT: 433 for _, f := range typ.field { 434 if err := definedType(f.typ); err != nil { 435 return err 436 } 437 } 438 case funcT: 439 for _, t := range typ.arg { 440 if err := definedType(t); err != nil { 441 return err 442 } 443 } 444 for _, t := range typ.ret { 445 if err := definedType(t); err != nil { 446 return err 447 } 448 } 449 case mapT: 450 if err := definedType(typ.key); err != nil { 451 return err 452 } 453 fallthrough 454 case linkedT, arrayT, chanT, chanSendT, chanRecvT, ptrT, variadicT: 455 if err := definedType(typ.val); err != nil { 456 return err 457 } 458 case nilT: 459 return typ.node.cfgErrorf("undefined: %s", typ.node.ident) 460 } 461 return nil 462 } 463 464 // equalNodes returns true if two slices of nodes are identical. 465 func equalNodes(a, b []*node) bool { 466 if len(a) != len(b) { 467 return false 468 } 469 for i, n := range a { 470 if n != b[i] { 471 return false 472 } 473 } 474 return true 475 }