// assumes translator 747 // variable assignments static class Ass { new Map map; void assign(S var, O value) { O v = map.get(var); if (v == null) map.put(var, value); else if (!v.equals(value)) fail("mismatch"); } } static class Pred { } static class Assign extends Pred { S var; O value; *(S *var, O *value) {} } static class And extends Pred { new List parts; *(Pred... parts) { this.parts = new ArrayList(Arrays.asList(parts)); } } static class Or extends Pred { new List parts; *(Pred... parts) { this.parts = new ArrayList(Arrays.asList(parts)); } } static void eval(Pred p, Ass ass) { if (p instanceof Assign) { Assign a = cast p; ass.assign(a.var, a.value); } else if (p instanceof And) { And a = cast p; for (Pred part : a.parts) eval(part, ass); } else fail(structure(p)); } static void shouldFail(Pred p) { try { eval(p, new Ass); fail("did not fail"); } catch (RuntimeException e) { print("OK (expected fail): " + structure(p)); } } static List singleton(X x) { new List list; list.add(x); return list; } static abstract class Iter { abstract Ass next(); } static class Singleton extends Iter { Ass value; *(Ass *value) {} Ass next() { if (value != null) { Ass v = value; value = null; return v; } return null; } } static class OrIterator extends Iter { Or o; int i; *(Or *o) {} public Ass next() { if (i >= o.parts.size()) return null; new Ass ass; eval(o.parts.get(i++), ass); return ass; } } static Iter multiEval(Pred p) { if (p instanceof Or) { Or o = cast p; return new OrIterator(o); } else { new Ass ass; eval(p, ass); return new Singleton(ass); } } p { new Ass ass; eval(new Assign("x", new Integer(1)), ass); print(structure(ass)); ass = new Ass; eval(new And( new Assign("x", new Integer(1)), new Assign("y", new Integer(2))), ass); print(structure(ass)); shouldFail(new And( new Assign("x", new Integer(1)), new Assign("x", new Integer(2)))); // test multiEval L list = all(multiEval(new Assign("a", new Integer(5)))); assertEquals(1, list.size()); print(structure(list)); list = all(multiEval(new Or( new Assign("a", new Integer(5)), new Assign("a", new Integer(7))))); assertEquals(2, list.size()); print(structure(list)); } static L all(Iter it) { new L l; while (true) { Ass ass = it.next(); if (ass != null) l.add(ass); else break; } return l; } static void assertEquals(O x, O y) { if (!(x == null ? y == null : x.equals(y))) fail(structure(x) + " != " + structure(y)); }