1 | // Copyright 2013 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 | package interp |
6 | |
7 | import ( |
8 | "bytes" |
9 | "fmt" |
10 | "go/constant" |
11 | "go/token" |
12 | "go/types" |
13 | "os" |
14 | "reflect" |
15 | "strings" |
16 | "sync" |
17 | "unsafe" |
18 | |
19 | "golang.org/x/tools/go/ssa" |
20 | ) |
21 | |
22 | // If the target program panics, the interpreter panics with this type. |
23 | type targetPanic struct { |
24 | v value |
25 | } |
26 | |
27 | func (p targetPanic) String() string { |
28 | return toString(p.v) |
29 | } |
30 | |
31 | // If the target program calls exit, the interpreter panics with this type. |
32 | type exitPanic int |
33 | |
34 | // constValue returns the value of the constant with the |
35 | // dynamic type tag appropriate for c.Type(). |
36 | func constValue(c *ssa.Const) value { |
37 | if c.Value == nil { |
38 | return zero(c.Type()) // typed zero |
39 | } |
40 | // c is not a type parameter so it's underlying type is basic. |
41 | |
42 | if t, ok := c.Type().Underlying().(*types.Basic); ok { |
43 | // TODO(adonovan): eliminate untyped constants from SSA form. |
44 | switch t.Kind() { |
45 | case types.Bool, types.UntypedBool: |
46 | return constant.BoolVal(c.Value) |
47 | case types.Int, types.UntypedInt: |
48 | // Assume sizeof(int) is same on host and target. |
49 | return int(c.Int64()) |
50 | case types.Int8: |
51 | return int8(c.Int64()) |
52 | case types.Int16: |
53 | return int16(c.Int64()) |
54 | case types.Int32, types.UntypedRune: |
55 | return int32(c.Int64()) |
56 | case types.Int64: |
57 | return c.Int64() |
58 | case types.Uint: |
59 | // Assume sizeof(uint) is same on host and target. |
60 | return uint(c.Uint64()) |
61 | case types.Uint8: |
62 | return uint8(c.Uint64()) |
63 | case types.Uint16: |
64 | return uint16(c.Uint64()) |
65 | case types.Uint32: |
66 | return uint32(c.Uint64()) |
67 | case types.Uint64: |
68 | return c.Uint64() |
69 | case types.Uintptr: |
70 | // Assume sizeof(uintptr) is same on host and target. |
71 | return uintptr(c.Uint64()) |
72 | case types.Float32: |
73 | return float32(c.Float64()) |
74 | case types.Float64, types.UntypedFloat: |
75 | return c.Float64() |
76 | case types.Complex64: |
77 | return complex64(c.Complex128()) |
78 | case types.Complex128, types.UntypedComplex: |
79 | return c.Complex128() |
80 | case types.String, types.UntypedString: |
81 | if c.Value.Kind() == constant.String { |
82 | return constant.StringVal(c.Value) |
83 | } |
84 | return string(rune(c.Int64())) |
85 | } |
86 | } |
87 | |
88 | panic(fmt.Sprintf("constValue: %s", c)) |
89 | } |
90 | |
91 | // fitsInt returns true if x fits in type int according to sizes. |
92 | func fitsInt(x int64, sizes types.Sizes) bool { |
93 | intSize := sizes.Sizeof(types.Typ[types.Int]) |
94 | if intSize < sizes.Sizeof(types.Typ[types.Int64]) { |
95 | maxInt := int64(1)<<(intSize-1) - 1 |
96 | minInt := -int64(1) << (intSize - 1) |
97 | return minInt <= x && x <= maxInt |
98 | } |
99 | return true |
100 | } |
101 | |
102 | // asInt64 converts x, which must be an integer, to an int64. |
103 | // |
104 | // Callers that need a value directly usable as an int should combine this with fitsInt(). |
105 | func asInt64(x value) int64 { |
106 | switch x := x.(type) { |
107 | case int: |
108 | return int64(x) |
109 | case int8: |
110 | return int64(x) |
111 | case int16: |
112 | return int64(x) |
113 | case int32: |
114 | return int64(x) |
115 | case int64: |
116 | return x |
117 | case uint: |
118 | return int64(x) |
119 | case uint8: |
120 | return int64(x) |
121 | case uint16: |
122 | return int64(x) |
123 | case uint32: |
124 | return int64(x) |
125 | case uint64: |
126 | return int64(x) |
127 | case uintptr: |
128 | return int64(x) |
129 | } |
130 | panic(fmt.Sprintf("cannot convert %T to int64", x)) |
131 | } |
132 | |
133 | // asUint64 converts x, which must be an unsigned integer, to a uint64 |
134 | // suitable for use as a bitwise shift count. |
135 | func asUint64(x value) uint64 { |
136 | switch x := x.(type) { |
137 | case uint: |
138 | return uint64(x) |
139 | case uint8: |
140 | return uint64(x) |
141 | case uint16: |
142 | return uint64(x) |
143 | case uint32: |
144 | return uint64(x) |
145 | case uint64: |
146 | return x |
147 | case uintptr: |
148 | return uint64(x) |
149 | } |
150 | panic(fmt.Sprintf("cannot convert %T to uint64", x)) |
151 | } |
152 | |
153 | // asUnsigned returns the value of x, which must be an integer type, as its equivalent unsigned type, |
154 | // and returns true if x is non-negative. |
155 | func asUnsigned(x value) (value, bool) { |
156 | switch x := x.(type) { |
157 | case int: |
158 | return uint(x), x >= 0 |
159 | case int8: |
160 | return uint8(x), x >= 0 |
161 | case int16: |
162 | return uint16(x), x >= 0 |
163 | case int32: |
164 | return uint32(x), x >= 0 |
165 | case int64: |
166 | return uint64(x), x >= 0 |
167 | case uint, uint8, uint32, uint64, uintptr: |
168 | return x, true |
169 | } |
170 | panic(fmt.Sprintf("cannot convert %T to unsigned", x)) |
171 | } |
172 | |
173 | // zero returns a new "zero" value of the specified type. |
174 | func zero(t types.Type) value { |
175 | switch t := t.(type) { |
176 | case *types.Basic: |
177 | if t.Kind() == types.UntypedNil { |
178 | panic("untyped nil has no zero value") |
179 | } |
180 | if t.Info()&types.IsUntyped != 0 { |
181 | // TODO(adonovan): make it an invariant that |
182 | // this is unreachable. Currently some |
183 | // constants have 'untyped' types when they |
184 | // should be defaulted by the typechecker. |
185 | t = types.Default(t).(*types.Basic) |
186 | } |
187 | switch t.Kind() { |
188 | case types.Bool: |
189 | return false |
190 | case types.Int: |
191 | return int(0) |
192 | case types.Int8: |
193 | return int8(0) |
194 | case types.Int16: |
195 | return int16(0) |
196 | case types.Int32: |
197 | return int32(0) |
198 | case types.Int64: |
199 | return int64(0) |
200 | case types.Uint: |
201 | return uint(0) |
202 | case types.Uint8: |
203 | return uint8(0) |
204 | case types.Uint16: |
205 | return uint16(0) |
206 | case types.Uint32: |
207 | return uint32(0) |
208 | case types.Uint64: |
209 | return uint64(0) |
210 | case types.Uintptr: |
211 | return uintptr(0) |
212 | case types.Float32: |
213 | return float32(0) |
214 | case types.Float64: |
215 | return float64(0) |
216 | case types.Complex64: |
217 | return complex64(0) |
218 | case types.Complex128: |
219 | return complex128(0) |
220 | case types.String: |
221 | return "" |
222 | case types.UnsafePointer: |
223 | return unsafe.Pointer(nil) |
224 | default: |
225 | panic(fmt.Sprint("zero for unexpected type:", t)) |
226 | } |
227 | case *types.Pointer: |
228 | return (*value)(nil) |
229 | case *types.Array: |
230 | a := make(array, t.Len()) |
231 | for i := range a { |
232 | a[i] = zero(t.Elem()) |
233 | } |
234 | return a |
235 | case *types.Named: |
236 | return zero(t.Underlying()) |
237 | case *types.Interface: |
238 | return iface{} // nil type, methodset and value |
239 | case *types.Slice: |
240 | return []value(nil) |
241 | case *types.Struct: |
242 | s := make(structure, t.NumFields()) |
243 | for i := range s { |
244 | s[i] = zero(t.Field(i).Type()) |
245 | } |
246 | return s |
247 | case *types.Tuple: |
248 | if t.Len() == 1 { |
249 | return zero(t.At(0).Type()) |
250 | } |
251 | s := make(tuple, t.Len()) |
252 | for i := range s { |
253 | s[i] = zero(t.At(i).Type()) |
254 | } |
255 | return s |
256 | case *types.Chan: |
257 | return chan value(nil) |
258 | case *types.Map: |
259 | if usesBuiltinMap(t.Key()) { |
260 | return map[value]value(nil) |
261 | } |
262 | return (*hashmap)(nil) |
263 | case *types.Signature: |
264 | return (*ssa.Function)(nil) |
265 | } |
266 | panic(fmt.Sprint("zero: unexpected ", t)) |
267 | } |
268 | |
269 | // slice returns x[lo:hi:max]. Any of lo, hi and max may be nil. |
270 | func slice(x, lo, hi, max value) value { |
271 | var Len, Cap int |
272 | switch x := x.(type) { |
273 | case string: |
274 | Len = len(x) |
275 | case []value: |
276 | Len = len(x) |
277 | Cap = cap(x) |
278 | case *value: // *array |
279 | a := (*x).(array) |
280 | Len = len(a) |
281 | Cap = cap(a) |
282 | } |
283 | |
284 | l := int64(0) |
285 | if lo != nil { |
286 | l = asInt64(lo) |
287 | } |
288 | |
289 | h := int64(Len) |
290 | if hi != nil { |
291 | h = asInt64(hi) |
292 | } |
293 | |
294 | m := int64(Cap) |
295 | if max != nil { |
296 | m = asInt64(max) |
297 | } |
298 | |
299 | switch x := x.(type) { |
300 | case string: |
301 | return x[l:h] |
302 | case []value: |
303 | return x[l:h:m] |
304 | case *value: // *array |
305 | a := (*x).(array) |
306 | return []value(a)[l:h:m] |
307 | } |
308 | panic(fmt.Sprintf("slice: unexpected X type: %T", x)) |
309 | } |
310 | |
311 | // lookup returns x[idx] where x is a map. |
312 | func lookup(instr *ssa.Lookup, x, idx value) value { |
313 | switch x := x.(type) { // map or string |
314 | case map[value]value, *hashmap: |
315 | var v value |
316 | var ok bool |
317 | switch x := x.(type) { |
318 | case map[value]value: |
319 | v, ok = x[idx] |
320 | case *hashmap: |
321 | v = x.lookup(idx.(hashable)) |
322 | ok = v != nil |
323 | } |
324 | if !ok { |
325 | v = zero(instr.X.Type().Underlying().(*types.Map).Elem()) |
326 | } |
327 | if instr.CommaOk { |
328 | v = tuple{v, ok} |
329 | } |
330 | return v |
331 | } |
332 | panic(fmt.Sprintf("unexpected x type in Lookup: %T", x)) |
333 | } |
334 | |
335 | // binop implements all arithmetic and logical binary operators for |
336 | // numeric datatypes and strings. Both operands must have identical |
337 | // dynamic type. |
338 | func binop(op token.Token, t types.Type, x, y value) value { |
339 | switch op { |
340 | case token.ADD: |
341 | switch x.(type) { |
342 | case int: |
343 | return x.(int) + y.(int) |
344 | case int8: |
345 | return x.(int8) + y.(int8) |
346 | case int16: |
347 | return x.(int16) + y.(int16) |
348 | case int32: |
349 | return x.(int32) + y.(int32) |
350 | case int64: |
351 | return x.(int64) + y.(int64) |
352 | case uint: |
353 | return x.(uint) + y.(uint) |
354 | case uint8: |
355 | return x.(uint8) + y.(uint8) |
356 | case uint16: |
357 | return x.(uint16) + y.(uint16) |
358 | case uint32: |
359 | return x.(uint32) + y.(uint32) |
360 | case uint64: |
361 | return x.(uint64) + y.(uint64) |
362 | case uintptr: |
363 | return x.(uintptr) + y.(uintptr) |
364 | case float32: |
365 | return x.(float32) + y.(float32) |
366 | case float64: |
367 | return x.(float64) + y.(float64) |
368 | case complex64: |
369 | return x.(complex64) + y.(complex64) |
370 | case complex128: |
371 | return x.(complex128) + y.(complex128) |
372 | case string: |
373 | return x.(string) + y.(string) |
374 | } |
375 | |
376 | case token.SUB: |
377 | switch x.(type) { |
378 | case int: |
379 | return x.(int) - y.(int) |
380 | case int8: |
381 | return x.(int8) - y.(int8) |
382 | case int16: |
383 | return x.(int16) - y.(int16) |
384 | case int32: |
385 | return x.(int32) - y.(int32) |
386 | case int64: |
387 | return x.(int64) - y.(int64) |
388 | case uint: |
389 | return x.(uint) - y.(uint) |
390 | case uint8: |
391 | return x.(uint8) - y.(uint8) |
392 | case uint16: |
393 | return x.(uint16) - y.(uint16) |
394 | case uint32: |
395 | return x.(uint32) - y.(uint32) |
396 | case uint64: |
397 | return x.(uint64) - y.(uint64) |
398 | case uintptr: |
399 | return x.(uintptr) - y.(uintptr) |
400 | case float32: |
401 | return x.(float32) - y.(float32) |
402 | case float64: |
403 | return x.(float64) - y.(float64) |
404 | case complex64: |
405 | return x.(complex64) - y.(complex64) |
406 | case complex128: |
407 | return x.(complex128) - y.(complex128) |
408 | } |
409 | |
410 | case token.MUL: |
411 | switch x.(type) { |
412 | case int: |
413 | return x.(int) * y.(int) |
414 | case int8: |
415 | return x.(int8) * y.(int8) |
416 | case int16: |
417 | return x.(int16) * y.(int16) |
418 | case int32: |
419 | return x.(int32) * y.(int32) |
420 | case int64: |
421 | return x.(int64) * y.(int64) |
422 | case uint: |
423 | return x.(uint) * y.(uint) |
424 | case uint8: |
425 | return x.(uint8) * y.(uint8) |
426 | case uint16: |
427 | return x.(uint16) * y.(uint16) |
428 | case uint32: |
429 | return x.(uint32) * y.(uint32) |
430 | case uint64: |
431 | return x.(uint64) * y.(uint64) |
432 | case uintptr: |
433 | return x.(uintptr) * y.(uintptr) |
434 | case float32: |
435 | return x.(float32) * y.(float32) |
436 | case float64: |
437 | return x.(float64) * y.(float64) |
438 | case complex64: |
439 | return x.(complex64) * y.(complex64) |
440 | case complex128: |
441 | return x.(complex128) * y.(complex128) |
442 | } |
443 | |
444 | case token.QUO: |
445 | switch x.(type) { |
446 | case int: |
447 | return x.(int) / y.(int) |
448 | case int8: |
449 | return x.(int8) / y.(int8) |
450 | case int16: |
451 | return x.(int16) / y.(int16) |
452 | case int32: |
453 | return x.(int32) / y.(int32) |
454 | case int64: |
455 | return x.(int64) / y.(int64) |
456 | case uint: |
457 | return x.(uint) / y.(uint) |
458 | case uint8: |
459 | return x.(uint8) / y.(uint8) |
460 | case uint16: |
461 | return x.(uint16) / y.(uint16) |
462 | case uint32: |
463 | return x.(uint32) / y.(uint32) |
464 | case uint64: |
465 | return x.(uint64) / y.(uint64) |
466 | case uintptr: |
467 | return x.(uintptr) / y.(uintptr) |
468 | case float32: |
469 | return x.(float32) / y.(float32) |
470 | case float64: |
471 | return x.(float64) / y.(float64) |
472 | case complex64: |
473 | return x.(complex64) / y.(complex64) |
474 | case complex128: |
475 | return x.(complex128) / y.(complex128) |
476 | } |
477 | |
478 | case token.REM: |
479 | switch x.(type) { |
480 | case int: |
481 | return x.(int) % y.(int) |
482 | case int8: |
483 | return x.(int8) % y.(int8) |
484 | case int16: |
485 | return x.(int16) % y.(int16) |
486 | case int32: |
487 | return x.(int32) % y.(int32) |
488 | case int64: |
489 | return x.(int64) % y.(int64) |
490 | case uint: |
491 | return x.(uint) % y.(uint) |
492 | case uint8: |
493 | return x.(uint8) % y.(uint8) |
494 | case uint16: |
495 | return x.(uint16) % y.(uint16) |
496 | case uint32: |
497 | return x.(uint32) % y.(uint32) |
498 | case uint64: |
499 | return x.(uint64) % y.(uint64) |
500 | case uintptr: |
501 | return x.(uintptr) % y.(uintptr) |
502 | } |
503 | |
504 | case token.AND: |
505 | switch x.(type) { |
506 | case int: |
507 | return x.(int) & y.(int) |
508 | case int8: |
509 | return x.(int8) & y.(int8) |
510 | case int16: |
511 | return x.(int16) & y.(int16) |
512 | case int32: |
513 | return x.(int32) & y.(int32) |
514 | case int64: |
515 | return x.(int64) & y.(int64) |
516 | case uint: |
517 | return x.(uint) & y.(uint) |
518 | case uint8: |
519 | return x.(uint8) & y.(uint8) |
520 | case uint16: |
521 | return x.(uint16) & y.(uint16) |
522 | case uint32: |
523 | return x.(uint32) & y.(uint32) |
524 | case uint64: |
525 | return x.(uint64) & y.(uint64) |
526 | case uintptr: |
527 | return x.(uintptr) & y.(uintptr) |
528 | } |
529 | |
530 | case token.OR: |
531 | switch x.(type) { |
532 | case int: |
533 | return x.(int) | y.(int) |
534 | case int8: |
535 | return x.(int8) | y.(int8) |
536 | case int16: |
537 | return x.(int16) | y.(int16) |
538 | case int32: |
539 | return x.(int32) | y.(int32) |
540 | case int64: |
541 | return x.(int64) | y.(int64) |
542 | case uint: |
543 | return x.(uint) | y.(uint) |
544 | case uint8: |
545 | return x.(uint8) | y.(uint8) |
546 | case uint16: |
547 | return x.(uint16) | y.(uint16) |
548 | case uint32: |
549 | return x.(uint32) | y.(uint32) |
550 | case uint64: |
551 | return x.(uint64) | y.(uint64) |
552 | case uintptr: |
553 | return x.(uintptr) | y.(uintptr) |
554 | } |
555 | |
556 | case token.XOR: |
557 | switch x.(type) { |
558 | case int: |
559 | return x.(int) ^ y.(int) |
560 | case int8: |
561 | return x.(int8) ^ y.(int8) |
562 | case int16: |
563 | return x.(int16) ^ y.(int16) |
564 | case int32: |
565 | return x.(int32) ^ y.(int32) |
566 | case int64: |
567 | return x.(int64) ^ y.(int64) |
568 | case uint: |
569 | return x.(uint) ^ y.(uint) |
570 | case uint8: |
571 | return x.(uint8) ^ y.(uint8) |
572 | case uint16: |
573 | return x.(uint16) ^ y.(uint16) |
574 | case uint32: |
575 | return x.(uint32) ^ y.(uint32) |
576 | case uint64: |
577 | return x.(uint64) ^ y.(uint64) |
578 | case uintptr: |
579 | return x.(uintptr) ^ y.(uintptr) |
580 | } |
581 | |
582 | case token.AND_NOT: |
583 | switch x.(type) { |
584 | case int: |
585 | return x.(int) &^ y.(int) |
586 | case int8: |
587 | return x.(int8) &^ y.(int8) |
588 | case int16: |
589 | return x.(int16) &^ y.(int16) |
590 | case int32: |
591 | return x.(int32) &^ y.(int32) |
592 | case int64: |
593 | return x.(int64) &^ y.(int64) |
594 | case uint: |
595 | return x.(uint) &^ y.(uint) |
596 | case uint8: |
597 | return x.(uint8) &^ y.(uint8) |
598 | case uint16: |
599 | return x.(uint16) &^ y.(uint16) |
600 | case uint32: |
601 | return x.(uint32) &^ y.(uint32) |
602 | case uint64: |
603 | return x.(uint64) &^ y.(uint64) |
604 | case uintptr: |
605 | return x.(uintptr) &^ y.(uintptr) |
606 | } |
607 | |
608 | case token.SHL: |
609 | u, ok := asUnsigned(y) |
610 | if !ok { |
611 | panic("negative shift amount") |
612 | } |
613 | y := asUint64(u) |
614 | switch x.(type) { |
615 | case int: |
616 | return x.(int) << y |
617 | case int8: |
618 | return x.(int8) << y |
619 | case int16: |
620 | return x.(int16) << y |
621 | case int32: |
622 | return x.(int32) << y |
623 | case int64: |
624 | return x.(int64) << y |
625 | case uint: |
626 | return x.(uint) << y |
627 | case uint8: |
628 | return x.(uint8) << y |
629 | case uint16: |
630 | return x.(uint16) << y |
631 | case uint32: |
632 | return x.(uint32) << y |
633 | case uint64: |
634 | return x.(uint64) << y |
635 | case uintptr: |
636 | return x.(uintptr) << y |
637 | } |
638 | |
639 | case token.SHR: |
640 | u, ok := asUnsigned(y) |
641 | if !ok { |
642 | panic("negative shift amount") |
643 | } |
644 | y := asUint64(u) |
645 | switch x.(type) { |
646 | case int: |
647 | return x.(int) >> y |
648 | case int8: |
649 | return x.(int8) >> y |
650 | case int16: |
651 | return x.(int16) >> y |
652 | case int32: |
653 | return x.(int32) >> y |
654 | case int64: |
655 | return x.(int64) >> y |
656 | case uint: |
657 | return x.(uint) >> y |
658 | case uint8: |
659 | return x.(uint8) >> y |
660 | case uint16: |
661 | return x.(uint16) >> y |
662 | case uint32: |
663 | return x.(uint32) >> y |
664 | case uint64: |
665 | return x.(uint64) >> y |
666 | case uintptr: |
667 | return x.(uintptr) >> y |
668 | } |
669 | |
670 | case token.LSS: |
671 | switch x.(type) { |
672 | case int: |
673 | return x.(int) < y.(int) |
674 | case int8: |
675 | return x.(int8) < y.(int8) |
676 | case int16: |
677 | return x.(int16) < y.(int16) |
678 | case int32: |
679 | return x.(int32) < y.(int32) |
680 | case int64: |
681 | return x.(int64) < y.(int64) |
682 | case uint: |
683 | return x.(uint) < y.(uint) |
684 | case uint8: |
685 | return x.(uint8) < y.(uint8) |
686 | case uint16: |
687 | return x.(uint16) < y.(uint16) |
688 | case uint32: |
689 | return x.(uint32) < y.(uint32) |
690 | case uint64: |
691 | return x.(uint64) < y.(uint64) |
692 | case uintptr: |
693 | return x.(uintptr) < y.(uintptr) |
694 | case float32: |
695 | return x.(float32) < y.(float32) |
696 | case float64: |
697 | return x.(float64) < y.(float64) |
698 | case string: |
699 | return x.(string) < y.(string) |
700 | } |
701 | |
702 | case token.LEQ: |
703 | switch x.(type) { |
704 | case int: |
705 | return x.(int) <= y.(int) |
706 | case int8: |
707 | return x.(int8) <= y.(int8) |
708 | case int16: |
709 | return x.(int16) <= y.(int16) |
710 | case int32: |
711 | return x.(int32) <= y.(int32) |
712 | case int64: |
713 | return x.(int64) <= y.(int64) |
714 | case uint: |
715 | return x.(uint) <= y.(uint) |
716 | case uint8: |
717 | return x.(uint8) <= y.(uint8) |
718 | case uint16: |
719 | return x.(uint16) <= y.(uint16) |
720 | case uint32: |
721 | return x.(uint32) <= y.(uint32) |
722 | case uint64: |
723 | return x.(uint64) <= y.(uint64) |
724 | case uintptr: |
725 | return x.(uintptr) <= y.(uintptr) |
726 | case float32: |
727 | return x.(float32) <= y.(float32) |
728 | case float64: |
729 | return x.(float64) <= y.(float64) |
730 | case string: |
731 | return x.(string) <= y.(string) |
732 | } |
733 | |
734 | case token.EQL: |
735 | return eqnil(t, x, y) |
736 | |
737 | case token.NEQ: |
738 | return !eqnil(t, x, y) |
739 | |
740 | case token.GTR: |
741 | switch x.(type) { |
742 | case int: |
743 | return x.(int) > y.(int) |
744 | case int8: |
745 | return x.(int8) > y.(int8) |
746 | case int16: |
747 | return x.(int16) > y.(int16) |
748 | case int32: |
749 | return x.(int32) > y.(int32) |
750 | case int64: |
751 | return x.(int64) > y.(int64) |
752 | case uint: |
753 | return x.(uint) > y.(uint) |
754 | case uint8: |
755 | return x.(uint8) > y.(uint8) |
756 | case uint16: |
757 | return x.(uint16) > y.(uint16) |
758 | case uint32: |
759 | return x.(uint32) > y.(uint32) |
760 | case uint64: |
761 | return x.(uint64) > y.(uint64) |
762 | case uintptr: |
763 | return x.(uintptr) > y.(uintptr) |
764 | case float32: |
765 | return x.(float32) > y.(float32) |
766 | case float64: |
767 | return x.(float64) > y.(float64) |
768 | case string: |
769 | return x.(string) > y.(string) |
770 | } |
771 | |
772 | case token.GEQ: |
773 | switch x.(type) { |
774 | case int: |
775 | return x.(int) >= y.(int) |
776 | case int8: |
777 | return x.(int8) >= y.(int8) |
778 | case int16: |
779 | return x.(int16) >= y.(int16) |
780 | case int32: |
781 | return x.(int32) >= y.(int32) |
782 | case int64: |
783 | return x.(int64) >= y.(int64) |
784 | case uint: |
785 | return x.(uint) >= y.(uint) |
786 | case uint8: |
787 | return x.(uint8) >= y.(uint8) |
788 | case uint16: |
789 | return x.(uint16) >= y.(uint16) |
790 | case uint32: |
791 | return x.(uint32) >= y.(uint32) |
792 | case uint64: |
793 | return x.(uint64) >= y.(uint64) |
794 | case uintptr: |
795 | return x.(uintptr) >= y.(uintptr) |
796 | case float32: |
797 | return x.(float32) >= y.(float32) |
798 | case float64: |
799 | return x.(float64) >= y.(float64) |
800 | case string: |
801 | return x.(string) >= y.(string) |
802 | } |
803 | } |
804 | panic(fmt.Sprintf("invalid binary op: %T %s %T", x, op, y)) |
805 | } |
806 | |
807 | // eqnil returns the comparison x == y using the equivalence relation |
808 | // appropriate for type t. |
809 | // If t is a reference type, at most one of x or y may be a nil value |
810 | // of that type. |
811 | func eqnil(t types.Type, x, y value) bool { |
812 | switch t.Underlying().(type) { |
813 | case *types.Map, *types.Signature, *types.Slice: |
814 | // Since these types don't support comparison, |
815 | // one of the operands must be a literal nil. |
816 | switch x := x.(type) { |
817 | case *hashmap: |
818 | return (x != nil) == (y.(*hashmap) != nil) |
819 | case map[value]value: |
820 | return (x != nil) == (y.(map[value]value) != nil) |
821 | case *ssa.Function: |
822 | switch y := y.(type) { |
823 | case *ssa.Function: |
824 | return (x != nil) == (y != nil) |
825 | case *closure: |
826 | return true |
827 | } |
828 | case *closure: |
829 | return (x != nil) == (y.(*ssa.Function) != nil) |
830 | case []value: |
831 | return (x != nil) == (y.([]value) != nil) |
832 | } |
833 | panic(fmt.Sprintf("eqnil(%s): illegal dynamic type: %T", t, x)) |
834 | } |
835 | |
836 | return equals(t, x, y) |
837 | } |
838 | |
839 | func unop(instr *ssa.UnOp, x value) value { |
840 | switch instr.Op { |
841 | case token.ARROW: // receive |
842 | v, ok := <-x.(chan value) |
843 | if !ok { |
844 | v = zero(instr.X.Type().Underlying().(*types.Chan).Elem()) |
845 | } |
846 | if instr.CommaOk { |
847 | v = tuple{v, ok} |
848 | } |
849 | return v |
850 | case token.SUB: |
851 | switch x := x.(type) { |
852 | case int: |
853 | return -x |
854 | case int8: |
855 | return -x |
856 | case int16: |
857 | return -x |
858 | case int32: |
859 | return -x |
860 | case int64: |
861 | return -x |
862 | case uint: |
863 | return -x |
864 | case uint8: |
865 | return -x |
866 | case uint16: |
867 | return -x |
868 | case uint32: |
869 | return -x |
870 | case uint64: |
871 | return -x |
872 | case uintptr: |
873 | return -x |
874 | case float32: |
875 | return -x |
876 | case float64: |
877 | return -x |
878 | case complex64: |
879 | return -x |
880 | case complex128: |
881 | return -x |
882 | } |
883 | case token.MUL: |
884 | return load(deref(instr.X.Type()), x.(*value)) |
885 | case token.NOT: |
886 | return !x.(bool) |
887 | case token.XOR: |
888 | switch x := x.(type) { |
889 | case int: |
890 | return ^x |
891 | case int8: |
892 | return ^x |
893 | case int16: |
894 | return ^x |
895 | case int32: |
896 | return ^x |
897 | case int64: |
898 | return ^x |
899 | case uint: |
900 | return ^x |
901 | case uint8: |
902 | return ^x |
903 | case uint16: |
904 | return ^x |
905 | case uint32: |
906 | return ^x |
907 | case uint64: |
908 | return ^x |
909 | case uintptr: |
910 | return ^x |
911 | } |
912 | } |
913 | panic(fmt.Sprintf("invalid unary op %s %T", instr.Op, x)) |
914 | } |
915 | |
916 | // typeAssert checks whether dynamic type of itf is instr.AssertedType. |
917 | // It returns the extracted value on success, and panics on failure, |
918 | // unless instr.CommaOk, in which case it always returns a "value,ok" tuple. |
919 | func typeAssert(i *interpreter, instr *ssa.TypeAssert, itf iface) value { |
920 | var v value |
921 | err := "" |
922 | if itf.t == nil { |
923 | err = fmt.Sprintf("interface conversion: interface is nil, not %s", instr.AssertedType) |
924 | |
925 | } else if idst, ok := instr.AssertedType.Underlying().(*types.Interface); ok { |
926 | v = itf |
927 | err = checkInterface(i, idst, itf) |
928 | |
929 | } else if types.Identical(itf.t, instr.AssertedType) { |
930 | v = itf.v // extract value |
931 | |
932 | } else { |
933 | err = fmt.Sprintf("interface conversion: interface is %s, not %s", itf.t, instr.AssertedType) |
934 | } |
935 | |
936 | if err != "" { |
937 | if !instr.CommaOk { |
938 | panic(err) |
939 | } |
940 | return tuple{zero(instr.AssertedType), false} |
941 | } |
942 | if instr.CommaOk { |
943 | return tuple{v, true} |
944 | } |
945 | return v |
946 | } |
947 | |
948 | // If CapturedOutput is non-nil, all writes by the interpreted program |
949 | // to file descriptors 1 and 2 will also be written to CapturedOutput. |
950 | // |
951 | // (The $GOROOT/test system requires that the test be considered a |
952 | // failure if "BUG" appears in the combined stdout/stderr output, even |
953 | // if it exits zero. This is a global variable shared by all |
954 | // interpreters in the same process.) |
955 | var CapturedOutput *bytes.Buffer |
956 | var capturedOutputMu sync.Mutex |
957 | |
958 | // write writes bytes b to the target program's standard output. |
959 | // The print/println built-ins and the write() system call funnel |
960 | // through here so they can be captured by the test driver. |
961 | func print(b []byte) (int, error) { |
962 | if CapturedOutput != nil { |
963 | capturedOutputMu.Lock() |
964 | CapturedOutput.Write(b) // ignore errors |
965 | capturedOutputMu.Unlock() |
966 | } |
967 | return os.Stdout.Write(b) |
968 | } |
969 | |
970 | // callBuiltin interprets a call to builtin fn with arguments args, |
971 | // returning its result. |
972 | func callBuiltin(caller *frame, callpos token.Pos, fn *ssa.Builtin, args []value) value { |
973 | switch fn.Name() { |
974 | case "append": |
975 | if len(args) == 1 { |
976 | return args[0] |
977 | } |
978 | if s, ok := args[1].(string); ok { |
979 | // append([]byte, ...string) []byte |
980 | arg0 := args[0].([]value) |
981 | for i := 0; i < len(s); i++ { |
982 | arg0 = append(arg0, s[i]) |
983 | } |
984 | return arg0 |
985 | } |
986 | // append([]T, ...[]T) []T |
987 | return append(args[0].([]value), args[1].([]value)...) |
988 | |
989 | case "copy": // copy([]T, []T) int or copy([]byte, string) int |
990 | src := args[1] |
991 | if _, ok := src.(string); ok { |
992 | params := fn.Type().(*types.Signature).Params() |
993 | src = conv(params.At(0).Type(), params.At(1).Type(), src) |
994 | } |
995 | return copy(args[0].([]value), src.([]value)) |
996 | |
997 | case "close": // close(chan T) |
998 | close(args[0].(chan value)) |
999 | return nil |
1000 | |
1001 | case "delete": // delete(map[K]value, K) |
1002 | switch m := args[0].(type) { |
1003 | case map[value]value: |
1004 | delete(m, args[1]) |
1005 | case *hashmap: |
1006 | m.delete(args[1].(hashable)) |
1007 | default: |
1008 | panic(fmt.Sprintf("illegal map type: %T", m)) |
1009 | } |
1010 | return nil |
1011 | |
1012 | case "print", "println": // print(any, ...) |
1013 | ln := fn.Name() == "println" |
1014 | var buf bytes.Buffer |
1015 | for i, arg := range args { |
1016 | if i > 0 && ln { |
1017 | buf.WriteRune(' ') |
1018 | } |
1019 | buf.WriteString(toString(arg)) |
1020 | } |
1021 | if ln { |
1022 | buf.WriteRune('\n') |
1023 | } |
1024 | print(buf.Bytes()) |
1025 | return nil |
1026 | |
1027 | case "len": |
1028 | switch x := args[0].(type) { |
1029 | case string: |
1030 | return len(x) |
1031 | case array: |
1032 | return len(x) |
1033 | case *value: |
1034 | return len((*x).(array)) |
1035 | case []value: |
1036 | return len(x) |
1037 | case map[value]value: |
1038 | return len(x) |
1039 | case *hashmap: |
1040 | return x.len() |
1041 | case chan value: |
1042 | return len(x) |
1043 | default: |
1044 | panic(fmt.Sprintf("len: illegal operand: %T", x)) |
1045 | } |
1046 | |
1047 | case "cap": |
1048 | switch x := args[0].(type) { |
1049 | case array: |
1050 | return cap(x) |
1051 | case *value: |
1052 | return cap((*x).(array)) |
1053 | case []value: |
1054 | return cap(x) |
1055 | case chan value: |
1056 | return cap(x) |
1057 | default: |
1058 | panic(fmt.Sprintf("cap: illegal operand: %T", x)) |
1059 | } |
1060 | |
1061 | case "real": |
1062 | switch c := args[0].(type) { |
1063 | case complex64: |
1064 | return real(c) |
1065 | case complex128: |
1066 | return real(c) |
1067 | default: |
1068 | panic(fmt.Sprintf("real: illegal operand: %T", c)) |
1069 | } |
1070 | |
1071 | case "imag": |
1072 | switch c := args[0].(type) { |
1073 | case complex64: |
1074 | return imag(c) |
1075 | case complex128: |
1076 | return imag(c) |
1077 | default: |
1078 | panic(fmt.Sprintf("imag: illegal operand: %T", c)) |
1079 | } |
1080 | |
1081 | case "complex": |
1082 | switch f := args[0].(type) { |
1083 | case float32: |
1084 | return complex(f, args[1].(float32)) |
1085 | case float64: |
1086 | return complex(f, args[1].(float64)) |
1087 | default: |
1088 | panic(fmt.Sprintf("complex: illegal operand: %T", f)) |
1089 | } |
1090 | |
1091 | case "panic": |
1092 | // ssa.Panic handles most cases; this is only for "go |
1093 | // panic" or "defer panic". |
1094 | panic(targetPanic{args[0]}) |
1095 | |
1096 | case "recover": |
1097 | return doRecover(caller) |
1098 | |
1099 | case "ssa:wrapnilchk": |
1100 | recv := args[0] |
1101 | if recv.(*value) == nil { |
1102 | recvType := args[1] |
1103 | methodName := args[2] |
1104 | panic(fmt.Sprintf("value method (%s).%s called using nil *%s pointer", |
1105 | recvType, methodName, recvType)) |
1106 | } |
1107 | return recv |
1108 | } |
1109 | |
1110 | panic("unknown built-in: " + fn.Name()) |
1111 | } |
1112 | |
1113 | func rangeIter(x value, t types.Type) iter { |
1114 | switch x := x.(type) { |
1115 | case map[value]value: |
1116 | return &mapIter{iter: reflect.ValueOf(x).MapRange()} |
1117 | case *hashmap: |
1118 | return &hashmapIter{iter: reflect.ValueOf(x.entries()).MapRange()} |
1119 | case string: |
1120 | return &stringIter{Reader: strings.NewReader(x)} |
1121 | } |
1122 | panic(fmt.Sprintf("cannot range over %T", x)) |
1123 | } |
1124 | |
1125 | // widen widens a basic typed value x to the widest type of its |
1126 | // category, one of: |
1127 | // |
1128 | // bool, int64, uint64, float64, complex128, string. |
1129 | // |
1130 | // This is inefficient but reduces the size of the cross-product of |
1131 | // cases we have to consider. |
1132 | func widen(x value) value { |
1133 | switch y := x.(type) { |
1134 | case bool, int64, uint64, float64, complex128, string, unsafe.Pointer: |
1135 | return x |
1136 | case int: |
1137 | return int64(y) |
1138 | case int8: |
1139 | return int64(y) |
1140 | case int16: |
1141 | return int64(y) |
1142 | case int32: |
1143 | return int64(y) |
1144 | case uint: |
1145 | return uint64(y) |
1146 | case uint8: |
1147 | return uint64(y) |
1148 | case uint16: |
1149 | return uint64(y) |
1150 | case uint32: |
1151 | return uint64(y) |
1152 | case uintptr: |
1153 | return uint64(y) |
1154 | case float32: |
1155 | return float64(y) |
1156 | case complex64: |
1157 | return complex128(y) |
1158 | } |
1159 | panic(fmt.Sprintf("cannot widen %T", x)) |
1160 | } |
1161 | |
1162 | // conv converts the value x of type t_src to type t_dst and returns |
1163 | // the result. |
1164 | // Possible cases are described with the ssa.Convert operator. |
1165 | func conv(t_dst, t_src types.Type, x value) value { |
1166 | ut_src := t_src.Underlying() |
1167 | ut_dst := t_dst.Underlying() |
1168 | |
1169 | // Destination type is not an "untyped" type. |
1170 | if b, ok := ut_dst.(*types.Basic); ok && b.Info()&types.IsUntyped != 0 { |
1171 | panic("oops: conversion to 'untyped' type: " + b.String()) |
1172 | } |
1173 | |
1174 | // Nor is it an interface type. |
1175 | if _, ok := ut_dst.(*types.Interface); ok { |
1176 | if _, ok := ut_src.(*types.Interface); ok { |
1177 | panic("oops: Convert should be ChangeInterface") |
1178 | } else { |
1179 | panic("oops: Convert should be MakeInterface") |
1180 | } |
1181 | } |
1182 | |
1183 | // Remaining conversions: |
1184 | // + untyped string/number/bool constant to a specific |
1185 | // representation. |
1186 | // + conversions between non-complex numeric types. |
1187 | // + conversions between complex numeric types. |
1188 | // + integer/[]byte/[]rune -> string. |
1189 | // + string -> []byte/[]rune. |
1190 | // |
1191 | // All are treated the same: first we extract the value to the |
1192 | // widest representation (int64, uint64, float64, complex128, |
1193 | // or string), then we convert it to the desired type. |
1194 | |
1195 | switch ut_src := ut_src.(type) { |
1196 | case *types.Pointer: |
1197 | switch ut_dst := ut_dst.(type) { |
1198 | case *types.Basic: |
1199 | // *value to unsafe.Pointer? |
1200 | if ut_dst.Kind() == types.UnsafePointer { |
1201 | return unsafe.Pointer(x.(*value)) |
1202 | } |
1203 | } |
1204 | |
1205 | case *types.Slice: |
1206 | // []byte or []rune -> string |
1207 | // TODO(adonovan): fix: type B byte; conv([]B -> string). |
1208 | switch ut_src.Elem().(*types.Basic).Kind() { |
1209 | case types.Byte: |
1210 | x := x.([]value) |
1211 | b := make([]byte, 0, len(x)) |
1212 | for i := range x { |
1213 | b = append(b, x[i].(byte)) |
1214 | } |
1215 | return string(b) |
1216 | |
1217 | case types.Rune: |
1218 | x := x.([]value) |
1219 | r := make([]rune, 0, len(x)) |
1220 | for i := range x { |
1221 | r = append(r, x[i].(rune)) |
1222 | } |
1223 | return string(r) |
1224 | } |
1225 | |
1226 | case *types.Basic: |
1227 | x = widen(x) |
1228 | |
1229 | // integer -> string? |
1230 | // TODO(adonovan): fix: test integer -> named alias of string. |
1231 | if ut_src.Info()&types.IsInteger != 0 { |
1232 | if ut_dst, ok := ut_dst.(*types.Basic); ok && ut_dst.Kind() == types.String { |
1233 | return fmt.Sprintf("%c", x) |
1234 | } |
1235 | } |
1236 | |
1237 | // string -> []rune, []byte or string? |
1238 | if s, ok := x.(string); ok { |
1239 | switch ut_dst := ut_dst.(type) { |
1240 | case *types.Slice: |
1241 | var res []value |
1242 | // TODO(adonovan): fix: test named alias of rune, byte. |
1243 | switch ut_dst.Elem().(*types.Basic).Kind() { |
1244 | case types.Rune: |
1245 | for _, r := range []rune(s) { |
1246 | res = append(res, r) |
1247 | } |
1248 | return res |
1249 | case types.Byte: |
1250 | for _, b := range []byte(s) { |
1251 | res = append(res, b) |
1252 | } |
1253 | return res |
1254 | } |
1255 | case *types.Basic: |
1256 | if ut_dst.Kind() == types.String { |
1257 | return x.(string) |
1258 | } |
1259 | } |
1260 | break // fail: no other conversions for string |
1261 | } |
1262 | |
1263 | // unsafe.Pointer -> *value |
1264 | if ut_src.Kind() == types.UnsafePointer { |
1265 | // TODO(adonovan): this is wrong and cannot |
1266 | // really be fixed with the current design. |
1267 | // |
1268 | // return (*value)(x.(unsafe.Pointer)) |
1269 | // creates a new pointer of a different |
1270 | // type but the underlying interface value |
1271 | // knows its "true" type and so cannot be |
1272 | // meaningfully used through the new pointer. |
1273 | // |
1274 | // To make this work, the interpreter needs to |
1275 | // simulate the memory layout of a real |
1276 | // compiled implementation. |
1277 | // |
1278 | // To at least preserve type-safety, we'll |
1279 | // just return the zero value of the |
1280 | // destination type. |
1281 | return zero(t_dst) |
1282 | } |
1283 | |
1284 | // Conversions between complex numeric types? |
1285 | if ut_src.Info()&types.IsComplex != 0 { |
1286 | switch ut_dst.(*types.Basic).Kind() { |
1287 | case types.Complex64: |
1288 | return complex64(x.(complex128)) |
1289 | case types.Complex128: |
1290 | return x.(complex128) |
1291 | } |
1292 | break // fail: no other conversions for complex |
1293 | } |
1294 | |
1295 | // Conversions between non-complex numeric types? |
1296 | if ut_src.Info()&types.IsNumeric != 0 { |
1297 | kind := ut_dst.(*types.Basic).Kind() |
1298 | switch x := x.(type) { |
1299 | case int64: // signed integer -> numeric? |
1300 | switch kind { |
1301 | case types.Int: |
1302 | return int(x) |
1303 | case types.Int8: |
1304 | return int8(x) |
1305 | case types.Int16: |
1306 | return int16(x) |
1307 | case types.Int32: |
1308 | return int32(x) |
1309 | case types.Int64: |
1310 | return int64(x) |
1311 | case types.Uint: |
1312 | return uint(x) |
1313 | case types.Uint8: |
1314 | return uint8(x) |
1315 | case types.Uint16: |
1316 | return uint16(x) |
1317 | case types.Uint32: |
1318 | return uint32(x) |
1319 | case types.Uint64: |
1320 | return uint64(x) |
1321 | case types.Uintptr: |
1322 | return uintptr(x) |
1323 | case types.Float32: |
1324 | return float32(x) |
1325 | case types.Float64: |
1326 | return float64(x) |
1327 | } |
1328 | |
1329 | case uint64: // unsigned integer -> numeric? |
1330 | switch kind { |
1331 | case types.Int: |
1332 | return int(x) |
1333 | case types.Int8: |
1334 | return int8(x) |
1335 | case types.Int16: |
1336 | return int16(x) |
1337 | case types.Int32: |
1338 | return int32(x) |
1339 | case types.Int64: |
1340 | return int64(x) |
1341 | case types.Uint: |
1342 | return uint(x) |
1343 | case types.Uint8: |
1344 | return uint8(x) |
1345 | case types.Uint16: |
1346 | return uint16(x) |
1347 | case types.Uint32: |
1348 | return uint32(x) |
1349 | case types.Uint64: |
1350 | return uint64(x) |
1351 | case types.Uintptr: |
1352 | return uintptr(x) |
1353 | case types.Float32: |
1354 | return float32(x) |
1355 | case types.Float64: |
1356 | return float64(x) |
1357 | } |
1358 | |
1359 | case float64: // floating point -> numeric? |
1360 | switch kind { |
1361 | case types.Int: |
1362 | return int(x) |
1363 | case types.Int8: |
1364 | return int8(x) |
1365 | case types.Int16: |
1366 | return int16(x) |
1367 | case types.Int32: |
1368 | return int32(x) |
1369 | case types.Int64: |
1370 | return int64(x) |
1371 | case types.Uint: |
1372 | return uint(x) |
1373 | case types.Uint8: |
1374 | return uint8(x) |
1375 | case types.Uint16: |
1376 | return uint16(x) |
1377 | case types.Uint32: |
1378 | return uint32(x) |
1379 | case types.Uint64: |
1380 | return uint64(x) |
1381 | case types.Uintptr: |
1382 | return uintptr(x) |
1383 | case types.Float32: |
1384 | return float32(x) |
1385 | case types.Float64: |
1386 | return float64(x) |
1387 | } |
1388 | } |
1389 | } |
1390 | } |
1391 | |
1392 | panic(fmt.Sprintf("unsupported conversion: %s -> %s, dynamic type %T", t_src, t_dst, x)) |
1393 | } |
1394 | |
1395 | // sliceToArrayPointer converts the value x of type slice to type t_dst |
1396 | // a pointer to array and returns the result. |
1397 | func sliceToArrayPointer(t_dst, t_src types.Type, x value) value { |
1398 | if _, ok := t_src.Underlying().(*types.Slice); ok { |
1399 | if ptr, ok := t_dst.Underlying().(*types.Pointer); ok { |
1400 | if arr, ok := ptr.Elem().Underlying().(*types.Array); ok { |
1401 | x := x.([]value) |
1402 | if arr.Len() > int64(len(x)) { |
1403 | panic("array length is greater than slice length") |
1404 | } |
1405 | if x == nil { |
1406 | return zero(t_dst) |
1407 | } |
1408 | v := value(array(x[:arr.Len()])) |
1409 | return &v |
1410 | } |
1411 | } |
1412 | } |
1413 | |
1414 | panic(fmt.Sprintf("unsupported conversion: %s -> %s, dynamic type %T", t_src, t_dst, x)) |
1415 | } |
1416 | |
1417 | // checkInterface checks that the method set of x implements the |
1418 | // interface itype. |
1419 | // On success it returns "", on failure, an error message. |
1420 | func checkInterface(i *interpreter, itype *types.Interface, x iface) string { |
1421 | if meth, _ := types.MissingMethod(x.t, itype, true); meth != nil { |
1422 | return fmt.Sprintf("interface conversion: %v is not %v: missing method %s", |
1423 | x.t, itype, meth.Name()) |
1424 | } |
1425 | return "" // ok |
1426 | } |
1427 |
Members