From 437f426a2498403f85352c8c463d36cefaf78812 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Mon, 9 Mar 2020 03:30:16 +0900 Subject: [PATCH 01/14] =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=94=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E7=94=A8=E3=81=AEmap=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/core/BucketMap.kt | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/main/kotlin/com/mapk/core/BucketMap.kt diff --git a/src/main/kotlin/com/mapk/core/BucketMap.kt b/src/main/kotlin/com/mapk/core/BucketMap.kt new file mode 100644 index 0000000..42ae3e3 --- /dev/null +++ b/src/main/kotlin/com/mapk/core/BucketMap.kt @@ -0,0 +1,76 @@ +package com.mapk.core + +import kotlin.reflect.KParameter + +class BucketMap private constructor( + capacity: Int, + private val initializeMask: List, + private val completionValue: Int +) : MutableMap { + private val keyArray: Array = Array(capacity) { null } + private val valueArray: Array = Array(capacity) { null } + + private var count: Int = 0 + private var initializationStatus: Int = 0 + + val isInitialized: Boolean get() = initializationStatus == completionValue + + class MutableEntry internal constructor( + override val key: KParameter, + override var value: Any? + ) : MutableMap.MutableEntry { + override fun setValue(newValue: Any?): Any? { + throw UnsupportedOperationException() + } + } + + override val size: Int get() = count + + override fun containsKey(key: KParameter): Boolean { + // NOTE: もしかしたらステータスを見た方が速いかも + return keyArray[key.index] != null + } + + override fun containsValue(value: Any?): Boolean { + throw UnsupportedOperationException() + } + + override fun get(key: KParameter): Any? = valueArray[key.index] + + override fun isEmpty(): Boolean = count == 0 + + override val entries: MutableSet> + get() = keyArray.mapNotNull { it?.let { MutableEntry(it, valueArray[it.index]) } }.toMutableSet() + override val keys: MutableSet + get() = keyArray.filterNotNull().toMutableSet() + override val values: MutableCollection + get() = if (isInitialized) values.toMutableList() + else throw UnsupportedOperationException("Must be full initialize.") + + override fun clear() { + throw UnsupportedOperationException() + } + + override fun put(key: KParameter, value: Any?) { + val index = key.index + val temp = initializationStatus or initializeMask[index] + + // 先に入ったものを優先するため、初期化済みなら何もしない + if (initializationStatus == temp) return + + count += 1 + initializationStatus = temp + keyArray[index] = key + valueArray[index] = value + + return + } + + override fun putAll(from: Map) { + throw UnsupportedOperationException() + } + + override fun remove(key: KParameter): Any? { + throw UnsupportedOperationException() + } +} From 66f93a06359c1926c40c39d60842dba8da8157b5 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Mon, 9 Mar 2020 03:32:12 +0900 Subject: [PATCH 02/14] =?UTF-8?q?=E7=BD=AE=E3=81=8D=E6=8F=9B=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/mapk/core/ArgumentBucket.kt | 92 ++++++++++++------- src/main/kotlin/com/mapk/core/BucketMap.kt | 76 --------------- 2 files changed, 60 insertions(+), 108 deletions(-) delete mode 100644 src/main/kotlin/com/mapk/core/BucketMap.kt diff --git a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt index a08c25a..3aeca42 100644 --- a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt +++ b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt @@ -2,47 +2,75 @@ package com.mapk.core import kotlin.reflect.KParameter -internal class BucketGenerator( - private val bucket: Array, - private val instancePair: Pair?, - private val initializationStatus: Int, - private val initializeMask: List -) { - private val completionValue: Int = initializeMask.reduce { l, r -> l or r } - private val bucketSize = bucket.size - - fun generate(): ArgumentBucket { - val tempMap = HashMap(bucketSize, 1.0f) - instancePair?.run { tempMap[this.first] = this.second } - - return ArgumentBucket( - bucket.copyOf(), - tempMap, - initializationStatus, - initializeMask, - completionValue - ) - } -} - -class ArgumentBucket internal constructor( - internal val bucket: Array, - internal val bucketMap: MutableMap, - private var initializationStatus: Int, +class ArgumentBucket private constructor( + capacity: Int, private val initializeMask: List, private val completionValue: Int -) { +) : MutableMap { + private val keyArray: Array = Array(capacity) { null } + private val valueArray: Array = Array(capacity) { null } + + private var count: Int = 0 + private var initializationStatus: Int = 0 + val isInitialized: Boolean get() = initializationStatus == completionValue - fun setArgument(kParameter: KParameter, argument: Any?) { - val index = kParameter.index + class MutableEntry internal constructor( + override val key: KParameter, + override var value: Any? + ) : MutableMap.MutableEntry { + override fun setValue(newValue: Any?): Any? { + throw UnsupportedOperationException() + } + } + + override val size: Int get() = count + + override fun containsKey(key: KParameter): Boolean { + // NOTE: もしかしたらステータスを見た方が速いかも + return keyArray[key.index] != null + } + + override fun containsValue(value: Any?): Boolean { + throw UnsupportedOperationException() + } + + override fun get(key: KParameter): Any? = valueArray[key.index] + + override fun isEmpty(): Boolean = count == 0 + + override val entries: MutableSet> + get() = keyArray.mapNotNull { it?.let { MutableEntry(it, valueArray[it.index]) } }.toMutableSet() + override val keys: MutableSet + get() = keyArray.filterNotNull().toMutableSet() + override val values: MutableCollection + get() = if (isInitialized) values.toMutableList() + else throw UnsupportedOperationException("Must be full initialize.") + + override fun clear() { + throw UnsupportedOperationException() + } + + override fun put(key: KParameter, value: Any?) { + val index = key.index val temp = initializationStatus or initializeMask[index] // 先に入ったものを優先するため、初期化済みなら何もしない if (initializationStatus == temp) return - bucketMap[kParameter] = argument - bucket[index] = argument + count += 1 initializationStatus = temp + keyArray[index] = key + valueArray[index] = value + + return + } + + override fun putAll(from: Map) { + throw UnsupportedOperationException() + } + + override fun remove(key: KParameter): Any? { + throw UnsupportedOperationException() } } diff --git a/src/main/kotlin/com/mapk/core/BucketMap.kt b/src/main/kotlin/com/mapk/core/BucketMap.kt deleted file mode 100644 index 42ae3e3..0000000 --- a/src/main/kotlin/com/mapk/core/BucketMap.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.mapk.core - -import kotlin.reflect.KParameter - -class BucketMap private constructor( - capacity: Int, - private val initializeMask: List, - private val completionValue: Int -) : MutableMap { - private val keyArray: Array = Array(capacity) { null } - private val valueArray: Array = Array(capacity) { null } - - private var count: Int = 0 - private var initializationStatus: Int = 0 - - val isInitialized: Boolean get() = initializationStatus == completionValue - - class MutableEntry internal constructor( - override val key: KParameter, - override var value: Any? - ) : MutableMap.MutableEntry { - override fun setValue(newValue: Any?): Any? { - throw UnsupportedOperationException() - } - } - - override val size: Int get() = count - - override fun containsKey(key: KParameter): Boolean { - // NOTE: もしかしたらステータスを見た方が速いかも - return keyArray[key.index] != null - } - - override fun containsValue(value: Any?): Boolean { - throw UnsupportedOperationException() - } - - override fun get(key: KParameter): Any? = valueArray[key.index] - - override fun isEmpty(): Boolean = count == 0 - - override val entries: MutableSet> - get() = keyArray.mapNotNull { it?.let { MutableEntry(it, valueArray[it.index]) } }.toMutableSet() - override val keys: MutableSet - get() = keyArray.filterNotNull().toMutableSet() - override val values: MutableCollection - get() = if (isInitialized) values.toMutableList() - else throw UnsupportedOperationException("Must be full initialize.") - - override fun clear() { - throw UnsupportedOperationException() - } - - override fun put(key: KParameter, value: Any?) { - val index = key.index - val temp = initializationStatus or initializeMask[index] - - // 先に入ったものを優先するため、初期化済みなら何もしない - if (initializationStatus == temp) return - - count += 1 - initializationStatus = temp - keyArray[index] = key - valueArray[index] = value - - return - } - - override fun putAll(from: Map) { - throw UnsupportedOperationException() - } - - override fun remove(key: KParameter): Any? { - throw UnsupportedOperationException() - } -} From 2528314db8560651219254734be00ad3e0f150ce Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Mon, 9 Mar 2020 03:54:25 +0900 Subject: [PATCH 03/14] =?UTF-8?q?=E3=83=90=E3=82=B1=E3=83=84=E3=82=B8?= =?UTF-8?q?=E3=82=A7=E3=83=8D=E3=83=AC=E3=83=BC=E3=82=BF=E3=81=BE=E3=81=A7?= =?UTF-8?q?=E7=A7=BB=E6=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/mapk/core/ArgumentBucket.kt | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt index 3aeca42..91badcc 100644 --- a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt +++ b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt @@ -2,8 +2,31 @@ package com.mapk.core import kotlin.reflect.KParameter -class ArgumentBucket private constructor( - capacity: Int, +internal class BucketGenerator(capacity: Int, instancePair: Pair?) { + private val initializationStatus: Int = if (instancePair == null) 0 else 1 + private val initializeMask: List = generateSequence(1) { it.shl(1) }.take(capacity).toList() + private val completionValue: Int = initializeMask.reduce { l, r -> l or r } + + private val keyArray: Array = Array(capacity) { null } + private val valueArray: Array = Array(capacity) { null } + + init { + if (instancePair != null) { + keyArray[0] = instancePair.first + valueArray[0] = instancePair.second + } + } + + fun generate(): ArgumentBucket = ArgumentBucket( + keyArray.copyOf(), + valueArray.copyOf(), + initializationStatus, + initializeMask, + completionValue + ) +} + +class ArgumentBucket internal constructor( private val initializeMask: List, private val completionValue: Int ) : MutableMap { From a18e00e9de9af8ec69bcda5747f7b86d7a96df27 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Mon, 9 Mar 2020 03:55:06 +0900 Subject: [PATCH 04/14] =?UTF-8?q?=E7=B4=B0=E3=81=8B=E3=81=AA=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/core/ArgumentBucket.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt index 91badcc..75b0dad 100644 --- a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt +++ b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt @@ -27,14 +27,13 @@ internal class BucketGenerator(capacity: Int, instancePair: Pair, + internal val valueArray: Array, + private var initializationStatus: Int, private val initializeMask: List, private val completionValue: Int ) : MutableMap { - private val keyArray: Array = Array(capacity) { null } - private val valueArray: Array = Array(capacity) { null } - private var count: Int = 0 - private var initializationStatus: Int = 0 val isInitialized: Boolean get() = initializationStatus == completionValue @@ -59,6 +58,9 @@ class ArgumentBucket internal constructor( } override fun get(key: KParameter): Any? = valueArray[key.index] + fun getByIndex(key: Int): Any? = + if (initializationStatus and initializeMask[key] != 0) valueArray[key] + else throw IllegalStateException("This argument is not initialized.") override fun isEmpty(): Boolean = count == 0 @@ -67,8 +69,7 @@ class ArgumentBucket internal constructor( override val keys: MutableSet get() = keyArray.filterNotNull().toMutableSet() override val values: MutableCollection - get() = if (isInitialized) values.toMutableList() - else throw UnsupportedOperationException("Must be full initialize.") + get() = throw UnsupportedOperationException() override fun clear() { throw UnsupportedOperationException() From f792390d97f8ac15a77d2630ebd7f97feb250d56 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Mon, 9 Mar 2020 03:55:26 +0900 Subject: [PATCH 05/14] =?UTF-8?q?=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=97?= =?UTF-8?q?=E3=81=AE=E3=81=9F=E3=82=81=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/core/KFunctionForCall.kt | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/com/mapk/core/KFunctionForCall.kt b/src/main/kotlin/com/mapk/core/KFunctionForCall.kt index 47cc3e4..33b8a3f 100644 --- a/src/main/kotlin/com/mapk/core/KFunctionForCall.kt +++ b/src/main/kotlin/com/mapk/core/KFunctionForCall.kt @@ -15,23 +15,16 @@ class KFunctionForCall(private val function: KFunction, instance: Any? = n // この関数には確実にアクセスするためアクセシビリティ書き換え function.isAccessible = true - // 初期化処理の共通化のため先に初期化 - val tempArray = Array(parameters.size) { null } - val maskList = generateSequence(1) { it.shl(1) }.take(parameters.size).toList() - generator = if (instance != null) { - tempArray[0] = instance - - // 引数の1番目は初期化済みということでinitializationStatusは1スタート - BucketGenerator(tempArray, parameters.first { it.kind == KParameter.Kind.INSTANCE } to instance, 1, maskList) + BucketGenerator(parameters.size, parameters.first { it.kind == KParameter.Kind.INSTANCE } to instance) } else { - BucketGenerator(tempArray, null, 0, maskList) + BucketGenerator(parameters.size, null) } } fun getArgumentBucket(): ArgumentBucket = generator.generate() fun call(argumentBucket: ArgumentBucket): T = - if (argumentBucket.isInitialized) function.call(*argumentBucket.bucket) - else function.callBy(argumentBucket.bucketMap) + if (argumentBucket.isInitialized) function.call(*argumentBucket.valueArray) + else function.callBy(argumentBucket) } From 2843ad71517ade02112adabf4dab4603b0759d65 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Mon, 9 Mar 2020 03:55:55 +0900 Subject: [PATCH 06/14] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=81=AE?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt | 12 ++++++------ .../kotlin/com/mapk/core/KFunctionForCallTest.kt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt b/src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt index 02561c2..f11e8d1 100644 --- a/src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt +++ b/src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt @@ -36,7 +36,7 @@ class ArgumentBucketTest { @DisplayName("初期化後") fun isInitialized() { ::sampleFunction.parameters.forEach { - argumentBucket.setArgument(it, object {}) + argumentBucket[it] = object {} } assertTrue(argumentBucket.isInitialized) @@ -50,8 +50,8 @@ class ArgumentBucketTest { @DisplayName("正常に追加した場合") fun setNewArgument() { val parameter = ::sampleFunction.parameters.first { it.index == 0 } - argumentBucket.setArgument(parameter, "argument") - assertEquals("argument", argumentBucket.bucket[0]) + argumentBucket[parameter] = "argument" + assertEquals("argument", argumentBucket.getByIndex(0)) } @Test @@ -59,9 +59,9 @@ class ArgumentBucketTest { fun setArgumentTwice() { val parameter = ::sampleFunction.parameters.first { it.index == 0 } - argumentBucket.setArgument(parameter, "first") - argumentBucket.setArgument(parameter, "second") - assertEquals("first", argumentBucket.bucket[0]) + argumentBucket[parameter] = "first" + argumentBucket[parameter] = "second" + assertEquals("first", argumentBucket.getByIndex(0)) } } } diff --git a/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt b/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt index 99d2691..e3450d5 100644 --- a/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt +++ b/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt @@ -48,7 +48,7 @@ class KFunctionForCallTest { val kFunctionForCall = KFunctionForCall(function, Companion) val bucket = kFunctionForCall.getArgumentBucket() - kFunctionForCall.parameters.forEach { bucket.setArgument(it, it.index) } + kFunctionForCall.parameters.forEach { bucket[it] = it.index } val result = kFunctionForCall.call(bucket) assertEquals("12", result) } @@ -61,7 +61,7 @@ class KFunctionForCallTest { val kFunctionForCall = KFunctionForCall(::func) val argumentBucket = kFunctionForCall.getArgumentBucket() - ::func.parameters.forEach { if (!it.isOptional) argumentBucket.setArgument(it, it.name) } + ::func.parameters.forEach { if (!it.isOptional) argumentBucket[it] = it.name } val result = kFunctionForCall.call(argumentBucket) assertEquals("key" to "default", result) From 1bbfd6de66e86645db6f932f553a5faa46d8f0a4 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Mon, 9 Mar 2020 10:26:18 +0900 Subject: [PATCH 07/14] =?UTF-8?q?count=E3=81=AE=E3=83=90=E3=82=B0=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/core/ArgumentBucket.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt index 75b0dad..cc8a9f1 100644 --- a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt +++ b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt @@ -33,7 +33,8 @@ class ArgumentBucket internal constructor( private val initializeMask: List, private val completionValue: Int ) : MutableMap { - private var count: Int = 0 + // インスタンス有りなら1、そうでなければ0スタート + private var count: Int = initializationStatus val isInitialized: Boolean get() = initializationStatus == completionValue From 880e16e567f54489a6fda9bcd0886606a1967941 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Wed, 11 Mar 2020 07:04:45 +0900 Subject: [PATCH 08/14] =?UTF-8?q?MutableMap=E3=81=A7=E3=81=82=E3=82=8B?= =?UTF-8?q?=E5=BF=85=E8=A6=81=E6=80=A7=E3=81=8C=E8=96=84=E3=81=8B=E3=81=A3?= =?UTF-8?q?=E3=81=9F=E3=81=AE=E3=81=A7=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/mapk/core/ArgumentBucket.kt | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt index cc8a9f1..79fc6e9 100644 --- a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt +++ b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt @@ -32,7 +32,7 @@ class ArgumentBucket internal constructor( private var initializationStatus: Int, private val initializeMask: List, private val completionValue: Int -) : MutableMap { +) : Map { // インスタンス有りなら1、そうでなければ0スタート private var count: Int = initializationStatus @@ -41,11 +41,7 @@ class ArgumentBucket internal constructor( class MutableEntry internal constructor( override val key: KParameter, override var value: Any? - ) : MutableMap.MutableEntry { - override fun setValue(newValue: Any?): Any? { - throw UnsupportedOperationException() - } - } + ) : Map.Entry override val size: Int get() = count @@ -65,18 +61,14 @@ class ArgumentBucket internal constructor( override fun isEmpty(): Boolean = count == 0 - override val entries: MutableSet> - get() = keyArray.mapNotNull { it?.let { MutableEntry(it, valueArray[it.index]) } }.toMutableSet() + override val entries: Set> + get() = keyArray.mapNotNull { it?.let { MutableEntry(it, valueArray[it.index]) } }.toSet() override val keys: MutableSet get() = keyArray.filterNotNull().toMutableSet() override val values: MutableCollection get() = throw UnsupportedOperationException() - override fun clear() { - throw UnsupportedOperationException() - } - - override fun put(key: KParameter, value: Any?) { + fun put(key: KParameter, value: Any?) { val index = key.index val temp = initializationStatus or initializeMask[index] @@ -90,12 +82,4 @@ class ArgumentBucket internal constructor( return } - - override fun putAll(from: Map) { - throw UnsupportedOperationException() - } - - override fun remove(key: KParameter): Any? { - throw UnsupportedOperationException() - } } From db08df145b8544bf4f74c1a7e84d043c68ec23b2 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Wed, 11 Mar 2020 07:08:38 +0900 Subject: [PATCH 09/14] =?UTF-8?q?=E5=8D=98=E7=B4=94=E3=81=AAput=E5=87=A6?= =?UTF-8?q?=E7=90=86=E3=81=A7=E3=81=AF=E3=81=AA=E3=81=84=E3=81=9F=E3=82=81?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/core/ArgumentBucket.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt index 79fc6e9..d5cf518 100644 --- a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt +++ b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt @@ -68,7 +68,7 @@ class ArgumentBucket internal constructor( override val values: MutableCollection get() = throw UnsupportedOperationException() - fun put(key: KParameter, value: Any?) { + fun putIfAbsent(key: KParameter, value: Any?) { val index = key.index val temp = initializationStatus or initializeMask[index] From b162493995ee0697125ac48da69ab794615ae367 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Wed, 11 Mar 2020 07:10:36 +0900 Subject: [PATCH 10/14] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt | 8 ++++---- src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt b/src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt index f11e8d1..c9f820c 100644 --- a/src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt +++ b/src/test/kotlin/com/mapk/core/ArgumentBucketTest.kt @@ -36,7 +36,7 @@ class ArgumentBucketTest { @DisplayName("初期化後") fun isInitialized() { ::sampleFunction.parameters.forEach { - argumentBucket[it] = object {} + argumentBucket.putIfAbsent(it, object {}) } assertTrue(argumentBucket.isInitialized) @@ -50,7 +50,7 @@ class ArgumentBucketTest { @DisplayName("正常に追加した場合") fun setNewArgument() { val parameter = ::sampleFunction.parameters.first { it.index == 0 } - argumentBucket[parameter] = "argument" + argumentBucket.putIfAbsent(parameter, "argument") assertEquals("argument", argumentBucket.getByIndex(0)) } @@ -59,8 +59,8 @@ class ArgumentBucketTest { fun setArgumentTwice() { val parameter = ::sampleFunction.parameters.first { it.index == 0 } - argumentBucket[parameter] = "first" - argumentBucket[parameter] = "second" + argumentBucket.putIfAbsent(parameter, "first") + argumentBucket.putIfAbsent(parameter, "second") assertEquals("first", argumentBucket.getByIndex(0)) } } diff --git a/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt b/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt index e3450d5..db6031b 100644 --- a/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt +++ b/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt @@ -48,7 +48,7 @@ class KFunctionForCallTest { val kFunctionForCall = KFunctionForCall(function, Companion) val bucket = kFunctionForCall.getArgumentBucket() - kFunctionForCall.parameters.forEach { bucket[it] = it.index } + kFunctionForCall.parameters.forEach { bucket.putIfAbsent(it, it.index) } val result = kFunctionForCall.call(bucket) assertEquals("12", result) } @@ -61,7 +61,7 @@ class KFunctionForCallTest { val kFunctionForCall = KFunctionForCall(::func) val argumentBucket = kFunctionForCall.getArgumentBucket() - ::func.parameters.forEach { if (!it.isOptional) argumentBucket[it] = it.name } + ::func.parameters.forEach { if (!it.isOptional) argumentBucket.putIfAbsent(it, it.name) } val result = kFunctionForCall.call(argumentBucket) assertEquals("key" to "default", result) From 7dfef796e606719ae03e4d0912cf55fde6460d6d Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Wed, 11 Mar 2020 07:35:54 +0900 Subject: [PATCH 11/14] =?UTF-8?q?=E9=80=9F=E5=BA=A6=E3=81=AE=E8=A6=B3?= =?UTF-8?q?=E7=82=B9=E3=81=A7=E7=96=91=E5=95=8F=E3=81=8C=E6=9C=89=E3=81=A3?= =?UTF-8?q?=E3=81=9F=E3=81=9F=E3=82=81Java=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/mapk/core/BucketGenerator.java | 50 +++++++++++++++++++ .../kotlin/com/mapk/core/ArgumentBucket.kt | 24 --------- 2 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/mapk/core/BucketGenerator.java diff --git a/src/main/java/com/mapk/core/BucketGenerator.java b/src/main/java/com/mapk/core/BucketGenerator.java new file mode 100644 index 0000000..b74eda7 --- /dev/null +++ b/src/main/java/com/mapk/core/BucketGenerator.java @@ -0,0 +1,50 @@ +package com.mapk.core; + +import kotlin.Pair; +import kotlin.reflect.KParameter; + +import java.util.ArrayList; +import java.util.List; + +class BucketGenerator { + private final int initializationStatus; + private final List initializeMask; + private final int completionValue; + + private final KParameter[] keyArray; + private final Object[] valueArray; + + BucketGenerator(int capacity, Pair instancePair) { + keyArray = new KParameter[capacity]; + valueArray = new Object[capacity]; + + if (instancePair != null) { + initializationStatus = 1; + + keyArray[0] = instancePair.getFirst(); + valueArray[0] = instancePair.getSecond(); + } else { + initializationStatus = 0; + } + + initializeMask = new ArrayList<>(capacity); + int completionValue = 0; + + for (int i = 0, mask = 1; i < capacity; i++, mask <<= 1) { + initializeMask.add(i, mask); + completionValue |= mask; + } + + this.completionValue = completionValue; + } + + ArgumentBucket generate() { + return new ArgumentBucket( + keyArray.clone(), + valueArray.clone(), + initializationStatus, + initializeMask, + completionValue + ); + } +} diff --git a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt index d5cf518..d148cff 100644 --- a/src/main/kotlin/com/mapk/core/ArgumentBucket.kt +++ b/src/main/kotlin/com/mapk/core/ArgumentBucket.kt @@ -2,30 +2,6 @@ package com.mapk.core import kotlin.reflect.KParameter -internal class BucketGenerator(capacity: Int, instancePair: Pair?) { - private val initializationStatus: Int = if (instancePair == null) 0 else 1 - private val initializeMask: List = generateSequence(1) { it.shl(1) }.take(capacity).toList() - private val completionValue: Int = initializeMask.reduce { l, r -> l or r } - - private val keyArray: Array = Array(capacity) { null } - private val valueArray: Array = Array(capacity) { null } - - init { - if (instancePair != null) { - keyArray[0] = instancePair.first - valueArray[0] = instancePair.second - } - } - - fun generate(): ArgumentBucket = ArgumentBucket( - keyArray.copyOf(), - valueArray.copyOf(), - initializationStatus, - initializeMask, - completionValue - ) -} - class ArgumentBucket internal constructor( private val keyArray: Array, internal val valueArray: Array, From c5906d80645905c9119ee4350472bf3cd52a983c Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Wed, 11 Mar 2020 07:48:09 +0900 Subject: [PATCH 12/14] =?UTF-8?q?mockk=E3=82=92=E5=B0=8E=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index bf4d22d..0c252ad 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,6 +34,8 @@ dependencies { testImplementation(group = "org.junit.jupiter", name = "junit-jupiter", version = "5.6.0") { exclude(group = "org.junit.vintage", module = "junit-vintage-engine") } + // https://mvnrepository.com/artifact/io.mockk/mockk + testImplementation("io.mockk:mockk:1.9.3") } tasks { From 0459eaeebce0f8f0929d32a0abe5b674d77bc6d2 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Wed, 11 Mar 2020 07:53:58 +0900 Subject: [PATCH 13/14] =?UTF-8?q?=E5=85=A8=E5=88=9D=E6=9C=9F=E5=8C=96/?= =?UTF-8?q?=E3=83=87=E3=83=95=E3=82=A9=E3=83=AB=E3=83=88=E5=80=A4=E3=81=A7?= =?UTF-8?q?=E9=81=A9=E5=88=87=E3=81=AA=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=97?= =?UTF-8?q?=E3=81=8C=E7=99=BA=E7=94=9F=E3=81=97=E3=81=A6=E3=81=84=E3=82=8B?= =?UTF-8?q?=E3=81=8B=E3=82=92=E7=A2=BA=E8=AA=8D=E3=81=99=E3=82=8B=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/mapk/core/KFunctionForCallTest.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt b/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt index db6031b..493d665 100644 --- a/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt +++ b/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt @@ -1,5 +1,7 @@ package com.mapk.core +import io.mockk.spyk +import io.mockk.verify import kotlin.reflect.full.functions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.DisplayName @@ -42,8 +44,9 @@ class KFunctionForCallTest { @Test @DisplayName("コンパニオンオブジェクトから取得した場合") fun fromCompanionObject() { - val function = - Companion::class.functions.find { it.name == (KFunctionForCallTest)::declaredOnCompanionObject.name }!! + val function = Companion::class.functions + .first { it.name == (KFunctionForCallTest)::declaredOnCompanionObject.name } + .let { spyk(it) } val kFunctionForCall = KFunctionForCall(function, Companion) @@ -51,6 +54,7 @@ class KFunctionForCallTest { kFunctionForCall.parameters.forEach { bucket.putIfAbsent(it, it.index) } val result = kFunctionForCall.call(bucket) assertEquals("12", result) + verify(exactly = 1) { function.call(*anyVararg()) } } private fun func(key: String, value: String = "default"): Pair = key to value @@ -58,13 +62,15 @@ class KFunctionForCallTest { @Test @DisplayName("デフォルト値を用いる場合") fun useDefaultValue() { - val kFunctionForCall = KFunctionForCall(::func) + val func = spyk(::func) + val kFunctionForCall = KFunctionForCall(func) val argumentBucket = kFunctionForCall.getArgumentBucket() - ::func.parameters.forEach { if (!it.isOptional) argumentBucket.putIfAbsent(it, it.name) } + func.parameters.forEach { if (!it.isOptional) argumentBucket.putIfAbsent(it, it.name) } val result = kFunctionForCall.call(argumentBucket) assertEquals("key" to "default", result) + verify(exactly = 1) { func.callBy(any()) } } } From f7406bef9c996c2097b5edd2247dfe28622156e3 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Wed, 11 Mar 2020 08:36:53 +0900 Subject: [PATCH 14/14] =?UTF-8?q?=E8=A4=87=E6=95=B0=E5=9B=9E=E5=91=BC?= =?UTF-8?q?=E3=82=93=E3=81=A7=E3=82=82=E3=81=8A=E3=81=8B=E3=81=97=E3=81=AA?= =?UTF-8?q?=E5=80=A4=E3=82=92=E8=BF=94=E3=81=95=E3=81=AA=E3=81=84=E3=81=8B?= =?UTF-8?q?=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mapk/core/KFunctionForCallTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt b/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt index 493d665..daf33ea 100644 --- a/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt +++ b/src/test/kotlin/com/mapk/core/KFunctionForCallTest.kt @@ -72,6 +72,28 @@ class KFunctionForCallTest { assertEquals("key" to "default", result) verify(exactly = 1) { func.callBy(any()) } } + + @Test + @DisplayName("同一関数を違うソースから複数回呼んだ場合") + fun multipleCall() { + val function = Companion::class.functions + .first { it.name == (KFunctionForCallTest)::declaredOnCompanionObject.name } + .let { spyk(it) } + + val kFunctionForCall = KFunctionForCall(function, Companion) + + val bucket1 = kFunctionForCall.getArgumentBucket() + kFunctionForCall.parameters.forEach { bucket1.putIfAbsent(it, it.index) } + val result1 = kFunctionForCall.call(bucket1) + assertEquals("12", result1) + + val bucket2 = kFunctionForCall.getArgumentBucket() + kFunctionForCall.parameters.forEach { bucket2.putIfAbsent(it, it.index + 1) } + val result2 = kFunctionForCall.call(bucket2) + assertEquals("23", result2) + + verify(exactly = 2) { function.call(*anyVararg()) } + } } companion object {