srecord MMOConsistencyError(int idx, S error) {}

// items: pairs of example inputs (line-separated) + pattern
static L<MMOConsistencyError> mmo_consistencyCheck(LPairS items) {
  new L<MMOConsistencyError> errors;
  for i over items:
    mmo_checkLocalConsistency(i, items.get(i), errors);
  ret errors;
}

svoid mmo_checkLocalConsistency(int idx, PairS qa, L<MMOConsistencyError> errors) {
  LS questions = tlft(qa.a);
  for (S q : questions)
    if (!mmo_match_parsedPattern(qa.b, q))
      errors.add(MMOConsistencyError(idx, "Example " + quote(q) + " not matched by patterns " + quote(qa.b)));
}

svoid mmo_checkGlobalConsistency(int idx, PairS qa, LPairS items, L<MMOConsistencyError> errors) {
  LS questions = tlft(qa.a);
  for (S q : tlft(qa.a)) {
    int idxFound = mmo_indexOfFirstMatch(q, pairsB_lazy(items));
    if (idxFound >= 0 && idxFound != idx)
      errors.add(new MMOConsistencyError(idx, "Example " + quote(q) + " (index " + (idx+1) + ") shadowed by patterns " + quote(items.get(idxFound).b) + " (item " + (idxFound+1) + ")");
  }
}