Share
Embed
Transcript
26 slides
-
• Kotlin compiler • for JVM and JavaScript • kotlin-native
generates LLVM bitcode • has frontend and backend • uses IntelliJ open API based AST • AST == abstract syntax tree • ex) PSIElement -
• Abstract syntax tree 1 + 1 == 2 •
KtBinaryExpression(1 + 1 == 2) • KtBinaryexpression(1 + 1) • KtConstantExpression(1) • KtOperationReference(+) • KtConstantExpression(1) • KtOperationReference(==) • KtConstantExpression(2) -
val root = Disposable { } val configuration = CompilerConfiguration()
configuration.addKotlinSourceRoot("./") val environment = KotlinCoreEnvironment.createForProduction(root, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) environment.getSourceFiles() ※ requires org.jetbrains.kotlin:kotlin-compiler-embeddable • Tip to get AST -
• Kotlin compiler plugin • perfectly undocumented part • currently
just for JVM? • kapt3 plugin • all-open plugin • no-arg plugin • android-extensions plugin -
AST JVM • no-arg plugin 0: aload_0 1: invokespecial //
Method java/ lang/Object."<init>":()V 4: return NoArgClassBuilderInterceptorExtension -
• Extension points • generates JVM bytecode by AST •
ExpressionCodegenExtension • ClassBuilderInterceptorExtension • Change modifier of variable • DeclarationAttributeAltererExtension -
• Extension points • PackageFragmentProviderExtension • for xml parser(android extensions)
• AnalysisHandlerExtension • used in kapt3 -
• How to create • Need to prepare: • gradle-plugin
• maven-plugin • idea-plugin • don’t talk about this -
• How to create • components lifecycle(Gradle) • 1. KotlinGradleSubplugin
• 2. CommandLineProcessor • 3. ComponentRegistrar • 4. Register extensions -
• Under the food • capture assert method calling •
in ExpressionCodegenExtension • parse argument AST • and generates JVM bytecode manually -
Code: 0: ldc #9 // String assert(1 + 2 ==
2) 2: iconst_3 // 1+2 3: invokestatic #15 // Method java/lang/Integer.valueOf:(I)Ljava/ lang/Integer; 6: bipush 9 // offset of + 8: invokestatic #21 // Method kt/powerassert/ RecorderRuntimeKt.record:(Ljava/lang/Object;I)Ljava/lang/Object; 11: checkcast #23 // class java/lang/Number 14: invokevirtual #27 // Method java/lang/Number.intValue:()I 17: iconst_2 // 2 18: if_icmpne 25 // == 21: iconst_1 22: goto 26 25: iconst_0 26: invokestatic #32 // Method java/lang/Boolean.valueOf: (Z)Ljava/lang/Boolean; 29: bipush 13 // offset of == 31: invokestatic #21 // Method kt/powerassert/ RecorderRuntimeKt.record:(Ljava/lang/Object;I)Ljava/lang/Object; 34: checkcast #29 // class java/lang/Boolean 37: invokevirtual #36 // Method java/lang/Boolean.booleanValue:()Z 40: iconst_0 // anchor point 41: invokestatic #40 // Method kt/powerassert/ RecorderRuntimeKt.powerAssert:(Ljava/lang/String;ZI)V 44: return -
• pain points • requires deep understanding of • Kotlin
compiler API/AST • JVM stack machine • No documents, just read code -
• References • JetBrains/kotlin • compiler plugin codes • Oracle
JVM specification doc • https://github.com/cmf/psiviewer