public override Meta BindInvoke(InvokeBinder binder, Meta[] args) { return new Meta( Et.Call( EtUtils.Cast<IFunction>( this.Expression ), IFunctionMethods.MiCall, EtUtils.Cast<IObj>( args[0].Expression ), AstUtils.NewArrayHelper( typeof(object), DynamicUtils.GetExpressions( ArrayUtils.RemoveFirst(args) ) ) ), RestrictUtils.BuildCallRestrictions( this, args, RestrictFlag.Type ) ); }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { ComMethodDesc method; var target = _callable.DispatchComObject; var name = _callable.MemberName; bool holdsNull = value.Value == null && value.HasValue; if (target.TryGetPropertySetter(name, out method, value.LimitType, holdsNull) || target.TryGetPropertySetterExplicit(name, out method, value.LimitType, holdsNull)) { List<ParameterExpression> temps = new List<ParameterExpression>(); List<Expression> initTemps = new List<Expression>(); bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(method, ref indexes, temps, initTemps); isByRef = isByRef.AddLast(false); // Convert the value to the target type DynamicMetaObject updatedValue = new DynamicMetaObject(value.CastOrConvertMethodArgument( value.LimitType, name, "SetIndex", temps, initTemps), value.Restrictions); var result = BindComInvoke(method, indexes.AddLast(updatedValue), binder.CallInfo, isByRef, temps, initTemps); // Make sure to return the value; some languages need it. return new DynamicMetaObject( Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))), result.Restrictions ); } return base.BindSetIndex(binder, indexes, value); }
/// <summary> /// Performs the binding of the dynamic set member operation if the target dynamic object /// cannot bind. /// </summary> /// <param name="target">The target of the dynamic set member operation.</param> /// <param name="value">The value to set to the member.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null. /// </param> /// <returns> /// The <see cref="T:System.Dynamic.DynamicMetaObject"/> representing the result of the /// binding. /// </returns> public override DynamicMetaObject FallbackSetMember( DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { return null; }
public override DYN.DynamicMetaObject FallbackGetMember(DYN.DynamicMetaObject target, DYN.DynamicMetaObject errorSuggestion) { DYN.BindingRestrictions restriction = DYN.BindingRestrictions.GetTypeRestriction(target.Expression, target.RuntimeType); string exceptionString = String.Format("GetMemberBinder: cannot bind member '{0}' on object '{1}'", this.Name, target.Value.ToString()); DLR.Expression throwBlock = DLR.Expression.Throw( DLR.Expression.New( typeof(Error.Value).GetConstructor(new Type[] { typeof(string) }), DLR.Expression.Constant(exceptionString) ), typeof(Error) ); DYN.DynamicMetaObject dynobj = new DYN.DynamicMetaObject( throwBlock, restriction ); return(dynobj); }
internal ComInvokeBinder( CallInfo callInfo, DynamicMetaObject[] args, bool[] isByRef, BindingRestrictions restrictions, Expression method, Expression dispatch, ComMethodDesc methodDesc ) { Debug.Assert(callInfo != null, "arguments"); Debug.Assert(args != null, "args"); Debug.Assert(isByRef != null, "isByRef"); Debug.Assert(method != null, "method"); Debug.Assert(dispatch != null, "dispatch"); Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(ComMethodDesc), method.Type), "method"); Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(IDispatch), dispatch.Type), "dispatch"); _method = method; _dispatch = dispatch; _methodDesc = methodDesc; _callInfo = callInfo; _args = args; _isByRef = isByRef; _restrictions = restrictions; // Set Instance to some value so that CallBinderHelper has the right number of parameters to work with _instance = dispatch; }
private DynamicMetaObject[] GetArguments(DynamicMetaObject[] args, IList<DynamicMetaObject> results, int metaBinderIndex) { BinderMappingInfo indices = _metaBinders[metaBinderIndex]; DynamicMetaObject[] res = new DynamicMetaObject[indices.MappingInfo.Count]; for (int i = 0; i < res.Length; i++) { ParameterMappingInfo mappingInfo = indices.MappingInfo[i]; if (mappingInfo.IsAction) { // input is the result of a previous bind res[i] = results[mappingInfo.ActionIndex]; } else if (mappingInfo.IsParameter) { // input is one of the original arguments res[i] = args[mappingInfo.ParameterIndex]; } else { // input is a constant res[i] = new DynamicMetaObject( mappingInfo.Constant, BindingRestrictions.Empty, mappingInfo.Constant.Value ); } } return res; }
public static bool TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, out DynamicMetaObject result, bool delayInvocation) { ContractUtils.RequiresNotNull(binder, "binder"); ContractUtils.RequiresNotNull(instance, "instance"); if (TryGetMetaObject(ref instance)) { // // Demand Full Trust to proceed with the binding. // new PermissionSet(PermissionState.Unrestricted).Demand(); var comGetMember = new ComGetMemberBinder(binder, delayInvocation); result = instance.BindGetMember(comGetMember); if (result.Expression.Type.IsValueType) { result = new DynamicMetaObject( Expression.Convert(result.Expression, typeof(object)), result.Restrictions ); } return true; } else { result = null; return false; } }
/// <summary> /// The method takes a DynamicMetaObject, and returns an instance restriction for testing null if the object /// holds a null value, otherwise returns a type restriction. /// </summary> internal static BindingRestrictions GetTypeRestriction(DynamicMetaObject obj) { if (obj.Value == null && obj.HasValue) { return BindingRestrictions.GetInstanceRestriction(obj.Expression, null); } else { return BindingRestrictions.GetTypeRestriction(obj.Expression, obj.LimitType); } }
/// <summary> /// Performs the binding of the dynamic operation. /// </summary> /// <param name="target">The target of the dynamic operation.</param> /// <param name="args">An array of arguments of the dynamic operation.</param> /// <returns>The System.Dynamic.DynamicMetaObject representing the result of the binding.</returns> public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { #if DEBUG if ((args == null) || (args.Length != 2)) throw new InvalidOperationException("The DoesNotUnderstandCallSiteBinder is special case and always requires 2 method arguments."); #endif // Look-up the #_doesNotUnderstand:arguments: method. BindingRestrictions restrictions; SmalltalkClass receiverClass; Expression expression; MethodLookupHelper.GetMethodInformation(this.Runtime, this.Runtime.GetSymbol("_doesNotUnderstand:arguments:"), null, target.Value, target, args, out receiverClass, out restrictions, out expression); // Every class is supposed to implement the #_doesNotUnderstand:arguments:, if not, throw a runtime exception if (expression == null) throw new RuntimeCodeGenerationException(RuntimeCodeGenerationErrors.DoesNotUnderstandMissing); // Perform a standard cal to the #_doesNotUnderstand:arguments: return new DynamicMetaObject(expression, target.Restrictions.Merge(restrictions)); }
/// <summary> /// Creates the MetaObject for indexing directly into arrays or indexing into objects which have /// default members. Returns null if we're not an indexing operation. /// </summary> public DynamicMetaObject SetIndex(OverloadResolverFactory resolverFactory, DynamicMetaObject[] args) { if (args[0].LimitType.IsArray) { return MakeArrayIndexRule(resolverFactory, IndexType.Set, args); } return MakeMethodIndexRule(IndexType.Set, resolverFactory, args); }
public RuntimeValueExpression (DynamicMetaObject obj, bool typed) { this.obj = obj; this.typed = typed; this.type = obj.RuntimeType; this.eclass = ExprClass.Value; }
public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args) { var constructors = ReflType.GetConstructors(); var ctors = constructors.Where(c => c.GetParameters().Length == args.Length); var res = new List<ConstructorInfo>(); foreach (var c in ctors) { if (RuntimeHelpers.ParametersMatchArguments(c.GetParameters(), args)) { res.Add(c); } } if (res.Count == 0) { // Binders won't know what to do with TypeModels, so pass the // RuntimeType they represent. The binder might not be Sympl's. return binder.FallbackCreateInstance( RuntimeHelpers.GetRuntimeTypeMoFromModel(this), args); } // For create instance of a TypeModel, we can create a instance // restriction on the MO, hence the true arg. var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(this, args, true); var ctorArgs = RuntimeHelpers.ConvertArguments(args, res[0].GetParameters()); return new DynamicMetaObject( // Creating an object, so don't need EnsureObjectResult. Expression.New(res[0], ctorArgs), restrictions); }
/// <summary> /// Performs the binding of the dynamic delete index operation. /// </summary> /// <param name="target">The target of the dynamic delete index operation.</param> /// <param name="args">An array of arguments of the dynamic delete index operation.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(target, nameof(target)); ContractUtils.RequiresNotNullItems(args, nameof(args)); return target.BindDeleteIndex(this, args); }
// negative start reserves as many slots at the beginning of the new array: internal static object/*!*/[]/*!*/ ToValues(DynamicMetaObject/*!*/[]/*!*/ args, int start) { var result = new object[args.Length - start]; for (int i = Math.Max(0, -start); i < result.Length; i++) { result[i] = args[start + i].Value; } return result; }
public DynamicMetaObject ConvertTo(Type toType, ConversionResultKind kind, DynamicMetaObject arg, OverloadResolverFactory resolverFactory, DynamicMetaObject errorSuggestion) { ContractUtils.RequiresNotNull(toType, "toType"); ContractUtils.RequiresNotNull(arg, "arg"); Type knownType = arg.GetLimitType(); // try all the conversions - first look for conversions against the expression type, // these can be done w/o any additional tests. Then look for conversions against the // restricted type. BindingRestrictions typeRestrictions = arg.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg.Expression, arg.GetLimitType())); DynamicMetaObject res = TryConvertToObject(toType, arg.Expression.Type, arg, typeRestrictions) ?? TryAllConversions(resolverFactory, toType, kind, arg.Expression.Type, typeRestrictions, arg) ?? TryAllConversions(resolverFactory, toType, kind, arg.GetLimitType(), typeRestrictions, arg) ?? errorSuggestion ?? MakeErrorTarget(toType, kind, typeRestrictions, arg); if ((kind == ConversionResultKind.ExplicitTry || kind == ConversionResultKind.ImplicitTry) && toType.IsValueType) { res = new DynamicMetaObject( AstUtils.Convert( res.Expression, typeof(object) ), res.Restrictions ); } return res; }
public void BindBinaryOperationInvalidTest() { DynamicMetaObject target; DynamicMetaObject argPrimitive = new DynamicMetaObject(Expression.Constant(10), BindingRestrictions.Empty); DynamicMetaObject argNonPrimitive = new DynamicMetaObject(Expression.Constant(AnyInstance.AnyJsonObject), BindingRestrictions.Empty); foreach (JsonValue value in AnyInstance.AnyJsonValueArray) { target = GetJsonValueDynamicMetaObject(value); TestBinaryOperationBinder.TestMetaObject(target, argPrimitive, TestBinaryOperationBinder.UnsupportedOperations, false); } foreach (JsonValue value in AnyInstance.AnyJsonValueArray) { target = GetJsonValueDynamicMetaObject(value); if (value is JsonPrimitive) { //// not supported on operand of type JsonValue if it isn't a primitive and not comparing JsonValue types. TestBinaryOperationBinder.TestMetaObject(target, argNonPrimitive, TestBinaryOperationBinder.NumberOperations, false); TestBinaryOperationBinder.TestMetaObject(target, argNonPrimitive, TestBinaryOperationBinder.BoolOperations, false); } else { //// When value is non-primitive, it must be a compare operation and (the other operand must be null or a JsonValue) TestBinaryOperationBinder.TestMetaObject(target, argPrimitive, TestBinaryOperationBinder.NumberOperations, false); TestBinaryOperationBinder.TestMetaObject(target, argPrimitive, TestBinaryOperationBinder.BoolOperations, false); } } }
// negative start reserves as many slots at the beginning of the new array: internal static Expression/*!*/[]/*!*/ ToExpressions(DynamicMetaObject/*!*/[]/*!*/ args, int start) { var result = new Expression[args.Length - start]; for (int i = Math.Max(0, -start); i < result.Length; i++) { result[i] = args[start + i].Expression; } return result; }
internal static bool CanIndexFromEndWithNegativeIndex(DynamicMetaObject target) { Type limitType = target.LimitType; return (((limitType.IsArray || limitType.Equals(typeof(string))) || limitType.Equals(typeof(StringBuilder))) || (typeof(IList).IsAssignableFrom(limitType) || (typeof(OrderedDictionary).IsAssignableFrom(limitType) || (from i in limitType.GetInterfaces() where i.IsGenericType && i.GetGenericTypeDefinition().Equals(typeof(IList<>)) select i).Any<Type>()))); }
public override MemberTracker BindToInstance(DynamicMetaObject instance) { if (IsStatic) { return this; } return new BoundMemberTracker(this, instance); }
/// <summary> /// Performs the binding of the dynamic set member operation. /// </summary> /// <param name="target">The target of the dynamic set member operation.</param> /// <param name="args">An array of arguments of the dynamic set member operation.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(target, "target"); ContractUtils.RequiresNotNullItems(args, "args"); ContractUtils.Requires(args.Length == 1); return target.BindSetMember(this, args[0]); }
// instance method call: public PythonOverloadResolver(PythonBinder binder, DynamicMetaObject instance, IList<DynamicMetaObject> args, CallSignature signature, Expression codeContext) : base(binder, instance, args, signature) { Assert.NotNull(codeContext); _context = codeContext; }
/// <summary> /// Performs the binding of the dynamic get member operation. /// </summary> /// <param name="target">The target of the dynamic get member operation.</param> /// <param name="args">An array of arguments of the dynamic get member operation.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public sealed override DynamicMetaObject Bind(DynamicMetaObject target, params DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(target, "target"); ContractUtils.Requires(args == null || args.Length == 0, "args"); return target.BindGetMember(this); }
public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { const string errorMsg = "{0}を符号反転出来ません。"; if (target.Value == null) { var msg = String.Format(errorMsg, ConstantNames.NullText); var ctorInfo = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) }); var expr = Expression.Throw(Expression.New(ctorInfo, Expression.Constant(errorMsg)), this.ReturnType); var rest = BindingRestrictions.GetExpressionRestriction(BinderHelper.IsNull(target.Expression)); return new DynamicMetaObject(expr, rest); } try { var expr = BinderHelper.Wrap(Expression.Negate(Expression.Convert(target.Expression, target.LimitType)), this.ReturnType); var rest = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType); return new DynamicMetaObject(expr, rest); } catch (InvalidOperationException) { var msgExpr = ExpressionHelper.BetaReduction<string, object, string>( (format, obj) => String.Format(format, obj), Expression.Constant(errorMsg), target.Expression); var ctorInfo = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) }); var expr = Expression.Throw(Expression.New(ctorInfo, msgExpr), this.ReturnType); var rest = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType); return new DynamicMetaObject(expr, rest); } }
public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion) { switch (Operation) { case ExpressionType.Or: case ExpressionType.OrAssign: case ExpressionType.ExclusiveOr: case ExpressionType.ExclusiveOrAssign: case ExpressionType.And: case ExpressionType.AndAssign: return BindBitOp(target, arg, errorSuggestion); case ExpressionType.Add: case ExpressionType.AddAssign: case ExpressionType.Subtract: case ExpressionType.SubtractAssign: case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: case ExpressionType.Divide: case ExpressionType.DivideAssign: case ExpressionType.LeftShift: case ExpressionType.LeftShiftAssign: case ExpressionType.RightShift: case ExpressionType.RightShiftAssign: return BindArithOp(target, arg, errorSuggestion); default: throw new System.Exception("Unhandled operation value"); } }
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject targetMO, DynamicMetaObject errorSuggestion) { // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!targetMO.HasValue) return Defer(targetMO); // Find our own binding. MemberInfo[] members = targetMO.LimitType.GetMember(Name, DefaultBindingFlags); if (members.Length == 1) { return new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.MakeMemberAccess( Expression.Convert(targetMO.Expression, members[0].DeclaringType), members[0])), // Don't need restriction test for name since this // rule is only used where binder is used, which is // only used in sites with this binder.Name. BindingRestrictions.GetTypeRestriction(targetMO.Expression, targetMO.LimitType)); } return errorSuggestion ?? RuntimeHelpers.CreateBindingThrow( targetMO, null, BindingRestrictions.GetTypeRestriction(targetMO.Expression, targetMO.LimitType), typeof(MissingMemberException), "cannot bind member, " + Name + ", on object " + targetMO.Value); }
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(); }
public DynamicMetaObject Create(CallSignature signature, DynamicMetaObject target, DynamicMetaObject[] args, Expression contextExpression) { Type t = GetTargetType(target.Value); if (t != null) { if (typeof(Delegate).IsAssignableFrom(t) && args.Length == 1) { // PythonOps.GetDelegate(CodeContext context, object callable, Type t); return new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("GetDelegate"), contextExpression, AstUtils.Convert(args[0].Expression, typeof(object)), Expression.Constant(t) ), target.Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)) ); } return CallMethod( new PythonOverloadResolver( this, args, signature, contextExpression ), CompilerHelpers.GetConstructors(t, PrivateBinding), target.Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)) ); } return null; }
public CSharpBinder (DynamicMetaObjectBinder binder, Compiler.Expression expr, DynamicMetaObject errorSuggestion) { this.binder = binder; this.expr = expr; this.restrictions = BindingRestrictions.Empty; this.errorSuggestion = errorSuggestion; }
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()); }
public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] packedIndexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { if (IDOUtils.NeedsDeferral(target, packedIndexes, value)) { Array.Resize<DynamicMetaObject>(ref packedIndexes, packedIndexes.Length + 1); packedIndexes[packedIndexes.Length - 1] = value; return this.Defer(target, packedIndexes); } string[] argNames = null; Expression[] args = null; object[] argValues = null; IDOUtils.UnpackArguments(packedIndexes, this.CallInfo, ref args, ref argNames, ref argValues); object[] array = new object[argValues.Length + 1]; argValues.CopyTo(array, 0); array[argValues.Length] = value.Value; if ((errorSuggestion != null) && !NewLateBinding.CanIndexSetComplex(target.Value, array, argNames, this._optimisticSet, this._rValueBase)) { return errorSuggestion; } Expression expression2 = IDOUtils.ConvertToObject(value.Expression); Expression[] expressionArray2 = new Expression[args.Length + 1]; args.CopyTo(expressionArray2, 0); expressionArray2[args.Length] = expression2; return new DynamicMetaObject(Expression.Block(Expression.Call(typeof(NewLateBinding).GetMethod("FallbackIndexSetComplex"), target.Expression, Expression.NewArrayInit(typeof(object), expressionArray2), Expression.Constant(argNames, typeof(string[])), Expression.Constant(this._optimisticSet), Expression.Constant(this._rValueBase)), expression2), IDOUtils.CreateRestrictions(target, packedIndexes, value)); }
public override Dyn.DynamicMetaObject FallbackConvert(Dyn.DynamicMetaObject target, Dyn.DynamicMetaObject errorSuggestion) { if (!target.HasValue) { return(Defer(target)); } if (target.LimitType.IsSubclassOf(typeof(Any))) { return(new Dyn.DynamicMetaObject(Expression.Convert(target.Expression, typeof(Any)), target.Restrictions.Merge(Dyn.BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)))); } if (target.Value == null) { return(new Dyn.DynamicMetaObject(Expression.Constant(Any.None, typeof(Any)), Dyn.BindingRestrictions.GetInstanceRestriction(target.Expression, null))); } var targetExpression = target.Expression; if (targetExpression.Type != target.LimitType) { targetExpression = Expression.Convert(targetExpression, target.LimitType); } var restrictions = target.Restrictions .Merge(Dyn.BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)); var converter = converters[target.LimitType]; return(new Dyn.DynamicMetaObject(converter(targetExpression), restrictions)); }
private DynamicMetaObject MakeDeleteMemberTarget(SetOrDeleteMemberInfo delInfo, DynamicMetaObject target, DynamicMetaObject errorSuggestion) { Type type = target.GetLimitType(); BindingRestrictions restrictions = target.Restrictions; DynamicMetaObject self = target; if (typeof(TypeTracker).IsAssignableFrom(type)) { restrictions = restrictions.Merge( BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value) ); type = ((TypeTracker)target.Value).Type; self = null; } delInfo.Body.Restrictions = restrictions; if (self == null || !MakeOperatorDeleteMemberBody(delInfo, self, type, "DeleteMember")) { MemberGroup group = GetMember(MemberRequestKind.Delete, type, delInfo.Name); if (group.Count != 0) { if (group[0].MemberType == TrackerTypes.Property) { MethodInfo del = ((PropertyTracker)group[0]).GetDeleteMethod(PrivateBinding); if (del != null) { MakePropertyDeleteStatement(delInfo, self, del); return delInfo.Body.GetMetaObject(target); } } delInfo.Body.FinishCondition(errorSuggestion ?? MakeError(MakeUndeletableMemberError(GetDeclaringMemberType(group), delInfo.Name), typeof(void))); } else { delInfo.Body.FinishCondition(errorSuggestion ?? MakeError(MakeMissingMemberErrorForDelete(type, self, delInfo.Name), typeof(void))); } } return delInfo.Body.GetMetaObject(target); }
public override Dyn.DynamicMetaObject FallbackUnaryOperation(Dyn.DynamicMetaObject target, Dyn.DynamicMetaObject errorSuggestion) { if (!target.HasValue) { return(Defer(target)); } throw new NotImplementedException(); }
public override DYN.DynamicMetaObject FallbackGetIndex(DYN.DynamicMetaObject target, DYN.DynamicMetaObject[] indexes, DYN.DynamicMetaObject errorSuggestion) { DLR.Expression expression; DYN.BindingRestrictions restriction; if (indexes.Length == 1 && indexes[0].HasValue && indexes[0].Value == null) { restriction = DYN.BindingRestrictions.GetExpressionRestriction( DLR.Expression.Equal(indexes[0].Expression, DLR.Expression.Constant(null)) ); expression = target.Expression; } else { restriction = DYN.BindingRestrictions.GetTypeRestriction( indexes[0].Expression, typeof(List <Types.AType>) ); var indexer = DLR.Expression.Convert(indexes[0].Expression, typeof(List <Types.AType>)); var rankCheck = DLR.Expression.IfThen( DLR.Expression.LessThan( DLR.Expression.Property(target.Expression, "Rank"), DLR.Expression.Property(indexer, "Count") ), DLR.Expression.Throw( DLR.Expression.New(typeof(Error.Rank).GetConstructor(new Type[] { typeof(string) }), //DLR.Expression.Constant("[]") // FIXME-LATER: This is just for debug, so remove it later: DLR.Expression.Call( DLR.Expression.Property(indexer, "Count"), typeof(Int32).GetMethod("ToString", new Type[] { }) ) ) ) ); expression = DLR.Expression.Block( rankCheck, DLR.Expression.MakeIndex( DLR.Expression.Convert(target.Expression, typeof(Types.AType)), GetIndexBinder.AArrayIndexerProperty, new DLR.Expression[] { indexer } ) ); } DYN.DynamicMetaObject dynobj = new DYN.DynamicMetaObject( expression, DYN.BindingRestrictions.GetTypeRestriction(target.Expression, target.RuntimeType).Merge(restriction) ); return(dynobj); }
/// <summary> /// Prints the list of contexts /// </summary> /// <param name="scope"></param> /// <returns></returns> public static AType PrintContexts(DYN.IDynamicMetaObjectProvider scope) { DYN.DynamicMetaObject storage = scope.GetMetaObject( DLR.Expression.Property( DLR.Expression.Convert(DLR.Expression.Constant(scope), typeof(Scope)), "Storage" ) ); Console.WriteLine(String.Join(" ", storage.GetDynamicMemberNames())); return(Utils.ANull()); }
public override Dyn.DynamicMetaObject FallbackBinaryOperation(Dyn.DynamicMetaObject target, Dyn.DynamicMetaObject arg, Dyn.DynamicMetaObject errorSuggestion) { if (!target.HasValue || !arg.HasValue) { return(Defer(target, arg)); } var restrictions = target.Restrictions.Merge(arg.Restrictions) .Merge(Dyn.BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)) .Merge(Dyn.BindingRestrictions.GetTypeRestriction(arg.Expression, arg.LimitType)); throw new NotImplementedException(); }
private DynamicMetaObject CallMethod( MethodInfo method, Expression[] parameters ) { var callMethod = new System.Dynamic.DynamicMetaObject( System.Linq.Expressions.Expression.Call( System.Linq.Expressions.Expression.Convert(Expression, LimitType), method, parameters), System.Dynamic.BindingRestrictions.GetTypeRestriction(Expression, LimitType) ); return(callMethod); }
public override DYN.DynamicMetaObject FallbackConvert(DYN.DynamicMetaObject target, DYN.DynamicMetaObject errorSuggestion) { DYN.BindingRestrictions restriction = DYN.BindingRestrictions.GetTypeRestriction( target.Expression, target.RuntimeType ); // Found an AType, simply return the expression // We check if it implements the AType interface if (target.RuntimeType.GetInterface("AType") != null) { DYN.DynamicMetaObject result = new DYN.DynamicMetaObject( DLR.Expression.Convert(target.Expression, typeof(AType)), restriction ); return(result); } else if (target.RuntimeType.Name == "Int32") { DYN.DynamicMetaObject result = new DYN.DynamicMetaObject( // Create a new AInteger from the input value (need to convert to int first) DLR.Expression.Call( typeof(AInteger).GetMethod("Create", new Type[] { typeof(int) }), DLR.Expression.Convert(target.Expression, typeof(int)) ), restriction ); // .New AplusCore.Types.AInteger((System.Int32)$$arg0) return(result); } else if (target.RuntimeType.Name == "String") { DYN.DynamicMetaObject result = new DYN.DynamicMetaObject( DLR.Expression.Convert(target.Expression, typeof(AType), typeof(Helpers).GetMethod("BuildString") ), restriction ); return(result); } // TODO:: throw new NotImplementedException(); }
/// <summary> /// Performs the binding of the dynamic set member operation. /// </summary> /// <param name="binder">An instance of the <see cref="T:System.Dynamic.SetMemberBinder" /> that represents the details of the dynamic operation.</param> /// <param name="value">The <see cref="T:System.Dynamic.DynamicMetaObject" /> representing the value for the set member operation.</param> /// <returns>The new <see cref="T:System.Dynamic.DynamicMetaObject" /> representing the result of the binding.</returns> public override System.Dynamic.DynamicMetaObject BindSetMember(System.Dynamic.SetMemberBinder binder, System.Dynamic.DynamicMetaObject value) { var parameters = new System.Linq.Expressions.Expression[] { System.Linq.Expressions.Expression.Constant(binder.Name), value.Expression, }; var callMethod = CallMethod(setValueMethod, parameters); return(callMethod); }
/// <summary> /// /// </summary> /// <param name="target">The <see cref="CallbackItem"/> to use.</param> /// <param name="args"></param> /// <remarks> /// Order of items in the <see cref="args"/> array: /// <list type="number"> /// <item><see cref="Aplus"/></item> /// <item>New value for the global variable</item> /// </list> /// </remarks> /// <returns></returns> public override DYN.DynamicMetaObject Bind(DYN.DynamicMetaObject target, DYN.DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(target, "target"); ContractUtils.RequiresNotNullItems(args, "args"); if (target.HasValue && target.Value is CallbackItem) { CallbackItem callbackItem = (CallbackItem)target.Value; AFunc callbackAFunction = (AFunc)callbackItem.CallbackFunction.Data; DLR.Expression callbackItemExpression = DLR.Expression.Convert( target.Expression, typeof(CallbackItem) ); DYN.BindingRestrictions baseRestriction = DYN.BindingRestrictions.GetTypeRestriction( target.Expression, target.LimitType ); DLR.Expression callbackAFunctionExpression = DLR.Expression.Convert( DLR.Expression.Convert(target.Expression, typeof(CallbackItem)) .Property("CallbackFunction").Property("Data"), typeof(AFunc) ); DYN.BindingRestrictions valenceRestriction = DYN.BindingRestrictions.GetExpressionRestriction( DLR.Expression.Equal( callbackAFunctionExpression.Property("Valence"), DLR.Expression.Constant(callbackAFunction.Valence) ) ); // TODO: refactor the argument generation, something similar is in the InvokeBinder IEnumerable <DLR.Expression> callbackBaseArguments = new DLR.Expression[] { callbackItemExpression.Property("StaticData"), // static data DLR.Expression.Convert(args[1].Expression, typeof(AType)), // new value DLR.Expression.Convert(args[2].Expression, typeof(AType)), // index/set of indices DLR.Expression.Convert(args[3].Expression, typeof(AType)), // path (left argument of pick) callbackItemExpression.Property("Context"), // context of the global variable callbackItemExpression.Property("UnqualifiedName") // name of the global variable }.Where((item, i) => i < callbackAFunction.Valence - 1).Reverse(); List <DLR.Expression> callbackArguments = new List <DLR.Expression>(); // Aplus callbackArguments.Add(DLR.Expression.Convert(args[0].Expression, args[0].RuntimeType)); callbackArguments.AddRange(callbackBaseArguments); Type[] callTypes = new Type[callbackAFunction.Valence + 1]; callTypes[0] = typeof(Aplus); for (int i = 1; i < callbackAFunction.Valence; i++) { callTypes[i] = typeof(AType); } // return type callTypes[callbackAFunction.Valence] = typeof(AType); DLR.Expression codeBlock = DLR.Expression.Invoke( DLR.Expression.Convert( callbackAFunctionExpression.Property("Method"), DLR.Expression.GetFuncType(callTypes) ), callbackArguments ); DYN.DynamicMetaObject dynobj = new DYN.DynamicMetaObject(codeBlock, baseRestriction.Merge(valenceRestriction)); return(dynobj); } // Throw a non-function error return(new DYN.DynamicMetaObject( DLR.Expression.Throw( DLR.Expression.New( typeof(Error.NonFunction).GetConstructor(new Type[] { typeof(string) }), DLR.Expression.Call( target.Expression, typeof(object).GetMethod("ToString") ) ), typeof(Error.NonFunction) ), DYN.BindingRestrictions.GetTypeRestriction(target.Expression, target.RuntimeType) )); }
public override DYN.DynamicMetaObject FallbackInvoke(DYN.DynamicMetaObject target, DYN.DynamicMetaObject[] args, DYN.DynamicMetaObject errorSuggestion) { if (target.HasValue && target.Value is AReference && ((AReference)target.Value).Data is AFunc) { DLR.Expression dataExpression = DLR.Expression.PropertyOrField( DLR.Expression.Convert(target.Expression, typeof(AType)), "Data" ); DYN.BindingRestrictions baseRestriction = DYN.BindingRestrictions.GetTypeRestriction( target.Expression, target.LimitType ); DYN.BindingRestrictions builtinRestriction; DYN.BindingRestrictions restriction; DLR.Expression targetExpression = DLR.Expression.Convert(dataExpression, typeof(AFunc)); // Func<..> types (argument types + return type) Type[] callTypes; // Convert every function parameters to AType DLR.Expression[] callArguments; DLR.Expression codeBlock = null; if (((AFunc)((AReference)target.Value).Data).IsBuiltin) { switch (this.CallInfo.ArgumentCount) { case 2: callTypes = new Type[args.Length + 2]; callArguments = new DLR.Expression[args.Length + 1]; BuildArguments(args, callTypes, callArguments); // Add the missing infos: callTypes[2] = typeof(AType); callArguments[2] = DLR.Expression.Constant(null, typeof(AType)); // Build the codeblock for the method invoke codeBlock = BuildInvoke(targetExpression, callTypes, callArguments); break; case 3: callTypes = new Type[args.Length + 1]; callArguments = new DLR.Expression[args.Length]; BuildArguments(args, callTypes, callArguments); // Build the codeblock for the method invoke codeBlock = BuildInvoke(targetExpression, callTypes, callArguments); break; default: // Every other case is invalid... codeBlock = DLR.Expression.Block( DLR.Expression.Throw( DLR.Expression.New( typeof(Error.Valence).GetConstructor(new Type[] { typeof(string) }), DLR.Expression.Property(targetExpression, "Name") ) ), DLR.Expression.Default(typeof(AType)) ); break; } builtinRestriction = DYN.BindingRestrictions.GetExpressionRestriction( DLR.Expression.IsTrue(DLR.Expression.Property(targetExpression, "IsBuiltin")) ); } else { callTypes = new Type[args.Length + 1]; callArguments = new DLR.Expression[args.Length]; BuildArguments(args, callTypes, callArguments); codeBlock = DLR.Expression.Block( // Check if the function we are calling have the correct valence DLR.Expression.IfThen( DLR.Expression.NotEqual( DLR.Expression.Property(targetExpression, "Valence"), DLR.Expression.Constant(this.CallInfo.ArgumentCount) ), // Function's valence is incorrect throw error DLR.Expression.Throw( DLR.Expression.New( typeof(Error.Valence).GetConstructor(new Type[] { typeof(string) }), DLR.Expression.Property(targetExpression, "Name") ) ) ), // Function's valence is OK // Call the function BuildInvoke(targetExpression, callTypes, callArguments) ); builtinRestriction = DYN.BindingRestrictions.GetExpressionRestriction( DLR.Expression.IsFalse(DLR.Expression.Property(targetExpression, "IsBuiltin")) ); } restriction = baseRestriction.Merge(builtinRestriction); DYN.DynamicMetaObject dynobj = new DYN.DynamicMetaObject(codeBlock, restriction); return(dynobj); } // Throw a non-function error return(new DYN.DynamicMetaObject( DLR.Expression.Throw( DLR.Expression.New( typeof(Error.NonFunction).GetConstructor(new Type[] { typeof(string) }), DLR.Expression.Call( target.Expression, typeof(object).GetMethod("ToString") ) ), typeof(Error.NonFunction) ), DYN.BindingRestrictions.GetTypeRestriction(target.Expression, target.RuntimeType) )); }
public override DYN.DynamicMetaObject FallbackSetMember(DYN.DynamicMetaObject target, DYN.DynamicMetaObject value, DYN.DynamicMetaObject errorSuggestion) { // NOTE: silently ignore everything for now... return(null); // TODO: fix this! }
public override Dyn.DynamicMetaObject FallbackGetIndex(Dyn.DynamicMetaObject target, Dyn.DynamicMetaObject[] indexes, Dyn.DynamicMetaObject errorSuggestion) { throw new NotImplementedException(); }
/// <summary> /// When overridden in the derived class, performs the binding of the dynamic get index operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic get index operation.</param> /// <param name="indexes">The arguments of the dynamic get index operation.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public abstract DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion);
public override Dyn.DynamicMetaObject FallbackSetMember(Dyn.DynamicMetaObject target, Dyn.DynamicMetaObject value, Dyn.DynamicMetaObject errorSuggestion) { throw new NotImplementedException(); }
public override DYN.DynamicMetaObject FallbackSetIndex(DYN.DynamicMetaObject target, DYN.DynamicMetaObject[] indexes, DYN.DynamicMetaObject value, DYN.DynamicMetaObject errorSuggestion) { DLR.Expression expression; DYN.BindingRestrictions restriction; // TODO: Fix this: add restirction to AType interface //// check if the target implements the AType interface //if (target.RuntimeType.GetInterface("AType") == null) //{ // dynobj = new DYN.DynamicMetaObject( // DLR.Expression.Block( // DLR.Expression.Throw( // DLR.Expression.New( // typeof(Error.Mismatch).GetConstructor(new Type[] { typeof(string) }), // DLR.Expression.Constant( // String.Format("No indexing defined on '{0}'", target.RuntimeType.ToString()) // ) // ) // ), // value.Expression // ), // restriction // ); // return dynobj; //} if (indexes.Length == 1 && indexes[0].HasValue && indexes[0].Value == null) { restriction = DYN.BindingRestrictions.GetExpressionRestriction( DLR.Expression.Equal(indexes[0].Expression, DLR.Expression.Constant(null)) ); BindingFlags searchFlags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public; expression = DLR.Expression.Block( DLR.Expression.Call( null, typeof(Utils).GetMethod("PerformAssign", searchFlags), DLR.Expression.Convert(target.Expression, typeof(AType)), DLR.Expression.Convert(value.Expression, typeof(AType)) ), value.Expression ); } else { // $target[$indexes] = $value; restriction = DYN.BindingRestrictions.GetTypeRestriction( indexes[0].Expression, typeof(List <Types.AType>) ); var indexer = DLR.Expression.Convert(indexes[0].Expression, typeof(List <Types.AType>)); var rankCheck = DLR.Expression.IfThen( DLR.Expression.LessThan( DLR.Expression.Property(target.Expression, "Rank"), DLR.Expression.Property(indexer, "Count") ), DLR.Expression.Throw( DLR.Expression.New(typeof(Error.Rank).GetConstructor(new Type[] { typeof(string) }), //DLR.Expression.Constant("[]") // FIXME-LATER: This is just for debug, so remove it later: DLR.Expression.Call( DLR.Expression.Property(indexer, "Count"), typeof(Int32).GetMethod("ToString", new Type[] { }) ) ) ) ); expression = DLR.Expression.Block( typeof(Types.AType), rankCheck, DLR.Expression.Assign( DLR.Expression.MakeIndex( DLR.Expression.Convert(Tools.CloneMemoryMappedFile(target.Expression), typeof(Types.AType)), SetIndexBinder.AArrayIndexerProperty, new DLR.Expression[] { indexer } ), value.Expression ), value.Expression ); } DYN.DynamicMetaObject dynobj = new DYN.DynamicMetaObject( expression, DYN.BindingRestrictions.GetTypeRestriction(target.Expression, target.RuntimeType).Merge(restriction) ); return(dynobj); }
public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { return(default(DynamicMetaObject)); }
public DynamicMetaObject FallbackGetMember(DynamicMetaObject target) { return(default(DynamicMetaObject)); }
public DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args) { return(this.FallbackInvokeMember(target, args, null)); }
public abstract DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion);
public abstract DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion);
public abstract DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion);
public override Dyn.DynamicMetaObject FallbackInvoke(Dyn.DynamicMetaObject target, Dyn.DynamicMetaObject[] args, Dyn.DynamicMetaObject errorSuggestion) { throw new NotImplementedException(); }
public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(target, "target"); ContractUtils.RequiresNotNullItems <DynamicMetaObject>(args, "args"); return(target.BindInvokeMember(this, args)); }
public abstract DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args);
public DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg) { return(this.FallbackBinaryOperation(target, arg, null)); }
/// <summary> /// Performs the binding of the dynamic create operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic create operation.</param> /// <param name="args">The arguments of the dynamic create operation.</param> /// <returns>The <see cref="DynamicMetaObject" /> representing the result of the binding.</returns> public DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args) { return(FallbackCreateInstance(target, args, null)); }
public sealed override Expression Bind(object[] args, ReadOnlyCollection <ParameterExpression> parameters, LabelTarget returnLabel) { Type returnType; ContractUtils.RequiresNotNull(args, "args"); ContractUtils.RequiresNotNull(parameters, "parameters"); ContractUtils.RequiresNotNull(returnLabel, "returnLabel"); if (args.Length == 0) { throw Error.OutOfRange("args.Length", 1); } if (parameters.Count == 0) { throw Error.OutOfRange("parameters.Count", 1); } if (args.Length != parameters.Count) { throw new ArgumentOutOfRangeException("args"); } if (this.IsStandardBinder) { returnType = this.ReturnType; if ((returnLabel.Type != typeof(void)) && !TypeUtils.AreReferenceAssignable(returnLabel.Type, returnType)) { throw Error.BinderNotCompatibleWithCallSite(returnType, this, returnLabel.Type); } } else { returnType = returnLabel.Type; } DynamicMetaObject target = DynamicMetaObject.Create(args[0], parameters[0]); DynamicMetaObject[] objArray = CreateArgumentMetaObjects(args, parameters); DynamicMetaObject obj3 = this.Bind(target, objArray); if (obj3 == null) { throw Error.BindingCannotBeNull(); } Expression expression = obj3.Expression; BindingRestrictions restrictions = obj3.Restrictions; if ((returnType != typeof(void)) && !TypeUtils.AreReferenceAssignable(returnType, expression.Type)) { if (target.Value is IDynamicMetaObjectProvider) { throw Error.DynamicObjectResultNotAssignable(expression.Type, target.Value.GetType(), this, returnType); } throw Error.DynamicBinderResultNotAssignable(expression.Type, this, returnType); } if ((this.IsStandardBinder && (args[0] is IDynamicMetaObjectProvider)) && (restrictions == BindingRestrictions.Empty)) { throw Error.DynamicBindingNeedsRestrictions(target.Value.GetType(), this); } restrictions = AddRemoteObjectRestrictions(restrictions, args, parameters); if (expression.NodeType != ExpressionType.Goto) { expression = Expression.Return(returnLabel, expression); } if (restrictions != BindingRestrictions.Empty) { expression = Expression.IfThen(restrictions.ToExpression(), expression); } return(expression); }
/// <summary> /// Performs the runtime binding of the dynamic operation on a set of arguments. /// </summary> /// <param name="args">An array of arguments to the dynamic operation.</param> /// <param name="parameters">The array of <see cref="ParameterExpression"/> instances that represent the parameters of the call site in the binding process.</param> /// <param name="returnLabel">A LabelTarget used to return the result of the dynamic binding.</param> /// <returns> /// An Expression that performs tests on the dynamic operation arguments, and /// performs the dynamic operation if the tests are valid. If the tests fail on /// subsequent occurrences of the dynamic operation, Bind will be called again /// to produce a new <see cref="Expression"/> for the new argument types. /// </returns> public sealed override Expression Bind(object[] args, ReadOnlyCollection <ParameterExpression> parameters, LabelTarget returnLabel) { ContractUtils.RequiresNotNull(args, "args"); ContractUtils.RequiresNotNull(parameters, "parameters"); ContractUtils.RequiresNotNull(returnLabel, "returnLabel"); if (args.Length == 0) { throw Error.OutOfRange("args.Length", 1); } if (parameters.Count == 0) { throw Error.OutOfRange("parameters.Count", 1); } if (args.Length != parameters.Count) { throw new ArgumentOutOfRangeException(nameof(args)); } // Ensure that the binder's ReturnType matches CallSite's return // type. We do this so meta objects and language binders can // compose trees together without needing to insert converts. Type expectedResult; if (IsStandardBinder) { expectedResult = ReturnType; if (returnLabel.Type != typeof(void) && !TypeUtils.AreReferenceAssignable(returnLabel.Type, expectedResult)) { throw Error.BinderNotCompatibleWithCallSite(expectedResult, this, returnLabel.Type); } } else { // Even for non-standard binders, we have to at least make sure // it works with the CallSite's type to build the return. expectedResult = returnLabel.Type; } DynamicMetaObject target = DynamicMetaObject.Create(args[0], parameters[0]); DynamicMetaObject[] metaArgs = CreateArgumentMetaObjects(args, parameters); DynamicMetaObject binding = Bind(target, metaArgs); if (binding == null) { throw Error.BindingCannotBeNull(); } Expression body = binding.Expression; BindingRestrictions restrictions = binding.Restrictions; // Ensure the result matches the expected result type. if (expectedResult != typeof(void) && !TypeUtils.AreReferenceAssignable(expectedResult, body.Type)) { // // Blame the last person that handled the result: assume it's // the dynamic object (if any), otherwise blame the language. // if (target.Value is IDynamicMetaObjectProvider) { throw Error.DynamicObjectResultNotAssignable(body.Type, target.Value.GetType(), this, expectedResult); } else { throw Error.DynamicBinderResultNotAssignable(body.Type, this, expectedResult); } } // if the target is IDO, standard binders ask it to bind the rule so we may have a target-specific binding. // it makes sense to restrict on the target's type in such cases. // ideally IDO metaobjects should do this, but they often miss that type of "this" is significant. if (IsStandardBinder && args[0] as IDynamicMetaObjectProvider != null) { if (restrictions == BindingRestrictions.Empty) { throw Error.DynamicBindingNeedsRestrictions(target.Value.GetType(), this); } } // Add the return if (body.NodeType != ExpressionType.Goto) { body = Expression.Return(returnLabel, body); } // Finally, add restrictions if (restrictions != BindingRestrictions.Empty) { body = Expression.IfThen(restrictions.ToExpression(), body); } return(body); }
/// <summary> /// When overridden in the derived class, performs the binding of the dynamic create operation if the target dynamic /// object cannot bind. /// </summary> /// <param name="target">The target of the dynamic create operation.</param> /// <param name="args">The arguments of the dynamic create operation.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject" /> representing the result of the binding.</returns> public abstract DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion);