• Nenhum resultado encontrado

5.3 Fase de An´alise

5.3.2 An´alise Semˆantica

A an´alise semˆantica tem como objetivo a verificac¸˜ao de tipos. ´E nesta fase que s˜ao de- tetados, por exemplo, os conflitos entre tipos, a ausˆencia de declarac¸˜oes de registos e etiquetas. A implementac¸˜ao da an´alise semˆantica ´e apoiada no sistema de tipos apresen- tado na secc¸˜ao 3.3 e consiste em efetuar v´arias passagens sobre a ´arvore, visitando os n´os relevantes da AST. Cada passagem na AST ´e feita com um visitante espec´ıfico obtido a

<<interface>> Type

isSubtype(type : Type) : boolean clone() : Type

replaceTypeVariable(tv : TypeVariable , type : Type)

unify(type : Type) : Type CodeType .... .... IntType .... .... TypeVariable .... .... LockType .... .... TupleType .... .... UninitializedType .... .... ExistsType .... .... StringType .... .... UniversalType .... ....

Figura 5.2: Diagrama de classes

partir da extens˜ao dos visitantes gerados pelo SableCC (pacoteanalysis).

Diagrama de Classes

A figura 5.2 mostra a hierarquia de classes que representa os tipos da linguagem e apoia a an´alise semˆantica.

O m´etodo isSubtype verifica se o tipo que chama o m´etodo ´e subtipo do tipo que ´e passado como parˆametro (type). Por exemplo, quando se atribui um valor (v) a uma posic¸˜ao (n) de um tuplo, o tipo do valor v tem ser subtipo do tipo da posic¸˜ao (n) do tu- plo. Esta verificac¸˜ao ´e feita com o m´etodoisSubtype(para mais detalhe ver as regras de subtipos do apˆendice B). O m´etodo clone cria uma r´eplica do tipo atual. Este m´etodo ´e necess´ario, para duplicar os tipos polim´orficos a fim de serem instanciados. Tome- mos o seguinte exemplo: o tipo do bloco levantarGarfoDireito, do exemplo da figura 4.1, ´e ∀ e1::Lock({},{}).∀ d1::Lock({e1},{}).{r1:lock e1,r2:lock d1} requires {e1}. Ao efetuar a aplicac¸˜ao de valores da linha 6 (r6 := levantarGarfoDireito [g1]) o trinco polim´orficoe1ser´a substitu´ıdo porg1, e esta substituic¸˜ao ´e efetuada sobre uma r´eplica do tipo da etiqueta

levantarGarfoDireito. Ap´os a aplicac¸˜ao levantarGarfoDireito [g1], o tipo do registo r6 fica

∀ d1::Lock({g1},{}).{r1:lock g1,r2:lock d1} requires {g1}. O replaceTypeVariable substitui, no tipo corrente, a vari´avel de tipotvpelo tipotype. Este m´etodo utiliza-se quando ´e feita uma aplicac¸˜ao de tipos, pois neste caso ´e necess´ario efetuar a substituic¸˜ao das vari´aveis. Por fim, o m´etodo unify determina se dois tipos s˜ao equivalentes. Unify foi implemen- tado com base no algoritmo de unificac¸˜ao apresentado em [1]. A unificac¸˜ao de dois tipos

determina a substituic¸˜ao que torna os tipos idˆenticos.

A classe TypeVariable representa as vari´aveis de tipo. Para al´em dos m´etodos que implementa do interface Type, cont´em os m´etodos getName, getLessSet e getGreaterSet. O m´etodogetNamedevolve uma representac¸˜ao textual da vari´avel. O m´etodogetLessSet

devolve o conjunto de trincos menores que a vari´avel e o m´etodogetGreaterSetdevolve o conjunto de trincos maiores que a vari´avel.

A classe UninitializedTyperepresenta o tipo n˜ao inicializado. Foi acrescentado o m´eto- do getType que devolve o tipo inicializado. A classe IntType representa o tipo inteiro e classe StringType representa o tipo string. A classe LockType representa o tipo lock. O m´etodogetLockdevolve o trinco correspondente ao tipo.

A classeTupleTyperepresenta o tuplo de tipos e cont´em os m´etodosgetLock, initialize

e uninitialized. Esta classe ´e iter´avel nos tipos do tuplo. O m´etodogetLockdevolve o trinco que protege o tuplo; o m´etodo initialize inicializa o tipo que est´a no ´ındice, passado por parˆametro, do tuplo e o m´etodo uninitialized torna o tipo que est´a no ´ındice, passado por parˆametro, do tuplo, num tipo n˜ao inicializado.

A classeCodeTyperepresenta o tipo bloco de c´odigo. Esta cont´em os m´etodosgetPermi ssions, getRegisters, isContainedAll e removeAll. O m´etodo getPermissions devolve o con- junto de permiss˜oes, e ogetRegistersdevolve a tabela de registos. O m´etodoisContainedAll

verifica se um conjunto de permiss˜oes (otherPermissions) cont´em todos os trincos fechados (permissions) do tipo atual. O m´etodo removeAllremove, de um conjunto de permiss˜oes (otherPermissions), todos os trincos fechados (permissions) do tipo atual.

A classe ExistsType representa o tipo existencial. Para al´em dos m´etodos que im- plementa do interfaceType, a classe ExistsType cont´em os m´etodosgetType, getVariablee

isLock. O m´etodogetTypedevolve o tipo abstra´ıdo contido no tipo existencial. O m´etodo

getVariable devolve a vari´avel de tipo. O m´etodoisLock indica se a vari´avel de tipo abs- tra´ıda ´e um trinco. A classeUniversalTyperepresenta o tipo universal. Esta classe cont´em exatamente os mesmos m´etodos que a classeExistsTypee com o mesmo significado.

Contextos

Contextos s˜ao estruturas de dados que guardam informac¸˜ao relevante para apoiar a an´alise semˆantica. A implementac¸˜ao dos v´arios contextos foi realizada atrav´es de conjuntos e mapas da linguagem Java. Usamos os conjuntos porque estes n˜ao permitem que haja elementos duplicados e tˆem as operac¸˜oes que precisamos: adicionar, remover e procurar elementos. Relativamente aos mapas, utiliz´amo-los porque precisamos de estabelecer uma relac¸˜ao entre identificadores e os seus tipos.

Os contextos de tipificac¸˜ao existentes no interpretador s˜ao: o conjunto de permiss˜oes, conjunto de trincos definidos, tabela Ψ que mapeia etiquetas com tipos e, por fim, a tabela Γ, que mapeia registos com os seus tipos.

trincos definidos (K) s˜ao Set<TypeVariable>, em que TypeVariable representa os trincos, Ψ ´eMap<Symbol, Type>, em queSymbolrepresenta uma etiqueta eTyperepresenta o tipo da etiqueta, e o Γ ´eMap<Register, Type>, em que Registerrepresenta um registo e Type

representa o tipo do registo.

Por fim, devido `a definic¸˜ao de tipos, associamos o tipo ao nome da definic¸˜ao atrav´es da tabelaMap<Symbol, Type>, em queSymbolrepresenta o nome do tipo eTyperepresenta o tipo da definic¸˜ao.

Visitantes

A fase de an´alise semˆantica assenta em v´arios visitantes para efetuar as verificac¸˜oes ne- cess´arias, de forma a averiguar se um programa ´e semanticamente correto. Os visitantes constru´ıdos foram os seguintes:DeclarationTypesVisitor, DeclarationVisitor,ExistsMainVisitor,

GlobalLockVisitor, InferRegistersVisitor, HeapValues, WellFormedTypes, TypeCheckValues e

TypeCheckerVisitor.

O visitante DeclarationTypesVisitor recolhe os tipos que s˜ao definidos globalmente e guarda-os na tabela de tipos globais. Para al´em disso, verifica se os tipos est˜ao bem formados, passando o visitanteWellFormedTypessobre o tipo da definic¸˜ao.

O DeclarationVisitor preenche o mapa Ψ (Map<Symbol, Type>). Antes de adicionar uma nova etiqueta na tabela, verifica se esta j´a existe na mesma. Se a etiqueta n˜ao existir na tabela, ´e adicionada com o respetivo tipo. No caso da etiqueta j´a existir, ´e lanc¸ado um erro, pois n˜ao ´e permitido a existˆencia de duas etiquetas com o mesmo nome.

O visitanteExistsMainVisitorverifica se existe a etiquetamain e se n˜ao requer registos nem permiss˜oes.

OGlobalLockVisitor´e um visitante que recolhe as declarac¸˜oes de trincos globais de pro- gramas MIL. O visitante InferRegistersVisitor infere o n´umero de registo dos programas. O visitanteHeapValuespercorre todas as etiquetas do programa e preenche os contextos. As etiquetas de um programa MIL podem ser compostas de 3 formas:

1. o tipo ´e um bloco de c´odigo e o valor um bloco de instruc¸˜oes;

2. o tipo ´e um tuplo de tipos e o valor um tuplo de valores;

3. o tipo ´e lock e o valor um valor de trincos.

Sobre cada tipo das etiquetas, ´e executado o visitante WellFormedTypes para analisar se o tipo est´a bem formado. No caso de uma etiqueta estar associada ao tipo lock e, no amontoado o valor do trinco ser 0, ´e adicionado o trinco ao conjunto de permiss˜oes. Por fim, no caso de o tipo ser um tuplo de tipos e o amontoado um tuplo de valores, ´e verificado se os tipos de cada um dos valores do tuplo de valores correspondem aos tipos do tuplo de tipos. Este visitante implementa as regras da figura B.1.

O visitanteWellFormedTypesverifica se um determinado tipo est´a bem formado. Este visitante ´e aplicado apenas sobre tipos e implementa as regras das figuras 3.4 e B.2.

O visitanteTypeCheckValuestem como finalidade obter o tipo dos valores, verificar se estes j´a foram declarados, ou seja, verifica se valores como etiquetas e registos j´a est˜ao declarados. No caso de n˜ao estarem, ´e lanc¸ado um erro. ´E verificado ainda se os valores ?τ elock l est˜ao bem formados. Este visitante implementa as regras da figura B.4. Por exemplo, na regra T-LABEL, ao receber a etiqueta l, devolve o seu tipo no caso de l existir em Ψ; caso contr´ario, ´e lanc¸ado um erro. No caso da regra T-REG, verifica-se se o registo

que esta recebe existe em Γ. Se existir, devolve o tipo do registo; caso contr´ario, lanc¸a um erro.

OTypeCheckerVisitor ´e o visitante principal da an´alise semˆantica e implementa as re- gras da figura 3.5.

Para al´em destes visitantes, foram constru´ıdos outros para proceder `a inferˆencia de anotac¸˜oes, de acordo com o algoritmo descrito no cap´ıtulo anterior. Os visitantes s˜ao:

LockDefinitionRestrictionsVisitor, SignatureRes trictionsVisitor, CodeBlockRestrictionsVisitore

RestrictionsEmitter.

O visitante LockDefinitionRestrictionsVisitor recolhe, atrav´es das anotac¸˜oes que se en- contram em programas MIL, as restric¸˜oes decorrentes dessas anotac¸˜oes. Este visitante recolhe apenas as restric¸˜oes no caso de existirem anotac¸˜oes nos programas. O visitante

SignatureRestrictionsVisitor percorre todas as assinaturas de blocos de c´odigo e gera novas anotac¸˜oes (vari´aveis de conjuntos) e novas restric¸˜oes. ´E poss´ıvel gerar estas anotac¸˜oes e restric¸˜oes de trˆes modos diferentes: quando o tipo da assinatura ´e∀ l :: Lock, quando a declarac¸˜ao de um trinco no corpo do bloco ´e (λ :: Lock.τ ) ou quando ´e uma instruc¸˜ao

unpack. Neste visitante, s˜ao geradas duas vari´aveis de conjuntos (Ln e Ln+1, em que n

´e um n´umero gerado cada vez que ´e criada uma vari´avel de conjuntos) e trˆes restric¸˜oes (Ln ≺ l, l ≺ Ln+1 e Ln ≺ Ln+1). Estas restric¸˜oes s˜ao geradas de acordo com a fi-

gura 3.8. Este visitante recolhe apenas as restric¸˜oes das vari´aveis de tipos que n˜ao contˆem anotac¸˜oes, uma vez que, no caso de conter anotac¸˜oes, as restric¸˜oes s˜ao recolhidas pelo visitante LockDefinitionRestrictionsVisitor.

O visitante CodeBlockRestrictionsVisitorrecolhe as restric¸˜oes que possam ser geradas dentro dos blocos de c´odigo. Essas restric¸˜oes s˜ao obtidas de acordo com o algoritmo apresentado no cap´ıtulo 4.

O visitante RestrictionsEmitter ´e o respons´avel por emitir as restric¸˜oes para o Z3 reco- lhidas pelos visitantes anteriores.

Por fim, apresentamos os m´etodos que concretizam a an´alise semˆantica, ilustramos alguns m´etodos das regras de tipos de instruc¸˜oes. Em relac¸˜ao `a regra T-FORK, esta ser´a aplicada quando na ´arvore existir um n´o que represente a instruc¸˜aofork. Para implementar a regra, o m´etodo a redefinir ´epublic void caseAForkInstruction (AForkInstruction node). Em primeiro lugar, ´e verificado se o tipo do registo r ´e do tipo bloco de c´odigo; no caso

de n˜ao ser, ´e lanc¸ado um erro. De seguida, verifica-se se as permiss˜oes requeridas pelo registo r est˜ao no conjunto de permiss˜oes atual. Se n˜ao estiverem, ´e lanc¸ado um erro, caso contr´ario as permiss˜oes que s˜ao requeridas pelo registo r s˜ao retiradas do conjunto de permiss˜oes atual. Por fim, verifica-se se o bloco de c´odigo do registo r ´e subtipo do bloco de c´odigo atual.

No que diz respeito `a instruc¸˜aonew, ´e necess´ario redefinir o m´etodopublic void case ANewInstruction(ANewInstruction node). A figura 5.3 ilustra o modo como esta regra foi implementada.

Se o tipo que a instruc¸˜ao recebe ´e um tuplo

1. Verifica se o tuplo est´a bem formado e no caso de n˜ao estar ´

e adicionado um erro `a lista de erros.

2. Transforma os tipos do tuplo em tipos n˜ao inicializados.

3. Adiciona a Γ o par (registo, tuplo com tipos n˜ao inicializados). Se o tipo que a instruc¸˜ao recebe ´e um trinco

1. Verifica se o tipo est´a bem formado e no caso de n˜ao estar, ´

e adicionado um erro `a lista de erros.

2. Adiciona o trinco ao conjunto de permiss˜oes Λ. 3. Adiciona a Γ o par (registo, trinco).

Sen˜ao

Adiciona o erro "´E esperado um tuplo de tipos ou um trinco" `

a lista de erros.

Figura 5.3: Algoritmo para a instruc¸˜aonew

Em relac¸˜ao `a regra T-STORE, que corresponde ao n´o AStoreInstruction, o m´etodo a redefinir ´e opublic void caseAStoreInstruction(AStoreInstruction node). A figura 5.4 ilustra o modo como esta regra foi implementada.

Em relac¸˜ao `a regra T-GSL, esta corresponde ao n´oAGetsetlockInstructionda AST. Para implementar esta regra, ´e necess´ario redefinir o m´etodopublic void caseAGetsetlockInstruc tion (AGetsetlockInstruction node). Em primeiro lugar, verifica-se se o registo ´e um trinco. No caso de ser falso, ´e adicionado um erro `a lista de erros; caso contr´ario, ´e verificado se o trinco j´a se encontra no conjunto de permiss˜oes. No caso de se encontrar no conjunto, ´e adicionado o erro ”O trinco j´a se encontra fechado” `a lista de erros. Por fim, ´e adicionado a Γ o par (registo, vari´avel de tipo do trinco).

Para a regra T-DONE, ´e necess´ario redefinir o m´etodopublic void caseADoneInstruction (ADoneInstruction node), no qual o n´o visitado representa a instruc¸˜ao done. Nesta regra, ´e apenas necess´ario garantir que n˜ao existe nenhum trinco fechado, ou seja, que o conjunto de permiss˜oes esteja vazio. No caso de este n˜ao estar vazio, ent˜ao ´e adicionado o erro ”Os trincos devem ser abertos”.

Por fim, apresentamos como foram implementadas as regras de valores T-REG e T-

VALAPP. Para a regra T-REG, ´e necess´ario redefinir o m´etodopublic void caseARegisterVa lue(ARegisterValue node), no qual o n´o visitado representa um registo. Inicialmente, ´e

Se o registo r n˜ao existe em Γ

Adiciona o erro "Registo n˜ao inicializado" `a lista de erros Se o registo r’ n˜ao existe em Γ

Adiciona o erro "Registo n˜ao inicializado" `a lista de erros Se o tipo do registo r n˜ao for um tuplo

Adiciona o erro "Espera um valor do tipo tuplo" `a lista de erros Se o ´ındice n n˜ao ´e v´alido

Adiciona o erro "O ´ındice n est´a fora dos limites" `a lista de erros Se Λ n˜ao cont´em o trinco λ

Adiciona o erro "O trinco n˜ao pertence `as permiss˜oes" `

a lista de erros TUPLO <- tipo do registo r

TIPO <- tipo que est´a no ´ındice n do tuplo TIPO DESTINO <- tipo do registo r’

Se TIPO DESTINO n˜ao ´e subtipo de TIPO Adiciona um erro `a lista de erros Sen˜ao

Inicializar TIPO

Adiciona a Γ o par (r, TUPLO)

Figura 5.4: Algoritmo para a regra T-STORE

obtido o tipo do registo atrav´es da tabela Γ, se o tipo for null, indica que o registo n˜ao foi inicializado antes, ou seja, ´e adicionado o erro ”Registo n˜ao inicializado”. Por fim, ´e devolvido o tipo do registo.

No que diz respeito `a regra T-VALAPP, ´e necess´ario redefinir o m´etodo public void ca seAValApp(AValApp node), no qual o n´o visitado representa a aplicac¸˜ao de valores. A fi- gura 5.5 ilustra o modo como esta regra foi implementada.

Se o tipo τ n˜ao estiver bem formado

Adiciona o erro "O tipo τ n˜ao est´a bem formado" `a lista de erros Se o tipo do valor v n˜ao ´e um tipo universal

Adiciona o erro "Espera um valor do tipo universal" `a lista de erros Se o λ do tipo universal ´e um trinco, ou seja: λ :: Lock

e o tipo τ n˜ao ´e um trinco

Adiciona o erro "Espera um trinco" `a lista de erros

No tipo τ ’ o τ ´e substitu´ıdo por λ, usando o m´etodo replaceTypeVariable. ´

E devolvido o tipo τ ’ com as substituic¸˜oes anteriores.

Trinco Vari´aveis Constante g1 L0 e L1 #b0000000100 g2 L2 e L3 #b0000000010 g3 L4 e L5 #b0000000001 e L6 e L7 #b0000001000 d L8 e L9 #b0001000000 l L10 e L11 #b1000000000 e1 L12 e L13 #b0000100000 d1 L14 e L15 #b0100000000 e2 L16 e L17 #b0000010000 d2 L18 e L19 #b0010000000

Tabela 5.1: Constantes e vari´aveis de trincos

Z3

No Z3 representamos os trincos e os conjuntos de trincos usando a teoria vetores de bits. O tamanho do vetor de bits coincide com o n´umero de trincos declarado no programa. A cada trinco ´e atribu´ıdo um bit diferente, uma potˆencia de 2. Um conjunto de trincos ´e representado por um vetor. Neste vetor, os bits correspondentes aos trincos que pertencem ao conjunto tˆem valor 1 e os restantes 0.

As func¸˜oes e predicados que definimos s˜ao gerados para cada programa, uma vez que o seu tipo depende do n´umero de trincos do programa e o Z3, como a generalidade dos SMT, n˜ao aceita definic¸˜oes polim´orficas em func¸˜oes.

De forma a ilustrar as func¸˜oes e os predicados gerados para cada programa, apresen- tamos um exemplo, que usa o programa da figura 4.1. O exemplo cont´em dez trincos:

g1, g2, g3, e, d, l, e1, d1, e2 e d2. Os trincos s˜ao representados por constantes. Por exemplo, em Z3, atribu´ımos ao trincog1do bloco main a constante#b0000000100, en- quanto ao trinco d do bloco levantarGarfoEsquerdo atribu´ımos #b0001000000, tal como podemos ver na tabela 5.1. Esta tabela apresenta as constantes e as vari´aveis de conjun- tos a que cada trinco corresponde. Outra qualquer escolha de constantes para os trincos seria v´alida, desde que fossem usados valores distintos para cada trinco. Para represen- tar o conjuntoL0, usamos a definic¸˜ao(declare−const L0 ( BitVec 10)), que declara uma constante com o nome da vari´avel (L0) e o seu tipo (um vetor de bits de tamanho coinci- dente com o n´umero de trincos do programa).

Para representar as restric¸˜oes h´a que implementar predicados e func¸˜oes que nos per- mitam escrever, por exemplo, que um trinco ´e menor do que um conjunto de trincos ou efetuar uma substituic¸˜ao de um trinco por outro num dado conjunto, de acordo com a representac¸˜ao que escolhemos para os trincos e para os conjuntos de trincos. O excerto seguinte define o predicadosubset e as func¸˜oesremove e add, que s˜ao utilizados para definir a func¸˜ao de substituic¸˜aosubs.

(define−fun subset ((S ( BitVec 10)) (S1 ( BitVec 10))) Bool

(= (bvand S S1) S))

(define−fun remove ((l ( BitVec 10)) (S ( BitVec 10))) ( BitVec 10) (bvand (bvxor All l ) S))

(define−fun add ((l ( BitVec 10)) (S ( BitVec 10))) ( BitVec 10) (bvadd l S))

(define−fun subs ((l( BitVec 10)) (m( BitVec 10)) (S( BitVec 10))) ( BitVec 10) (if (subset m S) (add l (remove m S)) S))

Para cada predicado e func¸˜ao, a primeira linha define a sua assinatura e a linha seguinte o seu corpo, escrito numa notac¸˜ao prefixa. As express˜oesbvand, bvxore bvadd fazem parte da teoria do Z3 para vetores de bits. Foram definidas duas constantes que s˜ao utili- zadas na definic¸˜ao de func¸˜oes e predicados. A constanteEmptyrepresenta um conjunto va- zio ((define−const Empty ( BitVec 10) #b0000000000)) e a constante Allrepresenta um conjunto com todos os trincos de um programa ((define−const All ( BitVec 10) #b1111

111111)). O predicadosubset verifica se o conjunto S est´a contido no conjuntoS1. A assinatura indica que o predicado tem dois parˆametrosS eS1, ambos do tipo BitVec 10, enquanto o resultado da func¸˜ao, definido a seguir aos dois parˆametros, ´e um booleano. O corpo do predicado aplica, sobre ambos os conjuntos, a express˜ao bvand, de forma a devolver um conjunto que contenha elementos que ambos os conjuntos contˆem. De se- guida, ´e verificado se este conjunto ´e igual ao conjuntoS, pois caso seja, o conjunto S

est´a contido emS1.

A assinatura da func¸˜aoremoveindica que a func¸˜ao tem dois parˆametros l eS, todos do tipo BitVec 10, tal como o retorno da func¸˜ao. O objetivo desta func¸˜ao ´e remover o elemento l do conjuntoS. Esta devolve um novo vetor de bits sem o elemento removido. A assinatura da func¸˜ao add ´e idˆentica `a assinatura da func¸˜ao remove. O objetivo desta func¸˜ao ´e adicionar o elementol ao conjuntoS. Esta devolve um novo vetor de bits com o elemento adicionado. A func¸˜aosubsimplementa a substituic¸˜ao dempor l emS(S[m/l]). A assinatura indica que a func¸˜ao tem trˆes parˆametros l,meS, todos do tipoBitVec 10, tal como o retorno da func¸˜ao. O corpo da func¸˜ao removeme adiciona l aS, casompertenc¸a aS. Caso contr´ario, comporta-se como a func¸˜ao identidade.

Os predicados setLessThanLock (apresentado na figura 5.6), lockLessThanSet (figura 5.7) esetLessThanSet(figura 5.8) representam a relac¸˜ao entre trincos e conjuntos. Os pre- dicadossetLessThanLock, lockLessThanSet e setLessThanSet definem, de forma expl´ıcita (com recurso a express˜oes condicionais), a associac¸˜ao entre trincos e vari´aveis sobre con- juntos, pois o Z3 n˜ao tem modo de especificar relac¸˜oes de dependˆencia funcional entre diferentes valores que permitam estabelecer esta associac¸˜ao, de forma compacta e efici- ente.

O predicadosetLessThanLockverifica se um conjunto ´e menor que um trinco, ou seja, se o vetor de bitsS´e menor que l. O predicado recebe trˆes vetores de bits: o primeiro,S, ´e o conjunto que se pretende que seja menor que o trinco; o segundo, l, ´e o trinco em

(define−fun setLessThanLock

2 (( S ( BitVec 10)) ( l ( BitVec 10)) (Less l ( BitVec 10))) Bool

(if (= S Empty)

4 true

(∀ (( x ( BitVec 10))) 6 (if (subSet x S)

(if (= #b0000000100 x) ;corresponde a g1

8 (or (subSet #b0000000100 Less l) (subSet l L1))

(if (= #b0000000010 x) ;corresponde a g2

10 (or (subSet #b0000000010 Less l) (subSet l L3))

(if (= #b0000000001 x) ;corresponde a g3

12 (or (subSet #b0000000001 Less l) (subSet l L5))

(if (= #b0000001000 x) ;corresponde a e

14 (or (subSet #b0000001000 Less l) (subSet l L7))

(if (= #b0001000000 x) ;corresponde a d

16 (or (subSet #b0001000000 Less l) (subSet l L9))

(if (= #b1000000000 x) ;corresponde a l

18 (or (subSet #b1000000000 Less l) (subSet l L11))

(if (= #b0000100000 x) ;corresponde a e1

20 (or (subSet #b0000100000 Less l) (subSet l L13))

(if (= #b0100000000 x) ;corresponde a d1

22 (or (subSet #b0100000000 Less l) (subSet l L15))

(if (= #b0000010000 x) ;corresponde a e2

24 (or (subSet #b0000010000 Less l) (subSet l L17))

(if (= #b0010000000 x) ;corresponde a d2

26 (or (subSet #b0010000000 Less l) (subSet l L19)) true )))))))))) ;no caso de ser vazio

28 true) ;para continuar o ciclo

) 30 ))

Figura 5.6: Representa o predicadosetLessThanLock

quest˜ao; e o terceiro vetor ´e o conjunto de trincos menores de l. Para verificar se o conjuntoS ´e menor que o trinco l, temos de verificar se todos os elementos do conjunto s˜ao menores que o trinco. Se, por exemplo, o trincog1, (#b0000000100), ´e menor que l, temos de verificar se g1 pertence ao conjunto de trincos menores (Less l) de l ou se l

pertence ao conjunto de trincos maiores (L1) de l1.

O predicadolockLessThanSetverifica se um trinco ´e menor que um conjunto, ou seja, se l ´e menor que o vetor de bits S. Tal como o predicadosetLessThanLock, que recebe trˆes vetores de bits: o primeiro, l, ´e o trinco em quest˜ao; o segundo, S, ´e o conjunto que se pretende que seja maior que o trinco l; e o terceiro vetor ´e o conjunto de trincos maiores de l. Para que o trinco l seja menor que o conjuntoS, temos de verificar se o trinco ´e menor que todos os elementos do conjunto. O que se confirma, se, por exemplo, o trincol ´e menor queg1, (#b0000000100) e se l pertence ao conjunto de trincos maiores

(define−fun lockLessThanSet

2 (( l ( BitVec 10))(S ( BitVec 10)) ( Greater l ( BitVec 10)))Bool

(if (= S Empty)

4 true

(∀ (( x ( BitVec 10))) 6 (if (subSet x S)

(if (= #b0000000100 x) ;corresponde a g1

Documentos relacionados