package edu.stanford.nlp.sempre;
import com.google.common.base.Function;
import fig.basic.LispTree;
import java.util.List;
/**
* Performs arithmetic operations (+, -, *, /).
* Note that these are non-binary relations, which means we can't model them
* using a join.
*
* @author Percy Liang
*/
public class ArithmeticFormula extends Formula {
public enum Mode { add, sub, mul, div };
public final Mode mode;
public final Formula child1;
public final Formula child2;
public ArithmeticFormula(Mode mode, Formula child1, Formula child2) {
this.mode = mode;
this.child1 = child1;
this.child2 = child2;
}
public LispTree toLispTree() {
LispTree tree = LispTree.proto.newList();
tree.addChild(modeToString(mode));
tree.addChild(child1.toLispTree());
tree.addChild(child2.toLispTree());
return tree;
}
@Override
public void forEach(Function<Formula, Boolean> func) {
if (!func.apply(this)) { child1.forEach(func); child2.forEach(func); }
}
@Override
public Formula map(Function<Formula, Formula> func) {
Formula result = func.apply(this);
return result == null ? new ArithmeticFormula(mode, child1.map(func), child2.map(func)) : result;
}
@Override
public List<Formula> mapToList(Function<Formula, List<Formula>> func, boolean alwaysRecurse) {
List<Formula> res = func.apply(this);
if (res.isEmpty() || alwaysRecurse) {
res.addAll(child1.mapToList(func, alwaysRecurse));
res.addAll(child2.mapToList(func, alwaysRecurse));
}
return res;
}
public static Mode parseMode(String mode) {
if ("+".equals(mode)) return Mode.add;
if ("-".equals(mode)) return Mode.sub;
if ("*".equals(mode)) return Mode.mul;
if ("/".equals(mode)) return Mode.div;
return null;
}
public static String modeToString(Mode mode) {
switch (mode) {
case add: return "+";
case sub: return "-";
case mul: return "*";
case div: return "/";
default: throw new RuntimeException("Invalid mode: " + mode);
}
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof ArithmeticFormula)) return false;
ArithmeticFormula that = (ArithmeticFormula) thatObj;
if (this.mode != that.mode) return false;
if (!this.child1.equals(that.child1)) return false;
if (!this.child2.equals(that.child2)) return false;
return true;
}
public int computeHashCode() {
int hash = 0x7ed55d16;
hash = hash * 0xd3a2646c + mode.toString().hashCode(); // Note: don't call hashCode() on mode directly.
hash = hash * 0xd3a2646c + child1.hashCode();
hash = hash * 0xd3a2646c + child2.hashCode();
return hash;
}
}