public void Compile(List <TupleInfo> tuples, ProcessSystem processes, CompileOptions options)
        {
            this.processes = processes;
            this.processes.MeetTheParents();
            this.tuples = tuples;
            this.processes.MainMethodStart += new CompileEventHandler(CompileTupleSpaces);
            PLRString.DisplayWithoutQuotes  = true; //To make localities look right...

            processes.Compile(options);
        }
        static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.Error.WriteLine(@"
CCS Compiler
Copyright (C) 2009 Einar Egilsson

Usage: CCS [options] <filename>
");
                return(1);
            }
            List <string> listArgs = new List <string>(args);

            CompileOptions.AddOptionWithArgument("p", "print", ""); //Allow printouts
            CompileOptions options = CompileOptions.Parse(listArgs);

            if (options.Help)
            {
                Console.Error.WriteLine(@"
CCS Compiler
Copyright (C) 2009 Einar Egilsson

Usage: CCS [options] <filename>

Available options:

    /reference:<filenames>   The assemblies that this program requires. It is 
    /r:<filenames>           not neccessary to specify the PLR assembly. 
                             Other assemblies should be specified in a comma
                             seperated list, e.g. /reference:Foo.dll,Bar.dll.
    
    /optimize                If specified then the generated assembly will be
    /op                      optimized, dead code eliminated and expressions
                             pre-evaluated where possible. Do not combine this
                             with the /debug switch.
    
    /embedPLR                Embeds the PLR into the generated file, so it can
    /e                       be distributed as a stand-alone file.
  
    /debug                   Emit debugging symbols in the generated file,
    /d                       this allows it to be debugged in Visual Studio, or
                             in the free graphical debugger that comes with the
                             .NET Framework SDK.

    /out:<filename>          Specify the name of the compiled executable. If 
    /o:<filename>            this is not specified then the name of the input
                             file is used, with .ccs replaced by .exe.

    /print:<format>          Prints a version of the program source in the
    /p:<format>              specified format. Allowed formats are ccs, html 
                             and latex. The generated file will have the same
                             name as the input file, except with the format
                             as extension.

");

                return(1);
            }

            DieIf(options.Arguments.Count == 0, "ERROR: Missing input file name");
            DieIf(options.Arguments.Count > 1, "ERROR: Only one input file is expected");
            string filename = options.Arguments[0];

            DieIf(!File.Exists(filename), "ERROR: File '{0}' does not exist!", filename);
            if (string.IsNullOrEmpty(options.OutputFile))
            {
                options.OutputFile = filename;
                if (options.OutputFile.ToLower().EndsWith(".ccs"))
                {
                    options.OutputFile = options.OutputFile.Substring(0, options.OutputFile.Length - 4);
                }
            }
            if (!options.OutputFile.ToLower().EndsWith(".exe"))
            {
                options.OutputFile += ".exe";
            }
            try {
                Parser parser = new Parser(new Scanner(new FileStream(filename, FileMode.Open)));
                parser.Parse();
                if (parser.errors.count > 0)
                {
                    Environment.Exit(1);
                }
                ProcessSystem system = parser.System;
                system.MeetTheParents();
                List <Warning> warnings = system.Analyze(new ReachingDefinitions());

                if (warnings.Count > 0)
                {
                    foreach (Warning warn in warnings)
                    {
                        Console.Error.WriteLine("ERROR({0},{1}): {2}", warn.LexicalInfo.StartLine, warn.LexicalInfo.StartColumn, warn.Message);
                    }
                    return(1); //This is an error so we die before attempting to compile
                }

                //These are just warnings, so just warn...
                warnings = system.Analyze(
                    new LiveVariables(),
                    new NilProcessWarning(),
                    new UnmatchedChannels(),
                    new UnusedProcesses(options.Optimize)
                    );

                foreach (Warning warn in warnings)
                {
                    Console.Error.WriteLine("WARNING({0},{1}): {2}", warn.LexicalInfo.StartLine, warn.LexicalInfo.StartColumn, warn.Message);
                }

                //This optimizes the tree before compilation, only do if we should optimize
                if (options.Optimize)
                {
                    system.Analyze(new FoldConstantExpressions());
                }

                CheckPrintout(options, system);
                system.Compile(options);
            } catch (Exception ex) {
                //Console.WriteLine(ex.StackTrace);
                DieIf(true, "ERROR: " + ex.Message);
            }
            return(0);
        }