[jit] Rewrite some logging to work on embedded systems.
[mono.git] / mcs / class / Microsoft.CSharp / Microsoft.CSharp.RuntimeBinder / DynamicContext.cs
1 //
2 // DynamicContext.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Dynamic;
31 using Compiler = Mono.CSharp;
32 using System.Reflection;
33 using System.Collections.Generic;
34
35 namespace Microsoft.CSharp.RuntimeBinder
36 {
37         class DynamicContext
38         {
39                 static DynamicContext dc;
40                 static object compiler_initializer = new object ();
41                 static object lock_object = new object ();
42
43                 readonly Compiler.ModuleContainer module;
44                 readonly Compiler.ReflectionImporter importer;
45
46                 private DynamicContext (Compiler.ModuleContainer module, Compiler.ReflectionImporter importer)
47                 {
48                         this.module = module;
49                         this.importer = importer;
50                 }
51
52                 public Compiler.CompilerContext CompilerContext {
53                         get {
54                                 return module.Compiler;
55                         }
56                 }
57
58                 public Compiler.ModuleContainer Module {
59                         get {
60                                 return module;
61                         }
62                 }
63
64                 public static DynamicContext Create ()
65                 {
66                         if (dc != null)
67                                 return dc;
68
69                         lock (compiler_initializer) {
70                                 if (dc != null)
71                                         return dc;
72
73                                 var settings = new Compiler.CompilerSettings () {
74                                         WarningLevel = 0
75                                 };
76
77                                 var cc = new Compiler.CompilerContext (settings, ErrorPrinter.Instance) {
78                                         IsRuntimeBinder = true
79                                 };
80
81                                 //
82                                 // Any later loaded assemblies are handled internally by GetAssemblyDefinition
83                                 // domain.AssemblyLoad cannot be used as that would be too destructive as we
84                                 // would hold all loaded assemblies even if they can be never visited
85                                 //
86                                 // TODO: Remove this code and rely on GetAssemblyDefinition only
87                                 //
88                                 var module = new Compiler.ModuleContainer (cc);
89                                 module.HasTypesFullyDefined = true;
90                                 
91                                 // Setup fake assembly, it's used mostly to simplify checks like friend-access
92                                 var temp = new Compiler.AssemblyDefinitionDynamic (module, "dynamic");
93                                 module.SetDeclaringAssembly (temp);
94
95                                 var importer = new Compiler.ReflectionImporter (module, cc.BuiltinTypes) {
96                                         IgnorePrivateMembers = false
97                                 };
98
99                                 // Import all currently loaded assemblies
100                                 // TODO: Rewrite this to populate type cache on-demand, that should greatly
101                                 // reduce our start-up cost
102                                 var domain = AppDomain.CurrentDomain;
103                                 foreach (var a in AppDomain.CurrentDomain.GetAssemblies ()) {
104                                         importer.ImportAssembly (a, module.GlobalRootNamespace);
105                                 }
106
107                                 cc.BuiltinTypes.CheckDefinitions (module);
108                                 module.InitializePredefinedTypes ();
109
110                                 dc = new DynamicContext (module, importer);
111                         }
112
113                         return dc;
114                 }
115
116                 //
117                 // Creates mcs expression from dynamic object
118                 //
119                 public Compiler.Expression CreateCompilerExpression (CSharpArgumentInfo info, DynamicMetaObject value)
120                 {
121                         //
122                         // No type details provider, go with runtime type
123                         //
124                         if (info == null) {
125                                 if (value.LimitType == typeof (object))
126                                         return new Compiler.NullLiteral (Compiler.Location.Null);
127
128                                 return new Compiler.RuntimeValueExpression (value, ImportType (value.RuntimeType));
129                         }
130
131                         //
132                         // Value is known to be a type
133                         //
134                         if ((info.Flags & CSharpArgumentInfoFlags.IsStaticType) != 0)
135                                 return new Compiler.TypeExpression (ImportType ((Type) value.Value), Compiler.Location.Null);
136
137                         if (value.Value == null &&
138                                 (info.Flags & (CSharpArgumentInfoFlags.IsOut | CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType)) == 0 &&
139                                 value.LimitType == typeof (object)) {
140                                 return new Compiler.NullLiteral (Compiler.Location.Null);
141                         }
142
143                         //
144                         // Use compilation time type when type was known not to be dynamic during compilation
145                         //
146                         Type value_type = (info.Flags & CSharpArgumentInfoFlags.UseCompileTimeType) != 0 ? value.Expression.Type : value.LimitType;
147                         var type = ImportType (value_type);
148
149                         if ((info.Flags & CSharpArgumentInfoFlags.Constant) != 0) {
150                                 var c = Compiler.Constant.CreateConstantFromValue (type, value.Value, Compiler.Location.Null);
151                                 //
152                                 // It can be null for misused Constant flag
153                                 //
154                                 if (c != null)
155                                         return c;
156                         }
157
158                         return new Compiler.RuntimeValueExpression (value, type);
159                 }
160
161                 //
162                 // Creates mcs arguments from dynamic argument info
163                 //
164                 public Compiler.Arguments CreateCompilerArguments (IEnumerable<CSharpArgumentInfo> info, DynamicMetaObject[] args)
165                 {
166                         var res = new Compiler.Arguments (args.Length);
167                         int pos = 0;
168
169                         // enumerates over args
170                         foreach (var item in info) {
171                                 var expr = CreateCompilerExpression (item, args[pos++]);
172                                 if (item.IsNamed) {
173                                         res.Add (new Compiler.NamedArgument (item.Name, Compiler.Location.Null, expr, item.ArgumentModifier));
174                                 } else {
175                                         res.Add (new Compiler.Argument (expr, item.ArgumentModifier));
176                                 }
177
178                                 if (pos == args.Length)
179                                         break;
180                         }
181
182                         return res;
183                 }
184
185                 public Compiler.TypeSpec ImportType (Type type)
186                 {
187                         lock (lock_object) {
188                                 return importer.ImportType (type);
189                         }
190                 }
191         }
192 }