Conversión del código Fortran 77 a C #

14

Estoy tratando de convertir un programa Fortan77 a C #. Tengo una subrutina con aproximadamente 650 líneas de código y horribles declaraciones GOTO por todo el lugar. Tengo muchos problemas incluso para comenzar a visualizar el flujo de la subrutina para descubrir qué hace.

¿Hay alguien con experiencia en este tipo de cosas que pueda darme algún consejo sobre cómo obtener una visión general de esta subrutina? ¿Hay algunas herramientas disponibles para acelerar o facilitar este tipo de conversión?

usuario643192
fuente
1
Como esta pregunta es más abierta y busca consejo, sería más apropiado para los Programadores SE
44
¿ha considerado simplemente compilarlo en .NET usando silverfrost.com/11/ftn95/ftn95_fortran_95_for_windows.aspx y luego simplemente hacer referencia al ensamblado?
@ Shaun, es una buena idea Shaun. Lo miraré si no puedo llegar a ningún lado con la reprogramación.
user643192
2
Lo siento por ti ...
marko
1
He estado en tu lugar. Fueron los peores días de mi carrera.
usuario

Respuestas:

10

En mi experiencia, una buena manera de hacerlo es crear un diagrama de flujo del código Fortran. Intente separar los objetivos de las declaraciones GOTO en bloques separados, y use el diagrama para tratar de comprender el código en un nivel alto.

Vea si puede reemplazar lógicamente los GOTO con bucles o llamadas a funciones; Si el diagrama resultante tiene la forma de una estructura de árbol, es relativamente fácil convertir a C # sin recurrir a GOTO. Al final, sin embargo, deberá comprender el código íntimamente para poder mantener y utilizar el resultado con confianza.

Daniel B
fuente
Buena sugerencia, gracias! Las declaraciones GOTO deben ser prohibidas.
user643192
66
@ user643192, gotoes algo extremadamente útil si se aplica con prudencia. No implementaría un autómata de estado grande y eficiente sin un goto. Ciertamente, también los necesitará en su código generado.
SK-logic
3
Hay herramientas que pueden dibujar diagramas de flujo del código Fortran. Ejemplo: home.comcast.net/~lchen223621
NoChance
OP: No puedes prohibir retroefectivamente. @EmmadKareem: sugerencia muy útil.
Kris
Terminé haciendo lo que Daniel B sugirió aquí e hice una versión en bloque del código Fortran. Ayudó mucho, así que gracias por eso. Para SK-logic, probablemente tenga razón sobre los GOTO. Mi comentario se hizo después de mi primera tarde mirando el código ... y hay
MUCHOS GOTOs
12

Además de lo que Daniel B escribió anteriormente, diría lo siguiente:

Primero, obtenga su código Fortran para trabajar con Fortran para DotNet. No si "no puede llegar a ningún lado con la reprogramación", sino antes de intentar cualquier reprogramación. Será un pequeño paso, pero en la dirección correcta.

Luego, escriba un conjunto de pruebas en C # que alimente el código Fortran con cualquier entrada que se haya hecho para masticar y almacene la salida. Ejecute el conjunto de pruebas una vez y guarde la salida. Luego, extienda el conjunto de pruebas para probar la salida producida contra la salida guardada. Suponiendo que el código Fortran siempre produce la misma salida cuando se alimenta con la misma entrada, la prueba, por supuesto, debe tener éxito.

Luego, mientras reescribe el código en C #, ejecutará su código en el conjunto de pruebas y le indicará si su código funciona correctamente o no, es decir, si está produciendo exactamente la misma salida que el Fortran código dado la misma entrada. Sin ella, estarás perdido.

No estoy de acuerdo con @ SK-logic, NO debería tener que usar ningún gotos en su código C #.

(Pero con suerte, una vez que haya hecho que el código Fortran funcione en DotNet, no verá ninguna razón para seguir perdiendo el tiempo convirtiendo una pieza de código de espagueti a C #).

Mike Nakis
fuente
1
¿Le importaría explicar por qué "NO debería"? ¿Algún argumento racional , además de "todos creen que es malo"? Mencioné dos casos extremadamente importantes en los que tienes que usar goto, de lo contrario terminarás escribiendo código ilegible o ineficiente (o ambos).
SK-logic
@ SK-logic No escribí "NO deberías", escribí "NO deberías tener que". En cualquier caso, aquí va: las declaraciones de goto hacen que el código sea muy difícil de comprender y verifican su corrección en casi todas las circunstancias, y sus supuestos beneficios de eficiencia son algo entre un mito y un concepto erróneo. Por supuesto, esto podría aclararse aún más, pero por favor abstenerse de hacerlo, este no es el lugar para esta discusión. Solo aceptemos estar en desacuerdo.
Mike Nakis
2
la ausencia de estadistas gototambién puede hacer que el código sea muy difícil de comprender en algunos casos (y una máquina de estados es el ejemplo más importante de tal caso). Simplemente no puedo soportar esta estúpida religión de goto-bashing: la gente sigue repitiendo la misma BS sin sentido sin siquiera tratar de entender la razón por la cual se considera que goto es dañino.
SK-logic
Eres una de esas personas que simplemente no pueden soportarlo si no tienen la última palabra, ¿eh? C -: =
Mike Nakis
1
@ ridecar2, escribo buenas máquinas de estado TODO EL TIEMPO. Uso enumeraciones y declaraciones de cambio, y dejo que el compilador escriba los GOTO en el lenguaje de máquina generado. En realidad, nunca he visto un ejemplo de una máquina de estados escrita explícitamente con GOTO. ¿Quieres publicar un puntero en un ejemplo?
John R. Strohm
3

Tu tarea es complicada. Realmente necesitas conocer bien a Fortran. Debe tener cuidado con la forma en que Fortran hace cálculos similares / diferentes y qué reglas de truncamiento y redondeo se aplican. Además, debe tener cuidado con los tipos primitivos que significan en C # y Fortran.

Otro enfoque de lo que ha sido sugerencia (no necesariamente una mejor, es solo otra):

A - Considere volver a escribir el código en C # basado en el conocimiento del negocio y la función, use el código Fortran solo como referencia

B - Considere usar una herramienta comercial que realiza el trabajo de conversión - Ejemplo: DataTek

Si la rutina representa una función estándar o una función para la que puede comprar una dll preparada (como la integración numérica), use la función estándar o el producto comercial en lugar de la traducción manual, y su problema se resolverá.

Si lo anterior no es suficiente, responda esta pregunta:

¿Necesito optimizar el código o simplemente hacer que se ejecute? En otras palabras, ¿cuál es el valor comercial de pasar 500 horas para mejorar el código?

Si no hay valor en la optimización, traduzca el código línea por línea y ya está.

Si esto todavía no es bueno, entonces:

0-Convierta el código Fortran línea por línea en C # (o use Fortan CLR)

1-Haz una prueba rápida asegúrate de que se ejecute

2-Use una refactorización (hay herramientas comerciales disponibles) para ayudarlo a escribir el código de una manera más optimizada.

Buena suerte.

Ninguna posibilidad
fuente
2

Una forma sencilla de recodificar cosas con muchos gotos es dibujar un diagrama de flujo y tirar de la cuerda recta. A veces, los programas F77 son solo programas F66 antiguos o incluso peores programas FII. F66 no tenía una construcción if-then-else, por lo que los gotos eran necesarios. Todo lo que necesita hacer es invertir la condición para obtener un if-then.

F66 tampoco tuvo un do-while, pero sí F77. Depende de si el codificador se convirtió de F66 a F77 (como muchos hoy en día son C a C ++ o C ++ a C #) donde están usando F77 como F66. Si puede detectar los patrones, en la codificación, es mucho más fácil convertir.

taza
fuente
1

Antes de comenzar, haga un conjunto de pruebas para probar el código existente. Sea muy cuidadoso ya que esto ayudará a arrojar luz sobre el comportamiento. Luego puede usar esta suite para medir la efectividad de su conversión.

Más allá de eso, sea ​​metódico , no se apresure y use mucho papel para rastrear la funcionalidad.

Bryan Oakley
fuente
1

Esta es la forma en que realmente traduje el código a C #. Como .NET admite declaraciones de goto, primero tomé todo el código Fortran y lo pegué como está en un nuevo método, bueno, tantos métodos como rutinas y subrutinas Fortran.

Al compilador se le ocurrió un millón de errores, principalmente sobre variables no declaradas y formato incorrecto de instrucciones de bloque, que eliminé uno por uno. También tuve que volver a escribir parte del código específico de Fortran, como las declaraciones de E / S y cosas por el estilo. Cuando se hizo eso, tenía una réplica exacta del código original.

Gracias al buen formato de Visual Studio, los bloques lógicos fueron mucho más fáciles de identificar que en el código original. Y podría comenzar a desentrañar las declaraciones de goto una por una.

De esta experiencia tengo que decir que hay algunos casos en los que las declaraciones de goto son realmente MUY útiles para evitar tener que volver a escribir el mismo código una y otra vez, aunque en muchos casos se puede lograr lo mismo utilizando métodos y llamando repetidamente .

También utilicé la versión gratuita de Silverfrost para compilar el código original y realizar verificaciones regulares en mi código reformateado para asegurar que el formateo no produjera errores.

usuario643192
fuente
0

Un enfoque genérico para "descompilar" dicho código sería el siguiente:

  • primero compílelo en un formulario de nivel inferior (p. ej., LLVM)
  • realice una transformación SSA en él (ayudará a limpiar sus variables locales)
  • dividir el flujo de control irreducible (si lo hay)
  • detectar bucles e ifs y reemplazarlos con las construcciones adecuadas de alto nivel

El propio backend C de LLVM puede proporcionarle un primer borrador.

SK-logic
fuente
0

La mejor forma, sin duda, es reescribir / refactorizar primero el código FORTRAN en una forma mejor estructurada y lógica. Esto lo obligará a comprender la lógica original antes de intentar portarlo a C #.

Así es como lo abordaría:

  • Comprenda el código existente y, si es necesario, refactorice e incluso vuelva a escribirlo en FORTRAN para que pueda probar fácilmente que funciona.
  • Portar el código refactorizado a C #

No pierda su tiempo con un convertidor de código automático que terminará con el mismo desorden de declaraciones goto que el FORTRAN original, ya que C # admite gotos y etiquetas, al igual que C.

dodgy_coder
fuente
0

Al fallar cualquier otra cosa, puede usar declaraciones goto en C # .

La instrucción goto transfiere el control del programa directamente a una instrucción etiquetada.

Un uso común de goto es transferir el control a una etiqueta de caja de cambio específica o la etiqueta predeterminada en una declaración de cambio .

La instrucción goto también es útil para salir de bucles profundamente anidados ...

Wyatt Barnett
fuente
-2

Para convertir cualquier código FORTRAN antiguo a un nuevo idioma, alguien debe seguir algunos pasos básicos en su código heredado (1) para la verificación de tipo estático, convertir el código a "IMPLICIT NONE" (2) convertir todos los comunes truncados a comunes completos (3) Eliminar conversión de equivalencia (4) común al módulo de FORTRAN 90

Entonces puedes intentar convertir a otros idiomas.

Debiprasad Ghosh
fuente