Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added IValue.getPatternMatchFingerprint() that simulates rascal-core:TopLevelType.getFingerprint(v) exactly for the value kinds we have in vallang #210

Merged
merged 12 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>io.usethesource</groupId>
<artifactId>vallang</artifactId>
<version>0.15.2-SNAPSHOT</version>
<version>1.0.0-SNAPSHOT</version>
DavyLandman marked this conversation as resolved.
Show resolved Hide resolved
<packaging>jar</packaging>

<scm>
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/io/usethesource/vallang/IBool.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
import io.usethesource.vallang.visitors.IValueVisitor;

public interface IBool extends IValue {
@Override
default int getMatchFingerprint() {
if (getValue()) {
return 3569038; /* "true".hashCode() */
}
else {
return 97196323; /* "false".hashCode() */
}
}

boolean getValue();
String getStringRepresentation();
IBool and(IBool other);
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/usethesource/vallang/IConstructor.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
*/
public interface IConstructor extends INode {

@Override
default int getMatchFingerprint() {
return getName().hashCode() + 131 * arity();
}

/**
* @return the specific ConstructorType of this constructor
*/
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/io/usethesource/vallang/IExternalValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 getMatchFingerprint();

/**
* @return an ExternalType
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/io/usethesource/vallang/IInteger.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@
import io.usethesource.vallang.visitors.IValueVisitor;

public interface IInteger extends INumber {
@Override
default int getMatchFingerprint() {
if (signum() == 0) {
return 104431; /* "int".hashCode() */
}
else {
return hashCode();
}
}

/**
* @return this + other;
*/
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/io/usethesource/vallang/IList.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
import io.usethesource.vallang.visitors.IValueVisitor;

public interface IList extends ICollection<IList> {

@Override
default int getMatchFingerprint() {
return 3322014; // "list".hashCode()
DavyLandman marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @return the number of elements in the list
*/
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/usethesource/vallang/IMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@

public interface IMap extends ICollection<IMap> {

@Override
default int getMatchFingerprint() {
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.
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/io/usethesource/vallang/INode.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@
* it recursively.
*/
public interface INode extends IValue, Iterable<IValue> {

@Override
default int getMatchFingerprint() {
int hash = getName().hashCode();

return hash == 0 ? 13547528 /* "node".hashCode() << 2*/ + arity() : hash + 131 * arity();
DavyLandman marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Get a child
* @param i the zero based index of the child
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/io/usethesource/vallang/IReal.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
import io.usethesource.vallang.visitors.IValueVisitor;

public interface IReal extends INumber {
@Override
default int getMatchFingerprint() {
int hash = hashCode();
return hash == 0 ? 3496350 /* real.hashCode() */ : hash;
DavyLandman marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @return this + other;
*/
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/usethesource/vallang/ISet.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@

public interface ISet extends ICollection<ISet> {

@Override
default int getMatchFingerprint() {
return 113762; // "set".hashCode()
}

/**
* Add an element to the set.
* @param element
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/io/usethesource/vallang/IString.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
import io.usethesource.vallang.visitors.IValueVisitor;

public interface IString extends IValue, Iterable<Integer> {

@Override
default int getMatchFingerprint() {
if (length() == 0) {
return 114225; /* "str".hashCode() */
}
else {
return hashCode();
}
}

/**
* @return the Java string that this string represents
*/
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/usethesource/vallang/ITuple.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
import io.usethesource.vallang.visitors.IValueVisitor;

public interface ITuple extends Iterable<IValue>, IValue {
@Override
default int getMatchFingerprint() {
return 442900256 /* "tuple".hashCode() << 2 */ + arity();
DavyLandman marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Retrieve the given field at the given index.
*
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/io/usethesource/vallang/IValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,35 @@ 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 getMatchFingerprint() {
DavyLandman marked this conversation as resolved.
Show resolved Hide resolved
return hashCode();
}

/**
* This method is used exclusively by code generated by the Rascal compiler,
*
* @return an integer code that:
* * is guaranteed to be different from `getMatchFingerPrint`
* * is guaranteed to be constant
* * is guaranteed to be the same for every IValue
*/
static int getDefaultMatchFingerprint() {
return 0;
}

/**
* Execute the {@link IValueVisitor} on the current node
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import io.usethesource.vallang.ISetWriter;
import io.usethesource.vallang.ITuple;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.exceptions.IllegalOperationException;
import io.usethesource.vallang.type.Type;
import io.usethesource.vallang.util.AbstractTypeBag;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ else if (isRationalType(other)) {
}
}

@Override
public int hashCode(){
int h = value ^ 0x85ebca6b;
// based on the final Avalanching phase of MurmurHash2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ public boolean equals(@Nullable Object obj) {
*/
private final HotEntry<T>[] hotEntries;
private final int mask;
private final int expireAfter;

/**
* All entries are also stored in a WeakReference, this helps with clearing memory
Expand All @@ -143,7 +142,6 @@ public WeakReferenceHashConsingMap(int size, int demoteAfterSeconds) {
size = Integer.highestOneBit(size - 1) << 1;
hotEntries = new HotEntry[size];
this.mask = size - 1;
this.expireAfter = demoteAfterSeconds;

coldEntries = new ConcurrentHashMap<>(size);

Expand Down
20 changes: 19 additions & 1 deletion src/test/java/io/usethesource/vallang/ValueProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,26 @@ private RandomTypesConfig configureRandomTypes(TypeConfig typeConfig, int depth)
* @return an instance assignable to `cl`
*/
private IValue generateValue(IValueFactory vf, TypeStore ts, Class<? extends IValue> cl, ExpectedType expected, int depth, int width) {
Type expectedType = expected != null ? readType(ts, expected) : types.getOrDefault(cl, (x, n) -> tf.valueType()).apply(ts, expected);
Type expectedType = tf.voidType();


// this should terminate through random selection.
// only tuple types with nested void arguments can reduce to void.
int i = 0;
while (expectedType.isBottom() && i++ < 1000) {
if (expected != null) {
expectedType = readType(ts, expected);
break;
}
else {
expectedType = types
.getOrDefault(cl, (x, n) -> tf.valueType())
.apply(ts, expected);
}
}

assert !expectedType.isBottom() : cl + " generated void type?";

if (previous != null && rnd.nextInt(4) == 0 && previous.getType().isSubtypeOf(expectedType)) {
return rnd.nextBoolean() ? previous : reinstantiate(vf, ts, previous);
}
Expand Down
Loading
Loading