📄 ruleclausecode.java
字号:
case CALL_TABLED:
out.println("CALL_TABLED ");
break;
case CALL_WILD_TABLED:
out.println("CALL_WILD_TABLED ");
break;
case CALL_PREDICATE_INDEX:
out.println("CALL_PREDICATE_INDEX " + args[argi++]);
break;
case LAST_CALL_PREDICATE:
out.println("LAST_CALL_PREDICATE " + args[argi++]);
break;
case CALL_TRIPLE_MATCH:
out.println("CALL_TRIPLE_MATCH");
break;
case PROCEED:
out.println("PROCEED");
break;
case MAKE_FUNCTOR:
out.println("MAKE_FUNCTOR " + args[argi++]);
break;
case GET_FUNCTOR:
out.println("GET_FUNCTOR " + args[argi++]);
break;
case CALL_BUILTIN:
out.println("CALL_BUILTIN " + ((Builtin)args[argi++]).getName() + "/" + code[p++]);
break;
case CLEAR_ARG:
out.println("CLEAR_ARG " + "A" + code[p++]);
break;
case ALLOCATE:
out.println("ALLOCATE + " + code[p++]);
break;
default:
out.println("Unused code: " + instruction);
break;
}
}
}
}
/**
* Print clause as rule for tracing.
*/
public String toString() {
if (rule == null) {
return "[anon]";
} else {
return "[" + rule.toShortString() + "]";
}
}
/**
* Inner class - compiler state.
*/
static class CompileState {
/** The temporary code vector during construction */
byte[] code;
/** The temporary arg list during construction */
ArrayList args;
/** The code pointer during construction */
int p;
/** array of lists of variables in the rule clauses, array index is 0 for head, body starts at 1 */
private List[] termVarTable;
/** Map from variables to the list of term positions in which it occurs */
private Map varOccurrence = new HashMap();
/** List of all permanent variables */
private List permanentVars = new ArrayList();
/** List of all temporary variables */
private List tempVars = new ArrayList();
/** The total number of var occurrences */
int totalOccurrences = 0;
/** the set of variables processed so far during the compile phase */
Set seen = new HashSet();
/** The rule being parsed */
Rule rule;
/**
* Constructor.
*/
CompileState(Rule rule) {
classifyVariables(rule);
this.rule = rule;
// Create a scratch area for assembling the code, use a worst-case size estimate
code = new byte[10 + totalOccurrences + rule.bodyLength()*10];
args = new ArrayList();
}
/**
* Emit the code for any bound/unbound tests add start of body
* and return the number of body clauses dealt with.
*/
int emitBindingTests() {
int i = 0;
while (i < rule.bodyLength()) {
ClauseEntry term = rule.getBodyElement(i);
if (term instanceof Functor) {
Functor f = (Functor)term;
if (f.getArgLength() != 1) break;
int ai = aIndex(f.getArgs()[0]);
if (ai >= 0) {
if (f.getName().equals("bound")) {
code[p++] = TEST_BOUND;
code[p++] = (byte)ai;
} else if (f.getName().equals("unbound")) {
code[p++] = TEST_UNBOUND;
code[p++] = (byte)ai;
} else {
break;
}
}
} else {
break;
}
i++;
}
return i;
}
/**
* Return the argument index of the given variable.
*/
int aIndex(Node n) {
TriplePattern tp = (TriplePattern)rule.getHeadElement(0);
if (tp.getSubject() == n) {
return 0;
} else if (tp.getPredicate() == n) {
return 1;
} else if (tp.getObject() == n) {
return 2;
} else {
return -1;
}
}
/**
* emit the code for the head clause
*/
void emitHead(TriplePattern head) {
if (permanentVars.size() > 0) {
code[p++] = ALLOCATE;
code[p++] = (byte)permanentVars.size();
}
emitHeadGet(head.getSubject(), 0);
emitHeadGet(head.getPredicate(), 1);
emitHeadGet(head.getObject(), 2);
}
/**
* Emit a single head get operation
* @param node the node to emit
* @param argi the argument register to address
*/
void emitHeadGet(Node node, int argi) {
if (node instanceof Node_RuleVariable) {
Node_RuleVariable var = (Node_RuleVariable)node;
if (isDummy(var)) {
// Node code required, var not used
return;
}
if (isTemp(var)) {
List occurrences = (List)varOccurrence.get(var);
if (occurrences.size() == 2 &&
((TermIndex)occurrences.get(0)).index <= 2 &&
((TermIndex)occurrences.get(0)).index ==((TermIndex)occurrences.get(1)).index) {
// No movement code required, var in right place
} else {
code[p++] = seen.add(var) ? GET_TEMP : UNIFY_TEMP;
code[p++] = (byte)tempVars.indexOf(var);
code[p++] = (byte)argi;
}
} else {
code[p++] = seen.add(var) ? GET_VARIABLE : UNIFY_VARIABLE;
code[p++] = (byte)permanentVars.indexOf(var);
code[p++] = (byte)argi;
}
} else if (Functor.isFunctor(node)) {
Functor f = (Functor)node.getLiteralValue();
code[p++] = GET_FUNCTOR;
args.add(f);
Node[] fargs = f.getArgs();
for (int i = 0; i < fargs.length; i++) {
emitHeadGet(fargs[i], i+3);
}
} else {
code[p++] = GET_CONSTANT;
code[p++] = (byte)argi;
args.add(node);
}
}
/**
* Emit code for a body clause.
* @param goal the triple pattern to be called
*/
void emitBody(TriplePattern goal, LPRuleStore store) {
int argi = 0;
emitBodyPut(goal.getSubject(), 0, false);
emitBodyPut(goal.getPredicate(), 1, false);
emitBodyPut(goal.getObject(), 2, false);
List predicateCode = store.codeFor(goal);
if (predicateCode == null || predicateCode.size() == 0) {
code[p++] = CALL_TRIPLE_MATCH;
} else {
// code[p++] = CALL_TABLED;
if (goal.getPredicate().isVariable()) {
// Experimental. Force tabling of any wildcard predicate calls
code[p++] = CALL_TABLED;
} else if (store.isTabled(goal)) {
// if (store.isTabled(goal)) {
code[p++] = goal.getPredicate().isVariable() ? CALL_WILD_TABLED : CALL_TABLED;
} else {
if (permanentVars.size() == 0) {
code[p++] = LAST_CALL_PREDICATE;
} else {
// Normal call, but can it be indexed further?
if (store.isIndexedPredicate(goal.getPredicate()) && goal.getObject().isVariable()) {
code[p++] = CALL_PREDICATE_INDEX;
} else {
code[p++] = CALL_PREDICATE;
}
}
args.add(predicateCode);
}
}
}
/**
* Emit code a single body put operation.
* @param node the node to emit
* @param argi the argument register to use
* @param deref if true force a dereference of the variable binding at this point for
* use in calling builtins
*/
void emitBodyPut(Node node, int argi, boolean deref) {
if (argi >= MAX_ARGUMENT_VARS) {
throw new LPRuleSyntaxException("Rule too complex for current implementation\n"
+ "Rule clauses are limited to " + MAX_ARGUMENT_VARS + " argument variables\n", rule);
}
if (node instanceof Node_RuleVariable) {
Node_RuleVariable var = (Node_RuleVariable)node;
if (isDummy(var)) {
code[p++] = CLEAR_ARG;
code[p++] = (byte)argi;
return;
}
if (isTemp(var)) {
List occurrences = (List)varOccurrence.get(var);
if (occurrences.size() == 2 &&
((TermIndex)occurrences.get(0)).index ==((TermIndex)occurrences.get(1)).index) {
// No movement code required, var in right place
} else {
code[p++] = PUT_TEMP;
code[p++] = (byte)tempVars.indexOf(var);
code[p++] = (byte)argi;
}
} else {
if (! seen.add(var)) {
code[p++] = (deref ? PUT_DEREF_VARIABLE : PUT_VARIABLE);
} else {
code[p++] = PUT_NEW_VARIABLE;
}
code[p++] = (byte)permanentVars.indexOf(var);
code[p++] = (byte)argi;
}
} else if (Functor.isFunctor(node)) {
Functor f = (Functor)node.getLiteralValue();
Node[] fargs = f.getArgs();
for (int i = 0; i < fargs.length; i++) {
emitBodyPut(fargs[i], i+3, deref);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -