No planeo escribir un compilador en el futuro cercano; Aún así, estoy bastante interesado en las tecnologías de compilación y en cómo esto podría mejorarse.
Comenzando con los lenguajes compilados, la mayoría de los compiladores tienen dos niveles de error: advertencias y errores, el primero es la mayoría de las veces cosas no fatales que debe corregir, y los errores que indican la mayoría de las veces que es imposible producir máquina (o byte) código de la entrada.
Sin embargo, esta es una definición bastante débil. En algunos lenguajes como Java, ciertas advertencias son simplemente imposibles de eliminar sin usar la @SuppressWarning
directiva. Además, Java trata ciertos problemas no fatales como errores (por ejemplo, el código inalcanzable en Java desencadena un error por una razón que me gustaría saber).
C # no tiene los mismos problemas, pero tiene algunos. Parece que la compilación se produce en varios pases, y un error de pase evitará que se ejecuten los pases posteriores. Debido a eso, el recuento de errores que obtienes cuando falla tu construcción a menudo se subestima enormemente. En una ejecución, podría decir que tiene dos errores, pero una vez que los arregle, tal vez obtendrá 26 nuevos.
Excavar en C y C ++ simplemente muestra una mala combinación en las debilidades de diagnóstico de compilación de Java y C # (aunque podría ser más exacto decir que Java y C # simplemente siguieron su camino con la mitad de los problemas cada uno). Algunas advertencias realmente deberían ser errores (por ejemplo, cuando no todas las rutas de código devuelven un valor) y aún son advertencias porque, supongo, en el momento en que escribieron el estándar, la tecnología del compilador no era lo suficientemente buena como para hacer este tipo de controles obligatorios En la misma línea, los compiladores a menudo verifican más de lo que dice el estándar, pero aún usan el nivel de error de advertencia "estándar" para los hallazgos adicionales. Y a menudo, los compiladores no informarán todos los errores que puedan encontrar de inmediato; Puede tomar algunas compilaciones deshacerse de todos ellos. Sin mencionar los errores crípticos que a los compiladores de C ++ les gusta escupir,
Ahora, agregando que muchos sistemas de compilación son configurables para informar fallas cuando los compiladores emiten advertencias, solo obtenemos una mezcla extraña: no todos los errores son fatales, pero algunas advertencias deberían; no todas las advertencias son merecidas, pero algunas se suprimen explícitamente sin mencionar más su existencia; y a veces todas las advertencias se convierten en errores.
Los idiomas no compilados aún tienen su parte de informes de errores deficientes. Los errores tipográficos en Python no se informarán hasta que el código se ejecute realmente, y nunca se puede eliminar más de un error a la vez porque el script dejará de ejecutarse después de que se encuentre con uno.
PHP, por su parte, tiene un montón de niveles de error más o menos significativos y excepciones. Los errores de análisis se informan uno a la vez, las advertencias son a menudo tan malas que deberían abortar su secuencia de comandos (pero no lo hacen de manera predeterminada), las notificaciones a menudo muestran problemas lógicos graves, algunos errores realmente no son lo suficientemente graves como para detener su secuencia de comandos, pero aún así hacer, y como de costumbre con PHP, hay algunas cosas realmente extrañas allí (¿por qué demonios necesitamos un nivel de error para errores fatales que no son realmente fatales?, E_RECOVERABLE_E_ERROR
estoy hablando contigo).
Me parece que todas las implementaciones de informes de errores del compilador que se me ocurren están rotas. Lo cual es una verdadera lástima, ya que todos los buenos programadores insisten en lo importante que es tratar los errores correctamente y, sin embargo, no pueden obtener sus propias herramientas para hacerlo.
¿Cuál crees que debería ser la forma correcta de informar los errores del compilador?
Respuestas:
Su pregunta no parece ser sobre cómo informamos los errores del compilador, sino sobre la clasificación de los problemas y qué hacer al respecto.
Si comenzamos suponiendo, por el momento, que la dicotomía advertencia / error es correcta, veamos qué tan bien podemos construir sobre eso. Algunas ideas:
Diferentes "niveles" de advertencia. Muchos compiladores implementan esto (por ejemplo, GCC tiene muchos interruptores para configurar exactamente sobre qué advertirá), pero necesita trabajo, por ejemplo, informar la gravedad de una advertencia informada y la capacidad de establecer "advertencias" son errores "solo para advertencias por encima de una gravedad especificada.
Clasificación sana de errores y advertencias. Solo se debe informar un error si el código no cumple con la especificación y, por lo tanto, no se puede compilar. Las declaraciones inalcanzables, aunque probablemente sean un error de codificación, deberían ser una advertencia , no un error: el código sigue siendo "válido" y hay instancias legítimas en las que uno querría compilar con código inalcanzable (modificaciones rápidas para la depuración, por ejemplo) .
Ahora cosas en las que no estoy de acuerdo contigo:
Hacer un esfuerzo extra para informar cada problema. Si hay un error, eso rompe la compilación. La construcción está rota. La compilación no funcionará hasta que se solucione ese error. Por lo tanto, es mejor informar ese error inmediatamente, en lugar de "continuar" para intentar identificar todo lo demás "incorrecto" con el código. Especialmente cuando muchas de esas cosas probablemente sean causadas por el error inicial de todos modos.
Su ejemplo específico de una advertencia que debería ser un error. Sí, probablemente sea un error del programador. No, no debería romper la construcción. Si sé que la entrada a la función es tal que siempre devolverá un valor, debería poder ejecutar la compilación y hacer algunas pruebas sin tener que agregar esas comprobaciones adicionales. Sí, debería ser una advertencia. Y una maldita de alta severidad. Pero no debería romper la compilación en sí misma, a menos que se compile con advertencias son errores.
Pensamientos?
fuente
Un problema que mencionó fue el informe incompleto de errores, por ejemplo, informar 2 errores, y cuando los arregla, obtiene un montón más.
Esto es (en gran parte) un compromiso por parte del escritor compilador. Dependiendo de qué error que ha hecho, es muy fácil para el compilador para empezar a malinterpretar lo que haga tiene bastante mal que comienza a errores del informe que tienen muy poco que ver con la realidad. Solo por ejemplo, considere un error tipográfico simple en el que tiene algo así en
itn x;
lugar deint x;
. A menos que haya hecho algo más queitn
signifique algo, esto se informará como un error. Eso está bien en lo que respecta, pero ahora considere lo que sucede a continuación: el compilador analiza un montón de código que intenta usarx
como variable. ¿Debería A) detenerse y dejar que arregle eso, o B) arrojar 2000 erroreserror: "x": undeclared identifier
o algo en ese orden? Considere otra posibilidad:Este es otro error bastante obvio, obviamente debería ser un en
{
lugar de un[
. El compilador puede decirle esa parte con bastante facilidad, pero ¿debería luego informar un error para algo comox=1;
decir algo comoerror: statement only allowed inside a function
?Tenga en cuenta que estos son incluso problemas bastante triviales: es mucho más fácil encontrar problemas mucho peores (especialmente, como la mayoría de nosotros sabemos, cuando ingresa a las plantillas de C ++). La conclusión es que el escritor del compilador generalmente está atascado en tratar de comprometerse entre informar errores falsos (es decir, informar algo como un error, aunque esté bien) y no informar errores reales. Hay algunas reglas generales que la mayoría sigue para tratar de evitar ir demasiado mal en cualquier dirección, pero casi ninguna de ellas está cerca de ser perfecta.
Otro problema que mencionaste fue Java y
@SupressWarning
. Esto es bastante diferente de lo anterior: sería bastante trivial solucionarlo. La única razón por la que no se soluciona es que hacerlo no encaja con el "carácter" básico de Java, es decir, en su opinión, "eso no es un error, es una característica". Aunque generalmente es una broma, en este caso las personas involucradas están tan equivocadas que realmente creen que es verdad.El problema que menciona en C y C ++ con rutas de código que no devuelven un valor no es realmente para permitir compiladores primitivos. Es para permitir décadas de código existente , algunos de los cuales nadie quiere arreglar, tocar o incluso leer. Es antiguo y feo, pero funciona, y nadie quiere nada más que seguir trabajando. Para bien o para mal, los comités de idiomas están bastante atascados con el mantenimiento de esa compatibilidad con versiones anteriores, por lo que continúan permitiendo cosas que a nadie realmente le gustan, pero algunas personas (al menos piensan que necesitan).
fuente
csc
rinde.