Add a more functional (i.e. fewer-stubs) implementation of System.Data.Linq.
[mono.git] / mcs / mcs / rootcontext.cs
1 //
2 // rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
3 //
4 // Author: Miguel de Icaza (miguel@ximian.com)
5 //            Ravi Pratap  (ravi@ximian.com)
6 //            Marek Safar  (marek.safar@gmail.com)
7 //
8 //
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 //
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2004-2008 Novell, Inc
13
14 using System;
15 using System.Collections;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Diagnostics;
19
20 namespace Mono.CSharp {
21
22         public enum LanguageVersion
23         {
24                 ISO_1           = 1,
25                 Default_MCS     = 2,
26                 ISO_2           = 3,
27                 LINQ            = 4,
28                 Future          = 5,
29
30 #if GMCS_SOURCE
31                 Default         = LINQ
32 #else
33                 Default         = Default_MCS
34 #endif
35         }
36
37         public class RootContext {
38
39                 //
40                 // COMPILER OPTIONS CLASS
41                 //
42                 public static Target Target;
43                 public static string TargetExt;
44                 public static bool VerifyClsCompliance = true;
45                 public static bool Optimize = true;
46                 public static LanguageVersion Version;
47
48                 //
49                 // We keep strongname related info here because
50                 // it's also used as complier options from CSC 8.x
51                 //
52                 public static string StrongNameKeyFile;
53                 public static string StrongNameKeyContainer;
54                 public static bool StrongNameDelaySign;
55
56                 //
57                 // If set, enable XML documentation generation
58                 //
59                 public static Documentation Documentation;
60
61                 static public string MainClass;
62
63                 // 
64                 // The default compiler checked state
65                 //
66                 static public bool Checked;
67
68                 //
69                 // If true, it means that the compiler is executing as
70                 // in eval mode so unresolved variables are resolved in
71                 // static classes maintained by the eval engine.
72                 //
73                 static public bool EvalMode;
74
75                 //
76                 // If true, the compiler is operating in statement mode,
77                 // this currently turns local variable declaration into
78                 // static variables of a class
79                 //
80                 static public bool StatementMode;
81                 
82                 //
83                 // Whether to allow Unsafe code
84                 //
85                 static public bool Unsafe;
86
87                 //
88                 // Whether we are being linked against the standard libraries.
89                 // This is only used to tell whether `System.Object' should
90                 // have a base class or not.
91                 //
92                 public static bool StdLib;
93
94                 public static bool NeedsEntryPoint {
95                         get { return Target == Target.Exe || Target == Target.WinExe; }
96                 }
97
98                 //
99                 // COMPILER OPTIONS CLASS END
100                 //
101
102                 //
103                 // Contains the parsed tree
104                 //
105                 static RootTypes root;
106
107                 //
108                 // This hashtable contains all of the #definitions across the source code
109                 // it is used by the ConditionalAttribute handler.
110                 //
111                 static ArrayList AllDefines;
112                 
113                 //
114                 // This keeps track of the order in which classes were defined
115                 // so that we can poulate them in that order.
116                 //
117                 // Order is important, because we need to be able to tell, by
118                 // examining the list of methods of the base class, which ones are virtual
119                 // or abstract as well as the parent names (to implement new, 
120                 // override).
121                 //
122                 static ArrayList type_container_resolve_order;
123
124                 //
125                 // Holds a reference to the Private Implementation Details
126                 // class.
127                 //
128                 static ArrayList helper_classes;
129                 
130                 static TypeBuilder impl_details_class;
131
132                 //
133                 // Constructor
134                 //
135                 static RootContext ()
136                 {
137                         Reset (true);
138                 }
139
140                 public static void PartialReset ()
141                 {
142                         Reset (false);
143                 }
144                 
145                 public static void Reset (bool full)
146                 {
147                         if (full)
148                                 root = new RootTypes ();
149                         
150                         type_container_resolve_order = new ArrayList ();
151                         EntryPoint = null;
152                         Report.WarningLevel = 4;
153                         Checked = false;
154                         Unsafe = false;
155                         StdLib = true;
156                         StrongNameKeyFile = null;
157                         StrongNameKeyContainer = null;
158                         StrongNameDelaySign = false;
159                         MainClass = null;
160                         Target = Target.Exe;
161                         TargetExt = ".exe";
162                         Version = LanguageVersion.Default;
163                         Documentation = null;
164                         impl_details_class = null;
165                         helper_classes = null;
166
167                         //
168                         // Setup default defines
169                         //
170                         RootContext.AllDefines = new ArrayList ();
171                         RootContext.AddConditional ("__MonoCS__");
172                 }
173
174                 public static void AddConditional (string p)
175                 {
176                         if (AllDefines.Contains (p))
177                                 return;
178                         AllDefines.Add (p);
179                 }
180
181                 public static bool IsConditionalDefined (string value)
182                 {
183                         return AllDefines.Contains (value);
184                 }
185
186                 static public RootTypes ToplevelTypes {
187                         get { return root; }
188                 }
189
190                 public static void RegisterOrder (TypeContainer tc)
191                 {
192                         type_container_resolve_order.Add (tc);
193                 }
194                 
195                 // <remarks>
196                 //   This function is used to resolve the hierarchy tree.
197                 //   It processes interfaces, structs and classes in that order.
198                 //
199                 //   It creates the TypeBuilder's as it processes the user defined
200                 //   types.  
201                 // </remarks>
202                 static public void ResolveTree ()
203                 {
204                         //
205                         // Interfaces are processed next, as classes and
206                         // structs might inherit from an object or implement
207                         // a set of interfaces, we need to be able to tell
208                         // them appart by just using the TypeManager.
209                         //
210                         foreach (TypeContainer tc in root.Types)
211                                 tc.CreateType ();
212
213                         foreach (TypeContainer tc in root.Types)
214                                 tc.DefineType ();
215
216                         if (root.Delegates != null)
217                                 foreach (Delegate d in root.Delegates) 
218                                         d.DefineType ();
219                 }
220
221                 // <summary>
222                 //   Closes all open types
223                 // </summary>
224                 //
225                 // <remarks>
226                 //   We usually use TypeBuilder types.  When we are done
227                 //   creating the type (which will happen after we have added
228                 //   methods, fields, etc) we need to "Define" them before we
229                 //   can save the Assembly
230                 // </remarks>
231                 static public void CloseTypes ()
232                 {
233                         //
234                         // We do this in two passes, first we close the structs,
235                         // then the classes, because it seems the code needs it this
236                         // way.  If this is really what is going on, we should probably
237                         // make sure that we define the structs in order as well.
238                         //
239                         foreach (TypeContainer tc in type_container_resolve_order){
240                                 if (tc.Kind == Kind.Struct && tc.Parent == root){
241                                         tc.CloseType ();
242                                 }
243                         }
244
245                         foreach (TypeContainer tc in type_container_resolve_order){
246                                 if (!(tc.Kind == Kind.Struct && tc.Parent == root))
247                                         tc.CloseType ();                                        
248                         }
249                         
250                         if (root.Delegates != null)
251                                 foreach (Delegate d in root.Delegates)
252                                         d.CloseType ();
253
254
255                         //
256                         // If we have a <PrivateImplementationDetails> class, close it
257                         //
258                         if (helper_classes != null){
259                                 foreach (TypeBuilder type_builder in helper_classes) {
260 #if GMCS_SOURCE
261                                         type_builder.SetCustomAttribute (TypeManager.GetCompilerGeneratedAttribute (Location.Null));
262 #endif
263                                         type_builder.CreateType ();
264                                 }
265                         }
266                         
267                         type_container_resolve_order = null;
268                         helper_classes = null;
269                         //root = null;
270                         TypeManager.CleanUp ();
271                 }
272
273                 /// <summary>
274                 ///   Used to register classes that need to be closed after all the
275                 ///   user defined classes
276                 /// </summary>
277                 public static void RegisterCompilerGeneratedType (TypeBuilder helper_class)
278                 {
279                         if (helper_classes == null)
280                                 helper_classes = new ArrayList ();
281
282                         helper_classes.Add (helper_class);
283                 }
284                 
285                 static public void PopulateCoreType (TypeContainer root, string name)
286                 {
287                         DeclSpace ds = (DeclSpace) root.GetDefinition (name);
288                         // Core type was imported
289                         if (ds == null)
290                                 return;
291
292                         ds.Define ();
293                 }
294                 
295                 static public void BootCorlib_PopulateCoreTypes ()
296                 {
297                         PopulateCoreType (root, "System.Object");
298                         PopulateCoreType (root, "System.ValueType");
299                         PopulateCoreType (root, "System.Attribute");
300                         PopulateCoreType (root, "System.Runtime.CompilerServices.IndexerNameAttribute");
301                 }
302                 
303                 // <summary>
304                 //   Populates the structs and classes with fields and methods
305                 // </summary>
306                 //
307                 // This is invoked after all interfaces, structs and classes
308                 // have been defined through `ResolveTree' 
309                 static public void PopulateTypes ()
310                 {
311
312                         if (type_container_resolve_order != null){
313                                 foreach (TypeContainer tc in type_container_resolve_order)
314                                         tc.ResolveType ();
315                                 foreach (TypeContainer tc in type_container_resolve_order)
316                                         tc.Define ();
317                         }
318
319                         ArrayList delegates = root.Delegates;
320                         if (delegates != null){
321                                 foreach (Delegate d in delegates)
322                                         d.Define ();
323                         }
324
325                         //
326                         // Check for cycles in the struct layout
327                         //
328                         if (type_container_resolve_order != null){
329                                 Hashtable seen = new Hashtable ();
330                                 foreach (TypeContainer tc in type_container_resolve_order)
331                                         TypeManager.CheckStructCycles (tc, seen);
332                         }
333                 }
334
335                 static public void EmitCode ()
336                 {
337                         if (type_container_resolve_order != null) {
338                                 foreach (TypeContainer tc in type_container_resolve_order)
339                                         tc.EmitType ();
340
341                                 if (Report.Errors > 0)
342                                         return;
343
344                                 foreach (TypeContainer tc in type_container_resolve_order)
345                                         tc.VerifyMembers ();
346                         }
347                         
348                         if (root.Delegates != null) {
349                                 foreach (Delegate d in root.Delegates)
350                                         d.Emit ();
351                         }                       
352
353                         CodeGen.Assembly.Emit (root);
354                         CodeGen.Module.Emit (root);
355                 }
356                 
357                 //
358                 // Public Field, used to track which method is the public entry
359                 // point.
360                 //
361                 static public Method EntryPoint;
362
363                 //
364                 // These are used to generate unique names on the structs and fields.
365                 //
366                 static int field_count;
367                 
368                 //
369                 // Makes an initialized struct, returns the field builder that
370                 // references the data.  Thanks go to Sergey Chaban for researching
371                 // how to do this.  And coming up with a shorter mechanism than I
372                 // was able to figure out.
373                 //
374                 // This works but makes an implicit public struct $ArrayType$SIZE and
375                 // makes the fields point to it.  We could get more control if we did
376                 // use instead:
377                 //
378                 // 1. DefineNestedType on the impl_details_class with our struct.
379                 //
380                 // 2. Define the field on the impl_details_class
381                 //
382                 static public FieldBuilder MakeStaticData (byte [] data)
383                 {
384                         FieldBuilder fb;
385                         
386                         if (impl_details_class == null){
387                                 impl_details_class = CodeGen.Module.Builder.DefineType (
388                                         "<PrivateImplementationDetails>",
389                                         TypeAttributes.NotPublic,
390                                         TypeManager.object_type);
391                                 
392                                 RegisterCompilerGeneratedType (impl_details_class);
393                         }
394
395                         fb = impl_details_class.DefineInitializedData (
396                                 "$$field-" + (field_count++), data,
397                                 FieldAttributes.Static | FieldAttributes.Assembly);
398                         
399                         return fb;
400                 }
401
402                 public static void CheckUnsafeOption (Location loc)
403                 {
404                         if (!Unsafe) {
405                                 Report.Error (227, loc, 
406                                         "Unsafe code requires the `unsafe' command line option to be specified");
407                         }
408                 }
409         }
410 }
411               
412