Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / ListArgumentProvider.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
6  * copy of the license can be found in the License.html file at the root of this distribution. If 
7  * you cannot locate the  Apache License, Version 2.0, please send an email to 
8  * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
9  * by the terms of the Apache License, Version 2.0.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 using System;
17 using System.Collections.Generic;
18 using System.Text;
19 using System.Dynamic.Utils;
20
21 #if !FEATURE_CORE_DLR
22 namespace Microsoft.Scripting.Ast {
23 #else
24 namespace System.Linq.Expressions {
25 #endif
26     /// <summary>
27     /// Provides a wrapper around an IArgumentProvider which exposes the argument providers
28     /// members out as an IList of Expression.  This is used to avoid allocating an array
29     /// which needs to be stored inside of a ReadOnlyCollection.  Instead this type has
30     /// the same amount of overhead as an array without duplicating the storage of the
31     /// elements.  This ensures that internally we can avoid creating and copying arrays
32     /// while users of the Expression trees also don't pay a size penalty for this internal
33     /// optimization.  See IArgumentProvider for more general information on the Expression
34     /// tree optimizations being used here.
35     /// </summary>
36     class ListArgumentProvider : IList<Expression> {
37         private readonly IArgumentProvider _provider;
38         private readonly Expression _arg0;
39
40         internal ListArgumentProvider(IArgumentProvider provider, Expression arg0) {
41             _provider = provider;
42             _arg0 = arg0;
43         }
44
45         #region IList<Expression> Members
46
47         public int IndexOf(Expression item) {
48             if (_arg0 == item) {
49                 return 0;
50             }
51
52             for (int i = 1; i < _provider.ArgumentCount; i++) {
53                 if (_provider.GetArgument(i) == item) {
54                     return i;
55                 }
56             }
57
58             return -1;
59         }
60
61         public void Insert(int index, Expression item) {
62             throw ContractUtils.Unreachable;
63         }
64
65         public void RemoveAt(int index) {
66             throw ContractUtils.Unreachable;
67         }
68
69         public Expression this[int index] {
70             get {
71                 if (index == 0) {
72                     return _arg0;
73                 }
74
75                 return _provider.GetArgument(index);
76             }
77             set {
78                 throw ContractUtils.Unreachable;
79             }
80         }
81
82         #endregion
83
84         #region ICollection<Expression> Members
85
86         public void Add(Expression item) {
87             throw ContractUtils.Unreachable;
88         }
89
90         public void Clear() {
91             throw ContractUtils.Unreachable;
92         }
93
94         public bool Contains(Expression item) {
95             return IndexOf(item) != -1;
96         }
97
98         public void CopyTo(Expression[] array, int arrayIndex) {
99             array[arrayIndex++] = _arg0;
100             for (int i = 1; i < _provider.ArgumentCount; i++) {
101                 array[arrayIndex++] = _provider.GetArgument(i);
102             }
103         }
104
105         public int Count {
106             get { return _provider.ArgumentCount; }
107         }
108
109         public bool IsReadOnly {
110             get { return true; }
111         }
112
113         public bool Remove(Expression item) {
114             throw ContractUtils.Unreachable;
115         }
116
117         #endregion
118
119         #region IEnumerable<Expression> Members
120
121         public IEnumerator<Expression> GetEnumerator() {
122             yield return _arg0;
123
124             for (int i = 1; i < _provider.ArgumentCount; i++) {
125                 yield return _provider.GetArgument(i);
126             }
127         }
128
129         #endregion
130
131         #region IEnumerable Members
132
133         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
134             yield return _arg0;
135
136             for (int i = 1; i < _provider.ArgumentCount; i++) {
137                 yield return _provider.GetArgument(i);
138             }
139         }
140
141         #endregion
142     }
143 }