From 9ad0bc4450161453c2d2598414cd503750439a84 Mon Sep 17 00:00:00 2001 From: Giorgio Garofalo Date: Mon, 24 Jun 2024 16:50:37 +0200 Subject: [PATCH] Fix append of `VoidValue` --- .../visitor/AppendExpressionVisitor.kt | 20 ++++++++++++++ .../iamgio/quarkdown/test/FullPipelineTest.kt | 26 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/core/src/main/kotlin/eu/iamgio/quarkdown/function/expression/visitor/AppendExpressionVisitor.kt b/core/src/main/kotlin/eu/iamgio/quarkdown/function/expression/visitor/AppendExpressionVisitor.kt index 0abf45ca..9ae39fe9 100644 --- a/core/src/main/kotlin/eu/iamgio/quarkdown/function/expression/visitor/AppendExpressionVisitor.kt +++ b/core/src/main/kotlin/eu/iamgio/quarkdown/function/expression/visitor/AppendExpressionVisitor.kt @@ -41,6 +41,22 @@ import eu.iamgio.quarkdown.function.value.VoidValue * These two values are then joined together by this [AppendExpressionVisitor], producing: * `StringValue(three plus two is 5)` * + * The same principle applies to 'block expressions': + * ``` + * .if {...} + * Item 1 + * .foreach {2..4} + * n: + * Item .n + * Item 5 + * ``` + * The previous example contains a body composed of multiple expressions: + * - `StringValue(Item 1)`; + * - `FunctionCall(foreach)` which returns an `IterableValue` of 3 elements; + * - `StringValue(Item 5)`. + * After appending these values, the resulting expression is an `IterableValue` (a [GeneralCollectionValue] in particular) + * which contains: `Item 1`, `Item 2`, `Item 3`, `Item 4`, `Item 5`. + * * @param other expression to append to the visited expression * @see ComposedExpression */ @@ -51,6 +67,10 @@ class AppendExpressionVisitor(private val other: Expression) : ExpressionVisitor private fun Value<*>.concatenate(): InputValue<*> { val otherEval = other.eval() // Evaluate the next expression. + // Void values are ignored. + if (this is VoidValue) return otherEval as InputValue<*> + if (otherEval is VoidValue) return this as InputValue<*> + // If the other value is a collection, add the current value to it as the first element. if (otherEval is IterableValue<*> && this is OutputValue<*>) { return GeneralCollectionValue(listOf(this, *otherEval.unwrappedValue.toList().toTypedArray())) diff --git a/test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt b/test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt index edfc8d10..286e4c53 100644 --- a/test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt +++ b/test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt @@ -235,6 +235,20 @@ class FullPipelineTest { assertFailsWith { execute(".function {hello}\n target:\n `Hello` .target!\n\n.hello") {} } + + execute( + """ + .if {yes} + .function {hello} + name: + Hello, *.name*! + + # .hello {world} + .hello {iamgio} + """.trimIndent(), + ) { + assertEquals("

Hello, world!

Hello, iamgio!

", it) + } } @Test @@ -253,6 +267,18 @@ class FullPipelineTest { ) { assertEquals("

Hello

", it) } + + execute( + """ + .var {x} {no} + .if {.x} + Hi + .ifnot {.x} + Hello + """.trimIndent(), + ) { + assertEquals("

Hello

", it) + } } @Test