Skip to content

Commit

Permalink
interp: allow redeclaration of imports
Browse files Browse the repository at this point in the history
This PR adds an interpreter option, `AllowRedeclaration`. If this option is set, `(*Interpreter).Eval` will allow package imports to be redeclared. That is, no error will be raised and the package symbol will be overwritten.

I would like to use Yaegi to power a Go notebook (VSCode extension), somewhat like Jupyter. A notebook can have multiple Go 'cells' which can be evaluated (using Yaegi). As much as is possible, evaluating cells should be idempotent - that is, evaluating a cell multiple times should have the same effect as evaluating it once, ideally. Cells that are not idempotent can degrade the user experience.

Specifically, Go files tend to declare all imports in a single block. In a notebook, I'd put all imports in a single block, in their own cell. When I decide I need to import an additional package, I want to add that import to the existing cell and evaluate it. Without this MR, reevaluating that block usually causes an error.
  • Loading branch information
firelizzard18 authored Mar 25, 2021
1 parent 451c754 commit 9926767
Showing 1 changed file with 8 additions and 2 deletions.
10 changes: 8 additions & 2 deletions interp/gta.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,12 @@ func (interp *Interpreter) gta(root *node, rpath, importPath string) ([]*node, e
// imports in different source files of the same package. Therefore, we suffix
// the key with the basename of the source file.
name = filepath.Join(name, baseName)
if _, exists := sc.sym[name]; !exists {
if sym, exists := sc.sym[name]; !exists {
sc.sym[name] = &symbol{kind: pkgSym, typ: &itype{cat: binPkgT, path: ipath, scope: sc}}
break
} else if sym.kind == pkgSym && sym.typ.cat == srcPkgT && sym.typ.path == ipath {
// ignore re-import of identical package
break
}

// redeclaration error. Not caught by the parser.
Expand All @@ -233,9 +236,12 @@ func (interp *Interpreter) gta(root *node, rpath, importPath string) ([]*node, e
name = pkgName
}
name = filepath.Join(name, baseName)
if _, exists := sc.sym[name]; !exists {
if sym, exists := sc.sym[name]; !exists {
sc.sym[name] = &symbol{kind: pkgSym, typ: &itype{cat: srcPkgT, path: ipath, scope: sc}}
break
} else if sym.kind == pkgSym && sym.typ.cat == srcPkgT && sym.typ.path == ipath {
// ignore re-import of identical package
break
}

// redeclaration error
Expand Down

0 comments on commit 9926767

Please sign in to comment.