Pseudocode: Generate fake values for Unit/Nothing-typed expressions

This commit is contained in:
Alexey Sedunov
2014-07-23 12:56:21 +04:00
parent 2d3ac9109b
commit 77bbf8f73b
72 changed files with 851 additions and 592 deletions
@@ -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);
}
@@ -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())
}