Special instructions added for calls and other constructs

This commit is contained in:
Andrey Breslav
2013-12-02 17:28:38 +04:00
parent 0b575da5d3
commit 1e2eb6dfa1
20 changed files with 594 additions and 115 deletions
@@ -19,7 +19,11 @@ package org.jetbrains.jet.lang.cfg;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import java.util.List;
@@ -82,7 +86,24 @@ public interface JetControlFlowBuilder {
// Reading values
void loadUnit(@NotNull JetExpression expression);
void read(@NotNull JetElement element);
void loadConstant(@NotNull JetExpression expression, @Nullable CompileTimeConstant<?> constant);
void createAnonymousObject(@NotNull JetObjectLiteralExpression expression);
void loadStringTemplate(@NotNull JetStringTemplateExpression expression);
void readThis(@NotNull JetExpression expression, @Nullable ReceiverParameterDescriptor parameterDescriptor);
void readVariable(@NotNull JetExpression expression, @Nullable VariableDescriptor variableDescriptor);
void call(@NotNull JetExpression expression, @NotNull ResolvedCall<?> resolvedCall);
enum PredefinedOperation {
AND,
OR,
NOT_NULL_ASSERTION
}
void predefinedOperation(@NotNull JetExpression expression, @Nullable PredefinedOperation operation);
void compilationError(@NotNull JetElement element, @NotNull String message);
void write(@NotNull JetElement assignment, @NotNull JetElement lValue);
// Other
@@ -19,7 +19,11 @@ package org.jetbrains.jet.lang.cfg;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import java.util.List;
@@ -27,13 +31,48 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
protected JetControlFlowBuilder builder;
@Override
public void read(@NotNull JetElement element) {
builder.read(element);
public void loadUnit(@NotNull JetExpression expression) {
builder.loadUnit(expression);
}
@Override
public void loadUnit(@NotNull JetExpression expression) {
builder.loadUnit(expression);
public void loadConstant(@NotNull JetExpression expression, @Nullable CompileTimeConstant<?> constant) {
builder.loadConstant(expression, constant);
}
@Override
public void createAnonymousObject(@NotNull JetObjectLiteralExpression expression) {
builder.createAnonymousObject(expression);
}
@Override
public void loadStringTemplate(@NotNull JetStringTemplateExpression expression) {
builder.loadStringTemplate(expression);
}
@Override
public void readThis(@NotNull JetExpression expression, @Nullable ReceiverParameterDescriptor parameterDescriptor) {
builder.readThis(expression, parameterDescriptor);
}
@Override
public void readVariable(@NotNull JetExpression expression, @Nullable VariableDescriptor variableDescriptor) {
builder.readVariable(expression, variableDescriptor);
}
@Override
public void call(@NotNull JetExpression expression, @NotNull ResolvedCall<?> resolvedCall) {
builder.call(expression, resolvedCall);
}
@Override
public void predefinedOperation(@NotNull JetExpression expression, @Nullable PredefinedOperation operation) {
builder.predefinedOperation(expression, operation);
}
@Override
public void compilationError(@NotNull JetElement element, @NotNull String message) {
builder.compilationError(element, message);
}
@Override
@@ -26,21 +26,35 @@ import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator
import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
import org.jetbrains.jet.lang.resolve.constants.BooleanValue;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import static org.jetbrains.jet.lang.cfg.JetControlFlowBuilder.PredefinedOperation.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
public class JetControlFlowProcessor {
@@ -153,8 +167,6 @@ public class JetControlFlowProcessor {
@Override
public void visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression) {
builder.read(expression);
JetExpression innerExpression = expression.getExpression();
if (innerExpression != null) {
generateInstructions(innerExpression, inCondition);
@@ -163,8 +175,6 @@ public class JetControlFlowProcessor {
@Override
public void visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression) {
builder.read(expression);
JetExpression baseExpression = expression.getBaseExpression();
if (baseExpression != null) {
generateInstructions(baseExpression, inCondition);
@@ -173,17 +183,26 @@ public class JetControlFlowProcessor {
@Override
public void visitThisExpression(@NotNull JetThisExpression expression) {
builder.read(expression);
ResolvedCall<?> resolvedCall = getResolvedCall(expression);
builder.readThis(expression, resolvedCall == null ? null : (ReceiverParameterDescriptor) resolvedCall.getResultingDescriptor());
}
@Override
public void visitConstantExpression(@NotNull JetConstantExpression expression) {
builder.read(expression);
CompileTimeConstant<?> constant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
builder.loadConstant(expression, constant);
}
@Override
public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) {
builder.read(expression);
ResolvedCall<?> resolvedCall = getResolvedCall(expression);
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
generateCall(expression, variableAsFunctionResolvedCall.getVariableCall());
}
else {
generateCall(expression);
}
}
@Override
@@ -204,7 +223,8 @@ public class JetControlFlowProcessor {
@SuppressWarnings("SuspiciousMethodCalls") @Override
public void visitBinaryExpression(@NotNull JetBinaryExpression expression) {
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
JetSimpleNameExpression operationReference = expression.getOperationReference();
IElementType operationType = operationReference.getReferencedNameElementType();
JetExpression right = expression.getRight();
if (operationType == JetTokens.ANDAND) {
generateInstructions(expression.getLeft(), true);
@@ -215,7 +235,7 @@ public class JetControlFlowProcessor {
}
builder.bindLabel(resultLabel);
if (!inCondition) {
builder.read(expression);
builder.predefinedOperation(expression, AND);
}
}
else if (operationType == JetTokens.OROR) {
@@ -227,51 +247,33 @@ public class JetControlFlowProcessor {
}
builder.bindLabel(resultLabel);
if (!inCondition) {
builder.read(expression);
builder.predefinedOperation(expression, OR);
}
}
else if (operationType == JetTokens.EQ) {
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
if (right != null) {
generateInstructions(right, false);
}
if (left instanceof JetSimpleNameExpression) {
builder.write(expression, left);
}
else if (left instanceof JetArrayAccessExpression) {
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
visitAssignToArrayAccess(expression, arrayAccessExpression);
}
else if (left instanceof JetQualifiedExpression) {
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) left;
generateInstructions(qualifiedExpression.getReceiverExpression(), false);
generateInstructions(expression.getOperationReference(), false);
builder.write(expression, left);
}
else {
builder.unsupported(expression); // TODO
}
visitAssignment(expression.getLeft(), expression);
}
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
if (left != null) {
generateInstructions(left, false);
if (generateCall(operationReference)) {
ResolvedCall<?> resolvedCall = getResolvedCall(operationReference);
assert resolvedCall != null : "Generation succeeded, but no call is found: " + expression.getText();
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken());
if (!descriptor.getName().equals(assignMethodName)) {
// plus() called, assignment needed
visitAssignment(expression.getLeft(), expression);
}
}
if (right != null) {
generateInstructions(right, false);
}
if (left instanceof JetSimpleNameExpression || left instanceof JetArrayAccessExpression) {
generateInstructions(expression.getOperationReference(), false);
builder.write(expression, left);
}
else if (left != null) {
builder.unsupported(expression); // TODO
else {
generateBothArguments(expression);
}
}
else if (operationType == JetTokens.ELVIS) {
builder.read(expression);
generateInstructions(expression.getLeft(), false);
generateInstructions(expression.getOperationReference(), false);
generateInstructions(operationReference, false);
Label afterElvis = builder.createUnboundLabel();
builder.jumpOnTrue(afterElvis);
if (right != null) {
@@ -280,22 +282,60 @@ public class JetControlFlowProcessor {
builder.bindLabel(afterElvis);
}
else {
generateInstructions(expression.getLeft(), false);
if (right != null) {
generateInstructions(right, false);
if (!generateCall(operationReference)) {
generateBothArguments(expression);
}
generateInstructions(expression.getOperationReference(), false);
builder.read(expression);
}
}
private void visitAssignToArrayAccess(JetBinaryExpression expression, JetArrayAccessExpression arrayAccessExpression) {
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
generateInstructions(index, false);
private void generateBothArguments(JetBinaryExpression expression) {
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
if (left != null) {
generateInstructions(left, false);
}
JetExpression right = expression.getRight();
if (right != null) {
generateInstructions(right, false);
}
}
private void visitAssignment(JetExpression lhs, JetExpression parentExpression) {
JetExpression left = JetPsiUtil.deparenthesize(lhs);
if (left == null) {
builder.compilationError(lhs, "No lValue in assignment");
return;
}
if (left instanceof JetSimpleNameExpression) {
// Do nothing, only record write below
}
else if (left instanceof JetArrayAccessExpression) {
generateArrayAccess((JetArrayAccessExpression) left);
}
else if (left instanceof JetQualifiedExpression) {
// read the receiver
generateInstructions(((JetQualifiedExpression) left).getReceiverExpression(), false);
}
else if (left instanceof JetProperty) {
// do nothing, just write below
}
else {
builder.unsupported(parentExpression); // TODO
}
VariableDescriptor descriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), left, false);
if (descriptor != null) {
builder.write(parentExpression, left);
}
}
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression) {
if (!generateCall(arrayAccessExpression)) {
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
generateInstructions(index, false);
}
generateInstructions(arrayAccessExpression.getArrayExpression(), false);
}
generateInstructions(arrayAccessExpression.getArrayExpression(), false);
generateInstructions(expression.getOperationReference(), false);
builder.write(expression, arrayAccessExpression); // TODO : ???
}
@Override
@@ -308,16 +348,20 @@ public class JetControlFlowProcessor {
String referencedName = operationSign.getReferencedName();
visitLabeledExpression(referencedName.substring(1), baseExpression);
}
else {
else if (JetTokens.EXCLEXCL == operationType) {
generateInstructions(baseExpression, false);
generateInstructions(operationSign, false);
builder.predefinedOperation(expression, NOT_NULL_ASSERTION);
}
else {
if (!generateCall(expression.getOperationReference())) {
generateInstructions(baseExpression, false);
}
boolean incrementOrDecrement = isIncrementOrDecrement(operationType);
if (incrementOrDecrement) {
builder.write(expression, baseExpression);
// We skip dup's and other subtleties here
visitAssignment(baseExpression, expression);
}
builder.read(expression);
}
}
@@ -353,7 +397,7 @@ public class JetControlFlowProcessor {
}
builder.bindLabel(resultLabel);
}
private class FinallyBlockGenerator {
private final JetFinallySection finallyBlock;
private Label startFinally = null;
@@ -382,7 +426,6 @@ public class JetControlFlowProcessor {
@Override
public void visitTryExpression(@NotNull JetTryExpression expression) {
builder.read(expression);
JetFinallySection finallyBlock = expression.getFinallyBlock();
final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock);
if (finallyBlock != null) {
@@ -414,7 +457,6 @@ public class JetControlFlowProcessor {
}
generateInstructions(expression.getTryBlock(), inCondition);
Collection<Label> allowDeadLabels = Lists.newArrayList();
if (hasCatches) {
Label afterCatches = builder.createUnboundLabel("afterCatches");
builder.jump(afterCatches);
@@ -467,7 +509,6 @@ public class JetControlFlowProcessor {
@Override
public void visitWhileExpression(@NotNull JetWhileExpression expression) {
builder.read(expression);
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
builder.bindLabel(loopInfo.getConditionEntryPoint());
@@ -498,7 +539,6 @@ public class JetControlFlowProcessor {
@Override
public void visitDoWhileExpression(@NotNull JetDoWhileExpression expression) {
builder.read(expression);
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
builder.bindLabel(loopInfo.getBodyEntryPoint());
@@ -518,7 +558,6 @@ public class JetControlFlowProcessor {
@Override
public void visitForExpression(@NotNull JetForExpression expression) {
builder.read(expression);
JetExpression loopRange = expression.getLoopRange();
if (loopRange != null) {
generateInstructions(loopRange, false);
@@ -657,42 +696,32 @@ public class JetControlFlowProcessor {
public void visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression) {
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
processLocalDeclaration(functionLiteral);
builder.read(expression);
}
@Override
public void visitQualifiedExpression(@NotNull JetQualifiedExpression expression) {
generateInstructions(expression.getReceiverExpression(), false);
JetExpression selectorExpression = expression.getSelectorExpression();
if (selectorExpression != null) {
generateInstructions(selectorExpression, false);
}
builder.read(expression);
}
private void visitCall(JetCallElement call) {
for (ValueArgument argument : call.getValueArguments()) {
JetExpression argumentExpression = argument.getArgumentExpression();
if (argumentExpression != null) {
generateInstructions(argumentExpression, false);
}
}
for (JetExpression functionLiteral : call.getFunctionLiteralArguments()) {
generateInstructions(functionLiteral, false);
}
}
@Override
public void visitCallExpression(@NotNull JetCallExpression expression) {
for (JetTypeProjection typeArgument : expression.getTypeArguments()) {
generateInstructions(typeArgument, false);
if (!generateCall(expression.getCalleeExpression())) {
for (ValueArgument argument : expression.getValueArguments()) {
JetExpression argumentExpression = argument.getArgumentExpression();
if (argumentExpression != null) {
generateInstructions(argumentExpression, false);
}
}
for (JetExpression functionLiteral : expression.getFunctionLiteralArguments()) {
generateInstructions(functionLiteral, false);
}
generateInstructions(expression.getCalleeExpression(), false);
}
visitCall(expression);
generateInstructions(expression.getCalleeExpression(), false);
builder.read(expression);
}
@Override
@@ -701,7 +730,7 @@ public class JetControlFlowProcessor {
JetExpression initializer = property.getInitializer();
if (initializer != null) {
generateInstructions(initializer, false);
builder.write(property, property);
visitAssignment(property, property);
}
JetExpression delegate = property.getDelegateExpression();
if (delegate != null) {
@@ -721,6 +750,10 @@ public class JetControlFlowProcessor {
List<JetMultiDeclarationEntry> entries = declaration.getEntries();
for (JetMultiDeclarationEntry entry : entries) {
builder.declareVariable(entry);
ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
if (resolvedCall != null) {
builder.call(entry, resolvedCall);
}
builder.write(entry, entry);
}
}
@@ -735,7 +768,6 @@ public class JetControlFlowProcessor {
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
generateInstructions(expression.getLeft(), false);
builder.read(expression);
}
else {
visitJetElement(expression);
@@ -753,20 +785,14 @@ public class JetControlFlowProcessor {
@Override
public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
for (JetExpression index : expression.getIndexExpressions()) {
generateInstructions(index, false);
if (!generateCall(expression)) {
generateArrayAccess(expression);
}
generateInstructions(expression.getArrayExpression(), false);
// TODO : read 'get' or 'set' function
builder.read(expression);
}
@Override
public void visitIsExpression(@NotNull JetIsExpression expression) {
generateInstructions(expression.getLeftHandSide(), inCondition);
// no CF for types
// TODO : builder.read(expression.getPattern());
builder.read(expression);
}
@Override
@@ -783,8 +809,6 @@ public class JetControlFlowProcessor {
for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) {
JetWhenEntry whenEntry = iterator.next();
builder.read(whenEntry);
boolean isElse = whenEntry.isElse();
if (isElse) {
hasElse = true;
@@ -837,7 +861,7 @@ public class JetControlFlowProcessor {
for (JetDeclaration function : functions) {
generateInstructions(function, inCondition);
}
builder.read(expression);
builder.createAnonymousObject(expression);
}
@Override
@@ -853,7 +877,7 @@ public class JetControlFlowProcessor {
generateInstructions(entryWithExpression.getExpression(), false);
}
}
builder.read(expression);
builder.loadStringTemplate(expression);
}
@Override
@@ -913,5 +937,79 @@ public class JetControlFlowProcessor {
public void visitJetElement(@NotNull JetElement element) {
builder.unsupported(element);
}
@Nullable
private ResolvedCall<?> getResolvedCall(@NotNull JetElement expression) {
return trace.get(BindingContext.RESOLVED_CALL, expression);
}
private boolean generateCall(JetExpression calleeExpression) {
ResolvedCall<?> resolvedCall = getResolvedCall(calleeExpression);
if (resolvedCall == null) {
builder.compilationError(calleeExpression, "No resolved call");
return false;
}
generateCall(calleeExpression, resolvedCall);
return true;
}
private void generateCall(JetExpression calleeExpression, ResolvedCall<?> resolvedCall) {
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
generateCall(calleeExpression, variableAsFunctionResolvedCall.getFunctionCall());
return;
}
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
if (resultingDescriptor instanceof ExpressionAsFunctionDescriptor) {
generateInstructions(((ExpressionAsFunctionDescriptor) resultingDescriptor).getExpression(), false);
}
generateReceiver(resolvedCall.getThisObject());
generateReceiver(resolvedCall.getReceiverArgument());
for (ValueParameterDescriptor parameterDescriptor : resultingDescriptor.getValueParameters()) {
ResolvedValueArgument argument = resolvedCall.getValueArguments().get(parameterDescriptor);
if (argument == null) continue;
generateValueArgument(argument);
}
if (resultingDescriptor instanceof VariableDescriptor) {
builder.readVariable(calleeExpression, (VariableDescriptor) resultingDescriptor);
}
else {
builder.call(calleeExpression, resolvedCall);
}
}
private void generateReceiver(ReceiverValue receiver) {
if (!receiver.exists()) return;
if (receiver instanceof ThisReceiver) {
// TODO: Receiver is passed implicitly: no expression to tie the read to
}
else if (receiver instanceof ExpressionReceiver) {
generateInstructions(((ExpressionReceiver) receiver).getExpression(), false);
}
else if (receiver instanceof TransientReceiver) {
// Do nothing
}
else if (receiver instanceof AutoCastReceiver) {
// No cast instruction in our CFG
generateReceiver(((AutoCastReceiver) receiver).getOriginal());
}
else {
throw new IllegalArgumentException("Unknown receiver kind: " + receiver);
}
}
private void generateValueArgument(ResolvedValueArgument argument) {
for (ValueArgument valueArgument : argument.getArguments()) {
JetExpression expression = valueArgument.getArgumentExpression();
if (expression != null) {
generateInstructions(expression, false);
}
}
}
}
}
@@ -80,11 +80,19 @@ public class InstructionVisitor {
visitInstructionWithNext(instruction);
}
public void visitWriteValue(WriteValueInstruction writeValueInstruction) {
visitInstructionWithNext(writeValueInstruction);
public void visitWriteValue(WriteValueInstruction instruction) {
visitInstructionWithNext(instruction);
}
public void visitLoadUnitValue(LoadUnitValueInstruction instruction) {
visitInstructionWithNext(instruction);
}
public void visitCallInstruction(CallInstruction instruction) {
visitInstructionWithNext(instruction);
}
public void visitCompilationErrorInstruction(CompilationErrorInstruction instruction) {
visitInstructionWithNext(instruction);
}
}
@@ -20,7 +20,11 @@ import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.*;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import java.util.ArrayList;
import java.util.HashMap;
@@ -251,11 +255,6 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
add(new LocalFunctionDeclarationInstruction(subroutine, pseudocode));
}
@Override
public void read(@NotNull JetElement element) {
add(new ReadValueInstruction(element));
}
@Override
public void loadUnit(@NotNull JetExpression expression) {
add(new LoadUnitValueInstruction(expression));
@@ -313,7 +312,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
handleJumpInsideTryFinally(error);
add(new ThrowExceptionInstruction(expression, error));
}
public void exitTryFinally() {
BlockInfo pop = allBlocks.pop();
assert pop instanceof TryFinallyBlockInfo;
@@ -328,6 +327,50 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) {
pseudocode.repeatPart(startLabel, finishLabel);
}
@Override
public void loadConstant(@NotNull JetExpression expression, @Nullable CompileTimeConstant<?> constant) {
read(expression);
}
@Override
public void createAnonymousObject(@NotNull JetObjectLiteralExpression expression) {
read(expression);
}
@Override
public void loadStringTemplate(@NotNull JetStringTemplateExpression expression) {
read(expression);
}
@Override
public void readThis(@NotNull JetExpression expression, @Nullable ReceiverParameterDescriptor parameterDescriptor) {
read(expression);
}
@Override
public void readVariable(@NotNull JetExpression expression, @Nullable VariableDescriptor variableDescriptor) {
read(expression);
}
@Override
public void call(@NotNull JetExpression expression, @NotNull ResolvedCall<?> resolvedCall) {
add(new CallInstruction(expression, resolvedCall));
}
@Override
public void predefinedOperation(@NotNull JetExpression expression, @Nullable PredefinedOperation operation) {
read(expression);
}
@Override
public void compilationError(@NotNull JetElement element, @NotNull String message) {
add(new CompilationErrorInstruction(element, message));
}
private void read(@NotNull JetElement element) {
add(new ReadValueInstruction(element));
}
}
public static class TryFinallyBlockInfo extends BlockInfo {
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.cfg.pseudocode
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
class CallInstruction(
element: JetElement,
val resolvedCall: ResolvedCall<*>
) : InstructionWithNext(element) {
override fun accept(visitor: InstructionVisitor) {
visitor.visitCallInstruction(this)
}
override fun createCopy() = CallInstruction(element, resolvedCall)
override fun toString() = "call(${element.getText()}, ${resolvedCall.getResultingDescriptor()!!.getName()})"
}
class CompilationErrorInstruction(
element: JetElement,
val message: String
) : InstructionWithNext(element) {
override fun accept(visitor: InstructionVisitor) {
visitor.visitCompilationErrorInstruction(this)
}
override fun createCopy() = CompilationErrorInstruction(element, message)
override fun toString() = "error(${element.getText()}, $message)"
}