📄 main.cs
字号:
//-----------------------------------------------------------------------------
// EntryPoint for Blue Compiler
// See http://blogs.msdn.com/jmstall for issues.
//-----------------------------------------------------------------------------
using System;
using System.Diagnostics;
using IO = System.IO;
using Blue.Public;
using Utilities = Blue.Utilities;
using CodeGen = Blue.CodeGen;
using ErrorLog = Blue.Utilities.ErrorLog;
// This is a dummy class just to serve as a tag for the XML docs
/// <summary>
/// Blue is a C# compiler written in C#.
/// </summary>
/// <remarks>
/// <para>Blue is an entirely managed C# implementation written
/// in C# using the .NET runtime and Frameworks.</para>
/// <para>See help on <see cref="Blue.Driver"/> for more details on the implementation</para>
/// </remarks>
public class Help
{
public static void About() { }
}
namespace Blue
{
#region Driver & helpers
/// <summary>
/// The <c>Driver</c> class houses the Main() function and
/// controls all other components.
/// </summary>
/// <remarks>
/// The Driver class is the primary client for the interfaces in <see cref="Blue.Public"/>.
/// It creates the components in the compilation pipeline.
/// <list type="bullet">
/// <item><see cref="ILexer"/> - convert source to a token stream </item>
/// <item><see cref="IParser"/> - convert token stream into AST </item>
/// <item><see cref="ISemanticChecker"/> - do symbol resolution on the AST </item>
/// <item><see cref="ICodeGenDriver"/> - emit IL for a resolved-AST </item>
/// </list>
/// It also creates the utility components:
/// <list type="bullet">
/// <item><see cref="IOptions"/> - register delegates to handle command line options</item>
/// <item><see cref="IError"/> - unified error-reporting system for user-errors</item>
/// <item><see cref="Log"/> - logging facility, mostly for debugging </item>
/// </list>
/// </remarks>
public class Driver
{
//-----------------------------------------------------------------------------
// Entry point for Blue
//-----------------------------------------------------------------------------
public static int Main(string[] arstArgs)
{
int iErrorValue = 1;
Init(arstArgs);
// Main work done here. This should not throw an exception.
// It will print all the error information. When we return from here,
// the binary should have been compiled, all error handling done, etc.
iErrorValue = MainProxy(arstArgs);
if (StdErrorLog.HasErrors())
iErrorValue = 2;
Terminate(iErrorValue);
return iErrorValue;
}
//-----------------------------------------------------------------------------
// Shutdown
//-----------------------------------------------------------------------------
static void Terminate(int iErrorValue)
{
Log.WriteLine(Log.LF.All, "Shutdown compiler, return value={0}",iErrorValue);
Log.TerminateLogging();
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
static void Init(string [] arstArgs)
{
PrintLogo();
// Initialize logging
Log.InitLogging(arstArgs);
// Log startup info
#if __BLUE__
Log.WriteLine(Log.LF.All, "DOGFOOD version compiled by Blue.");
#else
Log.WriteLine(Log.LF.All, "Normal version compiled by C#.");
#endif
Log.WriteLine(Log.LF.All, "Startup compiler, args={0}", Log.F(arstArgs));
// Create the error logging facility
m_ErrorLog = new Utilities.ErrorLog();
// Create the option facility
m_OptionMananager = new Utilities.Options();
// Let each of the differen components register their option handlers
AddDriverOptions();
m_codegen = new CodeGen.EmitCodeGen(OptionManager);
}
// Add the options for the Driver.
static void AddDriverOptions()
{
OptionManager.AddHandler("xml", null, new OptionHandler(Driver.OptionX),
"Generate XML debug information",
"Emit xml files for the parse tree and symbols.\n"+
"The parse tree of all source files are dumped into a single xml file.\n" +
"The following files are generated:\n"+
"'X_parse.xml' - the parse tree before any resolution.\n"+
"'X_post.xml' - the parse tree after resolution. This may display most.\n"+
" attributes as well as show the changes in the tree during.\n"+
" resolution.\n"+
"'X_sym.xml' - a dump of the symbol table, including imported symbols.\n"
);
OptionManager.AddHandler("dbg_quit", "_Q", new OptionHandler(Driver.OptionDbgQuit),
"Debugging: Quit after stage (Lexer, Parser, Resolve)",
"[For debugging purposes.]\n"+
"Quits after the specified compilation stage. Useful in conjuction with\n"+
"the 'xml' option.\n"+
"usage:\n"+
"/_Q:Lexer - quit after scanning. Implicitly output the lexemes.\n"+
"/_Q:Parser - quit after building the AST, before any resolution.\n"+
"/_Q:Resolve - quit after symbol resolution, but before codegen.\n"
);
OptionManager.AddHandler("reference", "r", new OptionHandler(Driver.OptionAddReference),
"Add assembly reference (/r:myassem)",
"Imports the meta data from the specified assembly\n" +
"/r:XXX will first search the local directory for a file XXX; if not found it\n"+
"will then search the GAC where XXX is the fully-qualified name; if not found it\n"+
"will then search where XXX is the partial name.\n"+
"ex: /r:System"
);
OptionManager.AddHandler("define", "d", new OptionHandler(Driver.OptionDefineSymbol),
"Define conditional compilation symbols (/d:<symbol>)",
"Adds a symbol to control the preprocessor's #if <symbol> behavior.\n"+
"This is equivalent to using a #define <symbol> in every source file.\n"+
"The symbol __BLUE__ is always prefedined."+
"ex:\n"+
"/define:DEBUG\n"
//"/d:Skip_First_thing,AnotherDefine,Third" @todo - allow this
);
}
#region Data
// Option manager
static Utilities.Options m_OptionMananager;
static Public.IOptions OptionManager {
get { return m_OptionMananager; }
}
// Codegen
static ICodeGenDriver m_codegen;
// Predefined symbols for preprocessor
static string [] m_defines;
// Expose the error log publicly
static Utilities.ErrorLog m_ErrorLog;
//static public Utilities.ErrorLog StdErrorLog
static public Blue.Public.IError StdErrorLog
{
get { return m_ErrorLog; }
}
#endregion
//-----------------------------------------------------------------------------
// Print the startup info
//-----------------------------------------------------------------------------
static void PrintLogo()
{
Console.Write("Blue Sample Compiler v1.0");
#if __BLUE__
Console.WriteLine(" [Dogfood]");
#else
Console.WriteLine(" [normal]");
#endif
Console.WriteLine("by Mike Stall (http://blogs.msdn.com/jmstall)");
Console.WriteLine("\n");
}
//-----------------------------------------------------------------------------
// Primary Worker. This drives the different stages.
// Returns the error code for all expected end-user errors.
// Unexpected errors (bugs / holes in the compiler) will throw an exception.
//-----------------------------------------------------------------------------
static int MainWorker(string[] arstSourceFiles)
{
if (arstSourceFiles == null)
{
PrintError_NoSourceFiles();
return 1;
}
// Check if debugging the lexer. Just do first file
// @todo - should we do all files?
if (ShouldDebugQuit(EStage.cLexer))
{
string stDefault = arstSourceFiles[0];
System.IO.StreamReader reader = new System.IO.StreamReader(stDefault);
ILexer lex = new ManualParser.Lexer(stDefault, reader);
return TestLexer(lex);
}
//
// Lex & Parse all source files.
// It doesn't matter which order files are parsed in
//
AST.ProgramDecl root = ParseAllFiles(arstSourceFiles);
if (root == null)
return 1;
if (ShouldDebugQuit(EStage.cParser))
return 0;
//
// Symantic checks:
//
// Must startup codegen so that it can assign clr types
m_codegen.BeginOutput(arstSourceFiles);
System.Reflection.Assembly [] refs = LoadImportedAssemblies();
if (StdErrorLog.HasErrors())
return 19;
ICLRtypeProvider provider = m_codegen.GetProvider(refs);
ISemanticChecker check = new SymbolEngine.SemanticChecker();
bool fCheckOk = check.DoCheck(root, provider, refs);
if (!fCheckOk)
{
return 2;
}
// Dump parse tree after resolution
if (s_fGenerateXML)
{
string stOutput = IO.Path.GetFileNameWithoutExtension(arstSourceFiles[0]);
System.Xml.XmlWriter oSym = new System.Xml.XmlTextWriter(stOutput + "_sym.xml", null);
check.DumpSymbolTable(oSym);
System.Xml.XmlWriter oPost = new System.Xml.XmlTextWriter(stOutput + "_post.xml", null);
AST.Node.DumpTree(root, oPost);
}
if (ShouldDebugQuit(EStage.cSymbolResolution))
return 0;
//
// Codegen
//
m_codegen.DoCodeGen(root);
m_codegen.EndOutput();
// If we make it this far, we have no errors.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -