internal/core/adt: change closeInfo.embedded to a flag field

This prepares for collecting more origin information into a
single field. The additional information will be helpful for
implementing trim and potentially other algorithms, and
will give more context for error messages (if we move to
a more dynamic model).

This could be implemented as more booleans, but grouping
them as flags seems clearer and less error-prone w.r.t.
deciding what needs to be copied from the parent closeInfo.
It probably will also be more performant.

Change-Id: Id131aa62300d8e989c22cf4f308aeb5fc53cf238
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8236
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/internal/core/adt/closed.go b/internal/core/adt/closed.go
index c385967..327d7a5 100644
--- a/internal/core/adt/closed.go
+++ b/internal/core/adt/closed.go
@@ -109,11 +109,16 @@
 // TODO(perf): use on StructInfo. Then if parent and expression are the same
 // it is possible to use cached value.
 func (c CloseInfo) SpawnEmbed(x Expr) CloseInfo {
+	var span SpanType
+	if c.closeInfo != nil {
+		span = c.span
+	}
+
 	c.closeInfo = &closeInfo{
 		parent:   c.closeInfo,
 		location: x,
 		mode:     closeEmbed,
-		embedded: true,
+		span:     span | EmbeddingSpan,
 	}
 	return c
 }
@@ -124,27 +129,27 @@
 //      a: {#foo} & {b: int}
 //
 func (c CloseInfo) SpawnGroup(x Expr) CloseInfo {
-	embedded := false
+	var span SpanType
 	if c.closeInfo != nil {
-		embedded = c.embedded
+		span = c.span
 	}
 	c.closeInfo = &closeInfo{
 		parent:   c.closeInfo,
 		location: x,
-		embedded: embedded,
+		span:     span,
 	}
 	return c
 }
 
 func (c CloseInfo) SpawnRef(arc *Vertex, isDef bool, x Expr) CloseInfo {
-	embedded := false
+	var span SpanType
 	if c.closeInfo != nil {
-		embedded = c.embedded
+		span = c.span
 	}
 	c.closeInfo = &closeInfo{
 		parent:   c.closeInfo,
 		location: x,
-		embedded: embedded,
+		span:     span,
 	}
 	if isDef {
 		c.mode = closeDef
@@ -174,6 +179,22 @@
 	return false
 }
 
+// A SpanType is used to indicate whether a CUE value is within the scope of
+// a certain CUE language construct, the span type.
+type SpanType uint8
+
+const (
+	// EmbeddingSpan means that this value was embedded at some point and should
+	// not be included as a possible root node in the todo field of OpContext.
+	EmbeddingSpan SpanType = 1 << iota
+
+	// TODO:
+	// from comprehension
+	// from template.
+	// from definition
+
+)
+
 type closeInfo struct {
 	// location records the expression that led to this node's introduction.
 	location Node
@@ -193,9 +214,7 @@
 	//  - it is a sibling of a new definition.
 	noCheck bool // don't process for inclusion info
 
-	// embedded means that this value was embedded at some point and should
-	// not be included as a possible root node in the todo field of OpContext.
-	embedded bool
+	span SpanType
 }
 
 // closeStats holds the administrative fields for a closeInfo value. Each
@@ -303,7 +322,7 @@
 			return
 		}
 
-		if !s.embedded {
+		if s.span&EmbeddingSpan == 0 {
 			x.next = ctx.todo
 			ctx.todo = x
 		}