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 NumericAlgebra.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 , E : AsmExpressionAlgebra> A.asm( + expressionAlgebra: E, + block: E.() -> AsmExpression +): Expression = expressionAlgebra.block() + +inline fun NumericAlgebra.asm(ast: MST): Expression = + AsmExpressionAlgebra(T::class, this).evaluate(ast) + +inline fun A.asmSpace(block: AsmExpressionSpace.() -> AsmExpression): Expression where A : NumericAlgebra, A : Space = + AsmExpressionSpace(T::class, this).block() + +inline fun A.asmSpace(ast: MST): Expression where A : NumericAlgebra, A : Space = + asmSpace { evaluate(ast) } + +inline fun A.asmRing(block: AsmExpressionRing.() -> AsmExpression): Expression where A : NumericAlgebra, A : Ring = + AsmExpressionRing(T::class, this).block() + +inline fun A.asmRing(ast: MST): Expression where A : NumericAlgebra, A : Ring = + asmRing { evaluate(ast) } + +inline fun A.asmField(block: AsmExpressionField.() -> AsmExpression): Expression where A : NumericAlgebra, A : Field = + AsmExpressionField(T::class, this).block() + +inline fun A.asmField(ast: MST): Expression where A : NumericAlgebra, A : Field = + 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 FunctionalExpressionField.expression(): Expression { + fun FunctionalExpressionField.expression(): Expression { val x = variable("x") return x * x + 2 * x + one } @@ -42,7 +42,7 @@ class ExpressionFieldTest { @Test fun valueExpression() { - val expressionBuilder: FunctionalExpressionField.() -> Expression = { + val expressionBuilder: FunctionalExpressionField.() -> Expression = { val x = variable("x") x * x + 2 * x + one }