static class EvalTransform { int varCount; Exception exception; boolean recurse = true; Lisp newVar() { ret lisp("$e" + (++varCount)); } Lisp transformEval(Lisp tree, L out) { if (tree.is("[]", 2) && tree.get(0).is("eval", 0) && tree.get(1).is("()", 1)) { Lisp exp = tree.get(1).get(0); if (recurse) exp = transformEval(exp, out); Lisp var = newVar(); out.add(lisp("[]", var, "=").addAll(nlUnroll(exp))); ret var; } // recurse Lisp n = new Lisp(tree.head); for (Lisp t : tree) n.add(transformEval(t, out)); ret n; } Lisp evalTransformRule(Lisp rule) { try { L ops = snlSplitOps(rule); // expand unconditional rule if (ops == null || ops.isEmpty() || !ops.get(0).is("if *", 1)) ops = litlist(lisp("then *", rule)); for (int i = 0; i < l(ops); i++) { Lisp op = ops.get(i).get(0); new L out; Lisp op2 = transformEval(op, out); if (out.isEmpty()) continue; for (Lisp l : out) { ops.add(i, lisp(i == 0 ? "if *" : "and *", l)); ++i; } ops.set(i, lisp(i == l(ops)-1 ? "then *" : "and *", op2)); } ret snlJoinOps(ops); } catch (Exception e) { exception = e; ret rule; } } Lisp evalTransformQuestion(Lisp question) { try { new L out; Lisp tree = transformEval(question, out); for (int i = l(out)-1; i >= 0; i--) tree = lisp("[]", out.get(i), "and", tree); ret tree; } catch (Exception e) { exception = e; ret question; } } }