Refactor Algebra call building

This commit is contained in:
Iaroslav 2020-06-27 20:04:22 +07:00
parent 27605aee82
commit efcfb44253
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
2 changed files with 40 additions and 40 deletions

View File

@ -1,10 +1,8 @@
package scientifik.kmath.asm package scientifik.kmath.asm
import org.objectweb.asm.Type
import scientifik.kmath.asm.internal.AsmBuilder import scientifik.kmath.asm.internal.AsmBuilder
import scientifik.kmath.asm.internal.buildExpectationStack import scientifik.kmath.asm.internal.buildAlgebraOperationCall
import scientifik.kmath.asm.internal.buildName import scientifik.kmath.asm.internal.buildName
import scientifik.kmath.asm.internal.tryInvokeSpecific
import scientifik.kmath.ast.MST import scientifik.kmath.ast.MST
import scientifik.kmath.ast.MstExpression import scientifik.kmath.ast.MstExpression
import scientifik.kmath.expressions.Expression import scientifik.kmath.expressions.Expression
@ -29,44 +27,21 @@ fun <T : Any> MST.compileWith(type: KClass<T>, algebra: Algebra<T>): Expression<
loadTConstant(constant) loadTConstant(constant)
} }
is MST.Unary -> { is MST.Unary -> buildAlgebraOperationCall(
loadAlgebra() context = algebra,
if (!buildExpectationStack(algebra, node.operation, 1)) loadStringConstant(node.operation) name = node.operation,
visit(node.value) fallbackMethodName = "unaryOperation",
arity = 1
) { visit(node.value) }
if (!tryInvokeSpecific(algebra, node.operation, 1)) invokeAlgebraOperation( is MST.Binary -> buildAlgebraOperationCall(
owner = AsmBuilder.ALGEBRA_TYPE.internalName, context = algebra,
method = "unaryOperation", name = node.operation,
fallbackMethodName = "binaryOperation",
descriptor = Type.getMethodDescriptor( arity = 2
AsmBuilder.OBJECT_TYPE, ) {
AsmBuilder.STRING_TYPE,
AsmBuilder.OBJECT_TYPE
),
expectedArity = 1
)
}
is MST.Binary -> {
loadAlgebra()
if (!buildExpectationStack(algebra, node.operation, 2)) loadStringConstant(node.operation)
visit(node.left) visit(node.left)
visit(node.right) visit(node.right)
if (!tryInvokeSpecific(algebra, node.operation, 2)) invokeAlgebraOperation(
owner = AsmBuilder.ALGEBRA_TYPE.internalName,
method = "binaryOperation",
descriptor = Type.getMethodDescriptor(
AsmBuilder.OBJECT_TYPE,
AsmBuilder.STRING_TYPE,
AsmBuilder.OBJECT_TYPE,
AsmBuilder.OBJECT_TYPE
),
expectedArity = 2
)
} }
} }
} }

View File

@ -21,7 +21,7 @@ private val methodNameAdapters: Map<Pair<String, Int>, String> by lazy {
* *
* @return `true` if contains, else `false`. * @return `true` if contains, else `false`.
*/ */
internal fun <T> AsmBuilder<T>.buildExpectationStack(context: Algebra<T>, name: String, arity: Int): Boolean { private fun <T> AsmBuilder<T>.buildExpectationStack(context: Algebra<T>, name: String, arity: Int): Boolean {
val theName = methodNameAdapters[name to arity] ?: name val theName = methodNameAdapters[name to arity] ?: name
val hasSpecific = context.javaClass.methods.find { it.name == theName && it.parameters.size == arity } != null val hasSpecific = context.javaClass.methods.find { it.name == theName && it.parameters.size == arity } != null
val t = if (primitiveMode && hasSpecific) primitiveMask else tType val t = if (primitiveMode && hasSpecific) primitiveMask else tType
@ -35,7 +35,7 @@ internal fun <T> AsmBuilder<T>.buildExpectationStack(context: Algebra<T>, name:
* *
* @return `true` if contains, else `false`. * @return `true` if contains, else `false`.
*/ */
internal fun <T> AsmBuilder<T>.tryInvokeSpecific(context: Algebra<T>, name: String, arity: Int): Boolean { private fun <T> AsmBuilder<T>.tryInvokeSpecific(context: Algebra<T>, name: String, arity: Int): Boolean {
val theName = methodNameAdapters[name to arity] ?: name val theName = methodNameAdapters[name to arity] ?: name
context.javaClass.methods.find { context.javaClass.methods.find {
@ -59,3 +59,28 @@ internal fun <T> AsmBuilder<T>.tryInvokeSpecific(context: Algebra<T>, name: Stri
return true return true
} }
internal fun <T> AsmBuilder<T>.buildAlgebraOperationCall(
context: Algebra<T>,
name: String,
fallbackMethodName: String,
arity: Int,
parameters: AsmBuilder<T>.() -> Unit
) {
loadAlgebra()
if (!buildExpectationStack(context, name, arity)) loadStringConstant(name)
parameters()
if (!tryInvokeSpecific(context, name, arity)) invokeAlgebraOperation(
owner = AsmBuilder.ALGEBRA_TYPE.internalName,
method = fallbackMethodName,
descriptor = Type.getMethodDescriptor(
AsmBuilder.OBJECT_TYPE,
AsmBuilder.STRING_TYPE,
*Array(arity) { AsmBuilder.OBJECT_TYPE }
),
expectedArity = arity
)
}