package edu.stanford.nlp.sempre; import java.util.List; import com.google.common.base.Function; import com.google.common.collect.Lists; import fig.basic.LispTree; /** * An ActionFormula represent a compositional action used in the interactive * package : is used as a prefix to denote an ActionFormula primitive (: * actioname args) sequential (:s ActionFormula ActionFormula ...) repeat (:loop * Number ActionFormula) conditional (:if Set ActionFormula) block scoping (:blk * ActionFormula) * * @author sidaw */ public class ActionFormula extends Formula { public enum Mode { primitive(":"), // (: remove *) sequential(":s"), // (:s (: add red top) (: remove this)) repeat(":loop"), // (:loop (count (has color green)) (: add red top)) conditional(":if"), // (:if (count (has color green)) (: add red top)) whileloop(":while"), // (:while (count (has color green)) (: add red top)) forset(":for"), // (:for (and this (color red)) (:s (: add red top) (: add // yellow top) (: remove))) foreach(":foreach"), // (:foreach * (add ((reverse color) this) top)) // primitives for declaring variables // let(":let"), // (:let X *), // set(":set"), // (:set X *) block(":blk"), // start a block of code (like {}) with a new scope blockr(":blkr"), // also return a result after finishing the block isolate(":isolate"), other(":?"); private final String value; Mode(String value) { this.value = value; } @Override public String toString() { return this.value; } }; public final Mode mode; public final List<Formula> args; public ActionFormula(Mode mode, List<Formula> args) { this.mode = mode; this.args = args; } public static Mode parseMode(String mode) { if (mode == null) return null; for (Mode m : Mode.values()) { // LogInfo.logs("mode string %s \t== %s \t!= %s", m.toString(), mode, // m.name()); if (m.toString().equals(mode)) return m; } if (mode.startsWith(":")) throw new RuntimeException("Unsupported ActionFormula mode"); return null; } @Override public LispTree toLispTree() { LispTree tree = LispTree.proto.newList(); tree.addChild(this.mode.toString()); for (Formula arg : args) tree.addChild(arg.toLispTree()); return tree; } @Override public void forEach(Function<Formula, Boolean> func) { if (!func.apply(this)) { for (Formula arg : args) arg.forEach(func); } } @Override public Formula map(Function<Formula, Formula> transform) { Formula result = transform.apply(this); if (result != null) return result; List<Formula> newArgs = Lists.newArrayList(); for (Formula arg : args) newArgs.add(arg.map(transform)); return new ActionFormula(this.mode, newArgs); } @Override public List<Formula> mapToList(Function<Formula, List<Formula>> transform, boolean alwaysRecurse) { List<Formula> res = transform.apply(this); if (res.isEmpty() || alwaysRecurse) { for (Formula arg : args) res.addAll(arg.mapToList(transform, alwaysRecurse)); } return res; } @SuppressWarnings({ "equalshashcode" }) @Override public boolean equals(Object thatObj) { if (!(thatObj instanceof ActionFormula)) return false; ActionFormula that = (ActionFormula) thatObj; if (!this.mode.equals(that.mode)) return false; if (!this.args.equals(that.args)) return false; return true; } @Override public int computeHashCode() { int hash = 0x7ed55d16; hash = hash * 0xd3a2646c + mode.hashCode(); hash = hash * 0xd3a2646c + args.hashCode(); return hash; } }