a technique for constructing aspect weavers using a program transformation engine aosd 2004...

27
A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury http://www.gray-area.org

Upload: bathsheba-mckenzie

Post on 05-Jan-2016

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

A Technique for Constructing

Aspect Weavers Using aProgram Transformation

Engine

AOSD 2004Lancaster, UKMarch 24, 2004

Jeff GraySuman Roychoudhury

http://www.gray-area.org

Page 2: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

This paper: An idea from 1997

I first heard of AOP while working ona commercial Delphi project.

Page 3: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Cobol

Legacy

Legacy System - Challenges

Software

Fortran

Object Pascal

Corporate Backbone 200 Billion Lines of Cobol Source

Migration is not an easy task !

Infrastructure, money effort already spent

Page 4: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Maintenance & Tool Support

Maintaining such systems is still an onerous task

Need modern tools and methodologies to reduce maintenance cost and effort

Can we extend AOSD to support legacy software?

Page 5: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Language- and Platform-Independent Weavers Weaver Explosion Problem

AOSD Approach (AspectJ, HyperJ, CF, etc.) Base programming language Execution environment/platform

Page 6: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Main Barriers

The grammar recovery and parser construction problem…

The weaving engine problem…

Incomplete/toy parsers will not scale and will leave a negative first impression of aspects to skeptical industry adopters

Grammarware:

Paul Klint, Ralf Lämmel, and Chris Verhoef, “Towards an Engineering Discipline for Grammarware” http://www.cs.vu.nl/grammarware/agenda/

Page 7: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Program Transformation Systems

Program Transformation

System

Aspect WeaversRefactoring Tools

Low Level xForm constructs

High level aspect constructs

Legacy Software

Reuse of core set of transformations for each new weaver

We use a commercial PTE from Semantic Designs (the Design Maintenance System - DMS)

Page 8: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Outline

Background Case Study Weaver Transformation Rules Aspect Domain Related/Future work Conclusion

Page 9: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Background Case Study Experiment conducted on commercial software

written in Delphi Utility applications to support

database schema migration database-independent error handling language internationalization

Several aspects identified Processing dialog meter

Updating of progress Exception handling of meter

(not shown, but in paper) Logging of SQL query statements Synchronization in database error handler Dirty Bits in language internationalization utility

~45k Object Pascal

Page 10: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Processing Dialog Meter…Inc(TotalInserts);if not ProcDlg1.Process(TotalInserts/TotalCalc)

then begin ProcDlg1.Canceled := True; Result := True; exit; end; // if not Process…

The conditional statement is executed after each call to increment function.

Listing 1 contains a redundant code fragment that appears in 62 different places of the schema migrator.

Listing 1

Page 11: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Logging of SQL Query Statements…with dmSERVERS.qryCreateTriggers dobegin <statements that build a SQL Create Trigger> LogSQL.AddSQL(dmSERVERS.qryCreateTriggers,True); ExecSQL;end;…

Listing 2

The methods of the logging object are invoked in over 50 different places in the schema migrator.

Note: Object parameter passed to logging object is scoped in Object Pascal “with” statement.

Page 12: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Database Error Handler Synchronization

function TExNullField.Handle(ServerType: TServerType; E : EDBEngineError) : Integer;

begin TExHandleCollection(Collection).LockHandle; try <database error handling code omitted here> finally TExHandleCollection(Collection).UnLockHandle; end; end;

The addition of this concurrency concern resulted in a manual invasive change to over 20 classes.

The same code is replicated in all of the entry and exit points of each type of error handler.

Listing 3

Page 13: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Language Internationalization Utility // The user wants to perform another searchprocedure TLangMan.SearchAgainClick(Sender:TObject);begin // Perform an update if an edit occurred that

// might change the focus of the listview if EditMadeDirtyBit then SaveDBControls;…end;

There are 29 unique places in the language internationalization source code where access to the Boolean variable EditMadeDirtyBit is made.

Listing 4

Page 14: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Outline

Background Case Study Weaver Transformation Rules Aspect Domain Related/Future work Conclusion

Page 15: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

DMS Reengineering Toolkit

© Semantic Designs, Inc.Provided with permission from:

Page 16: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Progress Meter Transformation Ruledefault base domain ObjectPascal.pattern advice(): if_statement = "if not ProcDlg1.Process (TotalInserts/TotalCalc) then begin ProcDlg1.Canceled := True; Result := True; exit; end;".

rule probe_progress_meter(): statement_list -> statement_list = "Inc(TotalInserts);" -> "Inc(TotalInserts); \advice\(\);".

public ruleset applyrules = { probe_progress_meter }.

The LHS / RHS of rule operates on the AST as defined by the

Delphi grammar fragments

Page 17: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

default base domain ObjectPascal.external pattern add_log_stmt (slist1:statement_list, slist2:statement_list, id1:IDENTIFIER, id2:IDENTIFIER): statement_list = 'add_log_statement' in domain ObjectPascal.

pattern advice(id1:IDENTIFIER, id2:IDENTIFIER): statement_list = "LogSQL.AddSQL (\id1.\id2 , True);".pattern func_call_sig(): "ExecSQL".

rule probe_logging(id1:IDENTIFIER,id2:IDENTIFIER,slist:statement_list): with_statement -> with_statement = "with \id1 . \id2 do begin \slist end" -> "with \id1 . \id2 do begin \add_log_stmt\(\slist \, \advice\(\id1 \,\id2\) \, \id2 \,\func_call_sig\(\)\) end".public ruleset applyrules = { probe_logging }.

Log Transformation Rule(lambda (function boolean AST:Node )function (value (local (;; );; (;; (ifthen(== ~t (AST:ContainsString ?)) (;; (= search_string (AST:GetString ?)) (ifthen (== (@ search_string) arguments:4) (return ~t)) ifthen );; )ifthen (return ~f) );; )local ~f )value )lambda …

default base domain ObjectPascal.external pattern add_log_stmt(slist1:statement_list, slist2:statement_list, id1:IDENTIFIER, id2:IDENTIFIER): statement_list = 'add_log_statement' in domain ObjectPascal.

pattern advice(id1:IDENTIFIER, id2:IDENTIFIER): statement_list = "LogSQL.AddSQL (\id1.\id2 , True);".pattern func_call_sig(): "ExecSQL".

rule probe_logging (id1:IDENTIFIER, id2:IDENTIFIER, slist:statement_list) :

with_statement -> with_statement = "with \id1 . \id2 do begin \slist end" -> "with \id1 . \id2 do begin \add_log_stmt\(\slist \, \advice\(\id1 \,\id2\) \, \id2 \,\func_call_sig\(\)\) end".

Page 18: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

default base domain ObjectPascal.pattern probe_handle(id:IDENTIFIER): qualified_identifier = "\id.Handle".pattern unlock():statement = "TExHandleCollection(Collection).UnLockHandle".pattern lock(): statement = "TExHandleCollection(Collection).LockHandle".pattern advice(slist:statement_list): statement_list = "\lock\(\); try \slist finally \unlock\(\); end;".rule probe_synchronize(slist:statement_list, id:IDENTIFIER, fps:formal_parameters, frt:function_result_type): implementation_decl -> implementation_decl = "function \probe_handle\(\id\) \fps : \frt ; begin \slist end;" -> "function \probe_handle\(\id\) \fps : \frt ; begin \advice\(\slist\) end;".if ~[modsList:statement_list .slist matches "\:statement_list \advice\(\modsList\)"].public ruleset applyrules = { probe_synchronize }.

Synchronization Rules

rule probe_synchronize(slist:statement_list, id:IDENTIFIER, fps:formal_parameters, frt:function_result_type):

implementation_decl -> implementation_decl = "function \probe_handle\(\id\) \fps : \frt ; begin \slist end;" -> "function \probe_handle\(\id\) \fps : \frt ; begin \advice\(\slist\) end;".

default base domain ObjectPascal.pattern probe_handle(id:IDENTIFIER): qualified_identifier = "\id.Handle".pattern unlock(): statement = "TExHandleCollection(Collection).UnLockHandle".pattern lock(): statement = "TExHandleCollection(Collection).LockHandle".pattern advice(slist:statement_list): statement_list = "\lock\(\); try \slist finally \unlock\(\); end;".

Page 19: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Dirty Bit Transformation Rule

default base domain ObjectPascal.external condition func_sig_has_click(id1:IDENTIFIER,id2:IDENTIFIER) = 'func_sig_has_click'.pattern advice(slist:statement_list) : statement_list = "if EditMadeDirtyBit then SaveDBControls; \slist".pattern isClick(id:IDENTIFIER): IDENTIFIER = id if func_sig_has_click(click(), id).pattern click (): IDENTIFIER = "Click".rule probe_dirty_bit (id1:IDENTIFIER, id2:IDENTIFIER,fps:formal_parameters, slist:statement_list): implementation_decl -> implementation_decl = "procedure \id1 . \isClick\(\id2\) \fps ; begin

\slist end;" -> "procedure \id1 . \id2 \fps ;

begin\advice\(\slist\)

end;".

if ~[modslist:statement_list .slist matches "\:statement_list \advice\(\modslist\)"].

public ruleset applyrules = { probe_dirty_bit }.

rule probe_dirty_bit (id1:IDENTIFIER, id2:IDENTIFIER, fps:formal_parameters, slist:statement_list): implementation_decl -> implementation_decl = "procedure \id1 . \isClick\(\id2\) \fps ; begin

\slist end;" -> "procedure \id1 . \id2 \fps ;

begin \advice\(\slist\)

end;".

external condition func_sig_has_click(id1:IDENTIFIER, id2:IDENTIFIER) = 'func_sig_has_click'.pattern advice(slist:statement_list) : statement_list = "if EditMadeDirtyBit then SaveDBControls; \slist".pattern isClick(id:IDENTIFIER): IDENTIFIER = id if func_sig_has_click(click(), id).

if ~[modslist:statement_list .slist matches "\:statement_list \advice\(\modslist\)"].

public ruleset applyrules={probe_dirty_bit}.

Page 20: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Video Demonstration

Dirty Bit Weaving with DMS More detailed example provided at:

http://www.gray-area.org/Research/GenAWeave

Page 21: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Outline

Background Case Study Weaver Transformation Rules Aspect Domain Related/Future work Conclusion

Page 22: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Aspect Weaver

Aspect Source Attribute

Evaluator

RSLRules

DMS Transformation

Engine

Lexer

Parser

PARLANSE f(x)

Delphi Source

Transformed Delphi Source

Pattern Instantiation

FRONT END

BACK END

// The user wants to perform another search

procedure TLangMan.SearchAgainClick(Sender: TObject);

begin

// Perform an update if an edit occurred that //might change the focus of the listview

if EditMadeDirtyBit then

SaveDBControls;

end;

default base domain ObjectPascal.external condition func_sig_has_click(id1:IDENTIFIER,id2:IDENTIFIER)= 'func_sig_has_click'.pattern advice(slist:statement_list) : statement_list = "if EditMadeDirtyBit then SaveDBControls; \slist".pattern isClick(id:IDENTIFIER): IDENTIFIER = id if func_sig_has_click(click(), id).pattern click (): IDENTIFIER = "Click".rule probe_dirty_bit (id1:IDENTIFIER, id2:IDENTIFIER,fps:formal_parameters, slist:statement_list): implementation_decl -> implementation_decl = "procedure \id1 . \isClick\(\id2\) \fps ; begin

\slist end;" -> "procedure \id1 . \id2 \fps ;

begin\advice\(\slist\)

end;".

if ~[modslist:statement_list .slist matches"\:statement_list \advice\(\modslist\)"].

public ruleset applyrules = { probe_dirty_bit }.

(define func_sig_has_click (lambda Registry:MatchingCondition (let (;;(= [const_string (reference string)] (AST:GetString arguments:1)) (= [search_string (reference string)] (AST:GetString arguments:2)) (= [scanner StringScan:Scan ] (StringScan:MakeScan search_string)) );; (value (while (== (StringScan:End? (. scanner)) ~f)

(ifthenelse (StringScan:MatchString? (. scanner) const_string) (return ~t)

(StringScan:Advance (. scanner)) )ifthenelse )while~f

)value )let )lambda)define

aspect ProbeDirtybit {

pointcut method_click() : execution(procedure *.*Click(..)); before() : method_click() { if EditMadeDirtyBit then SaveDBControls; } }

`Aspect Pascal Weaver - Takes Aspect source and weaves the changes to the Delphi source':

(;;

`include domains': (;; (include `ObjectPascalDomain.par') (include `AspectPascalDomain.par') );;

`include creating pattern and its registration code': (include `RegisterCreatingPattern.par')

`include ast/cst snippets needed for weaving: (;; `include appropriate SyntaxTreeSnippets module for selected configuration of infix arithmetic calculator':

(;; (define ObjectPascalASTRepresentationEliminatedTerminalNodes ObjectPascal:ASTRepresentationEliminatedTerminalNodes) ; work around compiler deficiency

(compileifthenelse ObjectPascalASTRepresentationEliminatedTerminalNodes (;; (include `%ObjectPascalASTSnippets.par')) (;; (include `%ObjectPascalCSTSnippets.par'))

)compileifthenelse );;

);;

`auxiliary function for driver': (define get_file_name `gets a file name from standard input' (lambda (function string void) (let [str string]

(value (;; (Console:Put (. `Enter file name : '))

(= str (Console:GetString)) (Console:PutNewline)

);; str )value

)let )lambda )define

`define driver for the weaver': (define main (action (procedure void) (local

(;; [file_name string] [domain_representation AST:Representation] (= [graph AST:Forest] (void AST:Forest)) [syntax_tree AST:Node] [op_syntax_tree AST:Node] );; (try (;; `get file name':

(= file_name (get_file_name)) `create working graph': (= graph (AST:CreateForest)) `parse file containing aspect pascal syntax': (try (= syntax_tree (Registry:ParseFile (. `AspectPascal') Registry:DefaultSyntaxTreeDomainRepresentation

graph (. file_name))) (case (exception)

SyntaxErrorsDetected (acknowledge (;; (Console:Put (. `Error: Syntax errors occurred during parsing

of file "')) (Console:Put (. file_name)) (Console:Put (. `".~l')) (return) ; program end takes care of memory being

freed for the created working graph );; )acknowledgeInputStream:FileNotFound (acknowledge (;; (Console:Put (. `Error: Could not find file "'))

(Console:Put (. file_name))…..

%%AspectPascal

#include "DMSLexical/Library/DMS.lex"

#macro A "[aA]"#macro B "[bB]"#macro C "[cC]"#macro D "[dD]"#macro E "[eE]"#macro F "[fF]"#macro G "[gG]"#macro H "[hH]"#macro I "[iI]"#macro J "[jJ]"#macro K "[kK]"#macro L "[lL]"#macro M "[mM]"#macro N "[nN]"#macro O "[oO]"#macro P "[pP]"#macro Q "[qQ]"#macro R "[rR]"#macro S "[sS]"#macro T "[tT]"#macro U "[uU]"#macro V "[vV]"#macro W "[wW]"#macro X "[xX]"#macro Y "[yY]"#macro Z "[zZ]"

-------------------------------------------------------------- Lexical definition for AspectPascal------------------------------------------------------------

-- comments

#macro newline " (\u000d\u000a) | [\u000a\u000c\u000d\u2028\u2029] " -- newline characters

#macro tab "[\t]"#macro blank "[\ ]"#macro whitespace "<blank>|<tab>"

#skip "(<whitespace>|<newline>)+"

#preskip "(<whitespace>|<newline>)*"

#postskip "<whitespace>*"

#macro digit "[0-9]"

-- symbols

#token '*' "\*"#token '.' "\."#token ';' "\;"#token ':' "\:"#token '(' "\("#token ')' "\)"#token '{' "\{"#token '}' "\}"

-- reserved keywords

#token 'aspect' "<A><S><P><E><C><T>"#token 'before' "<B><E><F><O><R><E>"#token 'pointcut' "<P><O><I><N><T><C><U><T>“

aspect_declaration = 'aspect' identifier '{' pointcut advice '}' ;

<<PrettyPrinter>>:{ V(H('aspect', identifier, '{'), I(pointcut),I(advice),'}') ; }

advice = before_advice ;

before_advice = 'before' '(' ')' ':' pointcut '{' statement_list '}';<<PrettyPrinter>>:{ V(H('before', '(' , ')', ':', pointcut, '{'),statement_list ,'}') ; }

statement_list = statement ';' statement_list ;<<PrettyPrinter>>:{I(H(statement , ';', statement_list[1]));}

statement_list = statement;<<PrettyPrinter>>:{H*;}

statement = string statement;<<PrettyPrinter>>:{H*;}

statement = ;

pointcut = 'call' '(' signature ')' ;<<PrettyPrinter>>:{I(H('call', '(', signature ,')'));}

pointcut = 'execution' '(' signature ')' ;<<PrettyPrinter>>:{I(H('execution', '(', signature ,')'));}

pointcut = 'pointcut' identifier '(' ')' ':' pointcut ';' ;<<PrettyPrinter>>:{V(H('pointcut', identifier, '(', ')',':') , H(pointcut[1],';'));}

pointcut = identifier '(' ')' ;<<PrettyPrinter>>:{H*;}

signature = type_pattern '(' type_pattern ')' ;<<PrettyPrinter>>:{H*;}

type_pattern = type_name_pattern type_pattern;<<PrettyPrinter>>:{H*;}

type_name_pattern = '*';<<PrettyPrinter>>:{H*;}

type_name_pattern = '.';<<PrettyPrinter>>:{H*;}

type_name_pattern = identifier ;type_pattern = ;

identifier = IDENTIFIER ;

string = IDENTIFIER;

Page 23: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Outline

Background Case Study Weaver Transformation Rules Aspect Domain Related/Future work Conclusion

Page 24: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Related Work Weaving from general transformation framework

Pascal Fradet and Mario Südholt (1998) Ralf Lämmel (1999)

Language Extension Environments JTS, JastAdd, GENOA

Program Transformation Systems ASF+SDF, TXL, Stratego

Language-Specific Aspect Weavers AspectC++, AspectS, AspectR, Apostle

Language-Independent and Domain-Specific Weavers Lafferty and Cahill (2003), Constantinides et al. (2002), Shonle et

al. (2003) Our own past work

Two-level weaving to support model-driven program transformation (http://www.gray-area.org/Research/C-SAW)

Page 25: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Future long term goal – Towards language independence Grammar Wrappers

Abstract Grammar

Rules

Abstract Grammar

Extract Commonalities

C#

Java

OP

Cobol

C

Fortran

PTE

Weave Changes Refactor source

Common classof languages

Page 26: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Conclusion It is inevitable that AOSD will find its way into legacy languages;

similar transition for OO into Ada95, OO-COBOL, FORTRAN 2000

This paper describes a very modest first effort to construct weavers for legacy languages using a program transformation system

The goal is to avoid: duplication of effort for each new weaver by building on

generalized/parameterized weaving primitives offer an example in support of the goals of Grammarware

Drawbacks of current effort Strictly syntax-based approach Deep initial investment to understand DMS Based on a commercial tool that is not open-source

Page 27: A Technique for Constructing Aspect Weavers Using a Program Transformation Engine AOSD 2004 Lancaster, UK March 24, 2004 Jeff Gray Suman Roychoudhury

Questions?

Summary of URLs referenced in talk

GenAWeave http://www.gray-area.org/Research/GenAWeave

C-SAW (two-level model/program weaving) http://www.gray-area.org/Research/C-SAW

Grammarware http://ww.cs.vu.nl/grammarware/agenda

DMS http://www.semdesigns.com

Shameless Plug: HICSS AESS Aspect-friendly mini-track in Hawaii http://www.cis.uab.edu/HICSS-AESS/