Truffle Specializations do not automatically have exclusive semantics. Instead, the rules of the Java type system apply.
Let's take the following node with three specializations as example.
Note, I return an int
here, usually you'd return a boolean, but the int
allows me to get the point across more precisely in the later tests.
@NodeChild(value = "e", type = ExprNode.class)
public abstract class IsNumberNode extends Node {
public abstract Object executeGeneric(VirtualFrame frame);
public abstract int executeEvaluated(Object o);
@Specialization
public final int isInt(final int o) {
return 1;
}
@Specialization
public final int isDouble(final double o) {
return 2;
}
@Specialization
public final int isObject(final Object o) {
return 3;
}
}
It is important to realize that isObject(Object)
is more general than isInt(int)
and isDouble(double)
, which means, it is expected to subsume the more specific specializations.
This can be made explicit with @Specialization(replaces = {"isInt", "isDouble"})
, which has the effect of disabling previously activated specializations.
Anyway, to demonstrate the semantics, here a test:
public class TestAdd {
@Test
public void testIsNumberOneAfterAnother() {
IsNumberNode n = IsNumberNodeGen.create(null);
assertEquals(1, n.executeEvaluated(42));
assertEquals(2, n.executeEvaluated(44.3));
assertEquals(3, n.executeEvaluated(new Object()));
assertEquals(2, n.executeEvaluated(44.3));
}
@Test
public void testIsNumberStartingWithTheMostGeneral() {
IsNumberNode n = IsNumberNodeGen.create(null);
assertEquals(3, n.executeEvaluated(new Object()));
assertEquals(3, n.executeEvaluated(44.3));
assertEquals(3, n.executeEvaluated(42));
}
}
And so to have
isObject
only handle "objects" and not the other specializations' types, it is needed to add guards like: