github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/internal/typeparams/termlist.go (about) 1 // Copyright 2021 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 // Code generated by copytermlist.go DO NOT EDIT. 6 7 package typeparams 8 9 import ( 10 "bytes" 11 "go/types" 12 ) 13 14 // A termlist represents the type set represented by the union 15 // t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn. 16 // A termlist is in normal form if all terms are disjoint. 17 // termlist operations don't require the operands to be in 18 // normal form. 19 type termlist []*term 20 21 // allTermlist represents the set of all types. 22 // It is in normal form. 23 var allTermlist = termlist{new(term)} 24 25 // String prints the termlist exactly (without normalization). 26 func (xl termlist) String() string { 27 if len(xl) == 0 { 28 return "∅" 29 } 30 var buf bytes.Buffer 31 for i, x := range xl { 32 if i > 0 { 33 buf.WriteString(" ∪ ") 34 } 35 buf.WriteString(x.String()) 36 } 37 return buf.String() 38 } 39 40 // isEmpty reports whether the termlist xl represents the empty set of types. 41 func (xl termlist) isEmpty() bool { 42 // If there's a non-nil term, the entire list is not empty. 43 // If the termlist is in normal form, this requires at most 44 // one iteration. 45 for _, x := range xl { 46 if x != nil { 47 return false 48 } 49 } 50 return true 51 } 52 53 // isAll reports whether the termlist xl represents the set of all types. 54 func (xl termlist) isAll() bool { 55 // If there's a 𝓤 term, the entire list is 𝓤. 56 // If the termlist is in normal form, this requires at most 57 // one iteration. 58 for _, x := range xl { 59 if x != nil && x.typ == nil { 60 return true 61 } 62 } 63 return false 64 } 65 66 // norm returns the normal form of xl. 67 func (xl termlist) norm() termlist { 68 // Quadratic algorithm, but good enough for now. 69 // TODO(gri) fix asymptotic performance 70 used := make([]bool, len(xl)) 71 var rl termlist 72 for i, xi := range xl { 73 if xi == nil || used[i] { 74 continue 75 } 76 for j := i + 1; j < len(xl); j++ { 77 xj := xl[j] 78 if xj == nil || used[j] { 79 continue 80 } 81 if u1, u2 := xi.union(xj); u2 == nil { 82 // If we encounter a 𝓤 term, the entire list is 𝓤. 83 // Exit early. 84 // (Note that this is not just an optimization; 85 // if we continue, we may end up with a 𝓤 term 86 // and other terms and the result would not be 87 // in normal form.) 88 if u1.typ == nil { 89 return allTermlist 90 } 91 xi = u1 92 used[j] = true // xj is now unioned into xi - ignore it in future iterations 93 } 94 } 95 rl = append(rl, xi) 96 } 97 return rl 98 } 99 100 // If the type set represented by xl is specified by a single (non-𝓤) term, 101 // structuralType returns that type. Otherwise it returns nil. 102 func (xl termlist) structuralType() types.Type { 103 if nl := xl.norm(); len(nl) == 1 { 104 return nl[0].typ // if nl.isAll() then typ is nil, which is ok 105 } 106 return nil 107 } 108 109 // union returns the union xl ∪ yl. 110 func (xl termlist) union(yl termlist) termlist { 111 return append(xl, yl...).norm() 112 } 113 114 // intersect returns the intersection xl ∩ yl. 115 func (xl termlist) intersect(yl termlist) termlist { 116 if xl.isEmpty() || yl.isEmpty() { 117 return nil 118 } 119 120 // Quadratic algorithm, but good enough for now. 121 // TODO(gri) fix asymptotic performance 122 var rl termlist 123 for _, x := range xl { 124 for _, y := range yl { 125 if r := x.intersect(y); r != nil { 126 rl = append(rl, r) 127 } 128 } 129 } 130 return rl.norm() 131 } 132 133 // equal reports whether xl and yl represent the same type set. 134 func (xl termlist) equal(yl termlist) bool { 135 // TODO(gri) this should be more efficient 136 return xl.subsetOf(yl) && yl.subsetOf(xl) 137 } 138 139 // includes reports whether t ∈ xl. 140 func (xl termlist) includes(t types.Type) bool { 141 for _, x := range xl { 142 if x.includes(t) { 143 return true 144 } 145 } 146 return false 147 } 148 149 // supersetOf reports whether y ⊆ xl. 150 func (xl termlist) supersetOf(y *term) bool { 151 for _, x := range xl { 152 if y.subsetOf(x) { 153 return true 154 } 155 } 156 return false 157 } 158 159 // subsetOf reports whether xl ⊆ yl. 160 func (xl termlist) subsetOf(yl termlist) bool { 161 if yl.isEmpty() { 162 return xl.isEmpty() 163 } 164 165 // each term x of xl must be a subset of yl 166 for _, x := range xl { 167 if !yl.supersetOf(x) { 168 return false // x is not a subset yl 169 } 170 } 171 return true 172 }