Академический Документы
Профессиональный Документы
Культура Документы
Florianpolis SC
2007/2
Giovani Pieri
Orientador:
Luiz Fernando Bier Melgarejo
Florianpolis SC
2007/2
Projeto e implementao de uma linguagem de
programao
Trabalho de concluso de curso apresentado como parte dos requisitos para obteno do grau
de Bacharel em Cincia da Computao.
Banca Examinadora
Lista de Figuras
1 Introduo 10
2.2.2 Concorrncia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3.4 Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3 Implementao do Interpretador 40
3.3.1 O Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5 Implementao do compilador 68
5.1 Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Referncias Bibliogrficas 71
Lista de Figuras
3.1 Ilustrando criao de listas. A lista nas variveis lista e listaEquivalente so iguais. 43
1 Introduo
Atualmente existem diversas linguagens de programao, cada uma com suas particula-
ridades, caractersticas, vantagens e desvantagens. Entretanto, estas linguagens possuem uma
sintaxe e semntica relativamente complexa. Alm disso alguns conceitos tal como paralelismo,
so tratados marginalmente tornando difcil e muitas vezes no-intuitivo trat-los.
Com isso em mente, existe uma brecha na qual poucas linguagens se encaixam surgindo a
necessidade de uma linguagem simples que seja semanticamente e sintaticamente simples, de
forma que se torne o mais natural possvel. Entretanto sem impor limitaes, sem dificultar o
desenvolvimento por parte de programadores experientes. Com esta proposta, uma linguagem
de programao ser criada.
Esta linguagem dever suportar um modelo de paralelismo de alto nvel nativamente, dever
ter sintaxe e semntica simples mas ser poderosa de modo a no limitar os desenvolvedores. As
demais caractersticas e construes da linguagem sero estudadas e debatidas sempre levando
em conta esta filosofia.
11
Telis uma linguagem madura, desenvolvida no laboratrio Edugraf, que vem sendo de-
senvolvida desde 1998. Ela fruto do estudo e desenvolvimento de vrias outras linguagens
anteriormente desenvolvidas pelo mesmo laboratrio. O objetivo desta linguagem ser sin-
ttica e semanticamente simples de tal forma que mesmo programadores iniciantes consigam
expressar-se de forma natural, mas ao mesmo tempo expor conceitos avanados como parale-
lismo, comunicao via Internet (sistemas distribudos) e princpios de orientao a objetos.
Telis vem sendo utilizado diariamente durante anos por alunos da Universidade Federal
de Santa Catarina nos cursos de Cincia da Computao e Engenharia de Automao e Siste-
mas. Por este motivo, as idia e conceitos desta linguagem sero utilizadas como base para a
linguagem alvo.
Telis possui uma sintaxe bastante simples, descrita pela gramtica EBNF (Extended Backus
Normal Form) mostrada na listagem 2.1.
programa : : = t e x t o l i s t a D e A t o r e s listaDeModelosOuMoldes i n c l u i r A p l i q u e
giria ::= ( palavra | lista )
l i s t a ::= "[" ( palavra | l i s t a ) "]"
listaDeAtores ::= "[" ( identificador ) "]"
listaDeModelosOuMoldes : : = " [ " ( chamadaParaInclusaoDeModeloOuMolde ) " ] "
chamadaParaInclusaoDeModeloOuMolde : : = l i s t a t e x t o l i s t a
primitivaDeInclusaoDeModeloOuMolde
p r i m i t i v a D e I n c l u s a o D e M o d e l o O u M o l d e : : = <ID>
palavra ::= atribuicao | ( identificador | identificadorValorAtual |
13
numero | o p e r a d o r | a l c a n c e | t e x t o | o p e r a d o r P o n t o | b o o l e a n o
)
a t r i b u i c a o : : = ( <ID> ( <ASSOCIAR> ) )
i d e n t i f i c a d o r : : = <ID>
i n c l u i r A p l i q u e : : = <INCLUIR_APLIQUE>
i d e n t i f i c a d o r V a l o r A t u a l : : = ( <ID_VALORATUAL> )
numero : : = <NUMERO>
o p e r a d o r P o n t o : : = " . " <ID>
o p e r a d o r : : = ( " + " | "" | " " | " / " | " ^ " | "\\" | " <" | " >" | " <=" |
" >=" | " < >" | " = " | <ASSOCIAR> )
t e x t o : : = <TEXTO>
b o o l e a n o : : = <BOOLEANO>
a l c a n c e : : = <ALCANCE>
Como possvel verificar um programa Telis composto basicamente por textos, nmeros,
smbolos e listas. Todo programa em Telis possui um texto com o nome do aplique, uma lista
contendo o nome dos modelos que sero instanciados, uma segunda lista contendo em seu
interior as definies de modelos e moldes, e por ltimo o smbolo incluirAplique responsvel
pela criao de Apliques. Toda esta definio de um programa Telis escondida do programador
pelo Ambiente Telis, um ambiente de desenvolvimento desenvolvido tambm pelo laboratrio
Edugraf para facilitar (ainda mais) a programao em Telis.
Tambm possvel ver que praticamente qualquer cdigo (lista) sintaticamente vlido,
muitas poucas restries so impostas pela gramtica Telis.
Quando o interpretador Telis encontra o operador + ele o executa. Para isso, dois parme-
tros da pilha so consumidos, somados e o resultado empilhado.
Smbolos em Telis so uma cadeia de caracteres separados por espaos. De forma anloga
aos operadores, sempre que a mquina Telis encontra um smbolo ela tenta execut-lo, caso no
consiga um erro de tempo de execuo gerado.
A mquina Telis possui um conjunto de smbolos, inerente mquina, sendo cada um dos
elementos denominado agenda primitiva e cada uma destas agendas primitivas possui associada
a si um determinado comportamento. Toda vez que um smbolo associado uma determinada
agenda encontrado o comportamento relacionado a esta agenda executado. Este comporta-
mento pode ser afetado por parmetros, que so obtidos da pilha e possveis resultados sero
empilhados. As primitivas so utilizadas para modelar as estruturas de controle de fluxo e repe-
tio, operaes sobre textos, listas e nmeros entre outras funcionalidades.
Listas desempenham um papel muito importante em Telis. Alm de poderem ser utilizadas
como estruturas de dados para o armazenamento e processamento de informaes, elas podem
agrupar um conjunto de instrues. Telis se aproveita deste fato para modelar, por exemplo, ex-
presses condicionais. Expresses condicionais recebem como parmetro uma lista contendo os
comandos que devero ser realizados dependendo do valor de um segundo parmetro booleano,
como mostrado na listagem 2.3.
verdadeiro
15
[
10 m o s t r a r
]
seVerdade
No cdigo da listagem 2.3, um valor booleano e uma lista contendo comandos so em-
pilhados. A primitiva seVerdade recebe estes dois parmetros e caso o valor booleano seja
verdadeiro, o que realmente ocorre neste caso, a lista de comandos executada. Neste caso, o
nmero 10 mostrado na tela.
Durante a execuo do cdigo mostrado na listagem 2.4, quando a mquina Telis se de-
para com o smbolo umaVarivel, olhado um token a frente e caso este token seja um asso-
ciar, o que realmente ocorre, o valor que est na pilha associado ao smbolo atual, no caso
umaVarivel. Para empilhar o valor anteriormente atribudo uma varivel, basta executar o
smbolo ao qual a varivel foi associada.
2.2.2 Concorrncia
Telis adota uma abordagem baseada em Atores. Atores so parecidos com processos no
16
Telis adotou uma abordagem distinta. Um ator no necessita nenhum tipo de informao
a respeito de quem receber a mensagem. A mensagem enviada a todos os outros atores que
tenham se cadastrado para receb-la.
Uma tupla uma seqncia finita de objetos, cada um de um determinado tipo. Uma tupla
em Telis representada por uma lista, e a base para o sistema de troca de mensagens do Telis.
Mensagens em Telis so chamadas de estmulos ou eventos. Ao enviar uma mensagem para um
ou mais atores diz-se que um estmulo foi emitido. Ao recepcionar este estmulo diz-se que o
estmulo foi tratado.
So necessrios dois mecanismos bsicos para que atores possam se comunicar: eles devem
poder emitir estmulos e poder se cadastrar com o intuito de receber um determinado estmulo.
Logo, duas primitivas so utilizadas para realizarem a comunicao entre dois atores distintos:
dizer e seDito.
Filtros so tuplas. Diz-se que um filtro casa com um estmulo se as condies abaixo forem
satisfeitas:
2. Para todo elemento do estmulo, o elemento de mesma posio no filtro deve: ser igual
17
ou indicar o tipo do elemento do estmulo atravs dos smbolos texto, nmero ou lista.
De maneira similar o ator Telis executa os comandos at que um tratador cujo filtro case
com um estmulo que tenha sido emitido. Neste momento, o fluxo normal de execuo in-
terrompido, empilhado o estmulo que est sendo tratado e as instrues anexadas ao tratador
pela execuo da primitiva seDito executado. Aps o trmino da execuo do tratador, a pilha
restaurada ao estado inicial, isto , os elementos contidos na pilha sero iguais ao que estava
na mesma antes do estmulo ser iniciado e o fluxo de execuo normal retomado.
Quando um ator criado ele executa a agenda de nome iniciar. Agendas so anlogos
mtodos em linguagens orientadas a objetos. Diferentemente de agendas primitivas, que
so providas diretamente pela linguagem, agendas contm cdigo definido pelo programador.
Agendas so executadas quando o smbolo associado ao nome da agenda for executado pelo
interpretador Telis.
Para se criar um ator necessrio uma espcie de fbrica de atores contendo a definio dos
mesmos, isto , a definio das agendas que ele possuir. Esta fbrica de atores chamada de
modelo, e funciona de maneira similar a classes em linguagens orientada a objetos. Uma vez
definido um modelo, e conseqentemente suas agendas, um ator pode ser instanciado. Para se
instanciar um ator a partir de um modelo basta executar o smbolo correspondente ao nome do
modelo que fora definido. Neste momento, o interpretador Telis toma as seguintes aes:
1. Cria um novo ator. Este ator possui acesso a todas as agendas definidas pelo modelo.
18
2. Copia o topo da pilha do ator que est criando o novo ator para a pilha do ator recm
criado.
4. Uma referncia ao ator criado empilhada no ator que criou o novo ator.
A referncia a um ator pode ser utilizada posteriormente para realizar comunicao di-
reta com o ator, isto , enviar uma mensagem direcionada pedindo que o mesmo execute uma
agenda. Todo ator possui uma identidade, e h garantia que esta identidade nica. possvel
acessar a prpria identidade atravs da primitiva obterIdentidade, e obter uma referncia para
si prprio atravs da primitiva euMesmo.
Telis permite uma noo de herana com a utilizao de moldes. A herana de Telis
diferente da herana em linguagens como Java e C++. O intuito fornecer um mecanismo
simples de ser entendido e explicado, embora seja menos flexvel. Isto ocorre porque o ponto
onde a superclasse ser chamada pr-definida ao invs de ser indicada pelo programador.
Classes abstratas em Telis so denominadas moldes. Diz-se que um molde molda um mo-
delo, e este por sua vez moldado pelo molde. Um modelo pode ser moldado por zero ou mais
moldes, como possvel que um modelo seja moldado por mais de um molde h em Telis a
noo de herana mltipla. Alm disso, um molde tambm pode ser moldado por zero ou mais
moldes. Um modelo no pode ser utilizado como molde.
2. Todos os modelos devem ser nodos folha, isto , seu grau de emisso1 igual a 0.
1O grau de emisso de um vrtice v corresponde ao nmero de arestas que partem de v.
19
Os moldes definem agendas, de forma anloga a modelos. Estas agendas podem ser utili-
zadas por quem for moldado por este molde. Caso um modelo ou molde defina uma agenda
com mesmo nome de uma agenda definida em um dos moldes que o est moldando, este ir
estender a agenda do molde. Do ponto de vista do programador, o cdigo definido pelo modelo
anexado ao fim das agendas do molde cujos nomes sejam idnticos.
importante notar que os moldes podem referenciar agendas inexistentes no molde. Isto
til para realizar implementao de alguns padres de projetos comuns tais como Template
Method. Como pode ser visto no diagrama mostrado na figura 2.3, a descrio geral de um
algoritmo definido em uma superclasse em um mtodo template, devendo este delegar tarefas
para mtodos abstratos. Cada subclasse deve preencher as lacunas no algoritmo com os detalhes
pertinentes. O diagrama de classes mostrado na figura .
Em Telis, agendas abstratas no so explicitamente definidas mas podem ento ser simula-
das atravs deste mecanismo de delegao para agendas inexistentes.
Por definio, durante a invocao de uma agenda, as agendas definidas nos moldes so
executados anteriormente as agendas de quem est sendo moldado. Dado um grafo de herana
G e um modelo M pertencente a este grafo, definido o subgrafo X composto pelos vrtices
20
pertencentes ao fecho transitivo inverso2 de M e toda aresta definida entre dois vrtices perten-
centes a este fecho transitivo inverso. Isto :
V = { x | x FTI(G, M)}, onde FTI(G, M) o conjunto de vrtices do fecho transitivo
inverso do vrtice M do grafo G.
A = { (x, y) | (x, y) E(G) }, onde E(G) o conjunto de arestas de G.
Outro ponto importante que durante a invocao da agenda de um modelo, todas as agen-
das de mesmo nome dos moldes contidos no fecho transitivo inverso do modelo so invocadas
uma e somente uma vez.
A sintaxe da comunicao direta foi inspirada em linguagens como Java e Ruby nos quais
mensagens so enviadas a objetos utilizando-se a notao do ponto, como mostrado na listagem
2.5
p u b l i c c l a s s Xpto {
p u b l i c v o i d metodo ( ) {
...
}
}
p u b l i c c l a s s Main {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
Xpto x p t o = new Xpto ( ) ;
x p t o . metodo ( ) ;
}
}
Permitir que um ator pea para que outro execute uma de suas agendas e retorne o resultado
pode ser bastante til, entretanto permitir que ele execute qualquer outra agenda no uma
boa pratica. Grande parte das linguagens possuem um sistema de restrio de visibilidade de
mtodos. Por exemplo Java define quatro nveis de visibilidade: public, protected, package,
private. Em Telis tambm existe nveis de visibilidade das agendas, dois mais especificamente:
pblico e privado. Agendas pblicas podem ser alvo de uma comunicao direta, enquanto
agendas privadas no. Caso tente-se fazer comunicao direta com uma agenda privada gerado
23
um erro em tempo de execuo. A diferenciao entre agendas pblicas e privadas diz respeito
ao nome. Foi convencionado que agendas cujo nome inicia com so privadas, qualquer outra
agenda pblica.
Telis uma linguagem dinamicamente tipada. Devido a isto, nenhum tipo de verificao
quanto a existncia de uma agenda realizada em tempo de compilao, sendo a validade da
comunicao direta verificada apenas em tempo de execuo. Devido a isto, o polimorfismo
algo natural e inerente. No necessrio, para utilizar polimorfismo, herana, interfaces ou casts
ao contrrio de linguagens estaticamente tipadas. Para utilizar polimorfismo em Telis basta
que os atores (e seus modelos) possuam o subconjunto das agendas utilizadas definidas. Ruby,
Python e outras linguagens dinamicamente tipadas possuem o mesmo comportamento. Este tipo
de polimorfismo denominado duck typing. Este termo tem origens na frase If it quacks like a
duck, walks like a duck, it must be a duck!. A origem deste termo desconhecida mas suspeita-
se que foi cunhada por Alex Martelli em uma mensagem ao newsgroup comp.lang.python.
24
Algumas linguagens conhecidas tambm implementam escopo dinmico, dentre elas pode-
se citar Perl e Common Lisp.
Para descobrir a quem uma varivel deve ser amarrada, necessrio realizar uma anlise da
pilha de execuo. A primeira varivel encontrada com mesmo nome analisando o stack-trace,
isto , as variveis associadas na agenda na ordem em que as agendas iro retornar.
O cdigo Telis na listagem 2.8 ilustra um exemplo onde escopo dinmico difere do escopo
esttico. Neste cdigo, apenas um ator do modelo ModeloExemplo instanciado. Sua agenda
iniciar invoca primeiro a agenda1 em seguida a agenda2. A agenda1 associa varivel x o
valor 10 e invoca a agenda mostrarX. A agenda mostrarX neste momento acessa a varivel
associada pela agenda agenda1, j que foi esta quem a invocou, mostrando na tela o valor 10.
A agenda2 funciona do mesmo modo. Primeiro associa varivel x o valor 20, em seguida
invoca a agenda mostrarX. Mas desta vez a agenda mostrarX ir acessar a varivel associada
pela agenda2 que 20, conseqentemente imprimindo o valor 20 na tela. Caso uma linguagem
com escopo esttico fosse utilizado neste caso, um erro em tempo de execuo ou compilao
ocorreria j que a varivel x no est definida lexicamente. Apenas em tempo de execuo
possvel encontrar esta varivel.
" ExemploEscopo " [ ModeloExemplo ]
[
[ ] " ModeloExemplo "
[
" iniciar "
[
agenda1
agenda2
]
incluirAgenda
incluirAgenda
]
incluirModelo
]
incluirAplique
A primitiva associar alm de associar um valor a uma varivel, cria uma nova varivel den-
tro do escopo da agenda atual caso esta varivel no consiga ser amarrada a nenhuma outra.
Entretanto com este comportamento do associar, pode-se tornar incomodo por exemplo para as-
sociar variveis em agendas recursivas. Como as variveis possuem o mesmo nome, a primeira
chamada a agenda recursiva cria uma varivel no escopo desta agenda. A partir da todas as
variveis de todas as agendas chamadas recursivamente acabam sendo amarradas a agenda da
primeira chamada fazendo com que as agendas compartilhem indesejavelmente a varivel. Para
resolver este problema, existe a primitiva declarar. Esta primitiva cria uma varivel na agenda
atual, sem tentar amarr-la a uma varivel. Desta forma possvel utilizar agendas recursivas
sem problemas. O cdigo da listagem 2.9 mostra o exemplo do fatorial escrito recursivamente.
" Fatorial " [ Fatorial ]
[
[] " Fatorial "
[
" iniciar "
[
20 f a t o r i a l
mostrar
]
incluirAgenda
entoSeno
]
incluirAgenda
]
incluirModelo
]
incluirAplique
nome
tamanho
definio de modelos
Apliques podem ser definidos atravs da prpria linguagem, como mostrado no cdigo da
listagem 2.6 na pgina 22. Mas existe uma representao alternativa tambm utilizada que
se baseia em arquivos xml (extensible mark-up language). A definio deste xml no ser
mostrado ou discutido, mas vale comentar que vrias transformaes so realizadas sobre este
xml. Desde a gerao do cdigo em linguagem Telis pura at gerao de pginas html (hyper-
text mark-up language) descrevendo o cdigo Telis.
28
A nova linguagem ser baseada em Telis. Telis foi utilizado por muito tempo, por muitos
programadores e provou ser uma linguagem simples e poderosa. Os conceitos na linguagem
permitem que sejam escritos programas bsicos, inclusive sem o uso de variveis, at programas
complexos, concorrentes e orientados a objetos.
Entretanto existem alguns pontos em Telis aos quais no foi dado muita ateno, algumas
excees que podem ser resolvidas ou funcionalidades e conceitos que ainda no foram im-
plementadas. Ento ser realizada uma anlise destes pontos nos quais Telis deixa a desejar e
propor alteraes semnticas e/ou sintticas com o objetivo de melhorar a linguagem.
O fragmento de cdigo mostrado na listagem 2.10 ilustra uma situao na qual o programa-
dor Telis normalmente espera um comportamento mas ocorre algo um tanto quanto inesperado.
O cdigo, quando lido de forma simplista, se comportaria da seguinte maneira: empilha o
20, variavel e Um, em seguida concatena variavel e Um resultando em variavelUm.
Agora a variavelUm seria associada ao nmero 20. Este pensamento, apesar de parecer coerente
no o que ocorre. Esta linha de raciocnio ignora o comportamento excepcional do associar.
O correto seria o seguinte: empilha o 20, variavel e Um, agora o smbolo concatenar se-
guido de um associar, logo o concatenar o nome da varivel e no uma agenda primitiva como
esperado. Conseqentemente, a varivel concatenar associada com o texto Um
29
Alm disso, este comportamento do associar causa um impacto na gramtica de Telis (mos-
trada na listagem 2.1 na pgina 12). Telis uma gramtica livre de contexto, mais especi-
ficamente uma gramtica LL. Gramticas LL so um subconjunto das linguagens livres de
contexto na qual as seguintes restries so impostas:
Se < X >< V 1 > | < V 2 > |...| < V n >, ento FIRST (Vi ) FIRST (V j ) = 0/
T
FIRST(X) definido como o conjunto de todos os terminais que podem aparecer no incio
de uma sentena derivada a partir de um no terminal X. FOLLOW(Z) definido como a unio
do FIRST(V) para todas as produes na forma: X ZV .
Caso exista um parser LL que com um nmero k de tokens de lookahead 3 possa reconhecer
todas as palavras geradas por uma gramtica sem realizar backtracking, ento diz-se que esta
gramtica LL(k).
As restries feitas sobre gramticas BNF tem o objetivo de simplificar o parsing. Exis-
tem vrios algoritmos para realizar o reconhecimento de sentenas de forma eficiente e quanto
menor o valor de k da gramtica, mais eficiente este algoritmo se torna.
A produo palavra na gramtica do Telis, torna a gramtica do Telis uma gramtica LL(2).
Pois h um conflito entre as produes atribuicao e identificador. Se a gramtica for alterada e a
produo atribuicao deixar de existir a gramtica poder ser reduzido a uma gramtica LL(1).
Para resolver o problema e tentar tornar o associar uma primitiva normal, como outra qual-
quer, foi proposto que continue se utilizando um smbolo para indicar o nome de uma varivel,
entretanto este simbolo dever ser buscado na pilha. Em Telis, smbolos no podem ir para a
pilha de modo simples pois quando o interpretador Telis os encontram ele imediatamente exe-
cuta. A nica forma de fazer isso no Telis antigo colocando o smbolo dentro de uma lista e
em seguida retir-lo. A proposta para facilitar o empilhamento de smbolos utilizar um ope-
rador, que pode ser utilizado em smbolos e quando este operador executado ele empilha o
3 Lookahead define quantos dados de entradas sero levados em considerao em um passo do algoritmo. No
caso de parsers, o nmero de tokens que sero levados em conta para realizar uma transio da mquina de reco-
nhecimento.
30
smbolo que ele est marcando, de forma similar a notao de ponto. Foi proposta tambm a
utilizao do caracter $ para realizar tal operao. O fragmento de cdigo mostrado na listagem
2.11 ilustra a associao de variveis utilizando-se este operador. No exemplo, o smbolo no-
meDaVarivel marcado com o operador $ e conseqentemente no ser executado, mas sim
empilhado e consumido pelo associar da pilha.
20 $ n o m e D a V a r i v e l a s s o c i a r
Essa abordagem, apesar de tornar o cdigo um pouco menos legvel trs importantes van-
tagens. A utilizao deste operador obriga o programador a explicitar quando o smbolo que
precede o associar deve ser executado ou realmente o nome da varivel. Outro ponto o
impacto que trs a gramtica, tornando-a LL(1) ao invs de LL(2), o que trs vantagens j
que parsers para gramticas LL(1) so muito mais otimizadas e simples do que gramticas LL
com um nmero maior de lookaheads. Alm disso, com smbolos sendo facilmente empilhados
os torna mais propensos a usos tais como para enumeraes e definio de nomes no s de
variveis mas de agendas, modelos e moldes tambm tornando Telis mais padronizada.
Esta no-diferenciao pode vir a ser til, permitindo a construo dinmica de comandos
por exemplo. Entretanto, traz alguns problemas, principalmente quando utilizadas em conjunto
com o operador valor atual (@) de Telis.
O operador valor atual utilizado dentro de listas. Sua funo realizar a avaliao de um
smbolo, colocando no lugar do mesmo o que restou no topo da pilha aps esta avaliao ocorrer.
importante salientar que a pilha limpa logo aps a avaliao ser realizada, isto , aps
cada avaliao utilizando-se o operador valor atual a pilha restaurada para o estado anterior,
na iminncia da lista ser empilhada. Os smbolo so resolvidos no escopo atual, e nenhuma
restrio posta em relao ao que este smbolo est atrelado. As duas nicas restries so:
No h passagem de parmetros;
O fragmento de cdigo mostrado na listagem 2.12 mostra como o operador valor atual
pode ser utilizado no Telis, e como obter o mesmo resultado sem utiliz-lo. Primeiramente,
uma varivel criada e um valor ela associado, logo em seguida a lista empilhada mas
como esta lista possui um operador valor atual, o smbolo ser substitudo pela avaliao do
mesmo. Como o smbolo a varivel previamente criada, o valor desta varivel ser colocada
no lugar do operador e do smbolo, resultando na lista [ valor da varivel ] na pilha, que
posteriormente mostrada na tela. Na prxima linha, mostrada uma forma alternativa de
obter o mesmo resultado sem utilizar o operador valor atual.
" v a l o r da v a r i v e l " a V a r i a v e l a s s o c i a r
[ @aVariavel ] m o s t r a r
aVariavel 1 gerarLista mostrar
Como no existe nenhum tipo de distino sinttica entre blocos de comandos e listas, deve
ser realizada uma analise semntica para descobrir o que uma lista representa e quais aes
devero ser tomadas. Este tipo de anlise complexa de ser feita devido a prpria estrutura de
Telis, no momento em que a lista vai para a pilha no h nenhum indcio do objetivo desta pilha
estar sendo empilhada. Este conflito de comportamento causado pelo operador valor atual foi
resolvido no interpretador Telis utilizando-se um algoritmo baseado em backtrack. Assume-
se que uma lista uma lista de dados, caso mais tarde se descubra que na realidade um
bloco de comandos o backtrack realizado e o valor correto da lista utilizado. Esta abordagem
funciona para grande parte dos casos, entretanto causa alguns problemas. Como utilizada uma
heurstica para decidir qual das duas abordagens deve ser tomada h uma chance de se errar e
caso se erre h a possibilidade de que um valor que no deveria ser avaliado seja podendo
resultando em loops infinitos e alguns outros comportamentos inesperados.
Para resolver este problema foi proposta a distino sinttica entre listas de dados e blocos
de comandos. Na nova linguagem que est sendo desenvolvida, as listas de dados sero deli-
32
mitadas por colchetes pareados, da mesma forma que listas em Telis. Blocos por sua vez sero
representados atravs de chaves, tambm pareadas.
A listagem 2.13 contm um fragmento de cdigo da nova linguagem que mostra como listas
de dados e comandos sero representados.
[ 0 4 ] g e r a r A l e a t r i o umValor a s s o c i a r
umValor 2 >=
{
" v a l o r m a i o r ou i g u a l a 2" m o s t r a r
}
{
" v a l o r menor que 2" m o s t r a r
}
entoSeno
Alm da resoluo de problemas relativo ao operador de valor atual, a distino entre es-
truturas de dados e blocos de comandos forte em outras linguagens. Conseqentemente a
adoo desta distino na nova linguagem favorece a transio para estas outras linguagens e
vice-versa.
Como foi exposto anteriormente, o escopo das variveis em Telis so do tipo dinmico.
Apesar de relativamente simples, alguns de seus efeitos no so muito intuitivos quando com-
parados ao escopo esttico (lxico). O fato da avaliao de uma varivel depender do contexto
em que uma chamada a agenda for feita pode levar a erros difceis de detectar. Por este motivo,
resolveu-se utilizar o sistema de escopo de varivel esttico para a nova linguagem.
Em escopos estticos a definio de qual varivel est sendo referenciada pode ser realizado
em tempo de compilao, diferentemente do escopo dinmico onde s em tempo de execuo
isto ser decidido.
Em uma linguagem com escopo esttico, uma varivel A declarada em um bloco B aces-
svel a um bloco C declarados dentro de B aps a declarao de A. Note que caso exista um
bloco D declarado dentro de C, D tambm poder acessar a varivel A. Caso B e C possuam
duas variveis diferentes de mesmo nome, o bloco D ir utilizar a varivel C pois est a que
est lexicamente mais prxima a D.
33
Em Telis o escopo dinmico facilita que blocos de comandos sejam elementos de primeira
classe. Como a varivel amarrada no momento em que executada no h problemas quanto
as variveis, elas sero amarradas quando o bloco for executado e fim. J com escopo esttico
no funciona deste modo. Com escopo esttico a varivel amarrada no momento em que o
bloco definido. Se o bloco for executado imediatamente, no ocorrem problemas. Entretanto,
caso o bloco seja passado para uma outra agenda ou for retornado, o escopo no qual o bloco
foi definido deve ser mantido para que as variveis definidas no bloco possam se referenciar ao
ambiente no qual se encontravam quando necessrio.
Closures so fragmentos de cdigo que mantm uma referncia ao ambiente no qual foram
criados. Desta forma, o retorno de um mtodo no necessariamente implica na destruio das
variveis locais deste j que um closure pode estar referenciando estas variveis locais. Isto
torna a pilha de execuo no mais uma pilha, mas sim uma rvore.
Closures so muito utilizados em linguagens como Ruby, Python, Lisp, entre outras. Alm
disso, closures provm uma forma elegante para a implementao de alguns padres de projetos
tais como Visitantes. O cdigo da listagem 2.14 mostra um cdigo escrito em Ruby que utiliza
um visitante para calcular o somatrio de uma lista de valores. Ao final da execuo, o valor 45
mostrado na tela.
valores = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
somatorio = 0
v a l o r e s . e a c h do | x |
somatorio = somatorio + x
end
puts somatorio
H linguagens nas quais no existem closures, apesar do escopo esttico, como Java4 . H
quem confunda as classes annimas de Java com closures, entretanto no so iguais. Classes
annimas, apesar de poderem ser utilizadas para algumas coisas da mesma forma que closures,
no so closures completos pois no mantm uma cpia para o contexto no qual fora criada.
4 Java ainda no possui closures, h um grupo de especialistas estudando a implementao, sintaxe e semntica
de closures na linguagem. Estima-se que closures sero incorporados a linguagens na verso 7 do Java.
34
Java permite apenas que variveis finais do escopo no qual a classe foi criada sejam acessadas,
permitindo que uma cpia da varivel externa seja feita para a classe annima.
Para evitar que este problema ocorra, h uma restrio em quem pode executar os closures.
Apenas o ator que criou um closure poder execut-lo. Desta forma, a condio de corrida ser
evitada, em contrapartida o potencial de utilizao de closures ser um pouco reduzido.
2.3.4 Objetos
Em Telis a unidade de execuo bsica um ator. Todo ator, por definio, roda indepen-
dentemente de qualquer outro ator, isto , possui uma linha de execuo prpria. Alm disso,
ele s destrudo quando executa a primitiva suicidar. Mesmo que termine sua agenda iniciar,
no pode simplesmente ser destrudo j que ele pode receber estmulos e ter de agir de acordo
com estes. Aps o trmino de execuo da agenda iniciar diz-se que ator entra em um estado
de hibernao, do qual pode ser acordado para tratar algum estmulo.
Atores uma boa forma de organizar o programa, mas no sempre isso que se deseja.
Muitas vezes no se quer uma entidade autnoma para resolver uma tarefa, mas sim algo mais
simples. Neste sentido, se prope o conceito de objeto.
A nova linguagem dever possuir o conceito de objeto. Objetos assim como atores so
definidos atravs de modelos que sero chamados de modelos de objetos. Modelos de objetos
so exatamente iguais modelos de atores, com a exceo de que quando instanciados no
criam um ator, mas sim um objeto. Um modelo de objetos, a exemplo de modelos de atores,
podero ser moldados por moldes e possuem uma coleo de agendas.
direta, ao contrrio dos estmulos dizer, so inerentemente sncronos, logo esta abordagem ser
utilizada para permitir que atores possam interagir com objetos, e estes com outros objetos.
$somar
{
parametro +
}
incluirAgenda
}
incluirModeloDeObjeto
Linguagens de programao como C++ e Java utilizam-se de uma marcao para definir as
classes que por sua vez contm mtodos que contm o cdigo. Em C/C++ o ponto de entrada de
programa descoberto atravs de uma conveno na nomenclatura de mtodo. O mtodo cha-
mado main ser o ponto de entrada do programa. Em Java a definio de pontos de entradas so
definidos por mtodos estticos chamados de main contidos em classes. O nome de uma classe
36
contendo este mtodo ento passada para a Mquina Virtual Java que inicializa o programa
invocando-o.
Este modo de inicializao no qual o ponto de entrada dado por uma conveno de no-
menclatura possui vantagens como simplicidade.
Claro que ningum escreve um aplique na mo. Programadores Telis se valem do ambiente
de desenvolvimento que torna todo o processo de definio de atributos grfico, deixando ao
programador o foco apenas no que importante.
Visando simplificar este processo, a nova linguagem dever possuir um novo sistema de ini-
cializao mais simples e menos verboso, isto , aplicaes simples devem poder ser descritas
de forma mnima. Linguagens como Python e Ruby conseguiram isto. No necessrio espe-
cificar nenhum ponto de entrada no programa. O cdigo inteiro pode ser visto como a definio
de um mtodo que ser invocado, podendo-se escrever instrues diretamente no arquivo fonte
sem a necessidade de marcar trechos de cdigo. Com a evoluo do programa, pode-se ento
criar novas classes, mtodos, entre outras coisas demarcando trechos de cdigo com palavras
chaves, mas a princpio isto no necessrio.
A nova linguagem adotar esta idia presente nestas linguagens. Um cdigo fonte nada mais
do que a definio da agenda iniciar de um modelo que ser instanciado automaticamente,
sendo criado o primeiro ator do sistema. Desta forma, o programa mostrado na listagem 2.16
ser vlido e faria exatamente a mesma coisa que o programa mostrado na listagem 2.17. Como
pode-se notar h uma grande simplificao do cdigo na linguagem nova em relao ao Telis
nos casos mais simples.
10 $x a s s o c i a r
20 $y a s s o c i a r
x y + mostrar
suicidar
[
" iniciar "
[
10 x a s s o c i a r
20 y a s s o c i a r
x y + mostrar
suicidar
]
incluirAgenda
]
incluirModelo
]
incluirAplique
A linguagem que ser desenvolvida dever poder rodar em ambientes distintos, com pecu-
liaridades diferentes. Um ambiente de execuo o local no qual o aplique rodar. A princpio
sero definidos trs ambientes bsicos, mas no so limitados apenas a estes:
Aplicao servidor
Um aplique dever ser capaz de rodar em um destes trs ambientes. Entretanto h diferenas
muito grandes com relao ao que dever ser oferecido ao programador em cada um destes
ambientes. Em ambientes grficos deve-se oferecer formas de manipular diferentes objetos
grficos, coisa que no dever existir em aplicaes textuais e de servidor.
Linguagens como Java resolvem este tipo de problema, fazendo uma linguagem absoluta-
mente neutra e entrega APIs (Application programmers interface) e frameworks que encapsu-
lam as peculiaridades destes ambientes. Esta uma abordagem simples, que transfere a res-
ponsabilidade da linguagem para a biblioteca desta mesma linguagem. Entretanto, Telis assim
como a nova linguagem tem como principal objetivo ser simples. Toda a funcionalidade ine-
rente a um dado ambiente deve estar disponvel de forma simples sem a necessidade de utilizar
38
A nova linguagem dever ser capaz de rodar independentemente do ambiente. Note que
no foi mencionado que um mesmo aplique dever ser capaz de rodar em mais de um ambiente
simultaneamente.
Aplicando este princpio, podemos dizer que a nova linguagem na verdade ser composta
por um framework comum e especializada para cada um destes diferentes ambientes de exe-
cuo. Quando o ncleo da linguagem especializado para um determinado ambiente de exe-
cuo, agendas primitivas especializadas podero ser includas, modelos/moldes definidos, a
inicializao personalizada, integrao com o ambiente em questo realizada e qualquer outra
ao que se achar necessria.
"" | "" | "" | "" | " " | " " | " " | " " |
" " | " " | " " | " " | "" | "" | "" | "" | "" |
"" | "" | "" | "" | "" | " " | " " | " " | " " |
"" | "" | "" | "" | " " | ""
<OPERADOR> = ( " + " | "" | " " | " / " | "\\" | " ^ " | " = " | "~=" | " <" | " >" |
" <=" | " > = " )
3 Implementao do Interpretador
O diagrama de classes completo ser omitido devido ao seu tamanho. O sistema com-
pleto composto por algumas centenas de classes e se torna impraticvel coloc-lo na integra.
Entretanto os pontos mais interessantes sero abordados.
O interpretador dividido em trs grandes reas como ilustrado na figura 3.1. Os wrappers
so uma biblioteca que implementa uma hierarquia de tipos responsveis por encapsular os tipos
de dados primitivos de Java, como por exemplo Strings, nmeros(double) nome, alm de repre-
sentar os tipos de dados nicos em Telis, como os smbolos, e fornecer operaes sobre estes
que ainda no existem nativamente na linguagem. Alm disso, possuem uma superclasse co-
mum permitindo que sejam criadas estruturas de dados parametrizadas. O corao da mquina
responsvel pela maior parte da funcionalidade do interpretador, ele implementa a estrutura
bsica da linguagem, as aes semnticas independentes do ambiente, o parser da linguagem, a
estrutura de concorrncia e sincronizao, etc.. Por fim, o ambiente ser responsvel em adaptar
o corao da mquina para cada um dos ambientes suportados, implementando primitivas de-
pendente do ambiente, realizando a inicializao da mquina e do ambiente no qual se encontra
entre outras funes. Para este trabalho sero desenvolvidos dois ambientes de execuo distin-
tos. O primeiro baseado em console, o segundo ser grfico sendo disponibilizadas agendas
primitivas para efetuar operaes tpicas de Turtle Graphics, de Logo.
41
O segundo objetivo visa aumentar a coeso, removendo cdigo de manipulao dos dados
das classes pertencentes ao corao da mquina e movendo-o para classes especializadas.
Os mdulos e classes de um sistema orientados devem apresentar alta coeso, isto , cada
classe e mtodo deve possuir uma nica responsabilidade. Mdulos e classes no coesas acarre-
tam problemas de manutenibilidade de cdigo, j que se torna difcil localizar onde determinada
funcionalidade dever ser encontrada e quando encontrada, ela normalmente est misturada com
cdigo responsvel por outras funcionalidades fazendo com que mudanas possam acarretar
conseqncias no previstas.
Alm destas classes, existe ainda mais uma classe adicional junto esta estrutura. uma
instncia do padro de projeto Builder, cujo nome ConstrutorDeListas. O objetivo do padro
de projeto Builder separar a construo de um objeto complexo de sua representao. A figura
3.3 mostra a estrutura tpica de um Builder.
O padro builder, conforme descrito por Gamma et al. (1995), possui os seguintes elementos
com suas respectivas responsabilidades:
Optou-se em utilizar o padro Builder para permitir a criao de listas e a definio de seu
contedo sem a necessidade de conhecimento da hierarquia mostrada na figura 3.2. A listagem
3.1 mostra um fragmento de cdigo Java criando uma lista com e sem a utilizao do Builder.
Nota-se que o cdigo que utiliza o builder no precisa ter conhecimento sobre os detalhes de
construo dos objetos, pois estes detalhes esto encapsuladas no ConstrutorDeListas.
/ / Utilizando Builder
C o n s t r u t o r D e L i s t a s c o n s t r u t o r = new C o n s t r u t o r D e L i s t a s ( ) ;
L i s t a < P a l a v r a > l i s t a = c o n s t r u t o r . a d i c i o n a r T e x t o ( "umTexto" )
. iniciarLista ()
. adicionarNmero (10)
. terminarLista ()
. obterSaidaComoLista ( ) ;
/ / Sem u t i l i z a r B u i l d e r
L i s t < P a l a v r a > c o n t e u d o = new A r r a y L i s t < P a l a v r a > ( ) ;
c o n t e u d o . add ( new T e x t o ( "umTexto" ) ) ;
L i s t < P a l a v r a > p r i m e i r o E l e m e n t o = new A r r a y L i s t < P a l a v r a > ( ) ;
p r i m e i r o E l e m e n t o . add ( new Numero ( 1 0 ) ) ;
c o n t e u d o . add ( new L i s t a < P a l a v r a > ( p r i m e i r o E l e m e n t o ) ) ;
L i s t a < P a l a v r a > l i s t a E q u i v a l e n t e = new L i s t a < P a l a v r a > ( c o n t e u d o ) ;
Listagem 3.1: Ilustrando criao de listas. A lista nas variveis lista e listaEquivalente so
iguais.
Implementar closures
Alm destes detalhes que o corao da mquina deve implementar h uma srie de outras
caractersticas desejveis:
3.3.1 O Parser
Existem vrios outros compiler-compilers para Java, mas uma das principais vantagens do
JavaCC que o cdigo gerado por ele no depende de nenhuma outra biblioteca como comum
em outras aplicaes. As classes geradas pelo JavaCC so mostradas no diagrama da figura 3.8.
O JavaCC permite que aes sejam realizadas quando uma sentena da linguagem reco-
nhecida. Estas aes so fragmentos de cdigo que podem realizar aes arbitrrias. No caso
do interpretador da nossa linguagem, estas aes so utilizadas para gerar uma estrutura de
48
dados intermediria representando o programa. A estrutura gerada durante o parsing pelo in-
terpretador uma Lista, e esta lista pode possuir qualquer elemento do tipo Palavra (hierarquia
mostrada na figura 3.2).
Para facilitar a gerao e diminuir a quantidade de cdigo dentro do parser gerado pelo
JavaCC utilizado sistema de callback, isto , toda vez que uma determinada seqncia reco-
nhecida pelo interpretador uma mensagem enviada a um objeto previamente cadastrado. Este
objeto uma instncia da classe ConstrutorRepresentacaoInterna. Esta classe uma instancia
do padro de projeto Adapter. Um adapter adapta a interface de um objeto para uma segunda in-
terface esperada pelo cliente, sendo responsabilidade dele transformar os parmetros recebidos
para os esperados. A classe ConstrutorRepresentacaoInterna adapta a classe ConstrutorDeLis-
tas para a interface de notificao esperada pelo parser.
Vrias classes so geradas pelo JavaCC, cada uma responsvel por uma parte do processo de
parsing. A classe ParserTelisTokenManager responsvel por realizar a analise lxica, gerando
tokens para a classe ParserTelis que implementa o analisador sinttico. As demais classes so
classes auxiliares utilizadas como estruturas de dados (Token por exemplo), classes utilitrias
(como JavaCharStream) ou classes para reportar erros.
Aps o parsing ter sido concludo, e a representao interna do programa gerada o prximo
passo tomado pelo algoritmo de inicializao implementado em AmbienteAbstrato a criao
de um ator e o incio de sua execuo.
A classe Aplique uma instncia do padro de projeto Method Factory. Ela responsvel
pela criao de novos atores, durante a criao de um ator, o mtodo fbrica alm de cri-lo
deve passar para o ator o seu parmetro inicial, o modelo a qual o Ator pertence e fornecer
ele uma identidade nica. Alm destas responsabilidades, a classe Aplique deve manter uma
coleo contendo todos os atores criados no sistema, para que, por exemplo, atores possam ser
notificados de estmulos emitidos. Alm de usar o padro Method Factory, o padro Singleton
tambm usado nesta classe, pois o interpretador deve possui um e apenas um Aplique criando
e mantendo referencias para os Atores.
A classe Aplique ainda oferece a possibilidade de uso do padro de projeto Visitor para que
um visitante visite todos os atores instanciados, de forma que durante o processamento nenhum
49
A classe Modelo guarda a descrio do ator, isto , a descrio de suas agendas (nome e
cdigo) e moldes. Oferece mtodos para acesso a descrio e para a alterao da mesma. Todo
Ator est atrelado a um Modelo, e este deve ser informado durante a construo do Ator.
O ator possui o ciclo de vida mostrado no diagrama de estados da figura 3.10. Quando o
ator instanciado ele se encontra no estado Criado. Aps o mtodo iniciarExecuo da classe
Ator ser invocado, o ator em questo transita para o estado Executando. Aps a transio, a
execuo de sua agenda iniciar realizada em uma linha de execuo (Thread ) prpria. Aps a
agenda iniciar ter sido concluda e retornado, o ator entra no estado Hibernando. Neste estado
o ator apenas espera por eventos. Um evento pode ser a chegada de um estmulo emitido por
um dizer ou uma comunicao direta, e em decorrncia destes estmulos o ator pode realizar
algum processamento novamente. O ator fica neste estado indefinidamente at que ele seja
destrudo, transitando para o estado Morto. Neste estado, o ator est se preparando para ser
destrudo tomando as medidas necessrias antes disso tais como: desregistrar-se de qualquer
lugar que tenha se inscrito para callback, sair da lista de atores do Aplique, finalizar a sua linha
de execuo.
Um objeto Ator uma instncia do padro de projeto Observer. Em cada uma das transies
do seu ciclo de vida, eventos so gerados e os observadores cadastrados no ator so notificados.
Desta forma oferecido ganchos para subsistemas realizarem aes dependendo do estado do
ator. Por exemplo, o subsistema de estmulos observa o ator e s o deixa receber estmulos de
50
A classe Ator mantm as referncias para o modelo e oferece mecanismos para o controle de
ciclo de vida de um ator, entretanto no responsvel diretamente pela execuo. Este trabalho
delegado para a classe MaquinaDePilha. A classe mquina de pilha quem realmente executa
o cdigo.
Simbolo
Operador
51
OperadorComunicacaoDireta
OperadorEmpilhamento
de projeto, apesar de no estarem entre os definidos por Gamma et al. (1995), e fornecem um
comportamento padro quando um objeto de determinado tipo no existe, substituindo assim o
null. O ResolvedorNulo no capaz de realizar nenhuma transformao de Resolvivel em Exe-
cutavel, portanto a MaquinaDePilha ir gerar erros de execuo para todo e qualquer Resolvivel
que for encontrado. O resolvedor pode ser alterado utilizando-se IoC, sigla para Inversion of
control. Neste estilo de programao os colaboradores de um objeto so injetados no mesmo
por algum responsvel por criar e gerenciar as dependncias entre estes objetos. No caso da
mquina de pilha, quem responsvel por gerenciar estas dependncias a classe Ator. Ela
cria, configura e injeta os colaboradores da MaquinaDePilha.
Para garantir flexibilidade e tornar simples e configurvel o Resolvedor, que quem real-
mente conhece as primitivas e como execut-las, utilizou-se o padro Composite. A classe que
implementa o padro composite chamada de ResolvedorComposto. O padro de projeto Com-
posite cria uma interface nica para colees de objetos e objetos propriamente dito. No caso
do Resolvedor, este comportamento se torna bastante til pois a MaquinaDePilha no precisa
de lgica adicional para tratar com colees de Resolvedores, e torna os resolvedores extre-
mamente flexveis pois cada subsistema pode criar um Resolvedor prprio contendo apenas os
seus prprios mapeamentos e uma entidade separada ser responsvel por coletar todos os resol-
vedores desejados. E isto mesmo que feito. Cada subsistema fornece um resolvedor (que
por sua vez pode ser um outro Composite) e um objeto separado configura um ResolvedorCom-
posto contendo referencia para todos os outros resolvedores. Este ltimo objeto implementa a
interface InstaladorDeModulos que deve ser implementado pelos ambientes de execuo, ele
53
armazenado junto classe Aplique e passado para as instancias de Ator que a utilizam para
configurar um resolvedor composto antes de injet-lo na MaquinaDePilha.
Uma instncia do padro Composite, como o caso do ResolvedorComposto, traz uma srie
de benifcios mas traz uma definincia muito importante para o interpretador: a ordem. A
ordem em que os resolvedores filhos sero invocados para a busca de um Executavel no
definida pelo padro. Isto um problema pois caso dois subsistemas definam dois Executaveis
diferentes para um mesmo Resolvivel, cria-se um problema. A linguagem deve fornecer um
esquema de prioridades para resolver este tipo de questo. Por este motivo, criou-se uma verso
um pouco alterada do ResolvedorComposto, chamado de ResolvedorPorCastas. A idia por trs
do ResolvedorPorCastas criar um Composite que leve em considerao os tipos essenciais
de resolvedores estipulando um ordem entre eles. Desta forma, o problema de prioridades
resolvido.
O escopo de variveis esta atrelado chamadas de agendas. Toda mquina de pilha possui
atrelada a si um GerenteDeEscopo. Toda vez que uma agenda invocada, o gerente de escopo
cria um novo escopo, e sempre que a agenda retorna, o escopo anterior restaurado.
Quem far uma chamada de agenda o subsistema que cuida de agendas, modelos e moldes.
Mas a mquina quem deve oferecer a infra-estrutura bsica para que este subsistema possa
controlar a mquina de pilha fazendo com que ela altere seu fluxo de execuo. Para isso
utilizada uma classe interna a mquina de pilha chamada ControladorDaMaquinaDePilha. Ela
classe interna privada, mas implementa uma interface pblica e passada como parmetro
para o Executavel. A classe ControladorDaMaquinaDePilha oferece mtodos para a execuo
de uma agenda, quando este mtodo invocado o ControladorDaMaquinaDePilha ir criar um
54
novo escopo com o escopo do ator como sendo o prximo escopo na cadeia de responsabilidade,
como explicado anteriormente. Ento realizada uma chamada MaquinaDePilha para que ela
execute o cdigo da agenda, como o escopo atual foi trocado no GerenteDeEscopo, a agenda
executar no novo escopo. Aps terminar a execuo da agenda, o fluxo de execuo retorna
ao ControladorDaMaquinaDePilha e o escopo que estava sendo utilizado antes da agenda ser
invocada restaurado e a MaquinaDePilha ir continuar a executar do ponto onde havia parado.
Closures podem ser executados posteriormente a sua declarao pela primitiva executar.
Esta primitiva envia uma mensagem ao ControladorDeMaquinaDePilha informando que se de-
seja executar o closure. Neste momento, a MaquinaDePilha troca o escopo que ela est utili-
zando para o escopo referenciado pelo Closure, executa a ListaDeComandos atrelado ao closure
e em seguida restaura o escopo que estava sendo utilizado anteriormente. O diagrama de classes
da figura 3.13 mostra o Closure, a interface ControladorDeExecucaoDaMaquina e sua imple-
mentao Controlador. Como pode-se ver, o Controlador possui os mtodos executar(Closure),
para realizar a execuo de um closure, e o mtodo avaliarExpresso(Closure, Palavras) que
permite que um closure seja avaliada e o que permanecer no topo da sua pilha ir ser retornado.
Importante ressaltar que avaliarExpresso no modifica a pilha que a MaquinaDePilha est uti-
lizando, uma nova pilha criada e as palavras passadas como parmetros empilhadas nesta
pilha temporria. Aps o termino de execuo do closure a pilha que estava sendo utilizada
restaurada e o fluxo de execuo retomado.
Existem outras primitivas que podem implicar na execuo de um closure como as pri-
mitivas de deciso (seVerdade, seFalso) e iterao (enquantoVerdadeiro, vezesRepetir). Outra
utilidade importante do closure que ele utilizado para definir o que deve ser feito em resposta
a um determinado evento, isto , definir as aes a serem tomadas mediante a chegada de um
55
evento.
adicionar, remover e acessar as estes elementos. Alm disso, implementada nesta classe o
algoritmo para o clculo do ordenamento topolgico sobre o grafo de herana, que define a
ordem em que as agendas herdadas sero invocadas.
Para percorrer o grafo de herana na ordem em que as agendas sero invocadas utilizado
o padro de projeto Visitor. O padro Visitor utilizado para separar o algoritmo utilizado para
percorrer uma estrutura de dados do algoritmo que operar sobre os dados contidos nesta estru-
tura. A principal vantagem da utilizao deste padro que se torna simples adicionar ou trocar
os algoritmos que iro operar sobre os dados. Outro padro que normalmente utilizado nestes
casos o padro Iterator. A principal diferena entre os dois padres que responsabilidade
de quem utiliza o Iterator verificar se h mais dados e peg-los do Iterator. No caso do Visitor,
quem faz isso o prpria classe da estruturas de dados. Logo o padro Visitor melhor, neste
caso, pois encapsula mais detalhes do que o Iterator tornando o cdigo do usurio mais simples
do que o equivalente utilizando Iterator.
Quando uma agenda invocada deve ser calculada todas as agendas que devero ser in-
vocadas, isto , as agendas de toda a hierarquia do modelo. Para isto, utilizado um visitante
que percorre a hierarquia de moldes em ordem e cria um objeto da classe AgendaComposta,
que uma instncia do padro de projeto Composite. O diagrama de classes pode ser visto no
diagrama da figura 3.16. A classe Agenda , na nomenclatura do padro Composite um Leaf
enquanto a classe AgendaComposta um Composite e a interface IAgenda um Component.
57
se que uma MaquinaDePilha sofre uma interrupo quando deve parar o que est executando
para executar um tratador. A MaquinaDePilha permite o agendamento de uma interrupo e
um sistema de callback utilizado para notificar MaquinaDeEstimulos quando a interrup-
o finalizou o seu tratamento. Na MaquinaDePilha no h nenhum esquema de prioridade, o
estmulo agendado na MaquinaDePilha ir interromper a mquina independente do que a Ma-
quinaDePilha est fazendo no momento. A responsabilidade de implementar prioridades da
MaquinaDeEstmulos.
O terminador de sentenas nesta linguagem ser o ponto final (.). O ponto final dever
ser colocado ao final de toda a sentena escrita nesta linguagem. Outro operador interessante
o operador ponto-e-vrgula. O operador ponto e vrgula possui o intuito de enviar diversas
mensagens a um mesmo objeto. Este operador utilizado aps uma mensagem ser enviada para
que a prxima mensagem opere sobre o mesmo objeto que havia recebido a mensagem anterior.
O que interessante notar na gramtica a precedncia dos seletores, que em outras lin-
guagens so chamados de operadores. Nota-se que no h uma precedncia, tudo avaliado da
esquerda para a direita. O motivo disso ficar mais claro quando a semntica da linguagem for
explicada.
O objetivo da linguagem compilada que ela seja semanticamente simples, com o mnimo
de excees possvel. Na linguagem basicamente o que h so trocas de mensagens. Um ator
envia mensagens a outros atores e objetos para que a computao se realize.
Ao encontrar um elemento sinttico descrevendo um tipo de dado, como por exemplo uma
String, um nmero ou uma lista, o compilador ir gerar cdigo para a criao de um modelo de
objeto previamente definido. Este modelo de objeto como qualquer outro e possui agendas
previamente definidas, sendo portanto capaz de responder as mensagens ele enviado.
alvo, as variveis so criadas automaticamente e so sempre locais, com exceo das variveis
declaradas na agenda iniciar de um modelo ou molde. Estas ltimas sero variveis de instncia
do modelo. possvel utilizar encademeamento de atribuies, como mostrado na listagem 4.3.
Como tudo na linguagem atribuies tambm retornam um valor, que o valor que acabara de
ser atribudo a ele. Assim sendo, todas as variveis em uma atribuio em cascata iro receber
o mesmo valor.
umNumero : = n u m e r o V i n t e : = 2 0 .
Existem trs tipos de mensagens diferentes como possvel ver na gramtica EBNF da
listagem 4.1, so elas:
Mensagem unria utilizado para enviar uma mensagem um destino sem realizar
passagem de parmetros. a mensagem mais prioritria.
Mensagem por palavra chave utilizado para enviar uma mensagem um destino
passando no mnimo um parmetro.
H pequenas diferenas sintticas entre cada uma dessas mensagens. Na listagem 4.4
mostrado um exemplo contendo todos os tipos de mensagens.
Na segunda linha do exemplo enviada a mensagem + com o objeto que est armazenado
na varivel numeroVinte e o objeto 10 enviado como parmetro. O valor retornado pelo m-
todo ser armazenado na varivel somatorio. Este exemplo da mensagem binria primeiro
colocado o objeto que ir receber a mensagem, assim como em todos os tipos de mensagens,
sendo seguido pelo seletor, um token SELETOR descrito na listagem 4.2 e por fim o parmetro.
Na terceira linha do exemplo enviada a mensagem mostrar: com o objeto que est
armazenado na varivel devo e o objeto armazenado na varivel somatorio enviado como
parmetro. Este exemplo da mensagem por palavra chave, primeiro colocado o objeto que
ir receber a mensagem seguido pelo primeiro fragmento do nome do mtodo (at o dois pontos)
64
seguido pelo parmetro, sendo seguido pelo segundo fragmento do nome do mtodo, seguido
por outro parmetro e assim por diante. O nmero de parmetros determinado pelo nmero
de fragmentos. Para cada fragmento h um parmetro. A palavra-chave devo utilizada para
dizer que o prprio ator deve receber a mensagem, isto , uma referncia para o prprio ator
que est executado.
n u m e r o V i n t e : = " 2 0 " comoNmero .
somatorio := numeroVinte + 10.
devo m o s t r a r : s o m a t o r i o .
interessante notar que estruturas de controle de fluxo pode ser explicado pelo tica de
mensagens e troca de mensagens. No fragmento de cdigo listagem 4.5 mostrado um exem-
plo de estrutura de escolha, no qual realizado um teste para verificar a igualdade entre dois
valores e mostrar um valor qualquer em cada um dos casos. A comparao entre umNumero
e outroNumero no nada mais do que a mensagem binria = enviada umNumero. Ao
valor retornado por esta mensagem enviado a mensagem seVerdade:seFalso:. Espera-se,
por conveno, que o valor retornado pela mensagem = seja um valor booleano, ou instncia
do modelo Verdadeiro ou do modelo Falso. Por polimorfismo ento a escolha feita. Caso
seja uma instncia de Verdadeiro, o primeiro parmetro avaliado. Caso seja uma instncia de
Falso, o segundo parmetro avaliado. Resumindo, possvel implementar estrutura de deciso
baseando-se somente as ferramentas oferecidas pela linguagem, ou seja, mensagens e closures.
umNumero = o u t r o N u m e r o
s e V e r d a d e : [ devo m o s t r a r : " i g u a l " . ]
s e F a l s o : [ devo m o s t r a r : " d i f e r e n t e " . ] .
65
Assim como na linguagem interpretada atores iro rodar simultaneamente de forma inde-
pendente, sendo que quando criados eles executam a agenda de nome iniciar.
Na listagem 4.6, v-se tambm como ocorre a declarao das agendas que respondem a
cada um dos trs tipos de mensagens. A primeira, e mais simples, a agenda da mensagem
unria, exemplificada pela agenda iniciar, que declarada simplesmente escrevendo-se o nome
da agenda seguida pela lista contendo a declarao da agenda. Aps temos a agenda que res-
pondem a mensagens por palavra chave, exemplificada pela mensagem somar: valor. As
mensagens por palavra chave so declaradas colocando-se as partes do nome da agenda entrela-
adas com os nomes dos parmetros. No caso da agenda somar:, valor o nome do parmetro
formal da agenda. Pode-se declarar agendas com maior nmero de parmetros. Por exemplo,
pode-se criar uma agenda com a assinatura: somar: valor com: valor2, neste caso o nome da
agenda somar:com: e os parmetros formais so valor e valor2. Por ltimo, a declarao de
uma agenda que responde a agendas binrias, exemplificado pela agenda +. Essas agendas
so criadas colocando-se o seletor, no caso +, seguido do nome do parmetro formal.
molde : #UmMolde
66
[
iniciar
[
var := 10.
]
somar : v a l o r
[
var := var + v a l o r .
]
].
As ltimas duas linhas do exemplo mostrado na listagem 4.6 mostram um exemplo do uso
do operador ponto-e-vrgula. Primeiramente, a mensagem mostrar: enviada ao prprio ob-
jeto (atravs da palavra chave devo). Em seguida, o operador utilizado para que a prxima
mensagem, que no caso suicidar, seja enviada para o mesmo objeto que a mensagem ante-
rior, isto , o prprio objeto.
Um outro aspecto importante que nesta linguagem tudo retorna algum valor. Caso uma
agenda no possua nenhum retorno, automaticamente ser retornado uma referncia ao objeto
ao qual a agenda pertence. No caso de closures, o valor retornado pela avaliao do mesmo
igual ao valor da ltima expresso do closure.
antiga em desenvolvimento de software que est ganhando muita ateno. DSLs so basi-
camente linguagens especficas particularizadas para um determinado domnio de aplicao.
Como exemplo de uma DSL pode-se citar JavaCC, compiler-compiler aqui utilizado. Existem
dois tipos de DSLs, as chamadas externas so escritas em uma linguagem diferente da lingua-
gem de programao principal utilizada para desenvolver o programa, as internas so escritas
na mesma linguagem de programao. Existem diversas vantagens e desvantagens em cada um
destes tipos de DSLs.
Devido a sua sintaxe, esta linguagem favorece muito o desenvolvimento de DSLs internas.
Como DSLs internas so limitadas pela linguagem e devem ser sintaticamente e semantica-
mente vlidas, quanto menor o impacto causado pela sintaxe melhor ser para desenvolver
DSL. A ausncia de parnteses para a passagem de parmetros, o entrelaamento do nome do
mtodo e parmetros, a ausncia de pontos para realizar a troca de mensagens entre objetos.
Tudo isso faz com que a estrutura de uma sentena se assemelhe muito a uma frase escrita em
uma linguagem natural, facilitando assim o desenvolvimento destes tipos de linguagens.
68
5 Implementao do compilador
Como opo de implementao, optou-se por tornar o compilador o mais simples poss-
vel sendo a maior parte da complexidade referente semntica da linguagem implementada
pelo interpretador. O sistema de herana, concorrncia, comunicao entre atores, entre outros
detalhes, so todos implementados pelo interpretador.
Quando o compilador executado lhe fornecido o arquivo no qual o cdigo fonte que se
deseja compilar est escrito e o arquivo no qual a sada do compilador dever ser escrita. Ento,
como ilustrado esquematicamente na figura 5.1, o compilador l o cdigo fonte e o envia ao
parser, responsvel por realizar a anlise lxica e sinttica gerando uma Abstract Syntax Tree
(AST) representando hierarquicamente a entrada. A AST gerada ento processada, sendo
realizada aqui a analise semntica (que muito limitada, no realizada quase nenhuma analise
semntica) e a gerao de cdigo. Por ltimo o cdigo gerado mesclado com o cdigo do
sistema de runtime e escrito no arquivo de sada.
5.1 Parser
O parser do compilador no foi escrito manualmente, exemplo do que foi feito no inter-
pretador. Foi utilizado tambm o compiler-compiler JavaCC para gerar o parser. Entretanto,
no foi utilizado apenas o JavaCC, foi utilizado uma ferramenta que acompanha a distribuio
do JavaCC chamada JJTree.
O JJTree uma ferramenta com um nvel de abstrao mais alto quando comparada ao
69
JavaCC. Com o JavaCC, possvel descrever o parser atravs de uma sintaxe semelhante a
EBNF, com uma extenso para descrever aes semnticas a serem tomadas. O JJTree um
pr-processador para o JavaCC que adiciona mais uma extenso a gramtica original do JavaCC
na qual possvel descrever a forma da AST que se quer gerar, sendo o cdigo responsvel pela
montagem da AST gerado automaticamente. Alm disto, uma classe gerada para cada tipo de
n diferente dentro da rvore.
As classes geradas pelo JJTree so muito semelhantes as que foram geradas pelo JavaCC
para o interpretador, e por este motivo ser omitida. A principal diferena entre as duas que
o JJTree alm de gerar o parser, gera uma interface Node e uma classe que implementa Node
para cada produo que ir gerar um n na AST.
70
Aps o parsing estar completo e a AST ter sido completamente gerada o compilador co-
mea a fase de anlise semntica e gerao de cdigo. Como dito anteriormente, a anlise
semntica bastante limitada sendo que poucas verificaes e testes so realizados, como
comum em linguagens dinamicamente tipadas.
Foram criados vrios visitantes, cada um responsvel pela anlise e gerao do cdigo em
um determinado contexto. Isto ocorre porque um mesmo nodo, dependendo do local no qual
utilizado, pode requerer aes semnticas e/ou gerao de cdigos diferentes. Quando se est
processando o nodo e sabe-se que o prximo nodo exigir um novo visitante, um criado e a
troca de visitante realizada.
Aps o processo de gerao ter sido concludo, o compilador pegar o cdigo fonte equiva-
lente escrito na linguagem alvo e o mesclar ao cdigo do sistema de runtime. Isto realizado
utilizando um sistema de templates chamado Velocity. Um sistema de template caracteri-
zado por processar um documento escrito em uma linguagem prpria definido pelo sistema de
template e gerar uma sada alterando vriaveis e dados do template por valores fornecidos pelo
usurio. O sistema de runtime escrito em forma de template, demarcando como e onde o
cdigo gerado dever ser inserido.
71
Referncias Bibliogrficas
ARMSTRONG, J. The development of erlang. SIGPLAN Not., ACM Press, New York, NY,
USA, v. 32, n. 8, p. 196203, 1997. ISSN 0362-1340.
BRODIE, L. Starting FORTH. Upper Saddle River, NJ, USA: Prentice-Hall, Inc., 1986. ISBN
0-13-843087-X.