ChoicePoint.java
/*
* #%L
* prolobjectlink-jpi-jtrolog
* %%
* Copyright (C) 2012 - 2018 WorkLogic Project
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
*/
package jTrolog.engine;
import jTrolog.terms.Struct;
import jTrolog.terms.Clause;
import jTrolog.errors.PrologException;
import jTrolog.parser.Parser;
import java.util.List;
/**
* @author janerist@stud.ntnu.no
* @author ivar.orstavik@hist.no
*/
@SuppressWarnings({ "rawtypes" })
class ChoicePoint {
// CP head
Struct head;
int headCtx = -1;
// CP body
private Struct[] body;
private int nextInBody = 0;
private int bodySize = 0;
int bodyCtx;
// CP parent and cutParent
ChoicePoint parent;
ChoicePoint cutParent;
// alternative rules
List alternatives;
int altPos;
int alternativeCount;
// or primitive
PrimitiveInfo prim;
/**
* recycles previously used CP objects on the stack
*
* @param s
* @param ctx
* @param parent
*/
final void set(final Struct s, final int ctx, final ChoicePoint parent) throws PrologException {
head = s;
headCtx = ctx;
this.parent = parent;
cutParent = Parser.isSemiAndNotIf(parent.head) ? parent.parent.cutParent : this;
altPos = 0;
this.alternatives = null;
this.alternativeCount = 0;
bodyCtx = -1;
nextInBody = 0;
bodySize = 0;
}
final void setRules(final List rules) throws PrologException {
altPos = 0;
alternatives = rules;
alternativeCount = alternatives.size();
}
final boolean hasAlternatives() {
return altPos < alternativeCount;
}
final Clause nextAlternative() {
return (Clause) alternatives.get(altPos++);
}
/**
* removes any choice points (alternative rules) on the ChoicePoint.
*/
final void cutAlternatives() {
altPos = alternativeCount;
}
public String toString() {
if (prim != null)
return "!!" + head + "<" + headCtx + ">" + "!!";
String s2 = head == null ? "?-\n " : head + "<" + headCtx + "> :-\n ";
if (body != null) {
for (int i = 0; i < bodySize; i++) {
if (i != 0)
s2 += ",\n ";
Object rule = body[i];
if (i == nextInBody)
s2 += "**" + rule + "**";
else
s2 += rule;
}
}
if (hasAlternatives()) {
s2 += "\n\n rules:\n";
for (int i = altPos; i < alternativeCount; i++)
s2 += " " + alternatives.get(i) + "\n";
}
return s2;
}
boolean hasTODO() {
return nextInBody < bodySize;
}
public void fail() {
bodySize = 0;
nextInBody = 0;
parent.nextInBody--;
}
Struct getTODO() {
return body[nextInBody++];
}
final void setBody(final Struct[] body, final int bodyCtx) {
this.bodyCtx = bodyCtx;
this.body = body;
nextInBody = 0;
bodySize = body.length;
}
public void reuse() {
this.head = body[0];
this.headCtx = bodyCtx;
this.nextInBody = 0;
this.altPos = 0;
}
}