Sie sind auf Seite 1von 95

UNIVERSIDADE FEDERAL DE SANTA MARIA CENTRO DE TECNOLOGIA CURSO DE CINCIA DA COMPUTAO

INCORPORAO DE NOVAS REFATORAES PARA LINGUAGEM FORTRAN NO IDE ECLIPSE

TRABALHO DE GRADUAO

Gustavo Rissetti

Santa Maria, RS, Brasil 2010

INCORPORAO DE NOVAS REFATORAES PARA LINGUAGEM FORTRAN NO IDE ECLIPSE

por

Gustavo Rissetti

Trabalho de Graduao apresentado ao Curso de Cincia da Computao da Universidade Federal de Santa Maria (UFSM, RS), como requisito parcial para a obteno do grau de Bacharel em Cincia da Computao

Orientador: Profa Dra Andrea Schwertner Charo

Trabalho de Graduao N. 290 Santa Maria, RS, Brasil 2010

Universidade Federal de Santa Maria Centro de Tecnologia Curso de Cincia da Computao

A Comisso Examinadora, abaixo assinada, aprova o Trabalho de Graduao

INCORPORAO DE NOVAS REFATORAES PARA LINGUAGEM FORTRAN NO IDE ECLIPSE elaborado por Gustavo Rissetti como requisito parcial para obteno do grau de Bacharel em Cincia da Computao COMISSO EXAMINADORA: Profa Dra Andrea Schwertner Charo (Presidente/Orientador) Profa Dra Iara Augustin (UFSM)

Prof. Dr. Giovani Rubert Librelotto (UFSM)

Prof. Dr. Eduardo Kessler Piveta (UFSM)

Santa Maria, 04 de Janeiro de 2010.

O maior prazer de um homem inteligente bancar o idiota diante de um idiota que banca o inteligente. C ONFCIO

A mudana a lei da vida. E aqueles que apenas olham para o passado ou para o presente iro com certeza perder o futuro. J OHN L ENNON

No sabendo que era impossvel, ele foi l e fez. AUTOR D ESCONHECIDO

AGRADECIMENTOS

Gostaria de agradecer primeiramente a Deus, por estar ao meu lado sempre que precisei, no deixando-me na mo at mesmo quando acreditei estar sozinho. Aos meus pais e minha irm, que com muita pacincia sempre me apoiaram, vivenciando cada preocupao, cada momento de tristeza e alegria, sempre acreditando no meu potencial. Aos meus colegas de aula, de PET, de curso, em especial ao Vitor Conrado, Vincius Vielmo Cogo e Rodrigo Extercktter Tjder. Nunca esquecerei o apoio, a amizade eterna que obtive com alguns e a fora nos trabalhos e nas provas. professora Andrea, sempre disposta a ouvir, passando dicas valiosas para o bom desenrolar do trabalho, e sem a qual nada disso seria possvel. E aos demais amigos, parentes e conhecidos que de uma forma ou de outra ajudaram no decorrer dessa jornada, muito obrigado!

RESUMO

Trabalho de Graduao Curso de Cincia da Computao Universidade Federal de Santa Maria INCORPORAO DE NOVAS REFATORAES PARA LINGUAGEM FORTRAN NO IDE ECLIPSE Autor: Gustavo Rissetti Orientador: Profa Dra Andrea Schwertner Charo Local e data da defesa: Santa Maria, 04 de Janeiro de 2010. Refatorao uma tcnica de engenharia de software que objetiva aplicar mudanas internas no cdigo fonte de aplicaes, sem que isso inuencie em suas funcionalidades e resultados. Essa tcnica no est restrita apenas ao cdigo fonte, podendo ser aplicada tambm em diversos outros componentes de um sistema de software, como no projeto da aplicao, modelos de anlise, bancos de dados, dentre outros. A refatorao uma tarefa permanentemente presente no ciclo de vida do software, e com ela busca-se melhorar aspectos no funcionais das aplicaes, como legibilidade e possibilidade de reutilizao, podendo tambm ser conseguido algum ganho de desempenho na execuo do software refatorado. Tcnicas de refatorao so amplamente utilizadas em sistemas desenvolvidos para o paradigma da orientao a objetos e esto presentes de forma automatizada em diversas ferramentas que atuam neste paradigma. Na computao cientca, na qual existem grandes quantidades de cdigo legado, escritos em linguagens anteriores ao paradigma da orientao a objetos, a refatorao pouco explorada, principalmente pelo fato de esses cdigos serem escritos em uma linguagem pouco comercializada atualmente. A linguagem Fortran (FORmula TRANslation) normalmente utilizada em aplicaes de cunho cientco, porm, apresenta uma grande carncia de ferramentas para a refatorao de cdigo. Neste contexto, este trabalho explora essa decincia atravs da automatizao de refatoraes, utilizando-se do framework da ferramenta Photran (um plugin para edio de cdigo Fortran integrado ao IDE Eclipse). Partindo-se da identicao de problemas em aberto referentes a aes de refatorao para cdigos Fortran, algumas tcnicas so desenvolvidas e integradas ferramenta Photran. As tcnicas automatizadas so utilizadas em aplicaes escritas nesta linguagem, de forma a avaliar seu funcionamento e valid-las, para que elas possam ser utilizadas em qualquer aplicao escrita em linguagem Fortran pela comunidade de usurios do IDE Eclipse.

Palavras-chave: Refatorao; Fortran.

ABSTRACT

Trabalho de Graduao Undergraduate Program in Computer Science Universidade Federal de Santa Maria INCORPORATION OF NEW REFACTORINGS FOR FORTRAN LANGUAGE IN ECLIPSE IDE Author: Gustavo Rissetti Advisor: Profa Dra Andrea Schwertner Charo Refactoring is a software engineering technique that aims to perform internal changes in the application source code, without inuence on its functionality and results. This technique is not restricted only to source code and can be applied also in several other components of a software system, such as application design, analysis models, databases, among others. Refactoring is a permanently present task in the life cycle of software, and it seeks to improve non-functional aspects of applications, such as readability and reusability of code, including a possible gain in performance on the refactored software. Refactoring techniques are widely used in systems developed for the object orientation paradigm and are present in a number of automated tools that work in this paradigm. In scientic computing, in which large amounts of legacy code written in languages before the object-oriented programming paradigm, refactoring is not enough explored, mainly because these codes are written in a little commercialized language today. The Fortran language (FORmula TRANslation) is usually used in scientic applications, but lacks tools for code refactoring. In this context, we explore this deciency by automating refactorings, using the Photran framework (a plugin for editing Fortran code integrated into the Eclipse IDE). Some techniques are developed and integrated in Photran, based on the identication of open issues concerning actions of refactoring to Fortran code. The automated techniques are used in applications written in Fortran, to assess its operation and validate them to be used in applications written in Fortran by the user community of Eclipse IDE.

Keywords: Refactoring, Fortran.

LISTA DE FIGURAS

Figura 2.1 Visualizao do IDE Photran em execuo . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Figura 2.2 Visualizao de um trecho de cdigo Fortran e sua AST . . . . . . . . . . . . . . 25 Figura 2.3 Visualizao do VPG de um programa (OVERBEY, 2009) . . . . . . . . . . . 27 Figura 3.1 Exemplos de tipos de declaraes de variveis em Fortran . . . . . . . . . . . . Figura 3.2 Refatorao aplicada no cdigo da Figura 3.1 . . . . . . . . . . . . . . . . . . . . . . . . Figura 3.3 Exemplo de aplicao da refatorao Standardize Statements . . . . . . . . . Figura 3.4 Exemplo tpico do descuido de um programador . . . . . . . . . . . . . . . . . . . . . Figura 3.5 Aviso sobre como proceder com a refatorao . . . . . . . . . . . . . . . . . . . . . . . Figura 3.6 Aviso que o usurio deve fazer novamente a refatorao . . . . . . . . . . . . . . Figura 3.7 Aviso que todas as variveis no usadas j foram removidas . . . . . . . . . . Figura 3.8 Aviso sobre o pr-requisito do Implicit None . . . . . . . . . . . . . . . . . . . . . . . . . Figura 3.9 Exemplo de aplicao da refatorao Remove Unused Variables . . . . . . Figura 3.10 Exemplos de declaraes do tipo Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Figura 3.11 Exemplo tpico de uso incorreto de declarao do tipo data . . . . . . . . . . . Figura 3.12 Refatorao aplicada ao cdigo da Figura 3.11 . . . . . . . . . . . . . . . . . . . . . . . Figura 3.13 Exemplo de aplicao da refatorao Data To Parameter . . . . . . . . . . . . . Figura 3.14 Diferenas nas classes importadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Figura 3.15 Diferenas no mtodo processInterfaces(IFile le) . . . . . . . . . . . . . . . . . . . Figura 3.16 Diferenas no mtodo processCallsAndFunctions(IASTNode node) . . . Figura 3.17 Diferenas no mtodo getPosicaoDaVariavel(String s) . . . . . . . . . . . . . . . Figura 4.1 Tabela de tempos de execuo da aplicao . . . . . . . . . . . . . . . . . . . . . . . . . . Figura 4.2 Refatorao Standardize Statements no cdigo gauselim.f90 (Bloco 1) Figura 4.3 Refatorao Standardize Statements no cdigo gauselim.f90 (Bloco 2) Figura 4.4 Refatorao Standardize Statements no cdigo gauselim.f90 (Bloco 3) Figura 4.5 Refatorao Standardize Statements no cdigo gauselim.f90 (Bloco 4) Figura 4.6 Refatorao Remove Unused Variables no cdigo bstt.f90 (Bloco 1) . Figura 4.7 Refatorao Remove Unused Variables no cdigo bstt.f90 (Bloco 2) . Figura 4.8 Refatorao Remove Unused Variables no cdigo bstt.f90 (Bloco 3) . Figura 4.9 Refatorao Data To Parameter no cdigo bstt.f90 (Bloco 1) . . . . . . . . Figura 4.10 Refatorao Data To Parameter no cdigo bstt.f90 (Bloco 2) . . . . . . . . 32 33 33 34 36 37 37 37 38 40 41 42 42 44 45 46 47 50 53 53 54 54 55 55 56 56 57

LISTA DE ABREVIATURAS E SIGLAS

CPTEC Centro de Previso de Tempo e Estudos Climticos BRAMS Brazilian Regional Atmospheric Modeling System INPE ANSI IDE ASA UML CDT GCC EPL VPG AST Instituto Nacional de Pesquisas Espaciais American National Standards Institute Integrated Development Environment American Standards Association Unied Modeling Language C/C++ Development Tools GNU Compiler Collection Eclipse Public Licence Virtual Program Graph Abstract Syntax Tree

UFSM Universidade Federal de Santa Maria

SUMRIO

1 INTRODUO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 Contextualizao e Justicativas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Objetivos e Contribuies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Organizao do Texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 FUNDAMENTAO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Refatorao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Refatorao versus Otimizao de Cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Eclipse IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 Photran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1 Photran: AST e VPG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.2 Infraestrutura do Photran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6 Sumrio do captulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 REFATORAES PARA FORTRAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 Padronizar Declaraes (Standardize Statements) . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 Motivao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.2 Mecnica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.3 Implementao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.4 Exemplo de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Remover Variveis No Utilizadas (Remove Unused Variables) . . . . . . . . . . . 3.2.1 Motivao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2 Mecnica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.3 Implementao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.4 Exemplo de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Transformar declaraes do tipo Data em Parameter (Data To Parameter) 3.3.1 Motivao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.2 Mecnica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.3 Implementao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.4 Exemplo de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 Introduzir atributo INTENT (Introduce INTENT ) . . . . . . . . . . . . . . . . . . . . . . . 3.4.1 Motivao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.2 Mecnica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.3 Implementao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5 Sumrio do captulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12 13 15 16 17 17 19 20 21 22 24 26 29 30 31 31 31 32 32 34 34 35 35 38 38 39 39 40 41 43 43 44 44 45

4 AVALIAO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Avaliao de Desempenho: Anlises Micrometeorolgicas . . . . . . . . . . . . . . . 4.2 Avaliao das refatoraes em diferentes verses do Fortran . . . . . . . . . . . . 4.2.1 Eliminao Gaussiana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.2 Ajuste de Curvas (Curve Fitting) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Trabalhos Relacionados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4 Sumrio do captulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

48 49 51 52 53 56 58

CONSIDERAES FINAIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

REFERNCIAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 APNDICE A CDIGO FONTE DAS IMPLEMENTAES . . . . . . . . . . . . . . . A.1 Standardize Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.1.1 Interface com o usurio (StandardizeStatementsAction.java) . . . . . . . . . . . . . . A.1.2 Arquivo de ao da refatorao (StandardizeStatementsRefactoring.java) . . A.2 Remove Unused Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2.1 Interface com o usurio (RemoveUnusedVariablesAction.java) . . . . . . . . . . . . A.2.2 Arquivo de ao da refatorao (RemoveUnusedVariablesRefactoring.java) A.3 Data To Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.3.1 Interface com o usurio (DataToParameterAction.java) . . . . . . . . . . . . . . . . . . . A.3.2 Arquivo de ao da refatorao (DataToParameterRefactoring.java) . . . . . . A.4 Introduce INTENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.4.1 Interface com o usurio (IntroduceIntentAction.java) . . . . . . . . . . . . . . . . . . . . . A.4.2 Arquivo de ao da refatorao (IntroduceIntentRefactoring.java) . . . . . . . . . 67 67 67 68 72 72 73 76 76 78 83 83 85

INTRODUO

Quando se considera o histrico das Tecnologias da Informao hoje utilizadas, nos deparamos com cdigos empregados em grandes centros que, tipicamente, tm dcadas de desenvolvimento, sendo compostos por centenas de milhares de linhas de cdigo e programados por diversas equipes diferentes, cada uma utilizando tcnicas de programao e costumes diferentes. Um efeito direto deste histrico o uso de uma linguagem de programao antiga. Essas linguagens antigas possuem alguns estilos e tcnicas de programao que, atualmente, so consideradas perigosas, dicultando a leitura de cdigo e a identicao de possveis erros de programao, assim como o processo de manuteno do cdigo, que fundamental durante todo o ciclo de vida do software. Muitas vezes, a opo de reprogramar todo o cdigo descartada, devido ao custo dessa recodicao ser muito elevado. Assim, uma maneira de contornar e melhorar tal problema, em geral, consiste em utilizar tcnicas de reengenharia de software, incluindo tcnicas de refatorao de cdigo fonte. Refatorao uma tcnica de engenharia de software que visa modicar um sistema para melhorar a estrutura interna do seu cdigo, sem alterar o seu comportamento externo (resultados, funcionalidades e sadas). Essa tcnica est permanentemente presente no ciclo de vida de uma aplicao e vem sendo amplamente utilizada nas linguagens de orientao a objetos mais recentes, como Java (FOWLER, 2004). Atualmente, um vasto nmero de refatoraes podem ser encontradas catalogadas, porm, a maioria dessas destinamse a linguagens mais recentes, voltadas ao paradigma da orientao a objetos, havendo uma carncia de refatoraes para linguagens mais antigas, como Fortran, por exemplo (FOWLER, 2009). Fortran uma linguagem de programao voltada para aplicaes cientcas, desenvolvida a partir da dcada de 1950 e que continua a ser usada. O nome tem como origem

13

a expresso FORmula TRANslation ou Translator, sendo que essa linguagem usada principalmente em Cincia da Computao e em Clculo Numrico. Diversos programas utilizados para aplicaes de larga escala, que visam obter um bom desempenho, foram escritos na linguagem Fortran. Devido carncia de recursos para refatorao em linguagens mais antigas, nesse Trabalho de Concluso de Curso optou-se por estudar possibilidades de refatorao de programas escritos em Fortran, para melhorar a qualidade do cdigo existente de aplicativos largamente utilizados com uma maior facilidade, sem depender de muito trabalho manual. At ento, a grande maioria das refatoraes voltadas para tal linguagem eram feitas manualmente, sem um processo automatizado. Este trabalho visa dar continuidade a um trabalho desenvolvido junto ao Mestrado em Computao do Programa de PsGraduao em Informtica da UFSM, que tambm tinha o objetivo de gerar processos automatizados de refatorao para a linguagem Fortran, utilizando o IDE Eclipse e o plugin Photran (BONIATI, 2009). Em seu trabalho (BONIATI, 2009; BONIATI; CHARAO; STEIN, 2009), Bruno Batista Boniati explorou tcnicas de refatorao para programas Fortran de alto desempenho, desenvolvendo quatro tcnicas de refatorao para Fortran, com o objetivo de fazer a evoluo da linguagem, melhorar o projeto de cdigo e explorar construes de cdigo que oferecem melhor desempenho. As tcnicas de refatorao implementadas em seu trabalho foram nomeadas, no Photran, como Replace Obsolete Operators (integrada ocialmente ao Photran), Introduce INTENT, Extract Subroutine e Loop Unrolling. Neste trabalho so desenvolvidas trs novas refatoraes para Fortran, dando continuidade ao trabalho iniciado por Bruno Batista Boniati. Os objetivos principais das refatoraes implementadas aqui consistem em melhorar a legibilidade do cdigo e gerar possveis ganhos de desempenho na execuo da aplicao refatorada.

1.1 Contextualizao e Justicativas


O processo de evoluo uma propriedade natural e que sempre est presente no processo de desenvolvimento de software. Normalmente, espera-se que um determinado aplicativo de software seja gerado a partir de um bom projeto, com planejamentos, estudos de caso, e estruturas necessrias para atingir a meta do mesmo, sendo posteriormente codicado. Durante o ciclo de vida, normalmente, necessrio que o aplicativo passe

14

por alguma evoluo, seja para adicionar um novo requisito ou para alterar alguma das funcionalidades existentes. Porm, em alguns casos, pode ocorrer que a aplicao no esteja preparada para receber novos requisitos ou suportar adaptaes em suas funcionalidades, e, dependendo da forma como as alteraes so feitas, elas podem acabar degradando a qualidade e enfraquecendo a relao da aplicao com o objetivo descrito no projeto original. Ao longo do processo de desenvolvimento ou manuteno de software, comum que mudanas em requisitos favoream a presena de cdigo mal escrito, na medida em que os programadores tm de adaptar o cdigo s novas funcionalidades, muitas vezes usando tcnicas de programao consideradas inadequadas. Com a introduo de cdigos ilegveis dicultada mais ainda a manuteno do software, que passa a ser incompreensvel por grande parte dos programadores. Uma medida a ser tomada para melhorar a qualidade desse cdigo a reengenharia de cdigo fonte e o uso de tcnicas de refatorao, que podem fazer com que o cdigo que otimizado e com legibilidade melhorada. O objetivo principal do uso da refatorao melhorar atributos de qualidade da aplicao tais como legibilidade, simplicidade, organizao e desempenho. Embora possam ser aplicadas manualmente sobre o cdigo fonte, a facilidade no uso de refatoraes se d quando as tcnicas de refatorao so automatizadas por meio de ferramentas que atuam sobre o cdigo fonte previamente escrito (ROBERTS, 1999). Neste caso, pode haver a necessidade de se utilizar ferramentas especcas para a linguagem de programao em que a aplicao foi escrita. Linguagens estruturadas, mais antigas, e pouco difundidas comercialmente na atualidade, possuem poucas e raras ferramentas, como o caso do Fortran, caracterizada por ser uma linguagem de programao amplamente utilizada no meio cientco e pioneira na adoo do paradigma imperativo (NYHOFF; LEESTMA, 1997). A grande quantidade de cdigos Fortran legados que permanecem sendo utilizados passam por processos manuais de refatorao, pois existem poucas ferramentas que auxiliam o trabalho com essa linguagem, o que justica o quo necessrio o desenvolvimento de tcnicas automatizadas para a refatorao de cdigos fonte em linguagem Fortran. A lacuna existente entre a quantidade de cdigo legado escrito em Fortran (em especial de aplicaes cientcas que exigem alto desempenho) e as raras tcnicas e ferramentas de refatorao existentes para esta linguagem, servem de motivao para a realizao deste

15

trabalho de pesquisa, pois visa-se obter uma melhora no aspecto relacionado s facilidades de refatorao dos aplicativos escritos em Fortran. Um cdigo fonte pode ser melhorado atravs de sucessivas refatoraes, sem perder sua funcionalidade. Porm, para que isso seja possvel, necessrio que a linguagem sendo trabalhada possua ferramentas de auxlio que ofeream mecanismos automatizados de refatorao, para que essa possa ser aplicada em larga escala e possa ser aplicada em sistemas de software de grande porte, o que acontece na maioria dos casos. Na literatura possvel encontrar diveras catalogaes de refatoraes independentes de linguagem, descritas muitas vezes em linguagem natural. A catalogao de tcnicas de refatorao uma atividade que pode ser desenvolvida de forma genrica, no associada a uma linguagem ou a um paradigma especco. Assim, possvel descrever os objetivos, pr-requisitos, limitaes e a prpria mecnica de funcionamento de uma tcnica de refatorao usando-se a linguagem natural (DE, 2004). A utilizao de ferramentas com automatizaes voltadas refatorao garantem uma reduo do risco de erros e inconsistncias, alm de reduzir tambm o trabalho e o custo de desenvolvimento de software (FOWLER, 2004). A refatorao automatizada por ferramentas torna a ao de refatorar cada vez menos separada da atividade de programar. Refatorar manualmente uma atividade cara, que, por vezes, justicada pelo seu alto custo, no feita. O objetivo de automatizar refatoraes reduzir o custo do processo de reestruturao de cdigo.

1.2 Objetivos e Contribuies


As principais contribuies deste trabalho so a identicao e automatizao de tcnicas de refatorao para linguagem Fortran na ferramenta Photran (um plugin para edio de cdigo Fortran do IDE Eclipse). O Photran um projeto mantido pela Eclipse Foundation sob licena EPL (Eclipse Public License) e desenvolvido, inicialmente, por um grupo de pesquisadores ligados Universidade de Illinois em Urbana-Champaign (EUA) e ao Laboratrio Nacional de Los Alamos (EUA) (ECLIPSE.ORG, 2009a,b). Foram automatizadas e integradas ferramenta Photran trs tcnicas: Padronizao na Declarao de Variveis (Standardize Statements), Remoo de Variveis no Utilizadas (Remove Unused Variables) e Transformao de Declaraes do Tipo Data em Declaraes do Tipo Parameter (Data To Parameter). Tambm foi feita uma atualizao da

16

refatorao Introduce INTENT (BONIATI, 2009), para que funcionasse na nova verso do Photran. Para validar e avaliar o impacto da utilizao das tcnicas de refatoraes automatizadas desenvolvidas nesse trabalho, foram usados dois programas de cunho cientco, que esto contidos no projeto org.eclipse.photran-samples, distribudo juntamente com o Photran, sendo desenvolvidos na linguagem Fotran 90. Tambm foi utilizada uma aplicao cedida pelo Laboratrio de Micrometeorologia vinculado Universidade Federal de Santa Maria, desenvolvida na linguagem Fortran 77, que usada intensamente no laboratrio para fazer anlises micrometeorolgicas.

1.3 Organizao do Texto


Este trabalho est organizado da seguinte maneira: o Captulo 2 apresenta uma reviso bibliogrca do tema central do trabalho, incluindo alguns requisitos necessrios para que uma tcnica de refatorao seja automatizada, apresentando tambm os recursos e caractersticas do Photran. O Captulo 3 detalha as caractersticas de implementao de algumas tcnicas de refatorao que foram identicadas durante a realizao do trabalho. Para cada tcnica descreve-se sua motivao, sua mecnica, assim como sua implementao. No Captulo 4 so realizados estudos de caso com a utilizao das tcnicas de refatorao automatizadas em aplicaes reais. Nesse captulo so identicadas oportunidades de refatorao do cdigo fonte dessas aplicaes e so avaliados os benefcios detectados no uso das tcnicas. Alguns trabalhos relacionados com o assunto de refatorao em Fortran e em outras linguagens de programao, assim como em outros componentes de um sistema de software, tambm podem ser observados nesse captulo. Por m, no Captulo 5, apresentam-se as consideraes nais do trabalho e, discutem-se algumas sugestes para a sua continuidade.

2 FUNDAMENTAO

Neste captulo so descritos alguns conceitos que formaram o embasamento terico necessrio para o desenvolvimento deste trabalho.

2.1 Refatorao
Refatorao pode ser denida como uma alterao feita na estrutura interna de um software para torn-lo mais fcil de ser entendido e menos custoso de ser modicado, sem alterar o seu funcionamento aparente. Refatorar signica, portanto, reestruturar um software, aplicando-lhe uma srie de modicaes sem alterar o seu comportamento observvel, como funcionalidades, entradas, sadas e resultados. O termo refatorar faz parte de um domnio de pesquisa mais amplo, relacionado reestruturao de software (GRISWOLD; NOTKIN, 1993). Comumente, empregado para caracterizar reestruturaes realizadas em software desenvolvido sob o paradigma da orientao a objetos. A idia chave redistribuir classes, variveis e mtodos atravs da hierarquia (estrutura) de software, de forma a facilitar futuras adaptaes e extenses (MENS; TOURW, 2004). Em geral, so alteraes simples que atuam sobre caractersticas no funcionais de software, como por exemplo, extensibilidade, modularidade, reusabilidade, complexidade e ecincia. Espera-se que uma ferramenta destinada a fazer refatoraes automatizadas esteja integrada a ambientes de desenvolvimento de software. Uma ferramenta para automatizao de tcnicas de refatorao precisa contemplar pelo menos os seguintes requisitos (ROBERTS; BRANT; JOHNSON, 1996): Representao abstrata do programa: a ferramenta deve oferecer a representao abstrata do programa por meio de uma rvore sinttica; Banco de dados do programa: desejvel que a ferramenta guarde de forma atu-

18

alizada um conjunto de informaes ligadas representao abstrata do programa; Corretude: ao nal da refatorao a aplicao deve preservar o mesmo comportamento que tinha antes de sofrer a refatorao (CORNLIO, 2004). A ferramenta deve dispor de recursos para minimamente detectar a introduo de um erro (e permitir desfazer as alteraes). Uma aplicao que esteja funcionando corretamente tambm pode estar necessitando de reestruturaes internas, pois pode conter falhas de projeto. Se o projeto falho e o cdigo ruim e mal estruturado, ento mesmo que a aplicao esteja atendendo corretamente aos usurios, ela poderia ser refatorada e o projeto seria corrigido. Nesse sentido, a refatorao insiste em atributos de qualidade de software que so menos tangveis, mas decisivos, como projeto, simplicidade, melhoria na compreenso do cdigo fonte, legibilidade, dentre outras. Algumas das caractersticas que podem ser citadas como indicadores de necessidade de refatorao so: mtodos ou classes muito extensos, mtodos com excessivos parmetros, falta de clareza ou legibilidade do cdigo. Tambm pode-se descrever algumas situaes para as quais recomendvel a utilizao de refatorao (FOWLER, 2004): Adio de um novo recurso: quando um novo recurso precisa ser adicionado ao software, primeiramente ele deve passar por uma preparao, que tambm pode ser feita atravs de outras refatoraes, como reorganizao do cdigo, extrao de subrotinas, etc. Correo de um erro (bug): quando um erro conhecido, na medida em que se pode utilizar um algoritmo que contenha a correo, pode-se, muitas vezes, simplicar esse algoritmo, diminuindo o tamanho do cdigo total e tambm diminuindo o custo de processamento de tal algoritmo. Reviso do cdigo: quando o cdigo base examinado, uma das metas deve ser simplicar a estrutura do cdigo e os algoritmos no contexto da aplicao como um todo. As tcnicas de refatorao so geralmente simples e, quando aplicadas isoladamente, produzem pequenas modicaes notveis no cdigo. Uma boa melhoria em um software se d realmente quando diversas tcnicas de refatorao so aplicadas, pois a aplicao

19

dessas tcnicas cumulativa, e juntando-se um conjunto de pequenas melhorias, obtmse no nal uma grande melhoria, que resulta em um cdigo melhor estruturado e mais legvel. Tambm possvel que existam inter-relaes entre tcnicas de refatorao, por exemplo: para que determinada tcnica seja aplicada pr-requisito que mais alguma ou algumas tcnicas sejam previamente aplicadas. Como exemplo de refatoraes sucessivas, pode-se citar o caso da refatorao Introduce INTENT, que tem como pr-requisito a aplicao da refatorao Introduce Implicit None (BONIATI, 2009). Uma importante recomendao que se deve considerar antes da refatorao de software a existncia de um conjunto de testes, preferencialmente automatizados (DEURSEN et al., 2001). A execuo de um teste automatizado antes e depois de se aplicar uma refatorao poder indicar se houve ou no a adio de alguma falha ao cdigo refatorado. Embora o termo refatorao tenha origem na orientao a objetos, o seu conceito pode ser usado para o paradigma estruturado, contendo algumas limitaes. Em linguagens desse paradigma, os uxos de controle e de dados so fortemente interligados, dicultando assim a manipulao do cdigo para ser refatorado (DE, 2004). Em geral, reestruturaes em cdigos no orientados a objeto so limitadas no nvel de subprograma, bloco de cdigo ou entidades (variveis, por exemplo). Existem, contudo, tcnicas e ferramentas que atuam sobre paradigmas no orientados a objetos, como o caso de um plugin do Eclipse que atua sobre cdigo fonte Fortran, o Photran, que utilizado no desenvolvimento deste trabalho.

2.2 Refatorao versus Otimizao de Cdigo


Muitas vezes o termo refatorao confundido com a otimizao de cdigo, que feita diretamente pelo compilador. A refatorao um processo semi-automtico, que normalmente necessita da interveno do usurio para obter informaes necessrias a sua execuo, como o nome de um novo mtodo, por exemplo. As refatoraes so feitas normalmente atravs do uso de IDEs de programao que oferecem esse recurso de forma automatizada (semi-automticas), atravs de menus, para facilitar o seu uso ao programador. J a otimizao de cdigo acontece na etapa nal na gerao de cdigo pelo compilador, de forma totalmente automatizada, sem a interveno do usurio. Como o cdigo

20

gerado atravs da traduo orientada a sintaxe contempla expresses independentes, diversas situaes contendo sequncias de cdigo inecientes podem ocorrer. O objetivo principal da otimizao de cdigo consiste em aplicar um conjunto de heursticas para detectar tais sequncias e substitu-las por outras que removam as situaes de inecincia, normalmente resultando em melhora de desempenho da execuo da aplicao (RICARTE, 2008). As tcnicas de otimizao que so usadas nos compiladores, assim como as refatoraes, devem manter as caractersticas do programa original. Tambm devem ser capazes de capturar a maior parte das possibilidades de melhoria do cdigo dentro dos limites razoveis do grau de otimizao escolhido. Em geral, os compiladores permitem especicar qual o grau de otimizao desejado no processo de otimizao. Por exemplo, no compilador GCC (GNU Compiler Collection) (GNU, 1999) h opes na forma -O0, -O1, -O2, -O3 e -Os, sendo que a opo -O0 signica nenhuma otimizao e a opo -O3 signica a mxima otimizao (aumentando o tempo de compilao). A opo -Os indica que o objetivo da otimizao reduzir a ocupao de espao em memria.

2.3 Eclipse IDE


O Eclipse (ECLIPSE.ORG, 2009a) um IDE de desenvolvimento que tem suporte para diversas linguagens de programao, como C, C++, Java, e recentemente Fortran, com o uso do plugin Photran, que visto na seo 2.5. Para a programao em Fortran, existe o plugin Photran, que desenvolvido sobre o plugin CDT (C/C++ Development Tools) (ECLIPSE.ORG, 2009c), utilizando a maioria dos recursos j disponves nele, como interfaces grcas, interao com o usurio e gerenciamento de projetos. Porm, o menu de refatorao para projetos Fortran possui poucas alternativas, e as refatoraes disponveis por padro no Photran so bastante simples. O motivo da escolha do Eclipse IDE e o plugin Photran como ferramentas para o desenvolvimento deste trabalho justicado pela inteno de dar continuidade a um trabalho j iniciado durante o mestrado de Bruno Batista Boniati (BONIATI, 2009). Bruno Batista Boniati usou as mesmas ferramentas em seu trabalho, pois as mesmas possuem a vantagem de ser software livre, permitindo incluir modicaes, e possuem um framework pronto para receber novas funcionalidades, como refatoraes automatizadas para Fortran, que o alvo deste trabalho.

21

2.4 Fortran
Com o advento do Fortran, foi possibilitado que programas fossem escritos mais rapidamente que quando se trabalhava apenas com Assembler, por exemplo, com somente uma pequena perda de ecincia no processamento, uma vez que todo cuidado era dedicado na construo do compilador. Pode-se dizer tambm que o Fortran foi determinante na evoluo da programao, na medida em que os programadores substituram o Assembler por uma linguagem de programao de mais alto nvel, com alto desempenho, assim, concentrando-se mais na soluo do problema em questo. A tarefa da programao no estava mais restrita a um pequeno nmero de programadores especialistas. O Fortran disseminou-se rapidamente, principalmente nas reas da fsica, engenharia e matemtica, uma vez que satisfazia a necessidade de os cientistas programarem em uma linguagem de programao de alto desempenho. Inevitavelmente, dialetos da linguagem foram desenvolvidos, os quais levaram a problemas quando havia necessidade de se trocar programas entre diferentes computadores. Em 1966, aps quatro anos de trabalho, a Associao Americana de Padres (American Standards Association, ASA), posteriormente Instituto Americano Nacional de Padres (American National Standards Institute, ANSI) originou o primeiro padro para uma linguagem de programao, o Fortran 66 (ou Fortran IV). Essencialmente, era um subconjunto comum de vrios dialetos, de tal forma que cada dialeto poderia ser reconhecido como uma extenso do padro. Aqueles usurios que desejassem escrever programas portveis deveriam evitar as extenses e restringir-se ao padro. O Fortran uma linguagem de programao imperativa, baseada em um controle sequencial do uxo de execuo composto por construes de desvio como procedimentos e funes. As verses atuais da linguagem permitem vrias caractersticas da programao orientada a objetos. H um grande legado de aplicaes cientcas escritas em Fortran. Geralmente, so aplicaes que durante anos sofreram estudos e otimizaes, e que executam tarefas especializadas, como anlises climticas, por exemplo. O BRAMS (Brazilian Regional Atmospheric Modeling System), aplicativo para anlise de modelos climticos, mantido pelo CPTEC (Centro de Previso de Tempo e Estudos Climticos) do INPE (Instituto Nacional de Pesquisas Espaciais), um exemplo de aplicao de alto desempenho escrita

22

em linguagem Fortran. Desempenho a palavra-chave que explica a perpetuao histrica de Fortran. A linguagem sofreu vrias revises ao longo do tempo, ganhou bibliotecas ricas e otimizadas. Uma das suas principais vantagens, considerando a computao de alto desempenho (muito utilizada em aplicaes de cunho cientco), a existncia de operaes para tratamento de dados multidimensionais que normalmente no so encontradas de forma nativa em outras linguagens de programao (KOFFMAN; FRIEDMAN, 1996). Pelo fato de o domnio da aplicao do Fortran ser bastante especco e ligado pesquisa cientca e no ao mercado, h uma lacuna entre a quantidade de cdigo legado escrito em Fortran e ferramentas que oferecem tcnicas automatizadas de refatorao existentes para essa linguagem.

2.5 Photran
Photran (ECLIPSE.ORG, 2009b) um plugin desenvolvido para o IDE Eclipse para dar suporte programao em linguagem Fortran, com nfase na refatorao automatizada de cdigos Fortran (Figura 2.1) (CHEN; OVERBEY, 2008). O Photran um IDE para Fortran 77, 90, 95 e 2003, sendo uma extenso do CDT (C/C++ Development Tools).

Figura 2.1: Visualizao do IDE Photran em execuo Assim como outras ferramentas que so extenses do Eclipse, o Photran desenvol-

23

vido em linguagem Java e compe-se de plugins e recursos (features). Plugins adicionam funcionalidades ao Eclipse. Recursos so unidades de desenvolvimento (diversos plugins so empacotados em recursos, que so distribudos aos usurios). Arquiteturalmente, o projeto Photran divide-se em subprojetos onde cada um se constitui de um plugin ou um recurso. O IDE Photran j possui um analisador sinttico completo e uma representao de programa, com o Photran VPG (Virtual Program Graph), que gera uma AST (Abstract Syntax Tree) do cdigo fonte, permitindo a sua manipulao e edio, alm de outras utilidades (OVERBEY, 2009). No Photran, durante a edio do cdigo fonte, possvel visualizar atravs do recurso Outline View a estrutura hierrquica de elementos que compem o cdigo fonte. Existindo erros sintticos, possvel detect-los durante a escrita do cdigo (uma vez que a rvore sinttica ca impossibilitada de ser construda e a Outline View mostra uma mensagem de erro). Alm destes e outros recursos, normalmente presentes de uma forma ou de outra em IDEs ou editores de cdigo, Photran oferece uma infraestrutura para refatorao de cdigo fonte. Essa infraestrutura consiste de representaes abstratas do programa (que permitem navegar e alterar sua estrutura em alto nvel), mecanismos para visualizar e comparar diferenas antes e depois da refatorao e, ainda, meios de cancelar ou desfazer uma refatorao efetuada. No Photran (verso 4.0.5), as seguintes refatoraes so disponibilizadas por padro na IDE: Rename: pode ser vista como uma busca e substituio "inteligente", permitindo a alterao do nome de uma varivel, subprograma, etc. Introduce Implicit None: adiciona o comando IMPLICIT NONE em um arquivo e acrescenta declaraes explcitas para todas as variveis que foram declaradas implicitamente. Extract Local Variable: remove uma subexpresso de uma expresso maior e atribui essa subexpresso a uma varivel local, substituindo a subexpresso original por uma referncia a essa varivel. Esta refatorao geralmente usada para eliminar subexpresses repetidas ou introduzir nomes de variveis explicativos em

24

expresses complexas. Extract Procedure: remove uma seqncia de declaraes de um procedimento, coloca-as em uma nova subrotina, e substitui as declaraes originais por uma chamada para a nova subrotina. Esta refatorao usada, geralmente, para diminuir o tamanho dos procedimentos. Move Saved Variables to Common Block: cria um COMMON BLOCK para todas as variveis do tipo save de um subprograma. As declaraes dessas variveis no subprograma no sero mais do tipo save. Replace Obsolete Operators: substitui todas as utilizaes dos antigos operadores de comparao (como .LT. e .EQ.) por seus equivalentes mais recentes (como smbolos < e ==), e acrescenta declaraes explcitas para todas as variveis que foram declaradas implicitamente. 2.5.1 Photran: AST e VPG Uma rvore sinttica abstrata (AST) uma estrutura para representao do cdigo do programa. Ela composta por uma raiz da qual so derivados vrios ns que, por sua vez, podem ser compostos de outros ns. O ltimo nvel dessa rvore, normalmente, representa os tokens da linguagem, com ns que caracterizam os operadores da linguagem de programao, por exemplo (JONES, 2003). Cada n classicado de acordo com seu funcionamento e suas aes. Por exemplo, um n do tipo declarao derivar outros ns que representaro, por exemplo, o nome da varivel declarada e o tipo da mesma, podendo ainda conter um valor para a inicializao da varivel. A construo de uma AST requer a existncia de um analisador sinttico especco para a linguagem de programao com a qual se deseja trabalhar. Caso o cdigo fonte no possa ser decomposto segundo a estrutura gramatical, o processo de anlise sinttica acusa um erro de sintaxe. Um analisador sinttico responsvel por validar a estrutura de um cdigo fonte (no caso deste trabalho, escrito em linguagem Fortran) e gerar uma sequncia de derivao, ou seja, uma rvore sinttica abstrata (AST). Uma AST uma estrutura hierrquica na qual seus ns decompem-se em conjuntos de ns lhos (terminais ou no terminais). Em geral, os ns terminais representam tokens (comandos, expresses, operadores, etc.) do cdigo fonte.

25

A AST uma pea chave para a automatizao de aes de refatorao, uma vez que ela possibilita ao desenvolvedor navegar pela estrutura do cdigo fonte, detectando correlaes entre seus ns e identicando oportunidades de refatorao (OVERBEY; JOHNSON, 2009). Quando disponibilizada uma estrutura de representao como a AST, a ao de refatorao consiste em introduzir as modicaes diretamente na AST, fazendo a incluso de ns, excluso de ns ou, ainda, alterando o posicionamento de determinados ns da rvore. O Photran oferece um recurso que possibilita ao programador visualizar em tempo real a AST enquanto est programando. Esse recurso disponibilizado atravs da Outline View. Na Figura 2.2 pode-se observar um cdigo simples em Fortran e sua AST no editor de texto do IDE Photran.

Figura 2.2: Visualizao de um trecho de cdigo Fortran e sua AST O analisador sinttico do Photran foi produzido utilizando-se da ferramenta para gerao de analisadores sintticos Ludwig (OVERBEY; JOHNSON, 2008, 2009). O projeto da ferramenta Ludwig originou-se a partir da idia de produzir analisadores sintticos e rvores sintticas abstratas com foco na simplicao e rapidez do processo de automatizao de refatoraes. Utiliza a notao EBNF (ISO, 1996) para a especicao da gramtica e produz o analisador sinttico em cdigo Java. Sua principal caracterstica a gerao de rvores sintticas abstratas que podem ser manipuladas, ou seja, cujos ns podem ser removidos, substitudos ou realocados de lugar, permitindo a partir dessa rvore reconstruir o cdigo fonte original (ou modicado) preservando at mesmo comentrios, espaos em branco, quebras de linha e formataes do programador. O Ludwig parte importante da ferramenta Photran e pea chave na implementao de refatoraes. O analisador sinttico do Photran, alm de fornecer a AST, providencia o VPG (Vir-

26

tual Program Graph), que outra estrutura muito importante, uma vez que possibilita a agregao de outras ligaes entre os ns da rvore sinttica abstrata, no representando necessariamente a hierarquia da rvore. Algumas das ligaes adicionais podem ser, por exemplo, um vnculo entre a utilizao de determinada varivel (em uma expresso) e sua respectiva declarao. por meio do VPG que se pode obter um conjunto rico de informaes para subsidiar a manipulao dos ns de uma AST. O VPG pode ser visto como um conjunto de arestas que ligam os ns de uma AST de forma no hierarquizada (OVERBEY, 2009). Na Figura 2.3 possvel observar um exemplo de um programa e seu VPG (OVERBEY, 2009). Os ns (elipses) com ligaes de linhas contnuas so os ns que compem a AST. Os ns retangulares representam os tokens no cdigo do programa fonte. As ligaes extras (em linhas tracejadas), que so rotuladas, transformam a AST em um VPG. Nesse exemplo, o VPG apresenta dois tipos de ligao, a binding, que liga referencias de variveis s suas respectivas declaraes e, scope of declaration, que liga cada declarao com o n que representa o seu escopo na AST. 2.5.2 Infraestrutura do Photran No Photran, para que seja possvel automatizar uma refatorao so necessrios trs passos: fazer uma pr-validao da ao a ser desenvolvida, fazer a manipulao da AST (a m de realizar as alteraes propostas) e fazer uma ps-validao para garantir a integridade da AST. A utilizao do framework do Eclipse e do plugin Photran possibilita atuar sobre o cdigo Fortran por meio da manipulao da AST e da utilizao da base de informaes existentes no VPG. Existem mtodos que possibilitam navegar sobre a AST, recuperar informaes acerca de seus ns e tokens e ainda executar operaes de atualizao sobre ela (remoo, adio ou substituio de ns). Para implementar e integrar uma ao de refatorao ao framework do Photran, necessrio estender o comportamento de algumas classes presentes no framework. A primeira responsvel por receber a chamada do usurio e associar a ao de refatorao com seu respectivo assistente. Essa classe deve estender a classe AbstractFortranRefactoringActionDelegate e deve implementar os mtodos de duas intefaces: IWorkbenchWindowActionDelegate, permitindo assim, que a chamada do usurio seja feita a partir do menu principal, e IEditorActionDelegate que permite ao usurio fazer a chamada a partir

27

Figura 2.3: Visualizao do VPG de um programa (OVERBEY, 2009) de um menu de contexto no prprio editor. A segunda classe a ser estendida o assistente (wizard) da refatorao. comum que uma ao de refatorao solicite ao usurio alguma informao adicional para que possa ser executada, como um novo nome para uma varivel, um nome para um novo mtodo, etc. Essa classe estendida de AbstractFortranRefactoringWizard e tem objetivo de fazer

28

a construo grca da janela do assistente. Seu mtodo construtor recebe como parmetro um objeto para a terceira classe necessria, que faz a ao de refatorao propriamente dita. A principal classe a ser codicada a ao da refatorao. Essa classe pode estender a superclasse SingleFileFortranRefactoring ou a superclasse MultipleFileFortranRefactoring, sendo que ambas so classes especcas do Photran. A primeira se destina a fazer refatoraes que so aplicadas a um arquivo por vez, que exigem entradas de dados pelo usurio, como a seleo de um trecho do cdigo fonte a ser refatorado, por exemplo. J a segunda destinada s refatoraes que podem ser aplicadas a lotes de arquivos, que no exigem entradas de dados pelo usurio, pois, normalmente, faz uma varredura do cdigo fonte fazendo alteraes independentes, como reindentao, eliminao de variveis no usadas, etc. Essas duas classes, por sua vez, estendem a classe AbstractFortranRefactoring, que tambm especca do Photran, e que estende a classe Refactoring, a qual faz parte do framework do Eclipse. Nessa classe (ao da refatorao), quatro mtodos precisam ser codicados: getName(): esse mtodo responsvel por fornecer o ttulo da refatorao para que possa ser utilizado em janelas e caixas de dilogo do Eclipse; doCheckInitialConditions(): esse mtodo serve para fazer uma pr-validao da AST e dos critrios exigidos pela ao de refatorao usada. O mtodo pode propagar uma exceo da classe PreconditionFailure indicando que alguma condio para a ao de refatorao no foi satisfeita e que a mesma no ser realizada; doCheckFinalConditions(): esse mtodo responsvel por fazer uma ps-validao, que conrma ou no as alteraes aplicadas sobre a AST. Assim como o item anterior, esse mtodo pode propagar uma exceo da classe PreconditionFailure indicando que alguma condio para a ao de refatorao no foi satisfeita e que a mesma no ser realizada; doCreateChange(): esse mtodo realiza a refatorao propriamente dita, fazendo as modicaes na AST, caso a pr-validao tenha sido positiva. Ao trmino de tais modicaes, este mtodo chama dois outros mtodos, o addChangeFromModiedAST() que tem o objetivo de adicionar as modicaes feitas AST utilizada

29

pelo Photran e o mtodo releaseAllASTs(), visando forar o Photran a atualizar os controles visuais da AST assim como sua validao. Aps realizadas as implementaes dessas classes, necessrio alterar o arquivo manifest (plugin.xml) para indicar ao Eclipse que existem novos pontos de extenso que precisam ser disponibilizados.

2.6 Sumrio do captulo


Nesse captulo foi possvel entender melhor o conceito de refatorao, esclarecendo quais so suas vantagens e quais so suas possibilidades e indicaes de uso. Tambm foram apresentadas as ferramentas utilizadas no desenvolvimento deste trabalho, justicando os motivos de suas escolhas. Foi feita tambm uma pequena reviso bibliogrca sobre a linguagem de programao Fortran, a qual um dos motivos do desenvolvimento deste trabalho. Foram descritas em detalhes algumas caractersticas e recursos do plugin Photran, descrevendo-se tambm a sua infraestrutura e os requesitos necessrios para a automatizao e integrao de novas tcnicas de refatorao no mesmo. No Captulo 3 so detalhadas as caractersticas de implementao das refatoraes identicadas durante a realizao deste trabalho. Para cada tcnica descreve-se sua motivao, sua mecnica e sua implementao.

3 REFATORAES PARA FORTRAN

Neste captulo so apresentadas as tcnicas de refatorao desenvolvidas neste trabalho. As tcnicas utilizadas possuem diferentes objetivos, como legibilidade de cdigo (melhores prticas que favorecem a interpretao do cdigo, tornando-o mais simples) e desempenho (reestruturao do cdigo com o objetivo de melhorar o desempenho da aplicao). Nas prximas sees as tcnicas desenvolvidas so descritas em detalhes. Foram desenvolvidas trs tcnicas de refatorao para cdigo Fortran, com o propsito de melhorar a legibilidade do cdigo e melhorar o desempenho do mesmo, alm da atualizao de uma refatorao previamente criada, chamada no Photran de Introduce INTENT (BONIATI, 2009). O cdigo fonte referente s implementaes realizadas neste trabalho pode ser consultado no Apndice A. Na ferramenta Photran as tcnicas desenvolvidas neste trabalho foram nomeadas como: Standardize Statements; Remove Unused Variables; Data To Parameter. Aps concluir a refatorao Standardize Statements, vista na seo 3.1, foi dado incio pesquisa de como automatizar uma ao de refatorao capaz de remover variveis no utilizadas em um cdigo fonte (Remove Unused Variables), tratada na seo 3.2. A proposta para tal refatorao, assim como a proposta para a refatorao Data To Parameter, vista na seo 3.3, encontram-se em um dos itens do projeto Fortran Refactoring: FortiFact, que vem sendo desenvolvido em conjunto entre as instituies UFRGS, UFSM e CPTEC (INPE).

31

3.1 Padronizar Declaraes (Standardize Statements)


Voc possui um cdigo programado por diversas pessoas, com costumes diferentes de programao, resultando em diversos tipos de declaraes de variveis, prejudicando a legibilidade do cdigo. Essa refatorao faz uma padronizao das declaraes de variveis, melhorando a legibilidade do cdigo e normalizando as declaraes. 3.1.1 Motivao Na linguagem Fortran, as variveis podem ser declaradas de maneiras diferentes, ou seja, podem ser declaraes simples, onde apenas uma varivel declarada a cada comando, podendo ou no ter os tradicionais dois pontos (::) do Fortran, ou podem ser declaradas listas de variveis. Porm, como a linguagem permite tais tipos de declaraes de variveis, muitas vezes cdigos que so escritos por grandes equipes passam pelas mos de diferentes programadores, que tm hbitos diferentes de programar, e usam uma maneira diferente para declarao de variveis. Essa mistura de gneros de declaraes podem dicultar a leitura de cdigo, uma vez que uma imensa lista de variveis pode ser declarada, e quando o leitor do cdigo chega ao nal de tal lista, j no lembra mais qual era o tipo de declarao das variveis, por exemplo. A refatorao, nomeada no Photran de Standardize Statements tem o objetivo de fazer uma padronizao nas declaraes de variveis. 3.1.2 Mecnica Percorrer o cdigo fonte em busca de identicadores de declarao de variveis. Vericar se cada declarao encontrada simples ou uma lista de declarao. Se for uma lista de declarao, devem-se criar novas declaraes simples a partir dos elementos contidos na lista de declarao. Remover o identicador que contm a lista de declarao. Adicionar os dois pontos (::) nas declaraes simples. Compilar e testar o cdigo, vericando seu correto funcionamento. A refatorao est completa.

32

3.1.3 Implementao O processo de implementao contou com algumas facilidades providas pela AST. Com o mtodo ast.getRoot().getAllContainedScopes() possvel obter todos os escopos da rvore sinttica abstrata, e, assim, tem-se liberdade de percorrer e alterar um escopo por vez. Cada escopo percorrido com um lao de iterao, a m de achar ns do tipo ASTTypeDeclarationStmtNode. Quando um desses ns encontrado, constri-se uma lista de variveis, que preenchida com as variveis presentes na lista de declarao do n (o tamanho da lista pode variar de 1 a N elementos). Posteriormente, atravs do mtodo getTypeSpec() conseguido ter acesso ao tipo da declarao da(s) variveis do n, para ser usado na criao dos ns padronizados. Aps preencher a lista de variveis e ter posse do tipo da declarao, so criados novos ns contendo as novas declaraes agora padronizadas (declaraes simples, usando os dois pontos). Esses ns so adicionados no escopo da AST que est sendo alterado, abaixo dos ns originais. Aps a insero de todos os novos ns, as declaraes antigas (ns antigos), que no estavam padronizados, so removidos da AST, e as alteraes realizadas na refatorao so adicionadas ao cdigo fonte, atravs da chamada do mtodo addChangeFromModiedAST(). 3.1.4 Exemplo de uso Na Figura 3.1 podem ser observados alguns exemplos dos diferentes tipos de declaraes de variveis permitidos no Fortran:

Figura 3.1: Exemplos de tipos de declaraes de variveis em Fortran Se a refatorao Standardize Statements fosse usada na Figura 3.1, obteria-se o cdigo da Figura 3.2, que usa um padro xo de declarao e tornou-se um cdigo de maior legibilidade, com um padro normalizado de declaraes.

33

Figura 3.2: Refatorao aplicada no cdigo da Figura 3.1 Na Figura 3.3 possvel observar um exemplo da refatorao em execuo no Photran, na tela de Preview do editor. Observe que, aps a refatorao, o cdigo fonte apresentado cou com sua legibilidade ligeiramente melhorada, e possvel observar uma padronizao nas declaraes de variveis.

Figura 3.3: Exemplo de aplicao da refatorao Standardize Statements

34

3.2 Remover Variveis No Utilizadas (Remove Unused Variables)


Voc possui um cdigo com diversos blocos comentados, porm, as variveis usadas apenas nesses blocos comentados no foram comentadas ou eliminadas da seo de declaraes, podendo assim prejudicar a legibilidade do cdigo e aumentar o tamanho do cdigo executvel gerado. Essa refatorao elimina as variveis no utilizadas no cdigo fonte, melhorando sua legibilidade, podendo tambm diminuir o tamanho do cdigo executvel gerado. 3.2.1 Motivao Normalmente, quando se programa um software, podem sobrar variveis inutilizadas, muitas vezes, por descuido do prprio programador, que comenta algum trecho do cdigo que no ser mais utilizado, e esquece de comentar as declaraes das variveis que estavam contidas no bloco comentado. Um exemplo tpico de tal erro, ou descuido, pode ser observado na Figura 3.4, onde est clara a evidncia do esquecimento de variveis no utilizadas ao longo do cdigo.

Figura 3.4: Exemplo tpico do descuido de um programador Observe que a linha salientada da Figura 3.4 foi comentada, e assim as variveis area, radius, height e pi no foram mais utilizadas ao longo do cdigo, tornando-se uma situao clssica de esquecimento de comentar ou retirar a declarao das mesmas do incio do cdigo.

35

Tendo em vista que tais descuidos ocorrem com grande frequncia, essa refatorao foi criada com a nalidade de eliminar tais variveis. A eliminao dessas variveis possibilita diminuir o tamanho do cdigo executvel gerado, e tambm de grande valia quando se quer paralelizar o cdigo, uma vez que ter menos variveis facilita o controle dos acessos concorrentes na memria, gerando uma melhora no desempenho da execuo do software (quando o prprio compilador no elimina as variveis no utilizadas no processo de compilao) e melhorando a sua legibilidade. A refatorao responsvel por eliminar as variveis no usadas foi nomeada Remove Unused Variables no Photran. 3.2.2 Mecnica Vericar se o cdigo usa declaraes implcitas ou explcitas. Se as declaraes so implcitas necessrio transform-las em explcitas. Percorrer o cdigo fonte em busca de identicadores de declarao de variveis. Vericar cada varivel encontrada quanto ao nmero de referncias no cdigo fonte. Se alguma varivel vericada no possuir nenhuma referncia, deve-se removla do cdigo fonte. Compilar e testar o cdigo, vericando seu correto funcionamento. A refatorao est completa. 3.2.3 Implementao O processo de implementao contou com algumas facilidades providas pela AST do Photran. Com o mtodo ast.getRoot().getAllContainedScopes() possvel obter todos os escopos da rvore sinttica abstrata, e, assim, tem-se liberdade de percorrer e alterar um escopo por vez. Em cada escopo possvel obter a lista de todas as denies de variveis nele contidas, com o uso do mtodo scope.getAllDenitions(). Uma vez que essa lista de denies obtida, percorre-se a mesma em busca de denies de variveis locais, que so identicadas atravs do mtodo provido pelo Photran, denition.isLocalVariable(), que retorna verdadeiro caso a denio seja uma varivel local, ou retorna falso, caso contrrio.

36

Uma varivel possui uma lista de referncias, onde descrito quais referncias so feitas a ela no cdigo fonte. Uma vez encontrada a varivel local, necessrio obter-se essa lista, que com o uso do mtodo denition.ndAllReferences() se torna uma operao simples. Se o tamanho da lista de referncias for igual a um (a declarao da varivel contada como uma referncia, assim se o tamanho da lista de referncias for igual a um, signica que a varivel foi apenas declarada), a varivel no foi usada, e ela deve ser removida da AST, com o mtodo remove(), provido pelo framework do Photran. Porm, no Photran no possvel fazer mltiplas execues da mesma refatorao automaticamente, pois a AST modicada s atualizada em arquivo aps o usurio conrmar a sua ao de refatorao. Sendo assim, o usurio alertado, antes de fazer a refatorao, que necessrio aplicar o processo novamente para que todas as variveis no utilizadas sejam realmente removidas (como pode ser visto na Figura 3.5).

Figura 3.5: Aviso sobre como proceder com a refatorao Alm do aviso prvio quanto a refatorao, mostrada uma informao de quando necessrio ou no refazer a refatorao, na tela de informao, que visualizada antes de o usurio concordar com a aplicao das modicaes no cdigo (essa informao obtida pela varivel de status da refatorao). Nesta tela, como pode ser visto nas Figuras 3.6 e 3.7, o usurio ca ciente de quando deve fazer mais uma rodada da refatorao, ou quando todas as variveis no usadas foram removidas do cdigo fonte. Aps a remoo das variveis no usadas, as alteraes realizadas na refatorao so adicionadas ao cdigo fonte, atravs da chamada do mtodo addChangeFromModiedAST(). Um detalhe importante dessa refatorao, que ela possui como requisito necessrio

37

Figura 3.6: Aviso que o usurio deve fazer novamente a refatorao

Figura 3.7: Aviso que todas as variveis no usadas j foram removidas sua aplicao, que o cdigo fonte a ser refatorado seja Implicit None. Para isso, caso o usurio tente aplicar essa tcnica a um cdigo que no respeite esse pr-requisito, a mensagem da Figura 3.8 mostrada, indicando ao usurio que primeiramente ele deve usar a refatorao nomeada no Photran como Introduce Implicit None. Assim, o cdigo fonte estar obecendo o pr-requisito necessrio e poder ser refatorado para a eliminao das variveis.

Figura 3.8: Aviso sobre o pr-requisito do Implicit None

38

3.2.4 Exemplo de uso Na Figura 3.9 possvel observar um exemplo da refatorao em execuo no Photran, na tela de Preview do editor. Observa-se que, aps a refatorao, o cdigo cou com sua legibilidade ligeiramente melhorada, uma vez que aparecem nele apenas as variveis realmente utilizadas, no cando um cdigo poludo.

Figura 3.9: Exemplo de aplicao da refatorao Remove Unused Variables

3.3 Transformar declaraes do tipo Data em Parameter (Data To Parameter)


Voc possui variveis declaradas com a inteno de serem constantes, propagadas diretamente pelo compilador em tempo de compilao. Porm, devido a um erro de programao, essas variveis so declaradas como variveis estticas, necessitando acessos para obter o seu contedo, causando perda de desempenho na execuo da aplicao. Essa refatorao identica ocasies em que variveis so declaradas como estticas,

39

quando havia a inteno de serem declaradas como constantes (propagadas pelo compilador), fazendo a troca do tipo de declarao das mesmas, transformando-as em constantes. 3.3.1 Motivao No Fortran, uma varivel pode ser inicializada de diversas formas e, usualmente, em programas existem algumas variveis que so constantes, isto , tem o seu valor denido no incio do cdigo e ele nunca alterado, sendo apenas referenciado (propagado pelo compilador) para usar em clculos ou operaes em que ele seja requerido. No Fortran existe um atributo que serve para esse m, fazendo com que uma varivel seja inicializada e seja uma constante, a declarao (atributo) Parameter. Uma varivel declarada como parameter tem um valor constante que o compilador propaga diretamente em todo o cdigo fonte, porm, as vezes essa declarao confundida com a declarao do tipo data. Uma varivel do tipo data automaticamente save, ou seja, ela uma varivel esttica. Quando se pensa em paralelizar um cdigo fonte, a m de ganhar desempenho, as variveis estticas podem ser acessadas em concorrncia por vrias threads1 , causando uma complicao na programao. Por isso vantajoso usar parameter quando se quer apenas tornar uma varivel constante em todo o cdigo fonte. Tendo em vista que tais erros ocorrem com frequncia, essa refatorao, nomeada no Photran como Data To Parameter, foi criada com a nalidade de substituir essas declaraes do tipo data que so confundidas com as declaraes do tipo parameter. 3.3.2 Mecnica Percorrer o cdigo fonte em busca de variveis declaradas com o tipo Data. Quando alguma dessas variveis no sofre alterao do valor inicial deve-se: Criar uma nova varivel vazia do tipo Parameter; Nomear e inicializar a nova varivel com os valores da varivel Data; Remover a varivel declarada como Data do cdigo fonte. Compilar e testar o cdigo, vericando seu correto funcionamento. A refatorao est completa.
uma thread, ou linha de execuo em portugus, uma forma de um processo dividir a si mesmo em duas ou mais tarefas que podem ser executadas simultaneamente.
1

40

3.3.3 Implementao O processo de implementao desta tcnica de refatorao automatizada consiste em, primeiramente, obter todos os escopos do cdigo fonte, usando o mtodo do framework do Photran que retorna uma lista de escopos, ast.getRoot().getAllContainedScopes(). Para poder tranformar uma declarao do tipo data nome / valor / em uma declarao do tipo parameter ( nome = valor ), a varivel nome no pode ser alterada no programa, podendo ser apenas referenciada. Sendo assim, necessrio fazer uma vericao de todas as variveis que tiveram seu valor alterado no cdigo fonte, para ter certeza na hora de fazer a alterao do tipo de declarao que no seja transformada uma declarao do tipo data que tenha o seu valor alterado no cdigo fonte. Caso uma das variveis do tipo data tiver sido alterada, ela permanece sendo do tipo data. Com essa vericao uma lista de variveis que foram alteradas preenchida para poder ser referenciada na hora da aplicao das modicaes. Aps obtidas todas as referncias de variveis alteradas, cada escopo percorrido em busca de ns do tipo ASTDataStmtNode, que se referem a declaraes do tipo data. Alguns exemplos de declaraes do tipo data podem ser vistos na Figura 3.10.

Figura 3.10: Exemplos de declaraes do tipo Data Quando um n do tipo ASTDataStmtNode encontrado, necessrio percorr-lo em busca das declaraes contidas em sua lista de declaraes e valores (ASTDataStmtSetNode). Ento, faz-se uma comparao com os nomes das variveis contidas na lista do n e as variveis modicadas obtidas anteriormete. Caso alguma das variveis contida na lista do n no esteja na lista de variveis modicadas, signica que ela nunca foi modicada e, portanto, deve ser transformada em uma declarao do tipo parameter. A cada varivel encontrada que deve ter sua declarao modicada, criado um novo n na AST, contendo uma declarao do tipo parameter, com nome e inicializao idnticos aos da varivel que estava na lista do n tipo data.

41

Aps serem criados os novos ns, eles so adicionados ao corpo do escopo, e as variveis que foram adicionadas aos novos ns so removidas do n com declarao do tipo data. Assim, pode ser gerado um ganho de desempenho, uma vez que o valor das variveis que so constantes passam a ser propagados em todas as suas referncias pelo compilador, quando se est usando a forma de declarao correta. Aps a substituio das variveis do tipo data que no sofrem alterao no cdigo por variveis do tipo parameter, que se destinam a ser valores constantes, as alteraes realizadas na refatorao so adicionadas ao cdigo fonte, atravs da chamada do mtodo addChangeFromModiedAST(). 3.3.4 Exemplo de uso Na Figura 3.11 possvel observar um exemplo de uso de declaraes do tipo data e parameter. Observe que a ltima varivel est declarada como data, mas como ela no tem o seu valor modicado ao longo do cdigo, a sua declarao deveria ser do tipo parameter, que observado na Figura 3.12, onde o cdigo da Figura 3.11 passou pelo processo de refatorao Data To Parameter.

Figura 3.11: Exemplo tpico de uso incorreto de declarao do tipo data Na Figura 3.13 possvel observar um exemplo da refatorao em execuo no Photran, na tela de Preview do editor. Observe que, aps a refatorao, o cdigo cou com os tipos de declaraes corretos, mantendo os nomes e valores originais das variveis.

42

Figura 3.12: Refatorao aplicada ao cdigo da Figura 3.11

Figura 3.13: Exemplo de aplicao da refatorao Data To Parameter

43

3.4 Introduzir atributo INTENT (Introduce INTENT )


Essa refatorao foi desenvolvida durante o mestrado de Bruno Batista Boniati (BONIATI, 2009), com o objetivo de introduzir o atributo INTENT em declaraes de argumentos de subprogramas, sendo utilizada para especicar a inteno de uso de determinado argumento de um subprograma. Recentemente, o Photran sofreu uma atualizao que causou mudanas internas nas hierarquias de classes. Como essa tcnica de refatorao foi feita para a verso do plugin anterior atualizao, ela deixou de funcionar. Partindo deste princpio, neste trabalho foi feita a atualizao desta refatorao para que ela voltasse a funcionar na nova verso do Photran. 3.4.1 Motivao O atributo INTENT uma construo recente (verso 90 do Fortran) e utilizada para especicar a inteno de uso de determinado argumento em um subprograma. So trs formas possveis de indicar a inteno de uso de um argumento com o atributo INTENT (ADAMS et al., 2008): INTENT(IN): especica que o argumento est sendo utilizado para passar dados como entrada para o subprograma; INTENT(OUT): especica que o argumento est sendo usado para retornar resultados da chamada feita pelo programa e no pode ser usado para fornecer dados de entrada; INTENT(INOUT): especica que o argumento que est sendo passado dene um valor de entrada e se for alterado seu valor permanecer disponvel aps a execuo do subprograma. Com o uso do INTENT, permitido ao programador conhecer a inteno dos argumentos de um subprograma apenas pela sua interface, sem a necessidade de ler todo seu cdigo, favorecendo a legibilidade do mesmo. Tambm permite meios para o compilador realizar vericaes mais apuradas (detectar se o uso do argumento est inconsistente com a inteno declarada, por exemplo) e utilizar estratgias de otimizao. A principal motivao dessa refatorao, o fato de que existe uma grande quantidade de cdigo legado que despreza o uso de tal tcnica (o parmetro INTENT opcional e

44

foi adicionado linguagem Fortran em suas verses mais recentes). Da mesma forma, identicar de forma manual todas as chamadas a subprogramas e a inteno de utilizao de seus argumentos uma tarefa um tanto exaustiva, o que justica a necessidade de uma ao de refatorao automatizada. 3.4.2 Mecnica A mecnica desta refatorao consiste na introduo do atributo INTENT, que deve ser realizada aps a seleo, por parte do programador, de um subprograma do cdigo fonte (no caso de Fortran, um bloco SUBROUTINE ou FUNCTION ). Os parmetros do subprograma devem receber o atributo INTENT de acordo com a forma que so utilizados dentro do subprograma (referenciado, modicado, ou ambos). Em funo da utilizao que um argumento tem, pode-se denir e alterar seu comando de declarao para INTENT(IN) se ele apenas referenciado, INTENT(OUT) se ele apenas modicado ou INTENT(INOUT) se ele sofre modicaes e referenciado (antes de ser modicado). Um requisito importante da refatorao Introduce INTENT, que o subprograma que est sendo refatorado (ou o programa principal que o contm) precisa utilizar-se da declarao explcita de tipos (usar o comando IMPLICIT NONE exigindo que todas as declaraes explicitem o tipo de dado). Assim, se faz necessrio primeiramente usar a refatorao nomeada no Photran de Introduce Implicit None, para que essa condio seja satisfeita. 3.4.3 Implementao A implementao dessa refatorao permaneceu a mesma descrita no trabalho de Bruno Batista Boniati (BONIATI, 2009), exceto que foram feitas pequenas modicaes para adequar o cdigo nova verso do Photran. Os trechos modicados do cdigo, assim como explicaes devido s mudaas aplicadas podem ser observados nas Figuras 3.14, 3.15, 3.16 e 3.17.
// Na verso original da refatorao o seguinte import era usado: import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranRefactoring; // Na verso atualizada, o import acima foi substitudo pelo seguinte: import org.eclipse.photran.internal.core.refactoring.infrastructure.SingleFileFortranRefactoring;

Figura 3.14: Diferenas nas classes importadas

45 // Alteraes no mtodo processInterfaces(IFile le). Na verso original, quando havia uma // declarao composta, e um argumento estava entre ela, essa declarao era ignorada, e o // atributo INTENT no era adicionado na declarao da varivel. public void processInterfaces(IFile le){ ... if (d.isSubprogramArgument()) { ASTTypeDeclarationStmtNode a = getTypeDeclarationStmtNode(d.getTokenRef(). ndToken().getParent()); // Limitao ... s atua se a declarao for simples if (a.getEntityDeclList().size() == 1) { ASTAttrSpecNode at = getASTAttrSpecNode(a); spi.addParam(d.getDeclaredName(), at); } } ... } // Na verso atualizada da refatorao, quando ocorre de um dos argumentos estar em uma lista // de declarao, exibido um aviso, para que o usurio use a tcnica de refatorao // Standardize Statements, para que todas as variveis quem normalizadas, e seja possvel // introduzir corretamente os atributos INTENT. public void processInterfaces(IFile le){ ... if (d.isSubprogramArgument()) { ASTTypeDeclarationStmtNode a = getTypeDeclarationStmtNode(d.getTokenRef(). ndToken().getParent()); // S atua se a declarao for simples. if (a.getEntityDeclList().size() == 1) { ASTAttrSpecNode at = getASTAttrSpecNode(a); spi.addParam(d.getDeclaredName(), at); }else // Se alguma declarao for composta, necessrio padronizla usando a // refatorao Standardize Statements. fail("All Statements must be simple (integer :: a). To Standardize all \n" + "statements in le, use Standardize Statements Refactoring rst!"); } ... }

Figura 3.15: Diferenas no mtodo processInterfaces(IFile le)

3.5 Sumrio do captulo


Nesse captulo foram apresentadas as refatoraes implementadas neste trabalho. As trs tcnicas implementadas (Santadardize Statements, Remove Unused Variables e Data To Parameter) tiveram sua motivao, mecnica e implementaes descritas em detalhes. Foram mostradas tambm, as alteraes introduzidas na refatorao Introduce INTENT (BONIATI, 2009). O Photran passou por uma atualizao, aps a criao dessa refatora-

46 // Na verso original, quando se tratava do processamento de ns de subprograma, o trecho do // cdigo fonte era o que est apresentado abaixo: private void processCallsAndFunctions(IASTNode node){ ... if (node instanceof ASTCallStmtNode) { SubProgramInformation spi = new SubProgramInformation(((ASTCallStmtNode)node). getDataRef().get(0).getName().getText(), leInEditor.getName() ); for (IASTNode child1 : node.getChildren()) { if (child1 instanceof ASTSeparatedListNode){ IASTNode n_aux = (ASTSeparatedListNode)child1; for (IASTNode child2 : n_aux.getChildren()) { if (child2 instanceof ASTSectionSubscriptNode) { IASTNode n_aux2 = ((ASTSectionSubscriptNode)child2).getExpr(); if (n_aux2 instanceof ASTVarOrFnRefNode) spi.addParam(((ASTVarOrFnRefNode)n_aux2).getName().getName(). getText(), null); } } } } callProgram.add(spi); } ... } // Na verso atualizada da refatorao, houveram melhorias nesse trecho do cdigo, atravs de // melhorias implementadas na atualizao do Photran, como pode ser visto abaixo: private void processCallsAndFunctions(IASTNode node){ ... if (node instanceof ASTCallStmtNode) { SubProgramInformation spi = new SubProgramInformation(((ASTCallStmtNode)node). getSubroutineName().getText(), leInEditor.getName()); IASTListNode<ASTSubroutineArgNode> argumentos = ((ASTCallStmtNode)node). getArgList(); for(ASTSubroutineArgNode arg : argumentos){ ASTVarOrFnRefNode exp = (ASTVarOrFnRefNode)arg.getExpr(); spi.addParam(exp.getName().getName().getText(), null); } callProgram.add(spi); } ... }

Figura 3.16: Diferenas no mtodo processCallsAndFunctions(IASTNode node) o, e a mesma parou de funcionar, necessitando de manuteno para voltar a funcionar. No Captulo 4, so descritas as modalidades de testes realizados nas refatoraes desenvolvidas neste trabalho, com a nalidade de avali-las e valid-las. Foram feitos testes de funcionamento em diferentes verses da linguagem Fortran, atravs de cdigos For-

47 // Na verso original, o mtodo para buscar a posio do incio do nome de uma varivel era // como apresentado abaixo. Porm, nesse mtodo, quando existem comentrios antes da // declarao, ele deixa de funcionar, retornando a posio errada da varivel. int getPosicaoDaVariavel(String s){ int i, j; boolean comecou = false; i = 0; for (j=0; j<s.length(); j++){ if ( (s.charAt(j) == ) & (comecou)){ i = j; break; }else if (s.charAt(j) != ) comecou = true; } return i; } // Na verso atualizada, foi corrigido o problema do retorno errado da posio do nome da // varivel, cando como apresentado abaixo: int getVariablePosition(String s, String attr){ String[] coments = s.split("\n"); int size = coments.length 1; int i, j; boolean start = false; int attr_length = attr.length()1; for(int k=0; k<coments.length 1; k++) size += coments[k].length(); String statement = coments[coments.length 1]; i = 0; for (j=0; j<statement.length(); j++){ if ( (statement.charAt(j) == ) & (start)){ i = j; break; }else if (statement.charAt(j) != ) start = true; } if(attr_length < 0) attr_length = 0; return i + size + attr_length; }

Figura 3.17: Diferenas no mtodo getPosicaoDaVariavel(String s) tran distribudos juntamente com o Photran, assim como testes de anlise no impacto das refatoraes no desempenho de aplicaes usando uma aplicao de alto desempenho cedida pelo Laboratrio de Micrometeorologia vinculado Universidade Federal de Santa Maria. Ainda nesse captulo, feita uma breve comparao deste trabalho com outros correlatos, servindo tambm como uma forma de avaliao.

AVALIAO

Para avaliar o impacto da utilizao de tcnicas de refatorao em aplicaes de alto desempenho escritas em linguagem Fortran, o trabalho utilizou-se do cdigo fonte de uma aplicao cedida pelo Laboratrio de Micrometeorologia vinculado Universidade Federal de Santa Maria. O objetivo do estudo deste cdigo avaliar de que forma a utilizao de tcnicas de refatorao podem inuenciar no desempenho (de forma positiva ou negativa) desta aplicao, escrita em Fortran 77. A aplicao foi submetida a duas formas de compilao para a realizao dos testes, compilando-se, primeiramente, sem o uso de otimizaes do compilador, e posteriormente, compilando-se com o uso de otimizaes do compilador. O objetivo da aplicao dessas duas formas de compilao foi para analisar se o desempenho era afetado quando se utilizava a refatorao em conjunto com a otimizao. A metodologia utilizada para os testes de desempenho podem ser vistos na seo 4.1. Aps avaliado o impacto das refatoraes em aplicaes de alto desempenho, passouse a avaliar o comportamento das mesmas em diferentes cdigos Fortran, de diferentes verses da linguagem, com o objetivo de vericar o seu correto funcionamento nas verses do Fortran suportadas pelo plugin Photran. Para a realizao dos testes em cdigos de diferentes verses do Fortran, as refatoraes foram aplicadas nos cdigos Fortran contidos no projeto org.eclipse.photransamples, distribudo juntamente com o Photran. Nesse projeto esto contidos diversos cdigos fonte de Fortran 77, 90, 95 e 2003. Os principais cdigos do projeto org.eclipse.photran-samples utilizados para os testes foram os cdigos bstt.f90, que um programa que faz o clculo de distncias usando o mtodo do Ajuste de Curvas (Curve Fitting), e o cdigo gauselim.f90, que um programa que resolve um sistema de equaes lineares com o mtodo da Eliminao Gaussiana.

49

Os testes realizados nesses dois cdigos podem ser vistos em detalhes nas sees 4.2.1 e 4.2.2. Pode-se observar que os cdigos usados para os testes so de aplicaes cientcas, e como descrito durante este trabalho, cdigos como esses podem apresentar erros. Na seo 4.3 so mostrados alguns trabalhos relacionados com o assunto de refatorao, mostrando que tambm existem pesquisas sobre refatorao em outras linguagens de programao, salientando que as tcnicas de refatorao no esto restritas apenas ao uso em cdigos fonte, fazendo-se uma breve comparao dessas pesquisas com este trabalho, servindo tambm como uma forma de avaliao do mesmo.

4.1 Avaliao de Desempenho: Anlises Micrometeorolgicas


A micrometeorologia uma subdiviso das cincias atmosfricas que estuda fenmenos fsicos de pequena escala espao-temporal que ocorrem na camada atmosfrica que faz contato com a superfcie da Terra (com espessura de 1 km em mdia). Anlises micrometeorolgicas contribuem para a soluo de problemas de ordem ambiental bem como para a previso do tempo e do clima. Normalmente, as anlises micrometeorolgicas se utilizam de observaes de campo. O conjunto de dados coletados em estaes meteorolgicas passa por anlises e interpretaes demandando alto poder de processamento. A aplicao a ser estudada utilizada para processar conjuntos de dados de um dia de coleta (um arquivo com 100 MBytes em mdia). Ao nal do processamento, os dados processados so gravados em arquivos e resultam em aproximadamente 70 MBytes de resultados. A aplicao estudada importante para os experimentos do laboratrio, mas dado seu tempo de vida e algumas construes obsoletas utilizadas no seu desenvolvimento, apresenta uma alta complexidade de compreenso e manuteno, representando um problema quando novas funcionalidades ou anlises precisam ser adicionadas aplicao. Para a realizao dos testes com a referida aplicao, foi utilizado o compilador GCC (gfortran), no sistema operacional GNU/Linux Ubuntu 8.10, em um computador Intel Core 2 Duo 1.8 GHz, com 3 GBytes de memria. Inicialmente, a aplicao foi compilada sem nenhuma otimizao, tanto a verso original, quanto a verso refatorada, sendo, posteriormente, ambas as verses compiladas com a opo de otimizao -O1 do compilador. Cada verso da aplicao compilada foi

50

executada trs vezes, para se obter uma mdia de tempo de execuo, resultado na tabela de tempos de execuo que pode ser vista na Figura 4.1.

Figura 4.1: Tabela de tempos de execuo da aplicao Quanto s otimizaes, foi utilizada apenas a opo -O1, pois a aplicao passou a comportar-se indevidamente quando utilizadas as opes -O2 e -O3, que so mais agressivas, na medida em que seu grau de otimizao maior. Normalmente, quando utilizadas essas duas ltimas opes em aplicaes de alto desempenho, bastante comum ocorrerem erros na execuo, pois muitas mudanas podem ocorrer nesse processo, podendo gerar pequenos erros (anomalias) que no so identicados no processo de compilao. Como pode ser visto na Figura 4.1, o tempo mdio de execuo do cdigo original com um arquivo de entrada de 106.8 MBytes, foi de 21m32.184s, com as opes de otimizao do compilador desligadas. Aps a vericao do tempo de execuo do programa original, foram aplicadas as refatoraes nas subrotinas do programa (10 subrotinas). Apenas as duas primeiras refatoraes (Standardize Statements e Remove Unused Variables) apresentaram resultados signicativos, pois na aplicao no foi usado o tipo de declarao Data, na qual a refatorao Data To Parameter atua. Com o uso da refatorao Remove Unused Variables algumas variveis no usadas presentes em alguns dos arquivos das subrotinas foram removidas. Na subrotina autocorrelacao a varivel corre(n) foi removida. J, na subrotina detrend foi encontrada uma varivel nomeada f, que no era usada e foi removida. Na subrotina rotacao3d foram removidas as variveis cor1, var e dp. Como possvel se observar, na aplicao no havia muitas variveis no utilizadas, mas a tcnica de refatorao foi capaz de identicar e remover todas as variveis no utilizadas, cumprindo sua descrio. J com o uso da re-

51

fatorao Standardize Statements, as 10 subrotinas do software tiveram suas declaraes de variveis padronizadas. O tempo mdio de execuo da aplicao, com o mesmo arquivo de entrada, tendo todas as suas subrotinas refatoradas com as refatoraes Standardize Statements e Remove Unused Variables, foi de 21m36.069s, tambm com as diretivas de otimizao do compilador desativadas. Posteriormente, compilou-se a aplicao original com as diretivas de otimizao do compilador ativadas (-O1), obtendo-se, uma mdia de 6m53.225s de tempo de execuo. Com o uso da otimizao houve uma diminuio signicativa no tempo de execuo da aplicao, sendo gasto apenas cerca de 32% do tempo que a aplicao sem otimizaes demorou para executar. No muito diferente da aplicao original, quando a aplicao refatorada foi compilada com as opes de otimizao ativadas (-O1), foi obtida uma mdia de 6m53.664s de tempo de execuo, sendo gasto tambm apenas cerca de 32% do tempo de execuo da aplicao refatorada sem otimizaes. Com esses resultados, pode-se concluir que com os uso das refatoraes implementadas neste trabalho, o cdigo fonte ca com maior legibilidade e melhor estruturado e o desempenho no afetado negativamente, nem mesmo quando se usam as opes de otimizao do compilador. A diferena de tempo de execuo entre a aplicao original e a aplicao refatorada foi de apenas 3.885s (representando aproximadamente 0,3% do tempo), sem o uso de otimizaes na compilao. J a diferena de tempo de execuo da aplicao original e a aplicao refatorada, com o uso da otimizao -O1, foi de apenas 0.439s (representando aproximadamente 0,1% do tempo).

4.2 Avaliao das refatoraes em diferentes verses do Fortran


Nesta seo pode-se observar os testes realizados em dois dos cdigos fonte do projeto org.eclipse.photran-samples, distribudo juntamente com o Photran. O objetivo dos testes nesses cdigos mostrar o correto funcionamento das refatoraes em diferentes verses da linguagem Fortran suportadas pelo plugin Photran.

52

4.2.1 Eliminao Gaussiana Em lgebra linear, a Eliminao Gaussiana um algoritmo para resolver sistemas de equaes lineares, encontrando o posto de uma matriz, e calculando a inversa de uma matriz inversvel quadrada. Operaes elementares de linha so utilizadas para reduzir uma matriz forma escalonada de linha, sendo que a Eliminao Gaussiana suciente para resolver muitas aplicaes. O processo de Eliminao Gaussiana divido em duas partes. A primeira parte (Forward Elimination) reduz um sistema dado a um sistema de forma triangular ou de forma escalonada, ou resulta em uma degenerao da equao sem soluo, indicando que o sistema no tem soluo. Isto conseguido atravs do uso de operaes elementares de linha. O segundo passo utiliza a substituio de volta para encontrar a soluo do sistema obtido pela primeira parte do algoritmo. O algoritmo interessante tambm porque calcula uma matriz de decomposio. As trs operaes elementares lineares utilizadas no mtodo (multiplicando as linhas, trocando as linhas, e adicionando mltiplos de linhas a outras linhas) elevam-se multiplicando a matriz original com matrizes inversveis esquerda. A primeira parte do algoritmo calcula uma decomposio LU1 , enquanto a segunda parte escreve a matriz original como o produto de uma matriz inversvel unicamente determinada e uma matriz linha-reduzida escalonada unicamente determinada (WIKIPEDIA.ORG, 2009a; STEINBRUCH; WINTERLE, 1987). O primeiro cdigo do projeto org.eclipse.photran-samples usado para fazer a aplicao foi o cdigo gauselim.f90, que possui cerca de 240 linhas, sendo um cdigo cientco. A refatorao Standardize Statements proporcionou uma melhoria na legibilidade das declaraes em algumas regies do cdigo, como pode ser visto nas Figuras 4.2, 4.3, 4.4 e 4.5. Com as demais refatoraes (Remove Unused Variables e Data To Parameter), o cdigo no sofreu alteraes, pois no possui nenhuma varivel no usada e tambm no usa nenhuma constante declarada como data. Mesmo assim, foi possvel perceber a melhora na legibilidade, quando h uma padronizao na declarao de variveis.
Em lgebra linear, a decomposio LU (em que LU vem do ingls lower e upper) uma forma de fatorao de uma matriz no singular como o produto de uma matriz triangular inferior (lower) e uma matriz triangular superior (upper).
1

53

Figura 4.2: Refatorao Standardize Statements no cdigo gauselim.f90 (Bloco 1)

Figura 4.3: Refatorao Standardize Statements no cdigo gauselim.f90 (Bloco 2) 4.2.2 Ajuste de Curvas (Curve Fitting) O mtodo de ajuste de curvas (Curve Fitting) um mtodo que consiste em encontrar uma curva que se ajuste a uma srie de pontos e que, possivelmente, cumpra uma srie de parmetros adicionais. O ajuste de curvas muito utilizado para, a partir de dados conhecidos, fazer-se extrapolaes. Por exemplo, conhece-se os dados de consumo anual

54

Figura 4.4: Refatorao Standardize Statements no cdigo gauselim.f90 (Bloco 3)

Figura 4.5: Refatorao Standardize Statements no cdigo gauselim.f90 (Bloco 4) de carga eltrica de uma cidade. A partir destes dados conhecidos, pode-se fazer projees para o futuro e, com isso, fazer-se um planejamento para que a cidade seja suprida de forma adequada nos anos subsequentes. A idia obter uma curva que melhor se ajuste aos dados disponveis. Conhecida a equao da curva, pode-se determinar valores fora do intervalo conhecido (WIKIPEDIA.ORG, 2009b). O segundo cdigo do projeto org.eclipse.photran-samples usado para realizao dos testes, um cdigo maior, com cerca de 870 linhas, foi o cdigo nomeado bstt.f90. Nesse cdigo foram adicionadas propositalmente variveis no utilizadas em regies aleatrias,

55

am de testar a refatorao Remove Unused Variables, e tambm foram adicionadas constantes declaradas como data, am de testar a refatorao Data To Parameter. Nas Figuras 4.6, 4.7 e 4.8, pode-se observar o resultado de regies modicadas quando foi aplicada a refatorao Remove Unused Variables. Observe que o cdigo preservou a identao e os comentrios que havia no local onde encontravam-se as variveis no utilizadas.

Figura 4.6: Refatorao Remove Unused Variables no cdigo bstt.f90 (Bloco 1)

Figura 4.7: Refatorao Remove Unused Variables no cdigo bstt.f90 (Bloco 2) Agora, nas Figuras 4.9 e 4.10, pode-se observar a aplicao da refatorao Data To Parameter, que foi aplicada aps a refatorao Remove Unused Variables, pois como

56

Figura 4.8: Refatorao Remove Unused Variables no cdigo bstt.f90 (Bloco 3) mencionado anteriormente, um cdigo fonte pode passar por diversas refatoraes sucessivas, am de atingir o melhoramento desejado, obtido por um conjunto de pequenas modicaes que geram uma grande modicao.

Figura 4.9: Refatorao Data To Parameter no cdigo bstt.f90 (Bloco 1)

4.3 Trabalhos Relacionados


O uso de refatorao no est restrito apenas ao cdigo fonte de aplicaes, podendo tambm ser aplicado a outros artefatos do software, como no projeto da aplicao, modelos de anlise, bancos de dados, dentre outros. Alguns trabalhos abordam o uso de

57

Figura 4.10: Refatorao Data To Parameter no cdigo bstt.f90 (Bloco 2) refatoraes em diagramas UML (ASTELS, 2002) assim como a automatizao de refatoraes integradas a editores UML (BOGER; STURM; FRAGEMANN, 2003). Existem tambm, na rea de banco de dados, trabalhos que discutem a refatorao no contexto da evoluo de esquemas relacionais (BOEHM et al., 2007). Um dos grandes desaos denir mecanismos para manter a consistncia entre diferentes artefatos (implementao e modelo) de software com o uso de refatorao. Na pesquisa de refatorao para Fortran, podem-se encontrar trabalhos que fazem a reestruturao de cdigo fonte seqencial para cdigo fonte paralelo/distribudo (EVERAARS; ARBAB; BURGER, 1996). Nesse caso, com a refatorao de software possvel se aproveitar o melhor desempenho oferecido pelos sistemas paralelo/distribudos, sem ter de reescrever todo o cdigo legado para conseguir a transformao, que muitas vezes um processo de alto custo. O presente trabalho explora as refatoraes de cdigo Fortran, no visando apenas o ganho de desempenho, mas tambm almeja-se obter como resultado um cdigo de melhor qualidade, maior legibilidade, e de mais fcil manuteno. Tambm, vale lembrar que as pesquisas relacionadas com refatorao abrangem muitas linguagens de programao diferentes. No Eclipse (ECLIPSE.ORG, 2009a), podemse encontrar 23 refatoraes para a linguagem Java, sendo que para as outras linguagens suportadas pelo IDE, o nmero de refatoraes bastante reduzido, sugerindo a carncia de pesquisa e desenvolvimento relacionados a refatorao para determinadas linguagens

58

de programao. Existem pesquisas que estudam os desaos da refatorao de cdigo fonte da linguagem de programao C (GARRIDO; JOHNSON, 2002). Nesse caso, assim como o Fortran, existe uma grande diculdade em refatorar cdigos C legados. Embora exista uma grande quantidade de cdigos legados nessa linguagem, ferramentas de refatorao para C com suporte completo para as diretivas de pr-processamento para essa linguagem ainda no existem. Logo, a semelhana dos problemas de refatorao tratados neste trabalho, com Fortran, tambm encontam-se em aberto quando se trata da linguagem C. Encontram-se, tambm, pesquisas que visam construir modelos de ferramentas para refatoraes independentes de linguagens. Normalmente, a maioria das ferramentas que atuam em processos de refatorao so dependentes das linguagens para as quais as refatoraes so desenvolvidas, impedindo uma maior integrao de tcnicas de refatorao a ambientes de programao em geral. No trabalho A Meta-Model for Language-Independent Refactoring (TICHELAAR et al., 2000), so estudadas as similaridades entre as refatoraes das linguagens Java e Smalltalk, onde criado um meta-modelo de linguagem independente, mostrando que possvel construir uma ferramenta de refatorao independente de linguagens. Usando um meta-modelo independente de linguagens pode-se eliminar a dependncia de existir uma ferramenta de refatorao para cada tipo de linguagem diferente. No plugin Photran, pode-se encontar um pouco da idia de se ter uma nica ferramenta para a refatorao de diversas linguagens, uma vez que o Photran possui um menu de refatorao para cada tipo de linguagem suportada. Porm, as refatoraes do Photran so dependentes das linguagens para as quais foram desenvolvidas. Por exemplo, uma refatorao de Fortran no funciona em um cdigo Java. Assim, no Photran ainda necessrio implementar refatoraes para uma linguagem especca desejada, desde que o plugin tenha suporte de refatoraes para essa linguagem.

4.4 Sumrio do captulo


Conforme visto nas sees anteriores, a aplicao das refatoraes desenvolvidas nesse trabalho mostraram resultados satisfatrios, uma vez que o desempenho das aplicaes no afetado negativamente, e resulta em um cdigo melhor estruturado e com melhor legibilidade. Tambm, durante os testes foram usados trs cdigos fonte diferentes,

59

de tamanhos diferentes e verses da linguagem diferentes, para avaliar o funcionamento das refatoraes em diferentes verses da linguagem. Alm das concluses relativas ao tempo de execuo preciso registrar que a utilizao de tcnicas automatizadas agilizam e do maior segurana ao programador, no inibindo a possibilidade de erros, mas diminuindo a chance de o usurio introduzir erros no processo de refatorao. O uso da ferramenta Photran tambm agrega a funcionalidade do programador pr-visualizar o cdigo refatorado e decidir ou no por sua utilizao. Tambm neste captulo, foi feita uma breve comparao deste trabalho com outros correlatos, mostrando que existem pesquisas sobre refatorao em outras linguagens de programao, salientando tambm que as tcnicas de refatorao no esto restritas apenas ao uso em cdigos fonte. Assim, possvel inferir que o objetivo do trabalho foi alcanado, e o resultado so as refatoraes aqui implementadas, que j foram submetidas ao comit de avaliao do Photran, para serem integradas ocialmente no plugin e serem usadas livremente por qualquer usurio do Photran.

CONSIDERAES FINAIS

Aplicaes de cunho cientco geralmente se preocupam com o emprego de metodologias e tcnicas para a execuo eciente de aplicaes, abrangindo tcnicas de programao, melhorias de cdigo e distribuio ou paralelizao de tarefas. Os melhores resultados em termos de desempenho esto associados utilizao de uma arquitetura de hardware especca com construes apropriadas de software. As tcnicas de refatorao tm por objetivo amenizar a degradao natural pela qual o cdigo fonte de aplicaes sofre com o tempo, uma vez que se podem aplicar diversas tcnicas sobre um mesmo cdigo para que este que adequado com as novas necessidades. O processo de refatorao pode ser executado manualmente, mas o ganho de qualidade em escala se d quando tcnicas so automatizadas e integradas a ferramentas para desenvolvimento de software (IDEs). A utilizao do suporte de ferramentas automatizadas para refatorar reduz o risco de erros e inconsistncias, alm de reduzir tambm o trabalho e o custo de desenvolvimento e manuteno de softwares. Neste trabalho foi explorada a utilizao de tcnicas de refatorao sobre aplicaes escritas em linguagem Fortran (geralmente, de cunho cientco), objetivando melhorar o projeto de cdigo, assim como a legibilidade do mesmo, e detectar oportunidades de ganho de desempenho (reduzindo o nmero de acesso variveis quando se substitui data por parameter nos locais corretos, por exemplo). As tcnicas estudadas foram automatizadas e integradas ferramenta Photran, um plugin do Eclipse que oferece recursos para o ciclo de desenvolvimento de aplicaes Fortran e que oferece um framework que permite estender funcionalidades de refatorao para essa linguagem de programao. As principais contribuies do trabalho so a identicao e automatizao de tcnicas de refatorao para linguagem Fortran, sendo que as tcnicas desenvolvidas neste trabalho (Standardize Statements, Remove Unused Variables e Data To Parameter) se mostraram

61

ecientes em todos os testes, atendendo aos requisitos para os quais as mesmas foram desenvolvidas, sem prejudicar o desempenho das aplicaes e gerando um cdigo mais legvel e melhor estruturado, como pode ser observado no Captulo 4, com os screenshots dos resultados das aplicaes das refatoraes. A utilizao do Photran como ferramenta de apoio codicao e automatizao de tcnicas de refatorao tambm merece destaque. Ferramentas como o Photran representam um importante avano no sentido de se preencher a lacuna existente entre a grande quantidade de cdigo Fortran legado (em especial de aplicaes cientcas) e o limitado nmero de ferramentas de apoio ao desenvolvimento com tcnicas de refatorao integradas. Desde seu advento, em meados de 2004, possvel observar um crescimento importante no nmero de usurios que se utilizam da ferramenta como tambm de voluntrios que implementam melhorias e agregam funcionalidades mesma, para contribuir e poder torn-la uma ferramente de excelncia na rea de refatorao de aplicaes escritas em linguagem Fortran. Como sugestes para trabalhos futuros, pretende-se aprofundar os conhecimentos sobre refatoraes, fazendo uma maior reviso bibliogrca sobre o tema, desenvolvendo-se tambm novas tcnicas de refatorao para Fortran. No projeto Fortran Refactoring: FortiFact, que vem sendo desenvolvido em conjunto entre as instituies UFRGS, UFSM e CPTEC (INPE), e de onde foram tiradas as propostas para duas das tcnicas de refatorao desenvolvidas nesse trabalho, encontra-se uma grande lista de propostas de novas refatoraes para Fortran, e deseja-se dar continuidade colaborao com o projeto, implementando-se algumas das tcnicas descritas no mesmo. Algumas das tcnicas descritas no projeto Fortran Refactoring: FortiFact que poderiam ser implementadas como trabalhos futuros so: rvore de Chamadas: Para cada subrotina, incluir um comentrio a precedendo, que indica a lista de subrotinas que podem cham-la, bem como a rvore de subrotinas que ela chama. O uso dessa refatorao pode ser fundamental para poder entender a lgica de um programa. Associao de Use: Quer-se determinar a rvore de uses e us-la para determinar em qual mdulo foi declarada uma varivel usada em outro mdulo. Use Only: Quer-se substituir todos os use por use only, a m de listar explicitamente

62

e exatamente apenas os smbolos necessrios ao mdulo que os quer incluir. Modularizao: Criar um mdulo a partir de um subconjunto de subrotinas, gerando sua interface e colocando o use no lugar apropriado de onde se quer chamar os procedimentos. Tambm se deve privatizar o que deve ser privatizado e tornar pblico o que pode ser pblico.

63

REFERNCIAS

ADAMS, J. C.; BRAINERD, W. S.; HENDRICKSON, R. A.; MAINE, R. E.; MARTIN, J. T.; SMITH, B. T. The Fortran 2003 Handbook: the complete syntax, features and procedures. [S.l.: s.n.], 2008. ASTELS, D. Refactoring with UML. In: INTL CONF. EXTREME PROGRAMMING AND FLEXIBLE PROCESSES IN SOFTWARE ENGINEERING (XP), 2002. Proceedings. . . [S.l.: s.n.], 2002. p.6770. Alghero, Sardinia, Italy. BOEHM, A. M.; SEIPEL, D.; SICKMANN, A.; WETZKA, M. Squash: a tool for analyzing, tuning and refactoring relational database applications. In: . [S.l.: s.n.], 2007. p.82 98. BOGER, M.; STURM, T.; FRAGEMANN, P. Refactoring Browser for UML. In: . [S.l.: s.n.], 2003. p.366377. BONIATI, B. B. Refatorao de Programas Fortran de Alto Desempenho. 2009. Dissertao (Mestrado) Universidade Federal de Santa Maria, Santa Maria, RS. BONIATI, B.; CHARAO, A.; STEIN, B. Automao de Refatoraes para Programas Fortran de Alto Desempenho. In: WSCAD-SSC09: X WORKSHOP EM SISTEMAS COMPUTACIONAIS DE ALTO DESEMPENHO / X SIMPSIO EM SISTEMAS COMPUTACIONAIS, 2009, So Paulo. Anais. . . [S.l.: s.n.], 2009. CHEN, N.; OVERBEY, J. Photran 4.0 Developers Guide. 2008. CORNLIO, M. Refactorings as Formal Renements. 2004. Tese (Doutorado) Universidade Federal de Pernambuco.

64

DE, V. A foundation for refactoring FORTRAN 90 in Eclipse. 2004. Dissertao (Mestrado) University of Illinois at Urbana-Champaign, Urbana-Champaign. DEURSEN, A. van; MOONEN, L.; BERGH, A. van den; KOK, G. Refactoring Test Code. Anais... ECLIPSE.ORG. Eclipse. Disponvel em: http://www.eclipse.org/. Acesso em: dezembro de 2009. ECLIPSE.ORG. Photran - An Integrated Development Environment for Fortran. Disponvel em: http://www.eclipse.org/photran/. Acesso em: dezembro de 2009. ECLIPSE.ORG. Eclipse C/C++ Development Tooling - CDT. Disponvel em: http: //www.eclipse.org/cdt/. Acesso em: dezembro de 2009. EVERAARS, C. T. H.; ARBAB, F.; BURGER, F. J. Restructuring sequential Fortran code into a parallel/distributed application. In: ICSM 96: PROCEEDINGS OF THE 1996 INTERNATIONAL CONFERENCE ON SOFTWARE MAINTENANCE, 1996, Washington, DC, USA. Anais. . . IEEE Computer Society, 1996. p.1322. FOWLER, M. Refatorao: aperfeioando o projeto de cdigo existente. [S.l.: s.n.], 2004. FOWLER, M. Refactoring Home Page. Disponvel em: refactoring.com/. Acesso em: dezembro de 2009. GARRIDO, A.; JOHNSON, R. Challenges of refactoring C programs. In: IWPSE 02: PROCEEDINGS OF THE INTERNATIONAL WORKSHOP ON PRINCIPLES OF SOFTWARE EVOLUTION, 2002, New York, NY, USA. Anais. . . ACM, 2002. p.614. GNU. GCC, the GNU Compiler Collection. Disponvel em: http://gcc.gnu. org/. Acesso em: dezembro de 2009. GRISWOLD, W. G.; NOTKIN, D. Automated assistance for program restructuring. ACM Trans. Softw. Eng. Methodol., New York, NY, USA, v.2, n.3, p.228269, 1993. ISO. ISO/IEC 14977: information technology: syntactic metalanguage: extended bnf. 1.ed. [S.l.: s.n.], 1996. http://www.

65

JONES, em:

J.

Abstract

Syntax

Tree

Implementation

Idioms.

Disponvel

http://jerry.cs.uiuc.edu/~plop/plop2003/Papers/

Jones-ImplementingASTs.pdf Acesso em: dezembro de 2009. KOFFMAN, E. B.; FRIEDMAN, F. L. FORTRAN. Boston, MA, USA: Addison-Wesley Longman Publishing Co., Inc., 1996. MENS, T.; TOURW, T. A Survey of Software Refactoring. IEEE Trans. Softw. Eng., Piscataway, NJ, USA, v.30, n.2, p.126139, 2004. NYHOFF, L.; LEESTMA, S. Fortran 90 for Engineers and Scientists. [S.l.: s.n.], 1997. OVERBEY, J. L. Virtual Program Graph. Disponvel em: http://jeff.over. bz/software/vpg/doc/. Acesso em: dezembro de 2009. OVERBEY, J. L.; JOHNSON, R. E. A Survey of Software Refactoring: a foundation for the rapid development of source code transformation tools. In: Software Language Engineering: rst international conference, 2008, toulouse, france. [S.l.: s.n.], 2008. OVERBEY, J. L.; JOHNSON, R. E. Generating Rewritable Abstract Syntax Trees. In: Software Language Engineering: rst international conference, 2009, toulouse, france. Berlin, Heidelberg: Springer-Verlag, 2009. p.114133. RICARTE, I. L. M. Introduo Compilao. [S.l.: s.n.], 2008. ROBERTS, D. B. Practical analysis for refactoring. [S.l.: s.n.], 1999. ROBERTS, D.; BRANT, J.; JOHNSON, R. An Automated Refactoring Tool. In: . Chicago, EUA: [s.n.], 1996. STEINBRUCH, A.; WINTERLE, P. lgebra Linear. So Paulo, BR: [s.n.], 1987. TICHELAAR, S.; DUCASSE, S.; DEMEYER, S.; NIERSTRASZ, O. A Meta-Model for Language-Independent Refactoring. In: INTERNATIONAL SYMPOSIUM ON PRINCIPLES OF SOFTWARE EVOLUTION, 2000, 2000. Anais. . . [S.l.: s.n.], 2000. p.154 164. WIKIPEDIA.ORG. Gaussian Elimination. Disponvel em: http://en. dezembro

wikipedia.org/wiki/Gaussian_elimination. Acesso em: de 2009.

66

WIKIPEDIA.ORG. Curve Fitting. Disponvel em: http://en.wikipedia.org/ wiki/Curve_fitting. Acesso em: dezembro de 2009.

APNDICE A CDIGO FONTE DAS IMPLEMENTAES

Neste apndice se encontram os cdigos fonte referentes s tcnicas de refatorao desenvolvidas neste trabalho, chamadas Standardize Statements, Remove Unused Variables e Data To Parameter, no plugin Photran do IDE Eclipse. Tambm encontra-se o cdigo fonte da refatorao Introduce INTENT, que foi atualizada para funcionar na verso utilizada do plugin. Os cdigos fonte de cada uma delas podem ser vistos nas sees A.1, A.2, A.3, A.4, respectivamente.

A.1

Standardize Statements

A.1.1 Interface com o usurio (StandardizeStatementsAction.java) Nesse cdigo fonte esto contidas duas classes, sendo que uma responsvel por receber a chamada do usurio e associar a ao de refatorao com seu respectivo assistente e a outra o prprio assistente (wizard) da refatorao.
package org.eclipse.photran.internal.refactoring.ui; import java.util.ArrayList; import org.eclipse.core.resources.IFile; import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; import org.eclipse.photran.internal.core.refactoring.StandardizeStatementsRefactoring; import org.eclipse.photran.internal.core.refactoring.infrastructure.AbstractFortranRefactoring; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IEditorActionDelegate; import org.eclipse.ui.IWorkbenchWindowActionDelegate; public class StandardizeStatementsAction extends AbstractFortranRefactoringActionDelegate implements IWorkbenchWindowActionDelegate, IEditorActionDelegate {

68

public StandardizeStatementsAction() { super(StandardizeStatementsRefactoring.class, FortranStandardizeStatementsRefactoringWizard.class); } @Override protected AbstractFortranRefactoring getRefactoring(ArrayList<IFile> les) { return new StandardizeStatementsRefactoring(les); } public static class FortranStandardizeStatementsRefactoringWizard extends AbstractFortranRefactoringWizard { protected StandardizeStatementsRefactoring standardizeStatementsRefactoring; public FortranStandardizeStatementsRefactoringWizard( StandardizeStatementsRefactoring r) { super(r); this.standardizeStatementsRefactoring = r; } @Override protected void doAddUserInputPages() { addPage(new UserInputWizardPage(standardizeStatementsRefactoring.getName()) { public void createControl(Composite parent) { Composite top = new Composite(parent, SWT.NONE); initializeDialogUnits(top); setControl(top); top.setLayout(new GridLayout(1, false)); Label lbl = new Label(top, SWT.NONE); lbl.setText("Click OK to standardize the statements in the selected les. To see what changes will be made, click Preview."); } }); } } }

A.1.2 Arquivo de ao da refatorao (StandardizeStatementsRefactoring.java) Nesse cdigo fonte est a principal classe a ser codicada, que consiste na ao propriamente dita da refatorao.
package org.eclipse.photran.internal.core.refactoring; import java.util.ArrayList; import java.util.LinkedList; import java.util.List;

69

import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.photran.core.IFortranAST; import org.eclipse.photran.internal.core.analysis.binding.ScopingNode; import org.eclipse.photran.internal.core.lexer.Token; import org.eclipse.photran.internal.core.parser.ASTDerivedTypeDefNode; import org.eclipse.photran.internal.core.parser.ASTEntityDeclNode; import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode; import org.eclipse.photran.internal.core.parser.ASTTypeDeclarationStmtNode; import org.eclipse.photran.internal.core.parser.ASTTypeSpecNode; import org.eclipse.photran.internal.core.parser.Parser.IASTListNode; import org.eclipse.photran.internal.core.parser.Parser.IASTNode; import org.eclipse.photran.internal.core.refactoring.infrastructure. MultipleFileFortranRefactoring; import org.eclipse.photran.internal.core.refactoring.infrastructure.Reindenter; import org.eclipse.photran.internal.core.refactoring.infrastructure.SourcePrinter; / Refatorao para padronizar as declaraes de variveis. @author Gustavo Rissetti / public class StandardizeStatementsRefactoring extends MultipleFileFortranRefactoring { public StandardizeStatementsRefactoring(ArrayList<IFile> myFiles) { super(myFiles); } @Override public String getName() { return "Standardize Statements"; } @Override protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { ensureProjectHasRefactoringEnabled(status); removeFixedFormFilesFrom(this.selectedFiles, status); } @Override protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { try { for (IFile le : selectedFiles) { IFortranAST ast = vpg.acquirePermanentAST(le);

70

if (ast == null) { status.addError("One of the selected les (" + le.getName() + ") cannot be parsed."); } makeChangesTo(le, ast, status, pm); vpg.releaseAST(le); } } nally { vpg.releaseAllASTs(); } } // Mtodo auxiliar utilizado para vericar se uma declarao contm os dois pontos (::). // Foi necessrio construir esse mtodo para tratar do caso em que existem os dois pontos // em um comentrio depois da declarao, por exemplo: // integer varivel ! comentario :: m do comentrio // Se fosse usado o recurso do java (if(s.indexOf("::") != 1)), no seria tratado o caso // do exemplo acima. private boolean points(String s) { for (int i = 0; i < s.length() 1; i++) { char p1 = s.charAt(i); char p2 = s.charAt(i + 1); if (p1 == ! || p2 == !) { return false; } else if (p1 == : && p2 == :) { return true; } } return false; } private void makeChangesTo(IFile le, IFortranAST ast, RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { List<ScopingNode> scopes = ast.getRoot().getAllContainedScopes(); for (ScopingNode scope : scopes) { if (!(scope instanceof ASTExecutableProgramNode) && !(scope instanceof ASTDerivedTypeDefNode)) { IASTListNode<IASTNode> body = (IASTListNode<IASTNode>) scope.getBody(); List<ASTTypeDeclarationStmtNode> statements = new LinkedList< ASTTypeDeclarationStmtNode>(); for (IASTNode node : body) { if (node instanceof ASTTypeDeclarationStmtNode) { IASTListNode<ASTEntityDeclNode> variables = (( ASTTypeDeclarationStmtNode) node).getEntityDeclList(); ASTTypeSpecNode type_node = new ASTTypeSpecNode(); // Pega o tipo das variveis. String type = ((ASTTypeDeclarationStmtNode) node).getTypeSpec().toString ().trim(); String[] typeWithoutComments = type.split("\n"); type = typeWithoutComments[typeWithoutComments.length 1].trim(); Token text_type = new Token(null, type);

71

type_node.setIsInteger(text_type); for (int i = 0; i < variables.size(); i++) { ASTTypeDeclarationStmtNode new_statement = ( ASTTypeDeclarationStmtNode) node.clone(); if (i > 0) { new_statement.setTypeSpec(type_node); } IASTListNode<ASTEntityDeclNode> new_variable = (IASTListNode< ASTEntityDeclNode>) variables.clone(); List<ASTEntityDeclNode> list_variables_to_remove = new LinkedList< ASTEntityDeclNode>(); for (int j = 0; j < variables.size(); j++) { if (j != i) { list_variables_to_remove.add(new_variable.get(j)); } } new_variable.removeAll(list_variables_to_remove); new_statement.setEntityDeclList(new_variable); // Coloca os :: caso na declarao original no tenha. String source = SourcePrinter.getSourceCodeFromASTNode( new_statement); int position_type = new_statement.getTypeSpec().toString().length(); String twoPoints = ""; String source_1 = source.substring(0, position_type); String source_2 = source.substring(position_type, source.length()); if (!points(source_2)) { twoPoints = " ::"; } // Nova declarao, j com os ::. source = source_1 + twoPoints + source_2; new_statement = (ASTTypeDeclarationStmtNode) parseLiteralStatement( source); // Adiciona uma referncia da antiga declarao. statements.add((ASTTypeDeclarationStmtNode) node); // Adiciona a nova declarao. statements.add(new_statement); } } } // Insere as novas declaraes, j padronizadas na AST. for (int i = 0; i < statements.size(); i += 2) { body.insertBefore(statements.get(i), statements.get(i + 1)); Reindenter.reindent(statements.get(i + 1), ast); } // Remove da AST as antigas declaraes que estavam fora do padro. for (int i = 0; i < statements.size(); i += 2) { ASTTypeDeclarationStmtNode delete = statements.get(i); if (body.contains(delete)) { delete.removeFromTree(); } }

72

} } // Adiciona as mudanas na AST. addChangeFromModiedAST(le, pm); } @Override protected void doCreateChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { // A mudana feita no mtodo makeChangesTo(...). } }

A.2

Remove Unused Variables

A.2.1 Interface com o usurio (RemoveUnusedVariablesAction.java) Nesse cdigo fonte esto contidas duas classes, sendo que uma responsvel por receber a chamada do usurio e associar a ao de refatorao com seu respectivo assistente e a outra o prprio assistente (wizard) da refatorao.
package org.eclipse.photran.internal.refactoring.ui; import java.util.ArrayList; import org.eclipse.core.resources.IFile; import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; import org.eclipse.photran.internal.core.refactoring.RemoveUnusedVariablesRefactoring; import org.eclipse.photran.internal.core.refactoring.infrastructure.AbstractFortranRefactoring; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IEditorActionDelegate; import org.eclipse.ui.IWorkbenchWindowActionDelegate; public class RemoveUnusedVariablesAction extends AbstractFortranRefactoringActionDelegate implements IWorkbenchWindowActionDelegate, IEditorActionDelegate { public RemoveUnusedVariablesAction() { super(RemoveUnusedVariablesRefactoring.class, FortranRemoveUnusedVariablesRefactoringWizard.class); } @Override protected AbstractFortranRefactoring getRefactoring(ArrayList<IFile> les) { return new RemoveUnusedVariablesRefactoring(les); }

73

public static class FortranRemoveUnusedVariablesRefactoringWizard extends AbstractFortranRefactoringWizard { protected RemoveUnusedVariablesRefactoring removeUnusedVariablesRefactoring; public FortranRemoveUnusedVariablesRefactoringWizard( RemoveUnusedVariablesRefactoring r) { super(r); this.removeUnusedVariablesRefactoring = r; } @Override protected void doAddUserInputPages() { addPage(new UserInputWizardPage(removeUnusedVariablesRefactoring.getName()) { public void createControl(Composite parent) { Composite top = new Composite(parent, SWT.NONE); initializeDialogUnits(top); setControl(top); top.setLayout(new GridLayout(1, false)); Label lbl = new Label(top, SWT.NONE); lbl.setText("Click OK to remove unused variables in the selected les. \ nTo see what changes will be made, click Preview.\n\nWARNING: If the les have some change so do the refactoring again \nuntil no change appears. So all the unused variables are removed."); } }); } } }

A.2.2 Arquivo de ao da refatorao (RemoveUnusedVariablesRefactoring.java) Nesse cdigo fonte est a principal classe a ser codicada, que consiste na ao propriamente dita da refatorao.
package org.eclipse.photran.internal.core.refactoring; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.photran.core.IFortranAST;

74

import org.eclipse.photran.core.vpg.PhotranTokenRef; import org.eclipse.photran.internal.core.analysis.binding.Denition; import org.eclipse.photran.internal.core.analysis.binding.ScopingNode; import org.eclipse.photran.internal.core.parser.ASTEntityDeclNode; import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode; import org.eclipse.photran.internal.core.parser.ASTObjectNameNode; import org.eclipse.photran.internal.core.parser.ASTTypeDeclarationStmtNode; import org.eclipse.photran.internal.core.parser.Parser.IASTListNode; import org.eclipse.photran.internal.core.parser.Parser.IASTNode; import org.eclipse.photran.internal.core.refactoring.infrastructure. MultipleFileFortranRefactoring; / Refatorao para remover variveis no utilizadas no cdigo. @author Gustavo Rissetti / public class RemoveUnusedVariablesRefactoring extends MultipleFileFortranRefactoring { public RemoveUnusedVariablesRefactoring(ArrayList<IFile> myFiles) { super(myFiles); } @Override public String getName() { return "Remove Unused Variables"; } @Override protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { ensureProjectHasRefactoringEnabled(status); removeFixedFormFilesFrom(this.selectedFiles, status); // Essa refatorao tem como prrequisito que o cdigo seja Implicit None. // necessrio primeiramente usar a refatorao Introduce Implicit None do Photran. try { for (IFile le : selectedFiles) { IFortranAST ast = vpg.acquirePermanentAST(le); if (ast == null) { status.addError("One of the selected les (" + le.getName() + ") cannot be parsed."); } List<ScopingNode> scopes = ast.getRoot().getAllContainedScopes(); for (ScopingNode scope : scopes) { if (!(scope instanceof ASTExecutableProgramNode)) { if (!scope.isImplicitNone()) { fail("All of the selected les must be Implict None! Please use the Introduce Implict None Refactoring rst to introduce the Implict None statements in le " + le.getName() + "!"); }

75

} } vpg.releaseAST(le); } } nally { vpg.releaseAllASTs(); } } @Override protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { try { for (IFile le : selectedFiles) { IFortranAST ast = vpg.acquirePermanentAST(le); if (ast == null) { status.addError("One of the selected les (" + le.getName() + ") cannot be parsed."); } makeChangesTo(le, ast, status, pm); vpg.releaseAST(le); } } nally { vpg.releaseAllASTs(); } } private ASTTypeDeclarationStmtNode getTypeDeclarationStmtNode(IASTNode node) { if (node == null) { return null; } if (node instanceof ASTTypeDeclarationStmtNode) { return (ASTTypeDeclarationStmtNode) node; } return getTypeDeclarationStmtNode(node.getParent()); } private void makeChangesTo(IFile le, IFortranAST ast, RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { boolean hasChanged = false; List<ScopingNode> scopes = ast.getRoot().getAllContainedScopes(); for (ScopingNode scope : scopes) { System.out.println("Scope: " + scope.getClass().getName()); List<Denition> denitions = scope.getAllDenitions(); for (Denition def : denitions) { if (def.isLocalVariable()) { Set<PhotranTokenRef> references = def.ndAllReferences(true); // Se a varivel no tiver sido referenciada ao longo do cdigo, // ento ela nunca foi usada, e dever, portanto, ser removida. if (references.isEmpty()) { hasChanged = true;

76

System.out.println("The variable [" + def.getDeclaredName() + "] was not used and will be removed."); ASTTypeDeclarationStmtNode declarationNode = getTypeDeclarationStmtNode(def.getTokenRef().ndToken().getParent()); if (declarationNode.getEntityDeclList().size() == 1) { declarationNode.replaceWith("\n"); } else { IASTListNode<ASTEntityDeclNode> statementsInNode = declarationNode.getEntityDeclList(); for (ASTEntityDeclNode statement : statementsInNode) { ASTObjectNameNode objectName = statement.getObjectName(); String statementName = objectName.getObjectName().getText(); if (statementName.equals(def.getDeclaredName())) { if (!statementsInNode.remove(statement)) { fail("Sorry, could not complete the operation."); } break; } } declarationNode.setEntityDeclList(statementsInNode); } } } } } if (hasChanged) { addChangeFromModiedAST(le, pm); status.addInfo("After clicking Continue, do the same refactoring again to make sure that all unused variables are removed from le " + le.getName () + "!"); } else { status.addInfo("All unused variables have been removed from le " + le. getName() + "!"); } } @Override protected void doCreateChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { // A mudana feita no mtodo makeChangesTo(...). } }

A.3

Data To Parameter

A.3.1 Interface com o usurio (DataToParameterAction.java) Nesse cdigo fonte esto contidas duas classes, sendo que uma responsvel por receber a chamada do usurio e associar a ao de refatorao com seu respectivo assistente

77

e a outra o prprio assistente (wizard) da refatorao.


package org.eclipse.photran.internal.refactoring.ui; import java.util.ArrayList; import org.eclipse.core.resources.IFile; import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; import org.eclipse.photran.internal.core.refactoring.DataToParameterRefactoring; import org.eclipse.photran.internal.core.refactoring.infrastructure.AbstractFortranRefactoring; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IEditorActionDelegate; import org.eclipse.ui.IWorkbenchWindowActionDelegate; public class DataToParameterAction extends AbstractFortranRefactoringActionDelegate implements IWorkbenchWindowActionDelegate, IEditorActionDelegate { public DataToParameterAction() { super(DataToParameterRefactoring.class, FortranDataToParameterRefactoringWizard. class); } @Override protected AbstractFortranRefactoring getRefactoring(ArrayList<IFile> les) { return new DataToParameterRefactoring(les); } public static class FortranDataToParameterRefactoringWizard extends AbstractFortranRefactoringWizard { protected DataToParameterRefactoring dataToParameterRefactoring; public FortranDataToParameterRefactoringWizard(DataToParameterRefactoring r) { super(r); this.dataToParameterRefactoring = r; } @Override protected void doAddUserInputPages() { addPage(new UserInputWizardPage(dataToParameterRefactoring.getName()) { public void createControl(Composite parent) { Composite top = new Composite(parent, SWT.NONE); initializeDialogUnits(top); setControl(top); top.setLayout(new GridLayout(1, false)); Label lbl = new Label(top, SWT.NONE);

78

lbl.setText("Click OK to change the attributes Data by attributes Parameter in the selected les. To see what changes will be made, click Preview."); } }); } } }

A.3.2 Arquivo de ao da refatorao (DataToParameterRefactoring.java) Nesse cdigo fonte est a principal classe a ser codicada, que consiste na ao propriamente dita da refatorao.
package org.eclipse.photran.internal.core.refactoring; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.photran.core.IFortranAST; import org.eclipse.photran.internal.core.analysis.binding.ScopingNode; import org.eclipse.photran.internal.core.parser.ASTAssignmentStmtNode; import org.eclipse.photran.internal.core.parser.ASTDataStmtNode; import org.eclipse.photran.internal.core.parser.ASTDataStmtSetNode; import org.eclipse.photran.internal.core.parser.ASTDataStmtValueNode; import org.eclipse.photran.internal.core.parser.ASTDatalistNode; import org.eclipse.photran.internal.core.parser.ASTDerivedTypeDefNode; import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode; import org.eclipse.photran.internal.core.parser.IDataStmtObject; import org.eclipse.photran.internal.core.parser.Parser.IASTListNode; import org.eclipse.photran.internal.core.parser.Parser.IASTNode; import org.eclipse.photran.internal.core.refactoring.infrastructure. MultipleFileFortranRefactoring; import org.eclipse.photran.internal.core.refactoring.infrastructure.Reindenter; import org.eclipse.photran.internal.core.refactoring.infrastructure.SourcePrinter; / Refatorao para transformar declaraes do tipo Data em declaraes do tipo Parameter. @author Gustavo Rissetti / public class DataToParameterRefactoring extends MultipleFileFortranRefactoring { public DataToParameterRefactoring(ArrayList<IFile> myFiles) {

79

super(myFiles); } @Override public String getName() { return "Data To Parameter"; } @Override protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { ensureProjectHasRefactoringEnabled(status); removeFixedFormFilesFrom(this.selectedFiles, status); } @Override protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { try { for (IFile le : selectedFiles) { IFortranAST ast = vpg.acquirePermanentAST(le); if (ast == null) { status.addError("One of the selected les (" + le.getName() + ") cannot be parsed."); } makeChangesTo(le, ast, status, pm); vpg.releaseAST(le); } } nally { vpg.releaseAllASTs(); } } private void makeChangesTo(IFile le, IFortranAST ast, RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { List<String> astAssignmentStmtNames = new LinkedList<String>(); List<IASTNode> parameter_nodes = new LinkedList<IASTNode>(); List<IASTNode> nodes_to_delete = new LinkedList<IASTNode>(); List<ASTDataStmtValueNode> values_to_delete = new LinkedList< ASTDataStmtValueNode>(); List<IDataStmtObject> statements_to_delete = new LinkedList<IDataStmtObject>(); List<ScopingNode> scopes = ast.getRoot().getAllContainedScopes(); boolean hasChanged = false; for (ScopingNode scope : scopes) { astAssignmentStmtNames.clear(); parameter_nodes.clear(); nodes_to_delete.clear(); values_to_delete.clear(); statements_to_delete.clear(); if (!(scope instanceof ASTExecutableProgramNode) && !(scope instanceof ASTDerivedTypeDefNode)) {

80

IASTListNode<IASTNode> body = (IASTListNode<IASTNode>) scope.getBody(); // Para poder transformar uma declarao do tipo: data nome / valor / // em uma declarao do tipo: parameter ( nome = valor ), a varivel // [nome] no pode ser alterada no programa, podendo ser apenas // referenciada. Assim, inicialmente, fazse uma vericao de todas // as variveis que tiveram seu valor alterado, para ter certeza na // hora de fazer a troca, de que nenhuma das variveis do tipo Data // alteradas seja transformada em Parameter. Caso uma das variveis // do tipo Data tiver sido alterada, ela permanece sendo do tipo Data. for (IASTNode node : body) { if (node instanceof ASTAssignmentStmtNode) { String name = ((ASTAssignmentStmtNode) node).getLhsVariable().getName() .getText(); astAssignmentStmtNames.add(name); } } for (IASTNode node : body) { if (node instanceof ASTDataStmtNode) { IASTListNode<ASTDatalistNode> data_list = ((ASTDataStmtNode) node). getDatalist(); int data_list_size = data_list.size(); for (ASTDatalistNode data_node : data_list) { ASTDataStmtSetNode stmt_set_node = data_node.getDataStmtSet(); IASTListNode<IDataStmtObject> statement_list = stmt_set_node. getDataStmtObjectList(); IASTListNode<ASTDataStmtValueNode> value_list = stmt_set_node. getDataStmtValueList(); int statement_count = 0; values_to_delete.clear(); statements_to_delete.clear(); for (statement_count = 0; statement_count < statement_list.size(); statement_count++) { String parameter_name = statement_list.get(statement_count).toString(). trim(); // Novo n que conter a declarao do tipo Parameter. IASTNode parameter = null; // Se a varivel no foi alterada, ento ela ser // transformada em Parameter. if (!astAssignmentStmtNames.contains(parameter_name)) { hasChanged = true; // Pega o cdigo do n. String source = SourcePrinter.getSourceCodeFromASTNode(node); String[] source_split = source.split("\n"); // Nova declarao. StringBuffer parameter_statement = new StringBuffer("parameter ( "); parameter_statement.append(parameter_name + " = "); String value = value_list.get(statement_count).getConstant().toString ().trim(); parameter_statement.append(value + " )"); // Pega os comentrios do nal da linha da declarao.

81

String comments_end_of_line = source_split[source_split.length 1]; boolean has_comment = false; int index_comment = 0; for (index_comment = 0; index_comment < comments_end_of_line. length(); index_comment++) { if (comments_end_of_line.charAt(index_comment) == !) { has_comment = true; break; } } if (has_comment) { parameter_statement.append(" " + comments_end_of_line. substring(index_comment)); } // criado o novo n. parameter = parseLiteralStatement(parameter_statement.toString()); // Referncia do local onde o novo n deve ser inserido na AST. parameter_nodes.add(node); // Novo n a ser inserido na AST. parameter_nodes.add(parameter); // Deve ser removido um valor e uma declarao das listas originais. ASTDataStmtValueNode value_to_remove = value_list.get( statement_count); IDataStmtObject statement_to_remove = statement_list.get( statement_count); values_to_delete.add(value_to_remove); statements_to_delete.add(statement_to_remove); } } // Remoo das entradas da AST. if (statement_list.size() == statements_to_delete.size()) { data_node.removeFromTree(); data_list_size; // Se um n tiver todos os seus dados removidos, necessrio recuperar // os comentrios que estavam antes do mesmo e recoloclos em seu // devido lugar. if (data_list_size == 0) { IASTNode parameter = null; String source = SourcePrinter.getSourceCodeFromASTNode(node); String[] source_split = source.split("\n"); String comments_before_line = new String(""); for (int i = 0; i < source_split.length 1; i++) { comments_before_line += source_split[i] + "\n"; } IASTNode last_parameter_node = parameter_nodes.get( parameter_nodes.size() 1); String last_parameter_node_source = SourcePrinter. getSourceCodeFromASTNode(last_parameter_node); // Adicionados os comentrios.

82

String last_parameter_with_comments = comments_before_line + last_parameter_node_source; // Gerado o novo n. parameter = parseLiteralStatement(last_parameter_with_comments); // substituido da lista o ltimo n pelo novo n com os // comentrios e o valor do antigo n. parameter_nodes.remove(parameter_nodes.size() 1); parameter_nodes.add(parameter); // adicionado na lista de ns a serem removidos o n vazio. nodes_to_delete.add(node); } } else { statement_list.removeAll(statements_to_delete); value_list.removeAll(values_to_delete); } } } } // Insere todos os ns do tipo Parameter criados. for (int i = 0; i < parameter_nodes.size(); i += 2) { body.insertAfter(parameter_nodes.get(i), parameter_nodes.get(i + 1)); Reindenter.reindent(parameter_nodes.get(i + 1), ast); } // Deleta os ns do tipo Data que caram vazios. for (int i = 0; i < nodes_to_delete.size(); i++) { ASTDataStmtNode delete = (ASTDataStmtNode) nodes_to_delete.get(i); if (body.contains(delete)) { delete.removeFromTree(); } } // Caso alguma declarao tenha cado como: data ,var/valor/ // necessrio retirar a vrgula que sobrou depois do termo Data. IASTNode coma = null; for (IASTNode node : body) { if (node instanceof ASTDataStmtNode) { coma = node; String source_coma = SourcePrinter.getSourceCodeFromASTNode(coma); String[] source_coma_split = source_coma.split("\n"); // Acha a declarao Data. String statement = source_coma_split[source_coma_split.length 1].trim(); String data = statement.substring(0, 4); String list_data = statement.substring(4); list_data = list_data.trim(); // Se iniciar com uma ",", ento tem que retirla. if (list_data.startsWith(",")) { // Retira a vrgula que est sobrando. list_data = list_data.substring(1); list_data = list_data.trim(); String new_source = new String(""); for (int i = 0; i < source_coma_split.length 1; i++) { new_source += source_coma_split[i] + "\n";

83

} new_source += data + " " + list_data; // Cria o novo n e substitui pelo antigo. IASTNode without_coma = parseLiteralStatement(new_source); coma.replaceWith(without_coma); Reindenter.reindent(without_coma, ast); } } } } } // Adiciona as mudanas na AST. if (hasChanged) { addChangeFromModiedAST(le, pm); } } @Override protected void doCreateChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { // A mudana feita no mtodo makeChangesTo(...). } }

A.4

Introduce INTENT

Essa refatorao foi desenvolvida durante o mestrado de Bruno Batista Boniati (BONIATI, 2009). Ela foi desenvolvida em uma verso anterior do plugin, e na ltima atualizao, com as mudanas estruturais do mesmo, a refatorao parou de funcionar. Foi feita ento uma atualizao da refatorao para que ela funcionasse na nova verso do Photran, fazendo-se tambm pequenas melhorias no cdigo. A.4.1 Interface com o usurio (IntroduceIntentAction.java) Nesse cdigo fonte esto contidas duas classes, sendo que uma responsvel por receber a chamada do usurio e associar a ao de refatorao com seu respectivo assistente e a outra o prprio assistente (wizard) da refatorao.
package org.eclipse.photran.internal.refactoring.ui; import java.util.ArrayList; import org.eclipse.core.resources.IFile; import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; import org.eclipse.photran.internal.core.refactoring.IntroduceIntentRefactoring; import org.eclipse.photran.internal.core.refactoring.infrastructure.AbstractFortranRefactoring; import org.eclipse.swt.SWT;

84

import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IEditorActionDelegate; import org.eclipse.ui.IWorkbenchWindowActionDelegate; public class IntroduceIntentAction extends AbstractFortranRefactoringActionDelegate implements IWorkbenchWindowActionDelegate, IEditorActionDelegate { public IntroduceIntentAction() { super(IntroduceIntentRefactoring.class, FortranIntroduceIntentRefactoringWizard.class); } public static class FortranIntroduceIntentRefactoringWizard extends AbstractFortranRefactoringWizard { protected IntroduceIntentRefactoring introduceIntentRefactoring; public FortranIntroduceIntentRefactoringWizard(IntroduceIntentRefactoring r) { super(r); this.introduceIntentRefactoring = r; } @Override protected void doAddUserInputPages() { addPage(new UserInputWizardPage(introduceIntentRefactoring.getName()) { public void createControl(Composite parent) { Composite top = new Composite(parent, SWT.NONE); initializeDialogUnits(top); setControl(top); top.setLayout(new GridLayout(1, false)); Label lbl = new Label(top, SWT.NONE); lbl.setText("Click OK to introduce intents in the selected subroutine/ function. To see what changes will be made, click Preview."); } }); } } @Override protected AbstractFortranRefactoring getRefactoring(ArrayList<IFile> les) { return new IntroduceIntentRefactoring(getFortranEditor().getIFile(), getFortranEditor(). getSelection()); } }

85

A.4.2 Arquivo de ao da refatorao (IntroduceIntentRefactoring.java) Nesse cdigo fonte est a principal classe a ser codicada, que consiste na ao propriamente dita da refatorao.
package org.eclipse.photran.internal.core.refactoring; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jface.text.ITextSelection; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.photran.core.vpg.PhotranTokenRef; import org.eclipse.photran.internal.core.analysis.binding.Denition; import org.eclipse.photran.internal.core.analysis.binding.ScopingNode; import org.eclipse.photran.internal.core.lexer.Token; import org.eclipse.photran.internal.core.parser.ASTAssignmentStmtNode; import org.eclipse.photran.internal.core.parser.ASTAttrSpecNode; import org.eclipse.photran.internal.core.parser.ASTCallStmtNode; import org.eclipse.photran.internal.core.parser.ASTDataRefNode; import org.eclipse.photran.internal.core.parser.ASTFunctionSubprogramNode; import org.eclipse.photran.internal.core.parser.ASTNameNode; import org.eclipse.photran.internal.core.parser.ASTObjectNameNode; import org.eclipse.photran.internal.core.parser.ASTReadStmtNode; import org.eclipse.photran.internal.core.parser.ASTSubroutineArgNode; import org.eclipse.photran.internal.core.parser.ASTSubroutineSubprogramNode; import org.eclipse.photran.internal.core.parser.ASTTypeDeclarationStmtNode; import org.eclipse.photran.internal.core.parser.ASTVarOrFnRefNode; import org.eclipse.photran.internal.core.parser.Parser.IASTListNode; import org.eclipse.photran.internal.core.parser.Parser.IASTNode; import org.eclipse.photran.internal.core.refactoring.infrastructure.SingleFileFortranRefactoring; import org.eclipse.photran.internal.core.refactoring.infrastructure.SourcePrinter; / Refatorao para introduzir os Intents em Subrotinas e Funes. @author Bruno Batista Boniati @author Gustavo Rissetti / public class IntroduceIntentRefactoring extends SingleFileFortranRefactoring { private ScopingNode subprogram = null; List<Denition> argumentDenitions; List<SubProgramInformation> subProgramInterfaces; List<SubProgramInformation> callProgram;

86

@Override public String getName() { return "Introduce Intent"; } public boolean subprogramExists(String name, String le) { boolean r = false; name = name.toUpperCase(); le = le.toUpperCase(); for (int i = 0; i < subProgramInterfaces.size(); i++) { String n_aux = subProgramInterfaces.get(i).getSubProgramName(); String f_aux = subProgramInterfaces.get(i).getFileName(); if ((n_aux.equalsIgnoreCase(name)) && (f_aux.equalsIgnoreCase(le))) { r = true; break; } } return r; } private ASTTypeDeclarationStmtNode getTypeDeclarationStmtNode(IASTNode o) { if (o == null) { return null; } if (o instanceof ASTTypeDeclarationStmtNode) { return (ASTTypeDeclarationStmtNode) o; } return getTypeDeclarationStmtNode(o.getParent()); } private void processInterfaces(IFile le) throws PreconditionFailure { List<ScopingNode> scopes = vpg.acquirePermanentAST(le).getRoot(). getAllContainedScopes(); for (ScopingNode scopingNode : scopes) { List<Denition> denitions = scopingNode.getAllDenitions(); for (Denition def : denitions) { if (def.isSubprogramArgument()) { PhotranTokenRef tr = def.getTokenRef(); Token t = tr.ndToken(); ScopingNode s = t.getEnclosingScope(); if (s != null) { String subprogram = s.getRepresentativeToken().getText(); String leName = def.getTokenRef().getFilename(); if (!subprogramExists(subprogram, leName)) { SubProgramInformation spi = new SubProgramInformation(subprogram, leName); List<Denition> def_scope = s.getAllDenitions(); for (Denition d : def_scope) { if (d.isSubprogramArgument()) {

87

ASTTypeDeclarationStmtNode a = getTypeDeclarationStmtNode(d. getTokenRef().ndToken().getParent()); // S atua se a declarao for simples. if (a.getEntityDeclList().size() == 1) { ASTAttrSpecNode at = getASTAttrSpecNode(a); spi.addParam(d.getDeclaredName(), at); } else { // Se alguma declarao for composta, necessrio padronizla // usando a refatorao Standardize Statements. fail("All Statements must be simple (integer :: a). To Standardize all \n" + "statements in le, use Standardize Statements Refactoring rst!"); } } } subProgramInterfaces.add(spi); } } } } } } private ASTAttrSpecNode getASTAttrSpecNode(IASTNode o) { ASTAttrSpecNode r = null; if (o instanceof ASTAttrSpecNode) { r = (ASTAttrSpecNode) o; } else { for (IASTNode child : o.getChildren()) { if (r == null) { r = getASTAttrSpecNode(child); } } } return r; } public IntroduceIntentRefactoring(IFile le, ITextSelection selection) { super(le, selection); subProgramInterfaces = new ArrayList<SubProgramInformation>(); callProgram = new ArrayList<SubProgramInformation>(); } @Override protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { ensureProjectHasRefactoringEnabled(status); processInterfaces(leInEditor); IASTNode n = ndEnclosingNode(astOfFileInEditor, selectedRegionInEditor); if (n != null) {

88

if ((n instanceof ASTSubroutineSubprogramNode) | (n instanceof ASTFunctionSubprogramNode)) { subprogram = (ScopingNode) n; } } if (subprogram == null) { fail("You can select a Subroutine or Subprogram"); } else { if (!subprogram.isImplicitNone()) { fail("The subprogram selected must be Implict None! Please use the Introduce Implict None Refactoring rst!"); } List<Denition> denitions = subprogram.getAllDenitions(); argumentDenitions = new LinkedList<Denition>(); for (Denition def : denitions) { if (def.isSubprogramArgument()) { argumentDenitions.add(def); } } for (int i = 0; i < subprogram.getBody().size(); i++) { processCallsAndFunctions(subprogram.getBody().get(i)); } processCallsAndFunctionsWithInterfaces(); } } private void processCallsAndFunctions(IASTNode node) { // Funes. if (node instanceof ASTVarOrFnRefNode) { if (((ASTVarOrFnRefNode) node).getPrimarySectionSubscriptList() != null) { SubProgramInformation spi = new SubProgramInformation(((ASTVarOrFnRefNode ) node).getName().getName().getText(), leInEditor.getName()); for (int i = 0; i < ((ASTVarOrFnRefNode) node).getPrimarySectionSubscriptList(). size(); i++) { if (((ASTVarOrFnRefNode) node).getPrimarySectionSubscriptList().get(i). getExpr() instanceof ASTVarOrFnRefNode) { spi.addParam(((ASTVarOrFnRefNode) ((ASTVarOrFnRefNode) node). getPrimarySectionSubscriptList().get(i).getExpr()).getName().getName(). getText(), null); } } callProgram.add(spi); } } else { // Subrotinas. if (node instanceof ASTCallStmtNode) { SubProgramInformation spi = new SubProgramInformation(((ASTCallStmtNode) node).getSubroutineName().getText(), leInEditor.getName()); IASTListNode<ASTSubroutineArgNode> argumentos = ((ASTCallStmtNode) node ).getArgList(); for (ASTSubroutineArgNode arg : argumentos) {

89

ASTVarOrFnRefNode exp = (ASTVarOrFnRefNode) arg.getExpr(); spi.addParam(exp.getName().getName().getText(), null); } callProgram.add(spi); } } for (IASTNode child : node.getChildren()) { processCallsAndFunctions(child); } } // Este mtodo vai percorrer todas as chamadas a mtodos dentro da subrotina e vericar nos // escopos de funo como so os intents. private void processCallsAndFunctionsWithInterfaces() { for (int i = 0; i < callProgram.size(); i++) { for (int j = 0; j < subProgramInterfaces.size(); j++) { if ((callProgram.get(i).getSubProgramName().equalsIgnoreCase( subProgramInterfaces.get(j).getSubProgramName())) && (callProgram.get(i).getParamsSize() == subProgramInterfaces.get(j). getParamsSize())) { for (int p = 0; p < subProgramInterfaces.get(j).getParamsSize(); p++) { switch (subProgramInterfaces.get(j).getIntentParam(p)) { case SubProgramInformation.intentINOUT: callProgram.get(i).setIntentInOut(p); break; case SubProgramInformation.intentIN: callProgram.get(i).setIntentIn(p); break; case SubProgramInformation.intentOUT: callProgram.get(i).setIntentOut(p); break; } } break; } } } } @Override protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) throws PreconditionFailure { // No faz nada... } @Override protected void doCreateChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { if (argumentDenitions != null) { for (Denition def : argumentDenitions) { if (def.getTokenRef().ndToken() != null) {

90

ASTTypeDeclarationStmtNode a = getTypeDeclarationStmtNode(def. getTokenRef().ndToken().getParent()); if (a.getEntityDeclList().size() == 1) { if (!isIntent(a)) { String name = getVariableName(a); if (name != null) { String s = SourcePrinter.getSourceCodeFromASTNode(a); String twoPoints = ""; String intentType = ""; String attr = ""; if (hasReference(name)) { intentType = "in"; } if (hasAssigment(name)) { intentType = intentType.concat("out"); } if (a.getAttrSpecSeq() != null) { attr = a.getAttrSpecSeq().toString(); } int p = getVariablePosition(s, attr); if (!hasTwoPoints(s.substring(p))) { twoPoints = ":: "; } String s2 = s.substring(0, p); String s3 = s.substring(p + 1, s.length()); if (intentType.length() > 0) { intentType = ", intent(".concat(intentType).concat(") "); } s = s2.concat(intentType).concat(twoPoints).concat(s3); a.replaceWith(parseLiteralStatement(s)); } } } } } } addChangeFromModiedAST(leInEditor, pm); vpg.releaseAST(leInEditor); } // Indica que a varivel passada por parmetro sofre alterao no corpo do procedimento. private boolean hasAssigment(String name) { boolean r = false; for (int i = 0; i < callProgram.size(); i++) { for (int j = 0; j < ((SubProgramInformation) callProgram.get(i)).getParamsSize(); j++) { if (name.equalsIgnoreCase(((SubProgramInformation) callProgram.get(i)). getParamName(j))) { if (((SubProgramInformation) callProgram.get(i)).paramIsIntentOut(j) || (( SubProgramInformation) callProgram.get(i)).paramIsIntentInOut(j)) { r = true;

91

break; } } } } if (!r) { for (int i = 0; i < subprogram.getBody().size(); i++) { r = hasAssigment(subprogram.getBody().get(i), name); if (r) { break; } } } return r; } private boolean hasRead(IASTNode node, String v) { boolean r = false; if (node instanceof ASTDataRefNode) { r = (((ASTDataRefNode) node).getName().getText().equalsIgnoreCase(v)); } else { for (IASTNode child : node.getChildren()) { if (!r) { r = hasRead(child, v); } else { break; } } } return r; } private boolean hasAssigment(IASTNode node, String variavel) { boolean r = false; if (node instanceof ASTAssignmentStmtNode) { r = (((ASTAssignmentStmtNode) node).getLhsVariable().getName().getText(). equalsIgnoreCase(variavel)); } else { if (node instanceof ASTReadStmtNode) { r = hasRead(((ASTReadStmtNode) node).getInputItemList(), variavel); } } if (!r) { for (IASTNode child : node.getChildren()) { if (!r) { r = hasAssigment(child, variavel); } else { break; } } }

92

return r; } // Indica que a varivel passada por parmetro referenciada no corpo do procedimento. private boolean hasReference(String name) { boolean r = false; for (int i = 0; i < subprogram.getBody().size(); i++) { r = isReferenced(subprogram.getBody().get(i), name); if (r) { break; } } return r; } private boolean isReferenced(IASTNode node, String name) { boolean r = false; if (node instanceof ASTVarOrFnRefNode) { r = existsReferenceForVariable(node, name); } else { for (IASTNode child : node.getChildren()) { if (!r) { r = isReferenced(child, name); } else { break; } } } return r; } private boolean existsReferenceForVariable(IASTNode node, String name) { boolean r = false; if (node instanceof ASTNameNode) { if (((ASTNameNode) node).getName().getText().equalsIgnoreCase(name)) { r = true; } } else { for (IASTNode child : node.getChildren()) { if (!r) { r = existsReferenceForVariable(child, name); } else { break; } } } return r; } private boolean hasTwoPoints(String s) { for (int i = 0; i < s.length() 1; i++) {

93

char p1 = s.charAt(i); char p2 = s.charAt(i + 1); if (p1 == ! || p2 == !) { return false; } else if (p1 == : && p2 == :) { return true; } } return false; } int getVariablePosition(String s, String attr) { String[] coments = s.split("\n"); int size = coments.length 1; int i, j; boolean start = false; int attr_length = attr.length() 1; for (int k = 0; k < coments.length 1; k++) { size += coments[k].length(); } String statement = coments[coments.length 1]; i = 0; for (j = 0; j < statement.length(); j++) { if ((statement.charAt(j) == ) & (start)) { i = j; break; } else { if (statement.charAt(j) != ) { start = true; } } } if (attr_length < 0) { attr_length = 0; } return i + size + attr_length; } private String getVariableName(IASTNode node) { String name = null; if (node instanceof ASTObjectNameNode) { name = ((ASTObjectNameNode) node).getObjectName().getText(); } else { for (IASTNode child : node.getChildren()) { if (name == null) { name = getVariableName(child); } else { break; } } }

94

return name; } private boolean isIntent(IASTNode node) { boolean r = false; if (node instanceof ASTAttrSpecNode) { r = ((ASTAttrSpecNode) node).isIntent(); } else { for (IASTNode child : node.getChildren()) { if (!r) { r = isIntent(child); } } } return r; } public class SubProgramInformation { public static nal int intentOFF = 1; public static nal int intentINOUT = 0; public static nal int intentIN = 1; public static nal int intentOUT = 2; private String subprogramName; private String leName; private List<String> parameters; private List<Integer> intentsInfo; public SubProgramInformation(String n, String f) { subprogramName = n.toUpperCase(); leName = f.toUpperCase(); parameters = new ArrayList<String>(); intentsInfo = new ArrayList<Integer>(); } public String getSubProgramName() { return subprogramName; } public String getFileName() { return leName; } public void addParam(String n, ASTAttrSpecNode att) { parameters.add(n.toUpperCase()); if (att != null) { if (att.isIntent()) { if (att.getIntentSpec().isIntentIn()) { intentsInfo.add(new Integer(intentIN)); } else { if (att.getIntentSpec().isIntentOut()) { intentsInfo.add(new Integer(intentOUT));

95

} else { intentsInfo.add(new Integer(intentINOUT)); } } } else { intentsInfo.add(new Integer(intentINOUT)); } } else { intentsInfo.add(new Integer(intentOFF)); } } public int getParamsSize() { return parameters.size(); } public String getParamName(int index) { return parameters.get(index); } public int getIntentParam(int index) { return intentsInfo.get(index).intValue(); } public void setIntentIn(int index) { intentsInfo.set(index, new Integer(intentIN)); } public void setIntentOut(int index) { intentsInfo.set(index, new Integer(intentOUT)); } public void setIntentInOut(int index) { intentsInfo.set(index, new Integer(intentINOUT)); } public boolean paramIsIntentIn(int index) { return intentsInfo.get(index).intValue() == intentIN; } public boolean paramIsIntentOut(int index) { return intentsInfo.get(index).intValue() == intentOUT; } public boolean paramIsIntentInOut(int index) { return intentsInfo.get(index).intValue() == intentINOUT; } } }

Das könnte Ihnen auch gefallen