Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(595)

Delta Between Two Patch Sets: src/pkg/go/types/const.go

Issue 4314054: code review 4314054: go/types: New Go type hierarchy implementation for AST. (Closed)
Left Patch Set: Created 14 years ago
Right Patch Set: diff -r ebef2da9ab43 https://go.googlecode.com/hg/ Created 13 years, 12 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/go/types/Makefile ('k') | src/pkg/go/types/exportdata.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
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.
4
5 // This file implements operations on ideal constants.
6
7 package types
8
9 import (
10 "big"
11 "go/token"
12 "strconv"
13 )
14
15
16 // TODO(gri) Consider changing the API so Const is an interface
17 // and operations on consts don't have to type switch.
18
19 // A Const implements an ideal constant Value.
20 // The zero value z for a Const is not a valid constant value.
21 type Const struct {
22 // representation of constant values:
23 // ideal bool -> bool
24 // ideal int -> *big.Int
25 // ideal float -> *big.Rat
26 // ideal complex -> cmplx
27 // ideal string -> string
28 val interface{}
29 }
30
31
32 // Representation of complex values.
33 type cmplx struct {
34 re, im *big.Rat
35 }
36
37
38 func assert(cond bool) {
39 if !cond {
40 panic("go/types internal error: assertion failed")
41 }
42 }
43
44
45 // MakeConst makes an ideal constant from a literal
46 // token and the corresponding literal string.
47 func MakeConst(tok token.Token, lit string) Const {
48 switch tok {
49 case token.INT:
50 var x big.Int
51 _, ok := x.SetString(lit, 0)
52 assert(ok)
53 return Const{&x}
54 case token.FLOAT:
55 var y big.Rat
56 _, ok := y.SetString(lit)
57 assert(ok)
58 return Const{&y}
59 case token.IMAG:
60 assert(lit[len(lit)-1] == 'i')
61 var im big.Rat
62 _, ok := im.SetString(lit[0 : len(lit)-1])
63 assert(ok)
64 return Const{cmplx{big.NewRat(0, 1), &im}}
65 case token.CHAR:
66 assert(lit[0] == '\'' && lit[len(lit)-1] == '\'')
67 code, _, _, err := strconv.UnquoteChar(lit[1:len(lit)-1], '\'')
68 assert(err == nil)
69 return Const{big.NewInt(int64(code))}
70 case token.STRING:
71 s, err := strconv.Unquote(lit)
72 assert(err == nil)
73 return Const{s}
74 }
75 panic("unreachable")
76 }
77
78
79 // MakeZero returns the zero constant for the given type.
80 func MakeZero(typ *Type) Const {
81 // TODO(gri) fix this
82 return Const{0}
83 }
84
85
86 // Match attempts to match the internal constant representations of x and y.
87 // If the attempt is successful, the result is the values of x and y,
88 // if necessary converted to have the same internal representation; otherwise
89 // the results are invalid.
90 func (x Const) Match(y Const) (u, v Const) {
91 switch a := x.val.(type) {
92 case bool:
93 if _, ok := y.val.(bool); ok {
94 u, v = x, y
95 }
96 case *big.Int:
97 switch y.val.(type) {
98 case *big.Int:
99 u, v = x, y
100 case *big.Rat:
101 var z big.Rat
102 z.SetInt(a)
103 u, v = Const{&z}, y
104 case cmplx:
105 var z big.Rat
106 z.SetInt(a)
107 u, v = Const{cmplx{&z, big.NewRat(0, 1)}}, y
108 }
109 case *big.Rat:
110 switch y.val.(type) {
111 case *big.Int:
112 v, u = y.Match(x)
113 case *big.Rat:
114 u, v = x, y
115 case cmplx:
116 u, v = Const{cmplx{a, big.NewRat(0, 0)}}, y
117 }
118 case cmplx:
119 switch y.val.(type) {
120 case *big.Int, *big.Rat:
121 v, u = y.Match(x)
122 case cmplx:
123 u, v = x, y
124 }
125 case string:
126 if _, ok := y.val.(string); ok {
127 u, v = x, y
128 }
129 default:
130 panic("unreachable")
131 }
132 return
133 }
134
135
136 // Convert attempts to convert the constant x to a given type.
137 // If the attempt is successful, the result is the new constant;
138 // otherwise the result is invalid.
139 func (x Const) Convert(typ *Type) Const {
140 // TODO(gri) implement this
141 switch x := x.val.(type) {
142 case bool:
143 case *big.Int:
144 case *big.Rat:
145 case cmplx:
146 case string:
147 }
148 return x
149 }
150
151
152 func (x Const) String() string {
153 switch x := x.val.(type) {
154 case bool:
155 if x {
156 return "true"
157 }
158 return "false"
159 case *big.Int:
160 return x.String()
161 case *big.Rat:
162 return x.FloatString(10) // 10 digits of precision after decimal point seems fine
163 case cmplx:
164 // TODO(gri) don't print 0 components
165 return x.re.FloatString(10) + " + " + x.im.FloatString(10) + "i"
166 case string:
167 return x
168 }
169 panic("unreachable")
170 }
171
172
173 func (x Const) UnaryOp(op token.Token) Const {
174 panic("unimplemented")
175 }
176
177
178 func (x Const) BinaryOp(op token.Token, y Const) Const {
179 var z interface{}
180 switch x := x.val.(type) {
181 case bool:
182 z = binaryBoolOp(x, op, y.val.(bool))
183 case *big.Int:
184 z = binaryIntOp(x, op, y.val.(*big.Int))
185 case *big.Rat:
186 z = binaryFloatOp(x, op, y.val.(*big.Rat))
187 case cmplx:
188 z = binaryCmplxOp(x, op, y.val.(cmplx))
189 case string:
190 z = binaryStringOp(x, op, y.val.(string))
191 default:
192 panic("unreachable")
193 }
194 return Const{z}
195 }
196
197
198 func binaryBoolOp(x bool, op token.Token, y bool) interface{} {
199 switch op {
200 case token.EQL:
201 return x == y
202 case token.NEQ:
203 return x != y
204 }
205 panic("unreachable")
206 }
207
208
209 func binaryIntOp(x *big.Int, op token.Token, y *big.Int) interface{} {
210 var z big.Int
211 switch op {
212 case token.ADD:
213 return z.Add(x, y)
214 case token.SUB:
215 return z.Sub(x, y)
216 case token.MUL:
217 return z.Mul(x, y)
218 case token.QUO:
219 return z.Quo(x, y)
220 case token.REM:
221 return z.Rem(x, y)
222 case token.AND:
223 return z.And(x, y)
224 case token.OR:
225 return z.Or(x, y)
226 case token.XOR:
227 return z.Xor(x, y)
228 case token.AND_NOT:
229 return z.AndNot(x, y)
230 case token.SHL:
231 panic("unimplemented")
232 case token.SHR:
233 panic("unimplemented")
234 case token.EQL:
235 return x.Cmp(y) == 0
236 case token.NEQ:
237 return x.Cmp(y) != 0
238 case token.LSS:
239 return x.Cmp(y) < 0
240 case token.LEQ:
241 return x.Cmp(y) <= 0
242 case token.GTR:
243 return x.Cmp(y) > 0
244 case token.GEQ:
245 return x.Cmp(y) >= 0
246 }
247 panic("unreachable")
248 }
249
250
251 func binaryFloatOp(x *big.Rat, op token.Token, y *big.Rat) interface{} {
252 var z big.Rat
253 switch op {
254 case token.ADD:
255 return z.Add(x, y)
256 case token.SUB:
257 return z.Sub(x, y)
258 case token.MUL:
259 return z.Mul(x, y)
260 case token.QUO:
261 return z.Quo(x, y)
262 case token.EQL:
263 return x.Cmp(y) == 0
264 case token.NEQ:
265 return x.Cmp(y) != 0
266 case token.LSS:
267 return x.Cmp(y) < 0
268 case token.LEQ:
269 return x.Cmp(y) <= 0
270 case token.GTR:
271 return x.Cmp(y) > 0
272 case token.GEQ:
273 return x.Cmp(y) >= 0
274 }
275 panic("unreachable")
276 }
277
278
279 func binaryCmplxOp(x cmplx, op token.Token, y cmplx) interface{} {
280 a, b := x.re, x.im
281 c, d := y.re, y.im
282 switch op {
283 case token.ADD:
284 // (a+c) + i(b+d)
285 var re, im big.Rat
286 re.Add(a, c)
287 im.Add(b, d)
288 return cmplx{&re, &im}
289 case token.SUB:
290 // (a-c) + i(b-d)
291 var re, im big.Rat
292 re.Sub(a, c)
293 im.Sub(b, d)
294 return cmplx{&re, &im}
295 case token.MUL:
296 // (ac-bd) + i(bc+ad)
297 var ac, bd, bc, ad big.Rat
298 ac.Mul(a, c)
299 bd.Mul(b, d)
300 bc.Mul(b, c)
301 ad.Mul(a, d)
302 var re, im big.Rat
303 re.Sub(&ac, &bd)
304 im.Add(&bc, &ad)
305 return cmplx{&re, &im}
306 case token.QUO:
307 // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
308 var ac, bd, bc, ad, s big.Rat
309 ac.Mul(a, c)
310 bd.Mul(b, d)
311 bc.Mul(b, c)
312 ad.Mul(a, d)
313 s.Add(c.Mul(c, c), d.Mul(d, d))
314 var re, im big.Rat
315 re.Add(&ac, &bd)
316 re.Quo(&re, &s)
317 im.Sub(&bc, &ad)
318 im.Quo(&im, &s)
319 return cmplx{&re, &im}
320 case token.EQL:
321 return a.Cmp(c) == 0 && b.Cmp(d) == 0
322 case token.NEQ:
323 return a.Cmp(c) != 0 || b.Cmp(d) != 0
324 }
325 panic("unreachable")
326 }
327
328
329 func binaryStringOp(x string, op token.Token, y string) interface{} {
330 switch op {
331 case token.ADD:
332 return x + y
333 case token.EQL:
334 return x == y
335 case token.NEQ:
336 return x != y
337 case token.LSS:
338 return x < y
339 case token.LEQ:
340 return x <= y
341 case token.GTR:
342 return x > y
343 case token.GEQ:
344 return x >= y
345 }
346 panic("unreachable")
347 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b