1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This file implements operations on ideal constants.
15 // TODO(gri) Consider changing the API so Const is an interface
16 // and operations on consts don't have to type switch.
18 // A Const implements an ideal constant Value.
19 // The zero value z for a Const is not a valid constant value.
21 // representation of constant values:
23 // ideal int -> *big.Int
24 // ideal float -> *big.Rat
25 // ideal complex -> cmplx
26 // ideal string -> string
30 // Representation of complex values.
35 func assert(cond bool) {
37 panic("go/types internal error: assertion failed")
41 // MakeConst makes an ideal constant from a literal
42 // token and the corresponding literal string.
43 func MakeConst(tok token.Token, lit string) Const {
47 _, ok := x.SetString(lit, 0)
52 _, ok := y.SetString(lit)
56 assert(lit[len(lit)-1] == 'i')
58 _, ok := im.SetString(lit[0 : len(lit)-1])
60 return Const{cmplx{big.NewRat(0, 1), &im}}
62 assert(lit[0] == '\'' && lit[len(lit)-1] == '\'')
63 code, _, _, err := strconv.UnquoteChar(lit[1:len(lit)-1], '\'')
65 return Const{big.NewInt(int64(code))}
67 s, err := strconv.Unquote(lit)
74 // MakeZero returns the zero constant for the given type.
75 func MakeZero(typ *Type) Const {
80 // Match attempts to match the internal constant representations of x and y.
81 // If the attempt is successful, the result is the values of x and y,
82 // if necessary converted to have the same internal representation; otherwise
83 // the results are invalid.
84 func (x Const) Match(y Const) (u, v Const) {
85 switch a := x.val.(type) {
87 if _, ok := y.val.(bool); ok {
101 u, v = Const{cmplx{&z, big.NewRat(0, 1)}}, y
104 switch y.val.(type) {
110 u, v = Const{cmplx{a, big.NewRat(0, 0)}}, y
113 switch y.val.(type) {
114 case *big.Int, *big.Rat:
120 if _, ok := y.val.(string); ok {
129 // Convert attempts to convert the constant x to a given type.
130 // If the attempt is successful, the result is the new constant;
131 // otherwise the result is invalid.
132 func (x Const) Convert(typ *Type) Const {
133 // TODO(gri) implement this
134 switch x.val.(type) {
144 func (x Const) String() string {
145 switch x := x.val.(type) {
154 return x.FloatString(10) // 10 digits of precision after decimal point seems fine
156 // TODO(gri) don't print 0 components
157 return x.re.FloatString(10) + " + " + x.im.FloatString(10) + "i"
164 func (x Const) UnaryOp(op token.Token) Const {
165 panic("unimplemented")
168 func (x Const) BinaryOp(op token.Token, y Const) Const {
170 switch x := x.val.(type) {
172 z = binaryBoolOp(x, op, y.val.(bool))
174 z = binaryIntOp(x, op, y.val.(*big.Int))
176 z = binaryFloatOp(x, op, y.val.(*big.Rat))
178 z = binaryCmplxOp(x, op, y.val.(cmplx))
180 z = binaryStringOp(x, op, y.val.(string))
187 func binaryBoolOp(x bool, op token.Token, y bool) interface{} {
197 func binaryIntOp(x *big.Int, op token.Token, y *big.Int) interface{} {
217 return z.AndNot(x, y)
219 panic("unimplemented")
221 panic("unimplemented")
238 func binaryFloatOp(x *big.Rat, op token.Token, y *big.Rat) interface{} {
265 func binaryCmplxOp(x cmplx, op token.Token, y cmplx) interface{} {
274 return cmplx{&re, &im}
280 return cmplx{&re, &im}
282 // (ac-bd) + i(bc+ad)
283 var ac, bd, bc, ad big.Rat
291 return cmplx{&re, &im}
293 // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
294 var ac, bd, bc, ad, s big.Rat
299 s.Add(c.Mul(c, c), d.Mul(d, d))
305 return cmplx{&re, &im}
307 return a.Cmp(c) == 0 && b.Cmp(d) == 0
309 return a.Cmp(c) != 0 || b.Cmp(d) != 0
314 func binaryStringOp(x string, op token.Token, y string) interface{} {