This patch brings the following modifications:
- consider that an interface is assignable to another if the former
implements the latter
- call TypeOf() method instead of rtype field when resolving methods, to
handle first met types
- unwrap error interface inplace rather than embedding it in an
interface definition, as lower case named embbeded interface may
not be handled by reflect when lookup for a method.
Fixes#1063. Partially improves #1058.
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.
Functions in a struct fields are always wrapped (as potentially
used by the runtime), so generate a function wrapper also for
closure when assigned to a struct field.
When such a function is called from the interpreter, ensure that
interface arguments are also wrapped so method and receiver resolution
can be performed.
Fixes partially #1043.
The first change forces a variable definition to reallocate a
new memory slot to avoid corrupting a previously defined one in
a loop block.
The second change ensures that the frame clone operations obtains
a copy of the original data slice, to preserve the original context
set in a loop.
Fixes#1035.
As mentioned in #1030, when an Eval panic, it is print with `fmt.Println()` and not to the configured `interp.Options.Stderr`. According to https://github.com/traefik/yaegi/blob/master/interp/interp.go#L210, it should be removed in future version so I'm not sure if this pull request is necessary. However, it could fix the issue in the meanwhile.
Fixes#1030.
This is a follow-up of #1017, generalizing the use of reflect.Set
method to set, and possibly overwrite, the concrete value of
interface objects all accross the implementation of operators.
Previous optimized implementation for non-interface objects is
preserved.
The empty interface (interface{}), and its variants (such as []interface{} and map[string]interface{}), are commonly used in Go to (json) Unmarshal arbitrary data. Within Yaegi, all interface types are wrapped in a valueInterface struct in order to retain all the information needed for a consistent internal state (as reflect is not enough to achieve that). However, this wrapping ends up being problematic when it comes to the type assertions related to the aforementioned Unmarshaling.
Therefore, this PR is an attempt to consider the empty interface (and its variants) as an exception within Yaegi, that should never be wrapped within a valueInterface, and to treat it similarly to the other basic Go types. The assumption is that the wrapping should not be needed, as there is no information about implemented methods to maintain.
Fixes#984Fixes#829Fixes#1015
When checking for untyped values, we can be sure at this stage that they must be a const value or already untyped. Checking for type string equality is no longer a good measure.
Fixes#1000
When passing a function reference as an interface in a composite binary map, the case should be handled to not take the value of the the node.
Related to #886
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.
A channel can be used to interchange data with the pre-compiled
runtime and therefore objects impletementing interfaces must be
wrapped if necessary, using genInterfaceWrapper.
A similar treatment could be applied when sending interpreted
functions over a channel, to be provided in a new PR.
Fixes#1010.
Fix the logic to detect recursive struct types, which was giving a false positive.
We now use the local type name as key in tracker map.
A non-regression test case is included (_test/struct49.go).
This completes #1008.
If a struct contains several fields of the same temporary incomplete
type, it could be detected incorrectly as a recursive struct. Pass
a copy of defined types map to avoid this issue.
Fixes#1007.
Always attempt to obtain an integer constant value for operators
expecting so. It allows to use '/' in integer constant defintions,
instead of default big.Rat.
Fixes#1005
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).
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.
The interpreter interface type was replaced by a reflect.Value in
objects passed or return to function wrappers, losing the ability
to retrieve methods.
The valueInterface is now preserved, and correctly accessed if
wrapped multiple times.
Fixes#977.
typeAssertStatus deals with the 3rd form of type assertion ("_, ok"), for
when one does not care about the result of the assertion itself.
Some cases for it, which are already fixed for the two other forms of
type assertions, had not been fixed for this form yet.
Therefore, this change fixes such cases for this form, while integrating
typeAssertStatus to the same code path as for the two other forms.
The type check was generating false negatives. A correct test to check the
adressable status of an array is more complex to implement, and will
be done later.
Fixes#973.
The long-form (with comma-ok) ones were already fixed but the short-form
ones were not because they were in a completely different code path.
This PR also refactors the code so that both short-form and long-form
are now merged in the same function.
N.B: even though most (all?) cases seem to now be supported, one of them
still yields a result that does not satisfy reflect's Implements method
yet. It does not prevent the resulting assertion to be usable though.
N.B2: the code path for the third-form (_, ok) hasn't been fixed and/or
refactored yet.
Fixes#919
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.
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.
in `callBin`, call arguments are converted to the corresponding
parameter type. In a case of an interface, the original concrete type
should be preserved instead, and only wrapped to an interface type for
internal interpreter types, as runtime values should already implement the
interface.
This change removes the interface wrapping when parameter is a runtime
value (valueT or ptrT to valueT).
This removes some overhead when handling runtime values, and keep a
similar behavior between interpreted and pre-compiled code. For
example, `io.Copy` preserves its internal optimisations when passed a
`bytes.Buffer`.
The function vUint, used to get the unsigned integer value of a value,
variable (frame) or constant, was broken for constant.Value expression.
Fixes#948.
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
Interpreter function types are represented internally by the AST node
of their definition. The conversion operation creates a new node with
the type field pointing to the target type.
Fixes#936.
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.