Me encanta todo lo que es tiempo de compilación y me encanta la idea de que una vez que compilas un programa, se hacen muchas garantías sobre su ejecución. En términos generales, un sistema de tipo estático (Haskell, C ++, ...) parece ofrecer garantías de tiempo de compilación más sólidas que cualquier sistema de tipo dinámico.
Por lo que entiendo, Ada va aún más lejos en lo que respecta a la verificación del tiempo de compilación, y es capaz de detectar una mayor gama de errores antes de la ejecución. También se considera bastante seguro, dado que, en algún momento, se eligió para campos delicados (cuando los errores de programación pueden costar vidas humanas).
Ahora, me pregunto: si las garantías estáticas más fuertes conducen a un código más documentado y seguro, ¿por qué no estamos investigando más en esa dirección?
Un ejemplo de algo que parece faltar sería un lenguaje que en lugar de definir un int
tipo genérico que tenga un rango determinado por el número de bits de la arquitectura subyacente, uno podría tener rangos (en el siguiente ejemplo se Int [a..b]
describe un tipo entero entre ayb incluidos):
a : Int [1..24]
b : Int [1..12]
a + b : Int [2..36]
a - b : Int [-11..23]
b - a : Int [-23..11]
o (tomando esto de Ada):
a : Int [mod 24]
b : Int [mod 24]
a + b : Int [mod 24]
Este lenguaje seleccionaría el mejor tipo subyacente para el rango y realizaría una verificación de tiempo de compilación en las expresiones. De modo que, por ejemplo, dado:
a : Int [-3..24]
b : Int [3..10]
luego:
a / b
nunca se definirá
Este es solo un ejemplo, pero siento que hay mucho más que podemos hacer cumplir en el momento de la compilación. Entonces, ¿por qué parece tan poca investigación sobre esto? ¿Cuáles son los términos técnicos que describen esta idea (para que pueda encontrar más información sobre este tema)? Cuales son los limites?
dependent type
orefinement type
.Respuestas:
No estoy en condiciones de decir cuánto se debe hacer más investigación sobre el tema, pero puedo decirle que se está haciendo investigación, por ejemplo, el programa Verisoft XT financiado por el gobierno alemán.
Los conceptos que creo que está buscando se llaman verificación formal y programación basada en contratos , donde este último es una forma fácil de programar para hacer lo primero. En la programación basada en contratos, primero debe escribir su código de manera normal y luego insertar los llamados contratos en el código. Un lenguaje fácil de usar que se basa en este paradigma es Spec # de Microsoft Research, y la extensión de contratos de código funcionalmente similar pero un poco menos bonita para C # que ambos pueden probar en línea (también tienen herramientas similares para otros idiomas, consulte rise4fun ) El "int con tipo de rango" que mencionó se reflejaría en dos contratos en una función:
Si desea llamar a esa función, debe usar parámetros que se aseguren de cumplir con estos criterios, u obtendrá un error de tiempo de compilación. Los anteriores son contratos muy simples, puede insertar casi cualquier suposición o requisito sobre variables o excepciones y su relación que pueda pensar y el compilador verificará si cada requisito está cubierto por una suposición o algo que pueda garantizarse, es decir, derivado de los supuestos Es por eso de donde proviene el nombre: la persona que llama establece requisitos , la persona que llama se asegura de que se cumplan, como en un contrato comercial.
Bajo el capó, los contratos de código generalmente se combinan con el conocimiento sobre el funcionamiento interno (semántica operativa) del lenguaje de programación en una lista de condiciones de verificación . Esta lista representa básicamente una gran proposición lógica con variables libres: las entradas de su programa. Si la proposición es verdadera para todas las asignaciones de variables posibles, entonces el programa se considera correcto. Para verificar si este es o no el caso, un Probador SMTn PP(x1,x2,...,xn) n P es usado Desde el lado de la CS, esas dos son las partes críticas del proceso: la generación de condiciones de verificación es complicada y SMT es un problema NP-completo o indecidible, dependiendo de las teorías consideradas. Incluso hay una competencia para los solucionadores SMT, por lo que ciertamente se investiga un poco al respecto. Además, existen enfoques alternativos para usar SMT para la verificación formal, como la enumeración del espacio de estado, la verificación de modelos simbólicos, la verificación de modelos acotados y muchos más que también se están investigando, aunque SMT es, afaik, actualmente el enfoque más "moderno".
En cuanto a los límites de la idea general:
Una última cosa que vale la pena mencionar que no se ajusta del todo a la explicación anterior es un campo llamado "Teoría de la complejidad implícita", por ejemplo, este artículo . Su objetivo es caracterizar los lenguajes de programación en los que cada programa que puede escribir se encuadra en una clase de complejidad específica, por ejemplo P. En dicho lenguaje, cada programa que escribe se "asegura" automáticamente para que tenga un tiempo de ejecución polinómico, que se puede "verificar" en tiempo de compilación simplemente compilando el programa. Sin embargo, no conozco ningún resultado prácticamente utilizable de esta investigación, pero también estoy lejos de ser un experto.
fuente