Para transformar o modelo foram especificadas um número avultado de regras que cooperativamente permitem obter o código Prolog final. Nesta secção apresentar-se-á, de forma intuitiva, as regras envolvidas na transformação de diversos trechos de um modelo especificado através da sintaxe textual do SATEL⊕EAPN. Para que a descrição não se fique pela forma intuitiva (logo informal), à medida que forem descritas as regras indicar-se-ão apontadores para o apêndice das regras em análise, especificadas na sintaxe do DSLTrans.
4. ABORDAGEM PROPOSTA/SOLUÇÃO 4.7. Modelo de transformação
Posto isto, atente-se no exemplo da figura 4.3. Na transformação aqui envolvida, note-se que é um gerador de naturais cujo nome da operação associada é③❡r♦ e cujo sort do resultado é claramente ♥❛t (naturais). Da figura depreende-se então que, em primeira análise, num gerador, dito constante, cria-se um predicado cujo nome é o sort do result, cuja aridade é um e o único argumento é um functor sem argumentos cujo nome é o nome do gerador.
zero -> nat nat(zero).
$L)
‘ ’).
2 1
Figura 4.3: Transformação do gerador
De uma forma mais geral, atente-se na figura 4.4. Neste exemplo tem-se um ge- rador que possui argumentos de determinado sort. Repare-se que a regra a aplicar é similar à anterior com as devidas extensões/generalizações. Com efeito, aqui o sort do resultado (nat) volta a ser o nome do functor da cabeça de uma cláusula. Neste exemplo é necessário uma cláusula porque é necessário impor condições sobre os ar- gumentos.
O functor da cabeça volta a imbricar o functor com o nome do gerador, no entanto, este agora tem aridade superior a zero. Os argumentos deste functor devem ser tantas variáveis quantos os argumentos do gerador, na mesma ordem de correspondência. No corpo da cláusula é necessário impôr que as variáveis criadas por via de cada um dos argumentos do gerador, sejam exactamente do sort do argumento correspondente (ex. fluxo 3 e 5) da figura.
suc : nat -> nat nat(suc(X1)):-nat(X1).
$L) ‘ ’). 4 3 5 6
Figura 4.4: Transformação do gerador
Da mesma forma e já generalizando, na figura 4.5, ao invés de se ter apenas um argumento, tem-se dois; um para o elemento a adicionar à lista e outro para a lista onde vai ser adicionado à cabeça. Assim pode-se concluir que se deve criar um predicado com aridade um quando o gerador é constante e uma cláusula quando o gerador tem
4. ABORDAGEM PROPOSTA/SOLUÇÃO 4.7. Modelo de transformação
argumentos. O nome do functor da cabeça é, nesse caso, o nome do sort do resultado, e contém um functor com tantas variáveis quantas os argumentos do gerador; variáveis essas que devem ser restringidas quanto ao seu sort no corpo da cláusula.
cons : nat list -> list list(cons(X1,X2)):-nat(X1), list(X2).
$L)
‘ ’).
7 8
Figura 4.5: Transformação do gerador
Para a transformação dos geradores são assim necessárias regras para as seguintes tarefas:
• criação de um objecto Clause por cada gerador • criação de um objecto Head para a Clause • criação de um objecto Body para a Clause • criação do functor com o nome do gerador (A)
• criação do functor com o nome do sort do resultado (B)
• criação de variáveis por cada argumento do gerador, para colocar em Head (V) • criação de functores por cada argumento do gerador, para colocar em Body (FV) • relacionar Clause com Head
• relacionar Clause com Body • relacionar Functores (A) e (B)
• relacionar Functores (FV) com as Variáveis respectivas (V) • relacionar object Clause com o objecto Model
Tendo já sido definidas as regras para os geradores de um ADT, observe-se a figura 4.6. A formulação empírica presente na regra corresponde à transformação de um axioma sobre uma operação de um ADT.
Este é um axioma sobre a operação♥❜❖❝✉rr que pode ser aplicado quando se veri- fica a condição a azul. Em cima, a laranja, tem-se o lado esquerdo da regra e a vermelho a reescrita dos termos que estão à esquerda.
4. ABORDAGEM PROPOSTA/SOLUÇÃO 4.7. Modelo de transformação
eq ($E, $H) = false => nbOcurr ($E, cons($H, $L)) = nbOcurr($E, $L)
:- nat(E), nat(H), list(L) ,
eval(nbOcurr(E, cons (E, H)), R)
eval(eq(E, H), R1), eval(false, R1),
eval(nbOcurr(E, H), R) .
‘ ’).
Figura 4.6: Transformação dos axiomas das operações
Posto isto, na transformação de um axioma deve ser criada uma cláusula. Nesta cláusula, a cabeça deve ser um functor com nome ’❡✈❛❧’ que tem como primeiro ar- gumento aquilo que se pretende reescrever e como segundo argumento uma variável que conterá o resultado da avaliação/redução do primeiro. Em particular, doravante, os functores ’❡✈❛❧’ funcionam sempre desta forma.
O corpo da cláusula deve conter nesta ordem, os functores que restringem o sort dos elementos envolvidos na operação seguidos de functores ’❡✈❛❧’ para ambos os mem- bros das equações das condições do axioma. Neste caso adiciona-se um functor ’❡✈❛❧’ que deve avaliar ❡q✭❊✱❍✮ e colocar o resultado numa variável (R1) e coloca-se outro functor que avalia❢❛❧s❡ e tenta unificar R1 para ambos os predicados. Por fim coloca- se um functor ❡✈❛❧ que avalia o lado direito da equação do axioma e que unificará o resultado com R (que é o resultado do lado esquerdo). Se houvesse mais condições, os respectivos predicados deveriam ser postos antes deste functor para que as condições fossem todas avaliadas previamente.
A esta estratégia há pelo menos duas adições a fazer. Em caso de condições que sejam inequações é necessário que para ambos os resultados (lado esquerdo e direito) sejam criadas variáveis diferentes, e garantir que elas não unificam (e.g. R1\=R2, em que R2 é a variável correspondente ao lado direito e R1 ao lado esquerdo).
A segunda adição tem que ver com o facto de os geradores terem que poder ser avaliados. Por exemplo em❡✈❛❧✭❢❛❧s❡✱❘✶✮, onde consta o gerador ❢❛❧s❡ dos booleanos, quer-se que R1 unifique com❢❛❧s❡, mas se um fosse um natural (e.g. eval(suc(X),R2)) querer-se-ia que R2 unificasse com suc(X), em que X já estivesse avaliado. Foi para este efeito que se criaram regras que resolvem os exemplos das figuras 4.7 e 4.8, as quais serão explicadas em seguida.
Posto isto foram criadas regras para o seguinte:
• Criação de Clause para cada CondEquation (Axioma) • Criação de Body e Head para cada CondEquation
4. ABORDAGEM PROPOSTA/SOLUÇÃO 4.7. Modelo de transformação
• Criação de functores eval para cada lado de uma equação ou inequação • Criação de variáveis para as variáveis envolvidas num axioma
• Criação de variáveis para os diversos resultados
• Criação de functores que representem os CTerm (e.g. suc(suc(zero))) • Criação das relações nextTerm entre ConditionAtom (Condições) • Criação de functores para restringir o sort de cada variável
• Criação de functores ’eval’ para os geradores tal como indicado nas figuras 4.7 e 4.8.
zero -> nat eval(zero,zero).
$L)
‘ ’).
1
Figura 4.7: Transformação do gerador
suc :nat -> nat eval(suc(X1),suc(XX1)):-eval(X1,XX1).
$L)
‘ ’).
Figura 4.8: Transformação do gerador
Por fim, tem-se regras para transformar a especificação das intenções de teste. O código Prolog pretendido para a transformação dos axiomas das intenções de teste é muito similar ao código pretendido para os axiomas dos ADT. Exceptua-se apenas pelo facto de as intenções de teste poderem dar origem a cláusulas sem corpo, como no caso da figura 4.9.
HML(T) in TickIntention in ( [top], ‘TickIntention’).
1 2
3
Figura 4.9: Transformação das intenções de teste
Em relação aos axiomas das intenções de teste quer-se que estes resultem numa cláusula cuja cabeça é um functor ’✐♥’ (fluxo 1 da figura 4.9), com aridade 2, cujos ar- gumentos são primeiramente uma lista com o padrão de execução do sistema (fluxo
4. ABORDAGEM PROPOSTA/SOLUÇÃO 4.7. Modelo de transformação
2), e o segundo é um quoted atom com o nome da intenção (fluxo 3). Caso existam con- dições os correspondentes functores ’❡✈❛❧’ devem ser colocados no corpo da cláusula (e.g. condições a azul e a verde na figura 4.10).
O padrão de execução pode conter o objecto❍▼▲❚♦♣ (que se representará com um functort♦♣ sem argumentos) e eventos que devem ser representados por um par orde- nado em que o primeiro elemento é um functor correspondente ao método de input e o segundo é um functor correspondente à gate de output; ambos podem conter argu- mentos correspondentes aos do método e da gate, respectivamente (e.g. a sublinhado na figura 4.10).
{lt($Counter, suc^3(zero))} = {t r u e} , $t in TickIntention
=>
$t . HML( { <mark with time($Counter ) > } T ) inMarkIntention ;
in([T,(mark,time(Counter)),top], 'MarkIntention'):- in(F,'TickIntention'),
flatten(F,T),
eval(algEquality(lt(Counter,suc(suc(suc(zero)))), true), true).
‘ ’). 1 2 3 4 5
Figura 4.10: Transformação das intenções de teste
Assim se conclui, que em relação à transformação das intenções de teste é necessá- rio criar regras para o seguinte:
• Criação do functor ’in’ para cada axioma
• Criação da lista que contém o padrão de execução
• Criação de um ’QuotedAtom’ referente ao nome da intenção • Criação de functor eval para ConditionAtom (Condições)
• A cada Inclusion que seja ConditionAtom deve estar associado o predicado flat- ten
• O necessário para transformar CompositeTerm (e.g. suc(suc(zero))). É equiva- lente aos CTerm no contexto das intenções de teste
• O necessário para construir todo o ConditionAtom
• Criação de todas as relações necessárias para associar os objectos 70
4. ABORDAGEM PROPOSTA/SOLUÇÃO 4.7. Modelo de transformação