diff --git a/kmath-ast/README.md b/kmath-ast/README.md new file mode 100644 index 000000000..f9dbd4663 --- /dev/null +++ b/kmath-ast/README.md @@ -0,0 +1,4 @@ +# AST based expression representation and operations + +## Dynamic expression code generation +Contributed by [Iaroslav Postovalov](https://github.com/CommanderTvis). \ No newline at end of file diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt index 3375ecdf3..900b9297a 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt @@ -11,7 +11,7 @@ sealed class MST { /** * A node containing unparsed string */ - data class Singular(val value: String) : MST() + data class Symbolic(val value: String) : MST() /** * A node containing a number @@ -43,7 +43,7 @@ sealed class MST { fun <T> NumericAlgebra<T>.evaluate(node: MST): T { return when (node) { is MST.Numeric -> number(node.value) - is MST.Singular -> symbol(node.value) + is MST.Symbolic -> symbol(node.value) is MST.Unary -> unaryOperation(node.operation, evaluate(node.value)) is MST.Binary -> when { node.left is MST.Numeric && node.right is MST.Numeric -> { diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt new file mode 100644 index 000000000..cc3e36e94 --- /dev/null +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt @@ -0,0 +1,47 @@ +package scientifik.kmath.asm + +import scientifik.kmath.ast.MST +import scientifik.kmath.ast.evaluate +import scientifik.kmath.expressions.Expression +import scientifik.kmath.operations.Field +import scientifik.kmath.operations.NumericAlgebra +import scientifik.kmath.operations.Ring +import scientifik.kmath.operations.Space + +internal fun buildName(expression: AsmExpression<*>, 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) +} + +inline fun <reified T : Any, A : NumericAlgebra<T>, E : AsmExpressionAlgebra<T, A>> A.asm( + expressionAlgebra: E, + block: E.() -> AsmExpression<T> +): Expression<T> = expressionAlgebra.block() + +inline fun <reified T : Any> NumericAlgebra<T>.asm(ast: MST): Expression<T> = + AsmExpressionAlgebra(T::class, this).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> = + AsmExpressionSpace<T, A>(T::class, this).block() + +inline fun <reified T : Any, A> A.asmSpace(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Space<T> = + 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> = + AsmExpressionRing(T::class, this).block() + +inline fun <reified T : Any, A> A.asmRing(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Ring<T> = + 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> = + AsmExpressionField(T::class, this).block() + +inline fun <reified T : Any, A> A.asmField(ast: MST): Expression<T> where A : NumericAlgebra<T>, A : Field<T> = + asmRing { evaluate(ast) } diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MethodVisitors.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/methodVisitors.kt similarity index 100% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MethodVisitors.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/methodVisitors.kt diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/Optimization.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/optimization.kt similarity index 100% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/Optimization.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/optimization.kt diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/asm/TestAsmAlgebras.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt similarity index 98% rename from kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/asm/TestAsmAlgebras.kt rename to kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt index 07f895c40..06f776597 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/asm/TestAsmAlgebras.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt @@ -1,4 +1,4 @@ -package scietifik.kmath.ast.asm +package scietifik.kmath.asm import scientifik.kmath.asm.asmField import scientifik.kmath.asm.asmRing diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/asm/TestAsmExpressions.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt similarity index 94% rename from kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/asm/TestAsmExpressions.kt rename to kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt index 2839b8a25..40d990537 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/asm/TestAsmExpressions.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt @@ -1,4 +1,4 @@ -package scietifik.kmath.ast.asm +package scietifik.kmath.asm import scientifik.kmath.asm.asmField import scientifik.kmath.expressions.invoke diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressions.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/expressions/ExpressionFieldTest.kt index b933f6a17..9eae60efc 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/expressions/ExpressionFieldTest.kt @@ -31,7 +31,7 @@ class ExpressionFieldTest { @Test fun separateContext() { - fun <T> FunctionalExpressionField<T>.expression(): Expression<T> { + fun <T> FunctionalExpressionField<T,*>.expression(): Expression<T> { val x = variable("x") return x * x + 2 * x + one } @@ -42,7 +42,7 @@ class ExpressionFieldTest { @Test fun valueExpression() { - val expressionBuilder: FunctionalExpressionField<Double>.() -> Expression<Double> = { + val expressionBuilder: FunctionalExpressionField<Double,*>.() -> Expression<Double> = { val x = variable("x") x * x + 2 * x + one }