diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournalImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournalImpl.kt index 8b35e9f4..408c4d7f 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournalImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournalImpl.kt @@ -48,7 +48,7 @@ internal open class MatchJournalImpl( val rulesWithOrigin = HashSet(4) - override fun toString() = "(id=$evidence, ${justifications()}, ${match.rule().uniqueTag().name()}, $entries)" + override fun toString() = "(id=$evidence, ${justifications()}, ${match.rule().uniqueTag().toString()}, $entries)" } private class OccChunkImpl(override val occ: Occurrence) : ChunkImpl(), Justified by occ, OccChunk { diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/program/Rule.java b/reactor/Core/src/jetbrains/mps/logic/reactor/program/Rule.java index a6b8c016..d7feab50 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/program/Rule.java +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/program/Rule.java @@ -17,8 +17,7 @@ package jetbrains.mps.logic.reactor.program; -import java.util.Collections; -import java.util.List; +import java.util.Objects; /** * A constraint rule description. @@ -28,18 +27,7 @@ import java.util.List; public abstract class Rule { public abstract Rule.Kind kind(); - - /** - * A list of objects identifying the segment this rule belongs to. An empty segment path signifies the root segment. - * An occurrence produced from the root segment can be processed by any rule in the program. - * An occurrence produced from segment identified by a path P can be processed by a rule from any segment that - * has P as the path prefix. - */ - // TODO Make abstract - public List segmentPath() { - return Collections.emptyList(); - } - + public boolean isBasis() { return false; } /** @@ -66,29 +54,26 @@ public abstract class Rule { public static final class Tag { + /** + * The name of the template that created this rule. + * @deprecated + */ public String groupName() { return group; } - public String name() { return name; } - /** - * Rule is "stable" if it has no unique part - * and its name coincides with unique tag. - * @return true if rule has no unique part + * + * @param groupName template that created this rule + * @param tagName + * @param uniquePart */ - public boolean stable() { return utag.length() == name.length(); } - - public Tag(String groupPrefix, String commonPart, Object uniquePart) { - if (!commonPart.startsWith(groupPrefix)) { + public Tag(String groupName, String tagName, Object uniquePart) { + if (!tagName.startsWith(groupName)) { throw new IllegalArgumentException(); } - StringBuilder utagSb = new StringBuilder(commonPart); - if (uniquePart != null) { - utagSb.append('_').append(uniquePart); - } - this.group = groupPrefix; - this.name = commonPart; - this.utag = utagSb.toString(); - this.hash = utag.hashCode(); + this.group = groupName; + this.tag = tagName; + this.id = uniquePart; + this.hash = Objects.hash(tag, id); } @Deprecated @@ -98,20 +83,20 @@ public abstract class Rule { public int hashCode() { return hash; } @Override - public boolean equals(Object obj) { - if (obj == null) return false; - if (this == obj) return true; - // FIXME WTF? NB: allow equality to String - return this.toString().equals(obj.toString()); + public boolean equals(Object that) { + if (that == null) return false; + if (this == that) return true; + if (!(that instanceof Tag)) return false; + return Objects.equals(this.id, ((Tag) that).id) && Objects.equals(this.tag, ((Tag) that).tag); } @Override - public String toString() { return utag; } + public String toString() { return tag; } private final int hash; private final String group; - private final String name; - private final String utag; + private final String tag; + private final Object id; } } diff --git a/reactor/Test/src/program/MockProgram.kt b/reactor/Test/src/program/MockProgram.kt index 26d41c31..f2b841e1 100644 --- a/reactor/Test/src/program/MockProgram.kt +++ b/reactor/Test/src/program/MockProgram.kt @@ -43,7 +43,7 @@ class HandlerBuilder(val name: String) { fun toHandler(): RulesList = MockHandler(name, rules.values.toList()) } -class RuleBuilder(val tag: String, val segmentPath: List) { +class RuleBuilder(val tag: String) { val kept = ArrayList() val replaced = ArrayList() val guard = ArrayList() @@ -62,7 +62,7 @@ class RuleBuilder(val tag: String, val segmentPath: List) { if (alt || body.isEmpty()) body.add(ArrayList()) body.last().addAll(andItem) } - fun toRule(): Rule = MockRule(Rule.Tag(tag), segmentPath, kept, replaced, guard, body) + fun toRule(): Rule = MockRule(Rule.Tag(tag), kept, replaced, guard, body) } class MockHandler( @@ -76,7 +76,6 @@ class MockHandler( class MockRule( val tag: Rule.Tag, - val segmentPath: List, val kept: Collection, val replaced: Collection, val guard: Collection, @@ -84,8 +83,6 @@ class MockRule( override fun kind(): Kind = TODO() - override fun segmentPath(): List = segmentPath - override fun uniqueTag() = tag override fun headKept(): Iterable = kept diff --git a/reactor/Test/test/RulesHelper.kt b/reactor/Test/test/RulesHelper.kt index 4a18e4ca..4de88bac 100644 --- a/reactor/Test/test/RulesHelper.kt +++ b/reactor/Test/test/RulesHelper.kt @@ -125,7 +125,7 @@ fun Builder.insertRulesWhen(at: (Rule) -> Boolean, vararg ruleBuilders: () -> Ru updateBuilder(this, arrayOf(insertRulesInHandlerWhen(at, "test", rulesLists.first(), * ruleBuilders))) fun rule(tag: String, vararg component: RuleBuilder.() -> Unit): () -> Rule = { - val rb = RuleBuilder(tag, emptyList()) + val rb = RuleBuilder(tag) for (cmp in component) { rb.cmp() } diff --git a/reactor/Test/test/TestIncrementalProgram.kt b/reactor/Test/test/TestIncrementalProgram.kt index 33e70f9c..9de460f4 100644 --- a/reactor/Test/test/TestIncrementalProgram.kt +++ b/reactor/Test/test/TestIncrementalProgram.kt @@ -1326,7 +1326,7 @@ class TestIncrementalProgram { ).launch("launch", progSpec) { result -> result.storeView().constraintSymbols() shouldBe setOf(sym0("important")) - assertTrue( result.lastChunk().let { it is MatchJournal.MatchChunk && it.match.rule().uniqueTag().name() == "foo" } ) + assertTrue( result.lastChunk().let { it is MatchJournal.MatchChunk && it.match.rule().uniqueTag().toString() == "foo" } ) }.also { (builder, evalRes) -> diff --git a/reactor/Test/test/TestRuleMatcher.kt b/reactor/Test/test/TestRuleMatcher.kt index dd0a3970..0ceae648 100644 --- a/reactor/Test/test/TestRuleMatcher.kt +++ b/reactor/Test/test/TestRuleMatcher.kt @@ -550,7 +550,7 @@ class TestRuleMatcher { expand(occurrence("bar", x, y)) }.apply { matches().size shouldBe 1 - matches().first().rule().uniqueTag().name() shouldBe "rule1" + matches().first().rule().uniqueTag().toString() shouldBe "rule1" } }