Pseudocode: Generate fake values for Unit/Nothing-typed expressions
This commit is contained in:
@@ -98,6 +98,8 @@ public interface JetControlFlowBuilder {
|
||||
@Nullable
|
||||
PseudoValue getBoundValue(@Nullable JetElement element);
|
||||
void bindValue(@NotNull PseudoValue value, @NotNull JetElement element);
|
||||
@NotNull
|
||||
PseudoValue newValue(@Nullable JetElement element);
|
||||
|
||||
void loadUnit(@NotNull JetExpression expression);
|
||||
|
||||
|
||||
@@ -288,6 +288,12 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
|
||||
getDelegateBuilder().bindValue(value, element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PseudoValue newValue(@Nullable JetElement element) {
|
||||
return getDelegateBuilder().newValue(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterLexicalScope(@NotNull JetElement element) {
|
||||
getDelegateBuilder().enterLexicalScope(element);
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.SmartFMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import jet.runtime.typeinfo.JetValueParameter;
|
||||
import kotlin.Function0;
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
@@ -235,12 +234,20 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
|
||||
private void copyValue(@Nullable JetElement from, @NotNull JetElement to) {
|
||||
PseudoValue value = builder.getBoundValue(from);
|
||||
PseudoValue value = getBoundOrUnreachableValue(from);
|
||||
if (value != null) {
|
||||
builder.bindValue(value, to);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PseudoValue getBoundOrUnreachableValue(@Nullable JetElement element) {
|
||||
if (element == null) return null;
|
||||
|
||||
PseudoValue value = builder.getBoundValue(element);
|
||||
return value != null || element instanceof JetDeclaration ? value : builder.newValue(element);
|
||||
}
|
||||
|
||||
private List<PseudoValue> elementsToValues(List<? extends JetElement> from) {
|
||||
if (from.isEmpty()) return Collections.emptyList();
|
||||
return KotlinPackage.filterNotNull(
|
||||
@@ -249,7 +256,7 @@ public class JetControlFlowProcessor {
|
||||
new Function1<JetElement, PseudoValue>() {
|
||||
@Override
|
||||
public PseudoValue invoke(JetElement element) {
|
||||
return builder.getBoundValue(element);
|
||||
return getBoundOrUnreachableValue(element);
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -427,7 +434,7 @@ public class JetControlFlowProcessor {
|
||||
@Override
|
||||
public PseudoValue invoke() {
|
||||
generateInstructions(expression);
|
||||
return builder.getBoundValue(expression);
|
||||
return getBoundOrUnreachableValue(expression);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1234,7 +1241,7 @@ public class JetControlFlowProcessor {
|
||||
JetExpression left = expression.getLeft();
|
||||
if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
|
||||
generateInstructions(left);
|
||||
if (builder.getBoundValue(left) != null) {
|
||||
if (getBoundOrUnreachableValue(left) != null) {
|
||||
createNonSyntheticValue(expression, MagicKind.CAST, left);
|
||||
}
|
||||
}
|
||||
@@ -1428,7 +1435,8 @@ public class JetControlFlowProcessor {
|
||||
List<PseudoValue> arguments = ContainerUtil.createMaybeSingletonList(builder.getBoundValue(specifier.getDelegateExpression()));
|
||||
JetType jetType = trace.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
TypePredicate expectedTypePredicate = jetType != null ? PseudocodePackage.getSubtypesPredicate(jetType) : AllTypes.INSTANCE$;
|
||||
builder.magic(specifier, null, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments), MagicKind.VALUE_CONSUMER);
|
||||
builder.magic(specifier, null, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments),
|
||||
MagicKind.VALUE_CONSUMER);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1539,7 +1547,7 @@ public class JetControlFlowProcessor {
|
||||
generateInstructions(expression);
|
||||
}
|
||||
|
||||
PseudoValue receiverPseudoValue = builder.getBoundValue(expression);
|
||||
PseudoValue receiverPseudoValue = getBoundOrUnreachableValue(expression);
|
||||
if (receiverPseudoValue != null) {
|
||||
receiverValues = receiverValues.plus(receiverPseudoValue, receiver);
|
||||
}
|
||||
@@ -1578,7 +1586,7 @@ public class JetControlFlowProcessor {
|
||||
generateInstructions(expression);
|
||||
}
|
||||
|
||||
PseudoValue argValue = builder.getBoundValue(expression);
|
||||
PseudoValue argValue = getBoundOrUnreachableValue(expression);
|
||||
if (argValue != null) {
|
||||
parameterValues = parameterValues.plus(argValue, parameterDescriptor);
|
||||
}
|
||||
|
||||
+7
-1
@@ -106,7 +106,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
private final PseudoValueFactory valueFactory = new PseudoValueFactoryImpl() {
|
||||
@NotNull
|
||||
@Override
|
||||
public PseudoValue newValue(@Nullable JetElement element, @NotNull InstructionWithValue instruction) {
|
||||
public PseudoValue newValue(@Nullable JetElement element, @Nullable InstructionWithValue instruction) {
|
||||
PseudoValue value = super.newValue(element, instruction);
|
||||
if (element != null) {
|
||||
bindValue(value, element);
|
||||
@@ -283,6 +283,12 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
pseudocode.bindElementToValue(element, value);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PseudoValue newValue(@Nullable JetElement element) {
|
||||
return valueFactory.newValue(element, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void returnValue(@NotNull JetExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine) {
|
||||
Label exitPoint = getExitPoint(subroutine);
|
||||
|
||||
@@ -22,9 +22,9 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.InstructionWithVa
|
||||
public trait PseudoValue {
|
||||
public val debugName: String
|
||||
public val element: JetElement?
|
||||
public val createdAt: InstructionWithValue
|
||||
public val createdAt: InstructionWithValue?
|
||||
}
|
||||
|
||||
public trait PseudoValueFactory {
|
||||
public fun newValue(element: JetElement?, instruction: InstructionWithValue): PseudoValue
|
||||
public fun newValue(element: JetElement?, instruction: InstructionWithValue?): PseudoValue
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.InstructionWithVa
|
||||
class PseudoValueImpl(
|
||||
override val debugName: String,
|
||||
override val element: JetElement?,
|
||||
override val createdAt: InstructionWithValue
|
||||
override val createdAt: InstructionWithValue?
|
||||
) : PseudoValue {
|
||||
override fun toString(): String = debugName
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class PseudoValueImpl(
|
||||
open class PseudoValueFactoryImpl: PseudoValueFactory {
|
||||
private var lastIndex: Int = 0
|
||||
|
||||
override fun newValue(element: JetElement?, instruction: InstructionWithValue): PseudoValue {
|
||||
return PseudoValueImpl("<v${lastIndex++}>", element, instruction)
|
||||
override fun newValue(element: JetElement?, instruction: InstructionWithValue?): PseudoValue {
|
||||
return PseudoValueImpl((instruction?.let { "" } ?: "!") + "<v${lastIndex++}>", element, instruction)
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,9 @@ fun getReceiverTypePredicate(resolvedCall: ResolvedCall<*>, receiverValue: Recei
|
||||
}
|
||||
|
||||
fun getExpectedTypePredicate(value: PseudoValue, bindingContext: BindingContext): TypePredicate {
|
||||
val pseudocode = value.createdAt.owner
|
||||
val pseudocode = value.createdAt?.owner
|
||||
if (pseudocode == null) return AllTypes
|
||||
|
||||
val typePredicates = LinkedHashSet<TypePredicate?>()
|
||||
|
||||
fun addSubtypesOf(jetType: JetType?) = typePredicates.add(jetType?.getSubtypesPredicate())
|
||||
@@ -66,7 +68,7 @@ fun getExpectedTypePredicate(value: PseudoValue, bindingContext: BindingContext)
|
||||
val returnElement = it.element
|
||||
val functionDescriptor = when(returnElement) {
|
||||
is JetReturnExpression -> returnElement.getTargetFunctionDescriptor(bindingContext)
|
||||
else -> bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, value.createdAt.owner.getCorrespondingElement()]
|
||||
else -> bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, pseudocode.getCorrespondingElement()]
|
||||
}
|
||||
addSubtypesOf((functionDescriptor as? CallableDescriptor)?.getReturnType())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user