public static (ASTNode node, string text) DecompileExport(ExportEntry export, FileLib lib = null)
        {
            try
            {
                ASTNode astNode = null;
                switch (export.ClassName)
                {
                case "Class":
                    astNode = ME3ObjectToASTConverter.ConvertClass(export.GetBinaryData <UClass>(), true, lib);
                    break;

                case "Function":
                    astNode = ME3ObjectToASTConverter.ConvertFunction(export.GetBinaryData <UFunction>(), lib: lib);
                    break;

                case "State":
                    astNode = ME3ObjectToASTConverter.ConvertState(export.GetBinaryData <UState>(), lib: lib);
                    break;

                case "Enum":
                    astNode = ME3ObjectToASTConverter.ConvertEnum(export.GetBinaryData <UEnum>());
                    break;

                case "ScriptStruct":
                    astNode = ME3ObjectToASTConverter.ConvertStruct(export.GetBinaryData <UScriptStruct>());
                    break;

                default:
                    if (export.ClassName.EndsWith("Property") && ObjectBinary.From(export) is UProperty uProp)
                    {
                        astNode = ME3ObjectToASTConverter.ConvertVariable(uProp);
                    }
                    else
                    {
                        astNode = ME3ObjectToASTConverter.ConvertDefaultProperties(export);
                    }

                    break;
                }

                if (astNode != null)
                {
                    var codeBuilder = new CodeBuilderVisitor();
                    astNode.AcceptVisitor(codeBuilder);
                    return(astNode, codeBuilder.GetCodeString());
                }
            }
            catch (Exception e) when(!App.IsDebug)
            {
                return(null, $"Error occured while decompiling {export?.InstancedFullPath}:\n\n{e.FlattenException()}");
            }

            return(null, "Could not decompile!");
        }
Example #2
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);
        }