JS backend: expand jsCode at translator

This commit is contained in:
Alexey Tsvetkov
2014-03-24 06:10:07 +04:00
parent 41af895caa
commit bc7afdf0b8
4 changed files with 101 additions and 17 deletions
+1
View File
@@ -14,5 +14,6 @@
<orderEntry type="module" module-name="js.dart-ast" exported="" />
<orderEntry type="module" module-name="js.frontend" exported="" />
<orderEntry type="module" module-name="js.inliner" exported="" />
<orderEntry type="module" module-name="js.parser" />
</component>
</module>
@@ -191,8 +191,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
if (shouldBeInlined(expression, context) &&
BindingContextUtilPackage.isUsedAsExpression(expression, context.bindingContext())) {
TemporaryVariable temporaryVariable = context.declareTemporary(null);
JsExpression callResult = CallExpressionTranslator.translate(expression, null, context).source(expression);
context.addStatementToCurrentBlock(JsAstUtils.assignment(temporaryVariable.reference(), callResult).makeStmt());
JsNode callResult = CallExpressionTranslator.translate(expression, null, context).source(expression);
assert callResult instanceof JsExpression;
JsExpression assignment = JsAstUtils.assignment(temporaryVariable.reference(), (JsExpression) callResult);
context.addStatementToCurrentBlock(assignment.makeStmt());
return temporaryVariable.reference();
} else {
return CallExpressionTranslator.translate(expression, null, context).source(expression);
@@ -16,32 +16,51 @@
package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsInvocation;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import com.google.dart.compiler.common.SourceInfoImpl;
import com.google.gwt.dev.js.JsParser;
import com.google.gwt.dev.js.JsParserException;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.types.lang.InlineStrategy;
import org.jetbrains.jet.lang.types.lang.InlineUtil;
import org.jetbrains.jet.lang.psi.ValueArgument;
import org.jetbrains.k2js.translate.callTranslator.CallTranslator;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredicate;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage.getFunctionResolvedCallWithAssert;
public final class CallExpressionTranslator extends AbstractCallExpressionTranslator {
@NotNull
public static JsExpression translate(
private final static DescriptorPredicate JSCODE_PATTERN = PatternBuilder.pattern("kotlin.js.js(String)");
@NotNull
public static JsNode translate(
@NotNull JetCallExpression expression,
@Nullable JsExpression receiver,
@NotNull TranslationContext context
) {
if (matchesJsCode(expression, context)) {
return (new CallExpressionTranslator(expression, receiver, context)).translateJsCode();
}
JsExpression callExpression = (new CallExpressionTranslator(expression, receiver, context)).translate();
if (shouldBeInlined(expression, context)
@@ -80,6 +99,16 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
return false;
}
private static boolean matchesJsCode(
@NotNull JetCallExpression expression,
@NotNull TranslationContext context
) {
FunctionDescriptor descriptor = getFunctionResolvedCallWithAssert(expression, context.bindingContext())
.getResultingDescriptor();
return JSCODE_PATTERN.apply(descriptor) && expression.getValueArguments().size() == 1;
}
private CallExpressionTranslator(
@NotNull JetCallExpression expression,
@Nullable JsExpression receiver,
@@ -92,4 +121,47 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
private JsExpression translate() {
return CallTranslator.INSTANCE$.translate(context(), resolvedCall, receiver);
}
@NotNull
private JsNode translateJsCode() {
List<? extends ValueArgument> arguments = expression.getValueArguments();
JetExpression argumentExpression = arguments.get(0).getArgumentExpression();
assert argumentExpression != null;
Object jsCode = BindingUtils.getCompileTimeValue(bindingContext(), argumentExpression);
assert jsCode instanceof String: "jsCode must be compile time string";
List<JsStatement> statements = parseJsCode((String) jsCode);
int size = statements.size();
if (size == 0) {
return program().getEmptyStatement();
} else if (size > 1) {
return new JsBlock(statements);
} else {
JsStatement resultStatement = statements.get(0);
if (resultStatement instanceof JsExpressionStatement) {
return ((JsExpressionStatement) resultStatement).getExpression();
}
return resultStatement;
}
}
@NotNull
private List<JsStatement> parseJsCode(@NotNull String jsCode) {
List<JsStatement> statements = new ArrayList<JsStatement>();
try {
SourceInfoImpl info = new SourceInfoImpl(null, 0, 0, 0, 0);
JsScope scope = context().scope();
StringReader reader = new StringReader(jsCode);
statements.addAll(JsParser.parse(info, scope, reader, /* insideFunction= */ true));
} catch (JsParserException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
return statements;
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
@@ -52,15 +53,17 @@ public final class QualifiedExpressionTranslator {
}
@NotNull
public static JsExpression translateQualifiedExpression(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
public static JsNode translateQualifiedExpression(
@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context
) {
JsExpression receiver = translateReceiver(expression, context);
JetExpression selector = getSelector(expression);
return dispatchToCorrectTranslator(receiver, selector, context);
}
@NotNull
private static JsExpression dispatchToCorrectTranslator(
private static JsNode dispatchToCorrectTranslator(
@Nullable JsExpression receiver,
@NotNull JetExpression selector,
@NotNull TranslationContext context
@@ -73,8 +76,12 @@ public final class QualifiedExpressionTranslator {
if (shouldBeInlined((JetCallExpression) selector, context) &&
BindingContextUtilPackage.isUsedAsExpression(selector, context.bindingContext())) {
TemporaryVariable temporaryVariable = context.declareTemporary(null);
JsExpression result = invokeCallExpressionTranslator(receiver, selector, context);
context.addStatementToCurrentBlock(JsAstUtils.assignment(temporaryVariable.reference(), result).makeStmt());
JsNode result = invokeCallExpressionTranslator(receiver, selector, context);
assert result instanceof JsExpression;
JsExpression assignment = JsAstUtils.assignment(temporaryVariable.reference(), (JsExpression) result);
context.addStatementToCurrentBlock(assignment.makeStmt());
return temporaryVariable.reference();
} else {
return invokeCallExpressionTranslator(receiver, selector, context);
@@ -88,7 +95,7 @@ public final class QualifiedExpressionTranslator {
}
@NotNull
private static JsExpression invokeCallExpressionTranslator(
private static JsNode invokeCallExpressionTranslator(
@Nullable JsExpression receiver,
@NotNull JetExpression selector,
@NotNull TranslationContext context