예제 #1
0
            /// <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));
            }
예제 #2
0
        /// <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();
        }
예제 #3
0
            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));
            }
예제 #4
0
            /// <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)));
        }
예제 #6
0
        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));
        }
예제 #8
0
        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));
        }
예제 #9
0
 public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
 {
     ContractUtils.RequiresNotNull(binder, "binder");
     return(binder.Defer(args.AddFirst(WrapSelf())));
 }
예제 #10
0
 public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
 {
     return(ErrorMetaObject(ReturnType, target, args.AddFirst(target), errorSuggestion));
 }
예제 #11
0
 public override MetaObject FallbackInvoke(MetaObject target, MetaObject[] args, MetaObject onBindingError)
 {
     return(ErrorMetaObject(target, args.AddFirst(target), onBindingError));
 }
예제 #12
0
            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));
            }
예제 #13
0
 public static TReturnConstant AddFirstAndReturnConstant <TElement, TReturnConstant>(this TElement[] array, ref long position, IList <TElement> elements, TReturnConstant returnConstant)
 {
     array.AddFirst(ref position, elements);
     return(returnConstant);
 }
예제 #14
0
파일: Path.cs 프로젝트: dennis-apter/Exader
 public void AddRoot(T item)
 {
     items = items.AddFirst(item);
 }
예제 #15
0
 public void AddFirstTest()
 {
     _array.AddFirst(1);
     Assert.AreEqual(1, _array.GetSize());
 }
예제 #16
0
 public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
 {
     Requires.NotNull(binder, nameof(binder));
     return(binder.Defer(args.AddFirst(WrapSelf())));
 }
예제 #17
0
 public object Call(object[] args)
 {
     return(_site.Invoke(args.AddFirst(_func)));
 }
예제 #18
0
 public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
 {
     return(binder.Defer(args.AddFirst(WrapSelf())));
 }