Пример #1
0
 private Expression Convert(LinqExp.MethodCallExpression linqCall)
 {
     return(Expression.Call(
                ConvertExp(linqCall.Object),
                linqCall.Method,
                Convert(linqCall.Arguments)));
 }
Пример #2
0
        internal Expression Reduce()
        {
            // Visit body
            Expression body = Visit(_generator.Body);

            Debug.Assert(_returnLabels.Count == 1);

            // Add the switch statement to the body
            int count = _yields.Count;
            var cases = new SwitchCase[count + 1];

            for (int i = 0; i < count; i++)
            {
                cases[i] = Expression.SwitchCase(Expression.Goto(_yields[i].Label), AstUtils.Constant(_yields[i].State));
            }
            cases[count] = Expression.SwitchCase(Expression.Goto(_returnLabels.Peek()), AstUtils.Constant(Finished));

            Type generatorNextOfT = typeof(GeneratorNext <>).MakeGenericType(_generator.Target.Type);

            // Create the lambda for the GeneratorNext<T>, hoisting variables
            // into a scope outside the lambda
            var allVars = new List <ParameterExpression>(_vars);

            allVars.AddRange(_temps);

            // Collect temps that don't have to be closed over
            var innerTemps = new ReadOnlyCollectionBuilder <ParameterExpression>(1 + (_labelTemps != null ? _labelTemps.Count : 0));

            innerTemps.Add(_gotoRouter);
            if (_labelTemps != null)
            {
                foreach (LabelInfo info in _labelTemps.Values)
                {
                    innerTemps.Add(info.Temp);
                }
            }

            body = Expression.Block(
                allVars,
                Expression.Lambda(
                    generatorNextOfT,
                    Expression.Block(
                        innerTemps,
                        Expression.Switch(Expression.Assign(_gotoRouter, _state), cases),
                        body,
                        Expression.Assign(_state, AstUtils.Constant(Finished)),
                        Expression.Label(_returnLabels.Peek())
                        ),
                    _generator.Name,
                    new ParameterExpression[] { _state, _current }
                    )
                );

            // Enumerable factory takes Func<GeneratorNext<T>> instead of GeneratorNext<T>
            if (_generator.IsEnumerable)
            {
                body = Expression.Lambda(body);
            }

            // We can't create a ConstantExpression of _debugCookies array here because we walk the tree
            // after constants have already been rewritten.  Instead we create a NewArrayExpression node
            // which initializes the array with contents from _debugCookies
            Expression debugCookiesArray = null;

            if (_debugCookies != null)
            {
                Expression[] debugCookies = new Expression[_debugCookies.Count];
                for (int i = 0; i < _debugCookies.Count; i++)
                {
                    debugCookies[i] = AstUtils.Constant(_debugCookies[i]);
                }

                debugCookiesArray = Expression.NewArrayInit(
                    typeof(int),
                    debugCookies);
            }

            // Generate a call to ScriptingRuntimeHelpers.MakeGenerator<T>(args)
            return(Expression.Call(
                       typeof(ScriptingRuntimeHelpers),
                       "MakeGenerator",
                       new[] { _generator.Target.Type },
                       (debugCookiesArray != null)
                    ? new[] { body, debugCookiesArray }
                    : new[] { body }
                       ));
        }