tools/flow: add IgnoreConcrete option

Ignore dependencies which point to immutable values.

This is the behavior of `cue cmd`. It is not sure whether
this is necessarily desirable, so this has been added as an option.

It would be possible to always have this behavior, though.

Change-Id: I3feacf5600a7ea1b69986e12fb5c7a285c9f413a
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7642
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
diff --git a/tools/flow/flow.go b/tools/flow/flow.go
index 5f0b412..f028cee 100644
--- a/tools/flow/flow.go
+++ b/tools/flow/flow.go
@@ -136,6 +136,10 @@
 	// by any of the tasks defined within Root.
 	InferTasks bool
 
+	// IgnoreConcrete ignores references for which the values are already
+	// concrete and cannot change.
+	IgnoreConcrete bool
+
 	// UpdateFunc is called whenever the information in the controller is
 	// updated. This includes directly after initialization. The task may be
 	// nil if this call is not the result of a task completing.
diff --git a/tools/flow/flow_test.go b/tools/flow/flow_test.go
index 455df11..c061561 100644
--- a/tools/flow/flow_test.go
+++ b/tools/flow/flow_test.go
@@ -72,9 +72,10 @@
 		}
 
 		cfg := &flow.Config{
-			Root:       cue.ParsePath("root"),
-			InferTasks: t.Bool("InferTasks"),
-			UpdateFunc: updateFunc,
+			Root:           cue.ParsePath("root"),
+			InferTasks:     t.Bool("InferTasks"),
+			IgnoreConcrete: t.Bool("IgnoreConcrete"),
+			UpdateFunc:     updateFunc,
 		}
 
 		c := flow.New(cfg, inst, taskFunc)
diff --git a/tools/flow/tasks.go b/tools/flow/tasks.go
index c5afc68..6ef1d6f 100644
--- a/tools/flow/tasks.go
+++ b/tools/flow/tasks.go
@@ -161,6 +161,12 @@
 
 	n := d.Node
 	for ; n != nil; n = n.Parent {
+		if c.cfg.IgnoreConcrete && n.Value.Concreteness() <= adt.Concrete {
+			if k := n.Value.Kind(); k != adt.StructKind && k != adt.ListKind {
+				return nil
+			}
+		}
+
 		t, ok := c.nodes[n]
 		if ok || !c.cfg.InferTasks {
 			return t
diff --git a/tools/flow/testdata/concrete.txtar b/tools/flow/testdata/concrete.txtar
new file mode 100644
index 0000000..e995fd4
--- /dev/null
+++ b/tools/flow/testdata/concrete.txtar
@@ -0,0 +1,46 @@
+#IgnoreConcrete: true
+-- in.cue --
+root: {
+    t1: {
+        $id:   "sequenced"
+        seq:   1
+        text:  t2.value
+        value: "v"
+    }
+    t2: {
+        $id:   "sequenced"
+        seq:   2
+        text:  t1.value
+        value: "v"
+    }
+}
+-- out/run/errors --
+-- out/run/t0 --
+graph TD
+  t0("root.t1 [Ready]")
+  t1("root.t2 [Ready]")
+
+-- out/run/t1 --
+graph TD
+  t0("root.t1 [Terminated]")
+  t1("root.t2 [Running]")
+
+-- out/run/t1/value --
+{
+	$id:   "sequenced"
+	seq:   1
+	text:  "v"
+	value: "v"
+}
+-- out/run/t2 --
+graph TD
+  t0("root.t1 [Terminated]")
+  t1("root.t2 [Terminated]")
+
+-- out/run/t2/value --
+{
+	$id:   "sequenced"
+	seq:   2
+	text:  "v"
+	value: "v"
+}