Fix XMM scanning on Mac x86.
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / ElementInit.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.Collections.ObjectModel;
19 using System.Reflection;
20 using System.Text;
21 using System.Dynamic.Utils;
22
23 #if !FEATURE_CORE_DLR
24 namespace Microsoft.Scripting.Ast {
25 #else
26 namespace System.Linq.Expressions {
27 #endif
28     /// <summary>
29     /// Represents the initialization of a list.
30     /// </summary>
31     public sealed class ElementInit : IArgumentProvider {
32         private MethodInfo _addMethod;
33         private ReadOnlyCollection<Expression> _arguments;
34
35         internal ElementInit(MethodInfo addMethod, ReadOnlyCollection<Expression> arguments) {
36             _addMethod = addMethod;
37             _arguments = arguments;
38         }
39         /// <summary>
40         /// Gets the <see cref="MethodInfo"/> used to add elements to the object.
41         /// </summary>
42         public MethodInfo AddMethod {
43             get { return _addMethod; }
44         }
45
46         /// <summary>
47         /// Gets the list of elements to be added to the object.
48         /// </summary>
49         public ReadOnlyCollection<Expression> Arguments {
50             get { return _arguments; }
51         }
52
53         Expression IArgumentProvider.GetArgument(int index) {
54             return _arguments[index];
55         }
56
57         int IArgumentProvider.ArgumentCount {
58             get {
59                 return _arguments.Count;
60             }
61         }
62
63         /// <summary>
64         /// Creates a <see cref="String"/> representation of the node.
65         /// </summary>
66         /// <returns>A <see cref="String"/> representation of the node.</returns>
67         public override string ToString() {
68             return ExpressionStringBuilder.ElementInitBindingToString(this);
69         }
70
71         /// <summary>
72         /// Creates a new expression that is like this one, but using the
73         /// supplied children. If all of the children are the same, it will
74         /// return this expression.
75         /// </summary>
76         /// <param name="arguments">The <see cref="Arguments" /> property of the result.</param>
77         /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
78         public ElementInit Update(IEnumerable<Expression> arguments) {
79             if (arguments == Arguments) {
80                 return this;
81             }
82             return Expression.ElementInit(AddMethod, arguments);
83         }
84     }
85
86
87     public partial class Expression {
88         /// <summary>
89         /// Creates an <see cref="T:ElementInit">ElementInit</see> expression that represents the initialization of a list.
90         /// </summary>
91         /// <param name="addMethod">The <see cref="MethodInfo"/> for the list's Add method.</param>
92         /// <param name="arguments">An array containing the Expressions to be used to initialize the list.</param>
93         /// <returns>The created <see cref="T:ElementInit">ElementInit</see> expression.</returns>
94         public static ElementInit ElementInit(MethodInfo addMethod, params Expression[] arguments) {
95             return ElementInit(addMethod, arguments as IEnumerable<Expression>);
96         }
97
98         /// <summary>
99         /// Creates an <see cref="T:ElementInit">ElementInit</see> expression that represents the initialization of a list.
100         /// </summary>
101         /// <param name="addMethod">The <see cref="MethodInfo"/> for the list's Add method.</param>
102         /// <param name="arguments">An <see cref="IEnumerable{T}"/> containing <see cref="Expression"/> elements to initialize the list.</param>
103         /// <returns>The created <see cref="T:ElementInit">ElementInit</see> expression.</returns>
104         public static ElementInit ElementInit(MethodInfo addMethod, IEnumerable<Expression> arguments) {
105             ContractUtils.RequiresNotNull(addMethod, "addMethod");
106             ContractUtils.RequiresNotNull(arguments, "arguments");
107
108             var argumentsRO = arguments.ToReadOnly();
109
110             RequiresCanRead(argumentsRO, "arguments");
111             ValidateElementInitAddMethodInfo(addMethod);
112             ValidateArgumentTypes(addMethod, ExpressionType.Call, ref argumentsRO);
113             return new ElementInit(addMethod, argumentsRO);
114         }
115
116         private static void ValidateElementInitAddMethodInfo(MethodInfo addMethod) {
117             ValidateMethodInfo(addMethod);
118             ParameterInfo[] pis = addMethod.GetParametersCached();
119             if (pis.Length == 0) {
120                 throw Error.ElementInitializerMethodWithZeroArgs();
121             }
122             if (!addMethod.Name.Equals("Add", StringComparison.OrdinalIgnoreCase)) {
123                 throw Error.ElementInitializerMethodNotAdd();
124             }
125             if (addMethod.IsStatic) {
126                 throw Error.ElementInitializerMethodStatic();
127             }
128             foreach (ParameterInfo pi in pis) {
129                 if (pi.ParameterType.IsByRef) {
130                     throw Error.ElementInitializerMethodNoRefOutParam(pi.Name, addMethod.Name);
131                 }
132             }
133         }
134     }
135 }