Пример #1
0
        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!");
        }
Пример #2
0
        public static Function CompileFunctionBodyAST(ExportEntry parentExport, string scriptText, Function func, MessageLog log, FileLib lib = null)
        {
            var symbols = lib?.GetSymbolTable() ?? StandardLibrary.GetSymbolTable();

            symbols.RevertToObjectStack();

            if (parentExport.IsClass && symbols.TryGetType(parentExport.ObjectName, out Class containingClass))
            {
                int      funcIdx          = containingClass.Functions.FindIndex(fun => fun.Name == func.Name);
                Function originalFunction = containingClass.Functions[funcIdx];
                originalFunction.Body       = func.Body;
                originalFunction.Body.Outer = originalFunction;
                for (int i = 0; i < func.Parameters.Count && i < originalFunction.Parameters.Count; i++)
                {
                    originalFunction.Parameters[i].UnparsedDefaultParam = func.Parameters[i].UnparsedDefaultParam;
                }
                originalFunction.Locals.Clear();

                if (!containingClass.Name.CaseInsensitiveEquals("Object"))
                {
                    symbols.GoDirectlyToStack(((Class)containingClass.Parent).GetInheritanceString());
                    symbols.PushScope(containingClass.Name);
                }

                CodeBodyParser.ParseFunction(originalFunction, scriptText, symbols, log);
                return(originalFunction);
            }
            //in state
            if (parentExport.Parent is ExportEntry classExport && classExport.IsClass && symbols.TryGetType(classExport.ObjectNameString, out Class cls) &&
                cls.States.FirstOrDefault(s => s.Name.CaseInsensitiveEquals(parentExport.ObjectNameString)) is State state &&
                state.Functions.FirstOrDefault(f => f.Name == func.Name) is Function canonicalFunction)
            {
                canonicalFunction.Body       = func.Body;
                canonicalFunction.Body.Outer = canonicalFunction;
                for (int i = 0; i < func.Parameters.Count && i < canonicalFunction.Parameters.Count; i++)
                {
                    canonicalFunction.Parameters[i].UnparsedDefaultParam = func.Parameters[i].UnparsedDefaultParam;
                }
                canonicalFunction.Locals.Clear();

                symbols.GoDirectlyToStack(((Class)cls.Parent).GetInheritanceString());
                symbols.PushScope(cls.Name);
                symbols.PushScope(state.Name);

                CodeBodyParser.ParseFunction(canonicalFunction, scriptText, symbols, log);
                return(canonicalFunction);
            }

            return(null);
        }
Пример #3
0
        public static (ASTNode astNode, MessageLog log) CompileFunction(ExportEntry export, string scriptText, FileLib lib = null)
        {
            (ASTNode astNode, MessageLog log) = CompileAST(scriptText, export.ClassName);
            if (astNode != null && log.AllErrors.IsEmpty())
            {
                if (astNode is Function func && (lib?.IsInitialized ?? StandardLibrary.IsInitialized) && export.Parent is ExportEntry parent)
                {
                    try
                    {
                        astNode = CompileFunctionBodyAST(parent, scriptText, func, log, lib);
                    }
                    catch (ParseError)
                    {
                        log.LogError("Parse failed!");
                        return(astNode, log);
                    }
                    catch (Exception exception)
                    {
                        log.LogError($"Parse failed! Exception: {exception}");
                        return(astNode, log);
                    }

                    if (astNode is Function funcFullAST)
                    {
                        try
                        {
                            var bytecodeVisitor = new ByteCodeCompilerVisitor(export.GetBinaryData <UFunction>());
                            bytecodeVisitor.Compile(funcFullAST);
                            if (log.AllErrors.Count == 0)
                            {
                                log.LogMessage("Compiled!");
                            }
                            return(astNode, log);
                        }
                        catch (Exception exception)
                        {
                            log.LogError(exception.Message);
                        }
                    }
                }
            }

            return(null, log);
        }