OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [exp/] [types/] [const.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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.
4
 
5
// This file implements operations on ideal constants.
6
 
7
package types
8
 
9
import (
10
        "go/token"
11
        "math/big"
12
        "strconv"
13
)
14
 
15
// TODO(gri) Consider changing the API so Const is an interface
16
//           and operations on consts don't have to type switch.
17
 
18
// A Const implements an ideal constant Value.
19
// The zero value z for a Const is not a valid constant value.
20
type Const struct {
21
        // representation of constant values:
22
        // ideal bool     ->  bool
23
        // ideal int      ->  *big.Int
24
        // ideal float    ->  *big.Rat
25
        // ideal complex  ->  cmplx
26
        // ideal string   ->  string
27
        val interface{}
28
}
29
 
30
// Representation of complex values.
31
type cmplx struct {
32
        re, im *big.Rat
33
}
34
 
35
func assert(cond bool) {
36
        if !cond {
37
                panic("go/types internal error: assertion failed")
38
        }
39
}
40
 
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 {
44
        switch tok {
45
        case token.INT:
46
                var x big.Int
47
                _, ok := x.SetString(lit, 0)
48
                assert(ok)
49
                return Const{&x}
50
        case token.FLOAT:
51
                var y big.Rat
52
                _, ok := y.SetString(lit)
53
                assert(ok)
54
                return Const{&y}
55
        case token.IMAG:
56
                assert(lit[len(lit)-1] == 'i')
57
                var im big.Rat
58
                _, ok := im.SetString(lit[0 : len(lit)-1])
59
                assert(ok)
60
                return Const{cmplx{big.NewRat(0, 1), &im}}
61
        case token.CHAR:
62
                assert(lit[0] == '\'' && lit[len(lit)-1] == '\'')
63
                code, _, _, err := strconv.UnquoteChar(lit[1:len(lit)-1], '\'')
64
                assert(err == nil)
65
                return Const{big.NewInt(int64(code))}
66
        case token.STRING:
67
                s, err := strconv.Unquote(lit)
68
                assert(err == nil)
69
                return Const{s}
70
        }
71
        panic("unreachable")
72
}
73
 
74
// MakeZero returns the zero constant for the given type.
75
func MakeZero(typ *Type) Const {
76
        // TODO(gri) fix this
77
        return Const{0}
78
}
79
 
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) {
86
        case bool:
87
                if _, ok := y.val.(bool); ok {
88
                        u, v = x, y
89
                }
90
        case *big.Int:
91
                switch y.val.(type) {
92
                case *big.Int:
93
                        u, v = x, y
94
                case *big.Rat:
95
                        var z big.Rat
96
                        z.SetInt(a)
97
                        u, v = Const{&z}, y
98
                case cmplx:
99
                        var z big.Rat
100
                        z.SetInt(a)
101
                        u, v = Const{cmplx{&z, big.NewRat(0, 1)}}, y
102
                }
103
        case *big.Rat:
104
                switch y.val.(type) {
105
                case *big.Int:
106
                        v, u = y.Match(x)
107
                case *big.Rat:
108
                        u, v = x, y
109
                case cmplx:
110
                        u, v = Const{cmplx{a, big.NewRat(0, 0)}}, y
111
                }
112
        case cmplx:
113
                switch y.val.(type) {
114
                case *big.Int, *big.Rat:
115
                        v, u = y.Match(x)
116
                case cmplx:
117
                        u, v = x, y
118
                }
119
        case string:
120
                if _, ok := y.val.(string); ok {
121
                        u, v = x, y
122
                }
123
        default:
124
                panic("unreachable")
125
        }
126
        return
127
}
128
 
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) {
135
        case bool:
136
        case *big.Int:
137
        case *big.Rat:
138
        case cmplx:
139
        case string:
140
        }
141
        return x
142
}
143
 
144
func (x Const) String() string {
145
        switch x := x.val.(type) {
146
        case bool:
147
                if x {
148
                        return "true"
149
                }
150
                return "false"
151
        case *big.Int:
152
                return x.String()
153
        case *big.Rat:
154
                return x.FloatString(10) // 10 digits of precision after decimal point seems fine
155
        case cmplx:
156
                // TODO(gri) don't print 0 components
157
                return x.re.FloatString(10) + " + " + x.im.FloatString(10) + "i"
158
        case string:
159
                return x
160
        }
161
        panic("unreachable")
162
}
163
 
164
func (x Const) UnaryOp(op token.Token) Const {
165
        panic("unimplemented")
166
}
167
 
168
func (x Const) BinaryOp(op token.Token, y Const) Const {
169
        var z interface{}
170
        switch x := x.val.(type) {
171
        case bool:
172
                z = binaryBoolOp(x, op, y.val.(bool))
173
        case *big.Int:
174
                z = binaryIntOp(x, op, y.val.(*big.Int))
175
        case *big.Rat:
176
                z = binaryFloatOp(x, op, y.val.(*big.Rat))
177
        case cmplx:
178
                z = binaryCmplxOp(x, op, y.val.(cmplx))
179
        case string:
180
                z = binaryStringOp(x, op, y.val.(string))
181
        default:
182
                panic("unreachable")
183
        }
184
        return Const{z}
185
}
186
 
187
func binaryBoolOp(x bool, op token.Token, y bool) interface{} {
188
        switch op {
189
        case token.EQL:
190
                return x == y
191
        case token.NEQ:
192
                return x != y
193
        }
194
        panic("unreachable")
195
}
196
 
197
func binaryIntOp(x *big.Int, op token.Token, y *big.Int) interface{} {
198
        var z big.Int
199
        switch op {
200
        case token.ADD:
201
                return z.Add(x, y)
202
        case token.SUB:
203
                return z.Sub(x, y)
204
        case token.MUL:
205
                return z.Mul(x, y)
206
        case token.QUO:
207
                return z.Quo(x, y)
208
        case token.REM:
209
                return z.Rem(x, y)
210
        case token.AND:
211
                return z.And(x, y)
212
        case token.OR:
213
                return z.Or(x, y)
214
        case token.XOR:
215
                return z.Xor(x, y)
216
        case token.AND_NOT:
217
                return z.AndNot(x, y)
218
        case token.SHL:
219
                panic("unimplemented")
220
        case token.SHR:
221
                panic("unimplemented")
222
        case token.EQL:
223
                return x.Cmp(y) == 0
224
        case token.NEQ:
225
                return x.Cmp(y) != 0
226
        case token.LSS:
227
                return x.Cmp(y) < 0
228
        case token.LEQ:
229
                return x.Cmp(y) <= 0
230
        case token.GTR:
231
                return x.Cmp(y) > 0
232
        case token.GEQ:
233
                return x.Cmp(y) >= 0
234
        }
235
        panic("unreachable")
236
}
237
 
238
func binaryFloatOp(x *big.Rat, op token.Token, y *big.Rat) interface{} {
239
        var z big.Rat
240
        switch op {
241
        case token.ADD:
242
                return z.Add(x, y)
243
        case token.SUB:
244
                return z.Sub(x, y)
245
        case token.MUL:
246
                return z.Mul(x, y)
247
        case token.QUO:
248
                return z.Quo(x, y)
249
        case token.EQL:
250
                return x.Cmp(y) == 0
251
        case token.NEQ:
252
                return x.Cmp(y) != 0
253
        case token.LSS:
254
                return x.Cmp(y) < 0
255
        case token.LEQ:
256
                return x.Cmp(y) <= 0
257
        case token.GTR:
258
                return x.Cmp(y) > 0
259
        case token.GEQ:
260
                return x.Cmp(y) >= 0
261
        }
262
        panic("unreachable")
263
}
264
 
265
func binaryCmplxOp(x cmplx, op token.Token, y cmplx) interface{} {
266
        a, b := x.re, x.im
267
        c, d := y.re, y.im
268
        switch op {
269
        case token.ADD:
270
                // (a+c) + i(b+d)
271
                var re, im big.Rat
272
                re.Add(a, c)
273
                im.Add(b, d)
274
                return cmplx{&re, &im}
275
        case token.SUB:
276
                // (a-c) + i(b-d)
277
                var re, im big.Rat
278
                re.Sub(a, c)
279
                im.Sub(b, d)
280
                return cmplx{&re, &im}
281
        case token.MUL:
282
                // (ac-bd) + i(bc+ad)
283
                var ac, bd, bc, ad big.Rat
284
                ac.Mul(a, c)
285
                bd.Mul(b, d)
286
                bc.Mul(b, c)
287
                ad.Mul(a, d)
288
                var re, im big.Rat
289
                re.Sub(&ac, &bd)
290
                im.Add(&bc, &ad)
291
                return cmplx{&re, &im}
292
        case token.QUO:
293
                // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
294
                var ac, bd, bc, ad, s big.Rat
295
                ac.Mul(a, c)
296
                bd.Mul(b, d)
297
                bc.Mul(b, c)
298
                ad.Mul(a, d)
299
                s.Add(c.Mul(c, c), d.Mul(d, d))
300
                var re, im big.Rat
301
                re.Add(&ac, &bd)
302
                re.Quo(&re, &s)
303
                im.Sub(&bc, &ad)
304
                im.Quo(&im, &s)
305
                return cmplx{&re, &im}
306
        case token.EQL:
307
                return a.Cmp(c) == 0 && b.Cmp(d) == 0
308
        case token.NEQ:
309
                return a.Cmp(c) != 0 || b.Cmp(d) != 0
310
        }
311
        panic("unreachable")
312
}
313
 
314
func binaryStringOp(x string, op token.Token, y string) interface{} {
315
        switch op {
316
        case token.ADD:
317
                return x + y
318
        case token.EQL:
319
                return x == y
320
        case token.NEQ:
321
                return x != y
322
        case token.LSS:
323
                return x < y
324
        case token.LEQ:
325
                return x <= y
326
        case token.GTR:
327
                return x > y
328
        case token.GEQ:
329
                return x >= y
330
        }
331
        panic("unreachable")
332
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.