Move TermWalker from tests package to core.internal to reuse for MPSCR-66
Also convert it to Kotlin
This commit is contained in:
parent
b87ae4b03a
commit
3ef1c53a85
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue