int++ and int--
This commit is contained in:
parent
9ae9752634
commit
baf9eab3ba
@ -97,6 +97,10 @@ class Compiler {
|
|||||||
parseExpression(tokens)
|
parseExpression(tokens)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Token.Type.PLUS2, Token.Type.MINUS2 -> {
|
||||||
|
tokens.previous()
|
||||||
|
parseExpression(tokens)
|
||||||
|
}
|
||||||
|
|
||||||
Token.Type.LABEL -> continue
|
Token.Type.LABEL -> continue
|
||||||
Token.Type.SINLGE_LINE_COMMENT, Token.Type.MULTILINE_COMMENT -> continue
|
Token.Type.SINLGE_LINE_COMMENT, Token.Type.MULTILINE_COMMENT -> continue
|
||||||
@ -222,6 +226,25 @@ class Compiler {
|
|||||||
throw ScriptError(t.pos, "Expected identifier after '.'")
|
throw ScriptError(t.pos, "Expected identifier after '.'")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token.Type.PLUS2 -> {
|
||||||
|
statement(id.pos) { context ->
|
||||||
|
context.pos = id.pos
|
||||||
|
val v = resolve(context).get(id.value)
|
||||||
|
?: throw ScriptError(id.pos, "Undefined symbol: ${id.value}")
|
||||||
|
v.value?.getAndIncrement(context)
|
||||||
|
?: context.raiseNPE()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Token.Type.MINUS2 -> {
|
||||||
|
statement(id.pos) { context ->
|
||||||
|
context.pos = id.pos
|
||||||
|
val v = resolve(context).get(id.value)
|
||||||
|
?: throw ScriptError(id.pos, "Undefined symbol: ${id.value}")
|
||||||
|
v.value?.getAndDecrement(context)
|
||||||
|
?: context.raiseNPE()
|
||||||
|
}
|
||||||
|
}
|
||||||
Token.Type.LPAREN -> {
|
Token.Type.LPAREN -> {
|
||||||
// function call
|
// function call
|
||||||
// Load arg list
|
// Load arg list
|
||||||
@ -243,10 +266,11 @@ class Compiler {
|
|||||||
resolve(context).get(id.value) ?: throw ScriptError(id.pos, "Undefined function: ${id.value}")
|
resolve(context).get(id.value) ?: throw ScriptError(id.pos, "Undefined function: ${id.value}")
|
||||||
(v.value as? Statement)?.execute(
|
(v.value as? Statement)?.execute(
|
||||||
context.copy(
|
context.copy(
|
||||||
|
id.pos,
|
||||||
Arguments(
|
Arguments(
|
||||||
nt.pos,
|
nt.pos,
|
||||||
args.map { Arguments.Info((it.value as Statement).execute(context), it.pos) }
|
args.map { Arguments.Info((it.value as Statement).execute(context), it.pos) }
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
?: throw ScriptError(id.pos, "Variable $id is not callable ($id)")
|
?: throw ScriptError(id.pos, "Variable $id is not callable ($id)")
|
||||||
@ -501,8 +525,9 @@ class Compiler {
|
|||||||
var closure: Context? = null
|
var closure: Context? = null
|
||||||
|
|
||||||
val fnBody = statement(t.pos) { callerContext ->
|
val fnBody = statement(t.pos) { callerContext ->
|
||||||
|
callerContext.pos = start
|
||||||
// restore closure where the function was defined:
|
// restore closure where the function was defined:
|
||||||
val context = closure ?: Context()
|
val context = closure ?: callerContext.raiseError("bug: closure not set")
|
||||||
// load params from caller context
|
// load params from caller context
|
||||||
for ((i, d) in params.withIndex()) {
|
for ((i, d) in params.withIndex()) {
|
||||||
if (i < callerContext.args.size)
|
if (i < callerContext.args.size)
|
||||||
@ -539,7 +564,7 @@ class Compiler {
|
|||||||
val block = parseScript(t.pos, tokens)
|
val block = parseScript(t.pos, tokens)
|
||||||
return statement(t.pos) {
|
return statement(t.pos) {
|
||||||
// block run on inner context:
|
// block run on inner context:
|
||||||
block.execute(it.copy())
|
block.execute(it.copy(t.pos))
|
||||||
}.also {
|
}.also {
|
||||||
val t1 = tokens.next()
|
val t1 = tokens.next()
|
||||||
if (t1.type != Token.Type.RBRACE)
|
if (t1.type != Token.Type.RBRACE)
|
||||||
|
@ -1,9 +1,27 @@
|
|||||||
package net.sergeych.ling
|
package net.sergeych.ling
|
||||||
|
|
||||||
class Context(
|
class Context(
|
||||||
val parent: Context? = Script.defaultContext.copy(),
|
val parent: Context?,
|
||||||
val args: Arguments = Arguments.EMPTY
|
val args: Arguments = Arguments.EMPTY,
|
||||||
|
var pos: Pos = Pos.builtIn
|
||||||
) {
|
) {
|
||||||
|
constructor(
|
||||||
|
args: Arguments = Arguments.EMPTY,
|
||||||
|
pos: Pos = Pos.builtIn
|
||||||
|
)
|
||||||
|
: this(Script.defaultContext, args, pos)
|
||||||
|
|
||||||
|
fun raiseNotImplemented(): Nothing = raiseError("operation not implemented")
|
||||||
|
|
||||||
|
fun raiseNPE(): Nothing = raiseError(ObjNullPointerError(this))
|
||||||
|
|
||||||
|
fun raiseError(message: String): Nothing {
|
||||||
|
throw ExecutionError(ObjError(this, message))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun raiseError(obj: ObjError): Nothing {
|
||||||
|
throw ExecutionError(obj)
|
||||||
|
}
|
||||||
|
|
||||||
private val objects = mutableMapOf<String, StoredObj>()
|
private val objects = mutableMapOf<String, StoredObj>()
|
||||||
|
|
||||||
@ -11,14 +29,20 @@ class Context(
|
|||||||
objects[name]
|
objects[name]
|
||||||
?: parent?.get(name)
|
?: parent?.get(name)
|
||||||
|
|
||||||
fun copy(args: Arguments = Arguments.EMPTY): Context = Context(this, args)
|
fun copy(pos: Pos, args: Arguments = Arguments.EMPTY): Context = Context(this, args, pos)
|
||||||
|
|
||||||
fun addItem(name: String, isMutable: Boolean, value: Obj?) {
|
fun addItem(name: String, isMutable: Boolean, value: Obj?) {
|
||||||
objects.put(name, StoredObj(name, value, isMutable))
|
objects.put(name, StoredObj(name, value, isMutable))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOrCreateNamespace(name: String) =
|
fun getOrCreateNamespace(name: String) =
|
||||||
(objects.getOrPut(name) { StoredObj(name, ObjNamespace(name,copy()), isMutable = false) }.value as ObjNamespace)
|
(objects.getOrPut(name) {
|
||||||
|
StoredObj(
|
||||||
|
name,
|
||||||
|
ObjNamespace(name, copy(pos)),
|
||||||
|
isMutable = false
|
||||||
|
)
|
||||||
|
}.value as ObjNamespace)
|
||||||
.context
|
.context
|
||||||
|
|
||||||
inline fun <reified T> addFn(vararg names: String, crossinline fn: suspend Context.() -> T) {
|
inline fun <reified T> addFn(vararg names: String, crossinline fn: suspend Context.() -> T) {
|
||||||
@ -43,7 +67,7 @@ class Context(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T> addConst(value: T,vararg names: String) {
|
inline fun <reified T> addConst(value: T, vararg names: String) {
|
||||||
val obj = Obj.from(value)
|
val obj = Obj.from(value)
|
||||||
for (name in names) {
|
for (name in names) {
|
||||||
addItem(
|
addItem(
|
||||||
@ -59,8 +83,5 @@ class Context(
|
|||||||
|
|
||||||
fun containsLocal(name: String): Boolean = name in objects
|
fun containsLocal(name: String): Boolean = name in objects
|
||||||
|
|
||||||
companion object {
|
|
||||||
operator fun invoke() = Context()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ sealed class ClassDef(
|
|||||||
) {
|
) {
|
||||||
instanceLock.withLock {
|
instanceLock.withLock {
|
||||||
instanceMethods[name]?.let {
|
instanceMethods[name]?.let {
|
||||||
if( !it.isMutable )
|
if (!it.isMutable)
|
||||||
throw ScriptError(pos, "existing method $name is frozen and can't be updated")
|
throw ScriptError(pos, "existing method $name is frozen and can't be updated")
|
||||||
it.value = body
|
it.value = body
|
||||||
} ?: instanceMethods.put(name, Item(body, freeze))
|
} ?: instanceMethods.put(name, Item(body, freeze))
|
||||||
@ -36,7 +36,7 @@ sealed class ClassDef(
|
|||||||
|
|
||||||
//suspend fun callInstanceMethod(context: Context, self: Obj,args: Arguments): Obj {
|
//suspend fun callInstanceMethod(context: Context, self: Obj,args: Arguments): Obj {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
object ObjClassDef : ClassDef("Obj")
|
object ObjClassDef : ClassDef("Obj")
|
||||||
@ -49,6 +49,18 @@ sealed class Obj : Comparable<Obj> {
|
|||||||
|
|
||||||
open val definition: ClassDef = ObjClassDef
|
open val definition: ClassDef = ObjClassDef
|
||||||
|
|
||||||
|
open fun plus(context: Context, other: Obj): Obj {
|
||||||
|
context.raiseNotImplemented()
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun getAndIncrement(context: Context): Obj {
|
||||||
|
context.raiseNotImplemented()
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun getAndDecrement(context: Context): Obj {
|
||||||
|
context.raiseNotImplemented()
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
enum class Type {
|
enum class Type {
|
||||||
@SerialName("Void")
|
@SerialName("Void")
|
||||||
@ -179,12 +191,27 @@ data class ObjReal(val value: Double) : Obj(), Numeric {
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("int")
|
@SerialName("int")
|
||||||
data class ObjInt(val value: Long) : Obj(), Numeric {
|
data class ObjInt(var value: Long) : Obj(), Numeric {
|
||||||
override val asStr by lazy { ObjString(value.toString()) }
|
override val asStr get() = ObjString(value.toString())
|
||||||
override val longValue: Long by lazy { value }
|
override val longValue get() = value
|
||||||
override val doubleValue: Double by lazy { value.toDouble() }
|
override val doubleValue get() = value.toDouble()
|
||||||
override val toObjInt: ObjInt by lazy { ObjInt(value) }
|
override val toObjInt get() = this
|
||||||
override val toObjReal: ObjReal by lazy { ObjReal(doubleValue) }
|
override val toObjReal = ObjReal(doubleValue)
|
||||||
|
|
||||||
|
override fun getAndIncrement(context: Context): Obj {
|
||||||
|
return ObjInt(value).also { value++ }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAndDecrement(context: Context): Obj {
|
||||||
|
return ObjInt(value).also { value-- }
|
||||||
|
}
|
||||||
|
|
||||||
|
// override fun plus(context: Context, other: Obj): Obj {
|
||||||
|
// if (other !is Numeric)
|
||||||
|
// context.raiseError("cannot add $this with $other")
|
||||||
|
// return if (other is ObjInt)
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
override fun compareTo(other: Obj): Int {
|
override fun compareTo(other: Obj): Int {
|
||||||
if (other !is Numeric) throw IllegalArgumentException("cannot compare $this with $other")
|
if (other !is Numeric) throw IllegalArgumentException("cannot compare $this with $other")
|
||||||
@ -215,4 +242,13 @@ data class ObjNamespace(val name: String, val context: Context) : Obj() {
|
|||||||
override fun compareTo(other: Obj): Int {
|
override fun compareTo(other: Obj): Int {
|
||||||
throw IllegalArgumentException("cannot compare namespaces")
|
throw IllegalArgumentException("cannot compare namespaces")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class ObjError(val context: Context, val message: String) : Obj() {
|
||||||
|
override val asStr: ObjString by lazy { ObjString("Error: $message") }
|
||||||
|
override fun compareTo(other: Obj): Int {
|
||||||
|
if (other === this) return 0 else return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ObjNullPointerError(context: Context) : ObjError(context, "object is null")
|
||||||
|
@ -50,8 +50,21 @@ private class Parser(fromPos: Pos) {
|
|||||||
Token("=", from, Token.Type.ASSIGN)
|
Token("=", from, Token.Type.ASSIGN)
|
||||||
}
|
}
|
||||||
|
|
||||||
'+' -> Token("+", from, Token.Type.PLUS)
|
'+' -> {
|
||||||
'-' -> Token("-", from, Token.Type.MINUS)
|
if( currentChar == '+') {
|
||||||
|
advance()
|
||||||
|
Token("+", from, Token.Type.PLUS2)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Token("+", from, Token.Type.PLUS)
|
||||||
|
}
|
||||||
|
'-' -> {
|
||||||
|
if (currentChar == '-') {
|
||||||
|
advance()
|
||||||
|
Token("--", from, Token.Type.MINUS2)
|
||||||
|
} else
|
||||||
|
Token("-", from, Token.Type.MINUS)
|
||||||
|
}
|
||||||
'*' -> Token("*", from, Token.Type.STAR)
|
'*' -> Token("*", from, Token.Type.STAR)
|
||||||
'/' -> {
|
'/' -> {
|
||||||
if( currentChar == '/') {
|
if( currentChar == '/') {
|
||||||
|
@ -15,10 +15,10 @@ class Script(
|
|||||||
return lastResult
|
return lastResult
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun execute() = execute(defaultContext.copy())
|
suspend fun execute() = execute(defaultContext.copy(pos))
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val defaultContext: Context = Context(null).apply {
|
val defaultContext: Context = Context().apply {
|
||||||
addFn("println") {
|
addFn("println") {
|
||||||
print("yn: ")
|
print("yn: ")
|
||||||
for( (i,a) in args.withIndex() ) {
|
for( (i,a) in args.withIndex() ) {
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
|
@file:Suppress("CanBeParameter")
|
||||||
|
|
||||||
package net.sergeych.ling
|
package net.sergeych.ling
|
||||||
|
|
||||||
class ScriptError(val pos: Pos, val errorMessage: String) : Exception(
|
open class ScriptError(val pos: Pos, val errorMessage: String) : Exception(
|
||||||
"""
|
"""
|
||||||
$pos: Error: $errorMessage
|
$pos: Error: $errorMessage
|
||||||
${pos.currentLine}
|
${pos.currentLine}
|
||||||
${"-".repeat(pos.column)}^
|
${"-".repeat(pos.column)}^
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class ExecutionError(val errorObject: ObjError) : ScriptError(errorObject.context.pos, errorObject.message)
|
||||||
|
@ -8,6 +8,7 @@ data class Token(val value: String, val pos: Pos, val type: Type) {
|
|||||||
ID, INT, REAL, HEX, STRING, LPAREN, RPAREN, LBRACE, RBRACE, LBRACKET, RBRACKET, COMMA,
|
ID, INT, REAL, HEX, STRING, LPAREN, RPAREN, LBRACE, RBRACE, LBRACKET, RBRACKET, COMMA,
|
||||||
SEMICOLON, COLON,
|
SEMICOLON, COLON,
|
||||||
PLUS, MINUS, STAR, SLASH, ASSIGN,
|
PLUS, MINUS, STAR, SLASH, ASSIGN,
|
||||||
|
PLUS2, MINUS2,
|
||||||
EQ, NEQ, LT, LTE, GT, GTE,
|
EQ, NEQ, LT, LTE, GT, GTE,
|
||||||
AND, BITAND, OR, BITOR, NOT, DOT, ARROW, QUESTION, COLONCOLON, PERCENT,
|
AND, BITAND, OR, BITOR, NOT, DOT, ARROW, QUESTION, COLONCOLON, PERCENT,
|
||||||
SINLGE_LINE_COMMENT, MULTILINE_COMMENT,
|
SINLGE_LINE_COMMENT, MULTILINE_COMMENT,
|
||||||
|
@ -117,7 +117,7 @@ class ScriptTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun varsAndConstsTest() = runTest {
|
fun varsAndConstsTest() = runTest {
|
||||||
val context = Context()
|
val context = Context(pos = Pos.builtIn)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
ObjVoid, context.eval(
|
ObjVoid, context.eval(
|
||||||
"""
|
"""
|
||||||
@ -137,7 +137,7 @@ class ScriptTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun functionTest() = runTest {
|
fun functionTest() = runTest {
|
||||||
val context = Context()
|
val context = Context(pos = Pos.builtIn)
|
||||||
context.eval(
|
context.eval(
|
||||||
"""
|
"""
|
||||||
fun foo(a, b) {
|
fun foo(a, b) {
|
||||||
@ -163,7 +163,7 @@ class ScriptTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun simpleClosureTest() = runTest {
|
fun simpleClosureTest() = runTest {
|
||||||
val context = Context()
|
val context = Context(pos = Pos.builtIn)
|
||||||
context.eval(
|
context.eval(
|
||||||
"""
|
"""
|
||||||
var global = 10
|
var global = 10
|
||||||
@ -180,7 +180,7 @@ class ScriptTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun nullAndVoidTest() = runTest {
|
fun nullAndVoidTest() = runTest {
|
||||||
val context = Context()
|
val context = Context(pos = Pos.builtIn)
|
||||||
assertEquals(ObjVoid, context.eval("void"))
|
assertEquals(ObjVoid, context.eval("void"))
|
||||||
assertEquals(ObjNull, context.eval("null"))
|
assertEquals(ObjNull, context.eval("null"))
|
||||||
}
|
}
|
||||||
@ -252,7 +252,7 @@ class ScriptTest {
|
|||||||
@Test
|
@Test
|
||||||
fun ifTest() = runTest {
|
fun ifTest() = runTest {
|
||||||
// if - single line
|
// if - single line
|
||||||
var context = Context()
|
var context = Context(pos = Pos.builtIn)
|
||||||
context.eval(
|
context.eval(
|
||||||
"""
|
"""
|
||||||
fn test1(n) {
|
fn test1(n) {
|
||||||
@ -267,7 +267,7 @@ class ScriptTest {
|
|||||||
assertEquals("more", context.eval("test1(1)").toString())
|
assertEquals("more", context.eval("test1(1)").toString())
|
||||||
|
|
||||||
// if - multiline (block)
|
// if - multiline (block)
|
||||||
context = Context()
|
context = Context(pos = Pos.builtIn)
|
||||||
context.eval(
|
context.eval(
|
||||||
"""
|
"""
|
||||||
fn test1(n) {
|
fn test1(n) {
|
||||||
@ -286,7 +286,7 @@ class ScriptTest {
|
|||||||
assertEquals("answer: more", context.eval("test1(1)").toString())
|
assertEquals("answer: more", context.eval("test1(1)").toString())
|
||||||
|
|
||||||
// else single line1
|
// else single line1
|
||||||
context = Context()
|
context = Context(pos = Pos.builtIn)
|
||||||
context.eval(
|
context.eval(
|
||||||
"""
|
"""
|
||||||
fn test1(n) {
|
fn test1(n) {
|
||||||
@ -301,7 +301,7 @@ class ScriptTest {
|
|||||||
assertEquals("more", context.eval("test1(1)").toString())
|
assertEquals("more", context.eval("test1(1)").toString())
|
||||||
|
|
||||||
// if/else with blocks
|
// if/else with blocks
|
||||||
context = Context()
|
context = Context(pos = Pos.builtIn )
|
||||||
context.eval(
|
context.eval(
|
||||||
"""
|
"""
|
||||||
fn test1(n) {
|
fn test1(n) {
|
||||||
@ -443,4 +443,86 @@ class ScriptTest {
|
|||||||
.toString()
|
.toString()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIncr() = runTest {
|
||||||
|
val c = Context()
|
||||||
|
c.eval("var x = 10")
|
||||||
|
assertEquals(10, c.eval("x++").toInt())
|
||||||
|
assertEquals(11, c.eval("x++").toInt())
|
||||||
|
assertEquals(12, c.eval("x").toInt())
|
||||||
|
|
||||||
|
assertEquals(12, c.eval("x").toInt())
|
||||||
|
assertEquals(12, c.eval("x").toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDecr() = runTest {
|
||||||
|
val c = Context()
|
||||||
|
c.eval("var x = 9")
|
||||||
|
assertEquals(9, c.eval("x--").toInt())
|
||||||
|
assertEquals(8, c.eval("x--").toInt())
|
||||||
|
assertEquals(7, c.eval("x--").toInt())
|
||||||
|
assertEquals(6, c.eval("x--").toInt())
|
||||||
|
assertEquals(5, c.eval("x").toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDecrIncr() = runTest {
|
||||||
|
val c = Context()
|
||||||
|
c.eval("var x = 9")
|
||||||
|
assertEquals(9, c.eval("x++").toInt())
|
||||||
|
assertEquals(10, c.eval("x++").toInt())
|
||||||
|
assertEquals(11, c.eval("x").toInt())
|
||||||
|
assertEquals(11, c.eval("x--").toInt())
|
||||||
|
assertEquals(10, c.eval("x--").toInt())
|
||||||
|
assertEquals(9, c.eval("x--").toInt())
|
||||||
|
assertEquals(8, c.eval("x--").toInt())
|
||||||
|
assertEquals(7, c.eval("x + 0").toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDecrIncr2() = runTest {
|
||||||
|
val c = Context()
|
||||||
|
c.eval("var x = 9")
|
||||||
|
assertEquals(9, c.eval("x--").toInt())
|
||||||
|
assertEquals(8, c.eval("x--").toInt())
|
||||||
|
assertEquals(7, c.eval("x--").toInt())
|
||||||
|
assertEquals(6, c.eval("x").toInt())
|
||||||
|
assertEquals(6, c.eval("x++").toInt())
|
||||||
|
assertEquals(7, c.eval("x++").toInt())
|
||||||
|
assertEquals(8, c.eval("x")
|
||||||
|
.also {
|
||||||
|
println("${it.toDouble()} ${it.toInt()} ${it.toLong()} ${it.toInt()}")
|
||||||
|
}
|
||||||
|
.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDecrIncr3() = runTest {
|
||||||
|
val c = Context()
|
||||||
|
c.eval("var x = 9")
|
||||||
|
assertEquals(9, c.eval("x++").toInt())
|
||||||
|
assertEquals(10, c.eval("x++").toInt())
|
||||||
|
assertEquals(11, c.eval("x++").toInt())
|
||||||
|
assertEquals(12, c.eval("x").toInt())
|
||||||
|
assertEquals(12, c.eval("x--").toInt())
|
||||||
|
assertEquals(11, c.eval("x").toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIncrAndDecr() = runTest {
|
||||||
|
val c = Context()
|
||||||
|
assertEquals( "8", c.eval("""
|
||||||
|
var x = 5
|
||||||
|
x--
|
||||||
|
x--
|
||||||
|
x++
|
||||||
|
x * 2
|
||||||
|
""").toString())
|
||||||
|
|
||||||
|
assertEquals( "4", c.eval("x").toString())
|
||||||
|
// assertEquals( "8", c.eval("x*2").toString())
|
||||||
|
// assertEquals( "4", c.eval("x+0").toString())
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user