Refactor ASM generation code #105
@ -1,52 +0,0 @@
|
|||||||
package scientifik.kmath.asm
|
|
||||||
|
|
||||||
import scientifik.kmath.asm.internal.AsmGenerator
|
|
||||||
import scientifik.kmath.ast.MST
|
|
||||||
import scientifik.kmath.ast.evaluate
|
|
||||||
import scientifik.kmath.expressions.Expression
|
|
||||||
import scientifik.kmath.operations.*
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal fun buildName(expression: AsmNode<*>, collision: Int = 0): String {
|
|
||||||
val name = "scientifik.kmath.expressions.generated.AsmCompiledExpression_${expression.hashCode()}_$collision"
|
|
||||||
|
|
||||||
try {
|
|
||||||
Class.forName(name)
|
|
||||||
} catch (ignored: ClassNotFoundException) {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildName(expression, collision + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal inline fun <reified T> AsmNode<T>.compile(algebra: Algebra<T>): Expression<T> =
|
|
||||||
AsmGenerator(T::class.java, algebra, buildName(this), this).getInstance()
|
|
||||||
|
|
||||||
inline fun <reified T, A : NumericAlgebra<T>, E : AsmExpressionAlgebra<T, A>> A.asm(
|
|
||||||
expressionAlgebra: E,
|
|
||||||
block: E.() -> AsmNode<T>
|
|
||||||
): Expression<T> = expressionAlgebra.block().compile(expressionAlgebra.algebra)
|
|
||||||
|
|
||||||
inline fun <reified T, A : NumericAlgebra<T>, E : AsmExpressionAlgebra<T, A>> A.asm(
|
|
||||||
expressionAlgebra: E,
|
|
||||||
ast: MST
|
|
||||||
): Expression<T> = asm(expressionAlgebra) { evaluate(ast) }
|
|
||||||
|
|
||||||
inline fun <reified T, A> A.asmSpace(block: AsmExpressionSpace<T, A>.() -> AsmNode<T>): Expression<T> where A : NumericAlgebra<T>, A : Space<T> =
|
|
||||||
AsmExpressionSpace(this).let { it.block().compile(it.algebra) }
|
|
||||||
|
|
||||||
inline fun <reified T, A> A.asmSpace(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Space<T> =
|
|
||||||
asmSpace { evaluate(ast) }
|
|
||||||
|
|
||||||
inline fun <reified T, A> A.asmRing(block: AsmExpressionRing<T, A>.() -> AsmNode<T>): Expression<T> where A : NumericAlgebra<T>, A : Ring<T> =
|
|
||||||
AsmExpressionRing(this).let { it.block().compile(it.algebra) }
|
|
||||||
|
|
||||||
inline fun <reified T, A> A.asmRing(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Ring<T> =
|
|
||||||
asmRing { evaluate(ast) }
|
|
||||||
|
|
||||||
inline fun <reified T, A> A.asmField(block: AsmExpressionField<T, A>.() -> AsmNode<T>): Expression<T> where A : NumericAlgebra<T>, A : Field<T> =
|
|
||||||
AsmExpressionField(this).let { it.block().compile(it.algebra) }
|
|
||||||
|
|
||||||
inline fun <reified T, A> A.asmField(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Field<T> =
|
|
||||||
asmRing { evaluate(ast) }
|
|
@ -1,6 +1,6 @@
|
|||||||
package scientifik.kmath.asm
|
package scientifik.kmath.asm
|
||||||
|
|
||||||
import scientifik.kmath.asm.internal.AsmGenerator
|
import scientifik.kmath.asm.internal.AsmBuilder
|
||||||
import scientifik.kmath.asm.internal.hasSpecific
|
import scientifik.kmath.asm.internal.hasSpecific
|
||||||
import scientifik.kmath.asm.internal.optimize
|
import scientifik.kmath.asm.internal.optimize
|
||||||
import scientifik.kmath.asm.internal.tryInvokeSpecific
|
import scientifik.kmath.asm.internal.tryInvokeSpecific
|
||||||
@ -9,11 +9,11 @@ import scientifik.kmath.expressions.ExpressionAlgebra
|
|||||||
import scientifik.kmath.operations.*
|
import scientifik.kmath.operations.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function declaration that could be compiled to [AsmGenerator].
|
* A function declaration that could be compiled to [AsmBuilder].
|
||||||
*
|
*
|
||||||
* @param T the type the stored function returns.
|
* @param T the type the stored function returns.
|
||||||
*/
|
*/
|
||||||
abstract class AsmNode<T> internal constructor() {
|
abstract class AsmExpression<T> internal constructor() {
|
||||||
/**
|
/**
|
||||||
* Tries to evaluate this function without its variables. This method is intended for optimization.
|
* Tries to evaluate this function without its variables. This method is intended for optimization.
|
||||||
*
|
*
|
||||||
@ -24,18 +24,18 @@ abstract class AsmNode<T> internal constructor() {
|
|||||||
/**
|
/**
|
||||||
* Compiles this declaration.
|
* Compiles this declaration.
|
||||||
*
|
*
|
||||||
* @param gen the target [AsmGenerator].
|
* @param gen the target [AsmBuilder].
|
||||||
*/
|
*/
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal abstract fun compile(gen: AsmGenerator<T>)
|
internal abstract fun compile(gen: AsmBuilder<T>)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class AsmUnaryOperation<T>(private val context: Algebra<T>, private val name: String, expr: AsmNode<T>) :
|
internal class AsmUnaryOperation<T>(private val context: Algebra<T>, private val name: String, expr: AsmExpression<T>) :
|
||||||
AsmNode<T>() {
|
AsmExpression<T>() {
|
||||||
private val expr: AsmNode<T> = expr.optimize()
|
private val expr: AsmExpression<T> = expr.optimize()
|
||||||
override fun tryEvaluate(): T? = context { unaryOperation(name, expr.tryEvaluate() ?: return@context null) }
|
override fun tryEvaluate(): T? = context { unaryOperation(name, expr.tryEvaluate() ?: return@context null) }
|
||||||
|
|
||||||
override fun compile(gen: AsmGenerator<T>) {
|
override fun compile(gen: AsmBuilder<T>) {
|
||||||
gen.loadAlgebra()
|
gen.loadAlgebra()
|
||||||
|
|
||||||
if (!hasSpecific(context, name, 1))
|
if (!hasSpecific(context, name, 1))
|
||||||
@ -47,11 +47,11 @@ internal class AsmUnaryOperation<T>(private val context: Algebra<T>, private val
|
|||||||
return
|
return
|
||||||
|
|
||||||
gen.invokeAlgebraOperation(
|
gen.invokeAlgebraOperation(
|
||||||
owner = AsmGenerator.ALGEBRA_CLASS,
|
owner = AsmBuilder.ALGEBRA_CLASS,
|
||||||
method = "unaryOperation",
|
method = "unaryOperation",
|
||||||
descriptor = "(L${AsmGenerator.STRING_CLASS};" +
|
descriptor = "(L${AsmBuilder.STRING_CLASS};" +
|
||||||
"L${AsmGenerator.OBJECT_CLASS};)" +
|
"L${AsmBuilder.OBJECT_CLASS};)" +
|
||||||
"L${AsmGenerator.OBJECT_CLASS};"
|
"L${AsmBuilder.OBJECT_CLASS};"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,11 +59,11 @@ internal class AsmUnaryOperation<T>(private val context: Algebra<T>, private val
|
|||||||
internal class AsmBinaryOperation<T>(
|
internal class AsmBinaryOperation<T>(
|
||||||
private val context: Algebra<T>,
|
private val context: Algebra<T>,
|
||||||
private val name: String,
|
private val name: String,
|
||||||
first: AsmNode<T>,
|
first: AsmExpression<T>,
|
||||||
second: AsmNode<T>
|
second: AsmExpression<T>
|
||||||
) : AsmNode<T>() {
|
) : AsmExpression<T>() {
|
||||||
private val first: AsmNode<T> = first.optimize()
|
private val first: AsmExpression<T> = first.optimize()
|
||||||
private val second: AsmNode<T> = second.optimize()
|
private val second: AsmExpression<T> = second.optimize()
|
||||||
|
|
||||||
override fun tryEvaluate(): T? = context {
|
override fun tryEvaluate(): T? = context {
|
||||||
binaryOperation(
|
binaryOperation(
|
||||||
@ -73,7 +73,7 @@ internal class AsmBinaryOperation<T>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun compile(gen: AsmGenerator<T>) {
|
override fun compile(gen: AsmBuilder<T>) {
|
||||||
gen.loadAlgebra()
|
gen.loadAlgebra()
|
||||||
|
|
||||||
if (!hasSpecific(context, name, 2))
|
if (!hasSpecific(context, name, 2))
|
||||||
@ -86,56 +86,56 @@ internal class AsmBinaryOperation<T>(
|
|||||||
return
|
return
|
||||||
|
|
||||||
gen.invokeAlgebraOperation(
|
gen.invokeAlgebraOperation(
|
||||||
owner = AsmGenerator.ALGEBRA_CLASS,
|
owner = AsmBuilder.ALGEBRA_CLASS,
|
||||||
method = "binaryOperation",
|
method = "binaryOperation",
|
||||||
descriptor = "(L${AsmGenerator.STRING_CLASS};" +
|
descriptor = "(L${AsmBuilder.STRING_CLASS};" +
|
||||||
"L${AsmGenerator.OBJECT_CLASS};" +
|
"L${AsmBuilder.OBJECT_CLASS};" +
|
||||||
"L${AsmGenerator.OBJECT_CLASS};)" +
|
"L${AsmBuilder.OBJECT_CLASS};)" +
|
||||||
"L${AsmGenerator.OBJECT_CLASS};"
|
"L${AsmBuilder.OBJECT_CLASS};"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class AsmVariableExpression<T>(private val name: String, private val default: T? = null) :
|
internal class AsmVariableExpression<T>(private val name: String, private val default: T? = null) :
|
||||||
AsmNode<T>() {
|
AsmExpression<T>() {
|
||||||
override fun compile(gen: AsmGenerator<T>): Unit = gen.loadVariable(name, default)
|
override fun compile(gen: AsmBuilder<T>): Unit = gen.loadVariable(name, default)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class AsmConstantExpression<T>(private val value: T) :
|
internal class AsmConstantExpression<T>(private val value: T) :
|
||||||
AsmNode<T>() {
|
AsmExpression<T>() {
|
||||||
override fun tryEvaluate(): T = value
|
override fun tryEvaluate(): T = value
|
||||||
override fun compile(gen: AsmGenerator<T>): Unit = gen.loadTConstant(value)
|
override fun compile(gen: AsmBuilder<T>): Unit = gen.loadTConstant(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class AsmConstProductExpression<T>(
|
internal class AsmConstProductExpression<T>(
|
||||||
private val context: Space<T>,
|
private val context: Space<T>,
|
||||||
expr: AsmNode<T>,
|
expr: AsmExpression<T>,
|
||||||
private val const: Number
|
private val const: Number
|
||||||
) : AsmNode<T>() {
|
) : AsmExpression<T>() {
|
||||||
private val expr: AsmNode<T> = expr.optimize()
|
private val expr: AsmExpression<T> = expr.optimize()
|
||||||
|
|
||||||
override fun tryEvaluate(): T? = context { (expr.tryEvaluate() ?: return@context null) * const }
|
override fun tryEvaluate(): T? = context { (expr.tryEvaluate() ?: return@context null) * const }
|
||||||
|
|
||||||
override fun compile(gen: AsmGenerator<T>) {
|
override fun compile(gen: AsmBuilder<T>) {
|
||||||
gen.loadAlgebra()
|
gen.loadAlgebra()
|
||||||
gen.loadNumberConstant(const)
|
gen.loadNumberConstant(const)
|
||||||
expr.compile(gen)
|
expr.compile(gen)
|
||||||
|
|
||||||
gen.invokeAlgebraOperation(
|
gen.invokeAlgebraOperation(
|
||||||
owner = AsmGenerator.SPACE_OPERATIONS_CLASS,
|
owner = AsmBuilder.SPACE_OPERATIONS_CLASS,
|
||||||
method = "multiply",
|
method = "multiply",
|
||||||
descriptor = "(L${AsmGenerator.OBJECT_CLASS};" +
|
descriptor = "(L${AsmBuilder.OBJECT_CLASS};" +
|
||||||
"L${AsmGenerator.NUMBER_CLASS};)" +
|
"L${AsmBuilder.NUMBER_CLASS};)" +
|
||||||
"L${AsmGenerator.OBJECT_CLASS};"
|
"L${AsmBuilder.OBJECT_CLASS};"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class AsmNumberExpression<T>(private val context: NumericAlgebra<T>, private val value: Number) :
|
internal class AsmNumberExpression<T>(private val context: NumericAlgebra<T>, private val value: Number) :
|
||||||
AsmNode<T>() {
|
AsmExpression<T>() {
|
||||||
override fun tryEvaluate(): T? = context.number(value)
|
override fun tryEvaluate(): T? = context.number(value)
|
||||||
|
|
||||||
override fun compile(gen: AsmGenerator<T>): Unit = gen.loadNumberConstant(value)
|
override fun compile(gen: AsmBuilder<T>): Unit = gen.loadNumberConstant(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class FunctionalCompiledExpression<T> internal constructor(
|
internal abstract class FunctionalCompiledExpression<T> internal constructor(
|
||||||
@ -146,10 +146,10 @@ internal abstract class FunctionalCompiledExpression<T> internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A context class for [AsmNode] construction.
|
* A context class for [AsmExpression] construction.
|
||||||
*/
|
*/
|
||||||
interface AsmExpressionAlgebra<T, A : NumericAlgebra<T>> : NumericAlgebra<AsmNode<T>>,
|
interface AsmExpressionAlgebra<T, A : NumericAlgebra<T>> : NumericAlgebra<AsmExpression<T>>,
|
||||||
ExpressionAlgebra<T, AsmNode<T>> {
|
ExpressionAlgebra<T, AsmExpression<T>> {
|
||||||
/**
|
/**
|
||||||
* The algebra to provide for AsmExpressions built.
|
* The algebra to provide for AsmExpressions built.
|
||||||
*/
|
*/
|
||||||
@ -158,108 +158,108 @@ interface AsmExpressionAlgebra<T, A : NumericAlgebra<T>> : NumericAlgebra<AsmNod
|
|||||||
/**
|
/**
|
||||||
* Builds an AsmExpression to wrap a number.
|
* Builds an AsmExpression to wrap a number.
|
||||||
*/
|
*/
|
||||||
override fun number(value: Number): AsmNode<T> = AsmNumberExpression(algebra, value)
|
override fun number(value: Number): AsmExpression<T> = AsmNumberExpression(algebra, value)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an AsmExpression of constant expression which does not depend on arguments.
|
* Builds an AsmExpression of constant expression which does not depend on arguments.
|
||||||
*/
|
*/
|
||||||
override fun const(value: T): AsmNode<T> = AsmConstantExpression(value)
|
override fun const(value: T): AsmExpression<T> = AsmConstantExpression(value)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an AsmExpression to access a variable.
|
* Builds an AsmExpression to access a variable.
|
||||||
*/
|
*/
|
||||||
override fun variable(name: String, default: T?): AsmNode<T> = AsmVariableExpression(name, default)
|
override fun variable(name: String, default: T?): AsmExpression<T> = AsmVariableExpression(name, default)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an AsmExpression of dynamic call of binary operation [operation] on [left] and [right].
|
* Builds an AsmExpression of dynamic call of binary operation [operation] on [left] and [right].
|
||||||
*/
|
*/
|
||||||
override fun binaryOperation(operation: String, left: AsmNode<T>, right: AsmNode<T>): AsmNode<T> =
|
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||||
AsmBinaryOperation(algebra, operation, left, right)
|
AsmBinaryOperation(algebra, operation, left, right)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an AsmExpression of dynamic call of unary operation with name [operation] on [arg].
|
* Builds an AsmExpression of dynamic call of unary operation with name [operation] on [arg].
|
||||||
*/
|
*/
|
||||||
override fun unaryOperation(operation: String, arg: AsmNode<T>): AsmNode<T> =
|
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||||
AsmUnaryOperation(algebra, operation, arg)
|
AsmUnaryOperation(algebra, operation, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A context class for [AsmNode] construction for [Space] algebras.
|
* A context class for [AsmExpression] construction for [Space] algebras.
|
||||||
*/
|
*/
|
||||||
open class AsmExpressionSpace<T, A>(override val algebra: A) : AsmExpressionAlgebra<T, A>,
|
open class AsmExpressionSpace<T, A>(override val algebra: A) : AsmExpressionAlgebra<T, A>,
|
||||||
Space<AsmNode<T>> where A : Space<T>, A : NumericAlgebra<T> {
|
Space<AsmExpression<T>> where A : Space<T>, A : NumericAlgebra<T> {
|
||||||
override val zero: AsmNode<T>
|
override val zero: AsmExpression<T>
|
||||||
get() = const(algebra.zero)
|
get() = const(algebra.zero)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an AsmExpression of addition of two another expressions.
|
* Builds an AsmExpression of addition of two another expressions.
|
||||||
*/
|
*/
|
||||||
override fun add(a: AsmNode<T>, b: AsmNode<T>): AsmNode<T> =
|
override fun add(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||||
AsmBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b)
|
AsmBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an AsmExpression of multiplication of expression by number.
|
* Builds an AsmExpression of multiplication of expression by number.
|
||||||
*/
|
*/
|
||||||
override fun multiply(a: AsmNode<T>, k: Number): AsmNode<T> = AsmConstProductExpression(algebra, a, k)
|
override fun multiply(a: AsmExpression<T>, k: Number): AsmExpression<T> = AsmConstProductExpression(algebra, a, k)
|
||||||
|
|
||||||
operator fun AsmNode<T>.plus(arg: T): AsmNode<T> = this + const(arg)
|
operator fun AsmExpression<T>.plus(arg: T): AsmExpression<T> = this + const(arg)
|
||||||
operator fun AsmNode<T>.minus(arg: T): AsmNode<T> = this - const(arg)
|
operator fun AsmExpression<T>.minus(arg: T): AsmExpression<T> = this - const(arg)
|
||||||
operator fun T.plus(arg: AsmNode<T>): AsmNode<T> = arg + this
|
operator fun T.plus(arg: AsmExpression<T>): AsmExpression<T> = arg + this
|
||||||
operator fun T.minus(arg: AsmNode<T>): AsmNode<T> = arg - this
|
operator fun T.minus(arg: AsmExpression<T>): AsmExpression<T> = arg - this
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: AsmNode<T>): AsmNode<T> =
|
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||||
super<AsmExpressionAlgebra>.unaryOperation(operation, arg)
|
super<AsmExpressionAlgebra>.unaryOperation(operation, arg)
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: AsmNode<T>, right: AsmNode<T>): AsmNode<T> =
|
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||||
super<AsmExpressionAlgebra>.binaryOperation(operation, left, right)
|
super<AsmExpressionAlgebra>.binaryOperation(operation, left, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A context class for [AsmNode] construction for [Ring] algebras.
|
* A context class for [AsmExpression] construction for [Ring] algebras.
|
||||||
*/
|
*/
|
||||||
open class AsmExpressionRing<T, A>(override val algebra: A) : AsmExpressionSpace<T, A>(algebra),
|
open class AsmExpressionRing<T, A>(override val algebra: A) : AsmExpressionSpace<T, A>(algebra),
|
||||||
Ring<AsmNode<T>> where A : Ring<T>, A : NumericAlgebra<T> {
|
Ring<AsmExpression<T>> where A : Ring<T>, A : NumericAlgebra<T> {
|
||||||
override val one: AsmNode<T>
|
override val one: AsmExpression<T>
|
||||||
get() = const(algebra.one)
|
get() = const(algebra.one)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an AsmExpression of multiplication of two expressions.
|
* Builds an AsmExpression of multiplication of two expressions.
|
||||||
*/
|
*/
|
||||||
override fun multiply(a: AsmNode<T>, b: AsmNode<T>): AsmNode<T> =
|
override fun multiply(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||||
AsmBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b)
|
AsmBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b)
|
||||||
|
|
||||||
operator fun AsmNode<T>.times(arg: T): AsmNode<T> = this * const(arg)
|
operator fun AsmExpression<T>.times(arg: T): AsmExpression<T> = this * const(arg)
|
||||||
operator fun T.times(arg: AsmNode<T>): AsmNode<T> = arg * this
|
operator fun T.times(arg: AsmExpression<T>): AsmExpression<T> = arg * this
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: AsmNode<T>): AsmNode<T> =
|
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||||
super<AsmExpressionSpace>.unaryOperation(operation, arg)
|
super<AsmExpressionSpace>.unaryOperation(operation, arg)
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: AsmNode<T>, right: AsmNode<T>): AsmNode<T> =
|
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||||
super<AsmExpressionSpace>.binaryOperation(operation, left, right)
|
super<AsmExpressionSpace>.binaryOperation(operation, left, right)
|
||||||
|
|
||||||
override fun number(value: Number): AsmNode<T> = super<AsmExpressionSpace>.number(value)
|
override fun number(value: Number): AsmExpression<T> = super<AsmExpressionSpace>.number(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A context class for [AsmNode] construction for [Field] algebras.
|
* A context class for [AsmExpression] construction for [Field] algebras.
|
||||||
*/
|
*/
|
||||||
open class AsmExpressionField<T, A>(override val algebra: A) :
|
open class AsmExpressionField<T, A>(override val algebra: A) :
|
||||||
AsmExpressionRing<T, A>(algebra),
|
AsmExpressionRing<T, A>(algebra),
|
||||||
Field<AsmNode<T>> where A : Field<T>, A : NumericAlgebra<T> {
|
Field<AsmExpression<T>> where A : Field<T>, A : NumericAlgebra<T> {
|
||||||
/**
|
/**
|
||||||
* Builds an AsmExpression of division an expression by another one.
|
* Builds an AsmExpression of division an expression by another one.
|
||||||
*/
|
*/
|
||||||
override fun divide(a: AsmNode<T>, b: AsmNode<T>): AsmNode<T> =
|
override fun divide(a: AsmExpression<T>, b: AsmExpression<T>): AsmExpression<T> =
|
||||||
AsmBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b)
|
AsmBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b)
|
||||||
|
|
||||||
operator fun AsmNode<T>.div(arg: T): AsmNode<T> = this / const(arg)
|
operator fun AsmExpression<T>.div(arg: T): AsmExpression<T> = this / const(arg)
|
||||||
operator fun T.div(arg: AsmNode<T>): AsmNode<T> = arg / this
|
operator fun T.div(arg: AsmExpression<T>): AsmExpression<T> = arg / this
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: AsmNode<T>): AsmNode<T> =
|
override fun unaryOperation(operation: String, arg: AsmExpression<T>): AsmExpression<T> =
|
||||||
super<AsmExpressionRing>.unaryOperation(operation, arg)
|
super<AsmExpressionRing>.unaryOperation(operation, arg)
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: AsmNode<T>, right: AsmNode<T>): AsmNode<T> =
|
override fun binaryOperation(operation: String, left: AsmExpression<T>, right: AsmExpression<T>): AsmExpression<T> =
|
||||||
super<AsmExpressionRing>.binaryOperation(operation, left, right)
|
super<AsmExpressionRing>.binaryOperation(operation, left, right)
|
||||||
|
|
||||||
override fun number(value: Number): AsmNode<T> = super<AsmExpressionRing>.number(value)
|
override fun number(value: Number): AsmExpression<T> = super<AsmExpressionRing>.number(value)
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
package scientifik.kmath.asm
|
package scientifik.kmath.asm
|
||||||
|
|
||||||
|
import scientifik.kmath.asm.internal.AsmBuilder
|
||||||
import scientifik.kmath.ast.MST
|
import scientifik.kmath.ast.MST
|
||||||
import scientifik.kmath.ast.evaluate
|
import scientifik.kmath.ast.evaluate
|
||||||
import scientifik.kmath.expressions.Expression
|
import scientifik.kmath.expressions.Expression
|
||||||
import scientifik.kmath.operations.Field
|
import scientifik.kmath.operations.*
|
||||||
import scientifik.kmath.operations.NumericAlgebra
|
|
||||||
import scientifik.kmath.operations.Ring
|
|
||||||
import scientifik.kmath.operations.Space
|
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
internal fun buildName(expression: AsmExpression<*>, collision: Int = 0): String {
|
internal fun buildName(expression: AsmExpression<*>, collision: Int = 0): String {
|
||||||
val name = "scientifik.kmath.expressions.generated.AsmCompiledExpression_${expression.hashCode()}_$collision"
|
val name = "scientifik.kmath.expressions.generated.AsmCompiledExpression_${expression.hashCode()}_$collision"
|
||||||
|
|
||||||
@ -20,28 +19,35 @@ internal fun buildName(expression: AsmExpression<*>, collision: Int = 0): String
|
|||||||
return buildName(expression, collision + 1)
|
return buildName(expression, collision + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : Any, A : NumericAlgebra<T>, E : AsmExpressionAlgebra<T, A>> A.asm(
|
@PublishedApi
|
||||||
|
internal inline fun <reified T> AsmExpression<T>.compile(algebra: Algebra<T>): Expression<T> =
|
||||||
|
AsmBuilder(T::class.java, algebra, buildName(this), this).getInstance()
|
||||||
|
|
||||||
|
inline fun <reified T, A : NumericAlgebra<T>, E : AsmExpressionAlgebra<T, A>> A.asm(
|
||||||
expressionAlgebra: E,
|
expressionAlgebra: E,
|
||||||
block: E.() -> AsmExpression<T>
|
block: E.() -> AsmExpression<T>
|
||||||
): Expression<T> = expressionAlgebra.block()
|
): Expression<T> = expressionAlgebra.block().compile(expressionAlgebra.algebra)
|
||||||
|
|
||||||
inline fun <reified T : Any> NumericAlgebra<T>.asm(ast: MST): Expression<T> =
|
inline fun <reified T, A : NumericAlgebra<T>, E : AsmExpressionAlgebra<T, A>> A.asm(
|
||||||
AsmExpressionAlgebra(T::class, this).evaluate(ast)
|
expressionAlgebra: E,
|
||||||
|
ast: MST
|
||||||
|
): Expression<T> = asm(expressionAlgebra) { evaluate(ast) }
|
||||||
|
|
||||||
inline fun <reified T : Any, A> A.asmSpace(block: AsmExpressionSpace<T, A>.() -> AsmExpression<T>): Expression<T> where A : NumericAlgebra<T>, A : Space<T> =
|
inline fun <reified T, A> A.asmSpace(block: AsmExpressionSpace<T, A>.() -> AsmExpression<T>): Expression<T> where A : NumericAlgebra<T>, A : Space<T> =
|
||||||
AsmExpressionSpace<T, A>(T::class, this).block()
|
AsmExpressionSpace(this).let { it.block().compile(it.algebra) }
|
||||||
|
|
||||||
inline fun <reified T : Any, A> A.asmSpace(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Space<T> =
|
inline fun <reified T, A> A.asmSpace(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Space<T> =
|
||||||
asmSpace { evaluate(ast) }
|
asmSpace { evaluate(ast) }
|
||||||
|
|
||||||
inline fun <reified T : Any, A> A.asmRing(block: AsmExpressionRing<T, A>.() -> AsmExpression<T>): Expression<T> where A : NumericAlgebra<T>, A : Ring<T> =
|
inline fun <reified T, A> A.asmRing(block: AsmExpressionRing<T, A>.() -> AsmExpression<T>): Expression<T> where A : NumericAlgebra<T>, A : Ring<T> =
|
||||||
AsmExpressionRing(T::class, this).block()
|
AsmExpressionRing(this).let { it.block().compile(it.algebra) }
|
||||||
|
|
||||||
inline fun <reified T : Any, A> A.asmRing(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Ring<T> =
|
inline fun <reified T, A> A.asmRing(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Ring<T> =
|
||||||
asmRing { evaluate(ast) }
|
asmRing { evaluate(ast) }
|
||||||
|
|
||||||
inline fun <reified T : Any, A> A.asmField(block: AsmExpressionField<T, A>.() -> AsmExpression<T>): Expression<T> where A : NumericAlgebra<T>, A : Field<T> =
|
inline fun <reified T, A> A.asmField(block: AsmExpressionField<T, A>.() -> AsmExpression<T>): Expression<T> where A : NumericAlgebra<T>, A : Field<T> =
|
||||||
AsmExpressionField(T::class, this).block()
|
AsmExpressionField(this).let { it.block().compile(it.algebra) }
|
||||||
|
|
||||||
inline fun <reified T : Any, A> A.asmField(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Field<T> =
|
inline fun <reified T, A> A.asmField(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Field<T> =
|
||||||
asmRing { evaluate(ast) }
|
asmRing { evaluate(ast) }
|
||||||
|
|
||||||
|
@ -4,13 +4,13 @@ import org.objectweb.asm.ClassWriter
|
|||||||
import org.objectweb.asm.Label
|
import org.objectweb.asm.Label
|
||||||
import org.objectweb.asm.MethodVisitor
|
import org.objectweb.asm.MethodVisitor
|
||||||
import org.objectweb.asm.Opcodes
|
import org.objectweb.asm.Opcodes
|
||||||
import scientifik.kmath.asm.AsmNode
|
import scientifik.kmath.asm.AsmExpression
|
||||||
import scientifik.kmath.asm.FunctionalCompiledExpression
|
import scientifik.kmath.asm.FunctionalCompiledExpression
|
||||||
import scientifik.kmath.asm.internal.AsmGenerator.ClassLoader
|
import scientifik.kmath.asm.internal.AsmBuilder.ClassLoader
|
||||||
import scientifik.kmath.operations.Algebra
|
import scientifik.kmath.operations.Algebra
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM Generator is a structure that abstracts building a class that unwraps [AsmNode] to plain Java expression.
|
* ASM Builder is a structure that abstracts building a class that unwraps [AsmExpression] to plain Java expression.
|
||||||
* This class uses [ClassLoader] for loading the generated class, then it is able to instantiate the new class.
|
* This class uses [ClassLoader] for loading the generated class, then it is able to instantiate the new class.
|
||||||
*
|
*
|
||||||
* @param T the type of AsmExpression to unwrap.
|
* @param T the type of AsmExpression to unwrap.
|
||||||
@ -18,11 +18,11 @@ import scientifik.kmath.operations.Algebra
|
|||||||
* @param className the unique class name of new loaded class.
|
* @param className the unique class name of new loaded class.
|
||||||
*/
|
*/
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal class AsmGenerator<T> @PublishedApi internal constructor(
|
internal class AsmBuilder<T> @PublishedApi internal constructor(
|
||||||
private val classOfT: Class<*>,
|
private val classOfT: Class<*>,
|
||||||
private val algebra: Algebra<T>,
|
private val algebra: Algebra<T>,
|
||||||
private val className: String,
|
private val className: String,
|
||||||
private val root: AsmNode<T>
|
private val root: AsmExpression<T>
|
||||||
) {
|
) {
|
||||||
private class ClassLoader(parent: java.lang.ClassLoader) : java.lang.ClassLoader(parent) {
|
private class ClassLoader(parent: java.lang.ClassLoader) : java.lang.ClassLoader(parent) {
|
||||||
internal fun defineClass(name: String?, b: ByteArray): Class<*> = defineClass(name, b, 0, b.size)
|
internal fun defineClass(name: String?, b: ByteArray): Class<*> = defineClass(name, b, 0, b.size)
|
||||||
@ -112,7 +112,7 @@ internal class AsmGenerator<T> @PublishedApi internal constructor(
|
|||||||
visitCode()
|
visitCode()
|
||||||
val l0 = Label()
|
val l0 = Label()
|
||||||
visitLabel(l0)
|
visitLabel(l0)
|
||||||
root.compile(this@AsmGenerator)
|
root.compile(this@AsmBuilder)
|
||||||
visitReturnObject()
|
visitReturnObject()
|
||||||
val l1 = Label()
|
val l1 = Label()
|
||||||
visitLabel(l1)
|
visitLabel(l1)
|
@ -2,7 +2,7 @@ package scientifik.kmath.asm.internal
|
|||||||
|
|
||||||
import org.objectweb.asm.Opcodes
|
import org.objectweb.asm.Opcodes
|
||||||
import scientifik.kmath.asm.AsmConstantExpression
|
import scientifik.kmath.asm.AsmConstantExpression
|
||||||
import scientifik.kmath.asm.AsmNode
|
import scientifik.kmath.asm.AsmExpression
|
||||||
import scientifik.kmath.operations.Algebra
|
import scientifik.kmath.operations.Algebra
|
||||||
|
|
||||||
private val methodNameAdapters: Map<String, String> = mapOf("+" to "add", "*" to "multiply", "/" to "divide")
|
private val methodNameAdapters: Map<String, String> = mapOf("+" to "add", "*" to "multiply", "/" to "divide")
|
||||||
@ -16,7 +16,7 @@ internal fun <T> hasSpecific(context: Algebra<T>, name: String, arity: Int): Boo
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun <T> AsmGenerator<T>.tryInvokeSpecific(context: Algebra<T>, name: String, arity: Int): Boolean {
|
internal fun <T> AsmBuilder<T>.tryInvokeSpecific(context: Algebra<T>, name: String, arity: Int): Boolean {
|
||||||
val aName = methodNameAdapters[name] ?: name
|
val aName = methodNameAdapters[name] ?: name
|
||||||
|
|
||||||
context::class.java.methods.find { it.name == aName && it.parameters.size == arity }
|
context::class.java.methods.find { it.name == aName && it.parameters.size == arity }
|
||||||
@ -26,9 +26,9 @@ internal fun <T> AsmGenerator<T>.tryInvokeSpecific(context: Algebra<T>, name: St
|
|||||||
|
|
||||||
val sig = buildString {
|
val sig = buildString {
|
||||||
append('(')
|
append('(')
|
||||||
repeat(arity) { append("L${AsmGenerator.OBJECT_CLASS};") }
|
repeat(arity) { append("L${AsmBuilder.OBJECT_CLASS};") }
|
||||||
append(')')
|
append(')')
|
||||||
append("L${AsmGenerator.OBJECT_CLASS};")
|
append("L${AsmBuilder.OBJECT_CLASS};")
|
||||||
}
|
}
|
||||||
|
|
||||||
invokeAlgebraOperation(
|
invokeAlgebraOperation(
|
||||||
@ -43,7 +43,7 @@ internal fun <T> AsmGenerator<T>.tryInvokeSpecific(context: Algebra<T>, name: St
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal fun <T> AsmNode<T>.optimize(): AsmNode<T> {
|
internal fun <T> AsmExpression<T>.optimize(): AsmExpression<T> {
|
||||||
val a = tryEvaluate()
|
val a = tryEvaluate()
|
||||||
return if (a == null) this else AsmConstantExpression(a)
|
return if (a == null) this else AsmConstantExpression(a)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user