diff --git a/src/main/java/io/usethesource/vallang/IConstructor.java b/src/main/java/io/usethesource/vallang/IConstructor.java index 305eca65..2070bbea 100644 --- a/src/main/java/io/usethesource/vallang/IConstructor.java +++ b/src/main/java/io/usethesource/vallang/IConstructor.java @@ -25,6 +25,14 @@ */ public interface IConstructor extends INode { + @Override + default int getPatternMatchFingerprint() { + return getName().hashCode() << 2 + arity(); + + // TODO: this would distinguish more constructors based on incomparable argument types: + // return getUninstantiatedConstructorType().hashCode(); + } + /** * @return the specific ConstructorType of this constructor */ diff --git a/src/main/java/io/usethesource/vallang/IExternalValue.java b/src/main/java/io/usethesource/vallang/IExternalValue.java index f3678054..84382e8d 100644 --- a/src/main/java/io/usethesource/vallang/IExternalValue.java +++ b/src/main/java/io/usethesource/vallang/IExternalValue.java @@ -37,6 +37,12 @@ * Note that NORMAL USE OF THE PDB DOES NOT REQUIRE IMPLEMENTING THIS INTERFACE */ public interface IExternalValue extends IValue { + /** + * External values must re-think their pattern match fingerprint, + * instead of returning `IValue.hashCode()` automatically. + */ + @Override + int getPatternMatchFingerprint(); /** * @return an ExternalType diff --git a/src/main/java/io/usethesource/vallang/IList.java b/src/main/java/io/usethesource/vallang/IList.java index 496e232d..edb0429e 100644 --- a/src/main/java/io/usethesource/vallang/IList.java +++ b/src/main/java/io/usethesource/vallang/IList.java @@ -22,6 +22,12 @@ import io.usethesource.vallang.visitors.IValueVisitor; public interface IList extends ICollection { + + @Override + default int getPatternMatchFingerprint() { + return 3322014; // "list".hashCode() + } + /** * @return the number of elements in the list */ diff --git a/src/main/java/io/usethesource/vallang/IMap.java b/src/main/java/io/usethesource/vallang/IMap.java index 46b31371..21202860 100644 --- a/src/main/java/io/usethesource/vallang/IMap.java +++ b/src/main/java/io/usethesource/vallang/IMap.java @@ -26,6 +26,11 @@ public interface IMap extends ICollection { + @Override + default int getPatternMatchFingerprint() { + return 107868; // "map".hashCode() + } + /** * Adds a new entry to the map, mapping the key to value. If the * key existed before, the old value will be lost. diff --git a/src/main/java/io/usethesource/vallang/INode.java b/src/main/java/io/usethesource/vallang/INode.java index bfe51cdb..12f2522c 100644 --- a/src/main/java/io/usethesource/vallang/INode.java +++ b/src/main/java/io/usethesource/vallang/INode.java @@ -30,6 +30,12 @@ * it recursively. */ public interface INode extends IValue, Iterable { + + @Override + default int getPatternMatchFingerprint() { + return getName().hashCode() << 2 + arity(); + } + /** * Get a child * @param i the zero based index of the child diff --git a/src/main/java/io/usethesource/vallang/ISet.java b/src/main/java/io/usethesource/vallang/ISet.java index 3fd05cf8..d58ad285 100644 --- a/src/main/java/io/usethesource/vallang/ISet.java +++ b/src/main/java/io/usethesource/vallang/ISet.java @@ -21,6 +21,11 @@ public interface ISet extends ICollection { + @Override + default int getPatternMatchFingerprint() { + return 113762; // "set".hashCode() + } + /** * Add an element to the set. * @param element diff --git a/src/main/java/io/usethesource/vallang/IString.java b/src/main/java/io/usethesource/vallang/IString.java index 8198be0e..a900405d 100644 --- a/src/main/java/io/usethesource/vallang/IString.java +++ b/src/main/java/io/usethesource/vallang/IString.java @@ -19,6 +19,7 @@ import io.usethesource.vallang.visitors.IValueVisitor; public interface IString extends IValue, Iterable { + /** * @return the Java string that this string represents */ diff --git a/src/main/java/io/usethesource/vallang/ITuple.java b/src/main/java/io/usethesource/vallang/ITuple.java index 35d01645..fc791ca3 100644 --- a/src/main/java/io/usethesource/vallang/ITuple.java +++ b/src/main/java/io/usethesource/vallang/ITuple.java @@ -16,6 +16,11 @@ import io.usethesource.vallang.visitors.IValueVisitor; public interface ITuple extends Iterable, IValue { + @Override + default int getPatternMatchFingerprint() { + return 442900256 /* "tuple".hashCode() << 2 */ + arity(); + } + /** * Retrieve the given field at the given index. * diff --git a/src/main/java/io/usethesource/vallang/IValue.java b/src/main/java/io/usethesource/vallang/IValue.java index 1af86064..9679fd01 100644 --- a/src/main/java/io/usethesource/vallang/IValue.java +++ b/src/main/java/io/usethesource/vallang/IValue.java @@ -28,6 +28,22 @@ public interface IValue { * @return the {@link Type} of a value */ public Type getType(); + + /** + * This method is used exclusively by code generated by the Rascal compiler, + * or by the Rascal interpreter. The returned integer codes are opaque, although stable. + * If you need to know what kind of value you have, use the IValueVisitor or the ITypeVisitor + * interfaces and the `accept` methods on IValue and Type. + * + * @return an integer code that: + * * accurate reflects the identity of the top-level structure of this value + * * such that if pattern.match(this) ===> pattern.getPatternMatchFingerprint() == this.getPatternMatchFingerprint() + * * distinguishes maximally between different kinds of values + * * never makes the same or similar value have a different fingerprint + */ + default int getPatternMatchFingerprint() { + return hashCode(); + } /** * Execute the {@link IValueVisitor} on the current node