/// <summary>Prepares to adapt a command entry to CIL.</summary> /// <param name="values">The adaptation-relevant values.</param> /// <param name="entry">The present entry ID.</param> public override void PreAdaptToCIL(CILAdaptationValues values, int entry) { CommandEntry cent = values.Entry.Entries[entry]; if (cent.IsCallback) { values.PopVarSet(); return; } string arg = cent.Arguments[0].ToString(); if (arg == "next" || arg == "stop") { return; } values.PushVarSet(); string sn = cent.GetSaveNameNoParse("while_index"); if (values.LocalVariableLocation(sn) >= 0) { throw new ErrorInducedException("Already have a while_index var (labeled '" + sn + "')?!"); } TagType type = cent.TagSystem.Types.Type_Integer; values.AddVariable(sn, type); }
/// <summary>Adapts a command entry to CIL.</summary> /// <param name="values">The adaptation-relevant values.</param> /// <param name="entry">The present entry ID.</param> public override void AdaptToCIL(CILAdaptationValues values, int entry) { CommandEntry cent = values.CommandAt(entry); bool db = cent.DBMode <= DebugMode.FULL; if (cent.IsCallback) { int lvar_ind_loc = GetSaveLoc(values, entry); values.LoadQueue(); if (db) { values.LoadEntry(entry); } else { values.ILGen.Emit(OpCodes.Ldc_I4, cent.BlockStart - 1); } values.LoadLocalVariable(lvar_ind_loc); values.ILGen.Emit(OpCodes.Call, db ? TryForeachCILMethod : TryForeachCILMethodNoDebug); values.ILGen.Emit(OpCodes.Brtrue, values.Entry.AdaptedILPoints[cent.BlockStart]); return; } string arg = cent.Arguments[0].ToString(); if (arg == "stop") { for (int i = entry - 1; i >= 0; i--) { CommandEntry nextEntry = values.Entry.Entries[i]; if (nextEntry.Command is not ForeachCommand || nextEntry.IsCallback) { continue; } string a0 = nextEntry.Arguments[0].ToString(); if (a0 == "start" && nextEntry.InnerCommandBlock != null) { if (db) { values.LoadQueue(); values.LoadEntry(entry); values.ILGen.Emit(OpCodes.Call, DebugStopMethod); } values.ILGen.Emit(OpCodes.Br, values.Entry.AdaptedILPoints[nextEntry.BlockEnd + 2]); return; } } throw new ErrorInducedException("Invalid 'foreach stop' command: not inside a foreach block!"); } else if (arg == "next") { for (int i = entry - 1; i >= 0; i--) { CommandEntry nextEntry = values.Entry.Entries[i]; if (nextEntry.Command is not ForeachCommand || nextEntry.IsCallback) { continue; } string a0 = nextEntry.Arguments[0].ToString(); if (a0 == "start" && nextEntry.InnerCommandBlock != null) { if (db) { values.LoadQueue(); values.LoadEntry(entry); values.ILGen.Emit(OpCodes.Call, DebugNextMethod); } values.ILGen.Emit(OpCodes.Br, values.Entry.AdaptedILPoints[nextEntry.BlockEnd + 1]); return; } } throw new ErrorInducedException("Invalid 'foreach next' command: not inside a foreach block!"); } else if (arg == "start") { SingleCILVariable locVar = cent.VarLookup[cent.GetSaveNameNoParse("foreach_value")]; values.LoadQueue(); values.LoadEntry(entry); values.LoadRunnable(); values.ILGen.Emit(OpCodes.Call, CreateListItemMethod); values.ILGen.Emit(OpCodes.Stfld, locVar.Field); values.LoadLocalVariable(locVar.Index); values.ILGen.Emit(OpCodes.Call, db ? TryForeachNumberedCILMethod : TryForeachNumberedCIL_NoDebugMethod); values.ILGen.Emit(OpCodes.Brfalse, values.Entry.AdaptedILPoints[cent.BlockEnd + 2]); } else { throw new ErrorInducedException("Invalid 'foreach' command: unknown argument: " + arg); } }
/// <summary>Adapts a command entry to CIL.</summary> /// <param name="values">The adaptation-relevant values.</param> /// <param name="entry">The present entry ID.</param> public override void AdaptToCIL(CILAdaptationValues values, int entry) { CommandEntry cent = values.CommandAt(entry); bool db = cent.DBMode <= DebugMode.FULL; if (cent.IsCallback) { string sn = values.Entry.Entries[cent.BlockStart - 1].GetSaveNameNoParse("while_index"); int lvar_ind_loc = cent.VarLoc(sn); values.LoadQueue(); if (db) { values.LoadEntry(entry); } else { values.ILGen.Emit(OpCodes.Ldc_I4, cent.BlockStart - 1); } values.LoadLocalVariable(lvar_ind_loc); values.ILGen.Emit(OpCodes.Call, db ? TryWhileCILMethod : TryWhileCILMethodNoDebug); values.ILGen.Emit(OpCodes.Brtrue, values.Entry.AdaptedILPoints[cent.BlockStart]); return; } string arg = cent.Arguments[0].ToString(); if (arg == "stop") { for (int i = entry - 1; i >= 0; i--) { CommandEntry nextEntry = values.Entry.Entries[i]; if (nextEntry.Command is not WhileCommand || nextEntry.IsCallback) { continue; } string a0 = nextEntry.Arguments[0].ToString(); if (a0 != "stop" && a0 != "next" && nextEntry.InnerCommandBlock != null) { if (db) { values.LoadQueue(); values.LoadEntry(entry); values.ILGen.Emit(OpCodes.Call, DebugStopMethod); } values.ILGen.Emit(OpCodes.Br, values.Entry.AdaptedILPoints[nextEntry.BlockEnd + 2]); return; } } throw new ErrorInducedException("Invalid 'while stop' command: not inside a while block!"); } else if (arg == "next") { for (int i = entry - 1; i >= 0; i--) { CommandEntry nextEntry = values.Entry.Entries[i]; if (nextEntry.Command is not WhileCommand || nextEntry.IsCallback) { continue; } string a0 = nextEntry.ToString(); if (a0 != "stop" && a0 != "next" && nextEntry.InnerCommandBlock != null) { if (db) { values.LoadQueue(); values.LoadEntry(entry); values.ILGen.Emit(OpCodes.Call, DebugNextMethod); } values.ILGen.Emit(OpCodes.Br, values.Entry.AdaptedILPoints[nextEntry.BlockEnd + 1]); return; } } throw new ErrorInducedException("Invalid 'while next' command: not inside a while block!"); } else { values.LoadQueue(); values.LoadEntry(entry); values.ILGen.Emit(OpCodes.Call, CreateIndexObjectMethod); values.ILGen.Emit(OpCodes.Stfld, cent.VarLookup[cent.GetSaveNameNoParse("while_index")].Field); values.ILGen.Emit(OpCodes.Call, db ? TryWhileNumberedCILMethod : TryWhileNumberedCIL_NoDebugMethod); values.ILGen.Emit(OpCodes.Brfalse, values.Entry.AdaptedILPoints[cent.BlockEnd + 2]); } }