mirror of
https://github.com/golang/go
synced 2024-11-23 20:00:04 -07:00
go/constant: add Val accessor and Make constructor to handle varied types
This change adds a Val accessor that returns the underlying type for a given constant.Value. This change also adds a Make constructor that builds a constant.Value given a value of a specific type. Fixes #29820 Change-Id: I4fc3f5221408e24af42ffecd21ce4099ee75b47a Reviewed-on: https://go-review.googlesource.com/c/go/+/164538 Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
4d8a37a6d9
commit
e269f4ce01
@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"math"
|
||||
"sort"
|
||||
)
|
||||
|
||||
@ -156,3 +157,24 @@ func ExampleSign() {
|
||||
// 1 (0 + 1i)
|
||||
// 1 (1 + 1i)
|
||||
}
|
||||
|
||||
func ExampleVal() {
|
||||
maxint := constant.MakeInt64(math.MaxInt64)
|
||||
fmt.Printf("%v\n", constant.Val(maxint))
|
||||
|
||||
e := constant.MakeFloat64(math.E)
|
||||
fmt.Printf("%v\n", constant.Val(e))
|
||||
|
||||
b := constant.MakeBool(true)
|
||||
fmt.Printf("%v\n", constant.Val(b))
|
||||
|
||||
b = constant.Make(false)
|
||||
fmt.Printf("%v\n", constant.Val(b))
|
||||
|
||||
// Output:
|
||||
//
|
||||
// 9223372036854775807
|
||||
// 6121026514868073/2251799813685248
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
@ -562,6 +562,68 @@ func Float64Val(x Value) (float64, bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// Val returns the underlying value for a given constant. Since it returns an
|
||||
// interface, it is up to the caller to type assert the result to the expected
|
||||
// type. The possible dynamic return types are:
|
||||
//
|
||||
// x Kind type of result
|
||||
// -----------------------------------------
|
||||
// Bool bool
|
||||
// String string
|
||||
// Int int64 or *big.Int
|
||||
// Float *big.Float or *big.Rat
|
||||
// everything else nil
|
||||
//
|
||||
func Val(x Value) interface{} {
|
||||
switch x := x.(type) {
|
||||
case boolVal:
|
||||
return bool(x)
|
||||
case *stringVal:
|
||||
return x.string()
|
||||
case int64Val:
|
||||
return int64(x)
|
||||
case intVal:
|
||||
return x.val
|
||||
case ratVal:
|
||||
return x.val
|
||||
case floatVal:
|
||||
return x.val
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Make returns the Value for x.
|
||||
//
|
||||
// type of x result Kind
|
||||
// ----------------------------
|
||||
// bool Bool
|
||||
// string String
|
||||
// int64 Int
|
||||
// *big.Int Int
|
||||
// *big.Float Float
|
||||
// *big.Rat Float
|
||||
// anything else Unknown
|
||||
//
|
||||
func Make(x interface{}) Value {
|
||||
switch x := x.(type) {
|
||||
case bool:
|
||||
return boolVal(x)
|
||||
case string:
|
||||
return &stringVal{s: x}
|
||||
case int64:
|
||||
return int64Val(x)
|
||||
case *big.Int:
|
||||
return intVal{x}
|
||||
case *big.Rat:
|
||||
return ratVal{x}
|
||||
case *big.Float:
|
||||
return floatVal{x}
|
||||
default:
|
||||
return unknownVal{}
|
||||
}
|
||||
}
|
||||
|
||||
// BitLen returns the number of bits required to represent
|
||||
// the absolute value x in binary representation; x must be an Int or an Unknown.
|
||||
// If x is Unknown, the result is 0.
|
||||
|
@ -7,6 +7,7 @@ package constant
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@ -596,6 +597,22 @@ func TestUnknown(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMake(t *testing.T) {
|
||||
for _, want := range []interface{}{
|
||||
false,
|
||||
"hello",
|
||||
int64(1),
|
||||
big.NewInt(10),
|
||||
big.NewFloat(2.0),
|
||||
big.NewRat(1, 3),
|
||||
} {
|
||||
got := Val(Make(want))
|
||||
if got != want {
|
||||
t.Errorf("got %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStringAdd(b *testing.B) {
|
||||
for size := 1; size <= 65536; size *= 4 {
|
||||
b.Run(fmt.Sprint(size), func(b *testing.B) {
|
||||
|
Loading…
Reference in New Issue
Block a user