Upload
mario-garcia
View
552
Download
3
Embed Size (px)
Citation preview
MACROMACRO,BURRITOMACROMACRO,BURRITOMACROMACRO,BURRITOMACROMACRO,BURRITOMACROMACRO,BURRITOMACROMACRO,BURRITO
MACROMACRO,BURRITO
MACROMACRO,BURRITO
MACROMACRO,BURRITO
MACROMACRO,BURRITO
MACROMACRO,BURRITO
MACROMACRO,BURRITO
MACROMACRO,BURRITO
MACROMACRO,BURRITO
MACROMACRO,BURRITOMACROMACRO,BURRITO
BURRITOBURRITOBURRITOBURRITOBURRITOBURRITO
BURRITO
BURRITO
BURRITO
BURRITO
BURRITO
BURRITO
BURRITO
BURRITO
BURRITOBURRITO@marioggar
1
SOBREMIMarioGarcia
TrabajoenKaleidos
ProgramoconGroovy,JDK_8
https://twitter.com/marioggar
http://kaleidos.net/
2
DEQUEVOYAHABLAR?Metaprogramacion
Macros
Asteroid
3
THEORY101TeoriabasicaparaentenderelapiAST.
4
QUE
5 . 1
ABSTRACTSYNTAXTREEElcompiladornecesitaunarepresentaciondetucodigo:
5 . 2
EXPRESSIONSUnaexpresionesunacombinaciondeunoomasvalores,constantesvariables,operadores,yfuncionesqueel
lenguagedeprogramacioninterpretayejecutaparaproducirotrovalor.
5 . 3
BINARY⇒BOOLEANBinaryExpression
constantexpression1
token==
constantexpression1
1==1
5 . 4
VARIABLE⇒CONSTANT⇒CALL
variableexpressionref
constantmyMethod
paramexpression3
ref.myMethod(3)
5 . 5
SENTENCIASEnprogramacion,unasentenciaeslapartemaspequenadeunlenguagedeprogramacionimperativoqueexpresauna
accionquesedebellevaracabo.Unasentenciapuedetenerexpresiones.
5 . 6
IFSTATEMENT
expressiontoevaluate
statementtobeexecutedifthebooleanexpressionevaluatestotrue
if(booleanExpression){println"hello"//statement}
5 . 7
BLOCKSTATEMENT
Ablockstatementiseasilyrecognizedbycurlybraces
Itisbuiltfromotherstatementscontainingexpressions
publicvoidmain(String[]args){//blockstarts//thisisinsideablockstatement}//blockends
5 . 8
BLOCKSTATEMENT(CONT.)
ThisblockstatementcontainsareturnstatementreceivingaconstantexpressionHelloGreach.
publicStringgreetings(){return"HelloGreach"}
5 . 9
NODES
—LordoftheRings
Aringtorulethemall
5 . 10
NODES(CONT.)Comoestaestructuradonuestroprograma.Agrupana
sentenciayexpressions.
classes
methods
fields
properties
…
5 . 11
ACLASSNODE
ClassNodemaycontain:methods,fields…MethodNodemaycontainstatements,andexpressions
…
classA{//ClassNodeStringgreetings//FieldNode
Stringhello(){//MethodNode
}}
5 . 12
PORLOTANTOclassA{//ClassNode
Stringhello()//MethodNode{//blockStatement{
return"Hello"//returnStatement(constantExpression)
}//}}
5 . 13
CUANDO
6 . 1
ENQUEMOMENTOSPUEDOENGANCHARMEALCOMPILADORPARACAMBIARELAST?
Dependsontypeoftransformation(LocalvsGlobal)
DependsontheCompilationPhaseyouneedtotarget
6 . 2
COMPILATIONPHASESInitialization,Parsing,Conversion,Semantic,Canonicalization,Instruction,Class,Output,Finalization
GroovyReference
6 . 3
RESUMIENDOSemanticAnalysis
Canonicalization
Instruction
Beforethatyouhavenotypes/scopes/imports…AfterthatyoubetterknowByteCode-Kunfu
6 . 4
METAPROGRAMACION
7 . 1
7 . 2
QUEES?"Metaprogrammingblablablabla…Itmeansthataprogramcouldbedesignedtoread,generate,analyseortransformotherprograms,andevenmodifyitselfwhilerunning.bla
blablabla…blablablablablablaminimizethenumberoflinesofcodetoexpressasolution…yblablabla.
— https://en.wikipedia.org/wiki/Metaprogramming
7 . 3
RESUMIENDO… Leer,generar,analizar,transformartucodigo
Tratadeexpresarlomismoconmenoscodigo
7 . 4
7 . 5
DOSSABORES:EntiempodeEJECUCION
EntiempodeCOMPILACION
7 . 6
TIEMPODEEJECUCION:PROSSencillo
Facildetestear
7 . 7
TIEMPODEEJECUCION:CONSDificildeaplicaraisladamente
Problemadepoluciondelcodigo
Tedascuentadelosproblemasentiempodeejecucion
7 . 8
EJEMPLOS:QUICKDEMO
7 . 9
TIEMPODEEJECUCION:TABLAName Category Difficulty
invokeMethod Runtime Easy
method/propertyMissing Runtime Easy
MetaClass Runtime Easy/Tricky
7 . 10
TIEMPODECOMPILACION:PROSPuedescontrolarmejorcomoseaplicanloscambios
Puedescrearnuevasformasdeexpresartucodigo
Muchosproblemassedetectanporelcompilador
7 . 11
TIEMPODECOMPILACION:CONSHastaahoracurvadeapredizajeparecidaa…Haskell?
DesconocimientodelcompiladordeGroovy
7 . 12
TIEMPODECOMPILACION:TABLAName Category Difficulty
Traits Compiletime Super-Easy
Extensions Compiletime Easy
Local Compiletime Hard
Global Compiletime Hardcore
7 . 13
PORQUESONNECESARIASLASMACROS?
8
ENPARTEPOR…
9
LAVIEJATRANSFORMACIONAST
10 . 1
10 . 2
COSASQUENOCAMBIANTransformacionesLOCALES
TransformacionesGLOBALES
10 . 3
ASTLOCALES
11 . 1
UN"SIMPLE"EJEMPLO:
11 . 2
ANOTACIONpackagecompile.old.local.md5
importorg.codehaus.groovy.transform.GroovyASTTransformationClass
importjava.lang.annotation.ElementTypeimportjava.lang.annotation.Retentionimportjava.lang.annotation.RetentionPolicyimportjava.lang.annotation.Target
@Retention(RetentionPolicy.SOURCE)@Target([ElementType.TYPE])@GroovyASTTransformationClass(["compile.old.local.md5.MD5Transform"])@interfaceMD5{}
11 . 3
TRANSFORMATIONimportorg.codehaus.groovy.ast.*importorg.codehaus.groovy.control.*importorg.codehaus.groovy.transform.*
@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classMD5TransformextendsAbstractASTTransformation{@Overridevoidvisit(ASTNode[]nodes,SourceUnitsourceUnit){//...}}
11 . 4
APLICACIONpackagecompile.old.local.md5
@MD5classDocument{
FilefileStringname
voidprintMD5(){println"===>${nameAsMD5()}"println"===>${fileAsMD5()}"}}
11 . 5
VEAMOSLATRANSFORMACION…
11 . 6
11 . 7
TRANSFORMACION(I)imports
importstaticorg.codehaus.groovy.ast.tools.GeneralUtils.*importstaticorg.codehaus.groovy.ast.ClassHelper.*
importorg.codehaus.groovy.ast.*importorg.codehaus.groovy.ast.expr.*importorg.codehaus.groovy.ast.stmt.*
importorg.codehaus.groovy.control.*importorg.codehaus.groovy.transform.*
11 . 8
TRANSFORMACION(II)clasetransformacion
@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classMD5TransformextendsAbstractASTTransformation{
11 . 9
TRANSFORMACION(III)visitmethod
@Overridevoidvisit(ASTNode[]nodes,SourceUnitsourceUnit){ClassNodecurrentClass=(ClassNode)nodes[1]
currentClass.fields.each{FieldNodefield->currentClass.addMethod(createMD5Method(field))}}
11 . 10
TRANSFORMACION(IV)MethodNodecreateMD5Method(FieldNodenode){returnnewMethodNode("${node.name}asMD5",ACC_PUBLIC,ClassHelper.STRING_TYPE,[]asParameter[],[]asClassNode[],createBlock(node))}
11 . 11
TRANSFORMACION(V)BlockStatementcreateBlock(FieldNodenode){returnblock(stmt(callX(callX(callX(callX(make(java.security.MessageDigest),'getInstance',args(constX('MD5'))),constX('digest'),args(callX(varX(node.name),constX('getBytes'),args(constX('UTF-8'))))),constX('encodeHex'),args()),constX('toString'),args()
11 . 12
11 . 13
QUEESTAMALENELEJEMPLO?
11 . 14
AGGREGARUNSIMPLEMETODO… RequiereconocerbastanteelAPIdeAST
RequieresabercomoseconstruyeelAST
Requiereunmontondecodigo:(
11 . 15
SEPODRIAHABERHECHO"MEJOR"?
11 . 16
ASTBUILDER.BUILDFROMCODEAstBuilder.buildFromCodeeselabuelodelasmacros
Elcodigoquegeneraesbuggy
Vamosquenolouses!
Sitienesqueusaralguno,usa…
11 . 17
ASTBUILDER.BUILDFROMSTRINGAstBuilder.buildFromString
Notendraschequeoestaticodecodigopero…Elcodigoseracompatibleafuturo
11 . 18
ASTBUILDER.BUILDFROMSTRINGBlockStatementcreateBlock(FieldNodenode){returnAstBuilder.buildFromString("""returnjava.security.MessageDigest.getInstance('MD5').digest(${node.name}.getBytes()).encodeHex().toString()""").first()asBlockStatement}
11 . 19
QUIEROESTOMISMO… PEROBIEN!
11 . 20
MACROS
12 . 1
12 . 2
NOVETA!!NOVETA!!EN2.5.0Graciasa@bsideupy@melix
http://docs.groovy-lang.org/docs/groovy-2.5.0-SNAPSHOT/
12 . 3
QUEESUNAMACRO?
—Wikipedia
Enprogramación,instrucciónescritaenunlenguajefuentequeequivaleavariasinstruccionesdelenguajemáquina.
12 . 4
QUEESUNAMACRO?(CONT)EnGroovy,unamacroesunafuncionquerepresentaunsetdeinstrucciones.Entiempodecompilacionsesustituye
partedelcodigodetuaplicacion(marcadores)porelsetdeinstruccionesqueencapsulabanestasmacros.
12 . 5
EJEMPLOILUSTRATIVOTenemosmacroX="hombremuyalto"
Ysustituimoselmarcadorxen"Johnesunx"porelcontenidodelamacro
Ytendriamos"Johnesunhombremuyalto"
12 . 6
QUENOSDANLASMACROSNosdanseguridaddetipos
Nospermitendevolverexpressionesostatements
Nospermitenespecificarelmomentodelcompiladorenelqueseprocesaraelcodigo
Nospermitensubstituirvariables
12 . 7
COMOENCAPULAMOSELCODIGO?
12 . 8
MACROMETHOD(I)Enrealidadesunameta-transformacion
ElcodigoqueencapsulalotransformaallamadasdelAPIAST
PuedecreartantoStatementscomoExpresiones
12 . 9
MACROMETHOD(II)MethodCallExpressionexpression=macro{println"hey"}
MethodCallExpressionexpression=callThisX('println',param(constX('hey')))
ConstantExpressionexpression=macro{42}
ConstantExpressionexpression=newConstantExpression(42)
ReturnStatementstatement=macro(true){return1+1}
ReturnStatementstatement=newReturnStatement(newBinaryExpression(newConstantExpression(42...
12 . 10
MACROMETHOD(III)
truesiquieresquedevuelvaunStatement
falsesiquieresquedevuelvaunExpression
macro(boolean){/*...CODE...*/}
12 . 11
EJEMPLO
@AddaggregaelmetodogetMessage()
getMessage()devolverasiempre42
@AddclassA{
}
assertnewA().getMessage()==42
12 . 12
SINMACROSClassNodeclassNode=(ClassNode)nodes[1]
ReturnStatementcode=newReturnStatement(newConstantExpression(42))
MethodNodemethodNode=newMethodNode("getMessage",ACC_PUBLIC,ClassHelper.make(String),[]asParameter[],[]asClassNode[],code)
classNode.addMethod(methodNode)
12 . 13
CONMACROSClassNodeclassNode=(ClassNode)nodes[1]
ReturnStatementcode=macro{return"42"}
MethodNodemethodNode=newMethodNode("getMessage",ACC_PUBLIC,ClassHelper.make(String),[]asParameter[],[]asClassNode[],code)
classNode.addMethod(methodNode)
12 . 14
MACROMETHOD(CONT.)
Fasedecompilacionenelquequierasqueseproceseelcodigo
PuedestambienindicarsidevuelveunStatementounExpression
macro(CompilePhase,boolean){/*...CODE...*/}
12 . 15
MD5REVISITEDBlockStatementcreateBlock(FieldNodenode){returnblock(stmt(callX(callX(callX(callX(make(java.security.MessageDigest),'getInstance',args(constX('MD5'))),constX('digest'),args(callX(varX(node.name),constX('getBytes'),args(constX('UTF-8'))))),constX('encodeHex'),args()),constX('toString'),args()
12 . 16
CONMACROSBlockStatementcreateBlock(FieldNodenode){VariableExpressionfieldVar=GeneralUtils.varX(fieldNode.name)
returnmacro(CompilePhase.SEMANTIC_ANALYSIS,true){returnjava.security.MessageDigest.getInstance('MD5').digest($v{fieldVar}.getBytes()).encodeHex().toString()}}
12 . 17
AHORA… Escodigonormal,nounstringollamadasalAPIdeAST
Sepuedecompilarestaticamente
Puedessustituirvariables
12 . 18
YCREARELMETODOENTERO?MacroClass
Necesita@CompileDynamic
http://docs.groovy-lang.org/docs/groovy-2.5.0-SNAPSHOT/html/documentation/#_macroclass
12 . 19
AUNASI… LasASTssiguenteniendomuchaceremonia
12 . 20
ASTEROID
13 . 1
13 . 2
QUEESASTEROIDEsunabibliotecaqueBuscareducirelcodigodetusASTs
http://grooviter.github.io/asteroid/
13 . 3
ORGANIZACIONAbstraccionessobretransformacionesLocalesyGlobales
FluentAPIparacrearexpresiones,metodosy/o
13 . 4
EJEMPLOMD5
13 . 5
ANOTACIONpackagecompile.old.local.md5
importorg.codehaus.groovy.transform.GroovyASTTransformationClass
importjava.lang.annotation.ElementTypeimportjava.lang.annotation.Retentionimportjava.lang.annotation.RetentionPolicyimportjava.lang.annotation.Target
@Retention(RetentionPolicy.SOURCE)@Target([ElementType.TYPE])@GroovyASTTransformationClass(["compile.old.local.md5.MD5Transform"])@interfaceMD5{}
packagecompile.gro.local.md5
importasteroid.Local
@Local(MD5Transform)@interfaceMD5{}
13 . 6
DECLARACIONASTantes
ahora
@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classMD5TransformextendsAbstractASTTransformation{
@Phase(Phase.LOCAL.SEMANTIC_ANALYSIS)classMD5TransformextendsAbstractLocalTransformation<MD5,ClassNode>{
13 . 7
DECLARACIONAST(CONT.)Noteequivocasdefasedecompilacion
Declarasquetipodeanotacionvaaprocesar(MD5)
Declarassobrequetiposevaaaplicar(ClassNode)
13 . 8
METODODOVISITantes
ahora
@Overridevoidvisit(ASTNode[]nodes,SourceUnitsourceUnit){ClassNodecurrentClass=(ClassNode)nodes[1]
currentClass.fields.each{FieldNodefield->currentClass.addMethod(createMD5Method(field))}}
@OverridevoiddoVisit(AnnotationNodeannotation,ClassNodenode){node.fields.each{FieldNodefield->node.addMethod(createMD5Method(field))}}
13 . 9
METODODOVISIT(CONT.)Yanohacenfaltaelhorriblecastingdetipos
13 . 10
CREANDOMETODO
LosbuildersteguiansinoconoceselAPI
MethodNodecreateMD5Method(FieldNodenode){returnA.NODES.method("${node.name}ToMD5").modifiers(A.ACC.ACC_PUBLIC).returnType(String).code(createBlock(node)).build()}
13 . 11
CREARMETODOMD5BlockStatementcreateBlock(FieldNodenode){VariableExpressionfieldVar=GeneralUtils.varX(node.name)
returnmacro(CompilePhase.SEMANTIC_ANALYSIS,true){returnjava.security.MessageDigest.getInstance('MD5').digest($v{fieldVar}.getBytes()).encodeHex().toString()}}
13 . 12
CREARMETODOMD5(CONT.)Todoescodigocompilado
Nopierdesdinamismograciasalosplaceholders
Aunasi,necesitassabersinecesitasunaExpr.ounStmt.
13 . 13
QUENOHEVISTOYQUEMEREZCALAPENA?MacroClass
ASTMatcher
http://docs.groovy-lang.org/docs/groovy-2.5.0-SNAPSHOT/html/documentation/#_macroclass
http://docs.groovy-lang.org/docs/groovy-2.5.0-SNAPSHOT/html/documentation/#_astmatcher
14 . 1
DETODASMANERASLasASTsconosinmacrosnosonelmejorsitiopordondeempezar
enserio
Traits,extensionmodules,ASTseselcaminomasrecomendado
RevisarladocumentaciondeGroovy
14 . 2
:)
14 . 3
Q&A
14 . 4
RAFFLE
14 . 5