Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1cde2be0f | ||
|
|
bb04af2d4d | ||
|
|
9a8a88dcb9 | ||
|
|
f3f54a5302 | ||
|
|
878fcc835c | ||
|
|
a1f2d3bf1d |
@@ -13,7 +13,12 @@ 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 [Containous 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/containous/yaegi/issues
|
||||
[Pull Requests]: https://github.com/containous/yaegi/issues
|
||||
[Feature Request]: https://github.com/containous/yaegi/issues/new?template=feature_request.md
|
||||
[Draft Pull Request]: https://github.blog/2019-02-14-introducing-draft-pull-requests/
|
||||
[Containous Contributor License Agreement]: https://cla-assistant.io/containous/yaegi
|
||||
|
||||
13
_test/bin2.go
Normal file
13
_test/bin2.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(math.Abs(-5))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 5
|
||||
12
_test/nil1.go
Normal file
12
_test/nil1.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
var a error = nil
|
||||
|
||||
if a == nil || a.Error() == "nil" {
|
||||
println("a is nil")
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// a is nil
|
||||
9
_test/or0.go
Normal file
9
_test/or0.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
c := false
|
||||
println(c || !c)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// true
|
||||
9
_test/or1.go
Normal file
9
_test/or1.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
c := false
|
||||
println(!c || c)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// true
|
||||
@@ -352,6 +352,30 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{range $name, $op := .Unary}}
|
||||
func {{$name}}Const(n *node) {
|
||||
t := n.typ.rtype
|
||||
v := n.child[0].rval
|
||||
n.rval = reflect.New(t).Elem()
|
||||
|
||||
{{- if $op.Bool}}
|
||||
n.rval.SetBool({{$op.Name}} v.Bool())
|
||||
{{- else}}
|
||||
switch t.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n.rval.SetInt({{$op.Name}} v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
n.rval.SetUint({{$op.Name}} v.Uint())
|
||||
{{- if $op.Float}}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
n.rval.SetFloat({{$op.Name}} v.Float())
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
n.rval.SetComplex({{$op.Name}} v.Complex())
|
||||
{{- end}}
|
||||
}
|
||||
{{- end}}
|
||||
}
|
||||
{{end}}
|
||||
{{range $name, $op := .Comparison}}
|
||||
func {{$name}}(n *node) {
|
||||
tnext := getExec(n.tnext)
|
||||
@@ -793,6 +817,7 @@ type Op struct {
|
||||
Float bool // true if operator applies to float
|
||||
Complex bool // true if operator applies to complex
|
||||
Shift bool // true if operator is a shift operation
|
||||
Bool bool // true if operator applies to bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -805,17 +830,17 @@ func main() {
|
||||
b := &bytes.Buffer{}
|
||||
data := map[string]interface{}{
|
||||
"Arithmetic": map[string]Op{
|
||||
"add": {"+", true, true, true, false},
|
||||
"sub": {"-", false, true, true, false},
|
||||
"mul": {"*", false, true, true, false},
|
||||
"quo": {"/", false, true, true, false},
|
||||
"rem": {"%", false, false, false, false},
|
||||
"shl": {"<<", false, false, false, true},
|
||||
"shr": {">>", false, false, false, true},
|
||||
"and": {"&", false, false, false, false},
|
||||
"or": {"|", false, false, false, false},
|
||||
"xor": {"^", false, false, false, false},
|
||||
"andNot": {"&^", false, false, false, false},
|
||||
"add": {"+", true, true, true, false, false},
|
||||
"sub": {"-", false, true, true, false, false},
|
||||
"mul": {"*", false, true, true, false, false},
|
||||
"quo": {"/", false, true, true, false, false},
|
||||
"rem": {"%", false, false, false, false, false},
|
||||
"shl": {"<<", false, false, false, true, false},
|
||||
"shr": {">>", false, false, false, true, false},
|
||||
"and": {"&", false, false, false, false, false},
|
||||
"or": {"|", false, false, false, false, false},
|
||||
"xor": {"^", false, false, false, false, false},
|
||||
"andNot": {"&^", false, false, false, false, false},
|
||||
},
|
||||
"IncDec": map[string]Op{
|
||||
"inc": {Name: "+"},
|
||||
@@ -829,6 +854,12 @@ func main() {
|
||||
"lowerEqual": {Name: "<=", Complex: false},
|
||||
"notEqual": {Name: "!=", Complex: true},
|
||||
},
|
||||
"Unary": map[string]Op{
|
||||
"not": {Name: "!", Float: false, Bool: true},
|
||||
"neg": {Name: "-", Float: true, Bool: false},
|
||||
"pos": {Name: "+", Float: true, Bool: false},
|
||||
"bitNot": {Name: "^", Float: false, Bool: false},
|
||||
},
|
||||
}
|
||||
if err = parse.Execute(b, data); err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
@@ -199,6 +199,7 @@ const (
|
||||
aAndAssign
|
||||
aAndNot
|
||||
aAndNotAssign
|
||||
aBitNot
|
||||
aCall
|
||||
aCase
|
||||
aCompositeLit
|
||||
@@ -217,11 +218,12 @@ const (
|
||||
aMethod
|
||||
aMul
|
||||
aMulAssign
|
||||
aNegate
|
||||
aNeg
|
||||
aNot
|
||||
aNotEqual
|
||||
aOr
|
||||
aOrAssign
|
||||
aPos
|
||||
aQuo
|
||||
aQuoAssign
|
||||
aRange
|
||||
@@ -255,6 +257,7 @@ var actions = [...]string{
|
||||
aAndAssign: "&=",
|
||||
aAndNot: "&^",
|
||||
aAndNotAssign: "&^=",
|
||||
aBitNot: "^",
|
||||
aCall: "call",
|
||||
aCase: "case",
|
||||
aCompositeLit: "compositeLit",
|
||||
@@ -271,11 +274,12 @@ var actions = [...]string{
|
||||
aMethod: "Method",
|
||||
aMul: "*",
|
||||
aMulAssign: "*=",
|
||||
aNegate: "-",
|
||||
aNeg: "-",
|
||||
aNot: "!",
|
||||
aNotEqual: "!=",
|
||||
aOr: "|",
|
||||
aOrAssign: "|=",
|
||||
aPos: "+",
|
||||
aQuo: "/",
|
||||
aQuoAssign: "/=",
|
||||
aRange: "range",
|
||||
@@ -771,6 +775,8 @@ func (interp *Interpreter) ast(src, name string) (string, *node, error) {
|
||||
var kind = unaryExpr
|
||||
var act action
|
||||
switch a.Op {
|
||||
case token.ADD:
|
||||
act = aPos
|
||||
case token.AND:
|
||||
kind = addressExpr
|
||||
act = aAddr
|
||||
@@ -779,7 +785,9 @@ func (interp *Interpreter) ast(src, name string) (string, *node, error) {
|
||||
case token.NOT:
|
||||
act = aNot
|
||||
case token.SUB:
|
||||
act = aNegate
|
||||
act = aNeg
|
||||
case token.XOR:
|
||||
act = aBitNot
|
||||
}
|
||||
st.push(addChild(&root, anc, pos, kind, act), nod)
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@ var constOp = map[action]func(*node){
|
||||
aShr: shrConst,
|
||||
aAndNot: andNotConst,
|
||||
aXor: xorConst,
|
||||
aNot: notConst,
|
||||
aBitNot: bitNotConst,
|
||||
aNeg: negConst,
|
||||
aPos: posConst,
|
||||
}
|
||||
|
||||
var constBltn = map[string]func(*node){
|
||||
@@ -1019,6 +1023,9 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
|
||||
n.child[1].tnext = n
|
||||
n.typ = n.child[0].typ
|
||||
n.findex = sc.add(n.typ)
|
||||
if n.start.action == aNop {
|
||||
n.start.gen = branch
|
||||
}
|
||||
|
||||
case lorExpr:
|
||||
n.start = n.child[0].start
|
||||
@@ -1027,6 +1034,9 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
|
||||
n.child[1].tnext = n
|
||||
n.typ = n.child[0].typ
|
||||
n.findex = sc.add(n.typ)
|
||||
if n.start.action == aNop {
|
||||
n.start.gen = branch
|
||||
}
|
||||
|
||||
case parenExpr:
|
||||
wireChild(n)
|
||||
@@ -1375,16 +1385,60 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
|
||||
case unaryExpr:
|
||||
wireChild(n)
|
||||
n.typ = n.child[0].typ
|
||||
if n.action == aRecv {
|
||||
switch n.action {
|
||||
case aRecv:
|
||||
// Channel receive operation: set type to the channel data type
|
||||
if n.typ.cat == valueT {
|
||||
n.typ = &itype{cat: valueT, rtype: n.typ.rtype.Elem()}
|
||||
} else {
|
||||
n.typ = n.typ.val
|
||||
}
|
||||
case aBitNot:
|
||||
if !isInt(n.typ.TypeOf()) {
|
||||
err = n.cfgErrorf("illegal operand type for '^' operator")
|
||||
return
|
||||
}
|
||||
case aNot:
|
||||
if !isBool(n.typ) {
|
||||
err = n.cfgErrorf("illegal operand type for '!' operator")
|
||||
return
|
||||
}
|
||||
case aNeg, aPos:
|
||||
if !isNumber(n.typ.TypeOf()) {
|
||||
err = n.cfgErrorf("illegal operand type for '%v' operator", n.action)
|
||||
return
|
||||
}
|
||||
}
|
||||
// TODO: Optimisation: avoid allocation if boolean branch op (i.e. '!' in an 'if' expr)
|
||||
n.findex = sc.add(n.typ)
|
||||
if n.child[0].rval.IsValid() && constOp[n.action] != nil {
|
||||
if n.typ == nil {
|
||||
if n.typ, err = nodeType(interp, sc, n); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
n.typ.TypeOf() // init reflect type
|
||||
constOp[n.action](n)
|
||||
}
|
||||
switch {
|
||||
case n.rval.IsValid():
|
||||
n.gen = nop
|
||||
n.findex = -1
|
||||
case n.anc.kind == assignStmt && n.anc.action == aAssign:
|
||||
dest := n.anc.child[childPos(n)-n.anc.nright]
|
||||
n.typ = dest.typ
|
||||
n.findex = dest.findex
|
||||
case n.anc.kind == returnStmt:
|
||||
pos := childPos(n)
|
||||
n.typ = sc.def.typ.ret[pos]
|
||||
n.findex = pos
|
||||
default:
|
||||
if n.typ == nil {
|
||||
if n.typ, err = nodeType(interp, sc, n); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
n.findex = sc.add(n.typ)
|
||||
}
|
||||
|
||||
case valueSpec:
|
||||
n.gen = reset
|
||||
|
||||
@@ -4,6 +4,18 @@ Package interp provides a complete Go interpreter.
|
||||
For the Go language itself, refer to the official Go specification
|
||||
https://golang.org/ref/spec.
|
||||
|
||||
Importing packages
|
||||
|
||||
Packages can be imported in source or binary form, using the standard
|
||||
Go import statement. In source form, packages are searched first in the
|
||||
vendor directory, the preferred way to store source dependencies. If not
|
||||
found in vendor, sources modules will be searched in GOPATH. Go modules
|
||||
are not supported yet by yaegi.
|
||||
|
||||
Binary form packages are compiled and linked with the interpreter
|
||||
executable, and exposed to scripts with the Use method. The goexports
|
||||
command can be used to generate package wrappers.
|
||||
|
||||
Custom build tags
|
||||
|
||||
Custom build tags allow to control which files in imported source
|
||||
|
||||
@@ -38,7 +38,7 @@ func (n *node) astDot(out io.Writer, name string) {
|
||||
func (n *node) cfgDot(out io.Writer) {
|
||||
fmt.Fprintf(out, "digraph cfg {\n")
|
||||
n.Walk(nil, func(n *node) {
|
||||
if n.kind == basicLit || n.kind == identExpr || n.tnext == nil {
|
||||
if n.kind == basicLit || n.tnext == nil {
|
||||
return
|
||||
}
|
||||
var label string
|
||||
|
||||
@@ -47,11 +47,17 @@ func TestEvalArithmetic(t *testing.T) {
|
||||
{desc: "shl_IN", src: "1 << -1", err: "1:28: illegal operand types for '<<' operator"},
|
||||
{desc: "shl_IF", src: "1 << 1.0", res: "2"},
|
||||
{desc: "shl_IF1", src: "1 << 1.1", err: "1:28: illegal operand types for '<<' operator"},
|
||||
{desc: "shl_IF", src: "1.0 << 1", res: "2"},
|
||||
{desc: "shl_IF2", src: "1.0 << 1", res: "2"},
|
||||
{desc: "shr_II", src: "1 >> 8", res: "0"},
|
||||
{desc: "shr_IN", src: "1 >> -1", err: "1:28: illegal operand types for '>>' operator"},
|
||||
{desc: "shr_IF", src: "1 >> 1.0", res: "0"},
|
||||
{desc: "shr_IF1", src: "1 >> 1.1", err: "1:28: illegal operand types for '>>' operator"},
|
||||
{desc: "neg_I", src: "-2", res: "-2"},
|
||||
{desc: "pos_I", src: "+2", res: "2"},
|
||||
{desc: "bitnot_I", src: "^2", res: "-3"},
|
||||
{desc: "bitnot_F", src: "^0.2", err: "1:28: illegal operand type for '^' operator"},
|
||||
{desc: "not_B", src: "!false", res: "true"},
|
||||
{desc: "not_I", src: "!0", err: "1:28: illegal operand type for '!' operator"},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
51
interp/op.go
51
interp/op.go
@@ -1864,6 +1864,57 @@ func inc(n *node) {
|
||||
}
|
||||
}
|
||||
|
||||
func bitNotConst(n *node) {
|
||||
t := n.typ.rtype
|
||||
v := n.child[0].rval
|
||||
n.rval = reflect.New(t).Elem()
|
||||
switch t.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n.rval.SetInt(^v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
n.rval.SetUint(^v.Uint())
|
||||
}
|
||||
}
|
||||
|
||||
func negConst(n *node) {
|
||||
t := n.typ.rtype
|
||||
v := n.child[0].rval
|
||||
n.rval = reflect.New(t).Elem()
|
||||
switch t.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n.rval.SetInt(-v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
n.rval.SetUint(-v.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
n.rval.SetFloat(-v.Float())
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
n.rval.SetComplex(-v.Complex())
|
||||
}
|
||||
}
|
||||
|
||||
func notConst(n *node) {
|
||||
t := n.typ.rtype
|
||||
v := n.child[0].rval
|
||||
n.rval = reflect.New(t).Elem()
|
||||
n.rval.SetBool(!v.Bool())
|
||||
}
|
||||
|
||||
func posConst(n *node) {
|
||||
t := n.typ.rtype
|
||||
v := n.child[0].rval
|
||||
n.rval = reflect.New(t).Elem()
|
||||
switch t.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n.rval.SetInt(+v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
n.rval.SetUint(+v.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
n.rval.SetFloat(+v.Float())
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
n.rval.SetComplex(+v.Complex())
|
||||
}
|
||||
}
|
||||
|
||||
func equal(n *node) {
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValue(n)
|
||||
|
||||
@@ -24,6 +24,7 @@ var builtin = [...]bltnGenerator{
|
||||
aAndAssign: andAssign,
|
||||
aAndNot: andNot,
|
||||
aAndNotAssign: andNotAssign,
|
||||
aBitNot: bitNot,
|
||||
aCall: call,
|
||||
aCase: _case,
|
||||
aCompositeLit: arrayLit,
|
||||
@@ -40,11 +41,12 @@ var builtin = [...]bltnGenerator{
|
||||
aLowerEqual: lowerEqual,
|
||||
aMul: mul,
|
||||
aMulAssign: mulAssign,
|
||||
aNegate: negate,
|
||||
aNeg: neg,
|
||||
aNot: not,
|
||||
aNotEqual: notEqual,
|
||||
aOr: or,
|
||||
aOrAssign: orAssign,
|
||||
aPos: pos,
|
||||
aQuo: quo,
|
||||
aQuoAssign: quoAssign,
|
||||
aRange: _range,
|
||||
@@ -340,21 +342,24 @@ func assign(n *node) {
|
||||
}
|
||||
|
||||
func not(n *node) {
|
||||
dest := genValue(n)
|
||||
value := genValue(n.child[0])
|
||||
tnext := getExec(n.tnext)
|
||||
i := n.findex
|
||||
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
n.exec = func(f *frame) bltn {
|
||||
if !value(f).Bool() {
|
||||
f.data[i].SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
f.data[i].SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
} else {
|
||||
i := n.findex
|
||||
n.exec = func(f *frame) bltn {
|
||||
f.data[i].SetBool(!value(f).Bool())
|
||||
dest(f).SetBool(!value(f).Bool())
|
||||
return tnext
|
||||
}
|
||||
}
|
||||
@@ -658,7 +663,7 @@ func call(n *node) {
|
||||
values = append(values, func(f *frame) reflect.Value { return f.data[ind] })
|
||||
}
|
||||
default:
|
||||
if c.kind == basicLit {
|
||||
if c.kind == basicLit || c.rval.IsValid() {
|
||||
var argType reflect.Type
|
||||
if variadic >= 0 && i >= variadic {
|
||||
argType = n.child[0].typ.arg[variadic].val.TypeOf()
|
||||
@@ -843,7 +848,7 @@ func callBin(n *node) {
|
||||
values = append(values, func(f *frame) reflect.Value { return f.data[ind] })
|
||||
}
|
||||
default:
|
||||
if c.kind == basicLit {
|
||||
if c.kind == basicLit || c.rval.IsValid() {
|
||||
// Convert literal value (untyped) to function argument type (if not an interface{})
|
||||
var argType reflect.Type
|
||||
if variadic >= 0 && i >= variadic {
|
||||
@@ -1246,7 +1251,7 @@ func getIndexSeqMethod(n *node) {
|
||||
}
|
||||
}
|
||||
|
||||
func negate(n *node) {
|
||||
func neg(n *node) {
|
||||
dest := genValue(n)
|
||||
value := genValue(n.child[0])
|
||||
next := getExec(n.tnext)
|
||||
@@ -1270,6 +1275,37 @@ func negate(n *node) {
|
||||
}
|
||||
}
|
||||
|
||||
func pos(n *node) {
|
||||
dest := genValue(n)
|
||||
value := genValue(n.child[0])
|
||||
next := getExec(n.tnext)
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(value(f))
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
func bitNot(n *node) {
|
||||
dest := genValue(n)
|
||||
value := genValue(n.child[0])
|
||||
next := getExec(n.tnext)
|
||||
typ := n.typ.TypeOf()
|
||||
|
||||
switch typ.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetInt(^value(f).Int())
|
||||
return next
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetUint(^value(f).Uint())
|
||||
return next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func land(n *node) {
|
||||
value0 := genValue(n.child[0])
|
||||
value1 := genValue(n.child[1])
|
||||
@@ -1946,7 +1982,7 @@ func _close(n *node) {
|
||||
}
|
||||
|
||||
func _complex(n *node) {
|
||||
i := n.findex
|
||||
dest := genValue(n)
|
||||
c1, c2 := n.child[1], n.child[2]
|
||||
convertLiteralValue(c1, floatType)
|
||||
convertLiteralValue(c2, floatType)
|
||||
@@ -1956,38 +1992,38 @@ func _complex(n *node) {
|
||||
|
||||
if typ := n.typ.TypeOf(); isComplex(typ) {
|
||||
n.exec = func(f *frame) bltn {
|
||||
f.data[i].SetComplex(complex(value0(f).Float(), value1(f).Float()))
|
||||
dest(f).SetComplex(complex(value0(f).Float(), value1(f).Float()))
|
||||
return next
|
||||
}
|
||||
} else {
|
||||
// Not a complex type: ignore imaginary part
|
||||
n.exec = func(f *frame) bltn {
|
||||
f.data[i].Set(value0(f).Convert(typ))
|
||||
dest(f).Set(value0(f).Convert(typ))
|
||||
return next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func _imag(n *node) {
|
||||
i := n.findex
|
||||
dest := genValue(n)
|
||||
convertLiteralValue(n.child[1], complexType)
|
||||
value := genValue(n.child[1])
|
||||
next := getExec(n.tnext)
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
f.data[i].SetFloat(imag(value(f).Complex()))
|
||||
dest(f).SetFloat(imag(value(f).Complex()))
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
func _real(n *node) {
|
||||
i := n.findex
|
||||
dest := genValue(n)
|
||||
convertLiteralValue(n.child[1], complexType)
|
||||
value := genValue(n.child[1])
|
||||
next := getExec(n.tnext)
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
f.data[i].SetFloat(real(value(f).Complex()))
|
||||
dest(f).SetFloat(real(value(f).Complex()))
|
||||
return next
|
||||
}
|
||||
}
|
||||
@@ -2005,12 +2041,12 @@ func _delete(n *node) {
|
||||
}
|
||||
|
||||
func _len(n *node) {
|
||||
i := n.findex
|
||||
dest := genValue(n)
|
||||
value := genValue(n.child[1])
|
||||
next := getExec(n.tnext)
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
f.data[i].SetInt(int64(value(f).Len()))
|
||||
dest(f).SetInt(int64(value(f).Len()))
|
||||
return next
|
||||
}
|
||||
}
|
||||
@@ -2222,13 +2258,16 @@ func recv2(n *node) {
|
||||
}
|
||||
|
||||
func convertLiteralValue(n *node, t reflect.Type) {
|
||||
if n.kind != basicLit || t == nil || t.Kind() == reflect.Interface {
|
||||
// Skip non-constant values, undefined target type or interface target type.
|
||||
if !(n.kind == basicLit || n.rval.IsValid()) || t == nil || t.Kind() == reflect.Interface {
|
||||
return
|
||||
}
|
||||
if n.rval.IsValid() {
|
||||
// Convert constant value to target type.
|
||||
n.rval = n.rval.Convert(t)
|
||||
} else {
|
||||
n.rval = reflect.New(t).Elem() // convert to type nil value
|
||||
// Create a zero value of target type.
|
||||
n.rval = reflect.New(t).Elem()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2420,19 +2459,21 @@ func isNil(n *node) {
|
||||
value = genValue(n.child[0])
|
||||
}
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValue(n)
|
||||
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
n.exec = func(f *frame) bltn {
|
||||
if value(f).IsNil() {
|
||||
dest(f).SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
} else {
|
||||
i := n.findex
|
||||
n.exec = func(f *frame) bltn {
|
||||
f.data[i].SetBool(value(f).IsNil())
|
||||
dest(f).SetBool(value(f).IsNil())
|
||||
return tnext
|
||||
}
|
||||
}
|
||||
@@ -2446,19 +2487,21 @@ func isNotNil(n *node) {
|
||||
value = genValue(n.child[0])
|
||||
}
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValue(n)
|
||||
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
n.exec = func(f *frame) bltn {
|
||||
if value(f).IsNil() {
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
dest(f).SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
} else {
|
||||
i := n.findex
|
||||
n.exec = func(f *frame) bltn {
|
||||
f.data[i].SetBool(!value(f).IsNil())
|
||||
dest(f).SetBool(!value(f).IsNil())
|
||||
return tnext
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// +build go1.12,!go1.14
|
||||
|
||||
// Package stdlib provides wrappers of standard library packages to be imported natively in Yaegi.
|
||||
package stdlib
|
||||
|
||||
import "reflect"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// +build go1.12,!go1.14
|
||||
|
||||
// Package syscall provide wrapper of standard library syscall package for native import in Yaegi.
|
||||
package syscall
|
||||
|
||||
import "reflect"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// +build go1.12,!go1.14
|
||||
|
||||
// Package unsafe provides wrapper of standard library unsafe package to be imported natively in Yaegi.
|
||||
package unsafe
|
||||
|
||||
import "reflect"
|
||||
|
||||
Reference in New Issue
Block a user