SlideShare une entreprise Scribd logo
1  sur  75
[object Object]
http://hamletdarcy.blogspot.com ,[object Object]
[object Object],[object Object],[object Object]
[object Object],[object Object]
[object Object],[object Object]
public class Person { private String firstName;  private String lastName;  void setFirstName(String fName) { this.firstName = fName;  } public String getFirstName() { return firstName;  } public void setLastName(String lName) { this.lastName = lName;  } public String getLastName() { return firstName;  } } import lombok.Getter; import lombok.Setter; public class Person { @Getter  @Setter  private String firstName;  @Getter  @Setter  private String lastname;  } ,[object Object]
@Getter / @Setter @ToString @EqualsAndHashCode @NoArgsConstructor @RequiredArgsConstructor  @AllArgsConstructor @Data @Cleanup @Synchronized @SneakyThrows @Log @Delegate val ,[object Object]
Generates Java Boilerplate Compile Time Only –  For Eclipse and javac –  IDEA & NetBeans too Removable with delombok –  Javadoc –  GWT Read the fine print –  Know what is generated –  Slows compilation times? ,[object Object]
[object Object],[object Object]
[object Object],[object Object]
[object Object],[object Object]
[object Object],Annotation Processor Javac Handler Eclipse Handler ,[object Object]
 
 
 
 
// javac private   void  generatePropertyChangeSupportField(JavacNode node) { if  (fieldAlreadyExists( PROPERTY_SUPPORT_FIELD_NAME , node))  return ; JCExpression exp = chainDots(node.getTreeMaker(), node,  "this" ); JCVariableDecl fieldDecl = newField() .ofType(PropertyChangeSupport. class ) .withName( PROPERTY_SUPPORT_FIELD_NAME ) .withModifiers( PRIVATE  |  FINAL ) .withArgs(exp) .buildWith(node); injectField(node, fieldDecl); } // ECJ private   void  generatePropertyChangeSupportField(EclipseNode node) { if  (fieldAlreadyExists( PROPERTY_SUPPORT_FIELD_NAME , node))  return ; Expression exp = referenceForThis(node.get()); FieldDeclaration fieldDecl = newField() .ofType(PropertyChangeSupport. class ) .withName( PROPERTY_SUPPORT_FIELD_NAME ) .withModifiers( PRIVATE  |  FINAL ) .withArgs(exp) .buildWith(node); injectField(node, fieldDecl); } Alex Ruiz – Custom AST  Transformations with Project Lombok http://www.ibm.com/developerworks/java/library/j-lombok/
[object Object],[object Object]
class Event { String title } class Event { String title public void getTitle() { title } public String setTitle(String t) { this.title = t  } } ,[object Object]
class Event { @Delegate Date when } class Event implements Comparable, Clonable { Date when boolean after(Date when) { this.when.after(when) } boolean before(Date when)  { this.when.before(when) } Object clone() { this.when.clone() }  Int compareTo(Date anotherDate)  { this.when.compareTo(otherDate)  } Int getDate()  { this.when.date } Int getDay()  { this.when.day } Int getHours()  { this.when.hours } Int getMinutes()  { this.when.minutes } Int getMonth()  { this.when.month } Int getSeconds()  { this.when.seconds } long getTime()  { this.when.time } Int getTimezoneOffset() {  this.when.timezoneOffset }  Int getYear()  { this.when.year } void setDate(int date) { this.when.date = date }  void setHours(int hours)  { this.when.hours = hours } void setMinutes(int minutes)  { this.when.minutes = minutes } void setMonth(int month)  { this.when.month = month } void setSeconds(int seconds) { this.when.seconds = seconds }  void setTime(long time) { this.when.time = time }  void setYear(int year)  { this.when.year = year } String toGMTString()  { this.when.toGMTString() } String toLocaleString() {  this.when.toLocaleString() }  } ,[object Object]
class Event { @Lazy ArrayList speakers } class Event { ArrayList speakers  def getSpeakers() { if (speakers != null) { return speakers } else { synchronized(this) { if (speakers == null) { speakers = [] }  return speakers } } } } ,[object Object]
@Immutable  class Event { String title } ,[object Object],–  Properties must be @Immutable or effectively immutable –  Properties are private –  Mutatators throw ReadOnlyPropertyException –  Map constructor created –  Tuple constructor created –  Equals(), hashCode() & toString() created –  Dates, Clonables, & arrays are defensively copied on way in & out (but not deeply cloned) –  Collections & Maps are wrapped in Immutable variants –  Non-immutable fields force an error –  Special handling for Date, Color, etc –  Many generated methods configurable ,[object Object]
[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Declarative Concurrency ,[object Object],Easier Cloning and Externalizing ,[object Object],Safer Scripting ,[object Object],[object Object],[object Object],[object Object]
[object Object],Local AST Transformations ,[object Object]
 
 
 
 
class  Event {   @Delegate Date when } @GroovyASTTransformationClass( "org.pkg.DelegateTransform" ) public  @ interface  Delegate {   ... } @GroovyASTTransformation(phase =  CANONICALIZATION ) public class   DelegateTransform   implements  ASTTransformation {   public void  visit(ASTNode[] nodes, SourceUnit source) {   ...   } } ,[object Object]
[object Object],[object Object]
[object Object],import   org.codehaus.groovy.ast.* import   org.codehaus.groovy.ast.stmt.* import   org.codehaus.groovy.ast.expr.* def   ast =  new  ReturnStatement( new  ConstructorCallExpression( ClassHelper. make (Date),   ArgumentListExpression. EMPTY_ARGUMENTS   ) ) assert  ast  instanceof  ReturnStatement ,[object Object]
[object Object],def  ast =  new  AstBuilder().buildFromSpec { returnStatement { constructorCall(Date) { argumentList {} } } } assert  ast[0]  instanceof  ReturnStatement ,[object Object]
[object Object],def  ast =  new  AstBuilder().buildFromString( 'new Date()' ) assert  assert ast[0]  instanceof  BlockStatement assert  ast[0].statements[0]  instanceof  ReturnStatement ,[object Object]
[object Object],def  ast =  new  AstBuilder().buildFromCode { new  Date() } assert  ast[0].statements[0]  instanceof  ReturnStatement ,[object Object]
[object Object],class  MainExample { @Main public   void  greet() { println  "Hello from greet()!" } } $ groovy MainExample.groovy  Hello from greet()! ,[object Object]
MethodNode makeMainMethod(MethodNode source) { def  className = source.declaringClass.name def  methodName = source.name def  ast =  new  AstBuilder().buildFromString( INSTRUCTION_SELECTION ,  false ,  """ package $source.declaringClass.packageName class $source.declaringClass.nameWithoutPackage { public static void main(String[] args) { new $className().$methodName() } } """ ) ast[ 1 ].methods.find { it.name ==  'main'  } } ,[object Object]
[object Object],[object Object]
How it Works Compiles Java to AST Analyzes AST Nodes Rewrites with Strings
(x != null && x instanceof SomeClass) @Override public void  visitBinaryExpression(PsiBinaryExpression exp) { if  (exp.token ==  '==' ) { if  (exp.left instanceof BinaryExpression ... ) { if  (exp.right instanceof BinaryExpression ... ) {   registerError(exp,  '...' ) } } } }
(x != null && x instanceof SomeClass) @Override public void visitBinaryExpression(PsiBinaryExpression expression) { super.visitBinaryExpression(expression); if (!expression.getOperationTokenType().equals(JavaTokenType.ANDAND)) { return; } PsiExpression lOperand = expression.getLOperand(); PsiExpression rOperand = expression.getROperand(); if (!isBinaryExpressionAndInstanceOfCheck(lOperand, rOperand) && !isBinaryExpressionAndInstanceOfCheck(rOperand, lOperand)) { return; } PsiBinaryExpression binaryExpression = getInnerBinaryExpression(expression); if (!binaryExpression.getOperationTokenType().equals(JavaTokenType.NE)) { return; } boolean leftIsNullCheck = isNullCheck(binaryExpression.getLOperand(), binaryExpression.getROperand()); boolean rightIsNullCheck = isNullCheck(binaryExpression.getROperand(), binaryExpression.getLOperand()); if (!leftIsNullCheck && !rightIsNullCheck) return; PsiReferenceExpression theReference = getReferenceFromNotNullCheck(binaryExpression); PsiExpression instanceOfOperand = getInstanceOfOperand(expression); if (!(instanceOfOperand instanceof PsiReferenceExpression)) { return; } String referenceNameA = (theReference).getReferenceName(); String referenceNameB = ((PsiReferenceExpression)instanceOfOperand).getReferenceName(); if (referenceNameA == null || referenceNameB == null) { return; } if (!referenceNameA.equals(referenceNameB)) { return; } registerError(expression); }
Rewrite: (x instanceof SomeClass) PsiElement andand = descriptor.getPsiElement(); if  (andand  instanceof  PsiBinaryExpression) { PsiExpression lhs = ((PsiBinaryExpression)andand).getLOperand(); PsiExpression rhs = ((PsiBinaryExpression)andand).getROperand(); if  (lhs  instanceof  PsiInstanceOfExpression) { replaceExpression((PsiBinaryExpression)andand, lhs.getText()); }  else if  (rhs  instanceof  PsiInstanceOfExpression) { replaceExpression((PsiBinaryExpression)andand, rhs.getText()); } }
Rewrite: (x instanceof SomeClass) when  (descriptor.psiElement) { is  PsiBinaryExpression @ ( val  lhs  is  PsiInstanceOfExpression, *) => replaceExpression(descriptor.psiElement, lhs.text)  is  PsiBinaryExpression @ (*,  val  rhs  is  PsiInstanceOfExpression) => replaceExpression(descriptor.psiElement, rhs.text)  } Kotlin's “Decomposer patterns”
How it Works Compiles Java to AST Analyzes AST Nodes Rewrites with Strings
[object Object],[object Object]
–  Dead Code –  Defects like Gstring as Map Key, Duplicate Map Key –  Return path analysis (null returns) –  Type inference (and improving) –  Concurrency Problems (busy wait, etc) –  Poor Testing Practices –  Un-Groovy code …  and 240+ more rules
How it works CodeNarc Rule:  Ban new java.util.Random() calls @Override void  visitConstructorCallExpression(   ConstructorCallExpression call) { if  (AstUtil.classNodeImplementsType(call. type , Random)) {   addViolation(call,  'Using Random is insecure...' )   }   super .visitConstructorCallExpression(call) }
How it works
How it works
How it works
[object Object],[object Object],[object Object],[object Object]
[object Object],From Terrence Parr's  “Language Implementation Patterns” ,[object Object],[object Object]
Embedded Languages def  s =  new  ArithmeticShell() assert 2 == s.evaluate( ' 1+1 ' ) assert 1.0 == s.evaluate( 'cos(2*PI)' ) public interface   GroovyCodeVisitor {   void  visitBlockStatement(BlockStatement statement);   void  visitForLoop(ForStatement forLoop);   void  visitWhileLoop(WhileStatement loop);   void  visitDoWhileLoop(DoWhileStatement loop);   ... }
[object Object],//FinallyStatement//ReturnStatement //SynchronizedStatement/Block[1][count(*) = 0] //AllocationExpression/ClassOrInterfaceType   [contains(@Image,'ThreadGroup')] | //PrimarySuffix   [contains(@Image, 'getThreadGroup')] ,[object Object],[object Object]
How it Works Compiles Groovy to AST Analyzes AST Nodes –  Not well typed –  Not many tokens –  unreliable with other AST Transforms
[object Object],[object Object],[object Object],[object Object]
[object Object],def   "Does simple math work?" () {   expect:   def  s =  new  ArithmeticShell()   s.evaluate(input) == output   where:   input  | output   '1 + 1'   | 2   'cos(2*PI)'   | 1.0 } ,[object Object],[object Object]
[object Object],Transform.jar | - transforms   | - global   | - CompiledAtASTTransformation.class   | - CompiledAtASTTransformation$_visit_closure1.class   | - ... | META-INF   | - services   | - org.codehaus.groovy.transform.ASTTransformation   | - org.codehaus.groovy.source.Extensions ,[object Object],[object Object]
[object Object],[object Object]
Ruby FizzBuzz 1.upto(100) do |n| print "Fizz" if a = ((n % 3) == 0) print "Buzz" if b = ((n % 5) == 0)  print n unless (a || b) print "" end
Mirah FizzBuzz 1.upto(100) do |n| print "Fizz" if a = ((n % 3) == 0) print "Buzz" if b = ((n % 5) == 0)  print n unless (a || b) print "" end
Mirah: Pure JVM Class Output public class Fizz-buzz { public static void main(String[] argv) { ... do { n = __xform_tmp_4; ... if (n % 15 == 0) System.out.println(&quot;FizzBuzz&quot;); else if (n % 5 == 0) System.out.println(&quot;Buzz&quot;); else if (n % 3 == 0) System.out.println(&quot;Fizz&quot;); else System.out.println(n); ... } while (__xform_tmp_4 <= __xform_tmp_5); } }
Mirah: .java File Output if (((n % 15) == 0)) { PrintStream temp$10 = System.out; temp$10.println(&quot;FizzBuzz&quot;); } else { if (((n % 5) == 0)) { PrintStream temp$11 = System.out; temp$11.println(&quot;Buzz&quot;); } else { if (((n % 3) == 0)) { PrintStream temp$12 = System.out; temp$12.println(&quot;Fizz&quot;); } else { PrintStream temp$13 = System.out; temp$13.println(n); } } }
What it Means –  Fast –  Lightweight –  Uses JDK –  Runs on Android? –  Runs on GWT?
How it Works
How it Works
 
Mirah Macros macro def eachChar(value, &block) quote {  `value`.toCharArray.each do | my_char | `block.body` end  } end eachChar('laat de leeeuw niet ...') do | my_char | puts my_char end
Mirah Macros class Person  make_attr :firstName, :string  end  p = Person.new p.firstName = 'hamlet' puts p.firstName
Mirah Macros macro def make_attr(name, type)  attribute_name = name.string_value() quote { def `name`  @`name`  end  def `&quot;#{attribute_name}_set&quot;`(value:`type`)  @`name` = value end  } end
[object Object],[object Object]
Difficult to find call-sites
Still Difficult to generate AST Macros are more general ,[object Object]
Easily quote ASTs into source

Contenu connexe

Tendances

Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2José Paumard
 
Kotlin as a Better Java
Kotlin as a Better JavaKotlin as a Better Java
Kotlin as a Better JavaGarth Gilmour
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!José Paumard
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Phil Calçado
 
Introduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoIntroduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoMuhammad Abdullah
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)Pavlo Baron
 
Develop your next app with kotlin @ AndroidMakersFr 2017
Develop your next app with kotlin @ AndroidMakersFr 2017Develop your next app with kotlin @ AndroidMakersFr 2017
Develop your next app with kotlin @ AndroidMakersFr 2017Arnaud Giuliani
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1José Paumard
 
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...Phil Calçado
 
ADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersBartosz Kosarzycki
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Languageintelliyole
 
​"Delegates, Delegates everywhere" Владимир Миронов
​"Delegates, Delegates everywhere" Владимир Миронов​"Delegates, Delegates everywhere" Владимир Миронов
​"Delegates, Delegates everywhere" Владимир МироновAvitoTech
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6Solution4Future
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesGanesh Samarthyam
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersBartosz Kosarzycki
 
Clojure for Java developers - Stockholm
Clojure for Java developers - StockholmClojure for Java developers - Stockholm
Clojure for Java developers - StockholmJan Kronquist
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé Paumard
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
Rust Workshop - NITC FOSSMEET 2017
Rust Workshop - NITC FOSSMEET 2017 Rust Workshop - NITC FOSSMEET 2017
Rust Workshop - NITC FOSSMEET 2017 pramode_ce
 

Tendances (20)

Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
Kotlin as a Better Java
Kotlin as a Better JavaKotlin as a Better Java
Kotlin as a Better Java
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)
 
Introduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoIntroduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demo
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
Develop your next app with kotlin @ AndroidMakersFr 2017
Develop your next app with kotlin @ AndroidMakersFr 2017Develop your next app with kotlin @ AndroidMakersFr 2017
Develop your next app with kotlin @ AndroidMakersFr 2017
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1
 
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
 
ADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developers
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Language
 
​"Delegates, Delegates everywhere" Владимир Миронов
​"Delegates, Delegates everywhere" Владимир Миронов​"Delegates, Delegates everywhere" Владимир Миронов
​"Delegates, Delegates everywhere" Владимир Миронов
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java Bytecodes
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
 
Clojure for Java developers - Stockholm
Clojure for Java developers - StockholmClojure for Java developers - Stockholm
Clojure for Java developers - Stockholm
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Rust Workshop - NITC FOSSMEET 2017
Rust Workshop - NITC FOSSMEET 2017 Rust Workshop - NITC FOSSMEET 2017
Rust Workshop - NITC FOSSMEET 2017
 
Java Generics - by Example
Java Generics - by ExampleJava Generics - by Example
Java Generics - by Example
 

Similaire à Ast transformations

Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...James Titcumb
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)James Titcumb
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldBTI360
 
Soundreader.classpathSoundreader.project Soundre.docx
Soundreader.classpathSoundreader.project  Soundre.docxSoundreader.classpathSoundreader.project  Soundre.docx
Soundreader.classpathSoundreader.project Soundre.docxwhitneyleman54422
 
C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607Kevin Hazzard
 
Patterns for JVM languages JokerConf
Patterns for JVM languages JokerConfPatterns for JVM languages JokerConf
Patterns for JVM languages JokerConfJaroslaw Palka
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Jesper Kamstrup Linnet
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecLoïc Descotte
 
05 pig user defined functions (udfs)
05 pig user defined functions (udfs)05 pig user defined functions (udfs)
05 pig user defined functions (udfs)Subhas Kumar Ghosh
 
Expression trees in c#
Expression trees in c#Expression trees in c#
Expression trees in c#Oleksii Holub
 
Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7Paulo Morgado
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodecamp Romania
 
Oop2010 Scala Presentation Stal
Oop2010 Scala Presentation StalOop2010 Scala Presentation Stal
Oop2010 Scala Presentation StalMichael Stal
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developersStoyan Stefanov
 
Introducing PHP Latest Updates
Introducing PHP Latest UpdatesIntroducing PHP Latest Updates
Introducing PHP Latest UpdatesIftekhar Eather
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Seri Moth
 

Similaire à Ast transformations (20)

What's New In C# 7
What's New In C# 7What's New In C# 7
What's New In C# 7
 
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
Soundreader.classpathSoundreader.project Soundre.docx
Soundreader.classpathSoundreader.project  Soundre.docxSoundreader.classpathSoundreader.project  Soundre.docx
Soundreader.classpathSoundreader.project Soundre.docx
 
C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607
 
Patterns for JVM languages JokerConf
Patterns for JVM languages JokerConfPatterns for JVM languages JokerConf
Patterns for JVM languages JokerConf
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
 
Groovy
GroovyGroovy
Groovy
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar Prokopec
 
05 pig user defined functions (udfs)
05 pig user defined functions (udfs)05 pig user defined functions (udfs)
05 pig user defined functions (udfs)
 
Expression trees in c#
Expression trees in c#Expression trees in c#
Expression trees in c#
 
Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
 
Scala - en bedre Java?
Scala - en bedre Java?Scala - en bedre Java?
Scala - en bedre Java?
 
Oop2010 Scala Presentation Stal
Oop2010 Scala Presentation StalOop2010 Scala Presentation Stal
Oop2010 Scala Presentation Stal
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Introducing PHP Latest Updates
Introducing PHP Latest UpdatesIntroducing PHP Latest Updates
Introducing PHP Latest Updates
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 

Plus de HamletDRC

Static Analysis and AST Transformations
Static Analysis and AST TransformationsStatic Analysis and AST Transformations
Static Analysis and AST TransformationsHamletDRC
 
Static Analysis in IDEA
Static Analysis in IDEAStatic Analysis in IDEA
Static Analysis in IDEAHamletDRC
 
10 Years of Groovy
10 Years of Groovy10 Years of Groovy
10 Years of GroovyHamletDRC
 
Java Boilerplate Busters
Java Boilerplate BustersJava Boilerplate Busters
Java Boilerplate BustersHamletDRC
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - GreachHamletDRC
 
Java Boilerplate Busters
Java Boilerplate BustersJava Boilerplate Busters
Java Boilerplate BustersHamletDRC
 

Plus de HamletDRC (6)

Static Analysis and AST Transformations
Static Analysis and AST TransformationsStatic Analysis and AST Transformations
Static Analysis and AST Transformations
 
Static Analysis in IDEA
Static Analysis in IDEAStatic Analysis in IDEA
Static Analysis in IDEA
 
10 Years of Groovy
10 Years of Groovy10 Years of Groovy
10 Years of Groovy
 
Java Boilerplate Busters
Java Boilerplate BustersJava Boilerplate Busters
Java Boilerplate Busters
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - Greach
 
Java Boilerplate Busters
Java Boilerplate BustersJava Boilerplate Busters
Java Boilerplate Busters
 

Dernier

A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
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 DiscoveryTrustArc
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 

Dernier (20)

A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
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
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 

Ast transformations

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.  
  • 14.  
  • 15.  
  • 16.  
  • 17. // javac private void generatePropertyChangeSupportField(JavacNode node) { if (fieldAlreadyExists( PROPERTY_SUPPORT_FIELD_NAME , node)) return ; JCExpression exp = chainDots(node.getTreeMaker(), node, &quot;this&quot; ); JCVariableDecl fieldDecl = newField() .ofType(PropertyChangeSupport. class ) .withName( PROPERTY_SUPPORT_FIELD_NAME ) .withModifiers( PRIVATE | FINAL ) .withArgs(exp) .buildWith(node); injectField(node, fieldDecl); } // ECJ private void generatePropertyChangeSupportField(EclipseNode node) { if (fieldAlreadyExists( PROPERTY_SUPPORT_FIELD_NAME , node)) return ; Expression exp = referenceForThis(node.get()); FieldDeclaration fieldDecl = newField() .ofType(PropertyChangeSupport. class ) .withName( PROPERTY_SUPPORT_FIELD_NAME ) .withModifiers( PRIVATE | FINAL ) .withArgs(exp) .buildWith(node); injectField(node, fieldDecl); } Alex Ruiz – Custom AST Transformations with Project Lombok http://www.ibm.com/developerworks/java/library/j-lombok/
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.  
  • 28.  
  • 29.  
  • 30.  
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40. How it Works Compiles Java to AST Analyzes AST Nodes Rewrites with Strings
  • 41. (x != null && x instanceof SomeClass) @Override public void visitBinaryExpression(PsiBinaryExpression exp) { if (exp.token == '==' ) { if (exp.left instanceof BinaryExpression ... ) { if (exp.right instanceof BinaryExpression ... ) { registerError(exp, '...' ) } } } }
  • 42. (x != null && x instanceof SomeClass) @Override public void visitBinaryExpression(PsiBinaryExpression expression) { super.visitBinaryExpression(expression); if (!expression.getOperationTokenType().equals(JavaTokenType.ANDAND)) { return; } PsiExpression lOperand = expression.getLOperand(); PsiExpression rOperand = expression.getROperand(); if (!isBinaryExpressionAndInstanceOfCheck(lOperand, rOperand) && !isBinaryExpressionAndInstanceOfCheck(rOperand, lOperand)) { return; } PsiBinaryExpression binaryExpression = getInnerBinaryExpression(expression); if (!binaryExpression.getOperationTokenType().equals(JavaTokenType.NE)) { return; } boolean leftIsNullCheck = isNullCheck(binaryExpression.getLOperand(), binaryExpression.getROperand()); boolean rightIsNullCheck = isNullCheck(binaryExpression.getROperand(), binaryExpression.getLOperand()); if (!leftIsNullCheck && !rightIsNullCheck) return; PsiReferenceExpression theReference = getReferenceFromNotNullCheck(binaryExpression); PsiExpression instanceOfOperand = getInstanceOfOperand(expression); if (!(instanceOfOperand instanceof PsiReferenceExpression)) { return; } String referenceNameA = (theReference).getReferenceName(); String referenceNameB = ((PsiReferenceExpression)instanceOfOperand).getReferenceName(); if (referenceNameA == null || referenceNameB == null) { return; } if (!referenceNameA.equals(referenceNameB)) { return; } registerError(expression); }
  • 43. Rewrite: (x instanceof SomeClass) PsiElement andand = descriptor.getPsiElement(); if (andand instanceof PsiBinaryExpression) { PsiExpression lhs = ((PsiBinaryExpression)andand).getLOperand(); PsiExpression rhs = ((PsiBinaryExpression)andand).getROperand(); if (lhs instanceof PsiInstanceOfExpression) { replaceExpression((PsiBinaryExpression)andand, lhs.getText()); } else if (rhs instanceof PsiInstanceOfExpression) { replaceExpression((PsiBinaryExpression)andand, rhs.getText()); } }
  • 44. Rewrite: (x instanceof SomeClass) when (descriptor.psiElement) { is PsiBinaryExpression @ ( val lhs is PsiInstanceOfExpression, *) => replaceExpression(descriptor.psiElement, lhs.text) is PsiBinaryExpression @ (*, val rhs is PsiInstanceOfExpression) => replaceExpression(descriptor.psiElement, rhs.text) } Kotlin's “Decomposer patterns”
  • 45. How it Works Compiles Java to AST Analyzes AST Nodes Rewrites with Strings
  • 46.
  • 47. – Dead Code – Defects like Gstring as Map Key, Duplicate Map Key – Return path analysis (null returns) – Type inference (and improving) – Concurrency Problems (busy wait, etc) – Poor Testing Practices – Un-Groovy code … and 240+ more rules
  • 48. How it works CodeNarc Rule: Ban new java.util.Random() calls @Override void visitConstructorCallExpression( ConstructorCallExpression call) { if (AstUtil.classNodeImplementsType(call. type , Random)) { addViolation(call, 'Using Random is insecure...' ) } super .visitConstructorCallExpression(call) }
  • 52.
  • 53.
  • 54. Embedded Languages def s = new ArithmeticShell() assert 2 == s.evaluate( ' 1+1 ' ) assert 1.0 == s.evaluate( 'cos(2*PI)' ) public interface GroovyCodeVisitor { void visitBlockStatement(BlockStatement statement); void visitForLoop(ForStatement forLoop); void visitWhileLoop(WhileStatement loop); void visitDoWhileLoop(DoWhileStatement loop); ... }
  • 55.
  • 56. How it Works Compiles Groovy to AST Analyzes AST Nodes – Not well typed – Not many tokens – unreliable with other AST Transforms
  • 57.
  • 58.
  • 59.
  • 60.
  • 61. Ruby FizzBuzz 1.upto(100) do |n| print &quot;Fizz&quot; if a = ((n % 3) == 0) print &quot;Buzz&quot; if b = ((n % 5) == 0) print n unless (a || b) print &quot;&quot; end
  • 62. Mirah FizzBuzz 1.upto(100) do |n| print &quot;Fizz&quot; if a = ((n % 3) == 0) print &quot;Buzz&quot; if b = ((n % 5) == 0) print n unless (a || b) print &quot;&quot; end
  • 63. Mirah: Pure JVM Class Output public class Fizz-buzz { public static void main(String[] argv) { ... do { n = __xform_tmp_4; ... if (n % 15 == 0) System.out.println(&quot;FizzBuzz&quot;); else if (n % 5 == 0) System.out.println(&quot;Buzz&quot;); else if (n % 3 == 0) System.out.println(&quot;Fizz&quot;); else System.out.println(n); ... } while (__xform_tmp_4 <= __xform_tmp_5); } }
  • 64. Mirah: .java File Output if (((n % 15) == 0)) { PrintStream temp$10 = System.out; temp$10.println(&quot;FizzBuzz&quot;); } else { if (((n % 5) == 0)) { PrintStream temp$11 = System.out; temp$11.println(&quot;Buzz&quot;); } else { if (((n % 3) == 0)) { PrintStream temp$12 = System.out; temp$12.println(&quot;Fizz&quot;); } else { PrintStream temp$13 = System.out; temp$13.println(n); } } }
  • 65. What it Means – Fast – Lightweight – Uses JDK – Runs on Android? – Runs on GWT?
  • 68.  
  • 69. Mirah Macros macro def eachChar(value, &block) quote { `value`.toCharArray.each do | my_char | `block.body` end } end eachChar('laat de leeeuw niet ...') do | my_char | puts my_char end
  • 70. Mirah Macros class Person make_attr :firstName, :string end p = Person.new p.firstName = 'hamlet' puts p.firstName
  • 71. Mirah Macros macro def make_attr(name, type) attribute_name = name.string_value() quote { def `name` @`name` end def `&quot;#{attribute_name}_set&quot;`(value:`type`) @`name` = value end } end
  • 72.
  • 73. Difficult to find call-sites
  • 74.
  • 75. Easily quote ASTs into source
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83. – Groovy Wiki and Mailing List is amazingly helpful
  • 84. – Use your creativity and patience
  • 85. – http://hamletdarcy.blogspot.com & @HamletDRC Groovy, Grails, Griffon, and Agile Consulting [email_address] or [email_address]