Compare commits

...

119 Commits

Author SHA1 Message Date
Marc Vertes
fbee2baf9d interp: fix wrapping of returned closure passed to runtime
Fixes #1333.
2021-12-21 17:44:06 +01:00
Marc Vertes
2819b4167b interp: fix derivation of type of slice expression of binary object
Fixes #1328.
2021-12-20 15:46:05 +01:00
Marc Vertes
2af660cb1f interp: improve method resolution on embedded fields
The capability to dereference pointers has been added to
methodByName(), improving method lookup on binary values.

Wrapping to valueInterface is performed in a missing use case at
return of function calls. It was done in the nested call, but not
at assign.

Fixes #1330.
2021-12-20 15:06:11 +01:00
Marc Vertes
8323068414 interp: fix nested calls with variadic interfaces
Fixes #1326
2021-12-08 17:16:05 +01:00
Marc Vertes
5b62f9fdb6 interp: fix setting of interface value from nested function calls
Fixes #1320 and #1294.
2021-11-30 15:44:05 +01:00
Marc Vertes
4f66e3fe6c interp: fix type switch when the case type is an interpreted interface
Fixes #1315.

With this PR, the package gopkg.in/yaml.v3 works in yaegi (fixes #1296).
2021-11-26 12:24:07 +01:00
Marc Vertes
1335b4c64f stdlib: add wrappers for go/build/constraint package 2021-11-26 12:10:08 +01:00
Marc Vertes
da03c922ca interp: get rid of deprecated stdlib package ioutil
No functional change.
2021-11-26 11:58:07 +01:00
Marc Vertes
9620116c30 interp: replace value.Type().Kind() by value.Kind()
No functional change. Just simpler and faster.
2021-11-26 11:42:07 +01:00
Marc Vertes
dd7197f2a2 interp: fix assign of multiple return function call
A runtime builtin assignFromCall is added to handle multiple values returned at once. It is necessary if some of the values require to be set to interface values in the caller space, which is performed by reflect.Set in assignFromCall.
 
Fixes #1311.
2021-11-19 15:30:05 +01:00
Marc Vertes
9214806342 interp: fix populating array of interfaces
Fixes #1308.
2021-11-09 11:26:11 +01:00
Marc Vertes
348e713a8e interp: avoid collision between type and variable names in assign
Fixes #1306
2021-11-09 11:14:09 +01:00
Marc Vertes
cb81fe41ab interp: fix type processing to support multiple recursive fields
Fixes #1304
2021-11-08 20:46:12 +01:00
Marc Vertes
a876bb3673 interp: virtualize environment in restricted mode
In restricted mode, replace environment related symbols in
stdlib os package by a version which operates on a private copy
per interpreter context.

It allows to have concurrent interpreters in the same process
operating each in their own environment without affecting each
other or the host.

If unrestricted opt is set, this behaviour is disabled, and the
default symbols from stdlib are used.

Note also that no modification is done for syscall package, as it
should be not used in restricted mode.
2021-11-08 09:58:10 +01:00
Marc Vertes
afa46daccd interp: fix assignment to a dereferenced struct pointer
disable the optimization of skipping assign operation in that case,
as this step is necessary in case of writing to a pointer.

Fixes #1300.
2021-11-02 15:56:13 +01:00
Marc Vertes
3c00da291e stdlib: add wrappers for standard lib runtime/metrics package
This package was forgotten. No reason to not include it.
2021-11-02 15:20:06 +01:00
Marc Vertes
c847481184 interp: fix comparison operators in if statement
At generation of operator closures, the comparison expression
was hard-coded instead of being derived from the operator name,
leading to a wrong result.

Fixes #1297.
2021-11-02 15:02:07 +01:00
Marc Vertes
f46ef67180 interp: fix computation of ellipsis array length
Fixes #1287.
2021-10-20 14:36:05 +02:00
Marc Vertes
229ddfdae1 interp: fix use of builtins in type definitions
Make len() and cap() work on pointers. Preserve scope in case of
nested calls of cfg.

Fixes #1285.
2021-10-18 10:50:14 +02:00
Marc Vertes
aa7f0849e3 interp: fix goto to a label with no statement
Fixes #1288.
2021-10-18 10:36:12 +02:00
Bai-Yingjie
7617b8a090 interp: add args option to let each interpreter have seperate args
In some cases, we use many yaegi instances in one process, each interpreter will expect its own os.Args. This is done in interp.go as an option in interp.Options besides Stdin Stdout and Stderr.
2021-10-11 16:58:07 +02:00
Marc Vertes
4e06abe002 interp: fix unsafe2 to work on 32 bits architectures
Fixes #1279.
2021-10-11 11:38:12 +02:00
Bai-Yingjie
b1a758dd5a extract: add an option to be able to set build tag to the created file
Add a tag option in the extract program to optionally give an opportunity to tailor some packages in for example the stdlib, for people who is interested in keeping the final binary size as smaller as possible.
Below go generate
```
//go:generate ../cmd/extract/extract -name stdlib -tag stdmime mime mime/multipart mime/quotedprintable
```
produces a header to stdlib/mime-multipart.go
```
// Code generated by 'yaegi extract mime/multipart'. DO NOT EDIT.

// +build go1.16,!go1.17,stdmime
```
2021-10-11 10:50:11 +02:00
Marc Vertes
5bf4daef2d interp: fix type check of methods with a receiver of interface kind
Fixes #1280.
2021-10-08 17:44:09 +02:00
Marc Vertes
e56db3b82e interp: improve interface wrappers when used by reflect
When an interpreter type implementing an interface is
used by the runtime, the runtime can extract its type
and create new values using reflect, and call methods
on it. The problem is that there will be no interpreted
method counterpart in this case, which makes wrapper panic.

Allow the String() method wrapper to always succeed and
return an empty string if no interpreted method is present.

This allows scripts to define custom flag.Value types on
which the runtime internally instantiates values using
reflect (see isZeroValue in Go src/flag/flag.go).

This workaround could be generalized to all wrappers if
necessary. At this moment, it is convenient to keep the
default behavior of expecting instantiated interpreter
methods, in order to catch interpreter bugs related to
interfaces.

Fixes #1276.
2021-10-08 15:56:06 +02:00
Marc Vertes
d3bbe01d5c interp: improve support of composed interfaces
Fixes #1260.
2021-10-07 16:28:05 +02:00
Nicholas Wiersma
286d6c6359 interp: handle recursive and incomplete seen types in nodeType
This comes from experiments looking into #1259 where incomplete twice seen types are marked as complete. To mitigate the problem instead of a map of seen types in `nodeType` a slice is used as a cheap way to keep track of our current path through the node tree.
2021-09-27 10:20:13 +02:00
Nicholas Wiersma
84424b52bc interp: handle alias of an alias
When dealing with an alias of an alias, the actual underlying type of the source alias should be used.
2021-09-27 10:08:11 +02:00
Marc Vertes
98c2dcd3e5 interp: fix interface wrapper for struct types
This change fixes a regression introduced by PR #1192 in a program using
https://github.com/NYTimes/gziphandler which defines several types
implementing stdlib interfaces. We do not implement a wrapper
if we see that a type already implements an interface, except that
it can be falsly reported by reflect in case of a struct with
embedded interface field. We need to force the wrapper generation
in this case.
The problem occurs only for wrappers on struct, not on pointers or
other indirection types.
2021-09-24 13:20:12 +02:00
Ethan Reesor
808f0bde9d interp: add a function to directly compile Go AST
Adds CompileAST, which can be used to compile Go AST directly. This
allows users to delegate parsing of source to their own code instead of
relying on the interpreter.

CLoses #1251
2021-09-23 12:34:12 +02:00
Nicholas Wiersma
c5c6012947 interp: support type spec assign
This supports type spec assign types which disallows the attachment of methods onto the alias type as per the Go spec.

Fixes #1154
2021-09-23 12:16:11 +02:00
Nicholas Wiersma
836060c8ad interp: allow GTA revisit for unresolved define statements
When a define statement relies on a selector or type that may exist in another file it should revisit once GTA is complete. This allows that revisit.

**Note:** In order to keep the original GTA error for the define statement, so the error received is correct and meaningful, I have added a node `meta` property. I decided to make it generic as it may be useful in future. There may be a better way to stash errors across the GTA runs and am open to suggestion here.

Fixes #1253
2021-09-20 12:04:06 +02:00
Nicholas Wiersma
7a54353c7b chore: update linter to v1.42.1
* chore: update linter to v1.42.1

* fix: linter issues
2021-09-20 10:18:14 +02:00
Marc Vertes
b591ba0e78 interp: do not export RealFS, used internally only 2021-09-15 16:22:07 +02:00
Nicholas Wiersma
5af51aefe6 interp: fix type selector precedence
The current `nodeType` selector precedence is heavy handed in favour of package type. It seems to often create `typeSym` symbols as variable types in the scope will never be found. To fix this if the ancestor node is a field expression, the package type is searched for. After this, if the type is still `nil` the normal scope is searched using `nodeType2`.

Fixes #1158
2021-09-15 10:42:08 +02:00
mpl
e7c0f68bab interp: fix Clone documentation 2021-09-14 12:30:13 +02:00
Marc Vertes
bd9a6a4f8a interp: improve processing of recursive types
Make sure to keep always a single copy of incomplete type structures.
Remove remnants of recursive types processing.

Now `import "go.uber.org/zap"` works again (see #1172), fixing regressions
introduced since #1236.
2021-09-13 18:24:10 +02:00
Nicholas Wiersma
3eb2c79fd8 interp: fix nil funcs in composite literals
When a nil are used in a func composite literal, the nil type is a `func` not a `*node`. This handles this case.

Fixes #1249
2021-09-13 16:32:12 +02:00
Nicholas Wiersma
4653d87298 interp: types should not recover data for aliases
When `nodeType` recovers names and methods, it can overwrite the data if the type is an aliasT. When aliasing a type, do not recover the methods, this will be done in the GTA typeSpec pass.

Related to #1158
2021-09-06 18:24:04 +02:00
Nicholas Wiersma
45d569c215 interp: fix parsing of late binding consts
When a const is late binding and specified with a type, the GTA defineStmt was creating the symbol with the current scopes `iota` which is incorrect. The symbol should be created with the source nodes `rval`.

Related to #1158
2021-09-06 17:30:12 +02:00
Nicholas Wiersma
c33caeb573 interp: improve handling of wrapped interface values
This test (assert2.go) display 2 separate issues:
1. assert2.go L28: Type assert tries to set an `interface{}` to a `valueInterface`. The typing here is complex, we have a valueT(strings.Builder) wrapped in a ptrT wrapped in a src iface wrapped in a valueT(interface{}). Type assert fails to realise that the `valueT` `interface{}` is wrapping the `valueInterface`.
2. assert2.go L29: `genValueBinMethodOnInterface` does not try and get the bin method, as the `typ.node` (`ptrT` or a `valueT`(`string.Builder`)) is set. In this case the src iface is called with a receiver argument. To fix this the method is looked for first if possible, and only if not found does it fall back to the `defaultGen`.

Fixes #1227
2021-09-06 17:16:11 +02:00
Ethan Reesor
91a55cc4c5 interp: add debug interface
Adds an interface to `interp` that can be used to build an interactive debugger, such as those used by IDEs.

Closes #1188

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

Example, using a Debug Adapter implementation with VSCode:

![image](https://user-images.githubusercontent.com/879055/128620736-94b6efde-2e5f-43ad-82c9-d919c3fe401f.png)
2021-09-06 15:32:10 +02:00
Nicholas Wiersma
05f08d776a interp: complete type constructors
This completes the types constructors, cleaning up `nodeType`.
2021-09-01 14:46:08 +02:00
Nicholas Wiersma
d2569a85a6 interp: fix default types for runes
When using an untyped rune in an interface, the default type was blindly untyping it. This fixes this issue.

Fixes #1238
2021-08-31 12:32:10 +02:00
Nicholas Wiersma
772cd68fea interp: make use of type constructors
It was initially assumed that `nodeType` needed to rebuild the type from scratch, but this is not the case anymore. The existing type constructors are now used in `nodeType` to make it more readable. In doing this some bugs in type strings were found and fixed, along with adding the real package name to the type.

As `ptrOf` is now the only place that pointer types are constructed, it is feasible to cache the pointer type on the value type. To ensures that we have a consistent pointer type for any value type.
2021-08-31 10:34:12 +02:00
Nicholas Wiersma
4af992bccb interp: create real recursive types with unsafe type swapping
As the unsafe and pointer methods in `reflect` are to be depreciated, and seeing no replacement functions, it is now forced that some unsafe is needed to replace this as when and interface is dereferenced it is made unsettable by reflect.

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

**Note:** While the struct field type is swapped for the real type, the type string is not changed. Due to this, unsafe will recreate the same type.
2021-08-30 18:38:12 +02:00
Nicholas Wiersma
da922ce90b interp: build type strings on the fly
This adds `itype.str` which is a string representation of the type built when the type is built. The goal is to make type comparison simpler and centralise the creation of types just to constructors and `nodeType`. `nodeType` continues to build types in parts so to reuse underlying types better.
2021-08-27 19:44:05 +02:00
Aloïs Micard
7b77b0fa22 test: only enable race detector when supported
Closes: #1228
2021-08-27 15:50:13 +02:00
Marc Vertes
b7f9a39eff interp: fix support of 32 bits and big-endian arch
Force recompute of bits.UintSize, make related tests portable.

Fixes #1230.
2021-08-27 14:54:05 +02:00
Marc Vertes
d2b25a7426 interp: fix append with 1 argument
Fixes #1224.
2021-08-24 12:16:08 +02:00
Johnny
b5bf4ef31a interp: allow for reading source files from diverse filesystems
Make use of fs.FS (new to go 1.16) to allow for reading source files from diverse filesystems (local, embed, custom).

* `Options` has a new field `SourcecodeFilesystem fs.FS` so users can supply their own read-only filesystem containing source code.
* Defaults to the local filesystems (via `RealFS` - a thin `os.Open` wrapper complying with `fs.FS`) so regular users should see no change in behaviour.
* When no filesystem is available (e.g. WASM, or if you want to embed files to retain single binary distribution) an alternative filesystem is preferable to using `Eval(string)` as that requires the stringy code to be a single file monolith instead of multiple files. By using an `fs.FS` we can use `EvalPath()` and gain the ability to handle multiple files and packages.
* You can make use of embed filesystems (https://pkg.go.dev/embed) and custom filesystems obeying the `fs.FS` interface (I use one for http served zip files when targeting wasm as there is no local filesystem on wasm). Tests can make use of `fstest.Map`.
* NOTE: This does NOT affect what the running yaegi code considers its local filesystem, this is only for the interpreter finding the source code.

See `example/fs/fs_test.go` for an example.

Fixes #1200.
2021-08-19 11:28:13 +02:00
Nicholas Wiersma
a69b9bc2dc stdlib: support go1.17 unsafe functions
This adds support for go1.17 `unsafe.Add` and `unsafe.Slice`.
2021-08-19 10:38:05 +02:00
Marc Vertes
b84278dcc6 stdlib: remove wrapper of runtime/cgo
Temporarily removing this wrapper which causes a failure
on freebsd system at build.

Fixes #1221.
2021-08-17 16:38:12 +02:00
Nicholas Wiersma
32cbcfb412 feat: update stdlib mapping for go1.17
* Drop go1.15
* Generate go1.17
* Update minimum extract version
* Update the CI config
2021-08-17 11:42:07 +02:00
Nicholas Wiersma
5c73f30f36 interp: fix handling of forward function declaration
Set node address in `val` field at creation of `funcDecl` node so it can be used correctly at closure generation, even in the case of forward function declarations, where the value was zero.

Fixes #1214
2021-08-16 16:24:05 +02:00
Nicholas Wiersma
5cc6fa42e4 feat: fix zero instance issue
When calling a function, if the input param is a "zero" instance, it is not set on the input. This is an issue where the param is an `interface{}` as a `nil` value is set instead of the zero value.

The actual solution for this is to remove the `if !val.IsZero()`, this however runs into an issue on `_test/struct48.go` where we have a zero recursive struct instance (`*interface{}`) and we have no way to get its real type. Should a way be figured out to keep tabs on the original type, the `if` can go away, and in the zero case of `genValueRecursiveInterfacePtrValue`, the actual zero type can be returned. 

Fixes #1215
2021-08-16 10:34:09 +02:00
Marc Vertes
37fe3422d8 interp: improve handling of interface struct field
Wrap non empty interface value  in struct field, to allow method
lookup.

Fixes #1208.
2021-08-06 12:16:10 +02:00
Dan Kortschak
d4e25f0259 interp: fix package lookup for type analysis of local types
Fixes #1203.
2021-08-02 12:14:11 +02:00
Marc Vertes
32ff3fb9b0 interp: fix handling of interface values in variadic calls
Fixes #1205.
2021-07-29 14:36:10 +02:00
Marc Vertes
b41fa6eb9d stdlib: add missing wrappers of io/fs for go1.16
Fixes #1195
2021-07-27 10:58:06 +02:00
Marc Vertes
c80c605ab9 interp: support wrapping of nested interfaces
Add getConcreteType to retrieve the concrete type of a nested interface
value implementing a specific interface for which a wrapper exists.

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

Fixes #1187.
2021-07-26 19:12:11 +02:00
Marc Vertes
bf843fc09e interp: fix handling returned func values
Fixes #1202.
2021-07-26 17:42:05 +02:00
Marc Vertes
a913a4ea8b interp: fix handling map of interfaces
Map handling builtins getIndexMap and rangeMap had some leftover
code of previous way of emulating interfaces, which was modified
following changes in #1017.

Specific code for interfaceT is removed, as not necessary anymore.
Map builtins are now simplified and more robust.

Fixes #1189.
2021-07-26 17:30:12 +02:00
Marc Vertes
2f8493c405 interp: fix map update by assign operators
When operating on map elements, result of assign operators were not
written to the map entry. Now check if the destination of an assign
operator is in a map, and if so, set the result to it.

Fixes #1194.
2021-07-21 11:44:04 +02:00
Marc Vertes
c7fcfa8534 interp: fix interface wrapper generation
Add early detection of cases where no wrapper is necessary because
the value type already implements the target interface.

It should both increase performances by avoiding the wrapper overhead,
and fix errors due to replacing valid values by incomplete wrappers,
caused by the presence of private methods in the interface definition,
as in #1191.

Fixes #1191.
2021-07-19 15:38:11 +02:00
Ludovic Fernandez
aa012b992e chore: update linter
- update golangci-lint to v1.41.1
- fix GitHub action cache configuration
2021-07-17 12:14:06 +02:00
Marc Vertes
538182e12c interp: fix append of values to an array of interface objects
Interface wrappers were not properly generated.

Fixes #1185
2021-07-15 11:38:12 +02:00
Marc Vertes
13d554acbe interp: fix receiver for exported method objects
When a function variable is assigned from an exported method,
make sure the receiver is updated from the coresponding symbol.

Fixes #1182.
2021-07-13 11:00:14 +02:00
Marc Vertes
4fcf90edae interp: fix swap assign with extra operation
The optimization in unary operaror bypasses the necessary temporary
variable in that case and must be disabled.

Fixes #1181.
2021-07-12 18:00:09 +02:00
Marc Vertes
fc970799a1 interp: add support of interface wrappers to type assertions
Store the interpreter value of the interface object to wrap as
a field called IValue, at offset 0 in wrapper structures.

Update extract to include IValue field.

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

Fixes #1166.
2021-07-12 17:10:13 +02:00
Marc Vertes
78d7e85352 interp: fix method resolution on pointer to binary values
In that case, the value must be derefenced before extracting
the method by index, otherwise an incorrect method is returned.

Fixes #1167.
2021-07-09 12:08:14 +02:00
Marc Vertes
c503855262 interp: fix handling of interface value in forwarding return calls
Special wrapping of interface value at return is no longer necessary and
must be avoided now.

Fixes #1179.
2021-07-08 16:04:08 +02:00
Marc Vertes
77acfb4593 interp: fix type checking of address of multi dimension array
Fixes #1177.
2021-07-08 12:40:09 +02:00
Marc Vertes
f6d0cf95fd interp: fix array declaration with a typed constant size
In parsing array type declaration, The type check of array size was
restricted to `int`. Broaden the test to accept any valid integer
kind.

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

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

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

Fixes #1163.
2021-07-06 12:12:05 +02:00
Daniel Tomcej
bd2cb06789 Update README.md
This PR:

- Updates the Readme to reflect the current supported Go versions 😄
2021-07-06 08:16:13 +02:00
Ludovic Fernandez
3c5682150d chore: improve issue templates
- use new GitHub issue forms
- update readme badges and links
2021-07-02 11:00:08 +02:00
Marc Vertes
e32b2ab6bd interp: improve handling of interface values
In selector resolution, struct field matching now precedes
method matching. Before struct field matching could be skipped
in case of a matching method, which is incorrect, as demontrated
by _test/issue-1156.go.

Field lookup has been fixed to operate on recursive structures.

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

LookupBinField has been fixed to skip non struct values.

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

Fixes #1156.
2021-06-24 16:20:13 +02:00
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
653 changed files with 20457 additions and 4747 deletions

View File

@@ -1,27 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
---
The following program `sample.go` triggers a panic:
```go
package main
func main() {
// add a sample
}
```
Expected result:
```console
$ go run ./sample.go
// output
```
Got:
```console
$ yaegi ./sample.go
// output
```

66
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,66 @@
name: Bug Report
description: Create a report to help us improve
body:
- type: markdown
attributes:
value: |
⚠️ Make sure to browse the opened and closed issues before submit your issue.
- type: textarea
id: sample
attributes:
label: "The following program `sample.go` triggers an unexpected result"
value: |
package main
func main() {
// add a sample
}
render: go
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected result
description: |-
```console
$ go run ./sample.go
// output
```
placeholder: $ go run ./sample.go
render: console
validations:
required: true
- type: textarea
id: got
attributes:
label: Got
description: |-
```console
$ yaegi ./sample.go
// output
```
placeholder: $ yaegi ./sample.go
render: console
validations:
required: true
- type: input
id: version
attributes:
label: Yaegi Version
description: Can be a tag or a hash.
validations:
required: true
- type: textarea
id: additional
attributes:
label: Additional Notes
description: Use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown) if needed.
validations:
required: false

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Questions
url: https://community.traefik.io/c/yaegi
about: If you have a question, or are looking for advice, please post on our discussions forum!
- name: Documentation
url: https://pkg.go.dev/github.com/traefik/yaegi
about: Please take a look to our documenation.

View File

@@ -1,19 +0,0 @@
---
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? -->

View File

@@ -0,0 +1,32 @@
name: Feature request
description: Propose a change to Yaegi
body:
- type: markdown
attributes:
value: |
⚠️ Make sure to browse the opened and closed issues before submit your issue.
- type: textarea
id: proposal
attributes:
label: Proposal
description: Write your feature request in the form of a proposal to be considered for implementation.
validations:
required: true
- type: textarea
id: background
attributes:
label: Background
description: Describe the background problem or need that led to this feature request.
validations:
required: true
- type: textarea
id: workarounds
attributes:
label: Workarounds
description: Are there any current workarounds that you're using that others in similar positions should know about?
validations:
required: true

View File

@@ -17,15 +17,14 @@ jobs:
strategy:
matrix:
go-version: [ 1.15, 1.16 ]
# os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, windows-latest]
go-version: [ 1.16, 1.17 ]
os: [ubuntu-latest, macos-latest, windows-latest]
include:
- os: ubuntu-latest
go-path-suffix: /go
# - os: macos-latest
# go-path-suffix: /go
- os: macos-latest
go-path-suffix: /go
- os: windows-latest
go-path-suffix: \go
@@ -46,11 +45,16 @@ jobs:
- name: Cache Go modules
uses: actions/cache@v2
with:
# In order:
# * Module download cache
# * Build cache (Linux)
# * Build cache (Mac)
# * Build cache (Windows)
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)
~/go/pkg/mod
~/.cache/go-build
~/Library/Caches/go-build
%LocalAppData%\go-build
key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-${{ matrix.go-version }}-go-

View File

@@ -7,8 +7,8 @@ on:
pull_request:
env:
GO_VERSION: 1.16
GOLANGCI_LINT_VERSION: v1.36.0
GO_VERSION: 1.17
GOLANGCI_LINT_VERSION: v1.42.1
jobs:
@@ -45,7 +45,7 @@ jobs:
needs: linting
strategy:
matrix:
go-version: [ 1.15, 1.16 ]
go-version: [ 1.16, 1.17 ]
steps:
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v2
@@ -75,7 +75,7 @@ jobs:
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/yaegi
strategy:
matrix:
go-version: [ 1.15, 1.16 ]
go-version: [ 1.16, 1.17 ]
steps:
- name: Set up Go ${{ matrix.go-version }}

View File

@@ -6,7 +6,7 @@ on:
- v[0-9]+.[0-9]+*
env:
GO_VERSION: 1.16
GO_VERSION: 1.17
jobs:

View File

@@ -23,13 +23,16 @@
[linters]
enable-all = true
disable = [
"maligned",
"golint", # deprecated
"scopelint", # deprecated
"interfacer", # deprecated
"maligned", # deprecated
"lll",
"gas",
"dupl",
"prealloc",
"scopelint",
"gocyclo",
"cyclop",
"gochecknoinits",
"gochecknoglobals",
"wsl",
@@ -49,6 +52,7 @@
"exhaustivestruct",
"forbidigo",
"ifshort",
"forcetypeassert",
"errorlint", # TODO: must be reactivate before fixes
]
@@ -59,8 +63,11 @@
exclude = []
[[issues.exclude-rules]]
path = "interp/.+_test\\.go"
path = ".+_test\\.go"
linters = ["goconst"]
[[issues.exclude-rules]]
path = ".+_test\\.go"
text = "var-declaration:"
[[issues.exclude-rules]]
path = "interp/interp.go"
@@ -68,6 +75,9 @@
[[issues.exclude-rules]]
path = "interp/interp.go"
text = "`out` can be `io.Writer`"
[[issues.exclude-rules]]
path = "interp/interp.go"
text = "`Panic` should conform to the `XxxError` format"
[[issues.exclude-rules]]
path = "interp/interp_eval_test.go"
linters = ["thelper"]

View File

@@ -3,9 +3,9 @@
</p>
[![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)
[![Build Status](https://github.com/traefik/yaegi/actions/workflows/main.yml/badge.svg)](https://github.com/traefik/yaegi/actions/workflows/main.yml)
[![GoDoc](https://godoc.org/github.com/traefik/yaegi?status.svg)](https://pkg.go.dev/mod/github.com/traefik/yaegi)
[![Discourse status](https://img.shields.io/discourse/https/community.traefik.io/status?label=Community&style=social)](https://community.traefik.io/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.
@@ -18,7 +18,7 @@ It powers executable Go scripts and plugins, in embedded interpreters or interac
* Works everywhere Go works
* All Go & runtime resources accessible from script (with control)
* Security: `unsafe` and `syscall` packages neither used nor exported by default
* Support Go 1.13 and Go 1.14 (the latest 2 major releases)
* Support Go 1.16 and Go 1.17 (the latest 2 major releases)
## Install
@@ -186,7 +186,7 @@ Beside the known [bugs] which are supposed to be fixed in the short term, there
[Apache 2.0][License].
[specs]: https://golang.org/ref/spec
[docs]: https://godoc.org/github.com/traefik/yaegi
[docs]: https://pkg.go.dev/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

View File

@@ -6,16 +6,18 @@ const (
zero = iota
one
two
three
)
func main() {
a := [...]string{
zero: "zero",
one: "one",
two: "two",
three: "three",
three + 2: "five",
}
fmt.Printf("%v %T\n", a, a)
}
// Output:
// [zero one two] [3]string
// [zero one three five] [6]string

View File

@@ -22,6 +22,12 @@ func main() {
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:
@@ -31,3 +37,5 @@ func main() {
// 10
// 11
// 12
// 13
// hello

View File

@@ -57,7 +57,7 @@ func main() {
fmt.Println(err, vvv)
}
// Ouput:
// Output:
// <nil> {work bob@work.com}
// <nil> {work bob@work.com}
// <nil> {work bob@work.com}

View File

@@ -103,7 +103,7 @@ func main() {
intoMap()
}
// Ouput:
// Output:
// 0 : foo
// 1 : bar
// 0 : foo

18
_test/alias2.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import "fmt"
func (t MyT) Test() string {
return "hello"
}
type MyT int
func main() {
t := MyT(1)
fmt.Println(t.Test())
}
// Output:
// hello

22
_test/alias3.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import "github.com/traefik/yaegi/_test/alias3"
var globalT *T
func init() {
globalT = &T{A: "test"}
}
type T alias3.T
func (t *T) PrintT() {
(*alias3.T)(t).Print()
}
func main() {
globalT.PrintT()
}
// Output:
// test

9
_test/alias3/alias3.go Normal file
View File

@@ -0,0 +1,9 @@
package alias3
type T struct {
A string
}
func (t *T) Print() {
println(t.A)
}

27
_test/alias4.go Normal file
View File

@@ -0,0 +1,27 @@
package main
import (
"fmt"
"net/http"
)
type A http.Header
func (a A) Test1() {
fmt.Println("test1")
}
type B A
func (b B) Test2() {
fmt.Println("test2")
}
func main() {
b := B{}
b.Test2()
}
// Output:
// test2

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>]

37
_test/assert2.go Normal file
View File

@@ -0,0 +1,37 @@
package main
import (
"strings"
"sync"
)
// Defined an interface of stringBuilder that compatible with
// strings.Builder(go 1.10) and bytes.Buffer(< go 1.10)
type stringBuilder interface {
WriteRune(r rune) (n int, err error)
WriteString(s string) (int, error)
Reset()
Grow(n int)
String() string
}
var builderPool = sync.Pool{New: func() interface{} {
return newStringBuilder()
}}
func newStringBuilder() stringBuilder {
return &strings.Builder{}
}
func main() {
i := builderPool.Get()
sb := i.(stringBuilder)
_, _ = sb.WriteString("hello")
println(sb.String())
builderPool.Put(i)
}
// Output:
// hello

View File

@@ -8,4 +8,4 @@ func main() {
}
// Error:
// _test/assign15.go:5:26: cannot use type chan<- struct{} as type <-chan struct{} in assignment
// _test/assign15.go:5:26: cannot use type chan<- struct {} as type <-chan struct {} in assignment

View File

@@ -1,13 +0,0 @@
// A test program
// +build darwin,linux !arm
// +build go1.12 !go1.13
package main
func main() {
println("hello world")
}
// Output:
// hello world

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"io"
"log"
"net"
"net/http"
@@ -13,7 +13,7 @@ func client(uri string) {
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"io"
"log"
"net"
"net/http"
@@ -21,7 +21,7 @@ func client(uri string) {
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"net/http/httptest"
@@ -13,7 +13,7 @@ func client(uri string) {
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"net/http/httptest"
@@ -40,7 +40,7 @@ func client(uri string) {
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"net/http/httptest"
@@ -40,7 +40,7 @@ func client(uri string) {
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"net/http/httptest"
@@ -41,7 +41,7 @@ func client(uri string) {
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}

32
_test/composite18.go Normal file
View File

@@ -0,0 +1,32 @@
package main
import "fmt"
type fn func(string, string) bool
var funcs = []fn{
cmpLessFn,
cmpGreaterFn,
nil,
}
func cmpLessFn(a string, b string) bool {
return a < b
}
func cmpGreaterFn(a string, b string) bool {
return a > b
}
func main() {
for _, f := range funcs {
if f == nil {
continue
}
fmt.Println(f("a", "b"))
}
}
// Output:
// true
// false

33
_test/composite19.go Normal file
View File

@@ -0,0 +1,33 @@
package main
import "fmt"
type fn func(string, string) bool
var funcs = map[string]fn{
"less": cmpLessFn,
"greater": cmpGreaterFn,
"none": nil,
}
func cmpLessFn(a string, b string) bool {
return a < b
}
func cmpGreaterFn(a string, b string) bool {
return a > b
}
func main() {
for _, n := range []string{"less", "greater", "none"} {
f := funcs[n]
if f == nil {
continue
}
fmt.Println(f("a", "b"))
}
}
// Output:
// true
// false

View File

@@ -9,7 +9,7 @@ func main() {
const huge = 1 << 100
const large = huge >> 38
fmt.Println(large)
fmt.Println(int64(large))
}
// Output:

View File

@@ -2,7 +2,7 @@ package main
import "fmt"
const maxLen = int64(int(^uint(0) >> 1))
const maxLen = int64(int64(^uint64(0) >> 1))
func main() {
fmt.Println(maxLen)

28
_test/const26.go Normal file
View File

@@ -0,0 +1,28 @@
package main
import (
"fmt"
)
func init() {
fmt.Println(constString)
fmt.Println(const2)
fmt.Println(varString)
}
const constString string = "hello"
const (
const1 = iota + 10
const2
const3
)
var varString string = "test"
func main() {}
// Output:
// hello
// 11
// test

9
_test/d1/d1.go Normal file
View File

@@ -0,0 +1,9 @@
package d1
type T struct {
Name string
}
func (t *T) F() { println(t.Name) }
func NewT(s string) *T { return &T{s} }

8
_test/d2/d2.go Normal file
View File

@@ -0,0 +1,8 @@
package d2
import "github.com/traefik/yaegi/_test/d1"
var (
X = d1.NewT("test")
F = X.F
)

11
_test/d3.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "github.com/traefik/yaegi/_test/d2"
func main() {
f := d2.F
f()
}
// Output:
// test

View File

@@ -2,12 +2,11 @@ package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
file, err := ioutil.TempFile("", "yeagibench")
file, err := os.CreateTemp("", "yeagibench")
if err != nil {
panic(err)
}
@@ -23,7 +22,7 @@ func main() {
panic(err)
}
b, err := ioutil.ReadFile(file.Name())
b, err := os.ReadFile(file.Name())
if err != nil {
panic(err)
}

25
_test/fun27.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
print("test")
}()
wg.Wait()
}
func print(state string) {
fmt.Println(state)
}
// Output:
// test

17
_test/interface52.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import "testing"
func main() {
t := testing.T{}
var tb testing.TB
tb = &t
if tb.TempDir() == "" {
println("FAIL")
return
}
println("PASS")
}
// Output:
// PASS

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"io"
"log"
"strings"
)
@@ -10,7 +10,7 @@ import (
func main() {
r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.")
b, err := ioutil.ReadAll(r)
b, err := io.ReadAll(r)
if err != nil {
log.Fatal(err)
}

19
_test/issue-1068.go Normal file
View File

@@ -0,0 +1,19 @@
package main
type I interface {
Hello()
}
type T struct{}
func (t T) Hello() { println("hello") }
type I2 I
func main() {
var i I2 = T{}
i.Hello()
}
// Output:
// hello

14
_test/issue-1088.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
func main() {
for i, ch := range "日本語" {
fmt.Printf("%#U starts at byte position %d\n", ch, i)
}
}
// Output:
// U+65E5 '日' starts at byte position 0
// U+672C '本' starts at byte position 3
// U+8A9E '語' starts at byte position 6

13
_test/issue-1089.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(`"` + time.RFC3339Nano + `"`)
}
// Output:
// "2006-01-02T15:04:05.999999999Z07:00"

13
_test/issue-1093.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func b() string {
return "b"
}
func main() {
var x int
x = "a" + b()
}
// Error:
// 9:6: cannot use type untyped string as type int in assignment

12
_test/issue-1094.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
var x interface{}
x = "a" + fmt.Sprintf("b")
fmt.Printf("%v %T\n", x, x)
}
// Output:
// ab string

17
_test/issue-1101.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import (
"fmt"
"net/http"
)
func main() {
method := "POST"
switch method {
case http.MethodPost:
fmt.Println("It's a post!")
}
}
// Output:
// It's a post!

24
_test/issue-1115.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import "fmt"
func main() {
outer:
for y := 0; y < 10; y++ {
for x := 0; x < 10; x++ {
if x == 5 && y == 5 {
break outer
}
}
fmt.Println(y)
}
fmt.Println("Yay! I finished!")
}
// Output:
// 0
// 1
// 2
// 3
// 4
// Yay! I finished!

23
_test/issue-1126.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import (
"errors"
"fmt"
"strings"
)
func main() {
err := errors.New("hello there")
switch true {
case err == nil:
break
case strings.Contains(err.Error(), "hello"):
fmt.Println("True!")
default:
fmt.Println("False!")
}
}
// Output:
// True!

11
_test/issue-1128.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "net"
func main() {
c := append(net.Buffers{}, []byte{})
println(len(c))
}
// Output:
// 1

20
_test/issue-1134.go Normal file
View File

@@ -0,0 +1,20 @@
package main
type I interface {
Hello()
}
type T struct {
Name string
Child []*T
}
func (t *T) Hello() { println("Hello", t.Name) }
func main() {
var i I = new(T)
i.Hello()
}
// Output:
// Hello

22
_test/issue-1136.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import (
"fmt"
"io"
)
type T struct {
r io.Reader
}
func (t *T) Read(p []byte) (n int, err error) { n, err = t.r.Read(p); return }
func main() {
x := io.LimitedReader{}
y := io.Reader(&x)
y = &T{y}
fmt.Println(y.Read([]byte("")))
}
// Output:
// 0 EOF

14
_test/issue-1145.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "sync"
type F func()
func main() {
var wg sync.WaitGroup
var f F = wg.Done
println(f != nil)
}
// Output:
// true

25
_test/issue-1156.go Normal file
View File

@@ -0,0 +1,25 @@
package main
type myInterface interface {
myFunc() string
}
type V struct{}
func (v *V) myFunc() string { return "hello" }
type U struct {
v myInterface
}
func (u *U) myFunc() string { return u.v.myFunc() }
func main() {
x := V{}
y := myInterface(&x)
y = &U{y}
println(y.myFunc())
}
// Output:
// hello

41
_test/issue-1163.go Normal file
View File

@@ -0,0 +1,41 @@
package main
import "fmt"
type WidgetEvent struct {
Nothing string
}
type WidgetControl interface {
HandleEvent(e *WidgetEvent)
}
type Button struct{}
func (b *Button) HandleEvent(e *WidgetEvent) {
}
type WindowEvent struct {
Something int
}
type Window struct {
Widget WidgetControl
}
func (w *Window) HandleEvent(e *WindowEvent) {
}
func main() {
window := &Window{
Widget: &Button{},
}
windowevent := &WindowEvent{}
// The next line uses the signature from the wrong method, resulting in an error.
// Renaming one of the clashing method names fixes the problem.
window.HandleEvent(windowevent)
fmt.Println("OK!")
}
// Output:
// OK!

24
_test/issue-1166.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import (
"fmt"
"io"
)
type T []byte
func (t *T) Write(p []byte) (n int, err error) { *t = append(*t, p...); return len(p), nil }
func foo(w io.Writer) {
a := w.(*T)
fmt.Fprint(a, "test")
fmt.Printf("%s\n", *a)
}
func main() {
x := T{}
foo(&x)
}
// Output:
// test

19
_test/issue-1167.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
)
func main() {
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
panic(err)
}
pub := key.Public().(*ecdsa.PublicKey)
println(pub.Params().Name)
}
// Output:
// P-256

10
_test/issue-1173.go Normal file
View File

@@ -0,0 +1,10 @@
package main
var real = func() { println("Hello") }
func main() {
real()
}
// Output:
// Hello

18
_test/issue-1175.go Normal file
View File

@@ -0,0 +1,18 @@
package main
type Level int8
const (
a Level = -1
b Level = 5
d = b - a + 1
)
type counters [d]int
func main() {
println(len(counters{}))
}
// Output:
// 7

13
_test/issue-1177.go Normal file
View File

@@ -0,0 +1,13 @@
package main
type counters [3][16]int
func main() {
cs := &counters{}
p := &cs[0][1]
*p = 2
println(cs[0][1])
}
// Output:
// 2

23
_test/issue-1179.go Normal file
View File

@@ -0,0 +1,23 @@
package main
type I interface {
F()
}
type T struct {
Name string
}
func (t *T) F() { println("in F", t.Name) }
func NewI(s string) I { return newT(s) }
func newT(s string) *T { return &T{s} }
func main() {
i := NewI("test")
i.F()
}
// Output:
// in F test

10
_test/issue-1181.go Normal file
View File

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

20
_test/issue-1185.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import "io"
type B []byte
func (b B) Write(p []byte) (n int, err error) {
b = p
return len(p), nil
}
func main() {
b := B{}
a := make([]io.Writer, 0)
a = append(a, b)
println(len(a))
}
// Output:
// 1

46
_test/issue-1187.go Normal file
View File

@@ -0,0 +1,46 @@
package main
import (
"io"
"os"
)
type sink interface {
io.Writer
io.Closer
}
func newSink() sink {
// return os.Stdout // Stdout is special in yaegi tests
file, err := os.CreateTemp("", "yaegi-test.*")
if err != nil {
panic(err)
}
return file
}
func main() {
s := newSink()
n, err := s.Write([]byte("Hello\n"))
if err != nil {
panic(err)
}
var writer io.Writer = s
m, err := writer.Write([]byte("Hello\n"))
if err != nil {
panic(err)
}
var closer io.Closer = s
err = closer.Close()
if err != nil {
panic(err)
}
err = os.Remove(s.(*os.File).Name())
if err != nil {
panic(err)
}
println(m, n)
}
// Output:
// 6 6

31
_test/issue-1189.go Normal file
View File

@@ -0,0 +1,31 @@
package main
type I interface {
Foo() int
}
type S1 struct {
i int
}
func (s S1) Foo() int { return s.i }
type S2 struct{}
func (s *S2) Foo() int { return 42 }
func main() {
Is := map[string]I{
"foo": S1{21},
"bar": &S2{},
}
n := 0
for _, s := range Is {
n += s.Foo()
}
bar := "bar"
println(n, Is["foo"].Foo(), Is[bar].Foo())
}
// Output:
// 63 21 42

34
_test/issue-1202.go Normal file
View File

@@ -0,0 +1,34 @@
package main
import "fmt"
type foobar struct {
callback func(string) func()
}
func cb(text string) func() {
return func() {
fmt.Println(text)
}
}
func main() {
// These ways of invoking it all work...
cb("Hi from inline callback!")()
asVarTest1 := cb("Hi from asVarTest1 callback!")
asVarTest1()
asVarTest2 := cb
asVarTest2("Hi from asVarTest2 callback!")()
// But inside a struct panics in yaegi...
asStructField := &foobar{callback: cb}
asStructField.callback("Hi from struct field callback!")() // <--- panics here
}
// Output:
// Hi from inline callback!
// Hi from asVarTest1 callback!
// Hi from asVarTest2 callback!
// Hi from struct field callback!

25
_test/issue-1205.go Normal file
View File

@@ -0,0 +1,25 @@
package main
type Option interface {
apply()
}
func f(opts ...Option) {
for _, opt := range opts {
opt.apply()
}
}
type T struct{}
func (t *T) apply() { println("in apply") }
func main() {
opt := []Option{&T{}}
f(opt[0]) // works
f(opt...) // fails
}
// Output:
// in apply
// in apply

23
_test/issue-1208.go Normal file
View File

@@ -0,0 +1,23 @@
package main
type Enabler interface {
Enabled() bool
}
type Logger struct {
core Enabler
}
func (log *Logger) GetCore() Enabler { return log.core }
type T struct{}
func (t *T) Enabled() bool { return true }
func main() {
base := &Logger{&T{}}
println(base.GetCore().Enabled())
}
// Output:
// true

67
_test/issue-1260.go Normal file
View File

@@ -0,0 +1,67 @@
package main
import (
"fmt"
"io"
"os"
)
type WriteSyncer interface {
io.Writer
Sync() error
}
type Sink interface {
WriteSyncer
io.Closer
}
func newFileSink(path string) (Sink, error) {
return os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
}
type Sink1 struct{ name string }
func (s Sink1) Write(b []byte) (int, error) { println("in Write"); return 0, nil }
func (s Sink1) Sync() error { println("in Sync"); return nil }
func (s Sink1) Close() error { println("in Close", s.name); return nil }
func newS1(name string) Sink { return Sink1{name} }
func newS1p(name string) Sink { return &Sink1{name} }
type Sink2 struct{ name string }
func (s *Sink2) Write(b []byte) (int, error) { println("in Write"); return 0, nil }
func (s *Sink2) Sync() error { println("in Sync"); return nil }
func (s *Sink2) Close() error { println("in Close", s.name); return nil }
func newS2(name string) Sink { return Sink1{name} }
func main() {
tmpfile, err := os.CreateTemp("", "xxx")
if err != nil {
panic(err)
}
defer os.Remove(tmpfile.Name())
closers := []io.Closer{}
sink, err := newFileSink(tmpfile.Name())
if err != nil {
panic(err)
}
closers = append(closers, sink)
s1p := newS1p("ptr")
s1 := newS1("struct")
s2 := newS2("ptr2")
closers = append(closers, s1p, s1, s2)
for _, closer := range closers {
fmt.Println(closer.Close())
}
}
// Output:
// <nil>
// in Close ptr
// <nil>
// in Close struct
// <nil>
// in Close ptr2
// <nil>

24
_test/issue-1276.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import (
"flag"
)
type customFlag struct{}
func (cf customFlag) String() string {
return "custom flag"
}
func (cf customFlag) Set(string) error {
return nil
}
func main() {
flag.Var(customFlag{}, "cf", "custom flag")
flag.Parse()
println("Hello, playground")
}
// Output:
// Hello, playground

30
_test/issue-1280.go Normal file
View File

@@ -0,0 +1,30 @@
package main
import (
"io"
"log"
"os"
)
type DBReader interface {
io.ReadCloser
io.ReaderAt
}
type DB struct {
f DBReader
}
func main() {
f, err := os.Open("/dev/null")
if err != nil {
log.Fatal(err)
}
d := &DB{f}
data := make([]byte, 1)
_, _ = d.f.ReadAt(data, 0)
println("bye")
}
// Output:
// bye

25
_test/issue-1285.go Normal file
View File

@@ -0,0 +1,25 @@
package main
type (
T1 struct{ Path [12]int8 }
T2 struct{ Path *[12]int8 }
)
var (
t11 = &T1{}
t21 = &T2{}
)
func main() {
b := [12]byte{}
t12 := &T1{}
t22 := &T2{}
b11 := (*[len(t11.Path)]byte)(&b)
b12 := (*[len(t12.Path)]byte)(&b)
b21 := (*[len(t21.Path)]byte)(&b)
b22 := (*[len(t22.Path)]byte)(&b)
println(len(b11), len(b12), len(b21), len(b22))
}
// Output:
// 12 12 12 12

10
_test/issue-1288.go Normal file
View File

@@ -0,0 +1,10 @@
package main
func main() {
println("Hi")
goto done
done:
}
// Output:
// Hi

20
_test/issue-1300.go Normal file
View File

@@ -0,0 +1,20 @@
package main
const buflen = 512
type T struct {
buf []byte
}
func f(t *T) { *t = T{buf: make([]byte, 0, buflen)} }
func main() {
s := T{}
println(cap(s.buf))
f(&s)
println(cap(s.buf))
}
// Output:
// 0
// 512

16
_test/issue-1304.go Normal file
View File

@@ -0,0 +1,16 @@
package main
type Node struct {
Name string
Alias *Node
Child []*Node
}
func main() {
n := &Node{Name: "parent"}
n.Child = append(n.Child, &Node{Name: "child"})
println(n.Name, n.Child[0].Name)
}
// Output:
// parent child

15
_test/issue-1306.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import "fmt"
func check() (result bool, err error) {
return true, nil
}
func main() {
result, error := check()
fmt.Println(result, error)
}
// Output:
// true <nil>

27
_test/issue-1308.go Normal file
View File

@@ -0,0 +1,27 @@
package main
import "fmt"
type test struct {
v interface{}
s string
}
type T struct {
name string
}
func main() {
t := []test{
{
v: []interface{}{
T{"hello"},
},
s: "world",
},
}
fmt.Println(t)
}
// Output:
// [{[{hello}] world}]

19
_test/issue-1311.go Normal file
View File

@@ -0,0 +1,19 @@
package main
type T struct {
v interface{}
}
func f() (ret int64, err error) {
ret += 2
return
}
func main() {
t := &T{}
t.v, _ = f()
println(t.v.(int64))
}
// Output:
// 2

32
_test/issue-1315.go Normal file
View File

@@ -0,0 +1,32 @@
package main
type Intf interface {
M()
}
type T struct {
s string
}
func (t *T) M() { println("in M") }
func f(i interface{}) {
switch j := i.(type) {
case Intf:
j.M()
default:
println("default")
}
}
func main() {
var i Intf
var k interface{} = 1
i = &T{"hello"}
f(i)
f(k)
}
// Output:
// in M
// default

29
_test/issue-1320.go Normal file
View File

@@ -0,0 +1,29 @@
package main
type Pooler interface {
Get() string
}
type baseClient struct {
connPool Pooler
}
type connPool struct {
name string
}
func (c *connPool) Get() string { return c.name }
func newBaseClient(i int, p Pooler) *baseClient {
return &baseClient{connPool: p}
}
func newConnPool() *connPool { return &connPool{name: "connPool"} }
func main() {
b := newBaseClient(0, newConnPool())
println(b.connPool.(*connPool).name)
}
// Output:
// connPool

42
_test/issue-1326.go Normal file
View File

@@ -0,0 +1,42 @@
package main
type Option interface {
apply(*T)
}
type T struct {
s string
}
type opt struct {
name string
}
func (o *opt) apply(t *T) {
println(o.name)
}
func BuildOptions() []Option {
return []Option{
&opt{"opt1"},
&opt{"opt2"},
}
}
func NewT(name string, options ...Option) *T {
t := &T{name}
for _, opt := range options {
opt.apply(t)
}
return t
}
func main() {
t := NewT("hello", BuildOptions()...)
println(t.s)
}
// Output:
// opt1
// opt2
// hello

16
_test/issue-1328.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import (
"crypto/sha1"
"encoding/hex"
)
func main() {
script := "hello"
sumRaw := sha1.Sum([]byte(script))
sum := hex.EncodeToString(sumRaw[:])
println(sum)
}
// Output:
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

42
_test/issue-1330.go Normal file
View File

@@ -0,0 +1,42 @@
package main
import (
"fmt"
"io"
"net"
)
type wrappedConn struct {
net.Conn
}
func main() {
_, err := net.Listen("tcp", "127.0.0.1:49153")
if err != nil {
panic(err)
}
dialer := &net.Dialer{
LocalAddr: &net.TCPAddr{
IP: net.ParseIP("127.0.0.1"),
Port: 0,
},
}
conn, err := dialer.Dial("tcp", "127.0.0.1:49153")
if err != nil {
panic(err)
}
defer conn.Close()
t := &wrappedConn{conn}
var w io.Writer = t
if n, err := w.Write([]byte("hello")); err != nil {
fmt.Println(err)
} else {
fmt.Println(n)
}
}
// Output:
// 5

37
_test/issue-1333.go Normal file
View File

@@ -0,0 +1,37 @@
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
)
func mock(name string) http.HandlerFunc {
return func(rw http.ResponseWriter, req *http.Request) {
fmt.Fprint(rw, "Hello ", name)
}
}
func client(uri string) {
resp, err := http.Get(uri)
if err != nil {
panic(err)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}
func main() {
mux := http.NewServeMux()
server := httptest.NewServer(mux)
defer server.Close()
mux.Handle("/", mock("foo"))
client(server.URL)
}
// Output:
// Hello foo

View File

@@ -3,7 +3,6 @@ package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"strings"
)
@@ -36,7 +35,7 @@ type pipe struct {
func newReadAutoCloser(r io.Reader) readAutoCloser {
if _, ok := r.(io.Closer); !ok {
return readAutoCloser{ioutil.NopCloser(r)}
return readAutoCloser{io.NopCloser(r)}
}
return readAutoCloser{r.(io.ReadCloser)}
}
@@ -44,7 +43,7 @@ func newReadAutoCloser(r io.Reader) readAutoCloser {
func main() {
p := &pipe{}
p.Reader = newReadAutoCloser(strings.NewReader("test"))
b, err := ioutil.ReadAll(p.Reader)
b, err := io.ReadAll(p.Reader)
if err != nil {
log.Fatal(err)
}

27
_test/map30.go Normal file
View File

@@ -0,0 +1,27 @@
package main
import "strings"
func f(s string) string { return "hello " + s }
func g(s string) string { return "hi " + s }
var methods = map[string]func(string) string{
"f": f,
"h": strings.ToLower,
}
func main() {
methods["i"] = strings.ToUpper
methods["g"] = g
println(methods["f"]("test"))
println(methods["g"]("test"))
println(methods["i"]("test"))
println(methods["h"]("TEST"))
}
// Output:
// hello test
// hi test
// TEST
// test

19
_test/method37.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import (
"net"
"os"
)
func writeBufs(bufs ...[]byte) error {
b := net.Buffers(bufs)
_, err := b.WriteTo(os.Stdout)
return err
}
func main() {
writeBufs([]byte("hello"))
}
// Output:
// hello

14
_test/method38.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import (
"fmt"
"github.com/traefik/yaegi/_test/method38"
)
func main() {
fmt.Println(method38.Get())
}
// Output:
// &{[] {<nil>}}

19
_test/method38/a.go Normal file
View File

@@ -0,0 +1,19 @@
package method38
import "sync"
func NewPool() Pool { return Pool{} }
type Buffer struct {
bs []byte
pool Pool
}
type Pool struct {
p *sync.Pool
}
var (
_pool = NewPool()
Get = _pool.Get
)

3
_test/method38/b.go Normal file
View File

@@ -0,0 +1,3 @@
package method38
func (p Pool) Get() *Buffer { return &Buffer{} }

32
_test/method39.go Normal file
View File

@@ -0,0 +1,32 @@
package main
import (
"fmt"
"sync"
"github.com/traefik/yaegi/_test/method38"
)
func NewPool() Pool { return Pool{} }
type Buffer struct {
bs []byte
pool Pool
}
type Pool struct {
p *sync.Pool
}
var (
_pool = NewPool()
Get = _pool.Get
)
func main() {
fmt.Println(Get())
}
// Error:
// 17:11: undefined selector Get

View File

@@ -7,4 +7,4 @@ func main() {
}
// Error:
// 5:2: invalid operation: mismatched types int and float64
// 5:2: invalid operation: mismatched types int and untyped float

View File

@@ -2,11 +2,11 @@ package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
_, err := ioutil.ReadFile("__NotExisting__")
_, err := os.ReadFile("__NotExisting__")
if err != nil {
fmt.Println(err.Error())
}

28
_test/ret8.go Normal file
View File

@@ -0,0 +1,28 @@
package main
import "fmt"
type CustomError string
func (s CustomError) Error() string {
return string(s)
}
func NewCustomError(errorText string) CustomError {
return CustomError(errorText)
}
func fail() (err error) {
return NewCustomError("Everything is going wrong!")
}
func main() {
fmt.Println(fail())
var myError error
myError = NewCustomError("ok")
fmt.Println(myError)
}
// Output:
// Everything is going wrong!
// ok

22
_test/rune2.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import "fmt"
const majorVersion = '2'
type hashed struct {
major byte
}
func main() {
fmt.Println(majorVersion)
p := new(hashed)
p.major = majorVersion
fmt.Println(p)
}
// Output:
// 50
// &{50}

View File

@@ -9,10 +9,20 @@ func test(time string, t time.Time) string {
return time
}
var zero = time.Time{}
func test2(time string) time.Time {
return zero
}
func main() {
str := test("test", time.Now())
fmt.Println(str)
str2 := test2("test2")
fmt.Println(str2)
}
// Output:
// test
// 0001-01-01 00:00:00 +0000 UTC

View File

@@ -8,6 +8,7 @@ type A struct {
}
type D struct {
F *A
E *A
}

20
_test/struct60.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import (
"fmt"
)
type data struct {
S string
}
func render(v interface{}) {
fmt.Println(v)
}
func main() {
render(data{})
}
// Output:
// {}

22
_test/struct61.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import "fmt"
type A struct {
B string
D
}
type D struct {
*A
E *A
}
func main() {
a := &A{B: "b"}
a.D = D{E: a}
fmt.Println(a.D.E.B)
}
// Output:
// b

11
_test/struct62.go Normal file
View File

@@ -0,0 +1,11 @@
package main
func main() {
type A struct{ *A }
v := &A{}
v.A = v
println("v.A.A = v", v.A.A == v)
}
// Output:
// v.A.A = v true

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