1
2
3
4
5 package types2
6
7 import (
8 "bytes"
9 "fmt"
10 "strconv"
11 "strings"
12 "sync"
13 )
14
15
16
17
18
19
20
21 type Context struct {
22 mu sync.Mutex
23 typeMap map[string][]ctxtEntry
24 nextID int
25 originIDs map[Type]int
26 }
27
28 type ctxtEntry struct {
29 orig Type
30 targs []Type
31 instance Type
32 }
33
34
35 func NewContext() *Context {
36 return &Context{
37 typeMap: make(map[string][]ctxtEntry),
38 originIDs: make(map[Type]int),
39 }
40 }
41
42
43
44
45 func (ctxt *Context) instanceHash(orig Type, targs []Type) string {
46 assert(ctxt != nil)
47 assert(orig != nil)
48 var buf bytes.Buffer
49
50 h := newTypeHasher(&buf, ctxt)
51 h.string(strconv.Itoa(ctxt.getID(orig)))
52
53
54
55 h.typ(orig)
56 if len(targs) > 0 {
57
58
59 h.typeList(targs)
60 }
61
62 return strings.Replace(buf.String(), " ", "#", -1)
63 }
64
65
66
67 func (ctxt *Context) lookup(h string, orig Type, targs []Type) Type {
68 ctxt.mu.Lock()
69 defer ctxt.mu.Unlock()
70
71 for _, e := range ctxt.typeMap[h] {
72 if identicalInstance(orig, targs, e.orig, e.targs) {
73 return e.instance
74 }
75 if debug {
76
77 panic(fmt.Sprintf("non-identical instances: (orig: %s, targs: %v) and %s", orig, targs, e.instance))
78 }
79 }
80
81 return nil
82 }
83
84
85
86
87
88 func (ctxt *Context) update(h string, orig Type, targs []Type, inst Type) Type {
89 assert(inst != nil)
90
91 ctxt.mu.Lock()
92 defer ctxt.mu.Unlock()
93
94 for _, e := range ctxt.typeMap[h] {
95 if inst == nil || Identical(inst, e.instance) {
96 return e.instance
97 }
98 if debug {
99
100 panic(fmt.Sprintf("%s and %s are not identical", inst, e.instance))
101 }
102 }
103
104 ctxt.typeMap[h] = append(ctxt.typeMap[h], ctxtEntry{
105 orig: orig,
106 targs: targs,
107 instance: inst,
108 })
109
110 return inst
111 }
112
113
114 func (ctxt *Context) getID(t Type) int {
115 ctxt.mu.Lock()
116 defer ctxt.mu.Unlock()
117 id, ok := ctxt.originIDs[t]
118 if !ok {
119 id = ctxt.nextID
120 ctxt.originIDs[t] = id
121 ctxt.nextID++
122 }
123 return id
124 }
125
View as plain text