Commit Graph

82 Commits

Author SHA1 Message Date
Marc Vertes
229ddfdae1 interp: fix use of builtins in type definitions
Make len() and cap() work on pointers. Preserve scope in case of
nested calls of cfg.

Fixes #1285.
2021-10-18 10:50:14 +02:00
Nicholas Wiersma
c5c6012947 interp: support type spec assign
This supports type spec assign types which disallows the attachment of methods onto the alias type as per the Go spec.

Fixes #1154
2021-09-23 12:16:11 +02:00
Nicholas Wiersma
836060c8ad interp: allow GTA revisit for unresolved define statements
When a define statement relies on a selector or type that may exist in another file it should revisit once GTA is complete. This allows that revisit.

**Note:** In order to keep the original GTA error for the define statement, so the error received is correct and meaningful, I have added a node `meta` property. I decided to make it generic as it may be useful in future. There may be a better way to stash errors across the GTA runs and am open to suggestion here.

Fixes #1253
2021-09-20 12:04:06 +02:00
Marc Vertes
bd9a6a4f8a interp: improve processing of recursive types
Make sure to keep always a single copy of incomplete type structures.
Remove remnants of recursive types processing.

Now `import "go.uber.org/zap"` works again (see #1172), fixing regressions
introduced since #1236.
2021-09-13 18:24:10 +02:00
Nicholas Wiersma
4653d87298 interp: types should not recover data for aliases
When `nodeType` recovers names and methods, it can overwrite the data if the type is an aliasT. When aliasing a type, do not recover the methods, this will be done in the GTA typeSpec pass.

Related to #1158
2021-09-06 18:24:04 +02:00
Nicholas Wiersma
45d569c215 interp: fix parsing of late binding consts
When a const is late binding and specified with a type, the GTA defineStmt was creating the symbol with the current scopes `iota` which is incorrect. The symbol should be created with the source nodes `rval`.

Related to #1158
2021-09-06 17:30:12 +02:00
Nicholas Wiersma
05f08d776a interp: complete type constructors
This completes the types constructors, cleaning up `nodeType`.
2021-09-01 14:46:08 +02:00
Nicholas Wiersma
772cd68fea interp: make use of type constructors
It was initially assumed that `nodeType` needed to rebuild the type from scratch, but this is not the case anymore. The existing type constructors are now used in `nodeType` to make it more readable. In doing this some bugs in type strings were found and fixed, along with adding the real package name to the type.

As `ptrOf` is now the only place that pointer types are constructed, it is feasible to cache the pointer type on the value type. To ensures that we have a consistent pointer type for any value type.
2021-08-31 10:34:12 +02:00
Nicholas Wiersma
da922ce90b interp: build type strings on the fly
This adds `itype.str` which is a string representation of the type built when the type is built. The goal is to make type comparison simpler and centralise the creation of types just to constructors and `nodeType`. `nodeType` continues to build types in parts so to reuse underlying types better.
2021-08-27 19:44:05 +02:00
Dan Kortschak
d4e25f0259 interp: fix package lookup for type analysis of local types
Fixes #1203.
2021-08-02 12:14:11 +02:00
Marc Vertes
d16bd4bcdb interp: fix package name extraction from import path
The heuristic to generate a package name identifier was incorrect. Now for binary packages, the package identifier is obtained by a symbol, generated by extract, which contains the string argument of package statement in source file. This should ensure an always correct default package identifier. 

Fixes #1095.
2021-05-10 11:20:07 +02:00
Marc Vertes
cdc6b773c2 interp: add ImportUsed method to pre-import compiled packages
This feature was already present, but part of REPL only.
It's now also possible to apply it when evaluating a string
(-e flag). Default package names collision handling is no
longer hard-coded.

With -e flag, the eval result is now printed if valid, allowing
simpler commands:

     yaegi -e 'reflect.TypeOf(fmt.Printf)'

instead of:

     yaegi -e 'println(reflect.TypeOf(fmt.Printf))'

Fixes #1084.
2021-04-30 11:36:05 +02:00
Ethan Reesor
428b658160 Allow colon-equal to override variable type
If I execute the following:

```
I := interp.New(interp.Options{})
I.Eval(`x := 1`)
I.Eval(`x := "foobar"`)
```

I expect the second declaration to override the first. `var x string` will override the previous type, and redeclaring a type, function, const, etc will override it, but the `:=` operator will not.

Currently, the result is: `reflect.Set: value of type string is not assignable to type int`
2021-04-02 09:08:04 +02:00
Ethan Reesor
992676722d interp: allow redeclaration of imports
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.
2021-03-25 23:34:03 +01:00
Marc Vertes
61b4980077 interp: do not panic in case of invalid constant definition
This is a follow-up of #1014, where an invalid constant definition  involving a builtin is now checked at CFG. In addition, some missing arithmetic operators are now detected for assign optimization.
2021-01-27 12:58:03 +01:00
Marc Vertes
8a1f9ef44e interp: parse circular interface definitions
An undefined type detection function has been added to better diagnose
incomplete type definitions. Implicit type names in interface or struct
declarations are now better handled. The incomplete status is not
fowarded to aliased type declarations to handle circular definitions.

Fixes #999 and #995. Improves #260 (goes farther, but still fails).
2021-01-14 15:46:04 +01:00
Marc Vertes
24b5375636 interp: fix memory handling of global values
In some cases, the global character of a value was lost, leading to
undefined behaviour. Now a node level field of -1 means that the value
is global, and that it should be accessed from the root data frame.

Fixes #993.
2021-01-05 17:28:03 +01:00
Marc Vertes
b25ee3f809 interp: fix method lookup on aliased types
In aliased type declarations, when the target type was imported from
an external package rather than declared locally, the aliased type was
overwritten by target, loosing ability to lookup methods on the aliased
type. Aliasing on imported types is now properly detected and handled.

Fixes #971.
2020-11-30 15:44:04 +01:00
Nicholas Wiersma
83676577ac fix: use the import path for types
When running GTA, the type `path` was set to `rpath`. This equates to the package path (`github.com/traefik/yaegi`) in most cases. In the vendored case the `rpath` is the sub package path `something/vendor/github.com/traefik/yaegi` causing issues in typecheck and likely further down the line. By using the `importPath` it makes this consistent.

**Note:** I have no clue how to test this decently. I am open to options here.

Potentially Fixes #916
2020-11-05 13:42:03 +01:00
Marc Vertes
b78d55c66b fix: compute array type size from constant expression
Fixes #875.
2020-10-05 16:12:04 +02:00
Marc Vertes
151699ef9f feature: test subcommand to run test and benchmark functions
This change allows the interpreter to execute tests and benchmarks
functions provided by packages.

The test subcommand is similar to the "go test" command and
all the relevant flags have been kept.

The ability to evaluate a directory or a package has also been added.

A new method Symbol to access exported symbol values of an interpreted
package has been added. This method is used by the test subcommand.

An EvalTest method has been added to evaluate all Go files, including "*_test.go".

The testing packages from the standard library have been added to stdlib used
symbols.
2020-09-14 11:14:04 +02:00
mpl
535e7e1c42 interp: enable declaration errors detection at parsing time
The Go parser is able to detect some (but not all) (re-)decleration errors,
if the DeclarationErrors flag is enabled, which was not done so far.

This PR therefore enables that flag, which allows the removal of some of
the now unneeded code that was recently added to support redeclarations.

Fixes #811
2020-08-28 14:36:00 +02:00
mpl
896bfeb5a1 interp: new EvalPath API
The recent changes that added some redeclaration checks implicitly added more
strictness related to namespaces and scopes which, among other things, broke
some uses that "accidentally" used to work.

For example, given

const script1 = `
	import "fmt"

	// more code
`
const script2 = `
	import "fmt"

	// some other code
`
If one Evals script1, then script2, with the same interpreter, without
specifying any scope, as the two fragments would be considered part of the same
(.go file) scope by default, a redeclaration error would be triggered because
import "fmt" is seen twice.

A work-around would have been to specify (a different) i.Name before each Eval
call, so that each script is considered as coming from a different .go file, and
hence are respectively in different scopes with respect to imports.

That lead us to realize we had to make specifying things such as file-scope, and
"incremental mode" (aka REPL), more obvious in the context of an Eval call.

In addition, we want to lay down the foundations for Yaegi being able to behave
more like the go tool wrt to various inputs, i.e. it should be able to take a
package directory, or an import path, as input, instead of just a .go file.

Hence the introduction of a new kind of Eval method (whose signature is not fixed yet):

func (interp *Interpreter) EvalPath(path string) (res reflect.Value, err error)

It partially solves the problem described above because:

1. the path given to EvalPath can be used as the file-scope hint mentioned
above, for now (even though the related implementation details might change).
2. Eval always runs in incremental mode, whereas EvalPath always runs in
non-incremental mode, hence clarifying the situation in that respect.

And to avoid confusion, the Name field of Interpreter is now non-exported,
since it is somewhat redundant with the path argument of EvalPath.

Note that #731 is not fully fixed (and might never be), as a requirement of the
proposed solution is to move the input bits of code into respective files
(instead of leaving them as strings).

Finally, some related bugfixes, documention changes, and some refactoring have
been included. Notably, there is no "empty scope" anymore, i.e. name defaults
to "_.go" when it is not specified.

Updates #731
Fixes #778
Fixes #798
Fixes #789 

Co-authored-by: Marc Vertes <mvertes@free.fr>
2020-08-20 13:14:15 +02:00
Nicholas Wiersma
913680d1ed feat: add call expression (not builtin) type checking
This adds type checking to CallExpr (excluding builtin type checking, as that is a PR in its own right) as well as handling any required constant type conversion.

This also changes constant strings and runes to be represented as `constant.Value`. Runes change `rval` type at CFG typing time to avoid having to type at AST time. There are also changes to importSpecs and `stdlib` to account for the string change. With this all `untyped` types should now be `constant.Value`s, although errors are still not returned if this is not the case to be sure we do not break things.

This also fixed a bug in `itype.methods` that would panic if the type was recursive.
2020-08-14 12:02:04 +02:00
Nicholas Wiersma
3c6df504df fix: dont allow calling init 2020-07-09 14:35:04 +02:00
Nicholas Wiersma
98eacf3610 fix: execute global variables in the correct order
* fix: constant definition loop on out of order vars

* fix: do not wire global varDecl

* fix: wire and execute global vars

* chore: add tests

* fix: refactor and lint
2020-07-09 14:05:03 +02:00
mpl
7323d97023 interp: global scope redeclaration detection 2020-06-18 15:08:04 +02:00
Marc Vertes
c1f5005b2a fix: finish support of type assertions which was incomplete (#657)
* fix: finish support of type assertions which was incomplete

TypeAssert was optimistically returning ok without verifying that
value could be converted to the required interface (in case of
type assert of an interface type), or not checking the type in
all conditions. There is now a working implements method for itype.

Fixes #640.

* style: appease lint

* fix: remove useless code block

* doc: improve comments

* avoid test conflict
2020-06-10 11:21:16 +02:00
Nicholas Wiersma
184623d81f Fix import source symbol package 2020-05-27 17:16:03 +02:00
Marc Vertes
7070367d21 fix: handle constant declarations inside function scopes 2020-05-03 18:56:04 +02:00
Marc Vertes
71f730b3d7 fix: handle forward declaration for aliased type 2020-04-22 10:50:05 +02:00
Marc Vertes
988f0c9672 fix: better handling of recursive types and forward declarations 2020-04-07 13:06:03 +02:00
Marc Vertes
b0053c874f fix: incomplete type analysis 2020-04-03 04:14:04 +02:00
Marc Vertes
b52dd8cc08 fix: substitute recursive struct type by interface{} in function arguments 2020-03-19 12:42:05 +01:00
Marc Vertes
27520f6dae fix: re-apply GTA until all global types/constants are defined 2020-02-20 12:44:04 +01:00
Marc Vertes
681f2f9c40 fix: correctly handle constant init for further type declarations 2020-02-12 12:32:03 +01:00
Marc Vertes
6c339ce562 fix: handle method declaration with forward declared type 2020-02-07 15:44:04 +01:00
Marc Vertes
92a63dbe09 fix: handle out of order type declaration for global var declaration 2020-02-03 17:36:04 +01:00
Marc Vertes
e434892b9a fix: import different source packages with same base name 2020-02-03 17:22:04 +01:00
Marc Vertes
137b16580c fix: handle binary methods where receiver is implicit 2020-02-03 16:54:04 +01:00
Marc Vertes
4f93be7f19 fix: emulate struct by interface{} only for recursive struct types 2019-12-16 19:00:07 +01:00
Marc Vertes
0d2c39d155 fix: implicit import package name was not correctly generated 2019-12-11 11:54:05 +01:00
Marc Vertes
0f46cd5efb fix: handle type declaration inside function 2019-09-26 00:50:04 +02:00
Marc Vertes
35e645c690 fix: correct handling of types alias of interfaces 2019-09-25 15:24:04 +02:00
Marc Vertes
effd64c980 fix: handle forward declaration of alias type 2019-09-24 16:10:04 +02:00
Marc Vertes
9e664ee8dd fix: global variable init from selector expression 2019-09-16 14:30:05 +02:00
Marc Vertes
058c121273 fix: add support for out of order declarations of empty global variables 2019-09-11 12:52:04 +02:00
Marc Vertes
2f0279f0f5 fix: reuse rather than re-import an already imported source package 2019-09-09 15:54:05 +02:00
Marc Vertes
b0937618b0 fix: improve handling of out of order declarations (#344) 2019-09-05 11:37:34 +02:00
Marc Vertes
869b6d2850 fix: iterate on global type analyis when necessary (#335) 2019-08-22 17:36:23 +02:00