13.6 Compiling Facts

The code in section 13.5 used the class inside without defining it. Here again are the rules for inside:

 inside(maryland, united_states). inside(baltimore, maryland). inside(california, united_states). inside(san_francisco, california). 

One difference between the definitions for inside and those for within is that the rules for inside have constants instead of variables in the head. Another is that the body is empty. The Prolog compiler first transforms the rules so that the heads contain only variables; this also takes care of the empty body. After the transformation,

 inside(X, Y) :- =(X, maryland), =(Y, united_states). inside(X, Y) :- =(X, baltimore), =(Y, maryland). inside(X, Y) :- =(X, california), =(Y, united_states). inside(X, Y) :- =(X, san_francisco), =(Y, california). 

This code makes use of the special predicate =. The predicate = returns true if the two arguments can be made to unify, false otherwise. Unlike other predicates, = returns true at most once. This means that it is unnecessary to backtrack on a call to =.

The predicate = is implemented as a call to unify. Here is pseudocode for inside:

 boolean inside(Object X, Object Y) {     stackTag = Prolog.markTrail();     if(unify(X, "maryland") && unify(Y, "united_states"))         yield true;     Prolog.undoBindings(stackTag);     stackTag = Prolog.markTrail();     if(unify(X, "baltimore") && unify(Y, "maryland"))         yield true;     Prolog.undoBindings(stackTag);     stackTag = Prolog.markTrail();     if(unify(X, "california") && unify(Y, "united_states"))         yield true;     Prolog.undoBindings(stackTag);     stackTag = Prolog.markTrail();     if(unify(X, "san_francisco") && unify(Y, "california"))         yield true;     yield false; } 

This code is similar to actual Java code, except for the yield statements; yield is handled the same way it is handled in within (section 13.5).

 .class public inside .field state$ I                         ; Keep track of state .field stackTag Ljava/lang/Object;      ; Stack token .method call(Ljava/lang/Object;Ljava/lang/Object;)Z     aload_0     getfield inside/state$ I     tableswitch 0     state0     state1     state2     state3     default: fail state0:     aload_0                   ; Mark the trail     invokestatic Prolog/markTrail()Ljava/lang/Object;     putfield inside/stackTag Ljava/lang/Object;     aload_1                   ; Try to unify X and maryland     ldc "maryland"     invokestatic Prolog/unify        (Ljava/lang/Object;Ljava/lang/Object;)Z     ifeq state1            ; If they don't unify,                            ; go to next state     aload_2                ; Unify Y and united_states     ldc "united_states"     invokestatic Prolog/unify         (Ljava/lang/Object;Ljava/lang/Object;)Z     ifeq state1             ; If they don't unify,                             ; go to next state          ; We have successfully matched the arguments against          ; maryland and united_states. Go to next state and          ; return true     aload_0                 ; Remember that the new state is 1     iconst_1     putfield inside/state$ I     iconst_1               ; Yield true     ireturn state1:     aload_0           ; Undo bindings from the last rule     getfield inside/stackTag Ljava/lang/Object;     invokestatic Prolog/undoBindings(Ljava/lang/Object;)V     ;; The rest of states 1, 2, and 3 have been omitted. They     ;; follow the same pattern used for state0:     ;;    Undo bindings     ;;    Mark the stack     ;;    Try to unify the arguments with the rule head     ;;    If that succeeds, set the state variable and return true fail:     iconst_0          ; Fail     ireturn .end method 

This code is much like the code for within. One difference is that instead of creating inside and within objects and calling call, this code uses unify, defined in the class Prolog (it was discussed in section 13.3.1). The method unify returns true if it can match the arguments to the method with the particulars of that rule.

Because only unify is being used, there is no need to loop. If it succeeds, it will succeed only once. There is no reason to try again. This makes the body a bit simpler, because there is no need to jump into the middle of a loop. When yielding, the code sets the state$ variable to the beginning of the next rule.



Programming for the Java Virtual Machine
Programming for the Javaв„ў Virtual Machine
ISBN: 0201309726
EAN: 2147483647
Year: 1998
Pages: 158
Authors: Joshua Engel

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net