Compare commits

...

415 Commits

Author SHA1 Message Date
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
Ethan Reesor
1df5dc2e93 Update Interpreter.Use API
### Background

#1102 changed how `Interpreter.Use` interprets export paths such that the last path component is stripped and used as the package name. This resulted in #1139 - attempting to Use an export with only one path component, such as `foo`, would result in the import path being `.`.

### Breaking API Change

This PR changes the signature of `Interpreter.Use` from `Use(Exports)` to `Use(Exports) error`.

### Fix for #1139

With this PR, if Use is called with an incomplete export path, such as `foo`, Use will return an error.
2021-06-24 10:00:05 +02:00
Ethan Reesor
36594014c9 Fix handling of ImportUsed packages
Fixes #1151

If I add a package with `Use` and import it with `ImportUsed`, the package is added to the universe scope as `<pkg>`. If I import with `Eval`, the package is added as `<pkg>/_.go`. However, `(*node).isType` (in cfg.go) only checks for `<pkg>/_.go`. Thus, packages imported with `ImportUsed` can be inaccessible.

This MR updates `(*node).isType` to fall back to `<pkg>` if `<pkg>/_.go` does not exist.
2021-06-21 11:24:10 +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
b2a11eaf2a interp: preserve concrete type when converting type to interface
This allows to fix the reassignment of an non empty interface value.
Before, reassignment was limited to empty interfaces.
    
Fixes #1138.
2021-06-18 10:32:13 +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
Ethan Reesor
3d1a21094a Avoid unnecessary calls to FieldByIndex
Fixes #1149

Because of how aliases are handled, `n.gen` is set to `getIndexSeqMethod` or `getIndexSeqPtrMethod` in cases like the one described in #1149. As a result, `FieldByIndex` can be called on a value that is not a struct, which causes a panic. This MR updates those two methods to avoid that call if the index array is empty.
2021-06-18 09:40:13 +02:00
Ethan Reesor
2a0d29a390 Add a newline after src in wrapInMain
Fixes #1142
2021-06-16 15:14:17 +02:00
Marc Vertes
db955e671f interp: fix append a slice on binary slice
Fixes #1128.
2021-06-15 14:34:08 +02:00
Ethan Reesor
ab44c38298 interp: handle binary array literals
This is a small change that allows use of composite array literals, such as:

```go
type Vec3 [3]float32

var foo = []Vec3{
	{1, 0, 0},
	{6, 0, 0},
	{6, 2, 0},
	{2, 2, 0},
	{1, 1, 0},
}
```
2021-06-14 14:48:05 +02:00
Marc Vertes
93e2db7085 interp: fix a wrong control flow in switch
In switch case expressions, the condition on case clause was
not always properly evaluated. Reverse the order of case clause
evaluations (as already done for if-else-if fashion), and fix the
wiring to false-next and true-next nodes.

Fixes #1126.
2021-06-14 12:18:07 +02:00
Marc Vertes
b1ef9251d4 interp: fix detection of binary types implementing interfaces
Fixes #1136.
2021-06-11 17:58:11 +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
a6762d500c interp: fix use of unrestricted symbols
This is fixing a regression introduced by #1102.

Fixes #1129.
2021-06-11 16:34:11 +02:00
Marc Vertes
c4174a7167 interp: fix assign of function call with implicit type assert.
De-optimize a use case to avoid skipping an assign operation with an implicit type assertion at function call return.

Fixes #1122.
2021-05-27 13:38:07 +02:00
Marc Vertes
2f9fe7003a interp: fix relative import path detection on MS-Windows
Fixes #1106.
2021-05-27 12:34:09 +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
29e912e90b interp: fix method lookup on pointers to binary types
This case was missing in the selector expression processing.

Fixes #1083.
2021-05-27 11:54:04 +02:00
Marc Vertes
e29de04513 interp: fix constant types from imported packages
In binary packages, constants are wrapped in constant.Values, to
support arbitrary precision. Their type must therefore be converted
back to a regular type at import.

Fixes #1101.
2021-05-27 11:40:06 +02:00
Marc Vertes
c6945514cb interp: sandbox to preserve type of os.Stdin os.Stdout and os.Stderr
Use YAEGI_SPECIAL_STDIO env boolean to overwrite os.Stdxxx by
non file descriptors io.Writer / io.Reader interfaces. It is set
to true when testing to allow redirection to byte buffers.

The default behaviour is now to preserve the original concrete type
when sandboxing stdio, which maintains compatibility.

Fixes #1092.
2021-05-25 09:36:08 +02:00
Marc Vertes
847cd7ed2b interp: fix calling of variadic binary methods
Fixes #1046.
2021-05-22 11:48:07 +02:00
Marc Vertes
fbf897b047 interp: improve type check of binary methods
Some binary method calls were wrongly rejected. There is still
some ambiguous cases as binary method signature may include or
not the receiver as first argument, depending on how the method
was resolved.

With this fix, `import "golang.org/x/net/html"` doesn't panic
anymore, but not all tests are passing yet, i.e.
`yaegi test golang.org/x/net/html` still has failures, to be
investigated.

Fixes #1107.
2021-05-20 17:12:10 +02:00
Marc Vertes
45c7b8008a interp: fix special range on string
In this range variant "for k, v := range aString", k must
be the byte position of the rune in the byte array, rather than
the index of the rune in the rune array.

Fixes #1088.
2021-05-20 17:02:13 +02:00
Marc Vertes
4788775f8c interp: improve type checking for "+" operator
Fixes #1093.
2021-05-20 15:50:08 +02:00
Marc Vertes
bcb8546e91 interp: fix goto label by not overwriting destination
Fixes #1115
2021-05-20 11:38:04 +02:00
Marc Vertes
befa5a2b54 interp: fix return of function call involving a type conversion
In that case, direct propagation of result can not be attempted,
as the frame types will be different between the source and destination.
Disabling the optimisation and using The regular case involves an intermediate
frame entry, which enables the type conversion.

Fixes #1091.
2021-05-17 15:12:07 +02:00
Dan Kortschak
0ba64fc318 interp: add example to show use of Self
This example clarifies how `interp.Self` can be accessed.

Please take a look.
2021-05-10 14:06:09 +02:00
Marc Vertes
d16bd4bcdb interp: fix package name extraction from import path
The heuristic to generate a package name identifier was incorrect. Now for binary packages, the package identifier is obtained by a symbol, generated by extract, which contains the string argument of package statement in source file. This should ensure an always correct default package identifier. 

Fixes #1095.
2021-05-10 11:20:07 +02:00
Marc Vertes
33a532ee01 interp: fix a bug when assigning to an empty interface
The concrete type was not forwarded propertly in case of a binary
expression involving a valueT. The corresponding part in type.go
has been refactored and the now the multi-assign case should be
handled as well.

Fixes #1094.
2021-05-07 16:30:09 +02:00
Marc Vertes
cdc6b773c2 interp: add ImportUsed method to pre-import compiled packages
This feature was already present, but part of REPL only.
It's now also possible to apply it when evaluating a string
(-e flag). Default package names collision handling is no
longer hard-coded.

With -e flag, the eval result is now printed if valid, allowing
simpler commands:

     yaegi -e 'reflect.TypeOf(fmt.Printf)'

instead of:

     yaegi -e 'println(reflect.TypeOf(fmt.Printf))'

Fixes #1084.
2021-04-30 11:36:05 +02:00
Marc Vertes
17d5f1814a interp: fix support of interpreted functions in map values
Interpreted functions were represented in an inconsistent way in the frame: as a node pointer by default, and wrapped in a function wrapper for maps. 

We now simply use the default (*node) representation, as elsewhere, so values can be assigned, passed and called as for the other types. The alternative (generating a function wrapper) is more complex, costly and reserved for cases where the interpreted function can be called from the runtime.

Test that a map of functions can store both binary functions from used packages and interpreted ones.

Fixes #1090.
2021-04-30 11:26:04 +02:00
Marc Vertes
5f8be70066 interp: fix type string extraction for wrapped constants
Fixes #1089.
2021-04-29 18:08:03 +02:00
Marc Vertes
5530eca17d interp: give a self to the interpreter
The interpreter is exposed to itself through a "Self" var which
is set on "Use" of the interpreter package.

It allows meta-programming features, for example using "Eval" in
the current interpreter context, or enabling self-inspection
capabilities.
2021-04-21 16:26:03 +02:00
Marc Vertes
c8d9e25085 stdlib: add wrapper for testing/fstest package in go1.16 2021-04-19 09:38:03 +02:00
Marc Vertes
a241119bf7 interp: improve handling of aliased types
Avoid to test directly for a type category, as it may give wrong
results for aliased types, where the interesting category remains
masked.  Instead, use some property helpers, such as isFuncSrc,
isPtrSrc and isInterfaceSrc to check if a type is of source function,
source pointer or source interface respectively (versus runtime
defined function, pointer or interface).

Fixes #1068.
2021-04-14 17:52:04 +02:00
Marc Vertes
3e3f8d5c2f interp: implement unsafe.Offsetof
Offsetof returns the offset of a field in a struct. It is computed
during parsing at CFG, due to the constraint of operating on a
struct selector expression.

With this function, the support of 'unsafe' package is now
complete in yaegi.

Fixes #1062.
2021-04-14 14:28:03 +02:00
Marc Vertes
9aeb78fc36 interp: fix method lookup for aliased types
Fixes #1058.
2021-04-13 18:10:04 +02:00
Marc Vertes
7863456d52 interp: refactor slice type management
Add missing `sliceT` type category for consistency. Remove
`sizedef` field in `itype` struct. Rename field `size` to `length`.
Clean the various hacks used to cope with the absence of `sliceT`.
2021-04-13 18:00:12 +02:00
Ethan Reesor
428b658160 Allow colon-equal to override variable type
If I execute the following:

```
I := interp.New(interp.Options{})
I.Eval(`x := 1`)
I.Eval(`x := "foobar"`)
```

I expect the second declaration to override the first. `var x string` will override the previous type, and redeclaring a type, function, const, etc will override it, but the `:=` operator will not.

Currently, the result is: `reflect.Set: value of type string is not assignable to type int`
2021-04-02 09:08:04 +02:00
Ludovic Fernandez
350cf80bbf chore: restore macos env in GitHub Actions. 2021-04-02 08:48:04 +02:00
Ethan Reesor
d92051d40f interp: treat var declaration within a block as a define statement
This PR:

- Treats a `varDecl` within a block as a `defineStmt`
  - More specifically, any `varDecl` with a grandparent that is *not* a `fileStmt`
- Adds an extra condition to the handler for implicit const assignment
- Adds a tests to cover the changes
- Closes #1071
2021-04-01 15:22:03 +02:00
Marc Vertes
aa2621f6c6 interp: fix a panic when embedding an error interface
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.
2021-04-01 10:38:05 +02:00
Marc Vertes
2b1d6f0e7a interp: fix append on variadic recursive struct
Fixes #1065. Improves #1058.
2021-03-26 09:34:03 +01:00
Ethan Reesor
992676722d interp: allow redeclaration of imports
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.
2021-03-25 23:34:03 +01:00
エガオノキミヘ
451c754068 extract: process interface wrapper method with variadic parameter
Fixes #1055
2021-03-24 11:48:03 +01:00
エガオノキミヘ
84ad46751a fix #1056, extract: replace the code for get package name.
fix #1056
2021-03-23 10:30:04 +01:00
Marc Vertes
ec5392d566 interp: do not skip use of tmp frame in multi-assign
Fixes #1052.
2021-03-19 11:24:04 +01: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
Marc Vertes
fdfcb9c1df interp: do not check properties of incomplete types
Fixes #1042.
2021-03-09 11:58:04 +01:00
Marc Vertes
a988459dcd interp: fix a memory management issue causing wrong closure context
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.
2021-03-09 09:30:04 +01:00
Sylvain Muller
51e0b46256 Use fmt.Fprintln instead of fmt.Println in runCfg
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.
2021-02-20 12:08:03 +01:00
Chris Waldon
eb06aeeb26 fix: use portable path manipulation for choosing package names
This *should* fix the generated names of packages on windows, which currently take the form `C:\kdfjslfj\jkfsjldkfjsf\sjdkfldjf` (this was reported to me by someone attempting to generate yaegi symbols for one of my projects). That being said, I don't have a windows machine to test on.
2021-02-17 10:12:08 +01:00
Ludovic Fernandez
8bb5daf60e feat: update stdlib mapping for go1.16
- drop stdlib for go1.14
- generate stdlib for go1.16
-  update CI configuration.
2021-02-17 10:02:03 +01:00
Marc Vertes
ac80d1b3ed interp: fix setting interface objects from operators
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.
2021-02-08 18:00: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
3f4e1665b1 interp: fix default type for constants from runtime
The default type must be derived from the constant value when necessary,
otherwise the type check fails wrongly.

Fixes #1026.
2021-02-03 11:48:03 +01:00
Marc Vertes
b9b0897d95 interp: fix nil value check in case of interface
A wrong logic was leading to panic in recover. Simplify the
workflow for clarity.

Fixes #1022.
2021-02-02 13:28:04 +01:00
mpl
6337f8bc01 interp: clarify error about GOPATH probably not set 2021-02-02 10:10:03 +01:00
Ludovic Fernandez
ccb8072759 chore: use GitHub Actions.
- use GitHub Actions instead of TravisCI
- updates golangci-lint to v1.36.0 and applies my rules
2021-02-01 12:23:29 +01:00
Nicholas Wiersma
d73111cda1 fix: untyped check
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
2021-01-28 16:20:04 +01:00
Nicholas Wiersma
ff521ecb1a fix: handle function references in composite bin map
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
2021-01-28 15:42:03 +01:00
Marc Vertes
61b4980077 interp: do not panic in case of invalid constant definition
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.
2021-01-27 12:58:03 +01:00
Marc Vertes
100d090853 interp: fix sending object implementing an interface through channel
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.
2021-01-26 18:58:04 +01:00
Marc Vertes
bd60de5995 interp: allow early constant evaluation from builtin call
One builtin has been identified to be used for constant definition:
len(), with a constant string argument. Add support for this.

Fixes #1012.
2021-01-26 11:12:04 +01:00
Marc Vertes
274eecdf18 interp: fix type recursivity detection
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.
2021-01-19 19:32:05 +01:00
Marc Vertes
8fa00f826c interp: fix map assignment from arithmetic operations
The logic to trigger assigment optimizations has been refactored for
clarity, and to exclude assignments to map entries.

Fixes #981.
2021-01-18 19:04:05 +01:00
Marc Vertes
a64fe5b210 interp: fix detection of type recursivity
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.
2021-01-15 12:14:04 +01:00
Marc Vertes
5c59dc425f interp: fix operators working on integer constants
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
2021-01-14 17:26:06 +01:00
Marc Vertes
8ad14d8ea4 interp: handle aliased string used as a slice
Fixes #1002.
2021-01-14 16:48:06 +01:00
Marc Vertes
8a1f9ef44e interp: parse circular interface definitions
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).
2021-01-14 15:46:04 +01:00
Marc Vertes
5cd1e11379 chore: rename github to tap, following goreleaser deprecation notice
The release of v0.9.9 failed, due to
https://goreleaser.com/deprecations/#brewsgithub.
2021-01-06 09:14: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
a83f492309 interp: add support for binary composite slice
Fixes #987.
2020-12-15 18:20:04 +01:00
mpl
02c30482cc interp: enable type assertion from empty interface into slice
Fixes #985
2020-12-15 17:28:04 +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
662838fd80 interp: fix and refactor typeAssertStatus in
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.
2020-12-07 15:58:04 +01:00
Marc Vertes
92d65c22f0 interp: remove incorrect type check on array object
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.
2020-12-02 17:26:03 +01:00
mpl
2db4579b6f interp: fix short-form type assertions
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
2020-12-02 14:46:03 +01:00
mpl
101633c380 interp: support two more type assertion cases
Fixes #967
2020-12-01 15:50:04 +01:00
mpl
1e0f6ece6e interp: support more type assertion cases
Fixes #955
2020-11-30 18:00:04 +01:00
Marc Vertes
662d2a6afe interp: fix parsing of assign to dereferenced pointer
Fixes #969.
2020-11-30 17:46:05 +01:00
Marc Vertes
b25ee3f809 interp: fix method lookup on aliased types
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.
2020-11-30 15:44:04 +01:00
Marc Vertes
81e1e5f206 interp: handle getting address of interpreter interface value
Fixes #963.
2020-11-30 11:48:04 +01:00
Marc Vertes
81d8339132 test: chdir to package directory prior to launch tests
Because this is what `go test` does, and some packages depend on that,
for example `github.com/jjcollinge/servicefabric`.
2020-11-25 16:10:04 +01:00
Marc Vertes
d494f9e420 interp: support calling goto from sub-scope
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.
2020-11-19 12:48:03 +01:00
Marc Vertes
6da1107c39 fix: do not confuse function call with type conversion
Use node action to better discriminate between function call and type
conversion which have the same pattern at AST level.

Fixes #960.
2020-11-18 14:56:05 +01:00
Marc Vertes
38a7331bf9 interp: fix type check on function signature
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.
2020-11-13 18:02:04 +01:00
Marc Vertes
13783889cb interp: avoid useless interface wrapping
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`.
2020-11-12 10:48:04 +01:00
mpl
ed626f3fb9 interp: support conversion of runtime func into interp func
Conversion of interp func into runtime func already worked, but added a
test anyway to watch out for regressions.

Fixes #941
2020-11-10 00:40: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
83676577ac fix: use the import path for types
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
2020-11-05 13:42:03 +01:00
mpl
f0fc907269 extract: support building/running yaegi with Go devel
Fixes #928
2020-11-05 11:40:04 +01:00
Marc Vertes
61f4704925 interp: fix CFG in case of for loop with empty init and cond
Refactor `for` variants for clarity. Ensure all possible 8 combinations
are covered.

Fixes #942.
2020-11-05 11:00:04 +01:00
Marc Vertes
b1ccfbf47f interp: apply type conversion on untyped variable at run
Fixes #938.
2020-11-04 18:16:04 +01:00
Marc Vertes
0ed4b362dc interp: implement conversion for interpreter function types
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.
2020-11-03 17:48:03 +01:00
Marc Vertes
98807387a4 interp: resolve type for untyped shift expressions
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.
2020-11-02 18:08:04 +01:00
Marc Vertes
c817823ba1 interp: fix incorrect infinite loop on for statement
Add a for statement variant for the case of a "for" with an init, no
condition and no post-increment.

Fixes #933.
2020-11-02 17:52:03 +01:00
mpl
3cb8bca81a interp: on panic, look for node where offending exec originated from
The execution flow is such that a node can end up running several chained exec
funcs, some of which actually originate from other nodes. For example, in:

var m []int // L0
println("hello world") // L1
m[0] = 1 // L2

the offending code is on a node on line 2 (out of range error). However, since
the assignment to m is part of the execution flow of the variable m, we'll get
the panic when running all the chained exec funcs attached to the node for m on
line 0.

Which is why, when that happens, we need to look for the actual node (the one on
L2) where the offending instruction originates from, in order to
properly report the origin of the panic.

Fixes #546
2020-11-02 10:26:04 +01:00
Marc Vertes
a38d19288f interp: fix testing for nil interface values
Fixes #924.
2020-10-30 16:20:04 +01:00
Marc Vertes
7f8ffa6719 interp: handle explicit nil values in literal composite values
Fixes #922.
2020-10-27 11:24:04 +01:00
Marc Vertes
513f5e37aa interp: fix type conversion for constant expressions
The case of a constant arithmetic expression being of float kind because
of quotient was not handled correctly. Simplify constant extraction to
reflect.Value first, then conversion to target type, and let reflect Convert
method panic if conversion is not valid.

Fixes #920.
2020-10-23 10:44:04 +02:00
Marc Vertes
9520a92241 interp: fix type in assign of shift operations
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.
2020-10-23 10:32:03 +02:00
rsteube
d47821bfaa interp: add indexExpr check for reflect.Array
In typecheck.go, type check was failing for expressions like `[2]int{0, 1}[0:]`.
```
cannot slice type [2]int
```

Fixes #914 .
2020-10-21 23:00:04 +02:00
rsteube
d7ede8ed5c interp: added sliceExpr and starExpr
Type check was failing for expression such as: `&(*tree)[node:][0]`, as in

```go
tree, _ := huffmanTreePool.Get().(*[]huffmanTree)
...

initHuffmanTree(&(*tree)[node:][0], histogram[l], -1, int16(l))
```

see c3da72aa01/brotli_bit_stream.go (L469)
2020-10-21 18:14:03 +02:00
Marc Vertes
22c63b225c interp: fix array size definition in case of forward declared constant
In type.go, the symbol lookup on constant id was not performed. Handle
the ident kind explicitely to allow that.

Fixes #911.
2020-10-21 13:08:03 +02:00
mpl
c0eaab0891 interp: fix assignable check
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.
2020-10-21 10:06:03 +02:00
rsteube
c74d050c5a interp: added kind to log for typecheck (#910) 2020-10-21 09:46:05 +02:00
Marc Vertes
804664c631 interp: fix type check in constant unary operations
In unary constant operations, the test for unsigned was defeated by
testing for int first, which is true also for unsigned. Make sure that
testing for unsigned precedes testing for int.

Fixes #907.
2020-10-19 10:32:03 +02:00
Kamil Samigullin
f6d8261a8a chore: add homebrew-tap recipe
Publish homebrew-tap recipe to https://github.com/traefik/homebrew-tap
2020-10-17 05:54:04 +02:00
Marc Vertes
68c02ce054 feature: expose extract package, previously internal 2020-10-15 18:58:03 +02:00
Marc Vertes
4b3e9ee231 feature: use environment in addition to flags to control test options
This applies to -syscall, -unsafe and -unrestricted flags with the
corresponding env variables YAEGI_SYSCALL, YAEGI_UNSAFE and
YAEGI_UNRESTRICTED, already used in the same way for the run
sub-command.
2020-10-15 18:42:04 +02:00
mpl
8916618a81 interp: API change for Symbols method
Often enough when debugging, one does not know exactly what argument
should be given to Symbols, as it's not always clear in which
scope/namespace the symbol one is looking for is stored in.

Therefore, this change enables the Symbols method to now take the empty
string as an argument, which results in all the known symbols to be
returned (keyed by import path).

As a consequence, when an non-empty argument is given, the returned
result should be similar to what we had before, except it is now
returned as the sole entry of an encompassing map.

In addition, the "binary" symbols (i.e. the ones ingested through a
Use call), are now also taken into account.
2020-10-15 10:02:04 +02:00
mpl
57b49f40d6 interp: make Symbols method take into account type objects too 2020-10-14 17:44:09 +02:00
Marc Vertes
190dade469 fix: detect a wrong number of arguments at return
Also fix error ouptut in the run command to avoid displaying twice
the same error.

Fixes #819.
2020-10-14 17:30:04 +02:00
Marc Vertes
6b652ea485 feature: provide a version sub-command
A version sub-command is implemented.
A local install target is added to Makefile, to set version from git at build.

Fixes #840.
2020-10-14 16:24:05 +02:00
Marc Vertes
473bc63588 fix: behavior of select and time ticker
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.
2020-10-14 15:50:04 +02:00
Marc Vertes
e32da38ad0 fix: append from / to runtime defined array
Check first for runtime defined array (typ.cat of valueT)
to avoid checking inexisting properties (an panic), when
deciding to use appendSlice or not.

Fixes #880.
2020-10-13 17:14:04 +02:00
Marc Vertes
b2b519c2fd fix: correctly return constant expressions in functions
In the case of a function returning a single value, a constant
result could be ignored, and the function would return a zero value.

Fixes #889.
2020-10-13 17:02:04 +02:00
Marc Vertes
9491e58920 fix: correct handling of select comm clause with empty body
Fixes #887.
2020-10-13 11:24:04 +02:00
Marc Vertes
f362237ac5 fix: perform constant type conversion when required
Fixes #893.
2020-10-12 19:06:03 +02:00
Marc Vertes
a83ec1f925 fix: allow yaegi command to interpret itself
Since the introduction of restricted stdlib and syscall symbols, the
capability of yaegi to interpret itself was broken.
The use of unrestricted symbols is now also controlled by environment
variables, to allow propagation accross nested interpreters.
The interpreter Panic symbol was not wrapped, this is fixed now.
the import path resolution was failing if the working directory was
outside of GOPATH.
The documentation and readme have been ajusted.

Fixes #890.
2020-10-09 11:48:04 +02:00
mpl
155ca4e6ad interp: support implicit-type slice of pointers of struct composite literal
Also fix same case for implicit-type maps of etc.

Fixes #883
2020-10-09 10:32:03 +02:00
mpl
ca196a5768 interp: fix implicit type for bin composite lit case
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
2020-10-05 16:42:03 +02:00
Marc Vertes
b78d55c66b fix: compute array type size from constant expression
Fixes #875.
2020-10-05 16:12:04 +02:00
mpl
16f5586a11 interp: apply integer division when appropriate
When working with an untyped const expression involving a division, if
the default type of the result should be an int (for example because the
default types of all the operands are ints as well), then we should make
sure that the operation that is applied is indeed an integer division,
and that the type of the result is not a float.

This is achieved by using the QUO_ASSIGN operator, instead of the QUO
operator.

This should fix several problems lurking around, and it notably fixes
one of the visible consequences, which is a systematic panic when using
the REPL as a "calculator".

This incidentally also allows us to revert what was done in
5dfc3b86dc since it now turns out it was
just a hack to fix one of the symptoms.

Fixes #864
2020-10-05 10:50:03 +02:00
Julien Breux
c3cf301c60 fix: replace playground link in docs 2020-09-30 10:26:03 +02:00
Marc Vertes
0dde990d0b feature: improve extract, add unrestricted syscalls 2020-09-29 18:42:05 +02:00
Marc Vertes
4cfeb1946e fix: concurrent eval test 2020-09-29 15:22:04 +02:00
Nicholas Wiersma
ec64b006cf fix: convert struct tags properly 2020-09-29 09:22:04 +02:00
Nicholas Wiersma
f36d4e01eb fix: yaegi os.Args should contain the script name 2020-09-28 10:54:05 +02:00
mpl
5dfc3b86dc interp: fix division for const 2020-09-28 10:42:05 +02:00
mpl
3ae01a2af3 interp: refactor doComposite cases 2020-09-22 17:26:03 +02:00
Marc Vertes
c06f83f34a fix: correct access to parameter type for variadic binary methods 2020-09-22 15:18:03 +02:00
Ludovic Fernandez
a6d9c84a30 chore: adds a downloader script. 2020-09-20 18:26:03 +02:00
Marc Vertes
6346d11286 chore: move to new organization 2020-09-16 10:58:04 +02:00
Marc Vertes
1edb6a1424 fix: native build of syscalls on android and illumos
As per https://golang.org/cmd/go/#hdr-Build_constraints,
using GOOS=android also matches tags and files for GOOS=linux,
so exclude it explicetly to avoid collisions.

Also using GOOS=illumos matches tags and files for GOOS=solaris.

Fixes #843.
2020-09-14 17:48:05 +02:00
mpl
a2f56431ea interp: fix data race for composite literal creation
This change fixes two data races related to composite literal creation.

The first one isn't controversial as it is just about initializing the
variable that contains the values in the right place, i.e. within the
n.exec, so that this variable is local to each potential goroutine,
instead of being racily shared by all goroutines.

The second one is more worrying, i.e. having to protect the node typ
with a mutex, because a call to func (t *itype) refType actually
modifies the itype itself, which means it is not concurrent safe.
The change seems to work, and does not seem to introduce regression, but
it is still a concern as it probably is a sign that more similar
guarding has to be done in several other places.
2020-09-14 16:22:04 +02:00
Marc Vertes
42abedb25d fix: keep atomic counter aligned on 64 bits boundary
Fixes #845.
2020-09-14 15:32:03 +02:00
Marc Vertes
151699ef9f feature: test subcommand to run test and benchmark functions
This change allows the interpreter to execute tests and benchmarks
functions provided by packages.

The test subcommand is similar to the "go test" command and
all the relevant flags have been kept.

The ability to evaluate a directory or a package has also been added.

A new method Symbol to access exported symbol values of an interpreted
package has been added. This method is used by the test subcommand.

An EvalTest method has been added to evaluate all Go files, including "*_test.go".

The testing packages from the standard library have been added to stdlib used
symbols.
2020-09-14 11:14:04 +02:00
Marc Vertes
f1f3ca7e06 fix: handle interface fields in literal composite structs
Struct fields of type interface must be converted in wrapper
values to be reachable by the runtime. Call genInterfaceWrapper
on such values.

Fixes #832.
2020-09-09 13:44:04 +02:00
Marc Vertes
9ddecfa121 fix: correct index for embedded binary method receiver
When searching for a binary method on structures, look up on embedded
fields first, otherwise the resulting index is incorrect, as
reflect.Type.MethodByName succeeds also on container struct.

Fixes #834.
2020-09-09 12:22:03 +02:00
mpl
04770a4b81 interp: fix data races (#839)
This change fixes two distinct data races:

1) some global vars of type *itype of the interp package are actually
mutated during the lifecycle of an Interpreter. Even worse: if more than
one Interpreter instance are created and used at a given time, they are
actually racing each other for these global vars.
Therefore, this change replaces these global vars with generator
functions that create the needed type on the fly.

2) the symbols given as argument of Interpreter.Use were directly copied
as reference (since they're maps) when mapped inside an Interpreter
instance. Since the usual case is to give the symbols from the stdlib
package, it means when the interpreter mutates its own symbols in
fixStdio, it would actually mutate the corresponding global vars of the
stdlib package. Again, this is at least racy as soon as several
instances of an Intepreter are concurrently running.
This change fixes the race by making sure Interpreter.Use actually
copies the symbol values instead of copying the references.
2020-09-09 11:59:07 +02:00
Marc Vertes
341c69d922 feat: configure stdin, stdout and stderr per interpreter
The goal is to provide greater control of input, output and error
streams of the interpreter. It is now possible to specify those
as options when creating a new interpreter. The provided values
are propagated to relevant stdlib symbols (i.e fmt.Print, etc).
Care is taken to not update the global variables os.Stdout, os.Stdin
and os.Stderr, as to not interfere with the host process.

The REPL function is now simplified. The deprecated version is removed.

The tests are updated to take advantage of the simplified access
to the interpreter output and errors.

Fixes #752.
2020-08-31 15:42:03 +02:00
mpl
f4cc059e3e TestEvalScanner: "fix" data race
When running TestEvalScanner with -race=true, one can observe a data race such as:

```
WARNING: DATA RACE
Read at 0x0000029f3d68 by goroutine 52:
  github.com/containous/yaegi/interp.(*itype).defaultType()
      /Users/mpl/src/github.com/containous/yaegi/interp/type.go:1466 +0x572
...
  github.com/containous/yaegi/interp.(*Interpreter).EvalWithContext.func1()
      /Users/mpl/src/github.com/containous/yaegi/interp/interp.go:501 +0xf0

Previous write at 0x0000029f3d68 by goroutine 43:
  github.com/containous/yaegi/interp.(*itype).refType()
      /Users/mpl/src/github.com/containous/yaegi/interp/type.go:1419 +0x854
  github.com/containous/yaegi/interp.(*itype).TypeOf()
      /Users/mpl/src/github.com/containous/yaegi/interp/type.go:1427 +0xa6
...
  github.com/containous/yaegi/interp.(*Interpreter).EvalWithContext.func1()
      /Users/mpl/src/github.com/containous/yaegi/interp/interp.go:501 +0xf0
```

Before this change, since closing the pipe to the REPL is done in a defer, it
means that all the i.REPL calls (and hence each goroutine for each of these
calls) are kept running and alive until the very end of the test. It should not
matter, since a new interpreter is created for each test case, and thus all the
i.REPL calls should be completely independent from each other.

And yet, by wrapping each test case in a function call, and thus making each
i.REPL call terminate as soon as the test case is over, the data race seems to
be fixed. This could suggest that the separate i.REPL calls from separate
interpreter instances are somehow sharing some memory, but I do not know how to
explain that.

The problem has yet to be fully understood, but at least this change restores
the test, without making the CI fail again.
2020-08-31 12:46:03 +02:00
mpl
535e7e1c42 interp: enable declaration errors detection at parsing time
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
2020-08-28 14:36:00 +02:00
mpl
cb0f3a77bb REPL: retry with full wrapping for anonymous func calls
In interactive mode, a line starting with the "func" keyword is usually
"wrapped", by prepending to it a "package main" statement, to make it
a valid piece of Go source code.

However, when the line is actually an anonymous function call, such as:

func() { println(3) }()

then this wrapping is not enough, as this is not valid Go in the global
context. Therefore, this kind of of expression must also be wrapped
inside a main func (as is the default case for most REPL inputs).

Since the detection and handling of such a case turned out to be quite
unelegant, this PR instead introduces a retrying phase when a parsing
error occurs for a particular class of cases. That is to say, when a
"func expression" wrapped in a main package fails to be parsed, it is
then wrapped in a main func before parsing is retried.

N.B. TestEvalScanner has been disabled for this change, because the additional test cases revealed a (most-likely already existing) data race.

Fixes #721
2020-08-28 10:28:15 +02:00
Marc Vertes
b1279d0a21 feature: improve handling of interrupt signal in REPL
The input scanning is now performed in a sub goroutine and
the interrupt is listened in another goroutine, either to cancel Eval
or to cancel the current line scan.
Entering a '\n' after a 'Ctrl-C` to get the prompt is
not necessary anymore.
2020-08-27 15:04:04 +02:00
Nicholas Wiersma
f3f9ffaea7 feat: add builtin type checking
This adds type checking for builtin functions. It also refactors builtin names into constants due to the number of times they are used.
2020-08-27 14:02:04 +02:00
Nicholas Wiersma
e332a6b3be fix: check array size symbol kind
When determining the size of an array and a symbol is found, the symbol must be a const for the type to be valid. 

While it makes sense for this check to be done in type checking, the type can be determined by GTA which would then fail. For now this check is done when getting the node type.

Fixes #825
2020-08-27 11:52:04 +02:00
Nicholas Wiersma
358a57b4b9 feat: add star expression type checking
This adds type checking to StarExpr. This also fixes a bug in assignment where the symbol type was updated but not the scope type associated with it.
2020-08-21 10:56:03 +02:00
Nicholas Wiersma
3640f2f820 feat: add type assertion expression type checking
This adds type checking to TypeAssertExpr. In order to allow for this, method types now have a receiver type in both reflect and native cases.
2020-08-20 17:06:05 +02:00
mpl
3faa47c61e interp: take into account embedded property of struct field
The trick is that in reflect, the field is called Anonymous, which is
actually a different notion in the Go spec/vocable.

n.b. only works for non-recursive types for now.

Fixes #781
2020-08-20 14:51:14 +02:00
mpl
896bfeb5a1 interp: new EvalPath API
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 #731
Fixes #778
Fixes #798
Fixes #789 

Co-authored-by: Marc Vertes <mvertes@free.fr>
2020-08-20 13:14:15 +02:00
Nicholas Wiersma
1029d102e5 feat: add slice expression type checking
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.
2020-08-19 16:04:05 +02:00
Marc Vertes
065d4fa4d7 fix: add mutual exclusion locks for cancelable select
In a couple of occurences, tests with enabled race detector exposed
some concurrent accesses to the cancelation callback used in select and
channel operations send and recv for EvalWithContext. This change ensure
that all accesses to this object are protected by mutex.

Fixes #815.
2020-08-19 13:52:04 +02:00
mpl
332becf95d interp: more tests for ignoreScannerError
They cover the extra cases that were "sneakily" added
after 611a8c37fa
2020-08-14 15:04:11 +02:00
Nicholas Wiersma
da9e6a0d6c fix: composite literal type check
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.
2020-08-14 12:14:03 +02: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
Ludovic Fernandez
a004809fc2 fix: main command for goreleaser. 2020-08-13 14:22:03 +02:00
Marc Vertes
b0cd93a936 fix: correct interrupt signal handling in REPL
Avoid goroutines leak, accumulation of defered functions and
spurious resets of signal handlers. Effectively catch interrupt
signal (Ctrl-C) to cancel current eval.

Fixes #713.
2020-08-12 22:22:03 +02:00
mpl
611a8c37fa interp: make REPL stricter about parsing errors
So far the REPL loop was treating any parsing error coming from
go/parser to generate the AST, as having occurred because the source
code was not yet complete (unfinished block). And it was therefore
ignoring all of them.

However, some of these errors are legitimate, and must be caught as soon
as they occur, otherwise the REPL cycle would stay in an errored state
forever (even when the block terminates), without the user getting any
feedback about it.

Therefore, this change adds an extra check when a parsing error occurs,
i.e. it verifies that it looks like an "EOF" error (unfinished block)
before it ignores it (as the user is supposed to terminate the block
eventually). Otherwise the error is treated just like a "non-parsing"
(cfg, gta, ...) error and printed out.

Fixes #637
2020-08-12 18:44:21 +02:00
Marc Vertes
e71ddc7edd chore: update golangci-lint config (#810)
Disable nlreturn. Fix one comment.
2020-08-12 17:46:28 +02:00
Ludovic Fernandez
1fe75f149d feat: update stdlib mapping for go1.15
- drop stdlib for go1.13
- generate stdlib for go1.15
-  update CI configuration.
2020-08-12 12:38: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
Nicholas Wiersma
88569f5df7 fix: interface call regression from #787
Fix #787 changes how interfaces are set on a struct (compositeSparce). This change however makes calling the interface panic. 

This PR reverts part of the change in #787 and adds a test to ensure it does not break again.
2020-08-10 16:32:05 +02:00
Marc Vertes
2ac0c6f70b feature: command line provide sub-commands
The Yaegi command line has been changed to provide subcommands.

The following sub-commands are provided:
- extract (formerly goexports)
- help
- run
- test

The previous behaviour is now implemented in run command which
is the default, so the change should be transparent.

In run command, prepare the ability to run a package or a directory
in addition to a file. Not implemented yet

The test command is not implemented yet.

The extract command is meant to generate wrappers to non stdlib
packages.

Fixes #639
2020-08-10 16:20:05 +02:00
Nicholas Wiersma
bd4ce37baa feat: refactor type checking
The previous type checking was off and did not do untyped type conversion. This endeavours to fix this with better type checking in its own type.
2020-07-31 14:00:03 +02:00
Nicholas Wiersma
9c4d3d1e5a chore: updated linter 2020-07-30 11:18: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
Marc Vertes
589b2a0cd2 fix: correct conversion to int in slice index expressions. 2020-07-23 12:05:03 +02:00
Marc Vertes
68911f8b4e fix: type assertion expression was not forwarding type
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.
2020-07-23 11:51:53 +02:00
mpl
e5a7b0de11 extract: new package to extract symbols from a dependency
cmd/goexports is now based on it.

Updates #639 

Co-authored-by: Marc Vertes <mvertes@free.fr>
2020-07-23 10:58:33 +02:00
mpl
563270ca02 interp: support yet another vendoring case
* interp: support another vendoring case

Namely, when the vendor dir is a sibling (or an uncle) relative to the
current pkg

Fixes #758

* make linter happier

* address review comments

* fix, cleanup, add unit tests

* add dummy files to force dirs into git
2020-07-15 15:35:04 +02:00
Marc Vertes
5eecbe515b fix: compositeSparse handles fields of interface kind
Fixes #776.
2020-07-13 17:55:04 +02:00
Marc Vertes
0a79069dfc fix: correct control flow graph for range init expression
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.
2020-07-13 15:35:04 +02:00
Marc Vertes
0c8f538cd9 fix: apply method receiver offset when generating interface wrapper
Fixes #772.
2020-07-12 14:20:03 +02:00
Nicholas Wiersma
ca80ada849 fix: deal with untyped in type check 2020-07-10 11:55:04 +02:00
Nicholas Wiersma
3c6df504df fix: dont allow calling init 2020-07-09 14:35:04 +02:00
Nicholas Wiersma
98eacf3610 fix: execute global variables in the correct order
* 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
2020-07-09 14:05:03 +02:00
Marc Vertes
16ff52a949 fix: avoid a panic in CFG in case of incomplete type
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.
2020-07-09 13:05:04 +02:00
Marc Vertes
640d1429e5 fix: type assert when status is _
If the status is _, there is no storage allocated in frame, and
the status assign operation should be skipped.

Fixes #761.
2020-07-09 08:45:03 +02:00
Nicholas Wiersma
659913eebe fix: convert type properly to the correct type 2020-07-08 22:55:03 +02:00
Marc Vertes
b3766509cc feature: restrict symbols which can exit the interpreter process
* feature: restrict symbols which can exit the interpreter process

Some symbols such as os.Exit or log.Fatal, which make the current process
to exit, are now restricted. They are replaced by a version which panics
instead of exiting, as panics are recovered by Eval.

The restricted os.FindProcess version is identical to the original
except it errors when trying to return the self process, in order to
forbid killing or signaling the interpreter process from script.

The os/exec symbols are available only through unrestricted package.

The original symbols are stored in an unrestricted package, which
requires an explicit Use, as for unsafe and syscall packages.

The Use() interpreter method has been slightly modified to allow inplace
updating of package symbols, allowing to replace some symbols but not
the entire imported package.

A command line option -unrestricted has been added to yaegi CLI to use
the unrestricted symbols.

Fixes #486.

* fix: lint
2020-07-08 22:35:04 +02:00
Nicholas Wiersma
bc2b224bae fix: make a copy of defined before detecting recursivness 2020-07-07 12:05:03 +02:00
Nicholas Wiersma
9d4685deea fix: handle interfaces in composite sparce (#749)
Co-authored-by: Marc Vertes <mvertes@free.fr>
2020-07-06 15:41:27 +02:00
Marc Vertes
2a70a71dc2 fix: avoid infinite loop when parsing recursive types
Mark all visited types as such when walking down struct fields.

Fixes #750.
Updates #652.
2020-07-06 15:30:04 +02:00
Nicholas Wiersma
851444453c fix: assert switch type from valueT in struct case (#747)
* 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
2020-07-06 15:09:48 +02:00
Nicholas Wiersma
a8b1c2a017 fix: a const, non-const equality check must convert 2020-07-06 11:25:03 +02:00
Nicholas Wiersma
d229c2a2c7 fix: handle Func Value in genFunctionWrapper params
* fix: handle Func value in func wrapper params

* fix: lint
2020-07-03 12:25:04 +02:00
Marc Vertes
2f2df7a0f8 fix: avoid memory errors by handling frame indirections (#739)
In all situations where the results are set directly
to the frame, and not using a value helper, the right level of
indirections must be applied, otherwise we may end-up writing
in the wrong frame (the local one, instead of a caller or global).

Fixes #735.
2020-07-03 11:02:46 +02:00
Nicholas Wiersma
4058fd8c44 fix: do type check on assignment (#738)
* fix: do type check on assignment

* fix: check for recursive type rather than field
2020-07-03 10:28:51 +02:00
Nicholas Wiersma
097a745e72 fix: variadic interface conversion in call/callBin 2020-07-02 23:55:03 +02:00
Nicholas Wiersma
1f514e63a8 fix: switch always compare like types 2020-07-02 23:35:03 +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
d4aa84f729 fix: set frame level in destination nodes to avoid memory corruption (#733)
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.
2020-07-02 10:03:32 +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
39430c34bb fix: untyped constant converson to default type (#729)
* 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
2020-07-01 14:39:47 +02:00
mpl
4f3481b55c interp: support another vendoring case 2020-07-01 10:44:03 +02:00
Marc Vertes
55f2fe396a fix: goexports skisp unimplemented solaris Syscall6 (#726)
The standard library syscall package for Solaris defines unimplemented
symbols Syscall6 and RawSyscall6 which makes the build fails on
Solaris platform, now that yaegi command imports syscall symbols.

As the standard library package is locked down, this will remain
unchanged. We just skip those symbols.

Fixes #725.
2020-06-30 22:50:44 +02:00
Marc Vertes
108b6fd722 feature: add -syscall option to enable use of syscall symbols (#723) 2020-06-29 14:43:43 +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
d2c4a36c25 fix: dont optimize map index assigns 2020-06-29 09:40:03 +02:00
Nicholas Wiersma
f5f44f7ddd fix: rework compatibility and ordering checks 2020-06-25 09:44:04 +02:00
Nicholas Wiersma
4d013e4686 fix: handle defer in builtins 2020-06-25 09:28:03 +02:00
Julien Levesy
c11d361953 Handle Receive and Send channels 2020-06-23 09:04:04 +02:00
Nicholas Wiersma
c2ad279643 fix: use pragma for ptr checks 2020-06-22 16:40:03 +02:00
Nicholas Wiersma
9627782394 feature: add Sizeof and Alignof to unsafe 2020-06-22 15:24:04 +02:00
Nicholas Wiersma
e00b853971 fix: make reftype func variadic 2020-06-22 13:38:04 +02:00
mpl
7cfa264dbc interp: force root scope for binPkgT selector 2020-06-22 13:24:03 +02:00
Ludovic Fernandez
a6c24a0d13 chore: update linter. (#706)
* chore: update linter.

* chore: remove not needed travis env var.
2020-06-22 12:55:42 +02:00
Nicholas Wiersma
f19b7563ea feature: unsafe type conversion 2020-06-18 18:14:03 +02:00
Nicholas Wiersma
0643762852 fix: allow uint in make len and cap 2020-06-18 15:18:04 +02:00
mpl
7323d97023 interp: global scope redeclaration detection 2020-06-18 15:08:04 +02:00
Julien Levesy
6486909921 fix: range over channels returned by binary calls 2020-06-18 14:22:03 +02:00
Nicholas Wiersma
d252821df3 feature: constant values in bin packages 2020-06-18 13:54:04 +02:00
Nicholas Wiersma
2bef03e253 fix: import non-existant package 2020-06-18 09:44:03 +02:00
Nicholas Wiersma
1fe91be882 feature: refactor numeric constants and detect overflow 2020-06-18 09:20:04 +02:00
Nicholas Wiersma
5cbbf9339c fix: type assertion of non-matching types 2020-06-18 09:06:03 +02:00
Nicholas Wiersma
8365f687e7 fix: composite map assign (#683)
* fix: composite map assign

* reword comment

Co-authored-by: Marc Vertes <mvertes@free.fr>
2020-06-10 12:29:09 +02:00
Nicholas Wiersma
36836cd4f2 fix: return correct package name for parsed package (#679)
Co-authored-by: Marc Vertes <mvertes@free.fr>
2020-06-10 12:17:10 +02:00
Marc Vertes
82b499a1c8 fix: detect default comm clause in select from AST (#678)
* 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
2020-06-10 12:06:59 +02:00
Marc Vertes
0ef7f8fb80 fix: perform send channel action for select (#665)
* 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>
2020-06-10 11:37:06 +02:00
Marc Vertes
c1f5005b2a fix: finish support of type assertions which was incomplete (#657)
* fix: finish support of type assertions which was incomplete

TypeAssert was optimistically returning ok without verifying that
value could be converted to the required interface (in case of
type assert of an interface type), or not checking the type in
all conditions. There is now a working implements method for itype.

Fixes #640.

* style: appease lint

* fix: remove useless code block

* doc: improve comments

* avoid test conflict
2020-06-10 11:21:16 +02:00
Nicholas Wiersma
def57d57c2 fix: dont assign receiver on indexExpr 2020-06-03 19:10:04 +02:00
mpl
74479d70e6 Travis: apply timeout multiplier on CI 2020-06-03 17:50:04 +02:00
Nicholas Wiersma
f1cff308e6 fix: handle printf changing nil type 2020-06-03 17:36:04 +02:00
mpl
6f878052f8 interp: detect local redeclaration (#673)
* 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>
2020-06-03 17:21:00 +02:00
Nicholas Wiersma
eb25c84797 fix: handle call ellipsis 2020-06-03 16:42:04 +02:00
Nicholas Wiersma
2de0c80d38 fix: handle range on chan function return 2020-06-03 16:30:05 +02:00
Nicholas Wiersma
151a856bf2 fix: composite literal child types for call expressions 2020-06-03 09:44:03 +02:00
Nicholas Wiersma
d5217f7db4 fix: handle nil interface conversion 2020-06-03 00:32:04 +02:00
Nicholas Wiersma
01e4cdea70 fix: recursive struct function call 2020-06-03 00:18:04 +02:00
Nicholas Wiersma
3c88542180 fix: handle empty interface conversion 2020-05-29 13:58:04 +02:00
Nicholas Wiersma
56d88ef89d fix: nil recover case 2020-05-29 13:28:03 +02:00
Nicholas Wiersma
5d78c8ae27 fix: compose recursion 2020-05-28 08:52:03 +02:00
Nicholas Wiersma
184623d81f Fix import source symbol package 2020-05-27 17:16:03 +02:00
mpl
5d56bac8d0 interp: extend dot debugging 2020-05-26 22:38:03 +02:00
Marc Vertes
4a068ea452 fix: hande empty clause in switch if statement (#635)
The CFG was wrong in presence of an empty last clause.

Fixes #634.
2020-05-20 21:57:24 +02:00
Marc Vertes
8605c238ef fix: use interface wrappers to expose interface values to runtime (#643)
* fix: use interface wrappers to expose interface values to runtime

If a value is assigned to, or returned as, a binary interface,
then use the interface wrapper generator to convert the value
accordingly.

Fixes #630.

* test: rename NewFoo in Foo

* test: rename NewFoo in Foo

* fix: improve branch flow to reduce indentation
2020-05-20 21:46:14 +02:00
Marc Vertes
4f39eaf893 fix: correct iterator in map range on binary values (#644)
* fix: correct iterator in map range on binary values

The map range iterator was not initialized correctly for values
originating from runtime.

Fixes #641.

* test: deterministic output for map28.go
2020-05-20 21:37:48 +02:00
Marc Vertes
4f8e1de267 fix: check the number of argument passed and returned to functions 2020-05-19 14:56:04 +02:00
Marc Vertes
6f4643ff19 fix: compute numeral constant on typed objects 2020-05-19 14:38:03 +02:00
Ozan Hacıbekiroğlu
bb1be9e6e1 add repl input bounds check (#638)
* add repl input bounds check

* use bytes.Equal instead of Compare

* fix: use strings.HasPrefix to perform boundcheck on REPL input

This allows to keep most of the code unchanged and more readable.

Co-authored-by: Marc Vertes <mvertes@free.fr>
2020-05-18 18:53:39 +02:00
Marc Vertes
cdf4622421 fix: assign an element in a map from runtime 2020-05-05 22:46:04 +02:00
Marc Vertes
b9720d15e1 fix: improve setting results in multiple output functions 2020-05-05 22:34:03 +02:00
Marc Vertes
7fab75fbe4 fix: correct assign from function returning an interface value (#625) 2020-05-05 13:54:36 +02:00
Marc Vertes
7eac6955b3 feature: pre-import used packages in REPL mode. 2020-05-04 16:18:05 +02:00
Marc Vertes
7070367d21 fix: handle constant declarations inside function scopes 2020-05-03 18:56:04 +02:00
Marc Vertes
22dfc8b10a fix: handle set of variadic arg list for a ... value 2020-05-03 18:44:04 +02:00
Marc Vertes
7fba3fe580 fix: improve generation of interface wrapper 2020-05-03 18:32:04 +02:00
Marc Vertes
ff36ec58b1 fix: improve switch and type switch statement processing 2020-05-03 18:20:04 +02:00
Marc Vertes
f6c8b8b14f fix: check that a function returns the correct number of values 2020-05-03 18:08:03 +02:00
Marc Vertes
e12c8b72c4 fix: store the result of a bin function call in frame 2020-05-03 17:56:04 +02:00
Marc Vertes
e4acba031d fix: improving handling of functions returning interfaces 2020-05-03 17:46:03 +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
01e2e4600e fix: handle default comm clause in select 2020-04-25 17:40:08 +02:00
Marc Vertes
92eebbade2 fix: handle function output value assigned to interface var 2020-04-25 17:28:04 +02:00
Marc Vertes
a6389aca5e fix: improve handling of nil 2020-04-25 17:16:03 +02:00
Marc Vertes
de8cb7dc3b fix: handle type conversion from pre-compiled types. 2020-04-23 19:20:04 +02:00
Marc Vertes
18b843646c fix: parsing of recursive interface types 2020-04-22 19:26:05 +02:00
Marc Vertes
71f730b3d7 fix: handle forward declaration for aliased type 2020-04-22 10:50:05 +02:00
Marc Vertes
7b2d91bcb5 fix: handling values in map of interfaces 2020-04-22 10:34:05 +02:00
Marc Vertes
3ed4ec3f6f fix: correct type assertion for bin func types (#588) 2020-04-20 23:01:01 +02:00
Marc Vertes
5e142fdedd fix: do not attempt to copy data in empty frame at func call 2020-04-18 18:36:04 +02:00
Marc Vertes
94d44e7265 fix: do not convert literal float to int at parse 2020-04-17 17:54:03 +02:00
Marc Vertes
56925e6fea fix: correct branch control flow graph for parenthesis expressions (#583) 2020-04-17 14:40:56 +02:00
Marc Vertes
c580dfdbc8 fix: correct handling of interface types in composite literals 2020-04-16 19:54:03 +02:00
Marc Vertes
29e1777d82 fix: assign composite literal by reference 2020-04-16 12:24:04 +02:00
Marc Vertes
50a34fd2a7 fix: correct control flow graph for select blocks 2020-04-15 12:24:04 +02:00
Marc Vertes
465cb578e7 fix: lookup embededded field on struct pointer 2020-04-09 01:26:03 +02:00
Marc Vertes
12942b59a0 fix: remove ambiguities in recursive type processing 2020-04-09 01:14:03 +02:00
Marc Vertes
3e76267f8e fix: method search on struct pointer in interface wrapper 2020-04-07 17:22:04 +02:00
Marc Vertes
988f0c9672 fix: better handling of recursive types and forward declarations 2020-04-07 13:06:03 +02:00
Marc Vertes
b0053c874f fix: incomplete type analysis 2020-04-03 04:14:04 +02:00
Marc Vertes
b20ad3a01d fix: checks that value implements a binary type in type assert 2020-04-03 04:02:04 +02:00
Marc Vertes
e78650d359 fix: correct branch action in parenthesis expression 2020-03-26 12:10:04 +01:00
Marc Vertes
7327ff2811 fix: correct comparison of interface type to nil 2020-03-25 13:56:05 +01:00
Marc Vertes
ebde09b47d fix: correct control flow graph for switch statement 2020-03-25 12:40:04 +01:00
Marc Vertes
4995654e04 fix: correct control flow graph for constant conditional statements 2020-03-25 12:18:05 +01:00
Marc Vertes
0a99eb48c3 fix: do not pass twice the receiver in deferred method calls 2020-03-23 13:40:03 +01:00
Ludovic Fernandez
4a22635585 doc: update supported Go version in the readme. 2020-03-20 12:36:04 +01:00
Marc Vertes
b52dd8cc08 fix: substitute recursive struct type by interface{} in function arguments 2020-03-19 12:42:05 +01:00
Marc Vertes
daaeac6e2c fix: convert literal nil to interface types 2020-03-18 10:34:05 +01:00
Marc Vertes
ca68c6cd95 fix: resolve embedded method on pointer types 2020-03-17 18:14:04 +01:00
Marc Vertes
953b122e67 fix: avoid infinite recursion in genFunctionWrapper() 2020-03-17 18:02:05 +01:00
Marc Vertes
9b07e73b5e fix: resolve receiver for binary methods on non interface types 2020-03-12 14:42:04 +01:00
Marc Vertes
78bbcda1f8 fix: do not overwrite input for assign operators 2020-03-12 12:24:04 +01:00
Marc Vertes
6e33f89146 fix: correct control flow graph for some switch statements 2020-03-09 18:20:04 +01:00
Dmitrii Okunev
d29b0a48ff Add option "-e"
Option "-e" allows to set the command to be executed:

```
echo '6001d5ff0000000003000000000107000000dcff' | \
	yaegi -e 'import "fmt"; import "os"; import "encoding/hex"; import "io/ioutil"; func main() { in, _ := ioutil.ReadAll(os.Stdin); decoded, _ := hex.DecodeString(string(in));fmt.Println(string(decoded)) }' 2>/dev/null | \
	hexdump -C
00000000  60 01 d5 ff 00 00 00 00  03 00 00 00 00 01 07 00  |`...............|
00000010  00 00 dc ff 0a                                    |.....|
00000015
```
2020-03-09 18:07:04 +01:00
Marc Vertes
c7c1bea7ef fix: do not attempt to store data in _ var 2020-03-09 13:22:04 +01:00
Marc Vertes
1ae2649655 fix: correct control flow graph for defer statements 2020-03-09 10:52:05 +01:00
Traefiker Bot
0ace9244c4 fix: correctly init variables from index expressions 2020-03-05 14:28:06 +01:00
Traefiker Bot
2edd18a0c0 fix: handle use of functions in struct fields 2020-03-05 13:40:05 +01:00
Marc Vertes
cfb73445a2 fix: handle interface values in map and arrays 2020-03-03 18:32:04 +01:00
Ludovic Fernandez
94e0b582ea Update stdlib for go1.14 2020-02-26 15:06:06 +01:00
Dan Kortschak
3548c8744e interp: weaken panics to errors and return panicked values 2020-02-25 13:12:05 +01:00
Marc Vertes
d8bdc6670b fix: detect field names in struct pointer 2020-02-22 15:24:06 +01:00
Marc Vertes
27520f6dae fix: re-apply GTA until all global types/constants are defined 2020-02-20 12:44:04 +01:00
Marc Vertes
7037424edf fix: correctly store boolean result for branching operations 2020-02-14 16:26:04 +01:00
Marc Vertes
1b971b539c fix: correctly handle arbitrary type of literal array index 2020-02-12 15:06: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
05960316f8 fix: correct type inference in composite literal init 2020-02-11 10:10:04 +01:00
Marc Vertes
902af477b8 fix: correct behavior for rune and byte types 2020-02-09 05:18:04 +01:00
Marc Vertes
812e55b95e fix: handle conversion of nil to an interface type 2020-02-09 05:04:04 +01:00
Marc Vertes
6c339ce562 fix: handle method declaration with forward declared type 2020-02-07 15:44:04 +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
4fd6a2dc56 fix: handle recursive type definition involving a map object 2020-02-04 16:36:05 +01:00
Marc Vertes
92a63dbe09 fix: handle out of order type declaration for global var declaration 2020-02-03 17:36:04 +01:00
Marc Vertes
e434892b9a fix: import different source packages with same base name 2020-02-03 17:22:04 +01:00
Marc Vertes
712891dd77 fix: allow reuse of _ symbol in the same scope 2020-02-03 17:08:05 +01:00
Marc Vertes
137b16580c fix: handle binary methods where receiver is implicit 2020-02-03 16:54:04 +01:00
Sven Dowideit
b057ada531 Add an example of yaegi in a shebang line 2020-01-15 16:54:06 +01:00
Camal Cakar
6d90c5a641 Case sensitivity fix 2020-01-15 16:40:06 +01:00
Marc Vertes
5381ee65d1 fix: continue statement was not applied correctly 2020-01-10 17:50:05 +01:00
Marc Vertes
f1cde2be0f fix: apply automatic type conversion to constant expressions (#484) 2020-01-09 18:01:44 +01:00
Marc Vertes
bb04af2d4d doc: document import of source and binary packages (#477) 2020-01-08 18:51:30 +01:00
Marc Vertes
9a8a88dcb9 fix: use branch operation in || and && operators, fix storage for ! (#476) 2020-01-07 17:27:22 +01:00
Marc Vertes
f3f54a5302 doc: add explanation about CLA in CONTRIBUTING.md (#483) 2020-01-07 16:30:05 +01:00
Marc Vertes
878fcc835c fix: add support for ^ and + as unary operators 2020-01-07 15:34:05 +01:00
Marc Vertes
a1f2d3bf1d fix: isNil was not forwarding result when used in a branch expression 2019-12-19 18:32:04 +01:00
Marc Vertes
3cd37645eb fix: correct isValueUntyped() to handle typed constants 2019-12-19 15:38:05 +01:00
Marc Vertes
e1ac83f7d8 fix: correct type extraction for returned value 2019-12-17 10:18:06 +01:00
Marc Vertes
4f93be7f19 fix: emulate struct by interface{} only for recursive struct types 2019-12-16 19:00:07 +01:00
Marc Vertes
7a0c09f5eb fix: detect untyped values when importing from binary packages 2019-12-13 11:18:04 +01:00
Marc Vertes
275391c1e8 fix: struct type detection, collision between field and type name 2019-12-12 14:40:05 +01:00
Marc Vertes
273df8af9f fix: improve interface type checks using method sets 2019-12-11 14:46:06 +01:00
Marc Vertes
0d2c39d155 fix: implicit import package name was not correctly generated 2019-12-11 11:54:05 +01:00
Marc Vertes
1ff1a50753 fix: add method checks for interface types 2019-12-09 18:24:04 +01:00
Marc Vertes
488e491bf8 fix: improve type switch clause with assign 2019-11-27 23:00:04 +01:00
Marc Vertes
eef59153d8 fix: detect non boolean condition for IF and FOR statements 2019-11-26 00:08:05 +01:00
Marc Vertes
d44e4af527 fix: handle selector expression in type switch 2019-11-25 23:52:03 +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
9f1f31210a fix: automatic type conversion when returning untyped value 2019-11-19 15:22:05 +01:00
Marc Vertes
56bec974e1 fix: handle index expression on binary string type 2019-11-19 15:06:05 +01:00
Marc Vertes
08a37fc4bf fix: handle type assertion from literal interface type 2019-11-19 14:50:06 +01:00
Marc Vertes
c5ec5e492f fix: assign a literal composite to an interface object 2019-11-19 14:34:05 +01:00
Marc Vertes
773147ef71 fix: properly align atomic counters 2019-11-08 00:34:04 +01:00
Marc Vertes
a6ecebab92 fix: automatic conversion of untyped literal float to int 2019-10-31 17:32:05 +01:00
Dan Kortschak
d893a7427e doc: fix spelling 2019-10-30 11:20:05 +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
75a696a5c8 fix: goexports performs correct conversion on float32 constants 2019-10-29 10:20:05 +01:00
Marc Vertes
15686873e0 fix: assign binary func to func type var 2019-10-20 04:52:03 +02:00
Marc Vertes
ac504a2e8a fix: assign untyped value to typed var may require type conversion 2019-10-20 02:30:03 +02:00
Ludovic Fernandez
e193d95dc2 feat: update syscall for go1.12.12 2019-10-19 18:30:04 +02:00
Marc Vertes
7164a23664 fix: do not hide receiver type for method with anonymous receiver 2019-10-19 17:44:03 +02:00
Marc Vertes
0b4dcbf7bb feature: add support for custom build tags 2019-10-11 16:02:05 +02:00
Ludovic Fernandez
2765478137 chore: update linter to support go1.13 2019-10-09 14:14:04 +02:00
Marc Vertes
de5a6e1038 feature: rename exported func Repl into REPL 2019-10-08 23:54:04 +02:00
Dan Kortschak
398b0e0255 interp: use io.Reader and io.Writer for REPL parameters 2019-10-08 17:34:05 +02:00
Marc Vertes
4f95c27634 fix: generate closures for literal functions in CFG 2019-10-05 19:26:04 +02:00
Marc Vertes
7d19108f01 fix: compute type of slice expression globally 2019-10-05 19:14:04 +02:00
Ludovic Fernandez
1cf327bd7d Drop go1.11 2019-10-01 14:40:05 +02:00
Dan Kortschak
4bf4aeecbb interp: fix map range handling 2019-10-01 13:54:03 +02:00
Dan Kortschak
47923866ff interp: fix array size assignment type inference 2019-09-30 22:58:04 +02:00
Dan Kortschak
bb2921b42f interp: fix range expression handling 2019-09-30 22:44:04 +02:00
Marc Vertes
2c2b471cb9 fix: goexports to convert value type only for untyped constants 2019-09-27 15:44:05 +02:00
Marc Vertes
0f46cd5efb fix: handle type declaration inside function 2019-09-26 00:50:04 +02:00
Marc Vertes
35e645c690 fix: correct handling of types alias of interfaces 2019-09-25 15:24:04 +02:00
Marc Vertes
03596dac45 fix: correct automatic type conversion for untyped constants 2019-09-25 15:02:04 +02:00
Dan Kortschak
8db7a815e3 interp: don't panic for undefined types 2019-09-25 12:24:05 +02:00
Dan Kortschak
424e7ac90d test: ensure hour-aligned timezone 2019-09-25 02:40:03 +02:00
Marc Vertes
effd64c980 fix: handle forward declaration of alias type 2019-09-24 16:10:04 +02:00
Marc Vertes
8a88a1ab8a fix: range over string iterates on runes instead of bytes 2019-09-23 17:02:04 +02:00
Marc Vertes
030dd3cbc2 fix: support variadic parameters on methods 2019-09-23 15:20:04 +02:00
Marc Vertes
bee21968c7 doc: README, supported go versions: 1.12 and 1.13 2019-09-19 15:00:05 +02:00
Marc Vertes
9abaeeb729 fix: binary method lookup works for struct field pointer receiver 2019-09-19 14:02:06 +02:00
Ludovic Fernandez
c8ae73ae8c chore: allow to build tags 2019-09-19 08:58:03 +02:00
Marc Vertes
5e49f83519 fix: shift operator inherits its type from first arg only 2019-09-18 23:44:03 +02:00
Marc Vertes
ec1ee5f5b6 fix: support array operations on array pointers 2019-09-18 23:32:04 +02:00
Marc Vertes
e03016b6d7 feature: detect import cycle 2019-09-17 01:32:03 +02:00
Marc Vertes
400b625153 fix: support defining recursive interface types 2019-09-17 01:18:03 +02:00
Marc Vertes
f7810d9761 fix: init global var from builtin 2019-09-16 16:50:06 +02:00
Ludovic Fernandez
7d4e5fb224 chore: build only master branch. 2019-09-16 15:38:04 +02:00
Marc Vertes
b08a51cb16 fix: conversion of type to reflect.Type avoids recursive loop 2019-09-16 15:04:03 +02:00
Marc Vertes
9e664ee8dd fix: global variable init from selector expression 2019-09-16 14:30:05 +02:00
Marc Vertes
cda23836f0 feature: additional binary packages in stdlib (#366)
Generate wrappers for the following packages:

- crypto/ed25519 (go1.13 only)
- debug/dwarf
- debug/elf
- debug/gosym
- debug/pe
- debug/plan9obj
- net/http/pprof
- runtime/pprof
- runtime/trace
2019-09-16 14:06:11 +02:00
Marc Vertes
058c121273 fix: add support for out of order declarations of empty global variables 2019-09-11 12:52:04 +02:00
Marc Vertes
3645904a15 fix: correct resolve of type and symbols from imported source package 2019-09-11 12:30:05 +02:00
Marc Vertes
82dd3f2953 fix: implement variadic using a type category to avoid corruption 2019-09-10 13:12:03 +02:00
Marc Vertes
2f0279f0f5 fix: reuse rather than re-import an already imported source package 2019-09-09 15:54:05 +02:00
Ludovic Fernandez
bfa9a267be Update stdlib for go1.13 (#351)
* chore: generate stdlib for go1.13

* chore: update CI configuration.

* fix: struct13 test is too dependent of the Go implementation.

* fix: disable test import4.go
2019-09-09 09:59:26 +02:00
Marc Vertes
978bbe0301 fix: avoid collision between package names and function args 2019-09-06 18:44:03 +02:00
Marc Vertes
63a537c8d9 fix: correct computation of type when dereference a binary object (#349) 2019-09-05 15:27:35 +02:00
Marc Vertes
b0937618b0 fix: improve handling of out of order declarations (#344) 2019-09-05 11:37:34 +02:00
Marc Vertes
d23a7e1d8b fix: assign a function value to a pre-declared variable 2019-08-29 05:16:04 -07:00
Marc Vertes
71fd938040 fix: improve handling of global declarations, possibly out of order (#336) 2019-08-28 16:59:46 +02:00
Marc Vertes
869b6d2850 fix: iterate on global type analyis when necessary (#335) 2019-08-22 17:36:23 +02:00
Marc Vertes
a4e15d7788 fix: do not skip AST errors when not in REPL mode (#329) 2019-08-20 18:43:01 +02:00
Marc Vertes
c88297459d doc: add a contributing guide (#333) 2019-08-19 19:14:58 +02:00
Marc Vertes
8aa22b9ebb feature: locate origin of CFG panic in input source (#330) 2019-08-19 17:40:03 +02:00
Sebastien Binet
75ad29c6b4 cmd/goexports: add -license flag to goexports 2019-08-05 03:10:05 -07:00
Ludovic Fernandez
a89a8b9ce4 chore: add goexports to the archive. 2019-08-01 01:46:04 -07:00
Ludovic Fernandez
458e8e911a interp/build: support custom build constraints. 2019-07-31 09:00:05 -07:00
Ludovic Fernandez
ee81ee7fea interp/build: improve Go version handling. 2019-07-30 14:34:04 -07:00
Marc Vertes
aaddc39981 fix: support 'range' with no index and value assigned 2019-07-30 11:00:06 -07:00
Ludovic Fernandez
5bf6618a53 goexports: allow to generate mapping for devel, beta, and rc. 2019-07-30 08:12:04 -07:00
Ludovic Fernandez
aad4c5a99b doc: add community badge. 2019-07-27 16:52:03 -07:00
Ludovic Fernandez
373e3204b4 chore: revert stdlib improvements 2019-07-26 22:36:03 -07:00
Marc Vertes
5f41fcb8bc doc: add a Limitations section in README 2019-07-26 20:56:03 -07:00
Ludovic Fernandez
43b8594c82 feat: improve stdlib generation. 2019-07-26 17:10:04 -07:00
Marc Vertes
4c877cc348 fix: correct assign to binary interface value (#291) 2019-07-26 10:59:16 -07:00
Marc Vertes
f199520048 doc: first attempt to document goexports command 2019-07-25 23:02:03 -07:00
Taufiq Rahman
4df03252f6 doc: Fixes the title and other formattings 2019-07-25 12:06:03 -07:00
Ludovic Fernandez
2dfede3b90 doc: add playground examples. 2019-07-25 09:08:03 -07:00
Fernandez Ludovic
6191f5d38a chore: add godoc badge. 2019-07-24 22:01:51 -07:00
Ludovic Fernandez
24db786bb6 fix: exclude syslog for windows, nacl, and plan9. 2019-07-24 18:58:04 -07:00
Ludovic Fernandez
aa98e2c2a9 feat: support yaegi in go playground 2019-07-24 17:52:03 -07:00
Ludovic Fernandez
8ace2eb6e6 doc: improve documentation. 2019-07-24 11:44:04 -07:00
Cuong Manh Le
f2034819c2 fix: blank identifier cause panic (#255) 2019-07-24 11:20:04 -07:00
Brendan Le Glaunec
172d4a4657 Fix installation instructions (#250) 2019-07-24 09:11:07 -07:00
1182 changed files with 192249 additions and 146825 deletions

View File

@@ -17,11 +17,11 @@ func main() {
Expected result:
```console
$ go run ./sample.go
// ouput
// output
```
Got:
```console
$ yaegi ./sample.go
// ouput
// output
```

View File

@@ -0,0 +1,19 @@
---
name: Feature request
about: Propose a change to Yaegi!
---
<!-- ⚠️ If you do not respect this template your issue will be closed. -->
<!-- ⚠️ Make sure to browse the opened and closed issues before submit your issue. -->
#### Proposal
<!-- Write your feature request in the form of a proposal to be considered for implementation -->
#### Background
<!-- Describe the background problem or need that led to this feature request -->
#### Workarounds
<!-- Are there any current workarounds that you're using that others in similar positions should know about? -->

67
.github/workflows/go-cross.yml vendored Normal file
View File

@@ -0,0 +1,67 @@
name: Build Cross OS
on:
push:
branches:
- master
pull_request:
jobs:
cross:
name: Go
runs-on: ${{ matrix.os }}
defaults:
run:
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/yaegi
strategy:
matrix:
go-version: [ 1.15, 1.16 ]
os: [ubuntu-latest, macos-latest, windows-latest]
include:
- os: ubuntu-latest
go-path-suffix: /go
- os: macos-latest
go-path-suffix: /go
- os: windows-latest
go-path-suffix: \go
steps:
# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
# https://github.com/marketplace/actions/checkout
- name: Checkout code
uses: actions/checkout@v2
with:
path: go/src/github.com/traefik/yaegi
# https://github.com/marketplace/actions/cache
- name: Cache Go modules
uses: actions/cache@v2
with:
path: |
~/go/pkg/mod # Module download cache
~/.cache/go-build # Build cache (Linux)
~/Library/Caches/go-build # Build cache (Mac)
'%LocalAppData%\go-build' # Build cache (Windows)
key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-${{ matrix.go-version }}-go-
- name: Setup GOPATH
run: go env -w GOPATH=${{ github.workspace }}${{ matrix.go-path-suffix }}
# TODO fail on windows
# - name: Tests
# run: go test -v -cover ./...
# env:
# GOPATH: ${{ github.workspace }}${{ matrix.go-path }}
- name: Build
run: go build -race -v -ldflags "-s -w" -trimpath

110
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,110 @@
name: Main
on:
push:
branches:
- master
pull_request:
env:
GO_VERSION: 1.16
GOLANGCI_LINT_VERSION: v1.36.0
jobs:
linting:
name: Linting
runs-on: ubuntu-latest
steps:
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v2
with:
go-version: ${{ env.GO_VERSION }}
- name: Check out code
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Check and get dependencies
run: |
go mod tidy
git diff --exit-code go.mod
# git diff --exit-code go.sum
go mod download
- name: Install golangci-lint ${{ env.GOLANGCI_LINT_VERSION }}
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION}
- name: Run golangci-lint ${{ env.GOLANGCI_LINT_VERSION }}
run: make check
generate:
name: Checks code and generated code
runs-on: ubuntu-latest
needs: linting
strategy:
matrix:
go-version: [ 1.15, 1.16 ]
steps:
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Check out code
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Check generated code
run: |
rm -f interp/op.go
make generate
git update-index -q --refresh
CHANGED=$(git diff-index --name-only HEAD --)
test -z "$CHANGED" || echo $CHANGED
test -z "$CHANGED"
main:
name: Build and Test
runs-on: ubuntu-latest
needs: linting
defaults:
run:
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/yaegi
strategy:
matrix:
go-version: [ 1.15, 1.16 ]
steps:
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Check out code
uses: actions/checkout@v2
with:
path: go/src/github.com/traefik/yaegi
fetch-depth: 0
# https://github.com/marketplace/actions/cache
- name: Cache Go modules
uses: actions/cache@v2
with:
path: ./_test/tmp
key: ${{ runner.os }}-yaegi-${{ hashFiles('**//_test/tmp/') }}
restore-keys: |
${{ runner.os }}-yaegi-
- name: Setup GOPATH
run: go env -w GOPATH=${{ github.workspace }}/go
- name: Build
run: go build -v ./...
- name: Run tests
run: make tests
env:
GOPATH: ${{ github.workspace }}/go

42
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: Release
on:
push:
tags:
- v[0-9]+.[0-9]+*
env:
GO_VERSION: 1.16
jobs:
release:
name: Create a release
runs-on: ubuntu-latest
steps:
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v2
with:
go-version: ${{ env.GO_VERSION }}
- name: Check out code
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Cache Go modules
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_REPO }}

3
.gitignore vendored
View File

@@ -3,6 +3,7 @@
*.dot
.idea/
/yaegi
cmd/goexports/goexports
internal/cmd/extract/extract
example/inception/inception
_test/tmp/
/dist

View File

@@ -5,7 +5,7 @@
[linters-settings]
[linters-settings.govet]
check-shadowing = true
check-shadowing = false
[linters-settings.gocyclo]
min-complexity = 12.0
@@ -32,6 +32,24 @@
"gocyclo",
"gochecknoinits",
"gochecknoglobals",
"wsl",
"nlreturn",
"godox",
"funlen",
"gocognit",
"stylecheck",
"gomnd",
"testpackage",
"paralleltest",
"tparallel",
"goerr113",
"wrapcheck",
"nestif",
"exhaustive",
"exhaustivestruct",
"forbidigo",
"ifshort",
"errorlint", # TODO: must be reactivate before fixes
]
[issues]
@@ -41,10 +59,15 @@
exclude = []
[[issues.exclude-rules]]
path = "cmd/goexports/goexports.go"
text = "SA1019: importer.For is deprecated: use ForCompiler, which populates a FileSet with the positions of objects created by the importer."
path = "interp/.+_test\\.go"
linters = ["goconst"]
# structcheck false-positive
[[issues.exclude-rules]]
path = "interp/interp.go"
text = "`(astDot|cfgDot|noRun)` is unused"
text = "`in` can be `io.Reader`"
[[issues.exclude-rules]]
path = "interp/interp.go"
text = "`out` can be `io.Writer`"
[[issues.exclude-rules]]
path = "interp/interp_eval_test.go"
linters = ["thelper"]

View File

@@ -1,8 +1,9 @@
project_name: yaegi
builds:
- binary: yaegi
main: ./cmd/yaegi/yaegi.go
- id: yaegi
binary: yaegi
main: ./cmd/yaegi/
goos:
- darwin
@@ -35,11 +36,28 @@ changelog:
- '^test:'
- '^tests:'
archive:
name_template: '{{ .ProjectName }}_v{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
format: tar.gz
format_overrides:
- goos: windows
format: zip
files:
- LICENSE
archives:
- id: archive
name_template: '{{ .ProjectName }}_v{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
format: tar.gz
format_overrides:
- goos: windows
format: zip
files:
- LICENSE
brews:
- tap:
owner: traefik
name: homebrew-tap
commit_author:
name: traefiker
email: 30906710+traefiker@users.noreply.github.com
folder: Formula
homepage: https://github.com/traefik/yaegi
description: |
Yaegi is Another Elegant Go Interpreter.
It powers executable Go scripts and plugins, in embedded interpreters
or interactive shells, on top of the Go runtime.
test: |
system "#{bin}/yaegi version"

View File

@@ -1,47 +0,0 @@
language: go
dist: xenial
env:
- GO111MODULE=on
notifications:
email:
on_success: never
on_failure: change
go:
- 1.11.x
- 1.12.x
go_import_path: github.com/containous/yaegi
before_install:
# Install linters and misspell
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.16.0
- golangci-lint --version
install:
- echo "TRAVIS_GO_VERSION=$TRAVIS_GO_VERSION"
- go mod download
before_script:
- rm -f interp/op.go interp/interp_test.go
- make generate
- git update-index -q --refresh
- CHANGED=$(git diff-index --name-only HEAD --)
- test -z "$CHANGED" || echo $CHANGED
- test -z "$CHANGED"
script:
- make check
- go build -v ./...
- GO111MODULE=off go test -v ./...
deploy:
- provider: script
skip_cleanup: true
script: curl -sL https://git.io/goreleaser | bash
on:
tags: true
condition: $TRAVIS_GO_VERSION =~ ^1\.12\.x$

24
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,24 @@
# Contributing
Yaegi is an open source project, and your feedback and contributions
are needed and always welcome.
[Issues] and [Pull Requests] are opened at https://github.com/traefik/yaegi.
Non trivial changes should be discussed with the project maintainers by
opening a [Feature Request] clearly explaining rationale, background
and possible implementation ideas. Feel free to provide code in such
discussions.
Once the proposal is approved, a Pull Request can be opened. If you want
to provide early visibility to reviewers, create a [Draft Pull Request].
We will also require you to sign the [Traefik Contributor License Agreement]
after you submit your first pull request to this project. The link to sign the
agreement will be presented to you in the web interface of the pull request.
[Issues]: https://github.com/traefik/yaegi/issues
[Pull Requests]: https://github.com/traefik/yaegi/issues
[Feature Request]: https://github.com/traefik/yaegi/issues/new?template=feature_request.md
[Draft Pull Request]: https://github.blog/2019-02-14-introducing-draft-pull-requests/
[Traefik Labs Contributor License Agreement]: https://cla-assistant.io/traefik/yaegi

View File

@@ -187,6 +187,7 @@
identification within third-party archives.
Copyright 2019 Containous SAS
Copyright 2020 Traefik Labs SAS
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,17 +3,28 @@ check:
golangci-lint run
# Generate stdlib/syscall/syscall_GOOS_GOARCH.go for all platforms
gen_all_syscall: cmd/goexports/goexports
@cd stdlib/syscall && \
for v in $$(go tool dist list); do \
gen_all_syscall: internal/cmd/extract/extract
@for v in $$(go tool dist list); do \
echo syscall_$${v%/*}_$${v#*/}.go; \
GOOS=$${v%/*} GOARCH=$${v#*/} go generate; \
GOOS=$${v%/*} GOARCH=$${v#*/} go generate ./stdlib/syscall ./stdlib/unrestricted; \
done
cmd/goexports/goexports: cmd/goexports/goexports.go
go generate cmd/goexports/goexports.go
internal/cmd/extract/extract:
rm -f internal/cmd/extract/extract
go generate ./internal/cmd/extract
generate: gen_all_syscall
go generate
.PHONY: check gen_all_syscall gen_tests
install:
GOFLAGS=-ldflags=-X=main.version=$$(git describe --tags) go install ./...
tests:
go test -v ./...
go test -race ./interp
# https://github.com/goreleaser/godownloader
install.sh: .goreleaser.yml
godownloader --repo=traefik/yaegi -o install.sh .goreleaser.yml
.PHONY: check gen_all_syscall gen_tests generate_downloader internal/cmd/extract/extract install

135
README.md
View File

@@ -2,8 +2,10 @@
<img width="400" src="doc/images/yaegi.png" alt="Yaegi" title="Yaegi" />
</p>
[![release](https://img.shields.io/github/tag-date/containous/yaegi.svg?label=alpha)](https://github.com/containous/yaegi/releases)
[![Build Status](https://travis-ci.com/containous/yaegi.svg?branch=master)](https://travis-ci.com/containous/yaegi)
[![release](https://img.shields.io/github/tag-date/traefik/yaegi.svg?label=alpha)](https://github.com/traefik/yaegi/releases)
[![Build Status](https://travis-ci.com/traefik/yaegi.svg?branch=master)](https://travis-ci.com/traefik/yaegi)
[![GoDoc](https://godoc.org/github.com/traefik/yaegi?status.svg)](https://godoc.org/github.com/traefik/yaegi)
[![Discourse status](https://img.shields.io/discourse/https/community.containo.us/status?label=Community&style=social)](https://community.containo.us/c/yaegi)
Yaegi is Another Elegant Go Interpreter.
It powers executable Go scripts and plugins, in embedded interpreters or interactive shells, on top of the Go runtime.
@@ -11,49 +13,38 @@ It powers executable Go scripts and plugins, in embedded interpreters or interac
## Features
* Complete support of [Go specification][specs]
* In pure Go, using only standard library
* Written in pure Go, using only the standard library
* Simple interpreter API: `New()`, `Eval()`, `Use()`
* works everywhere Go works
* Works everywhere Go works
* All Go & runtime resources accessible from script (with control)
* Security: `unsafe` and `syscall` packages not used or exported by default
* Security: `unsafe` and `syscall` packages neither used nor exported by default
* Support Go 1.13 and Go 1.14 (the latest 2 major releases)
## Install
### As library
### Go package
```go
import "github.com/containous/yaegi/interp"
import "github.com/traefik/yaegi/interp"
```
### REPL
### Command-line executable
```bash
go get -u github.com/containous/yaegi/cmd
go get -u github.com/traefik/yaegi/cmd/yaegi
```
Note that you can use [rlwrap](https://github.com/hanslub42/rlwrap) (install with your favorite package manager),
and alias the `yaegi` command in `alias yaegi='rlwrap yaegi'` in your `~/.bashrc`, to have history and command line edition.
### CI Integration
```bash
curl -sfL https://raw.githubusercontent.com/traefik/yaegi/master/install.sh | bash -s -- -b $GOPATH/bin v0.9.0
```
## Usage
### As a command line interpreter
The Yaegi command can run an interactive Read-Eval-Print-Loop:
```console
$ yaegi
> 1 + 2
3
> import "fmt"
> fmt.Println("Hello World")
Hello World
>
```
Or interpret Go files:
```console
$ yaegi cmd/yaegi/yaegi.go
>
```
### As an embedded interpreter
Create an interpreter with `New()`, run Go code with `Eval()`:
@@ -62,8 +53,8 @@ Create an interpreter with `New()`, run Go code with `Eval()`:
package main
import (
"github.com/containous/yaegi/interp"
"github.com/containous/yaegi/stdlib"
"github.com/traefik/yaegi/interp"
"github.com/traefik/yaegi/stdlib"
)
func main() {
@@ -76,13 +67,15 @@ func main() {
panic(err)
}
_, err = i.Eval(`fmt.Println("hello")`)
_, err = i.Eval(`fmt.Println("Hello Yaegi")`)
if err != nil {
panic(err)
}
}
```
[Go Playground](https://play.golang.org/p/2n-EpZbMYI9)
### As a dynamic extension framework
The following program is compiled ahead of time, except `bar()` which is interpreted, with the following steps:
@@ -94,7 +87,7 @@ The following program is compiled ahead of time, except `bar()` which is interpr
```go
package main
import "github.com/containous/yaegi/interp"
import "github.com/traefik/yaegi/interp"
const src = `package foo
func Bar(s string) string { return s + "-Foo" }`
@@ -119,23 +112,81 @@ func main() {
}
```
[Go Playground](https://play.golang.org/p/WvwH4JqrU-p)
### As a command-line interpreter
The Yaegi command can run an interactive Read-Eval-Print-Loop:
```console
$ yaegi
> 1 + 2
3
> import "fmt"
> fmt.Println("Hello World")
Hello World
>
```
Note that in interactive mode, all stdlib package are pre-imported,
you can use them directly:
```console
$ yaegi
> reflect.TypeOf(time.Date)
: func(int, time.Month, int, int, int, int, int, *time.Location) time.Time
>
```
Or interpret Go packages, directories or files, including itself:
```console
$ yaegi -syscall -unsafe -unrestricted github.com/traefik/yaegi/cmd/yaegi
>
```
Or for Go scripting in the shebang line:
```console
$ cat /tmp/test
#!/usr/bin/env yaegi
package main
import "fmt"
func main() {
fmt.Println("test")
}
$ ls -la /tmp/test
-rwxr-xr-x 1 dow184 dow184 93 Jan 6 13:38 /tmp/test
$ /tmp/test
test
```
## Documentation
Documentation about Yaegi commands and libraries can be found at usual [godoc.org][docs].
## Limitations
Beside the known [bugs] which are supposed to be fixed in the short term, there are some limitations not planned to be addressed soon:
- Assembly files (`.s`) are not supported.
- Calling C code is not supported (no virtual "C" package).
- Interfaces to be used from the pre-compiled code can not be added dynamically, as it is required to pre-compile interface wrappers.
- Representation of types by `reflect` and printing values using %T may give different results between compiled mode and interpreted mode.
- Interpreting computation intensive code is likely to remain significantly slower than in compiled mode.
## Contributing
Yaegi is an open source project, and your feedback and contributions are needed and always welcome.
[Issues] and [pull requests] are opened at https://github.com/containous/yaegi
[Contributing guide](CONTRIBUTING.md).
## License
[Apache 2.0][License].
[specs]: https://golang.org/ref/spec
[docs]: https://godoc.org/github.com/containous/yaegi
[license]: https://github.com/containous/yaegi/blob/master/LICENSE
[github]: https://github.com/containous/yaegi
[Issues]: https://github.com/containous/yaegi/issues
[pull requests]: https://github.com/containous/yaegi/issues
[docs]: https://godoc.org/github.com/traefik/yaegi
[license]: https://github.com/traefik/yaegi/blob/master/LICENSE
[github]: https://github.com/traefik/yaegi
[bugs]: https://github.com/traefik/yaegi/issues?q=is%3Aissue+is%3Aopen+label%3Abug

10
_test/a30.go Normal file
View File

@@ -0,0 +1,10 @@
package main
func main() {
for range []struct{}{} {
}
println("ok")
}
// Output:
// ok

11
_test/a31.go Normal file
View File

@@ -0,0 +1,11 @@
package main
func main() {
for range []int{0, 1, 2} {
print("hello ")
}
println("")
}
// Output:
// hello hello hello

14
_test/a32.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
type T struct{}
var a = []T{{}}
func main() {
fmt.Println(a)
}
// Output:
// [{}]

12
_test/a33.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3}
b := a
fmt.Println(b)
}
// Output:
// [1 2 3]

12
_test/a34.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3}
var b [3]int = a
fmt.Println(b)
}
// Output:
// [1 2 3]

13
_test/a35.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3}
b := a
b[0] = -1
fmt.Println(a)
}
// Output:
// [1 2 3]

13
_test/a36.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3}
var b [3]int = a
b[0] = -1
fmt.Println(a)
}
// Output:
// [1 2 3]

11
_test/a37.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3}
fmt.Println(a)
}
// Output:
// [1 2 3]

11
_test/a38.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
a := [...]byte{}
fmt.Printf("%T\n", a)
}
// Output:
// [0]uint8

12
_test/a39.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
a := [...]byte{}
b := a
fmt.Printf("%T %T\n", a, b)
}
// Output:
// [0]uint8 [0]uint8

23
_test/a40.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import "fmt"
type rule uint8
const (
r0 rule = iota
r1
r2
)
var a = [...]int{
r0: 1,
r1: 12,
}
func main() {
fmt.Println(a)
}
// Output:
// [1 12]

10
_test/a41.go Normal file
View File

@@ -0,0 +1,10 @@
package main
var a = [...]bool{true, true}
func main() {
println(a[0] && true)
}
// Output:
// true

16
_test/a42.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import (
"encoding/binary"
"fmt"
)
func main() {
var b [8]byte
binary.LittleEndian.PutUint64(b[:], uint64(1))
fmt.Println(b)
}
// Output:
// [1 0 0 0 0 0 0 0]

17
_test/a43.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import "fmt"
type T [l1 + l2]int
const (
l1 = 2
l2 = 3
)
func main() {
fmt.Println(T{})
}
// Output:
// [0 0 0 0 0]

12
_test/a44.go Normal file
View File

@@ -0,0 +1,12 @@
package main
var a = [max]int{}
const max = 32
func main() {
println(len(a))
}
// Output:
// 32

9
_test/add0.go Normal file
View File

@@ -0,0 +1,9 @@
package main
func main() {
var a interface{} = 2 + 5
println(a.(int))
}
// Output:
// 7

41
_test/add1.go Normal file
View File

@@ -0,0 +1,41 @@
package main
func main() {
b := 2 // int
var c int = 5 + b
println(c)
var d int32 = 6 + int32(b)
println(d)
var a interface{} = 7 + b
println(a.(int))
var e int32 = 2
var f interface{} = 8 + e
println(f.(int32))
a = 9 + e
println(a.(int32))
var g int = 2
a = 10 + g
println(a.(int))
// multiple assignment
var foo interface{}
foo, a = "hello", 11 + g
println(a.(int))
println(foo.(string))
}
// Output:
// 7
// 8
// 9
// 10
// 11
// 12
// 13
// hello

12
_test/add2.go Normal file
View File

@@ -0,0 +1,12 @@
package main
type iface interface{}
func main() {
b := 2
var a iface = 5 + b
println(a.(int))
}
// Output:
// 7

25
_test/addr0.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import (
"fmt"
"net/http"
)
type extendedRequest struct {
http.Request
Data string
}
func main() {
r := extendedRequest{}
req := &r.Request
fmt.Println(r)
fmt.Println(req)
}
// Output:
// {{ <nil> 0 0 map[] <nil> <nil> 0 [] false map[] map[] <nil> map[] <nil> <nil> <nil> <nil>} }
// &{ <nil> 0 0 map[] <nil> <nil> 0 [] false map[] map[] <nil> map[] <nil> <nil> <nil> <nil>}

22
_test/addr1.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import "fmt"
type T struct {
A int
B int
}
func main() {
a := &[]T{
{1, 2},
{3, 4},
}
fmt.Println("a:", a)
x := &(*a)[1:][0]
fmt.Println("x:", x)
}
// Output:
// a: &[{1 2} {3 4}]
// x: &{3 4}

63
_test/addr2.go Normal file
View File

@@ -0,0 +1,63 @@
package main
import (
"encoding/xml"
"errors"
"fmt"
)
type Email struct {
Where string `xml:"where,attr"`
Addr string
}
func f(r interface{}) error {
return withPointerAsInterface(&r)
}
func withPointerAsInterface(r interface{}) error {
_ = (r).(*interface{})
rp, ok := (r).(*interface{})
if !ok {
return errors.New("cannot assert to *interface{}")
}
em, ok := (*rp).(*Email)
if !ok {
return errors.New("cannot assert to *Email")
}
em.Where = "work"
em.Addr = "bob@work.com"
return nil
}
func ff(s string, r interface{}) error {
return xml.Unmarshal([]byte(s), r)
}
func fff(s string, r interface{}) error {
return xml.Unmarshal([]byte(s), &r)
}
func main() {
data := `
<Email where='work'>
<Addr>bob@work.com</Addr>
</Email>
`
v := Email{}
err := f(&v)
fmt.Println(err, v)
vv := Email{}
err = ff(data, &vv)
fmt.Println(err, vv)
vvv := Email{}
err = ff(data, &vvv)
fmt.Println(err, vvv)
}
// Output:
// <nil> {work bob@work.com}
// <nil> {work bob@work.com}
// <nil> {work bob@work.com}

24
_test/addr3.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import (
"fmt"
)
func main() {
var a interface{}
a = 2
fmt.Println(a)
var b *interface{}
b = &a
fmt.Println(*b)
var c **interface{}
c = &b
fmt.Println(**c)
}
// Output:
// 2
// 2
// 2

114
_test/addr4.go Normal file
View File

@@ -0,0 +1,114 @@
package main
import (
"encoding/json"
"fmt"
"log"
)
const jsonData = `[
"foo",
"bar"
]`
const jsonData2 = `[
{"foo": "foo"},
{"bar": "bar"}
]`
const jsonData3 = `{
"foo": "foo",
"bar": "bar"
}`
func fromSlice() {
var a []interface{}
var c, d interface{}
c = 2
d = 3
a = []interface{}{c, d}
if err := json.Unmarshal([]byte(jsonData), &a); err != nil {
log.Fatalln(err)
}
for k, v := range a {
fmt.Println(k, ":", v)
}
}
func fromEmpty() {
var a interface{}
var c, d interface{}
c = 2
d = 3
a = []interface{}{c, d}
if err := json.Unmarshal([]byte(jsonData), &a); err != nil {
log.Fatalln(err)
}
b := a.([]interface{})
for k, v := range b {
fmt.Println(k, ":", v)
}
}
func sliceOfObjects() {
var a interface{}
if err := json.Unmarshal([]byte(jsonData2), &a); err != nil {
log.Fatalln(err)
}
b := a.([]interface{})
for k, v := range b {
fmt.Println(k, ":", v)
}
}
func intoMap() {
var a interface{}
if err := json.Unmarshal([]byte(jsonData3), &a); err != nil {
log.Fatalln(err)
}
b := a.(map[string]interface{})
seenFoo := false
for k, v := range b {
vv := v.(string)
if vv != "foo" {
if seenFoo {
fmt.Println(k, ":", vv)
break
}
kk := k
vvv := vv
defer fmt.Println(kk, ":", vvv)
continue
}
seenFoo = true
fmt.Println(k, ":", vv)
}
}
func main() {
fromSlice()
fromEmpty()
sliceOfObjects()
intoMap()
}
// Output:
// 0 : foo
// 1 : bar
// 0 : foo
// 1 : bar
// 0 : map[foo:foo]
// 1 : map[bar:bar]
// foo : foo
// bar : bar

62
_test/addr5.go Normal file
View File

@@ -0,0 +1,62 @@
package main
import (
"encoding/json"
"fmt"
"net/url"
)
func main() {
body := []byte(`{
"BODY_1": "VALUE_1",
"BODY_2": "VALUE_2",
"BODY_3": null,
"BODY_4": {
"BODY_1": "VALUE_1",
"BODY_2": "VALUE_2",
"BODY_3": null
},
"BODY_5": [
"VALUE_1",
"VALUE_2",
"VALUE_3"
]
}`)
values := url.Values{}
var rawData map[string]interface{}
err := json.Unmarshal(body, &rawData)
if err != nil {
fmt.Println("can't parse body")
return
}
for key, val := range rawData {
switch val.(type) {
case string, bool, float64:
values.Add(key, fmt.Sprint(val))
case nil:
values.Add(key, "")
case map[string]interface{}, []interface{}:
jsonVal, err := json.Marshal(val)
if err != nil {
fmt.Println("can't encode json")
return
}
values.Add(key, string(jsonVal))
}
}
fmt.Println(values.Get("BODY_1"))
fmt.Println(values.Get("BODY_2"))
fmt.Println(values.Get("BODY_3"))
fmt.Println(values.Get("BODY_4"))
fmt.Println(values.Get("BODY_5"))
}
// Output:
// VALUE_1
// VALUE_2
//
// {"BODY_1":"VALUE_1","BODY_2":"VALUE_2","BODY_3":null}
// ["VALUE_1","VALUE_2","VALUE_3"]

16
_test/alias1.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import "fmt"
type MyT T
type T struct {
Name string
}
func main() {
fmt.Println(MyT{})
}
// Output:
// {}

10
_test/and3.go Normal file
View File

@@ -0,0 +1,10 @@
package main
var a = true && true
func main() {
println(a)
}
// Output:
// true

14
_test/append0.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
func f(a []int, b int) interface{} { return append(a, b) }
func main() {
a := []int{1, 2}
r := f(a, 3)
fmt.Println(r.([]int))
}
// Output:
// [1 2 3]

15
_test/append1.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"bufio"
"bytes"
)
func main() {
s := bufio.NewScanner(bytes.NewReader([]byte("Hello\nTest\nLine3")))
s.Scan()
println(string(append(s.Bytes(), []byte(" World")...)))
}
// Output:
// Hello World

15
_test/append2.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"bufio"
"bytes"
)
func main() {
s := bufio.NewScanner(bytes.NewReader([]byte("Hello\nTest\nLine3")))
s.Scan()
println(string(append(s.Bytes(), " World"...)))
}
// Output:
// Hello World

14
_test/append3.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
func main() {
a := []int{1, 2}
b := [2]int{3, 4}
fmt.Println(append(a, b[:]...))
fmt.Println(append(a, []int{5, 6}...))
}
// Output:
// [1 2 3 4]
// [1 2 5 6]

12
_test/append4.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
a := []*int{}
a = append(a, nil)
fmt.Println(a)
}
// Output:
// [<nil>]

128
_test/assert0.go Normal file
View File

@@ -0,0 +1,128 @@
package main
import (
"fmt"
"time"
)
type MyWriter interface {
Write(p []byte) (i int, err error)
}
type DummyWriter interface {
Write(p []byte) (i int, err error)
}
type TestStruct struct{}
func (t TestStruct) Write(p []byte) (n int, err error) {
return len(p), nil
}
func usesWriter(w MyWriter) {
n, _ := w.Write([]byte("hello world"))
fmt.Println(n)
}
type MyStringer interface {
String() string
}
type DummyStringer interface {
String() string
}
func usesStringer(s MyStringer) {
fmt.Println(s.String())
}
func main() {
// TODO(mpl): restore when we can deal with empty interface.
// var t interface{}
var t DummyWriter
t = TestStruct{}
var tw MyWriter
var ok bool
tw, ok = t.(MyWriter)
if !ok {
fmt.Println("TestStruct does not implement MyWriter")
} else {
fmt.Println("TestStruct implements MyWriter")
usesWriter(tw)
}
n, _ := t.(MyWriter).Write([]byte("hello world"))
fmt.Println(n)
// not redundant with the above, because it goes through a slightly different code path.
if _, ok := t.(MyWriter); !ok {
fmt.Println("TestStruct does not implement MyWriter")
return
} else {
fmt.Println("TestStruct implements MyWriter")
}
// TODO(mpl): restore
/*
t = 42
foo, ok := t.(MyWriter)
if !ok {
fmt.Println("42 does not implement MyWriter")
} else {
fmt.Println("42 implements MyWriter")
}
_ = foo
if _, ok := t.(MyWriter); !ok {
fmt.Println("42 does not implement MyWriter")
} else {
fmt.Println("42 implements MyWriter")
}
*/
// var tt interface{}
var tt DummyStringer
tt = time.Nanosecond
var myD MyStringer
myD, ok = tt.(MyStringer)
if !ok {
fmt.Println("time.Nanosecond does not implement MyStringer")
} else {
fmt.Println("time.Nanosecond implements MyStringer")
usesStringer(myD)
}
fmt.Println(tt.(MyStringer).String())
if _, ok := tt.(MyStringer); !ok {
fmt.Println("time.Nanosecond does not implement MyStringer")
} else {
fmt.Println("time.Nanosecond implements MyStringer")
}
// TODO(mpl): restore
/*
tt = 42
bar, ok := tt.(MyStringer)
if !ok {
fmt.Println("42 does not implement MyStringer")
} else {
fmt.Println("42 implements MyStringer")
}
_ = bar
if _, ok := tt.(MyStringer); !ok {
fmt.Println("42 does not implement MyStringer")
} else {
fmt.Println("42 implements MyStringer")
}
*/
}
// Output:
// TestStruct implements MyWriter
// 11
// 11
// TestStruct implements MyWriter
// time.Nanosecond implements MyStringer
// 1ns
// 1ns
// time.Nanosecond implements MyStringer

88
_test/assert1.go Normal file
View File

@@ -0,0 +1,88 @@
package main
import (
"fmt"
"reflect"
"time"
)
type TestStruct struct{}
func (t TestStruct) String() string {
return "hello world"
}
type DummyStringer interface{
String() string
}
func main() {
aType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
var t interface{}
t = time.Nanosecond
s, ok := t.(fmt.Stringer)
if !ok {
fmt.Println("time.Nanosecond does not implement fmt.Stringer")
return
}
fmt.Println(s.String())
fmt.Println(t.(fmt.Stringer).String())
bType := reflect.TypeOf(time.Nanosecond)
fmt.Println(bType.Implements(aType))
// not redundant with the above, because it goes through a slightly different code path.
if _, ok := t.(fmt.Stringer); !ok {
fmt.Println("time.Nanosecond does not implement fmt.Stringer")
return
} else {
fmt.Println("time.Nanosecond implements fmt.Stringer")
}
t = 42
foo, ok := t.(fmt.Stringer)
if !ok {
fmt.Println("42 does not implement fmt.Stringer")
} else {
fmt.Println("42 implements fmt.Stringer")
return
}
_ = foo
if _, ok := t.(fmt.Stringer); !ok {
fmt.Println("42 does not implement fmt.Stringer")
} else {
fmt.Println("42 implements fmt.Stringer")
return
}
// TODO(mpl): restore when fixed
// var tt interface{}
var tt DummyStringer
tt = TestStruct{}
ss, ok := tt.(fmt.Stringer)
if !ok {
fmt.Println("TestStuct does not implement fmt.Stringer")
return
}
fmt.Println(ss.String())
fmt.Println(tt.(fmt.Stringer).String())
if _, ok := tt.(fmt.Stringer); !ok {
fmt.Println("TestStuct does not implement fmt.Stringer")
return
} else {
fmt.Println("TestStuct implements fmt.Stringer")
}
}
// Output:
// 1ns
// 1ns
// true
// time.Nanosecond implements fmt.Stringer
// 42 does not implement fmt.Stringer
// 42 does not implement fmt.Stringer
// hello world
// hello world
// TestStuct implements fmt.Stringer

View File

@@ -9,5 +9,5 @@ func main() {
fmt.Println(buf)
}
// Output
// Output:
// []

10
_test/assign10.go Normal file
View File

@@ -0,0 +1,10 @@
package main
func main() {
var a uint
a = 1 + 2
println(a)
}
// Output:
// 3

10
_test/assign11.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import "fmt"
func main() {
_, _, _ = fmt.Println("test")
}
// Error:
// 6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values

11
_test/assign12.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
a, b, c := fmt.Println("test")
println(a, b, c)
}
// Error:
// 6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values

19
_test/assign13.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import "fmt"
func getStr() string {
return "test"
}
func main() {
m := make(map[string]string, 0)
m["a"] = fmt.Sprintf("%v", 0.1)
m["b"] = string(fmt.Sprintf("%v", 0.1))
m["c"] = getStr()
fmt.Println(m)
}
// Output:
// map[a:0.1 b:0.1 c:test]

16
_test/assign14.go Normal file
View File

@@ -0,0 +1,16 @@
package main
var optionsG map[string]string = nil
var roundG = 30
func main() {
dummy := roundG
roundG = dummy + 1
println(roundG)
println(optionsG == nil)
}
// Output:
// 31
// true

11
_test/assign15.go Normal file
View File

@@ -0,0 +1,11 @@
package main
func main() {
var c chan<- struct{} = make(chan struct{})
var d <-chan struct{} = c
_ = d
}
// Error:
// _test/assign15.go:5:26: cannot use type chan<- struct{} as type <-chan struct{} in assignment

15
_test/assign16.go Normal file
View File

@@ -0,0 +1,15 @@
package main
type H struct {
bits uint
}
func main() {
h := &H{8}
var x uint = (1 << h.bits) >> 6
println(x)
}
// Output:
// 4

9
_test/assign8.go Normal file
View File

@@ -0,0 +1,9 @@
package main
func main() {
_ = 1
println(1)
}
// Output:
// 1

15
_test/assign9.go Normal file
View File

@@ -0,0 +1,15 @@
package main
type foo func(b int)
func boo(b int) { println("boo", b) }
func main() {
var f foo
f = boo
f(4)
}
// Output:
// boo 4

7
_test/b1/foo/foo.go Normal file
View File

@@ -0,0 +1,7 @@
package foo
import bar "github.com/traefik/yaegi/_test/b2/foo"
var Desc = "in b1/foo"
var Desc2 = Desc + bar.Desc

3
_test/b2/foo/foo.go Normal file
View File

@@ -0,0 +1,3 @@
package foo
var Desc = "in b2/foo"

4
_test/bad0.go Normal file
View File

@@ -0,0 +1,4 @@
println("Hello")
// Error:
// 1:1: expected 'package', found println

3
_test/baz-bat/baz-bat.go Normal file
View File

@@ -0,0 +1,3 @@
package baz
var Name = "baz-bat"

13
_test/bin2.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.Abs(-5))
}
// Output:
// 5

12
_test/bin3.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
str := "part1"
str += fmt.Sprintf("%s", "part2")
fmt.Println(str)
}
// Output:
// part1part2

18
_test/bin4.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"fmt"
"strings"
)
func Bar(s string) bool {
a := strings.HasPrefix("fas", "f")
b := strings.HasPrefix("aaaaa", "a")
a_and_b := strings.HasPrefix("fas", "f") && strings.HasPrefix("aaaaa", "a")
fmt.Println(a, b, a && b, a_and_b)
return a && b
}
func main() {
println(Bar("kung"))
}

15
_test/bin5.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"fmt"
"net"
)
func main() {
addr := net.TCPAddr{IP: net.IPv4(1, 1, 1, 1), Port: 80}
var s fmt.Stringer = &addr
fmt.Println(s.String())
}
// Output:
// 1.1.1.1:80

View File

@@ -0,0 +1,17 @@
package main
import (
"fmt"
"image"
)
func main() {
v := map[string]*image.Point{
"foo": {X: 3, Y: 2},
"bar": {X: 4, Y: 5},
}
fmt.Println(v["foo"], v["bar"])
}
// Output:
// (3,2) (4,5)

View File

@@ -0,0 +1,17 @@
package main
import (
"fmt"
"image"
)
func main() {
v := []*image.Point{
{X: 3, Y: 2},
{X: 4, Y: 5},
}
fmt.Println(v)
}
// Output:
// [(3,2) (4,5)]

16
_test/binstruct_slice0.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import (
"fmt"
"image"
)
func main() {
v := []image.Point{
{X: 3, Y: 2},
}
fmt.Println(v)
}
// Output:
// [(3,2)]

5
_test/c1/c1.go Normal file
View File

@@ -0,0 +1,5 @@
package c1
import "github.com/traefik/yaegi/_test/c2"
var C1 = c2.C2 + "x"

5
_test/c2/c2.go Normal file
View File

@@ -0,0 +1,5 @@
package c2
import "github.com/traefik/yaegi/_test/c1"
var C2 = c1.C1 + "Y"

19
_test/cap0.go Normal file
View File

@@ -0,0 +1,19 @@
package main
func f(a []int) interface{} {
return cap(a)
}
func g(a []int) int {
return cap(a)
}
func main() {
a := []int{1, 2}
println(g(a))
println(f(a).(int))
}
// Output:
// 2
// 2

12
_test/chan10.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "time"
func main() {
var tick <-chan time.Time = time.Tick(time.Millisecond)
_ = tick
println("success")
}
// Output:
// success

12
_test/chan8.go Normal file
View File

@@ -0,0 +1,12 @@
package main
func main() {
messages := make(chan bool)
go func() { messages <- true }()
println(<-messages && true)
}
// Output:
// true

20
_test/chan9.go Normal file
View File

@@ -0,0 +1,20 @@
package main
type Channel chan string
type T struct {
Channel
}
func send(c Channel) { c <- "ping" }
func main() {
t := &T{}
t.Channel = make(Channel)
go send(t.Channel)
msg := <-t.Channel
println(msg)
}
// Output:
// ping

59
_test/cli2.go Normal file
View File

@@ -0,0 +1,59 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
)
type T struct {
ln net.Listener
}
func (t *T) Close() {
t.ln.Close()
}
func client(uri string) {
resp, err := http.Get(uri)
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
func server(ln net.Listener, ready chan bool) {
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
var r1 *http.Request = r
fmt.Fprintln(w, "Welcome to my website!", r1.RequestURI)
})
go http.Serve(ln, nil)
ready <- true
}
func main() {
ln, err := net.Listen("tcp", "localhost:0")
t := &T{ln}
if err != nil {
log.Fatal(err)
}
defer t.Close()
// defer ln.Close()
ready := make(chan bool)
go server(ln, ready)
<-ready
client(fmt.Sprintf("http://%s/hello", ln.Addr().String()))
http.DefaultServeMux = &http.ServeMux{}
}
// Output:
// Welcome to my website! /hello

51
_test/cli4.go Normal file
View File

@@ -0,0 +1,51 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
)
type mw1 struct {
next http.Handler
}
func (m *mw1) ServeHTTP(rw http.ResponseWriter, rq *http.Request) {
m.next.ServeHTTP(rw, rq)
}
type mw0 struct{}
func (m *mw0) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Welcome to my website!")
}
func main() {
m0 := &mw0{}
m1 := &mw1{m0}
mux := http.NewServeMux()
mux.HandleFunc("/", m1.ServeHTTP)
server := httptest.NewServer(mux)
defer server.Close()
client(server.URL)
}
func client(uri string) {
resp, err := http.Get(uri)
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
// Output:
// Welcome to my website!

51
_test/cli5.go Normal file
View File

@@ -0,0 +1,51 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
)
type mw1 struct {
next http.Handler
}
func (m *mw1) ServeHTTP(rw http.ResponseWriter, rq *http.Request) {
m.next.ServeHTTP(rw, rq)
}
type mw0 struct{}
func (m *mw0) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Welcome to my website!")
}
func main() {
m0 := &mw0{}
m1 := &mw1{next: m0}
mux := http.NewServeMux()
mux.HandleFunc("/", m1.ServeHTTP)
server := httptest.NewServer(mux)
defer server.Close()
client(server.URL)
}
func client(uri string) {
resp, err := http.Get(uri)
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
// Output:
// Welcome to my website!

52
_test/cli6.go Normal file
View File

@@ -0,0 +1,52 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
)
type T struct {
http.ResponseWriter
}
type mw1 struct {
next http.Handler
}
func (m *mw1) ServeHTTP(rw http.ResponseWriter, rq *http.Request) {
t := &T{
ResponseWriter: rw,
}
x := t.Header()
fmt.Fprint(rw, "Welcome to my website!", x)
}
func main() {
m1 := &mw1{}
mux := http.NewServeMux()
mux.HandleFunc("/", m1.ServeHTTP)
server := httptest.NewServer(mux)
defer server.Close()
client(server.URL)
}
func client(uri string) {
resp, err := http.Get(uri)
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
// Output:
// Welcome to my website!map[]

18
_test/closure10.go Normal file
View File

@@ -0,0 +1,18 @@
package main
func main() {
foos := []func(){}
for i := 0; i < 3; i++ {
a, b := i, i
foos = append(foos, func() { println(i, a, b) })
}
foos[0]()
foos[1]()
foos[2]()
}
// Output:
// 3 0 0
// 3 1 1
// 3 2 2

22
_test/closure11.go Normal file
View File

@@ -0,0 +1,22 @@
package main
type T struct {
F func()
}
func main() {
foos := []T{}
for i := 0; i < 3; i++ {
a := i
foos = append(foos, T{func() { println(i, a) }})
}
foos[0].F()
foos[1].F()
foos[2].F()
}
// Output:
// 3 0
// 3 1
// 3 2

25
_test/closure12.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import "fmt"
type T struct {
F func()
}
func main() {
foos := []T{}
for i := 0; i < 3; i++ {
a := i
n := fmt.Sprintf("i=%d", i)
foos = append(foos, T{func() { println(i, a, n) }})
}
foos[0].F()
foos[1].F()
foos[2].F()
}
// Output:
// 3 0 i=0
// 3 1 i=1
// 3 2 i=2

10
_test/closure8.go Normal file
View File

@@ -0,0 +1,10 @@
package main
var f = func(a int) int { return 2 + a }
func main() {
println(f(3))
}
// Output:
// 5

18
_test/closure9.go Normal file
View File

@@ -0,0 +1,18 @@
package main
func main() {
foos := []func(){}
for i := 0; i < 3; i++ {
a := i
foos = append(foos, func() { println(i, a) })
}
foos[0]()
foos[1]()
foos[2]()
}
// Output:
// 3 0
// 3 1
// 3 2

9
_test/comp1.go Normal file
View File

@@ -0,0 +1,9 @@
package main
func main() {
var a interface{} = 1 < 2
println(a.(bool))
}
// Output:
// true

14
_test/comp2.go Normal file
View File

@@ -0,0 +1,14 @@
package main
type delta int32
func main() {
a := delta(-1)
println(a != -1)
println(a == -1)
}
// Output:
// false
// true

12
_test/complex1.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
var c complex128
c = 1
fmt.Printf("%T %v\n", c, c)
}
// Output:
// complex128 (1+0i)

12
_test/complex2.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
c := complex(1, 0)
c += 1
fmt.Printf("%T %v\n", c, c)
}
// Output:
// complex128 (2+0i)

11
_test/complex3.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
var s int = 1 + complex(1, 0)
fmt.Printf("%T %v\n", s, s)
}
// Output:
// int 2

13
_test/complex4.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import "fmt"
func f(a, b float64) interface{} { return complex(a, b) }
func main() {
a := f(3, 2)
fmt.Println(a.(complex128))
}
// Output:
// (3+2i)

14
_test/composite0.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
var a = &[]*T{}
type T struct{ name string }
func main() {
fmt.Println(a)
}
// Output:
// &[]

14
_test/composite1.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
var a = &[]*T{{}}
type T struct{ name string }
func main() {
fmt.Println((*a)[0])
}
// Output:
// &{}

14
_test/composite10.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
func main() {
a := []map[int]int{make(map[int]int)}
for _, b := range a {
fmt.Println(b)
}
}
// Output:
// map[]

15
_test/composite11.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"fmt"
"image/color"
)
func main() {
c := color.NRGBA64{1, 1, 1, 1}
fmt.Println(c)
}
// Output:
// {1 1 1 1}

19
_test/composite12.go Normal file
View File

@@ -0,0 +1,19 @@
package main
type A struct {
C D
}
type D struct {
E string
}
func main() {
a := A{}
a.C = D{"bb"}
println(a.C.E)
}
// Output:
// bb

19
_test/composite13.go Normal file
View File

@@ -0,0 +1,19 @@
package main
type A struct {
C D
}
type D struct {
E string
}
func main() {
a := A{}
a.C = D{E: "bb"}
println(a.C.E)
}
// Output:
// bb

15
_test/composite14.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import "fmt"
type T struct {
b []byte
}
func main() {
t := T{nil}
fmt.Println(t)
}
// Output:
// {[]}

52
_test/composite15.go Normal file
View File

@@ -0,0 +1,52 @@
package main
import (
"fmt"
)
func interfaceAsInts() {
var a interface{}
b := 2
c := 3
a = []int{b, c}
d, ok := a.([]int)
if !ok {
println("nope")
return
}
for _, v := range d {
fmt.Println(v)
}
}
func interfaceAsInterfaces() {
var a, b, c interface{}
b = 2
c = 3
a = []interface{}{b, c}
d, ok := a.([]interface{})
if !ok {
println("nope")
return
}
fmt.Println(d)
for _, v := range d {
fmt.Println(v)
}
}
func main() {
interfaceAsInts()
interfaceAsInterfaces()
}
// Output:
// 2
// 3
// [2 3]
// 2
// 3

16
_test/composite16.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import (
"fmt"
"net/url"
)
func main() {
body := url.Values{
"Action": {"none"},
}
fmt.Println(body)
}
// Output:
// map[Action:[none]]

30
_test/composite17.go Normal file
View File

@@ -0,0 +1,30 @@
package main
import (
"html/template"
)
var str = `{{ stringOr .Data "test" }}`
func main() {
_, err := template.New("test").
Funcs(template.FuncMap{
"stringOr": stringOr,
}).
Parse(str)
if err != nil {
println(err.Error())
return
}
println("success")
}
func stringOr(v, def string) string {
if v == "" {
return def
}
return v
}
// Output:
// success

14
_test/composite2.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
var a = &[]*T{{"hello"}}
type T struct{ name string }
func main() {
fmt.Println((*a)[0])
}
// Output:
// &{hello}

12
_test/composite3.go Normal file
View File

@@ -0,0 +1,12 @@
package main
func main() {
var err error
var ok bool
_, ok = err.(interface{ IsSet() bool })
println(ok)
}
// Output:
// false

Some files were not shown because too many files have changed in this diff Show More