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 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.Name
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.provider.Provider 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. * 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 package hep.dataforge.context
import hep.dataforge.provider.Type import hep.dataforge.type.Type
import kotlin.reflect.KClass import kotlin.reflect.KClass
@Type(PluginFactory.TYPE) @Type(PluginFactory.TYPE)

View File

@ -4,6 +4,7 @@ import hep.dataforge.context.Context
import hep.dataforge.context.gather import hep.dataforge.context.gather
import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.DFExperimental
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.type.Type
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.full.findAnnotation 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 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 final class hep/dataforge/data/CoroutineMonitor : kotlin/coroutines/CoroutineContext$Element {
public static final field Companion Lhep/dataforge/data/CoroutineMonitor$Companion; public static final field Companion Lhep/dataforge/data/CoroutineMonitor$Companion;
public fun <init> ()V 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 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 final class hep/dataforge/data/DataFilter : hep/dataforge/meta/Scheme {
public static final field Companion Lhep/dataforge/data/DataFilter$Companion; public static final field Companion Lhep/dataforge/data/DataFilter$Companion;
public fun <init> ()V 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 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/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/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 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 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 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 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 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 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/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/ComputationData;
} }
public abstract interface class hep/dataforge/data/DataNode : hep/dataforge/meta/MetaRepr { 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 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 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 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 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;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 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 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 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 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 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 { 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 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 final class hep/dataforge/data/Dependencies : kotlin/coroutines/CoroutineContext$Element {
public static final field Companion Lhep/dataforge/data/Dependencies$Companion; public static final field Companion Lhep/dataforge/data/Dependencies$Companion;
public fun <init> (Ljava/util/Collection;)V 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/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 final class hep/dataforge/data/FragmentRule {
public field result Lkotlin/jvm/functions/Function2; public field result Lkotlin/jvm/functions/Function2;
public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaBuilder;)V 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 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 fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
public final fun getInputType ()Lkotlin/reflect/KClass;
public final fun getOutputType ()Lkotlin/reflect/KClass; public final fun getOutputType ()Lkotlin/reflect/KClass;
public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode; public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
public fun isTerminal ()Z 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 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 fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
public final fun getInputType ()Lkotlin/reflect/KClass;
public final fun getOutputType ()Lkotlin/reflect/KClass; public final fun getOutputType ()Lkotlin/reflect/KClass;
public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode; public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
public fun isTerminal ()Z 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 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 fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
public final fun getInputType ()Lkotlin/reflect/KClass;
public final fun getOutputType ()Lkotlin/reflect/KClass; public final fun getOutputType ()Lkotlin/reflect/KClass;
public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode; public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
public fun isTerminal ()Z public fun isTerminal ()Z

View File

@ -3,6 +3,7 @@ package hep.dataforge.data
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaRepr import hep.dataforge.meta.MetaRepr
import hep.dataforge.meta.isEmpty import hep.dataforge.meta.isEmpty
import hep.dataforge.type.Type
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext
@ -11,7 +12,8 @@ import kotlin.reflect.KClass
/** /**
* A data element characterized by its meta * 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. * 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 public val meta: Meta
override fun toMeta(): Meta = Meta { override fun toMeta(): Meta = Meta {
"type" put (type.simpleName?:"undefined") "type" put (type.simpleName ?: "undefined")
if(!meta.isEmpty()) { if (!meta.isEmpty()) {
"meta" put meta "meta" put meta
} }
} }
@ -37,14 +39,14 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext, context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(), dependencies: Collection<Data<*>> = emptyList(),
block: suspend CoroutineScope.() -> T block: suspend CoroutineScope.() -> T,
): Data<T> = DynamicData(type, meta, context, dependencies, block) ): Data<T> = ComputationData(type, meta, context, dependencies, block)
public inline operator fun <reified T : Any> invoke( public inline operator fun <reified T : Any> invoke(
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext, context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(), dependencies: Collection<Data<*>> = emptyList(),
noinline block: suspend CoroutineScope.() -> T noinline block: suspend CoroutineScope.() -> T,
): Data<T> = invoke(T::class, meta, context, dependencies, block) ): Data<T> = invoke(T::class, meta, context, dependencies, block)
public operator fun <T : Any> invoke( public operator fun <T : Any> invoke(
@ -53,7 +55,7 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext, context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(), dependencies: Collection<Data<*>> = emptyList(),
block: suspend CoroutineScope.() -> T block: suspend CoroutineScope.() -> T,
): Data<T> = NamedData(name, invoke(type, meta, context, dependencies, block)) ): Data<T> = NamedData(name, invoke(type, meta, context, dependencies, block))
public inline operator fun <reified T : Any> invoke( 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, meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext, context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(), dependencies: Collection<Data<*>> = emptyList(),
noinline block: suspend CoroutineScope.() -> T noinline block: suspend CoroutineScope.() -> T,
): Data<T> = ): Data<T> =
invoke(name, T::class, meta, context, dependencies, block) 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 type: KClass<out T>,
override val meta: Meta = Meta.EMPTY, override val meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext, context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(), dependencies: Collection<Data<*>> = emptyList(),
block: suspend CoroutineScope.() -> T block: suspend CoroutineScope.() -> T,
) : Data<T>, DynamicGoal<T>(context, dependencies, block) ) : Data<T>, ComputationGoal<T>(context, dependencies, block)
public class StaticData<T : Any>( public class StaticData<T : Any>(
value: T, value: T,
override val meta: Meta = Meta.EMPTY override val meta: Meta = Meta.EMPTY,
) : Data<T>, StaticGoal<T>(value) { ) : Data<T>, StaticGoal<T>(value) {
override val type: KClass<out T> get() = value::class 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>, outputType: KClass<out R>,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta = this.meta, meta: Meta = this.meta,
block: suspend CoroutineScope.(T) -> R block: suspend CoroutineScope.(T) -> R,
): Data<R> = DynamicData(outputType, meta, coroutineContext, listOf(this)) { ): Data<R> = ComputationData(outputType, meta, coroutineContext, listOf(this)) {
block(await()) 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( public inline fun <T : Any, reified R : Any> Data<T>.map(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta = this.meta, meta: Meta = this.meta,
noinline block: suspend CoroutineScope.(T) -> R noinline block: suspend CoroutineScope.(T) -> R,
): Data<R> = DynamicData(R::class, meta, coroutineContext, listOf(this)) { ): Data<R> = ComputationData(R::class, meta, coroutineContext, listOf(this)) {
block(await()) 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( public inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduce(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta, meta: Meta,
noinline block: suspend CoroutineScope.(Collection<T>) -> R noinline block: suspend CoroutineScope.(Collection<T>) -> R,
): Data<R> = DynamicData( ): Data<R> = ComputationData(
R::class, R::class,
meta, meta,
coroutineContext, coroutineContext,
@ -129,8 +131,8 @@ public fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
outputType: KClass<out R>, outputType: KClass<out R>,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta, meta: Meta,
block: suspend CoroutineScope.(Map<K, T>) -> R block: suspend CoroutineScope.(Map<K, T>) -> R,
): DynamicData<R> = DynamicData( ): ComputationData<R> = ComputationData(
outputType, outputType,
meta, meta,
coroutineContext, 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( public inline fun <K, T : Any, reified R : Any> Map<K, Data<T>>.reduce(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
meta: Meta, meta: Meta,
noinline block: suspend CoroutineScope.(Map<K, T>) -> R noinline block: suspend CoroutineScope.(Map<K, T>) -> R,
): DynamicData<R> = DynamicData( ): ComputationData<R> = ComputationData(
R::class, R::class,
meta, meta,
coroutineContext, coroutineContext,

View File

@ -2,13 +2,13 @@ package hep.dataforge.data
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.names.* import hep.dataforge.names.*
import hep.dataforge.type.Type
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.collections.component1 import kotlin.collections.component1
import kotlin.collections.component2 import kotlin.collections.component2
import kotlin.collections.set
import kotlin.reflect.KClass import kotlin.reflect.KClass
public sealed class DataItem<out T : Any> : MetaRepr { 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 * 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 { public interface DataNode<out T : Any> : MetaRepr {
/** /**
@ -49,6 +50,7 @@ public interface DataNode<out T : Any> : MetaRepr {
override fun toMeta(): Meta = Meta { override fun toMeta(): Meta = Meta {
"type" put (type.simpleName ?: "undefined") "type" put (type.simpleName ?: "undefined")
"meta" put meta
"items" put { "items" put {
this@DataNode.items.forEach { this@DataNode.items.forEach {
it.key.toString() put it.value.toMeta() it.key.toString() put it.value.toMeta()
@ -64,7 +66,7 @@ public interface DataNode<out T : Any> : MetaRepr {
items.values.forEach { items.values.forEach {
when (it) { when (it) {
is DataItem.Node<*> -> it.node.run { startAll() } 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 * 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) -> items.forEach { (head, item) ->
yield(head.asName() to item) yield(head.asName() to item)
if (item is DataItem.Node) { if (item is DataItem.Node) {
val subSequence = item.node.asSequence() val subSequence = item.node.itemSequence()
.map { (name, data) -> (head.asName() + name) to data } .map { (name, data) -> (head.asName() + name) to data }
yieldAll(subSequence) 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) { public fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean): DataNode<T> = DataNode.invoke(type) {
dataSequence().forEach { (name, data) -> dataSequence().forEach { (name, data) ->
if (predicate(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.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext 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 interface Goal<out T> {
public val dependencies: Collection<Goal<*>> public val dependencies: Collection<Goal<*>>
/** /**
* Returns current running coroutine if the goal is started * 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. * Get ongoing computation or start a new one.
* Does not guarantee thread safety. In case of multi-thread access, could create orphan computations. * 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 * Reset the computation
@ -26,7 +30,7 @@ public interface Goal<out T> {
public companion object 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 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 dependencies: Collection<Goal<*>> get() = emptyList()
override val result: Deferred<T> = CompletableDeferred(value) 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() { override fun reset() {
//doNothing //doNothing
} }
} }
public open class DynamicGoal<T>( public open class ComputationGoal<T>(
private val coroutineContext: CoroutineContext = EmptyCoroutineContext, private val coroutineContext: CoroutineContext = EmptyCoroutineContext,
override val dependencies: Collection<Goal<*>> = emptyList(), override val dependencies: Collection<Goal<*>> = emptyList(),
public val block: suspend CoroutineScope.() -> T public val block: suspend CoroutineScope.() -> T,
) : Goal<T> { ) : Goal<T> {
final override var result: Deferred<T>? = null 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. * Does not guarantee thread safety. In case of multi-thread access, could create orphan computations.
*/ */
@DFExperimental @DFExperimental
override fun CoroutineScope.startAsync(): Deferred<T> { override fun startAsync(coroutineScope: CoroutineScope): Deferred<T> {
val startedDependencies = this@DynamicGoal.dependencies.map { goal -> val startedDependencies = this.dependencies.map { goal ->
goal.run { startAsync() } goal.run { startAsync(coroutineScope) }
} }
return result return result ?: coroutineScope.async(
?: async(this@DynamicGoal.coroutineContext + CoroutineMonitor() + Dependencies(startedDependencies)) { this.coroutineContext + CoroutineMonitor() + Dependencies(startedDependencies)
startedDependencies.forEach { deferred -> ) {
deferred.invokeOnCompletion { error -> startedDependencies.forEach { deferred ->
if (error != null) cancel(CancellationException("Dependency $deferred failed with error: ${error.message}")) 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( public fun <T, R> Goal<T>.map(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.(T) -> R block: suspend CoroutineScope.(T) -> R,
): Goal<R> = DynamicGoal(coroutineContext, listOf(this)) { ): Goal<R> = ComputationGoal(coroutineContext, listOf(this)) {
block(await()) block(await())
} }
@ -94,8 +99,8 @@ public fun <T, R> Goal<T>.map(
*/ */
public fun <T, R> Collection<Goal<T>>.reduce( public fun <T, R> Collection<Goal<T>>.reduce(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.(Collection<T>) -> R block: suspend CoroutineScope.(Collection<T>) -> R,
): Goal<R> = DynamicGoal(coroutineContext, this) { ): Goal<R> = ComputationGoal(coroutineContext, this) {
block(map { run { it.await() } }) 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( public fun <K, T, R> Map<K, Goal<T>>.reduce(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.(Map<K, T>) -> R block: suspend CoroutineScope.(Map<K, T>) -> R,
): Goal<R> = DynamicGoal(coroutineContext, this.values) { ): Goal<R> = ComputationGoal(coroutineContext, this.values) {
block(mapValues { it.value.await() }) 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 class MapAction<T : Any, out R : Any>(
public val inputType: KClass<T>,
public val outputType: KClass<out R>, public val outputType: KClass<out R>,
private val block: MapActionBuilder<T, R>.() -> Unit private val block: MapActionBuilder<T, R>.() -> Unit
) : Action<T, R> { ) : Action<T, R> {
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> { override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> = DataNode(outputType) {
node.ensureType(inputType) 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) { //applying transformation from builder
node.dataSequence().forEach { (name, data) -> val builder = MapActionBuilder<T, R>(
/* name,
* Creating a new environment for action using **old** name, old meta and task meta data.meta.builder(), // using data meta
*/ meta
val env = ActionEnv(name, data.meta, meta) ).apply(block)
//applying transformation from builder //getting new name
val builder = MapActionBuilder<T, R>( val newName = builder.name
name,
data.meta.builder(), // using data meta
meta
).apply(block)
//getting new name //getting new meta
val newName = builder.name val newMeta = builder.meta.seal()
//getting new meta val newData = data.map(outputType, meta = newMeta) { builder.result(env, it) }
val newMeta = builder.meta.seal() //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, meta: Meta,
noinline action: MapActionBuilder<in T, out R>.() -> Unit 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 * The same rules as for KPipe
*/ */
public class ReduceAction<T : Any, R : Any>( public class ReduceAction<T : Any, R : Any>(
public val inputType: KClass<T>,
public val outputType: KClass<out R>, public val outputType: KClass<out R>,
private val action: ReduceGroupBuilder<T, R>.() -> Unit private val action: ReduceGroupBuilder<T, R>.() -> Unit
) : Action<T, R> { ) : Action<T, R> {
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> { override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> = DataNode(outputType) {
node.ensureType(inputType) ReduceGroupBuilder<T, R>(meta).apply(action).buildGroups(node).forEach { group ->
return DataNode.invoke(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( val res: ComputationData<R> = dataMap.reduce(
outputType, outputType,
meta = groupMeta meta = groupMeta
) { group.result.invoke(env, it) } ) { group.result.invoke(env, it) }
set(env.name, res)
}
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 class SplitAction<T : Any, R : Any>(
public val inputType: KClass<T>,
public val outputType: KClass<out R>, public val outputType: KClass<out R>,
private val action: SplitBuilder<T, R>.() -> Unit private val action: SplitBuilder<T, R>.() -> Unit
) : Action<T, R> { ) : Action<T, R> {
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> { override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> = DataNode(outputType) {
node.ensureType(inputType) node.dataSequence().forEach { (name, data) ->
return DataNode.invoke(outputType) { val laminate = Laminate(data.meta, meta)
node.dataSequence().forEach { (name, data) ->
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 // apply individual fragment rules to result
split.fragments.forEach { (fragmentName, rule) -> split.fragments.forEach { (fragmentName, rule) ->
val env = FragmentRule<T, R>(fragmentName, laminate.builder()) val env = FragmentRule<T, R>(fragmentName, laminate.builder())
rule(env) rule(env)
val res = data.map(outputType, meta = env.meta) { env.result(it) } val res = data.map(outputType, meta = env.meta) { env.result(it) }
set(env.name, res) 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 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 kotlinx.coroutines.runBlocking
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf 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 * 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) 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) 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 * 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.meta.Meta
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.provider.Type import hep.dataforge.type.Type
import kotlinx.io.Input import kotlinx.io.Input
import kotlinx.io.Output import kotlinx.io.Output
import kotlin.reflect.KClass import kotlin.reflect.KClass

View File

@ -10,7 +10,7 @@ import hep.dataforge.meta.MetaRepr
import hep.dataforge.meta.ValueItem import hep.dataforge.meta.ValueItem
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.provider.Type import hep.dataforge.type.Type
import hep.dataforge.values.Value import hep.dataforge.values.Value
import kotlinx.io.* import kotlinx.io.*
import kotlinx.io.buffer.Buffer 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.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.provider.Type import hep.dataforge.type.Type
import kotlinx.io.ByteArrayInput import kotlinx.io.ByteArrayInput
import kotlinx.io.Input import kotlinx.io.Input
import kotlinx.io.Output 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 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 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 <init> ([D)V
public fun equals (Ljava/lang/Object;)Z 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. * 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 final class hep/dataforge/workspace/Workspace$Companion {
public static final field TYPE Ljava/lang/String; 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 { 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 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 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 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; 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.data.DataNode
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.descriptors.Described import hep.dataforge.meta.descriptors.Described
import hep.dataforge.provider.Type import hep.dataforge.type.Type
import hep.dataforge.workspace.Task.Companion.TYPE import hep.dataforge.workspace.Task.Companion.TYPE
import kotlin.reflect.KClass import kotlin.reflect.KClass

View File

@ -1,8 +1,6 @@
package hep.dataforge.workspace package hep.dataforge.workspace
import hep.dataforge.context.Context
import hep.dataforge.context.ContextAware import hep.dataforge.context.ContextAware
import hep.dataforge.context.Global
import hep.dataforge.data.Data import hep.dataforge.data.Data
import hep.dataforge.data.DataNode import hep.dataforge.data.DataNode
import hep.dataforge.data.dataSequence import hep.dataforge.data.dataSequence
@ -11,7 +9,7 @@ import hep.dataforge.meta.MetaBuilder
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.provider.Provider import hep.dataforge.provider.Provider
import hep.dataforge.provider.Type import hep.dataforge.type.Type
@Type(Workspace.TYPE) @Type(Workspace.TYPE)
@ -52,11 +50,6 @@ public interface Workspace : ContextAware, Provider {
public companion object { public companion object {
public const val TYPE: String = "workspace" 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.Name
import hep.dataforge.names.isEmpty import hep.dataforge.names.isEmpty
import hep.dataforge.names.toName import hep.dataforge.names.toName
import kotlin.jvm.JvmName
import kotlin.reflect.KClass import kotlin.reflect.KClass
@DFBuilder @DFBuilder
@ -28,7 +27,7 @@ public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass
private inner class DataTransformation( private inner class DataTransformation(
val from: String = "", val from: String = "",
val to: 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>? { operator fun invoke(workspace: Workspace, model: TaskModel, node: DataNode<Any>): DataNode<R>? {
val localData = if (from.isEmpty()) { 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( public fun transform(
from: String = "", from: String = "",
to: String = "", to: String = "",
block: TaskEnv.(DataNode<*>) -> DataNode<R> block: TaskEnv.(DataNode<*>) -> DataNode<R>,
) { ) {
dataTransforms += DataTransformation(from, to) { context, model, data -> dataTransforms += DataTransformation(from, to) { context, model, data ->
val env = TaskEnv(Name.EMPTY, model.meta, context, 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>, inputType: KClass<out T>,
from: String = "", from: String = "",
to: String = "", to: String = "",
block: TaskEnv.(DataNode<T>) -> DataNode<R> block: TaskEnv.(DataNode<T>) -> DataNode<R>,
) { ) {
dataTransforms += DataTransformation(from, to) { context, model, data -> dataTransforms += DataTransformation(from, to) { context, model, data ->
data.ensureType(inputType) 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( public inline fun <reified T : Any> transform(
from: String = "", from: String = "",
to: String = "", to: String = "",
noinline block: TaskEnv.(DataNode<T>) -> DataNode<R> noinline block: TaskEnv.(DataNode<T>) -> DataNode<R>,
) { ) {
transform(T::class, from, to, block) 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( public inline fun <reified T : Any> action(
from: String = "", from: String = "",
to: String = "", to: String = "",
crossinline block: TaskEnv.() -> Action<T, R> crossinline block: TaskEnv.() -> Action<T, R>,
) { ) {
transform(from, to) { data: DataNode<T> -> transform(from, to) { data: DataNode<T> ->
block().invoke(data, meta) 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()) { public operator fun <T : Any> DirectTaskDependency<T>.invoke(): DataNode<T> = if (placement.isEmpty()) {
data.cast(task.type) data.cast(task.type)
} else { } 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( public inline fun <reified T : Any> mapAction(
from: String = "", from: String = "",
to: String = "", to: String = "",
crossinline block: MapActionBuilder<T, R>.(TaskEnv) -> Unit crossinline block: MapActionBuilder<T, R>.(TaskEnv) -> Unit,
) { ) {
action(from, to) { action(from, to) {
val env = this val env = this
MapAction( MapAction<T, R>(type) {
inputType = T::class,
outputType = type
) {
block(env) 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( public inline fun <reified T : Any> map(
from: String = "", from: String = "",
to: String = "", to: String = "",
crossinline block: suspend TaskEnv.(T) -> R crossinline block: suspend TaskEnv.(T) -> R,
) { ) {
action(from, to) { action(from, to) {
MapAction( MapAction<T,R>(type) {
inputType = T::class,
outputType = type
) {
//TODO automatically append task meta //TODO automatically append task meta
result = { data -> result = { data ->
block(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( public inline fun <reified T : Any> reduceByGroup(
from: String = "", from: String = "",
to: 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) { action(from, to) {
val env = this val env = this
ReduceAction( ReduceAction<T, R>(type) { block(env) }
inputType = T::class,
outputType = 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( public inline fun <reified T : Any> reduce(
from: String = "", from: String = "",
to: String = "", to: String = "",
crossinline block: suspend TaskEnv.(Map<Name, T>) -> R crossinline block: suspend TaskEnv.(Map<Name, T>) -> R,
) { ) {
action(from, to) { action(from, to) {
ReduceAction( ReduceAction<T, R>(type) {
inputType = T::class, result(
outputType = type, actionMeta[TaskModel.MODEL_TARGET_KEY]?.string ?: "@anonymous"
action = { ) { data ->
result( block(data)
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( public inline fun <reified T : Any> split(
from: String = "", from: String = "",
to: 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) { action(from, to) {
val env = this val env = this
SplitAction( SplitAction<T, R>(type) { block(this, env) }
inputType = T::class,
outputType = type
) { block(env) }
} }
} }

View File

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