SlideShare a Scribd company logo
1 of 17
Download to read offline
Code Transformation by
Direct Transformation of ASTs
M. Rizun, J.-C. Bach, S. Ducasse
1
Example of simple code transformation
foo
| result a b |
a := 2.
b := 3.
result := a >= b
ifTrue: [ a ]
ifFalse: [ b ]
foo
| result a b |
a := 2.
b := 3.
result := a max: b
Source code Resulting code
2
transformation
Manual code transformation process
(in big system)
Replace all found occurrences by target code.
Search for all occurrences of the code to replace in the source code.
Definition of the desired target code. (RHS)
Definition of the code to change. (LHS)
3
Find & Replace
“…code…”
x >= y
ifTrue: [ x ]
ifFalse: [ y ]
“…code…”
“…code…”
x max: y
“…code…”
4
Right-Hand Side partLeft-Hand Side part
Problems
Time-consuming and annoying task.
Complex and error-prone process.
Rules are not reusable.
5
Tools to automate process
Tool Create transformation rules.
Apply rules on desired environment scope.
Save rules for later reuse.
6
Rewrite Engine
Engine for code
transformation
Unintuitive
syntax & no GUI
to apply rules
Pros
Cons
7
“Scary” transformation rule
Left-Hand Side part
| `@temporaries |
`.InitializationStatement.
`@condition1
ifTrue: [
| `@otherTemporaries |
`@.Statements.
`@condition2
ifTrue: [ ``@value := ``@calculate ]
ifFalse: [ ``@value := `#wrongLiteral ] ]
Right-Hand Side part
| `@temporaries `@otherTemporaries |
`.InitializationStatement.
`@condition1
ifFalse: [ ^self ].
`@.Statements.
``@value := `@condition2
ifTrue: [ ``@calculate ]
ifFalse: [ `#wrongLiteral ]
8
Inattention causes impactful mistakes!
`.InitializationStatement `InitializationStatement
9
10
How to apply rules?
OR
| rule result aCollection anEnvironment |
aCollection := self environment.
anEnvironment := RBClassEnvironment
classes: aCollection.
rule := (Smalltalk globals at: self rules
selectedItem) new.
result := RBSmalllintChecker
runRule: rule
onEnvironment: anEnvironment.
(ChangesBrowser changes: result builder
changes) open
11
Rewrite Tool
´  Intuitive GUI
´  Real time result
´  Apply rules to any scope you want
´  Save rules for later reuse
12
A.  Input code
B.  Resulting code
C.  LHS part of rule
D.  RHS part of rule
13
15
Live Demo
16
Download & Info
´ http://smalltalkhub.com/#!/~MarkRizun/RewriteTool
´ Configuration Browser (Pharo4)
´ http://myfuncoding.com
´ Pharo For The Enterprise (RewriteTool chapter)
https://github.com/SquareBracketAssociates/PharoForTheEnterprise-english/tree/master/RewriteTool
Mark Rizun e-mail: mrizun@gmail.com blog: http://myfuncoding.blogspot.com/
17

More Related Content

What's hot

Exercise6 ch2
Exercise6 ch2Exercise6 ch2
Exercise6 ch2
IIUM
 
7.3 daqy 2
7.3 daqy 27.3 daqy 2
7.3 daqy 2
leblance
 

What's hot (17)

Code optimization
Code optimization Code optimization
Code optimization
 
Code Optimization
Code OptimizationCode Optimization
Code Optimization
 
Exercise6 ch2
Exercise6 ch2Exercise6 ch2
Exercise6 ch2
 
C programming Tutorial Session 1
C programming Tutorial Session 1C programming Tutorial Session 1
C programming Tutorial Session 1
 
7.3 daqy 2
7.3 daqy 27.3 daqy 2
7.3 daqy 2
 
Debugging Python with Pdb!
Debugging Python with Pdb!Debugging Python with Pdb!
Debugging Python with Pdb!
 
C programming Tutorial Session 4
C programming Tutorial Session 4C programming Tutorial Session 4
C programming Tutorial Session 4
 
Hash Function(Grostl) and Contex Hull Research paper
Hash Function(Grostl) and Contex Hull Research paperHash Function(Grostl) and Contex Hull Research paper
Hash Function(Grostl) and Contex Hull Research paper
 
Write a C function that returns the length of a string. Function name: strinq...
Write a C function that returns the length of a string. Function name: strinq...Write a C function that returns the length of a string. Function name: strinq...
Write a C function that returns the length of a string. Function name: strinq...
 
String functions in C
String functions in CString functions in C
String functions in C
 
NACA Regula Falsi Method
 NACA Regula Falsi Method NACA Regula Falsi Method
NACA Regula Falsi Method
 
Optimization in the world of 64-bit errors
Optimization  in the world of 64-bit errorsOptimization  in the world of 64-bit errors
Optimization in the world of 64-bit errors
 
Recurrence relationships
Recurrence relationshipsRecurrence relationships
Recurrence relationships
 
C programming - String
C programming - StringC programming - String
C programming - String
 
vhdl exp-5
vhdl exp-5vhdl exp-5
vhdl exp-5
 
Process of algorithm evaluation
Process of algorithm evaluationProcess of algorithm evaluation
Process of algorithm evaluation
 
Hw5 2017-spring
Hw5 2017-springHw5 2017-spring
Hw5 2017-spring
 

Similar to Code Transformation by Direct Transformation of ASTs

Detecting soft errors by a purely software approach
Detecting soft errors by a purely software approachDetecting soft errors by a purely software approach
Detecting soft errors by a purely software approach
Md. Hasibur Rashid
 
Software testing strategies
Software testing strategiesSoftware testing strategies
Software testing strategies
Krishna Sujeer
 

Similar to Code Transformation by Direct Transformation of ASTs (20)

Compilation
CompilationCompilation
Compilation
 
Compilation
CompilationCompilation
Compilation
 
Cs419 lec12 semantic analyzer
Cs419 lec12  semantic analyzerCs419 lec12  semantic analyzer
Cs419 lec12 semantic analyzer
 
refactoring code by clean code rules
refactoring code by clean code rulesrefactoring code by clean code rules
refactoring code by clean code rules
 
DAC CCAT GUESS PAPER Jun-Jul 2013
DAC CCAT GUESS PAPER Jun-Jul 2013 DAC CCAT GUESS PAPER Jun-Jul 2013
DAC CCAT GUESS PAPER Jun-Jul 2013
 
Javascript.ppt
Javascript.pptJavascript.ppt
Javascript.ppt
 
Phases of the Compiler - Systems Programming
Phases of the Compiler - Systems ProgrammingPhases of the Compiler - Systems Programming
Phases of the Compiler - Systems Programming
 
Unit1 C
Unit1 CUnit1 C
Unit1 C
 
Unit1 C
Unit1 CUnit1 C
Unit1 C
 
Introduction to Python Programming.pptx
Introduction to Python Programming.pptxIntroduction to Python Programming.pptx
Introduction to Python Programming.pptx
 
Detecting soft errors by a purely software approach
Detecting soft errors by a purely software approachDetecting soft errors by a purely software approach
Detecting soft errors by a purely software approach
 
Detecting soft errors by a purely software approach
Detecting soft errors by a purely software approachDetecting soft errors by a purely software approach
Detecting soft errors by a purely software approach
 
Libra : A Compatible Method for Defending Against Arbitrary Memory Overwrite
Libra : A Compatible Method for Defending Against Arbitrary Memory OverwriteLibra : A Compatible Method for Defending Against Arbitrary Memory Overwrite
Libra : A Compatible Method for Defending Against Arbitrary Memory Overwrite
 
GSP 215 Effective Communication - tutorialrank.com
GSP 215  Effective Communication - tutorialrank.comGSP 215  Effective Communication - tutorialrank.com
GSP 215 Effective Communication - tutorialrank.com
 
3 algorithm-and-flowchart
3 algorithm-and-flowchart3 algorithm-and-flowchart
3 algorithm-and-flowchart
 
Code optimization
Code optimizationCode optimization
Code optimization
 
Code optimization
Code optimizationCode optimization
Code optimization
 
Software testing strategies
Software testing strategiesSoftware testing strategies
Software testing strategies
 
Principal Sources of Optimization in compiler design
Principal Sources of Optimization in compiler design Principal Sources of Optimization in compiler design
Principal Sources of Optimization in compiler design
 
embedded C.pptx
embedded C.pptxembedded C.pptx
embedded C.pptx
 

More from ESUG

Workshop: Identifying concept inventories in agile programming
Workshop: Identifying concept inventories in agile programmingWorkshop: Identifying concept inventories in agile programming
Workshop: Identifying concept inventories in agile programming
ESUG
 
The Pharo Debugger and Debugging tools: Advances and Roadmap
The Pharo Debugger and Debugging tools: Advances and RoadmapThe Pharo Debugger and Debugging tools: Advances and Roadmap
The Pharo Debugger and Debugging tools: Advances and Roadmap
ESUG
 
Migration process from monolithic to micro frontend architecture in mobile ap...
Migration process from monolithic to micro frontend architecture in mobile ap...Migration process from monolithic to micro frontend architecture in mobile ap...
Migration process from monolithic to micro frontend architecture in mobile ap...
ESUG
 
Analyzing Dart Language with Pharo: Report and early results
Analyzing Dart Language with Pharo: Report and early resultsAnalyzing Dart Language with Pharo: Report and early results
Analyzing Dart Language with Pharo: Report and early results
ESUG
 
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
ESUG
 
A Unit Test Metamodel for Test Generation
A Unit Test Metamodel for Test GenerationA Unit Test Metamodel for Test Generation
A Unit Test Metamodel for Test Generation
ESUG
 
Creating Unit Tests Using Genetic Programming
Creating Unit Tests Using Genetic ProgrammingCreating Unit Tests Using Genetic Programming
Creating Unit Tests Using Genetic Programming
ESUG
 
Threaded-Execution and CPS Provide Smooth Switching Between Execution Modes
Threaded-Execution and CPS Provide Smooth Switching Between Execution ModesThreaded-Execution and CPS Provide Smooth Switching Between Execution Modes
Threaded-Execution and CPS Provide Smooth Switching Between Execution Modes
ESUG
 
Exploring GitHub Actions through EGAD: An Experience Report
Exploring GitHub Actions through EGAD: An Experience ReportExploring GitHub Actions through EGAD: An Experience Report
Exploring GitHub Actions through EGAD: An Experience Report
ESUG
 
Pharo: a reflective language A first systematic analysis of reflective APIs
Pharo: a reflective language A first systematic analysis of reflective APIsPharo: a reflective language A first systematic analysis of reflective APIs
Pharo: a reflective language A first systematic analysis of reflective APIs
ESUG
 
Improving Performance Through Object Lifetime Profiling: the DataFrame Case
Improving Performance Through Object Lifetime Profiling: the DataFrame CaseImproving Performance Through Object Lifetime Profiling: the DataFrame Case
Improving Performance Through Object Lifetime Profiling: the DataFrame Case
ESUG
 
Pharo DataFrame: Past, Present, and Future
Pharo DataFrame: Past, Present, and FuturePharo DataFrame: Past, Present, and Future
Pharo DataFrame: Past, Present, and Future
ESUG
 
A New Architecture Reconciling Refactorings and Transformations
A New Architecture Reconciling Refactorings and TransformationsA New Architecture Reconciling Refactorings and Transformations
A New Architecture Reconciling Refactorings and Transformations
ESUG
 

More from ESUG (20)

Workshop: Identifying concept inventories in agile programming
Workshop: Identifying concept inventories in agile programmingWorkshop: Identifying concept inventories in agile programming
Workshop: Identifying concept inventories in agile programming
 
Technical documentation support in Pharo
Technical documentation support in PharoTechnical documentation support in Pharo
Technical documentation support in Pharo
 
The Pharo Debugger and Debugging tools: Advances and Roadmap
The Pharo Debugger and Debugging tools: Advances and RoadmapThe Pharo Debugger and Debugging tools: Advances and Roadmap
The Pharo Debugger and Debugging tools: Advances and Roadmap
 
Sequence: Pipeline modelling in Pharo
Sequence: Pipeline modelling in PharoSequence: Pipeline modelling in Pharo
Sequence: Pipeline modelling in Pharo
 
Migration process from monolithic to micro frontend architecture in mobile ap...
Migration process from monolithic to micro frontend architecture in mobile ap...Migration process from monolithic to micro frontend architecture in mobile ap...
Migration process from monolithic to micro frontend architecture in mobile ap...
 
Analyzing Dart Language with Pharo: Report and early results
Analyzing Dart Language with Pharo: Report and early resultsAnalyzing Dart Language with Pharo: Report and early results
Analyzing Dart Language with Pharo: Report and early results
 
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
 
A Unit Test Metamodel for Test Generation
A Unit Test Metamodel for Test GenerationA Unit Test Metamodel for Test Generation
A Unit Test Metamodel for Test Generation
 
Creating Unit Tests Using Genetic Programming
Creating Unit Tests Using Genetic ProgrammingCreating Unit Tests Using Genetic Programming
Creating Unit Tests Using Genetic Programming
 
Threaded-Execution and CPS Provide Smooth Switching Between Execution Modes
Threaded-Execution and CPS Provide Smooth Switching Between Execution ModesThreaded-Execution and CPS Provide Smooth Switching Between Execution Modes
Threaded-Execution and CPS Provide Smooth Switching Between Execution Modes
 
Exploring GitHub Actions through EGAD: An Experience Report
Exploring GitHub Actions through EGAD: An Experience ReportExploring GitHub Actions through EGAD: An Experience Report
Exploring GitHub Actions through EGAD: An Experience Report
 
Pharo: a reflective language A first systematic analysis of reflective APIs
Pharo: a reflective language A first systematic analysis of reflective APIsPharo: a reflective language A first systematic analysis of reflective APIs
Pharo: a reflective language A first systematic analysis of reflective APIs
 
Garbage Collector Tuning
Garbage Collector TuningGarbage Collector Tuning
Garbage Collector Tuning
 
Improving Performance Through Object Lifetime Profiling: the DataFrame Case
Improving Performance Through Object Lifetime Profiling: the DataFrame CaseImproving Performance Through Object Lifetime Profiling: the DataFrame Case
Improving Performance Through Object Lifetime Profiling: the DataFrame Case
 
Pharo DataFrame: Past, Present, and Future
Pharo DataFrame: Past, Present, and FuturePharo DataFrame: Past, Present, and Future
Pharo DataFrame: Past, Present, and Future
 
thisContext in the Debugger
thisContext in the DebuggerthisContext in the Debugger
thisContext in the Debugger
 
Websockets for Fencing Score
Websockets for Fencing ScoreWebsockets for Fencing Score
Websockets for Fencing Score
 
ShowUs: PharoJS.org Develop in Pharo, Run on JavaScript
ShowUs: PharoJS.org Develop in Pharo, Run on JavaScriptShowUs: PharoJS.org Develop in Pharo, Run on JavaScript
ShowUs: PharoJS.org Develop in Pharo, Run on JavaScript
 
Advanced Object- Oriented Design Mooc
Advanced Object- Oriented Design MoocAdvanced Object- Oriented Design Mooc
Advanced Object- Oriented Design Mooc
 
A New Architecture Reconciling Refactorings and Transformations
A New Architecture Reconciling Refactorings and TransformationsA New Architecture Reconciling Refactorings and Transformations
A New Architecture Reconciling Refactorings and Transformations
 

Recently uploaded

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Recently uploaded (20)

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 

Code Transformation by Direct Transformation of ASTs

  • 1. Code Transformation by Direct Transformation of ASTs M. Rizun, J.-C. Bach, S. Ducasse 1
  • 2. Example of simple code transformation foo | result a b | a := 2. b := 3. result := a >= b ifTrue: [ a ] ifFalse: [ b ] foo | result a b | a := 2. b := 3. result := a max: b Source code Resulting code 2 transformation
  • 3. Manual code transformation process (in big system) Replace all found occurrences by target code. Search for all occurrences of the code to replace in the source code. Definition of the desired target code. (RHS) Definition of the code to change. (LHS) 3
  • 4. Find & Replace “…code…” x >= y ifTrue: [ x ] ifFalse: [ y ] “…code…” “…code…” x max: y “…code…” 4 Right-Hand Side partLeft-Hand Side part
  • 5. Problems Time-consuming and annoying task. Complex and error-prone process. Rules are not reusable. 5
  • 6. Tools to automate process Tool Create transformation rules. Apply rules on desired environment scope. Save rules for later reuse. 6
  • 7. Rewrite Engine Engine for code transformation Unintuitive syntax & no GUI to apply rules Pros Cons 7
  • 8. “Scary” transformation rule Left-Hand Side part | `@temporaries | `.InitializationStatement. `@condition1 ifTrue: [ | `@otherTemporaries | `@.Statements. `@condition2 ifTrue: [ ``@value := ``@calculate ] ifFalse: [ ``@value := `#wrongLiteral ] ] Right-Hand Side part | `@temporaries `@otherTemporaries | `.InitializationStatement. `@condition1 ifFalse: [ ^self ]. `@.Statements. ``@value := `@condition2 ifTrue: [ ``@calculate ] ifFalse: [ `#wrongLiteral ] 8
  • 9. Inattention causes impactful mistakes! `.InitializationStatement `InitializationStatement 9
  • 10. 10 How to apply rules?
  • 11. OR | rule result aCollection anEnvironment | aCollection := self environment. anEnvironment := RBClassEnvironment classes: aCollection. rule := (Smalltalk globals at: self rules selectedItem) new. result := RBSmalllintChecker runRule: rule onEnvironment: anEnvironment. (ChangesBrowser changes: result builder changes) open 11
  • 12. Rewrite Tool ´  Intuitive GUI ´  Real time result ´  Apply rules to any scope you want ´  Save rules for later reuse 12
  • 13. A.  Input code B.  Resulting code C.  LHS part of rule D.  RHS part of rule 13
  • 14.
  • 16. 16 Download & Info ´ http://smalltalkhub.com/#!/~MarkRizun/RewriteTool ´ Configuration Browser (Pharo4) ´ http://myfuncoding.com ´ Pharo For The Enterprise (RewriteTool chapter) https://github.com/SquareBracketAssociates/PharoForTheEnterprise-english/tree/master/RewriteTool
  • 17. Mark Rizun e-mail: mrizun@gmail.com blog: http://myfuncoding.blogspot.com/ 17