Skip to content

Commit

Permalink
Correct range indexes
Browse files Browse the repository at this point in the history
  • Loading branch information
iamgio committed Jun 27, 2024
1 parent f312312 commit 82eab63
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ object ValueFactory {
// 2..5 maps to Range(1, 4)
val range =
Range(
start?.toIntOrNull()?.minus(1),
end?.toIntOrNull()?.minus(1),
start?.toIntOrNull(),
end?.toIntOrNull(),
)

return ObjectValue(range)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import eu.iamgio.quarkdown.function.value.GeneralCollectionValue
import eu.iamgio.quarkdown.function.value.IterableValue
import eu.iamgio.quarkdown.function.value.NumberValue

/**
* Default lower bound index of a [Range] whose `start` value is `null`, when converted to a collection.
* This can also be seen as `N` in _arrays start from `N`_.
* @see Range.toCollection
*/
private const val DEFAULT_LOWER_BOUND_INDEX = 1

/**
* Represents a range of numbers, which can also be iterated through.
* @property start start of the range (inclusive). If `null`, the range is infinite on the left end
Expand All @@ -21,24 +28,27 @@ data class Range(val start: Int?, val end: Int?) : Iterable<NumberValue> {
* @param upperBound upper bound of the range, in case [end] is `null`
* @return this range as an [IntRange], with [start] and [end] replaced by [lowerBound] and [upperBound] respectively if they are `null`
*/
fun toIntRange(
private fun toIntRange(
lowerBound: Int,
upperBound: Int,
) = IntRange(start ?: lowerBound, end ?: upperBound)

/**
* @return this range as an iterable collection value
*/
fun toCollection(): IterableValue<NumberValue> = GeneralCollectionValue(this)

/**
* @return a new iterator for this range.
* If this is open on the left end, it starts from 0.
* If this is open on the left end, it starts from [DEFAULT_LOWER_BOUND_INDEX].
* @throws IllegalStateException if [end] is `null`
*/
override fun iterator(): Iterator<NumberValue> {
if (end == null) {
throw IllegalStateException("Cannot iterate through an endless range.")
}

return toIntRange(lowerBound = 0, upperBound = end).asSequence()
return toIntRange(lowerBound = DEFAULT_LOWER_BOUND_INDEX, upperBound = end).asSequence()
.map(::NumberValue)
.iterator()
}
Expand All @@ -55,9 +65,9 @@ data class Range(val start: Int?, val end: Int?) : Iterable<NumberValue> {

/**
* @param range range to get the sublist from
* @return sublist of [this] list, starting from [range]'s start and ending at [range]'s end (both inclusive).
* @return sublist of [this] list, starting from [range]'s start (starting from 1) and ending at [range]'s end (both inclusive).
* If any of the bounds is `null`, it is replaced by the list's start or end index respectively
*/
fun <T> List<T>.subList(range: Range): List<T> {
return subList(range.start ?: 0, range.end?.plus(1) ?: this.size)
return subList(range.start?.minus(DEFAULT_LOWER_BOUND_INDEX) ?: 0, range.end ?: this.size)
}
7 changes: 3 additions & 4 deletions core/src/test/kotlin/eu/iamgio/quarkdown/ValueFactoryTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ class ValueFactoryTest {

@Test
fun range() {
// TODO x..y should actually map to Range(x, y) instead of Range(x - 1, y - 1)
assertEquals(Range(0, 8), ValueFactory.range("1..9").unwrappedValue)
assertEquals(Range(null, 10), ValueFactory.range("..11").unwrappedValue)
assertEquals(Range(13, null), ValueFactory.range("14..").unwrappedValue)
assertEquals(Range(1, 9), ValueFactory.range("1..9").unwrappedValue)
assertEquals(Range(null, 11), ValueFactory.range("..11").unwrappedValue)
assertEquals(Range(14, null), ValueFactory.range("14..").unwrappedValue)
assertEquals(Range(null, null), ValueFactory.range("..").unwrappedValue)
}

Expand Down
6 changes: 3 additions & 3 deletions stdlib/src/test/kotlin/eu/iamgio/quarkdown/stdlib/DataTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ class DataTest {

assertEquals(
"Line 2${LINE_SEPARATOR}${LINE_SEPARATOR}Line 4",
fileContent(context, path, Range(1, 3)).unwrappedValue,
fileContent(context, path, Range(2, 4)).unwrappedValue,
)

assertEquals(
"Line 1${LINE_SEPARATOR}Line 2",
fileContent(context, path, Range(null, 1)).unwrappedValue,
fileContent(context, path, Range(null, 2)).unwrappedValue,
)

assertEquals(
"Line 4${LINE_SEPARATOR}Line 5",
fileContent(context, path, Range(3, null)).unwrappedValue,
fileContent(context, path, Range(4, null)).unwrappedValue,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ class FlowTest {

assertEquals(
listOf(
DynamicValue("N: 0"),
DynamicValue("N: 1"),
DynamicValue("N: 2"),
DynamicValue("N: 3"),
DynamicValue("N: 4"),
),
loop3.unwrappedValue,
)
Expand Down
27 changes: 16 additions & 11 deletions test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class FullPipelineTest {
}

execute(".foreach {..3}\n **N:** .1") {
assertEquals("<p><strong>N:</strong> 0</p><p><strong>N:</strong> 1</p><p><strong>N:</strong> 2</p>", it)
assertEquals("<p><strong>N:</strong> 1</p><p><strong>N:</strong> 2</p><p><strong>N:</strong> 3</p>", it)
}

execute(
Expand All @@ -185,7 +185,7 @@ class FullPipelineTest {
Hi .n
""".trimIndent(),
) {
assertEquals("<h1>Title</h1><p>Hi 0</p><p>Hi 1</p>", it)
assertEquals("<h1>Title</h1><p>Hi 1</p><p>Hi 2</p>", it)
}

execute(
Expand Down Expand Up @@ -368,7 +368,7 @@ class FullPipelineTest {
.var {t2} {1}
.table
.foreach {..4}
.foreach {0..4}
| $ F_{.1} $ |
|:-------------:|
| .t1 |
Expand All @@ -389,7 +389,7 @@ class FullPipelineTest {
| .t1 |
.table
.foreach {..4}
.foreach {0..4}
.tablecolumn {.1}
.var {tmp} {.sum {.t1} {.t2}}
.var {t1} {.t2}
Expand All @@ -411,7 +411,7 @@ class FullPipelineTest {
}
.table
.foreach {..4}
.foreach {0..4}
| $ F_{.1} $ |
|:------------:|
| .fib {.1} |
Expand All @@ -422,10 +422,15 @@ class FullPipelineTest {
"<th align=\"center\">__QD_INLINE_MATH__\$F_{0}\$__QD_INLINE_MATH__</th>" +
"<th align=\"center\">__QD_INLINE_MATH__\$F_{1}\$__QD_INLINE_MATH__</th>" +
"<th align=\"center\">__QD_INLINE_MATH__\$F_{2}\$__QD_INLINE_MATH__</th>" +
"<th align=\"center\">__QD_INLINE_MATH__\$F_{3}\$__QD_INLINE_MATH__</th></tr></thead><tbody><tr>" +
"<td align=\"center\">0</td><td align=\"center\">1</td>" +
"<th align=\"center\">__QD_INLINE_MATH__\$F_{3}\$__QD_INLINE_MATH__</th>" +
"<th align=\"center\">__QD_INLINE_MATH__\$F_{4}\$__QD_INLINE_MATH__</th>" +
"</tr></thead><tbody><tr>" +
"<td align=\"center\">0</td>" +
"<td align=\"center\">1</td>" +
"<td align=\"center\">1</td>" +
"<td align=\"center\">2</td></tr></tbody></table>"
"<td align=\"center\">2</td>" +
"<td align=\"center\">3</td>" +
"</tr></tbody></table>"

execute(iterative) {
assertEquals(out, it)
Expand Down Expand Up @@ -473,10 +478,10 @@ class FullPipelineTest {
""".trimIndent(),
) {
assertEquals(
"<h1>Hello, world!</h1><p>0__QD_INLINE_MATH__$\\times\$__QD_INLINE_MATH__0 is 0</p><h3>End</h3>" +
"<h1>Hello, world!</h1><p>1__QD_INLINE_MATH__$\\times\$__QD_INLINE_MATH__1 is 1</p><h3>End</h3>" +
"<h1>Hello, world!</h1><p>1__QD_INLINE_MATH__$\\times\$__QD_INLINE_MATH__1 is 1</p><h3>End</h3>" +
"<h1>Hello, world!</h1><p>2__QD_INLINE_MATH__$\\times\$__QD_INLINE_MATH__2 is 4</p><h3>End</h3>" +
"<h1>Hello, world!</h1><p>3__QD_INLINE_MATH__$\\times\$__QD_INLINE_MATH__3 is 9</p><h3>End</h3>",
"<h1>Hello, world!</h1><p>3__QD_INLINE_MATH__$\\times\$__QD_INLINE_MATH__3 is 9</p><h3>End</h3>" +
"<h1>Hello, world!</h1><p>4__QD_INLINE_MATH__$\\times\$__QD_INLINE_MATH__4 is 16</p><h3>End</h3>",
it,
)
}
Expand Down

0 comments on commit 82eab63

Please sign in to comment.