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));
}
}
What's the "better" pattern here? Using guards as suggested by @eregon seems to require lots of boilerplate code (e.g. many guard methods), but it's clear how the specialization works. I still don't feel very comfortable using
@Fallback
, and it's seems others do, too. Also, can anyone think of an example where you'd need more than one@Fallback
(which you can't have)?