diff --git a/.run/Tests in 'lyng.lynglib.jvmTest'.run.xml b/.run/Tests in 'lyng.lynglib.jvmTest'.run.xml new file mode 100644 index 0000000..2a4139c --- /dev/null +++ b/.run/Tests in 'lyng.lynglib.jvmTest'.run.xml @@ -0,0 +1,28 @@ + + + + + + + false + true + false + false + true + false + false + + + \ No newline at end of file diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt index 4858297..1626253 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt @@ -155,52 +155,65 @@ class Script( sqrt(args.firstAndOnly().toDouble()) ) } - addFn( "abs" ) { + addFn("abs") { val x = args.firstAndOnly() - if( x is ObjInt) ObjInt( x.value.absoluteValue ) else ObjReal( x.toDouble().absoluteValue ) + if (x is ObjInt) ObjInt(x.value.absoluteValue) else ObjReal(x.toDouble().absoluteValue) } addVoidFn("assert") { val cond = requiredArg(0) - val message = if( args.size > 1 ) + val message = if (args.size > 1) ": " + (args[1] as Statement).execute(this).toString(this).value else "" - if( !cond.value == true ) + if (!cond.value == true) raiseError(ObjAssertionFailedException(this, "Assertion failed$message")) } addVoidFn("assertEquals") { val a = requiredArg(0) val b = requiredArg(1) - if( a.compareTo(this, b) != 0 ) - raiseError(ObjAssertionFailedException(this,"Assertion failed: ${a.inspect(this)} == ${b.inspect(this)}")) + if (a.compareTo(this, b) != 0) + raiseError( + ObjAssertionFailedException( + this, + "Assertion failed: ${a.inspect(this)} == ${b.inspect(this)}" + ) + ) } // alias used in tests addVoidFn("assertEqual") { val a = requiredArg(0) val b = requiredArg(1) - if( a.compareTo(this, b) != 0 ) - raiseError(ObjAssertionFailedException(this,"Assertion failed: ${a.inspect(this)} == ${b.inspect(this)}")) + if (a.compareTo(this, b) != 0) + raiseError( + ObjAssertionFailedException( + this, + "Assertion failed: ${a.inspect(this)} == ${b.inspect(this)}" + ) + ) } addVoidFn("assertNotEquals") { val a = requiredArg(0) val b = requiredArg(1) - if( a.compareTo(this, b) == 0 ) - raiseError(ObjAssertionFailedException(this,"Assertion failed: ${a.inspect(this)} != ${b.inspect(this)}")) + if (a.compareTo(this, b) == 0) + raiseError( + ObjAssertionFailedException( + this, + "Assertion failed: ${a.inspect(this)} != ${b.inspect(this)}" + ) + ) } addFn("assertThrows") { val code = requireOnlyArg() - val result =try { + val result = try { code.execute(this) null - } - catch( e: ExecutionError ) { + } catch (e: ExecutionError) { e.errorObject - } - catch (_: ScriptError) { + } catch (_: ScriptError) { ObjNull } - result ?: raiseError(ObjAssertionFailedException(this,"Expected exception but nothing was thrown")) + result ?: raiseError(ObjAssertionFailedException(this, "Expected exception but nothing was thrown")) } addFn("dynamic") { @@ -209,7 +222,7 @@ class Script( addFn("require") { val condition = requiredArg(0) - if( !condition.value ) { + if (!condition.value) { val message = args.list.getOrNull(1)?.toString() ?: "requirement not met" raiseIllegalArgument(message) } @@ -217,7 +230,7 @@ class Script( } addFn("check") { val condition = requiredArg(0) - if( !condition.value ) { + if (!condition.value) { val message = args.list.getOrNull(1)?.toString() ?: "check failed" raiseIllegalState(message) } @@ -340,7 +353,7 @@ class Script( doc = "Suspend for the given time. Accepts Duration, Int seconds, or Real seconds." ) { val a = args.firstAndOnly() - when(a) { + when (a) { is ObjInt -> delay(a.value * 1000) is ObjReal -> delay((a.value * 1000).roundToLong()) is ObjDuration -> delay(a.duration) diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/miniast/CompletionEngineLight.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/miniast/CompletionEngineLight.kt index 3d62be8..b9f63ca 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/miniast/CompletionEngineLight.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/miniast/CompletionEngineLight.kt @@ -131,7 +131,7 @@ object CompletionEngineLight { } is MiniClassDecl -> add(CompletionItem(d.name, Kind.Class_)) is MiniValDecl -> add(CompletionItem(d.name, Kind.Value, typeText = typeOf(d.type))) - else -> add(CompletionItem(d.name, Kind.Value)) +// else -> add(CompletionItem(d.name, Kind.Value)) } } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjInstance.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjInstance.kt index 8e6916f..c66a228 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjInstance.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjInstance.kt @@ -197,9 +197,20 @@ class ObjInstance(override val objClass: ObjClass) : Obj() { !it.key.contains("::") && it.value.visibility.isPublic && it.value.type.serializable } - override fun toString(): String { - val fields = publicFields.map { "${it.key}=${it.value.value}" }.joinToString(",") - return "${objClass.className}($fields)" + override suspend fun toString(scope: Scope, calledFromLyng: Boolean): ObjString { + return ObjString(buildString { + append("${objClass.className}(") + var first = true + for ((name, value) in publicFields) { + if (first) first = false else append(",") + append("$name=${value.value.toString(scope)}") + } + append(")") + }) + } + + override suspend fun inspect(scope: Scope): String { + return toString(scope).value } override suspend fun serialize(scope: Scope, encoder: LynonEncoder, lynonType: LynonType?) { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjList.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjList.kt index 55e4a5c..216cbdd 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjList.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjList.kt @@ -198,6 +198,18 @@ class ObjList(val list: MutableList = mutableListOf()) : Obj() { return JsonArray(list.map { it.toJson(scope) }) } + override suspend fun toString(scope: Scope, calledFromLyng: Boolean): ObjString { + return ObjString(buildString { + append("[") + var first = true + for (v in list) { + if (first) first = false else append(",") + append(v.toString(scope).value) + } + append("]") + }) + } + companion object { val type = object : ObjClass("List", ObjArray) { override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjMap.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjMap.kt index b1fa47e..6b2373b 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjMap.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjMap.kt @@ -52,8 +52,8 @@ class ObjMapEntry(val key: Obj, val value: Obj) : Obj() { else -> scope.raiseIndexOutOfBounds() } - override fun toString(): String { - return "$key=>$value" + override suspend fun toString(scope: Scope, calledFromLyng: Boolean): ObjString { + return ObjString("(${key.toString(scope).value} => ${value.toString(scope).value})") } override val objClass = type diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjRef.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjRef.kt index 8bdbf83..f28852f 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjRef.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjRef.kt @@ -1625,7 +1625,7 @@ class ListLiteralRef(private val entries: List) : ObjRef { when (elements) { is ObjList -> { // Grow underlying array once when possible - if (list is ArrayList) list.ensureCapacity(list.size + elements.list.size) + list.ensureCapacity(list.size + elements.list.size) list.addAll(elements.list) } else -> scope.raiseError("Spread element must be list") diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonDecoder.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonDecoder.kt index 9413986..6e230d1 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonDecoder.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonDecoder.kt @@ -82,7 +82,11 @@ open class LynonDecoder(val bin: BitInput, val settings: LynonSettings = LynonSe if (it !is ObjClass) scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}") it - } ?: scope.raiseSymbolNotFound("can't deserialize: not found type $className") + } ?: scope.also { + println("Class not found: $className") + println("::: ${runCatching { scope.eval("Vault")}.getOrNull() }") + println("::2 [${className}]: ${scope.get(className.value)}") + }.raiseSymbolNotFound("can't deserialize: not found type $className") } suspend fun decodeAnyList(scope: Scope, fixedSize: Int? = null): MutableList {