/// <summary> /// Adds a dynamic test which checks if the version has changed. The test is only necessary for /// performance as the methods will do the correct thing if called with an incorrect version. /// </summary> private DynamicMetaObject AddDynamicTestAndDefer(DynamicMetaObjectBinder binder, ExpandoClass klass, ExpandoClass originalClass, DynamicMetaObject succeeds) { Expression ifTestSucceeds = succeeds.Expression; if (originalClass != null) { // we are accessing a member which has not yet been defined on this class. // We force a class promotion after the type check. If the class changes the // promotion will fail and the set/delete will do a full lookup using the new // class to discover the name. Debug.Assert(originalClass != klass); ifTestSucceeds = Expression.Block( Expression.Call( null, typeof(RuntimeOps).GetMethod("ExpandoPromoteClass"), GetLimitedSelf(), Expression.Constant(originalClass, typeof(object)), Expression.Constant(klass, typeof(object)) ), succeeds.Expression ); } return(new DynamicMetaObject( Expression.Condition( Expression.Call( null, typeof(RuntimeOps).GetMethod("ExpandoCheckVersion"), GetLimitedSelf(), Expression.Constant(originalClass ?? klass, typeof(object)) ), ifTestSucceeds, binder.GetUpdateExpression(ifTestSucceeds.Type) ), GetRestrictions().Merge(succeeds.Restrictions) )); }
internal DynamicMetaObject/*!*/ CreateMetaObject(DynamicMetaObjectBinder/*!*/ action) { Debug.Assert(ControlFlowBuilder == null, "Control flow required but not built"); var expr = _error ? Ast.Throw(_result) : _result; if (_condition != null) { var deferral = action.GetUpdateExpression(typeof(object)); expr = Ast.Condition(_condition, AstUtils.Convert(expr, typeof(object)), deferral); } if (_temps != null) { expr = Ast.Block(_temps, expr); } BindingRestrictions restrictions; if (_restriction != null) { restrictions = BindingRestrictions.GetExpressionRestriction(_restriction); } else { restrictions = BindingRestrictions.Empty; } return new DynamicMetaObject(expr, restrictions); }
internal DynamicMetaObject/*!*/ CreateMetaObject(DynamicMetaObjectBinder/*!*/ binder, Type/*!*/ returnType) { Debug.Assert(ControlFlowBuilder == null, "Control flow required but not built"); var restrictions = _restrictions; var expr = _error ? Ast.Throw(_result, returnType) : AstUtils.Convert(_result, returnType); if (_condition != null) { var deferral = binder.GetUpdateExpression(returnType); expr = Ast.Condition(_condition, expr, deferral); } if (_temps != null || _initializations != null) { AddInitialization(expr); if (_temps != null) { expr = Ast.Block(_temps, _initializations); } else { expr = Ast.Block(_initializations); } } Clear(); RubyBinder.DumpRule(binder, restrictions, expr); return new DynamicMetaObject(expr, restrictions); }
internal static DynamicMetaObject/*!*/ AddDynamicTestAndDefer(DynamicMetaObjectBinder/*!*/ operation, DynamicMetaObject/*!*/ res, DynamicMetaObject/*!*/[] args, ValidationInfo typeTest, Type deferType, params ParameterExpression[] temps) { if (typeTest != null) { if (typeTest.Test != null) { // add the test and a validator if persent Expression defer = operation.GetUpdateExpression(deferType ?? typeof(object)); Type bestType = BindingHelpers.GetCompatibleType(defer.Type, res.Expression.Type); res = new DynamicMetaObject( Ast.Condition( typeTest.Test, AstUtils.Convert(res.Expression, bestType), AstUtils.Convert(defer, bestType) ), res.Restrictions ); } } if (temps.Length > 0) { // finally add the scoped variables res = new DynamicMetaObject( Ast.Block(temps, res.Expression), res.Restrictions, null ); } return res; }
internal DynamicMetaObject/*!*/ CreateMetaObject(DynamicMetaObjectBinder/*!*/ action, Type/*!*/ returnType) { Debug.Assert(ControlFlowBuilder == null, "Control flow required but not built"); var expr = _error ? Ast.Throw(_result, returnType) : AstUtils.Convert(_result, returnType); if (_condition != null) { var deferral = action.GetUpdateExpression(returnType); expr = Ast.Condition(_condition, expr, deferral); } if (_temps != null) { expr = Ast.Block(_temps, expr); } RubyBinder.DumpRule(action, _restrictions, expr); return new DynamicMetaObject(expr, _restrictions); }
internal DynamicMetaObject/*!*/ CreateMetaObject(DynamicMetaObjectBinder/*!*/ action, Type/*!*/ returnType) { Debug.Assert(ControlFlowBuilder == null, "Control flow required but not built"); var expr = _error ? Ast.Throw(_result, returnType) : AstUtils.Convert(_result, returnType); if (_condition != null) { var deferral = action.GetUpdateExpression(returnType); expr = Ast.Condition(_condition, expr, deferral); } if (_temps != null) { expr = Ast.Block(_temps, expr); } #if DEBUG && !SILVERLIGHT && !SYSTEM_CORE if (RubyOptions.ShowRules) { var oldColor = Console.ForegroundColor; try { Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("Rule #{0}: {1}", Interlocked.Increment(ref _ruleCounter), action); Console.ForegroundColor = ConsoleColor.DarkGray; var d = (_restrictions != BindingRestrictions.Empty) ? Ast.IfThen(_restrictions.ToExpression(), expr) : expr; d.DumpExpression(Console.Out); } finally { Console.ForegroundColor = oldColor; } } #endif return new DynamicMetaObject(expr, _restrictions); }
internal static Expression MaybeDebase(DynamicMetaObjectBinder binder, Func<Expression, Expression> generator, DynamicMetaObject target) { ParameterExpression expression; if (!(target.Value is PSObject)) { return generator(target.Expression); } object obj2 = PSObject.Base(target.Value); return Expression.Block(new ParameterExpression[] { expression = Expression.Parameter(typeof(object), "value") }, new Expression[] { Expression.Assign(expression, Expression.Call(CachedReflectionInfo.PSObject_Base, target.Expression)), Expression.Condition((obj2 == null) ? ((Expression) Expression.AndAlso(Expression.Equal(expression, ExpressionCache.NullConstant), Expression.Not(Expression.Equal(target.Expression, ExpressionCache.AutomationNullConstant)))) : ((Expression) Expression.TypeEqual(expression, obj2.GetType())), generator(expression), binder.GetUpdateExpression(binder.ReturnType)) }); }