Make primitive array factory functions constructors

This commit is contained in:
Alexander Udalov
2016-01-20 23:14:06 +03:00
parent 4b03adaa57
commit 9e8b6571f4
7 changed files with 203 additions and 223 deletions
@@ -25,8 +25,8 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.Stack;
import kotlin.Pair;
import kotlin.collections.CollectionsKt;
import kotlin.Unit;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -56,6 +56,8 @@ import org.jetbrains.kotlin.jvm.bindingContextSlices.BindingContextSlicesKt;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
@@ -78,11 +80,13 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
import org.jetbrains.kotlin.serialization.deserialization.FindClassInModuleKt;
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeProjection;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.utils.StringsKt;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
@@ -97,8 +101,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.*;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isObject;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
@@ -3345,7 +3348,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Type type = expressionType(expression);
if (type.getSort() == Type.ARRAY) {
//noinspection ConstantConditions
return generateNewArray(expression, bindingContext.getType(expression));
return generateNewArray(expression, bindingContext.getType(expression), resolvedCall);
}
return generateConstructorCall(resolvedCall, type);
@@ -3391,20 +3394,54 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
});
}
public StackValue generateNewArray(@NotNull KtCallExpression expression, @NotNull final KotlinType arrayType) {
assert expression.getValueArguments().size() == 1 : "Size argument expected";
public StackValue generateNewArray(
@NotNull KtCallExpression expression, @NotNull final KotlinType arrayType, @NotNull ResolvedCall<?> resolvedCall
) {
List<KtValueArgument> args = expression.getValueArguments();
assert args.size() == 1 || args.size() == 2 : "Unknown constructor called: " + args.size() + " arguments";
final KtExpression sizeExpression = expression.getValueArguments().get(0).getArgumentExpression();
Type type = typeMapper.mapType(arrayType);
if (args.size() == 1) {
final KtExpression sizeExpression = args.get(0).getArgumentExpression();
return StackValue.operation(typeMapper.mapType(arrayType), new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
gen(sizeExpression, Type.INT_TYPE);
newArrayInstruction(arrayType);
return Unit.INSTANCE;
}
});
}
return StackValue.operation(type, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
gen(sizeExpression, Type.INT_TYPE);
newArrayInstruction(arrayType);
return Unit.INSTANCE;
final ConstructorDescriptor constructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
final ClassDescriptor intrinsicConstructors =
FindClassInModuleKt.findClassAcrossModuleDependencies(
getContainingModule(context.getContextDescriptor()),
ClassId.topLevel(new FqName("kotlin.jvm.internal.IntrinsicArrayConstructors"))
);
// TODO: do not depend on a class from the runtime
assert intrinsicConstructors != null : "Class IntrinsicArrayConstructors is not found";
ResolvedCall<?> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) {
private final CallableDescriptor descriptor;
{
Collection<FunctionDescriptor> functions = intrinsicConstructors.getUnsubstitutedMemberScope().getContributedFunctions(
constructor.getContainingDeclaration().getName(), NoLookupLocation.FROM_BACKEND);
assert functions.size() == 1
: "IntrinsicArrayConstructors does not have a single constructor for " +
constructor.getContainingDeclaration().getName() + ":\n" + StringsKt.join(functions, "\n");
descriptor = CollectionsKt.single(functions);
}
});
@NotNull
@Override
public CallableDescriptor getResultingDescriptor() {
return descriptor;
}
};
return invokeFunction(fakeResolvedCall, StackValue.singleton(intrinsicConstructors, typeMapper));
}
public void newArrayInstruction(@NotNull KotlinType arrayType) {
@@ -110,7 +110,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
if (referencedFunction instanceof ConstructorDescriptor) {
if (returnType.getSort() == Type.ARRAY) {
//noinspection ConstantConditions
result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType());
result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType(), fakeResolvedCall);
}
else {
result = codegen.generateConstructorCall(fakeResolvedCall, returnType);
+48
View File
@@ -23,6 +23,12 @@ package kotlin
* @constructor Creates a new array of the specified [size], with all elements initialized to zero.
*/
public class ByteArray(size: Int) : Cloneable {
/**
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
public constructor(size: Int, init: (Int) -> Byte)
/** Returns the array element at the given [index]. This method can be called using the index operator. */
public operator fun get(index: Int): Byte
/** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */
@@ -42,6 +48,12 @@ public class ByteArray(size: Int) : Cloneable {
* @constructor Creates a new array of the specified [size], with all elements initialized to zero.
*/
public class CharArray(size: Int) : Cloneable {
/**
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
public constructor(size: Int, init: (Int) -> Char)
/** Returns the array element at the given [index]. This method can be called using the index operator. */
public operator fun get(index: Int): Char
/** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */
@@ -61,6 +73,12 @@ public class CharArray(size: Int) : Cloneable {
* @constructor Creates a new array of the specified [size], with all elements initialized to zero.
*/
public class ShortArray(size: Int) : Cloneable {
/**
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
public constructor(size: Int, init: (Int) -> Short)
/** Returns the array element at the given [index]. This method can be called using the index operator. */
public operator fun get(index: Int): Short
/** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */
@@ -80,6 +98,12 @@ public class ShortArray(size: Int) : Cloneable {
* @constructor Creates a new array of the specified [size], with all elements initialized to zero.
*/
public class IntArray(size: Int) : Cloneable {
/**
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
public constructor(size: Int, init: (Int) -> Int)
/** Returns the array element at the given [index]. This method can be called using the index operator. */
public operator fun get(index: Int): Int
/** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */
@@ -99,6 +123,12 @@ public class IntArray(size: Int) : Cloneable {
* @constructor Creates a new array of the specified [size], with all elements initialized to zero.
*/
public class LongArray(size: Int) : Cloneable {
/**
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
public constructor(size: Int, init: (Int) -> Long)
/** Returns the array element at the given [index]. This method can be called using the index operator. */
public operator fun get(index: Int): Long
/** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */
@@ -118,6 +148,12 @@ public class LongArray(size: Int) : Cloneable {
* @constructor Creates a new array of the specified [size], with all elements initialized to zero.
*/
public class FloatArray(size: Int) : Cloneable {
/**
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
public constructor(size: Int, init: (Int) -> Float)
/** Returns the array element at the given [index]. This method can be called using the index operator. */
public operator fun get(index: Int): Float
/** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */
@@ -137,6 +173,12 @@ public class FloatArray(size: Int) : Cloneable {
* @constructor Creates a new array of the specified [size], with all elements initialized to zero.
*/
public class DoubleArray(size: Int) : Cloneable {
/**
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
public constructor(size: Int, init: (Int) -> Double)
/** Returns the array element at the given [index]. This method can be called using the index operator. */
public operator fun get(index: Int): Double
/** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */
@@ -156,6 +198,12 @@ public class DoubleArray(size: Int) : Cloneable {
* @constructor Creates a new array of the specified [size], with all elements initialized to false.
*/
public class BooleanArray(size: Int) : Cloneable {
/**
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
public constructor(size: Int, init: (Int) -> Boolean)
/** Returns the array element at the given [index]. This method can be called using the index operator. */
public operator fun get(index: Int): Boolean
/** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */
@@ -29,102 +29,6 @@ public inline fun <reified @PureReifiable T> Array(size: Int, init: (Int) -> T):
return result as Array<T>
}
/**
* Returns an array of [Double] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun DoubleArray(size: Int, init: (Int) -> Double): DoubleArray {
val result = DoubleArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Float] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun FloatArray(size: Int, init: (Int) -> Float): FloatArray {
val result = FloatArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Long] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun LongArray(size: Int, init: (Int) -> Long): LongArray {
val result = LongArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Int] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun IntArray(size: Int, init: (Int) -> Int): IntArray {
val result = IntArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Char] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun CharArray(size: Int, init: (Int) -> Char): CharArray {
val result = CharArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Short] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun ShortArray(size: Int, init: (Int) -> Short): ShortArray {
val result = ShortArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Byte] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun ByteArray(size: Int, init: (Int) -> Byte): ByteArray {
val result = ByteArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Boolean] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun BooleanArray(size: Int, init: (Int) -> Boolean): BooleanArray {
val result = BooleanArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an empty array of the specified type [T].
*/
@@ -0,0 +1,84 @@
/*
* Copyright 2010-2016 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 kotlin.jvm.internal
@Suppress("unused")
object IntrinsicArrayConstructors {
private inline fun DoubleArray(size: Int, init: (Int) -> Double): DoubleArray {
val result = DoubleArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun FloatArray(size: Int, init: (Int) -> Float): FloatArray {
val result = FloatArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun LongArray(size: Int, init: (Int) -> Long): LongArray {
val result = LongArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun IntArray(size: Int, init: (Int) -> Int): IntArray {
val result = IntArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun CharArray(size: Int, init: (Int) -> Char): CharArray {
val result = CharArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun ShortArray(size: Int, init: (Int) -> Short): ShortArray {
val result = ShortArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun ByteArray(size: Int, init: (Int) -> Byte): ByteArray {
val result = ByteArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun BooleanArray(size: Int, init: (Int) -> Boolean): BooleanArray {
val result = BooleanArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
}
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.generators.builtins.arrays
import org.jetbrains.kotlin.generators.builtins.PrimitiveType
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.*
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.BuiltInsSourceGenerator
import java.io.PrintWriter
class GenerateArrays(out: PrintWriter) : BuiltInsSourceGenerator(out) {
@@ -27,12 +27,18 @@ class GenerateArrays(out: PrintWriter) : BuiltInsSourceGenerator(out) {
for (kind in PrimitiveType.values()) {
val typeLower = kind.name.toLowerCase()
val s = kind.capitalized
val defaultValue = when(kind) { PrimitiveType.BOOLEAN -> "false"; else -> "zero" }
val defaultValue = if (kind == PrimitiveType.BOOLEAN) "false" else "zero"
out.println("/**")
out.println(" * An array of ${typeLower}s. When targeting the JVM, instances of this class are represented as `${typeLower}[]`.")
out.println(" * @constructor Creates a new array of the specified [size], with all elements initialized to ${defaultValue}.")
out.println(" * An array of ${typeLower}s. When targeting the JVM, instances of this class are represented as `$typeLower[]`.")
out.println(" * @constructor Creates a new array of the specified [size], with all elements initialized to $defaultValue.")
out.println(" */")
out.println("public class ${s}Array(size: Int) : Cloneable {")
out.println(" /**")
out.println(" * Creates a new array of the specified [size], where each element is calculated by calling the specified")
out.println(" * [init] function. The [init] function returns an array element given its index.")
out.println(" */")
out.println(" public constructor(size: Int, init: (Int) -> $s)")
out.println()
out.println(" /** Returns the array element at the given [index]. This method can be called using the index operator. */")
out.println(" public operator fun get(index: Int): $s")
out.println(" /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */")
+8 -107
View File
@@ -14,133 +14,34 @@ public inline fun <reified T> Array(size: Int, init: (Int) -> T): Array<T> {
return result as Array<T>
}
/**
* Returns an array of [Double] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun DoubleArray(size: Int, init: (Int) -> Double): DoubleArray {
val result = DoubleArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Float] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun FloatArray(size: Int, init: (Int) -> Float): FloatArray {
val result = FloatArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Long] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun LongArray(size: Int, init: (Int) -> Long): LongArray {
val result = LongArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Int] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun IntArray(size: Int, init: (Int) -> Int): IntArray {
val result = IntArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Char] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun CharArray(size: Int, init: (Int) -> Char): CharArray {
val result = CharArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Short] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun ShortArray(size: Int, init: (Int) -> Short): ShortArray {
val result = ShortArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Byte] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun ByteArray(size: Int, init: (Int) -> Byte): ByteArray {
val result = ByteArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an array of [Boolean] numbers with the specified [size],
* where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun BooleanArray(size: Int, init: (Int) -> Boolean): BooleanArray {
val result = BooleanArray(size)
for (i in 0..size - 1)
result[i] = init(i)
return result
}
/**
* Returns an empty array of the specified type [T].
*/
public inline fun <reified T> emptyArray(): Array<T> = arrayOfNulls<T>(0) as Array<T>
@library
public fun <T> arrayOf(vararg elements: T): Array<T> = noImpl
// "constructors" for primitive types array
@library
public fun doubleArrayOf(vararg elements: Double): DoubleArray = noImpl
@library
public fun doubleArrayOf(vararg elements: Double): DoubleArray = noImpl
public fun floatArrayOf(vararg elements: Float): FloatArray = noImpl
@library
public fun floatArrayOf(vararg elements: Float): FloatArray = noImpl
public fun longArrayOf(vararg elements: Long): LongArray = noImpl
@library
public fun longArrayOf(vararg elements: Long): LongArray = noImpl
public fun intArrayOf(vararg elements: Int): IntArray = noImpl
@library
public fun intArrayOf(vararg elements: Int): IntArray = noImpl
public fun charArrayOf(vararg elements: Char): CharArray = noImpl
@library
public fun charArrayOf(vararg elements: Char): CharArray = noImpl
public fun shortArrayOf(vararg elements: Short): ShortArray = noImpl
@library
public fun shortArrayOf(vararg elements: Short): ShortArray = noImpl
@library
public fun byteArrayOf(vararg elements: Byte): ByteArray = noImpl
public fun byteArrayOf(vararg elements: Byte): ByteArray = noImpl
@library
public fun booleanArrayOf(vararg elements: Boolean): BooleanArray = noImpl