aboutsummaryrefslogtreecommitdiff
path: root/internal/cond/eval.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/cond/eval.go')
-rw-r--r--internal/cond/eval.go41
1 files changed, 38 insertions, 3 deletions
diff --git a/internal/cond/eval.go b/internal/cond/eval.go
index 31c54e3..1147c05 100644
--- a/internal/cond/eval.go
+++ b/internal/cond/eval.go
@@ -44,6 +44,9 @@ type Result struct {
// text holds - (and (content "x") (type txt)) on a pdf - is not
// unknown (plan 11).
Unreadable bool
+ // Undecided says what made the value unknown: "content unreadable",
+ // "duplicate check failed", or both, comma-separated (plan 12).
+ Undecided string
}
// Trace is the full evaluation of every node, for krino explain.
@@ -73,6 +76,29 @@ type evalCtx struct {
captures []string
warned map[string]bool
warnings []string
+ // unknownContent and unknownDup record which kinds of test came back
+ // unknown, for Result.Undecided.
+ unknownContent, unknownDup bool
+}
+
+// undecidedLabel names the kinds of test that came back unknown.
+func (ctx *evalCtx) undecidedLabel() string {
+ switch {
+ case ctx.unknownContent && ctx.unknownDup:
+ return "content unreadable, duplicate check failed"
+ case ctx.unknownDup:
+ return "duplicate check failed"
+ case ctx.unknownContent:
+ return "content unreadable"
+ }
+ return ""
+}
+
+// undecidable reports whether a leaf whose fact could not be read is
+// unknown rather than false: a content test (review M11) or a duplicate
+// test (plan 12).
+func undecidable(k kind) bool {
+ return k == kContent || k == kDuplicate
}
// warn records msg unless it has already been recorded.
@@ -98,7 +124,11 @@ func (c *Cond) Eval(f Facts) Result {
}
ctx := &evalCtx{}
v, reasons := c.eval(c.root, f, ctx, false)
- return Result{Match: v == yes, Captures: ctx.captures, Reasons: reasons, Warnings: ctx.warnings, Unreadable: v == unknown}
+ r := Result{Match: v == yes, Captures: ctx.captures, Reasons: reasons, Warnings: ctx.warnings, Unreadable: v == unknown}
+ if r.Unreadable {
+ r.Undecided = ctx.undecidedLabel()
+ }
+ return r
}
// eval evaluates one node against f, short-circuiting and/or in child
@@ -163,7 +193,12 @@ func (c *Cond) eval(n *node, f Facts, ctx *evalCtx, negated bool) (tri, []string
}
ok, reason, warn, caps := c.evalLeaf(n, f)
ctx.warn(warn)
- if warn != "" && n.kind == kContent {
+ if warn != "" && undecidable(n.kind) {
+ if n.kind == kContent {
+ ctx.unknownContent = true
+ } else {
+ ctx.unknownDup = true
+ }
return unknown, nil
}
if !ok {
@@ -355,7 +390,7 @@ func (c *Cond) explain(n *node, f Facts) *Trace {
default:
ok, _, warn, _ := c.evalLeaf(n, f)
t := &Trace{Label: n.label, Value: ok, Err: warn}
- if m, undecided := f.Matched(); (warn != "" && n.kind == kContent) || (n.kind == kMatched && !m && undecided) {
+ if m, undecided := f.Matched(); (warn != "" && undecidable(n.kind)) || (n.kind == kMatched && !m && undecided) {
t.set(unknown)
}
return t