public static CalledFunction CallEventFunction(Process parent, string label, LogicalLine retAddress) { var called = new CalledFunction(label); var newLabelList = new List <FunctionLabelLine>(); called.Finished = false; called.eventLabelList = parent.LabelDictionary.GetEventLabels(label); if (called.eventLabelList == null) { var line = parent.LabelDictionary.GetNonEventLabel(label); if (parent.LabelDictionary.GetNonEventLabel(label) != null) { throw new CodeEE("イベント関数でない関数@" + label + "(" + line.Position.Filename + ":" + line.Position.LineNo + "行目)に対しEVENT呼び出しが行われました"); } return(null); } called.counter = -1; called.group = 0; called.ShiftNext(); called.TopLabel = called.CurrentLabel; called.ReturnAddress = retAddress; called.IsEvent = true; return(called); }
public static CalledFunction CallFunction(Process parent, string label, LogicalLine retAddress) { var called = new CalledFunction(label); called.Finished = false; var labelline = parent.LabelDictionary.GetNonEventLabel(label); if (labelline == null) { if (parent.LabelDictionary.GetEventLabels(label) != null) { throw new CodeEE("イベント関数@" + label + "に対し通常のCALLが行われました(このエラーは互換性オプション「" + Config.GetConfigName(ConfigCode.CompatiCallEvent) + "」により無視できます)"); } return(null); } if (labelline.IsMethod) { throw new CodeEE("#FUCNTION(S)が定義された関数@" + labelline.LabelName + "(" + labelline.Position.Filename + ":" + labelline.Position.LineNo + "行目)に対し通常のCALLが行われました"); } called.TopLabel = labelline; called.CurrentLabel = labelline; called.ReturnAddress = retAddress; called.IsEvent = false; return(called); }
/// <summary> /// 関数内の移動。JUMPではなくGOTOやIF文など /// </summary> /// <param name="line"></param> public void JumpTo(LogicalLine line) { currentLine = line; lineCount++; //sequential = false; //ShfitNextLine(); }
public void ShiftNextLine() { currentLine = currentLine.NextLine; //nextLine = nextLine.NextLine; //RunningLine = null; //sequential = true; //GlobalStatic.Process.lineCount++; lineCount++; }
public ScriptPosition GetRunningPosition() { LogicalLine line = state.ErrorLine; if (line == null) { return(null); } return(line.Position); }
public void DoScript() { startTime = _Library.WinmmTimer.TickCount; state.lineCount = 0; bool systemProcRunning = true; //uint sp = 0; //List<uint> spl = new List<uint>(); try { //int i = 0; while (true) { methodStack = 0; systemProcRunning = true; while (state.ScriptEnd && console.IsRunning) { runSystemProc(); } if (!console.IsRunning) { //Console.Write("test"); break; } systemProcRunning = false; //sp = _Library.WinmmTimer.TickCount; runScriptProc(); //spl.Add(_Library.WinmmTimer.TickCount - sp); //++i; } } catch (Exception ec) { LogicalLine currentLine = state.ErrorLine; if (currentLine != null && currentLine is NullLine) { currentLine = null; } if (systemProcRunning) { handleExceptionInSystemProc(ec, currentLine, true); } else { handleException(ec, currentLine, true); } } }
internal LogicalLine GetScaningLine() { if (scaningLine != null) { return(scaningLine); } LogicalLine line = state.ErrorLine; if (line == null) { return(null); } return(line); }
private void checkInfiniteLoop() { //うまく動かない。BEEP音が鳴るのを止められないのでこの処理なかったことに(1.51) ////フリーズ防止。処理中でも履歴を見たりできる ////System.Windows.Forms.//Application.DoEvents(); ////System.Threading.Thread.Sleep(0); //if (!console.Enabled) //{ // //DoEvents()の間にウインドウが閉じられたらおしまい。 // console.ReadAnyKey(); // return; //} uint time = _Library.WinmmTimer.TickCount - startTime; if (time < Config.InfiniteLoopAlertTime) { return; } LogicalLine currentLine = state.CurrentLine; if ((currentLine == null) || (currentLine is NullLine)) { return; //現在の行が特殊な状態ならスルー } if (!console.Enabled) { return; //クローズしてるとMessageBox.Showができないので。 } string caption = string.Format("無限ループの可能性があります"); string text = string.Format( "現在、{0}の{1}行目を実行中です。\n最後の入力から{3}ミリ秒経過し{2}行が実行されました。\n処理を中断し強制終了しますか?", currentLine.Position.Filename, currentLine.Position.LineNo, state.lineCount, time); DialogResult result = MessageBox.Show(text, caption, MessageBoxButtons.YesNo); if (result == DialogResult.Yes) { throw new CodeEE("無限ループの疑いにより強制終了が選択されました"); } else { state.lineCount = 0; startTime = _Library.WinmmTimer.TickCount; } }
public void DoScript() { startTime = _Library.WinmmTimer.TickCount; state.lineCount = 0; bool systemProcRunning = true; try { while (true) { methodStack = 0; systemProcRunning = true; while (state.ScriptEnd && console.IsRunning) { runSystemProc(); } if (!console.IsRunning) { break; } systemProcRunning = false; runScriptProc(); } } catch (Exception ec) { LogicalLine currentLine = state.ErrorLine; if (currentLine != null && currentLine is NullLine) { currentLine = null; } if (systemProcRunning) { handleExceptionInSystemProc(ec, currentLine, true); } else { handleException(ec, currentLine, true); } } }
private void handleExceptionInSystemProc(Exception exc, LogicalLine current, bool playSound) { console.ThrowError(playSound); if (exc is CodeEE) { console.PrintError("関数の終端でエラーが発生しました:" + Program.ExeName); console.PrintError(exc.Message); } else if (exc is ExeEE) { console.PrintError("関数の終端でEmueraのエラーが発生しました:" + Program.ExeName); console.PrintError(exc.Message); } else { console.PrintError("関数の終端で予期しないエラーが発生しました:" + Program.ExeName); console.PrintError(exc.GetType().ToString() + ":" + exc.Message); string[] stack = exc.StackTrace.Split('\n'); for (int i = 0; i < stack.Length; i++) { console.PrintError(stack[i]); } } }
public void ReturnF(SingleTerm ret) { //読み込み時のチェック済みのはず //if (!IsFunctionMethod) // throw new ExeEE("ReturnFと#FUNCTIONのチェックがおかしい"); //sequential = false;//いずれにしろ順列ではない。 //呼び出し元はRETURNFコマンドか関数終了時のみ //if (functionList.Count == 0) // throw new ExeEE("実行中の関数が存在しません"); //非イベント呼び出しなので、これは起こりえない //else if (functionList.Count != 1) // throw new ExeEE("関数が複数ある"); if (Program.DebugMode) { console.DebugRemoveTraceLog(); } //OutはGetValue側で行う //functionList[0].TopLabel.Out(); currentLine = functionList[functionList.Count - 1].ReturnAddress; functionList.RemoveAt(functionList.Count - 1); //nextLine = null; MethodReturnValue = ret; return; }
private void runScriptProc() { while (true) { //bool sequential = state.Sequential; state.ShiftNextLine(); //WinmmTimerから時間を取得するのはそれ自体結構なコストがかかるので10000行に一回くらいで。 if (Config.InfiniteLoopAlertTime > 0 && (state.lineCount % 10000 == 0)) { checkInfiniteLoop(); } LogicalLine line = state.CurrentLine; InstructionLine func = line as InstructionLine; //これがNULLになる様な処理は現状ないはず //if (line == null) // throw new ExeEE("Emuera.exeは次に実行する行を見失いました"); if (line.IsError) { throw new CodeEE(line.ErrMes); } else if (func != null) { //1753 InstructionLineを先に持ってきてみる。わずかに速くなった気がしないでもない if (!Program.DebugMode && func.Function.IsDebug()) { //非DebugモードでのDebug系命令。何もしない。(SIF文のためにコメント行扱いにはできない) continue; } if (func.Argument == null) { ArgumentParser.SetArgumentTo(func); if (func.IsError) { throw new CodeEE(func.ErrMes); } } if ((skipPrint) && (func.Function.IsPrint())) { if ((userDefinedSkip) && (func.Function.IsInput())) { console.PrintError("表示スキップ中にデフォルト値を持たないINPUTに遭遇しました"); console.PrintError("INPUTに必要な処理をNOSKIP~ENDNOSKIPで囲むか、SKIPDISP 0~SKIPDISP 1で囲ってください"); throw new CodeEE("無限ループに入る可能性が高いため実行を終了します"); } continue; } if (func.Function.Instruction != null) { func.Function.Instruction.DoInstruction(exm, func, state); } else if (func.Function.IsFlowContorol()) { doFlowControlFunction(func); } else { doNormalFunction(func); } } else if ((line is NullLine) || (line is FunctionLabelLine)) { //(関数終端) or ファイル終端 //if (sequential) //{//流れ落ちてきた if (!state.IsFunctionMethod) { vEvaluator.RESULT = 0; } state.Return(0); //} //1750 飛んできた直後にShiftNextが入るのでここが実行されることは無いはず //else//CALLやJUMPで飛んできた //return; } else if (line is GotoLabelLine) { continue; //$ラベル。何もすることはない。 } else if (line is InvalidLine) { if (string.IsNullOrEmpty(line.ErrMes)) { throw new CodeEE("読込に失敗した行が実行されました。エラーの詳細は読込時の警告を参照してください。"); } else { throw new CodeEE(line.ErrMes); } } //現在そんなものはない //else // throw new ExeEE("定義されていない種類の行です"); if (!console.IsRunning || state.ScriptEnd) { return; } } }
bool doFlowControlFunction(InstructionLine func) { switch (func.FunctionCode) { case FunctionCode.LOADDATA: { ExpressionArgument intExpArg = (ExpressionArgument)func.Argument; Int64 target = intExpArg.Term.GetIntValue(exm); if (target < 0) { throw new CodeEE("LOADDATAの引数に負の値(" + target.ToString() + ")が指定されました"); } else if (target > int.MaxValue) { throw new CodeEE("LOADDATAの引数(" + target.ToString() + ")が大きすぎます"); } //EraDataResult result = vEvaluator.checkData((int)target); EraDataResult result = vEvaluator.CheckData((int)target, EraSaveFileType.Normal); if (result.State != EraDataState.OK) { throw new CodeEE("不正なデータをロードしようとしました"); } if (!vEvaluator.LoadFrom((int)target)) { throw new ExeEE("ファイルのロード中に予期しないエラーが発生しました"); } state.ClearFunctionList(); state.SystemState = SystemStateCode.LoadData_DataLoaded; return(false); } case FunctionCode.TRYCALLLIST: case FunctionCode.TRYJUMPLIST: { //if (!sequential)//RETURNで帰ってきた //{ // state.JumpTo(func.JumpTo); // break; //} string funcName = ""; CalledFunction callto = null; SpCallArgment cfa = null; foreach (InstructionLine iLine in func.callList) { cfa = (SpCallArgment)iLine.Argument; funcName = cfa.FuncnameTerm.GetStrValue(exm); if (Config.ICFunction) { funcName = funcName.ToUpper(); } callto = CalledFunction.CallFunction(this, funcName, func.JumpTo); if (callto == null) { continue; } callto.IsJump = func.Function.IsJump(); string errMes; UserDefinedFunctionArgument args = callto.ConvertArg(cfa.RowArgs, out errMes); if (args == null) { throw new CodeEE(errMes); } state.IntoFunction(callto, args, exm); return(true); } state.JumpTo(func.JumpTo); } break; case FunctionCode.TRYGOTOLIST: { string funcName = ""; LogicalLine jumpto = null; foreach (InstructionLine iLine in func.callList) { if (iLine.Argument == null) { ArgumentParser.SetArgumentTo(iLine); } funcName = ((SpCallArgment)iLine.Argument).FuncnameTerm.GetStrValue(exm); if (Config.ICVariable) { funcName = funcName.ToUpper(); } jumpto = state.CurrentCalled.CallLabel(this, funcName); if (jumpto != null) { break; } } if (jumpto == null) { state.JumpTo(func.JumpTo); } else { state.JumpTo(jumpto); } } break; case FunctionCode.CALLTRAIN: { ExpressionArgument intExpArg = (ExpressionArgument)func.Argument; Int64 count = intExpArg.Term.GetIntValue(exm); SetCommnds(count); return(false); } case FunctionCode.STOPCALLTRAIN: { if (isCTrain) { ClearCommands(); skipPrint = false; } return(false); } case FunctionCode.DOTRAIN: { switch (state.SystemState) { //case SystemStateCode.Train_Begin://BEGIN TRAINから。 case SystemStateCode.Train_CallEventTrain: //@EVENTTRAINの呼び出し中。スキップ可能 case SystemStateCode.Train_CallShowStatus: //@SHOW_STATUSの呼び出し中 //case SystemStateCode.Train_CallComAbleXX://@COM_ABLExxの呼び出し中。 case SystemStateCode.Train_CallShowUserCom: //@SHOW_USERCOMの呼び出し中 //case SystemStateCode.Train_WaitInput://入力待ち状態。選択が実行可能ならEVENTCOMからCOMxx、そうでなければ@USERCOMにRESULTを渡す //case SystemStateCode.Train_CallEventCom://@EVENTCOMの呼び出し中 //case SystemStateCode.Train_CallComXX://@COMxxの呼び出し中 //case SystemStateCode.Train_CallSourceCheck://@SOURCE_CHECKの呼び出し中 case SystemStateCode.Train_CallEventComEnd: //@EVENTCOMENDの呼び出し中。スキップ可能。Train_CallEventTrainへ帰る。@USERCOMの呼び出し中もここ break; default: exm.Console.PrintSystemLine(state.SystemState.ToString()); throw new CodeEE("DOTRAIN命令をこの位置で実行することはできません"); } coms.Clear(); isCTrain = false; this.count = 0; Int64 train = ((ExpressionArgument)func.Argument).Term.GetIntValue(exm); if (train < 0) { throw new CodeEE("DOTRAIN命令に0未満の値が渡されました"); } if (train >= TrainName.Length) { throw new CodeEE("DOTRAIN命令にTRAINNAMEの配列数以上の値が渡されました"); } doTrainSelectCom = train; state.SystemState = SystemStateCode.Train_DoTrain; return(false); } #if DEBUG default: throw new ExeEE("未定義の関数です"); #endif } return(true); }
private void handleException(Exception exc, LogicalLine current, bool playSound) { console.ThrowError(playSound); ScriptPosition position = null; EmueraException ee = exc as EmueraException; if ((ee != null) && (ee.Position != null)) { position = ee.Position; } else if ((current != null) && (current.Position != null)) { position = current.Position; } string posString = ""; if (position != null) { if (position.LineNo >= 0) { posString = position.Filename + "の" + position.LineNo.ToString() + "行目で"; } else { posString = position.Filename + "で"; } } if (exc is CodeEE) { if (position != null) { InstructionLine procline = current as InstructionLine; if (procline != null && procline.FunctionCode == FunctionCode.THROW) { console.PrintErrorButton(posString + "THROWが発生しました", position); if (position.RowLine != null) { console.PrintError(position.RowLine); } console.PrintError("THROW内容:" + exc.Message); } else { console.PrintErrorButton(posString + "エラーが発生しました:" + Program.ExeName, position); if (position.RowLine != null) { console.PrintError(position.RowLine); } console.PrintError("エラー内容:" + exc.Message); } console.PrintError("現在の関数:@" + current.ParentLabelLine.LabelName + "(" + current.ParentLabelLine.Position.Filename + "の" + current.ParentLabelLine.Position.LineNo.ToString() + "行目)"); console.PrintError("関数呼び出しスタック:"); LogicalLine parent = null; int depth = 0; while ((parent = state.GetReturnAddressSequensial(depth++)) != null) { if (parent.Position != null) { console.PrintErrorButton("↑" + parent.Position.Filename + "の" + parent.Position.LineNo.ToString() + "行目(関数@" + parent.ParentLabelLine.LabelName + "内)", parent.Position); } } } else { console.PrintError(posString + "エラーが発生しました:" + Program.ExeName); console.PrintError(exc.Message); } } else if (exc is ExeEE) { console.PrintError(posString + "Emueraのエラーが発生しました:" + Program.ExeName); console.PrintError(exc.Message); } else { console.PrintError(posString + "予期しないエラーが発生しました:" + Program.ExeName); console.PrintError(exc.GetType().ToString() + ":" + exc.Message); string[] stack = exc.StackTrace.Split('\n'); for (int i = 0; i < stack.Length; i++) { console.PrintError(stack[i]); } } }
public void Return(Int64 ret) { if (IsFunctionMethod) { ReturnF(null); return; } //sequential = false;//いずれにしろ順列ではない。 //呼び出し元は全部スクリプト処理 //if (functionList.Count == 0) //{ // throw new ExeEE("実行中の関数が存在しません"); //} CalledFunction called = functionList[functionList.Count - 1]; if (called.IsJump) { //JUMPした場合。即座にRETURN RESULTする。 if (called.TopLabel.hasPrivDynamicVar) { called.TopLabel.Out(); } functionList.Remove(called); if (Program.DebugMode) { console.DebugRemoveTraceLog(); } Return(ret); return; } if (!called.IsEvent) { if (called.TopLabel.hasPrivDynamicVar) { called.TopLabel.Out(); } currentLine = null; } else { if (called.CurrentLabel.hasPrivDynamicVar) { called.CurrentLabel.Out(); } //#Singleフラグ付き関数で1が返された。 //1752 非0ではなく1と等価であることを見るように修正 //1756 全てを終了ではなく#PRIや#LATERのグループごとに修正 if (called.IsOnly) { called.FinishEvent(); } else if ((called.HasSingleFlag) && (ret == 1)) { called.ShiftNextGroup(); } else { called.ShiftNext(); //次の同名関数に進む。 } currentLine = called.CurrentLabel; //関数の始点(@~~)へ移動。呼ぶべき関数が無ければnull if (called.CurrentLabel != null) { lineCount++; if (called.CurrentLabel.hasPrivDynamicVar) { called.CurrentLabel.In(); } } } if (Program.DebugMode) { console.DebugRemoveTraceLog(); } //関数終了 if (currentLine == null) { currentLine = called.ReturnAddress; functionList.RemoveAt(functionList.Count - 1); if (currentLine == null) { //この時点でfunctionListは空のはず //functionList.Clear();//全て終了。stateEndProcessに処理を返す if (begintype != BeginType.NULL) //BEGIN XXが行なわれていれば { Begin(); } return; } lineCount++; //ShfitNextLine(); return; } else if (Program.DebugMode) { FunctionLabelLine label = called.CurrentLabel; console.DebugAddTraceLog("CALL :@" + label.LabelName + ":" + label.Position.ToString() + "行目"); } lineCount++; //ShfitNextLine(); return; }
public void IntoFunction(CalledFunction call, UserDefinedFunctionArgument srcArgs, ExpressionMediator exm) { if (call.IsEvent) { foreach (CalledFunction called in functionList) { if (called.IsEvent) { throw new CodeEE("EVENT関数の解決前にCALLEVENT命令が行われました"); } } } if (Program.DebugMode) { FunctionLabelLine label = call.CurrentLabel; if (call.IsJump) { console.DebugAddTraceLog("JUMP :@" + label.LabelName + ":" + label.Position.ToString() + "行目"); } else { console.DebugAddTraceLog("CALL :@" + label.LabelName + ":" + label.Position.ToString() + "行目"); } } if (srcArgs != null) { //引数の値を確定させる srcArgs.SetTransporter(exm); //プライベート変数更新 if (call.TopLabel.hasPrivDynamicVar) { call.TopLabel.In(); } //更新した変数へ引数を代入 for (int i = 0; i < call.TopLabel.Arg.Length; i++) { if (srcArgs.Arguments[i] != null) { if (call.TopLabel.Arg[i].Identifier.IsReference) { ((ReferenceToken)(call.TopLabel.Arg[i].Identifier)).SetRef(srcArgs.TransporterRef[i]); } else if (srcArgs.Arguments[i].GetOperandType() == typeof(Int64)) { call.TopLabel.Arg[i].SetValue(srcArgs.TransporterInt[i], exm); } else { call.TopLabel.Arg[i].SetValue(srcArgs.TransporterStr[i], exm); } } } } else//こっちに来るのはシステムからの呼び出し=引数は存在しない関数のみ ifネストの外に出していい気もしないでもないがはてさて { //プライベート変数更新 if (call.TopLabel.hasPrivDynamicVar) { call.TopLabel.In(); } } functionList.Add(call); //sequential = false; currentLine = call.CurrentLabel; lineCount++; //ShfitNextLine(); }
public void updateRetAddress(LogicalLine line) { ReturnAddress = line; }