public static Equal ( |
||
left | An |
|
right | An |
|
return |
private static Expression <Func <T, bool> > PrimaryKeyEquals(PropertyInfo property, int value) { var param = Expression.Parameter(typeof(T)); var body = Expression.Equal(Expression.Property(param, property), Expression.Constant(value)); return(Expression.Lambda <Func <T, bool> >(body, param)); }
public void TestWhereComparison() { // Partial LINQ expression (x => x.Number1) var parameter = LinqExpression.Parameter(typeof(NumbersModel), "x"); var n1 = LinqExpression.Property(parameter, "Number1"); var l3 = new Func <int, bool>(n => n < 3); var le3 = new Func <int, bool>(n => n <= 3); var g6 = new Func <int, bool>(n => n > 6); var ge6 = new Func <int, bool>(n => n >= 6); var e7 = new Func <int, bool>(n => n == 7); var ne7 = new Func <int, bool>(n => n != 7); var cases = new[] { Tuple.Create((LinqExpression)LinqExpression.LessThan(n1, LinqExpression.Constant(3)), (Func <NumbersModel, object, bool>)TestWhereCompareValidator, (object)l3, parameter), Tuple.Create((LinqExpression)LinqExpression.LessThanOrEqual(n1, LinqExpression.Constant(3)), (Func <NumbersModel, object, bool>)TestWhereCompareValidator, (object)le3, parameter), Tuple.Create((LinqExpression)LinqExpression.GreaterThan(n1, LinqExpression.Constant(6)), (Func <NumbersModel, object, bool>)TestWhereCompareValidator, (object)g6, parameter), Tuple.Create((LinqExpression)LinqExpression.GreaterThanOrEqual(n1, LinqExpression.Constant(6)), (Func <NumbersModel, object, bool>)TestWhereCompareValidator, (object)ge6, parameter), Tuple.Create((LinqExpression)LinqExpression.Equal(n1, LinqExpression.Constant(7)), (Func <NumbersModel, object, bool>)TestWhereCompareValidator, (object)e7, parameter), Tuple.Create((LinqExpression)LinqExpression.NotEqual(n1, LinqExpression.Constant(7)), (Func <NumbersModel, object, bool>)TestWhereCompareValidator, (object)ne7, parameter) }; LoadModelNumbers(10); Db.Count.Should().Be(10); RunTestWithNumbers(new[] { 2, 3, 4, 5, 1, 9 }, cases); }
internal bool AddSplattedArgumentTest(object value, Expression /*!*/ expression, out int listLength, out ParameterExpression /*!*/ listVariable) { if (value == null) { AddRestriction(Ast.Equal(expression, Ast.Constant(null))); } else { // test exact type: AddTypeRestriction(value.GetType(), expression); List <object> list = value as List <object>; if (list != null) { Type type = typeof(List <object>); listLength = list.Count; listVariable = GetTemporary(type, "#list"); AddCondition(Ast.Equal( Ast.Property(Ast.Assign(listVariable, Ast.Convert(expression, type)), type.GetProperty("Count")), Ast.Constant(list.Count)) ); return(true); } } listLength = -1; listVariable = null; return(false); }
/// <summary> /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for /// Ruby method calls with a block given in arguments. /// /// Sets up a RFC frame similarly to MethodDeclaration. /// </summary> internal static void ApplyBlockFlowHandlingInternal(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { // TODO (improvement): // We don't special case null block here, although we could (we would need a test for that then). // We could also statically know (via call-site flag) that the current method is not a proc-converter (passed by ref), // which would make such calls faster. if (metaBuilder.Error || !args.Signature.HasBlock) { return; } Expression rfcVariable = metaBuilder.GetTemporary(typeof(RuntimeFlowControl), "#rfc"); ParameterExpression methodUnwinder = metaBuilder.GetTemporary(typeof(MethodUnwinder), "#unwinder"); Expression resultVariable = metaBuilder.GetTemporary(typeof(object), "#result"); metaBuilder.Result = Ast.Block( // initialize frame (RFC): Ast.Assign(rfcVariable, Methods.CreateRfcForMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))), AstUtils.Try( Ast.Assign(resultVariable, metaBuilder.Result) ).Filter(methodUnwinder, Ast.Equal(Ast.Field(methodUnwinder, MethodUnwinder.TargetFrameField), rfcVariable), // return unwinder.ReturnValue; Ast.Assign(resultVariable, Ast.Field(methodUnwinder, MethodUnwinder.ReturnValueField)) ).Finally( // we need to mark the RFC dead snce the block might escape and break later: Ast.Assign(Ast.Field(rfcVariable, RuntimeFlowControl.IsActiveMethodField), Ast.Constant(false)) ), resultVariable ); }
private Exp CheckIfZero(CompilerState state, Exp expression) { if (state == null) { throw new Exception(); } if (expression == null) { throw new Exception(); } if (expression.Type == typeof(int)) { var constructor = typeof(Exception).GetConstructor(new Type[] { typeof(string) }); return(Exp.Block( Exp.IfThen(Exp.Equal(expression, Exp.Constant(0)), Exp.Throw(Exp.New(constructor, Exp.Constant("Division by zero")))), expression)); } if (expression.Type == typeof(float)) { var constructor = typeof(Exception).GetConstructor(new Type[] { typeof(string) }); return(Exp.Block( Exp.IfThen(Exp.Equal(expression, Exp.Constant(0.0f)), Exp.Throw(Exp.New(constructor, Exp.Constant("Division by zero")))), expression)); } return(expression); }
/// <summary> /// Creates an expression tha defines an equality comparison /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <returns></returns> public static Expression <Func <bool> > Equal <X>(this Expression <Func <X> > left, Expression <Func <X> > right) { var lValue = XPR.Invoke(left); var rValue = XPR.Invoke(right); return(XPR.Lambda <Func <bool> >(XPR.Equal(lValue, rValue))); }
/// <summary> /// Implements Class#new feature. /// </summary> public void BuildObjectConstruction(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ methodName) { Debug.Assert(!IsSingletonClass, "Cannot instantiate singletons"); Type type = GetUnderlyingSystemType(); RubyMemberInfo initializer = ResolveMethod(Symbols.Initialize, true).InvalidateSitesOnOverride(); RubyMethodInfo overriddenInitializer = initializer as RubyMethodInfo; // check the version of this class to ensure the initializer won't be changed without rebuilding the site: metaBuilder.AddCondition( Ast.Equal(Ast.Property(Ast.Constant(this), RubyModule.VersionProperty), Ast.Constant(this.Version)) ); // Initializer is overridden => initializer is invoked on an uninitialized instance. // Is user class (defined in Ruby code) => construct it as if it had initializer that calls super immediately // (we need to "inherit" factories/constructors from the base class (e.g. class S < String; self; end.new('foo')). if (overriddenInitializer != null || (_isRubyClass && _structInfo == null)) { metaBuilder.Result = MakeAllocatorCall(args, () => Ast.Constant(Name)); if (overriddenInitializer != null || (_isRubyClass && initializer != null && !initializer.IsEmpty)) { BuildOverriddenInitializerCall(metaBuilder, args, initializer); } } else if (type.IsSubclassOf(typeof(Delegate))) { metaBuilder.Result = MakeDelegateConstructorCall(type, args); } else { MethodBase[] constructionOverloads; bool includeSelf; if (_structInfo != null) { constructionOverloads = new MethodBase[] { Methods.CreateStructInstance }; includeSelf = true; } else if (_factories != null) { constructionOverloads = (MethodBase[])ReflectionUtils.GetMethodInfos(_factories); includeSelf = true; } else { constructionOverloads = type.GetConstructors(); if (constructionOverloads.Length == 0) { throw RubyExceptions.CreateTypeError(String.Format("allocator undefined for {0}", Name)); } includeSelf = false; } RubyMethodGroupInfo.BuildCallNoFlow(metaBuilder, args, methodName, constructionOverloads, includeSelf, false); RubyMethodGroupInfo.ApplyBlockFlowHandlingInternal(metaBuilder, args); } }
public void MiscellaneousExpression_Block() { var variable = Expr.Variable(typeof(bool)); var block = Expr.Block(Expr.Assign(variable, Expr.Constant(true)), variable); UnsupportedExpr(Property.Active, active => Expr.Equal(active, block), ExpressionType.Block); }
public void CanConstantExpressionBeNull() { ConstantExpression c2 = Expression.Constant(null); ConstantExpression c1 = Expression.Constant(null); BinaryExpression a = Expression.Equal(c1, c2); Assert.Pass(); }
protected override Expression VisitMethodCall(MethodCallExpression expr) { switch (expr.Method.Name) { case "Any": CurrentCriterions.Add(GetExistsCriteria(expr)); break; case "StartsWith": CurrentCriterions.Add(GetLikeCriteria(expr, MatchMode.Start)); break; case "EndsWith": CurrentCriterions.Add(GetLikeCriteria(expr, MatchMode.End)); break; case "Contains": if (expr.Object == null) { if (expr.Arguments[0] is ConstantExpression) { CurrentCriterions.Add(GetCollectionContainsCriteria(expr.Arguments[0], expr.Arguments[1])); } else if (expr.Arguments[0] is CollectionAccessExpression) { CurrentCriterions.Add(GetCollectionContainsCriteria((CollectionAccessExpression)expr.Arguments[0], expr.Arguments[1])); } else { //myArray.Contains(user.Name) CurrentCriterions.Add(GetCollectionContainsCriteria(expr.Arguments[0], expr.Arguments[1])); } } else if (expr.Object is ConstantExpression) { //myList.Contains(user.Name) CurrentCriterions.Add(GetCollectionContainsCriteria(expr.Object, expr.Arguments[0])); } else if (expr.Object is CollectionAccessExpression) { //timesheet.Entries.Contains(entry) CurrentCriterions.Add(GetCollectionContainsCriteria((CollectionAccessExpression)expr.Object, expr.Arguments[0])); } else { //user.Name.Contains(partialName) CurrentCriterions.Add(GetLikeCriteria(expr, MatchMode.Anywhere)); } break; case "Equals": VisitBinaryCriterionExpression(Expression.Equal(expr.Object, expr.Arguments[0])); break; } return(expr); }
public void BinaryExpression_SubtractChecked() { ExecuteExpr(Property.Id, id => { var subtract = Expr.SubtractChecked(id, Expr.Constant(3)); return(Expr.Equal(subtract, Expr.Constant(2))); }, ExpressionType.SubtractChecked); }
public static Expression /*!*/ GetObjectTypeTestExpression(object value, Expression /*!*/ expression) { if (value == null) { return(Ast.Equal(expression, Ast.Constant(null))); } else { return(RuleBuilder.MakeTypeTestExpression(value.GetType(), expression)); } }
public void AddObjectTypeRestriction(object value, Expression /*!*/ expression) { if (value == null) { AddRestriction(Ast.Equal(expression, Ast.Constant(null))); } else { AddTypeRestriction(value.GetType(), expression); } }
/// <summary> /// 操作 /// </summary> /// <param name="left">左操作数</param> /// <param name="operator">运算符</param> /// <param name="value">值</param> public static MicrosoftExpression Operation(this MicrosoftExpression left, Operator @operator, object value) { return(@operator switch { Operator.Equal => left.Equal(value), Operator.NotEqual => left.NotEqual(value), Operator.Greater => left.Greater(value), Operator.GreaterEqual => left.GreaterEqual(value), Operator.Less => left.Less(value), Operator.LessEqual => left.LessEqual(value), Operator.Starts => left.StartsWith(value), Operator.Ends => left.EndsWith(value), Operator.Contains => left.Contains(value), _ => throw new NotImplementedException() });
public void TryCatchVariableBodyFilter() { var expected = LinqExpression.TryCatch( LinqExpression.Constant(0L), LinqExpression.Catch( LinqExpression.Parameter( typeof(Exception)), LinqExpression.Constant(0L), LinqExpression.Equal( LinqExpression.Constant(0L), LinqExpression.Constant(0L)))); using var g = new GraphEngine.Graph(); g.LoadFromString(@" @prefix : <http://example.com/> . @prefix xt: <http://example.com/ExpressionTypes/> . :s :tryBody _:zero ; :tryHandlers ( [ :catchVariable [ :parameterType [ :typeName ""System.Exception"" ; ] ; ] ; :catchBody _:zero ; :catchFilter [ :binaryExpressionType xt:Equal ; :binaryLeft _:zero ; :binaryRight _:zero ; ] ; ] ) ; . _:zero :constantValue 0 ; . "); var s = g.GetUriNode(":s"); var actual = Expression.Parse(s).LinqExpression; Console.WriteLine(actual.GetDebugView()); actual.Should().Be(expected); }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null || parameter == null) { return(null); } if (!value.GetType().IsEnum || !parameter.GetType().IsEnum) { return(null); } var flagsParam = Expression.Parameter(typeof(object), "flags"); var flagParam = Expression.Parameter(typeof(object), "flag"); var hasFlag = Expression.Equal(Expression.And(Expression.Convert(flagsParam, value.GetType()), Expression.Convert(flagParam, parameter.GetType())), flagParam); var expression = Expression.Lambda <Func <object, object, bool> >(hasFlag, flagsParam, flagParam); return(expression.Compile()(value, parameter) ? Visibility.Visible : Visibility.Collapsed); }
public void TestWhereArithmetic() { var parameter = LinqExpression.Parameter(typeof(NumbersModel), "x"); var n1 = LinqExpression.Property(parameter, "Number1"); var n2 = LinqExpression.Property(parameter, "Number2"); var m2g8 = new Func <int, int, bool>((x1, x2) => x1 * 2 > 8); var d2g3 = new Func <int, int, bool>((x1, x2) => x1 / 2 > 3); var m2e0 = new Func <int, int, bool>((x1, x2) => (x1 % 2) == 0); var a5g10 = new Func <int, int, bool>((x1, x2) => x1 + 5 > 10); var s5g0 = new Func <int, int, bool>((x1, x2) => x1 - 5 > 0); var mn2g10 = new Func <int, int, bool>((x1, x2) => x1 * x2 > 10); var dn1g3 = new Func <int, int, bool>((x1, x2) => x2 / x1 > 3); var mn2e0 = new Func <int, int, bool>((x1, x2) => (x1 % x2) == 0); var an2e10 = new Func <int, int, bool>((x1, x2) => x1 + x2 == 10); var sn2g0 = new Func <int, int, bool>((x1, x2) => x1 - x2 > 0); var cases = new[] { Tuple.Create((LinqExpression)LinqExpression.GreaterThan(LinqExpression.Multiply(n1, LinqExpression.Constant(2)), LinqExpression.Constant(8)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)m2g8, parameter), Tuple.Create((LinqExpression)LinqExpression.GreaterThan(LinqExpression.Divide(n1, LinqExpression.Constant(2)), LinqExpression.Constant(3)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)d2g3, parameter), Tuple.Create((LinqExpression)LinqExpression.Equal(LinqExpression.Modulo(n1, LinqExpression.Constant(2)), LinqExpression.Constant(0)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)m2e0, parameter), Tuple.Create((LinqExpression)LinqExpression.GreaterThan(LinqExpression.Add(n1, LinqExpression.Constant(5)), LinqExpression.Constant(10)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)a5g10, parameter), Tuple.Create((LinqExpression)LinqExpression.GreaterThan(LinqExpression.Subtract(n1, LinqExpression.Constant(5)), LinqExpression.Constant(0)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)s5g0, parameter), Tuple.Create((LinqExpression)LinqExpression.GreaterThan(LinqExpression.Multiply(n1, n2), LinqExpression.Constant(10)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)mn2g10, parameter), Tuple.Create((LinqExpression)LinqExpression.GreaterThan(LinqExpression.Divide(n2, n1), LinqExpression.Constant(3)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)dn1g3, parameter), Tuple.Create((LinqExpression)LinqExpression.Equal(LinqExpression.Modulo(n1, n2), LinqExpression.Constant(0)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)mn2e0, parameter), Tuple.Create((LinqExpression)LinqExpression.Equal(LinqExpression.Add(n1, n2), LinqExpression.Constant(10)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)an2e10, parameter), Tuple.Create((LinqExpression)LinqExpression.GreaterThan(LinqExpression.Subtract(n1, n2), LinqExpression.Constant(0)), (Func <NumbersModel, object, bool>)TestWhereMathValidator, (object)sn2g0, parameter) }; LoadModelNumbers(10); RunTestWithNumbers(new[] { 6, 3, 5, 5, 5, 7, 2, 3, 10, 5 }, cases); }
public static TEntity LastOrNullBy <TEntity, TValue>(this IQueryable <TEntity> query, Expression <Func <TEntity, TValue> > keyFieldPredicate) { if (keyFieldPredicate == null) { throw new ArgumentNullException(nameof(keyFieldPredicate)); } var p = keyFieldPredicate.Parameters.Single(); if (query.LongCount() == 0) { return(default(TEntity)); } var max = query.Max(keyFieldPredicate); var equalsOne = (Expression)Expression.Equal(keyFieldPredicate.Body, Expression.Constant(max, typeof(TValue))); return(query.Single(Expression.Lambda <Func <TEntity, bool> >(equalsOne, p))); }
public static Expression CreateLambdaExpression <T, TModel>(IEnumerable <FilterElement> filterElements, Type querytype, ParameterExpression arg) { Expression expression = Expression.Constant(true); foreach (var filterElement in filterElements) { string[] props = filterElement.FilterSpecs.DataElement.Split('.'); Expression propertyExpression = arg; var type = typeof(T); Expression notNullExpression = Expression.Constant(true); foreach (var property in props) { PropertyInfo pi = type.GetProperty(property); propertyExpression = Expression.Property(propertyExpression, pi); var nullExpression = Expression.Constant(GetNullExpressionForType(pi.PropertyType), pi.PropertyType); notNullExpression = Expression.AndAlso(notNullExpression, Expression.NotEqual(propertyExpression, nullExpression)); type = pi.PropertyType; } var isLiteralType = type.IsEquivalentTo(typeof(string)); var valueExpression = Expression.Constant(filterElement.FieldValue, filterElement.Property.PropertyType); Expression inputExpression, variableExpression; if (filterElement.FilterSpecs.CaseSensitive && isLiteralType) { variableExpression = Expression.Call(propertyExpression, typeof(String).GetMethod("ToUpper", new Type[] { })); inputExpression = Expression.Call(valueExpression, typeof(String).GetMethod("ToUpper", new Type[] { })); } else { // special case to handle nullable values if (valueExpression.Type.IsNullable()) { valueExpression = Expression.Constant(valueExpression.Value, filterElement.Property.PropertyType.NullableOf()); } inputExpression = valueExpression; variableExpression = propertyExpression; } BinaryExpression conditionExpression = Expression.Equal(variableExpression, valueExpression); switch (filterElement.FilterSpecs.OperatorOption) { case Operator.Equal: conditionExpression = Expression.Equal(variableExpression, inputExpression); break; case Operator.GreaterThan: conditionExpression = Expression.GreaterThan(variableExpression, inputExpression); break; case Operator.GreaterThanOrEqualTo: conditionExpression = Expression.GreaterThanOrEqual(variableExpression, inputExpression); break; case Operator.LessThan: conditionExpression = Expression.LessThan(variableExpression, inputExpression); break; case Operator.LessThanOrEqualTo: conditionExpression = Expression.LessThanOrEqual(variableExpression, inputExpression); break; case Operator.Unequal: conditionExpression = Expression.NotEqual(variableExpression, inputExpression); break; case Operator.Like: MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); var containsMethodCall = Expression.Call(variableExpression, method, inputExpression); conditionExpression = Expression.Equal(containsMethodCall, Expression.Constant(true)); break; } var clausePart = Expression.AndAlso(notNullExpression, conditionExpression); if (!filterElement.FieldValue.Equals(GetNullExpressionForType(filterElement.Property.PropertyType))) { expression = Expression.AndAlso(expression, clausePart); } } return(expression); }
public void UnaryExpression_Unbox() => ExecuteExpr(Property.LastUp, lastUp => { var unbox = Expr.Unbox(Expr.Convert(lastUp, typeof(object)), typeof(DateTime)); return(Expr.Equal(unbox, Expr.Constant(new DateTime(2000, 10, 2, 12, 10, 5, DateTimeKind.Utc)))); }, ExpressionType.Unbox, "filter_lastup=36801.5070023148");
public void UnaryExpression_IsFalse() => ExecuteExpr(Property.Active, active => Expr.Equal(active, Expr.IsFalse(Expr.Constant(false))), ExpressionType.IsFalse, "filter_active=-1");
protected void ExecuteBinaryExpr(Property property, Func <Expr, Expr> expr, ExpressionType nodeType, string url = "") { ExecuteExpr(property, v => Expr.Equal(expr(v), Expr.Constant(3)), nodeType, url); }
// TODO: do not test runtime for runtime bound sites // TODO: ResolveMethod invalidates modules that were not initialized yet -> snapshot version after method resolution // TODO: thread safety: synchronize version snapshot and method resolution public void AddTargetTypeTest(object target, Expression /*!*/ targetParameter, RubyContext /*!*/ context, Expression /*!*/ contextExpression) { // singleton nil: if (target == null) { AddRestriction(Ast.Equal(targetParameter, Ast.Constant(null))); context.NilClass.AddFullVersionTest(this, contextExpression); return; } // singletons true, false: if (target is bool) { AddRestriction(Ast.AndAlso( Ast.TypeIs(targetParameter, typeof(bool)), Ast.Equal(Ast.Convert(targetParameter, typeof(bool)), Ast.Constant(target)) )); if ((bool)target) { context.TrueClass.AddFullVersionTest(this, contextExpression); } else { context.FalseClass.AddFullVersionTest(this, contextExpression); } return; } RubyClass immediateClass = context.GetImmediateClassOf(target); // user defined instance singletons, modules, classes: if (immediateClass.IsSingletonClass) { AddRestriction( Ast.Equal( Ast.Convert(targetParameter, typeof(object)), Ast.Convert(Ast.Constant(target), typeof(object)) ) ); // we need to check for a runtime (e.g. "foo" .NET string instance could be shared accross runtimes): immediateClass.AddFullVersionTest(this, contextExpression); return; } Type type = target.GetType(); AddTypeRestriction(type, targetParameter); if (typeof(IRubyObject).IsAssignableFrom(type)) { // Ruby objects (get the method directly to prevent interface dispatch): MethodInfo classGetter = type.GetMethod("get_" + RubyObject.ClassPropertyName, BindingFlags.Public | BindingFlags.Instance); if (classGetter != null && classGetter.ReturnType == typeof(RubyClass)) { AddCondition( // (#{type})target.Class.Version == #{immediateClass.Version} Ast.Equal( Ast.Call(Ast.Call(Ast.Convert(targetParameter, type), classGetter), RubyModule.VersionProperty.GetGetMethod()), Ast.Constant(immediateClass.Version) ) ); return; } // TODO: explicit iface-implementation throw new NotSupportedException("Type implementing IRubyObject should have RubyClass getter"); } else { // CLR objects: immediateClass.AddFullVersionTest(this, contextExpression); } }
protected void UnsupportedBinaryExpr(Property property, Func <Expr, Expr> expr, ExpressionType nodeType) { UnsupportedExpr(property, v => Expr.Equal(expr(v), Expr.Constant(3)), nodeType); }
public static Ex Eq(this Ex me, Ex other) => Ex.Equal(me, other);
private BinaryExpression BinaryExpression( ExpressionType nodeType, System.Type type, JObject obj) { var left = this.Prop(obj, "left", this.Expression); var right = this.Prop(obj, "right", this.Expression); var method = this.Prop(obj, "method", this.Method); var conversion = this.Prop(obj, "conversion", this.LambdaExpression); var liftToNull = this.Prop(obj, "liftToNull").Value <bool>(); switch (nodeType) { case ExpressionType.Add: return(Expr.Add(left, right, method)); case ExpressionType.AddAssign: return(Expr.AddAssign(left, right, method, conversion)); case ExpressionType.AddAssignChecked: return(Expr.AddAssignChecked(left, right, method, conversion)); case ExpressionType.AddChecked: return(Expr.AddChecked(left, right, method)); case ExpressionType.And: return(Expr.And(left, right, method)); case ExpressionType.AndAlso: return(Expr.AndAlso(left, right, method)); case ExpressionType.AndAssign: return(Expr.AndAssign(left, right, method, conversion)); case ExpressionType.ArrayIndex: return(Expr.ArrayIndex(left, right)); case ExpressionType.Assign: return(Expr.Assign(left, right)); case ExpressionType.Coalesce: return(Expr.Coalesce(left, right, conversion)); case ExpressionType.Divide: return(Expr.Divide(left, right, method)); case ExpressionType.DivideAssign: return(Expr.DivideAssign(left, right, method, conversion)); case ExpressionType.Equal: return(Expr.Equal(left, right, liftToNull, method)); case ExpressionType.ExclusiveOr: return(Expr.ExclusiveOr(left, right, method)); case ExpressionType.ExclusiveOrAssign: return(Expr.ExclusiveOrAssign(left, right, method, conversion)); case ExpressionType.GreaterThan: return(Expr.GreaterThan(left, right, liftToNull, method)); case ExpressionType.GreaterThanOrEqual: return(Expr.GreaterThanOrEqual(left, right, liftToNull, method)); case ExpressionType.LeftShift: return(Expr.LeftShift(left, right, method)); case ExpressionType.LeftShiftAssign: return(Expr.LeftShiftAssign(left, right, method, conversion)); case ExpressionType.LessThan: return(Expr.LessThan(left, right, liftToNull, method)); case ExpressionType.LessThanOrEqual: return(Expr.LessThanOrEqual(left, right, liftToNull, method)); case ExpressionType.Modulo: return(Expr.Modulo(left, right, method)); case ExpressionType.ModuloAssign: return(Expr.ModuloAssign(left, right, method, conversion)); case ExpressionType.Multiply: return(Expr.Multiply(left, right, method)); case ExpressionType.MultiplyAssign: return(Expr.MultiplyAssign(left, right, method, conversion)); case ExpressionType.MultiplyAssignChecked: return(Expr.MultiplyAssignChecked(left, right, method, conversion)); case ExpressionType.MultiplyChecked: return(Expr.MultiplyChecked(left, right, method)); case ExpressionType.NotEqual: return(Expr.NotEqual(left, right, liftToNull, method)); case ExpressionType.Or: return(Expr.Or(left, right, method)); case ExpressionType.OrAssign: return(Expr.OrAssign(left, right, method, conversion)); case ExpressionType.OrElse: return(Expr.OrElse(left, right, method)); case ExpressionType.Power: return(Expr.Power(left, right, method)); case ExpressionType.PowerAssign: return(Expr.PowerAssign(left, right, method, conversion)); case ExpressionType.RightShift: return(Expr.RightShift(left, right, method)); case ExpressionType.RightShiftAssign: return(Expr.RightShiftAssign(left, right, method, conversion)); case ExpressionType.Subtract: return(Expr.Subtract(left, right, method)); case ExpressionType.SubtractAssign: return(Expr.SubtractAssign(left, right, method, conversion)); case ExpressionType.SubtractAssignChecked: return(Expr.SubtractAssignChecked(left, right, method, conversion)); case ExpressionType.SubtractChecked: return(Expr.SubtractChecked(left, right, method)); default: throw new NotSupportedException(); } }
/// <summary> /// 创建等于运算表达式 /// </summary> /// <param name="left">左操作数</param> /// <param name="value">值</param> public static MicrosoftExpression Equal(this MicrosoftExpression left, object value) { return(left.Equal(Lambda.Constant(value, left))); }
/// <summary> /// 创建等于运算表达式 /// </summary> /// <param name="left">左操作数</param> /// <param name="right">右操作数</param> public static MicrosoftExpression Equal(this MicrosoftExpression left, MicrosoftExpression right) { return(MicrosoftExpression.Equal(left, right)); }
internal void SetRule(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { Assert.NotNull(metaBuilder, args); Debug.Assert(args.SimpleArgumentCount == 0 && !args.Signature.HasBlock && !args.Signature.HasSplattedArgument && !args.Signature.HasRhsArgument); Debug.Assert(args.Signature.HasScope); var ec = args.RubyContext; // implicit conversions should only depend on a static type: if (TryImplicitConversion(metaBuilder, args)) { if (args.Target == null) { metaBuilder.AddRestriction(Ast.Equal(args.TargetExpression, Ast.Constant(null, args.TargetExpression.Type))); } else { metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression); } return; } // check for type version: metaBuilder.AddTargetTypeTest(args); string toMethodName = ToMethodName; Expression targetClassNameConstant = Ast.Constant(ec.GetClassOf(args.Target).Name); // Kernel#respond_to? method is not overridden => we can optimize RubyMemberInfo respondToMethod = ec.ResolveMethod(args.Target, Symbols.RespondTo, true).InvalidateSitesOnOverride(); if (respondToMethod == null || // the method is defined in library, hasn't been replaced by user defined method (TODO: maybe we should make this check better) (respondToMethod.DeclaringModule == ec.KernelModule && respondToMethod is RubyMethodGroupInfo)) { RubyMemberInfo conversionMethod = ec.ResolveMethod(args.Target, toMethodName, false).InvalidateSitesOnOverride(); if (conversionMethod == null) { // error: SetError(metaBuilder, targetClassNameConstant, args); return; } else { // invoke target.to_xxx() and validate it; returns an instance of TTargetType: conversionMethod.BuildCall(metaBuilder, args, toMethodName); if (!metaBuilder.Error && ConversionResultValidator != null) { metaBuilder.Result = ConversionResultValidator.OpCall(targetClassNameConstant, AstFactory.Box(metaBuilder.Result)); } return; } } else if (!RubyModule.IsMethodVisible(respondToMethod, false)) { // respond_to? is private: SetError(metaBuilder, targetClassNameConstant, args); return; } // slow path: invoke respond_to?, to_xxx and result validation: var conversionCallSite = Ast.Dynamic( RubyCallAction.Make(toMethodName, RubyCallSignature.WithScope(0)), typeof(object), args.ScopeExpression, args.TargetExpression ); Expression opCall; metaBuilder.Result = Ast.Condition( // If // respond_to?() Methods.IsTrue.OpCall( Ast.Dynamic( RubyCallAction.Make(Symbols.RespondTo, RubyCallSignature.WithScope(1)), typeof(object), args.ScopeExpression, args.TargetExpression, Ast.Constant(SymbolTable.StringToId(toMethodName)) ) ), // Then // to_xxx(): opCall = (ConversionResultValidator == null) ? conversionCallSite : ConversionResultValidator.OpCall(targetClassNameConstant, conversionCallSite), // Else AstUtils.Convert( (ConversionResultValidator == null) ? args.TargetExpression : Ast.Convert( Ast.Throw(Methods.CreateTypeConversionError.OpCall(targetClassNameConstant, Ast.Constant(TargetTypeName))), typeof(object) ), opCall.Type ) ); }
public static Expression[] /*!*/ MakeActualArgs(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool includeSelf, bool selfIsInstance, bool calleeHasBlockParam, bool injectMissingBlockParam) { var actualArgs = new List <Expression>(args.ExplicitArgumentCount); // self (instance): if (includeSelf && selfIsInstance) { // test already added by method resolver Debug.Assert(args.TargetExpression != null); AddArgument(actualArgs, args.Target, args.TargetExpression); } Proc block = null; Expression blockExpression = null; // block test - we need to test for a block regardless of whether it is actually passed to the method or not // since the information that the block is not null is used for overload resolution. if (args.Signature.HasBlock) { block = args.GetBlock(); blockExpression = args.GetBlockExpression(); if (block == null) { metaBuilder.AddRestriction(Ast.Equal(blockExpression, Ast.Constant(null))); } else { // don't need to test the exact type of the Proc since the code is subclass agnostic: metaBuilder.AddRestriction(Ast.NotEqual(blockExpression, Ast.Constant(null))); } } // block: if (calleeHasBlockParam) { if (args.Signature.HasBlock) { if (block == null) { // the user explicitly passed nil as a block arg: actualArgs.Add(Ast.Constant(null)); } else { // pass BlockParam: Debug.Assert(metaBuilder.BfcVariable != null); actualArgs.Add(metaBuilder.BfcVariable); } } else { // no block passed into a method with a BlockParam: actualArgs.Add(Ast.Constant(null)); } } else if (injectMissingBlockParam) { // no block passed into a method w/o a BlockParam (we still need to fill the missing block argument): actualArgs.Add(Ast.Constant(null)); } // self (non-instance): if (includeSelf && !selfIsInstance) { // test already added by method resolver AddArgument(actualArgs, args.Target, args.TargetExpression); } // simple arguments: for (int i = 0; i < args.SimpleArgumentCount; i++) { var value = args.GetSimpleArgument(i); var expr = args.GetSimpleArgumentExpression(i); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } // splat argument: int listLength; ParameterExpression listVariable; if (args.Signature.HasSplattedArgument) { object splattedArg = args.GetSplattedArgument(); Expression splattedArgExpression = args.GetSplattedArgumentExpression(); if (metaBuilder.AddSplattedArgumentTest(splattedArg, splattedArgExpression, out listLength, out listVariable)) { // AddTestForListArg only returns 'true' if the argument is a List<object> var list = (List <object>)splattedArg; // get arguments, add tests for (int j = 0; j < listLength; j++) { var value = list[j]; var expr = Ast.Call(listVariable, typeof(List <object>).GetMethod("get_Item"), Ast.Constant(j)); metaBuilder.AddObjectTypeCondition(value, expr); AddArgument(actualArgs, value, expr); } } else { // argument is not an array => add the argument itself: AddArgument(actualArgs, splattedArg, splattedArgExpression); } } // rhs argument: if (args.Signature.HasRhsArgument) { var value = args.GetRhsArgument(); var expr = args.GetRhsArgumentExpression(); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } return(actualArgs.ToArray()); }