diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index d7dbfc8d51a..6ab0daef28b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -39,8 +39,8 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.calls.TailRecursionKind; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; -import org.jetbrains.jet.lang.resolve.calls.tail.TailRecursionKind; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver; @@ -55,10 +55,9 @@ import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.BACK import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.FORWARD; import static org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; -import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE; -import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; import static org.jetbrains.jet.lang.resolve.BindingContext.*; -import static org.jetbrains.jet.lang.resolve.calls.tail.TailRecursionKind.*; +import static org.jetbrains.jet.lang.resolve.calls.TailRecursionKind.*; +import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType; public class JetFlowInformationProvider { @@ -680,7 +679,7 @@ public class JetFlowInformationProvider { boolean sameThisObject = sameThisObject(resolvedCall); - TailRecursionKind kind = isTail && sameThisObject ? MIGHT_BE : NON_TAIL; + TailRecursionKind kind = isTail && sameThisObject ? TAIL_CALL : NON_TAIL; KindAndCall kindAndCall = calls.get(element); calls.put(element, @@ -696,9 +695,8 @@ public class JetFlowInformationProvider { JetElement element = entry.getKey(); KindAndCall kindAndCall = entry.getValue(); switch (kindAndCall.kind) { - case MIGHT_BE: - case IN_RETURN: - trace.record(TAIL_RECURSION_CALL, kindAndCall.call, TailRecursionKind.IN_RETURN); + case TAIL_CALL: + trace.record(TAIL_RECURSION_CALL, kindAndCall.call, TailRecursionKind.TAIL_CALL); trace.record(BindingContext.HAS_TAIL_CALLS, (FunctionDescriptor) subroutineDescriptor); break; case IN_TRY: @@ -745,14 +743,14 @@ public class JetFlowInformationProvider { resultingKind = kind; } else { - if (check(kind, existingKind, IN_TRY, MIGHT_BE)) { + if (check(kind, existingKind, IN_TRY, TAIL_CALL)) { resultingKind = IN_TRY; } else if (check(kind, existingKind, IN_TRY, NON_TAIL)) { resultingKind = IN_TRY; } else { - // MIGHT_BE, NON_TAIL + // TAIL_CALL, NON_TAIL resultingKind = NON_TAIL; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index f4a291bbd2e..f6f130e919c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -1028,37 +1028,4 @@ public class JetPsiUtil { expression; return (JetToken) elementType; } - - @NotNull - public static T visitUpwardToRoot( - @NotNull PsiElement element, - @NotNull JetVisitor, VisitorData> visitor, - T def - ) { - List track = new ArrayList(); - List view = Collections.unmodifiableList(track); - @NotNull - BacktraceVisitorStatus lastStatus = new BacktraceVisitorStatus(def, true); - VisitorData data = new VisitorData(view); - - do { - track.add(element); - PsiElement parent = element.getParent(); - if (parent instanceof JetElement) { - JetElement jet = (JetElement) parent; - data.last = element; - data.data = lastStatus.getData(); - - BacktraceVisitorStatus status = jet.accept(visitor, data); - if (status == null) { - throw new IllegalStateException("visitor has returned null status"); - } - lastStatus = status; - } - - element = parent; - } while (element != null && !lastStatus.isAbortTrace()); - - return lastStatus.getData(); - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverExtensionProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverExtensionProvider.java index ee89bc9660d..ae5e3c17b22 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverExtensionProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverExtensionProvider.java @@ -20,7 +20,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; -import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.lang.ref.WeakReference; import java.util.*; @@ -78,14 +77,7 @@ public class CallResolverExtensionProvider { extensions.add(new InlineCallResolverExtension(descriptor)); } } - if (isAnnotatedAsTailRecursive(declarationDescriptor)) { - extensions.add(TailRecursionDetectorExtension.INSTANCE); - } // add your extensions here extensions.add(DEFAULT); } - - private static boolean isAnnotatedAsTailRecursive(DeclarationDescriptor descriptor) { - return KotlinBuiltIns.getInstance().isTailRecursive(descriptor); - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/RecursiveCallRecorderResolverExtension.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/RecursiveCallRecorderResolverExtension.java deleted file mode 100644 index 072622a65d0..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/RecursiveCallRecorderResolverExtension.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.calls; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.psi.JetCallExpression; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; -import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl; - -import java.util.ArrayList; -import java.util.List; - -public class RecursiveCallRecorderResolverExtension extends RecursiveCallResolverExtension { - - public static final RecursiveCallRecorderResolverExtension INSTANCE = new RecursiveCallRecorderResolverExtension(); - - @Override - protected void runImpl( - @NotNull JetCallExpression callExpression, - @NotNull ResolvedCall resolvedCall, - @NotNull BasicCallResolutionContext context - ) { - DeclarationDescriptor declarationDescriptor = context.scope.getContainingDeclaration(); - - List expressions = - context.trace.get(BindingContext.FUNCTION_RECURSIVE_CALL_EXPRESSIONS, declarationDescriptor); - - if (expressions == null) { - expressions = new ArrayList(2); - context.trace.record(BindingContext.FUNCTION_RECURSIVE_CALL_EXPRESSIONS, declarationDescriptor, expressions); - } - - expressions.add(callExpression); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionDetectorExtension.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionDetectorExtension.java deleted file mode 100644 index 684be153b3c..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionDetectorExtension.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.calls; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; -import org.jetbrains.jet.lang.diagnostics.Errors; -import org.jetbrains.jet.lang.psi.JetCallExpression; -import org.jetbrains.jet.lang.psi.JetPsiUtil; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; -import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl; - -public class TailRecursionDetectorExtension extends RecursiveCallResolverExtension { - - public static final TailRecursionDetectorExtension INSTANCE = new TailRecursionDetectorExtension(); - - @Override - protected void runImpl( - @NotNull JetCallExpression callExpression, - @NotNull ResolvedCall resolvedCall, - @NotNull BasicCallResolutionContext context - ) { - BindingTrace trace = context.trace; - - TailRecursionKind recursionKind = - JetPsiUtil.visitUpwardToRoot(callExpression, new TailRecursionDetectorVisitor(), TailRecursionKind.MIGHT_BE); - - trace.record(BindingContext.TAIL_RECURSION_CALL, - callExpression, - recursionKind); - - switch (recursionKind) { - case NON_TAIL: - trace.report(Errors.NON_TAIL_RECURSIVE_CALL.on(callExpression)); - break; - case IN_TRY: - trace.report(Errors.TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED.on(callExpression)); - break; - default: - break; - } - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionDetectorVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionDetectorVisitor.java deleted file mode 100644 index 8e2e6ba15db..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionDetectorVisitor.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.calls; - -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lexer.JetTokens; - -public class TailRecursionDetectorVisitor extends JetVisitor, VisitorData> { - - @Override - public BacktraceVisitorStatus visitNamedFunction( - @NotNull JetNamedFunction function, VisitorData data - ) { - return new BacktraceVisitorStatus(data.data, true); - } - - @Override - public BacktraceVisitorStatus visitTryExpression( - @NotNull JetTryExpression expression, VisitorData data - ) { - return noTailRecursion(TailRecursionKind.IN_TRY); - } - - @Override - public BacktraceVisitorStatus visitCatchSection( - @NotNull JetCatchClause catchClause, VisitorData data - ) { - return continueTrace(data); - } - - @Override - public BacktraceVisitorStatus visitFinallySection( - @NotNull JetFinallySection finallySection, VisitorData data - ) { - return continueTrace(data); - } - - @Override - public BacktraceVisitorStatus visitBlockExpression( - @NotNull JetBlockExpression expression, VisitorData data - ) { - - if (data.data.isReturn()) return continueTrace(data); - - PsiElement child = data.last; - - JetElement last = findLastJetElement(expression.getLastChild()); - if (last != child) { // if last statement - if (!(last instanceof JetReturnExpression)) { - return noTailRecursion(); - } - - JetReturnExpression returnExpression = (JetReturnExpression) last; - if (returnExpression.getReturnedExpression() != null) { - return noTailRecursion(); - } - - if (findLastJetElement(returnExpression.getPrevSibling()) != child) { - return noTailRecursion(); - } - } - - return continueTrace(data); - } - - @Override - public BacktraceVisitorStatus visitWhenExpression( - @NotNull JetWhenExpression expression, VisitorData data - ) { - if (expression.getSubjectExpression() == data.last) { - return noTailRecursion(); - } - - return continueTrace(data); - } - - @Override - public BacktraceVisitorStatus visitWhenEntry( - @NotNull JetWhenEntry jetWhenEntry, VisitorData data - ) { - return continueTrace(data); - } - - @Override - public BacktraceVisitorStatus visitWhenConditionExpression( - @NotNull JetWhenConditionWithExpression condition, VisitorData data - ) { - return noTailRecursion(); - } - - @Override - public BacktraceVisitorStatus visitIfExpression( - @NotNull JetIfExpression expression, VisitorData data - ) { - if (expression.getCondition() == data.last) { - return noTailRecursion(); - } - - return continueTrace(data); - } - - @Override - public BacktraceVisitorStatus visitBinaryExpression( - @NotNull JetBinaryExpression expression, VisitorData data - ) { - if (expression.getOperationToken() == JetTokens.ELVIS) { - if (expression.getLeft() == data.last) { - return noTailRecursion(); - } - else if (expression.getRight() == data.last) { - return continueTrace(data); - } - else { - return noTailRecursion(); - } - } - - return super.visitBinaryExpression(expression, data); - } - - @Override - public BacktraceVisitorStatus visitQualifiedExpression( - @NotNull JetQualifiedExpression expression, VisitorData data - ) { - if (!(expression.getReceiverExpression() instanceof JetThisExpression)) { - return noTailRecursion(); - } - - return continueTrace(data); - } - - @Override - public BacktraceVisitorStatus visitReturnExpression( - @NotNull JetReturnExpression expression, VisitorData data - ) { - JetExpression returned = expression.getReturnedExpression(); - if (returned == null) { - throw new IllegalStateException("Bad case: how could we reach void return?"); - } - - return continueTrace(data, TailRecursionKind.IN_RETURN); - } - - @Override - public BacktraceVisitorStatus visitJetElement( - @NotNull JetElement element, VisitorData state - ) { - if (element instanceof JetContainerNode) { - return continueTrace(state); - } - - if (state.data == TailRecursionKind.MIGHT_BE) { - return noTailRecursion(); - } - - return continueTrace(state); - } - - private static BacktraceVisitorStatus noTailRecursion() { - return new BacktraceVisitorStatus(TailRecursionKind.NON_TAIL, true); - } - - private static BacktraceVisitorStatus noTailRecursion(TailRecursionKind status) { - return new BacktraceVisitorStatus(status, true); - } - - private static BacktraceVisitorStatus continueTrace(VisitorData data) { - return continueTrace(data, TailRecursionKind.MIGHT_BE); - } - - private static BacktraceVisitorStatus continueTrace(VisitorData data, TailRecursionKind desiredStatus) { - TailRecursionKind newStatus = data.data.and(desiredStatus); - return new BacktraceVisitorStatus(newStatus, !newStatus.isDoGenerateTailRecursion()); - } - - @Nullable - private static JetElement findLastJetElement(@Nullable PsiElement rightNode) { - PsiElement node = rightNode; - while (node != null) { - if (node instanceof JetElement) { - return (JetElement) node; - } - node = node.getPrevSibling(); - } - - return null; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionKind.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionKind.java index 13e6ff537a3..1f33c581c94 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionKind.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TailRecursionKind.java @@ -17,8 +17,7 @@ package org.jetbrains.jet.lang.resolve.calls; public enum TailRecursionKind { - MIGHT_BE(true), - IN_RETURN(true), + TAIL_CALL(true), IN_TRY(false), NON_TAIL(false); @@ -31,31 +30,4 @@ public enum TailRecursionKind { public boolean isDoGenerateTailRecursion() { return doGenerateTailRecursion; } - - public boolean isReturn() { - return this == IN_RETURN; - } - - public TailRecursionKind and(TailRecursionKind b) { - if (this == b) { - return this; - } - if (!this.isDoGenerateTailRecursion()) { - return this; - } - if (!b.isDoGenerateTailRecursion()) { - return this; - } - - if (isOneOf(this, b, IN_RETURN)) { - return IN_RETURN; - } - - return this; - } - - private static boolean isOneOf(TailRecursionKind a, TailRecursionKind b, TailRecursionKind value) { - return a == value || b == value; - } - }