/**
  * Returns a string of the modules in the compile stack, beginning with the the specified module
  * and ending with the module at the top of the stack. The modules have arrows between them to
  * indicate dependencies. This method is used when reporting a circular module dependency error.
  */
 public String printStackPath(ModuleID id) {
   StringBuffer sb = new StringBuffer();
   Stack<ModuleID> stack2 = new Stack<ModuleID>();
   boolean printID = false;
   ModuleID id2 = null;
   while (!stack.isEmpty()) {
     id2 = stack.pop();
     stack2.push(id2);
   }
   sb.append("(");
   while (!stack2.isEmpty()) {
     id2 = stack2.pop();
     if (id2 == id) {
       printID = true;
     }
     if (printID) {
       sb.append(id2.toString());
       if (!stack2.isEmpty()) {
         sb.append(" -> ");
       }
     }
     stack.push(id2);
   }
   sb.append(")");
   return sb.toString();
 }
 /** Returns a string representation of the compilation environment. */
 public String toString() {
   StringBuffer sb = new StringBuffer();
   sb.append("==============================" + "==============================\n");
   sb.append("Compilation environment for " + targetFile.getName() + "\n");
   sb.append("==============================" + "==============================\n");
   sb.append("Main directory: " + mainDir.getName() + "\n");
   sb.append("------------------------------" + "------------------------------\n");
   sb.append("Unparsable files: " + getResolveNames(unparsables) + "\n");
   sb.append("Compile stack: " + stack.toString() + "\n");
   Iterator<ModuleID> i = map.keyIterator();
   while (i.hasNext()) {
     ModuleID id = i.next();
     ModuleRecord record = map.get(id);
     // sb.append(getResolveName(record.getFile()) + " ");
     sb.append(id.toString());
     if (record.isComplete()) {
       sb.append(" is complete");
     } else {
       sb.append(" is incomplete");
     }
     if (record.containsErrors()) {
       sb.append(" due to errors");
     }
     sb.append(".\n");
     sb.append("    Theories: " + record.getTheories().toString());
     sb.append("\n");
   }
   sb.append("------------------------------" + "------------------------------\n");
   return sb.toString();
 }
  /**
   * Places the symbol table for an associated module into the environment and pops the module from
   * the compilation stack, indicating that compilation has been completed for this module.
   */
  public void completeRecord(ModuleID id, OldSymbolTable table) {
    ModuleRecord record = map.get(id);
    record.setSymbolTable(table);
    ModuleID id2 = stack.pop();
    assert id == id2 : "id != id2";

    if (!debugOff) {
      err.message("Complete record: " + id.toString()); // DEBUG
    }
  }
  /**
   * Constructs a record containing the module id, the file, and the module dec, and places it in
   * the module environment. Also places the module into a stack that indicates compilation has
   * begun on this module but has not completed.
   */
  public void constructRecord(ModuleID id, File file, ModuleDec dec) {
    ModuleRecord record = new ModuleRecord(id, file);
    record.setModuleDec(dec);
    assert !map.containsKey(id) : "map already contains key";
    assert !fmap.containsKey(file) : "fmap already contains file";
    map.put(id, record);
    fmap.put(file, id);
    stack.push(id);

    if (!debugOff) {
      err.message("Construct record: " + id.toString()); // DEBUG
    }
  }
 /**
  * Aborts compilation of a module which parsed without errors, and pops this module from the
  * compilation stack.
  */
 public void abortCompile(ModuleID id) {
   map.get(id).setErrorFlag();
   ModuleID id2 = stack.pop();
   assert id == id2 : "id != id2";
   err.message("Abort compile: " + id.toString()); // DEBUG
 }