Remove functionality delegated to LiteralFunctionTranslator from FunctionTranslator.

Adapted from https://github.com/develar/kotlin/commit/a9e0a42fb1347fa8e21c86b5a073ef8a7c873da0.
This commit is contained in:
Pavel V. Talanov
2012-08-10 21:30:17 +04:00
parent 02622595b5
commit 5694a3644c
@@ -17,24 +17,24 @@
package org.jetbrains.k2js.translate.expression;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import com.google.dart.compiler.backend.js.ast.JsFunction;
import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsParameter;
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.Modality;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.reference.ReferenceTranslator;
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import org.jetbrains.k2js.translate.utils.closure.ClosureContext;
import org.jetbrains.k2js.translate.utils.closure.ClosureUtils;
import java.util.ArrayList;
import java.util.List;
@@ -43,14 +43,12 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescrip
import static org.jetbrains.k2js.translate.utils.ErrorReportingUtils.message;
import static org.jetbrains.k2js.translate.utils.FunctionBodyTranslator.translateFunctionBody;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setParameters;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedReceiverDescriptor;
/**
* @author Pavel Talanov
*/
public final class FunctionTranslator extends AbstractTranslator {
@NotNull
public static FunctionTranslator newInstance(@NotNull JetDeclarationWithBody function,
@NotNull TranslationContext context) {
@@ -59,19 +57,14 @@ public final class FunctionTranslator extends AbstractTranslator {
@NotNull
private final TranslationContext functionBodyContext;
@Nullable
private TemporaryVariable aliasForContainingClassThis = null;
@NotNull
private final JetDeclarationWithBody functionDeclaration;
@Nullable
private JsName extensionFunctionReceiverName = null;
private JsName extensionFunctionReceiverName;
@NotNull
private final JsFunction functionObject;
@NotNull
private final FunctionDescriptor descriptor;
// function body needs to be explicitly created here to include it in the context
@NotNull
private final JsBlock functionBody;
private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration,
@NotNull TranslationContext context) {
@@ -81,33 +74,18 @@ public final class FunctionTranslator extends AbstractTranslator {
this.functionObject = context().getFunctionObject(descriptor);
assert this.functionObject.getParameters().isEmpty()
: message(bindingContext(), descriptor, "Function " + functionDeclaration.getText() + " processed for the second time.");
this.functionBody = functionObject.getBody();
//NOTE: it's important we compute the context before we start the computation
this.functionBodyContext = getFunctionBodyContext();
}
@NotNull
private TranslationContext getFunctionBodyContext() {
if (isLiteral()) {
return getFunctionBodyContextForLiteral();
}
if (isExtensionFunction()) {
return getFunctionBodyContextForExtensionFunction();
}
return getContextWithFunctionBodyBlock();
}
@NotNull
private TranslationContext getFunctionBodyContextForLiteral() {
ClassDescriptor containingClass = getContainingClass(descriptor);
if (containingClass == null) {
return getContextWithFunctionBodyBlock();
}
JsExpression thisQualifier = TranslationUtils.getThisObject(context(), containingClass);
aliasForContainingClassThis = context().declareTemporary(thisQualifier);
return getContextWithFunctionBodyBlock().innerContextWithThisAliased(containingClass, aliasForContainingClassThis.name());
}
@NotNull
private TranslationContext getFunctionBodyContextForExtensionFunction() {
TranslationContext contextWithFunctionBodyBlock = getContextWithFunctionBodyBlock();
@@ -119,10 +97,9 @@ public final class FunctionTranslator extends AbstractTranslator {
@NotNull
private TranslationContext getContextWithFunctionBodyBlock() {
return context().newDeclaration(functionDeclaration).innerBlock(functionBody);
return context().newDeclaration(functionDeclaration).innerBlock(functionObject.getBody());
}
@NotNull
public JsFunction translateAsLocalFunction() {
JsName functionName = context().getNameForElement(functionDeclaration);
@@ -144,51 +121,6 @@ public final class FunctionTranslator extends AbstractTranslator {
return new JsPropertyInitializer(functionName.makeRef(), functionObject);
}
@NotNull
public JsExpression translateAsLiteral() {
assert getExpectedThisDescriptor(descriptor) == null;
generateFunctionObject();
ClosureContext closureContext = ClosureUtils.captureClosure(context(), (JetElement) functionDeclaration);
if (closureContext.getDescriptors().isEmpty()) {
return mayBeWrapWithThisAlias();
}
return wrapInClosureCaptureExpression(functionObject, closureContext);
}
@NotNull
private JsExpression mayBeWrapWithThisAlias() {
if (!shouldAliasThisObject()) {
return functionObject;
}
assert aliasForContainingClassThis != null;
return AstUtil.newSequence(aliasForContainingClassThis.assignmentExpression(), functionObject);
}
private boolean shouldAliasThisObject() {
if (!isLiteral()) {
return false;
}
ClassDescriptor containingClass = getContainingClass(descriptor);
return containingClass != null;
}
@NotNull
private JsExpression wrapInClosureCaptureExpression(@NotNull JsExpression wrappedExpression,
@NotNull ClosureContext closureContext) {
JsFunction dummyFunction = new JsFunction(context().scope());
JsInvocation dummyFunctionInvocation = new JsInvocation(dummyFunction);
for (VariableDescriptor variableDescriptor : closureContext.getDescriptors()) {
dummyFunction.getParameters().add(new JsParameter(context().getNameForDescriptor(variableDescriptor)));
dummyFunctionInvocation.getArguments().add(ReferenceTranslator.translateAsLocalNameReference(variableDescriptor, context()));
if (aliasForContainingClassThis != null) {
dummyFunction.getParameters().add(new JsParameter(aliasForContainingClassThis.name()));
dummyFunctionInvocation.getArguments().add(aliasForContainingClassThis.initExpression());
}
}
dummyFunction.setBody(new JsBlock(new JsReturn(wrappedExpression)));
return dummyFunctionInvocation;
}
private void generateFunctionObject() {
setParameters(functionObject, translateParameters());
translateBody();
@@ -200,24 +132,21 @@ public final class FunctionTranslator extends AbstractTranslator {
assert descriptor.getModality().equals(Modality.ABSTRACT);
return;
}
functionBody.getStatements().add(translateFunctionBody(descriptor, functionDeclaration, functionBodyContext));
functionObject.getBody().getStatements().addAll(translateFunctionBody(descriptor, functionDeclaration, functionBodyContext).getStatements());
}
@NotNull
private List<JsParameter> translateParameters() {
List<JsParameter> jsParameters = new ArrayList<JsParameter>();
mayBeAddThisParameterForExtensionFunction(jsParameters);
for (ValueParameterDescriptor valueParameter : descriptor.getValueParameters()) {
JsName parameterName = declareParameter(valueParameter);
jsParameters.add(new JsParameter(parameterName));
}
addParameters(jsParameters, descriptor, context());
return jsParameters;
}
@NotNull
private JsName declareParameter(@NotNull ValueParameterDescriptor valueParameter) {
return context().getNameForDescriptor(valueParameter);
public static void addParameters(List<JsParameter> list, FunctionDescriptor descriptor, TranslationContext context) {
for (ValueParameterDescriptor valueParameter : descriptor.getValueParameters()) {
list.add(new JsParameter(context.getNameForDescriptor(valueParameter)));
}
}
private void mayBeAddThisParameterForExtensionFunction(@NotNull List<JsParameter> jsParameters) {
@@ -228,10 +157,6 @@ public final class FunctionTranslator extends AbstractTranslator {
}
private boolean isExtensionFunction() {
return JsDescriptorUtils.isExtension(descriptor) && !isLiteral();
}
private boolean isLiteral() {
return functionDeclaration instanceof JetFunctionLiteralExpression;
return JsDescriptorUtils.isExtension(descriptor) && !(functionDeclaration instanceof JetFunctionLiteralExpression);
}
}