diff options
Diffstat (limited to 'src/cmd/compile/internal/types2/typeterm.go')
-rw-r--r-- | src/cmd/compile/internal/types2/typeterm.go | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/types2/typeterm.go b/src/cmd/compile/internal/types2/typeterm.go new file mode 100644 index 0000000000..1d7223f13c --- /dev/null +++ b/src/cmd/compile/internal/types2/typeterm.go @@ -0,0 +1,166 @@ +// 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 types2 + +// A term describes elementary type sets: +// +// β
: (*term)(nil) == β
// set of no types (empty set) +// π€: &term{} == π€ // set of all types (π€niverse) +// T: &term{false, T} == {T} // set of type T +// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t +// +type term struct { + tilde bool // valid if typ != nil + typ Type +} + +func (x *term) String() string { + switch { + case x == nil: + return "β
" + case x.typ == nil: + return "π€" + case x.tilde: + return "~" + x.typ.String() + default: + return x.typ.String() + } +} + +// equal reports whether x and y represent the same type set. +func (x *term) equal(y *term) bool { + // easy cases + switch { + case x == nil || y == nil: + return x == y + case x.typ == nil || y.typ == nil: + return x.typ == y.typ + } + // β
β x, y β π€ + + return x.tilde == y.tilde && Identical(x.typ, y.typ) +} + +// union returns the union x βͺ y: zero, one, or two non-nil terms. +func (x *term) union(y *term) (_, _ *term) { + // easy cases + switch { + case x == nil && y == nil: + return nil, nil // β
βͺ β
== β
+ case x == nil: + return y, nil // β
βͺ y == y + case y == nil: + return x, nil // x βͺ β
== x + case x.typ == nil: + return x, nil // π€ βͺ y == π€ + case y.typ == nil: + return y, nil // x βͺ π€ == π€ + } + // β
β x, y β π€ + + if x.disjoint(y) { + return x, y // x βͺ y == (x, y) if x β© y == β
+ } + // x.typ == y.typ + + // ~t βͺ ~t == ~t + // ~t βͺ T == ~t + // T βͺ ~t == ~t + // T βͺ T == T + if x.tilde || !y.tilde { + return x, nil + } + return y, nil +} + +// intersect returns the intersection x β© y. +func (x *term) intersect(y *term) *term { + // easy cases + switch { + case x == nil || y == nil: + return nil // β
β© y == β
and β© β
== β
+ case x.typ == nil: + return y // π€ β© y == y + case y.typ == nil: + return x // x β© π€ == x + } + // β
β x, y β π€ + + if x.disjoint(y) { + return nil // x β© y == β
if x β© y == β
+ } + // x.typ == y.typ + + // ~t β© ~t == ~t + // ~t β© T == T + // T β© ~t == T + // T β© T == T + if !x.tilde || y.tilde { + return x + } + return y +} + +// includes reports whether t β x. +func (x *term) includes(t Type) bool { + // easy cases + switch { + case x == nil: + return false // t β β
== false + case x.typ == nil: + return true // t β π€ == true + } + // β
β x β π€ + + u := t + if x.tilde { + u = under(u) + } + return Identical(x.typ, u) +} + +// subsetOf reports whether x β y. +func (x *term) subsetOf(y *term) bool { + // easy cases + switch { + case x == nil: + return true // β
β y == true + case y == nil: + return false // x β β
== false since x != β
+ case y.typ == nil: + return true // x β π€ == true + case x.typ == nil: + return false // π€ β y == false since y != π€ + } + // β
β x, y β π€ + + if x.disjoint(y) { + return false // x β y == false if x β© y == β
+ } + // x.typ == y.typ + + // ~t β ~t == true + // ~t β T == false + // T β ~t == true + // T β T == true + return !x.tilde || y.tilde +} + +// disjoint reports whether x β© y == β
. +// x.typ and y.typ must not be nil. +func (x *term) disjoint(y *term) bool { + if debug && (x.typ == nil || y.typ == nil) { + panic("invalid argument(s)") + } + ux := x.typ + if y.tilde { + ux = under(ux) + } + uy := y.typ + if x.tilde { + uy = under(uy) + } + return !Identical(ux, uy) +} |