internal/core/adt: add methods for concreteness
This is the first step to make marker value a different
type as to let the compiler prevent them from
being passed around as values.
Issue #598
Change-Id: Iaf58635bd2ca4591e6ce4589f237076ff8359ede
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7764
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
diff --git a/cue/context.go b/cue/context.go
index 8b5f908..ed85619 100644
--- a/cue/context.go
+++ b/cue/context.go
@@ -76,12 +76,7 @@
panic("undefined value")
}
x := ctx.manifest(v.v)
- switch x.Kind() {
- case adt.StructKind, adt.ListKind:
- return x
- default:
- return x.Value
- }
+ return x.ActualValue()
}
// func (v Value) evalFull(u value) (Value, adt.Value) {
diff --git a/cue/load/config.go b/cue/load/config.go
index dd0cef3..6a9972a 100644
--- a/cue/load/config.go
+++ b/cue/load/config.go
@@ -536,12 +536,12 @@
v.Finalize(ctx)
prefix := v.Lookup(ctx.StringLabel("module"))
if prefix != nil {
- name := ctx.StringValue(prefix.Value)
+ name := ctx.StringValue(prefix.ActualValue())
if err := ctx.Err(); err != nil {
return &c, err.Err
}
pos := token.NoPos
- src := prefix.Value.Source()
+ src := prefix.ActualValue().Source()
if src != nil {
pos = src.Pos()
}
diff --git a/cue/types.go b/cue/types.go
index f5570f5..e4d7cef 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -844,7 +844,7 @@
return BottomKind
}
c := v.v.Value
- if !adt.IsConcrete(c) {
+ if !v.v.IsConcrete() {
return BottomKind
}
if v.IncompleteKind() == adt.ListKind && !v.IsClosed() {
@@ -2161,12 +2161,7 @@
var env *adt.Environment
if v.v.IsData() {
- switch x := v.v.Value.(type) {
- case *adt.ListMarker, *adt.StructMarker:
- expr = v.v
- default:
- expr = x
- }
+ expr = v.v.ActualValue()
} else {
switch len(v.v.Conjuncts) {
@@ -2174,12 +2169,7 @@
if v.v.Value == nil {
return NoOp, []Value{makeValue(v.idx, v.v)}
}
- switch x := v.v.Value.(type) {
- case *adt.ListMarker, *adt.StructMarker:
- expr = v.v
- default:
- expr = x
- }
+ expr = v.v.ActualValue()
case 1:
// the default case, processed below.
diff --git a/internal/core/adt/adt.go b/internal/core/adt/adt.go
index 90d3d51..a43792a 100644
--- a/internal/core/adt/adt.go
+++ b/internal/core/adt/adt.go
@@ -136,10 +136,16 @@
func (x *Vertex) Concreteness() Concreteness {
// Depends on concreteness of value.
- if x.Value == nil {
+ switch v := x.Value.(type) {
+ case nil:
return Concrete // Should be indetermined.
+
+ case Value:
+ return v.Concreteness()
+
+ default: // *StructMarker, *ListMarker:
+ return Concrete
}
- return x.Value.Concreteness()
}
func (x *NodeLink) Concreteness() Concreteness { return Concrete }
diff --git a/internal/core/adt/composite.go b/internal/core/adt/composite.go
index 00f0737..a6b56fe 100644
--- a/internal/core/adt/composite.go
+++ b/internal/core/adt/composite.go
@@ -255,6 +255,25 @@
v.status = s
}
+// ActualValue returns the Value of v without definitions if it is a scalar
+// or itself otherwise.
+func (v *Vertex) ActualValue() Value {
+ // TODO: rename to Value.
+ switch x := v.Value.(type) {
+ // XXX: remove
+ case *StructMarker, *ListMarker:
+ return v
+ case Value:
+ return x
+ default:
+ return v
+ }
+}
+
+func (x *Vertex) IsConcrete() bool {
+ return x.Concreteness() <= Concrete
+}
+
// IsData reports whether v should be interpreted in data mode. In other words,
// it tells whether optional field matching and non-regular fields, like
// definitions and hidden fields, should be ignored.
@@ -385,12 +404,7 @@
if !ok {
return v
}
- switch x.Value.(type) {
- case *StructMarker, *ListMarker:
- return v
- default:
- return x.Value
- }
+ return x.ActualValue()
}
// Acceptor is a single interface that reports whether feature f is a valid
diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go
index fe9ffcf..6c049a2 100644
--- a/internal/core/adt/context.go
+++ b/internal/core/adt/context.go
@@ -449,17 +449,14 @@
case *Disjunction:
d = t
- case *StructMarker, *ListMarker:
- return v, true
-
case *Vertex:
return c.getDefault(t, scalar)
default:
if !scalar {
- return v, true
+ return x, true
}
- return t, true
+ return x.ActualValue(), true
}
case *Disjunction:
@@ -551,7 +548,7 @@
}
if isIncomplete(arc) {
if arc != nil {
- return arc.Value
+ return arc.ActualValue() // *Bottom
}
return nil
}