public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) { ContractUtils.RequiresNotNull(binder, nameof(binder)); ContractUtils.RequiresNotNull(value, nameof(value)); var originalClass = GetClassEnsureIndex(binder.Name, binder.IgnoreCase, Value !, out var @class, out var index); return(AddDynamicTestAndDefer ( binder, @class, originalClass, new DynamicMetaObject ( Expression.Call ( _expandoTrySetValue, GetLimitedSelf(), Expression.Constant(@class, typeof(object)), AstUtils.Constant(index), Expression.Convert(value.Expression, typeof(object)), Expression.Constant(binder.Name), AstUtils.Constant(binder.IgnoreCase) ), BindingRestrictions.Empty ) )); }
public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) { ArgumentNullException.ThrowIfNull(binder); ArgumentNullException.ThrowIfNull(value); ExpandoClass klass; int index; ExpandoClass?originalClass = GetClassEnsureIndex(binder.Name, binder.IgnoreCase, Value, out klass, out index); return(AddDynamicTestAndDefer( binder, klass, originalClass, new DynamicMetaObject( Expression.Call( s_expandoTrySetValue, GetLimitedSelf(), Expression.Constant(klass, typeof(object)), AstUtils.Constant(index), Expression.Convert(value.Expression, typeof(object)), Expression.Constant(binder.Name), AstUtils.Constant(binder.IgnoreCase) ), BindingRestrictions.Empty ) )); }
public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) { ContractUtils.RequiresNotNull(binder, nameof(binder)); // Value can be null, let it true if it is var index = Value !.Class.GetValueIndex(binder.Name, binder.IgnoreCase, Value); Expression tryDelete = Expression.Call ( _expandoTryDeleteValue, GetLimitedSelf(), Expression.Constant(Value.Class, typeof(object)), AstUtils.Constant(index), Expression.Constant(binder.Name), AstUtils.Constant(binder.IgnoreCase) ); var fallback = binder.FallbackDeleteMember(this); var target = new DynamicMetaObject ( Expression.IfThen(Expression.Not(tryDelete), fallback.Expression), fallback.Restrictions ); return(AddDynamicTestAndDefer(binder, Value.Class, null, target)); }
private Expression ReduceConstantTypeEqual() { ConstantExpression?ce = Expression as ConstantExpression; //TypeEqual(null, T) always returns false. if (ce !.Value == null) { return(Utils.Constant(value: false)); }
private Expression ReduceConstantTypeEqual() { if (Expression is ConstantExpression ce && ce.Value != null) { return(Utils.Constant(TypeOperand.GetNonNullable() == ce.Value.GetType())); } return(Utils.Constant(false)); }
internal Expression ReduceTypeEqual() { Type cType = Expression.Type; if (cType.IsValueType || TypeOperand.IsPointer) { if (cType.IsNullableType()) { // If the expression type is a nullable type, it will match if // the value is not null and the type operand // either matches or is its type argument (T to its T?). if (cType.GetNonNullableType() != TypeOperand.GetNonNullableType()) { return(Expression.Block(Expression, Utils.Constant(value: false))); } else { return(Expression.NotEqual(Expression, Expression.Constant(null, Expression.Type))); } } else { // For other value types (including Void), we can // determine the result now return(Expression.Block(Expression, Utils.Constant(cType == TypeOperand.GetNonNullableType()))); } } Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(object), Expression.Type), "Expecting reference types only after this point."); // Can check the value right now for constants. if (Expression.NodeType == ExpressionType.Constant) { return(ReduceConstantTypeEqual()); } // expression is a ByVal parameter. Can safely reevaluate. var parameter = Expression as ParameterExpression; if (parameter != null && !parameter.IsByRef) { return(ByValParameterTypeEqual(parameter)); } // Create a temp so we only evaluate the left side once parameter = Expression.Parameter(typeof(object)); return(Expression.Block( new TrueReadOnlyCollection <ParameterExpression>(parameter), new TrueReadOnlyCollection <Expression>( Expression.Assign(parameter, Expression), ByValParameterTypeEqual(parameter) ) )); }
private Expression ReduceConstantTypeEqual() { ConstantExpression ce = Expression as ConstantExpression; //TypeEqual(null, T) always returns false. // ReSharper disable once PossibleNullReferenceException if (ce.Value == null) { return(Utils.Constant(value: false)); } return(Utils.Constant(TypeOperand.GetNonNullable() == ce.Value.GetType())); }
private Expression ReduceConstantTypeEqual() { ConstantExpression ce = Expression as ConstantExpression; //TypeEqual(null, T) always returns false. if (ce.Value == null) { return(Utils.Constant(value: false)); } else { return(Utils.Constant(TypeOperand.GetNonNullableType() == ce.Value.GetType())); } }
private DynamicMetaObject BindGetOrInvokeMember(DynamicMetaObjectBinder binder, string name, bool ignoreCase, DynamicMetaObject fallback, Func <DynamicMetaObject, DynamicMetaObject>?fallbackInvoke) { // Value can be null, let it true if it is var @class = Value !.Class; //try to find the member, including the deleted members var index = @class.GetValueIndex(name, ignoreCase, Value); var value = Expression.Parameter(typeof(object), "value"); Expression tryGetValue = Expression.Call ( _expandoTryGetValue, GetLimitedSelf(), Expression.Constant(@class, typeof(object)), AstUtils.Constant(index), Expression.Constant(name), AstUtils.Constant(ignoreCase), value ); var result = new DynamicMetaObject(value, BindingRestrictions.Empty); if (fallbackInvoke != null) { result = fallbackInvoke(result); } result = new DynamicMetaObject ( Expression.Block ( ReadOnlyCollectionEx.Create(value), ReadOnlyCollectionEx.Create <Expression> ( Expression.Condition ( tryGetValue, result.Expression, fallback.Expression, typeof(object) ) ) ), result.Restrictions.Merge(fallback.Restrictions) ); return(AddDynamicTestAndDefer(binder, Value.Class, null, result)); }
private DynamicMetaObject BindGetOrInvokeMember(DynamicMetaObjectBinder binder, string name, bool ignoreCase, DynamicMetaObject fallback, Func <DynamicMetaObject, DynamicMetaObject> fallbackInvoke) { ExpandoClass klass = Value.Class; //try to find the member, including the deleted members int index = klass.GetValueIndex(name, ignoreCase, Value); ParameterExpression value = Expression.Parameter(typeof(object), "value"); Expression tryGetValue = Expression.Call( typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.ExpandoTryGetValue)), GetLimitedSelf(), Expression.Constant(klass, typeof(object)), AstUtils.Constant(index), Expression.Constant(name), AstUtils.Constant(ignoreCase), value ); var result = new DynamicMetaObject(value, BindingRestrictions.Empty); if (fallbackInvoke != null) { result = fallbackInvoke(result); } result = new DynamicMetaObject( Expression.Block( new TrueReadOnlyCollection <ParameterExpression>(value), Expression.Condition( tryGetValue, result.Expression, fallback.Expression, typeof(object) ) ), result.Restrictions.Merge(fallback.Restrictions) ); return(AddDynamicTestAndDefer(binder, Value.Class, null, result)); }
/// <summary> /// Helper method for generating expressions that assign byRef call /// parameters back to their original variables. /// </summary> private static Expression ReferenceArgAssign(Expression callArgs, Expression[] args) { ReadOnlyCollectionBuilder <Expression> block = null; for (int i = 0; i < args.Length; i++) { ParameterExpression variable = args[i] as ParameterExpression; ContractUtils.Requires(variable != null, nameof(args)); if (variable.IsByRef) { if (block == null) { block = new ReadOnlyCollectionBuilder <Expression>(); } block.Add( Expression.Assign( variable, Expression.Convert( Expression.ArrayIndex( callArgs, AstUtils.Constant(i) ), variable.Type ) ) ); } } if (block != null) { return(Expression.Block(block)); } else { return(AstUtils.Empty); } }
private static Expression ReferenceArgAssign(Expression callArgs, Expression[] args) { ReadOnlyCollectionBuilder <Expression> block = null; for (var i = 0; i < args.Length; i++) { var variable = args[i] as ParameterExpression; if (variable == null && variable == null) { throw new ArgumentException("Invalid argument value", nameof(args)); } if (variable.IsByRef) { (block ?? (block = new ReadOnlyCollectionBuilder <Expression>())).Add ( Expression.Assign ( variable, Expression.Convert ( Expression.ArrayIndex ( callArgs, AstUtils.Constant(i) ), variable.Type ) ) ); } } if (block != null) { return(Expression.Block(block)); } return(AstUtils.Empty); }
public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) { ArgumentNullException.ThrowIfNull(binder); int index = Value.Class.GetValueIndex(binder.Name, binder.IgnoreCase, Value); Expression tryDelete = Expression.Call( s_expandoTryDeleteValue, GetLimitedSelf(), Expression.Constant(Value.Class, typeof(object)), AstUtils.Constant(index), Expression.Constant(binder.Name), AstUtils.Constant(binder.IgnoreCase) ); DynamicMetaObject fallback = binder.FallbackDeleteMember(this); DynamicMetaObject target = new DynamicMetaObject( Expression.IfThen(Expression.Not(tryDelete), fallback.Expression), fallback.Restrictions ); return(AddDynamicTestAndDefer(binder, Value.Class, null, target)); }
public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) { ContractUtils.RequiresNotNull(binder, nameof(binder)); int index = Value.Class.GetValueIndex(binder.Name, binder.IgnoreCase, Value); Expression tryDelete = Expression.Call( typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.ExpandoTryDeleteValue)), GetLimitedSelf(), Expression.Constant(Value.Class, typeof(object)), AstUtils.Constant(index), Expression.Constant(binder.Name), AstUtils.Constant(binder.IgnoreCase) ); DynamicMetaObject fallback = binder.FallbackDeleteMember(this); DynamicMetaObject target = new DynamicMetaObject( Expression.IfThen(Expression.Not(tryDelete), fallback.Expression), fallback.Restrictions ); return(AddDynamicTestAndDefer(binder, Value.Class, null, target)); }
/// <summary> /// Creates the <see cref="Expression"/> representing the binding restrictions. /// </summary> /// <returns>The expression tree representing the restrictions.</returns> public Expression ToExpression() { // We could optimize this better, e.g. common subexpression elimination // But for now, it's good enough. if (this == Empty) { return(AstUtils.Constant(true)); } var testBuilder = new TestBuilder(); // Visit the tree, left to right. // Use an explicit stack so we don't stack overflow. // // Left-most node is on top of the stack, so we always expand the // left most node each iteration. var stack = new Stack <BindingRestrictions>(); stack.Push(this); do { var top = stack.Pop(); var m = top as MergedRestriction; if (m != null) { stack.Push(m.Right); stack.Push(m.Left); } else { testBuilder.Append(top); } } while (stack.Count > 0); return(testBuilder.ToExpression()); }
private Expression ReduceConstantTypeEqual() { return(!(Expression is ConstantExpression ce) || ce.Value == null ? Utils.Constant(false) : Utils.Constant(TypeOperand.GetNonNullable() == ce.Value.GetType())); }
//TODO enable sharing of these custom delegates private Delegate CreateCustomDelegate(Type delegateType) { //PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Synchronously compiling a custom delegate"); var method = delegateType.GetMethod("Invoke"); var paramInfos = method.GetParameters(); var parameters = new ParameterExpression[paramInfos.Length]; var parametersAsObject = new Expression[paramInfos.Length]; bool hasByRef = false; for (int i = 0; i < paramInfos.Length; i++) { ParameterExpression parameter = Expression.Parameter(paramInfos[i].ParameterType, paramInfos[i].Name); hasByRef = hasByRef || paramInfos[i].ParameterType.IsByRef; parameters[i] = parameter; parametersAsObject[i] = Expression.Convert(parameter, typeof(object)); } var data = Expression.NewArrayInit(typeof(object), parametersAsObject); var dlg = new Func <object[], object>(Run); var dlgExpr = AstUtils.Constant(dlg); var argsParam = Expression.Parameter(typeof(object[]), "$args"); Expression body; if (method.ReturnType == typeof(void)) { body = Expression.Block(typeof(void), Expression.Invoke(dlgExpr, argsParam)); } else { body = Expression.Convert(Expression.Invoke(dlgExpr, argsParam), method.ReturnType); } if (hasByRef) { List <Expression> updates = new List <Expression>(); for (int i = 0; i < paramInfos.Length; i++) { if (paramInfos[i].ParameterType.IsByRef) { updates.Add( Expression.Assign( parameters[i], Expression.Convert( Expression.ArrayAccess(argsParam, Expression.Constant(i)), paramInfos[i].ParameterType.GetElementType() ) ) ); } } body = Expression.TryFinally(body, Expression.Block(typeof(void), updates)); } body = Expression.Block( method.ReturnType, new[] { argsParam }, Expression.Assign(argsParam, data), body ); var lambda = Expression.Lambda(delegateType, body, parameters); //return System.Linq.Expressions.Compiler.LambdaCompiler.Compile(lambda, null); throw new NotImplementedException("byref delegate"); }