public Statement DecompileForEach(bool isDynArray = false) { PopByte(); var scopeStatements = new List <Statement>(); var iteratorFunc = DecompileExpression(); if (iteratorFunc == null) { return(null); } if (isDynArray) { Expression dynArrVar = DecompileExpression(); bool hasIndex = Convert.ToBoolean(ReadByte()); Expression dynArrIndex = DecompileExpression(); iteratorFunc = new DynArrayIterator(iteratorFunc, dynArrVar, dynArrIndex); } var scopeEnd = ReadUInt16(); // MemOff ForEachScopes.Push(scopeEnd); Scopes.Add(scopeStatements); CurrentScope.Push(Scopes.Count - 1); while (Position < Size) { if (CurrentIs(OpCodes.IteratorNext)) { PopByte(); // IteratorNext if (PeekByte == (byte)OpCodes.IteratorPop) { StatementLocations[(ushort)(Position - 1)] = new IteratorNext(); StatementLocations[(ushort)Position] = new IteratorPop(); PopByte(); // IteratorPop break; } Position--; } var current = DecompileStatement(); if (current == null) { return(null); // ERROR ? } scopeStatements.Add(current); } CurrentScope.Pop(); ForEachScopes.Pop(); var statement = new ForEachLoop(iteratorFunc, new CodeBody(scopeStatements)) { iteratorPopPos = Position - 1 }; StatementLocations.Add(StartPositions.Pop(), statement); return(statement); }
// Add a specific set of methods into a new scope // Pop the scope but keep a pointer to it in a look up table private void AddBuiltinMethods(PredefScopes predefscope, Type codetype, Type deftype, PredefKinds kind) { var scope = CurrentScope.Push(); PredefScopeDict[predefscope] = new BuiltinScopeInfo { Predef = predefscope, CodeType = codetype, DefType = deftype, Scope = scope, Kind = kind, }; foreach (var binfo in CallInfo.GetBuiltinInfo(codetype)) { AddMethod(binfo.Name, binfo, predefscope); } scope.Pop(); }
public SwitchStatement DecompileSwitch() { PopByte(); var objIndex = ReadObject(); var unknByte = ReadByte(); var expr = DecompileExpression(); var scopeStatements = new List <Statement>(); UInt16 endOffset = 0xFFFF; // set it at max to begin with, so we can begin looping Scopes.Add(scopeStatements); CurrentScope.Push(Scopes.Count - 1); while (Position < endOffset && Position < Size) { if (CurrentIs(StandardByteCodes.Jump)) // break detected, save the endOffset { // executes for all occurences, to handle them all. StartPositions.Push((UInt16)Position); PopByte(); endOffset = ReadUInt16(); var breakStatement = new BreakStatement(null, null); StatementLocations.Add(StartPositions.Pop(), breakStatement); scopeStatements.Add(breakStatement); continue; } var current = DecompileStatement(); if (current == null) { return(null); // ERROR ? } scopeStatements.Add(current); if (current is DefaultStatement && endOffset == 0xFFFF) { break; // If no break was detected, we end the switch rather than include the rest of ALL code in the default. } } CurrentScope.Pop(); var statement = new SwitchStatement(expr, new CodeBody(scopeStatements, null, null), null, null); StatementLocations.Add(StartPositions.Pop(), statement); return(statement); }
public Statement DecompileForEach(bool isDynArray = false) // TODO: guess for loop, probably requires a large restructure { 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); }
public Statement DecompileConditionalJump(bool isOpt = false) // TODO: guess for loop, probably requires a large restructure { 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); }