fix #39 correct implementation of ++ and -- with indexing access
This commit is contained in:
		
							parent
							
								
									f1ae4b2d23
								
							
						
					
					
						commit
						5848adca61
					
				@ -54,6 +54,8 @@ Buffer provides concatenation with another Buffer:
 | 
			
		||||
    assertEquals( Buffer(101, 102, 1, 2), b + [1,2])
 | 
			
		||||
    >>> void
 | 
			
		||||
 | 
			
		||||
Please note that indexed bytes are _readonly projection_, e.g. you can't modify these with
 | 
			
		||||
 | 
			
		||||
## Comparing
 | 
			
		||||
 | 
			
		||||
Buffers are comparable with other buffers:
 | 
			
		||||
 | 
			
		||||
@ -12,10 +12,6 @@ class Compiler(
 | 
			
		||||
    settings: Settings = Settings()
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        println("Compiler initialized: $importManager")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var packageName: String? = null
 | 
			
		||||
 | 
			
		||||
    class Settings
 | 
			
		||||
@ -27,7 +23,7 @@ class Compiler(
 | 
			
		||||
        // package level declarations
 | 
			
		||||
        do {
 | 
			
		||||
            val t = cc.current()
 | 
			
		||||
            if(t.type == Token.Type.NEWLINE || t.type == Token.Type.SINLGE_LINE_COMMENT || t.type == Token.Type.MULTILINE_COMMENT) {
 | 
			
		||||
            if (t.type == Token.Type.NEWLINE || t.type == Token.Type.SINLGE_LINE_COMMENT || t.type == Token.Type.MULTILINE_COMMENT) {
 | 
			
		||||
                cc.next()
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
@ -44,6 +40,7 @@ class Compiler(
 | 
			
		||||
                        packageName = name
 | 
			
		||||
                        continue
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    "import" -> {
 | 
			
		||||
                        cc.next()
 | 
			
		||||
                        val pos = cc.currentPos()
 | 
			
		||||
@ -349,17 +346,26 @@ class Compiler(
 | 
			
		||||
                        left.setter(startPos)
 | 
			
		||||
                        operand = Accessor { cxt ->
 | 
			
		||||
                            val x = left.getter(cxt)
 | 
			
		||||
                            if (x.isMutable)
 | 
			
		||||
                                x.value.getAndIncrement(cxt).asReadonly
 | 
			
		||||
                            else cxt.raiseError("Cannot increment immutable value")
 | 
			
		||||
                            if (x.isMutable) {
 | 
			
		||||
                                if (x.value.isConst) {
 | 
			
		||||
                                    x.value.plus(cxt, ObjInt.One).also {
 | 
			
		||||
                                        left.setter(startPos)(cxt, it)
 | 
			
		||||
                                    }.asReadonly
 | 
			
		||||
                                } else
 | 
			
		||||
                                    x.value.getAndIncrement(cxt).asReadonly
 | 
			
		||||
                            } else cxt.raiseError("Cannot increment immutable value")
 | 
			
		||||
                        }
 | 
			
		||||
                    } ?: run {
 | 
			
		||||
                        // no lvalue means pre-increment, expression to increment follows
 | 
			
		||||
                        val next = parseAccessor() ?: throw ScriptError(t.pos, "Expecting expression")
 | 
			
		||||
                        val next = parseTerm() ?: throw ScriptError(t.pos, "Expecting expression")
 | 
			
		||||
                        operand = Accessor { ctx ->
 | 
			
		||||
                            next.getter(ctx).also {
 | 
			
		||||
                            val x = next.getter(ctx).also {
 | 
			
		||||
                                if (!it.isMutable) ctx.raiseError("Cannot increment immutable value")
 | 
			
		||||
                            }.value.incrementAndGet(ctx).asReadonly
 | 
			
		||||
                            }.value
 | 
			
		||||
                            if (x.isConst) {
 | 
			
		||||
                                next.setter(startPos)(ctx, x.plus(ctx, ObjInt.One))
 | 
			
		||||
                                x.asReadonly
 | 
			
		||||
                            } else x.incrementAndGet(ctx).asReadonly
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@ -369,18 +375,28 @@ class Compiler(
 | 
			
		||||
                    operand?.let { left ->
 | 
			
		||||
                        // post decrement
 | 
			
		||||
                        left.setter(startPos)
 | 
			
		||||
                        operand = Accessor { ctx ->
 | 
			
		||||
                            left.getter(ctx).also {
 | 
			
		||||
                                if (!it.isMutable) ctx.raiseError("Cannot decrement immutable value")
 | 
			
		||||
                            }.value.getAndDecrement(ctx).asReadonly
 | 
			
		||||
                        operand = Accessor { cxt ->
 | 
			
		||||
                            val x = left.getter(cxt)
 | 
			
		||||
                            if (!x.isMutable) cxt.raiseError("Cannot decrement immutable value")
 | 
			
		||||
                            if (x.value.isConst) {
 | 
			
		||||
                                x.value.minus(cxt, ObjInt.One).also {
 | 
			
		||||
                                    left.setter(startPos)(cxt, it)
 | 
			
		||||
                                }.asReadonly
 | 
			
		||||
                            } else
 | 
			
		||||
                                x.value.getAndDecrement(cxt).asReadonly
 | 
			
		||||
                        }
 | 
			
		||||
                    } ?: run {
 | 
			
		||||
                        // no lvalue means pre-decrement, expression to decrement follows
 | 
			
		||||
                        val next = parseAccessor() ?: throw ScriptError(t.pos, "Expecting expression")
 | 
			
		||||
                        operand = Accessor { ctx ->
 | 
			
		||||
                            next.getter(ctx).also {
 | 
			
		||||
                                if (!it.isMutable) ctx.raiseError("Cannot decrement immutable value")
 | 
			
		||||
                            }.value.decrementAndGet(ctx).asReadonly
 | 
			
		||||
                        val next = parseTerm() ?: throw ScriptError(t.pos, "Expecting expression")
 | 
			
		||||
                        operand = Accessor { cxt ->
 | 
			
		||||
                            val x = next.getter(cxt)
 | 
			
		||||
                            if (!x.isMutable) cxt.raiseError("Cannot decrement immutable value")
 | 
			
		||||
                            if (x.value.isConst) {
 | 
			
		||||
                                x.value.minus(cxt, ObjInt.One).also {
 | 
			
		||||
                                    next.setter(startPos)(cxt, it)
 | 
			
		||||
                                }.asReadonly
 | 
			
		||||
                            } else
 | 
			
		||||
                                x.value.decrementAndGet(cxt).asReadonly
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@ -1623,8 +1639,8 @@ class Compiler(
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
 | 
			
		||||
        suspend fun compile(source: Source,importManager: ImportProvider): Script {
 | 
			
		||||
            return Compiler(CompilerContext(parseLyng(source)),importManager).parseScript()
 | 
			
		||||
        suspend fun compile(source: Source, importManager: ImportProvider): Script {
 | 
			
		||||
            return Compiler(CompilerContext(parseLyng(source)), importManager).parseScript()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private var lastPriority = 0
 | 
			
		||||
 | 
			
		||||
@ -48,6 +48,12 @@ data class Accessor(
 | 
			
		||||
 | 
			
		||||
open class Obj {
 | 
			
		||||
 | 
			
		||||
    open val isConst: Boolean = false
 | 
			
		||||
 | 
			
		||||
    fun ensureNotConst(scope: Scope) {
 | 
			
		||||
        if( isConst ) scope.raiseError("can't assign to constant")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val isNull by lazy { this === ObjNull }
 | 
			
		||||
 | 
			
		||||
    var isFrozen: Boolean = false
 | 
			
		||||
 | 
			
		||||
@ -82,7 +82,6 @@ open class ObjClass(
 | 
			
		||||
 | 
			
		||||
    override suspend fun readField(scope: Scope, name: String): ObjRecord {
 | 
			
		||||
        classMembers[name]?.let {
 | 
			
		||||
            println("class field $it")
 | 
			
		||||
            return it
 | 
			
		||||
        }
 | 
			
		||||
        return super.readField(scope, name)
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
package net.sergeych.lyng
 | 
			
		||||
 | 
			
		||||
class ObjInt(var value: Long,val isConst: Boolean = false) : Obj(), Numeric {
 | 
			
		||||
class ObjInt(var value: Long,override val isConst: Boolean = false) : Obj(), Numeric {
 | 
			
		||||
    override val asStr get() = ObjString(value.toString())
 | 
			
		||||
    override val longValue get() = value
 | 
			
		||||
    override val doubleValue get() = value.toDouble()
 | 
			
		||||
@ -14,18 +14,22 @@ class ObjInt(var value: Long,val isConst: Boolean = false) : Obj(), Numeric {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun getAndIncrement(scope: Scope): Obj {
 | 
			
		||||
        ensureNotConst(scope)
 | 
			
		||||
        return ObjInt(value).also { value++ }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun getAndDecrement(scope: Scope): Obj {
 | 
			
		||||
        ensureNotConst(scope)
 | 
			
		||||
        return ObjInt(value).also { value-- }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun incrementAndGet(scope: Scope): Obj {
 | 
			
		||||
        ensureNotConst(scope)
 | 
			
		||||
        return ObjInt(++value)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun decrementAndGet(scope: Scope): Obj {
 | 
			
		||||
        ensureNotConst(scope)
 | 
			
		||||
        return ObjInt(--value)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -101,7 +101,6 @@ class ImportManager(
 | 
			
		||||
     */
 | 
			
		||||
    private suspend fun doImport(packageName: String, pos: Pos): ModuleScope {
 | 
			
		||||
        val entry = imports[packageName] ?: throw ImportException(pos, "package not found: $packageName")
 | 
			
		||||
        println("import enrty found: $packageName")
 | 
			
		||||
        return entry.getScope(pos)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ sealed class ObjType {
 | 
			
		||||
@Suppress("unused")
 | 
			
		||||
abstract class Statement(
 | 
			
		||||
    val isStaticConst: Boolean = false,
 | 
			
		||||
    val isConst: Boolean = false,
 | 
			
		||||
    override val isConst: Boolean = false,
 | 
			
		||||
    val returnType: ObjType = ObjType.Any
 | 
			
		||||
) : Obj() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -707,19 +707,13 @@ class ScriptTest {
 | 
			
		||||
            var t1 = 10
 | 
			
		||||
            outer@ while( t1 > 0 ) {
 | 
			
		||||
                var t2 = 10
 | 
			
		||||
                println("starting t2 = " + t2)
 | 
			
		||||
                while( t2 > 0 ) {
 | 
			
		||||
                    t2 = t2 - 1
 | 
			
		||||
                    println("t2 " + t2 + " t1 " + t1)
 | 
			
		||||
                    if( t2 == 3 && t1 == 7) {
 | 
			
		||||
                        println("will break")
 | 
			
		||||
                        break@outer "ok2:"+t2+":"+t1
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                println("next t1")
 | 
			
		||||
                t1 = t1 - 1
 | 
			
		||||
                println("t1 now "+t1)
 | 
			
		||||
                t1
 | 
			
		||||
                --t1
 | 
			
		||||
            }
 | 
			
		||||
        """.trimIndent()
 | 
			
		||||
            ).toString()
 | 
			
		||||
@ -734,8 +728,6 @@ class ScriptTest {
 | 
			
		||||
                """
 | 
			
		||||
                val count = 3
 | 
			
		||||
                val res = if( count > 10 ) "too much" else "just " + count
 | 
			
		||||
                println(count)
 | 
			
		||||
                println(res)
 | 
			
		||||
                res
 | 
			
		||||
                """.trimIndent()
 | 
			
		||||
            )
 | 
			
		||||
@ -771,7 +763,7 @@ class ScriptTest {
 | 
			
		||||
    fun testDecr() = runTest {
 | 
			
		||||
        val c = Scope()
 | 
			
		||||
        c.eval("var x = 9")
 | 
			
		||||
        assertEquals(9, c.eval("x--").toInt())
 | 
			
		||||
        assertEquals(9, c.eval("println(x); val a = x--; println(x); println(a); a").toInt())
 | 
			
		||||
        assertEquals(8, c.eval("x--").toInt())
 | 
			
		||||
        assertEquals(7, c.eval("x--").toInt())
 | 
			
		||||
        assertEquals(6, c.eval("x--").toInt())
 | 
			
		||||
@ -2612,4 +2604,40 @@ class ScriptTest {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testIndexIntIncrements() = runTest {
 | 
			
		||||
        eval("""
 | 
			
		||||
        val x = [1,2,3]
 | 
			
		||||
        x[1]++
 | 
			
		||||
        ++x[0]
 | 
			
		||||
        assertEquals( [2,3,3], x )
 | 
			
		||||
        
 | 
			
		||||
        import lyng.buffer
 | 
			
		||||
        
 | 
			
		||||
        val b = Buffer(1,2,3)
 | 
			
		||||
        b[1]++
 | 
			
		||||
        assert( b == Buffer(1,3,3) )
 | 
			
		||||
        ++b[0]
 | 
			
		||||
        assertEquals( b, Buffer(2,3,3) )
 | 
			
		||||
        """.trimIndent())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testIndexIntDecrements() = runTest {
 | 
			
		||||
        eval("""
 | 
			
		||||
        val x = [1,2,3]
 | 
			
		||||
        x[1]--
 | 
			
		||||
        --x[0]
 | 
			
		||||
        assertEquals( [0,1,3], x )
 | 
			
		||||
        
 | 
			
		||||
        import lyng.buffer
 | 
			
		||||
        
 | 
			
		||||
        val b = Buffer(1,2,3)
 | 
			
		||||
        b[1]--
 | 
			
		||||
        assert( b == Buffer(1,1,3) )
 | 
			
		||||
        --b[0]
 | 
			
		||||
        assertEquals( b, Buffer(0,1,3) )
 | 
			
		||||
        """.trimIndent())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user