Groovy AST Transformations

  • 710 views
Uploaded on

Introduction to Groovy AST Transformations for Detroit JUG January 2013

Introduction to Groovy AST Transformations for Detroit JUG January 2013

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
710
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
11
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    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 ( http://en.wikipedia.org/wiki/Visitor_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