Your SlideShare is downloading. ×
Groovy AST Transformations
Upcoming SlideShare
Loading in...5

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Groovy AST Transformations


Published on

Introduction to Groovy AST Transformations for Detroit JUG January 2013

Introduction to Groovy AST Transformations for Detroit JUG January 2013

Published in: Technology

  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

No notes for slide
  • Grails – MVC framework with controllers and service classes in Groovy Griffon – Grails-like application framework for developing rich desktop applications Gaelyk – lightweight Groovy toolkit for building and deploying applications on Google App Engine Easyb – test specifications written in Groovy
  • Gant – tool for scripting Ant tasks using Groovy instead of XML to specify logic Gradle – enterprise-grade build system - Groovy build scripts - Dependency management - Used by hibernate, Grails, Groovy
  • This AST is a rooted tree made up of nodes that describes the various constructs within source code in a form that can be easily processed using the Visitor design pattern ( ). The Visitor design pattern essentially constructs a visitor object that traverses the tree and performs some action on each node in the tree.
  • Focus on automating repetative task of writing common methods likequals, hashCode and constructors
  • Verify using javap on OwnerClass
  • - Shorthand notation for every ASTNode type - API simplified - Helps eliminates some verbosity and complexity - Returns script class node as well - desired AST in first entry
  • Transcript

    • 1. Groovy AST Transformations
    • 2. What is Groovy?● A dynamic programming language that runs on the JVM● Language is essentially a superset of Java, in fact grammar to parse Groovy is constructed from Java grammar● Groovy source code is translated into Java bytecode by the Groovy compiler for execution on the JVM
    • 3. Where is Groovy?● Groovy as a scripting language● Frameworks for application development ● Grails – Web framework ● Griffon – Swing applications ● Gaelyk – Google App Engine● Testing ● Easyb – Behavior Driven Development ● Spock – BDD and mocking ● Gmock - Mocking
    • 4. Where is Groovy? (cont...)● Building projects ● Gradle ● Gant
    • 5. How does Groovy code become bytcode?
    • 6. What is an Abstract Syntax Tree?● Rooted tree of nodes● Composed of nodes that correspond to Groovy language constructs● We are interested in Groovys AST syntax tree● Composed of ASTNodes from the org.codehaus.groovy.ast package and subpackages● Tree structure lends itself to processing using Visitor design pattern
    • 7. What is an AST Transformation?● Compiler hook Groovy provides into compilation process● Means of extending language without grammar changes● Allows manipulation of AST during compilation prior to bytecode generation● Two types ● Local ● Global
    • 8. Local AST Transformations● More common● Applied to specific declarations whose AST is to be modified by the transformation● Annotation indicates AST transformation should be applied to declaration● AST is walked and AST transformation applied to nodes that are annotated with transformation annotation (Visitor design pattern)● Many supplied with Groovy distribution
    • 9. Global AST Transformations● Less common● Applied to every source unit in compilation● Uses jar file service provider mechanism to identify global AST transformations● Jar file added to classpath of compiler that contains service locator file identifying name of class that implements AST transformation
    • 10. Groovys Built-in AST Transformations● Code generation● Design pattern implementation● Simplified logging● Concurrency support● Cloning and externalization● JavaBeans support● Script safety● Static typing● Miscellaneous
    • 11. Code Generation● @ToString● @EqualsAndHashCode● @TupleConstructor● @Canonical● @Lazy● @InheritConstructors
    • 12. Example - @ToString@groovy.transform.ToStringclass Person { String first, last}def person = new Person(first:"Hamlet", last:"DArcy")println "${person.toString()}"Result with @ToString transformation:Person(Hamlet, DArcy)Result without @ToString transformation:Person@175078b
    • 13. Design Pattern Implementation● @Delgate● @Singleton● @Immutable● @Mixin● @Category
    • 14. Example - @Delegateclass Delegate1Class { public void method1() {} public void method2(String p) {}}public class OwnerClass { @Delegate Delegate1Class delegate1 = new Delegate1Class()}The @Delegate AST transformation implements delegation byadding all of the public methods from the delegate class to theowner class.
    • 15. Simplified Logging● @Log● @Log4j● @Slf4j● @Commons
    • 16. Concurrency Support● @Synchronized● @WithReadLock● @WithWriteLock
    • 17. Cloning and Externalization● @AutoClone● @AutoExternalize
    • 18. JavaBeans Support● @Bindable● @Vetoable● @ListenerList
    • 19. Scripting Safety● @TimedInterrupt● @ThreadInterrupt● @ConditionalInterrupt
    • 20. Static Typing● @TypeChecked● @CompileStatic
    • 21. Example - @TypeChecked@groovy.transform.TypeCheckedNumber test() { // Cannot find matching method MyMethod() // Variable is undelcared println myField // Cannot assign String to int int object = "myString" // Cannot return value of type String on method returning type Number return "myString"}
    • 22. Miscellaneous● @Field● @PackageScope● @Newify
    • 23. Location of Built-in AST Transformations● Annotation definition usually found in groovy.transform or groovy.lang● Implementation class usually found in org.codehaus.groovy.transform
    • 24. Custom AST Transformations● Defined in exactly same manner as built-in AST transformations● Steps 1. Create AST transformation implementation class that implements the ASTTransformation interface 2. Create AST transformation annotation declaration and link it to the implementation class with the @GroovyASTTransformationClass annotation
    • 25. The Implementation Class● Implements the ASTTransformation interface ● Single method void visit(ASTNode nodes[], SourceUnit source)● Compiler invokes this method on AST of annotated element● nodes array contains AnnotationNode for AST transformation annotation and AnnotatedNode corresponding to annotated declaration
    • 26. HelloWorldASTTransformation@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)public class HelloWorldASTTransformation implements ASTTransformation { public void visit(ASTNode[] nodes, SourceUnit source) { MethodNode methodNode = (MethodNode)nodes[1] Statement methodCode = methodNode.getCode() // // Add greeting to beginning of code block. // methodCode.getStatements().add(0, createPrintlnStatement()) }
    • 27. The Annotation Type Declaration● Indicate declaration types to which AST transformation is applicable with @Target annotation● Indicate implementation class with @GroovyASTTransformationClass annotation
    • 28. HelloWorld@Target([ElementType.METHOD])@GroovyASTTransformationClass("HelloWorldASTTransformation")public @interface HelloWorld {}
    • 29. HelloWorldExample@HelloWorldvoid myMethod() {}myMethod()
    • 30. The Hard Part – Creating AST objects● Tools to help ● AST Browser ● ASTBuilder● Ways to create AST objects ● Manually using ASTNode subclass constructors (leveraging AST Browser) ● Using ASTBuilder.buildFromSpec ● Using ASTBuilder.buildFromString ● Using ASTBuilder.buildFromCode
    • 31. Implementing createPrintlnStatement Manuallyprivate Statement createPrintlnStatement() { Statement printlnStatement = new ExpressionStatement( new MethodCallExpression( new VariableExpression("this"), new ConstantExpression("println"), new ArgumentListExpression( new ConstantExpression("Hello World!!!!")) )) return printlnStatement}
    • 32. Implementing createPrintlnStatement using buildFromSpec private Statement createPrintlnStatement() { List<ASTNode> results = new AstBuilder().buildFromSpec { expression { methodCall { variable "this" constant "println" argumentList { constant "Hello World!!!!" } } } } return results[0] }
    • 33. Implementing createPrintlnStatement using buildFromStringprivate Statement createPrintlnStatement() { List<ASTNode> result = new AstBuilder().buildFromString("println Hello World!!!!; return") return result[0]}
    • 34. Implementing createPrintlnStatement using buildFromCodeprivate Statement createPrintlnStatement() { List<ASTNode> result = new AstBuilder().buildFromCode { println "Hello World!!!!" return } return result[0]}
    • 35. Resources● Groovy code itself provides excellent examples● AST Browser is invaluable for seeing what code is generated by a transformation● Groovy in Action (2nd edition) in MEAP – Chapter 9 written by Hamlet DArcy● Unit tests for ASTBuilder● Shameless plug: Groovy Under the Hood in GroovyMag