internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection <ParameterExpression> vars)
 {
     if (this.NearestHoistedLocals != null)
     {
         List <long> list = new List <long>(vars.Count);
         foreach (ParameterExpression expression in vars)
         {
             ulong         num = 0L;
             HoistedLocals nearestHoistedLocals = this.NearestHoistedLocals;
             while (!nearestHoistedLocals.Indexes.ContainsKey(expression))
             {
                 num += (ulong)1L;
                 nearestHoistedLocals = nearestHoistedLocals.Parent;
             }
             ulong num2 = (num << 0x20) | ((ulong)nearestHoistedLocals.Indexes[expression]);
             list.Add((long)num2);
         }
         if (list.Count > 0)
         {
             this.EmitGet(this.NearestHoistedLocals.SelfVariable);
             lc.EmitConstantArray <long>(list.ToArray());
             lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", new Type[] { typeof(object[]), typeof(long[]) }));
             return;
         }
     }
     lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", Type.EmptyTypes));
 }
예제 #2
0
 private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals)
 {
     lc.EmitClosureArgument();
     lc.IL.Emit(OpCodes.Ldfld, typeof(Closure).GetField("Locals"));
     AddLocal(lc, locals.SelfVariable);
     EmitSet(locals.SelfVariable);
 }
예제 #3
0
 private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals)
 {
     lc.EmitClosureArgument();
     lc.IL.Emit(OpCodes.Ldfld, Closure_Locals);
     AddLocal(lc, locals.SelfVariable);
     EmitSet(locals.SelfVariable);
 }
 private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals)
 {
     if (locals != null)
     {
         this.EmitClosureToVariable(lc, locals);
         while ((locals = locals.Parent) != null)
         {
             ParameterExpression selfVariable = locals.SelfVariable;
             LocalStorage        storage      = new LocalStorage(lc, selfVariable);
             storage.EmitStore(this.ResolveVariable(selfVariable));
             this._locals.Add(selfVariable, storage);
         }
     }
 }
 internal HoistedLocals(HoistedLocals parent, ReadOnlyCollection<ParameterExpression> vars)
 {
     if (parent != null)
     {
         vars = new TrueReadOnlyCollection<ParameterExpression>(vars.AddFirst<ParameterExpression>(parent.SelfVariable));
     }
     Dictionary<Expression, int> dict = new Dictionary<Expression, int>(vars.Count);
     for (int i = 0; i < vars.Count; i++)
     {
         dict.Add(vars[i], i);
     }
     this.SelfVariable = Expression.Variable(typeof(object[]), null);
     this.Parent = parent;
     this.Variables = vars;
     this.Indexes = new ReadOnlyDictionary<Expression, int>(dict);
 }
예제 #6
0
        internal HoistedLocals(HoistedLocals parent, ReadOnlyCollection <ParameterExpression> vars)
        {
            if (parent != null)
            {
                vars = new TrueReadOnlyCollection <ParameterExpression>(vars.AddFirst <ParameterExpression>(parent.SelfVariable));
            }
            Dictionary <Expression, int> dict = new Dictionary <Expression, int>(vars.Count);

            for (int i = 0; i < vars.Count; i++)
            {
                dict.Add(vars[i], i);
            }
            this.SelfVariable = Expression.Variable(typeof(object[]), null);
            this.Parent       = parent;
            this.Variables    = vars;
            this.Indexes      = new ReadOnlyDictionary <Expression, int>(dict);
        }
        private void SetParent(LambdaCompiler lc, CompilerScope parent)
        {
            this._parent = parent;
            if (this.NeedsClosure && (this._parent != null))
            {
                this._closureHoistedLocals = this._parent.NearestHoistedLocals;
            }
            ReadOnlyCollection <ParameterExpression> vars = (from p in this.GetVariables()
                                                             where ((VariableStorageKind)this.Definitions[p]) == VariableStorageKind.Hoisted
                                                             select p).ToReadOnly <ParameterExpression>();

            if (vars.Count > 0)
            {
                this._hoistedLocals = new HoistedLocals(this._closureHoistedLocals, vars);
                this.AddLocal(lc, this._hoistedLocals.SelfVariable);
            }
        }
        internal CompilerScope Exit()
        {
            if (!this.IsMethod)
            {
                foreach (Storage storage in this._locals.Values)
                {
                    storage.FreeLocal();
                }
            }
            CompilerScope scope = this._parent;

            this._parent               = null;
            this._hoistedLocals        = null;
            this._closureHoistedLocals = null;
            this._locals.Clear();
            return(scope);
        }
예제 #9
0
        // Creates IL locals for accessing closures
        private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals)
        {
            if (locals == null)
            {
                return;
            }

            EmitClosureToVariable(lc, locals);

            while ((locals = locals.Parent) != null)
            {
                var v     = locals.SelfVariable;
                var local = new LocalStorage(lc, v);
                local.EmitStore(ResolveVariable(v));
                _locals.Add(v, local);
            }
        }
예제 #10
0
        private void SetParent(LambdaCompiler lc, CompilerScope parent)
        {
            Debug.Assert(_parent == null && parent != this);
            _parent = parent;

            if (NeedsClosure && _parent != null)
            {
                _closureHoistedLocals = _parent.NearestHoistedLocals;
            }

            var hoistedVars = GetVariables().Where(p => Definitions[p] == VariableStorageKind.Hoisted).ToReadOnly();

            if (hoistedVars.Count > 0)
            {
                _hoistedLocals = new HoistedLocals(_closureHoistedLocals, hoistedVars);
                AddLocal(lc, _hoistedLocals.SelfVariable);
            }
        }
예제 #11
0
        internal HoistedLocals(HoistedLocals parent, ReadOnlyCollection<ParameterExpression> vars)
        {
            if (parent != null)
            {
                // Add the parent locals array as the 0th element in the array
                vars = vars.AddFirst(parent.SelfVariable);
            }

            Dictionary<Expression, int> indexes = new Dictionary<Expression, int>(vars.Count);
            for (int i = 0; i < vars.Count; i++)
            {
                indexes.Add(vars[i], i);
            }

            SelfVariable = Expression.Variable(typeof(object[]), name: null);
            Parent = parent;
            Variables = vars;
            Indexes = new ReadOnlyDictionary<Expression, int>(indexes);
        }
예제 #12
0
        internal HoistedLocals(HoistedLocals parent, ReadOnlyCollection <ParameterExpression> vars)
        {
            if (parent != null)
            {
                // Add the parent locals array as the 0th element in the array
                vars = new TrueReadOnlyCollection <ParameterExpression>(vars.AddFirst(parent.SelfVariable));
            }

            Dictionary <Expression, int> indexes = new Dictionary <Expression, int>(vars.Count);

            for (int i = 0; i < vars.Count; i++)
            {
                indexes.Add(vars[i], i);
            }

            SelfVariable = Expression.Variable(typeof(object[]), null);
            Parent       = parent;
            Variables    = vars;
            Indexes      = new ReadOnlyDictionary <Expression, int>(indexes);
        }
예제 #13
0
        /// <summary>
        /// Resolve a local variable in this scope or a closed over scope
        /// Throws if the variable is defined
        /// </summary>
        private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals)
        {
            // Search IL locals and arguments, but only in this lambda
            for (CompilerScope s = this; s != null; s = s._parent)
            {
                Storage storage;
                if (s._locals.TryGetValue(variable, out storage))
                {
                    return(storage);
                }

                // if this is a lambda, we're done
                if (s.IsMethod)
                {
                    break;
                }
            }

            // search hoisted locals
            for (HoistedLocals h = hoistedLocals; h != null; h = h.Parent)
            {
                int index;
                if (h.Indexes.TryGetValue(variable, out index))
                {
                    return(new ElementBoxStorage(
                               ResolveVariable(h.SelfVariable, hoistedLocals),
                               index,
                               variable
                               ));
                }
            }

            //
            // If this is an unbound variable in the lambda, the error will be
            // thrown from VariableBinder. So an error here is generally caused
            // by an internal error, e.g. a scope was created but it bypassed
            // VariableBinder.
            //
            throw Error.UndefinedVariable(variable.Name, variable.Type, CurrentLambdaName);
        }
예제 #14
0
        /// <summary>
        ///     Frees unnamed locals, clears state associated with this compiler
        /// </summary>
        internal CompilerScope Exit()
        {
            // free scope's variables
            if (!IsMethod)
            {
                foreach (var storage in _locals.Values)
                {
                    storage.FreeLocal();
                }
            }

            // Clear state that is associated with this parent
            // (because the scope can be reused in another context)
            var parent = _parent;

            _parent               = null;
            _hoistedLocals        = null;
            _closureHoistedLocals = null;
            _locals.Clear();

            return(parent);
        }
예제 #15
0
        internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection <ParameterExpression> vars)
        {
            if (NearestHoistedLocals != null)
            {
                // Find what array each variable is on & its index
                var indexes = new List <long>(vars.Count);

                foreach (var variable in vars)
                {
                    // For each variable, find what array it's defined on
                    ulong         parents = 0;
                    HoistedLocals locals  = NearestHoistedLocals;
                    while (!locals.Indexes.ContainsKey(variable))
                    {
                        parents++;
                        locals = locals.Parent;
                        Debug.Assert(locals != null);
                    }

                    // combine the number of parents we walked, with the
                    // real index of variable to get the index to emit.
                    ulong index = (parents << 32) | (uint)locals.Indexes[variable];

                    indexes.Add((long)index);
                }

                if (indexes.Count > 0)
                {
                    EmitGet(NearestHoistedLocals.SelfVariable);
                    lc.EmitConstantArray(indexes.ToArray());
                    lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", new[] { typeof(object[]), typeof(long[]) }));
                    return;
                }
            }

            // No visible variables
            lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", Type.EmptyTypes));
            return;
        }
예제 #16
0
        private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals)
        {
            // Search IL locals and arguments, but only in this lambda
            for (var s = this; s != null; s = s._parent)
            {
                if (s._locals.TryGetValue(variable, out var storage))
                {
                    return(storage);
                }

                // if this is a lambda, we're done
                if (s.IsMethod)
                {
                    break;
                }
            }

            // search hoisted locals
            for (var h = hoistedLocals; h != null; h = h.Parent)
            {
                if (h.Indexes.TryGetValue(variable, out var index))
                {
                    return(new ElementBoxStorage
                           (
                               ResolveVariable(h.SelfVariable, hoistedLocals),
                               index,
                               variable
                           ));
                }
            }

            //
            // If this is an unbound variable in the lambda, the error will be
            // thrown from VariableBinder. So an error here is generally caused
            // by an internal error, e.g. a scope was created but it bypassed
            // VariableBinder.
            //
            throw new InvalidOperationException($"variable '{variable.Name}' of type '{variable.Type}' referenced from scope '{CurrentLambdaName}', but it is not defined");
        }
 private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals)
 {
     for (CompilerScope scope = this; scope != null; scope = scope._parent)
     {
         Storage storage;
         if (scope._locals.TryGetValue(variable, out storage))
         {
             return(storage);
         }
         if (scope.IsMethod)
         {
             break;
         }
     }
     for (HoistedLocals locals = hoistedLocals; locals != null; locals = locals.Parent)
     {
         int num;
         if (locals.Indexes.TryGetValue(variable, out num))
         {
             return(new ElementBoxStorage(this.ResolveVariable(locals.SelfVariable, hoistedLocals), num, variable));
         }
     }
     throw Error.UndefinedVariable(variable.Name, variable.Type, this.CurrentLambdaName);
 }
예제 #18
0
        /// <summary>
        /// Resolve a local variable in this scope or a closed over scope
        /// Throws if the variable is defined
        /// </summary>
        private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals)
        {
            // Search IL locals and arguments, but only in this lambda
            for (CompilerScope s = this; s != null; s = s._parent)
            {
                Storage storage;
                if (s._locals.TryGetValue(variable, out storage))
                {
                    return(storage);
                }

                // if this is a lambda, we're done
                if (s.IsLambda)
                {
                    break;
                }
            }

            // search hoisted locals
            for (HoistedLocals h = hoistedLocals; h != null; h = h.Parent)
            {
                int index;
                if (h.Indexes.TryGetValue(variable, out index))
                {
                    return(new ElementBoxStorage(
                               ResolveVariable(h.SelfVariable, hoistedLocals),
                               index,
                               variable
                               ));
                }
            }

            // If this is a genuine unbound variable, the error should be
            // thrown in VariableBinder.
            throw Error.UndefinedVariable(variable.Name, variable.Type, CurrentLambdaName);
        }
예제 #19
0
        internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection <ParameterExpression> vars)
        {
            if (NearestHoistedLocals != null && vars.Count > 0)
            {
                // Find what array each variable is on & its index
                var indexes = new ArrayBuilder <long>(vars.Count);

                foreach (var variable in vars)
                {
                    // For each variable, find what array it's defined on
                    ulong         parents = 0;
                    HoistedLocals locals  = NearestHoistedLocals;
                    while (!locals.Indexes.ContainsKey(variable))
                    {
                        parents++;
                        locals = locals.Parent;
                        Debug.Assert(locals != null);
                    }

                    // combine the number of parents we walked, with the
                    // real index of variable to get the index to emit.
                    ulong index = (parents << 32) | (uint)locals.Indexes[variable];

                    indexes.UncheckedAdd((long)index);
                }

                EmitGet(NearestHoistedLocals.SelfVariable);
                lc.EmitConstantArray(indexes.ToArray());
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables_ObjectArray_Int64Array);
            }
            else
            {
                // No visible variables
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables);
            }
        }
예제 #20
0
 private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals)
 {
     lc.EmitClosureArgument();
     lc.IL.Emit(OpCodes.Ldfld, Closure_Locals);
     AddLocal(lc, locals.SelfVariable);
     EmitSet(locals.SelfVariable);
 }
예제 #21
0
        /// <summary>
        /// Resolve a local variable in this scope or a closed over scope
        /// Throws if the variable is defined
        /// </summary>
        private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals) {
            // Search IL locals and arguments, but only in this lambda
            for (CompilerScope s = this; s != null; s = s._parent) {
                Storage storage;
                if (s._locals.TryGetValue(variable, out storage)) {
                    return storage;
                }

                // if this is a lambda, we're done
                if (s.IsLambda) {
                    break;
                }
            }

            // search hoisted locals
            for (HoistedLocals h = hoistedLocals; h != null; h = h.Parent) {
                int index;
                if (h.Indexes.TryGetValue(variable, out index)) {
                    return new ElementBoxStorage(
                        ResolveVariable(h.SelfVariable, hoistedLocals),
                        index,
                        variable
                    );
                }
            }

            // If this is a genuine unbound variable, the error should be
            // thrown in VariableBinder.
            throw Error.UndefinedVariable(variable.Name, variable.Type, CurrentLambdaName);
        }
예제 #22
0
        /// <summary>
        /// Frees unnamed locals, clears state associated with this compiler
        /// </summary>
        internal CompilerScope Exit()
        {
            // free scope's variables
            if (!IsMethod)
            {
                foreach (Storage storage in _locals.Values)
                {
                    storage.FreeLocal();
                }
            }

            // Clear state that is associated with this parent
            // (because the scope can be reused in another context)
            CompilerScope parent = _parent;
            _parent = null;
            _hoistedLocals = null;
            _closureHoistedLocals = null;
            _locals.Clear();

            return parent;
        }
예제 #23
0
        /// <summary>
        /// Resolve a local variable in this scope or a closed over scope
        /// Throws if the variable is not defined
        /// </summary>
        private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals)
        {
            // Search IL locals and arguments, but only in this lambda
            for (CompilerScope s = this; s != null; s = s._parent)
            {
                Storage storage;
                if (s._locals.TryGetValue(variable, out storage))
                {
                    return storage;
                }

                // if this is a lambda, we're done
                if (s.IsMethod)
                {
                    break;
                }
            }

            // search hoisted locals
            for (HoistedLocals h = hoistedLocals; h != null; h = h.Parent)
            {
                int index;
                if (h.Indexes.TryGetValue(variable, out index))
                {
                    return new ElementBoxStorage(
                        ResolveVariable(h.SelfVariable, hoistedLocals),
                        index,
                        variable
                    );
                }
            }

            //
            // If this is an unbound variable in the lambda, the error will be
            // thrown from VariableBinder. So an error here is generally caused
            // by an internal error, e.g. a scope was created but it bypassed
            // VariableBinder.
            //
            throw Error.UndefinedVariable(variable.Name, variable.Type, CurrentLambdaName);
        }
예제 #24
0
        private void SetParent(LambdaCompiler lc, CompilerScope parent)
        {
            Debug.Assert(_parent == null && parent != this);
            _parent = parent;

            if (NeedsClosure && _parent != null)
            {
                _closureHoistedLocals = _parent.NearestHoistedLocals;
            }

            ReadOnlyCollection<ParameterExpression> hoistedVars = GetVariables().Where(p => Definitions[p] == VariableStorageKind.Hoisted).ToReadOnly();

            if (hoistedVars.Count > 0)
            {
                _hoistedLocals = new HoistedLocals(_closureHoistedLocals, hoistedVars);
                AddLocal(lc, _hoistedLocals.SelfVariable);
            }
        }
예제 #25
0
        // Creates IL locals for accessing closures
        private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals)
        {
            if (locals == null)
            {
                return;
            }

            EmitClosureToVariable(lc, locals);

            while ((locals = locals.Parent) != null)
            {
                ParameterExpression v = locals.SelfVariable;
                var local = new LocalStorage(lc, v);
                local.EmitStore(ResolveVariable(v));
                _locals.Add(v, local);
            }
        }
 private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals)
 {
     lc.EmitClosureArgument();
     lc.IL.Emit(OpCodes.Ldfld, typeof(Closure).GetField("Locals"));
     this.AddLocal(lc, locals.SelfVariable);
     this.EmitSet(locals.SelfVariable);
 }
 internal CompilerScope Exit()
 {
     if (!this.IsMethod)
     {
         foreach (Storage storage in this._locals.Values)
         {
             storage.FreeLocal();
         }
     }
     CompilerScope scope = this._parent;
     this._parent = null;
     this._hoistedLocals = null;
     this._closureHoistedLocals = null;
     this._locals.Clear();
     return scope;
 }
 private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals)
 {
     if (locals != null)
     {
         this.EmitClosureToVariable(lc, locals);
         while ((locals = locals.Parent) != null)
         {
             ParameterExpression selfVariable = locals.SelfVariable;
             LocalStorage storage = new LocalStorage(lc, selfVariable);
             storage.EmitStore(this.ResolveVariable(selfVariable));
             this._locals.Add(selfVariable, storage);
         }
     }
 }
 private void SetParent(LambdaCompiler lc, CompilerScope parent)
 {
     this._parent = parent;
     if (this.NeedsClosure && (this._parent != null))
     {
         this._closureHoistedLocals = this._parent.NearestHoistedLocals;
     }
     ReadOnlyCollection<ParameterExpression> vars = (from p in this.GetVariables()
         where ((VariableStorageKind) this.Definitions[p]) == VariableStorageKind.Hoisted
         select p).ToReadOnly<ParameterExpression>();
     if (vars.Count > 0)
     {
         this._hoistedLocals = new HoistedLocals(this._closureHoistedLocals, vars);
         this.AddLocal(lc, this._hoistedLocals.SelfVariable);
     }
 }
 private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals)
 {
     for (CompilerScope scope = this; scope != null; scope = scope._parent)
     {
         Storage storage;
         if (scope._locals.TryGetValue(variable, out storage))
         {
             return storage;
         }
         if (scope.IsMethod)
         {
             break;
         }
     }
     for (HoistedLocals locals = hoistedLocals; locals != null; locals = locals.Parent)
     {
         int num;
         if (locals.Indexes.TryGetValue(variable, out num))
         {
             return new ElementBoxStorage(this.ResolveVariable(locals.SelfVariable, hoistedLocals), num, variable);
         }
     }
     throw Error.UndefinedVariable(variable.Name, variable.Type, this.CurrentLambdaName);
 }