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); } }