Make IrScript a statement container first, update JS support

The IrScript is now the IrStatementContainer with significant
statements order, and the code is adapted accordingly
This commit is contained in:
Ilya Chernikov
2020-07-14 12:08:48 +02:00
parent 55048f40ab
commit 01d73ba0fc
18 changed files with 330 additions and 114 deletions
@@ -5,14 +5,14 @@
package org.jetbrains.kotlin.ir.declarations
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.expressions.IrStatementContainer
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
//TODO: make IrScript as IrPackageFragment, because script is used as a file, not as a class
//NOTE: declarations and statements stored separately
abstract class IrScript :
IrDeclarationBase(), IrSymbolDeclaration<IrScriptSymbol>, IrDeclarationContainer, IrDeclarationWithName, IrDeclarationParent {
abstract val statements: MutableList<IrStatement>
IrDeclarationBase(), IrSymbolDeclaration<IrScriptSymbol>, IrDeclarationWithName,
IrDeclarationParent, IrStatementContainer {
// NOTE: is the result of the FE conversion, because there script interpreted as a class and has receiver
abstract var thisReceiver: IrValueParameter
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.SmartList
private val SCRIPT_ORIGIN = object : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE") {}
private val SCRIPT_ORIGIN = object : IrDeclarationOriginImpl("SCRIPT") {}
class IrScriptImpl(
override val symbol: IrScriptSymbol,
@@ -38,7 +38,6 @@ class IrScriptImpl(
override var annotations: List<IrConstructorCall> = SmartList()
override val declarations: MutableList<IrDeclaration> = mutableListOf()
override val statements: MutableList<IrStatement> = mutableListOf()
override lateinit var thisReceiver: IrValueParameter
@@ -59,13 +58,11 @@ class IrScriptImpl(
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
declarations.forEach { it.accept(visitor, data) }
statements.forEach { it.accept(visitor, data) }
thisReceiver.accept(visitor, data)
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
declarations.transformInPlace(transformer, data)
statements.transformInPlace(transformer, data)
thisReceiver = thisReceiver.transform(transformer, data)
}
@@ -117,10 +117,9 @@ open class DeepCopyIrTreeWithSymbols(
//TODO: something may go wrong, because expected using symbolRemapper
IrScriptSymbolImpl(declaration.descriptor as ScriptDescriptor),
declaration.name
).also {
it.thisReceiver = declaration.thisReceiver.transform()
declaration.transformDeclarationsTo(it)
it.statements.addAll(declaration.statements.map { it.transform() })
).also { scriptCopy ->
scriptCopy.thisReceiver = declaration.thisReceiver.transform()
declaration.statements.mapTo(scriptCopy.statements) { it.transform() }
}
}
@@ -51,6 +51,7 @@ private tailrec fun erase(type: IrType): IrClass? {
return when (classifier) {
is IrClassSymbol -> classifier.owner
is IrScriptSymbol -> null // TODO: check if correct
is IrTypeParameterSymbol -> erase(classifier.owner.superTypes.first())
else -> error(classifier)
}
@@ -46,19 +46,42 @@ inline fun <T> MutableList<T>.transformFlat(transformation: (T) -> List<T>?) {
while (i < size) {
val item = get(i)
val transformed = transformation(item)
i = replaceInPlace(transformation(item), i)
}
}
when (transformed?.size) {
null -> i++
0 -> removeAt(i)
1 -> set(i++, transformed.first())
else -> {
addAll(i, transformed)
i += transformed.size
removeAt(i)
}
/**
* Transforms a subset of a mutable list in place.
* Each element `it` that has a type S is replaced with a result of `transformation(it)`,
* `null` means "keep existing element" (to avoid creating excessive singleton lists).
*/
inline fun <T, reified S : T> MutableList<T>.transformSubsetFlat(transformation: (S) -> List<S>?) {
var i = 0
while (i < size) {
val item = get(i)
if (item !is S) {
i++
continue
}
i = replaceInPlace(transformation(item), i)
}
}
@PublishedApi internal fun <T> MutableList<T>.replaceInPlace(transformed: List<T>?, atIndex: Int): Int {
var i = atIndex
when (transformed?.size) {
null -> i++
0 -> removeAt(i)
1 -> set(i++, transformed.first())
else -> {
addAll(i, transformed)
i += transformed.size
removeAt(i)
}
}
return i
}
/**