JS backend: expand jsCode at translator
This commit is contained in:
@@ -14,5 +14,6 @@
|
|||||||
<orderEntry type="module" module-name="js.dart-ast" exported="" />
|
<orderEntry type="module" module-name="js.dart-ast" exported="" />
|
||||||
<orderEntry type="module" module-name="js.frontend" exported="" />
|
<orderEntry type="module" module-name="js.frontend" exported="" />
|
||||||
<orderEntry type="module" module-name="js.inliner" exported="" />
|
<orderEntry type="module" module-name="js.inliner" exported="" />
|
||||||
|
<orderEntry type="module" module-name="js.parser" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
@@ -191,8 +191,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
if (shouldBeInlined(expression, context) &&
|
if (shouldBeInlined(expression, context) &&
|
||||||
BindingContextUtilPackage.isUsedAsExpression(expression, context.bindingContext())) {
|
BindingContextUtilPackage.isUsedAsExpression(expression, context.bindingContext())) {
|
||||||
TemporaryVariable temporaryVariable = context.declareTemporary(null);
|
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();
|
return temporaryVariable.reference();
|
||||||
} else {
|
} else {
|
||||||
return CallExpressionTranslator.translate(expression, null, context).source(expression);
|
return CallExpressionTranslator.translate(expression, null, context).source(expression);
|
||||||
|
|||||||
+81
-9
@@ -16,32 +16,51 @@
|
|||||||
|
|
||||||
package org.jetbrains.k2js.translate.reference;
|
package org.jetbrains.k2js.translate.reference;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage;
|
import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import com.google.dart.compiler.common.SourceInfoImpl;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import com.google.gwt.dev.js.JsParser;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import com.google.gwt.dev.js.JsParserException;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
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.callUtil.CallUtilPackage;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||||
import org.jetbrains.jet.lang.types.lang.InlineStrategy;
|
import org.jetbrains.jet.lang.types.lang.InlineStrategy;
|
||||||
import org.jetbrains.jet.lang.types.lang.InlineUtil;
|
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.callTranslator.CallTranslator;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
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 {
|
public final class CallExpressionTranslator extends AbstractCallExpressionTranslator {
|
||||||
|
|
||||||
@NotNull
|
@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,
|
@NotNull JetCallExpression expression,
|
||||||
@Nullable JsExpression receiver,
|
@Nullable JsExpression receiver,
|
||||||
@NotNull TranslationContext context
|
@NotNull TranslationContext context
|
||||||
) {
|
) {
|
||||||
|
if (matchesJsCode(expression, context)) {
|
||||||
|
return (new CallExpressionTranslator(expression, receiver, context)).translateJsCode();
|
||||||
|
}
|
||||||
|
|
||||||
JsExpression callExpression = (new CallExpressionTranslator(expression, receiver, context)).translate();
|
JsExpression callExpression = (new CallExpressionTranslator(expression, receiver, context)).translate();
|
||||||
|
|
||||||
if (shouldBeInlined(expression, context)
|
if (shouldBeInlined(expression, context)
|
||||||
@@ -80,6 +99,16 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
|||||||
return false;
|
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(
|
private CallExpressionTranslator(
|
||||||
@NotNull JetCallExpression expression,
|
@NotNull JetCallExpression expression,
|
||||||
@Nullable JsExpression receiver,
|
@Nullable JsExpression receiver,
|
||||||
@@ -92,4 +121,47 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
|||||||
private JsExpression translate() {
|
private JsExpression translate() {
|
||||||
return CallTranslator.INSTANCE$.translate(context(), resolvedCall, receiver);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-6
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.k2js.translate.reference;
|
package org.jetbrains.k2js.translate.reference;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
@@ -52,15 +53,17 @@ public final class QualifiedExpressionTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsExpression translateQualifiedExpression(@NotNull JetQualifiedExpression expression,
|
public static JsNode translateQualifiedExpression(
|
||||||
@NotNull TranslationContext context) {
|
@NotNull JetQualifiedExpression expression,
|
||||||
|
@NotNull TranslationContext context
|
||||||
|
) {
|
||||||
JsExpression receiver = translateReceiver(expression, context);
|
JsExpression receiver = translateReceiver(expression, context);
|
||||||
JetExpression selector = getSelector(expression);
|
JetExpression selector = getSelector(expression);
|
||||||
return dispatchToCorrectTranslator(receiver, selector, context);
|
return dispatchToCorrectTranslator(receiver, selector, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JsExpression dispatchToCorrectTranslator(
|
private static JsNode dispatchToCorrectTranslator(
|
||||||
@Nullable JsExpression receiver,
|
@Nullable JsExpression receiver,
|
||||||
@NotNull JetExpression selector,
|
@NotNull JetExpression selector,
|
||||||
@NotNull TranslationContext context
|
@NotNull TranslationContext context
|
||||||
@@ -73,8 +76,12 @@ public final class QualifiedExpressionTranslator {
|
|||||||
if (shouldBeInlined((JetCallExpression) selector, context) &&
|
if (shouldBeInlined((JetCallExpression) selector, context) &&
|
||||||
BindingContextUtilPackage.isUsedAsExpression(selector, context.bindingContext())) {
|
BindingContextUtilPackage.isUsedAsExpression(selector, context.bindingContext())) {
|
||||||
TemporaryVariable temporaryVariable = context.declareTemporary(null);
|
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();
|
return temporaryVariable.reference();
|
||||||
} else {
|
} else {
|
||||||
return invokeCallExpressionTranslator(receiver, selector, context);
|
return invokeCallExpressionTranslator(receiver, selector, context);
|
||||||
@@ -88,7 +95,7 @@ public final class QualifiedExpressionTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JsExpression invokeCallExpressionTranslator(
|
private static JsNode invokeCallExpressionTranslator(
|
||||||
@Nullable JsExpression receiver,
|
@Nullable JsExpression receiver,
|
||||||
@NotNull JetExpression selector,
|
@NotNull JetExpression selector,
|
||||||
@NotNull TranslationContext context
|
@NotNull TranslationContext context
|
||||||
|
|||||||
Reference in New Issue
Block a user