internal/core/adt: initial commit

Defines Abstract Data Types. These are internal
types used by the CUE evaluator.

Change-Id: Ibb109bf3b5d63525199cab05ec609595bee0a5bf
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6500
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
diff --git a/internal/core/adt/feature.go b/internal/core/adt/feature.go
new file mode 100644
index 0000000..684a74e
--- /dev/null
+++ b/internal/core/adt/feature.go
@@ -0,0 +1,137 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package adt
+
+import (
+	"strconv"
+
+	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/errors"
+	"cuelang.org/go/cue/token"
+	"cuelang.org/go/internal"
+)
+
+// A Feature is an encoded form of a label which comprises a compact
+// representation of an integer or string label as well as a label type.
+type Feature uint32
+
+// InvalidLabel is an encoding of an erroneous label.
+const InvalidLabel Feature = 0x7 // 0xb111
+
+// MaxIndex indicates the maximum number of unique strings that are used for
+// labeles within this CUE implementation.
+const MaxIndex int64 = 1<<28 - 1
+
+// A StringIndexer coverts strings to and from an index that is unique for a
+// given string.
+type StringIndexer interface {
+	// ToIndex returns a unique positive index for s (0 < index < 2^28-1).
+	//
+	// For each pair of strings s and t it must return the same index if and
+	// only if s == t.
+	StringToIndex(s string) (index int64)
+
+	// ToString returns a string s for index such that ToIndex(s) == index.
+	IndexToString(index int64) string
+}
+
+// SelectorString reports the shortest string representation of f when used as a
+// selector.
+func (f Feature) SelectorString(index StringIndexer) string {
+	if f == 0 {
+		return "_"
+	}
+	x := f.Index()
+	switch f.Typ() {
+	case IntLabel:
+		return strconv.Itoa(int(x))
+	case StringLabel:
+		s := index.IndexToString(int64(x))
+		if ast.IsValidIdent(s) && !internal.IsDefOrHidden(s) {
+			return s
+		}
+		return strconv.Quote(s)
+	default:
+		return index.IndexToString(int64(x))
+	}
+}
+
+// MakeLabel creates a label. It reports an error if the index is out of range.
+func MakeLabel(p token.Pos, index int64, f FeatureType) (Feature, errors.Error) {
+	if 0 > index || index > MaxIndex {
+		return InvalidLabel,
+			errors.Newf(p, "int label out of range (%d not >=0 and <= %d)",
+				index, MaxIndex)
+	}
+	return Feature(index)<<indexShift | Feature(f), nil
+}
+
+// A FeatureType indicates the type of label.
+type FeatureType int8
+
+const (
+	StringLabel           FeatureType = 0 // 0b000
+	IntLabel              FeatureType = 1 // 0b001
+	DefinitionLabel       FeatureType = 3 // 0b011
+	HiddenLabel           FeatureType = 6 // 0b110
+	HiddenDefinitionLabel FeatureType = 7 // 0b111
+
+	// letLabel              FeatureType = 0b010
+
+	fTypeMask Feature = 7 // 0b111
+
+	indexShift = 3
+)
+
+// IsValid reports whether f is a valid label.
+func (f Feature) IsValid() bool { return f != InvalidLabel }
+
+// Typ reports the type of label.
+func (f Feature) Typ() FeatureType { return FeatureType(f & fTypeMask) }
+
+// IsRegular reports whether a label represents a data field.
+func (f Feature) IsRegular() bool { return f.Typ() <= IntLabel }
+
+// IsString reports whether a label represents a regular field.
+func (f Feature) IsString() bool { return f.Typ() == StringLabel }
+
+// IsDef reports whether the label is a definition (an identifier starting with
+// # or #_.
+func (f Feature) IsDef() bool {
+	if f == InvalidLabel {
+		// TODO(perf): do more mask trickery to avoid this branch.
+		return false
+	}
+	return f.Typ()&DefinitionLabel == DefinitionLabel
+}
+
+// IsInt reports whether this is an integer index.
+func (f Feature) IsInt() bool { return f.Typ() == IntLabel }
+
+// IsHidden reports whether this label is hidden (an identifier starting with
+// _ or #_).
+func (f Feature) IsHidden() bool {
+	if f == InvalidLabel {
+		// TODO(perf): do more mask trickery to avoid this branch.
+		return false
+	}
+	return f.Typ()&HiddenLabel == HiddenLabel
+}
+
+// Index reports the abstract index associated with f.
+func (f Feature) Index() int { return int(f >> indexShift) }
+
+// TODO: should let declarations be implemented as fields?
+// func (f Feature) isLet() bool  { return f.typ() == letLabel }