Task and data input validation moved to JVM

This commit is contained in:
Alexander Nozik 2020-12-29 22:19:11 +03:00
parent 030f3ed6fe
commit 8b1d5eb69e
27 changed files with 429 additions and 479 deletions

View File

@ -326,7 +326,3 @@ public final class hep/dataforge/provider/ProviderKt {
public static final fun top (Lhep/dataforge/provider/Provider;Ljava/lang/String;Lkotlin/reflect/KClass;)Ljava/util/Map;
}
public abstract interface annotation class hep/dataforge/provider/Type : java/lang/annotation/Annotation {
public abstract fun id ()Ljava/lang/String;
}

View File

@ -6,7 +6,7 @@ import hep.dataforge.meta.MetaRepr
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.provider.Provider
import hep.dataforge.provider.Type
import hep.dataforge.type.Type
/**
* The interface to define a Context plugin. A plugin stores all runtime features of a context.

View File

@ -1,6 +1,6 @@
package hep.dataforge.context
import hep.dataforge.provider.Type
import hep.dataforge.type.Type
import kotlin.reflect.KClass
@Type(PluginFactory.TYPE)

View File

@ -4,6 +4,7 @@ import hep.dataforge.context.Context
import hep.dataforge.context.gather
import hep.dataforge.meta.DFExperimental
import hep.dataforge.names.Name
import hep.dataforge.type.Type
import kotlin.reflect.KClass
import kotlin.reflect.full.findAnnotation

View File

@ -26,6 +26,24 @@ public final class hep/dataforge/data/ActionKt {
public static final fun then (Lhep/dataforge/data/Action;Lhep/dataforge/data/Action;)Lhep/dataforge/data/Action;
}
public final class hep/dataforge/data/ComputationData : hep/dataforge/data/ComputationGoal, hep/dataforge/data/Data {
public fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
public synthetic fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun getMeta ()Lhep/dataforge/meta/Meta;
public fun getType ()Lkotlin/reflect/KClass;
public fun toMeta ()Lhep/dataforge/meta/Meta;
}
public class hep/dataforge/data/ComputationGoal : hep/dataforge/data/Goal {
public fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
public synthetic fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getBlock ()Lkotlin/jvm/functions/Function2;
public fun getDependencies ()Ljava/util/Collection;
public final fun getResult ()Lkotlinx/coroutines/Deferred;
public fun reset ()V
public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
}
public final class hep/dataforge/data/CoroutineMonitor : kotlin/coroutines/CoroutineContext$Element {
public static final field Companion Lhep/dataforge/data/CoroutineMonitor$Companion;
public fun <init> ()V
@ -79,14 +97,6 @@ public final class hep/dataforge/data/Data$DefaultImpls {
public static fun toMeta (Lhep/dataforge/data/Data;)Lhep/dataforge/meta/Meta;
}
public final class hep/dataforge/data/DataCastKt {
public static final fun canCast (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Z
public static final fun cast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
public static final fun cast (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
public static final fun ensureType (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)V
public static final fun upcast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
}
public final class hep/dataforge/data/DataFilter : hep/dataforge/meta/Scheme {
public static final field Companion Lhep/dataforge/data/DataFilter$Companion;
public fun <init> ()V
@ -129,17 +139,22 @@ public final class hep/dataforge/data/DataItem$Node : hep/dataforge/data/DataIte
}
public final class hep/dataforge/data/DataJVMKt {
public static final fun canCast (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Z
public static final fun cast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
public static final fun cast (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
public static final fun ensureType (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)V
public static final fun filterIsInstance (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
public static final fun filterIsInstance (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataItem;
public static final fun filterIsInstance (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
public static final fun get (Lhep/dataforge/data/Data;)Ljava/lang/Object;
public static final fun upcast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
}
public final class hep/dataforge/data/DataKt {
public static final fun map (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Data;
public static synthetic fun map$default (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Data;
public static final fun reduce (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/DynamicData;
public static synthetic fun reduce$default (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/DynamicData;
public static final fun reduce (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/ComputationData;
public static synthetic fun reduce$default (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/ComputationData;
}
public abstract interface class hep/dataforge/data/DataNode : hep/dataforge/meta/MetaRepr {
@ -164,27 +179,16 @@ public final class hep/dataforge/data/DataNode$DefaultImpls {
}
public final class hep/dataforge/data/DataNodeKt {
public static final fun asSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
public static final fun builder (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/DataTreeBuilder;
public static final fun dataSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/Data;)V
public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/Data;)V
public static final fun filter (Lhep/dataforge/data/DataNode;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/DataNode;
public static final fun first (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/Data;
public static final fun get (Lhep/dataforge/data/DataNode;Lhep/dataforge/names/Name;)Lhep/dataforge/data/DataItem;
public static final fun get (Lhep/dataforge/data/DataNode;Ljava/lang/String;)Lhep/dataforge/data/DataItem;
public static final fun getData (Lhep/dataforge/data/DataItem;)Lhep/dataforge/data/Data;
public static final fun getNode (Lhep/dataforge/data/DataItem;)Lhep/dataforge/data/DataNode;
public static final fun itemSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
public static final fun iterator (Lhep/dataforge/data/DataNode;)Ljava/util/Iterator;
public static final fun join (Lhep/dataforge/data/DataNode;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/DataNode;)V
public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
}
public final class hep/dataforge/data/DataTree : hep/dataforge/data/DataNode {
@ -214,6 +218,20 @@ public final class hep/dataforge/data/DataTreeBuilder {
public final fun update (Lhep/dataforge/data/DataNode;)V
}
public final class hep/dataforge/data/DataTreeBuilderKt {
public static final fun builder (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/DataTreeBuilder;
public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/Data;)V
public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/Data;)V
public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/DataNode;)V
public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
}
public final class hep/dataforge/data/Dependencies : kotlin/coroutines/CoroutineContext$Element {
public static final field Companion Lhep/dataforge/data/Dependencies$Companion;
public fun <init> (Ljava/util/Collection;)V
@ -228,24 +246,6 @@ public final class hep/dataforge/data/Dependencies : kotlin/coroutines/Coroutine
public final class hep/dataforge/data/Dependencies$Companion : kotlin/coroutines/CoroutineContext$Key {
}
public final class hep/dataforge/data/DynamicData : hep/dataforge/data/DynamicGoal, hep/dataforge/data/Data {
public fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
public synthetic fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun getMeta ()Lhep/dataforge/meta/Meta;
public fun getType ()Lkotlin/reflect/KClass;
public fun toMeta ()Lhep/dataforge/meta/Meta;
}
public class hep/dataforge/data/DynamicGoal : hep/dataforge/data/Goal {
public fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
public synthetic fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getBlock ()Lkotlin/jvm/functions/Function2;
public fun getDependencies ()Ljava/util/Collection;
public final fun getResult ()Lkotlinx/coroutines/Deferred;
public fun reset ()V
public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
}
public final class hep/dataforge/data/FragmentRule {
public field result Lkotlin/jvm/functions/Function2;
public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaBuilder;)V
@ -302,8 +302,7 @@ public final class hep/dataforge/data/JoinGroup {
}
public final class hep/dataforge/data/MapAction : hep/dataforge/data/Action {
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
public final fun getInputType ()Lkotlin/reflect/KClass;
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
public final fun getOutputType ()Lkotlin/reflect/KClass;
public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
public fun isTerminal ()Z
@ -335,8 +334,7 @@ public final class hep/dataforge/data/NamedData : hep/dataforge/data/Data {
}
public final class hep/dataforge/data/ReduceAction : hep/dataforge/data/Action {
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
public final fun getInputType ()Lkotlin/reflect/KClass;
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
public final fun getOutputType ()Lkotlin/reflect/KClass;
public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
public fun isTerminal ()Z
@ -357,8 +355,7 @@ public final class hep/dataforge/data/ReduceGroupBuilder {
}
public final class hep/dataforge/data/SplitAction : hep/dataforge/data/Action {
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
public final fun getInputType ()Lkotlin/reflect/KClass;
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
public final fun getOutputType ()Lkotlin/reflect/KClass;
public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
public fun isTerminal ()Z

View File

@ -3,6 +3,7 @@ package hep.dataforge.data
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaRepr
import hep.dataforge.meta.isEmpty
import hep.dataforge.type.Type
import kotlinx.coroutines.CoroutineScope
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
@ -11,7 +12,8 @@ import kotlin.reflect.KClass
/**
* A data element characterized by its meta
*/
public interface Data<out T : Any> : Goal<T>, MetaRepr{
@Type(Data.TYPE)
public interface Data<out T : Any> : Goal<T>, MetaRepr {
/**
* Type marker for the data. The type is known before the calculation takes place so it could be checked.
*/
@ -22,9 +24,9 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
*/
public val meta: Meta
override fun toMeta(): Meta = Meta {
"type" put (type.simpleName?:"undefined")
if(!meta.isEmpty()) {
override fun toMeta(): Meta = Meta {
"type" put (type.simpleName ?: "undefined")
if (!meta.isEmpty()) {
"meta" put meta
}
}
@ -37,14 +39,14 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(),
block: suspend CoroutineScope.() -> T
): Data<T> = DynamicData(type, meta, context, dependencies, block)
block: suspend CoroutineScope.() -> T,
): Data<T> = ComputationData(type, meta, context, dependencies, block)
public inline operator fun <reified T : Any> invoke(
meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(),
noinline block: suspend CoroutineScope.() -> T
noinline block: suspend CoroutineScope.() -> T,
): Data<T> = invoke(T::class, meta, context, dependencies, block)
public operator fun <T : Any> invoke(
@ -53,7 +55,7 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(),
block: suspend CoroutineScope.() -> T
block: suspend CoroutineScope.() -> T,
): Data<T> = NamedData(name, invoke(type, meta, context, dependencies, block))
public inline operator fun <reified T : Any> invoke(
@ -61,7 +63,7 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(),
noinline block: suspend CoroutineScope.() -> T
noinline block: suspend CoroutineScope.() -> T,
): Data<T> =
invoke(name, T::class, meta, context, dependencies, block)
@ -71,17 +73,17 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
}
public class DynamicData<T : Any>(
public class ComputationData<T : Any>(
override val type: KClass<out T>,
override val meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(),
block: suspend CoroutineScope.() -> T
) : Data<T>, DynamicGoal<T>(context, dependencies, block)
block: suspend CoroutineScope.() -> T,
) : Data<T>, ComputationGoal<T>(context, dependencies, block)
public class StaticData<T : Any>(
value: T,
override val meta: Meta = Meta.EMPTY
override val meta: Meta = Meta.EMPTY,
) : Data<T>, StaticGoal<T>(value) {
override val type: KClass<out T> get() = value::class
}
@ -92,8 +94,8 @@ public fun <T : Any, R : Any> Data<T>.map(
outputType: KClass<out R>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta = this.meta,
block: suspend CoroutineScope.(T) -> R
): Data<R> = DynamicData(outputType, meta, coroutineContext, listOf(this)) {
block: suspend CoroutineScope.(T) -> R,
): Data<R> = ComputationData(outputType, meta, coroutineContext, listOf(this)) {
block(await())
}
@ -104,8 +106,8 @@ public fun <T : Any, R : Any> Data<T>.map(
public inline fun <T : Any, reified R : Any> Data<T>.map(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta = this.meta,
noinline block: suspend CoroutineScope.(T) -> R
): Data<R> = DynamicData(R::class, meta, coroutineContext, listOf(this)) {
noinline block: suspend CoroutineScope.(T) -> R,
): Data<R> = ComputationData(R::class, meta, coroutineContext, listOf(this)) {
block(await())
}
@ -115,8 +117,8 @@ public inline fun <T : Any, reified R : Any> Data<T>.map(
public inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduce(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta,
noinline block: suspend CoroutineScope.(Collection<T>) -> R
): Data<R> = DynamicData(
noinline block: suspend CoroutineScope.(Collection<T>) -> R,
): Data<R> = ComputationData(
R::class,
meta,
coroutineContext,
@ -129,8 +131,8 @@ public fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
outputType: KClass<out R>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta,
block: suspend CoroutineScope.(Map<K, T>) -> R
): DynamicData<R> = DynamicData(
block: suspend CoroutineScope.(Map<K, T>) -> R,
): ComputationData<R> = ComputationData(
outputType,
meta,
coroutineContext,
@ -149,8 +151,8 @@ public fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
public inline fun <K, T : Any, reified R : Any> Map<K, Data<T>>.reduce(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta,
noinline block: suspend CoroutineScope.(Map<K, T>) -> R
): DynamicData<R> = DynamicData(
noinline block: suspend CoroutineScope.(Map<K, T>) -> R,
): ComputationData<R> = ComputationData(
R::class,
meta,
coroutineContext,

View File

@ -2,13 +2,13 @@ package hep.dataforge.data
import hep.dataforge.meta.*
import hep.dataforge.names.*
import hep.dataforge.type.Type
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
import kotlin.reflect.KClass
public sealed class DataItem<out T : Any> : MetaRepr {
@ -36,6 +36,7 @@ public sealed class DataItem<out T : Any> : MetaRepr {
/**
* A tree-like data structure grouped into the node. All data inside the node must inherit its type
*/
@Type(DataNode.TYPE)
public interface DataNode<out T : Any> : MetaRepr {
/**
@ -49,6 +50,7 @@ public interface DataNode<out T : Any> : MetaRepr {
override fun toMeta(): Meta = Meta {
"type" put (type.simpleName ?: "undefined")
"meta" put meta
"items" put {
this@DataNode.items.forEach {
it.key.toString() put it.value.toMeta()
@ -64,7 +66,7 @@ public interface DataNode<out T : Any> : MetaRepr {
items.values.forEach {
when (it) {
is DataItem.Node<*> -> it.node.run { startAll() }
is DataItem.Leaf<*> -> it.data.run { startAsync() }
is DataItem.Leaf<*> -> it.data.run { startAsync(this@launch) }
}
}
}
@ -98,11 +100,11 @@ public operator fun <T : Any> DataNode<T>.get(name: String): DataItem<T>? = get(
/**
* Sequence of all children including nodes
*/
public fun <T : Any> DataNode<T>.asSequence(): Sequence<Pair<Name, DataItem<T>>> = sequence {
public fun <T : Any> DataNode<T>.itemSequence(): Sequence<Pair<Name, DataItem<T>>> = sequence {
items.forEach { (head, item) ->
yield(head.asName() to item)
if (item is DataItem.Node) {
val subSequence = item.node.asSequence()
val subSequence = item.node.itemSequence()
.map { (name, data) -> (head.asName() + name) to data }
yieldAll(subSequence)
}
@ -125,166 +127,6 @@ public fun <T : Any> DataNode<T>.dataSequence(): Sequence<Pair<Name, Data<T>>> =
}
}
public operator fun <T : Any> DataNode<T>.iterator(): Iterator<Pair<Name, DataItem<T>>> = asSequence().iterator()
public class DataTree<out T : Any> internal constructor(
override val type: KClass<out T>,
override val items: Map<NameToken, DataItem<T>>,
override val meta: Meta
) : DataNode<T>
private sealed class DataTreeBuilderItem<out T : Any> {
class Node<T : Any>(val tree: DataTreeBuilder<T>) : DataTreeBuilderItem<T>()
class Leaf<T : Any>(val value: Data<T>) : DataTreeBuilderItem<T>()
}
/**
* A builder for a DataTree.
*/
@DFBuilder
public class DataTreeBuilder<T : Any>(public val type: KClass<out T>) {
private val map = HashMap<NameToken, DataTreeBuilderItem<T>>()
private var meta = MetaBuilder()
public operator fun set(token: NameToken, node: DataTreeBuilder<out T>) {
if (map.containsKey(token)) error("Tree entry with name $token is not empty")
map[token] = DataTreeBuilderItem.Node(node)
}
public operator fun set(token: NameToken, data: Data<T>) {
if (map.containsKey(token)) error("Tree entry with name $token is not empty")
map[token] = DataTreeBuilderItem.Leaf(data)
}
private fun buildNode(token: NameToken): DataTreeBuilder<T> {
return if (!map.containsKey(token)) {
DataTreeBuilder(type).also { map[token] = DataTreeBuilderItem.Node(it) }
} else {
(map[token] as? DataTreeBuilderItem.Node<T> ?: error("The node with name $token is occupied by leaf")).tree
}
}
private fun buildNode(name: Name): DataTreeBuilder<T> {
return when (name.length) {
0 -> this
1 -> buildNode(name.firstOrNull()!!)
else -> buildNode(name.firstOrNull()!!).buildNode(name.cutFirst())
}
}
public operator fun set(name: Name, data: Data<T>) {
when (name.length) {
0 -> error("Can't add data with empty name")
1 -> set(name.firstOrNull()!!, data)
2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = data
}
}
public operator fun set(name: Name, node: DataTreeBuilder<out T>) {
when (name.length) {
0 -> error("Can't add data with empty name")
1 -> set(name.firstOrNull()!!, node)
2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = node
}
}
public operator fun set(name: Name, node: DataNode<T>): Unit = set(name, node.builder())
public operator fun set(name: Name, item: DataItem<T>): Unit = when (item) {
is DataItem.Node<T> -> set(name, item.node.builder())
is DataItem.Leaf<T> -> set(name, item.data)
}
/**
* Append data to node
*/
public infix fun String.put(data: Data<T>): Unit = set(toName(), data)
/**
* Append node
*/
public infix fun String.put(node: DataNode<T>): Unit = set(toName(), node)
public infix fun String.put(item: DataItem<T>): Unit = set(toName(), item)
/**
* Build and append node
*/
public infix fun String.put(block: DataTreeBuilder<T>.() -> Unit): Unit = set(toName(), DataTreeBuilder(type).apply(block))
/**
* Update data with given node data and meta with node meta.
*/
public fun update(node: DataNode<T>) {
node.dataSequence().forEach {
//TODO check if the place is occupied
this[it.first] = it.second
}
meta.update(node.meta)
}
public fun meta(block: MetaBuilder.() -> Unit): MetaBuilder = meta.apply(block)
public fun meta(meta: Meta) {
this.meta = meta.builder()
}
public fun build(): DataTree<T> {
val resMap = map.mapValues { (_, value) ->
when (value) {
is DataTreeBuilderItem.Leaf -> DataItem.Leaf(value.value)
is DataTreeBuilderItem.Node -> DataItem.Node(value.tree.build())
}
}
return DataTree(type, resMap, meta.seal())
}
}
public fun <T : Any> DataTreeBuilder<T>.datum(name: Name, data: Data<T>) {
this[name] = data
}
public fun <T : Any> DataTreeBuilder<T>.datum(name: String, data: Data<T>) {
this[name.toName()] = data
}
public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, meta: Meta = Meta.EMPTY) {
this[name] = Data.static(data, meta)
}
public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, block: MetaBuilder.() -> Unit = {}) {
this[name] = Data.static(data, Meta(block))
}
public fun <T : Any> DataTreeBuilder<T>.static(name: String, data: T, block: MetaBuilder.() -> Unit = {}) {
this[name.toName()] = Data.static(data, Meta(block))
}
public fun <T : Any> DataTreeBuilder<T>.node(name: Name, node: DataNode<T>) {
this[name] = node
}
public fun <T : Any> DataTreeBuilder<T>.node(name: String, node: DataNode<T>) {
this[name.toName()] = node
}
public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: Name, noinline block: DataTreeBuilder<T>.() -> Unit) {
this[name] = DataNode(T::class, block)
}
public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: String, noinline block: DataTreeBuilder<T>.() -> Unit) {
this[name.toName()] = DataNode(T::class, block)
}
/**
* Generate a mutable builder from this node. Node content is not changed
*/
public fun <T : Any> DataNode<T>.builder(): DataTreeBuilder<T> = DataTreeBuilder(type).apply {
dataSequence().forEach { (name, data) -> this[name] = data }
}
public fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean): DataNode<T> = DataNode.invoke(type) {
dataSequence().forEach { (name, data) ->
if (predicate(name, data)) {
@ -293,4 +135,8 @@ public fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean):
}
}
public fun <T : Any> DataNode<T>.first(): Data<T>? = dataSequence().first().second
public fun <T : Any> DataNode<T>.first(): Data<T>? = dataSequence().firstOrNull()?.second
public operator fun <T : Any> DataNode<T>.iterator(): Iterator<Pair<Name, DataItem<T>>> = itemSequence().iterator()

View File

@ -0,0 +1,164 @@
package hep.dataforge.data
import hep.dataforge.meta.*
import hep.dataforge.names.*
import kotlin.reflect.KClass
public class DataTree<out T : Any> internal constructor(
override val type: KClass<out T>,
override val items: Map<NameToken, DataItem<T>>,
override val meta: Meta
) : DataNode<T>
private sealed class DataTreeBuilderItem<out T : Any> {
class Node<T : Any>(val tree: DataTreeBuilder<T>) : DataTreeBuilderItem<T>()
class Leaf<T : Any>(val value: Data<T>) : DataTreeBuilderItem<T>()
}
/**
* A builder for a DataTree.
*/
@DFBuilder
public class DataTreeBuilder<T : Any>(public val type: KClass<out T>) {
private val map = HashMap<NameToken, DataTreeBuilderItem<T>>()
private var meta = MetaBuilder()
public operator fun set(token: NameToken, node: DataTreeBuilder<out T>) {
if (map.containsKey(token)) error("Tree entry with name $token is not empty")
map[token] = DataTreeBuilderItem.Node(node)
}
public operator fun set(token: NameToken, data: Data<T>) {
if (map.containsKey(token)) error("Tree entry with name $token is not empty")
map[token] = DataTreeBuilderItem.Leaf(data)
}
private fun buildNode(token: NameToken): DataTreeBuilder<T> {
return if (!map.containsKey(token)) {
DataTreeBuilder(type).also { map[token] = DataTreeBuilderItem.Node(it) }
} else {
(map[token] as? DataTreeBuilderItem.Node<T> ?: error("The node with name $token is occupied by leaf")).tree
}
}
private fun buildNode(name: Name): DataTreeBuilder<T> {
return when (name.length) {
0 -> this
1 -> buildNode(name.firstOrNull()!!)
else -> buildNode(name.firstOrNull()!!).buildNode(name.cutFirst())
}
}
public operator fun set(name: Name, data: Data<T>) {
when (name.length) {
0 -> error("Can't add data with empty name")
1 -> set(name.firstOrNull()!!, data)
2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = data
}
}
public operator fun set(name: Name, node: DataTreeBuilder<out T>) {
when (name.length) {
0 -> error("Can't add data with empty name")
1 -> set(name.firstOrNull()!!, node)
2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = node
}
}
public operator fun set(name: Name, node: DataNode<T>): Unit = set(name, node.builder())
public operator fun set(name: Name, item: DataItem<T>): Unit = when (item) {
is DataItem.Node<T> -> set(name, item.node.builder())
is DataItem.Leaf<T> -> set(name, item.data)
}
/**
* Append data to node
*/
public infix fun String.put(data: Data<T>): Unit = set(toName(), data)
/**
* Append node
*/
public infix fun String.put(node: DataNode<T>): Unit = set(toName(), node)
public infix fun String.put(item: DataItem<T>): Unit = set(toName(), item)
/**
* Build and append node
*/
public infix fun String.put(block: DataTreeBuilder<T>.() -> Unit): Unit = set(toName(), DataTreeBuilder(type).apply(block))
/**
* Update data with given node data and meta with node meta.
*/
public fun update(node: DataNode<T>) {
node.dataSequence().forEach {
//TODO check if the place is occupied
this[it.first] = it.second
}
meta.update(node.meta)
}
public fun meta(block: MetaBuilder.() -> Unit): MetaBuilder = meta.apply(block)
public fun meta(meta: Meta) {
this.meta = meta.builder()
}
public fun build(): DataTree<T> {
val resMap = map.mapValues { (_, value) ->
when (value) {
is DataTreeBuilderItem.Leaf -> DataItem.Leaf(value.value)
is DataTreeBuilderItem.Node -> DataItem.Node(value.tree.build())
}
}
return DataTree(type, resMap, meta.seal())
}
}
public fun <T : Any> DataTreeBuilder<T>.datum(name: Name, data: Data<T>) {
this[name] = data
}
public fun <T : Any> DataTreeBuilder<T>.datum(name: String, data: Data<T>) {
this[name.toName()] = data
}
public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, meta: Meta = Meta.EMPTY) {
this[name] = Data.static(data, meta)
}
public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, block: MetaBuilder.() -> Unit = {}) {
this[name] = Data.static(data, Meta(block))
}
public fun <T : Any> DataTreeBuilder<T>.static(name: String, data: T, block: MetaBuilder.() -> Unit = {}) {
this[name.toName()] = Data.static(data, Meta(block))
}
public fun <T : Any> DataTreeBuilder<T>.node(name: Name, node: DataNode<T>) {
this[name] = node
}
public fun <T : Any> DataTreeBuilder<T>.node(name: String, node: DataNode<T>) {
this[name.toName()] = node
}
public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: Name, noinline block: DataTreeBuilder<T>.() -> Unit) {
this[name] = DataNode(T::class, block)
}
public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: String, noinline block: DataTreeBuilder<T>.() -> Unit) {
this[name.toName()] = DataNode(T::class, block)
}
/**
* Generate a mutable builder from this node. Node content is not changed
*/
public fun <T : Any> DataNode<T>.builder(): DataTreeBuilder<T> = DataTreeBuilder(type).apply {
dataSequence().forEach { (name, data) -> this[name] = data }
}

View File

@ -5,8 +5,12 @@ import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
/**
* Lazy computation result with its dependencies to allowing to stat computing dependencies ahead of time
*/
public interface Goal<out T> {
public val dependencies: Collection<Goal<*>>
/**
* Returns current running coroutine if the goal is started
*/
@ -16,7 +20,7 @@ public interface Goal<out T> {
* Get ongoing computation or start a new one.
* Does not guarantee thread safety. In case of multi-thread access, could create orphan computations.
*/
public fun CoroutineScope.startAsync(): Deferred<T>
public fun startAsync(coroutineScope: CoroutineScope): Deferred<T>
/**
* Reset the computation
@ -26,7 +30,7 @@ public interface Goal<out T> {
public companion object
}
public suspend fun <T> Goal<T>.await(): T = coroutineScope { startAsync().await() }
public suspend fun <T> Goal<T>.await(): T = coroutineScope { startAsync(this).await() }
public val Goal<*>.isComplete: Boolean get() = result?.isCompleted ?: false
@ -34,17 +38,17 @@ public open class StaticGoal<T>(public val value: T) : Goal<T> {
override val dependencies: Collection<Goal<*>> get() = emptyList()
override val result: Deferred<T> = CompletableDeferred(value)
override fun CoroutineScope.startAsync(): Deferred<T> = result
override fun startAsync(coroutineScope: CoroutineScope): Deferred<T> = result
override fun reset() {
//doNothing
}
}
public open class DynamicGoal<T>(
public open class ComputationGoal<T>(
private val coroutineContext: CoroutineContext = EmptyCoroutineContext,
override val dependencies: Collection<Goal<*>> = emptyList(),
public val block: suspend CoroutineScope.() -> T
public val block: suspend CoroutineScope.() -> T,
) : Goal<T> {
final override var result: Deferred<T>? = null
@ -55,19 +59,20 @@ public open class DynamicGoal<T>(
* Does not guarantee thread safety. In case of multi-thread access, could create orphan computations.
*/
@DFExperimental
override fun CoroutineScope.startAsync(): Deferred<T> {
val startedDependencies = this@DynamicGoal.dependencies.map { goal ->
goal.run { startAsync() }
override fun startAsync(coroutineScope: CoroutineScope): Deferred<T> {
val startedDependencies = this.dependencies.map { goal ->
goal.run { startAsync(coroutineScope) }
}
return result
?: async(this@DynamicGoal.coroutineContext + CoroutineMonitor() + Dependencies(startedDependencies)) {
startedDependencies.forEach { deferred ->
deferred.invokeOnCompletion { error ->
if (error != null) cancel(CancellationException("Dependency $deferred failed with error: ${error.message}"))
}
return result ?: coroutineScope.async(
this.coroutineContext + CoroutineMonitor() + Dependencies(startedDependencies)
) {
startedDependencies.forEach { deferred ->
deferred.invokeOnCompletion { error ->
if (error != null) this.cancel(CancellationException("Dependency $deferred failed with error: ${error.message}"))
}
block()
}.also { result = it }
}
block()
}.also { result = it }
}
/**
@ -84,8 +89,8 @@ public open class DynamicGoal<T>(
*/
public fun <T, R> Goal<T>.map(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.(T) -> R
): Goal<R> = DynamicGoal(coroutineContext, listOf(this)) {
block: suspend CoroutineScope.(T) -> R,
): Goal<R> = ComputationGoal(coroutineContext, listOf(this)) {
block(await())
}
@ -94,8 +99,8 @@ public fun <T, R> Goal<T>.map(
*/
public fun <T, R> Collection<Goal<T>>.reduce(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.(Collection<T>) -> R
): Goal<R> = DynamicGoal(coroutineContext, this) {
block: suspend CoroutineScope.(Collection<T>) -> R,
): Goal<R> = ComputationGoal(coroutineContext, this) {
block(map { run { it.await() } })
}
@ -107,8 +112,8 @@ public fun <T, R> Collection<Goal<T>>.reduce(
*/
public fun <K, T, R> Map<K, Goal<T>>.reduce(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.(Map<K, T>) -> R
): Goal<R> = DynamicGoal(coroutineContext, this.values) {
block: suspend CoroutineScope.(Map<K, T>) -> R,
): Goal<R> = ComputationGoal(coroutineContext, this.values) {
block(mapValues { it.value.await() })
}

View File

@ -30,46 +30,41 @@ public class MapActionBuilder<T, R>(public var name: Name, public var meta: Meta
public class MapAction<T : Any, out R : Any>(
public val inputType: KClass<T>,
public val outputType: KClass<out R>,
private val block: MapActionBuilder<T, R>.() -> Unit
) : Action<T, R> {
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
node.ensureType(inputType)
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> = DataNode(outputType) {
node.dataSequence().forEach { (name, data) ->
/*
* Creating a new environment for action using **old** name, old meta and task meta
*/
val env = ActionEnv(name, data.meta, meta)
return DataNode.invoke(outputType) {
node.dataSequence().forEach { (name, data) ->
/*
* Creating a new environment for action using **old** name, old meta and task meta
*/
val env = ActionEnv(name, data.meta, meta)
//applying transformation from builder
val builder = MapActionBuilder<T, R>(
name,
data.meta.builder(), // using data meta
meta
).apply(block)
//applying transformation from builder
val builder = MapActionBuilder<T, R>(
name,
data.meta.builder(), // using data meta
meta
).apply(block)
//getting new name
val newName = builder.name
//getting new name
val newName = builder.name
//getting new meta
val newMeta = builder.meta.seal()
//getting new meta
val newMeta = builder.meta.seal()
val newData = data.map(outputType, meta = newMeta) { builder.result(env, it) }
//setting the data node
this[newName] = newData
}
val newData = data.map(outputType, meta = newMeta) { builder.result(env, it) }
//setting the data node
this[newName] = newData
}
}
}
public inline fun <reified T : Any, reified R : Any> DataNode<T>.map(
public inline fun <T : Any, reified R : Any> DataNode<T>.map(
meta: Meta,
noinline action: MapActionBuilder<in T, out R>.() -> Unit
): DataNode<R> = MapAction(T::class, R::class, action).invoke(this, meta)
): DataNode<R> = MapAction(R::class, action).invoke(this, meta)

View File

@ -72,35 +72,31 @@ public class ReduceGroupBuilder<T : Any, R : Any>(public val actionMeta: Meta) {
* The same rules as for KPipe
*/
public class ReduceAction<T : Any, R : Any>(
public val inputType: KClass<T>,
public val outputType: KClass<out R>,
private val action: ReduceGroupBuilder<T, R>.() -> Unit
) : Action<T, R> {
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
node.ensureType(inputType)
return DataNode.invoke(outputType) {
ReduceGroupBuilder<T, R>(meta).apply(action).buildGroups(node).forEach { group ->
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> = DataNode(outputType) {
ReduceGroupBuilder<T, R>(meta).apply(action).buildGroups(node).forEach { group ->
//val laminate = Laminate(group.meta, meta)
//val laminate = Laminate(group.meta, meta)
val dataMap = group.node.dataSequence().associate { it }
val dataMap = group.node.dataSequence().associate { it }
val groupName: String = group.name
val groupName: String = group.name
val groupMeta = group.meta
val groupMeta = group.meta
val env = ActionEnv(groupName.toName(), groupMeta, meta)
val env = ActionEnv(groupName.toName(), groupMeta, meta)
val res: DynamicData<R> = dataMap.reduce(
outputType,
meta = groupMeta
) { group.result.invoke(env, it) }
set(env.name, res)
}
val res: ComputationData<R> = dataMap.reduce(
outputType,
meta = groupMeta
) { group.result.invoke(env, it) }
set(env.name, res)
}
}
}

View File

@ -33,31 +33,26 @@ public class SplitBuilder<T : Any, R : Any>(public val name: Name, public val me
}
public class SplitAction<T : Any, R : Any>(
public val inputType: KClass<T>,
public val outputType: KClass<out R>,
private val action: SplitBuilder<T, R>.() -> Unit
) : Action<T, R> {
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
node.ensureType(inputType)
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> = DataNode(outputType) {
node.dataSequence().forEach { (name, data) ->
return DataNode.invoke(outputType) {
node.dataSequence().forEach { (name, data) ->
val laminate = Laminate(data.meta, meta)
val laminate = Laminate(data.meta, meta)
val split = SplitBuilder<T, R>(name, data.meta).apply(action)
val split = SplitBuilder<T, R>(name, data.meta).apply(action)
// apply individual fragment rules to result
split.fragments.forEach { (fragmentName, rule) ->
val env = FragmentRule<T, R>(fragmentName, laminate.builder())
// apply individual fragment rules to result
split.fragments.forEach { (fragmentName, rule) ->
val env = FragmentRule<T, R>(fragmentName, laminate.builder())
rule(env)
rule(env)
val res = data.map(outputType, meta = env.meta) { env.result(it) }
set(env.name, res)
}
val res = data.map(outputType, meta = env.meta) { env.result(it) }
set(env.name, res)
}
}
}

View File

@ -1,73 +0,0 @@
package hep.dataforge.data
import hep.dataforge.meta.Meta
import hep.dataforge.names.NameToken
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlin.reflect.KClass
public fun <R : Any, T : R> Data<T>.upcast(type: KClass<out R>): Data<R> {
return object : Data<R> by this {
override val type: KClass<out R> = type
}
}
/**
* Safe upcast a [Data] to a supertype
*/
public inline fun <reified R : Any, T : R> Data<T>.upcast(): Data<R> = upcast(R::class)
/**
* Check if node could be safely cast to given class
*/
internal expect fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean
/**
* Check if data could be safely cast to given class
*/
internal expect fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean
public fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
is DataItem.Node -> node.canCast(type)
is DataItem.Leaf -> data.canCast(type)
}
/**
* Unsafe cast of data node
*/
@Suppress("UNCHECKED_CAST")
public fun <R : Any> Data<*>.cast(type: KClass<out R>): Data<R> {
return object : Data<R> {
override val meta: Meta get() = this@cast.meta
override val dependencies: Collection<Goal<*>> get() = this@cast.dependencies
override val result: Deferred<R>? get() = this@cast.result as Deferred<R>
override fun CoroutineScope.startAsync(): Deferred<R> = this@cast.run { startAsync() as Deferred<R> }
override fun reset() = this@cast.reset()
override val type: KClass<out R> = type
}
}
public inline fun <reified R : Any> Data<*>.cast(): Data<R> = cast(R::class)
@Suppress("UNCHECKED_CAST")
public fun <R : Any> DataNode<*>.cast(type: KClass<out R>): DataNode<R> {
return object : DataNode<R> {
override val meta: Meta get() = this@cast.meta
override val type: KClass<out R> = type
override val items: Map<NameToken, DataItem<R>> get() = this@cast.items as Map<NameToken, DataItem<R>>
}
}
public inline fun <reified R : Any> DataNode<*>.cast(): DataNode<R> = cast(R::class)
/**
* Check that node is compatible with given type meaning that each element could be cast to the type
*/
public fun <T : Any> DataNode<*>.ensureType(type: KClass<out T>) {
if (!canCast(type)) {
error("$type expected, but $type received")
}
}
//expect fun <T : Any, R : Any> DataNode<T>.cast(type: KClass<out R>): DataNode<R>

View File

@ -1,14 +0,0 @@
package hep.dataforge.data
import kotlin.reflect.KClass
/**
* Check that node is compatible with given type meaning that each element could be cast to the type
*/
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
return this.type == type
}
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
return this.type == type
}

View File

@ -1,5 +1,9 @@
package hep.dataforge.data
import hep.dataforge.meta.Meta
import hep.dataforge.names.NameToken
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.runBlocking
import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf
@ -12,12 +16,72 @@ public fun <T : Any> Data<T>.get(): T = runBlocking { await() }
/**
* Check that node is compatible with given type meaning that each element could be cast to the type
*/
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
internal fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
type.isSubclassOf(this.type)
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
/**
* Check if data could be safely cast to given class
*/
internal fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
this.type.isSubclassOf(type)
public fun <R : Any, T : R> Data<T>.upcast(type: KClass<out R>): Data<R> {
return object : Data<R> by this {
override val type: KClass<out R> = type
}
}
/**
* Safe upcast a [Data] to a supertype
*/
public inline fun <reified R : Any, T : R> Data<T>.upcast(): Data<R> = upcast(R::class)
public fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
is DataItem.Node -> node.canCast(type)
is DataItem.Leaf -> data.canCast(type)
}
/**
* Unsafe cast of data node
*/
@Suppress("UNCHECKED_CAST")
public fun <R : Any> Data<*>.cast(type: KClass<out R>): Data<R> {
if(!canCast(type)) error("Can't cast ${this.type} to $type")
return object : Data<R> {
override val meta: Meta get() = this@cast.meta
override val dependencies: Collection<Goal<*>> get() = this@cast.dependencies
override val result: Deferred<R>? get() = this@cast.result as Deferred<R>?
override fun startAsync(coroutineScope: CoroutineScope): Deferred<R> = this@cast.run {
startAsync(coroutineScope) as Deferred<R>
}
override fun reset() = this@cast.reset()
override val type: KClass<out R> = type
}
}
public inline fun <reified R : Any> Data<*>.cast(): Data<R> = cast(R::class)
@Suppress("UNCHECKED_CAST")
public fun <R : Any> DataNode<*>.cast(type: KClass<out R>): DataNode<R> {
return object : DataNode<R> {
override val meta: Meta get() = this@cast.meta
override val type: KClass<out R> = type
override val items: Map<NameToken, DataItem<R>> get() = this@cast.items as Map<NameToken, DataItem<R>>
}
}
public inline fun <reified R : Any> DataNode<*>.cast(): DataNode<R> = cast(R::class)
/**
* Check that node is compatible with given type meaning that each element could be cast to the type
*/
public fun <T : Any> DataNode<*>.ensureType(type: KClass<out T>) {
if (!canCast(type)) {
error("$type expected, but $type received")
}
}
/**
* Cast the node to given type if the cast is possible or return null
*/

View File

@ -1,14 +0,0 @@
package hep.dataforge.data
import kotlin.reflect.KClass
/**
* Check that node is compatible with given type meaning that each element could be cast to the type
*/
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
return this.type == type
}
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
return this.type == type
}

View File

@ -5,7 +5,7 @@ import hep.dataforge.io.EnvelopeFormatFactory.Companion.ENVELOPE_FORMAT_TYPE
import hep.dataforge.meta.Meta
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.provider.Type
import hep.dataforge.type.Type
import kotlinx.io.Input
import kotlinx.io.Output
import kotlin.reflect.KClass

View File

@ -10,7 +10,7 @@ import hep.dataforge.meta.MetaRepr
import hep.dataforge.meta.ValueItem
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.provider.Type
import hep.dataforge.type.Type
import hep.dataforge.values.Value
import kotlinx.io.*
import kotlinx.io.buffer.Buffer

View File

@ -7,7 +7,7 @@ import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.provider.Type
import hep.dataforge.type.Type
import kotlinx.io.ByteArrayInput
import kotlinx.io.Input
import kotlinx.io.Output

View File

@ -812,6 +812,10 @@ public final class hep/dataforge/names/NameTokenKt {
public static final fun withIndex (Lhep/dataforge/names/NameToken;Ljava/lang/String;)Lhep/dataforge/names/NameToken;
}
public abstract interface annotation class hep/dataforge/type/Type : java/lang/annotation/Annotation {
public abstract fun id ()Ljava/lang/String;
}
public final class hep/dataforge/values/DoubleArrayValue : hep/dataforge/values/Value, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
public fun <init> ([D)V
public fun equals (Ljava/lang/Object;)Z

View File

@ -1,4 +1,4 @@
package hep.dataforge.provider
package hep.dataforge.type
/**
* A text label for internal DataForge type classification. Alternative for mime container type.

View File

@ -210,8 +210,6 @@ public abstract interface class hep/dataforge/workspace/Workspace : hep/dataforg
public final class hep/dataforge/workspace/Workspace$Companion {
public static final field TYPE Ljava/lang/String;
public final fun invoke (Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/SimpleWorkspace;
public static synthetic fun invoke$default (Lhep/dataforge/workspace/Workspace$Companion;Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/workspace/SimpleWorkspace;
}
public final class hep/dataforge/workspace/Workspace$DefaultImpls {
@ -235,6 +233,8 @@ public abstract interface class hep/dataforge/workspace/WorkspaceBuilder {
}
public final class hep/dataforge/workspace/WorkspaceBuilderKt {
public static final fun Workspace (Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/Workspace;
public static synthetic fun Workspace$default (Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/workspace/Workspace;
public static final fun context (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun context$default (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static final fun rawData (Lhep/dataforge/workspace/WorkspaceBuilder;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataNode;

View File

@ -4,7 +4,7 @@ import hep.dataforge.context.Named
import hep.dataforge.data.DataNode
import hep.dataforge.meta.Meta
import hep.dataforge.meta.descriptors.Described
import hep.dataforge.provider.Type
import hep.dataforge.type.Type
import hep.dataforge.workspace.Task.Companion.TYPE
import kotlin.reflect.KClass

View File

@ -1,8 +1,6 @@
package hep.dataforge.workspace
import hep.dataforge.context.Context
import hep.dataforge.context.ContextAware
import hep.dataforge.context.Global
import hep.dataforge.data.Data
import hep.dataforge.data.DataNode
import hep.dataforge.data.dataSequence
@ -11,7 +9,7 @@ import hep.dataforge.meta.MetaBuilder
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.provider.Provider
import hep.dataforge.provider.Type
import hep.dataforge.type.Type
@Type(Workspace.TYPE)
@ -52,11 +50,6 @@ public interface Workspace : ContextAware, Provider {
public companion object {
public const val TYPE: String = "workspace"
public operator fun invoke(
parent: Context = Global,
block: SimpleWorkspaceBuilder.() -> Unit,
): SimpleWorkspace =
SimpleWorkspaceBuilder(parent).apply(block).build()
}
}

View File

@ -11,7 +11,6 @@ import hep.dataforge.meta.string
import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty
import hep.dataforge.names.toName
import kotlin.jvm.JvmName
import kotlin.reflect.KClass
@DFBuilder
@ -28,7 +27,7 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
private inner class DataTransformation(
val from: String = "",
val to: String = "",
val transform: (Context, TaskModel, DataNode<Any>) -> DataNode<R>
val transform: (Context, TaskModel, DataNode<Any>) -> DataNode<R>,
) {
operator fun invoke(workspace: Workspace, model: TaskModel, node: DataNode<Any>): DataNode<R>? {
val localData = if (from.isEmpty()) {
@ -55,7 +54,7 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
public fun transform(
from: String = "",
to: String = "",
block: TaskEnv.(DataNode<*>) -> DataNode<R>
block: TaskEnv.(DataNode<*>) -> DataNode<R>,
) {
dataTransforms += DataTransformation(from, to) { context, model, data ->
val env = TaskEnv(Name.EMPTY, model.meta, context, data)
@ -67,7 +66,7 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
inputType: KClass<out T>,
from: String = "",
to: String = "",
block: TaskEnv.(DataNode<T>) -> DataNode<R>
block: TaskEnv.(DataNode<T>) -> DataNode<R>,
) {
dataTransforms += DataTransformation(from, to) { context, model, data ->
data.ensureType(inputType)
@ -79,7 +78,7 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
public inline fun <reified T : Any> transform(
from: String = "",
to: String = "",
noinline block: TaskEnv.(DataNode<T>) -> DataNode<R>
noinline block: TaskEnv.(DataNode<T>) -> DataNode<R>,
) {
transform(T::class, from, to, block)
}
@ -90,14 +89,19 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
public inline fun <reified T : Any> action(
from: String = "",
to: String = "",
crossinline block: TaskEnv.() -> Action<T, R>
crossinline block: TaskEnv.() -> Action<T, R>,
) {
transform(from, to) { data: DataNode<T> ->
block().invoke(data, meta)
}
}
public class TaskEnv(public val name: Name, public val meta: Meta, public val context: Context, public val data: DataNode<Any>) {
public class TaskEnv(
public val name: Name,
public val meta: Meta,
public val context: Context,
public val data: DataNode<Any>,
) {
public operator fun <T : Any> DirectTaskDependency<T>.invoke(): DataNode<T> = if (placement.isEmpty()) {
data.cast(task.type)
} else {
@ -112,14 +116,11 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
public inline fun <reified T : Any> mapAction(
from: String = "",
to: String = "",
crossinline block: MapActionBuilder<T, R>.(TaskEnv) -> Unit
crossinline block: MapActionBuilder<T, R>.(TaskEnv) -> Unit,
) {
action(from, to) {
val env = this
MapAction(
inputType = T::class,
outputType = type
) {
MapAction<T, R>(type) {
block(env)
}
}
@ -131,13 +132,10 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
public inline fun <reified T : Any> map(
from: String = "",
to: String = "",
crossinline block: suspend TaskEnv.(T) -> R
crossinline block: suspend TaskEnv.(T) -> R,
) {
action(from, to) {
MapAction(
inputType = T::class,
outputType = type
) {
MapAction<T,R>(type) {
//TODO automatically append task meta
result = { data ->
block(data)
@ -152,14 +150,11 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
public inline fun <reified T : Any> reduceByGroup(
from: String = "",
to: String = "",
crossinline block: ReduceGroupBuilder<T, R>.(TaskEnv) -> Unit //TODO needs KEEP-176
crossinline block: ReduceGroupBuilder<T, R>.(TaskEnv) -> Unit, //TODO needs KEEP-176
) {
action(from, to) {
val env = this
ReduceAction(
inputType = T::class,
outputType = type
) { block(env) }
ReduceAction<T, R>(type) { block(env) }
}
}
@ -169,20 +164,16 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
public inline fun <reified T : Any> reduce(
from: String = "",
to: String = "",
crossinline block: suspend TaskEnv.(Map<Name, T>) -> R
crossinline block: suspend TaskEnv.(Map<Name, T>) -> R,
) {
action(from, to) {
ReduceAction(
inputType = T::class,
outputType = type,
action = {
result(
actionMeta[TaskModel.MODEL_TARGET_KEY]?.string ?: "@anonymous"
) { data ->
block(data)
}
ReduceAction<T, R>(type) {
result(
actionMeta[TaskModel.MODEL_TARGET_KEY]?.string ?: "@anonymous"
) { data ->
block(data)
}
)
}
}
}
@ -192,14 +183,11 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
public inline fun <reified T : Any> split(
from: String = "",
to: String = "",
crossinline block: SplitBuilder<T, R>.(TaskEnv) -> Unit //TODO needs KEEP-176
crossinline block: SplitBuilder<T, R>.(TaskEnv) -> Unit, //TODO needs KEEP-176
) {
action(from, to) {
val env = this
SplitAction(
inputType = T::class,
outputType = type
) { block(env) }
SplitAction<T, R>(type) { block(this, env) }
}
}

View File

@ -2,13 +2,13 @@ package hep.dataforge.workspace
import hep.dataforge.context.Context
import hep.dataforge.context.ContextBuilder
import hep.dataforge.context.Global
import hep.dataforge.data.DataNode
import hep.dataforge.data.DataTreeBuilder
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty
import hep.dataforge.names.toName
import kotlin.jvm.JvmName
import kotlin.reflect.KClass
@DFBuilder
@ -96,3 +96,8 @@ public class SimpleWorkspaceBuilder(override val parentContext: Context) : Works
return SimpleWorkspace(context, data.build(), targets, tasks)
}
}
public fun Workspace(
parent: Context = Global,
block: SimpleWorkspaceBuilder.() -> Unit,
): Workspace = SimpleWorkspaceBuilder(parent).apply(block).build()