Ejemplo n.º 1
0
 public AssignStatement(SymbolReference target, Expression value,
     SourcePosition start, SourcePosition end)
     : base(ASTNodeType.AssignStatement, start, end)
 {
     Target = target;
     Value = value;
 }
Ejemplo n.º 2
0
        public Expression DecompileNativeFunction(UInt16 index)
        {
            var parameters = new List<Expression>();
            while (!CurrentIs(StandardByteCodes.EndFunctionParms))
            {
                var param = DecompileExpression();
                if (param == null)
                    return null; // ERROR

                parameters.Add(param);
            }
            PopByte();

            var entry = NativeTable[index];
            Expression call = null;

            switch (entry.Type)
            {
                case NativeType.Function:
                    var func = new SymbolReference(null, null, null, entry.Name);
                    call = new FunctionCall(func, parameters, null, null);
                    break;

                case NativeType.Operator:   // TODO: table should hold precedence, currently all have 0 and it'll be a mess.
                    var op = new InOpDeclaration(entry.Name, entry.Precedence, false, null, null, null, null, null, null, null);
                    call = new InOpReference(op, parameters[0], parameters[1], null, null);
                    break;

                case NativeType.PreOperator:   // TODO: table should hold precedence, currently all have 0 and it'll be a mess.
                    var preOp = new PreOpDeclaration(entry.Name, false, null, null, null, null, null, null);
                    call = new PreOpReference(preOp, parameters[0], null, null);
                    break;

                case NativeType.PostOperator:   // TODO: table should hold precedence, currently all have 0 and it'll be a mess.
                    var postOp = new PostOpDeclaration(entry.Name, false, null, null, null, null, null, null);
                    call = new PostOpReference(postOp, parameters[0], null, null);
                    break;
            }

            StartPositions.Pop();
            return call;
        }
Ejemplo n.º 3
0
        public Expression DecompileGoW_DefaultValue()
        {
            PopByte();
            var unkn = ReadByte();
            var expr = DecompileExpression();

            StartPositions.Pop();
            var op = new InOpDeclaration("", 0, true, null, null, null, null, null, null, null);
            var objRef = new SymbolReference(null, null, null, "UNSUPPORTED: GoW_DefaultValue: Byte:" + unkn + " - ");
            return new InOpReference(op, objRef, expr, null, null);
        }
Ejemplo n.º 4
0
        public Expression DecompileFunctionCall(bool byName = false, bool withUnknShort = false, bool global = false)
        {
            PopByte();
            String funcName;
            if (byName)
            {
                funcName = PCC.GetName(ReadNameRef());
            }
            else
            {
                var funcObj = ReadObject();
                funcName = funcObj.ObjectName;

                if (funcName == DataContainer.Name && !isInClassContext) // If we're calling ourself, it's a super call
                {
                    var str = "super";

                    var currentClass = DataContainer.ExportEntry.GetOuterOfType("Class").Object as ME3Class;
                    var funcOuterClass = funcObj.GetOuterOfType("Class").ObjectName;
                    if (currentClass != null && currentClass.SuperField != null && currentClass.SuperField.Name == funcOuterClass)
                        funcName = str + "." + funcName;
                    else
                        funcName = str + "(" + funcOuterClass + ")." + funcName;
                }
            }

            if (global)
                funcName = "global." + funcName;

            if (withUnknShort)
                ReadInt16(); // TODO: related to unkn65, split out? Possibly jump?

            var parameters = new List<Expression>();
            while (!CurrentIs(StandardByteCodes.EndFunctionParms))
            {
                if (CurrentIs(StandardByteCodes.Nothing))
                {
                    PopByte(); // TODO: is this reasonable? what does it mean?
                    parameters.Add(new SymbolReference(null, null, null, "None"));
                    continue;
                }

                var param = DecompileExpression();
                if (param == null)
                    return null; // ERROR

                parameters.Add(param);
            }
            PopByte();

            StartPositions.Pop();
            var func = new SymbolReference(null, null, null, funcName);
            return new FunctionCall(func, parameters, null, null);
        }
Ejemplo n.º 5
0
        // TODO: only skips one object? see code.
        public Expression DecompileEatReturn()
        {
            PopByte();
            var obj = ReadObject();
            var expr = DecompileExpression();

            StartPositions.Pop();
            var op = new InOpDeclaration("", 0, true, null, null, null, null, null, null, null);
            var objRef = new SymbolReference(null, null, null, "UNSUPPORTED: EatReturnValue: " + obj.ObjectName + "|" + obj.ClassName + " -");
            return new InOpReference(op, objRef, expr, null, null);
        }
Ejemplo n.º 6
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.º 7
0
 public FunctionCall(SymbolReference func, List <Expression> arguments, SourcePosition start, SourcePosition end)
     : base(ASTNodeType.FunctionCall, start, end)
 {
     Function  = func;
     Arguments = arguments;
 }
Ejemplo n.º 8
0
 public FunctionCall(SymbolReference func, List<Expression> parameters, SourcePosition start, SourcePosition end)
     : base(ASTNodeType.FunctionCall, start, end)
 {
     Function = func;
     Parameters = parameters;
 }
Ejemplo n.º 9
0
 public bool VisitNode(SymbolReference node)
 {
     // symbolname
     Append("{0}", node.Name);
     return true;
 }
Ejemplo n.º 10
0
        // TODO: guess for loop, probably requires a large restructure
        public Statement DecompileConditionalJump(bool isOpt = false)
        {
            PopByte();
            var scopeStartOffset = StartPositions.Pop();
            Statement statement = null;
            bool hasElse = false;
            var scopeStatements = new List<Statement>();

            UInt16 scopeEndJmpOffset = 0;
            UInt16 afterScopeOffset = 0;
            Expression conditional = null;

            if (isOpt)
            {
                var obj = ReadObject();
                var optCheck = Convert.ToBoolean(ReadByte());
                afterScopeOffset = ReadUInt16();

                String special = (optCheck ? "" : "!") + obj.ObjectName;
                conditional = new SymbolReference(null, null, null, special);
            }
            else
            {
                afterScopeOffset = ReadUInt16();
                conditional = DecompileExpression();
            }

            if (conditional == null)
                return null;

            if (afterScopeOffset < scopeStartOffset) // end of do_until detection
            {
                scopeStartOffset = afterScopeOffset;
                var outerScope = Scopes[CurrentScope.Peek()];
                var startStatement = StatementLocations[afterScopeOffset];
                StatementLocations.Remove(afterScopeOffset);
                var index = outerScope.IndexOf(startStatement);
                scopeStatements = new List<Statement>(outerScope.Skip(index));
                outerScope.RemoveRange(index, outerScope.Count - index);
                statement = new DoUntilLoop(conditional, new CodeBody(scopeStatements, null, null), null, null);
            }

            Scopes.Add(scopeStatements);
            CurrentScope.Push(Scopes.Count - 1);
            while (Position < afterScopeOffset)
            {
                if (CurrentIs(StandardByteCodes.Jump))
                {
                    var contPos = (UInt16)Position;
                    PopByte();
                    scopeEndJmpOffset = ReadUInt16();
                    if (scopeEndJmpOffset == scopeStartOffset)
                    {
                        statement = new WhileLoop(conditional, new CodeBody(scopeStatements, null, null), null, null);
                        break;
                    }
                    else if (Position < afterScopeOffset) // if we are not at the end of the scope, this is a continue statement in a loop rather than an else statement
                    {
                        var cont = new ContinueStatement(null, null);
                        StatementLocations.Add(contPos, cont);
                        scopeStatements.Add(cont);
                    }
                    else if (ForEachScopes.Count != 0 && scopeEndJmpOffset == ForEachScopes.Peek())
                    {
                        var breakStatement = new BreakStatement(null, null);
                        StatementLocations.Add(contPos, breakStatement);
                        scopeStatements.Add(breakStatement);
                    }
                    else
                    {
                        hasElse = true;
                    }

                    continue;
                }

                var current = DecompileStatement();
                if (current == null)
                    return null; // ERROR ?

                scopeStatements.Add(current);
            }
            CurrentScope.Pop();

            List<Statement> elseStatements = new List<Statement>();
            if (hasElse)
            {
                var endElseOffset = scopeEndJmpOffset;
                Scopes.Add(elseStatements);
                CurrentScope.Push(Scopes.Count - 1);
                while (Position < endElseOffset)
                {
                    var current = DecompileStatement();
                    if (current == null)
                        return null; // ERROR ?

                    elseStatements.Add(current);
                }
                CurrentScope.Pop();
            }

            statement = statement ?? new IfStatement(conditional, new CodeBody(scopeStatements, null, null),
                        null, null, elseStatements.Count != 0 ? new CodeBody(elseStatements, null, null) : null);
            StatementLocations.Add(scopeStartOffset, statement);
            return statement;
        }
Ejemplo n.º 11
0
        public Statement DecompileStatement()
        {
            StartPositions.Push((UInt16)Position);
            var token = CurrentByte;

            switch (token)
            {
                // return [expression];
                case (byte)StandardByteCodes.Return:
                    return DecompileReturn();

                // switch (expression)
                case (byte)StandardByteCodes.Switch:
                    return DecompileSwitch();

                // case expression :
                case (byte)StandardByteCodes.Case:
                    return DecompileCase();

                // if (expression) // while / for / do until
                case (byte)StandardByteCodes.JumpIfNot:
                    return DecompileConditionalJump();

                // continue
                case (byte)StandardByteCodes.Jump: // TODO: UDK seems to compile this from break when inside ForEach, handle?
                    return DecompileJump();

                // continue (iterator)
                case (byte)StandardByteCodes.IteratorNext:
                    PopByte(); // pop iteratornext token
                    return DecompileJump();

                // break;
                case (byte)StandardByteCodes.IteratorPop:
                    return DecompileIteratorPop();

                // stop;
                case (byte)StandardByteCodes.Stop:
                    PopByte();
                    var stopStatement = new StopStatement(null, null);
                    StatementLocations.Add(StartPositions.Pop(), stopStatement);
                    return stopStatement;

                // Goto label
                case (byte)StandardByteCodes.GotoLabel:
                    PopByte();
                    var labelExpr = DecompileExpression();
                    var func = new SymbolReference(null, null, null, "goto");
                    var call = new FunctionCall(func, new List<Expression>() { labelExpr }, null, null);
                    var gotoLabel = new ExpressionOnlyStatement(null, null, call);
                    StatementLocations.Add(StartPositions.Pop(), gotoLabel);
                    return gotoLabel;

                // assignable expression = expression;
                case (byte)StandardByteCodes.Let:
                case (byte)StandardByteCodes.LetBool:
                case (byte)StandardByteCodes.LetDelegate:
                    return DecompileAssign();

                // [skip x bytes]
                case (byte)StandardByteCodes.Skip: // TODO: this should never occur as statement, possibly remove?
                    PopByte();
                    ReadUInt16();
                    StartPositions.Pop();
                    return DecompileStatement();

                case (byte)StandardByteCodes.Nothing:
                    PopByte();
                    StartPositions.Pop();
                    return DecompileStatement(); // TODO, should probably have a nothing expression or statement, this is ugly

                // foreach IteratorFunction(...)
                case (byte)StandardByteCodes.Iterator:
                    return DecompileForEach();

                // foreach arrayName(valuevariable[, indexvariable])
                case (byte)StandardByteCodes.DynArrayIterator:
                    return DecompileForEach(isDynArray: true);

                case (byte)StandardByteCodes.LabelTable:
                    DecompileLabelTable();
                    StartPositions.Pop();
                    return DecompileStatement();

                #region unsupported

                case (byte)StandardByteCodes.OptIfLocal: // TODO: verify, handle syntax
                    return DecompileConditionalJump(isOpt: true);

                case (byte)StandardByteCodes.OptIfInstance: // TODO: verify, handle syntax
                    return DecompileConditionalJump(isOpt: true);

                #endregion

                default:
                    var expr = DecompileExpression();
                    if (expr != null)
                    {
                        var statement = new ExpressionOnlyStatement(null, null, expr);
                        StatementLocations.Add(StartPositions.Pop(), statement);
                        return statement;
                    }

                    // ERROR!
                    break;
            }

            return null;
        }
Ejemplo n.º 12
0
        public ReturnStatement DecompileReturn()
        {
            PopByte();

            Expression expr = null;
            if (CurrentIs(StandardByteCodes.ReturnNullValue))
            {
                // TODO: research this a bit, seems to be the zero-equivalent value for the return type.
                PopByte();
                var retVal = ReadObject();
                expr = new SymbolReference(null, null, null, "null"); // TODO: faulty obv, kind of illustrates the thing though.
            }
            else if(CurrentIs(StandardByteCodes.Nothing))
            {
                PopByte();
            }
            else
            {
                expr = DecompileExpression();
                if (expr == null && PopByte() != (byte)StandardByteCodes.Nothing)
                    return null; //ERROR ?
            }

            var statement = new ReturnStatement(null, null, expr);
            StatementLocations.Add(StartPositions.Pop(), statement);
            return statement;
        }
Ejemplo n.º 13
0
        // TODO: guess for loop, probably requires a large restructure
        public Statement DecompileForEach(bool isDynArray = false)
        {
            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.º 14
0
 public DelegateCall(SymbolReference del, List <Expression> arguments, SourcePosition start = null, SourcePosition end = null)
     : base(ASTNodeType.FunctionCall, start, end)
 {
     DelegateReference = del;
     Arguments         = arguments;
 }
Ejemplo n.º 15
0
        public DefaultPropertiesBlock ConvertDefaultProperties(List<ME3DefaultProperty> properties)
        {
            var defaults = new List<Statement>();
            foreach (var prop in properties)
            {
                        var name = new SymbolReference(null, null, null, prop.Name);
                        var value = ConvertPropertyValue(prop);
                        defaults.Add(new AssignStatement(name, value, null, null));
            }

            return new DefaultPropertiesBlock(defaults, null, null);
        }
Ejemplo n.º 16
0
        // TODO: replace this ugly-ass hack with proper AST support.
        public Expression DecompileNew()
        {
            PopByte();
            var parameters = new List<Expression>();
            for (int n = 0; n < 5; n++)
            {
                if (CurrentIs(StandardByteCodes.Nothing))
                {
                    parameters.Add(null);
                    continue;
                }

                var param = DecompileExpression();
                if (param == null)
                    return null; // ERROR

                parameters.Add(param);
            }

            Expression first = null;
            if ((parameters[0] ?? parameters[1] ?? parameters[2]) != null)
            {
                var innerParms = new List<Expression>();
                if (parameters[0] != null)
                    innerParms.Add(parameters[0]);
                if (parameters[1] != null)
                    innerParms.Add(parameters[1]);
                if (parameters[2] != null)
                    innerParms.Add(parameters[2]);
                first = new FunctionCall(new SymbolReference(null, null, null, "new"), innerParms, null, null);
            }
            else {
                first = new SymbolReference(null, null, null, "new");
            }

            var second = parameters[3] ?? new SymbolReference(null, null, null, "NoClass??");

            var op = new InOpDeclaration("", 0, true, null, null, null, null, null, null, null);
            var firstHalf = new InOpReference(op, first, second, null, null);
            StartPositions.Pop();

            if (parameters[4] != null)
                return new InOpReference(op, firstHalf, parameters[4], null, null);
            else
                return firstHalf;
        }
Ejemplo n.º 17
0
        public Expression DecompileStructMember()
        {
            PopByte();

            var MemberRef = ReadObject();
            var StructRef = ReadObject();

            ReadByte(); // discard unknown bytes
            ReadByte();

            var expr = DecompileExpression(); // get the expression for struct instance
            if (expr == null)
                return null; // ERROR

            StartPositions.Pop();
            var member = new SymbolReference(null, null, null, MemberRef.ObjectName);
            return new CompositeSymbolRef(expr, member, null, null);
        }
Ejemplo n.º 18
0
 public bool VisitNode(SymbolReference node)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 19
0
 public FunctionCall(SymbolReference func, List <Expression> parameters, SourcePosition start, SourcePosition end)
     : base(ASTNodeType.FunctionCall, start, end)
 {
     Function   = func;
     Parameters = parameters;
 }
Ejemplo n.º 20
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);
                    }
                }
            }
        }