Especificação de ação para uma calculadora simples

De Augusto Baffa Wiki
Revisão de 18h39min de 7 de novembro de 2020 por Abaffa (discussão | contribs)
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)
Ir para navegação Ir para pesquisar
fig. 8.1

Considere a seguinte especificação um plano de ação para uma calculadora simples.

Requisitos informais ou intenções ...

  1. O aplicativo deve ser gráfico e ter uma aparência semelhante a esta (da fig. 8.1).
  2. Os botões devem estar "ativos" e os botões pressionados realmente ativam as funções da calculadora.
  3. Um acumulador interno mantém um valor total em execução refletindo as operações que foram feitas até agora durante o uso da calculadora.
  4. Um sinalizador de operador indica qual é a operação pendente que será realizada assim que outro operando for inserido.
  5. A área de exibição mostra o último numeral que foi inserido, o valor da memória que é recuperado usando 'MR' ou o valor total calculado até agora quando as teclas '=' ou 'M+' são pressionadas.
  6. A memória da calculadora contém um valor, inicialmente zero. É alterado pelas teclas 'M+' e 'MR'.

Domínios...

Button --> Digit | Arithmetic_Operator | Memory_Operator | Clear | Equal
Digit --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
Numeral --> Digit | Numeral Digit
Arithmetic_Operator --> plus | minus | times | plus_minus
Memory_Operator --> mem_plus | mem_rec
Clear --> clear
Equal --> equal
Mode --> init | cont

Propriedades mutáveis

accumulator(N)   where N is Numeral  
op(F)            where F is Arithmetic_Operator  
displayed(D)     where D is Numeral  
memory(M)        where M is Numeral  
mode(C)          where C is Mode

Ações

push(B)          where B is Button

Animador de Ações

Animator --> Show_Action | Show_Action Animator
Show_Action --> Action Show
Show --> ...

Especificações de Ações

Os registradores da calculadora são modelados como uma 4-tupla [a,op,d,m] onde...

accumulator(a)
op(op)
displayed(d)
memory(m)

declara (ou expressa) os valores "verdadeiros" atuais dessas propriedades mutáveis.

Uma ação muda os valores desses quatro registradores, ou seja, uma ação mudao estado verdadeiro ou falso das propriedades mutáveis ...

[a,op,d,m] -- Action --> [a',op', d', m'] 

or 

Action < - {preconditions},
             deny({old properties}), 
             {local calculations}, 
             affirm({new properties}).

As especificações são fornecidas em dois formulários. A primeira é uma expressão de resumo mais intuitiva, a segunda é a especificação de ação formal ...

action_module(calculator) .


%[-,-,d1,-] --push(D)-->          [-,-,D,-]  if mode(init)  
push(D) < - 
  mode(init), 
  deny([displayed(D1),mode(init)]), 
  affirm([displayed(D),mode(cont)]).
  
%[-,-,D1,-] --push(D)-->          [-,-,10*D1+D,-]  if mode(cont) 
push(D) < - 
  mode(cont), 
  deny(displayed(D1)), 
  New = 10*D1 + D, 
  affirm(displayed(New)). 

%[a,op,d,m] --push(clear)-->      [0,nop,0,0] 
push(clear) < -
  deny([accumulator(A),op(O),displayed(D),memory(M),mode(X)]), 
  affirm([accumulator(0),op(nop),displayed(0),memory(0),mode(init)]). 

%[a,op,d,m] --push(mem_rec)-->    [a,op,m,m] 
push(mem_rec) < -
  memory(M), 
  deny([displayed(D),mode(X)]), 
  affirm([displayed(M),mode(init)]). 

%[a,op,d,m] --push(plus)-->       [op(a,d),plus,d,m] 
push(plus) < -
  displayed(D), 
  deny([accumulator(A),op(O),mode(X)]),  
  eval(O,A,D,V),   ; use normal arithmetic, i.e., V=O(A,D)  
  affirm([accumulator(V),op(plus),mode(init)]).  
 
%[a,op,d,m] --push(minus)-->      [op(a,d,minus,d,m] 
push(minus) lt -
  displayed(D), 
  deny([accumulator(A),op(O),mode(X)]), 
  eval(O,A,D,V),   ; use normal arithmetic, i.e., V=O(A,D) 
  affirm([accumulator(V),op(minus),mode(init)]). 

%[a,op,d,m] --push(times)-->      [op(a,d),times,d,m] 
push(times) < -
  displayed(D), 
  deny([accumulator(A),op(O),mode(X)]), 
  eval(O,A,D,V),   ; use normal arithmetic, i.e., V=O(A,D) 
  affirm([accumulator(V),op(times),mode(init)]). 

%[a,op,d,m] --push(equal)-->      [a,nop,op(a,d),m] 
push(equal) < -
  accumulator(A), 
  deny([op(O),displayed(D),mode(X)]), 
  eval(O,A,D,V), 
  affirm([op(nop),displayed(V),mode(init)]). 

%[a,op,d,m] --push(mem_plus)-->   [a,nop,v,plus(m,v)] where v=op(a,d) 
push(mem_plus) < -
  accumulator(A), 
  deny([op(O),displayed(D),memory(M),mode(X)]), 
  eval(O,A,D,V), 
  eval(plus,M,V,V1), 
  affirm([op(nop),displayed(V),memory(V1),mode(init)]).

%[a,op,d,m] --push(plus_minus)--> [a,op,-d,m] 
push(clear) < -
  deny([displayed(D),mode(X)]), 
  eval(minus,0,D,V), 
  affirm([displayed(V),mode(init)]).

Uma tradução bastante direta das cláusulas de ação fornece um protótipo do Prolog.


Exercício 8.1 Estenda a especificação da calculadora para aritmética real, implemente a especificação e teste a implementação.


Veja Também