One way to do it would be to write your own expression evaluator. You
can use the eval function to parse and execute strings, so if you
store the expressions you want to evaluate as strings or multi field
values, you could dynamically parse those values, pull out the
individual conditions to evaluate, and then evaluate them one by one
so that you could determine where the evaluation failed. Here's some
small examples of using eval.
CLIPS> (eval "(> 3 5)")
FALSE
CLIPS> (eval "(< 3 5)")
TRUE
CLIPS> (defglobal ?*task* = 4)
CLIPS> (eval "(< ?*task* 5)")
TRUE
CLIPS> (bind ?*task* 6)
6
CLIPS> (eval "(< ?*task* 5)")
FALSE
CLIPS>
(deffunction comparator (?task ?rel ?value)
(bind ?*task* ?task)
(bind ?str (str-cat "(" ?rel " ?*task* " ?value ")"))
(eval ?str))
CLIPS> (comparator 3 > 5)
FALSE
CLIPS> (comparator 3 < 5)
TRUE
CLIPS>