Debugging WebLS Logic-Bases

In general you will find that logic-bases are generally 'flat'. This means that most rules won't depend on multiple layers of distilled facts. So debugging the rules is generally straight-forward.

Syntax Errors

The most common problem you will encounter is typing errors in your logic-base. The two most likely will be missing the period at the end of a rule or output function, and forgetting to quote facts and values that do not start with a lowercase letter, or contain characters other than letters, numbers and underscores.

Syntax errors are reported by WebLS in your browser. The indicator <- NEAR HERE -> will give you an idea of where the error is in the text of your logic-base.

Trace Facility

WebLS includes a trace facility to assist in testing and debugging logic-bases. The trace lists all the known facts, and then shows each rule being tried, indicating which facts match, and which rule or hypothesis matches. When tracing is enabled (by defining a log file at the top of your logic-base), a URL pointing to the output is included on the bottom of each page generated by WebLS. This allows you to examine the trace directly in your browser.

A typical debugging session has you fill-in the answers on the form (in the same manner your users would), then see the trace to determine how the answer was reached, or why another set of facts is being asked for.

Below is a small logic-base and the trace of a particular run of liltech.lb.
% ------------------------------------------------------------------- %
%                          The Logic-Base                             %
% ------------------------------------------------------------------- %

:- op(790, fx, if).     	% prefix operator
:- op(780, xfx, then).  	% infix operator
:- op(775, xfy, or).    	% infix that can be linked
:- op(770, xfy, and).   	% infix that can be linked
:- op(700, xfx, <=).		% infix operator
:- op(700, xfx, include).	% infix operator
:- op(700, xfx, exclude).	% infix operator

:- asserta(system('Body Args', $bgcolor=#CEFAFF text=#000000$)).
:- asserta(system('Title', $Amzi! Problem Resolver$)).
:- asserta(system('Header', $<H2>Amzi! Problem Resolver</H2>$)).
:- asserta(system('Footer', $<FONT SIZE=-1>Copyright ©1996 Amzi! inc. All Rights Reserved.$)).
:- asserta(system('Form Action', 'Executable Path')).
:- asserta(system('Goal', ['problem'])).

question(errorCode, 
[
firstForm,
prompt = $What error code was displayed or 'none'?$,
ask = field,
length = 5
]).

question(programType, 
[
firstForm,
prompt = $What program are you running?$,
ask = menu(['other', 'Amzi! Hello Program', 'Amzi! Sample Program',
            'Amzi! IDE', 'My Program', 'Windows Application'])
]).

if errorCode = '600' and
   programType = 'Amzi! Hello Program' 
then problem = helloXPL.

if errorCode = '600' and
   programType = 'Amzi! Sample Program' 
then problem = sampleXPL.

if errorCode = '600' and
   programType = 'My Program' 
then problem = missingXPL.

answer(helloXPL, 
[
text = [$The program is unable to locate the Amzi! Prolog object module, an XPL file. $,
        $Make sure the AMZI installation directory is in your path, and that HELLO.XPL file $,
        $exists in the path or the current directory.$]
]).

answer(sampleXPL, 
[
text = [$The program is unable to locate the Amzi! Prolog object module, an XPL file. $,
        $Some of the Amzi! samples include source only, $,
        $and the PRO file needs to be compiled and linked $,
        $into an XPL file.$,
        $<P>If the XPL file exists, then it must be in your $,
        $path or the current directory.$]
]).

answer(missingXPL, 
[
text = [$The program is unable to locate the Amzi! Prolog object module, an XPL file. $,
        $Make sure the the XPL file exists in your path $,
        $or the current directory.$,
        $<P>Note: Some development environments such as Visual Basic and $,
        $Delphi set the current directory to a directory you might not $,
        $have expected.$]
]).

Figure: A Sample Logic-Base

You can see in the listing above the three main parts of the logic-base. There are the question, the rules and the answers.
Logic-Base Debugging Trace
system($Input File$,$C:\WEBSITE\CGI-TEMP\287WS.INI$).
system('Content File','C:\WEBSITE\CGI-TEMP\287WS.INP').
system('Output File','C:\WebSite\cgi-temp\287ws.out').
. . .
system('Log File','C:\AmziCGI\logs\lilrun.htm').
system('Title',$Amzi! Problem Resolver$).
system('Initial Form',$C:\AmziCGI\html\rptprob.htm$).
system('AmziCGI Directory',$C:\AmziCGI$).
system('Form Action','Executable Path').
system('Goal',problem).

cgi('Content Length','191').
cgi('Content Type','application/x-www-form-urlencoded').
. . .
cgi('Executable Path','/cgi-win/cgirun.exe').
cgi('Request Method','POST').
cgi('Request Protocol','HTTP/1.0').

fact(submitForm,Submit)
fact(programType,Amzi! Sample Program)
fact(errorCode,600)

Processing input file C:\WEBSITE\CGI-TEMP\8AAWS.INI
Processing POST method (subsequent times through)


---> Calling logic-base to find hypotheses for goal problem

if errorCode = 600 and programType = Amzi! Hello Program
then problem = helloXPL
   Checking then problem = helloXPL
      Checking if errorCode = 600
      Matching errorCode = 600
      Checking if programType = Amzi! Hello Program
if errorCode = 600 and programType = Amzi! Sample Program
then problem = sampleXPL
   Checking then problem = sampleXPL
      Checking if errorCode = 600
      Matching errorCode = 600
      Checking if programType = Amzi! Sample Program
      Matching programType = Amzi! Sample Program
   Matching problem = sampleXPL
if errorCode = 600 and programType = My Program
then problem = missingXPL
   Checking then problem = missingXPL
      Checking if errorCode = 600
      Matching errorCode = 600
      Checking if programType = My Program


---> Calling logic-base to find answers for goal problem

if errorCode = 600 and programType = Amzi! Hello Program
then problem = helloXPL
   Checking then problem = helloXPL
      Checking if errorCode = 600
      Matching errorCode = 600
      Checking if programType = Amzi! Hello Program
if errorCode = 600 and programType = Amzi! Sample Program
then problem = sampleXPL
   Checking then problem = sampleXPL
      Checking if errorCode = 600
      Matching errorCode = 600
      Checking if programType = Amzi! Sample Program
      Matching programType = Amzi! Sample Program
   Matching problem = sampleXPL
if errorCode = 600 and programType = My Program
then problem = missingXPL
   Checking then problem = missingXPL
      Checking if errorCode = 600
      Matching errorCode = 600
      Checking if programType = My Program

---> Logic-base found answers [sampleXPL]

Figure: Trace of the Sample Logic-Base

This trace illuminates the 'backtracking' search that is inherent in the Prolog language and implemented in the WebLS inference engine. You can see the first rule matches on the errorCode ('600') but fails on the programType. The second rules matches on both and succeeds; that is, it identifies the problem as 'sampleXPL.'

Error Messages

In addition to the trace facility, WebLS reports when question is not defined for a needed fact and when answer is not defined for a reached conclusion. These errors are returned on an HTML error page designed for the purpose.

Here are the error messages returned by WebLS and their explanations:

Any other error messages are internal and should be reported to