#============================================================================== # This file contains operations dealing with the functioning of the rule # editor and inference engine. #============================================================================== rulebase is external variable; title is 5 forwardchain is external operation; backwardchain is external operation; explain is external variable ; textwindow:=[1 3,22 70,0,0,2,'']; nialwindow:=[12 3,11 70,0,0,2,'type RESUME to exit']; cmdline:=[22 3,1 70,0,2,0,'']; substring IS OP Pattern Line { sub IS OP S1 S2 { S1 = ((tally S1) take S2)}; Tbs := findall (first Pattern) Line; rc:=(o 0); FOR Tb WITH Tbs DO IF (sub Pattern (Tb drop Line)) THEN rc:=(l tb); EXIT ("found); ENDIF; ENDFOR; rc } #============================================================================== # browse is called by ruled -- the rule editor -- to use editwindow in view # mode. It handles mostly cases concerning window scrolling: forward, # backward, right, left. It also handles the calling of host commands. #============================================================================== browse IS OPERATION Strings&things { setwindow Textwindow; List_of_strings Parameters := [first,rest] Strings&things; Height Width := 1 pick Window; Noofrows := tally List_of_strings; Noofcols := max EACH tally List_of_strings; Offset Cursor := Parameters; Rc Cc := Cursor; Ro Co := Offset; Endbrowse := Falsehood; Lastline := Height - Noofrows; Lastcol := Width - Noofcols; Pattern := Null; Last_thing_done := pair Null; REPEAT Clearwindow; Repeats := 1; Param Code := [front,last] editwindow [List_of_strings,Ro Co,Rc Cc, ["view_mode]]; List_of_strings := first Param; Ro Co Rc Cc Mode := link rest Param; IF Code in [`1,`2,`3,`4,`5,`6,`7,`8,`9,`0] THEN Code := execute Code; A := Readchar; WHILE A in `1 `2 `3 `4 `5 `6 `7 `8 `9 `0 DO Code := (10 * Code) + (execute A); A := Readchar; ENDWHILE; Repeats := Code; Code := A; ENDIF; IF Code in `: `/ `? `! THEN setwindow Cmdline; Pattern := readscreen Code; ENDIF; IF Code = `. THEN Repeats Code := Last_thing_done; ENDIF; CASE Code FROM `b : Ro := max (0(Ro - Repeats)); END `B : Ro := max (0(Ro - (Repeats * Height))); END `f : Ro := Ro + Repeats; END `F : Ro := Ro + (Repeats * Height); END `l : Co := max (0(Co - Repeats)); END `L : Co := max (0(Co - (Repeats * Width))); END `r : Co := Co + Repeats; END ` : Cc := min (Noofcols (Cc + Repeats)); END `R : Co := Co + (Repeats * Width); END `! : setwindow [ ]; host Pattern; readscreen 'press return to continue'; Clearscreen; END ELSE Endbrowse := Truth; ENDCASE; setwindow Textwindow; Last_thing_done := Repeats Code; UNTIL Endbrowse ENDREPEAT; List_of_strings (Ro Co)(Rc Cc) Code } #============================================================================== # ruled handles the editing of the rules in rulebase. It calls browse to # perform the actual editwindow function and to handle the window scrolling. # The facilities that ruled handles itself is the trace facility and the # actual editing of the rule. 'I' is the keystroke that initiates editing # of the rule, and 'O' initiates the trace by putting the user in break mode. #============================================================================== ruled IS OP Rule Direction { NONLOCAL Rulebase Textwindow Cl; Textwindow @ 5 := link 'rule editor ' (string Rule) ' ' (string Direction) ' (hit to exit)'; Tv Cl := getunit Rulebase [Rule] Direction; IF first Tv THEN Original := Cl; Nialwindow @@ [0,0] := tally Cl + 2; Nialwindow @@ [1,0] := 21 - tally Cl; Ro Co Rc Cc := 0 0 0 0; Endedit := Falsehood; S&t := Cl (Ro Co)(Rc Cc); REPEAT S&t Code := [front,last] browse S&t; CASE Code FROM `I : S&t Mode Code := [ front , last ] editwindow S&t ; Tvx Rb := modifynote Rulebase [Rule][Direction] ["last][(first S&t)]; setwindow Cmdline; IF first Tvx THEN Rulebase := Rb; Reference := Null; IF Direction = "THENPART THEN Reference := "FORWARD; ELSEIF Direction = "IFPART THEN Reference := "BACKWARD; ENDIF; IF Reference unequal Null THEN Chainers := display second getunit Rulebase [Rule] Reference; Chainers := first editwindow [[Chainers],0 0,0 0]; clearwindow; Tvy Rb := modifynote Rulebase [Rule][Reference] ["last][(execute link Chainers)]; ENDIF; IF first Tvy THEN Rulebase := Rb; readscreen 'rulebase updated. press return'; ELSE readscreen 'something wrong in chainers'; ENDIF; ELSE readscreen 'something wrong in clauses. press return'; ENDIF; END `O : setwindow Nialwindow; Clearwindow; Break; END `Q : setwindow Cmdline; saveroster null "RULEBASE "kb; Endedit := l; END ELSE Code := second charrep Code; CASE Code FROM 49 : Endedit := l; END ELSE setwindow Cmdline; readscreen 'invalid keystroke'; Clearwindow; ENDCASE ENDCASE UNTIL Endedit ENDREPEAT; Clearscreen; ELSE readscreen 'rulebase not accessed properly. press return'; ENDIF; } #-- allows user to make a new rule and add it to rulebase --------------------- Mkrule IS { NONLOCAL Rulebase; Rule := phrase readscreen 'Name ? '; writescreen ' '; Tv := first first getnote Rulebase [Rule]; IF not Tv THEN Tv Rulebase := insertnote Rulebase [rule]('' '' '' [] [] o) "Insert; EACHRIGHT ruled Rule ("ENGLISH "IFPART "THENPART); ELSE iterate writescreen 'rule already exists. use RULED "name "zone' 'where "zone is one of "ENGLISH "IFPART "THENPART'; ENDIF; } process is execute #-- tracing operations to be called by user when in break mode -------------- try is op n {process (n pick cl)} tracetry is op n {set "trace; process (n pick cl); set "notrace;} traceall is {each try (tell tally cl)} #-- inference engine function that conducts checks on rules to see if #-- they are valid -------------------------------------------------- backwardchain IS OPERATION Goalrule { _ _ Clauses _ _ Backrules Trace_status:=second getnote Rulebase [Goalrule]; IF Trace_status THEN ruled Goalrule "IFPART; ENDIF; FOR I WITH grid Clauses DO Rules := I pick Backrules; REPEAT Failed := not process (I pick Clauses); IF Failed and not empty Rules THEN Firstrule Rules := [first,rest] Rules; Tv := backwardchain Firstrule; IF Tv THEN forwardchain Firstrule ENDIF; ELSE EXIT l ENDIF; UNTIL not Failed ENDREPEAT; IF Failed THEN EXIT l ENDIF; ENDFOR; not Failed } #-- inference engine function that controls the logical flow of control- #-- of the rules-------------------------------------------------------- forwardchain IS OPERATION Rule { _ explanation _ Actions Rules _ Trace_status:=second getnote rulebase [Rule]; IF Trace_status THEN ruled rule "THENPART; ENDIF; IF Explain THEN ITERATE writescreen (Explanation link '' ''); ENDIF; FOR J WITH grid Actions DO process ((J pick) Actions); Forwardrules := J pick Rules; Tv := Falsehood; WHILE (not empty Forwardrules) and (not Tv) DO Nextrule Forwardrules := [first,rest] Forwardrules; Tv := backwardchain Nextrule; IF Tv THEN forwardchain Nextrule ENDIF; ENDWHILE; ENDFOR; } switch is op rule whichway { nonlocal rulebase; tv rb:=modifynote rulebase [rule]["TRACE_STATUS]["last][whichway="on]; if first tv then rulebase:=rb; endif; tv }