If
An If expression performs a test, and if the test is true it executes an expression,
and if the test is false, it executes a different expression. In some functional
languages, an if expression is required to have both a true and false expression.
JFuncMachine allows for having only a true expression if the true expression has
type SimpleTypes.UNIT.
Like a typical functional language, If is an expression, not a statement. That is,
If returns the value of either its true expression or its false expression. Java does
have an equivalent to this, which is the ternary operator. For example:
x = a > b ? 5 : 0The above ternary expression is the equivalent of this in JFuncMachine:
new SetValue("x", new If(new BinaryComparison(Tests.GT, new GetValue("a", SimpleTypes.INT),
new GetValue("b", SimpleTypes.INT)),
new IntConstant(5), new IntConstant(0)));Tests
The test part of the If expression determines which path to take.
There are several types of comparisons.
Binary Comparisons
A BinaryComparison compares two items, which means it takes a “left” and “right”
expression. For numeric and string types, you can use
the following tests:
Tests.EQTests.NETests.LTTests.LETests.GTTests.GE
Java doesn’t have instructions for comparing strings, so JFuncMachine uses the
String.compare method to compare strings when you uses any of these tests.
Since you may want to compare strings while ignoring case, the following
tests are also available for strings:
Tests.EQ_IgnoreCaseTests.NE_IgnoreCaseTests.LT_IgnoreCaseTests.LE_IgnoreCaseTests.GT_IgnoreCaseTests.GE_IgnoreCase
For example, the following expression tests whether local variable x is less then local variable y:
new BinaryComparison(Tests.LT, new GetValue("x", SimpleTypes.INT), new GetValue("y", SimpleTypes.INT))Unary Comparisons
A UnaryComparison performs a test against a single expression. The following
tests are available for unary comparisons:
Tests.IsNullTests.IsNotNullTests.IsTrueTests.IsFalse
For example, the following UnaryComparison tests whether local variable obj is non-null:
new UnaryComparison(Tests.IsNonNull, new GetValue("obj", new ObjectType()))The Tests.IsTrue and Tests.IsFalse technically just check whether or not
an int value (which includes boolean, byte, char, int, and short) is zero (false)
or non-zero (true).
Java has a Comparable interface whose compareTo method returns either a
negative integer for less-than, zero for equal, and positive for greater.
You can use a UnaryComparison to test the result of a compareTo using
the same numeric tests as in the BinaryComparison without having to
explicitly compare against 0:
Tests.EQTests.NETests.LTTests.LETests.GTTests.GE
Although it is much easier (and generates the same code) to use a BinaryComparison
to compare whether local string variable x is less than local string variable y,
here is how it can be done with UnaryComparison:
new UnaryComparison(Tests.LT,
new CallJavaMethod(String.class.getName(), "compareTo",
new Type[] { SimpleTypes.STRING }, SimpleTypes.INT,
new GetValue("x", SimpleTypes.STRING),
new Expression[] { new GetValue("y", SimpleTypes.STRING)}))Instanceof Comparisons
The InstanceofComparison is sort of a binary comparison in that it
takes two arguments, but at runtime it only has to determine the value
of one expression. The other argument is given in the constructor for
InstanceofComparison. Use Tests.EQ to test whether the item is an
instance of a particular class, and Tests.NE to test whether the
item is not an instance of a particular class.
For example, here is how to test whether local variable obj is a string:
new InstanceofComparison(Tests.EQ, new GetValue("obj", new ObjectType()),
String.class.getName())Boolean Expressions
There are three expressions that operate on one or two boolean expressions.
Not
The Not expression negates a boolean expression. For example, the
following two expressions are equivalent:
new BinaryComparison(Tests.NE, new GetValue("x", SimpleTypes.INT), new IntConstant(5))new Not(new BinaryComparison(Tests.EQ, new GetValue("x", SimpleTypes.INT), new IntConstant(5)))While the first expression is simpler, it turns out they will generate exactly the same code because JFuncMachine eliminates not expressions by inverting the boolean expression it contains. That is, in the second expression, it rewrites the expression to be exactly the same as the first expression
And
The And expression is true if both of its arguments are true. For example:
new And(new UnaryComparison(Tests.IsNotNull, new GetValue("obj", new ObjectType())),
new InstanceOfComparison(Tests.EQ, new GetValue("obj", new ObjectType()), "java.io.File"))Or
The Or expression is true if either of its arguments is true. For example:
new Or(new BinaryComparison(Tests.GT, new IntConstant(4), new IntConstant(5)),
new BinaryComparison(Tests.NE, new IntConstant(3), new IntConstant(7)))Example If Expression
Here is an If expression from a function that is computing a factorial:
new If(new BinaryComparison(Tests.LE, new GetValue("n", SimpleTypes.LONG),
new LongConstant(1)),
new GetValue("acc", SimpleTypes.LONG),
new CallMethod("fact", new Type[] { SimpleTypes.LONG, SimpleTypes.LONG},
SimpleTypes.LONG,
new GetValue("this", new ObjectType()),
new Expression[] {
new InlineCall(Inlines.LongSub, new Expression[] {
new GetValue("n", SimpleTypes.LONG),
new LongConstant(1)}),
new InlineCall(Inlines.LongMul, new Expression[] {
new GetValue("acc", SimpleTypes.LONG),
new GetValue("n", SimpleTypes.LONG)
})
})
));The equivalent Java code for the above expression is roughly:
if (n < 1) {
return acc;
} else {
this.fact(n-1, n * acc);
}