5 // Marek Safar <marek.safar@gmail.com>
7 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
31 using Compiler = Mono.CSharp;
32 using System.Reflection;
33 using System.Collections.Generic;
35 namespace Microsoft.CSharp.RuntimeBinder
39 static DynamicContext dc;
40 static object compiler_initializer = new object ();
41 static object lock_object = new object ();
43 readonly Compiler.ModuleContainer module;
44 readonly Compiler.ReflectionImporter importer;
46 private DynamicContext (Compiler.ModuleContainer module, Compiler.ReflectionImporter importer)
49 this.importer = importer;
52 public Compiler.CompilerContext CompilerContext {
54 return module.Compiler;
58 public Compiler.ModuleContainer Module {
64 public static DynamicContext Create ()
69 lock (compiler_initializer) {
73 var settings = new Compiler.CompilerSettings () {
77 var cc = new Compiler.CompilerContext (settings, ErrorPrinter.Instance) {
78 IsRuntimeBinder = true
81 //IList<Compiler.PredefinedTypeSpec> core_types = null;
82 //// HACK: To avoid re-initializing static TypeManager types, like string_type
83 //if (!Compiler.RootContext.EvalMode) {
84 // core_types = Compiler.TypeManager.InitCoreTypes ();
88 // Any later loaded assemblies are handled internally by GetAssemblyDefinition
89 // domain.AssemblyLoad cannot be used as that would be too destructive as we
90 // would hold all loaded assemblies even if they can be never visited
92 // TODO: Remove this code and rely on GetAssemblyDefinition only
94 var module = new Compiler.ModuleContainer (cc);
95 module.HasTypesFullyDefined = true;
96 var temp = new Compiler.AssemblyDefinitionDynamic (module, "dynamic");
97 module.SetDeclaringAssembly (temp);
99 // Import all currently loaded assemblies
100 var domain = AppDomain.CurrentDomain;
102 temp.Create (domain, System.Reflection.Emit.AssemblyBuilderAccess.Run);
103 var importer = new Compiler.ReflectionImporter (module, cc.BuiltinTypes) {
104 IgnorePrivateMembers = false
107 foreach (var a in AppDomain.CurrentDomain.GetAssemblies ()) {
108 importer.ImportAssembly (a, module.GlobalRootNamespace);
111 cc.BuiltinTypes.CheckDefinitions (module);
112 module.InitializePredefinedTypes ();
114 dc = new DynamicContext (module, importer);
121 // Creates mcs expression from dynamic object
123 public Compiler.Expression CreateCompilerExpression (CSharpArgumentInfo info, DynamicMetaObject value)
126 // No type details provider, go with runtime type
129 if (value.LimitType == typeof (object))
130 return new Compiler.NullLiteral (Compiler.Location.Null);
132 return new Compiler.RuntimeValueExpression (value, ImportType (value.RuntimeType));
136 // Value is known to be a type
138 if ((info.Flags & CSharpArgumentInfoFlags.IsStaticType) != 0)
139 return new Compiler.TypeExpression (ImportType ((Type) value.Value), Compiler.Location.Null);
141 if (value.Value == null &&
142 (info.Flags & (CSharpArgumentInfoFlags.IsOut | CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType)) == 0 &&
143 value.LimitType == typeof (object)) {
144 return new Compiler.NullLiteral (Compiler.Location.Null);
148 // Use compilation time type when type was known not to be dynamic during compilation
150 Type value_type = (info.Flags & CSharpArgumentInfoFlags.UseCompileTimeType) != 0 ? value.Expression.Type : value.LimitType;
151 var type = ImportType (value_type);
153 if ((info.Flags & CSharpArgumentInfoFlags.Constant) != 0)
154 return Compiler.Constant.CreateConstantFromValue (type, value.Value, Compiler.Location.Null);
156 return new Compiler.RuntimeValueExpression (value, type);
160 // Creates mcs arguments from dynamic argument info
162 public Compiler.Arguments CreateCompilerArguments (IEnumerable<CSharpArgumentInfo> info, DynamicMetaObject[] args)
164 var res = new Compiler.Arguments (args.Length);
167 // enumerates over args
168 foreach (var item in info) {
169 var expr = CreateCompilerExpression (item, args[pos++]);
171 res.Add (new Compiler.NamedArgument (item.Name, Compiler.Location.Null, expr, item.ArgumentModifier));
173 res.Add (new Compiler.Argument (expr, item.ArgumentModifier));
176 if (pos == args.Length)
183 public Compiler.TypeSpec ImportType (Type type)
186 return importer.ImportType (type);