Refactoring function translator.

This commit is contained in:
Pavel V. Talanov
2012-03-22 15:14:56 +04:00
parent fe53d20a88
commit 69758669cf
@@ -53,8 +53,6 @@ import static org.jetbrains.k2js.translate.utils.mutator.LastExpressionMutator.m
/** /**
* @author Pavel Talanov * @author Pavel Talanov
*/ */
//TODO: class has convoluted code. REFACTOR before changing
public final class FunctionTranslator extends AbstractTranslator { public final class FunctionTranslator extends AbstractTranslator {
@NotNull @NotNull
@@ -63,6 +61,8 @@ public final class FunctionTranslator extends AbstractTranslator {
return new FunctionTranslator(function, context); return new FunctionTranslator(function, context);
} }
@NotNull
private final TranslationContext functionBodyContext;
@Nullable @Nullable
private TemporaryVariable aliasForContaingClassThis = null; private TemporaryVariable aliasForContaingClassThis = null;
@NotNull @NotNull
@@ -84,6 +84,8 @@ public final class FunctionTranslator extends AbstractTranslator {
this.functionDeclaration = functionDeclaration; this.functionDeclaration = functionDeclaration;
this.functionObject = context().getFunctionObject(descriptor); this.functionObject = context().getFunctionObject(descriptor);
this.functionBody = functionObject.getBody(); this.functionBody = functionObject.getBody();
//NOTE: it's important we compute the context before we start the computation
this.functionBodyContext = getFunctionBodyContext();
} }
@NotNull @NotNull
@@ -126,7 +128,7 @@ public final class FunctionTranslator extends AbstractTranslator {
@NotNull @NotNull
public JsFunction translateAsLocalFunction() { public JsFunction translateAsLocalFunction() {
JsName functionName = context().getNameForElement(functionDeclaration); JsName functionName = context().getNameForElement(functionDeclaration);
generateFunctionObject(getFunctionBodyContext()); generateFunctionObject();
functionObject.setName(functionName); functionObject.setName(functionName);
return functionObject; return functionObject;
} }
@@ -134,21 +136,20 @@ public final class FunctionTranslator extends AbstractTranslator {
@NotNull @NotNull
public JsPropertyInitializer translateAsMethod() { public JsPropertyInitializer translateAsMethod() {
JsName functionName = context().getNameForElement(functionDeclaration); JsName functionName = context().getNameForElement(functionDeclaration);
generateFunctionObject(getFunctionBodyContext()); generateFunctionObject();
return new JsPropertyInitializer(functionName.makeRef(), functionObject); return new JsPropertyInitializer(functionName.makeRef(), functionObject);
} }
@NotNull @NotNull
public JsExpression translateAsLiteral() { public JsExpression translateAsLiteral() {
return mayBeWrapInClosureCaptureExpression(doTranslateAsLiteral()); assert getExpectedThisDescriptor(descriptor) == null;
generateFunctionObject();
return mayBeWrapInClosureCaptureExpression(mayBeWrapWithThisAlias());
} }
@NotNull @NotNull
private JsExpression doTranslateAsLiteral() { private JsExpression mayBeWrapWithThisAlias() {
assert getExpectedThisDescriptor(descriptor) == null; if (!shouldAliasThisObject()) {
generateFunctionObject(getFunctionBodyContext());
boolean shouldAliasThisObject = shouldAliasThisObject();
if (!shouldAliasThisObject) {
return functionObject; return functionObject;
} }
assert aliasForContaingClassThis != null; assert aliasForContaingClassThis != null;
@@ -185,19 +186,27 @@ public final class FunctionTranslator extends AbstractTranslator {
return dummyFunctionInvocation; return dummyFunctionInvocation;
} }
private void generateFunctionObject(@NotNull TranslationContext context) { private void generateFunctionObject() {
setParameters(functionObject, translateParameters()); setParameters(functionObject, translateParameters());
translateBody(context); translateBody();
} }
private void translateBody(@NotNull TranslationContext context) { private void translateBody() {
JetExpression jetBodyExpression = functionDeclaration.getBodyExpression(); JetExpression jetBodyExpression = functionDeclaration.getBodyExpression();
if (jetBodyExpression == null) { if (jetBodyExpression == null) {
assert descriptor.getModality().equals(Modality.ABSTRACT); assert descriptor.getModality().equals(Modality.ABSTRACT);
return; return;
} }
JsNode realBody = Translation.translateExpression(jetBodyExpression, context); JsNode realBody = Translation.translateExpression(jetBodyExpression, functionBodyContext);
functionBody.getStatements().add(wrapWithReturnIfNeeded(realBody, mustAddReturnToGeneratedFunctionBody())); functionBody.getStatements().add(mayBeWrapWithReturn(realBody));
}
@NotNull
private JsBlock mayBeWrapWithReturn(@NotNull JsNode body) {
if (!mustAddReturnToGeneratedFunctionBody()) {
return convertToBlock(body);
}
return convertToBlock(lastExpressionReturned(body));
} }
private boolean mustAddReturnToGeneratedFunctionBody() { private boolean mustAddReturnToGeneratedFunctionBody() {
@@ -207,13 +216,6 @@ public final class FunctionTranslator extends AbstractTranslator {
} }
@NotNull @NotNull
private static JsBlock wrapWithReturnIfNeeded(@NotNull JsNode body, boolean needsReturn) {
if (!needsReturn) {
return convertToBlock(body);
}
return convertToBlock(lastExpressionReturned(body));
}
private static JsNode lastExpressionReturned(@NotNull JsNode body) { private static JsNode lastExpressionReturned(@NotNull JsNode body) {
return mutateLastExpression(body, new Mutator() { return mutateLastExpression(body, new Mutator() {
@Override @Override