-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implement expressions with yaml config support
feat: Add support for registering action results under variable names, and conditions per action
- Loading branch information
Showing
13 changed files
with
202 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
addons/geary-actions/src/commonMain/kotlin/com/mineinabyss/geary/actions/Action.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
package com.mineinabyss.geary.actions | ||
|
||
interface Action { | ||
fun ActionGroupContext.execute() | ||
fun ActionGroupContext.execute(): Any? | ||
} |
21 changes: 18 additions & 3 deletions
21
addons/geary-actions/src/commonMain/kotlin/com/mineinabyss/geary/actions/ActionGroup.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 51 additions & 4 deletions
55
...ctions/src/commonMain/kotlin/com/mineinabyss/geary/actions/event_binds/EntityObservers.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,71 @@ | ||
package com.mineinabyss.geary.actions.event_binds | ||
|
||
import com.mineinabyss.geary.actions.Action | ||
import com.mineinabyss.geary.actions.ActionEntry | ||
import com.mineinabyss.geary.actions.actions.EmitEventAction | ||
import com.mineinabyss.geary.actions.actions.EnsureAction | ||
import com.mineinabyss.geary.serialization.serializers.InnerSerializer | ||
import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer | ||
import com.mineinabyss.geary.serialization.serializers.SerializableComponentId | ||
import com.mineinabyss.geary.serialization.serializers.SerializedComponents | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.builtins.ListSerializer | ||
import kotlinx.serialization.builtins.MapSerializer | ||
import kotlin.jvm.JvmInline | ||
|
||
@Serializable(with = EntityObservers.Serializer::class) | ||
class EntityObservers(val observers: List<EventBind>) { | ||
class EntityObservers( | ||
val observers: List<EventBind>, | ||
) { | ||
class Serializer : InnerSerializer<Map<SerializableComponentId, List<SerializedComponents>>, EntityObservers>( | ||
serialName = "geary:observe", | ||
inner = MapSerializer( | ||
SerializableComponentId.serializer(), | ||
ListSerializer(PolymorphicListAsMapSerializer.ofComponents()) | ||
ListSerializer( | ||
PolymorphicListAsMapSerializer.ofComponents( | ||
PolymorphicListAsMapSerializer.Config( | ||
customKeys = mapOf( | ||
"when" to ActionWhen.serializer(), | ||
"register" to ActionRegister.serializer() | ||
) | ||
) | ||
) | ||
) | ||
), | ||
inverseTransform = { it.observers.associate { it.event to it.emit } }, | ||
transform = { EntityObservers(it.map { (event, emit) -> EventBind(event, emit = emit) }) } | ||
inverseTransform = { TODO() }, | ||
transform = { | ||
EntityObservers( | ||
it.map { (event, emit) -> | ||
val actions = emit.map { components -> | ||
var action: Action? = null | ||
var condition: List<EnsureAction>? = null | ||
var register: String? = null | ||
components.forEach { comp -> | ||
when { | ||
comp is ActionWhen -> condition = comp.conditions | ||
comp is ActionRegister -> register = comp.register | ||
action != null -> error("Multiple actions defined in one block!") | ||
else -> action = EmitEventAction.wrapIfNotAction(comp) | ||
} | ||
} | ||
ActionEntry( | ||
action = action!!, | ||
conditions = condition, | ||
register = register | ||
) | ||
} | ||
EventBind(event, emit = actions) | ||
} | ||
) | ||
} | ||
) | ||
} | ||
|
||
|
||
@JvmInline | ||
@Serializable | ||
value class ActionWhen(val conditions: List<EnsureAction>) | ||
|
||
@JvmInline | ||
@Serializable | ||
value class ActionRegister(val register: String) |
3 changes: 2 additions & 1 deletion
3
...eary-actions/src/commonMain/kotlin/com/mineinabyss/geary/actions/event_binds/EventBind.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,11 @@ | ||
package com.mineinabyss.geary.actions.event_binds | ||
|
||
import com.mineinabyss.geary.actions.ActionEntry | ||
import com.mineinabyss.geary.serialization.serializers.SerializableComponentId | ||
import com.mineinabyss.geary.serialization.serializers.SerializedComponents | ||
|
||
class EventBind( | ||
val event: SerializableComponentId, | ||
val involving: List<SerializableComponentId> = listOf(), | ||
val emit: List<SerializedComponents>, | ||
val emit: List<ActionEntry>, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 55 additions & 3 deletions
58
...ary-actions/src/commonMain/kotlin/com/mineinabyss/geary/actions/expressions/Expression.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,61 @@ | ||
package com.mineinabyss.geary.actions.expressions | ||
|
||
import com.mineinabyss.geary.actions.ActionGroupContext | ||
import kotlinx.serialization.ContextualSerializer | ||
import kotlinx.serialization.InternalSerializationApi | ||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.builtins.serializer | ||
import kotlinx.serialization.descriptors.SerialDescriptor | ||
import kotlinx.serialization.encoding.AbstractDecoder | ||
import kotlinx.serialization.encoding.Decoder | ||
import kotlinx.serialization.encoding.Encoder | ||
import kotlinx.serialization.encoding.decodeStructure | ||
import kotlinx.serialization.modules.SerializersModule | ||
|
||
@Serializable | ||
abstract class Expression<T> { | ||
abstract fun evaluate(context: ActionGroupContext): T | ||
@Serializable(with = Expression.Serializer::class) | ||
sealed interface Expression<T> { | ||
fun evaluate(context: ActionGroupContext): T | ||
data class Fixed<T>( | ||
val value: T, | ||
) : Expression<T> { | ||
override fun evaluate(context: ActionGroupContext): T = value | ||
} | ||
|
||
data class Evaluate<T>( | ||
val expression: String, | ||
) : Expression<T> { | ||
override fun evaluate(context: ActionGroupContext): T { | ||
return context.environment[expression] as? T ?: error("Expression $expression not found in context") | ||
} | ||
} | ||
|
||
// TODO kaml handles contextual completely different form Json, can we somehow allow both? Otherwise | ||
// kaml also has broken contextual serializer support that we need to work around :( | ||
class Serializer<T : Any>(val serializer: KSerializer<T>) : KSerializer<Expression<T>> { | ||
@OptIn(InternalSerializationApi::class) | ||
override val descriptor: SerialDescriptor = | ||
ContextualSerializer(Any::class).descriptor//buildSerialDescriptor("ExpressionSerializer", SerialKind.CONTEXTUAL) | ||
|
||
override fun deserialize(decoder: Decoder): Expression<T> { | ||
// Try reading string value, if serial type isn't string, this fails | ||
runCatching { | ||
decoder.decodeStructure(String.serializer().descriptor) { | ||
decodeSerializableElement(String.serializer().descriptor, 0, String.serializer()) | ||
} | ||
}.onSuccess { string -> | ||
if (string.startsWith("{{") && string.endsWith("}}")) | ||
return Evaluate(string.removePrefix("{{").removeSuffix("}}").trim()) | ||
} | ||
|
||
// Fallback to reading the value in-place | ||
return decoder.decodeStructure(serializer.descriptor) { | ||
Fixed(decodeSerializableElement(serializer.descriptor, 0, serializer)) | ||
} | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: Expression<T>) { | ||
TODO("Not yet implemented") | ||
} | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
.../geary-actions/src/jvmTest/kotlin/com/mineinabyss/geary/actions/ExpressionDecodingTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package com.mineinabyss.geary.actions | ||
|
||
import com.charleskorn.kaml.Yaml | ||
import com.mineinabyss.geary.actions.expressions.Expression | ||
import com.mineinabyss.geary.serialization.formats.YamlFormat | ||
import com.mineinabyss.geary.serialization.serializableComponents | ||
import io.kotest.matchers.shouldBe | ||
import kotlinx.serialization.Contextual | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.builtins.serializer | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.modules.SerializersModule | ||
import kotlinx.serialization.modules.contextual | ||
import org.junit.jupiter.api.Test | ||
|
||
class ExpressionDecodingTest { | ||
@Serializable | ||
data class TestData( | ||
val name: Expression<String>, | ||
val age: Expression<Int>, | ||
val regular: String, | ||
) | ||
|
||
// @org.junit.jupiter.api.Test | ||
// fun `should correctly decode json`() { | ||
// val input = """ | ||
// { | ||
// "age": "{{ test }}", | ||
// "name": "variable", | ||
// "regular": "{{ asdf }}" | ||
// } | ||
// """.trimIndent() | ||
// Json.decodeFromString<TestData>(input) shouldBe TestData( | ||
// name = Expression.Fixed("variable"), | ||
// age = Expression.Evaluate("test"), | ||
// regular = "{{ asdf }}" | ||
// ) | ||
// } | ||
|
||
@org.junit.jupiter.api.Test | ||
fun `should correctly decode yaml`() { | ||
val input = """ | ||
{ | ||
"age": "{{ test }}", | ||
"name": "variable", | ||
"regular": "{{ asdf }}" | ||
} | ||
""".trimIndent() | ||
Yaml.default.decodeFromString(TestData.serializer(), input) shouldBe TestData( | ||
name = Expression.Fixed("variable"), | ||
age = Expression.Evaluate("test"), | ||
regular = "{{ asdf }}" | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters