Ejemplo n.º 1
0
        public Expression DecompileContext(bool isClass = false)
        {
            PopByte();

            var left = DecompileExpression();

            if (left == null)
            {
                return(null); // ERROR
            }
            ReadInt16();      // discard MemSize value. (size of expr-right in half-bytes)
            ReadObject();     // discard RetValRef.
            ReadByte();       // discard unknown byte.

            isInClassContext = isClass;
            var right = DecompileExpression();

            if (right == null)
            {
                return(null); // ERROR
            }
            isInClassContext = false;

            if (isClass)
            {
                var builder = new CodeBuilderVisitor(); // what a wonderful hack, TODO.
                left.AcceptVisitor(builder);
                var str = builder.GetCodeString() + ".static";
                left = new SymbolReference(null, null, null, str);
            }

            StartPositions.Pop();
            return(new CompositeSymbolRef(left, right, null, null));
        }
Ejemplo n.º 2
0
        public Expression DecompileDynArrFunction(String name, bool secondArg = false, bool withoutMemOffs = false, bool withoutTrailingByte = false)
        {
            PopByte();
            var arr = DecompileExpression();

            if (arr == null)
            {
                return(null);
            }

            if (!withoutMemOffs)
            {
                ReadInt16(); // MemSize
            }
            var args = new List <Expression>();

            if (secondArg)
            {
                var prop = DecompileExpression();
                if (prop == null)
                {
                    return(null);
                }
                args.Add(prop);
            }

            var value = DecompileExpression();

            if (value == null)
            {
                return(null);
            }
            args.Add(value);

            if (!withoutTrailingByte)
            {
                PopByte();                          // EndFuncParms
            }
            var builder = new CodeBuilderVisitor(); // what a wonderful hack, TODO.

            arr.AcceptVisitor(builder);

            StartPositions.Pop();
            // TODO: ugly solution, should be reworked once dynarrays are in the AST.
            return(new FunctionCall(new SymbolReference(null, null, null, builder.GetCodeString() + "." + name), args, null, null));
        }
Ejemplo n.º 3
0
        private void DecompileDefaultParameterValues(List <Statement> statements)
        {
            OptionalParams = new Stack <FunctionParameter>();
            var func = DataContainer as ME3Function;

            if (func != null) // Gets all optional params for default value parsing
            {
                for (int n = 0; n < Parameters.Count; n++)
                {
                    if (func.Parameters[n].PropertyFlags.HasFlag(PropertyFlags.OptionalParm))
                    {
                        OptionalParams.Push(Parameters[n]);
                    }
                }
            }

            while (CurrentByte == (byte)StandardByteCodes.DefaultParmValue ||
                   CurrentByte == (byte)StandardByteCodes.Nothing)
            {
                StartPositions.Push((UInt16)Position);
                var token = PopByte();
                if (token == (byte)StandardByteCodes.DefaultParmValue) // default value assigned
                {
                    ReadInt16();                                       //MemSize of value
                    var value = DecompileExpression();
                    PopByte();                                         // end of value

                    var builder = new CodeBuilderVisitor();            // what a wonderful hack, TODO.
                    value.AcceptVisitor(builder);

                    if (OptionalParams.Count != 0)
                    {
                        var parm = OptionalParams.Pop();
                        parm.Variables.First().Name += " = " + builder.GetCodeString();
                        StartPositions.Pop();
                    }
                    else
                    {       // TODO: weird, research how to deal with this
                        var comment   = new SymbolReference(null, null, null, "// Orphaned Default Parm: " + builder.GetCodeString());
                        var statement = new ExpressionOnlyStatement(null, null, comment);
                        StatementLocations.Add(StartPositions.Pop(), statement);
                        statements.Add(statement);
                    }
                }
            }
        }
Ejemplo n.º 4
0
        public void BasicClassTest()
        {
            var source =
                "class Test Deprecated Transient; \n" +
                "var enum ETestnumeration {\n" +
                "     TEST_value1,\n" +
                "     TEST_value2,\n" +
                "     TEST_value3,\n" +
                "} inlineNumeration, testnum2;\n" +
                "var private deprecated int X; \n" +
                "VAR INT Y, Z; \n" +
                "var ETestnumeration testnum;\n" +
                "struct transient testStruct\n" +
                "{ var float a, b, c; };\n" +
                "var private struct transient twoStruct extends testStruct\n" +
                "{\n" +
                "   var etestnumeration num;\n" +
                "} structA, structB;\n" +
                "function float funcB( testStruct one, float two ) \n" +
                "{\n" +
                "   local float c;" +
                "   one.a = 1.3 * c;" +
                "   while (true)" +
                "   {" +
                "       c = c - c - c;" +
                "   }" +
                "   if (false) {" +
                "       switch(one.a) {" +
                "           case one.a:" +
                "               c = one.a;" +
                "               break;" +
                "           case 1.2:" +
                "           case 1.3:" +
                "               c = c + 0.5;" +
                "               break;" +
                "           default:" +
                "               c = 6.6;" +
                "       }" +
                "   }" +
                "   return one.a + 0.33 * (0.66 + 0.1) * 1.5;\n" +
                "}\n" +
                "private simulated function float MyFunc( out testStruct one, coerce optional float two ) \n" +
                "{\n" +
                "   return one.b + funcB(one, two);\n" +
                "}\n" +
                "auto state MyState\n" +
                "{\n" +
                "ignores MyFunc;\n" +
                "function StateFunc()\n" +
                "{\n" +
                "}\n" +
                "\n" +
                "Begin:\n" +
                "       moredragons\n" +
                "}\n" +
                "\n" +
                "final static operator(254) int >>>( coerce float left, coerce float right )\n" +
                "{\n" +
                "   all the dragons\n" +
                "}\n" +
                "\n" +
                "\n" +
                "\n";

            var parser  = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);
            var symbols = new SymbolTable();

            Class obj = new Class("Object", null, null, null, null, null, null, null, null, null, null);

            obj.OuterClass = obj;
            symbols.PushScope(obj.Name);
            symbols.AddSymbol(obj.Name, obj);

            VariableType integer = new VariableType("int", null, null);

            symbols.AddSymbol(integer.Name, integer);
            VariableType floatingpoint = new VariableType("float", null, null);

            symbols.AddSymbol(floatingpoint.Name, floatingpoint);

            InOpDeclaration plus_float = new InOpDeclaration("+", 20, false, null, floatingpoint, new FunctionParameter(floatingpoint, null, null, null, null),
                                                             new FunctionParameter(floatingpoint, null, null, null, null), null, null, null);

            symbols.AddOperator(plus_float);

            InOpDeclaration sub_float = new InOpDeclaration("-", 20, false, null, floatingpoint, new FunctionParameter(floatingpoint, null, null, null, null),
                                                            new FunctionParameter(floatingpoint, null, null, null, null), null, null, null);

            symbols.AddOperator(sub_float);

            InOpDeclaration mult_float = new InOpDeclaration("*", 16, false, null, floatingpoint, new FunctionParameter(floatingpoint, null, null, null, null),
                                                             new FunctionParameter(floatingpoint, null, null, null, null), null, null, null);

            symbols.AddOperator(mult_float);

            Class node           = (Class)parser.ParseDocument();
            var   ClassValidator = new ClassValidationVisitor(log, symbols);

            node.AcceptVisitor(ClassValidator);

            symbols.GoDirectlyToStack(node.GetInheritanceString());
            foreach (Function f in node.Functions)
            {
                symbols.PushScope(f.Name);
                var p = new CodeBodyParser(new TokenStream <String>(new StringLexer(source)), f.Body, symbols, f, log);
                var b = p.ParseBody();
                symbols.PopScope();
            }

            var CodeBuilder = new CodeBuilderVisitor();

            node.AcceptVisitor(CodeBuilder);
            Console.Write(CodeBuilder.GetCodeString());

            Assert.IsTrue(log.AllErrors.Count == 0);

            return;
        }
Ejemplo n.º 5
0
        public Statement DecompileForEach(bool isDynArray = false) // TODO: guess for loop, probably requires a large restructure
        {
            PopByte();
            var scopeStatements = new List <Statement>();

            var iteratorFunc = DecompileExpression();

            if (iteratorFunc == null)
            {
                return(null);
            }

            Expression dynArrVar   = null;
            Expression dynArrIndex = null;
            bool       unknByte    = false;

            if (isDynArray)
            {
                dynArrVar   = DecompileExpression();
                unknByte    = Convert.ToBoolean(ReadByte());
                dynArrIndex = DecompileExpression();
            }

            var scopeEnd = ReadUInt16(); // MemOff

            ForEachScopes.Push(scopeEnd);

            Scopes.Add(scopeStatements);
            CurrentScope.Push(Scopes.Count - 1);
            while (Position < Size)
            {
                if (CurrentIs(StandardByteCodes.IteratorNext) && PeekByte == (byte)StandardByteCodes.IteratorPop)
                {
                    PopByte(); // IteratorNext
                    PopByte(); // IteratorPop
                    break;
                }

                var current = DecompileStatement();
                if (current == null)
                {
                    return(null); // ERROR ?
                }
                scopeStatements.Add(current);
            }
            CurrentScope.Pop();
            ForEachScopes.Pop();

            if (isDynArray)
            {
                var builder = new CodeBuilderVisitor(); // what a wonderful hack, TODO.
                iteratorFunc.AcceptVisitor(builder);
                var arrayName  = new SymbolReference(null, null, null, builder.GetCodeString());
                var parameters = new List <Expression>()
                {
                    dynArrVar, dynArrIndex
                };
                iteratorFunc = new FunctionCall(arrayName, parameters, null, null);
            }

            var statement = new ForEachLoop(iteratorFunc, new CodeBody(scopeStatements, null, null), null, null);

            StatementLocations.Add(StartPositions.Pop(), statement);
            return(statement);
        }
Ejemplo n.º 6
0
        public static bool ResolveAllClassesInPackage(IMEPackage pcc, ref SymbolTable symbols)
        {
            string fileName = Path.GetFileNameWithoutExtension(pcc.FilePath);

#if DEBUGSCRIPT
            string dumpFolderPath = Path.Combine(ME3Directory.gamePath, "ScriptDump", fileName);
            Directory.CreateDirectory(dumpFolderPath);
#endif
            var log = new MessageLog();
            Debug.WriteLine($"{fileName}: Beginning Parse.");
            var classes = new List <(Class ast, string scriptText)>();
            foreach (ExportEntry export in pcc.Exports.Where(exp => exp.IsClass))
            {
                Class  cls        = ME3ObjectToASTConverter.ConvertClass(export.GetBinaryData <UClass>(), false);
                string scriptText = "";
                try
                {
#if DEBUGSCRIPT
                    var codeBuilder = new CodeBuilderVisitor();
                    cls.AcceptVisitor(codeBuilder);
                    scriptText = codeBuilder.GetCodeString();
                    File.WriteAllText(Path.Combine(dumpFolderPath, $"{cls.Name}.uc"), scriptText);
                    var parser = new ClassOutlineParser(new TokenStream <string>(new StringLexer(scriptText, log)), log);
                    cls = parser.TryParseClass();
                    if (cls == null || log.Content.Any())
                    {
                        DisplayError(scriptText, log.ToString());
                        return(false);
                    }
#endif

                    if (export.ObjectName == "Object")
                    {
                        symbols = SymbolTable.CreateIntrinsicTable(cls);
                    }
                    else
                    {
                        symbols.AddType(cls);
                    }

                    classes.Add(cls, scriptText);
                }
                catch (Exception e) when(!App.IsDebug)
                {
                    DisplayError(scriptText, log.ToString());
                    return(false);
                }
            }
            Debug.WriteLine($"{fileName}: Finished parse.");
            foreach (var validationPass in Enums.GetValues <ValidationPass>())
            {
                foreach ((Class ast, string scriptText) in classes)
                {
                    try
                    {
                        var validator = new ClassValidationVisitor(log, symbols, validationPass);
                        ast.AcceptVisitor(validator);
                        if (log.Content.Any())
                        {
                            DisplayError(scriptText, log.ToString());
                            return(false);
                        }
                    }
                    catch (Exception e) when(!App.IsDebug)
                    {
                        DisplayError(scriptText, log.ToString());
                        return(false);
                    }
                }
                Debug.WriteLine($"{fileName}: Finished validation pass {validationPass}.");
            }

            switch (fileName)
            {
            case "Core":
                symbols.InitializeOperators();
                break;

            case "Engine":
                symbols.ValidateIntrinsics();
                break;
            }

#if DEBUGSCRIPT
            //parse function bodies for testing purposes
            foreach ((Class ast, string scriptText) in classes)
            {
                symbols.RevertToObjectStack();
                if (!ast.Name.CaseInsensitiveEquals("Object"))
                {
                    symbols.GoDirectlyToStack(((Class)ast.Parent).GetInheritanceString());
                    symbols.PushScope(ast.Name);
                }

                foreach (Function function in ast.Functions.Where(func => !func.IsNative && func.IsDefined))
                {
                    CodeBodyParser.ParseFunction(function, scriptText, symbols, log);
                    if (log.Content.Any())
                    {
                        DisplayError(scriptText, log.ToString());
                    }
                }
            }
#endif


            symbols.RevertToObjectStack();

            return(true);
        }