A questão é bastante ampla. Para responder em um espaço razoável, farei muitas simplificações demais.
Vamos concordar com a terminologia. Um programa está correto quando implica sua especificação. Essa vaga declaração é precisa de várias maneiras, identificando exatamente o que é um programa e o que exatamente é uma especificação. Por exemplo, na verificação de modelo, o programa é uma estrutura Kripke e a especificação geralmente é uma fórmula LTL . Ou, o programa pode ser uma lista de instruções do PowerPC e a especificação pode ser um conjunto de asserções de Hoare-Floyd escritas em, digamos, lógica de primeira ordem. Existem muitas variações possíveis. É tentador concluir que em um caso (estrutura Kripke) não verificamos um programa real, enquanto no segundo caso (lista de instruções do PowerPC), verificamos. No entanto, é importante perceber que realmente estamos analisando modelos matemáticos nos dois casos, e isso está perfeitamente correto. (A situação é bastante semelhante à física, onde, por exemplo, a mecânica clássica é um modelo matemático da realidade.)
A maioria das formalizações distingue entre a sintaxe e a semântica de um programa; isto é, como é representado e o que isso significa. A semântica de um programa é o que conta do ponto de vista da verificação do programa. Mas, é claro que é importante ter uma maneira clara de atribuir significados a (representações sintáticas de) programas. Duas maneiras populares são as seguintes:
- (pequena etapa) semântica operacional : é como definir uma linguagem de programação escrevendo um intérprete para ela. Para isso, você precisa dizer qual é o estado , e ele é afetado por cada afirmação no idioma. (Você pode se perguntar em qual idioma escreve o intérprete, mas vou fingir que não.)
- semântica axiomática : aqui cada tipo de instrução vem com um esquema axiomático . Então, grosso modo, sempre que uma declaração específica desse tipo é usada, ela se traduz em poder usar certos axiomas. Por exemplo, a atribuição vem com o esquema { P [ x / e ] }x : = e ; a atribuição específica x : = x + 1 vem com o axioma { x + 1 = 1 }{ P[ x / e ] }x : = e{ P}x : = x + 1 se instanciarmos o esquema com P = ( x = 1 ) .{ x + 1 = 1 }x : = x + 1{ x = 1 }P= ( x = 1 )
(Existem outros. Sinto-me particularmente mal por omitir a semântica denotacional, mas essa resposta já é longa.) O código da máquina e a semântica operacional estão bem próximos do que a maioria das pessoas chamaria de 'programa real'. Aqui está um documento seminal, que usa semântica operacional para um subconjunto do código de máquina DEC Alpha:
Por que você usaria alguma semântica de nível superior, como as axiomáticas? Quando você não deseja que sua prova de correção dependa do hardware no qual você executa. A abordagem, então, é provar a correção de um algoritmo com relação a algumas semânticas de alto nível convenientes e, em seguida, provar que a semântica soa com relação à semântica de nível inferior mais próxima das máquinas reais.
Em resumo, pude pensar em três razões que levaram à sua pergunta:
- Você viu apenas semânticas de alto nível que não se parecem com o que costumava chamar de programa e se pergunta se há semânticas de baixo nível. A resposta é sim.
- Você quer saber como provar que um modelo corresponde à realidade. Como na física, você não. Você simplesmente cria modelos melhores e os compara com a realidade.
- Você não viu a distinção entre sintaxe e semântica e várias maneiras de atribuir significados a programas. Duas perguntas anteriores listam alguns livros.
Essa resposta está apenas tentando identificar três maneiras diferentes pelas quais eu entendi a pergunta. Aprofundar-se em qualquer um desses pontos exigiria muito espaço.