summaryrefslogtreecommitdiffstats
path: root/test/abi/idata.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/abi/idata.go')
-rw-r--r--test/abi/idata.go97
1 files changed, 97 insertions, 0 deletions
diff --git a/test/abi/idata.go b/test/abi/idata.go
new file mode 100644
index 0000000..af2b87b
--- /dev/null
+++ b/test/abi/idata.go
@@ -0,0 +1,97 @@
+// run
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Excerpted from go/constant/value.go to capture a bug from there.
+
+package main
+
+import (
+ "fmt"
+ "math"
+ "math/big"
+)
+
+type (
+ unknownVal struct{}
+ intVal struct{ val *big.Int } // Int values not representable as an int64
+ ratVal struct{ val *big.Rat } // Float values representable as a fraction
+ floatVal struct{ val *big.Float } // Float values not representable as a fraction
+ complexVal struct{ re, im Value }
+)
+
+const prec = 512
+
+func (unknownVal) String() string { return "unknown" }
+
+func (x intVal) String() string { return x.val.String() }
+func (x ratVal) String() string { return rtof(x).String() }
+
+func (x floatVal) String() string {
+ f := x.val
+
+ // Use exact fmt formatting if in float64 range (common case):
+ // proceed if f doesn't underflow to 0 or overflow to inf.
+ if x, _ := f.Float64(); f.Sign() == 0 == (x == 0) && !math.IsInf(x, 0) {
+ return fmt.Sprintf("%.6g", x)
+ }
+
+ return "OOPS"
+}
+
+func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
+
+func newFloat() *big.Float { return new(big.Float).SetPrec(prec) }
+
+//go:noinline
+//go:registerparams
+func itor(x intVal) ratVal { return ratVal{nil} }
+
+//go:noinline
+//go:registerparams
+func itof(x intVal) floatVal { return floatVal{nil} }
+func rtof(x ratVal) floatVal { return floatVal{newFloat().SetRat(x.val)} }
+
+type Value interface {
+ String() string
+}
+
+//go:noinline
+//go:registerparams
+func ToFloat(x Value) Value {
+ switch x := x.(type) {
+ case intVal:
+ if smallInt(x.val) {
+ return itor(x)
+ }
+ return itof(x)
+ case ratVal, floatVal:
+ return x
+ case complexVal:
+ if Sign(x.im) == 0 {
+ return ToFloat(x.re)
+ }
+ }
+ return unknownVal{}
+}
+
+//go:noinline
+//go:registerparams
+func smallInt(x *big.Int) bool {
+ return false
+}
+
+//go:noinline
+//go:registerparams
+func Sign(x Value) int {
+ return 0
+}
+
+
+func main() {
+ v := ratVal{big.NewRat(22,7)}
+ s := ToFloat(v).String()
+ fmt.Printf("s=%s\n", s)
+}