diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 08a6876344b..cb3ff5bf545 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -69,8 +69,6 @@ import java.util.*; import static org.jetbrains.jet.codegen.AsmUtil.*; import static org.jetbrains.jet.codegen.JvmCodegenUtil.*; -import static org.jetbrains.jet.codegen.FunctionTypesUtil.functionTypeToImpl; -import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionImplType; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull; @@ -1312,7 +1310,11 @@ public class ExpressionCodegen extends JetVisitor implem FunctionDescriptor descriptor = bindingContext.get(FUNCTION, declaration); assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText(); - Type closureSuperClass = samInterfaceClass == null ? getFunctionImplType(descriptor) : OBJECT_TYPE; + String functionImplClassPrefix = descriptor.getReceiverParameter() != null ? "ExtensionFunctionImpl" : "FunctionImpl"; + Type closureSuperClass = + samInterfaceClass == null ? + Type.getObjectType("kotlin/" + functionImplClassPrefix + descriptor.getValueParameters().size()) : + OBJECT_TYPE; ClosureCodegen closureCodegen = new ClosureCodegen(state, declaration, descriptor, samInterfaceClass, closureSuperClass, context, kind, this, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), parentCodegen); @@ -2416,7 +2418,7 @@ public class ExpressionCodegen extends JetVisitor implem JetType kFunctionType = bindingContext.get(EXPRESSION_TYPE, expression); assert kFunctionType != null : "Callable reference is not type checked: " + expression.getText(); - ClassDescriptor kFunctionImpl = functionTypeToImpl(kFunctionType); + ClassDescriptor kFunctionImpl = state.getFunctionTypesUtil().kFunctionTypeToImpl(kFunctionType); assert kFunctionImpl != null : "Impl type is not found for the function type: " + kFunctionType; Type closureSuperClass = typeMapper.mapType(kFunctionImpl); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionTypesUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionTypesUtil.java index 9de9936a726..1ec97232563 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionTypesUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionTypesUtil.java @@ -19,10 +19,10 @@ package org.jetbrains.jet.codegen; import com.google.common.collect.ImmutableMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor; +import org.jetbrains.jet.lang.reflect.ReflectionTypes; import org.jetbrains.jet.lang.resolve.ImportPath; import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -37,24 +37,22 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import static org.jetbrains.jet.lang.types.lang.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME; - public class FunctionTypesUtil { - private static final List FUNCTIONS; - private static final List EXTENSION_FUNCTIONS; - private static final List K_FUNCTIONS; - private static final List K_MEMBER_FUNCTIONS; - private static final List K_EXTENSION_FUNCTIONS; + private final List functions; + private final List extensionFunctions; + private final List kFunctions; + private final List kMemberFunctions; + private final List kExtensionFunctions; - private static final ImmutableMap FUNCTION_TO_IMPL; + private final ImmutableMap kFunctionToImpl; - static { + public FunctionTypesUtil(@NotNull ReflectionTypes reflectionTypes) { int n = KotlinBuiltIns.FUNCTION_TRAIT_COUNT; - FUNCTIONS = new ArrayList(n); - EXTENSION_FUNCTIONS = new ArrayList(n); - K_FUNCTIONS = new ArrayList(n); - K_MEMBER_FUNCTIONS = new ArrayList(n); - K_EXTENSION_FUNCTIONS = new ArrayList(n); + functions = new ArrayList(n); + extensionFunctions = new ArrayList(n); + kFunctions = new ArrayList(n); + kMemberFunctions = new ArrayList(n); + kExtensionFunctions = new ArrayList(n); ModuleDescriptor module = new ModuleDescriptorImpl(Name.special(""), Collections.emptyList(), JavaToKotlinClassMap.getInstance()); @@ -63,34 +61,31 @@ public class FunctionTypesUtil { KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); for (int i = 0; i < n; i++) { - createFunctionImpl(FUNCTIONS, kotlin, "FunctionImpl" + i, builtIns.getFunction(i)); - createFunctionImpl(EXTENSION_FUNCTIONS, kotlin, "ExtensionFunctionImpl" + i, builtIns.getExtensionFunction(i)); - createFunctionImpl(K_FUNCTIONS, reflect, "KFunctionImpl" + i, builtIns.getKFunction(i)); - createFunctionImpl(K_MEMBER_FUNCTIONS, reflect, "KMemberFunctionImpl" + i, builtIns.getKMemberFunction(i)); - createFunctionImpl(K_EXTENSION_FUNCTIONS, reflect, "KExtensionFunctionImpl" + i, builtIns.getKExtensionFunction(i)); + createFunctionImpl(functions, kotlin, "FunctionImpl" + i, builtIns.getFunction(i)); + createFunctionImpl(extensionFunctions, kotlin, "ExtensionFunctionImpl" + i, builtIns.getExtensionFunction(i)); + createFunctionImpl(kFunctions, reflect, "KFunctionImpl" + i, reflectionTypes.getKFunction(i)); + createFunctionImpl(kMemberFunctions, reflect, "KMemberFunctionImpl" + i, reflectionTypes.getKMemberFunction(i)); + createFunctionImpl(kExtensionFunctions, reflect, "KExtensionFunctionImpl" + i, reflectionTypes.getKExtensionFunction(i)); } ImmutableMap.Builder builder = ImmutableMap.builder(); for (int i = 0; i < n; i++) { - builder.put(builtIns.getKFunction(i), K_FUNCTIONS.get(i)); - builder.put(builtIns.getKMemberFunction(i), K_MEMBER_FUNCTIONS.get(i)); - builder.put(builtIns.getKExtensionFunction(i), K_EXTENSION_FUNCTIONS.get(i)); + builder.put(reflectionTypes.getKFunction(i), kFunctions.get(i)); + builder.put(reflectionTypes.getKMemberFunction(i), kMemberFunctions.get(i)); + builder.put(reflectionTypes.getKExtensionFunction(i), kExtensionFunctions.get(i)); } - FUNCTION_TO_IMPL = builder.build(); - } - - private FunctionTypesUtil() { + kFunctionToImpl = builder.build(); } @Nullable - public static ClassDescriptor functionTypeToImpl(@NotNull JetType functionType) { + public ClassDescriptor kFunctionTypeToImpl(@NotNull JetType functionType) { //noinspection SuspiciousMethodCalls - return FUNCTION_TO_IMPL.get(functionType.getConstructor().getDeclarationDescriptor()); + return kFunctionToImpl.get(functionType.getConstructor().getDeclarationDescriptor()); } @NotNull - public static JetType getSuperTypeForClosure(@NotNull FunctionDescriptor descriptor, boolean kFunction) { + public JetType getSuperTypeForClosure(@NotNull FunctionDescriptor descriptor, boolean kFunction) { int arity = descriptor.getValueParameters().size(); ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter(); @@ -108,26 +103,27 @@ public class FunctionTypesUtil { typeArguments.add(new TypeProjectionImpl(parameter.getType())); } + //noinspection ConstantConditions typeArguments.add(new TypeProjectionImpl(descriptor.getReturnType())); ClassDescriptor classDescriptor; if (kFunction) { if (expectedThisObject != null) { - classDescriptor = K_MEMBER_FUNCTIONS.get(arity); + classDescriptor = kMemberFunctions.get(arity); } else if (receiverParameter != null) { - classDescriptor = K_EXTENSION_FUNCTIONS.get(arity); + classDescriptor = kExtensionFunctions.get(arity); } else { - classDescriptor = K_FUNCTIONS.get(arity); + classDescriptor = kFunctions.get(arity); } } else { if (receiverParameter != null) { - classDescriptor = EXTENSION_FUNCTIONS.get(arity); + classDescriptor = extensionFunctions.get(arity); } else { - classDescriptor = FUNCTIONS.get(arity); + classDescriptor = functions.get(arity); } } @@ -160,26 +156,4 @@ public class FunctionTypesUtil { result.add(functionImpl); } - - @NotNull - public static Type getFunctionTraitClassName(@NotNull FunctionDescriptor descriptor) { - int paramCount = descriptor.getValueParameters().size(); - if (descriptor.getReceiverParameter() != null) { - return Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/ExtensionFunction" + paramCount); - } - else { - return Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/Function" + paramCount); - } - } - - @NotNull - public static Type getFunctionImplType(@NotNull FunctionDescriptor descriptor) { - int paramCount = descriptor.getValueParameters().size(); - if (descriptor.getReceiverParameter() != null) { - return Type.getObjectType("kotlin/ExtensionFunctionImpl" + paramCount); - } - else { - return Type.getObjectType("kotlin/FunctionImpl" + paramCount); - } - } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java index 3c77408509c..39ef24b366d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java @@ -22,6 +22,7 @@ import com.intellij.psi.tree.TokenSet; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.FunctionTypesUtil; import org.jetbrains.jet.codegen.SamCodegenUtil; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.lang.descriptors.*; @@ -47,7 +48,6 @@ import org.jetbrains.org.objectweb.asm.Type; import java.util.*; import static org.jetbrains.jet.codegen.JvmCodegenUtil.peekFromStack; -import static org.jetbrains.jet.codegen.FunctionTypesUtil.getSuperTypeForClosure; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lexer.JetTokens.*; @@ -87,13 +87,14 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { private final BindingTrace bindingTrace; private final BindingContext bindingContext; - private final GenerationState.GenerateClassFilter filter; + private final FunctionTypesUtil functionTypesUtil; - public CodegenAnnotatingVisitor(BindingTrace bindingTrace, GenerationState.GenerateClassFilter filter) { - this.bindingTrace = bindingTrace; - this.filter = filter; - this.bindingContext = bindingTrace.getBindingContext(); + public CodegenAnnotatingVisitor(@NotNull GenerationState state) { + this.bindingTrace = state.getBindingTrace(); + this.bindingContext = state.getBindingContext(); + this.filter = state.getGenerateDeclaredClassFilter(); + this.functionTypesUtil = state.getFunctionTypesUtil(); } @NotNull @@ -269,7 +270,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { if (functionDescriptor == null) return; String name = inventAnonymousClassName(expression); - JetType superType = getSuperTypeForClosure(functionDescriptor, false); + JetType superType = functionTypesUtil.getSuperTypeForClosure(functionDescriptor, false); ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, superType); recordClosure(functionLiteral, classDescriptor, name); @@ -317,7 +318,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { ResolvedCall referencedFunction = bindingContext.get(RESOLVED_CALL, expression.getCallableReference()); if (referencedFunction == null) return; - JetType superType = getSuperTypeForClosure((FunctionDescriptor) referencedFunction.getResultingDescriptor(), true); + JetType superType = + functionTypesUtil.getSuperTypeForClosure((FunctionDescriptor) referencedFunction.getResultingDescriptor(), true); String name = inventAnonymousClassName(expression); ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, superType); @@ -371,7 +373,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { } else { String name = inventAnonymousClassName(function); - JetType superType = getSuperTypeForClosure(functionDescriptor, false); + JetType superType = functionTypesUtil.getSuperTypeForClosure(functionDescriptor, false); ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, superType); recordClosure(function, classDescriptor, name); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java index e904962492a..d0a0f1461bd 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java @@ -66,7 +66,7 @@ public class CodegenBinding { } public static void initTrace(@NotNull GenerationState state) { - CodegenAnnotatingVisitor visitor = new CodegenAnnotatingVisitor(state.getBindingTrace(), state.getGenerateDeclaredClassFilter()); + CodegenAnnotatingVisitor visitor = new CodegenAnnotatingVisitor(state); for (JetFile file : allFilesInPackages(state.getBindingContext(), state.getFiles())) { file.accept(visitor); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java index cc8278d1d22..6261798b28c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java @@ -19,19 +19,20 @@ package org.jetbrains.jet.codegen.state; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.codegen.ClassBuilderFactory; -import org.jetbrains.jet.codegen.ClassBuilderMode; -import org.jetbrains.jet.codegen.ClassFileFactory; -import org.jetbrains.jet.codegen.SamWrapperClasses; +import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.inline.InlineCodegenUtil; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; +import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor; import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.reflect.ReflectionTypes; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.util.List; @@ -97,6 +98,8 @@ public class GenerationState { @Nullable private List earlierScriptsForReplInterpreter; + private final FunctionTypesUtil functionTypesUtil; + public GenerationState( @NotNull Project project, @NotNull ClassBuilderFactory builderFactory, @@ -124,7 +127,7 @@ public class GenerationState { this.classBuilderMode = builderFactory.getClassBuilderMode(); this.inlineEnabled = inlineEnabled; - bindingTrace = new DelegatingBindingTrace(bindingContext, "trace in GenerationState"); + this.bindingTrace = new DelegatingBindingTrace(bindingContext, "trace in GenerationState"); this.bindingContext = bindingTrace.getBindingContext(); this.typeMapper = new JetTypeMapper(bindingTrace, classBuilderMode); @@ -136,6 +139,24 @@ public class GenerationState { this.generateNotNullAssertions = generateNotNullAssertions; this.generateNotNullParamAssertions = generateNotNullParamAssertions; this.generateClassFilter = generateClassFilter; + + ReflectionTypes reflectionTypes = new ReflectionTypes(getAnyModule()); + this.functionTypesUtil = new FunctionTypesUtil(reflectionTypes); + } + + @NotNull + private ModuleDescriptor getAnyModule() { + // TODO: this shouldn't be happening once we have modules in the compiler (there simply will be a ModuleDescriptor instance here) + + if (files.isEmpty()) { + // This is a hackish workaround for this code not to fail when invoked for an empty file list. Technically it doesn't matter + // which module we return here: if we're not compiling anything, we should never reach a point where we need this module + return KotlinBuiltIns.getInstance().getBuiltInsModule(); + } + + PackageFragmentDescriptor descriptor = bindingContext.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, files.get(0)); + assert descriptor != null : "File is not under any module: " + files.get(0); + return descriptor.getContainingDeclaration(); } @NotNull @@ -200,6 +221,11 @@ public class GenerationState { return generateClassFilter; } + @NotNull + public FunctionTypesUtil getFunctionTypesUtil() { + return functionTypesUtil; + } + public boolean isInlineEnabled() { return inlineEnabled; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/reflect/ReflectionTypes.kt b/compiler/frontend/src/org/jetbrains/jet/lang/reflect/ReflectionTypes.kt new file mode 100644 index 00000000000..29896a904b4 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/reflect/ReflectionTypes.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.reflect + +import kotlin.properties.Delegates +import org.jetbrains.jet.lang.descriptors.* +import org.jetbrains.jet.lang.resolve.name.FqName +import org.jetbrains.jet.lang.resolve.name.Name +import org.jetbrains.jet.lang.resolve.scopes.JetScope +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns + +public class ReflectionTypes(private val module: ModuleDescriptor) { + // TODO: use module instead of built-ins + public fun getKFunction(n: Int): ClassDescriptor = KotlinBuiltIns.getInstance().getKFunction(n) + public fun getKExtensionFunction(n: Int): ClassDescriptor = KotlinBuiltIns.getInstance().getKExtensionFunction(n) + public fun getKMemberFunction(n: Int): ClassDescriptor = KotlinBuiltIns.getInstance().getKMemberFunction(n) +}