From 5e3de7073747d35e0f44e28602be30ba6cdb8c36 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 5 Jan 2024 13:02:11 +0300 Subject: [PATCH] Add action delegate for task creation --- .../dataforge/data/DataTreeBuilder.kt | 12 ++--- .../kscience/dataforge/data/StaticDataTree.kt | 2 - .../kscience/dataforge/data/ActionsTest.kt | 2 +- .../dataforge/data/DataTreeBuilderTest.kt | 4 +- .../dataforge/workspace/WorkspaceBuilder.kt | 51 +++++++++++++------ 5 files changed, 41 insertions(+), 30 deletions(-) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTreeBuilder.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTreeBuilder.kt index 303ba44e..f8a5dd4c 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTreeBuilder.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTreeBuilder.kt @@ -10,7 +10,6 @@ import space.kscience.dataforge.misc.ThreadSafe import space.kscience.dataforge.names.* import kotlin.collections.set import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.coroutineContext import kotlin.reflect.KType import kotlin.reflect.typeOf @@ -21,7 +20,7 @@ public interface DataSourceBuilder : DataSetBuilder, DataSource { /** * A mutable [DataTree] that propagates updates */ -public class DataTreeBuilder( +public class DataTreeBuilder internal constructor( override val dataType: KType, coroutineContext: CoroutineContext, ) : DataTree, DataSourceBuilder { @@ -100,19 +99,14 @@ public class DataTreeBuilder( public fun DataSource( type: KType, parent: CoroutineScope, - block: DataSourceBuilder.() -> Unit, + block: DataSourceBuilder.() -> Unit = {}, ): DataTreeBuilder = DataTreeBuilder(type, parent.coroutineContext).apply(block) @Suppress("OPT_IN_USAGE", "FunctionName") public inline fun DataSource( parent: CoroutineScope, - crossinline block: DataSourceBuilder.() -> Unit, -): DataTreeBuilder = DataSource(typeOf(), parent) { block() } - -@Suppress("FunctionName") -public suspend inline fun DataSource( crossinline block: DataSourceBuilder.() -> Unit = {}, -): DataTreeBuilder = DataTreeBuilder(typeOf(), coroutineContext).apply { block() } +): DataTreeBuilder = DataSource(typeOf(), parent) { block() } public inline fun DataSourceBuilder.emit( name: Name, diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/StaticDataTree.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/StaticDataTree.kt index 4f0f455e..186e5c2a 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/StaticDataTree.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/StaticDataTree.kt @@ -65,13 +65,11 @@ internal class StaticDataTree( } } -@Suppress("FunctionName") public inline fun DataTree( dataType: KType, block: DataSetBuilder.() -> Unit, ): DataTree = StaticDataTree(dataType).apply { block() } -@Suppress("FunctionName") public inline fun DataTree( noinline block: DataSetBuilder.() -> Unit, ): DataTree = DataTree(typeOf(), block) diff --git a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt index b24c4f27..06a7e755 100644 --- a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt +++ b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt @@ -29,7 +29,7 @@ internal class ActionsTest { @Test fun testDynamicMapAction() = runTest { - val data: DataSourceBuilder = DataSource() + val data: DataSourceBuilder = DataSource(this) val plusOne = Action.mapping { result { it + 1 } diff --git a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt index b77f7ea2..a4d28eab 100644 --- a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt +++ b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt @@ -56,7 +56,7 @@ internal class DataTreeBuilderTest { try { lateinit var updateJob: Job supervisorScope { - val subNode = DataSource { + val subNode = DataSource(this) { updateJob = launch { repeat(10) { delay(10) @@ -70,7 +70,7 @@ internal class DataTreeBuilderTest { println(it) } } - val rootNode = DataSource { + val rootNode = DataSource(this) { setAndWatch("sub".asName(), subNode) } diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt index 5489e200..39e35b39 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt @@ -1,18 +1,17 @@ package space.kscience.dataforge.workspace import kotlinx.coroutines.CoroutineScope +import space.kscience.dataforge.actions.Action import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.ContextBuilder import space.kscience.dataforge.context.Global -import space.kscience.dataforge.data.* -import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaRepr -import space.kscience.dataforge.meta.MetaSpec -import space.kscience.dataforge.meta.MutableMeta +import space.kscience.dataforge.data.DataSet +import space.kscience.dataforge.data.DataSource +import space.kscience.dataforge.data.DataSourceBuilder +import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.collections.set @@ -45,6 +44,9 @@ public inline fun TaskContainer.registerTask( noinline builder: suspend TaskResultBuilder.() -> Unit, ): Unit = registerTask(Name.parse(name), Task(MetaDescriptor(descriptorBuilder), builder)) +/** + * Create a new t + */ public inline fun TaskContainer.buildTask( name: String, descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, @@ -67,6 +69,9 @@ public inline fun TaskContainer.task( ReadOnlyProperty { _, _ -> TaskReference(taskName, task) } } +/** + * Create a task based on [MetaSpec] + */ public inline fun TaskContainer.task( specification: MetaSpec, noinline builder: suspend TaskResultBuilder.(C) -> Unit, @@ -77,15 +82,34 @@ public inline fun TaskContainer.task( ReadOnlyProperty { _, _ -> TaskReference(taskName, task) } } +/** + * A delegate to create a custom task + */ public inline fun TaskContainer.task( noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, noinline builder: suspend TaskResultBuilder.() -> Unit, ): PropertyDelegateProvider>> = task(MetaDescriptor(descriptorBuilder), builder) -public class WorkspaceBuilder(private val parentContext: Context = Global) : TaskContainer { +/** + * A delegate for creating a task based on [action] + */ +public inline fun TaskContainer.action( + selector: DataSelector, + action: Action, + noinline metaTransform: MutableMeta.()-> Unit = {}, + noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, +): PropertyDelegateProvider>> = + task(MetaDescriptor(descriptorBuilder)) { + result(action.execute(from(selector), taskMeta.copy(metaTransform))) + } + +public class WorkspaceBuilder( + private val parentContext: Context = Global, + private val coroutineScope: CoroutineScope = parentContext, +) : TaskContainer { private var context: Context? = null - private var data: DataSet<*>? = null + private val data = DataSource(coroutineScope) private val targets: HashMap = HashMap() private val tasks = HashMap>() private var cache: WorkspaceCache? = null @@ -100,13 +124,8 @@ public class WorkspaceBuilder(private val parentContext: Context = Global) : Tas /** * Define intrinsic data for the workspace */ - public fun data(builder: DataSetBuilder.() -> Unit) { - data = DataTree(builder) - } - - @DFExperimental - public fun data(scope: CoroutineScope, builder: DataSourceBuilder.() -> Unit) { - data = DataSource(scope, builder) + public fun data(builder: DataSourceBuilder.() -> Unit) { + data.apply(builder) } /** @@ -132,7 +151,7 @@ public class WorkspaceBuilder(private val parentContext: Context = Global) : Tas val postProcess: suspend (TaskResult<*>) -> TaskResult<*> = { result -> cache?.evaluate(result) ?: result } - return WorkspaceImpl(context ?: parentContext, data ?: DataSet.EMPTY, targets, tasks, postProcess) + return WorkspaceImpl(context ?: parentContext, data, targets, tasks, postProcess) } }