@@ -43,7 +43,7 @@ class KotlinExtractorExtension(private val invocationTrapFile: String, private v
4343 moduleFragment.files.mapIndexed { index: Int , file: IrFile ->
4444 val fileTrapWriter = FileTrapWriter (lm, invocationTrapFileBW, file)
4545 fileTrapWriter.writeCompilation_compiling_files(compilation, index, fileTrapWriter.fileId)
46- doFile(invocationTrapFile, fileTrapWriter, checkTrapIdentical, logCounter, trapDir, srcDir, file)
46+ doFile(invocationTrapFile, fileTrapWriter, checkTrapIdentical, logCounter, trapDir, srcDir, file, pluginContext )
4747 }
4848 logger.printLimitedWarningCounts()
4949 // We don't want the compiler to continue and generate class
@@ -94,7 +94,14 @@ private fun equivalentTrap(f1: File, f2: File): Boolean {
9494 }
9595}
9696
97- fun doFile (invocationTrapFile : String , fileTrapWriter : FileTrapWriter , checkTrapIdentical : Boolean , logCounter : LogCounter , trapDir : File , srcDir : File , file : IrFile ) {
97+ fun doFile (invocationTrapFile : String ,
98+ fileTrapWriter : FileTrapWriter ,
99+ checkTrapIdentical : Boolean ,
100+ logCounter : LogCounter ,
101+ trapDir : File ,
102+ srcDir : File ,
103+ file : IrFile ,
104+ pluginContext : IrPluginContext ) {
98105 val filePath = file.path
99106 val logger = FileLogger (logCounter, fileTrapWriter)
100107 logger.info(" Extracting file $filePath " )
@@ -116,7 +123,7 @@ fun doFile(invocationTrapFile: String, fileTrapWriter: FileTrapWriter, checkTrap
116123 trapTmpFile.bufferedWriter().use { trapFileBW ->
117124 trapFileBW.write(" // Generated by invocation ${invocationTrapFile.replace(" \n " , " \n // " )} \n " )
118125 val tw = FileTrapWriter (TrapLabelManager (), trapFileBW, file)
119- val fileExtractor = KotlinFileExtractor (logger, tw, file)
126+ val fileExtractor = KotlinFileExtractor (logger, tw, file, pluginContext )
120127 fileExtractor.extractFileContents(tw.fileId)
121128 }
122129 if (checkTrapIdentical && trapFile.exists()) {
@@ -151,7 +158,7 @@ fun <T> fakeLabel(): Label<T> {
151158 return IntLabel (0 )
152159}
153160
154- class KotlinFileExtractor (val logger : FileLogger , val tw : FileTrapWriter , val file : IrFile ) {
161+ class KotlinFileExtractor (val logger : FileLogger , val tw : FileTrapWriter , val file : IrFile , val pluginContext : IrPluginContext ) {
155162 val fileClass by lazy {
156163 extractFileClass(file)
157164 }
@@ -213,11 +220,7 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
213220 is IrClass -> extractClass(declaration)
214221 is IrFunction -> extractFunction(declaration, if (optParentid.isPresent()) optParentid.get() else fileClass)
215222 is IrAnonymousInitializer -> {
216- // todo: how do we want to represent this?
217- // there could be multiple 'init' blocks inside a declaration.
218- // We could add a generated 'init' method, with all the statements inside the blocks.
219- // In Kotlin/JVM, the statements inside 'init' blocks get copied to the default constructor, or if there's no default then to all of them.
220- logger.warnElement(Severity .ErrorSevere , " Todo: handle IrAnonymousInitializer" , declaration)
223+ // Leaving this intentionally empty. init blocks are extracted during class extraction.
221224 }
222225 is IrProperty -> extractProperty(declaration, if (optParentid.isPresent()) optParentid.get() else fileClass)
223226 else -> logger.warnElement(Severity .ErrorSevere , " Unrecognised IrDeclaration: " + declaration.javaClass, declaration)
@@ -363,6 +366,9 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
363366 }
364367 }
365368 c.declarations.map { extractDeclaration(it, Optional .of(id)) }
369+
370+ extractObjectInitializerFunction(c, id)
371+
366372 return id
367373 }
368374
@@ -399,10 +405,14 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
399405 }
400406
401407 private fun getFunctionLabel (f : IrFunction ) : String {
402- val paramTypeIds = f.valueParameters.joinToString() { " {${useType(erase(it.type)).toString()} }" }
403- val returnTypeId = useType(erase(f.returnType))
404- val parentId = useDeclarationParent(f.parent)
405- val label = " @\" callable;{$parentId }.${f.name.asString()} ($paramTypeIds ){$returnTypeId }\" "
408+ return getFunctionLabel(f.parent, f.name.asString(), f.valueParameters, f.returnType)
409+ }
410+
411+ private fun getFunctionLabel (parent : IrDeclarationParent , name : String , parameters : List <IrValueParameter >, returnType : IrType ) : String {
412+ val paramTypeIds = parameters.joinToString() { " {${useType(erase(it.type)).toString()} }" }
413+ val returnTypeId = useType(erase(returnType))
414+ val parentId = useDeclarationParent(parent)
415+ val label = " @\" callable;{$parentId }.$name ($paramTypeIds ){$returnTypeId }\" "
406416 return label
407417 }
408418
@@ -459,6 +469,19 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
459469 tw.writeParamName(id, vp.name.asString())
460470 }
461471
472+ private fun extractObjectInitializerFunction (c : IrClass , parentid : Label <out DbReftype >) {
473+ var methodLabel = getFunctionLabel(c, " <obinit>" , listOf (), pluginContext.irBuiltIns.unitType)
474+ val methodId = tw.getLabelFor<DbMethod >(methodLabel)
475+ val signature = " TODO"
476+ val returnTypeId = useType(pluginContext.irBuiltIns.unitType)
477+ tw.writeMethods(methodId, " <obinit>" , signature, returnTypeId, parentid, methodId)
478+
479+ val locId = tw.getLocation(c)
480+ tw.writeHasLocation(methodId, locId)
481+
482+ // todo add body with non-static field initializers, and init blocks
483+ }
484+
462485 fun extractFunction (f : IrFunction , parentid : Label <out DbReftype >) {
463486 val id = useFunction(f)
464487 val locId = tw.getLocation(f)
@@ -702,11 +725,19 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
702725 val callableLabel = useFunction(irCallable)
703726 when (e) {
704727 is IrInstanceInitializerCall -> {
705- // todo: how do we want to handle this?
706- // In Kotlin/JVM, this seems like a no-op.
707- if (e.classSymbol.owner.declarations.any { it is IrAnonymousInitializer }) {
708- // we could add a call to a generated 'init' function.
728+ if (irCallable is IrConstructor && irCallable.isPrimary) {
729+ // Todo add parameter to field assignments
709730 }
731+
732+ // Add call to <obinit>:
733+ val id = tw.getFreshIdLabel<DbMethodaccess >()
734+ val typeId = useType(e.type)
735+ val locId = tw.getLocation(e)
736+ var methodLabel = getFunctionLabel(irCallable.parent, " <obinit>" , listOf (), e.type)
737+ val methodId = tw.getLabelFor<DbMethod >(methodLabel)
738+ tw.writeExprs_methodaccess(id, typeId, parent, idx)
739+ tw.writeHasLocation(id, locId)
740+ tw.writeCallableBinding(id, methodId)
710741 }
711742 is IrDelegatingConstructorCall -> {
712743 val delegatingClass = e.symbol.owner.parent as IrClass
0 commit comments