ControlFlowInstructionsGenerator: converted to Kotlin

This commit is contained in:
Mikhail Glukhikh
2016-01-26 16:45:59 +03:00
parent 80338ecb88
commit 42b6b41378
3 changed files with 261 additions and 387 deletions
@@ -32,16 +32,13 @@ interface ControlFlowBuilder {
fun exitSubroutine(subroutine: KtElement): Pseudocode fun exitSubroutine(subroutine: KtElement): Pseudocode
val currentSubroutine: KtElement val currentSubroutine: KtElement
val returnSubroutine: KtElement? val returnSubroutine: KtElement
// Lexical scopes // Lexical scopes
fun enterLexicalScope(element: KtElement) fun enterLexicalScope(element: KtElement)
fun exitLexicalScope(element: KtElement) fun exitLexicalScope(element: KtElement)
// Entry/exit points
fun getEntryPoint(labelElement: KtElement): Label
fun getExitPoint(labelElement: KtElement): Label fun getExitPoint(labelElement: KtElement): Label
fun getConditionEntryPoint(labelElement: KtElement): Label fun getConditionEntryPoint(labelElement: KtElement): Label
@@ -123,10 +123,6 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
delegateBuilder.throwException(throwExpression, thrownValue) delegateBuilder.throwException(throwExpression, thrownValue)
} }
override fun getEntryPoint(labelElement: KtElement): Label {
return delegateBuilder.getEntryPoint(labelElement)
}
override fun getExitPoint(labelElement: KtElement): Label { override fun getExitPoint(labelElement: KtElement): Label {
return delegateBuilder.getExitPoint(labelElement) return delegateBuilder.getExitPoint(labelElement)
} }
@@ -169,7 +165,7 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
override val currentSubroutine: KtElement override val currentSubroutine: KtElement
get() = delegateBuilder.currentSubroutine get() = delegateBuilder.currentSubroutine
override val returnSubroutine: KtElement? override val returnSubroutine: KtElement
get() = delegateBuilder.returnSubroutine get() = delegateBuilder.returnSubroutine
override fun returnValue(returnExpression: KtExpression, returnValue: PseudoValue, subroutine: KtElement) { override fun returnValue(returnExpression: KtExpression, returnValue: PseudoValue, subroutine: KtElement) {
@@ -14,534 +14,415 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.cfg.pseudocode; package org.jetbrains.kotlin.cfg.pseudocode
import com.intellij.util.containers.Stack; import com.intellij.util.containers.Stack
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cfg.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.*; import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction; import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope; import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*; import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.*; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.*; import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.*; import java.util.*
public class ControlFlowInstructionsGenerator extends ControlFlowBuilderAdapter { class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
private ControlFlowBuilder builder = null; private var builder: ControlFlowBuilder? = null
private final Stack<LoopInfo> loopInfo = new Stack<LoopInfo>(); override val delegateBuilder: ControlFlowBuilder
private final Stack<LexicalScope> lexicalScopes = new Stack<LexicalScope>(); get() = builder ?: throw AssertionError("Builder stack is empty in ControlFlowInstructionsGenerator!")
private final Map<KtElement, BreakableBlockInfo> elementToBlockInfo = new HashMap<KtElement, BreakableBlockInfo>();
private int labelCount = 0;
private final Stack<ControlFlowInstructionsGeneratorWorker> builders = new Stack<ControlFlowInstructionsGeneratorWorker>(); private val loopInfo = Stack<LoopInfo>()
private val lexicalScopes = Stack<LexicalScope>()
private val elementToBlockInfo = HashMap<KtElement, BreakableBlockInfo>()
private var labelCount = 0
private final Stack<BlockInfo> allBlocks = new Stack<BlockInfo>(); private val builders = Stack<ControlFlowInstructionsGeneratorWorker>()
@NotNull private val allBlocks = Stack<BlockInfo>()
@Override
protected ControlFlowBuilder getDelegateBuilder() { private fun pushBuilder(scopingElement: KtElement, subroutine: KtElement) {
return builder; val worker = ControlFlowInstructionsGeneratorWorker(scopingElement, subroutine)
builders.push(worker)
builder = worker
} }
private void pushBuilder(KtElement scopingElement, KtElement subroutine) { private fun popBuilder(): ControlFlowInstructionsGeneratorWorker {
ControlFlowInstructionsGeneratorWorker worker = new ControlFlowInstructionsGeneratorWorker(scopingElement, subroutine); val worker = builders.pop()
builders.push(worker);
builder = worker;
}
private ControlFlowInstructionsGeneratorWorker popBuilder(@NotNull KtElement element) {
ControlFlowInstructionsGeneratorWorker worker = builders.pop();
if (!builders.isEmpty()) { if (!builders.isEmpty()) {
builder = builders.peek(); builder = builders.peek()
} }
else { else {
builder = null; builder = null
} }
return worker; return worker
} }
@Override override fun enterSubroutine(subroutine: KtElement) {
public void enterSubroutine(@NotNull KtElement subroutine) { val builder = builder
if (builder != null && subroutine instanceof KtFunctionLiteral) { if (builder != null && subroutine is KtFunctionLiteral) {
pushBuilder(subroutine, builder.getReturnSubroutine()); pushBuilder(subroutine, builder.returnSubroutine)
} }
else { else {
pushBuilder(subroutine, subroutine); pushBuilder(subroutine, subroutine)
} }
assert builder != null; delegateBuilder.enterLexicalScope(subroutine)
builder.enterLexicalScope(subroutine); delegateBuilder.enterSubroutine(subroutine)
builder.enterSubroutine(subroutine);
} }
@NotNull override fun exitSubroutine(subroutine: KtElement): Pseudocode {
@Override super.exitSubroutine(subroutine)
public Pseudocode exitSubroutine(@NotNull KtElement subroutine) { delegateBuilder.exitLexicalScope(subroutine)
super.exitSubroutine(subroutine); val worker = popBuilder()
builder.exitLexicalScope(subroutine);
ControlFlowInstructionsGeneratorWorker worker = popBuilder(subroutine);
if (!builders.empty()) { if (!builders.empty()) {
ControlFlowInstructionsGeneratorWorker builder = builders.peek(); val builder = builders.peek()
builder.declareFunction(subroutine, worker.getPseudocode()); builder.declareFunction(subroutine, worker.pseudocode)
} }
return worker.getPseudocode(); return worker.pseudocode
} }
private class ControlFlowInstructionsGeneratorWorker implements ControlFlowBuilder { private inner class ControlFlowInstructionsGeneratorWorker(scopingElement: KtElement, override val returnSubroutine: KtElement) : ControlFlowBuilder {
private final PseudocodeImpl pseudocode; val pseudocode: PseudocodeImpl
private final Label error; private val error: Label
private final Label sink; private val sink: Label
private final KtElement returnSubroutine;
private final PseudoValueFactory valueFactory = new PseudoValueFactoryImpl() { private val valueFactory = object : PseudoValueFactoryImpl() {
@NotNull override fun newValue(element: KtElement?, instruction: InstructionWithValue?): PseudoValue {
@Override val value = super.newValue(element, instruction)
public PseudoValue newValue(@Nullable KtElement element, @Nullable InstructionWithValue instruction) {
PseudoValue value = super.newValue(element, instruction);
if (element != null) { if (element != null) {
bindValue(value, element); bindValue(value, element)
} }
return value; return value
} }
};
private ControlFlowInstructionsGeneratorWorker(@NotNull KtElement scopingElement, @NotNull KtElement returnSubroutine) {
this.pseudocode = new PseudocodeImpl(scopingElement);
this.error = pseudocode.createLabel("error", null);
this.sink = pseudocode.createLabel("sink", null);
this.returnSubroutine = returnSubroutine;
} }
public PseudocodeImpl getPseudocode() { init {
return pseudocode; this.pseudocode = PseudocodeImpl(scopingElement)
this.error = pseudocode.createLabel("error", null)
this.sink = pseudocode.createLabel("sink", null)
} }
private void add(@NotNull Instruction instruction) { private fun add(instruction: Instruction) {
pseudocode.addInstruction(instruction); pseudocode.addInstruction(instruction)
} }
@NotNull override fun createUnboundLabel(): Label {
@Override return pseudocode.createLabel("L" + labelCount++, null)
public final Label createUnboundLabel() {
return pseudocode.createLabel("L" + labelCount++, null);
} }
@NotNull override fun createUnboundLabel(name: String): Label {
@Override return pseudocode.createLabel("L" + labelCount++, name)
public Label createUnboundLabel(@NotNull String name) {
return pseudocode.createLabel("L" + labelCount++, name);
} }
@NotNull override fun enterLoop(expression: KtLoopExpression): LoopInfo {
@Override val info = LoopInfo(
public final LoopInfo enterLoop(@NotNull KtLoopExpression expression) {
LoopInfo info = new LoopInfo(
expression, expression,
createUnboundLabel("loop entry point"), createUnboundLabel("loop entry point"),
createUnboundLabel("loop exit point"), createUnboundLabel("loop exit point"),
createUnboundLabel("body entry point"), createUnboundLabel("body entry point"),
createUnboundLabel("body exit point"), createUnboundLabel("body exit point"),
createUnboundLabel("condition entry point")); createUnboundLabel("condition entry point"))
bindLabel(info.getEntryPoint()); bindLabel(info.entryPoint)
elementToBlockInfo.put(expression, info); elementToBlockInfo.put(expression, info)
return info; return info
} }
@Override override fun enterLoopBody(expression: KtLoopExpression) {
public void enterLoopBody(@NotNull KtLoopExpression expression) { val info = elementToBlockInfo[expression] as LoopInfo
LoopInfo info = (LoopInfo) elementToBlockInfo.get(expression); bindLabel(info.bodyEntryPoint)
bindLabel(info.getBodyEntryPoint()); loopInfo.push(info)
loopInfo.push(info); allBlocks.push(info)
allBlocks.push(info);
} }
@Override override fun exitLoopBody(expression: KtLoopExpression) {
public final void exitLoopBody(@NotNull KtLoopExpression expression) { val info = loopInfo.pop()
LoopInfo info = loopInfo.pop(); elementToBlockInfo.remove(expression)
elementToBlockInfo.remove(expression); allBlocks.pop()
allBlocks.pop(); bindLabel(info.bodyExitPoint)
bindLabel(info.getBodyExitPoint());
} }
@Override override val currentLoop: KtLoopExpression?
public KtLoopExpression getCurrentLoop() { get() = if (loopInfo.empty()) null else loopInfo.peek().element
return loopInfo.empty() ? null : loopInfo.peek().getElement();
}
@Override override fun enterSubroutine(subroutine: KtElement) {
public void enterSubroutine(@NotNull KtElement subroutine) { val blockInfo = BreakableBlockInfo(
BreakableBlockInfo blockInfo = new BreakableBlockInfo(
subroutine, subroutine,
/* entry point */ createUnboundLabel(), /* entry point */ createUnboundLabel(),
/* exit point */ createUnboundLabel()); /* exit point */ createUnboundLabel())
elementToBlockInfo.put(subroutine, blockInfo); elementToBlockInfo.put(subroutine, blockInfo)
allBlocks.push(blockInfo); allBlocks.push(blockInfo)
bindLabel(blockInfo.getEntryPoint()); bindLabel(blockInfo.entryPoint)
add(new SubroutineEnterInstruction(subroutine, getCurrentScope())); add(SubroutineEnterInstruction(subroutine, currentScope))
} }
@NotNull override val currentSubroutine: KtElement
@Override get() = pseudocode.correspondingElement
public KtElement getCurrentSubroutine() {
return pseudocode.getCorrespondingElement(); override fun getConditionEntryPoint(labelElement: KtElement): Label {
val blockInfo = elementToBlockInfo[labelElement]
assert(blockInfo is LoopInfo) { "expected LoopInfo for " + labelElement.text }
return (blockInfo as LoopInfo).conditionEntryPoint
} }
@Override override fun getExitPoint(labelElement: KtElement): Label {
public KtElement getReturnSubroutine() { val blockInfo = elementToBlockInfo[labelElement] ?: error(labelElement.text)
return returnSubroutine;// subroutineInfo.empty() ? null : subroutineInfo.peek().getElement(); return blockInfo.exitPoint
} }
@NotNull private val currentScope: LexicalScope
@Override get() = lexicalScopes.peek()
public Label getEntryPoint(@NotNull KtElement labelElement) {
return elementToBlockInfo.get(labelElement).getEntryPoint(); override fun enterLexicalScope(element: KtElement) {
val current = if (lexicalScopes.isEmpty()) null else currentScope
val scope = LexicalScope(current, element)
lexicalScopes.push(scope)
} }
@NotNull override fun exitLexicalScope(element: KtElement) {
@Override val currentScope = currentScope
public Label getConditionEntryPoint(@NotNull KtElement labelElement) { assert(currentScope.element === element) {
BreakableBlockInfo blockInfo = elementToBlockInfo.get(labelElement); "Exit from not the current lexical scope.\n" +
assert blockInfo instanceof LoopInfo : "expected LoopInfo for " + labelElement.getText() ; "Current scope is for: " + currentScope.element + ".\n" +
return ((LoopInfo)blockInfo).getConditionEntryPoint(); "Exit from the scope for: " + element.text
} }
lexicalScopes.pop()
@NotNull
@Override
public Label getExitPoint(@NotNull KtElement labelElement) {
BreakableBlockInfo blockInfo = elementToBlockInfo.get(labelElement);
assert blockInfo != null : labelElement.getText();
return blockInfo.getExitPoint();
}
@NotNull
private LexicalScope getCurrentScope() {
return lexicalScopes.peek();
}
@Override
public void enterLexicalScope(@NotNull KtElement element) {
LexicalScope current = lexicalScopes.isEmpty() ? null : getCurrentScope();
LexicalScope scope = new LexicalScope(current, element);
lexicalScopes.push(scope);
}
@Override
public void exitLexicalScope(@NotNull KtElement element) {
LexicalScope currentScope = getCurrentScope();
assert currentScope.getElement() == element : "Exit from not the current lexical scope.\n" +
"Current scope is for: " + currentScope.getElement() + ".\n" +
"Exit from the scope for: " + element.getText();
lexicalScopes.pop();
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void handleJumpInsideTryFinally(Label jumpTarget) { private fun handleJumpInsideTryFinally(jumpTarget: Label) {
List<TryFinallyBlockInfo> finallyBlocks = new ArrayList<TryFinallyBlockInfo>(); val finallyBlocks = ArrayList<TryFinallyBlockInfo>()
for (int i = allBlocks.size() - 1; i >= 0; i--) { for (i in allBlocks.indices.reversed()) {
BlockInfo blockInfo = allBlocks.get(i); val blockInfo = allBlocks[i]
if (blockInfo instanceof BreakableBlockInfo) { if (blockInfo is BreakableBlockInfo) {
BreakableBlockInfo breakableBlockInfo = (BreakableBlockInfo) blockInfo; if (blockInfo.referablePoints.contains(jumpTarget) || jumpTarget === error) {
if (breakableBlockInfo.getReferablePoints().contains(jumpTarget) || jumpTarget == error) { for (j in finallyBlocks.indices.reversed()) {
for (int j = finallyBlocks.size() - 1; j >= 0; j--) { finallyBlocks[j].generateFinallyBlock()
finallyBlocks.get(j).generateFinallyBlock();
} }
break; break
} }
} }
else if (blockInfo instanceof TryFinallyBlockInfo) { else if (blockInfo is TryFinallyBlockInfo) {
TryFinallyBlockInfo tryFinallyBlockInfo = (TryFinallyBlockInfo) blockInfo; finallyBlocks.add(blockInfo)
finallyBlocks.add(tryFinallyBlockInfo);
} }
} }
} }
@NotNull override fun exitSubroutine(subroutine: KtElement): Pseudocode {
@Override bindLabel(getExitPoint(subroutine))
public Pseudocode exitSubroutine(@NotNull KtElement subroutine) { pseudocode.addExitInstruction(SubroutineExitInstruction(subroutine, currentScope, false))
bindLabel(getExitPoint(subroutine)); bindLabel(error)
pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, getCurrentScope(), false)); pseudocode.addErrorInstruction(SubroutineExitInstruction(subroutine, currentScope, true))
bindLabel(error); bindLabel(sink)
pseudocode.addErrorInstruction(new SubroutineExitInstruction(subroutine, getCurrentScope(), true)); pseudocode.addSinkInstruction(SubroutineSinkInstruction(subroutine, currentScope, "<SINK>"))
bindLabel(sink); elementToBlockInfo.remove(subroutine)
pseudocode.addSinkInstruction(new SubroutineSinkInstruction(subroutine, getCurrentScope(), "<SINK>")); allBlocks.pop()
elementToBlockInfo.remove(subroutine); return pseudocode
allBlocks.pop();
return pseudocode;
} }
@Override override fun mark(element: KtElement) {
public void mark(@NotNull KtElement element) { add(MarkInstruction(element, currentScope))
add(new MarkInstruction(element, getCurrentScope()));
} }
@Nullable override fun getBoundValue(element: KtElement?): PseudoValue? {
@Override return pseudocode.getElementValue(element)
public PseudoValue getBoundValue(@Nullable KtElement element) {
return pseudocode.getElementValue(element);
} }
@Override override fun bindValue(value: PseudoValue, element: KtElement) {
public void bindValue(@NotNull PseudoValue value, @NotNull KtElement element) { pseudocode.bindElementToValue(element, value)
pseudocode.bindElementToValue(element, value);
} }
@NotNull override fun newValue(element: KtElement?): PseudoValue {
@Override return valueFactory.newValue(element, null)
public PseudoValue newValue(@Nullable KtElement element) {
return valueFactory.newValue(element, null);
} }
@Override override fun returnValue(returnExpression: KtExpression, returnValue: PseudoValue, subroutine: KtElement) {
public void returnValue(@NotNull KtExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull KtElement subroutine) { val exitPoint = getExitPoint(subroutine)
Label exitPoint = getExitPoint(subroutine); handleJumpInsideTryFinally(exitPoint)
handleJumpInsideTryFinally(exitPoint); add(ReturnValueInstruction(returnExpression, currentScope, exitPoint, returnValue))
add(new ReturnValueInstruction(returnExpression, getCurrentScope(), exitPoint, returnValue));
} }
@Override override fun returnNoValue(returnExpression: KtReturnExpression, subroutine: KtElement) {
public void returnNoValue(@NotNull KtReturnExpression returnExpression, @NotNull KtElement subroutine) { val exitPoint = getExitPoint(subroutine)
Label exitPoint = getExitPoint(subroutine); handleJumpInsideTryFinally(exitPoint)
handleJumpInsideTryFinally(exitPoint); add(ReturnNoValueInstruction(returnExpression, currentScope, exitPoint))
add(new ReturnNoValueInstruction(returnExpression, getCurrentScope(), exitPoint));
} }
@Override override fun write(
public void write( assignment: KtElement,
@NotNull KtElement assignment, lValue: KtElement,
@NotNull KtElement lValue, rValue: PseudoValue,
@NotNull PseudoValue rValue, target: AccessTarget,
@NotNull AccessTarget target, receiverValues: Map<PseudoValue, ReceiverValue>) {
@NotNull Map<PseudoValue, ? extends ReceiverValue> receiverValues) { add(WriteValueInstruction(assignment, currentScope, target, receiverValues, lValue, rValue))
add(new WriteValueInstruction(assignment, getCurrentScope(), target, receiverValues, lValue, rValue));
} }
@Override override fun declareParameter(parameter: KtParameter) {
public void declareParameter(@NotNull KtParameter parameter) { add(VariableDeclarationInstruction(parameter, currentScope))
add(new VariableDeclarationInstruction(parameter, getCurrentScope()));
} }
@Override override fun declareVariable(property: KtVariableDeclaration) {
public void declareVariable(@NotNull KtVariableDeclaration property) { add(VariableDeclarationInstruction(property, currentScope))
add(new VariableDeclarationInstruction(property, getCurrentScope()));
} }
@Override override fun declareFunction(subroutine: KtElement, pseudocode: Pseudocode) {
public void declareFunction(@NotNull KtElement subroutine, @NotNull Pseudocode pseudocode) { add(LocalFunctionDeclarationInstruction(subroutine, pseudocode, currentScope))
add(new LocalFunctionDeclarationInstruction(subroutine, pseudocode, getCurrentScope()));
} }
@Override override fun loadUnit(expression: KtExpression) {
public void loadUnit(@NotNull KtExpression expression) { add(LoadUnitValueInstruction(expression, currentScope))
add(new LoadUnitValueInstruction(expression, getCurrentScope()));
} }
@Override override fun jump(label: Label, element: KtElement) {
public void jump(@NotNull Label label, @NotNull KtElement element) { handleJumpInsideTryFinally(label)
handleJumpInsideTryFinally(label); add(UnconditionalJumpInstruction(element, label, currentScope))
add(new UnconditionalJumpInstruction(element, label, getCurrentScope()));
} }
@Override override fun jumpOnFalse(label: Label, element: KtElement, conditionValue: PseudoValue?) {
public void jumpOnFalse(@NotNull Label label, @NotNull KtElement element, @Nullable PseudoValue conditionValue) { handleJumpInsideTryFinally(label)
handleJumpInsideTryFinally(label); add(ConditionalJumpInstruction(element, false, currentScope, label, conditionValue))
add(new ConditionalJumpInstruction(element, false, getCurrentScope(), label, conditionValue));
} }
@Override override fun jumpOnTrue(label: Label, element: KtElement, conditionValue: PseudoValue?) {
public void jumpOnTrue(@NotNull Label label, @NotNull KtElement element, @Nullable PseudoValue conditionValue) { handleJumpInsideTryFinally(label)
handleJumpInsideTryFinally(label); add(ConditionalJumpInstruction(element, true, currentScope, label, conditionValue))
add(new ConditionalJumpInstruction(element, true, getCurrentScope(), label, conditionValue));
} }
@Override override fun bindLabel(label: Label) {
public void bindLabel(@NotNull Label label) { pseudocode.bindLabel(label)
pseudocode.bindLabel(label);
} }
@Override override fun nondeterministicJump(label: Label, element: KtElement, inputValue: PseudoValue?) {
public void nondeterministicJump(@NotNull Label label, @NotNull KtElement element, @Nullable PseudoValue inputValue) { handleJumpInsideTryFinally(label)
handleJumpInsideTryFinally(label); add(NondeterministicJumpInstruction(element, listOf(label), currentScope, inputValue))
add(new NondeterministicJumpInstruction(element, Collections.singletonList(label), getCurrentScope(), inputValue));
} }
@Override override fun nondeterministicJump(label: List<Label>, element: KtElement) {
public void nondeterministicJump(@NotNull List<? extends Label> labels, @NotNull KtElement element) {
//todo //todo
//handleJumpInsideTryFinally(label); //handleJumpInsideTryFinally(label);
add(new NondeterministicJumpInstruction(element, labels, getCurrentScope(), null)); add(NondeterministicJumpInstruction(element, label, currentScope, null))
} }
@Override override fun jumpToError(element: KtElement) {
public void jumpToError(@NotNull KtElement element) { handleJumpInsideTryFinally(error)
handleJumpInsideTryFinally(error); add(UnconditionalJumpInstruction(element, error, currentScope))
add(new UnconditionalJumpInstruction(element, error, getCurrentScope()));
} }
@Override override fun enterTryFinally(trigger: GenerationTrigger) {
public void enterTryFinally(@NotNull GenerationTrigger generationTrigger) { allBlocks.push(TryFinallyBlockInfo(trigger))
allBlocks.push(new TryFinallyBlockInfo(generationTrigger));
} }
@Override override fun throwException(throwExpression: KtThrowExpression, thrownValue: PseudoValue) {
public void throwException(@NotNull KtThrowExpression expression, @NotNull PseudoValue thrownValue) { handleJumpInsideTryFinally(error)
handleJumpInsideTryFinally(error); add(ThrowExceptionInstruction(throwExpression, currentScope, error, thrownValue))
add(new ThrowExceptionInstruction(expression, getCurrentScope(), error, thrownValue));
} }
@Override override fun exitTryFinally() {
public void exitTryFinally() { val pop = allBlocks.pop()
BlockInfo pop = allBlocks.pop(); assert(pop is TryFinallyBlockInfo)
assert pop instanceof TryFinallyBlockInfo;
} }
@Override override fun repeatPseudocode(startLabel: Label, finishLabel: Label) {
public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) { labelCount = pseudocode.repeatPart(startLabel, finishLabel, labelCount)
labelCount = pseudocode.repeatPart(startLabel, finishLabel, labelCount);
} }
@NotNull override fun loadConstant(expression: KtExpression, constant: CompileTimeConstant<*>?): InstructionWithValue {
@Override return read(expression)
public InstructionWithValue loadConstant(@NotNull KtExpression expression, @Nullable CompileTimeConstant<?> constant) {
return read(expression);
} }
@NotNull override fun createAnonymousObject(expression: KtObjectLiteralExpression): InstructionWithValue {
@Override return read(expression)
public InstructionWithValue createAnonymousObject(@NotNull KtObjectLiteralExpression expression) {
return read(expression);
} }
@NotNull override fun createLambda(expression: KtFunction): InstructionWithValue {
@Override return read(if (expression is KtFunctionLiteral) expression.getParent() as KtLambdaExpression else expression)
public InstructionWithValue createLambda(@NotNull KtFunction expression) {
return read(expression instanceof KtFunctionLiteral ? (KtLambdaExpression) expression.getParent() : expression);
} }
@NotNull override fun loadStringTemplate(expression: KtStringTemplateExpression, inputValues: List<PseudoValue>): InstructionWithValue {
@Override return if (inputValues.isEmpty()) read(expression) else magic(expression, expression, inputValues, MagicKind.STRING_TEMPLATE)
public InstructionWithValue loadStringTemplate(@NotNull KtStringTemplateExpression expression, @NotNull List<? extends PseudoValue> inputValues) {
return inputValues.isEmpty() ? read(expression) : magic(expression, expression, inputValues, MagicKind.STRING_TEMPLATE);
} }
@NotNull override fun magic(
@Override instructionElement: KtElement,
public MagicInstruction magic( valueElement: KtElement?,
@NotNull KtElement instructionElement, inputValues: List<PseudoValue>,
@Nullable KtElement valueElement, kind: MagicKind): MagicInstruction {
@NotNull List<? extends PseudoValue> inputValues, val instruction = MagicInstruction(
@NotNull MagicKind kind instructionElement, valueElement, currentScope, inputValues, kind, valueFactory)
) { add(instruction)
MagicInstruction instruction = new MagicInstruction( return instruction
instructionElement, valueElement, getCurrentScope(), inputValues, kind, valueFactory
);
add(instruction);
return instruction;
} }
@NotNull override fun merge(expression: KtExpression, inputValues: List<PseudoValue>): MergeInstruction {
@Override val instruction = MergeInstruction(expression, currentScope, inputValues, valueFactory)
public MergeInstruction merge(@NotNull KtExpression expression, @NotNull List<? extends PseudoValue> inputValues) { add(instruction)
MergeInstruction instruction = new MergeInstruction(expression, getCurrentScope(), inputValues, valueFactory); return instruction
add(instruction);
return instruction;
} }
@NotNull override fun readVariable(
@Override expression: KtExpression,
public ReadValueInstruction readVariable( resolvedCall: ResolvedCall<*>,
@NotNull KtExpression expression, receiverValues: Map<PseudoValue, ReceiverValue>): ReadValueInstruction {
@NotNull ResolvedCall<?> resolvedCall, return read(expression, resolvedCall, receiverValues)
@NotNull Map<PseudoValue, ? extends ReceiverValue> receiverValues
) {
return read(expression, resolvedCall, receiverValues);
} }
@NotNull override fun call(
@Override valueElement: KtElement,
public CallInstruction call( resolvedCall: ResolvedCall<*>,
@NotNull KtElement valueElement, receiverValues: Map<PseudoValue, ReceiverValue>,
@NotNull ResolvedCall<?> resolvedCall, arguments: Map<PseudoValue, ValueParameterDescriptor>): CallInstruction {
@NotNull Map<PseudoValue, ? extends ReceiverValue> receiverValues, val returnType = resolvedCall.resultingDescriptor.returnType
@NotNull Map<PseudoValue, ? extends ValueParameterDescriptor> arguments val instruction = CallInstruction(
) {
KotlinType returnType = resolvedCall.getResultingDescriptor().getReturnType();
CallInstruction instruction = new CallInstruction(
valueElement, valueElement,
getCurrentScope(), currentScope,
resolvedCall, resolvedCall,
receiverValues, receiverValues,
arguments, arguments,
returnType != null && KotlinBuiltIns.isNothing(returnType) ? null : valueFactory if (returnType != null && KotlinBuiltIns.isNothing(returnType)) null else valueFactory)
); add(instruction)
add(instruction); return instruction
return instruction;
} }
@NotNull override fun predefinedOperation(
@Override expression: KtExpression,
public OperationInstruction predefinedOperation( operation: ControlFlowBuilder.PredefinedOperation,
@NotNull KtExpression expression, inputValues: List<PseudoValue>): OperationInstruction {
@NotNull PredefinedOperation operation, return magic(expression, expression, inputValues, getMagicKind(operation))
@NotNull List<? extends PseudoValue> inputValues
) {
return magic(expression, expression, inputValues, getMagicKind(operation));
} }
@NotNull private fun getMagicKind(operation: ControlFlowBuilder.PredefinedOperation): MagicKind {
private MagicKind getMagicKind(@NotNull PredefinedOperation operation) { when (operation) {
switch(operation) { ControlFlowBuilder.PredefinedOperation.AND -> return MagicKind.AND
case AND: ControlFlowBuilder.PredefinedOperation.OR -> return MagicKind.OR
return MagicKind.AND; ControlFlowBuilder.PredefinedOperation.NOT_NULL_ASSERTION -> return MagicKind.NOT_NULL_ASSERTION
case OR: else -> throw IllegalArgumentException("Invalid operation: " + operation)
return MagicKind.OR;
case NOT_NULL_ASSERTION:
return MagicKind.NOT_NULL_ASSERTION;
default:
throw new IllegalArgumentException("Invalid operation: " + operation);
} }
} }
@NotNull private fun read(
private ReadValueInstruction read( expression: KtExpression,
@NotNull KtExpression expression, resolvedCall: ResolvedCall<*>? = null,
@Nullable ResolvedCall<?> resolvedCall, receiverValues: Map<PseudoValue, ReceiverValue> = emptyMap<PseudoValue, ReceiverValue>()): ReadValueInstruction {
@NotNull Map<PseudoValue, ? extends ReceiverValue> receiverValues val accessTarget = if (resolvedCall != null) AccessTarget.Call(resolvedCall) else AccessTarget.BlackBox
) { val instruction = ReadValueInstruction(
AccessTarget accessTarget = resolvedCall != null ? new AccessTarget.Call(resolvedCall) : AccessTarget.BlackBox.INSTANCE; expression, currentScope, accessTarget, receiverValues, valueFactory)
ReadValueInstruction instruction = new ReadValueInstruction( add(instruction)
expression, getCurrentScope(), accessTarget, receiverValues, valueFactory return instruction
);
add(instruction);
return instruction;
}
@NotNull
private ReadValueInstruction read(@NotNull KtExpression expression) {
return read(expression, null, Collections.<PseudoValue, ReceiverValue>emptyMap());
} }
} }
public static class TryFinallyBlockInfo extends BlockInfo { private class TryFinallyBlockInfo(private val finallyBlock: GenerationTrigger) : BlockInfo() {
private final GenerationTrigger finallyBlock;
private TryFinallyBlockInfo(GenerationTrigger finallyBlock) { fun generateFinallyBlock() {
this.finallyBlock = finallyBlock; finallyBlock.generate()
}
public void generateFinallyBlock() {
finallyBlock.generate();
} }
} }