case ExpressionType.Coalesce:
EmitCoalesce (ec);
return;
+
+ case ExpressionType.Power:
+ left.Emit (ec);
+ right.Emit (ec);
+ ig.Emit (OpCodes.Call, typeof (System.Math).GetMethod ("Pow"));
+ return;
}
Label? empty_value = null;
opcode = OpCodes.Xor;
break;
- case ExpressionType.Coalesce:
- case ExpressionType.Equal:
case ExpressionType.GreaterThan:
+ if (is_unsigned)
+ opcode = OpCodes.Cgt_Un;
+ else
+ opcode = OpCodes.Cgt;
+ break;
+
case ExpressionType.GreaterThanOrEqual:
+ Type le = left.Type;
+
+ if (is_unsigned || (le == typeof (double) || le == typeof (float)))
+ ig.Emit (OpCodes.Clt_Un);
+ else
+ ig.Emit (OpCodes.Clt);
+
+ ig.Emit (OpCodes.Ldc_I4_0);
+
+ opcode = OpCodes.Ceq;
+ break;
+
case ExpressionType.LessThan:
+ if (is_unsigned)
+ opcode = OpCodes.Clt_Un;
+ else
+ opcode = OpCodes.Clt;
+ break;
+
case ExpressionType.LessThanOrEqual:
+ Type lt = left.Type;
+
+ if (is_unsigned || (lt == typeof (double) || lt == typeof (float)))
+ ig.Emit (OpCodes.Cgt_Un);
+ else
+ ig.Emit (OpCodes.Cgt);
+ ig.Emit (OpCodes.Ldc_I4_0);
+
+ opcode = OpCodes.Ceq;
+ break;
+
+ case ExpressionType.Equal:
+ opcode = OpCodes.Ceq;
+ break;
+
case ExpressionType.NotEqual:
- case ExpressionType.Power:
- throw new NotImplementedException (String.Format ("No support for {0} node yet", NodeType));
-
+ ig.Emit (OpCodes.Ceq);
+ ig.Emit (OpCodes.Ldc_I4_0);
+
+ opcode = OpCodes.Ceq;
+ break;
+
default:
throw new Exception (String.Format ("Internal error: BinaryExpression contains non-Binary nodetype {0}", NodeType));
}
ig.Emit (opcode);
-
+
if (IsLifted){
ig.Emit (OpCodes.Newobj, left.Type.GetConstructors ()[0]);
-
+
Label skip = ig.DefineLabel ();
ig.Emit (OpCodes.Br_S, skip);
ig.MarkLabel (empty_value.Value);
Things missing:
+ *** Add support for MethodInfos ** and the nullable stuff, I believe
+ we have to pull the values before calling the various
+ MethodINfos in BinaryExpression, need to write test
+
Coalesce's conversion, what is this used for?
Constant generation of objects, how are those Constants in the first place?
Try:
OrElse (Constant (new Boo(), new Boo ()))
-Binary missing:
- case ExpressionType.Coalesce:
- case ExpressionType.Equal:
- case ExpressionType.GreaterThan:
- case ExpressionType.GreaterThanOrEqual:
- case ExpressionType.LessThan:
- case ExpressionType.LessThanOrEqual:
- case ExpressionType.NotEqual:
- case ExpressionType.Power:
-
Tests missing:
Must write tests for all the codepaths currently in
BinaryExpression.Emit (specially the XXXChecked variants as
those so far have shown most of the problems).
+
+ Write tests for stuff using MethodInfos (the various
+ BinaryExpressions using MEthodInfos have been barely tested).
+
+ Write more tests using nullables, currently we are short on
+ them, and they are not extensively tested.
+
Missing:
Add, Subtract, Multiply, Divide, Modulo, <<, >> And, Or, Xor
Expression.GreaterThan (Expression.Constant (true), Expression.Constant (false));
}
+ [Test]
+ [ExpectedException (typeof (InvalidOperationException))]
+ public void StringS ()
+ {
+ Expression.GreaterThan (Expression.Constant (""), Expression.Constant (""));
+ }
+
[Test]
public void UserDefinedClass ()
{
Assert.AreEqual ("op_GreaterThan", expr.Method.Name);
Assert.AreEqual ("(value(MonoTests.System.Linq.Expressions.OpClass) > value(MonoTests.System.Linq.Expressions.OpClass))", expr.ToString ());
}
+
+ [Test]
+ public void TestCompiled ()
+ {
+ ParameterExpression a = Expression.Parameter(typeof(int), "a");
+ ParameterExpression b = Expression.Parameter(typeof(int), "b");
+
+ BinaryExpression p = Expression.GreaterThan (a, b);
+
+ Expression<Func<int,int,bool>> pexpr = Expression.Lambda<Func<int,int,bool>> (
+ p, new ParameterExpression [] { a, b });
+
+ Func<int,int,bool> compiled = pexpr.Compile ();
+ Assert.AreEqual (true, compiled (10, 1), "tc1");
+ Assert.AreEqual (true, compiled (1, 0), "tc2");
+ Assert.AreEqual (true, compiled (Int32.MinValue+1, Int32.MinValue), "tc3");
+ Assert.AreEqual (false, compiled (-1, 0), "tc4");
+ Assert.AreEqual (false, compiled (0, Int32.MaxValue), "tc5");
+ }
}
}
Assert.AreEqual (100.0/3, CodeGen<double> ((a, b) => Expression.Divide (a, b), 100, 3));
}
+ void CTest<T> (ExpressionType node, bool r, T a, T b)
+ {
+ ParameterExpression pa = Expression.Parameter(typeof(T), "a");
+ ParameterExpression pb = Expression.Parameter(typeof(T), "b");
+
+ BinaryExpression p = Expression.MakeBinary (node, Expression.Constant (a), Expression.Constant(b));
+ Expression<Func<T,T,bool>> pexpr = Expression.Lambda<Func<T,T,bool>> (
+ p, new ParameterExpression [] { pa, pb });
+
+ Func<T,T,bool> compiled = pexpr.Compile ();
+ Assert.AreEqual (r, compiled (a, b), String.Format ("{0} ({1},{2}) == {3}", node, a, b, r));
+ }
+
+ [Test]
+ public void ComparisonTests ()
+ {
+ ExpressionType t = ExpressionType.Equal;
+
+ CTest<byte> (t, true, 10, 10);
+ CTest<sbyte> (t, false, 1, 5);
+ CTest<sbyte> (t, true, 1, 1);
+ CTest<int> (t, true, 1, 1);
+ CTest<double> (t, true, 1.0, 1.0);
+ CTest<string> (t, true, "", "");
+ CTest<string> (t, true, "Hey", "Hey");
+ CTest<string> (t, false, "Hey", "There");
+
+ t = ExpressionType.NotEqual;
+
+ CTest<byte> (t, false, 10, 10);
+ CTest<sbyte> (t, true, 1, 5);
+ CTest<sbyte> (t, false, 1, 1);
+ CTest<int> (t, false, 1, 1);
+ CTest<double> (t, false, 1.0, 1.0);
+ CTest<double> (t, false, 1.0, 1.0);
+ CTest<string> (t, false, "", "");
+ CTest<string> (t, false, "Hey", "Hey");
+ CTest<string> (t, true, "Hey", "There");
+
+ t = ExpressionType.GreaterThan;
+ CTest<byte> (t, true, 5, 1);
+ CTest<byte> (t, false, 10, 10);
+ CTest<sbyte> (t, false, 1, 5);
+ CTest<sbyte> (t, false, 1, 1);
+ CTest<int> (t, false, 1, 1);
+ CTest<uint> (t, true, 1, 0);
+ CTest<ulong> (t, true, Int64.MaxValue, 0);
+ CTest<double> (t, false, 1.0, 1.0);
+ CTest<double> (t, false, 1.0, 1.0);
+
+
+ t = ExpressionType.LessThan;
+ CTest<byte> (t, false, 5, 1);
+ CTest<byte> (t, false, 10, 10);
+ CTest<sbyte> (t, true, 1, 5);
+ CTest<sbyte> (t, false, 1, 1);
+ CTest<int> (t, false, 1, 1);
+ CTest<uint> (t, false, 1, 0);
+ CTest<ulong> (t, false, Int64.MaxValue, 0);
+ CTest<double> (t, false, 1.0, 1.0);
+ CTest<double> (t, false, 1.0, 1.0);
+
+ t = ExpressionType.GreaterThanOrEqual;
+ CTest<byte> (t, true, 5, 1);
+ CTest<byte> (t, true, 10, 10);
+ CTest<sbyte> (t, false, 1, 5);
+ CTest<sbyte> (t, true, 1, 1);
+ CTest<int> (t, true, 1, 1);
+ CTest<uint> (t, true, 1, 0);
+ CTest<ulong> (t, true, Int64.MaxValue, 0);
+ CTest<double> (t, true, 1.0, 1.0);
+ CTest<double> (t, true, 1.0, 1.0);
+
+
+ t = ExpressionType.LessThanOrEqual;
+ CTest<byte> (t, false, 5, 1);
+ CTest<byte> (t, true, 10, 10);
+ CTest<sbyte> (t, true, 1, 5);
+ CTest<sbyte> (t, true, 1, 1);
+ CTest<int> (t, true, 1, 1);
+ CTest<uint> (t, false, 1, 0);
+ CTest<ulong> (t, false, Int64.MaxValue, 0);
+ CTest<double> (t, true, 1.0, 1.0);
+ CTest<double> (t, true, 1.0, 1.0);
+
+ }
+
}
}
[Test]
public void ArgTypesFloat_OK ()
{
- Expression.Power (Expression.Constant (1.0), Expression.Constant (2.0));
- }
-
-#if false
- [Test]
- [ExpectedException (typeof (InvalidOperationException))]
- public void NoOperatorClass ()
- {
- Expression.Subtract (Expression.Constant (new NoOpClass ()), Expression.Constant (new NoOpClass ()));
- }
-
- [Test]
- public void Nullable ()
- {
- int? a = 1;
- int? b = 2;
+ BinaryExpression p = Expression.Power (Expression.Constant (1.0), Expression.Constant (2.0));
- BinaryExpression expr = Expression.Subtract (Expression.Constant (a), Expression.Constant (b));
- Assert.AreEqual (ExpressionType.Subtract, expr.NodeType, "Subtract#05");
- Assert.AreEqual (typeof (int), expr.Type, "Subtract#06");
- Assert.IsNull (expr.Method, "Subtract#07");
- Assert.AreEqual ("(1 - 2)", expr.ToString(), "Subtract#08");
+ Assert.AreEqual (ExpressionType.Power, p.NodeType, "Power#01");
+ Assert.AreEqual (typeof (double), p.Type, "Add#02");
}
[Test]
- public void UserDefinedClass ()
+ public void TestCompile ()
{
- // We can use the simplest version of GetMethod because we already know only one
- // exists in the very simple class we're using for the tests.
- MethodInfo mi = typeof (OpClass).GetMethod ("op_Subtraction");
-
- BinaryExpression expr = Expression.Subtract (Expression.Constant (new OpClass ()), Expression.Constant (new OpClass ()));
- Assert.AreEqual (ExpressionType.Subtract, expr.NodeType, "Subtract#09");
- Assert.AreEqual (typeof (OpClass), expr.Type, "Subtract#10");
- Assert.AreEqual (mi, expr.Method, "Subtract#11");
- Assert.AreEqual ("op_Subtraction", expr.Method.Name, "Subtract#12");
- Assert.AreEqual ("(value(MonoTests.System.Linq.Expressions.OpClass) - value(MonoTests.System.Linq.Expressions.OpClass))",
- expr.ToString(), "Subtract#13");
+ ParameterExpression a = Expression.Parameter(typeof(double), "a");
+ ParameterExpression b = Expression.Parameter(typeof(double), "b");
+ BinaryExpression p = Expression.Power (a, b);
+
+ Expression<Func<double,double,double>> pexpr = Expression.Lambda<Func<double,double,double>> (p, new ParameterExpression [] { a, b });
+ Func<double,double,double> compiled = pexpr.Compile ();
+ Assert.AreEqual (1, compiled (1, 10));
+ Assert.AreEqual (16, compiled (2, 4));
}
-#endif
+
}
}