mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
3.9 KiB
116 lines
3.9 KiB
Compiler operation |
|
|
|
The compiler has a number of phases: |
|
|
|
* Parsing. |
|
|
|
Initially the compiler parses all the source files and keeps a |
|
parsed representation in memory. Very syntax error checking |
|
is performed at this point. |
|
|
|
The compiler stores the information in classes whose names |
|
represent the language construct, for example, the "if" |
|
construct is stored in an `If' class. A class is stored in a |
|
`Class'. |
|
|
|
* The TypeManager |
|
|
|
The TypeManager loads all the assemblies that were referenced |
|
by the programmer. The CLR type system is used as our |
|
repository for types defined as well. |
|
|
|
So the same interface that is used to query the types, |
|
properties and flags about system types is the same interface |
|
that we use for our types. |
|
|
|
As we work our way through the code generation and semantic |
|
analysis, new types are entered into the Type system through |
|
the use of System.Reflection.Emit. The TypeManager will |
|
lookup types on both the user defined types and on the system |
|
defined ones. |
|
|
|
So special care has to be used. The order in which we |
|
proceeed from here is important. |
|
|
|
* Base class resolution and type definition. |
|
|
|
Once the parsing has happened, the compiler resolves the |
|
inheritance tree for interfaces. This is done recursively |
|
and we catch recursive interface definitions here. |
|
|
|
After this is done, we continue on with classes. Classes have |
|
can have an optional "parent" inherit from or the implicit |
|
System.Object class (for normal builds, builds with /nostdlib |
|
will allow you to compile class System.Object with no parent). |
|
|
|
At this point we do some error checking and verify that the |
|
inherits/implements section of a class is correct (since we |
|
have previously built the interface inheritance). |
|
|
|
By the time we are done, all classes, structs and interfaces |
|
have been created using System.Reflection.Emit and registered |
|
with the Type Manager. |
|
|
|
This allows us to define fields and resolve argument names for |
|
methods, properties, indexers and events. |
|
|
|
* Field generation |
|
|
|
Fields are generated next, we go through all the type |
|
containers (classes and structs) and enter the fields into |
|
their types. |
|
|
|
* Method, Properties, Indexers and events definitions |
|
|
|
Now all the methods, constructors, properties, indexers and |
|
events are entered. They are only `defined' using |
|
System.Reflection.Emit. No code generation will happen until |
|
everything has been entered into System.Reflection.Emit. |
|
|
|
This is important because to actually generate code we need to |
|
know everything about the environment in which the code is |
|
being generated. |
|
|
|
* Code Generation |
|
|
|
At this point all the definitions have been entered into the |
|
type manager through System.Reflection.Emit. We can now use |
|
System.Reflection to query all the information about the |
|
types. |
|
|
|
Your normal semantic analysis and code generation phase lives |
|
here. |
|
|
|
* Statements |
|
|
|
Most of the statements are handled in the codegen.cs file. |
|
|
|
* Expressions |
|
|
|
* Error reporting |
|
|
|
Always use `Report::Error' or `Report::Warning' methods of Report |
|
class. The actual Report instance is available via local context. |
|
An expression error reporting has to be done during Resolve phase, |
|
except when it's Emit specific (very rare). |
|
|
|
Error reporting should try to use the same codes that the |
|
Microsoft compiler uses (if only so we can track which errors |
|
we handle and which ones we dont). |
|
|
|
If there is an error which is specific to MSC, use negative |
|
numbers, and register the number in mcs/errors/errors.txt |
|
|
|
Try to write a test case for any error that you run into the |
|
code of the compiler if there is none already. |
|
|
|
Put your test case in a file called csNNNN.cs in the |
|
mcs/errors directory, and have the first two lines be: |
|
|
|
// csNNNN.cs: This is the error message |
|
// Line: XXX |
|
// Compiler options: an optional compiler options |
|
|
|
Where `XXX' is the line where the error ocurrs. We will later |
|
use this as a regression test suite for catching errors in the |
|
compiler.
|
|
|