Welcome to mirror list, hosted at ThFree Co, Russian Federation.

HoistedLocals.cs « Compiler « Microsoft.Scripting.Core « Runtime « dlr « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ddb304be98628f4044924a79b23976d52a3468b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Apache License, Version 2.0, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Apache License, Version 2.0.
 *
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;
using System.Dynamic.Utils;

#if !FEATURE_CORE_DLR
namespace Microsoft.Scripting.Ast.Compiler {
#else
namespace System.Linq.Expressions.Compiler {
#endif

    // Suppose we have something like:
    //
    //    (string s)=>()=>s.
    //
    // We wish to generate the outer as:
    // 
    //      Func<string> OuterMethod(Closure closure, string s)
    //      {
    //          object[] locals = new object[1];
    //          locals[0] = new StrongBox<string>();
    //          ((StrongBox<string>)locals[0]).Value = s;
    //          return ((DynamicMethod)closure.Constants[0]).CreateDelegate(typeof(Func<string>), new Closure(null, locals));
    //      }
    //      
    // ... and the inner as:
    // 
    //      string InnerMethod(Closure closure)
    //      {
    //          object[] locals = closure.Locals;
    //          return ((StrongBox<string>)locals[0]).Value;
    //      }
    //
    // This class tracks that "s" was hoisted into a closure, as the 0th
    // element in the array
    //
    /// <summary>
    /// Stores information about locals and arguments that are hoisted into
    /// the closure array because they're referenced in an inner lambda.
    /// 
    /// This class is sometimes emitted as a runtime constant for internal
    /// use to hoist variables/parameters in quoted expressions
    /// 
    /// Invariant: this class stores no mutable state
    /// </summary>
    internal sealed class HoistedLocals {

        // The parent locals, if any
        internal readonly HoistedLocals Parent;

        // A mapping of hoisted variables to their indexes in the array
        internal readonly System.Dynamic.Utils.ReadOnlyDictionary<Expression, int> Indexes;

        // The variables, in the order they appear in the array
        internal readonly ReadOnlyCollection<ParameterExpression> Variables;

        // A virtual variable for accessing this locals array
        internal readonly ParameterExpression SelfVariable;

        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 System.Dynamic.Utils.ReadOnlyDictionary<Expression, int>(indexes);
        }

        internal ParameterExpression ParentVariable {
            get { return Parent != null ? Parent.SelfVariable : null; }
        }

        internal static object[] GetParent(object[] locals) {
            return ((StrongBox<object[]>)locals[0]).Value;
        }
    }
}