示例#1
0
                /// <summary>
                /// Creates a new compiler scope for inner expressions that establish a scope.
                /// </summary>
                /// <param name="parent">The parent scope.</param>
                /// <param name="scope">The scope information obtained during analysis.</param>
                public CompilerScope(CompilerScope parent, Scope scope)
                {
                    Parent = parent;
                    _scope = scope;

                    var locals  = new List <ParameterExpression>();
                    var hoisted = new List <ParameterExpression>();

                    //
                    // Get all variables that need hoisting. These will be registered in a
                    // HoistedLocals instance for runtime access in Quote and RuntimeVariables
                    // nodes. The remaining variables are kept as locals.
                    //
                    foreach (var local in scope.Locals)
                    {
                        var variable = local.Key;
                        var storage  = local.Value;

                        if (storage == StorageKind.Local)
                        {
                            locals.Add(variable);
                        }
                        else
                        {
                            hoisted.Add(variable);
                        }
                    }

                    _hoistedLocals = new HoistedLocals(parent._hoistedLocals, hoisted.AsReadOnly(), scope.Locals);
                    Closure        = _hoistedLocals.SelfVariable;

                    Locals = locals;
                }
示例#2
0
 /// <summary>
 /// Creates a new compiler scope for the top-level lambda.
 /// </summary>
 /// <param name="methodTable">The method table parameter.</param>
 public CompilerScope(ParameterExpression methodTable)
 {
     Parent         = null;
     _scope         = null;
     Closure        = methodTable;
     _hoistedLocals = new HoistedLocals(methodTable);
     Locals         = new List <ParameterExpression>();
 }
示例#3
0
        /// <summary>
        /// Creates a new object representing information about hoisted locals.
        /// </summary>
        /// <param name="parent">The parent scope.</param>
        /// <param name="variables">The hoisted locals in the current scope.</param>
        /// <param name="definitions">The storage kinds of the variables.</param>
        public HoistedLocals(HoistedLocals parent, ReadOnlyCollection <ParameterExpression> variables, Dictionary <ParameterExpression, StorageKind> definitions)
        {
            Parent      = parent;
            Definitions = definitions;

            //
            // By convention, we'll store the parent's self-variable in the first slot of the closure.
            //
            // Note that the self-variable is statically typed, so the whole closure and all its storage
            // slots are statically typed too, no matter how far we have to ascend through the parent
            // chain. This differs from LINQ ETs at the point of writing (10/10/16).
            //
            if (parent != null)
            {
                variables = variables.AddFirst(parent.SelfVariable);
            }

            Variables = variables;

            //
            // Next, build the index map and gather all the storage kinds for the hoisted locals in
            // order to create a statically typed closure. The index map will be used for runtime
            // variable access; the closure will be used to emit code to access the locals in the
            // compiled expression tree.
            //
            var count   = variables.Count;
            var indexes = new Dictionary <ParameterExpression, int>(count);
            var fields  = new List <KeyValuePair <ParameterExpression, StorageKind> >(count);

            for (var i = 0; i < count; i++)
            {
                var variable    = variables[i];
                var storageKind = variable == parent?.SelfVariable ? StorageKind.Hoisted : definitions[variable];

                indexes.Add(variable, i);
                fields.Add(new KeyValuePair <ParameterExpression, StorageKind>(variable, storageKind));
            }

            //
            // Build the closure and store the closure information. The static type of the closure
            // is used for the self-variable, resulting in static typing across the closure and its
            // parent chain.
            //
            Closure      = ClosureGenerator.Create(fields);
            SelfVariable = Expression.Variable(Closure.ClosureType, name: null);
            Indexes      = new ReadOnlyDictionary <ParameterExpression, int>(indexes);
        }