Validação Formal de Documentos Hipermídia usando Verificação de Modelos
description
Transcript of Validação Formal de Documentos Hipermídia usando Verificação de Modelos
Universidade Candido Mendes
Curso de Ciência da Computação
Validação Formal de Documentos Hipermídia
usando Verificação de Modelos
José Carlos Rocha Pereira Júnior
Campos dos Goytacazes - RJ
2003
Universidade Candido Mendes
Curso de Ciência da Computação
Validação Formal de Documentos Hipermídia
usando Verificação de Modelos
José Carlos Rocha Pereira Júnior
Monografia apresentada à banca de
projeto final do Curso de Ciência da
Computação da Universidade Candido
Mendes como parte dos requisitos para
obtenção do grau de Bacharel em
Ciência da Computação.
Prof. Marcelo Fagundes Felix
(orientador)
Campos dos Goytacazes - RJ
25 de Setembro de 2003
Universidade Candido Mendes
Curso de Ciência da Computação
Validação Formal de Documentos Hipermídia
usando Verificação de Modelos
José Carlos Rocha Pereira Júnior
Defesa de Monografia de Conclusão de Curso para
obtenção do Título de Bacharel em Ciência da Computação
da Universidade Candido Mendes.
Campos dos Goytacazes, ....... de ............................. de ...............
Banca Examinadora:
..............................................................
Prof. Dr. Marcelo Fagundes Felix
..............................................................
Prof. MSc. Marcelo Machado Feres
..............................................................
Prof. Dr. Rogério Atem de Carvalho
Média Final: …......
Dedicatória
Em memória de meus avós Abílio Alves Pereira, Sebastiana
Rocha Pereira e Antônio Ferreira de Medeiros que gostariam de
estar próximos a mim na conclusão deste curso.
Agradecimentos
A Deus por me dar forças para conseguir chegar até aqui.
Aos meus pais pelo apoio e esforço.
Ao Professor Marcelo Fagundes Felix pela orientação.
A todos os professores da Universidade Candido Mendes que foram responsáveis pela minha
formação.
A todos os meus colegas do curso de Ciência da Computação.
À Universidade Candido Mendes pelo suporte financeiro sem o qual, talvez, não pudesse
concluir meus estudos.
Resumo
Devido a uma grande quantidade de sistemas de tempo real serem utilizados em
aplicações críticas, o processo de teste e validação de tais sistemas torna-se um fator essencial.
Por dificuldades em testar requisitos temporais nesses sistemas, as técnicas tradicionais não são
eficazes então, um método formal de validação denominado Verificação de Modelos tem sido
amplamente utilizado.
Documentos hipermídia podem ser vistos como um caso peculiar de aplicação de tempo
real onde se deseja garantir que a apresentação das diversas mídias que os compõem se dê de
forma sincronizada, conforme sua especificação.
Neste trabalho, apresentamos as bases de uma metodologia de validação formal para a
apresentação de documentos hipermídia, onde mostramos como criar uma “ponte” entre a
especificação do sistema hipermídia e o respectivo modelo formal sobre o qual aplicamos a
técnica de validação escolhida. O método desenvolvido consiste em, dada uma especificação
de documento hipermídia, extrair dela um modelo de semântica operacional (Autômatos
Temporizados) que permita a validação formal utilizando-se algum verificador de modelos. A
obtenção do modelo de autômatos é automática e baseada em métodos transformacionais. O
processo de validação dos requisitos de projeto é interativo, permitindo realimentar o autor do
documento com informações para a correção da especificação inicial.
Palavras chaves: documentos hipermídia, transformação de código, validação formal,
Verificação de Modelos.
i
Sumário
Capítulo 1 – Introdução
1. Motivação ....................................................................................................................... 01
2. Documentos Hipermídia ................................................................................................. 02
3. Sistemas de Tempo Real ................................................................................................. 03
4. Métodos Formais ............................................................................................................ 04
4.1. Verificação de Modelos .................................................................................... 05
4.2. Prova de Teoremas ........................................................................................... 06
5. Lógica Modal .................................................................................................................. 07
6. Metodologia .................................................................................................................... 08
Capítulo 2 - NCM: Um Modelo Conceitual Hipermídia
1. Introdução ....................................................................................................................... 10
2. Conceitos do NCM ......................................................................................................... 11
3. Uma Descrição Formal para o NCM ............................................................................... 15
4. Exemplo ......................................................................................................................... 17
Capítulo 3 - UPPAAL: Um Verificador de Modelos
1. Introdução ....................................................................................................................... 19
2. Apresentação .................................................................................................................. 20
3. Utilização ....................................................................................................................... 22
3.1. Modelagem ...................................................................................................... 22
3.2. Simulação ......................................................................................................... 26
3.3. Verificação ....................................................................................................... 27
4. Exemplos ........................................................................................................................ 28
4.1. Exemplo Elucidativo ........................................................................................ 29
4.2. Exemplo Elevador ............................................................................................ 31
4.3. Exemplo Cruzamento ....................................................................................... 32
ii
Capítulo 4 - Validação de Documentos Hipermídia
1. Introdução ....................................................................................................................... 34
2. Modelando Documentos Hipermídia em UPPAAL ......................................................... 34
2.1. Exemplo ............................................................................................................ 35
2.2. Validação do Modelo ....................................................................................... 40
Capítulo 5 - TXL: Uma Introdução à Programação Transformacional
1. Introdução ....................................................................................................................... 42
2. Instalação, Configuração e Execução .............................................................................. 43
3. Parsing ............................................................................................................................ 44
4. A Fase de Transformação ................................................................................................ 46
4.1. Funções Embutidas ........................................................................................... 49
4.2. Variáveis .......................................................................................................... 51
4.3. Condições ......................................................................................................... 53
4.4. Regras ou Função de Condição ......................................................................... 55
5. Formatação ..................................................................................................................... 56
6. MGM versus MGA ......................................................................................................... 57
7. O Tradutor SIM2C .......................................................................................................... 58
Capítulo 6 - O Tradutor NCL2TA
1. Introdução ....................................................................................................................... 60
2. O Meta-Modelo Hipermídia em UPPAAL ...................................................................... 60
3. Uma Metodologia de Tradução da NCL para TA ............................................................ 64
4. Validação do documento hipermídia ............................................................................... 67
Capítulo 7 - Considerações Finais
1. Revisão Final .................................................................................................................. 71
2. Trabalho Relacionado ..................................................................................................... 71
2.1. RT-LOTOS: Conceitos Básicos ........................................................................ 72
3. Trabalhos Futuros ........................................................................................................... 74
3.1. Hipermídia e a Arquitetura de Software ............................................................ 74
iii
Referências ........................................................................................................................ 76
Anexo A – O Tradutor SIM2C
A.1 - Código do Tradutor SIM2C ....................................................................................... 78
A.2 – Exemplos .................................................................................................................. 81
A.2.1 - Divisão de Números Naturais ...................................................................... 81
A.2.2 - Multiplicação de Números Naturais ............................................................. 82
Anexo B – O Tradutor NCL2TA
B.1 – Código do Tradutor NCL2TA ................................................................................... 83
B.2 – Exemplo ..................................................................................................................... 97
I – Código em NCL ................................................................................................. 97
II - Resultado da Transformação em TA .................................................................. 97
Anexo C – Introdução a Arquitetura de Software
C.1 – Introdução ................................................................................................................. 101
C.2 – A Arquitetura de Software ......................................................................................... 102
C.3 – Linguagens de Descrição Arquitetural ....................................................................... 104
iv
Figuras e Tabelas
Capítulo 1 - Introdução
Figura 1.1 – Exemplo de STR ........................................................................................... 03
Figura 1.2 - Validação de Documentos Hipermídia ........................................................... 08
Figura 1.3 - Validação de Documentos Hipermídia utilizando um tradutor para extração
de modelos de autômatos temporizados ............................................................................ 09
Capítulo 2 - NCM: Um Modelo Conceitual Hipermídia
Figura 2.1 – Nós terminais de um modelo exemplo ........................................................... 12
Figura 2.2 – Nó de composição de um modelo exemplo .................................................... 12
Figura 2.3 – Âncoras de um modelo exemplo ................................................................... 13
Figura 2.4 – Elos de um modelo exemplo ......................................................................... 13
Figura 2.5 – Máquina de estados dos eventos .................................................................... 14
Figura 2.6 – Exemplo de documento hipermídia ............................................................... 17
Capítulo 3 - UPPAAL: Um Verificador de Modelos
Figura 3.1 – GUI da ferramenta UPPAAL apresentando a guia System Editor .................. 21
Figura 3.2 – Caixa de diálogo Edit Location ..................................................................... 22
Figura 3.3 – Caixa de diálogo Edit Transition ................................................................... 23
Figura 3.4 – Formas de modelagem .................................................................................. 25
Figura 3.5 – GUI da ferramenta UPPAAL apresentado a guia Simulator ............................ 26
Figura 3.6 – GUI da ferramenta UPPAAL apresentado a guia Verifier .............................. 27
Figura 3.7 – Sintaxe para formulação de consultas em UPPAAL ...................................... 28
Figura 3.8 – Modelo elucidativo ....................................................................................... 29
Tabela 3.1 – Verificação do modelo elucidativo ................................................................ 30
Figura 3.9 – Modelo elevador ........................................................................................... 31
Tabela 3.2 – Verificação do modelo elevador .................................................................... 32
Figura 3.10 – Modelo cruzamento ..................................................................................... 32
Tabela 3.3 – Verificação do modelo cruzamento. .............................................................. 33
v
Capítulo 4 - Validação de Documentos Hipermídia
Figura 4.1 – Mapeamento do NCM em autômatos ............................................................ 35
Figura 4.2 – Autômato Usuário ......................................................................................... 35
Figura 4.3 – Autômato do evento E1 ................................................................................. 36
Figura 4.4 – Autômato do evento E2 ................................................................................. 36
Figura 4.5 – Autômato do evento E3 ................................................................................. 36
Figura 4.6 – Autômato do evento E4 ................................................................................. 37
Figura 4.7 – Autômato do evento E5 ................................................................................. 37
Figura 4.8 – Autômato do evento E6 ................................................................................. 37
Figura 4.9 – Autômato do evento E7 ................................................................................. 38
Figura 4.10 – Autômato do evento E8 ............................................................................... 38
Figura 4.11 – Autômato do elo L1 .................................................................................... 38
Figura 4.12 – Autômato do elo L2 .................................................................................... 39
Figura 4.13 – Autômato do elo L3 .................................................................................... 39
Figura 4.14 – Autômato do elo L4 .................................................................................... 39
Figura 4.15 – Autômato do elo L5 .................................................................................... 40
Figura 4.16 – Especificações do sistema ........................................................................... 40
Tabela 4.1 – Verificação do modelo elucidativo ................................................................ 41
Capítulo 5 - TXL: Uma Introdução à Programação Transformacional
Figura 5.1 – Fases da transformação ................................................................................. 43
Figura 5.2 – Exemplo de definição de um não-terminal ..................................................... 44
Figura 5.3 – Alguns tipos não-terminais pré-definidos em TXL ........................................ 45
Figura 5.4 - Alguns modificadores em TXL ...................................................................... 45
Figura 5.5 – Exemplo de gramática ................................................................................... 46
Figura 5.6 – Sintaxe da regra e função .............................................................................. 47
Figura 5.7 – Exemplo de regra e função ............................................................................ 47
Figura 5.8 – Exemplo de função de busca ......................................................................... 48
Figura 5.9 – Exemplo de função com parâmetro ............................................................... 48
Figura 5.10 – Exemplo de aplicação do each ..................................................................... 49
Figura 5.11 – Exemplo de regra de um passo .................................................................... 49
vi
Figura 5.12 – Algumas funções embutidas ........................................................................ 50
Figura 5.13 – Exemplo com construct e deconstruct .......................................................... 51
Figura 5.14 – Exemplo de função com parâmetro ............................................................ 52
Figura 5.15 – Sintaxe da cláusula export e import ............................................................. 52
Figura 5.16 – Exemplo de código com import e export ..................................................... 53
Figura 5.17 – Condições ................................................................................................... 53
Figura 5.18 – Exemplo com condição ............................................................................... 54
Figura 5.19 – Exemplo de regras de transformação ........................................................... 54
Figura 5.20 – Exemplo de função de condição .................................................................. 55
Figura 5.21 – Exemplo utilizando função transformacional ............................................... 56
Figura 5.22 – Alguns não-terminais de formatação da saída .............................................. 56
Figura 5.23 – Exemplo de declaração compounds ............................................................. 57
Figura 5.24 – Instruções da linguagem SIMPLES ............................................................. 58
Figura 5.25 – Mapeamento SIMPLES para C .................................................................... 59
Capítulo 6 - O Tradutor NCL2TA
Figura 6.1 – O autômato User ........................................................................................... 61
Figura 6.2 – O autômato dos Eventos de Seleção .............................................................. 61
Figura 6.3 – O autômato dos Eventos de Apresentação ..................................................... 61
Figura 6.4 – O autômato Delay ......................................................................................... 62
Figura 6.5 – O autômato Broadcast ................................................................................... 62
Figura 6.6 – Autômato dos Elos ........................................................................................ 63
Figura 6.7 – Par Condição-Ação dos Elos ......................................................................... 64
Figura 6.8 – Gramática dos nós de apresentação e seleção ................................................ 65
Figura 6.9 – Modelo criado pelo tradutor NCL2TA .......................................................... 66
Figura 6.10 – Modelo criado pelo tradutor NCL2TA corrigido manualmente .................... 67
Figura 6.11 – Gráfico temporal dos eventos ...................................................................... 68
Figura 6.12 – Simulação exibindo uma situação de deadlock ............................................ 69
Capítulo 7 - Considerações Finais
Figura 7.1 – O modelo NCM em RT-LOTOS ................................................................... 73
Figura 7.2 – Relacionamentos entre Hipermídia e Arquitetura .......................................... 74
Figura 7.3 – Mapeamento de estruturas de arquiteturas em TA ......................................... 75
1
Capítulo 1
Introdução
1. Motivação
Documentos hipermídia podem ser vistos como um caso peculiar de aplicação de tempo
real onde se deseja manter a estrutura lógico-temporal do documento, ou seja, garantir as
relações de cooperação e coordenação entre as diversas mídias que os compõem [Santos et al.,
1998] segundo sua especificação.
Através de um verificador de modelos (model-checker) de tempo real, é possível garantir
a consistência temporal1 do documento especificado, numa fase inicial do processo de
desenvolvimento, reduzindo o custo de projeto e manutenção. Essa abordagem ajuda a tornar o
processo de desenvolvimento mais rápido e eficiente, uma vez que assim, evitamos a etapa de
teste sistemático que, além de tediosa e lenta, pode se tornar inaplicável quando o sistema
desenvolvido guarda aspectos de tempo-real.
O presente trabalho propõe uma metodologia formal para a validação dos requisitos de
projeto de sistemas hipermídia. A partir do desenvolvimento de um tradutor, implementado na
linguagem transformacional TXL2, é possível extrair da especificação do documento, escrita
em uma Linguagem de Contextos Aninhados (NCL), um modelo de autômatos temporizados
que indica o comportamento temporal da apresentação especificada. Especificações em NCL
seguem o Modelo de Contextos Aninhados (NCM) para definição e apresentação de
composições3 hipermídia. Com o modelo de autômatos temporizados, é possível realizar
normalmente sua validação através da verificação de propriedades (requisitos de projeto)
utilizando um verificador de modelos como UPPAAL.
1 No escopo deste trabalho, um documento é dito consistente temporalmente [Santos et al., 1998] quando sua apresentação termina decorrido
um tempo finito após seu início.
2 Tree Xformation Language.
3 Fragmentos de informações ordenados logicamente.
2
2. Documentos Hipermídia
O advento de dispositivos de baixo custo para manipulação de mídias e sua integração a
computadores permitiram a criação de documentos multimídia (composições de diferentes
mídias).
Em 1945 foi criado o conceito de hipertexto definido como fragmentos de texto,
conectados entre si por elos, associados a âncoras (regiões marcadas dentro do texto).
Atualmente, o conceito de hipertexto é bastante difundido através da HTML (Hypertext
Markup Language), linguagem utilizada para criação de páginas Web.
A aplicação da estrutura hipertexto aos documentos multimídia gerou o que
denominamos documentos hipermídia. Assim, o conceito de hipermídia corresponde a do
hipertexto, mas aplicado a outros tipos de mídia além de texto. Na estrutura hipertexto, os elos
capturam a noção de relacionamento de sincronismo4 espaço-temporal.
A composição hipermídia implica na descrição de seus componentes, da estrutura do
documento e da forma como estes componentes devem ser apresentados. Estas descrições
podem ser representadas por um modelo conceitual de documentos.
Existem várias aplicações para hipermídia como tutoriais, vídeo-conferência,
monitoramentos cirúrgicos, jogos, entre outras. Podemos perceber, então, que nestas aplicações
o tempo em que as ações ocorrem pode ser fator determinante de qualidade. Por exemplo, não
seria interessante as ações dos objetos ou personagens de um jogo ocorrerem no momento
diferente ao qual foi especificado, o que poderia prejudicar sua qualidade. Desta forma,
podemos incluir os documentos hipermídia ao grupo de aplicações de tempo real onde as
diversas mídias que os compõem devem ser apresentadas de forma sincronizada conforme sua
especificação.
4 Ações que controlam relações durante uma tarefa, no caso, apresentação do documento.
3
3. Sistemas de Tempo Real
Os sistemas computadorizados de tempo real (STR) surgiram durante a segunda era da
evolução do software (1960-1970) e por muitos anos tiveram como seus principais usuários os
militares, mas atualmente está ao acesso de todos.
Segundo PRESSMAN [1995], “Sistemas de tempo real são sistemas que monitoram,
analisam e controlam eventos do mundo real”. Desta forma, o tempo de resposta destes
sistemas é um fator crítico, isto é, o sistema deve atender ao domínio do problema num tempo
determinado para não obter resultados desastrosos.
O tempo de resposta é o tempo que o sistema leva para detectar um evento e aplicar uma
ação. Esse tempo de resposta pode ser afetado por vários fatores, dentre eles podemos destacar
a mudança contextual que está relacionada com o tempo e o overhead para a troca de tarefas; a
latência de interrupção definida como o retardamento antes que esta troca seja realmente
possível; a velocidade de computação e o acesso à memória de massa.
Figura 1.1 – Exemplo de STR
A figura 1.1 representa uma máquina separadora de blocos que servirá como exemplo de
sistema de tempo real para facilitar a compreensão da importância do tempo nestes sistemas. A
máquina possui uma esteira que é alimenta por blocos pretos e brancos aleatoriamente. Logo
após 10 unidades de tempo (u.t.) na esteira, a cor do bloco é identificada por um sensor. Se o
bloco for preto, o sensor fornecerá um sinal ao removedor para retirar o bloco após 20 u.t.
passado à identificação. Caso contrário, o bloco continuará na esteira até chegar ao final do
4
processo. Neste exemplo, fica clara a importância do tempo, pois o bloco preto após ser
identificado pelo sensor deverá estar na posição e no momento certo para ser retirado, caso
contrário, o sistema será falho.
A aplicação de sistemas de tempo real se estende a diversas áreas do conhecimento e para
vários fins como: controle de tráfego aéreo, monitoração de batidas cardíacas, controle de
sinais de trânsito, controle de centrais telefônicas, jogos, vídeos, apresentação de documentos
hipermídia, entre outros.
Os sistemas de tempo real interagem continuamente com o ambiente em que se
encontram, ou seja, são sistemas reativos e contam com uma intensa concorrência de
processos. Esta concorrência aumenta o grau de complexidade para o desenvolvimento de tais
sistemas e como eles são utilizados em situações críticas, o seu projeto deve seguir a regras
especiais para garantir sua correção (correctness).
A técnicas tradicionais de teste de sistemas, como por inspeção, não são eficazes quando
aplicadas aos sistemas de tempo real devido às dificuldades introduzidas pelos requisitos de
tempo impostos para realização de uma tarefa (requisitos temporais). Estas técnicas não
garantem que os requisitos temporais sejam atendidos, ou seja, podemos verificar a rapidez da
execução de uma tarefa, mas a velocidade não garante que ela foi executada no tempo certo.
Para suprir essa necessidade, um método formal denominado Verificação de Modelos (model-
checking) tem sido amplamente utilizado.
4. Métodos Formais
Os sistemas de software mantêm-se crescendo em tamanho e complexidade. Muitos
sistemas de softwares grandes e complexos devem garantir certas propriedades funcionais
críticas como tempo-real, tolerância a falhas e desempenho. Provar que um dado sistema
satisfaz estas propriedades pode aumentar nossa confiança de que este sistema operará
corretamente e com segurança [WING & VAZIRI-FARAHANI, 1996]. Uma forma de
alcançar esta meta é através da utilização dos métodos formais que são linguagens, técnicas e
ferramentas com base matemática para especificação e verificação de sistemas. Os métodos
formais aumentam o nosso entendimento de um sistema por revelar inconsistências,
5
ambigüidades e não-inteireza que podem, até então, não ter sido detectadas [CLARKE &
WING, 1996].
No passado a utilização dos métodos formais era uma prática árdua, pois as notações
eram muito confusas, as ferramentas eram inadequadas ou difíceis de serem utilizadas,
existiam poucos estudos de casos e poucas pessoas para utilizá-los. Atualmente tem se visto
uma maior apreciação de pesquisadores e profissionais pela técnica que vem apresentando cada
vez mais estudos de casos e benefícios.
O método tradicional de se argumentar formalmente sobre software é a verificação do
programa através de sua especificação5 formal que utiliza uma linguagem com uma sintaxe e
semântica definida matematicamente. Duas técnicas de verificação de sistemas quanto às
propriedades desejadas são a Prova de Teoremas e a Verificação de Modelos.
4.1. Verificação de Modelos
É uma técnica que conta com a construção de um modelo de estados finitos6 de um
sistema e verificação se uma propriedade é satisfeita para este modelo através de uma busca
exaustiva, rudemente falando, que cobre todos os comportamentos dinâmicos do sistema.
Definindo mais formalmente, a Verificação de Modelos é uma técnica automática em que
dado um modelo de estados finitos M de um sistema e uma propriedade definida em alguma
notação formal (por exemplo, lógica temporal), sistematicamente verifica a validade da
propriedade. Em outras palavras, a ferramenta de Verificação de Modelos verifica se M |=
acontece. Se o modelo M contém algum erro, a verificação de modelos produzirá um contra-
exemplo que pode ser utilizado para localizar a fonte do erro [RUYS, 2001].
As ferramentas verificadoras de modelos têm tido grande sucesso em termos de
aplicações industriais [RUYS, 2001]. Razões para este sucesso se devem principalmente a
automação que reduz o nível de interação do usuário, tornando uma boa alternativa para
5 Especificação é o processo de descrição do sistema e suas propriedades desejadas [CLARKE & WING, 1996].
6 Modelo de estados finitos é um modelo matemático de sistema com um número finito e pré-definido de estados
ao qual é atribuído entradas e saídas discretas.
6
usuários com pouca experiência; e a rapidez da técnica que pode produzir respostas em poucos
minutos.
A grande desvantagem desta técnica encontra fundamento no problema da explosão de
estados que provém de sistemas que são compostos por muitos processos paralelos.
Introduzindo uma representação simbólica de um conjunto de estados, relações de transição e
usando um procedimento simbólico de Verificação de Modelos, sistemas com espaço de
estados exponencial podem ser verificados com tempo e espaço polinomiais em relação ao
número de componentes do sistema. Este fator impõe limites à técnica acarretando o não
tratamento de muitos problemas reais.
Um método óbvio de tentar evitar o problema de explosão de estados é utilizar a
decomposição natural do sistema. O objetivo é verificar propriedades de componentes
individuais, inferindo que estas acontecem no sistema completo o que pode fornecer
informações úteis sobre a correção (correctness) dos sistemas já que os mesmos não foram
completamente especificados [CLARKE & WING, 1996]. Além deste método, existe um
grande progresso nas pesquisas, incentivadas pela Verificação de Modelos, que buscam lidar
com o problema dado e, assim reduzir os requerimentos de memória.
Atualmente, existem vários verificadores de modelos com as mais variadas aplicações
podendo verificar em minutos um modelo de 1030
estados. Dentre exemplos de verificadores,
podemos citar UPPAAL, KRONOS, SPIN, VERUS, LOTOS, etc.
4.2. Prova de Teoremas
A Prova de Teoremas é uma técnica onde ambos sistemas e suas propriedades desejadas
são expressas como fórmulas em alguma lógica matemática. Esta lógica é dada por um sistema
formal, que define um conjunto de axiomas e um conjunto de regras de dedução. A Prova de
Teoremas é o processo de encontrar a prova de uma propriedade de um axioma do sistema.
A Prova de Teoremas, atualmente, tem sido muito utilizada em verificação mecânica de
propriedades críticas de segurança de projetos de hardware e software. Como exemplos de
provadores de teorema, temos ACL2, PVS, ISABELLE, 3TAP, EQP, entre outros.
7
Em contraste com a Verificação de Modelos, pode lidar diretamente com espaço infinito
de estados e devido a este motivo foi o primeiro ambiente de verificação, pois geralmente
sistemas de software são máquinas de estados infinitos. Uma outra característica dos
provadores de teoremas é que estes necessitam da interação humana, o que torna o processo
lento e propenso a erros. Entretanto, no processo de encontrar a prova, o usuário humano
freqüentemente ganha inestimável perspicácia dentro do sistema ou propriedade sendo
provada.
5. Lógica Modal
Como mencionado anteriormente, verificadores de modelo utilizam alguma notação
formal para definir propriedades a serem verificadas. Este trabalho considera o verificador de
modelos UPPAAL (capítulo 3) que utiliza a lógica modal como notação formal para tal
definição.
Originalmente concebida como uma lógica da necessidade e possibilidade, foi
desenvolvida dentro de uma poderosa disciplina matemática que trata restritamente com
descrições de linguagens para argumentar sobre vários tipos de estruturas relacionais.
O termo “lógica modal” é utilizado mais amplamente para cobrir uma família de lógicas
com regras similares e uma variedade de diferentes símbolos [Garson, 2001] como, por
exemplo, a lógica temporal.
As expressões modais mais investigadas são “É possível que” e “É necessário que”. Na
lógica modal, essas expressões são representadas, respectivamente, pelos símbolos e . Neste
contexto, observa-se que A = ~~A, ou seja, o operador é dual do .
A lógica modal foi formalizada em 1918 por Lewis, a partir da noção de mundo possível
(Kripke), cuja interpretação pode ser descrita como uma alternativa “imaginável” ao mundo
real. Uma verdade necessária permanece verdadeira em todos os mundos; já uma verdade
possível se verifica em apenas alguns mundos.
Uma das limitações da lógica de primeira ordem é a não diferenciação entre os conceitos
de possível e necessário, já que de acordo com o formalismo clássico, fórmulas são apenas
8
verdadeiras ou falsas de forma absoluta, independente de noções de contexto como a que é
provida pela semântica de mundos possíveis de Kripke.
6. Metodologia
O principal fator que tange a validação hipermídia é a necessidade de apresentação das
diversas mídias do documento de forma sincronizada de acordo com sua especificação.
De modo a realizar tal validação, em 1998 teve início na Pontifícia Universidade Católica
do Rio de Janeiro (PUC-Rio), a aplicação da Verificação de Modelos a sistemas hipermídia
baseados no Modelo de Contextos Aninhados – NCM (capítulo 2). A figura 1.2 apresenta um
diagrama das etapas contidas neste ambiente.
Figura 1.2 - Validação de Documentos Hipermídia
A partir de uma especificação de sistemas hipermídia será abstraído um modelo e serão
definidos requisitos aos quais este modelo a ser validado deverá atender. De modo a validar o
modelo, ou seja, verificar se os requisitos são satisfeitos ou não pelo modelo, é utilizada uma
ferramenta verificadora de modelos. Caso algum requisito não seja satisfeito, a ferramenta
permite rastrear (trace) uma possível localização para a fonte do erro. Desta forma, uma
correção poderá ser aplicada à especificação retornando ao início do processo.
Verificador de
Modelos
9
A abstração de modelos pode ser tornar uma tarefa árdua e sujeita a erros, como qualquer
processo de modelagem. Desta forma, o presente trabalho busca propor um mecanismo
automático de geração de modelos passíveis de validação a partir de uma especificação textual
de documentos hipermídia baseada no NCM, minimizando a existência de erros e o custo para
verificação de requisitos. Assim, a validação de documentos hipermídia seria efetuada,
teoricamente, a partir de sua especificação textual o que tornaria o trabalho mais rápido e
eficiente.
Figura 1.3 - Validação de Documentos Hipermídia utilizando um tradutor para
extração de modelos de autômatos temporizados
A figura 1.3 apresenta este novo método para validação de sistemas hipermídia que
propõe a inclusão de um tradutor desenvolvido na linguagem transformacional TXL (capítulo
5), que irá extrair de uma especificação hipermídia (NCL – Nested Context Language) um
modelo de autômatos temporizados em uma especificação apropriada (TA – Timed Automata)
a qual é reconhecida por UPPAAL, o verificador de modelos considerado neste trabalho.
Podemos vislumbrar a aplicabilidade deste método quando estendido para permitir a
validação de arquiteturas de software de tempo real especificadas por alguma linguagem de
descrição de arquitetura de software (ADL). Segundo Muchaluat-Saade e Soares [2001],
existem fortes relacionamentos entre linguagens de autoria para sistemas hipermídia, como a
apresentada neste trabalho (NCL), e algumas ADLs conhecidas.
Especificação
do Sistema Hipermídia
Verificador de Modelos
(UPPAAL)
Requisitos
OK
Trace
Correção
Tradutor
(TXL)
Especificação em TA
10
Capítulo 2
NCM: Um Modelo Conceitual
Hipermídia
1. Introdução
Um documento multimídia é uma composição de fragmentos de informação ordenados
logicamente representados por diferentes mídias que expressam as idéias que o autor deseja
difundir.
Uma característica dos documentos multimídia que merece ser mencionada é o tamanho
dos seus componentes (o armazenamento de vídeos demanda usualmente centenas de
megabytes ou mesmo gigabytes) [SOUZA, 1997]. Na tentativa de evitar a replicação
desnecessária de componentes e incorporar o menor número possível de estruturas aos
documentos multimídia, buscou-se definir a sua estrutura lógica e de apresentação com base no
paradigma hipertexto e, dessa forma, criou-se o que denominamos documentos hipermídia.
A maioria dos sistemas hipermídia foram desenvolvidos como aplicações autocontidas,
não proporcionando facilidades para intercâmbio de informações, interoperabilidade e reuso de
código entre aplicações [SOARES et.al., 1997]. Buscando um modelo para descrição de
documentos hipermídia que separa os componentes de dados e de exibição dos objetos,
permitindo a manipulação de documentos independente da plataforma final de exibição, está
em desenvolvimento desde 1990, no laboratório Telemídia da Pontifícia Universidade Católica
do Rio de Janeiro (PUC-Rio), um modelo conceitual orientado a objetos denominado Modelo
de Contextos Aninhados (NCM).
Este modelo está incluso ao sistema Hyperprop cujo objetivo é fornecer um ambiente
para a construção de aplicações hipermídia através de uma biblioteca de classes que reflitam
seu modelo conceitual [SOARES, 1995].
11
As primeiras descrições do NCM se ativeram mais aos aspectos da estrutura de dados do
modelo e das regras de estruturação. As estruturas e operações para controle de versão foram
assunto posterior de especificação. A segunda versão do modelo acrescenta ao modelo básico
operações para criação, edição e exibição da estrutura do documento, novas estruturas de dados
para a definição de relações de sincronismo espacial e temporal de documentos, bem como
operações para definição e exibição dessas relações de sincronismo. Atualmente, este modelo
possui as mais modernas características desejáveis para aplicação em projetos deste tipo.
2. Conceitos do NCM
A definição de documentos hipermídia no NCM baseia-se no conceito de duas entidades:
nós e elos. Os nós são constituídos de fragmentos de informação e os elos definem os
relacionamentos entre os nós.
Uma entidade é um objeto que tem como atributos um identificador único, data e hora
de criação, autor e uma lista de controle de acesso onde cada entrada desta lista associa a
usuários direitos de acesso a cada atributo do objeto. Denota-se usuário como uma pessoa ou
processo de uma aplicação [ANTONACCI, 2000].
Um nó é uma entidade que tem como atributos adicionais um conteúdo, uma lista
ordenada de âncoras e um descritor. Âncoras são regiões marcadas do conteúdo da entidade –
como as âncoras em HTML. Somente pelas âncoras que o acesso ao conteúdo do nó é possível.
Um descritor contém informações de como a entidade deve ser apresentada ao usuário final
(dispositivo de E/S, duração, etc.), escolhido dependendo da melhor QoS (Qualidade de
Serviço – parâmetro que determina a qualidade e o custo de atendimento).
O modelo divide os nós em duas classes básicas: os nós de composição ou de contexto e
os nós de conteúdo ou terminais.
12
Figura 2.1 – Nós terminais de um modelo exemplo
O nó terminal apresenta em seu interior o conteúdo real da mídia (áudio, vídeo, texto,
imagem). A unidade de informação do nó terminal depende do tipo de mídia que o compõe.
Por exemplo, se for um texto, a unidade de informação poderá ser um caracter ou uma palavra;
ser for uma imagem, poderá ser um ponto (pixel) ou conjunto de pontos. A figura 2.1
apresenta, em destaque, nós terminais de um modelo exemplo.
Figura 2.2 – Nó de composição de um modelo exemplo
O nó de composição (figura 2.2) define a estrutura lógica do documento que agrupa um
conjunto de outros nós (terminais ou de composição recursivamente) relacionados por elos. O
AT
A I
V
1
C
L2
L1 L3 L5
L4
2
AT
A I
V
1
C
L2
L1 L3 L5
L4
2
13
nó de composição é o ponto central do modelo e podemos dizer que todo documento
hipermídia é um nó de composição.
Figura 2.3 – Âncoras de um modelo exemplo
Aos nós estão associados uma âncora padrão denominada , que representa todo o
conteúdo do nó. O nó de composição, além da âncora padrão, poderá possuir uma âncora
denominada , agindo como um controle da composição, definindo por onde iniciará a exibição
do nó, permitindo diferentes visões do documento. Já o nó terminal poderá possuir uma âncora
denominada a, indicando que parte do conteúdo será apresentada. A figura 2.3 apresenta
algumas dessas âncoras.
Figura 2.4 – Elos de um modelo exemplo
AT
A I
V
1
C
L2
L1 L3 L5
L4
2
AT
A I
V
1
C
L2
L1 L3 L5
L4
2
14
Um elo é uma entidade que apresenta como atributos adicionais um conjunto de pontos
terminais de origem e de destino que define os eventos, um ponto de encontro especificando a
relação entre estes eventos e um descritor que descreve como os nós associados aos eventos de
destino devem ser apresentados. A relação definida num ponto de encontro estabelece que
condições aplicadas a eventos de origem sejam satisfeitas e, assim, ações sejam aplicadas a
eventos de destino. Por exemplo, se um evento E1 iniciou sua execução (condição satisfeita),
deve-se iniciar a execução de um evento E2 (ação aplicável).
Um evento é a unidade básica para sincronização no NCM e corresponde a algum tipo de
ocorrência no tempo, não necessariamente de forma instantânea. Os eventos são classificados
em três tipos: os eventos de seleção que estão associados com a interação do usuário com o
documento – como acesso a um link numa página Web; os eventos de apresentação associados
com a exibição dos nós sincronizados; e os eventos de atribuição associados à mudança do
valor de algum atributo. A seleção de uma certa região nomeada por uma âncora implica num
evento de apresentação da mesma região. Assim, sempre que temos eventos de seleção,
teremos eventos de apresentação associados a eles.
Um evento pode estar genericamente no estado dormindo, preparando, preparado,
ocorrendo, suspenso e abortado conforme apresentado na figura 2.5.
Figura 2.5 – Máquina de estados dos eventos [ANTONACCI, 2000]
Todo evento possui uma variável Occurrence (Ocorrência), inteira, que conta quantas
vezes o evento muda do estado ocorrendo para preparado, durante a apresentação do
documento. Os eventos de apresentação, por sua vez, possuem uma variável Repetition
(Repetição) que determina quantas vezes seguidas o mesmo deve ser exibido, podendo esta
15
variável receber um valor finito ou indefinido, o qual levará o evento a um loop até ser
interrompido. Estas variáveis podem ser utilizadas para avaliar condições por comparação de
um ponto de encontro.
Os eventos considerados no presente trabalho são os de seleção e de apresentação, uma
vez que os eventos de atribuição constituem um tipo de mecanismo auxiliar.
3. Uma Descrição Formal para o NCM
Toda linguagem é definida formalmente evitando descrições ambíguas e se baseia num
modelo conceitual que lhe fornece suas características básicas.
A Linguagem de Contextos Aninhados (NCL) é uma linguagem para especificação de
documentos hipermídia. Existem várias destas linguagens (SMIL, Madeus, etc.) e a diferença
entre elas está na capacidade de representarem as características do NCM em suas descrições
formais.
Entre as vantagens da NCL, podemos destacar a facilidade para especificação de
documentos hipermídia e para análise da consistência temporal do documento.
O presente trabalho considera a parte da sintaxe abstrata da NCL apresentada abaixo,
citada em [FELIX et. al., 2002].
Metavariables
: Composition
: Nodes
: Links
: Events
: Descriptor
: Cond
: Action
: State
: Signal
: Identifier
: Attribute
: Operator
: Anchors
: Number
: Type
: Media
16
Abstract Syntax
::= comp
::= term | comp | 1 2
::= ev | 1 2
::= | |
::= prs | sel | att
::= desc | desc null
::= audio | video | text | image
::= link | 1 2
::= @ | . | () | 1 and 2 | 1 or 2 | | | true
::= SLEEPING|PREPARING|PREPARED|SUSPENDED|OCCURRING|ABORTED
::= prepare | start | stop | suspend | resume | abort
::= Occurrence | Repetition |
::= =|<>|<|<=|>|>=
::= prepare() | start() | stop() | suspend() | resume() | abort() | 1||2 | 1;2 | 1,2 | delay()
Um aspecto importante a se destacar na sintaxe acima, e que não foi comentado
anteriormente, é o tipo de condição e ação definida num ponto de encontro em um elo.
Condições definidas num ponto de encontro podem ser complexas ou atômicas. ::=1 and 2
| 1 or 2 | | caracterizam condições complexas significando, respectivamente,
uma conjunção lógica, uma disjunção, uma negação e uma condição de retardo em que, para
ser verdadeira, deverá ter sido verdadeira a unidades de tempo atrás. ::=@ | . | ()
caracterizam condições atômicas que serão verdadeiras, respectivamente, quando a
transição no evento acontece; quando o evento fica no estado ; quando o atributo do
evento está incrementado comparado a , segundo o operador . As ações definidas num
ponto de encontro também podem ser complexas ou atômicas. ::=1||2 | 1;2 | 1,2 |
delay() caracterizam ações complexas determinando, respectivamente, que 1 e 2 devem
ser iniciados ao mesmo tempo (paralelismo); que o término de 1 deve ser num tempo menor
ou igual ao inicio de 2 (seqüenciamento completo); que o início 1 deve ser num tempo
menor ou igual ao início de 2 (seqüenciamento fraco); e que haverá um atraso de unidades
de tempo. As ações atômicas (prepare() | start() | stop() | suspend() | resume() |
abort()) são usadas para produzir mudanças de estado, por exemplo, o reassume (resume())
muda o estado do evento de suspenso para ocorrendo.
17
4. Exemplo
A figura 2.6 apresenta o diagrama de um documento hipermídia exemplo e sua
especificação NCL, citado em [FELIX et. al., 2002].
Figura 2.6 – Exemplo de documento hipermídia
O exemplo apresenta o nó de composição C (comp C) que é composto pelos nós
terminais AT (áudio ou texto), A (áudio), I (imagem) e V (vídeo) que estão associados a
eventos de apresentação (E2, E3,...) relacionados por elos (L1, L2,...) de acordo com a
especificação.
As declarações ev E1 1 prs desc null e ev E4 2 prs desc null especificam que a
apresentação do documento poderá ser iniciada através dos eventos de seleção E1 e E4 que
irão apresentar todo o conteúdo do documento conforme as âncoras 1 e 2 respectivamente,
tendo, assim, duas formas de apresentação (visões) do mesmo documento.
Uma especificação como term V ev E3 prs desc video 8 9, descreve um evento de
apresentação E3 (ev – prs) associado à exibição de todo conteúdo do nó terminal V, conforme
a âncora , contendo uma mídia do tipo video de duração mínima 8 e máxima 9 u.t. (unidades
de tempo).
AT
A I
V
1
C
L2
L1 L3 L5
L4
comp C
term AT ev E2 prs desc audio 10 10
ev E7 prs desc text 6 6
term V ev E3 prs desc video 8 9
ev E5 prs desc video 8 9
term A ev E6 prs desc audio 7 7
term I ev E8 prs desc image
ev E1 1 sel desc null
ev E4 2 sel desc null
link L1 E1.start start(E2) || start(E3)
link L2 E4.start start(E5) || start(E6)
link L3 E6.start delay(3);start(E7)
link L4 E3.stop or E5.stop start(E8)
link L5 E2.stop or E7.stop stop(E8)
2
18
A especificação exibida na figura 1 mostra claramente o ponto de encontro num elo. Na
declaração link L1 E1.start start(E2) || start(E3), por exemplo, o ponto de encontro define
que se o evento E1 for iniciado (condição), devem-se iniciar os eventos E2 e E3 em paralelo
(ação), conforme definição do par condição/ação. Já na declaração link L3 E6.start
delay(3);start(E7), o ponto de encontro define que se o evento E6 for iniciado, deve-se ter um
atraso de 3 u.t. e que após, ou no mesmo instante do término deste atraso, o evento E7 deve ser
iniciado, conforme a definição do seqüenciamento completo (A1;A2).
19
Capítulo 3
UPPAAL: Um Verificador de Modelos
1. Introdução
UPPAAL é uma ferramenta para modelagem, simulação e verificação de sistemas de
tempo real desenvolvida pelo Basic Research in Computer Science (BRICS) da Aalborg
University na Dinamarca e o Department of Computer Systems (DoCS) da Uppsala University
na Suécia. É apropriada para sistemas que podem ser modelados como uma composição
paralela de processos seqüenciais não-determinísticos com valores de tempo real, comunicação
por canais e variáveis compartilhadas. Sua aplicação típica inclui controladores de tempo real e
protocolos de comunicação, ou seja, sistemas onde o tempo é um fator crítico [Larsen et. al.,
1997].
Desde de sua primeira versão em 1995, a UPPAAL tem sido ampliada para atender aos
mais variados estudos de caso. A atual versão 3.2 (UPPAAL2k), que está sendo considerada
no presente trabalho, foi implementa em Java e C++ e está disponível para as plataformas mais
utilizadas como Linux, Windows e SunOS.
A utilização da ferramenta se baseia:
1) na modelagem abstrata de um sistema através de uma rede de autômatos
temporizados, onde cada autômato representa um componente do sistema;
2) na simulação deste sistema modelado e;
3) na verificação de suas propriedades pré-estabelecidas.
Um autômato é um conjunto de estados interligados por transições que podem ser
sincronizadas e ter sua habilitação controlada por guardas que nada mais são do que condições
sobre uma variável. Os autômatos temporizados são basicamente autômatos finitos não-
determinísticos acrescidos de variáveis relógio que são a forma de controlar o tempo em
20
UPPAAL. O não-determinismo, característico em sistemas reativos e concorrentes, é
estabelecido pela possibilidade de deixar um estado e seguir por uma dentre várias transições.
A ferramenta apresenta uma interface gráfica que permite a descrição do sistema, a
visualização e armazenamento de um passo da simulação, um verificador para validar o
modelo por verificação automática dos requisitos, além de indicar na simulação uma possível
localização da satisfação ou não dos requisitos pré-estabelecidos.
O núcleo da máquina computacional de UPPAAL consiste de uma coleção de algoritmos
eficientes que podem ser utilizados para desempenhar análise de alcançabilidade sobre um
modelo de um sistema real [ACETO et. al., 1997].
A escolha de UPPAAL como verificador de modelos é justificada pela facilidade de uso,
eficiência e portabilidade; além de ser resultado de pesquisas mais recentes na área de
verificação baseada em autômatos e aspectos de tempo real.
2. Apresentação
A interface gráfica do usuário (GUI) da ferramenta UPPAAL possui duas partes
principais: a barra de menus e as guias (System Editor, Simulator, Verifier).
A ferramenta apresenta ajuda integrada acessível através do menu Help que descreve,
entre outras coisas, a barra de menus. Este capítulo focalizará os processos de modelagem,
simulação e verificação de um sistema.
A primeira guia, apresentada na figura 3.1 e denominada System Editor, é a área de
modelagem do sistema. Esta guia é dividida em duas partes: a parte com quadriculados é a área
onde será criado o desenho de cada autômato (processo) do sistema; e a outra parte é a área de
especificação do sistema onde serão declaradas as variáveis, constantes e referências aos
autômatos. Assim, a idéia da edição é definir um grupo de autômatos referenciados que
possuem variáveis e constantes como parâmetros para representar um sistema completo
(modelo). As variáveis e constantes são de tipos de dados simples (inteiros, vetores, etc.) e
ajudam a descrever o comportamento do sistema.
21
Figura 3.1 – GUI da ferramenta UPPAAL apresentando a guia System Editor
A segunda guia, denominada Simulator, é uma área de simulação do sistema modelado,
o que permite executar o sistema interativamente e visualizar falhas detectadas na fase de
verificação. O Simulator fornece, também, a capacidade de armazenar um passo da execução
do sistema (simulação).
A última guia, denominada Verifier, serve para verificar por Verificação de Modelos
automática se os requisitos ou propriedades pré-estabelecidas para um sistema em seu modelo
são satisfeitos ou não. A Verificação de Modelos cobre todos os possíveis comportamentos
dinâmicos do sistema verificando invariantes (condições sobre um relógio) e propriedades de
alcance, ou seja, se um certo estado é alcançado ou não. As consultas (Queries), especificação
de requisitos, sobre o modelo são realizadas baseando-se na lógica modal (operadores e ) –
capítulo 1, seção 5.
22
3. Utilização
A utilização da ferramenta é bastante simples, comparável com a utilização de outros
softwares conhecidos do mercado, baseando-se nos princípios utilizados por ferramentas com
GUI. Apesar disto, não deixa de ser importante o conhecimento de alguns conceitos e
abordagens específicos durante os processos de modelagem, simulação e verificação.
3.1. Modelagem
Figura 3.2 – Caixa de diálogo Edit Location
O modelo de um sistema é construído na guia System Editor (Figura 3.1) e para criá-lo é
utilizado dois modos: o Select Mode (Modo de Seleção) e o Transition Mode (Modo de
Transição). A diferença básica entre eles está relacionada com a movimentação dos objetos na
área de modelagem. O modo de seleção permite que os objetos sejam movimentados na área
de modelagem, mas não permite criar transições entre os estados do modelo. Já o modo de
transição permite criar transições, mas não permite movimentá-los.
A definição de estados (Locations) em UPPAAL é exatamente igual em Teoria dos
Autômatos. Estados são situações (em quantidade finita), bem determinadas em que uma
máquina pode se encontrar durante sua execução. Há permanência da máquina nesses estados,
medida em unidades de tempo.
23
Ao criar um estado, algumas propriedades, conforme apresentado na figura 3.2, poderão
ser alteradas:
Name – definição do nome do estado;
Invariant - declaração de invariantes que são condições expressando restrições aplicadas
ao valor de uma variável declarada como relógio. O padrão para invariantes é verdadeiro;
Initial – ao selecionar esta opção, o estado será declarado como o inicial. O estado inicial
é apresentado no modelo com um círculo em seu interior;
Urgent – ao selecionar esta opção, nenhum atraso é permitido até o estado ser deixado. O
estado urgente permite ”interleaving”, ou seja, que alguma ação que não gaste tempo ocorra
em outro autômato concorrentemente; e é apresentado no modelo com a letra “U” em seu
interior;
Committed – como o estado urgente, nenhum atraso é permitido até deixar o estado, mas
impede “interleaving” produzindo uma transição atômica. Ao deixar um estado committed, a
transição pode aplicar uma ação (atribuições e sincronizações) e não um atraso (condições). O
estado committed é muito utilizado para fazer broadcast.
Uma transição além de interligar estados, permite a aplicação de ações como tarefas com
variáveis ou reajustes dos relógios.
Figura 3.3 – Caixa de diálogo Edit Transition
Nas transições, poderão ser incluídos os itens apresentados na figura 3.3, descritos a
seguir:
24
Guardas (Guards) – são condições aplicadas a variáveis inteiras e relógios. A diferença
entre guardas e invariantes é que estas são condições de progressão que estão associadas a um
estado, isto é, não permitem que o sistema ultrapasse o tempo de permanência em um estado,
determinado pela condição, fazendo com que a transição seja habilitada. Já aqueles estão
relacionados à transição e não permitem sua habilitação caso a condição não seja satisfeita. O
padrão para o guarda é um valor verdadeiro;
Canais de sincronismo (Sync) – permitem o sincronismo (hand-shaking) entre duas
transições de autômatos diferentes. Desta forma, cada um de dois processos habilita uma
transição ao mesmo tempo. Um canal de sincronização chamado a será representado por a!
para enviar um sinal de sincronismo e a? para recebê-lo;
Atribuições (Assign) – permitem atribuir valores ou expressões simples a variáveis.
A sintaxe aplicada às variáveis é semelhante à da linguagem C, o que facilita o
aprendizado da ferramenta por ser uma linguagem bastante conhecida. Até o operador ternário
da linguagem C (x:=y==1?2:1) é suportado.
Após o desenho do sistema, o próximo passo é o da especificação do mesmo. As
variáveis a serem declaradas podem ser globais (Global Declarations) ou locais
(Declarations). As variáveis globais estão relacionadas a todo o sistema e as locais apenas ao
autômato que se refere.
Os tipos de dados possíveis a serem declarados são: int (inteiros e vetores de inteiros),
clock (relógios), chan (canais de sincronização), urgent chan (canais urgentes) e const
(constantes).
Canais urgentes previnem uma rede de atraso em uma situação onde dois componentes
(autômatos) já estão habilitados para sincronizar. Por questões de eficiência, os canais urgentes
não podem ter guardas sobre o relógio.
É importante saber que o número de relógios tem importante impacto na complexidade e
que para o valor de um relógio, o tempo progredirá globalmente num mesmo passo por todo o
sistema.
Em Process Assignments (Atribuições de Processos), são definidos os parâmetros a
serem passados aos autômatos e em System definition (Definição do Sistema) é definido que
autômatos serão utilizados para representar o sistema modelado.
25
A ferramenta UPPAAL permite verificar se a sintaxe está correta acessível pelo menu
File – Check Syntax.
O modelo pode ser criado num formato textual através das linguagens TA (timed-
automata) ou XML (eXtensible Markup Language) reconhecidas pela ferramenta. Atualmente
o XML é o formato padrão para armazenar modelos. A diferença entre as duas linguagens está
no fato de que o formato TA não permite registrar informações gráficas sobre o modelo, o que
não ocorre com o XML. A figura 3.4 apresenta as três formas de modelagem.
MODELO GRÁFICO MODELO EM TA
// Insert declarations of global clocks, variables,
// constants and channels.
clock x;
process P{
// Insert local declarations of
// clocks, variables and constants.
state A, B;
init A;
trans A -> B{guard x>3; };
}
// Edit system definition.
system P;
MODELO EM XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE nta PUBLIC "-//Uppaal Team//DTD Flat System 1.0//EN"
"http://www.docs.uu.se/docs/rtmv/uppaal/xml/flat-1_0.dtd">
<nta>
<declaration>
//Insert declarations of global clocks, variables, constants and channels.
clock x;</declaration>
<template>
<name x="5" y="5">P</name>
<parameter x="5" y="20"/>
<declaration>//Insert local declarations of clocks, variables and constants.
</declaration>
<location x="112" y="96" id="id0"><name x="102" y="66">A</name><label kind="invariant"
x="102" y="111"/></location><location x="216" y="80" id="id1"><name x="206"
y="50">B</name><label kind="invariant" x="206" y="95"/></location><init
ref="id0"/><transition><source ref="id0"/><target ref="id1"/><label kind="guard" x="144"
y="64">x>3</label></transition></template>
<instantiation>//Insert process assignments.
</instantiation>
<system>//Edit system definition.
system P;</system>
</nta>
Figura 3.4 – Formas de modelagem
26
3.2. Simulação
A figura 3.5 apresenta a guia Simulator onde é realizada a simulação, exibindo um
exemplo que mostra, com clareza, o sincronismo entre duas transições.
O simulador apresenta um painel de controle que habilita as possíveis transições podendo
esta habilitação ser imposta pelo usuário. Desta forma, o sistema é executado interativamente
permitindo sua validação. Neste painel, é possível também visualizar um trace da simulação,
reiniciar/salvar/abrir um passo da simulação, além de poder executar a simulação
randomicamente e com velocidade controlável através da barra de controle disponível.
Figura 3.5 – GUI da ferramenta UPPAAL apresentado a guia Simulator
Ao lado do painel de controle da simulação, temos a apresentação das variáveis com seus
respectivos valores atribuídos de acordo com o passo da simulação; e a visualização da
simulação gráfica do modelo propriamente dita.
27
3.3. Verificação
A figura 3.6 apresenta a guia Verifier onde é realizada a verificação de requisitos
(propriedades) sobre um modelo. As consultas (Queries) são feitas baseando-se na lógica
modal. Desta forma, temos os seguintes operadores e suas interpretações [PETTERSSON,
2003][GRUPO UPPAAL, 2000]:
E<> x – x é possível;
E[] x – Existe um caminho onde x sempre ocorre. Também se pode interpretar como: em
um caminho, a partir de um certo estado, x é necessário;
A<> x – Por todos os caminhos, x eventualmente ocorrerá. Outra interpretação seria: a
partir de qualquer configuração (vetor de estados), é possível que x aconteça;
A[] x – x é sempre verdade (é necessário);
x --> y – onde quer que x ocorra, y eventualmente ocorrerá. Isto é o mesmo que dizer A[]
(x imply A<> y), só que o agrupamento de operadores não é permitido ainda em UPPAAL.
Figura 3.6 – GUI da ferramenta UPPAAL apresentado a guia Verifier
28
Além dos operadores citados anteriormente, a ferramenta UPPAAL permite verificar a
possibilidade de deadlock, por exemplo: A[] not deadlock.
A figura 3.7 apresenta a sintaxe para formulação de consultas fornecida na ajuda
integrada da ferramenta [PETTERSSON, 2003]. É importante citá-la porque é base para este
trabalho.
Requirements
In this help section we give a BNF-grammar for the requirement specification language
used in the verifier of UPPAAL2k.
Like in the grammar for system descriptions we use names with capital initial letters
to denote non-terminals, NAT to denote natural number (including 0), ID to denote a valid
identifier names, and NULL to denote the empty string.
Prop ::= A[] SP | E<> SP
| E[] SP | A<> SP | SP --> SP
SP ::= AP | not SP | ( SP ) | SP or SP
| SP and SP | SP imply SP | deadlock
AP ::= ID.ID | CGuard | IGuard
CGuard ::= ID REL NAT | ID REL ID
| ID REL ID + NAT | ID REL ID - NAT
IGuard ::= IExpr REL IExpr
| IExpr != IExpr
IExpr ::= ID | ID[IExpr] | NAT | -IExpr
| (IExpr) | IExpr OP IExpr
REL ::= < | <= | >= | > | ==
OP ::= + | - | * | /
ID.ID should be in the form "process name.location name". CGuard and IGuard are the
guards over clocks and integer variables, also described in the help section for the system
description language.
Notice that at the moment the deadlock state predicate is only allowed with E<> and A[]
properties.
Figura 3.7 – Sintaxe para formulação de consultas em UPPAAL
Ao aplicar o Model Check, o Verifier retornará como resposta se a propriedade foi
satisfeita ou não e o porquê representado no simulador se o Diagnostic Trace no menu
Options estiver habilitado.
4. Exemplos
Os exemplos apresentados a seguir foram desenvolvidos com o intuito de aprendizagem
do processo de utilização da ferramenta e abstração de sistemas. O importante ao modelar um
sistema é avaliar o que será verificado e como serão avaliados os requisitos pré-estabelecidos
para tal sistema.
29
4.1. Exemplo Elucidativo
Este exemplo não tem aplicação sistemática, mas serve para elucidar a maioria dos
conceitos utilizados na ferramenta apresentados na seção 3 deste capítulo.
a) Modelagem
GLOBAL DECLARATIONS SYSTEM DEFINITION
clock y;
int x;
chan a;
System A,B;
Figura 3.8 – Modelo elucidativo
b) Simulação
No processo A, o estado A0 apresenta uma invariante (y<=5) e um guarda (y>=3) em
sua transição para o estado A1. Desta forma, não podemos permanecer no estado A0 por mais
de 5 u.t. (unidades de tempo) e só poderemos habilitar a transição se o valor do relógio y for
30
maior ou igual a 3 u.t.. Resumindo, o estado terá que ser deixado com o relógio 3 y 5 u.t..
Ao habilitar a transição entre A0 e A1, ocorre uma sincronização com a transição entre os
estados B0 e B1 do processo B através do canal de sincronização a (a!,a?). Isto significa que
as transições A0A1 e B0B1 serão habilitadas no mesmo instante. Assim, A0 e B0 serão
deixados no mesmo passo. Supondo que a fosse um canal urgente, a transição seria habilitada
com y=3, pois não poderá haver atraso, mas não é possível aplicar um guarda sobre o relógio
numa transição urgente. Portanto, esta suposição foi apenas para elucidar o conceito de canal
urgente. Como a transição B0B1 foi habilitada, uma atribuição é aplicada ao valor da
variável inteira x (x:=0).
Estando nos estados A1 e B1, o estado B1 será deixado primeiro por ser um estado
committed, aplicando uma nova atribuição à variável x (x:=x+1) que passa a ter valor 1. Agora
estando nos estados A1 e B2, qualquer um dos dois poderão ser deixados. Supondo que A1 seja
deixado primeiro, uma atribuição é aplicada à variável x que passa a ter valor 3. É interessante
reparar que ações são aplicadas pela transição à variável x.
Agora os estados A2 e B2 poderão ser deixados. Como A2 é um estado urgente, não
impedirá que os outros estados do processo B sejam executados desde que não surjam atrasos.
Este é o fator característico dos estados urgentes. Daqui por diante, os passos da simulação
seguiram normalmente até reinicar o processo.
c) Verificação
PROPRIEDADE DESCRIÇÃO COMENTÁRIO RESULTADO
E<> B.B3 and A.A2 É possível estar em
B.B3 e A.A2
Esta é a prova do estado urgente.
Estando em B.B2 e A.A2 (estado
urgente) é permitido ir para
B.B3.
Satisfeita
A[] B.B1 imply not
A.A2
É sempre verdade que
estando em B.B1
implica em não estar
em A.A2
Esta é a prova do estado
committed. Estando em B.B1
(estado committed) e A.A2 não é
permitido sair de A.A2 sem antes
deixar B.B1.
Satisfeita
E<> deadlock É possível deadlock
Para alcançar o estado B.B0, o
valor do relógio y deverá ser
maior ou igual a 5 u.t.. Se o
alcance B.B0 foi possível e
estando em A.A2 então y deverá
ter valor exato a 5 u.t. para
acessar A.A0 devido sua
invariante (y<=5), caso contrário
ocorrerá um deadlock.
Satisfeita
Tabela 3.1 – Verificação do modelo elucidativo
31
4.2. Exemplo Elevador
O objetivo principal de modelar um elevador é validar a possibilidade da cabine estar em
movimento com a porta aberta comprometendo a segurança do usuário.
a) Modelagem
GLOBAL DECLARATIONS SYSTEM DEFINITION
int andar;
chan a,b,c,d;
System Usuario,Porta,Cabine;
Figura 3.9 – Modelo elevador
32
b) Verificação
PROPRIEDADE DESCRIÇÃO COMENTÁRIO RESULTADO
A[] Cabine.Mov imply
Porta.Fechada
Sempre que a cabine
estiver em movimento,
a porta estará
fechada.
Esta é a pergunta-chave do
modelo. É possível visualmente
concluir este fato.
Satisfeita
E<> Cabine.Parada and
Porta.Fechada
É possível a cabine
estar parada e a
porta fechada.
Em uma situação normal esta
propriedade é possível, mas o
modelo foi construído para
validar se a cabine não entra
em movimento com a porta
fechada.
Não satisfeita
Tabela 3.2 – Verificação do modelo elevador
4.3. Exemplo Cruzamento
Este modelo valida um cruzamento através da possibilidade dos semáforos estarem com
sinal aberto, ou o trânsito liberado, ao mesmo tempo possibilitando a colisão de carros que
provém de lados diferentes do cruzamento.
a) Modelagem
GLOBAL DECLARATIONS DECLARATIONS SYSTEM DEFINITION
chan a,b; RuaA RuaB
System RuaA,RuaB; clock x; clock y;
Figura 3.10 – Modelo cruzamento
33
b) Verificação
PROPRIEDADE DESCRIÇÃO COMENTÁRIO RESULTADO
E<> RuaA.Vd and
(RuaB.Vd or RuaB.Am)
É possível estar na rua A e
B com o sinal aberto.
Esta é a pergunta-chave do
modelo.
Não satisfeita
Tabela 3.3 – Verificação do modelo cruzamento.
34
Capítulo 4
Validação de Documentos Hipermídia
1. Introdução
A modelagem de documentos hipermídia como uma rede de autômatos temporizados
fornece um elevado nível de abstração que facilita a compreensão e validação de tais sistemas,
principalmente por permitir a utilização de verificadores de modelo como UPPAAL.
O principal motivador para modelagem e validação de tais documentos é solução do
problema durante sua concepção: testar relações lógico-temporais entre suas diversas mídias.
Em outras palavras, queremos testar e validar se as diversas mídias componentes de um
documento hipermídia são exibidas de forma sincronizada conforme sua especificação. Face às
inúmeras aplicações dos documentos hipermídia, sua validação é um caso peculiar que fomenta
este projeto.
2. Modelando Documentos Hipermídia em UPPAAL
As especificações NCL descrevem como documentos hipermídia devem ser controlados.
Assim, podemos fazer o mapeamento dos conceitos NCM para um modelo de autômatos
temporizados em UPPAAL.
35
Figura 4.1 – Mapeamento do NCM em autômatos
Os conceitos NCM irão corresponder a um autômato temporizado com canais de
sincronização. Então, os eventos darão lugar a este autômato com sincronização segundo os
relacionamentos existentes entre eles, definido pelos elos.
2.1. Exemplo
O modelo a seguir foi criado através da abstração do sistema real. Assim, é possível ter
diferentes maneiras de representá-lo dependendo somente do usuário que o modelará.
Este modelo baseia-se no exemplo de documento hipermídia apresentado no capítulo 2,
seção 4. O advento do modelo inicia-se com o autômato User que definirá por onde iniciará a
apresentação do documento, seguido do mapeamento de outros componentes do modelo NCM
segundo sua especificação.
Figura 4.2 – Autômato Usuário
MMOODDEELLOO NNCCMM UUPPPPAAAALL
Processos Concorrentes
(Eventos) Autômatos
Sincronia dos Processos
(Elos) Sinais (x? / x!)
36
ev E1 1 prs desc null
Figura 4.3 – Autômato do evento E1
term AT ev E2 prs desc audio 10 10
Figura 4.4 – Autômato do evento E2
term V ev E3 prs desc video 8 9
Figura 4.5 – Autômato do evento E3
37
ev E4 2 prs desc null
Figura 4.6 – Autômato do evento E4
term V ev E5 prs desc video 8 9
Figura 4.7 – Autômato do evento E5
term A ev E6 prs desc audio 7 7
Figura 4.8 – Autômato do evento E6
38
term AT ev E7 prs desc text 6 6
Figura 4.9 – Autômato do evento E7
term I ev E8 prs desc image
Figura 4.10 – Autômato do evento E8
link L1 E1.start start(E2) || start(E3)
Figura 4.11 – Autômato do elo L1
39
link L2 E4.start start(E5) || start(E6)
Figura 4.12 – Autômato do elo L2
link L3 E6.start delay(3);start(E7)
Figura 4.13 – Autômato do elo L3
link L4 E3.stop or E5.stop start(E8)
Figura 4.14 – Autômato do elo L4
40
link L5 E2.stop or E7.stop stop(E8)
Figura 4.15 – Autômato do elo L5
GLOBAL DECLARATIONS DECLARATIONS – E7 SYSTEM DEFINITION
chan StartE1,E1Start,StartE2,
StartE3,E2Stop,E3Stop,end1,
StartE4,E4Start,StartE5,
E6Start,E5Stop,StartE6,StartE7,
E7Stop,StartE8,StopE8,end2;
clock ck;
int endev;
clock ckE7; System User,L1,E1,
E2,E3,L2,L3,L4,
L5,E4,E5,E6,E7,E8;
Figura 4.16 – Especificações do sistema
2.2. Validação do Modelo
PROPRIEDADE DESCRIÇÃO COMENTÁRIO RESULTADO
A[] not deadlock É sempre verdade que
não há deadlock
O evento E7 finaliza o E8,
portanto não deve terminar
primeiro que o E5 que inicializa
o E8, porém isto está sendo
possível causando deadlock. No
capítulo 6 (seção 4) a
verificação desta propriedade é
apresentada com mais detalhes.
Satisfeita
E<> L5.S1 and E3.o
É possível terminar o
evento E2 antes do
E3.
O evento E3 inicia o E8 e o
evento E2 finaliza-o. E2 não deve
terminar primeiro que E3, caso
contrário ocorrerá um deadlock. A
apresentação do áudio (E2) tem
duração de 10 u.t. e do vídeo
(E3) tem duração entre 8 e 9
u.t., se o modelo estiver correto
então o resultado da verificação
desta propriedade já era
previsível.
Não
satisfeita
E<> E6.o and (L4.S1
or E8.o)
É possível o evento
E5 terminar antes do
E6.
Os eventos E5 e E6 iniciam-se ao
mesmo tempo mas a duração da
apresentação do áudio (E6) é
menor que a do vídeo (E5). Desta
forma, esta propriedade testa
apenas o sincronismo temporal.
Não
satisfeita
41
E<> L5.S1 and not
E8.o
É possível o evento
E7 terminar antes do
E5.
Esta é a validação do problema de
deadlock apresentado
anteriormente.
Não
satisfeita
E<> E8.o and L3.S2
and ck>1000
É possível apresentar
a imagem (E8) por um
tempo maior que 1000
u.t..
Esta é a prova do starvation. Satisfeita
Tabela 4.1 – Verificação do modelo elucidativo
42
Capítulo 5
TXL: Uma Introdução à Programação
Transformacional
1. Introdução
A conversão de formalismos, ou seja, a transformação de código é uma atividade bem
conhecida entre os profissionais de computação. O problema deste processo está em encontrar
uma função que transforme uma sentença de uma linguagem fonte em uma outra sentença
semanticamente equivalente na linguagem alvo. Existem vários sistemas para suportar a
transformação de código e podemos até mesmo considerar o paradigma de programação
subjacente, a chamada programação transformacional. Entre estes sistemas, podemos destacar
TXL (Tree Xformation Language) que se baseia no reconhecimento e troca de padrões,
considerada neste trabalho por uma decisão de projeto.
Desenvolvida a partir de um projeto iniciado na University of Toronto (1985) e concluída
pela equipe da Queen‟s University (1987), atualmente na versão 10, a TXL atende a qualquer
processamento baseado na transformação de código, como engenharia reversa, sendo utilizada
por usuários acadêmicos e industriais de diversas partes do mundo.
A programação em TXL consiste na especificação das estruturas a serem transformadas,
através de uma gramática EBNF (Extended Backus-Nauer Form) livre de contexto, e de um
conjunto de regras de transformação baseadas em padrões que descrevem um modelo e sua
respectiva substituição.
43
O processo de transformação engloba três fases: parse, transformation e unparsing.
Figura 5.1 – Fases da transformação [FELIX, HAEUSLER, 1999]
Na primeira fase do processo (parsing), será construída a árvore sintática da entrada que
será transformada, a partir da aplicação de regras de transformação (transformation), na árvore
da saída. Esta árvore resultante será percorrida em ordem (unparsing) fornecendo um formato
textual para o resultado da transformação, conforme demonstrado na figura 5.1.
2. Instalação, Configuração e Execução
A obtenção da ferramenta é feita através do registro e download no site TXL [2002]
segundo a plataforma utilizada. No caso deste trabalho, consideramos a plataforma Windows
2000.
Para instalação deve-se descompactar, na unidade e pasta desejada, o arquivo adquirido
no site e alterar os arquivos TXL.BAT e TXLDB.BAT, localizados na pasta BIN, com
caminho da instalação.
Os arquivos com código TXL devem ter a extensão de mesmo nome. Já os arquivos com
o código de entrada para a transformação podem ter como extensão o mesmo nome do arquivo
txl. Por exemplo, para um arquivo SIM2C.TXL, um arquivo de entrada poderia ser
DIV.SIM2C. Desta forma, para executar a transformação basta digitar na linha de comando:
txl DIV.SIM2C
Sugere-se a adoção do programa EditPlus (http://www.editplus.com) para edição e
execução dos programas devido a seu ambiente amigável.
Unparsing Transformação Parsing
1
(a+b)*c *+ab c
( )
c *
a b +
* c
+ b a
44
3. Parsing
A construção da árvore sintática da entrada baseia-se na definição de uma gramática
especificada em uma notação similar à EBNF. A unidade básica de uma gramática TXL é a
declaração define [CORDY et al., 2000] que irá especificar um não-terminal, ou seja, definir
um tipo de árvore sintática que será manipulada pelas regras de transformação.
Figura 5.2 – Exemplo de definição de um não-terminal [CORDY et al., 2000]
A figura 5.2 apresenta a definição da sub-árvore do tipo expression constituída de um
número, ou de alguma coisa que já é expression seguida de um símbolo „+‟ e um número, ou
de uma expression seguida de um símbolo „-‟ e um número. Estas alternativas de representação
para o não-terminal são separadas pela barra vertical, „|‟, como se pôde perceber. Declarações
como 5, 10+2 e 23-43+2 são exemplos de expression conforme a definição.
Em uma declaração define pode aparecer referências a não-terminais, fechadas entre
colchetes [ ]; e símbolos terminais, como o „+‟ da figura 5.2, que representam uma parte da
sintaxe requerida da gramática. Símbolos pré-definidos e palavras reservadas da TXL que
necessitam ser definidos como terminais devem aparecer precedidos por uma aspa simples
como por exemplo, „|.
Na gramática sempre deverá existir uma especificação para o não-terminal program
representante do tipo que descreve a estrutura de toda entrada no programa TXL. Por
convenção, o não-terminal program é o primeiro tipo a ser definido.
A TXL apresenta alguns tipos não-terminais pré-definidos, tais como apresentados na
figura 5.3.
define expression
[number]
| [expression] + [number]
| [expression] - [number]
end define
45
TIPO DESCRIÇÃO
[id] Algum identificador composto por números, letras e
sublinhado, contanto que seja iniciado com uma letra
ou sublinhado. Exemplos: _A, Ab13, _12, A_B.
[number] Algum número inteiro ou real sem sinal. Exemplos: 3,
12.4, 2e10.
[stringlit] Uma cadeia de caracteres entre aspas duplas (“). Caso
o caracter (“) faça parte da cadeia, este deve
aparecer precedido por (\). Exemplos: “A casa”,
“Disse: \“oi\””,“ ”.
[charlit] Uma cadeia de caracteres entre aspas simples („).
Exemplos: „A casa‟, „Disse: \„oi\‟‟,„ ‟.
[token] Qualquer item [id], [number], [stringlit], [charlit].
Utilizado nos programas TXL mais sofisticados.
Figura 5.3 – Alguns tipos não-terminais pré-definidos em TXL
Em TXL é possível fazer referência a um conjunto de não-terminais do mesmo tipo
através da utilização de modificadores. A figura 5.4 apresenta alguns destes modificadores.
MODIFICADOR ABREVIAÇÃO DESCRIÇÃO
[opt id] [id?] Representa que o identificador é opcional.
[repeat id] [id*] Representa zero ou várias repetições de
identificadores (separados por espaço).
[repeat id+] [id+] Representa uma ou várias repetições de
identificadores.
[list id] [id,] Representa uma lista de zero ou vários
identificadores (separados por vírgula).
[list id+] [id,+] Representa uma lista de um ou vários
identificadores.
Figura 5.4 - Alguns modificadores em TXL
É permitido também modificar um terminal desde que este venha precedido por uma aspa
simples („). Por exemplo, [opt „}] denota que a chave é opcional.
TXL apresenta alguns não-terminais especiais, entre eles podemos citar o [empty] e o
[any]. O primeiro sempre é reconhecido independentemente da entrada, mas não consome
46
nenhum item da entrada [CORDY et al., 2000]. O segundo é o não-terminal universal que
equivale a qualquer tipo. O não-terminal [any] aparecendo na gramática pode nunca ser
reconhecido e sempre causar erro de sintaxe, entretanto é largamente utilizado na fase de
definição de regras e funções do processo de transformação.
Figura 5.5 – Exemplo de gramática [FELIX, HAEUSLER, 1999]
A figura 5.5 apresenta a definição da gramática para o exemplo apresentado na figura
5.1. Esta gramática representa a estrutura sintática da entrada (expressões infixadas) e da saída
(expressões prefixadas) segundo o método de gramática misturada (MGM), garantindo a
correção sintática do resultado das transformações. Uma outra forma de implementação é
utilizando o método da gramática achatada (MGA) na qual somente a gramática da linguagem
fonte precisa ser fornecida. Além da forma de especificar a gramática, este dois métodos
possuem diferenças em relação à implementação do processo transformacional. Mais
informações sobre estes dois métodos serão discutidas na seção 6.
4. A Fase de Transformação
Após a construção da árvore de entrada, inicia-se o processo de transformação sobre esta
árvore. Para executar este processo, TXL utiliza duas construções básicas: regras e funções. A
declaração de regras e funções é dada segundo a sintaxe apresentada na figura 5.6.
TXL BNF
define program
[E]
end define
define E E ::= T + E | T
[T] + [E] | [T] | +[T][E]
end define
define T T ::= F * T | F
[F] * [T] | [F] | *[F][T]
end define
define F F ::= id | ( E )
[id] | ([E]) | +[T][E] | *[F][T]
end define
47
Figura 5.6 – Sintaxe da regra e função
Estas estruturas são aplicadas a uma árvore sintática de um certo tipo, denominada
escopo, que denota uma árvore do mesmo tipo do escopo. O processo de transformação inicia-
se com a regra ou função main.
O funcionamento de qualquer regra ou função se divide em duas etapas básicas:
matching e replacement. A primeira etapa verifica se o escopo do tipo especificado no replace
combina com o padrão dado. Em caso afirmativo, o processo passa para a segunda etapa
realizando a troca conforme especificado na cláusula by; caso contrário, o escopo é retornado
inalterado.
A diferença básica entre a função e a regra é que a primeira recebe diretamente uma sub-
árvore do tipo especificado que combine com o padrão dado, realizando a troca. Já a segunda
faz uma busca e troca iterativa até que não encontre mais o tipo especificado. Esta diferença
entre regra e função fica mais fácil de compreender com o exemplo da figura 5.7. Neste
exemplo, o objetivo da regra e da função é o mesmo, trocar o número 2 pelo número 42. A
regra irá procurar em toda a entrada um número que seja igual a 2 e trocá-lo por 42. A função
já recebe como escopo a árvore do tipo que combina com o padrão dado.
REGRA FUNÇÃO
rule TrocaTodo2_42
replace [number]
2
by
42
end rule
function Troca2_42
replace [number]
2
by
42
end function
Entrada: 27 33 2 5 76 2 Entrada: 2
Saída: 27 33 42 5 76 42 Saída: 42
Figura 5.7 – Exemplo de regra e função [CORDY et al., 2000]
function nome
replace [tipo]
padrão
by
troca
end function
rule nome
replace [tipo]
padrão
by
troca
end rule
48
Existe um tipo especial de função denominada função de busca que realiza uma busca
em seu escopo pelo primeiro tipo que combine com o padrão dado fazendo a respectiva troca.
Para denotar a função de busca é acrescentado logo após a palavra-chave replace um asterisco
(*). A figura 5.8 apresenta uma função de busca com o objetivo de trocar a primeira ocorrência
do número 2 pelo número 42.
FUNÇÃO DE BUSCA
function TrocaPrimeiro2_42
replace * [number]
2
by
42
end function
Entrada: 1 3 5 7 9 2 4 6 8 2 9 4
Saída: 1 3 5 7 9 42 4 6 8 2 9 4
Figura 5.8 – Exemplo de função de busca [CORDY et al., 2000]
Funções ou regras são aplicadas a uma sub-árvore utilizando uma notação composicional
posfixada e com o seu nome entre colchetes. Desta forma, expressões matemáticas como f(X)
são declaradas na forma X[f] e, do mesmo modo, f(g(X)) é declarado como X[g][f]. Como
exemplo mais prático, podemos citar N[TrocaPrimeiro2_42], onde N representa uma árvore
que denota uma repetição de inteiros.
É possível também a passagem de parâmetros para uma função ou regra, bastando apenas
definir um nome arbitrário, denominado variável, que irá representar o tipo da árvore; e o tipo
da árvore propriamente dito para cada parâmetro na declaração da regra ou função como
mostrado na figura 5.9.
function Troca2_N N[number]
replace [number]
2
by
N
end function
Chamada: X[Troca2_N 10]
Figura 5.9 – Exemplo de função com parâmetro [CORDY et al., 2000]
49
A aplicação de regras envolvendo parâmetros que são listas ou repetições pode ser
modificada utilizando “each” precedendo o parâmetro. Desta forma, a regra será reaplicada
para cada elemento da lista ou repetição.
define program
[repeat number]
end define
function main
replace [program]
NUMEROS[repeat number]
construct RESULTADO[number]
_[SOMA_ELEMENTOS each NUMEROS]
by
RESULTADO
end function
function SOMA_ELEMENTOS NUMERO[number]
replace [number]
N[number]
by
N[+ NUMERO]
end function
Figura 5.10 – Exemplo de aplicação do each
Existe um tipo especial de regra, denomina regra de um passo, na qual o escopo é
percorrido somente uma vez. Para definir este tipo de regra, basta incluir após a palavra-chave
replace o símbolo $. A figura 5.11 apresenta um exemplo desta regra que incrementa todos os
elementos de uma seqüência de números em uma unidade.
rule Incrementa
replace $ [number*]
N[number] Ns[number*]
by
N[+ 1] Ns
end rule
Figura 5.11 – Exemplo de regra de um passo
4.1. Funções Embutidas
TXL fornece um conjunto de funções comuns que são difíceis ou ineficientes de serem
implementadas diretamente. A seguir temos algumas destas funções descritas com base em
[CORDY et al., 2000]:
50
Operações Aritméticas N1 e N2 devem ser [number] ou outro tipo
numérico
N1 [+ N2]
N1 [- N2]
N1 [* N2]
N1 [/ N2]
N1 [div N2]
N1 [rem N2]
Soma
Subtração
Multiplicação
Divisão
Quociente da divisão inteira
Resto da divisão inteira
Operações com Texto T1 e T2 são tipos compostos por caracteres,
como [stringlit], [id] e [charlit]
T1 [+ T2]
N1 [# T1]
Concatenação
Tamanho do texto T1
Operações com Identificadores ID1 e ID2 devem ser do tipo [id]
ID1 [_ ID2]
ID1 [!]
Concatenação
Identificação única numérica utilizando o
ID1. Por exemplo: Se ID1 é „Bob‟, o
resultado será „Bob10‟
Operações com Seqüências R1 e R2 são repetições de algum tipo [repeat X]
R1 [. R2]
N1 [length R1]
R1 [select N1 N2]
R1 [head N1]
R1 [tail N1]
R1 [^ X1]
Concatenação
Tamanho da seqüência R1
Substitui R1 pelos seus elementos de N1
até N2
Substitui R1 pelos seus N1 primeiros
elementos
Substitui R1 pelos seus N1 últimos
elementos
Substitui R1 com um seqüência constituída
de cada sub-árvore do tipo [T] contida em
X1 (Função de Extração)
Operações com Listas L1 e L2 são listas de algum tipo [list X]
L1 [, L2]
N1 [length L1]
L1 [select N1 N2]
L1 [head N1]
L1 [tail N1]
Concatenação
Tamanho da lista L1
Substitui L1 pelos seus elementos de N1
até N2
Substitui L1 pelos seus N1 primeiros
elementos
Substitui L1 pelos seus N1 últimos
elementos
Comparações Numéricas
N1 [= N2]
N1 [~= N2]
N1 [> N2]
N1 [>= N2]
N1 [< N2]
N1 [<= N2]
Verifica se N1 é igual a N2
Verifica se N1 é diferente a N2
Verifica se N1 é maior a N2
Verifica se N1 é maior ou igual a N2
Verifica se N1 é menor a N2
Verifica se N1 é menor ou igual a N2
Comparações com Texto
T1 [= T2]
T1 [~= T2]
T1 [> T2]
T1 [>= T2]
T1 [< T2]
T1 [<= T2]
Verifica se T1 equivale a T2
Verifica se T1 é diferente a T2
Verifica se o tamanho de T1 é maior que T2
Verifica se o tamanho de T1 é maior ou
igual que T2
Verifica se o tamanho de T1 é menor que T2
Verifica se o tamanho de T1 é menor ou
igual que T2
Figura 5.12 – Algumas funções embutidas
51
4.2. Variáveis
Todas as variáveis TXL são locais para a regra na qual elas estão introduzidas [CORDY
et al., 2000]. Variáveis são apenas nomes atribuídos a sub-árvores de um determinado tipo para
os quais serão feitas referências posteriormente. No exemplo da figura 5.13, a variável N
denota uma árvore do tipo [number], ou seja, um número. Existe em TXL uma variável
anônima representada pelo caracter sublinhado “_” que denota uma variável sem nome sendo
explicitamente tipada e que não pode ser referenciada.
Variáveis podem ser quebradas em pequenas partes através da cláusula deconstruct e
novas variáveis podem ser criadas através da cláusula construct, ou seja, respectivamente é
possível desmontar e montar árvores de um certo tipo dado.
% Definição da gramática
define program
[number*]
end define
% Funções de Tranformação
function main
replace [program]
P[program]
deconstruct P % Desmonta a árvore P
N[number] OutrosN[number*]
construct NovoP[program] % Cria uma nova árvore do tipo [program]
N[+ 1] OutrosN[TrataOutros]
by
NovoP
end function
function TrataOutros
replace [number*]
N[number] OutrosN[number*]
by
N[+ 1] OutrosN[TrataOutros] % Função recursiva
end function
Entrada: 1 3 4 2 5 6 1 2 0
Saída: 2 4 5 3 6 7 2 3 1
Figura 5.13 – Exemplo com construct e deconstruct
52
Um tipo especial de “deconstrutor” (deconstruct) poder ser utilizado para “desmontar”
uma árvore, uma sub-árvore de um dado tipo que esteja de acordo com o padrão dado. A figura
5.14 apresenta a sintaxe deste “deconstrutor” de busca. Deve-se ressalvar que o tipo [Type] é
opcional.
deconstruct * [type] Arv
padrão
Figura 5.14 – Exemplo de função com parâmetro [CORDY et al., 2000]
Variáveis globais podem ser criadas utilizando a cláusula export, atuando exatamente
como o construtor. Já o acesso as variáveis globais é feito através da cláusula import. Tanto o
export quanto o import podem aparecer em algum ponto antes do replacement do corpo de
uma regra ou função. A figura 5.15 apresenta a sintaxe para estas cláusulas.
export NomeVar [tipo]
troca
import NomeVar [tipo]
padrão
Figura 5.15 – Sintaxe da cláusula export e import
Caso uma variável seja re-exportada, esta permanecerá com a definição mais atual até ser
redefinida.
Variáveis locais e importadas também podem ser exportadas. Neste caso, o tipo não é
especificado, pois o mesmo já foi previamente definido e a troca não necessita ser especificada
se o desejado for manter sua definição atual.
Na importação, o padrão é opcional, mas caso exista, possui a semântica idêntica ao
“deconstrutor”.
Caso uma variável tenha sido previamente importada ou exportada e venha ser (re)-
importada dentro da regra ou função, na qual ela se encontra, não será necessário especificar o
tipo.
53
A figura 5.16 apresenta um código em TXL que concatena seqüências de números
fornecidos pela entrada, pela importação e pela construção. É interessante ressaltar que a
cláusula export na função Adiciona modifica o conteúdo da variável N para o valor mais atual.
define program
[number*]
end define
function main
replace [program]
P[program]
export N[number*]
6 7 8 9 10
by
P[Adiciona]
end function
function Adiciona
replace [program]
P[number*]
import N[number*]
construct N2[number*]
11 12 13 14 15
export N % N conterá números de 6 a 15
N[. N2]
by
P[. N]
end function
Entrada: 1 2 3 4 5
Saída: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Figura 5.16 – Exemplo de código com import e export
4.3. Condições
Em TXL, durante a fase de matching, é possível acrescentar condições lógicas sobre uma
seqüência de regras aplicadas a uma variável simples, como X[E_numero][E_identificador].
CONDIÇÃO DESCRIÇÃO
where É verdadeiro se pelo menos uma das regras aplicadas
encontra uma combinação com seu padrão.
where not É verdadeiro se nenhuma das regras aplicadas encontra
uma combinação com seu padrão.
where all É verdadeiro se todas as regras aplicadas encontram
uma combinação com seu padrão.
where not all É verdadeiro se pelo menos uma regra não encontra uma
combinação com seu padrão.
Figura 5.17 – Condições
54
A figura 5.18 apresenta um exemplo utilizando uma condição. O objetivo deste exemplo
é substituir em uma seqüência de números os que são menores que 20, conforme a condição
where N[< 20], pelo seu dobro. É interessante notar que como está sendo utilizado uma regra,
esta será aplicada iterativamente enquanto o resultado do dobro de cada número da seqüência
for menor que 20.
% Definição da gramática
define program
[repeat number]
end define
% Regra de Transformação
rule main
replace [number]
N [number]
where N[< 20]
by
N [* 2]
end rule
Entrada: 3 4 2 5 7
Saída: 24 32 32 20 28
Figura 5.18 – Exemplo com condição
Para concluir o código para o exemplo da figura 5.1, a próxima figura apresenta regras de
transformação para o exemplo proposto.
Figura 5.19 – Exemplo de regras de transformação [FELIX, HAEUSLER, 1999]
rule main
replace [program]
x[E]
construct Aux[E]
x[traduzSoma]
[traduzMult]
[traduzPar1]
[traduzPar2]
where not
Aux[= x]
by
Aux
end rule
rule traduzSoma
replace [E]
a[T] + b[E]
by
+ a b
end rule
rule traduzMult
replace [T]
a[F] * b[T]
by
* a b
end rule
rule traduzPar1
replace [F]
'( + a[T] b[E] ')
by
+ a b
end rule
rule traduzPar2
replace [F]
'( * a[F] b[T] ')
by
* a b
end rule
55
4.4. Regras ou Função de Condição
Denominamos regras ou funções de condição aquelas que podem ser utilizadas em
condições (cláusulas where) para testar se o escopo para esta regra ou função combina com o
padrão da mesma tornando a condição verdadeira.
A figura 5.20 apresenta um exemplo de função de condição que verifica se existe alguma
referência para o identificador I na seqüência de identificadores STATE_SEQ. Caso exista esta
referência, a condição se tornará verdadeira e o número N será incrementado. Caso contrário, o
número N permanecerá inalterado.
function UpdateWithSeq I[id]
import STATE_SEQ[id*]
replace [number]
N[number]
where
STATE_SEQ[ID_Reference I]
by
N[+ 1]
end function
% A função de condição verifica se existe referência para I
function ID_Reference I[id]
match * [id] % Busca no escopo um identificador que combine com o
I % padrão dado, no caso I.
end function
Figura 5.20 – Exemplo de função de condição
É possível, ao invés de criar uma função de condição, testar o reconhecimento de padrões
para satisfação de uma condição utilizando regras ou funções de transformação. Para isto, basta
preceder ao nome da regra ou função o símbolo „?‟. Desta forma, será verificado se o escopo
dado para esta regra ou função combina com o padrão dado, tornando a condição verdadeira.
A figura 5.21 apresenta um exemplo que verifica se o número dado como escopo da
função main equivale ao padrão da função VerificaUm, ou seja, verifica se o número é igual a
um. Em caso afirmativo, o número é incrementado. Caso contrário, o número permanece
inalterado.
56
define program
[number]
end define
function main
replace [program]
N[number]
where
N[? VerificaUm]
by
N[+ 1]
end function
function VerificaUm
replace [number]
1
by
0
end function
Entrada: 1 3
Saída: 2 3
Figura 5.21 – Exemplo utilizando função transformacional
5. Formatação
TXL fornece alguns não-terminais que podem ser incluídos na gramática, não tendo
nenhum efeito na fase de parsing e transformação, somente na fase de unparsing na qual a
árvore de saída é percorrida em ordem para dar um formato textual. Alguns destes não-
terminais são apresentados abaixo:
NÃO TERMINAL DESCRIÇÃO
[NL] Força uma nova linha
[IN] Aumenta o recuo em quatro espaços
[IN_NN] Aumenta o recuo em NN espaços
[EX] Diminui o recuo em quatro espaços
[EX_NN] Diminui o recuo em NN espaços
[SP] Acrescenta um espaço
[SP_NN] Acrescenta NN espaços
[SPOFF] Retira todo o espaçamento da saída
[SPON] Habilita o espaçamento da saída
Figura 5.22 – Alguns não-terminais de formatação da saída
57
Por padrão, TXL acrescenta um espaço entre caracteres especiais (de pontuação). Por
exemplo, o operador de atribuição do Pascal (:=) não deve conter espaços, mas ao utilizar o
TXL para transformar algum formalismo em Pascal, este operador apresentará um espaço entre
os dois caracteres especiais (: =). De forma a evitar isto, TXL inclui a declaração compounds
na qual cada item incluído nesta declaração será interpretado pelo TXL como um simples
símbolo terminal. Caso o caracter seja reservado do TXL, como o caracter de comentário (%),
este deverá ser precedido por uma aspa simples conforme na figura 5.23.
compounds
:= >= <= „%=
end compounds
Figura 5.23 – Exemplo de declaração compounds
6. MGM versus MGA
Podemos definir dois métodos de programação TXL: o método da gramática misturada
(MGM) e o método da gramática achatada1 (MGA).
O primeiro método, o MGM, utiliza somente regras de transformação e a gramática
define a sintaxe da linguagem fonte e alvo garantindo a correção sintática do resultado das
transformações. Com a utilização de regras, como já foi explanado, o escopo é varrido várias
vezes o que torna a eficiência deste método questionável. Outro ponto relevante é a dificuldade
da definição da gramática misturada que, para muitos problemas reais, pode ser problemática.
Assim como má estrutura de dados pode induzir um mau algoritmo, nesse paradigma; as
transformações irão refletir em seu código os problemas estruturais que porventura existam na
gramática (que define a estrutura do dado a ser transformado).
O segundo método, o MGA, utiliza somente funções e o programador necessita definir
somente a gramática da linguagem fonte. A tradução é realizada através da concatenação de
uma seqüência de tokens guiado pela estrutura sintática da entrada, ou seja, “tradução dirigida
por sintaxe”. A correção sintática da sentença traduzida é dada por construção [FELIX,
1 Este nome se deve ao fato de que as árvores da linguagem alvo possuírem apenas um nível, uma vez que são
uma seqüência de tokens.
58
HAEUSLER, 1999]. É interessante notar que em alguns casos existe a necessidade de se
percorrer todo escopo até mais de duas vezes, atentando para utilização de regras ou outros
métodos e técnicas. Informações relevantes sobre estes métodos de programação TXL podem
ser obtidas em [FELIX, HAEUSLER, 1999].
7. O Tradutor SIM2C
No anexo A, apresentamos o tradutor SIM2C (SIMPLES para C) que servirá como uma
boa experiência para introdução ao estudo da programação transformacional com TXL.
SIMPLES é uma linguagem teórica, composta por poucas instruções (figura 5.24) e,
como o próprio nome diz, bastante elementar. Ela é utilizada na disciplina de Teoria da
Computação em cursos de graduação em Ciência da Computação para mostrar que qualquer
programa, em qualquer formalismo de programação, pode ser reduzido a esse conjunto mínimo
de instruções.
Instrução Significado
dat X1..Xn Aloca n variáveis inteiras na memória.
res X Atribui o valor 0 a variável X (X = 0).
inc X Incrementa X (X = X + 1).
cop X Y Copia o valor de Y para X (X = Y).
jum L Desvio incondicional para instrução rotulada com L:
Do X <bloco> od Repete as instruções de <bloco> X vezes.
get X Ler um valor para X da entrada padrão (teclado).
out X Escreve o valor de X na saída padrão (monitor).
Figura 5.24 – Instruções da linguagem SIMPLES
Este tradutor foi construído baseando-se no MGM que, num primeiro momento, é mais
fácil de se compreender. A tradução para a linguagem C foi escolhida devido à facilidade de
manipulação de sua estrutura sintática, porém para compilar o resultado da operação será
59
necessário utilizar o compilador C++. A figura 5.25 apresenta o mapeamento das instruções
SIMPLES para as da linguagem C.
Instrução SIMPLES Instrução C
dat X1 ... Xn int X1, ..., Xn;
res X X = 0;
inc X X++;
cop X Y X = Y;
jum L goto L;
do X <bloco> od For (int _X1 = 0; _X1 < X; _X1++)
{<bloco>}
get X printf(“X = ”); scanf(“%d”,&X);
out X printf(“X = %d”,X);
Figura 5.25 – Mapeamento SIMPLES para C
Como dificuldade, temos a tradução do comando de repetição LOOP para C. Pelo fato de
que na linguagem C é necessária uma variável para funcionar como contador ou índice da
repetição, a criação dessa torna-se um fator considerável se pensarmos na composição de
comandos de repetição. Como solução, atribuímos ao nome da variável do comando LOOP em
SIMPLES (X), um identificador único e um símbolo de sublinhado que o precede (_X1)
criando, assim, a variável contadora ou índice em C. Porém, esta solução restringiu a definição
dos nomes de variáveis iniciarem com o símbolo de sublinhado não permitindo, dessa forma,
que exista algum conflito entre o nome da variável criada e de uma variável definida pelo
usuário.
60
Capítulo 6
O Tradutor NCL2TA
1. Introdução
Extrair um modelo de autômatos temporizados da especificação hipermídia poderá ser
tornar uma tarefa árdua e sujeita a erros, como qualquer processo de modelagem. Nesta
direção, podemos propor um mecanismo automático de geração de modelos passíveis de
validação, minimizando a proliferação de erros e o método de trabalho para validação de
requisitos de projeto, ou seja, a validação de documentos hipermídia seria efetuada,
teoricamente, a partir de sua especificação textual o que tornaria o trabalho mais rápido e
eficiente.
Este novo método visa extrair de uma especificação NCL (capítulo 2 – seção 3) um
modelo de autômatos temporizados especificado no formato TA (Timed Automata),
reconhecido por UPPAAL, utilizando o tradutor NCL2TA desenvolvido a partir da linguagem
transformacional TXL.
2. O Meta-Modelo Hipermídia em UPPAAL
A seguir, é apresentada uma proposta de mapeamento em autômatos temporizados de
documentos hipermídia propondo o desenvolvimento de um meta-modelo para validação em
UPPAAL. A partir deste mapeamento, será possível descrever como as especificações NCL
podem ser transformadas em autômatos temporizados.
O presente trabalho considera apenas o mapeamento dos conceitos NCM apresentados no
documento exemplo do capítulo 2, seção 4. Tem-se como trabalho futuro o mapeamento de
outros conceitos propostos.
61
User
Figura 6.1 – O autômato User
O autômato User – Este autômato representa a ação do usuário sobre o documento. O
canal StartEi! inicializa o evento de seleção Ei e, na mesma transição, o relógio global ck é
reiniciado. O canal endC? recebe o sinal de finalização da apresentação da composição C dado
pelo evento de seleção.
Eventos de Seleção
Figura 6.2 – O autômato dos Eventos de Seleção
Eventos de Seleção – O evento associado à ação do usuário sobre o documento é
denominado evento de seleção. Este evento é finalizado pelo evento associado à última mídia a
ser apresentada, o qual denominamos evento Ender.
Eventos de Apresentação
Figura 6.3 – O autômato dos Eventos de Apresentação
EStart? ck_e := 0 ck_e <= MAX
EStop! ck_e >= MIN
StopE?
EiStart?
endC!
EiStop?
StartEi! ck := 0
endC?
C
62
Eventos de Apresentação – Cada evento de apresentação possui um relógio próprio
ck_e que representa a duração da apresentação da mídia limitada por um tempo mínimo MIN e
máximo MAX. Caso MIN seja infinito, a transição correspondente não existirá no modelo.
Caso MAX seja infinito, o invariante correspondente não existirá no modelo.
A transição com o guarda representa a finalização da apresentação da mídia num tempo
pré-definido; já a outra transição, com apenas um canal de comunicação, representa a
paralisação da apresentação devido alguma ação produzida por um elo, o que permite a
finalização da mídia num tempo inferior ao pré-definido. Esta última não existirá somente se o
tempo mínimo não for infinito e não existir alguma ação stop(E) para o evento. Caso nenhum
elo receba o sinal de parada do evento (condição), então o canal EStop! não existirá.
Delay
Figura 6.4 – O autômato Delay
O autômato Delay – Cada ação delay(N) num elo possui um autômato com um relógio
próprio ck_d que representa a duração do atraso. O canal DelayNSp! existirá apenas quando o
delay(N) for A1 num seqüenciamento completo (A1;A2).
Broadcast (a) Broadcast (b)
Figura 6.5 – O autômato Broadcast
CHin? cont := NP
cont <= 1
CHout!
C
EiStop!
Ender
C
cont > 1
CHout!
cont := cont - 1
CHin? cont := NP
CHout! cont <= 1
C
DelayNSt? ck_d := 0
DelayNSp! ck_d == N ck_d <= N
cont > 1
CHout!
cont := cont - 1
63
O autômato Broadcast – O autômato Broadcast (a) é responsável por receber sinais dos
outros autômatos e encaminhá-los a todos os autômatos que necessitam receber aquele sinal.
CHin representa o canal que receberá o sinal de entrada (StartE ou EStop para um dado evento
E), CHout representa o canal para onde o sinal será enviado (EStart ou StopE para um dado
evento E) e NP representa a quantidade de autômatos que necessitam receber aquele sinal.
Um caso especial, Broadcast (b), ocorre quando o canal CHin sinaliza a finalização da
apresentação da última mídia a ser apresentada de uma composição (eventos Ender). Neste
caso, é acrescentado um estado committed Ender que, ao deixá-lo, sinaliza o término do
evento de seleção Ei que por sua vez finaliza a apresentação do documento.
Como a identificação dos atrasos (delays) depende diretamente de uma ação aplicada em
um elo e como cada atraso possui seu autômato exclusivo, não existirão relacionamentos entre
os autômatos delay e broadcast, sendo a comunicação ao autômato representativo do atraso
feita diretamente pelo autômato do elo que o gerou.
Elos
Figura 6.6 – Autômato dos Elos
Os elos no NCM definem um par condição-ação que no modelo é separado por um
estado committed conforme a figura 6.6. Cada condição ou ação é modelada conforme a
representação apresentada na figura abaixo.
CONDIÇÃO DO ELO
C1 and C2 C1 or C2 E.start / E.stop
Canais EStart? / StopE? respectivamente.
C2
C1
C1 C2
CONDIÇÃO
AÇÃO
C
C
64
AÇÃO DO ELO
A1 || A2 A1 ; A2 start(E)
Canal StartE!, mas se for A1 em A1;A2 será:
Delay(N) stop(E)
Canal DelayNSt!, mas se for A1 em A1;A2 será:
Canal StopE!.
Figura 6.7 – Par Condição-Ação dos Elos
3. Uma Metodologia de Tradução da NCL para TA
O evento Ender apresentado na seção anterior não faz parte da especificação original
NCL. Este evento equivale ao evento de apresentação associado à última mídia do documento
e foi identificado para sinalizar o fim da apresentação do documento modelado em UPPAAL.
Para representar o evento Ender na NCL e, assim, modelá-lo a partir do tradutor
proposto, foi acrescentado à NCL uma última declaração Ender na qual estes eventos são
identificados pelo nome dos eventos de apresentação correspondentes. Por exemplo, na
especificação NCL da seção 4 do capítulo 2 será incluída, ao final a declaração, Ender E8,
definindo que o evento E8 é o responsável pela apresentação da última mídia.
O desenvolvimento do tradutor baseou-se somente em funções TXL, mas não considerou
totalmente o Método da Gramática Achatada (MGA) – capítulo 5, seção 6 – principalmente
pela necessidade da formatação do resultado da transformação a partir da gramática da
linguagem destino. Para este trabalho, considerou-se que toda apresentação de um documento
inicia-se pela ação do usuário (autômato User) que acionará a inicialização de um evento de
seleção e este formalizaria a apresentação do documento como um todo. Assim sendo, ao
finalizar o autômato do evento de seleção em questão, indicaria a finalização da apresentação
StartE! StopE?
A1 A2
A1 A2
C
DelayNSt! DelayNSp?
65
propriamente dita. De forma a representar este fator em TXL, a gramática apresentada foi
levemente modificada, conforme mostra a figura 6.8.
Gramática Original
define COMPOSITION
comp [id][NODE*][EVENT*][LINK*]
end define
define NODE
term [id][EVENT*]
| [COMPOSITION]
end define
define EVENT
ev [id][ANCHOR][TYPE][DESCRIPTION]
end define
define TYPE
prs | sel | att
end define
Gramática Modificada
define COMPOSITION
comp [id][NODE*][SEL_EVENT*][LINK*] ender [id*]
end define
define NODE
term [id][PRS_EVENT*]
| [COMPOSITION]
end define
define PRS_EVENT
ev [id][ANCHOR] prs [DESCRIPTION]
end define
define SEL_EVENT
ev [id][ANCHOR] sel [DESCRIPTION]
end define
Figura 6.8 – Gramática dos nós de apresentação e seleção
66
Os eventos de apresentação e seleção foram explicitamente identificados pelo fato da
árvore construída para os nós de apresentação estar agregando os nós de seleção deixando a
árvore dedicada aos eventos de seleção sem conteúdo. Pode-se até argumentar a questão da
identificação dos eventos (prs | sel) que poderia ser cada um deles alocado via código TXL na
árvore correspondente, mas a definição explícita destas duas árvores facilita a construção do
tradutor até o ponto desejado do presente trabalho.
No anexo B, encontra-se todo o código TXL referente ao tradutor NCL2TA. Como já se
sabe, o formato TA não armazena informações gráficas do modelo, porém a interface gráfica
do UPPAAL reconhece a linguagem e faz uma tentativa de organizar o modelo na tela. A
figura 6.9 apresenta a representação gráfica do modelo construído pelo tradutor proposto e,
para efeito de entendimento, o leitor encontra na figura 6.10 o modelo corrigido manualmente.
Figura 6.9 – Modelo criado pelo tradutor NCL2TA
67
Figura 6.10 – Modelo criado pelo tradutor NCL2TA corrigido manualmente.
4. Validação do documento hipermídia
Ao verificar se o modelo satisfaz a fórmula A[] not deadlock (É sempre verdade que não
há deadlock) obtém-se como resultado uma mensagem indicando que a propriedade expressa
pela fórmula não se verifica no modelo. Isto significa que o modelo construído não atende ao
requisito desejável que expressamos com a fórmula.
A seguir apresentamos alguns passos do trace encontrado como contra-exemplo por
UPPAAL, numa seqüência temporal decrescente, a partir da possível localização do estado
(mundo) em que ocorreu o deadlock.
68
[7] L5 sinaliza E8Stop!
E7.ck_e = 6
E5.ck_e = 9
Delay3_1.ck_d = 9
[6] L5 recebe o sinal StopE7?
E7.ck_e = 6
E5.ck_e = 9
Delay3_1.ck_d = 9
[5] E7 termina
E7.ck_e in [0,6]
E5.ck_e in [7,9]
Delay3_1.ck_d in [7,9]
[4] E7 inicia
E7.ck_e in [3,inf]
E5.ck_e in [3,7]
Delay3_1.ck_d in [3,7]
[3] L3 sinaliza StartE7!
E7.ck_e in [3,inf]
E5.ck_e in [3,7]
Delay3_1.ck_d in [3,7]
[2] L3 recebe o sinal Delay3_1Sp?
E5.ck_e in [0,3]
Delay3_1.ck_d in [0,3]
[1] L3 sinaliza Delay3_1St!
E5.ck_e = 0
Em [2] podemos verificar que as máquinas Delay3_1 e E5 iniciam em paralelo. Quando
Delay3_1 termina, E7 é iniciada no mesmo instante, conforme apresentado em [3]. Assim,
podemos perceber em [7] que o tempo gasto por Delay3_1 até o término de E7 equivale à
duração da apresentação relacionada à máquina E5.
A figura 6.11 apresenta um gráfico temporal com a distribuição do tempo destes eventos
de apresentação conforme o trace apresentado.
Figura 6.11 – Gráfico temporal dos eventos
Como pode ser visto, as máquinas E7 e E5 concorrem pela sua própria finalização. De
acordo com o trace, E7 terminou primeiro que E5, pois sinalizou a finalização de E8 a partir da
condição atribuída no elo L5 (ver [7]). Segundo a especificação do documento, o término de
E5 inicializa a apresentação de E8, portanto este deve sempre terminar primeiro que E7. Esta
0 1 2 3 4 5 6 7 8 9
Unidades de Tempo
E5
Delay
E7
69
situação não está sendo possível. Assim, o evento E8 nunca chegará ao fim e,
conseqüentemente, a apresentação da composição C não poderá ser concluída, caracterizando
uma indesejável situação de deadlock.
A figura 6.12 apresenta os processos envolvidos no deadlock através do simulador do
UPPAAL.
Figura 6.12 – Simulação exibindo uma situação de deadlock
A possibilidade de E7 iniciar no mesmo instante que Delay3_1 termina se deve à ação
(A1;A2) que os relaciona, conforme definido no elo. Como tentativa de solucionar o problema
do deadlock propomos evitar a possibilidade de E7 finalizar no mesmo instante Delay3_1. Esta
solução tem duas implementações: a) poderíamos aumentar o tempo de atraso em uma unidade
o que tornaria o documento consistente, mas poderia prejudicar a visualização pelo usuário do
mesmo; b) poderíamos modificar parcialmente o conceito da ação (1;2), para passar a
garantir que o início de E7 se dá após o fim de Delay3_1 e nunca no mesmo instante.
poderíamos expressar esta ação pela seguinte expressão de ação no elo: (1;delay();2)8 que
significa “após o fim da ação A1, e pasado algum delay, a ação A2 inicia”.
8 NCL oferece o operador delay(N) onde fixamos um valor de tempo. O que propomos exigiria que esse operador de ação permita um delay
sem tempo fixado e isto pode ser facilmente acrescentado à semântica de NCL.
70
A proposta tenta manter a boa apresentação do documento para o usuário. Porém na
especificação delay(3);start(E7), conforme definição desta ação, E7 não possui um tempo
certo atribuído para ser iniciado, o que caracteriza uma situação de starvation. O que também
pode ocorrer é que E7 termine num tempo ínfimo em relação à E5 fazendo com que E8 seja
apresentado neste período (Lembre que E5 inicia E8 e E7 finaliza-o). De acordo com a
especificação exemplo, estas duas situações são possíveis, cabendo ao especificador decidir por
qual correção irá efetuar sobre a especificação inicial.
Outras propriedades a serem verificadas podem ser encontradas no capítulo 4 (seção 2.2).
71
Capítulo 7
Considerações Finais
1. Revisão Final
É considerável a grande quantidade de sistemas de tempo real utilizados em aplicações
críticas. Portanto, torna-se essencial a validação de tais sistemas quanto à verificação de
propriedades temporais. Para aplicar tal validação, métodos formais têm sido amplamente
utilizados visto que, os métodos tradicionais de teste de sistemas não apresentam a eficácia
necessária quando estes sistemas incluem aspectos de tempo real.
Neste contexto, incluem-se os documentos hipermídia como sistemas que consideram o
tempo um fator crítico, principalmente no que diz respeito à qualidade do produto final. Assim,
a validação destes documentos é considerável, pois deseja-se manter a estrutura lógico-
temporal do documento, segundo sua especificação, através de um método formal competente
e eficiente como a Verificação de Modelos.
O presente trabalho propôs uma metodologia de validação onde, por meio de um
tradutor, é gerada uma rede de autômatos temporizados a partir da especificação de um
documento hipermídia. O modelo de autômatos temporizados gerado é fornecido para um
verificador de modelos (UPPAAL), iniciando-se então a fase de validação de requisitos para a
apresentação. É sabido que validar requisitos, nesta fase inicial do desenvolvimento, reduz
custos futuros no ciclo de vida da apresentação, o que foi exemplificado por nós.
2. Trabalho Relacionado
Como mencionado anteriormente, o objetivo do tradutor é criar um modelo de autômatos
temporizados a partir de uma NCL. Este modelo baseia-se em uma descrição formal utilizada
por ferramentas verificadoras de modelos.
72
Este trabalho concentra-se na tradução da NCL em um formato TA reconhecido pela
ferramenta UPPAAL, mas existem outros formatos e ferramentas para validação de sistemas
como hipermídia. Dentre estas ferramentas, podemos destacar RT-LOTOS (Real Time –
Language Of Temporal Ordering Specification), Verus, RT-SPIN, entre outros.
Um trabalho semelhante [Santos et al., 1998] utiliza RT-LOTOS para descrever o
comportamento de apresentações hipermídia especificadas conforme o NCM, mas não
esclarece como realizar a verificação.
2.1. RT-LOTOS: Conceitos Básicos
Em LOTOS, um sistema é visto como um processo composto por outros processos e que,
por sua vez, podem ser compostos de outros processos, sincronizados através de portas
formando uma estrutura parecida ao nó de composição do NCM.
A figura 7.1 exibe um nó de composição (Composite Node) representado em RT-LOTOS
com sua lista de parâmetros que correspondem aos descritores dos nós, elos e âncoras.
Cada nó (nodeID) possui um conjunto de portas start e end caracterizando o início e o
fim de sua apresentação; user associada à interação do usuário sobre uma âncora; e trigger que
corresponde à interação do usuário sobre a âncora de um outro nó, mas que afeta a
apresentação do nó em questão.
Após a sincronização com a porta start do nó de composição, o sistema passa para o
processo nodeBody que descreve a estrutura interna da composição que é modelada pelos
processos nodePresentations e nodeConstraints. O nodePresentations corresponde à
composição paralela de um conjunto de nós de composição e de conteúdo (nodeStructure) e de
um conjunto de âncoras (nodeInteractions); já o nodeConstraints corresponde à composição
paralela de processos link que modelam as diversas interações entre os processos da
composição.
73
Figura 7.1 – O modelo NCM em RT-LOTOS
Esta é apenas uma visão bastante simples do trabalho de Santos et al. [1998] no final
poderão ser pesquisadas mais informações. Este presente trabalho e o trabalho proposto por
Santos et al. [1998] visam a um objetivo comum quanto à representação dos conceitos NCM
em outro formalismo. Visto que o processo de modelagem das estruturas NCM em RT-LOTOS
apresenta um certo grau de dificuldade tanto na descrição quanto na detecção de erros, o
proposto trabalho oferece o conhecimento para implementação de modelos com alto nível de
abstração, maior que o RT-LOTOS, facilitando o trabalho para iniciantes. Também propõe um
recurso de modelagem automático a partir da NCL o que reduzirá o trabalho e a existência de
erros.
74
3. Trabalhos Futuros
Entre as perspectivas de trabalhos futuros, está a melhoria do mapeamento de NCM para
o modelo de autômatos temporizados implementado pelo tradutor construído, incluindo o
mapeamento e devida tradução dos conceitos NCM não considerados neste trabalho. Além
disso, podemos vislumbrar a aplicabilidade deste método quando estendido para permitir a
validação de arquiteturas de software de tempo real quando especificadas por uma alguma
linguagem de descrição de arquitetura de software (ADL). Segundo Muchaluat-Saade e Soares
[2001], existem fortes relacionamentos entre linguagens de autoria para sistemas hipermídia,
como a apresentada neste trabalho (NCL) e algumas ADLs conhecidas. O anexo C apresenta
uma pequena introdução sobre Arquitetura de Software.
3.1. Hipermídia e a Arquitetura de Software
Observando atentamente as estruturas NCM e de Arquitetura de Software, podemos
descrever algumas semelhança entre elas. A figura a seguir, apresenta uma comparação entre
estas estruturas.
Figura 7.2 – Relacionamentos entre Hipermídia e Arquitetura
AArrqquuiitteettuurraa
HHiippeerrmmííddiiaa AArrqquuiitteettuurraa ddee
SSooffttwwaarree
Nó Terminal Componente
Nó de Composição Componente
Modular
Link Conector
Âncora Porta/Papel
Documento Configuração
NCL ADL
75
O relacionamento apresentado na figura 7.2 permite-nos propor a aplicação do trabalho
de validação sobre a arquitetura de software. Pensando nesta possibilidade, podemos também
propor o mapeamento das estruturas da arquitetura em autômatos temporizados e, assim,
aplicar métodos formais para validar tal sistema, principalmente pelo uso de verificadores de
modelo como UPPAAL.
Figura 7.3 – Mapeamento de estruturas de arquiteturas em TA
A figura 7.3 apresenta justamente esta nova metodologia que, inclusive, permite alterar
alguns aspectos do tradutor proposto neste trabalho para gerar o modelo em UPPALL de forma
automática.
Apesar de parecer simples, é importante ressaltar que o mapeamento entre ADLs e
Linguagens de Autoria Hipermídia, como a NCL, não é diretamente estabelecido
principalmente pelo fato de que existem algumas características das Arquiteturas que não
possuem representação em NCM. Devido a isto, Muchaluat-Saade e Soares [2001] propõem
um princípio de meta-modelo para relacionar estas duas estruturas.
O estudo mais aprofundado e a aplicação desta nova metodologia são sugestões para um
trabaho futuro.
Componente
(Nó)
gera
Autômato
Temporizado
Conector
(Elo)
gera
C1? C2!
C3!
Perguntas do tipo:
C1 pode executar depois de C2 e antes de C3 terminar.
C
C
76
Referências
Aceto L., Burgueño, A., Larsen, K. G. (1997) ”Model Checking via Reachability Testing for
Timed Automata”. Tools and Algorithms for Construction and Analysis of Systems
(TACAS'98), Lisboa, Portugal.
Antonacci, M. J. (2000) “NCL: Uma Linguagem Declarativa para Especificação de
Documentos Hipermídia com Sincronização Temporal e Espacial”. Tese de M.Sc., Pontifícia
Universidade Católica do Rio de Janeiro (PUC-Rio), Rio de Janeiro, Brasil.
Clarke, E. M., Wing, J. M. (1996) “Formal Methods: State of the Art and Future Directions”.
report by the Working Group on Formal Methods for the ACM Workshop on Strategic
Directions in Computing Research, ACM Computing Surveys, vol. 28, nº. 4.
Cordy, J. R., Carmichael, I. H., Halliday, R. (1995) “The TXL Programming Language
Version 8”. Legasys Corporation, Kingston.
David, A. (2002) “UPPAAL2k: Small Tutorial”. http://www.uppaal.com
Felix, M. F., Haeusler, E. H. (1998) “LET: Uma Linguagem para Especificar Transformações”.
III Simpósio Brasileiro de Programação (SBLP‟99), Porto Alegre, RS, Brasil.
Felix, M. F., Haeusler, E. H., Soares, L. F. G. (2002) “Validating Hypermedia Documents: a
Timed Automata Approach”. Monografias em Ciência da Computação - PUC-RJ, Brasil.
Garson, J. (2001) “Modal Logic”. In: Stanford Encyclopedia of Philosophy.
http://plato.stanford.edu/entries/logic-modal/ (acesso em 2001).
Grupo UPPAAL (2000) Lista de discussão da ferramenta de verificação de modelos UPPAAL.
http://groups.yahoo.com/group/uppaal/ (acesso em 2001/2002)
Larsen, K. G., Pettersson, P., Yi, W. (1997) “UPPAAL in a Nutshell”. In Springer International
Journal of Software Tools for Technology Transfer, vol 1.
Mendes, A. (2002) Arquitetura de Software: desenvolvimento orientado para arquitetura.
Editora Campus. Rio de Janeiro, RJ, Brasil.
Muchaluat-Saade, D. C., Soares, L. F. G. (2001) “Towards the Convergence between
Hypermedia Authoring Languages and Architecture Description Languages”. I ACM
Symposium on Document Engineering (DocEng2001), Atlanta, Georgia, USA.
Pettersson, P. (2003). “UPPAAL2k”. http://www.uppaal.com (acesso em 2001/2002).
Pressman, Roger S. (1995) Engenharia de Software. 3ª edição. Makron Books. São Paulo, SP,
Brasil.
77
Rodriguez, N. L. R., Soares, L.F.G., Casanova, M.A. (1995) “NCM: A Conceptual Model for
Hyperdocuments”. Anais do I Workshop em Sistemas Hipermídia Distribuídos, São Carlos,
São Paulo, Brasil.
Ruys, T. C. (2001) Towards Effective Model Checking. Tese de D.Sc., Universiteit Twente,
Enschede.
Santos, C.A.S., Courtiat, J-P., Souza, G.L., Soares, L.F.G. (1998) “Um Modelo Formal para
Verificação da Consistência de Documentos Hipermídia NCM”. Anais do SBMIDIA'98, Rio
de Janeiro, Brasil.
Soares, L. F. G. (1995) “Hyperprop: Uma visão geral”. I Workshop em Sistemas Hipermídia
Distribuídos. São Carlos, SP, Brasil.
Soares, L. F. G., Souza, G. L. (1997) Modelo de Contextos Aninhados Segunda Versão.
Relatório técnico do laboratório de TeleMídia, Departamento de Informática PUC-Rio, Rio de
Janeiro, RJ, Brasil.
Soares, L.F.G., Casanova, M.A., Rodriguez, N. R. (1994) “Modelo de Contextos Aninhados –
Um Modelo Conceitual Hipermídia”. Revista Brasileira de Computação - Julho. p. 1-7.
Soares, L.F.G., Casanova, M.A., Souza, G.L. (1996) “Âncoras e Elos em Nós de Composição”.
Anais do XXIII Seminário Integrado de Software e Hardware, Recife, Pernambuco.
Souza, G. L. (1997) “Sincronismo na Modelagem e Execução de Apresentações de
Documentos Multimídia”. Tese de D.Sc., Pontifícia Universidade Católica do Rio de Janeiro
(PUC-Rio), Rio de Janeiro, Brasil.
TXL (2002) http://www.txl.ca (acesso em 2002)
Wing, J. M., Vaziri-Farahani, M. (1996) “A Case Study in Model Checking Software
Systems”. Science of Computer Programming, Janeiro 1996.
78
Anexo A – O Tradutor SIM2C
A.1 - Código do Tradutor SIM2C
A seguir é apresentado o código do tradutor SIM2C, criado em TXL, que gera um código
em linguagem C++ a partir do código em SIMPLES.
SIMPLES é uma linguagem téorica para mostrar que qualquer formalismo de programação
pode ser reduzido a um conjunto mínimo de instruções. A partir deste tradutor será possível
executar este conjunto mínimo de instruções.
O código deste tradutor pode ser aprimorado, mas seu principal objetivo é o aprendizado
da linguagem TXL. Como sugestão de estudo, poderíamos recriar este tradutor utilizando
somente funções TXL.
comments
//
/* */
end comments
compounds
'(" ",
end compounds
% ================ GRAMÁTICA =================
% A gramática baseia-se no Método da Gramática Misturada (MGM)
define program
% Define a estrutura principal do programa.
[DECLS] [CMDS] % Em SIMPLES
| [SPOFF] #'include [SP] <stdio.h> [NL] % Em C
void [SP] main'(') [SPON] [NL]
{ [IN]
[DECLS] [NL]
[CMDS] [EX]
}
end define
define DECLS
% Define um conjunto de declarações de variáveis.
[repeat DECL]
end define
define CMDS
% Define um conjunto de comandos.
[repeat CMD]
end define
define DECL
% Define a declaração de uma variável.
dat [NAME]
| [NL] int [NAME];
end define
79
define NAME
% Define nomes de variáveis.
[id]
| [NAME] [id]
| [NAME],[id]
end define
define CMD
% Define um comando.
[INSTRUCTION] [NL]
| [LOOPS] [NL]
| [JUMP]
end define
define JUMP
% Define o comando de desvio.
[SPOFF][id]:[SP][CMD][SPON]
| jum [id]
| [SPOFF] goto [SP] [id]; [NL] [SPON]
end define
define LOOPS
% Define o comando de repetição.
do [id] [CMDS] od
| [SPOFF] for'(int [SP]_[id]=0;[SP]_[id]<[id];[SP]_[id]++') [SPON][NL]
{ [NL] [IN] [CMDS] [EX]}
end define
define INSTRUCTION
% Define uma instrução.
[ASSIGMENT]
| [WRITE]
| [READ]
end define
define ASSIGMENT
% Define atribuições.
res [id]
| inc [id]
| cop [id] [id]
| [id]=0;
| [SPOFF][id]++;[SPON]
| [id]=[id];
end define
define READ
% Define a instrução de leitura.
get [id]
| [SPOFF] printf("[id][SP]=[SP]"); scanf("'%d",&[id]); [SPON]
end define
define WRITE
% Define a instrução de escrita.
out [id]
| [SPOFF] printf("[id][SP]=[SP]'%d\n ",[id]);[SPON]
end define
% ===== REGRAS =====
rule main
% Regra principal responsável por iniciar o processo de tradução.
replace [program]
P1[DECLS] P2[CMDS]
construct D[DECLS] % Constrói árvore de declarações
P1[TrataDECLS][TrataNAME]
where not
D [= P1]
construct C[CMDS] % Constrói árvore de comandos
P2[TrataLOOP][TrataJUMP]
[TrataREAD][TrataWRITE]
[TrataZero][TrataInc][TrataAtrib]
where not
C [= P2]
by
80
'#'include <stdio.h>
void main()
{
D
C
}
end rule
% ===== DECLARAÇÕES =====
rule TrataDECLS
% Trata as declarações de variáveis.
replace [DECL]
dat N[NAME]
by
int N;
end rule
rule TrataNAME
% Trata os nomes das variáveis.
replace [NAME]
B[NAME] A[id]
by
B,A
end rule
% ===== COMANDOS =====
rule TrataLOOP
% Trata o camando de repetição.
replace [LOOPS]
do N[id] C[CMDS] 'od
construct NID[id] % Constrói o índice do comando for.
N[!]
by
for'(int _ NID = 0; _ NID < N; _ NID++) { C }
end rule
rule TrataJUMP
% Trata o camando de desvio.
replace [JUMP]
jum A[id]
by
goto A;
end rule
rule TrataREAD
% Trata a instrução de leitura.
replace [READ]
get A[id]
by
printf("A = "); scanf("'%d",&A);
end rule
rule TrataWRITE
% Trata a instrução de escrita.
replace [WRITE]
out A[id]
by
printf("A = '%d\n ",A);
end rule
rule TrataZero
% Trata o comando reset.
replace [ASSIGMENT]
res N[id]
by
N = 0;
end rule
rule TrataInc
% Trata o camando de incremento.
replace [ASSIGMENT]
inc N1[id]
81
by
N1++;
end rule
rule TrataAtrib
% Trata o comando de cópia.
replace [ASSIGMENT]
cop N1[id] N2[id]
by
N1 = N2;
end rule
A.2 - Exemplos
A.2.1 - Divisão de Números Naturais
O código em SIMPLES a seguir realiza a operação de divisão de números naturais que não
é nativa da linguagem.
Código em SIMPLES Resultado da Transformação em C
dat CONT X Y K W
dat T P
res CONT
get X
get Y
inc X
L1: do X
do Y
res K
res W
do X
cop W K
inc K
od
cop X W
od
inc CONT
jum L1
od
res K
res W
do CONT
cop W K
inc K
od
out W
#include <stdio.h>
void main()
{
int CONT, X, Y, K, W;
int T, P;
CONT = 0;
printf("X = "); scanf("%d",&X);
printf("Y = "); scanf("%d",&Y);
X++;
L1: for(int _X1=0; _X1<X; _X1++)
{
for(int _Y1=0; _Y1<Y; _Y1++)
{
K = 0;
W = 0;
for(int _X2=0; _X2<X; _X2++)
{
W = K;
K++;
}
X = W;
}
CONT++;
goto L1;
}
K = 0;
W = 0;
for(int _CONT1=0; _CONT1<CONT; _CONT1++)
{
W = K;
K++;
}
printf("W = %d\n",W);
}
82
A.2.2 - Multiplicação de Números Naturais
Este outro exemplo realiza a operação de multiplicação de números naturais que também
não é nativa da linguagem SIMPLES.
Código em SIMPLES Resultado da Transformação em C
dat X Y Z
res Z
get X
get Y
do X
do Y
inc Z
od
od
G: jum K
K: jum P
P: out Z
#include <stdio.h>
void main()
{
int X, Y, Z;
Z = 0;
printf("X = "); scanf("%d",&X);
printf("Y = "); scanf("%d",&Y);
for(int _X1=0; _X1<X; _X1++)
{
for(int _Y1=0; _Y1<Y; _Y1++)
{
Z++;
}
}
G: goto K;
K: goto P;
P: printf("Z = %d\n",Z);
}
83
Anexo B – O Tradutor NCL2TA
B.1 – Código do Tradutor NCL2TA
A seguir é apresentado o código do tradutor NCL2TA, criado em TXL, que extrai um
modelo de autômatos temporizados, especificado na linguagem TA, a partir de uma
especificação NCM na linguagem NCL.
Com o modelo em TA, será possível utilizar um verificador de modelos como UPPAAL
para fazer a validação do mesmo a partir de um conjunto de propriedades pré-estabelecidas.
compounds
=> -> || == := <= >=
end compounds
tokens
% Acrescenta o caracteres "?" e "!" ao identificador.
id ... | "\u\i*[?!]"
end tokens
% ================== GRAMMAR =====================
define program
% Define toda a estrutura da entrada, ou seja, o documento hipermídia especificado em NCL.
% Como todo documento hipermídia é uma composição, program será composto por uma composição.
[COMPOSITION]
| chan [id,]; [NL][NL] clock ck; [NL] [PROC*] [NL] system [id,];
end define
define COMPOSITION
% Define a composição como um conjunto de nós e elos.
% A declaração ender define o último evento de cada visão do documento para que na construção
% dos autômatos seja possível representar o término da apresentação do documento hipermídia.
comp [id][NODE*][SEL_EVENT*][LINK*] ender [id*]
end define
define NODE
% Define os nós terminais e os nós de composição aninhados.
term [id][PRS_EVENT*]
| [COMPOSITION]
end define
define PRS_EVENT
% Define os eventos de apresentação.
ev [id][ANCHOR] prs [DESCRIPTION]
end define
define SEL_EVENT
% Define os eventos de seleção.
ev [id][ANCHOR] sel [DESCRIPTION]
end define
define ANCHOR
% Define a âncora associada ao nó.
'&[number]
| y
end define
84
define DESCRIPTION
% Define a descrição do nó: tipo de mídia, tempo mínimo e máximo de apresentação.
desc [MEDIA][number][number]
| desc null
end define
define MEDIA
% Define os tipos de mídia.
audio
| video
| text
| image
end define
define LINK
% Define os elos ficando claro o ponto de encontro (par condição/ação).
link [id][CONDITION] => [ACTION]
end define
define CONDITION
% Define as condições que devem ser satisfeitas no elo.
[id].[STATE]
| [CONDITION] or [CONDITION]
| [CONDITION] and [CONDITION]
end define
define STATE
% Define os estados de um evento.
start
| stop
end define
define ACTION
% Define as ações a serem aplicadas quando as condições num elo são satisfeitas.
start'([id]')
| stop'([id]')
| delay'([number]')
| [ACTION] || [ACTION]
| [ACTION] ; [ACTION]
end define
% ======================== TA_GRAMMAR =====================
define PROC
% Define um processo em TA.
[NL] process [id] { [NL] [IN] [DECL*] [BODY] [EX] [NL]}
end define
define DECL
% Define a declaração de variáveis.
[empty]
| int [id,]; [NL]
| clock [id,]; [NL]
| chan [id,]; [NL]
end define
define BODY
% Define o corpo de um processo.
state [SIL,]; [NL] [opCOMMIT] init [id]; [NL] [opTRANS]
end define
define SIL
% Define a declaração de estados.
[id][INV]
end define
define INV
% Define a declaração de invariantes.
[empty]
| { [INVL] }
end define
85
define INVL
% Define condições em invariantes.
[id] < [number]
| [id] <= [number]
end define
define opCOMMIT
% Define estados committed.
[empty]
| commit [id,]; [NL]
end define
define opTRANS
% Define as transições em um processo.
[empty]
| trans [IN] [TL,]; [EX]
end define
define TL
% Define uma transição.
[NL] [id] -> [id] { [G] [SINC] [ASS] }
end define
define G
% Define a declaração de um guarda.
[empty]
| guard [GL,];
end define
define GL
% Define as condições no guarda.
[CGUARD] | [IGUARD]
end define
define CGUARD
% Define as condições no guarda.
[id] [REL] [CEXPR] | [id] [REL] [id] | [id] [REL] [id] + [CEXPR]
end define
define IGUARD
% Define as condições no guarda.
[IEXPR] [REL] [IEXPR] | [IEXPR] != [IEXPR]
end define
define SINC
% Define os canais de comunicação (sincronização).
[empty]
| sync [id];
end define
define ASS
% Define a declaração de atribuições.
[empty]
| assign [AL,];
end define
define AL
% Define uma atribuição.
[id]:=[CEXPR] | [id]:=[IEXPR]
end define
define IEXPR
% Define expressões.
[id] | [CEXPR] | -[IEXPR] | '([IEXPR]') | [IEXPR] [OP] [IEXPR]
end define
define CEXPR
% Define expressões.
[number] | '([CEXPR]') | [id] | [CEXPR] [OP] [CEXPR]
end define
define REL
% Define operadores de comparação.
< | <= | >= | > | ==
86
end define
define OP
% Define operadores matemáticos.
+ | - | * | /
end define
% ================== FUNCTIONS =====================
function main
% Função principal responsável por iniciar o processo de transformação.
export LIST_CHANS[id,] _
export LIST_SYSTEM[id,] _
replace [program]
C[COMPOSITION]
construct PROCESSES[PROC*]
_[CREATE_PROCESS_USER C]
[CREATE_PROCESSES_EVENTS C]
[CREATE_PROCESSESS_LINKS_AND_DELAYS C]
[CREATE_PROCESS_BROADCAST C]
import LIST_CHANS
import LIST_SYSTEM
by
chan LIST_CHANS;
clock ck;
PROCESSES
system LIST_SYSTEM;
end function
% ============== PROCESS_BROADCAST ================
% Representa o processo BROADCAST em TA esponsável pela comunicação entre os outros processos.
% Como cada ação delay(N) tem seu próprio processo, a comunicação é feita
% diretamente pelo elo a qual pertence, não sendo incluído no processo broadcast.
function CREATE_PROCESS_BROADCAST C[COMPOSITION]
% Cria o processo BROADCAST.
export CONT[number] 1 % Contador para criar a identificação única dos estados.
export BROADCAST_STATES[SIL,] 'Ender, 'S0 % Representa o conjunto de estados do processo
BROADCAST.
export ENDER_TRANS[TL,] _ % Representa as transições Ender -> S0
replace [PROC*]
P[PROC*]
deconstruct C
comp I[id] N[NODE*] SEL_EV[SEL_EVENT*] L[LINK*] ender EV_ENDER[id*]
construct PRS_EV[PRS_EVENT*] _[^ C] % Conjunto dos eventos de apresentação.
export ALL_CONDITION[CONDITION*] _[^ L] % Conjunto de condições dos elos.
export ALL_ACTIONS[ACTION*] _[^ L] % Conjunto de ações dos elos.
export EV_SEQ[id*] % Conjunto de nomes de eventos em A1 no A1;A2.
_[GET_A1_IN_SEQ each ALL_ACTIONS]
construct BROADCAST_TRANS[TL,] % Representa as tansições do processo BROADCAST.
_[CONSTRUCT_TRANS_SEL_EV each SEL_EV][CONSTRUCT_TRANS_PRS_EV L EV_ENDER each PRS_EV]
import BROADCAST_STATES
construct SIZE_BC_STATES[number] _[length BROADCAST_STATES] % Quantidade de estados do processo
BROADCAST.
construct STATES_COMMIT[id*] % Representa o conjunto de estados que serão COMMITTED.
_[^ BROADCAST_STATES][select 3 SIZE_BC_STATES][. 'Ender]
construct BROADCAST_COMMIT_STATES[id,] % Representa a lista de estados COMMITTED.
_[CREATE_BROADCAST_COMMIT_STATES each STATES_COMMIT]
construct BD_NAME[id] 'Broadcast
construct PROCESS_BROADCAST[PROC]
process BD_NAME[ADD_LIST_SYSTEM] {
int cont;
state BROADCAST_STATES;
commit BROADCAST_COMMIT_STATES;
init 'S0;
trans BROADCAST_TRANS;
}
by
P[. PROCESS_BROADCAST]
end function
function GET_A1_IN_SEQ ACT[ACTION]
% Representa o conjunto de nomes de eventos em A1 no A1;A2.
deconstruct ACT
87
A1[ACTION];A2[ACTION]
replace [id*]
EV_NAMES[id*]
construct EV[id*] _[^ A1]
by
EV_NAMES[. EV]
end function
function CREATE_BROADCAST_COMMIT_STATES STATES_COMMIT[id]
% Cria a lista de estados COMMITTED.
replace [id,]
LIST_STATES_COMMIT[id,]
by
LIST_STATES_COMMIT[, STATES_COMMIT]
end function
% ========================= TRANS_SEL_EV ==================================
% Representa as transições para o processo BROADCAST dos eventos de seleção.
function CONSTRUCT_TRANS_SEL_EV SEL_EV[SEL_EVENT]
% Constrói a transição do processo BROADCAST com comunicação para cada evento de seleção
% e a respectiva transição Ender -> S0.
deconstruct SEL_EV
ev EV_NAME[id] A[ANCHOR] sel D[DESCRIPTION]
replace [TL,]
T[TL,]
import ENDER_TRANS[TL,]
construct TRANS[TL] % Constrói a transição Ender -> S0.
'Ender -> 'S0 { sync EV_NAME[+ 'Stop][ADD_LIST_CHANS][+ '!]; }
export ENDER_TRANS
ENDER_TRANS[, TRANS]
construct CHin[id] EV_NAME[INV_CONCAT 'Start][ADD_LIST_CHANS][+ '?]
construct CHout[id] EV_NAME[+ 'Start][ADD_LIST_CHANS][+ '!]
construct COND[CONDITION] EV_NAME.start
construct REPT[number] % Quantidade de processos que serão avisados que o evento iniciou.
_[CONSTRUCT_REPT COND][+ 1]
by
T[ADD_BROADCAST_TRANS CHin CHout REPT]
end function
% ======================= TRANS_PRS_EV ==================================
% Representa as transições para o processo BROADCAST dos eventos de apresentação.
function CONSTRUCT_TRANS_PRS_EV L[LINK*] EV_ENDER[id*] PRS_EV[PRS_EVENT]
% Constrói a transição do processo BROADCAST com comunicação para cada evento de apresentação.
deconstruct PRS_EV
ev EV_NAME[id] An[ANCHOR] prs D[DESCRIPTION]
replace [TL,]
T[TL,]
construct TRANS[TL,] % Representa as transições para inicialização e finalização do evento.
_[HAS_START EV_NAME L][HAS_STOP EV_NAME EV_ENDER]
by
T[, TRANS]
end function
%========================= HAS_START ==============================
% Representa as transições de inicialização do processo BROADCAST para os eventos de
apresentação.
function HAS_START EV_NAME[id] L[LINK*]
% Cria as transições de inicialização do evento de apresentação para o processo BROADCAST.
replace [TL,]
T[TL,]
deconstruct * [ACTION] L
start'(EV_NAME')
construct CHin[id] EV_NAME[INV_CONCAT 'Start][ADD_LIST_CHANS][+ '?]
construct CHout[id] EV_NAME[+ 'Start][ADD_LIST_CHANS][+ '!]
construct COND[CONDITION] EV_NAME.start
construct REPT[number] _[CONSTRUCT_REPT COND][+ 1] % Quantidade de processos que serão avisados
que o evento iniciou.
by
T[ADD_BROADCAST_TRANS CHin CHout REPT]
end function
88
%========================= HAS_STOP ==============================
% Representa as transições de finalização do processo BROADCAST para os eventos de apresentação.
function HAS_STOP EV_NAME[id] EV_ENDER[id*]
% Cria as transições de finalização do evento de apresentação para o processo BROADCAST.
construct N0[number] 0
construct InSEQ[number] % Verifica se evento está em A1 no A1;A2 (InSEQ = 1).
N0[TEST_IN_SEQ EV_NAME]
construct COND[CONDITION] EV_NAME.stop
construct REPT[number] % Quantidade de processos que serão avisados que o evento finalizou.
_[CONSTRUCT_REPT COND][+ InSEQ]
construct IsSTOPED[number] % Verifica se existe a ação stop() para o evento (IsSTOPED = 1).
N0[TEST_STOPED EV_NAME]
construct N1[number] 1
replace [TL,]
T[TL,]
where N1[= InSEQ][<= REPT][= IsSTOPED]
construct CHin[id] EV_NAME[+ 'Stop][ADD_LIST_CHANS][+ '?]
construct CHout[id] EV_NAME[INV_CONCAT 'Stop][ADD_LIST_CHANS][+ '!]
by
T[ADD_BROADCAST_TRANS CHin CHout REPT]
[ADD_ENDER_TRANS EV_NAME EV_ENDER] % Inclui a transição Ender, caso o evento o seja.
end function
function TEST_IN_SEQ EV_NAME[id]
% Verifica se evento está em A1 no A1;A2 (InSEQ = 1).
import EV_SEQ[id*] % Conjunto de nomes de eventos em A1 no A1;A2.
replace [number]
0
deconstruct * [id] EV_SEQ
EV_NAME
by
1
end function
function TEST_STOPED EV_NAME[id]
% Verifica se existe a ação stop() para o evento (IsSTOPED = 1).
import ALL_ACTIONS[ACTION*]
deconstruct * [ACTION] ALL_ACTIONS
stop'(EV_NAME')
replace [number]
0
by
1
end function
function ADD_ENDER_TRANS EV_NAME[id] EV_ENDER[id*]
% Inclui as transição Ender no processo BROADCAST para quando o evento de apresentação
correspondente
% finalizar, a apresentação da composição hipermídia também finalize.
deconstruct * [id] EV_ENDER
EV_NAME
replace [TL,]
TRANS[TL,]
construct SIZE[number] _[length TRANS]
construct LAST_TRANS[TL,] TRANS[tail SIZE] % Retira a última transição.
construct DEC_SIZE[number] SIZE[- 1]
construct OTHER_TRANS[TL,] TRANS[select 1 DEC_SIZE]
deconstruct LAST_TRANS
STATE1[id] -> STATE2[id] { GRD[G] SNC[SINC] ASG[ASS] }
construct LAST_TRANS_CHANGED[TL] % Altera a última transição.
STATE1 -> 'Ender { GRD SNC ASG }
import ENDER_TRANS[TL,] % Importa as transições Ender -> S0.
by
OTHER_TRANS[, LAST_TRANS_CHANGED][, ENDER_TRANS]
end function
% =============== FUNÇÕES DE USO GERAL DO BROADCAST ================
function CONSTRUCT_REPT COND[CONDITION]
% Representa a quantidade de processos que serão avisados sobre a satisfação de uma determinada
condição.
replace [number]
A[any]
89
import ALL_CONDITION[CONDITION*]
construct N0[number] 0
construct REPT[number] % Quantidade de processos.
N0[INC_NUMBER_CONDITION COND each ALL_CONDITION]
by
REPT
end function
function INC_NUMBER_CONDITION COND1[CONDITION] COND2[CONDITION]
% Incrementa a quantidade de processos que necessitam ser avisados que uma condição foi
satisfeita.
replace [number]
N[number]
where COND1[= COND2]
by
N[+ 1]
end function
function ADD_BROADCAST_TRANS CHin[id] CHout[id] REPT[number]
% Cria a transição do processo BROADCAST para cada evento.
replace [TL,]
T[TL,]
import CONT[number]
construct STATE[id] 'S
construct NEW_STATE[id] STATE[+ CONT]
export CONT CONT[+ 1]
construct ST[SIL] NEW_STATE
import BROADCAST_STATES[SIL,]
export BROADCAST_STATES
BROADCAST_STATES[, ST]
construct BC_TRANS[TL,]
'S0 -> NEW_STATE {sync CHin; assign cont := REPT; },
NEW_STATE -> NEW_STATE{guard cont > 1; sync CHout; assign cont := cont - 1; },
NEW_STATE -> 'S0{guard cont <= 1; sync CHout; }
by
T[, BC_TRANS]
end function
% ==================== PROCESSESS_LINKS_AND_DELAYS ===================
% Representa os processos dos elos (links) e dos atrasos (delays) em TA de uma composição
hipermídia.
function CREATE_PROCESSESS_LINKS_AND_DELAYS C[COMPOSITION]
% Cria os processos dos elos (links) e dos atrasos (delays).
export PROCESSES_DELAYS[PROC*] _ % Representa os processos dos atrasos.
replace [PROC*]
P[PROC*]
deconstruct C
comp I[id] N[NODE*] SEL_EV[SEL_EVENT*] L[LINK*] ender EV_ENDER[id*]
construct PROCESSES_LINKS[PROC*] % Representa os processos dos elos.
_[CONSTRUCT_PROCESSES_LINKS each L]
import PROCESSES_DELAYS
by
P[. PROCESSES_LINKS][. PROCESSES_DELAYS]
end function
function CONSTRUCT_PROCESSES_LINKS LNK[LINK]
% Constói o processo de um elo.
export CONT[number] 1 % Contador para criar a identificação única dos estados.
export CONT_SPECIAL[number] 0 % Contador para criar a identificação única dos estados do
seqüenciamento completo.
export LINK_COMMIT_STATES[id,] _ % Representa o conjunto dos estados committed.
export LINK_STATES[SIL,] 'S0, 'S1 % Representa o conjunto dos estados dos estados normais.
replace [PROC*]
P[PROC*]
deconstruct LNK
link LNK_NAME[id] COND[CONDITION] => ACT[ACTION]
construct LINK_TRANS[TL,] % Constrói as transições entre os estados do processo.
_[TRANS_AND COND][TRANS_OR COND][TRANS_OTHERS_COND COND] % Constrói as transições das CONDIÇÕES
do elo.
[ADD_LINK_COMMIT_STATES][ADD_STATE 'S] % Insere um estado committed separando as condições das
ações.
[TRANS_PRL ACT][TRANS_SEQ ACT][TRANS_OTHERS_ACT ACT 0][CLOSE_TRANS] % Constrói as transições
das AÇÕES do elo.
90
import LINK_STATES
import LINK_COMMIT_STATES
construct PROCESS_LINK[PROC] % Contrói o processo elo.
process LNK_NAME[ADD_LIST_SYSTEM] {
state LINK_STATES;
commit LINK_COMMIT_STATES;
init 'S0;
trans LINK_TRANS;
}
by
P[. PROCESS_LINK]
end function
% ======================== ACTIONS ============================
% Representa o conjunto de transições das ações dos elos,
% juntamente com os respectivos estados.
function TRANS_PRL A[ACTION]
% Cria a transição da ação de paralelismo.
deconstruct A
A1[ACTION] || A2[ACTION]
replace [TL,]
T[TL,]
construct OTHER_TRANS[TL,] % Representa as outras transições.
_[TRANS_PRL A1][TRANS_SEQ A1][TRANS_OTHERS_ACT A1 0]
[ADD_LINK_COMMIT_STATES][ADD_STATE 'S][TRANS_OTHERS_ACT A2 0]
by
T[, OTHER_TRANS]
end function
function TRANS_SEQ A[ACTION]
% Cria a transição da ação de seqüenciamento completo.
deconstruct A
A1[ACTION] ; A2[ACTION]
replace [TL,]
T[TL,]
construct OTHER_TRANS[TL,] % Representa as outras transições
_[TRANS_PRL_SEQ A1][TRANS_SEQ_SEQ A1][TRANS_OTHERS_ACT A1 1]
[ADD_STATE 'S][TRANS_OTHERS_ACT A2 0]
by
T[, OTHER_TRANS]
end function
function TRANS_PRL_SEQ A[ACTION]
% Verifica se o elemento A1 num seqüenciamento completo (A1;A2) é um paralelismo.
deconstruct A
A1[ACTION] || A2[ACTION]
replace [TL,]
T[TL,]
construct OTHER_TRANS[TL,] % Representa as outras transições
_[TRANS_PRL A1][TRANS_SEQ A1][TRANS_OTHERS_ACT A1 0]
[ADD_LINK_COMMIT_STATES][ADD_STATE 'S][TRANS_OTHERS_ACT A2 1]
by
T[, OTHER_TRANS]
end function
function TRANS_SEQ_SEQ A[ACTION]
% Verifica se o elemento A1 num seqüenciamento completo (A1;A2) é também um seqüenciamento
completo.
deconstruct A
A1[ACTION] ; A2[ACTION]
replace [TL,]
T[TL,]
construct OTHER_TRANS[TL,] % Representa as outras transições
_[TRANS_PRL_SEQ A1][TRANS_SEQ_SEQ A1][TRANS_OTHERS_ACT A1 1]
[ADD_STATE 'S][TRANS_OTHERS_ACT A2 1]
by
T[, OTHER_TRANS]
end function
function TRANS_OTHERS_ACT A[ACTION] IsSEQ[number]
% Trata as ações start() e stop(), criando as transições segundo o valor de IsSeQ
% (1 se for A1 em A1;A2 e 0, caso contrário).
replace [TL,]
91
T[TL,]
construct CHANS[id*] % Constrói um lista de canais de comunicação da transição.
_[CHAN_ST A IsSEQ][CHAN_D A IsSEQ][CHAN_SP A]
construct N[number] % N será 0 caso a ação seja stop(). Se N = 0 a transição será normal.
IsSEQ[IsSP A]
construct LAST_STATES[SIL,] _[GET_LAST_STATES 2] % Representa os dois últimos estados.
deconstruct LAST_STATES
STATE1[id], STATE2[id], SX[SIL,]
construct TRANS[TL,] % Constrói a transição da ação start() ou stop().
_[TRANS_IF_NORMAL CHANS STATE1 STATE2 N][TRANS_IF_SEQ CHANS STATE1 STATE2 N]
by
T[, TRANS]
end function
function IsSP A[ACTION]
% Inverte o IsSEQ de 1 para 0, caso a ação seja de parada.
deconstruct A stop'(EV_NAME[id]')
replace [number]
1
by
0
end function
function TRANS_IF_NORMAL CHANS[id*] STATE1[id] STATE2[id] IsSEQ[number]
% Constrói a transição caso a ação NÃO seja A1 em A1;A2 (IsSEQ = 0).
deconstruct IsSEQ 0
replace [TL,]
T[TL,]
deconstruct CHANS % Representa o canal de comunicação.
CHAN[id] OTHER_CHANS[id*]
construct TRANS[TL]
STATE1 -> STATE2 { sync CHAN; }
by
T[, TRANS]
end function
function TRANS_IF_SEQ CHANS[id*] STATE1[id] STATE2[id] IsSEQ[number]
% Constrói a transição caso a ação seja A1 em A1;A2 (IsSEQ = 1).
deconstruct IsSEQ 1
replace [TL,]
T[TL,]
deconstruct CHANS % Representa os canais de comunicação.
CHAN1[id] CHAN2[id] OTHER_CHANS[id*]
import CONT_SPECIAL[number]
export CONT_SPECIAL CONT_SPECIAL[+ 1]
construct NEW_STATE[id] _[parse 'ST][+ CONT_SPECIAL] % Cria um novo estado para ser incluído
import LINK_STATES[SIL,] % em caso de ser A1 <> stop() em A1;A2.
construct LAST_STATE[SIL,] _[GET_LAST_STATES 1]
construct SIZE[number] _[length LINK_STATES][- 1]
construct NEW_ST[SIL] NEW_STATE
export LINK_STATES
LINK_STATES[select 1 SIZE][, NEW_ST][, LAST_STATE] % Inserir o estado especial na lista de
estados.
construct TRANS[TL,]
STATE1 -> NEW_STATE { sync CHAN1; },
NEW_STATE -> STATE2 { sync CHAN2; }
by
T[, TRANS]
end function
function CHAN_ST A[ACTION] IsSEQ[number]
% Cria os canais de comunicação para a ação start().
deconstruct A start'(EV_NAME[id]')
replace [id*]
An[any]
construct CHANS[id*]
EV_NAME[INV_CONCAT 'Start][+ '!]
EV_NAME[INV_CONCAT 'Stop][+ '?]
by
CHANS[IS_IT_SEQ IsSEQ] % Modifica os canais criados caso a ação A1 não esteja em A1;A2 (IsSEQ =
0)
end function
function IS_IT_SEQ IsSEQ[number]
92
% Verifica se IsSEQ = 0, considerando apenas o primeiro elemento de uma lista de canais de
comunicação.
replace [id*]
CHAN1[id] CHANS[id*]
where IsSEQ[= 0]
by
CHAN1
end function
function CHAN_SP A[ACTION]
% Cria o canal de comunicação para a ação stop().
deconstruct A stop'(EV_NAME[id]')
replace [id*]
An[any]
by
EV_NAME[+ 'Stop!]
end function
function CHAN_D A[ACTION] IsSEQ[number]
% Cria os canais de comunicação para a ação delay().
% Também solicita a criação do processo delay.
deconstruct A delay'(N[number]')
replace [id*]
An[any]
construct D[id] 'Delay
construct D_NAME[id]
D[+ N][+ '_][!]
import PROCESSES_DELAYS[PROC*]
construct PROCESS_DELAY[PROC*] % Representa o processo delay().
_[CREATE_PROCESS_DELAY N D_NAME IsSEQ]
export PROCESSES_DELAYS
PROCESSES_DELAYS[. PROCESS_DELAY]
construct CHANS[id*]
D_NAME[+ 'St!]
D_NAME[+ 'Sp?]
by
CHANS[IS_IT_SEQ IsSEQ] % Modifica os canais criados caso a ação A1 não esteja em A1;A2 (IsSEQ =
0)
end function
% ======================== CONDITIONS ==========================
% Representa o conjunto de transições das condições dos elos,
% juntamente com os respectivos estados.
function TRANS_AND C[CONDITION]
% Cria a transição da condição AND.
deconstruct C
C1[CONDITION] and C2[CONDITION]
replace [TL,]
T[TL,]
construct OTHER_TRANS[TL,] % Representa as outras transições.
_[TRANS_AND C1][TRANS_OR C1]
[TRANS_OTHERS_COND C1]
[ADD_LINK_COMMIT_STATES][ADD_STATE 'S] % Insere um estado committed entre C1 and C2.
[TRANS_OTHERS_COND C2]
by
T[, OTHER_TRANS]
end function
function TRANS_OR C[CONDITION]
% Cria a transição da condição OR.
deconstruct C
C1[CONDITION] or C2[CONDITION]
replace [TL,]
T[TL,]
construct OTHER_TRANS[TL,] % Representa as outras transições.
_[TRANS_AND C1][TRANS_OR C1]
[TRANS_OTHERS_COND C1][TRANS_OTHERS_COND C2]
by
T[, OTHER_TRANS]
end function
function TRANS_OTHERS_COND C[CONDITION]
93
% Cria a transição das condição .start e .stop.
replace [TL,]
T[TL,]
where C[? TEST_ST][? TEST_SP] % Verifica se a condição é start ou stop.
construct LAST_STATES[SIL,] _[GET_LAST_STATES 2]
deconstruct LAST_STATES
STATE1[id], STATE2[id], SX[SIL,]
import TRANS_CHAN[id] % Representa o canal de comunicação.
construct TRANS[TL] % Constrói a transição propriamente dita.
STATE1 -> STATE2 { sync TRANS_CHAN; }
by
T[, TRANS]
end function
function TEST_ST
% Verifica se a condição é start e exporta o canal de comunicação próprio.
match [CONDITION]
EV_NAME[id].start
export TRANS_CHAN[id]
EV_NAME[+ 'Start][+ '?]
end function
function TEST_SP
% Verifica se a condição é stop e exporta o canal de comunicação próprio.
match [CONDITION]
EV_NAME[id].stop
export TRANS_CHAN[id]
EV_NAME[INV_CONCAT 'Stop][+ '?]
end function
% ================== FUNÇÕES DE USO GERAL DOS ELOS =====================
function ADD_STATE I[id]
% Insere um novo estado na lista de estados do processo de um elo.
import CONT[number]
import LINK_STATES[SIL,]
construct NOVO_ID[number] CONT[+ 1]
export CONT NOVO_ID
construct STATE[SIL] I[+ NOVO_ID]
export LINK_STATES LINK_STATES[, STATE]
match [TL,]
T[TL,]
end function
function GET_LAST_STATES N[number]
% Retorna os N's últimos estados da lista de estados de um elo.
import LINK_STATES[SIL,]
replace [SIL,]
A[any]
construct N1[number] N[- 1]
construct SIZE[number] _[length LINK_STATES][- N1]
by
LINK_STATES[tail SIZE]
end function
function CLOSE_TRANS
% Retira a última transição do processo de cada elo que está em excesso, adequando o penúltima
% transição para fechar o processo.
replace [TL,]
T[TL,]
construct SIZE[number] _[length T]
construct POS_PENULTIMATE[number] SIZE[- 1]
construct LAST_TRANS[TL,]
T[tail SIZE]
deconstruct LAST_TRANS
STATE1[id] -> STATE2[id] { GD[G] SNC[SINC] AS[ASS]}
construct NEW_TRANS[TL]
STATE1 -> 'S0 { GD SNC AS }
import LINK_STATES[SIL,]
construct LINK_STATES_SIZE[number] _[length LINK_STATES][- 1]
export LINK_STATES LINK_STATES[select 1 LINK_STATES_SIZE]
by
T[select 1 POS_PENULTIMATE][, NEW_TRANS]
end function
94
function ADD_LINK_COMMIT_STATES
% Adiciona um novo estado a lista de estados committed dos elos.
match [TL,]
A[any]
import LINK_STATES[SIL,]
construct LINK_STATES_SIZE[number] _[length LINK_STATES]
construct STATE_WILL_BE_COMMIT[SIL,] LINK_STATES[tail LINK_STATES_SIZE]
deconstruct STATE_WILL_BE_COMMIT
COMMIT_STATE[id], OTHER_STATES[SIL,]
import LINK_COMMIT_STATES[id,]
export LINK_COMMIT_STATES
LINK_COMMIT_STATES[, COMMIT_STATE]
end function
% ======================== PROCESS_USER ==========================
% Representa o processo do usuário equivalente a interação do mesmo em uma composição hipermídia.
function CREATE_PROCESS_USER C[COMPOSITION]
% Cria o processo User de uma composição.
replace [PROC*]
P[PROC*]
deconstruct C
comp COMP_NAME[id] N[NODE*] SEL_EV[SEL_EVENT*] L[LINK*] ender EV_ENDER[id*]
construct CHAN_COMP[id] COMP_NAME[INV_CONCAT 'end][ADD_LIST_CHANS]
export USER_STATES[SIL,] 'Start % Representa a lista de estados do processo User.
construct USER_TRANS[TL,] % Constrói as transições do processo User.
_[CONSTRUCT_USER_TRANS CHAN_COMP each SEL_EV]
import USER_STATES
construct PROCESS_USER[PROC*]
process COMP_NAME[INV_CONCAT 'User_][ADD_LIST_SYSTEM] {
state USER_STATES;
init 'Start;
trans USER_TRANS;
}
by
P[. PROCESS_USER]
end function
function CONSTRUCT_USER_TRANS CHAN_COMP[id] SEL_EV[SEL_EVENT]
% Constrói as transição do processo User.
replace [TL,]
T[TL,]
deconstruct SEL_EV
ev EV_NAME[id] AN[ANCHOR] sel desc null
construct USER_TRANS[TL,]
Start -> EV_NAME[INV_CONCAT 'State][ADD_USER_STATE]
{ sync EV_NAME[INV_CONCAT 'Start][+ '!]; assign ck := 0; },
EV_NAME[INV_CONCAT 'State] -> Start { sync CHAN_COMP[+ '?]; }
by
T[, USER_TRANS]
end function
function ADD_USER_STATE
% Adiciona um novo estado nas lista de estados do processo User.
import USER_STATES[SIL,]
match [id]
I[id]
construct S[SIL] I
export USER_STATES
USER_STATES[, S]
end function
% ======================== PROCESS_DELAY ==========================
% Representa o processo de um atraso (delay) de uma composição hipermídia.
function CREATE_PROCESS_DELAY DELAY_TIME[number] D_NAME[id] IsSEQ[number]
% Constrói o processo delay.
replace [PROC*]
P[PROC*]
construct SNC[SINC] % Representa um canal de comunicação caso IsSEQ = 1
_[SNC_IS_NULL D_NAME IsSEQ]
by
process D_NAME[ADD_LIST_SYSTEM] {
95
clock ck_d;
state S1, S2 { ck_d <= DELAY_TIME };
init 'S1;
trans S1 -> S2 { sync D_NAME[+ 'St][ADD_LIST_CHANS][+ '?]; assign ck_d := 0; },
S2 -> S1 { guard ck_d == DELAY_TIME; SNC };
}
end function
function SNC_IS_NULL D_NAME[id] IsSEQ[number]
% Cria um canal de comunicação caso o delay seja A1 em A1;A2 (IsSEQ = 1)
replace [SINC]
S[SINC]
where IsSEQ[= 1]
by
sync D_NAME[+ 'Sp][ADD_LIST_CHANS][+ '!];
end function
% ======================== PROCESSES_EVENTS ==========================
% Representa os processos de todos os eventos de uma composição hipermídia.
function CREATE_PROCESSES_EVENTS C[COMPOSITION]
% Cria os processos em TA de todos os eventos.
replace [PROC*]
P[PROC*]
deconstruct C
comp I[id] N[NODE*] SEL_EV[SEL_EVENT*] L[LINK*] ender EV_ENDER[id*]
export ALL_CONDITIONS[CONDITION*] _[^ L] % Conjunto de todas as condições dos elos,
% para identificar a finalização de um evento de
apresentação.
export ALL_ACTIONS[ACTION*] _[^ L] % Conjunto de todas as ações dos elos para identificar quando
um
% evento de apresentação deve ser finalizado.
construct PRS_EV[PRS_EVENT*] _[^ C] % Conjunto dos eventos de apresentação.
construct PROCESSES_EVENTS[PROC*] % Representa todos os processos dos eventos.
_[CONSTRUCT_PROCESSES_SEL_EVENTS I each SEL_EV] % Processos dos eventos de seleção.
[CONSTRUCT_PROCESSES_PRS_EVENTS each PRS_EV] % Processos dos eventos de apresentação.
by
P[. PROCESSES_EVENTS]
end function
% ======================== PROCESSES_SEL_EVENTS ==========================
% Representa os processos em TA dos eventos de seleção.
function CONSTRUCT_PROCESSES_SEL_EVENTS COMP_NAME[id] SEL_EV[SEL_EVENT]
% Constrói os processos dos eventos de seleção.
replace [PROC*]
P[PROC*]
deconstruct SEL_EV
ev EV_NAME[id] AN[ANCHOR] sel desc null
construct SELECT_EVENT_PROCESS[PROC]
process EV_NAME[ADD_LIST_SYSTEM] {
state 'p, 'o, 's;
commit 's;
init 'p;
trans 'p -> 'o{sync EV_NAME[+ 'Start?]; },
'o -> 's{sync EV_NAME[+ 'Stop?]; },
's -> 'p{sync COMP_NAME[INV_CONCAT 'end][+ '!]; };
}
by
P[. SELECT_EVENT_PROCESS]
end function
% ======================== PROCESSES_PRS_EVENTS ==========================
% Representa os processos em TA dos eventos de apresentação.
function CONSTRUCT_PROCESSES_PRS_EVENTS PRS_EV[PRS_EVENT]
% Constrói os processos dos eventos de apresentação.
replace [PROC*]
P[PROC*]
deconstruct PRS_EV
ev EV_NAME[id] AN[ANCHOR] prs desc M[MEDIA] T_MIN[number] T_MAX[number]
export EV_NAME
construct TRANSITIONS[TL,]
p -> o { sync EV_NAME[+ 'Start?]; assign ck_e := 0; },
96
o -> p { sync EV_NAME[INV_CONCAT 'Stop][+ '?]; }
construct INVARIANT[INV]
_[INV_IS_NULL T_MAX] % Somente existirá esta invariante se T_MAX não for infinito (zero).
construct EV_PROCESS[PROC]
process EV_NAME[ADD_LIST_SYSTEM] {
clock ck_e;
state p, o INVARIANT;
init p;
trans TRANSITIONS[DELETE_TRANS_WITH_SYNC_ONLY EV_NAME T_MIN] % Uma transição será retirada,
caso não exista stop()
[ADD_TRANS_GUARD T_MIN]; % Uma transição será adicionada, caso T_MIN não for
infinito.
}
by
P[. EV_PROCESS]
end function
function INV_IS_NULL T_MAX[number]
% Verifica se o tempo máximo da apresentação é infinito (zero).
% Em caso afirmativo, não existirá a invariante no processo.
replace [INV]
A[any]
where T_MAX[~= 0]
by
{ck_e <= T_MAX}
end function
function DELETE_TRANS_WITH_SYNC_ONLY EV_NAME[id] T_MIN[number]
% Verifica se é sinalizado a finalização do evento.
% Em caso negativo, a transição com o guarda StopE? é retirada.
replace [TL,]
T[TL,]
where T_MIN[~= 0]
construct N0[number] 0
construct SP[number] N0[TEST_STOPED EV_NAME]
deconstruct T
TRANS1[TL], TRANS2[TL], OTHER_TRANS[TL,]
where SP[= 0]
by
TRANS1
end function
function ADD_TRANS_GUARD T_MIN[number]
% Inclui a transição com o guarda no processo do evento
% de apresentação, caso o tempo mínimo não for infinito (zero).
replace [TL,]
T[TL,]
where T_MIN[~= 0]
construct SINC_CHAN[SINC]
_[SINC_IS_NULL] % Adiciona um canal de sincronismo, caso uma condição de parada necessite ser
satisfeita.
construct NewTrans[TL]
o -> p{ guard ck_e >= T_MIN; SINC_CHAN }
by
T[, NewTrans]
end function
function SINC_IS_NULL
% Verifica se existe uma condição de parada nos elos para um dado evento de apresentação.
% Em caso afirmativo, constrói um canal de sincronização no processo do evento.
import ALL_CONDITIONS[CONDITION*]
import EV_NAME[id]
construct CND[CONDITION] EV_NAME.stop
replace [SINC]
A[any]
where ALL_CONDITIONS[COND_REFERENCE CND]
by
sync EV_NAME[+ 'Stop!];
end function
function COND_REFERENCE CND[CONDITION]
% Esta função de condição verifica se há referência para a condição dada.
match * [CONDITION]
CND
97
end function
% ============================ FUNÇÕES DE USO GERAL =======================
function ADD_LIST_SYSTEM
% Adiciona um novo processo ao sistema.
import LIST_SYSTEM[id,]
match [id]
I[id]
export LIST_SYSTEM
LIST_SYSTEM[, I]
end function
function ADD_LIST_CHANS
% Adiciona um novo canal na lista de canais de comunicação.
import LIST_CHANS[id,]
match [id]
I[id]
export LIST_CHANS
LIST_CHANS[, I]
end function
function INV_CONCAT ID2[id]
% Concatena dois identificadores de forma invertida.
replace [id]
ID1[id]
by
ID2[+ ID1]
end function
B.2 - Exemplo
O exemplo a seguir é o mesmo do referenciado em todo este trabalho, cujo modelo pode ser
encontrado no capítulo 2 – seção 4.
I – Código em NCL
comp C
term AT ev E2 y prs desc audio 10 10
ev E7 y prs desc text 6 6
term V ev E3 y prs desc video 8 9
ev E5 y prs desc video 8 9
term A ev E6 y prs desc audio 7 7
term I ev E8 y prs desc image 0 0
ev E1 &1 sel desc null
ev E4 &2 sel desc null
link L1 E1.start => start(E2) || start(E3)
link L2 E4.start => start(E5) || start(E6)
link L3 E6.start => delay(4) ; start(E7)
link L4 E3.stop or E5.stop => start(E8)
link L5 E2.stop or E7.stop => stop(E8)
ender E8
II - Resultado da Transformação em TA
chan endC, Delay4_1Sp, Delay4_1St, E1Stop, StartE1, E1Start, E4Stop, StartE4, E4Start, StartE2,
E2Start, E2Stop, StopE2, StartE7, E7Start, E7Stop, StopE7, StartE3, E3Start, E3Stop, StopE3,
StartE5, E5Start, E5Stop, StopE5, StartE6, E6Start, StartE8, E8Start, E8Stop, StopE8;
98
clock ck;
process User_C {
state Start, StateE1, StateE4;
init Start;
trans
Start -> StateE1 {sync StartE1!; assign ck := 0;},
StateE1 -> Start {sync endC?;},
Start -> StateE4 {sync StartE4!; assign ck := 0;},
StateE4 -> Start {sync endC?;};
}
process E1 {
state p, o, s;
commit s;
init p;
trans
p -> o {sync E1Start?;},
o -> s {sync E1Stop?;},
s -> p {sync endC!;};
}
process E4 {
state p, o, s;
commit s;
init p;
trans
p -> o {sync E4Start?;},
o -> s {sync E4Stop?;},
s -> p {sync endC!;};
}
process E2 {
clock ck_e;
state p, o {ck_e <= 10};
init p;
trans
p -> o {sync E2Start?; assign ck_e := 0;},
o -> p {guard ck_e >= 10; sync E2Stop!;};
}
process E7 {
clock ck_e;
state p, o {ck_e <= 6};
init p;
trans
p -> o {sync E7Start?; assign ck_e := 0;},
o -> p {guard ck_e >= 6; sync E7Stop!;};
}
process E3 {
clock ck_e;
state p, o {ck_e <= 9};
init p;
trans
p -> o {sync E3Start?; assign ck_e := 0;},
o -> p {guard ck_e >= 8; sync E3Stop!;};
}
process E5 {
clock ck_e;
state p, o {ck_e <= 9};
init p;
trans
p -> o {sync E5Start?; assign ck_e := 0;},
o -> p {guard ck_e >= 8; sync E5Stop!;};
}
process E6 {
clock ck_e;
state p, o {ck_e <= 7};
init p;
trans
p -> o {sync E6Start?; assign ck_e := 0;},
o -> p {guard ck_e >= 7;};
}
process E8 {
clock ck_e;
state p, o;
init p;
99
trans
p -> o {sync E8Start?; assign ck_e := 0;},
o -> p {sync StopE8?;};
}
process L1 {
state S0, S1, S2;
commit S1, S2;
init S0;
trans
S0 -> S1 {sync E1Start?;},
S1 -> S2 {sync StartE2!;},
S2 -> S0 {sync StartE3!;};
}
process L2 {
state S0, S1, S2;
commit S1, S2;
init S0;
trans
S0 -> S1 {sync E4Start?;},
S1 -> S2 {sync StartE5!;},
S2 -> S0 {sync StartE6!;};
}
process L3 {
state S0, S1, ST1, S2;
commit S1;
init S0;
trans
S0 -> S1 {sync E6Start?;},
S1 -> ST1 {sync Delay4_1St!;},
ST1 -> S2 {sync Delay4_1Sp?;},
S2 -> S0 {sync StartE7!;};
}
process L4 {
state S0, S1;
commit S1;
init S0;
trans
S0 -> S1 {sync StopE3?;},
S0 -> S1 {sync StopE5?;},
S1 -> S0 {sync StartE8!;};
}
process L5 {
state S0, S1;
commit S1;
init S0;
trans
S0 -> S1 {sync StopE2?;},
S0 -> S1 {sync StopE7?;},
S1 -> S0 {sync E8Stop!;};
}
process Delay4_1 {
clock ck_d;
state S1, S2 {ck_d <= 4};
init S1;
trans
S1 -> S2 {sync Delay4_1St?; assign ck_d := 0;},
S2 -> S1 {guard ck_d == 4; sync Delay4_1Sp!;};
}
process Broadcast {
int cont;
state Ender, S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13;
commit S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, Ender;
init S0;
trans
S0 -> S1 {sync StartE1?; assign cont := 2;},
S1 -> S1 {guard cont > 1; sync E1Start!; assign cont := cont - 1;},
S1 -> S0 {guard cont <= 1; sync E1Start!;},
S0 -> S2 {sync StartE4?; assign cont := 2;},
S2 -> S2 {guard cont > 1; sync E4Start!; assign cont := cont - 1;},
S2 -> S0 {guard cont <= 1; sync E4Start!;},
S0 -> S3 {sync StartE2?; assign cont := 1;},
S3 -> S3 {guard cont > 1; sync E2Start!; assign cont := cont - 1;},
S3 -> S0 {guard cont <= 1; sync E2Start!;},
S0 -> S4 {sync E2Stop?; assign cont := 1;},
100
S4 -> S4 {guard cont > 1; sync StopE2!; assign cont := cont - 1;},
S4 -> S0 {guard cont <= 1; sync StopE2!;},
S0 -> S5 {sync StartE7?; assign cont := 1;},
S5 -> S5 {guard cont > 1; sync E7Start!; assign cont := cont - 1;},
S5 -> S0 {guard cont <= 1; sync E7Start!;},
S0 -> S6 {sync E7Stop?; assign cont := 1;},
S6 -> S6 {guard cont > 1; sync StopE7!; assign cont := cont - 1;},
S6 -> S0 {guard cont <= 1; sync StopE7!;},
S0 -> S7 {sync StartE3?; assign cont := 1;},
S7 -> S7 {guard cont > 1; sync E3Start!; assign cont := cont - 1;},
S7 -> S0 {guard cont <= 1; sync E3Start!;},
S0 -> S8 {sync E3Stop?; assign cont := 1;},
S8 -> S8 {guard cont > 1; sync StopE3!; assign cont := cont - 1;},
S8 -> S0 {guard cont <= 1; sync StopE3!;},
S0 -> S9 {sync StartE5?; assign cont := 1;},
S9 -> S9 {guard cont > 1; sync E5Start!; assign cont := cont - 1;},
S9 -> S0 {guard cont <= 1; sync E5Start!;},
S0 -> S10 {sync E5Stop?; assign cont := 1;},
S10 -> S10 {guard cont > 1; sync StopE5!; assign cont := cont - 1;},
S10 -> S0 {guard cont <= 1; sync StopE5!;},
S0 -> S11 {sync StartE6?; assign cont := 2;},
S11 -> S11 {guard cont > 1; sync E6Start!; assign cont := cont - 1;},
S11 -> S0 {guard cont <= 1; sync E6Start!;},
S0 -> S12 {sync StartE8?; assign cont := 1;},
S12 -> S12 {guard cont > 1; sync E8Start!; assign cont := cont - 1;},
S12 -> S0 {guard cont <= 1; sync E8Start!;},
S0 -> S13 {sync E8Stop?; assign cont := 0;},
S13 -> S13 {guard cont > 1; sync StopE8!; assign cont := cont - 1;},
S13 -> Ender {guard cont <= 1; sync StopE8!;},
Ender -> S0 {sync E1Stop!;},
Ender -> S0 {sync E4Stop!;};
}
system User_C, E1, E4, E2, E7, E3, E5, E6, E8, L1, L2, Delay4_1, L3, L4, L5, Broadcast;
101
Anexo C – Introdução a Arquitetura de Software
C.1 – Introdução
Até quase metade da década de 1950, o principal esforço no que diz respeito a sistemas
computacionais era de desenvolver um hardware que reduzisse o custo de processamento e
armazenamento de dados, enquanto a produção de software era bastante limitada. O software era
composto de poucos métodos sistemáticos e projetado sob medida para ser utilizado dentro das
próprias organizações. Geralmente, a manutenção do software era feita pelos próprios
profissionais que o desenvolveram e, desta forma, não havia preocupação em gerar uma
documentação clara sobre o produto desenvolvido.
A otimização de tarefas fornecida pelos sistemas computacionais tornava sua utilização
cada vez mais atraente e, pouco a pouco, o software foi ganhando espaço em termos de inovação
tecnológica sendo utilizado nas mais diversas áreas constituindo desde aplicações mais simples
como um sistema comercial, até aplicações mais complexas como um sistema de controle de
tráfego aéreo. Assim, milhares de instruções de programas eram produzidas dentro das empresas
e o software ganhou tamanho, complexidade e crescente necessidade de manutenção. Esta
atividade requeria esforço e recursos em índices alarmantes devido ao desenvolvimento
personalizado dos softwares e à falta de documentação. Vale ressaltar que nos dias atuais a
manutenção de software ainda é uma atividade que gera altos custos.
Estes fatores contribuíram para o surgimento da Engenharia de Software, termo cunhado
numa conferência seminal da NATO em Garmisch, Alemanha (1968), cuja idéia central é de
utilizar os princípios da engenharia no desenvolvimento de softwares de qualidade, a baixo
custo, e funcionamento eficiente em equipamentos em que sejam instalados.
A Engenharia de Software forneceu rigorosas práticas e métodos formais que permitiram a
criação de soluções economicamente efetivas para problemas práticos no desenvolvimento de
software. Apesar disto, o software continuou crescendo em tamanho e complexidade requerendo
mais confiabilidade, economia e desempenho que as técnicas de abstração utilizadas até o final
da década de 1980, as quais não são mais suficientes para atender a estes requisitos referentes ao
nível de organização do sistema, ou mais propriamente, ao nível de arquitetura de software.
102
C.2 – A Arquitetura de Software
Com o aumento do tamanho e complexidade dos sistemas de software, o projeto e a
especificação da estrutura global do sistema tornaram-se um problema mais significante do que a
escolha de algoritmos e estruturas de dados da computação [SHAW, 1994]. Projetar e especificar
a estrutura global de um sistema emerge como um novo tipo de problema, ou seja,
desenvolvimento de software voltado para arquitetura. Questões estruturais quanto ao
desenvolvimento de software no nível arquitetural incluem:
organização e estrutura geral de controle;
protocolos de comunicação, sincronização e acesso a dados;
atribuição de funcionalidade a elementos de projeto;
composição de elementos de projeto;
escalabilidade e desempenho;
seleção de alternativas de projeto.
É cada vez mais evidente que a engenharia de software requer projeto arquitetural de
software. Primeiro, é importante ser capaz de reconhecer estruturas comuns de modo que as
relações de alto-nível entre sistemas possam ser compreendidas e que novos sistemas possam ser
construídos a partir de sistemas antigos. Segundo, obter a arquitetura correta geralmente é crucial
para o sucesso de um projeto de sistema de software. Terceiro, o conhecimento detalhado de
arquiteturas de software permite aos engenheiros tomarem decisões sobre alternativas de projeto.
Quarto, uma representação arquitetural é essencial para a análise e descrição de propriedades de
um sistema complexo. Quinto, o conhecimento de notações formais para descrever arquiteturas
possibilita que os engenheiros apresentem novos projetos de sistemas a outros membros de uma
equipe de desenvolvimento.
Examinando o papel da arquitetura quanto ao desenvolvimento de sistemas de software,
alguns benefícios podem ser apontados. Segundo MENDES [2002], a arquitetura pode:
atuar como uma estrutura a fim de atender aos requisitos do sistema;
103
ser utilizada como aspecto técnico para o projeto de sistema bem como suporte na
estimação de custos e na gerência de processo;
servir de base para a análise da consistência e da dependência;
prover suporte ao reuso.
Foi no decorrer da década de 1990, que houve uma crescente preocupação em
compreender a organização dos sistemas de software, culminando com o surgimento da
arquitetura de software e que, portanto, é uma área relativamente nova dentro da Engenharia de
Software e constitui-se de um fator importante no projeto de sistemas de grande porte. MENDES
[2002] definiu que:
“Arquitetura de Software é o estudo da organização global dos sistemas de software bem
como do relacionamento entre subsistemas e componentes”.
Diagrama de caixas e linhas
Freqüentemente a arquitetura de software de um sistema aparece descrita na forma de um
diagrama de “caixas” e “linhas”, conforme apresentado na figura 7.2. Este nível de abstração
elimina detalhes de implementação e aumenta a independência dos componentes (subsistemas),
permitindo que muitos problemas sejam localizados fazendo com que os engenheiros
argumentem sobre seus sistemas, principalmente sobre atributos de qualidade como
confiabilidade e manutenibilidade. A confiabilidade implica em dizer se a aplicação realiza suas
funções conforme esperado, sendo portando um atributo essencial a um sistema de software
independente de seu uso. A manutenibilidade está associada à necessidade de reparo do sistema
de software no caso de existirem defeitos; e a necessidade de evolução dos sistemas a fim
satisfazer novos requisitos de usuários. De modo formal, a arquitetura é composta por:
Cliente
Servidor RPC
104
Componentes – representam um elemento computacional e de armazenamento de dados
de um sistema. Exemplos típicos incluem clientes, servidores, objetos e banco de dados.
Um componente tem duas importantes partes, as interfaces e a computação. As interfaces
fazem a interação entre o componente e o ambiente, como por exemplo, uma coleção de
chamada de procedimento que devem ser invocadas numa certa ordem. A computação
descreve o que o componente faz para transformar dados de entrada em dados de saída.
Conectores – de forma geral, representam interações entre componentes (pode haver
ligação entre conectores). Informalmente, eles fornecem uma “cola” para projetos
arquiteturais que descreve como os participantes trabalham juntos para criar a interação.
Os conectores também possuem interfaces as quais definem os participantes da interação.
Exemplos de conectores incluem formas de interação, tais como uma chamada de
procedimento (RPC), protocolos cliente-servidor ou um link SQL entre o banco de dados
e uma aplicação.
Configurações – é uma coleção de componentes interligados via conectores
representando a topologia da arquitetura.
C.3 – Linguagens de Descrição Arquitetural
Como abordado anteriormente, as configurações arquiteturais são geralmente descritas por
diagramas de caixas e linhas, os quais fornecem pouca informação sobre a computação
representada pelas caixas (componentes), suas interfaces e natureza das interações entre elas
(representadas pelas linhas – conectores).
Esta falta de informação limita severamente a utilidade destes diagramas. Sem informação
específica sobre as interfaces dos componentes e sem informação necessária para determinar o
significado de uma composição de diferentes elementos, os desenvolvedores têm que adivinhar
as intenções do arquiteto.
105
Assim, a prática de projeto arquitetural tem sido largamente ad hoc e informal, tornando
difícil o seu entendimento pelos desenvolvedores. O projeto é mais baseado em padrões do que
em sólidos princípios de engenharia. Em resposta a isto, pesquisadores industriais e acadêmicos
têm proposto notações formais para representar e analisar projetos arquiteturais. A estas notações
formais denominamos Linguagens de Descrição de Arquitetura (ADLs).
Linguagens de descrição de arquitetura são linguagens formais que fornecem uma estrutura
conceitual e uma sintaxe concreta para caracterizar arquiteturas de software.
Embora essas linguagens estejam concentradas no projeto arquitetural, cada uma das várias
existentes foca aspectos distintos.