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
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
86 // TODO: Remove this code and rely on GetAssemblyDefinition only
88 var module = new Compiler.ModuleContainer (cc);
89 module.HasTypesFullyDefined = true;
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);
95 var importer = new Compiler.ReflectionImporter (module, cc.BuiltinTypes) {
96 IgnorePrivateMembers = false
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);
107 cc.BuiltinTypes.CheckDefinitions (module);
108 module.InitializePredefinedTypes ();
110 dc = new DynamicContext (module, importer);
117 // Creates mcs expression from dynamic object
119 public Compiler.Expression CreateCompilerExpression (CSharpArgumentInfo info, DynamicMetaObject value)
122 // No type details provider, go with runtime type
125 if (value.LimitType == typeof (object))
126 return new Compiler.NullLiteral (Compiler.Location.Null);
128 return new Compiler.RuntimeValueExpression (value, ImportType (value.RuntimeType));
132 // Value is known to be a type
134 if ((info.Flags & CSharpArgumentInfoFlags.IsStaticType) != 0)
135 return new Compiler.TypeExpression (ImportType ((Type) value.Value), Compiler.Location.Null);
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);
144 // Use compilation time type when type was known not to be dynamic during compilation
146 Type value_type = (info.Flags & CSharpArgumentInfoFlags.UseCompileTimeType) != 0 ? value.Expression.Type : value.LimitType;
147 var type = ImportType (value_type);
149 if ((info.Flags & CSharpArgumentInfoFlags.Constant) != 0) {
150 var c = Compiler.Constant.CreateConstantFromValue (type, value.Value, Compiler.Location.Null);
152 // It can be null for misused Constant flag
158 return new Compiler.RuntimeValueExpression (value, type);
162 // Creates mcs arguments from dynamic argument info
164 public Compiler.Arguments CreateCompilerArguments (IEnumerable<CSharpArgumentInfo> info, DynamicMetaObject[] args)
166 var res = new Compiler.Arguments (args.Length);
169 // enumerates over args
170 foreach (var item in info) {
171 var expr = CreateCompilerExpression (item, args[pos++]);
173 res.Add (new Compiler.NamedArgument (item.Name, Compiler.Location.Null, expr, item.ArgumentModifier));
175 res.Add (new Compiler.Argument (expr, item.ArgumentModifier));
178 if (pos == args.Length)
185 public Compiler.TypeSpec ImportType (Type type)
188 return importer.ImportType (type);