Aspen SCM‎ > ‎Expert System‎ > ‎2. Flow of Control‎ > ‎

2.d Error on Unknown

Error on Unknown Flag

The “Error on Unknown” flag, CNTLE(EOU,1), determines whether it is an error or not if a statement resolves as UNKNOWN. If this flag is set to YES, it causes the interpreter to raise an error when a statement resolves as UNKNOWN. If the rule is running inside a macro with an ON ERROR clause, control passes to the ON ERROR block; otherwise processing stops and the error is reported. If CNTLE(EOU,1) = NO, the UNKNOWN is regarded as equivalent to FALSE and processing continues.

Reasons a Statement may Resolve UNKNOWN

A statement may resolve UNKNOWN if:

  • it is of the form <free_variable> IN <empty_set>, e.g. ?I IN MYSET where ?I is FREE and the Actual Count of MYSET is 0;

  • it is interpreted as a predicate but the predicate does not match any canonical predicate in $PRED; see Mistakes Interpreted as Predicates in section 2.a;

  • it is a predicate but the rule which is executed to prove it ends without either proving the predicate TRUE or FALSE; this can happen :

  • if the rule contains a statement which resolves UNKNOWN without any alternative path; or

  • if the interpreter BREAKs out of a loop without having proved the predicate TRUE.

With the exception of the BREAK out of a loop, all of these represent errors in the code. The first frequently occurs after SELECT statements where a loop is intended, e.g. ?ITEM IN CHOSEN. To protect against this, the number of elements selected should be tested and the loop only executed if there are elements:

AND     ?NSIZE = SIZEOF CHOSEN
AND     ( ?NSIZE EQ 0
           OR ?ITEM IN CHOSEN
          ...
         )

With the second, a message will appear in ERROR if CNTLE(EOU,1) = YES, e.g.

E0060:UNRECOGNIZED PREDICATE   SET: RTEMP    RULE: RCHECK0   COND: CHECK1 ?FRED

Legacy Code and BREAKs out of Loops

This automatic detection of errors appears to provide a compelling reason to set CNTLE(EOU,1) = YES. Unfortunately, there is often an even more compelling reason to set CNTLE(EOU,1) = NO: the code contains loops with BREAK statements where the predicate may never be reached.

A change was made with Aspen SCM 2004 to the way that the interpreter handles rules where the predicate is never proved. Before then, such rules ended UNKNOWN but the interpreter did not stop even if CNTLE(EOU,1) = YES. Instead the rule was regarded as having ended FALSE and processing continued. Only where the predicate did not match any canonical predicate did the interpreter stop and report an error.

As a result, much code was written with BREAKs out of loops in which the predicate might never be reached. In the calling rule the predicate would have an “OR TRUE” clause after it so that, if the predicate was not proved, the calling rule would continue. Where an application contains rules which were written for versions before Aspen SCM 2004, it will therefore often be necessary to set CNTLE(EOU,1) = NO.

Unless the application already contains rules which may BREAK out a loop without proving the predicate, it, new code should avoid doing so. See sections 3.3 and 3.6 for details of how to write loops and jump out of them without risking UNKNOWNs.

UNTRUE Rule Set Detects Statements Not Resolving TRUE

As changes to code risk introducing bugs, it is unlikely to be worth converting legacy code to avoid ending UNKNOWN. This means that CNTLE(EOU,1) has to be set to NO, so errors in newly-written code will not be detected automatically.

Eudoxus Systems has developed a special pattern-matching rule set UNTRUE.R (available for downloading at www.eudoxus.com/untrue.html) which can be used in conjunction with CNTLE(EOU,1) = NO. This provides run-time detection of non-existent predicates and of rules which do not end TRUE. It is incompatible with predicate unification so either UNIF must be absent from SCNTLE or CNTLE(UNIF,1) must be set to NO. It is intended as a development tool and should be removed when the system is moved into production.


Back                                Next
Comments