!include once #1027630 // Msg static transformable record LogicRule(lhs, rhs) {} cmodule NewEngineSpike > DynPrintLog { L msgs; bool verbose = true, printNonMatches = true; start-thread { if (empty(msgs)) setField(msgs := mainCruddieLog()); print("Have " + nMessages(msgs)); pnlStruct(takeFirst(2, msgs)); L msgs2 = whereFieldIsTrue fromUser(msgs); new L props; for (Msg msg : takeFirst(5, msgs2)) print(addAndReturn(props, ll(msg, "was understood correctly"))); props.add(print(ll(get(msgs2, 5), "is a wrong recognition"))); LogicRule rule = new( ll("$x", "is a wrong recognition"), ll("$x", "should be corrected")); for (O prop : props) applyLogicRuleToFact(rule, prop); } // use standard deep-zip & replace utils Map deepZip(O a, O b) { ret newGazelle_deepZip1(a, b); } O replaceVars(O o, Map map) { ret replaceVars_understandsTransformableAndList(o, map); } // define what a variable is bool isVar(O o) { ret o instanceof S && isDollarVar(o/S); } void applyLogicRuleToFact(LogicRule rule, O fact) { O cond = rule.lhs, rhs = rule.rhs; // now we match the fact to our condition Map map = deepZip(cond, fact); // Discard unless all keys are variables if (map != null && !all(keys(map), s -> isVar(s))) map = null; if (map == null) ret with if (printNonMatches) print("Non-match: " + quote(cond) + " / " + quote(fact)); // Now we have a proper mapping with the keys being variables! if (verbose) print("Match: " + quote(cond) + " / " + quote(fact)); // Apply mapping to right hand side O rhs_replaced = replaceVars(rhs, map); if (verbose) print(+rhs_replaced); Map trail = litorderedmap(op := "applyLogicRuleToFact", +rule, +fact, +rhs_replaced); addRewrittenRHS(rhs_replaced, trail); } void addRewrittenRHS(O rhs, O trail) { print("Derived: " + rhs); } }