sclass NLLogic_MultiThreadedEngine { bool unsafeEvals, showFailed; F0 makeLogicChecker; Pair, LS> rulesAndFacts; MultiMap executedRules = treeMultiMap(); new MultiThreadStepper stepper; new LinkedHashSet inputs; *(Pair, LS> *rulesAndFacts) {} void processInput(S input) { if (!inputs.add(input)) ret; temp tempSetTL(nlLogic_processInputOrFact_steppable_allowUnsafeEvals, unsafeEvals); stepper.add(nlLogic_processInputOrFact_steppable(makeLogicChecker(), input, false /*inputAsFact*/, rulesAndFacts, new Collector() { bool add(ExecutedRule r) { if (!showFailed && r.isFailed()) true; executedRules.put(ai_executedRuleScorer().get(r), r); for (S s : unnull(r.newInput)) processInput(s); true; } })); }; void seedInput(S input) { processInput(input); } void fullRun { stepAllWithStats_multiThreaded(stepper); } NLLogicChecker_v2 makeLogicChecker() { ret makeLogicChecker != null ? callF(makeLogicChecker) : new NLLogicChecker_v2; } L executedRules() { ret executedRules.allValues(); } }