fix #15, default toString for a class

+default comparison for a class
!give up struct in favor of class (simpler)
This commit is contained in:
Sergey Chernov 2025-06-10 18:50:52 +04:00
parent 2a93e6f7da
commit 652e1d3af4
4 changed files with 67 additions and 5 deletions

View File

@ -141,7 +141,24 @@ set at construction but not available outside the class:
void
>>> void
## Default class methods
In many cases it is necessary to implement custom comparison and `toString`, still
each class is provided with default implementations:
- default toString outputs class name and its _public_ fields.
- default comparison compares compares all public fields in order of appearance.
For example, for our class Point:
class Point(x,y)
assert( Point(1,2) == Point(1,2) )
assert( Point(1,2) !== Point(1,2) )
assert( Point(1,2) != Point(1,3) )
assert( Point(1,2) < Point(2,2) )
assert( Point(1,2) < Point(1,3) )
Point(1,1+1)
>>> Point(1, 2)
# Theory

View File

@ -1,7 +1,7 @@
# Declaring arguments in Lyng
It is a common thing that occurs in many places in Lyng, function declarations,
lambdas, struct and class declarations.
lambdas and class declarations.
## Regular

View File

@ -26,4 +26,23 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
if( name in publicFields ) return instanceContext[name]!!.value.invoke(context, this, args)
return super.invokeInstanceMethod(context, name, args)
}
override fun toString(): String {
val fields = publicFields.map {
instanceContext[it]?.value?.toString() ?: "??"
}.joinToString(", ")
return "${objClass.className}($fields)"
}
override suspend fun compareTo(context: Context, other: Obj): Int {
if( other !is ObjInstance ) return -1
if( other.objClass != objClass ) return -1
for( f in publicFields ) {
val a = instanceContext[f]!!.value
val b = other.instanceContext[f]!!.value
val d = a.compareTo(context, b)
if (d != 0) return d
}
return 0
}
}

View File

@ -1386,7 +1386,7 @@ class ScriptTest {
fun testSimpleStruct() = runTest {
val c = Context()
c.eval("""
struct Point(x,y)
class Point(x,y)
assert( Point::class is Class )
val p = Point(2,3)
assert(p is Point)
@ -1405,7 +1405,7 @@ class ScriptTest {
fun testNonAssignalbeFieldInStruct() = runTest {
val c = Context()
c.eval("""
struct Point(x,y)
class Point(x,y)
val p = Point("2",3)
assert(p is Point)
assert( p.x == "2" )
@ -1420,7 +1420,7 @@ class ScriptTest {
fun testStructBodyVal() = runTest {
val c = Context()
c.eval("""
struct Point(x,y) {
class Point(x,y) {
val length = sqrt(x*x+y*y)
var foo = "zero"
}
@ -1440,7 +1440,7 @@ class ScriptTest {
fun testStructBodyFun() = runTest {
val c = Context()
c.eval("""
struct Point(x,y) {
class Point(x,y) {
fun length() {
sqrt(x*x+y*y)
}
@ -1487,4 +1487,30 @@ class ScriptTest {
assertEquals( 1, cond { 1 } )
""".trimIndent())
}
@Test
fun testClasstoString() = runTest {
eval("""
class Point {
var x
var y
}
val p = Point()
p.x = 1
p.y = 2
println(p)
""".trimIndent())
}
@Test
fun testClassDefaultCompare() = runTest {
eval("""
class Point(x,y)
assert( Point(1,2) == Point(1,2) )
assert( Point(1,2) !== Point(1,2) )
assert( Point(1,2) != Point(1,3) )
assert( Point(1,2) < Point(2,2) )
assert( Point(1,2) < Point(1,3) )
""".trimIndent())
}
}