interp: fix operators working on integer constants

Always attempt to obtain an integer constant value for operators
expecting so. It allows to use '/' in integer constant defintions,
instead of default big.Rat.

Fixes #1005
This commit is contained in:
Marc Vertes
2021-01-14 17:26:06 +01:00
committed by GitHub
parent 8ad14d8ea4
commit 5c59dc425f
3 changed files with 37 additions and 17 deletions

15
_test/const22.go Normal file
View File

@@ -0,0 +1,15 @@
package main
const (
numDec uint8 = (1 << iota) / 2
numHex
numOct
numFloat
)
func main() {
println(13 & (numHex | numOct))
}
// Output:
// 1

View File

@@ -209,7 +209,11 @@ func {{$name}}Const(n *node) {
v := constant.BinaryOp(vConstantValue(v0), operator, vConstantValue(v1))
n.rval.Set(reflect.ValueOf(v))
{{- else}}
{{- if $op.Int}}
v := constant.BinaryOp(constant.ToInt(vConstantValue(v0)), token.{{tokenFromName $name}}, constant.ToInt(vConstantValue(v1)))
{{- else}}
v := constant.BinaryOp(vConstantValue(v0), token.{{tokenFromName $name}}, vConstantValue(v1))
{{- end}}
n.rval.Set(reflect.ValueOf(v))
{{- end}}
{{- if $op.Str}}
@@ -940,6 +944,7 @@ type Op struct {
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
Int bool // true if operator applies to int only
}
func main() {
@@ -968,17 +973,17 @@ func main() {
b := &bytes.Buffer{}
data := map[string]interface{}{
"Arithmetic": map[string]Op{
"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},
"add": {"+", true, true, true, false, false, false},
"sub": {"-", false, true, true, false, false, false},
"mul": {"*", false, true, true, false, false, false},
"quo": {"/", false, true, true, false, false, false},
"rem": {"%", false, false, false, false, false, true},
"shl": {"<<", false, false, false, true, false, true},
"shr": {">>", false, false, false, true, false, true},
"and": {"&", false, false, false, false, false, true},
"or": {"|", false, false, false, false, false, true},
"xor": {"^", false, false, false, false, false, true},
"andNot": {"&^", false, false, false, false, false, true},
},
"IncDec": map[string]Op{
"inc": {Name: "+"},
@@ -996,7 +1001,7 @@ func main() {
"not": {Name: "!", Float: false, Bool: true},
"neg": {Name: "-", Float: true, Bool: false},
"pos": {Name: "+", Float: true, Bool: false},
"bitNot": {Name: "^", Float: false, Bool: false},
"bitNot": {Name: "^", Float: false, Bool: false, Int: true},
},
}
if err = parse.Execute(b, data); err != nil {

View File

@@ -253,7 +253,7 @@ func andConst(n *node) {
n.rval = reflect.New(t).Elem()
switch {
case isConst:
v := constant.BinaryOp(vConstantValue(v0), token.AND, vConstantValue(v1))
v := constant.BinaryOp(constant.ToInt(vConstantValue(v0)), token.AND, constant.ToInt(vConstantValue(v1)))
n.rval.Set(reflect.ValueOf(v))
case isUint(t):
n.rval.SetUint(vUint(v0) & vUint(v1))
@@ -338,7 +338,7 @@ func andNotConst(n *node) {
n.rval = reflect.New(t).Elem()
switch {
case isConst:
v := constant.BinaryOp(vConstantValue(v0), token.AND_NOT, vConstantValue(v1))
v := constant.BinaryOp(constant.ToInt(vConstantValue(v0)), token.AND_NOT, constant.ToInt(vConstantValue(v1)))
n.rval.Set(reflect.ValueOf(v))
case isUint(t):
n.rval.SetUint(vUint(v0) &^ vUint(v1))
@@ -564,7 +564,7 @@ func orConst(n *node) {
n.rval = reflect.New(t).Elem()
switch {
case isConst:
v := constant.BinaryOp(vConstantValue(v0), token.OR, vConstantValue(v1))
v := constant.BinaryOp(constant.ToInt(vConstantValue(v0)), token.OR, constant.ToInt(vConstantValue(v1)))
n.rval.Set(reflect.ValueOf(v))
case isUint(t):
n.rval.SetUint(vUint(v0) | vUint(v1))
@@ -799,7 +799,7 @@ func remConst(n *node) {
n.rval = reflect.New(t).Elem()
switch {
case isConst:
v := constant.BinaryOp(vConstantValue(v0), token.REM, vConstantValue(v1))
v := constant.BinaryOp(constant.ToInt(vConstantValue(v0)), token.REM, constant.ToInt(vConstantValue(v1)))
n.rval.Set(reflect.ValueOf(v))
case isUint(t):
n.rval.SetUint(vUint(v0) % vUint(v1))
@@ -1195,7 +1195,7 @@ func xorConst(n *node) {
n.rval = reflect.New(t).Elem()
switch {
case isConst:
v := constant.BinaryOp(vConstantValue(v0), token.XOR, vConstantValue(v1))
v := constant.BinaryOp(constant.ToInt(vConstantValue(v0)), token.XOR, constant.ToInt(vConstantValue(v1)))
n.rval.Set(reflect.ValueOf(v))
case isUint(t):
n.rval.SetUint(vUint(v0) ^ vUint(v1))