1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Microsoft Public License. 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 Microsoft Public License, 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 Microsoft Public License.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
15 using System; using Microsoft;
18 #if !SILVERLIGHT // ComObject
20 using System.Collections.Generic;
21 using System.Diagnostics;
22 using System.Globalization;
24 using System.Linq.Expressions;
26 using Microsoft.Linq.Expressions;
28 using System.Reflection;
29 using System.Reflection.Emit;
30 using System.Runtime.InteropServices;
33 namespace System.Dynamic {
35 namespace Microsoft.Scripting {
38 [StructLayout(LayoutKind.Sequential)]
39 internal struct VariantArray1 {
40 public Variant Element0;
43 [StructLayout(LayoutKind.Sequential)]
44 internal struct VariantArray2 {
45 public Variant Element0, Element1;
48 [StructLayout(LayoutKind.Sequential)]
49 internal struct VariantArray4 {
50 public Variant Element0, Element1, Element2, Element3;
53 [StructLayout(LayoutKind.Sequential)]
54 internal struct VariantArray8 {
55 public Variant Element0, Element1, Element2, Element3, Element4, Element5, Element6, Element7;
59 // Helper for getting the right VariantArray struct for a given number of
60 // arguments. Will generate a struct if needed.
62 // We use this because we don't have stackalloc or pinning in Expression
63 // Trees, so we can't create an array of Variants directly.
65 internal static class VariantArray {
66 // Don't need a dictionary for this, it will have very few elements
67 // (guarenteed less than 28, in practice 0-2)
68 private static readonly List<Type> _generatedTypes = new List<Type>(0);
70 internal static MemberExpression GetStructField(ParameterExpression variantArray, int field) {
71 return Expression.Field(variantArray, "Element" + field);
74 internal static Type GetStructType(int args) {
75 Debug.Assert(args >= 0);
76 if (args <= 1) return typeof(VariantArray1);
77 if (args <= 2) return typeof(VariantArray2);
78 if (args <= 4) return typeof(VariantArray4);
79 if (args <= 8) return typeof(VariantArray8);
86 lock (_generatedTypes) {
87 // See if we can find an existing type
88 foreach (Type t in _generatedTypes) {
89 int arity = int.Parse(t.Name.Substring("VariantArray".Length), CultureInfo.InvariantCulture);
95 // Else generate a new type
96 Type type = CreateCustomType(size).MakeGenericType(new Type[]{typeof(Variant)});
97 _generatedTypes.Add(type);
102 private static Type CreateCustomType(int size) {
103 var attrs = TypeAttributes.NotPublic | TypeAttributes.SequentialLayout;
104 TypeBuilder type = UnsafeMethods.DynamicModule.DefineType("VariantArray" + size, attrs, typeof(ValueType));
105 var T = type.DefineGenericParameters(new string[] { "T" })[0];
106 for (int i = 0; i < size; i++) {
107 type.DefineField("Element" + i, T, FieldAttributes.Public);
109 return type.CreateType();