From 077c2b4e3b7168a297f5518876dca8ca9a390578 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov <38042667+CommanderTvis@users.noreply.github.com> Date: Fri, 23 Apr 2021 08:49:01 +0700 Subject: [PATCH 1/2] Update README.md in kmath-ast --- kmath-ast/README.md | 5 +++-- kmath-ast/docs/README-TEMPLATE.md | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/kmath-ast/README.md b/kmath-ast/README.md index eedba16fa..1ee78956e 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -50,7 +50,7 @@ For example, the following builder: MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +... leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; @@ -97,6 +97,7 @@ var executable = function (constants, arguments) { }; ``` +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin import space.kscience.kmath.wasm.* @@ -104,7 +105,7 @@ import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -An example of emitted WASM IR in the form of WAT: +An example of emitted Wasm IR in the form of WAT: ```lisp (func $executable (param $0 f64) (result f64) diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index b38311ea1..1ecf477ef 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -19,7 +19,7 @@ For example, the following builder: MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +... leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; @@ -66,6 +66,7 @@ var executable = function (constants, arguments) { }; ``` +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin import space.kscience.kmath.wasm.* @@ -73,7 +74,7 @@ import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -An example of emitted WASM IR in the form of WAT: +An example of emitted Wasm IR in the form of WAT: ```lisp (func \$executable (param \$0 f64) (result f64) From e3f7b7a5fa560d4084a16a611b0266576d1e5728 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 28 Apr 2021 10:25:03 +0700 Subject: [PATCH 2/2] Promote kmath-ast as experimental, mark AST Rendering and WASM with @UnstableKMathAPI --- kmath-ast/build.gradle.kts | 6 +- .../kotlin/space/kscience/kmath/ast/parser.kt | 1 - .../ast/rendering/LatexSyntaxRenderer.kt | 3 + .../ast/rendering/MathMLSyntaxRenderer.kt | 5 +- .../kmath/ast/rendering/MathRenderer.kt | 4 + .../kmath/ast/rendering/MathSyntax.kt | 25 ++ .../kmath/ast/rendering/SyntaxRenderer.kt | 4 + .../kscience/kmath/ast/rendering/features.kt | 280 ++++++++++++------ .../kscience/kmath/ast/rendering/stages.kt | 4 + .../kmath/ast/ParserPrecedenceTest.kt | 1 - .../kscience/kmath/ast/rendering/TestUtils.kt | 6 +- .../nonDeclarations.WebAssembly.kt | 3 +- .../kmath/wasm/internal/WasmBuilder.kt | 2 +- .../kotlin/space/kscience/kmath/wasm/wasm.kt | 9 + .../kscience/kmath/asm/internal/AsmBuilder.kt | 4 +- .../kmath/asm/internal/codegenUtils.kt | 2 +- 16 files changed, 259 insertions(+), 100 deletions(-) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index b4a0b28ac..508374d82 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -18,6 +18,10 @@ kotlin.js { } kotlin.sourceSets { + filter { it.name.contains("test", true) } + .map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings) + .forEach { it.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") } + commonMain { dependencies { api("com.github.h0tk3y.betterParse:better-parse:0.4.2") @@ -54,7 +58,7 @@ tasks.dokkaHtml { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt index d2e92c37f..246625d29 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -29,7 +29,6 @@ import space.kscience.kmath.operations.RingOperations * @author Iaroslav Postovalov */ public object ArithmeticsEvaluator : Grammar() { - // TODO replace with "...".toRegex() when better-parse 0.4.1 is released private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?".toRegex()) private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex()) private val lpar: Token by literalToken("(") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 1c82bd6e7..5909f1f9d 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * [SyntaxRenderer] implementation for LaTeX. * @@ -23,6 +25,7 @@ package space.kscience.kmath.ast.rendering * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object LatexSyntaxRenderer : SyntaxRenderer { public override fun render(node: MathSyntax, output: Appendable): Unit = output.run { fun render(syntax: MathSyntax) = render(syntax, output) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index decd4ba46..517ec0dc9 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * [SyntaxRenderer] implementation for MathML. * @@ -12,9 +14,10 @@ package space.kscience.kmath.ast.rendering * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object MathMLSyntaxRenderer : SyntaxRenderer { public override fun render(node: MathSyntax, output: Appendable) { - output.append("") + output.append("") render0(node, output) output.append("") } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index 9df2c54dd..6b22ac519 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -6,12 +6,14 @@ package space.kscience.kmath.ast.rendering import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.UnstableKMathAPI /** * Renders [MST] to [MathSyntax]. * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun interface MathRenderer { /** * Renders [MST] to [MathSyntax]. @@ -25,6 +27,7 @@ public fun interface MathRenderer { * @property features The applied features. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public open class FeaturedMathRenderer(public val features: List) : MathRenderer { public override fun render(mst: MST): MathSyntax { for (feature in features) feature.render(this, mst)?.let { return it } @@ -48,6 +51,7 @@ public open class FeaturedMathRenderer(public val features: List) * @property stages The applied stages. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public open class FeaturedMathRendererWithPostProcess( features: List, public val stages: List, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 6a46bf535..3c023e342 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -5,11 +5,14 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * Mathematical typography syntax node. * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class MathSyntax { /** * The parent node of this syntax node. @@ -22,6 +25,7 @@ public sealed class MathSyntax { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class TerminalSyntax : MathSyntax() /** @@ -29,6 +33,7 @@ public sealed class TerminalSyntax : MathSyntax() * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class OperationSyntax : MathSyntax() { /** * The operation token. @@ -41,6 +46,7 @@ public sealed class OperationSyntax : MathSyntax() { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class UnarySyntax : OperationSyntax() { /** * The operand of this node. @@ -53,6 +59,7 @@ public sealed class UnarySyntax : OperationSyntax() { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class BinarySyntax : OperationSyntax() { /** * The left-hand side operand. @@ -71,6 +78,7 @@ public sealed class BinarySyntax : OperationSyntax() { * @property string The digits of number. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class NumberSyntax(public var string: String) : TerminalSyntax() /** @@ -79,6 +87,7 @@ public data class NumberSyntax(public var string: String) : TerminalSyntax() * @property string The symbol. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SymbolSyntax(public var string: String) : TerminalSyntax() /** @@ -89,6 +98,7 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax() * @see UnaryOperatorSyntax * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() /** @@ -97,6 +107,7 @@ public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() * @property kind The kind of symbol. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() { /** * The kind of symbol. @@ -121,6 +132,7 @@ public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() * @property parentheses Whether the operand should be wrapped with parentheses. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class OperandSyntax( public val operand: MathSyntax, public var parentheses: Boolean, @@ -136,6 +148,7 @@ public data class OperandSyntax( * @property prefix The prefix. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class UnaryOperatorSyntax( public override val operation: String, public var prefix: MathSyntax, @@ -151,6 +164,7 @@ public data class UnaryOperatorSyntax( * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class UnaryPlusSyntax( public override val operation: String, public override val operand: OperandSyntax, @@ -165,6 +179,7 @@ public data class UnaryPlusSyntax( * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class UnaryMinusSyntax( public override val operation: String, public override val operand: OperandSyntax, @@ -180,6 +195,7 @@ public data class UnaryMinusSyntax( * @property operand The radicand. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class RadicalSyntax( public override val operation: String, public override val operand: MathSyntax, @@ -197,6 +213,7 @@ public data class RadicalSyntax( * (*ex*). * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class ExponentSyntax( public override val operation: String, public override val operand: OperandSyntax, @@ -214,6 +231,7 @@ public data class ExponentSyntax( * @property right The superscript. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SuperscriptSyntax( public override val operation: String, public override val left: MathSyntax, @@ -232,6 +250,7 @@ public data class SuperscriptSyntax( * @property right The subscript. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SubscriptSyntax( public override val operation: String, public override val left: MathSyntax, @@ -249,6 +268,7 @@ public data class SubscriptSyntax( * @property prefix The prefix. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class BinaryOperatorSyntax( public override val operation: String, public var prefix: MathSyntax, @@ -268,6 +288,7 @@ public data class BinaryOperatorSyntax( * @param right The addend. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class BinaryPlusSyntax( public override val operation: String, public override val left: OperandSyntax, @@ -286,6 +307,7 @@ public data class BinaryPlusSyntax( * @param right The subtrahend. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class BinaryMinusSyntax( public override val operation: String, public override val left: OperandSyntax, @@ -304,6 +326,7 @@ public data class BinaryMinusSyntax( * @property right The denominator. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class FractionSyntax( public override val operation: String, public override val left: MathSyntax, @@ -322,6 +345,7 @@ public data class FractionSyntax( * @property right The radicand. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class RadicalWithIndexSyntax( public override val operation: String, public override val left: MathSyntax, @@ -341,6 +365,7 @@ public data class RadicalWithIndexSyntax( * @property times whether the times (×) symbol should be used. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class MultiplicationSyntax( public override val operation: String, public override val left: OperandSyntax, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt index 7fa91e158..fb2b3b66f 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt @@ -5,12 +5,15 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should * involve traversal of MathSyntax with handling each its subtype. * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun interface SyntaxRenderer { /** * Renders the [MathSyntax] to [output]. @@ -23,6 +26,7 @@ public fun interface SyntaxRenderer { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String { val sb = StringBuilder() render(node, sb) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index c09282bb6..c1b513345 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.ast.rendering import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.reflect.KClass @@ -15,11 +16,12 @@ import kotlin.reflect.KClass * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object PrintSymbolic : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Symbolic) return null - return SymbolSyntax(string = node.value) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? = + if (node !is MST.Symbolic) null + else + SymbolSyntax(string = node.value) } /** @@ -27,25 +29,25 @@ public object PrintSymbolic : RenderFeature { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object PrintNumeric : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Numeric) return null - return NumberSyntax(string = node.value.toString()) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric) + null + else + NumberSyntax(string = node.value.toString()) } -private fun printSignedNumberString(s: String): MathSyntax { - if (s.startsWith('-')) - return UnaryMinusSyntax( - operation = GroupOperations.MINUS_OPERATION, - operand = OperandSyntax( - operand = NumberSyntax(string = s.removePrefix("-")), - parentheses = true, - ), - ) - - return NumberSyntax(string = s) -} +@UnstableKMathAPI +private fun printSignedNumberString(s: String): MathSyntax = if (s.startsWith('-')) + UnaryMinusSyntax( + operation = GroupOperations.MINUS_OPERATION, + operand = OperandSyntax( + operand = NumberSyntax(string = s.removePrefix("-")), + parentheses = true, + ), + ) +else + NumberSyntax(string = s) /** * Special printing for numeric types which are printed in form of @@ -53,9 +55,11 @@ private fun printSignedNumberString(s: String): MathSyntax { * * @property types The suitable types. */ +@UnstableKMathAPI public class PrettyPrintFloats(public val types: Set>) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Numeric || node.value::class !in types) return null + val toString = when (val v = node.value) { is Float -> v.multiplatformToString() is Double -> v.multiplatformToString() @@ -110,11 +114,13 @@ public class PrettyPrintFloats(public val types: Set>) : Rend * * @property types The suitable types. */ +@UnstableKMathAPI public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Numeric || node.value::class !in types) return null - return printSignedNumberString(node.value.toString()) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? = + if (node !is MST.Numeric || node.value::class !in types) + null + else + printSignedNumberString(node.value.toString()) public companion object { /** @@ -130,11 +136,13 @@ public class PrettyPrintIntegers(public val types: Set>) : Re * * @property symbols The allowed symbols. */ +@UnstableKMathAPI public class PrettyPrintPi(public val symbols: Set) : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Symbolic || node.value !in symbols) return null - return SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? = + if (node !is MST.Symbolic || node.value !in symbols) + null + else + SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI) public companion object { /** @@ -150,16 +158,18 @@ public class PrettyPrintPi(public val symbols: Set) : RenderFeature { * * @param operations the allowed operations. If `null`, any operation is accepted. */ +@UnstableKMathAPI public abstract class Unary(public val operations: Collection?) : RenderFeature { /** - * The actual render function. + * The actual render function specialized for [MST.Unary]. */ - protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax? + protected abstract fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax? - public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Unary || operations != null && node.operation !in operations) return null - return render0(renderer, node) - } + public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? = + if (node !is MST.Unary || operations != null && node.operation !in operations) + null + else + renderUnary(renderer, node) } /** @@ -168,164 +178,258 @@ public abstract class Unary(public val operations: Collection?) : Render * * @property operations the allowed operations. If `null`, any operation is accepted. */ +@UnstableKMathAPI public abstract class Binary(public val operations: Collection?) : RenderFeature { /** - * The actual render function. + * The actual render function specialized for [MST.Binary]. */ - protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax? + protected abstract fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax? public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Binary || operations != null && node.operation !in operations) return null - return render0(renderer, node) + return renderBinary(renderer, node) } } +/** + * Handles binary nodes by producing [BinaryPlusSyntax]. + */ +@UnstableKMathAPI public class BinaryPlus(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax( - operation = node.operation, - left = OperandSyntax(parent.render(node.left), true), - right = OperandSyntax(parent.render(node.right), true), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax = + BinaryPlusSyntax( + operation = node.operation, + left = OperandSyntax(parent.render(node.left), true), + right = OperandSyntax(parent.render(node.right), true), + ) public companion object { + /** + * The default instance configured with [GroupOperations.PLUS_OPERATION]. + */ public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION)) } } +/** + * Handles binary nodes by producing [BinaryMinusSyntax]. + */ +@UnstableKMathAPI public class BinaryMinus(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax( - operation = node.operation, - left = OperandSyntax(operand = parent.render(node.left), parentheses = true), - right = OperandSyntax(operand = parent.render(node.right), parentheses = true), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax = + BinaryMinusSyntax( + operation = node.operation, + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + ) public companion object { + /** + * The default instance configured with [GroupOperations.MINUS_OPERATION]. + */ public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION)) } } +/** + * Handles unary nodes by producing [UnaryPlusSyntax]. + */ +@UnstableKMathAPI public class UnaryPlus(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) public companion object { + /** + * The default instance configured with [GroupOperations.PLUS_OPERATION]. + */ public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION)) } } +/** + * Handles binary nodes by producing [UnaryMinusSyntax]. + */ +@UnstableKMathAPI public class UnaryMinus(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) public companion object { + /** + * The default instance configured with [GroupOperations.MINUS_OPERATION]. + */ public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION)) } } +/** + * Handles binary nodes by producing [FractionSyntax]. + */ +@UnstableKMathAPI public class Fraction(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax( + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax( operation = node.operation, left = parent.render(node.left), right = parent.render(node.right), ) public companion object { + /** + * The default instance configured with [FieldOperations.DIV_OPERATION]. + */ public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION)) } } +/** + * Handles binary nodes by producing [BinaryOperatorSyntax]. + */ +@UnstableKMathAPI public class BinaryOperator(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax( - operation = node.operation, - prefix = OperatorNameSyntax(name = node.operation), - left = parent.render(node.left), - right = parent.render(node.right), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax = + BinaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(name = node.operation), + left = parent.render(node.left), + right = parent.render(node.right), + ) public companion object { + /** + * The default instance configured with `null`. + */ public val Default: BinaryOperator = BinaryOperator(null) } } +/** + * Handles unary nodes by producing [UnaryOperatorSyntax]. + */ +@UnstableKMathAPI public class UnaryOperator(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( - operation = node.operation, - prefix = OperatorNameSyntax(node.operation), - operand = OperandSyntax(parent.render(node.value), true), - ) + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + UnaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(node.operation), + operand = OperandSyntax(parent.render(node.value), true), + ) public companion object { + /** + * The default instance configured with `null`. + */ public val Default: UnaryOperator = UnaryOperator(null) } } +/** + * Handles binary nodes by producing [SuperscriptSyntax]. + */ +@UnstableKMathAPI public class Power(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax( - operation = node.operation, - left = OperandSyntax(parent.render(node.left), true), - right = OperandSyntax(parent.render(node.right), true), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax = + SuperscriptSyntax( + operation = node.operation, + left = OperandSyntax(parent.render(node.left), true), + right = OperandSyntax(parent.render(node.right), true), + ) public companion object { + /** + * The default instance configured with [PowerOperations.POW_OPERATION]. + */ public val Default: Power = Power(setOf(PowerOperations.POW_OPERATION)) } } +/** + * Handles binary nodes by producing [RadicalSyntax] with no index. + */ +@UnstableKMathAPI public class SquareRoot(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): RadicalSyntax = RadicalSyntax(operation = node.operation, operand = parent.render(node.value)) public companion object { + /** + * The default instance configured with [PowerOperations.SQRT_OPERATION]. + */ public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION)) } } +/** + * Handles unary nodes by producing [ExponentSyntax]. + */ +@UnstableKMathAPI public class Exponent(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): ExponentSyntax = ExponentSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), useOperatorForm = true, ) public companion object { + /** + * The default instance configured with [ExponentialOperations.EXP_OPERATION]. + */ public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION)) } } +/** + * Handles binary nodes by producing [MultiplicationSyntax]. + */ +@UnstableKMathAPI public class Multiplication(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = MultiplicationSyntax( - operation = node.operation, - left = OperandSyntax(operand = parent.render(node.left), parentheses = true), - right = OperandSyntax(operand = parent.render(node.right), parentheses = true), - times = true, - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MultiplicationSyntax = + MultiplicationSyntax( + operation = node.operation, + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + times = true, + ) public companion object { - public val Default: Multiplication = Multiplication(setOf( - RingOperations.TIMES_OPERATION, - )) + /** + * The default instance configured with [RingOperations.TIMES_OPERATION]. + */ + public val Default: Multiplication = Multiplication(setOf(RingOperations.TIMES_OPERATION)) } } +/** + * Handles binary nodes by producing inverse [UnaryOperatorSyntax] (like *sin-1*) with removing the `a` + * prefix of operation ID. + */ +@UnstableKMathAPI public class InverseTrigonometricOperations(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( - operation = node.operation, - prefix = SuperscriptSyntax( - operation = PowerOperations.POW_OPERATION, - left = OperatorNameSyntax(name = node.operation.removePrefix("a")), - right = UnaryMinusSyntax( - operation = GroupOperations.MINUS_OPERATION, - operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true), + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + UnaryOperatorSyntax( + operation = node.operation, + prefix = SuperscriptSyntax( + operation = PowerOperations.POW_OPERATION, + left = OperatorNameSyntax(name = node.operation.removePrefix("a")), + right = UnaryMinusSyntax( + operation = GroupOperations.MINUS_OPERATION, + operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true), + ), ), - ), - operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), - ) + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + ) public companion object { + /** + * The default instance configured with [TrigonometricOperations.ACOS_OPERATION], + * [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION], + * [ExponentialOperations.ACOSH_OPERATION], [ExponentialOperations.ASINH_OPERATION], and + * [ExponentialOperations.ATANH_OPERATION]. + */ public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf( TrigonometricOperations.ACOS_OPERATION, TrigonometricOperations.ASIN_OPERATION, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt index a08f089f1..7eb75b9ff 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.PowerOperations @@ -15,6 +16,7 @@ import space.kscience.kmath.operations.RingOperations * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage { public override fun perform(node: MathSyntax): Unit = when (node) { is NumberSyntax -> Unit @@ -88,6 +90,7 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage { private fun perform0(node: MathSyntax): Boolean { return when (node) { @@ -129,6 +132,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt * @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : FeaturedMathRendererWithPostProcess.PostProcessStage { public override fun perform(node: MathSyntax): Unit = when (node) { diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt index ca3a95bc8..67d77839a 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ast -import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.evaluate import space.kscience.kmath.operations.DoubleField import kotlin.test.Test diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt index 7c9400532..bf87b6fd0 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt @@ -30,17 +30,17 @@ internal object TestUtils { ) internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", + expected = "$expectedMathML", actual = mathML(mst), ) internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", + expected = "$expectedMathML", actual = mathML(expression.parseMath()), ) internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", + expected = "$expectedMathML", actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), ) } diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt index 59733299a..c5023c384 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt @@ -3,7 +3,8 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:Suppress("INTERFACE_WITH_SUPERCLASS", +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index bd2b340a0..8fd3c9fb9 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -26,7 +26,7 @@ internal sealed class WasmBuilder( val keys: MutableList = mutableListOf() lateinit var ctx: BinaryenModule - open fun visitSymbolic(mst: MST.Symbolic): ExpressionRef { + open fun visitSymbolic(mst: Symbolic): ExpressionRef { try { algebra.bindSymbol(mst.value) } catch (ignored: Throwable) { diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt index d44c4e49d..394a0567e 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -10,6 +10,7 @@ import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.invoke import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.wasm.internal.DoubleWasmBuilder @@ -20,6 +21,7 @@ import space.kscience.kmath.wasm.internal.IntWasmBuilder * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun DoubleField.expression(mst: MST): Expression = DoubleWasmBuilder(mst).instance @@ -28,6 +30,7 @@ public fun DoubleField.expression(mst: MST): Expression = * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun IntRing.expression(mst: MST): Expression = IntWasmBuilder(mst).instance @@ -36,6 +39,7 @@ public fun IntRing.expression(mst: MST): Expression = * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compileToExpression(algebra: IntRing): Expression = compileWith(algebra) @@ -44,6 +48,7 @@ public fun MST.compileToExpression(algebra: IntRing): Expression = compileW * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: IntRing, arguments: Map): Int = compileToExpression(algebra).invoke(arguments) @@ -53,6 +58,7 @@ public fun MST.compile(algebra: IntRing, arguments: Map): Int = * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: IntRing, vararg arguments: Pair): Int = compileToExpression(algebra)(*arguments) @@ -61,6 +67,7 @@ public fun MST.compile(algebra: IntRing, vararg arguments: Pair): I * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compileToExpression(algebra: DoubleField): Expression = compileWith(algebra) @@ -69,6 +76,7 @@ public fun MST.compileToExpression(algebra: DoubleField): Expression = c * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: DoubleField, arguments: Map): Double = compileToExpression(algebra).invoke(arguments) @@ -78,5 +86,6 @@ public fun MST.compile(algebra: DoubleField, arguments: Map): Do * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: DoubleField, vararg arguments: Pair): Double = compileToExpression(algebra).invoke(*arguments) diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt index bdd8f52b6..39ebf049d 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt @@ -342,8 +342,8 @@ internal class AsmBuilder( val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") } /** - * ASM Type for [kscience.kmath.expressions.Symbol]. + * ASM Type for [space.kscience.kmath.misc.Symbol]. */ - val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") } + val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/misc/Symbol") } } } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt index 560780f99..cfac59847 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt @@ -52,7 +52,7 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.( * * @author Iaroslav Postovalov */ -internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) } +internal fun MethodVisitor.label(): Label = Label().also(::visitLabel) /** * Creates a class name for [Expression] subclassed to implement [mst] provided.