Provide dynamic operations currying for Algebra<T> instead of eager calls and add JS code generation support #162
13
README.md
13
README.md
@ -89,7 +89,16 @@ submit a feature request if you want something to be implemented first.
|
|||||||
* ### [kmath-ast](kmath-ast)
|
* ### [kmath-ast](kmath-ast)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: PROTOTYPE
|
||||||
|
>
|
||||||
|
> **Features:**
|
||||||
|
> - [expression-language](kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||||
|
> - [mst](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
|
||||||
|
> - [mst-building](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
|
||||||
|
> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter
|
||||||
|
> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
|
||||||
|
> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-commons](kmath-commons)
|
* ### [kmath-commons](kmath-commons)
|
||||||
@ -122,7 +131,7 @@ submit a feature request if you want something to be implemented first.
|
|||||||
* ### [kmath-dimensions](kmath-dimensions)
|
* ### [kmath-dimensions](kmath-dimensions)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: PROTOTYPE
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-ejml](kmath-ejml)
|
* ### [kmath-ejml](kmath-ejml)
|
||||||
|
2
docs/templates/ARTIFACT-TEMPLATE.md
vendored
2
docs/templates/ARTIFACT-TEMPLATE.md
vendored
@ -14,7 +14,7 @@
|
|||||||
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
||||||
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
|
>
|
||||||
> }
|
> }
|
||||||
>
|
>
|
||||||
> dependencies {
|
> dependencies {
|
||||||
|
@ -4,13 +4,19 @@ import kscience.kmath.asm.compile
|
|||||||
import kscience.kmath.expressions.Expression
|
import kscience.kmath.expressions.Expression
|
||||||
import kscience.kmath.expressions.expressionInField
|
import kscience.kmath.expressions.expressionInField
|
||||||
import kscience.kmath.expressions.invoke
|
import kscience.kmath.expressions.invoke
|
||||||
|
import kscience.kmath.expressions.symbol
|
||||||
import kscience.kmath.operations.Field
|
import kscience.kmath.operations.Field
|
||||||
import kscience.kmath.operations.RealField
|
import kscience.kmath.operations.RealField
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark
|
||||||
|
import org.openjdk.jmh.annotations.Scope
|
||||||
|
import org.openjdk.jmh.annotations.State
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
import kotlin.system.measureTimeMillis
|
|
||||||
|
|
||||||
|
@State(Scope.Benchmark)
|
||||||
internal class ExpressionsInterpretersBenchmark {
|
internal class ExpressionsInterpretersBenchmark {
|
||||||
private val algebra: Field<Double> = RealField
|
private val algebra: Field<Double> = RealField
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
fun functionalExpression() {
|
fun functionalExpression() {
|
||||||
val expr = algebra.expressionInField {
|
val expr = algebra.expressionInField {
|
||||||
symbol("x") * const(2.0) + const(2.0) / symbol("x") - const(16.0)
|
symbol("x") * const(2.0) + const(2.0) / symbol("x") - const(16.0)
|
||||||
@ -19,6 +25,7 @@ internal class ExpressionsInterpretersBenchmark {
|
|||||||
invokeAndSum(expr)
|
invokeAndSum(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
fun mstExpression() {
|
fun mstExpression() {
|
||||||
val expr = algebra.mstInField {
|
val expr = algebra.mstInField {
|
||||||
symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
|
symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
|
||||||
@ -27,6 +34,7 @@ internal class ExpressionsInterpretersBenchmark {
|
|||||||
invokeAndSum(expr)
|
invokeAndSum(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
fun asmExpression() {
|
fun asmExpression() {
|
||||||
val expr = algebra.mstInField {
|
val expr = algebra.mstInField {
|
||||||
symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
|
symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
|
||||||
@ -35,6 +43,13 @@ internal class ExpressionsInterpretersBenchmark {
|
|||||||
invokeAndSum(expr)
|
invokeAndSum(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun rawExpression() {
|
||||||
|
val x by symbol
|
||||||
|
val expr = Expression<Double> { args -> args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 }
|
||||||
|
invokeAndSum(expr)
|
||||||
|
}
|
||||||
|
|
||||||
private fun invokeAndSum(expr: Expression<Double>) {
|
private fun invokeAndSum(expr: Expression<Double>) {
|
||||||
val random = Random(0)
|
val random = Random(0)
|
||||||
var sum = 0.0
|
var sum = 0.0
|
||||||
@ -46,35 +61,3 @@ internal class ExpressionsInterpretersBenchmark {
|
|||||||
println(sum)
|
println(sum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This benchmark compares basically evaluation of simple function with MstExpression interpreter, ASM backend and
|
|
||||||
* core FunctionalExpressions API.
|
|
||||||
*
|
|
||||||
* The expected rating is:
|
|
||||||
*
|
|
||||||
* 1. ASM.
|
|
||||||
* 2. MST.
|
|
||||||
* 3. FE.
|
|
||||||
*/
|
|
||||||
fun main() {
|
|
||||||
val benchmark = ExpressionsInterpretersBenchmark()
|
|
||||||
|
|
||||||
val fe = measureTimeMillis {
|
|
||||||
benchmark.functionalExpression()
|
|
||||||
}
|
|
||||||
|
|
||||||
println("fe=$fe")
|
|
||||||
|
|
||||||
val mst = measureTimeMillis {
|
|
||||||
benchmark.mstExpression()
|
|
||||||
}
|
|
||||||
|
|
||||||
println("mst=$mst")
|
|
||||||
|
|
||||||
val asm = measureTimeMillis {
|
|
||||||
benchmark.asmExpression()
|
|
||||||
}
|
|
||||||
|
|
||||||
println("asm=$asm")
|
|
||||||
}
|
|
@ -16,17 +16,13 @@ internal class ArrayBenchmark {
|
|||||||
@Benchmark
|
@Benchmark
|
||||||
fun benchmarkBufferRead() {
|
fun benchmarkBufferRead() {
|
||||||
var res = 0
|
var res = 0
|
||||||
for (i in 1..size) res += arrayBuffer.get(
|
for (i in 1..size) res += arrayBuffer[size - i]
|
||||||
size - i
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun nativeBufferRead() {
|
fun nativeBufferRead() {
|
||||||
var res = 0
|
var res = 0
|
||||||
for (i in 1..size) res += nativeBuffer.get(
|
for (i in 1..size) res += nativeBuffer[size - i]
|
||||||
size - i
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -2,43 +2,55 @@
|
|||||||
|
|
||||||
This subproject implements the following features:
|
This subproject implements the following features:
|
||||||
|
|
||||||
- Expression Language and its parser.
|
- [expression-language](src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||||
- MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation.
|
- [mst](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
|
||||||
- Type-safe builder for MST.
|
- [mst-building](src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
|
||||||
- Evaluating expressions by traversing MST.
|
- [mst-interpreter](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter
|
||||||
|
- [mst-jvm-codegen](src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
|
||||||
|
- [mst-js-codegen](src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
|
||||||
|
|
||||||
|
|
||||||
> #### Artifact:
|
> #### Artifact:
|
||||||
> This module is distributed in the artifact `kscience.kmath:kmath-ast:0.1.4-dev-8`.
|
>
|
||||||
|
> This module artifact: `kscience.kmath:kmath-ast:0.2.0-dev-4`.
|
||||||
|
>
|
||||||
|
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ast/_latestVersion)
|
||||||
|
>
|
||||||
|
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-ast/_latestVersion)
|
||||||
>
|
>
|
||||||
> **Gradle:**
|
> **Gradle:**
|
||||||
>
|
>
|
||||||
> ```gradle
|
> ```gradle
|
||||||
> repositories {
|
> repositories {
|
||||||
|
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
|
||||||
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
||||||
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
||||||
> maven { url https://dl.bintray.com/hotkeytlt/maven' }
|
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
|
>
|
||||||
> }
|
> }
|
||||||
>
|
>
|
||||||
> dependencies {
|
> dependencies {
|
||||||
> implementation 'kscience.kmath:kmath-ast:0.1.4-dev-8'
|
> implementation 'kscience.kmath:kmath-ast:0.2.0-dev-4'
|
||||||
> }
|
> }
|
||||||
> ```
|
> ```
|
||||||
> **Gradle Kotlin DSL:**
|
> **Gradle Kotlin DSL:**
|
||||||
>
|
>
|
||||||
> ```kotlin
|
> ```kotlin
|
||||||
> repositories {
|
> repositories {
|
||||||
|
> maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||||
> maven("https://dl.bintray.com/mipt-npm/kscience")
|
> maven("https://dl.bintray.com/mipt-npm/kscience")
|
||||||
> maven("https://dl.bintray.com/mipt-npm/dev")
|
> maven("https://dl.bintray.com/mipt-npm/dev")
|
||||||
> maven("https://dl.bintray.com/hotkeytlt/maven")
|
> maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||||
> }
|
> }
|
||||||
>
|
>
|
||||||
> dependencies {
|
> dependencies {
|
||||||
> implementation("kscience.kmath:kmath-ast:0.1.4-dev-8")
|
> implementation("kscience.kmath:kmath-ast:0.2.0-dev-4")
|
||||||
> }
|
> }
|
||||||
> ```
|
> ```
|
||||||
>
|
|
||||||
|
|
||||||
## Dynamic Expression Code Generation with ObjectWeb ASM
|
## Dynamic expression code generation
|
||||||
|
|
||||||
|
### On JVM
|
||||||
|
|
||||||
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds
|
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds
|
||||||
a special implementation of `Expression<T>` with implemented `invoke` function.
|
a special implementation of `Expression<T>` with implemented `invoke` function.
|
||||||
@ -55,19 +67,20 @@ RealField.mstInField { symbol("x") + 2 }.compile()
|
|||||||
package kscience.kmath.asm.generated;
|
package kscience.kmath.asm.generated;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import kotlin.jvm.functions.Function2;
|
||||||
import kscience.kmath.asm.internal.MapIntrinsics;
|
import kscience.kmath.asm.internal.MapIntrinsics;
|
||||||
import kscience.kmath.expressions.Expression;
|
import kscience.kmath.expressions.Expression;
|
||||||
import kscience.kmath.operations.RealField;
|
import kscience.kmath.expressions.Symbol;
|
||||||
|
|
||||||
public final class AsmCompiledExpression_1073786867_0 implements Expression<Double> {
|
public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||||
private final RealField algebra;
|
private final Object[] constants;
|
||||||
|
|
||||||
public final Double invoke(Map<String, ? extends Double> arguments) {
|
public final Double invoke(Map<Symbol, Double> arguments) {
|
||||||
return (Double)this.algebra.add(((Double)MapIntrinsics.getOrFail(arguments, "x")).doubleValue(), 2.0D);
|
return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsmCompiledExpression_1073786867_0(RealField algebra) {
|
public AsmCompiledExpression_45045_0(Object[] constants) {
|
||||||
this.algebra = algebra;
|
this.constants = constants;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,10 +95,28 @@ RealField.mstInField { symbol("x") + 2 }.compile()
|
|||||||
RealField.expression("x+2".parseMath())
|
RealField.expression("x+2".parseMath())
|
||||||
```
|
```
|
||||||
|
|
||||||
### Known issues
|
#### Known issues
|
||||||
|
|
||||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid
|
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid
|
||||||
class loading overhead.
|
class loading overhead.
|
||||||
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
|
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
|
||||||
|
|
||||||
Contributed by [Iaroslav Postovalov](https://github.com/CommanderTvis).
|
### On JS
|
||||||
|
|
||||||
|
A similar feature is also available on JS.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
RealField.mstInField { symbol("x") + 2 }.compile()
|
||||||
|
```
|
||||||
|
|
||||||
|
The code above returns expression implemented with such a JS function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var executable = function (constants, arguments) {
|
||||||
|
return constants[1](constants[0](arguments, "x"), 2);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Known issues
|
||||||
|
|
||||||
|
- This feature uses `eval` which can be unavailable in several environments.
|
||||||
|
@ -1,7 +1,23 @@
|
|||||||
|
import ru.mipt.npm.gradle.Maturity
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.mpp")
|
id("ru.mipt.npm.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlin.js {
|
||||||
|
nodejs {
|
||||||
|
testTask {
|
||||||
|
useMocha().timeout = "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
browser {
|
||||||
|
testTask {
|
||||||
|
useMocha().timeout = "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -9,15 +25,58 @@ kotlin.sourceSets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jsMain {
|
||||||
|
dependencies {
|
||||||
|
implementation(npm("astring", "1.4.3"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
jvmMain {
|
jvmMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api("com.github.h0tk3y.betterParse:better-parse:0.4.0")
|
api("com.github.h0tk3y.betterParse:better-parse:0.4.0")
|
||||||
implementation("org.ow2.asm:asm:8.0.1")
|
implementation("org.ow2.asm:asm:9.0")
|
||||||
implementation("org.ow2.asm:asm-commons:8.0.1")
|
implementation("org.ow2.asm:asm-commons:9.0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readme{
|
readme {
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
maturity = Maturity.PROTOTYPE
|
||||||
|
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||||
|
|
||||||
|
feature(
|
||||||
|
id = "expression-language",
|
||||||
|
description = "Expression language and its parser",
|
||||||
|
ref = "src/jvmMain/kotlin/kscience/kmath/ast/parser.kt"
|
||||||
|
)
|
||||||
|
|
||||||
|
feature(
|
||||||
|
id = "mst",
|
||||||
|
description = "MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation",
|
||||||
|
ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt"
|
||||||
|
)
|
||||||
|
|
||||||
|
feature(
|
||||||
|
id = "mst-building",
|
||||||
|
description = "MST building algebraic structure",
|
||||||
|
ref = "src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt"
|
||||||
|
)
|
||||||
|
|
||||||
|
feature(
|
||||||
|
id = "mst-interpreter",
|
||||||
|
description = "MST interpreter",
|
||||||
|
ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt"
|
||||||
|
)
|
||||||
|
|
||||||
|
feature(
|
||||||
|
id = "mst-jvm-codegen",
|
||||||
|
description = "Dynamic MST to JVM bytecode compiler",
|
||||||
|
ref = "src/jvmMain/kotlin/kscience/kmath/asm/asm.kt"
|
||||||
|
)
|
||||||
|
|
||||||
|
feature(
|
||||||
|
id = "mst-js-codegen",
|
||||||
|
description = "Dynamic MST to JS compiler",
|
||||||
|
ref = "src/jsMain/kotlin/kscience/kmath/estree/estree.kt"
|
||||||
|
)
|
||||||
}
|
}
|
80
kmath-ast/docs/README-TEMPLATE.md
Normal file
80
kmath-ast/docs/README-TEMPLATE.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# Abstract Syntax Tree Expression Representation and Operations (`kmath-ast`)
|
||||||
|
|
||||||
|
This subproject implements the following features:
|
||||||
|
|
||||||
|
${features}
|
||||||
|
|
||||||
|
${artifact}
|
||||||
|
|
||||||
|
## Dynamic expression code generation
|
||||||
|
|
||||||
|
### On JVM
|
||||||
|
|
||||||
|
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds
|
||||||
|
a special implementation of `Expression<T>` with implemented `invoke` function.
|
||||||
|
|
||||||
|
For example, the following builder:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
RealField.mstInField { symbol("x") + 2 }.compile()
|
||||||
|
```
|
||||||
|
|
||||||
|
… leads to generation of bytecode, which can be decompiled to the following Java class:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package kscience.kmath.asm.generated;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import kotlin.jvm.functions.Function2;
|
||||||
|
import kscience.kmath.asm.internal.MapIntrinsics;
|
||||||
|
import kscience.kmath.expressions.Expression;
|
||||||
|
import kscience.kmath.expressions.Symbol;
|
||||||
|
|
||||||
|
public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||||
|
private final Object[] constants;
|
||||||
|
|
||||||
|
public final Double invoke(Map<Symbol, Double> arguments) {
|
||||||
|
return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsmCompiledExpression_45045_0(Object[] constants) {
|
||||||
|
this.constants = constants;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Usage
|
||||||
|
|
||||||
|
This API extends MST and MstExpression, so you may optimize as both of them:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
RealField.mstInField { symbol("x") + 2 }.compile()
|
||||||
|
RealField.expression("x+2".parseMath())
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Known issues
|
||||||
|
|
||||||
|
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid
|
||||||
|
class loading overhead.
|
||||||
|
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
|
||||||
|
|
||||||
|
### On JS
|
||||||
|
|
||||||
|
A similar feature is also available on JS.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
RealField.mstInField { symbol("x") + 2 }.compile()
|
||||||
|
```
|
||||||
|
|
||||||
|
The code above returns expression implemented with such a JS function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var executable = function (constants, arguments) {
|
||||||
|
return constants[1](constants[0](arguments, "x"), 2);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Known issues
|
||||||
|
|
||||||
|
- This feature uses `eval` which can be unavailable in several environments.
|
@ -55,24 +55,24 @@ public sealed class MST {
|
|||||||
public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
|
public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
|
||||||
is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
|
is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
|
||||||
?: error("Numeric nodes are not supported by $this")
|
?: error("Numeric nodes are not supported by $this")
|
||||||
|
|
||||||
is MST.Symbolic -> symbol(node.value)
|
is MST.Symbolic -> symbol(node.value)
|
||||||
is MST.Unary -> unaryOperation(node.operation, evaluate(node.value))
|
is MST.Unary -> unaryOperationFunction(node.operation)(evaluate(node.value))
|
||||||
|
|
||||||
is MST.Binary -> when {
|
is MST.Binary -> when {
|
||||||
this !is NumericAlgebra -> binaryOperation(node.operation, evaluate(node.left), evaluate(node.right))
|
this !is NumericAlgebra -> binaryOperationFunction(node.operation)(evaluate(node.left), evaluate(node.right))
|
||||||
|
|
||||||
node.left is MST.Numeric && node.right is MST.Numeric -> {
|
node.left is MST.Numeric && node.right is MST.Numeric -> {
|
||||||
val number = RealField.binaryOperation(
|
val number = RealField
|
||||||
node.operation,
|
.binaryOperationFunction(node.operation)
|
||||||
node.left.value.toDouble(),
|
.invoke(node.left.value.toDouble(), node.right.value.toDouble())
|
||||||
node.right.value.toDouble()
|
|
||||||
)
|
|
||||||
|
|
||||||
number(number)
|
number(number)
|
||||||
}
|
}
|
||||||
|
|
||||||
node.left is MST.Numeric -> leftSideNumberOperation(node.operation, node.left.value, evaluate(node.right))
|
node.left is MST.Numeric -> leftSideNumberOperationFunction(node.operation)(node.left.value, evaluate(node.right))
|
||||||
node.right is MST.Numeric -> rightSideNumberOperation(node.operation, evaluate(node.left), node.right.value)
|
node.right is MST.Numeric -> rightSideNumberOperationFunction(node.operation)(evaluate(node.left), node.right.value)
|
||||||
else -> binaryOperation(node.operation, evaluate(node.left), evaluate(node.right))
|
else -> binaryOperationFunction(node.operation)(evaluate(node.left), evaluate(node.right))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,53 +6,64 @@ import kscience.kmath.operations.*
|
|||||||
* [Algebra] over [MST] nodes.
|
* [Algebra] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstAlgebra : NumericAlgebra<MST> {
|
public object MstAlgebra : NumericAlgebra<MST> {
|
||||||
override fun number(value: Number): MST.Numeric = MST.Numeric(value)
|
public override fun number(value: Number): MST.Numeric = MST.Numeric(value)
|
||||||
|
public override fun symbol(value: String): MST.Symbolic = MST.Symbolic(value)
|
||||||
|
|
||||||
override fun symbol(value: String): MST.Symbolic = MST.Symbolic(value)
|
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
|
||||||
|
{ arg -> MST.Unary(operation, arg) }
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: MST): MST.Unary =
|
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
||||||
MST.Unary(operation, arg)
|
{ left, right -> MST.Binary(operation, left, right) }
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary =
|
|
||||||
MST.Binary(operation, left, right)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [Space] over [MST] nodes.
|
* [Space] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
public object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
||||||
override val zero: MST.Numeric by lazy { number(0.0) }
|
public override val zero: MST.Numeric by lazy { number(0.0) }
|
||||||
|
|
||||||
override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
|
public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
|
||||||
override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value)
|
public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value)
|
||||||
override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION, a, b)
|
public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b)
|
||||||
override fun multiply(a: MST, k: Number): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION, a, number(k))
|
public override operator fun MST.unaryPlus(): MST.Unary = unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this)
|
||||||
|
public override operator fun MST.unaryMinus(): MST.Unary = unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this)
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary =
|
public override operator fun MST.minus(b: MST): MST.Binary =
|
||||||
MstAlgebra.binaryOperation(operation, left, right)
|
binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b)
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstAlgebra.unaryOperation(operation, arg)
|
public override fun multiply(a: MST, k: Number): MST.Binary =
|
||||||
|
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(k))
|
||||||
|
|
||||||
|
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
||||||
|
MstAlgebra.binaryOperationFunction(operation)
|
||||||
|
|
||||||
|
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
|
||||||
|
MstAlgebra.unaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [Ring] over [MST] nodes.
|
* [Ring] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
public object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
||||||
override val zero: MST.Numeric
|
public override val zero: MST.Numeric
|
||||||
get() = MstSpace.zero
|
get() = MstSpace.zero
|
||||||
|
|
||||||
override val one: MST.Numeric by lazy { number(1.0) }
|
public override val one: MST.Numeric by lazy { number(1.0) }
|
||||||
|
|
||||||
override fun number(value: Number): MST.Numeric = MstSpace.number(value)
|
public override fun number(value: Number): MST.Numeric = MstSpace.number(value)
|
||||||
override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value)
|
public override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value)
|
||||||
override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b)
|
public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b)
|
||||||
override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k)
|
public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k)
|
||||||
override fun multiply(a: MST, b: MST): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION, a, b)
|
public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b)
|
||||||
|
public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus }
|
||||||
|
public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus }
|
||||||
|
public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b }
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary =
|
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
||||||
MstSpace.binaryOperation(operation, left, right)
|
MstSpace.binaryOperationFunction(operation)
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstSpace.unaryOperation(operation, arg)
|
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
|
||||||
|
MstAlgebra.unaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,51 +81,56 @@ public object MstField : Field<MST> {
|
|||||||
public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b)
|
public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b)
|
||||||
public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k)
|
public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k)
|
||||||
public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b)
|
public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b)
|
||||||
public override fun divide(a: MST, b: MST): MST.Binary = binaryOperation(FieldOperations.DIV_OPERATION, a, b)
|
public override fun divide(a: MST, b: MST): MST.Binary = binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b)
|
||||||
|
public override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus }
|
||||||
|
public override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus }
|
||||||
|
public override operator fun MST.minus(b: MST): MST.Binary = MstRing { this@minus - b }
|
||||||
|
|
||||||
public override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary =
|
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
||||||
MstRing.binaryOperation(operation, left, right)
|
MstRing.binaryOperationFunction(operation)
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstRing.unaryOperation(operation, arg)
|
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstRing.unaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [ExtendedField] over [MST] nodes.
|
* [ExtendedField] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstExtendedField : ExtendedField<MST> {
|
public object MstExtendedField : ExtendedField<MST> {
|
||||||
override val zero: MST.Numeric
|
public override val zero: MST.Numeric
|
||||||
get() = MstField.zero
|
get() = MstField.zero
|
||||||
|
|
||||||
override val one: MST.Numeric
|
public override val one: MST.Numeric
|
||||||
get() = MstField.one
|
get() = MstField.one
|
||||||
|
|
||||||
override fun symbol(value: String): MST.Symbolic = MstField.symbol(value)
|
public override fun symbol(value: String): MST.Symbolic = MstField.symbol(value)
|
||||||
override fun number(value: Number): MST.Numeric = MstField.number(value)
|
public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
|
||||||
override fun sin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg)
|
public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg)
|
||||||
override fun cos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.COS_OPERATION, arg)
|
public override fun tan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.TAN_OPERATION)(arg)
|
||||||
override fun tan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.TAN_OPERATION, arg)
|
public override fun asin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ASIN_OPERATION)(arg)
|
||||||
override fun asin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg)
|
public override fun acos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ACOS_OPERATION)(arg)
|
||||||
override fun acos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg)
|
public override fun atan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ATAN_OPERATION)(arg)
|
||||||
override fun atan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg)
|
public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.SINH_OPERATION)(arg)
|
||||||
override fun sinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.SINH_OPERATION, arg)
|
public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.COSH_OPERATION)(arg)
|
||||||
override fun cosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.COSH_OPERATION, arg)
|
public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.TANH_OPERATION)(arg)
|
||||||
override fun tanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.TANH_OPERATION, arg)
|
public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ASINH_OPERATION)(arg)
|
||||||
override fun asinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ASINH_OPERATION, arg)
|
public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ACOSH_OPERATION)(arg)
|
||||||
override fun acosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ACOSH_OPERATION, arg)
|
public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ATANH_OPERATION)(arg)
|
||||||
override fun atanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ATANH_OPERATION, arg)
|
public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
|
||||||
override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
|
public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k)
|
||||||
override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k)
|
public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b)
|
||||||
override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b)
|
public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b)
|
||||||
override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b)
|
public override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus }
|
||||||
|
public override operator fun MST.unaryMinus(): MST.Unary = MstField { -this@unaryMinus }
|
||||||
|
public override operator fun MST.minus(b: MST): MST.Binary = MstField { this@minus - b }
|
||||||
|
|
||||||
override fun power(arg: MST, pow: Number): MST.Binary =
|
public override fun power(arg: MST, pow: Number): MST.Binary =
|
||||||
binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow))
|
binaryOperationFunction(PowerOperations.POW_OPERATION)(arg, number(pow))
|
||||||
|
|
||||||
override fun exp(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.EXP_OPERATION, arg)
|
public override fun exp(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.EXP_OPERATION)(arg)
|
||||||
override fun ln(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.LN_OPERATION, arg)
|
public override fun ln(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.LN_OPERATION)(arg)
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary =
|
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
||||||
MstField.binaryOperation(operation, left, right)
|
MstField.binaryOperationFunction(operation)
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstField.unaryOperation(operation, arg)
|
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstField.unaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,14 @@ import kotlin.contracts.contract
|
|||||||
*/
|
*/
|
||||||
public class MstExpression<T, out A : Algebra<T>>(public val algebra: A, public val mst: MST) : Expression<T> {
|
public class MstExpression<T, out A : Algebra<T>>(public val algebra: A, public val mst: MST) : Expression<T> {
|
||||||
private inner class InnerAlgebra(val arguments: Map<Symbol, T>) : NumericAlgebra<T> {
|
private inner class InnerAlgebra(val arguments: Map<Symbol, T>) : NumericAlgebra<T> {
|
||||||
override fun symbol(value: String): T = arguments[StringSymbol(value)] ?: algebra.symbol(value)
|
override fun symbol(value: String): T = try {
|
||||||
override fun unaryOperation(operation: String, arg: T): T = algebra.unaryOperation(operation, arg)
|
algebra.symbol(value)
|
||||||
|
} catch (ignored: IllegalStateException) {
|
||||||
|
null
|
||||||
|
} ?: arguments.getValue(StringSymbol(value))
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: T, right: T): T =
|
override fun unaryOperationFunction(operation: String): (arg: T) -> T = algebra.unaryOperationFunction(operation)
|
||||||
algebra.binaryOperation(operation, left, right)
|
override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = algebra.binaryOperationFunction(operation)
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun number(value: Number): T = if (algebra is NumericAlgebra<*>)
|
override fun number(value: Number): T = if (algebra is NumericAlgebra<*>)
|
||||||
|
78
kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt
Normal file
78
kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package kscience.kmath.estree
|
||||||
|
|
||||||
|
import kscience.kmath.ast.MST
|
||||||
|
import kscience.kmath.ast.MstExpression
|
||||||
|
import kscience.kmath.estree.internal.ESTreeBuilder
|
||||||
|
import kscience.kmath.estree.internal.estree.BaseExpression
|
||||||
|
import kscience.kmath.expressions.Expression
|
||||||
|
import kscience.kmath.operations.Algebra
|
||||||
|
import kscience.kmath.operations.NumericAlgebra
|
||||||
|
import kscience.kmath.operations.RealField
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> {
|
||||||
|
fun ESTreeBuilder<T>.visit(node: MST): BaseExpression = when (node) {
|
||||||
|
is MST.Symbolic -> {
|
||||||
|
val symbol = try {
|
||||||
|
algebra.symbol(node.value)
|
||||||
|
} catch (ignored: IllegalStateException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symbol != null)
|
||||||
|
constant(symbol)
|
||||||
|
else
|
||||||
|
variable(node.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
is MST.Numeric -> constant(node.value)
|
||||||
|
is MST.Unary -> call(algebra.unaryOperationFunction(node.operation), visit(node.value))
|
||||||
|
|
||||||
|
is MST.Binary -> when {
|
||||||
|
algebra is NumericAlgebra<T> && node.left is MST.Numeric && node.right is MST.Numeric -> constant(
|
||||||
|
algebra.number(
|
||||||
|
RealField
|
||||||
|
.binaryOperationFunction(node.operation)
|
||||||
|
.invoke(node.left.value.toDouble(), node.right.value.toDouble())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
algebra is NumericAlgebra<T> && node.left is MST.Numeric -> call(
|
||||||
|
algebra.leftSideNumberOperationFunction(node.operation),
|
||||||
|
visit(node.left),
|
||||||
|
visit(node.right),
|
||||||
|
)
|
||||||
|
|
||||||
|
algebra is NumericAlgebra<T> && node.right is MST.Numeric -> call(
|
||||||
|
algebra.rightSideNumberOperationFunction(node.operation),
|
||||||
|
visit(node.left),
|
||||||
|
visit(node.right),
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> call(
|
||||||
|
algebra.binaryOperationFunction(node.operation),
|
||||||
|
visit(node.left),
|
||||||
|
visit(node.right),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESTreeBuilder<T> { visit(this@compileWith) }.instance
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles an [MST] to ESTree generated expression using given algebra.
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik.
|
||||||
|
*/
|
||||||
|
public fun <T : Any> Algebra<T>.expression(mst: MST): Expression<T> =
|
||||||
|
mst.compileWith(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimizes performance of an [MstExpression] by compiling it into ESTree generated expression.
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik.
|
||||||
|
*/
|
||||||
|
public fun <T : Any> MstExpression<T, Algebra<T>>.compile(): Expression<T> =
|
||||||
|
mst.compileWith(algebra)
|
@ -0,0 +1,79 @@
|
|||||||
|
package kscience.kmath.estree.internal
|
||||||
|
|
||||||
|
import kscience.kmath.estree.internal.astring.generate
|
||||||
|
import kscience.kmath.estree.internal.estree.*
|
||||||
|
import kscience.kmath.expressions.Expression
|
||||||
|
import kscience.kmath.expressions.Symbol
|
||||||
|
|
||||||
|
internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) {
|
||||||
|
private class GeneratedExpression<T>(val executable: dynamic, val constants: Array<dynamic>) : Expression<T> {
|
||||||
|
@Suppress("UNUSED_VARIABLE")
|
||||||
|
override fun invoke(arguments: Map<Symbol, T>): T {
|
||||||
|
val e = executable
|
||||||
|
val c = constants
|
||||||
|
val a = js("{}")
|
||||||
|
arguments.forEach { (key, value) -> a[key.identity] = value }
|
||||||
|
return js("e(c, a)").unsafeCast<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val instance: Expression<T> by lazy {
|
||||||
|
val node = Program(
|
||||||
|
sourceType = "script",
|
||||||
|
VariableDeclaration(
|
||||||
|
kind = "var",
|
||||||
|
VariableDeclarator(
|
||||||
|
id = Identifier("executable"),
|
||||||
|
init = FunctionExpression(
|
||||||
|
params = arrayOf(Identifier("constants"), Identifier("arguments")),
|
||||||
|
body = BlockStatement(ReturnStatement(bodyCallback())),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
eval(generate(node))
|
||||||
|
GeneratedExpression(js("executable"), constants.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
private val constants = mutableListOf<Any>()
|
||||||
|
|
||||||
|
fun constant(value: Any?) = when {
|
||||||
|
value == null || jsTypeOf(value) == "number" || jsTypeOf(value) == "string" || jsTypeOf(value) == "boolean" ->
|
||||||
|
SimpleLiteral(value)
|
||||||
|
|
||||||
|
jsTypeOf(value) == "undefined" -> Identifier("undefined")
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val idx = if (value in constants) constants.indexOf(value) else constants.also { it += value }.lastIndex
|
||||||
|
|
||||||
|
MemberExpression(
|
||||||
|
computed = true,
|
||||||
|
optional = false,
|
||||||
|
`object` = Identifier("constants"),
|
||||||
|
property = SimpleLiteral(idx),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun variable(name: String): BaseExpression = call(getOrFail, Identifier("arguments"), SimpleLiteral(name))
|
||||||
|
|
||||||
|
fun call(function: Function<T>, vararg args: BaseExpression): BaseExpression = SimpleCallExpression(
|
||||||
|
optional = false,
|
||||||
|
callee = constant(function),
|
||||||
|
*args,
|
||||||
|
)
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
@Suppress("UNUSED_VARIABLE")
|
||||||
|
val getOrFail: (`object`: dynamic, key: String) -> dynamic = { `object`, key ->
|
||||||
|
val k = key
|
||||||
|
val o = `object`
|
||||||
|
|
||||||
|
if (!(js("k in o") as Boolean))
|
||||||
|
throw NoSuchElementException("Key $key is missing in the map.")
|
||||||
|
|
||||||
|
js("o[k]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
@file:JsModule("astring")
|
||||||
|
@file:JsNonModule
|
||||||
|
|
||||||
|
package kscience.kmath.estree.internal.astring
|
||||||
|
|
||||||
|
import kscience.kmath.estree.internal.estree.BaseNode
|
||||||
|
|
||||||
|
internal external interface Options {
|
||||||
|
var indent: String?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var lineEnd: String?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var startingIndentLevel: Number?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var comments: Boolean?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var generator: Any?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var sourceMap: Any?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external fun generate(node: BaseNode, options: Options /* Options & `T$0` */ = definedExternally): String
|
||||||
|
|
||||||
|
internal external fun generate(node: BaseNode): String
|
||||||
|
|
||||||
|
internal external var baseGenerator: Generator
|
@ -0,0 +1,3 @@
|
|||||||
|
package kscience.kmath.estree.internal.astring
|
||||||
|
|
||||||
|
internal typealias Generator = Any
|
@ -0,0 +1,13 @@
|
|||||||
|
package kscience.kmath.estree.internal.emitter
|
||||||
|
|
||||||
|
internal open external class Emitter {
|
||||||
|
constructor(obj: Any)
|
||||||
|
constructor()
|
||||||
|
|
||||||
|
open fun on(event: String, fn: () -> Unit)
|
||||||
|
open fun off(event: String, fn: () -> Unit)
|
||||||
|
open fun once(event: String, fn: () -> Unit)
|
||||||
|
open fun emit(event: String, vararg any: Any)
|
||||||
|
open fun listeners(event: String): Array<() -> Unit>
|
||||||
|
open fun hasListeners(event: String): Boolean
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package kscience.kmath.estree.internal.estree
|
||||||
|
|
||||||
|
internal fun Program(sourceType: String, vararg body: dynamic) = object : Program {
|
||||||
|
override var type = "Program"
|
||||||
|
override var sourceType = sourceType
|
||||||
|
override var body = body
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun VariableDeclaration(kind: String, vararg declarations: VariableDeclarator) = object : VariableDeclaration {
|
||||||
|
override var type = "VariableDeclaration"
|
||||||
|
override var declarations = declarations.toList().toTypedArray()
|
||||||
|
override var kind = kind
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun VariableDeclarator(id: dynamic, init: dynamic) = object : VariableDeclarator {
|
||||||
|
override var type = "VariableDeclarator"
|
||||||
|
override var id = id
|
||||||
|
override var init = init
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun Identifier(name: String) = object : Identifier {
|
||||||
|
override var type = "Identifier"
|
||||||
|
override var name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun FunctionExpression(params: Array<dynamic>, body: BlockStatement) = object : FunctionExpression {
|
||||||
|
override var params = params
|
||||||
|
override var type = "FunctionExpression"
|
||||||
|
override var body = body
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun BlockStatement(vararg body: dynamic) = object : BlockStatement {
|
||||||
|
override var type = "BlockStatement"
|
||||||
|
override var body = body
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun ReturnStatement(argument: dynamic) = object : ReturnStatement {
|
||||||
|
override var type = "ReturnStatement"
|
||||||
|
override var argument = argument
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun SimpleLiteral(value: dynamic) = object : SimpleLiteral {
|
||||||
|
override var type = "Literal"
|
||||||
|
override var value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun MemberExpression(computed: Boolean, optional: Boolean, `object`: dynamic, property: dynamic) =
|
||||||
|
object : MemberExpression {
|
||||||
|
override var type = "MemberExpression"
|
||||||
|
override var computed = computed
|
||||||
|
override var optional = optional
|
||||||
|
override var `object` = `object`
|
||||||
|
override var property = property
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun SimpleCallExpression(optional: Boolean, callee: dynamic, vararg arguments: dynamic) =
|
||||||
|
object : SimpleCallExpression {
|
||||||
|
override var type = "CallExpression"
|
||||||
|
override var optional = optional
|
||||||
|
override var callee = callee
|
||||||
|
override var arguments = arguments
|
||||||
|
}
|
@ -0,0 +1,644 @@
|
|||||||
|
package kscience.kmath.estree.internal.estree
|
||||||
|
|
||||||
|
import kotlin.js.RegExp
|
||||||
|
|
||||||
|
internal external interface BaseNodeWithoutComments {
|
||||||
|
var type: String
|
||||||
|
var loc: SourceLocation?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var range: dynamic /* JsTuple<Number, Number> */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BaseNode : BaseNodeWithoutComments {
|
||||||
|
var leadingComments: Array<Comment>?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var trailingComments: Array<Comment>?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface Comment : BaseNodeWithoutComments {
|
||||||
|
override var type: String /* "Line" | "Block" */
|
||||||
|
var value: String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface SourceLocation {
|
||||||
|
var source: String?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var start: Position
|
||||||
|
var end: Position
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface Position {
|
||||||
|
var line: Number
|
||||||
|
var column: Number
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface Program : BaseNode {
|
||||||
|
override var type: String /* "Program" */
|
||||||
|
var sourceType: String /* "script" | "module" */
|
||||||
|
var body: Array<dynamic /* Directive | ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration | ImportDeclaration | ExportNamedDeclaration | ExportDefaultDeclaration | ExportAllDeclaration */>
|
||||||
|
var comments: Array<Comment>?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface Directive : BaseNode {
|
||||||
|
override var type: String /* "ExpressionStatement" */
|
||||||
|
var expression: dynamic /* SimpleLiteral | RegExpLiteral */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var directive: String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BaseFunction : BaseNode {
|
||||||
|
var params: Array<dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */>
|
||||||
|
var generator: Boolean?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var async: Boolean?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var body: dynamic /* BlockStatement | ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BaseStatement : BaseNode
|
||||||
|
|
||||||
|
internal external interface EmptyStatement : BaseStatement {
|
||||||
|
override var type: String /* "EmptyStatement" */
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BlockStatement : BaseStatement {
|
||||||
|
override var type: String /* "BlockStatement" */
|
||||||
|
var body: Array<dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */>
|
||||||
|
var innerComments: Array<Comment>?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ExpressionStatement : BaseStatement {
|
||||||
|
override var type: String /* "ExpressionStatement" */
|
||||||
|
var expression: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface IfStatement : BaseStatement {
|
||||||
|
override var type: String /* "IfStatement" */
|
||||||
|
var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var consequent: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var alternate: dynamic /* ExpressionStatement? | BlockStatement? | EmptyStatement? | DebuggerStatement? | WithStatement? | ReturnStatement? | LabeledStatement? | BreakStatement? | ContinueStatement? | IfStatement? | SwitchStatement? | ThrowStatement? | TryStatement? | WhileStatement? | DoWhileStatement? | ForStatement? | ForInStatement? | ForOfStatement? | FunctionDeclaration? | VariableDeclaration? | ClassDeclaration? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface LabeledStatement : BaseStatement {
|
||||||
|
override var type: String /* "LabeledStatement" */
|
||||||
|
var label: Identifier
|
||||||
|
var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BreakStatement : BaseStatement {
|
||||||
|
override var type: String /* "BreakStatement" */
|
||||||
|
var label: Identifier?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ContinueStatement : BaseStatement {
|
||||||
|
override var type: String /* "ContinueStatement" */
|
||||||
|
var label: Identifier?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface WithStatement : BaseStatement {
|
||||||
|
override var type: String /* "WithStatement" */
|
||||||
|
var `object`: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface SwitchStatement : BaseStatement {
|
||||||
|
override var type: String /* "SwitchStatement" */
|
||||||
|
var discriminant: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var cases: Array<SwitchCase>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ReturnStatement : BaseStatement {
|
||||||
|
override var type: String /* "ReturnStatement" */
|
||||||
|
var argument: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ThrowStatement : BaseStatement {
|
||||||
|
override var type: String /* "ThrowStatement" */
|
||||||
|
var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface TryStatement : BaseStatement {
|
||||||
|
override var type: String /* "TryStatement" */
|
||||||
|
var block: BlockStatement
|
||||||
|
var handler: CatchClause?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var finalizer: BlockStatement?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface WhileStatement : BaseStatement {
|
||||||
|
override var type: String /* "WhileStatement" */
|
||||||
|
var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface DoWhileStatement : BaseStatement {
|
||||||
|
override var type: String /* "DoWhileStatement" */
|
||||||
|
var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ForStatement : BaseStatement {
|
||||||
|
override var type: String /* "ForStatement" */
|
||||||
|
var init: dynamic /* VariableDeclaration? | ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var test: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var update: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BaseForXStatement : BaseStatement {
|
||||||
|
var left: dynamic /* VariableDeclaration | Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ForInStatement : BaseForXStatement {
|
||||||
|
override var type: String /* "ForInStatement" */
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface DebuggerStatement : BaseStatement {
|
||||||
|
override var type: String /* "DebuggerStatement" */
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BaseDeclaration : BaseStatement
|
||||||
|
|
||||||
|
internal external interface FunctionDeclaration : BaseFunction, BaseDeclaration {
|
||||||
|
override var type: String /* "FunctionDeclaration" */
|
||||||
|
var id: Identifier?
|
||||||
|
override var body: BlockStatement
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface VariableDeclaration : BaseDeclaration {
|
||||||
|
override var type: String /* "VariableDeclaration" */
|
||||||
|
var declarations: Array<VariableDeclarator>
|
||||||
|
var kind: String /* "var" | "let" | "const" */
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface VariableDeclarator : BaseNode {
|
||||||
|
override var type: String /* "VariableDeclarator" */
|
||||||
|
var id: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var init: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BaseExpression : BaseNode
|
||||||
|
|
||||||
|
internal external interface ChainExpression : BaseExpression {
|
||||||
|
override var type: String /* "ChainExpression" */
|
||||||
|
var expression: dynamic /* SimpleCallExpression | MemberExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ThisExpression : BaseExpression {
|
||||||
|
override var type: String /* "ThisExpression" */
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ArrayExpression : BaseExpression {
|
||||||
|
override var type: String /* "ArrayExpression" */
|
||||||
|
var elements: Array<dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | SpreadElement */>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ObjectExpression : BaseExpression {
|
||||||
|
override var type: String /* "ObjectExpression" */
|
||||||
|
var properties: Array<dynamic /* Property | SpreadElement */>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface Property : BaseNode {
|
||||||
|
override var type: String /* "Property" */
|
||||||
|
var key: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var value: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var kind: String /* "init" | "get" | "set" */
|
||||||
|
var method: Boolean
|
||||||
|
var shorthand: Boolean
|
||||||
|
var computed: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface FunctionExpression : BaseFunction, BaseExpression {
|
||||||
|
var id: Identifier?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
override var type: String /* "FunctionExpression" */
|
||||||
|
override var body: BlockStatement
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface SequenceExpression : BaseExpression {
|
||||||
|
override var type: String /* "SequenceExpression" */
|
||||||
|
var expressions: Array<dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface UnaryExpression : BaseExpression {
|
||||||
|
override var type: String /* "UnaryExpression" */
|
||||||
|
var operator: String /* "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" */
|
||||||
|
var prefix: Boolean
|
||||||
|
var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BinaryExpression : BaseExpression {
|
||||||
|
override var type: String /* "BinaryExpression" */
|
||||||
|
var operator: String /* "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**" | "|" | "^" | "&" | "in" | "instanceof" */
|
||||||
|
var left: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface AssignmentExpression : BaseExpression {
|
||||||
|
override var type: String /* "AssignmentExpression" */
|
||||||
|
var operator: String /* "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" */
|
||||||
|
var left: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface UpdateExpression : BaseExpression {
|
||||||
|
override var type: String /* "UpdateExpression" */
|
||||||
|
var operator: String /* "++" | "--" */
|
||||||
|
var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var prefix: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface LogicalExpression : BaseExpression {
|
||||||
|
override var type: String /* "LogicalExpression" */
|
||||||
|
var operator: String /* "||" | "&&" | "??" */
|
||||||
|
var left: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ConditionalExpression : BaseExpression {
|
||||||
|
override var type: String /* "ConditionalExpression" */
|
||||||
|
var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var alternate: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var consequent: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BaseCallExpression : BaseExpression {
|
||||||
|
var callee: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | Super */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var arguments: Array<dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | SpreadElement */>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface SimpleCallExpression : BaseCallExpression {
|
||||||
|
override var type: String /* "CallExpression" */
|
||||||
|
var optional: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface NewExpression : BaseCallExpression {
|
||||||
|
override var type: String /* "NewExpression" */
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface MemberExpression : BaseExpression, BasePattern {
|
||||||
|
override var type: String /* "MemberExpression" */
|
||||||
|
var `object`: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | Super */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var property: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var computed: Boolean
|
||||||
|
var optional: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BasePattern : BaseNode
|
||||||
|
|
||||||
|
internal external interface SwitchCase : BaseNode {
|
||||||
|
override var type: String /* "SwitchCase" */
|
||||||
|
var test: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var consequent: Array<dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface CatchClause : BaseNode {
|
||||||
|
override var type: String /* "CatchClause" */
|
||||||
|
var param: dynamic /* Identifier? | ObjectPattern? | ArrayPattern? | RestElement? | AssignmentPattern? | MemberExpression? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var body: BlockStatement
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface Identifier : BaseNode, BaseExpression, BasePattern {
|
||||||
|
override var type: String /* "Identifier" */
|
||||||
|
var name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface SimpleLiteral : BaseNode, BaseExpression {
|
||||||
|
override var type: String /* "Literal" */
|
||||||
|
var value: dynamic /* String? | Boolean? | Number? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var raw: String?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface `T$1` {
|
||||||
|
var pattern: String
|
||||||
|
var flags: String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface RegExpLiteral : BaseNode, BaseExpression {
|
||||||
|
override var type: String /* "Literal" */
|
||||||
|
var value: RegExp?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var regex: `T$1`
|
||||||
|
var raw: String?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ForOfStatement : BaseForXStatement {
|
||||||
|
override var type: String /* "ForOfStatement" */
|
||||||
|
var await: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface Super : BaseNode {
|
||||||
|
override var type: String /* "Super" */
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface SpreadElement : BaseNode {
|
||||||
|
override var type: String /* "SpreadElement" */
|
||||||
|
var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ArrowFunctionExpression : BaseExpression, BaseFunction {
|
||||||
|
override var type: String /* "ArrowFunctionExpression" */
|
||||||
|
var expression: Boolean
|
||||||
|
override var body: dynamic /* BlockStatement | ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface YieldExpression : BaseExpression {
|
||||||
|
override var type: String /* "YieldExpression" */
|
||||||
|
var argument: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var delegate: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface TemplateLiteral : BaseExpression {
|
||||||
|
override var type: String /* "TemplateLiteral" */
|
||||||
|
var quasis: Array<TemplateElement>
|
||||||
|
var expressions: Array<dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface TaggedTemplateExpression : BaseExpression {
|
||||||
|
override var type: String /* "TaggedTemplateExpression" */
|
||||||
|
var tag: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var quasi: TemplateLiteral
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface `T$2` {
|
||||||
|
var cooked: String
|
||||||
|
var raw: String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface TemplateElement : BaseNode {
|
||||||
|
override var type: String /* "TemplateElement" */
|
||||||
|
var tail: Boolean
|
||||||
|
var value: `T$2`
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface AssignmentProperty : Property {
|
||||||
|
override var value: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
override var kind: String /* "init" */
|
||||||
|
override var method: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ObjectPattern : BasePattern {
|
||||||
|
override var type: String /* "ObjectPattern" */
|
||||||
|
var properties: Array<dynamic /* AssignmentProperty | RestElement */>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ArrayPattern : BasePattern {
|
||||||
|
override var type: String /* "ArrayPattern" */
|
||||||
|
var elements: Array<dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface RestElement : BasePattern {
|
||||||
|
override var type: String /* "RestElement" */
|
||||||
|
var argument: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface AssignmentPattern : BasePattern {
|
||||||
|
override var type: String /* "AssignmentPattern" */
|
||||||
|
var left: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BaseClass : BaseNode {
|
||||||
|
var superClass: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var body: ClassBody
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ClassBody : BaseNode {
|
||||||
|
override var type: String /* "ClassBody" */
|
||||||
|
var body: Array<MethodDefinition>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface MethodDefinition : BaseNode {
|
||||||
|
override var type: String /* "MethodDefinition" */
|
||||||
|
var key: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var value: FunctionExpression
|
||||||
|
var kind: String /* "constructor" | "method" | "get" | "set" */
|
||||||
|
var computed: Boolean
|
||||||
|
var static: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ClassDeclaration : BaseClass, BaseDeclaration {
|
||||||
|
override var type: String /* "ClassDeclaration" */
|
||||||
|
var id: Identifier?
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ClassExpression : BaseClass, BaseExpression {
|
||||||
|
override var type: String /* "ClassExpression" */
|
||||||
|
var id: Identifier?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface MetaProperty : BaseExpression {
|
||||||
|
override var type: String /* "MetaProperty" */
|
||||||
|
var meta: Identifier
|
||||||
|
var property: Identifier
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface BaseModuleDeclaration : BaseNode
|
||||||
|
|
||||||
|
internal external interface BaseModuleSpecifier : BaseNode {
|
||||||
|
var local: Identifier
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ImportDeclaration : BaseModuleDeclaration {
|
||||||
|
override var type: String /* "ImportDeclaration" */
|
||||||
|
var specifiers: Array<dynamic /* ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier */>
|
||||||
|
var source: dynamic /* SimpleLiteral | RegExpLiteral */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ImportSpecifier : BaseModuleSpecifier {
|
||||||
|
override var type: String /* "ImportSpecifier" */
|
||||||
|
var imported: Identifier
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ImportExpression : BaseExpression {
|
||||||
|
override var type: String /* "ImportExpression" */
|
||||||
|
var source: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ImportDefaultSpecifier : BaseModuleSpecifier {
|
||||||
|
override var type: String /* "ImportDefaultSpecifier" */
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ImportNamespaceSpecifier : BaseModuleSpecifier {
|
||||||
|
override var type: String /* "ImportNamespaceSpecifier" */
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ExportNamedDeclaration : BaseModuleDeclaration {
|
||||||
|
override var type: String /* "ExportNamedDeclaration" */
|
||||||
|
var declaration: dynamic /* FunctionDeclaration? | VariableDeclaration? | ClassDeclaration? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var specifiers: Array<ExportSpecifier>
|
||||||
|
var source: dynamic /* SimpleLiteral? | RegExpLiteral? */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ExportSpecifier : BaseModuleSpecifier {
|
||||||
|
override var type: String /* "ExportSpecifier" */
|
||||||
|
var exported: Identifier
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ExportDefaultDeclaration : BaseModuleDeclaration {
|
||||||
|
override var type: String /* "ExportDefaultDeclaration" */
|
||||||
|
var declaration: dynamic /* FunctionDeclaration | VariableDeclaration | ClassDeclaration | ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ExportAllDeclaration : BaseModuleDeclaration {
|
||||||
|
override var type: String /* "ExportAllDeclaration" */
|
||||||
|
var source: dynamic /* SimpleLiteral | RegExpLiteral */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface AwaitExpression : BaseExpression {
|
||||||
|
override var type: String /* "AwaitExpression" */
|
||||||
|
var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package kscience.kmath.estree.internal.stream
|
||||||
|
|
||||||
|
import kscience.kmath.estree.internal.emitter.Emitter
|
||||||
|
|
||||||
|
internal open external class Stream : Emitter {
|
||||||
|
open fun pipe(dest: Any, options: Any): Any
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package kscience.kmath.estree.internal.tsstdlib
|
||||||
|
|
||||||
|
internal external interface IteratorYieldResult<TYield> {
|
||||||
|
var done: Boolean?
|
||||||
|
get() = definedExternally
|
||||||
|
set(value) = definedExternally
|
||||||
|
var value: TYield
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface IteratorReturnResult<TReturn> {
|
||||||
|
var done: Boolean
|
||||||
|
var value: TReturn
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface Iterator<T, TReturn, TNext> {
|
||||||
|
fun next(vararg args: Any /* JsTuple<> | JsTuple<TNext> */): dynamic /* IteratorYieldResult<T> | IteratorReturnResult<TReturn> */
|
||||||
|
val `return`: ((value: TReturn) -> dynamic)?
|
||||||
|
val `throw`: ((e: Any) -> dynamic)?
|
||||||
|
}
|
||||||
|
|
||||||
|
internal typealias Iterator__1<T> = Iterator<T, Any, Nothing?>
|
||||||
|
|
||||||
|
internal external interface Iterable<T>
|
||||||
|
|
||||||
|
internal external interface IterableIterator<T> : Iterator__1<T>
|
@ -0,0 +1,82 @@
|
|||||||
|
@file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION")
|
||||||
|
|
||||||
|
package kscience.kmath.estree.internal.tsstdlib
|
||||||
|
|
||||||
|
import kotlin.js.RegExp
|
||||||
|
|
||||||
|
internal typealias RegExpMatchArray = Array<String>
|
||||||
|
|
||||||
|
internal typealias RegExpExecArray = Array<String>
|
||||||
|
|
||||||
|
internal external interface RegExpConstructor {
|
||||||
|
@nativeInvoke
|
||||||
|
operator fun invoke(pattern: RegExp, flags: String = definedExternally): RegExp
|
||||||
|
|
||||||
|
@nativeInvoke
|
||||||
|
operator fun invoke(pattern: RegExp): RegExp
|
||||||
|
|
||||||
|
@nativeInvoke
|
||||||
|
operator fun invoke(pattern: String, flags: String = definedExternally): RegExp
|
||||||
|
|
||||||
|
@nativeInvoke
|
||||||
|
operator fun invoke(pattern: String): RegExp
|
||||||
|
var prototype: RegExp
|
||||||
|
var `$1`: String
|
||||||
|
var `$2`: String
|
||||||
|
var `$3`: String
|
||||||
|
var `$4`: String
|
||||||
|
var `$5`: String
|
||||||
|
var `$6`: String
|
||||||
|
var `$7`: String
|
||||||
|
var `$8`: String
|
||||||
|
var `$9`: String
|
||||||
|
var lastMatch: String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ConcatArray<T> {
|
||||||
|
var length: Number
|
||||||
|
|
||||||
|
@nativeGetter
|
||||||
|
operator fun get(n: Number): T?
|
||||||
|
|
||||||
|
@nativeSetter
|
||||||
|
operator fun set(n: Number, value: T)
|
||||||
|
fun join(separator: String = definedExternally): String
|
||||||
|
fun slice(start: Number = definedExternally, end: Number = definedExternally): Array<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ArrayConstructor {
|
||||||
|
fun <T> from(iterable: Iterable<T>): Array<T>
|
||||||
|
fun <T> from(iterable: ArrayLike<T>): Array<T>
|
||||||
|
fun <T, U> from(iterable: Iterable<T>, mapfn: (v: T, k: Number) -> U, thisArg: Any = definedExternally): Array<U>
|
||||||
|
fun <T, U> from(iterable: Iterable<T>, mapfn: (v: T, k: Number) -> U): Array<U>
|
||||||
|
fun <T, U> from(iterable: ArrayLike<T>, mapfn: (v: T, k: Number) -> U, thisArg: Any = definedExternally): Array<U>
|
||||||
|
fun <T, U> from(iterable: ArrayLike<T>, mapfn: (v: T, k: Number) -> U): Array<U>
|
||||||
|
fun <T> of(vararg items: T): Array<T>
|
||||||
|
|
||||||
|
@nativeInvoke
|
||||||
|
operator fun invoke(arrayLength: Number = definedExternally): Array<Any>
|
||||||
|
|
||||||
|
@nativeInvoke
|
||||||
|
operator fun invoke(): Array<Any>
|
||||||
|
|
||||||
|
@nativeInvoke
|
||||||
|
operator fun <T> invoke(arrayLength: Number): Array<T>
|
||||||
|
|
||||||
|
@nativeInvoke
|
||||||
|
operator fun <T> invoke(vararg items: T): Array<T>
|
||||||
|
fun isArray(arg: Any): Boolean
|
||||||
|
var prototype: Array<Any>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal external interface ArrayLike<T> {
|
||||||
|
var length: Number
|
||||||
|
|
||||||
|
@nativeGetter
|
||||||
|
operator fun get(n: Number): T?
|
||||||
|
|
||||||
|
@nativeSetter
|
||||||
|
operator fun set(n: Number, value: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal typealias Extract<T, U> = Any
|
@ -0,0 +1,115 @@
|
|||||||
|
package kscience.kmath.estree
|
||||||
|
|
||||||
|
import kscience.kmath.ast.*
|
||||||
|
import kscience.kmath.expressions.invoke
|
||||||
|
import kscience.kmath.operations.ByteRing
|
||||||
|
import kscience.kmath.operations.ComplexField
|
||||||
|
import kscience.kmath.operations.RealField
|
||||||
|
import kscience.kmath.operations.toComplex
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
internal class TestESTreeConsistencyWithInterpreter {
|
||||||
|
@Test
|
||||||
|
fun mstSpace() {
|
||||||
|
val res1 = MstSpace.mstInSpace {
|
||||||
|
binaryOperationFunction("+")(
|
||||||
|
unaryOperationFunction("+")(
|
||||||
|
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
||||||
|
add(number(1), number(1)),
|
||||||
|
2
|
||||||
|
) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
|
||||||
|
),
|
||||||
|
|
||||||
|
number(1)
|
||||||
|
) + symbol("x") + zero
|
||||||
|
}("x" to MST.Numeric(2))
|
||||||
|
|
||||||
|
val res2 = MstSpace.mstInSpace {
|
||||||
|
binaryOperationFunction("+")(
|
||||||
|
unaryOperationFunction("+")(
|
||||||
|
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
||||||
|
add(number(1), number(1)),
|
||||||
|
2
|
||||||
|
) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
|
||||||
|
),
|
||||||
|
|
||||||
|
number(1)
|
||||||
|
) + symbol("x") + zero
|
||||||
|
}.compile()("x" to MST.Numeric(2))
|
||||||
|
|
||||||
|
assertEquals(res1, res2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun byteRing() {
|
||||||
|
val res1 = ByteRing.mstInRing {
|
||||||
|
binaryOperationFunction("+")(
|
||||||
|
unaryOperationFunction("+")(
|
||||||
|
(symbol("x") - (2.toByte() + (multiply(
|
||||||
|
add(number(1), number(1)),
|
||||||
|
2
|
||||||
|
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||||
|
),
|
||||||
|
|
||||||
|
number(1)
|
||||||
|
) * number(2)
|
||||||
|
}("x" to 3.toByte())
|
||||||
|
|
||||||
|
val res2 = ByteRing.mstInRing {
|
||||||
|
binaryOperationFunction("+")(
|
||||||
|
unaryOperationFunction("+")(
|
||||||
|
(symbol("x") - (2.toByte() + (multiply(
|
||||||
|
add(number(1), number(1)),
|
||||||
|
2
|
||||||
|
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||||
|
),
|
||||||
|
number(1)
|
||||||
|
) * number(2)
|
||||||
|
}.compile()("x" to 3.toByte())
|
||||||
|
|
||||||
|
assertEquals(res1, res2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun realField() {
|
||||||
|
val res1 = RealField.mstInField {
|
||||||
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
|
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||||
|
+ number(1),
|
||||||
|
number(1) / 2 + number(2.0) * one
|
||||||
|
) + zero
|
||||||
|
}("x" to 2.0)
|
||||||
|
|
||||||
|
val res2 = RealField.mstInField {
|
||||||
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
|
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||||
|
+ number(1),
|
||||||
|
number(1) / 2 + number(2.0) * one
|
||||||
|
) + zero
|
||||||
|
}.compile()("x" to 2.0)
|
||||||
|
|
||||||
|
assertEquals(res1, res2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun complexField() {
|
||||||
|
val res1 = ComplexField.mstInField {
|
||||||
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
|
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||||
|
+ number(1),
|
||||||
|
number(1) / 2 + number(2.0) * one
|
||||||
|
) + zero
|
||||||
|
}("x" to 2.0.toComplex())
|
||||||
|
|
||||||
|
val res2 = ComplexField.mstInField {
|
||||||
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
|
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||||
|
+ number(1),
|
||||||
|
number(1) / 2 + number(2.0) * one
|
||||||
|
) + zero
|
||||||
|
}.compile()("x" to 2.0.toComplex())
|
||||||
|
|
||||||
|
assertEquals(res1, res2)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package kscience.kmath.estree
|
||||||
|
|
||||||
|
import kscience.kmath.ast.mstInExtendedField
|
||||||
|
import kscience.kmath.ast.mstInField
|
||||||
|
import kscience.kmath.ast.mstInSpace
|
||||||
|
import kscience.kmath.expressions.invoke
|
||||||
|
import kscience.kmath.operations.RealField
|
||||||
|
import kotlin.random.Random
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
internal class TestESTreeOperationsSupport {
|
||||||
|
@Test
|
||||||
|
fun testUnaryOperationInvocation() {
|
||||||
|
val expression = RealField.mstInSpace { -symbol("x") }.compile()
|
||||||
|
val res = expression("x" to 2.0)
|
||||||
|
assertEquals(-2.0, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBinaryOperationInvocation() {
|
||||||
|
val expression = RealField.mstInSpace { -symbol("x") + number(1.0) }.compile()
|
||||||
|
val res = expression("x" to 2.0)
|
||||||
|
assertEquals(-1.0, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testConstProductInvocation() {
|
||||||
|
val res = RealField.mstInField { symbol("x") * 2 }("x" to 2.0)
|
||||||
|
assertEquals(4.0, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMultipleCalls() {
|
||||||
|
val e = RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile()
|
||||||
|
val r = Random(0)
|
||||||
|
var s = 0.0
|
||||||
|
repeat(1000000) { s += e("x" to r.nextDouble()) }
|
||||||
|
println(s)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package kscience.kmath.estree
|
||||||
|
|
||||||
|
import kscience.kmath.ast.mstInField
|
||||||
|
import kscience.kmath.expressions.invoke
|
||||||
|
import kscience.kmath.operations.RealField
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
internal class TestESTreeSpecialization {
|
||||||
|
@Test
|
||||||
|
fun testUnaryPlus() {
|
||||||
|
val expr = RealField.mstInField { unaryOperationFunction("+")(symbol("x")) }.compile()
|
||||||
|
assertEquals(2.0, expr("x" to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUnaryMinus() {
|
||||||
|
val expr = RealField.mstInField { unaryOperationFunction("-")(symbol("x")) }.compile()
|
||||||
|
assertEquals(-2.0, expr("x" to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAdd() {
|
||||||
|
val expr = RealField.mstInField { binaryOperationFunction("+")(symbol("x"), symbol("x")) }.compile()
|
||||||
|
assertEquals(4.0, expr("x" to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSine() {
|
||||||
|
val expr = RealField.mstInField { unaryOperationFunction("sin")(symbol("x")) }.compile()
|
||||||
|
assertEquals(0.0, expr("x" to 0.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMinus() {
|
||||||
|
val expr = RealField.mstInField { binaryOperationFunction("-")(symbol("x"), symbol("x")) }.compile()
|
||||||
|
assertEquals(0.0, expr("x" to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDivide() {
|
||||||
|
val expr = RealField.mstInField { binaryOperationFunction("/")(symbol("x"), symbol("x")) }.compile()
|
||||||
|
assertEquals(1.0, expr("x" to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPower() {
|
||||||
|
val expr = RealField
|
||||||
|
.mstInField { binaryOperationFunction("pow")(symbol("x"), number(2)) }
|
||||||
|
.compile()
|
||||||
|
|
||||||
|
assertEquals(4.0, expr("x" to 2.0))
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package kscience.kmath.estree
|
||||||
|
|
||||||
|
import kscience.kmath.ast.mstInRing
|
||||||
|
import kscience.kmath.expressions.invoke
|
||||||
|
import kscience.kmath.operations.ByteRing
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
|
internal class TestESTreeVariables {
|
||||||
|
@Test
|
||||||
|
fun testVariable() {
|
||||||
|
val expr = ByteRing.mstInRing { symbol("x") }.compile()
|
||||||
|
assertEquals(1.toByte(), expr("x" to 1.toByte()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUndefinedVariableFails() {
|
||||||
|
val expr = ByteRing.mstInRing { symbol("x") }.compile()
|
||||||
|
assertFailsWith<NoSuchElementException> { expr() }
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
package kscience.kmath.asm
|
package kscience.kmath.asm
|
||||||
|
|
||||||
import kscience.kmath.asm.internal.AsmBuilder
|
import kscience.kmath.asm.internal.AsmBuilder
|
||||||
import kscience.kmath.asm.internal.MstType
|
|
||||||
import kscience.kmath.asm.internal.buildAlgebraOperationCall
|
|
||||||
import kscience.kmath.asm.internal.buildName
|
import kscience.kmath.asm.internal.buildName
|
||||||
import kscience.kmath.ast.MST
|
import kscience.kmath.ast.MST
|
||||||
import kscience.kmath.ast.MstExpression
|
import kscience.kmath.ast.MstExpression
|
||||||
import kscience.kmath.expressions.Expression
|
import kscience.kmath.expressions.Expression
|
||||||
import kscience.kmath.operations.Algebra
|
import kscience.kmath.operations.Algebra
|
||||||
|
import kscience.kmath.operations.NumericAlgebra
|
||||||
|
import kscience.kmath.operations.RealField
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles given MST to an Expression using AST compiler.
|
* Compiles given MST to an Expression using AST compiler.
|
||||||
@ -23,37 +23,46 @@ internal fun <T : Any> MST.compileWith(type: Class<T>, algebra: Algebra<T>): Exp
|
|||||||
is MST.Symbolic -> {
|
is MST.Symbolic -> {
|
||||||
val symbol = try {
|
val symbol = try {
|
||||||
algebra.symbol(node.value)
|
algebra.symbol(node.value)
|
||||||
} catch (ignored: Throwable) {
|
} catch (ignored: IllegalStateException) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (symbol != null)
|
if (symbol != null)
|
||||||
loadTConstant(symbol)
|
loadObjectConstant(symbol as Any)
|
||||||
else
|
else
|
||||||
loadVariable(node.value)
|
loadVariable(node.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
is MST.Numeric -> loadNumeric(node.value)
|
is MST.Numeric -> loadNumberConstant(node.value)
|
||||||
|
is MST.Unary -> buildCall(algebra.unaryOperationFunction(node.operation)) { visit(node.value) }
|
||||||
|
|
||||||
is MST.Unary -> buildAlgebraOperationCall(
|
is MST.Binary -> when {
|
||||||
context = algebra,
|
algebra is NumericAlgebra<T> && node.left is MST.Numeric && node.right is MST.Numeric -> loadObjectConstant(
|
||||||
name = node.operation,
|
algebra.number(
|
||||||
fallbackMethodName = "unaryOperation",
|
RealField
|
||||||
parameterTypes = arrayOf(MstType.fromMst(node.value))
|
.binaryOperationFunction(node.operation)
|
||||||
) { visit(node.value) }
|
.invoke(node.left.value.toDouble(), node.right.value.toDouble())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
is MST.Binary -> buildAlgebraOperationCall(
|
algebra is NumericAlgebra<T> && node.left is MST.Numeric -> buildCall(algebra.leftSideNumberOperationFunction(node.operation)) {
|
||||||
context = algebra,
|
visit(node.left)
|
||||||
name = node.operation,
|
visit(node.right)
|
||||||
fallbackMethodName = "binaryOperation",
|
}
|
||||||
parameterTypes = arrayOf(MstType.fromMst(node.left), MstType.fromMst(node.right))
|
|
||||||
) {
|
algebra is NumericAlgebra<T> && node.right is MST.Numeric -> buildCall(algebra.rightSideNumberOperationFunction(node.operation)) {
|
||||||
|
visit(node.left)
|
||||||
|
visit(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> buildCall(algebra.binaryOperationFunction(node.operation)) {
|
||||||
visit(node.left)
|
visit(node.left)
|
||||||
visit(node.right)
|
visit(node.right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return AsmBuilder(type, algebra, buildName(this)) { visit(this@compileWith) }.getInstance()
|
return AsmBuilder<T>(type, buildName(this)) { visit(this@compileWith) }.instance
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,29 +3,30 @@ package kscience.kmath.asm.internal
|
|||||||
import kscience.kmath.asm.internal.AsmBuilder.ClassLoader
|
import kscience.kmath.asm.internal.AsmBuilder.ClassLoader
|
||||||
import kscience.kmath.ast.MST
|
import kscience.kmath.ast.MST
|
||||||
import kscience.kmath.expressions.Expression
|
import kscience.kmath.expressions.Expression
|
||||||
import kscience.kmath.operations.Algebra
|
|
||||||
import kscience.kmath.operations.NumericAlgebra
|
|
||||||
import org.objectweb.asm.*
|
import org.objectweb.asm.*
|
||||||
import org.objectweb.asm.Opcodes.*
|
import org.objectweb.asm.Opcodes.*
|
||||||
|
import org.objectweb.asm.Type.*
|
||||||
import org.objectweb.asm.commons.InstructionAdapter
|
import org.objectweb.asm.commons.InstructionAdapter
|
||||||
import java.util.*
|
import java.lang.invoke.MethodHandles
|
||||||
import java.util.stream.Collectors
|
import java.lang.invoke.MethodType
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
import java.util.stream.Collectors.toMap
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM Builder is a structure that abstracts building a class designated to unwrap [MST] to plain Java expression.
|
* ASM Builder is a structure that abstracts building a class designated to unwrap [MST] to plain Java expression.
|
||||||
* This class uses [ClassLoader] for loading the generated class, then it is able to instantiate the new class.
|
* This class uses [ClassLoader] for loading the generated class, then it is able to instantiate the new class.
|
||||||
*
|
*
|
||||||
* @property T the type of AsmExpression to unwrap.
|
* @property T the type of AsmExpression to unwrap.
|
||||||
* @property algebra the algebra the applied AsmExpressions use.
|
|
||||||
* @property className the unique class name of new loaded class.
|
* @property className the unique class name of new loaded class.
|
||||||
* @property invokeLabel0Visitor the function to apply to this object when generating invoke method, label 0.
|
* @property callbackAtInvokeL0 the function to apply to this object when generating invoke method, label 0.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
internal class AsmBuilder<T> internal constructor(
|
internal class AsmBuilder<T>(
|
||||||
private val classOfT: Class<*>,
|
classOfT: Class<*>,
|
||||||
private val algebra: Algebra<T>,
|
|
||||||
private val className: String,
|
private val className: String,
|
||||||
private val invokeLabel0Visitor: AsmBuilder<T>.() -> Unit,
|
private val callbackAtInvokeL0: AsmBuilder<T>.() -> Unit,
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* Internal classloader of [AsmBuilder] with alias to define class from byte array.
|
* Internal classloader of [AsmBuilder] with alias to define class from byte array.
|
||||||
@ -39,20 +40,15 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
*/
|
*/
|
||||||
private val classLoader: ClassLoader = ClassLoader(javaClass.classLoader)
|
private val classLoader: ClassLoader = ClassLoader(javaClass.classLoader)
|
||||||
|
|
||||||
/**
|
|
||||||
* ASM Type for [algebra].
|
|
||||||
*/
|
|
||||||
private val tAlgebraType: Type = algebra.javaClass.asm
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM type for [T].
|
* ASM type for [T].
|
||||||
*/
|
*/
|
||||||
internal val tType: Type = classOfT.asm
|
private val tType: Type = classOfT.asm
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM type for new class.
|
* ASM type for new class.
|
||||||
*/
|
*/
|
||||||
private val classType: Type = Type.getObjectType(className.replace(oldChar = '.', newChar = '/'))!!
|
private val classType: Type = getObjectType(className.replace(oldChar = '.', newChar = '/'))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of constants to provide to the subclass.
|
* List of constants to provide to the subclass.
|
||||||
@ -64,55 +60,14 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
*/
|
*/
|
||||||
private lateinit var invokeMethodVisitor: InstructionAdapter
|
private lateinit var invokeMethodVisitor: InstructionAdapter
|
||||||
|
|
||||||
/**
|
|
||||||
* States whether this [AsmBuilder] needs to generate constants field.
|
|
||||||
*/
|
|
||||||
private var hasConstants: Boolean = true
|
|
||||||
|
|
||||||
/**
|
|
||||||
* States whether [T] a primitive type, so [AsmBuilder] may generate direct primitive calls.
|
|
||||||
*/
|
|
||||||
internal var primitiveMode: Boolean = false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Primitive type to apply for specific primitive calls. Use [OBJECT_TYPE], if not in [primitiveMode].
|
|
||||||
*/
|
|
||||||
internal var primitiveMask: Type = OBJECT_TYPE
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Boxed primitive type to apply for specific primitive calls. Use [OBJECT_TYPE], if not in [primitiveMode].
|
|
||||||
*/
|
|
||||||
internal var primitiveMaskBoxed: Type = OBJECT_TYPE
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stack of useful objects types on stack to verify types.
|
|
||||||
*/
|
|
||||||
private val typeStack: ArrayDeque<Type> = ArrayDeque()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stack of useful objects types on stack expected by algebra calls.
|
|
||||||
*/
|
|
||||||
internal val expectationStack: ArrayDeque<Type> = ArrayDeque<Type>(1).also { it.push(tType) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The cache for instance built by this builder.
|
|
||||||
*/
|
|
||||||
private var generatedInstance: Expression<T>? = null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclasses, loads and instantiates [Expression] for given parameters.
|
* Subclasses, loads and instantiates [Expression] for given parameters.
|
||||||
*
|
*
|
||||||
* The built instance is cached.
|
* The built instance is cached.
|
||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
internal fun getInstance(): Expression<T> {
|
val instance: Expression<T> by lazy {
|
||||||
generatedInstance?.let { return it }
|
val hasConstants: Boolean
|
||||||
|
|
||||||
if (SIGNATURE_LETTERS.containsKey(classOfT)) {
|
|
||||||
primitiveMode = true
|
|
||||||
primitiveMask = SIGNATURE_LETTERS.getValue(classOfT)
|
|
||||||
primitiveMaskBoxed = tType
|
|
||||||
}
|
|
||||||
|
|
||||||
val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) {
|
val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) {
|
||||||
visit(
|
visit(
|
||||||
@ -121,20 +76,20 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
classType.internalName,
|
classType.internalName,
|
||||||
"${OBJECT_TYPE.descriptor}L${EXPRESSION_TYPE.internalName}<${tType.descriptor}>;",
|
"${OBJECT_TYPE.descriptor}L${EXPRESSION_TYPE.internalName}<${tType.descriptor}>;",
|
||||||
OBJECT_TYPE.internalName,
|
OBJECT_TYPE.internalName,
|
||||||
arrayOf(EXPRESSION_TYPE.internalName)
|
arrayOf(EXPRESSION_TYPE.internalName),
|
||||||
)
|
)
|
||||||
|
|
||||||
visitMethod(
|
visitMethod(
|
||||||
ACC_PUBLIC or ACC_FINAL,
|
ACC_PUBLIC or ACC_FINAL,
|
||||||
"invoke",
|
"invoke",
|
||||||
Type.getMethodDescriptor(tType, MAP_TYPE),
|
getMethodDescriptor(tType, MAP_TYPE),
|
||||||
"(L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;)${tType.descriptor}",
|
"(L${MAP_TYPE.internalName}<${SYMBOL_TYPE.descriptor}${if (Modifier.isFinal(classOfT.modifiers)) "" else "+"}${tType.descriptor}>;)${tType.descriptor}",
|
||||||
null
|
null,
|
||||||
).instructionAdapter {
|
).instructionAdapter {
|
||||||
invokeMethodVisitor = this
|
invokeMethodVisitor = this
|
||||||
visitCode()
|
visitCode()
|
||||||
val l0 = label()
|
val l0 = label()
|
||||||
invokeLabel0Visitor()
|
callbackAtInvokeL0()
|
||||||
areturn(tType)
|
areturn(tType)
|
||||||
val l1 = label()
|
val l1 = label()
|
||||||
|
|
||||||
@ -144,7 +99,7 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
null,
|
null,
|
||||||
l0,
|
l0,
|
||||||
l1,
|
l1,
|
||||||
invokeThisVar
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
visitLocalVariable(
|
visitLocalVariable(
|
||||||
@ -153,7 +108,7 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
"L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;",
|
"L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;",
|
||||||
l0,
|
l0,
|
||||||
l1,
|
l1,
|
||||||
invokeArgumentsVar
|
1,
|
||||||
)
|
)
|
||||||
|
|
||||||
visitMaxs(0, 2)
|
visitMaxs(0, 2)
|
||||||
@ -163,17 +118,15 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
visitMethod(
|
visitMethod(
|
||||||
ACC_PUBLIC or ACC_FINAL or ACC_BRIDGE or ACC_SYNTHETIC,
|
ACC_PUBLIC or ACC_FINAL or ACC_BRIDGE or ACC_SYNTHETIC,
|
||||||
"invoke",
|
"invoke",
|
||||||
Type.getMethodDescriptor(OBJECT_TYPE, MAP_TYPE),
|
getMethodDescriptor(OBJECT_TYPE, MAP_TYPE),
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
|
||||||
).instructionAdapter {
|
).instructionAdapter {
|
||||||
val thisVar = 0
|
|
||||||
val argumentsVar = 1
|
|
||||||
visitCode()
|
visitCode()
|
||||||
val l0 = label()
|
val l0 = label()
|
||||||
load(thisVar, OBJECT_TYPE)
|
load(0, OBJECT_TYPE)
|
||||||
load(argumentsVar, MAP_TYPE)
|
load(1, MAP_TYPE)
|
||||||
invokevirtual(classType.internalName, "invoke", Type.getMethodDescriptor(tType, MAP_TYPE), false)
|
invokevirtual(classType.internalName, "invoke", getMethodDescriptor(tType, MAP_TYPE), false)
|
||||||
areturn(tType)
|
areturn(tType)
|
||||||
val l1 = label()
|
val l1 = label()
|
||||||
|
|
||||||
@ -183,7 +136,7 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
null,
|
null,
|
||||||
l0,
|
l0,
|
||||||
l1,
|
l1,
|
||||||
thisVar
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
visitMaxs(0, 2)
|
visitMaxs(0, 2)
|
||||||
@ -192,15 +145,6 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
|
|
||||||
hasConstants = constants.isNotEmpty()
|
hasConstants = constants.isNotEmpty()
|
||||||
|
|
||||||
visitField(
|
|
||||||
access = ACC_PRIVATE or ACC_FINAL,
|
|
||||||
name = "algebra",
|
|
||||||
descriptor = tAlgebraType.descriptor,
|
|
||||||
signature = null,
|
|
||||||
value = null,
|
|
||||||
block = FieldVisitor::visitEnd
|
|
||||||
)
|
|
||||||
|
|
||||||
if (hasConstants)
|
if (hasConstants)
|
||||||
visitField(
|
visitField(
|
||||||
access = ACC_PRIVATE or ACC_FINAL,
|
access = ACC_PRIVATE or ACC_FINAL,
|
||||||
@ -208,55 +152,36 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
descriptor = OBJECT_ARRAY_TYPE.descriptor,
|
descriptor = OBJECT_ARRAY_TYPE.descriptor,
|
||||||
signature = null,
|
signature = null,
|
||||||
value = null,
|
value = null,
|
||||||
block = FieldVisitor::visitEnd
|
block = FieldVisitor::visitEnd,
|
||||||
)
|
)
|
||||||
|
|
||||||
visitMethod(
|
visitMethod(
|
||||||
ACC_PUBLIC,
|
ACC_PUBLIC,
|
||||||
"<init>",
|
"<init>",
|
||||||
|
getMethodDescriptor(VOID_TYPE, *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }),
|
||||||
Type.getMethodDescriptor(
|
null,
|
||||||
Type.VOID_TYPE,
|
|
||||||
tAlgebraType,
|
|
||||||
*OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }),
|
|
||||||
|
|
||||||
null,
|
null,
|
||||||
null
|
|
||||||
).instructionAdapter {
|
).instructionAdapter {
|
||||||
val thisVar = 0
|
|
||||||
val algebraVar = 1
|
|
||||||
val constantsVar = 2
|
|
||||||
val l0 = label()
|
val l0 = label()
|
||||||
load(thisVar, classType)
|
load(0, classType)
|
||||||
invokespecial(OBJECT_TYPE.internalName, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE), false)
|
invokespecial(OBJECT_TYPE.internalName, "<init>", getMethodDescriptor(VOID_TYPE), false)
|
||||||
label()
|
label()
|
||||||
load(thisVar, classType)
|
load(0, classType)
|
||||||
load(algebraVar, tAlgebraType)
|
|
||||||
putfield(classType.internalName, "algebra", tAlgebraType.descriptor)
|
|
||||||
|
|
||||||
if (hasConstants) {
|
if (hasConstants) {
|
||||||
label()
|
label()
|
||||||
load(thisVar, classType)
|
load(0, classType)
|
||||||
load(constantsVar, OBJECT_ARRAY_TYPE)
|
load(1, OBJECT_ARRAY_TYPE)
|
||||||
putfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
|
putfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
label()
|
label()
|
||||||
visitInsn(RETURN)
|
visitInsn(RETURN)
|
||||||
val l4 = label()
|
val l4 = label()
|
||||||
visitLocalVariable("this", classType.descriptor, null, l0, l4, thisVar)
|
visitLocalVariable("this", classType.descriptor, null, l0, l4, 0)
|
||||||
|
|
||||||
visitLocalVariable(
|
|
||||||
"algebra",
|
|
||||||
tAlgebraType.descriptor,
|
|
||||||
null,
|
|
||||||
l0,
|
|
||||||
l4,
|
|
||||||
algebraVar
|
|
||||||
)
|
|
||||||
|
|
||||||
if (hasConstants)
|
if (hasConstants)
|
||||||
visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l4, constantsVar)
|
visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l4, 1)
|
||||||
|
|
||||||
visitMaxs(0, 3)
|
visitMaxs(0, 3)
|
||||||
visitEnd()
|
visitEnd()
|
||||||
@ -265,296 +190,156 @@ internal class AsmBuilder<T> internal constructor(
|
|||||||
visitEnd()
|
visitEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
val new = classLoader
|
val cls = classLoader.defineClass(className, classWriter.toByteArray())
|
||||||
.defineClass(className, classWriter.toByteArray())
|
java.io.File("dump.class").writeBytes(classWriter.toByteArray())
|
||||||
.constructors
|
val l = MethodHandles.publicLookup()
|
||||||
.first()
|
|
||||||
.newInstance(algebra, *(constants.toTypedArray().wrapToArrayIf { hasConstants })) as Expression<T>
|
|
||||||
|
|
||||||
generatedInstance = new
|
if (hasConstants)
|
||||||
return new
|
l.findConstructor(cls, MethodType.methodType(Void.TYPE, Array<Any>::class.java))
|
||||||
|
.invoke(constants.toTypedArray()) as Expression<T>
|
||||||
|
else
|
||||||
|
l.findConstructor(cls, MethodType.methodType(Void.TYPE)).invoke() as Expression<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a [T] constant from [constants].
|
|
||||||
*/
|
|
||||||
internal fun loadTConstant(value: T) {
|
|
||||||
if (classOfT in INLINABLE_NUMBERS) {
|
|
||||||
val expectedType = expectationStack.pop()
|
|
||||||
val mustBeBoxed = expectedType.sort == Type.OBJECT
|
|
||||||
loadNumberConstant(value as Number, mustBeBoxed)
|
|
||||||
|
|
||||||
if (mustBeBoxed)
|
|
||||||
invokeMethodVisitor.checkcast(tType)
|
|
||||||
|
|
||||||
if (mustBeBoxed) typeStack.push(tType) else typeStack.push(primitiveMask)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
loadObjectConstant(value as Any, tType)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Boxes the current value and pushes it.
|
|
||||||
*/
|
|
||||||
private fun box(primitive: Type) {
|
|
||||||
val r = PRIMITIVES_TO_BOXED.getValue(primitive)
|
|
||||||
|
|
||||||
invokeMethodVisitor.invokestatic(
|
|
||||||
r.internalName,
|
|
||||||
"valueOf",
|
|
||||||
Type.getMethodDescriptor(r, primitive),
|
|
||||||
false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unboxes the current boxed value and pushes it.
|
|
||||||
*/
|
|
||||||
private fun unboxTo(primitive: Type) = invokeMethodVisitor.invokevirtual(
|
|
||||||
NUMBER_TYPE.internalName,
|
|
||||||
NUMBER_CONVERTER_METHODS.getValue(primitive),
|
|
||||||
Type.getMethodDescriptor(primitive),
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads [java.lang.Object] constant from constants.
|
* Loads [java.lang.Object] constant from constants.
|
||||||
*/
|
*/
|
||||||
private fun loadObjectConstant(value: Any, type: Type): Unit = invokeMethodVisitor.run {
|
fun loadObjectConstant(value: Any, type: Type = tType): Unit = invokeMethodVisitor.run {
|
||||||
val idx = if (value in constants) constants.indexOf(value) else constants.apply { add(value) }.lastIndex
|
val idx = if (value in constants) constants.indexOf(value) else constants.also { it += value }.lastIndex
|
||||||
loadThis()
|
invokeMethodVisitor.load(0, classType)
|
||||||
getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
|
getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
|
||||||
iconst(idx)
|
iconst(idx)
|
||||||
visitInsn(AALOAD)
|
visitInsn(AALOAD)
|
||||||
checkcast(type)
|
if (type != OBJECT_TYPE) checkcast(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun loadNumeric(value: Number) {
|
|
||||||
if (expectationStack.peek() == NUMBER_TYPE) {
|
|
||||||
loadNumberConstant(value, true)
|
|
||||||
expectationStack.pop()
|
|
||||||
typeStack.push(NUMBER_TYPE)
|
|
||||||
} else (algebra as? NumericAlgebra<T>)?.number(value)?.let { loadTConstant(it) }
|
|
||||||
?: error("Cannot resolve numeric $value since target algebra is not numeric, and the current operation doesn't accept numbers.")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads this variable.
|
|
||||||
*/
|
|
||||||
private fun loadThis(): Unit = invokeMethodVisitor.load(invokeThisVar, classType)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Either loads a numeric constant [value] from the class's constants field or boxes a primitive
|
* Either loads a numeric constant [value] from the class's constants field or boxes a primitive
|
||||||
* constant from the constant pool (some numbers with special opcodes like [Opcodes.ICONST_0] aren't even loaded
|
* constant from the constant pool.
|
||||||
* from it).
|
|
||||||
*/
|
*/
|
||||||
private fun loadNumberConstant(value: Number, mustBeBoxed: Boolean) {
|
fun loadNumberConstant(value: Number) {
|
||||||
val boxed = value.javaClass.asm
|
val boxed = value.javaClass.asm
|
||||||
val primitive = BOXED_TO_PRIMITIVES[boxed]
|
val primitive = BOXED_TO_PRIMITIVES[boxed]
|
||||||
|
|
||||||
if (primitive != null) {
|
if (primitive != null) {
|
||||||
when (primitive) {
|
when (primitive) {
|
||||||
Type.BYTE_TYPE -> invokeMethodVisitor.iconst(value.toInt())
|
BYTE_TYPE -> invokeMethodVisitor.iconst(value.toInt())
|
||||||
Type.DOUBLE_TYPE -> invokeMethodVisitor.dconst(value.toDouble())
|
DOUBLE_TYPE -> invokeMethodVisitor.dconst(value.toDouble())
|
||||||
Type.FLOAT_TYPE -> invokeMethodVisitor.fconst(value.toFloat())
|
FLOAT_TYPE -> invokeMethodVisitor.fconst(value.toFloat())
|
||||||
Type.LONG_TYPE -> invokeMethodVisitor.lconst(value.toLong())
|
LONG_TYPE -> invokeMethodVisitor.lconst(value.toLong())
|
||||||
Type.INT_TYPE -> invokeMethodVisitor.iconst(value.toInt())
|
INT_TYPE -> invokeMethodVisitor.iconst(value.toInt())
|
||||||
Type.SHORT_TYPE -> invokeMethodVisitor.iconst(value.toInt())
|
SHORT_TYPE -> invokeMethodVisitor.iconst(value.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mustBeBoxed)
|
val r = PRIMITIVES_TO_BOXED.getValue(primitive)
|
||||||
box(primitive)
|
|
||||||
|
invokeMethodVisitor.invokestatic(
|
||||||
|
r.internalName,
|
||||||
|
"valueOf",
|
||||||
|
getMethodDescriptor(r, primitive),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
loadObjectConstant(value, boxed)
|
loadObjectConstant(value, boxed)
|
||||||
|
|
||||||
if (!mustBeBoxed)
|
|
||||||
unboxTo(primitiveMask)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a variable [name] from arguments [Map] parameter of [Expression.invoke]. The [defaultValue] may be
|
* Loads a variable [name] from arguments [Map] parameter of [Expression.invoke].
|
||||||
* provided.
|
|
||||||
*/
|
*/
|
||||||
internal fun loadVariable(name: String): Unit = invokeMethodVisitor.run {
|
fun loadVariable(name: String): Unit = invokeMethodVisitor.run {
|
||||||
load(invokeArgumentsVar, MAP_TYPE)
|
load(1, MAP_TYPE)
|
||||||
aconst(name)
|
aconst(name)
|
||||||
|
|
||||||
invokestatic(
|
invokestatic(
|
||||||
MAP_INTRINSICS_TYPE.internalName,
|
MAP_INTRINSICS_TYPE.internalName,
|
||||||
"getOrFail",
|
"getOrFail",
|
||||||
Type.getMethodDescriptor(OBJECT_TYPE, MAP_TYPE, STRING_TYPE),
|
getMethodDescriptor(OBJECT_TYPE, MAP_TYPE, STRING_TYPE),
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
|
|
||||||
checkcast(tType)
|
checkcast(tType)
|
||||||
val expectedType = expectationStack.pop()
|
|
||||||
|
|
||||||
if (expectedType.sort == Type.OBJECT)
|
|
||||||
typeStack.push(tType)
|
|
||||||
else {
|
|
||||||
unboxTo(primitiveMask)
|
|
||||||
typeStack.push(primitiveMask)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
inline fun buildCall(function: Function<T>, parameters: AsmBuilder<T>.() -> Unit) {
|
||||||
* Loads algebra from according field of the class and casts it to class of [algebra] provided.
|
contract { callsInPlace(parameters, InvocationKind.EXACTLY_ONCE) }
|
||||||
*/
|
val `interface` = function.javaClass.interfaces.first { Function::class.java in it.interfaces }
|
||||||
internal fun loadAlgebra() {
|
|
||||||
loadThis()
|
|
||||||
invokeMethodVisitor.getfield(classType.internalName, "algebra", tAlgebraType.descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
val arity = `interface`.methods.find { it.name == "invoke" }?.parameterCount
|
||||||
* Writes a method instruction of opcode with its [owner], [method] and its [descriptor]. The default opcode is
|
?: error("Provided function object doesn't contain invoke method")
|
||||||
* [Opcodes.INVOKEINTERFACE], since most Algebra functions are declared in interfaces. [loadAlgebra] should be
|
|
||||||
* called before the arguments and this operation.
|
|
||||||
*
|
|
||||||
* The result is casted to [T] automatically.
|
|
||||||
*/
|
|
||||||
internal fun invokeAlgebraOperation(
|
|
||||||
owner: String,
|
|
||||||
method: String,
|
|
||||||
descriptor: String,
|
|
||||||
expectedArity: Int,
|
|
||||||
opcode: Int = INVOKEINTERFACE,
|
|
||||||
) {
|
|
||||||
run loop@{
|
|
||||||
repeat(expectedArity) {
|
|
||||||
if (typeStack.isEmpty()) return@loop
|
|
||||||
typeStack.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeMethodVisitor.visitMethodInsn(
|
val type = getType(`interface`)
|
||||||
opcode,
|
loadObjectConstant(function, type)
|
||||||
owner,
|
parameters(this)
|
||||||
method,
|
|
||||||
descriptor,
|
invokeMethodVisitor.invokeinterface(
|
||||||
opcode == INVOKEINTERFACE
|
type.internalName,
|
||||||
|
"invoke",
|
||||||
|
getMethodDescriptor(OBJECT_TYPE, *Array(arity) { OBJECT_TYPE }),
|
||||||
)
|
)
|
||||||
|
|
||||||
invokeMethodVisitor.checkcast(tType)
|
invokeMethodVisitor.checkcast(tType)
|
||||||
val isLastExpr = expectationStack.size == 1
|
|
||||||
val expectedType = expectationStack.pop()
|
|
||||||
|
|
||||||
if (expectedType.sort == Type.OBJECT || isLastExpr)
|
|
||||||
typeStack.push(tType)
|
|
||||||
else {
|
|
||||||
unboxTo(primitiveMask)
|
|
||||||
typeStack.push(primitiveMask)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a LDC Instruction with string constant provided.
|
|
||||||
*/
|
|
||||||
internal fun loadStringConstant(string: String): Unit = invokeMethodVisitor.aconst(string)
|
|
||||||
|
|
||||||
internal companion object {
|
|
||||||
/**
|
|
||||||
* Index of `this` variable in invoke method of the built subclass.
|
|
||||||
*/
|
|
||||||
private const val invokeThisVar: Int = 0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Index of `arguments` variable in invoke method of the built subclass.
|
|
||||||
*/
|
|
||||||
private const val invokeArgumentsVar: Int = 1
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps JVM primitive numbers boxed types to their primitive ASM types.
|
|
||||||
*/
|
|
||||||
private val SIGNATURE_LETTERS: Map<Class<out Any>, Type> by lazy {
|
|
||||||
hashMapOf(
|
|
||||||
java.lang.Byte::class.java to Type.BYTE_TYPE,
|
|
||||||
java.lang.Short::class.java to Type.SHORT_TYPE,
|
|
||||||
java.lang.Integer::class.java to Type.INT_TYPE,
|
|
||||||
java.lang.Long::class.java to Type.LONG_TYPE,
|
|
||||||
java.lang.Float::class.java to Type.FLOAT_TYPE,
|
|
||||||
java.lang.Double::class.java to Type.DOUBLE_TYPE
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
/**
|
/**
|
||||||
* Maps JVM primitive numbers boxed ASM types to their primitive ASM types.
|
* Maps JVM primitive numbers boxed ASM types to their primitive ASM types.
|
||||||
*/
|
*/
|
||||||
private val BOXED_TO_PRIMITIVES: Map<Type, Type> by lazy { SIGNATURE_LETTERS.mapKeys { (k, _) -> k.asm } }
|
private val BOXED_TO_PRIMITIVES: Map<Type, Type> by lazy {
|
||||||
|
hashMapOf(
|
||||||
|
Byte::class.java.asm to BYTE_TYPE,
|
||||||
|
Short::class.java.asm to SHORT_TYPE,
|
||||||
|
Integer::class.java.asm to INT_TYPE,
|
||||||
|
Long::class.java.asm to LONG_TYPE,
|
||||||
|
Float::class.java.asm to FLOAT_TYPE,
|
||||||
|
Double::class.java.asm to DOUBLE_TYPE,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps JVM primitive numbers boxed ASM types to their primitive ASM types.
|
* Maps JVM primitive numbers boxed ASM types to their primitive ASM types.
|
||||||
*/
|
*/
|
||||||
private val PRIMITIVES_TO_BOXED: Map<Type, Type> by lazy {
|
private val PRIMITIVES_TO_BOXED: Map<Type, Type> by lazy {
|
||||||
BOXED_TO_PRIMITIVES.entries.stream().collect(
|
BOXED_TO_PRIMITIVES.entries.stream().collect(
|
||||||
Collectors.toMap(
|
toMap(Map.Entry<Type, Type>::value, Map.Entry<Type, Type>::key),
|
||||||
Map.Entry<Type, Type>::value,
|
|
||||||
Map.Entry<Type, Type>::key
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps primitive ASM types to [Number] functions unboxing them.
|
|
||||||
*/
|
|
||||||
private val NUMBER_CONVERTER_METHODS: Map<Type, String> by lazy {
|
|
||||||
hashMapOf(
|
|
||||||
Type.BYTE_TYPE to "byteValue",
|
|
||||||
Type.SHORT_TYPE to "shortValue",
|
|
||||||
Type.INT_TYPE to "intValue",
|
|
||||||
Type.LONG_TYPE to "longValue",
|
|
||||||
Type.FLOAT_TYPE to "floatValue",
|
|
||||||
Type.DOUBLE_TYPE to "doubleValue"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides boxed number types values of which can be stored in JVM bytecode constant pool.
|
|
||||||
*/
|
|
||||||
private val INLINABLE_NUMBERS: Set<Class<out Any>> by lazy { SIGNATURE_LETTERS.keys }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM type for [Expression].
|
* ASM type for [Expression].
|
||||||
*/
|
*/
|
||||||
internal val EXPRESSION_TYPE: Type by lazy { Type.getObjectType("kscience/kmath/expressions/Expression") }
|
val EXPRESSION_TYPE: Type by lazy { getObjectType("kscience/kmath/expressions/Expression") }
|
||||||
|
|
||||||
/**
|
|
||||||
* ASM type for [java.lang.Number].
|
|
||||||
*/
|
|
||||||
internal val NUMBER_TYPE: Type by lazy { Type.getObjectType("java/lang/Number") }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM type for [java.util.Map].
|
* ASM type for [java.util.Map].
|
||||||
*/
|
*/
|
||||||
internal val MAP_TYPE: Type by lazy { Type.getObjectType("java/util/Map") }
|
val MAP_TYPE: Type by lazy { getObjectType("java/util/Map") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM type for [java.lang.Object].
|
* ASM type for [java.lang.Object].
|
||||||
*/
|
*/
|
||||||
internal val OBJECT_TYPE: Type by lazy { Type.getObjectType("java/lang/Object") }
|
val OBJECT_TYPE: Type by lazy { getObjectType("java/lang/Object") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM type for array of [java.lang.Object].
|
* ASM type for array of [java.lang.Object].
|
||||||
*/
|
*/
|
||||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "RemoveRedundantQualifierName")
|
val OBJECT_ARRAY_TYPE: Type by lazy { getType("[Ljava/lang/Object;") }
|
||||||
internal val OBJECT_ARRAY_TYPE: Type by lazy { Type.getType("[Ljava/lang/Object;") }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ASM type for [Algebra].
|
|
||||||
*/
|
|
||||||
internal val ALGEBRA_TYPE: Type by lazy { Type.getObjectType("kscience/kmath/operations/Algebra") }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM type for [java.lang.String].
|
* ASM type for [java.lang.String].
|
||||||
*/
|
*/
|
||||||
internal val STRING_TYPE: Type by lazy { Type.getObjectType("java/lang/String") }
|
val STRING_TYPE: Type by lazy { getObjectType("java/lang/String") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM type for MapIntrinsics.
|
* ASM type for MapIntrinsics.
|
||||||
*/
|
*/
|
||||||
internal val MAP_INTRINSICS_TYPE: Type by lazy { Type.getObjectType("kscience/kmath/asm/internal/MapIntrinsics") }
|
val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("kscience/kmath/asm/internal/MapIntrinsics") }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ASM Type for [kscience.kmath.expressions.Symbol].
|
||||||
|
*/
|
||||||
|
val SYMBOL_TYPE: Type by lazy { getObjectType("kscience/kmath/expressions/Symbol") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package kscience.kmath.asm.internal
|
|
||||||
|
|
||||||
import kscience.kmath.ast.MST
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents types known in [MST], numbers and general values.
|
|
||||||
*/
|
|
||||||
internal enum class MstType {
|
|
||||||
GENERAL,
|
|
||||||
NUMBER;
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun fromMst(mst: MST): MstType {
|
|
||||||
if (mst is MST.Numeric)
|
|
||||||
return NUMBER
|
|
||||||
|
|
||||||
return GENERAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,29 +2,11 @@ package kscience.kmath.asm.internal
|
|||||||
|
|
||||||
import kscience.kmath.ast.MST
|
import kscience.kmath.ast.MST
|
||||||
import kscience.kmath.expressions.Expression
|
import kscience.kmath.expressions.Expression
|
||||||
import kscience.kmath.operations.Algebra
|
|
||||||
import kscience.kmath.operations.FieldOperations
|
|
||||||
import kscience.kmath.operations.RingOperations
|
|
||||||
import kscience.kmath.operations.SpaceOperations
|
|
||||||
import org.objectweb.asm.*
|
import org.objectweb.asm.*
|
||||||
import org.objectweb.asm.Opcodes.INVOKEVIRTUAL
|
|
||||||
import org.objectweb.asm.commons.InstructionAdapter
|
import org.objectweb.asm.commons.InstructionAdapter
|
||||||
import java.lang.reflect.Method
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
private val methodNameAdapters: Map<Pair<String, Int>, String> by lazy {
|
|
||||||
hashMapOf(
|
|
||||||
SpaceOperations.PLUS_OPERATION to 2 to "add",
|
|
||||||
RingOperations.TIMES_OPERATION to 2 to "multiply",
|
|
||||||
FieldOperations.DIV_OPERATION to 2 to "divide",
|
|
||||||
SpaceOperations.PLUS_OPERATION to 1 to "unaryPlus",
|
|
||||||
SpaceOperations.MINUS_OPERATION to 1 to "unaryMinus",
|
|
||||||
SpaceOperations.MINUS_OPERATION to 2 to "minus"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns ASM [Type] for given [Class].
|
* Returns ASM [Type] for given [Class].
|
||||||
*
|
*
|
||||||
@ -109,107 +91,3 @@ internal inline fun ClassWriter.visitField(
|
|||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
return visitField(access, name, descriptor, signature, value).apply(block)
|
return visitField(access, name, descriptor, signature, value).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> AsmBuilder<T>.findSpecific(context: Algebra<T>, name: String, parameterTypes: Array<MstType>): Method? =
|
|
||||||
context.javaClass.methods.find { method ->
|
|
||||||
val nameValid = method.name == name
|
|
||||||
val arityValid = method.parameters.size == parameterTypes.size
|
|
||||||
val notBridgeInPrimitive = !(primitiveMode && method.isBridge)
|
|
||||||
|
|
||||||
val paramsValid = method.parameterTypes.zip(parameterTypes).all { (type, mstType) ->
|
|
||||||
!(mstType != MstType.NUMBER && type == java.lang.Number::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
nameValid && arityValid && notBridgeInPrimitive && paramsValid
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the target [context] for code generation contains a method with needed [name] and arity, also builds
|
|
||||||
* type expectation stack for needed arity.
|
|
||||||
*
|
|
||||||
* @author Iaroslav Postovalov
|
|
||||||
*/
|
|
||||||
private fun <T> AsmBuilder<T>.buildExpectationStack(
|
|
||||||
context: Algebra<T>,
|
|
||||||
name: String,
|
|
||||||
parameterTypes: Array<MstType>
|
|
||||||
): Boolean {
|
|
||||||
val arity = parameterTypes.size
|
|
||||||
val specific = findSpecific(context, methodNameAdapters[name to arity] ?: name, parameterTypes)
|
|
||||||
|
|
||||||
if (specific != null)
|
|
||||||
mapTypes(specific, parameterTypes).reversed().forEach { expectationStack.push(it) }
|
|
||||||
else
|
|
||||||
expectationStack.addAll(Collections.nCopies(arity, tType))
|
|
||||||
|
|
||||||
return specific != null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> AsmBuilder<T>.mapTypes(method: Method, parameterTypes: Array<MstType>): List<Type> = method
|
|
||||||
.parameterTypes
|
|
||||||
.zip(parameterTypes)
|
|
||||||
.map { (type, mstType) ->
|
|
||||||
when {
|
|
||||||
type == java.lang.Number::class.java && mstType == MstType.NUMBER -> AsmBuilder.NUMBER_TYPE
|
|
||||||
else -> if (primitiveMode) primitiveMask else primitiveMaskBoxed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the target [context] for code generation contains a method with needed [name] and arity and inserts
|
|
||||||
* [AsmBuilder.invokeAlgebraOperation] of this method.
|
|
||||||
*
|
|
||||||
* @author Iaroslav Postovalov
|
|
||||||
*/
|
|
||||||
private fun <T> AsmBuilder<T>.tryInvokeSpecific(
|
|
||||||
context: Algebra<T>,
|
|
||||||
name: String,
|
|
||||||
parameterTypes: Array<MstType>
|
|
||||||
): Boolean {
|
|
||||||
val arity = parameterTypes.size
|
|
||||||
val theName = methodNameAdapters[name to arity] ?: name
|
|
||||||
val spec = findSpecific(context, theName, parameterTypes) ?: return false
|
|
||||||
val owner = context.javaClass.asm
|
|
||||||
|
|
||||||
invokeAlgebraOperation(
|
|
||||||
owner = owner.internalName,
|
|
||||||
method = theName,
|
|
||||||
descriptor = Type.getMethodDescriptor(primitiveMaskBoxed, *mapTypes(spec, parameterTypes).toTypedArray()),
|
|
||||||
expectedArity = arity,
|
|
||||||
opcode = INVOKEVIRTUAL
|
|
||||||
)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds specialized [context] call with option to fallback to generic algebra operation accepting [String].
|
|
||||||
*
|
|
||||||
* @author Iaroslav Postovalov
|
|
||||||
*/
|
|
||||||
internal inline fun <T> AsmBuilder<T>.buildAlgebraOperationCall(
|
|
||||||
context: Algebra<T>,
|
|
||||||
name: String,
|
|
||||||
fallbackMethodName: String,
|
|
||||||
parameterTypes: Array<MstType>,
|
|
||||||
parameters: AsmBuilder<T>.() -> Unit
|
|
||||||
) {
|
|
||||||
contract { callsInPlace(parameters, InvocationKind.EXACTLY_ONCE) }
|
|
||||||
val arity = parameterTypes.size
|
|
||||||
loadAlgebra()
|
|
||||||
if (!buildExpectationStack(context, name, parameterTypes)) loadStringConstant(name)
|
|
||||||
parameters()
|
|
||||||
|
|
||||||
if (!tryInvokeSpecific(context, name, parameterTypes)) invokeAlgebraOperation(
|
|
||||||
owner = AsmBuilder.ALGEBRA_TYPE.internalName,
|
|
||||||
method = fallbackMethodName,
|
|
||||||
|
|
||||||
descriptor = Type.getMethodDescriptor(
|
|
||||||
AsmBuilder.OBJECT_TYPE,
|
|
||||||
AsmBuilder.STRING_TYPE,
|
|
||||||
*Array(arity) { AsmBuilder.OBJECT_TYPE }
|
|
||||||
),
|
|
||||||
|
|
||||||
expectedArity = arity
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// TODO move to common when https://github.com/h0tk3y/better-parse/pull/33 is merged
|
||||||
|
|
||||||
package kscience.kmath.ast
|
package kscience.kmath.ast
|
||||||
|
|
||||||
import com.github.h0tk3y.betterParse.combinators.*
|
import com.github.h0tk3y.betterParse.combinators.*
|
||||||
@ -17,7 +19,8 @@ import kscience.kmath.operations.RingOperations
|
|||||||
import kscience.kmath.operations.SpaceOperations
|
import kscience.kmath.operations.SpaceOperations
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO move to common after IR version is released
|
* better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4.
|
||||||
|
*
|
||||||
* @author Alexander Nozik and Iaroslav Postovalov
|
* @author Alexander Nozik and Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public object ArithmeticsEvaluator : Grammar<MST>() {
|
public object ArithmeticsEvaluator : Grammar<MST>() {
|
||||||
@ -83,7 +86,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to parse the string into [MST]. Returns [ParseResult] representing expression or error.
|
* Tries to parse the string into [MST] using [ArithmeticsEvaluator]. Returns [ParseResult] representing expression or error.
|
||||||
*
|
*
|
||||||
* @receiver the string to parse.
|
* @receiver the string to parse.
|
||||||
* @return the [MST] node.
|
* @return the [MST] node.
|
||||||
@ -91,7 +94,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
|
|||||||
public fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryParseToEnd(this)
|
public fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryParseToEnd(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the string into [MST].
|
* Parses the string into [MST] using [ArithmeticsEvaluator].
|
||||||
*
|
*
|
||||||
* @receiver the string to parse.
|
* @receiver the string to parse.
|
||||||
* @return the [MST] node.
|
* @return the [MST] node.
|
||||||
|
@ -1,24 +1,20 @@
|
|||||||
package kscience.kmath.asm
|
package kscience.kmath.asm
|
||||||
|
|
||||||
import kscience.kmath.ast.mstInField
|
import kscience.kmath.ast.*
|
||||||
import kscience.kmath.ast.mstInRing
|
|
||||||
import kscience.kmath.ast.mstInSpace
|
|
||||||
import kscience.kmath.expressions.invoke
|
import kscience.kmath.expressions.invoke
|
||||||
import kscience.kmath.operations.ByteRing
|
import kscience.kmath.operations.ByteRing
|
||||||
|
import kscience.kmath.operations.ComplexField
|
||||||
import kscience.kmath.operations.RealField
|
import kscience.kmath.operations.RealField
|
||||||
|
import kscience.kmath.operations.toComplex
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class TestAsmAlgebras {
|
internal class TestAsmConsistencyWithInterpreter {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun space() {
|
fun mstSpace() {
|
||||||
val res1 = ByteRing.mstInSpace {
|
val res1 = MstSpace.mstInSpace {
|
||||||
binaryOperation(
|
binaryOperationFunction("+")(
|
||||||
"+",
|
unaryOperationFunction("+")(
|
||||||
|
|
||||||
unaryOperation(
|
|
||||||
"+",
|
|
||||||
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
||||||
add(number(1), number(1)),
|
add(number(1), number(1)),
|
||||||
2
|
2
|
||||||
@ -27,14 +23,11 @@ internal class TestAsmAlgebras {
|
|||||||
|
|
||||||
number(1)
|
number(1)
|
||||||
) + symbol("x") + zero
|
) + symbol("x") + zero
|
||||||
}("x" to 2.toByte())
|
}("x" to MST.Numeric(2))
|
||||||
|
|
||||||
val res2 = ByteRing.mstInSpace {
|
val res2 = MstSpace.mstInSpace {
|
||||||
binaryOperation(
|
binaryOperationFunction("+")(
|
||||||
"+",
|
unaryOperationFunction("+")(
|
||||||
|
|
||||||
unaryOperation(
|
|
||||||
"+",
|
|
||||||
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
||||||
add(number(1), number(1)),
|
add(number(1), number(1)),
|
||||||
2
|
2
|
||||||
@ -43,19 +36,16 @@ internal class TestAsmAlgebras {
|
|||||||
|
|
||||||
number(1)
|
number(1)
|
||||||
) + symbol("x") + zero
|
) + symbol("x") + zero
|
||||||
}.compile()("x" to 2.toByte())
|
}.compile()("x" to MST.Numeric(2))
|
||||||
|
|
||||||
assertEquals(res1, res2)
|
assertEquals(res1, res2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun ring() {
|
fun byteRing() {
|
||||||
val res1 = ByteRing.mstInRing {
|
val res1 = ByteRing.mstInRing {
|
||||||
binaryOperation(
|
binaryOperationFunction("+")(
|
||||||
"+",
|
unaryOperationFunction("+")(
|
||||||
|
|
||||||
unaryOperation(
|
|
||||||
"+",
|
|
||||||
(symbol("x") - (2.toByte() + (multiply(
|
(symbol("x") - (2.toByte() + (multiply(
|
||||||
add(number(1), number(1)),
|
add(number(1), number(1)),
|
||||||
2
|
2
|
||||||
@ -67,17 +57,13 @@ internal class TestAsmAlgebras {
|
|||||||
}("x" to 3.toByte())
|
}("x" to 3.toByte())
|
||||||
|
|
||||||
val res2 = ByteRing.mstInRing {
|
val res2 = ByteRing.mstInRing {
|
||||||
binaryOperation(
|
binaryOperationFunction("+")(
|
||||||
"+",
|
unaryOperationFunction("+")(
|
||||||
|
|
||||||
unaryOperation(
|
|
||||||
"+",
|
|
||||||
(symbol("x") - (2.toByte() + (multiply(
|
(symbol("x") - (2.toByte() + (multiply(
|
||||||
add(number(1), number(1)),
|
add(number(1), number(1)),
|
||||||
2
|
2
|
||||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||||
),
|
),
|
||||||
|
|
||||||
number(1)
|
number(1)
|
||||||
) * number(2)
|
) * number(2)
|
||||||
}.compile()("x" to 3.toByte())
|
}.compile()("x" to 3.toByte())
|
||||||
@ -86,10 +72,9 @@ internal class TestAsmAlgebras {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun field() {
|
fun realField() {
|
||||||
val res1 = RealField.mstInField {
|
val res1 = RealField.mstInField {
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperation(
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
"+",
|
|
||||||
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||||
+ number(1),
|
+ number(1),
|
||||||
number(1) / 2 + number(2.0) * one
|
number(1) / 2 + number(2.0) * one
|
||||||
@ -97,8 +82,7 @@ internal class TestAsmAlgebras {
|
|||||||
}("x" to 2.0)
|
}("x" to 2.0)
|
||||||
|
|
||||||
val res2 = RealField.mstInField {
|
val res2 = RealField.mstInField {
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperation(
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
"+",
|
|
||||||
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||||
+ number(1),
|
+ number(1),
|
||||||
number(1) / 2 + number(2.0) * one
|
number(1) / 2 + number(2.0) * one
|
||||||
@ -107,4 +91,25 @@ internal class TestAsmAlgebras {
|
|||||||
|
|
||||||
assertEquals(res1, res2)
|
assertEquals(res1, res2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun complexField() {
|
||||||
|
val res1 = ComplexField.mstInField {
|
||||||
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
|
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||||
|
+ number(1),
|
||||||
|
number(1) / 2 + number(2.0) * one
|
||||||
|
) + zero
|
||||||
|
}("x" to 2.0.toComplex())
|
||||||
|
|
||||||
|
val res2 = ComplexField.mstInField {
|
||||||
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
|
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||||
|
+ number(1),
|
||||||
|
number(1) / 2 + number(2.0) * one
|
||||||
|
) + zero
|
||||||
|
}.compile()("x" to 2.0.toComplex())
|
||||||
|
|
||||||
|
assertEquals(res1, res2)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,14 +1,15 @@
|
|||||||
package kscience.kmath.asm
|
package kscience.kmath.asm
|
||||||
|
|
||||||
import kscience.kmath.asm.compile
|
import kscience.kmath.ast.mstInExtendedField
|
||||||
import kscience.kmath.ast.mstInField
|
import kscience.kmath.ast.mstInField
|
||||||
import kscience.kmath.ast.mstInSpace
|
import kscience.kmath.ast.mstInSpace
|
||||||
import kscience.kmath.expressions.invoke
|
import kscience.kmath.expressions.invoke
|
||||||
import kscience.kmath.operations.RealField
|
import kscience.kmath.operations.RealField
|
||||||
|
import kotlin.random.Random
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class TestAsmExpressions {
|
internal class TestAsmOperationsSupport {
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryOperationInvocation() {
|
fun testUnaryOperationInvocation() {
|
||||||
val expression = RealField.mstInSpace { -symbol("x") }.compile()
|
val expression = RealField.mstInSpace { -symbol("x") }.compile()
|
||||||
@ -28,4 +29,13 @@ internal class TestAsmExpressions {
|
|||||||
val res = RealField.mstInField { symbol("x") * 2 }("x" to 2.0)
|
val res = RealField.mstInField { symbol("x") * 2 }("x" to 2.0)
|
||||||
assertEquals(4.0, res)
|
assertEquals(4.0, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMultipleCalls() {
|
||||||
|
val e = RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile()
|
||||||
|
val r = Random(0)
|
||||||
|
var s = 0.0
|
||||||
|
repeat(1000000) { s += e("x" to r.nextDouble()) }
|
||||||
|
println(s)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package kscience.kmath.asm
|
package kscience.kmath.asm
|
||||||
|
|
||||||
import kscience.kmath.asm.compile
|
|
||||||
import kscience.kmath.ast.mstInField
|
import kscience.kmath.ast.mstInField
|
||||||
import kscience.kmath.expressions.invoke
|
import kscience.kmath.expressions.invoke
|
||||||
import kscience.kmath.operations.RealField
|
import kscience.kmath.operations.RealField
|
||||||
@ -10,44 +9,44 @@ import kotlin.test.assertEquals
|
|||||||
internal class TestAsmSpecialization {
|
internal class TestAsmSpecialization {
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryPlus() {
|
fun testUnaryPlus() {
|
||||||
val expr = RealField.mstInField { unaryOperation("+", symbol("x")) }.compile()
|
val expr = RealField.mstInField { unaryOperationFunction("+")(symbol("x")) }.compile()
|
||||||
assertEquals(2.0, expr("x" to 2.0))
|
assertEquals(2.0, expr("x" to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryMinus() {
|
fun testUnaryMinus() {
|
||||||
val expr = RealField.mstInField { unaryOperation("-", symbol("x")) }.compile()
|
val expr = RealField.mstInField { unaryOperationFunction("-")(symbol("x")) }.compile()
|
||||||
assertEquals(-2.0, expr("x" to 2.0))
|
assertEquals(-2.0, expr("x" to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAdd() {
|
fun testAdd() {
|
||||||
val expr = RealField.mstInField { binaryOperation("+", symbol("x"), symbol("x")) }.compile()
|
val expr = RealField.mstInField { binaryOperationFunction("+")(symbol("x"), symbol("x")) }.compile()
|
||||||
assertEquals(4.0, expr("x" to 2.0))
|
assertEquals(4.0, expr("x" to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSine() {
|
fun testSine() {
|
||||||
val expr = RealField.mstInField { unaryOperation("sin", symbol("x")) }.compile()
|
val expr = RealField.mstInField { unaryOperationFunction("sin")(symbol("x")) }.compile()
|
||||||
assertEquals(0.0, expr("x" to 0.0))
|
assertEquals(0.0, expr("x" to 0.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMinus() {
|
fun testMinus() {
|
||||||
val expr = RealField.mstInField { binaryOperation("-", symbol("x"), symbol("x")) }.compile()
|
val expr = RealField.mstInField { binaryOperationFunction("-")(symbol("x"), symbol("x")) }.compile()
|
||||||
assertEquals(0.0, expr("x" to 2.0))
|
assertEquals(0.0, expr("x" to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDivide() {
|
fun testDivide() {
|
||||||
val expr = RealField.mstInField { binaryOperation("/", symbol("x"), symbol("x")) }.compile()
|
val expr = RealField.mstInField { binaryOperationFunction("/")(symbol("x"), symbol("x")) }.compile()
|
||||||
assertEquals(1.0, expr("x" to 2.0))
|
assertEquals(1.0, expr("x" to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPower() {
|
fun testPower() {
|
||||||
val expr = RealField
|
val expr = RealField
|
||||||
.mstInField { binaryOperation("power", symbol("x"), number(2)) }
|
.mstInField { binaryOperationFunction("pow")(symbol("x"), number(2)) }
|
||||||
.compile()
|
.compile()
|
||||||
|
|
||||||
assertEquals(4.0, expr("x" to 2.0))
|
assertEquals(4.0, expr("x" to 2.0))
|
||||||
|
@ -9,14 +9,14 @@ import kotlin.test.assertFailsWith
|
|||||||
|
|
||||||
internal class TestAsmVariables {
|
internal class TestAsmVariables {
|
||||||
@Test
|
@Test
|
||||||
fun testVariableWithoutDefault() {
|
fun testVariable() {
|
||||||
val expr = ByteRing.mstInRing { symbol("x") }
|
val expr = ByteRing.mstInRing { symbol("x") }.compile()
|
||||||
assertEquals(1.toByte(), expr("x" to 1.toByte()))
|
assertEquals(1.toByte(), expr("x" to 1.toByte()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testVariableWithoutDefaultFails() {
|
fun testUndefinedVariableFails() {
|
||||||
val expr = ByteRing.mstInRing { symbol("x") }
|
val expr = ByteRing.mstInRing { symbol("x") }.compile()
|
||||||
assertFailsWith<IllegalStateException> { expr() }
|
assertFailsWith<NoSuchElementException> { expr() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
package kscience.kmath.ast
|
|
||||||
|
|
||||||
import kscience.kmath.asm.compile
|
|
||||||
import kscience.kmath.asm.expression
|
|
||||||
import kscience.kmath.ast.mstInField
|
|
||||||
import kscience.kmath.ast.parseMath
|
|
||||||
import kscience.kmath.expressions.invoke
|
|
||||||
import kscience.kmath.operations.Complex
|
|
||||||
import kscience.kmath.operations.ComplexField
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
internal class AsmTest {
|
|
||||||
@Test
|
|
||||||
fun `compile MST`() {
|
|
||||||
val res = ComplexField.expression("2+2*(2+2)".parseMath())()
|
|
||||||
assertEquals(Complex(10.0, 0.0), res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `compile MSTExpression`() {
|
|
||||||
val res = ComplexField.mstInField { number(2) + number(2) * (number(2) + number(2)) }.compile()()
|
|
||||||
assertEquals(Complex(10.0, 0.0), res)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,5 @@
|
|||||||
package kscience.kmath.ast
|
package kscience.kmath.ast
|
||||||
|
|
||||||
import kscience.kmath.ast.evaluate
|
|
||||||
import kscience.kmath.ast.parseMath
|
|
||||||
import kscience.kmath.operations.Field
|
import kscience.kmath.operations.Field
|
||||||
import kscience.kmath.operations.RealField
|
import kscience.kmath.operations.RealField
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package kscience.kmath.ast
|
package kscience.kmath.ast
|
||||||
|
|
||||||
import kscience.kmath.ast.evaluate
|
|
||||||
import kscience.kmath.ast.mstInField
|
|
||||||
import kscience.kmath.ast.parseMath
|
|
||||||
import kscience.kmath.expressions.invoke
|
import kscience.kmath.expressions.invoke
|
||||||
import kscience.kmath.operations.Algebra
|
import kscience.kmath.operations.Algebra
|
||||||
import kscience.kmath.operations.Complex
|
import kscience.kmath.operations.Complex
|
||||||
@ -45,10 +42,13 @@ internal class ParserTest {
|
|||||||
val magicalAlgebra = object : Algebra<String> {
|
val magicalAlgebra = object : Algebra<String> {
|
||||||
override fun symbol(value: String): String = value
|
override fun symbol(value: String): String = value
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: String): String = throw NotImplementedError()
|
override fun unaryOperationFunction(operation: String): (arg: String) -> String {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: String, right: String): String = when (operation) {
|
override fun binaryOperationFunction(operation: String): (left: String, right: String) -> String =
|
||||||
"magic" -> "$left ★ $right"
|
when (operation) {
|
||||||
|
"magic" -> { left, right -> "$left ★ $right" }
|
||||||
else -> throw NotImplementedError()
|
else -> throw NotImplementedError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ The core features of KMath:
|
|||||||
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
||||||
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
|
>
|
||||||
> }
|
> }
|
||||||
>
|
>
|
||||||
> dependencies {
|
> dependencies {
|
||||||
|
@ -7,9 +7,8 @@ import kscience.kmath.operations.*
|
|||||||
*
|
*
|
||||||
* @param algebra The algebra to provide for Expressions built.
|
* @param algebra The algebra to provide for Expressions built.
|
||||||
*/
|
*/
|
||||||
public abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(
|
public abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(public val algebra: A) :
|
||||||
public val algebra: A,
|
ExpressionAlgebra<T, Expression<T>> {
|
||||||
) : ExpressionAlgebra<T, Expression<T>> {
|
|
||||||
/**
|
/**
|
||||||
* Builds an Expression of constant expression which does not depend on arguments.
|
* Builds an Expression of constant expression which does not depend on arguments.
|
||||||
*/
|
*/
|
||||||
@ -25,19 +24,18 @@ public abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(
|
|||||||
/**
|
/**
|
||||||
* Builds an Expression of dynamic call of binary operation [operation] on [left] and [right].
|
* Builds an Expression of dynamic call of binary operation [operation] on [left] and [right].
|
||||||
*/
|
*/
|
||||||
public override fun binaryOperation(
|
public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
|
||||||
operation: String,
|
{ left, right ->
|
||||||
left: Expression<T>,
|
Expression { arguments ->
|
||||||
right: Expression<T>,
|
algebra.binaryOperationFunction(operation)(left.invoke(arguments), right.invoke(arguments))
|
||||||
): Expression<T> = Expression { arguments ->
|
}
|
||||||
algebra.binaryOperation(operation, left.invoke(arguments), right.invoke(arguments))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an Expression of dynamic call of unary operation with name [operation] on [arg].
|
* Builds an Expression of dynamic call of unary operation with name [operation] on [arg].
|
||||||
*/
|
*/
|
||||||
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> = Expression { arguments ->
|
public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> = { arg ->
|
||||||
algebra.unaryOperation(operation, arg.invoke(arguments))
|
Expression { arguments -> algebra.unaryOperationFunction(operation)(arg.invoke(arguments)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +50,7 @@ public open class FunctionalExpressionSpace<T, A : Space<T>>(algebra: A) :
|
|||||||
* Builds an Expression of addition of two another expressions.
|
* Builds an Expression of addition of two another expressions.
|
||||||
*/
|
*/
|
||||||
public override fun add(a: Expression<T>, b: Expression<T>): Expression<T> =
|
public override fun add(a: Expression<T>, b: Expression<T>): Expression<T> =
|
||||||
binaryOperation(SpaceOperations.PLUS_OPERATION, a, b)
|
binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an Expression of multiplication of expression by number.
|
* Builds an Expression of multiplication of expression by number.
|
||||||
@ -66,11 +64,11 @@ public open class FunctionalExpressionSpace<T, A : Space<T>>(algebra: A) :
|
|||||||
public operator fun T.plus(arg: Expression<T>): Expression<T> = arg + this
|
public operator fun T.plus(arg: Expression<T>): Expression<T> = arg + this
|
||||||
public operator fun T.minus(arg: Expression<T>): Expression<T> = arg - this
|
public operator fun T.minus(arg: Expression<T>): Expression<T> = arg - this
|
||||||
|
|
||||||
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
|
||||||
super<FunctionalExpressionAlgebra>.unaryOperation(operation, arg)
|
super<FunctionalExpressionAlgebra>.unaryOperationFunction(operation)
|
||||||
|
|
||||||
public override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
|
||||||
super<FunctionalExpressionAlgebra>.binaryOperation(operation, left, right)
|
super<FunctionalExpressionAlgebra>.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class FunctionalExpressionRing<T, A>(algebra: A) : FunctionalExpressionSpace<T, A>(algebra),
|
public open class FunctionalExpressionRing<T, A>(algebra: A) : FunctionalExpressionSpace<T, A>(algebra),
|
||||||
@ -82,16 +80,16 @@ public open class FunctionalExpressionRing<T, A>(algebra: A) : FunctionalExpress
|
|||||||
* Builds an Expression of multiplication of two expressions.
|
* Builds an Expression of multiplication of two expressions.
|
||||||
*/
|
*/
|
||||||
public override fun multiply(a: Expression<T>, b: Expression<T>): Expression<T> =
|
public override fun multiply(a: Expression<T>, b: Expression<T>): Expression<T> =
|
||||||
binaryOperation(RingOperations.TIMES_OPERATION, a, b)
|
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b)
|
||||||
|
|
||||||
public operator fun Expression<T>.times(arg: T): Expression<T> = this * const(arg)
|
public operator fun Expression<T>.times(arg: T): Expression<T> = this * const(arg)
|
||||||
public operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
|
public operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
|
||||||
|
|
||||||
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
|
||||||
super<FunctionalExpressionSpace>.unaryOperation(operation, arg)
|
super<FunctionalExpressionSpace>.unaryOperationFunction(operation)
|
||||||
|
|
||||||
public override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
|
||||||
super<FunctionalExpressionSpace>.binaryOperation(operation, left, right)
|
super<FunctionalExpressionSpace>.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class FunctionalExpressionField<T, A>(algebra: A) :
|
public open class FunctionalExpressionField<T, A>(algebra: A) :
|
||||||
@ -101,49 +99,49 @@ public open class FunctionalExpressionField<T, A>(algebra: A) :
|
|||||||
* Builds an Expression of division an expression by another one.
|
* Builds an Expression of division an expression by another one.
|
||||||
*/
|
*/
|
||||||
public override fun divide(a: Expression<T>, b: Expression<T>): Expression<T> =
|
public override fun divide(a: Expression<T>, b: Expression<T>): Expression<T> =
|
||||||
binaryOperation(FieldOperations.DIV_OPERATION, a, b)
|
binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b)
|
||||||
|
|
||||||
public operator fun Expression<T>.div(arg: T): Expression<T> = this / const(arg)
|
public operator fun Expression<T>.div(arg: T): Expression<T> = this / const(arg)
|
||||||
public operator fun T.div(arg: Expression<T>): Expression<T> = arg / this
|
public operator fun T.div(arg: Expression<T>): Expression<T> = arg / this
|
||||||
|
|
||||||
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
|
||||||
super<FunctionalExpressionRing>.unaryOperation(operation, arg)
|
super<FunctionalExpressionRing>.unaryOperationFunction(operation)
|
||||||
|
|
||||||
public override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
|
||||||
super<FunctionalExpressionRing>.binaryOperation(operation, left, right)
|
super<FunctionalExpressionRing>.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class FunctionalExpressionExtendedField<T, A>(algebra: A) :
|
public open class FunctionalExpressionExtendedField<T, A>(algebra: A) :
|
||||||
FunctionalExpressionField<T, A>(algebra),
|
FunctionalExpressionField<T, A>(algebra),
|
||||||
ExtendedField<Expression<T>> where A : ExtendedField<T>, A : NumericAlgebra<T> {
|
ExtendedField<Expression<T>> where A : ExtendedField<T>, A : NumericAlgebra<T> {
|
||||||
public override fun sin(arg: Expression<T>): Expression<T> =
|
public override fun sin(arg: Expression<T>): Expression<T> =
|
||||||
unaryOperation(TrigonometricOperations.SIN_OPERATION, arg)
|
unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun cos(arg: Expression<T>): Expression<T> =
|
public override fun cos(arg: Expression<T>): Expression<T> =
|
||||||
unaryOperation(TrigonometricOperations.COS_OPERATION, arg)
|
unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun asin(arg: Expression<T>): Expression<T> =
|
public override fun asin(arg: Expression<T>): Expression<T> =
|
||||||
unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg)
|
unaryOperationFunction(TrigonometricOperations.ASIN_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun acos(arg: Expression<T>): Expression<T> =
|
public override fun acos(arg: Expression<T>): Expression<T> =
|
||||||
unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg)
|
unaryOperationFunction(TrigonometricOperations.ACOS_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun atan(arg: Expression<T>): Expression<T> =
|
public override fun atan(arg: Expression<T>): Expression<T> =
|
||||||
unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg)
|
unaryOperationFunction(TrigonometricOperations.ATAN_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun power(arg: Expression<T>, pow: Number): Expression<T> =
|
public override fun power(arg: Expression<T>, pow: Number): Expression<T> =
|
||||||
binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow))
|
binaryOperationFunction(PowerOperations.POW_OPERATION)(arg, number(pow))
|
||||||
|
|
||||||
public override fun exp(arg: Expression<T>): Expression<T> =
|
public override fun exp(arg: Expression<T>): Expression<T> =
|
||||||
unaryOperation(ExponentialOperations.EXP_OPERATION, arg)
|
unaryOperationFunction(ExponentialOperations.EXP_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun ln(arg: Expression<T>): Expression<T> = unaryOperation(ExponentialOperations.LN_OPERATION, arg)
|
public override fun ln(arg: Expression<T>): Expression<T> = unaryOperationFunction(ExponentialOperations.LN_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
|
public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
|
||||||
super<FunctionalExpressionField>.unaryOperation(operation, arg)
|
super<FunctionalExpressionField>.unaryOperationFunction(operation)
|
||||||
|
|
||||||
public override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
|
public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
|
||||||
super<FunctionalExpressionField>.binaryOperation(operation, left, right)
|
super<FunctionalExpressionField>.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline fun <T, A : Space<T>> A.expressionInSpace(block: FunctionalExpressionSpace<T, A>.() -> Expression<T>): Expression<T> =
|
public inline fun <T, A : Space<T>> A.expressionInSpace(block: FunctionalExpressionSpace<T, A>.() -> Expression<T>): Expression<T> =
|
||||||
|
@ -19,9 +19,10 @@ public interface MatrixContext<T : Any, out M : Matrix<T>> : SpaceOperations<Mat
|
|||||||
public fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): M
|
public fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): M
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
public override fun binaryOperation(operation: String, left: Matrix<T>, right: Matrix<T>): M = when (operation) {
|
public override fun binaryOperationFunction(operation: String): (left: Matrix<T>, right: Matrix<T>) -> M =
|
||||||
"dot" -> left dot right
|
when (operation) {
|
||||||
else -> super.binaryOperation(operation, left, right) as M
|
"dot" -> { left, right -> left dot right }
|
||||||
|
else -> super.binaryOperationFunction(operation) as (Matrix<T>, Matrix<T>) -> M
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,31 +13,79 @@ public annotation class KMathContext
|
|||||||
*/
|
*/
|
||||||
public interface Algebra<T> {
|
public interface Algebra<T> {
|
||||||
/**
|
/**
|
||||||
* Wrap raw string or variable
|
* Wraps a raw string to [T] object. This method is designed for three purposes:
|
||||||
|
*
|
||||||
|
* 1. Mathematical constants (`e`, `pi`).
|
||||||
|
* 2. Variables for expression-like contexts (`a`, `b`, `c`...).
|
||||||
|
* 3. Literals (`{1, 2}`, (`(3; 4)`)).
|
||||||
|
*
|
||||||
|
* In case if algebra can't parse the string, this method must throw [kotlin.IllegalStateException].
|
||||||
|
*
|
||||||
|
* @param value the raw string.
|
||||||
|
* @return an object.
|
||||||
*/
|
*/
|
||||||
public fun symbol(value: String): T = error("Wrapping of '$value' is not supported in $this")
|
public fun symbol(value: String): T = error("Wrapping of '$value' is not supported in $this")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamic call of unary operation with name [operation] on [arg]
|
* Dynamically dispatches an unary operation with the certain name.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with second `unaryOperation` overload:
|
||||||
|
* i.e. `unaryOperationFunction(a)(b) == unaryOperation(a, b)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @return an operation.
|
||||||
*/
|
*/
|
||||||
public fun unaryOperation(operation: String, arg: T): T
|
public fun unaryOperationFunction(operation: String): (arg: T) -> T =
|
||||||
|
error("Unary operation $operation not defined in $this")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currying version of [unaryOperation]
|
* Dynamically invokes an unary operation with the certain name.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with second [unaryOperationFunction] overload:
|
||||||
|
* i.e. `unaryOperationFunction(a)(b) == unaryOperation(a, b)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @param arg the argument of operation.
|
||||||
|
* @return a result of operation.
|
||||||
*/
|
*/
|
||||||
public fun unaryOperationFunction(operation: String): (T) -> T = { unaryOperation(operation, it) }
|
public fun unaryOperation(operation: String, arg: T): T = unaryOperationFunction(operation)(arg)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamic call of binary operation [operation] on [left] and [right]
|
* Dynamically dispatches a binary operation with the certain name.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with second [binaryOperationFunction] overload:
|
||||||
|
* i.e. `binaryOperationFunction(a)(b, c) == binaryOperation(a, b, c)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @return an operation.
|
||||||
*/
|
*/
|
||||||
public fun binaryOperation(operation: String, left: T, right: T): T
|
public fun binaryOperationFunction(operation: String): (left: T, right: T) -> T =
|
||||||
|
error("Binary operation $operation not defined in $this")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Curring version of [binaryOperation]
|
* Dynamically invokes a binary operation with the certain name.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with second [binaryOperationFunction] overload:
|
||||||
|
* i.e. `binaryOperationFunction(a)(b, c) == binaryOperation(a, b, c)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @param left the first argument of operation.
|
||||||
|
* @param right the second argument of operation.
|
||||||
|
* @return a result of operation.
|
||||||
*/
|
*/
|
||||||
public fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = { left, right ->
|
public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperationFunction(operation)(left, right)
|
||||||
binaryOperation(operation, left, right)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,37 +95,76 @@ public interface Algebra<T> {
|
|||||||
*/
|
*/
|
||||||
public interface NumericAlgebra<T> : Algebra<T> {
|
public interface NumericAlgebra<T> : Algebra<T> {
|
||||||
/**
|
/**
|
||||||
* Wraps a number.
|
* Wraps a number to [T] object.
|
||||||
|
*
|
||||||
|
* @param value the number to wrap.
|
||||||
|
* @return an object.
|
||||||
*/
|
*/
|
||||||
public fun number(value: Number): T
|
public fun number(value: Number): T
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamic call of binary operation [operation] on [left] and [right] where left element is [Number].
|
* Dynamically dispatches a binary operation with the certain name with numeric first argument.
|
||||||
*/
|
*
|
||||||
public fun leftSideNumberOperation(operation: String, left: Number, right: T): T =
|
* This function must follow two properties:
|
||||||
binaryOperation(operation, number(left), right)
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
/**
|
* 2. This function is symmetric with the other [leftSideNumberOperation] overload:
|
||||||
* Curring version of [leftSideNumberOperation]
|
* i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @return an operation.
|
||||||
*/
|
*/
|
||||||
public fun leftSideNumberOperationFunction(operation: String): (left: Number, right: T) -> T =
|
public fun leftSideNumberOperationFunction(operation: String): (left: Number, right: T) -> T =
|
||||||
{ left: Number, right: T ->
|
{ l, r -> binaryOperationFunction(operation)(number(l), r) }
|
||||||
leftSideNumberOperation(operation, left, right)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamic call of binary operation [operation] on [left] and [right] where right element is [Number].
|
* Dynamically invokes a binary operation with the certain name with numeric first argument.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with second [leftSideNumberOperation] overload:
|
||||||
|
* i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @param left the first argument of operation.
|
||||||
|
* @param right the second argument of operation.
|
||||||
|
* @return a result of operation.
|
||||||
*/
|
*/
|
||||||
public fun rightSideNumberOperation(operation: String, left: T, right: Number): T =
|
public fun leftSideNumberOperation(operation: String, left: Number, right: T): T =
|
||||||
leftSideNumberOperation(operation, right, left)
|
leftSideNumberOperationFunction(operation)(left, right)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Curring version of [rightSideNumberOperation]
|
* Dynamically dispatches a binary operation with the certain name with numeric first argument.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload:
|
||||||
|
* i.e. `rightSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @return an operation.
|
||||||
*/
|
*/
|
||||||
public fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T =
|
public fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T =
|
||||||
{ left: T, right: Number ->
|
{ l, r -> binaryOperationFunction(operation)(l, number(r)) }
|
||||||
rightSideNumberOperation(operation, left, right)
|
|
||||||
}
|
/**
|
||||||
|
* Dynamically invokes a binary operation with the certain name with numeric second argument.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload:
|
||||||
|
* i.e. `rightSideNumberOperationFunction(a)(b, c) == rightSideNumberOperation(a, b, c)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @param left the first argument of operation.
|
||||||
|
* @param right the second argument of operation.
|
||||||
|
* @return a result of operation.
|
||||||
|
*/
|
||||||
|
public fun rightSideNumberOperation(operation: String, left: T, right: Number): T =
|
||||||
|
rightSideNumberOperationFunction(operation)(left, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -174,26 +261,26 @@ public interface SpaceOperations<T> : Algebra<T> {
|
|||||||
*/
|
*/
|
||||||
public operator fun Number.times(b: T): T = b * this
|
public operator fun Number.times(b: T): T = b * this
|
||||||
|
|
||||||
override fun unaryOperation(operation: String, arg: T): T = when (operation) {
|
public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) {
|
||||||
PLUS_OPERATION -> arg
|
PLUS_OPERATION -> { arg -> arg }
|
||||||
MINUS_OPERATION -> -arg
|
MINUS_OPERATION -> { arg -> -arg }
|
||||||
else -> error("Unary operation $operation not defined in $this")
|
else -> super.unaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) {
|
public override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) {
|
||||||
PLUS_OPERATION -> add(left, right)
|
PLUS_OPERATION -> ::add
|
||||||
MINUS_OPERATION -> left - right
|
MINUS_OPERATION -> { left, right -> left - right }
|
||||||
else -> error("Binary operation $operation not defined in $this")
|
else -> super.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
/**
|
/**
|
||||||
* The identifier of addition.
|
* The identifier of addition and unary positive operator.
|
||||||
*/
|
*/
|
||||||
public const val PLUS_OPERATION: String = "+"
|
public const val PLUS_OPERATION: String = "+"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The identifier of subtraction (and negation).
|
* The identifier of subtraction and unary negative operator.
|
||||||
*/
|
*/
|
||||||
public const val MINUS_OPERATION: String = "-"
|
public const val MINUS_OPERATION: String = "-"
|
||||||
}
|
}
|
||||||
@ -235,9 +322,9 @@ public interface RingOperations<T> : SpaceOperations<T> {
|
|||||||
*/
|
*/
|
||||||
public operator fun T.times(b: T): T = multiply(this, b)
|
public operator fun T.times(b: T): T = multiply(this, b)
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) {
|
public override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) {
|
||||||
TIMES_OPERATION -> multiply(left, right)
|
TIMES_OPERATION -> ::multiply
|
||||||
else -> super.binaryOperation(operation, left, right)
|
else -> super.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
@ -260,21 +347,7 @@ public interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
|
|||||||
*/
|
*/
|
||||||
public val one: T
|
public val one: T
|
||||||
|
|
||||||
override fun number(value: Number): T = one * value.toDouble()
|
public override fun number(value: Number): T = one * value.toDouble()
|
||||||
|
|
||||||
override fun leftSideNumberOperation(operation: String, left: Number, right: T): T = when (operation) {
|
|
||||||
SpaceOperations.PLUS_OPERATION -> left + right
|
|
||||||
SpaceOperations.MINUS_OPERATION -> left - right
|
|
||||||
RingOperations.TIMES_OPERATION -> left * right
|
|
||||||
else -> super.leftSideNumberOperation(operation, left, right)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun rightSideNumberOperation(operation: String, left: T, right: Number): T = when (operation) {
|
|
||||||
SpaceOperations.PLUS_OPERATION -> left + right
|
|
||||||
SpaceOperations.MINUS_OPERATION -> left - right
|
|
||||||
RingOperations.TIMES_OPERATION -> left * right
|
|
||||||
else -> super.rightSideNumberOperation(operation, left, right)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Addition of element and scalar.
|
* Addition of element and scalar.
|
||||||
@ -336,9 +409,9 @@ public interface FieldOperations<T> : RingOperations<T> {
|
|||||||
*/
|
*/
|
||||||
public operator fun T.div(b: T): T = divide(this, b)
|
public operator fun T.div(b: T): T = divide(this, b)
|
||||||
|
|
||||||
override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) {
|
public override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) {
|
||||||
DIV_OPERATION -> divide(left, right)
|
DIV_OPERATION -> ::divide
|
||||||
else -> super.binaryOperation(operation, left, right)
|
else -> super.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package kscience.kmath.operations
|
package kscience.kmath.operations
|
||||||
|
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlin.math.pow as kpow
|
import kotlin.math.pow as kpow
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,23 +14,23 @@ public interface ExtendedFieldOperations<T> :
|
|||||||
public override fun tan(arg: T): T = sin(arg) / cos(arg)
|
public override fun tan(arg: T): T = sin(arg) / cos(arg)
|
||||||
public override fun tanh(arg: T): T = sinh(arg) / cosh(arg)
|
public override fun tanh(arg: T): T = sinh(arg) / cosh(arg)
|
||||||
|
|
||||||
public override fun unaryOperation(operation: String, arg: T): T = when (operation) {
|
public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) {
|
||||||
TrigonometricOperations.COS_OPERATION -> cos(arg)
|
TrigonometricOperations.COS_OPERATION -> ::cos
|
||||||
TrigonometricOperations.SIN_OPERATION -> sin(arg)
|
TrigonometricOperations.SIN_OPERATION -> ::sin
|
||||||
TrigonometricOperations.TAN_OPERATION -> tan(arg)
|
TrigonometricOperations.TAN_OPERATION -> ::tan
|
||||||
TrigonometricOperations.ACOS_OPERATION -> acos(arg)
|
TrigonometricOperations.ACOS_OPERATION -> ::acos
|
||||||
TrigonometricOperations.ASIN_OPERATION -> asin(arg)
|
TrigonometricOperations.ASIN_OPERATION -> ::asin
|
||||||
TrigonometricOperations.ATAN_OPERATION -> atan(arg)
|
TrigonometricOperations.ATAN_OPERATION -> ::atan
|
||||||
HyperbolicOperations.COSH_OPERATION -> cosh(arg)
|
HyperbolicOperations.COSH_OPERATION -> ::cosh
|
||||||
HyperbolicOperations.SINH_OPERATION -> sinh(arg)
|
HyperbolicOperations.SINH_OPERATION -> ::sinh
|
||||||
HyperbolicOperations.TANH_OPERATION -> tanh(arg)
|
HyperbolicOperations.TANH_OPERATION -> ::tanh
|
||||||
HyperbolicOperations.ACOSH_OPERATION -> acosh(arg)
|
HyperbolicOperations.ACOSH_OPERATION -> ::acosh
|
||||||
HyperbolicOperations.ASINH_OPERATION -> asinh(arg)
|
HyperbolicOperations.ASINH_OPERATION -> ::asinh
|
||||||
HyperbolicOperations.ATANH_OPERATION -> atanh(arg)
|
HyperbolicOperations.ATANH_OPERATION -> ::atanh
|
||||||
PowerOperations.SQRT_OPERATION -> sqrt(arg)
|
PowerOperations.SQRT_OPERATION -> ::sqrt
|
||||||
ExponentialOperations.EXP_OPERATION -> exp(arg)
|
ExponentialOperations.EXP_OPERATION -> ::exp
|
||||||
ExponentialOperations.LN_OPERATION -> ln(arg)
|
ExponentialOperations.LN_OPERATION -> ::ln
|
||||||
else -> super.unaryOperation(operation, arg)
|
else -> super<FieldOperations>.unaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,9 +45,10 @@ public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T> {
|
|||||||
public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one)))
|
public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one)))
|
||||||
public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2
|
public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2
|
||||||
|
|
||||||
public override fun rightSideNumberOperation(operation: String, left: T, right: Number): T = when (operation) {
|
public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T =
|
||||||
PowerOperations.POW_OPERATION -> power(left, right)
|
when (operation) {
|
||||||
else -> super.rightSideNumberOperation(operation, left, right)
|
PowerOperations.POW_OPERATION -> ::power
|
||||||
|
else -> super.rightSideNumberOperationFunction(operation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,9 +80,10 @@ public object RealField : ExtendedField<Double>, Norm<Double, Double> {
|
|||||||
public override val one: Double
|
public override val one: Double
|
||||||
get() = 1.0
|
get() = 1.0
|
||||||
|
|
||||||
public override fun binaryOperation(operation: String, left: Double, right: Double): Double = when (operation) {
|
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
||||||
PowerOperations.POW_OPERATION -> left pow right
|
when (operation) {
|
||||||
else -> super.binaryOperation(operation, left, right)
|
PowerOperations.POW_OPERATION -> ::power
|
||||||
|
else -> super.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override inline fun add(a: Double, b: Double): Double = a + b
|
public override inline fun add(a: Double, b: Double): Double = a + b
|
||||||
@ -130,9 +131,9 @@ public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
|
|||||||
public override val one: Float
|
public override val one: Float
|
||||||
get() = 1.0f
|
get() = 1.0f
|
||||||
|
|
||||||
public override fun binaryOperation(operation: String, left: Float, right: Float): Float = when (operation) {
|
public override fun binaryOperationFunction(operation: String): (left: Float, right: Float) -> Float = when (operation) {
|
||||||
PowerOperations.POW_OPERATION -> left pow right
|
PowerOperations.POW_OPERATION -> ::power
|
||||||
else -> super.binaryOperation(operation, left, right)
|
else -> super.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override inline fun add(a: Float, b: Float): Float = a + b
|
public override inline fun add(a: Float, b: Float): Float = a + b
|
||||||
@ -247,10 +248,10 @@ public object ByteRing : Ring<Byte>, Norm<Byte, Byte> {
|
|||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||||
public object LongRing : Ring<Long>, Norm<Long, Long> {
|
public object LongRing : Ring<Long>, Norm<Long, Long> {
|
||||||
public override val zero: Long
|
public override val zero: Long
|
||||||
get() = 0
|
get() = 0L
|
||||||
|
|
||||||
public override val one: Long
|
public override val one: Long
|
||||||
get() = 1
|
get() = 1L
|
||||||
|
|
||||||
public override inline fun add(a: Long, b: Long): Long = a + b
|
public override inline fun add(a: Long, b: Long): Long = a + b
|
||||||
public override inline fun multiply(a: Long, k: Number): Long = a * k.toLong()
|
public override inline fun multiply(a: Long, k: Number): Long = a * k.toLong()
|
||||||
|
@ -12,6 +12,8 @@ internal class FieldVerifier<T>(override val algebra: Field<T>, a: T, b: T, c: T
|
|||||||
super.verify()
|
super.verify()
|
||||||
|
|
||||||
algebra {
|
algebra {
|
||||||
|
assertEquals(a + b, b + a, "Addition in $algebra is not commutative.")
|
||||||
|
assertEquals(a * b, b * a, "Multiplication in $algebra is not commutative.")
|
||||||
assertNotEquals(a / b, b / a, "Division in $algebra is not anti-commutative.")
|
assertNotEquals(a / b, b / a, "Division in $algebra is not anti-commutative.")
|
||||||
assertNotEquals((a / b) / c, a / (b / c), "Division in $algebra is associative.")
|
assertNotEquals((a / b) / c, a / (b / c), "Division in $algebra is associative.")
|
||||||
assertEquals((a + b) / c, (a / c) + (b / c), "Division in $algebra is not right-distributive.")
|
assertEquals((a + b) / c, (a / c) + (b / c), "Division in $algebra is not right-distributive.")
|
||||||
|
@ -10,7 +10,7 @@ internal open class RingVerifier<T>(override val algebra: Ring<T>, a: T, b: T, c
|
|||||||
super.verify()
|
super.verify()
|
||||||
|
|
||||||
algebra {
|
algebra {
|
||||||
assertEquals(a * b, a * b, "Multiplication in $algebra is not commutative.")
|
assertEquals(a + b, b + a, "Addition in $algebra is not commutative.")
|
||||||
assertEquals(a * b * c, a * (b * c), "Multiplication in $algebra is not associative.")
|
assertEquals(a * b * c, a * (b * c), "Multiplication in $algebra is not associative.")
|
||||||
assertEquals(c * (a + b), (c * a) + (c * b), "Multiplication in $algebra is not distributive.")
|
assertEquals(c * (a + b), (c * a) + (c * b), "Multiplication in $algebra is not distributive.")
|
||||||
assertEquals(a * one, one * a, "$one in $algebra is not a neutral multiplication element.")
|
assertEquals(a * one, one * a, "$one in $algebra is not a neutral multiplication element.")
|
||||||
|
@ -15,7 +15,6 @@ internal open class SpaceVerifier<T>(
|
|||||||
AlgebraicVerifier<T, Space<T>> {
|
AlgebraicVerifier<T, Space<T>> {
|
||||||
override fun verify() {
|
override fun verify() {
|
||||||
algebra {
|
algebra {
|
||||||
assertEquals(a + b, b + a, "Addition in $algebra is not commutative.")
|
|
||||||
assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.")
|
assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.")
|
||||||
assertEquals(x * (a + b), x * a + x * b, "Addition in $algebra is not distributive.")
|
assertEquals(x * (a + b), x * a + x * b, "Addition in $algebra is not distributive.")
|
||||||
assertEquals((a + b) * x, a * x + b * x, "Addition in $algebra is not distributive.")
|
assertEquals((a + b) * x, a * x + b * x, "Addition in $algebra is not distributive.")
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
package kscience.kmath.structures
|
package kscience.kmath.structures
|
||||||
|
|
||||||
|
import kscience.kmath.operations.internal.FieldVerifier
|
||||||
|
import kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
internal class NDFieldTest {
|
||||||
|
@Test
|
||||||
|
fun verify() {
|
||||||
|
(NDField.real(12, 32)) { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) }
|
||||||
|
}
|
||||||
|
|
||||||
class NDFieldTest {
|
|
||||||
@Test
|
@Test
|
||||||
fun testStrides() {
|
fun testStrides() {
|
||||||
val ndArray = NDElement.real(intArrayOf(10, 10)) { (it[0] + it[1]).toDouble() }
|
val ndArray = NDElement.real(intArrayOf(10, 10)) { (it[0] + it[1]).toDouble() }
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
||||||
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
|
>
|
||||||
> }
|
> }
|
||||||
>
|
>
|
||||||
> dependencies {
|
> dependencies {
|
||||||
|
@ -23,7 +23,7 @@ This subproject implements the following features:
|
|||||||
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
||||||
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
|
>
|
||||||
> }
|
> }
|
||||||
>
|
>
|
||||||
> dependencies {
|
> dependencies {
|
||||||
|
Loading…
Reference in New Issue
Block a user