Catch illegal combinations for all binary operators.
Memoize type conversion to reflect.type.
Add some unit tests for arithmetic and assign operations.
* 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.
Define a new Method action to detect method calls on interface types.
In this case the receiver is resolved from a dynamic type rather than a static one.
Handle method calls where receiver is a pointer.
In typeAssert, always return an interface value with the concrete type, to fix method lookup on interface objects.
Add relevant tests.
evalCheck is renamed in eval.
Add testCase struct to describe test cases. A "pre" function can be
invoked prior to run the eval script which generate the result.
A runTests function executes all tests in a testCase array. Parallel
sub-tests execution is disabled, as simultaneous compile operations
in the same interpreter context is not yet safe.
Many simple tests can now be describe in one-liners.
A Wrap represents the wrapper which allows objects created by the
interpreter to satify Go interfaces (despite limitations in reflect
which forbid dynamic method creation).
All the struct fields are functions, where the fied name corresponds
to the method name prefixed by "Do". The function signature must
be the same as the interface one.
A corresponding Wrap method Xyz which satisfies the interface must
exist and must invoke the DoXyz function.
To be usable, the interpreter should return a Wrap instance with
the relevant function fields filled. The application can then invoke
methods on it. The method calls will be forwarded to the interpreter.
Only the Wrap type definition needs to be exported to the interpreter
(not the interfaces and methods definitions)
A complete working example test is provided, and necessary corrections
in binary struct fields as functions.
Add an iString() type helper function, and use it to define the correct
conversion value prior to compare. The correction is to be applied to all
comparison operators, so regenerate op.go.
Wrap functions in struct fields in `reflect.Value` to have a consistent
representation of function inside and outside the interpreter.
Teach assign to wrap a function node if destination is reflect.Value
The same needs to be done for composite literal, in a next commit.
The field index computed from the key value expression in sparse
composite literal was stored in `node.findex`, corrupting the memory
allocation. It is now stored in a local variable for immediate use.
Type category `UnsetT` is renamed in `NilT`.
Catch invalid use of untyped nil in `:=` expression.
Convert nil to output parameter type when used in `return` expression.
Improve and add relevant unit tests.
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.
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.
append() now returns the underlying array type.
Method lookup was skipped for selector expression on arrays.
Pointer expression was incorrectly parsed as a dereference instead of
type expression.
Call genNodeWrapper on interpreted function returned by a closure,
itself being wrapped, to ensure that the function can be called from
binary, no matter the level of nesting closures.
Rename the package scope from internal package name to alias name.
Detect different packages in the same directory (forbidden by spec).
Update example to test named import.
At CFG, in pre-order processing, determine the correct type of CompositeLitExpr from its first child (if it's a type) or from the ancestor node.
Make sure The type is propagated to children so the algorithm works recursively.
Fix also the isType() method to handle case of imported types,
either from source or binary packages.