예제 #1
0
        /// <summary>
        /// Decides how an expression will be handled and which actions to perform, based on the expression type.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="expression">The expression, which is being handled.</param>
        /// <param name="newLine">Indicates whether the expressions of the branch start on a new line.</param>
        private void HandleExpression(IndentedTextWriter output, ScriptExpression expression, bool newLine)
        {
            ushort ifOp        = _opcodes.GetFunctionInfo("if")[0].Opcode;
            ushort funcNameOp  = _opcodes.GetTypeInfo("function_name").Opcode;
            short  clippedtype = (short)((short)expression.Type & 0xFF);

            bool _ = (ScriptExpressionType)clippedtype switch
            {
                ScriptExpressionType.Group when expression.Opcode == ifOp && expression.LineNumber == 0 => GenerateCond(output, expression, newLine),
                ScriptExpressionType.Group => GenerateGroup(output, expression, newLine),

                ScriptExpressionType.Expression when expression.ReturnType == funcNameOp => true,
                ScriptExpressionType.Expression => GenerateExpression(output, expression, newLine),

                ScriptExpressionType.ScriptReference => GenerateScriptReference(output, expression, newLine),
                ScriptExpressionType.GlobalsReference => GenerateGlobalsReference(output, expression, newLine),
                ScriptExpressionType.ParameterReference => GenerateParameterReference(output, expression, newLine),

                _ => throw new NotImplementedException($"The Decompiler encountered an unknown Expression Type: \"{(ScriptExpressionType)clippedtype}\".")
            };
        }
예제 #2
0
        private void GenerateCode(ScriptExpression expression, IndentedTextWriter output, bool firstrun = false)
        {
            int  firstIndentedArg = int.MaxValue;
            bool isFunctionCall   = false;

            if (expression.Type == ScriptExpressionType.Expression || expression.Type == ScriptExpressionType.Expression4)
            {
                ScriptValueType type = _opcodes.GetTypeInfo((ushort)expression.ReturnType);
                if (type.Name == "function_name")
                {
                    isFunctionCall = true;

                    if (!_nextFunctionIsScript)
                    {
                        FunctionInfo info = _opcodes.GetFunctionInfo(expression.Opcode);
                        if (info != null)
                        {
                            if (info.Name.StartsWith("begin"))
                            {
                                firstIndentedArg = 0;
                                if (expression.LineNumber > 0 && !_onNewLine)
                                {
                                    output.Indent++;
                                    output.WriteLine();
                                }
                            }
                            else if (info.Name == "if")
                            {
                                firstIndentedArg = 1;
                            }
                        }
                    }
                    if (expression.LineNumber > 0)
                    {
                        output.Write("(");
                    }
                }
            }

            bool wroteAnything = HandleExpression(expression, output);
            int  startIndent   = output.Indent;

            int currentArg = 0;

            if (_h4 && firstrun)
            {
                firstIndentedArg = 0;
                currentArg       = 1;
                _h4 = false;
            }

            ScriptExpression sibling = expression.NextExpression;

            while (sibling != null)
            {
                if (wroteAnything && !_nextExpressionIsVar)
                {
                    if (currentArg == firstIndentedArg)
                    {
                        output.Indent++;
                    }
                    if (currentArg >= firstIndentedArg)
                    {
                        output.WriteLine();
                        _onNewLine = true;
                    }
                    else if (output.Indent != startIndent)
                    {
                        output.WriteLine();
                        _onNewLine = true;
                    }
                    else
                    {
                        output.Write(" ");
                    }
                }

                if (!_nextExpressionIsVar)
                {
                    wroteAnything = HandleExpression(sibling, output);
                }
                else if ((_nextExpressionIsVar && sibling.Opcode != 0xFFFF))
                {
                    if (!_varTypeWritten)
                    {
                        ScriptValueType type = _opcodes.GetTypeInfo((ushort)sibling.ReturnType);
                        output.Write(type.Name + " var_" + localVarCounter.ToString() + " ");
                        _varTypeWritten = true;
                    }

                    wroteAnything = HandleExpression(sibling, output);
                }

                sibling = sibling.NextExpression;
                currentArg++;
            }

            if (isFunctionCall && expression.LineNumber > 0)
            {
                if (output.Indent != startIndent)
                {
                    output.Indent = startIndent;
                    if (wroteAnything)
                    {
                        output.WriteLine();
                    }
                    output.Write(")");
                    _onNewLine = true;
                }
                else
                {
                    output.Write(")");
                }
            }
        }
        private void GenerateCode(ScriptExpression expression, IndentedTextWriter output)
        {
            int  firstIndentedArg = int.MaxValue;
            bool isFunctionCall   = false;

            if (expression.Type == ScriptExpressionType.Expression)
            {
                ScriptValueType type = _opcodes.GetTypeInfo((ushort)expression.ReturnType);
                if (type.Name == "function_name")
                {
                    isFunctionCall = true;

                    if (!_nextFunctionIsScript)
                    {
                        ScriptFunctionInfo info = _opcodes.GetFunctionInfo(expression.Opcode);
                        if (info != null)
                        {
                            if (info.Name.StartsWith("begin"))
                            {
                                firstIndentedArg = 0;
                                if (expression.LineNumber > 0 && !_onNewLine)
                                {
                                    output.Indent++;
                                    output.WriteLine();
                                }
                            }
                            else if (info.Name == "if")
                            {
                                firstIndentedArg = 1;
                            }
                        }
                    }
                    if (expression.LineNumber > 0)
                    {
                        output.Write("(");
                    }
                }
            }

            bool wroteAnything = HandleExpression(expression, output);
            int  startIndent   = output.Indent;

            int currentArg           = 0;
            ScriptExpression sibling = expression.Next;

            while (sibling != null)
            {
                if (wroteAnything)
                {
                    if (currentArg == firstIndentedArg)
                    {
                        output.Indent++;
                    }
                    if (currentArg >= firstIndentedArg || output.Indent != startIndent)
                    {
                        output.WriteLine();
                        _onNewLine = true;
                    }
                    else
                    {
                        output.Write(" ");
                    }
                }

                wroteAnything = HandleExpression(sibling, output);
                sibling       = sibling.Next;
                currentArg++;
            }

            if (isFunctionCall && expression.LineNumber > 0)
            {
                if (output.Indent != startIndent)
                {
                    output.Indent = startIndent;
                    if (wroteAnything)
                    {
                        output.WriteLine();
                    }
                    output.Write(")");
                    _onNewLine = true;
                }
                else
                {
                    output.Write(")");
                }
            }
        }