Commit Graph

52 Commits

Author SHA1 Message Date
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
c80c605ab9 interp: support wrapping of nested interfaces
Add getConcreteType to retrieve the concrete type of a nested interface
value implementing a specific interface for which a wrapper exists.

If method resolution fails at runtime, a panic is now issued instead
of an error message and continue.

Fixes #1187.
2021-07-26 19:12:11 +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
Marc Vertes
b19afbfe93 interp: avoid panic in output value generation for recursive types
Fixes #1134.
2021-06-11 17:44:12 +02:00
Marc Vertes
c86436afa6 interp: fix litteral map containing binary functions
The case of assigning a binary function to a funcT object was
solved elsewhere. Factor the case in genDestValue to apply it
at multiple places.

Fixes #1100.
2021-05-27 12:04:11 +02:00
Marc Vertes
7d8fdbc1fc interp: fix closure in a struct field
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.
2021-03-11 15:26:04 +01:00
mpl
2e17cfab4f interp: do not wrap empty interface
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 #984 
Fixes #829 
Fixes #1015
2021-02-04 12:08: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
9e1da978b0 interp: fix handling interface types in wrapped functions
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.
2020-12-15 16:14:05 +01:00
mpl
1e0f6ece6e interp: support more type assertion cases
Fixes #955
2020-11-30 18:00:04 +01:00
Marc Vertes
d0a34d467b interp: fix getting unsigned constant value
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.
2020-11-09 17:40:04 +01: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
cdc352cee2 feat: add index and composite literal type checking
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.
2020-08-11 15:58:04 +02:00
Marc Vertes
25c681c1e6 fix: regression on range following #787 2020-07-30 10:52:05 +02:00
Marc Vertes
9c51f6bb69 fix: correct range on arrays of interface objects 2020-07-23 12:25:04 +02:00
Nicholas Wiersma
a15ecb7176 feature: handle nested recursion
* 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
2020-07-02 23:20:03 +02:00
Marc Vertes
9977ef6fc6 Revert "fix: make interpreter methods discoverable by runtime (#722)" (#732)
This reverts commit a3b2737b5c.
2020-07-01 16:16:26 +02:00
Marc Vertes
a3b2737b5c fix: make interpreter methods discoverable by runtime (#722)
* fix: make interpreter methods discoverable by runtime

When generating an interface wrapper, lookup existing wrappers by method
to get the one with the biggest set of methods implemented by interpreter.

A string method is also added to wrappers, in order to provide a string
representation of the interpreter value rather than the wrapper itself
(at least for %s and %v verbs).

This allows the runtime to pickup an interpreter method automatically
even if the conversion to the interface is not specified in the script. As
in Go spec, it is enough for the type to implement the required methods.

A current limitation is that only single wrappers can be instantiated,
not allowing to compose interfaces.

This limitation can be removed when the Go reflect issue
https://github.com/golang/go/issues/15924 is fixed.

Fixes #435.

* test: add a simpler test
2020-06-29 14:25:14 +02:00
Nicholas Wiersma
1fe91be882 feature: refactor numeric constants and detect overflow 2020-06-18 09:20:04 +02:00
Nicholas Wiersma
eb25c84797 fix: handle call ellipsis 2020-06-03 16:42:04 +02:00
Nicholas Wiersma
01e4cdea70 fix: recursive struct function call 2020-06-03 00:18:04 +02:00
Marc Vertes
7d56fb067e fix: improve setting of interface objects 2020-04-30 17:44:04 +02:00
Marc Vertes
1feece61ce fix: improve handling of function return values 2020-04-30 10:32:04 +02:00
Marc Vertes
7b2d91bcb5 fix: handling values in map of interfaces 2020-04-22 10:34:05 +02:00
Marc Vertes
c7c1bea7ef fix: do not attempt to store data in _ var 2020-03-09 13:22: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
23dfef0ac8 fix: define a correct zero value for an not initialized interface{} 2020-02-04 18:04:05 +01:00
Marc Vertes
786ea366ab fix: handle nil function closure 2019-11-25 23:36:03 +01:00
Marc Vertes
e506969172 fix: correct handling of dynamic type for interface values 2019-11-25 23:20:04 +01:00
Marc Vertes
3969ab16c4 fix: improve handling of untyped complex numbers 2019-10-29 18:14:05 +01:00
Dan Kortschak
714253c1e6 interp: add eval cancelation by semaphore 2019-10-29 16:18:04 +01:00
Marc Vertes
15686873e0 fix: assign binary func to func type var 2019-10-20 04:52:03 +02:00
Dan Kortschak
bb2921b42f interp: fix range expression handling 2019-09-30 22:44:04 +02:00
Marc Vertes
ec1ee5f5b6 fix: support array operations on array pointers 2019-09-18 23:32:04 +02:00
Marc Vertes
122506cc79 Fix: handle recursive type definition (#239) 2019-07-09 00:08:12 +02:00
Marc Vertes
cc8e05d61b chore: cleanup API, unexport internal constants, types and variables. (#229) 2019-06-24 16:24:47 +02:00
Marc Vertes
25ddbbad03 fix: correct handling of function in struct field (#226) 2019-06-17 14:40:55 +02:00
Marc Vertes
cc2d122cd3 fix: correct negate operator (#199) 2019-05-31 12:48:46 +02:00
Marc Vertes
557a02d616 perf: better handling of return values in func calls (#193) 2019-05-27 12:21:03 +02:00
Marc Vertes
eb705baa01 fix: implement a single interface wrapper for error type (#190) 2019-05-21 16:49:26 +02:00
Marc Vertes
1eb950f9b9 fix: correct type conversion for unsigned array index (#179) 2019-05-01 19:12:52 +02:00
Marc Vertes
c6c7f8cea6 fix: automatic type conversion for untyped arg of append (#177) 2019-05-01 16:49:57 +02:00
Marc Vertes
16690838e3 fix: correct handling of multi-assign operations, including swap (#173) 2019-05-01 16:25:31 +02:00
Marc Vertes
6657e9a18b feat: add support for named output variables (#113)
* feat: add support for named output variables

Function output parameters are located at the start of the function
frame, uninitialized, as they could be only set through return
statements.

Supporting named output variables requires to:

- identify and allocate symbols corresponding to output names:
  done at ident parsing, with the funcRet() helper,

- compute the location of output name in the frame:
  done with retRank() helper,

- initialize the frame entry with the zero value of symbol type,
  as the symbol can be accessed and written at multiple times,
  and return not setting the variable (opposite to unnamed).
  Done with frameType() helper, which now takes into account
  output parameters.

* refactor: simplify memory management

Perform function frame analysis at pre-order, instead of post-order, to
initialize memory frame, and track value types. Remove all operation
involving unitialized types. Frame memory layout is now build
incrementally, instead of having to perform dedicated tree walks on AST.
2019-03-12 19:58:02 +01:00
Marc Vertes
5677e0501e fix: correct propagation of values during eval (#95)
Eval returns the value of the root node of AST, so ensure
that node values are propagated back to ExprStmt and BlockStmt,
which should be sufficient to handle evaluation of simple
statements.
2019-02-19 14:51:44 +01:00
Marc Vertes
6d21cefe75 fix: allow imported binary variables to be set (#85)
Change the way imported binary variables are imported, from
`reflect.ValueOf(val)` to `reflect.ValueOf(&val).Elem()`, to allow these
variables to be set from the interpreter.
Regenerate stdlib packages accordingly.
Ensure that binary value is forwarded if it exists.
Add tests.
2019-02-07 15:41:22 +01:00
Marc Vertes
17fa77c693 fix: implement handling of interface types (#80)
Methods are now resolved correctly on interface objects.
2019-02-06 10:21:25 +01:00
Marc Vertes
5c79a97543 feat: add support for comparison of multiple types (#42)
The code for comparison operators is now generated by genop.
The support for multiple type has been added.
Missing operators <= and >= are now implemented.
2019-01-24 19:13:30 +01:00