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  }