diff options
Diffstat (limited to 'internal/cond/eval.go')
| -rw-r--r-- | internal/cond/eval.go | 41 |
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 |
