Integrating TermTrie in the occurrence store.

This commit is contained in:
Fedor Isakov 2016-05-22 17:08:01 +02:00
parent e9969b08b7
commit 1652eacfe3
3 changed files with 73 additions and 24 deletions

View File

@ -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<ConstraintOccurrence>
fun forTerm(term: Term): Iterable<ConstraintOccurrence>
fun forValue(value: Any): Iterable<ConstraintOccurrence>
}
@ -48,6 +51,8 @@ class OccurrenceStore : LogicalObserver, OccurrenceIndex {
lateinit var logical2occurrences: PersMap<Logical<*>, ConsList<ConstraintOccurrence>>
lateinit var term2occurrences: TermTrie<ConstraintOccurrence>
lateinit var value2occurrences: PersMap<Any, ConsList<ConstraintOccurrence>>
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<ConstraintOccurrence> {
return term2occurrences.lookupValues(term)
}
override fun forValue(value: Any): Iterable<ConstraintOccurrence> {
val list = value2occurrences[value] ?: emptyConsList()

View File

@ -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<ConstraintOccurrence> = emptyList()
override fun forTerm(term: Term): Iterable<ConstraintOccurrence> = emptyList()
override fun forValue(value: Any): Iterable<ConstraintOccurrence> = emptyList()
}

View File

@ -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 <T> assertEquals(a: Sequence<T>, b: Sequence<T>) {
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")))
}
}