diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Builders.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmBuilders.kt similarity index 94% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Builders.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmBuilders.kt index 67870e07e..14456a426 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Builders.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmBuilders.kt @@ -18,9 +18,10 @@ internal fun buildName(expression: AsmExpression<*>, collision: Int = 0): String return buildName(expression, collision + 1) } -inline fun AsmExpression.compile(algebra: Algebra): Expression { +@PublishedApi +internal inline fun AsmExpression.compile(algebra: Algebra): Expression { val ctx = AsmGenerationContext(T::class.java, algebra, buildName(this)) - invoke(ctx) + compile(ctx) return ctx.generate() } 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 83f3b7754..cd1815f7c 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmExpressions.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmExpressions.kt @@ -1,14 +1,31 @@ package scientifik.kmath.asm +import scientifik.kmath.asm.internal.hasSpecific +import scientifik.kmath.asm.internal.optimize +import scientifik.kmath.asm.internal.tryInvokeSpecific import scientifik.kmath.expressions.Expression import scientifik.kmath.expressions.ExpressionAlgebra import scientifik.kmath.operations.* -import kotlin.reflect.full.memberFunctions -import kotlin.reflect.jvm.jvmName +/** + * A function declaration that could be compiled to [AsmGenerationContext]. + * + * @param T the type the stored function returns. + */ interface AsmExpression { + /** + * Tries to evaluate this function without its variables. This method is intended for optimization. + * + * @return `null` if the function depends on its variables, the value if the function is a constant. + */ fun tryEvaluate(): T? = null - fun invoke(gen: AsmGenerationContext) + + /** + * Compiles this declaration. + * + * @param gen the target [AsmGenerationContext]. + */ + fun compile(gen: AsmGenerationContext) } internal class AsmUnaryOperation(private val context: Algebra, private val name: String, expr: AsmExpression) : @@ -16,13 +33,13 @@ internal class AsmUnaryOperation(private val context: Algebra, private val private val expr: AsmExpression = expr.optimize() override fun tryEvaluate(): T? = context { unaryOperation(name, expr.tryEvaluate() ?: return@context null) } - override fun invoke(gen: AsmGenerationContext) { + override fun compile(gen: AsmGenerationContext) { gen.visitLoadAlgebra() if (!hasSpecific(context, name, 1)) gen.visitStringConstant(name) - expr.invoke(gen) + expr.compile(gen) if (gen.tryInvokeSpecific(context, name, 1)) return @@ -54,14 +71,14 @@ internal class AsmBinaryOperation( ) } - override fun invoke(gen: AsmGenerationContext) { + override fun compile(gen: AsmGenerationContext) { gen.visitLoadAlgebra() if (!hasSpecific(context, name, 2)) gen.visitStringConstant(name) - first.invoke(gen) - second.invoke(gen) + first.compile(gen) + second.compile(gen) if (gen.tryInvokeSpecific(context, name, 2)) return @@ -79,13 +96,13 @@ internal class AsmBinaryOperation( internal class AsmVariableExpression(private val name: String, private val default: T? = null) : AsmExpression { - override fun invoke(gen: AsmGenerationContext): Unit = gen.visitLoadFromVariables(name, default) + override fun compile(gen: AsmGenerationContext): Unit = gen.visitLoadFromVariables(name, default) } internal class AsmConstantExpression(private val value: T) : AsmExpression { override fun tryEvaluate(): T = value - override fun invoke(gen: AsmGenerationContext): Unit = gen.visitLoadFromConstants(value) + override fun compile(gen: AsmGenerationContext): Unit = gen.visitLoadFromConstants(value) } internal class AsmConstProductExpression( @@ -98,10 +115,10 @@ internal class AsmConstProductExpression( override fun tryEvaluate(): T? = context { (expr.tryEvaluate() ?: return@context null) * const } - override fun invoke(gen: AsmGenerationContext) { + override fun compile(gen: AsmGenerationContext) { gen.visitLoadAlgebra() gen.visitNumberConstant(const) - expr.invoke(gen) + expr.compile(gen) gen.visitAlgebraOperation( owner = AsmGenerationContext.SPACE_OPERATIONS_CLASS, @@ -117,7 +134,7 @@ internal class AsmNumberExpression(private val context: NumericAlgebra, pr AsmExpression { override fun tryEvaluate(): T? = context.number(value) - override fun invoke(gen: AsmGenerationContext): Unit = gen.visitNumberConstant(value) + override fun compile(gen: AsmGenerationContext): Unit = gen.visitNumberConstant(value) } internal abstract class FunctionalCompiledExpression internal constructor( 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 cc7874e37..be8da3eff 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmGenerationContext.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/AsmGenerationContext.kt @@ -5,6 +5,9 @@ import org.objectweb.asm.Label import org.objectweb.asm.MethodVisitor import org.objectweb.asm.Opcodes import scientifik.kmath.asm.AsmGenerationContext.ClassLoader +import scientifik.kmath.asm.internal.visitLdcOrDConstInsn +import scientifik.kmath.asm.internal.visitLdcOrFConstInsn +import scientifik.kmath.asm.internal.visitLdcOrIConstInsn import scientifik.kmath.operations.Algebra /** @@ -16,7 +19,7 @@ import scientifik.kmath.operations.Algebra * @param algebra the algebra the applied AsmExpressions use. * @param className the unique class name of new loaded class. */ -class AsmGenerationContext( +class AsmGenerationContext @PublishedApi internal constructor( private val classOfT: Class<*>, private val algebra: Algebra, private val className: String diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/MethodVisitors.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MethodVisitors.kt similarity index 95% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/MethodVisitors.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MethodVisitors.kt index aec5a123d..356de4765 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/MethodVisitors.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MethodVisitors.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.asm +package scientifik.kmath.asm.internal import org.objectweb.asm.MethodVisitor import org.objectweb.asm.Opcodes.* diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Optimization.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/Optimization.kt similarity index 88% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Optimization.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/Optimization.kt index 51048c77c..cd41ff07c 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/Optimization.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/Optimization.kt @@ -1,8 +1,10 @@ -package scientifik.kmath.asm +package scientifik.kmath.asm.internal import org.objectweb.asm.Opcodes +import scientifik.kmath.asm.AsmConstantExpression +import scientifik.kmath.asm.AsmExpression +import scientifik.kmath.asm.AsmGenerationContext import scientifik.kmath.operations.Algebra -import scientifik.kmath.operations.ByteRing private val methodNameAdapters: Map = mapOf("+" to "add", "*" to "multiply", "/" to "divide")