Exemple #1
0
        public Statement DecompileStatement(ushort?startPosition = null)
        {
            StartPositions.Push(startPosition ?? (ushort)Position);
            var token = PeekByte;

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

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

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

            // if (expression) // while / for / do until
            case (byte)OpCodes.JumpIfNot:
            {
                PopByte();
                var jump = new IfNotJump(ReadUInt16(), DecompileExpression(), Position - StartPositions.Peek());
                StatementLocations.Add(StartPositions.Pop(), jump);
                return(jump);
            }

            case (byte)OpCodes.Jump:
            {
                PopByte();
                ushort jumpLoc = ReadUInt16();
                if (ForEachScopes.Count > 0 && jumpLoc == ForEachScopes.Peek())
                {
                    var brk = new BreakStatement();
                    StatementLocations.Add(StartPositions.Pop(), brk);
                    return(brk);
                }
                var jump = new UnconditionalJump(jumpLoc);
                StatementLocations.Add(StartPositions.Pop(), jump);
                return(jump);
            }

            // continue (iterator)
            case (byte)OpCodes.IteratorNext:
            {
                PopByte();
                var itNext = new ContinueStatement();
                StatementLocations.Add(StartPositions.Pop(), itNext);
                if (PopByte() != (byte)OpCodes.Jump)
                {
                    return(null);    //there should always be a jump after an iteratornext that's not at the end of the loop
                }
                //skip the jump address
                PopByte();
                PopByte();
                return(itNext);
            }

            // break;
            case (byte)OpCodes.IteratorPop:
            {
                PopByte();
                return(DecompileStatement(StartPositions.Pop()));
            }

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

            // Goto label
            case (byte)OpCodes.GotoLabel:
                PopByte();
                var gotoLabel = new StateGoto(DecompileExpression());
                StatementLocations.Add(StartPositions.Pop(), gotoLabel);
                return(gotoLabel);

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

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

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

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

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

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

            case (byte)OpCodes.OptIfLocal:
            case (byte)OpCodes.OptIfInstance:
            {
                PopByte();
                IEntry obj       = ReadObject();
                var    condition = new SymbolReference(null, obj.ObjectName.Instanced);
                bool   not       = Convert.ToBoolean(ReadByte());
                if (obj.ClassName == "BoolProperty")
                {
                    var ifJump = new IfNotJump(
                        ReadUInt16(), not ? (Expression)condition : new PreOpReference(new PreOpDeclaration("!", SymbolTable.BoolType, 0, null), condition),
                        Position - StartPositions.Peek());
                    StatementLocations.Add(StartPositions.Pop(), ifJump);
                    return(ifJump);
                }

                var nullJump = new NullJump(ReadUInt16(), condition, not)
                {
                    SizeOfExpression = Position - StartPositions.Peek()
                };
                StatementLocations.Add(StartPositions.Pop(), nullJump);
                return(nullJump);
            }

            case (byte)OpCodes.FilterEditorOnly:
            {
                PopByte();
                var edFilter = new InEditorJump(ReadUInt16());
                StatementLocations.Add(StartPositions.Pop(), edFilter);
                return(edFilter);
            }

            case (byte)OpCodes.EatReturnValue:
                PopByte();
                ReadObject();
                return(DecompileStatement(StartPositions.Pop()));

            case (byte)OpCodes.Assert:
                return(DecompileAssert());

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

                // ERROR!
                return(null);
            }
        }