IMPLEMENTATION Testing

IMPORT EQUALITY ONLY wEqual
       Triple ONLY triple & untriple
       PrettyFormatting ONLY prettyFormula prettyExpr fmtObjectNameLong
       Bool ONLY implies equiv
       BoolConv ONLY `
       RepoCom1 ONLY with
       Com ONLY succeed com
       RepoDiag COMPLETELY
       Repo ONLY repo
       RepoName COMPLETELY
       RepoAbsy COMPLETELY
       Seq ONLY :: <> ft rt seq revert # forall? % exist? ++ <>? ::? front
       Loquacity ONLY progress debugMsg
       Nat ONLY nat 10 |= 2 1 = 0 6 max succ 3 4
       Denotation ONLY ++
       NFmt ONLY fmtLatin1
       InternEval COMPLETELY
       ComSeqMapEnv ONLY &&
       SeqReduce ONLY /
       RepoObjectAccess ONLY actuals kind fct lookup
       SeqMap ONLY *
       Pair ONLY pair & 1st
       SeqZip ONLY zip
       Option ONLY option cont avail? avail nil
       OSubstitution ONLY subst def {} <$
       ABORT ONLY ABORT
       String ONLY string
       Expression ONLY expr:SORT repo obj tupleExpr apply tpos tuple
       RUNTIME ONLY obj
       ComCompose ONLY &
       SeqOfSeq ONLY flat
       OptionMap ONLY *
       RepoSource ONLY locator? locator
       Set ONLY set arb #
       PredefEntities ONLY proofscript
       DbGlobalEnv ONLY identTable
       DbConvEnv ONLY init @ env
       DbImpl2Expr ONLY expr2expr
       CAST ONLY cast
       Stopwatch ONLY start elapsed
       RealConv ONLY ``
       FmtSeq ONLY fmtSeq
       PROOFSCRIPT ONLY caseTests resultT diags: resultT -> diag
       Void ONLY void
       Real ONLY real
       Fmt ONLY pretty lit ; brk
       SeqSupplements ONLY sd td
       RepoAn ONLY none
       AbsySC ONLY ! tuple1
       RepoUnitAccess ONLY lookup? enterInstance
       StringConv ONLY `
       ComAction ONLY done
       NatConv ONLY `

-- %$Evaluating formulae$

DEF evaluate(R, main, f, r) ==
  IF hasQ(f) THEN succeed(&(R, (error, r) !! "formula not quantifier free"))
  ELSE
    evaluate(R, main, r)(f) & (\\tr.
    LET (R1, diags, res) == untriple(tr)
        e == IF res THEN ok
             ELSE (error, r) !! "could not be proven by evaluation"
             FI
    IN
    succeed(&(R1, diags <+ e))
    )
  FI
    
    
-- %return true, if formula is valid
FUN evaluate: repo ** unitName ** ref -> formula ->
               com[triple[repo, diag, bool]]
DEF evaluate(R, main, re)(F AS atomic(_, dfd, e :: _)) ==
  progress(10, \\ . " evaluating »" ++
           fmtLatin1(prettyFormula(R, main)(F)) ++ "«")(R) & (\\ R1.
  with(R1, eval(main, e)) && (\\res, R2.
  IF res okay? THEN succeed(&(R2, ok, true))
  IF res undefined? THEN succeed(&(R2, ok, false))
  IF res unknown? THEN succeed(&(R2, noEval(R1, re, main, e, msg(res)), false))
  FI
  ))
DEF evaluate(R, main, re)(F AS atomic(_, approx, e1 :: e2 :: _)) ==
  progress(10, \\ . " evaluating »" ++
           fmtLatin1(prettyFormula(R, main)(F)) ++ "«")(R) & (\\ R1.
  with(R1, eval(main, e1)) && (\\res1, R2.
  with(R2, eval(main, e2)) && (\\res2, R3.
  IF res1 unknown? THEN succeed(&(R3, noEval(R3, re, main, e1, msg(res1)),
                                  false))
  IF res2 unknown? THEN succeed(&(R3, noEval(R3, re, main, e2, msg(res2)),
                                  false))
  OTHERWISE
  IF res1 undefined? THEN succeed(&(R3, ok, true))
  OTHERWISE
  IF res2 undefined? THEN succeed(&(R3, ok, false))
  ELSE
    succeed(&(R3, ok, data(res1) wEqual data(res2)))
  FI
  )))
DEF evaluate(R, main, re)(F AS atomic(_, cong, e1 :: e2 :: _)) ==
  progress(10, \\ . " evaluating »" ++
           fmtLatin1(prettyFormula(R, main)(F)) ++ "«")(R) & (\\ R1.
  with(R1, eval(main, e1)) && (\\res1, R2.
  with(R2, eval(main, e2)) && (\\res2, R3.
  IF res1 unknown? THEN succeed(&(R3, noEval(R3, re, main, e1, msg(res1)),
                                  false))
  IF res2 unknown? THEN succeed(&(R3, noEval(R3, re, main, e2, msg(res2)),
                                  false))
  OTHERWISE
  IF (res1 undefined?) and (res2 undefined?) THEN succeed(&(R3, ok, true))
  OTHERWISE
  IF res1 undefined? THEN succeed(&(R3, hUndef(R, re, main,
                                               e1, msg(res1)), false))
  IF res2 undefined? THEN succeed(&(R3, hUndef(R, re, main,
                                               e2, msg(res2)), false))
  ELSE
    LET eq? == data(res1) wEqual data(res2)
        h == IF eq? THEN ok
             ELSE ok /* (hint, re) !! "equality test may fail" ++
                                " if function values are involved" */
             FI
    IN
    succeed(&(R3, h, eq?))
  FI
  )))
DEF evaluate(R, main, re)(F AS atomic(_, other(id, _), _)) ==
  progress(10, \\ . " evaluating »" ++
           fmtLatin1(prettyFormula(R, main)(F)) ++ "«")(R) & (\\ R1.
  succeed(&(R1, (error, re) !! "cannot evaluate `other(" ++ id ++
                               ", ...)'", false))
  )
DEF evaluate(R, main, re)(F AS atomic(_, informal(_), _)) ==
  progress(10, \\ . " evaluating »" ++
           fmtLatin1(prettyFormula(R, main)(F)) ++ "«")(R) & (\\ R1.
  succeed(&(R1, (error, re) !! "cannot evaluate informal formula", false))
  )
DEF evaluate(R, main, re)(F AS connect(_, k, fs)) ==
  progress(10, \\ . " starting »" ++
           fmtLatin1(prettyFormula(R, main)(F)) ++ "«")(R) & (\\ R1.
  evaluateAll(R1, main, re)(fs, <>, ok) & (\\ res.
  LET (R2, dg, ress) == untriple(res)
      final == IF dg ok? THEN
                 IF k neg? THEN ~(ft(ress))
                 IF k conj? THEN (and, true) / ress
                 IF k disj? THEN (or, false) / ress
                 IF k impl? THEN ft(ress) implies ft(rt(ress))
                 IF k equiv? THEN ft(ress) equiv ft(rt(ress))
                 ELSE false
                 FI
               ELSE
                 false
               FI
  IN
  progress(10, \\ . "ending with " ++ `(final))(R2) & (\\ R3.
  succeed(&(R3, dg, final))
  )))


FUN evaluateAll: repo ** unitName ** ref ->
                  seq[formula] ** seq[bool] ** diag ->
                  com[triple[repo, diag, seq[bool]]]
DEF evaluateAll(R, _main, _re)(<>, ress, dg) == succeed(&(R, dg, revert(ress)))
DEF evaluateAll(R, main, re)(f :: Fs, ress, dg) ==
  evaluate(R, main, re)(f) & (\\ res.
  LET (R1, dg1, valid?) == untriple(res)
  IN
  evaluateAll(R1, main, re)(Fs, valid? :: ress, dg <+ dg1)
  )

-- %$$Generating diagnostics for evaluation$

FUN noEval: repo ** ref ** unitName ** expr'RepoAbsy ** denotation -> diag
DEF noEval(R, re, main, e, msg) ==
  (error, re) !! "could not evaluate »" ++
                 fmtLatin1(prettyExpr(R, main)(e)) ++
                 "« " ++ msg

FUN hUndef: repo ** ref ** unitName ** expr'RepoAbsy ** denotation -> diag
DEF hUndef(R, re, main, e, msg) ==
  (hint, set(re, e)) !! "»" ++ fmtLatin1(prettyExpr(R, main)(e)) ++
  "« is undefined [" ++ msg ++ "]"


FUN set: ref ** expr'RepoAbsy -> ref
DEF set(re, e) ==
  IF re unitRef? THEN
    IF avail?(locator?(an(e))) THEN
      unitRef(cont(locator?(an(e))), unit(re))
    ELSE re
    FI
  ELSE re
  FI

-- %$Performing tests$

-- %we assume that e is an application of test[f, data]
DEF doTest(R, main, F, re, e) ==
  IF #(actuals(oper(funct(e)))(R)) |= 2 THEN
    succeed(R & (error, re) !! "!? wrong number of parameters for test")
  IF ~(checkF(F)) THEN
    succeed(R & (error, re) !! "malformed formula for test")
  ELSE
    IF hasQ(range(F)) THEN 
      succeed(R & (error, re) !! "range may not contain quantifiers")
    ELSE
      LET testF == ft(actuals(oper(funct(e)))(R))  -- test function
      IN
      IF ~(conforms(R, testF, vars(F))) THEN
        succeed(R & (error, re) !! "mismatch of function functionality" ++
                " and types of quantified variables")
      ELSE
        LET testValues == findArgs(testF, e)  
            g == instF(range(F), vars(F)) * testValues
        IN
        doTest(R, main, re)(g, testValues, ok)
      FI
    FI
  FI

FUN doTest: repo ** unitName ** ref ->
             seq[formula] ** seq[expr'RepoAbsy] ** diag ->
             com[pair[repo, diag]]
DEF doTest(R, _main, _re)(<>, _, dg) == succeed(R & dg)
DEF doTest(R, main, re)(f :: fs, e :: es, dg) ==
  evaluate(R, main, re)(f) & (\\tr.
  LET (R1, dg1, ok?) == untriple(tr)
      dg2 == IF ok? THEN ok
             ELSE (error, set(re, e)) !! "test failed for »" ++
                   fmtLatin1(prettyExpr(R, main)(e)) ++ "«" 
             FI
  IN
  doTest(R1, main, re)(fs, es, dg <+ dg1 <+ dg2)
  )
               

/* %@code{conforms(R, f, vars)} is true, iff @code{f(vars)} is type correct.
    (actually, vars may be scattered along higher-order calls) */
FUN conforms: repo ** objectName ** seq[objectName] -> bool
DEF conforms(R, f, vars) ==
  IF kind(f)(R) oper? ANDIF
    fct(kind(f)(R)) funct? THEN conforms(R, flat(dom(fct(kind(f)(R)))), vars)
  ELSE
    false
  FI

FUN conforms: repo ** fct'RepoAbsy ** seq[objectName] -> bool
DEF conforms(R, name(sr), var :: <>) == sr = sort(fct(var)(R))
DEF conforms(R, cart(els), vars) ==
  IF #(els) = #(vars) ANDIF forall?(name?, els) THEN
      forall?(\\x.x, zip(\\el,var. sort(el) = sort(fct(var)(R)))(els, vars))
  ELSE
    false
  FI
  
/* %return a sequence of arguments to given function within expr. */
FUN findArgs: objectName ** expr'RepoAbsy -> seq[expr'RepoAbsy]
DEF findArgs(_f, name(_, _)) == <>
DEF findArgs(f, apply(_, f1, args)) ==
  IF f1 name? ANDIF oper(f1) = f THEN %(args)
  ELSE findArgs(f, f1) ++ findArgs(f, args)
  FI
DEF findArgs(f, tuple(_, elems)) == flat(findArgs(f, _) * elems)
DEF findArgs(_f, den(_, _)) == <>
DEF findArgs(f, cases(_, ifs, optelse)) ==
  flat(findArgs(f, _) * then * ifs) ++ cont(<>)(findArgs(f, _) * optelse)
DEF findArgs(_f, lambda(_, _, _, _)) == <>
DEF findArgs(_f, let(_,_,_)) == <>
DEF findArgs(f, as(_, _, e)) == findArgs(f, e)
DEF findArgs(_f, any(_)) == <>

/* %Replace variables in formula by expression(s).
    Error checking here is over-engineering: these conditions should have
    been (and are) ensured by the caller. */
FUN instF: formula ** seq[objectName] -> expr'RepoAbsy -> formula
DEF instF(f, vars)(e) ==
  IF #(vars) = 1 ANDIF ~(tuple?(e)) THEN
    subst(ft(vars), e)(f)
  ELSE
    IF ~(tuple?(e)) THEN ABORT("instF'Testing: expr is not a tuple")
    ELSE
      IF #(vars) |= #(elems(e)) THEN
        ABORT("instF'Testing: number of vars and tuple exprs mismatch")
      ELSE
        def(vars, elems(e), {}) <$ f
      FI
    FI
  FI

-- %$Auxiliary functions$
FUN hasQ: formula -> bool
DEF hasQ(f) ==
  IF f atomic? THEN false
  IF f connect? THEN exist?(hasQ, formulas(f))
  IF f quant? THEN true
  FI

FUN checkF: formula -> bool
DEF checkF(f) == IF f quant? THEN kind(f) forall? ELSE false FI

FUN flat: fct'RepoAbsy -> fct'RepoAbsy
DEF flat(F AS name(_)) == F
DEF flat(cart(elems)) == cart(flat * elems)
DEF flat(funct(d, c)) == cart(%(flat(d), flat(c)))

/* %$Formal test$ */
/* %Perform a formal test */
DEF checkFormalTest1 == checkFormalTestX(1)
DEF checkFormalTest2 == checkFormalTestX(2)
DEF checkFormalTest3 == checkFormalTestX(3)
DEF checkFormalTest4 == checkFormalTestX(4)

FUN checkFormalTestX: nat -> repo ** unitName ** formula ** ref ** expr'RepoAbsy ->
                       com[pair[repo, diag]]
DEF checkFormalTestX(argNo)(R, main, F, re, e) ==
  LET func == ft(elems(arg(e)))  -- %function to be tested
      caseTest == sd(elems(arg(e))) -- %function to compute case tests
  IN       
  IF ~(checkF(F)) THEN succeed(R & (error, re) !! "malformed formula for test")
  ELSE
    IF hasQ(range(F)) THEN 
      succeed(R & (error, re) !! "range may not contain quantifiers")
    ELSE
      IF ~(conforms(R, oper(func), vars(F))) THEN
        succeed(R & (error, re) !! "mismatch of function functionality" ++
                " and types of quantified variables")
      ELSE 
        doEvalTestCases(R, main, caseTest, oper(func), re) & (\\ tr.
        LET (R2, dg, testFs) == untriple(tr)
        IN
        IF ~(ok?(dg)) THEN succeed(R & dg)
        ELSE
          LET actParams == front(actuals(oper(funct(e)))(R))
          IN
          debugMsg("checkFormalTest",
                   \\ . "now looking up checkTestFun /" ++
                   `(#(actParams)) ++ "/" ++ `(argNo) ++
                  pretty(fmtSeq(fmtObjectNameLong(R2))
                               (actParams)))(R2) & (\\ R3.
          LET
            (R5, ctF) == findCheckTestFun(argNo)(R3, actParams)
          IN
          IF avail?(ctF) THEN
            doCheckTestCases(R5, main, cont(ctF), re, e)
                            (testFs, <>) && (\\ R6, dg1.
            IF ok?(dg1) THEN
              doPerformFormalTest(argNo)(R6, main, re, F, e)
            ELSE
              succeed(R6 & dg1)
            FI
            )
          ELSE
            succeed(R5 & (error, re) !! "function `checkTestCases' not found")
          FI
          )
        FI
        )
      FI
    FI
  FI

/* %Liefert die Prädikate ab, mit denen die Testfälle beschrieben werden */
FUN doEvalTestCases: repo ** unitName ** expr'RepoAbsy ** objectName ** ref ->
                      com[triple[repo, diag, seq[expr'RepoAbsy]]]
DEF doEvalTestCases(R, main, caseTest, fctName, re) ==
  identTable & (\\ iTab.
  LET E0 == init(R, iTab)
      (E1, cTest, _) == expr2expr(E0, caseTest)
      (E2, arg0) == E1 @ repo(_)
      (E3, arg1) == E2 @ obj(_, cast(fctName))
      (E4, args) == E3 @ tuple(_, %(tupleExpr(arg0, 0),
                                    tupleExpr(arg1, 1)), 2)
      (_E5, top) == E4 @ apply(_, cTest, args, 1)
  IN
  start & (\\ _ .
  debugMsg("checkFormalTest", \\ . "evaluating case tests ...")(R) & (\\ R1.
  eval(main, top, resultT(R1)) & (\\ res.
  debugMsg("checkFormalTest", \\ . "... done")(R1) & (\\ R2.
  elapsed & (\\ diff.
  debugMsg("timer", \\ . "elapsed time: " ++ 
           ``(diff, 6) ++ " sec")(R2) & (\\ R3 . 
  IF res undefined? THEN
    succeed(&(R, (error, re) !! "undefined case test evaluator: " ++ msg(res),
              <>))
  IF res unknown? THEN
    succeed(&(R, (error, re) !! msg(res), <>))
  IF res okay? THEN
    LET testFs == caseTests(cast(data(res)))
        dg == diags(cast[obj, resultT](data(res)))
    IN
    debugMsg("checkFormalTest", \\ . "resulting case tests:\n" ++
             pretty(fmtSeq(prettyExpr(R2, main))(testFs)))(R3) & (\\ R4.
    succeed(&(R4, dg, testFs))
    )
  FI
  )))))))
  
/* Aufgerufen mit den Prädikaten und den schon abgelehnten Prädikaten */
FUN doCheckTestCases: repo ** unitName ** objectName ** ref ** expr'RepoAbsy ->
                       seq[expr'RepoAbsy] ** seq[expr'RepoAbsy] ->
                       com[pair[repo, diag]]
DEF doCheckTestCases(R, main, ctFun, re, e)(testFs, notFulfilled) ==
  IF testFs <>? THEN
    IF notFulfilled <>? THEN succeed(R & ok)
    IF notFulfilled ::? THEN 
      succeed(R & (<+, ok) / noTestData(R, main, re) * notFulfilled)
    FI
  IF testFs ::? THEN
    LET testF == ft(testFs)
        testData == td(elems(arg(e)))
        iExpr == apply(none, ctFun!, tuple1(%(testF, testData)))
    IN
    start & (\\ _ .
    debugMsg("doCheckTestCases", \\ . pretty(lit("checking test case ");
              prettyExpr(R, main)(testF)))(R) & (\\ R1a.
    with(R1a, eval(main, iExpr)) && (\\ res, R2.
    elapsed & (\\ diff.
    debugMsg("timer", \\ . "elapsed time: " ++ 
             ``(diff, 6) ++ " sec")(R2) & (\\ R3 . 
    IF res undefined? THEN
      debugMsg("doCheckTestCases", \\ . "returned undefined")(R3) & (\\ R4.
      doCheckTestCases(R4, main, ctFun, re, e)
                      (rt(testFs), testF :: notFulfilled)
      )
    IF res unknown? THEN
      succeed(R3 & (error, re) !! msg(res))
    IF res okay? THEN
      LET ires:bool == cast(data(res)) 
      IN
      debugMsg("doCheckTestCases", \\ . "returned " ++ `(ires))(R3) & (\\ R4.
      IF ires THEN
        doCheckTestCases(R4, main, ctFun, re, e)(rt(testFs), notFulfilled)
      ELSE
        doCheckTestCases(R4, main, ctFun, re, e)
                        (rt(testFs), testF :: notFulfilled)
      FI
      )
    FI
    )))))
  FI

    
FUN doPerformFormalTest: nat ->
                          repo ** unitName ** ref **
                          formula ** expr'RepoAbsy -> com[pair[repo, diag]]
DEF doPerformFormalTest(argNo)(R, main, re, F, e) ==
  LET testData == td(elems(arg(e)))
      errorFunct == \\ den. (error, re) !! den
      aParams == actuals(oper(funct(e)))(R)
      (R2, aFuns) == 
        IF argNo = 1 THEN findAuxFuns(R, ft(aParams))
        IF argNo = 2 THEN findAuxFuns(R, ft(aParams), sd(aParams))
        IF argNo = 3 THEN findAuxFuns(R, ft(aParams), sd(aParams),
                                             ft(rt(rt(aParams))))
        IF argNo = 4 THEN findAuxFuns(R, ft(aParams), sd(aParams),
                                             ft(rt(rt(aParams))),
                                             ft(rt(rt(rt(aParams)))))
        FI
  IN
  IF error?(aFuns) THEN
    succeed(R2 & diags(aFuns))
  ELSE
    doFT(argNo)(R2, main, F, re, errorFunct, aFuns)(testData, ok, 0)
  FI

FUN doFT: nat -> repo ** unitName ** formula ** ref **
           (denotation -> diag) ** auxFuns ->
           expr'RepoAbsy ** diag ** nat -> com[pair[repo, diag]]
DEF doFT(argNo)(R, main, F, re, diagF, aFuns)
        (restTestData, dg, no) ==
  LET testEmpty == apply(none, <>?(aFuns) !, restTestData)
  IN
  debugMsg("doFT", \\ . "#" ++ `(no) ++
                        " testing for empty test data")(R) & (\\ R1.
  with(R1, eval(main, testEmpty)) && (\\ res, R2.
  IF res undefined? THEN succeed(R2 & dg <+ diagF("doFT: <>? undefined ?!?"))
  IF res unknown? THEN succeed(R2 & dg <+ diagF("doFT: <>? unknown ?!? " ++
                                                msg(res)))
  IF res okay? THEN
    LET isEmpty? == cast(data(res))
    IN
    debugMsg("doFT", \\ . "returned " ++ `(isEmpty?))(R2) & (\\ R3.
    IF isEmpty? THEN succeed(R3 & dg)
    ELSE
      LET ftData == apply(none, ft(aFuns)!, restTestData)
          tupleArgs == IF argNo = 1 THEN
                         ftData
                       IF argNo = 2 THEN
                         tuple(none, %(apply(none, 1st(aFuns)!, ftData),
                                       apply(none, 2nd(aFuns)!, ftData)))
                       IF argNo = 3 THEN
                         tuple(none, %(apply(none, 1st(aFuns)!, ftData),
                                       apply(none, 2nd(aFuns)!, ftData),
                                       apply(none, 3rd(aFuns)!, ftData)))
                       IF argNo = 4 THEN
                         tuple(none, %(apply(none, 1st(aFuns)!, ftData),
                                       apply(none, 2nd(aFuns)!, ftData),
                                       apply(none, 3rd(aFuns)!, ftData),
                                       apply(none, 4th(aFuns)!, ftData)))
                       ELSE
                         ABORT("doFT'Testing: argNo too big (max 4, found " ++
                                                             `(argNo) ++ ")")
                       FI
          thisF == instF(range(F), vars(F))(tupleArgs)
          newRest == apply(none, rt(aFuns)!, restTestData)
          continue == \\r.doFT(argNo)(r, main, F, re, diagF, aFuns)
      IN
      debugMsg("doFT", \\ . "testing current input data")(R3) & (\\ R4.
      evaluate(R4, main, re)(thisF) & (\\ trRes.
      LET (R5, dg0, valid?) == untriple(trRes)
      IN
      IF valid? THEN
        debugMsg("doFT", \\ . "test successful")(R5) & (\\ R6.
        continue(R6)(newRest, dg <+ dg0, succ(no))
        )
      ELSE
        with(R5, evalD(main, ftData)) && (\\resD, R6.
        LET xmsg == IF resD undefined? THEN "[representation undefined:" ++
                      msg(resD) ++ "]"
                    IF resD unknown? THEN "[no representation:" ++
                      msg(resD) ++ "]"
                    IF resD okay? THEN data(resD)
                    FI
        IN 
        continue(R6)(newRest,
                     dg <+ dg0 <+ diagF("test failed for input data no " ++
                                        `(no) ++ " " ++ xmsg),
                     succ(no))
        )
      FI
      ))
    FI
    )
  FI
  ))    

DATA auxFuns == error(diags:diag)
                okay1(ft: objectName, rt: objectName, <>? : objectName)
                okay2(pair: objectName, 1st: objectName, 2nd: objectName,
                      ft: objectName, rt: objectName, <>? : objectName)
                okay3(triple: objectName, 1st: objectName,
                      2nd: objectName, 3rd: objectName,
                      ft: objectName, rt: objectName, <>? : objectName)
                okay4(quad: objectName, 1st: objectName,
                      2nd: objectName, 3rd: objectName, 4th: objectName,
                      ft: objectName, rt: objectName, <>? : objectName)
            
-- %1 argument
FUN findAuxFuns: repo ** objectName -> repo ** auxFuns
DEF findAuxFuns(R, data1) ==
  LET (R4, ftI) == findON(R, "Seq", %(data1), "ft")
      (R5, <>?_I) == findON(R4, "Seq", %(data1), "<>?")
      (R6, rt_I) == findON(R5, "Seq", %(data1), "rt")
    IN
    IF avail?(ftI) and avail?(<>?_I) and avail?(rt_I) THEN
      (R6, okay1(cont(ftI), cont(rt_I), cont(<>?_I)))
    ELSE
      LET dg4 == IF avail?(ftI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "ft'Seq not found ?!?" FI
          dg5 == IF avail?(<>?_I) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "<>?'Seq not found ?!?" FI
          dg6 == IF avail?(rt_I) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "rt'Seq not found ?!?" FI
      IN
      (R6, error(dg4 <+ dg5 <+ dg6))
    FI

-- %2 arguments    
FUN findAuxFuns: repo ** objectName ** objectName -> repo ** auxFuns
DEF findAuxFuns(R, data1, data2) ==
  LET (R1, pairI) == findON(R, "Pair", %(data1, data2), "pair")
      (R2, 1stI) == findON(R1, "Pair", %(data1, data2), "1st")
      (R3, 2ndI) == findON(R2, "Pair", %(data1, data2), "2nd")
  IN
  IF avail?(pairI) THEN
    LET (R4, ftI) == findON(R3, "Seq", %(cont(pairI)), "ft")
        (R5, <>?_I) == findON(R4, "Seq", %(cont(pairI)), "<>?")
        (R6, rt_I) == findON(R5, "Seq", %(cont(pairI)), "rt")
    IN
    IF avail?(1stI) and avail?(2ndI) and
         avail?(ftI) and avail?(<>?_I) and avail?(rt_I) THEN
      (R6, okay2(cont(pairI), cont(1stI), cont(2ndI), 
                cont(ftI), cont(rt_I), cont(<>?_I)))
    ELSE
      LET dg2 == IF avail?(1stI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "1st'Pair not found ?!?" FI
          dg3 == IF avail?(2ndI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "2nd'Pair not found ?!?" FI
          dg4 == IF avail?(ftI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "ft'Seq not found ?!?" FI
          dg5 == IF avail?(<>?_I) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "<>?'Seq not found ?!?" FI
          dg6 == IF avail?(rt_I) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "rt'Seq not found ?!?" FI
      IN
      (R6, error(dg2 <+ dg3 <+ dg4 <+ dg5 <+ dg6))
    FI
  ELSE
      LET dg1 == (error, freeRef("findAuxFuns'Testing")) !!
                  "pair'Pair not found ?!?" 
          dg2 == IF avail?(1stI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "1st'Pair not found ?!?" FI
          dg3 == IF avail?(2ndI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "2nd'Pair not found ?!?" FI
      IN
      (R3, error(dg1 <+ dg2 <+ dg3))
  FI

-- %3 arguments
FUN findAuxFuns: repo ** objectName ** objectName ** objectName ->
                  repo ** auxFuns
DEF findAuxFuns(R, data1, data2, data3) ==
  LET (R1, tripleI) == findON(R, "Triple", %(data1, data2, data3), "triple")
      (R2, 1stI) == findON(R1, "Triple", %(data1, data2, data3), "1st")
      (R3, 2ndI) == findON(R2, "Triple", %(data1, data2, data3), "2nd")
      (R3a, 3rdI) == findON(R3, "Triple", %(data1, data2, data3), "3rd")
  IN
  IF avail?(tripleI) THEN
    LET (R4, ftI) == findON(R3a, "Seq", %(cont(tripleI)), "ft")
        (R5, <>?_I) == findON(R4, "Seq", %(cont(tripleI)), "<>?")
        (R6, rt_I) == findON(R5, "Seq", %(cont(tripleI)), "rt")
    IN
    IF avail?(1stI) and avail?(2ndI) and avail?(3rdI) and 
         avail?(ftI) and avail?(<>?_I) and avail?(rt_I) THEN
      (R6, okay3(cont(tripleI), cont(1stI), cont(2ndI), cont(3rdI),
                cont(ftI), cont(rt_I), cont(<>?_I)))
    ELSE
      LET dg2 == IF avail?(1stI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "1st'Triple not found ?!?" FI
          dg3 == IF avail?(2ndI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "2nd'Triple not found ?!?" FI
          dg3a == IF avail?(3rdI) THEN ok
                  ELSE (error, freeRef("findAuxFuns'Testing")) !!
                    "   3rd'Triple not found ?!?" FI
          dg4 == IF avail?(ftI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "ft'Seq not found ?!?" FI
          dg5 == IF avail?(<>?_I) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "<>?'Seq not found ?!?" FI
          dg6 == IF avail?(rt_I) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "rt'Seq not found ?!?" FI
      IN
      (R6, error(dg2 <+ dg3 <+ dg3a <+ dg4 <+ dg5 <+ dg6))
    FI
  ELSE
      LET dg1 == (error, freeRef("findAuxFuns'Testing")) !!
                  "Triple not found ?!?" 
          dg2 == IF avail?(1stI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "1st'Triple not found ?!?" FI
          dg3 == IF avail?(2ndI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "2nd'Triple not found ?!?" FI
          dg4 == IF avail?(3rdI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "3rd'Triple not found ?!?" FI
      IN
      (R3, error(dg1 <+ dg2 <+ dg3 <+ dg4))
  FI
   
-- %4 arguments
FUN findAuxFuns: repo ** objectName ** objectName **
                  objectName ** objectName -> repo ** auxFuns
DEF findAuxFuns(R, data1, data2, data3, data4) ==
  LET params == %(data1, data2, data3, data4)
      F == \\rr, nn. findON(rr, "Quadruple", params, nn)                  
      (R1, quadI) == F(R, "quad")
      (R2, 1stI) == F(R1, "1st")
      (R3, 2ndI) == F(R2, "2nd")
      (R3a, 3rdI) == F(R3, "3rd")
      (R3b, 4thI) == F(R3a, "4th")
  IN
  IF avail?(quadI) THEN
    LET (R4, ftI) == findON(R3b, "Seq", %(cont(quadI)), "ft")
        (R5, <>?_I) == findON(R4, "Seq", %(cont(quadI)), "<>?")
        (R6, rt_I) == findON(R5, "Seq", %(cont(quadI)), "rt")
    IN
    IF (avail?(1stI) and avail?(2ndI) and avail?(3rdI) and avail?(4thI)) and
         (avail?(ftI) and avail?(<>?_I) and avail?(rt_I)) THEN
      (R6, okay4(cont(quadI), cont(1stI), cont(2ndI), cont(3rdI), cont(4thI),
                cont(ftI), cont(rt_I), cont(<>?_I)))
    ELSE
      LET dg2 == IF avail?(1stI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "1st'Quadruple not found ?!?" FI
          dg3 == IF avail?(2ndI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "2nd'Quadruple not found ?!?" FI
          dg3a == IF avail?(3rdI) THEN ok
                  ELSE (error, freeRef("findAuxFuns'Testing")) !!
                    "   3rd'Quadruple not found ?!?" FI
          dg3b == IF avail?(4thI) THEN ok
                  ELSE (error, freeRef("findAuxFuns'Testing")) !!
                    "   4th'Quadruple not found ?!?" FI
          dg4 == IF avail?(ftI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "ft'Seq not found ?!?" FI
          dg5 == IF avail?(<>?_I) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "<>?'Seq not found ?!?" FI
          dg6 == IF avail?(rt_I) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "rt'Seq not found ?!?" FI
      IN
      (R6, error(dg2 <+ dg3 <+ dg3a <+ dg3b <+ dg4 <+ dg5 <+ dg6))
    FI
  ELSE
      LET dg1 == (error, freeRef("findAuxFuns'Testing")) !!
                  "Triple not found ?!?" 
          dg2 == IF avail?(1stI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "1st'Quadruple not found ?!?" FI
          dg3 == IF avail?(2ndI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "2nd'Quadruple not found ?!?" FI
          dg4 == IF avail?(3rdI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "3rd'Quadruple not found ?!?" FI
          dg5 == IF avail?(4thI) THEN ok
                 ELSE (error, freeRef("findAuxFuns'Testing")) !!
                       "4th'Quadruple not found ?!?" FI
      IN
      (R3, error(dg1 <+ dg2 <+ dg3 <+ dg4 <+ dg5))
  FI
   
FUN findON: repo ** denotation ** seq[objectName] ** denotation ->
             repo ** option[objectName]
DEF findON(R, unit, instance, name) ==
  LET u == lookup?(unit, sign)(R)
  IN
  IF u avail? THEN
    LET n == lookup(cont(u), name)(R)
    IN
    IF #(n) = 1 THEN
      LET (u2, R1) == enterInstance(cont(u), instance)(R)
      IN
      (R1, avail(globalObjectName(no(arb(n)), u2)))
    ELSE
      (R, nil)
    FI
  ELSE
    (R, nil)
  FI

FUN noTestData: repo ** unitName ** ref -> expr'RepoAbsy -> diag
DEF noTestData(R, main, re)(e) ==
  (error, re) !! : mode**ref**denotation->diag
  pretty((lit("no test data for test case "); brk; prettyExpr(R, main)(e)))

FUN findCheckTestFun: nat -> repo ** seq[objectName] ->
                       repo ** option[objectName]
DEF findCheckTestFun(argNo)(R, dataSeq) ==
    findON(R, "CheckTestCases" ++ `(argNo), dataSeq, "checkTestCases")

FUN resultT: repo -> fct'RepoAbsy
DEF resultT(R) == name(arb(lookup(proofscript(R), "resultT")(R)))
