Skip to content

Commit

Permalink
fix lists serialization and factorise ObjsectsUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
gciatto committed Jul 1, 2020
1 parent 2e92aa7 commit 8328253
Show file tree
Hide file tree
Showing 15 changed files with 135 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package it.unibo.tuprolog.serialize

expect object ObjectsUtils {
fun parseAsObject(string: String, mimeType: MimeType): Any

fun deeplyEqual(obj1: Any?, obj2: Any?): Boolean
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,36 @@ import kotlin.test.Test
import kotlin.test.assertEquals

class TestTermDeserializer {
@Test
fun testTailedListSerializationInJSON() {
val deserializer: TermDeserializer = TermDeserializer.of(MimeType.Json)
assertEquals(MimeType.Json, deserializer.mimeType)

deserializer.assertTermDeserializationWorks("{\"fun\":\"member\",\"args\":[{\"var\":\"H\"},{\"list\":[{\"var\":\"H\"}],\"tail\":{\"var\":\"_\"}}]}") {
structOf("member", varOf("H"), consOf(varOf("H"), anonymous()))
}
}

@Test
fun testTailedListSerializationInYAML() {
val deserializer: TermDeserializer = TermDeserializer.of(MimeType.Yaml)
assertEquals(MimeType.Yaml, deserializer.mimeType)

deserializer.assertTermDeserializationWorks(
"""
|fun: member
|args:
| - var: H
| - list:
| - var: H
| tail:
| var: _
""".trimMargin()
) {
structOf("member", varOf("H"), consOf(varOf("H"), anonymous()))
}
}

@Test
fun testAtomDeserializationInJSON() {
val deserializer: TermDeserializer = TermDeserializer.of(MimeType.Json)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ class TestTermSerializer {
}
}

@Test
fun testTailedListSerializationInJSON() {
val serializer: TermSerializer = TermSerializer.of(MimeType.Json)
assertEquals(MimeType.Json, serializer.mimeType)

serializer.assertTermSerializationWorks("{\"fun\":\"member\",\"args\":[{\"var\":\"H\"},{\"list\":[{\"var\":\"H\"}],\"tail\":{\"var\":\"_\"}}]}") {
structOf("member", varOf("H"), consOf(varOf("H"), anonymous()))
}
}

@Test
fun testListSerializationInYAML() {
val serializer: TermSerializer = TermSerializer.of(MimeType.Yaml)
Expand All @@ -100,6 +110,26 @@ class TestTermSerializer {
}
}

@Test
fun testTailedListSerializationInYAML() {
val serializer: TermSerializer = TermSerializer.of(MimeType.Yaml)
assertEquals(MimeType.Yaml, serializer.mimeType)

serializer.assertTermSerializationWorks(
"""
|fun: member
|args:
| - var: H
| - list:
| - var: H
| tail:
| var: _
""".trimMargin()
) {
structOf("member", varOf("H"), consOf(varOf("H"), anonymous()))
}
}

@Test
fun testSetSerializationInJSON() {
val serializer: TermSerializer = TermSerializer.of(MimeType.Json)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package it.unibo.tuprolog.serialize

import it.unibo.tuprolog.core.*
import it.unibo.tuprolog.serialize.ObjectsUtils.deeplyEqual
import it.unibo.tuprolog.serialize.ObjectsUtils.parseAsObject

/**
* Utility assertion method aimed at checking if a serializer correctly works
Expand Down Expand Up @@ -46,7 +48,7 @@ fun <T : Term> Deserializer<T>.assertDeserializationWorks(expected: T, actual: S
|got:
| $deserialized
|
""".trimMargin()) { termsRepresentationsAreEqual(expected, deserialized) }
""".trimMargin()) { expected.equals(deserialized, false) }
}

/**
Expand All @@ -65,22 +67,4 @@ fun <T : Term> Deserializer<T>.assertDeserializationWorks(expected: T, actual: S
*/
fun Deserializer<Term>.assertTermDeserializationWorks(actual: String, expectedGenerator: Scope.() -> Term) {
assertDeserializationWorks(Scope.empty().expectedGenerator(), actual)
}

private fun termsRepresentationsAreEqual(t1: Term, t2: Term): Boolean {
return when {
t1 is Var && t2 is Var -> t1.name == t2.name
t1 is Atom && t2 is Atom -> t1.value == t2.value
t1 is Integer && t2 is Integer -> t1.value.compareTo(t2.value) == 0
t1 is Real && t2 is Real -> t1.value.compareTo(t2.value) == 0
t1 is Struct && t2 is Struct -> {
t1.arity == t2.arity && t1.functor == t2.functor && (0 until t1.arity).all {
termsRepresentationsAreEqual(
t1[it],
t2[it]
)
}
}
else -> false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ internal class JsTermDeobjectifier : TermDeobjectifier {

private fun deobjectifyList(value: dynamic): Term {
val items = value["list"] as? Array<dynamic> ?: throw DeobjectificationException(value)
val last = value["last"]
val last = value["tail"]
return scope.listFrom(
items.map {
deobjectify(it ?: throw DeobjectificationException(value))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,19 @@ internal class JsTermObjectifier : TermObjectifier {
override fun visitEmptySet(term: EmptySet): Any =
visitSet(term)

override fun visitList(term: List): Any =
jsObject("list" to term.toList().map { it.accept(this) }) {
if (!term.isWellFormed) {
this["tail"] = term.unfoldedSequence.last().accept(this@JsTermObjectifier)
}
override fun visitList(term: List): Any {
val listed = term.toList()
return if (term.isWellFormed) {
jsObject(
"list" to listed.map { it.accept(this) }.toTypedArray()
)
} else {
jsObject(
"list" to listed.subList(0, listed.lastIndex).map { it.accept(this) }.toTypedArray(),
"tail" to listed[listed.lastIndex].accept(this)
)
}
}

override fun visitCons(term: Cons): Any =
visitList(term)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package it.unibo.tuprolog.serialize

actual object ObjectsUtils {

actual fun parseAsObject(string: String, mimeType: MimeType): Any {
return when (mimeType) {
is MimeType.Xml -> throw NotImplementedError()
is MimeType.Yaml -> YAML.parse(string)
is MimeType.Json -> JSON.parse(string)
} as Any
}

actual fun deeplyEqual(obj1: Any?, obj2: Any?): Boolean {
return JSON.stringify(obj1) == JSON.stringify(obj2)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ internal class JvmTermDeobjectifier : TermDeobjectifier {

private fun deobjectifyList(value: Map<*, *>): Term {
val items = value["list"] as? List<*> ?: throw DeobjectificationException(value)
val last = value["last"]
val last = value["tail"]
return scope.listFrom(
items.map {
deobjectify(it ?: throw DeobjectificationException(value))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,19 @@ internal class JvmTermObjectifier : TermObjectifier {
override fun visitEmptySet(term: EmptySet): Map<String, Any> =
visitSet(term)

override fun visitList(term: List): Map<String, Any> =
mapOf(
"list" to term.toList().map { it.accept(this) }
) + if (term.isWellFormed) {
emptyMap()
override fun visitList(term: List): Map<String, Any> {
val listed = term.toList()
return if (term.isWellFormed) {
mapOf(
"list" to listed.map { it.accept(this) }
)
} else {
mapOf(
"tail" to term.unfoldedSequence.last().accept(this)
"list" to listed.subList(0, listed.lastIndex).map { it.accept(this) },
"tail" to listed[listed.lastIndex].accept(this)
)
}
}

override fun visitCons(term: Cons): Map<String, Any> =
visitList(term)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package it.unibo.tuprolog.serialize

actual object ObjectsUtils {
actual fun parseAsObject(string: String, mimeType: MimeType): Any {
return mimeType.objectMapper.readValue(string, java.lang.Object::class.java)
}

actual fun deeplyEqual(obj1: Any?, obj2: Any?): Boolean {
return when {
obj1 is Number && obj2 is Number -> obj1.toString() == obj2.toString()
obj1 is List<*> && obj2 is List<*> -> obj1.asSequence().zip(obj2.asSequence()).all {
deeplyEqual(it.first, it.second)
}
obj1 is Map<*,*> && obj2 is Map<*,*> -> {
if (obj1.keys != obj2.keys) {
false
} else {
obj1.keys.all { deeplyEqual(obj1[it], obj2[it]) }
}
}
else -> obj1 == obj2
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import it.unibo.tuprolog.theory.Theory
internal class JsTheoryDeobjectifier : TheoryDeobjectifier {
override fun deobjectify(`object`: Any): Theory {
return Theory.of(
JsTermDeobjectifier().deobjectifyMany(`object`)
TermDeobjectifier.default.deobjectifyMany(`object`)
.asSequence()
.map { it as Clause }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package it.unibo.tuprolog.serialize
import it.unibo.tuprolog.theory.Theory

internal class JsTheoryObjectifier : TheoryObjectifier {
private val objectifier = JsTermObjectifier()
private val objectifier = TermObjectifier.default

override fun objectify(value: Theory): Any {
return value.map { objectifier.objectify(it) }.toTypedArray()
Expand Down

0 comments on commit 8328253

Please sign in to comment.