/*!*/ public static DynamicMetaObject TypeError(DynamicMetaObjectBinder/*!*/ action, string message, params DynamicMetaObject[] types) { if (action is ITotemSite) { ITotemSite site = (ITotemSite)action; message = String.Format(message, ArrayUtils.ConvertAll(types, x => { var t = site.Context.GetTypeHandler(x.LimitType); if (t != null) return t.Name; return x.LimitType.Name; })); Expression error = action.Throw( Ast.Call( AstMethods.SimpleTypeError, Ast.Constant(message) ), typeof(object) ); return new DynamicMetaObject( error, BindingRestrictions.Combine(types) ); } return GenericFallback(action, types); }
internal static DynamicMetaObject ConvertToString(DynamicMetaObjectBinder conversion, DynamicMetaObject self) { Assert.NotNull(conversion, self); TotemType ltype = MetaTotemObject.GetTotemType(self); var matches = ltype.GetOperatorFunctions(TotemOperationKind.ToString).ToList(); var overloadResolver = GetTotemContext(conversion).SharedOverloadResolverFactory.CreateOverloadResolver(new[] { self }, new CallSignature(1), CallTypes.None); var ret = overloadResolver.ResolveOverload("ToString", ArrayUtils.ToArray(matches, m => CreateOverloadInfo(m)), NarrowingLevel.None, NarrowingLevel.All); if (!ret.Success) { return new DynamicMetaObject( Expression.Throw( Expression.Call( AstMethods.TypeError, Utils.Constant("No toString found on type {1}."), Expression.NewArrayInit( typeof(string), Expression.Constant(ltype.Name) ) ) ), BindingRestrictions.Combine(new[] { self }) ); } return new DynamicMetaObject(ret.MakeExpression(), ret.RestrictedArguments.GetAllRestrictions()); }
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); } #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(null, Console.Out); } finally { Console.ForegroundColor = oldColor; } } #endif return new DynamicMetaObject(expr, _restrictions); }
public CSharpBinder (DynamicMetaObjectBinder binder, Compiler.Expression expr, DynamicMetaObject errorSuggestion) { this.binder = binder; this.expr = expr; this.restrictions = BindingRestrictions.Empty; this.errorSuggestion = errorSuggestion; }
public static DynamicMetaObject/*!*/ Bind(string/*!*/ methodName, CallInfo/*!*/ callInfo, DynamicMetaObjectBinder/*!*/ binder, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args, Func<DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject>/*!*/ fallback) { Debug.Assert(fallback != null); //create DMO var phpInvokeBinder = Binder.MethodCall(methodName, 0, callInfo.ArgumentCount, null, Types.Object[0]) as PhpBaseInvokeMemberBinder; if (phpInvokeBinder != null) { //Add ScriptContext.CurrentContext var context = new DynamicMetaObject(Expression.Call(Methods.ScriptContext.GetCurrentContext), BindingRestrictions.Empty); var restrictions = BinderHelper.GetSimpleInvokeRestrictions(target, args); //Value type arguments have to be boxed DynamicMetaObject[] arguments = new DynamicMetaObject[1 + args.Length]; arguments[0] = context; for (int i = 0; i < args.Length; ++i) arguments[1 + i] = new DynamicMetaObject(WrapDynamic(args[i].Expression), args[i].Restrictions); var result = phpInvokeBinder.Bind(target, arguments); //Unwrap result var res = new DynamicMetaObject(Unwrap(result.Expression), restrictions); return res; } else return fallback(target, args);//this will never happen }
/// <summary> /// Constror /// </summary> /// <param name="target">Be weaved object.</param> /// <param name="binder">Dynamic object binder <see cref="DynamicMetaObjectBinder"/></param> /// <param name="argumentValues">To store Arguement values of calling method.</param> /// <param name="returnValue">To store return value of the calling method, if it has one.</param> public WeavingContext(object target, DynamicMetaObjectBinder binder, object[] argumentValues=null, object returnValue=null) { this.Target = target; this.binder = binder; this.ArgumentValues = argumentValues; this.ReturnValue = returnValue; }
internal static DynamicMetaObject Call(DynamicMetaObjectBinder call, DynamicMetaObject target, DynamicMetaObject[] args) { Assert.NotNull(call, args); Assert.NotNullItems(args); if (target.NeedsDeferral()) return call.Defer(ArrayUtils.Insert(target, args)); foreach (var mo in args) { if (mo.NeedsDeferral()) { RestrictTypes(args); return call.Defer( ArrayUtils.Insert(target, args) ); } } DynamicMetaObject self = target.Restrict(target.GetLimitType()); ValidationInfo valInfo = BindingHelpers.GetValidationInfo(target); TotemType tt = DynamicHelpers.GetTotemType(target.Value); TotemContext toContext = GetTotemContext(call); throw new NotImplementedException(); }
internal static bool IsNoThrow(DynamicMetaObjectBinder action) { PythonGetMemberBinder gmb = action as PythonGetMemberBinder; if (gmb != null) { return gmb.IsNoThrow; } return false; }
public DynamicMetaObject FallbackConvert(DynamicMetaObjectBinder binder) { TotemConversionBinder toBinder = binder as TotemConversionBinder; if (toBinder != null) return toBinder.FallbackConvert(binder.ReturnType, this, null); return ((ConvertBinder)binder).FallbackConvert(this); }
public DynamicMetaObject/*!*/ FallbackConvert(DynamicMetaObjectBinder/*!*/ binder) { PythonConversionBinder pyBinder = binder as PythonConversionBinder; if (pyBinder != null) { return pyBinder.FallbackConvert(binder.ReturnType, this, null); } return ((ConvertBinder)binder).FallbackConvert(this); }
public static BinderState/*!*/ GetBinderState(DynamicMetaObjectBinder/*!*/ action) { IPythonSite pySite = action as IPythonSite; if (pySite != null) { return pySite.Binder; } Debug.Assert(Default != null); return Default; }
internal static BindingRestrictions GetOptionalVersionAndLanguageCheckForType(DynamicMetaObjectBinder binder, Type targetType, int expectedVersionNumber) { BindingRestrictions empty = BindingRestrictions.Empty; if (CoreTypes.Contains(targetType)) { return empty; } if (expectedVersionNumber != -1) { empty = empty.Merge(GetVersionCheck(binder, expectedVersionNumber)); } return empty.Merge(GetLanguageModeCheckIfHasEverUsedConstrainedLanguage()); }
public BinaryRetTypeBinder(DynamicMetaObjectBinder operationBinder, PythonConversionBinder conversionBinder) : base(new BinderMappingInfo( operationBinder, ParameterMappingInfo.Parameter(0), ParameterMappingInfo.Parameter(1) ), new BinderMappingInfo( conversionBinder, ParameterMappingInfo.Action(0) ) ) { _opBinder = operationBinder; _convBinder = conversionBinder; }
private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[]/*!*/ args) { if (this.NeedsDeferral()) { return call.Defer(ArrayUtils.Insert(this, args)); } for (int i = 0; i < args.Length; i++) { if (args[i].NeedsDeferral()) { return call.Defer(ArrayUtils.Insert(this, args)); } } if (Value.IsUnbound) { return MakeSelflessCall(call, codeContext, args); } else { return MakeSelfCall(call, codeContext, args); } }
private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[] args) { CallSignature signature = BindingHelpers.GetCallSignature(call); BindingRestrictions selfRestrict = BindingRestrictions.GetInstanceRestriction(Expression, Value).Merge(Restrictions); selfRestrict = selfRestrict.Merge( BindingRestrictions.GetExpressionRestriction( MakeFunctionTest( Ast.Call( typeof(PythonOps).GetMethod("GetBuiltinMethodDescriptorTemplate"), Ast.Convert(Expression, typeof(BuiltinMethodDescriptor)) ) ) ) ); return Value.Template.MakeBuiltinFunctionCall( call, codeContext, this, args, false, // no self true, selfRestrict, (newArgs) => { BindingTarget target; BinderState state = BinderState.GetBinderState(call); DynamicMetaObject res = state.Binder.CallMethod( new ParameterBinderWithCodeContext(state.Binder, codeContext), Value.Template.Targets, newArgs, signature, selfRestrict, NarrowingLevel.None, Value.Template.IsBinaryOperator ? PythonNarrowing.BinaryOperator : NarrowingLevel.All, Value.Template.Name, out target ); return new BuiltinFunction.BindingResult(target, res); }); }
internal static DynamicMetaObject/*!*/ FilterShowCls(DynamicMetaObject/*!*/ codeContext, DynamicMetaObjectBinder/*!*/ action, DynamicMetaObject/*!*/ res, Expression/*!*/ failure) { if (action is IPythonSite) { return new DynamicMetaObject( Ast.Condition( Ast.Call( typeof(PythonOps).GetMethod("IsClsVisible"), codeContext.Expression ), AstUtils.Convert(res.Expression, typeof(object)), AstUtils.Convert(failure, typeof(object)) ), res.Restrictions ); } return res; }
/// <summary> /// Gets a MetaObject which converts the provided object to a bool using __nonzero__ or __len__ /// protocol methods. This code is shared between both our fallback for a site and our MetaObject /// for user defined objects. /// </summary> internal static DynamicMetaObject ConvertToBool(DynamicMetaObjectBinder/*!*/ conversion, DynamicMetaObject/*!*/ self) { Assert.NotNull(conversion, self); SlotOrFunction sf = SlotOrFunction.GetSlotOrFunction( BinderState.GetBinderState(conversion), Symbols.NonZero, self); if (sf.Success) { if (sf.Target.Expression.Type != typeof(bool)) { return new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("ThrowingConvertToNonZero"), sf.Target.Expression ), sf.Target.Restrictions ); } return sf.Target; } sf = SlotOrFunction.GetSlotOrFunction( BinderState.GetBinderState(conversion), Symbols.Length, self); if (sf.Success) { return new DynamicMetaObject( GetConvertByLengthBody( BinderState.GetBinderState(conversion), sf.Target.Expression ), sf.Target.Restrictions ); } return null; }
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); }
public static DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ context, string/*!*/ methodName, CallInfo/*!*/ callInfo, DynamicMetaObjectBinder/*!*/ binder, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args, Func<DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject>/*!*/ fallback) { Debug.Assert(fallback != null); var callArgs = new CallArguments(context, target, args, RubyCallSignature.Interop(callInfo.ArgumentCount)); var metaBuilder = new MetaObjectBuilder(target, args); if (!RubyCallAction.BuildCall(metaBuilder, methodName, callArgs, false, false)) { metaBuilder.SetMetaResult(fallback(target, args), false); } return metaBuilder.CreateMetaObject(binder); }
/// <summary> /// Helper method for generating a MetaObject which calls a /// specific method on DynamicObject that returns a result. /// /// args is either an array of arguments to be passed /// to the method as an object[] or NoArgs to signify that /// the target method takes no parameters. /// </summary> private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke) { if (!IsOverridden(methodName)) { return fallbackResult; } // // Build a new expression like: // { // object result; // TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult // } // var result = Expression.Parameter(typeof(object), null); ParameterExpression callArgs = methodName != "TryBinaryOperation" ? Expression.Parameter(typeof(object[]), null) : Expression.Parameter(typeof(object), null); var callArgsValue = GetConvertedArgs(args); var resultMO = new DynamicMetaObject(result, BindingRestrictions.Empty); // Need to add a conversion if calling TryConvert if (binder.ReturnType != typeof(object)) { Debug.Assert(binder is ConvertBinder && fallbackInvoke == null); var convert = Expression.Convert(resultMO.Expression, binder.ReturnType); // will always be a cast or unbox Debug.Assert(convert.Method == null); #if !SILVERLIGHT // Prepare a good exception message in case the convert will fail string convertFailed = Strings.DynamicObjectResultNotAssignable( "{0}", this.Value.GetType(), binder.GetType(), binder.ReturnType ); Expression condition; // If the return type can not be assigned null then just check for type assignablity otherwise allow null. if (binder.ReturnType.IsValueType && Nullable.GetUnderlyingType(binder.ReturnType) == null) { condition = Expression.TypeIs(resultMO.Expression, binder.ReturnType); } else { condition = Expression.OrElse( Expression.Equal(resultMO.Expression, Expression.Constant(null)), Expression.TypeIs(resultMO.Expression, binder.ReturnType)); } var checkedConvert = Expression.Condition( condition, convert, Expression.Throw( Expression.New(typeof(InvalidCastException).GetConstructor(new Type[]{typeof(string)}), Expression.Call( typeof(string).GetMethod("Format", new Type[] {typeof(string), typeof(object[])}), Expression.Constant(convertFailed), Expression.NewArrayInit(typeof(object), Expression.Condition( Expression.Equal(resultMO.Expression, Expression.Constant(null)), Expression.Constant("null"), Expression.Call( resultMO.Expression, typeof(object).GetMethod("GetType") ), typeof(object) ) ) ) ), binder.ReturnType ), binder.ReturnType ); #else var checkedConvert = convert; #endif resultMO = new DynamicMetaObject(checkedConvert, resultMO.Restrictions); } if (fallbackInvoke != null) { resultMO = fallbackInvoke(resultMO); } var callDynamic = new DynamicMetaObject( Expression.Block( new[] { result, callArgs }, methodName != "TryBinaryOperation" ? Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)) : Expression.Assign(callArgs, callArgsValue[0]), Expression.Condition( Expression.Call( GetLimitedSelf(), typeof(DynamicObject).GetMethod(methodName), BuildCallArgs( binder, args, callArgs, result ) ), Expression.Block( methodName != "TryBinaryOperation" ? ReferenceArgAssign(callArgs, args) : Expression.Empty(), resultMO.Expression ), fallbackResult.Expression, binder.ReturnType ) ), GetRestrictions().Merge(resultMO.Restrictions).Merge(fallbackResult.Restrictions) ); return callDynamic; }
/// <summary> /// Helper method for generating a MetaObject which calls a /// specific method on Dynamic, but uses one of the arguments for /// the result. /// /// args is either an array of arguments to be passed /// to the method as an object[] or NoArgs to signify that /// the target method takes no parameters. /// </summary> private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) { // // First, call fallback to do default binding // This produces either an error or a call to a .NET member // DynamicMetaObject fallbackResult = fallback(null); var callArgs = Expression.Parameter(typeof(object[]), null); var callArgsValue = GetConvertedArgs(args); // // Build a new expression like: // if (TryDeleteMember(payload)) { } else { fallbackResult } // var callDynamic = new DynamicMetaObject( Expression.Block( new[] { callArgs }, Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)), Expression.Condition( Expression.Call( GetLimitedSelf(), typeof(DynamicObject).GetMethod(methodName), BuildCallArgs( binder, args, callArgs, null ) ), Expression.Block( ReferenceArgAssign(callArgs, args), Expression.Empty() ), fallbackResult.Expression, typeof(void) ) ), GetRestrictions().Merge(fallbackResult.Restrictions) ); // // Now, call fallback again using our new MO as the error // When we do this, one of two things can happen: // 1. Binding will succeed, and it will ignore our call to // the dynamic method, OR // 2. Binding will fail, and it will use the MO we created // above. // return fallback(callDynamic); }
/// <summary> /// Helper method for generating a MetaObject which calls a /// specific method on Dynamic that returns a result /// </summary> private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) { return CallMethodWithResult(methodName, binder, args, fallback, null); }
/// <summary> /// Helper method for generating a MetaObject which calls a /// specific method on Dynamic that returns a result /// </summary> private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback, Fallback fallbackInvoke) { // // First, call fallback to do default binding // This produces either an error or a call to a .NET member // DynamicMetaObject fallbackResult = fallback(null); var callDynamic = BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke); // // Now, call fallback again using our new MO as the error // When we do this, one of two things can happen: // 1. Binding will succeed, and it will ignore our call to // the dynamic method, OR // 2. Binding will fail, and it will use the MO we created // above. // return fallback(callDynamic); }
/// <summary> /// Helper method for generating arguments for calling methods /// on DynamicObject. parameters is either a list of ParameterExpressions /// to be passed to the method as an object[], or NoArgs to signify that /// the target method takes no object[] parameter. /// </summary> private static Expression[] BuildCallArgs(DynamicMetaObjectBinder binder, Expression[] parameters, Expression arg0, Expression arg1) { if (!object.ReferenceEquals(parameters, NoArgs)) return arg1 != null ? new Expression[] { Constant(binder), arg0, arg1 } : new Expression[] { Constant(binder), arg0 }; else return arg1 != null ? new Expression[] { Constant(binder), arg1 } : new Expression[] { Constant(binder) }; }
private static ConstantExpression Constant(DynamicMetaObjectBinder binder) { Type t = binder.GetType(); while (!t.IsVisible) { t = t.BaseType; } return Expression.Constant(binder, t); }
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 DynamicMetaObject/*!*/ CreateMetaObject(DynamicMetaObjectBinder/*!*/ action) { return CreateMetaObject(action, action.ReturnType); }
internal static DynamicMetaObject FallbackWorker(DynamicMetaObject/*!*/ self, Expression/*!*/ codeContext, string name, GetMemberOptions options, DynamicMetaObjectBinder action) { if (self.NeedsDeferral()) { return action.Defer(self); } bool isNoThrow = ((options & GetMemberOptions.IsNoThrow) != 0) ? true : false; Type limitType = self.GetLimitType() ; if (limitType == typeof(DynamicNull) || PythonBinder.IsPythonType(limitType)) { // look up in the PythonType so that we can // get our custom method names (e.g. string.startswith) PythonType argType = DynamicHelpers.GetPythonTypeFromType(limitType); // if the name is defined in the CLS context but not the normal context then // we will hide it. if (argType.IsHiddenMember(name)) { DynamicMetaObject baseRes = BinderState.GetBinderState(action).Binder.GetMember( name, self, codeContext, isNoThrow ); Expression failure = GetFailureExpression(limitType, name, isNoThrow, action); return BindingHelpers.FilterShowCls(codeContext, action, baseRes, failure); } } if (self.GetLimitType() == typeof(OldInstance)) { if ((options & GetMemberOptions.IsNoThrow) != 0) { return new DynamicMetaObject( Ast.Field( null, typeof(OperationFailed).GetField("Value") ), self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, typeof(OldInstance))) ); } else { return new DynamicMetaObject( Ast.Throw( Ast.Call( typeof(PythonOps).GetMethod("AttributeError"), Ast.Constant("{0} instance has no attribute '{1}'"), Ast.NewArrayInit( typeof(object), Ast.Constant(((OldInstance)self.Value)._class._name), Ast.Constant(name) ) ) ), self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, typeof(OldInstance))) ); } } var res = BinderState.GetBinderState(action).Binder.GetMember(name, self, codeContext, isNoThrow); // Default binder can return something typed to boolean or int. // If that happens, we need to apply Python's boxing rules. if (res.Expression.Type == typeof(bool) || res.Expression.Type == typeof(int)) { res = new DynamicMetaObject( AstUtils.Convert(res.Expression, typeof(object)), res.Restrictions ); } return res; }
private static Expression/*!*/ GetFailureExpression(Type/*!*/ limitType, string name, bool isNoThrow, DynamicMetaObjectBinder action) { return isNoThrow ? Ast.Field(null, typeof(OperationFailed).GetField("Value")) : DefaultBinder.MakeError( BinderState.GetBinderState(action).Binder.MakeMissingMemberError( limitType, name ) ); }
public BinderMappingInfo(DynamicMetaObjectBinder binder, params ParameterMappingInfo[] mappingInfos) : this(binder, (IList<ParameterMappingInfo>)mappingInfos) { }