Ejemplo n.º 1
0
        /// <summary>
        ///		Parses a function declaration. A function is a way of isolating code that you want
        ///		to be able to call multiple times without rewriting it each time.
        ///		Syntax:
        ///			ReturnType Identifier "(" { Identifier ["=" Expression] [ "," ] } ")" Statement
        /// </summary>
        private void ParseFunction()
        {
            // Make sure we are in a state's scope.
            if (_currentToken.ID == TokenID.KeywordEvent &&
                _currentScope.Type != SymbolType.State)
                Error(ErrorCode.InvalidScope, "Events can only be declared within a state block.", false, 0);

            // Make sure we are in the global scopes as functions can't
            // be declared anywhere else.
            if (_currentScope.Type != SymbolType.State &&
                _currentScope.Type != SymbolType.Function &&
                _currentScope.Type != SymbolType.Namespace)
                Error(ErrorCode.InvalidScope, "Functions can only be declared in a function's, state's or event's scope.", false, 0);

            // Read in each flag.
            bool isThread = false;
            bool isEvent = false;
            bool isConsole = false;
            bool isExport = false;
            bool isImport = false;
            SymbolAccessModifier modifier = SymbolAccessModifier.Private;
            bool gotModifier = false;
            while (_currentToken.IsDataType == false && EndOfTokenStream() != true)
            {
                switch (_currentToken.ID)
                {
                    case TokenID.KeywordThread:
                        if (isThread == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isThread = true;
                        break;
                    case TokenID.KeywordEvent:
                        if (isEvent == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isEvent = true;
                        break;
                    case TokenID.KeywordConsole:
                        if (isConsole == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isConsole = true;
                        break;
                    case TokenID.KeywordImport:
                        if (isImport == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isImport = true;
                        break;
                    case TokenID.KeywordExport:
                        if (isExport == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isExport = true;
                        break;
                    case TokenID.KeywordPublic:
                        if (gotModifier == true) Error(ErrorCode.DuplicateFlag, "Access modifier has already been declared.", false, 0);
                        modifier = SymbolAccessModifier.Public;
                        gotModifier = true;
                        break;
                    case TokenID.KeywordPrivate:
                        if (gotModifier == true) Error(ErrorCode.DuplicateFlag, "Access modifier has already been declared.", false, 0);
                        modifier = SymbolAccessModifier.Private;
                        gotModifier = true;
                        break;
                    case TokenID.KeywordProtected:
                        if (gotModifier == true) Error(ErrorCode.DuplicateFlag, "Access modifier has already been declared.", false, 0);
                        modifier = SymbolAccessModifier.Protected;
                        gotModifier = true;
                        break;
                }
                NextToken();
            }
            if (isEvent == true && (isThread == true || isExport == true || isImport == true || isConsole == true))
                Error(ErrorCode.InvalidFlag, "Events can't be declared as native, threaded, exported, imported or console.");

            // Store the return type for later.
            DataTypeValue returnDataType = new DataTypeValue(DataTypeFromKeywordToken(_currentToken.ID), false, false);
            if (returnDataType.DataType == DataType.Invalid)
                Error(ErrorCode.InvalidDataType, "Functions can't be declared as \"" + _currentToken.Ident + "\".", false, 0);

            // Check for an array reference
            if (LookAheadToken().ID == TokenID.CharOpenBracket)
            {
                NextToken();
                returnDataType.IsArray = true;
                ExpectToken(TokenID.CharCloseBracket);
            }

            // Read in the functions identifier and store it
            // for layer use.
            ExpectToken(TokenID.TypeIdentifier);
            string functionIdentifier = _currentToken.Ident;

            // Read in the opening parenthesis used to define the paremeter list.
            ExpectToken(TokenID.CharOpenParenthesis);

            // Read in each paremeter.
            ArrayList functionParameterMask = new ArrayList();
            int parameterCount = 0;
            ArrayList paramList = new ArrayList();
            if (LookAheadToken().ID != TokenID.CharCloseParenthesis)
            {

                // Read in each parameter
                while (true)
                {

                    // Check if there is a constant keyword before this variable.
                    bool paramIsConst = false;
                    if (LookAheadToken().ID == TokenID.KeywordConst)
                    {
                        NextToken();
                        paramIsConst = true;
                    }

                    // Read in the data type keyword and store it.
                    NextToken();
                    DataTypeValue paramDataType = new DataTypeValue(DataTypeFromKeywordToken(_currentToken.ID), false, false);
                    if (paramDataType.DataType == DataType.Invalid) Error(ErrorCode.InvalidDataType, "Expecting data type keyword.", false, 0);

                    // Read in array declaration.
                    bool paramIsArray = false;
                    if (LookAheadToken().ID == TokenID.CharOpenBracket)
                    {
                        NextToken();
                        paramIsArray = true;
                        paramDataType.IsArray = true;
                        ExpectToken(TokenID.CharCloseBracket);
                    }

                    // Increase the parameter mask
                    functionParameterMask.Add(paramDataType);
                    parameterCount++;

                    // Read in the parameters identifier.
                    ExpectToken(TokenID.TypeIdentifier);
                    string paramIdentifier = _currentToken.Ident;

                    // Process parameters depending on current pass.
                    if (_currentPass == 0)
                    {
                        VariableSymbol variableSymbol = new VariableSymbol(null);
                        variableSymbol.DataType = paramDataType;
                        variableSymbol.Identifier = paramIdentifier;
                        variableSymbol.VariableType = VariableType.Parameter;
                        variableSymbol.IsArray = paramIsArray;
                        variableSymbol.IsConstant = paramIsConst;
                        paramList.Add(variableSymbol);
                    }

                    // Read in comma if it exists.
                    if (LookAheadToken().ID == TokenID.CharComma)
                        NextToken();
                    else
                        break;

                }

            }

            // *looks arounds shiftily* ... Ok its hack like but it works.
            functionParameterMask.Reverse();

            // Create a new function symbol.
            FunctionSymbol functionSymbol;
            if (_currentPass == 0)
            {
                if (_currentScope.FindFunctionByMask(functionIdentifier, functionParameterMask) != null)
                    Error(ErrorCode.DuplicateSymbol, "Function \"" + functionIdentifier + "\" redefinition.", false, 0);

                functionSymbol = new FunctionSymbol(functionIdentifier, _currentScope);
                functionSymbol.ReturnType = returnDataType;
                functionSymbol.ParameterCount = parameterCount;
                functionSymbol.IsThreadSpawner = isThread;
                functionSymbol.IsEvent = isEvent;
                functionSymbol.IsConsole = isConsole;
                functionSymbol.IsImport = isImport;
                functionSymbol.IsExport = isExport;
                functionSymbol.AccessModifier = modifier;

                if (isConsole == true && functionSymbol.ReturnType.DataType != DataType.Void)
                    Error(ErrorCode.InvalidDataType, "Console variables cannot return a value.");

                paramList.Reverse();
                int parameterIndex = 0;
                foreach (VariableSymbol variableSymbol in paramList)
                {
                    if (functionSymbol.FindSymbol(variableSymbol.Identifier, SymbolType.Variable) != null)
                        Error(ErrorCode.DuplicateSymbol, "Variable redefinition \"" + variableSymbol.Identifier + "\"");

                    // If we're a console function we can only accept bool, int, string or float
                    if (isConsole == true &&
                        (variableSymbol.DataType.IsArray == true ||
                        variableSymbol.DataType.DataType == DataType.Byte ||
                        variableSymbol.DataType.DataType == DataType.Double ||
                        variableSymbol.DataType.DataType == DataType.Object ||
                        variableSymbol.DataType.DataType == DataType.Short))
                        Error(ErrorCode.InvalidDataType, "Console variables can only accept bool, integer, string or float parameters.");

                    functionSymbol.AddSymbol(variableSymbol);
                    variableSymbol.Scope = functionSymbol;
                    parameterIndex++;
                }
            }
            else
            {
                functionSymbol = _currentScope.FindFunctionByMask(functionIdentifier, functionParameterMask) as FunctionSymbol;
                if (functionSymbol == null) functionSymbol = _globalScope.FindFunctionByMask(functionIdentifier, functionParameterMask) as FunctionSymbol;
                if (functionSymbol == null) Error(ErrorCode.InvalidFunction, "Attempt to call undeclared function \"" + functionIdentifier + "(" + functionParameterMask + ")\".");

                for (int i = 0; i < parameterCount; i++)
                {
                    VariableSymbol variableSymbol = (VariableSymbol)functionSymbol.Symbols[i];
                    variableSymbol.StackIndex = -(functionSymbol.LocalDataSize + 2 + (i + 1));
                }
            }
            _lastMetaDataSymbol = functionSymbol;

            // Read in the closing parenthesis used to define the end of the paremeter list.
            ExpectToken(TokenID.CharCloseParenthesis);

            // Read in this function's statement block.
            if (functionSymbol.IsImport == false)
            {
                Symbol scope = _currentScope;
                Instruction instruction = null;
                _currentScope = functionSymbol;
                ParseStatement();
                _currentScope = scope;

                // Append a mandatory return instruction if we are in pass 2.
                if (_currentPass == 1)
                {
                    // Cast the return registered into the return type.
                    if (functionSymbol.ReturnType.DataType != DataType.Void)
                    {
                        instruction = CreateInstruction(OpCodeByType(functionSymbol.ReturnType, OpCodeType.CAST), functionSymbol, _currentToken);
                        new Operand(instruction, Register.Return);
                    }

                    // Return from function.
                    instruction = CreateInstruction(OpCode.RETURN, functionSymbol, _currentToken);
                }
            }
            else
                ExpectToken(TokenID.CharSemiColon);
        }
 /// <summary>
 ///     Invoked when a script wants to call a method of this object.
 /// </summary>
 /// <param name="thread">Script thread that invoked this function.</param>
 /// <param name="method">Symbol describing the method that it wants called.</param>
 /// <returns>True if successfull or false if not.</returns>
 public virtual bool InvokeMethod(ScriptThread thread, FunctionSymbol method)
 {
     return false;
 }
Ejemplo n.º 3
0
        /// <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>
        ///		Executes a script or native function.
        /// </summary>
        /// <param name="symbol">Symbol of function to call.</param>
        /// <param name="ignoreThread">If set and this function is a thread spawner a new thread will not be created.</param>
        private void CallFunction(FunctionSymbol symbol, bool ignoreThread)
        {
            // Can't call if debugging :S.
            if (_debugger != null && _debugger.RunScript == false)
                return;

            // Push this function onto the call stack.
            _callStack.Push(symbol);
            _registers[(int)Register.Return].Clear();
            _callingFunction = symbol;

            if (symbol.IsImport == true)
            {
                // Find and call native function.
                if (_process.VirtualMachine != null)
                {
                    DataTypeValue[] parameterTypes = null;
                    NativeFunction function = symbol.NativeFunction;
                    if (function == null)
                    {
                        // Find the functions parameter types.
                        parameterTypes = new DataTypeValue[symbol.ParameterCount];
                        for (int i = 0; i < symbol.ParameterCount; i++)
                            parameterTypes[(symbol.ParameterCount - 1) - i] = ((VariableSymbol)symbol.Symbols[i]).DataType;

                        // Find native function
                        function = _process.VirtualMachine.FindNativeFunction(symbol.Identifier, parameterTypes);
                        symbol.NativeFunction = function;
                    }

                    if (function != null)
                    {
            #if !DEBUG
                        try
                        {

            #endif
                            function.Delegate(this);
            #if !DEBUG
                        }
                        catch (Exception e)
                        {
                            Error(e.ToString());
                        }
            #endif
                    }

                    // Ok so its not a native one, lets check the script exports.
                    else
                    {
                        ScriptExportFunction callFunction = (ScriptExportFunction)ScriptExportFunction.FunctionHashTable[symbol.ToString().ToLower()];

                        /*
                        foreach (ScriptExportFunction exportFunction in ScriptExportFunction.FunctionList)
                        {
                            if (exportFunction.Symbol.Identifier.ToLower() != symbol.Identifier.ToLower()) continue;
                            if (exportFunction.Symbol.ParameterCount != parameterTypes.Length) continue;

                            bool paramsValid = true;
                            for (int i = 0; i < parameterTypes.Length; i++)
                                if (exportFunction.Symbol.CheckParameterTypeValid(i, parameterTypes[i]) == false)
                                    paramsValid = false;

                            if (paramsValid == false) continue;

                            callFunction = exportFunction;
                            break;
                        }
                        */

                        if (callFunction != null)
                        {
                            InvokeExportFunction(callFunction.Symbol, callFunction.Thread, this);
                        }
                        else
                        {
                            Error("Attempt to call unknown function '" + symbol.ToString() + "'");
                        }
                    }
                }

                // Pop of this functions parameters.
                for (int i = 0; i < symbol.ParameterCount; i++)
                {
                    RuntimeValue stack = _runtimeStack.Pop();

                    if (stack.ObjectIndex != -1) SetObjectValue(stack, -1);
                    else if (stack.MemoryIndex != -1) SetMemoryIndexValue(stack, -1);
                }

                // Pop this value off the call stack.
                _callStack.Pop();
            }
            else
            {
                if (symbol.IsThreadSpawner == true && ignoreThread == false)
                    SpawnThread(symbol);
                else
                {
                    int oldFrameIndex = _runtimeStack.FrameIndex;

                    // Push the return address which is the current instruction.
                    RuntimeValue returnAddress = _runtimeStack.PushEmpty(RuntimeValueType.ReturnAddress);
                    returnAddress.InstrIndex = _instructionPointer;

                    // Pushs this function stack frame onto stack.
                    _runtimeStack.PushFrame(symbol.LocalDataSize + 1);

                    // Place the function and old stack index into value
                    // and push it onto stack.
                    RuntimeValue stackValue = _runtimeStack.Peek();
                    stackValue.ValueType = RuntimeValueType.StackFrameIndex;
                    stackValue.Symbol = symbol;
                    stackValue.InstrIndex = oldFrameIndex;

                    // Jump to entry point of this function.
                    _instructionPointer = symbol.EntryPoint;

                    // Force this script into 'running' mode if its been stopped.
                    _isRunning = true;
                }
            }
        }
 /// <summary>
 ///		Creates a new thread attached to the given function.
 /// </summary>
 /// <param name="symbol">The symbol of the function to execute from.</param>
 private void SpawnThread(FunctionSymbol symbol)
 {
     ScriptThread thread = new ScriptThread(_process);
     thread.InvokeFunction(symbol.Identifier, false, true);
 }
Ejemplo n.º 6
0
        /// <summary>
        ///     Syncronizes all the data shown on the window with that of the script. 
        /// </summary>
        private void SyncronizeWindow()
        {
            // Clear everything.
            Text = "Script Debugger - " + _scriptThread.Process.Url;
            variablesPropertyListView.Clear();
            callStackListView.Items.Clear();
            stackTreeView.Nodes.Clear();
            heapTreeView.Nodes.Clear();
            objectsTreeView.Nodes.Clear();
            sourceCodeScriptTextBox.Enabled = true;
            disassemblyScriptTextBox.Enabled = true;
            variablesPropertyListView.Enabled = true;
            callStackListView.Enabled = true;
            startToolStripButton.Enabled = true;
            stopToolStripButton.Enabled = false;
            stepToolStripButton.Enabled = true;
            stackTreeView.Enabled = true;
            stackPropertyGrid.Enabled = true;
            heapTreeView.Enabled = true;
            heapPropertyGrid.Enabled = true;
            objectsTreeView.Enabled = true;
            objectsPropertyGrid.Enabled = true;

            // If we are running then show nothing.
            if (_runScript == true)
            {
                startToolStripButton.Enabled = false;
                stopToolStripButton.Enabled = true;
                stepToolStripButton.Enabled = false;
                sourceCodeScriptTextBox.Enabled = false;
                disassemblyScriptTextBox.Enabled = false;
                variablesPropertyListView.Enabled = false;
                callStackListView.Enabled = false;
                stackTreeView.Enabled = false;
                stackPropertyGrid.Enabled = false;
                heapTreeView.Enabled = false;
                heapPropertyGrid.Enabled = false;
                objectsTreeView.Enabled = false;
                objectsPropertyGrid.Enabled = false;

                return;
            }

            // Grab the current instruction.
            RuntimeInstruction currentInstruction = _scriptThread.Process.Instructions[_scriptThread.InstructionPointer];

            // See if we can find the source code for this instruction.
            if (currentInstruction.File != "")
            {
                if (File.Exists(currentInstruction.File))
                {
                    // Load in source code.
                    if (_sourceURL == "" || _sourceURL != currentInstruction.File)
                    {
                        string text = File.ReadAllText(currentInstruction.File);
                        sourceCodeScriptTextBox.Text = text;
                        _sourceURL = currentInstruction.File;

                        // Highlight.
                        sourceCodeScriptTextBox.Highlight(true);
                    }

                    // Remove any background colors.
                    sourceCodeScriptTextBox.RichTextBox.SelectionStart = 0;
                    sourceCodeScriptTextBox.RichTextBox.SelectionLength = sourceCodeScriptTextBox.RichTextBox.Text.Length;
                    sourceCodeScriptTextBox.RichTextBox.SelectionBackColor = Color.White;

                    // Scroll to the correct line.
                    sourceCodeScriptTextBox.Focus();
                    sourceCodeScriptTextBox.RichTextBox.SelectionStart = sourceCodeScriptTextBox.RichTextBox.GetFirstCharIndexFromLine(currentInstruction.Line - 1);// +currentInstruction.Offset;
                    int nextLineIndex = sourceCodeScriptTextBox.RichTextBox.Text.IndexOf('\n', sourceCodeScriptTextBox.RichTextBox.SelectionStart);
                    sourceCodeScriptTextBox.RichTextBox.SelectionLength = nextLineIndex == -1 ? sourceCodeScriptTextBox.Text.Length - sourceCodeScriptTextBox.RichTextBox.SelectionStart : nextLineIndex - sourceCodeScriptTextBox.RichTextBox.SelectionStart;
                    sourceCodeScriptTextBox.RichTextBox.SelectionBackColor = Color.Red;
                    sourceCodeScriptTextBox.RichTextBox.ScrollToCaret();
                    sourceCodeScriptTextBox.RichTextBox.SelectionLength = 0;
                }
                else
                    sourceCodeScriptTextBox.Text = "";
            }

            // Build the disassembly text.
            if (disassemblyScriptTextBox.Text == "")
            {
                StringBuilder builder = new StringBuilder();
                foreach (RuntimeInstruction instruction in _scriptThread.Process.Instructions)
                    builder.Append(instruction.Decompile() + "\n");
                disassemblyScriptTextBox.Text = builder.ToString();
            }

            // Remove any background colors.
            disassemblyScriptTextBox.RichTextBox.SelectionStart = 0;
            disassemblyScriptTextBox.RichTextBox.SelectionLength = disassemblyScriptTextBox.RichTextBox.Text.Length;
            disassemblyScriptTextBox.RichTextBox.SelectionBackColor = Color.Transparent;

            // Scroll to the correct line.
            disassemblyScriptTextBox.Focus();
            disassemblyScriptTextBox.RichTextBox.SelectionStart = disassemblyScriptTextBox.RichTextBox.GetFirstCharIndexFromLine(_scriptThread.InstructionPointer);
            int disassemblyNextLineIndex = disassemblyScriptTextBox.RichTextBox.Text.IndexOf('\n', disassemblyScriptTextBox.RichTextBox.SelectionStart);
            disassemblyScriptTextBox.RichTextBox.SelectionLength = disassemblyNextLineIndex == -1 ? disassemblyScriptTextBox.Text.Length - disassemblyScriptTextBox.RichTextBox.SelectionStart : disassemblyNextLineIndex - disassemblyScriptTextBox.RichTextBox.SelectionStart;
            disassemblyScriptTextBox.RichTextBox.SelectionBackColor = Color.Red;
            disassemblyScriptTextBox.RichTextBox.ScrollToCaret();
            disassemblyScriptTextBox.RichTextBox.SelectionLength = 0;

            // Find the last last scope we were in thats not native :P.
            _lastScope = null;
            object[] callStack = _scriptThread.CallStack.ToArray();
            for (int i = 0; i < callStack.Length; i++)
            {
                callStackListView.Items.Add(new ListViewItem(new string[] { ((FunctionSymbol)callStack[i]).Identifier})); // FIX ENTRY POINT
                if (_lastScope == null && ((FunctionSymbol)callStack[i]).IsImport == false)
                {
                    _lastScope = ((FunctionSymbol)callStack[i]);
                    callStackListView.SelectedIndices.Add(callStackListView.Items.Count - 1);
                    callStackListView.Items[callStackListView.Items.Count - 1].BackColor = Color.Red;
                }
            }

            // If we have a valid scope then starting filling the locals list :P.
            #region Variables
            _localCategory = new PropertyListViewCategory("Locals");
            variablesPropertyListView.AddCategory(_localCategory);
            if (_lastScope != null)
            {
                foreach (Symbol symbol in _lastScope.Symbols)
                {
                    if (symbol.Type == SymbolType.Variable)
                    {
                        VariableSymbol variable = symbol as VariableSymbol;
                        if (variable.IsArray == true)
                        {
                            int arrayIndex = _scriptThread.GetArrayLocal(variable.Identifier); // Can be optimized.
                            if (arrayIndex == -1 || _scriptThread.Process.MemoryHeap[arrayIndex - 1] == null)
                            {
                                _localCategory.AddProperty(new PropertyListViewItem(variable.Identifier, null, null, "", typeof(string)));
                                continue;
                            }

                            int arrayLength = _scriptThread.GetArrayLength(arrayIndex);
                            object value = "";
                            Type valueType = null;

                            switch (variable.DataType.DataType)
                            {
                                case DataType.Bool:
                                    value = new bool[arrayLength];
                                    for (int i = 0; i < arrayLength; i++)
                                        ((bool[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).BooleanLiteral;
                                    valueType = typeof(bool[]);
                                    break;
                                case DataType.Byte:
                                    value = new byte[arrayLength];
                                    for (int i = 0; i < arrayLength; i++)
                                        ((byte[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).ByteLiteral;
                                    valueType = typeof(byte[]);
                                    break;
                                case DataType.Double:
                                    value = new double[arrayLength];
                                    for (int i = 0; i < arrayLength; i++)
                                        ((double[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).DoubleLiteral;
                                    valueType = typeof(double[]);
                                    break;
                                case DataType.Float:
                                    value = new float[arrayLength];
                                    for (int i = 0; i < arrayLength; i++)
                                        ((float[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).FloatLiteral;
                                    valueType = typeof(float[]);
                                    break;
                                case DataType.Int:
                                    value = new int[arrayLength];
                                    for (int i = 0; i < arrayLength; i++)
                                        ((int[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).IntegerLiteral;
                                    valueType = typeof(int[]);
                                    break;
                                case DataType.Long:
                                    value = new long[arrayLength];
                                    for (int i = 0; i < arrayLength; i++)
                                        ((long[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).LongLiteral;
                                    valueType = typeof(long[]);
                                    break;
                                case DataType.Object:
                                    value = new int[arrayLength];
                                    for (int i = 0; i < arrayLength; i++)
                                        ((int[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).ObjectIndex;
                                    valueType = typeof(int[]);
                                    break;
                                case DataType.Short:
                                    value = new short[arrayLength];
                                    for (int i = 0; i < arrayLength; i++)
                                        ((short[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).ShortLiteral;
                                    valueType = typeof(short[]);
                                    break;
                                case DataType.String:
                                    value = new string[arrayLength];
                                    for (int i = 0; i < arrayLength; i++)
                                        ((string[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).StringLiteral;
                                    valueType = typeof(string[]);
                                    break;
                            }

                            _localCategory.AddProperty(new PropertyListViewItem(variable.Identifier, value, value, "", valueType));
                        }
                        else
                        {
                            RuntimeValue variableValue = _scriptThread.GetRuntimeValueLocal(variable.Identifier); // Can be optimized.
                            object value = "";
                            Type valueType = null;
                            switch (variable.DataType.DataType)
                            {
                                case DataType.Bool: value = variableValue.BooleanLiteral; valueType = typeof(bool); break;
                                case DataType.Byte: value = variableValue.ByteLiteral; valueType = typeof(byte); break;
                                case DataType.Double: value = variableValue.DoubleLiteral; valueType = typeof(double); break;
                                case DataType.Float: value = variableValue.FloatLiteral; valueType = typeof(float); break;
                                case DataType.Int: value = variableValue.IntegerLiteral; valueType = typeof(int); break;
                                case DataType.Long: value = variableValue.LongLiteral; valueType = typeof(long); break;
                                case DataType.Object: value = variableValue.ObjectIndex; valueType = typeof(int); break;
                                case DataType.Short: value = variableValue.ShortLiteral; valueType = typeof(short); break;
                                case DataType.String: value = variableValue.StringLiteral; valueType = typeof(string); break;
                            }
                            _localCategory.AddProperty(new PropertyListViewItem(variable.Identifier, value,value, "", valueType));
                        }
                    }
                }
            }

            // Global list FTW!
               _globalCategory = new PropertyListViewCategory("Globals");
            variablesPropertyListView.AddCategory(_globalCategory);
            foreach (Symbol symbol in _scriptThread.Process.GlobalScope.Symbols)
            {
                if (symbol.Type == SymbolType.Variable)
                {
                    VariableSymbol variable = symbol as VariableSymbol;
                    if (variable.IsArray == true)
                    {
                        int arrayIndex = _scriptThread.GetArrayGlobal(variable.Identifier); // Can be optimized.
                        if (arrayIndex == -1 || _scriptThread.Process.MemoryHeap[arrayIndex - 1] == null)
                        {
                            _globalCategory.AddProperty(new PropertyListViewItem(variable.Identifier, null, null, "", typeof(string)));
                            continue;
                        }

                        int arrayLength = _scriptThread.GetArrayLength(arrayIndex);
                        object value = "";
                        Type valueType = null;

                        switch (variable.DataType.DataType)
                        {
                            case DataType.Bool:
                                value = new bool[arrayLength];
                                for (int i = 0; i < arrayLength; i++)
                                    ((bool[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).BooleanLiteral;
                                valueType = typeof(bool[]);
                                break;
                            case DataType.Byte:
                                value = new byte[arrayLength];
                                for (int i = 0; i < arrayLength; i++)
                                    ((byte[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).ByteLiteral;
                                valueType = typeof(byte[]);
                                break;
                            case DataType.Double:
                                value = new double[arrayLength];
                                for (int i = 0; i < arrayLength; i++)
                                    ((double[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).DoubleLiteral;
                                valueType = typeof(double[]);
                                break;
                            case DataType.Float:
                                value = new float[arrayLength];
                                for (int i = 0; i < arrayLength; i++)
                                    ((float[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).FloatLiteral;
                                valueType = typeof(float[]);
                                break;
                            case DataType.Int:
                                value = new int[arrayLength];
                                for (int i = 0; i < arrayLength; i++)
                                    ((int[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).IntegerLiteral;
                                valueType = typeof(int[]);
                                break;
                            case DataType.Long:
                                value = new long[arrayLength];
                                for (int i = 0; i < arrayLength; i++)
                                    ((long[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).LongLiteral;
                                valueType = typeof(long[]);
                                break;
                            case DataType.Object:
                                value = new int[arrayLength];
                                for (int i = 0; i < arrayLength; i++)
                                    ((int[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).ObjectIndex;
                                valueType = typeof(int[]);
                                break;
                            case DataType.Short:
                                value = new short[arrayLength];
                                for (int i = 0; i < arrayLength; i++)
                                    ((short[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).ShortLiteral;
                                valueType = typeof(short[]);
                                break;
                            case DataType.String:
                                value = new string[arrayLength];
                                for (int i = 0; i < arrayLength; i++)
                                    ((string[])value)[i] = _scriptThread.GetRuntimeValueArrayElement(arrayIndex, i).StringLiteral;
                                valueType = typeof(string[]);
                                break;
                        }

                        _globalCategory.AddProperty(new PropertyListViewItem(variable.Identifier, value, value, "", valueType));
                    }
                    else
                    {
                        RuntimeValue variableValue = _scriptThread.GetRuntimeValueGlobal(variable.Identifier); // Can be optimized.
                        object value = "";
                        Type valueType = null;
                        switch (variable.DataType.DataType)
                        {
                            case DataType.Bool: value = variableValue.BooleanLiteral; valueType = typeof(bool); break;
                            case DataType.Byte: value = variableValue.ByteLiteral; valueType = typeof(byte); break;
                            case DataType.Double: value = variableValue.DoubleLiteral; valueType = typeof(double); break;
                            case DataType.Float: value = variableValue.FloatLiteral; valueType = typeof(float); break;
                            case DataType.Int: value = variableValue.IntegerLiteral; valueType = typeof(int); break;
                            case DataType.Long: value = variableValue.LongLiteral; valueType = typeof(long); break;
                            case DataType.Object: value = variableValue.ObjectIndex; valueType = typeof(int); break;
                            case DataType.Short: value = variableValue.ShortLiteral; valueType = typeof(short); break;
                            case DataType.String: value = variableValue.StringLiteral; valueType = typeof(string); break;
                        }
                        _globalCategory.AddProperty(new PropertyListViewItem(variable.Identifier, value, value, "", valueType));
                    }
                }
            }
            #endregion

            // Fill up stack.
            topIndexLabel.Text = "Top Index: " + _scriptThread.Stack.TopIndex;
            frameIndexLabel.Text = "Frame Index: " + _scriptThread.Stack.FrameIndex;
            int top = _scriptThread.Stack.TopIndex > _scriptThread.Stack.FrameIndex ? _scriptThread.Stack.TopIndex : _scriptThread.Stack.FrameIndex;
            for (int i = 0; i < top; i++)
            {
                RuntimeValue runtimeValue = _scriptThread.Stack.RawStack[i];
                string name = runtimeValue.ToString();
                stackTreeView.Nodes.Add(i + ": " + name, i + ": " + name, 0);
            }

            // Fill up the object stack.
            int index = 0;
            foreach (RuntimeObject obj in _scriptThread.Process.ObjectHeap)
            {
                if (obj != null)
                {
                    string name = obj.ToString();
                    if (name.LastIndexOf('.') > -1)
                        name = name.Substring(name.LastIndexOf('.') + 1);
                    objectsTreeView.Nodes.Add(index + ": " + name, index + ": " + name, 0);
                }
                index++;
            }

            // Fill up the heap.
            index = 0;
            foreach (RuntimeValue obj in _scriptThread.Process.MemoryHeap)
            {
                if (obj != null)
                {
                    string name = obj.ToString();
                    heapTreeView.Nodes.Add(index + ": " + name, index + ": " + name, 0);
                }
                index++;
            }

            // Refresh the variables list!
            variablesPropertyListView.Refresh();
        }
 public void InvokeFunction(FunctionSymbol symbol)
 {
     InvokeFunction(symbol, false, false, false);
 }
        /// <summary>
        ///     Invokes a export function from a given script.
        /// </summary>
        /// <param name="symbol">Symbol of function to call.</param>
        /// <param name="toThread">Thread to call function.</param>
        /// <param name="fromThread">Thread to call function from.</param>
        /// <returns>Memory index of new array.</returns>
        public void InvokeExportFunction(FunctionSymbol symbol, ScriptThread toThread, ScriptThread fromThread)
        {
            // Can't invoke functions if debugging :S.
            if (_debugger != null && _debugger.AllowInvokedFunctions == false && toThread == this)
                return;

            // Find the functions parameter types.
            DataTypeValue[] parameterTypes = new DataTypeValue[symbol.ParameterCount];
            for (int i = 0; i < symbol.ParameterCount; i++)
                parameterTypes[i] = ((VariableSymbol)symbol.Symbols[i]).DataType;

            // Push any parameters we have been given.
            for (int i = 0; i < parameterTypes.Length; i++)
            {
                RuntimeValue parameter = fromThread._runtimeStack[(fromThread._runtimeStack.TopIndex - parameterTypes.Length) + i];
                parameter.DataType = parameterTypes[i];

                if (parameterTypes[i].IsArray == true)
                    toThread.PassParameterArray(CopyValueArrayFromThread(parameter, toThread, fromThread));
                else
                    toThread.PassParameter(CopyValueFromThread(parameter, toThread, fromThread));
            }

            // Call the function.
            toThread.InvokeFunction(symbol.Identifier, true, true);

            // Copy the return register.
            fromThread._registers[(int)Register.Return].DataType = symbol.ReturnType;
            if (symbol.ReturnType.IsArray == true)
                SetMemoryIndexValue(fromThread._registers[(int)Register.Return], CopyValueArrayFromThread(toThread._registers[(int)Register.Return], fromThread, toThread));
            else
                fromThread._registers[(int)Register.Return] = CopyValueFromThread(toThread._registers[(int)Register.Return], fromThread, toThread);
        }
        public void InvokeFunction(FunctionSymbol functionSymbol, bool waitForReturn, bool ignoreThread, bool stackTop)
        {
            // Can't invoke functions if debugging :S.
            if (_debugger != null && _debugger.AllowInvokedFunctions == false)
                return;

            // Check we haven't already been called.
            if (stackTop == true && _callStack.Count != 0 && _callStack.Contains(functionSymbol))
                return;

            // Check the function exists.
            if (functionSymbol == null || _isWaiting == true)
            {
                // Clear out the return register.
                _registers[(int)Register.Return].Clear();

                // Pop of passed parameters.
                for (int i = 0; i < _passedParameterCount; i++)
                {
                    RuntimeValue value = _runtimeStack.Pop();

                    if (value.ObjectIndex != -1) SetObjectValue(value, -1);
                    else if (value.MemoryIndex != -1) SetMemoryIndexValue(value, -1);
                }

                _passedParameterMask.Clear();
                _passedParameterCount = 0;
                return;
            }

            // Look through functions parameters and check the mask is correct.
            int parameterIndex = 0;
            foreach (DataTypeValue value in _passedParameterMask)
                if (functionSymbol.CheckParameterTypeValid(parameterIndex++, value) == false)
                {
                    for (int i = 0; i < _passedParameterCount; i++)
                    {
                        RuntimeValue stack = _runtimeStack.Pop();
                        if (stack.ObjectIndex != -1) SetObjectValue(stack, -1);
                        else if (stack.MemoryIndex != -1) SetMemoryIndexValue(stack, -1);
                    }
                    _passedParameterMask.Clear();
                    _passedParameterCount = 0;
                    return;
                }
            _passedParameterMask.Clear();
            _passedParameterCount = 0;

            // Call the function.
            _isRunning = true;
            CallFunction(functionSymbol, ignoreThread);

            // Push the stack base marker onto frame.
            _runtimeStack.Peek().ValueType = RuntimeValueType.StackBaseMarker;

            // Wait until function returns if thats what has been asked for.
            // Don't exit if thread is just paused.
            if (waitForReturn == true)
            {
                while (true)
                {
                    int retVal = Run(-1);
                    if (retVal == 2 || retVal == 3 || retVal == 4 || retVal == 5 || retVal == 6) break;
                }
            }

            // Collect any garbage if required.
            _process.CheckForGarbageCollection();
        }
 ///     Initializes a new instance of thsi class.
 /// </summary>
 /// <param name="symbol">Function symbol describing the function to call.</param>
 /// <param name="thread">Script thread that function is embedded in.</param>
 public ScriptExportFunction(FunctionSymbol symbol, ScriptThread thread)
 {
     _thread = thread;
     _functionSymbol = symbol;
     _functionHashTable.Add(symbol.ToString().ToLower(), this);
 }
        /// <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>
        ///     Initializes a new instance of thsi class.
        /// </summary>
        /// <param name="symbol">Function symbol describing the function to call.</param>
        /// <param name="thread">Script thread that function is embedded in.</param>
        public ScriptConsoleCommand(FunctionSymbol symbol, ScriptThread thread)
        {
            _thread = thread;
            _functionSymbol = symbol;

            ConsoleValueType[] parameters = new ConsoleValueType[symbol.ParameterCount];
            for (int i = 0; i < parameters.Length; i++)
            {
                switch (((VariableSymbol)symbol.Symbols[i]).DataType.DataType)
                {
                    case DataType.Bool: parameters[i] = ConsoleValueType.Bool; break;
                    case DataType.Float: parameters[i] = ConsoleValueType.Float; break;
                    case DataType.Int: parameters[i] = ConsoleValueType.Int; break;
                    case DataType.String: parameters[i] = ConsoleValueType.String; break;
                }
            }

            _command = new ConsoleCommand(symbol.Identifier, new CommandDelegate(InvokeCommand), parameters);
            Console.Console.RegisterCommand(_command);
        }
 ///     Initializes a new instance of thsi class.
 /// </summary>
 /// <param name="symbol">Function symbol describing the function to call.</param>
 /// <param name="thread">Script thread that function is embedded in.</param>
 public ScriptExportFunction(FunctionSymbol symbol, ScriptThread thread)
 {
     _thread = thread;
     _functionSymbol = symbol;
     _functionList.Add(this);
 }
 /// <summary>
 ///     Called when the state of this entities script is changed.
 /// </summary>
 /// <param name="process">Process that had its state changed.</param>
 /// <param name="sate">New state.</param>
 public void OnStateChange(ScriptProcess process, StateSymbol state)
 {
     _tickFunction = (state == null ? null : (state.FindSymbol("OnTick", SymbolType.Function) as FunctionSymbol));
 }
Ejemplo n.º 15
0
        /// <summary>
        /// 
        /// </summary>
        private void ParseMemberFunctionCall(string identifier, DataTypeValue returnDataType)
        {
            // Read the opening parenthesis.
            ExpectToken(TokenID.CharOpenParenthesis);

            // Pop the object out.
            if (_currentPass == 1)
            {
                Instruction instruction = CreateInstruction(OpCode.POP_OBJECT, _currentScope, _currentToken);
                new Operand(instruction, Register.Member);
            }

            // Read in each parameter's expression.
            ArrayList parameterTypeList = new ArrayList();
            string parameterMask = "";
            while (true)
            {
                // Check for parenthesis close
                if (LookAheadToken().ID != TokenID.CharCloseParenthesis)
                {
                    // Read in the parameters expression.
                    DataTypeValue expressionType = ParseExpression();
                    parameterMask += (parameterMask != "" ? "," : "") + expressionType.ToString();
                    parameterTypeList.Add(expressionType);

                    // Read in comma if we are not at the
                    // end of the parameter list.
                    if (LookAheadToken().ID != TokenID.CharCloseParenthesis)
                        ExpectToken(TokenID.CharComma);
                }
                else
                    break;
            }

            // *looks arounds shiftily* ... Ok its hack like but it works.
            parameterTypeList.Reverse();

            // Read the closing parenthesis.
            ExpectToken(TokenID.CharCloseParenthesis);

            // Get the function symbol if in pass 2.
            FunctionSymbol functionSymbol = null;
            if (_currentPass == 1)
            {
                functionSymbol = _memberScope.FindFunctionByMask(identifier, parameterTypeList) as FunctionSymbol;
                if (functionSymbol == null)
                {
                    // Create the function symbol.
                    functionSymbol = new FunctionSymbol(identifier, _memberScope);
                    functionSymbol.Identifier = identifier;
                    functionSymbol.ReturnType = returnDataType;
                    functionSymbol.IsMember = true;
                    functionSymbol.ParameterCount = parameterTypeList.Count;

                    // Create a symbol for each parameters.
                    foreach (DataTypeValue value in parameterTypeList)
                    {
                        VariableSymbol variableSymbol = new VariableSymbol(functionSymbol);
                        variableSymbol.DataType = value;
                        variableSymbol.Identifier = "";
                        variableSymbol.VariableType = VariableType.Parameter;
                        variableSymbol.IsArray = value.IsArray;
                    }
                }

                Instruction instruction = CreateInstruction(OpCode.CALL_METHOD, _currentScope, _currentToken);
                new Operand(instruction, Register.Member);
                new Operand(instruction, functionSymbol);
            }
        }
 public void InvokeFunction(FunctionSymbol symbol, bool waitForReturn, bool ignoreThread)
 {
     InvokeFunction(symbol, waitForReturn, ignoreThread, false);
 }
 /// <summary>
 ///     Called when the state of this entities script is changed.
 /// </summary>
 /// <param name="process">Process that had its state changed.</param>
 /// <param name="sate">New state.</param>
 public void OnStateChange(ScriptProcess process, StateSymbol state)
 {
     _renderFunction = state == null ? null : _process.Process.State.FindSymbol("OnRender", SymbolType.Function) as FunctionSymbol;
        // SyncCollisionEvents();
 }
Ejemplo n.º 18
0
        /// <summary>
        ///     Invoked when a script wants to call a method of this object.
        /// </summary>
        /// <param name="thread">Script thread that invoked this function.</param>
        /// <param name="method">Symbol describing the method that it wants called.</param>
        /// <returns>True if successfull or false if not.</returns>
        public override bool InvokeMethod(ScriptThread thread, FunctionSymbol method)
        {
            if (_nativeObject is ScriptedEntityNode)
            {
                ScriptProcess process = ((ScriptedEntityNode)_nativeObject).ScriptProcess;
                if (process == null)
                    return false;

                FunctionSymbol func = (FunctionSymbol)process.MemberFunctionHashTable[method.ToString().ToLower()];
                if (func != null)
                {
                    // Call the method.
                    process[0].InvokeExportFunction(func, process[0], thread);
                    return true;
                }

                /*
                foreach (Symbol symbol in process.GlobalScope.Symbols)
                {
                    if (symbol != null && symbol.Identifier.ToLower() == method.Identifier.ToLower() && symbol.Type == SymbolType.Function && ((FunctionSymbol)symbol).ParameterCount == method.ParameterCount && ((FunctionSymbol)symbol).AccessModifier == SymbolAccessModifier.Public)
                    {
                        FunctionSymbol functionSymbol = symbol as FunctionSymbol;
                        bool parametersValid = true;
                        for (int i = 0; i < functionSymbol.ParameterCount; i++)
                            if (((VariableSymbol)symbol.Symbols[i]).DataType != ((VariableSymbol)method.Symbols[i]).DataType)
                            {
                                parametersValid = false;
                                break;
                            }

                        if (parametersValid == true)
                        {
                            // Call the method.
                            process[0].InvokeExportFunction(functionSymbol, process[0], thread);
                            return true;
                        }
                    }
                }
                */
                DebugLogger.WriteLog("Unable to find method '"+method.Identifier+"'.", LogAlertLevel.Warning);
            }
            else if (_nativeObject is EntityNode)
            {
                //EntityNode entityNode = _nativeObject as EntityNode;

            }
            else if (_nativeObject is EmitterNode)
            {

            }
            else if (_nativeObject is TilemapSegmentNode)
            {

            }
            else if ((_nativeObject as SceneNode) != null)
            {

            }

            return false;
        }