]> Cypherpunks repositories - gostls13.git/commitdiff
go/constant: add Val accessor and Make constructor to handle varied types
authorRebecca Stambler <rstambler@golang.org>
Wed, 27 Feb 2019 19:10:07 +0000 (14:10 -0500)
committerRebecca Stambler <rstambler@golang.org>
Wed, 6 Mar 2019 23:36:59 +0000 (23:36 +0000)
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>
src/go/constant/example_test.go
src/go/constant/value.go
src/go/constant/value_test.go

index ed20d6bf0916780cc754520162a52b590bcef721..6443ee6db8b4bf3d4f79af7861c0bcfd05aa85b9 100644 (file)
@@ -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
+}
index f7efa95404a01e9c771d7a26e6f669a4b8192eb9..cd77b376d12a946fcf85fe9b0ad976356dc6eeee 100644 (file)
@@ -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.
index 560712a8f55cdd20cc157b4c5c80a9801b0613cf..a319039fc6e89d7962666219d105d5e0f2549ce2 100644 (file)
@@ -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) {