Fix minor problems, update README
This commit is contained in:
parent
c738fb1f2a
commit
d631c048c7
@ -38,7 +38,9 @@ This subproject implements the following features:
|
|||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
|
|
||||||
## 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 +57,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 +85,30 @@ 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).
|
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.
|
||||||
|
@ -27,7 +27,9 @@ public object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
|||||||
public 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 = binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b)
|
||||||
public override operator fun MST.unaryPlus(): MST.Unary = unaryOperation(SpaceOperations.PLUS_OPERATION)(this)
|
public override operator fun MST.unaryPlus(): MST.Unary = unaryOperation(SpaceOperations.PLUS_OPERATION)(this)
|
||||||
public override operator fun MST.unaryMinus(): MST.Unary = unaryOperation(SpaceOperations.MINUS_OPERATION)(this)
|
public override operator fun MST.unaryMinus(): MST.Unary = unaryOperation(SpaceOperations.MINUS_OPERATION)(this)
|
||||||
public override operator fun MST.minus(b: MST): MST.Binary = binaryOperation(SpaceOperations.MINUS_OPERATION)(this, b)
|
|
||||||
|
public override operator fun MST.minus(b: MST): MST.Binary =
|
||||||
|
binaryOperation(SpaceOperations.MINUS_OPERATION)(this, b)
|
||||||
|
|
||||||
public override fun multiply(a: MST, k: Number): MST.Binary =
|
public override fun multiply(a: MST, k: Number): MST.Binary =
|
||||||
binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k))
|
binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k))
|
||||||
|
@ -2,13 +2,16 @@ 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.ast.mstInField
|
||||||
import kscience.kmath.expressions.Expression
|
import kscience.kmath.expressions.Expression
|
||||||
|
import kscience.kmath.operations.RealField
|
||||||
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.Type.*
|
||||||
import org.objectweb.asm.commons.InstructionAdapter
|
import org.objectweb.asm.commons.InstructionAdapter
|
||||||
import java.lang.invoke.MethodHandles
|
import java.lang.invoke.MethodHandles
|
||||||
import java.lang.invoke.MethodType
|
import java.lang.invoke.MethodType
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
import java.util.stream.Collectors.toMap
|
import java.util.stream.Collectors.toMap
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
@ -82,7 +85,7 @@ internal class AsmBuilder<T>(
|
|||||||
ACC_PUBLIC or ACC_FINAL,
|
ACC_PUBLIC or ACC_FINAL,
|
||||||
"invoke",
|
"invoke",
|
||||||
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
|
||||||
@ -159,7 +162,7 @@ internal class AsmBuilder<T>(
|
|||||||
"<init>",
|
"<init>",
|
||||||
getMethodDescriptor(VOID_TYPE, *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }),
|
getMethodDescriptor(VOID_TYPE, *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }),
|
||||||
null,
|
null,
|
||||||
null
|
null,
|
||||||
).instructionAdapter {
|
).instructionAdapter {
|
||||||
val l0 = label()
|
val l0 = label()
|
||||||
load(0, classType)
|
load(0, classType)
|
||||||
@ -190,6 +193,7 @@ internal class AsmBuilder<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val cls = classLoader.defineClass(className, classWriter.toByteArray())
|
val cls = classLoader.defineClass(className, classWriter.toByteArray())
|
||||||
|
java.io.File("dump.class").writeBytes(classWriter.toByteArray())
|
||||||
val l = MethodHandles.publicLookup()
|
val l = MethodHandles.publicLookup()
|
||||||
|
|
||||||
if (hasConstants)
|
if (hasConstants)
|
||||||
@ -334,5 +338,10 @@ internal class AsmBuilder<T>(
|
|||||||
* ASM type for MapIntrinsics.
|
* ASM type for MapIntrinsics.
|
||||||
*/
|
*/
|
||||||
val MAP_INTRINSICS_TYPE: Type by lazy { 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") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@ package kscience.kmath.ast
|
|||||||
|
|
||||||
import kscience.kmath.asm.compile
|
import kscience.kmath.asm.compile
|
||||||
import kscience.kmath.asm.expression
|
import kscience.kmath.asm.expression
|
||||||
import kscience.kmath.ast.mstInField
|
|
||||||
import kscience.kmath.ast.parseMath
|
|
||||||
import kscience.kmath.expressions.invoke
|
import kscience.kmath.expressions.invoke
|
||||||
import kscience.kmath.operations.Complex
|
import kscience.kmath.operations.Complex
|
||||||
import kscience.kmath.operations.ComplexField
|
import kscience.kmath.operations.ComplexField
|
||||||
|
@ -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
|
||||||
|
@ -275,12 +275,12 @@ public interface SpaceOperations<T> : Algebra<T> {
|
|||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
/**
|
/**
|
||||||
* The identifier of addition and unary positive.
|
* 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 unary negation.
|
* The identifier of subtraction and unary negative operator.
|
||||||
*/
|
*/
|
||||||
public const val MINUS_OPERATION: String = "-"
|
public const val MINUS_OPERATION: String = "-"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user