Macro macro, burrito burrit

Preview:

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

Recommended