@Override
  public void exitOperationProcedureDecl(ResolveParser.OperationProcedureDeclContext ctx) {
    Scope s = symtab.getScope(ctx);
    VCAssertiveBlockBuilder block = assertiveBlocks.pop();
    List<ProgParameterSymbol> paramSyms = s.getSymbolsOfType(ProgParameterSymbol.class);

    PExp corrFnExpEnsures =
        perParameterCorrFnExpSubstitute(
            paramSyms,
            tr.getMathExpASTFor(
                g, ctx.ensuresClause())); // postcondition[params 1..i <-- corr_fn_exp]
    corrFnExpEnsures =
        corrFnExpEnsures.withVCInfo(ctx.getStart(), "Ensures clause of " + ctx.name.getText());
    Token loc = ctx.ensuresClause() != null ? ctx.ensuresClause().getStart() : ctx.getStart();

    List<PExp> paramConsequents = new ArrayList<>();
    Utils.apply(paramSyms, paramConsequents, this::extractConsequentsFromParameter);

    // add verification statements to the assertive context/block
    block.stats(Utils.collect(VCRuleBackedStat.class, ctx.stmt(), stats));

    // add any additional confirms from the parameters, etc
    for (ProgParameterSymbol p : paramSyms) {
      confirmParameterConsequentsForBlock(block, p); // modfies 'block' with additional confims!
    }
    // TODO: Tomorrow look at the verification statements in the assertive context for
    // int_do_nothing, then
    block.finalConfirm(corrFnExpEnsures);
    outputFile.addAssertiveBlock(block.build());
  }
  @Override
  public void exitTypeRepresentationDecl(ResolveParser.TypeRepresentationDeclContext ctx) {
    PExp constraint = g.getTrueExp();
    PExp correspondence = g.getTrueExp();
    if (currentTypeReprSym == null) return;
    correspondence = currentTypeReprSym.getCorrespondence();

    if (currentTypeReprSym.getDefinition() != null) {
      constraint = currentTypeReprSym.getDefinition().getProgramType().getConstraint();
    }
    VCAssertiveBlockBuilder block = assertiveBlocks.pop();
    PExp newConstraint =
        constraint.substitute(
            currentTypeReprSym.exemplarAsPSymbol(),
            currentTypeReprSym.conceptualExemplarAsPSymbol());
    newConstraint =
        newConstraint.withVCInfo(ctx.getStart(), "Constraint for type: " + ctx.name.getText());
    block.assume(correspondence.splitIntoConjuncts());
    // throw new UnsupportedOperationException("re-institute the final confirm for this dan");
    block.finalConfirm(newConstraint);
    outputFile.addAssertiveBlock(block.build());
  }
  @Override
  public void exitProcedureDecl(ResolveParser.ProcedureDeclContext ctx) {
    Scope scope = symtab.getScope(ctx);
    List<ProgParameterSymbol> paramSyms = scope.getSymbolsOfType(ProgParameterSymbol.class);
    VCAssertiveBlockBuilder block = assertiveBlocks.pop();
    List<ProgParameterSymbol> formalParameters = new ArrayList<>();
    try {
      formalParameters =
          scope.query(new SymbolTypeQuery<ProgParameterSymbol>(ProgParameterSymbol.class));
    } catch (NoSuchModuleException | UnexpectedSymbolException e) {
      e.printStackTrace();
    }

    List<PExp> corrFnExps =
        paramSyms
            .stream()
            .filter(p -> p.getDeclaredType() instanceof PTRepresentation)
            .map(p -> (PTRepresentation) p.getDeclaredType())
            .map(p -> p.getReprTypeSymbol().getCorrespondence())
            .collect(Collectors.toList());
    PExp corrFnExpEnsures =
        perParameterCorrFnExpSubstitute(paramSyms, currentProcOpSym.getEnsures())
            .withVCInfo(ctx.getStart(), "Ensures clause of " + ctx.name.getText());
    // postcondition[params 1..i <-- corr_fn_exp]

    List<PExp> paramConsequents = new ArrayList<>();
    Utils.apply(formalParameters, paramConsequents, this::extractConsequentsFromParameter);

    block
        .stats(Utils.collect(VCRuleBackedStat.class, ctx.stmt(), stats))
        .assume(corrFnExps)
        .confirm(ctx, g.formConjuncts(paramConsequents))
        .finalConfirm(corrFnExpEnsures);

    outputFile.addAssertiveBlock(block.build());
    currentProcOpSym = null;
  }
  @Override
  public void actionPerformed(AnActionEvent e) {
    Project project = e.getData(PlatformDataKeys.PROJECT);
    if (project == null) {
      LOGGER.error("actionPerformed (genVCs): no project for " + e);
      return;
    }
    VirtualFile resolveFile = getRESOLVEFileFromEvent(e);
    LOGGER.info("prove actionPerformed " + (resolveFile == null ? "NONE" : resolveFile));
    if (resolveFile == null) return;
    String title = "RESOLVE Prove";
    boolean canBeCancelled = true;

    commitDoc(project, resolveFile);
    Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
    if (editor == null) return;

    RunRESOLVEOnLanguageFile gen = new RunRESOLVEOnLanguageFile(resolveFile, project, title);

    MyProverListener pl = new MyProverListener();
    VCOutputFile vco = generateVCs(resolveFile, editor, project);
    // give each action an instance of the prover listener and make Update() print the result as it
    // comes back produce
    if (vco == null) return;

    RESOLVEPluginController controller = RESOLVEPluginController.getInstance(project);
    VerifierPanel verifierPanel = controller.getVerifierPanel();
    verifierPanel.createVerifierView2(
        vco.getFinalVCs(), pl); // TODO: maybe make this take in a list of VCs

    addVCGutterIcons(vco, editor, project, pl);
    controller.getVerifierWindow().show(null);

    // runProver
    List<String> args = new ArrayList<>();
    args.add(resolveFile.getPath());
    args.add("-lib");
    args.add(RunRESOLVEOnLanguageFile.getContentRoot(project, resolveFile).getPath());
    args.add("-prove");
    RESOLVECompiler compiler = new RESOLVECompiler(args.toArray(new String[args.size()]));
    compiler.addProverListener(pl);

    // TODO: Instead of this being anon, make a separate static class and add an error listener to
    // 'compiler' that (make it accessible
    // right here though so the UI part below can stop and update remaining (unproved) vcs if the
    // compiler does indeed suffer some
    // catastrophic failure: npe, etc.
    Task.Backgroundable proverTask =
        new Task.Backgroundable(project, "Proving") {
          @Override
          public void run(@NotNull final ProgressIndicator progressIndicator) {
            compiler.processCommandLineTargets();
          }
        };
    ProgressManager.getInstance().run(proverTask);

    // TODO: Different status icons for different proof results.
    running = true;
    Task.Backgroundable task =
        new Task.Backgroundable(project, "Updating Presentation") {

          @Override
          public void run(@NotNull final ProgressIndicator progressIndicator) {
            Map<String, Boolean> processed = new HashMap<>();
            for (VC vc : vco.getFinalVCs()) {
              processed.put(vc.getName(), false);
            }
            while (pl.vcIsProved.size() != vco.getFinalVCs().size()) {
              // if (proverTask.getNotificationInfo().)//TODO: Put something here that breaks out of
              // this if the compiler crashes..
              for (VC vc : vco.getFinalVCs()) {
                if (pl.vcIsProved.containsKey(vc.getName()) && !processed.get(vc.getName())) {
                  processed.put(vc.getName(), true);
                  long dur = pl.vcMetrics.get(vc.getName()).getProofDuration();
                  ConditionCollapsiblePanel section =
                      verifierPanel.vcSelectorPanel.vcTabs.get(vc.getNumber());
                  section.changeToFinalState(
                      pl.vcIsProved.get(vc.getName())
                          ? ConditionCollapsiblePanel.State.PROVED
                          : ConditionCollapsiblePanel.State.NOT_PROVED,
                      dur);
                }
              }
            }
            running = false;
          }
        };
    ProgressManager.getInstance().run(task);
  }
  private void addVCGutterIcons(
      VCOutputFile vco, Editor editor, Project project, MyProverListener listener) {
    if (!editor.isDisposed()) {
      highlighters.clear();
      MarkupModel markup = editor.getMarkupModel();
      RESOLVEPluginController controller = RESOLVEPluginController.getInstance(project);
      markup.removeAllHighlighters();

      // A mapping from [line number] -> [vc_1, .., vc_j]
      Map<Integer, List<VC>> byLine = vco.getVCsGroupedByLineNumber();
      List<RangeHighlighter> vcRelatedHighlighters = new ArrayList<>();

      for (Map.Entry<Integer, List<VC>> vcsByLine : byLine.entrySet()) {
        List<AnAction> actionsPerVC = new ArrayList<>();
        // create clickable actions for each vc
        for (VC vc : vcsByLine.getValue()) {
          actionsPerVC.add(
              new VCNavigationAction(listener, vc.getNumber() + "", vc.getExplanation()));
        }

        highlighter =
            markup.addLineHighlighter(
                vcsByLine.getKey() - 1, HighlighterLayer.ELEMENT_UNDER_CARET, null);
        highlighter.setGutterIconRenderer(
            new GutterIconRenderer() {
              @NotNull
              @Override
              public Icon getIcon() {
                return RESOLVEIcons.VC;
              }

              @Override
              public boolean equals(Object obj) {
                return false;
              }

              @Override
              public int hashCode() {
                return 0;
              }

              @Override
              public boolean isNavigateAction() {
                return true;
              }

              @Nullable
              public ActionGroup getPopupMenuActions() {
                DefaultActionGroup g = new DefaultActionGroup();
                g.addAll(actionsPerVC);
                return g;
              }

              @Nullable
              public AnAction getClickAction() {
                return null;
              }
            });
        vcRelatedHighlighters.add(highlighter);
        highlighters.add(highlighter);
      }

      editor
          .getDocument()
          .addDocumentListener(
              new DocumentListener() {
                @Override
                public void beforeDocumentChange(DocumentEvent event) {}

                @Override
                public void documentChanged(DocumentEvent event) {
                  // remove all highlighters
                  for (RangeHighlighter h : vcRelatedHighlighters) {
                    markup.removeHighlighter(h);
                  }
                  VerifierPanel verifierPanel = controller.getVerifierPanel();
                  controller.getVerifierWindow().hide(null);
                  verifierPanel.revertToBaseGUI();
                }
              });
    }
  }