Skip to content

Commit e552a5a

Browse files
Consider changes in objects via immutable refs
1 parent da9d0e8 commit e552a5a

File tree

4 files changed

+83
-10
lines changed

4 files changed

+83
-10
lines changed

jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/compiler/util/serializedCompiledScript.kt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,29 @@ data class SerializedVariablesState(
2525
val type: String = "",
2626
val value: String? = null,
2727
val isContainer: Boolean = false,
28-
val ID: String = ""
28+
val stateId: String = ""
2929
) {
3030
// todo: not null
3131
val fieldDescriptor: MutableMap<String, SerializedVariablesState?> = mutableMapOf()
32+
override fun equals(other: Any?): Boolean {
33+
if (this === other) return true
34+
if (javaClass != other?.javaClass) return false
35+
36+
other as SerializedVariablesState
37+
38+
if (type != other.type) return false
39+
if (value != other.value) return false
40+
if (isContainer != other.isContainer) return false
41+
42+
return true
43+
}
44+
45+
override fun hashCode(): Int {
46+
var result = type.hashCode()
47+
result = 31 * result + (value?.hashCode() ?: 0)
48+
result = 31 * result + isContainer.hashCode()
49+
return result
50+
}
3251
}
3352

3453
@Serializable

src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,8 @@ class ReplForJupyterImpl(
441441
notebook.updateVariablesState(internalEvaluator)
442442
// printVars()
443443
// printUsagesInfo(jupyterId, cellVariables[jupyterId - 1])
444-
val serializedData = variablesSerializer.serializeVariables(jupyterId - 1, notebook.variablesState, notebook.unchangedVariables())
444+
val variablesCells: Map<String, Int> = notebook.variablesState.mapValues { internalEvaluator.findVariableCell(it.key) }
445+
val serializedData = variablesSerializer.serializeVariables(jupyterId - 1, notebook.variablesState, variablesCells, notebook.unchangedVariables())
445446

446447
GlobalScope.launch(Dispatchers.Default) {
447448
variablesSerializer.tryValidateCache(jupyterId - 1, notebook.cellVariables)

src/main/kotlin/org/jetbrains/kotlinx/jupyter/serializationUtils.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ class VariablesSerializer(
358358
clearOldData(currentCellId, cellVariables)
359359
}
360360

361-
fun serializeVariables(cellId: Int, variablesState: Map<String, VariableState>, unchangedVariables: Set<String>): Map<String, SerializedVariablesState> {
361+
fun serializeVariables(cellId: Int, variablesState: Map<String, VariableState>, variablesCells: Map<String, Int>, unchangedVariables: Set<String>): Map<String, SerializedVariablesState> {
362362
fun removeNonExistingEntries() {
363363
val toRemoveSet = mutableSetOf<String>()
364364
serializedVariablesCache.forEach { (name, _) ->
@@ -382,17 +382,22 @@ class VariablesSerializer(
382382
val wasRedeclared = !unchangedVariables.contains(it)
383383
if (wasRedeclared) {
384384
removedFromSightVariables.remove(it)
385-
}
386-
(unchangedVariables.contains(it) || serializedVariablesCache[it]?.value != variablesState[it]?.stringValue) &&
385+
} /*
386+
(unchangedVariables.contains(it) || serializedVariablesCache[it]?.value != variablesState[it]?.value?.getOrNull().toString()) &&
387+
!removedFromSightVariables.contains(it)*/
388+
(unchangedVariables.contains(it)) &&
387389
!removedFromSightVariables.contains(it)
388390
}
389391
log.debug("Variables state as is: $variablesState")
390392
log.debug("Serializing variables after filter: $neededEntries")
391-
log.debug("Unchanged variables: $unchangedVariables")
393+
log.debug("Unchanged variables: ${unchangedVariables - neededEntries.keys}")
392394

393395
// remove previous data
394396
computedDescriptorsPerCell[cellId]?.instancesPerState?.clear()
395-
val serializedData = neededEntries.mapValues { serializeVariableState(cellId, it.key, it.value) }
397+
val serializedData = neededEntries.mapValues {
398+
val actualCell = variablesCells[it.key] ?: cellId
399+
serializeVariableState(actualCell, it.key, it.value)
400+
}
396401

397402
serializedVariablesCache.putAll(serializedData)
398403
removeNonExistingEntries()
@@ -730,7 +735,7 @@ class VariablesSerializer(
730735
""
731736
}
732737

733-
val serializedVariablesState = SerializedVariablesState(type, getProperString(value), isContainer, ID = finalID)
738+
val serializedVariablesState = SerializedVariablesState(type, getProperString(value), isContainer, finalID)
734739

735740
return ProcessedSerializedVarsState(serializedVariablesState, membersProperties?.toTypedArray())
736741
}

src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/repl/ReplTests.kt

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ class ReplVarsTest : AbstractSingleReplTest() {
771771

772772
@Test
773773
fun testRecursiveVarsState() {
774-
eval(
774+
val res = eval(
775775
"""
776776
val l = mutableListOf<Any>()
777777
l.add(listOf(l))
@@ -781,7 +781,7 @@ class ReplVarsTest : AbstractSingleReplTest() {
781781
val z = setOf(1, 2, 4)
782782
""".trimIndent(),
783783
jupyterId = 1
784-
)
784+
).metadata
785785
val state = repl.notebook.variablesState
786786
assertTrue(state.contains("l"))
787787
assertTrue(state.contains("m"))
@@ -790,6 +790,54 @@ class ReplVarsTest : AbstractSingleReplTest() {
790790
assertEquals("ArrayList: recursive structure", state["l"]!!.stringValue)
791791
assertTrue(state["m"]!!.stringValue!!.contains(" recursive structure"))
792792
assertEquals("[1, 2, 4]", state["z"]!!.stringValue)
793+
794+
val serializer = repl.variablesSerializer
795+
val descriptor = res.evaluatedVariablesState["l"]!!.fieldDescriptor
796+
val innerList = descriptor["elementData"]!!.fieldDescriptor["data"]
797+
val newData = serializer.doIncrementalSerialization(0, "data", innerList!!)
798+
assertEquals(2, newData.fieldDescriptor.size)
799+
}
800+
801+
@Test
802+
fun testUnchangedVars() {
803+
eval(
804+
"""
805+
var l = 11111
806+
val m = "abc"
807+
""".trimIndent(),
808+
jupyterId = 1
809+
)
810+
var state = repl.notebook.unchangedVariables()
811+
val res = eval(
812+
"""
813+
l += 11111
814+
""".trimIndent(),
815+
jupyterId = 2
816+
).metadata.evaluatedVariablesState
817+
state = repl.notebook.unchangedVariables()
818+
assertEquals(1, state.size)
819+
assertTrue(state.contains("m"))
820+
}
821+
822+
@Test
823+
fun testMutableList() {
824+
eval(
825+
"""
826+
val l = mutableListOf(1, 2, 3, 4)
827+
""".trimIndent(),
828+
jupyterId = 1
829+
)
830+
val serializer = repl.variablesSerializer
831+
val res = eval(
832+
"""
833+
l.add(5)
834+
""".trimIndent(),
835+
jupyterId = 2
836+
).metadata.evaluatedVariablesState
837+
val innerList = res["l"]!!.fieldDescriptor["elementData"]!!.fieldDescriptor["data"]
838+
val newData = serializer.doIncrementalSerialization(0, "data", innerList!!)
839+
assertTrue(newData.isContainer)
840+
assertTrue(newData.fieldDescriptor.size > 4)
793841
}
794842

795843
@Test

0 commit comments

Comments
 (0)