Skip to content

Commit

Permalink
added getConcreteMatchFingerprint to ITree
Browse files Browse the repository at this point in the history
  • Loading branch information
jurgenvinju committed Nov 2, 2023
1 parent 56787fd commit afe38a0
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 8 deletions.
54 changes: 52 additions & 2 deletions src/org/rascalmpl/values/RascalValueFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,11 @@ static class CharInt implements ITree {
public boolean isChar() {
return true;
}

@Override
public int getConcreteMatchFingerprint() {
return 3052374 /* "char".hashCode() */ + ch;
}

@Override
public INode setChildren(IValue[] childArray) {
Expand Down Expand Up @@ -683,6 +688,11 @@ private static class CharByte implements ITree {
public CharByte(byte ch) {
this.ch = ch;
}

@Override
public int getConcreteMatchFingerprint() {
return 3052374 /* "char".hashCode() */ + ch;
}

@Override
public boolean isChar() {
Expand Down Expand Up @@ -855,6 +865,11 @@ public Cycle(IConstructor symbol, int cycleLength) {
this.symbol = symbol;
this.cycleLength = cycleLength;
}

@Override
public int getConcreteMatchFingerprint() {
return 95131878 /* "cycle".hashCode() */ + 13 * symbol.hashCode();
}

@Override
public boolean isCycle() {
Expand Down Expand Up @@ -1033,11 +1048,21 @@ public Amb(ISet alts) {
this.alternatives = alts;
}

@Override
public int getConcreteMatchFingerprint() {
return 96694 /* "amb".hashCode() */ + 43 * alternatives.getElementType().hashCode();
}

@Override
public boolean isAmb() {
return true;
}

@Override
public int getMatchFingerprint() {
return 96694 /* Tree_Amb.getName().hashCode() */ + 131; // should be equal what IConstructor does for the amb constructor!
}

@Override
public <E extends Throwable> ITree accept(TreeVisitor<E> v) throws E {
return (ITree) v.visitTreeAmb(this);
Expand Down Expand Up @@ -1101,8 +1126,8 @@ public boolean hasNext() {
public IValue next() {
count++;
switch(count) {
case 1: return getAlternatives();
default: return null;
case 1: return getAlternatives();
default: return null;
}
}
};
Expand Down Expand Up @@ -1217,6 +1242,11 @@ public ApplWithKeywordParametersFacade(IConstructor content, io.usethesource.cap
super(content, parameters);
}

@Override
public int getConcreteMatchFingerprint() {
return ((ITree) content).getConcreteMatchFingerprint();
}

@Override
public <E extends Throwable> ITree accept(TreeVisitor<E> v) throws E {
return v.visitTreeAppl(this);
Expand Down Expand Up @@ -1268,6 +1298,11 @@ public AmbWithKeywordParametersFacade(IConstructor content, io.usethesource.caps
super(content, parameters);
}

@Override
public int getConcreteMatchFingerprint() {
return ((ITree) content).getConcreteMatchFingerprint();
}

@Override
public <E extends Throwable> ITree accept(TreeVisitor<E> v) throws E {
return v.visitTreeAmb(this);
Expand Down Expand Up @@ -1314,6 +1349,11 @@ public CycleWithKeywordParametersFacade(IConstructor content, io.usethesource.ca
super(content, parameters);
}

@Override
public int getConcreteMatchFingerprint() {
return ((ITree) content).getConcreteMatchFingerprint();
}

@Override
public <E extends Throwable> ITree accept(TreeVisitor<E> v) throws E {
return v.visitTreeCycle(this);
Expand Down Expand Up @@ -1356,6 +1396,11 @@ public CharWithKeywordParametersFacade(IConstructor content, io.usethesource.cap
super(content, parameters);
}

@Override
public int getConcreteMatchFingerprint() {
return ((ITree) content).getConcreteMatchFingerprint();
}

@Override
public <E extends Throwable> ITree accept(TreeVisitor<E> v) throws E {
return v.visitTreeChar(this);
Expand Down Expand Up @@ -1403,6 +1448,11 @@ private static abstract class AbstractAppl implements ITree {
protected Type type = null;


@Override
public int getConcreteMatchFingerprint() {
return 3568542 /* "tree".hashCode() */ + 41 * production.hashCode();
}

@Override
public <E extends Throwable> ITree accept(TreeVisitor<E> v) throws E {
return v.visitTreeAppl(this);
Expand Down
17 changes: 16 additions & 1 deletion src/org/rascalmpl/values/parsetrees/ITree.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,24 @@ default <T, E extends Throwable> T accept(IValueVisitor<T, E> v) throws E {

@Override
default int getMatchFingerprint() {
return 3568542 /* "tree".hashCode() */ + 41 * getProduction().hashCode();
// ITrees must simulate their constructor prints in case
// we pattern match on the abstract Tree data-type
return IConstructor.super.getMatchFingerprint();
}

/**
* Concrete patterns need another layer of fingerprinting on top
* of `getMatchFingerprint`. The reason is that _the same IValue_
* can be matched against an abstract pattern of the Tree data-type,
* and against concrete patterns.
*
* Like before, the match-fingerprint contract is:
* if pattern.match(tree) ==> pattern.fingerprint() == match.fingerprint();
*
* @return a unique code for each outermost ITree node
*/
int getConcreteMatchFingerprint();

default boolean isAppl() {
return false;
}
Expand Down
1 change: 1 addition & 0 deletions src/org/rascalmpl/values/parsetrees/TreeAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ else if (isChar(tree)) {
return SymbolAdapter.charClass(TreeAdapter.getCharacter(tree));
}
else if (isAmb(tree)) {
// ambiguities are never empty
return getType((ITree) getAlternatives(tree).iterator().next());
}
throw new ImplementationError("ITree does not have a type");
Expand Down
50 changes: 45 additions & 5 deletions test/org/rascalmpl/MatchFingerprintTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.rascalmpl.types.RascalTypeFactory;

import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.IInteger;
import io.usethesource.vallang.exceptions.FactTypeUseException;
import io.usethesource.vallang.io.StandardTextReader;
import io.usethesource.vallang.type.Type;
Expand All @@ -29,6 +30,7 @@
import org.rascalmpl.values.RascalFunctionValueFactory;
import org.rascalmpl.values.functions.IFunction;
import org.rascalmpl.values.parsetrees.ITree;
import org.rascalmpl.values.parsetrees.TreeAdapter;

import junit.framework.TestCase;

Expand All @@ -46,7 +48,6 @@ public class MatchFingerprintTest extends TestCase {
private final Evaluator eval = new Evaluator(IRascalValueFactory.getInstance(), System.in, System.err, System.out, root, heap);
private final RascalFunctionValueFactory VF = eval.getFunctionValueFactory();
private final TypeFactory TF = TypeFactory.getInstance();
private final RascalTypeFactory RTF = RascalTypeFactory.getInstance();

public void testFunctionFingerPrintStability() {
Type intint = TF.functionType(TF.integerType(), TF.tupleType(TF.integerType()), TF.tupleEmpty());
Expand All @@ -59,19 +60,58 @@ public void testFunctionFingerPrintStability() {
assertEquals(func.getMatchFingerprint(), "func".hashCode() + 89 * intint.hashCode());
}

public void testTreeApplFingerPrintStability() {
String prodString = "prod(sort(\"E\"),[],{})";

public void testTreeFingerPrintStability() {
String prodString="prod(sort(\"E\"),[],{})";
try {
IConstructor prod = (IConstructor) new StandardTextReader().read(VF, RascalFunctionValueFactory.getStore(), RascalFunctionValueFactory.Production, new StringReader(prodString));
ITree tree = VF.appl(prod, VF.list());

assertEquals(tree.getMatchFingerprint(), "tree".hashCode() + 41 * prod.hashCode());
assertEquals(tree.getMatchFingerprint(), "prod".hashCode() + 131 * prod.arity());
assertEquals(tree.getConcreteMatchFingerprint(), "tree".hashCode() + 41 * prod.hashCode());
}
catch (FactTypeUseException | IOException e) {
fail(e.getMessage());
}
}


public void testTreeAmbFingerPrintStability() {
String prodString = "prod(sort(\"E\"),[],{})";

try {
IConstructor prod = (IConstructor) new StandardTextReader().read(VF, RascalFunctionValueFactory.getStore(), RascalFunctionValueFactory.Production, new StringReader(prodString));
ITree tree = VF.appl(prod, VF.list());
ITree amb = VF.amb(VF.set(tree));

assertEquals(amb.getMatchFingerprint(), "amb".hashCode() + 131);
assertEquals(tree.getConcreteMatchFingerprint(), "amb".hashCode() + 43 * TreeAdapter.getType(amb).hashCode());
}
catch (FactTypeUseException | IOException e) {
fail(e.getMessage());
}
}

public void testTreeCharFingerPrintStability() {
try {
ITree theChar = (ITree) new StandardTextReader().read(VF, RascalFunctionValueFactory.getStore(), RascalFunctionValueFactory.Tree, new StringReader("char(32)"));

assertEquals(theChar.getMatchFingerprint(), "char".hashCode() + 131);
assertEquals(theChar.getConcreteMatchFingerprint(), "char".hashCode() + ((IInteger) theChar.get(0)).intValue());
}
catch (FactTypeUseException | IOException e) {
fail(e.getMessage());
}
}

public void testTreeCycleFingerPrintStability() {
try {
ITree theCycle = (ITree) new StandardTextReader().read(VF, RascalFunctionValueFactory.getStore(), RascalFunctionValueFactory.Tree, new StringReader("cycle(sort(\"A\"), 3)"));

assertEquals(theCycle.getMatchFingerprint(), "cycle".hashCode() + 2 * 131);
assertEquals(theCycle.getConcreteMatchFingerprint(), "cycle".hashCode() + 13 * theCycle.get(0).hashCode());
}
catch (FactTypeUseException | IOException e) {
fail(e.getMessage());
}
}
}

0 comments on commit afe38a0

Please sign in to comment.