/// <summary> /// Helper method for generating a MetaObject which calls a /// specific method on Dynamic, but uses one of the arguments for /// the result. /// </summary> private MetaObject CallMethodNoResult(string methodName, MetaObjectBinder binder, Expression[] args, Fallback fallback) { // // First, call fallback to do default binding // This produces either an error or a call to a .NET member // MetaObject fallbackResult = fallback(null); // // Build a new expression like: // TryDeleteMember(payload) ? null : fallbackResult // var callDynamic = new MetaObject( Expression.Condition( Expression.Call( GetLimitedSelf(), typeof(DynamicObject).GetMethod(methodName), args.AddFirst(Constant(binder)) ), Expression.Constant(null), Expression.Convert(fallbackResult.Expression, typeof(object)) ), 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> /// Creates a lambda compiler that will compile into the provided Methodbuilder /// </summary> private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method) { _hasClosureArgument = tree.Scopes[lambda].NeedsClosure; Type[] paramTypes = GetParameterTypes(lambda); if (_hasClosureArgument) { paramTypes = paramTypes.AddFirst(typeof(Closure)); } method.SetReturnType(lambda.ReturnType); method.SetParameters(paramTypes); var paramNames = lambda.Parameters.Map(p => p.Name); // parameters are index from 1, with closure argument we need to skip the first arg int startIndex = _hasClosureArgument ? 2 : 1; for (int i = 0; i < paramNames.Length; i++) { method.DefineParameter(i + startIndex, ParameterAttributes.None, paramNames[i]); } _tree = tree; _lambda = lambda; _typeBuilder = (TypeBuilder)method.DeclaringType.GetTypeInfo(); _method = method; _ilg = method.GetILGenerator(); // These are populated by AnalyzeTree/VariableBinder _scope = tree.Scopes[lambda]; _boundConstants = tree.Constants[lambda]; InitializeMethod(); }
private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) { DynamicMetaObject obj2 = fallback(null); ParameterExpression left = Expression.Parameter(typeof(object), null); Expression[] arguments = args.AddFirst <Expression>(Constant(binder)); arguments[args.Length] = Expression.Assign(left, arguments[args.Length]); DynamicMetaObject errorSuggestion = new DynamicMetaObject(Expression.Block(new ParameterExpression[] { left }, new Expression[] { Expression.Condition(Expression.Call(this.GetLimitedSelf(), typeof(DynamicObject).GetMethod(methodName), arguments), left, obj2.Expression, typeof(object)) }), this.GetRestrictions().Merge(obj2.Restrictions)); return(fallback(errorSuggestion)); }
/// <summary> /// Helper method for generating a MetaObject which calls a /// specific method on Dynamic, but uses one of the arguments for /// the result. /// </summary> private DynamicMetaObject CallMethodReturnLast(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); // // Build a new expression like: // { // object result; // TrySetMember(payload, result = value) ? result : fallbackResult // } // var result = Expression.Parameter(typeof(object), null); var callArgs = args.AddFirst(Constant(binder)); callArgs[args.Length] = Expression.Assign(result, callArgs[args.Length]); var callDynamic = new DynamicMetaObject( Expression.Block( new[] { result }, Expression.Condition( Expression.Call( GetLimitedSelf(), typeof(DynamicObject).GetMethod(methodName), callArgs ), result, fallbackResult.Expression, typeof(object) ) ), 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)); }
System.Delegate Compile(TypeContext context, System.Type returnType, System.Type[] types, ParameterInfo[] parameters, System.Type delType) { var names = Parameters.Map(para => para.Name).AddFirst("closure"); // Emit First Argument var lamdaVisit = new LamdaVisitor(names); Body.Accept(lamdaVisit); var parameterTypes = types.AddFirst(typeof(Runtime.Closure)); var method = new System.Reflection.Emit.DynamicMethod(Name, returnType, parameterTypes, true); var methodGen = new Generators.DynamicMethodGenerator(method, parameters, null) { SyntaxBody = Body, Context = context }; methodGen.EmitParameterInfo(); var bodyGen = new MethodBodyGenerator(methodGen, method.GetILGenerator()); object[] values = new object[lamdaVisit.HoistedLocals.Count]; if (values.Length > 0) { int index = 0; var field = typeof(Runtime.Closure).GetField("Values"); foreach (var item in lamdaVisit.HoistedLocals) { var value = item.Value; values[index] = value.Accept(ScriptCompiler.Instance); // if binder is null variable or member may not exist if (value.NodeType == ExpressionType.Identifier && ((NameExpression)value).Binder is null) { continue; } var variable = bodyGen.DeclareVariable(value.Type, item.Key); // load closure argument bodyGen.LoadArgument(0); bodyGen.LoadField(field); bodyGen.LoadInt32(index); bodyGen.LoadArrayElement(typeof(object)); bodyGen.UnboxObject(value.Type); bodyGen.StoreVariable(variable); index++; } } bodyGen.Compile(); return(method.CreateDelegate(delType, new Runtime.Closure(values))); }
public void TestAdd() { var arr = new Array <int>(); arr.Add(0, 101); arr.AddFirst(9); arr.AddLast(200); arr.Add(0, 222); arr.Add(1, 555); Console.WriteLine(arr); var ret = new int[] { 222, 555, 9, 101, 200 }; Assert.AreEqual(arr.Size, ret.Length); for (var i = 0; i < ret.Length; i++) { Assert.AreEqual(ret[i], arr[i]); } }
public void AddFirstTest() { var peopleList = RandomData.GeneratePersonCollection <PersonProper>(10); var peopleArray = peopleList.ToArray(); var person = RandomData.GeneratePerson <PersonProper>(); // Collection test Assert.IsTrue(peopleList.AddFirst(person)); Assert.IsTrue(peopleList.First().Equals(person)); peopleList.AddFirst(null); Assert.IsTrue(peopleList.Count == peopleList.Count); _ = Assert.ThrowsException <ArgumentReadOnlyException>(() => peopleList.ToReadOnlyCollection() .AddFirst(person)); // Array Test var result2 = peopleArray.AddFirst(person); PersonProper[] nullArray = default(PersonProper[]); Assert.IsTrue(result2.First().Equals(person)); _ = Assert.ThrowsException <ArgumentNullException>(() => nullArray.AddFirst(null)); _ = Assert.ThrowsException <ArgumentReadOnlyException>(() => Array.AsReadOnly(result2).AddFirst(person)); }
private Expression GenerateTryBlock() { // // Declare variables // ParameterExpression excepInfo = Expression.Variable(typeof(ExcepInfo), "excepInfo"); ParameterExpression argErr = Expression.Variable(typeof(uint), "argErr"); ParameterExpression hresult = Expression.Variable(typeof(int), "hresult"); List <Expression> tryStatements = new List <Expression>(); Expression expr; if (_keywordArgNames.Length > 0) { string[] names = _keywordArgNames.AddFirst(_methodDesc.Name); tryStatements.Add( Expression.Assign( Expression.Field( DispParamsVariable, typeof(ComTypes.DISPPARAMS).GetField("rgdispidNamedArgs") ), Expression.Call(typeof(UnsafeMethods).GetMethod("GetIdsOfNamedParameters"), DispatchObjectVariable, Expression.Constant(names), DispIdVariable, DispIdsOfKeywordArgsPinnedVariable ) ) ); } // // Marshal the arguments to Variants // // For a call like this: // comObj.Foo(100, 101, 102, x=123, z=125) // DISPPARAMS needs to be setup like this: // cArgs: 5 // cNamedArgs: 2 // rgArgs: 123, 125, 102, 101, 100 // rgdispidNamedArgs: dispid x, dispid z (the dispids of x and z respectively) Expression[] parameters = MakeArgumentExpressions(); int reverseIndex = _varEnumSelector.VariantBuilders.Length - 1; int positionalArgs = _varEnumSelector.VariantBuilders.Length - _keywordArgNames.Length; // args passed by position order and not by name for (int i = 0; i < _varEnumSelector.VariantBuilders.Length; i++, reverseIndex--) { int variantIndex; if (i >= positionalArgs) { // Named arguments are in order at the start of rgArgs variantIndex = i - positionalArgs; } else { // Positial arguments are in reverse order at the tail of rgArgs variantIndex = reverseIndex; } VariantBuilder variantBuilder = _varEnumSelector.VariantBuilders[i]; Expression marshal = variantBuilder.InitializeArgumentVariant( VariantArray.GetStructField(ParamVariantsVariable, variantIndex), parameters[i + 1] ); if (marshal != null) { tryStatements.Add(marshal); } } // // Call Invoke // ComTypes.INVOKEKIND invokeKind; if (_methodDesc.IsPropertyPut) { if (_methodDesc.IsPropertyPutRef) { invokeKind = ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF; } else { invokeKind = ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT; } } else { // INVOKE_PROPERTYGET should only be needed for COM objects without typeinfo, where we might have to treat properties as methods invokeKind = ComTypes.INVOKEKIND.INVOKE_FUNC | ComTypes.INVOKEKIND.INVOKE_PROPERTYGET; } MethodCallExpression invoke = Expression.Call( typeof(UnsafeMethods).GetMethod("IDispatchInvoke"), DispatchPointerVariable, DispIdVariable, Expression.Constant(invokeKind), DispParamsVariable, InvokeResultVariable, excepInfo, argErr ); expr = Expression.Assign(hresult, invoke); tryStatements.Add(expr); // // ComRuntimeHelpers.CheckThrowException(hresult, excepInfo, argErr, ThisParameter); // expr = Expression.Call( typeof(ComRuntimeHelpers).GetMethod("CheckThrowException"), hresult, excepInfo, argErr, Expression.Constant(_methodDesc.Name, typeof(string)) ); tryStatements.Add(expr); // // _returnValue = (ReturnType)_invokeResult.ToObject(); // Expression invokeResultObject = Expression.Call( InvokeResultVariable, typeof(Variant).GetMethod("ToObject")); VariantBuilder[] variants = _varEnumSelector.VariantBuilders; Expression[] parametersForUpdates = MakeArgumentExpressions(); tryStatements.Add(Expression.Assign(ReturnValueVariable, invokeResultObject)); for (int i = 0, n = variants.Length; i < n; i++) { Expression updateFromReturn = variants[i].UpdateFromReturn(parametersForUpdates[i + 1]); if (updateFromReturn != null) { tryStatements.Add(updateFromReturn); } } tryStatements.Add(Expression.Empty()); return(Expression.Block(new[] { excepInfo, argErr, hresult }, tryStatements)); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(binder, "binder"); return(binder.Defer(args.AddFirst(WrapSelf()))); }
public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { return(ErrorMetaObject(ReturnType, target, args.AddFirst(target), errorSuggestion)); }
public override MetaObject FallbackInvoke(MetaObject target, MetaObject[] args, MetaObject onBindingError) { return(ErrorMetaObject(target, args.AddFirst(target), onBindingError)); }
private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) { DynamicMetaObject obj2 = fallback(null); DynamicMetaObject errorSuggestion = new DynamicMetaObject(Expression.Condition(Expression.Call(this.GetLimitedSelf(), typeof(DynamicObject).GetMethod(methodName), args.AddFirst <Expression>(Constant(binder))), Expression.Empty(), obj2.Expression, typeof(void)), this.GetRestrictions().Merge(obj2.Restrictions)); return(fallback(errorSuggestion)); }
public static TReturnConstant AddFirstAndReturnConstant <TElement, TReturnConstant>(this TElement[] array, ref long position, IList <TElement> elements, TReturnConstant returnConstant) { array.AddFirst(ref position, elements); return(returnConstant); }
public void AddRoot(T item) { items = items.AddFirst(item); }
public void AddFirstTest() { _array.AddFirst(1); Assert.AreEqual(1, _array.GetSize()); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { Requires.NotNull(binder, nameof(binder)); return(binder.Defer(args.AddFirst(WrapSelf()))); }
public object Call(object[] args) { return(_site.Invoke(args.AddFirst(_func))); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { return(binder.Defer(args.AddFirst(WrapSelf()))); }