fix #94 overridden toString() now is called correctly in known cases, default implementation is still generated for ObjInstances and some other classes
This commit is contained in:
parent
b7838b45ec
commit
3acd56f55a
@ -142,15 +142,19 @@ open class Obj {
|
|||||||
* @param calledFromLyng true if called from Lyng's `toString`. Normally this parameter should be ignored,
|
* @param calledFromLyng true if called from Lyng's `toString`. Normally this parameter should be ignored,
|
||||||
* but it is used to avoid endless recursion in [Obj.toString] base implementation
|
* but it is used to avoid endless recursion in [Obj.toString] base implementation
|
||||||
*/
|
*/
|
||||||
open suspend fun toString(scope: Scope,calledFromLyng: Boolean=false): ObjString {
|
open suspend fun toString(scope: Scope, calledFromLyng: Boolean = false): ObjString {
|
||||||
return if (this is ObjString) this
|
if (this is ObjString) return this
|
||||||
else if( !calledFromLyng ) {
|
return if (!calledFromLyng) {
|
||||||
invokeInstanceMethod(scope, "toString") {
|
invokeInstanceMethod(scope, "toString", Arguments.EMPTY) {
|
||||||
ObjString(this.toString())
|
defaultToString(scope)
|
||||||
} as ObjString
|
} as ObjString
|
||||||
} else { ObjString(this.toString()) }
|
} else {
|
||||||
|
defaultToString(scope)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open suspend fun defaultToString(scope: Scope): ObjString = ObjString(this.toString())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class of the object: definition of member functions (top-level), etc.
|
* Class of the object: definition of member functions (top-level), etc.
|
||||||
* Note that using lazy allows to avoid endless recursion here
|
* Note that using lazy allows to avoid endless recursion here
|
||||||
|
|||||||
@ -89,7 +89,7 @@ open class ObjException(
|
|||||||
|
|
||||||
override val objClass: ObjClass = exceptionClass
|
override val objClass: ObjClass = exceptionClass
|
||||||
|
|
||||||
override suspend fun toString(scope: Scope, calledFromLyng: Boolean): ObjString {
|
override suspend fun defaultToString(scope: Scope): ObjString {
|
||||||
val at = getStackTrace().list.firstOrNull()?.toString(scope)
|
val at = getStackTrace().list.firstOrNull()?.toString(scope)
|
||||||
?: ObjString("(unknown)")
|
?: ObjString("(unknown)")
|
||||||
return ObjString("${objClass.className}: $message at $at")
|
return ObjString("${objClass.className}: $message at $at")
|
||||||
|
|||||||
@ -187,16 +187,16 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
|
|||||||
!it.key.contains("::") && it.value.visibility.isPublic && it.value.type.serializable
|
!it.key.contains("::") && it.value.visibility.isPublic && it.value.type.serializable
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun toString(scope: Scope, calledFromLyng: Boolean): ObjString {
|
override suspend fun defaultToString(scope: Scope): ObjString {
|
||||||
return ObjString(buildString {
|
return ObjString(buildString {
|
||||||
append("${objClass.className}(")
|
append("${objClass.className}(")
|
||||||
var first = true
|
var first = true
|
||||||
for ((name, value) in publicFields) {
|
for ((name, value) in publicFields) {
|
||||||
if (first) first = false else append(",")
|
if (first) first = false else append(",")
|
||||||
append("$name=${value.value.toString(scope)}")
|
append("$name=${value.value.toString(scope)}")
|
||||||
}
|
}
|
||||||
append(")")
|
append(")")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun inspect(scope: Scope): String {
|
override suspend fun inspect(scope: Scope): String {
|
||||||
|
|||||||
@ -43,7 +43,7 @@ class ObjInstanceClass(val name: String, vararg parents: ObjClass) : ObjClass(na
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
addFn("toString", true) {
|
addFn("toString", true) {
|
||||||
ObjString(thisObj.toString())
|
thisObj.toString(this, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -198,7 +198,7 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
|
|||||||
return JsonArray(list.map { it.toJson(scope) })
|
return JsonArray(list.map { it.toJson(scope) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun toString(scope: Scope, calledFromLyng: Boolean): ObjString {
|
override suspend fun defaultToString(scope: Scope): ObjString {
|
||||||
return ObjString(buildString {
|
return ObjString(buildString {
|
||||||
append("[")
|
append("[")
|
||||||
var first = true
|
var first = true
|
||||||
|
|||||||
@ -52,7 +52,7 @@ class ObjMapEntry(val key: Obj, val value: Obj) : Obj() {
|
|||||||
else -> scope.raiseIndexOutOfBounds()
|
else -> scope.raiseIndexOutOfBounds()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun toString(scope: Scope, calledFromLyng: Boolean): ObjString {
|
override suspend fun defaultToString(scope: Scope): ObjString {
|
||||||
return ObjString("(${key.toString(scope).value} => ${value.toString(scope).value})")
|
return ObjString("(${key.toString(scope).value} => ${value.toString(scope).value})")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ class ObjMap(val map: MutableMap<Obj, Obj> = mutableMapOf()) : Obj() {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun toString(scope: Scope, calledFromLyng: Boolean): ObjString {
|
override suspend fun defaultToString(scope: Scope): ObjString {
|
||||||
val reusult = buildString {
|
val reusult = buildString {
|
||||||
append("Map(")
|
append("Map(")
|
||||||
var first = true
|
var first = true
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob
|
|||||||
|
|
||||||
override val objClass: ObjClass = type
|
override val objClass: ObjClass = type
|
||||||
|
|
||||||
override suspend fun toString(scope: Scope,calledFromLyng: Boolean): ObjString {
|
override suspend fun defaultToString(scope: Scope): ObjString {
|
||||||
val result = StringBuilder()
|
val result = StringBuilder()
|
||||||
result.append("${start?.inspect(scope) ?: '∞'} ..")
|
result.append("${start?.inspect(scope) ?: '∞'} ..")
|
||||||
if (!isEndInclusive) result.append('<')
|
if (!isEndInclusive) result.append('<')
|
||||||
|
|||||||
@ -103,7 +103,7 @@ class ObjRegexMatch(val match: MatchResult) : Obj() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun toString(scope: Scope,calledFromLyng: Boolean): ObjString {
|
override suspend fun defaultToString(scope: Scope): ObjString {
|
||||||
return ObjString("RegexMath(${objRange.toString(scope)},${objGroups.toString(scope)})")
|
return ObjString("RegexMath(${objRange.toString(scope)},${objGroups.toString(scope)})")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4311,6 +4311,28 @@ class ScriptTest {
|
|||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCustomToStringBug() = runTest {
|
||||||
|
eval("""
|
||||||
|
class A(x,y)
|
||||||
|
class B(x,y) {
|
||||||
|
fun toString() {
|
||||||
|
"B(%d,%d)"(x,y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("B(1,2)", B(1,2).toString())
|
||||||
|
assertEquals("A(x=1,y=2)", A(1,2).toString())
|
||||||
|
|
||||||
|
// now tricky part: this _should_ cakk custom toString()
|
||||||
|
assertEquals(":B(1,2)", ":" + B(1,2).toString())
|
||||||
|
// and this must be exactly same:
|
||||||
|
assertEquals(":B(1,2)", ":" + B(1,2))
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
// fun testSplatAssignemnt() = runTest {
|
// fun testSplatAssignemnt() = runTest {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user