As opposed to other symbols, goto labels must be searched in included
scopes, not upper ones. Implement scope.lookdown to perform this,
to allow calls to goto to be embedded in included scopes where label
is defined.
Fixes#953.
Perform function declaration type check from the upper level scope (the scope where the
function is declared), to avoid possible collisions of local variables with package names.
Fixes#957.
A non-constant shift expression can be untyped, requiring to apply a
type from inherited context. This change insures that such context is
propagated during CFG pre-order walk, to be used if necessary.
Fixes#927.
Type checking on shift operands was failing for untyped variable values.
Fix propagation of type in assignment. Optimize assignment of arithmetic
operations on variables by skipping the assign and writing directly to
destination frame value in the operator function.
Skip some slow tests when given -short test option.
Fixes#917.
The assignable check used to be too strict as it lacked the property that
if an untyped const can be represented as a T, then it is assignable to T.
And we can now use that fixed check to add a missing check: in a return
statement, we now make sure that any of the returned elements are
assignable to what the signature tells us they should be.
There was several issues:
- access to field on pointer to struct from runtime: fix in
lookupBinField
- assign operation was skipped when performed in a comm clause
- the direction of comm clause was wrong if a channel send operation was
performed in a body of a receive comm clause
Fixes#884.
When the type is implicit, the first element in the list of children is
not the type of the composite literal, but it is one of the actual
children, so it should not be discarded.
Fixes#862
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
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 #731Fixes#778Fixes#798Fixes#789
Co-authored-by: Marc Vertes <mvertes@free.fr>
This adds type checking to SliceExpr as well as handling any required constant type conversion.
It should be noted that the check that `high` and `max` are not nil in a 3-index slice has been left out as this check is handled before type checking. Tests have been included for these cases.
In the case of a pointer or alias composite literal expression, `compositeGenerator` changes the type to remove the pointer or alias. This causes a nested composite literal to have the wrong type.
Instead of changing the node type, the removal of the pointer or alias is moved to the runtime, allowing the node type to remain unchanged. This fixes potential issues in the 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.
This adds type checking to both `IndexExpr` and `CompositeLitExpr` as well as handling any required constant type conversion.
This includes a change to the type propagation to the children of a composite literal. Previously in most cases the composite literal type was propagated to its children. This does not work with type checking as the actual child type is needed.
The detection of special cases of interpreter functions and interfaces
is more precise. It allows at least to complete parsing of
code where type is derived from a type assertion expression.
Fixes#770.
The range init AST execution was skipped, and range could work
only over variables or direct function calls. By setting the
start node to the start of init and not init itself, we ensure
that the init AST is always taken into account.
Fixes#775.
* 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
By returning early in case of incomplete type in CFG, we avoid
a panic, and let a chance to a new attempt after the missing
type has been parsed.
Fixes 763.
* fix: switch type from valueT in struct case
In a struct case in type assertion, if the source is a valueT, we still need to take the struct type to allow method and field resolution.
* fix: handle all ptr structs as well
* fix: copy the type in recursion
In more advanced recursive cases, setting the rtype to interface may interfear with typeing. To stop this from happening, instead of setting t.val.rtype to interface in the hope it will be set correctly later, a copy if the type is made, and the rtype of the copy is set to interface{}.
* fix: detect intermediate recursive structs
In the case of a nested recussion, each symbol can have
a different perspective on the recursion. In this case,
it is impossible to move from one struct to the next.
To keep the perspectives the same, any intermediate struct
that contains a recursion should also be set to interface{}.
so that all perspectives are the same.
* fix: handle arb recursion
* chore: refactor dref to be consistent
* fix: invalid recursive struct issue
* fix: handle checkptr issue
* fix: move unsafe into function to stop ptr check
* fix: handle deref in assign
When operations write their result to a non-local frame, the node
level field must be set accordingly, otherwise they attempt to write
in the wrong frame.
Fixes#730.
* fix: untyped constant cconverson to default type
In definition assign expression, the source type is propagated to
the assigned value. If the source is an untyped constant, the
destination type must be set to the default type of the constant
definition. A fixType function is provided to perform this.
In addition, the type conversion and check of constants is
refactored for simplifications.
Fixes#727.
* test: fix _test/const14.go
* fix: detect default comm clause in select from AST
The heuristic to distinguish a default comm clause was too weak.
Make it robust by using AST.
Fixes#646.
* rename test to avoid conflict
* fix: perform send channel action for select
The CFG was wrong for select send comm clauses. If an init operation
on channel was required (like a derefence, index operation, ...) it
was skipped. The bug was invisible in case of a local var channel.
A send channel init operation consist to prepare both the data to
send (right subtree of send AST) and the channel itself (left
subtree of send AST). All channel init operation must be performed
prior to call select.
Fixes#647.
* doc: fix comment
* invert test to continue early
please note that this also changes the logic a little bit, since the
line that was:
if pn != nil {
now implictly becomes:
if an != nil && pn != nil {
(which I think is actually more correct).
* explicit chaining of init actions in select
* explicit chaining of init actions in select
Co-authored-by: mpl <mathieu.lonjaret@gmail.com>
* interp: detect local redecleration
Fixes#666
* make make check happy
* fix typo in filenames, add them to the exclusion list
Co-authored-by: Marc Vertes <mvertes@free.fr>