public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { return(new DynamicMetaObject( Expression.Constant("FallbackSetMember"), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) )); }
public DynamicMetaObject MakeCallExpression(OverloadResolverFactory resolverFactory, MethodInfo method, params DynamicMetaObject[] parameters) { OverloadResolver resolver; if (method.IsStatic) { resolver = resolverFactory.CreateOverloadResolver(parameters, new CallSignature(parameters.Length), CallTypes.None); } else { resolver = resolverFactory.CreateOverloadResolver(parameters, new CallSignature(parameters.Length - 1), CallTypes.ImplicitInstance); } BindingTarget target = resolver.ResolveOverload(method.Name, new MethodBase[] { method }, NarrowingLevel.None, NarrowingLevel.All); if (!target.Success) { BindingRestrictions restrictions = BindingRestrictions.Combine(parameters); foreach (DynamicMetaObject mo in parameters) { restrictions = restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(mo.Expression, mo.GetLimitType())); } return(DefaultBinder.MakeError( resolver.MakeInvalidParametersError(target), restrictions, typeof(object) )); } return(new DynamicMetaObject(target.MakeExpression(), target.RestrictedArguments.GetAllRestrictions())); }
private DynamicMetaObject MakeArrayIndexRule(OverloadResolverFactory factory, IndexType oper, DynamicMetaObject[] args) { if (CanConvertFrom(GetArgType(args, 1), typeof(int), false, NarrowingLevel.All)) { BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args)); if (oper == IndexType.Get) { return(new DynamicMetaObject( Expression.ArrayAccess( args[0].Expression, ConvertIfNeeded(factory, args[1].Expression, typeof(int)) ), restrictions )); } return(new DynamicMetaObject( Expression.Assign( Expression.ArrayAccess( args[0].Expression, ConvertIfNeeded(factory, args[1].Expression, typeof(int)) ), ConvertIfNeeded(factory, args[2].Expression, args[0].GetLimitType().GetElementType()) ), restrictions.Merge(args[1].Restrictions) )); } return(null); }
public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { return(new DynamicMetaObject( Expression.Constant(_result, ReturnType), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) )); }
public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { if (target.HasValue && target.Value == null) { return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(String.Format("Cannot call {0} method named {1} on nil", _isStatic ? "static" : "instance", this.Name))), typeof(object)), BindingRestrictions.GetInstanceRestriction(target.Expression, null))); } Type typeToUse = _isStatic && target.Value is Type ? (Type)target.Value : target.LimitType; IList <DynamicMetaObject> argsPlus = new List <DynamicMetaObject>(args.Length + (_isStatic ? 0 : 1)); if (!_isStatic) { argsPlus.Add(target); } foreach (DynamicMetaObject arg in args) { argsPlus.Add(arg); } OverloadResolverFactory factory = _context.SharedOverloadResolverFactory; DefaultOverloadResolver res = factory.CreateOverloadResolver(argsPlus, new CallSignature(args.Length), _isStatic ? CallTypes.None : CallTypes.ImplicitInstance); BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Public | (_isStatic ? BindingFlags.Static : BindingFlags.Instance); IList <MethodBase> methods = new List <MethodBase>(typeToUse.GetMethods(flags).Where <MethodBase>(x => x.Name == Name && x.GetParameters().Length == args.Length)); if (methods.Count > 0) { BindingTarget bt; DynamicMetaObject dmo = _context.Binder.CallMethod( res, methods, target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target).Merge(BindingRestrictions.Combine(args))), Name, NarrowingLevel.None, NarrowingLevel.All, out bt); dmo = DynUtils.MaybeBoxReturnValue(dmo); //; Console.WriteLine(dmo.Expression.DebugView); return(dmo); } return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(String.Format("No matching member {0} taking {1} args for {2}", this.Name, args.Length, typeToUse.Name))), typeof(object)), target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target).Merge(BindingRestrictions.Combine(args))))); }
private static DynamicMetaObject MakeCallSignatureResult(MethodBase[] methods, DynamicMetaObject target) { List <string> arrres = new List <string>(); if (methods != null) { foreach (MethodBase mb in methods) { StringBuilder res = new StringBuilder(); string comma = ""; foreach (ParameterInfo param in mb.GetParameters()) { res.Append(comma); res.Append(param.ParameterType.Name); res.Append(" "); res.Append(param.Name); comma = ", "; } arrres.Add(res.ToString()); } } return(new DynamicMetaObject( AstUtils.Constant(arrres.ToArray()), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target.Expression, target.GetLimitType()).Merge(target.Restrictions) )); }
public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { return(new DynamicMetaObject( Expression.Constant("FallbackInvoke"), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) )); }
private static DynamicMetaObject TryPrimitiveCompare(OperatorInfo info, DynamicMetaObject[] args) { if (args[0].GetLimitType().GetNonNullableType() == args[1].GetLimitType().GetNonNullableType() && args[0].GetLimitType().IsNumeric()) { Expression arg0 = args[0].Expression; Expression arg1 = args[1].Expression; // TODO: Nullable<PrimitveType> Support Expression expr; switch (info.Operator) { case ExpressionType.Equal: expr = Expression.Equal(arg0, arg1); break; case ExpressionType.NotEqual: expr = Expression.NotEqual(arg0, arg1); break; case ExpressionType.GreaterThan: expr = Expression.GreaterThan(arg0, arg1); break; case ExpressionType.LessThan: expr = Expression.LessThan(arg0, arg1); break; case ExpressionType.GreaterThanOrEqual: expr = Expression.GreaterThanOrEqual(arg0, arg1); break; case ExpressionType.LessThanOrEqual: expr = Expression.LessThanOrEqual(arg0, arg1); break; default: throw new InvalidOperationException(); } return(new DynamicMetaObject( expr, BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg0, args[0].GetLimitType()).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg1, args[0].GetLimitType())).Merge(BindingRestrictions.Combine(args)) )); } return(null); }
public DynamicMetaObject ConvertTo(Type toType, ConversionResultKind kind, DynamicMetaObject arg, OverloadResolverFactory resolverFactory, DynamicMetaObject errorSuggestion) { ContractUtils.RequiresNotNull(toType, nameof(toType)); ContractUtils.RequiresNotNull(arg, nameof(arg)); // 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); }
/// <summary> /// Transforms an invoke member into a Python GetMember/Invoke. The caller should /// verify that the given attribute is not resolved against a normal .NET class /// before calling this. If it is a normal .NET member then a fallback InvokeMember /// is preferred. /// </summary> internal static DynamicMetaObject /*!*/ GenericInvokeMember(InvokeMemberBinder /*!*/ action, ValidationInfo valInfo, DynamicMetaObject target, DynamicMetaObject /*!*/[] /*!*/ args) { if (target.NeedsDeferral()) { return(action.Defer(args)); } return(AddDynamicTestAndDefer(action, action.FallbackInvoke( new DynamicMetaObject( Binders.Get( PythonContext.GetCodeContext(action), PythonContext.GetPythonContext(action), typeof(object), action.Name, target.Expression ), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) ), args, null ), args, valInfo )); }
private BindingRestrictions EnumRestrictions() { return(BindingRestrictionsHelpers.GetRuntimeTypeRestriction( Expression, typeof(ComTypeEnumDesc) ).Merge( // ((ComTypeEnumDesc)<arg>).TypeLib.Guid == <guid> BindingRestrictions.GetExpressionRestriction( Expression.Equal( Expression.Property( Expression.Property( AstUtils.Convert(Expression, typeof(ComTypeEnumDesc)), typeof(ComTypeDesc).GetProperty("TypeLib")), typeof(ComTypeLibDesc).GetProperty("Guid")), AstUtils.Constant(_desc.TypeLib.Guid) ) ) ).Merge( BindingRestrictions.GetExpressionRestriction( Expression.Equal( Expression.Property( AstUtils.Convert(Expression, typeof(ComTypeEnumDesc)), typeof(ComTypeEnumDesc).GetProperty("TypeName") ), AstUtils.Constant(_desc.TypeName) ) ) )); }
/// <summary> /// Creates a nested dynamic site which uses the unpacked arguments. /// </summary> internal DynamicMetaObject InvokeForeignObject(DynamicMetaObject target, DynamicMetaObject[] args) { // need to unpack any dict / list arguments... CallInfo callInfo; List <Expression> metaArgs; Expression test; BindingRestrictions restrictions; TranslateArguments(target, args, out callInfo, out metaArgs, out test, out restrictions); Debug.Assert(metaArgs.Count > 0); return(BindingHelpers.AddDynamicTestAndDefer( this, new DynamicMetaObject( DynamicExpression.Dynamic( _context.CompatInvoke(callInfo), typeof(object), metaArgs.ToArray() ), restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target.Expression, target.GetLimitType())) ), args, new ValidationInfo(test) )); }
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { if (target.HasValue && target.Value == null) { return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(String.Format("Cannot call {0} field/property/member name {1} on nil", _isStatic ? "static" : "instance", this.Name))), typeof(object)), BindingRestrictions.GetInstanceRestriction(target.Expression, null))); } Expression instanceExpr = _isStatic ? null : Expression.Convert(target.Expression, target.LimitType); Type typeToUse = _isStatic && target.Value is Type ? (Type)target.Value : target.LimitType; BindingRestrictions restrictions = target.Restrictions.Merge(BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)); BindingFlags flags = BindingFlags.Public; if (_isStatic) { flags |= BindingFlags.Static; } else { flags |= BindingFlags.Instance; } FieldInfo finfo = typeToUse.GetField(Name, flags); if (finfo != null) { return(DynUtils.MaybeBoxReturnValue(new DynamicMetaObject(Expression.Field(instanceExpr, finfo), restrictions))); } PropertyInfo pinfo = typeToUse.GetProperty(Name, flags); if (pinfo != null) { return(DynUtils.MaybeBoxReturnValue(new DynamicMetaObject(Expression.Property(instanceExpr, pinfo), restrictions))); } MethodInfo minfo = typeToUse.GetMethod(Name, flags, Type.DefaultBinder, Type.EmptyTypes, new ParameterModifier[0]); if (minfo != null) { return(DynUtils.MaybeBoxReturnValue(new DynamicMetaObject(Expression.Call(instanceExpr, minfo), restrictions))); } return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(String.Format("Cannot find {0} field/property/member name {1}", _isStatic ? "static" : "instance", this.Name))), typeof(object)), target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target)))); }
public static SlotOrFunction /*!*/ GetSlotOrFunction(PythonContext /*!*/ state, string op, params DynamicMetaObject[] types) { PythonTypeSlot slot; SlotOrFunction res; if (TryGetBinder(state, types, op, null, out res)) { if (res != SlotOrFunction.Empty) { return(res); } } else if (MetaUserObject.GetPythonType(types[0]).TryResolveSlot(state.SharedContext, op, out slot)) { ParameterExpression tmp = Ast.Variable(typeof(object), "slotVal"); Expression[] args = new Expression[types.Length - 1]; for (int i = 1; i < types.Length; i++) { args[i - 1] = types[i].Expression; } return(new SlotOrFunction( new DynamicMetaObject( Ast.Block( new ParameterExpression[] { tmp }, MetaPythonObject.MakeTryGetTypeMember( state, slot, tmp, types[0].Expression, Ast.Call( typeof(DynamicHelpers).GetMethod("GetPythonType"), types[0].Expression ) ), DynamicExpression.Dynamic( state.Invoke( new CallSignature(args.Length) ), typeof(object), ArrayUtils.Insert <Expression>( AstUtils.Constant(state.SharedContext), tmp, args ) ) ), BindingRestrictions.Combine(types).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(types[0].Expression, types[0].GetLimitType())) ), slot )); } return(SlotOrFunction.Empty); }
private DynamicMetaObject GetForeignObject(DynamicMetaObject self) { return(new DynamicMetaObject( Expression.Dynamic( _context.CompatGetMember(Name, IsNoThrow), typeof(object), self.Expression ), self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, self.GetLimitType())) )); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { return(new DynamicMetaObject( Expression.Call( typeof(String).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }), Expression.Constant("FallbackInvoke"), target.Expression ), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) )); }
public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { return(new DynamicMetaObject( Expression.Call( typeof(String).GetMethod("Concat", new Type[] { typeof(object), typeof(object), typeof(object) }), Expression.Constant("FallbackSetIndex:"), indexes[0].Expression, value.Expression ), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) )); }
private DynamicMetaObject MakeCannotCallRule(DynamicMetaObject self, Type type) { return MakeError( ErrorInfo.FromException( Expression.New( typeof(ArgumentTypeException).GetConstructor(new Type[] { typeof(string) }), AstUtils.Constant(GetTypeName(type) + " is not callable") ) ), self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, type)), typeof(object) ); }
/// <summary> /// Builds the restrictions for calling with a splatted argument array. Ensures that the /// argument is still an ICollection of object and that it has the same number of arguments. /// </summary> private static BindingRestrictions MakeParamsTest(DynamicMetaObject splattee, bool testTypes) { IList <object> list = splattee.Value as IList <object>; if (list == null) { if (splattee.Value == null) { return(BindingRestrictions.GetExpressionRestriction(Ast.Equal(splattee.Expression, AstUtils.Constant(null)))); } else { return(BindingRestrictions.GetTypeRestriction(splattee.Expression, splattee.Value.GetType())); } } BindingRestrictions res = BindingRestrictions.GetExpressionRestriction( Ast.AndAlso( Ast.TypeIs(splattee.Expression, typeof(IList <object>)), Ast.Equal( Ast.Property( Ast.Convert(splattee.Expression, typeof(IList <object>)), typeof(ICollection <object>).GetDeclaredProperty("Count") ), AstUtils.Constant(list.Count) ) ) ); if (testTypes) { for (int i = 0; i < list.Count; i++) { res = res.Merge( BindingRestrictionsHelpers.GetRuntimeTypeRestriction( Ast.Call( AstUtils.Convert( splattee.Expression, typeof(IList <object>) ), typeof(IList <object>).GetMethod("get_Item"), AstUtils.Constant(i) ), CompilerHelpers.GetType(list[i]) ) ); } } return(res); }
/// <summary> /// Produces a rule for comparing a value to null - supports comparing object references and nullable types. /// </summary> private static DynamicMetaObject TryNullComparisonRule(DynamicMetaObject[] args) { Type otherType = args[1].GetLimitType(); BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args)); if (args[0].GetLimitType() == typeof(DynamicNull)) { if (!otherType.IsValueType) { return(new DynamicMetaObject( Expression.Equal(args[0].Expression, AstUtils.Constant(null)), restrictions )); } if (otherType.GetGenericTypeDefinition() == typeof(Nullable <>)) { return(new DynamicMetaObject( Expression.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")), restrictions )); } } else if (otherType == typeof(DynamicNull)) { if (!args[0].GetLimitType().IsValueType) { return(new DynamicMetaObject( Expression.Equal(args[0].Expression, AstUtils.Constant(null)), restrictions )); } if (args[0].GetLimitType().GetGenericTypeDefinition() == typeof(Nullable <>)) { return(new DynamicMetaObject( Expression.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")), restrictions )); } } return(null); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { Expression[] exprs = new Expression[args.Length + 1]; exprs[0] = Expression.Constant("FallbackInvoke"); for (int i = 0; i < args.Length; i++) { exprs[i + 1] = args[i].Expression; } return(new DynamicMetaObject( Expression.Call( typeof(String).GetMethod("Concat", new Type[] { typeof(object[]) }), Expression.NewArrayInit( typeof(object), exprs ) ), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) )); }
public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { var newTarget = new DynamicMetaObject(Expression.Convert(target.Expression, target.LimitType), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), target.Value); var exp = TryConvertExpression(newTarget.Expression, Type, null); if (exp == null) { exp = Expression.Throw(Expression.Constant(new InvalidCastException()), Type); } if (ReturnType != Type) { exp = Expression.Convert(exp, ReturnType); } var ret = _context.Binder.ConvertTo( Type, Explicit ? Microsoft.Scripting.Actions.ConversionResultKind.ExplicitCast : Microsoft.Scripting.Actions.ConversionResultKind.ImplicitCast, newTarget, new TjsOverloadResolverFactory(_context.Binder), new DynamicMetaObject(exp, BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target)) ); return(ret); }
private static DynamicMetaObject TryMakeDefaultUnaryRule(OperatorInfo info, DynamicMetaObject[] args) { if (args.Length == 1) { BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args)); switch (info.Operator) { case ExpressionType.IsTrue: if (args[0].GetLimitType() == typeof(bool)) { return(args[0]); } break; case ExpressionType.Negate: if (args[0].GetLimitType().IsArithmetic()) { return(new DynamicMetaObject( Expression.Negate(args[0].Expression), restrictions )); } break; case ExpressionType.Not: if (args[0].GetLimitType().IsIntegerOrBool()) { return(new DynamicMetaObject( Expression.Not(args[0].Expression), restrictions )); } break; } } return(null); }
public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { var restrictions = target.Restrictions.Merge( BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target)); //target = target.Restrict(target.RuntimeType); //args = args.Select(o => o.Restrict(o.RuntimeType)).ToArray(); MethodBase targetMethod; switch (Name) { case "SelectMany": targetMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where( o => o.Name == Name).Skip(3).First().MakeGenericMethod( typeof(object), typeof(object), typeof(object)); break; default: targetMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where( o => o.Name == Name).First().MakeGenericMethod( typeof(object), typeof(object)); break; } foreach (var o in args) { restrictions = restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(o)); } return(_binder.CallMethod( new DefaultOverloadResolver(_binder, target, args.ToList(), new CallSignature(args.Length)), new[] { targetMethod }, restrictions, Name)); }
/// <summary> /// Translates our CallSignature into a DLR Argument list and gives the simple MetaObject's which are extracted /// from the tuple or dictionary parameters being splatted. /// </summary> private void TranslateArguments(DynamicMetaObject target, DynamicMetaObject /*!*/[] /*!*/ args, out CallInfo /*!*/ callInfo, out List <Expression /*!*/> /*!*/ metaArgs, out Expression test, out BindingRestrictions restrictions) { Argument[] argInfo = _signature.GetArgumentInfos(); List <string> namedArgNames = new List <string>(); metaArgs = new List <Expression>(); metaArgs.Add(target.Expression); Expression splatArgTest = null; Expression splatKwArgTest = null; restrictions = BindingRestrictions.Empty; for (int i = 0; i < argInfo.Length; i++) { Argument ai = argInfo[i]; switch (ai.Kind) { case ArgumentType.Dictionary: PythonDictionary iac = (PythonDictionary)args[i].Value; List <string> argNames = new List <string>(); foreach (KeyValuePair <object, object> kvp in iac) { string key = (string)kvp.Key; namedArgNames.Add(key); argNames.Add(key); metaArgs.Add( Expression.Call( AstUtils.Convert(args[i].Expression, typeof(PythonDictionary)), typeof(PythonDictionary).GetMethod("get_Item", new[] { typeof(object) }), AstUtils.Constant(key) ) ); } restrictions = restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[i].Expression, args[i].GetLimitType())); splatKwArgTest = Expression.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.CheckDictionaryMembers)), AstUtils.Convert(args[i].Expression, typeof(PythonDictionary)), AstUtils.Constant(argNames.ToArray()) ); break; case ArgumentType.List: IList <object> splattedArgs = (IList <object>)args[i].Value; splatArgTest = Expression.Equal( Expression.Property(AstUtils.Convert(args[i].Expression, args[i].GetLimitType()), typeof(ICollection <object>).GetProperty("Count")), AstUtils.Constant(splattedArgs.Count) ); for (int splattedArg = 0; splattedArg < splattedArgs.Count; splattedArg++) { metaArgs.Add( Expression.Call( AstUtils.Convert(args[i].Expression, typeof(IList <object>)), typeof(IList <object>).GetMethod("get_Item"), AstUtils.Constant(splattedArg) ) ); } restrictions = restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[i].Expression, args[i].GetLimitType())); break; case ArgumentType.Named: namedArgNames.Add(ai.Name); metaArgs.Add(args[i].Expression); break; case ArgumentType.Simple: metaArgs.Add(args[i].Expression); break; default: throw new InvalidOperationException(); } } callInfo = new CallInfo(metaArgs.Count - 1, namedArgNames.ToArray()); test = splatArgTest; if (splatKwArgTest != null) { test = test != null?Expression.AndAlso(test, splatKwArgTest) : splatKwArgTest; } }
private DynamicMetaObject /*!*/ MakeSelfCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args) { BindingRestrictions selfRestrict = Restrictions.Merge( BindingRestrictionsHelpers.GetRuntimeTypeRestriction( Expression, LimitType ) ).Merge( BindingRestrictions.GetExpressionRestriction( Value.MakeBoundFunctionTest( AstUtils.Convert(Expression, typeof(BuiltinFunction)) ) ) ); Expression instance = Ast.Call( typeof(PythonOps).GetMethod("GetBuiltinFunctionSelf"), AstUtils.Convert( Expression, typeof(BuiltinFunction) ) ); DynamicMetaObject self = GetInstance(instance, CompilerHelpers.GetType(Value.BindingSelf)); return(Value.MakeBuiltinFunctionCall( call, codeContext, this, ArrayUtils.Insert(self, args), true, // has self selfRestrict, (newArgs) => { CallSignature signature = BindingHelpers.GetCallSignature(call); DynamicMetaObject res; PythonContext state = PythonContext.GetPythonContext(call); BindingTarget target; PythonOverloadResolver resolver; if (Value.IsReversedOperator) { resolver = new PythonOverloadResolver( state.Binder, newArgs, GetReversedSignature(signature), codeContext ); } else { resolver = new PythonOverloadResolver( state.Binder, self, args, signature, codeContext ); } res = state.Binder.CallMethod( resolver, Value.Targets, self.Restrictions, Value.Name, NarrowingLevel.None, Value.IsBinaryOperator ? PythonNarrowing.BinaryOperator : NarrowingLevel.All, out target ); return BindingHelpers.CheckLightThrow(call, res, target); } )); }
internal DynamicMetaObject FallbackConvert(Type returnType, DynamicMetaObject self, DynamicMetaObject errorSuggestion) { Type type = Type; DynamicMetaObject res = null; switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: res = MakeToBoolConversion(self); break; case TypeCode.Char: res = TryToCharConversion(self); break; case TypeCode.String: if (self.GetLimitType() == typeof(Bytes) && !_context.PythonOptions.Python30) { res = new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("MakeString"), AstUtils.Convert(self.Expression, typeof(IList <byte>)) ), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, typeof(Bytes)) ); } break; case TypeCode.Object: // !!! Deferral? if (type.IsArray && self.Value is PythonTuple && type.GetArrayRank() == 1) { res = MakeToArrayConversion(self, type); } else if (type.IsGenericType && !type.IsAssignableFrom(CompilerHelpers.GetType(self.Value))) { Type genTo = type.GetGenericTypeDefinition(); // Interface conversion helpers... if (genTo == typeof(IList <>)) { if (self.LimitType == typeof(string)) { res = new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("MakeByteArray"), AstUtils.Convert(self.Expression, typeof(string)) ), BindingRestrictions.GetTypeRestriction( self.Expression, typeof(string) ) ); } else { res = TryToGenericInterfaceConversion(self, type, typeof(IList <object>), typeof(ListGenericWrapper <>)); } } else if (genTo == typeof(IDictionary <,>)) { res = TryToGenericInterfaceConversion(self, type, typeof(IDictionary <object, object>), typeof(DictionaryGenericWrapper <,>)); } else if (genTo == typeof(IEnumerable <>)) { res = TryToGenericInterfaceConversion(self, type, typeof(IEnumerable), typeof(IEnumerableOfTWrapper <>)); } } else if (type == typeof(IEnumerable)) { if (!typeof(IEnumerable).IsAssignableFrom(self.GetLimitType()) && IsIndexless(self)) { res = ConvertToIEnumerable(this, self.Restrict(self.GetLimitType())); } } else if (type == typeof(IEnumerator)) { if (!typeof(IEnumerator).IsAssignableFrom(self.GetLimitType()) && !typeof(IEnumerable).IsAssignableFrom(self.GetLimitType()) && IsIndexless(self)) { res = ConvertToIEnumerator(this, self.Restrict(self.GetLimitType())); } } break; } if (type.IsEnum && Enum.GetUnderlyingType(type) == self.GetLimitType()) { // numeric type to enum, this is ok if the value is zero object value = Activator.CreateInstance(type); return(new DynamicMetaObject( Ast.Condition( Ast.Equal( AstUtils.Convert(self.Expression, Enum.GetUnderlyingType(type)), AstUtils.Constant(Activator.CreateInstance(self.GetLimitType())) ), AstUtils.Constant(value), Ast.Call( typeof(PythonOps).GetMethod("TypeErrorForBadEnumConversion").MakeGenericMethod(type), AstUtils.Convert(self.Expression, typeof(object)) ) ), self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, self.GetLimitType())), value )); } return(res ?? EnsureReturnType(returnType, Context.Binder.ConvertTo(Type, ResultKind, self, _context.SharedOverloadResolverFactory, errorSuggestion))); }
internal static DynamicMetaObject TranslateArguments(DynamicMetaObjectBinder call, Expression codeContext, DynamicMetaObject function, DynamicMetaObject /*!*/[] args, bool hasSelf, string name) { if (hasSelf) { args = ArrayUtils.RemoveFirst(args); } CallSignature sig = BindingHelpers.GetCallSignature(call); if (sig.HasDictionaryArgument()) { int index = sig.IndexOf(ArgumentType.Dictionary); DynamicMetaObject dict = args[index]; if (!(dict.Value is IDictionary) && dict.Value != null) { // The DefaultBinder only handles types that implement IDictionary. Here we have an // arbitrary user-defined mapping type. We'll convert it into a PythonDictionary // and then have an embedded dynamic site pass that dictionary through to the default // binder. DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args); dynamicArgs[index + 1] = new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.UserMappingToPythonDictionary)), codeContext, args[index].Expression, AstUtils.Constant(name) ), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()), PythonOps.UserMappingToPythonDictionary(PythonContext.GetPythonContext(call).SharedContext, dict.Value, name) ); if (call is IPythonSite) { dynamicArgs = ArrayUtils.Insert( new DynamicMetaObject(codeContext, BindingRestrictions.Empty), dynamicArgs ); } return(new DynamicMetaObject( DynamicExpression.Dynamic( call, typeof(object), DynamicUtils.GetExpressions(dynamicArgs) ), BindingRestrictions.Combine(dynamicArgs).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType())) )); } } if (sig.HasListArgument()) { int index = sig.IndexOf(ArgumentType.List); DynamicMetaObject str = args[index]; // TODO: ANything w/ __iter__ that's not an IList<object> if (!(str.Value is IList <object>) && str.Value is IEnumerable) { // The DefaultBinder only handles types that implement IList<object>. Here we have a // string. We'll convert it into a tuple // and then have an embedded dynamic site pass that tuple through to the default // binder. DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args); dynamicArgs[index + 1] = new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.MakeTupleFromSequence)), Expression.Convert(args[index].Expression, typeof(object)) ), BindingRestrictions.Empty ); if (call is IPythonSite) { dynamicArgs = ArrayUtils.Insert( new DynamicMetaObject(codeContext, BindingRestrictions.Empty), dynamicArgs ); } return(new DynamicMetaObject( DynamicExpression.Dynamic( call, typeof(object), DynamicUtils.GetExpressions(dynamicArgs) ), function.Restrictions.Merge( BindingRestrictions.Combine(args).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(str.Expression, str.GetLimitType())) ) )); } } return(null); }
private DynamicMetaObject /*!*/ GetInstance(Expression /*!*/ instance, Type /*!*/ testType) { Assert.NotNull(instance, testType); object instanceValue = Value.BindingSelf; BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(instance, testType); // cast the instance to the correct type if (CompilerHelpers.IsStrongBox(instanceValue)) { instance = ReadStrongBoxValue(instance); instanceValue = ((IStrongBox)instanceValue).Value; } else if (!testType.IsEnum) { // We need to deal w/ wierd types like MarshalByRefObject. // We could have an MBRO whos DeclaringType is completely different. // Therefore we special case it here and cast to the declaring type Type selfType = CompilerHelpers.GetType(Value.BindingSelf); selfType = CompilerHelpers.GetVisibleType(selfType); if (selfType == typeof(object) && Value.DeclaringType.IsInterface) { selfType = Value.DeclaringType; Type genericTypeDefinition = null; if (Value.DeclaringType.IsGenericType && Value.DeclaringType.FullName == null && Value.DeclaringType.ContainsGenericParameters && !Value.DeclaringType.IsGenericTypeDefinition) { // from MSDN: If the current type contains generic type parameters that have not been replaced by // specific types (that is, the ContainsGenericParameters property returns true), but the type // is not a generic type definition (that is, the IsGenericTypeDefinition property returns false), // this property returns Nothing. For example, consider the classes Base and Derived in the following code. // if this type is completely generic (no type arguments specified) then we'll go ahead and get the // generic type definition for the this parameter - that'll let us successfully type infer on it later. var genericArgs = Value.DeclaringType.GetGenericArguments(); bool hasOnlyGenerics = genericArgs.Length > 0; foreach (var genericParam in genericArgs) { if (!genericParam.IsGenericParameter) { hasOnlyGenerics = false; break; } } if (hasOnlyGenerics) { genericTypeDefinition = Value.DeclaringType.GetGenericTypeDefinition(); } } else if (Value.DeclaringType.IsGenericTypeDefinition) { genericTypeDefinition = Value.DeclaringType; } if (genericTypeDefinition != null) { // we're a generic interface method on a non-public type. // We need to see if we can match any types implemented on // the concrete selfType. var interfaces = CompilerHelpers.GetType(Value.BindingSelf).GetInterfaces(); foreach (var iface in interfaces) { if (iface.IsGenericType && iface.GetGenericTypeDefinition() == genericTypeDefinition) { selfType = iface; break; } } } } if (Value.DeclaringType.IsInterface && selfType.IsValueType) { // explicit interface implementation dispatch on a value type, don't // unbox the value type before the dispatch. instance = AstUtils.Convert(instance, Value.DeclaringType); } else if (selfType.IsValueType) { // We might be calling a a mutating method (like // Rectangle.Intersect). If so, we want it to mutate // the boxed value directly instance = Ast.Unbox(instance, selfType); } else { #if SILVERLIGHT instance = AstUtils.Convert(instance, selfType); #else Type convType = selfType == typeof(MarshalByRefObject) ? CompilerHelpers.GetVisibleType(Value.DeclaringType) : selfType; instance = AstUtils.Convert(instance, convType); #endif } } else { // we don't want to cast the enum to its real type, it will unbox it // and turn it into its underlying type. We presumably want to call // a method on the Enum class though - so we cast to Enum instead. instance = AstUtils.Convert(instance, typeof(Enum)); } return(new DynamicMetaObject( instance, restrictions, instanceValue )); }
/// <summary> /// Creating a Python type involves calling __new__ and __init__. We resolve them /// and generate calls to either the builtin funcions directly or embed sites which /// call the slots at runtime. /// </summary> private DynamicMetaObject /*!*/ MakePythonTypeCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args) { ValidationInfo valInfo = MakeVersionCheck(); DynamicMetaObject self = new RestrictedMetaObject( AstUtils.Convert(Expression, LimitType), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, LimitType), Value ); CallSignature sig = BindingHelpers.GetCallSignature(call); ArgumentValues ai = new ArgumentValues(sig, self, args); NewAdapter newAdapter; InitAdapter initAdapter; if (TooManyArgsForDefaultNew(call, args)) { return(MakeIncorrectArgumentsForCallError(call, ai, valInfo)); } else if (Value.UnderlyingSystemType.IsGenericTypeDefinition) { return(MakeGenericTypeDefinitionError(call, ai, valInfo)); } else if (Value.HasAbstractMethods(PythonContext.GetPythonContext(call).SharedContext)) { return(MakeAbstractInstantiationError(call, ai, valInfo)); } DynamicMetaObject translated = BuiltinFunction.TranslateArguments(call, codeContext, self, args, false, Value.Name); if (translated != null) { return(translated); } GetAdapters(ai, call, codeContext, out newAdapter, out initAdapter); PythonContext state = PythonContext.GetPythonContext(call); // get the expression for calling __new__ DynamicMetaObject createExpr = newAdapter.GetExpression(state.Binder); if (createExpr.Expression.Type == typeof(void)) { return(BindingHelpers.AddDynamicTestAndDefer( call, createExpr, args, valInfo )); } Expression res; BindingRestrictions additionalRestrictions = BindingRestrictions.Empty; if (!Value.IsSystemType && (!(newAdapter is DefaultNewAdapter) || HasFinalizer(call))) { // we need to dynamically check the return value to see if it's a subtype of // the type that we are calling. If it is then we need to call __init__/__del__ // for the actual returned type. res = Expression.Dynamic( Value.GetLateBoundInitBinder(sig), typeof(object), ArrayUtils.Insert( codeContext, Expression.Convert(createExpr.Expression, typeof(object)), DynamicUtils.GetExpressions(args) ) ); additionalRestrictions = createExpr.Restrictions; } else { // just call the __init__ method, built-in types currently have // no wacky return values which don't return the derived type. // then get the statement for calling __init__ ParameterExpression allocatedInst = Ast.Variable(createExpr.GetLimitType(), "newInst"); Expression tmpRead = allocatedInst; DynamicMetaObject initCall = initAdapter.MakeInitCall( state.Binder, new RestrictedMetaObject( AstUtils.Convert(allocatedInst, Value.UnderlyingSystemType), createExpr.Restrictions ) ); List <Expression> body = new List <Expression>(); Debug.Assert(!HasFinalizer(call)); // add the call to init if we need to if (initCall.Expression != tmpRead) { // init can fail but if __new__ returns a different type // no exception is raised. DynamicMetaObject initStmt = initCall; if (body.Count == 0) { body.Add( Ast.Assign(allocatedInst, createExpr.Expression) ); } if (!Value.UnderlyingSystemType.IsAssignableFrom(createExpr.Expression.Type)) { // return type of object, we need to check the return type before calling __init__. body.Add( AstUtils.IfThen( Ast.TypeIs(allocatedInst, Value.UnderlyingSystemType), initStmt.Expression ) ); } else { // just call the __init__ method, no type check necessary (TODO: need null check?) body.Add(initStmt.Expression); } } // and build the target from everything we have if (body.Count == 0) { res = createExpr.Expression; } else { body.Add(allocatedInst); res = Ast.Block(body); } res = Ast.Block(new ParameterExpression[] { allocatedInst }, res); additionalRestrictions = initCall.Restrictions; } return(BindingHelpers.AddDynamicTestAndDefer( call, new DynamicMetaObject( res, self.Restrictions.Merge(additionalRestrictions) ), ArrayUtils.Insert(this, args), valInfo )); }