@@ -20,6 +20,17 @@ type arrayDesc struct {
2020 elementContains [][]placeholderID
2121}
2222
23+ func (a * arrayDesc ) copy () * arrayDesc {
24+ elementContains := make ([][]placeholderID , len (a .elementContains ))
25+ for i , placeholders := range a .elementContains {
26+ elementContains [i ] = append ([]placeholderID {}, placeholders ... )
27+ }
28+ return & arrayDesc {
29+ furtherContain : append ([]placeholderID {}, a .furtherContain ... ),
30+ elementContains : elementContains ,
31+ }
32+ }
33+
2334func (a * arrayDesc ) widen (other * arrayDesc ) {
2435 if other == nil {
2536 return
@@ -49,6 +60,18 @@ type objectDesc struct {
4960 allFieldsKnown bool
5061}
5162
63+ func (o * objectDesc ) copy () * objectDesc {
64+ fieldContains := make (map [string ][]placeholderID )
65+ for k , v := range o .fieldContains {
66+ fieldContains [k ] = append ([]placeholderID (nil ), v ... )
67+ }
68+ return & objectDesc {
69+ unknownContain : append ([]placeholderID (nil ), o .unknownContain ... ),
70+ fieldContains : fieldContains ,
71+ allFieldsKnown : o .allFieldsKnown ,
72+ }
73+ }
74+
5275func (o * objectDesc ) widen (other * objectDesc ) {
5376 if other == nil {
5477 return
@@ -77,6 +100,7 @@ func (o *objectDesc) normalize() {
77100type functionDesc struct {
78101 resultContains []placeholderID
79102
103+ // Read-only
80104 // TODO(sbarzowski) instead of keeping "real" parameters here,
81105 // maybe keep only what we care about in the linter desc
82106 // (names and required-or-not).
@@ -85,6 +109,15 @@ type functionDesc struct {
85109 minArity , maxArity int
86110}
87111
112+ func (f * functionDesc ) copy () * functionDesc {
113+ return & functionDesc {
114+ resultContains : append ([]placeholderID {}, f .resultContains ... ),
115+ params : f .params , // this is read-only, so we can just copy the pointer
116+ minArity : f .minArity ,
117+ maxArity : f .maxArity ,
118+ }
119+ }
120+
88121func sameParameters (a , b []ast.Parameter ) bool {
89122 if a == nil || b == nil {
90123 return false
@@ -255,7 +288,44 @@ func Describe(t *TypeDesc) string {
255288 return strings .Join (parts , " or " )
256289}
257290
291+ // An intuitive notion of the size of type description. For performance tuning.
292+ func (t * TypeDesc ) size () int64 {
293+ res := 0
294+ if t .Bool {
295+ res += 1
296+ }
297+ if t .Number {
298+ res += 1
299+ }
300+ if t .String {
301+ res += 1
302+ }
303+ if t .Null {
304+ res += 1
305+ }
306+ if t .Function () {
307+ res += len (t .FunctionDesc .resultContains )
308+ res += len (t .FunctionDesc .params )
309+ }
310+ if t .Array () {
311+ res += len (t .ArrayDesc .furtherContain )
312+ for _ , elem := range t .ArrayDesc .elementContains {
313+ res += len (elem )
314+ }
315+ }
316+ if t .Object () {
317+ res += len (t .ObjectDesc .unknownContain )
318+ for _ , elem := range t .ObjectDesc .fieldContains {
319+ res += len (elem )
320+ }
321+ }
322+ return int64 (res )
323+ }
324+
258325func (t * TypeDesc ) widen (b * TypeDesc ) {
326+ if t == b {
327+ panic ("BUG: widening the type with itself" )
328+ }
259329 t .Bool = t .Bool || b .Bool
260330 t .Number = t .Number || b .Number
261331 t .String = t .String || b .String
@@ -264,22 +334,24 @@ func (t *TypeDesc) widen(b *TypeDesc) {
264334 if t .FunctionDesc != nil {
265335 t .FunctionDesc .widen (b .FunctionDesc )
266336 } else if t .FunctionDesc == nil && b .FunctionDesc != nil {
267- copy := * b .FunctionDesc
268- t .FunctionDesc = & copy
337+ // copy := *b.FunctionDesc
338+ // t.FunctionDesc = ©
339+ t .FunctionDesc = b .FunctionDesc .copy ()
269340 }
270341
271342 if t .ObjectDesc != nil {
272343 t .ObjectDesc .widen (b .ObjectDesc )
273344 } else if t .ObjectDesc == nil && b .ObjectDesc != nil {
274- copy := * b .ObjectDesc
275- t .ObjectDesc = & copy
345+ // TODO(sbarzowski) Maybe we want copy on write?
346+ // So that it actually aliases underneath (with a bool marker)
347+ // which is resolved when widened.
348+ t .ObjectDesc = b .ObjectDesc .copy ()
276349 }
277350
278351 if t .ArrayDesc != nil {
279352 t .ArrayDesc .widen (b .ArrayDesc )
280353 } else if t .ArrayDesc == nil && b .ArrayDesc != nil {
281- copy := * b .ArrayDesc
282- t .ArrayDesc = & copy
354+ t .ArrayDesc = b .ArrayDesc .copy ()
283355 }
284356}
285357
0 commit comments