GoPLS Viewer

Home|gopls/go/ssa/interp/ops.go
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
5package interp
6
7import (
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.
23type targetPanic struct {
24    v value
25}
26
27func (p targetPanicString() string {
28    return toString(p.v)
29}
30
31// If the target program calls exit, the interpreter panics with this type.
32type exitPanic int
33
34// constValue returns the value of the constant with the
35// dynamic type tag appropriate for c.Type().
36func constValue(c *ssa.Constvalue {
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 tok := c.Type().Underlying().(*types.Basic); ok {
43        // TODO(adonovan): eliminate untyped constants from SSA form.
44        switch t.Kind() {
45        case types.Booltypes.UntypedBool:
46            return constant.BoolVal(c.Value)
47        case types.Inttypes.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.Int32types.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.Float64types.UntypedFloat:
75            return c.Float64()
76        case types.Complex64:
77            return complex64(c.Complex128())
78        case types.Complex128types.UntypedComplex:
79            return c.Complex128()
80        case types.Stringtypes.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.
92func fitsInt(x int64sizes types.Sizesbool {
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().
105func asInt64(x valueint64 {
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.
135func asUint64(x valueuint64 {
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.
155func asUnsigned(x value) (valuebool) {
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 uintuint8uint32uint64uintptr:
168        return xtrue
169    }
170    panic(fmt.Sprintf("cannot convert %T to unsigned"x))
171}
172
173// zero returns a new "zero" value of the specified type.
174func zero(t types.Typevalue {
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(arrayt.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(structuret.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(tuplet.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.
270func slice(xlohimax valuevalue {
271    var LenCap 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.
312func lookup(instr *ssa.Lookupxidx valuevalue {
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            vok = 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{vok}
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.
338func binop(op token.Tokent types.Typexy valuevalue {
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        uok := 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        uok := 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(txy)
736
737    case token.NEQ:
738        return !eqnil(txy)
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"xopy))
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.
811func eqnil(t types.Typexy valuebool {
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"tx))
834    }
835
836    return equals(txy)
837}
838
839func unop(instr *ssa.UnOpx valuevalue {
840    switch instr.Op {
841    case token.ARROW// receive
842        vok := <-x.(chan value)
843        if !ok {
844            v = zero(instr.X.Type().Underlying().(*types.Chan).Elem())
845        }
846        if instr.CommaOk {
847            v = tuple{vok}
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.Opx))
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.
919func typeAssert(i *interpreterinstr *ssa.TypeAssertitf ifacevalue {
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 idstok := instr.AssertedType.Underlying().(*types.Interface); ok {
926        v = itf
927        err = checkInterface(iidstitf)
928
929    } else if types.Identical(itf.tinstr.AssertedType) {
930        v = itf.v // extract value
931
932    } else {
933        err = fmt.Sprintf("interface conversion: interface is %s, not %s"itf.tinstr.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{vtrue}
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.)
955var CapturedOutput *bytes.Buffer
956var 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.
961func print(b []byte) (interror) {
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.
972func callBuiltin(caller *framecallpos token.Posfn *ssa.Builtinargs []valuevalue {
973    switch fn.Name() {
974    case "append":
975        if len(args) == 1 {
976            return args[0]
977        }
978        if sok := args[1].(string); ok {
979            // append([]byte, ...string) []byte
980            arg0 := args[0].([]value)
981            for i := 0i < len(s); i++ {
982                arg0 = append(arg0s[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(margs[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 iarg := 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(fargs[1].(float32))
1085        case float64:
1086            return complex(fargs[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                recvTypemethodNamerecvType))
1106        }
1107        return recv
1108    }
1109
1110    panic("unknown built-in: " + fn.Name())
1111}
1112
1113func rangeIter(x valuet types.Typeiter {
1114    switch x := x.(type) {
1115    case map[value]value:
1116        return &mapIter{iterreflect.ValueOf(x).MapRange()}
1117    case *hashmap:
1118        return &hashmapIter{iterreflect.ValueOf(x.entries()).MapRange()}
1119    case string:
1120        return &stringIter{Readerstrings.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.
1132func widen(x valuevalue {
1133    switch y := x.(type) {
1134    case boolint64uint64float64complex128stringunsafe.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.
1165func conv(t_dstt_src types.Typex valuevalue {
1166    ut_src := t_src.Underlying()
1167    ut_dst := t_dst.Underlying()
1168
1169    // Destination type is not an "untyped" type.
1170    if bok := 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([]byte0len(x))
1212            for i := range x {
1213                b = append(bx[i].(byte))
1214            }
1215            return string(b)
1216
1217        case types.Rune:
1218            x := x.([]value)
1219            r := make([]rune0len(x))
1220            for i := range x {
1221                r = append(rx[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_dstok := 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 sok := 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(resr)
1247                    }
1248                    return res
1249                case types.Byte:
1250                    for _b := range []byte(s) {
1251                        res = append(resb)
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_srct_dstx))
1393}
1394
1395// sliceToArrayPointer converts the value x of type slice to type t_dst
1396// a pointer to array and returns the result.
1397func sliceToArrayPointer(t_dstt_src types.Typex valuevalue {
1398    if _ok := t_src.Underlying().(*types.Slice); ok {
1399        if ptrok := t_dst.Underlying().(*types.Pointer); ok {
1400            if arrok := 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_srct_dstx))
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.
1420func checkInterface(i *interpreteritype *types.Interfacex ifacestring {
1421    if meth_ := types.MissingMethod(x.titypetrue); meth != nil {
1422        return fmt.Sprintf("interface conversion: %v is not %v: missing method %s",
1423            x.titypemeth.Name())
1424    }
1425    return "" // ok
1426}
1427
MembersX
targetPanic
lookup.x
slice.Cap
checkInterface
eqnil.x
zero.BlockStmt.RangeStmt_6005.i
slice.h
eqnil
sliceToArrayPointer.t_dst
checkInterface.x
targetPanic.String
fitsInt
zero.BlockStmt.RangeStmt_5546.i
slice.l
lookup.idx
sync
print
conv
asInt64.x
zero
zero.BlockStmt.a
callBuiltin
constant
conv.BlockStmt.BlockStmt.b
asUint64
rangeIter.x
typeAssert.itf
conv.BlockStmt.BlockStmt.kind
asUint64.x
asUnsigned.x
callBuiltin.BlockStmt.BlockStmt.i
rangeIter.t
checkInterface._
exitPanic
binop.BlockStmt.y
typeAssert.instr
callBuiltin.BlockStmt.RangeStmt_22984.arg
slice
binop.BlockStmt.u
callBuiltin.fn
conv.ut_dst
slice.lo
slice.max
lookup
eqnil.t
targetPanic.v
slice.m
eqnil.y
typeAssert.i
typeAssert.err
conv.t_src
conv.ut_src
slice.hi
sliceToArrayPointer.x
fitsInt.sizes
lookup.BlockStmt.ok
binop.x
callBuiltin.BlockStmt.BlockStmt.params
conv.t_dst
asInt64
rangeIter
sliceToArrayPointer.BlockStmt.BlockStmt.BlockStmt.v
checkInterface.meth
unsafe
lookup.BlockStmt.v
widen.x
conv.BlockStmt.BlockStmt.BlockStmt.BlockStmt.RangeStmt_28559.b
binop.op
binop
slice.x
unop.instr
callBuiltin.BlockStmt.buf
checkInterface.itype
fitsInt.intSize
lookup.instr
conv.BlockStmt.BlockStmt.r
targetPanic.String.p
zero.t
slice.Len
binop.y
conv.BlockStmt.BlockStmt.RangeStmt_27798.i
typeAssert
fitsInt.x
unop.x
binop.BlockStmt.ok
conv.BlockStmt.BlockStmt.BlockStmt.BlockStmt.RangeStmt_28453.r
asUnsigned
print.b
widen
conv.BlockStmt.BlockStmt.RangeStmt_27648.i
capturedOutputMu
zero.BlockStmt.s
zero.BlockStmt.RangeStmt_5832.i
callBuiltin.BlockStmt.RangeStmt_22984.i
conv.x
constValue.c
checkInterface.i
typeAssert.v
callBuiltin.caller
callBuiltin.args
conv.BlockStmt.BlockStmt.BlockStmt.res
binop.t
CapturedOutput
unop
callBuiltin.callpos
constValue
sliceToArrayPointer.t_src
sliceToArrayPointer
Members
X