• Nenhum resultado encontrado

Resultado da síntese do Max3 em linguagem SKETCH

2 if( len ( lst ) =1) then { r e t u r n fi rst ( lst ) ; } 3 else { 4 int a := f irs t ( lst ) ; 5 int b := f i n d _ m a x ( rest lst ) ; 6 if( a > b ) then { 7 r et u r n a ; 8 } else { 9 r et u r n b ; 10 } 11 } 12 }

A síntese usando a linguagem SKETCH tem uma abordagem dedutiva, obrigando o usuário a definir a funcionalidade dos programas parciais (através de asserções e de- finições). Também, na implementação do sketch, o usuário precisa informar o fluxo de controle e em que posições os comandos devem estar. Entende-se que a abordagem do PSMF diminui a dificuldade do usuário, pois não é preciso definir expressões de síntese dedutiva (basta informar exemplos E/S que, embora indutivos, costumam ser mais fáceis de implementar). Por fim, no caso do PSMF, é usado soft sketch, ou seja, não é preciso se preocupar em que posição os comandos serão colocados, pois o sintetizador irá alocá-los na ordem de execução certa quando algum programa candidato representar a solução da tarefa de síntese.

6.3 SÍNTESE DE PROGRAMAS POR RESOLVEDORES SAT/SMT

Srivastava (2010) implementou uma abordagem de síntese via resolvedores SAT, no qual descreve o processo de síntese através de uma estrutura (scaffold) para facilitar a sua construção (sendo identificado como ptheoSyn na Tabela 16). A scaffold do programa a ser sintetizado é uma tripla {ℱ , 𝒟, ℛ}, onde: ℱ é uma especificação funcional da pré e pós-condição; 𝒟 são as restrições do domínio expressas em termos de guardas Booleanas (guards) e outras expressões (expressions); e ℛ são as restrições de recursos em termos de fragmentos do código do programa (similar a um sketch).

O sintetizador transforma o que foi definido noscaffold em um esqueleto de programa contendo incógnitas. Depois, percorrendo possíveis caminhos do esqueleto, as condições de síntese especificam um conjunto de restrições sobre essas incógnitas para declarações, guardas, invariantes de laço e funções de ranking. Tais condições de síntese vão em busca de garantir que o programa inicie atendendo a pré-condição (corretude parcial) e atinja a terminação de laço e expressões bem formadas desse esqueleto. Por fim, codificam-se essas condições de síntese em um problema de satisfatibilidade, que pode ser resolvido com os atuais solvers SAT/SMT.

Srivastava (2010) apresenta a síntese de alguns programas bem conhecidos em três domínios. Aqui menciona-se apenas um exemplo de cada, a saber: aritmética (IntSqrt), ordenação (aBubSort) e programação dinâmica (Fib). A ferramenta não apenas sintetiza o programa desejado, mas também gera a prova de corretude e terminação. Ou seja, é a primeira abordagem que mecanicamente gera o programa e a sua prova, enquanto que outras abordagens (Seção 2.1) ou precisavam da prova para sintetizar o programa ou não tentam prover qualquer prova formal (SRIVASTAVA, 2010).

Para dar uma ideia do resultado que a ferramenta produziu na tarefa de síntese, considere uma implementação do programa IntSqrt. A scaffold terá um par de especi- ficações funcionais da pré e pós-condições ℱ = (𝑥 ≥ 1; (𝑖 − 1)2 ≤ 𝑥 < 𝑖2); 𝒟 são as restrições do domínio (𝒟𝑒𝑥𝑝 e 𝒟𝑔𝑟𝑑) apenas com expressões de aritmética linear, ou

seja, nada de operadores quadráticos nativos, como por exemplo 𝑠𝑞𝑟𝑡(); e as restrições de recursos em termos de modelo de fluxo, pilha e computação serão, respectivamente, ℛ = (ℛ𝑓 𝑙𝑜𝑤= 𝑎𝑐𝑦𝑐𝑙𝑒; 𝑙𝑜𝑜𝑝(𝑎𝑐𝑦𝑐𝑙𝑒); 𝑎𝑐𝑦𝑐𝑙𝑒)(ℛ𝑠𝑡𝑎𝑐𝑘 = 𝑖𝑛𝑡, 1)(ℛ𝑐𝑜𝑚𝑝 = 𝑣𝑎𝑧𝑖𝑜). O ℛ𝑓 𝑙𝑜𝑤 in-

forma que o programa tem comandos sequenciais seguidos de um laço seguido de mais comandos sequenciais. ℛ𝑠𝑡𝑎𝑐𝑘 determina que existe ao menos uma variável local e ℛ𝑐𝑜𝑚𝑝

vazio determina que o laço não tem um número constante de iterações. O sintetizador, além de produzir o código-fonte do programa, também gerou o invariante do laço (que garante a corretude parcial) e a função de ranking (que garante terminação) mostrados na Figura 9.

Figura 9 – Programa e prova gerados na síntese por prova teórica.

Seria interessante visualizar na prática as ideias do autor, mas o seu conjunto de ferramentas não está mais disponível para uso, pois a Microsoft Phoenix Framework foi descontinuada2 e as ferramentas desenvolvidas possuem forte dependência de funciona- 2 Mais informação sobre a descontinuidade da Microsoft Phoenix Framework

mento com a extinta framework. Também vale informar que o próprio autor chegou a conclusão de que tinha que fornecer uma boa quantidade de input e fazer “refinamen- tos manuais após a síntese” pra sua tecnologia gerar resultados satisfatórios para certos problemas que foram abordados.

A abordagem de síntese de programas por resolvedores SAT/SMT condiciona a cons- trução do scaffold de forma que o usuário precisa informar as estruturas sintáticas, como laços, atribuição, operadores (quais, a quantidade e em que ordem aparecerão na estrutura do programa a ser sintetizado) para realizar a tarefa de síntese. Por exemplo, no contexto do programa IntSqrt, a abordagem do PSMF permite opcionalmente que o usuário informe restrições soft sketch como (??=v+2*i+1; ??=i+1; ??=i-1;) sem necessidade em definir em que ordem elas (ou quaisquer outras estruturas sintáticas) ocorrem.

6.4 SÍNTESE DE PROGRAMAS COM LINGUAGEM AUXILIADA POR RESOLVEDORES E ROSETTE

Torlak e Bodik (2013) propuseram uma ferramenta, denominada Rosette, para o desenvol- vimento de linguagens “auxiliadas por resolvedores” (solver-aided) a serem usadas, entre outras finalidades, para verificação e síntese de programas. Baseada na linguagem Rac- ket (FLATT, 2012), Rosette apresenta o problema da síntese de programas com resultados interessantes através de sketch de uma forma “mais atraente” que o uso direto dos atuais revolvedores SAT/SMT (sendo identificado como rosette na Tabela 16).

Rosette acaba ficando “mais atraente” porque libera o usuário da tarefa não trivial de escrever predicados de síntese como fórmulas lógicas que são compreendidas pelos resolve- dores SAT/SMT. E isso ocorre porque a ferramenta é dotada de um conjunto de recursos (os chamados construtores de linguagem, que serão apresentados adiante) que funcionam como um tradutor entre a intenção do usuário e os resolvedores SAT/SMT (TORLAK; BODIK, 2013).

Para dar uma ideia de como funciona a ferramenta na tarefa de síntese, considere uma implementação recursiva de um programa similar ao aMax em linguagem Java (Lista- gem 6.4). Ao invés de retornar o maior elemento de um array (como faz o aMax), ele retorna o maior elemento de uma lista. A ideia central da implementação é verificar quem é maior: o valor da cabeça da lista lst_head ou o valor do maior elemento de sua cauda

lst_tail.

Listagem 6.4 – Implementação recursiva com sketch do programa aMax para listas.