Skip to content

Commit

Permalink
fix: apply automatic type conversion to constant expressions (#484)
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes authored and ldez committed Jan 9, 2020
1 parent bb04af2 commit f1cde2b
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
13 changes: 13 additions & 0 deletions _test/bin2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"fmt"
"math"
)

func main() {
fmt.Println(math.Abs(-5))
}

// Output:
// 5
30 changes: 29 additions & 1 deletion interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -1410,7 +1410,35 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
}
}
// 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
Expand Down
11 changes: 7 additions & 4 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,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()
Expand Down Expand Up @@ -848,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 {
Expand Down Expand Up @@ -2258,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()
}
}

Expand Down

0 comments on commit f1cde2b

Please sign in to comment.