private void inicializaVariaveisGlobaisNaoPassadasPorReferencia(
        List<NoDeclaracaoInicializavel> variaveisGlobais) throws ExcecaoVisitaASA {
      for (NoDeclaracaoInicializavel variavel : variaveisGlobais) {
        if (variavel instanceof NoDeclaracaoVariavel) {
          if (((NoDeclaracaoVariavel) variavel).ehPassadaPorReferencia()) {
            continue; // variáveis globais que são passadas como referência não são declaradas como
            // atributo no código Java
          }
        }

        boolean ehVetor = variavel instanceof NoDeclaracaoVetor;
        boolean ehMatriz = variavel instanceof NoDeclaracaoMatriz;
        boolean variavelInicializada = variavel.temInicializacao();

        if (ehVetor || ehMatriz || variavelInicializada) {
          saida.append(Utils.geraIdentacao(nivelEscopo + 1));
          saida.format("%s = ", variavel.getNome());
          if (variavelInicializada) {
            variavel.getInicializacao().aceitar(this);
          } else // vetores e matrizes não inicializados precisam ser instanciados
          {
            if (ehVetor) {
              NoExpressao tamanho = ((NoDeclaracaoVetor) variavel).getTamanho();
              if (tamanho != null) {
                String nomeTipo = Utils.getNomeTipoJava(variavel.getTipoDado());
                saida.format("new %s[", nomeTipo);
                tamanho.aceitar(this);
                saida.append("]");
              }
            } else // é uma matriz
            {
              NoExpressao linhas = ((NoDeclaracaoMatriz) variavel).getNumeroLinhas();
              NoExpressao colunas = ((NoDeclaracaoMatriz) variavel).getNumeroColunas();
              if (linhas != null && colunas != null) {
                String nomeTipo = Utils.getNomeTipoJava(variavel.getTipoDado());
                saida.format("new %s[", nomeTipo);
                linhas.aceitar(this);
                saida.append("][");
                colunas.aceitar(this);
                saida.append("]");
              }
            }
          }
          saida.append(";").println();
        }
      }
    }
    public VisitorGeracaoCodigo geraAtributosParaAsVariaveisPassadasPorReferencia(
        Map<TipoDado, List<NoDeclaracaoVariavel>> variaveis) {
      if (variaveis.isEmpty()) {
        return this;
      }

      String identacao = Utils.geraIdentacao(nivelEscopo);

      // declara os arrays (separados por tipo) que armazenam todas as referências
      // gera os arrays nessa sequência de tipos
      TipoDado tipos[] = {
        TipoDado.INTEIRO, TipoDado.REAL, TipoDado.LOGICO, TipoDado.CARACTER, TipoDado.CADEIA
      };

      for (TipoDado tipo : tipos) {
        if (variaveis.containsKey(tipo)) {
          String nomeTipo = Utils.getNomeTipoJava(tipo);
          int numeroVariaveis = variaveis.get(tipo).size();
          saida
              .append(identacao)
              .format(
                  "private final %s[] REFS_%s = new %s[%d];",
                  nomeTipo, nomeTipo.toUpperCase(), nomeTipo, numeroVariaveis)
              .println();
        }
      }

      saida.println(); // pula uma linha antes de declarar as variáveis de cada tipo

      for (TipoDado tipo : tipos) {
        if (variaveis.containsKey(tipo)) {
          for (NoDeclaracaoVariavel variavel : variaveis.get(tipo)) {
            saida
                .append(identacao)
                .append("private final int ")
                .append(Utils.geraStringIndice(variavel))
                .append(" = ")
                .append(String.valueOf(variavel.getIndiceReferencia()))
                .append(";")
                .println();
          }

          saida.println(); // separa as declarações para cada tipo
        }
      }

      return this;
    }
 private void inicializaVariaveisGlobaisQueSaoPassadasPorReferencia() throws ExcecaoVisitaASA {
   List<NoDeclaracao> declaracoes = asa.getListaDeclaracoesGlobais();
   for (NoDeclaracao declaracao : declaracoes) {
     if (declaracao instanceof NoDeclaracaoVariavel) {
       NoDeclaracaoVariavel variavel = (NoDeclaracaoVariavel) declaracao;
       if (variavel.ehPassadaPorReferencia() && variavel.temInicializacao()) {
         String nomeTipo = Utils.getNomeTipoJava(variavel.getTipoDado());
         saida.append(Utils.geraIdentacao(nivelEscopo));
         saida.format(
             "REFS_%s[%s] = ", nomeTipo.toUpperCase(), Utils.geraStringIndice(variavel));
         variavel.getInicializacao().aceitar(this);
         saida.append(";").println(); // o ponto e vírgula depois da inicialização
       }
     }
   }
 }
    @Override
    public Void visitar(NoReferenciaVariavel no) throws ExcecaoVisitaASA {
      String nome = no.getNome();
      if (no.getEscopo() != null) {
        saida.append(no.getEscopo()).append(".");
      }

      NoDeclaracao declaracao = no.getOrigemDaReferencia();
      boolean ehParametroPorReferencia =
          declaracao instanceof NoDeclaracaoParametro
              && (((NoDeclaracaoParametro) declaracao).getModoAcesso()
                  == ModoAcesso.POR_REFERENCIA);
      if (ehParametroPorReferencia || no.ehPassadoPorReferencia()) {
        String stringIndice = ehParametroPorReferencia ? no.getNome() : Utils.geraStringIndice(no);
        String nomeTipo = Utils.getNomeTipoJava(declaracao.getTipoDado()).toUpperCase();
        saida.format("REFS_%s[%s]", nomeTipo, stringIndice);
      } else {
        saida.append(nome);
      }

      return null;
    }