// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.

// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types

import 

// A termlist represents the type set represented by the union
// t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn.
// A termlist is in normal form if all terms are disjoint.
// termlist operations don't require the operands to be in
// normal form.
type termlist []*term

// allTermlist represents the set of all types.
// It is in normal form.
var allTermlist = termlist{new(term)}

// termSep is the separator used between individual terms.
const termSep = " | "

// String prints the termlist exactly (without normalization).
func ( termlist) () string {
	if len() == 0 {
		return "∅"
	}
	var  strings.Builder
	for ,  := range  {
		if  > 0 {
			.WriteString(termSep)
		}
		.WriteString(.String())
	}
	return .String()
}

// isEmpty reports whether the termlist xl represents the empty set of types.
func ( termlist) () bool {
	// If there's a non-nil term, the entire list is not empty.
	// If the termlist is in normal form, this requires at most
	// one iteration.
	for ,  := range  {
		if  != nil {
			return false
		}
	}
	return true
}

// isAll reports whether the termlist xl represents the set of all types.
func ( termlist) () bool {
	// If there's a 𝓤 term, the entire list is 𝓤.
	// If the termlist is in normal form, this requires at most
	// one iteration.
	for ,  := range  {
		if  != nil && .typ == nil {
			return true
		}
	}
	return false
}

// norm returns the normal form of xl.
func ( termlist) () termlist {
	// Quadratic algorithm, but good enough for now.
	// TODO(gri) fix asymptotic performance
	 := make([]bool, len())
	var  termlist
	for ,  := range  {
		if  == nil || [] {
			continue
		}
		for  :=  + 1;  < len(); ++ {
			 := []
			if  == nil || [] {
				continue
			}
			if ,  := .union();  == nil {
				// If we encounter a 𝓤 term, the entire list is 𝓤.
				// Exit early.
				// (Note that this is not just an optimization;
				// if we continue, we may end up with a 𝓤 term
				// and other terms and the result would not be
				// in normal form.)
				if .typ == nil {
					return allTermlist
				}
				 = 
				[] = true // xj is now unioned into xi - ignore it in future iterations
			}
		}
		 = append(, )
	}
	return 
}

// union returns the union xl ∪ yl.
func ( termlist) ( termlist) termlist {
	return append(, ...).norm()
}

// intersect returns the intersection xl ∩ yl.
func ( termlist) ( termlist) termlist {
	if .isEmpty() || .isEmpty() {
		return nil
	}

	// Quadratic algorithm, but good enough for now.
	// TODO(gri) fix asymptotic performance
	var  termlist
	for ,  := range  {
		for ,  := range  {
			if  := .intersect();  != nil {
				 = append(, )
			}
		}
	}
	return .norm()
}

// equal reports whether xl and yl represent the same type set.
func ( termlist) ( termlist) bool {
	// TODO(gri) this should be more efficient
	return .subsetOf() && .subsetOf()
}

// includes reports whether t ∈ xl.
func ( termlist) ( Type) bool {
	for ,  := range  {
		if .includes() {
			return true
		}
	}
	return false
}

// supersetOf reports whether y ⊆ xl.
func ( termlist) ( *term) bool {
	for ,  := range  {
		if .subsetOf() {
			return true
		}
	}
	return false
}

// subsetOf reports whether xl ⊆ yl.
func ( termlist) ( termlist) bool {
	if .isEmpty() {
		return .isEmpty()
	}

	// each term x of xl must be a subset of yl
	for ,  := range  {
		if !.supersetOf() {
			return false // x is not a subset yl
		}
	}
	return true
}