Skip to content

Commit

Permalink
fix: import different source packages with same base name
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes authored Feb 3, 2020
1 parent 712891d commit e434892
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 46 deletions.
7 changes: 7 additions & 0 deletions _test/b1/foo/foo.go
Original file line number Diff line number Diff line change
@@ -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 changes: 3 additions & 0 deletions _test/b2/foo/foo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package foo

var Desc = "in b2/foo"
10 changes: 10 additions & 0 deletions _test/import8.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

import "github.com/containous/yaegi/_test/b1/foo"

func main() {
println(foo.Desc)
}

// Output:
// in b1/foo
19 changes: 6 additions & 13 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions interp/gta.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions interp/interp.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
Expand All @@ -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()
Expand Down
21 changes: 9 additions & 12 deletions interp/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}

Expand Down Expand Up @@ -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
}
22 changes: 10 additions & 12 deletions interp/src.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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
}
Expand All @@ -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
}
}
Expand All @@ -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...)
Expand All @@ -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()
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit e434892

Please sign in to comment.