Skip to content

Commit 9520a92

Browse files
authored
interp: fix type in assign of shift operations
Type checking on shift operands was failing for untyped variable values. Fix propagation of type in assignment. Optimize assignment of arithmetic operations on variables by skipping the assign and writing directly to destination frame value in the operator function. Skip some slow tests when given -short test option. Fixes #917.
1 parent d47821b commit 9520a92

File tree

5 files changed

+55
-5
lines changed

5 files changed

+55
-5
lines changed

_test/assign16.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package main
2+
3+
type H struct {
4+
bits uint
5+
}
6+
7+
func main() {
8+
h := &H{8}
9+
var x uint = (1 << h.bits) >> 6
10+
11+
println(x)
12+
}
13+
14+
// Output:
15+
// 4

_test/select1.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
package main
22

3-
import "time"
4-
import "fmt"
3+
import (
4+
"fmt"
5+
"time"
6+
)
57

68
func main() {
79
c1 := make(chan string)
810
c2 := make(chan string)
911

1012
go func() {
11-
time.Sleep(1e9)
13+
time.Sleep(1e7)
1214
c1 <- "one"
1315
}()
1416
go func() {
15-
time.Sleep(2e9)
17+
time.Sleep(2e7)
1618
c2 <- "two"
1719
}()
1820

interp/cfg.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,14 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
551551
n.gen = nop
552552
src.findex = dest.findex
553553
src.level = level
554+
case n.action == aAssign && len(n.child) < 4 && !src.rval.IsValid() && isArithmeticAction(src):
555+
// Optimize single assignments from some arithmetic operations.
556+
// Skip the assign operation entirely, the source frame index is set
557+
// to destination index, avoiding extra memory alloc and duplication.
558+
src.typ = dest.typ
559+
src.findex = dest.findex
560+
src.level = level
561+
n.gen = nop
554562
case src.kind == basicLit && !src.rval.IsValid():
555563
// Assign to nil.
556564
src.rval = reflect.New(dest.typ.TypeOf()).Elem()
@@ -2449,3 +2457,13 @@ func isValueUntyped(v reflect.Value) bool {
24492457
}
24502458
return t.String() == t.Kind().String()
24512459
}
2460+
2461+
// isArithmeticAction returns true if the node action is an arithmetic operator.
2462+
func isArithmeticAction(n *node) bool {
2463+
switch n.action {
2464+
case aAdd, aAnd, aAndNot, aBitNot, aMul, aQuo, aRem, aShl, aShr, aSub, aXor:
2465+
return true
2466+
default:
2467+
return false
2468+
}
2469+
}

interp/interp_eval_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,9 @@ func TestConcurrentEvals(t *testing.T) {
986986
// called by EvalWithContext is sequential. And that there is no data race for the
987987
// interp package global vars or the interpreter fields in this case.
988988
func TestConcurrentEvals2(t *testing.T) {
989+
if testing.Short() {
990+
return
991+
}
989992
pin, pout := io.Pipe()
990993
defer func() {
991994
_ = pin.Close()
@@ -1045,6 +1048,9 @@ func TestConcurrentEvals2(t *testing.T) {
10451048
// - when calling Interpreter.Use, the symbols given as argument should be
10461049
// copied when being inserted into interp.binPkg, and not directly used as-is.
10471050
func TestConcurrentEvals3(t *testing.T) {
1051+
if testing.Short() {
1052+
return
1053+
}
10481054
allDone := make(chan bool)
10491055
runREPL := func() {
10501056
done := make(chan error)
@@ -1123,6 +1129,9 @@ func TestConcurrentComposite2(t *testing.T) {
11231129
}
11241130

11251131
func testConcurrentComposite(t *testing.T, filePath string) {
1132+
if testing.Short() {
1133+
return
1134+
}
11261135
pin, pout := io.Pipe()
11271136
i := interp.New(interp.Options{Stdout: pout})
11281137
i.Use(stdlib.Symbols)
@@ -1160,6 +1169,9 @@ func testConcurrentComposite(t *testing.T, filePath string) {
11601169
}
11611170

11621171
func TestEvalScanner(t *testing.T) {
1172+
if testing.Short() {
1173+
return
1174+
}
11631175
type testCase struct {
11641176
desc string
11651177
src []string
@@ -1333,6 +1345,9 @@ func applyCIMultiplier(timeout time.Duration) time.Duration {
13331345
}
13341346

13351347
func TestREPLDivision(t *testing.T) {
1348+
if testing.Short() {
1349+
return
1350+
}
13361351
_ = os.Setenv("YAEGI_PROMPT", "1")
13371352
defer func() {
13381353
_ = os.Setenv("YAEGI_PROMPT", "0")

interp/typecheck.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func (check typecheck) shift(n *node) error {
151151
t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf()
152152

153153
var v0 constant.Value
154-
if c0.typ.untyped {
154+
if c0.typ.untyped && c0.rval.IsValid() {
155155
v0 = constant.ToInt(c0.rval.Interface().(constant.Value))
156156
c0.rval = reflect.ValueOf(v0)
157157
}

0 commit comments

Comments
 (0)