astra.reasoner.util.AbstractEvaluateVisitor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of astra-interpreter Show documentation
Show all versions of astra-interpreter Show documentation
Core interpreter artifact for the ASTRA Language
package astra.reasoner.util;
import java.util.HashMap;
import java.util.Map;
import astra.formula.AND;
import astra.formula.Bind;
import astra.formula.BooleanTermFormula;
import astra.formula.BracketFormula;
import astra.formula.Comparison;
import astra.formula.Formula;
import astra.formula.FormulaVariable;
import astra.formula.Goal;
import astra.formula.ModuleFormula;
import astra.formula.NOT;
import astra.formula.OR;
import astra.formula.Predicate;
import astra.formula.TestGoal;
import astra.term.AtIndex;
import astra.term.Brackets;
import astra.term.Count;
import astra.term.FormulaTerm;
import astra.term.Funct;
import astra.term.Head;
import astra.term.ListSplitter;
import astra.term.ListTerm;
import astra.term.Not;
import astra.term.Operator;
import astra.term.Performative;
import astra.term.Primitive;
import astra.term.Tail;
import astra.term.Term;
import astra.term.Variable;
import astra.type.InvalidTypeException;
import astra.type.Type;
@SuppressWarnings("rawtypes")
public abstract class AbstractEvaluateVisitor implements LogicVisitor {
public static interface Handler {
public Class getType();
public Object handle(LogicVisitor visitor, T object, boolean passByValue);
}
private static Map, Handler extends Formula>> formulaHandlers = new HashMap, Handler extends Formula>>();
private static Map, Handler extends Term>> termHandlers = new HashMap, Handler extends Term>>();
public static void addFormulaHandler(Handler handler) {
formulaHandlers.put(handler.getType(), handler);
}
public static void addTermHandler(Handler handler) {
termHandlers.put(handler.getType(), handler);
}
@SuppressWarnings("unchecked")
private static Handler getFormulaHandler(Class cls) {
return (Handler) formulaHandlers.get(cls);
}
@SuppressWarnings("unchecked")
private static Handler getTermHandler(Class cls) {
// System.out.println("cls: " + cls.getCanonicalName());
return (Handler) termHandlers.get(cls);
}
protected boolean passByValue=true;
public AbstractEvaluateVisitor(boolean passByValue) {
this.passByValue = passByValue;
}
public Object visit(Formula formula) {
Handler handler = getFormulaHandler(formula.getClass());
// System.out.println("AEV Formula:" + formula + " / handler="+ handler);
if (handler == null) return null;
return handler.handle(this, formula, passByValue);
}
public Object visit(Term term) {
// System.out.println("AEV: Term: " + term.getClass().getCanonicalName());
Handler handler = getTermHandler(term.getClass());
// System.out.println("AEV: Term: " + term + " / handler="+ handler);
if (handler == null) return null;
return handler.handle(this, term, passByValue);
}
static {
addFormulaHandler(new Handler() {
public Class getType() { return Predicate.class; }
public Object handle(LogicVisitor visitor, Predicate predicate,boolean passByValue) {
Term[] terms = new Term[predicate.size()];
for (int i=0; i < predicate.size(); i++) {
terms[i] = (Term) predicate.getTerm(i).accept(visitor);
}
return new Predicate(predicate.predicate(), terms);
}
});
addFormulaHandler(new Handler() {
public Class getType() { return ModuleFormula.class; }
public Object handle(LogicVisitor visitor, ModuleFormula formula,boolean passByValue) {
return new ModuleFormula(formula.module(), (Predicate) formula.predicate().accept(visitor), formula.adaptor());
}
});
addFormulaHandler(new Handler() {
public Class getType() { return AND.class; }
public Object handle(LogicVisitor visitor, AND and,boolean passByValue) {
return new AND((Formula) and.left().accept(visitor), (Formula) and.right().accept(visitor));
}
});
addFormulaHandler(new Handler() {
public Class getType() { return OR.class; }
public Object handle(LogicVisitor visitor, OR or,boolean passByValue) {
// Formula left = (Formula) or.left().accept(visitor);
// Formula right = (Formula) or.right().accept(visitor);
// if (left == Predicate.TRUE || right == Predicate.TRUE) return Predicate.TRUE;
// if (left == Predicate.FALSE && right == Predicate.FALSE) return Predicate.FALSE;
return new OR((Formula) or.left().accept(visitor), (Formula) or.right().accept(visitor));
}
});
addFormulaHandler(new Handler() {
public Class getType() { return NOT.class; }
public Object handle(LogicVisitor visitor, NOT not,boolean passByValue) {
return new NOT((Formula) not.formula().accept(visitor));
}
});
addFormulaHandler(new Handler() {
public Class getType() { return Goal.class; }
public Object handle(LogicVisitor visitor, Goal goal,boolean passByValue) {
return new Goal((Predicate) goal.formula().accept(visitor));
}
});
addFormulaHandler(new Handler() {
public Class getType() { return TestGoal.class; }
public Object handle(LogicVisitor visitor, TestGoal goal,boolean passByValue) {
return new TestGoal((Predicate) goal.formula().accept(visitor));
}
});
addFormulaHandler(new Handler() {
public Class getType() { return FormulaVariable.class; }
public Object handle(LogicVisitor visitor, FormulaVariable variable,boolean passByValue) {
return variable.variable().accept(visitor);
}
});
addFormulaHandler(new Handler() {
public Class getType() { return BracketFormula.class; }
public Object handle(LogicVisitor visitor, BracketFormula formula,boolean passByValue) {
return new BracketFormula((Formula) formula.formula().accept(visitor));
}
});
addFormulaHandler(new Handler() {
public Class getType() { return Bind.class; }
public Object handle(LogicVisitor visitor, Bind bind,boolean passByValue) {
Bind b = new Bind(bind.variable(), (Term) bind.term().accept(visitor));
return b;
}
});
addFormulaHandler(new Handler() {
public Class getType() { return Comparison.class; }
@SuppressWarnings("unchecked")
public Object handle(LogicVisitor visitor, Comparison comparison,boolean passByValue) {
// Need to check if the bindings have been generated yet...
// System.out.println("\tvisitor: " + visitor.getClass().getCanonicalName());
// System.out.println("\tl: "+ comparison.left());
Term il = (Term) comparison.left().accept(visitor);
// System.out.println("\til: "+ il);
// System.out.println("\tr: "+ comparison.right());
Term ir = (Term) comparison.right().accept(visitor);
// System.out.println("\tir: "+ ir);
if (il instanceof Variable || ir instanceof Variable) return new Comparison(comparison.operator(), il,ir);
if (Type.isNumeric(il) && Type.isNumeric(ir)) {
Primitive> l = (Primitive>) il;
Primitive> r = (Primitive>) ir;
if (comparison.operator() == Comparison.LESS_THAN) {
return Type.doubleValue(l) < Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
} else if (comparison.operator() == Comparison.LESS_THAN_OR_EQUAL) {
return Type.doubleValue(l) <= Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
} else if (comparison.operator() == Comparison.GREATER_THAN) {
return Type.doubleValue(l) > Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
} else if (comparison.operator() == Comparison.GREATER_THAN_OR_EQUAL) {
return Type.doubleValue(l) >= Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
} else if (comparison.operator() == Comparison.EQUAL) {
return Type.doubleValue(l) == Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
} else if (comparison.operator() == Comparison.NOT_EQUAL || comparison.operator() == Comparison.OTHER_NOT_EQUAL) {
return Type.doubleValue(l) != Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
}
// } else if (il.type() == Type.performativeType && ir.type() == Type.performativeType) {
// Performative l = (Performative) il;
// Performative r = (Performative) ir;
// if (comparison.operator() == Comparison.EQUAL) {
// return l.equals(r) ? Predicate.TRUE : Predicate.FALSE;
// } else if (comparison.operator() == Comparison.NOT_EQUAL) {
// return l.equals(r) ? Predicate.FALSE : Predicate.TRUE;
// }
} else if (il.type() == Type.STRING && ir.type() == Type.STRING) {
Primitive l = (Primitive) il;
Primitive r = (Primitive) ir;
if (comparison.operator() == Comparison.EQUAL) {
return l.equals(r) ? Predicate.TRUE : Predicate.FALSE;
} else if (comparison.operator() == Comparison.NOT_EQUAL) {
// System.out.println("Comparison: " + comparison);
// System.out.println("result: " + l.equals(r));
return l.equals(r) ? Predicate.FALSE : Predicate.TRUE;
} else {
System.out.println("unknown opeator: " + comparison.operator());
}
} else if (il.type() == Type.BOOLEAN && ir.type() == Type.BOOLEAN) {
Primitive> l = (Primitive>) il;
Primitive> r = (Primitive>) ir;
if (comparison.operator() == Comparison.EQUAL) {
return l.equals(r) ? Predicate.TRUE : Predicate.FALSE;
} else if (comparison.operator() == Comparison.NOT_EQUAL) {
return l.equals(r) ? Predicate.FALSE : Predicate.TRUE;
}
} else if (il.type() == Type.LIST && ir.type() == Type.LIST) {
ListTerm l = (ListTerm) il;
ListTerm r = (ListTerm) ir;
if (comparison.operator() == Comparison.EQUAL) {
return l.equals(r) ? Predicate.TRUE : Predicate.FALSE;
} else if (comparison.operator() == Comparison.NOT_EQUAL) {
return l.equals(r) ? Predicate.FALSE : Predicate.TRUE;
}
} else {
System.out.println("Comparison Not Supported: " + comparison);
System.out.println("Left Type: " + il.type());
System.out.println("Right Type: " + ir.type());
}
throw new RuntimeException("Problem comparing non-numeric terms in astra.plan.EvaluateVisitor: " + comparison);
}
});
addFormulaHandler(new Handler() {
public Class getType() { return BooleanTermFormula.class; }
public Object handle(LogicVisitor visitor, BooleanTermFormula formula,boolean passByValue) {
return new BooleanTermFormula((Term) formula.term().accept(visitor));
}
});
addTermHandler(new Handler() {
public Class getType() { return Primitive.class; }
public Object handle(LogicVisitor visitor, Primitive term,boolean passByValue) {
return term;
}
});
addTermHandler(new Handler() {
public Class getType() { return Funct.class; }
public Object handle(LogicVisitor visitor, Funct function,boolean passByValue) {
Term[] terms = new Term[function.size()];
for (int i=0; i < function.size(); i++) {
terms[i] = (Term) function.getTerm(i).accept(visitor);
}
return new Funct(function.functor(), terms);
}
});
addTermHandler(new Handler() {
public Class getType() { return ListTerm.class; }
public Object handle(LogicVisitor visitor, ListTerm list, boolean passByValue) {
// Version 3:
// The latest edition of the saga: copy if not grounded. The main
// culprit here is the cartago.params([name, cls]) argument used in
// cartago.makeArtifact(...).
// System.out.println("List: " + list);
// if (!isGrounded(list)) {
// This was modified to ignore pass by value (not sure this is good)
// Problem was due to dealing with ModuleTerm instances which cannot
// be replaced with the actual value...
// NOTE: line below commented out to allow isGrounded() to be used
if (passByValue) {
ListTerm out = new ListTerm();
for (int i=0; i < list.size(); i++) {
out.add((Term) list.get(i).accept(visitor));
}
return out;
}
// Added the code below to make Prelude.remove(...) work
// Wrote test case for list containing an element generated by a listTerm, but not
// sure that previous issue has not been reintroduced...
for (int i=0; i < list.size(); i++) {
list.set(i, (Term) list.get(i).accept(visitor));
}
return list;
}
// private boolean isGrounded(Term term) {
// if (Variable.class.isInstance(term)) return false;
// if (ModuleTerm.class.isInstance(term)) return false;
// if (ListTerm.class.isInstance(term)) {
// for (Term t : (ListTerm) term) {
// if (!isGrounded(t)) return false;
// }
// }
// if (Funct.class.isInstance(term)) {
// for (Term t : ((Funct) term).terms()) {
// if (!isGrounded(t)) return false;
// }
// }
// return true;
// }
});
addTermHandler(new Handler() {
public Class getType() { return Operator.class; }
public Object handle(LogicVisitor visitor, Operator operator, boolean passByValue) {
// System.out.println("Operator: " + operator);
((AbstractEvaluateVisitor) visitor).passByValue=true;
Term l = (Term) operator.left().accept(visitor);
Term r = (Term) operator.right().accept(visitor);
((AbstractEvaluateVisitor) visitor).passByValue=passByValue;
// System.out.println("l: " + l);
// System.out.println("r: " + r + " / " + r.getClass().getCanonicalName());
// System.out.println("term types: " + l.type() + " / " + r.type());
// System.out.println("operator type: " + operator.type());
if (l instanceof Variable || r instanceof Variable) return Operator.newOperator(operator.op(), l, r);
// if (r instanceof Variable) {
// System.out.println("Right hand operand is unbound: " + r);
// System.exit(0);
// }
if (operator.type().equals(Type.STRING)) {
try {
if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.stringValue(l) + Type.stringValue(r));
} catch (Throwable th) {
System.out.println("Failed to evaluate: " + operator);
System.out.println("Left: " + Type.stringValue(l));
System.out.println("Right: " + Type.stringValue(r));
th.printStackTrace();
System.exit(0);
}
} else if (operator.type().equals(Type.LIST)) {
if (operator.op() == Operator.PLUS) {
return ((ListTerm) l).merge((ListTerm) r);
}
} else if (operator.type().equals(Type.INTEGER)) {
if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.integerValue(l) + Type.integerValue(r));
if (operator.op() == Operator.MINUS) return Primitive.newPrimitive(Type.integerValue(l) - Type.integerValue(r));
if (operator.op() == Operator.MULTIPLY) return Primitive.newPrimitive(Type.integerValue(l) * Type.integerValue(r));
if (operator.op() == Operator.DIVIDE) return Primitive.newPrimitive(Type.integerValue(l) / Type.integerValue(r));
if (operator.op() == Operator.MODULO) return Primitive.newPrimitive(Type.integerValue(l) % Type.integerValue(r));
} else if (operator.type().equals(Type.LONG)) {
// System.out.println("l=" + l + " / r=" + r + " / p(l)=" + Type.longValue(l) + " / p(r)=" + Type.longValue(r));
if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.longValue(l) + Type.longValue(r));
if (operator.op() == Operator.MINUS) return Primitive.newPrimitive(Type.longValue(l) - Type.longValue(r));
if (operator.op() == Operator.MULTIPLY) return Primitive.newPrimitive(Type.longValue(l) * Type.longValue(r));
if (operator.op() == Operator.DIVIDE) return Primitive.newPrimitive(Type.longValue(l) / Type.longValue(r));
if (operator.op() == Operator.MODULO) return Primitive.newPrimitive(Type.longValue(l) % Type.longValue(r));
} else if (operator.type().equals(Type.FLOAT)) {
if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.floatValue(l) + Type.floatValue(r));
if (operator.op() == Operator.MINUS) return Primitive.newPrimitive(Type.floatValue(l) - Type.floatValue(r));
if (operator.op() == Operator.MULTIPLY) return Primitive.newPrimitive(Type.floatValue(l) * Type.floatValue(r));
if (operator.op() == Operator.DIVIDE) return Primitive.newPrimitive(Type.floatValue(l) / Type.floatValue(r));
} else if (operator.type().equals(Type.DOUBLE)) {
if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.doubleValue(l) + Type.doubleValue(r));
if (operator.op() == Operator.MINUS) return Primitive.newPrimitive(Type.doubleValue(l) - Type.doubleValue(r));
if (operator.op() == Operator.MULTIPLY) return Primitive.newPrimitive(Type.doubleValue(l) * Type.doubleValue(r));
if (operator.op() == Operator.DIVIDE) return Primitive.newPrimitive(Type.doubleValue(l) / Type.doubleValue(r));
}
return null;
}
});
addTermHandler(new Handler() {
public Class getType() { return Performative.class; }
public Object handle(LogicVisitor visitor, Performative performative, boolean passByValue) {
return performative;
}
});
addTermHandler(new Handler() {
public Class getType() { return FormulaTerm.class; }
public Object handle(LogicVisitor visitor, FormulaTerm formula, boolean passByValue) {
if (formula.value() != null) formula.value().accept(visitor);
return null;
}
});
addTermHandler(new Handler() {
public Class getType() { return Brackets.class; }
public Object handle(LogicVisitor visitor, Brackets term, boolean passByValue) {
// System.out.println("term: " + term);
// System.out.println("term.term: " + term.term());
return term.term().accept(visitor);
}
});
addTermHandler(new Handler() {
public Class getType() { return ListSplitter.class; }
public Object handle(LogicVisitor visitor, ListSplitter term, boolean passByValue) {
return term;
}
});
addTermHandler(new Handler() {
public Class getType() { return Count.class; }
public Object handle(LogicVisitor visitor, Count count, boolean passByValue) {
// System.out.println("(AEV) Handling count: " + count);
Term c = (Term) count.term().accept(visitor);
if (c instanceof ListTerm) {
return Primitive.newPrimitive(((ListTerm) c).size());
}
return count;
}
});
addTermHandler(new Handler() {
public Class getType() { return Head.class; }
public Object handle(LogicVisitor visitor, Head head, boolean passByValue) {
// System.out.println("(AEV) Handling head: " + head);
Term c = (Term) head.term().accept(visitor);
// System.out.println("(AEV) processed: " + c);
if (c instanceof ListTerm) {
return ((ListTerm) c).get(0);
}
return head;
}
});
addTermHandler(new Handler() {
public Class getType() { return Tail.class; }
public Object handle(LogicVisitor visitor, Tail tail, boolean passByValue) {
// System.out.println("(AEV) Handling tail: " + tail);
Term c = (Term) tail.term().accept(visitor);
// System.out.println("(AEV) processed: " + c);
if (c instanceof ListTerm) {
ListTerm tailList = new ListTerm();
for (int i=1;i<((ListTerm)c).size(); i++) {
tailList.add(((ListTerm) c).get(i));
}
return tailList;
}
return tail;
}
});
addTermHandler(new Handler() {
public Class getType() { return AtIndex.class; }
@SuppressWarnings("unchecked")
public Object handle(LogicVisitor visitor, AtIndex atIndex, boolean passByValue) {
// System.out.println("(AEV) Handling at_index: " + atIndex);
Term t = (Term) atIndex.term().accept(visitor);
Term i = (Term) atIndex.index().accept(visitor);
if (t instanceof ListTerm && i instanceof Primitive) {
return ((ListTerm) t).get(((Primitive) i).value());
}
return atIndex;
}
});
addTermHandler(new Handler() {
public Class getType() { return Not.class; }
public Object handle(LogicVisitor visitor, Not term, boolean passByValue) {
Term innerTerm = (Term) term.term().accept(visitor);
if (innerTerm instanceof Primitive) {
Primitive primitive = (Primitive) innerTerm;
if (primitive.type().equals(Type.BOOLEAN)) {
return Primitive.newPrimitive(!(Boolean) primitive.value());
}
}
System.out.println("Term: " +term.term().accept(visitor));
System.out.println("Class: " +term.term().accept(visitor).getClass());
throw new InvalidTypeException("Expected boolean term but got: " + innerTerm.type());
}
});
}
// @Override
// public Object visit(AcreHistory history) {
// history.getConversationId().accept(this);
// history.getIndex().accept(this);
// history.getType().accept(this);
// history.getContent().accept(this);
// return null;
// }
}