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  }