/**
   * type check a test
   *
   * @param classdef
   * @param interpreter
   * @param test
   * @throws AnalysisException
   * @throws Exception
   */
  protected void typeCheck(
      INode classdef, Interpreter interpreter, CallSequence test, Environment outer)
      throws AnalysisException, Exception {
    FlatEnvironment env = null;

    if (classdef instanceof SClassDefinition) {

      env =
          new FlatEnvironment(
              interpreter.getAssistantFactory(),
              classdef.apply(interpreter.getAssistantFactory().getSelfDefinitionFinder()),
              outer);
    } else {

      env =
          new FlatEnvironment(interpreter.getAssistantFactory(), new Vector<PDefinition>(), outer);
    }

    for (int i = 0; i < test.size(); i++) {
      PStm statement = test.get(i);

      if (statement instanceof TraceVariableStatement) {
        ((TraceVariableStatement) statement).typeCheck(env, NameScope.NAMESANDSTATE);
      } else {
        statement = statement.clone();
        test.set(i, statement);
        interpreter.typeCheck(statement, env);
      }
    }
  }
  private void evaluateTests(
      String className, TraceXmlWrapper storage, Object traceDefinition, Context ctxt)
      throws Exception {
    ANamedTraceDefinition mtd = (ANamedTraceDefinition) traceDefinition;
    TestSequence tests = null;
    if (!reduce) {
      subset = 1.0F;
      traceReductionType = TraceReductionType.NONE;
      seed = 999;
    }

    tests =
        ctxt.assistantFactory
            .createANamedTraceDefinitionAssistant()
            .getTests(mtd, ctxt, subset, traceReductionType, seed);

    int size = tests.size();

    infoProcessingTrace(className, mtd.getName().getName(), size);
    if (storage != null) {
      storage.StartTrace(
          mtd.getName().getName(),
          mtd.getLocation().getFile().getName(),
          mtd.getLocation().getStartLine(),
          mtd.getLocation().getStartPos(),
          size,
          new Float(subset),
          TraceReductionType.valueOf(traceReductionType.toString()),
          new Long(seed));
    }

    INode traceContainer = null;
    Environment rootEnv = null;
    if (interpreter instanceof ClassInterpreter) {
      traceContainer = mtd.getClassDefinition();
      rootEnv =
          new PrivateClassEnvironment(
              interpreter.getAssistantFactory(),
              mtd.getClassDefinition(),
              interpreter.getGlobalEnvironment());
      ;
    } else {
      traceContainer = mtd.parent();
      if (((AModuleModules) traceContainer).getIsFlat()) {
        // search for the combined module
        for (AModuleModules m : ((ModuleInterpreter) interpreter).modules) {
          if (m instanceof CombinedDefaultModule) {
            traceContainer = m;
            break;
          }
        }
      }
      rootEnv =
          new ModuleEnvironment(interpreter.getAssistantFactory(), (AModuleModules) traceContainer);
    }

    int n = 1;

    int faildCount = 0;
    int inconclusiveCount = 0;
    int skippedCount = 0;

    StopWatch.set();

    for (CallSequence test : tests) {
      StopWatch.stop("Getting test");

      infoProcessingTest(className, mtd.getName().getName(), n, size);

      List<Object> result = null;
      Verdict verdict = null;

      // type check
      boolean typeOk = false;
      try {
        if (interpreter instanceof ClassInterpreter) {
          typeCheck(traceContainer, interpreter, test, rootEnv);
        } else {
          typeCheck(traceContainer, interpreter, test, rootEnv);
        }
        typeOk = true;
      } catch (Exception e) {
        result = new Vector<Object>();
        result.add(e);
        verdict = Verdict.FAILED;
        result.add(verdict);
      }

      // interpret
      if (typeOk) {
        StopWatch.set();
        result = evaluateCallSequence(mtd, test);
        StopWatch.stop("Executing   ");
        StopWatch.set();

        verdict = (Verdict) result.get(result.size() - 1);

        if (verdict == Verdict.ERROR) {
        } else {
          tests.filter(result, test, n);
        }
      }

      switch (verdict) {
        case FAILED:
          faildCount++;
          break;
        case INCONCLUSIVE:
          inconclusiveCount++;
          break;
        default:
          break;
      }

      if (storage != null) {
        /*
         * Bodge until we figure out how to not have explicit op names.
         */
        String clean = test.toString().replaceAll("\\.\\w+`", ".");
        storage.StartTest(new Integer(n).toString(), clean);
        storage.StopElement();
      }

      if (test.getFilter() > 0) {
        skippedCount++;
        infoTestFiltered(n, test.getFilter(), test);
        if (storage != null) {
          storage.AddSkippedResult(new Integer(n).toString());
        }
      } else {

        if (verdict == Verdict.ERROR) {
          if (storage != null) {
            storage.AddResults(new Integer(n).toString(), result);
            storage.AddTraceStatus(
                Verdict.valueOf(Verdict.FAILED.toString()),
                size,
                skippedCount,
                faildCount,
                inconclusiveCount);
            storage.StopElement();
          }

          Exception e = (Exception) result.get(result.size() - 2);
          result.remove(result.size() - 2);

          throw e;
        }

        if (storage != null) {
          storage.AddResults(new Integer(n).toString(), result);
        }
      }

      n++;
      StopWatch.stop("store&filter");
      StopWatch.set();
    }

    if (storage != null) {
      Verdict worstVerdict = Verdict.PASSED;
      if (faildCount > 0) {
        worstVerdict = Verdict.FAILED;
      } else if (inconclusiveCount > 0) {
        worstVerdict = Verdict.INCONCLUSIVE;
      }

      storage.AddTraceStatus(
          Verdict.valueOf(worstVerdict.toString()),
          size,
          skippedCount,
          faildCount,
          inconclusiveCount);
      storage.StopElement();
    }

    infoProcessingTraceFinished(
        className, mtd.getName().getName(), size, faildCount, inconclusiveCount, skippedCount);
  }