Projeto de PLP (2005.1) Extensão da Linguagem OA1 (2003.1) Alunos: Alberto Costa Neto (acn) Manoel Messias da Silva Menezes Júnior (mmsmj) Rafael Leão da Fonseca (rlf) Agenda • • • BNF/API de OA1 Ambientes de Execução e Compilação Extensões da Linguagem OA1 1. 2. 3. 4. 5. 6. 7. 8. • • Acrescentar Join Points para leitura/escrita de atributos Introdução de atributos e métodos Implementação do operador not em PointcutExpressao Implementação de cflow e cflowbelow Implementação de within e withincode Uso de Matching na definição de Pointcuts Advice com pointcut anônimo Inclusão de objeto thisJoinPoint Conclusões Trabalhos Futuros BNF/API de OA1 Ambientes de Execução e Compilação Ambiente de Execução • Componentes herdados de LOO1 – uma pilha de mapeamentos de identificadores (incluindo this) em valores (incluindo referências). – um mapeamento de referências em objetos. – a referência para a próxima célula a ser alocada. – um mapeamento de identificadores em definições de classes. – listas de valores de entrada e saída. • Componentes adicionais – Gerenciador de aspectos. – Pilha de interceptáveis (join points). Ambiente de Execução • Gerenciador de Aspectos – Mapeamento de identificador de pointcut em pointcut – Mapeamento de identificador de pointcut em um grupo de advices Ambiente de Compilação • Componentes herdados de LOO1 – uma pilha de mapeamentos de identificadores em tipos. – um mapeamento de identificadores em definições de classes. – listas de valores de entrada. Extensão da Linguagem OA1 Extensão da linguagem OA1 Propostas 1. Acrescentar Join Points para leitura/escrita de atributos 2. Introdução de atributos e métodos 3. Implementação do operador not em PointcutExpressao 4. Implementação de cflow e cflowbelow 5. Implementação de within e withincode 6. Uso de Matching na definição de Pointcuts 7. Inclusão de objeto thisJoinPoint 8. Modificar advice para usar PointcutExpressao ao invés de um simples Id (advice com pointcut anônimo) Extensão da linguagem OA1 classe Ponto { int x = 0, int y = 0; proc setX(int x) { this.x := x }, proc setY(int y) { this.y := y}, proc mover(int offsetX, int offsetY) { this.x := this.x + offsetX; this.y := this.y + offsetY }, proc printX() { write(“x:” ++ this.x) }, proc printY() { write(“y:” ++ this.y) }, proc print() { printX(); printY() } } Extensão da linguagem OA1 1. Introdução dos Join Points (get e set) – get: Captura leitura de um atributo – set: Captura modificação de um atributo aspect PontoLog { pointcut leitura: get(Ponto.x), pointcut escrita: set(Ponto.x); after : leitura { write(“leitura de Ponto.x”) }, after : escrita { write(“escrita em Ponto.x”) } }; Extensão da linguagem OA1 2. Introdução de atributos e métodos aspect PontoLog { proc Ponto.moverX(int offsetX) { this.x := this.x + offsetX }, proc Ponto.moverY(int offsetY) { this.y := this.y + offsetY } } Extensão da linguagem OA1 3. Implementação do operador not em PointcutExpressao • Negação de qualquer PointcutExpressao. Extensão da linguagem OA1 4. Implementação de cflow e cflowbellow – cflow(Pointcut): intercepta qualquer join point no fluxo de controle de qualquer join point P interceptado por Pointcut, incluindo P. aspect PontoLog { pointcut noFluxoDePrint: cflow(Ponto.print()); before : noFluxoDePrint { write("JP no fluxo de controle de print()") } }; Extensão da linguagem OA1 – cflowbelow(Pointcut): intercepta qualquer join point no fluxo de controle de qualquer join point P interceptado por Pointcut, sem incluir P. aspect PontoLog { pointcut noFluxoDePrint: cflowbelow(Ponto.print()); before : noFluxoDePrint { write("JP no fluxo de controle abaixo de print()") } }; Extensão da linguagem OA1 • Pilha / Cache de Join Points Pilha de Join Points Cache de Join Points Extensão da linguagem OA1 1. Chamada à Ponto.print() Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.print() Extensão da linguagem OA1 2. Execução do Advice de PontoLog Pilha de Join Points Cache de Join Points Ponto.print() = 1 PontoLog = 1 PontoLog Ponto.print() Extensão da linguagem OA1 3. Fim da execução do Advice Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.print() Extensão da linguagem OA1 4. Chamada a Ponto.printX() Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.printX() = 1 Ponto.printX() Ponto.print() Extensão da linguagem OA1 5. Execução do Advice de PontoLog Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.printX() = 1 PontoLog = 1 PontoLog Ponto.printX() Ponto.print() Extensão da linguagem OA1 6. Fim da execução do Advice Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.printX() = 1 Ponto.printX() Ponto.print() Extensão da linguagem OA1 7. Acesso a Ponto.x Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.printX() = 1 Ponto.x = 1 Ponto.x Ponto.printX() Ponto.print() Extensão da linguagem OA1 8. Execução do Advice de PontoLog Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.printX() = 1 PontoLog Ponto.x = 1 Ponto.x PontoLog = 1 Ponto.printX() Ponto.print() Extensão da linguagem OA1 9. Fim da execução do Advice Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.printX() = 1 Ponto.x = 1 Ponto.x Ponto.printX() Ponto.print() Extensão da linguagem OA1 10. Remoção de Acesso a Ponto.x Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.printX() = 1 Ponto.printX() Ponto.print() Extensão da linguagem OA1 11. Remoção de Chamada a Ponto.printX() Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.print() Extensão da linguagem OA1 12. Chamada à Ponto.printY() – Executa de forma similar à chamada de Ponto.printX(). – Intercepta dois join points: Ponto.printY() e get(Ponto.y), executando o advice de PontoLog duas vezes. Extensão da linguagem OA1 13. Remoção de Chamada a Ponto.print() Pilha de Join Points Cache de Join Points Extensão da linguagem OA1 5. Implementação de within e withincode – within(PadrãoCasamento) : intercepta os join points nos quais o código em execução é definido na declaração de um dos tipos de PadrãoCasamento. – withincode(PadrãoCasamentoMetodo) : intercepta cada join point onde o código em execução é definido na declaração do método especificado. Extensão da linguagem OA1 { aspect PontoLog { pointcut noFluxoDePrintEForaDePontoLog: cflow(Ponto.print()) and not within(PontoLog), pointcut withincodePrint: withincode(Ponto.print()); before : noFluxoDePrintEForaDePontoLog { write(“No fluxo de controle de print() e not Within PontoLog”) }, before : withincodePrint { write("Withincode Ponto.print()") } } Extensão da linguagem OA1 • Uso da pilha – – Within: Checa o nome da classe/aspecto do join point que está abaixo do elemento no topo da pilha Withincode: Checa o join point que está abaixo do elemento no topo da pilha, que deve ser uma chamada de método e casar com a fornecida Pilha de Join Points Cache de Join Points Ponto.print() = 1 Ponto.printX() Ponto.print() Ponto.printX() = 1 Extensão da linguagem OA1 6. Uso de Matching na definição de Pointcuts aspect PontoLog { pointcut movimento:Ponto.se*(*) or Ponto.mover(..); after : movimento { write(“O ponto mudou de posicao.") }; Extensão da linguagem OA1 • Exemplos de Matching – get/set/cflow(below) • get(*.*), get(*.x), get(Ponto.*), get(P*.*), get(*o.*), get(P*o.*), cflow(*.*), cflowbelow(*.x) – within • within(*), within(P*), within(*to), within(Po*o) – Chamada de método/withincode/cflow(below) • *.*(int, string), *.*(*), *.*(..), *.*(..,int), *.*(int,..), *.*(..,int,..) • *.*(..,..,..), *.*(..,..,int,..,..) Extensão da linguagem OA1 7. Uso de PointcutExpressao na definição de Advice aspect PontoLog { pointcut setX : Ponto.setX(int); after : setX or Ponto.setY(*) or Ponto.mover(..) { write("O ponto mudou de posicao.") } } Extensão da linguagem OA1 8. Inclusão de objeto thisJoinPoint – Dá acesso a metadados sobre o join point interceptado durante a execução de um advice. – Oferece os seguintes atributos: • • kind: string com tipo do join point signature: string com a assinatura do método Extensão da linguagem OA1 • Uso de thisJoinPoint na definição de Advice aspect PontoLog { before : Ponto.setX(*) or Ponto.setY(*) { write(thisJoinPoint.signature); write(thisJoinPoint.kind) } } Conclusões Conclusões • A introdução do conceito de aspectos tornou a implementação do interpretador relativamente complexa – Se usássemos AspectJ na implementação do interpretador, seria mais simples • A introdução de aspectos na LOO1 faz com que expressões tenham efeitos colaterais – Execução dos advices ativados por um pointcut designators get Conclusões • A implementação interpretada exige que para cada comando ou expressão interceptável seja feita a avaliação de todos os pointcuts • Essa abordagem é bastante lenta, principalmente quando utiliza-se cflow/cflowbelow – O cache de join points implementados ajuda, mas não no caso de matching Conclusões • A utilização de Generics na implementação das pilhas e mapeamentos permitiu – melhor reutilização de código – checagem estática • Otimização das pilhas para permitir navegação sem desempilhar/empilhar Trabalhos Futuros Trabalhos Futuros • Estender o ambiente de compilação para permitir a verificação estática das declarações de aspectos • Retirar obrigatoriedade de haver um pointcut e um advice no aspecto • Permitir declarações de atributos e métodos nos aspectos Trabalhos Futuros • Controlar a instanciação de aspectos por cflow (percflow), cflowbelow (percflowbelow), this (perthis), target (pertarget) e única (issingleton) • Implementação dos poincut designators adviceexecution e if de AspectJ • Permitir o uso de anotações ao estilo de AspectJ 5 Trabalhos Futuros • Estender LOO1 com conceitos como: função, herança, array e type casting. – Isso permitiria, implementar outros pointcut designators • • Permitir que um método ou atributo introduzido em uma classe não seja utilizado apenas dentro do aspecto que realizou a introdução Implementar a precedência entre os operadores and e or.