@Override
 public void enterFacilityDecl(ResolveParser.FacilityDeclContext ctx) {
   VCAssertiveBlockBuilder block =
       new VCAssertiveBlockBuilder(g, moduleScope, "Facility_Inst=" + ctx.name.getText(), ctx);
   block.assume(g.getTrueExp());
   assertiveBlocks.push(block);
 }
  private List<PExp> extractConsequentsFromParameter(ProgParameterSymbol p) {
    List<PExp> result = new ArrayList<>();
    PExp incParamExp = new PSymbolBuilder(p.asPSymbol()).incoming(true).build();
    PExp paramExp = new PSymbolBuilder(p.asPSymbol()).incoming(false).build();

    if (p.getDeclaredType() instanceof ProgNamedType) {
      ProgNamedType t = (ProgNamedType) p.getDeclaredType();
      PExp exemplar = new PSymbolBuilder(t.getExemplarName()).mathClssfctn(t.toMath()).build();

      if (t instanceof PTRepresentation) {
        ProgReprTypeSymbol repr = ((PTRepresentation) t).getReprTypeSymbol();

        PExp convention = repr.getConvention();
        PExp corrFnExp = repr.getCorrespondence();
        result.add(convention.substitute(t.getExemplarAsPSymbol(), paramExp));
      }
      if (p.getMode() == ParameterMode.PRESERVES || p.getMode() == ParameterMode.RESTORES) {
        PExp equalsExp =
            g.formEquals(paramExp, incParamExp)
                .withVCInfo(
                    p.getDefiningTree().getStart(),
                    "Ensure parameter " + p.getName() + " is restored");
        result.add(equalsExp);
      } else if (p.getMode() == ParameterMode.CLEARS) {
        PExp init =
            ((ProgNamedType) p.getDeclaredType())
                .getInitializationEnsures()
                .substitute(exemplar, paramExp);
        result.add(init);
      }
    }
    return result;
  }
  @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 enterTypeImplInit(ResolveParser.TypeImplInitContext ctx) {
    Scope s = symtab.getScope(ctx.getParent());
    PExp convention = currentTypeReprSym.getConvention();
    PExp correspondence = currentTypeReprSym.getCorrespondence();
    PExp typeInitEnsures = g.getTrueExp();
    List<ModuleParameterSymbol> moduleParamSyms = getAllModuleParameterSyms();

    VCAssertiveBlockBuilder block =
        new VCAssertiveBlockBuilder(g, s, "T_Init_Hypo=" + currentTypeReprSym.getName(), ctx)
            .assume(getModuleLevelAssertionsOfType(ClauseType.REQUIRES))
            .assume(
                getAssertionsFromModuleFormalParameters(
                    moduleParamSyms, this::extractAssumptionsFromParameter));

    assertiveBlocks.push(block);
  }
 // The only way I'm current aware of a local requires clause getting changed
 // is by passing a locally defined type  to an operation (something of type
 // PTRepresentation). This method won't do anything otherwise.
 @NotNull
 private PExp perParameterCorrFnExpSubstitute(
     @NotNull List<ProgParameterSymbol> params, @Nullable PExp requiresOrEnsures) {
   List<PExp> result = new ArrayList<>();
   PExp resultingClause = requiresOrEnsures;
   for (ProgParameterSymbol p : params) {
     if (p.getDeclaredType() instanceof PTRepresentation) {
       ProgReprTypeSymbol repr = ((PTRepresentation) p.getDeclaredType()).getReprTypeSymbol();
       PExp corrFnExp = repr.getCorrespondence();
       // distribute conc.X into the clause passed
       Map<PExp, PExp> concReplMapping = new HashMap<>();
       concReplMapping.put(repr.exemplarAsPSymbol(), repr.conceptualExemplarAsPSymbol());
       concReplMapping.put(repr.exemplarAsPSymbol(true), repr.conceptualExemplarAsPSymbol(true));
       resultingClause = resultingClause.substitute(concReplMapping);
     }
   }
   return resultingClause == null ? g.getTrueExp() : resultingClause;
 }
 @Override
 public void exitTypeImplInit(ResolveParser.TypeImplInitContext ctx) {
   PExp typeInitEnsures = g.getTrueExp();
   PExp convention = currentTypeReprSym.getConvention();
   PExp correspondence = currentTypeReprSym.getCorrespondence();
   if (currentTypeReprSym.getDefinition() != null) {
     typeInitEnsures =
         currentTypeReprSym.getDefinition().getProgramType().getInitializationEnsures();
   }
   VCAssertiveBlockBuilder block = assertiveBlocks.pop();
   PExp newInitEnsures =
       typeInitEnsures.substitute(
           currentTypeReprSym.exemplarAsPSymbol(),
           currentTypeReprSym.conceptualExemplarAsPSymbol());
   // block.stats(Utils.collect(VCRuleBackedStat.class, ctx.stmt(), stats));
   // block.confirm(convention);  //order here is important
   block.assume(correspondence);
   throw new UnsupportedOperationException("re-institute the final confirm for this dan");
   // block.finalConfirm(newInitEnsures, "Initialization-ensures clause of " +
   // currentTypeReprSym.getName());
   // outputFile.addAssertiveBlock(block.build());
 }
  private void confirmParameterConsequentsForBlock(
      VCAssertiveBlockBuilder block, ProgParameterSymbol p) {
    PExp incParamExp = new PSymbolBuilder(p.asPSymbol()).incoming(true).build();
    PExp paramExp = new PSymbolBuilder(p.asPSymbol()).incoming(false).build();

    if (p.getDeclaredType() instanceof ProgNamedType) {
      ProgNamedType t = (ProgNamedType) p.getDeclaredType();
      PExp exemplar = new PSymbolBuilder(t.getExemplarName()).mathClssfctn(t.toMath()).build();

      if (t instanceof PTRepresentation) {
        ProgReprTypeSymbol repr = ((PTRepresentation) t).getReprTypeSymbol();

        PExp convention = repr.getConvention();
        PExp corrFnExp = repr.getCorrespondence();
        // if we're doing this its going to be on a procedure decl or op-proc decl, so just
        // say block.definingTree
        PExp newConvention =
            convention
                .substitute(t.getExemplarAsPSymbol(), paramExp)
                .withVCInfo(block.definingTree.getStart(), "Convention for " + t.getName());
        block.confirm(block.definingTree, newConvention);
      }
      if (p.getMode() == ParameterMode.PRESERVES || p.getMode() == ParameterMode.RESTORES) {
        PExp equalsExp =
            g.formEquals(paramExp, incParamExp)
                .withVCInfo(
                    block.definingTree.getStart(),
                    "Ensure parameter " + p.getName() + " is restored");
        block.confirm(block.definingTree, equalsExp);
      } else if (p.getMode() == ParameterMode.CLEARS) {
        PExp init =
            ((ProgNamedType) p.getDeclaredType())
                .getInitializationEnsures()
                .substitute(exemplar, paramExp);
        // result.add(init);
      }
    }
  }
  @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;
  }