5f916ce64b6894ba3e4b87b8e23a1363915af885
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Dynamic / Interpreter / Instructions / InstructionFactory.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 #if FEATURE_NUMERICS
17 using BigInt = System.Numerics.BigInteger;
18 #endif
19
20 using System;
21 using System.Collections.Generic;
22
23 using Microsoft.Scripting.Math;
24 using Microsoft.Scripting.Utils;
25
26 namespace Microsoft.Scripting.Interpreter {
27     public abstract class InstructionFactory {
28         // TODO: weak table for types in a collectible assembly?
29         private static Dictionary<Type, InstructionFactory> _factories;
30
31         internal static InstructionFactory GetFactory(Type type) {
32             if (_factories == null) {
33                 _factories = new Dictionary<Type, InstructionFactory>() {
34                     { typeof(object), InstructionFactory<object>.Factory },
35                     { typeof(bool), InstructionFactory<bool>.Factory },
36                     { typeof(byte), InstructionFactory<byte>.Factory },
37                     { typeof(sbyte), InstructionFactory<sbyte>.Factory },
38                     { typeof(short), InstructionFactory<short>.Factory },
39                     { typeof(ushort), InstructionFactory<ushort>.Factory },
40                     { typeof(int), InstructionFactory<int>.Factory },
41                     { typeof(uint), InstructionFactory<uint>.Factory },
42                     { typeof(long), InstructionFactory<long>.Factory },
43                     { typeof(ulong), InstructionFactory<ulong>.Factory },
44                     { typeof(float), InstructionFactory<float>.Factory },
45                     { typeof(double), InstructionFactory<double>.Factory },
46                     { typeof(char), InstructionFactory<char>.Factory },
47                     { typeof(string), InstructionFactory<string>.Factory },
48 #if FEATURE_NUMERICS
49                     { typeof(BigInt), InstructionFactory<BigInt>.Factory },
50 #endif
51                     { typeof(BigInteger), InstructionFactory<BigInteger>.Factory }  
52                 };
53             }
54
55             lock (_factories) {
56                 InstructionFactory factory;
57                 if (!_factories.TryGetValue(type, out factory)) {
58                     factory = (InstructionFactory)typeof(InstructionFactory<>).MakeGenericType(type).GetDeclaredField("Factory").GetValue(null);
59                     _factories[type] = factory;
60                 }
61                 return factory;
62             }
63         }
64
65         internal protected abstract Instruction GetArrayItem();
66         internal protected abstract Instruction SetArrayItem();
67         internal protected abstract Instruction TypeIs();
68         internal protected abstract Instruction TypeAs();
69         internal protected abstract Instruction DefaultValue();
70         internal protected abstract Instruction NewArray();
71         internal protected abstract Instruction NewArrayInit(int elementCount);
72         internal protected abstract Instruction WrapToNullable(Type elementType);
73     }
74
75     public sealed class InstructionFactory<T> : InstructionFactory {
76         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
77         public static readonly InstructionFactory Factory = new InstructionFactory<T>();
78
79         private Instruction _getArrayItem;
80         private Instruction _setArrayItem;
81         private Instruction _typeIs;
82         private Instruction _defaultValue;
83         private Instruction _newArray;
84         private Instruction _typeAs;
85         private Instruction _nullableWrap;
86
87         private InstructionFactory() { }
88
89         internal protected override Instruction GetArrayItem() {
90             return _getArrayItem ?? (_getArrayItem = new GetArrayItemInstruction<T>());
91         }
92
93         internal protected override Instruction SetArrayItem() {
94             return _setArrayItem ?? (_setArrayItem = new SetArrayItemInstruction<T>());
95         }
96
97         internal protected override Instruction TypeIs() {
98             return _typeIs ?? (_typeIs = new TypeIsInstruction<T>());
99         }
100
101         internal protected override Instruction TypeAs() {
102             return _typeAs ?? (_typeAs = new TypeAsInstruction<T>());
103         }
104
105         internal protected override Instruction DefaultValue() {
106             return _defaultValue ?? (_defaultValue = new DefaultValueInstruction<T>());
107         }
108
109         internal protected override Instruction NewArray() {
110             return _newArray ?? (_newArray = new NewArrayInstruction<T>());
111         }
112
113         internal protected override Instruction NewArrayInit(int elementCount) {
114             return new NewArrayInitInstruction<T>(elementCount);
115         }
116
117         internal protected override Instruction WrapToNullable(Type elementType) {
118             return _nullableWrap ?? (_nullableWrap = new WrapToNullableInstruction<T>(elementType));
119         }        
120     }
121 }