Concurso/Encontro Nacional de Programação Lógica
CeNPL'2003
Universidade de Évora
May 9--11, 2003
Make
O comando make
Para se construirem sistemas de software complexos (ou talvez não tanto...) é
necessário efectuar diversas tarefas, algumas dependentes de outras. A
maioria dos ambientes de desenvolvimento oferecem uma ferramenta para
automatizar o processo de construção, facilitanto a vida ao programador.
Tarefa
Trata-se de implementar uma cópia (lobotomizada) do comando Un*x
make, que deverá:
-
Aceitar uma especificação feita de regras e um objectivo.
- Produzir a sequência mais curta de acções necessária para atingir o
objectivo designado.
A especificação consiste em regras que dizem que um objectivo específico
depende de outros objectivos intermédios, obtendo-se após a execução
duma acção. Pode haver mais de uma acção por objectivo. Cada
objectivo pode depender de vários outros objectivos, os seus
antecedentes, o que significa que todos os antecedentes deverão
encontrar-se satisfeitos para que o objectivo considerado seja elegível. Pode
haver múltiplas formas de satisfazer um determinado objectivo.
Dados
Uma especificação é um ficheiro, com termos Prolog, que poderá ser lido pelo
programa ou (de preferência) ser incluido com este, aquando da compilação. A
especificação contém termos que se apresentam como factos para o
predicado rule/3, que será interpretado como sendo da forma
rule(OBJECTIVO, ANTECEDENTES, ACÇÕES) onde OBJECTIVO é um
átomo que designa o objectivo desta regra, ANTECEDENTES uma
lista de átomos que designam os antecedentes deste objectivo e
ACÇÕES é uma outra lista de átomos que designa ``comandos'' que seria
necessário executar para satisfazer o objectivo em questão, caso os seus
antecedentes já estejam satisfeitos.
Resultados
O objectivo designado é especificado pela interrogação:
| ?- make(OBJECTIVO, ACÇÕES, EFEITOS_SECUNDÁRIOS).
Em que OBJECTIVO é o nome do objectivo pretendido (instanciado),
ACÇÕES será a lista de acções que é necessário efectuar para atingir
o objectivo (variável) e EFEITOS_SECUNDÁRIOS será a lista de
objectivos ``secundários'' que tiveram de ser satisfeitos para que o objectivo
pretendido também o fosse. Os seguintes pontos deverão sempre verificar-se
acerca do predicado make/3:
-
A solução produzida deverá sempre ser a mais curta (em termos de
número de acções).
- Poderão haver múltiplas ocorrências dum determinado objectivo, no
decorrer do processo desencadeado pelo make: serão consideradas
como independentes.
- No caso em que o objectivo é impossível de satisfazer, o predicado
make/3 deverá falhar silenciosamente.
- Caso haja um ciclo nas dependências, o predicado make/3
deverá levantar uma excepção da forma loop(LISTA). LISTA
é uma lista com todos os objectivos que formam a dependência circular (o
ciclo.)
Exemplo
Considere as regras:
rule(f1, [], []).
rule(f2, [], []).
rule(g, [f1, f2], [preprocess([f1,f2]), compile(g)]).
rule(h, [g], [bork(h)]).
rule(h, [f2], [shortcut(h)]).
rule(l, [m], [foo]).
rule(m, [l], [bar]).
Poderemos obter a seguinte sessão:
| ?- load(rules).
| ?- make(g, A, S).
A = [preprocess([f1,f2]), compile(g)],
S = [f2, f1]
| ?- make(h, A, S).
A = [shortcut(h)],
S = [f2]
| ?- make(l, A, S).
ERROR: Unhandled exception: loop([l, m])
| ?- make(x, A, S).
no
This document was translated from LATEX by
HEVEA.