From 1652eacfe3aaba3f7e030e81216677d81942c98f Mon Sep 17 00:00:00 2001 From: Fedor Isakov Date: Sun, 22 May 2016 17:08:01 +0200 Subject: [PATCH] Integrating TermTrie in the occurrence store. --- .../mps/logic/reactor/core/OccurrenceStore.kt | 79 +++++++++++++------ reactor/Test/test/TestMatcher.kt | 3 + reactor/Test/test/TestOccurrenceStore.kt | 15 +++- 3 files changed, 73 insertions(+), 24 deletions(-) diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/OccurrenceStore.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/OccurrenceStore.kt index 35729341..af5165f4 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/OccurrenceStore.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/OccurrenceStore.kt @@ -11,6 +11,7 @@ import jetbrains.mps.logic.reactor.program.ConstraintSymbol import jetbrains.mps.logic.reactor.util.cons import jetbrains.mps.logic.reactor.util.emptyConsList import jetbrains.mps.logic.reactor.util.remove +import jetbrains.mps.unification.Term import java.util.* /** @@ -36,6 +37,8 @@ interface OccurrenceIndex { fun forLogical(logical: Logical<*>): Iterable + fun forTerm(term: Term): Iterable + fun forValue(value: Any): Iterable } @@ -48,6 +51,8 @@ class OccurrenceStore : LogicalObserver, OccurrenceIndex { lateinit var logical2occurrences: PersMap, ConsList> + lateinit var term2occurrences: TermTrie + lateinit var value2occurrences: PersMap> constructor(copyFrom: OccurrenceStore, proxy: LogicalObserverProxy) @@ -55,6 +60,7 @@ class OccurrenceStore : LogicalObserver, OccurrenceIndex { this.proxy = proxy this.symbol2occurrences = copyFrom.symbol2occurrences this.logical2occurrences = copyFrom.logical2occurrences + this.term2occurrences = copyFrom.term2occurrences this.value2occurrences = copyFrom.value2occurrences } @@ -62,17 +68,31 @@ class OccurrenceStore : LogicalObserver, OccurrenceIndex { this.proxy = proxy this.symbol2occurrences = Maps.of() this.logical2occurrences = Maps.of() + this.term2occurrences = TermTrie() this.value2occurrences = Maps.of() } override fun valueUpdated(logical: Logical<*>) { logical2occurrences[logical.findRoot()]?.let { toMerge -> val value = logical.findRoot().value() - var newList = value2occurrences[value] ?: emptyConsList() - for (occ in toMerge) { - newList = newList.prepend(occ) + when (value) { + is Term -> { + for (occ in toMerge) { + this.term2occurrences = term2occurrences.put(value, occ) + } + } + is Any -> { + var newList = value2occurrences[value] ?: emptyConsList() + for (occ in toMerge) { + newList = newList.prepend(occ) + } + this.value2occurrences = value2occurrences.put(value, newList) + } + else -> { + // never happens + throw NullPointerException() + } } - this.value2occurrences = value2occurrences.put(value, newList) } } @@ -101,14 +121,22 @@ class OccurrenceStore : LogicalObserver, OccurrenceIndex { for (arg in occ.arguments()) { when (arg) { - is Logical<*> -> { - this.logical2occurrences = logical2occurrences.put(arg.findRoot(), - logical2occurrences[arg.findRoot()]?.prepend(occ) ?: cons(occ)) - proxy.addObserver(arg, this) - } - - is Any -> this.value2occurrences = value2occurrences.put(arg, - value2occurrences[arg]?.prepend(occ) ?: cons(occ)) + is Logical<*> -> { + this.logical2occurrences = logical2occurrences.put(arg.findRoot(), + logical2occurrences[arg.findRoot()]?.prepend(occ) ?: cons(occ)) + proxy.addObserver(arg, this) + } + is Term -> { + this.term2occurrences = term2occurrences.put(arg, occ) + } + is Any -> { + this.value2occurrences = value2occurrences.put(arg, + value2occurrences[arg]?.prepend(occ) ?: cons(occ)) + } + else -> { + // never happens + throw NullPointerException() + } } } @@ -125,16 +153,20 @@ class OccurrenceStore : LogicalObserver, OccurrenceIndex { for (arg in occ.arguments()) { when (arg) { - is Logical<*> -> { - logical2occurrences[arg.findRoot()].remove(occ)?.let { newList -> - this.logical2occurrences = logical2occurrences.put(arg.findRoot(), newList) - } - // TODO: remove observer? - } - - is Any -> value2occurrences[arg].remove(occ)?. let { newList -> - this.value2occurrences = value2occurrences.put(arg, newList) - } + is Logical<*> -> { + logical2occurrences[arg.findRoot()].remove(occ)?.let { newList -> + this.logical2occurrences = logical2occurrences.put(arg.findRoot(), newList) + } + // TODO: remove observer? + } + is Term -> { + this.term2occurrences = term2occurrences.remove(arg, occ) + } + is Any -> { + value2occurrences[arg].remove(occ)?. let { newList -> + this.value2occurrences = value2occurrences.put(arg, newList) + } + } } } @@ -157,6 +189,9 @@ class OccurrenceStore : LogicalObserver, OccurrenceIndex { return list.filter { co -> co.isStored() } } + override fun forTerm(term: Term): Iterable { + return term2occurrences.lookupValues(term) + } override fun forValue(value: Any): Iterable { val list = value2occurrences[value] ?: emptyConsList() diff --git a/reactor/Test/test/TestMatcher.kt b/reactor/Test/test/TestMatcher.kt index c356ab91..319d95fb 100644 --- a/reactor/Test/test/TestMatcher.kt +++ b/reactor/Test/test/TestMatcher.kt @@ -4,6 +4,7 @@ import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence import jetbrains.mps.logic.reactor.logical.Logical import jetbrains.mps.logic.reactor.program.Constraint import jetbrains.mps.logic.reactor.program.ConstraintSymbol +import jetbrains.mps.unification.Term import jetbrains.mps.unification.test.MockTermsParser import jetbrains.mps.unification.test.MockTermsParser.parse import org.jetbrains.kotlin.js.parser.parse @@ -26,6 +27,8 @@ class TestMatcher { override fun forLogical(logical: Logical<*>): Iterable = emptyList() + override fun forTerm(term: Term): Iterable = emptyList() + override fun forValue(value: Any): Iterable = emptyList() } diff --git a/reactor/Test/test/TestOccurrenceStore.kt b/reactor/Test/test/TestOccurrenceStore.kt index 2f02ca77..3f728de5 100644 --- a/reactor/Test/test/TestOccurrenceStore.kt +++ b/reactor/Test/test/TestOccurrenceStore.kt @@ -1,6 +1,9 @@ import jetbrains.mps.logic.reactor.core.* import jetbrains.mps.logic.reactor.logical.Logical import jetbrains.mps.logic.reactor.util.emptyConsList +import jetbrains.mps.unification.test.MockTermsParser +import jetbrains.mps.unification.test.MockTermsParser.parse +import org.jetbrains.kotlin.js.parser.parse import org.junit.Test import org.junit.Assert.* @@ -82,9 +85,17 @@ class TestOccurrenceStore { assertEquals(listOf(main), occstore.forValue(value)) } + @Test + fun testTermIndex () { + val occstore = OccurrenceStore(mockProxy) - fun assertEquals(a: Sequence, b: Sequence) { - assertEquals(a.toSet(), b.toSet()) + val foo = occurrence("foo", parse("a{b c}")) + occstore.store(foo) + + // TODO: more tests + assertEquals(listOf(foo), occstore.forTerm(parse("a{b c}"))) + assertEquals(listOf(foo), occstore.forTerm(parse("a{b Y}"))) + assertEquals(listOf(foo), occstore.forTerm(parse("Z"))) } }