fix #10 set
+collection functions (map, forEach, toList, toSet, isEmpty, etc,)
This commit is contained in:
parent
8a4363bd84
commit
a4448ab2ff
13
docs/Collection.md
Normal file
13
docs/Collection.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Collection
|
||||
|
||||
Is a [Iterable] with known `size`, a finite [Iterable]:
|
||||
|
||||
class Collection : Iterable {
|
||||
val size
|
||||
}
|
||||
|
||||
See [List], [Set] and [Iterable]
|
||||
|
||||
[Iterable]: Iterable.md
|
||||
[List]: List.md
|
||||
[Set]: Set.md
|
@ -1,13 +1,17 @@
|
||||
# Iterable interface
|
||||
|
||||
The inteface which requires iterator to be implemented:
|
||||
Iterable is a class that provides function that creates _the iterator_:
|
||||
|
||||
fun iterator(): Iterator
|
||||
class Iterable {
|
||||
abstract fun iterator()
|
||||
}
|
||||
|
||||
Note that each call of `iterator()` must provide an independent iterator.
|
||||
|
||||
Iterator itself is a simple interface that should provide only to method:
|
||||
|
||||
interface Iterable {
|
||||
fun hasNext(): Bool
|
||||
class Iterator {
|
||||
abstract fun hasNext(): Bool
|
||||
fun next(): Obj
|
||||
}
|
||||
|
||||
@ -15,19 +19,26 @@ Just remember at this stage typed declarations are not yet supported.
|
||||
|
||||
Having `Iterable` in base classes allows to use it in for loop. Also, each `Iterable` has some utility functions available:
|
||||
|
||||
## Instance methods
|
||||
|
||||
fun Iterable.toList(): List
|
||||
fun Iterable.toSet(): Set
|
||||
fun Iterable.indexOf(element): Int
|
||||
fun Iterable.contains(element): Bool
|
||||
fun Iterable.isEmpty(element): Bool
|
||||
fun Iterable.forEach(block: (Any?)->Void ): Void
|
||||
fun Iterable.map(block: (Any?)->Void ): List
|
||||
|
||||
|
||||
## Abstract methods
|
||||
|
||||
fun iterator(): Iterator
|
||||
|
||||
## Instance methods
|
||||
|
||||
### toList()
|
||||
|
||||
Creates a list by iterating to the end. So, the Iterator should be finite to be used with it.
|
||||
|
||||
## Included in interfaces:
|
||||
|
||||
- Collection, Array, [List]
|
||||
- [Collection], Array, [List]
|
||||
|
||||
## Implemented in classes:
|
||||
|
||||
|
@ -116,6 +116,8 @@ Open end ranges remove head and tail elements:
|
||||
: `+=` 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.
|
||||
|
||||
It inherits from [Iterable] too.
|
||||
|
||||
## Member inherited from Array
|
||||
|
||||
| name | meaning | type |
|
||||
@ -130,8 +132,6 @@ instance is appended. If you want to append an Iterable object itself, use `add`
|
||||
: 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
|
||||
[Range]: Range.md
|
||||
[Iterable]: Iterable.md
|
94
docs/Set.md
Normal file
94
docs/Set.md
Normal file
@ -0,0 +1,94 @@
|
||||
# List built-in class
|
||||
|
||||
Mutable set of any objects: a group of different objects, no repetitions.
|
||||
Sets are not ordered, order of appearance does not matter.
|
||||
|
||||
val set = Set(1,2,3, "foo")
|
||||
assert( 1 in set )
|
||||
assert( "foo" in set)
|
||||
assert( "bar" !in set)
|
||||
>>> void
|
||||
|
||||
## Set is collection and therefore [Iterable]:
|
||||
|
||||
assert( Set(1,2) is Set)
|
||||
assert( Set(1,2) is Iterable)
|
||||
assert( Set(1,2) is Collection)
|
||||
>>> void
|
||||
|
||||
So it supports all methods from [Iterable]; set is not, though, an [Array] and has
|
||||
no indexing. Use [set.toList] as needed.
|
||||
|
||||
## Set operations
|
||||
|
||||
// Union
|
||||
assertEquals( Set(1,2,3,4), Set(3, 1) + Set(2, 4))
|
||||
|
||||
// intersection
|
||||
assertEquals( Set(1,4), Set(3, 1, 4).intersect(Set(2, 4, 1)) )
|
||||
// or simple
|
||||
assertEquals( Set(1,4), Set(3, 1, 4) * Set(2, 4, 1) )
|
||||
|
||||
// To find collection elements not present in another collection, use the
|
||||
// subtract() or `-`:
|
||||
assertEquals( Set( 1, 2), Set(1, 2, 4, 3) - Set(3, 4))
|
||||
|
||||
>>> void
|
||||
|
||||
## Adding elements
|
||||
|
||||
var s = Set()
|
||||
s += 1
|
||||
assertEquals( Set(1), s)
|
||||
|
||||
s += [3, 3, 4]
|
||||
assertEquals( Set(3, 4, 1), s)
|
||||
>>> void
|
||||
|
||||
## Removing elements
|
||||
|
||||
List is mutable, so it is possible to remove its contents. To remove a single element
|
||||
by index use:
|
||||
|
||||
var s = Set(1,2,3)
|
||||
s.remove(2)
|
||||
assertEquals( s, Set(1,3) )
|
||||
|
||||
s = Set(1,2,3)
|
||||
s.remove(2,1)
|
||||
assertEquals( s, Set(3) )
|
||||
>>> void
|
||||
|
||||
Note that `remove` returns true if at least one element was actually removed and false
|
||||
if the set has not been changed.
|
||||
|
||||
## Comparisons and inclusion
|
||||
|
||||
Sets are only equal when contains exactly same elements, order, as was said, is not significant:
|
||||
|
||||
assert( Set(1, 2) == Set(2, 1) )
|
||||
assert( Set(1, 2, 2) == Set(2, 1) )
|
||||
assert( Set(1, 3) != Set(2, 1) )
|
||||
assert( 1 in Set(5,1))
|
||||
assert( 10 !in Set(5,1))
|
||||
>>> void
|
||||
|
||||
## Members
|
||||
|
||||
| name | meaning | type |
|
||||
|---------------------|--------------------------------------|-------|
|
||||
| `size` | current size | Int |
|
||||
| `+=` | add one or more elements | Any |
|
||||
| `+`, `union` | union sets | Any |
|
||||
| `-`, `subtract` | subtract sets | Any |
|
||||
| `*`, `intersect` | subtract sets | Any |
|
||||
| `remove(items...)` | remove one or more items | Range |
|
||||
| `contains(element)` | check the element is in the list (1) | |
|
||||
|
||||
(1)
|
||||
: optimized implementation that override `Iterable` one
|
||||
|
||||
Also, it inherits methods from [Iterable].
|
||||
|
||||
|
||||
[Range]: Range.md
|
@ -159,9 +159,8 @@ class Compiler(
|
||||
cc.next()
|
||||
isCall = true
|
||||
val lambda =
|
||||
parseExpression(cc) ?: throw ScriptError(t.pos, "expected valid lambda here")
|
||||
parseLambdaExpression(cc)
|
||||
println(cc.current())
|
||||
cc.skipTokenOfType(Token.Type.RBRACE)
|
||||
operand = Accessor { context ->
|
||||
context.pos = next.pos
|
||||
val v = left.getter(context).value
|
||||
@ -172,7 +171,7 @@ class Compiler(
|
||||
v.invokeInstanceMethod(
|
||||
context,
|
||||
next.value,
|
||||
Arguments(listOf(lambda), true)
|
||||
Arguments(listOf(lambda.getter(context).value), true)
|
||||
), isMutable = false
|
||||
)
|
||||
}
|
||||
|
@ -265,6 +265,7 @@ open class Obj {
|
||||
is Boolean -> ObjBool(obj)
|
||||
Unit -> ObjVoid
|
||||
null -> ObjNull
|
||||
is Iterator<*> -> ObjKotlinIterator(obj)
|
||||
else -> throw IllegalArgumentException("cannot convert to Obj: $obj")
|
||||
}
|
||||
}
|
||||
|
38
lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjArray.kt
Normal file
38
lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjArray.kt
Normal file
@ -0,0 +1,38 @@
|
||||
package net.sergeych.lyng
|
||||
|
||||
val ObjArray by lazy {
|
||||
|
||||
/**
|
||||
* Array abstract class is a [ObjCollection] with `getAt` method.
|
||||
*/
|
||||
ObjClass("Array", ObjCollection).apply {
|
||||
// we can create iterators using size/getat:
|
||||
|
||||
addFn("iterator") {
|
||||
ObjArrayIterator(thisObj).also { it.init(this) }
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
ObjFalse
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package net.sergeych.lyng
|
||||
|
||||
class ObjArrayIterator(val array: Obj) : Obj() {
|
||||
|
||||
override val objClass: ObjClass by lazy { type }
|
||||
|
||||
private var nextIndex = 0
|
||||
private var lastIndex = 0
|
||||
|
||||
suspend fun init(context: Context) {
|
||||
nextIndex = 0
|
||||
lastIndex = array.invokeInstanceMethod(context, "size").toInt()
|
||||
ObjVoid
|
||||
}
|
||||
|
||||
companion object {
|
||||
val type by lazy {
|
||||
ObjClass("ArrayIterator", ObjIterator).apply {
|
||||
addFn("next") {
|
||||
val self = thisAs<ObjArrayIterator>()
|
||||
if (self.nextIndex < self.lastIndex) {
|
||||
self.array.invokeInstanceMethod(this, "getAt", (self.nextIndex++).toObj())
|
||||
} else raiseError(ObjIterationFinishedException(this))
|
||||
}
|
||||
addFn("hasNext") {
|
||||
val self = thisAs<ObjArrayIterator>()
|
||||
if (self.nextIndex < self.lastIndex) ObjTrue else ObjFalse
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -69,118 +69,4 @@ open class ObjClass(
|
||||
?: throw ScriptError(atPos, "symbol doesn't exist: $name")
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class that must provide `iterator` method that returns [ObjIterator] instance.
|
||||
*/
|
||||
val ObjIterable by lazy {
|
||||
ObjClass("Iterable").apply {
|
||||
|
||||
addFn("toList") {
|
||||
val result = mutableListOf<Obj>()
|
||||
val iterator = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
|
||||
while (iterator.invokeInstanceMethod(this, "hasNext").toBool())
|
||||
result += iterator.invokeInstanceMethod(this, "next")
|
||||
|
||||
|
||||
// val next = iterator.getMemberOrNull("next")!!
|
||||
// val hasNext = iterator.getMemberOrNull("hasNext")!!
|
||||
// while( hasNext.invoke(this, iterator).toBool() )
|
||||
// result += next.invoke(this, iterator)
|
||||
ObjList(result)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collection is an iterator with `size`]
|
||||
*/
|
||||
val ObjCollection by lazy {
|
||||
val i: ObjClass = ObjIterable
|
||||
ObjClass("Collection", i).apply {
|
||||
// it is not effective, but it is open:
|
||||
addFn("contains", isOpen = true) {
|
||||
val obj = args.firstAndOnly()
|
||||
val it = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
|
||||
if( obj.compareTo(this, it.invokeInstanceMethod(this, "next")) == 0 )
|
||||
return@addFn ObjTrue
|
||||
}
|
||||
ObjFalse
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
val ObjIterator by lazy { ObjClass("Iterator") }
|
||||
|
||||
class ObjArrayIterator(val array: Obj) : Obj() {
|
||||
|
||||
override val objClass: ObjClass by lazy { type }
|
||||
|
||||
private var nextIndex = 0
|
||||
private var lastIndex = 0
|
||||
|
||||
suspend fun init(context: Context) {
|
||||
nextIndex = 0
|
||||
lastIndex = array.invokeInstanceMethod(context, "size").toInt()
|
||||
ObjVoid
|
||||
}
|
||||
|
||||
companion object {
|
||||
val type by lazy {
|
||||
ObjClass("ArrayIterator", ObjIterator).apply {
|
||||
addFn("next") {
|
||||
val self = thisAs<ObjArrayIterator>()
|
||||
if (self.nextIndex < self.lastIndex) {
|
||||
self.array.invokeInstanceMethod(this, "getAt", (self.nextIndex++).toObj())
|
||||
} else raiseError(ObjIterationFinishedException(this))
|
||||
}
|
||||
addFn("hasNext") {
|
||||
val self = thisAs<ObjArrayIterator>()
|
||||
if (self.nextIndex < self.lastIndex) ObjTrue else ObjFalse
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val ObjArray by lazy {
|
||||
|
||||
/**
|
||||
* Array abstract class is a [ObjCollection] with `getAt` method.
|
||||
*/
|
||||
ObjClass("Array", ObjCollection).apply {
|
||||
// we can create iterators using size/getat:
|
||||
|
||||
addFn("iterator") {
|
||||
ObjArrayIterator(thisObj).also { it.init(this) }
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
ObjFalse
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
package net.sergeych.lyng
|
||||
|
||||
/**
|
||||
* Collection is an iterator with `size`]
|
||||
*/
|
||||
val ObjCollection = ObjClass("Collection", ObjIterable).apply {
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package net.sergeych.lyng
|
||||
|
||||
/**
|
||||
* Abstract class that must provide `iterator` method that returns [ObjIterator] instance.
|
||||
*/
|
||||
val ObjIterable by lazy {
|
||||
ObjClass("Iterable").apply {
|
||||
|
||||
addFn("toList") {
|
||||
val result = mutableListOf<Obj>()
|
||||
val iterator = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
|
||||
while (iterator.invokeInstanceMethod(this, "hasNext").toBool())
|
||||
result += iterator.invokeInstanceMethod(this, "next")
|
||||
ObjList(result)
|
||||
}
|
||||
|
||||
// it is not effective, but it is open:
|
||||
addFn("contains", isOpen = true) {
|
||||
val obj = args.firstAndOnly()
|
||||
val it = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
|
||||
if (obj.compareTo(this, it.invokeInstanceMethod(this, "next")) == 0)
|
||||
return@addFn ObjTrue
|
||||
}
|
||||
ObjFalse
|
||||
}
|
||||
|
||||
addFn("indexOf", isOpen = true) {
|
||||
val obj = args.firstAndOnly()
|
||||
var index = 0
|
||||
val it = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
|
||||
if (obj.compareTo(this, it.invokeInstanceMethod(this, "next")) == 0)
|
||||
return@addFn ObjInt(index.toLong())
|
||||
index++
|
||||
}
|
||||
ObjInt(-1L)
|
||||
}
|
||||
|
||||
addFn("toSet") {
|
||||
val result = mutableSetOf<Obj>()
|
||||
val it = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
|
||||
result += it.invokeInstanceMethod(this, "next")
|
||||
}
|
||||
ObjSet(result)
|
||||
}
|
||||
|
||||
addFn("forEach", isOpen = true) {
|
||||
val it = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
val fn = requiredArg<Statement>(0)
|
||||
while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
|
||||
val x = it.invokeInstanceMethod(this, "next")
|
||||
fn.execute(this.copy(Arguments(listOf(x))))
|
||||
}
|
||||
ObjVoid
|
||||
}
|
||||
|
||||
addFn("map", isOpen = true) {
|
||||
val it = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
val fn = requiredArg<Statement>(0)
|
||||
val result = mutableListOf<Obj>()
|
||||
while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
|
||||
val x = it.invokeInstanceMethod(this, "next")
|
||||
result += fn.execute(this.copy(Arguments(listOf(x))))
|
||||
}
|
||||
ObjList(result)
|
||||
}
|
||||
|
||||
addFn("isEmpty") {
|
||||
ObjBool(
|
||||
thisObj.invokeInstanceMethod(this, "iterator")
|
||||
.invokeInstanceMethod(this, "hasNext").toBool()
|
||||
.not()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
package net.sergeych.lyng
|
||||
|
||||
val ObjIterator by lazy { ObjClass("Iterator") }
|
@ -0,0 +1,14 @@
|
||||
package net.sergeych.lyng
|
||||
|
||||
class ObjKotlinIterator(val iterator: Iterator<Any?>): Obj() {
|
||||
|
||||
override val objClass = type
|
||||
|
||||
companion object {
|
||||
val type = ObjClass("KotlinIterator", ObjIterator).apply {
|
||||
addFn("next") { thisAs<ObjKotlinIterator>().iterator.next().toObj() }
|
||||
addFn("hasNext") { thisAs<ObjKotlinIterator>().iterator.hasNext().toObj() }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -211,4 +211,6 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
97
lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjSet.kt
Normal file
97
lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjSet.kt
Normal file
@ -0,0 +1,97 @@
|
||||
package net.sergeych.lyng
|
||||
|
||||
class ObjSet(val set: MutableSet<Obj> = mutableSetOf()) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
|
||||
override suspend fun contains(context: Context, other: Obj): Boolean {
|
||||
return set.contains(other)
|
||||
}
|
||||
|
||||
override suspend fun plus(context: Context, other: Obj): Obj {
|
||||
return ObjSet(
|
||||
if (other is ObjSet)
|
||||
(set + other.set).toMutableSet()
|
||||
else
|
||||
(set + other).toMutableSet()
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun plusAssign(context: Context, other: Obj): Obj {
|
||||
when (other) {
|
||||
is ObjSet -> {
|
||||
set += other.set
|
||||
}
|
||||
|
||||
is ObjList -> {
|
||||
set += other.list
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (other.isInstanceOf(ObjIterable)) {
|
||||
val i = other.invokeInstanceMethod(context, "iterable")
|
||||
while (i.invokeInstanceMethod(context, "hasNext").toBool()) {
|
||||
set += i.invokeInstanceMethod(context, "next")
|
||||
}
|
||||
}
|
||||
set += other
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
override suspend fun mul(context: Context, other: Obj): Obj {
|
||||
return if (other is ObjSet) {
|
||||
ObjSet(set.intersect(other.set).toMutableSet())
|
||||
} else
|
||||
context.raiseArgumentError("set operator * requires another set")
|
||||
}
|
||||
|
||||
override suspend fun minus(context: Context, other: Obj): Obj {
|
||||
if (other !is ObjSet)
|
||||
context.raiseArgumentError("set operator - requires another set")
|
||||
return ObjSet(set.minus(other.set).toMutableSet())
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Set(${set.joinToString(", ")})"
|
||||
}
|
||||
|
||||
override suspend fun compareTo(context: Context, other: Obj): Int {
|
||||
return if (other !is ObjSet) -1
|
||||
else {
|
||||
if (set == other.set) 0
|
||||
else -1
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val type = object : ObjClass("Set", ObjCollection) {
|
||||
override suspend fun callOn(context: Context): Obj {
|
||||
return ObjSet(context.args.list.toMutableSet())
|
||||
}
|
||||
}.apply {
|
||||
addFn("size") {
|
||||
thisAs<ObjSet>().set.size.toObj()
|
||||
}
|
||||
addFn("intersect") {
|
||||
thisAs<ObjSet>().mul(this, args.firstAndOnly())
|
||||
}
|
||||
addFn("iterator") {
|
||||
thisAs<ObjSet>().set.iterator().toObj()
|
||||
}
|
||||
addFn("union") {
|
||||
thisAs<ObjSet>().plus(this, args.firstAndOnly())
|
||||
}
|
||||
addFn("subtract") {
|
||||
thisAs<ObjSet>().minus(this, args.firstAndOnly())
|
||||
}
|
||||
addFn("remove") {
|
||||
val set = thisAs<ObjSet>().set
|
||||
val n = set.size
|
||||
for( x in args.list ) set -= x
|
||||
if( n == set.size ) ObjFalse else ObjTrue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -152,11 +152,13 @@ class Script(
|
||||
addConst("Bool", ObjBool.type)
|
||||
addConst("Char", ObjChar.type)
|
||||
addConst("List", ObjList.type)
|
||||
addConst("Set", ObjSet.type)
|
||||
addConst("Range", ObjRange.type)
|
||||
@Suppress("RemoveRedundantQualifierName")
|
||||
addConst("Callable", Statement.type)
|
||||
// interfaces
|
||||
addConst("Iterable", ObjIterable)
|
||||
addConst("Collection", ObjCollection)
|
||||
addConst("Array", ObjArray)
|
||||
addConst("Class", ObjClassType)
|
||||
addConst("Object", Obj().objClass)
|
||||
|
@ -1221,21 +1221,6 @@ class ScriptTest {
|
||||
println(a)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun iterableList() = runTest {
|
||||
// 473
|
||||
eval(
|
||||
"""
|
||||
for( i in 0..<1024 ) {
|
||||
val list = (1..1024).toList()
|
||||
assert(list.size == 1024)
|
||||
assert(list[0] == 1)
|
||||
assert(list.last == 1024)
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLambdaWithIt1() = runTest {
|
||||
eval(
|
||||
@ -2206,4 +2191,55 @@ class ScriptTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCollectionStructure() = runTest {
|
||||
eval(
|
||||
"""
|
||||
val list = [1,2,3]
|
||||
assert( 1 in list )
|
||||
assert( list.indexOf(3) == 2 )
|
||||
assert( list.indexOf(5) == -1 )
|
||||
assert( list is List )
|
||||
assert( list is Array )
|
||||
assert( list is Iterable )
|
||||
assert( list is Collection )
|
||||
|
||||
val other = []
|
||||
list.forEach { other += it }
|
||||
assertEquals( list, other )
|
||||
|
||||
assert( list.isEmpty() == false )
|
||||
|
||||
assertEquals( [10, 20, 30], list.map { it * 10 } )
|
||||
assertEquals( [10, 20, 30], (1..3).map { it * 10 } )
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSet() = runTest {
|
||||
eval(
|
||||
"""
|
||||
val set = Set(1,2,3)
|
||||
|
||||
assert( set.contains(1) )
|
||||
assert( 1 in set )
|
||||
|
||||
assert(set is Set)
|
||||
assert(set is Iterable)
|
||||
assert(set is Collection)
|
||||
println(set)
|
||||
for( x in set ) println(x)
|
||||
assert([1,2,3] == set.toList())
|
||||
set += 4
|
||||
assert(set.toList() == [1,2,3,4])
|
||||
assert(set == Set(1,2,3,4))
|
||||
|
||||
val s1 = [1, 2].toSet()
|
||||
assertEquals( Set(1,2), s1 * set)
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
@ -255,6 +255,11 @@ class BookTest {
|
||||
runDocTests("../docs/Range.md")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSet() = runTest {
|
||||
runDocTests("../docs/Set.md")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSampleBooks() = runTest {
|
||||
for (bt in Files.list(Paths.get("../docs/samples")).toList()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user