fix: import different source packages with same base name

This commit is contained in:
Marc Vertes
2020-02-03 17:22:04 +01:00
committed by GitHub
parent 712891dd77
commit e434892b9a
9 changed files with 54 additions and 46 deletions

7
_test/b1/foo/foo.go Normal file
View File

@@ -0,0 +1,7 @@
package foo
import bar "github.com/containous/yaegi/_test/b2/foo"
var Desc = "in b1/foo"
var Desc2 = Desc + bar.Desc

3
_test/b2/foo/foo.go Normal file
View File

@@ -0,0 +1,3 @@
package foo
var Desc = "in b2/foo"

10
_test/import8.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import "github.com/containous/yaegi/_test/b1/foo"
func main() {
println(foo.Desc)
}
// Output:
// in b1/foo

View File

@@ -42,8 +42,8 @@ var identifier = regexp.MustCompile(`([\pL_][\pL_\d]*)$`)
// and pre-compute frame sizes and indexes for all un-named (temporary) and named
// variables. A list of nodes of init functions is returned.
// Following this pass, the CFG is ready to run
func (interp *Interpreter) cfg(root *node) ([]*node, error) {
sc, pkgName := interp.initScopePkg(root)
func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
sc := interp.initScopePkg(pkgID)
var initNodes []*node
var iotaValue int
var err error
@@ -901,10 +901,10 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
sc = sc.pop()
funcName := n.child[1].ident
if !isMethod(n) {
interp.scopes[pkgName].sym[funcName].index = -1 // to force value to n.val
interp.scopes[pkgName].sym[funcName].typ = n.typ
interp.scopes[pkgName].sym[funcName].kind = funcSym
interp.scopes[pkgName].sym[funcName].node = n
interp.scopes[pkgID].sym[funcName].index = -1 // to force value to n.val
interp.scopes[pkgID].sym[funcName].typ = n.typ
interp.scopes[pkgID].sym[funcName].kind = funcSym
interp.scopes[pkgID].sym[funcName].node = n
}
case funcLit:
@@ -1787,13 +1787,6 @@ func getExec(n *node) bltn {
return n.exec
}
func fileNode(n *node) *node {
if n == nil || n.kind == fileStmt {
return n
}
return fileNode(n.anc)
}
// setExec recursively sets the node exec builtin function by walking the CFG
// from the entry point (first node to exec).
func setExec(n *node) {

View File

@@ -8,8 +8,8 @@ import (
// variables and functions symbols at package level, prior to CFG.
// All function bodies are skipped. GTA is necessary to handle out of
// order declarations and multiple source files packages.
func (interp *Interpreter) gta(root *node, rpath string) ([]*node, error) {
sc, _ := interp.initScopePkg(root)
func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error) {
sc := interp.initScopePkg(pkgID)
var err error
var iotaValue int
var revisit []*node
@@ -146,7 +146,7 @@ func (interp *Interpreter) gta(root *node, rpath string) ([]*node, error) {
default: // import symbols in package namespace
sc.sym[name] = &symbol{kind: pkgSym, typ: &itype{cat: binPkgT, path: ipath}}
}
} else if err = interp.importSrc(rpath, ipath, name); err == nil {
} else if err = interp.importSrc(rpath, ipath); err == nil {
sc.types = interp.universe.types
switch name {
case "_": // no import of symbols

View File

@@ -283,7 +283,7 @@ func (interp *Interpreter) resizeFrame() {
func (interp *Interpreter) main() *node {
interp.mutex.RLock()
defer interp.mutex.RUnlock()
if m, ok := interp.scopes[mainID]; ok && m.sym[mainID] != nil {
if m, ok := interp.scopes[interp.Name]; ok && m.sym[mainID] != nil {
return m.sym[mainID].node
}
return nil
@@ -308,18 +308,18 @@ func (interp *Interpreter) Eval(src string) (reflect.Value, error) {
}
// Global type analysis
revisit, err := interp.gta(root, pkgName)
revisit, err := interp.gta(root, pkgName, interp.Name)
if err != nil {
return res, err
}
for _, n := range revisit {
if _, err = interp.gta(n, pkgName); err != nil {
if _, err = interp.gta(n, pkgName, interp.Name); err != nil {
return res, err
}
}
// Annotate AST with CFG infos
initNodes, err := interp.cfg(root)
initNodes, err := interp.cfg(root, interp.Name)
if err != nil {
return res, err
}
@@ -336,7 +336,7 @@ func (interp *Interpreter) Eval(src string) (reflect.Value, error) {
interp.mutex.Lock()
if interp.universe.sym[pkgName] == nil {
// Make the package visible under a path identical to its name
interp.srcPkg[pkgName] = interp.scopes[pkgName].sym
interp.srcPkg[pkgName] = interp.scopes[interp.Name].sym
interp.universe.sym[pkgName] = &symbol{kind: pkgSym, typ: &itype{cat: srcPkgT, path: pkgName}}
}
interp.mutex.Unlock()

View File

@@ -78,6 +78,7 @@ type scope struct {
def *node // function definition node this scope belongs to, or nil
loop *node // loop exit node for break statement
loopRestart *node // loop restart node for continue statement
pkgID string // unique id of package in which scope is defined
types []reflect.Type // Frame layout, may be shared by same level scopes
level int // Frame level: number of frame indirections to access var during execution
sym map[string]*symbol // Map of symbols defined in this current scope
@@ -97,8 +98,8 @@ func (s *scope) push(indirect bool) *scope {
sc.global = s.global
sc.level = s.level
}
// inherit loop state from ancestor
sc.loop, sc.loopRestart = s.loop, s.loopRestart
// inherit loop state and pkgID from ancestor
sc.loop, sc.loopRestart, sc.pkgID = s.loop, s.loopRestart, s.pkgID
return &sc
}
@@ -160,19 +161,15 @@ func (s *scope) add(typ *itype) (index int) {
return
}
func (interp *Interpreter) initScopePkg(n *node) (*scope, string) {
func (interp *Interpreter) initScopePkg(pkgID string) *scope {
sc := interp.universe
pkgName := mainID
if p := fileNode(n); p != nil {
pkgName = p.child[0].ident
}
interp.mutex.Lock()
if _, ok := interp.scopes[pkgName]; !ok {
interp.scopes[pkgName] = sc.pushBloc()
if _, ok := interp.scopes[pkgID]; !ok {
interp.scopes[pkgID] = sc.pushBloc()
}
sc = interp.scopes[pkgName]
sc = interp.scopes[pkgID]
sc.pkgID = pkgID
interp.mutex.Unlock()
return sc, pkgName
return sc
}

View File

@@ -8,7 +8,7 @@ import (
"strings"
)
func (interp *Interpreter) importSrc(rPath, path, alias string) error {
func (interp *Interpreter) importSrc(rPath, path string) error {
var dir string
var err error
@@ -29,6 +29,7 @@ func (interp *Interpreter) importSrc(rPath, path, alias string) error {
} else if dir, rPath, err = pkgDir(interp.context.GOPATH, rPath, path); err != nil {
return err
}
if interp.rdir[path] {
return fmt.Errorf("import cycle not allowed\n\timports %s", path)
}
@@ -66,6 +67,9 @@ func (interp *Interpreter) importSrc(rPath, path, alias string) error {
if root == nil {
continue
}
if interp.astDot {
root.astDot(dotX(), name)
}
if pkgName == "" {
pkgName = pname
} else if pkgName != pname {
@@ -75,7 +79,7 @@ func (interp *Interpreter) importSrc(rPath, path, alias string) error {
subRPath := effectivePkg(rPath, path)
var list []*node
list, err = interp.gta(root, subRPath)
list, err = interp.gta(root, subRPath, path)
if err != nil {
return err
}
@@ -85,7 +89,7 @@ func (interp *Interpreter) importSrc(rPath, path, alias string) error {
// revisit incomplete nodes where GTA could not complete
for pkg, nodes := range revisit {
for _, n := range nodes {
if _, err = interp.gta(n, pkg); err != nil {
if _, err = interp.gta(n, pkg, path); err != nil {
return err
}
}
@@ -94,7 +98,7 @@ func (interp *Interpreter) importSrc(rPath, path, alias string) error {
// Generate control flow graphs
for _, root := range rootNodes {
var nodes []*node
if nodes, err = interp.cfg(root); err != nil {
if nodes, err = interp.cfg(root, path); err != nil {
return err
}
initNodes = append(initNodes, nodes...)
@@ -103,13 +107,7 @@ func (interp *Interpreter) importSrc(rPath, path, alias string) error {
// Register source package in the interpreter. The package contains only
// the global symbols in the package scope.
interp.mutex.Lock()
interp.srcPkg[path] = interp.scopes[pkgName].sym
// Rename imported pkgName to alias if they are different
if pkgName != alias {
interp.scopes[alias] = interp.scopes[pkgName]
delete(interp.scopes, pkgName)
}
interp.srcPkg[path] = interp.scopes[path].sym
interp.frame.mutex.Lock()
interp.resizeFrame()
@@ -189,7 +187,7 @@ func effectivePkg(root, path string) string {
for i := 0; i < len(splitPath); i++ {
part := splitPath[len(splitPath)-1-i]
if part == splitRoot[len(splitRoot)-1-rootIndex] {
if part == splitRoot[len(splitRoot)-1-rootIndex] && i != 0 {
prevRootIndex = rootIndex
rootIndex++
} else if prevRootIndex == rootIndex {

View File

@@ -176,7 +176,7 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
}
} else {
// Evaluate constant array size expression
if _, err = interp.cfg(n.child[0]); err != nil {
if _, err = interp.cfg(n.child[0], sc.pkgID); err != nil {
return nil, err
}
t.incomplete = true