fix #26 lists redesigned for ranges, less chaotic and serpentic
This commit is contained in:
		
							parent
							
								
									19eae213ec
								
							
						
					
					
						commit
						8a4363bd84
					
				
							
								
								
									
										73
									
								
								docs/List.md
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								docs/List.md
									
									
									
									
									
								
							@ -20,11 +20,11 @@ indexing is zero-based, as in C/C++/Java/Kotlin, etc.
 | 
			
		||||
    list[1]
 | 
			
		||||
    >>> 20
 | 
			
		||||
 | 
			
		||||
Using negative indexes has a special meaning: _offset from the end of the list_:
 | 
			
		||||
There is a shortcut for the last:
 | 
			
		||||
 | 
			
		||||
    val list = [10, 20, 30]
 | 
			
		||||
    list[-1]
 | 
			
		||||
    >>> 30
 | 
			
		||||
    [list.last, list.lastIndex]
 | 
			
		||||
    >>> [30, 2]
 | 
			
		||||
 | 
			
		||||
__Important__ negative indexes works wherever indexes are used, e.g. in insertion and removal methods too.
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,8 @@ You can concatenate lists or iterable objects:
 | 
			
		||||
 | 
			
		||||
## Appending
 | 
			
		||||
 | 
			
		||||
To append to lists, use `+=` with elements, lists and any [Iterable] instances, but beware it will concatenate [Iterable] objects instead of appending them. To append [Iterable] instance itself, use `list.add`:
 | 
			
		||||
To append to lists, use `+=` with elements, lists and any [Iterable] instances, but beware it will
 | 
			
		||||
concatenate [Iterable] objects instead of appending them. To append [Iterable] instance itself, use `list.add`:
 | 
			
		||||
 | 
			
		||||
    var list = [1, 2]
 | 
			
		||||
    val other = [3, 4]
 | 
			
		||||
@ -57,7 +58,28 @@ To append to lists, use `+=` with elements, lists and any [Iterable] instances,
 | 
			
		||||
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
## Removing elements
 | 
			
		||||
 | 
			
		||||
List is mutable, so it is possible to remove its contents. To remove a single element
 | 
			
		||||
by index use:
 | 
			
		||||
 | 
			
		||||
    assertEquals( [1,2,3].removeAt(1), [1,3] )
 | 
			
		||||
    assertEquals( [1,2,3].removeAt(0), [2,3] )
 | 
			
		||||
    assertEquals( [1,2,3].removeLast(), [1,2] )
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
There is a way to remove a range (see [Range] for more on ranges):
 | 
			
		||||
 | 
			
		||||
    assertEquals( [1, 4], [1,2,3,4].removeRange(1..2))
 | 
			
		||||
    assertEquals( [1, 4], [1,2,3,4].removeRange(1..<3))
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
Open end ranges remove head and tail elements:
 | 
			
		||||
 | 
			
		||||
    assertEquals( [3, 4, 5], [1,2,3,4,5].removeRange(..1))
 | 
			
		||||
    assertEquals( [3, 4, 5], [1,2,3,4,5].removeRange(..<2))
 | 
			
		||||
    assertEquals( [1, 2], [1,2,3,4,5].removeRange( (2..) ))
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
## Comparisons
 | 
			
		||||
 | 
			
		||||
@ -72,19 +94,44 @@ To append to lists, use `+=` with elements, lists and any [Iterable] instances,
 | 
			
		||||
 | 
			
		||||
## Members
 | 
			
		||||
 | 
			
		||||
| name                              | meaning                             | type     |
 | 
			
		||||
|-----------------------------------|-------------------------------------|----------|
 | 
			
		||||
| `size`                            | current size                        | Int      |
 | 
			
		||||
| `add(elements...)`                | add one or more elements to the end | Any      |
 | 
			
		||||
| `addAt(index,elements...)`        | insert elements at position         | Int, Any |
 | 
			
		||||
| `removeAt(index)`                 | remove element at position          | Int      |
 | 
			
		||||
| `removeRangeInclusive(start,end)` | remove range, inclusive (1)         | Int, Int |
 | 
			
		||||
|                                   |                                     |          |
 | 
			
		||||
| name                          | meaning                               | type        |
 | 
			
		||||
|-------------------------------|---------------------------------------|-------------|
 | 
			
		||||
| `size`                        | current size                          | Int         |
 | 
			
		||||
| `add(elements...)`            | add one or more elements to the end   | Any         |
 | 
			
		||||
| `insertAt(index,elements...)` | insert elements at position           | Int, Any    |
 | 
			
		||||
| `removeAt(index)`             | remove element at position            | Int         |
 | 
			
		||||
| `remove(from,toNonInclusive)` | remove range from (incl) to (nonincl) | Int, Int    |
 | 
			
		||||
| `remove(Range)`               | remove range                          | Range       |
 | 
			
		||||
| `removeLast()`                | remove last element                   |             |
 | 
			
		||||
| `removeLast(n)`               | remove n last elements                | Int         |
 | 
			
		||||
| `contains(element)`           | check the element is in the list (1)  |             |
 | 
			
		||||
| `[index]`                     | get or set element at index           | Int         |
 | 
			
		||||
| `[Range]`                     | get slice of the array (copy)         | Range       |
 | 
			
		||||
| `+=`                          | append element(s)                     | List or Obj |
 | 
			
		||||
 | 
			
		||||
(1)
 | 
			
		||||
: end-inclisiveness allows to use negative indexes to, for exampe, remove several last elements, like `list.removeRangeInclusive(-2, -1)` will remove two last elements.
 | 
			
		||||
: optimized implementation that override `Array` one
 | 
			
		||||
 | 
			
		||||
(2)
 | 
			
		||||
: `+=` append either a single element, or all elements if the List or other Iterable
 | 
			
		||||
instance is appended. If you want to append an Iterable object itself, use `add` instead.
 | 
			
		||||
 | 
			
		||||
## Member inherited from Array
 | 
			
		||||
 | 
			
		||||
| name             | meaning                        | type  |
 | 
			
		||||
|------------------|--------------------------------|-------|
 | 
			
		||||
| `last`           | last element (throws if empty) |       |
 | 
			
		||||
| `lastOrNull`     | last element or null           |       |
 | 
			
		||||
| `lastIndex`      |                                | Int   |
 | 
			
		||||
| `indices`        | range of indexes               | Range |
 | 
			
		||||
| `contains(item)` | test that item is in the list  |       |
 | 
			
		||||
 | 
			
		||||
(1)
 | 
			
		||||
: end-inclisiveness allows to use negative indexes to, for exampe, remove several last elements, like
 | 
			
		||||
`list.removeRangeInclusive(-2, -1)` will remove two last elements.
 | 
			
		||||
 | 
			
		||||
# Notes
 | 
			
		||||
 | 
			
		||||
Could be rewritten using array as a class but List as the interface
 | 
			
		||||
 | 
			
		||||
[Range]: Range.md
 | 
			
		||||
@ -514,62 +514,73 @@ To add elements to the list:
 | 
			
		||||
    assert( x == [1, 2, 3, "the", "end"])
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
Self-modifying concatenation by `+=` also works:
 | 
			
		||||
Self-modifying concatenation by `+=` also works (also with single elements):
 | 
			
		||||
 | 
			
		||||
    val x = [1, 2]
 | 
			
		||||
    x += [3, 4]
 | 
			
		||||
    assert( x == [1, 2, 3, 4])
 | 
			
		||||
    x += 5
 | 
			
		||||
    assert( x == [1, 2, 3, 4, 5])
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
You can insert elements at any position using `addAt`:
 | 
			
		||||
You can insert elements at any position using `insertAt`:
 | 
			
		||||
 | 
			
		||||
    val x = [1,2,3]
 | 
			
		||||
    x.addAt(1, "foo", "bar")
 | 
			
		||||
    x.insertAt(1, "foo", "bar")
 | 
			
		||||
    assert( x == [1, "foo", "bar", 2, 3])
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
Using splat arguments can simplify inserting list in list:
 | 
			
		||||
 | 
			
		||||
    val x = [1, 2, 3]
 | 
			
		||||
    x.addAt( 1, ...[0,100,0])
 | 
			
		||||
    x.insertAt( 1, ...[0,100,0])
 | 
			
		||||
    x
 | 
			
		||||
    >>> [1, 0, 100, 0, 2, 3]
 | 
			
		||||
 | 
			
		||||
Using negative indexes can insert elements as offset from the end, for example:
 | 
			
		||||
 | 
			
		||||
    val x = [1,2,3]
 | 
			
		||||
    x.addAt(-1, 10)
 | 
			
		||||
    x
 | 
			
		||||
    >>> [1, 2, 10, 3]
 | 
			
		||||
 | 
			
		||||
Note that to add to the end you still need to use `add` or positive index of the after-last element:
 | 
			
		||||
 | 
			
		||||
    val x = [1,2,3]
 | 
			
		||||
    x.addAt(3, 10)
 | 
			
		||||
    x.insertAt(3, 10)
 | 
			
		||||
    x
 | 
			
		||||
    >>> [1, 2, 3, 10]
 | 
			
		||||
 | 
			
		||||
but it is much simpler, and we recommend to use '+='
 | 
			
		||||
 | 
			
		||||
    val x = [1,2,3]
 | 
			
		||||
    x += 10
 | 
			
		||||
    >>> [1, 2, 3, 10]
 | 
			
		||||
 | 
			
		||||
## Removing list items
 | 
			
		||||
 | 
			
		||||
    val x = [1, 2, 3, 4, 5]
 | 
			
		||||
    x.removeAt(2)
 | 
			
		||||
    assert( x == [1, 2, 4, 5])
 | 
			
		||||
    // or remove range (start inclusive, end exclusive):
 | 
			
		||||
    x.removeRangeInclusive(1,2)    
 | 
			
		||||
    x.removeRange(1..2)    
 | 
			
		||||
    assert( x == [1, 5])
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
Again, you can use negative indexes. For example, removing last elements like:
 | 
			
		||||
There is a shortcut to remove the last elements:
 | 
			
		||||
 | 
			
		||||
    val x = [1, 2, 3, 4, 5]
 | 
			
		||||
 | 
			
		||||
    // remove last:
 | 
			
		||||
    x.removeAt(-1)
 | 
			
		||||
    x.removeLast()
 | 
			
		||||
    assert( x == [1, 2, 3, 4])
 | 
			
		||||
    
 | 
			
		||||
    // remove 2 last:
 | 
			
		||||
    x.removeRangeInclusive(-2,-1)
 | 
			
		||||
    assert( x == [1, 2])
 | 
			
		||||
    x.removeLast(2)
 | 
			
		||||
    assertEquals( [1, 2], x)
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
You can get ranges to extract a portion from a list:
 | 
			
		||||
 | 
			
		||||
    val list = [1, 2, 3, 4, 5]
 | 
			
		||||
    assertEquals( [1,2,3], list[..2])
 | 
			
		||||
    assertEquals( [1,2,], list[..<2])
 | 
			
		||||
    assertEquals( [4,5], list[3..])
 | 
			
		||||
    assertEquals( [2,3], list[1..2])
 | 
			
		||||
    assertEquals( [2,3], list[1..<3])
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
# Flow control operators
 | 
			
		||||
 | 
			
		||||
@ -365,7 +365,7 @@ class Compiler(
 | 
			
		||||
                    } ?: parseLambdaExpression(cc)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Token.Type.RBRACKET -> {
 | 
			
		||||
                Token.Type.RBRACKET, Token.Type.RPAREN -> {
 | 
			
		||||
                    cc.previous()
 | 
			
		||||
                    return operand
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -161,13 +161,26 @@ val ObjArray by lazy {
 | 
			
		||||
 | 
			
		||||
        addFn("contains", isOpen = true) {
 | 
			
		||||
            val obj = args.firstAndOnly()
 | 
			
		||||
            for( i in 0..< thisObj.invokeInstanceMethod(this, "size").toInt()) {
 | 
			
		||||
                if( thisObj.getAt(this, ObjInt(i.toLong())).compareTo(this, obj) == 0 ) return@addFn ObjTrue
 | 
			
		||||
            for (i in 0..<thisObj.invokeInstanceMethod(this, "size").toInt()) {
 | 
			
		||||
                if (thisObj.getAt(this, ObjInt(i.toLong())).compareTo(this, obj) == 0) return@addFn ObjTrue
 | 
			
		||||
            }
 | 
			
		||||
            ObjFalse
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        addFn("isample") { "ok".toObj() }
 | 
			
		||||
        addFn("last") {
 | 
			
		||||
            thisObj.invokeInstanceMethod(
 | 
			
		||||
                this,
 | 
			
		||||
                "getAt",
 | 
			
		||||
                (thisObj.invokeInstanceMethod(this, "size").toInt() - 1).toObj()
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        addFn("lastIndex") { (thisObj.invokeInstanceMethod(this, "size").toInt() - 1).toObj() }
 | 
			
		||||
 | 
			
		||||
        addFn("indices") {
 | 
			
		||||
            ObjRange(0.toObj(), thisObj.invokeInstanceMethod(this, "size"), false)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,20 +11,48 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
 | 
			
		||||
        list.joinToString(separator = ", ") { it.inspect() }
 | 
			
		||||
    }]"
 | 
			
		||||
 | 
			
		||||
    fun normalize(context: Context, index: Int, allowsEndInclusive: Boolean = false): Int {
 | 
			
		||||
        val i = if (index < 0) list.size + index else index
 | 
			
		||||
        if (allowsEndInclusive && i == list.size) return i
 | 
			
		||||
        if (i !in list.indices) context.raiseError("index $index out of bounds for size ${list.size}")
 | 
			
		||||
        return i
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun getAt(context: Context, index: Obj): Obj {
 | 
			
		||||
        val i = normalize(context, index.toInt())
 | 
			
		||||
        return list[i]
 | 
			
		||||
        return when (index) {
 | 
			
		||||
            is ObjInt -> {
 | 
			
		||||
                list[index.toInt()]
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            is ObjRange -> {
 | 
			
		||||
                when {
 | 
			
		||||
                    index.start is ObjInt && index.end is ObjInt -> {
 | 
			
		||||
                        if (index.isEndInclusive)
 | 
			
		||||
                            ObjList(list.subList(index.start.toInt(), index.end.toInt() + 1).toMutableList())
 | 
			
		||||
                        else
 | 
			
		||||
                            ObjList(list.subList(index.start.toInt(), index.end.toInt()).toMutableList())
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    index.isOpenStart && !index.isOpenEnd -> {
 | 
			
		||||
                        if (index.isEndInclusive)
 | 
			
		||||
                            ObjList(list.subList(0, index.end!!.toInt() + 1).toMutableList())
 | 
			
		||||
                        else
 | 
			
		||||
                            ObjList(list.subList(0, index.end!!.toInt()).toMutableList())
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    index.isOpenEnd && !index.isOpenStart -> {
 | 
			
		||||
                        ObjList(list.subList(index.start!!.toInt(), list.size).toMutableList())
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    index.isOpenStart && index.isOpenEnd -> {
 | 
			
		||||
                        ObjList(list.toMutableList())
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    else -> {
 | 
			
		||||
                        throw RuntimeException("Can't apply range for index: $index")
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            else -> context.raiseArgumentError("Illegal index object for a list: ${index.inspect()}")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun putAt(context: Context, index: Int, newValue: Obj) {
 | 
			
		||||
        val i = normalize(context, index)
 | 
			
		||||
        val i = index
 | 
			
		||||
        list[i] = newValue
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -111,33 +139,74 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
 | 
			
		||||
                    ObjVoid
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
            createField("addAt",
 | 
			
		||||
                statement {
 | 
			
		||||
                    if (args.size < 2) raiseError("addAt takes 2+ arguments")
 | 
			
		||||
                    val l = thisAs<ObjList>()
 | 
			
		||||
                    var index = l.normalize(
 | 
			
		||||
                        this, requiredArg<ObjInt>(0).value.toInt(),
 | 
			
		||||
                        allowsEndInclusive = true
 | 
			
		||||
                    )
 | 
			
		||||
                    for (i in 1..<args.size) l.list.add(index++, args[i])
 | 
			
		||||
                    ObjVoid
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
            addFn("insertAt") {
 | 
			
		||||
                if (args.size < 2) raiseError("addAt takes 2+ arguments")
 | 
			
		||||
                val l = thisAs<ObjList>()
 | 
			
		||||
                var index = requiredArg<ObjInt>(0).value.toInt()
 | 
			
		||||
                for (i in 1..<args.size) l.list.add(index++, args[i])
 | 
			
		||||
                ObjVoid
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            addFn("removeAt") {
 | 
			
		||||
                val self = thisAs<ObjList>()
 | 
			
		||||
                val start = self.normalize(this, requiredArg<ObjInt>(0).value.toInt())
 | 
			
		||||
                val start = requiredArg<ObjInt>(0).value.toInt()
 | 
			
		||||
                if (args.size == 2) {
 | 
			
		||||
                    val end = requireOnlyArg<ObjInt>().value.toInt()
 | 
			
		||||
                    self.list.subList(start, self.normalize(this, end)).clear()
 | 
			
		||||
                    self.list.subList(start, end).clear()
 | 
			
		||||
                } else
 | 
			
		||||
                    self.list.removeAt(start)
 | 
			
		||||
                self
 | 
			
		||||
            }
 | 
			
		||||
            addFn("removeRangeInclusive") {
 | 
			
		||||
 | 
			
		||||
            addFn("removeLast") {
 | 
			
		||||
                val self = thisAs<ObjList>()
 | 
			
		||||
                val start = self.normalize(this, requiredArg<ObjInt>(0).value.toInt())
 | 
			
		||||
                val end = self.normalize(this, requiredArg<ObjInt>(1).value.toInt()) + 1
 | 
			
		||||
                self.list.subList(start, end).clear()
 | 
			
		||||
                if (args.isNotEmpty()) {
 | 
			
		||||
                    val count = requireOnlyArg<ObjInt>().value.toInt()
 | 
			
		||||
                    val size = self.list.size
 | 
			
		||||
                    if (count >= size) self.list.clear()
 | 
			
		||||
                    else self.list.subList(size - count, size).clear()
 | 
			
		||||
                } else self.list.removeLast()
 | 
			
		||||
                self
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            addFn("removeRange") {
 | 
			
		||||
                val self = thisAs<ObjList>()
 | 
			
		||||
                val list = self.list
 | 
			
		||||
                val range = requiredArg<Obj>(0)
 | 
			
		||||
                if (range is ObjRange) {
 | 
			
		||||
                    val index = range
 | 
			
		||||
                    when {
 | 
			
		||||
                        index.start is ObjInt && index.end is ObjInt -> {
 | 
			
		||||
                            if (index.isEndInclusive)
 | 
			
		||||
                                list.subList(index.start.toInt(), index.end.toInt() + 1)
 | 
			
		||||
                            else
 | 
			
		||||
                                list.subList(index.start.toInt(), index.end.toInt())
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        index.isOpenStart && !index.isOpenEnd -> {
 | 
			
		||||
                            if (index.isEndInclusive)
 | 
			
		||||
                                list.subList(0, index.end!!.toInt() + 1)
 | 
			
		||||
                            else
 | 
			
		||||
                                list.subList(0, index.end!!.toInt())
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        index.isOpenEnd && !index.isOpenStart -> {
 | 
			
		||||
                            list.subList(index.start!!.toInt(), list.size)
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        index.isOpenStart && index.isOpenEnd -> {
 | 
			
		||||
                            list
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        else -> {
 | 
			
		||||
                            throw RuntimeException("Can't apply range for index: $index")
 | 
			
		||||
                        }
 | 
			
		||||
                    }.clear()
 | 
			
		||||
                } else {
 | 
			
		||||
                    val start = range.toInt()
 | 
			
		||||
                    val end = requiredArg<ObjInt>(1).value.toInt() + 1
 | 
			
		||||
                    self.list.subList(start, end).clear()
 | 
			
		||||
                }
 | 
			
		||||
                self
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,9 @@ package net.sergeych.lyng
 | 
			
		||||
 | 
			
		||||
class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Obj() {
 | 
			
		||||
 | 
			
		||||
    val isOpenStart by lazy { start == null || start.isNull }
 | 
			
		||||
    val isOpenEnd by lazy { end == null || end.isNull }
 | 
			
		||||
 | 
			
		||||
    override val objClass: ObjClass = type
 | 
			
		||||
 | 
			
		||||
    override fun toString(): String {
 | 
			
		||||
 | 
			
		||||
@ -1137,7 +1137,8 @@ class ScriptTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testOpenStartRanges() = runTest {
 | 
			
		||||
        eval("""
 | 
			
		||||
        eval(
 | 
			
		||||
            """
 | 
			
		||||
            var r = ..5
 | 
			
		||||
            assert( r::class == Range)
 | 
			
		||||
            assert( r.start == null)
 | 
			
		||||
@ -1155,17 +1156,20 @@ class ScriptTest {
 | 
			
		||||
            assert( (-2..3) in r)
 | 
			
		||||
            assert( (-2..12) !in r)
 | 
			
		||||
            
 | 
			
		||||
        """.trimIndent())
 | 
			
		||||
        """.trimIndent()
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testOpenEndRanges() = runTest {
 | 
			
		||||
        eval("""
 | 
			
		||||
        eval(
 | 
			
		||||
            """
 | 
			
		||||
            var r = 5..
 | 
			
		||||
            assert( r::class == Range)
 | 
			
		||||
            assert( r.end == null)
 | 
			
		||||
            assert( r.start == 5)
 | 
			
		||||
        """.trimIndent())
 | 
			
		||||
        """.trimIndent()
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@ -1226,7 +1230,7 @@ class ScriptTest {
 | 
			
		||||
            val list = (1..1024).toList()
 | 
			
		||||
            assert(list.size == 1024)
 | 
			
		||||
            assert(list[0] == 1)
 | 
			
		||||
            assert(list[-1] == 1024)
 | 
			
		||||
            assert(list.last == 1024)
 | 
			
		||||
            }
 | 
			
		||||
        """.trimIndent()
 | 
			
		||||
        )
 | 
			
		||||
@ -2149,7 +2153,8 @@ class ScriptTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testNull1() = runTest {
 | 
			
		||||
        eval("""
 | 
			
		||||
        eval(
 | 
			
		||||
            """
 | 
			
		||||
            var s = null
 | 
			
		||||
            assertThrows { s.length }
 | 
			
		||||
            assertThrows { s.size() }
 | 
			
		||||
@ -2164,25 +2169,41 @@ class ScriptTest {
 | 
			
		||||
            s = "xx"
 | 
			
		||||
            assert(s.lower().size == 2)
 | 
			
		||||
            assert(s.length == 2)
 | 
			
		||||
        """.trimIndent())
 | 
			
		||||
        """.trimIndent()
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testSprintf() = runTest {
 | 
			
		||||
        eval(""" 
 | 
			
		||||
        eval(
 | 
			
		||||
            """ 
 | 
			
		||||
            assertEquals( "123.45", "%3.2f"(123.451678) )
 | 
			
		||||
            assertEquals( "123.45: hello", "%3.2f: %s"(123.451678, "hello") )
 | 
			
		||||
            assertEquals( "123.45: true", "%3.2f: %s"(123.451678, true) )
 | 
			
		||||
        """.trimIndent())
 | 
			
		||||
        """.trimIndent()
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testSubstringRangeFailure() = runTest {
 | 
			
		||||
        eval(""" 
 | 
			
		||||
        eval(
 | 
			
		||||
            """ 
 | 
			
		||||
            assertEquals("pult", "catapult"[4..])
 | 
			
		||||
            assertEquals("cat", "catapult"[..2])
 | 
			
		||||
            """.trimIndent()
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun passingOpenEndedRangeAsParam() = runTest {
 | 
			
		||||
        eval(
 | 
			
		||||
            """
 | 
			
		||||
                fun test(r) {
 | 
			
		||||
                    assert( r is Range ) 
 | 
			
		||||
                }
 | 
			
		||||
                test( 1.. )
 | 
			
		||||
            """.trimIndent()
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user