Commit Graph

249 Commits

Author SHA1 Message Date
bysir
c10e468d01 interp: fix fieldName method parsing embedded + generic fields
Fix https://github.com/traefik/yaegi/issues/1571
2023-07-01 12:58:05 +02:00
Marc Vertes
68a430f969 interp: fix support of type assert expressions in the global scope
Add the support of type assert expressions in type parsing
which allows to process type assertions in the global scope.

Fixes #1543.
2023-04-26 10:52:05 +02:00
Marc Vertes
dc7c64ba88 interp: improve support of unsafe
Unsafe functions such as `unsafe.Alignof`, `unsafe.Offsetof` and `unsafe.Sizeof` can be used for type declarations early on during compile, and as such, must be treated as builtins returning constants at compile time. It is still necessary to explicitely enable unsafe support in yaegi.

The support of `unsafe.Add` has also been added.

Fixes #1544.
2023-04-26 10:16:05 +02:00
Marc Vertes
d6ad13acea interp: improve handling of embedded fields with binary methods
Only structures with one embedded field can be marked anonymous, due to golang/go#15924. Also check only that the method is defined, do not verify its complete signature, as the receiver may or not be defined in the arguments of the method.

Fixes #1537.
2023-04-13 18:16:05 +02:00
Marc Vertes
d124954a7d interp: fix computation of array size from constant expression
The result of the expression giving the size of an array may be an `int` instead of `constant.Value` in case of an out of order declaration. Handle both cases.

Fixes #1536.
2023-04-11 17:54:05 +02:00
Marc Vertes
c4a297cbdc interp: fix use of function as field of a recursive struct.
The logic of patching reflect struct representation has been fixed in presence of function fields and to better handle indirect recursivity (struct recursive through nested struct).

Fixes #1519.
2023-03-21 11:50:05 +01:00
Marc Vertes
8efc4f0735 interp: improve handling of methods defined on interfaces
For methods defined on interfaces (vs concrete methods), the resolution of the method is necessarily delayed at the run time and can not be completed at compile time.

The selectorExpr processing has been changed to correctly identify calls on interface methods which were confused as fields rather than methods (due to the fact that in a interface definition, methods are fields of the interface).

Then at runtime, method lookup has been fixed to correctly recurse in nested valueInterface wrappers and to find embedded interface fields in case of struct or pointer to struct.

Finally, remove receiver processing in `call()`.The receiver is already processed at method resolution and in genFunctionWrapper. Removing redundant processing in call fixes handling of variadic method, simplifies the code and makes it faster.

With those fixes, it is now possible to load and run `go.uber.org/zap` in yaegi. In turn, it makes possible for yaegi to run plugins dependent on zap, such as coraza-waf.

Fixes #1515, 
Fixes #1172,
Fixes #1275,
Fixes #1485.
2023-03-06 16:46:06 +01:00
Marc Vertes
f3dbce93a4 interp: improve handling of generic types
When generating a new type, the parameter type was not correctly duplicated in the new AST. This is fixed by making copyNode recursive if needed. The out of order processing of generic types has also been fixed.

Fixes #1488
2023-02-08 11:48:05 +01:00
Marc Vertes
7bb8b4631f interp: fix processing of aliased types
For a long time, there was a confusion between aliased types and named types (due to my misunderstanding of alias types in Go at that time). The type category `aliasT` has been renamed into `linkedT`, which is correct semantically. 

Aliased types are only declared using `typeSpecAssign`, and its processing is now distinct from `typeSpec` statement, used for named types.

A `linkedT` type is obtained by a statement like `type A uint32`, where `A` type category is therefore `linkedT`.

An aliased type is obtained by a statement like `type A = uint32` (notice the `=` sign, translating into `typeSpecAssign`).

The semantic difference is that in the first linkedT form, `A` and `uint32` are 2 distinct types, instead of being strictly equivalent in the `typeSpecAssign` form (the 2 names lead to one type definition).


Fixes #1416.
2022-10-26 17:00:07 +02:00
Marc Vertes
4a8093609f interp: fix handling interface in operators
In case of interface values, make sure that the concrete type is preserved during type inference.

Fixes #1466.
2022-10-25 14:02:05 +02:00
Marc Vertes
a5242cbb9e interp: retry type definition if an array size is undefined
In case of forward definition of a constant, a symbol may be undefined when attempting to compute the array size in type analysis. Just mark the type as incomplete instead of aborting directly, to allow resolution at a second pass.

Fixes #1470.
2022-10-24 10:44:06 +02:00
Marc Vertes
e003140c6e interp: improve internal handling of functions
Up to now functions could be stored as node values in frame (as for interpreter defined functions) or function values, directly callable by the Go runtime. We now always store functions in the later form, making the processing of functions, anonymous closures and methods simpler and more robust. All functions, once compiled are always directly callable, with no further wrapping necessary.

Fixes #1459.
2022-10-19 17:54:08 +02:00
Marc Vertes
dfeddbe823 interp: fix handling generic types with multiple type parameters
Those declarations involve the indexListExpr AST token, which was not handled in type.go. The same processing as for a single type parameter is applied.

Fixes #1460.
2022-09-22 13:50:09 +02:00
Marc Vertes
021824930d interp: improve type assertions
In type assertion at compile time, compare signatures between function types only.

Make `itype.numOut()` return the correct value for Go builtins (this was not strictly necessary due to above fix, but it is correct and improves maintainability).

Fixes #1454.
2022-09-12 22:30:08 +02:00
Marc Vertes
b8301f10a8 interp: add missing conversion for non integer array dimension
Fixes #1451.
2022-09-12 19:40:08 +02:00
Marc Vertes
63825e7201 interp: fix use of interfaces in composite types
The representation of non empty interfaces defined in the interpreter is now identical between refType() and frameType() functions, which are used to generate interpreter objects.

Fixes #1447 and #1426.
2022-09-01 12:18:08 +02:00
Marc Vertes
ae725fb3d9 interp: fix generic check on nil function
Related to issue https://github.com/traefik/traefik/issues/9231
2022-08-05 18:20:08 +02:00
Marc Vertes
14bc3b56b8 interp: add support of Go generics in interpreter
Status:
* [x] parsing code with generics
* [x] instantiate generics from concrete types
* [x] automatic type inference
* [x] support of generic recursive types 
* [x] support of generic methods
* [x] support of generic receivers in methods
* [x] support of multiple type parameters
* [x] support of generic constraints
* [x] tests (see _test/gen*.go)

Fixes #1363.
2022-08-03 15:18:08 +02:00
Marc Vertes
f76db27c77 interp: fix resolution of methods on aliased types
The type.val field was always pointing to the final underlying type
for aliased types, defeating a possible match if a method was
attached to a type in between. Now the complete chain of aliases
is always preserved.

We have added an underlying() itype method which returns the underlying
type of a defined type (aliasT), even in the presence of multiple
indirections.

We have added a definedType function which checks if type t1 is
defined from type t2 or t2 defined from t1, required when checking
assignability of aliasT types.

Fixes #1411.

PS: this is the 2nd attempt, as the first version #1412 wasn't passing
_test/issue-1408.go as well. This PR does pass and supersedes #1412.
2022-06-14 16:42:09 +02:00
Marc Vertes
6933ba2b4e interp: improve type checking for defined types
Fixes #1408.
2022-06-13 11:24:09 +02:00
Marc Vertes
6c74ab7bec interp: allow conversions of untyped complex
For untyped numerical types, conversions to different numerical
types can be allowed if there is no overflow (not checked here).

Fixes #1402.
2022-06-13 10:42:08 +02:00
Marc Vertes
2248851d77 interp: fix creation of binary composite types (#1391)
* interp: fix creation of binary composite types

Use direct assignment instead of reflect.Value Set method to
initialize a binary composite type, as for non binary types.
It ensures that a new reflect.Value is stored in the frame
instead of modifying a possibly existing one, which can defeat
the purpose of initializing variables in a body loop.

While there, remove the need to have and use a mutex on types.

Fixes #1381.

* review: rework a bit the test

Co-authored-by: mpl <mathieu.lonjaret@gmail.com>
2022-05-05 21:31:10 +02:00
Marc Vertes
f07f25f1ba interp: handle struct with multiple recursive fields (#1372)
* interp: handle struct with multiple recursive fields

In case of a recursive struct with several recursive fields of
different type, only the first one was properly fixed when
constructing the corresponding reflect type. We now memorize and
process all fields at the same depth level.

Fixes #1371.

* Update interp/type.go

Co-authored-by: mpl <mathieu.lonjaret@gmail.com>

* fix lint

* fix comment

Co-authored-by: mpl <mathieu.lonjaret@gmail.com>
2022-04-07 14:53:23 +02:00
Marc Vertes
2819b4167b interp: fix derivation of type of slice expression of binary object
Fixes #1328.
2021-12-20 15:46:05 +01:00
Marc Vertes
cb81fe41ab interp: fix type processing to support multiple recursive fields
Fixes #1304
2021-11-08 20:46:12 +01:00
Marc Vertes
f46ef67180 interp: fix computation of ellipsis array length
Fixes #1287.
2021-10-20 14:36:05 +02:00
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
Marc Vertes
5bf4daef2d interp: fix type check of methods with a receiver of interface kind
Fixes #1280.
2021-10-08 17:44:09 +02:00
Nicholas Wiersma
286d6c6359 interp: handle recursive and incomplete seen types in nodeType
This comes from experiments looking into #1259 where incomplete twice seen types are marked as complete. To mitigate the problem instead of a map of seen types in `nodeType` a slice is used as a cheap way to keep track of our current path through the node tree.
2021-09-27 10:20:13 +02:00
Nicholas Wiersma
84424b52bc interp: handle alias of an alias
When dealing with an alias of an alias, the actual underlying type of the source alias should be used.
2021-09-27 10:08:11 +02:00
Nicholas Wiersma
5af51aefe6 interp: fix type selector precedence
The current `nodeType` selector precedence is heavy handed in favour of package type. It seems to often create `typeSym` symbols as variable types in the scope will never be found. To fix this if the ancestor node is a field expression, the package type is searched for. After this, if the type is still `nil` the normal scope is searched using `nodeType2`.

Fixes #1158
2021-09-15 10:42:08 +02:00
mpl
e7c0f68bab interp: fix Clone documentation 2021-09-14 12:30:13 +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
Ethan Reesor
91a55cc4c5 interp: add debug interface
Adds an interface to `interp` that can be used to build an interactive debugger, such as those used by IDEs.

Closes #1188

All basic debugger features work, with one exception: breakpoints in some locations don't work, due to `setExec` creating a temporary `bltn` (https://github.com/traefik/yaegi/issues/1188#issuecomment-886107905).

Example, using a Debug Adapter implementation with VSCode:

![image](https://user-images.githubusercontent.com/879055/128620736-94b6efde-2e5f-43ad-82c9-d919c3fe401f.png)
2021-09-06 15:32:10 +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
d2569a85a6 interp: fix default types for runes
When using an untyped rune in an interface, the default type was blindly untyping it. This fixes this issue.

Fixes #1238
2021-08-31 12:32:10 +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
4af992bccb interp: create real recursive types with unsafe type swapping
As the unsafe and pointer methods in `reflect` are to be depreciated, and seeing no replacement functions, it is now forced that some unsafe is needed to replace this as when and interface is dereferenced it is made unsettable by reflect.

With this in mind, this adds real recursive types by hot swapping the struct field type on the fly. This removes a lot of compensation code, simplifying all previous cases.

**Note:** While the struct field type is swapped for the real type, the type string is not changed. Due to this, unsafe will recreate the same type.
2021-08-30 18:38: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
Marc Vertes
fc970799a1 interp: add support of interface wrappers to type assertions
Store the interpreter value of the interface object to wrap as
a field called IValue, at offset 0 in wrapper structures.

Update extract to include IValue field.

In typeAssert, detect interface wrapper, and dereference the
interpreter value from IValue wrapper field.

Fixes #1166.
2021-07-12 17:10:13 +02:00
Marc Vertes
f6d0cf95fd interp: fix array declaration with a typed constant size
In parsing array type declaration, The type check of array size was
restricted to `int`. Broaden the test to accept any valid integer
kind.

Fixes #1175.
2021-07-08 12:30:12 +02:00
Marc Vertes
25b570d7e9 interp: fix the detection of builtin calls during parsing
Avoid shortcuts, and apply regular scoping rules for symbol
resolution when checking for builtin calls.

Fixes #1173.
2021-07-08 11:26:05 +02:00
Marc Vertes
297b40d526 interp: improve field and method resolution in presence of collisions.
The resolution method was not compliant with the Go specification which
requires to retain the object where the field or method is the most
shallowed.

The detection of ambiguous fields or methods (same depth in different
objects) has also been added.

Fixes #1163.
2021-07-06 12:12:05 +02:00
Marc Vertes
e32b2ab6bd interp: improve handling of interface values
In selector resolution, struct field matching now precedes
method matching. Before struct field matching could be skipped
in case of a matching method, which is incorrect, as demontrated
by _test/issue-1156.go.

Field lookup has been fixed to operate on recursive structures.

Concrete type values are derived when filling a receiver for
interface methods.

LookupBinField has been fixed to skip non struct values.

LookupMethod has been fixed to iterate on interface values as
well as concrete type values.

Fixes #1156.
2021-06-24 16:20:13 +02:00
Marc Vertes
8f9eccdd61 interp: fix assign of function values with binary methods
In typecheck.go, detect binary methods so we know when to skip the receiver as first parameter when checking function signatures. The signature check is not yet performed, we just avoid a false error.

In cfg.go, take care to label types with isBinMethod field to true whenever a binary method is resolved.

Also, do not attempt to wrap node in functions if the node value is already a binary function.

Fixes #1145.
2021-06-18 12:56:05 +02:00
Marc Vertes
dd03989709 interp: fix handing nil when appending to a slice
Fixes #1147.
2021-06-18 12:44:07 +02:00
Ethan Reesor
25c2a435f5 Correctly resolve type aliases when building array literals
Fixes #1150

1. When resolving a selector expression involving an aliased type, resolve the aliased type
2. When building an array literal, resolve the aliased type

Aliases of named array and slice types were the only ones that didn't work, but I added the other test cases for the sake of completeness and through testing.
2021-06-18 10:10:10 +02:00
Marc Vertes
db955e671f interp: fix append a slice on binary slice
Fixes #1128.
2021-06-15 14:34:08 +02:00
Marc Vertes
b1ef9251d4 interp: fix detection of binary types implementing interfaces
Fixes #1136.
2021-06-11 17:58:11 +02:00