public int CompileString(string data, CompileFlags flags, Define[] defineList, string fileUrl)
 {
     return CompileString(data, flags, defineList, _defaultIncludes, fileUrl);
 }
 public int Compile(object url, CompileFlags flags, Define[] defineList)
 {
     return Compile(url, flags, defineList, _defaultIncludes);
 }
        /// <summary>
        ///		Compiles a script from a string into byte code.
        /// </summary>
        /// <param name="data">Data of script to compile.</param>
        /// <param name="flags">Bitmask of flags defining how the script should be compiled.</param>
        /// <param name="defineList">A list of defines to use while preprocessing script.</param>
        /// <param name="includePaths">A list of directory paths to use when looking for include files.</param>
        /// <param name="fileUrl">Contains the url of the file this data comes from.</param>
        /// <returns>The number of errors or warning this script has generated duren compilation.</returns>
        public int CompileString(string data, CompileFlags flags, Define[] defineList, object[] includePaths, string fileUrl)
        {
            #if !DEBUG
            try
            {
            #endif
                // Reset all variables used to store compilation details.
                _errorList.Clear();
                _compiledSymbolList.Clear();
                _compiledInstructionList.Clear();
                _compiledDebugFileList.Clear();
                _compiledDefineList.Clear();
                _loopTrackerStack.Clear();
                _metaDataList.Clear();
                _currentToken = null;
                _currentPass = 0;
                _currentScope = null;
                _globalScope = new FunctionSymbol("$global", null); // Initialize global scope here.
                _memberScope = new FunctionSymbol("$member", null); // Initialize member scope here.
                _compileFlags = flags;
                _tokenList = null;
                _tokenIndex = 0;
                _memorySize = 1; // Reserve space for 'special' globals like 'this'.
                _internalVariableIndex = 0;
                _defaultEngineState = _defaultEditorState = null;
                _errorsOccured = false;
                _overrideInstructionScope = null;

                // Create the 'this' variable.
                VariableSymbol thisSymbol = new VariableSymbol(_globalScope);
                thisSymbol.DataType = new DataTypeValue(DataType.Object, false, false);
                thisSymbol.Identifier = "this";
                thisSymbol.IsConstant = true;
                thisSymbol.IsUsed = true;
                thisSymbol.MemoryIndex = 0;
                thisSymbol.VariableType = VariableType.Constant;

                // Create a lexer and convert script into a list
                // of tokens.
                DebugLogger.WriteLog("Preforming lexical analysis on script.");
                Lexer lexer = new Lexer();
                if (lexer.Analyse(data, _compileFlags, fileUrl) > 0)
                {
                    foreach (CompileError error in lexer.ErrorList)
                        _errorList.Add(error);
                }
                _tokenList = lexer.TokenList;

                // Add the script directory into the include path array.
                string includePath = Path.GetDirectoryName(fileUrl);
                string[] newIncludePaths = new string[includePaths.Length + 1];
                includePaths.CopyTo(newIncludePaths, 0);
                newIncludePaths[newIncludePaths.Length - 1] = includePath;
                includePaths = newIncludePaths;

                // Create a pre-processor and process the token list
                DebugLogger.WriteLog("Preforming preprocessing on script.");
                PreProcessor preProcessor = new PreProcessor();
                if (preProcessor.Process(_tokenList, _compileFlags, defineList, includePaths) > 0)
                {
                    foreach (CompileError error in preProcessor.ErrorList)
                        _errorList.Add(error);
                }
                _compiledDefineList = preProcessor.DefineList;
                _tokenList = preProcessor.TokenList;

                try
                {
                    // Pass 0: Collect infomation.
                    // Pass 1: Generate byte code.
                    DebugLogger.WriteLog("Compiling script in 2 passes.");

                    // Go over the source code in 2 passes.
                    for (int pass = 0; pass < 2; pass++)
                    {
                        _currentPass = pass;
                        _currentToken = null;
                        _tokenIndex = 0;
                        _currentScope = _globalScope;
                        _internalVariableIndex = 0; // This needs to be reset so statements using
                        // an internal variables can find them on the second pass.
                        while (!EndOfTokenStream())
                        {
                            try
                            {
                                ParseStatement();
                            }
                            catch (CompilePanicModeException)
                            {
                                DebugLogger.WriteLog("Panic mode initialized in script.");
                                // Don't do anything here, just allow the error to be
                                // forgoten and carry on as normal.
                            }

                            // If there are any errors quit compilation now.
                            if (_errorsOccured == true)
                                throw new CompileBreakException();
                        }
                    }

                    // Yell at user if no default state has been declared.
                    if (_defaultEngineState == null && (_compileFlags & CompileFlags.Library) == 0)
                        Error(ErrorCode.MissingDefaultState, "Default engine state is missing.");

                }
                catch (CompileBreakException)
                {
                    DebugLogger.WriteLog("Script compilation broken via CompileBreakException.");
                }

                // Check what errors occured.
                int fatalErrorCount = 0;
                int errorCount = 0;
                int warningCount = 0;
                int messageCount = 0;
                foreach (CompileError error in _errorList)
                {
                    switch (error.AlertLevel)
                    {
                        case ErrorAlertLevel.Error: errorCount++; break;
                        case ErrorAlertLevel.FatalError: fatalErrorCount++; break;
                        case ErrorAlertLevel.Message: messageCount++; break;
                        case ErrorAlertLevel.Warning: warningCount++; break;
                    }
                    DebugLogger.WriteLog(error.ToString(), LogAlertLevel.Warning);
                }

                DebugLogger.WriteLog("Script compiled with "+fatalErrorCount+" fatal errors, "+errorCount+" errors, "+warningCount+" warnings and "+messageCount+" messages.");

                // If there are any errors quit compilation now.
                if (_errorsOccured == true) return _errorList.Count;

                // Append an exit symbol onto the global scopes instruction list.
                CreateInstruction(OpCode.EXIT, _globalScope, _currentToken);

                DebugLogger.WriteLog("Optimizing and tweeking symbols and instructions.");

                // Compile symbol list.
                CompileSymbol(_globalScope);
                CompileSymbol(_memberScope);

                // Go through instruction list and replace placeholders with their values.
                int symbolIndex = 0;
                foreach (Symbol symbol in _compiledSymbolList)
                {
                    symbol.Index = symbolIndex;
                    symbolIndex++;

                    // Update the entry point if this is a function or event.
                    switch (symbol.Type)
                    {
                        case SymbolType.Function:
                            ((FunctionSymbol)symbol).EntryPoint = _compiledInstructionList.Count;
                            break;
                        case SymbolType.Variable:
                            bool check = true;
                            if (symbol.Scope.Type == SymbolType.Function)
                                if (((FunctionSymbol)symbol.Scope).IsImport == true) check = false;

                            // Should we remove it rather than warning?
                            if (((VariableSymbol)symbol).IsUsed == false && ((VariableSymbol)symbol).IsConstant == false && check == true)
                                Warning(ErrorCode.UnusedVariable, "Variable \"" + symbol.Identifier + "\" is declared but never used.");
                            break;
                    }

                    foreach (Instruction instruction in symbol.Instructions)
                    {
                        // Create a new debug file entry if this instruction
                        // was generated in a previously unknown file.
                        if (instruction.File != null && instruction.File != "")
                        {
                            bool found = false;
                            foreach (string file in _compiledDebugFileList)
                                if (file == instruction.File) found = true;
                            if (found == false) _compiledDebugFileList.Add(instruction.File);
                        }

                        // Go through each operand attach to this instruction
                        // and check for any trackers.
                        foreach (Operand operand in instruction.Operands)
                        {
                            if (operand == null) continue;

                            // Update operand based on type.
                            switch (operand.OpType)
                            {
                                case OperandType.JumpTarget:
                                    operand.OpType = OperandType.InstrIndex;
                                    switch (symbol.Type)
                                    {
                                        case SymbolType.Function:
                                            operand.InstrIndex = ((FunctionSymbol)symbol).EntryPoint + operand.JumpTarget.InstrIndex;
                                            break;
                                    }
                                    break;
                                case OperandType.SymbolIndexTracker:
                                    operand.OpType = OperandType.SymbolIndex;
                                    operand.SymbolIndex = _compiledSymbolList.IndexOf(operand.SymbolIndexTracker);
                                    break;
                            }
                        }
                        _compiledInstructionList.Add(instruction);
                    }
                }

                // Optimize this symbols instructions. (Currently somewhat error prone)
                //int instructionCount = _compiledInstructionList.Count;
                //ScriptOptimizer optimizer = new ScriptOptimizer();
                //optimizer.Optimize(_compiledInstructionList, _compiledSymbolList);
                //_compiledInstructionList = optimizer.OptimizedInstructions;
                //_compiledSymbolList = optimizer.OptimizedSymbols;

               // int index = 0;
                //foreach (Instruction instr in _compiledInstructionList)
                //{
                //    System.Console.WriteLine("\t"+instr.Decompile());
                //    index++;
                //}

            #if !DEBUG
            }
            catch (Exception)
            {
                _errorList.Add(new CompileError(ErrorCode.InternalError, "An internal compiler error occured.", ErrorAlertLevel.FatalError, 0, 0, ""));
            }
            #endif
            return _errorList.Count;
        }
        /// <summary>
        ///		Compiles a script from a url into byte code.
        /// </summary>
        /// <param name="url">Url of script to compile.</param>
        /// <param name="flags">Bitmask of flags defining how the script should be compiled.</param>
        /// <param name="defineList">A list of defines to use while preprocessing script.</param>
        /// <param name="includePaths">A list of directory paths to use when looking for include files.</param>
        /// <returns>The number of errors or warning this script has generated duren compilation.</returns>
        public int Compile(object url, CompileFlags flags, Define[] defineList, object[] includePaths)
        {
            // Open a stream so we can read in the script.
            Stream stream = StreamFactory.RequestStream(url, StreamMode.Open);
            if (stream == null) return 0;
            StreamReader reader = new StreamReader(stream);

            // Read in the whole text
            DebugLogger.WriteLog("Loading script into compiler from "+url.ToString()+".");
            CompileString(reader.ReadToEnd().Trim(), flags, defineList, includePaths, url.ToString());

            // Clean up the open stream.
            stream.Close();

            return _errorList.Count;
        }
        /// <summary>
        ///		Loads the byte code from a given binary reader.
        /// </summary>
        /// <param name="reader">BinaryReader to load byte code from.</param>
        private void LoadByteCode(BinaryReader reader)
        {
            // Check the header is correct
            if (reader.ReadByte() == 'C' && reader.ReadByte() == 'R' && reader.ReadByte() == 'X')
            {
                // Read in header variables.
                _compileFlags			= (CompileFlags)reader.ReadInt32();
                _internalVariableIndex	= reader.ReadInt32();
                _memorySize				= reader.ReadInt32();
                int globalScopeIndex	= reader.ReadInt32();
                int memberScopeIndex = reader.ReadInt32();
                _defaultEngineStateIndex = reader.ReadInt32();
                _defaultEditorStateIndex = reader.ReadInt32();

                // Create a new memory heap of the correct size
                if (_memorySize > _memoryHeap.Length) _memoryHeap = new RuntimeValue[_memorySize];
                for (int i = 0; i < _memorySize; i++)
                    _memoryHeap[i] = new RuntimeValue(RuntimeValueType.Invalid);

                // Set the 'special' globals to their appropriate values.
                _memoryHeap[0].ValueType = RuntimeValueType.Object;
                _memoryHeap[0].ObjectIndex = 0;

                int defineCount = reader.ReadInt32();
                int symbolCount			= reader.ReadInt32();
                int instructionCount	= reader.ReadInt32();
                int debugFileCount		= 0;

                if ((_compileFlags & CompileFlags.Debug) != 0)
                    debugFileCount = reader.ReadInt32();

                // Read in debug file list.
                string[] debugFiles = new string[debugFileCount];
                if ((_compileFlags & CompileFlags.Debug) != 0)
                {
                    for (int i = 0; i < debugFileCount; i++)
                        debugFiles[i] = reader.ReadString();
                }

                // Read in the define list.
                for (int i = 0; i < defineCount; i++)
                {
                    string ident = reader.ReadString();
                    TokenID valueID = (TokenID)reader.ReadInt32();
                    string value = reader.ReadString();
                    Define define = new Define(ident, value, valueID);
                    _defineList.Add(define);
                }

                // Read in symbol list.
                _symbolList = new Symbol[symbolCount];
                for (int i = 0; i < symbolCount; i++)
                {
                    // Read in general details about symbol.
                    SymbolType type	  = (SymbolType)reader.ReadByte();
                    string identifier = reader.ReadString();
                    int scopeIndex	  = reader.ReadInt32();
                    Symbol scope	  = null;
                    Symbol symbol	  = null;

                    if (scopeIndex != -1)
                        scope = (Symbol)_symbolList[scopeIndex];

                    // Read in specialized details about symbol.
                    switch (type)
                    {
                        case SymbolType.JumpTarget:
                            continue; // Ignore jump targets.

                        case SymbolType.Namespace:
                            NamespaceSymbol namespaceSymbol = new NamespaceSymbol(scope);
                            symbol = namespaceSymbol;
                            break;

                        case SymbolType.Enumeration:
                            EnumerationSymbol enumSymbol = new EnumerationSymbol(scope);
                            symbol = enumSymbol;
                            break;

                        case SymbolType.String:
                            StringSymbol stringSymbol = new StringSymbol(scope, identifier);
                            symbol = stringSymbol;
                            break;

                        case SymbolType.Function:
                            FunctionSymbol functionSymbol = new FunctionSymbol(identifier, scope);
                            symbol = functionSymbol;
                            functionSymbol.EntryPoint = reader.ReadInt32();
                            functionSymbol.LocalDataSize = reader.ReadInt16();
                            functionSymbol.IsEvent = reader.ReadBoolean();
                            functionSymbol.IsConsole = reader.ReadBoolean();
                            functionSymbol.IsExport = reader.ReadBoolean();
                            functionSymbol.IsImport = reader.ReadBoolean();
                            functionSymbol.IsThreadSpawner = reader.ReadBoolean();
                            functionSymbol.IsMember = reader.ReadBoolean();
                            functionSymbol.ParameterCount = reader.ReadByte();
                            bool isArray = reader.ReadBoolean();
                            bool isReference = reader.ReadBoolean();
                            functionSymbol.ReturnType = new DataTypeValue((DataType)reader.ReadByte(), isArray, isReference);
                            functionSymbol.AccessModifier = (SymbolAccessModifier)reader.ReadByte();
                            break;

                        case SymbolType.State:
                            StateSymbol stateSymbol = new StateSymbol(scope);
                            symbol = stateSymbol;
                            stateSymbol.IsEngineDefault = reader.ReadBoolean();
                            stateSymbol.IsEditorDefault = reader.ReadBoolean();
                            break;

                        case SymbolType.Variable:
                            VariableSymbol variableSymbol = new VariableSymbol(scope);
                            symbol = variableSymbol;
                            variableSymbol.DataType		= new DataTypeValue((DataType)reader.ReadByte(), false, false);
                            variableSymbol.DataType.IsReference = reader.ReadBoolean();
                            variableSymbol.IsArray		= reader.ReadBoolean();
                            variableSymbol.DataType.IsArray = variableSymbol.IsArray;
                            variableSymbol.IsConstant	= reader.ReadBoolean();
                            variableSymbol.MemoryIndex	= reader.ReadInt32();
                            variableSymbol.StackIndex	= reader.ReadInt32();
                            variableSymbol.VariableType = (VariableType)reader.ReadByte();
                            variableSymbol.IsProperty = reader.ReadBoolean();
                            variableSymbol.AccessModifier = (SymbolAccessModifier)reader.ReadByte();
                            variableSymbol.ConstToken = new Token(TokenID.TypeIdentifier, reader.ReadString(), 0, 0, "");
                            break;

                        case SymbolType.MetaData:
                            MetaDataSymbol metaDataSymbol = new MetaDataSymbol(scope, identifier, "");
                            symbol = metaDataSymbol;
                            metaDataSymbol.Value = reader.ReadString();
                            break;
                    }

                    symbol.Identifier = identifier;
                    symbol.Index = i;
                    _symbolList[i] = symbol;
                }

                // Retrieve global scope.
                _globalScope = _symbolList[globalScopeIndex] as FunctionSymbol;
                _memberScope = _symbolList[memberScopeIndex] as FunctionSymbol;
                //_currentState = _symbolList[_defaultEngineStateIndex] as StateSymbol; // Force this to be declared in the engine / editor.

                // Read in instruction list.
                _instructionList = new RuntimeInstruction[instructionCount];
                for (int i = 0; i < instructionCount; i++)
                {
                    // Read in instruction details and create a new instruction.
                    OpCode opCode = (OpCode)reader.ReadByte();
                    int operandCount = reader.ReadByte();
                    RuntimeInstruction instruction = new RuntimeInstruction(opCode);
                    _instructionList[i] = instruction;

                    if ((_compileFlags & CompileFlags.Debug) != 0)
                    {
                        int fileIndex = reader.ReadSByte();
                        if (fileIndex != -1) instruction.File = debugFiles[fileIndex];
                        instruction.Offset = reader.ReadInt16();
                        instruction.Line   = reader.ReadInt16();
                    }

                    // Read in each operand attached to this instruction
                    for (int k = 0; k < operandCount; k++)
                    {
                        // Read in general details about this operand and create
                        // a new runtime value instance.
                        RuntimeValueType opType = (RuntimeValueType)reader.ReadInt32();
                        RuntimeValue operand = new RuntimeValue(opType);
                        instruction.Operands[instruction.OperandCount] = operand;
                        instruction.OperandCount++;

                        // Read in specialized info about this operand.
                        switch(opType)
                        {
                            case RuntimeValueType.BooleanLiteral:
                                operand.BooleanLiteral = reader.ReadBoolean();
                                break;
                            case RuntimeValueType.ByteLiteral:
                                operand.ByteLiteral = reader.ReadByte();
                                break;
                            case RuntimeValueType.DirectMemory:
                                operand.MemoryIndex = reader.ReadInt32();
                                break;
                            case RuntimeValueType.DirectMemoryIndexed:
                                operand.MemoryIndex = reader.ReadInt32();
                                operand.OffsetRegister = (Register)reader.ReadByte();
                                break;
                            case RuntimeValueType.DirectStack:
                                operand.StackIndex = reader.ReadInt32();
                                break;
                            case RuntimeValueType.DirectStackIndexed:
                                operand.StackIndex = reader.ReadInt32();
                                operand.OffsetRegister = (Register)reader.ReadByte();
                                break;
                            case RuntimeValueType.DoubleLiteral:
                                operand.DoubleLiteral = reader.ReadDouble();
                                break;
                            case RuntimeValueType.FloatLiteral:
                                operand.FloatLiteral = reader.ReadSingle();
                                break;
                            case RuntimeValueType.IndirectMemory:
                                operand.Register = (Register)reader.ReadByte();
                                break;
                            case RuntimeValueType.IndirectMemoryIndexed:
                                operand.Register = (Register)reader.ReadByte();
                                operand.OffsetRegister = (Register)reader.ReadByte();
                                break;
                            case RuntimeValueType.IndirectStack:
                                operand.Register = (Register)reader.ReadByte();
                                break;
                            case RuntimeValueType.IndirectStackIndexed:
                                operand.Register = (Register)reader.ReadByte();
                                operand.OffsetRegister = (Register)reader.ReadByte();
                                break;
                            case RuntimeValueType.InstrIndex:
                                operand.InstrIndex = reader.ReadInt32();
                                break;
                            case RuntimeValueType.IntegerLiteral:
                                operand.IntegerLiteral = reader.ReadInt32();
                                break;
                            case RuntimeValueType.LongLiteral:
                                operand.LongLiteral = reader.ReadInt64();
                                break;
                            case RuntimeValueType.Register:
                                operand.Register = (Register)reader.ReadByte();
                                break;
                            case RuntimeValueType.ShortLiteral:
                                operand.ShortLiteral = reader.ReadInt16();
                                break;
                            case RuntimeValueType.SymbolIndex:
                                operand.SymbolIndex = reader.ReadInt32();
                                operand.Symbol = (Symbol)_symbolList[operand.SymbolIndex];
                                if (operand.Symbol is StringSymbol)
                                {
                                    operand.StringLiteral = operand.Symbol.Identifier;
                                    operand.ValueType = RuntimeValueType.StringLiteral;
                                }
                                break;
                        }
                    }
                }

                // Fill the member-function hash table.
                foreach (Symbol symbol in GlobalScope.Symbols)
                    if (symbol != null && symbol.Type == SymbolType.Function && ((FunctionSymbol)symbol).AccessModifier == SymbolAccessModifier.Public)
                        _memberFunctionHashTable.Add(symbol.ToString().ToLower(), symbol);
            }
            else
                throw new Exception("Unable to load script byte code, header is invalid.");
        }
        /// <summary>
        ///		Used as an entry point for the project building thread.
        /// </summary>
        private void BuildProjectThread()
        {
            // Work out script compiling options
            _compileFlags = _compileInDebugMode == true ? CompileFlags.Debug : 0;
            if (_treatMessagesAsErrors) _compileFlags |= CompileFlags.TreatMessagesAsErrors;
            if (_treatWarningsAsErrors) _compileFlags |= CompileFlags.TreatWarningsAsErrors;

            // Split up the script defines string.
            string[] defines = _scriptDefines.Split(new char[1] { ',' });
            _scriptDefineList = new Define[defines.Length + 1];
            for (int i = 0; i < defines.Length; i++)
            {
                if (defines[i].IndexOf('=') >= 0)
                {
                    string[] splitList = defines[i].Split(new char[1] { '=' });
                    _scriptDefineList[i] = new Define(splitList[0], splitList[1], TokenID.TypeIdentifier);
                }
                else
                    _scriptDefineList[i] = new Define(defines[i], "", TokenID.TypeIdentifier);
            }
            _scriptDefineList[_scriptDefineList.Length - 1] = new Define(_compileInDebugMode ? "__DEBUG__" : "__RELEASE__", "", TokenID.TypeBoolean);

            // Set the include path list to include the script library path.
            _scriptIncludePathList = new string[] { Environment.CurrentDirectory + "\\" + Editor.GlobalInstance.ScriptLibraryPath, Editor.GlobalInstance.GlobalScriptLibraryPath };

            // Work out a directory that we can build to.
            _buildBasePath = _buildDirectory;
            _buildDirectory = _buildBasePath + "\\" + DateTime.Now.Day + "-" + DateTime.Now.Month + "-" + DateTime.Now.Year + " " + DateTime.Now.Hour + "-" + DateTime.Now.Minute+"-"+DateTime.Now.Second;
            int buildIndex = 2;

            if (Directory.Exists(_buildBasePath) == false)
                Directory.CreateDirectory(_buildBasePath);

            while (Directory.Exists(_buildDirectory) == true)
                _buildDirectory = _buildBasePath + "\\" + DateTime.Now.Day + "-" + DateTime.Now.Month + "-" + DateTime.Now.Year + " " + DateTime.Now.Hour + "-" + DateTime.Now.Minute +"-"+ DateTime.Now.Second + (buildIndex++).ToString().PadLeft(4, '0');

            // Create the build directory.
            Directory.CreateDirectory(_buildDirectory);

            // Open the game configuration file, change the pak file settings and save it into
            // the new build folder.
            XmlConfigFile configFile = new XmlConfigFile(Editor.GlobalInstance.GameName + ".xml");
            configFile.SetSetting("path:resources:usepakfiles", _compilePakFiles == true || _buildStandAlone == true ? "1" : "0");
            if (_buildStandAlone == false)
                configFile.Save(_buildDirectory + "\\" + Editor.GlobalInstance.GameName + ".xml");

            // Copy the configuration directory into the build directory.
            //IOMethods.CopyDirectory(Editor.GlobalInstance.ConfigPath, _buildDirectory + "\\" + Editor.GlobalInstance.ConfigPath);

            // Copy the language directory into the build directory.
            //IOMethods.CopyDirectory(Editor.GlobalInstance.LanguagePath, _buildDirectory + "\\" + Editor.GlobalInstance.LanguagePath);

            // Copy the saves file if we have been told to.
            if (_copySaves == true && Directory.GetFiles(Editor.GlobalInstance.SavePath).Length != 0)
                IOMethods.CopyDirectory(Editor.GlobalInstance.SavePath, _buildDirectory + "\\" + Editor.GlobalInstance.SavePath);

            // Create a plugins folder.
            //IOMethods.CopyDirectory(Editor.GlobalInstance.GamePluginPath, _buildDirectory + "\\" + Editor.GlobalInstance.GamePluginPath);

            // Copy the icon.
            if (_buildStandAlone == false && File.Exists(Editor.GlobalInstance.GamePath + "\\icon.ico"))
                File.Copy(Editor.GlobalInstance.GamePath + "\\icon.ico", _buildDirectory + "\\icon.ico");

            // Compile the pak files or copy the media directory if we are not using pak files.
            if (_buildStandAlone == true)
            {
                _taskProgress = 0;
                _task = "Packing files";
                _logStack.Push(_task);

                // Work out the game ID code.
                long gameIDCode = DateTime.Now.Ticks ^ (long)configFile["title", "engine"].GetHashCode();

                // Create the pak file to save resources to.
                _pakFile = new PakFile();
                _pakFileIndex = 0;
                _pakFileSize = 0;
                _pakFileMaximumSize = 0;

                // Compile the media directory to the pak file.
                CompileDirectoryToPak(Editor.GlobalInstance.MediaPath);
                CompileDirectoryToPak(Editor.GlobalInstance.ConfigPath);
                CompileDirectoryToPak(Editor.GlobalInstance.LanguagePath);

                // Work out game files that we need.
                ArrayList gameFiles = new ArrayList();
                gameFiles.Add(AppDomain.CurrentDomain.BaseDirectory + "fusion.exe");
                gameFiles.Add(AppDomain.CurrentDomain.BaseDirectory + "graphics.dll");
                gameFiles.Add(AppDomain.CurrentDomain.BaseDirectory + "runtime.dll");
                gameFiles.Add(AppDomain.CurrentDomain.BaseDirectory + "input.dll");
                gameFiles.Add(AppDomain.CurrentDomain.BaseDirectory + "audio.dll");
                gameFiles.Add(AppDomain.CurrentDomain.BaseDirectory + "engine.dll");

                // Copy plugins.
                string[] requiredPlugins = Editor.GlobalInstance.GameConfigFile.GetSettings("requirements");
                if (requiredPlugins != null)
                {
                    foreach (string requirement in requiredPlugins)
                    {
                        string[] pathSplit = requirement.Split(new char[] { ':' });
                        string name = pathSplit[pathSplit.Length - 1];
                        string value = Editor.GlobalInstance.GameConfigFile[requirement, ""];
                        switch (name.ToLower())
                        {
                            case "plugin":
                                if (File.Exists(Editor.GlobalInstance.PluginPath + "\\" + value))
                                {
                                    //if (Directory.Exists(_buildDirectory + "\\" + Editor.GlobalInstance.PluginPath) == false)
                                    //    Directory.CreateDirectory(_buildDirectory + "\\" + Editor.GlobalInstance.PluginPath);
                                    //File.Copy(Editor.GlobalInstance.PluginPath + "\\" + value, _buildDirectory + "\\" + Editor.GlobalInstance.PluginPath + value);
                                    gameFiles.Add(AppDomain.CurrentDomain.BaseDirectory + Editor.GlobalInstance.PluginPath + "\\" + value);
                                }
                                break;
                        }
                    }
                }

                // Copy all!
                else
                {
                    if (Directory.Exists(Editor.GlobalInstance.PluginPath))
                    {
                        foreach (string file in Directory.GetFiles(Editor.GlobalInstance.PluginPath))
                        {
                            if (Path.GetExtension(file).ToLower() != ".dll") continue;
                            gameFiles.Add(file);
                        }
                    }

                    // Game plugins as well.
                    // TODO
                }

                _taskProgress = 50;
                _task = "Building executable";

                // Create the sub that we are going to add the files into.
                string stubFile = _buildDirectory + "\\" + string.Join("", configFile["title", "engine"].Split(new char[] { '\\', '/', ':', '*', '?', '"', '<', '>', '|' }, StringSplitOptions.None)) + ".exe";
                File.Copy(AppDomain.CurrentDomain.BaseDirectory + "Stand Alone Stub.exe", stubFile);

                // Open up the stub.
                Stream stubStream = StreamFactory.RequestStream(stubFile, StreamMode.Append);
                BinaryWriter stubWriter = new BinaryWriter(stubStream);

                // Grab the offset.
                long offset = stubStream.Position;
                stubWriter.Write(gameFiles.Count + 3);
                foreach (string gameFilePath in gameFiles)
                {
                    Stream fileStream = null;
                    fileStream = StreamFactory.RequestStream(gameFilePath, StreamMode.Open);
                    if (fileStream == null)
                    {
                        string tmpFile = Path.GetTempFileName();
                        File.Delete(tmpFile);
                        File.Copy(gameFilePath, tmpFile);
                        fileStream = StreamFactory.RequestStream(tmpFile, StreamMode.Open);
                    }
                    byte[] buffer = new byte[fileStream.Length];
                    fileStream.Read(buffer, 0, (int)fileStream.Length);

                    string url = gameFilePath;
                    if (url.ToLower().StartsWith(AppDomain.CurrentDomain.BaseDirectory.ToLower()))
                        url = url.Substring(AppDomain.CurrentDomain.BaseDirectory.Length);

                    stubWriter.Write(url);
                    stubWriter.Write(buffer.Length);
                    stubWriter.Write(buffer, 0, buffer.Length);
                }

                stubStream.Flush();
                GC.Collect();

                // Write the pak file into a memory stream.
                MemoryStream engineMemStream = new MemoryStream();
                BinaryWriter engineMemWriter = new BinaryWriter(engineMemStream);

                XmlConfigFile engineConfigFile = new XmlConfigFile(AppDomain.CurrentDomain.BaseDirectory + "fusion.xml");
                engineConfigFile.SetSetting("standalone", _buildStandAlone == true ? "1" : "0");
                engineConfigFile.Save(engineMemWriter);

                GC.Collect();

                // Write the game config file.
                stubWriter.Write("fusion.xml");
                stubWriter.Write((int)engineMemStream.Length);
                engineMemStream.WriteTo(stubStream);

                // Write the pak file into a memory stream.
                MemoryStream gameMemStream = new MemoryStream();
                BinaryWriter gameMemWriter = new BinaryWriter(gameMemStream);
                configFile.Save(gameMemWriter);
                GC.Collect();

                // Write the game config file.
                stubWriter.Write("standalone.xml");
                stubWriter.Write((int)gameMemStream.Length);
                gameMemStream.WriteTo(stubStream);

                // Write the pak file into a memory stream.
                MemoryStream memStream = new MemoryStream();
                BinaryWriter memWriter = new BinaryWriter(memStream);
                _pakFile.Save(memWriter);
                _pakFile.Resources.Clear();
                GC.Collect();

                // Write in the pak file.
                stubWriter.Write("data.pk");
                stubWriter.Write((int)memStream.Length);
                memStream.WriteTo(stubStream);

                // Write in the offset footer
                stubWriter.Write(gameIDCode);
                stubWriter.Write(offset);

                // Write the data into the stub.
                stubWriter.Close();
                stubStream.Close();
            }
            else
            {
                if (_compilePakFiles == true)
                {
                    _taskProgress = 0;
                    _task = "Compiling pak files";
                    _logStack.Push(_task);

                    // Create the pak file to save resources to.
                    _pakFile = new PakFile();
                    _pakFileIndex = 0;
                    _pakFileSize = 0;

                    // Compile the media directory to the pak file.
                    CompileDirectoryToPak(Editor.GlobalInstance.MediaPath);
                    CompileDirectoryToPak(Editor.GlobalInstance.ConfigPath);
                    CompileDirectoryToPak(Editor.GlobalInstance.LanguagePath);

                    // Save the pak file to the hard drive.
                    if (_pakFile.Resources.Count != 0)
                    {
                        string filePath = _buildDirectory + "\\" + _pakFilePrefix.Replace("#", _pakFileIndex.ToString()) + ".pk";
                        int index = 0;
                        while (File.Exists(filePath) == true)
                            filePath = _buildDirectory + "\\" + _pakFilePrefix.Replace("#", _pakFileIndex.ToString()) + (index++) + ".pk";
                        _pakFile.Save(filePath);
                        _pakFile.Dispose();
                    }
                }
                else
                {
                    _taskProgress = 0;
                    _task = "Copying media";
                    _logStack.Push(_task);
                    CopyDirectoryWithProgress(Editor.GlobalInstance.MediaPath, _buildDirectory + "\\" + Editor.GlobalInstance.MediaPath);
                    CopyDirectoryWithProgress(Editor.GlobalInstance.ConfigPath, _buildDirectory + "\\" + Editor.GlobalInstance.ConfigPath);
                    CopyDirectoryWithProgress(Editor.GlobalInstance.LanguagePath, _buildDirectory + "\\" + Editor.GlobalInstance.LanguagePath);
                }

                // If we are building an FGE distrubutable file then copy the icon file and copile all to pak file.
                if (_buildFGE)
                {
                    _taskProgress = 0;
                    _task = "Compiling FGE files";
                    _logStack.Push(_task);

                    // Create the pak file to save resources to.
                    _pakFile = new PakFile();
                    _pakFileIndex = 0;
                    _pakFileSize = 0;
                    _pakFileMaximumSize = 0;

                    // Pak the build directory.
                    string oldDirectory = Directory.GetCurrentDirectory();

                    Directory.SetCurrentDirectory(_buildDirectory);
                    CompileDirectoryToPak(Directory.GetCurrentDirectory());

                    // Save the pak file.
                    _pakFile.Save(Editor.GlobalInstance.GameName + ".pk");
                    _pakFile.Dispose();

                    Directory.SetCurrentDirectory(oldDirectory);

                    // Delete folder.
                    if (_copySaves == true && Directory.GetFiles(Editor.GlobalInstance.SavePath).Length != 0)
                        Directory.Delete(_buildDirectory + "\\" + Editor.GlobalInstance.SavePath);

                    // Delete all files and folders.
                    File.Delete(_buildDirectory + "\\" + Editor.GlobalInstance.GameName + ".xml");
                    if (Directory.Exists(_buildDirectory + "\\" + Editor.GlobalInstance.MediaPath))
                        Directory.Delete(_buildDirectory + "\\" + Editor.GlobalInstance.MediaPath, true);
                    if (Directory.Exists(_buildDirectory + "\\" + Editor.GlobalInstance.ConfigPath))
                        Directory.Delete(_buildDirectory + "\\" + Editor.GlobalInstance.ConfigPath, true);
                    if (Directory.Exists(_buildDirectory + "\\" + Editor.GlobalInstance.LanguagePath))
                        Directory.Delete(_buildDirectory + "\\" + Editor.GlobalInstance.LanguagePath, true);
                }
            }
        }
        /// <summary>
        ///		Processes an if expression.
        /// </summary>
        /// <returns>Result of if expression</returns>
        private bool ProcessIf()
        {
            bool result = false;

            NextToken();             // Skip the If token.

            // Check for the not operator
            bool notExists = false;

            if (_currentToken.ID == TokenID.OpLogicalNot)
            {
                notExists = true;
                NextToken();
            }

            Define define = null;

            foreach (Define def in _defineList)
            {
                if (def.Ident.ToLower() == _currentToken.Ident.ToLower())
                {
                    define = def;
                    break;
                }
            }

            if (LookAheadToken().ID == TokenID.OpEqual ||
                LookAheadToken().ID == TokenID.OpNotEqual ||
                LookAheadToken().ID == TokenID.OpGreater ||
                LookAheadToken().ID == TokenID.OpGreaterEqual ||
                LookAheadToken().ID == TokenID.OpLess ||
                LookAheadToken().ID == TokenID.OpLessEqual)
            {
                NextToken();                 // Get operator.
                TokenID opID = _currentToken.ID;
                NextToken();                 // Get value.
                string value = _currentToken.Ident;

                if (define != null)
                {
                    // Evaluate expression based on op.
                    switch (opID)
                    {
                    case TokenID.OpEqual:
                        if (define.Value == value)
                        {
                            result = true;
                        }
                        break;

                    case TokenID.OpNotEqual:
                        if (define.Value != value)
                        {
                            result = true;
                        }
                        break;

                    case TokenID.OpGreater:
                        if (int.Parse(define.Value) > int.Parse(value))
                        {
                            result = true;
                        }
                        break;

                    case TokenID.OpGreaterEqual:
                        if (int.Parse(define.Value) >= int.Parse(value))
                        {
                            result = true;
                        }
                        break;

                    case TokenID.OpLess:
                        if (int.Parse(define.Value) < int.Parse(value))
                        {
                            result = true;
                        }
                        break;

                    case TokenID.OpLessEqual:
                        if (int.Parse(define.Value) <= int.Parse(value))
                        {
                            result = true;
                        }
                        break;
                    }
                }
            }
            else
            {
                if (define != null)
                {
                    result = true;
                }
            }

            if (notExists == true)
            {
                result = !result;
            }
            return(result);
        }
        /// <summary>
        ///		Processes the given token list and acts upon any pre processor directives (eg. #if, #define, ...).
        /// </summary>
        /// <param name="tokenList">Text of script to analyse.</param>
        /// <param name="flags">Bitmask of flags explaining how to process tokens.</param>
        /// <param name="defineList">A list of defines to use while preprocessing script.</param>
        /// <param name="includePaths">A list of directory paths to use when looking for include files.</param>
        /// <returns>Number of error that occured.</returns>
        public int Process(ArrayList tokenList, CompileFlags flags, Define[] defineList, object[] includePaths)
        {
            _tokenList = tokenList;
            _newTokenList.Clear();
            _errorList.Clear();
            _defineList.Clear();
            _includedFiles.Clear();
            _includePaths = includePaths;
            _currentToken = null;
            _tokenIndex = 0;
            _compileFlags = flags;

            // Create a new define for every definition passed.
            if (defineList != null)
            {
                foreach (Define def in defineList)
                    _defineList.Add(def);
            }
            try
            {
                while (!EndOfTokenStream())
                {
                    NextToken();
                    ProcessToken();
                }
            }
            catch (CompileBreakException)
            {
                // Ignore this exception, it is used to jump out of the compiling loop.
            }

            return _errorList.Count;
        }