Carregar apresentação
A apresentação está carregando. Por favor, espere
PublicouJoão Henrique Fidalgo Brandt Alterado mais de 7 anos atrás
1
jpf@fe.up.pt www.fe.up.pt/~jpf
Métodos Formais em Engenharia de Software Especificação Algébrica em CafeOBJ (1ª parte) João Pascoal Faria
2
Índice Funções e operadores parciais Equações condicionais
Operadores "mixfix" Igualdade (==) e equivalência (=) Espécies de erros Subespécies (subtipos) Módulos e tipos pré-definidos Como funciona a redução de expressões Exercícios Linguagens de especificação algébrica Exemplo: especificação da Stack em OBJ Instalação da ferramenta CafeOBJ Especificação da Stack em CafeOBJ Teste da especificação Módulos e espécies (tipos) Aspectos léxicos
3
Linguagens de especificação algébrica
Definem tipos de dados de forma abstracta A semântica das operações sobre os dados é definida através de uma colecção de relações de equivalência (axiomas equacionais) Não se define a forma como os dados são representados Exemplos: Linguagem OBJ e suas derivadas (OBJ1, OBJ2, OBJ3, CafeOBJ, Maude, etc.) Aplicáveis à especificação formal (e verificação formal) de Tipos abstractos de dados (abstract data types) (rever AED!) Interfaces (semelhantes a classes, mas só com operações, sem atributos)
4
Exemplo: especificação da Stack em OBJ
Spec: Stack; Extend Nat by Sorts: Stack; Operations: newstack: Stack push: Nat Stack Stack pop: Stack Stack top: Stack Nat Variables: s: Stack; n: Nat Axioms: pop(newstack) = newstack; top(newstack) = zero; pop(push(n, s)) = s; top(push(n, s)) = n;
5
Exemplo: especificação da Stack em OBJ
Uma instância de um tipo é sempre representada por uma expressão de construção push(3, push(2, push(1, newstack))) Axiomas permitem simplificar/avaliar expressões top(pop(push(2, push(1, newstack)))) = = top(push(1, newstack)) = 1
6
Instalação da ferramenta CafeOBJ
Aceder ao site Seleccionar o tab "download" Descarregar a versão binária (já compilada) mais recente para a plataforma pretendida: Mac OS X, i386-linux ou Windows, por exemplo Descompactar e instalar Colocar no "PATH" o directório onde foi instalado o CafeOBJ
7
Especificação da Stack em CafeOBJ
module STACK { imports { using (NAT) } signature { [ Stack ] op newstack : -> Stack op push : Nat Stack -> Stack op pop : Stack -> Stack op top : Stack -> Nat axioms { var X : Nat var S : Stack eq pop(push(X,S)) = S . eq top(push(X,S)) = X . eq pop(newstack) = newstack . eq top(newstack) = 0 . módulo importado (define o tipo Nat) espécie (tipo de dados) introduzida operações (funções) introduzidas e respectivas assinaturas (sintaxe) variáveis usadas nos axiomas (quantificadas universalmente) Fim da aula 20/9 (demo com stack1.mod) axiomas equacionais (definem a semântica das operações )
8
Teste da especificação (1)
Escrever especificação num ficheiro com um editor de texto Entrar no CafeOBJ - a partir de uma "shell" ou "command prompt", executar o comando "cafeobj" É mais prático executar o CafeOBJ a partir do directório onde temos os ficheiros com as especificações que queremos analisar Carregar especificação com "input stack.mod" ou simplesmente "input stack" (.mod assumido por omissão) Colocar corrente o módulo STACK com "select STACK"
9
Teste da especificação (2)
Avaliar / simplificar expressão com "reduce exp ." Não esquecer o espaço e ponto final no fim! Não esquecer espaços a separar todos os símbolos na expressão (a não ser quando se usam parêntesis e vírgulas) Sair do CafeOBJ com comando "quit" Estes comandos também se podem colocar num ficheiro de texto separado, por exemplo "teststack.mod" (ou outra extensão), que é executado com "input teststack.mod" no fim do próprio ficheiro com a definição do módulo a testar
11
Módulos e espécies (tipos)
O conceito de espécie (sort) corresponde ao conceito de tipo de dados Em CafeOBJ as especificações são organizadas em módulos e fisicamente armazenadas em ficheiros Um ficheiro pode conter mais do que um módulo Extensão por omissão é ".mod" Um módulo reúne as definições de um conjunto de operações relacionadas, envolvendo uma ou mais espécies (tipos de dados) Um módulo também pode ser usado apenas para introduzir o nome de uma espécie
12
Aspectos léxicos Comentários
Indicados com ** ou -- e vão até ao fim da linha Se indicados com **> ou -->, mostra no ecrã quando ficheiro é analisado Distingue minúsculas de maiúsculas (case sensitive) Convenções de nomes habituais maiúsculas para nomes de módulos e variáveis minúsculas para nomes de operadores nomes capitalizados para nomes de espécies Separadores e terminadores Axiomas e instruções "reduce" são terminados com " ." precedido de espaço Separador espaço necessário muito importante: operadores e variáveis têm de ser separados por espaço (ou então parêntesis e vírgulas) Nomes são definidos antes de serem usados
13
Funções e operadores parciais
Funções e operadores parciais (contrário de totais): não estão definidas para todos os valores do domínio Exemplos: Funções totais: push Funções parciais: pop, top (não estão definidos para a stack vazia) Operadores totais: multiplicação Operadores parciais: divisão (não está definida a divisão por zero) Como tratar: passar artificialmente a funções totais - ver "stack1.mod" sub-especificar – aconselhado - ver "stack2.mod" sinalizar erros explicitamente - ver "espécies de erros" adiante e "stack3.mod" restringir aplicação a subtipos – ver "subespécies" adiante e "stack4.mod" Qual o resultado ao avaliar / reduzir expressões? DEMO não reduz se não tiver axiomas que o permitam
14
Equações condicionais
Equações incondicionais eq left-hand-side = right-hand-side . Equações condicionais (conditional equations) ceq left-hand-side = right-hand-side if condition . Usadas normalmente para definir funções / operações parciais ou separar a definição de uma função / operação total por vários casos Exemplo do factorial: var N : Nat eq 0 ! = 1 . ceq N ! = N * ((N - 1) !) if N > 0 .
15
Operadores "mixfix" Operações: funções ou operadores
Operadores: Usar sinal sublinhado "_" como placeholder para argumento junto ao símbolo do operador ao introduzir a operação Exemplos (espaços opcionais em torno do símbolo): op _+_ : Int Int -> Int soma (infixo) (exemplificado sem espaços) op _ - _ : Int Int -> Int subtracção (infixo) (exemplificado com espaços) op - _ : Int -> Int -- simétrico (prefixo) op _ ! : Nat -> Nat -- factorial (posfixo) op _ mod _ : Int Int -> Int -- resto da divisão inteira (infixo) op max : Int Int -> Int -- função Utilização (espaços geralmente obrigatórios) 1 + 2 1 – 2 - 4 4 ! 4 mod 3 max(4, 3) Cuidado: Uma vez que "_" tem este significado especial, o nome de uma operação não pode incluir "_" !
16
Igualdade (==) e equivalência (=)
Equivalência (=) : usado nos axiomas equacionais, define uma relação de equivalência Igualdade (==) : usado nas expressões para testar a igualdade do lado esquerdo e o lado direito Exemplo – formas equivalentes: ceq equal(X, Y) = true if X == Y . ceq equal(X, Y) = false if not X == Y . eq equal(X, Y) = (if X == Y then true else false fi) . eq equal(X, Y) = (X == Y) . Desigualdade: not (a == b) ou a =/= b
17
Espécies de erros (error sorts)
Para cada espécie S definida é definida automaticamente uma espécie de erro ?S Erros podem ser representados por constantes (funções sem argumentos) do tipo ?S op empty-stack-exception : -> ?Stack
18
Espécies de erros – Exemplo da Stack
module STACK { imports { using (NAT) } signature { [ Stack ] op newstack : -> Stack op push : Nat Stack -> Stack op pop : Stack -> Stack op top : Stack -> Nat op pop-empty-stack : -> ?Stack op top-empty-stack : -> ?Nat axioms { var X : Nat var S : Stack eq pop(push(X,S)) = S . eq top(push(X,S)) = X . eq pop(newstack) = pop-empty-stack . eq top(newstack) = top-empty-stack . select STACK reduce pop(newstack) . --> pop-empty-stack : ?Stack reduce top(newstack) . --> top-empty-stack : ?Nat reduce top(pop(newstack)) . --> top(pop-empty-stack) : ?Nat
19
Subespécies (Subtipos)
Uma espécie s' é uma subespécie de uma espécie s (chamada super-espécie) se o conjunto de valores de s' é um subconjunto dos valores de s e as operações de s estão disponíveis em s' (herança) Notação: signature { [ s' < s] } Exemplo de declarações equivalentes: [ Nat < Int < Rat ] [Nat < Int, Int < Rat] [Nat Int Rat, Nat < Int < Rat ] [Nat < Int, Int < Rat] Semelhante à noção de sub-classe em OO
20
Subespécies (Subtipos)
Útil para restringir a aplicação das operações aos tipos apropriados Princípio da substitutabilidade: onde se espera uma valor de um tipo, pode-se passar um valor de um sub-tipo, directo ou indirecto Uma espécie pode ter múltiplas super-espécies (herança múltipla) Podem-se redefinir as operações herdadas (overriding, overloading)
21
Subespécies – Exemplo da stack
module STACK { imports { protecting (NAT) } signature { [ EmptyStack NonEmptyStack < Stack ] op newstack : -> EmptyStack op push : Nat Stack -> NonEmptyStack op pop : NonEmptyStack -> Stack op top : NonEmptyStack -> Nat axioms { var X : Nat var X : Stack eq pop(push(X,S)) = S . eq top(push(X,S)) = X . select STACK red top(push(1, newstack)) . red pop(push(1,newstack)) . red pop(pop(push(1,push(0,newstack)))). red top(newstack) dá ?Nat red pop(newstack) . -- dá ?Stack
22
Subespécies – Exemplo abstracto
signature { [ s4 < s2 s3 < s1 , s5 < s1 , s6 ] s1 op f1 : ... -> s1 op f2 : ... -> s2 op f3 : ... -> s3 op f4 : ... -> s4 op f5 : ... -> s5 op f6 : ... -> s6 op g : s2 -> t } s3 s2 s6 s4 s5 Aceite antes de reduzir, mas não depois de reduzir argumento (*) g(f1(...)) g(f3(...)) (*) dá erro do tipo ?t BEM g(f2(...)) g(f4(...)) MAL g(f5(...)) g(f6(...))
23
Módulos e tipos pré-definidos (1)
Operações (3) Constantes BOOL (2) Bool not and and-also xor or or-else implies iff true false NAT Nat NzNat Zero * >= > <= < quo (quociente) rem (resto) divides s (sucessor) p (predecessor) INT Int Idem, mais - (subtracção) e – (simétrico) -2 ... FLOAT Float * / < <= > >= exp log sqrt abs sin atan etc. pi STRING String string= string> string< string>= string<= length substring (concatenar) upcase downcase etc. "uma string" ... (1) Consultar no manual ou com comando "show nome-do-módulo" (2) O módulo BOOL é automaticamente importado (3) Algumas operações primitivas são definidas por chamadas a Lisp com "#!" como em eq M + N = #! (+ m n).
24
Como funciona a redução de expressões?
Axiomas equacionais são usados como regras de restrita Motor de execução funciona como um Sistema de Rescrita de Termos (Term Rewriting System) Dada uma expressão a reduzir (termo sem variáveis), o sistema procura fazer match com o lado esquerdo dum axioma (instanciando assim as variáveis do axioma), e substitui a expressão pelo lado direito do axioma com as variáveis instanciadas No caso de equações condicionais, depois de fazer "match", tem ainda de verificar se a condição é satisfeita O processo repete-se até não haver mais axiomas aplicáveis Os axiomas devem ser escritos por forma a garantir: terminação - ausência de caminhos infinitos (e ciclos) determinismo (confluência) - se num dado momento foram aplicáveis várias regras de rescrita, o resultado final não deve depender da regra que se escolhe
25
Como funciona a redução de expressões?
-- subtraccao de numeros naturais -- à custa do sucessor module SUB { imports { using (NAT) } signature { [Nat] op _ - _ : Nat Nat -> Nat axioms { vars N M : Nat -- caso base eq N - N = 0 . -- caso recursivo ceq N - M = s(N - s(M)) if N > M . select SUB reduce 5 – 4 . reduce 3 – 5. 5 - 3 (2) [5 > 3] s(5 – s(3)) (2) [5 > s(s(3))] (3) s(5 – 4) s(s(5 – s(s(3))) (2) s(s(5 – s(4)) Este caminho não é percorrido, pois reduz primeiro os argumentos! (3) s(s(5 – 5)) (1) (1) (2) s(s(0)) (3) s(1) (3) (3) eq s(N) = #! (+ n 1) (ver NAT) 2
26
Exercícios a resolver na aula teórica
Experimentar diferentes definições da subtracção de números naturais Especificar o tipo abstracto de dados Queue (Fila), com operações para criar uma fila vazia (newqueue) inserir um elemento (String) na cauda da fila (enqueue) obter o elemento que está à cabeça da fila (front) remover o elemento que está à cabeça da fila (dequeue) verificar se a fila está vazia (is-empty) Especificar uma fila com prioridades (PriorityQueue) ao inserir um elemento indica-se a prioridade (numérica) esse elemento passa à frente de elementos com menor prioridade
27
Referências e leituras adicionais
Specification of Software Systems, V.S. Alagar and K. Periyasamy, ISBN: , Springer, (capítulo 8) Introducing OBJ, Joseph A. Goguen, Timothy Winkler, José Meseguer, Kokichi Futatsugi, JeanPierre Jouannaud ( ) CafeOBJ official home page ( download doc (manual.ps) Manual de CafeOBJ
Apresentações semelhantes
© 2025 SlidePlayer.com.br Inc.
All rights reserved.