JS backend: added the support extension functions as expression.

This commit is contained in:
Zalim Bashorov
2014-02-26 14:55:00 +04:00
parent 396afb05cb
commit 14ed970dc3
3 changed files with 30 additions and 12 deletions
@@ -87,6 +87,9 @@ public class FunctionTest extends AbstractExpressionTest {
fooBoxTest(); fooBoxTest();
} }
public void testExpressionAsExtFunction() throws Exception {
checkFooBoxIsOk();
}
public void testVararg() throws Exception { public void testVararg() throws Exception {
checkFooBoxIsOk(); checkFooBoxIsOk();
@@ -22,22 +22,18 @@ import com.google.dart.compiler.backend.js.ast.JsInvocation
import java.util.Collections import java.util.Collections
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.k2js.translate.context.Namer import org.jetbrains.k2js.translate.context.Namer
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import org.jetbrains.jet.lang.descriptors.CallableDescriptor import org.jetbrains.jet.lang.descriptors.CallableDescriptor
import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind
import com.google.dart.compiler.backend.js.ast.JsNew import com.google.dart.compiler.backend.js.ast.JsNew
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor
import org.jetbrains.k2js.translate.utils.TranslationUtils
import org.jetbrains.k2js.translate.general.Translation import org.jetbrains.k2js.translate.general.Translation
import org.jetbrains.k2js.translate.utils.PsiUtils
import com.google.dart.compiler.backend.js.ast.JsLiteral import com.google.dart.compiler.backend.js.ast.JsLiteral
import com.google.dart.compiler.backend.js.ast.JsName import com.google.dart.compiler.backend.js.ast.JsName
import org.jetbrains.k2js.translate.context.TranslationContext import org.jetbrains.k2js.translate.context.TranslationContext
import org.jetbrains.k2js.translate.reference.CallArgumentTranslator import org.jetbrains.k2js.translate.reference.CallArgumentTranslator
public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpression>) : List<JsExpression> { public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpression>): List<JsExpression> {
if (arguments.isEmpty()) if (arguments.isEmpty())
return Collections.singletonList(receiver) return Collections.singletonList(receiver)
@@ -58,10 +54,10 @@ object DefaultFunctionCallCase : FunctionCallCase {
} }
fun buildDefaultCallWithThisObject(argumentsInfo: CallArgumentTranslator.ArgumentsInfo, fun buildDefaultCallWithThisObject(argumentsInfo: CallArgumentTranslator.ArgumentsInfo,
thisObject: JsExpression, thisObject: JsExpression,
functionName: JsName, functionName: JsName,
isNative: Boolean, isNative: Boolean,
hasSpreadOperator: Boolean): JsExpression { hasSpreadOperator: Boolean): JsExpression {
if (isNative && hasSpreadOperator) { if (isNative && hasSpreadOperator) {
return nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo, functionName) return nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo, functionName)
} }
@@ -113,7 +109,8 @@ object DefaultFunctionCallCase : FunctionCallCase {
return JsInvocation(functionRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments())) return JsInvocation(functionRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
} }
override fun FunctionCallInfo.bothReceivers(): JsExpression { // TODO: think about crazy case: spreadOperator + native override fun FunctionCallInfo.bothReceivers(): JsExpression {
// TODO: think about crazy case: spreadOperator + native
val functionRef = JsNameRef(functionName, thisObject!!) val functionRef = JsNameRef(functionName, thisObject!!)
return JsInvocation(functionRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments())) return JsInvocation(functionRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
} }
@@ -178,6 +175,15 @@ object ExpressionAsFunctionDescriptorIntrinsic : FunctionCallCase {
val funRef = Translation.translateAsExpression((callableDescriptor as ExpressionAsFunctionDescriptor).getExpression()!!, context) val funRef = Translation.translateAsExpression((callableDescriptor as ExpressionAsFunctionDescriptor).getExpression()!!, context)
return JsInvocation(funRef, argumentsInfo.getTranslateArguments()) return JsInvocation(funRef, argumentsInfo.getTranslateArguments())
} }
override fun FunctionCallInfo.receiverArgument(): JsExpression {
if (callableDescriptor !is ExpressionAsFunctionDescriptor) {
throw IllegalStateException("callableDescriptor must be ExpressionAsFunctionDescriptor $this")
}
val funRef = Translation.translateAsExpression((callableDescriptor as ExpressionAsFunctionDescriptor).getExpression()!!, context)
return JsInvocation(funRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
}
} }
object SuperCallCase : FunctionCallCase { object SuperCallCase : FunctionCallCase {
@@ -185,9 +191,10 @@ object SuperCallCase : FunctionCallCase {
return callInfo.isSuperInvocation() return callInfo.isSuperInvocation()
} }
override fun FunctionCallInfo.thisObject(): JsExpression { // TODO: spread operator override fun FunctionCallInfo.thisObject(): JsExpression {
// TODO: spread operator
val prototypeClass = JsNameRef(Namer.getPrototypeName(), thisObject!!) val prototypeClass = JsNameRef(Namer.getPrototypeName(), thisObject!!)
val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass)) val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass))
return JsInvocation(functionRef, addReceiverToArgs(JsLiteral.THIS, argumentsInfo.getTranslateArguments())) return JsInvocation(functionRef, addReceiverToArgs(JsLiteral.THIS, argumentsInfo.getTranslateArguments()))
} }
} }
@@ -0,0 +1,8 @@
package foo
fun box(): String {
val a = 23.{ Int.(a: Int) -> a * a + this }(3)
if (a != 32) return "a != 32, a = $a";
return "OK";
}