Move TermWalker from tests package to core.internal to reuse for MPSCR-66

Also convert it to Kotlin
This commit is contained in:
Grigorii Kirgizov 2020-07-27 11:09:18 +03:00
parent b87ae4b03a
commit 3ef1c53a85
2 changed files with 91 additions and 72 deletions

View File

@ -0,0 +1,77 @@
/*
* Copyright 2014-2020 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.logic.reactor.core.internal
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.logical.LogicalOwner
import jetbrains.mps.unification.Term
import java.util.*
/**
* @author Fedor Isakov
*/
class TermWalker(vararg visitors: TermVisitor<out Term>) {
abstract class TermVisitor<T : Term?>(private val kind: Term.Kind) {
fun applicableTo(): Term.Kind = kind
@Throws(Exception::class)
abstract fun visit(t: T): MutableCollection<out Term>
}
private val visitorMap: MutableMap<Term.Kind, TermVisitor<out Term>> = EnumMap(Term.Kind::class.java)
init {
for (visitor in visitors) {
visitorMap[visitor.applicableTo()] = visitor
}
}
@Throws(Exception::class)
fun walk(term: Term) {
walk(term, IdentityHashMap())
}
@Throws(Exception::class)
private fun walk(term: Term, visited: MutableMap<Term, Any?>) {
if (term.`is`(Term.Kind.FUN)) {
visited[term] = SINGLETON
}
val arguments = switchClass(term)
for (arg in arguments) {
if (visited.containsKey(arg)) {
continue
}
walk(arg, visited)
}
}
@Throws(Exception::class)
private fun switchClass(term: Term): Collection<Term> {
for ((key, value1) in visitorMap) {
if (term.`is`(key)) {
val value = value1 as TermVisitor<Term>
return value.visit(term)
}
}
return emptyList()
}
companion object {
private val SINGLETON = Any()
}
}

View File

@ -16,6 +16,7 @@
package jetbrains.mps.unification.test;
import jetbrains.mps.logic.reactor.core.internal.TermWalker;
import jetbrains.mps.unification.Term;
import static org.junit.Assert.*;
@ -32,40 +33,40 @@ public class AssertStructurallyEquivalent {
signature.setWalkers(
// first pass
new TermWalker(
new TermVisitor<Term>(Term.Kind.FUN) {
new TermWalker.TermVisitor<Term>(Term.Kind.FUN) {
@Override
public Collection<? extends Term> visit(Term term) throws Exception {
signature.label(term);
return term.arguments();
}
}
,
new TermVisitor<Term>(Term.Kind.REF) {
@Override
public Collection<? extends Term> visit(Term ref) throws Exception {
if (ref.get().is(Term.Kind.FUN)) {
return Collections.singletonList(ref.get());
},
new TermWalker.TermVisitor<Term>(Term.Kind.REF) {
@Override
public Collection<? extends Term> visit(Term ref) throws Exception {
if (ref.get().is(Term.Kind.FUN)) {
return Collections.singletonList(ref.get());
}
return Collections.emptyList();
}
return Collections.emptyList();
}
}
),
// second pass
new TermWalker(
new TermVisitor<Term>(Term.Kind.FUN) {
new TermWalker.TermVisitor<Term>(Term.Kind.FUN) {
@Override
public Collection<? extends Term> visit(Term term) throws Exception {
signature.appendSignature("@").append(signature.getLabel(term)).append(term.symbol());
return term.arguments();
}
},
new TermVisitor<Term>(Term.Kind.VAR) {
new TermWalker.TermVisitor<Term>(Term.Kind.VAR) {
@Override
public Collection<? extends Term> visit(Term var) throws Exception {
signature.appendSignature("$").append(var.symbol());
return Collections.emptyList();
}
}, new TermVisitor<Term>(Term.Kind.REF) {
},
new TermWalker.TermVisitor<Term>(Term.Kind.REF) {
@Override
public Collection<? extends Term> visit(Term ref) throws Exception {
if (ref.get().is(Term.Kind.FUN)) {
@ -139,63 +140,4 @@ public class AssertStructurallyEquivalent {
}
}
private static abstract class TermVisitor<T extends Term> {
private Term.Kind kind;
public TermVisitor(Term.Kind kind) {
this.kind = kind;
}
public Term.Kind applicableTo() {
return kind;
}
public abstract Collection<? extends Term> visit(T t) throws Exception ;
}
private static class TermWalker {
private static Object SINGLETON = new Object();
private Map<Term.Kind, TermVisitor<? extends Term>> visitorMap = new HashMap<Term.Kind, TermVisitor<? extends Term>>();
public TermWalker(TermVisitor<? extends Term>... visitors) {
for (TermVisitor<? extends Term> visitor : visitors) {
visitorMap.put(visitor.applicableTo(), visitor);
}
}
public void walk(Term term) throws Exception {
walk(term, new IdentityHashMap<Term, Object>());
}
private void walk(Term term, Map<Term, Object> visited) throws Exception {
if (term.is(Term.Kind.FUN)) {
visited.put(term, SINGLETON);
}
Collection<? extends Term> arguments = switchClass(term);
for (Term arg : arguments) {
if (visited.containsKey(arg)) {
continue;
}
walk(arg, visited);
}
}
private Collection<? extends Term> switchClass(Term term) throws Exception {
for (Map.Entry<Term.Kind, TermVisitor<? extends Term>> e : visitorMap.entrySet()) {
if (term.is(e.getKey())) {
TermVisitor<Term> value = (TermVisitor<Term>) e.getValue();
return value.visit(term);
}
}
return Collections.emptyList();
}
}
}