3 The compiler has a number of phases:
7 Initially the compiler parses all the source files and keeps a
8 parsed representation in memory. Very syntax error checking
9 is performed at this point.
11 The compiler stores the information in classes whose names
12 represent the language construct, for example, the "if"
13 construct is stored in an `If' class. A class is stored in a
18 The TypeManager loads all the assemblies that were referenced
19 by the programmer. The CLR type system is used as our
20 repository for types defined as well.
22 So the same interface that is used to query the types,
23 properties and flags about system types is the same interface
24 that we use for our types.
26 As we work our way through the code generation and semantic
27 analysis, new types are entered into the Type system through
28 the use of System.Reflection.Emit. The TypeManager will
29 lookup types on both the user defined types and on the system
32 So special care has to be used. The order in which we
33 proceeed from here is important.
35 * Base class resolution and type definition.
37 Once the parsing has happened, the compiler resolves the
38 inheritance tree for interfaces. This is done recursively
39 and we catch recursive interface definitions here.
41 After this is done, we continue on with classes. Classes have
42 can have an optional "parent" inherit from or the implicit
43 System.Object class (for normal builds, builds with /nostdlib
44 will allow you to compile class System.Object with no parent).
46 At this point we do some error checking and verify that the
47 inherits/implements section of a class is correct (since we
48 have previously built the interface inheritance).
50 By the time we are done, all classes, structs and interfaces
51 have been created using System.Reflection.Emit and registered
52 with the Type Manager.
54 This allows us to define fields and resolve argument names for
55 methods, properties, indexers and events.
59 Fields are generated next, we go through all the type
60 containers (classes and structs) and enter the fields into
63 * Method, Properties, Indexers and events definitions
65 Now all the methods, constructors, properties, indexers and
66 events are entered. They are only `defined' using
67 System.Reflection.Emit. No code generation will happen until
68 everything has been entered into System.Reflection.Emit.
70 This is important because to actually generate code we need to
71 know everything about the environment in which the code is
76 At this point all the definitions have been entered into the
77 type manager through System.Reflection.Emit. We can now use
78 System.Reflection to query all the information about the
81 Your normal semantic analysis and code generation phase lives
86 Most of the statements are handled in the codegen.cs file.
92 Always use `Report::Error' or `Report::Warning' methods of Report
93 class. The actual Report instance is available via local context.
94 An expression error reporting has to be done during Resolve phase,
95 except when it's Emit specific (very rare).
97 Error reporting should try to use the same codes that the
98 Microsoft compiler uses (if only so we can track which errors
99 we handle and which ones we dont).
101 If there is an error which is specific to MSC, use negative
102 numbers, and register the number in mcs/errors/errors.txt
104 Try to write a test case for any error that you run into the
105 code of the compiler if there is none already.
107 Put your test case in a file called csNNNN.cs in the
108 mcs/errors directory, and have the first two lines be:
110 // csNNNN.cs: This is the error message
112 // Compiler options: an optional compiler options
114 Where `XXX' is the line where the error ocurrs. We will later
115 use this as a regression test suite for catching errors in the