More Related Content Similar to Groovy, Transforming Language (20) More from Uehara Junji (20) Groovy, Transforming Language2. Slide# 2 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
3. •
• NTT
• JGGUG
• “Gr ”
• “Grails ”
• JavaWorld
• Twitter: uehaj
Slide# 3 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
4. • Groovy
• Groovy
• Groovy
• Groovy
• Groovy
• Groovy
• Groovy
•
Slide# 4 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
5. Slide# 5 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
6. Slide# 6 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
7. • Java (Stand by me)
Slide# 6 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
8. • Java (Stand by me)
• JavaVM
Slide# 6 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
9. • Java (Stand by me)
• JavaVM
• Java ( )
Slide# 6 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
10. • Java (Stand by me)
• JavaVM
• Java ( )
• Java
• annotation/enum/generics/vararg/static import/
Slide# 6 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
11. • Java (Stand by me)
• JavaVM
• Java ( )
• Java
• annotation/enum/generics/vararg/static import/
• JSP
Slide# 6 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
12. • Java (Stand by me)
• JavaVM
• Java ( )
• Java
• annotation/enum/generics/vararg/static import/
• JSP
:(Java )
Slide# 6 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
13. • Scala JRuby
• Scala Ruby
•
Java API
•
• Groovy
• Java
• Java
• Maven Java
Slide# 7 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
14. • Java API GDK
Java
•
• , / ,etc
•
• (DSL)
Slide# 8 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
15. import java.io.*; String line;
import java.net.*; while ((line = bis.readLine()) != null)
System.out.println(line);
public class SocketAccess { }
}
public static void main(String[] args) { catch (IOException e) {
Socket soc = null; e.printStackTrace();
InputStream ins = null; try {
OutputStream outs = null; if (soc != null) soc.close();
try { }
soc = new Socket("www.java-users.jp", 80); catch(IOException ex) {}
ins = soc.getInputStream(); }
outs = soc.getOutputStream(); }
outs.write("GET / HTTP/1.0nn".getBytes()); }
BufferedReader bis = new
BufferedReader(new InputStreamReader(ins));
Slide# 9 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
16. import java.io.*; String line;
import java.net.*; while ((line = bis.readLine()) != null)
System.out.println(line);
public class SocketAccess { }
}
public static void main(String[] args) { catch (IOException e) {
Socket soc = null; e.printStackTrace();
InputStream ins = null; try {
OutputStream outs = null; if (soc != null) soc.close();
try { }
soc = new Socket("www.java-users.jp", 80); catch(IOException ex) {}
ins = soc.getInputStream(); }
outs = soc.getOutputStream(); }
outs.write("GET / HTTP/1.0nn".getBytes()); }
BufferedReader bis = new
BufferedReader(new InputStreamReader(ins));
Slide# 10 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
17. import java.io.*; String line;
import java.net.*; while ((line = bis.readLine()) != null)
System.out.println(line);
public class SocketAccess { }
}
public static void main(String[] args) { catch (IOException e) {
Socket soc = null; e.printStackTrace();
InputStream ins = null; try {
OutputStream outs = null; if (soc != null) soc.close();
try { }
soc = new Socket("www.java-users.jp", 80); catch(IOException ex) {}
ins = soc.getInputStream(); }
outs = soc.getOutputStream(); }
outs.write("GET / HTTP/1.0nn".getBytes()); }
BufferedReader bis = new
BufferedReader(new InputStreamReader(ins));
Slide# 10 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
24. •
•
• (what)
SN
•
1
•
Slide# 13 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
25. •
•
(Algol, Common Lisp, Ada, C++…)
(Polyglot Programing)
• Groovy
Java
Slide# 14 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
26. Slide# 15 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
27. 2003 2004 2005
8 3 2
▲ ▲
1.0b4 1.0b10
JSR JSR EA
2006 2007 2008 2009
7 2 4 12 2 12 8
▲ ▲ ▲ ▲ ▲ ▲ ▲
1.0 JSR-6 1.0 1.1b2 1.5.0 1.5.4 1.5.7 1.6.4
Grails Grails 1.6-rc1 1.7-b1
0.3 0.5.6
Slide# 16 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
28. • 2004
?
• SyntaxError Stacktrace!
•
• Grails
• JRuby
Slide# 17 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
29. Slide# 18 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
30. •
(1.6 )
• Grape(1.6 )
• AST (1.6 )
• Power Assert(1.7 )
Slide# 19 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
31. Slide# 20 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
32. 'ls'.metaClass.exec = { new File(".").eachFile{println it} }
'pwd'.metaClass.exec = { println new File(".").absolutePath }
'env'.metaClass.exec = {
System.getenv().each{k,v->println "$k=$v" }
}
System.in.eachLine {
it.intern().exec()
}
Slide# 21 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
34. transformation
• Groovy
(AST )
• Groovy
• AST AST
aka
Slide# 23 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
35. (Antlr) (Antlr) (ASM)
a=a+a 0xCAFEBABE
........
Groovy Java
Slide# 24 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
36. (Antlr) (Antlr) (ASM)
=
a=a+a a = a + 1 a + 0xCAFEBABE
........
a 1
Groovy Java
AST
Slide# 24 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
37. (Antlr) (Antlr) (ASM)
=
a=a+a a = a + 1 a + 0xCAFEBABE
........
a 1
Groovy Java
AST
AST
Slide# 24 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
38. (Antlr) (Antlr) (ASM)
=
a=a+a a = a + 1 a + 0xCAFEBABE
........
a 1
Groovy Java
AST
AST
AST
Slide# 24 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
39. (Antlr) (Antlr) (ASM)
=
a=a+a a = a + 1 a + 0xCAFEBABE
........
a 1
Groovy Java
AST
AST
AST
AST
Slide# 24 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
40. (Antlr) (Antlr) (ASM)
=
a=a+a a = a + 1 a + 0xCAFEBABE
........
a 1
Groovy Java
AST
AST
AST
AST
Slide# 24 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
41. • AST
•
AST
• AST
•
Slide# 25 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
42. •
• groovyc AST
• groovy
•
Groovy
Slide# 26 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
44. JAR
Grape(@Grab)
(Apache Ivy )
Assert
Power Assert
AST Groovy
ASTBuilder
AST
Slide# 28 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
45. @Grab('org.mortbay.jetty:jetty-embedded:6.1.0')
import org.mortbay.jetty.Server
import org.mortbay.jetty.servlet.*
import groovy.servlet.*
def server = new Server(8080)
def context = new Context(server, "/", Context.SESSIONS)
context.resourceBase = "."
context.addServlet(TemplateServlet, "*.gsp")
server.start()
• jetty Jar
• Maven Jar ‾/.groovy/
grapes
Slide# 29 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
46. a = 4
assert 1+Math.max(3,a)*5==3
==>
EXCEPTION:
Assertion failed:
assert 1+Math.max(3,a)*5==3
| | | | |
21 4 4 | false
25
• assert FAIL
Slide# 30 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
47. @Bindable / Swing
@Vetoable (java.beans. PropertyChangeSupport )
@Singleton
@Immutable
@Delegate
@Lazy
@Category
@Mixin mixin
@Newify Python/Ruby new( : Integer(5),
Integer.new(5))
@PackageScope package
Slide# 31 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
48. •
@Singleton
class Foo {
def hello() { println "hello" }
}
Foo.instance.hello() //
a = new Foo() // new
==>
EXCEPTION:
java.lang.RuntimeException: Can't instantiate
singleton Foo. Use Foo.instance
at Foo.<init>(Script1.groovy)
at Script1.run(Script1.groovy:6)
Slide# 32 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
49. •
@Immutable
final class Foo {
String x, y
}
a = new Foo(x:"a",y:"b")
a.x = "hoge" //
==>
EXCEPTION:
groovy.lang.ReadOnlyPropertyException: Cannot set
readonly property: x for class: Foo
at Foo.setProperty(Script1.groovy)
at Script1.run(Script1.groovy:6)
Slide# 33 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
50. • /Proxy
import java.util.concurrent.locks.*
class LockableMap {
@Delegate private Map map = [:]
@Delegate private Lock lock = new ReentrantLock ()
}
res = new LockableMap()
res.lock() // Lock
try {
res.a = 0 // Map
} finally {
res.unlock ()
}
assert res instanceof Map
assert res instanceof Lock
Slide# 34 JJUG CCC 2009 Fall / 2009.10.08
http://www.infoq.com/jp/articles/groovy-1-6
2009 10 10
51. •
class LazyTest {
@Lazy List s1 ={println "s1 initializing"; [1,2,3] }();
List s2 = {println "s2 initializing"; [4,5,6] }();
}
x = new LazyTest()
// s2 initializing
println x.s1 // s1
// s1 initializing
// [1, 2, 3]
println x.s2
// [4, 5, 6]
println x.s1
// [1, 2, 3]
Slide# 35 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
52. • use
@Category(String)
class TrMethod {
String tr(from,to) {
def result = this
from.eachWithIndex{it,idx->
result = result.replaceAll(it, to.getAt(idx))
}
result
}
}
use (TrMethod) {
assert 'abcdef 123'.tr('abc ','XYZ ')
== 'XYZdef 123'
}
Slide# 36 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
53. •
class Dumpable { x = new MyClass()
void dump() { x.dump()
this.metaClass.methods.each{ ==>
println it.name } toString
this.metaClass.properties.each { dump
println it.name } get__timeStamp__239_ne
} 28920761
} set__timeStamp__239_ne
28920761
@Mixin(Dumpable) equals
class MyClass { getClass
int field :
void foo() {} bar
int bar(String i) {} foo
} field
Slide# 37 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
54. • Python/Ruby new
class Test {
@Newify(String) // Python
static test() {
def s0 = new String("hoge") // Groovy/Java
def s1 = String("hoge") // Python
def s2 = String.new("hoge") // Ruby
}
}
Slide# 38 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
56. • AST
•
( AST
)
•
Groovy
Slide# 40 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
57. • AST
•
• AST
• META-INF/services/
org.codehaus.groovy.transform.AST
Transformation
• Groovy (JAR )
Slide# 41 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
58. •
ASTTransformation
•
• void visit(ASTNode[] nodes,
SourceUnit source)
• SourceUnit getSourceUnit()
• visit() AST
Visitor
Slide# 42 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
59. • _FILE_, _LINE_,
_CLASS_, _METHOD_
AST
• log("$_FILE_:$_LINE_:
$_CLASS_:$_METHOD_
", ..)
Slide# 43 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
60. package org.jggug.transform
import org.codehaus.groovy.transform.GroovyASTTransformationClass;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.SOURCE)
@Target([ElementType.TYPE])
@GroovyASTTransformationClass("org.jggug.transform.U
seSourceInfoSymbolASTTransformation")
public @interface UseSourceInfoSymbol {
}
AST
Slide# 44 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
61. package org.jggug.transform
void visitConstructorOrMethod(MethodNode
import org.codehaus.groovy.ast.*; node, boolean isConstructor) {
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.Statement; visitingMethod = node.name
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit; super.visitConstructorOrMethod(node,
import org.codehaus.groovy.transform.ASTTransformation;
import org.codehaus.groovy.transform.GroovyASTTransformation; isConstructor)
}
@GroovyASTTransformation(phase = ( )
CompilePhase.CANONICALIZATION)
public class
UseSourceInfoSymbolASTTransformation extends
ClassCodeExpressionTransformer implements
ASTTransformation {
private SourceUnit sourceUnit;
SourceUnit getSourceUnit() {
return sourceUnit;
}
String visitingMethod = null
String visitingClass = null
void visit(ASTNode[] nodes, SourceUnit
source) {
sourceUnit = source;
def parent = nodes[1]
visitingClass = parent.name
super.visitClass(parent)
}
Slide# 45 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
62. Expression transform(Expression exp) {
if (exp == null) return null;
switch (exp.class) {
case VariableExpression.class:
switch (exp.name) {
case '_FILE_': return new ConstantExpression(sourceUnit.name)
case '_LINE_': return new ConstantExpression(exp.lineNumber)
case '_COLUMN_': return new ConstantExpression(exp.columnNumber)
case '_CLASS_': return new ConstantExpression(visitingClass)
case '_METHOD_': return new ConstantExpression(visitingMethod)
default: return exp
}
case MethodCallExpression.class:
def args = transform(exp.arguments);
def method = transform(exp.method);
def object = transform(exp.objectExpression);
return new MethodCallExpression(object, method, args);
case ClosureExpression.class:
Statement code = exp.code;
if (code == null) return exp
return code.visit(this)
case ConstructorCallExpression.class:
return exp.transformExpression(this)
default:
return exp.transformExpression(this)
}
}
}
Slide# 46 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
63. import org.jggug.transform.UseSourceInfoSymbol
@UseSourceInfoSymbol
class Test {
def foo(hoge, fuga) {
println _FILE_+':'+_LINE_
println _FILE_+':'+_LINE_
println _FILE_+':'+_LINE_
println _FILE_+':'+_LINE_ ==>
println _FILE_+':'+_LINE_ /tmp/test02.groovy:6
println _CLASS_+':'+_METHOD_ /tmp/test02.groovy:7
} /tmp/test02.groovy:8
} /tmp/test02.groovy:9
/tmp/test02.groovy:10
test = new Test() sample.Test:foo
test.foo(1,2)
Slide# 47 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
64. • $b
(Java 7 )
@UseBinaryLit
eral println $b01_001_0001
==> 145
@WithTimeout @WithTimeout(3) def work()
{ ....... }
@Define(symbol="that", value="delegate")
@Define @Define(symbol=" ", value="it")
@Define(symbol=" ", value="this")
Slide# 48 @Define(symbol="
JJUG CCC 2009 Fall / 2009.10.08 ", value="println")
2009 10 10
65. • groovyConsole AST
Slide# 49 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
66. • ASTBuilder
• buildFromSpec … AST DSL
• buildFromString …
AST
• buildFromCode … (
) AST
Slide# 50 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
67. •
•
•
•
• Scala @Scalify
Slide# 51 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
68. Slide# 52 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
69. • Groovy Java
•
• :
• DSL
•
•
Slide# 53 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10
71. • http://groovy.codehaus.org/Compile-time+Metaprogramming+-+AST
+Transformations
Compile-time Metaprogramming - AST Transformations
• http://groovy.codehaus.org/AST+Macros+and+Annotations
AST Macros and Annotations
• http://groovy.codehaus.org/Building+AST+Guide
Building AST in Groovy 1.6 and Prior
• http://kartik-shah.blogspot.com/2009/03/groovy-16-ast-
transformation-example_5323.html
Groovy 1.6 AST Transformation Example
• http://www.infoq.com/jp/articles/groovy-1-6
Groovy 1.6 - Groovy
• http://www.slideshare.net/paulk_asert/groovy-testing-
aug2009-1945995
Groovy Testing Sep2009
• http://dl.getdropbox.com/u/132573/groovy_scala/index.html
Groovy Scala: JVM
•
Slide# 55 JJUG CCC 2009 Fall / 2009.10.08
2009 10 10