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