• Nenhum resultado encontrado

As figuras 6.2 e 6.3 ilustra uma implementac¸˜ao do c´alculo do fatorial de um n´umero escrito em MOOL. O c´alculo do fatorial ´e conseguido atrav´es da competic¸˜ao, de dois fios de execuc¸˜ao, a fim de obter n´umeros de forma a multiplicar os valores de cada fio de execuc¸˜ao. Quando ambos os fios de execuc¸˜ao terminarem, ´e efetuado o produto do resultado dos fios de execuc¸˜ao. Por exemplo, para calcular o fatorial de 6 desta forma, um dos fios de execuc¸˜ao (A) ter´a de consumir os n´umeros 1, 3 e 4 e o outro fio, B, consumir

class Fatorial {

2 int valor ; int prod1; int prod2; boolean fimProd1; boolean fimProd2;

4 unit inicializar ( int v){

valor = v + 1;

6 prod1 = 1; prod2 = 1;

fimProd1 =false; fimProd2 = false;

8 } unit calcProd1() { 10 int n; n = decNum(); while (n > 0) { 12 prod1 = prod1 ∗ n; n = decNum(); 14 } fimProd1 =true; 16 } unit calcProd2() { 18 int n; n = decNum(); while (n > 0) { 20 prod2 = prod2 ∗ n; n = decNum(); 22 } fimProd2 =true; 24 }

sync int decNum() {

26 valor = valor − 1; valor ; 28 } unit getResult() { 30 while (! fimProd1) { while (! fimProd2) {} 32 }

int result ; result = prod1 ∗ prod2;

34 printInt ( result );

} 36 }

Figura 6.2: Fatorial escrito em MOOL

os n´umeros 2, 5 e 6, com isto, o resultado de A seria 12 e do B seria 60. O produto do resultado de A com B seria 720.

O programa ´e composto por duas classes: Main(6.3) e Fatorial (6.2). Cada classe tem de ser programada num ficheiro com o seu nome, `a semelhanc¸a do que ocorre em Java. Na classe Fatorial (6.2) s˜ao declarados cinco m´etodos e cinco atributos. Os atributos, cujos os nomes s˜aovalor,prod1eprod2(linha 2), s˜ao do tipo inteiro. Os restantes atributosfimProd1

efimProd2s˜ao do tipo booleano. A definic¸˜ao de m´etodos corresponde a uma assinatura e um corpo. Por exemplo, o m´etodo inicializar (linhas 4–8) aceita um parˆametro inteiro e devolve um valor do tipounit, que tem semelhanc¸as com o tipovoiddo Java. O objetivo deste m´etodo ´e inicializar os atributos da classe. As linhas 9, 17 e 29 da figura 6.2 e a linha 2 da figura 6.3 contˆem as assinaturas dos m´etodoscalcProd1,calcProd2,getResult

class Main {

2 unit main() {

Fatorial f ; f =new Fatorial ();

4 f . inicializar (5); spawn f.calcProd1(); 6 spawn f.calcProd2(); f .getResult (); 8 } }

Figura 6.3: Classe Main

emain, respetivamente, que n˜ao recebem parˆametros nem retornam valores. O objetivo do m´etodogetResult ´e garantir que o resultado do programa seja apresentado apenas quando ambos os fios de execuc¸˜ao tenham terminado. A linha 25 da figura 6.2 cont´em a assinatura do m´etododecNum, este retorna um valor do tipo inteiro e n˜ao recebe parˆametros, mas ´e um m´etodo sincronizado, pois possui a primitivasync. Esta primitiva garante que n˜ao existam condic¸˜oes de corrida emvalor.

As express˜oes dos corpos dos m´etodos s˜ao idˆenticas `as linguagens imperativas usu- ais. As ´unicas diferenc¸as residem no retorno dos m´etodos e na criac¸˜ao de novos fios de execuc¸˜ao. O retorno dos m´etodos n˜ao tem nenhuma primitiva associada, pois basta colo- car o valor que se pretende que o m´etodo devolva. Por exemplo, na linha 27 da figura 6.2 ´e devolvido o atributo valor. No que diz respeito `a criac¸˜ao de novos fios de execuc¸˜ao, ´e usada a primitivaspawn(linhas 5-6 da figura 6.3). Neste caso, estamos a criar dois novos fios de execuc¸˜ao para calcular o fatorial de um n´umero de forma concorrente, ou seja, o que acontece ´e que tanto ocalcProd1 como ocalcProd2 usam o m´etodo decNum. Como este m´etodo ´e sincronizado, os m´etodosincProd1e incProd2consomem o pr´oximo valor de uma forma sincronizada.

Compilac¸˜ao de MOOL em MIL

Neste cap´ıtulo apresentamos a func¸˜ao de traduc¸˜ao que serve de base `a implementac¸˜ao de um compilador da linguagem MOOL na linguagem MIL, ambas apresentadas nos cap´ıtulos anteriores.

Para efetuar a traduc¸˜ao foram usadas duas t´ecnicas: continuation-passing style (CPS) [21] e closure conversion [20]. Continuation-passing style ´e um modelo de programac¸˜ao em que ´e passado a cada func¸˜ao o enderec¸o onde o programa deve continuar ap´os a execuc¸˜ao da func¸˜ao. Este modelo contrasta com o modelo de pilha de chamada. Closure conversion´e um processo de eliminac¸˜ao de vari´aveis livres da definic¸˜ao de func¸˜oes. Esta eliminac¸˜ao permite que o compilador contenha definic¸˜oes locais fora do seu contexto, adicionando um parˆametro extra que substitui cada uma das vari´aveis locais da func¸˜ao a ser chamada.

7.1

Func¸˜ao de Traduc¸˜ao

A func¸˜ao de traduc¸˜ao mapeia a estrutura da linguagem fonte na estrutura da linguagem alvo. Por´em, o processo de traduc¸˜ao de MOOL em MIL n˜ao ´e direto nem trivial, uma vez que os tipos da linguagem alvo s˜ao bastante ricos.

A traduc¸˜ao de MOOL em MIL compreende a traduc¸˜ao de programas (P[·]), de classes (C[·]), de m´etodos (M[·]), de tipos (T [·]), de valores (V[·]), de express˜oes (E [·]) e de operadores booleanos (O[·]).

O processo de traduc¸˜ao de MOOL em MIL inicia-se pela func¸˜ao de traduc¸˜ao de pro- gramas, que guia a traduc¸˜ao e invoca as restantes func¸˜oes, quando necess´arias. A traduc¸˜ao de programas P[·] cont´em v´arios blocos de c´odigo, incluindo o bloco de arranque da m´aquina abstrata do MIL, o blocomain. Antes de saltar para a etiquetamainMain, cujo m´etodo corresponde ao ponto de partida do compilador do MOOL (o m´etodo main da classeMain), s˜ao preenchidos os registos necess´arios para a continuac¸˜ao do m´etodomain. O bloco de c´odigo da etiquetadoneLabel ir´a conter apenas a instruc¸˜ao donede forma a terminar o fio de execuc¸˜ao, lanc¸ado pela etiquetamain. Por fim, s˜ao traduzidas todas as

classes ( ~D) do programa. A traduc¸˜ao de um programa P[·] ´e efetuada da seguinte forma:

P[ ~D] , main :: {} main = {

r1 :=newRO <>

r2 :=newRO < r1, doneLabel >

r2 :=pack <> guarded by readOnly, r2 as ∃e. < e, {r1 : e} > guarded by readOnly l1 :: Lock

r4 :=new lock l1 r3 :=new M ain[l1] jump mainM ain[l1] }

C[D1] ... C[Dn]

A traduc¸˜ao de m´etodos que permitem imprimir resultados na consola (printInt, print Bool e printStr) ´e tratada de forma diferente, porque no MIL n˜ao existe uma forma di- reta de imprimir na consola, tal como explicado no cap´ıtulo 3. Posto isto, estes blocos s˜ao carregados na func¸˜ao de traduc¸˜ao de programas, pois estes m´etodos s˜ao iguais em todos os programas traduzidos. A figura 7.1 apresenta a forma como a traduc¸˜ao dos m´etodos printInt e printBool ´e feita. A etiqueta printLock ´e uma entrada especial, que ´e do tipo lock consoleLock. No que diz respeito ao m´etodo printStr, a ´unica diferenc¸a, para a traduc¸˜ao acabada de apresentar, ´e que, em vez de se colocar r3 [1] := r1 na eti- queta printIntCritical , coloca-ser3 [2] := r1, e o tipo der1passa a serstring.

A traduc¸˜ao de uma classe C[·] ´e feita da seguinte forma:

C[class C {u; ~t~f ; ~M }] , type T AtrC = ∀λ :: Lock. < T [~t ] >λ

type T ClasseC = ∃λ0 :: Lock. < T AtrC[λ0], lock λ0 >readOnly C1... Cnwhere

(C1, T1) = M[M1, ∅],

(C2, T2) = M[M2, T1] ... (Cn, Tn) = M[Mn, Tn−1]

Para cada classe ´e criado um identificador de tipos global com o nome TAtrC. Este ´e um tipo universal que abstrai o trinco que protege o tuplo que vai guardar os atributos da classe C. Para al´em disto, ´e criado outro identificador com o nome TClasseC. Este identificador representa um tipo existencial, que define um par que cont´em o tuplo com

unit printInt(int x) , printInt :: {r1 : < int > guarded by readOnly, r2 : ∃e. < e, {r1 : e} > guarded by readOnly} printInt = { r3 := printLock r4 :=getSetLock r3 if r4 == 0 jump printIntCritical jump printInt }

printIntCritical :: {r1 : < int > guarded by readOnly, r2 : ∃e. < e, {r1 : e} > guarded by readOnly} requires {consoleLock} printIntCritical = { r1 := r1[1] r3 := console r3[1] := r1 r4 := printLock unlock r4 l, r2 :=unpack r2 r1 := r2[1] r2 := r2[2] jump r2 }

Figura 7.1: Func¸˜ao de traduc¸˜ao dos m´etodos printInt eprintBool

os atributos da classe C e o trinco que protege este tuplo. O novo tuplo ´e protegido porreadOnlypara diminuir a construc¸˜ao no acesso a informac¸˜ao sobre objetos de classes diferentes (ver vantagens na secc¸˜ao 3.3). O objetivo deste ´ultimo identificador ´e guardar, na mesma estrutura, os atributos e o trinco que protege o tuplo de forma a permitir obter e libertar o trinco, quando ´e necess´ario usar um atributo. Por fim, ´e traduzido cada m´etodo da classe. Esta traduc¸˜ao recebe como parˆametro, a tabela T, que mapeia referˆencias a objetos com os tuplos descritos. No inicio a tabela est´a vazia, e vai sendo preenchida ao longo da traduc¸˜ao dos m´etodos.

A traduc¸˜ao dos tipos T [·] de MOOL para MIL ´e simples: o tipo integer ´e traduzido emint; o tipo booleano ´e traduzido como tipo inteiro e o tipo C[u] ´e traduzido no identi-

ficador de tipos que representa a classeC, TClasseC. Como abaixo se ilustra:

T [int] , int T [boolean] , int

T [C[u]] , T ClasseC

A func¸˜ao de traduc¸˜ao relativa aos m´etodos M[·] ´e a seguinte:

M[s t m(~t ~x) {e}, T ] , (H, T0) where

H = m :: ∀ λ :: Lock. {r1 : < T [~t ] > guarded by readOnly, r2 : ∃ b. < b, {r : b} > guarded by readOnly, r3 : T Atr[λ], r4 : lock λ} requires {λ}

m = { C unlock r4 l, r0 :=unpack r0 r := r0[1] r0 := r0[2] jump r0 } (C, T0) = E [e, T ]

A func¸˜ao recebe como parˆametros a definic¸˜ao dos m´etodos e a tabelaT, e devolve um par (H, T0) em queHcont´em o c´odigo MIL e T0a tabela que cont´em os objetos associados aos registos. A declarac¸˜ao de m´etodos no MOOL apoia a assinatura das etiquetas do MIL, pois, como se pode verificar na func¸˜ao, a etiqueta com o nomemfica com um tipo bloco de c´odigo. Assim, os parˆametros do m´etodoms˜ao associados aor1, na forma de um tuplo com os tipos ~t dos parˆametros. Para al´em deste tuplo, os m´etodos contˆem a continuac¸˜ao (atrav´es do uso da t´ecnica continuation-passing style), ou seja, o registo r2 indica para onde a etiquetamvai saltar no fim da avaliac¸˜ao. O registor3cont´em os atributos da classe `a qual o m´etodo pertence e o registor4cont´em o trinco que protege o tuplo der3. O corpo do bloco de c´odigo resulta da traduc¸˜ao das express˜oesedo m´etodo. Por fim, o registor2

´e desempacotado (sem impacto em tempo de execuc¸˜ao) de forma a carregar os registos necess´arios para a continuac¸˜ao, j´a que esta necessita que o registor1fique com o tipob.

Em relac¸˜ao `a traduc¸˜ao de valores V[·], os booleanos true e false s˜ao traduzidos em inteiros 0 e 1, respetivamente. Por sua vez, os valores inteiros s˜ao iguais em ambas as

linguagens e os objetos passam a ser os registos onde estes foram criados. Esta corres- pondˆencia ´e obtida atrav´es da tabelaT, pois o m´etodo get(o) devolve o registo que est´a associado ao objetoo. A traduc¸˜ao de valores V[·] ´e assim ilustrada:

V[true, T ] , 0 V[false, T ] , 1 V[n, T ] , n

V[o, T ] , T.get(o)

A func¸˜ao de traduc¸˜ao para express˜oes ´e representada por E [·]. Esta func¸˜ao recebe como parˆametros uma express˜ao e a tabelaT, e devolve um par(H, T), tal como a func¸˜ao de traduc¸˜ao dos m´etodos M[·]. A traduc¸˜ao da express˜ao v corresponde `a traduc¸˜ao de valores V[·]. A func¸˜aoposition (x)obt´em a posic¸˜ao do parˆametro x no tuplo de parˆametros.

E[v, T ] , (V[v, T ], T ) E[x, T ] , (r[position(x)], T )

Em relac¸˜ao `a utilizac¸˜ao de atributos, a func¸˜ao position ( f ) calcula a posic¸˜ao do atri- buto f. No caso do acesso a atributos, o valor do atributo f ´e carregado para um registo. Por outro lado, na alterac¸˜ao de atributos, a express˜aoe ´e guardada no atributo f, como a seguir se ilustra:

E[o.f, T ] , (T.get(o) := r[position(f)], T ) E[o.f = e, T ] , (r[position(f)] := E[e, T ], T )

A func¸˜ao de traduc¸˜ao para a criac¸˜ao de objetos ´e a seguinte:

E[o = new C(), T ] , (H, T0) where H = λ :: Lock r :=new lock λ r0 :=new C[λ] r00:=newRO < r, r0 > r :=pack λ, r00as P C T0 = T ] (o : r0)

Quando ´e criado um objeto na linguagem MOOL ´e criado na linguagem MIL um trinco para proteger o tuplo referente `a classeC, um tuplo para guardar os valores dos atributos do objeto e um pacote que cont´em o tuplo e o trinco que protege o tuplo. Para al´em disso, ´e adicionado `a tabela o par(o:r0), pois ´e neste ponto que os objetos s˜ao atribu´ıdos a vari´aveis logo, ´e neste ponto, que se conhece qual o registo que fica associado ao objetoo.

As func¸˜oes de traduc¸˜ao para a chamada de m´etodos e a criac¸˜ao de novos fios de execuc¸˜ao s˜ao definidas da seguinte forma:

E[e; e0, T ] , (H, T ) = E[e, T ] ] E[e0, T ] E[o.m(e), T ] , (H, T ) where

H = createRegisters(e, T, om) jump spin }

E[o.f .m(e), T ] , (H, T ) where

H = createRegisters(e, T, of m) jump spin }

E[spawn o.m(e), T ] , (H, T ) where

H = createRegisters(e, T, om) fork spin

createRegisters(e, T, cont) , r := newRO < E[e, T ] > r0 :=newRO < r, cont >

r0 := pack < ~t > guarded by readOnly, r0as ∃e. < e, {r1 : e} > guarded by readOnly

Para auxiliar as func¸˜oes de traduc¸˜ao para a chamada de m´etodos e a criac¸˜ao de novos fios de execuc¸˜ao, foi criada a func¸˜ao createRegisters(e, T, cont), em que cont ´e o nome da continuac¸˜ao. Esta func¸˜ao tem dois objetivos: criar o tuplo com os argumentos dos m´etodos, que ´e guardado no registo r e criar a continuac¸˜ao dos m´etodos e guard´a-la no registo r0. O bloco de c´odigo correspondente `a etiquetaspinencontra-se representado na figura 7.2 No blocospin pode observar-se a t´ecnica padr˜ao para a aquisic¸˜ao de trincos, denominada por spinLock, na qual o processador tenta adquirir o trinco, utilizando o m´etodo da espera ativa. Neste caso, o processador n˜ao pode saltar para outro bloco at´e que o trinco seja fechado.

Na linguagem MOOL, as duas func¸˜oes de traduc¸˜ao para a chamada de m´etodos s˜ao idˆenticas. A ´unica diferenc¸a encontra-se no jump: numa das func¸˜oes ´e passado como continuac¸˜aoom, em queom´e o m´etodo da classe do tipo do objeto o e, na outra, ´e passado como continuac¸˜aoofm, em que ofm ´e o m´etodo da classe do tipo do objeto de f. Antes de efetuar estes saltos, os argumentos do m´etodo m s˜ao guardados num tuplo, atrav´es da func¸˜aocreateRegisters(e, T, cont). Por fim, em relac¸˜ao `a instruc¸˜aospawn, ´e feita uma substituic¸˜ao despawn por fork e, tal como na chamada aos m´etodos, os argumentos do m´etodoms˜ao guardados num tuplo.

spin :: {r2: ∃ e. <e, ∀ l1 :: Lock. {r1: e} requires {l1}> guarded by readOnly, r3: TClasseC} spin = { l , r1 := unpack r3 r4 := r1 [1] r5 := r1 [2] r5 := getSetLock r5 m, r6 := unpack r2 r1 := r6 [1] r6 := r6 [2] if r5 == 0 jump r6[l] jump spin }

Figura 7.2: Blocospin

`a definic¸˜ao de func¸˜oes para traduzir as express˜oes de controlo de fluxo. E[if (e) e0 else e00, T ] , (H, T0)where

H =if C jump then jump else } then = { E [e0] jump endIf } else = { E [e00] jump endIf } endIf = {

(C, T0) = E [e, T ]

E[while (e) e0] , (H, T0)where H =jump while }

while = {if jump continueW hile jump endW hile }

continueW hile = {E [e0, T ] jump while } endW hile = {

(C, T0) = E [e, T ]

E[if (o.f .m(e)) e0 else e00, T ] , E[if (E[o.f .m(e), T ]) e0 else e00, T ] E[while (o.f .m(e)) e0, T ] , E[while (E[o.f .m(e), T ]) e0, T ]

Em relac¸˜ao ao if (e) e0 else e00, em primeiro lugar ´e efetuado um if em que a condic¸˜ao ´e a express˜aoe e salta, no caso de a condic¸˜ao ser verdadeira, para a etiquetathen. Esta etiqueta cont´em a traduc¸˜ao da express˜ao e0 e um salto para o fim do if. Neste caso, o salto ´e feito para a etiquetaendIf, que termina o fluxo de controlo do if e continua com a execuc¸˜ao das express˜oes subsequentes ao if. Por fim, na etiqueta atual, ´e feito um salto

jump elsepara a etiquetaelse, no caso de a condic¸˜ao ser falsa. A etiquetaelsecont´em a traduc¸˜ao da express˜ao e00e um salto para o fim do if.

No que diz respeito ao while (e) e0, inicialmente, ´e feito um salto para a etiqueta

while, no qual ser´a verificada a condic¸˜ao do ciclo. No caso de ser verdadeira, ´e feito um salto para continueWhile e, no caso de ser falsa, ´e feito um salto para endWhile. A etiquetacontinueWhile vai apresentar a traduc¸˜ao da express˜ao e0 e um salto para while, para que se avance em mais uma iterac¸˜ao no ciclo. Por fim, a etiquetaendWhile termina o fluxo de controlo do ciclo e continua com as express˜oes subsequentes ao ciclowhile. Relativamente, `as express˜oes if (o.f .m(e)) e0else e00e while (o.f .m(e)) e0, as func¸˜oes de traduc¸˜ao chamam, recursivamente, a func¸˜ao de express˜oes sobre a express˜ao o.f .m(e). Nesta express˜ao, vai ser utilizada a func¸˜ao E sobre as condic¸˜oes (o.f .m(e)), de forma a resolver a chamada aos m´etodos.

Em relac¸˜ao `a operac¸˜ao booleana&&a func¸˜ao definida foi a seguinte:

O[e && e0, T ] , r := 1 if E[e, T ] == 0 jump andRight jump endAnd }

andRight = {

if E[e0, T ] ! = 0jump endAnd r := 0

jump endAnd }

endAnd = {

A primeira instruc¸˜ao a efetuar, quando se tem a operac¸˜ao booleana &&, ´e verificar se o lado esquerdo da express˜ao e ´e verdadeiro, no caso de ser verdadeiro, verificar se o lado direito, (andRight), ´e tamb´em verdadeiro. No caso de ambos serem verdadeiros, o resultado da operac¸˜ao ´e verdadeiro e o registo r vai conter o valor 0. No caso de uma das express˜oes ser falsa, o resultado da operac¸˜ao ´e falso e o registo r vai conter o valor 1. A etiqueta endAnd finaliza o fluxo de controlo de && e continua com as express˜oes subsequentes a&&.

Em relac¸˜ao `a operac¸˜ao booleana || a func¸˜ao definida foi a seguinte:

O[e || e0, T ] , r := 0 if E[e, T ] == 0 jump orEnd jump orRight }

orRight = {

if E[e0, T ] == 0jump orEnd r := 1

jump orEnd }

A primeira instruc¸˜ao a efetuar, quando se tem a operac¸˜ao booleana ||, ´e verificar se o lado esquerdo da express˜ao e ´e verdadeiro. No caso de ser falso, vamos verificar se o lado direito (orRight) ´e verdadeiro. Se um dos lados for verdadeiro, o resultado da operac¸˜ao ´e verdadeiro e o registo r vai conter o valor 0. Se ambas as express˜oes forem falsas, ent˜ao o resultado da operac¸˜ao ´e falso e o registo r vai conter o valor 1. A etiquetaorEndfinaliza o fluxo de controlo de || e continua a execuc¸˜ao das express˜oes subsequentes a ||.

Por fim, no que diz respeito `a operac¸˜ao booleana !, inicialmente, verificamos se a express˜ao e ´e verdadeira. No caso de ser verdadeira, ´e efetuado um salto para a etiqueta

notTrue. Esta etiqueta adiciona o valor 1 ao registo r, de forma a indicar que o resultado de !e ´e falso. No caso da express˜ao e ser falsa, ´e efetuado um salto para a etiquetanotFalse. Esta etiqueta adiciona o valor 0 ao registo r, de forma a indicar que o resultado de !e ´e verdadeiro. No final, quer na etiquetanotTrue, quer na etiqueta notFalse, ´e adicionado um salto para o fim da operac¸˜ao !. A etiquetaendNotfinaliza o fluxo de controlo de ! e continua a execuc¸˜ao das express˜oes subsequentes a !. A func¸˜ao de traduc¸˜ao ´e:

O[!e, T ] , if E[e, T ] == 0 jump notT rue jump notF alse }

notT rue = { r := 1 jump endN ot } notF alse = { r := 0 jump endN ot } endN ot = {

7.2

Exemplo

Para ilustrar como se efetua, passo a passo, a traduc¸˜ao de MOOL em MIL, analisemos as figuras 6.2 e 6.3.

O primeiro passo ´e construir a etiquetamain, pois este ´e o ponto de entrada da execuc¸˜ao dos programas MIL. A assinatura do bloco main ser´a: main :: {}, j´a que o m´etodomain

n˜ao cont´em parˆametros. Inicialmente, no bloco de c´odigo main ´e criada a continuac¸˜ao do bloco mainMain, ponto de entrada do programa MOOL. Seguidamente, ´e criado um

novo trinco e um novo tuplo, que cont´em os atributos da classe Main, efetuando um salto para o m´etodo main correspondente `a classe Main, de forma a iniciar a execuc¸˜ao do programa MOOL. Como a classeMain n˜ao cont´em atributos, ´e criado um tuplo vazio (<>guarded by l1). Este processo pode ser assim ilustrado:

main :: {} main = {

r1 := newRO <>

r2 := newRO <r1, doneLabel>

r2 := pack <> guarded by readOnly, r2 as ∃e. <e, {r1: e}> guarded by readOnly

l1 :: Lock

r3 := new lock l1

r4 := new Main[l1] jump mainMain[l1]

}

O pr´oximo passo ´e traduzir todas as classes do programa MOOL, ou seja, as clas- sesMaine Fatorial. O c´odigo correspondente a estas classes em MIL ´e o seguinte:

type Main = ∀ l1 :: Lock. <> guarded by l1

type PMain = ∃ b :: Lock. <<> guarded by b, lock b> guarded by readOnly type Fatorial = ∀ l2 :: Lock. <int, int , int , int , int> guarded by l2

type PFatorial = ∃ b :: Lock. <<int, int, int , int , int> guarded by b, lock b> guarded by readOnly

O primeiro e o terceiro identificadores representam o conjunto de atributos das classes e o segundo e quarto representam o tipo das classes, j´a que estes contˆem o tuplo com atributos da classe e o trinco que protege o tuplo.

A criac¸˜ao de um novo objeto na linha 3 da figura 6.3 corresponde, em MIL, `a criac¸˜ao de um novo trinco, um novo tuplo, que cont´em os atributos do objeto, e um pacote, que cont´em o tuplo e o trinco que protege o tuplo, como abaixo se ilustra:

l2 :: Lock

r3 := new lock l2

r4 := new Fatorial[l2 ]

r5 := newRO <r4, r3>

r5 := pack l2, r5 as PFatorial

Na chamada a m´etodos (linha 4 da figura 6.3) ´e criado um tuplo, que cont´em os ar- gumentos passados aos m´etodos, e um pacote, que tem como objetivo indicar ao bloco

inicializar para onde este deve continuar. Para al´em disso, ´e efetuado um salto para o bloco inicializar . O c´odigo correspondente em MIL ´e o seguinte:

r1 := newRO <5>

r2 := newRO <r1, main continuation>

r2 := pack <int> guarded by readOnly, r2 as ∃e. <e, {r1: e}> guarded by readOnly jump inicializar [ l2 ]

A assinatura do m´etodo inicializar cont´em um tuplo com um inteiro (registo r1), o inteiro respetivo ao parˆametro do m´etodo da linha 4 da figura 6.2. Para al´em disso, a assinatura cont´em: o pacote que indica para onde o m´etodo inicializar deve continuar (registor2), o tuplo que cont´em os atributos da classe Fatorial (registor4), o trinco que protege o tuplo (registo r3) e o pacote que cont´em o tuplo (registor5). Como o m´etodo

inicializar altera atributos da classe Fatorial, o bloco requer que o trinco que protege o tuplo de atributos esteja fechado (requires {l2}). A assinatura fica da seguinte forma:

inicializar :: ∀ l2 :: Lock. {r1: <int> guarded by readOnly,

r2: ∃ e. <e, {r1: e}>guarded by readOnly,

r3: lock l2 , r4: Fatorial [ l2 ], r5: PFatorial} requires {l2}

O corpo do m´etodo inicializar inicializa os atributos da classe Fatorial (linhas 5–7 da figura 6.2). Primeiramente, ´e efetuada a atribuic¸˜ao do parˆametrovao atributovalor. Neste

Documentos relacionados