Dev #127
@ -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
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user