+list + / += Iterable
+CLI app started
This commit is contained in:
		
							parent
							
								
									939e391a20
								
							
						
					
					
						commit
						6ef94fff65
					
				@ -15,7 +15,13 @@ 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:
 | 
					Having `Iterable` in base classes allows to use it in for loop. Also, each `Iterable` has some utility functions available:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## toList()
 | 
					## 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.
 | 
					Creates a list by iterating to the end. So, the Iterator should be finite to be used with it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										29
									
								
								docs/Iterator.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								docs/Iterator.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					# Iterator interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Iterators are representing the [Iterable] entity, to access its contents
 | 
				
			||||||
 | 
					sequentially. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To implement the iterator you need to implement only two abstract methods:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Abstract methods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### hasNext(): Bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Should return `true` if call to `next()` will return valid next element.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### next(): Obj
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Should return next object in the iterated entity. If there is no next method,
 | 
				
			||||||
 | 
					must throw `ObjIterationFinishedError`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Iterators are returned when implementing [Iterable] interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Implemented for classes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [List], [Range]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[List]: List.md
 | 
				
			||||||
 | 
					[Range]: Range.md
 | 
				
			||||||
 | 
					[Iterable]: Iterable.md
 | 
				
			||||||
							
								
								
									
										26
									
								
								docs/List.md
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								docs/List.md
									
									
									
									
									
								
							@ -30,9 +30,35 @@ __Important__ negative indexes works wherever indexes are used, e.g. in insertio
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Concatenation
 | 
					## Concatenation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can concatenate lists or iterable objects:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert( [4,5] + [1,2] == [4,5,1,2])
 | 
					    assert( [4,5] + [1,2] == [4,5,1,2])
 | 
				
			||||||
 | 
					    assert( [4,5] + (1..3) == [4, 5, 1, 2, 3])
 | 
				
			||||||
    >>> void
 | 
					    >>> void
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 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`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var list = [1, 2]
 | 
				
			||||||
 | 
					    val other = [3, 4]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // appending lists is clear:
 | 
				
			||||||
 | 
					    list += other
 | 
				
			||||||
 | 
					    assert( list == [1, 2, 3, 4] )
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // but appending other Iterables could be confusing:
 | 
				
			||||||
 | 
					    list += (10..12)
 | 
				
			||||||
 | 
					    assert( list == [1, 2, 3, 4, 10, 11, 12])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // now adding list as sublist:
 | 
				
			||||||
 | 
					    list.add(other)
 | 
				
			||||||
 | 
					    assert( list == [1, 2, 3, 4, 10, 11, 12, [3,4]])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    >>> void
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Comparisons
 | 
					## Comparisons
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert( [1, 2] != [1, 3])
 | 
					    assert( [1, 2] != [1, 3])
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,6 @@ You can use Char as both ends of the closed range:
 | 
				
			|||||||
    val r = 'a' .. 'c'
 | 
					    val r = 'a' .. 'c'
 | 
				
			||||||
    assert( 'b' in r)
 | 
					    assert( 'b' in r)
 | 
				
			||||||
    assert( 'e' !in r)
 | 
					    assert( 'e' !in r)
 | 
				
			||||||
    assert( 'c' == r[2] )
 | 
					 | 
				
			||||||
    for( ch in r )
 | 
					    for( ch in r )
 | 
				
			||||||
        println(ch)
 | 
					        println(ch)
 | 
				
			||||||
    >>> a
 | 
					    >>> a
 | 
				
			||||||
 | 
				
			|||||||
@ -278,9 +278,13 @@ Ling has built-in mutable array class `List` with simple literals:
 | 
				
			|||||||
    [1, "two", 3.33].size
 | 
					    [1, "two", 3.33].size
 | 
				
			||||||
    >>> 3
 | 
					    >>> 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[List] is an implementation of the type `Array`, and through it `Collection` and [Iterable].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Lists can contain any type of objects, lists too:
 | 
					Lists can contain any type of objects, lists too:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val list = [1, [2, 3], 4]
 | 
					    val list = [1, [2, 3], 4]
 | 
				
			||||||
 | 
					    assert( list is List )      // concrete implementatino
 | 
				
			||||||
 | 
					    assert( list is Array )     // general interface
 | 
				
			||||||
    assert(list.size == 3)
 | 
					    assert(list.size == 3)
 | 
				
			||||||
    // second element is a list too:
 | 
					    // second element is a list too:
 | 
				
			||||||
    assert(list[1].size == 2)
 | 
					    assert(list[1].size == 2)
 | 
				
			||||||
@ -307,7 +311,7 @@ Of course, you can set any list element:
 | 
				
			|||||||
    a
 | 
					    a
 | 
				
			||||||
    >>> [1, 200, 3]
 | 
					    >>> [1, 200, 3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Lists are comparable, as long as their respective elements are:
 | 
					Lists are comparable, and it works well as long as their respective elements are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert( [1,2,3] == [1,2,3])
 | 
					    assert( [1,2,3] == [1,2,3])
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -322,11 +326,48 @@ Lists are comparable, as long as their respective elements are:
 | 
				
			|||||||
    assert( [1,2,3] < [1,3] )
 | 
					    assert( [1,2,3] < [1,3] )
 | 
				
			||||||
    >>> void
 | 
					    >>> void
 | 
				
			||||||
 | 
					
 | 
				
			||||||
All comparison operators with list are working ok. Also, you can concatenate lists:
 | 
					The simplest way to concatenate lists is using `+` and `+=`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // + works to concatenate iterables: 
 | 
				
			||||||
    assert( [5, 4] + ["foo", 2] == [5, 4, "foo", 2])
 | 
					    assert( [5, 4] + ["foo", 2] == [5, 4, "foo", 2])
 | 
				
			||||||
 | 
					    var list = [1, 2]
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // append allow adding iterables: all elements of it:
 | 
				
			||||||
 | 
					    list += [2, 1]      
 | 
				
			||||||
 | 
					    // or you can append a single element:
 | 
				
			||||||
 | 
					    list += "end"
 | 
				
			||||||
 | 
					    assert( list == [1, 2, 2, 1, "end"])
 | 
				
			||||||
    >>> void
 | 
					    >>> void
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					***Important note***: the pitfall of using `+=` is that you can't append in [Iterable] instance as an object: it will always add all its contents. Use `list.add` to add a single iterable instance:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var list = [1, 2]
 | 
				
			||||||
 | 
					    val other = [3, 4]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // appending lists is clear:
 | 
				
			||||||
 | 
					    list += other
 | 
				
			||||||
 | 
					    assert( list == [1, 2, 3, 4] )
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // but appending other Iterables could be confusing:
 | 
				
			||||||
 | 
					    list += (10..12)
 | 
				
			||||||
 | 
					    assert( list == [1, 2, 3, 4, 10, 11, 12])
 | 
				
			||||||
 | 
					    >>> void
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use `list.add` to avoid confusion:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var list = [1, 2]
 | 
				
			||||||
 | 
					    val other = [3, 4]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // appending lists is clear:
 | 
				
			||||||
 | 
					    list.add(other)
 | 
				
			||||||
 | 
					    assert( list == [1, 2, [3, 4]] )
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // but appending other Iterables could be confusing:
 | 
				
			||||||
 | 
					    list.add(10..12)
 | 
				
			||||||
 | 
					    assert( list == [1, 2, [3, 4], (10..12)])
 | 
				
			||||||
 | 
					    >>> void
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To add elements to the list:
 | 
					To add elements to the list:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val x = [1,2]
 | 
					    val x = [1,2]
 | 
				
			||||||
@ -696,6 +737,10 @@ See [math functions](math.md). Other general purpose functions are:
 | 
				
			|||||||
| Real, Int, List, String, List, Bool | Class types for real numbers |
 | 
					| Real, Int, List, String, List, Bool | Class types for real numbers |
 | 
				
			||||||
| π                                   | See [math](math.md)          |
 | 
					| π                                   | See [math](math.md)          |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[List]: List.md
 | 
				
			||||||
 | 
					[Iterable]: Iterable.md
 | 
				
			||||||
 | 
					[Iterator]: Iterator.md
 | 
				
			||||||
 | 
					[Real]: Real.md
 | 
				
			||||||
 | 
					[Range]: Range.md
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -44,6 +44,12 @@ open class Obj {
 | 
				
			|||||||
    suspend fun invokeInstanceMethod(context: Context, name: String, vararg args: Obj): Obj =
 | 
					    suspend fun invokeInstanceMethod(context: Context, name: String, vararg args: Obj): Obj =
 | 
				
			||||||
        invokeInstanceMethod(context, name, Arguments(args.map { Arguments.Info(it, context.pos) }))
 | 
					        invokeInstanceMethod(context, name, Arguments(args.map { Arguments.Info(it, context.pos) }))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline suspend fun <reified T : Obj> callMethod(
 | 
				
			||||||
 | 
					        context: Context,
 | 
				
			||||||
 | 
					        name: String,
 | 
				
			||||||
 | 
					        args: Arguments = Arguments.EMPTY
 | 
				
			||||||
 | 
					    ): T = invokeInstanceMethod(context, name, args) as T
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    suspend fun invokeInstanceMethod(
 | 
					    suspend fun invokeInstanceMethod(
 | 
				
			||||||
        context: Context,
 | 
					        context: Context,
 | 
				
			||||||
        name: String,
 | 
					        name: String,
 | 
				
			||||||
 | 
				
			|||||||
@ -3,8 +3,8 @@ package net.sergeych.ling
 | 
				
			|||||||
class ObjList(val list: MutableList<Obj>) : Obj() {
 | 
					class ObjList(val list: MutableList<Obj>) : Obj() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init {
 | 
					    init {
 | 
				
			||||||
        for( p in objClass.parents)
 | 
					        for (p in objClass.parents)
 | 
				
			||||||
            parentInstances.add( p.defaultInstance())
 | 
					            parentInstances.add(p.defaultInstance())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun toString(): String = "[${
 | 
					    override fun toString(): String = "[${
 | 
				
			||||||
@ -46,20 +46,31 @@ class ObjList(val list: MutableList<Obj>) : Obj() {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override suspend fun plus(context: Context, other: Obj): Obj {
 | 
					    override suspend fun plus(context: Context, other: Obj): Obj =
 | 
				
			||||||
        (other as? ObjList) ?: context.raiseError("'+': can't concatenate $this with $other")
 | 
					        when {
 | 
				
			||||||
        return ObjList((list + other.list).toMutableList())
 | 
					            other is ObjList ->
 | 
				
			||||||
 | 
					                ObjList((list + other.list).toMutableList())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            other.isInstanceOf(ObjIterable) -> {
 | 
				
			||||||
 | 
					                val l = other.callMethod<ObjList>(context, "toList")
 | 
				
			||||||
 | 
					                ObjList((list + l.list).toMutableList())
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            else ->
 | 
				
			||||||
 | 
					                context.raiseError("'+': can't concatenate $this with $other")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override suspend fun plusAssign(context: Context, other: Obj): Obj {
 | 
					    override suspend fun plusAssign(context: Context, other: Obj): Obj {
 | 
				
			||||||
        // optimization
 | 
					        // optimization
 | 
				
			||||||
        if( other is ObjList) {
 | 
					        if (other is ObjList) {
 | 
				
			||||||
            list += other.list
 | 
					            list += other.list
 | 
				
			||||||
            return this
 | 
					            return this
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if( other.isInstanceOf(ObjIterable)) {
 | 
					        if (other.isInstanceOf(ObjIterable)) {
 | 
				
			||||||
            TODO("plusassign for iterable is not yet implemented")
 | 
					            val otherList = other.invokeInstanceMethod(context, "toList") as ObjList
 | 
				
			||||||
        }
 | 
					            list += otherList.list
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
            list += other
 | 
					            list += other
 | 
				
			||||||
        return this
 | 
					        return this
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -56,24 +56,6 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob
 | 
				
			|||||||
        return true
 | 
					        return true
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override suspend fun getAt(context: Context, index: Int): Obj {
 | 
					 | 
				
			||||||
        if (!isIntRange && !isCharRange) {
 | 
					 | 
				
			||||||
            return when (index) {
 | 
					 | 
				
			||||||
                0 -> start ?: ObjNull
 | 
					 | 
				
			||||||
                1 -> end ?: ObjNull
 | 
					 | 
				
			||||||
                else -> context.raiseIndexOutOfBounds("index out of range: $index for max of 2 for non-int ranges")
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // int range, should be finite
 | 
					 | 
				
			||||||
        val r0 = start?.toInt() ?: context.raiseArgumentError("start is not integer")
 | 
					 | 
				
			||||||
        var r1 = end?.toInt() ?: context.raiseArgumentError("end is not integer")
 | 
					 | 
				
			||||||
        if (isEndInclusive) r1++
 | 
					 | 
				
			||||||
        val i = index + r0
 | 
					 | 
				
			||||||
        if (i >= r1) context.raiseIndexOutOfBounds("index $index is not in range (${r1 - r0})")
 | 
					 | 
				
			||||||
        return if (isIntRange) ObjInt(i.toLong()) else ObjChar(i.toChar())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    val isIntRange: Boolean by lazy {
 | 
					    val isIntRange: Boolean by lazy {
 | 
				
			||||||
        start is ObjInt && end is ObjInt
 | 
					        start is ObjInt && end is ObjInt
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -82,6 +64,13 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob
 | 
				
			|||||||
        start is ObjChar && end is ObjChar
 | 
					        start is ObjChar && end is ObjChar
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override suspend fun compareTo(context: Context, other: Obj): Int {
 | 
				
			||||||
 | 
					        return (other as? ObjRange)?.let {
 | 
				
			||||||
 | 
					            if( start == other.start && end == other.end ) 0 else -1
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					            ?: -1
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    companion object {
 | 
					    companion object {
 | 
				
			||||||
        val type = ObjClass("Range", ObjIterable).apply {
 | 
					        val type = ObjClass("Range", ObjIterable).apply {
 | 
				
			||||||
            addFn("start") {
 | 
					            addFn("start") {
 | 
				
			||||||
@ -110,50 +99,3 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ObjRangeIterator(val self: ObjRange) : Obj() {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private var nextIndex = 0
 | 
					 | 
				
			||||||
    private var lastIndex = 0
 | 
					 | 
				
			||||||
    private var isCharRange: Boolean = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override val objClass: ObjClass = type
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fun Context.init() {
 | 
					 | 
				
			||||||
        if (self.start == null || self.end == null)
 | 
					 | 
				
			||||||
            raiseError("next is only available for finite ranges")
 | 
					 | 
				
			||||||
        isCharRange = self.isCharRange
 | 
					 | 
				
			||||||
        lastIndex = if (self.isIntRange || self.isCharRange) {
 | 
					 | 
				
			||||||
            if (self.isEndInclusive)
 | 
					 | 
				
			||||||
                self.end.toInt() - self.start.toInt() + 1
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                self.end.toInt() - self.start.toInt()
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            raiseError("not implemented iterator for range of $this")
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fun hasNext(): Boolean = nextIndex < lastIndex
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fun next(context: Context): Obj =
 | 
					 | 
				
			||||||
        if (nextIndex < lastIndex) {
 | 
					 | 
				
			||||||
            val x = if (self.isEndInclusive)
 | 
					 | 
				
			||||||
                self.start!!.toLong() + nextIndex++
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                self.start!!.toLong() + nextIndex++
 | 
					 | 
				
			||||||
            if( isCharRange ) ObjChar(x.toInt().toChar()) else ObjInt(x)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            context.raiseError(ObjIterationFinishedError(context))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    companion object {
 | 
					 | 
				
			||||||
        val type = ObjClass("RangeIterator", ObjIterable).apply {
 | 
					 | 
				
			||||||
            addFn("hasNext") {
 | 
					 | 
				
			||||||
                thisAs<ObjRangeIterator>().hasNext().toObj()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            addFn("next") {
 | 
					 | 
				
			||||||
                thisAs<ObjRangeIterator>().next(this)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					package net.sergeych.ling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ObjRangeIterator(val self: ObjRange) : Obj() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private var nextIndex = 0
 | 
				
			||||||
 | 
					    private var lastIndex = 0
 | 
				
			||||||
 | 
					    private var isCharRange: Boolean = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override val objClass: ObjClass = type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun Context.init() {
 | 
				
			||||||
 | 
					        if (self.start == null || self.end == null)
 | 
				
			||||||
 | 
					            raiseError("next is only available for finite ranges")
 | 
				
			||||||
 | 
					        isCharRange = self.isCharRange
 | 
				
			||||||
 | 
					        lastIndex = if (self.isIntRange || self.isCharRange) {
 | 
				
			||||||
 | 
					            if (self.isEndInclusive)
 | 
				
			||||||
 | 
					                self.end.toInt() - self.start.toInt() + 1
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                self.end.toInt() - self.start.toInt()
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            raiseError("not implemented iterator for range of $this")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun hasNext(): Boolean = nextIndex < lastIndex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun next(context: Context): Obj =
 | 
				
			||||||
 | 
					        if (nextIndex < lastIndex) {
 | 
				
			||||||
 | 
					            val x = if (self.isEndInclusive)
 | 
				
			||||||
 | 
					                self.start!!.toLong() + nextIndex++
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                self.start!!.toLong() + nextIndex++
 | 
				
			||||||
 | 
					            if( isCharRange ) ObjChar(x.toInt().toChar()) else ObjInt(x)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            context.raiseError(ObjIterationFinishedError(context))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					        val type = ObjClass("RangeIterator", ObjIterable).apply {
 | 
				
			||||||
 | 
					            addFn("hasNext") {
 | 
				
			||||||
 | 
					                thisAs<ObjRangeIterator>().hasNext().toObj()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            addFn("next") {
 | 
				
			||||||
 | 
					                thisAs<ObjRangeIterator>().next(this)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								lyng/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								lyng/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					plugins {
 | 
				
			||||||
 | 
					    kotlin("multiplatform") version "2.1.21"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					group = "net.sergeych"
 | 
				
			||||||
 | 
					version = "unspecified"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					repositories {
 | 
				
			||||||
 | 
					    mavenCentral()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					kotlin {
 | 
				
			||||||
 | 
					    jvm()
 | 
				
			||||||
 | 
					    linuxX64 {
 | 
				
			||||||
 | 
					        binaries {
 | 
				
			||||||
 | 
					            executable()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    sourceSets {
 | 
				
			||||||
 | 
					        val commonMain by getting {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        val commonTest by getting {
 | 
				
			||||||
 | 
					            dependencies {
 | 
				
			||||||
 | 
					                implementation(kotlin("test-common"))
 | 
				
			||||||
 | 
					                implementation(kotlin("test-annotations-common"))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        val linuxX64Main by getting {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								lyng/src/commonMain/kotlin/Common.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								lyng/src/commonMain/kotlin/Common.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package net.sergeych
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// common code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun commonCode() {
 | 
				
			||||||
 | 
					    println("Common code")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								lyng/src/jvmMain/kotlin/Main.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lyng/src/jvmMain/kotlin/Main.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					import net.sergeych.commonCode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
 | 
				
			||||||
 | 
					// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
 | 
				
			||||||
 | 
					fun main() {
 | 
				
			||||||
 | 
					    val name = "Kotlin"
 | 
				
			||||||
 | 
					    //TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
 | 
				
			||||||
 | 
					    // to see how GIGA IDE suggests fixing it.
 | 
				
			||||||
 | 
					    println("Hello, native " + name + "!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commonCode()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i in 1..5) {
 | 
				
			||||||
 | 
					        //TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
 | 
				
			||||||
 | 
					        // for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
 | 
				
			||||||
 | 
					        println("i = $i")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								lyng/src/linuxX64Main/kotlin/Main.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lyng/src/linuxX64Main/kotlin/Main.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					import net.sergeych.commonCode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
 | 
				
			||||||
 | 
					// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
 | 
				
			||||||
 | 
					fun main() {
 | 
				
			||||||
 | 
					    val name = "Kotlin"
 | 
				
			||||||
 | 
					    //TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
 | 
				
			||||||
 | 
					    // to see how GIGA IDE suggests fixing it.
 | 
				
			||||||
 | 
					    println("Hello, native " + name + "!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commonCode()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i in 1..5) {
 | 
				
			||||||
 | 
					        //TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
 | 
				
			||||||
 | 
					        // for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
 | 
				
			||||||
 | 
					        println("i = $i")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -17,5 +17,6 @@ dependencyResolutionManagement {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rootProject.name = "ling"
 | 
					rootProject.name = "lyng"
 | 
				
			||||||
include(":library")
 | 
					include(":library")
 | 
				
			||||||
 | 
					include(":lyng")
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user