JS backend: Use new call translator in CallExpressionTranslator and move invoke intrinsic to FunctionCallCases
This commit is contained in:
-46
@@ -19,9 +19,7 @@ package org.jetbrains.k2js.translate.intrinsic.functions.factories;
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
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.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
|
||||
@@ -31,12 +29,9 @@ import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
||||
import org.jetbrains.k2js.translate.context.Namer;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
|
||||
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredicate;
|
||||
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
|
||||
import org.jetbrains.k2js.translate.reference.CallTranslator;
|
||||
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
|
||||
@@ -47,7 +42,6 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic.CallParametersAwareFunctionIntrinsic;
|
||||
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
|
||||
import static org.jetbrains.k2js.translate.utils.TranslationUtils.generateInvocationArguments;
|
||||
|
||||
public final class TopLevelFIF extends CompositeFIF {
|
||||
@NotNull
|
||||
@@ -139,46 +133,6 @@ public final class TopLevelFIF extends CompositeFIF {
|
||||
add(pattern("String|Boolean|Char|Number.equals"), EQUALS);
|
||||
add(pattern("jet", "arrayOfNulls"), new KotlinFunctionIntrinsic("nullArray"));
|
||||
add(pattern("jet", "iterator").receiverExists(), RETURN_RECEIVER_INTRINSIC);
|
||||
add(new DescriptorPredicate() {
|
||||
@Override
|
||||
public boolean apply(@NotNull FunctionDescriptor descriptor) {
|
||||
if (!descriptor.getName().asString().equals("invoke")) {
|
||||
return false;
|
||||
}
|
||||
int parameterCount = descriptor.getValueParameters().size();
|
||||
DeclarationDescriptor fun = descriptor.getContainingDeclaration();
|
||||
return fun == (descriptor.getReceiverParameter() == null
|
||||
? KotlinBuiltIns.getInstance().getFunction(parameterCount)
|
||||
: KotlinBuiltIns.getInstance().getExtensionFunction(parameterCount));
|
||||
}
|
||||
}, new CallParametersAwareFunctionIntrinsic() {
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression apply(
|
||||
@NotNull CallTranslator callTranslator,
|
||||
@NotNull List<JsExpression> arguments,
|
||||
@NotNull TranslationContext context
|
||||
) {
|
||||
JsExpression thisExpression = callTranslator.getCallParameters().getThisObject();
|
||||
JsExpression functionReference = callTranslator.getCallParameters().getFunctionReference();
|
||||
if (thisExpression == null) {
|
||||
return new JsInvocation(functionReference, arguments);
|
||||
}
|
||||
else if (callTranslator.getResolvedCall().getReceiverArgument().exists()) {
|
||||
return callTranslator.extensionFunctionCall(false);
|
||||
}
|
||||
else {
|
||||
CallableDescriptor descriptor = callTranslator.getResolvedCall().getCandidateDescriptor();
|
||||
if (descriptor.getName().asString().equals("invoke") &&
|
||||
functionReference instanceof JsNameRef &&
|
||||
((JsNameRef) functionReference).getIdent().startsWith("invoke")) {
|
||||
return callTranslator.explicitInvokeCall();
|
||||
}
|
||||
return new JsInvocation(Namer.getFunctionCallRef(functionReference), generateInvocationArguments(thisExpression, arguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
add(pattern("jet", "Map", "get").checkOverridden(), NATIVE_MAP_GET);
|
||||
add(pattern("js", "set").receiverExists(), NATIVE_MAP_SET);
|
||||
|
||||
+2
-1
@@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.reference;
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
@@ -31,7 +32,7 @@ public abstract class AbstractCallExpressionTranslator extends AbstractTranslato
|
||||
@NotNull
|
||||
protected final JetCallExpression expression;
|
||||
@NotNull
|
||||
protected final ResolvedCall<?> resolvedCall;
|
||||
protected final ResolvedCall<? extends FunctionDescriptor> resolvedCall;
|
||||
@Nullable
|
||||
protected final JsExpression receiver;
|
||||
@NotNull
|
||||
|
||||
+1
-88
@@ -17,23 +17,10 @@
|
||||
package org.jetbrains.k2js.translate.reference;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsName;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
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.util.ExpressionAsFunctionDescriptor;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.general.Translation;
|
||||
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
|
||||
import org.jetbrains.k2js.translate.utils.PsiUtils;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.getCallee;
|
||||
|
||||
public final class CallExpressionTranslator extends AbstractCallExpressionTranslator {
|
||||
|
||||
@@ -48,88 +35,14 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
||||
return (new CallExpressionTranslator(expression, receiver, callType, context)).translate();
|
||||
}
|
||||
|
||||
private final boolean isNativeFunctionCall;
|
||||
private CallArgumentTranslator.ArgumentsInfo argumentsInfo = null;
|
||||
private JsExpression translatedReceiver = null;
|
||||
private JsExpression translatedCallee = null;
|
||||
|
||||
private CallExpressionTranslator(@NotNull JetCallExpression expression,
|
||||
@Nullable JsExpression receiver,
|
||||
@NotNull CallType callType, @NotNull TranslationContext context) {
|
||||
super(expression, receiver, callType, context);
|
||||
this.isNativeFunctionCall = AnnotationsUtils.isNativeObject(resolvedCall.getCandidateDescriptor());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression translate() {
|
||||
prepareToBuildCall();
|
||||
|
||||
return CallBuilder.build(context())
|
||||
.receiver(translatedReceiver)
|
||||
.callee(translatedCallee)
|
||||
.args(argumentsInfo.getTranslateArguments())
|
||||
.resolvedCall(getResolvedCall())
|
||||
.type(callType)
|
||||
.translate();
|
||||
return ReferencePackage.buildCall(context(), resolvedCall, receiver);
|
||||
}
|
||||
|
||||
private void prepareToBuildCall() {
|
||||
argumentsInfo = CallArgumentTranslator.translate(resolvedCall, receiver, context());
|
||||
translatedReceiver = getReceiver();
|
||||
translatedCallee = getCalleeExpression();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ResolvedCall<?> getResolvedCall() {
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
return ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall();
|
||||
}
|
||||
return resolvedCall;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JsExpression getReceiver() {
|
||||
assert argumentsInfo != null : "the results of this function depends on the argumentsInfo";
|
||||
if (receiver == null) {
|
||||
return null;
|
||||
}
|
||||
if (argumentsInfo.getCachedReceiver() != null) {
|
||||
return argumentsInfo.getCachedReceiver().assignmentExpression();
|
||||
}
|
||||
return receiver;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JsExpression getCalleeExpression() {
|
||||
assert argumentsInfo != null : "the results of this function depends on the argumentsInfo";
|
||||
if (isNativeFunctionCall && argumentsInfo.isHasSpreadOperator()) {
|
||||
JsName functionName = context().getNameForDescriptor(resolvedCall.getCandidateDescriptor());
|
||||
return new JsNameRef("apply", functionName.makeRef());
|
||||
}
|
||||
CallableDescriptor candidateDescriptor = resolvedCall.getCandidateDescriptor();
|
||||
if (candidateDescriptor instanceof ExpressionAsFunctionDescriptor) {
|
||||
return translateExpressionAsFunction();
|
||||
}
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
return translateVariableForVariableAsFunctionResolvedCall();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
//TODO: looks hacky and should be modified soon
|
||||
private JsExpression translateVariableForVariableAsFunctionResolvedCall() {
|
||||
JetExpression callee = PsiUtils.getCallee(expression);
|
||||
if (callee instanceof JetSimpleNameExpression) {
|
||||
return ReferenceTranslator.getAccessTranslator((JetSimpleNameExpression) callee, receiver, context()).translateAsGet();
|
||||
}
|
||||
assert receiver != null;
|
||||
return Translation.translateAsExpression(callee, context());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression translateExpressionAsFunction() {
|
||||
return Translation.translateAsExpression(getCallee(expression), context());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -97,6 +97,28 @@ class DelegateFunctionIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(c
|
||||
}
|
||||
}
|
||||
|
||||
class InvokeIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) {
|
||||
class object {
|
||||
fun canApply(callInfo: FunctionCallInfo): Boolean {
|
||||
if (!callInfo.callableDescriptor.getName().asString().equals("invoke"))
|
||||
return false
|
||||
val parameterCount = callInfo.callableDescriptor.getValueParameters().size()
|
||||
val funDeclaration = callInfo.callableDescriptor.getContainingDeclaration()
|
||||
return funDeclaration == ((if (callInfo.callableDescriptor.getReceiverParameter() == null)
|
||||
KotlinBuiltIns.getInstance().getFunction(parameterCount)
|
||||
else
|
||||
KotlinBuiltIns.getInstance().getExtensionFunction(parameterCount)))
|
||||
}
|
||||
}
|
||||
|
||||
override fun FunctionCallInfo.thisObject(): JsExpression {
|
||||
return JsInvocation(thisObject, argumentsInfo.getTranslateArguments())
|
||||
}
|
||||
override fun FunctionCallInfo.bothReceivers(): JsExpression {
|
||||
return JsInvocation(thisObject, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
|
||||
}
|
||||
}
|
||||
|
||||
class ConstructorCallCase(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) {
|
||||
override fun FunctionCallInfo.noReceivers(): JsExpression {
|
||||
return JsNew(context.getQualifiedReference(callableDescriptor), argumentsInfo.getTranslateArguments())
|
||||
@@ -138,6 +160,7 @@ fun createFunctionCases(): CallCaseDispatcher<FunctionCallCase, FunctionCallInfo
|
||||
val caseDispatcher = CallCaseDispatcher<FunctionCallCase, FunctionCallInfo>()
|
||||
|
||||
caseDispatcher.addCase(::ExpressionAsFunctionDescriptorIntrinsic) {ExpressionAsFunctionDescriptorIntrinsic.canApply(it)}
|
||||
caseDispatcher.addCase(::InvokeIntrinsic) {InvokeIntrinsic.canApply(it)}
|
||||
|
||||
caseDispatcher.addCase { DelegateFunctionIntrinsic(it).intrinsic() }
|
||||
|
||||
|
||||
@@ -156,10 +156,13 @@ public final class BindingUtils {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ResolvedCall<?> getResolvedCallForCallExpression(@NotNull BindingContext context,
|
||||
public static ResolvedCall<? extends FunctionDescriptor> getResolvedCallForCallExpression(@NotNull BindingContext context,
|
||||
@NotNull JetCallExpression expression) {
|
||||
JetExpression calleeExpression = PsiUtils.getCallee(expression);
|
||||
return getResolvedCall(context, calleeExpression);
|
||||
ResolvedCall<?> resolvedCall = getResolvedCall(context, calleeExpression);
|
||||
assert resolvedCall.getResultingDescriptor() instanceof FunctionDescriptor
|
||||
: message(expression, "ResolvedCall for this expression must be ResolvedCall<? extends FunctionDescriptor>");
|
||||
return (ResolvedCall<? extends FunctionDescriptor>) resolvedCall;
|
||||
}
|
||||
|
||||
public static boolean isVariableReassignment(@NotNull BindingContext context, @NotNull JetExpression expression) {
|
||||
|
||||
Reference in New Issue
Block a user