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