Replace tag() method in rule with uniqueTag() returning Object. This
allows for further memory optimization.
This commit is contained in:
parent
0697437ec7
commit
0e02bab768
|
|
@ -27,12 +27,12 @@ import com.github.andrewoma.dexx.collection.Map as PersMap
|
|||
*/
|
||||
class Dispatcher (val ruleIndex: RuleIndex) {
|
||||
|
||||
private val ruletag2matcher = HashMap<String, RuleMatcher>()
|
||||
private val ruletag2matcher = HashMap<Any, RuleMatcher>()
|
||||
|
||||
init {
|
||||
ruleIndex.forEach { rule ->
|
||||
val matcher = createRuleMatcher(ruleIndex, rule.tag())
|
||||
ruletag2matcher.put(rule.tag(), matcher);
|
||||
val matcher = createRuleMatcher(ruleIndex, rule.uniqueTag())
|
||||
ruletag2matcher.put(rule.uniqueTag(), matcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ class Dispatcher (val ruleIndex: RuleIndex) {
|
|||
|
||||
inner class DispatchingFront {
|
||||
|
||||
private var ruletag2probe: PersMap<String, RuleMatchingProbe>
|
||||
private var ruletag2probe: PersMap<Any, RuleMatchingProbe>
|
||||
|
||||
private val allMatches = arrayListOf<RuleMatchImpl>()
|
||||
|
||||
|
|
@ -57,15 +57,15 @@ class Dispatcher (val ruleIndex: RuleIndex) {
|
|||
private constructor(pred: DispatchingFront, matching: Iterable<RuleMatchingProbe>) {
|
||||
this.ruletag2probe = pred.ruletag2probe
|
||||
matching.forEach { probe ->
|
||||
this.ruletag2probe = ruletag2probe.put(probe.rule().tag(), probe)
|
||||
this.ruletag2probe = ruletag2probe.put(probe.rule().uniqueTag(), probe)
|
||||
allMatches.addAll(probe.matches() as Collection<RuleMatchImpl>)
|
||||
}
|
||||
}
|
||||
|
||||
private constructor(pred: DispatchingFront, consumedMatch: RuleMatchEx) {
|
||||
this.ruletag2probe = pred.ruletag2probe
|
||||
pred.ruletag2probe[consumedMatch.rule().tag()]?.let {
|
||||
this.ruletag2probe = ruletag2probe.put(consumedMatch.rule().tag(), it.consume(consumedMatch))
|
||||
pred.ruletag2probe[consumedMatch.rule().uniqueTag()]?.let {
|
||||
this.ruletag2probe = ruletag2probe.put(consumedMatch.rule().uniqueTag(), it.consume(consumedMatch))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,8 +80,8 @@ class Dispatcher (val ruleIndex: RuleIndex) {
|
|||
*/
|
||||
fun expand(activated: Occurrence) = DispatchingFront(this,
|
||||
ruleIndex.forOccurrenceWithMask(activated).mapNotNull { (rule, mask) ->
|
||||
ruletag2probe[rule.tag()]?.expand(activated, mask)
|
||||
ruletag2probe[rule.tag()]?.expand(activated, mask)
|
||||
ruletag2probe[rule.uniqueTag()]?.expand(activated, mask)
|
||||
ruletag2probe[rule.uniqueTag()]?.expand(activated, mask)
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
@ -90,7 +90,7 @@ class Dispatcher (val ruleIndex: RuleIndex) {
|
|||
*/
|
||||
fun contract(discarded: Occurrence) = DispatchingFront(this,
|
||||
ruleIndex.forOccurrence(discarded).mapNotNull { rule ->
|
||||
ruletag2probe[rule.tag()]
|
||||
ruletag2probe[rule.uniqueTag()]
|
||||
}.map { probe ->
|
||||
probe.contract(discarded)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -29,14 +29,13 @@ import kotlin.collections.HashMap
|
|||
/**
|
||||
* A container for [Rule] instances with the ability to look up by [ConstraintOccurrence].
|
||||
*
|
||||
* FIXME handler to be renamed to RulesList
|
||||
* @author Fedor Isakov
|
||||
*/
|
||||
class RuleIndex(handlers: Iterable<RulesList>) : Iterable<Rule>, RuleLookup {
|
||||
|
||||
private val symbol2index = HashMap<ConstraintSymbol, ArgumentRuleIndex>()
|
||||
|
||||
private val tag2rule = LinkedHashMap<String, Rule>()
|
||||
private val tag2rule = LinkedHashMap<Any, Rule>()
|
||||
|
||||
// rule's index is rule's position in this list
|
||||
private val rulesList = ArrayList<Rule>()
|
||||
|
|
@ -55,7 +54,7 @@ class RuleIndex(handlers: Iterable<RulesList>) : Iterable<Rule>, RuleLookup {
|
|||
buildIndex(handlers)
|
||||
}
|
||||
|
||||
override fun lookupRuleByTag(tag: String): Rule? = tag2rule[tag]
|
||||
override fun lookupRuleByTag(tag: Any): Rule? = tag2rule[tag]
|
||||
|
||||
/**
|
||||
* Returns instances of [Rule] that can potentially match the specified [ConstraintOccurrence].
|
||||
|
|
@ -88,8 +87,8 @@ class RuleIndex(handlers: Iterable<RulesList>) : Iterable<Rule>, RuleLookup {
|
|||
var ruleBit = 0
|
||||
for (h in handlers) {
|
||||
for (rule in h.rules()) {
|
||||
if (tag2rule.containsKey(rule.tag())) throw IllegalStateException("duplicate rule tag ${rule.tag()}")
|
||||
tag2rule[rule.tag()] = rule
|
||||
if (tag2rule.containsKey(rule.uniqueTag())) throw IllegalStateException("duplicate rule tag ${rule.uniqueTag()}")
|
||||
tag2rule[rule.uniqueTag()] = rule
|
||||
rulesList.add(rule)
|
||||
|
||||
val head = rule.headKept() + rule.headReplaced()
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ import jetbrains.mps.logic.reactor.program.Rule
|
|||
|
||||
interface RuleLookup {
|
||||
|
||||
fun lookupRuleByTag(tag: String): Rule?
|
||||
fun lookupRuleByTag(tag: Any): Rule?
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,5 +30,5 @@ interface RuleMatcher {
|
|||
|
||||
}
|
||||
|
||||
fun createRuleMatcher(lookup: RuleLookup, tag: String): RuleMatcher = RuleMatcherImpl(lookup, tag)
|
||||
fun createRuleMatcher(lookup: RuleLookup, tag: Any): RuleMatcher = RuleMatcherImpl(lookup, tag)
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import com.github.andrewoma.dexx.collection.Vector as PersVector
|
|||
* @author Fedor Isakov
|
||||
*/
|
||||
internal class RuleMatcherImpl(private val ruleLookup: RuleLookup,
|
||||
private val tag: String) : RuleMatcher
|
||||
private val tag: Any) : RuleMatcher
|
||||
{
|
||||
|
||||
val head = lookupRule().run { ArrayList(headKept() + headReplaced()) }
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public abstract class Rule {
|
|||
/**
|
||||
* A tag uniquely identifies the rule.
|
||||
*/
|
||||
public abstract String tag();
|
||||
public abstract Object uniqueTag();
|
||||
|
||||
/**
|
||||
* An origin serves as justification for all constraints affected by this rule.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class ProgramBuilder(val registry: MockConstraintRegistry) {
|
|||
|
||||
class HandlerBuilder(val name: String) {
|
||||
|
||||
val rules = LinkedHashMap<String, Rule>()
|
||||
val rules = LinkedHashMap<Any, Rule>()
|
||||
|
||||
constructor(name: String, rulesList: RulesList) : this(name) {
|
||||
for (r in rulesList.rules()) {
|
||||
|
|
@ -35,7 +35,7 @@ class HandlerBuilder(val name: String) {
|
|||
}
|
||||
|
||||
fun appendRule(rule: Rule) {
|
||||
rules[rule.tag()] = rule
|
||||
rules[rule.uniqueTag()] = rule
|
||||
}
|
||||
|
||||
fun toHandler(): RulesList = MockHandler(name, rules.values.toList())
|
||||
|
|
@ -80,8 +80,8 @@ class MockRule(
|
|||
val body: Collection<Collection<AndItem>>) : Rule() {
|
||||
|
||||
override fun kind(): Kind = TODO()
|
||||
|
||||
override fun tag(): String = tag
|
||||
|
||||
override fun uniqueTag() = tag
|
||||
|
||||
override fun headKept(): Iterable<Constraint> = kept
|
||||
|
||||
|
|
|
|||
|
|
@ -15,22 +15,22 @@ import kotlin.collections.HashMap
|
|||
|
||||
class Builder(var rulesLists: List<RulesList>) : RuleLookup {
|
||||
|
||||
val tag2rule = HashMap<String, Rule>()
|
||||
val tag2rule = HashMap<Any, Rule>()
|
||||
|
||||
val programBuilder = ProgramBuilder(MockConstraintRegistry())
|
||||
|
||||
init {
|
||||
rulesLists
|
||||
.flatMap { it.rules() }
|
||||
.forEach { r -> tag2rule[r.tag()] = r }
|
||||
.forEach { r -> tag2rule[r.uniqueTag()] = r }
|
||||
}
|
||||
|
||||
val rules: List<Rule>
|
||||
get() = tag2rule.values.toList()
|
||||
|
||||
override fun lookupRuleByTag(tag: String): Rule? = tag2rule[tag]
|
||||
override fun lookupRuleByTag(tag: Any): Rule? = tag2rule[tag]
|
||||
|
||||
fun ruleMatcher(): RuleMatcher = createRuleMatcher(this, rules.first().tag())
|
||||
fun ruleMatcher(): RuleMatcher = createRuleMatcher(this, rules.first().uniqueTag())
|
||||
|
||||
fun program(name: String): Program = programBuilder.program(name, rulesLists)
|
||||
|
||||
|
|
|
|||
|
|
@ -509,8 +509,8 @@ class TestController {
|
|||
constraint("foo", Z, "a{c}")), body(constraint("done")))
|
||||
|
||||
).controller().evaluate(occurrence("main")).run {
|
||||
assertEquals(setOf(ConstraintSymbol("done", 0)), constraintSymbols())
|
||||
assertEquals(1, occurrences(ConstraintSymbol.symbol("done", 0)).count())
|
||||
constraintSymbols() shouldBe setOf(sym0("done"))
|
||||
occurrences(sym0("done")).count() shouldBe 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -820,10 +820,10 @@ class TestController {
|
|||
|
||||
@Test(expected = EvaluationFailureException::class)
|
||||
fun failureHandler() {
|
||||
val failures = ArrayList<Pair<EvaluationFailure, String>>()
|
||||
val failures = ArrayList<Pair<EvaluationFailure, Any>>()
|
||||
val failureHandler = { rule: Rule, feedback: EvaluationFeedback ->
|
||||
if (feedback is EvaluationFailure) {
|
||||
failures.add(feedback to rule.tag())
|
||||
failures.add(feedback to rule.uniqueTag())
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
@ -862,11 +862,11 @@ class TestController {
|
|||
|
||||
@Test
|
||||
fun failureHandlerRecover() {
|
||||
val failures = ArrayList<Pair<EvaluationFailure, String>>()
|
||||
val failures = ArrayList<Pair<EvaluationFailure, Any>>()
|
||||
val failureHandler = { rule: Rule, feedback: EvaluationFeedback ->
|
||||
if (feedback is EvaluationFailure) {
|
||||
failures.add(feedback to rule.tag())
|
||||
(rule.tag()?.startsWith("recoverable") == true)
|
||||
failures.add(feedback to rule.uniqueTag())
|
||||
(rule.uniqueTag().toString().startsWith("recoverable"))
|
||||
} else false
|
||||
}
|
||||
|
||||
|
|
@ -916,9 +916,9 @@ class TestController {
|
|||
|
||||
@Test
|
||||
fun detailsFeedbackHandler() {
|
||||
val feedbacks = arrayListOf<Pair<EvaluationFeedback, String>>()
|
||||
val feedbacks = arrayListOf<Pair<EvaluationFeedback, Any>>()
|
||||
val feedbackHandler = { rule: Rule, feedback: EvaluationFeedback ->
|
||||
feedbacks.add(feedback to rule.tag())
|
||||
feedbacks.add(feedback to rule.uniqueTag())
|
||||
feedback.message.startsWith("catchme")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -522,7 +522,7 @@ class TestRuleMatcher {
|
|||
matches().size shouldBe 1
|
||||
|
||||
with(matches().first()) {
|
||||
rule().tag() shouldBe "rule1"
|
||||
rule().uniqueTag().toString() shouldBe "rule1"
|
||||
|
||||
with(logicalContext()) {
|
||||
variable(X).findRoot().value() shouldBe parseTerm("h")
|
||||
|
|
@ -555,7 +555,7 @@ class TestRuleMatcher {
|
|||
|
||||
with(matches().first()) {
|
||||
|
||||
rule().tag() shouldBe "main"
|
||||
rule().uniqueTag().toString() shouldBe "main"
|
||||
matchHeadKept().count() shouldBe 0
|
||||
matchHeadReplaced().count() shouldBe 2
|
||||
|
||||
|
|
@ -597,7 +597,7 @@ class TestRuleMatcher {
|
|||
|
||||
with(matches().first()) {
|
||||
|
||||
rule().tag() shouldBe "rule1"
|
||||
rule().uniqueTag().toString() shouldBe "rule1"
|
||||
|
||||
}
|
||||
}.run {
|
||||
|
|
@ -606,7 +606,7 @@ class TestRuleMatcher {
|
|||
|
||||
with(matches().first()) {
|
||||
|
||||
rule().tag() shouldBe "rule2"
|
||||
rule().uniqueTag().toString() shouldBe "rule2"
|
||||
logicalContext().variable(X).value() shouldBe "a"
|
||||
|
||||
}
|
||||
|
|
@ -616,7 +616,7 @@ class TestRuleMatcher {
|
|||
|
||||
with(matches().drop(1).first()) {
|
||||
|
||||
rule().tag() shouldBe "rule2"
|
||||
rule().uniqueTag().toString() shouldBe "rule2"
|
||||
logicalContext().variable(X).value() shouldBe "b"
|
||||
|
||||
}
|
||||
|
|
@ -670,7 +670,7 @@ class TestRuleMatcher {
|
|||
expand(occurrence("foo")) }.apply {
|
||||
matches().count() shouldBe 3 }.run {
|
||||
|
||||
matches().map { it.rule().tag() }.toList() shouldBe listOf("rule1", "rule2", "rule3")
|
||||
matches().map { it.rule().uniqueTag().toString() }.toList() shouldBe listOf("rule1", "rule2", "rule3")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -713,15 +713,15 @@ class TestRuleMatcher {
|
|||
|
||||
expand(occurrence("bar")) }.apply {
|
||||
matches().count() shouldBe 1
|
||||
matches().first().rule().tag() shouldBe "rule2" }.run {
|
||||
matches().first().rule().uniqueTag().toString() shouldBe "rule2" }.run {
|
||||
|
||||
expand(occurrence("bazz")) }.apply {
|
||||
matches().count() shouldBe 1
|
||||
matches().first().rule().tag() shouldBe "rule1" }.run {
|
||||
matches().first().rule().uniqueTag().toString() shouldBe "rule1" }.run {
|
||||
|
||||
expand(occurrence("blin")) }.apply {
|
||||
matches().count() shouldBe 1
|
||||
matches().first().rule().tag() shouldBe "rule3"
|
||||
matches().first().rule().uniqueTag().toString() shouldBe "rule3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -766,11 +766,11 @@ class TestRuleMatcher {
|
|||
|
||||
expand(bar) }.apply {
|
||||
matches().count() shouldBe 1
|
||||
matches().first().rule().tag() shouldBe "rule2" }.run {
|
||||
matches().first().rule().uniqueTag().toString() shouldBe "rule2" }.run {
|
||||
|
||||
expand(occurrence("bazz")) }.apply {
|
||||
matches().count() shouldBe 1
|
||||
matches().first().rule().tag() shouldBe "rule1" }.run {
|
||||
matches().first().rule().uniqueTag().toString() shouldBe "rule1" }.run {
|
||||
|
||||
contract(bar) }.apply {
|
||||
matches().count() shouldBe 0 }.run {
|
||||
|
|
@ -780,7 +780,7 @@ class TestRuleMatcher {
|
|||
}.run {
|
||||
expand(bar) }.apply {
|
||||
matches().count() shouldBe 3
|
||||
matches().map { it.rule().tag() }.toList() shouldBe listOf("rule1", "rule2", "rule3")
|
||||
matches().map { it.rule().uniqueTag().toString() }.toList() shouldBe listOf("rule1", "rule2", "rule3")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue