From 36ad1fcf589e0f8e9b4701f463360d7d66c80c41 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sat, 13 Jun 2020 15:44:54 +0700 Subject: [PATCH] Minor refactor and document --- .../scientifik/kmath/asm/AsmExpressions.kt | 101 +++++++++++++----- .../kmath/asm/AsmGenerationContext.kt | 12 ++- .../expressions/FunctionalExpressions.kt | 84 ++++++++++----- 3 files changed, 141 insertions(+), 56 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmExpressions.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmExpressions.kt index 75b5f26d0..ef579278a 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmExpressions.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmExpressions.kt @@ -142,7 +142,8 @@ internal class AsmConstProductExpression( } } -internal class AsmNumberExpression(private val context: NumericAlgebra, private val value: Number) : AsmExpression { +internal class AsmNumberExpression(private val context: NumericAlgebra, private val value: Number) : + AsmExpression { override fun tryEvaluate(): T? = context.number(value) override fun invoke(gen: AsmGenerationContext): Unit = gen.visitNumberConstant(value) @@ -155,75 +156,121 @@ internal abstract class FunctionalCompiledExpression internal constructor( abstract override fun invoke(arguments: Map): T } +/** + * A context class for [AsmExpression] construction. + */ interface AsmExpressionAlgebra> : NumericAlgebra>, ExpressionAlgebra> { + /** + * The algebra to provide for AsmExpressions built. + */ val algebra: A + + /** + * Builds an AsmExpression to wrap a number. + */ + override fun number(value: Number): AsmExpression = AsmNumberExpression(algebra, value) + + /** + * Builds an AsmExpression of constant expression which does not depend on arguments. + */ + override fun const(value: T): AsmExpression = AsmConstantExpression(value) + + /** + * Builds an AsmExpression to access a variable. + */ + override fun variable(name: String, default: T?): AsmExpression = AsmVariableExpression(name, default) + + /** + * Builds an AsmExpression of dynamic call of binary operation [operation] on [left] and [right]. + */ override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = AsmBinaryOperation(algebra, operation, left, right) + /** + * Builds an AsmExpression of dynamic call of unary operation with name [operation] on [arg]. + */ override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = AsmUnaryOperation(algebra, operation, arg) - - override fun number(value: Number): AsmExpression = AsmNumberExpression(algebra, value) - override fun const(value: T): AsmExpression = AsmConstantExpression(value) - override fun variable(name: String, default: T?): AsmExpression = AsmVariableExpression(name, default) } +/** + * A context class for [AsmExpression] construction for [Space] algebras. + */ open class AsmExpressionSpace(override val algebra: A) : AsmExpressionAlgebra, Space> where A : Space, A : NumericAlgebra { override val zero: AsmExpression get() = const(algebra.zero) - override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = - AsmBinaryOperation(algebra, operation, left, right) - - override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = - AsmUnaryOperation(algebra, operation, arg) - + /** + * Builds an AsmExpression of addition of two another expressions. + */ override fun add(a: AsmExpression, b: AsmExpression): AsmExpression = AsmBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b) + /** + * Builds an AsmExpression of multiplication of expression by number. + */ override fun multiply(a: AsmExpression, k: Number): AsmExpression = AsmConstProductExpression(algebra, a, k) + operator fun AsmExpression.plus(arg: T): AsmExpression = this + const(arg) operator fun AsmExpression.minus(arg: T): AsmExpression = this - const(arg) operator fun T.plus(arg: AsmExpression): AsmExpression = arg + this operator fun T.minus(arg: AsmExpression): AsmExpression = arg - this + + override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = + super.unaryOperation(operation, arg) + + override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = + super.binaryOperation(operation, left, right) } +/** + * A context class for [AsmExpression] construction for [Ring] algebras. + */ open class AsmExpressionRing(override val algebra: A) : AsmExpressionSpace(algebra), Ring> where A : Ring, A : NumericAlgebra { override val one: AsmExpression get() = const(algebra.one) - override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = - AsmUnaryOperation(algebra, operation, arg) - - override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = - AsmBinaryOperation(algebra, operation, left, right) - - override fun number(value: Number): AsmExpression = const(algebra { one * value }) - + /** + * Builds an AsmExpression of multiplication of two expressions. + */ override fun multiply(a: AsmExpression, b: AsmExpression): AsmExpression = AsmBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b) operator fun AsmExpression.times(arg: T): AsmExpression = this * const(arg) operator fun T.times(arg: AsmExpression): AsmExpression = arg * this + + override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = + super.unaryOperation(operation, arg) + + override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = + super.binaryOperation(operation, left, right) + + override fun number(value: Number): AsmExpression = super.number(value) } +/** + * A context class for [AsmExpression] construction for [Field] algebras. + */ open class AsmExpressionField(override val algebra: A) : AsmExpressionRing(algebra), Field> where A : Field, A : NumericAlgebra { - - override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = - AsmUnaryOperation(algebra, operation, arg) - - override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = - AsmBinaryOperation(algebra, operation, left, right) - + /** + * Builds an AsmExpression of division an expression by another one. + */ override fun divide(a: AsmExpression, b: AsmExpression): AsmExpression = AsmBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b) operator fun AsmExpression.div(arg: T): AsmExpression = this / const(arg) operator fun T.div(arg: AsmExpression): AsmExpression = arg / this -} + override fun unaryOperation(operation: String, arg: AsmExpression): AsmExpression = + super.unaryOperation(operation, arg) + + override fun binaryOperation(operation: String, left: AsmExpression, right: AsmExpression): AsmExpression = + super.binaryOperation(operation, left, right) + + override fun number(value: Number): AsmExpression = super.number(value) +} diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmGenerationContext.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmGenerationContext.kt index d9dba746d..69a2b6c85 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmGenerationContext.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmGenerationContext.kt @@ -6,6 +6,15 @@ import org.objectweb.asm.MethodVisitor import org.objectweb.asm.Opcodes import scientifik.kmath.operations.Algebra +/** + * AsmGenerationContext 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. + * + * @param T the type of AsmExpression to unwrap. + * @param algebra the algebra the applied AsmExpressions use. + * @param className the unique class name of new loaded class. + */ class AsmGenerationContext( classOfT: Class<*>, private val algebra: Algebra, @@ -29,8 +38,7 @@ class AsmGenerationContext( private val invokeArgumentsVar: Int = 1 private var maxStack: Int = 0 private val constants: MutableList = mutableListOf() - private val asmCompiledClassWriter: ClassWriter = - ClassWriter(0) + private val asmCompiledClassWriter: ClassWriter = ClassWriter(0) private val invokeMethodVisitor: MethodVisitor private val invokeL0: Label private lateinit var invokeL1: Label diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt index 88d8c87b7..c3f36a814 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt @@ -28,40 +28,61 @@ internal class FunctionalConstantExpression(val value: T) : Expression { internal class FunctionalConstProductExpression( val context: Space, - val expr: Expression, + private val expr: Expression, val const: Number -) : - Expression { +) : Expression { override fun invoke(arguments: Map): T = context.multiply(expr.invoke(arguments), const) } +/** + * A context class for [Expression] construction. + */ interface FunctionalExpressionAlgebra> : ExpressionAlgebra> { + /** + * The algebra to provide for Expressions built. + */ val algebra: A + /** + * Builds an Expression of constant expression which does not depend on arguments. + */ + override fun const(value: T): Expression = FunctionalConstantExpression(value) + + /** + * Builds an Expression to access a variable. + */ + override fun variable(name: String, default: T?): Expression = FunctionalVariableExpression(name, default) + + /** + * Builds an Expression of dynamic call of binary operation [operation] on [left] and [right]. + */ override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = FunctionalBinaryOperation(algebra, operation, left, right) + /** + * Builds an Expression of dynamic call of unary operation with name [operation] on [arg]. + */ override fun unaryOperation(operation: String, arg: Expression): Expression = FunctionalUnaryOperation(algebra, operation, arg) - - override fun const(value: T): Expression = FunctionalConstantExpression(value) - override fun variable(name: String, default: T?): Expression = FunctionalVariableExpression(name, default) } +/** + * A context class for [Expression] construction for [Space] algebras. + */ open class FunctionalExpressionSpace(override val algebra: A) : FunctionalExpressionAlgebra, Space> where A : Space { override val zero: Expression get() = const(algebra.zero) - override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = - FunctionalBinaryOperation(algebra, operation, left, right) - - override fun unaryOperation(operation: String, arg: Expression): Expression = - FunctionalUnaryOperation(algebra, operation, arg) - + /** + * Builds an Expression of addition of two another expressions. + */ override fun add(a: Expression, b: Expression): Expression = FunctionalBinaryOperation(algebra, SpaceOperations.PLUS_OPERATION, a, b) + /** + * Builds an Expression of multiplication of expression by number. + */ override fun multiply(a: Expression, k: Number): Expression = FunctionalConstProductExpression(algebra, a, k) @@ -69,6 +90,12 @@ open class FunctionalExpressionSpace(override val algebra: A) : Functional operator fun Expression.minus(arg: T): Expression = this - const(arg) operator fun T.plus(arg: Expression): Expression = arg + this operator fun T.minus(arg: Expression): Expression = arg - this + + override fun unaryOperation(operation: String, arg: Expression): Expression = + super.unaryOperation(operation, arg) + + override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = + super.binaryOperation(operation, left, right) } open class FunctionalExpressionRing(override val algebra: A) : FunctionalExpressionSpace(algebra), @@ -76,34 +103,37 @@ open class FunctionalExpressionRing(override val algebra: A) : FunctionalE override val one: Expression get() = const(algebra.one) - override fun unaryOperation(operation: String, arg: Expression): Expression = - FunctionalUnaryOperation(algebra, operation, arg) - - override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = - FunctionalBinaryOperation(algebra, operation, left, right) - - override fun number(value: Number): Expression = const(algebra { one * value }) - + /** + * Builds an Expression of multiplication of two expressions. + */ override fun multiply(a: Expression, b: Expression): Expression = FunctionalBinaryOperation(algebra, RingOperations.TIMES_OPERATION, a, b) operator fun Expression.times(arg: T): Expression = this * const(arg) operator fun T.times(arg: Expression): Expression = arg * this + + override fun unaryOperation(operation: String, arg: Expression): Expression = + super.unaryOperation(operation, arg) + + override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = + super.binaryOperation(operation, left, right) } open class FunctionalExpressionField(override val algebra: A) : FunctionalExpressionRing(algebra), Field> where A : Field, A : NumericAlgebra { - - override fun unaryOperation(operation: String, arg: Expression): Expression = - FunctionalUnaryOperation(algebra, operation, arg) - - override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = - FunctionalBinaryOperation(algebra, operation, left, right) - + /** + * Builds an Expression of division an expression by another one. + */ override fun divide(a: Expression, b: Expression): Expression = FunctionalBinaryOperation(algebra, FieldOperations.DIV_OPERATION, a, b) operator fun Expression.div(arg: T): Expression = this / const(arg) operator fun T.div(arg: Expression): Expression = arg / this + + override fun unaryOperation(operation: String, arg: Expression): Expression = + super.unaryOperation(operation, arg) + + override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = + super.binaryOperation(operation, left, right) }