Convertendo o código Fortran 77 em C #

14

Estou tentando converter um programa Fortan77 para c #. Eu tenho uma sub-rotina com cerca de 650 linhas de código e declarações GOTO horríveis em todo o lugar. Estou tendo muitos problemas até começando a visualizar o fluxo da sub-rotina para descobrir o que ela faz.

Existe alguém com experiência nesse tipo de coisa que poderia me dar algum conselho sobre como obter uma visão geral desta sub-rotina? Existem algumas ferramentas disponíveis para acelerar ou facilitar esse tipo de conversão?

user643192
fonte
1
Como esta pergunta é mais aberta e procura conselhos, seria mais apropriado em Programmers SE
4
você já pensou em compilá-lo no .NET usando silverfrost.com/11/ftn95/ftn95_fortran_95_for_windows.aspx e depois referenciar o assembly?
@ Shaun, é uma boa ideia, Shaun. Vou ver se não consigo chegar a lugar nenhum com a reprogramação.
user643192
2
Eu sinto pena de você ...
Marko
1
Eu estive no seu lugar. Foram os piores dias da minha carreira.
usuário

Respostas:

10

Na minha experiência, uma boa maneira de fazer isso é criar um fluxograma do código Fortran. Tente separar os destinos das instruções GOTO em blocos separados e use o diagrama para tentar entender o código em um nível alto.

Veja se você pode substituir logicamente os GOTOs por loops ou chamadas de função; se o diagrama resultante estiver na forma de uma estrutura em árvore, é relativamente fácil converter para C # sem recorrer a GOTOs. No final, porém, você precisará entender intimamente o código para poder manter e usar o resultado com confiança.

Daniel B
fonte
Boa sugestão, obrigado! As declarações GOTO devem ser banidas.
user643192
6
@ user643192, gotoé uma coisa extremamente útil se aplicada com sabedoria. Você não implementaria um autômato de estado grande e eficiente sem um goto. Você certamente precisará deles também no código gerado.
SK-logic
3
Existem ferramentas que podem desenhar fluxogramas do código Fortran. Exemplo: home.comcast.net/~lchen223621
NoChance
OP: Você não pode banir retroativamente. @EmmadKareem: sugestão muito útil.
Kris
Acabei fazendo o que Daniel B sugeriu aqui e fiz uma versão em bloco do código Fortran. Ajudou muito, então obrigado por isso. Para a SK-logic, você provavelmente está certo sobre os GOTOs. Meu comentário foi feito depois da minha primeira tarde olhando para o código ... e há muitos de GOTOs nele: o (
user643192
12

Além do que Daniel B escreveu acima, eu diria o seguinte:

Primeiro, faça com que seu código Fortran funcione com o Fortran for DotNet. Não se você "não conseguir chegar a lugar nenhum com a reprogramação", mas antes de tentar qualquer reprogramação. Será um pequeno passo, mas na direção certa.

Em seguida, escreva um conjunto de testes em C # que alimente o código Fortran com qualquer entrada que foi feita para mastigar e armazene a saída. Execute o conjunto de testes uma vez e salve a saída. Em seguida, estenda o conjunto de testes para testar a saída produzida em relação à saída salva. Supondo que o código Fortran sempre produz a mesma saída quando alimentado com a mesma entrada, é claro que o teste deve ter sucesso.

Então, enquanto você reescreve o código em C #, você estará executando seu código no conjunto de testes e ele informará se seu código está funcionando corretamente ou não, ou seja, se está produzindo exatamente a mesma saída que o Fortran código dado a mesma entrada. Sem ele, você estará perdido.

Não concordo com a @ SK-logic, você NÃO deve usar nenhum gotos no seu código C #.

(Mas, esperançosamente, depois de fazer o código Fortran funcionar no DotNet, você não verá motivos para continuar perdendo seu tempo convertendo um pedaço de código espaguete em C #.)

Mike Nakis
fonte
1
mente explicando, por que "você não deveria"? Algum argumento racional , além de "todo mundo acredita que é mau"? Eu citei dois casos extremamente importantes em que você precisa usar goto; caso contrário, você acabará escrevendo código ilegível ou ineficiente (ou ambos).
SK-logic
@ SK-logic Eu não escrevi "você NÃO DEVE", escrevi "você NÃO DEVE". De qualquer forma, aqui vai: as instruções goto dificultam a compreensão e a verificação do código em quase todas as circunstâncias, e seus supostos benefícios de eficiência são algo entre um mito e um equívoco. Claro que isso poderia ser mais esclarecido, mas, por favor, evitemos fazer isso, este não é o lugar para esta discussão. Vamos apenas concordar em discordar.
quer
2
uma ausência de gotostatemens também pode dificultar sua compreensão em alguns casos (e uma máquina de estado é o exemplo mais importante desse caso). Eu simplesmente não suporto essa religião estúpida e gótica - as pessoas continuam repetindo a mesma BS sem sentido, sem nunca tentar entender a razão pela qual goto é considerado prejudicial.
SK-logic
Você é uma daquelas pessoas que simplesmente não aguentam se não tiverem a última palavra, não é? C:: =
Mike Nakis
1
@ ridecar2, escrevo boas máquinas de estado o tempo todo. Uso enumerações e alterno instruções e deixo o compilador escrever os GOTOs na linguagem de máquina gerada. Na verdade, nunca vi um exemplo de máquina de estado escrita explicitamente com GOTOs. Gostaria de postar um ponteiro para um exemplo?
John R. Strohm
3

Sua tarefa é complicada. Você realmente precisa conhecer bem o Fortran. Você deve ter cuidado com o quão semelhante / diferente o Fortran faz os cálculos e quais regras de truncamento e arredondamento se aplicam. Além disso, você precisa ter cuidado com os tipos primitivos que significam em C # e Fortran.

Outra abordagem do que foi sugestão (não necessariamente melhor, é apenas outra):

A - Considere reescrever o código em C # com base no conhecimento e na função do negócio, use o código Fortran apenas como referência

B - Considere usar uma ferramenta comercial que faz o trabalho de conversão - Exemplo: DataTek

Se a rotina representar uma função padrão ou uma função para a qual você pode comprar uma DLL pronta (como integração numérica), use a função padrão ou o produto comercial em vez da tradução manual, e seu problema foi resolvido.

Se o exposto acima não resolver, responda a esta pergunta:

Preciso otimizar o código ou apenas fazê-lo funcionar. Em outras palavras, qual é o valor comercial de gastar 500 horas para melhorar o código?

se não houver valor na otimização, traduza o código linha por linha e pronto.

Se isso ainda não estiver bom, então:

0-Converta o código do Fortran linha por linha em C # (ou use Fortan CLR)

1-Faça um teste rápido e verifique se ele é executado

2-Use uma re-fatoração (ferramentas comerciais estão disponíveis) para ajudá-lo a escrever o código de uma maneira mais otimizada.

Boa sorte.

NoChance
fonte
2

Uma maneira simples de recodificar coisas com muitos gotos é desenhar um fluxograma e esticar a corda. Às vezes, os programas F77 são apenas programas F66 antigos ou programas FII ainda piores. F66 não tinha uma construção if-then-else, então gotos eram necessários. Tudo o que você precisa fazer é inverter a condição para obter um if-then.

F66 também não teve um tempo de folga, mas F77 possui. Depende se o codificador foi convertido de F66 para F77 (como muitos hoje são C para C ++ ou C ++ para C #) onde eles estão usando F77 como F66. Se você pode identificar os padrões, na codificação, é muito mais fácil converter.

copo
fonte
1

Antes de começar, faça um conjunto de testes para testar o código existente. Seja muito cuidadoso, pois isso ajudará a esclarecer o comportamento. Você pode usar esse conjunto para avaliar a eficácia de sua conversão.

Além disso, seja metódico , não se apresse e use muito papel para rastrear a funcionalidade.

Bryan Oakley
fonte
1

Aqui está a maneira como eu realmente traduzi o código em C #. Como o .NET suporta instruções goto, primeiro peguei o código Fortran inteiro e colei-o como está em um novo método, assim como tantos métodos quanto as rotinas e sub-rotinas Fortran.

O compilador apresentou um milhão de erros, principalmente sobre variáveis ​​não declaradas e formatação incorreta de instruções de bloco, que eu resolvi uma a uma. Também tive que reescrever parte do código específico do Fortran, como instruções de E / S e coisas assim. Quando isso foi feito, eu tinha uma réplica exata do código original.

Graças à boa formatação do Visual Studio, os blocos lógicos eram muito mais fáceis de identificar do que no código original. E eu poderia começar a desvendar as instruções goto uma a uma.

A partir dessa experiência, devo dizer que há alguns casos em que as instruções goto são MUITO úteis para evitar a necessidade de reescrever o mesmo código repetidamente, embora em muitos casos o mesmo possa ser alcançado usando métodos e chamando-os repetidamente .

Também usei a versão gratuita do Silverfrost para compilar o código original e realizar verificações regulares no meu código reformatado para garantir que a reformatação não produzisse erros.

user643192
fonte
0

Uma abordagem genérica para "descompilar" esse código seria a seguinte:

  • primeiro compile-o em um formato de nível inferior (por exemplo, LLVM)
  • execute uma transformação SSA nele (ajudará a limpar suas variáveis ​​locais)
  • dividir o fluxo de controle irredutível (se houver)
  • detectar loops e ifs e substituí-los pelas construções de alto nível apropriadas

O back-end C do LLVM pode fornecer um primeiro rascunho.

SK-logic
fonte
0

A melhor maneira, sem dúvida, é primeiro reescrever / refatorar o código FORTRAN para uma maneira melhor estruturada e lógica. Isso forçará você a entender a lógica original antes de tentar portá-la para C #.

Aqui está como eu abordaria isso:

  • Entenda o código existente e, se necessário, refatorar e até reescreva-o no FORTRAN para poder testar facilmente se ele funciona.
  • Portar o código refatorado para C #

Não perca seu tempo com um conversor de código automático que acaba com a mesma bagunça de instruções goto que o FORTRAN original, pois o C # suporta gotos e etiquetas, assim como o C.

dodgy_coder
fonte
0

Na falta de algo, você pode usar as instruções goto em C # .

A instrução goto transfere o controle do programa diretamente para uma instrução rotulada.

Um uso comum do goto é transferir o controle para um rótulo de caixa de switch específico ou o rótulo padrão em uma instrução de switch .

A instrução goto também é útil para sair de loops profundamente aninhados ...

Wyatt Barnett
fonte
-2

Para converter qualquer código FORTRAN antigo em um novo idioma, alguém deve seguir algumas etapas básicas do código legado (1) para verificação de tipo estático, converter o código em "IMPLICIT NONE" (2) converter todos os truncados comuns em comuns completos (3) Remover equivalence (4) converte comum no Módulo de FORTRAN 90

Então você pode tentar converter para outros idiomas.

Debiprasad Ghosh
fonte