001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.cfg;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.psi.PsiElement;
021 import com.intellij.psi.tree.IElementType;
022 import com.intellij.psi.util.PsiTreeUtil;
023 import com.intellij.util.SmartFMap;
024 import com.intellij.util.containers.ContainerUtil;
025 import kotlin.ArraysKt;
026 import kotlin.CollectionsKt;
027 import kotlin.jvm.functions.Function0;
028 import kotlin.jvm.functions.Function1;
029 import org.jetbrains.annotations.NotNull;
030 import org.jetbrains.annotations.Nullable;
031 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
032 import org.jetbrains.kotlin.cfg.pseudocode.ControlFlowInstructionsGenerator;
033 import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue;
034 import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode;
035 import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeImpl;
036 import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessTarget;
037 import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.InstructionWithValue;
038 import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind;
039 import org.jetbrains.kotlin.descriptors.*;
040 import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
041 import org.jetbrains.kotlin.lexer.KtToken;
042 import org.jetbrains.kotlin.lexer.KtTokens;
043 import org.jetbrains.kotlin.name.Name;
044 import org.jetbrains.kotlin.psi.*;
045 import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
046 import org.jetbrains.kotlin.resolve.BindingContext;
047 import org.jetbrains.kotlin.resolve.BindingContextUtils;
048 import org.jetbrains.kotlin.resolve.BindingTrace;
049 import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils;
050 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
051 import org.jetbrains.kotlin.resolve.calls.model.*;
052 import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
053 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
054 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
055 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
056 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
057 import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
058 import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
059 import org.jetbrains.kotlin.types.KotlinType;
060 import org.jetbrains.kotlin.types.expressions.OperatorConventions;
061
062 import java.util.*;
063
064 import static org.jetbrains.kotlin.cfg.ControlFlowBuilder.PredefinedOperation.*;
065 import static org.jetbrains.kotlin.diagnostics.Errors.*;
066 import static org.jetbrains.kotlin.lexer.KtTokens.*;
067
068 public class ControlFlowProcessor {
069
070 private final ControlFlowBuilder builder;
071 private final BindingTrace trace;
072
073 public ControlFlowProcessor(BindingTrace trace) {
074 this.builder = new ControlFlowInstructionsGenerator();
075 this.trace = trace;
076 }
077
078 @NotNull
079 public Pseudocode generatePseudocode(@NotNull KtElement subroutine) {
080 Pseudocode pseudocode = generate(subroutine);
081 ((PseudocodeImpl) pseudocode).postProcess();
082 return pseudocode;
083 }
084
085 @NotNull
086 private Pseudocode generate(@NotNull KtElement subroutine) {
087 builder.enterSubroutine(subroutine);
088 CFPVisitor cfpVisitor = new CFPVisitor(builder);
089 if (subroutine instanceof KtDeclarationWithBody && !(subroutine instanceof KtSecondaryConstructor)) {
090 KtDeclarationWithBody declarationWithBody = (KtDeclarationWithBody) subroutine;
091 List<KtParameter> valueParameters = declarationWithBody.getValueParameters();
092 for (KtParameter valueParameter : valueParameters) {
093 cfpVisitor.generateInstructions(valueParameter);
094 }
095 KtExpression bodyExpression = declarationWithBody.getBodyExpression();
096 if (bodyExpression != null) {
097 cfpVisitor.generateInstructions(bodyExpression);
098 if (!declarationWithBody.hasBlockBody()) {
099 generateImplicitReturnValue(bodyExpression, subroutine);
100 }
101 }
102 } else {
103 cfpVisitor.generateInstructions(subroutine);
104 }
105 return builder.exitSubroutine(subroutine);
106 }
107
108 private void generateImplicitReturnValue(@NotNull KtExpression bodyExpression, @NotNull KtElement subroutine) {
109 CallableDescriptor subroutineDescriptor = (CallableDescriptor) trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, subroutine);
110 if (subroutineDescriptor == null) return;
111
112 KotlinType returnType = subroutineDescriptor.getReturnType();
113 if (returnType != null && KotlinBuiltIns.isUnit(returnType) && subroutineDescriptor instanceof AnonymousFunctionDescriptor) return;
114
115 PseudoValue returnValue = builder.getBoundValue(bodyExpression);
116 if (returnValue == null) return;
117
118 builder.returnValue(bodyExpression, returnValue, subroutine);
119 }
120
121 private void processLocalDeclaration(@NotNull KtDeclaration subroutine) {
122 Label afterDeclaration = builder.createUnboundLabel("after local declaration");
123
124 builder.nondeterministicJump(afterDeclaration, subroutine, null);
125 generate(subroutine);
126 builder.bindLabel(afterDeclaration);
127 }
128
129 private class CFPVisitor extends KtVisitorVoid {
130 private final ControlFlowBuilder builder;
131
132 private final KtVisitorVoid conditionVisitor = new KtVisitorVoid() {
133
134 private KtExpression getSubjectExpression(KtWhenCondition condition) {
135 KtWhenExpression whenExpression = PsiTreeUtil.getParentOfType(condition, KtWhenExpression.class);
136 return whenExpression != null ? whenExpression.getSubjectExpression() : null;
137 }
138
139 @Override
140 public void visitWhenConditionInRange(@NotNull KtWhenConditionInRange condition) {
141 if (!generateCall(condition.getOperationReference())) {
142 KtExpression rangeExpression = condition.getRangeExpression();
143 generateInstructions(rangeExpression);
144 createNonSyntheticValue(condition, MagicKind.UNRESOLVED_CALL, rangeExpression);
145 }
146 }
147
148 @Override
149 public void visitWhenConditionIsPattern(@NotNull KtWhenConditionIsPattern condition) {
150 mark(condition);
151 createNonSyntheticValue(condition, MagicKind.IS, getSubjectExpression(condition));
152 }
153
154 @Override
155 public void visitWhenConditionWithExpression(@NotNull KtWhenConditionWithExpression condition) {
156 mark(condition);
157
158 KtExpression expression = condition.getExpression();
159 generateInstructions(expression);
160
161 KtExpression subjectExpression = getSubjectExpression(condition);
162 if (subjectExpression != null) {
163 // todo: this can be replaced by equals() invocation (when corresponding resolved call is recorded)
164 createNonSyntheticValue(condition, MagicKind.EQUALS_IN_WHEN_CONDITION, subjectExpression, expression);
165 }
166 else {
167 copyValue(expression, condition);
168 }
169 }
170
171 @Override
172 public void visitKtElement(@NotNull KtElement element) {
173 throw new UnsupportedOperationException("[ControlFlowProcessor] " + element.toString());
174 }
175 };
176
177 private CFPVisitor(@NotNull ControlFlowBuilder builder) {
178 this.builder = builder;
179 }
180
181 private void mark(KtElement element) {
182 builder.mark(element);
183 }
184
185 public void generateInstructions(@Nullable KtElement element) {
186 if (element == null) return;
187 element.accept(this);
188 checkNothingType(element);
189 }
190
191 private void checkNothingType(KtElement element) {
192 if (!(element instanceof KtExpression)) return;
193
194 KtExpression expression = KtPsiUtil.deparenthesize((KtExpression) element);
195 if (expression == null) return;
196
197 if (expression instanceof KtStatementExpression || expression instanceof KtTryExpression
198 || expression instanceof KtIfExpression || expression instanceof KtWhenExpression) {
199 return;
200 }
201
202 KotlinType type = trace.getBindingContext().getType(expression);
203 if (type != null && KotlinBuiltIns.isNothing(type)) {
204 builder.jumpToError(expression);
205 }
206 }
207
208 @NotNull
209 private PseudoValue createSyntheticValue(@NotNull KtElement instructionElement, @NotNull MagicKind kind, KtElement... from) {
210 List<PseudoValue> values = elementsToValues(from.length > 0 ? Arrays.asList(from) : Collections.<KtElement>emptyList());
211 return builder.magic(instructionElement, null, values, kind).getOutputValue();
212 }
213
214 @NotNull
215 private PseudoValue createNonSyntheticValue(
216 @NotNull KtElement to, @NotNull List<? extends KtElement> from, @NotNull MagicKind kind
217 ) {
218 List<PseudoValue> values = elementsToValues(from);
219 return builder.magic(to, to, values, kind).getOutputValue();
220 }
221
222 @NotNull
223 private PseudoValue createNonSyntheticValue(@NotNull KtElement to, @NotNull MagicKind kind, KtElement... from) {
224 return createNonSyntheticValue(to, Arrays.asList(from), kind);
225 }
226
227 private void mergeValues(@NotNull List<KtExpression> from, @NotNull KtExpression to) {
228 builder.merge(to, elementsToValues(from));
229 }
230
231 private void copyValue(@Nullable KtElement from, @NotNull KtElement to) {
232 PseudoValue value = getBoundOrUnreachableValue(from);
233 if (value != null) {
234 builder.bindValue(value, to);
235 }
236 }
237
238 @Nullable
239 private PseudoValue getBoundOrUnreachableValue(@Nullable KtElement element) {
240 if (element == null) return null;
241
242 PseudoValue value = builder.getBoundValue(element);
243 return value != null || element instanceof KtDeclaration ? value : builder.newValue(element);
244 }
245
246 private List<PseudoValue> elementsToValues(List<? extends KtElement> from) {
247 if (from.isEmpty()) return Collections.emptyList();
248 return CollectionsKt.filterNotNull(
249 CollectionsKt.map(
250 from,
251 new Function1<KtElement, PseudoValue>() {
252 @Override
253 public PseudoValue invoke(KtElement element) {
254 return getBoundOrUnreachableValue(element);
255 }
256 }
257 )
258 );
259 }
260
261 private void generateInitializer(@NotNull KtDeclaration declaration, @NotNull PseudoValue initValue) {
262 builder.write(
263 declaration,
264 declaration,
265 initValue,
266 getDeclarationAccessTarget(declaration),
267 Collections.<PseudoValue, ReceiverValue>emptyMap()
268 );
269 }
270
271 @NotNull
272 private AccessTarget getResolvedCallAccessTarget(KtElement element) {
273 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(element, trace.getBindingContext());
274 return resolvedCall != null ? new AccessTarget.Call(resolvedCall) : AccessTarget.BlackBox.INSTANCE$;
275 }
276
277 @NotNull
278 private AccessTarget getDeclarationAccessTarget(KtElement element) {
279 DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
280 return descriptor instanceof VariableDescriptor
281 ? new AccessTarget.Declaration((VariableDescriptor) descriptor)
282 : AccessTarget.BlackBox.INSTANCE$;
283 }
284
285 @Override
286 public void visitParenthesizedExpression(@NotNull KtParenthesizedExpression expression) {
287 mark(expression);
288 KtExpression innerExpression = expression.getExpression();
289 if (innerExpression != null) {
290 generateInstructions(innerExpression);
291 copyValue(innerExpression, expression);
292 }
293 }
294
295 @Override
296 public void visitAnnotatedExpression(@NotNull KtAnnotatedExpression expression) {
297 KtExpression baseExpression = expression.getBaseExpression();
298 if (baseExpression != null) {
299 generateInstructions(baseExpression);
300 copyValue(baseExpression, expression);
301 }
302 }
303
304 @Override
305 public void visitThisExpression(@NotNull KtThisExpression expression) {
306 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, trace.getBindingContext());
307 if (resolvedCall == null) {
308 createNonSyntheticValue(expression, MagicKind.UNRESOLVED_CALL);
309 return;
310 }
311
312 CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
313 if (resultingDescriptor instanceof ReceiverParameterDescriptor) {
314 builder.readVariable(expression, resolvedCall, getReceiverValues(resolvedCall));
315 }
316
317 copyValue(expression, expression.getInstanceReference());
318 }
319
320 @Override
321 public void visitConstantExpression(@NotNull KtConstantExpression expression) {
322 CompileTimeConstant<?> constant = ConstantExpressionEvaluator.getConstant(expression, trace.getBindingContext());
323 builder.loadConstant(expression, constant);
324 }
325
326 @Override
327 public void visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression) {
328 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, trace.getBindingContext());
329 if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
330 VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
331 generateCall(variableAsFunctionResolvedCall.getVariableCall());
332 }
333 else if (!generateCall(expression) && !(expression.getParent() instanceof KtCallExpression)) {
334 createNonSyntheticValue(expression, MagicKind.UNRESOLVED_CALL, generateAndGetReceiverIfAny(expression));
335 }
336 }
337
338 @Override
339 public void visitLabeledExpression(@NotNull KtLabeledExpression expression) {
340 mark(expression);
341 KtExpression baseExpression = expression.getBaseExpression();
342 if (baseExpression != null) {
343 generateInstructions(baseExpression);
344 copyValue(baseExpression, expression);
345 }
346 }
347
348 @SuppressWarnings("SuspiciousMethodCalls")
349 @Override
350 public void visitBinaryExpression(@NotNull KtBinaryExpression expression) {
351 KtSimpleNameExpression operationReference = expression.getOperationReference();
352 IElementType operationType = operationReference.getReferencedNameElementType();
353
354 KtExpression left = expression.getLeft();
355 KtExpression right = expression.getRight();
356 if (operationType == ANDAND || operationType == OROR) {
357 generateBooleanOperation(expression);
358 }
359 else if (operationType == EQ) {
360 visitAssignment(left, getDeferredValue(right), expression);
361 }
362 else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
363 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, trace.getBindingContext());
364 if (resolvedCall != null) {
365 PseudoValue rhsValue = generateCall(resolvedCall).getOutputValue();
366 Name assignMethodName = OperatorConventions.getNameForOperationSymbol((KtToken) expression.getOperationToken());
367 if (!resolvedCall.getResultingDescriptor().getName().equals(assignMethodName)) {
368 /* At this point assignment of the form a += b actually means a = a + b
369 * So we first generate call of "+" operation and then use its output pseudo-value
370 * as a right-hand side when generating assignment call
371 */
372 visitAssignment(left, getValueAsFunction(rhsValue), expression);
373 }
374 }
375 else {
376 generateBothArgumentsAndMark(expression);
377 }
378 }
379 else if (operationType == ELVIS) {
380 generateInstructions(left);
381 mark(expression);
382 Label afterElvis = builder.createUnboundLabel("after elvis operator");
383 builder.jumpOnTrue(afterElvis, expression, builder.getBoundValue(left));
384 if (right != null) {
385 generateInstructions(right);
386 }
387 builder.bindLabel(afterElvis);
388 mergeValues(Arrays.asList(left, right), expression);
389 }
390 else {
391 if (!generateCall(expression)) {
392 generateBothArgumentsAndMark(expression);
393 }
394 }
395 }
396
397 private void generateBooleanOperation(KtBinaryExpression expression) {
398 IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
399 KtExpression left = expression.getLeft();
400 KtExpression right = expression.getRight();
401
402 Label resultLabel = builder.createUnboundLabel("result of boolean operation");
403 generateInstructions(left);
404 if (operationType == ANDAND) {
405 builder.jumpOnFalse(resultLabel, expression, builder.getBoundValue(left));
406 }
407 else {
408 builder.jumpOnTrue(resultLabel, expression, builder.getBoundValue(left));
409 }
410 if (right != null) {
411 generateInstructions(right);
412 }
413 builder.bindLabel(resultLabel);
414 ControlFlowBuilder.PredefinedOperation operation = operationType == ANDAND ? AND : OR;
415 builder.predefinedOperation(expression, operation, elementsToValues(Arrays.asList(left, right)));
416 }
417
418 private Function0<PseudoValue> getValueAsFunction(final PseudoValue value) {
419 return new Function0<PseudoValue>() {
420 @Override
421 public PseudoValue invoke() {
422 return value;
423 }
424 };
425 }
426
427 private Function0<PseudoValue> getDeferredValue(final KtExpression expression) {
428 return new Function0<PseudoValue>() {
429 @Override
430 public PseudoValue invoke() {
431 generateInstructions(expression);
432 return getBoundOrUnreachableValue(expression);
433 }
434 };
435 }
436
437 private void generateBothArgumentsAndMark(KtBinaryExpression expression) {
438 KtExpression left = KtPsiUtil.deparenthesize(expression.getLeft());
439 if (left != null) {
440 generateInstructions(left);
441 }
442 KtExpression right = expression.getRight();
443 if (right != null) {
444 generateInstructions(right);
445 }
446 mark(expression);
447 createNonSyntheticValue(expression, MagicKind.UNRESOLVED_CALL, left, right);
448 }
449
450 private void visitAssignment(
451 KtExpression lhs,
452 @NotNull Function0<PseudoValue> rhsDeferredValue,
453 KtExpression parentExpression
454 ) {
455 KtExpression left = KtPsiUtil.deparenthesize(lhs);
456 if (left == null) {
457 List<PseudoValue> arguments = Collections.singletonList(rhsDeferredValue.invoke());
458 builder.magic(parentExpression, parentExpression, arguments, MagicKind.UNSUPPORTED_ELEMENT);
459 return;
460 }
461
462 if (left instanceof KtArrayAccessExpression) {
463 generateArrayAssignment((KtArrayAccessExpression) left, rhsDeferredValue, parentExpression);
464 return;
465 }
466
467 Map<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap();
468 AccessTarget accessTarget = AccessTarget.BlackBox.INSTANCE$;
469 if (left instanceof KtSimpleNameExpression || left instanceof KtQualifiedExpression) {
470 accessTarget = getResolvedCallAccessTarget(KtPsiUtilKt.getQualifiedElementSelector(left));
471 if (accessTarget instanceof AccessTarget.Call) {
472 receiverValues = getReceiverValues(((AccessTarget.Call) accessTarget).getResolvedCall());
473 }
474 }
475 else if (left instanceof KtProperty) {
476 accessTarget = getDeclarationAccessTarget(left);
477 }
478
479 if (accessTarget == AccessTarget.BlackBox.INSTANCE$ && !(left instanceof KtProperty)) {
480 generateInstructions(left);
481 createSyntheticValue(left, MagicKind.VALUE_CONSUMER, left);
482 }
483
484 PseudoValue rightValue = rhsDeferredValue.invoke();
485 PseudoValue rValue =
486 rightValue != null ? rightValue : createSyntheticValue(parentExpression, MagicKind.UNRECOGNIZED_WRITE_RHS);
487 builder.write(parentExpression, left, rValue, accessTarget, receiverValues);
488 }
489
490 private void generateArrayAssignment(
491 KtArrayAccessExpression lhs,
492 @NotNull Function0<PseudoValue> rhsDeferredValue,
493 @NotNull KtExpression parentExpression
494 ) {
495 ResolvedCall<FunctionDescriptor> setResolvedCall = trace.get(BindingContext.INDEXED_LVALUE_SET, lhs);
496
497 if (setResolvedCall == null) {
498 generateArrayAccess(lhs, null);
499
500 List<PseudoValue> arguments = CollectionsKt.filterNotNull(
501 Arrays.asList(getBoundOrUnreachableValue(lhs), rhsDeferredValue.invoke())
502 );
503 builder.magic(parentExpression, parentExpression, arguments, MagicKind.UNRESOLVED_CALL);
504
505 return;
506 }
507
508 // In case of simple ('=') array assignment mark instruction is not generated yet, so we put it before generating "set" call
509 if (((KtOperationExpression) parentExpression).getOperationReference().getReferencedNameElementType() == EQ) {
510 mark(lhs);
511 }
512
513 generateInstructions(lhs.getArrayExpression());
514
515 Map<PseudoValue, ReceiverValue> receiverValues = getReceiverValues(setResolvedCall);
516 SmartFMap<PseudoValue, ValueParameterDescriptor> argumentValues = getArraySetterArguments(rhsDeferredValue, setResolvedCall);
517
518 builder.call(parentExpression, setResolvedCall, receiverValues, argumentValues);
519 }
520
521 /* We assume that assignment right-hand side corresponds to the last argument of the call
522 * So receiver instructions/pseudo-values are generated for all arguments except the last one which is replaced
523 * by pre-generated pseudo-value
524 * For example, assignment a[1, 2] += 3 means a.set(1, 2, a.get(1) + 3), so in order to generate "set" call
525 * we first generate instructions for 1 and 2 whereas 3 is replaced by pseudo-value corresponding to "a.get(1) + 3"
526 */
527 private SmartFMap<PseudoValue, ValueParameterDescriptor> getArraySetterArguments(
528 Function0<PseudoValue> rhsDeferredValue,
529 final ResolvedCall<FunctionDescriptor> setResolvedCall
530 ) {
531 List<ValueArgument> valueArguments = CollectionsKt.flatMapTo(
532 setResolvedCall.getResultingDescriptor().getValueParameters(),
533 new ArrayList<ValueArgument>(),
534 new Function1<ValueParameterDescriptor, Iterable<? extends ValueArgument>>() {
535 @Override
536 public Iterable<? extends ValueArgument> invoke(ValueParameterDescriptor descriptor) {
537 ResolvedValueArgument resolvedValueArgument = setResolvedCall.getValueArguments().get(descriptor);
538 return resolvedValueArgument != null
539 ? resolvedValueArgument.getArguments()
540 : Collections.<ValueArgument>emptyList();
541 }
542 }
543 );
544
545 ValueArgument rhsArgument = CollectionsKt.lastOrNull(valueArguments);
546 SmartFMap<PseudoValue, ValueParameterDescriptor> argumentValues = SmartFMap.emptyMap();
547 for (ValueArgument valueArgument : valueArguments) {
548 ArgumentMapping argumentMapping = setResolvedCall.getArgumentMapping(valueArgument);
549 if (argumentMapping.isError() || (!(argumentMapping instanceof ArgumentMatch))) continue;
550
551 ValueParameterDescriptor parameterDescriptor = ((ArgumentMatch) argumentMapping).getValueParameter();
552 if (valueArgument != rhsArgument) {
553 argumentValues = generateValueArgument(valueArgument, parameterDescriptor, argumentValues);
554 }
555 else {
556 PseudoValue rhsValue = rhsDeferredValue.invoke();
557 if (rhsValue != null) {
558 argumentValues = argumentValues.plus(rhsValue, parameterDescriptor);
559 }
560 }
561 }
562 return argumentValues;
563 }
564
565 private void generateArrayAccess(KtArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> resolvedCall) {
566 if (builder.getBoundValue(arrayAccessExpression) != null) return;
567 mark(arrayAccessExpression);
568 if (!checkAndGenerateCall(resolvedCall)) {
569 generateArrayAccessWithoutCall(arrayAccessExpression);
570 }
571 }
572
573 private void generateArrayAccessWithoutCall(KtArrayAccessExpression arrayAccessExpression) {
574 createNonSyntheticValue(arrayAccessExpression, generateArrayAccessArguments(arrayAccessExpression), MagicKind.UNRESOLVED_CALL);
575 }
576
577 private List<KtExpression> generateArrayAccessArguments(KtArrayAccessExpression arrayAccessExpression) {
578 List<KtExpression> inputExpressions = new ArrayList<KtExpression>();
579
580 KtExpression arrayExpression = arrayAccessExpression.getArrayExpression();
581 inputExpressions.add(arrayExpression);
582 generateInstructions(arrayExpression);
583
584 for (KtExpression index : arrayAccessExpression.getIndexExpressions()) {
585 generateInstructions(index);
586 inputExpressions.add(index);
587 }
588
589 return inputExpressions;
590 }
591
592 @Override
593 public void visitUnaryExpression(@NotNull KtUnaryExpression expression) {
594 KtSimpleNameExpression operationSign = expression.getOperationReference();
595 IElementType operationType = operationSign.getReferencedNameElementType();
596 KtExpression baseExpression = expression.getBaseExpression();
597 if (baseExpression == null) return;
598 if (KtTokens.EXCLEXCL == operationType) {
599 generateInstructions(baseExpression);
600 builder.predefinedOperation(expression, NOT_NULL_ASSERTION, elementsToValues(Collections.singletonList(baseExpression)));
601 return;
602 }
603
604 boolean incrementOrDecrement = isIncrementOrDecrement(operationType);
605 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, trace.getBindingContext());
606
607 PseudoValue rhsValue;
608 if (resolvedCall != null) {
609 rhsValue = generateCall(resolvedCall).getOutputValue();
610 }
611 else {
612 generateInstructions(baseExpression);
613 rhsValue = createNonSyntheticValue(expression, MagicKind.UNRESOLVED_CALL, baseExpression);
614 }
615
616 if (incrementOrDecrement) {
617 visitAssignment(baseExpression, getValueAsFunction(rhsValue), expression);
618 if (expression instanceof KtPostfixExpression) {
619 copyValue(baseExpression, expression);
620 }
621 }
622 }
623
624 private boolean isIncrementOrDecrement(IElementType operationType) {
625 return operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS;
626 }
627
628 @Override
629 public void visitIfExpression(@NotNull KtIfExpression expression) {
630 mark(expression);
631 List<KtExpression> branches = new ArrayList<KtExpression>(2);
632 KtExpression condition = expression.getCondition();
633 if (condition != null) {
634 generateInstructions(condition);
635 }
636 Label elseLabel = builder.createUnboundLabel("else branch");
637 builder.jumpOnFalse(elseLabel, expression, builder.getBoundValue(condition));
638 KtExpression thenBranch = expression.getThen();
639 if (thenBranch != null) {
640 branches.add(thenBranch);
641 generateInstructions(thenBranch);
642 }
643 else {
644 builder.loadUnit(expression);
645 }
646 Label resultLabel = builder.createUnboundLabel("'if' expression result");
647 builder.jump(resultLabel, expression);
648 builder.bindLabel(elseLabel);
649 KtExpression elseBranch = expression.getElse();
650 if (elseBranch != null) {
651 branches.add(elseBranch);
652 generateInstructions(elseBranch);
653 }
654 else {
655 builder.loadUnit(expression);
656 }
657 builder.bindLabel(resultLabel);
658 mergeValues(branches, expression);
659 }
660
661 private class FinallyBlockGenerator {
662 private final KtFinallySection finallyBlock;
663 private Label startFinally = null;
664 private Label finishFinally = null;
665
666 private FinallyBlockGenerator(KtFinallySection block) {
667 finallyBlock = block;
668 }
669
670 public void generate() {
671 KtBlockExpression finalExpression = finallyBlock.getFinalExpression();
672 if (finalExpression == null) return;
673 if (startFinally != null) {
674 assert finishFinally != null;
675 builder.repeatPseudocode(startFinally, finishFinally);
676 return;
677 }
678 startFinally = builder.createUnboundLabel("start finally");
679 builder.bindLabel(startFinally);
680 generateInstructions(finalExpression);
681 finishFinally = builder.createUnboundLabel("finish finally");
682 builder.bindLabel(finishFinally);
683 }
684 }
685
686 @Override
687 public void visitTryExpression(@NotNull KtTryExpression expression) {
688 mark(expression);
689
690 KtFinallySection finallyBlock = expression.getFinallyBlock();
691 final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock);
692 boolean hasFinally = finallyBlock != null;
693 if (hasFinally) {
694 builder.enterTryFinally(new GenerationTrigger() {
695 private boolean working = false;
696
697 @Override
698 public void generate() {
699 // This checks are needed for the case of having e.g. return inside finally: 'try {return} finally{return}'
700 if (working) return;
701 working = true;
702 finallyBlockGenerator.generate();
703 working = false;
704 }
705 });
706 }
707
708 Label onExceptionToFinallyBlock = generateTryAndCatches(expression);
709
710 if (hasFinally) {
711 assert onExceptionToFinallyBlock != null : "No finally lable generated: " + expression.getText();
712
713 builder.exitTryFinally();
714
715 Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock");
716 builder.jump(skipFinallyToErrorBlock, expression);
717 builder.bindLabel(onExceptionToFinallyBlock);
718 finallyBlockGenerator.generate();
719 builder.jumpToError(expression);
720 builder.bindLabel(skipFinallyToErrorBlock);
721
722 finallyBlockGenerator.generate();
723 }
724
725 List<KtExpression> branches = new ArrayList<KtExpression>();
726 branches.add(expression.getTryBlock());
727 for (KtCatchClause catchClause : expression.getCatchClauses()) {
728 branches.add(catchClause.getCatchBody());
729 }
730 mergeValues(branches, expression);
731 }
732
733 // Returns label for 'finally' block
734 @Nullable
735 private Label generateTryAndCatches(@NotNull KtTryExpression expression) {
736 List<KtCatchClause> catchClauses = expression.getCatchClauses();
737 boolean hasCatches = !catchClauses.isEmpty();
738
739 Label onException = null;
740 if (hasCatches) {
741 onException = builder.createUnboundLabel("onException");
742 builder.nondeterministicJump(onException, expression, null);
743 }
744
745 Label onExceptionToFinallyBlock = null;
746 if (expression.getFinallyBlock() != null) {
747 onExceptionToFinallyBlock = builder.createUnboundLabel("onExceptionToFinallyBlock");
748 builder.nondeterministicJump(onExceptionToFinallyBlock, expression, null);
749 }
750
751 KtBlockExpression tryBlock = expression.getTryBlock();
752 generateInstructions(tryBlock);
753
754 if (hasCatches) {
755 Label afterCatches = builder.createUnboundLabel("afterCatches");
756 builder.jump(afterCatches, expression);
757
758 builder.bindLabel(onException);
759 LinkedList<Label> catchLabels = Lists.newLinkedList();
760 int catchClausesSize = catchClauses.size();
761 for (int i = 0; i < catchClausesSize - 1; i++) {
762 catchLabels.add(builder.createUnboundLabel("catch " + i));
763 }
764 if (!catchLabels.isEmpty()) {
765 builder.nondeterministicJump(catchLabels, expression);
766 }
767 boolean isFirst = true;
768 for (KtCatchClause catchClause : catchClauses) {
769 builder.enterLexicalScope(catchClause);
770 if (!isFirst) {
771 builder.bindLabel(catchLabels.remove());
772 }
773 else {
774 isFirst = false;
775 }
776 KtParameter catchParameter = catchClause.getCatchParameter();
777 if (catchParameter != null) {
778 builder.declareParameter(catchParameter);
779 generateInitializer(catchParameter, createSyntheticValue(catchParameter, MagicKind.FAKE_INITIALIZER));
780 }
781 KtExpression catchBody = catchClause.getCatchBody();
782 if (catchBody != null) {
783 generateInstructions(catchBody);
784 }
785 builder.jump(afterCatches, expression);
786 builder.exitLexicalScope(catchClause);
787 }
788
789 builder.bindLabel(afterCatches);
790 }
791
792 return onExceptionToFinallyBlock;
793 }
794
795 @Override
796 public void visitWhileExpression(@NotNull KtWhileExpression expression) {
797 LoopInfo loopInfo = builder.enterLoop(expression);
798
799 builder.bindLabel(loopInfo.getConditionEntryPoint());
800 KtExpression condition = expression.getCondition();
801 if (condition != null) {
802 generateInstructions(condition);
803 }
804 mark(expression);
805 boolean conditionIsTrueConstant = CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace, true);
806 if (!conditionIsTrueConstant) {
807 builder.jumpOnFalse(loopInfo.getExitPoint(), expression, builder.getBoundValue(condition));
808 }
809 else {
810 assert condition != null : "Invalid while condition: " + expression.getText();
811 createSyntheticValue(condition, MagicKind.VALUE_CONSUMER, condition);
812 }
813
814 builder.enterLoopBody(expression);
815 KtExpression body = expression.getBody();
816 if (body != null) {
817 generateInstructions(body);
818 }
819 builder.jump(loopInfo.getEntryPoint(), expression);
820 builder.exitLoopBody(expression);
821 builder.bindLabel(loopInfo.getExitPoint());
822 builder.loadUnit(expression);
823 }
824
825 @Override
826 public void visitDoWhileExpression(@NotNull KtDoWhileExpression expression) {
827 builder.enterLexicalScope(expression);
828 mark(expression);
829 LoopInfo loopInfo = builder.enterLoop(expression);
830
831 builder.enterLoopBody(expression);
832 KtExpression body = expression.getBody();
833 if (body != null) {
834 generateInstructions(body);
835 }
836 builder.exitLoopBody(expression);
837 builder.bindLabel(loopInfo.getConditionEntryPoint());
838 KtExpression condition = expression.getCondition();
839 if (condition != null) {
840 generateInstructions(condition);
841 }
842 builder.jumpOnTrue(loopInfo.getEntryPoint(), expression, builder.getBoundValue(condition));
843 builder.bindLabel(loopInfo.getExitPoint());
844 builder.loadUnit(expression);
845 builder.exitLexicalScope(expression);
846 }
847
848 @Override
849 public void visitForExpression(@NotNull KtForExpression expression) {
850 builder.enterLexicalScope(expression);
851
852 KtExpression loopRange = expression.getLoopRange();
853 if (loopRange != null) {
854 generateInstructions(loopRange);
855 }
856 declareLoopParameter(expression);
857
858 // TODO : primitive cases
859 LoopInfo loopInfo = builder.enterLoop(expression);
860
861 builder.bindLabel(loopInfo.getConditionEntryPoint());
862 builder.nondeterministicJump(loopInfo.getExitPoint(), expression, null);
863
864
865 writeLoopParameterAssignment(expression);
866
867 mark(expression);
868 builder.enterLoopBody(expression);
869 KtExpression body = expression.getBody();
870 if (body != null) {
871 generateInstructions(body);
872 }
873 builder.jump(loopInfo.getEntryPoint(), expression);
874
875 builder.exitLoopBody(expression);
876 builder.bindLabel(loopInfo.getExitPoint());
877 builder.loadUnit(expression);
878 builder.exitLexicalScope(expression);
879 }
880
881 private void declareLoopParameter(KtForExpression expression) {
882 KtParameter loopParameter = expression.getLoopParameter();
883 KtDestructuringDeclaration multiDeclaration = expression.getDestructuringParameter();
884 if (loopParameter != null) {
885 builder.declareParameter(loopParameter);
886 }
887 else if (multiDeclaration != null) {
888 visitDestructuringDeclaration(multiDeclaration, false);
889 }
890 }
891
892 private void writeLoopParameterAssignment(KtForExpression expression) {
893 KtParameter loopParameter = expression.getLoopParameter();
894 KtDestructuringDeclaration multiDeclaration = expression.getDestructuringParameter();
895 KtExpression loopRange = expression.getLoopRange();
896
897 PseudoValue value = builder.magic(
898 loopRange != null ? loopRange : expression,
899 null,
900 ContainerUtil.createMaybeSingletonList(builder.getBoundValue(loopRange)),
901 MagicKind.LOOP_RANGE_ITERATION
902 ).getOutputValue();
903
904 if (loopParameter != null) {
905 generateInitializer(loopParameter, value);
906 }
907 else if (multiDeclaration != null) {
908 for (KtDestructuringDeclarationEntry entry : multiDeclaration.getEntries()) {
909 generateInitializer(entry, value);
910 }
911 }
912 }
913
914 @Override
915 public void visitBreakExpression(@NotNull KtBreakExpression expression) {
916 KtElement loop = getCorrespondingLoop(expression);
917 if (loop != null) {
918 checkJumpDoesNotCrossFunctionBoundary(expression, loop);
919 builder.jump(builder.getExitPoint(loop), expression);
920 }
921 }
922
923 @Override
924 public void visitContinueExpression(@NotNull KtContinueExpression expression) {
925 KtElement loop = getCorrespondingLoop(expression);
926 if (loop != null) {
927 checkJumpDoesNotCrossFunctionBoundary(expression, loop);
928 builder.jump(builder.getConditionEntryPoint(loop), expression);
929 }
930 }
931
932 @Nullable
933 private KtElement getCorrespondingLoop(KtExpressionWithLabel expression) {
934 String labelName = expression.getLabelName();
935 KtLoopExpression loop;
936 if (labelName != null) {
937 KtSimpleNameExpression targetLabel = expression.getTargetLabel();
938 assert targetLabel != null;
939 PsiElement labeledElement = trace.get(BindingContext.LABEL_TARGET, targetLabel);
940 if (labeledElement instanceof KtLoopExpression) {
941 loop = (KtLoopExpression) labeledElement;
942 }
943 else {
944 trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
945 loop = null;
946 }
947 }
948 else {
949 loop = builder.getCurrentLoop();
950 if (loop == null) {
951 trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression));
952 } else {
953 KtWhenExpression whenExpression = PsiTreeUtil.getParentOfType(expression, KtWhenExpression.class, true,
954 KtLoopExpression.class);
955 if (whenExpression != null) {
956 trace.report(BREAK_OR_CONTINUE_IN_WHEN.on(expression));
957 }
958 }
959 }
960 if (loop != null && loop.getBody() != null
961 // the faster version of 'isAncestor' check:
962 && !loop.getBody().getTextRange().contains(expression.getTextRange())) {
963 trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression));
964 return null;
965 }
966 return loop;
967 }
968
969 private void checkJumpDoesNotCrossFunctionBoundary(@NotNull KtExpressionWithLabel jumpExpression, @NotNull KtElement jumpTarget) {
970 BindingContext bindingContext = trace.getBindingContext();
971
972 FunctionDescriptor labelExprEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpExpression);
973 FunctionDescriptor labelTargetEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpTarget);
974 if (labelExprEnclosingFunc != labelTargetEnclosingFunc) {
975 trace.report(BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY.on(jumpExpression));
976 }
977 }
978
979 @Override
980 public void visitReturnExpression(@NotNull KtReturnExpression expression) {
981 KtExpression returnedExpression = expression.getReturnedExpression();
982 if (returnedExpression != null) {
983 generateInstructions(returnedExpression);
984 }
985 KtSimpleNameExpression labelElement = expression.getTargetLabel();
986 KtElement subroutine;
987 String labelName = expression.getLabelName();
988 if (labelElement != null && labelName != null) {
989 PsiElement labeledElement = trace.get(BindingContext.LABEL_TARGET, labelElement);
990 if (labeledElement != null) {
991 assert labeledElement instanceof KtElement;
992 subroutine = (KtElement) labeledElement;
993 }
994 else {
995 subroutine = null;
996 }
997 }
998 else {
999 subroutine = builder.getReturnSubroutine();
1000 // TODO : a context check
1001 }
1002
1003 if (subroutine instanceof KtFunction || subroutine instanceof KtPropertyAccessor) {
1004 PseudoValue returnValue = returnedExpression != null ? builder.getBoundValue(returnedExpression) : null;
1005 if (returnValue == null) {
1006 builder.returnNoValue(expression, subroutine);
1007 }
1008 else {
1009 builder.returnValue(expression, returnValue, subroutine);
1010 }
1011 }
1012 else {
1013 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, returnedExpression);
1014 }
1015 }
1016
1017 @Override
1018 public void visitParameter(@NotNull KtParameter parameter) {
1019 builder.declareParameter(parameter);
1020 KtExpression defaultValue = parameter.getDefaultValue();
1021 if (defaultValue != null) {
1022 Label skipDefaultValue = builder.createUnboundLabel("after default value for parameter " + parameter.getName());
1023 builder.nondeterministicJump(skipDefaultValue, defaultValue, null);
1024 generateInstructions(defaultValue);
1025 builder.bindLabel(skipDefaultValue);
1026 }
1027 generateInitializer(parameter, computePseudoValueForParameter(parameter));
1028 }
1029
1030 @NotNull
1031 private PseudoValue computePseudoValueForParameter(@NotNull KtParameter parameter) {
1032 PseudoValue syntheticValue = createSyntheticValue(parameter, MagicKind.FAKE_INITIALIZER);
1033 PseudoValue defaultValue = builder.getBoundValue(parameter.getDefaultValue());
1034 if (defaultValue == null) {
1035 return syntheticValue;
1036 }
1037 return builder.merge(parameter, Lists.newArrayList(defaultValue, syntheticValue)).getOutputValue();
1038 }
1039
1040 @Override
1041 public void visitBlockExpression(@NotNull KtBlockExpression expression) {
1042 boolean declareLexicalScope = !isBlockInDoWhile(expression);
1043 if (declareLexicalScope) {
1044 builder.enterLexicalScope(expression);
1045 }
1046 mark(expression);
1047 List<KtExpression> statements = expression.getStatements();
1048 for (KtExpression statement : statements) {
1049 generateInstructions(statement);
1050 }
1051 if (statements.isEmpty()) {
1052 builder.loadUnit(expression);
1053 }
1054 else {
1055 copyValue(CollectionsKt.lastOrNull(statements), expression);
1056 }
1057 if (declareLexicalScope) {
1058 builder.exitLexicalScope(expression);
1059 }
1060 }
1061
1062 private boolean isBlockInDoWhile(@NotNull KtBlockExpression expression) {
1063 PsiElement parent = expression.getParent();
1064 if (parent == null) return false;
1065 return parent.getParent() instanceof KtDoWhileExpression;
1066 }
1067
1068 private void visitFunction(@NotNull KtFunction function) {
1069 processLocalDeclaration(function);
1070 boolean isAnonymousFunction = function instanceof KtFunctionLiteral || function.getName() == null;
1071 if (isAnonymousFunction || (function.isLocal() && !(function.getParent() instanceof KtBlockExpression))) {
1072 builder.createLambda(function);
1073 }
1074 }
1075
1076 @Override
1077 public void visitNamedFunction(@NotNull KtNamedFunction function) {
1078 visitFunction(function);
1079 }
1080
1081 @Override
1082 public void visitLambdaExpression(@NotNull KtLambdaExpression lambdaExpression) {
1083 mark(lambdaExpression);
1084 KtFunctionLiteral functionLiteral = lambdaExpression.getFunctionLiteral();
1085 visitFunction(functionLiteral);
1086 copyValue(functionLiteral, lambdaExpression);
1087 }
1088
1089 @Override
1090 public void visitQualifiedExpression(@NotNull KtQualifiedExpression expression) {
1091 mark(expression);
1092 KtExpression selectorExpression = expression.getSelectorExpression();
1093 KtExpression receiverExpression = expression.getReceiverExpression();
1094
1095 // todo: replace with selectorExpresion != null after parser is fixed
1096 if (selectorExpression instanceof KtCallExpression || selectorExpression instanceof KtSimpleNameExpression) {
1097 generateInstructions(selectorExpression);
1098 copyValue(selectorExpression, expression);
1099 }
1100 else {
1101 generateInstructions(receiverExpression);
1102 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, receiverExpression);
1103 }
1104 }
1105
1106 @Override
1107 public void visitCallExpression(@NotNull KtCallExpression expression) {
1108 if (!generateCall(expression)) {
1109 List<KtExpression> inputExpressions = new ArrayList<KtExpression>();
1110 for (ValueArgument argument : expression.getValueArguments()) {
1111 KtExpression argumentExpression = argument.getArgumentExpression();
1112 if (argumentExpression != null) {
1113 generateInstructions(argumentExpression);
1114 inputExpressions.add(argumentExpression);
1115 }
1116 }
1117 KtExpression calleeExpression = expression.getCalleeExpression();
1118 generateInstructions(calleeExpression);
1119 inputExpressions.add(calleeExpression);
1120 inputExpressions.add(generateAndGetReceiverIfAny(expression));
1121
1122 mark(expression);
1123 createNonSyntheticValue(expression, inputExpressions, MagicKind.UNRESOLVED_CALL);
1124 }
1125 }
1126
1127 @Nullable
1128 private KtExpression generateAndGetReceiverIfAny(KtExpression expression) {
1129 PsiElement parent = expression.getParent();
1130 if (!(parent instanceof KtQualifiedExpression)) return null;
1131
1132 KtQualifiedExpression qualifiedExpression = (KtQualifiedExpression) parent;
1133 if (qualifiedExpression.getSelectorExpression() != expression) return null;
1134
1135 KtExpression receiverExpression = qualifiedExpression.getReceiverExpression();
1136 generateInstructions(receiverExpression);
1137
1138 return receiverExpression;
1139 }
1140
1141 @Override
1142 public void visitProperty(@NotNull KtProperty property) {
1143 builder.declareVariable(property);
1144 KtExpression initializer = property.getInitializer();
1145 if (initializer != null) {
1146 visitAssignment(property, getDeferredValue(initializer), property);
1147 }
1148 KtExpression delegate = property.getDelegateExpression();
1149 if (delegate != null) {
1150 generateInstructions(delegate);
1151 if (builder.getBoundValue(delegate) != null) {
1152 createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate);
1153 }
1154 }
1155
1156 if (KtPsiUtil.isLocal(property)) {
1157 for (KtPropertyAccessor accessor : property.getAccessors()) {
1158 generateInstructions(accessor);
1159 }
1160 }
1161 }
1162
1163 @Override
1164 public void visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration declaration) {
1165 visitDestructuringDeclaration(declaration, true);
1166 }
1167
1168 private void visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration declaration, boolean generateWriteForEntries) {
1169 KtExpression initializer = declaration.getInitializer();
1170 generateInstructions(initializer);
1171 for (KtDestructuringDeclarationEntry entry : declaration.getEntries()) {
1172 builder.declareVariable(entry);
1173
1174 ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
1175
1176 PseudoValue writtenValue;
1177 if (resolvedCall != null) {
1178 writtenValue = builder.call(
1179 entry,
1180 resolvedCall,
1181 getReceiverValues(resolvedCall),
1182 Collections.<PseudoValue, ValueParameterDescriptor>emptyMap()
1183 ).getOutputValue();
1184 }
1185 else {
1186 writtenValue = createSyntheticValue(entry, MagicKind.UNRESOLVED_CALL, initializer);
1187 }
1188
1189 if (generateWriteForEntries) {
1190 generateInitializer(entry, writtenValue != null ? writtenValue : createSyntheticValue(entry, MagicKind.FAKE_INITIALIZER));
1191 }
1192 }
1193 }
1194
1195 @Override
1196 public void visitPropertyAccessor(@NotNull KtPropertyAccessor accessor) {
1197 processLocalDeclaration(accessor);
1198 }
1199
1200 @Override
1201 public void visitBinaryWithTypeRHSExpression(@NotNull KtBinaryExpressionWithTypeRHS expression) {
1202 mark(expression);
1203
1204 IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
1205 KtExpression left = expression.getLeft();
1206 if (operationType == KtTokens.AS_KEYWORD || operationType == KtTokens.AS_SAFE) {
1207 generateInstructions(left);
1208 if (getBoundOrUnreachableValue(left) != null) {
1209 createNonSyntheticValue(expression, MagicKind.CAST, left);
1210 }
1211 }
1212 else {
1213 visitKtElement(expression);
1214 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, left);
1215 }
1216 }
1217
1218 @Override
1219 public void visitThrowExpression(@NotNull KtThrowExpression expression) {
1220 mark(expression);
1221
1222 KtExpression thrownExpression = expression.getThrownExpression();
1223 if (thrownExpression == null) return;
1224
1225 generateInstructions(thrownExpression);
1226
1227 PseudoValue thrownValue = builder.getBoundValue(thrownExpression);
1228 if (thrownValue == null) return;
1229
1230 builder.throwException(expression, thrownValue);
1231 }
1232
1233 @Override
1234 public void visitArrayAccessExpression(@NotNull KtArrayAccessExpression expression) {
1235 generateArrayAccess(expression, trace.get(BindingContext.INDEXED_LVALUE_GET, expression));
1236 }
1237
1238 @Override
1239 public void visitIsExpression(@NotNull KtIsExpression expression) {
1240 mark(expression);
1241 KtExpression left = expression.getLeftHandSide();
1242 generateInstructions(left);
1243 createNonSyntheticValue(expression, MagicKind.IS, left);
1244 }
1245
1246 @Override
1247 public void visitWhenExpression(@NotNull KtWhenExpression expression) {
1248 mark(expression);
1249
1250 KtExpression subjectExpression = expression.getSubjectExpression();
1251 if (subjectExpression != null) {
1252 generateInstructions(subjectExpression);
1253 }
1254
1255 List<KtExpression> branches = new ArrayList<KtExpression>();
1256
1257 Label doneLabel = builder.createUnboundLabel("after 'when' expression");
1258
1259 Label nextLabel = null;
1260 for (Iterator<KtWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) {
1261 KtWhenEntry whenEntry = iterator.next();
1262 mark(whenEntry);
1263
1264 boolean isElse = whenEntry.isElse();
1265 if (isElse) {
1266 if (iterator.hasNext()) {
1267 trace.report(ELSE_MISPLACED_IN_WHEN.on(whenEntry));
1268 }
1269 }
1270 Label bodyLabel = builder.createUnboundLabel("'when' entry body");
1271
1272 KtWhenCondition[] conditions = whenEntry.getConditions();
1273 for (int i = 0; i < conditions.length; i++) {
1274 KtWhenCondition condition = conditions[i];
1275 condition.accept(conditionVisitor);
1276 if (i + 1 < conditions.length) {
1277 builder.nondeterministicJump(bodyLabel, expression, builder.getBoundValue(condition));
1278 }
1279 }
1280
1281 if (!isElse) {
1282 nextLabel = builder.createUnboundLabel("next 'when' entry");
1283 KtWhenCondition lastCondition = ArraysKt.lastOrNull(conditions);
1284 builder.nondeterministicJump(nextLabel, expression, builder.getBoundValue(lastCondition));
1285 }
1286
1287 builder.bindLabel(bodyLabel);
1288 KtExpression whenEntryExpression = whenEntry.getExpression();
1289 if (whenEntryExpression != null) {
1290 generateInstructions(whenEntryExpression);
1291 branches.add(whenEntryExpression);
1292 }
1293 builder.jump(doneLabel, expression);
1294
1295 if (!isElse) {
1296 builder.bindLabel(nextLabel);
1297 // For the last entry of exhaustive when,
1298 // attempt to jump further should lead to error, not to "done"
1299 if (!iterator.hasNext() && WhenChecker.isWhenExhaustive(expression, trace)) {
1300 builder.jumpToError(expression);
1301 }
1302 }
1303 }
1304 builder.bindLabel(doneLabel);
1305
1306 mergeValues(branches, expression);
1307 }
1308
1309 @Override
1310 public void visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression) {
1311 mark(expression);
1312 KtObjectDeclaration declaration = expression.getObjectDeclaration();
1313 generateInstructions(declaration);
1314
1315 builder.createAnonymousObject(expression);
1316 }
1317
1318 @Override
1319 public void visitObjectDeclaration(@NotNull KtObjectDeclaration objectDeclaration) {
1320 generateHeaderDelegationSpecifiers(objectDeclaration);
1321 generateInitializersForScriptClassOrObject(objectDeclaration);
1322 generateDeclarationForLocalClassOrObjectIfNeeded(objectDeclaration);
1323 }
1324
1325 @Override
1326 public void visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression) {
1327 mark(expression);
1328
1329 List<KtExpression> inputExpressions = new ArrayList<KtExpression>();
1330 for (KtStringTemplateEntry entry : expression.getEntries()) {
1331 if (entry instanceof KtStringTemplateEntryWithExpression) {
1332 KtExpression entryExpression = entry.getExpression();
1333 generateInstructions(entryExpression);
1334 inputExpressions.add(entryExpression);
1335 }
1336 }
1337 builder.loadStringTemplate(expression, elementsToValues(inputExpressions));
1338 }
1339
1340 @Override
1341 public void visitTypeProjection(@NotNull KtTypeProjection typeProjection) {
1342 // TODO : Support Type Arguments. Companion object may be initialized at this point");
1343 }
1344
1345 @Override
1346 public void visitAnonymousInitializer(@NotNull KtAnonymousInitializer classInitializer) {
1347 generateInstructions(classInitializer.getBody());
1348 }
1349
1350 private void generateHeaderDelegationSpecifiers(@NotNull KtClassOrObject classOrObject) {
1351 for (KtSuperTypeListEntry specifier : classOrObject.getSuperTypeListEntries()) {
1352 generateInstructions(specifier);
1353 }
1354 }
1355
1356 private void generateInitializersForScriptClassOrObject(@NotNull KtDeclarationContainer classOrObject) {
1357 for (KtDeclaration declaration : classOrObject.getDeclarations()) {
1358 if (declaration instanceof KtProperty || declaration instanceof KtAnonymousInitializer) {
1359 generateInstructions(declaration);
1360 }
1361 }
1362 }
1363
1364 @Override
1365 public void visitClass(@NotNull KtClass klass) {
1366 if (klass.hasPrimaryConstructor()) {
1367 processParameters(klass.getPrimaryConstructorParameters());
1368
1369 // delegation specifiers of primary constructor, anonymous class and property initializers
1370 generateHeaderDelegationSpecifiers(klass);
1371 generateInitializersForScriptClassOrObject(klass);
1372 }
1373
1374 generateDeclarationForLocalClassOrObjectIfNeeded(klass);
1375 }
1376
1377 @Override
1378 public void visitScript(@NotNull KtScript script) {
1379 generateInitializersForScriptClassOrObject(script);
1380 }
1381
1382 private void generateDeclarationForLocalClassOrObjectIfNeeded(@NotNull KtClassOrObject classOrObject) {
1383 if (classOrObject.isLocal()) {
1384 for (KtDeclaration declaration : classOrObject.getDeclarations()) {
1385 if (declaration instanceof KtSecondaryConstructor ||
1386 declaration instanceof KtProperty ||
1387 declaration instanceof KtAnonymousInitializer) {
1388 continue;
1389 }
1390 generateInstructions(declaration);
1391 }
1392 }
1393 }
1394
1395 private void processParameters(@NotNull List<KtParameter> parameters) {
1396 for (KtParameter parameter : parameters) {
1397 generateInstructions(parameter);
1398 }
1399 }
1400
1401 @Override
1402 public void visitSecondaryConstructor(@NotNull KtSecondaryConstructor constructor) {
1403 KtClassOrObject classOrObject = PsiTreeUtil.getParentOfType(constructor, KtClassOrObject.class);
1404 assert classOrObject != null : "Guaranteed by parsing contract";
1405
1406 processParameters(constructor.getValueParameters());
1407 generateCallOrMarkUnresolved(constructor.getDelegationCall());
1408
1409 if (!constructor.getDelegationCall().isCallToThis()) {
1410 generateInitializersForScriptClassOrObject(classOrObject);
1411 }
1412
1413 generateInstructions(constructor.getBodyExpression());
1414 }
1415
1416 @Override
1417 public void visitSuperTypeCallEntry(@NotNull KtSuperTypeCallEntry call) {
1418 generateCallOrMarkUnresolved(call);
1419 }
1420
1421 private void generateCallOrMarkUnresolved(@Nullable KtCallElement call) {
1422 if (call == null) return;
1423 if (!generateCall(call)) {
1424 List<KtExpression> arguments = CollectionsKt.map(
1425 call.getValueArguments(),
1426 new Function1<ValueArgument, KtExpression>() {
1427 @Override
1428 public KtExpression invoke(ValueArgument valueArgument) {
1429 return valueArgument.getArgumentExpression();
1430 }
1431 }
1432 );
1433
1434 for (KtExpression argument : arguments) {
1435 generateInstructions(argument);
1436 }
1437 createNonSyntheticValue(call, arguments, MagicKind.UNRESOLVED_CALL);
1438 }
1439 }
1440
1441 @Override
1442 public void visitDelegatedSuperTypeEntry(@NotNull KtDelegatedSuperTypeEntry specifier) {
1443 KtExpression delegateExpression = specifier.getDelegateExpression();
1444 generateInstructions(delegateExpression);
1445 createSyntheticValue(specifier, MagicKind.VALUE_CONSUMER, delegateExpression);
1446 }
1447
1448 @Override
1449 public void visitSuperTypeEntry(@NotNull KtSuperTypeEntry specifier) {
1450 // Do not generate UNSUPPORTED_ELEMENT here
1451 }
1452
1453 @Override
1454 public void visitSuperTypeList(@NotNull KtSuperTypeList list) {
1455 list.acceptChildren(this);
1456 }
1457
1458 @Override
1459 public void visitKtFile(@NotNull KtFile file) {
1460 for (KtDeclaration declaration : file.getDeclarations()) {
1461 if (declaration instanceof KtProperty) {
1462 generateInstructions(declaration);
1463 }
1464 }
1465 }
1466
1467 @Override
1468 public void visitDoubleColonExpression(@NotNull KtDoubleColonExpression expression) {
1469 mark(expression);
1470 createNonSyntheticValue(expression, MagicKind.CALLABLE_REFERENCE);
1471 }
1472
1473 @Override
1474 public void visitKtElement(@NotNull KtElement element) {
1475 createNonSyntheticValue(element, MagicKind.UNSUPPORTED_ELEMENT);
1476 }
1477
1478 private boolean generateCall(@Nullable KtElement callElement) {
1479 if (callElement == null) return false;
1480 return checkAndGenerateCall(CallUtilKt.getResolvedCall(callElement, trace.getBindingContext()));
1481 }
1482
1483 private boolean checkAndGenerateCall(@Nullable ResolvedCall<?> resolvedCall) {
1484 if (resolvedCall == null) return false;
1485 generateCall(resolvedCall);
1486 return true;
1487 }
1488
1489 @NotNull
1490 private InstructionWithValue generateCall(@NotNull ResolvedCall<?> resolvedCall) {
1491 KtElement callElement = resolvedCall.getCall().getCallElement();
1492
1493 Map<PseudoValue, ReceiverValue> receivers = getReceiverValues(resolvedCall);
1494
1495 SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues = SmartFMap.emptyMap();
1496 for (ValueArgument argument : resolvedCall.getCall().getValueArguments()) {
1497 ArgumentMapping argumentMapping = resolvedCall.getArgumentMapping(argument);
1498 KtExpression argumentExpression = argument.getArgumentExpression();
1499 if (argumentMapping instanceof ArgumentMatch) {
1500 parameterValues = generateValueArgument(argument, ((ArgumentMatch) argumentMapping).getValueParameter(), parameterValues);
1501 }
1502 else if (argumentExpression != null) {
1503 generateInstructions(argumentExpression);
1504 createSyntheticValue(argumentExpression, MagicKind.VALUE_CONSUMER, argumentExpression);
1505 }
1506 }
1507
1508 if (resolvedCall.getResultingDescriptor() instanceof VariableDescriptor) {
1509 // If a callee of the call is just a variable (without 'invoke'), 'read variable' is generated.
1510 // todo : process arguments for such a case (KT-5387)
1511 KtExpression callExpression = callElement instanceof KtExpression ? (KtExpression) callElement : null;
1512 assert callExpression != null
1513 : "Variable-based call without callee expression: " + callElement.getText();
1514 assert parameterValues.isEmpty()
1515 : "Variable-based call with non-empty argument list: " + callElement.getText();
1516 return builder.readVariable(callExpression, resolvedCall, receivers);
1517 }
1518
1519 mark(resolvedCall.getCall().getCallElement());
1520 return builder.call(callElement, resolvedCall, receivers, parameterValues);
1521 }
1522
1523 @NotNull
1524 private Map<PseudoValue, ReceiverValue> getReceiverValues(ResolvedCall<?> resolvedCall) {
1525 PseudoValue varCallResult = null;
1526 ReceiverValue explicitReceiver = null;
1527 if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
1528 varCallResult = generateCall(((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall()).getOutputValue();
1529
1530 ExplicitReceiverKind kind = resolvedCall.getExplicitReceiverKind();
1531 //noinspection EnumSwitchStatementWhichMissesCases
1532 switch (kind) {
1533 case DISPATCH_RECEIVER:
1534 explicitReceiver = resolvedCall.getDispatchReceiver();
1535 break;
1536 case EXTENSION_RECEIVER:
1537 case BOTH_RECEIVERS:
1538 explicitReceiver = (ReceiverValue) resolvedCall.getExtensionReceiver();
1539 break;
1540 }
1541 }
1542
1543 SmartFMap<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap();
1544 if (explicitReceiver != null && varCallResult != null) {
1545 receiverValues = receiverValues.plus(varCallResult, explicitReceiver);
1546 }
1547 KtElement callElement = resolvedCall.getCall().getCallElement();
1548 receiverValues = getReceiverValues(callElement, resolvedCall.getDispatchReceiver(), receiverValues);
1549 receiverValues = getReceiverValues(callElement, (ReceiverValue) resolvedCall.getExtensionReceiver(), receiverValues);
1550 return receiverValues;
1551 }
1552
1553 @NotNull
1554 private SmartFMap<PseudoValue, ReceiverValue> getReceiverValues(
1555 KtElement callElement,
1556 @Nullable ReceiverValue receiver,
1557 SmartFMap<PseudoValue, ReceiverValue> receiverValues
1558 ) {
1559 if (receiver == null || receiverValues.containsValue(receiver)) return receiverValues;
1560
1561 if (receiver instanceof ImplicitReceiver) {
1562 receiverValues = receiverValues.plus(createSyntheticValue(callElement, MagicKind.IMPLICIT_RECEIVER), receiver);
1563 }
1564 else if (receiver instanceof ExpressionReceiver) {
1565 KtExpression expression = ((ExpressionReceiver) receiver).getExpression();
1566 if (builder.getBoundValue(expression) == null) {
1567 generateInstructions(expression);
1568 }
1569
1570 PseudoValue receiverPseudoValue = getBoundOrUnreachableValue(expression);
1571 if (receiverPseudoValue != null) {
1572 receiverValues = receiverValues.plus(receiverPseudoValue, receiver);
1573 }
1574 }
1575 else if (receiver instanceof TransientReceiver) {
1576 // Do nothing
1577 }
1578 else {
1579 throw new IllegalArgumentException("Unknown receiver kind: " + receiver);
1580 }
1581
1582 return receiverValues;
1583 }
1584
1585 @NotNull
1586 private SmartFMap<PseudoValue, ValueParameterDescriptor> generateValueArgument(
1587 ValueArgument valueArgument,
1588 ValueParameterDescriptor parameterDescriptor,
1589 SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues) {
1590 KtExpression expression = valueArgument.getArgumentExpression();
1591 if (expression != null) {
1592 if (!valueArgument.isExternal()) {
1593 generateInstructions(expression);
1594 }
1595
1596 PseudoValue argValue = getBoundOrUnreachableValue(expression);
1597 if (argValue != null) {
1598 parameterValues = parameterValues.plus(argValue, parameterDescriptor);
1599 }
1600 }
1601 return parameterValues;
1602 }
1603 }
1604 }